From 5e60e0e3af85f22aa0afe8bf0ecf85619afacfeb Mon Sep 17 00:00:00 2001 From: Micah Anderson Date: Thu, 22 Aug 2013 16:39:52 -0400 Subject: Imported Upstream version 0.6.0.12 --- .darcs-boringfile | 17 - COPYING.ed25519 | 25 + ChangeLog | 29 +- MANIFEST.in | 11 +- NEWS.rst | 2 +- PKG-INFO | 90 +- README.ed25519.rst | 137 + README.rst | 81 + README.txt | 67 - _doubleloadtester.cpp | 35 + _testdoubleloadmodule.cpp | 23 - copyright | 2 +- darcsver-1.6.3.egg/EGG-INFO/PKG-INFO | 121 - darcsver-1.6.3.egg/EGG-INFO/SOURCES.txt | 17 - darcsver-1.6.3.egg/EGG-INFO/dependency_links.txt | 1 - darcsver-1.6.3.egg/EGG-INFO/entry_points.txt | 10 - darcsver-1.6.3.egg/EGG-INFO/not-zip-safe | 1 - darcsver-1.6.3.egg/EGG-INFO/top_level.txt | 2 - darcsver-1.6.3.egg/darcsver/__init__.py | 8 - darcsver-1.6.3.egg/darcsver/_version.py | 17 - darcsver-1.6.3.egg/darcsver/darcsvermodule.py | 192 - darcsver-1.6.3.egg/darcsver/setuptools_command.py | 116 - darcsver-1.6.3.egg/scripts/__init__.py | 0 darcsver-1.6.3.egg/scripts/darcsverscript.py | 46 - .../share/doc/python-darcsver/README.txt | 95 - embeddedcryptopp/Doxyfile | 1109 --- embeddedcryptopp/GNUmakefile | 168 - embeddedcryptopp/License.txt | 67 - embeddedcryptopp/Readme.txt | 429 - embeddedcryptopp/TestVectors/Readme.txt | 72 - embeddedcryptopp/TestVectors/aes.txt | 189 - embeddedcryptopp/TestVectors/all.txt | 29 - embeddedcryptopp/TestVectors/camellia.txt | 8646 ------------------ embeddedcryptopp/TestVectors/ccm.txt | 240 - embeddedcryptopp/TestVectors/cmac.txt | 38 - embeddedcryptopp/TestVectors/dlies.txt | 542 -- embeddedcryptopp/TestVectors/dsa.txt | 337 - embeddedcryptopp/TestVectors/dsa_1363.txt | 553 -- embeddedcryptopp/TestVectors/eax.txt | 75 - embeddedcryptopp/TestVectors/esign.txt | 93 - embeddedcryptopp/TestVectors/gcm.txt | 139 - embeddedcryptopp/TestVectors/hmac.txt | 125 - embeddedcryptopp/TestVectors/mars.txt | 66 - embeddedcryptopp/TestVectors/nr.txt | 615 -- embeddedcryptopp/TestVectors/panama.txt | 76 - embeddedcryptopp/TestVectors/rsa_oaep.txt | 1765 ---- embeddedcryptopp/TestVectors/rsa_pkcs1_1_5.txt | 89 - embeddedcryptopp/TestVectors/rsa_pss.txt | 2083 ----- embeddedcryptopp/TestVectors/rw.txt | 166 - embeddedcryptopp/TestVectors/salsa.txt | 463 - embeddedcryptopp/TestVectors/seal.txt | 137 - embeddedcryptopp/TestVectors/seed.txt | 19 - embeddedcryptopp/TestVectors/sha.txt | 59 - embeddedcryptopp/TestVectors/shacal2.txt | 5123 ----------- embeddedcryptopp/TestVectors/sosemanuk.txt | 25 - embeddedcryptopp/TestVectors/tea.txt | 711 -- embeddedcryptopp/TestVectors/ttmac.txt | 40 - embeddedcryptopp/TestVectors/vmac.txt | 77 - embeddedcryptopp/TestVectors/whrlpool.txt | 39 - embeddedcryptopp/adhoc.cpp.proto | 17 - embeddedcryptopp/aes.h | 16 - embeddedcryptopp/algebra.cpp | 340 - embeddedcryptopp/algebra.h | 285 - embeddedcryptopp/algparam.cpp | 75 - embeddedcryptopp/algparam.h | 398 - embeddedcryptopp/argnames.h | 79 - embeddedcryptopp/asn.cpp | 595 -- embeddedcryptopp/asn.h | 369 - embeddedcryptopp/authenc.h | 49 - embeddedcryptopp/basecode.cpp | 238 - embeddedcryptopp/basecode.h | 86 - embeddedcryptopp/cbcmac.h | 50 - embeddedcryptopp/ccm.h | 101 - embeddedcryptopp/channels.h | 123 - embeddedcryptopp/cmac.h | 52 - embeddedcryptopp/config.h | 457 - embeddedcryptopp/cpu.cpp | 199 - embeddedcryptopp/cpu.h | 263 - embeddedcryptopp/cryptdll.dsp | 594 -- embeddedcryptopp/cryptdll.vcproj | 2694 ------ embeddedcryptopp/cryptest.dsp | 207 - embeddedcryptopp/cryptest.dsw | 74 - embeddedcryptopp/cryptest.sln | 100 - embeddedcryptopp/cryptest.vcproj | 1850 ---- embeddedcryptopp/cryptest_bds.bdsgroup | 22 - embeddedcryptopp/cryptest_bds.bdsproj | 267 - embeddedcryptopp/cryptest_bds.bpf | 5 - embeddedcryptopp/cryptlib.cpp | 821 -- embeddedcryptopp/cryptlib.dsp | 1204 --- embeddedcryptopp/cryptlib.h | 1668 ---- embeddedcryptopp/cryptlib.vcproj | 9580 -------------------- embeddedcryptopp/cryptlib_bds.bdsproj | 377 - embeddedcryptopp/cryptopp.rc | 104 - embeddedcryptopp/des.cpp | 449 - embeddedcryptopp/des.h | 144 - embeddedcryptopp/dessp.cpp | 95 - embeddedcryptopp/dh.h | 99 - embeddedcryptopp/dll.cpp | 146 - embeddedcryptopp/dll.h | 71 - embeddedcryptopp/dlltest.dsp | 90 - embeddedcryptopp/dlltest.vcproj | 419 - embeddedcryptopp/dsa.cpp | 119 - embeddedcryptopp/dsa.h | 35 - embeddedcryptopp/ec2n.cpp | 288 - embeddedcryptopp/ec2n.h | 113 - embeddedcryptopp/eccrypto.cpp | 694 -- embeddedcryptopp/eccrypto.h | 280 - embeddedcryptopp/ecp.cpp | 473 - embeddedcryptopp/ecp.h | 126 - embeddedcryptopp/emsa2.h | 86 - embeddedcryptopp/eprecomp.cpp | 112 - embeddedcryptopp/eprecomp.h | 75 - embeddedcryptopp/extraversion.h | 9 - embeddedcryptopp/files.h | 97 - embeddedcryptopp/filters.cpp | 1120 --- embeddedcryptopp/filters.h | 808 -- embeddedcryptopp/fips140.cpp | 84 - embeddedcryptopp/fips140.h | 59 - embeddedcryptopp/fltrimpl.h | 67 - embeddedcryptopp/gcm.h | 105 - embeddedcryptopp/gf2n.cpp | 879 -- embeddedcryptopp/gf2n.h | 369 - embeddedcryptopp/gfpcrypt.cpp | 275 - embeddedcryptopp/gfpcrypt.h | 536 -- embeddedcryptopp/hex.cpp | 44 - embeddedcryptopp/hex.h | 36 - embeddedcryptopp/hmac.cpp | 86 - embeddedcryptopp/hmac.h | 61 - embeddedcryptopp/integer.cpp | 4245 --------- embeddedcryptopp/integer.h | 420 - embeddedcryptopp/iterhash.cpp | 159 - embeddedcryptopp/iterhash.h | 106 - embeddedcryptopp/misc.cpp | 130 - embeddedcryptopp/misc.h | 1134 --- embeddedcryptopp/modarith.h | 158 - embeddedcryptopp/modes.cpp | 243 - embeddedcryptopp/modes.h | 421 - embeddedcryptopp/modexppc.h | 34 - embeddedcryptopp/mqueue.cpp | 174 - embeddedcryptopp/mqueue.h | 100 - embeddedcryptopp/mqv.h | 141 - embeddedcryptopp/nbtheory.cpp | 1123 --- embeddedcryptopp/nbtheory.h | 131 - embeddedcryptopp/oaep.cpp | 97 - embeddedcryptopp/oaep.h | 42 - embeddedcryptopp/oids.h | 123 - embeddedcryptopp/osrng.cpp | 171 - embeddedcryptopp/osrng.h | 153 - embeddedcryptopp/pch.h | 21 - embeddedcryptopp/pkcspad.cpp | 124 - embeddedcryptopp/pkcspad.h | 94 - embeddedcryptopp/pssr.cpp | 145 - embeddedcryptopp/pssr.h | 66 - embeddedcryptopp/pubkey.cpp | 162 - embeddedcryptopp/pubkey.h | 1678 ---- embeddedcryptopp/queue.cpp | 564 -- embeddedcryptopp/queue.h | 143 - embeddedcryptopp/randpool.cpp | 52 - embeddedcryptopp/randpool.h | 33 - embeddedcryptopp/rdtables.cpp | 172 - embeddedcryptopp/rijndael.cpp | 989 -- embeddedcryptopp/rijndael.h | 65 - embeddedcryptopp/rng.cpp | 142 - embeddedcryptopp/rng.h | 77 - embeddedcryptopp/rsa.cpp | 304 - embeddedcryptopp/rsa.h | 174 - embeddedcryptopp/rw.h | 92 - embeddedcryptopp/secblock.h | 500 - embeddedcryptopp/seckey.h | 221 - embeddedcryptopp/serpent.cpp | 123 - embeddedcryptopp/serpent.h | 52 - embeddedcryptopp/serpentp.h | 434 - embeddedcryptopp/sha.cpp | 900 -- embeddedcryptopp/sha.h | 63 - embeddedcryptopp/simple.h | 209 - embeddedcryptopp/skipjack.h | 61 - embeddedcryptopp/smartptr.h | 223 - embeddedcryptopp/sosemanuk.cpp | 711 -- embeddedcryptopp/sosemanuk.h | 40 - embeddedcryptopp/stdcpp.h | 27 - embeddedcryptopp/strciphr.cpp | 252 - embeddedcryptopp/strciphr.h | 306 - embeddedcryptopp/tiger.cpp | 265 - embeddedcryptopp/tiger.h | 24 - embeddedcryptopp/tigertab.cpp | 525 -- embeddedcryptopp/trdlocal.h | 44 - embeddedcryptopp/words.h | 103 - embeddedcryptopp/x64dll.asm | 1968 ---- embeddedcryptopp/x64masm.asm | 1563 ---- misc/build_helpers/run_trial.py | 55 - misc/build_helpers/show-tool-versions.py | 90 +- misc/coding_helpers/python.supp | 105 +- pycryptopp.egg-info/PKG-INFO | 90 +- pycryptopp.egg-info/SOURCES.txt | 465 +- pycryptopp/__init__.py | 29 - pycryptopp/_pycryptoppmodule.cpp | 62 - pycryptopp/_version.py | 17 - pycryptopp/cipher/__init__.py | 3 - pycryptopp/cipher/aes.py | 68 - pycryptopp/cipher/aesmodule.cpp | 187 - pycryptopp/cipher/aesmodule.hpp | 7 - pycryptopp/hash/__init__.py | 3 - pycryptopp/hash/sha256.py | 43 - pycryptopp/hash/sha256module.cpp | 189 - pycryptopp/hash/sha256module.hpp | 7 - pycryptopp/publickey/__init__.py | 3 - pycryptopp/publickey/ecdsa.py | 5 - pycryptopp/publickey/ecdsamodule.cpp | 523 -- pycryptopp/publickey/ecdsamodule.hpp | 7 - pycryptopp/publickey/rsa.py | 5 - pycryptopp/publickey/rsamodule.cpp | 383 - pycryptopp/publickey/rsamodule.hpp | 21 - pycryptopp/test/__init__.py | 0 pycryptopp/test/test_aes.py | 107 - pycryptopp/test/test_ecdsa.py | 263 - pycryptopp/test/test_from_Nikratio.py | 32 - pycryptopp/test/test_rsa.py | 122 - pycryptopp/test/test_sha256.py | 181 - pycryptopp/test/test_startup.py | 5 - pycryptopp/testvectors/KAT_AES/ECBGFSbox128e.txt | 36 - pycryptopp/testvectors/KAT_AES/ECBGFSbox256e.txt | 26 - pycryptopp/testvectors/KAT_AES/ECBKeySbox128e.txt | 106 - pycryptopp/testvectors/KAT_AES/ECBKeySbox256e.txt | 81 - pycryptopp/testvectors/KAT_AES/ECBVarKey128e.txt | 641 -- pycryptopp/testvectors/KAT_AES/ECBVarKey256e.txt | 1281 --- pycryptopp/testvectors/KAT_AES/ECBVarTxt128e.txt | 641 -- pycryptopp/testvectors/KAT_AES/ECBVarTxt256e.txt | 641 -- pycryptopp/testvectors/SHA256LongMsg.txt | 263 - pycryptopp/testvectors/SHA256Monte.txt | 309 - pycryptopp/testvectors/SHA256ShortMsg.txt | 267 - setup.cfg | 18 +- setup.py | 317 +- .../EGG-INFO/PKG-INFO | 32 - .../EGG-INFO/SOURCES.txt | 13 - .../EGG-INFO/dependency_links.txt | 1 - .../EGG-INFO/entry_points.txt | 3 - .../EGG-INFO/not-zip-safe | 1 - .../EGG-INFO/top_level.txt | 1 - .../setuptools_darcs/__init__.py | 8 - .../setuptools_darcs/_version.py | 16 - .../setuptools_darcs/setuptools_darcs.py | 79 - .../share/doc/python-setuptools_darcs/README.txt | 143 - src-cryptopp/Doxyfile | 1109 +++ src-cryptopp/GNUmakefile | 168 + src-cryptopp/License.txt | 67 + src-cryptopp/Readme.txt | 429 + src-cryptopp/TestVectors/Readme.txt | 72 + src-cryptopp/TestVectors/aes.txt | 189 + src-cryptopp/TestVectors/all.txt | 29 + src-cryptopp/TestVectors/camellia.txt | 8646 ++++++++++++++++++ src-cryptopp/TestVectors/ccm.txt | 240 + src-cryptopp/TestVectors/cmac.txt | 38 + src-cryptopp/TestVectors/dlies.txt | 542 ++ src-cryptopp/TestVectors/dsa.txt | 337 + src-cryptopp/TestVectors/dsa_1363.txt | 553 ++ src-cryptopp/TestVectors/eax.txt | 75 + src-cryptopp/TestVectors/esign.txt | 93 + src-cryptopp/TestVectors/gcm.txt | 139 + src-cryptopp/TestVectors/hmac.txt | 125 + src-cryptopp/TestVectors/mars.txt | 66 + src-cryptopp/TestVectors/nr.txt | 615 ++ src-cryptopp/TestVectors/panama.txt | 76 + src-cryptopp/TestVectors/rsa_oaep.txt | 1765 ++++ src-cryptopp/TestVectors/rsa_pkcs1_1_5.txt | 89 + src-cryptopp/TestVectors/rsa_pss.txt | 2083 +++++ src-cryptopp/TestVectors/rw.txt | 166 + src-cryptopp/TestVectors/salsa.txt | 463 + src-cryptopp/TestVectors/seal.txt | 137 + src-cryptopp/TestVectors/seed.txt | 19 + src-cryptopp/TestVectors/sha.txt | 59 + src-cryptopp/TestVectors/shacal2.txt | 5123 +++++++++++ src-cryptopp/TestVectors/sosemanuk.txt | 25 + src-cryptopp/TestVectors/tea.txt | 711 ++ src-cryptopp/TestVectors/ttmac.txt | 40 + src-cryptopp/TestVectors/vmac.txt | 77 + src-cryptopp/TestVectors/whrlpool.txt | 39 + src-cryptopp/adhoc.cpp.proto | 17 + src-cryptopp/aes.h | 16 + src-cryptopp/algebra.cpp | 340 + src-cryptopp/algebra.h | 285 + src-cryptopp/algparam.cpp | 75 + src-cryptopp/algparam.h | 398 + src-cryptopp/argnames.h | 79 + src-cryptopp/asn.cpp | 595 ++ src-cryptopp/asn.h | 369 + src-cryptopp/authenc.h | 49 + src-cryptopp/basecode.cpp | 238 + src-cryptopp/basecode.h | 86 + src-cryptopp/cbcmac.h | 50 + src-cryptopp/ccm.h | 101 + src-cryptopp/channels.h | 123 + src-cryptopp/cmac.h | 52 + src-cryptopp/config.h | 459 + src-cryptopp/cpu.cpp | 199 + src-cryptopp/cpu.h | 263 + src-cryptopp/cryptdll.dsp | 594 ++ src-cryptopp/cryptdll.vcproj | 2694 ++++++ src-cryptopp/cryptest.dsp | 207 + src-cryptopp/cryptest.dsw | 74 + src-cryptopp/cryptest.sln | 100 + src-cryptopp/cryptest.vcproj | 1850 ++++ src-cryptopp/cryptest_bds.bdsgroup | 22 + src-cryptopp/cryptest_bds.bdsproj | 267 + src-cryptopp/cryptest_bds.bpf | 5 + src-cryptopp/cryptlib.cpp | 835 ++ src-cryptopp/cryptlib.dsp | 1204 +++ src-cryptopp/cryptlib.h | 1661 ++++ src-cryptopp/cryptlib.vcproj | 9580 ++++++++++++++++++++ src-cryptopp/cryptlib_bds.bdsproj | 377 + src-cryptopp/cryptopp.rc | 104 + src-cryptopp/des.cpp | 449 + src-cryptopp/des.h | 144 + src-cryptopp/dessp.cpp | 95 + src-cryptopp/dh.h | 99 + src-cryptopp/dll.cpp | 146 + src-cryptopp/dll.h | 71 + src-cryptopp/dlltest.dsp | 90 + src-cryptopp/dlltest.vcproj | 419 + src-cryptopp/dsa.cpp | 119 + src-cryptopp/dsa.h | 35 + src-cryptopp/ec2n.cpp | 288 + src-cryptopp/ec2n.h | 113 + src-cryptopp/eccrypto.cpp | 694 ++ src-cryptopp/eccrypto.h | 280 + src-cryptopp/ecp.cpp | 473 + src-cryptopp/ecp.h | 126 + src-cryptopp/emsa2.h | 86 + src-cryptopp/eprecomp.cpp | 112 + src-cryptopp/eprecomp.h | 75 + src-cryptopp/extraversion.h | 8 + src-cryptopp/files.h | 97 + src-cryptopp/filters.cpp | 1120 +++ src-cryptopp/filters.h | 808 ++ src-cryptopp/fips140.cpp | 84 + src-cryptopp/fips140.h | 59 + src-cryptopp/fltrimpl.h | 67 + src-cryptopp/gcm.h | 105 + src-cryptopp/gf2n.cpp | 879 ++ src-cryptopp/gf2n.h | 369 + src-cryptopp/gfpcrypt.cpp | 275 + src-cryptopp/gfpcrypt.h | 536 ++ src-cryptopp/hex.cpp | 44 + src-cryptopp/hex.h | 36 + src-cryptopp/hmac.cpp | 86 + src-cryptopp/hmac.h | 61 + src-cryptopp/integer.cpp | 4245 +++++++++ src-cryptopp/integer.h | 420 + src-cryptopp/iterhash.cpp | 159 + src-cryptopp/iterhash.h | 106 + src-cryptopp/misc.cpp | 130 + src-cryptopp/misc.h | 1125 +++ src-cryptopp/modarith.h | 158 + src-cryptopp/modes.cpp | 243 + src-cryptopp/modes.h | 421 + src-cryptopp/modexppc.h | 34 + src-cryptopp/mqueue.cpp | 174 + src-cryptopp/mqueue.h | 100 + src-cryptopp/mqv.h | 141 + src-cryptopp/nbtheory.cpp | 1123 +++ src-cryptopp/nbtheory.h | 131 + src-cryptopp/oaep.cpp | 97 + src-cryptopp/oaep.h | 42 + src-cryptopp/oids.h | 123 + src-cryptopp/osrng.cpp | 171 + src-cryptopp/osrng.h | 153 + src-cryptopp/pch.h | 21 + src-cryptopp/pkcspad.cpp | 124 + src-cryptopp/pkcspad.h | 94 + src-cryptopp/pssr.cpp | 145 + src-cryptopp/pssr.h | 66 + src-cryptopp/pubkey.cpp | 162 + src-cryptopp/pubkey.h | 1678 ++++ src-cryptopp/queue.cpp | 564 ++ src-cryptopp/queue.h | 143 + src-cryptopp/randpool.cpp | 52 + src-cryptopp/randpool.h | 33 + src-cryptopp/rdtables.cpp | 172 + src-cryptopp/rijndael.cpp | 981 ++ src-cryptopp/rijndael.h | 65 + src-cryptopp/rng.cpp | 142 + src-cryptopp/rng.h | 77 + src-cryptopp/rsa.cpp | 304 + src-cryptopp/rsa.h | 174 + src-cryptopp/rw.h | 92 + src-cryptopp/salsa.cpp | 598 ++ src-cryptopp/salsa.h | 65 + src-cryptopp/secblock.h | 501 + src-cryptopp/seckey.h | 221 + src-cryptopp/serpent.cpp | 123 + src-cryptopp/serpent.h | 52 + src-cryptopp/serpentp.h | 434 + src-cryptopp/sha.cpp | 900 ++ src-cryptopp/sha.h | 63 + src-cryptopp/simple.h | 209 + src-cryptopp/skipjack.h | 61 + src-cryptopp/smartptr.h | 223 + src-cryptopp/sosemanuk.cpp | 711 ++ src-cryptopp/sosemanuk.h | 40 + src-cryptopp/stdcpp.h | 31 + src-cryptopp/strciphr.cpp | 252 + src-cryptopp/strciphr.h | 306 + src-cryptopp/tiger.cpp | 265 + src-cryptopp/tiger.h | 24 + src-cryptopp/tigertab.cpp | 525 ++ src-cryptopp/trdlocal.h | 44 + src-cryptopp/words.h | 103 + src-cryptopp/x64dll.asm | 1968 ++++ src-cryptopp/x64masm.asm | 1563 ++++ src-ed25519/glue/ed25519module.c | 199 + src-ed25519/supercop-ref/Makefile | 10 + src-ed25519/supercop-ref/api.h | 4 + src-ed25519/supercop-ref/crypto_int32.h | 6 + src-ed25519/supercop-ref/crypto_sign.h | 13 + src-ed25519/supercop-ref/crypto_uint32.h | 6 + src-ed25519/supercop-ref/crypto_verify_32.h | 7 + src-ed25519/supercop-ref/ed25519.c | 136 + src-ed25519/supercop-ref/fe25519.c | 326 + src-ed25519/supercop-ref/fe25519.h | 63 + src-ed25519/supercop-ref/ge25519.c | 311 + src-ed25519/supercop-ref/ge25519.h | 35 + src-ed25519/supercop-ref/ge25519_base.data | 850 ++ src-ed25519/supercop-ref/sc25519.c | 298 + src-ed25519/supercop-ref/sc25519.h | 73 + src-ed25519/supercop-ref/sha512-blocks.c | 239 + src-ed25519/supercop-ref/sha512-hash.c | 72 + src-ed25519/supercop-ref/sha512.h | 4 + src-ed25519/supercop-ref/test.c | 39 + src-ed25519/supercop-ref/verify.c | 40 + src/pycryptopp/__init__.py | 31 + src/pycryptopp/_pycryptoppmodule.cpp | 72 + src/pycryptopp/_version.py | 8 + src/pycryptopp/cipher/__init__.py | 4 + src/pycryptopp/cipher/aes.py | 68 + src/pycryptopp/cipher/aesmodule.cpp | 191 + src/pycryptopp/cipher/aesmodule.hpp | 7 + src/pycryptopp/cipher/xsalsa20.py | 31 + src/pycryptopp/cipher/xsalsa20module.cpp | 176 + src/pycryptopp/cipher/xsalsa20module.hpp | 6 + src/pycryptopp/hash/__init__.py | 3 + src/pycryptopp/hash/sha256.py | 43 + src/pycryptopp/hash/sha256module.cpp | 189 + src/pycryptopp/hash/sha256module.hpp | 7 + src/pycryptopp/publickey/__init__.py | 3 + src/pycryptopp/publickey/ecdsa.py | 5 + src/pycryptopp/publickey/ecdsamodule.cpp | 523 ++ src/pycryptopp/publickey/ecdsamodule.hpp | 7 + src/pycryptopp/publickey/ed25519/__init__.py | 7 + src/pycryptopp/publickey/ed25519/_version.py | 11 + src/pycryptopp/publickey/ed25519/keys.py | 70 + src/pycryptopp/publickey/rsa.py | 5 + src/pycryptopp/publickey/rsamodule.cpp | 393 + src/pycryptopp/publickey/rsamodule.hpp | 21 + src/pycryptopp/test/__init__.py | 0 src/pycryptopp/test/test_aes.py | 114 + src/pycryptopp/test/test_ecdsa.py | 263 + src/pycryptopp/test/test_ed25519.py | 148 + src/pycryptopp/test/test_ed25519_kat.py | 47 + src/pycryptopp/test/test_from_Nikratio.py | 32 + src/pycryptopp/test/test_rsa.py | 137 + src/pycryptopp/test/test_sha256.py | 181 + src/pycryptopp/test/test_xsalsa20.py | 136 + .../testvectors/KAT_AES/ECBGFSbox128e.txt | 36 + .../testvectors/KAT_AES/ECBGFSbox256e.txt | 26 + .../testvectors/KAT_AES/ECBKeySbox128e.txt | 106 + .../testvectors/KAT_AES/ECBKeySbox256e.txt | 81 + .../testvectors/KAT_AES/ECBVarKey128e.txt | 641 ++ .../testvectors/KAT_AES/ECBVarKey256e.txt | 1281 +++ .../testvectors/KAT_AES/ECBVarTxt128e.txt | 641 ++ .../testvectors/KAT_AES/ECBVarTxt256e.txt | 641 ++ src/pycryptopp/testvectors/SHA256LongMsg.txt | 263 + src/pycryptopp/testvectors/SHA256Monte.txt | 309 + src/pycryptopp/testvectors/SHA256ShortMsg.txt | 267 + src/pycryptopp/testvectors/kat-ed25519-short.txt | 100 + src/pycryptopp/testvectors/kat-ed25519.txt | 1024 +++ src/pycryptopp/testvectors/xsalsa20.txt | 102 + versioneer.py | 648 ++ 476 files changed, 92906 insertions(+), 87391 deletions(-) delete mode 100644 .darcs-boringfile create mode 100644 COPYING.ed25519 create mode 100644 README.ed25519.rst create mode 100644 README.rst delete mode 100644 README.txt create mode 100644 _doubleloadtester.cpp delete mode 100644 _testdoubleloadmodule.cpp delete mode 100644 darcsver-1.6.3.egg/EGG-INFO/PKG-INFO delete mode 100644 darcsver-1.6.3.egg/EGG-INFO/SOURCES.txt delete mode 100644 darcsver-1.6.3.egg/EGG-INFO/dependency_links.txt delete mode 100644 darcsver-1.6.3.egg/EGG-INFO/entry_points.txt delete mode 100644 darcsver-1.6.3.egg/EGG-INFO/not-zip-safe delete mode 100644 darcsver-1.6.3.egg/EGG-INFO/top_level.txt delete mode 100644 darcsver-1.6.3.egg/darcsver/__init__.py delete mode 100644 darcsver-1.6.3.egg/darcsver/_version.py delete mode 100644 darcsver-1.6.3.egg/darcsver/darcsvermodule.py delete mode 100644 darcsver-1.6.3.egg/darcsver/setuptools_command.py delete mode 100644 darcsver-1.6.3.egg/scripts/__init__.py delete mode 100644 darcsver-1.6.3.egg/scripts/darcsverscript.py delete mode 100644 darcsver-1.6.3.egg/share/doc/python-darcsver/README.txt delete mode 100644 embeddedcryptopp/Doxyfile delete mode 100644 embeddedcryptopp/GNUmakefile delete mode 100644 embeddedcryptopp/License.txt delete mode 100644 embeddedcryptopp/Readme.txt delete mode 100644 embeddedcryptopp/TestVectors/Readme.txt delete mode 100644 embeddedcryptopp/TestVectors/aes.txt delete mode 100644 embeddedcryptopp/TestVectors/all.txt delete mode 100644 embeddedcryptopp/TestVectors/camellia.txt delete mode 100644 embeddedcryptopp/TestVectors/ccm.txt delete mode 100644 embeddedcryptopp/TestVectors/cmac.txt delete mode 100644 embeddedcryptopp/TestVectors/dlies.txt delete mode 100644 embeddedcryptopp/TestVectors/dsa.txt delete mode 100644 embeddedcryptopp/TestVectors/dsa_1363.txt delete mode 100644 embeddedcryptopp/TestVectors/eax.txt delete mode 100644 embeddedcryptopp/TestVectors/esign.txt delete mode 100644 embeddedcryptopp/TestVectors/gcm.txt delete mode 100644 embeddedcryptopp/TestVectors/hmac.txt delete mode 100644 embeddedcryptopp/TestVectors/mars.txt delete mode 100644 embeddedcryptopp/TestVectors/nr.txt delete mode 100644 embeddedcryptopp/TestVectors/panama.txt delete mode 100644 embeddedcryptopp/TestVectors/rsa_oaep.txt delete mode 100644 embeddedcryptopp/TestVectors/rsa_pkcs1_1_5.txt delete mode 100644 embeddedcryptopp/TestVectors/rsa_pss.txt delete mode 100644 embeddedcryptopp/TestVectors/rw.txt delete mode 100644 embeddedcryptopp/TestVectors/salsa.txt delete mode 100644 embeddedcryptopp/TestVectors/seal.txt delete mode 100644 embeddedcryptopp/TestVectors/seed.txt delete mode 100644 embeddedcryptopp/TestVectors/sha.txt delete mode 100644 embeddedcryptopp/TestVectors/shacal2.txt delete mode 100644 embeddedcryptopp/TestVectors/sosemanuk.txt delete mode 100644 embeddedcryptopp/TestVectors/tea.txt delete mode 100644 embeddedcryptopp/TestVectors/ttmac.txt delete mode 100644 embeddedcryptopp/TestVectors/vmac.txt delete mode 100644 embeddedcryptopp/TestVectors/whrlpool.txt delete mode 100644 embeddedcryptopp/adhoc.cpp.proto delete mode 100644 embeddedcryptopp/aes.h delete mode 100644 embeddedcryptopp/algebra.cpp delete mode 100644 embeddedcryptopp/algebra.h delete mode 100644 embeddedcryptopp/algparam.cpp delete mode 100644 embeddedcryptopp/algparam.h delete mode 100644 embeddedcryptopp/argnames.h delete mode 100644 embeddedcryptopp/asn.cpp delete mode 100644 embeddedcryptopp/asn.h delete mode 100644 embeddedcryptopp/authenc.h delete mode 100644 embeddedcryptopp/basecode.cpp delete mode 100644 embeddedcryptopp/basecode.h delete mode 100644 embeddedcryptopp/cbcmac.h delete mode 100644 embeddedcryptopp/ccm.h delete mode 100644 embeddedcryptopp/channels.h delete mode 100644 embeddedcryptopp/cmac.h delete mode 100644 embeddedcryptopp/config.h delete mode 100644 embeddedcryptopp/cpu.cpp delete mode 100644 embeddedcryptopp/cpu.h delete mode 100644 embeddedcryptopp/cryptdll.dsp delete mode 100644 embeddedcryptopp/cryptdll.vcproj delete mode 100644 embeddedcryptopp/cryptest.dsp delete mode 100644 embeddedcryptopp/cryptest.dsw delete mode 100644 embeddedcryptopp/cryptest.sln delete mode 100644 embeddedcryptopp/cryptest.vcproj delete mode 100644 embeddedcryptopp/cryptest_bds.bdsgroup delete mode 100644 embeddedcryptopp/cryptest_bds.bdsproj delete mode 100644 embeddedcryptopp/cryptest_bds.bpf delete mode 100644 embeddedcryptopp/cryptlib.cpp delete mode 100644 embeddedcryptopp/cryptlib.dsp delete mode 100644 embeddedcryptopp/cryptlib.h delete mode 100644 embeddedcryptopp/cryptlib.vcproj delete mode 100644 embeddedcryptopp/cryptlib_bds.bdsproj delete mode 100644 embeddedcryptopp/cryptopp.rc delete mode 100644 embeddedcryptopp/des.cpp delete mode 100644 embeddedcryptopp/des.h delete mode 100644 embeddedcryptopp/dessp.cpp delete mode 100644 embeddedcryptopp/dh.h delete mode 100644 embeddedcryptopp/dll.cpp delete mode 100644 embeddedcryptopp/dll.h delete mode 100644 embeddedcryptopp/dlltest.dsp delete mode 100644 embeddedcryptopp/dlltest.vcproj delete mode 100644 embeddedcryptopp/dsa.cpp delete mode 100644 embeddedcryptopp/dsa.h delete mode 100644 embeddedcryptopp/ec2n.cpp delete mode 100644 embeddedcryptopp/ec2n.h delete mode 100644 embeddedcryptopp/eccrypto.cpp delete mode 100644 embeddedcryptopp/eccrypto.h delete mode 100644 embeddedcryptopp/ecp.cpp delete mode 100644 embeddedcryptopp/ecp.h delete mode 100644 embeddedcryptopp/emsa2.h delete mode 100644 embeddedcryptopp/eprecomp.cpp delete mode 100644 embeddedcryptopp/eprecomp.h delete mode 100644 embeddedcryptopp/extraversion.h delete mode 100644 embeddedcryptopp/files.h delete mode 100644 embeddedcryptopp/filters.cpp delete mode 100644 embeddedcryptopp/filters.h delete mode 100644 embeddedcryptopp/fips140.cpp delete mode 100644 embeddedcryptopp/fips140.h delete mode 100644 embeddedcryptopp/fltrimpl.h delete mode 100644 embeddedcryptopp/gcm.h delete mode 100644 embeddedcryptopp/gf2n.cpp delete mode 100644 embeddedcryptopp/gf2n.h delete mode 100644 embeddedcryptopp/gfpcrypt.cpp delete mode 100644 embeddedcryptopp/gfpcrypt.h delete mode 100644 embeddedcryptopp/hex.cpp delete mode 100644 embeddedcryptopp/hex.h delete mode 100644 embeddedcryptopp/hmac.cpp delete mode 100644 embeddedcryptopp/hmac.h delete mode 100644 embeddedcryptopp/integer.cpp delete mode 100644 embeddedcryptopp/integer.h delete mode 100644 embeddedcryptopp/iterhash.cpp delete mode 100644 embeddedcryptopp/iterhash.h delete mode 100644 embeddedcryptopp/misc.cpp delete mode 100644 embeddedcryptopp/misc.h delete mode 100644 embeddedcryptopp/modarith.h delete mode 100644 embeddedcryptopp/modes.cpp delete mode 100644 embeddedcryptopp/modes.h delete mode 100644 embeddedcryptopp/modexppc.h delete mode 100644 embeddedcryptopp/mqueue.cpp delete mode 100644 embeddedcryptopp/mqueue.h delete mode 100644 embeddedcryptopp/mqv.h delete mode 100644 embeddedcryptopp/nbtheory.cpp delete mode 100644 embeddedcryptopp/nbtheory.h delete mode 100644 embeddedcryptopp/oaep.cpp delete mode 100644 embeddedcryptopp/oaep.h delete mode 100644 embeddedcryptopp/oids.h delete mode 100644 embeddedcryptopp/osrng.cpp delete mode 100644 embeddedcryptopp/osrng.h delete mode 100644 embeddedcryptopp/pch.h delete mode 100644 embeddedcryptopp/pkcspad.cpp delete mode 100644 embeddedcryptopp/pkcspad.h delete mode 100644 embeddedcryptopp/pssr.cpp delete mode 100644 embeddedcryptopp/pssr.h delete mode 100644 embeddedcryptopp/pubkey.cpp delete mode 100644 embeddedcryptopp/pubkey.h delete mode 100644 embeddedcryptopp/queue.cpp delete mode 100644 embeddedcryptopp/queue.h delete mode 100644 embeddedcryptopp/randpool.cpp delete mode 100644 embeddedcryptopp/randpool.h delete mode 100644 embeddedcryptopp/rdtables.cpp delete mode 100644 embeddedcryptopp/rijndael.cpp delete mode 100644 embeddedcryptopp/rijndael.h delete mode 100644 embeddedcryptopp/rng.cpp delete mode 100644 embeddedcryptopp/rng.h delete mode 100644 embeddedcryptopp/rsa.cpp delete mode 100644 embeddedcryptopp/rsa.h delete mode 100644 embeddedcryptopp/rw.h delete mode 100644 embeddedcryptopp/secblock.h delete mode 100644 embeddedcryptopp/seckey.h delete mode 100644 embeddedcryptopp/serpent.cpp delete mode 100644 embeddedcryptopp/serpent.h delete mode 100644 embeddedcryptopp/serpentp.h delete mode 100644 embeddedcryptopp/sha.cpp delete mode 100644 embeddedcryptopp/sha.h delete mode 100644 embeddedcryptopp/simple.h delete mode 100644 embeddedcryptopp/skipjack.h delete mode 100644 embeddedcryptopp/smartptr.h delete mode 100644 embeddedcryptopp/sosemanuk.cpp delete mode 100644 embeddedcryptopp/sosemanuk.h delete mode 100644 embeddedcryptopp/stdcpp.h delete mode 100644 embeddedcryptopp/strciphr.cpp delete mode 100644 embeddedcryptopp/strciphr.h delete mode 100644 embeddedcryptopp/tiger.cpp delete mode 100644 embeddedcryptopp/tiger.h delete mode 100644 embeddedcryptopp/tigertab.cpp delete mode 100644 embeddedcryptopp/trdlocal.h delete mode 100644 embeddedcryptopp/words.h delete mode 100644 embeddedcryptopp/x64dll.asm delete mode 100644 embeddedcryptopp/x64masm.asm delete mode 100644 misc/build_helpers/run_trial.py delete mode 100644 pycryptopp/__init__.py delete mode 100644 pycryptopp/_pycryptoppmodule.cpp delete mode 100644 pycryptopp/_version.py delete mode 100644 pycryptopp/cipher/__init__.py delete mode 100644 pycryptopp/cipher/aes.py delete mode 100644 pycryptopp/cipher/aesmodule.cpp delete mode 100644 pycryptopp/cipher/aesmodule.hpp delete mode 100644 pycryptopp/hash/__init__.py delete mode 100644 pycryptopp/hash/sha256.py delete mode 100644 pycryptopp/hash/sha256module.cpp delete mode 100644 pycryptopp/hash/sha256module.hpp delete mode 100644 pycryptopp/publickey/__init__.py delete mode 100644 pycryptopp/publickey/ecdsa.py delete mode 100644 pycryptopp/publickey/ecdsamodule.cpp delete mode 100644 pycryptopp/publickey/ecdsamodule.hpp delete mode 100644 pycryptopp/publickey/rsa.py delete mode 100644 pycryptopp/publickey/rsamodule.cpp delete mode 100644 pycryptopp/publickey/rsamodule.hpp delete mode 100644 pycryptopp/test/__init__.py delete mode 100644 pycryptopp/test/test_aes.py delete mode 100644 pycryptopp/test/test_ecdsa.py delete mode 100644 pycryptopp/test/test_from_Nikratio.py delete mode 100644 pycryptopp/test/test_rsa.py delete mode 100644 pycryptopp/test/test_sha256.py delete mode 100644 pycryptopp/test/test_startup.py delete mode 100644 pycryptopp/testvectors/KAT_AES/ECBGFSbox128e.txt delete mode 100644 pycryptopp/testvectors/KAT_AES/ECBGFSbox256e.txt delete mode 100644 pycryptopp/testvectors/KAT_AES/ECBKeySbox128e.txt delete mode 100644 pycryptopp/testvectors/KAT_AES/ECBKeySbox256e.txt delete mode 100644 pycryptopp/testvectors/KAT_AES/ECBVarKey128e.txt delete mode 100644 pycryptopp/testvectors/KAT_AES/ECBVarKey256e.txt delete mode 100644 pycryptopp/testvectors/KAT_AES/ECBVarTxt128e.txt delete mode 100644 pycryptopp/testvectors/KAT_AES/ECBVarTxt256e.txt delete mode 100644 pycryptopp/testvectors/SHA256LongMsg.txt delete mode 100644 pycryptopp/testvectors/SHA256Monte.txt delete mode 100644 pycryptopp/testvectors/SHA256ShortMsg.txt delete mode 100644 setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/PKG-INFO delete mode 100644 setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/SOURCES.txt delete mode 100644 setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/dependency_links.txt delete mode 100644 setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/entry_points.txt delete mode 100644 setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/not-zip-safe delete mode 100644 setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/top_level.txt delete mode 100644 setuptools_darcs-1.2.11-py2.6.egg/setuptools_darcs/__init__.py delete mode 100644 setuptools_darcs-1.2.11-py2.6.egg/setuptools_darcs/_version.py delete mode 100644 setuptools_darcs-1.2.11-py2.6.egg/setuptools_darcs/setuptools_darcs.py delete mode 100644 setuptools_darcs-1.2.11-py2.6.egg/share/doc/python-setuptools_darcs/README.txt create mode 100644 src-cryptopp/Doxyfile create mode 100644 src-cryptopp/GNUmakefile create mode 100644 src-cryptopp/License.txt create mode 100644 src-cryptopp/Readme.txt create mode 100644 src-cryptopp/TestVectors/Readme.txt create mode 100644 src-cryptopp/TestVectors/aes.txt create mode 100644 src-cryptopp/TestVectors/all.txt create mode 100644 src-cryptopp/TestVectors/camellia.txt create mode 100644 src-cryptopp/TestVectors/ccm.txt create mode 100644 src-cryptopp/TestVectors/cmac.txt create mode 100644 src-cryptopp/TestVectors/dlies.txt create mode 100644 src-cryptopp/TestVectors/dsa.txt create mode 100644 src-cryptopp/TestVectors/dsa_1363.txt create mode 100644 src-cryptopp/TestVectors/eax.txt create mode 100644 src-cryptopp/TestVectors/esign.txt create mode 100644 src-cryptopp/TestVectors/gcm.txt create mode 100644 src-cryptopp/TestVectors/hmac.txt create mode 100644 src-cryptopp/TestVectors/mars.txt create mode 100644 src-cryptopp/TestVectors/nr.txt create mode 100644 src-cryptopp/TestVectors/panama.txt create mode 100644 src-cryptopp/TestVectors/rsa_oaep.txt create mode 100644 src-cryptopp/TestVectors/rsa_pkcs1_1_5.txt create mode 100644 src-cryptopp/TestVectors/rsa_pss.txt create mode 100644 src-cryptopp/TestVectors/rw.txt create mode 100644 src-cryptopp/TestVectors/salsa.txt create mode 100644 src-cryptopp/TestVectors/seal.txt create mode 100644 src-cryptopp/TestVectors/seed.txt create mode 100644 src-cryptopp/TestVectors/sha.txt create mode 100644 src-cryptopp/TestVectors/shacal2.txt create mode 100644 src-cryptopp/TestVectors/sosemanuk.txt create mode 100644 src-cryptopp/TestVectors/tea.txt create mode 100644 src-cryptopp/TestVectors/ttmac.txt create mode 100644 src-cryptopp/TestVectors/vmac.txt create mode 100644 src-cryptopp/TestVectors/whrlpool.txt create mode 100644 src-cryptopp/adhoc.cpp.proto create mode 100644 src-cryptopp/aes.h create mode 100644 src-cryptopp/algebra.cpp create mode 100644 src-cryptopp/algebra.h create mode 100644 src-cryptopp/algparam.cpp create mode 100644 src-cryptopp/algparam.h create mode 100644 src-cryptopp/argnames.h create mode 100644 src-cryptopp/asn.cpp create mode 100644 src-cryptopp/asn.h create mode 100644 src-cryptopp/authenc.h create mode 100644 src-cryptopp/basecode.cpp create mode 100644 src-cryptopp/basecode.h create mode 100644 src-cryptopp/cbcmac.h create mode 100644 src-cryptopp/ccm.h create mode 100644 src-cryptopp/channels.h create mode 100644 src-cryptopp/cmac.h create mode 100644 src-cryptopp/config.h create mode 100644 src-cryptopp/cpu.cpp create mode 100644 src-cryptopp/cpu.h create mode 100644 src-cryptopp/cryptdll.dsp create mode 100644 src-cryptopp/cryptdll.vcproj create mode 100644 src-cryptopp/cryptest.dsp create mode 100644 src-cryptopp/cryptest.dsw create mode 100644 src-cryptopp/cryptest.sln create mode 100644 src-cryptopp/cryptest.vcproj create mode 100644 src-cryptopp/cryptest_bds.bdsgroup create mode 100644 src-cryptopp/cryptest_bds.bdsproj create mode 100644 src-cryptopp/cryptest_bds.bpf create mode 100644 src-cryptopp/cryptlib.cpp create mode 100644 src-cryptopp/cryptlib.dsp create mode 100644 src-cryptopp/cryptlib.h create mode 100644 src-cryptopp/cryptlib.vcproj create mode 100644 src-cryptopp/cryptlib_bds.bdsproj create mode 100644 src-cryptopp/cryptopp.rc create mode 100644 src-cryptopp/des.cpp create mode 100644 src-cryptopp/des.h create mode 100644 src-cryptopp/dessp.cpp create mode 100644 src-cryptopp/dh.h create mode 100644 src-cryptopp/dll.cpp create mode 100644 src-cryptopp/dll.h create mode 100644 src-cryptopp/dlltest.dsp create mode 100644 src-cryptopp/dlltest.vcproj create mode 100644 src-cryptopp/dsa.cpp create mode 100644 src-cryptopp/dsa.h create mode 100644 src-cryptopp/ec2n.cpp create mode 100644 src-cryptopp/ec2n.h create mode 100644 src-cryptopp/eccrypto.cpp create mode 100644 src-cryptopp/eccrypto.h create mode 100644 src-cryptopp/ecp.cpp create mode 100644 src-cryptopp/ecp.h create mode 100644 src-cryptopp/emsa2.h create mode 100644 src-cryptopp/eprecomp.cpp create mode 100644 src-cryptopp/eprecomp.h create mode 100644 src-cryptopp/extraversion.h create mode 100644 src-cryptopp/files.h create mode 100644 src-cryptopp/filters.cpp create mode 100644 src-cryptopp/filters.h create mode 100644 src-cryptopp/fips140.cpp create mode 100644 src-cryptopp/fips140.h create mode 100644 src-cryptopp/fltrimpl.h create mode 100644 src-cryptopp/gcm.h create mode 100644 src-cryptopp/gf2n.cpp create mode 100644 src-cryptopp/gf2n.h create mode 100644 src-cryptopp/gfpcrypt.cpp create mode 100644 src-cryptopp/gfpcrypt.h create mode 100644 src-cryptopp/hex.cpp create mode 100644 src-cryptopp/hex.h create mode 100644 src-cryptopp/hmac.cpp create mode 100644 src-cryptopp/hmac.h create mode 100644 src-cryptopp/integer.cpp create mode 100644 src-cryptopp/integer.h create mode 100644 src-cryptopp/iterhash.cpp create mode 100644 src-cryptopp/iterhash.h create mode 100644 src-cryptopp/misc.cpp create mode 100644 src-cryptopp/misc.h create mode 100644 src-cryptopp/modarith.h create mode 100644 src-cryptopp/modes.cpp create mode 100644 src-cryptopp/modes.h create mode 100644 src-cryptopp/modexppc.h create mode 100644 src-cryptopp/mqueue.cpp create mode 100644 src-cryptopp/mqueue.h create mode 100644 src-cryptopp/mqv.h create mode 100644 src-cryptopp/nbtheory.cpp create mode 100644 src-cryptopp/nbtheory.h create mode 100644 src-cryptopp/oaep.cpp create mode 100644 src-cryptopp/oaep.h create mode 100644 src-cryptopp/oids.h create mode 100644 src-cryptopp/osrng.cpp create mode 100644 src-cryptopp/osrng.h create mode 100644 src-cryptopp/pch.h create mode 100644 src-cryptopp/pkcspad.cpp create mode 100644 src-cryptopp/pkcspad.h create mode 100644 src-cryptopp/pssr.cpp create mode 100644 src-cryptopp/pssr.h create mode 100644 src-cryptopp/pubkey.cpp create mode 100644 src-cryptopp/pubkey.h create mode 100644 src-cryptopp/queue.cpp create mode 100644 src-cryptopp/queue.h create mode 100644 src-cryptopp/randpool.cpp create mode 100644 src-cryptopp/randpool.h create mode 100644 src-cryptopp/rdtables.cpp create mode 100644 src-cryptopp/rijndael.cpp create mode 100644 src-cryptopp/rijndael.h create mode 100644 src-cryptopp/rng.cpp create mode 100644 src-cryptopp/rng.h create mode 100644 src-cryptopp/rsa.cpp create mode 100644 src-cryptopp/rsa.h create mode 100644 src-cryptopp/rw.h create mode 100644 src-cryptopp/salsa.cpp create mode 100644 src-cryptopp/salsa.h create mode 100644 src-cryptopp/secblock.h create mode 100644 src-cryptopp/seckey.h create mode 100644 src-cryptopp/serpent.cpp create mode 100644 src-cryptopp/serpent.h create mode 100644 src-cryptopp/serpentp.h create mode 100644 src-cryptopp/sha.cpp create mode 100644 src-cryptopp/sha.h create mode 100644 src-cryptopp/simple.h create mode 100644 src-cryptopp/skipjack.h create mode 100644 src-cryptopp/smartptr.h create mode 100644 src-cryptopp/sosemanuk.cpp create mode 100644 src-cryptopp/sosemanuk.h create mode 100644 src-cryptopp/stdcpp.h create mode 100644 src-cryptopp/strciphr.cpp create mode 100644 src-cryptopp/strciphr.h create mode 100644 src-cryptopp/tiger.cpp create mode 100644 src-cryptopp/tiger.h create mode 100644 src-cryptopp/tigertab.cpp create mode 100644 src-cryptopp/trdlocal.h create mode 100644 src-cryptopp/words.h create mode 100644 src-cryptopp/x64dll.asm create mode 100644 src-cryptopp/x64masm.asm create mode 100644 src-ed25519/glue/ed25519module.c create mode 100644 src-ed25519/supercop-ref/Makefile create mode 100644 src-ed25519/supercop-ref/api.h create mode 100644 src-ed25519/supercop-ref/crypto_int32.h create mode 100644 src-ed25519/supercop-ref/crypto_sign.h create mode 100644 src-ed25519/supercop-ref/crypto_uint32.h create mode 100644 src-ed25519/supercop-ref/crypto_verify_32.h create mode 100644 src-ed25519/supercop-ref/ed25519.c create mode 100644 src-ed25519/supercop-ref/fe25519.c create mode 100644 src-ed25519/supercop-ref/fe25519.h create mode 100644 src-ed25519/supercop-ref/ge25519.c create mode 100644 src-ed25519/supercop-ref/ge25519.h create mode 100644 src-ed25519/supercop-ref/ge25519_base.data create mode 100644 src-ed25519/supercop-ref/sc25519.c create mode 100644 src-ed25519/supercop-ref/sc25519.h create mode 100644 src-ed25519/supercop-ref/sha512-blocks.c create mode 100644 src-ed25519/supercop-ref/sha512-hash.c create mode 100644 src-ed25519/supercop-ref/sha512.h create mode 100644 src-ed25519/supercop-ref/test.c create mode 100644 src-ed25519/supercop-ref/verify.c create mode 100644 src/pycryptopp/__init__.py create mode 100644 src/pycryptopp/_pycryptoppmodule.cpp create mode 100644 src/pycryptopp/_version.py create mode 100644 src/pycryptopp/cipher/__init__.py create mode 100644 src/pycryptopp/cipher/aes.py create mode 100644 src/pycryptopp/cipher/aesmodule.cpp create mode 100644 src/pycryptopp/cipher/aesmodule.hpp create mode 100644 src/pycryptopp/cipher/xsalsa20.py create mode 100644 src/pycryptopp/cipher/xsalsa20module.cpp create mode 100644 src/pycryptopp/cipher/xsalsa20module.hpp create mode 100644 src/pycryptopp/hash/__init__.py create mode 100644 src/pycryptopp/hash/sha256.py create mode 100644 src/pycryptopp/hash/sha256module.cpp create mode 100644 src/pycryptopp/hash/sha256module.hpp create mode 100644 src/pycryptopp/publickey/__init__.py create mode 100644 src/pycryptopp/publickey/ecdsa.py create mode 100644 src/pycryptopp/publickey/ecdsamodule.cpp create mode 100644 src/pycryptopp/publickey/ecdsamodule.hpp create mode 100644 src/pycryptopp/publickey/ed25519/__init__.py create mode 100644 src/pycryptopp/publickey/ed25519/_version.py create mode 100644 src/pycryptopp/publickey/ed25519/keys.py create mode 100644 src/pycryptopp/publickey/rsa.py create mode 100644 src/pycryptopp/publickey/rsamodule.cpp create mode 100644 src/pycryptopp/publickey/rsamodule.hpp create mode 100644 src/pycryptopp/test/__init__.py create mode 100644 src/pycryptopp/test/test_aes.py create mode 100644 src/pycryptopp/test/test_ecdsa.py create mode 100644 src/pycryptopp/test/test_ed25519.py create mode 100644 src/pycryptopp/test/test_ed25519_kat.py create mode 100644 src/pycryptopp/test/test_from_Nikratio.py create mode 100644 src/pycryptopp/test/test_rsa.py create mode 100644 src/pycryptopp/test/test_sha256.py create mode 100644 src/pycryptopp/test/test_xsalsa20.py create mode 100644 src/pycryptopp/testvectors/KAT_AES/ECBGFSbox128e.txt create mode 100644 src/pycryptopp/testvectors/KAT_AES/ECBGFSbox256e.txt create mode 100644 src/pycryptopp/testvectors/KAT_AES/ECBKeySbox128e.txt create mode 100644 src/pycryptopp/testvectors/KAT_AES/ECBKeySbox256e.txt create mode 100644 src/pycryptopp/testvectors/KAT_AES/ECBVarKey128e.txt create mode 100644 src/pycryptopp/testvectors/KAT_AES/ECBVarKey256e.txt create mode 100644 src/pycryptopp/testvectors/KAT_AES/ECBVarTxt128e.txt create mode 100644 src/pycryptopp/testvectors/KAT_AES/ECBVarTxt256e.txt create mode 100644 src/pycryptopp/testvectors/SHA256LongMsg.txt create mode 100644 src/pycryptopp/testvectors/SHA256Monte.txt create mode 100644 src/pycryptopp/testvectors/SHA256ShortMsg.txt create mode 100644 src/pycryptopp/testvectors/kat-ed25519-short.txt create mode 100644 src/pycryptopp/testvectors/kat-ed25519.txt create mode 100644 src/pycryptopp/testvectors/xsalsa20.txt create mode 100644 versioneer.py diff --git a/.darcs-boringfile b/.darcs-boringfile deleted file mode 100644 index 3cfa1b0..0000000 --- a/.darcs-boringfile +++ /dev/null @@ -1,17 +0,0 @@ -# Boring file regexps: - -# _version.py is generated at build time, and never checked in -^pycryptopp/_version\.py$ - -# if ez_setup.py needs to build setuptools, that goes here -^setuptools-.*.egg$ -# creating a tahoe egg puts files here -^pycryptopp.egg-info$ - -# if setup.py needs to install plugins from eggs to satisfy setup_requires: -^setuptools_darcs.*.egg$ -^darcsver.*.egg$ -^pyutil.*.egg$ - -^build($|/) -^ez_setup\.pyc$ diff --git a/COPYING.ed25519 b/COPYING.ed25519 new file mode 100644 index 0000000..a40b040 --- /dev/null +++ b/COPYING.ed25519 @@ -0,0 +1,25 @@ +"python-ed25519" Copyright (c) 2011 Brian Warner + +Portions written by the Ed25519 Contributors and placed in the +public domain. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/ChangeLog b/ChangeLog index a4f5614..f4b99ac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,11 +1,28 @@ -2009-09-15 Zooko O'Whielacronx +2012-03-13 Zooko Wilcox-O'Hearn - * release pycryptopp-0.5.17 + • src/pycryptopp/_version.py: release pycryptopp-0.6.0 + • add Ed25519 signatures (#75) + • add XSalsa20 cipher (#40) + • switch from darcs to git for revision control + • pycryptopp version numbers now include a decimal encoding of the + git revid + • reorganize the source tree and the version number generation + • aesmodule.cpp: validate size of IV and throw exception if it is not 16 (#70) + • fixed compile errors with gcc-4.7.0 (#78) + • fixed compile errors concerning "CryptoPP::g_nullNameValuePairs" (#77) + • suppress warnings from valgrind with new OpenSSL 1.0.1 on Fedora (#82) + • raise Python exception instead of uncaught C++ exception + (resulting in abort) when deserializing malformed RSA keys (#83) - * publickey/rsamodule.cpp, publickey/ecdsamodule.cpp, hash/sha256module.cpp, cipher/aesmodule.cpp: fix a segfault bug when sizeof(size_t) > sizeof(int) (not exploitable); thanks Nathan Wilcox and Brian Warner. ticket #19 2009-09-15 Zooko O'Whielacronx +2009-09-15 Zooko Wilcox-O'Hearn -2009-07-27 Zooko Wilcox-O'Hearn + • release pycryptopp-0.5.17 + • publickey/rsamodule.cpp, publickey/ecdsamodule.cpp, + hash/sha256module.cpp, cipher/aesmodule.cpp: fix a segfault bug + when sizeof(size_t) > sizeof(int) (not exploitable); thanks Nathan + Wilcox and Brian Warner. (#19) - * release pycryptopp-0.5.16 +2009-07-27 Zooko Wilcox-O'Hearn - * setup.py, misc/: a few improvements to the build/packaging + • release pycryptopp-0.5.16 + • setup.py, misc/: a few improvements to the build/packaging diff --git a/MANIFEST.in b/MANIFEST.in index b161a5f..37ed49f 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1,10 @@ -include embeddedcryptopp/extraversion.h \ No newline at end of file +include copyright COPYING.GPL COPYING.TGPPL.html ChangeLog NEWS.rst README.rst +include COPYING.ed25519 README.ed25519.rst +include MANIFEST.in +include versioneer.py +include _doubleloadtester.cpp + +graft src/pycryptopp +graft src-cryptopp +graft src-ed25519 +graft misc diff --git a/NEWS.rst b/NEWS.rst index ef2db42..f797344 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -14,7 +14,7 @@ 2010-09-18 -- pycryptopp v0.5.20 * fix bugs in assembly implementation of SHA-256 from Crypto++ - * fix it to compile on *BSD (#39) + * fix it to compile on \*BSD (#39) * improve doc strings * add a quick start-up-self-test of SHA256 (#43) * execute the quick start-up-self-tests of AES and SHA256 on module import diff --git a/PKG-INFO b/PKG-INFO index 48c4ab6..d308672 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,12 +1,93 @@ Metadata-Version: 1.0 Name: pycryptopp -Version: 0.5.29 +Version: 0.6.0.1206569328141510525648634803928199668821045408958 Summary: Python wrappers for a few algorithms from the Crypto++ library -Home-page: http://tahoe-lafs.org/trac/pycryptopp -Author: Zooko O'Whielacronx +Home-page: https://tahoe-lafs.org/trac/pycryptopp +Author: Zooko Wilcox-O'Hearn Author-email: zooko@zooko.com License: GNU GPL -Description: RSA-PSS-SHA256 signatures, ECDSA(1363)/EMSA1(SHA-256) signatures, SHA-256 hashes, and AES-CTR encryption +Description: =========================================================== + pycryptopp: a small number of good cryptography algorithms + =========================================================== + + Introduction and Licence + ======================== + + pycryptopp is a python wrapper around a few algorithms from the Crypto++ and + python-Ed25519 libraries. + + It lives at https://tahoe-lafs.org/trac/pycryptopp + + LICENCE + ------- + + You may use this package under the GNU General Public License, version 2 or, + at your option, any later version. You may use this package under the + Transitive Grace Period Public Licence, version 1.0 or, at your option, any + later version. (You may choose to use this package under the terms of either + licence, at your option.) See the file COPYING.GPL for the terms of the GNU + General Public License, version 2. See the file COPYING.TGPPL.html for the + terms of the Transitive Grace Period Public Licence, version 1.0. + + The Ed25519 code comes from the python-ed25519 distribution ¹_, for which the + basic C code is in the public domain, and the Python bindings are under the + MIT license. See COPYING.ed25519 for details. + + BUILDING + -------- + + To build it run "./setup.py build". To test it run "./setup.py test". To + install it into your system run "./setup.py install". To create a binary + package run "./setup.py bdist_egg". + + If "./setup.py test" doesn't print out "PASSED" and exit with exit code 0 + then there is something seriously wrong. Do not use this build of + pycryptopp. Please report the error to the tahoe-dev mailing list ²_. + + DOCUMENTATION + ------------- + + The documentation is in the docstrings. From a command-line, use "pydoc + pycryptopp", "pydoc pycryptopp.cipher", and so on. From within a Python + interpreter use "help(pycryptopp)", "help(pycryptopp.cipher)", + "help(pycryptopp.cipher.aes)" and so on. + + The documentation for pycryptopp.publickey.ed25519 is in README.ed25519, + adapted from the upstream python-ed25519 library. + + CONTACT + ------- + + Please post to the tahoe-dev mailing list ²_ with comments about this + package. + + BOOK REVIEW + ----------- + + If you are not already acquainted with how to use modern cryptography, buy a + copy of Ferguson, Schneier, and Kohno "Cryptography Engineering" and read it. + It is easy going and will increase your understanding greatly. + + ACKNOWLEDGEMENTS + ---------------- + + Thanks to Wei Dai and the contributors to Crypto++, Andrew M. Kuchling for + his "pycrypto" library which inspired this one, Brian Warner for help on + Python packaging questions, python-Ed25519, inspiration, and a million other + things besides, Greg Hazel and Samuel Neves for Windows porting and fixing + bugs, and Daniel J. Bernstein for Ed25519. + + + Zooko Wilcox-O'Hearn + + Santa Clara, California, USA + + 2012-03-12 + + + .. _¹: https://github.com/warner/python-ed25519 + .. _²: https://tahoe-lafs.org/cgi-bin/mailman/listinfo/tahoe-dev + Platform: UNKNOWN Classifier: Environment :: Console Classifier: License :: OSI Approved :: GNU General Public License (GPL) @@ -24,4 +105,5 @@ Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.4 Classifier: Programming Language :: Python :: 2.5 Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 Classifier: Topic :: Software Development :: Libraries diff --git a/README.ed25519.rst b/README.ed25519.rst new file mode 100644 index 0000000..2216233 --- /dev/null +++ b/README.ed25519.rst @@ -0,0 +1,137 @@ +===================================================== + Python Bindings to Ed25519 Digital Signature System +===================================================== + +This package provides python bindings to a C implementation of the Ed25519 +public-key signature system [1]_. The C code is copied from the SUPERCOP +benchmark suite [2]_, using the portable "ref" implementation (not the +high-performance assembly code), and is very similar to the copy in the NaCl +library [3]_. The C code is in the public domain [4]_. This python binding is +released under the MIT license [5]_. + +With this library, you can quickly (2ms) create signing+verifying keypairs, +derive a verifying key from a signing key, sign messages, and verify the +signatures. The keys and signatures are very short, making them easy to +handle and incorporate into other protocols. All known attacks take at least +2^128 operations, providing the same security level as AES-128, NIST P-256, +and RSA-3072. + + +Speed and Key Sizes +------------------- + +Signing keys are just 32 bytes (256 bits) of random data, so generating a +signing key is trivial: signingkey = os.urandom(32). Deriving a public +verifying key takes more time, as do the actual signing and verifying +operations. + +A 256-bit elliptic curve key is estimated to be as strong as a much larger +RSA key. The "ECRYPT II" cryptographic experts group estimate the strength of +a 256-bit elliptic curve key to similar to the strength of a 3248-bit RSA +public key: http://keylength.com + +On Brian Warner's 2010-era Mac laptop (2.8GHz Core2Duo), deriving a verifying +key takes 1.9ms, signing takes 1.9ms, and verification takes 6.3ms. The +high-performance assembly code in SUPERCOP (amd64-51-30k and amd64-64-24k) is +up to 100x faster than the portable reference version, and the python +overhead appears to be minimal (1-2us), so future releases may run even +faster. + +Ed25519 private signing keys are 32 bytes long (this is expanded internally +to 64 bytes when necessary). The public verifying keys are also 32 bytes +long. Signatures are 64 bytes long. All operations provide a 128-bit +security level. + + +Security +-------- + +The Ed25519 algorithm and C implementation are carefully designed to prevent +timing attacks. The Python wrapper might not preserve this property. Until it +has been audited for this purpose, do not allow attackers to measure how long +it takes you to generate a keypair or sign a message. Key generation depends +upon a strong source of random numbers. Do not use it on a system where +os.urandom() is weak. + +Unlike typical DSA/ECDSA algorithms, signing does *not* require a source of +entropy. Ed25519 signatures are deterministic: using the same key to sign the +same data any number of times will result in the same signature each time. + + +Usage +----- + +The first step is to generate a signing key and store it. At the same time, +you'll probably need to derive the verifying key and give it to someone else. +Signing keys are 32-byte uniformly-random strings. The safest way to generate +a key is with os.urandom(32):: + + import os + from pycryptopp.publickey import ed25519 + + sk_bytes = os.urandom(32) + signing_key = ed25519.SigningKey(sk_bytes) + open("my-secret-key","wb").write(sk_bytes) + + vkey_hex = signing_key.get_verifying_key_bytes().encode('hex') + print "the public key is", vkey_hex + +To reconstruct the same key from the stored form later, just pass it back +into SigningKey:: + + sk_bytes = open("my-secret-key","rb").read() + signing_key = ed25519.SigningKey(sk_bytes) + + +Once you have the SigningKey instance, use its .sign() method to sign a +message. The signature is 64 bytes:: + + sig = signing_key.sign("hello world") + print "sig is:", sig.encode('hex') + +On the verifying side, the receiver first needs to construct a +ed25519.VerifyingKey instance from the serialized form, then use its +.verify() method on the signature and message:: + + vkey_hex = "1246b84985e1ab5f83f4ec2bdf271114666fd3d9e24d12981a3c861b9ed523c6" + verifying_key = ed25519.VerifyingKey(vkey_hex.decode('hex')) + try: + verifying_key.verify(sig, "hello world") + print "signature is good" + except ed25519.BadSignatureError: + print "signature is bad!" + +If you happen to have the SigningKey but not the corresponding VerifyingKey, +you can derive it with .get_verifying_key_bytes(). This allows the sending +side to hold just 32 bytes of data and derive everything else from that. +Deriving a verifying key takes about 1.9ms:: + + sk_bytes = open("my-secret-key","rb").read() + signing_key = ed25519.SigningKey(sk_bytes) + verifying_key = ed25519.VerifyingKey(signing_key.get_verifying_key_bytes()) + +There is also a basic command-line keygen/sign/verify tool in bin/edsig . + + +API Summary +----------- + +The complete API is summarized here:: + + sk_bytes = os.urandom(32) + sk = SigningKey(sk_bytes) + vk_bytes = sk.get_verifying_key_bytes() + vk = VerifyingKey(vk_bytes) + + signature = sk.sign(message) + vk.verify(signature, message) + + +footnotes +--------- + +.. [1] http://ed25519.cr.yp.to/ +.. [2] http://bench.cr.yp.to/supercop.html +.. [3] http://nacl.cr.yp.to/ +.. [4] http://ed25519.cr.yp.to/software.html "Copyrights" +.. [5] LICENSE, included in this distribution diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..27a3995 --- /dev/null +++ b/README.rst @@ -0,0 +1,81 @@ +=========================================================== + pycryptopp: a small number of good cryptography algorithms +=========================================================== + +Introduction and Licence +======================== + +pycryptopp is a python wrapper around a few algorithms from the Crypto++ and +python-Ed25519 libraries. + +It lives at https://tahoe-lafs.org/trac/pycryptopp + +LICENCE +------- + +You may use this package under the GNU General Public License, version 2 or, +at your option, any later version. You may use this package under the +Transitive Grace Period Public Licence, version 1.0 or, at your option, any +later version. (You may choose to use this package under the terms of either +licence, at your option.) See the file COPYING.GPL for the terms of the GNU +General Public License, version 2. See the file COPYING.TGPPL.html for the +terms of the Transitive Grace Period Public Licence, version 1.0. + +The Ed25519 code comes from the python-ed25519 distribution ¹_, for which the +basic C code is in the public domain, and the Python bindings are under the +MIT license. See COPYING.ed25519 for details. + +BUILDING +-------- + +To build it run "./setup.py build". To test it run "./setup.py test". To +install it into your system run "./setup.py install". To create a binary +package run "./setup.py bdist_egg". + +If "./setup.py test" doesn't print out "PASSED" and exit with exit code 0 +then there is something seriously wrong. Do not use this build of +pycryptopp. Please report the error to the tahoe-dev mailing list ²_. + +DOCUMENTATION +------------- + +The documentation is in the docstrings. From a command-line, use "pydoc +pycryptopp", "pydoc pycryptopp.cipher", and so on. From within a Python +interpreter use "help(pycryptopp)", "help(pycryptopp.cipher)", +"help(pycryptopp.cipher.aes)" and so on. + +The documentation for pycryptopp.publickey.ed25519 is in README.ed25519, +adapted from the upstream python-ed25519 library. + +CONTACT +------- + +Please post to the tahoe-dev mailing list ²_ with comments about this +package. + +BOOK REVIEW +----------- + +If you are not already acquainted with how to use modern cryptography, buy a +copy of Ferguson, Schneier, and Kohno "Cryptography Engineering" and read it. +It is easy going and will increase your understanding greatly. + +ACKNOWLEDGEMENTS +---------------- + +Thanks to Wei Dai and the contributors to Crypto++, Andrew M. Kuchling for +his "pycrypto" library which inspired this one, Brian Warner for help on +Python packaging questions, python-Ed25519, inspiration, and a million other +things besides, Greg Hazel and Samuel Neves for Windows porting and fixing +bugs, and Daniel J. Bernstein for Ed25519. + + +Zooko Wilcox-O'Hearn + +Santa Clara, California, USA + +2012-03-12 + + +.. _¹: https://github.com/warner/python-ed25519 +.. _²: https://tahoe-lafs.org/cgi-bin/mailman/listinfo/tahoe-dev diff --git a/README.txt b/README.txt deleted file mode 100644 index d2563ed..0000000 --- a/README.txt +++ /dev/null @@ -1,67 +0,0 @@ -ABOUT THIS PACKAGE - -pycryptopp [1] is a python wrapper around a few algorithms from the -Crypto++ library [2]. - -LICENCE - -You may use this package under the GNU General Public License, version -2 or, at your option, any later version. You may use this package -under the Transitive Grace Period Public Licence, version 1.0 or, at -your option, any later version. (You may choose to use this package -under the terms of either licence, at your option.) See the file -COPYING.GPL for the terms of the GNU General Public License, version 2. -See the file COPYING.TGPPL.html for the terms of the Transitive Grace -Period Public Licence, version 1.0. - -BUILDING - -To build it run "./setup.py build". To test it run "./setup.py test". -To install it into your system run "./setup.py install". To create a -binary package run "./setup.py bdist_egg". There are more features of -setup.py -- see the documentation of setuptools [3] for details. - -If "./setup.py test" doesn't print out "PASSED" and exit with exit -code 0 then there is something seriously wrong. Do not use this build -of pycryptopp. Please report the error to the cryptopp-users mailing -list [4]. The next step in debugging if the pycryptopp tests fail is -to find out if the underlying Crypto++ tests fail on the same system. -To do that, you have to acquire the Crypto++ source code from -http://cryptopp.com , build it, and run the self-test, by executing -"cryptest.exe v", as described in Crypto++'s Readme.txt file. - -DOCUMENTATION - -The documentation is in the docstrings. From a command-line, use -"pydoc pycryptopp", "pydoc pycryptopp.cipher", and so on. From within -a Python interpreter use "help(pycryptopp)", -"help(pycryptopp.cipher)", "help(pycryptopp.cipher.aes)" and so on. - -CONTACT - -Please post to the cryptopp-users mailing list [4] with comments about -this package. - -BOOK REVIEW - -If you are not already acquainted with modern cryptography, buy a copy -of Ferguson, Schneier, and Kohno "Cryptography Engineering" and read it. -It is easy going and will increase your understanding greatly. - -ACKNOWLEDGEMENTS - -Thanks to Wei Dai and the contributors to Crypto++, Andrew M. Kuchling -for his "pycrypto" library which inspired this one, Brian Warner for -help on Python packaging questions, inspiration, and a million other -things besides, and Greg Hazel and Samuel Neves for Windows porting -and fixing bugs. - - -Zooko O'Whielacronx -Boulder, Colorado -September 18, 2010 - -[1] http://pypi.python.org/pypi/pycryptopp -[2] http://cryptopp.com -[3] http://peak.telecommunity.com/DevCenter/setuptools -[4] http://groups.google.com/group/cryptopp-users diff --git a/_doubleloadtester.cpp b/_doubleloadtester.cpp new file mode 100644 index 0000000..64e95f8 --- /dev/null +++ b/_doubleloadtester.cpp @@ -0,0 +1,35 @@ + +#include + +PyDoc_STRVAR(_doubleloadtester__doc__, + "_doubleloadtester -- just for testing ticket #9 per ticket #44\n\ +"); + +static PyMethodDef _doubleloadtester_functions[] = { + {NULL, NULL, 0, NULL} /* sentinel */ +}; + +/* from Crypto++ */ +#ifdef DISABLE_EMBEDDED_CRYPTOPP +#include +#else +#include +#endif + +#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ +#define PyMODINIT_FUNC void +#endif +PyMODINIT_FUNC +init_doubleloadtester(void) { + const CryptoPP::NameValuePairs &my_nullNameValuePairs = CryptoPP::g_nullNameValuePairs; + PyObject *module; + + + printf("HELLO WORLD i'm doubleloadtester\n"); + printf("%d\n", my_nullNameValuePairs.GetVoidValue("anything", typeid(0), NULL)); + printf("GOODBYE i'm doubleloadtester\n"); + + module = Py_InitModule3("_doubleloadtester", _doubleloadtester_functions, _doubleloadtester__doc__); + if (!module) + return; +} diff --git a/_testdoubleloadmodule.cpp b/_testdoubleloadmodule.cpp deleted file mode 100644 index 61deeeb..0000000 --- a/_testdoubleloadmodule.cpp +++ /dev/null @@ -1,23 +0,0 @@ - -#include - -PyDoc_STRVAR(_testdoubleload__doc__, -"_testdoubleload -- just for testing ticket #9 per ticket #44\n\ -"); - -static PyMethodDef _testdoubleload_functions[] = { - {NULL, NULL, 0, NULL} /* sentinel */ -}; - -#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ -#define PyMODINIT_FUNC void -#endif -PyMODINIT_FUNC -init_testdoubleload(void) { - PyObject *module; - - module = Py_InitModule3("_testdoubleload", _testdoubleload_functions, _testdoubleload__doc__); - if (!module) - return; -} - diff --git a/copyright b/copyright index 85c072d..d59b0f5 100644 --- a/copyright +++ b/copyright @@ -17,7 +17,7 @@ See the file COPYING.TGPPL.html for the terms of the Transitive Grace Period Public Licence, version 1.0. The following licensing text applies to a subset of the Crypto++ source code -which is included in the pycryptopp source tree under the "embeddedcryptopp" +which is included in the pycryptopp source tree under the "src-cryptopp" subdirectory. That embedded subset of the Crypto++ source code is not used when pycryptopp is built for Debian -- instead the --disable-embedded-cryptopp option to "setup.py build" is used to for pycryptopp to build against the diff --git a/darcsver-1.6.3.egg/EGG-INFO/PKG-INFO b/darcsver-1.6.3.egg/EGG-INFO/PKG-INFO deleted file mode 100644 index 0bee80f..0000000 --- a/darcsver-1.6.3.egg/EGG-INFO/PKG-INFO +++ /dev/null @@ -1,121 +0,0 @@ -Metadata-Version: 1.0 -Name: darcsver -Version: 1.6.3 -Summary: generate a version number from darcs history -Home-page: http://tahoe-lafs.org/trac/darcsver -Author: Zooko O'Whielacronx -Author-email: zooko@zooko.com -License: BSD -Description: darcsver - generate version numbers from darcs revision control history - ======================================================================= - - What Does It Do - --------------- - - Create files containing version numbers, based upon the latest darcs - release tag. - - If your source tree is coming from darcs (i.e. it is in a darcs - repository), this tool will determine the most recent release tag, - count the patches that have been applied since then, and compute a - version number to be written into _version.py (and optionally other - version files). This version number will be available by doing: - - from your_package_name import __version__ - - Source trees that do not come from darcs (e.g. release tarballs, nightly - tarballs) and are not within a darcs repository should instead, come with a - _version.py that was generated before the tarball was produced. In this case, - this tool will quietly exit without modifying the existing _version.py . - - 'release tags' are tags in the source repository that match the following - regexp: - - ^your_package_name-(\d+)(\.(\d+)(\.(\d+))?)?((a|b|c|rc)(\d+))? - - - Installation - ------------ - - With easy_install: - - easy_install darcsver - - Alternative manual installation: - - tar -zxvf darcsver-X.Y.Z.tar.gz - cd darcsver-X.Y.Z - python setup.py install - - Where X.Y.Z is a version number. - - Alternative to make a specific package use darcsver without installing - darcsver into the system: - - Put "setup_requires=['darcsver']" in the call to setup() in the - package's setup.py file. - - - Usage - ----- - - There are two ways to use this: the command-line tool and the - setuptools plugin. - - To use the command-line tool, execute it as: - - darcsver $PACKAGE_NAME $PATH_TO_VERSION_PY - - - To use the setuptools plugin (which enables you to write "./setup.py - darcsver" and which cleverly figures out where the _version.py file - ought to go), you must first package your python module with - `setup.py` and use setuptools. - - The former is well documented in the distutils manual: - - http://docs.python.org/dist/dist.html - - To use setuptools instead of distutils, just edit `setup.py` and - change - - from distutils.core import setup - - to - - from setuptools import setup - - - References - ---------- - - How to distribute Python modules with Distutils: - - http://docs.python.org/dist/dist.html - - - Setuptools complete manual: - - http://peak.telecommunity.com/DevCenter/setuptools - - - Thanks to Yannick Gingras for providing the prototype for this - README.txt. - -Keywords: distutils setuptools plugin setup darcs -Platform: UNKNOWN -Classifier: Framework :: Setuptools Plugin -Classifier: Development Status :: 5 - Production/Stable -Classifier: License :: OSI Approved :: BSD License -Classifier: License :: DFSG approved -Classifier: Intended Audience :: Developers -Classifier: Operating System :: OS Independent -Classifier: Natural Language :: English -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.4 -Classifier: Programming Language :: Python :: 2.5 -Classifier: Programming Language :: Python :: 2.6 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Topic :: Utilities -Classifier: Topic :: Software Development :: Libraries diff --git a/darcsver-1.6.3.egg/EGG-INFO/SOURCES.txt b/darcsver-1.6.3.egg/EGG-INFO/SOURCES.txt deleted file mode 100644 index 38380a4..0000000 --- a/darcsver-1.6.3.egg/EGG-INFO/SOURCES.txt +++ /dev/null @@ -1,17 +0,0 @@ -README.txt -TODO -setup.py -darcsver/__init__.py -darcsver/_version.py -darcsver/darcsvermodule.py -darcsver/setuptools_command.py -darcsver.egg-info/PKG-INFO -darcsver.egg-info/SOURCES.txt -darcsver.egg-info/dependency_links.txt -darcsver.egg-info/entry_points.txt -darcsver.egg-info/not-zip-safe -darcsver.egg-info/top_level.txt -darcsver/test/__init__.py -darcsver/test/test_darcsver.py -scripts/__init__.py -scripts/darcsverscript.py \ No newline at end of file diff --git a/darcsver-1.6.3.egg/EGG-INFO/dependency_links.txt b/darcsver-1.6.3.egg/EGG-INFO/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/darcsver-1.6.3.egg/EGG-INFO/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/darcsver-1.6.3.egg/EGG-INFO/entry_points.txt b/darcsver-1.6.3.egg/EGG-INFO/entry_points.txt deleted file mode 100644 index 569b4e4..0000000 --- a/darcsver-1.6.3.egg/EGG-INFO/entry_points.txt +++ /dev/null @@ -1,10 +0,0 @@ -[distutils.setup_keywords] -versionbodies = darcsver.setuptools_command:validate_versionbodies -versionfiles = darcsver.setuptools_command:validate_versionfiles - -[console_scripts] -darcsver = scripts.darcsverscript:main - -[distutils.commands] -darcsver = darcsver.setuptools_command:DarcsVer - diff --git a/darcsver-1.6.3.egg/EGG-INFO/not-zip-safe b/darcsver-1.6.3.egg/EGG-INFO/not-zip-safe deleted file mode 100644 index 8b13789..0000000 --- a/darcsver-1.6.3.egg/EGG-INFO/not-zip-safe +++ /dev/null @@ -1 +0,0 @@ - diff --git a/darcsver-1.6.3.egg/EGG-INFO/top_level.txt b/darcsver-1.6.3.egg/EGG-INFO/top_level.txt deleted file mode 100644 index 4eebf09..0000000 --- a/darcsver-1.6.3.egg/EGG-INFO/top_level.txt +++ /dev/null @@ -1,2 +0,0 @@ -darcsver -scripts diff --git a/darcsver-1.6.3.egg/darcsver/__init__.py b/darcsver-1.6.3.egg/darcsver/__init__.py deleted file mode 100644 index 3421c13..0000000 --- a/darcsver-1.6.3.egg/darcsver/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -__version__ = "unknown" -try: - from _version import __version__ -except ImportError: - # We're running in a tree that hasn't run darcsver, and didn't come with a - # _version.py, so we don't know what our version is. This should not happen - # very often. - pass diff --git a/darcsver-1.6.3.egg/darcsver/_version.py b/darcsver-1.6.3.egg/darcsver/_version.py deleted file mode 100644 index 9d41f7d..0000000 --- a/darcsver-1.6.3.egg/darcsver/_version.py +++ /dev/null @@ -1,17 +0,0 @@ - -# This is the version of this tree, as created by setup.py darcsver from the darcs patch -# information: the main version number is taken from the most recent release -# tag. If some patches have been added since the last release, this will have a -# -NN "build number" suffix, or else a -rNN "revision number" suffix. Please see -# pyutil.version_class for a description of what the different fields mean. - -__pkgname__ = "darcsver" -verstr = "1.6.3" -try: - from pyutil.version_class import Version as pyutil_Version - __version__ = pyutil_Version(verstr) -except (ImportError, ValueError): - # Maybe there is no pyutil installed, or this may be an older version of - # pyutil.version_class which does not support SVN-alike revision numbers. - from distutils.version import LooseVersion as distutils_Version - __version__ = distutils_Version(verstr) diff --git a/darcsver-1.6.3.egg/darcsver/darcsvermodule.py b/darcsver-1.6.3.egg/darcsver/darcsvermodule.py deleted file mode 100644 index 4f03572..0000000 --- a/darcsver-1.6.3.egg/darcsver/darcsvermodule.py +++ /dev/null @@ -1,192 +0,0 @@ -import os, string, sys, re -import xml.dom.minidom -import subprocess -PIPE=subprocess.PIPE -from distutils import log - -def all(iterable): - for thing in iterable: - if not thing: - return False - return True - -OUR_VERSION_BASE_RE_STR="(\d+)(\.(\d+)(\.(\d+))?)?((a|b|c)(\d+))?(\.dev(\d+))?" -try: - # If we can import pyutil.version_class then use its regex. - from pyutil import version_class - VERSION_BASE_RE_STR = version_class.VERSION_BASE_RE_STR -except (ImportError, AttributeError): - # Else (perhaps a bootstrapping problem),then we'll use this - # regex, which was copied from the pyutil source code on - # 2010-09-02. - VERSION_BASE_RE_STR=OUR_VERSION_BASE_RE_STR - -def get_text(nodelist): - rc = "" - for node in nodelist: - if node.nodeType == node.TEXT_NODE: - rc = rc + node.data - return rc - -VERSION_BODY = ''' -# This is the version of this tree, as created by %(versiontool)s from the darcs patch -# information: the main version number is taken from the most recent release -# tag. If some patches have been added since the last release, this will have a -# -NN "build number" suffix, or else a -rNN "revision number" suffix. Please see -# pyutil.version_class for a description of what the different fields mean. - -__pkgname__ = "%(pkgname)s" -verstr = "%(pkgversion)s" -try: - from pyutil.version_class import Version as pyutil_Version - __version__ = pyutil_Version(verstr) -except (ImportError, ValueError): - # Maybe there is no pyutil installed. - from distutils.version import LooseVersion as distutils_Version - __version__ = distutils_Version(verstr) -''' - -def write_version_py(verstr, outfname, EXE_NAME, version_body, pkgname): - f = open(outfname, "wt+") - f.write(version_body % { - 'versiontool': EXE_NAME, - 'pkgversion': verstr, - 'pkgname': pkgname, - }) - f.close() - -def read_version_py(infname): - try: - verstrline = open(infname, "rt").read() - except EnvironmentError: - return None - else: - VSRE = r"^verstr = ['\"]([^'\"]*)['\"]" - mo = re.search(VSRE, verstrline, re.M) - if mo: - return mo.group(1) - -def update(pkgname, verfilename, revision_number=False, loud=False, abort_if_snapshot=False, EXE_NAME="darcsver", version_body=VERSION_BODY): - """ - @param revision_number If true, count the total number of patches in all - history. If false, count the total number of patches since the most recent - release tag. - - Returns a tuple of (exit code, new version string). - """ - if isinstance(verfilename, basestring): - verfilenames = [verfilename] - else: - verfilenames = verfilename - if isinstance(version_body, basestring): - verbodies = [version_body] - else: - verbodies = version_body - rc = -1 - - # First we try "darcs query repo" because if that fails then we - # won't try "darcs changes" at all, because "darcs changes" emits - # an ugly error message when run in not-a-repo. - try: - p = subprocess.Popen(["darcs", 'query', 'repo'], stdout=PIPE, stderr=PIPE, universal_newlines=True) - except OSError, ose: - if ose.errno == 2 and '~' in os.environ['PATH']: - expanded_path = os.environ['PATH'].replace('~', os.path.expanduser('~')) - msg = ("WARNING: 'darcs' was not found. However '~' was found in your PATH. \n" - "Please note that bugs in python cause it to fail to traverse '~' in \n" - "the user's PATH. Please fix your path, e.g. \nPATH=%s" ) - log.warn(msg % (expanded_path,)) - pass - else: - (output, errput) = p.communicate() - rc = p.returncode - - if rc == 0: - cmd = ["changes", "--xml-output"] - if not revision_number: - cmd.append("--from-tag=^%s" % (pkgname,)) - errput = None - try: - p = subprocess.Popen(["darcs"] + cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True) - except OSError: - pass - else: - (output, errput) = p.communicate() - rc = p.returncode - if rc != 0 and errput: - log.info("%s: darcs wrote to stderr: '%s'" % (EXE_NAME, errput,)) - else: - if all([os.path.exists(vfn) for vfn in verfilenames]): - log.info("%s: using extant version file %s" % (EXE_NAME, verfilenames)) - return (0, read_version_py(verfilenames[0])) - else: - log.warn("%s: didn't find version tags with darcs, and %s don't exist." % (EXE_NAME, verfilenames)) - return (rc, None) - - # Filter out bad chars that can cause the XML parser to give up in despair. - # (Thanks to lelit of the tailor project and ndurner and warner for this hack.) - allbadchars = "".join([chr(i) for i in range(0x0a) + [0x0b, 0x0c] + range(0x0e, 0x20) + range(0x7f,0x100)]) - tt = string.maketrans(allbadchars, "-"*len(allbadchars)) - output = output.translate(tt) - - # strip off trailing warning messages that darcs 2.3.1 writes to stdout - endi = output.find("")+len("") - output = output[:endi] - doc = xml.dom.minidom.parseString(output) - - changelog = doc.getElementsByTagName("changelog")[0] - patches = changelog.getElementsByTagName("patch") - regexstr = "^TAG %s-(%s)$" % (pkgname, VERSION_BASE_RE_STR) - version_re = re.compile(regexstr) - last_tag = None - count_since_last_patch = 0 - if abort_if_snapshot: - for patch in patches: - name = get_text(patch.getElementsByTagName("name")[0].childNodes) - m = version_re.match(name) - if m: - last_tag = m.group(1) - last_tag = last_tag.encode("utf-8") - break - else: - sys.exit(0) # because abort_if_snapshot - else: - for patch in patches: - name = get_text(patch.getElementsByTagName("name")[0].childNodes) - m = version_re.match(name) - if m: - last_tag = m.group(1) - last_tag = last_tag.encode("utf-8") - break - else: - count_since_last_patch += 1 - - if not last_tag: - if errput: - log.info("%s: darcs wrote to stderr: '%s'" % (EXE_NAME, errput,)) - if all([os.path.exists(vfn) for vfn in verfilenames]): - log.warn("%s: I'm unable to find a tag in the darcs history matching \"%s\", so I'm leaving %s alone." % (EXE_NAME, regexstr, verfilenames,)) - return (0, read_version_py(verfilenames[0])) - else: - log.warn("%s: I'm unable to find a tag in the darcs history matching \"%s\", and %s don't exist." % (EXE_NAME, regexstr, verfilenames,)) - return (0, None) - - if revision_number: - if count_since_last_patch: - # this is an interim version - verstr = "%s-r%d" % (last_tag, len(patches)) - else: - # this is a release - verstr = last_tag - else: - if count_since_last_patch: - # this is an interim version - verstr = "%s-%d" % (last_tag, count_since_last_patch) - else: - # this is a release - verstr = last_tag - - for verfn, verbod in zip(verfilenames, verbodies): - write_version_py(verstr, verfn, EXE_NAME, verbod, pkgname) - log.info("%s: wrote '%s' into %s" % (EXE_NAME, verstr, verfn,)) - return (0, verstr) diff --git a/darcsver-1.6.3.egg/darcsver/setuptools_command.py b/darcsver-1.6.3.egg/darcsver/setuptools_command.py deleted file mode 100644 index 44fd50c..0000000 --- a/darcsver-1.6.3.egg/darcsver/setuptools_command.py +++ /dev/null @@ -1,116 +0,0 @@ -import os - -import setuptools - -from darcsver import darcsvermodule - -from distutils.errors import DistutilsSetupError - -def validate_string_or_iter_of_strings(dist, attr, value): - # value is required to be a string or else a list of strings - if isinstance(value, basestring): - return - try: - for thing in value: - if not isinstance(thing, basestring): - raise DistutilsSetupError("%r is required to be a string or an iterable of strings (got %r)" % (attr, value)) - except TypeError: - raise DistutilsSetupError("%r is required to be a string or an iterable of strings (got %r)" % (attr, value)) - -def validate_versionfiles(dist, attr, value): - return validate_string_or_iter_of_strings(dist, attr, value) - -def validate_versionbodies(dist, attr, value): - return validate_string_or_iter_of_strings(dist, attr, value) - -PYTHON_VERSION_BODY=''' -# This is the version of this tree, as created by %(versiontool)s from the darcs patch -# information: the main version number is taken from the most recent release -# tag. If some patches have been added since the last release, this will have a -# -NN "build number" suffix, or else a -rNN "revision number" suffix. Please see -# pyutil.version_class for a description of what the different fields mean. - -__pkgname__ = "%(pkgname)s" -verstr = "%(pkgversion)s" -try: - from pyutil.version_class import Version as pyutil_Version - __version__ = pyutil_Version(verstr) -except (ImportError, ValueError): - # Maybe there is no pyutil installed, or this may be an older version of - # pyutil.version_class which does not support SVN-alike revision numbers. - from distutils.version import LooseVersion as distutils_Version - __version__ = distutils_Version(verstr) -''' - -class DarcsVer(setuptools.Command): - description = "generate a version number from darcs history" - user_options = [ - ('project-name', None, "name of the project as it appears in the project's release tags (default's the to the distribution name)"), - ('version-file', None, "path to file into which the version number should be written (defaults to the package directory's _version.py)"), - ('count-all-patches', None, "If true, count the total number of patches in all history. If false, count the total number of patches since the most recent release tag."), - ('abort-if-snapshot', None, "If true, the if the current version is a snapshot (not a release tag), then immediately exit the process with exit code 0."), - ] - - def initialize_options(self): - self.project_name = None - self.version_file = None - self.count_all_patches = None - self.abort_if_snapshot = None - - def finalize_options(self): - if self.project_name is None: - self.project_name = self.distribution.get_name() - - # If the user passed --version-file on the cmdline, override - # the setup.py's versionfiles argument. - if self.version_file is not None: - self.distribution.versionfiles = [self.version_file] - - if self.abort_if_snapshot is None: - self.abort_if_snapshot=False - - def run(self): - if self.distribution.versionfiles is None: - toppackage = '' - # If there is a package with the same name as the project name and - # there is a directory by that name then use that. - packagedir = None - if self.distribution.packages and self.project_name in self.distribution.packages: - toppackage = self.project_name - srcdir = '' - if self.distribution.package_dir: - srcdir = self.distribution.package_dir.get(toppackage) - if not srcdir is None: - srcdir = self.distribution.package_dir.get('', '') - packagedir = os.path.join(srcdir, toppackage) - - if packagedir is None or not os.path.isdir(packagedir): - # Else, if there is a singly-rooted tree of packages, use the - # root of that. - if self.distribution.packages: - for package in self.distribution.packages: - if not toppackage: - toppackage = package - else: - if toppackage.startswith(package+"."): - toppackage = package - else: - if not package.startswith(toppackage+"."): - # Not singly-rooted - toppackage = '' - break - - srcdir = '' - if self.distribution.package_dir: - srcdir = self.distribution.package_dir.get(toppackage) - if srcdir is None: - srcdir = self.distribution.package_dir.get('', '') - packagedir = os.path.join(srcdir, toppackage) - - self.distribution.versionfiles = [os.path.join(packagedir, '_version.py')] - - if self.distribution.versionbodies is None: - self.distribution.versionbodies = [PYTHON_VERSION_BODY] - - (rc, verstr) = darcsvermodule.update(self.project_name, self.distribution.versionfiles, self.count_all_patches, abort_if_snapshot=self.abort_if_snapshot, EXE_NAME="setup.py darcsver", version_body=self.distribution.versionbodies) - self.distribution.metadata.version = verstr diff --git a/darcsver-1.6.3.egg/scripts/__init__.py b/darcsver-1.6.3.egg/scripts/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/darcsver-1.6.3.egg/scripts/darcsverscript.py b/darcsver-1.6.3.egg/scripts/darcsverscript.py deleted file mode 100644 index 7c54f53..0000000 --- a/darcsver-1.6.3.egg/scripts/darcsverscript.py +++ /dev/null @@ -1,46 +0,0 @@ -#! /usr/bin/env python - -from optparse import OptionParser -import os, sys - -from darcsver import darcsvermodule, __version__ - -try: - EXE_NAME=os.path.basename(sys.argv[0]) -except: - EXE_NAME="darcsver" - -def main(): - parser = OptionParser(usage="Usage: %prog [options] [pkgname [verfilename]]", - version="%prog " + str(__version__), - prog=EXE_NAME) - parser.add_option("-q", "--quiet", default=False, action="store_true", - help="Be quiet, do the job without any output.") - parser.add_option("--count-all-patches", "--revision-number", default=False, - action="store_true", dest="count_all_patches", - help="By default %s counts the number of patches since the " - "most recent release tag. With this option, it counts " - "all the patches in the repository." % EXE_NAME) - - options, args = parser.parse_args() - - if args: - pkgname = args.pop(0) - else: - pkgname = os.path.basename(os.getcwd()) - if not options.quiet: - print "%s: You didn't pass a pkg-name on the command-line, so I'm going to take the name of the current working directory: \"%s\"" % (EXE_NAME, pkgname,) - - if args: - verfilename = args.pop(0) - else: - verfilename = os.path.join(pkgname, "_version.py") - if not options.quiet: - print "%s: You didn't pass a verfilename on the command-line, so I'm going to build one from the name of the package: \"%s\"" % (EXE_NAME, verfilename,) - - (rc, newverstr) = darcsvermodule.update(pkgname=pkgname, verfilename=verfilename, revision_number=options.count_all_patches, quiet=options.quiet, EXE_NAME=EXE_NAME) - return rc - -if __name__ == "__main__": - rc = main() - sys.exit(rc) diff --git a/darcsver-1.6.3.egg/share/doc/python-darcsver/README.txt b/darcsver-1.6.3.egg/share/doc/python-darcsver/README.txt deleted file mode 100644 index 8f0ffa7..0000000 --- a/darcsver-1.6.3.egg/share/doc/python-darcsver/README.txt +++ /dev/null @@ -1,95 +0,0 @@ -darcsver - generate version numbers from darcs revision control history -======================================================================= - -What Does It Do ---------------- - -Create files containing version numbers, based upon the latest darcs -release tag. - -If your source tree is coming from darcs (i.e. it is in a darcs -repository), this tool will determine the most recent release tag, -count the patches that have been applied since then, and compute a -version number to be written into _version.py (and optionally other -version files). This version number will be available by doing: - - from your_package_name import __version__ - -Source trees that do not come from darcs (e.g. release tarballs, nightly -tarballs) and are not within a darcs repository should instead, come with a -_version.py that was generated before the tarball was produced. In this case, -this tool will quietly exit without modifying the existing _version.py . - -'release tags' are tags in the source repository that match the following -regexp: - - ^your_package_name-(\d+)(\.(\d+)(\.(\d+))?)?((a|b|c|rc)(\d+))? - - -Installation ------------- - -With easy_install: - - easy_install darcsver - -Alternative manual installation: - - tar -zxvf darcsver-X.Y.Z.tar.gz - cd darcsver-X.Y.Z - python setup.py install - -Where X.Y.Z is a version number. - -Alternative to make a specific package use darcsver without installing -darcsver into the system: - - Put "setup_requires=['darcsver']" in the call to setup() in the - package's setup.py file. - - -Usage ------ - -There are two ways to use this: the command-line tool and the -setuptools plugin. - -To use the command-line tool, execute it as: - -darcsver $PACKAGE_NAME $PATH_TO_VERSION_PY - - -To use the setuptools plugin (which enables you to write "./setup.py -darcsver" and which cleverly figures out where the _version.py file -ought to go), you must first package your python module with -`setup.py` and use setuptools. - -The former is well documented in the distutils manual: - - http://docs.python.org/dist/dist.html - -To use setuptools instead of distutils, just edit `setup.py` and -change - - from distutils.core import setup - -to - - from setuptools import setup - - -References ----------- - -How to distribute Python modules with Distutils: - - http://docs.python.org/dist/dist.html - - -Setuptools complete manual: - - http://peak.telecommunity.com/DevCenter/setuptools - - -Thanks to Yannick Gingras for providing the prototype for this -README.txt. diff --git a/embeddedcryptopp/Doxyfile b/embeddedcryptopp/Doxyfile deleted file mode 100644 index 1fb9d81..0000000 --- a/embeddedcryptopp/Doxyfile +++ /dev/null @@ -1,1109 +0,0 @@ -# Doxyfile 1.3.7 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = Crypto++ - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = doc - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 2 levels of 10 sub-directories under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of source -# files, where putting all generated files in the same directory would otherwise -# cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, -# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en -# (Japanese with English messages), Korean, Korean-en, Norwegian, Polish, Portuguese, -# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is used -# as the annotated text. Otherwise, the brief description is used as-is. If left -# blank, the following values are used ("$name" is automatically replaced with the -# name of the entity): "The $name class" "The $name widget" "The $name file" -# "is" "provides" "specifies" "contains" "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited -# members of a class in the documentation of that class as if those members were -# ordinary class members. Constructors, destructors and assignment operators of -# the base classes will not be shown. - -INLINE_INHERITED_MEMB = YES - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = NO - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like the Qt-style comments (thus requiring an -# explicit @brief command for a brief description. - -JAVADOC_AUTOBRIEF = YES - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the DETAILS_AT_TOP tag is set to YES then Doxygen -# will output the detailed description near the top, like JavaDoc. -# If set to NO, the detailed description appears after the member -# documentation. - -DETAILS_AT_TOP = Yes - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 8 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources -# only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources -# only. Doxygen will then generate output that is more tailored for Java. -# For instance, namespaces will be presented as packages, qualified scopes -# will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# users are advised to set this option to NO. - -CASE_SENSE_NAMES = NO - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = NO - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = No - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = No - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = . - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp -# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm - -FILE_PATTERNS = *.h \ - *.cpp - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = NO - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = adhoc.cpp - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories -# that are symbolic links (a Unix filesystem feature) are excluded from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. - -EXCLUDE_PATTERNS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = . - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. - -INPUT_FILTER = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = YES - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = NO - -# If the REFERENCED_BY_RELATION tag is set to YES (the default) -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = YES - -# If the REFERENCES_RELATION tag is set to YES (the default) -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = YES - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = YES - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 3 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = YES - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be -# generated containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, -# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are -# probably better off using the HTML help feature. - -GENERATE_TREEVIEW = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4 - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = NO - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = NO - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. This is useful -# if you want to understand what is going on. On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = YES - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_PREDEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = . - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. - -PREDEFINED = _WIN32 \ - _WINDOWS \ - __FreeBSD__ \ - CRYPTOPP_DOXYGEN_PROCESSING - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse the -# parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or -# super classes. Setting the tag to NO turns the diagrams off. Note that this -# option is superseded by the HAVE_DOT option below. This is only a fallback. It is -# recommended to install and use dot, since it yields more powerful graphs. - -CLASS_DIAGRAMS = YES - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = NO - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will -# generate a call dependency graph for every global function or class method. -# Note that enabling this option will significantly increase the time of a run. -# So in most cases it will be better to enable call graphs for selected -# functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found on the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- - -# The SEARCHENGINE tag specifies whether or not a search engine should be -# used. If set to NO the values of all tags below this one will be ignored. - -SEARCHENGINE = NO diff --git a/embeddedcryptopp/GNUmakefile b/embeddedcryptopp/GNUmakefile deleted file mode 100644 index 291eb60..0000000 --- a/embeddedcryptopp/GNUmakefile +++ /dev/null @@ -1,168 +0,0 @@ -CXXFLAGS = -DNDEBUG -g -O2 -#CXXFLAGS = -g -# -fPIC is supported. Please report any breakage of -fPIC as a bug. -# CXXFLAGS += -fPIC -# the following options reduce code size, but breaks link or makes link very slow on some systems -# CXXFLAGS += -ffunction-sections -fdata-sections -# LDFLAGS += -Wl,--gc-sections -ARFLAGS = -cr # ar needs the dash on OpenBSD -RANLIB = ranlib -CP = cp -MKDIR = mkdir -EGREP = egrep -UNAME = $(shell uname) -ISX86 = $(shell uname -m | $(EGREP) -c "i.86|x86|i86|amd64") - -# Default prefix for make install -ifeq ($(PREFIX),) -PREFIX = /usr -endif - -ifeq ($(CXX),gcc) # for some reason CXX is gcc on cygwin 1.1.4 -CXX = g++ -endif - -ifeq ($(ISX86),1) - -GCC42_OR_LATER = $(shell $(CXX) --version 2>&1 | $(EGREP) -c "\(GCC\) (4.[2-9]|[5-9])") -INTEL_COMPILER = $(shell $(CXX) --version 2>&1 | $(EGREP) -c "\(ICC\)") -GAS210_OR_LATER = $(shell echo "" | $(AS) -v 2>&1 | $(EGREP) -c "GNU assembler version (2\.[1-9][0-9]|[3-9])") -GAS217_OR_LATER = $(shell echo "" | $(AS) -v 2>&1 | $(EGREP) -c "GNU assembler version (2\.1[7-9]|2\.[2-9]|[3-9])") -ISMINGW = $(shell $(CXX) --version 2>&1 | $(EGREP) -c "mingw") - -ifneq ($(GCC42_OR_LATER),0) -ifneq ($(UNAME),Darwin) -CXXFLAGS += -march=native -mtune=native -endif -endif - -ifneq ($(INTEL_COMPILER),0) -# "internal error: backend signals" occurs on some x86 inline assembly with ICC 9 and some x64 inline assembly with ICC 11 -# if you want to use Crypto++'s assembly code with ICC, try enabling it on individual files -CXXFLAGS += -DCRYPTOPP_DISABLE_ASM -endif - -ifeq ($(GAS210_OR_LATER),0) # .intel_syntax wasn't supported until GNU assembler 2.10 -CXXFLAGS += -DCRYPTOPP_DISABLE_ASM -else -ifeq ($(GAS217_OR_LATER),0) -CXXFLAGS += -DCRYPTOPP_DISABLE_SSSE3 -endif -ifeq ($(UNAME),SunOS) -CXXFLAGS += -Wa,--divide # allow use of "/" operator -endif -endif - -ifeq ($(ISMINGW),1) -LDLIBS += -lws2_32 -endif - -endif # ISX86 - -ifeq ($(UNAME),) # for DJGPP, where uname doesn't exist -CXXFLAGS += -mbnu210 -else -CXXFLAGS += -pipe -endif - -ifeq ($(UNAME),Linux) -LDFLAGS += -pthread -endif - -ifeq ($(UNAME),Darwin) -AR = libtool -ARFLAGS = -static -o -CXX = c++ -IS_GCC2 = $(shell $(CXX) -v 2>&1 | $(EGREP) -c gcc-932) -ifeq ($(IS_GCC2),1) -CXXFLAGS += -fno-coalesce-templates -fno-coalesce-static-vtables -LDLIBS += -lstdc++ -LDFLAGS += -flat_namespace -undefined suppress -m -endif -endif - -ifeq ($(UNAME),SunOS) -LDLIBS += -lnsl -lsocket -ifeq ($(CXX),CC) # override flags for CC (Solaris native C++ compiler) -CXXFLAGS = -DNDEBUG -O -g0 -native -template=no%extdef -m$(shell isainfo -b) -LDFLAGS = -ifeq ($(ISX86),1) -# SSE2 intrinsics should work in Sun Studio 12, but we're not using SSE2 intrinsics anymore -# CXXFLAGS += -xarch=sse2 -D__SSE2__ -endif -endif -endif - -SRCS = $(wildcard *.cpp) -ifeq ($(SRCS),) # workaround wildcard function bug in GNU Make 3.77 -SRCS = $(shell echo *.cpp) -endif - -OBJS = $(SRCS:.cpp=.o) -# test.o needs to be after bench.o for cygwin 1.1.4 (possible ld bug?) -TESTOBJS = bench.o bench2.o test.o validat1.o validat2.o validat3.o adhoc.o datatest.o regtest.o fipsalgt.o dlltest.o -LIBOBJS = $(filter-out $(TESTOBJS),$(OBJS)) - -DLLSRCS = algebra.cpp algparam.cpp asn.cpp basecode.cpp cbcmac.cpp channels.cpp cryptlib.cpp des.cpp dessp.cpp dh.cpp dll.cpp dsa.cpp ec2n.cpp eccrypto.cpp ecp.cpp eprecomp.cpp files.cpp filters.cpp fips140.cpp fipstest.cpp gf2n.cpp gfpcrypt.cpp hex.cpp hmac.cpp integer.cpp iterhash.cpp misc.cpp modes.cpp modexppc.cpp mqueue.cpp nbtheory.cpp oaep.cpp osrng.cpp pch.cpp pkcspad.cpp pubkey.cpp queue.cpp randpool.cpp rdtables.cpp rijndael.cpp rng.cpp rsa.cpp sha.cpp simple.cpp skipjack.cpp strciphr.cpp trdlocal.cpp -DLLOBJS = $(DLLSRCS:.cpp=.export.o) -LIBIMPORTOBJS = $(LIBOBJS:.o=.import.o) -TESTIMPORTOBJS = $(TESTOBJS:.o=.import.o) -DLLTESTOBJS = dlltest.dllonly.o - -all: cryptest.exe - -test: cryptest.exe - ./cryptest.exe v - -clean: - $(RM) cryptest.exe libcryptopp.a $(LIBOBJS) $(TESTOBJS) cryptopp.dll libcryptopp.dll.a libcryptopp.import.a cryptest.import.exe dlltest.exe $(DLLOBJS) $(LIBIMPORTOBJS) $(TESTIMPORTOBJS) $(DLLTESTOBJS) - -install: - $(MKDIR) -p $(PREFIX)/include/cryptopp $(PREFIX)/lib $(PREFIX)/bin - $(CP) *.h $(PREFIX)/include/cryptopp - $(CP) *.a $(PREFIX)/lib - $(CP) *.exe $(PREFIX)/bin - -libcryptopp.a: $(LIBOBJS) - $(AR) $(ARFLAGS) $@ $(LIBOBJS) - $(RANLIB) $@ - -cryptest.exe: libcryptopp.a $(TESTOBJS) - $(CXX) -o $@ $(CXXFLAGS) $(TESTOBJS) -L. -lcryptopp $(LDFLAGS) $(LDLIBS) - -nolib: $(OBJS) # makes it faster to test changes - $(CXX) -o ct $(CXXFLAGS) $(OBJS) $(LDFLAGS) $(LDLIBS) - -dll: cryptest.import.exe dlltest.exe - -cryptopp.dll: $(DLLOBJS) - $(CXX) -shared -o $@ $(CXXFLAGS) $(DLLOBJS) $(LDFLAGS) $(LDLIBS) -Wl,--out-implib=libcryptopp.dll.a - -libcryptopp.import.a: $(LIBIMPORTOBJS) - $(AR) $(ARFLAGS) $@ $(LIBIMPORTOBJS) - $(RANLIB) $@ - -cryptest.import.exe: cryptopp.dll libcryptopp.import.a $(TESTIMPORTOBJS) - $(CXX) -o $@ $(CXXFLAGS) $(TESTIMPORTOBJS) -L. -lcryptopp.dll -lcryptopp.import $(LDFLAGS) $(LDLIBS) - -dlltest.exe: cryptopp.dll $(DLLTESTOBJS) - $(CXX) -o $@ $(CXXFLAGS) $(DLLTESTOBJS) -L. -lcryptopp.dll $(LDFLAGS) $(LDLIBS) - -adhoc.cpp: adhoc.cpp.proto -ifeq ($(wildcard adhoc.cpp),) - cp adhoc.cpp.proto adhoc.cpp -else - touch adhoc.cpp -endif - -%.dllonly.o : %.cpp - $(CXX) $(CXXFLAGS) -DCRYPTOPP_DLL_ONLY -c $< -o $@ - -%.import.o : %.cpp - $(CXX) $(CXXFLAGS) -DCRYPTOPP_IMPORTS -c $< -o $@ - -%.export.o : %.cpp - $(CXX) $(CXXFLAGS) -DCRYPTOPP_EXPORTS -c $< -o $@ - -%.o : %.cpp - $(CXX) $(CXXFLAGS) -c $< diff --git a/embeddedcryptopp/License.txt b/embeddedcryptopp/License.txt deleted file mode 100644 index fc3f054..0000000 --- a/embeddedcryptopp/License.txt +++ /dev/null @@ -1,67 +0,0 @@ -Compilation Copyright (c) 1995-2009 by Wei Dai. All rights reserved. -This copyright applies only to this software distribution package -as a compilation, and does not imply a copyright on any particular -file in the package. - -The following files are copyrighted by their respective original authors, -and their use is subject to additional licenses included in these files. - -mars.cpp - Copyright 1998 Brian Gladman. - -All other files in this compilation are placed in the public domain by -Wei Dai and other contributors. - -I would like to thank the following authors for placing their works into -the public domain: - -Joan Daemen - 3way.cpp -Leonard Janke - cast.cpp, seal.cpp -Steve Reid - cast.cpp -Phil Karn - des.cpp -Andrew M. Kuchling - md2.cpp, md4.cpp -Colin Plumb - md5.cpp -Seal Woods - rc6.cpp -Chris Morgan - rijndael.cpp -Paulo Baretto - rijndael.cpp, skipjack.cpp, square.cpp -Richard De Moliner - safer.cpp -Matthew Skala - twofish.cpp -Kevin Springle - camellia.cpp, shacal2.cpp, ttmac.cpp, whrlpool.cpp, ripemd.cpp - -Permission to use, copy, modify, and distribute this compilation for -any purpose, including commercial applications, is hereby granted -without fee, subject to the following restrictions: - -1. Any copy or modification of this compilation in any form, except -in object code form as part of an application software, must include -the above copyright notice and this license. - -2. Users of this software agree that any modification or extension -they provide to Wei Dai will be considered public domain and not -copyrighted unless it includes an explicit copyright notice. - -3. Wei Dai makes no warranty or representation that the operation of the -software in this compilation will be error-free, and Wei Dai is under no -obligation to provide any services, by way of maintenance, update, or -otherwise. THE SOFTWARE AND ANY DOCUMENTATION ARE PROVIDED "AS IS" -WITHOUT EXPRESS OR IMPLIED WARRANTY INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. IN NO EVENT WILL WEI DAI OR ANY OTHER CONTRIBUTOR BE LIABLE FOR -DIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -4. Users will not use Wei Dai or any other contributor's name in any -publicity or advertising, without prior written consent in each case. - -5. Export of this software from the United States may require a -specific license from the United States Government. It is the -responsibility of any person or organization contemplating export -to obtain such a license before exporting. - -6. Certain parts of this software may be protected by patents. It -is the users' responsibility to obtain the appropriate -licenses before using those parts. - -If this compilation is used in object code form in an application -software, acknowledgement of the author is not required but would be -appreciated. The contribution of any useful modifications or extensions -to Wei Dai is not required but would also be appreciated. diff --git a/embeddedcryptopp/Readme.txt b/embeddedcryptopp/Readme.txt deleted file mode 100644 index 861c036..0000000 --- a/embeddedcryptopp/Readme.txt +++ /dev/null @@ -1,429 +0,0 @@ -Crypto++: a C++ Class Library of Cryptographic Schemes -Version 5.6.0 (3/15/2009) - -Crypto++ Library is a free C++ class library of cryptographic schemes. -Currently the library contains the following algorithms: - - algorithm type name - - authenticated encryption schemes GCM, CCM, EAX - - high speed stream ciphers Panama, Sosemanuk, Salsa20, XSalsa20 - - AES and AES candidates AES (Rijndael), RC6, MARS, Twofish, Serpent, - CAST-256 - - IDEA, Triple-DES (DES-EDE2 and DES-EDE3), - other block ciphers Camellia, SEED, RC5, Blowfish, TEA, XTEA, - Skipjack, SHACAL-2 - - block cipher modes of operation ECB, CBC, CBC ciphertext stealing (CTS), - CFB, OFB, counter mode (CTR) - - message authentication codes VMAC, HMAC, CMAC, CBC-MAC, DMAC, - Two-Track-MAC - - SHA-1, SHA-2 (SHA-224, SHA-256, SHA-384, and - hash functions SHA-512), Tiger, WHIRLPOOL, RIPEMD-128, - RIPEMD-256, RIPEMD-160, RIPEMD-320 - - RSA, DSA, ElGamal, Nyberg-Rueppel (NR), - public-key cryptography Rabin, Rabin-Williams (RW), LUC, LUCELG, - DLIES (variants of DHAES), ESIGN - - padding schemes for public-key PKCS#1 v2.0, OAEP, PSS, PSSR, IEEE P1363 - systems EMSA2 and EMSA5 - - Diffie-Hellman (DH), Unified Diffie-Hellman - key agreement schemes (DH2), Menezes-Qu-Vanstone (MQV), LUCDIF, - XTR-DH - - elliptic curve cryptography ECDSA, ECNR, ECIES, ECDH, ECMQV - - insecure or obsolescent MD2, MD4, MD5, Panama Hash, DES, ARC4, SEAL -algorithms retained for backwards 3.0, WAKE, WAKE-OFB, DESX (DES-XEX3), RC2, - compatibility and historical SAFER, 3-WAY, GOST, SHARK, CAST-128, Square - value - -Other features include: - - * pseudo random number generators (PRNG): ANSI X9.17 appendix C, RandomPool - * password based key derivation functions: PBKDF1 and PBKDF2 from PKCS #5, - PBKDF from PKCS #12 appendix B - * Shamir's secret sharing scheme and Rabin's information dispersal algorithm - (IDA) - * fast multi-precision integer (bignum) and polynomial operations - * finite field arithmetics, including GF(p) and GF(2^n) - * prime number generation and verification - * useful non-cryptographic algorithms - + DEFLATE (RFC 1951) compression/decompression with gzip (RFC 1952) and - zlib (RFC 1950) format support - + hex, base-32, and base-64 coding/decoding - + 32-bit CRC and Adler32 checksum - * class wrappers for these operating system features (optional): - + high resolution timers on Windows, Unix, and Mac OS - + Berkeley and Windows style sockets - + Windows named pipes - + /dev/random, /dev/urandom, /dev/srandom - + Microsoft's CryptGenRandom on Windows - * A high level interface for most of the above, using a filter/pipeline - metaphor - * benchmarks and validation testing - * x86, x86-64 (x64), MMX, and SSE2 assembly code for the most commonly used - algorithms, with run-time CPU feature detection and code selection - * some versions are available in FIPS 140-2 validated form - -You are welcome to use it for any purpose without paying me, but see -License.txt for the fine print. - -The following compilers are supported for this release. Please visit -http://www.cryptopp.com the most up to date build instructions and porting notes. - - * MSVC 6.0 - 2008 - * GCC 3.3 - 4.3 - * C++Builder 2009 - * Intel C++ Compiler 9 - 11 - * Sun Studio 12 (CC 5.9) - -*** Important Usage Notes *** - -1. If a constructor for A takes a pointer to an object B (except primitive -types such as int and char), then A owns B and will delete B at A's -destruction. If a constructor for A takes a reference to an object B, -then the caller retains ownership of B and should not destroy it until -A no longer needs it. - -2. Crypto++ is thread safe at the class level. This means you can use -Crypto++ safely in a multithreaded application, but you must provide -synchronization when multiple threads access a common Crypto++ object. - -*** MSVC-Specific Information *** - -On Windows, Crypto++ can be compiled into 3 forms: a static library -including all algorithms, a DLL with only FIPS Approved algorithms, and -a static library with only algorithms not in the DLL. -(FIPS Approved means Approved according to the FIPS 140-2 standard.) -The DLL may be used by itself, or it may be used together with the second -form of the static library. MSVC project files are included to build -all three forms, and sample applications using each of the three forms -are also included. - -To compile Crypto++ with MSVC, open the "cryptest.dsw" (for MSVC 6 and MSVC .NET -2003) or "cryptest.sln" (for MSVC .NET 2005) workspace file and build one or -more of the following projects: - -cryptdll - This builds the DLL. Please note that if you wish to use Crypto++ - as a FIPS validated module, you must use a pre-built DLL that has undergone - the FIPS validation process instead of building your own. -dlltest - This builds a sample application that only uses the DLL. -cryptest Non-DLL-Import Configuration - This builds the full static library - along with a full test driver. -cryptest DLL-Import Configuration - This builds a static library containing - only algorithms not in the DLL, along with a full test driver that uses - both the DLL and the static library. - -To use the Crypto++ DLL in your application, #include "dll.h" before including -any other Crypto++ header files, and place the DLL in the same directory as -your .exe file. dll.h includes the line #pragma comment(lib, "cryptopp") -so you don't have to explicitly list the import library in your project -settings. To use a static library form of Crypto++, specify it as -an additional library to link with in your project settings. -In either case you should check the compiler options to -make sure that the library and your application are using the same C++ -run-time libraries and calling conventions. - -*** DLL Memory Management *** - -Because it's possible for the Crypto++ DLL to delete objects allocated -by the calling application, they must use the same C++ memory heap. Three -methods are provided to achieve this. -1. The calling application can tell Crypto++ what heap to use. This method - is required when the calling application uses a non-standard heap. -2. Crypto++ can tell the calling application what heap to use. This method - is required when the calling application uses a statically linked C++ Run - Time Library. (Method 1 does not work in this case because the Crypto++ DLL - is initialized before the calling application's heap is initialized.) -3. Crypto++ can automatically use the heap provided by the calling application's - dynamically linked C++ Run Time Library. The calling application must - make sure that the dynamically linked C++ Run Time Library is initialized - before Crypto++ is loaded. (At this time it is not clear if it is possible - to control the order in which DLLs are initialized on Windows 9x machines, - so it might be best to avoid using this method.) - -When Crypto++ attaches to a new process, it searches all modules loaded -into the process space for exported functions "GetNewAndDeleteForCryptoPP" -and "SetNewAndDeleteFromCryptoPP". If one of these functions is found, -Crypto++ uses methods 1 or 2, respectively, by calling the function. -Otherwise, method 3 is used. - -*** GCC-Specific Information *** - -A makefile is included for you to compile Crypto++ with GCC. Make sure -you are using GNU Make and GNU ld. The make process will produce two files, -libcryptopp.a and cryptest.exe. Run "cryptest.exe v" for the validation -suite. - -*** Documentation and Support *** - -Crypto++ is documented through inline comments in header files, which are -processed through Doxygen to produce an HTML reference manual. You can find -a link to the manual from http://www.cryptopp.com. Also at that site is -the Crypto++ FAQ, which you should browse through before attempting to -use this library, because it will likely answer many of questions that -may come up. - -If you run into any problems, please try the Crypto++ mailing list. -The subscription information and the list archive are available on -http://www.cryptopp.com. You can also email me directly by visiting -http://www.weidai.com, but you will probably get a faster response through -the mailing list. - -*** History *** - -1.0 - First public release. Withdrawn at the request of RSA DSI. - - included Blowfish, BBS, DES, DH, Diamond, DSA, ElGamal, IDEA, - MD5, RC4, RC5, RSA, SHA, WAKE, secret sharing, DEFLATE compression - - had a serious bug in the RSA key generation code. - -1.1 - Removed RSA, RC4, RC5 - - Disabled calls to RSAREF's non-public functions - - Minor bugs fixed - -2.0 - a completely new, faster multiprecision integer class - - added MD5-MAC, HAVAL, 3-WAY, TEA, SAFER, LUC, Rabin, BlumGoldwasser, - elliptic curve algorithms - - added the Lucas strong probable primality test - - ElGamal encryption and signature schemes modified to avoid weaknesses - - Diamond changed to Diamond2 because of key schedule weakness - - fixed bug in WAKE key setup - - SHS class renamed to SHA - - lots of miscellaneous optimizations - -2.1 - added Tiger, HMAC, GOST, RIPE-MD160, LUCELG, LUCDIF, XOR-MAC, - OAEP, PSSR, SHARK - - added precomputation to DH, ElGamal, DSA, and elliptic curve algorithms - - added back RC5 and a new RSA - - optimizations in elliptic curves over GF(p) - - changed Rabin to use OAEP and PSSR - - changed many classes to allow copy constructors to work correctly - - improved exception generation and handling - -2.2 - added SEAL, CAST-128, Square - - fixed bug in HAVAL (padding problem) - - fixed bug in triple-DES (decryption order was reversed) - - fixed bug in RC5 (couldn't handle key length not a multiple of 4) - - changed HMAC to conform to RFC-2104 (which is not compatible - with the original HMAC) - - changed secret sharing and information dispersal to use GF(2^32) - instead of GF(65521) - - removed zero knowledge prover/verifier for graph isomorphism - - removed several utility classes in favor of the C++ standard library - -2.3 - ported to EGCS - - fixed incomplete workaround of min/max conflict in MSVC - -3.0 - placed all names into the "CryptoPP" namespace - - added MD2, RC2, RC6, MARS, RW, DH2, MQV, ECDHC, CBC-CTS - - added abstract base classes PK_SimpleKeyAgreementDomain and - PK_AuthenticatedKeyAgreementDomain - - changed DH and LUCDIF to implement the PK_SimpleKeyAgreementDomain - interface and to perform domain parameter and key validation - - changed interfaces of PK_Signer and PK_Verifier to sign and verify - messages instead of message digests - - changed OAEP to conform to PKCS#1 v2.0 - - changed benchmark code to produce HTML tables as output - - changed PSSR to track IEEE P1363a - - renamed ElGamalSignature to NR and changed it to track IEEE P1363 - - renamed ECKEP to ECMQVC and changed it to track IEEE P1363 - - renamed several other classes for clarity - - removed support for calling RSAREF - - removed option to compile old SHA (SHA-0) - - removed option not to throw exceptions - -3.1 - added ARC4, Rijndael, Twofish, Serpent, CBC-MAC, DMAC - - added interface for querying supported key lengths of symmetric ciphers - and MACs - - added sample code for RSA signature and verification - - changed CBC-CTS to be compatible with RFC 2040 - - updated SEAL to version 3.0 of the cipher specification - - optimized multiprecision squaring and elliptic curves over GF(p) - - fixed bug in MARS key setup - - fixed bug with attaching objects to Deflator - -3.2 - added DES-XEX3, ECDSA, DefaultEncryptorWithMAC - - renamed DES-EDE to DES-EDE2 and TripleDES to DES-EDE3 - - optimized ARC4 - - generalized DSA to allow keys longer than 1024 bits - - fixed bugs in GF2N and ModularArithmetic that can cause calculation errors - - fixed crashing bug in Inflator when given invalid inputs - - fixed endian bug in Serpent - - fixed padding bug in Tiger - -4.0 - added Skipjack, CAST-256, Panama, SHA-2 (SHA-256, SHA-384, and SHA-512), - and XTR-DH - - added a faster variant of Rabin's Information Dispersal Algorithm (IDA) - - added class wrappers for these operating system features: - - high resolution timers on Windows, Unix, and MacOS - - Berkeley and Windows style sockets - - Windows named pipes - - /dev/random and /dev/urandom on Linux and FreeBSD - - Microsoft's CryptGenRandom on Windows - - added support for SEC 1 elliptic curve key format and compressed points - - added support for X.509 public key format (subjectPublicKeyInfo) for - RSA, DSA, and elliptic curve schemes - - added support for DER and OpenPGP signature format for DSA - - added support for ZLIB compressed data format (RFC 1950) - - changed elliptic curve encryption to use ECIES (as defined in SEC 1) - - changed MARS key schedule to reflect the latest specification - - changed BufferedTransformation interface to support multiple channels - and messages - - changed CAST and SHA-1 implementations to use public domain source code - - fixed bug in StringSource - - optmized multi-precision integer code for better performance - -4.1 - added more support for the recommended elliptic curve parameters in SEC 2 - - added Panama MAC, MARC4 - - added IV stealing feature to CTS mode - - added support for PKCS #8 private key format for RSA, DSA, and elliptic - curve schemes - - changed Deflate, MD5, Rijndael, and Twofish to use public domain code - - fixed a bug with flushing compressed streams - - fixed a bug with decompressing stored blocks - - fixed a bug with EC point decompression using non-trinomial basis - - fixed a bug in NetworkSource::GeneralPump() - - fixed a performance issue with EC over GF(p) decryption - - fixed syntax to allow GCC to compile without -fpermissive - - relaxed some restrictions in the license - -4.2 - added support for longer HMAC keys - - added MD4 (which is not secure so use for compatibility purposes only) - - added compatibility fixes/workarounds for STLport 4.5, GCC 3.0.2, - and MSVC 7.0 - - changed MD2 to use public domain code - - fixed a bug with decompressing multiple messages with the same object - - fixed a bug in CBC-MAC with MACing multiple messages with the same object - - fixed a bug in RC5 and RC6 with zero-length keys - - fixed a bug in Adler32 where incorrect checksum may be generated - -5.0 - added ESIGN, DLIES, WAKE-OFB, PBKDF1 and PBKDF2 from PKCS #5 - - added key validation for encryption and signature public/private keys - - renamed StreamCipher interface to SymmetricCipher, which is now implemented - by both stream ciphers and block cipher modes including ECB and CBC - - added keying interfaces to support resetting of keys and IVs without - having to destroy and recreate objects - - changed filter interface to support non-blocking input/output - - changed SocketSource and SocketSink to use overlapped I/O on Microsoft Windows - - grouped related classes inside structs to help templates, for example - AESEncryption and AESDecryption are now AES::Encryption and AES::Decryption - - where possible, typedefs have been added to improve backwards - compatibility when the CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY macro is defined - - changed Serpent, HAVAL and IDEA to use public domain code - - implemented SSE2 optimizations for Integer operations - - fixed a bug in HMAC::TruncatedFinal() - - fixed SKIPJACK byte ordering following NIST clarification dated 5/9/02 - -5.01 - added known answer test for X9.17 RNG in FIPS 140 power-up self test - - submitted to NIST/CSE, but not publicly released - -5.02 - changed EDC test to MAC integrity check using HMAC/SHA1 - - improved performance of integrity check - - added blinding to defend against RSA timing attack - -5.03 - created DLL version of Crypto++ for FIPS 140-2 validation - - fixed vulnerabilities in GetNextIV for CTR and OFB modes - -5.0.4 - Removed DES, SHA-256, SHA-384, SHA-512 from DLL - -5.1 - added PSS padding and changed PSSR to track IEEE P1363a draft standard - - added blinding for RSA and Rabin to defend against timing attacks - on decryption operations - - changed signing and decryption APIs to support the above - - changed WaitObjectContainer to allow waiting for more than 64 - objects at a time on Win32 platforms - - fixed a bug in CBC and ECB modes with processing non-aligned data - - fixed standard conformance bugs in DLIES (DHAES mode) and RW/EMSA2 - signature scheme (these fixes are not backwards compatible) - - fixed a number of compiler warnings, minor bugs, and portability problems - - removed Sapphire - -5.2 - merged in changes for 5.01 - 5.0.4 - - added support for using encoding parameters and key derivation parameters - with public key encryption (implemented by OAEP and DL/ECIES) - - added Camellia, SHACAL-2, Two-Track-MAC, Whirlpool, RIPEMD-320, - RIPEMD-128, RIPEMD-256, Base-32 coding, FIPS variant of CFB mode - - added ThreadUserTimer for timing thread CPU usage - - added option for password-based key derivation functions - to iterate until a mimimum elapsed thread CPU time is reached - - added option (on by default) for DEFLATE compression to detect - uncompressible files and process them more quickly - - improved compatibility and performance on 64-bit platforms, - including Alpha, IA-64, x86-64, PPC64, Sparc64, and MIPS64 - - fixed ONE_AND_ZEROS_PADDING to use 0x80 instead 0x01 as padding. - - fixed encoding/decoding of PKCS #8 privateKeyInfo to properly - handle optional attributes - -5.2.1 - fixed bug in the "dlltest" DLL testing program - - fixed compiling with STLport using VC .NET - - fixed compiling with -fPIC using GCC - - fixed compiling with -msse2 on systems without memalign() - - fixed inability to instantiate PanamaMAC - - fixed problems with inline documentation - -5.2.2 - added SHA-224 - - put SHA-256, SHA-384, SHA-512, RSASSA-PSS into DLL - -5.2.3 - fixed issues with FIPS algorithm test vectors - - put RSASSA-ISO into DLL - -5.3 - ported to MSVC 2005 with support for x86-64 - - added defense against AES timing attacks, and more AES test vectors - - changed StaticAlgorithmName() of Rijndael to "AES", CTR to "CTR" - -5.4 - added Salsa20 - - updated Whirlpool to version 3.0 - - ported to GCC 4.1, Sun C++ 5.8, and Borland C++Builder 2006 - -5.5 - added VMAC and Sosemanuk (with x86-64 and SSE2 assembly) - - improved speed of integer arithmetic, AES, SHA-512, Tiger, Salsa20, - Whirlpool, and PANAMA cipher using assembly (x86-64, MMX, SSE2) - - optimized Camellia and added defense against timing attacks - - updated benchmarks code to show cycles per byte and to time key/IV setup - - started using OpenMP for increased multi-core speed - - enabled GCC optimization flags by default in GNUmakefile - - added blinding and computational error checking for RW signing - - changed RandomPool, X917RNG, GetNextIV, DSA/NR/ECDSA/ECNR to reduce - the risk of reusing random numbers and IVs after virtual machine state - rollback - - changed default FIPS mode RNG from AutoSeededX917RNG to - AutoSeededX917RNG - - fixed PANAMA cipher interface to accept 256-bit key and 256-bit IV - - moved MD2, MD4, MD5, PanamaHash, ARC4, WAKE_CFB into the namespace "Weak" - - removed HAVAL, MD5-MAC, XMAC - -5.5.1 - fixed VMAC validation failure on 32-bit big-endian machines - -5.5.2 - ported x64 assembly language code for AES, Salsa20, Sosemanuk, and Panama - to MSVC 2005 (using MASM since MSVC doesn't support inline assembly on x64) - - fixed Salsa20 initialization crash on non-SSE2 machines - - fixed Whirlpool crash on Pentium 2 machines - - fixed possible branch prediction analysis (BPA) vulnerability in - MontgomeryReduce(), which may affect security of RSA, RW, LUC - - fixed link error with MSVC 2003 when using "debug DLL" form of runtime library - - fixed crash in SSE2_Add on P4 machines when compiled with - MSVC 6.0 SP5 with Processor Pack - - ported to MSVC 2008, GCC 4.2, Sun CC 5.9, Intel C++ Compiler 10.0, - and Borland C++Builder 2007 - -5.6 - added AuthenticatedSymmetricCipher interface class and Filter wrappers - - added CCM, GCM (with SSE2 assembly), EAX, CMAC, XSalsa20, and SEED - - added support for variable length IVs - - improved AES and SHA-256 speed on x86 and x64 - - fixed incorrect VMAC computation on message lengths - that are >64 mod 128 (x86 assembly version is not affected) - - fixed compiler error in vmac.cpp on x86 with GCC -fPIC - - fixed run-time validation error on x86-64 with GCC 4.3.2 -O2 - - fixed HashFilter bug when putMessage=true - - removed WORD64_AVAILABLE; compiler support for 64-bit int is now required - - ported to GCC 4.3, C++Builder 2009, Sun CC 5.10, Intel C++ Compiler 11 - -Written by Wei Dai diff --git a/embeddedcryptopp/TestVectors/Readme.txt b/embeddedcryptopp/TestVectors/Readme.txt deleted file mode 100644 index 755a046..0000000 --- a/embeddedcryptopp/TestVectors/Readme.txt +++ /dev/null @@ -1,72 +0,0 @@ -Test Data Format - -A test data file is an ASCII text file composed of sections separated by -blank lines. Each section is stand-alone and independent of other -sections that may be in the same file, and contains one or more tests. - -A section is composed of a sequence of fields. Each field is one or more -lines composed of a field name, followed by a colon (":"), followed by a -field body. All but the last line of a field must end with a backslash -("\"). If any line contains a hash mark ("#"), the hash mark and -everything after it on the same line is not considered part of the field -body. - -Each section must contain fields named AlgorithmType, Name, Source, and -Test. The presence and semantics of other fields depend on the algorithm -being tested and the tests to be run. - -Each section may contain more than one test and therefore more than one -field named Test. In that case the order of the fields is significant. A -test should always use the last field with any given name that occurs -before the Test field. - -Data Types - -int - small integer (less than 2^32) in decimal representation -string - human readable string -encoded string - can be one of the following - - quoted string: "message" means "message" without the quotes - or terminating '\0' - - hex encoded string: 0x74657374 or 74657374 means "test" - - repeated string: r100 "message" to repeat "message" 100 times, or - r256 0x0011 to repeat 0x0011 256 times - -Field Types - -AlgorithmType - string, for example "Signature", "AsymmetricCipher", -"SymmetricCipher", "MAC", "MessageDigest", or "KeyFactory" -Name - string, an algorithm name from SCAN -Test - string, identifies the test to run -Source - string, text explaining where the test data came from -Comment - string, other comments about the test data -KeyFormat - string, specifies the key format. "Component" here means -each component of the key or key pair is specified separately as a name, -value pair, with the names depending on the algorithm being tested. -Otherwise the value names "Key", or "PublicKey" and "PrivateKey" are -used. -Key - encoded string -PublicKey - encoded string -PrivateKey - encoded string -Message - encoded string, message to be signed or verified -Signature - encoded string, signature to be verified or compared -with -Plaintext - encoded string -Ciphertext - encoded string -Digest - encoded string -TruncatedSize - int, size of truncated digest in bytes -Seek - int, seek location for random access ciphers -(more to come here) - -Possible Tests - -KeyPairValidAndConsistent - public and private keys are both valid and -consistent with each other -PublicKeyInvalid - public key validation should not pass -PrivateKeyInvalid - private key validation should not pass -Verify - signature/digest/MAC verification should pass -VerifyTruncated - truncated digest/MAC verification should pass -NotVerify - signature/digest/MAC verification should not pass -DeterministicSign - sign message using given seed, and the resulting -signature should be equal to the given signature -DecryptMatch - ciphertext decrypts to plaintext -(more to come here) diff --git a/embeddedcryptopp/TestVectors/aes.txt b/embeddedcryptopp/TestVectors/aes.txt deleted file mode 100644 index 0012629..0000000 --- a/embeddedcryptopp/TestVectors/aes.txt +++ /dev/null @@ -1,189 +0,0 @@ -AlgorithmType: SymmetricCipher -Name: AES/ECB -Source: NIST Special Publication 800-38A -Plaintext: 6bc1bee22e409f96e93d7e117393172a ae2d8a571e03ac9c9eb76fac45af8e51 30c81c46a35ce411e5fbc1191a0a52ef f69f2445df4f9b17ad2b417be66c3710 -Comment: F.1.1 ECB-AES128.Encrypt -Key: 2b7e151628aed2a6abf7158809cf4f3c -Ciphertext: 3ad77bb40d7a3660a89ecaf32466ef97 f5d3d58503b9699de785895a96fdbaaf 43b1cd7f598ece23881b00e3ed030688 7b0c785e27e8ad3f8223207104725dd4 -Test: Encrypt -Comment: F.1.3 ECB-AES192.Encrypt -Key: 8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b -Ciphertext: bd334f1d6e45f25ff712a214571fa5cc 974104846d0ad3ad7734ecb3ecee4eef ef7afd2270e2e60adce0ba2face6444e 9a4b41ba738d6c72fb16691603c18e0e -Test: Encrypt -Comment: F.1.5 ECB-AES256.Encrypt -Key: 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4 -Ciphertext: f3eed1bdb5d2a03c064b5a7e3db181f8 591ccb10d410ed26dc5ba74a31362870 b6ed21b99ca6f4f9f153e7b1beafed1d 23304b7a39f9f3ff067d8d8f9e24ecc7 -Test: Encrypt - -AlgorithmType: SymmetricCipher -Name: AES/CBC -Source: NIST Special Publication 800-38A -IV: 000102030405060708090a0b0c0d0e0f -Plaintext: 6bc1bee22e409f96e93d7e117393172a ae2d8a571e03ac9c9eb76fac45af8e51 30c81c46a35ce411e5fbc1191a0a52ef f69f2445df4f9b17ad2b417be66c3710 -Comment: F.2.1 CBC-AES128.Encrypt -Key: 2b7e151628aed2a6abf7158809cf4f3c -Ciphertext: 7649abac8119b246cee98e9b12e9197d 5086cb9b507219ee95db113a917678b2 73bed6b8e3c1743b7116e69e22229516 3ff1caa1681fac09120eca307586e1a7 -Test: Encrypt -Comment: F.2.3 CBC-AES192.Encrypt -Key: 8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b -Ciphertext: 4f021db243bc633d7178183a9fa071e8 b4d9ada9ad7dedf4e5e738763f69145a 571b242012fb7ae07fa9baac3df102e0 08b0e27988598881d920a9e64f5615cd -Test: Encrypt -Comment: F.2.5 CBC-AES256.Encrypt -Key: 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4 -Ciphertext: f58c4c04d6e5f1ba779eabfb5f7bfbd6 9cfc4e967edb808d679f777bc6702c7d 39f23369a9d9bacfa530e26304231461 b2eb05e2c39be9fcda6c19078c6a9d1b -Test: Encrypt - -AlgorithmType: SymmetricCipher -Name: AES/CBC -Source: RFC 3602 -Comment: Case 1: Encrypting 16 bytes (1 block) using AES-CBC with 128-bit key -Key : 0x06a9214036b8a15b512e03d534120006 -IV : 0x3dafba429d9eb430b422da802c9fac41 -Plaintext : "Single block msg" -Ciphertext: 0xe353779c1079aeb82708942dbe77181a -Test: Encrypt -Comment: Case 2: Encrypting 32 bytes (2 blocks) using AES-CBC with 128-bit key -Key : 0xc286696d887c9aa0611bbb3e2025a45a -IV : 0x562e17996d093d28ddb3ba695a2e6f58 -Plaintext : 0x000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f -Ciphertext: 0xd296cd94c2cccf8a3a863028b5e1dc0a 7586602d253cfff91b8266bea6d61ab1 -Test: Encrypt -Comment: Case 3: Encrypting 48 bytes (3 blocks) using AES-CBC with 128-bit key -Key : 0x6c3ea0477630ce21a2ce334aa746c2cd -IV : 0xc782dc4c098c66cbd9cd27d825682c81 -Plaintext : "This is a 48-byte message (exactly 3 AES blocks)" -Ciphertext: 0xd0a02b3836451753d493665d33f0e886 2dea54cdb293abc7506939276772f8d5 021c19216bad525c8579695d83ba2684 -Test: Encrypt -Comment: Case 4: Encrypting 64 bytes (4 blocks) using AES-CBC with 128-bit key -Key : 0x56e47a38c5598974bc46903dba290349 -IV : 0x8ce82eefbea0da3c44699ed7db51b7d9 -Plaintext : 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf d0d1d2d3d4d5d6d7d8d9dadbdcdddedf -Ciphertext: 0xc30e32ffedc0774e6aff6af0869f71aa 0f3af07a9a31a9c684db207eb0ef8e4e 35907aa632c3ffdf868bb7b29d3d46ad 83ce9f9a102ee99d49a53e87f4c3da55 -Test: Encrypt - -AlgorithmType: SymmetricCipher -Name: AES/CFB -Source: NIST Special Publication 800-38A -IV: 000102030405060708090a0b0c0d0e0f -Plaintext: 6bc1bee22e409f96e93d7e117393172aae2d8 -FeedbackSize: 1 -Comment: F.3.7 CFB8-AES128.Encrypt -Key: 2b7e151628aed2a6abf7158809cf4f3c -Ciphertext: 3b79424c9c0dd436bace9e0ed4586a4f32b9 -Test: Encrypt -Comment: F.3.9 CFB8-AES192.Encrypt -Key: 8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b -Ciphertext: cda2521ef0a905ca44cd057cbf0d47a0678a -Test: Encrypt -Comment: F.3.11 CFB8-AES256.Encrypt -Key: 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4 -Ciphertext: dc1f1a8520a64db55fcc8ac554844e889700 -Test: Encrypt -Plaintext: 6bc1bee22e409f96e93d7e117393172a ae2d8a571e03ac9c9eb76fac45af8e51 30c81c46a35ce411e5fbc1191a0a52ef f69f2445df4f9b17ad2b417be66c3710 -FeedbackSize: 16 -Comment: F.3.13 CFB128-AES128.Encrypt -Key: 2b7e151628aed2a6abf7158809cf4f3c -Ciphertext: 3b3fd92eb72dad20333449f8e83cfb4a c8a64537a0b3a93fcde3cdad9f1ce58b 26751f67a3cbb140b1808cf187a4f4df c04b05357c5d1c0eeac4c66f9ff7f2e6 -Test: Encrypt -Comment: F.3.15 CFB128-AES192.Encrypt -Key: 8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b -Ciphertext: cdc80d6fddf18cab34c25909c99a4174 67ce7f7f81173621961a2b70171d3d7a 2e1e8a1dd59b88b1c8e60fed1efac4c9 c05f9f9ca9834fa042ae8fba584b09ff -Test: Encrypt -Comment: F.3.17 CFB128-AES256.Encrypt -Key: 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4 -Ciphertext: dc7e84bfda79164b7ecd8486985d3860 39ffed143b28b1c832113c6331e5407b df10132415e54b92a13ed0a8267ae2f9 75a385741ab9cef82031623d55b1e471 -Test: Encrypt - -AlgorithmType: SymmetricCipher -Name: AES/OFB -Source: NIST Special Publication 800-38A -IV: 000102030405060708090a0b0c0d0e0f -Plaintext: 6bc1bee22e409f96e93d7e117393172a ae2d8a571e03ac9c9eb76fac45af8e51 30c81c46a35ce411e5fbc1191a0a52ef f69f2445df4f9b17ad2b417be66c3710 -Comment: F.4.1 OFB-AES128.Encrypt -Key: 2b7e151628aed2a6abf7158809cf4f3c -Ciphertext: 3b3fd92eb72dad20333449f8e83cfb4a 7789508d16918f03f53c52dac54ed825 9740051e9c5fecf64344f7a82260edcc 304c6528f659c77866a510d9c1d6ae5e -Test: Encrypt -Comment: F.4.3 OFB-AES192.Encrypt -Key: 8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b -Ciphertext: cdc80d6fddf18cab34c25909c99a4174 fcc28b8d4c63837c09e81700c1100401 8d9a9aeac0f6596f559c6d4daf59a5f2 6d9f200857ca6c3e9cac524bd9acc92a -Test: Encrypt -Comment: F.4.5 OFB-AES256.Encrypt -Key: 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4 -Ciphertext: dc7e84bfda79164b7ecd8486985d3860 4febdc6740d20b3ac88f6ad82a4fb08d 71ab47a086e86eedf39d1c5bba97c408 0126141d67f37be8538f5a8be740e484 -Test: Encrypt - -AlgorithmType: SymmetricCipher -Name: AES/CTR -Source: NIST Special Publication 800-38A -IV: f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff -Plaintext: 6bc1bee22e409f96e93d7e117393172a ae2d8a571e03ac9c9eb76fac45af8e51 30c81c46a35ce411e5fbc1191a0a52ef f69f2445df4f9b17ad2b417be66c3710 -Comment: F.5.1 CTR-AES128.Encrypt -Key: 2b7e151628aed2a6abf7158809cf4f3c -Ciphertext: 874d6191b620e3261bef6864990db6ce 9806f66b7970fdff8617187bb9fffdff 5ae4df3edbd5d35e5b4f09020db03eab 1e031dda2fbe03d1792170a0f3009cee -Test: Encrypt -Comment: F.5.3 CTR-AES192.Encrypt -Key: 8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b -Ciphertext: 1abc932417521ca24f2b0459fe7e6e0b 090339ec0aa6faefd5ccc2c6f4ce8e94 1e36b26bd1ebc670d1bd1d665620abf7 4f78a7f6d29809585a97daec58c6b050 -Test: Encrypt -Comment: F.5.5 CTR-AES256.Encrypt -Key: 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4 -Ciphertext: 601ec313775789a5b7a7f504bbf3d228 f443e3ca4d62b59aca84e990cacaf5c5 2b0930daa23de94ce87017ba2d84988d dfc9c58db67aada613c2dd08457941a6 -Test: Encrypt - -AlgorithmType: SymmetricCipher -Name: AES/CTR -Source: RFC 3686 -#Test Vector #1: Encrypting 16 octets using AES-CTR with 128-bit key -Key : AE 68 52 F8 12 10 67 CC 4B F7 A5 76 55 77 F3 9E -Plaintext : 53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67 -IV: 00 00 00 30 00 00 00 00 00 00 00 00 00 00 00 01 -Ciphertext : E4 09 5D 4F B7 A7 B3 79 2D 61 75 A3 26 13 11 B8 -Test: Encrypt -#Test Vector #2: Encrypting 32 octets using AES-CTR with 128-bit key -Key : 7E 24 06 78 17 FA E0 D7 43 D6 CE 1F 32 53 91 63 -Plaintext : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F -IV: 00 6C B6 DB C0 54 3B 59 DA 48 D9 0B 00 00 00 01 -Ciphertext : 51 04 A1 06 16 8A 72 D9 79 0D 41 EE 8E DA D3 88 EB 2E 1E FC 46 DA 57 C8 FC E6 30 DF 91 41 BE 28 -Test: Encrypt -#Test Vector #3: Encrypting 36 octets using AES-CTR with 128-bit key -Key : 76 91 BE 03 5E 50 20 A8 AC 6E 61 85 29 F9 A0 DC -Plaintext : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 -IV: 00 E0 01 7B 27 77 7F 3F 4A 17 86 F0 00 00 00 01 -Ciphertext : C1 CF 48 A8 9F 2F FD D9 CF 46 52 E9 EF DB 72 D7 45 40 A4 2B DE 6D 78 36 D5 9A 5C EA AE F3 10 53 25 B2 07 2F -Test: Encrypt -#Test Vector #4: Encrypting 16 octets using AES-CTR with 192-bit key -Key : 16 AF 5B 14 5F C9 F5 79 C1 75 F9 3E 3B FB 0E ED 86 3D 06 CC FD B7 85 15 -Plaintext : 53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67 -IV: 00 00 00 48 36 73 3C 14 7D 6D 93 CB 00 00 00 01 -Ciphertext : 4B 55 38 4F E2 59 C9 C8 4E 79 35 A0 03 CB E9 28 -Test: Encrypt -#Test Vector #5: Encrypting 32 octets using AES-CTR with 192-bit key -Key : 7C 5C B2 40 1B 3D C3 3C 19 E7 34 08 19 E0 F6 9C 67 8C 3D B8 E6 F6 A9 1A -Plaintext : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F -IV: 00 96 B0 3B 02 0C 6E AD C2 CB 50 0D 00 00 00 01 -Ciphertext : 45 32 43 FC 60 9B 23 32 7E DF AA FA 71 31 CD 9F 84 90 70 1C 5A D4 A7 9C FC 1F E0 FF 42 F4 FB 00 -Test: Encrypt -#Test Vector #6: Encrypting 36 octets using AES-CTR with 192-bit key -Key : 02 BF 39 1E E8 EC B1 59 B9 59 61 7B 09 65 27 9B F5 9B 60 A7 86 D3 E0 FE -Plaintext : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 -IV: 00 07 BD FD 5C BD 60 27 8D CC 09 12 00 00 00 01 -Ciphertext : 96 89 3F C5 5E 5C 72 2F 54 0B 7D D1 DD F7 E7 58 D2 88 BC 95 C6 91 65 88 45 36 C8 11 66 2F 21 88 AB EE 09 35 -Test: Encrypt -#Test Vector #7: Encrypting 16 octets using AES-CTR with 256-bit key -Key : 77 6B EF F2 85 1D B0 6F 4C 8A 05 42 C8 69 6F 6C 6A 81 AF 1E EC 96 B4 D3 7F C1 D6 89 E6 C1 C1 04 -Plaintext : 53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67 -IV: 00 00 00 60 DB 56 72 C9 7A A8 F0 B2 00 00 00 01 -Ciphertext : 14 5A D0 1D BF 82 4E C7 56 08 63 DC 71 E3 E0 C0 -Test: Encrypt -#Test Vector #8: Encrypting 32 octets using AES-CTR with 256-bit key -Key : F6 D6 6D 6B D5 2D 59 BB 07 96 36 58 79 EF F8 86 C6 6D D5 1A 5B 6A 99 74 4B 50 59 0C 87 A2 38 84 -Plaintext : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F -IV: 00 FA AC 24 C1 58 5E F1 5A 43 D8 75 00 00 00 01 -Ciphertext : F0 5E 23 1B 38 94 61 2C 49 EE 00 0B 80 4E B2 A9 B8 30 6B 50 8F 83 9D 6A 55 30 83 1D 93 44 AF 1C -Test: Encrypt -#Test Vector #9: Encrypting 36 octets using AES-CTR with 256-bit key -Key : FF 7A 61 7C E6 91 48 E4 F1 72 6E 2F 43 58 1D E2 AA 62 D9 F8 05 53 2E DF F1 EE D6 87 FB 54 15 3D -Plaintext : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 -IV: 00 1C C5 B7 51 A5 1D 70 A1 C1 11 48 00 00 00 01 -Ciphertext : EB 6C 52 82 1D 0B BB F7 CE 75 94 46 2A CA 4F AA B4 07 DF 86 65 69 FD 07 F4 8C C0 B5 83 D6 07 1F 1E C0 E6 B8 -Test: Encrypt diff --git a/embeddedcryptopp/TestVectors/all.txt b/embeddedcryptopp/TestVectors/all.txt deleted file mode 100644 index 3f06e78..0000000 --- a/embeddedcryptopp/TestVectors/all.txt +++ /dev/null @@ -1,29 +0,0 @@ -AlgorithmType: FileList -Name: all.txt collection -Test: TestVectors/tea.txt -Test: TestVectors/camellia.txt -Test: TestVectors/shacal2.txt -Test: TestVectors/ttmac.txt -Test: TestVectors/whrlpool.txt -Test: TestVectors/dlies.txt -Test: TestVectors/dsa.txt -Test: TestVectors/dsa_1363.txt -Test: TestVectors/esign.txt -Test: TestVectors/hmac.txt -Test: TestVectors/nr.txt -Test: TestVectors/rsa_oaep.txt -Test: TestVectors/rsa_pkcs1_1_5.txt -Test: TestVectors/rsa_pss.txt -Test: TestVectors/rw.txt -Test: TestVectors/seal.txt -Test: TestVectors/sha.txt -Test: TestVectors/panama.txt -Test: TestVectors/aes.txt -Test: TestVectors/salsa.txt -Test: TestVectors/vmac.txt -Test: TestVectors/sosemanuk.txt -Test: TestVectors/ccm.txt -Test: TestVectors/gcm.txt -Test: TestVectors/cmac.txt -Test: TestVectors/eax.txt -Test: TestVectors/mars.txt diff --git a/embeddedcryptopp/TestVectors/camellia.txt b/embeddedcryptopp/TestVectors/camellia.txt deleted file mode 100644 index f88d05b..0000000 --- a/embeddedcryptopp/TestVectors/camellia.txt +++ /dev/null @@ -1,8646 +0,0 @@ -AlgorithmType: SymmetricCipher -Name: Camellia/ECB -Source: NESSIE submission -Comment: Tests with 128-bit keys -Comment: Set 1, vector 0 -Key: 80000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 6C227F749319A3AA7DA235A9BBA05A2C -Test: Encrypt -Comment: Set 1, vector 1 -Key: 40000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F04D51E45E70FB6DEE0D16A204FBBA16 -Test: Encrypt -Comment: Set 1, vector 2 -Key: 20000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: ED44242E619F8C32EAA2D3641DA47EA4 -Test: Encrypt -Comment: Set 1, vector 3 -Key: 10000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: AC640BBBF84CD3B8E8258BF66C210AE2 -Test: Encrypt -Comment: Set 1, vector 4 -Key: 08000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 8A42BDA76C84B8960B23530100AFB748 -Test: Encrypt -Comment: Set 1, vector 5 -Key: 04000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 1D20D15F3EE21EE6051803ADF83E31D7 -Test: Encrypt -Comment: Set 1, vector 6 -Key: 02000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 6896B2FB85D26A243BB5697F6A764307 -Test: Encrypt -Comment: Set 1, vector 7 -Key: 01000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 43A865A61E1117008372932EA9CE8BB2 -Test: Encrypt -Comment: Set 1, vector 8 -Key: 00800000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: CB5ECC200DDE8E9076A8AEA2250F49E4 -Test: Encrypt -Comment: Set 1, vector 9 -Key: 00400000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0B2A489718DC0B0E11F11C1D3913F4A8 -Test: Encrypt -Comment: Set 1, vector 10 -Key: 00200000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 1D28A0A70B3C72ADC5B77487AD442873 -Test: Encrypt -Comment: Set 1, vector 11 -Key: 00100000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 26D344959095765A3DD6986B656F353D -Test: Encrypt -Comment: Set 1, vector 12 -Key: 00080000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 048248D32A74DB80DAF5642417F7832A -Test: Encrypt -Comment: Set 1, vector 13 -Key: 00040000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 44D400F8752F16B20DB95A959917B650 -Test: Encrypt -Comment: Set 1, vector 14 -Key: 00020000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E885DD9B2794459B2133BC84B59C2DED -Test: Encrypt -Comment: Set 1, vector 15 -Key: 00010000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 89D6E4182FD0DD7E4038710F597DD242 -Test: Encrypt -Comment: Set 1, vector 16 -Key: 00008000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7FE5BA5FF1D0EB81132A3DA0CD8E829D -Test: Encrypt -Comment: Set 1, vector 17 -Key: 00004000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 470FEDAAA6FFFCBC48AF8B3859B1E45F -Test: Encrypt -Comment: Set 1, vector 18 -Key: 00002000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B6FA2D9F41110E6914890AF888C36091 -Test: Encrypt -Comment: Set 1, vector 19 -Key: 00001000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 46D2C0FD0C3A4D2B5CA6BA5E14382DCA -Test: Encrypt -Comment: Set 1, vector 20 -Key: 00000800000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 730D700DCC5AB632DD9D92C6D1C18E5A -Test: Encrypt -Comment: Set 1, vector 21 -Key: 00000400000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 067D56D80AF5D2F24D84F518B8FC7920 -Test: Encrypt -Comment: Set 1, vector 22 -Key: 00000200000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 027F6EE9F54534E4C21F9263B68BAEA0 -Test: Encrypt -Comment: Set 1, vector 23 -Key: 00000100000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: D115CB2324E8FDA3576DEE57E49CC315 -Test: Encrypt -Comment: Set 1, vector 24 -Key: 00000080000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0976DB57B27E4136743E58BCECFBC056 -Test: Encrypt -Comment: Set 1, vector 25 -Key: 00000040000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0C889DF89972EB42DB2BD2AAC335CCC8 -Test: Encrypt -Comment: Set 1, vector 26 -Key: 00000020000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: CB6B80177047A3B2AC290A41B94174EF -Test: Encrypt -Comment: Set 1, vector 27 -Key: 00000010000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F816631F8FBC54ECDC1AB5323FF8424E -Test: Encrypt -Comment: Set 1, vector 28 -Key: 00000008000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 40CB64DF57D2A6BBCBD82DFCC749707D -Test: Encrypt -Comment: Set 1, vector 29 -Key: 00000004000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 885BD3C2DD560765B11F5A2D238E9F9A -Test: Encrypt -Comment: Set 1, vector 30 -Key: 00000002000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 877AAEF064555DE89C99B7C5A1326C62 -Test: Encrypt -Comment: Set 1, vector 31 -Key: 00000001000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: AA4FBBE7A02020F5D81030E0EF7A460D -Test: Encrypt -Comment: Set 1, vector 32 -Key: 00000000800000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: AA2759BC215E49F26008206F6F65B7AC -Test: Encrypt -Comment: Set 1, vector 33 -Key: 00000000400000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 419A8069C3D531475FF7F29AE049D57C -Test: Encrypt -Comment: Set 1, vector 34 -Key: 00000000200000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 455588067DB9088130C861F5BE9E15BF -Test: Encrypt -Comment: Set 1, vector 35 -Key: 00000000100000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: FDD6967ADA65ED3E20718C451AE5AE34 -Test: Encrypt -Comment: Set 1, vector 36 -Key: 00000000080000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 1C74228D2A82248CD29800B64BEFF97A -Test: Encrypt -Comment: Set 1, vector 37 -Key: 00000000040000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 4B88B7FFB32B05840BE7B497377AFDAA -Test: Encrypt -Comment: Set 1, vector 38 -Key: 00000000020000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 4D4EC4C728524DA2F366FC272AB2666A -Test: Encrypt -Comment: Set 1, vector 39 -Key: 00000000010000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 4FA8A27ED16BF36FA296D8AB2B423C77 -Test: Encrypt -Comment: Set 1, vector 40 -Key: 00000000008000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 943B9D570D371A3D823B680BBDA9477D -Test: Encrypt -Comment: Set 1, vector 41 -Key: 00000000004000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: DCC390F5E1CAADBE061D02929473D084 -Test: Encrypt -Comment: Set 1, vector 42 -Key: 00000000002000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 9655F00C4A5C40DF401A3FF806575834 -Test: Encrypt -Comment: Set 1, vector 43 -Key: 00000000001000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: FCC9F6B36DE6DD6AA578AD0B59DF5996 -Test: Encrypt -Comment: Set 1, vector 44 -Key: 00000000000800000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F573FF52ACAA16609E5B3C3C7353DA75 -Test: Encrypt -Comment: Set 1, vector 45 -Key: 00000000000400000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 203EF49006A7FC856FF7A7A3B953D999 -Test: Encrypt -Comment: Set 1, vector 46 -Key: 00000000000200000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 16659E823D942E99C83926C4055D896D -Test: Encrypt -Comment: Set 1, vector 47 -Key: 00000000000100000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 139D5DB9EF0119F4E5D11256C5ECB8B0 -Test: Encrypt -Comment: Set 1, vector 48 -Key: 00000000000080000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 63FB244962CCE915425EF1B31DE6AAE2 -Test: Encrypt -Comment: Set 1, vector 49 -Key: 00000000000040000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 6F771C2DC848A106E907A990DABA0272 -Test: Encrypt -Comment: Set 1, vector 50 -Key: 00000000000020000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: CFA1F114CF0D9C7DAD301B833962ABF2 -Test: Encrypt -Comment: Set 1, vector 51 -Key: 00000000000010000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 58A3BE61DA53D0AA8F33DE95E6F38A3F -Test: Encrypt -Comment: Set 1, vector 52 -Key: 00000000000008000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 2FE96FCB3D845B568AE804B217F3498F -Test: Encrypt -Comment: Set 1, vector 53 -Key: 00000000000004000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: FD74EB6621127D58FA44BA3E6EE7835D -Test: Encrypt -Comment: Set 1, vector 54 -Key: 00000000000002000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 834C0C5D8D88EE63C989AA1E66F4E18C -Test: Encrypt -Comment: Set 1, vector 55 -Key: 00000000000001000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: FEF8E0097B9EB5CE6DE710F5742F7E4F -Test: Encrypt -Comment: Set 1, vector 56 -Key: 00000000000000800000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 75FCC55F284311B81D967618C2D35700 -Test: Encrypt -Comment: Set 1, vector 57 -Key: 00000000000000400000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 91AE4E35623A7F10383BF7448F1F74AD -Test: Encrypt -Comment: Set 1, vector 58 -Key: 00000000000000200000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 8928B2B6967BA1B4230AA1EBA49D1A08 -Test: Encrypt -Comment: Set 1, vector 59 -Key: 00000000000000100000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 707EA08174ED5C0AD0A74363B403F02D -Test: Encrypt -Comment: Set 1, vector 60 -Key: 00000000000000080000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7C0C13410DDE30C0AD3565FFAA33E8AD -Test: Encrypt -Comment: Set 1, vector 61 -Key: 00000000000000040000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 56DA72C545C490A749C66BCC5D90AACD -Test: Encrypt -Comment: Set 1, vector 62 -Key: 00000000000000020000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 2CC0CF6E2AAA7916AF636B1546BA1179 -Test: Encrypt -Comment: Set 1, vector 63 -Key: 00000000000000010000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: A19FE617883D409B1F78882E0D5EF39C -Test: Encrypt -Comment: Set 1, vector 64 -Key: 00000000000000008000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 2B8586BBB979CFFAC5A76C25D77C1E2C -Test: Encrypt -Comment: Set 1, vector 65 -Key: 00000000000000004000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 5A08C9B5A2940E3ACD1086867E3E4733 -Test: Encrypt -Comment: Set 1, vector 66 -Key: 00000000000000002000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7443F1072833BFC8AA38CBF6963CF880 -Test: Encrypt -Comment: Set 1, vector 67 -Key: 00000000000000001000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 6809A1F2D2B5367D5E8442E7972BD1D4 -Test: Encrypt -Comment: Set 1, vector 68 -Key: 00000000000000000800000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: A61D4FE41D5DBB7A6BCE5984502CD767 -Test: Encrypt -Comment: Set 1, vector 69 -Key: 00000000000000000400000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 30D86F43B81F4D2098A4D43AB2637549 -Test: Encrypt -Comment: Set 1, vector 70 -Key: 00000000000000000200000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 5B16E9033FA40BF141D3EE73FF7E2564 -Test: Encrypt -Comment: Set 1, vector 71 -Key: 00000000000000000100000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 15574EF70C880682DBFBD93FAE8023F6 -Test: Encrypt -Comment: Set 1, vector 72 -Key: 00000000000000000080000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0D8D220DB69B15FFE2001B3F42E910EA -Test: Encrypt -Comment: Set 1, vector 73 -Key: 00000000000000000040000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 030AB24DA9E4ADD4E350E692077A948C -Test: Encrypt -Comment: Set 1, vector 74 -Key: 00000000000000000020000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7F6509A9FD8525126BFB69AFE8624A96 -Test: Encrypt -Comment: Set 1, vector 75 -Key: 00000000000000000010000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 9600EB0B7E38A5ABEBBDADD3DFC70298 -Test: Encrypt -Comment: Set 1, vector 76 -Key: 00000000000000000008000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3CF0F71B4687AAABEB9FA8CDE00B17D7 -Test: Encrypt -Comment: Set 1, vector 77 -Key: 00000000000000000004000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 8B1C549A655C0041D866B7875A2736CB -Test: Encrypt -Comment: Set 1, vector 78 -Key: 00000000000000000002000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 8F507233FBC9E1DBF716FB4C828DBF06 -Test: Encrypt -Comment: Set 1, vector 79 -Key: 00000000000000000001000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 14A45A121DC8996020C29A040FE8E52D -Test: Encrypt -Comment: Set 1, vector 80 -Key: 00000000000000000000800000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 32390FB6FC15BB4B37D1CD8817BAEB09 -Test: Encrypt -Comment: Set 1, vector 81 -Key: 00000000000000000000400000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 9E61986F3F4C31132D436CCFCF751043 -Test: Encrypt -Comment: Set 1, vector 82 -Key: 00000000000000000000200000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 24E63FAD370974C60330F7C3071938F1 -Test: Encrypt -Comment: Set 1, vector 83 -Key: 00000000000000000000100000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3CE71D4E9F2F7EF9A6F9F2548C5489CC -Test: Encrypt -Comment: Set 1, vector 84 -Key: 00000000000000000000080000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E42436B8E076A00600DFD67B8C427DB1 -Test: Encrypt -Comment: Set 1, vector 85 -Key: 00000000000000000000040000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 5C2577FA8104DCC58ACE852B4D11FE24 -Test: Encrypt -Comment: Set 1, vector 86 -Key: 00000000000000000000020000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 12FC9DD7132B3BB346C53FD193531638 -Test: Encrypt -Comment: Set 1, vector 87 -Key: 00000000000000000000010000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 5D91F775E26599F26B21F9FB1F67DA38 -Test: Encrypt -Comment: Set 1, vector 88 -Key: 00000000000000000000008000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: D4B3683AA62D2EF0331A960A0BF01A29 -Test: Encrypt -Comment: Set 1, vector 89 -Key: 00000000000000000000004000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: EE32582D35DDF3A82142ED18FEE38014 -Test: Encrypt -Comment: Set 1, vector 90 -Key: 00000000000000000000002000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 148632AE69514D5776DA4AF38E1AE4FD -Test: Encrypt -Comment: Set 1, vector 91 -Key: 00000000000000000000001000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 30A3EE1AA1CA17B128DAAF06AF9025BD -Test: Encrypt -Comment: Set 1, vector 92 -Key: 00000000000000000000000800000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 88D82D9E508CBFB392E47E524BB33019 -Test: Encrypt -Comment: Set 1, vector 93 -Key: 00000000000000000000000400000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0C20870A9FC751F6E41F92305B7C4D92 -Test: Encrypt -Comment: Set 1, vector 94 -Key: 00000000000000000000000200000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 6A4EDE5FD13F3676C1BCF8B73AB273CB -Test: Encrypt -Comment: Set 1, vector 95 -Key: 00000000000000000000000100000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 5A62CE50EA837CA4FD0F7304D1572D22 -Test: Encrypt -Comment: Set 1, vector 96 -Key: 00000000000000000000000080000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 84DB8599B48ED4F39E872F13F7FCDF0B -Test: Encrypt -Comment: Set 1, vector 97 -Key: 00000000000000000000000040000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: CDD25F8276411E892035C9703C7588EE -Test: Encrypt -Comment: Set 1, vector 98 -Key: 00000000000000000000000020000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 73BCFB16436B5C52CD4BC9629F75C5C8 -Test: Encrypt -Comment: Set 1, vector 99 -Key: 00000000000000000000000010000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 03752D935029B09699C29CA5C6E79553 -Test: Encrypt -Comment: Set 1, vector 100 -Key: 00000000000000000000000008000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: EF439A1B86698409E91D992BDB3F54E5 -Test: Encrypt -Comment: Set 1, vector 101 -Key: 00000000000000000000000004000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 2A34BDE7EC74221BFF58B251E54F089F -Test: Encrypt -Comment: Set 1, vector 102 -Key: 00000000000000000000000002000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 35FBB78716B78FB57F96BC8A5D869B72 -Test: Encrypt -Comment: Set 1, vector 103 -Key: 00000000000000000000000001000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: AC3A7363DFB6C3F06CCCA1A46F44A5F8 -Test: Encrypt -Comment: Set 1, vector 104 -Key: 00000000000000000000000000800000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 4895E1B7E54CA168CE42E3994D564B62 -Test: Encrypt -Comment: Set 1, vector 105 -Key: 00000000000000000000000000400000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E98956EFC457FE8AA103DB303A3B1DF1 -Test: Encrypt -Comment: Set 1, vector 106 -Key: 00000000000000000000000000200000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 276646992D6E752A649183DB05073422 -Test: Encrypt -Comment: Set 1, vector 107 -Key: 00000000000000000000000000100000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 82F36DE401E21D01A476A163A92F4B16 -Test: Encrypt -Comment: Set 1, vector 108 -Key: 00000000000000000000000000080000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E54DD90800B92153C314F8B1590B17E5 -Test: Encrypt -Comment: Set 1, vector 109 -Key: 00000000000000000000000000040000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F4A146DFB33405EC6B8F37AEB10F5198 -Test: Encrypt -Comment: Set 1, vector 110 -Key: 00000000000000000000000000020000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: C332ADBC2D44FA1A1A4F7C8EAE2CED29 -Test: Encrypt -Comment: Set 1, vector 111 -Key: 00000000000000000000000000010000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 21AA542624DA9F2363404CE42BC2BAEF -Test: Encrypt -Comment: Set 1, vector 112 -Key: 00000000000000000000000000008000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E101DBEF627038AE819441D133AEE068 -Test: Encrypt -Comment: Set 1, vector 113 -Key: 00000000000000000000000000004000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7A9B635E6AA5D273DE697747FE6BB08E -Test: Encrypt -Comment: Set 1, vector 114 -Key: 00000000000000000000000000002000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0541AA347D36F03D9177FC91398874DB -Test: Encrypt -Comment: Set 1, vector 115 -Key: 00000000000000000000000000001000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: BE27D6FE099AB98BF07A74A1ABF5C945 -Test: Encrypt -Comment: Set 1, vector 116 -Key: 00000000000000000000000000000800 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 472ACD81A6626822E220F431C4491704 -Test: Encrypt -Comment: Set 1, vector 117 -Key: 00000000000000000000000000000400 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 2D5152F19E29AD7D5823CDCA188E0CD8 -Test: Encrypt -Comment: Set 1, vector 118 -Key: 00000000000000000000000000000200 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 875C90B3669DF8F4867B6769689656E7 -Test: Encrypt -Comment: Set 1, vector 119 -Key: 00000000000000000000000000000100 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 59641CA52EEBC2C229930CE42529277F -Test: Encrypt -Comment: Set 1, vector 120 -Key: 00000000000000000000000000000080 -Plaintext: 00000000000000000000000000000000 -Ciphertext: A3B4D666AC56C284D40DC27FDB0F787C -Test: Encrypt -Comment: Set 1, vector 121 -Key: 00000000000000000000000000000040 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0511D526FC5F255F51F1914B4B12AD84 -Test: Encrypt -Comment: Set 1, vector 122 -Key: 00000000000000000000000000000020 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 2D14332989F629DA4720ECC916B4DAF0 -Test: Encrypt -Comment: Set 1, vector 123 -Key: 00000000000000000000000000000010 -Plaintext: 00000000000000000000000000000000 -Ciphertext: C44EAC8457E2F17E9BC86EB4C436E8DB -Test: Encrypt -Comment: Set 1, vector 124 -Key: 00000000000000000000000000000008 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 022F3EB45AAA39F785FF80B6A3006BF6 -Test: Encrypt -Comment: Set 1, vector 125 -Key: 00000000000000000000000000000004 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B8A714C8F8427767B384B0E2F6BAF619 -Test: Encrypt -Comment: Set 1, vector 126 -Key: 00000000000000000000000000000002 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 01F745A7C09FECD3497F087BD52A9A0F -Test: Encrypt -Comment: Set 1, vector 127 -Key: 00000000000000000000000000000001 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 41E0E6DC2DDEC65D8B8120E60977B82D -Test: Encrypt -Comment: Set 2, vector 0 -Key: 00000000000000000000000000000000 -Plaintext: 80000000000000000000000000000000 -Ciphertext: 07923A39EB0A817D1C4D87BDB82D1F1C -Test: Encrypt -Comment: Set 2, vector 1 -Key: 00000000000000000000000000000000 -Plaintext: 40000000000000000000000000000000 -Ciphertext: 48CD6419809672D2349260D89A08D3D3 -Test: Encrypt -Comment: Set 2, vector 2 -Key: 00000000000000000000000000000000 -Plaintext: 20000000000000000000000000000000 -Ciphertext: D07493CCB2E95CE0B4945A05ACC97D82 -Test: Encrypt -Comment: Set 2, vector 3 -Key: 00000000000000000000000000000000 -Plaintext: 10000000000000000000000000000000 -Ciphertext: 5DBE1EAC9F7080A88DBED7F6DA101448 -Test: Encrypt -Comment: Set 2, vector 4 -Key: 00000000000000000000000000000000 -Plaintext: 08000000000000000000000000000000 -Ciphertext: F01EE477D199DF2701027034B229622F -Test: Encrypt -Comment: Set 2, vector 5 -Key: 00000000000000000000000000000000 -Plaintext: 04000000000000000000000000000000 -Ciphertext: C841587ABD9A912E563774CB569D051E -Test: Encrypt -Comment: Set 2, vector 6 -Key: 00000000000000000000000000000000 -Plaintext: 02000000000000000000000000000000 -Ciphertext: 1D9BC0C04546F0915C8CCD11391A455C -Test: Encrypt -Comment: Set 2, vector 7 -Key: 00000000000000000000000000000000 -Plaintext: 01000000000000000000000000000000 -Ciphertext: 05E6EBB4BA167F5C479CEFF3152F943B -Test: Encrypt -Comment: Set 2, vector 8 -Key: 00000000000000000000000000000000 -Plaintext: 00800000000000000000000000000000 -Ciphertext: 93211E0F788845B9FC0E4551FFE92AC9 -Test: Encrypt -Comment: Set 2, vector 9 -Key: 00000000000000000000000000000000 -Plaintext: 00400000000000000000000000000000 -Ciphertext: B6D35701CD8FADDE383BBE8E6B70BAF7 -Test: Encrypt -Comment: Set 2, vector 10 -Key: 00000000000000000000000000000000 -Plaintext: 00200000000000000000000000000000 -Ciphertext: 8358F9F4EBCFEE348CB30551ACB151A0 -Test: Encrypt -Comment: Set 2, vector 11 -Key: 00000000000000000000000000000000 -Plaintext: 00100000000000000000000000000000 -Ciphertext: D57516EB5AD93C523E40521BF447AFCE -Test: Encrypt -Comment: Set 2, vector 12 -Key: 00000000000000000000000000000000 -Plaintext: 00080000000000000000000000000000 -Ciphertext: 66B2534C279C439133F52E5AD8B439A9 -Test: Encrypt -Comment: Set 2, vector 13 -Key: 00000000000000000000000000000000 -Plaintext: 00040000000000000000000000000000 -Ciphertext: A71C69184A9F63C2992A5F18F77C1FE9 -Test: Encrypt -Comment: Set 2, vector 14 -Key: 00000000000000000000000000000000 -Plaintext: 00020000000000000000000000000000 -Ciphertext: 1ADCBE49AEACB9ECEBBD492B10E82C7B -Test: Encrypt -Comment: Set 2, vector 15 -Key: 00000000000000000000000000000000 -Plaintext: 00010000000000000000000000000000 -Ciphertext: 27E3BCFB227C5561DB6CF7FC30387036 -Test: Encrypt -Comment: Set 2, vector 16 -Key: 00000000000000000000000000000000 -Plaintext: 00008000000000000000000000000000 -Ciphertext: F4AE20365CC9D06B0CAE6B695ED2CEC1 -Test: Encrypt -Comment: Set 2, vector 17 -Key: 00000000000000000000000000000000 -Plaintext: 00004000000000000000000000000000 -Ciphertext: 3DD682F0B641ED32AD3D43EA2A0456E4 -Test: Encrypt -Comment: Set 2, vector 18 -Key: 00000000000000000000000000000000 -Plaintext: 00002000000000000000000000000000 -Ciphertext: 6E5D14A95ECC290B509EA6B673652E3A -Test: Encrypt -Comment: Set 2, vector 19 -Key: 00000000000000000000000000000000 -Plaintext: 00001000000000000000000000000000 -Ciphertext: F1CDF0F8D7B3FFD95422D7CC0CF40B7B -Test: Encrypt -Comment: Set 2, vector 20 -Key: 00000000000000000000000000000000 -Plaintext: 00000800000000000000000000000000 -Ciphertext: A9253D459A34C385A1F1B2CFFA3935C5 -Test: Encrypt -Comment: Set 2, vector 21 -Key: 00000000000000000000000000000000 -Plaintext: 00000400000000000000000000000000 -Ciphertext: 291024D99FF09A47A1DEE45BA700AE52 -Test: Encrypt -Comment: Set 2, vector 22 -Key: 00000000000000000000000000000000 -Plaintext: 00000200000000000000000000000000 -Ciphertext: 49241D9459B277187BB10081C60361C0 -Test: Encrypt -Comment: Set 2, vector 23 -Key: 00000000000000000000000000000000 -Plaintext: 00000100000000000000000000000000 -Ciphertext: AD9BA365CC4DD5553D2D9FE303841D88 -Test: Encrypt -Comment: Set 2, vector 24 -Key: 00000000000000000000000000000000 -Plaintext: 00000080000000000000000000000000 -Ciphertext: C2ECA616664A249DC622CC11196B4AE1 -Test: Encrypt -Comment: Set 2, vector 25 -Key: 00000000000000000000000000000000 -Plaintext: 00000040000000000000000000000000 -Ciphertext: 6E1A2D4794BB0DC08777A0BC7523E70E -Test: Encrypt -Comment: Set 2, vector 26 -Key: 00000000000000000000000000000000 -Plaintext: 00000020000000000000000000000000 -Ciphertext: 6DB1F0CF59656BDD235E82B8CEF0BE8E -Test: Encrypt -Comment: Set 2, vector 27 -Key: 00000000000000000000000000000000 -Plaintext: 00000010000000000000000000000000 -Ciphertext: 52F239C5EAF401EBDC54D2F011FF4B6A -Test: Encrypt -Comment: Set 2, vector 28 -Key: 00000000000000000000000000000000 -Plaintext: 00000008000000000000000000000000 -Ciphertext: 6B58A08F648414B67FD6847D2AA51CBF -Test: Encrypt -Comment: Set 2, vector 29 -Key: 00000000000000000000000000000000 -Plaintext: 00000004000000000000000000000000 -Ciphertext: 2959DD5367885A75EB48053CF3251A36 -Test: Encrypt -Comment: Set 2, vector 30 -Key: 00000000000000000000000000000000 -Plaintext: 00000002000000000000000000000000 -Ciphertext: 630B292E3B88EF641CDFD531E206605E -Test: Encrypt -Comment: Set 2, vector 31 -Key: 00000000000000000000000000000000 -Plaintext: 00000001000000000000000000000000 -Ciphertext: 4BBB88EF82B70593FCC56AFD91540FDB -Test: Encrypt -Comment: Set 2, vector 32 -Key: 00000000000000000000000000000000 -Plaintext: 00000000800000000000000000000000 -Ciphertext: 0A13055B118A45C606999257BD191426 -Test: Encrypt -Comment: Set 2, vector 33 -Key: 00000000000000000000000000000000 -Plaintext: 00000000400000000000000000000000 -Ciphertext: 5CF8E5C9F15D7E4F865020224853EB77 -Test: Encrypt -Comment: Set 2, vector 34 -Key: 00000000000000000000000000000000 -Plaintext: 00000000200000000000000000000000 -Ciphertext: 3898805042C7A4315C5EE51AF2DE47E2 -Test: Encrypt -Comment: Set 2, vector 35 -Key: 00000000000000000000000000000000 -Plaintext: 00000000100000000000000000000000 -Ciphertext: 8D3F96372E87CBB0B375425B3A10B9E7 -Test: Encrypt -Comment: Set 2, vector 36 -Key: 00000000000000000000000000000000 -Plaintext: 00000000080000000000000000000000 -Ciphertext: 4D9510A378BD784A70A66BCC75B7D3C8 -Test: Encrypt -Comment: Set 2, vector 37 -Key: 00000000000000000000000000000000 -Plaintext: 00000000040000000000000000000000 -Ciphertext: 70DB1902D37CFBDFB98F7C516F79D416 -Test: Encrypt -Comment: Set 2, vector 38 -Key: 00000000000000000000000000000000 -Plaintext: 00000000020000000000000000000000 -Ciphertext: 383C6C2AABEF7FDE25CD470BF774A331 -Test: Encrypt -Comment: Set 2, vector 39 -Key: 00000000000000000000000000000000 -Plaintext: 00000000010000000000000000000000 -Ciphertext: 47CBCB5288349B1A15DC9F81FBEE6B8F -Test: Encrypt -Comment: Set 2, vector 40 -Key: 00000000000000000000000000000000 -Plaintext: 00000000008000000000000000000000 -Ciphertext: 21DA34D4468EEB13AED95DAE0FF48310 -Test: Encrypt -Comment: Set 2, vector 41 -Key: 00000000000000000000000000000000 -Plaintext: 00000000004000000000000000000000 -Ciphertext: 021C9A8E6BD36FBD036411E5D852A80F -Test: Encrypt -Comment: Set 2, vector 42 -Key: 00000000000000000000000000000000 -Plaintext: 00000000002000000000000000000000 -Ciphertext: 6A459E2F839AF60ACDE83774D0BB5574 -Test: Encrypt -Comment: Set 2, vector 43 -Key: 00000000000000000000000000000000 -Plaintext: 00000000001000000000000000000000 -Ciphertext: C19255121F1B933CAE09E58AEC0E9977 -Test: Encrypt -Comment: Set 2, vector 44 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000800000000000000000000 -Ciphertext: 7BA949E27B2BE148A6B801F9305F43D5 -Test: Encrypt -Comment: Set 2, vector 45 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000400000000000000000000 -Ciphertext: E8CEB1026BCF7BCEA32E8A380EA76DB7 -Test: Encrypt -Comment: Set 2, vector 46 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000200000000000000000000 -Ciphertext: 63F97747ED56A8F521B20CC65F6F9465 -Test: Encrypt -Comment: Set 2, vector 47 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000100000000000000000000 -Ciphertext: 2091CFDC629819106188424AC694F75B -Test: Encrypt -Comment: Set 2, vector 48 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000080000000000000000000 -Ciphertext: A91BDF8E8B88407942423CCE000527C4 -Test: Encrypt -Comment: Set 2, vector 49 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000040000000000000000000 -Ciphertext: 73F9B44B9635A3FD683DBF8D49E9825B -Test: Encrypt -Comment: Set 2, vector 50 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000020000000000000000000 -Ciphertext: 9DC64B2133FAD5069FD9A7CC2FFFD1CC -Test: Encrypt -Comment: Set 2, vector 51 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000010000000000000000000 -Ciphertext: 28240F81FEC36B71E13F1FEA7A7641E3 -Test: Encrypt -Comment: Set 2, vector 52 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000008000000000000000000 -Ciphertext: 20DD39FEE96CD2EFF972872A692B28FD -Test: Encrypt -Comment: Set 2, vector 53 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000004000000000000000000 -Ciphertext: 47A9E40483EC1925B635E47E964E8E93 -Test: Encrypt -Comment: Set 2, vector 54 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000002000000000000000000 -Ciphertext: 9C0EBD822C49FB3D853DF5B315A87BA0 -Test: Encrypt -Comment: Set 2, vector 55 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000001000000000000000000 -Ciphertext: C18D813FDB45A594C6DC24E5A1F6CE32 -Test: Encrypt -Comment: Set 2, vector 56 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000800000000000000000 -Ciphertext: 7E5467FF245ECF80CB55C2D8E91F0711 -Test: Encrypt -Comment: Set 2, vector 57 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000400000000000000000 -Ciphertext: 394D4365B77954FDEA4145FCF7A7A041 -Test: Encrypt -Comment: Set 2, vector 58 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000200000000000000000 -Ciphertext: B1D8311A492ED11F11E57B29221610C4 -Test: Encrypt -Comment: Set 2, vector 59 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000100000000000000000 -Ciphertext: E5FBB947A63AEA90163AF04AD6951EF8 -Test: Encrypt -Comment: Set 2, vector 60 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000080000000000000000 -Ciphertext: CA0627DDF580F0E7D59562825C9D0492 -Test: Encrypt -Comment: Set 2, vector 61 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000040000000000000000 -Ciphertext: EF98FFD1AED295AAE1860F0274C8F555 -Test: Encrypt -Comment: Set 2, vector 62 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000020000000000000000 -Ciphertext: 8C698E5CFFF08FACE10C2DC5FF1E2A81 -Test: Encrypt -Comment: Set 2, vector 63 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000010000000000000000 -Ciphertext: 35A7767E02032C35B5CE1A6F49C57C28 -Test: Encrypt -Comment: Set 2, vector 64 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000008000000000000000 -Ciphertext: AB36F8734E76EBA306CF00D6763D90B0 -Test: Encrypt -Comment: Set 2, vector 65 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000004000000000000000 -Ciphertext: E854EB66D4EC66889B5E6CD4F44A5806 -Test: Encrypt -Comment: Set 2, vector 66 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000002000000000000000 -Ciphertext: 15B66DF1455ACD640B8716BCF5DB2D69 -Test: Encrypt -Comment: Set 2, vector 67 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000001000000000000000 -Ciphertext: 4C57AB5333E5C2D4B7E30A007E449F48 -Test: Encrypt -Comment: Set 2, vector 68 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000800000000000000 -Ciphertext: BA3E7FF28EB38EA09D8DB1440A9A3552 -Test: Encrypt -Comment: Set 2, vector 69 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000400000000000000 -Ciphertext: 64E60227AFD80C40C70186CC94804C1A -Test: Encrypt -Comment: Set 2, vector 70 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000200000000000000 -Ciphertext: CEB4423C20B4C91C2551F6FC227C9514 -Test: Encrypt -Comment: Set 2, vector 71 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000100000000000000 -Ciphertext: F736894B843EF32DA28576DE500D448C -Test: Encrypt -Comment: Set 2, vector 72 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000080000000000000 -Ciphertext: 58FDA98B678D15053D4B6C060368108C -Test: Encrypt -Comment: Set 2, vector 73 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000040000000000000 -Ciphertext: E28CAE384E578F47657755EBCD97996C -Test: Encrypt -Comment: Set 2, vector 74 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000020000000000000 -Ciphertext: 0A64617BD4B5B166668240D105B7B6A2 -Test: Encrypt -Comment: Set 2, vector 75 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000010000000000000 -Ciphertext: 4BD090C7E3D365B5EA80F19B4798881E -Test: Encrypt -Comment: Set 2, vector 76 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000008000000000000 -Ciphertext: BC7B6CB9BFF4F72973BB2CD20A512C06 -Test: Encrypt -Comment: Set 2, vector 77 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000004000000000000 -Ciphertext: 4C7ADDC5C867594E9EE75F0AA6AB9C23 -Test: Encrypt -Comment: Set 2, vector 78 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000002000000000000 -Ciphertext: 1FBD05C71A36691AC6566A5298101D53 -Test: Encrypt -Comment: Set 2, vector 79 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000001000000000000 -Ciphertext: 42D7D6B1F499D412F8793972BD968DA2 -Test: Encrypt -Comment: Set 2, vector 80 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000800000000000 -Ciphertext: 260EC86E2786FC68824576B934F32814 -Test: Encrypt -Comment: Set 2, vector 81 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000400000000000 -Ciphertext: 576C26DFD7046F9357F34BEA7DFB26A0 -Test: Encrypt -Comment: Set 2, vector 82 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000200000000000 -Ciphertext: 6D55E54BFB6F927174A02294C95E0F8F -Test: Encrypt -Comment: Set 2, vector 83 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000100000000000 -Ciphertext: 1A6CE91DD458229C7675A34950D10E23 -Test: Encrypt -Comment: Set 2, vector 84 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000080000000000 -Ciphertext: DAD0D5E7E000652825AA34D228EA8D8F -Test: Encrypt -Comment: Set 2, vector 85 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000040000000000 -Ciphertext: E68013F48D75EAD2BBC0B0BDA5E690BF -Test: Encrypt -Comment: Set 2, vector 86 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000020000000000 -Ciphertext: A07D92312FBAE37BFE8A834210AE4F9C -Test: Encrypt -Comment: Set 2, vector 87 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000010000000000 -Ciphertext: 6EEE5F8544CD7D456366EB448813989A -Test: Encrypt -Comment: Set 2, vector 88 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000008000000000 -Ciphertext: F8E5C7FF4B79D7ABE8BFA2DD148820A8 -Test: Encrypt -Comment: Set 2, vector 89 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000004000000000 -Ciphertext: C6349D75C7472BBD66F95B3A07C79C91 -Test: Encrypt -Comment: Set 2, vector 90 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000002000000000 -Ciphertext: B85713C12D8658951CD1AD21C74D2CD2 -Test: Encrypt -Comment: Set 2, vector 91 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000001000000000 -Ciphertext: 907AA00B9F7D47A97623FB55BA911F29 -Test: Encrypt -Comment: Set 2, vector 92 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000800000000 -Ciphertext: DC3CD0ED23D11776FAB43A2A6A8F3557 -Test: Encrypt -Comment: Set 2, vector 93 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000400000000 -Ciphertext: 4BFE58A8FD69179C14765B09AB70B705 -Test: Encrypt -Comment: Set 2, vector 94 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000200000000 -Ciphertext: A23996E0EA67EC280356E5F77130A551 -Test: Encrypt -Comment: Set 2, vector 95 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000100000000 -Ciphertext: CDEADE859B3AACD273CCA85A3E2E45F2 -Test: Encrypt -Comment: Set 2, vector 96 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000080000000 -Ciphertext: E0FC78489857D84DA03F40CE97147174 -Test: Encrypt -Comment: Set 2, vector 97 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000040000000 -Ciphertext: 7615EA6351F6BB12855E8579C6995D8E -Test: Encrypt -Comment: Set 2, vector 98 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000020000000 -Ciphertext: 13E184344FE28C2E70ED0E4D0A8037F9 -Test: Encrypt -Comment: Set 2, vector 99 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000010000000 -Ciphertext: A5FE395F568482B87BC3EB208C81C942 -Test: Encrypt -Comment: Set 2, vector 100 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000008000000 -Ciphertext: B3103E11AF06C85565823F8CAA3159F6 -Test: Encrypt -Comment: Set 2, vector 101 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000004000000 -Ciphertext: 7EBC2234D271B89C519C396985300030 -Test: Encrypt -Comment: Set 2, vector 102 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000002000000 -Ciphertext: 0661D338F2E0C939BA1687820A768467 -Test: Encrypt -Comment: Set 2, vector 103 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000001000000 -Ciphertext: EC2B42667C0195A90715499617884DA5 -Test: Encrypt -Comment: Set 2, vector 104 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000800000 -Ciphertext: AE077BA19D24E7188DDD3682FF196892 -Test: Encrypt -Comment: Set 2, vector 105 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000400000 -Ciphertext: 98823C24B9C65A66073C7952DC2B4B5E -Test: Encrypt -Comment: Set 2, vector 106 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000200000 -Ciphertext: 6AB58432CBB3C2F503DA2D16796CC297 -Test: Encrypt -Comment: Set 2, vector 107 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000100000 -Ciphertext: EEB5EBB3A53E4196C2F22BC1A4DDF5E8 -Test: Encrypt -Comment: Set 2, vector 108 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000080000 -Ciphertext: 33DC40AC5FDC126D38878416AF6C0FA6 -Test: Encrypt -Comment: Set 2, vector 109 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000040000 -Ciphertext: 38EDDC08E18B4AD982CEA921D2765A9A -Test: Encrypt -Comment: Set 2, vector 110 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000020000 -Ciphertext: 7D6BEA038E9347C642E18631660A9558 -Test: Encrypt -Comment: Set 2, vector 111 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000010000 -Ciphertext: FDA57921A473B5EE3700AD5ADF035019 -Test: Encrypt -Comment: Set 2, vector 112 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000008000 -Ciphertext: 699B4812E200337E9C1D2C397F0DFE4E -Test: Encrypt -Comment: Set 2, vector 113 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000004000 -Ciphertext: 7A1EADF68B0807145D6C414852DECFC8 -Test: Encrypt -Comment: Set 2, vector 114 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000002000 -Ciphertext: 1645FFAA8AD76689C01DA8C40882781F -Test: Encrypt -Comment: Set 2, vector 115 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000001000 -Ciphertext: BA0C053BE702FA62FC66D8FEB12FC97E -Test: Encrypt -Comment: Set 2, vector 116 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000000800 -Ciphertext: 841FD8AF69CF2C31F7D4D7B6959662B5 -Test: Encrypt -Comment: Set 2, vector 117 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000000400 -Ciphertext: F675D59BDB33231861268F539829DA0B -Test: Encrypt -Comment: Set 2, vector 118 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000000200 -Ciphertext: A4967F45ABB4E8C7DC5E3806680F35E0 -Test: Encrypt -Comment: Set 2, vector 119 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000000100 -Ciphertext: 4D7E08081CC82F92ABA7C58C99F8343F -Test: Encrypt -Comment: Set 2, vector 120 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000000080 -Ciphertext: 9AEFDB287C119B82353612B60ECCBFD8 -Test: Encrypt -Comment: Set 2, vector 121 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000000040 -Ciphertext: 979BB6A1553A17592A86E78DF144A699 -Test: Encrypt -Comment: Set 2, vector 122 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000000020 -Ciphertext: A6FA8CAB06FD2E5BF3A858983C01757A -Test: Encrypt -Comment: Set 2, vector 123 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000000010 -Ciphertext: BE8511254C31E25420B91D6FEF1710ED -Test: Encrypt -Comment: Set 2, vector 124 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000000008 -Ciphertext: F589A908D18A21894971C0433581E1A5 -Test: Encrypt -Comment: Set 2, vector 125 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000000004 -Ciphertext: 4237585130E7C9F715235EB1D8C94DE7 -Test: Encrypt -Comment: Set 2, vector 126 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000000002 -Ciphertext: DEFE3E0B5C54C94B4F2A0F5A46F6210D -Test: Encrypt -Comment: Set 2, vector 127 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000000001 -Ciphertext: F5574ACC3148DFCB9015200631024DF9 -Test: Encrypt -Comment: Set 3, vector 0 -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3D028025B156327C17F762C1F2CBCA71 -Test: Encrypt -Comment: Set 3, vector 1 -Key: 01010101010101010101010101010101 -Plaintext: 01010101010101010101010101010101 -Ciphertext: 637084CB1120D6F25DB618893040AA27 -Test: Encrypt -Comment: Set 3, vector 2 -Key: 02020202020202020202020202020202 -Plaintext: 02020202020202020202020202020202 -Ciphertext: 612834AAC9EF906BAEAA076E1C75179D -Test: Encrypt -Comment: Set 3, vector 3 -Key: 03030303030303030303030303030303 -Plaintext: 03030303030303030303030303030303 -Ciphertext: AECEE4C59E91366360923654C17140A9 -Test: Encrypt -Comment: Set 3, vector 4 -Key: 04040404040404040404040404040404 -Plaintext: 04040404040404040404040404040404 -Ciphertext: B24FAF8A579E4EFE986571FB2F68B5B4 -Test: Encrypt -Comment: Set 3, vector 5 -Key: 05050505050505050505050505050505 -Plaintext: 05050505050505050505050505050505 -Ciphertext: C102E40B5E584CF6AA16108D93DA26E3 -Test: Encrypt -Comment: Set 3, vector 6 -Key: 06060606060606060606060606060606 -Plaintext: 06060606060606060606060606060606 -Ciphertext: 962F98098E6CEA968FA568C5A32ADA50 -Test: Encrypt -Comment: Set 3, vector 7 -Key: 07070707070707070707070707070707 -Plaintext: 07070707070707070707070707070707 -Ciphertext: 27E9AB0117A37D228B77B29B38B3836F -Test: Encrypt -Comment: Set 3, vector 8 -Key: 08080808080808080808080808080808 -Plaintext: 08080808080808080808080808080808 -Ciphertext: 3E5CAFBB70545AABB1109293A1C44C14 -Test: Encrypt -Comment: Set 3, vector 9 -Key: 09090909090909090909090909090909 -Plaintext: 09090909090909090909090909090909 -Ciphertext: E4AC7417ECB8B2871B0EF12CECD20F46 -Test: Encrypt -Comment: Set 3, vector 10 -Key: 0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A -Plaintext: 0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A -Ciphertext: B29D18DD34C1CC00257838F1B8BD43DB -Test: Encrypt -Comment: Set 3, vector 11 -Key: 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B -Plaintext: 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B -Ciphertext: FC1094A0A2850499D874B6DDC1EBA0B7 -Test: Encrypt -Comment: Set 3, vector 12 -Key: 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C -Plaintext: 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C -Ciphertext: AD062A5D53BB0478F17DA5528839F9FF -Test: Encrypt -Comment: Set 3, vector 13 -Key: 0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D -Plaintext: 0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D -Ciphertext: 2C9DFEC27363BD0E651CC91FC05FDADF -Test: Encrypt -Comment: Set 3, vector 14 -Key: 0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E -Plaintext: 0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E -Ciphertext: 487C72BD251D4566AE6119A70A95B79F -Test: Encrypt -Comment: Set 3, vector 15 -Key: 0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F -Plaintext: 0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F -Ciphertext: 18CE9F8E752F787051CB8E407EB16C12 -Test: Encrypt -Comment: Set 3, vector 16 -Key: 10101010101010101010101010101010 -Plaintext: 10101010101010101010101010101010 -Ciphertext: E1FA5FD3F40B766BBE3DF469AF41B420 -Test: Encrypt -Comment: Set 3, vector 17 -Key: 11111111111111111111111111111111 -Plaintext: 11111111111111111111111111111111 -Ciphertext: 09628EDC6CD69F4F85483DC37633F732 -Test: Encrypt -Comment: Set 3, vector 18 -Key: 12121212121212121212121212121212 -Plaintext: 12121212121212121212121212121212 -Ciphertext: 2E6C94A96F6744C4E8D4146B4ECCD815 -Test: Encrypt -Comment: Set 3, vector 19 -Key: 13131313131313131313131313131313 -Plaintext: 13131313131313131313131313131313 -Ciphertext: 800996B5B363ACAB3FB8982F9BBE767F -Test: Encrypt -Comment: Set 3, vector 20 -Key: 14141414141414141414141414141414 -Plaintext: 14141414141414141414141414141414 -Ciphertext: C254C27642167B8FF363EAAD41A165A8 -Test: Encrypt -Comment: Set 3, vector 21 -Key: 15151515151515151515151515151515 -Plaintext: 15151515151515151515151515151515 -Ciphertext: 0B43A548CFFE916BAD7AB58B5F51B1E2 -Test: Encrypt -Comment: Set 3, vector 22 -Key: 16161616161616161616161616161616 -Plaintext: 16161616161616161616161616161616 -Ciphertext: 6C753853277756B8E0578FDC371A8738 -Test: Encrypt -Comment: Set 3, vector 23 -Key: 17171717171717171717171717171717 -Plaintext: 17171717171717171717171717171717 -Ciphertext: A278A500B02D8B2C7E829F1816872B1A -Test: Encrypt -Comment: Set 3, vector 24 -Key: 18181818181818181818181818181818 -Plaintext: 18181818181818181818181818181818 -Ciphertext: 67DD5353E13CDD51FC52716BC6BAB258 -Test: Encrypt -Comment: Set 3, vector 25 -Key: 19191919191919191919191919191919 -Plaintext: 19191919191919191919191919191919 -Ciphertext: 1B2DF65083662590F49719D7721D7C61 -Test: Encrypt -Comment: Set 3, vector 26 -Key: 1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A -Plaintext: 1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A -Ciphertext: B12E384030DE7B77866E758FB251CCFF -Test: Encrypt -Comment: Set 3, vector 27 -Key: 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B -Plaintext: 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B -Ciphertext: C37B3145C36FE5B95AC1392BEB81C9D8 -Test: Encrypt -Comment: Set 3, vector 28 -Key: 1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C -Plaintext: 1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C -Ciphertext: 5C25502EF79A5792DEE9359EDF7BA8BC -Test: Encrypt -Comment: Set 3, vector 29 -Key: 1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D -Plaintext: 1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D -Ciphertext: F0D899AEF42F226605E6A61A650F00A1 -Test: Encrypt -Comment: Set 3, vector 30 -Key: 1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E -Plaintext: 1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E -Ciphertext: 12096937A3474FE4D87C77581C09380B -Test: Encrypt -Comment: Set 3, vector 31 -Key: 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F -Plaintext: 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F -Ciphertext: CFC3A30819A45111983ABBF16CC61E9A -Test: Encrypt -Comment: Set 3, vector 32 -Key: 20202020202020202020202020202020 -Plaintext: 20202020202020202020202020202020 -Ciphertext: 7E724027BB2F591C63254D936FCC4B43 -Test: Encrypt -Comment: Set 3, vector 33 -Key: 21212121212121212121212121212121 -Plaintext: 21212121212121212121212121212121 -Ciphertext: FC9893DACCE806419957685270D5BF13 -Test: Encrypt -Comment: Set 3, vector 34 -Key: 22222222222222222222222222222222 -Plaintext: 22222222222222222222222222222222 -Ciphertext: F6C372A2AE2C03D7A9E0597DBEDFE961 -Test: Encrypt -Comment: Set 3, vector 35 -Key: 23232323232323232323232323232323 -Plaintext: 23232323232323232323232323232323 -Ciphertext: 4EE3CD585BD7A498DE93DDE42FDCBE73 -Test: Encrypt -Comment: Set 3, vector 36 -Key: 24242424242424242424242424242424 -Plaintext: 24242424242424242424242424242424 -Ciphertext: 71D0FFA714D70B5A3CDCE26BC91D93EE -Test: Encrypt -Comment: Set 3, vector 37 -Key: 25252525252525252525252525252525 -Plaintext: 25252525252525252525252525252525 -Ciphertext: 918EB6A7FA54EE795DE68EB5C0011BFD -Test: Encrypt -Comment: Set 3, vector 38 -Key: 26262626262626262626262626262626 -Plaintext: 26262626262626262626262626262626 -Ciphertext: 3A3DBFD37FB057816485BA948034E25E -Test: Encrypt -Comment: Set 3, vector 39 -Key: 27272727272727272727272727272727 -Plaintext: 27272727272727272727272727272727 -Ciphertext: 1FAD9F63890CF5475F3557B83924427C -Test: Encrypt -Comment: Set 3, vector 40 -Key: 28282828282828282828282828282828 -Plaintext: 28282828282828282828282828282828 -Ciphertext: 63F70DD87B9D63FC79628DECC6F34605 -Test: Encrypt -Comment: Set 3, vector 41 -Key: 29292929292929292929292929292929 -Plaintext: 29292929292929292929292929292929 -Ciphertext: D8FE7DF75B51024B69BDAB4844233CBB -Test: Encrypt -Comment: Set 3, vector 42 -Key: 2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A -Plaintext: 2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A -Ciphertext: D927B8DB454BEECFEE2F89ACD2D26F1A -Test: Encrypt -Comment: Set 3, vector 43 -Key: 2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B -Plaintext: 2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B -Ciphertext: 958B7CFABED67123D21541083FA90EB8 -Test: Encrypt -Comment: Set 3, vector 44 -Key: 2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C -Plaintext: 2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C -Ciphertext: 2F220AA3BB400736F3D0295E3C6D9052 -Test: Encrypt -Comment: Set 3, vector 45 -Key: 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D -Plaintext: 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D -Ciphertext: A14F57CE4D9EA4C5E282108DF8FDE00E -Test: Encrypt -Comment: Set 3, vector 46 -Key: 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E -Plaintext: 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E -Ciphertext: 23E437F93E0BE22B4C54BC187D70BCC1 -Test: Encrypt -Comment: Set 3, vector 47 -Key: 2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F -Plaintext: 2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F -Ciphertext: 615B6706E39E4A55EA8BFA4EFB8EBAEA -Test: Encrypt -Comment: Set 3, vector 48 -Key: 30303030303030303030303030303030 -Plaintext: 30303030303030303030303030303030 -Ciphertext: 5354CC9F7CAA08298C9A8AD471B39235 -Test: Encrypt -Comment: Set 3, vector 49 -Key: 31313131313131313131313131313131 -Plaintext: 31313131313131313131313131313131 -Ciphertext: DA2512B115E748580B7D198BFF01A537 -Test: Encrypt -Comment: Set 3, vector 50 -Key: 32323232323232323232323232323232 -Plaintext: 32323232323232323232323232323232 -Ciphertext: AEF890FCDEC04BFB0C4724558688810B -Test: Encrypt -Comment: Set 3, vector 51 -Key: 33333333333333333333333333333333 -Plaintext: 33333333333333333333333333333333 -Ciphertext: AEC153899584F8B9FC9836B86A40BA4A -Test: Encrypt -Comment: Set 3, vector 52 -Key: 34343434343434343434343434343434 -Plaintext: 34343434343434343434343434343434 -Ciphertext: E86D0DBEBD69030C0654656E0D348A8E -Test: Encrypt -Comment: Set 3, vector 53 -Key: 35353535353535353535353535353535 -Plaintext: 35353535353535353535353535353535 -Ciphertext: 3EFFEE758220F7138D31564D5CDA82EF -Test: Encrypt -Comment: Set 3, vector 54 -Key: 36363636363636363636363636363636 -Plaintext: 36363636363636363636363636363636 -Ciphertext: A0A57A825008700B246CEE9821803321 -Test: Encrypt -Comment: Set 3, vector 55 -Key: 37373737373737373737373737373737 -Plaintext: 37373737373737373737373737373737 -Ciphertext: 318692397CD421D958D142299AE24E5E -Test: Encrypt -Comment: Set 3, vector 56 -Key: 38383838383838383838383838383838 -Plaintext: 38383838383838383838383838383838 -Ciphertext: 1B949505033DB5554BBBBBB9488970DE -Test: Encrypt -Comment: Set 3, vector 57 -Key: 39393939393939393939393939393939 -Plaintext: 39393939393939393939393939393939 -Ciphertext: 20600DB3471001F93837F8EB50F7EB2B -Test: Encrypt -Comment: Set 3, vector 58 -Key: 3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A -Plaintext: 3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A -Ciphertext: 004C126190B7D20ADCA7331EA26AC487 -Test: Encrypt -Comment: Set 3, vector 59 -Key: 3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B -Plaintext: 3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B -Ciphertext: 7F535656FE3113A61D21BE216365D9FD -Test: Encrypt -Comment: Set 3, vector 60 -Key: 3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C -Plaintext: 3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C -Ciphertext: A7DA48E8AD71B1DC583A895A8CC85FF2 -Test: Encrypt -Comment: Set 3, vector 61 -Key: 3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D -Plaintext: 3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D -Ciphertext: 02E8CB85E9DDEDFAB4D9DB7106C6C38F -Test: Encrypt -Comment: Set 3, vector 62 -Key: 3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E -Plaintext: 3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E -Ciphertext: 44ACE8B20DF2DBA70C0287362D51ED5C -Test: Encrypt -Comment: Set 3, vector 63 -Key: 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F -Plaintext: 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F -Ciphertext: 8ABDD80D977FAF208FDFC69AA70E9810 -Test: Encrypt -Comment: Set 3, vector 64 -Key: 40404040404040404040404040404040 -Plaintext: 40404040404040404040404040404040 -Ciphertext: 538ADCBE104A3483B3C2A3D8CE72FBD6 -Test: Encrypt -Comment: Set 3, vector 65 -Key: 41414141414141414141414141414141 -Plaintext: 41414141414141414141414141414141 -Ciphertext: 7F757894F1A04645BCB523E925A937C7 -Test: Encrypt -Comment: Set 3, vector 66 -Key: 42424242424242424242424242424242 -Plaintext: 42424242424242424242424242424242 -Ciphertext: FA4304C7D16E164E000461B2550207B1 -Test: Encrypt -Comment: Set 3, vector 67 -Key: 43434343434343434343434343434343 -Plaintext: 43434343434343434343434343434343 -Ciphertext: 5B8E43BF0CACBCB80933B4061F9702B2 -Test: Encrypt -Comment: Set 3, vector 68 -Key: 44444444444444444444444444444444 -Plaintext: 44444444444444444444444444444444 -Ciphertext: 4DB11630D8CD9390797EE30EE9A25CB3 -Test: Encrypt -Comment: Set 3, vector 69 -Key: 45454545454545454545454545454545 -Plaintext: 45454545454545454545454545454545 -Ciphertext: 61150375D22621E9DD7AB45227E4ADC1 -Test: Encrypt -Comment: Set 3, vector 70 -Key: 46464646464646464646464646464646 -Plaintext: 46464646464646464646464646464646 -Ciphertext: 825AA0A2275496EA00BE2C75982EC24E -Test: Encrypt -Comment: Set 3, vector 71 -Key: 47474747474747474747474747474747 -Plaintext: 47474747474747474747474747474747 -Ciphertext: 1EA3F70E26F079CE37801787B5F3655C -Test: Encrypt -Comment: Set 3, vector 72 -Key: 48484848484848484848484848484848 -Plaintext: 48484848484848484848484848484848 -Ciphertext: F46E712267A6CA8DA8AC044A4E3ADC69 -Test: Encrypt -Comment: Set 3, vector 73 -Key: 49494949494949494949494949494949 -Plaintext: 49494949494949494949494949494949 -Ciphertext: 00FCF96BD11DB90E045B948C2658FC07 -Test: Encrypt -Comment: Set 3, vector 74 -Key: 4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A -Plaintext: 4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A -Ciphertext: 08E264CCDA07442DD6FB5BC8AF05A9C1 -Test: Encrypt -Comment: Set 3, vector 75 -Key: 4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B -Plaintext: 4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B -Ciphertext: 35C189E86440D125B0CAF6C62CA0E4F9 -Test: Encrypt -Comment: Set 3, vector 76 -Key: 4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C -Plaintext: 4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C -Ciphertext: 7FC2F545C0DE78664218F4F635CC8D10 -Test: Encrypt -Comment: Set 3, vector 77 -Key: 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D -Plaintext: 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D -Ciphertext: 9DC067581AD80555C6E46C6594A626F5 -Test: Encrypt -Comment: Set 3, vector 78 -Key: 4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E -Plaintext: 4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E -Ciphertext: D33A3E8035B42D76A483BE06B62054A6 -Test: Encrypt -Comment: Set 3, vector 79 -Key: 4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F -Plaintext: 4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F -Ciphertext: 7CA26FD5D6DB7EAA785FCCA1E2854910 -Test: Encrypt -Comment: Set 3, vector 80 -Key: 50505050505050505050505050505050 -Plaintext: 50505050505050505050505050505050 -Ciphertext: E9A672BD5401539C1C8F2AB21A83B26B -Test: Encrypt -Comment: Set 3, vector 81 -Key: 51515151515151515151515151515151 -Plaintext: 51515151515151515151515151515151 -Ciphertext: 2948CB8989780E74BA525CC2FDDC42CF -Test: Encrypt -Comment: Set 3, vector 82 -Key: 52525252525252525252525252525252 -Plaintext: 52525252525252525252525252525252 -Ciphertext: A3A8308145C318D42F4E8310DF6D97E0 -Test: Encrypt -Comment: Set 3, vector 83 -Key: 53535353535353535353535353535353 -Plaintext: 53535353535353535353535353535353 -Ciphertext: 1757125D19851062D7782A2200A813E9 -Test: Encrypt -Comment: Set 3, vector 84 -Key: 54545454545454545454545454545454 -Plaintext: 54545454545454545454545454545454 -Ciphertext: 9BC4FC94FF7A09F9D4C23A3BDEAF498E -Test: Encrypt -Comment: Set 3, vector 85 -Key: 55555555555555555555555555555555 -Plaintext: 55555555555555555555555555555555 -Ciphertext: B36C8A8DC251A4D08B38160011498AB2 -Test: Encrypt -Comment: Set 3, vector 86 -Key: 56565656565656565656565656565656 -Plaintext: 56565656565656565656565656565656 -Ciphertext: 6C6058C8D5F2A32E31988239C4A657F1 -Test: Encrypt -Comment: Set 3, vector 87 -Key: 57575757575757575757575757575757 -Plaintext: 57575757575757575757575757575757 -Ciphertext: B8B914785FD465FB0F83FE4A676C3A6B -Test: Encrypt -Comment: Set 3, vector 88 -Key: 58585858585858585858585858585858 -Plaintext: 58585858585858585858585858585858 -Ciphertext: 00BBEEC24412F8A2C4291B5F1F32E662 -Test: Encrypt -Comment: Set 3, vector 89 -Key: 59595959595959595959595959595959 -Plaintext: 59595959595959595959595959595959 -Ciphertext: AF8353C84504526068884176D45CC8A0 -Test: Encrypt -Comment: Set 3, vector 90 -Key: 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A -Plaintext: 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A -Ciphertext: F84DF1519736174F6F23B4CC3FC939F1 -Test: Encrypt -Comment: Set 3, vector 91 -Key: 5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B -Plaintext: 5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B -Ciphertext: 320326E1024C9156B0E4C483065F0D94 -Test: Encrypt -Comment: Set 3, vector 92 -Key: 5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C -Plaintext: 5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C -Ciphertext: 80AFE13AEC30894E8B772E73F367A148 -Test: Encrypt -Comment: Set 3, vector 93 -Key: 5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D -Plaintext: 5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D -Ciphertext: 5F0D8BE9294D27DB7E6CD4D4F8A08D48 -Test: Encrypt -Comment: Set 3, vector 94 -Key: 5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E -Plaintext: 5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E -Ciphertext: B6D8E7EF37171F6271AC274411E26867 -Test: Encrypt -Comment: Set 3, vector 95 -Key: 5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F -Plaintext: 5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F -Ciphertext: 23DEBDDF60703AE0F8E9337C73C6FDC3 -Test: Encrypt -Comment: Set 3, vector 96 -Key: 60606060606060606060606060606060 -Plaintext: 60606060606060606060606060606060 -Ciphertext: D03B4696B0DCC56C37F7038747BEF222 -Test: Encrypt -Comment: Set 3, vector 97 -Key: 61616161616161616161616161616161 -Plaintext: 61616161616161616161616161616161 -Ciphertext: 201E6A1FA7898892DA1D3148766F7939 -Test: Encrypt -Comment: Set 3, vector 98 -Key: 62626262626262626262626262626262 -Plaintext: 62626262626262626262626262626262 -Ciphertext: D9643DBC3C373D300DB5AC3E699F7DDE -Test: Encrypt -Comment: Set 3, vector 99 -Key: 63636363636363636363636363636363 -Plaintext: 63636363636363636363636363636363 -Ciphertext: 1B04DAF08A764C09DFFE140403F4EC5D -Test: Encrypt -Comment: Set 3, vector 100 -Key: 64646464646464646464646464646464 -Plaintext: 64646464646464646464646464646464 -Ciphertext: 0510AA045E35862885AEEB1752328032 -Test: Encrypt -Comment: Set 3, vector 101 -Key: 65656565656565656565656565656565 -Plaintext: 65656565656565656565656565656565 -Ciphertext: 894E5FE4164A0B9CC2C50D95F18329E6 -Test: Encrypt -Comment: Set 3, vector 102 -Key: 66666666666666666666666666666666 -Plaintext: 66666666666666666666666666666666 -Ciphertext: 99D16D251893E474CD8A18C10798D418 -Test: Encrypt -Comment: Set 3, vector 103 -Key: 67676767676767676767676767676767 -Plaintext: 67676767676767676767676767676767 -Ciphertext: B41A0DEEA15FCB419E00318752503FA8 -Test: Encrypt -Comment: Set 3, vector 104 -Key: 68686868686868686868686868686868 -Plaintext: 68686868686868686868686868686868 -Ciphertext: 8BDDFBD29844F3EED1E02FB76628E877 -Test: Encrypt -Comment: Set 3, vector 105 -Key: 69696969696969696969696969696969 -Plaintext: 69696969696969696969696969696969 -Ciphertext: E71C41B95412E2ED6BC6B5693BC445E5 -Test: Encrypt -Comment: Set 3, vector 106 -Key: 6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A -Plaintext: 6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A -Ciphertext: 566E5667E9BDDCE13F3B6DE0DEF06305 -Test: Encrypt -Comment: Set 3, vector 107 -Key: 6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B -Plaintext: 6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B -Ciphertext: 49372FDCE8DC81E45A9E6FBFB8952F76 -Test: Encrypt -Comment: Set 3, vector 108 -Key: 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C -Plaintext: 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C -Ciphertext: 034EAB9E0E881ABF0C4F9B7933E7F1B2 -Test: Encrypt -Comment: Set 3, vector 109 -Key: 6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D -Plaintext: 6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D -Ciphertext: 56FFE171E45816C5808380530F3F9F23 -Test: Encrypt -Comment: Set 3, vector 110 -Key: 6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E -Plaintext: 6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E -Ciphertext: 5FE59EE65A0321F3B09A1748CF18CC02 -Test: Encrypt -Comment: Set 3, vector 111 -Key: 6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F -Plaintext: 6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F -Ciphertext: 8C13790203280B652614D224178C4289 -Test: Encrypt -Comment: Set 3, vector 112 -Key: 70707070707070707070707070707070 -Plaintext: 70707070707070707070707070707070 -Ciphertext: 52D7C5111B52E5356C8EF2B629BA6166 -Test: Encrypt -Comment: Set 3, vector 113 -Key: 71717171717171717171717171717171 -Plaintext: 71717171717171717171717171717171 -Ciphertext: 4FB997235548FB5C202A1514FF408068 -Test: Encrypt -Comment: Set 3, vector 114 -Key: 72727272727272727272727272727272 -Plaintext: 72727272727272727272727272727272 -Ciphertext: 8DDE9345FEDAB8D8D2DE5E2577756F16 -Test: Encrypt -Comment: Set 3, vector 115 -Key: 73737373737373737373737373737373 -Plaintext: 73737373737373737373737373737373 -Ciphertext: C1B39136F69B2044C30E38023EB6E7D2 -Test: Encrypt -Comment: Set 3, vector 116 -Key: 74747474747474747474747474747474 -Plaintext: 74747474747474747474747474747474 -Ciphertext: 6032D1B3844BEA4ACE81142A013C42BC -Test: Encrypt -Comment: Set 3, vector 117 -Key: 75757575757575757575757575757575 -Plaintext: 75757575757575757575757575757575 -Ciphertext: 985A9D8DDE048107368028AA24F5D70B -Test: Encrypt -Comment: Set 3, vector 118 -Key: 76767676767676767676767676767676 -Plaintext: 76767676767676767676767676767676 -Ciphertext: 5343E03D587A538475BB92F23E96FDF8 -Test: Encrypt -Comment: Set 3, vector 119 -Key: 77777777777777777777777777777777 -Plaintext: 77777777777777777777777777777777 -Ciphertext: 98253AF78B8DA7E5AE98E7B4E9FA74F9 -Test: Encrypt -Comment: Set 3, vector 120 -Key: 78787878787878787878787878787878 -Plaintext: 78787878787878787878787878787878 -Ciphertext: 8404DDA01CC702790B8B31408205E128 -Test: Encrypt -Comment: Set 3, vector 121 -Key: 79797979797979797979797979797979 -Plaintext: 79797979797979797979797979797979 -Ciphertext: C782C96911F30723AB90E3A0BA59B808 -Test: Encrypt -Comment: Set 3, vector 122 -Key: 7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A -Plaintext: 7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A -Ciphertext: 471270191B1BB659804CEAE818793167 -Test: Encrypt -Comment: Set 3, vector 123 -Key: 7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B -Plaintext: 7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B -Ciphertext: 2B27BBF7E47DA05F72EED52D038A3241 -Test: Encrypt -Comment: Set 3, vector 124 -Key: 7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C -Plaintext: 7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C -Ciphertext: 0BD3B3F3F6F404B6B7C6D436605640B7 -Test: Encrypt -Comment: Set 3, vector 125 -Key: 7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D -Plaintext: 7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D -Ciphertext: 74578268B9D9AD5D9819E51CA288F81D -Test: Encrypt -Comment: Set 3, vector 126 -Key: 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E -Plaintext: 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E -Ciphertext: A77A67CC08111CE41B817176859675B5 -Test: Encrypt -Comment: Set 3, vector 127 -Key: 7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F -Plaintext: 7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F -Ciphertext: 9BE99EFDAF9CCCB4D879173EA2197FEF -Test: Encrypt -Comment: Set 3, vector 128 -Key: 80808080808080808080808080808080 -Plaintext: 80808080808080808080808080808080 -Ciphertext: AA7627F70F6B54C217C3EF232D362459 -Test: Encrypt -Comment: Set 3, vector 129 -Key: 81818181818181818181818181818181 -Plaintext: 81818181818181818181818181818181 -Ciphertext: EE41F8DC661C2A8B95667CB1F908367A -Test: Encrypt -Comment: Set 3, vector 130 -Key: 82828282828282828282828282828282 -Plaintext: 82828282828282828282828282828282 -Ciphertext: AF2D71AC4D7E482E8134A65F2841101A -Test: Encrypt -Comment: Set 3, vector 131 -Key: 83838383838383838383838383838383 -Plaintext: 83838383838383838383838383838383 -Ciphertext: 98CFCAA37D3B1825C55FA94825BBC91A -Test: Encrypt -Comment: Set 3, vector 132 -Key: 84848484848484848484848484848484 -Plaintext: 84848484848484848484848484848484 -Ciphertext: 2ACFCBC772417EBD445F8B272857578C -Test: Encrypt -Comment: Set 3, vector 133 -Key: 85858585858585858585858585858585 -Plaintext: 85858585858585858585858585858585 -Ciphertext: 424DE49A69767A539E26581A19CD4F17 -Test: Encrypt -Comment: Set 3, vector 134 -Key: 86868686868686868686868686868686 -Plaintext: 86868686868686868686868686868686 -Ciphertext: F25ED7239B234E58AE40F7612E3CE6BA -Test: Encrypt -Comment: Set 3, vector 135 -Key: 87878787878787878787878787878787 -Plaintext: 87878787878787878787878787878787 -Ciphertext: 4BF44DBA1E6E80DE3554F7EEF0621EBF -Test: Encrypt -Comment: Set 3, vector 136 -Key: 88888888888888888888888888888888 -Plaintext: 88888888888888888888888888888888 -Ciphertext: 6B87409975816BC8480985D079B08594 -Test: Encrypt -Comment: Set 3, vector 137 -Key: 89898989898989898989898989898989 -Plaintext: 89898989898989898989898989898989 -Ciphertext: D026A866DD55C02EE77DF1E93405A751 -Test: Encrypt -Comment: Set 3, vector 138 -Key: 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A -Plaintext: 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A -Ciphertext: A45F7212DD04352DEF319D58922C44CE -Test: Encrypt -Comment: Set 3, vector 139 -Key: 8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B -Plaintext: 8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B -Ciphertext: 4600AD219EE97A7BFF629D8F6E337C79 -Test: Encrypt -Comment: Set 3, vector 140 -Key: 8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C -Plaintext: 8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C -Ciphertext: A26CEFEC7612A89E8543503A678D921F -Test: Encrypt -Comment: Set 3, vector 141 -Key: 8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D -Plaintext: 8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D -Ciphertext: 5CA126B9342723816C82AC1D41F97EFB -Test: Encrypt -Comment: Set 3, vector 142 -Key: 8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E -Plaintext: 8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E -Ciphertext: 76DC82C091F5691C35E8735EB901B788 -Test: Encrypt -Comment: Set 3, vector 143 -Key: 8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F -Plaintext: 8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F -Ciphertext: 2F8AA5E8D7D90B3E7FCC20128F462AAD -Test: Encrypt -Comment: Set 3, vector 144 -Key: 90909090909090909090909090909090 -Plaintext: 90909090909090909090909090909090 -Ciphertext: 67B8B189FCD886FD2160005C93D9F3B2 -Test: Encrypt -Comment: Set 3, vector 145 -Key: 91919191919191919191919191919191 -Plaintext: 91919191919191919191919191919191 -Ciphertext: 8DFBD0B7D8B614E15B56571A6A5B443D -Test: Encrypt -Comment: Set 3, vector 146 -Key: 92929292929292929292929292929292 -Plaintext: 92929292929292929292929292929292 -Ciphertext: F10DA9ABD28359461A3BB271C2037D1A -Test: Encrypt -Comment: Set 3, vector 147 -Key: 93939393939393939393939393939393 -Plaintext: 93939393939393939393939393939393 -Ciphertext: 5A53C6ADF38E807BC03CC53193133CDE -Test: Encrypt -Comment: Set 3, vector 148 -Key: 94949494949494949494949494949494 -Plaintext: 94949494949494949494949494949494 -Ciphertext: 298AF9909A89241F34DB6BF6ACC6A909 -Test: Encrypt -Comment: Set 3, vector 149 -Key: 95959595959595959595959595959595 -Plaintext: 95959595959595959595959595959595 -Ciphertext: DAA5C134BDD34A775DEC219F6DE219BE -Test: Encrypt -Comment: Set 3, vector 150 -Key: 96969696969696969696969696969696 -Plaintext: 96969696969696969696969696969696 -Ciphertext: 2514903F8ABA0F65CA22C8AD82FF2574 -Test: Encrypt -Comment: Set 3, vector 151 -Key: 97979797979797979797979797979797 -Plaintext: 97979797979797979797979797979797 -Ciphertext: 11696CB06D2F97B1A2CB380E2887AB7E -Test: Encrypt -Comment: Set 3, vector 152 -Key: 98989898989898989898989898989898 -Plaintext: 98989898989898989898989898989898 -Ciphertext: E70BAE913D953A66AC35DE9CAA6D205D -Test: Encrypt -Comment: Set 3, vector 153 -Key: 99999999999999999999999999999999 -Plaintext: 99999999999999999999999999999999 -Ciphertext: 20BC3C8F4E81EEA320189E6063017706 -Test: Encrypt -Comment: Set 3, vector 154 -Key: 9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A -Plaintext: 9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A -Ciphertext: 53A956A32B4B532F5E9BE8C94278EC57 -Test: Encrypt -Comment: Set 3, vector 155 -Key: 9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B -Plaintext: 9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B -Ciphertext: 2562236E541426B29A4232E592237CAD -Test: Encrypt -Comment: Set 3, vector 156 -Key: 9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C -Plaintext: 9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C -Ciphertext: 0F8A9DEDA85B0A1CF7487C6ED823B869 -Test: Encrypt -Comment: Set 3, vector 157 -Key: 9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D -Plaintext: 9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D -Ciphertext: 8917CF4F1A25A500440CF0665BB517A0 -Test: Encrypt -Comment: Set 3, vector 158 -Key: 9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E -Plaintext: 9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E -Ciphertext: F5C065F3821FA664724BF6AFF1039430 -Test: Encrypt -Comment: Set 3, vector 159 -Key: 9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F -Plaintext: 9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F -Ciphertext: F5D5131F0D2F4859EC38F8999A93E74D -Test: Encrypt -Comment: Set 3, vector 160 -Key: A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0 -Plaintext: A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0 -Ciphertext: 9A02DF44F2194E94B7E34F1DCC234685 -Test: Encrypt -Comment: Set 3, vector 161 -Key: A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1 -Plaintext: A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1 -Ciphertext: 59491E467432E6147EAFE37BCD93DA01 -Test: Encrypt -Comment: Set 3, vector 162 -Key: A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 -Plaintext: A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 -Ciphertext: 4D0B317CE4AE577CF87B225C53DDF352 -Test: Encrypt -Comment: Set 3, vector 163 -Key: A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3 -Plaintext: A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3 -Ciphertext: 73E082DC996995BDDD1F5544326D56D6 -Test: Encrypt -Comment: Set 3, vector 164 -Key: A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4 -Plaintext: A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4 -Ciphertext: 46C5C6E23A72C9DF410EF979F93CF266 -Test: Encrypt -Comment: Set 3, vector 165 -Key: A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5 -Plaintext: A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5 -Ciphertext: 1F55093C234648C5C9C781E8C9FD42C4 -Test: Encrypt -Comment: Set 3, vector 166 -Key: A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6 -Plaintext: A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6 -Ciphertext: BFA2702CF3DAE25705D1DE1CCDBDC49E -Test: Encrypt -Comment: Set 3, vector 167 -Key: A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7 -Plaintext: A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7 -Ciphertext: 3223365425C1ADE87FF766AB048D9ADB -Test: Encrypt -Comment: Set 3, vector 168 -Key: A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8 -Plaintext: A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8 -Ciphertext: 5449889254C565DF3ADDFB7A86A93DA9 -Test: Encrypt -Comment: Set 3, vector 169 -Key: A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9 -Plaintext: A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9 -Ciphertext: 7D21880CCA919B0CE3917A8C598025FA -Test: Encrypt -Comment: Set 3, vector 170 -Key: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -Plaintext: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -Ciphertext: 5EE203A6739E822A54D9678B604EFD4F -Test: Encrypt -Comment: Set 3, vector 171 -Key: ABABABABABABABABABABABABABABABAB -Plaintext: ABABABABABABABABABABABABABABABAB -Ciphertext: 07038EFBEFDE2228F79A6B526306483A -Test: Encrypt -Comment: Set 3, vector 172 -Key: ACACACACACACACACACACACACACACACAC -Plaintext: ACACACACACACACACACACACACACACACAC -Ciphertext: 78447EBF959FFBD120283CE319FF6005 -Test: Encrypt -Comment: Set 3, vector 173 -Key: ADADADADADADADADADADADADADADADAD -Plaintext: ADADADADADADADADADADADADADADADAD -Ciphertext: 76769D40A286F0FD1C1C6F8895000DE8 -Test: Encrypt -Comment: Set 3, vector 174 -Key: AEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAE -Plaintext: AEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAE -Ciphertext: 7E163343CA44FADFAFDE5386CC111437 -Test: Encrypt -Comment: Set 3, vector 175 -Key: AFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAF -Plaintext: AFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAF -Ciphertext: 4B1E7FE684222BF783142B5DC396F61D -Test: Encrypt -Comment: Set 3, vector 176 -Key: B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0 -Plaintext: B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0 -Ciphertext: 4ECF97472658AC941EC99B255CF95535 -Test: Encrypt -Comment: Set 3, vector 177 -Key: B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1 -Plaintext: B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1 -Ciphertext: 23EE9DF24C8DC126A04586EFF27DBEAC -Test: Encrypt -Comment: Set 3, vector 178 -Key: B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2 -Plaintext: B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2 -Ciphertext: 4B06EE28B7769C4318D509F91D691F39 -Test: Encrypt -Comment: Set 3, vector 179 -Key: B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3 -Plaintext: B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3 -Ciphertext: 51994EF8283D1D29711F602A7ACDA3CA -Test: Encrypt -Comment: Set 3, vector 180 -Key: B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 -Plaintext: B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 -Ciphertext: DCBFBE6BE3234BBB61EA68218C89D098 -Test: Encrypt -Comment: Set 3, vector 181 -Key: B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5 -Plaintext: B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5 -Ciphertext: B84BFA0883546D912BD14807253F8892 -Test: Encrypt -Comment: Set 3, vector 182 -Key: B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6 -Plaintext: B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6 -Ciphertext: 90C1745C0DB97E70BA362CF2C1D376DF -Test: Encrypt -Comment: Set 3, vector 183 -Key: B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7 -Plaintext: B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7 -Ciphertext: 064743C2E8293C1B7619F6E6DEC13B04 -Test: Encrypt -Comment: Set 3, vector 184 -Key: B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8 -Plaintext: B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8 -Ciphertext: 38D913C68ABEE287368CBA38D8FE9F0D -Test: Encrypt -Comment: Set 3, vector 185 -Key: B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9 -Plaintext: B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9 -Ciphertext: B2279D520B33258B7DB221ECDD3C4EBB -Test: Encrypt -Comment: Set 3, vector 186 -Key: BABABABABABABABABABABABABABABABA -Plaintext: BABABABABABABABABABABABABABABABA -Ciphertext: 8AD710DDAE51BE6D4BE7ABC5443B7F9B -Test: Encrypt -Comment: Set 3, vector 187 -Key: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB -Plaintext: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB -Ciphertext: 246BA7624BBF83702764CC1B214A0691 -Test: Encrypt -Comment: Set 3, vector 188 -Key: BCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC -Plaintext: BCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC -Ciphertext: 80E0360B03FA048A892CD47BD7FE948A -Test: Encrypt -Comment: Set 3, vector 189 -Key: BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD -Plaintext: BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD -Ciphertext: 09D5D35BB6DBAE0CC9982D6955EAA01C -Test: Encrypt -Comment: Set 3, vector 190 -Key: BEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBE -Plaintext: BEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBE -Ciphertext: EEBDCE2BDE1F25A40184B9C57DD4E49D -Test: Encrypt -Comment: Set 3, vector 191 -Key: BFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBF -Plaintext: BFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBF -Ciphertext: 22706CFCCD2B0BB15ED30E373FA4E945 -Test: Encrypt -Comment: Set 3, vector 192 -Key: C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0 -Plaintext: C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0 -Ciphertext: D2A4EEACB5F41D12908DD1E069EC14DC -Test: Encrypt -Comment: Set 3, vector 193 -Key: C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1 -Plaintext: C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1 -Ciphertext: E78F614BC7F53C9298098DFEE8ADFB09 -Test: Encrypt -Comment: Set 3, vector 194 -Key: C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2 -Plaintext: C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2 -Ciphertext: B53E3865A8B28A36EF3A505102A6329D -Test: Encrypt -Comment: Set 3, vector 195 -Key: C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3 -Plaintext: C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3 -Ciphertext: 9B32AA8673DFFC47CF8C9B35DDE08DD3 -Test: Encrypt -Comment: Set 3, vector 196 -Key: C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4 -Plaintext: C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4 -Ciphertext: CE70E7257E6C8686C7407E22ACB3E94B -Test: Encrypt -Comment: Set 3, vector 197 -Key: C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5 -Plaintext: C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5 -Ciphertext: 677DB939CA272D717DB4B03EFB70F988 -Test: Encrypt -Comment: Set 3, vector 198 -Key: C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 -Plaintext: C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 -Ciphertext: 6582B069058FA86898A3B12B617C27FD -Test: Encrypt -Comment: Set 3, vector 199 -Key: C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7 -Plaintext: C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7 -Ciphertext: 4DFB68486ECF9833FCE74BD663E20768 -Test: Encrypt -Comment: Set 3, vector 200 -Key: C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8 -Plaintext: C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8 -Ciphertext: 6A3840D2780BABD68A73FAC89C4E8D91 -Test: Encrypt -Comment: Set 3, vector 201 -Key: C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9 -Plaintext: C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9 -Ciphertext: 44C79926D7EAB9DE5A2B95472A79A7BC -Test: Encrypt -Comment: Set 3, vector 202 -Key: CACACACACACACACACACACACACACACACA -Plaintext: CACACACACACACACACACACACACACACACA -Ciphertext: 3813E774EE9EFA8FDB2646E607B2A434 -Test: Encrypt -Comment: Set 3, vector 203 -Key: CBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCB -Plaintext: CBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCB -Ciphertext: FCA748E6AE5678A047E806F8FF103A65 -Test: Encrypt -Comment: Set 3, vector 204 -Key: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC -Plaintext: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC -Ciphertext: 3E3CC9CBE6952AB968FBBEE0C08BF667 -Test: Encrypt -Comment: Set 3, vector 205 -Key: CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD -Plaintext: CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD -Ciphertext: 4FFF3EDC7BCB70E7846DCC4688F9CB3A -Test: Encrypt -Comment: Set 3, vector 206 -Key: CECECECECECECECECECECECECECECECE -Plaintext: CECECECECECECECECECECECECECECECE -Ciphertext: 5728481E82E0DC1631EC611F63B9DD3C -Test: Encrypt -Comment: Set 3, vector 207 -Key: CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF -Plaintext: CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF -Ciphertext: 182BB0D3C52E56248FDA1D343844891D -Test: Encrypt -Comment: Set 3, vector 208 -Key: D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0 -Plaintext: D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0 -Ciphertext: 6B984FC45D0352F3336E7895ECB6DE0E -Test: Encrypt -Comment: Set 3, vector 209 -Key: D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1 -Plaintext: D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1 -Ciphertext: 8DD24A1B23D845E7A6C6D416C7C5B595 -Test: Encrypt -Comment: Set 3, vector 210 -Key: D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2 -Plaintext: D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2 -Ciphertext: 4F4D69B4563373962007945C3197806C -Test: Encrypt -Comment: Set 3, vector 211 -Key: D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3 -Plaintext: D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3 -Ciphertext: DD333390213EB632A51EAE0334A5AEA2 -Test: Encrypt -Comment: Set 3, vector 212 -Key: D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4 -Plaintext: D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4 -Ciphertext: D352ACE83BF6A3BC39EA10D751853009 -Test: Encrypt -Comment: Set 3, vector 213 -Key: D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5 -Plaintext: D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5 -Ciphertext: F2E118276BFCCF6DCDD47E1EAB919BDC -Test: Encrypt -Comment: Set 3, vector 214 -Key: D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6 -Plaintext: D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6 -Ciphertext: 688E877D8B69050F2736D0768571E9A0 -Test: Encrypt -Comment: Set 3, vector 215 -Key: D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7 -Plaintext: D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7 -Ciphertext: DE6F098E56985B7DCFEC52C897F2E735 -Test: Encrypt -Comment: Set 3, vector 216 -Key: D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 -Plaintext: D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 -Ciphertext: 398FA1FE47E3971DA3F9DFD479C9B1AA -Test: Encrypt -Comment: Set 3, vector 217 -Key: D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9 -Plaintext: D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9 -Ciphertext: 6F17B7D7C899B48DAEAD1E90F22AB180 -Test: Encrypt -Comment: Set 3, vector 218 -Key: DADADADADADADADADADADADADADADADA -Plaintext: DADADADADADADADADADADADADADADADA -Ciphertext: D39EBBA5B742F15FCB75D6E656BBF2DA -Test: Encrypt -Comment: Set 3, vector 219 -Key: DBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDB -Plaintext: DBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDB -Ciphertext: 1C6D82247D0BAB18B52CA5293A2C1050 -Test: Encrypt -Comment: Set 3, vector 220 -Key: DCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDC -Plaintext: DCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDC -Ciphertext: B54F248DF57060E40A6A2FA4688C7082 -Test: Encrypt -Comment: Set 3, vector 221 -Key: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD -Plaintext: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD -Ciphertext: 1BB5EB8732CBAB2E3FC334FAAB8BBFBC -Test: Encrypt -Comment: Set 3, vector 222 -Key: DEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDE -Plaintext: DEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDE -Ciphertext: 3734B4B21B50C4740B90FD863EF8627B -Test: Encrypt -Comment: Set 3, vector 223 -Key: DFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDF -Plaintext: DFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDF -Ciphertext: E22E22E60F981D64B7CB341F12F2B362 -Test: Encrypt -Comment: Set 3, vector 224 -Key: E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0 -Plaintext: E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0 -Ciphertext: A2A40EB448D87E39B20460E8CB07515A -Test: Encrypt -Comment: Set 3, vector 225 -Key: E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 -Plaintext: E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 -Ciphertext: 88E6AC929D4D7858015B35D509882C5C -Test: Encrypt -Comment: Set 3, vector 226 -Key: E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2 -Plaintext: E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2 -Ciphertext: FFE4B3B5D0E8229F5428FA2945DBD5EE -Test: Encrypt -Comment: Set 3, vector 227 -Key: E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3 -Plaintext: E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3 -Ciphertext: FCD5F897398A7796A0DAA1809CA7D870 -Test: Encrypt -Comment: Set 3, vector 228 -Key: E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4 -Plaintext: E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4 -Ciphertext: 7F3556B18EC8F04D953DCD27549AF1FC -Test: Encrypt -Comment: Set 3, vector 229 -Key: E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5 -Plaintext: E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5 -Ciphertext: 4433546A8E63AE841CD78B074ED0B91F -Test: Encrypt -Comment: Set 3, vector 230 -Key: E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6 -Plaintext: E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6 -Ciphertext: 2E04671C718BD6C3D115DB2D827A6669 -Test: Encrypt -Comment: Set 3, vector 231 -Key: E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7 -Plaintext: E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7 -Ciphertext: AAE7DA4B977F5EED28F9AF01F8FD47B4 -Test: Encrypt -Comment: Set 3, vector 232 -Key: E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8 -Plaintext: E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8 -Ciphertext: 84AD8F52D51BD3D8E4D8318AF6DB9786 -Test: Encrypt -Comment: Set 3, vector 233 -Key: E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9 -Plaintext: E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9 -Ciphertext: 95EFA65090BD603A1F65A21A43104F79 -Test: Encrypt -Comment: Set 3, vector 234 -Key: EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA -Plaintext: EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA -Ciphertext: 1B83F51E157BBA004CC5BD05986017C8 -Test: Encrypt -Comment: Set 3, vector 235 -Key: EBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEB -Plaintext: EBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEB -Ciphertext: A0C37A641126D5801C4259DFD38E8E8A -Test: Encrypt -Comment: Set 3, vector 236 -Key: ECECECECECECECECECECECECECECECEC -Plaintext: ECECECECECECECECECECECECECECECEC -Ciphertext: 3153A212C2E4727C1032223134342B31 -Test: Encrypt -Comment: Set 3, vector 237 -Key: EDEDEDEDEDEDEDEDEDEDEDEDEDEDEDED -Plaintext: EDEDEDEDEDEDEDEDEDEDEDEDEDEDEDED -Ciphertext: C680D98CAF4409CF31BABCF67352E1D5 -Test: Encrypt -Comment: Set 3, vector 238 -Key: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE -Plaintext: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE -Ciphertext: A7FC85C8459274B836B6F0CBED80AF49 -Test: Encrypt -Comment: Set 3, vector 239 -Key: EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF -Plaintext: EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF -Ciphertext: 5CA8B8A4B8AF15A6184259831B18BBB5 -Test: Encrypt -Comment: Set 3, vector 240 -Key: F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -Plaintext: F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -Ciphertext: F118089963B9AB37776B10B0D4CCEBA4 -Test: Encrypt -Comment: Set 3, vector 241 -Key: F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1 -Plaintext: F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1 -Ciphertext: C233B864E78E9EC272112A34FF7AADBA -Test: Encrypt -Comment: Set 3, vector 242 -Key: F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2 -Plaintext: F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2 -Ciphertext: 2B1C503E7F755A47CC4C57BEB4135B46 -Test: Encrypt -Comment: Set 3, vector 243 -Key: F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 -Plaintext: F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 -Ciphertext: 60D8177BE1044FC5F46DA2B3CAA33102 -Test: Encrypt -Comment: Set 3, vector 244 -Key: F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4 -Plaintext: F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4 -Ciphertext: BA1CBC06977ECE57C5CBC12D99324E00 -Test: Encrypt -Comment: Set 3, vector 245 -Key: F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5 -Plaintext: F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5 -Ciphertext: 01C8561E24A32F53FBAF8864AEE803E3 -Test: Encrypt -Comment: Set 3, vector 246 -Key: F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6 -Plaintext: F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6 -Ciphertext: 797ECFA429014F26B9E62D58B4C1B84E -Test: Encrypt -Comment: Set 3, vector 247 -Key: F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7 -Plaintext: F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7 -Ciphertext: 6AD7FA698A7F3EA8AE13B1DF537BF6EA -Test: Encrypt -Comment: Set 3, vector 248 -Key: F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8 -Plaintext: F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8 -Ciphertext: 49157343BE8B8ED4E59C1AEC3CAB1B94 -Test: Encrypt -Comment: Set 3, vector 249 -Key: F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9 -Plaintext: F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9 -Ciphertext: D33C742DEA4A2C64983766E3068EC200 -Test: Encrypt -Comment: Set 3, vector 250 -Key: FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA -Plaintext: FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA -Ciphertext: 66AE1EAFB45091982E40000BADE002C9 -Test: Encrypt -Comment: Set 3, vector 251 -Key: FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB -Plaintext: FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB -Ciphertext: B6614B0FF5924D0C1EB2C461560BFC01 -Test: Encrypt -Comment: Set 3, vector 252 -Key: FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC -Plaintext: FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC -Ciphertext: 5B4DFBE2BB7666425A858C4769D8DAD0 -Test: Encrypt -Comment: Set 3, vector 253 -Key: FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD -Plaintext: FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD -Ciphertext: 2F142B9044DEC39915ED9347E7B0ED1E -Test: Encrypt -Comment: Set 3, vector 254 -Key: FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE -Plaintext: FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE -Ciphertext: 17E02528D6655CEA7BE6B8548FC2DA65 -Test: Encrypt -Comment: Set 3, vector 255 -Key: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -Plaintext: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -Ciphertext: 25DD9EB9DD67FBC6E8431F56F4FBE651 -Test: Encrypt -Comment: Tests with 192-bit keys -Comment: Set 1, vector 0 -Key: 800000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 1B6220D365C2176C1D41A5826520FCA1 -Test: Encrypt -Comment: Set 1, vector 1 -Key: 400000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0F6DAEEA95CFC8925F23AFA932DF489B -Test: Encrypt -Comment: Set 1, vector 2 -Key: 200000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7330199225AD384F8DD39582D61389BB -Test: Encrypt -Comment: Set 1, vector 3 -Key: 100000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 2CC5A47D5C62F70634E27BA332D37D53 -Test: Encrypt -Comment: Set 1, vector 4 -Key: 080000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: CDF1D23AB15E20AE8E9A2FE380920897 -Test: Encrypt -Comment: Set 1, vector 5 -Key: 040000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: CE995A8AF1FD7E0F5FA07ED654841EEE -Test: Encrypt -Comment: Set 1, vector 6 -Key: 020000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0678BA4335E44354363005F278AF83A4 -Test: Encrypt -Comment: Set 1, vector 7 -Key: 010000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 6162ED593434D738B44D642254066FB4 -Test: Encrypt -Comment: Set 1, vector 8 -Key: 008000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F7F146E61396EC9AB9F7D04BFA6D37F5 -Test: Encrypt -Comment: Set 1, vector 9 -Key: 004000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 8BF96FE41906AF2CC702726B963E56A6 -Test: Encrypt -Comment: Set 1, vector 10 -Key: 002000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B164168F7D6BADBCCBE19B2BCF4EAA91 -Test: Encrypt -Comment: Set 1, vector 11 -Key: 001000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 5A81508260797F7BCFD4E0DB62F5E3A7 -Test: Encrypt -Comment: Set 1, vector 12 -Key: 000800000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 36641169D53E61CB32B97B98C37DF262 -Test: Encrypt -Comment: Set 1, vector 13 -Key: 000400000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: EFFEC137ECEE5D439F8B21ACE1D863F8 -Test: Encrypt -Comment: Set 1, vector 14 -Key: 000200000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7462DEB8C153EECB6C78CE690E764B53 -Test: Encrypt -Comment: Set 1, vector 15 -Key: 000100000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 34F873BD3D6FF62B18C3778B123B15C5 -Test: Encrypt -Comment: Set 1, vector 16 -Key: 000080000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 9850C8E08F952EE1D173B1A4A78686F5 -Test: Encrypt -Comment: Set 1, vector 17 -Key: 000040000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3285534795E8547B68580343DC5BF330 -Test: Encrypt -Comment: Set 1, vector 18 -Key: 000020000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E0495AA72CB3C27233850F3192254232 -Test: Encrypt -Comment: Set 1, vector 19 -Key: 000010000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 33ED350E83B7FE34E74C22A883EC6728 -Test: Encrypt -Comment: Set 1, vector 20 -Key: 000008000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 912D73428CBA7F631AE577854C111C91 -Test: Encrypt -Comment: Set 1, vector 21 -Key: 000004000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 76E747DC49B25D8E6EBE5DE83980AB57 -Test: Encrypt -Comment: Set 1, vector 22 -Key: 000002000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 82A2ED3BE0371C98C176AA7E7DF9FF8D -Test: Encrypt -Comment: Set 1, vector 23 -Key: 000001000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 96282A04DD3405294F9714B396D5219A -Test: Encrypt -Comment: Set 1, vector 24 -Key: 000000800000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 86ECD349003006A6DE29D4AAC1ACE296 -Test: Encrypt -Comment: Set 1, vector 25 -Key: 000000400000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7A9A9F2BBEA203ECE7C9F531B6D41B6A -Test: Encrypt -Comment: Set 1, vector 26 -Key: 000000200000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: BA5FE8CD976DEA118728C2950D325042 -Test: Encrypt -Comment: Set 1, vector 27 -Key: 000000100000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 46F29ADE35C839AE69454CB0C9EEBF71 -Test: Encrypt -Comment: Set 1, vector 28 -Key: 000000080000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E5B83E23535FC32DD8153C46EC894FAD -Test: Encrypt -Comment: Set 1, vector 29 -Key: 000000040000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 877CC6280A8E7740F710AEA535DADFD4 -Test: Encrypt -Comment: Set 1, vector 30 -Key: 000000020000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 284D6EEC89721D40BDCFD260AF4FF052 -Test: Encrypt -Comment: Set 1, vector 31 -Key: 000000010000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 6482ED6C71B60F1ED92B9913B5EAF6B3 -Test: Encrypt -Comment: Set 1, vector 32 -Key: 000000008000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 30135C97C9C23C8C64612D6BB813AD61 -Test: Encrypt -Comment: Set 1, vector 33 -Key: 000000004000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 336F70CF867920BBC00699CA8DBDF6DA -Test: Encrypt -Comment: Set 1, vector 34 -Key: 000000002000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3F4003C9600469670DE0B1B20ED5F33D -Test: Encrypt -Comment: Set 1, vector 35 -Key: 000000001000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 9D5FFEDF7166F74DCAF2D643E2934ABE -Test: Encrypt -Comment: Set 1, vector 36 -Key: 000000000800000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 9BFAC0EEB78A21F006DB6847CC7D7929 -Test: Encrypt -Comment: Set 1, vector 37 -Key: 000000000400000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B64332DC813BE982897C1E14DA808F5D -Test: Encrypt -Comment: Set 1, vector 38 -Key: 000000000200000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: AB8FCEB76C37E5FE5737DA4382F14347 -Test: Encrypt -Comment: Set 1, vector 39 -Key: 000000000100000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: C9C121859975147145AF6CAE313BA00D -Test: Encrypt -Comment: Set 1, vector 40 -Key: 000000000080000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 9B1307BF36B6FF5BA4AD9C6574B63955 -Test: Encrypt -Comment: Set 1, vector 41 -Key: 000000000040000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 8842C3EBB26C1863440D52DC3B26414B -Test: Encrypt -Comment: Set 1, vector 42 -Key: 000000000020000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: ADEADD3E035D591B2197D5B9C9B06ADA -Test: Encrypt -Comment: Set 1, vector 43 -Key: 000000000010000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 4F36AD57F9BA5FB6624E504D0FC2DC93 -Test: Encrypt -Comment: Set 1, vector 44 -Key: 000000000008000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 92A364EEB2D964949210C7FF14BAE7B5 -Test: Encrypt -Comment: Set 1, vector 45 -Key: 000000000004000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: EA027B9653456B8A41910FE19A90FD50 -Test: Encrypt -Comment: Set 1, vector 46 -Key: 000000000002000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 254A41CA04427C9E87F65BB52A0ACF74 -Test: Encrypt -Comment: Set 1, vector 47 -Key: 000000000001000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F935FD318C08AC6CD57A028384FA447B -Test: Encrypt -Comment: Set 1, vector 48 -Key: 000000000000800000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E5BA10850CBCFF8F42FEC0E658685096 -Test: Encrypt -Comment: Set 1, vector 49 -Key: 000000000000400000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 6F145C7015923CE515D78CEF0157CCC6 -Test: Encrypt -Comment: Set 1, vector 50 -Key: 000000000000200000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3A6FCA03EA6DBF6996FD2CE99EC17C31 -Test: Encrypt -Comment: Set 1, vector 51 -Key: 000000000000100000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 21E2ED82498B110EAEAD90F1BBEA03A6 -Test: Encrypt -Comment: Set 1, vector 52 -Key: 000000000000080000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 6B16ED3CBADC3151323891C373C43DFB -Test: Encrypt -Comment: Set 1, vector 53 -Key: 000000000000040000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B621A20E0CA41620C2A483154DB6102C -Test: Encrypt -Comment: Set 1, vector 54 -Key: 000000000000020000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 8C754011BD3B87AA1EB3607B98E6CE86 -Test: Encrypt -Comment: Set 1, vector 55 -Key: 000000000000010000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: FEEE2DFBA1DD3DBF4017B13833117816 -Test: Encrypt -Comment: Set 1, vector 56 -Key: 000000000000008000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 62A9C6CC76519FCF8FAD9EED0552CEB3 -Test: Encrypt -Comment: Set 1, vector 57 -Key: 000000000000004000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: FF822FAFB79035AB813246BA5234D675 -Test: Encrypt -Comment: Set 1, vector 58 -Key: 000000000000002000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F3E17F2406DF31E7074DF97B062396B9 -Test: Encrypt -Comment: Set 1, vector 59 -Key: 000000000000001000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3F4F81B3573B6756ADD3005087EDE501 -Test: Encrypt -Comment: Set 1, vector 60 -Key: 000000000000000800000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 65A03A1A1C44191B73D576B7C75B5C32 -Test: Encrypt -Comment: Set 1, vector 61 -Key: 000000000000000400000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B08EBB2097DA76C34E2D8A869DCD3D7D -Test: Encrypt -Comment: Set 1, vector 62 -Key: 000000000000000200000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: BA7B88E1B1FCFA03C3DBB2EDE047F5DC -Test: Encrypt -Comment: Set 1, vector 63 -Key: 000000000000000100000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 1B3CB3884C12691CC66202EDB0838106 -Test: Encrypt -Comment: Set 1, vector 64 -Key: 000000000000000080000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 4A85BE25546958B1E91801A35C7386E2 -Test: Encrypt -Comment: Set 1, vector 65 -Key: 000000000000000040000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F14CAACDD919872396DBCDCBEF9A384C -Test: Encrypt -Comment: Set 1, vector 66 -Key: 000000000000000020000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 23B0D4FC870309DFEF7AFC04C46AF26A -Test: Encrypt -Comment: Set 1, vector 67 -Key: 000000000000000010000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: C93604723C3DBBC66AFF87AB1864C76C -Test: Encrypt -Comment: Set 1, vector 68 -Key: 000000000000000008000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 6C14E822857BA0983AAC42995D973092 -Test: Encrypt -Comment: Set 1, vector 69 -Key: 000000000000000004000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 700AFEA175DBEAE688F90B8D32990560 -Test: Encrypt -Comment: Set 1, vector 70 -Key: 000000000000000002000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 54AE9EFA09FC70A852212752B83AF1F2 -Test: Encrypt -Comment: Set 1, vector 71 -Key: 000000000000000001000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 2474EF8E660333FC9763E137DDB1AA1F -Test: Encrypt -Comment: Set 1, vector 72 -Key: 000000000000000000800000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E52ECE1281186644B6A2228A89BD2304 -Test: Encrypt -Comment: Set 1, vector 73 -Key: 000000000000000000400000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 610A02ECEC1B5BA0C6EC7CE8D6197722 -Test: Encrypt -Comment: Set 1, vector 74 -Key: 000000000000000000200000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 8A8AB3DA5CE37E1D68B496F110E4F941 -Test: Encrypt -Comment: Set 1, vector 75 -Key: 000000000000000000100000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 6961F3A7E6550753C55E4C03FA7869E9 -Test: Encrypt -Comment: Set 1, vector 76 -Key: 000000000000000000080000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: D8F149C207FAD4480BA2FC609BEB4471 -Test: Encrypt -Comment: Set 1, vector 77 -Key: 000000000000000000040000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: DE9DC95336F2088935881DD57C0A4B98 -Test: Encrypt -Comment: Set 1, vector 78 -Key: 000000000000000000020000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: DC4EA3B0F76439DB8847FE61C1A64F7A -Test: Encrypt -Comment: Set 1, vector 79 -Key: 000000000000000000010000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 21D4802EB72232AD2B0B46C50C98445B -Test: Encrypt -Comment: Set 1, vector 80 -Key: 000000000000000000008000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: D6C32522B546BAC316E5F3A07F83FFE6 -Test: Encrypt -Comment: Set 1, vector 81 -Key: 000000000000000000004000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 4B07B02C86B579A0C68D916DF8A1EB76 -Test: Encrypt -Comment: Set 1, vector 82 -Key: 000000000000000000002000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 060B15735C978DF9F4F3ED503B95D6C3 -Test: Encrypt -Comment: Set 1, vector 83 -Key: 000000000000000000001000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3040B3C9C560C968FE14664E3496D5D1 -Test: Encrypt -Comment: Set 1, vector 84 -Key: 000000000000000000000800000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 8971CFB236598BBD46E47E172B0690F7 -Test: Encrypt -Comment: Set 1, vector 85 -Key: 000000000000000000000400000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 8D7FAB4985A0BAC4CAEE341972D49CF4 -Test: Encrypt -Comment: Set 1, vector 86 -Key: 000000000000000000000200000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: ED29003D83CB7D7747C17A8691323021 -Test: Encrypt -Comment: Set 1, vector 87 -Key: 000000000000000000000100000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 98EBFDA32C99438F0A549B7BFAAC0635 -Test: Encrypt -Comment: Set 1, vector 88 -Key: 000000000000000000000080000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: A59AB8EAF03BCDFD7CB0A9650E59F27B -Test: Encrypt -Comment: Set 1, vector 89 -Key: 000000000000000000000040000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 71422297CE93952D46FFC27530D6255D -Test: Encrypt -Comment: Set 1, vector 90 -Key: 000000000000000000000020000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 519E2607543C3AFE49190EBCA12ADBBC -Test: Encrypt -Comment: Set 1, vector 91 -Key: 000000000000000000000010000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 8989C908C50E008E70EA5B897DC3544C -Test: Encrypt -Comment: Set 1, vector 92 -Key: 000000000000000000000008000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 981C174277F29F8DD06E1D4C97D9816F -Test: Encrypt -Comment: Set 1, vector 93 -Key: 000000000000000000000004000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0279DEC16A532E160AA5B4FF7682F696 -Test: Encrypt -Comment: Set 1, vector 94 -Key: 000000000000000000000002000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: C3BFFB31FCB0A61188DE9AA606CB286C -Test: Encrypt -Comment: Set 1, vector 95 -Key: 000000000000000000000001000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 5C1C4966B387A41D52F83BBF322D25DF -Test: Encrypt -Comment: Set 1, vector 96 -Key: 000000000000000000000000800000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 6602ECC6AF62EF1EB4D17E2487A64F7A -Test: Encrypt -Comment: Set 1, vector 97 -Key: 000000000000000000000000400000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 2DA725366BD7774BA235183CC9B273B4 -Test: Encrypt -Comment: Set 1, vector 98 -Key: 000000000000000000000000200000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 71B29CF87C313F0B89B75251EFC4FF7F -Test: Encrypt -Comment: Set 1, vector 99 -Key: 000000000000000000000000100000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 4D9BDBCBA04C54AEAA7F48470428ECA2 -Test: Encrypt -Comment: Set 1, vector 100 -Key: 000000000000000000000000080000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: C6BC53A3C6D6C8A6F12B97B151BFBB3F -Test: Encrypt -Comment: Set 1, vector 101 -Key: 000000000000000000000000040000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: FD3E8D6732BBC2AA13F03F9AB0BCEC14 -Test: Encrypt -Comment: Set 1, vector 102 -Key: 000000000000000000000000020000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7D5ED8FEF289FF7F8953278E0A0297A1 -Test: Encrypt -Comment: Set 1, vector 103 -Key: 000000000000000000000000010000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 84A20023EF5E31771802E8A2FFBA485B -Test: Encrypt -Comment: Set 1, vector 104 -Key: 000000000000000000000000008000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7BD6E573AE79F0FA9FE38ECF6011D756 -Test: Encrypt -Comment: Set 1, vector 105 -Key: 000000000000000000000000004000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: EB58EA6B6DE1282A7BB9EA1A2254A542 -Test: Encrypt -Comment: Set 1, vector 106 -Key: 000000000000000000000000002000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 30A697E325C4D3BEC8E69A2DAD2AE5BB -Test: Encrypt -Comment: Set 1, vector 107 -Key: 000000000000000000000000001000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3205F6FEAA38500AC74BE66FEDF3231E -Test: Encrypt -Comment: Set 1, vector 108 -Key: 000000000000000000000000000800000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 83C007676041E81B836886ABED807A71 -Test: Encrypt -Comment: Set 1, vector 109 -Key: 000000000000000000000000000400000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 24B33B3138855437CC11D3792A1FD00F -Test: Encrypt -Comment: Set 1, vector 110 -Key: 000000000000000000000000000200000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 26324D7E2C055366910464699D73608A -Test: Encrypt -Comment: Set 1, vector 111 -Key: 000000000000000000000000000100000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F9A94A959AE7CD2A9D5FB7274703906B -Test: Encrypt -Comment: Set 1, vector 112 -Key: 000000000000000000000000000080000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: AD13D85E47EFC76B67ED25791E119A5C -Test: Encrypt -Comment: Set 1, vector 113 -Key: 000000000000000000000000000040000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 5FB689176B296F2E579FC69A18FA07EB -Test: Encrypt -Comment: Set 1, vector 114 -Key: 000000000000000000000000000020000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 936DFBA0A052A299C195F34A66C0CEDF -Test: Encrypt -Comment: Set 1, vector 115 -Key: 000000000000000000000000000010000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 486C03278BB30F26D25AE0D6348C9491 -Test: Encrypt -Comment: Set 1, vector 116 -Key: 000000000000000000000000000008000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: FCE14E6CE2073B5E8D1572A1EC1BD502 -Test: Encrypt -Comment: Set 1, vector 117 -Key: 000000000000000000000000000004000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 5F15B8A64EDBF0E55C3B8BB67BC9B2E1 -Test: Encrypt -Comment: Set 1, vector 118 -Key: 000000000000000000000000000002000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7BDC738A342891C7BE06E87E12F71418 -Test: Encrypt -Comment: Set 1, vector 119 -Key: 000000000000000000000000000001000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 31C6FEDABBC8C8AD64C27505F02BC7CC -Test: Encrypt -Comment: Set 1, vector 120 -Key: 000000000000000000000000000000800000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 33CCD97EB8C3C06B7BCD16659E1F9837 -Test: Encrypt -Comment: Set 1, vector 121 -Key: 000000000000000000000000000000400000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 12C3089895D4A1C1D03DB0071F88AB1B -Test: Encrypt -Comment: Set 1, vector 122 -Key: 000000000000000000000000000000200000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 8EB4796C7F7C3B0858750EBE3BAA335C -Test: Encrypt -Comment: Set 1, vector 123 -Key: 000000000000000000000000000000100000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 67169AF324151E92C6B7C31687B83783 -Test: Encrypt -Comment: Set 1, vector 124 -Key: 000000000000000000000000000000080000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: AB0E10564D41594B55CE3D5B088D93B4 -Test: Encrypt -Comment: Set 1, vector 125 -Key: 000000000000000000000000000000040000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 45228986B08E63728239ADC9C249E475 -Test: Encrypt -Comment: Set 1, vector 126 -Key: 000000000000000000000000000000020000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: CA7E48D5A4CD15984CA9EF99EC789EFD -Test: Encrypt -Comment: Set 1, vector 127 -Key: 000000000000000000000000000000010000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B4DD56FF85F7ABBEB9E0F5AE6B0E491D -Test: Encrypt -Comment: Set 1, vector 128 -Key: 000000000000000000000000000000008000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 044BE36D2F5A3D0FEA74443538F55393 -Test: Encrypt -Comment: Set 1, vector 129 -Key: 000000000000000000000000000000004000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 531EC401FB7C3BFADF64BB08E0DD9992 -Test: Encrypt -Comment: Set 1, vector 130 -Key: 000000000000000000000000000000002000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: EA8D6B6963EC2267050F8CF5D1D1D939 -Test: Encrypt -Comment: Set 1, vector 131 -Key: 000000000000000000000000000000001000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: CF5D7F27462FF7415D4E5ECBAEE0797C -Test: Encrypt -Comment: Set 1, vector 132 -Key: 000000000000000000000000000000000800000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: DF28B8322D4B8606FF3EFF09D39697B0 -Test: Encrypt -Comment: Set 1, vector 133 -Key: 000000000000000000000000000000000400000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 956EF889AAB218E21FAF8E9CC2AE41F9 -Test: Encrypt -Comment: Set 1, vector 134 -Key: 000000000000000000000000000000000200000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: AD0CF3C46F420E96B876DD55515B4B80 -Test: Encrypt -Comment: Set 1, vector 135 -Key: 000000000000000000000000000000000100000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: EC8620D3B9B456633AD174573CF82ABD -Test: Encrypt -Comment: Set 1, vector 136 -Key: 000000000000000000000000000000000080000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: A7CC6C810C1433B8D130594A48A36F69 -Test: Encrypt -Comment: Set 1, vector 137 -Key: 000000000000000000000000000000000040000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B02C5AF13D523A2A62E9F3829F9E3364 -Test: Encrypt -Comment: Set 1, vector 138 -Key: 000000000000000000000000000000000020000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 5AC8368EC6150F08CC2C44DBA8A9D84F -Test: Encrypt -Comment: Set 1, vector 139 -Key: 000000000000000000000000000000000010000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3BD51735D6087217EEF17B40750D701F -Test: Encrypt -Comment: Set 1, vector 140 -Key: 000000000000000000000000000000000008000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 330CC76A5529364B08F722C6206214E7 -Test: Encrypt -Comment: Set 1, vector 141 -Key: 000000000000000000000000000000000004000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 13CA2152CB81267D8429670A8D983592 -Test: Encrypt -Comment: Set 1, vector 142 -Key: 000000000000000000000000000000000002000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3943D67CE79CB8519EB9A5D1021988ED -Test: Encrypt -Comment: Set 1, vector 143 -Key: 000000000000000000000000000000000001000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 642858D825E8640718ABE6174BD04A32 -Test: Encrypt -Comment: Set 1, vector 144 -Key: 000000000000000000000000000000000000800000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F22616DE88A4CCBF97CF2DB709237EC7 -Test: Encrypt -Comment: Set 1, vector 145 -Key: 000000000000000000000000000000000000400000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B90D7F6BF0D9FC11A01F2B33194806DB -Test: Encrypt -Comment: Set 1, vector 146 -Key: 000000000000000000000000000000000000200000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: C161D350DC897B210D0D0CE8CE78F4B4 -Test: Encrypt -Comment: Set 1, vector 147 -Key: 000000000000000000000000000000000000100000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 66E46482150E7CF9BCBE60AF7BCA6892 -Test: Encrypt -Comment: Set 1, vector 148 -Key: 000000000000000000000000000000000000080000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B17C912E085D8854F220555EB0FA89BD -Test: Encrypt -Comment: Set 1, vector 149 -Key: 000000000000000000000000000000000000040000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 6FD6A99633FBD3A6D238CADF37824AD2 -Test: Encrypt -Comment: Set 1, vector 150 -Key: 000000000000000000000000000000000000020000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 9DE6D76D9A7E4AAB7A58EECE0E153D73 -Test: Encrypt -Comment: Set 1, vector 151 -Key: 000000000000000000000000000000000000010000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B4716A7DB10E3B8D1475C7EFB929F93A -Test: Encrypt -Comment: Set 1, vector 152 -Key: 000000000000000000000000000000000000008000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3D0F65F16AD143FB2FABDF4DFE621398 -Test: Encrypt -Comment: Set 1, vector 153 -Key: 000000000000000000000000000000000000004000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 249F1415D963DE146F4141C200B81D1D -Test: Encrypt -Comment: Set 1, vector 154 -Key: 000000000000000000000000000000000000002000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 454CD7040ED3851C3894F6259CE0D3FE -Test: Encrypt -Comment: Set 1, vector 155 -Key: 000000000000000000000000000000000000001000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 4D613EE6FA78A573ECBE989A64193E0C -Test: Encrypt -Comment: Set 1, vector 156 -Key: 000000000000000000000000000000000000000800000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B39384E429291B9C22005BC9B3FF2DEF -Test: Encrypt -Comment: Set 1, vector 157 -Key: 000000000000000000000000000000000000000400000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 957D0B27740C952E45DB97C8814F49C0 -Test: Encrypt -Comment: Set 1, vector 158 -Key: 000000000000000000000000000000000000000200000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 2879F58F238865D877D8C276CA9E9102 -Test: Encrypt -Comment: Set 1, vector 159 -Key: 000000000000000000000000000000000000000100000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: EA5B920037608FC9D51F39488D4666F7 -Test: Encrypt -Comment: Set 1, vector 160 -Key: 000000000000000000000000000000000000000080000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7659A705ABCA25205078541E713088BC -Test: Encrypt -Comment: Set 1, vector 161 -Key: 000000000000000000000000000000000000000040000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 47E340BB8BF2E8E1015BEFB68C7B1100 -Test: Encrypt -Comment: Set 1, vector 162 -Key: 000000000000000000000000000000000000000020000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 777E3E572CA33076B2CB34226CC70158 -Test: Encrypt -Comment: Set 1, vector 163 -Key: 000000000000000000000000000000000000000010000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 1FEC7C6719C7CA2E9A981851C5CEE204 -Test: Encrypt -Comment: Set 1, vector 164 -Key: 000000000000000000000000000000000000000008000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 9AF07DABE083EFDA75708A36AEB74CAF -Test: Encrypt -Comment: Set 1, vector 165 -Key: 000000000000000000000000000000000000000004000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 5D1482F8EF9CB18911BB7F78BC3B89FC -Test: Encrypt -Comment: Set 1, vector 166 -Key: 000000000000000000000000000000000000000002000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 5242753E01D470DD8C2B73A986BA009F -Test: Encrypt -Comment: Set 1, vector 167 -Key: 000000000000000000000000000000000000000001000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 83AE5BC112B73AB7978D13DD534B770B -Test: Encrypt -Comment: Set 1, vector 168 -Key: 000000000000000000000000000000000000000000800000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 848EB7330A82B91D36FBEFF6E6CE1347 -Test: Encrypt -Comment: Set 1, vector 169 -Key: 000000000000000000000000000000000000000000400000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F1B14465EFFD3E14DD1BAC6E0FA4E5BD -Test: Encrypt -Comment: Set 1, vector 170 -Key: 000000000000000000000000000000000000000000200000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 5ACD25AA05AFD21F43F6A51709FD0B6A -Test: Encrypt -Comment: Set 1, vector 171 -Key: 000000000000000000000000000000000000000000100000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 12321AEFA53F1503E3A473F729388CBD -Test: Encrypt -Comment: Set 1, vector 172 -Key: 000000000000000000000000000000000000000000080000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 1602DBA20E2ACFDDCC78390B473B322B -Test: Encrypt -Comment: Set 1, vector 173 -Key: 000000000000000000000000000000000000000000040000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 14C1853C3CF3CDFCE3799D5C130138EC -Test: Encrypt -Comment: Set 1, vector 174 -Key: 000000000000000000000000000000000000000000020000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: DC17F9E8236350BDC285F9B2F88F670F -Test: Encrypt -Comment: Set 1, vector 175 -Key: 000000000000000000000000000000000000000000010000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: ABA03FEE8133DD4ED9B8194B643E20CE -Test: Encrypt -Comment: Set 1, vector 176 -Key: 000000000000000000000000000000000000000000008000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 5822E80530C7CECCE4F56CF1691B386F -Test: Encrypt -Comment: Set 1, vector 177 -Key: 000000000000000000000000000000000000000000004000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 25CFA6F1B9BE5E14DFAF87A44B3B2E3D -Test: Encrypt -Comment: Set 1, vector 178 -Key: 000000000000000000000000000000000000000000002000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 5ED866CBC298B4DEE46C1A02F958F1F5 -Test: Encrypt -Comment: Set 1, vector 179 -Key: 000000000000000000000000000000000000000000001000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: BD2B63C026EB0E58D26ED16D2ED64A3E -Test: Encrypt -Comment: Set 1, vector 180 -Key: 000000000000000000000000000000000000000000000800 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 9FFCFF9CF9E1483BC7971888246AF9FE -Test: Encrypt -Comment: Set 1, vector 181 -Key: 000000000000000000000000000000000000000000000400 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 367C409AEE218E02DEAC8751698BA1B8 -Test: Encrypt -Comment: Set 1, vector 182 -Key: 000000000000000000000000000000000000000000000200 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 248E3A3C0360B44C512A9AC3CAAEC21B -Test: Encrypt -Comment: Set 1, vector 183 -Key: 000000000000000000000000000000000000000000000100 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 49B47C542CA396260B53A34372985612 -Test: Encrypt -Comment: Set 1, vector 184 -Key: 000000000000000000000000000000000000000000000080 -Plaintext: 00000000000000000000000000000000 -Ciphertext: CE35FDBDBE086EA8A501A4571925A95F -Test: Encrypt -Comment: Set 1, vector 185 -Key: 000000000000000000000000000000000000000000000040 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 873442FAE891B0767220742B84A32A4E -Test: Encrypt -Comment: Set 1, vector 186 -Key: 000000000000000000000000000000000000000000000020 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 2C90E17AD13E4E84686BC5B369F0FA8F -Test: Encrypt -Comment: Set 1, vector 187 -Key: 000000000000000000000000000000000000000000000010 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0E7AAAA67D8593A9DFC55083B48B381A -Test: Encrypt -Comment: Set 1, vector 188 -Key: 000000000000000000000000000000000000000000000008 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 1D8B58EE529AB17B10AC15D0E6E7ECB2 -Test: Encrypt -Comment: Set 1, vector 189 -Key: 000000000000000000000000000000000000000000000004 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 1C10FAC725B905AD93B6F4B2430A8D18 -Test: Encrypt -Comment: Set 1, vector 190 -Key: 000000000000000000000000000000000000000000000002 -Plaintext: 00000000000000000000000000000000 -Ciphertext: D36CF625EE94AB029CD23253C77C0E15 -Test: Encrypt -Comment: Set 1, vector 191 -Key: 000000000000000000000000000000000000000000000001 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E37577F71E0E643C4D3F55219ABA1394 -Test: Encrypt -Comment: Set 2, vector 0 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 80000000000000000000000000000000 -Ciphertext: 3EB6CC5618EFC98455B5992050D474E7 -Test: Encrypt -Comment: Set 2, vector 1 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 40000000000000000000000000000000 -Ciphertext: A2C645044CBC74DE5A4A161C6B2E98B9 -Test: Encrypt -Comment: Set 2, vector 2 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 20000000000000000000000000000000 -Ciphertext: 36A9A8C164BD90D4972AB1BE56C96A0B -Test: Encrypt -Comment: Set 2, vector 3 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 10000000000000000000000000000000 -Ciphertext: 38965592D728F9B765140C0A36A1BCCD -Test: Encrypt -Comment: Set 2, vector 4 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 08000000000000000000000000000000 -Ciphertext: 94CDECA78E10827914A49B5AE7F15643 -Test: Encrypt -Comment: Set 2, vector 5 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 04000000000000000000000000000000 -Ciphertext: 11C0DF672B45CDCD311EB86A7560EDA1 -Test: Encrypt -Comment: Set 2, vector 6 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 02000000000000000000000000000000 -Ciphertext: 030CAA9B8DE6F8AB88882F9596D9B1B4 -Test: Encrypt -Comment: Set 2, vector 7 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 01000000000000000000000000000000 -Ciphertext: FA02C8D1CDDD08B1FE3650DBD8E43C4F -Test: Encrypt -Comment: Set 2, vector 8 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00800000000000000000000000000000 -Ciphertext: 10ACEC25736340600D712338357C7FD4 -Test: Encrypt -Comment: Set 2, vector 9 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00400000000000000000000000000000 -Ciphertext: BBEF172E9E18679C6546EA2D9357BDD1 -Test: Encrypt -Comment: Set 2, vector 10 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00200000000000000000000000000000 -Ciphertext: 707CF6F582F5921765DBC6E1C79C45B6 -Test: Encrypt -Comment: Set 2, vector 11 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00100000000000000000000000000000 -Ciphertext: 3E9206A85F9FE99CD5538FA196E58147 -Test: Encrypt -Comment: Set 2, vector 12 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00080000000000000000000000000000 -Ciphertext: 6758B118659E9BB40BB7DC8C3D15ECEC -Test: Encrypt -Comment: Set 2, vector 13 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00040000000000000000000000000000 -Ciphertext: 9BCA6C88B928C1B0F57F99866583A9BC -Test: Encrypt -Comment: Set 2, vector 14 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00020000000000000000000000000000 -Ciphertext: 53D60CF8CA0B41B3991EF892917FA26F -Test: Encrypt -Comment: Set 2, vector 15 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00010000000000000000000000000000 -Ciphertext: 49E438685E189FB95791C655FBF40B3B -Test: Encrypt -Comment: Set 2, vector 16 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00008000000000000000000000000000 -Ciphertext: 6BFE6661C074077EF95DC499CA30A6B9 -Test: Encrypt -Comment: Set 2, vector 17 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00004000000000000000000000000000 -Ciphertext: FE82A6754DD56ACBD1895F8257597B74 -Test: Encrypt -Comment: Set 2, vector 18 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00002000000000000000000000000000 -Ciphertext: AF4551CFCEAEF2AEE1933C4AB5F036F5 -Test: Encrypt -Comment: Set 2, vector 19 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00001000000000000000000000000000 -Ciphertext: 5175E53EA4CA77E085363B2948B77B17 -Test: Encrypt -Comment: Set 2, vector 20 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000800000000000000000000000000 -Ciphertext: 19F544B2B2AAE4AF00DE2853F83349A5 -Test: Encrypt -Comment: Set 2, vector 21 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000400000000000000000000000000 -Ciphertext: 45A4379AC855738F6FEE3AFFBB2D839F -Test: Encrypt -Comment: Set 2, vector 22 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000200000000000000000000000000 -Ciphertext: 73A390407DD07D4ABEB299A5051A8DD1 -Test: Encrypt -Comment: Set 2, vector 23 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000100000000000000000000000000 -Ciphertext: 923B1E3525217E5C7A41CE3BCAE7C083 -Test: Encrypt -Comment: Set 2, vector 24 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000080000000000000000000000000 -Ciphertext: F58098D6E68E975C922B05354C0E2094 -Test: Encrypt -Comment: Set 2, vector 25 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000040000000000000000000000000 -Ciphertext: 371631601CE2BED9B7706FA4254BBAE5 -Test: Encrypt -Comment: Set 2, vector 26 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000020000000000000000000000000 -Ciphertext: 794F34CD64B44095BAB5C470B36E60BE -Test: Encrypt -Comment: Set 2, vector 27 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000010000000000000000000000000 -Ciphertext: 1A4CE8CBFEDB4F64B1A64D926B9BE3A1 -Test: Encrypt -Comment: Set 2, vector 28 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000008000000000000000000000000 -Ciphertext: 11C391C85F8FCF72EB03E1C4CC40B529 -Test: Encrypt -Comment: Set 2, vector 29 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000004000000000000000000000000 -Ciphertext: 9D8ADDC48EC36BB449234C7C06BEDC0F -Test: Encrypt -Comment: Set 2, vector 30 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000002000000000000000000000000 -Ciphertext: 952A1FAD7FAEA148FA31B50C244CF5C4 -Test: Encrypt -Comment: Set 2, vector 31 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000001000000000000000000000000 -Ciphertext: 613E5E9BBBF1B9943B3B5CBD3E69C98F -Test: Encrypt -Comment: Set 2, vector 32 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000800000000000000000000000 -Ciphertext: 5ABF9CB600BB50DB64211DE2DEAEEDBA -Test: Encrypt -Comment: Set 2, vector 33 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000400000000000000000000000 -Ciphertext: 14697658FDA5B1F14C3303F5951CAE70 -Test: Encrypt -Comment: Set 2, vector 34 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000200000000000000000000000 -Ciphertext: 2A29179C05F2F5F5909A34130B92BB25 -Test: Encrypt -Comment: Set 2, vector 35 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000100000000000000000000000 -Ciphertext: 60A9DAB8068CC085F3B9853D0C1FCF07 -Test: Encrypt -Comment: Set 2, vector 36 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000080000000000000000000000 -Ciphertext: D625356ACCE7B9F874754AE52FD1C7BF -Test: Encrypt -Comment: Set 2, vector 37 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000040000000000000000000000 -Ciphertext: 31196A29DAA0A41E982819C26AF0567A -Test: Encrypt -Comment: Set 2, vector 38 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000020000000000000000000000 -Ciphertext: D1763FC019D77CC930BFF2A56F7C9364 -Test: Encrypt -Comment: Set 2, vector 39 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000010000000000000000000000 -Ciphertext: BBC9D3C96666B01D0C33CC067ADDA228 -Test: Encrypt -Comment: Set 2, vector 40 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000008000000000000000000000 -Ciphertext: 4FC9284574F433DD6C5ADEAB6DC64A06 -Test: Encrypt -Comment: Set 2, vector 41 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000004000000000000000000000 -Ciphertext: 7176B9E3628380ADDCF02493DB254B01 -Test: Encrypt -Comment: Set 2, vector 42 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000002000000000000000000000 -Ciphertext: C6B124A17B3AB55A983DC2B6E8253FF1 -Test: Encrypt -Comment: Set 2, vector 43 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000001000000000000000000000 -Ciphertext: 5853A6B6AB0FC47DEBA33526B628DF6E -Test: Encrypt -Comment: Set 2, vector 44 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000800000000000000000000 -Ciphertext: 416945C1D1902238C42955CFF166D705 -Test: Encrypt -Comment: Set 2, vector 45 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000400000000000000000000 -Ciphertext: 2478F40DC7B7FA98E59DA21F1D2140F9 -Test: Encrypt -Comment: Set 2, vector 46 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000200000000000000000000 -Ciphertext: 6A912316499FBECA17D1683EAF79FDC9 -Test: Encrypt -Comment: Set 2, vector 47 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000100000000000000000000 -Ciphertext: 8A41DB2271FD345BC1DDE61A427E4E3E -Test: Encrypt -Comment: Set 2, vector 48 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000080000000000000000000 -Ciphertext: B6C62C6A14D2276C8FE8D1062C1E8080 -Test: Encrypt -Comment: Set 2, vector 49 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000040000000000000000000 -Ciphertext: D23F90169810210A45BD9B8681B24C34 -Test: Encrypt -Comment: Set 2, vector 50 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000020000000000000000000 -Ciphertext: EDB2A77815A074B50D88C6C2B15AF814 -Test: Encrypt -Comment: Set 2, vector 51 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000010000000000000000000 -Ciphertext: 2D6D81C8FDD2C7D5B98317488846969D -Test: Encrypt -Comment: Set 2, vector 52 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000008000000000000000000 -Ciphertext: 92F2805613A82EE25568B32ED7550DCC -Test: Encrypt -Comment: Set 2, vector 53 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000004000000000000000000 -Ciphertext: E321480A1DE5F36040F1FD170F24802B -Test: Encrypt -Comment: Set 2, vector 54 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000002000000000000000000 -Ciphertext: 3188FFADE35652067E6E2228130762D6 -Test: Encrypt -Comment: Set 2, vector 55 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000001000000000000000000 -Ciphertext: B3A3A43D68A82EC54B5D437346375584 -Test: Encrypt -Comment: Set 2, vector 56 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000800000000000000000 -Ciphertext: 023ECF3BD9FEB4891366ABE45EC1728B -Test: Encrypt -Comment: Set 2, vector 57 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000400000000000000000 -Ciphertext: 50D8160676748E1718A030F4F512C1C2 -Test: Encrypt -Comment: Set 2, vector 58 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000200000000000000000 -Ciphertext: 30DF20541978D9C96D43D609DEF39C00 -Test: Encrypt -Comment: Set 2, vector 59 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000100000000000000000 -Ciphertext: BA1AA1682750C0CEB2A87E1A46A7CE0E -Test: Encrypt -Comment: Set 2, vector 60 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000080000000000000000 -Ciphertext: 03AC8261D8F98C90B9CE9C9E47A39AA5 -Test: Encrypt -Comment: Set 2, vector 61 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000040000000000000000 -Ciphertext: 4C6C2FDC2693F2A43EAEB180AD8190F8 -Test: Encrypt -Comment: Set 2, vector 62 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000020000000000000000 -Ciphertext: B65D2C8CEE12BB4FA127356632CB0ECA -Test: Encrypt -Comment: Set 2, vector 63 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000010000000000000000 -Ciphertext: 6D785867F379BCE03580ED9DE83C0EFD -Test: Encrypt -Comment: Set 2, vector 64 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000008000000000000000 -Ciphertext: D2B25B3EECB454DCE070D11C408D73B2 -Test: Encrypt -Comment: Set 2, vector 65 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000004000000000000000 -Ciphertext: 8035FF5E625955D6328F570D53188C0C -Test: Encrypt -Comment: Set 2, vector 66 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000002000000000000000 -Ciphertext: A8BECF868B0D964E04012BE5F8121A9C -Test: Encrypt -Comment: Set 2, vector 67 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000001000000000000000 -Ciphertext: AA76DF2E83C0D31ECFE66A62E16A91D3 -Test: Encrypt -Comment: Set 2, vector 68 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000800000000000000 -Ciphertext: BAA324177EA5AF61ADBD27F594297278 -Test: Encrypt -Comment: Set 2, vector 69 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000400000000000000 -Ciphertext: 40BBEB33938AFA9BD566991B53B0FDA7 -Test: Encrypt -Comment: Set 2, vector 70 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000200000000000000 -Ciphertext: 6F58204780BEA9102506C477CBB3C8FE -Test: Encrypt -Comment: Set 2, vector 71 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000100000000000000 -Ciphertext: D296BCA9261A3410E47FA289BD70B955 -Test: Encrypt -Comment: Set 2, vector 72 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000080000000000000 -Ciphertext: 4C57FB4234A64462C6D441A782723777 -Test: Encrypt -Comment: Set 2, vector 73 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000040000000000000 -Ciphertext: 33478DE51DBDA949E17CB82373DAF866 -Test: Encrypt -Comment: Set 2, vector 74 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000020000000000000 -Ciphertext: 7CC11B9A6A9E2CE13D3596686C624AF0 -Test: Encrypt -Comment: Set 2, vector 75 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000010000000000000 -Ciphertext: 0C55ACA2BDA80E8F84A3879FF077802A -Test: Encrypt -Comment: Set 2, vector 76 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000008000000000000 -Ciphertext: 885B84843BADC6501CBDCBEA4386AB7F -Test: Encrypt -Comment: Set 2, vector 77 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000004000000000000 -Ciphertext: DCF23815FEF1697B0618E205B637648A -Test: Encrypt -Comment: Set 2, vector 78 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000002000000000000 -Ciphertext: BF5EBE09157E65743AAD033473B0DFED -Test: Encrypt -Comment: Set 2, vector 79 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000001000000000000 -Ciphertext: 1E9E5E1032307B75915E9BD48205FEB8 -Test: Encrypt -Comment: Set 2, vector 80 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000800000000000 -Ciphertext: 0EB8AC09A10303A7CE9762C1B029F0E0 -Test: Encrypt -Comment: Set 2, vector 81 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000400000000000 -Ciphertext: 2A42627713BFC603A88AD1D66292B80C -Test: Encrypt -Comment: Set 2, vector 82 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000200000000000 -Ciphertext: D7E9512485B9E5E409FB51E26D269795 -Test: Encrypt -Comment: Set 2, vector 83 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000100000000000 -Ciphertext: 57CC59F8B92D73E1B38EEE405A8EC12F -Test: Encrypt -Comment: Set 2, vector 84 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000080000000000 -Ciphertext: 161783F5FFC9A383E36B80A2032A71F1 -Test: Encrypt -Comment: Set 2, vector 85 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000040000000000 -Ciphertext: F5B24CE20FFD8702AC63F9C844BC5730 -Test: Encrypt -Comment: Set 2, vector 86 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000020000000000 -Ciphertext: 440930601D4013076587D882A1958280 -Test: Encrypt -Comment: Set 2, vector 87 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000010000000000 -Ciphertext: AEA4C3F9E520651C5FE38B915423843F -Test: Encrypt -Comment: Set 2, vector 88 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000008000000000 -Ciphertext: E300D7417C4F547DBCD5FC84E3833A7B -Test: Encrypt -Comment: Set 2, vector 89 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000004000000000 -Ciphertext: 5543860CE9247B38E8D0E7B216C0B5A5 -Test: Encrypt -Comment: Set 2, vector 90 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000002000000000 -Ciphertext: C20449053BF90C899899EE02794DB3C5 -Test: Encrypt -Comment: Set 2, vector 91 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000001000000000 -Ciphertext: AC0CB3B34AC32244CF196AE49E94D380 -Test: Encrypt -Comment: Set 2, vector 92 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000800000000 -Ciphertext: 0CDF3F25852287E3BAFAF490DE18D125 -Test: Encrypt -Comment: Set 2, vector 93 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000400000000 -Ciphertext: 583BB44512CE75268F72E6BC6682901B -Test: Encrypt -Comment: Set 2, vector 94 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000200000000 -Ciphertext: 217140522F0C505FDAC4BFDE6E9D9A81 -Test: Encrypt -Comment: Set 2, vector 95 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000100000000 -Ciphertext: CFA59EB13DDD780A2EAEF89E83737C9A -Test: Encrypt -Comment: Set 2, vector 96 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000080000000 -Ciphertext: 75E473CCD4D116426753B44900D919A6 -Test: Encrypt -Comment: Set 2, vector 97 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000040000000 -Ciphertext: E15E4627F7F8A3F09424D3D5CAC1C777 -Test: Encrypt -Comment: Set 2, vector 98 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000020000000 -Ciphertext: B83E20A23802D8755A2E850242B64EEF -Test: Encrypt -Comment: Set 2, vector 99 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000010000000 -Ciphertext: E6790AF3911360F28FD17886DD311F88 -Test: Encrypt -Comment: Set 2, vector 100 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000008000000 -Ciphertext: 0A6304DF33E409C8A21E1C19187183FF -Test: Encrypt -Comment: Set 2, vector 101 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000004000000 -Ciphertext: 51966561DA7ED5F30130B55CD108B5BE -Test: Encrypt -Comment: Set 2, vector 102 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000002000000 -Ciphertext: 0ECA40693BF4CB41FDD15BCFD8C9D9B9 -Test: Encrypt -Comment: Set 2, vector 103 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000001000000 -Ciphertext: 8731B42742ADBA2D89C9BA90EBD4E42A -Test: Encrypt -Comment: Set 2, vector 104 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000800000 -Ciphertext: BE4C6C18AA231E9BB13909242CC92EE3 -Test: Encrypt -Comment: Set 2, vector 105 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000400000 -Ciphertext: 39AC45537E9AFDC6C8BDD4204039A218 -Test: Encrypt -Comment: Set 2, vector 106 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000200000 -Ciphertext: AEA354F16E1E8EECEB5A98D88418B1A0 -Test: Encrypt -Comment: Set 2, vector 107 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000100000 -Ciphertext: 4F5D37D7D0DC7714E62BE4A0331DB07B -Test: Encrypt -Comment: Set 2, vector 108 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000080000 -Ciphertext: 9603F03C3CAA8C2F0ECFBA1374891007 -Test: Encrypt -Comment: Set 2, vector 109 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000040000 -Ciphertext: C58768944996884B46A8FFDDB9AB87EF -Test: Encrypt -Comment: Set 2, vector 110 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000020000 -Ciphertext: 3BCCF2396A97FC1C0CFFFB6ED41716DB -Test: Encrypt -Comment: Set 2, vector 111 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000010000 -Ciphertext: DC299278DCA45AC1B6B08ED4B62D9BC9 -Test: Encrypt -Comment: Set 2, vector 112 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000008000 -Ciphertext: E195AECA31E10241BD0EC4AC5418A25D -Test: Encrypt -Comment: Set 2, vector 113 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000004000 -Ciphertext: B397A4983ED647A0EB806ACDFE7BCB34 -Test: Encrypt -Comment: Set 2, vector 114 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000002000 -Ciphertext: BC8F7224B0447E8A1CF0F5506A060F3C -Test: Encrypt -Comment: Set 2, vector 115 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000001000 -Ciphertext: FFD3ED02E7F64A5D6B37A9DC5E531646 -Test: Encrypt -Comment: Set 2, vector 116 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000800 -Ciphertext: BC6019EB208B7AF8EFA6AE7B4CA0556B -Test: Encrypt -Comment: Set 2, vector 117 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000400 -Ciphertext: D2915AE2779F8F70E17CE953C6C1A380 -Test: Encrypt -Comment: Set 2, vector 118 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000200 -Ciphertext: B2AA4B1ED2285C9DA4088B6E9681C690 -Test: Encrypt -Comment: Set 2, vector 119 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000100 -Ciphertext: BE0D64EA88A3FF27C8DFCE13F13A4E1F -Test: Encrypt -Comment: Set 2, vector 120 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000080 -Ciphertext: D7629F1DD395A985AF9497F6ACB4EDA1 -Test: Encrypt -Comment: Set 2, vector 121 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000040 -Ciphertext: 33FDF72DA1D8815DE2DBE81D97DDC6F8 -Test: Encrypt -Comment: Set 2, vector 122 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000020 -Ciphertext: D35742045F3DF8D184D6CC58EB9DE323 -Test: Encrypt -Comment: Set 2, vector 123 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000010 -Ciphertext: DE6469D10C044ED53CFEB523C8DF34A2 -Test: Encrypt -Comment: Set 2, vector 124 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000008 -Ciphertext: 2FAEAC3A41CCEABA8140BDA9C7AC7740 -Test: Encrypt -Comment: Set 2, vector 125 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000004 -Ciphertext: 7BA6691787BF0C526F3697E2ED659B0D -Test: Encrypt -Comment: Set 2, vector 126 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000002 -Ciphertext: 8F9C0AA2549714C88BB2665E8AF86D41 -Test: Encrypt -Comment: Set 2, vector 127 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000001 -Ciphertext: BA9AE89FDDCE4B51131E17C4D65CE587 -Test: Encrypt -Comment: Set 3, vector 0 -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 56E1E129CA5C02C7F9AC6AFDEF86ADC3 -Test: Encrypt -Comment: Set 3, vector 1 -Key: 010101010101010101010101010101010101010101010101 -Plaintext: 01010101010101010101010101010101 -Ciphertext: 8F764397C10BE84BA876CEEFA4225BFF -Test: Encrypt -Comment: Set 3, vector 2 -Key: 020202020202020202020202020202020202020202020202 -Plaintext: 02020202020202020202020202020202 -Ciphertext: 60B00674BFD444D07B5A19851E6151CD -Test: Encrypt -Comment: Set 3, vector 3 -Key: 030303030303030303030303030303030303030303030303 -Plaintext: 03030303030303030303030303030303 -Ciphertext: CF431D70E25D5450B9979C52E4ECF590 -Test: Encrypt -Comment: Set 3, vector 4 -Key: 040404040404040404040404040404040404040404040404 -Plaintext: 04040404040404040404040404040404 -Ciphertext: 81B26FF4F6B4377CC555873504B3A38B -Test: Encrypt -Comment: Set 3, vector 5 -Key: 050505050505050505050505050505050505050505050505 -Plaintext: 05050505050505050505050505050505 -Ciphertext: 8C864C445E6B9312E6F3843C53BF7870 -Test: Encrypt -Comment: Set 3, vector 6 -Key: 060606060606060606060606060606060606060606060606 -Plaintext: 06060606060606060606060606060606 -Ciphertext: 28C1EABB23C2A04E7A37BB0EF42D45A2 -Test: Encrypt -Comment: Set 3, vector 7 -Key: 070707070707070707070707070707070707070707070707 -Plaintext: 07070707070707070707070707070707 -Ciphertext: 0068C08827CBD904A3C0AF89A35CD8E6 -Test: Encrypt -Comment: Set 3, vector 8 -Key: 080808080808080808080808080808080808080808080808 -Plaintext: 08080808080808080808080808080808 -Ciphertext: A2AA1C6693DC2B70D75C9B39B9B214D0 -Test: Encrypt -Comment: Set 3, vector 9 -Key: 090909090909090909090909090909090909090909090909 -Plaintext: 09090909090909090909090909090909 -Ciphertext: 0423A756A133734C66944536033B978C -Test: Encrypt -Comment: Set 3, vector 10 -Key: 0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A -Plaintext: 0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A -Ciphertext: 279B7FA09352F4194B2C33089267BD2E -Test: Encrypt -Comment: Set 3, vector 11 -Key: 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B -Plaintext: 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B -Ciphertext: 7788EEE46AC2927434A93D3B5D295DF3 -Test: Encrypt -Comment: Set 3, vector 12 -Key: 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C -Plaintext: 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C -Ciphertext: 3A2D0C1F30AE1E50A61102D2DF5BEAE5 -Test: Encrypt -Comment: Set 3, vector 13 -Key: 0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D -Plaintext: 0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D -Ciphertext: 320FB708B47319484538CD73F8773526 -Test: Encrypt -Comment: Set 3, vector 14 -Key: 0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E -Plaintext: 0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E -Ciphertext: 6213EB688C8CDA5152A65BFC007BCAEA -Test: Encrypt -Comment: Set 3, vector 15 -Key: 0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F -Plaintext: 0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F -Ciphertext: D1904ACDB021DDCCCBE436CA7B5A4264 -Test: Encrypt -Comment: Set 3, vector 16 -Key: 101010101010101010101010101010101010101010101010 -Plaintext: 10101010101010101010101010101010 -Ciphertext: A907BFDAEEF8C81D05855235E8D3BE08 -Test: Encrypt -Comment: Set 3, vector 17 -Key: 111111111111111111111111111111111111111111111111 -Plaintext: 11111111111111111111111111111111 -Ciphertext: DB23D9326A998A4CB06AE04A8C592217 -Test: Encrypt -Comment: Set 3, vector 18 -Key: 121212121212121212121212121212121212121212121212 -Plaintext: 12121212121212121212121212121212 -Ciphertext: 472427C234EAE3082E84F493C9559792 -Test: Encrypt -Comment: Set 3, vector 19 -Key: 131313131313131313131313131313131313131313131313 -Plaintext: 13131313131313131313131313131313 -Ciphertext: EE4E318D27820F691BD3BDA9617561A0 -Test: Encrypt -Comment: Set 3, vector 20 -Key: 141414141414141414141414141414141414141414141414 -Plaintext: 14141414141414141414141414141414 -Ciphertext: 221E909D7B259C098480DBDE71BCF9BF -Test: Encrypt -Comment: Set 3, vector 21 -Key: 151515151515151515151515151515151515151515151515 -Plaintext: 15151515151515151515151515151515 -Ciphertext: 8702C6A150F2DD2E1736F09518C1A267 -Test: Encrypt -Comment: Set 3, vector 22 -Key: 161616161616161616161616161616161616161616161616 -Plaintext: 16161616161616161616161616161616 -Ciphertext: 7E8DAEBBA15C7B9705B501998F61CC6E -Test: Encrypt -Comment: Set 3, vector 23 -Key: 171717171717171717171717171717171717171717171717 -Plaintext: 17171717171717171717171717171717 -Ciphertext: 3DD555C7277FA156330D05CD621394D5 -Test: Encrypt -Comment: Set 3, vector 24 -Key: 181818181818181818181818181818181818181818181818 -Plaintext: 18181818181818181818181818181818 -Ciphertext: E5575CDC315F1C244441E6D1DE25ED20 -Test: Encrypt -Comment: Set 3, vector 25 -Key: 191919191919191919191919191919191919191919191919 -Plaintext: 19191919191919191919191919191919 -Ciphertext: 434859EB42087F83B9849DC23ABB7C1D -Test: Encrypt -Comment: Set 3, vector 26 -Key: 1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A -Plaintext: 1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A -Ciphertext: 1EA1A5CC662DCA0B56B2BBF560A1B032 -Test: Encrypt -Comment: Set 3, vector 27 -Key: 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B -Plaintext: 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B -Ciphertext: A3AC0CD9342242A72005F8E6DBF50DE8 -Test: Encrypt -Comment: Set 3, vector 28 -Key: 1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C -Plaintext: 1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C -Ciphertext: AF6251A285EBEA9408315822F2072D86 -Test: Encrypt -Comment: Set 3, vector 29 -Key: 1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D -Plaintext: 1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D -Ciphertext: FA084220DB82A88E6D7B6E7849550183 -Test: Encrypt -Comment: Set 3, vector 30 -Key: 1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E -Plaintext: 1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E -Ciphertext: E7AABEAA3F669E0D963A19C3BDE43676 -Test: Encrypt -Comment: Set 3, vector 31 -Key: 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F -Plaintext: 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F -Ciphertext: ED7C11A689A72FF834A777013DBEC50A -Test: Encrypt -Comment: Set 3, vector 32 -Key: 202020202020202020202020202020202020202020202020 -Plaintext: 20202020202020202020202020202020 -Ciphertext: 87F8EA30332036F17CEAC0097CE33BC1 -Test: Encrypt -Comment: Set 3, vector 33 -Key: 212121212121212121212121212121212121212121212121 -Plaintext: 21212121212121212121212121212121 -Ciphertext: E83CC178B21703D1BDFA0A1350A587F3 -Test: Encrypt -Comment: Set 3, vector 34 -Key: 222222222222222222222222222222222222222222222222 -Plaintext: 22222222222222222222222222222222 -Ciphertext: 581CF260A93B67E27BBA6D6D68C645B6 -Test: Encrypt -Comment: Set 3, vector 35 -Key: 232323232323232323232323232323232323232323232323 -Plaintext: 23232323232323232323232323232323 -Ciphertext: D7155FD4BABA5DAA1E0576BAF4BB3BDE -Test: Encrypt -Comment: Set 3, vector 36 -Key: 242424242424242424242424242424242424242424242424 -Plaintext: 24242424242424242424242424242424 -Ciphertext: 0C2382377892DC0CA4B1C7753CDB2753 -Test: Encrypt -Comment: Set 3, vector 37 -Key: 252525252525252525252525252525252525252525252525 -Plaintext: 25252525252525252525252525252525 -Ciphertext: 9E568ACFE44E1926BE207D25107EBD90 -Test: Encrypt -Comment: Set 3, vector 38 -Key: 262626262626262626262626262626262626262626262626 -Plaintext: 26262626262626262626262626262626 -Ciphertext: 1F9C7FEF0BA7D4C38555B957FA9FDAC8 -Test: Encrypt -Comment: Set 3, vector 39 -Key: 272727272727272727272727272727272727272727272727 -Plaintext: 27272727272727272727272727272727 -Ciphertext: 2C00730AAB18247D4F79C8BA0107E759 -Test: Encrypt -Comment: Set 3, vector 40 -Key: 282828282828282828282828282828282828282828282828 -Plaintext: 28282828282828282828282828282828 -Ciphertext: 26150BB68C5529903D3624CB8F36D717 -Test: Encrypt -Comment: Set 3, vector 41 -Key: 292929292929292929292929292929292929292929292929 -Plaintext: 29292929292929292929292929292929 -Ciphertext: C6F9CD75F9DC3DF5C945E028038660AB -Test: Encrypt -Comment: Set 3, vector 42 -Key: 2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A -Plaintext: 2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A -Ciphertext: 9D90F692A1149E3E7F19BE419038F42F -Test: Encrypt -Comment: Set 3, vector 43 -Key: 2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B -Plaintext: 2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B -Ciphertext: 9981F6F8C071F4CAF3E25884B8749FD3 -Test: Encrypt -Comment: Set 3, vector 44 -Key: 2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C -Plaintext: 2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C -Ciphertext: 62957FC449C78B7EABA9C41B335F731E -Test: Encrypt -Comment: Set 3, vector 45 -Key: 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D -Plaintext: 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D -Ciphertext: 265E17BD08B2E34BC879D5BC801D1217 -Test: Encrypt -Comment: Set 3, vector 46 -Key: 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E -Plaintext: 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E -Ciphertext: 55BBE8CE99907AC77D4F009EABA6B8D9 -Test: Encrypt -Comment: Set 3, vector 47 -Key: 2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F -Plaintext: 2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F -Ciphertext: EECB495C2F81243857D0A1A8919F9C7E -Test: Encrypt -Comment: Set 3, vector 48 -Key: 303030303030303030303030303030303030303030303030 -Plaintext: 30303030303030303030303030303030 -Ciphertext: E3BA996DF81895C86E30500CE9F7ED01 -Test: Encrypt -Comment: Set 3, vector 49 -Key: 313131313131313131313131313131313131313131313131 -Plaintext: 31313131313131313131313131313131 -Ciphertext: E507914B7CDDB2A3A915EB5663CE43CE -Test: Encrypt -Comment: Set 3, vector 50 -Key: 323232323232323232323232323232323232323232323232 -Plaintext: 32323232323232323232323232323232 -Ciphertext: AA2E53FC2D073DE62554691F507B23FF -Test: Encrypt -Comment: Set 3, vector 51 -Key: 333333333333333333333333333333333333333333333333 -Plaintext: 33333333333333333333333333333333 -Ciphertext: 875707D7E4FA8028D878DFB8338160FF -Test: Encrypt -Comment: Set 3, vector 52 -Key: 343434343434343434343434343434343434343434343434 -Plaintext: 34343434343434343434343434343434 -Ciphertext: 1158285A6787F8B6500E9FB046D88FB7 -Test: Encrypt -Comment: Set 3, vector 53 -Key: 353535353535353535353535353535353535353535353535 -Plaintext: 35353535353535353535353535353535 -Ciphertext: 6BFF4FB554ADD3F4321E6BA6029CD48A -Test: Encrypt -Comment: Set 3, vector 54 -Key: 363636363636363636363636363636363636363636363636 -Plaintext: 36363636363636363636363636363636 -Ciphertext: 8F2077CE672419A3AE15CA8800D5ACF8 -Test: Encrypt -Comment: Set 3, vector 55 -Key: 373737373737373737373737373737373737373737373737 -Plaintext: 37373737373737373737373737373737 -Ciphertext: 80ECE69E3EEBD391FCAEA8B3B38578D9 -Test: Encrypt -Comment: Set 3, vector 56 -Key: 383838383838383838383838383838383838383838383838 -Plaintext: 38383838383838383838383838383838 -Ciphertext: A23A2ADDE21BDB44EF99072331FA8EAB -Test: Encrypt -Comment: Set 3, vector 57 -Key: 393939393939393939393939393939393939393939393939 -Plaintext: 39393939393939393939393939393939 -Ciphertext: 8E41065415264354D4DC276F6ED582B9 -Test: Encrypt -Comment: Set 3, vector 58 -Key: 3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A -Plaintext: 3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A -Ciphertext: D591D51BA578836C7D3945991FD0184A -Test: Encrypt -Comment: Set 3, vector 59 -Key: 3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B -Plaintext: 3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B -Ciphertext: B88105C11F9FFCA9037E1F90FAE1C61E -Test: Encrypt -Comment: Set 3, vector 60 -Key: 3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C -Plaintext: 3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C -Ciphertext: F8A1A047994B4363028BC1B3B6339954 -Test: Encrypt -Comment: Set 3, vector 61 -Key: 3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D -Plaintext: 3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D -Ciphertext: EFB57CEA359E1F9F68729B156BEBDCB8 -Test: Encrypt -Comment: Set 3, vector 62 -Key: 3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E -Plaintext: 3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E -Ciphertext: 2323D15570873D4E5616CDDC466B1D34 -Test: Encrypt -Comment: Set 3, vector 63 -Key: 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F -Plaintext: 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F -Ciphertext: 842C7B6C67BB38B508558058531B37FE -Test: Encrypt -Comment: Set 3, vector 64 -Key: 404040404040404040404040404040404040404040404040 -Plaintext: 40404040404040404040404040404040 -Ciphertext: A2C32EA499E41A248565253BACC11E3B -Test: Encrypt -Comment: Set 3, vector 65 -Key: 414141414141414141414141414141414141414141414141 -Plaintext: 41414141414141414141414141414141 -Ciphertext: CF72033A0BA3E03A8B1E336F85100489 -Test: Encrypt -Comment: Set 3, vector 66 -Key: 424242424242424242424242424242424242424242424242 -Plaintext: 42424242424242424242424242424242 -Ciphertext: 0A194208C1B722A5719C14231EE4C532 -Test: Encrypt -Comment: Set 3, vector 67 -Key: 434343434343434343434343434343434343434343434343 -Plaintext: 43434343434343434343434343434343 -Ciphertext: 7365018F7A2564165EC162F948C4824A -Test: Encrypt -Comment: Set 3, vector 68 -Key: 444444444444444444444444444444444444444444444444 -Plaintext: 44444444444444444444444444444444 -Ciphertext: 20AC87CE21C47D99D6D2202B0C62E52D -Test: Encrypt -Comment: Set 3, vector 69 -Key: 454545454545454545454545454545454545454545454545 -Plaintext: 45454545454545454545454545454545 -Ciphertext: 72D32F7C4D03529C7DBF6865E36E7C84 -Test: Encrypt -Comment: Set 3, vector 70 -Key: 464646464646464646464646464646464646464646464646 -Plaintext: 46464646464646464646464646464646 -Ciphertext: 18E88EF941A7D1793B8D545323CCBD7E -Test: Encrypt -Comment: Set 3, vector 71 -Key: 474747474747474747474747474747474747474747474747 -Plaintext: 47474747474747474747474747474747 -Ciphertext: C87B12CD28646842FCE0C8658EA8A6C9 -Test: Encrypt -Comment: Set 3, vector 72 -Key: 484848484848484848484848484848484848484848484848 -Plaintext: 48484848484848484848484848484848 -Ciphertext: 03347AC4B4D0AE9C208B1B12802E6562 -Test: Encrypt -Comment: Set 3, vector 73 -Key: 494949494949494949494949494949494949494949494949 -Plaintext: 49494949494949494949494949494949 -Ciphertext: A5F9E726E53A74C9CF59E7CBBCE507D1 -Test: Encrypt -Comment: Set 3, vector 74 -Key: 4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A -Plaintext: 4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A -Ciphertext: 228C852461BBB0BB12B3F9192311DFDD -Test: Encrypt -Comment: Set 3, vector 75 -Key: 4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B -Plaintext: 4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B -Ciphertext: DFD5B30B1401FBE49EA0C725E64B91A3 -Test: Encrypt -Comment: Set 3, vector 76 -Key: 4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C -Plaintext: 4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C -Ciphertext: 38D59DD18C98488451070B28F91A15C0 -Test: Encrypt -Comment: Set 3, vector 77 -Key: 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D -Plaintext: 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D -Ciphertext: E6A73709A37C7B00484BD54EED3A6128 -Test: Encrypt -Comment: Set 3, vector 78 -Key: 4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E -Plaintext: 4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E -Ciphertext: 12A6AD3ED9A3BA4FBA285B64D4823706 -Test: Encrypt -Comment: Set 3, vector 79 -Key: 4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F -Plaintext: 4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F -Ciphertext: CCB3FFAD253207DFB312A8B4FE0F390D -Test: Encrypt -Comment: Set 3, vector 80 -Key: 505050505050505050505050505050505050505050505050 -Plaintext: 50505050505050505050505050505050 -Ciphertext: A1C7DFA83502CE5558242F83CC12BF82 -Test: Encrypt -Comment: Set 3, vector 81 -Key: 515151515151515151515151515151515151515151515151 -Plaintext: 51515151515151515151515151515151 -Ciphertext: C9C8FCD1E4E482AF47555FEA823DE62A -Test: Encrypt -Comment: Set 3, vector 82 -Key: 525252525252525252525252525252525252525252525252 -Plaintext: 52525252525252525252525252525252 -Ciphertext: 5F9DD3265B6B043BF4CE8E11A3DAE4E1 -Test: Encrypt -Comment: Set 3, vector 83 -Key: 535353535353535353535353535353535353535353535353 -Plaintext: 53535353535353535353535353535353 -Ciphertext: 79D02BFAD35C67C8586694A068662F1D -Test: Encrypt -Comment: Set 3, vector 84 -Key: 545454545454545454545454545454545454545454545454 -Plaintext: 54545454545454545454545454545454 -Ciphertext: 361AC03A4827F590A5DDE28A5FFF723A -Test: Encrypt -Comment: Set 3, vector 85 -Key: 555555555555555555555555555555555555555555555555 -Plaintext: 55555555555555555555555555555555 -Ciphertext: 1758AC2E8DDE2126621AEB5759FC93D0 -Test: Encrypt -Comment: Set 3, vector 86 -Key: 565656565656565656565656565656565656565656565656 -Plaintext: 56565656565656565656565656565656 -Ciphertext: 14422A052A86DC0033B70F77D46A7E3C -Test: Encrypt -Comment: Set 3, vector 87 -Key: 575757575757575757575757575757575757575757575757 -Plaintext: 57575757575757575757575757575757 -Ciphertext: 154457A732BC11F0A4C43BEC607B9B91 -Test: Encrypt -Comment: Set 3, vector 88 -Key: 585858585858585858585858585858585858585858585858 -Plaintext: 58585858585858585858585858585858 -Ciphertext: 789BBC53CBE8A7D6119F61C8DC5DAEAB -Test: Encrypt -Comment: Set 3, vector 89 -Key: 595959595959595959595959595959595959595959595959 -Plaintext: 59595959595959595959595959595959 -Ciphertext: 6F8CDA92BF849BE59858544689DA2ACE -Test: Encrypt -Comment: Set 3, vector 90 -Key: 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A -Plaintext: 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A -Ciphertext: CCA696D494AF8877C0753106D5AD07A6 -Test: Encrypt -Comment: Set 3, vector 91 -Key: 5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B -Plaintext: 5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B -Ciphertext: E76884CA9F00DCF95BBB15C5FBB26D1C -Test: Encrypt -Comment: Set 3, vector 92 -Key: 5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C -Plaintext: 5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C -Ciphertext: CD3FA7BC9EC9EC0B0CF4F5A82A98550E -Test: Encrypt -Comment: Set 3, vector 93 -Key: 5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D -Plaintext: 5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D -Ciphertext: BC2FB535DC0D8C86682E32AC3761F299 -Test: Encrypt -Comment: Set 3, vector 94 -Key: 5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E -Plaintext: 5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E -Ciphertext: AB19152E1788D8B2878357484832BB27 -Test: Encrypt -Comment: Set 3, vector 95 -Key: 5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F -Plaintext: 5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F -Ciphertext: 87D1D7E297CED2C6606A171794FE1BB2 -Test: Encrypt -Comment: Set 3, vector 96 -Key: 606060606060606060606060606060606060606060606060 -Plaintext: 60606060606060606060606060606060 -Ciphertext: 6BF6F1728474F1050F712A0FF3F59319 -Test: Encrypt -Comment: Set 3, vector 97 -Key: 616161616161616161616161616161616161616161616161 -Plaintext: 61616161616161616161616161616161 -Ciphertext: 46646FF0ED8A8EDB395BA4B3DC97A35F -Test: Encrypt -Comment: Set 3, vector 98 -Key: 626262626262626262626262626262626262626262626262 -Plaintext: 62626262626262626262626262626262 -Ciphertext: F558C5F67CDF59374F5426D5846A622E -Test: Encrypt -Comment: Set 3, vector 99 -Key: 636363636363636363636363636363636363636363636363 -Plaintext: 63636363636363636363636363636363 -Ciphertext: E06CC0A3436C80F5F0271ACFC8F535D3 -Test: Encrypt -Comment: Set 3, vector 100 -Key: 646464646464646464646464646464646464646464646464 -Plaintext: 64646464646464646464646464646464 -Ciphertext: 903AA2EA9F99C3CCDD1EF1CD906FC800 -Test: Encrypt -Comment: Set 3, vector 101 -Key: 656565656565656565656565656565656565656565656565 -Plaintext: 65656565656565656565656565656565 -Ciphertext: EAE1010E86CF45476CEB180E78608841 -Test: Encrypt -Comment: Set 3, vector 102 -Key: 666666666666666666666666666666666666666666666666 -Plaintext: 66666666666666666666666666666666 -Ciphertext: 341F33B7FB7C5807BFB4C2C497565817 -Test: Encrypt -Comment: Set 3, vector 103 -Key: 676767676767676767676767676767676767676767676767 -Plaintext: 67676767676767676767676767676767 -Ciphertext: 4DA345AB1B3F7575F8D01BED5C17AF26 -Test: Encrypt -Comment: Set 3, vector 104 -Key: 686868686868686868686868686868686868686868686868 -Plaintext: 68686868686868686868686868686868 -Ciphertext: 1613C2DE21E7082312BF414C88310FAB -Test: Encrypt -Comment: Set 3, vector 105 -Key: 696969696969696969696969696969696969696969696969 -Plaintext: 69696969696969696969696969696969 -Ciphertext: 474D73001BD4BF9A9B79CFF79198E2F3 -Test: Encrypt -Comment: Set 3, vector 106 -Key: 6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A -Plaintext: 6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A -Ciphertext: 9C487E0BFB6FE07C521C663D03F175CF -Test: Encrypt -Comment: Set 3, vector 107 -Key: 6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B -Plaintext: 6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B -Ciphertext: 39F5672BEFCFCC072F292D47AD481DC7 -Test: Encrypt -Comment: Set 3, vector 108 -Key: 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C -Plaintext: 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C -Ciphertext: D9B86F02C3CB07CEF53834924A01DF14 -Test: Encrypt -Comment: Set 3, vector 109 -Key: 6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D -Plaintext: 6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D -Ciphertext: B42C9F4A33C5425FB20425889ECFFB9D -Test: Encrypt -Comment: Set 3, vector 110 -Key: 6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E -Plaintext: 6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E -Ciphertext: 832D535E3B4C40113C82AE10A7E1B78A -Test: Encrypt -Comment: Set 3, vector 111 -Key: 6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F -Plaintext: 6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F -Ciphertext: E9A8F63AAF1B1FFF05CFEB7E22E519DF -Test: Encrypt -Comment: Set 3, vector 112 -Key: 707070707070707070707070707070707070707070707070 -Plaintext: 70707070707070707070707070707070 -Ciphertext: C61B4EF13F07576701B1018AC9F01863 -Test: Encrypt -Comment: Set 3, vector 113 -Key: 717171717171717171717171717171717171717171717171 -Plaintext: 71717171717171717171717171717171 -Ciphertext: B098DBE07C3528931F14D40AC9F99ACC -Test: Encrypt -Comment: Set 3, vector 114 -Key: 727272727272727272727272727272727272727272727272 -Plaintext: 72727272727272727272727272727272 -Ciphertext: 3FCC0182E96BC01863EB161967D6482A -Test: Encrypt -Comment: Set 3, vector 115 -Key: 737373737373737373737373737373737373737373737373 -Plaintext: 73737373737373737373737373737373 -Ciphertext: D8F20E80F4AC4666066B0E3F1966C8DA -Test: Encrypt -Comment: Set 3, vector 116 -Key: 747474747474747474747474747474747474747474747474 -Plaintext: 74747474747474747474747474747474 -Ciphertext: 4E96D8CC1A34E3C38C37B5339CF26A5D -Test: Encrypt -Comment: Set 3, vector 117 -Key: 757575757575757575757575757575757575757575757575 -Plaintext: 75757575757575757575757575757575 -Ciphertext: 266EDB14B89857636C0F8E8C7D2FACD8 -Test: Encrypt -Comment: Set 3, vector 118 -Key: 767676767676767676767676767676767676767676767676 -Plaintext: 76767676767676767676767676767676 -Ciphertext: 1D060BD61CFA82764CE4DF283FCB2278 -Test: Encrypt -Comment: Set 3, vector 119 -Key: 777777777777777777777777777777777777777777777777 -Plaintext: 77777777777777777777777777777777 -Ciphertext: 4734355A933BFC1F2918CDF1A4E2BAAE -Test: Encrypt -Comment: Set 3, vector 120 -Key: 787878787878787878787878787878787878787878787878 -Plaintext: 78787878787878787878787878787878 -Ciphertext: DADBACBB42FEB35635A8DEBBFA93F5BA -Test: Encrypt -Comment: Set 3, vector 121 -Key: 797979797979797979797979797979797979797979797979 -Plaintext: 79797979797979797979797979797979 -Ciphertext: 8BB5C2E0B44B986EF523870C41721B7D -Test: Encrypt -Comment: Set 3, vector 122 -Key: 7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A -Plaintext: 7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A -Ciphertext: F66844E5DC500F43FF95E05965BAFD63 -Test: Encrypt -Comment: Set 3, vector 123 -Key: 7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B -Plaintext: 7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B -Ciphertext: ECC75A2BE7E27481907621A1796DC821 -Test: Encrypt -Comment: Set 3, vector 124 -Key: 7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C -Plaintext: 7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C -Ciphertext: D195666137F49B67F80EBC8C3ED824BF -Test: Encrypt -Comment: Set 3, vector 125 -Key: 7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D -Plaintext: 7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D -Ciphertext: 2F1ACC482BE5DEFD3EC1AD1F3A064A60 -Test: Encrypt -Comment: Set 3, vector 126 -Key: 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E -Plaintext: 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E -Ciphertext: 5FDDFA05A7F72D294DC386260DC59009 -Test: Encrypt -Comment: Set 3, vector 127 -Key: 7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F -Plaintext: 7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F -Ciphertext: FE94D733BABEB5A5382C2816311E515E -Test: Encrypt -Comment: Set 3, vector 128 -Key: 808080808080808080808080808080808080808080808080 -Plaintext: 80808080808080808080808080808080 -Ciphertext: F602BA7F515B082983B8F7A27F92408F -Test: Encrypt -Comment: Set 3, vector 129 -Key: 818181818181818181818181818181818181818181818181 -Plaintext: 81818181818181818181818181818181 -Ciphertext: 48E95062B889D83CC72767E303329710 -Test: Encrypt -Comment: Set 3, vector 130 -Key: 828282828282828282828282828282828282828282828282 -Plaintext: 82828282828282828282828282828282 -Ciphertext: 0D98319B8ED1E612F063591AAFA95962 -Test: Encrypt -Comment: Set 3, vector 131 -Key: 838383838383838383838383838383838383838383838383 -Plaintext: 83838383838383838383838383838383 -Ciphertext: 6D987B21F8072C09514C711819BDF42D -Test: Encrypt -Comment: Set 3, vector 132 -Key: 848484848484848484848484848484848484848484848484 -Plaintext: 84848484848484848484848484848484 -Ciphertext: 56C6CA23BC6A52C9967D70C6471A0788 -Test: Encrypt -Comment: Set 3, vector 133 -Key: 858585858585858585858585858585858585858585858585 -Plaintext: 85858585858585858585858585858585 -Ciphertext: 03C1004551B9B74D96CC3F9F7D11B04A -Test: Encrypt -Comment: Set 3, vector 134 -Key: 868686868686868686868686868686868686868686868686 -Plaintext: 86868686868686868686868686868686 -Ciphertext: 6356481250E8D52A0D922985BB2BED27 -Test: Encrypt -Comment: Set 3, vector 135 -Key: 878787878787878787878787878787878787878787878787 -Plaintext: 87878787878787878787878787878787 -Ciphertext: BC51A66892A956F44BF75168E935720E -Test: Encrypt -Comment: Set 3, vector 136 -Key: 888888888888888888888888888888888888888888888888 -Plaintext: 88888888888888888888888888888888 -Ciphertext: 73FAAAFB0517BD4D459A250E2CA4F017 -Test: Encrypt -Comment: Set 3, vector 137 -Key: 898989898989898989898989898989898989898989898989 -Plaintext: 89898989898989898989898989898989 -Ciphertext: 160C7D6510CCEB35318629FFFE1E8BA7 -Test: Encrypt -Comment: Set 3, vector 138 -Key: 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A -Plaintext: 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A -Ciphertext: 785ECC6F1A9415EBB05A4990786865A5 -Test: Encrypt -Comment: Set 3, vector 139 -Key: 8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B -Plaintext: 8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B -Ciphertext: 210498B4AC4D909CC7D6DAD6B8851C1A -Test: Encrypt -Comment: Set 3, vector 140 -Key: 8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C -Plaintext: 8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C -Ciphertext: 7094C31A06ED2AA0B3B63C210DEB96E2 -Test: Encrypt -Comment: Set 3, vector 141 -Key: 8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D -Plaintext: 8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D -Ciphertext: F8426DAE3B7C3FF568456EB4D4EB623B -Test: Encrypt -Comment: Set 3, vector 142 -Key: 8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E -Plaintext: 8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E -Ciphertext: 090487421369DED8EAC9812B544A29BE -Test: Encrypt -Comment: Set 3, vector 143 -Key: 8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F -Plaintext: 8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F -Ciphertext: 1AFA1FC5ECA8EAD74F9FE9B67993CB6F -Test: Encrypt -Comment: Set 3, vector 144 -Key: 909090909090909090909090909090909090909090909090 -Plaintext: 90909090909090909090909090909090 -Ciphertext: 38124FCE77189341DE7B225951CDE6E9 -Test: Encrypt -Comment: Set 3, vector 145 -Key: 919191919191919191919191919191919191919191919191 -Plaintext: 91919191919191919191919191919191 -Ciphertext: 059A775350A44BB880A750B32B19E179 -Test: Encrypt -Comment: Set 3, vector 146 -Key: 929292929292929292929292929292929292929292929292 -Plaintext: 92929292929292929292929292929292 -Ciphertext: 7CFA631E8BABF7DEE00DAB0754C385DD -Test: Encrypt -Comment: Set 3, vector 147 -Key: 939393939393939393939393939393939393939393939393 -Plaintext: 93939393939393939393939393939393 -Ciphertext: 0632ED71BA440232DECE4F1B38F94323 -Test: Encrypt -Comment: Set 3, vector 148 -Key: 949494949494949494949494949494949494949494949494 -Plaintext: 94949494949494949494949494949494 -Ciphertext: D049FF03ACF47C866A4209E7588E0CFA -Test: Encrypt -Comment: Set 3, vector 149 -Key: 959595959595959595959595959595959595959595959595 -Plaintext: 95959595959595959595959595959595 -Ciphertext: 910408E331C64A71D50A149DFD50C242 -Test: Encrypt -Comment: Set 3, vector 150 -Key: 969696969696969696969696969696969696969696969696 -Plaintext: 96969696969696969696969696969696 -Ciphertext: 0829C2DD4AF8F06C30978A0199A43C3C -Test: Encrypt -Comment: Set 3, vector 151 -Key: 979797979797979797979797979797979797979797979797 -Plaintext: 97979797979797979797979797979797 -Ciphertext: C70D286C18D2A0EA5D16FEB97F35DE6F -Test: Encrypt -Comment: Set 3, vector 152 -Key: 989898989898989898989898989898989898989898989898 -Plaintext: 98989898989898989898989898989898 -Ciphertext: A220CD3CD177BDD73D44B6D4A7A9ED0E -Test: Encrypt -Comment: Set 3, vector 153 -Key: 999999999999999999999999999999999999999999999999 -Plaintext: 99999999999999999999999999999999 -Ciphertext: 74EC1A68010A0D5FA9688F1552E70EF5 -Test: Encrypt -Comment: Set 3, vector 154 -Key: 9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A -Plaintext: 9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A -Ciphertext: C1C0EE9EEA079CCE8544BA9940963720 -Test: Encrypt -Comment: Set 3, vector 155 -Key: 9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B -Plaintext: 9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B -Ciphertext: 500418F7142C273CCADBDAD8831619D2 -Test: Encrypt -Comment: Set 3, vector 156 -Key: 9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C -Plaintext: 9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C -Ciphertext: 703A0223D3ABA658C531F9BE03F6E842 -Test: Encrypt -Comment: Set 3, vector 157 -Key: 9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D -Plaintext: 9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D -Ciphertext: EBC65558CD43197D87CFF645FDBA1661 -Test: Encrypt -Comment: Set 3, vector 158 -Key: 9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E -Plaintext: 9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E -Ciphertext: 6F6E140E44934DA754F008EB5597BDA3 -Test: Encrypt -Comment: Set 3, vector 159 -Key: 9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F -Plaintext: 9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F -Ciphertext: 3D533A98B85CDD624541956E348ACBD3 -Test: Encrypt -Comment: Set 3, vector 160 -Key: A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0 -Plaintext: A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0 -Ciphertext: 13833D60F1D247019258C457E9F2292A -Test: Encrypt -Comment: Set 3, vector 161 -Key: A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1 -Plaintext: A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1 -Ciphertext: FC13CECE4F5E2467427582595EDB6B87 -Test: Encrypt -Comment: Set 3, vector 162 -Key: A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 -Plaintext: A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 -Ciphertext: 2772A4E636F01514949D47B037825AF9 -Test: Encrypt -Comment: Set 3, vector 163 -Key: A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3 -Plaintext: A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3 -Ciphertext: F13DC1CCF105212AF8BC4F73F0AEF272 -Test: Encrypt -Comment: Set 3, vector 164 -Key: A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4 -Plaintext: A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4 -Ciphertext: A6EB0CABBBA03DB1B2425E6FC559B06A -Test: Encrypt -Comment: Set 3, vector 165 -Key: A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5 -Plaintext: A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5 -Ciphertext: 32222D875D9E73DE72848EA88AC9B259 -Test: Encrypt -Comment: Set 3, vector 166 -Key: A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6 -Plaintext: A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6 -Ciphertext: 7DA6BC64D1E71FFE2D24C1A2FF7405BF -Test: Encrypt -Comment: Set 3, vector 167 -Key: A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7 -Plaintext: A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7 -Ciphertext: AD5129092054880300AFCF09A2921DAF -Test: Encrypt -Comment: Set 3, vector 168 -Key: A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8 -Plaintext: A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8 -Ciphertext: FCF2E0AA207754597C8C00A4615B5B5B -Test: Encrypt -Comment: Set 3, vector 169 -Key: A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9 -Plaintext: A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9 -Ciphertext: 83D1475128C93C79BFE2AC9DA7E5D7BC -Test: Encrypt -Comment: Set 3, vector 170 -Key: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -Plaintext: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -Ciphertext: 9BA09846E13568B746B7D6A43364915F -Test: Encrypt -Comment: Set 3, vector 171 -Key: ABABABABABABABABABABABABABABABABABABABABABABABAB -Plaintext: ABABABABABABABABABABABABABABABAB -Ciphertext: 387BDB77D285F9E59CB88CD830CB31E2 -Test: Encrypt -Comment: Set 3, vector 172 -Key: ACACACACACACACACACACACACACACACACACACACACACACACAC -Plaintext: ACACACACACACACACACACACACACACACAC -Ciphertext: 82BFCC439310DD5DC411CCD4451E789B -Test: Encrypt -Comment: Set 3, vector 173 -Key: ADADADADADADADADADADADADADADADADADADADADADADADAD -Plaintext: ADADADADADADADADADADADADADADADAD -Ciphertext: 34C4240853DA191DF1D63E83401CE0E2 -Test: Encrypt -Comment: Set 3, vector 174 -Key: AEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAE -Plaintext: AEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAE -Ciphertext: B3CE3C38C10A667F5FD67BC8B7037283 -Test: Encrypt -Comment: Set 3, vector 175 -Key: AFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAF -Plaintext: AFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAF -Ciphertext: BEF04E726DC1D5D1D4AB0A025CFDFD7D -Test: Encrypt -Comment: Set 3, vector 176 -Key: B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0 -Plaintext: B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0 -Ciphertext: 725D70D564E78095739EA7980B481056 -Test: Encrypt -Comment: Set 3, vector 177 -Key: B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1 -Plaintext: B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1 -Ciphertext: CAB9293C9E3A82D40E85558F9DA488C1 -Test: Encrypt -Comment: Set 3, vector 178 -Key: B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2 -Plaintext: B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2 -Ciphertext: B433CACA5FF9F5AADB6BAFB7D4BE81FC -Test: Encrypt -Comment: Set 3, vector 179 -Key: B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3 -Plaintext: B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3 -Ciphertext: 3910F153098B638696101E04022A7849 -Test: Encrypt -Comment: Set 3, vector 180 -Key: B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 -Plaintext: B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 -Ciphertext: 1D7FF785CFC6AF98C5C81CDA2ABC9816 -Test: Encrypt -Comment: Set 3, vector 181 -Key: B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5 -Plaintext: B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5 -Ciphertext: 4A30C5521BAC28E5942808CB536376C7 -Test: Encrypt -Comment: Set 3, vector 182 -Key: B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6 -Plaintext: B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6 -Ciphertext: 17B908EF18EB7703DDB667C7A8DBA777 -Test: Encrypt -Comment: Set 3, vector 183 -Key: B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7 -Plaintext: B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7 -Ciphertext: 3222E0228F29C9F27467CB7047838E39 -Test: Encrypt -Comment: Set 3, vector 184 -Key: B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8 -Plaintext: B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8 -Ciphertext: E422497D1FD54DF8F9CEE11548D77303 -Test: Encrypt -Comment: Set 3, vector 185 -Key: B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9 -Plaintext: B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9 -Ciphertext: B26A00606A375B1A64B7F0C333D81A50 -Test: Encrypt -Comment: Set 3, vector 186 -Key: BABABABABABABABABABABABABABABABABABABABABABABABA -Plaintext: BABABABABABABABABABABABABABABABA -Ciphertext: D5032B06E290F6B76327E47E519F8F6D -Test: Encrypt -Comment: Set 3, vector 187 -Key: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB -Plaintext: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB -Ciphertext: 2CED7355B82DF3B88C4417149FFA1783 -Test: Encrypt -Comment: Set 3, vector 188 -Key: BCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC -Plaintext: BCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC -Ciphertext: FC7B4D95C62CA6D33862D56768EA9A1A -Test: Encrypt -Comment: Set 3, vector 189 -Key: BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD -Plaintext: BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD -Ciphertext: 375A9C1E1FCFA6F2369306D966F82156 -Test: Encrypt -Comment: Set 3, vector 190 -Key: BEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBE -Plaintext: BEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBE -Ciphertext: BA4C218D8691D5D9CE15ECCC75C75D8B -Test: Encrypt -Comment: Set 3, vector 191 -Key: BFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBF -Plaintext: BFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBF -Ciphertext: 4D5C53279B76A6F74195C65F09DF85D9 -Test: Encrypt -Comment: Set 3, vector 192 -Key: C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0 -Plaintext: C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0 -Ciphertext: 75CF5E6B3B0BFFF2290A5E58A85CF994 -Test: Encrypt -Comment: Set 3, vector 193 -Key: C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1 -Plaintext: C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1 -Ciphertext: 3482A5C83234E75CB443E09BA17EE3A0 -Test: Encrypt -Comment: Set 3, vector 194 -Key: C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2 -Plaintext: C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2 -Ciphertext: DA592D849C1BFBBEF5C3D0D8DA0F4B9A -Test: Encrypt -Comment: Set 3, vector 195 -Key: C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3 -Plaintext: C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3 -Ciphertext: 6656047376A76ED53FFF8C5DE1B6F886 -Test: Encrypt -Comment: Set 3, vector 196 -Key: C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4 -Plaintext: C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4 -Ciphertext: F86FD06864804515B17B453F8A42A44D -Test: Encrypt -Comment: Set 3, vector 197 -Key: C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5 -Plaintext: C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5 -Ciphertext: E57CD8E81BBF5B42446A7880B32A9A2F -Test: Encrypt -Comment: Set 3, vector 198 -Key: C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 -Plaintext: C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 -Ciphertext: A17219F7DEFF2985BDFADD62A6854947 -Test: Encrypt -Comment: Set 3, vector 199 -Key: C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7 -Plaintext: C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7 -Ciphertext: FF288A92FB408DA875531D163CE0105A -Test: Encrypt -Comment: Set 3, vector 200 -Key: C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8 -Plaintext: C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8 -Ciphertext: 11828CD066FD12620DFA16358CF1A705 -Test: Encrypt -Comment: Set 3, vector 201 -Key: C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9 -Plaintext: C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9 -Ciphertext: 6FA5DCBD14D2520E7F8147EDBEBBEAEE -Test: Encrypt -Comment: Set 3, vector 202 -Key: CACACACACACACACACACACACACACACACACACACACACACACACA -Plaintext: CACACACACACACACACACACACACACACACA -Ciphertext: F365CE3849AFB23AF3B62D7CFF80B19B -Test: Encrypt -Comment: Set 3, vector 203 -Key: CBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCB -Plaintext: CBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCB -Ciphertext: 74BE047CAAE10D095B3BDA14016EA262 -Test: Encrypt -Comment: Set 3, vector 204 -Key: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC -Plaintext: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC -Ciphertext: DC7A7D66AD1ABF1C7AA28891BE685AB5 -Test: Encrypt -Comment: Set 3, vector 205 -Key: CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD -Plaintext: CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD -Ciphertext: 8BED9C5BAD5C4A4AFB41CDFD7E88BB97 -Test: Encrypt -Comment: Set 3, vector 206 -Key: CECECECECECECECECECECECECECECECECECECECECECECECE -Plaintext: CECECECECECECECECECECECECECECECE -Ciphertext: 915FF93DC6A3984F11AB60BD2AA3DC61 -Test: Encrypt -Comment: Set 3, vector 207 -Key: CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF -Plaintext: CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF -Ciphertext: 43DFEEBBFB3692763752E6EA8931A9B8 -Test: Encrypt -Comment: Set 3, vector 208 -Key: D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0 -Plaintext: D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0 -Ciphertext: 2BB966115263DF2296C5D23E02D9C335 -Test: Encrypt -Comment: Set 3, vector 209 -Key: D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1 -Plaintext: D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1 -Ciphertext: FCCA1E3616236F0D5A1A9D035A35049D -Test: Encrypt -Comment: Set 3, vector 210 -Key: D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2 -Plaintext: D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2 -Ciphertext: 2E7246518C923B2AE23C61C99D7E6CE7 -Test: Encrypt -Comment: Set 3, vector 211 -Key: D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3 -Plaintext: D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3 -Ciphertext: 8D19232494905BAF83F4230395C8E09B -Test: Encrypt -Comment: Set 3, vector 212 -Key: D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4 -Plaintext: D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4 -Ciphertext: 6BC0BBCC76A7F8DF2A03BAB1CDE47FB6 -Test: Encrypt -Comment: Set 3, vector 213 -Key: D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5 -Plaintext: D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5 -Ciphertext: BD3D30B62DC0B0FEED0CC760879DB806 -Test: Encrypt -Comment: Set 3, vector 214 -Key: D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6 -Plaintext: D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6 -Ciphertext: 647388D8E6A9C8D09828041F4E338D47 -Test: Encrypt -Comment: Set 3, vector 215 -Key: D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7 -Plaintext: D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7 -Ciphertext: 4861CFC3FDDC434F2742E45B97FBB270 -Test: Encrypt -Comment: Set 3, vector 216 -Key: D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 -Plaintext: D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 -Ciphertext: 4426BC1C3990A5DE10760D0C10A3BB9A -Test: Encrypt -Comment: Set 3, vector 217 -Key: D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9 -Plaintext: D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9 -Ciphertext: 805211D0BD914F07AB1579EF9E3827EE -Test: Encrypt -Comment: Set 3, vector 218 -Key: DADADADADADADADADADADADADADADADADADADADADADADADA -Plaintext: DADADADADADADADADADADADADADADADA -Ciphertext: 519DB5AA8DA219224EDA77F77B96C135 -Test: Encrypt -Comment: Set 3, vector 219 -Key: DBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDB -Plaintext: DBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDB -Ciphertext: 7A96F769BF260E6D91A070BA7766D3E3 -Test: Encrypt -Comment: Set 3, vector 220 -Key: DCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDC -Plaintext: DCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDC -Ciphertext: 902222F1779476A44CEEDACEDA72B3EC -Test: Encrypt -Comment: Set 3, vector 221 -Key: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD -Plaintext: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD -Ciphertext: 99859E56FE0DAB67CDE755E4790ED51D -Test: Encrypt -Comment: Set 3, vector 222 -Key: DEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDE -Plaintext: DEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDE -Ciphertext: C2F4EE121941873763F302ECE6D8DF9E -Test: Encrypt -Comment: Set 3, vector 223 -Key: DFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDF -Plaintext: DFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDF -Ciphertext: FE1E93DBF071E2280130E169C9E5254A -Test: Encrypt -Comment: Set 3, vector 224 -Key: E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0 -Plaintext: E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0 -Ciphertext: 58F45B5E30D9DE7038EC405B601521AB -Test: Encrypt -Comment: Set 3, vector 225 -Key: E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 -Plaintext: E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 -Ciphertext: 8783BD662F65899EF61E113B7CC6505D -Test: Encrypt -Comment: Set 3, vector 226 -Key: E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2 -Plaintext: E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2 -Ciphertext: A3F6BBB2C3403F433203E0E18DB3E4C0 -Test: Encrypt -Comment: Set 3, vector 227 -Key: E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3 -Plaintext: E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3 -Ciphertext: D3EE663795362A0D2E7A8DB784F95A33 -Test: Encrypt -Comment: Set 3, vector 228 -Key: E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4 -Plaintext: E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4 -Ciphertext: 1B75895E7FCEEEA5ECA62E14F77ECF6A -Test: Encrypt -Comment: Set 3, vector 229 -Key: E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5 -Plaintext: E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5 -Ciphertext: 5040525E4F3B78D2036539C1C463A48B -Test: Encrypt -Comment: Set 3, vector 230 -Key: E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6 -Plaintext: E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6 -Ciphertext: A48E63494241AEACB0EF7B18A431E50D -Test: Encrypt -Comment: Set 3, vector 231 -Key: E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7 -Plaintext: E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7 -Ciphertext: 9DAF4DBBBC81465BC4270129C522ABCB -Test: Encrypt -Comment: Set 3, vector 232 -Key: E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8 -Plaintext: E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8 -Ciphertext: 20B118C870AF1A85C683C60A31ED24E4 -Test: Encrypt -Comment: Set 3, vector 233 -Key: E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9 -Plaintext: E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9 -Ciphertext: 52FF30830000A72FA2CB030539550F06 -Test: Encrypt -Comment: Set 3, vector 234 -Key: EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA -Plaintext: EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA -Ciphertext: 797ED3DB1B9A4BF4122EA0FF667BC36D -Test: Encrypt -Comment: Set 3, vector 235 -Key: EBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEB -Plaintext: EBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEB -Ciphertext: 708CE40FC810F5E84B6EE8FC2E0A46FA -Test: Encrypt -Comment: Set 3, vector 236 -Key: ECECECECECECECECECECECECECECECECECECECECECECECEC -Plaintext: ECECECECECECECECECECECECECECECEC -Ciphertext: 0BA7446B1D3D803BB80CDE94E096E79C -Test: Encrypt -Comment: Set 3, vector 237 -Key: EDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDED -Plaintext: EDEDEDEDEDEDEDEDEDEDEDEDEDEDEDED -Ciphertext: 6B0E95AED4DC9E923EDF3DDD5BAEEA0C -Test: Encrypt -Comment: Set 3, vector 238 -Key: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE -Plaintext: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE -Ciphertext: DE45D435FD6F8A240AD8DCE5A4BD8CC3 -Test: Encrypt -Comment: Set 3, vector 239 -Key: EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF -Plaintext: EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF -Ciphertext: 8823002161D635ADA686D85B087F3022 -Test: Encrypt -Comment: Set 3, vector 240 -Key: F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -Plaintext: F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -Ciphertext: C00F367B98CC819F5F6ADADEA8513DD8 -Test: Encrypt -Comment: Set 3, vector 241 -Key: F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1 -Plaintext: F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1 -Ciphertext: 9C25269FB7FA889FBD9E55AAD4C92DE0 -Test: Encrypt -Comment: Set 3, vector 242 -Key: F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2 -Plaintext: F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2 -Ciphertext: 5DD1D60A62B551FFA18CFF8263C5FCE4 -Test: Encrypt -Comment: Set 3, vector 243 -Key: F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 -Plaintext: F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 -Ciphertext: D183A9113393C1EEC7170331C65D2547 -Test: Encrypt -Comment: Set 3, vector 244 -Key: F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4 -Plaintext: F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4 -Ciphertext: FADF9E4AF6C1D7A6965D5DBA03194F18 -Test: Encrypt -Comment: Set 3, vector 245 -Key: F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5 -Plaintext: F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5 -Ciphertext: F2E9E5BE04D7B47B93D2B81DBCDA8BF3 -Test: Encrypt -Comment: Set 3, vector 246 -Key: F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6 -Plaintext: F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6 -Ciphertext: 7A04D513A59636ECA8A8608F10F21910 -Test: Encrypt -Comment: Set 3, vector 247 -Key: F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7 -Plaintext: F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7 -Ciphertext: 659552FCEF0E90F77050CF3902A22475 -Test: Encrypt -Comment: Set 3, vector 248 -Key: F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8 -Plaintext: F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8 -Ciphertext: F81709C989061D4439BDD47E71DBB457 -Test: Encrypt -Comment: Set 3, vector 249 -Key: F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9 -Plaintext: F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9 -Ciphertext: E05425C950E298F31FC6751375B48B66 -Test: Encrypt -Comment: Set 3, vector 250 -Key: FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA -Plaintext: FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA -Ciphertext: 6E90B365BEBAFA5C49DC4D6AB1593F94 -Test: Encrypt -Comment: Set 3, vector 251 -Key: FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB -Plaintext: FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB -Ciphertext: B2469C08D0F878579E162E8ACC5EF802 -Test: Encrypt -Comment: Set 3, vector 252 -Key: FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC -Plaintext: FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC -Ciphertext: C1DCAB694C7FDBEC88C6FC2597EAC180 -Test: Encrypt -Comment: Set 3, vector 253 -Key: FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD -Plaintext: FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD -Ciphertext: 6651FFBD3C30A496D072493A519D44D9 -Test: Encrypt -Comment: Set 3, vector 254 -Key: FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE -Plaintext: FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE -Ciphertext: A2F5A98929658AF4A9700B9923DAF014 -Test: Encrypt -Comment: Set 3, vector 255 -Key: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -Plaintext: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -Ciphertext: 3F8D5676F51CE23DC3BDB627F8B3883E -Test: Encrypt -Comment: Tests with 256-bit keys -Comment: Set 1, vector 0 -Key: 8000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 2136FABDA091DFB5171B94B8EFBB5D08 -Test: Encrypt -Comment: Set 1, vector 1 -Key: 4000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 6EBC4F33B3EADA5DBF25130F3D02CD34 -Test: Encrypt -Comment: Set 1, vector 2 -Key: 2000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3A7BCDC53A1F02EF20C79CFCE107D38B -Test: Encrypt -Comment: Set 1, vector 3 -Key: 1000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 88A96052B61C5A621EE9A6316A42ED4A -Test: Encrypt -Comment: Set 1, vector 4 -Key: 0800000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: CBD7A2D8354B2DA972A0950BDFFF2CBD -Test: Encrypt -Comment: Set 1, vector 5 -Key: 0400000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 690BEB5FBEA12A4861E826F568E9F8F3 -Test: Encrypt -Comment: Set 1, vector 6 -Key: 0200000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 799A6FA3B78846E424F41370654ABD6F -Test: Encrypt -Comment: Set 1, vector 7 -Key: 0100000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: DD7E24E12F391C5FEDE40136F8DE3731 -Test: Encrypt -Comment: Set 1, vector 8 -Key: 0080000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F7412D526E9244574F9933F602595385 -Test: Encrypt -Comment: Set 1, vector 9 -Key: 0040000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: FD9D0174A83BEC3E7E1C3372CB5E7C9B -Test: Encrypt -Comment: Set 1, vector 10 -Key: 0020000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: FCA62D360A7DFE54DB8D53819A407E71 -Test: Encrypt -Comment: Set 1, vector 11 -Key: 0010000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: AC821C68913DCE3E74A20DB8E902CC4C -Test: Encrypt -Comment: Set 1, vector 12 -Key: 0008000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 80633F6CB8F10863E0A7FDE4C35D50E9 -Test: Encrypt -Comment: Set 1, vector 13 -Key: 0004000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: D417D1D94869EE2364FCE869C0C1114E -Test: Encrypt -Comment: Set 1, vector 14 -Key: 0002000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0FA96DCEA2ACB849490CD5A1488A2FD9 -Test: Encrypt -Comment: Set 1, vector 15 -Key: 0001000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3E99BCB51CAEB9147DCF8643771D1C83 -Test: Encrypt -Comment: Set 1, vector 16 -Key: 0000800000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 25EA413BBC3C2579D3F7CBFD9E378091 -Test: Encrypt -Comment: Set 1, vector 17 -Key: 0000400000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: C0433C1AD2E468FC679988CFBFCA5CD4 -Test: Encrypt -Comment: Set 1, vector 18 -Key: 0000200000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 05108B7D7C2871D9DE1F22232CF6966B -Test: Encrypt -Comment: Set 1, vector 19 -Key: 0000100000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 8ABE085B75333946450F2D1D162E8650 -Test: Encrypt -Comment: Set 1, vector 20 -Key: 0000080000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 487A9C50152B44F5B009D8682EA1FD22 -Test: Encrypt -Comment: Set 1, vector 21 -Key: 0000040000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 739207A812F142B545798BA85170AF25 -Test: Encrypt -Comment: Set 1, vector 22 -Key: 0000020000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E40B90A5840591FEC98A24B23E73892B -Test: Encrypt -Comment: Set 1, vector 23 -Key: 0000010000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0258BFB0DC942F6A9139D3C00EBBEB35 -Test: Encrypt -Comment: Set 1, vector 24 -Key: 0000008000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 650CD6035752320B8252F44AEEBEC9E4 -Test: Encrypt -Comment: Set 1, vector 25 -Key: 0000004000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: FABFFBB7028B53E0BB88E3E4462ACF0D -Test: Encrypt -Comment: Set 1, vector 26 -Key: 0000002000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: C48D3416904896E2F2307EA26FB8CF1C -Test: Encrypt -Comment: Set 1, vector 27 -Key: 0000001000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 2237452352F488F1DA3F1619FC6A7F85 -Test: Encrypt -Comment: Set 1, vector 28 -Key: 0000000800000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: D3E6ECF4A3F70E672AABEE0C2ECA3960 -Test: Encrypt -Comment: Set 1, vector 29 -Key: 0000000400000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7A3EFC8AC6A82E8AEF377D8D96D8E830 -Test: Encrypt -Comment: Set 1, vector 30 -Key: 0000000200000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7278F0441F5AA34C0B7CDB076B453225 -Test: Encrypt -Comment: Set 1, vector 31 -Key: 0000000100000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 382E61EAC044E2151906F936CC9D33AE -Test: Encrypt -Comment: Set 1, vector 32 -Key: 0000000080000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: C51147F4AD33C35647DF7E856C2965D4 -Test: Encrypt -Comment: Set 1, vector 33 -Key: 0000000040000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: DAFE261154ADF63EA3F75B1253A9F77C -Test: Encrypt -Comment: Set 1, vector 34 -Key: 0000000020000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B1A0B0E765C1D0379CA538ED0EFB9649 -Test: Encrypt -Comment: Set 1, vector 35 -Key: 0000000010000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 78F7D01D7795ACA0846CCE835E71FBC2 -Test: Encrypt -Comment: Set 1, vector 36 -Key: 0000000008000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E001A545AC71F53D3AD99C84D7F5B062 -Test: Encrypt -Comment: Set 1, vector 37 -Key: 0000000004000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 58E3907C56BF5ADFDBAE61C172B8F488 -Test: Encrypt -Comment: Set 1, vector 38 -Key: 0000000002000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 16F77C9515B473167BD7ABA7C97B1CCA -Test: Encrypt -Comment: Set 1, vector 39 -Key: 0000000001000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 4BC9F687C7757CDF5A5E94D69E5EA173 -Test: Encrypt -Comment: Set 1, vector 40 -Key: 0000000000800000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 804261A34F26A87694F70C35F338989D -Test: Encrypt -Comment: Set 1, vector 41 -Key: 0000000000400000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E8D8BF002738D7067CD06437C4459365 -Test: Encrypt -Comment: Set 1, vector 42 -Key: 0000000000200000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E131137F7EA2AEAB37F72AF3644FFCCE -Test: Encrypt -Comment: Set 1, vector 43 -Key: 0000000000100000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 542A1FD5CB4BE8485FA83AA14FAAD4A8 -Test: Encrypt -Comment: Set 1, vector 44 -Key: 0000000000080000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: BEC6C8C1A9E5E7982A990B8F9BA0ADE3 -Test: Encrypt -Comment: Set 1, vector 45 -Key: 0000000000040000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: DE55BE1AA823A9F7474C65BD50D55095 -Test: Encrypt -Comment: Set 1, vector 46 -Key: 0000000000020000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: D67CC199AF361A07A0DBD8F6700A4744 -Test: Encrypt -Comment: Set 1, vector 47 -Key: 0000000000010000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: DBAD180017184EF80D398D8D22AAC4A1 -Test: Encrypt -Comment: Set 1, vector 48 -Key: 0000000000008000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 27E68691F10EEFD1B594682DC3EF65A5 -Test: Encrypt -Comment: Set 1, vector 49 -Key: 0000000000004000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 6D4EF0587B948AD62B703D3D7CCEA229 -Test: Encrypt -Comment: Set 1, vector 50 -Key: 0000000000002000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: C0F443758F239E3A3E31E6F93AD4766B -Test: Encrypt -Comment: Set 1, vector 51 -Key: 0000000000001000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: BEB5CB1D8EB3A9EA795A4B43CA1567A9 -Test: Encrypt -Comment: Set 1, vector 52 -Key: 0000000000000800000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: D89A97957F1979C63459A385E21B4A84 -Test: Encrypt -Comment: Set 1, vector 53 -Key: 0000000000000400000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 39A6615147FF571F2FABAD5BE9800A10 -Test: Encrypt -Comment: Set 1, vector 54 -Key: 0000000000000200000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E18B0CB1980124504B46A46A6F4273F3 -Test: Encrypt -Comment: Set 1, vector 55 -Key: 0000000000000100000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 1E13C8034ED53FD4E3F433E1CF4B5CE1 -Test: Encrypt -Comment: Set 1, vector 56 -Key: 0000000000000080000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 71FA53EAADBA0C9BCF86A3071408966D -Test: Encrypt -Comment: Set 1, vector 57 -Key: 0000000000000040000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E50502EC84BB024C7466FE225C7FD8BA -Test: Encrypt -Comment: Set 1, vector 58 -Key: 0000000000000020000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: DEB33581D79C9D4294E315998377BCBF -Test: Encrypt -Comment: Set 1, vector 59 -Key: 0000000000000010000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: A713C2503CE44A04C9108FA160659945 -Test: Encrypt -Comment: Set 1, vector 60 -Key: 0000000000000008000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 520E9E8DB8A67601B02E369916FAB8CC -Test: Encrypt -Comment: Set 1, vector 61 -Key: 0000000000000004000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 8FDC11B74D17D79C6B2DFF2D6A561258 -Test: Encrypt -Comment: Set 1, vector 62 -Key: 0000000000000002000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3EA497AD2FC8F2587EFAA7D49121F26C -Test: Encrypt -Comment: Set 1, vector 63 -Key: 0000000000000001000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3340905F7413C979E5AED11D71B9294E -Test: Encrypt -Comment: Set 1, vector 64 -Key: 0000000000000000800000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 067FAC22E16205FF209B1760ABDE0565 -Test: Encrypt -Comment: Set 1, vector 65 -Key: 0000000000000000400000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: BECA010BAB7BDD7E8A8084DA9853A0F4 -Test: Encrypt -Comment: Set 1, vector 66 -Key: 0000000000000000200000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 146F5A4A7B2880F5AF57333C7F129028 -Test: Encrypt -Comment: Set 1, vector 67 -Key: 0000000000000000100000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F773C1BD724955109A8B4EA3DA1C2197 -Test: Encrypt -Comment: Set 1, vector 68 -Key: 0000000000000000080000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B427EFAC8C656AB6F4DF7F420A177B8E -Test: Encrypt -Comment: Set 1, vector 69 -Key: 0000000000000000040000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B3D1BDB29010DB5FC81B66E2F7189D54 -Test: Encrypt -Comment: Set 1, vector 70 -Key: 0000000000000000020000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 676EEA415693F303ACF5CD84C50816AB -Test: Encrypt -Comment: Set 1, vector 71 -Key: 0000000000000000010000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: BA21C564E52961DEB4B3A3CA9E0B70EF -Test: Encrypt -Comment: Set 1, vector 72 -Key: 0000000000000000008000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: A60FB5DBD17EA92E303492E3F54D0BF2 -Test: Encrypt -Comment: Set 1, vector 73 -Key: 0000000000000000004000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F4F5A0540107D66F32FB289B14EF4299 -Test: Encrypt -Comment: Set 1, vector 74 -Key: 0000000000000000002000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 8D9B4A19F391175CF7DA42FEF313EDD8 -Test: Encrypt -Comment: Set 1, vector 75 -Key: 0000000000000000001000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B0AFAB0183A9FC69DA8BBE9B8FAF653A -Test: Encrypt -Comment: Set 1, vector 76 -Key: 0000000000000000000800000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 68FFD91FD5AD1F1AC176D639694FEA29 -Test: Encrypt -Comment: Set 1, vector 77 -Key: 0000000000000000000400000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 97EC38070014494A2E97EFE354BA2865 -Test: Encrypt -Comment: Set 1, vector 78 -Key: 0000000000000000000200000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E3EC51F889C63AD2C708F22AFC42D18C -Test: Encrypt -Comment: Set 1, vector 79 -Key: 0000000000000000000100000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 8CC5BDB49037DC1D3D8DADFA0B8ECD96 -Test: Encrypt -Comment: Set 1, vector 80 -Key: 0000000000000000000080000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 14F5C3D75BA0397D7436E1479F78435B -Test: Encrypt -Comment: Set 1, vector 81 -Key: 0000000000000000000040000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: FF3B01851C8254967E4DFAA2A0F0C057 -Test: Encrypt -Comment: Set 1, vector 82 -Key: 0000000000000000000020000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B8C8E9AFF66FFEC9D0342FF297A543B1 -Test: Encrypt -Comment: Set 1, vector 83 -Key: 0000000000000000000010000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: A95A113F088FFE17A79050C46377545E -Test: Encrypt -Comment: Set 1, vector 84 -Key: 0000000000000000000008000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: EA4C3AFA65016D057EC1DFDD0411ED06 -Test: Encrypt -Comment: Set 1, vector 85 -Key: 0000000000000000000004000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7D535C84DFAD692D0F89AB73C1F42F60 -Test: Encrypt -Comment: Set 1, vector 86 -Key: 0000000000000000000002000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E857DF0CEBAB1E03CB9AF73CBF9C19D1 -Test: Encrypt -Comment: Set 1, vector 87 -Key: 0000000000000000000001000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7A59BCF6FAC80379EB7E8E2EFAB147D4 -Test: Encrypt -Comment: Set 1, vector 88 -Key: 0000000000000000000000800000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 43EF17F87BAF7536DDE734F885C4CE85 -Test: Encrypt -Comment: Set 1, vector 89 -Key: 0000000000000000000000400000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 2B71CE14089741A1EF1E99DC9E22E739 -Test: Encrypt -Comment: Set 1, vector 90 -Key: 0000000000000000000000200000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 9283885622781998186B7DACBFF68ED2 -Test: Encrypt -Comment: Set 1, vector 91 -Key: 0000000000000000000000100000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 756A184F392D8C821479EFF930338C0A -Test: Encrypt -Comment: Set 1, vector 92 -Key: 0000000000000000000000080000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: CE848D49BB76CA30B607C9539793DA41 -Test: Encrypt -Comment: Set 1, vector 93 -Key: 0000000000000000000000040000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 50F2D5238991EEA9654C8895AFC0AC37 -Test: Encrypt -Comment: Set 1, vector 94 -Key: 0000000000000000000000020000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 561564103E13F4CBB58A9E096DB1958B -Test: Encrypt -Comment: Set 1, vector 95 -Key: 0000000000000000000000010000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: EF2BB05AC6868C15D66D956BD580D467 -Test: Encrypt -Comment: Set 1, vector 96 -Key: 0000000000000000000000008000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: C7B1A5A3A201DF25FD97A47B1FC3569E -Test: Encrypt -Comment: Set 1, vector 97 -Key: 0000000000000000000000004000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0A1873FF47B38095CF6A8BABF3901FF2 -Test: Encrypt -Comment: Set 1, vector 98 -Key: 0000000000000000000000002000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: A96F8F977DC45ABF55518EA10C598E10 -Test: Encrypt -Comment: Set 1, vector 99 -Key: 0000000000000000000000001000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 778C644278689EC0577BDDB2154AE635 -Test: Encrypt -Comment: Set 1, vector 100 -Key: 0000000000000000000000000800000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: DEF97DBCF02648E7BCE6A368F7F34C14 -Test: Encrypt -Comment: Set 1, vector 101 -Key: 0000000000000000000000000400000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 71B85362022D53AF03A17870D8F66614 -Test: Encrypt -Comment: Set 1, vector 102 -Key: 0000000000000000000000000200000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3593FC550A2950C2EF94F6E8F6E90BB3 -Test: Encrypt -Comment: Set 1, vector 103 -Key: 0000000000000000000000000100000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 29E64004DBF1E7833A7CD82EDACD932A -Test: Encrypt -Comment: Set 1, vector 104 -Key: 0000000000000000000000000080000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 715E700DF74A8680F04A48B18AEDB99C -Test: Encrypt -Comment: Set 1, vector 105 -Key: 0000000000000000000000000040000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 72E3288FFB02D1100F84FA605855D812 -Test: Encrypt -Comment: Set 1, vector 106 -Key: 0000000000000000000000000020000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 9021082D3C4CB202936FD76F1392446B -Test: Encrypt -Comment: Set 1, vector 107 -Key: 0000000000000000000000000010000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 1552BD181EE0FB914558053F2662F9AE -Test: Encrypt -Comment: Set 1, vector 108 -Key: 0000000000000000000000000008000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 599D87052322E19141057F0EF3C47508 -Test: Encrypt -Comment: Set 1, vector 109 -Key: 0000000000000000000000000004000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 505AC03CEB2ECA1C9D411B4A1CF2011C -Test: Encrypt -Comment: Set 1, vector 110 -Key: 0000000000000000000000000002000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: DD639574D8FFCD24EA68B2243C5AA7D6 -Test: Encrypt -Comment: Set 1, vector 111 -Key: 0000000000000000000000000001000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 45F5371B714D2652BA4AD083EDB65BEE -Test: Encrypt -Comment: Set 1, vector 112 -Key: 0000000000000000000000000000800000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: DEAB9C368B21FE41E709554340E87C0B -Test: Encrypt -Comment: Set 1, vector 113 -Key: 0000000000000000000000000000400000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3A981045526766BD13943F11CE917AF9 -Test: Encrypt -Comment: Set 1, vector 114 -Key: 0000000000000000000000000000200000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 35CDF30A485CE21F0D005EE0C2BCF315 -Test: Encrypt -Comment: Set 1, vector 115 -Key: 0000000000000000000000000000100000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F561A8C91820252580317385F8336305 -Test: Encrypt -Comment: Set 1, vector 116 -Key: 0000000000000000000000000000080000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0789680D27735220798079572BF4ECF6 -Test: Encrypt -Comment: Set 1, vector 117 -Key: 0000000000000000000000000000040000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B4F16729D7AB16C9AE44FB61291920DE -Test: Encrypt -Comment: Set 1, vector 118 -Key: 0000000000000000000000000000020000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: FB83BF9B1D983CA7FB3718E22D9A2155 -Test: Encrypt -Comment: Set 1, vector 119 -Key: 0000000000000000000000000000010000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: CEC5C5D13E59508D3DA431F1479730F3 -Test: Encrypt -Comment: Set 1, vector 120 -Key: 0000000000000000000000000000008000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 09BEA932E60A4AD34271FF11A2B2AA02 -Test: Encrypt -Comment: Set 1, vector 121 -Key: 0000000000000000000000000000004000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B102F72FD89452C0CD1C6897071F903E -Test: Encrypt -Comment: Set 1, vector 122 -Key: 0000000000000000000000000000002000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: A469F9411F0A3A6E1A8076416C6B55CB -Test: Encrypt -Comment: Set 1, vector 123 -Key: 0000000000000000000000000000001000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 6C3F88FCB538699547A1CF07A529993F -Test: Encrypt -Comment: Set 1, vector 124 -Key: 0000000000000000000000000000000800000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 493E8CC2A63534632A6456ED47BF233C -Test: Encrypt -Comment: Set 1, vector 125 -Key: 0000000000000000000000000000000400000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 1FD81E905F7055C4B04DB1F9718A6861 -Test: Encrypt -Comment: Set 1, vector 126 -Key: 0000000000000000000000000000000200000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B22882E01D7A1BF2D7F0E3BFBFC87156 -Test: Encrypt -Comment: Set 1, vector 127 -Key: 0000000000000000000000000000000100000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 86C9822E849322FB00DF89233D33935D -Test: Encrypt -Comment: Set 1, vector 128 -Key: 0000000000000000000000000000000080000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 12012E8E028D0D3D8DC00847130D424C -Test: Encrypt -Comment: Set 1, vector 129 -Key: 0000000000000000000000000000000040000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 182A96CC3BF10035B9DB292D1399F993 -Test: Encrypt -Comment: Set 1, vector 130 -Key: 0000000000000000000000000000000020000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 91E0E6991989D1FC4CBD754E4E7D0590 -Test: Encrypt -Comment: Set 1, vector 131 -Key: 0000000000000000000000000000000010000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F3EFC4E6F207E370C8CAE39408C4BF1B -Test: Encrypt -Comment: Set 1, vector 132 -Key: 0000000000000000000000000000000008000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: AA767AB2EC6FA2FA183DAF9C0F3BAE5E -Test: Encrypt -Comment: Set 1, vector 133 -Key: 0000000000000000000000000000000004000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: D1FF11F4D1AEEAAE01A115081AF886EF -Test: Encrypt -Comment: Set 1, vector 134 -Key: 0000000000000000000000000000000002000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 5390139711090B56B28338FEA98FCC82 -Test: Encrypt -Comment: Set 1, vector 135 -Key: 0000000000000000000000000000000001000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 13E693CCF6EBF0E6061B92B7ED0B95B6 -Test: Encrypt -Comment: Set 1, vector 136 -Key: 0000000000000000000000000000000000800000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 588FB2F95861D3C427669C68D04ADB25 -Test: Encrypt -Comment: Set 1, vector 137 -Key: 0000000000000000000000000000000000400000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F472ECDF8DEBC416313AAF7C8AAFB43E -Test: Encrypt -Comment: Set 1, vector 138 -Key: 0000000000000000000000000000000000200000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: EAA654BE38E857941A921C70AC7FC7CE -Test: Encrypt -Comment: Set 1, vector 139 -Key: 0000000000000000000000000000000000100000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F2A4E47AE80CDF506B9513C510EA0954 -Test: Encrypt -Comment: Set 1, vector 140 -Key: 0000000000000000000000000000000000080000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F08EC7ED8FBB99F175A990C3E4DECB6B -Test: Encrypt -Comment: Set 1, vector 141 -Key: 0000000000000000000000000000000000040000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 5C767BC584CA3653EDE27CD8B209A0AD -Test: Encrypt -Comment: Set 1, vector 142 -Key: 0000000000000000000000000000000000020000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: AFF9A8BA92A40B2BF42FDB4089B1F9CC -Test: Encrypt -Comment: Set 1, vector 143 -Key: 0000000000000000000000000000000000010000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: BFC1E9198BBE22266712EB1ECB17D748 -Test: Encrypt -Comment: Set 1, vector 144 -Key: 0000000000000000000000000000000000008000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 235184136A29208BD041E60BCB9F7464 -Test: Encrypt -Comment: Set 1, vector 145 -Key: 0000000000000000000000000000000000004000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 83DC48F9177C5C94CBC22E83A2B76829 -Test: Encrypt -Comment: Set 1, vector 146 -Key: 0000000000000000000000000000000000002000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 72CD31ACB7A1A459E4D27C1F26039FA7 -Test: Encrypt -Comment: Set 1, vector 147 -Key: 0000000000000000000000000000000000001000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 139AC4734C3136FD9982FCC7A569B9D3 -Test: Encrypt -Comment: Set 1, vector 148 -Key: 0000000000000000000000000000000000000800000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 12FFA3EF4346F4C57A03A36F9938B251 -Test: Encrypt -Comment: Set 1, vector 149 -Key: 0000000000000000000000000000000000000400000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 43DDB100CE22E5553CF4DCF814BF3CAC -Test: Encrypt -Comment: Set 1, vector 150 -Key: 0000000000000000000000000000000000000200000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: ABDADF4C948BB61C0A917885ADE4C7C5 -Test: Encrypt -Comment: Set 1, vector 151 -Key: 0000000000000000000000000000000000000100000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 197391E089DE173B522DDD8CBEEC3118 -Test: Encrypt -Comment: Set 1, vector 152 -Key: 0000000000000000000000000000000000000080000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 43FBE8BF2728C55C9368D01E40C1CF96 -Test: Encrypt -Comment: Set 1, vector 153 -Key: 0000000000000000000000000000000000000040000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0F5DE5F67EC84F2CB253A0BC48991C71 -Test: Encrypt -Comment: Set 1, vector 154 -Key: 0000000000000000000000000000000000000020000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 52BA4666B972EAE3D2E960D7372D3C48 -Test: Encrypt -Comment: Set 1, vector 155 -Key: 0000000000000000000000000000000000000010000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0735AE765BC079A93B451D873FA93702 -Test: Encrypt -Comment: Set 1, vector 156 -Key: 0000000000000000000000000000000000000008000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 89D988508A4569E2232F72412AE50B65 -Test: Encrypt -Comment: Set 1, vector 157 -Key: 0000000000000000000000000000000000000004000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: BCF0EE2403BC9344030C0FF065B6FD88 -Test: Encrypt -Comment: Set 1, vector 158 -Key: 0000000000000000000000000000000000000002000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 25D76D36F3376D6FD835BA012C7DD2E5 -Test: Encrypt -Comment: Set 1, vector 159 -Key: 0000000000000000000000000000000000000001000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: EF364A31E8551732D4B2098281D4E2C9 -Test: Encrypt -Comment: Set 1, vector 160 -Key: 0000000000000000000000000000000000000000800000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 64B1F927C0A7315EA60BC5F2A0DCCFE2 -Test: Encrypt -Comment: Set 1, vector 161 -Key: 0000000000000000000000000000000000000000400000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: CA99E0EDFA0E121F27659346BCDCC443 -Test: Encrypt -Comment: Set 1, vector 162 -Key: 0000000000000000000000000000000000000000200000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 1816D9D23D1069BC6DEC195F60994C05 -Test: Encrypt -Comment: Set 1, vector 163 -Key: 0000000000000000000000000000000000000000100000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 9819575F6890E093091378AED0612051 -Test: Encrypt -Comment: Set 1, vector 164 -Key: 0000000000000000000000000000000000000000080000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 41903DE72A486B823842FBA2840E265C -Test: Encrypt -Comment: Set 1, vector 165 -Key: 0000000000000000000000000000000000000000040000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 30651D416912A01EDEC4290D34B4A605 -Test: Encrypt -Comment: Set 1, vector 166 -Key: 0000000000000000000000000000000000000000020000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0949AD8AB2E85995686D6D495ABA1028 -Test: Encrypt -Comment: Set 1, vector 167 -Key: 0000000000000000000000000000000000000000010000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3789C2D08E122BE204662FE9A0FDF77A -Test: Encrypt -Comment: Set 1, vector 168 -Key: 0000000000000000000000000000000000000000008000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: A0C66EE031FF045123475E6F5FA64F57 -Test: Encrypt -Comment: Set 1, vector 169 -Key: 0000000000000000000000000000000000000000004000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 1BACCDD314AF39124709013C94CAD1AC -Test: Encrypt -Comment: Set 1, vector 170 -Key: 0000000000000000000000000000000000000000002000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 2FB5DF5527A8E06AED03D683EDF14E9A -Test: Encrypt -Comment: Set 1, vector 171 -Key: 0000000000000000000000000000000000000000001000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: FF2C61AD63CDA6207605C18C888B383D -Test: Encrypt -Comment: Set 1, vector 172 -Key: 0000000000000000000000000000000000000000000800000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 71CE4A5B48671AB9A6561B7109FB8345 -Test: Encrypt -Comment: Set 1, vector 173 -Key: 0000000000000000000000000000000000000000000400000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 37299C12377E9CB8DF5FE730DFFCB5CA -Test: Encrypt -Comment: Set 1, vector 174 -Key: 0000000000000000000000000000000000000000000200000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: C5454350A7CB0EC5CA3932A3948F48BC -Test: Encrypt -Comment: Set 1, vector 175 -Key: 0000000000000000000000000000000000000000000100000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 8AB40D09FFBD0C82E9091FC80D2A63C9 -Test: Encrypt -Comment: Set 1, vector 176 -Key: 0000000000000000000000000000000000000000000080000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 9CB3FE43EAE3DC7AC4F97E609FDE9F10 -Test: Encrypt -Comment: Set 1, vector 177 -Key: 0000000000000000000000000000000000000000000040000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 51369DC689B25C3AC593B578BAEA046E -Test: Encrypt -Comment: Set 1, vector 178 -Key: 0000000000000000000000000000000000000000000020000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 13D9D885A24AE8B859F239890DF438C9 -Test: Encrypt -Comment: Set 1, vector 179 -Key: 0000000000000000000000000000000000000000000010000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: CEACAE376290D5C62D2DAE422CA6E5C0 -Test: Encrypt -Comment: Set 1, vector 180 -Key: 0000000000000000000000000000000000000000000008000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 6AE17D621F97B62F4571AB165CE0A11F -Test: Encrypt -Comment: Set 1, vector 181 -Key: 0000000000000000000000000000000000000000000004000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: C91318F8FD17E9BC656E639A0D648B3A -Test: Encrypt -Comment: Set 1, vector 182 -Key: 0000000000000000000000000000000000000000000002000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: BFF1BC1C935E40FB0C20DED5985F1910 -Test: Encrypt -Comment: Set 1, vector 183 -Key: 0000000000000000000000000000000000000000000001000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 96F0B387F487BBDD5227B595A506F963 -Test: Encrypt -Comment: Set 1, vector 184 -Key: 0000000000000000000000000000000000000000000000800000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 62265B7EFB73A77205ECBBFD166B3EAE -Test: Encrypt -Comment: Set 1, vector 185 -Key: 0000000000000000000000000000000000000000000000400000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 016E8F3087757E8F576B19A58D356FB6 -Test: Encrypt -Comment: Set 1, vector 186 -Key: 0000000000000000000000000000000000000000000000200000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 456FAF632EA07797CEC23DC6553988F9 -Test: Encrypt -Comment: Set 1, vector 187 -Key: 0000000000000000000000000000000000000000000000100000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 147694E2231FA00D6B62D3E51CC8201D -Test: Encrypt -Comment: Set 1, vector 188 -Key: 0000000000000000000000000000000000000000000000080000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 2299D31F3D747838C65FE7C6C0C59214 -Test: Encrypt -Comment: Set 1, vector 189 -Key: 0000000000000000000000000000000000000000000000040000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: C5A669612A23E4F7551D79650071E040 -Test: Encrypt -Comment: Set 1, vector 190 -Key: 0000000000000000000000000000000000000000000000020000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F0A32D722EDFD2BA628C781DACD5FC50 -Test: Encrypt -Comment: Set 1, vector 191 -Key: 0000000000000000000000000000000000000000000000010000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 422C8E2A0DFF095E40654CB2B7176A9B -Test: Encrypt -Comment: Set 1, vector 192 -Key: 0000000000000000000000000000000000000000000000008000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 99DEF168961D4AB9E63157E60F76399C -Test: Encrypt -Comment: Set 1, vector 193 -Key: 0000000000000000000000000000000000000000000000004000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 49C92ACC622A00BCFF7DFDCABF33CB4C -Test: Encrypt -Comment: Set 1, vector 194 -Key: 0000000000000000000000000000000000000000000000002000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 517117A096B2EE66D4BEF2D1EE570CE7 -Test: Encrypt -Comment: Set 1, vector 195 -Key: 0000000000000000000000000000000000000000000000001000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 9DAECC0E82559BC2CDB8A01AB30BA605 -Test: Encrypt -Comment: Set 1, vector 196 -Key: 0000000000000000000000000000000000000000000000000800000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 50B2882928DAB54488413ABA5743535E -Test: Encrypt -Comment: Set 1, vector 197 -Key: 0000000000000000000000000000000000000000000000000400000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E6725F73ED920F473E1442ABEC7DB722 -Test: Encrypt -Comment: Set 1, vector 198 -Key: 0000000000000000000000000000000000000000000000000200000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: CB4F06002C5864E40C80F97157452575 -Test: Encrypt -Comment: Set 1, vector 199 -Key: 0000000000000000000000000000000000000000000000000100000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 8DF72D7C8AE547F2AA3E9AFAAD1D62F0 -Test: Encrypt -Comment: Set 1, vector 200 -Key: 0000000000000000000000000000000000000000000000000080000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0DA429E486F5ED9460B7C54460B0A699 -Test: Encrypt -Comment: Set 1, vector 201 -Key: 0000000000000000000000000000000000000000000000000040000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 24832DB462328D93306C6714E100ADAB -Test: Encrypt -Comment: Set 1, vector 202 -Key: 0000000000000000000000000000000000000000000000000020000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3170D82FEC3D2A58C7D2F28BAC4C7809 -Test: Encrypt -Comment: Set 1, vector 203 -Key: 0000000000000000000000000000000000000000000000000010000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 638A46425AEA9C808AC752EE69F56822 -Test: Encrypt -Comment: Set 1, vector 204 -Key: 0000000000000000000000000000000000000000000000000008000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F98954D90C5E3DB2EEC8A86078D70763 -Test: Encrypt -Comment: Set 1, vector 205 -Key: 0000000000000000000000000000000000000000000000000004000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 8D5868451617FB145B8F7F91712A7AA0 -Test: Encrypt -Comment: Set 1, vector 206 -Key: 0000000000000000000000000000000000000000000000000002000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 2292BA337A4F465E0DFB85DAAC266AE6 -Test: Encrypt -Comment: Set 1, vector 207 -Key: 0000000000000000000000000000000000000000000000000001000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F2560D5063A2F928D699005012A0C839 -Test: Encrypt -Comment: Set 1, vector 208 -Key: 0000000000000000000000000000000000000000000000000000800000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 44968AEABB2852075F83FB942E05099D -Test: Encrypt -Comment: Set 1, vector 209 -Key: 0000000000000000000000000000000000000000000000000000400000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: EB339742AB40B5627A7CB60D4F54DD2E -Test: Encrypt -Comment: Set 1, vector 210 -Key: 0000000000000000000000000000000000000000000000000000200000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 9AAA6FC3BBDE523E9FCD9D5C0255F912 -Test: Encrypt -Comment: Set 1, vector 211 -Key: 0000000000000000000000000000000000000000000000000000100000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E6E25CBAFF57F4C6056706FD13E6A2E3 -Test: Encrypt -Comment: Set 1, vector 212 -Key: 0000000000000000000000000000000000000000000000000000080000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 8A9628166922E8EC6FC28F5E847B9C71 -Test: Encrypt -Comment: Set 1, vector 213 -Key: 0000000000000000000000000000000000000000000000000000040000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 97CF8FF5D1337DA8602F8AB6C0224AF7 -Test: Encrypt -Comment: Set 1, vector 214 -Key: 0000000000000000000000000000000000000000000000000000020000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: DDBBE09A93364599E9233969ADBEBA63 -Test: Encrypt -Comment: Set 1, vector 215 -Key: 0000000000000000000000000000000000000000000000000000010000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: E772954B9DA3DA8A005582C4E9E5B6FA -Test: Encrypt -Comment: Set 1, vector 216 -Key: 0000000000000000000000000000000000000000000000000000008000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 507DFD30F7EEF807F994B298D487FDE6 -Test: Encrypt -Comment: Set 1, vector 217 -Key: 0000000000000000000000000000000000000000000000000000004000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 6FF09F69AED61F091F92503547A19B68 -Test: Encrypt -Comment: Set 1, vector 218 -Key: 0000000000000000000000000000000000000000000000000000002000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 1141E6BB725E09640DD6971F4EF1A886 -Test: Encrypt -Comment: Set 1, vector 219 -Key: 0000000000000000000000000000000000000000000000000000001000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 9C0E8061BA0361B730D24675EF128705 -Test: Encrypt -Comment: Set 1, vector 220 -Key: 0000000000000000000000000000000000000000000000000000000800000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7D0137240D0D3D086198E83BC0CF22D0 -Test: Encrypt -Comment: Set 1, vector 221 -Key: 0000000000000000000000000000000000000000000000000000000400000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: BC4460FF55EBFAA1171B0CE249830281 -Test: Encrypt -Comment: Set 1, vector 222 -Key: 0000000000000000000000000000000000000000000000000000000200000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: CDBE93ADCF1867B952FB82C42DF60CFD -Test: Encrypt -Comment: Set 1, vector 223 -Key: 0000000000000000000000000000000000000000000000000000000100000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 007AA375E4402B8A5657C01259AF3D49 -Test: Encrypt -Comment: Set 1, vector 224 -Key: 0000000000000000000000000000000000000000000000000000000080000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: F5C2B13998E5687C773017C14EB01FE4 -Test: Encrypt -Comment: Set 1, vector 225 -Key: 0000000000000000000000000000000000000000000000000000000040000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0AE71BFDD72FBC4576305E4B0807E17C -Test: Encrypt -Comment: Set 1, vector 226 -Key: 0000000000000000000000000000000000000000000000000000000020000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 35FB1CE6CB7449DF115D3AC6BA656439 -Test: Encrypt -Comment: Set 1, vector 227 -Key: 0000000000000000000000000000000000000000000000000000000010000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 6D64CEC5D9D74BD40FBC0BE69C70B777 -Test: Encrypt -Comment: Set 1, vector 228 -Key: 0000000000000000000000000000000000000000000000000000000008000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7257851ACD3E3E3AE50048973C3A2AE8 -Test: Encrypt -Comment: Set 1, vector 229 -Key: 0000000000000000000000000000000000000000000000000000000004000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 50852661D5BD7960412B29A86F549619 -Test: Encrypt -Comment: Set 1, vector 230 -Key: 0000000000000000000000000000000000000000000000000000000002000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: CDF3561D971D40521CD46BAE98F5867A -Test: Encrypt -Comment: Set 1, vector 231 -Key: 0000000000000000000000000000000000000000000000000000000001000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: FA3C84185B9ABF9887DD501B3B0F52D3 -Test: Encrypt -Comment: Set 1, vector 232 -Key: 0000000000000000000000000000000000000000000000000000000000800000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 40A5B434F81574733D00F25511109E08 -Test: Encrypt -Comment: Set 1, vector 233 -Key: 0000000000000000000000000000000000000000000000000000000000400000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: DA0D248315C527572F1673BDE26A475E -Test: Encrypt -Comment: Set 1, vector 234 -Key: 0000000000000000000000000000000000000000000000000000000000200000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0F8366D8EFB9AB63B0299F278C55CFB4 -Test: Encrypt -Comment: Set 1, vector 235 -Key: 0000000000000000000000000000000000000000000000000000000000100000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 25A089C523CD153EC094862B5923F492 -Test: Encrypt -Comment: Set 1, vector 236 -Key: 0000000000000000000000000000000000000000000000000000000000080000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7268A4628C6A0BE6A8391ABE70986176 -Test: Encrypt -Comment: Set 1, vector 237 -Key: 0000000000000000000000000000000000000000000000000000000000040000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7C11E6478CC688FE707454DF4AB5B666 -Test: Encrypt -Comment: Set 1, vector 238 -Key: 0000000000000000000000000000000000000000000000000000000000020000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 7601B6EBD5CE578973E949C21BFA8CAA -Test: Encrypt -Comment: Set 1, vector 239 -Key: 0000000000000000000000000000000000000000000000000000000000010000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0FCE9CCDF89F2EB139DBEB09B55375D5 -Test: Encrypt -Comment: Set 1, vector 240 -Key: 0000000000000000000000000000000000000000000000000000000000008000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: AAABFDD9E28A3ADCA1212F3D7F53A269 -Test: Encrypt -Comment: Set 1, vector 241 -Key: 0000000000000000000000000000000000000000000000000000000000004000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: FC6B4304423917E41677768BD7A8D402 -Test: Encrypt -Comment: Set 1, vector 242 -Key: 0000000000000000000000000000000000000000000000000000000000002000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 2AA3239D19ADBA9A4190E3653875C589 -Test: Encrypt -Comment: Set 1, vector 243 -Key: 0000000000000000000000000000000000000000000000000000000000001000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 4F4AB0DB2F3D3EA1E5FCBF99651485DC -Test: Encrypt -Comment: Set 1, vector 244 -Key: 0000000000000000000000000000000000000000000000000000000000000800 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B542CEF08D13E300B282CE6A74C51C96 -Test: Encrypt -Comment: Set 1, vector 245 -Key: 0000000000000000000000000000000000000000000000000000000000000400 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 9955E16433B0D58BFC4B35EE9F44734C -Test: Encrypt -Comment: Set 1, vector 246 -Key: 0000000000000000000000000000000000000000000000000000000000000200 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 5027A7DDC6F99A112E45D3090C7C3465 -Test: Encrypt -Comment: Set 1, vector 247 -Key: 0000000000000000000000000000000000000000000000000000000000000100 -Plaintext: 00000000000000000000000000000000 -Ciphertext: CB14EBD24FC63194495FACFFB5C3A07B -Test: Encrypt -Comment: Set 1, vector 248 -Key: 0000000000000000000000000000000000000000000000000000000000000080 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 2BCBE64545A08F59178242452566B997 -Test: Encrypt -Comment: Set 1, vector 249 -Key: 0000000000000000000000000000000000000000000000000000000000000040 -Plaintext: 00000000000000000000000000000000 -Ciphertext: DE428FF12360A0C8FAE73E9D8E6A0657 -Test: Encrypt -Comment: Set 1, vector 250 -Key: 0000000000000000000000000000000000000000000000000000000000000020 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 6425603FCB0F088D87D3AC7078C7014C -Test: Encrypt -Comment: Set 1, vector 251 -Key: 0000000000000000000000000000000000000000000000000000000000000010 -Plaintext: 00000000000000000000000000000000 -Ciphertext: A837813C9436F4C48C45B6C85A4EAF84 -Test: Encrypt -Comment: Set 1, vector 252 -Key: 0000000000000000000000000000000000000000000000000000000000000008 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B95F9010E694BA44B812D6A7A59E027A -Test: Encrypt -Comment: Set 1, vector 253 -Key: 0000000000000000000000000000000000000000000000000000000000000004 -Plaintext: 00000000000000000000000000000000 -Ciphertext: DF2746A2D9ED707DCC686BB64B77C9DD -Test: Encrypt -Comment: Set 1, vector 254 -Key: 0000000000000000000000000000000000000000000000000000000000000002 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 40DD304C3FC8FEF5D7D08FD467E018F6 -Test: Encrypt -Comment: Set 1, vector 255 -Key: 0000000000000000000000000000000000000000000000000000000000000001 -Plaintext: 00000000000000000000000000000000 -Ciphertext: AFCD38B195E0A736304E89B9AE3019D3 -Test: Encrypt -Comment: Set 2, vector 0 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 80000000000000000000000000000000 -Ciphertext: B0C6B88AEA518AB09E847248E91B1B9D -Test: Encrypt -Comment: Set 2, vector 1 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 40000000000000000000000000000000 -Ciphertext: B8D7684E35FA1DB15BDCEE7A48659858 -Test: Encrypt -Comment: Set 2, vector 2 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 20000000000000000000000000000000 -Ciphertext: F0CAD59AF92FBB79F36951E697492750 -Test: Encrypt -Comment: Set 2, vector 3 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 10000000000000000000000000000000 -Ciphertext: 117100F6635389560DC4A2DA24EBA70F -Test: Encrypt -Comment: Set 2, vector 4 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 08000000000000000000000000000000 -Ciphertext: DBDD62355553019ED84C35886421E532 -Test: Encrypt -Comment: Set 2, vector 5 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 04000000000000000000000000000000 -Ciphertext: 9CB8D04FA506F19848F7B9110518BFC8 -Test: Encrypt -Comment: Set 2, vector 6 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 02000000000000000000000000000000 -Ciphertext: E4308E253BC3444D293500701BA82C6A -Test: Encrypt -Comment: Set 2, vector 7 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 01000000000000000000000000000000 -Ciphertext: EA2FAE53F7F30C0170A20E95A068503E -Test: Encrypt -Comment: Set 2, vector 8 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00800000000000000000000000000000 -Ciphertext: 14B14839EA221880B2C64D1FE000B93D -Test: Encrypt -Comment: Set 2, vector 9 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00400000000000000000000000000000 -Ciphertext: A5CFC075B342D5101AACC334E73058BB -Test: Encrypt -Comment: Set 2, vector 10 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00200000000000000000000000000000 -Ciphertext: 477EA56B2EBAD0F8AC5E1936866560FF -Test: Encrypt -Comment: Set 2, vector 11 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00100000000000000000000000000000 -Ciphertext: 107E8598418404196EC59F63E45B7F6D -Test: Encrypt -Comment: Set 2, vector 12 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00080000000000000000000000000000 -Ciphertext: FF6A891E7C1C074A68FEC291928FDD8D -Test: Encrypt -Comment: Set 2, vector 13 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00040000000000000000000000000000 -Ciphertext: F64C250A13F45D377ADB7545B2B157A9 -Test: Encrypt -Comment: Set 2, vector 14 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00020000000000000000000000000000 -Ciphertext: FAD0F252086F11C830C65B63197CBC38 -Test: Encrypt -Comment: Set 2, vector 15 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00010000000000000000000000000000 -Ciphertext: 9DCB89B209441F02AD0D25C6AB826629 -Test: Encrypt -Comment: Set 2, vector 16 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00008000000000000000000000000000 -Ciphertext: E62E4ED4E4F34EDC563710D960E09D4C -Test: Encrypt -Comment: Set 2, vector 17 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00004000000000000000000000000000 -Ciphertext: 98A1B926BA06895C3F2E84CCBACBC356 -Test: Encrypt -Comment: Set 2, vector 18 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00002000000000000000000000000000 -Ciphertext: 29BE0BE4DB7F4D196718AEA38F3B0BFD -Test: Encrypt -Comment: Set 2, vector 19 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00001000000000000000000000000000 -Ciphertext: F670C4EBECBA0B43E71F6D752BFD4854 -Test: Encrypt -Comment: Set 2, vector 20 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000800000000000000000000000000 -Ciphertext: 7D7666B4484CDB7E3605468E093A787C -Test: Encrypt -Comment: Set 2, vector 21 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000400000000000000000000000000 -Ciphertext: 562D06B181C091DA6C43642AE99460C6 -Test: Encrypt -Comment: Set 2, vector 22 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000200000000000000000000000000 -Ciphertext: AB0EFB5975E6186B7D76BC9672453488 -Test: Encrypt -Comment: Set 2, vector 23 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000100000000000000000000000000 -Ciphertext: 10C0756538E7BFF88D19AE2B1F7B859A -Test: Encrypt -Comment: Set 2, vector 24 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000080000000000000000000000000 -Ciphertext: AF7FCD5248F8C72F1695AA05DD1CADE0 -Test: Encrypt -Comment: Set 2, vector 25 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000040000000000000000000000000 -Ciphertext: 9841E555655609A75D7BE20B8A90EF1E -Test: Encrypt -Comment: Set 2, vector 26 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000020000000000000000000000000 -Ciphertext: 27F9546E6A1B7464780000561783569C -Test: Encrypt -Comment: Set 2, vector 27 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000010000000000000000000000000 -Ciphertext: 8671D935D7A8354EECB7288803D42D7A -Test: Encrypt -Comment: Set 2, vector 28 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000008000000000000000000000000 -Ciphertext: 0DA44F508DEBC6F044394624FCEB8EBE -Test: Encrypt -Comment: Set 2, vector 29 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000004000000000000000000000000 -Ciphertext: AB137369BE6D93FBB18006BDB236EC09 -Test: Encrypt -Comment: Set 2, vector 30 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000002000000000000000000000000 -Ciphertext: EB90C4E597A7E1779FFA260886E26F75 -Test: Encrypt -Comment: Set 2, vector 31 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000001000000000000000000000000 -Ciphertext: 618CF3588D5C128EAF252616230E08F7 -Test: Encrypt -Comment: Set 2, vector 32 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000800000000000000000000000 -Ciphertext: 98DC4DB49D197AB9152D12B9DE2D73CA -Test: Encrypt -Comment: Set 2, vector 33 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000400000000000000000000000 -Ciphertext: 5BDDE24B15702A35E1F140C57D206443 -Test: Encrypt -Comment: Set 2, vector 34 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000200000000000000000000000 -Ciphertext: CF755809882BED8BA2F9F1A4ED296A2B -Test: Encrypt -Comment: Set 2, vector 35 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000100000000000000000000000 -Ciphertext: F1A8DBB999538AE89D16F92A7F4D1DF1 -Test: Encrypt -Comment: Set 2, vector 36 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000080000000000000000000000 -Ciphertext: 775222FDDAAECB81CF675C4E0B98179E -Test: Encrypt -Comment: Set 2, vector 37 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000040000000000000000000000 -Ciphertext: 12A648CADCD153C760A965826683119A -Test: Encrypt -Comment: Set 2, vector 38 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000020000000000000000000000 -Ciphertext: 0503FB10AB241E7CF45D8CDEEE474335 -Test: Encrypt -Comment: Set 2, vector 39 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000010000000000000000000000 -Ciphertext: 3D299C0070CBBD831B802690B8E7CA24 -Test: Encrypt -Comment: Set 2, vector 40 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000008000000000000000000000 -Ciphertext: 33105BD4D11D66753DC34D128BEFE3F4 -Test: Encrypt -Comment: Set 2, vector 41 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000004000000000000000000000 -Ciphertext: 5EFCE2B4B987C0F77D27B44836881682 -Test: Encrypt -Comment: Set 2, vector 42 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000002000000000000000000000 -Ciphertext: 7835449454128035D7F0EA99E327577B -Test: Encrypt -Comment: Set 2, vector 43 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000001000000000000000000000 -Ciphertext: 27BEDDA0601BE35122FB1D272D73AB3E -Test: Encrypt -Comment: Set 2, vector 44 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000800000000000000000000 -Ciphertext: 54C3F99FF48E318CC515EDE75800C4B3 -Test: Encrypt -Comment: Set 2, vector 45 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000400000000000000000000 -Ciphertext: C627C329F8E48299F6FDB23B9DBEA0BB -Test: Encrypt -Comment: Set 2, vector 46 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000200000000000000000000 -Ciphertext: 1B6578F9E23BD8C1845A02431C5F9AA3 -Test: Encrypt -Comment: Set 2, vector 47 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000100000000000000000000 -Ciphertext: 6DB2FB8C0B9344D0547C0FF1292020C6 -Test: Encrypt -Comment: Set 2, vector 48 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000080000000000000000000 -Ciphertext: 4FAD9B2C37C131493FBEF53581FA4F83 -Test: Encrypt -Comment: Set 2, vector 49 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000040000000000000000000 -Ciphertext: 47502A01E93D2C87BD5584F6AFD3D99D -Test: Encrypt -Comment: Set 2, vector 50 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000020000000000000000000 -Ciphertext: 056E1C6F651BFE50271B3B7A18E76D84 -Test: Encrypt -Comment: Set 2, vector 51 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000010000000000000000000 -Ciphertext: 5632BAF6627B3D96AD4E06FA6A561F55 -Test: Encrypt -Comment: Set 2, vector 52 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000008000000000000000000 -Ciphertext: E29807CAACDFA2D41A7D9E91FA7FD8EB -Test: Encrypt -Comment: Set 2, vector 53 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000004000000000000000000 -Ciphertext: 81DD44BB5D1822DEE605F9E6FF01D7B3 -Test: Encrypt -Comment: Set 2, vector 54 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000002000000000000000000 -Ciphertext: 5C3649925E47D7FF96482A8FBD9666FD -Test: Encrypt -Comment: Set 2, vector 55 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000001000000000000000000 -Ciphertext: 695415A836E66E737887845EC08A1ADB -Test: Encrypt -Comment: Set 2, vector 56 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000800000000000000000 -Ciphertext: F5416BCE292D9E2CEA5D1CC70BBAEED1 -Test: Encrypt -Comment: Set 2, vector 57 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000400000000000000000 -Ciphertext: 7AEC4F1388FC29C47F7FED74ADDE8485 -Test: Encrypt -Comment: Set 2, vector 58 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000200000000000000000 -Ciphertext: 82A9F1A6CE08BC4876E649D8A8EA7EB6 -Test: Encrypt -Comment: Set 2, vector 59 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000100000000000000000 -Ciphertext: B6296C88ADF1A792908B065EEB04BFC2 -Test: Encrypt -Comment: Set 2, vector 60 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000080000000000000000 -Ciphertext: E766A39AECCA40BDBFBE6FF3FA292913 -Test: Encrypt -Comment: Set 2, vector 61 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000040000000000000000 -Ciphertext: C6D081454EA00D83C23B5A62C84359E1 -Test: Encrypt -Comment: Set 2, vector 62 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000020000000000000000 -Ciphertext: 85D259A79CCA80484504D1603F7A8F53 -Test: Encrypt -Comment: Set 2, vector 63 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000010000000000000000 -Ciphertext: D8291FA1C6DC250078824B2D0A20883F -Test: Encrypt -Comment: Set 2, vector 64 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000008000000000000000 -Ciphertext: 95387CB74C48FFBD1F8D64A6CC45E074 -Test: Encrypt -Comment: Set 2, vector 65 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000004000000000000000 -Ciphertext: A17F975F538F56CDF629B516011DE837 -Test: Encrypt -Comment: Set 2, vector 66 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000002000000000000000 -Ciphertext: B50B615A1654C6E1CB6AB33716C097FE -Test: Encrypt -Comment: Set 2, vector 67 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000001000000000000000 -Ciphertext: 7BBB2CBB874DF6C8B821DA7FB0F9011B -Test: Encrypt -Comment: Set 2, vector 68 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000800000000000000 -Ciphertext: E9EFE074D096A275E47CD2E6206DF6A1 -Test: Encrypt -Comment: Set 2, vector 69 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000400000000000000 -Ciphertext: 88F2F8D5A836406AE8BBB98C65BBDA55 -Test: Encrypt -Comment: Set 2, vector 70 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000200000000000000 -Ciphertext: F64620D8D87585A3EF038B9AD58F5EA0 -Test: Encrypt -Comment: Set 2, vector 71 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000100000000000000 -Ciphertext: 694438EC141C8ED5F2F898B4554A298F -Test: Encrypt -Comment: Set 2, vector 72 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000080000000000000 -Ciphertext: 3E6226EC7726A1EE5F5FA9B18CCE8C44 -Test: Encrypt -Comment: Set 2, vector 73 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000040000000000000 -Ciphertext: 8AB6949E79911647800B9E87362AB97A -Test: Encrypt -Comment: Set 2, vector 74 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000020000000000000 -Ciphertext: 093C5CF24EDAF7F9F1C8A80DE4FF50A9 -Test: Encrypt -Comment: Set 2, vector 75 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000010000000000000 -Ciphertext: 28A36E50061F19E240351ED0E378CBF4 -Test: Encrypt -Comment: Set 2, vector 76 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000008000000000000 -Ciphertext: B93BB36CB88BF26EA79198652AA51D3C -Test: Encrypt -Comment: Set 2, vector 77 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000004000000000000 -Ciphertext: DE4948083D044FAC9BCA6DA8CD67B8A6 -Test: Encrypt -Comment: Set 2, vector 78 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000002000000000000 -Ciphertext: 6E778B5BDA6CA118117E47470D080D3C -Test: Encrypt -Comment: Set 2, vector 79 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000001000000000000 -Ciphertext: 0A9107324DA32B4281D032A3487EF875 -Test: Encrypt -Comment: Set 2, vector 80 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000800000000000 -Ciphertext: 18ED5635312D71ABD123CCE779D4D68A -Test: Encrypt -Comment: Set 2, vector 81 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000400000000000 -Ciphertext: 2E3C63F95C4BC1F944BAB06DEDC9AA8E -Test: Encrypt -Comment: Set 2, vector 82 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000200000000000 -Ciphertext: ACCC869EF07004C8C3C709083BE7BA2F -Test: Encrypt -Comment: Set 2, vector 83 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000100000000000 -Ciphertext: DF60B34FB1A59147CC1FB049C1578206 -Test: Encrypt -Comment: Set 2, vector 84 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000080000000000 -Ciphertext: 4228DC636C08E41021054AA0E1E2227A -Test: Encrypt -Comment: Set 2, vector 85 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000040000000000 -Ciphertext: 7CE27F66EFD735FFD6B3E1738C50495B -Test: Encrypt -Comment: Set 2, vector 86 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000020000000000 -Ciphertext: F8E74B33A9CDE351DA0BBC06D69093D7 -Test: Encrypt -Comment: Set 2, vector 87 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000010000000000 -Ciphertext: AE0D22A5B37B8DC5D81CC641EED334D0 -Test: Encrypt -Comment: Set 2, vector 88 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000008000000000 -Ciphertext: C181C6CA5E163743458B9167A0B6A16A -Test: Encrypt -Comment: Set 2, vector 89 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000004000000000 -Ciphertext: 5171F4F6095E4B276CFBA1F07223FBE6 -Test: Encrypt -Comment: Set 2, vector 90 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000002000000000 -Ciphertext: 2732F4D3A8C9D1D8D493840D6E0B864F -Test: Encrypt -Comment: Set 2, vector 91 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000001000000000 -Ciphertext: 3EF04E0059A061D973532CA5C1DFBE7B -Test: Encrypt -Comment: Set 2, vector 92 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000800000000 -Ciphertext: 6D9A8F23579E4978EBAA87B5ADEB77E5 -Test: Encrypt -Comment: Set 2, vector 93 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000400000000 -Ciphertext: BBD08873CC44BA4253C0C41FEEB7F124 -Test: Encrypt -Comment: Set 2, vector 94 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000200000000 -Ciphertext: 72E4B2437CBD283F3809CE686F6A591E -Test: Encrypt -Comment: Set 2, vector 95 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000100000000 -Ciphertext: 6E5580514B92512B1BF4B1B987B9AA1B -Test: Encrypt -Comment: Set 2, vector 96 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000080000000 -Ciphertext: 5EF5D0C5BCBDCB604D3A083B68CE0FA3 -Test: Encrypt -Comment: Set 2, vector 97 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000040000000 -Ciphertext: 9D991FDD723AD2182777A15CA0E0F665 -Test: Encrypt -Comment: Set 2, vector 98 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000020000000 -Ciphertext: 24440626EFC8F86BEA7DE78085AB8A22 -Test: Encrypt -Comment: Set 2, vector 99 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000010000000 -Ciphertext: 17C3630D62D13C1E826C0FCCBD74A864 -Test: Encrypt -Comment: Set 2, vector 100 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000008000000 -Ciphertext: 4CF5AB86A56AB134A7FE46CCE3F9FCE9 -Test: Encrypt -Comment: Set 2, vector 101 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000004000000 -Ciphertext: 3E6B9C0388F6D9B8F458F30221907607 -Test: Encrypt -Comment: Set 2, vector 102 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000002000000 -Ciphertext: AD9C926B8A5CD98EEE88200617E59958 -Test: Encrypt -Comment: Set 2, vector 103 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000001000000 -Ciphertext: AFF8AED5E075E02AF720CA4BF0028B3B -Test: Encrypt -Comment: Set 2, vector 104 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000800000 -Ciphertext: D90EAFF909202BB209BB3BB8C7F9A954 -Test: Encrypt -Comment: Set 2, vector 105 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000400000 -Ciphertext: 2C709B00E6A22F00F64A7D8EE341853F -Test: Encrypt -Comment: Set 2, vector 106 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000200000 -Ciphertext: CCEC598F0D9F0BF201B2F487136D54A4 -Test: Encrypt -Comment: Set 2, vector 107 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000100000 -Ciphertext: 73B2883A0A166AAE1BF14E60A5195FA3 -Test: Encrypt -Comment: Set 2, vector 108 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000080000 -Ciphertext: E676867BD9AD5EF915143388496779D7 -Test: Encrypt -Comment: Set 2, vector 109 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000040000 -Ciphertext: CDCB73D1BFCFD4BE7F1DAA9B1C6A4055 -Test: Encrypt -Comment: Set 2, vector 110 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000020000 -Ciphertext: 02A3A5C89DAA24CD2C517F7A73286A89 -Test: Encrypt -Comment: Set 2, vector 111 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000010000 -Ciphertext: C0FA2AC9E92EE58C2DD12D6D43AB7035 -Test: Encrypt -Comment: Set 2, vector 112 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000008000 -Ciphertext: EDC2CB1F7291353BDBF2385519E6AE16 -Test: Encrypt -Comment: Set 2, vector 113 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000004000 -Ciphertext: B4B62D16D197A98CD3B978812B9D9884 -Test: Encrypt -Comment: Set 2, vector 114 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000002000 -Ciphertext: 5CDFC95A529A905101CEA26BC1B891ED -Test: Encrypt -Comment: Set 2, vector 115 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000001000 -Ciphertext: CC7150CD3650B98363296C7C4ED368D1 -Test: Encrypt -Comment: Set 2, vector 116 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000800 -Ciphertext: CC57706B0C6526B8E25A5DBD32EACBDB -Test: Encrypt -Comment: Set 2, vector 117 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000400 -Ciphertext: 30D30456AD98B182D64C649648F6AEC9 -Test: Encrypt -Comment: Set 2, vector 118 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000200 -Ciphertext: D7E9DA7F631938EB649A08AF82FBD75F -Test: Encrypt -Comment: Set 2, vector 119 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000100 -Ciphertext: B8DA2AF6600B07895B5D0FFAF4991469 -Test: Encrypt -Comment: Set 2, vector 120 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000080 -Ciphertext: 0F6F64F930BA6C178943322B98114599 -Test: Encrypt -Comment: Set 2, vector 121 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000040 -Ciphertext: 8B1F247802E47C91BEE2AA34ECFD7A01 -Test: Encrypt -Comment: Set 2, vector 122 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000020 -Ciphertext: 7A6985778D3A66E97F23E01F0D0E45E7 -Test: Encrypt -Comment: Set 2, vector 123 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000010 -Ciphertext: BA664AC39855518DFDEE10D1B3111FAE -Test: Encrypt -Comment: Set 2, vector 124 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000008 -Ciphertext: 7C92854D801A1648F65CA81813DDBF83 -Test: Encrypt -Comment: Set 2, vector 125 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000004 -Ciphertext: 6A3F25AAB7E92D9CF378E5D9C040F26B -Test: Encrypt -Comment: Set 2, vector 126 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000002 -Ciphertext: 3D4B2CDE666761BA5DFB305178E667FB -Test: Encrypt -Comment: Set 2, vector 127 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000001 -Ciphertext: 9CDB269B5D293BC5DB9C55B057D9B591 -Test: Encrypt -Comment: Set 3, vector 0 -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 396154111ADEFC500CF6E5C99038BC17 -Test: Encrypt -Comment: Set 3, vector 1 -Key: 0101010101010101010101010101010101010101010101010101010101010101 -Plaintext: 01010101010101010101010101010101 -Ciphertext: 438D0C2E7E86869B56EBA23B66086A01 -Test: Encrypt -Comment: Set 3, vector 2 -Key: 0202020202020202020202020202020202020202020202020202020202020202 -Plaintext: 02020202020202020202020202020202 -Ciphertext: D4F553BFA794F55EF3B7A578629F6DEA -Test: Encrypt -Comment: Set 3, vector 3 -Key: 0303030303030303030303030303030303030303030303030303030303030303 -Plaintext: 03030303030303030303030303030303 -Ciphertext: B1EB06630CF3E25AEF18FA34709232F7 -Test: Encrypt -Comment: Set 3, vector 4 -Key: 0404040404040404040404040404040404040404040404040404040404040404 -Plaintext: 04040404040404040404040404040404 -Ciphertext: 5E858730ABC9823A93CA4CAB67F0B423 -Test: Encrypt -Comment: Set 3, vector 5 -Key: 0505050505050505050505050505050505050505050505050505050505050505 -Plaintext: 05050505050505050505050505050505 -Ciphertext: 9FC988D43FE3712CF6D2DB552FE3C80F -Test: Encrypt -Comment: Set 3, vector 6 -Key: 0606060606060606060606060606060606060606060606060606060606060606 -Plaintext: 06060606060606060606060606060606 -Ciphertext: 6109500D59414C9974D15818A2BA6DD0 -Test: Encrypt -Comment: Set 3, vector 7 -Key: 0707070707070707070707070707070707070707070707070707070707070707 -Plaintext: 07070707070707070707070707070707 -Ciphertext: 5F6BF9AC53A680EACAE7583A8933DA8E -Test: Encrypt -Comment: Set 3, vector 8 -Key: 0808080808080808080808080808080808080808080808080808080808080808 -Plaintext: 08080808080808080808080808080808 -Ciphertext: F9A9C1540AE1B314DBEDF9A49054DC9D -Test: Encrypt -Comment: Set 3, vector 9 -Key: 0909090909090909090909090909090909090909090909090909090909090909 -Plaintext: 09090909090909090909090909090909 -Ciphertext: 6D66755ACDB9D90BEC599A0BC0C7BF48 -Test: Encrypt -Comment: Set 3, vector 10 -Key: 0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A -Plaintext: 0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A -Ciphertext: 5527F328AF93C2D5CCC80AF7A3E8DF3D -Test: Encrypt -Comment: Set 3, vector 11 -Key: 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B -Plaintext: 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B -Ciphertext: 27AA99F8E6EA08D8E8D5A528EE4774B6 -Test: Encrypt -Comment: Set 3, vector 12 -Key: 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C -Plaintext: 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C -Ciphertext: 46F7D660A22232F5E3664EF355098CE4 -Test: Encrypt -Comment: Set 3, vector 13 -Key: 0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D -Plaintext: 0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D -Ciphertext: BDC0AEC72B53B747AB5C7BD62062826A -Test: Encrypt -Comment: Set 3, vector 14 -Key: 0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E -Plaintext: 0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E -Ciphertext: A0CAB391DC8BFF0281F3E1C70C1CE33B -Test: Encrypt -Comment: Set 3, vector 15 -Key: 0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F -Plaintext: 0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F -Ciphertext: 5CBFB3E894AE1428549CCF777A9F0A73 -Test: Encrypt -Comment: Set 3, vector 16 -Key: 1010101010101010101010101010101010101010101010101010101010101010 -Plaintext: 10101010101010101010101010101010 -Ciphertext: 6693FC130669F194F81E8D175194DDA2 -Test: Encrypt -Comment: Set 3, vector 17 -Key: 1111111111111111111111111111111111111111111111111111111111111111 -Plaintext: 11111111111111111111111111111111 -Ciphertext: A6A72472F8C04329C0E2FB56982A33C7 -Test: Encrypt -Comment: Set 3, vector 18 -Key: 1212121212121212121212121212121212121212121212121212121212121212 -Plaintext: 12121212121212121212121212121212 -Ciphertext: 6321875C5F89CCE16C6FF5E85E759C9A -Test: Encrypt -Comment: Set 3, vector 19 -Key: 1313131313131313131313131313131313131313131313131313131313131313 -Plaintext: 13131313131313131313131313131313 -Ciphertext: 8819C97D05C91A23062E9851F07EF6F7 -Test: Encrypt -Comment: Set 3, vector 20 -Key: 1414141414141414141414141414141414141414141414141414141414141414 -Plaintext: 14141414141414141414141414141414 -Ciphertext: F894FEB12164BB32AC846DD9530604CE -Test: Encrypt -Comment: Set 3, vector 21 -Key: 1515151515151515151515151515151515151515151515151515151515151515 -Plaintext: 15151515151515151515151515151515 -Ciphertext: 61B02392CD3F571B35C862E703DB2053 -Test: Encrypt -Comment: Set 3, vector 22 -Key: 1616161616161616161616161616161616161616161616161616161616161616 -Plaintext: 16161616161616161616161616161616 -Ciphertext: 6269E137F8480D555D1B24F392162DBA -Test: Encrypt -Comment: Set 3, vector 23 -Key: 1717171717171717171717171717171717171717171717171717171717171717 -Plaintext: 17171717171717171717171717171717 -Ciphertext: B6662F56AA3D23DE1DFDE165B2D63FA0 -Test: Encrypt -Comment: Set 3, vector 24 -Key: 1818181818181818181818181818181818181818181818181818181818181818 -Plaintext: 18181818181818181818181818181818 -Ciphertext: C8271ACE969013EE2C9EF1512FFABAE5 -Test: Encrypt -Comment: Set 3, vector 25 -Key: 1919191919191919191919191919191919191919191919191919191919191919 -Plaintext: 19191919191919191919191919191919 -Ciphertext: 6982E764E750CDF3E5F9C4E40A5DFE28 -Test: Encrypt -Comment: Set 3, vector 26 -Key: 1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A -Plaintext: 1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A -Ciphertext: 23172E86AF4A140A78CB1DC776270FFF -Test: Encrypt -Comment: Set 3, vector 27 -Key: 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B -Plaintext: 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B -Ciphertext: BA0BD958FC1DE142EC40326B2C315AA5 -Test: Encrypt -Comment: Set 3, vector 28 -Key: 1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C -Plaintext: 1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C -Ciphertext: 7FB2B8A4B95CBFB74BFD5F7A5641261C -Test: Encrypt -Comment: Set 3, vector 29 -Key: 1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D -Plaintext: 1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D -Ciphertext: 56B261D89F8978041E2602DF97386BF7 -Test: Encrypt -Comment: Set 3, vector 30 -Key: 1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E -Plaintext: 1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E -Ciphertext: A2D74F5148C84C1F990290E17DD3EDFA -Test: Encrypt -Comment: Set 3, vector 31 -Key: 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F -Plaintext: 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F -Ciphertext: 7D8BC76F1D941FC3C7E4C6F17AC03FF4 -Test: Encrypt -Comment: Set 3, vector 32 -Key: 2020202020202020202020202020202020202020202020202020202020202020 -Plaintext: 20202020202020202020202020202020 -Ciphertext: F3E1FDA6B9C8314799F4654C29F1C690 -Test: Encrypt -Comment: Set 3, vector 33 -Key: 2121212121212121212121212121212121212121212121212121212121212121 -Plaintext: 21212121212121212121212121212121 -Ciphertext: 9BB8499B8631F6211D22DE555010E482 -Test: Encrypt -Comment: Set 3, vector 34 -Key: 2222222222222222222222222222222222222222222222222222222222222222 -Plaintext: 22222222222222222222222222222222 -Ciphertext: B098D857086ABC425B437BD63E8A53D2 -Test: Encrypt -Comment: Set 3, vector 35 -Key: 2323232323232323232323232323232323232323232323232323232323232323 -Plaintext: 23232323232323232323232323232323 -Ciphertext: F157E2B1298A205C7EF526F3E3196BF4 -Test: Encrypt -Comment: Set 3, vector 36 -Key: 2424242424242424242424242424242424242424242424242424242424242424 -Plaintext: 24242424242424242424242424242424 -Ciphertext: 91FE4F664ED2FE0097D8B95703694BBE -Test: Encrypt -Comment: Set 3, vector 37 -Key: 2525252525252525252525252525252525252525252525252525252525252525 -Plaintext: 25252525252525252525252525252525 -Ciphertext: 742EF3C2DC4490F7D1BDB3031137B6C1 -Test: Encrypt -Comment: Set 3, vector 38 -Key: 2626262626262626262626262626262626262626262626262626262626262626 -Plaintext: 26262626262626262626262626262626 -Ciphertext: 79302D9C8DBBBDAD7B8D8B9E7A60E42D -Test: Encrypt -Comment: Set 3, vector 39 -Key: 2727272727272727272727272727272727272727272727272727272727272727 -Plaintext: 27272727272727272727272727272727 -Ciphertext: 4F4DA48026B809452E7FFB1C3DAFBD99 -Test: Encrypt -Comment: Set 3, vector 40 -Key: 2828282828282828282828282828282828282828282828282828282828282828 -Plaintext: 28282828282828282828282828282828 -Ciphertext: 6D9DF175ED0DAFE550619CF8362B98E8 -Test: Encrypt -Comment: Set 3, vector 41 -Key: 2929292929292929292929292929292929292929292929292929292929292929 -Plaintext: 29292929292929292929292929292929 -Ciphertext: 5D4A406E3C89612AA89A9D38A80ECFEF -Test: Encrypt -Comment: Set 3, vector 42 -Key: 2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A -Plaintext: 2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A -Ciphertext: 51CE933AD1EB3117A129788D3D0B815A -Test: Encrypt -Comment: Set 3, vector 43 -Key: 2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B -Plaintext: 2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B -Ciphertext: DD39326230AC02767866ADE07AED1DAA -Test: Encrypt -Comment: Set 3, vector 44 -Key: 2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C -Plaintext: 2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C -Ciphertext: DC493BAD40D435273B18026DE5412278 -Test: Encrypt -Comment: Set 3, vector 45 -Key: 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D -Plaintext: 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D -Ciphertext: 8A61E9750E1DAC58C92F5E243CA7465B -Test: Encrypt -Comment: Set 3, vector 46 -Key: 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E -Plaintext: 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E -Ciphertext: 57A7641E6A7B61A86AFD7A23578DFBC5 -Test: Encrypt -Comment: Set 3, vector 47 -Key: 2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F -Plaintext: 2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F -Ciphertext: 019A8F9D38B4B92B077D08B025C15550 -Test: Encrypt -Comment: Set 3, vector 48 -Key: 3030303030303030303030303030303030303030303030303030303030303030 -Plaintext: 30303030303030303030303030303030 -Ciphertext: 9F6EEA9C215C273135C53A3F4208469E -Test: Encrypt -Comment: Set 3, vector 49 -Key: 3131313131313131313131313131313131313131313131313131313131313131 -Plaintext: 31313131313131313131313131313131 -Ciphertext: 7BF3D63D790CAB57EA8354B10FEBDE18 -Test: Encrypt -Comment: Set 3, vector 50 -Key: 3232323232323232323232323232323232323232323232323232323232323232 -Plaintext: 32323232323232323232323232323232 -Ciphertext: AB30751ED4052A1D916E50C4073DFCB5 -Test: Encrypt -Comment: Set 3, vector 51 -Key: 3333333333333333333333333333333333333333333333333333333333333333 -Plaintext: 33333333333333333333333333333333 -Ciphertext: C39180F205BBA8BEE9832BF56FCC75C0 -Test: Encrypt -Comment: Set 3, vector 52 -Key: 3434343434343434343434343434343434343434343434343434343434343434 -Plaintext: 34343434343434343434343434343434 -Ciphertext: 3BEDE5E09CB9CCFC8BE38F8378D49AE9 -Test: Encrypt -Comment: Set 3, vector 53 -Key: 3535353535353535353535353535353535353535353535353535353535353535 -Plaintext: 35353535353535353535353535353535 -Ciphertext: 448AE4ADF7070A8B8C4AB0FE7277E8D7 -Test: Encrypt -Comment: Set 3, vector 54 -Key: 3636363636363636363636363636363636363636363636363636363636363636 -Plaintext: 36363636363636363636363636363636 -Ciphertext: 095A361F2243FC39F4ECD94A5AC0F94A -Test: Encrypt -Comment: Set 3, vector 55 -Key: 3737373737373737373737373737373737373737373737373737373737373737 -Plaintext: 37373737373737373737373737373737 -Ciphertext: AD77D7D2A7F3AF5732CE5A51E83D7025 -Test: Encrypt -Comment: Set 3, vector 56 -Key: 3838383838383838383838383838383838383838383838383838383838383838 -Plaintext: 38383838383838383838383838383838 -Ciphertext: 930DA09C18DF5F6D072AA662CC8F7751 -Test: Encrypt -Comment: Set 3, vector 57 -Key: 3939393939393939393939393939393939393939393939393939393939393939 -Plaintext: 39393939393939393939393939393939 -Ciphertext: F3B3871B66FE8A1FA4AE2150EC8B7060 -Test: Encrypt -Comment: Set 3, vector 58 -Key: 3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A -Plaintext: 3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A -Ciphertext: 62DD93CFA7EFC223A822A6F754B6298D -Test: Encrypt -Comment: Set 3, vector 59 -Key: 3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B -Plaintext: 3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B -Ciphertext: C86A0377B3C45C2B1896829D7B0610F3 -Test: Encrypt -Comment: Set 3, vector 60 -Key: 3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C -Plaintext: 3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C -Ciphertext: 8CCFC961EBAB55C0ECB1B10EDEDD9C61 -Test: Encrypt -Comment: Set 3, vector 61 -Key: 3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D -Plaintext: 3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D -Ciphertext: D828E857BDBD6192300764A2084E0680 -Test: Encrypt -Comment: Set 3, vector 62 -Key: 3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E -Plaintext: 3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E -Ciphertext: 24C0DC84D72EA678201534CE8DC22A45 -Test: Encrypt -Comment: Set 3, vector 63 -Key: 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F -Plaintext: 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F -Ciphertext: D65F340A25D35E5D0B08C63FA44F9898 -Test: Encrypt -Comment: Set 3, vector 64 -Key: 4040404040404040404040404040404040404040404040404040404040404040 -Plaintext: 40404040404040404040404040404040 -Ciphertext: 4A30476F1141FBF303ED63FCD3CB0536 -Test: Encrypt -Comment: Set 3, vector 65 -Key: 4141414141414141414141414141414141414141414141414141414141414141 -Plaintext: 41414141414141414141414141414141 -Ciphertext: 78246080B38B5283960E0253E2FF6A5E -Test: Encrypt -Comment: Set 3, vector 66 -Key: 4242424242424242424242424242424242424242424242424242424242424242 -Plaintext: 42424242424242424242424242424242 -Ciphertext: 475E8388EE3D3EE111DD0E816B244DD2 -Test: Encrypt -Comment: Set 3, vector 67 -Key: 4343434343434343434343434343434343434343434343434343434343434343 -Plaintext: 43434343434343434343434343434343 -Ciphertext: D40D3FECE8B05875F2FCD23526CCD6B2 -Test: Encrypt -Comment: Set 3, vector 68 -Key: 4444444444444444444444444444444444444444444444444444444444444444 -Plaintext: 44444444444444444444444444444444 -Ciphertext: CD9846E1B120482E6B6D71C4F5D704FE -Test: Encrypt -Comment: Set 3, vector 69 -Key: 4545454545454545454545454545454545454545454545454545454545454545 -Plaintext: 45454545454545454545454545454545 -Ciphertext: E707C35474257CE52617B5889ECB974B -Test: Encrypt -Comment: Set 3, vector 70 -Key: 4646464646464646464646464646464646464646464646464646464646464646 -Plaintext: 46464646464646464646464646464646 -Ciphertext: 9A79D57FD89D938F4B4CACA52E8CB544 -Test: Encrypt -Comment: Set 3, vector 71 -Key: 4747474747474747474747474747474747474747474747474747474747474747 -Plaintext: 47474747474747474747474747474747 -Ciphertext: 34F9B98AC130F7E7B123ECBF8910735C -Test: Encrypt -Comment: Set 3, vector 72 -Key: 4848484848484848484848484848484848484848484848484848484848484848 -Plaintext: 48484848484848484848484848484848 -Ciphertext: BF75CC83FE76E8A15981DA738E5A8513 -Test: Encrypt -Comment: Set 3, vector 73 -Key: 4949494949494949494949494949494949494949494949494949494949494949 -Plaintext: 49494949494949494949494949494949 -Ciphertext: 4A452EFBE634441444FB50641CB2EFC1 -Test: Encrypt -Comment: Set 3, vector 74 -Key: 4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A -Plaintext: 4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A -Ciphertext: 3D5ED11F0C81E81BAB97B7148D67BA55 -Test: Encrypt -Comment: Set 3, vector 75 -Key: 4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B -Plaintext: 4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B -Ciphertext: DBBAE78B177C27954DEDBAD5D98E7BEE -Test: Encrypt -Comment: Set 3, vector 76 -Key: 4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C -Plaintext: 4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C -Ciphertext: F52D16EFC5DE991430F6E7D13983DEB8 -Test: Encrypt -Comment: Set 3, vector 77 -Key: 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D -Plaintext: 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D -Ciphertext: B6C98EBC320B3BDD927C2FE57F8180B5 -Test: Encrypt -Comment: Set 3, vector 78 -Key: 4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E -Plaintext: 4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E -Ciphertext: D510C35680C9B958C81599F3665FBEC1 -Test: Encrypt -Comment: Set 3, vector 79 -Key: 4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F -Plaintext: 4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F -Ciphertext: 72DAD08BF510CDFEEC76FEAB908829B4 -Test: Encrypt -Comment: Set 3, vector 80 -Key: 5050505050505050505050505050505050505050505050505050505050505050 -Plaintext: 50505050505050505050505050505050 -Ciphertext: AC7B447EDB38F935469309E766BCB1F6 -Test: Encrypt -Comment: Set 3, vector 81 -Key: 5151515151515151515151515151515151515151515151515151515151515151 -Plaintext: 51515151515151515151515151515151 -Ciphertext: 18B937F666BF580F9CDB60A935427459 -Test: Encrypt -Comment: Set 3, vector 82 -Key: 5252525252525252525252525252525252525252525252525252525252525252 -Plaintext: 52525252525252525252525252525252 -Ciphertext: 6A08B38202685E610CA9584725D6092A -Test: Encrypt -Comment: Set 3, vector 83 -Key: 5353535353535353535353535353535353535353535353535353535353535353 -Plaintext: 53535353535353535353535353535353 -Ciphertext: 1CA09E9C14C2A833A7B7ACB1C9C12AC1 -Test: Encrypt -Comment: Set 3, vector 84 -Key: 5454545454545454545454545454545454545454545454545454545454545454 -Plaintext: 54545454545454545454545454545454 -Ciphertext: 8AB7ED64FE477B7D9A6B5B5056EA1E02 -Test: Encrypt -Comment: Set 3, vector 85 -Key: 5555555555555555555555555555555555555555555555555555555555555555 -Plaintext: 55555555555555555555555555555555 -Ciphertext: D610D6199D4FE03ED09AD568664F709A -Test: Encrypt -Comment: Set 3, vector 86 -Key: 5656565656565656565656565656565656565656565656565656565656565656 -Plaintext: 56565656565656565656565656565656 -Ciphertext: D400C1E6109F04AE50C1C341BA4E3175 -Test: Encrypt -Comment: Set 3, vector 87 -Key: 5757575757575757575757575757575757575757575757575757575757575757 -Plaintext: 57575757575757575757575757575757 -Ciphertext: DF888CBB7DBD8DE3F0BE6C6EDC72060F -Test: Encrypt -Comment: Set 3, vector 88 -Key: 5858585858585858585858585858585858585858585858585858585858585858 -Plaintext: 58585858585858585858585858585858 -Ciphertext: 9C3B100466C63AA93D420EDF54381BF4 -Test: Encrypt -Comment: Set 3, vector 89 -Key: 5959595959595959595959595959595959595959595959595959595959595959 -Plaintext: 59595959595959595959595959595959 -Ciphertext: 0BE794F0233BE9A7DB7C41A1CA4BA7E3 -Test: Encrypt -Comment: Set 3, vector 90 -Key: 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A -Plaintext: 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A -Ciphertext: 2C8D04D6B9DA81D07174729A07F25BB9 -Test: Encrypt -Comment: Set 3, vector 91 -Key: 5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B -Plaintext: 5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B -Ciphertext: FFCEB69835E2E5EF4C867CE28540F91F -Test: Encrypt -Comment: Set 3, vector 92 -Key: 5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C -Plaintext: 5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C -Ciphertext: A7F7F8437918BEFF5DCFCFB366CDFABD -Test: Encrypt -Comment: Set 3, vector 93 -Key: 5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D -Plaintext: 5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D -Ciphertext: 14C9736F407AE78D7D3ED18B875B940D -Test: Encrypt -Comment: Set 3, vector 94 -Key: 5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E -Plaintext: 5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E -Ciphertext: 1668A0C6A5734B98D9D641E0B6FAD80C -Test: Encrypt -Comment: Set 3, vector 95 -Key: 5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F -Plaintext: 5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F -Ciphertext: DA8775267C9722BA743A085F8591F06D -Test: Encrypt -Comment: Set 3, vector 96 -Key: 6060606060606060606060606060606060606060606060606060606060606060 -Plaintext: 60606060606060606060606060606060 -Ciphertext: 5F8172C28603C80206C276E0979EA40E -Test: Encrypt -Comment: Set 3, vector 97 -Key: 6161616161616161616161616161616161616161616161616161616161616161 -Plaintext: 61616161616161616161616161616161 -Ciphertext: E4938D0078D29E0247BF2EA0C1FCB85F -Test: Encrypt -Comment: Set 3, vector 98 -Key: 6262626262626262626262626262626262626262626262626262626262626262 -Plaintext: 62626262626262626262626262626262 -Ciphertext: A48FEE4F9FA4597303C2CF92061304A1 -Test: Encrypt -Comment: Set 3, vector 99 -Key: 6363636363636363636363636363636363636363636363636363636363636363 -Plaintext: 63636363636363636363636363636363 -Ciphertext: 3C8F6CF66C73684DDB09D1AA57CD0950 -Test: Encrypt -Comment: Set 3, vector 100 -Key: 6464646464646464646464646464646464646464646464646464646464646464 -Plaintext: 64646464646464646464646464646464 -Ciphertext: B3D9EE0337253E9C4027FEA938AB399C -Test: Encrypt -Comment: Set 3, vector 101 -Key: 6565656565656565656565656565656565656565656565656565656565656565 -Plaintext: 65656565656565656565656565656565 -Ciphertext: 3BE933A85E5997573077903CEB481AFA -Test: Encrypt -Comment: Set 3, vector 102 -Key: 6666666666666666666666666666666666666666666666666666666666666666 -Plaintext: 66666666666666666666666666666666 -Ciphertext: 06AFED96C6E7130EB3311D81CCE69F9C -Test: Encrypt -Comment: Set 3, vector 103 -Key: 6767676767676767676767676767676767676767676767676767676767676767 -Plaintext: 67676767676767676767676767676767 -Ciphertext: 183C3606139211F90F4849E93DB7DDEE -Test: Encrypt -Comment: Set 3, vector 104 -Key: 6868686868686868686868686868686868686868686868686868686868686868 -Plaintext: 68686868686868686868686868686868 -Ciphertext: 217C34184950DE7B43E46EE4BE88A9BE -Test: Encrypt -Comment: Set 3, vector 105 -Key: 6969696969696969696969696969696969696969696969696969696969696969 -Plaintext: 69696969696969696969696969696969 -Ciphertext: CA447ED204F2A4B2ED6B82E3926967B1 -Test: Encrypt -Comment: Set 3, vector 106 -Key: 6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A -Plaintext: 6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A -Ciphertext: B447F4BEBA7D88A5C62E5F9C316A4523 -Test: Encrypt -Comment: Set 3, vector 107 -Key: 6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B -Plaintext: 6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B -Ciphertext: DEDF599C54D0009795303013CD933B49 -Test: Encrypt -Comment: Set 3, vector 108 -Key: 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C -Plaintext: 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C -Ciphertext: B06280650C77C83AF3D71874AE00D3DA -Test: Encrypt -Comment: Set 3, vector 109 -Key: 6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D -Plaintext: 6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D -Ciphertext: 1BB5B9E9C7DC8AD690F5FC217B7B53C1 -Test: Encrypt -Comment: Set 3, vector 110 -Key: 6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E -Plaintext: 6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E -Ciphertext: FEECFCF0C172C6152F33E4DEE206EBCF -Test: Encrypt -Comment: Set 3, vector 111 -Key: 6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F -Plaintext: 6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F -Ciphertext: FA4C7EA42C425F37588CD273320940C9 -Test: Encrypt -Comment: Set 3, vector 112 -Key: 7070707070707070707070707070707070707070707070707070707070707070 -Plaintext: 70707070707070707070707070707070 -Ciphertext: 563AE5884FC374C4E45B96A6431E51E3 -Test: Encrypt -Comment: Set 3, vector 113 -Key: 7171717171717171717171717171717171717171717171717171717171717171 -Plaintext: 71717171717171717171717171717171 -Ciphertext: 0669E609578A33DBE637C5B86C7F425D -Test: Encrypt -Comment: Set 3, vector 114 -Key: 7272727272727272727272727272727272727272727272727272727272727272 -Plaintext: 72727272727272727272727272727272 -Ciphertext: B2AD99D3941924DDD2A73C4725A08EC3 -Test: Encrypt -Comment: Set 3, vector 115 -Key: 7373737373737373737373737373737373737373737373737373737373737373 -Plaintext: 73737373737373737373737373737373 -Ciphertext: 72C8239B5F4E5319EE05B6E39C9BD336 -Test: Encrypt -Comment: Set 3, vector 116 -Key: 7474747474747474747474747474747474747474747474747474747474747474 -Plaintext: 74747474747474747474747474747474 -Ciphertext: BAD014C4B0A5734AA48E7E80A42E80AF -Test: Encrypt -Comment: Set 3, vector 117 -Key: 7575757575757575757575757575757575757575757575757575757575757575 -Plaintext: 75757575757575757575757575757575 -Ciphertext: BBE294CDB3582B3C1F61ACD43A0E5DB5 -Test: Encrypt -Comment: Set 3, vector 118 -Key: 7676767676767676767676767676767676767676767676767676767676767676 -Plaintext: 76767676767676767676767676767676 -Ciphertext: C231DC35D38F5857BD3449D3E0A1EF1F -Test: Encrypt -Comment: Set 3, vector 119 -Key: 7777777777777777777777777777777777777777777777777777777777777777 -Plaintext: 77777777777777777777777777777777 -Ciphertext: B19E0BACBF3EC295AA6F99B0817B99F3 -Test: Encrypt -Comment: Set 3, vector 120 -Key: 7878787878787878787878787878787878787878787878787878787878787878 -Plaintext: 78787878787878787878787878787878 -Ciphertext: 0E81D1133E74F1A9425237377890584C -Test: Encrypt -Comment: Set 3, vector 121 -Key: 7979797979797979797979797979797979797979797979797979797979797979 -Plaintext: 79797979797979797979797979797979 -Ciphertext: E1149AA17A8B6499E0FA5C45F05D6582 -Test: Encrypt -Comment: Set 3, vector 122 -Key: 7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A -Plaintext: 7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A -Ciphertext: D9208954D8D28335E6F45FFB9D1B92D4 -Test: Encrypt -Comment: Set 3, vector 123 -Key: 7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B -Plaintext: 7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B -Ciphertext: DFABDB0594208A2902703E85C4A657FF -Test: Encrypt -Comment: Set 3, vector 124 -Key: 7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C -Plaintext: 7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C -Ciphertext: E05B6C6E90E852229BF0EFDC4FEB851E -Test: Encrypt -Comment: Set 3, vector 125 -Key: 7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D -Plaintext: 7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D -Ciphertext: 6834CCFDC940452CF40A0866009E58CC -Test: Encrypt -Comment: Set 3, vector 126 -Key: 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E -Plaintext: 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E -Ciphertext: 91449066A1966246636D9085E02002B0 -Test: Encrypt -Comment: Set 3, vector 127 -Key: 7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F -Plaintext: 7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F -Ciphertext: 235C2D836B2025CCCDAE4B26264132E2 -Test: Encrypt -Comment: Set 3, vector 128 -Key: 8080808080808080808080808080808080808080808080808080808080808080 -Plaintext: 80808080808080808080808080808080 -Ciphertext: 0C765AA494E048FC8BB23139F2124CB6 -Test: Encrypt -Comment: Set 3, vector 129 -Key: 8181818181818181818181818181818181818181818181818181818181818181 -Plaintext: 81818181818181818181818181818181 -Ciphertext: ED970D660C84642D0EAFF188F55CC33C -Test: Encrypt -Comment: Set 3, vector 130 -Key: 8282828282828282828282828282828282828282828282828282828282828282 -Plaintext: 82828282828282828282828282828282 -Ciphertext: E124EB4A8BE05CA633238DD69E81E057 -Test: Encrypt -Comment: Set 3, vector 131 -Key: 8383838383838383838383838383838383838383838383838383838383838383 -Plaintext: 83838383838383838383838383838383 -Ciphertext: 4653FBDD6CA7C13CE2DF31B1279B3D5A -Test: Encrypt -Comment: Set 3, vector 132 -Key: 8484848484848484848484848484848484848484848484848484848484848484 -Plaintext: 84848484848484848484848484848484 -Ciphertext: 2D4D87CFB763C3974CEBF6AE1C6269D4 -Test: Encrypt -Comment: Set 3, vector 133 -Key: 8585858585858585858585858585858585858585858585858585858585858585 -Plaintext: 85858585858585858585858585858585 -Ciphertext: F153B13F57F1AE16186EF3B1E98549B8 -Test: Encrypt -Comment: Set 3, vector 134 -Key: 8686868686868686868686868686868686868686868686868686868686868686 -Plaintext: 86868686868686868686868686868686 -Ciphertext: 5451DB2B141B894B4892C7F12BE3F389 -Test: Encrypt -Comment: Set 3, vector 135 -Key: 8787878787878787878787878787878787878787878787878787878787878787 -Plaintext: 87878787878787878787878787878787 -Ciphertext: 61B2185653CFF14EE873DBD3CB663E79 -Test: Encrypt -Comment: Set 3, vector 136 -Key: 8888888888888888888888888888888888888888888888888888888888888888 -Plaintext: 88888888888888888888888888888888 -Ciphertext: C17ACB243808B86349D4176EECF602DF -Test: Encrypt -Comment: Set 3, vector 137 -Key: 8989898989898989898989898989898989898989898989898989898989898989 -Plaintext: 89898989898989898989898989898989 -Ciphertext: 6FCE3ED2207D58A5976FE8B20B247275 -Test: Encrypt -Comment: Set 3, vector 138 -Key: 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A -Plaintext: 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A -Ciphertext: 403F73CC70C7F9A5E96CD77D61140961 -Test: Encrypt -Comment: Set 3, vector 139 -Key: 8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B -Plaintext: 8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B -Ciphertext: DE2B34DECB33550C97D6C074032F3333 -Test: Encrypt -Comment: Set 3, vector 140 -Key: 8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C -Plaintext: 8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C -Ciphertext: FB395AE4F537F8FB7C98BAD54BDB86A0 -Test: Encrypt -Comment: Set 3, vector 141 -Key: 8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D -Plaintext: 8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D -Ciphertext: 258E83BB639D0BEDE648F3AF96CC8E75 -Test: Encrypt -Comment: Set 3, vector 142 -Key: 8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E -Plaintext: 8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E -Ciphertext: A1B5E73720E43FA0871EAAE245B55A0E -Test: Encrypt -Comment: Set 3, vector 143 -Key: 8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F -Plaintext: 8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F -Ciphertext: 774A9ABE1FAB9E3B85A91C0F86758B0E -Test: Encrypt -Comment: Set 3, vector 144 -Key: 9090909090909090909090909090909090909090909090909090909090909090 -Plaintext: 90909090909090909090909090909090 -Ciphertext: 0A6EC1CF2056076933259AE6A337B185 -Test: Encrypt -Comment: Set 3, vector 145 -Key: 9191919191919191919191919191919191919191919191919191919191919191 -Plaintext: 91919191919191919191919191919191 -Ciphertext: C96729F87D62104F941DC21448756F95 -Test: Encrypt -Comment: Set 3, vector 146 -Key: 9292929292929292929292929292929292929292929292929292929292929292 -Plaintext: 92929292929292929292929292929292 -Ciphertext: 1CB85A610C2250A78143A31BB1C19094 -Test: Encrypt -Comment: Set 3, vector 147 -Key: 9393939393939393939393939393939393939393939393939393939393939393 -Plaintext: 93939393939393939393939393939393 -Ciphertext: 16194ABEDEA340C6D57E4C4F50640FBE -Test: Encrypt -Comment: Set 3, vector 148 -Key: 9494949494949494949494949494949494949494949494949494949494949494 -Plaintext: 94949494949494949494949494949494 -Ciphertext: 379A5A54C198FB03178EE841D67F3502 -Test: Encrypt -Comment: Set 3, vector 149 -Key: 9595959595959595959595959595959595959595959595959595959595959595 -Plaintext: 95959595959595959595959595959595 -Ciphertext: A25119AD8A0F6654ECDB2696CF4F8225 -Test: Encrypt -Comment: Set 3, vector 150 -Key: 9696969696969696969696969696969696969696969696969696969696969696 -Plaintext: 96969696969696969696969696969696 -Ciphertext: 264B7FAAD26DEC203D0DE29CE4F0F45B -Test: Encrypt -Comment: Set 3, vector 151 -Key: 9797979797979797979797979797979797979797979797979797979797979797 -Plaintext: 97979797979797979797979797979797 -Ciphertext: 2EBD2A2CD16284D206D81ACF18122E2E -Test: Encrypt -Comment: Set 3, vector 152 -Key: 9898989898989898989898989898989898989898989898989898989898989898 -Plaintext: 98989898989898989898989898989898 -Ciphertext: 25FB2B75B6915C0543412DF9EBD20FC3 -Test: Encrypt -Comment: Set 3, vector 153 -Key: 9999999999999999999999999999999999999999999999999999999999999999 -Plaintext: 99999999999999999999999999999999 -Ciphertext: 21B89B53845A828E0A14F4AE45940284 -Test: Encrypt -Comment: Set 3, vector 154 -Key: 9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A -Plaintext: 9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A -Ciphertext: 4CE809A241E8E59E231F2D00BE0EA285 -Test: Encrypt -Comment: Set 3, vector 155 -Key: 9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B -Plaintext: 9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B -Ciphertext: F914E06D9F7889DC71974DFF104F94D4 -Test: Encrypt -Comment: Set 3, vector 156 -Key: 9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C -Plaintext: 9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C -Ciphertext: AF08BADB48FF961FD5EB663FA3766FC6 -Test: Encrypt -Comment: Set 3, vector 157 -Key: 9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D -Plaintext: 9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D -Ciphertext: 05DDDE95AE659D6BBBD2B4E394399B53 -Test: Encrypt -Comment: Set 3, vector 158 -Key: 9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E -Plaintext: 9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E -Ciphertext: 25E6FE1C89F811D827BDF8D4E977071C -Test: Encrypt -Comment: Set 3, vector 159 -Key: 9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F -Plaintext: 9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F -Ciphertext: 3D00A9143A1829D05F787A904C48C75B -Test: Encrypt -Comment: Set 3, vector 160 -Key: A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0 -Plaintext: A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0 -Ciphertext: 391DF944B0E0BCB84483AF5C4F34D754 -Test: Encrypt -Comment: Set 3, vector 161 -Key: A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1 -Plaintext: A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1 -Ciphertext: BB2D2E556210A7C0EBA3165F63A74967 -Test: Encrypt -Comment: Set 3, vector 162 -Key: A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 -Plaintext: A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 -Ciphertext: A1B0BB24291B259AC4A1CDE9A3B817C9 -Test: Encrypt -Comment: Set 3, vector 163 -Key: A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3 -Plaintext: A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3 -Ciphertext: 6F798763B6ED7F8BB234D2CA78D026DC -Test: Encrypt -Comment: Set 3, vector 164 -Key: A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4 -Plaintext: A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4 -Ciphertext: 038443760056AB3D23BC70ECE6FB4397 -Test: Encrypt -Comment: Set 3, vector 165 -Key: A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5 -Plaintext: A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5 -Ciphertext: C75ECE40A7AE9BB38F604615C873EF02 -Test: Encrypt -Comment: Set 3, vector 166 -Key: A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6 -Plaintext: A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6 -Ciphertext: 2D308C2078842EDBBB35ABCA3F41E467 -Test: Encrypt -Comment: Set 3, vector 167 -Key: A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7 -Plaintext: A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7 -Ciphertext: 393C0E3350B3219DD8FD851C48E28C63 -Test: Encrypt -Comment: Set 3, vector 168 -Key: A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8 -Plaintext: A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8 -Ciphertext: 964BD4A28DB1434570E27FB3AD880398 -Test: Encrypt -Comment: Set 3, vector 169 -Key: A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9 -Plaintext: A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9 -Ciphertext: B668D17C027B550C0C22BDE151EB6EB1 -Test: Encrypt -Comment: Set 3, vector 170 -Key: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -Plaintext: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -Ciphertext: E14186F8205957B243CE522C16453621 -Test: Encrypt -Comment: Set 3, vector 171 -Key: ABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB -Plaintext: ABABABABABABABABABABABABABABABAB -Ciphertext: 0E352BEB6B6BCAFDAE61BBE86F8F1D0E -Test: Encrypt -Comment: Set 3, vector 172 -Key: ACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACAC -Plaintext: ACACACACACACACACACACACACACACACAC -Ciphertext: 4BCF038D9458EAAA3D279CCAC3F5D693 -Test: Encrypt -Comment: Set 3, vector 173 -Key: ADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADAD -Plaintext: ADADADADADADADADADADADADADADADAD -Ciphertext: D5EF17646A481C3B79AAB3C08B4F1611 -Test: Encrypt -Comment: Set 3, vector 174 -Key: AEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAE -Plaintext: AEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAE -Ciphertext: 37642DA589775C2FFA40A7274E9D56E2 -Test: Encrypt -Comment: Set 3, vector 175 -Key: AFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAF -Plaintext: AFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAF -Ciphertext: F829FA6B756F1B1D16B49CB7C8AFFA22 -Test: Encrypt -Comment: Set 3, vector 176 -Key: B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0 -Plaintext: B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0 -Ciphertext: 6FE1450D48D611031E81C70478DB5326 -Test: Encrypt -Comment: Set 3, vector 177 -Key: B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1 -Plaintext: B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1 -Ciphertext: 68C5ECE7F525F69DABF63288533C5C60 -Test: Encrypt -Comment: Set 3, vector 178 -Key: B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2 -Plaintext: B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2 -Ciphertext: 5DF627500627E59A5BAB5D30B6C93219 -Test: Encrypt -Comment: Set 3, vector 179 -Key: B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3 -Plaintext: B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3 -Ciphertext: AD3A4AC8F666C0FCA5D7995783D0986D -Test: Encrypt -Comment: Set 3, vector 180 -Key: B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 -Plaintext: B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 -Ciphertext: A3AEE54D09357B187622109296534F88 -Test: Encrypt -Comment: Set 3, vector 181 -Key: B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5 -Plaintext: B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5 -Ciphertext: 7D1D9A73DB386A717862C4F5089970E1 -Test: Encrypt -Comment: Set 3, vector 182 -Key: B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6 -Plaintext: B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6 -Ciphertext: 916347935FBD0D868A0127D602B91BD5 -Test: Encrypt -Comment: Set 3, vector 183 -Key: B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7 -Plaintext: B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7 -Ciphertext: 4F167893651993D9150ED9E0B780BF82 -Test: Encrypt -Comment: Set 3, vector 184 -Key: B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8 -Plaintext: B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8 -Ciphertext: 488352470ACF9361F22FAC1B3ED67003 -Test: Encrypt -Comment: Set 3, vector 185 -Key: B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9 -Plaintext: B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9 -Ciphertext: 4BBD307FCDE0F89C9A663A0F9C9358C5 -Test: Encrypt -Comment: Set 3, vector 186 -Key: BABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABA -Plaintext: BABABABABABABABABABABABABABABABA -Ciphertext: E402E706D262078113D6626E7071589E -Test: Encrypt -Comment: Set 3, vector 187 -Key: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB -Plaintext: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB -Ciphertext: 422D6FA4519F2E72420685CD4ED2CC8E -Test: Encrypt -Comment: Set 3, vector 188 -Key: BCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC -Plaintext: BCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC -Ciphertext: 6D14CC5F618DF7E0B2210F6C5DD62C92 -Test: Encrypt -Comment: Set 3, vector 189 -Key: BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD -Plaintext: BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD -Ciphertext: 5CC4A5E81F7D7EC528C150437AC2B027 -Test: Encrypt -Comment: Set 3, vector 190 -Key: BEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBE -Plaintext: BEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBE -Ciphertext: B3BE0F996494323504946446EDE489FC -Test: Encrypt -Comment: Set 3, vector 191 -Key: BFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBF -Plaintext: BFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBF -Ciphertext: ABC7DB10FE04BEE94F5887E539C1D235 -Test: Encrypt -Comment: Set 3, vector 192 -Key: C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0 -Plaintext: C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0 -Ciphertext: B18BE6FB1D04E76F21C0678A4333D255 -Test: Encrypt -Comment: Set 3, vector 193 -Key: C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1 -Plaintext: C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1 -Ciphertext: FC5802BAFEDC03088BBA0A5F22402968 -Test: Encrypt -Comment: Set 3, vector 194 -Key: C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2 -Plaintext: C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2 -Ciphertext: 8EA96801643AE7BF649EAC22812214D5 -Test: Encrypt -Comment: Set 3, vector 195 -Key: C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3 -Plaintext: C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3 -Ciphertext: F7683FCDDC2BB0BCFD1350F8E3D76602 -Test: Encrypt -Comment: Set 3, vector 196 -Key: C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4 -Plaintext: C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4 -Ciphertext: 08D0345431AE120CAD6C6D4275E00CA8 -Test: Encrypt -Comment: Set 3, vector 197 -Key: C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5 -Plaintext: C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5 -Ciphertext: 7CD50A623DA79EC84D61CD7FBDBA4153 -Test: Encrypt -Comment: Set 3, vector 198 -Key: C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 -Plaintext: C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 -Ciphertext: 42ACA2B048E5C58D8F004F0E8A2C6DEF -Test: Encrypt -Comment: Set 3, vector 199 -Key: C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7 -Plaintext: C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7 -Ciphertext: E03AD353225F76121D130740C75B839B -Test: Encrypt -Comment: Set 3, vector 200 -Key: C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8 -Plaintext: C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8 -Ciphertext: 26807D0A6D6330A77804B4B1AE84432B -Test: Encrypt -Comment: Set 3, vector 201 -Key: C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9 -Plaintext: C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9 -Ciphertext: 864CE880AE89660474F64B93AF4CE043 -Test: Encrypt -Comment: Set 3, vector 202 -Key: CACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACA -Plaintext: CACACACACACACACACACACACACACACACA -Ciphertext: 82EAD2C033986CAC1F4C3EEEEA1D1892 -Test: Encrypt -Comment: Set 3, vector 203 -Key: CBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCB -Plaintext: CBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCB -Ciphertext: 53F1A5C39DD062DF8D133B3A0FB3DA02 -Test: Encrypt -Comment: Set 3, vector 204 -Key: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC -Plaintext: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC -Ciphertext: E913208594B288125EEAE0EFEC764D39 -Test: Encrypt -Comment: Set 3, vector 205 -Key: CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD -Plaintext: CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD -Ciphertext: 7DAE4BD638A36A794A73E9B945BEF4D4 -Test: Encrypt -Comment: Set 3, vector 206 -Key: CECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECE -Plaintext: CECECECECECECECECECECECECECECECE -Ciphertext: 04E8155E3E81C261D3A9D4A800182A62 -Test: Encrypt -Comment: Set 3, vector 207 -Key: CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF -Plaintext: CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF -Ciphertext: F466172A8C4C7854F59388474098F441 -Test: Encrypt -Comment: Set 3, vector 208 -Key: D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0 -Plaintext: D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0 -Ciphertext: E95DBB0B366E77D7BC1BF206B95DAEBA -Test: Encrypt -Comment: Set 3, vector 209 -Key: D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1 -Plaintext: D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1 -Ciphertext: 76490E6DD8380855E26BCACF8746978F -Test: Encrypt -Comment: Set 3, vector 210 -Key: D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2 -Plaintext: D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2 -Ciphertext: 3C3B73C8FBDA8CAE5E0D7D0070735DA1 -Test: Encrypt -Comment: Set 3, vector 211 -Key: D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3 -Plaintext: D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3 -Ciphertext: B039EBC9C48828C3913A3BC346CAEAE3 -Test: Encrypt -Comment: Set 3, vector 212 -Key: D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4 -Plaintext: D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4 -Ciphertext: 0AFCC6A58BD3ADB2C0B2A1586C9FA8DE -Test: Encrypt -Comment: Set 3, vector 213 -Key: D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5 -Plaintext: D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5 -Ciphertext: C2187D0E74CE2307BC4DF249EA6E57F1 -Test: Encrypt -Comment: Set 3, vector 214 -Key: D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6 -Plaintext: D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6 -Ciphertext: F3F4AEA2492106A45C12D0029F58ACE1 -Test: Encrypt -Comment: Set 3, vector 215 -Key: D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7 -Plaintext: D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7 -Ciphertext: 3FFADF96B37B67D62D71387C52C41AE9 -Test: Encrypt -Comment: Set 3, vector 216 -Key: D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 -Plaintext: D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 -Ciphertext: 4C1644AD69F7D0D3A1E2B4B0E7F0A592 -Test: Encrypt -Comment: Set 3, vector 217 -Key: D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9 -Plaintext: D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9 -Ciphertext: 68FD6F6592AE5BD9245FA959FE1CA849 -Test: Encrypt -Comment: Set 3, vector 218 -Key: DADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADA -Plaintext: DADADADADADADADADADADADADADADADA -Ciphertext: 7AB97B70C2CCC7D0D1AA7A6D8B7C48CA -Test: Encrypt -Comment: Set 3, vector 219 -Key: DBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDB -Plaintext: DBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDB -Ciphertext: 961BF9E037E303B9B494C2EE063FC4CC -Test: Encrypt -Comment: Set 3, vector 220 -Key: DCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDC -Plaintext: DCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDC -Ciphertext: 0FBF042B227603DB4A1CC8EE62E93DF3 -Test: Encrypt -Comment: Set 3, vector 221 -Key: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD -Plaintext: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD -Ciphertext: 71360ED44C9FAF8F1139D31252A35F49 -Test: Encrypt -Comment: Set 3, vector 222 -Key: DEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDE -Plaintext: DEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDE -Ciphertext: 5E806BD29351AE456549E73B8DDC0026 -Test: Encrypt -Comment: Set 3, vector 223 -Key: DFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDF -Plaintext: DFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDF -Ciphertext: C7908A288B86C1C4FCE5A8A59457EFD3 -Test: Encrypt -Comment: Set 3, vector 224 -Key: E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0 -Plaintext: E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0 -Ciphertext: AAC45B53F6292082B93F949BD77E5776 -Test: Encrypt -Comment: Set 3, vector 225 -Key: E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 -Plaintext: E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 -Ciphertext: 231150ED4D85B4217B3EFC3E71A522C6 -Test: Encrypt -Comment: Set 3, vector 226 -Key: E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2 -Plaintext: E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2 -Ciphertext: 639D9C5EEC8D9569C6DF24630CA8257D -Test: Encrypt -Comment: Set 3, vector 227 -Key: E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3 -Plaintext: E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3 -Ciphertext: 0E7F8C538946D87A01AD49A8CC981B58 -Test: Encrypt -Comment: Set 3, vector 228 -Key: E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4 -Plaintext: E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4 -Ciphertext: 09A293907E499502D78569230D3F1A97 -Test: Encrypt -Comment: Set 3, vector 229 -Key: E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5 -Plaintext: E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5 -Ciphertext: ACF67CC086E386DA064EDBF97F7E889A -Test: Encrypt -Comment: Set 3, vector 230 -Key: E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6 -Plaintext: E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6 -Ciphertext: E7C44DB1A9FCAC410253A7E2674C54F6 -Test: Encrypt -Comment: Set 3, vector 231 -Key: E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7 -Plaintext: E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7 -Ciphertext: B99BA33ECB86DA790FF0CC4F0D41A065 -Test: Encrypt -Comment: Set 3, vector 232 -Key: E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8 -Plaintext: E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8 -Ciphertext: 73405114FDBDB81B1A54C4EFED1BB3FE -Test: Encrypt -Comment: Set 3, vector 233 -Key: E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9 -Plaintext: E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9 -Ciphertext: 80152E139834B3CC01EBF7E6417C5537 -Test: Encrypt -Comment: Set 3, vector 234 -Key: EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA -Plaintext: EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA -Ciphertext: 05CE579D4804FF3C7874571730D81CEC -Test: Encrypt -Comment: Set 3, vector 235 -Key: EBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEB -Plaintext: EBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEB -Ciphertext: F984801E7A806A130325E152DF60012E -Test: Encrypt -Comment: Set 3, vector 236 -Key: ECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECEC -Plaintext: ECECECECECECECECECECECECECECECEC -Ciphertext: 92CBB121474A307505425B4DD1B7F803 -Test: Encrypt -Comment: Set 3, vector 237 -Key: EDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDED -Plaintext: EDEDEDEDEDEDEDEDEDEDEDEDEDEDEDED -Ciphertext: 2DEB2F282D60EFCDB300EADB15C798D8 -Test: Encrypt -Comment: Set 3, vector 238 -Key: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE -Plaintext: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE -Ciphertext: 0F4D7D59B535E29D315D2A5C7BFE4973 -Test: Encrypt -Comment: Set 3, vector 239 -Key: EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF -Plaintext: EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF -Ciphertext: 61E391F7C29B5AD705121CF9559E5C04 -Test: Encrypt -Comment: Set 3, vector 240 -Key: F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -Plaintext: F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -Ciphertext: 65BCBE179D19A5BCF12D141A21E0F7A8 -Test: Encrypt -Comment: Set 3, vector 241 -Key: F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1 -Plaintext: F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1 -Ciphertext: FDB75C659B72AE81E51204CFCB86E631 -Test: Encrypt -Comment: Set 3, vector 242 -Key: F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2 -Plaintext: F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2 -Ciphertext: 5643ED3A3679B9E33E21CD0F95580877 -Test: Encrypt -Comment: Set 3, vector 243 -Key: F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 -Plaintext: F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 -Ciphertext: 618EFEB4C6E4270B81FF7DE786E68420 -Test: Encrypt -Comment: Set 3, vector 244 -Key: F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4 -Plaintext: F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4 -Ciphertext: 75A2A9CC91F006059CA873E5D73C2CCC -Test: Encrypt -Comment: Set 3, vector 245 -Key: F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5 -Plaintext: F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5 -Ciphertext: B55840B5001D1875C29A56EDFDE10E55 -Test: Encrypt -Comment: Set 3, vector 246 -Key: F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6 -Plaintext: F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6 -Ciphertext: 6DD9BDEA7EC0E622DE8B83460BDEA719 -Test: Encrypt -Comment: Set 3, vector 247 -Key: F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7 -Plaintext: F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7 -Ciphertext: D164075BD4CDC95288D896C7CC98285D -Test: Encrypt -Comment: Set 3, vector 248 -Key: F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8 -Plaintext: F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8 -Ciphertext: 8420071C55241802D88FB7AF17EBE43F -Test: Encrypt -Comment: Set 3, vector 249 -Key: F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9 -Plaintext: F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9 -Ciphertext: 03D1D5646E4B2B8A924AB242E485C5D1 -Test: Encrypt -Comment: Set 3, vector 250 -Key: FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA -Plaintext: FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA -Ciphertext: 29106DFB63F4CD6EF5D82CF07C0DBB3A -Test: Encrypt -Comment: Set 3, vector 251 -Key: FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB -Plaintext: FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB -Ciphertext: E9DC1CDD5011E00E0C5699201E1EA002 -Test: Encrypt -Comment: Set 3, vector 252 -Key: FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC -Plaintext: FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC -Ciphertext: 8006C8BD5B210F2FC5B3538F66A6BE0B -Test: Encrypt -Comment: Set 3, vector 253 -Key: FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD -Plaintext: FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD -Ciphertext: 2C6386229480E806D0CD21CDA0EA6B53 -Test: Encrypt -Comment: Set 3, vector 254 -Key: FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE -Plaintext: FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE -Ciphertext: ACDBB0F5A00E3CF63A89D9C09B44A058 -Test: Encrypt -Comment: Set 3, vector 255 -Key: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -Plaintext: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -Ciphertext: 4F05F28CA23EEAE205B67B1C95CD5280 -Test: Encrypt diff --git a/embeddedcryptopp/TestVectors/ccm.txt b/embeddedcryptopp/TestVectors/ccm.txt deleted file mode 100644 index f23f084..0000000 --- a/embeddedcryptopp/TestVectors/ccm.txt +++ /dev/null @@ -1,240 +0,0 @@ -AlgorithmType: AuthenticatedSymmetricCipher -Name: AES/CCM -Source: aes-modes-src-07-10-08/Testvals/ccm.1, Basic Tests for CCM (compiled by B. R. Gladman) -Key: 404142434445464748494a4b4c4d4e4f -IV: 10111213141516 -Header: 0001020304050607 -Plaintext: 20212223 -Ciphertext: 7162015b -MAC: 4dac255d -Test: Encrypt -Key: 404142434445464748494a4b4c4d4e4f -IV: 1011121314151617 -Header: 000102030405060708090a0b0c0d0e0f -Plaintext: 202122232425262728292a2b2c2d2e2f -Ciphertext: d2a1f0e051ea5f62081a7792073d593d -MAC: 1fc64fbfaccd -Test: Encrypt -Key: 404142434445464748494a4b4c4d4e4f -IV: 101112131415161718191a1b -Header: 000102030405060708090a0b0c0d0e0f10111213 -Plaintext: 202122232425262728292a2b2c2d2e2f3031323334353637 -Ciphertext: e3b201a9f5b71a7a9b1ceaeccd97e70b6176aad9a4428aa5 -MAC: 484392fbc1b09951 -Test: Encrypt -Key: 404142434445464748494a4b4c4d4e4f -IV: 101112131415161718191a1b1c -Header: r256 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff -Plaintext: 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f -Ciphertext: 69915dad1e84c6376a68c2967e4dab615ae0fd1faec44cc484828529463ccf72 -MAC: b4ac6bec93e8598e7f0dadbcea5b -Test: Encrypt -Key: c97c1f67ce371185514a8a19f2bdd52f -IV: 005030f1844408b5039776e70c -Header: 08400fd2e128a57c5030f1844408abaea5b8fcba0000 -Plaintext: f8ba1a55d02f85ae967bb62fb6cda8eb7e78a050 -Ciphertext: f3d0a2fe9a3dbf2342a643e43246e80c3c04d019 -MAC: 7845ce0b16f97623 -Test: Encrypt -Key: 8f7a053fa577a5597529272097a603d5 -IV: 00eec1762c88de31f3cbba97ea -Header: 08c0ea100c846850eec1762c88deaf2ee9f46a070000 -Plaintext: 83a0634b5ed7627eb9df225e05740342de194117 -Ciphertext: 814b6965d05bf2b2ed38d4beb069fe82714a610b -MAC: 542fbf8da06aa4ae -Test: Encrypt -Key: 40cfb7a62e88013bd6d3affcc191041e -IV: 00b6a88adf36912fdca0f3a5ae -Header: 88c0d9577df763c8b6a88adf3691dc4a8bca94dd00000000 -Plaintext: 2c1bd036831c95496c5f4dbf3d559e72de802a18 -Ciphertext: 89d8580340b626a0b6d4d013bf18f291b89646c8 -MAC: fd1f1f61a9fb4bb3 -Test: Encrypt -Key: 8c89a2ebc96c7602707fcf24b32d3833 -IV: 078ef822734701f670a55a0fe3 -Header: 88c2712a9ddf11db8ef82273470159140dd646a200000700 -Plaintext: 4fad2b1c290fa5ebd872fbc3f3a074898f8b2fbb -Ciphertext: 9d59b15f371448c230f4d739052e13ab3b1a7b10 -MAC: 31fc88004f35ee3d -Test: Encrypt -Key: a574d5143bb25efddeff30122fdfd066 -IV: 0bf351946bc96ba7ffe03c0e37 -Header: 88c245dec69a7480f351946bc96be276fbe6c12700000b00 -Plaintext: 28969b954f263a8018a9ef70a8b051462481922e -Ciphertext: eb4ae4956a801da9624b7e0c18b23e615ec03af6 -MAC: ce0c3be197d305eb -Test: Encrypt -Key: f71eea4e1f58804b9717230ad0614641 -IV: 0dbff943b9f9a66b81eca48989 -Header: 88425af28430fdabbff943b9f9a6ab1d98c7fe7300000d00 -Plaintext: abfda22d3a0bfc9cc1fc079363c2fca143e6eb1d -Ciphertext: 9a709b60a39d40b1dfb612e18b5f114badb6cc86 -MAC: 309a8d5c466bbb71 -Test: Encrypt -Key: 1bdb34980e038124a1db1a892bec366a -IV: 00efec952016915eec4073e723 -Header: 08419b50f4fd56f6efec9520169183570c4ccdee0000 -Plaintext: 98beca86f4b38da20cfdf24724c58eb835665339 -Ciphertext: 12c537ebf3ab584ef1fef9a1f3547a8c13b3225a -MAC: 2d0957ecfabe95b9 -Test: Encrypt -Key: 6eac1bf54bd54edb2321754303024c71 -IV: 0aca3f3aae60c4cefd996eccdd -Header: 88c1552d5f72bb70ca3f3aae60c48ba9b5f82c2f00000a00 -Plaintext: 57cb5c0e5fcd885e9a4239e9b9cad60d64375979 -Ciphertext: 4bf281ef8ec7739f91591b97a87dc14b3fa17462 -MAC: 6dba8ef7f08087dd -Test: Encrypt -Key: 494b501e194675971a48d08c5bc353cb -IV: 0aa4ad6d319985ba82e93437b3 -Header: 88c19afb798b8a4ba4ad6d319985bc429e8f0afa00000a00 -Plaintext: 25a98f9c1bd9c93cf383ab9d98152d76cb4a32c6 -Ciphertext: 561a0d068eac2eadb0c57fe2d0a6cc7398b6ddbf -MAC: cfe438cbea61fa9a -Test: Encrypt -Key: 489e49bc3cfe3fce3895820e872ee1a3 -IV: 0053f869fe279acf1d3e75fea9 -Header: 084340ec29fa759b53f869fe279af0f9f8a65416000052bfd2703d24 -Plaintext: 7f91f2472d7a121c9cdd4b6c9080675a1020aa00 -Ciphertext: 25df5173835e4fba23bc05a253885ebed3ac4871 -MAC: c868a725552c5565 -Test: Encrypt -Key: 02be5c4545672a07e4e314d70f1f9e85 -IV: 0d347ceb9aabffd2d6596e55d4 -Header: 88c3298c0baa9190347ceb9aabffd83d4886e5c20000e29d524ae1960d00 -Plaintext: f9a812e4a28af7f3714d4bf6622e5932f2184509 -Ciphertext: 6315500f924295cd3eafbdc3e151b1df46465b71 -MAC: 681fdee8513c62dc -Test: Encrypt -Key: 77077ed79453e4a18d60438cc6484d6e -IV: 00d8ac5a7ec44450b01e77fd8e -Header: 0843aa288b8435bcd8ac5a7ec444e8b46250538b0000e81402c2ee11 -Plaintext: 431981a2336d02f8cb8448d5428916be95293537 -Ciphertext: cf71b2ccbd590b20800792f359ed1cfd74d800b4 -MAC: fd0f41f426bb8f30 -Test: Encrypt -Source: aes-modes-src-07-10-08/Testvals/ccm.2, Vectors for IEEE P1619.1 CCM Mode -Header: -Key: 0000000000000000000000000000000000000000000000000000000000000000 -IV: 000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: c1944044c8e7aa95d2de9513c7f3dd8c -MAC: 4b0a3e5e51f151eb0ffae7c43d010fdb -Test: Encrypt -Plaintext: -Ciphertext: -Key: 0000000000000000000000000000000000000000000000000000000000000000 -IV: 000000000000000000000000 -Header: 00000000000000000000000000000000 -MAC: 904704e89fb216443cb9d584911fc3c2 -Test: Encrypt -Key: 0000000000000000000000000000000000000000000000000000000000000000 -IV: 000000000000000000000000 -Header: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: c1944044c8e7aa95d2de9513c7f3dd8c -MAC: 87314e9c1fa01abe6a6415943dc38521 -Test: Encrypt -Header: -Key: fb7615b23d80891dd470980bc79584c8b2fb64ce60978f4d17fce45a49e830b7 -IV: dbd1a3636024b7b402da7d6f -Plaintext: a845348ec8c5b5f126f50e76fefd1b1e -Ciphertext: cc881261c6a7fa72b96a1739176b277f -MAC: 3472e1145f2c0cbe146349062cf0e423 -Test: Encrypt -Key: 404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f -IV: 101112131415161718191a1b -Header: 000102030405060708090a0b0c0d0e0f10111213 -Plaintext: 202122232425262728292a2b2c2d2e2f3031323334353637 -Ciphertext: 04f883aeb3bd0730eaf50bb6de4fa2212034e4e41b0e75e5 -MAC: 9bba3f3a107f3239bd63902923f80371 -Test: Encrypt -Key: 404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f -IV: 101112131415161718191a1b -Header: r256 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff -Plaintext: 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f -Ciphertext: 04f883aeb3bd0730eaf50bb6de4fa2212034e4e41b0e75e577f6bf2422c0f6d2 -MAC: 3376d2cf256ef613c56454cbb5265834 -Test: Encrypt -Key: 404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f -IV: 101112131415161718191a1b -Header: 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f -Plaintext: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f 404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f 606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff -Ciphertext: 24d8a38e939d2710cad52b96fe6f82010014c4c43b2e55c557d69f0402e0d6f2 06c53d6cbd3f1c3c6de5dcdcad9fb74f25741dea741149fe4278a0cc24741e86 58cc0523b8d7838c60fb1de4b7c3941f5b26dea9322aa29656ec37ac18a9b108 a6f38b7917f5a9c398838b22afbd17252e96694a9e6237964a0eae21c0a6e152 15a0e82022926be97268249599e456e05029c3ebc07d78fc5b4a0862e04e68c2 9514c7bdafc4b52e04833bf30622e4eb42504a44a9dcbc774752de7bb82891ad 1eba9dc3281422a8aba8654268d3d9c81705f4c5a531ef856df5609a159af738 eb753423ed2001b8f20c23725f2bef18c409f7e52132341f27cb8f0e79894dd9 -MAC: ebb1fa9d28ccfe21bdfea7e6d91e0bab -Test: Encrypt -Key: fb7615b23d80891dd470980bc79584c8b2fb64ce6097878d17fce45a49e830b7 -IV: dbd1a3636024b7b402da7d6f -Header: 36 -Plaintext: a9 -Ciphertext: 9d -MAC: 3261b1cf931431e99a32806738ecbd2a -Test: Encrypt -Key: f8d476cfd646ea6c2384cb1c27d6195dfef1a9f37b9c8d21a79c21f8cb90d289 -IV: dbd1a3636024b7b402da7d6f -Header: 7bd859a247961a21823b380e9fe8b65082ba61d3 -Plaintext: 90ae61cf7baebd4cade494c54a29ae70269aec71 -Ciphertext: 6c05313e45dc8ec10bea6c670bd94f31569386a6 -MAC: 8f3829e8e76ee23c04f566189e63c686 -Test: Encrypt -Source: RFC 3610 -Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF -IV: 00 00 00 03 02 01 00 A0 A1 A2 A3 A4 A5 -Header: 00 01 02 03 04 05 06 07 -Plaintext: 08 09 0A 0B 0C 0D 0E 0F\ - 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E -Ciphertext: 58 8C 97 9A 61 C6 63 D2\ - F0 66 D0 C2 C0 F9 89 80 6D 5F 6B 61 DA C3 84 -MAC: 17 E8 D1 2C FD F9 26 E0 -Test: Encrypt -MAC: 17 E8 D1 2C FD F9 26 00 -Test: NotVerify -Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF -IV: 00 00 00 04 03 02 01 A0 A1 A2 A3 A4 A5 -Header: 00 01 02 03 04 05 06 07 -Plaintext: 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F -Ciphertext: 72 C9 1A 36 E1 35 F8 CF 29 1C A8 94 08 5C 87 E3 CC 15 C4 39 C9 E4 3A 3B -MAC: A0 91 D5 6E 10 40 09 16 -Test: Encrypt -Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF -IV: 00 00 00 05 04 03 02 A0 A1 A2 A3 A4 A5 -Header: 00 01 02 03 04 05 06 07 -Plaintext: 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 -Ciphertext: 51 B1 E5 F4 4A 19 7D 1D A4 6B 0F 8E 2D 28 2A E8 71 E8 38 BB 64 DA 85 96 57 -MAC: 4A DA A7 6F BD 9F B0 C5 -Test: Encrypt -Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF -IV: 00 00 00 06 05 04 03 A0 A1 A2 A3 A4 A5 -Header: 00 01 02 03 04 05 06 07 08 09 0A 0B -Plaintext: 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E -Ciphertext: A2 8C 68 65 93 9A 9A 79 FA AA 5C 4C 2A 9D 4A 91 CD AC 8C -MAC: 96 C8 61 B9 C9 E6 1E F1 -Test: Encrypt -Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF -IV: 00 00 00 07 06 05 04 A0 A1 A2 A3 A4 A5 -Header: 00 01 02 03 04 05 06 07 08 09 0A 0B -Plaintext: 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F -Ciphertext: DC F1 FB 7B 5D 9E 23 FB 9D 4E 13 12 53 65 8A D8 6E BD CA 3E -MAC: 51 E8 3F 07 7D 9C 2D 93 -Test: Encrypt -Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF -IV: 00 00 00 08 07 06 05 A0 A1 A2 A3 A4 A5 -Header: 00 01 02 03 04 05 06 07 08 09 0A 0B -Plaintext: 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 -Ciphertext: 6F C1 B0 11 F0 06 56 8B 51 71 A4 2D 95 3D 46 9B 25 70 A4 BD 87 -MAC: 40 5A 04 43 AC 91 CB 94 -Test: Encrypt -Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF -IV: 00 00 00 09 08 07 06 A0 A1 A2 A3 A4 A5 -Header: 00 01 02 03 04 05 06 07 -Plaintext: 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E -Ciphertext: 01 35 D1 B2 C9 5F 41 D5 D1 D4 FE C1 85 D1 66 B8 09 4E 99 9D FE D9 6C -MAC: 04 8C 56 60 2C 97 AC BB 74 90 -Test: Encrypt -Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF -IV: 00 00 00 0A 09 08 07 A0 A1 A2 A3 A4 A5 -Header: 00 01 02 03 04 05 06 07 -Plaintext: 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F -Ciphertext: 7B 75 39 9A C0 83 1D D2 F0 BB D7 58 79 A2 FD 8F 6C AE 6B 6C D9 B7 DB 24 -MAC: C1 7B 44 33 F4 34 96 3F 34 B4 -Test: Encrypt diff --git a/embeddedcryptopp/TestVectors/cmac.txt b/embeddedcryptopp/TestVectors/cmac.txt deleted file mode 100644 index 4fa6c41..0000000 --- a/embeddedcryptopp/TestVectors/cmac.txt +++ /dev/null @@ -1,38 +0,0 @@ -AlgorithmType: MAC -Name: CMAC(AES) -Source: RFC 4493 -Key: 2b7e1516 28aed2a6 abf71588 09cf4f3c -Message: -MAC: bb1d6929 e9593728 7fa37d12 9b756746 -Test: Verify -Message: 6bc1bee2 2e409f96 e93d7e11 7393172a -MAC: 070a16b4 6b4d4144 f79bdd9d d04a287c -Test: Verify -Message: 6bc1bee2 2e409f96 e93d7e11 7393172a ae2d8a57 1e03ac9c 9eb76fac 45af8e51 30c81c46 a35ce411 -MAC: dfa66747 de9ae630 30ca3261 1497c827 -Test: Verify -Message: 6bc1bee2 2e409f96 e93d7e11 7393172a ae2d8a57 1e03ac9c 9eb76fac 45af8e51 30c81c46 a35ce411 e5fbc119 1a0a52ef f69f2445 df4f9b17 ad2b417b e66c3710 -MAC: 51f0bebf 7e3b9d92 fc497417 79363cfe -Test: Verify -MAC: 51f0bebf 7e3b9d92 fc497417 79363cff -Test: NotVerify - -AlgorithmType: MAC -Name: CMAC(DES-EDE3) -Source: http://csrc.nist.gov/groups/STM/cavp/documents/mac/cmactestvectors.zip -Key: f8fba7b9b3e9d68a 2f70bfd304d32a15 9e13453e0d16928a -Message: -MAC: eb61515b -Test: VerifyTruncated -Key: 344a6732dc5e5431 e98a4f7c323dc1c4 6b0275dc150e68e9 -Message: 25db0710fb165d316e7c32dd25648ed0 -MAC: 862f0e2b -Test: VerifyTruncated -Key: 20ae32c49bab3bf8 f86bb66173fb54d5 3e700868c46bc291 -Message: 582bd9c8c36ec815d0a9 -MAC: 0d62f14f -Test: VerifyTruncated -Key: 62232501b9e9c1b5 54209d7c075d2c31 73a2f289a84c49ce -Message: adaf4bfffab79ffb60b94647faac634929c56e694052881881e60b1149b6 -MAC: a05674f2c905d153 -Test: Verify diff --git a/embeddedcryptopp/TestVectors/dlies.txt b/embeddedcryptopp/TestVectors/dlies.txt deleted file mode 100644 index aa71155..0000000 --- a/embeddedcryptopp/TestVectors/dlies.txt +++ /dev/null @@ -1,542 +0,0 @@ -AlgorithmType: AsymmetricCipher -Name: DLIES(NoCofactorMultiplication, KDF2(SHA-1), XOR, HMAC(SHA-1), DHAES) -Source: generated by Wei Dai using Crypto++ 5.1 -Comment: keys are encoded as DSA keys, with OID id-dsa -KeyFormat: DER -Comment: 1024-bit DLIES key -PrivateKey: \ - 308201370201003082011706072a8648ce3804013082010a02818100ba3ed941\ - 10332be99b77a345da72a33146ca960498a6fc2e0e207fdeaadf69c3e5650df7\ - 3255475854900b75af7f6aac021de687a1c166ecb2ab6ec6b9da82ad4fb0f48a\ - 966a2b968406e18ba50947d7ee3bb1f13511cb4dde191f0ade1933d089c5e82a\ - b8d283943d85ef0102e173abf2635aeac2f84cfc9ec6c4e8f3fbc4130281805d\ - 1f6ca0881995f4cdbbd1a2ed395198a3654b024c537e1707103fef556fb4e1f2\ - b286fb992aa3ac2a4805bad7bfb556010ef343d0e0b3765955b7635ced4156a7\ - d87a454b3515cb420370c5d284a3ebf71dd8f89a88e5a6ef0c8f856f0c99e844\ - e2f4155c6941ca1ec2f7808170b9d5f931ad75617c267e4f63627479fde20902\ - 01030417021501fdc788cd93f07dba3af2de42ae5aa3ede219919d -PublicKey: \ - 308201a23082011706072a8648ce3804013082010a02818100ba3ed94110332b\ - e99b77a345da72a33146ca960498a6fc2e0e207fdeaadf69c3e5650df7325547\ - 5854900b75af7f6aac021de687a1c166ecb2ab6ec6b9da82ad4fb0f48a966a2b\ - 968406e18ba50947d7ee3bb1f13511cb4dde191f0ade1933d089c5e82ab8d283\ - 943d85ef0102e173abf2635aeac2f84cfc9ec6c4e8f3fbc4130281805d1f6ca0\ - 881995f4cdbbd1a2ed395198a3654b024c537e1707103fef556fb4e1f2b286fb\ - 992aa3ac2a4805bad7bfb556010ef343d0e0b3765955b7635ced4156a7d87a45\ - 4b3515cb420370c5d284a3ebf71dd8f89a88e5a6ef0c8f856f0c99e844e2f415\ - 5c6941ca1ec2f7808170b9d5f931ad75617c267e4f63627479fde20902010303\ - 81840002818029eaa5b193357c200e0d42f374d4c003c633c77f4778fe40ad0b\ - d035b87ae5da4e74110ec2b15eefe1bd8b9357534c85328382946d314e15b79f\ - 7b854227012dfaac9bd862e73a5630e01327b36319765a3eb1434e108ef6421c\ - 659e3f9223966759611429b3c86ed9937563efbfad8bfedcfa92db3d7d2157fe\ - 2c8a33f08636 -Test: KeyPairValidAndConsistent -Plaintext: 76 -Ciphertext: B11D906CC5A8E71CA8962A8CC0AC4CAFF2DA00DC130C370F42D11FCF5C37DE046EBC07C7D457CA351CE456A043695D14ED055ADAD2B58BE0DF992685EF8B0D21597A43D7B3D9634A077CB70C4590CD73C20FAAACBC5649413EECA0C7B3CBF469E531299398F61496C51FE9FFE48AE9FE6034F104EFC562DE9529C776B86ADD4025AD6B0C3687B012F92C7B9E82F794E4FBE247D644 -Test: DecryptMatch -Plaintext: 89338CE80AFB62E9577A310E40311BB3F77F -Ciphertext: 8A33B0E212DB8155CA796B472F55CD77267C9106229B6055141EA3AAAE42AD27249D90E70F892B0CDC80D29D3D586A5CA6FE67D4BB44C58B03496708F80681125DCEF983B7453B1E4F927438BD2E3E506C1951E9F19BA70F9B687012440CD75C0BB78BDCFAB22AF535D3E2670ABD1F4D44ED95F3360536612B1A7DF35E2A88F66BD6E8C813EB9DC89D93A85C9A0BA13E4862B91171B681E64A0750197C6467B22566BC640E11 -Test: DecryptMatch -Plaintext: 0835455ABD53E6FB11ED9B0C00485D3C6845DB -Ciphertext: A81181517BD270B0D921AF735052898932008DF00D501EDE0D2D564871D61A6A837776E8D7C7F9B0E5F9181C1FC68BC430F30ABB1A64D62B444C0AC5AAE588B4481AEF08B38E466155F10CA04C8202F281186016AE35212A2C7815A22DB2750ABD526D285BDBC598672BFB52E95CE33A0D3E5DCF4CF5F46224CFBB85297F3AB170C8B9478994E32D9A21A452B095D3D902E92C7E444A3307FDD7256FE49341142E5FF7A616475A -Test: DecryptMatch -Plaintext: 1EBED48EC47B6987091C52BC -Ciphertext: 1DF446FF43AAAAAC8E3F7D70C912E2D45AB832BCA3D0FBD17AF864B9EA878C45B9E2902804171A739A0552BB7CE0CD46DC16343714CC9C2E71AE26304885EEEB242665814DD9E33C480ABA214755D5449F16CD8870D1AB3A8E64E45E463AB3F4D3031FA3ECD395B61B372602665FCF218D9C51E8C791FA1E5BCC2916EFBB482E1814632CDF0F1852EE4943D9652DAA4E1F3B22F17F57F51D52A0997BED5B04ED -Test: DecryptMatch -Plaintext: 65D8 -Ciphertext: 4385797FD38AD5DFBB4F613BC87637B0051501E57699A5880E235DB7A6994A04A1613D0C8E07E36AFD08F2E47D018951B22E7625DA647AA1A0791DB3B2FA794610892D9A3D3F173CF95277B4B1EB92579A229510B67E171CB5BBA8B3AA732047BA038816A30124AF1C4C57CA80E93AACCC8EC70BCF7867914E7DE2C403568F9778F8DBEAF08FDB9F48452054C9735DC84F012DF8FE17 -Test: DecryptMatch -Plaintext: F86D8ED91E9934125DA6E9B4E97545C83A -Ciphertext: 13B0AE03AB532D5E31C9384B4E726A9AC73583CFBB0643EC322E3D2D45D9358CAF745B0541C136E8AA2220C42CEC9E1ED174886475538732AA6D6417DA89FA411AEDEADCD9F15D25D27D0AE252F77E888470AE696D5805CE8CCCB40B45D4AA835E97C7BF2CD6A2B4FEC6FCF858606CE4695DCE998C518360068ED028FC882478BF96096D92C166899EB51778BC4B7DA1BA8C4B6CEBA1139F17CEE484EA104A0325420A3D56 -Test: DecryptMatch -Comment: 1025-bit DLIES key -PrivateKey: \ - 308201380201003082011806072a8648ce3804013082010b028181015dd79808\ - 07a15e557e3a39466eb2987828c536a871d4fc7f3723d52f8145a0d10d996295\ - 64aca54fd567c0509ef3c428fac68d916551e77a5ca0ed6d9f12cc96262b1f11\ - 49f398ef9f0f17fc0ed92bb917f890d1e6a4f62b91a7978d0aa1bf53b89805c1\ - 06ebebd0924cb99a4168a38dad65238236d4d166d38a3dfd5359ec5f02818100\ - aeebcc0403d0af2abf1d1ca337594c3c14629b5438ea7e3f9b91ea97c0a2d068\ - 86ccb14ab25652a7eab3e0284f79e2147d6346c8b2a8f3bd2e5076b6cf89664b\ - 13158f88a4f9cc77cf878bfe076c95dc8bfc4868f3527b15c8d3cbc68550dfa9\ - dc4c02e08375f5e849265ccd20b451c6d6b291c11b6a68b369c51efea9acf62f\ - 020102041702150f514282f489098f1df0c7be02ccbb3f23bed00376 -PublicKey: \ - 308201a43082011806072a8648ce3804013082010b028181015dd7980807a15e\ - 557e3a39466eb2987828c536a871d4fc7f3723d52f8145a0d10d99629564aca5\ - 4fd567c0509ef3c428fac68d916551e77a5ca0ed6d9f12cc96262b1f1149f398\ - ef9f0f17fc0ed92bb917f890d1e6a4f62b91a7978d0aa1bf53b89805c106ebeb\ - d0924cb99a4168a38dad65238236d4d166d38a3dfd5359ec5f02818100aeebcc\ - 0403d0af2abf1d1ca337594c3c14629b5438ea7e3f9b91ea97c0a2d06886ccb1\ - 4ab25652a7eab3e0284f79e2147d6346c8b2a8f3bd2e5076b6cf89664b13158f\ - 88a4f9cc77cf878bfe076c95dc8bfc4868f3527b15c8d3cbc68550dfa9dc4c02\ - e08375f5e849265ccd20b451c6d6b291c11b6a68b369c51efea9acf62f020102\ - 038185000281810107143658b98a3725010d3631a3f4f7448cb967ac0118e4ca\ - 8fc8871eb4fb872d55c52d93a4f21eed98b6499db74315956a268f38a288958b\ - f7c4d548662c668669d69375e0cb710ff3a1a9f43e49add1f7ae58b836b6444e\ - 419e40474c27066cb03aae8132e65f3fead0109307ab1c7f0254eb14e9d76639\ - 1a66ca1ba442b425 -Test: KeyPairValidAndConsistent -Plaintext: 256F07E0D37D69BE542BD17FA98CE4CFC3DA849B -Ciphertext: 01269CE30DE12430904CEC9D8B91A6D8860B4F8D37FCE7DBDCE8FA18AC521684F4C1CD5C38BF3B42C259033CD36A53F0376A0CDD801979CF1B76ADD72AFDD27830BD85B373C4D451B84926ABA34012EB98331F0B81CCF8E801ACCDEE88A35DF60EFADABA1F395250A15463203FDCCEDAB7DD6CD1271B38A5E0946F8D189B225E8A307D198AC5E4EB33BCF26A02C0C602AA14592AEA01452E4F8AE46E7A032BABD1BA8ACB0919F2EA18 -Test: DecryptMatch -Plaintext: A992 -Ciphertext: 007822B0BDF45CC5B15102B5E21F7656C8896E98FAD6C2AF6CD55D0DB90B7A6B05E36D260C7A5C070526813290BCA722959B9B9BF00041B4B7F3E3EAFA9B5376A1E02944EDA55B99202601AE6D402D56617B56B28BAC1B405016053CDC78AB4D372B0D58E7380D50F1CD0E31B8CB77FD2F6BA3E7A436A5B35552B9974EA5AB30AC0C4989E34F5FD7D272417FF2094B97119BEB2C73C68B -Test: DecryptMatch -Plaintext: 1D20C118C894EFDC67DAC33E56179C5D262C83 -Ciphertext: 001587AFEC265C244875371B680521FF93F0B1196901A7D580785B62A257B1736C86D1D9E59A31E62F53B92B209B45A7952776C6AC839243B0BBF3A059E6CEE99B120BBD45922B4E813DDE0F5793A42B3AF2DDDAA357136A010519D884589A1F9912110020A8C16E9B91C753EB8842B3224FE9C9A22AE2B82251CFF7799E78885B0B67B27DAAC6A7B58013C31115C2B8C0C0176BC2A7B96A299CC75693B4F2138B2B4053CB5320D5 -Test: DecryptMatch -Plaintext: 83BC82A4F7A4DFC96CD7798BAC52254CD6E9 -Ciphertext: 0085E83465997BFED9CAE63B04B0419578D0BD85B1A65285E5537F4367E5E7E11DD8762BD3335916A13B8CF9D5BC651E762458E9879363B06748BEA0CA86D32CBC4F1B0C0BF67E616B872A64F7356241CD052944F6594A570522EF2BCC53D90E3326D2ECFA036C46256D9B678C93BE5877749AF8FF8FEDB6E1E17B67C7B6C6098D0C71D5B2AB503AFD7739ABCC8DE67DAC056AFE99D8A107230BA88C282FB8FD46E9E9E2C6874A -Test: DecryptMatch -Plaintext: 157597899A950A32 -Ciphertext: 013623199FFDD0D4689A4C50A9FEA3C2250D0C73F209F33BF3EF13E6035976D6F3EAFBA3D83A3862E4B6DFC7581EA43B62F49BC85392B7EAB854F92DA8DD5921A6A4C42777E89004EB7E6D479BD028F758171C324168DC0814369C6BCD8471D9620C4E9BED785A220EF9C0DCF1201311A16C51341E0551043C6EAB45E04A81C9280633F58621D8D3492864FFF6A39EDC48450ABFE0C7AABAEB9A86CFFD -Test: DecryptMatch -Plaintext: CDE651 -Ciphertext: 0040308CCDAB105426597D84A64665200A93208713004DB38594C490F7B85F08ADB67BBE47B7FB7BBDA435A6B6A2CA0B4CBE0FDCBD4FF078FD052213CBCAA4580D1C7962A3505DAA9BEA2957718AB36D061E61B9DEB3D7DD726975C6E7FD79AADBF649F5ABE51AC384E967D3CDAFD9EAA18EEB69774961E439F54844FA22DA1B6892E86471DAE6F7E74CACC944123234826621C7634AE34E -Test: DecryptMatch -Comment: 1026-bit DLIES key -PrivateKey: \ - 308201380201003082011806072a8648ce3804013082010b028181031e7d8589\ - b9fa11e77204b8c1b27ad66b39863978d26912a65de306dcb32a0c7c96bb431d\ - c4a14204a8f01a65b0fe56a4d016716914c21576f10d63dac5f49287636519ac\ - f9be56c9f58eeb90ba3240d4cce26f647bfd86360cf0f6b8ff609ae2ef736558\ - 155a1498adf4e92dc90f34169123a5fcd8ddfc763c81658a4d08383702818101\ - 8f3ec2c4dcfd08f3b9025c60d93d6b359cc31cbc693489532ef1836e5995063e\ - 4b5da18ee250a10254780d32d87f2b52680b38b48a610abb7886b1ed62fa4943\ - b1b28cd67cdf2b64fac775c85d19206a667137b23dfec31b06787b5c7fb04d71\ - 77b9b2ac0aad0a4c56fa7496e4879a0b4891d2fe6c6efe3b1e40b2c526841c1b\ - 020102041702151fa3003b00efad22ecc26c5115e6d036d13d3b2f7e -PublicKey: \ - 308201a33082011806072a8648ce3804013082010b028181031e7d8589b9fa11\ - e77204b8c1b27ad66b39863978d26912a65de306dcb32a0c7c96bb431dc4a142\ - 04a8f01a65b0fe56a4d016716914c21576f10d63dac5f49287636519acf9be56\ - c9f58eeb90ba3240d4cce26f647bfd86360cf0f6b8ff609ae2ef736558155a14\ - 98adf4e92dc90f34169123a5fcd8ddfc763c81658a4d083837028181018f3ec2\ - c4dcfd08f3b9025c60d93d6b359cc31cbc693489532ef1836e5995063e4b5da1\ - 8ee250a10254780d32d87f2b52680b38b48a610abb7886b1ed62fa4943b1b28c\ - d67cdf2b64fac775c85d19206a667137b23dfec31b06787b5c7fb04d7177b9b2\ - ac0aad0a4c56fa7496e4879a0b4891d2fe6c6efe3b1e40b2c526841c1b020102\ - 038184000281802c6360e6e3eba6da6efb5bce8d07a99e42949b68b3c2900583\ - c2eb34498081c7212d8dc95a631d63edeafc625f8faf063e57b41d7b662ba9c1\ - a99b3f2506fdf5e59116a0e93e7e94aab55691abae75eaac9637a713949360a4\ - 5f6908f23ba5503d4760bcd6f7abceb8351a66bb14fae05f03b1494e7ef4154c\ - 99a9cb6a9bfe12 -Test: KeyPairValidAndConsistent -Plaintext: DEC85711F12C0D1D6C26797E91B0F39B37 -Ciphertext: 0215D75DD99B8A59DEA3FBA9B0F8A621EFFBFD831E9543749B04B495147CE9B56D519EE71BDF56D86FD1D9C1AE8BC1D7F29DC469A05221E4A31C726971731CF627E63FAB269FC92DEDDFF3319819373F299D55F4CABE08DADF29A7C60E9B4E2806899371B93A853F828EC4312D94CFDADFDEF2037D9C1FCE21A3E451006AC542E1BC36D3C33AEAC0D1666C26AA886F4C118836EDCA7C5A428E407C4ACD62A885C03202230FA6 -Test: DecryptMatch -Plaintext: 0E665CD2CF75C2E6E24908448F29E9A198EF -Ciphertext: 00A4583FF3A9451C6F8970E53D95EC74F41F709F5156B4FC9C698B1E43C7B5F3230D5417AED2C7447455009CE8381A30BE400EC15BBB1D7BCB9461E593D416421157541479FE1DCEAAE635728C68C58D260337A25D0CF9FA291D84E9E1DF4FF96822CA1F05CDD247AD14E5AFB231A0AF0F2E79FB9A0528CA2FE9431724C0AC9F0A2ABCED9A20EC1203DE2A835D90EA5FB1447EC722456B6F4C75D0645CEC5BECCE35B79FF3071A -Test: DecryptMatch -Plaintext: BE2A -Ciphertext: 02823CB4ABD598FC5D36300306460886BBECFAE6F56E02708A96EFB27EF7E3D8F08442FC819EAB1DC35CC70A074984A149F209EB285C6064DDDBC7781CEF7358F384D592BFC75D346A6D97D8524CB35060A35E3B3145199F4968677FA22BB468DBFF63E3E366D778B3042D5858699D9FE5D6F53D0CB084E107111B572AE9B933B94FF37F2681DC50CDED2714668375DA90787CF0144F1B -Test: DecryptMatch -Plaintext: 20D57B7E074BFFF8F54AF3E69C9B632253B3B5C0 -Ciphertext: 00D18C24BF39CD527455737B4B214BADDE99B070181C1E4729CC7B6EAC82298417FFAE7BDA1F41A7D74D6969BF9CAF3A7F9EC9397DB75F5E53D0282F793D601A28E8B3CA8730CD9D7A0ABA338E2DB3EB5314321EEBA2F16C8072DA6AD9A887AA5AED0EC5EF3DC7E5726626511F8F23B0BA4D83BA358DF0951B07399C7515349E3DE2938D2AA53AB11A4D1C07213E091CD3FB6453AF7DFB6799D45DA44B060F7BF5ACA5A25B3892BBB6 -Test: DecryptMatch -Plaintext: CC47935F7976 -Ciphertext: 02366250DE032B147BCEABCB576ED39F4993251D25010FAEEB41BDDA4301B890063247EEDC041539488E70B977091BF581033EE6EF75C224C8046EE3E7D2330383A30BA07FF33D10F07FF6E1EE20FA4D112CAB1BF457B50DC301DE5C6DBFACE227903379A41DC4D92517A547968D3F147D6435C3DF6A3D0D13635360716CBAC322EBD295593865C3A117050059FBEC83D112C5C3727377EBA7778A -Test: DecryptMatch -Plaintext: 3A370FAFD82869FEC40117 -Ciphertext: 026AE53843D3EFE36D8E52D9FD55DC6F0A0F51584BF81529914DAB6E380A6C9716828A7254307440B6A0CD16BF0D9D713939AE7F6C4D82D5AA70F33C9531E4071B9CB415C7622A23DBF4C81820BE04272874549F081B57D40B27BC1879BF134A2CF5D15203D326F9F97BCAC8606082A50A755CAE6FE2B72060EB1E0B72EF5AFAE8A823B3F0F91877C931CA64A06F3888DD4E2C823B3FCF529407255BE2AAD36A -Test: DecryptMatch -Comment: 1027-bit DLIES key -PrivateKey: \ - 308201380201003082011806072a8648ce3804013082010b028181072c45d24e\ - de76df2a03270413d8ab37645c8d6301ea76bb6cedea97142df7aa422b83043f\ - 8cfd8874dd684f47138433f5832c83c8c811d3c6d477b088006381ffb066402c\ - 951670f1927b1b67883451202f456bdb975d8bb2cde9b43c178ecfe788a0a0ab\ - df2cbfc700fbb97ef71e52221bc054fbd3cf8c04175e4841a45b89cf02818103\ - 9622e9276f3b6f9501938209ec559bb22e46b180f53b5db676f54b8a16fbd521\ - 15c1821fc67ec43a6eb427a389c219fac19641e46408e9e36a3bd8440031c0ff\ - d83320164a8b3878c93d8db3c41a289017a2b5edcbaec5d966f4da1e0bc767f3\ - c4505055ef965fe3807ddcbf7b8f29110de02a7de9e7c6020baf2420d22dc4e7\ - 0201020417021506533f6f0886a8a44137598adb93aeee548c9af303 -PublicKey: \ - 308201a43082011806072a8648ce3804013082010b028181072c45d24ede76df\ - 2a03270413d8ab37645c8d6301ea76bb6cedea97142df7aa422b83043f8cfd88\ - 74dd684f47138433f5832c83c8c811d3c6d477b088006381ffb066402c951670\ - f1927b1b67883451202f456bdb975d8bb2cde9b43c178ecfe788a0a0abdf2cbf\ - c700fbb97ef71e52221bc054fbd3cf8c04175e4841a45b89cf028181039622e9\ - 276f3b6f9501938209ec559bb22e46b180f53b5db676f54b8a16fbd52115c182\ - 1fc67ec43a6eb427a389c219fac19641e46408e9e36a3bd8440031c0ffd83320\ - 164a8b3878c93d8db3c41a289017a2b5edcbaec5d966f4da1e0bc767f3c45050\ - 55ef965fe3807ddcbf7b8f29110de02a7de9e7c6020baf2420d22dc4e7020102\ - 03818500028181056bf5dcced97da0ddd23c1f1294f97431e323f9719fc9bed6\ - 352d08a88ceb13a06b559b8ef7dc04c5a04a761a9631aa1000f32f885fb0de56\ - 505524ae89462079631f438284c8e5225c021d7731087ec0aad11aba9bba95de\ - 03f5c99ac228861a3ee6a7b47617cec687a58255321694b923e63ed247e65ff1\ - 4c279bec5282bc1b -Test: KeyPairValidAndConsistent -Plaintext: D391B4F3B53EB9B035C3AB1E3C6E -Ciphertext: 05D90F9892F6DD3DC3654130CAA312D2287D9E57607C301BE58607BB19FC78D67F2082C907FACA819A0D946AD16B46FE1E7264BE7D25D4EAB4F80D136E89EE7BC53B65CC1692581E3ABFA3C15482A6FEEB607AD1765897E67BCEDAED0E03FDE18E05330A99BEBB8710C77E7735CBB747EB507FE1EC04F239E964B509A4FEE8463478E28BF5338AE016DED9FE6B2DDBD3FDE467C45F0FA619E039FEF085D2F1544EA3CD -Test: DecryptMatch -Plaintext: 28 -Ciphertext: 066BBCB2D9E474A2C6CD514663BDA7AECA1F79136A00C1F9BDBAEDE344872093E67102307C96BF824999D86543121CC3D99B5CC4B511153A42E8A1569D063C27788E105858AF8EEB0766FAD9E0EDEFAEFFC733BE6824644CEE03AEE5FF15860CB3CBF4A46F95988D5E010FB844F944628043C830E575964EC36E2C38326C771085D796F2C22C0969E58665626415463A3CA1F56C357B -Test: DecryptMatch -Plaintext: D2C349F40A24230689EA15736C3AEFB1588A -Ciphertext: 019A66A4ADFED556BBD1E58728A3B7A3631458DCF677BB155DA989827C2240A586783D8C5DB98E266C39FCDF6FB016BBB25D53A6B30F3BC9D1109CB908B54F1932335F3DFC2C80847D94D13C5933953EA1D212107AB42189536171069621403681CAAB2A13EEAEC847193FA6A0234FA8F107E2C1747425584EBB4F4D702E29A3A09580E25B34413208009F9643327A636DF622B7F0267D3169A64646F301C584F64066801383ED -Test: DecryptMatch -Plaintext: 85D75863811C6F574222B577 -Ciphertext: 02C6FFDB38965F3061C736E633B497192862677CB247A37C5FA1FEB4F2C021EA94C65AD9506C73C2E98ADF0F340DAFAD2BF6F6CC906C93655594D093D4B0F6867755013C25ED0AD75DC9A04DD0666E6340BDD6C1E748479F3D64129F76B5BAB37D26319287EC9D65CE9E2243D4CCC7BCEA4065623C4D388A7BD779941EE541DD29E070F7356ED1A1ADAE947D79F8421FA717F933F08CBB8B699B551F1EFF75B8F5 -Test: DecryptMatch -Plaintext: DD07A91D32C26D3258AA4ABBD82E81 -Ciphertext: 05669E0777B003CC2EBE9BF3981160806A8B416A2DEAB4058497C5AF6A5C8F8D1ADF1225CC6FF7D292320E9C98CEDA144862FB4E32EE11AD9CC76A5C85FAE56A2567E6C9D168586F288CF4D525C94FF9F0ED6C3DBD08787768B90F8CD776520EFB920E61FB0E4463BE8D5AAE2683D31F392229A9554E0977BF25BCBBAAC7BB4FCCB009630D0203451A7A2AF847BA60AA0CE8C4D656DBED02353B92025925E1A0A6DF490F -Test: DecryptMatch -Plaintext: 0AA6B9FB846D1230F521F2624127 -Ciphertext: 01A9D56F1547728782D4F80BB0EBC8890BAEFE994900F41D56094F4734ABA2BB371060B2A69C6B7BC8944358519D141FC277E1195B3A78F7068731C3AF3C604A062A0D551397CD804168B7F400F786BC5CC3F912457AEAD56873AEF1A2378F34E953E240C20FFD7DDA229D4C020BDC68684A53C0AB3ACF9B44581353C60CE9854E3451645A604BB7AB3EB44088A07F59CE0FEB6454CC5A83BE5E939B317D4D8537CAFA -Test: DecryptMatch -Comment: 1028-bit DLIES key -PrivateKey: \ - 308201380201003082011806072a8648ce3804013082010b0281810cb31a78b6\ - 6dafe2dd020483aec0cad421e4a3df2a81b827009dd74f5ef0468fc508477190\ - f628033471ee2d56f913d45a94a8ad1582b29785a7ead06c88ce73812e653797\ - 921d3c4a8fba91c1423d6609e85625b2f41494546500237151958b13d1cc0f90\ - 586b0233290d052a18c2aa3ec2bdc32adb4676cbeb30309e330b823702818106\ - 598d3c5b36d7f16e810241d760656a10f251ef9540dc13804eeba7af782347e2\ - 8423b8c87b14019a38f716ab7c89ea2d4a54568ac1594bc2d3f56836446739c0\ - 97329bcbc90e9e2547dd48e0a11eb304f42b12d97a0a4a2a328011b8a8cac589\ - e8e607c82c358119948682950c61551f615ee1956da33b65f598184f1985c11b\ - 020102041702151c0cefd22a713385985cacb5fe84cd40e724ce9587 -PublicKey: \ - 308201a43082011806072a8648ce3804013082010b0281810cb31a78b66dafe2\ - dd020483aec0cad421e4a3df2a81b827009dd74f5ef0468fc508477190f62803\ - 3471ee2d56f913d45a94a8ad1582b29785a7ead06c88ce73812e653797921d3c\ - 4a8fba91c1423d6609e85625b2f41494546500237151958b13d1cc0f90586b02\ - 33290d052a18c2aa3ec2bdc32adb4676cbeb30309e330b823702818106598d3c\ - 5b36d7f16e810241d760656a10f251ef9540dc13804eeba7af782347e28423b8\ - c87b14019a38f716ab7c89ea2d4a54568ac1594bc2d3f56836446739c097329b\ - cbc90e9e2547dd48e0a11eb304f42b12d97a0a4a2a328011b8a8cac589e8e607\ - c82c358119948682950c61551f615ee1956da33b65f598184f1985c11b020102\ - 038185000281810aacd80676c540b97f74d2a94c2f389795c9f696d2a1fa934d\ - 20e93d49d0099d9312552e6e310da5d97cef87c9a5a4c47e7acd195293b09adf\ - db8e0cac95139446aba60fd625d17eaa102c7c26568b34891edb38226f949656\ - 44a9d52ff299cd007ab3dbc15779d4388431a66774ffaae5c6be04526b28c620\ - ac97e8618cb09d46 -Test: KeyPairValidAndConsistent -Plaintext: -Ciphertext: 0194C64DEB9CB401573730A29359456F4E9528347ED80F24E5AEC4441E896E38047EF95AAD9AD7A25AED6CC89FD95CAAEF27F3C814C26FE43F6D65288D87E372A204D1A66C3BCF0346CE89E9D2D7646E90BACB9A85022ACFEF8903C72A663BAED9A346E1A6B2B2FCF70E239EE70A34385F8C76CDD121F6B190085BAB3300E6B811906CE38AC740FE88A3DF8DCA1C6DF73A03236D51 -Test: DecryptMatch -Plaintext: 9498EB7300 -Ciphertext: 0A38C373F6A96D87528D2D55F6391A9E801252A65F622F36A130ABD140E1858024E31F247C3BC8C07D9500CBE7A8A3D6C0670AF0FA14D020DC54B201E657C233F8031DF990AE801077D4D3AD9B861F4C32D36FFB9E8BD5E2651169BC4560CC7FD02159929AA50882F8B4C8508BB98F6BE8A6A7C0E21A2A81AF781447ABEC85C170F3F6256C3B6C5E2D3A01BB5EA8B502D37561C06F1DA536BD59 -Test: DecryptMatch -Plaintext: F07FFAC9794BD8D528F750D50C05 -Ciphertext: 03DAF7F6C2BEBF8D0B380EB71BD8BEE9D649AD7647DF6DE4CBCE00D0363E31F11E0DC0331409863E3C069EE3F975E7F623B55D7F4690C7419C5AD97EB52BBC0212D3FF0A83A031591A31481116B2CD232A9C86A20EA40BD13A53BB73E644A6C7DC1E6C767756E7235538E9D5B155B3173416E99F121E96E02034C6DB9129489A050740F603DEFF96EF1D99E7EB4A32083D0D946670B1AEF30E1E38D3F076D6BCB57255 -Test: DecryptMatch -Plaintext: 85916A46E0965C69C4773C7DF9AF -Ciphertext: 053D29F0878C68FF55FFC8E6E0E03044AE23B79588034F0236A49A5B6D00EFE8C564D2D29ACB61FE49C0E984EFC3A48A96EAF22AF3032D8D0FD3B3BB16A0157C161F2B3D3DF802FDD6B61899212F44493383DDDEA8B2463BACD0C5E1F4F9E4063DE5E52032E7DA8B79E04C5F03144CD710ADA74506CEC2D448BEA0F2B59AB63FCC443BBE920748E122DDD6123BDDAE484DBD02088817D999FDF80D5ED4B308AF4C2DCC -Test: DecryptMatch -Plaintext: EB632C72F563174E680961BCF26EC7 -Ciphertext: 0BBE666C02191F668A2DB000646A14385A8E9199BD887913BA587DA4C683535801853186673AD7C43EFA5B65902559BA5345EFA111E0514D461C1B1EFFAE58708EE6C17F1758EBED31F0B3206B0EC1B4BEB2EF911C589E25CDC3B0020C47119B5F33EA2FB7C332CA6B1FDA2F350A4CB0D6844637F2CCA71EFB036C7400957AE093B21BE90E30A8672847C9BA5266EBBF9D62341F67A4D09FFA196A817DD2F5EE1A9654EC -Test: DecryptMatch -Plaintext: 42B5D2DB89374231 -Ciphertext: 0085B6894D887B59393F9D7365411DF239BE1104FD86CC63A52C990A84FC4660FF9B60CF0641E44A8224C169A9FD1B35EAF78008E34F14B5311CB5D725096D9DE92F35BE6E71E3AC3E3B3D68BDD5351A5AF93F0B3BCDB00B9B126D8DA07E5F42107181F9580CCD0D6F086C94177FD48ECFAE3FCF2F26D64940D749E8A964275290A247AF700210500517BEB2175326F4CD3016AB175B352F9BD3289079 -Test: DecryptMatch -Comment: 1029-bit DLIES key -PrivateKey: \ - 308201380201003082011806072a8648ce3804013082010b0281811b02fc18f7\ - ba0ae7f84ebcaf319294fa2bad52e47e1926267ad38b2f1b2566145bbc190cb5\ - c39a8d6229eb238d3742bbd234b0f28eac92363a31ac96c5b08eaeb1963de59a\ - 3b2d0295c0266a7da4ca92b64f96c497f262e98df7f20ec55814b8441acfb639\ - 7abf9c4e42ab9bd6dda6ae180b12e12ead68672f9d56b98ee40e2b630281810d\ - 817e0c7bdd0573fc275e5798c94a7d15d6a9723f0c93133d69c5978d92b30a2d\ - de0c865ae1cd46b114f591c69ba15de91a58794756491b1d18d64b62d8475758\ - cb1ef2cd1d96814ae013353ed265495b27cb624bf93174c6fbf90762ac0a5c22\ - 0d67db1cbd5fce272155cdeb6ed3570c0589709756b43397ceab5cc7720715b1\ - 020103041702152c7c60166a1bfebb17831e65b8e1f61f3ef9ed9ff7 -PublicKey: \ - 308201a43082011806072a8648ce3804013082010b0281811b02fc18f7ba0ae7\ - f84ebcaf319294fa2bad52e47e1926267ad38b2f1b2566145bbc190cb5c39a8d\ - 6229eb238d3742bbd234b0f28eac92363a31ac96c5b08eaeb1963de59a3b2d02\ - 95c0266a7da4ca92b64f96c497f262e98df7f20ec55814b8441acfb6397abf9c\ - 4e42ab9bd6dda6ae180b12e12ead68672f9d56b98ee40e2b630281810d817e0c\ - 7bdd0573fc275e5798c94a7d15d6a9723f0c93133d69c5978d92b30a2dde0c86\ - 5ae1cd46b114f591c69ba15de91a58794756491b1d18d64b62d8475758cb1ef2\ - cd1d96814ae013353ed265495b27cb624bf93174c6fbf90762ac0a5c220d67db\ - 1cbd5fce272155cdeb6ed3570c0589709756b43397ceab5cc7720715b1020103\ - 038185000281810e6e9c7b74e33a1f4683ddfa35509c39a75b75c10f438efad0\ - 82caad08a7418990983150a9a5ffe3f8e340443dfbabf82fe060da487f94afdd\ - 1e713d491b983fc4fb69d4405a12e356808c5cf6a7bd397c1a5637ba8e168b7e\ - d3f549a9f39f343e8fe3992706e782a1dde5c5e9e6a950f7d980835c1bc1742d\ - c2840cb2e61086d7 -Test: KeyPairValidAndConsistent -Plaintext: 03C57B87 -Ciphertext: 1440C6776914314A1DA161EAA41D52B283E2C0B487C801CEC33DCDB639F579F69D12FD029C994A311913EB6869C7A5659EE8BD9F5D7225BBB2EB77CF6F3D24A5E9866BD2CC50E593EC5CEBA4A96C59FE8B98B5EE2121E5892F2436F98B5C4E4A12077A1A64F1FCEB783D05453A657BB91909637063813CC00754402DE24F4AD6C0D9D4C15B7F4E485AF3538D391CF5993A59F6D1FE6C76E2A7 -Test: DecryptMatch -Plaintext: C5598C0FE0D90B10E7125079E2EDA32E531C2EBF -Ciphertext: 129FC863B70BB82C1C59EE2DA37FF3909F1DAB4B55D9727EE0CA3311BE5797F93446ACA0409CBFA848A90756D2598B6ECA56F6341C6E9F716A62380CB5D47400CF392A5441DA5AD2C1D066F894942837EA7B6237D7BE2E94FFE0A106148C2B7B9AF624242A945BF3B217D89FDBB070FA5940C1C899AD83AF1F865DEADFF0F4E48A7E00BF7AC5625F6E32F8B01394AE90284AFA061AF6DD61ECA1B8FA77CBC172573A9938332D7AEE41 -Test: DecryptMatch -Plaintext: -Ciphertext: 068117F2BCF29C72CDA3F4560A2165B7DB7C29314EFEC8D110425D5AA02F35C0F9A2304A0554C097944EF3A615BD70F5461E6549C319AC1207B100FEF022410C46284CEA9CA103685A18EC944DEA0BAE8E06D2489A3E2D1D9B255F192677664CA6FF44130C28CDE1FD437E85396503DFF305BA2D64E8BF9C75B00CA1595A1AED2C60865C0DF03F408EF95517E70552B2D5A8C190DC -Test: DecryptMatch -Plaintext: 8DDB5FC737283E5B -Ciphertext: 0B3E0CE51E1D3AE240EB34787DB5D49D6786B3BCC29C37EF8B9155F342C4D226CE1D07F7BAE09DFF7E8CD89915E1312F43540A26F03D918BF56B07E6D07A96870362643092F24FBCC6A2DE62F637B5F5F807E430DAF9B7AFE1890143591BBA035538FB419BE4CBADFCED5EB8BE2471B39CFCFBB2BA854C9E0F52E67524ECB80F9FBB3173D2A18C9F4C43F4E20866428A9256AB8AD199BA0BAD55A18896 -Test: DecryptMatch -Plaintext: -Ciphertext: 197D4DC43B0716191F926DC806A1B707ABD6684735144AFE07E0EAEEDD9BB3C89B9D0076859DACE6FFF9E2685592ECB010909910DCA50D2FB1B15EB9B9CFF4F71250D807EDDC2EFB2033BDFD93FD10E117683E3E4E8A5D3308572D4852954BD51251279A79092E3DCB95F1FCEC8310931933F47998DDB61438478CD80864F08D3370C863BE6E7E1CD22E38BC512D9A160478814057 -Test: DecryptMatch -Plaintext: 53AC983CEE599A17261C53 -Ciphertext: 0E31EAACA9E8A86ACEFD1CB817869F48EAB342EAD0DAFE17B848CA9CB72B92567987B929F655B8D601EB1384BE380C8E4BA8B4E274F724F02FC5C00479C308813A3963E2D8AC88ACE92AEB00AB024A4EC5560857310E03009752B86793B356DA344B4AEF01F3ACCD9CBFBE399D0016260C006FCA5443359EA1E012D43921B8D2B8CFD31B94972ECE9C0031420238C76514635E9B40F17D9AF25A1009DB75E4C0 -Test: DecryptMatch -Comment: 1030-bit DLIES key -PrivateKey: \ - 308201380201003082011806072a8648ce3804013082010b02818127b35992d0\ - 8edcc7aaa6ca70365afa8ffacb4a9bef0ea348e27414c2100b81827fbf1abd3f\ - 14150bb5d85ab13b2aca21304365f150511a68c90f4a4eac0bfef0c548e3076b\ - 30a24929c4482f42f2b03ce122b3a251e685a3fe3dbb539932bf8d2b117b1b08\ - dbceb78c84966270657164fe6f20c6d27dca270dd4417f843fdfb23302818113\ - d9acc968476e63d55365381b2d7d47fd65a54df78751a4713a0a610805c0c13f\ - df8d5e9f8a0a85daec2d589d9565109821b2f8a8288d346487a5275605ff7862\ - a47183b598512494e22417a179581e709159d128f342d1ff1edda9cc995fc695\ - 88bd8d846de75bc6424b313832b8b27f379063693ee51386ea20bfc21fefd919\ - 0201030417021513560b35fe90d01a106b1e6ccba4cec953421d48cb -PublicKey: \ - 308201a43082011806072a8648ce3804013082010b02818127b35992d08edcc7\ - aaa6ca70365afa8ffacb4a9bef0ea348e27414c2100b81827fbf1abd3f14150b\ - b5d85ab13b2aca21304365f150511a68c90f4a4eac0bfef0c548e3076b30a249\ - 29c4482f42f2b03ce122b3a251e685a3fe3dbb539932bf8d2b117b1b08dbceb7\ - 8c84966270657164fe6f20c6d27dca270dd4417f843fdfb23302818113d9acc9\ - 68476e63d55365381b2d7d47fd65a54df78751a4713a0a610805c0c13fdf8d5e\ - 9f8a0a85daec2d589d9565109821b2f8a8288d346487a5275605ff7862a47183\ - b598512494e22417a179581e709159d128f342d1ff1edda9cc995fc69588bd8d\ - 846de75bc6424b313832b8b27f379063693ee51386ea20bfc21fefd919020103\ - 0381850002818117f468e3d38f1198556447bc16fb6c6ffe98b31f9042e59602\ - c71286db3e0780601e47372e6eb4a570f2059a7a87ee4471eaf94bcf23e34017\ - 5a377333d39dc64b7eaefcc065bef4a92d0d10acbba71082852c2014d9d3eb2f\ - 8583947c2cbf52865730d2b9511ed8a68367e4d89eca4589b836889cd424485c\ - 9305bc0386b16619 -Test: KeyPairValidAndConsistent -Plaintext: 4424 -Ciphertext: 0C570D0317363DB43DEB295D49A3BC937116F2ECAC9226415952CE634679272B7041A4B806164F12E87A0050AC2D60D393F845965CB3A56FF0CF28D31CFA0285015452C59949E3D96C5C6D1DBE38F6EE98E2C93357E6C036053DF920C7CA5E2EA1617AE44434A347FCE426C55295172ADDE9CAC3AEF2C6D6AB2C8F0FAB1B146FF1A10D5EC2191C99D6418519443EEE2A198BFD159BCC63 -Test: DecryptMatch -Plaintext: 5092C5D9FA398EE31AE27C97 -Ciphertext: 196476CA0E6622569F233780EE0C449C2CAAD3819B348D01B4DE5425EBCDEAEA739C6D9CCACE4DDF06520E83C94D237AFD46A4EFED635112CC78534E2FA6046ED6C06806EA8F4B9F3FC3F87DC55F63B9E14F9ABD82E9CC80A298DB281C9F690391F5B064880CF35C5A0BC7537DE9F65DEB2467FAB5CE8F41529A5B06BFA6B587ED661849BC7388277AE7F7E5EFA3F2526E503ECB106B718275BF32C4F83278CA30 -Test: DecryptMatch -Plaintext: 89BB350DC43CB3 -Ciphertext: 13844D63B45821E8704A9C1F6E9166B5EB7FD98DE5369E5DBB9DECE506EE467294282B5B174EF2F81B6766A3616AC5A974F06D9C47163C69668F4C1C78F8A6716A4EC28A6AE25F615A838B9C747EE857AA2AC92DEDC575AC568A78E8A86EF78D55EDB88707F7B6D558E8A760095BE8BCD066FC57396E67C9D8654245676DAE9FC4BC9D578496CA450B35E179410A5DB443C2026FFF0E5F7E54821E39 -Test: DecryptMatch -Plaintext: -Ciphertext: 040E084ED4A1C135C8867BAFF219A0092855E1E9FC96F38277E16B96986FDEABDC22F3B02CC53B655369DDE3356EA6FE49B77C8EAA49815CD5B1DFDC6E7D0AF6AA985483345BBA8A251F1EC7658DF708C8EED8AB6B953393C03BA2EEDB8B6391D921C9EAD2AA61DBE724B15C9C664EC4EFF83A535E46BF768FD519B043DBF46A36FA03921224281A826F6F43DEA6DF38749D600317 -Test: DecryptMatch -Plaintext: BB296D4FF04AE0171F1F24AE -Ciphertext: 0AA9A85958D9F1BB06E3DB48DACC842534915A7E42715057BD33523EE756F62AD973E37128BB8031358A1DC583F40598B74F079AD667C037D4BE89938233BFE1C167EFE764724F97F2EA42479FB455B1166AAB26A43440867ACE77472CCB13643D5BC9532F68C5368825BF225DF49E2D3BD023447A795AFFE927A796C70E5D6359537A9CE2B4B9323D7FE208540CC32447940ACD91F4718FC7A7CAD45A524B6DA6 -Test: DecryptMatch -Plaintext: 87A2C6B33856C6A096EE -Ciphertext: 12D17080AD0E7FD426E02B6A90736AB4B566F31E937B2D3E642D663D6ABFEB903FC9C4763AE492191E0C15B264CEF321DC8747C590F751A9BA2825D9250F72BA85EEB45B1F1D7B2BA972455DCE7DAE6CBD7B5BFBFB88FCEF52910F9B28D3DCD6BB5D479BBFC73896C3D1C44AB387989DE4D77855F6B8C7A8C12969D51DC6B10BA15C2B19E91A55BD5542853EC6F8F13260E8774C706958B1C9866114FADA1D -Test: DecryptMatch -Comment: 1031-bit DLIES key -PrivateKey: \ - 308201380201003082011806072a8648ce3804013082010b0281814ff13b3664\ - f5c527c36120159d9b9a82054f9ade6866b379e13d03e76cb63b25731132d5f7\ - ec6e95186ed83c793b5d63189dac30c6e6a655605f885fe73d2ae5433c80e660\ - c5d985ad6d12783082861829355c25cd7a7ff84b3033cb7fb530a7baa4000830\ - 2c1eb24b866cf467f570e782bceee66e15585f70b0633965c870530302818127\ - f89d9b327ae293e1b0900acecdcd4102a7cd6f343359bcf09e81f3b65b1d92b9\ - 88996afbf6374a8c376c1e3c9daeb18c4ed6186373532ab02fc42ff39e9572a1\ - 9e40733062ecc2d6b6893c1841430c149aae12e6bd3ffc259819e5bfda9853dd\ - 52000418160f5925c3367a33fab873c15e7773370aac2fb858319cb2e4382981\ - 020103041702150910a291c216ca5f944c5f3eaaa1535c3b8a1f0b15 -PublicKey: \ - 308201a43082011806072a8648ce3804013082010b0281814ff13b3664f5c527\ - c36120159d9b9a82054f9ade6866b379e13d03e76cb63b25731132d5f7ec6e95\ - 186ed83c793b5d63189dac30c6e6a655605f885fe73d2ae5433c80e660c5d985\ - ad6d12783082861829355c25cd7a7ff84b3033cb7fb530a7baa40008302c1eb2\ - 4b866cf467f570e782bceee66e15585f70b0633965c870530302818127f89d9b\ - 327ae293e1b0900acecdcd4102a7cd6f343359bcf09e81f3b65b1d92b988996a\ - fbf6374a8c376c1e3c9daeb18c4ed6186373532ab02fc42ff39e9572a19e4073\ - 3062ecc2d6b6893c1841430c149aae12e6bd3ffc259819e5bfda9853dd520004\ - 18160f5925c3367a33fab873c15e7773370aac2fb858319cb2e4382981020103\ - 038185000281812e9a62ec280cf5ee7d09e5e5675b67a4c325c7565a1129c079\ - 095d0f078e7b8a5b3c947c21c022f01c0b9267a45fdd9f267e63c7f674a02d39\ - 6fc59a960d7991d2e3552d01deb2784f26ec4c9355c0df0497271cb583d157db\ - 90b0634180578ac85005143dda75a33a127df96639e275cee8fe9c02db62d2ed\ - 879f3caae11d6e00 -Test: KeyPairValidAndConsistent -Plaintext: 1FBE21CDBCEBA28625584CB1EA0D9627A919A6CA -Ciphertext: 2CFC251CB2A397880EFD0077D9CEF817A6D69EB6278CD82998C5988DD18D6ED15FC8CAFD1611DE58BB46BA8A87013C7BBD4A8DCFC454F13DB282BBBD4E1594E6AF17AB6219E91D7354EB88515007B58BF0D8FF4BD4C387FF6E02BF81455803E6A936F25245863F1580F00ADFA4BDE052BEC72739B88042CF99480AB6F4489F9C8B9319828A000FDDC4D1A6E49868E3B39DBF7DCDADD9B882B755E330C762FCC023EBBCBD0330D28DB6 -Test: DecryptMatch -Plaintext: DCF33FA5BEDFDD93DA -Ciphertext: 14BA927F10262B134AC43F6787EAEC3546C17EFE3F6D54AD2A245A0EE732B749B7312521372F21716E1DE29AF8FB329C25ADEDE2DADE3A455235DAC6C1F347C2A052893DBA6511C3760384935D68C7808D23CB194E6A19F579782B22C3D8880736BECE89FD75E7E69022E9B2500E5A044105B832C9BFC5F18A807889B401E61A9888276B31FD299D604AEA85091578D41E5B36D66C4510F4B147C5E59615 -Test: DecryptMatch -Plaintext: 217B0E -Ciphertext: 37B50EFF3A3FDA419988CA44CCA3AE95F465A18C89CE2DF025F565DAF0F833E198DAEEB46517FBDE47AA3D5DC5039B873A31D0DEE1EBC63F3E97C0A63CC05A8F877FE70EB7F6198C088FF35C1C369616D3EACB013F295F764146A5AAA2D21CD36B9DA4490CF1B37D379ED7713B955C3B0581650B5C7F4F5B8F45B89B94DC364D3340414B491C29AAF2E197AD6F59B0DD687F2E60F8826169 -Test: DecryptMatch -Plaintext: 36DA002D110CD632A9969DC42409B478A3AD3B -Ciphertext: 37126F749ACDF2B6BF667DE9635CC0BBD61753B30931C847B612936C1AE122D6F0E409B4E9454852540C5FD8DD3DA8BA4026FBE8CC8449CA0071409DB47165907202DC078E5A8F6B0E9C8D3497A2D02F53DC3A47389C1B3778EDDEE980055BC4B7EBAC0B95C0CC4783A4B202CE127FA0D7B65B252492A1847FAA9D1ABE893376917BCD46DB4FFADC06C880AD848683B874F7CDFBF0E4BD87AFC39303C512C44EF58B510702C1129C -Test: DecryptMatch -Plaintext: FAFD -Ciphertext: 0F63F22B7817F2449388E0422C6122200D76BA8D4CEDE63DE950ED26768E6779BA0A238C8C3F2CC5C87C7926F1247A7067E27245423EEEFABCDB606976BA2FD9977320F903733FB57D02620682820B1AEE165604410157C5ECFAB7090EE83638A99E4CA36CA0879D3C14856A3417690A52F14F33CC50FE44503FC47F2D90C096C03F62A85D88891E9568911AF61DF916C3677DCF152FD3 -Test: DecryptMatch -Plaintext: 9E9145E890FEEADC706AE1 -Ciphertext: 0B60A14F132D21E47E2FA20633DE43694EC0394115DB297C1B68D1A7EE7722B6AF5D149A2EF5D0EA05761C0FABCF8C0862AF320E9D273AE743717F78A46F15B640C87F4AD0C25865EA3453B0FB59D997E41A31B6C1669F14639E2F70F7D4324B8729A26C8869D97B432740F7CE28A74EFFC82AD7EF172A02AC678C13235BA2C6EF79143D189838E1F101385BD7098AE3B5B78A80964D5C0A3D7DBA7FD7328BE8 -Test: DecryptMatch -Comment: 1032-bit DLIES key -PrivateKey: \ - 308201390201003082011906072a8648ce3804013082010c02818200b98458f5\ - ada1f23f4ae8a3a519c27fde91efd1f201e386aa6119749aaf6ed389079ae49c\ - c76317f81f14164673e8f0be00edd4db4792d446e7bf84b30200626b442af3f7\ - c9a6ee6fb0f95807e62fa5b2d171a4b326cd60c82b20d63ef00b408ea337f50f\ - a51f07549dc4f9a660842724566b94d6e2a58980d2d20281ce6c327643028181\ - 5cc22c7ad6d0f91fa57451d28ce13fef48f7e8f900f1c355308cba4d57b769c4\ - 83cd724e63b18bfc0f8a0b2339f4785f0076ea6da3c96a2373dfc25981003135\ - a21579fbe4d37737d87cac03f317d2d968b8d2599366b06415906b1f7805a047\ - 519bfa87d28f83aa4ee27cd3304213922b35ca6b7152c4c069690140e736193b\ - 210201030417021534999c0e7b17cc3c110cff71571e8d4708c3122a1a -PublicKey: \ - 308201a53082011906072a8648ce3804013082010c02818200b98458f5ada1f2\ - 3f4ae8a3a519c27fde91efd1f201e386aa6119749aaf6ed389079ae49cc76317\ - f81f14164673e8f0be00edd4db4792d446e7bf84b30200626b442af3f7c9a6ee\ - 6fb0f95807e62fa5b2d171a4b326cd60c82b20d63ef00b408ea337f50fa51f07\ - 549dc4f9a660842724566b94d6e2a58980d2d20281ce6c3276430281815cc22c\ - 7ad6d0f91fa57451d28ce13fef48f7e8f900f1c355308cba4d57b769c483cd72\ - 4e63b18bfc0f8a0b2339f4785f0076ea6da3c96a2373dfc25981003135a21579\ - fbe4d37737d87cac03f317d2d968b8d2599366b06415906b1f7805a047519bfa\ - 87d28f83aa4ee27cd3304213922b35ca6b7152c4c069690140e736193b210201\ - 03038185000281813c42dc88e1e15b9a737bfd64b96a7448983da5242a6cf43e\ - 1cc72e8886db723b681c291f772bfe33de5ba735404581c839341969a691c199\ - 229c2849c1c8c80396837c71d711ce34129d3006aef9d16cac504543c6e570bc\ - 3d730d5cd35d8a375edacf591b2837f9a705d63dd62754365d13c103961161dd\ - 984d89792985ad688f -Test: KeyPairValidAndConsistent -Plaintext: 23 -Ciphertext: 0BE692E3384A784AD01D80A65D22B48449AFC0281B36085B0D8FA03574B4BAD05F754D6FFB8E3F4B4BFE60FC7EA2BC1F11253505C753BEFB1D3BDA0084E6CC1FD82454A601F1C0ADB52B3FFC4895D36542FE0139465B490102C7B6A75C9273B737536DD122CC8C3EA0F32900C82C45B0FEE97D995AC5B4345A8899DD6888D1E814BB5A1141A86E636D31FA05689ABA512DE869D12BB4 -Test: DecryptMatch -Plaintext: 4F571384FD52A9041C8F3094 -Ciphertext: AB7942750662F0FA422F4628B558938545FBF7C749995B4D5B32BBF392292FD1B4EF02E5A2EEF6874BCA9F0D4CBCB92D684CDA821829850BD4CAE110E78E42909CF069B54B4BC7D742E113E57C85BCF54AA5CAE1005516BADA834A857315DD6C3DEF4AEBBBF6CB4AE217107E16E83F884B2933EE618F22C45B78092B2EFF7D5C33DB7D89FED4E134921DFD9DA999FB8AFBFD094D77BD887D2C86AACC401A621905 -Test: DecryptMatch -Plaintext: E421A467654B3B88C93C8E5384FE2B85D4E340 -Ciphertext: 7485B8E5360BC1383FCE1C586E126D5DE89FF1CA7CC8146C37A1E6582A564C4588984915CCE9635EA6ED434C80CAE138FBC1EB15D16B294AC1E59CDE544E4DFBF276D30A7F51461C2B7E7F076222DE6AC534DC47E015BA85062694FD78DC37E9460C10FDAF2C61FC7EE0669E99793A657543B881B50B0D3916E395A959EF55B02DB8E7B4C5B5B653AE2D11CCE639342C8C77C667625116D9E6B6C6AE822CDDF2AA503EC3FAD53D80 -Test: DecryptMatch -Plaintext: 3D6C941B1F03E5C9A4 -Ciphertext: 684AA8D2AD35D2775BC30794A078CFC931096A37D472FE511F72B03B33E87AB1E7B958C3447AF6285AC379379E0D1F1BEC535E4032E186573742A75C1B42BDC52F679DCA13B2B9E67CC73461084DE1777FAAED93C7C1E4A6B19473EDF6A57CD88C076574A356748D501A05AF66A136E908993A0A70538FEB03109C62A41540EB4E166596887B4860E3AB0BF9C1AFD02C67D4BFF28BAECD31D1CEB207A245 -Test: DecryptMatch -Plaintext: -Ciphertext: 111C252A9E64FB777F09AF6AEF9C4210B9644C3A66D5528C631D5348E30B146A6225783DE1FB796DBAB3A901E37818B5AE49BF1F8CC0A6C8909D2DB06D651CB08009A25E13A89653DBBA5959674E37BD72039D4E7BFFB3A2395DF8C36164C3FA71334DBFF2FACA090F1C349BF68443838A0D893B9B498D3B6CC86646F935D5ADED81967A387506688B6478492129534F3A651C9985 -Test: DecryptMatch -Plaintext: DE5F0B92C45A0C1530 -Ciphertext: AE6BAEF52B43EE88AEA7796D667D044887407ED07E7618358243A0108514FE9793EB28EB42B4BA2F28F6687FE7973FB8DBF825541010F1BC1FC7350CBEC0B055C0C71FF2C4D2634582C966C1CFD3449AF8AC956BEC3EE797F7E81E589450EA13C1A8C99116E05E49F4BB87C9B95EFDBEB35B21C36711CEC8A1ECF3E4F194251563F88C056749B835FC19A7CD560FEC785207DD14D43C6104D83BB05F1DA1 -Test: DecryptMatch -Comment: 1536-bit DLIES key -PrivateKey: \ - 308201bb0201003082019706072a8648ce3804013082018a0281c100f9566c8d\ - 687a5ead7c780617d3ed37b4afc46582e9fc0d75ae217fb506f5c2024c2a0e6d\ - 7e042544235b4de63047a33940d772721e895f9d4e92790bef0d3668ec7f6cad\ - e7f9b18049b33efa773c83e97b35ef7ebf18934b48dd4700a48c1f76ffc20684\ - 521bad52834086ccdf1e3d5c9128fef52f6a9444d8e9944d49e5ab411f46b63b\ - 290b7fdc8f48fab24c2059510bb7247e0930d5043802522d67f2b69ac18b82bd\ - 0229e53bf6769fe83c469188d600e6afa6686bd9725afb9ce39bbd9f0281c07c\ - ab3646b43d2f56be3c030be9f69bda57e232c174fe06bad710bfda837ae10126\ - 150736bf0212a211ada6f31823d19ca06bb9390f44afcea7493c85f7869b3476\ - 3fb656f3fcd8c024d99f7d3b9e41f4bd9af7bf5f8c49a5a46ea38052460fbb7f\ - e10342290dd6a941a043666f8f1eae48947f7a97b54a226c74ca26a4f2d5a08f\ - a35b1d9485bfee47a47d5926102ca885db923f04986a821c012916b3f95b4d60\ - c5c15e8114f29dfb3b4ff41e2348c46b007357d33435ecb92d7dce71cddecf02\ - 0102041b02191d78b208d09b23e859be7e79ca76e612d8e5ac75a5ca02c506 -PublicKey: \ - 308202623082019706072a8648ce3804013082018a0281c100f9566c8d687a5e\ - ad7c780617d3ed37b4afc46582e9fc0d75ae217fb506f5c2024c2a0e6d7e0425\ - 44235b4de63047a33940d772721e895f9d4e92790bef0d3668ec7f6cade7f9b1\ - 8049b33efa773c83e97b35ef7ebf18934b48dd4700a48c1f76ffc20684521bad\ - 52834086ccdf1e3d5c9128fef52f6a9444d8e9944d49e5ab411f46b63b290b7f\ - dc8f48fab24c2059510bb7247e0930d5043802522d67f2b69ac18b82bd0229e5\ - 3bf6769fe83c469188d600e6afa6686bd9725afb9ce39bbd9f0281c07cab3646\ - b43d2f56be3c030be9f69bda57e232c174fe06bad710bfda837ae10126150736\ - bf0212a211ada6f31823d19ca06bb9390f44afcea7493c85f7869b34763fb656\ - f3fcd8c024d99f7d3b9e41f4bd9af7bf5f8c49a5a46ea38052460fbb7fe10342\ - 290dd6a941a043666f8f1eae48947f7a97b54a226c74ca26a4f2d5a08fa35b1d\ - 9485bfee47a47d5926102ca885db923f04986a821c012916b3f95b4d60c5c15e\ - 8114f29dfb3b4ff41e2348c46b007357d33435ecb92d7dce71cddecf02010203\ - 81c4000281c07a5b4ddf442b2cd7fd925be84f2ef4c4032d61c5a55c5949b30a\ - 765cd4d5d4566af37ffa7f814f51bdd71c3e5575c6fd0203f14d3ded4e14baa8\ - 2747a6437d35ebc81e2035bfb0e04087fb5fe449163377d47b045b680b394962\ - 20b3138e85f6d24e06f955ec7a1b785ce34c2926cda441bfc86ba2f44a489a41\ - ee1740ab5ec3daf6d2c598e1d143654c05ce61792b47ac92c8d6ba0711419e41\ - 221743b768eeec2601f66d277fba154a62dc996537a0caccfa313cc9fde0194c\ - 05493aab1f07 -Test: KeyPairValidAndConsistent -Plaintext: 9302C420D137C310 -Ciphertext: EEF64A81C754B2EF543A19549AC0FF3F44E4B548284ABAA1E5F1EB704B0D246749D7F1CEF7B20A5226384DBE8FB596101591BE2B53E9909EE3723CB70A385FC2DAF6CE15629EBA21E7F26223B0A2428D8931CBB4F1B281E318A540F38A809C8BAD92D10FDD63305DBBE972E6CB973FC4F2FDF0BB9CC37FC42C7AD76E8DE3FA91E5E79B09796652BFCD62A28A59D9A97759032A0A78E0E1B081DF212A15AA44E35DE9E291EDA499DDB631486C029D56052246C9E37FF24EE9E86465B3B55BC4BAD77B9AC873B6F36EA65892B202E320756540009C81B9C6747BDAF40E -Test: DecryptMatch -Plaintext: 9FD4F26B7317BBD1B235 -Ciphertext: 514DB5C63AD9707197B4F0B2A30CDA18369B963E62F7ABBA1E030E08D3DE4E6C17D4BD7CB8097C2E641FBB0AED6A9FE7FBEAAC1C6B85BB3570D0E86FF6105B9F8C9B562A4EFE4AE3AECA26978C514129006D22C108B1C8A0FA55864EED3D3F81643AAFE36DF1CBC3B4E1B1AD6D5E0612214938A55114589B97286A7EE5B04E39254696DA91453027F07346984423FE2784DEA9375C236E6640504B5BCAC32062836E5BE1695CE73285CD77CE9717FA38E080C28C2959D9E32A589C04ACE5E52970ED49BE34703AD6B9F024DDA176C631EF5EE76833B427E233A5DAEC4328 -Test: DecryptMatch -Plaintext: 337D8BDD32 -Ciphertext: A4EFBF2151DAC683F0C51D60A647151A1EA0C0DAA8CF3497D7116439E6AEEC62A36D06F89AB2F1886FB9F62403E3DA8D6F67F66DA2436EE20FFBADD698DF87EF40470749C0BE0414A7AE4D2755459F8A17F6C7D8920236400313D7846532C391A0A4D99C26C556772E2D3C74E0119C4CEC7EF224488BFEBA017A910E5FD167B4486E436F7481DC5A46F3FF0536193C75A857DC53C5242C11AB911BD21926462C5060BB89F71D99FDEAD3D16B1E21E0D0791B59ED0F49871F744B13F23EF5028C238B895532F90B0ABE9912644EC079604939A0CF519BA9D185 -Test: DecryptMatch -Plaintext: 25549A5AE844ABEAA694E3F6 -Ciphertext: E2B30DD7781DB7EE7B2EE3FEB77F7360A6069396D8BF1DFD85D5429DA5A156677679085D612D0FCCA0979C97E924E77C43D3702940DBB556A5BB6EA33D650E078B1CDF8E5F76DA6591D0AFF4389A3A982A9AC581BFF393B35D36894E407AA56B493C2F7C4CBB75AEC72394AC4F8A99089702F3AEDB2FC7486F5CD01691C3C8F8FF3E951CEC70A4E172B763124BE1D9F96DBBFBA8FA0EBD1A71067A20F68DA6AAAE849880DD7F88901DF051715E240BF0F5B49EEFE35B9B0ED2B69757111080DCE2E2A933CFBE8FB9E6E9A2C2C75E0A4228D06689796AB919EF80405CBF648137 -Test: DecryptMatch -Plaintext: 5E61EB24085019F4A76893517C0A13 -Ciphertext: B13E45F9288FD2C5C0FEE230D1A09DE376ADADB5A4330F33BEC04C6F14C4A1CF3789B976F402F11611AB8345B2EB1069CFEE1E2F482A02A0ED9A3B9D94EB78C7BD7222ECD48A598E34D1F0B6205331CB20E0B2C6C146FB29CC11BAD5CA06BCA3EE39DD536FF330663A817ADECCC284B92F6AE3EB75B00316992BEF8A955EBB4DDE2CEF504E9298AC243C00FDB64B6AE96FD7B2135E6BCEFA7CBFEE135A650AA3D8CD095D1C9156232DCFE1904BC4CCE58B455CEFDDEC1D201B07ED4F999D6281AE21C2008525DB24BEA2D9FDAC1BFEADC3E6E6B1181F1A55A75976C565BC28F177CF02 -Test: DecryptMatch -Plaintext: 87 -Ciphertext: 174E5CFE167D4F6FB9A8FCC0FBEFC12864745900F5A18EA92282C8B6689EF53BBB87B30FC21DB101D93E9FFCED05538EDAB59F9FA07FB176407651DD0C4CD8269B1DBB70F24C8177EC6E16294CF5E87A3070A077B1CE84B612C3E3B1D4FD60D732C4D2CAEF5AC442A358AD0F323E60F58FC8B29894F3EAD3AE0DB8FD08BEBCCD4220CEE6B7C43A5E769D1F890A6B6505EE7FCDC7E399FE5321C2792D7AE094D13EC493CC0911B3EDBA6DAA037E2EA0CD3642784FFF2CB1BE04E5B12AC9D2871F016D8BCCE6DF25C1C04D912CBE707FD4DB0F9E89C4 -Test: DecryptMatch -Comment: 2048-bit DLIES key -PrivateKey: \ - 308202400201003082021906072a8648ce3804013082020c028201010096411b\ - e93e733637e91b1d74f808f4c9c528293e3123ac1d3d2f94c462ff38d0cd2fde\ - c0eb03bc5e54b6df41e9bbe9127a1b3a7f47cfb513340664829ffae26f832b48\ - e2d660d10e4debc1bfb412f331ab7b2f88c0d31fb587ed5c5256e0ebf7da698a\ - fd3cfa0443af91bab8c539376fcbad72bfa6985b6e64250e6b546b07a4575b08\ - 449d383b5650083c637d2452e7d1b9227adfd328ce473bb4374fa31e0ad52e56\ - 7feff6a9c4842d24d069e7babb35313ad63ca5d33d572bb309689a571e9ffe25\ - 38816bd7bde7bb11c10752e6a842751f594f50cf4b8111f387134e30c6c03ba6\ - 40be7cd5b6574c0d0b571a98fcdc292070595dcf6e8d034cc0ef92e8ef028201\ - 004b208df49f399b1bf48d8eba7c047a64e294149f1891d60e9e97ca62317f9c\ - 686697ef607581de2f2a5b6fa0f4ddf4893d0d9d3fa3e7da899a0332414ffd71\ - 37c195a4716b30688726f5e0dfda097998d5bd97c460698fdac3f6ae292b7075\ - fbed34c57e9e7d0221d7c8dd5c629c9bb7e5d6b95fd34c2db732128735aa3583\ - d22bad84224e9c1dab28041e31be922973e8dc913d6fe99467239dda1ba7d18f\ - 056a972b3ff7fb54e24216926834f3dd5d9a989d6b1e52e99eab95d984b44d2b\ - 8f4fff129c40b5ebdef3dd88e083a97354213a8faca7a867a5c088f9c389a718\ - 63601dd3205f3e6adb2ba60685ab8d4c7e6e1490382caee7b74681a66077c974\ - 77020102041e021c614682228a4bea799d01008a4bca099e7cf7711d7914a81c\ - 39d2407f -PublicKey: \ - 308203263082021906072a8648ce3804013082020c028201010096411be93e73\ - 3637e91b1d74f808f4c9c528293e3123ac1d3d2f94c462ff38d0cd2fdec0eb03\ - bc5e54b6df41e9bbe9127a1b3a7f47cfb513340664829ffae26f832b48e2d660\ - d10e4debc1bfb412f331ab7b2f88c0d31fb587ed5c5256e0ebf7da698afd3cfa\ - 0443af91bab8c539376fcbad72bfa6985b6e64250e6b546b07a4575b08449d38\ - 3b5650083c637d2452e7d1b9227adfd328ce473bb4374fa31e0ad52e567feff6\ - a9c4842d24d069e7babb35313ad63ca5d33d572bb309689a571e9ffe2538816b\ - d7bde7bb11c10752e6a842751f594f50cf4b8111f387134e30c6c03ba640be7c\ - d5b6574c0d0b571a98fcdc292070595dcf6e8d034cc0ef92e8ef028201004b20\ - 8df49f399b1bf48d8eba7c047a64e294149f1891d60e9e97ca62317f9c686697\ - ef607581de2f2a5b6fa0f4ddf4893d0d9d3fa3e7da899a0332414ffd7137c195\ - a4716b30688726f5e0dfda097998d5bd97c460698fdac3f6ae292b7075fbed34\ - c57e9e7d0221d7c8dd5c629c9bb7e5d6b95fd34c2db732128735aa3583d22bad\ - 84224e9c1dab28041e31be922973e8dc913d6fe99467239dda1ba7d18f056a97\ - 2b3ff7fb54e24216926834f3dd5d9a989d6b1e52e99eab95d984b44d2b8f4fff\ - 129c40b5ebdef3dd88e083a97354213a8faca7a867a5c088f9c389a71863601d\ - d3205f3e6adb2ba60685ab8d4c7e6e1490382caee7b74681a66077c974770201\ - 020382010500028201001eb30132e415358b7d3f726b93e2eeb083fe7add7abb\ - 6ca352c9e09b365e5768ce032ee52d59f1c65311045c490c42c36ae08cd0264a\ - 26199aeec8c3a8882a363397b4d7e0b6c4abc407f27847be0e8477993069a1a3\ - a3fe68093e09ce55bbedf97c91e741ad2eceb7a0f4be6ff87f68deb03c5280d4\ - 8fdf4900485bf5ca20257b176f58fcee1f0451b3716862488b0642bcd76654ec\ - 4874512538976967a545cdc208a0050f26e541ca70343f653222e6df7aaa07cb\ - cf354a5ab910eb8447382d7f512c440982ab37a402c87d2888eecb35c636ba6c\ - 84a5cce917f234fc7f8d9167167e30f2840407e13751f1944f6aceae3f5a7025\ - 36723c1d88c8c04981e4 -Test: KeyPairValidAndConsistent -Plaintext: 5EE1 -Ciphertext: 73279829369404A1B68D5E86FF334259936133CB04C9186CFF733972054918C3285EE907C2863DEE872252BF03EC9FB088B8DCE6D69D78C6BCD6B3FF87E683C6CF3CA05FA6AF0C068D964BE01030A3AB4E19575811D141A59CFBC9D3558E48CB771D88CB1E0E6C7ABED041077D24005E337AFCFE8531569FE56E2CE97C40693C071409888AE46DAC8BD739AE0E1C392586917FE07A66F7D3AAF0DDC398117B594481D0D5CD19C8708DAED6338EAA552564C31F9548FFC7E5C641FDA95B252EF637C6CF708979948A3E6B4F37A9ADCD60BDD841F3B0945CFF55E2F13468EC71C550CC2AD48E7E1FB444F132AADB1EF2A7C5A22450D0E0CFE9E37D999B4794B5A594A4EB7ED406DB24ED541E575B9F2756545DDD34F6DB -Test: DecryptMatch -Plaintext: 0252EE2E1C603017 -Ciphertext: 0E742D794904D05C0F0B6F60E9655337F8C110F289C6E4A0D6FBA6A2A8EB0FBB566A7F9B9862175C7A00A8205E8C8012366023FD8DDB6EB713DEF86917233DC5D16C2822707230169C183FD3A714806220D7DBA735C4F747A23E4131CE12C5572BD5E659F967A8B7DAD0EB6138D1BB569C6F04EAD79F9A6301609697F73F6FD8CCE934FAC6FC138B4C552E211FB1CC242805C035815F462D0291537DE10632141ED0A7C22439C7270AF0A6244C073CE9E2654FED918C86697988B0B341C5EAD2CD6DE75EAFDB1DFFCC5FE465E8D8C9A34D5B7F0E9DDE62204FD12EE2F99435DD58F3254268F8E6CFFADEA9205DDFCC943004887C405859866A0A40456A6C50B57FCED319AE0EC92B9069F765013436FC9A0253481CBE12B707A2B20D -Test: DecryptMatch -Plaintext: 01AE -Ciphertext: 6AB2E26D99942CEEE4844632355BB3B7713DF000DA11099D4E1BF9EDD1781A9396032E9D96BA0DF21B309A9CABCE9AE3D022C33A931183DEC5A3721EA5CEB39C18935A43E3B0BC153E4469AEB604D031A0084BE5927478AF8EA652D0A4AF455BDC57EDF26E2C6F9A01C91F29984C11D3C60313A53D8AC65D9FA504742868AD3D313506EB4FDD0E9799B111F3041F4C0547BBB06BF7DB20D18B427BCA1BA5099821A5F0997EF08C319B851F0C88B4814CAC7BAA4290B3182738C37B6ABFC2C4770A633F70E6FA4FA53AB286384FFC2AF9B64DECBE12C8EEB97862F76296D13D889E864418056420DCCD0DF9B76FB32FA6BDEE149585F427F133972DB7281D91D6E78B6BC46151901179D186CAAC784D6271023FD6E84B -Test: DecryptMatch -Plaintext: D52A1E0E3253FE281A9471 -Ciphertext: 63F60818E399024073EAF02A7A419229EA4E2FA4126C910AE7D31DE7EB6C9502752F5B7241F2A133E9D71C1A75E23A6F5DBE36C1B661935B0F20123BF434153B1F81BBDE278611C9FAF9F56BE8C78116823AC5B5F355B88A82AD6A73D2B63BECFC7D3B39DB2A6B393E23826235AB76653EDF65DD7A94BD27E221E9D511041340FE83A27F7B26CCF3FA40B2BD786BB9D67D2BCED415F2F76D116E8F3EDC953B8A327D2846F247D91626F643F8DB800F5E1DF0CDAE2369AA8969A938E0BB5A44F0A9C0BBC7D15A34DAF4713531A7B6B59CCCA2282952B16A7E1A1D1CD47D8B2AC6A88BC6A85E692FED89BB3D1F16AC2A922836152059433A29F786F2386A74DD6F555CC8D06C890A4A93E9FE88CEB078333A631E9E3EED0610F0A17F2A4F8DAF -Test: DecryptMatch -Plaintext: 53 -Ciphertext: 7F820C0C9A5709C6026E58446623B5D4B323BACE54724F456684526BD1966A360944227D04824B3C9BAF19A602EBAD25B8047FB6BF9997EBDE6B854140C032481F1479E4B994FC5A2DE8128375099A7A0024AE1CB985D73BB2B806B20E0751EA154BE2A70ECBCA49335BA57694DF1E0EA4566304B8DF4BBFE5AA41D0B767AE1679BDDE70F95E1C0C7E06F4A635F987E2858407BCA2133C3EC5620D58F1AB7FE1426B615959009A4706797FE4060E1C690DA373E48D6BA684F69E981DEE5DB9A58C504DED4D4CA6CD9B776DA03E55DEBA97E541A300465FFC68C5417A10ACED061023ADE00FEED4099180948F26F10D2F9470978469F67AE1092100C16D8FC4104DD1E711CF67D5842DE4102869E96E817F9C9FF520 -Test: DecryptMatch -Plaintext: CEA6026338 -Ciphertext: 13D877F0F00D01125447982639AC82AACF30FA0573001DD809C72D0F811138088C6D6D0569E63AB001CEB0339BFB90F7B71F339CA2F75859920370C622C0C4930B79B99DAC0560C763A1162AB46F58D1409E25301AE6D70DD4FA64984FE894DAD2B6401F8864580132664DDC2A57D1AF8AAE43C2759780C8587475F21275D61765251DA8FE91921703DC8DD279DFF4260D8AFE69257BB43EC609DA30DC33526D66E46365F399AA04F34FA7BA6469CA964AD6F2299233424E7342F1BF493C0BBB31FA1C713543D758219AB0F73B9C24F4699415F96C32E2A700669FCAE7EA6921F96288723ECEDF9677EF35702C8C0B71AC27A57624A7667580A2FBFF72818B2BCBA3589DCB686486FDDB50E29E75EBC8AD3DEDC8B741AF80F7 -Test: DecryptMatch diff --git a/embeddedcryptopp/TestVectors/dsa.txt b/embeddedcryptopp/TestVectors/dsa.txt deleted file mode 100644 index 8f31ee9..0000000 --- a/embeddedcryptopp/TestVectors/dsa.txt +++ /dev/null @@ -1,337 +0,0 @@ -AlgorithmType: Signature -Name: DSA(1363) -Source: sent by CygnaCom during Crypto++ 5.0 FIPS 140-2 evaluation -KeyFormat: Component -Modulus: 8fbb9edf2fd2834b1a9fe97c25999fbc381ae165d932aa521592c2cdcb4318bfb99a2408f118ea874b73704e2cc557fc89a01ecfb5bc412951e86613b0b2fad2389e81ef42f79705fcdc87a9b9dcb1afb44c37d971aeffc1c859be367457ea19d71f22bcaa29752f15242f59b295125e9e01ab582887fa869e4b0f4a308167a7 -SubgroupOrder: cd6c675f1d22c771e7f59020ca0e94078950df9b -SubgroupGenerator: 7b473ffda9ed6e10f85177ac05f43ec666dc6d42310151053ae83369de9f9b331232cbc83bef31166e19b111e46e57703fc6666ac9a571ff053e18f3c2fbc4c2f32521750a941981a55379a2fe13bc78c6a3787f44dea397af63a7ce432704657feb57295ab9711ac7070ca5b7344bcaaedfd8bbddecd8de9c67e7cffa2fa20d -PublicElement: 64f31bc4d5b42622b41326361fb0d67f9feb364b34be67f6b2e4dc1f928fc70e6fe42cd9cd6ce3dc40113e7b4742d4af6fbe04d962adc5238d4d95b7bb67f0ec6592e966517d0a34137a45dc82ebe282c904750e1aa31b62c919b250d4d8ef922b0b0574cb2ccf1b451d7facd075e77fa532626602b32fee6fb334e1c2911388 -Test: PublicKeyValid -Message: 699c4211bcba049ac8d73c37fc3d02241f70b8ccbd6a1225d813664bcd043660847dfba3dca434cf5600afb60036171ea402bfdc3279ae2f6b7deb5fd0810a96ca7ff7ff1a36021d84a92b6db7d4b03f80b1d5d2306cf3af4be2c448725fedd09399cd5d4fe8853cabc84895fb91e4400c7591e691bafa5cd0398a3c8d18f8c5 -Signature: c0aa11b2571acf6fb78dd85148d97ae04877ea1a05d27ab73783ba4efa3a4b7f110cc44c7ba2c842 -Test: Verify -Message: f5373216e55156d66524e39dd8a345cc519edd8cee2b7cdb755222d42ef8f843000e8b69cffa4b0c154543c3bf871b804a904b5e1ed8a1ad2a29f63bc28b2ce5b5706c5fb2219e40dd682951ad7fed1709397d9ea36fa18894ad0c57391e5af74db54d8f479d4989f6e40de05b63b4a9c7f0ebe535c87485ea36dcbf4b897890 -Signature: 33e28ca5be57567a880c52451ec72f27d25b6e26c38216900ef17f0c307fd7614b399ff5febfd7e6 -Test: Verify -Message: 92fe48a60045104207970b674f800f67cabbba0dbc8d1d120b64a4ddc9b149800003f9efbd6446825ff84fae21d4ed00e61d1f5b4562b872d53b4788ba2247677091889fd75ddd017f52075b3610e275d025ce4c366c608eb2a64a567a5688287ae2cd3066e72db701dc0ce6a7eb46bf210c9f59aa646e5c3ddd86bc210665ba -Signature: 95616a85b6d9ff3c9af7264cbbf8b9cdb71404eec47fa7c91291fb93ddd8b0327df74cfae6698e0d -Test: Verify -Message: 18b8baa09b84cf8ec77a1d34d68b0971fa71016ad5b71838350ce9d114c8aa34d0bf8fd9a747615876845f58b2fb55bba757fb08f176901838b7b7042f87924fcf2a1c50d1c7cce36ab768514b0f277cd86b0a4fa7fe7c653cd729f803751b0d8f8f1cde121d47871caaf0f598deb70c0447e718f0671576ba04f68488ab80c5 -Signature: 23c6fde5fd9a2478d99c3abaa61363d90b2c161e847be181af07276e376ce4f76db56dfc3a1f2425 -Test: Verify -Message: 598660449d62f60b1e0581b0c493803d3ba5cb49a5c5d5917f2a41d6d1b6a8f69a2ea94e7bb8334fa29a0f5ffa32b1f291313fe9491ce32ac3044e8188848db77afd10f17a0ef84b5b56a1b5076d700df021de7ebaeec51827c0eab042ecccfacf6bace5f35add3820b04e6a443e55c632ecbec05032149182d52e1a57e4fef8 -Signature: 2c07790afcaf89768f1d1492345510d937e65bca5621811e1b705651a861be1f88f52090036cc1ce -Test: Verify -Message: e37395964c3c1f7b37c99c2f56070cf9672de2f7cf63bc6778ae6532e81f09baa23cb7e5c2af1c6ad32e7e5bf4aaf7f42cbbf4a20a4bed578182660d02f22799db04b8b2cfa31f41f727ddebd88326ddc6b361d77860e07cedd6e1d87e28c53244a28f14ad6fa099598cb1f73bec114ceded21ad53fa0d6d7482ccaa951a5b1e -Signature: 58697e6dad83ddfe43817e5534535ecd78a985d3928e271212165dec4e76c8025d531ee84ba8caf3 -Test: Verify -Message: 24976d350993351696b33cf2db5440303d5a722cc2d25eeb9ccf1e20f57ec060fa8bf4a22ab9fafbe0bdcb971f5b86fb9ec41e79142e42f4c6b58dd54e71ef4eadd95cce9458b3c5ef2df19ab38896e9e9e35801fb9e079e3fdec0e3c1a7559b5638fdb1dea738edd9bd06f12d144873366f76bc0f5a83621f030d42e857cac0 -Signature: 7488f2ca5fe2bec2c7a83e73407411c9e89bf8cd594d4a03a736423ebd913c2b98a21e445bdf70f6 -Test: NotVerify -Message: 430cde2feba0256295b6366211252174a29c9bd2b8e6db8fe97fb9ce35580a247be8364a37741b077e9f275d3b34b1f2ab3397c2171b1e04d177065972aced3c5201e6a648ef5900a3ab1e4f69f2d59bcf1488a0f84485b8f21e7508ef7ac1eac070269b97ac9726fef3539012f647450557a6c2d4fac685448d3e32235a3e06 -Signature: 7500d2fe4b2943b4da93490d3bac5c344bb18eb550975ead0e461ec33485e11714b4ceab478644b0 -Test: Verify -Message: 81bd412f4f9c8f8b7885d9fec9b013be8246d4284121dc9c2fbfe59a6987af1db141463855cf96ef6031325800b961f2378a6a46c65722bc565ab3c0e993ae15814354790fa8217a9efa9a98c0a6599c39c95638ebf077e0010f5be860bf63df4abc032a559e47e58bd8a9f6e3ee1173e0fb2d378762f4bf87d4764aa483e631 -Signature: 37cb9d9adb92a7e74365f9e4c4857a88a6fabd200d955dc76333b0ea9c1b2f05fee9117c79b10d09 -Test: Verify -Message: 84652beae6fec221ab800bf6303f17a47a84278a1274a2b11f40569bc58ff34ebe28c5a138e4b1c7eed4731989ae1728397db5038f8970c59e84b16353f8a1b411ede5c290de9e50f7de9fab3807f1b6ad238530f09e384900ac0c6591b6a530b30b03e2a8c47ed4fff80744f5219e650cce0eaaed8bf0547b0edf3a39a3f8d9 -Signature: 194a79f399087d977a29a3eab308670b7b133acf4e8b43068639e0e5e37d7ed305e32b85e30a0a22 -Test: Verify -Message: 9cdf6e966c37794c7b3dd6234e76d715099128caff3d03917a4a96a2c703b19386cab41830f5b8ffe9e9fd6b88759450e4714d2f6298e413bca267cc13a5ea6c38ae6fff379b0f8e253b6e562ca95f45d4e6d3b694b6076e99bdeed7d5d9dc7b4bc275c49ae0d5f2c86c015d51cb8eed702790d7ad50c59aa8d203392456dfba -Signature: 7b427233d9e49dbfd8ff2a7814dd99cbd4533d67155696b215d593d5ac3989c8927850601c0d453d -Test: Verify -Message: df577c9f2370b362f86a928e40106d7b0a511d5d8ec619776b82d57e1f195b4bc7f328c619d2490e9fa2b6ed3681ef7cc60fd51343f7cb74e5be0d37a3cb5078f6b89bc0ccd86532ca09f0f7c6bbe5eb85413088b1571e131ef5b6063e5355bfe23d8d6733993f24f036f682ead7871fbd7fe796d0ff4dae90be88c4e8c9a276 -Signature: 39a7efc692685eed0c3cea8838c026b39367c6f446a16258906787af9447329ab99e821eba53cb89 -Test: Verify -Message: 91042eb63d47c10f678bec836f98630e13e707b29c98b28d47b1443cf699e97018d4aecfd500440e7f11134c35c982b1d97b86473500691869fadc89974840f7d2ca319045565573a0fb630bc87576a8bff09460d1027a2500e3ab28b2eeb86d995dd1afe3418c76a4c0f5778094d72c9dc04ab4c8947eede6e3c6cf9d83e80c -Signature: a813d89e3de90f1ce1b77a7d6c629e8f83296aefb8bfe1194f914797d08b53fb59cb9186935dc10e -Test: Verify -Message: e644b9a45009da8248611de174b5613dfb4aafc0a772740c38f1ff480bb23e69ecabb5c2380dbfcf37b1093eb8bf4c3feea04a0d8b270cbd1bfb5a46a2487bd279a62e446649e80afb6b502431f6f97544765f4ad13f24282edb8bdb0ab635bc460d1c421314cdcc4c66eaad16b3e078b6a4e48eb21234e62b688c1d7a56e6be -Signature: 4e4fbbd84fc44f0ecd6c163fa292cd96051ca51764fb5626f8ecbd8470faf6ae5d79c731d9a3497e -Test: NotVerify -Message: d30ac577ac767ce6eee34ccfe09f0278f2faf8d28f657cb424ca7f53712b7f040f7eb63643c784ab02771af64405693a8eca4a21ba22ee1b09c189d96c533a0910583e53283e5693ffc076593d7eaf9e79de5ec9002296e2e4cacc15492cc26beb52b5c4f414ca17fd77b6ee6245ad1ccbec8ec2f89c4c81cc9ca0019deeeda3 -Signature: 4ee3704d4bff39aff0efded0930cf28ff7641f089280f1d0e38a186075e91d73a5b1e7d028340fe5 -Test: Verify -Message: 82bb8073af3e53b8ae158f342c4cae3c039dc830703bf0e893dacf5d280284948596bbd0d3a00cf8915f96464693dc328507df9e27607d43c426095b74102c90c494fc24fbaf5a628ef29146e1ce2c684020182f1e00fb338cc6d4f2fd5ed3b739ce7bc89e05f6cf9fe6b88b769558b72c01ab3accb22291e3d5667a3c8532e3 -Signature: 0b0b366b23090265e75752fdcde1a7d76113653246e0da762e25012cceb13859313e469f4dc31680 -Test: Verify -Message: 12da3a70153655976cba8144f67dc21719410fd136aa69ab4cc11df9eaa955005ba0e5140d3955f643d82a6cfc6e7a222376afc1f8309b4dbe1dbdc4a6bcd2f5fc839f9e9020fec967f12768a3c14130b0c529b3b0d682c129f1fd00eeeceac94b7a0046746269ca30fc1171c2ed30f9182416df371436bde63376e49ab2b635 -Signature: b43f325f82eb07dd2cb3a03a022e8c89216e820da743c216ec6eec5bf445f12b2d326d52e38b90ab -Test: Verify -Message: 45a2799fb193f3adbef66b8035318c5f7eb3610dfc64dbd1a84b87c0f082884ed257db1435c4cce38711b30b9dc8f4e5c7d936a7330ee36984b2e172b37d8ec925c401f80ede802305d93d4ae85e56dbf3e20c7b1c0f4216b17238253465893f773f63e3f4bb07846fa781d6cfcea858382658226e3eeff166e306702e1271c9 -Signature: 238f01011e1b3e7d027af353e06e2138f5a40ffd3d7a78d55c95ea3b94ad82b8ed58c308f7db5ef3 -Test: Verify -Message: 6cff32791fa0d15947fdedf67508fee334d1739512e15ce3ecdb5ac17f56c43e2cf51bbb0bc8b06d34e894164a4dc0ff48f3863a902d3716314916e278667de7bb914ea061279d3c36679b57ee56c6f4f7d84fbe830bcb80d6e71ee2cd15a565b00ca3a13972eebfe4b2da3279d966bad8b7a69a0533701873ed4a36951b94b0 -Signature: c9194d5ca3dbb424faae51f66377836a93bc55ab1d481e5eb9663c7033329d82c13af868f4a24efd -Test: Verify -Message: 37a363f2ebaa01fd1ed7902a4804c8fa46845b63d82b947e59a23073c0e97da2d72db113bbcc8d2095a6336197a744d83a923d5eb610134dc1f80d6f8de1e327fce615de26b88db10dea78599f79615aed9b906fabcaa236e8106a180e94077b1c65462c23863a07003b19e858935ad7d9360d6fae717a8f4480fd443c1a21f7 -Signature: 9ca210249d306006ecffd384f87c4dfcb1d466e005d877c2508475bf0074c4c6fffad6e123bd5dab -Test: Verify -Message: d3b14dfc79ab30cae8e40dcda6bafd6434741e6ab1b9e0d2cd4e8d80f10f176aac3126ef61b662772f31fe4d21bc85b99737e961f5c2c9e28a7d02aac27f7a19901529d8163c687997617e509f576890719ae9aab1c3d3e3524b9434c384036655d56d6ef035db06f7eaa68e78843e22981437fc3eb2950bff2e59d54a154b8a -Signature: 30cffe077d2330f111eaff346634237473feb83cc522a5d20c75db7b4c90c4e21583e1cec8e00f29 -Test: NotVerify -Message: 69d5980a58474652bf27388ea6041f9e0fe688ea95f59fa745682c69bcb1c7ea82e75f19a773eb669cff6e4d549b31219b323c1bb62d16a33c65bfdd344feb77706280b229cc51afdc571dfc6495c35f5953c8e1a83d0b1e73cec7cd2b7bca8beb20f4ec18abf2c437073cb20f4b4def00232255a27ff6b3a17b3b50d88fdcbd -Signature: 18eeda64cc75f18f58d43ce6b95eb3918a521bfb40c1745a38f985d294caf2d86879528678881191 -Test: NotVerify -Message: e0ac66b23eabe745886613c4698c79478f484a43f8dc444e7e7ee215a673c29ba56a56b4b41bcfc1962046ad66132d28a6eaf623858f028c71c3cc4bdd34567d54ddd4f0bf9f97dff31e3def7edd1769b39cdbbaf3f28b283e27a5d7fb548cfc04be365ff66f1717b7164e8148210f83cd1951ffda3db89a0062c5af980a3c8e -Signature: 6db33727b795d286a69ddebadd6e09c527bcb1ee596915b6fc950549beed350fda40a4c1f52c6a34 -Test: Verify -Message: f9cec4d6e1f2c2285dfb17d3ec5d16edec0da9b05ad12d62cbcd8f84ab4ba73eb6cad40ab44ad9a079d7f8221c544d89778a6d50df713f5f25bd1a3acdac1f6a8d0fd92c0a971459ce62fb958dc675bc995dc189a3515088b3e9e33f6b54e59978b60b9359712a2954b55883b54b475c4a9ddeb31c0a19b66f6922ebfcdbb0a1 -Signature: 947428406add226d1dd8db3245d00617b152921404ee5ab8d4e840c87d26073cc4d144a0b51e19a5 -Test: Verify -Message: 966d6fa1ea1ae8d344037a48420d6379278133fbc0c25450974fd9105bf988398f652ad373c511c830d2eb02470dc7c63b3865507d0fc3b0994ce4e4a0dae337d55839d99bd14bbf9eba37be412de0e348653815c77acdee4b5d97d646170062c03e35ec3cb8ac73e8b3f6b40ae5c78aa7014383757a8bc4037c881f2727f772 -Signature: 63137ff0730f28235e87cd5122d22a973035869332ec538d5be6e2c9c0db94f3c012ae4abf3af9fd -Test: Verify -Message: 43a8f0b5992db54d1d65acbf72780493d1af881fe95f9f14f61b834f201ac1df16e5f252eb46b845306efc2b5365655d38b71c63155dbf8193e9a48623f64fd19ecf36a4205fb4ad26594bd2e6a81e3cee19aea80147d4ea2fc700c23395b0e411bf3342f050a09c357f114be21925492e2cb58564f5d666010c0f9e09cedc31 -Signature: 1bf8e80c8183d00907ce80e74989d84815db85dd1654a6d49f74c020a83e8bc931a178ce18056f57 -Test: Verify -Message: c4aaf1632b1438752e9790c89cff4773932d3fab0ef710bcaf41794bcf5c0ccac49e1a3c7143dd2b1484e4e74cf6c4006925fd06f9702a8090276e2ad7e41b74d727a3378835c4ba9533efe5727efac4a14d073f4089b418d7ec8526605a8ed0987c65cc85a3471948dc893b254f41b7d0dd36cefafa057d1cc796b58374bfd7 -Signature: 5fa8964b471c76211e2743c4d993e793dfa7239dc84a19bb3fdad2162a8c98a2434c94213f3a163d -Test: Verify -Message: 739d44364282b7bc61c62188d07e0ef12b907960a740f1764ff8ed7981586c04a47ed0ef2b97fc7dcfa6adc508941762cd79c05f8d2aa15d6e037a06c5f676b7d6d40069cddbe4e0fc81aa18578030ed2d22860929cf0f1389d4d5159d762c2f82378b7a2067a73f62efd159b55a91e8c3248438714773f01704b57fffefc7c3 -Signature: 1b61d79c6b33e3c3394fff6efd641405652033690d7219da8475faaabce3e395bc720d70c60e12f0 -Test: Verify -Message: fc205229f11c877b617739d9ac191773c207ac714c5e2a061a917ad2cde4827ec628b5924eb8e19a06b4357a927d920e8171130580e8dfffc06f2ee5a4449a89af12a87faeed963b2291676cf0d72d984c7997f8e207ba96472924a5a0161f21915542a769b33e978b85e7681f20814bfb964d03ccb25404893674cb1954a87d -Signature: 283d55c038d4270e71ae39db618390f17675478b704764d1fe352550054076f4461eb6da6174dd17 -Test: Verify -Message: c343029ce5d70a70251b50cc5e784126dd65e35080940f450d5cf435d567c9ce8a9dd2cd5d5096c55ba95f2f0952f2b33f6490b642942d24259aef7f62e2ea29b4771bee372ca2d5c30c4428850421c1e0cfb2978323068acb1a3d6b5be34550f9a9d416acc3a637141ef8ce09e845e7787f400d7a99120eb5b4d611f8c051db -Signature: 0cdabb09213e0f09cf01e0329bba5661753950fc92e681173a6eb46c02d00224b50ebca62a248faa -Test: Verify -Message: 5e126ef683f3b61a39065574bece4ad82dbf4d34495f40cb899dd2b163717588ddb683795244ac758252a3adde0a0950126e9984d26a96a7e93b72c780ffbf60ac9d5b553cd8d831c1af2a9edef79426d13cd42942d48e204c45f611cadac252e3804f81d8e612c40dd5423e56cdc3d285e1561b31d400acc875b885d73854d5 -Signature: 01dde9613b9ce3c29b3503c19c13f863f27ab71bc0844476b3860ac891f9ce374aea6c24f517b8ab -Test: Verify -Message: f799a6b5a7bf7c32847fc243cbe0166f5244a377c43682c41b75530e6342174fade751e751885d10692e10858b11926ec626788fdfe925b2cd6d625272a13c899ce41e3c3ccc2f84e533ef6088840d9a6e448bf777e415a291c59ddb7b8d3cdcbca9450bde23ab67f0a6952c3bcf3fc944b6140502bc0a6d60983d00f69dcf1e -Signature: 0fc64023e095044c9d2d003a555e2da7aa5daf413896cd4e7ac774ecbaa0e4ece8e8ccfa053ab62e -Test: Verify -Message: ae0424ff8fb19e8842828a3cd51c93e1123e0c4ce9f9fbbc1b326979295be9ad7c6e6783d62b337ef8924e1b95a3f4aa77546a6af0d409e483ff8b89d422958fcdf0860912c47f45a819b36be047f0538a806ea6580bd83990bf99a6f6c2682cf98316c91df69796a80f50639082a093a5b9b139fb1580739a692b0769b47b3d -Signature: 6fbe751842e02a3fc3726a5d8298d1a7adb799a02d897597f4c459d28e9e25cf447b8cdf50001d21 -Test: Verify -Message: fc5837b228cd6c963b52cabd227cf61b5a1e6ccb4baff71ae4f971da7904bce5d94201efb3fc28912bfc9894b87c307a414f8653784e5fbe76056e3d989f51bf990fca68f0813aa36c00646a0e685fd5278fdce1b2af9a83f41726ed5212d82072180bb396339ce235b5a5dadb187b434335e50fb2aa9f829685108260354721 -Signature: 5bb80b35dad17648220dbe980a660effaddd7c43ad3584318e835c355dd7bf2f5510091389c42914 -Test: Verify -Message: 689eec3b665d72447abe64d4ddd79b7b73cd171bd22fa8689395e0a3d9793997205583d449fe912be240246ababb1859a5fdcdf48ce1d9ebb928ec58615503c073ced04ca0306948abf231ddf33e040b3e0ca7eac8816e218b872fa7d1ad67b9f841ab1c85ab52956d0c61a69f18b78ad5317a739dc6c102a2ea82084038bf7c -Signature: 3cb07367288036891a8861931e5b2104734a6e7e70ffaa32a49032b968805dd0bfc9f1989da22b12 -Test: Verify -Message: bc4828ec0810c7a43cbf028dced7a5890803681f86238a28f296aebeffc7f561a4fa5d6c9a595ab7193ab38eceb39fd220601f6ea5739efddffec8b93b7da7a74ba705014376fde4b375e33a844a57ea3583a43f56a55f9745723c4d287b34e82be7d584fb82e98183094b6be6b4052abd05ae6b92d0034d9d8cc550bdd8d27b -Signature: 67b214ed56ba44ced95d3d9e8c25c99331e3e973a3099e524473ccc8d4256f4ff7de9674a369cb57 -Test: Verify -PublicElement: 19b80e6f0132bd24dc0f26acc6a30445c4deb4fe7394440ce1ea0039d9c8137ec962e54b09d4383989baa288129e551e027477965ba1dbca0b6d586e482325f09a0fb16236d7b4ac3a3bb822a7a329aefeb91936f4b8cae38fd1e369db4f3f97421277533724d27e39248de3618a662c4b757cbbea2e3d805116d3e9d0ab3547 -Test: PublicKeyValid -Message: ceba9387e7ba8d55f8010aa2e8ed7de2c8310df67951e1c49c5fad18baf47dbbb571c2d26f779a79b8a564a07d9184252f097432728b0cda080212effcc3052612c8266e6f2bc88e85e6dafd42cab20679bd1b1d9038a27b6b001e0199237e4cbe37d81441ceaeca363d82728d8f9ebe7dc41d6c2b4f3ee19fcfea07e90c8364 -Signature: 84d8e940de14bfb65b8c0e0999e296a1d3c51f18b8bd79c57d826d9d200a6e38e52490722c6ee201 -Test: Verify -Message: 7b9058ef673b23e5b6a3d97784b898e0d912c990449be876b77b768da6443ba95b5fc1849db70e0482a4a1cf901aaf111b129e8dda38c3e2ccd758204a03c18b6d0500aea30b76a48c11dca21b0a82c9ea54c62bdd5bd71bfb8bacba897c3fbf68590f86b191d55c8ec285095ce2899fffb03983845a9eb9fe6f68749a082ddd -Signature: 7d07f3033c1c841466eeb641ad899ee247757ca067ab38f6f698ad0cce5f26517da7bc51b8e630fa -Test: Verify -Message: 2404a0e4c5ff8fa11c40f9932c8bfd3bac118eee53085c8e658cff857eb56b029ffa907876c65054f258a7fd07e01512bfd850df82a02820a65dbafb3a13d9380f01b9c3093ddd64a49044bcc994cf84d30cf602dd84accc4f2a8fc1a8eb55458ed173bc139c0f494aa028c80ade040a0166da50fdecc00a77aad8d16175b7a2 -Signature: 793e491940787f4e76495575616901c1c77d023342569cb8bc96efcfbc9746b3f51c31e29b221b02 -Test: Verify -Message: 5c311c167d2e3ebc19fbf7ab1c619d8ac1611152527a953d2137eaecc6fdaed79c13f4fa76f224bea7cf162531676a3a4c0a2ab81beba3f9aaa681222b122a8d724a5c77aef60aeb69df73eec3b384eceb157063dee88dce64dd72d4473b4fb2d6ee8de59bd3a61d5843465e48dea37894991aaa130a0b9246f3f659940ed61c -Signature: 7f76e9d084a9afd5c390271261b316cbd1095e710d1b7e4503188c99b8a8d851b130ad240e31f0c3 -Test: NotVerify -Message: 9dc221be2ab612b2ce6c7fc8b739af7fe740e9601f3201d3094a2444a488e076f52c7727ec7665e5949d2f307f0e6ed171e71c7a4cb21f9f3c661494239b5de7470e6d003a5553f80ae385b6aa3fef50a0803ca1f10d64264a93761e6f47a8e2e95e9c82ecc9f5a186361a930e434ab5cc05e10ce5b9e9218bc9e41b6203d81e -Signature: 332a2daa48681410763f13c3b127516c861bf1f187504d8b3bb1bd11ecbf9a9821f18466c10f1859 -Test: Verify -Message: e4354b9c9bd98d62fe629486b6856c96f34d2fa2460200c5c25746f454d32a065f8153049bdbe1b32ff4a8600de6aeeb8f7be7174f1f2f114c06893e3a9997492927596d5bc92a005f96f8417209c36316af59d9f41450e4eff0445b8a8e52ba7d7ed56e927b6060c59ffcc09bc5a313c33ffc80ecba5957e56deee2fc895471 -Signature: 65c2fd8a2635d6942b4b833682b29637eff64d80ac5ba18491bdc26d1c34d70a2c4b680900347d1d -Test: Verify -Message: a090ca3eecf8677a7699f42b16428445a3cbe74981efd6436d66620185469e959b9c8c0dbb464672fa136dff821ed7a2db6874b97bb5810691a9f1f30f22180df6d89abae633943ee56c08ee6fe88eb3bfd139c25df7c899e8e60e3d2647a3b3497cccbd8477a9d7cfdb9d71f657036ee83f0fdc3e6b01f60a559157e36e9781 -Signature: 19b4876e4043fe5f5a58e70b1560b0942ff4fdba842266a6653a6aa1550b91f4ba85a3b676a3659b -Test: Verify -Message: 8e2ecbfb35ae99dd004f2305cb2fe98c81edcccc13372e86b98f4e526d5dde4da43ae6fd4f7cdd8812fd0516c43107832767cf49e95faaaddb0e9f2a70ad0b1b790880ac1f05df022172b3a94f14d13f47ee2e5f70cf01d0341f19ef82ea805a832e51de9b61d7a3a346e89665f280175919a0e59f9e69463d5b757a9a2d7662 -Signature: 6d67367aa1caef2722c125a30e9e08ef7dad05a015893ec3c395c35d81944fe2db2a660e4e60913e -Test: Verify -Message: 6d3ba912c4bc10feb611e15965fe814bb2d5e5de67705a1ca46e8e6a8cb2e3243018f57abb7a698bdfe3f9c08012bd6aa033bc9f8bd9b351433f24b12ec0a3c3fe945c42e1cce9b6eb9153d4c099661686ea3a9b0ad3ff4131280800a2bd1b8ab125f7218fac27b8b092064d7d8a13863c73788a3c56d52344a051113ea1e3b1 -Signature: c56d1aa9f30790bec01fc07e5816fc6f44ab659898a959ecb061b4347e7f2be6f2df97ba33043a00 -Test: Verify -Message: cf2010dec81c60bbe408df2bf20f465d259a5a8d2f7920ce9c566318705c69950423f1281edf713f50ca8eda93cedbdc2378d6929d192081573efd7500520cc6799247edf3323e4849cd902aa013aa273daec49ea6741887fcd4657e987aa511e5450a467e6c3f7088ebdc3451342ad729141aca81e3807843f0944e712bab0c -Signature: a6640671721cb21d86265e30cabbc09ba20cf6081b4a5c7928ab3a53d4e291bf6049e8bf8418f6d6 -Test: Verify -Message: 4b00e4324ff7fbeb0fc48a6c83de82d52da1bcd1eb6669cffbe2bd824fc1d7971383f4b67d96d5bcd4b56e36c480d021e05d58e0788e197f9e93882773c267e1b725f38f919451289b143633316ed687fb131041b930d7064e0de47a10ac9a014f9e39b5232847a87b973c5b63e16d7f957d3aea43847cdd24092975bdb5496f -Signature: ab2f5b0d5237ec1b7e6297700a7c06647a526cb069c8162c513100008fe0dc37d4a8c9639ac94cb0 -Test: Verify -Message: 20f18b1eb4ccf98fa68c10d680f1536bd5c7c3307cb13ede0e3717afa213f74dc8b8f4fbc324ef020ce7335e03744baaf8a824495a9964d63ea00ace13a9467ca4ba9b264fc2337684a4822b81841f004c51dfdcf193333cfd77c4de3a184db0ad10b8f8ce3f7cc407da369470b88647c8d92d43b73864e942d37f388ff7c3c0 -Signature: ae23d943a56fc60ef381a2a5c056d24e472e9e906e4af1bcc91a27800b99b7cbbae8d4fc303ada82 -Test: Verify -Message: c9db3284c5b9a283f38da98655485939d5662045b325ccae3207df72838a1660f22634364f8814fe9f0eeeaa0483e9efea1ce25f74b37bca264268d6d3a3f6dcc986dc063cb347a7f08220db2b97a060dae317b302d8f86e6aec29e287518af0a8f2c32d62b153363ee0d650a2fe9744fdb3567a370e5a5458fdbbce770de953 -Signature: 06bd46f7ec091697c86e82497dc184139a988e3b9adee67ce3d87d739871fb1cdcef9dc6de421615 -Test: Verify -Message: e2e5fc81619b215141e12ea9544184e5ebabcb3834e96dbad2464fb5be7bd22c5dda0aade2be3d59e732a03147e04da33f3c8854c4f23330278e8fb0e76b356bd7de54e071a22c827987cb05d65708e8ac09bd43be2948d304874443881f84bd874852b1c421e6e52f3929bdb77eabcd6c68e29dda66a4bba189e807596fb93b -Signature: c86708f91828158b1c129e48ccc6adfdccf4997e8eb2214c24fd4bf4edd8ac1f3411d77ec65321c2 -Test: Verify -Message: b9a5127b9995a063f3422d3069a4b22ff9b7816e01ceeb3f933733f1fc11b3ca8f694d49b79c159a3ce93c59d555408befc452dabd54071181fd43d8196863b1cc0caa32568fee84335c841c298068b919cbb19e06233412662b7815a916da6408c501af8f2885196ed3dbf17cdf84af0c047632f5f4ca39dcfaa81fc5d370db -Signature: 0461b5dfdcfa1f9be6e7528478e2785903f0b8990f2354209554aeedd246d231567b06c5f81e0842 -Test: Verify -Message: 38da1e2a517a87304f85291a67e7a7ea0e637e797fa1a122707b58ac10845b7d44da2afe232eaf49b011171ad781edf4aab47992dc2358927eda5d5df9ffa75a4da2035389c484278aaa60b1f7630ef97d979e9a48935873c2929892904ee95dc9c7610279533c2256e7bcb9c1a4405100a5a367ba08d81db43bc322cb885adf -Signature: 3e7f697603dd770218ff55f027a8fc980763b6b9bbe84a766e0e55fc7c23e4f734d28f67fd73e14c -Test: Verify -Message: e431f4fc91ec6111098c5de4532c76bdd3ab9a42e92c6c10e7ccc69539a38f31cffdbe8dcedaaf3b78a3a68f592fa1bcb4f663332d94bd38b8811fc7c10f60a69da5cacb303a6af0e0159675bac3bf76e459782d43ebc7896c4dac0fd009f0f224a0306e0f06296a1858454ecee06722394bf4e88129223adda68528bf87d74c -Signature: 2b2111694dd96095c76bd18fbce8f720ddcffe6c8d9c194e880b0abfa44bcaee6b97addc84c519de -Test: NotVerify -Message: 2f3e3407e1c3e585d3f87ecdf8ee45321c8d46ed84410565c7e282c1ece573acc5c2bd688ba53416bb5894433070bfb782b7397b9edae229a653f2780b993a07e887996aa20bbd73be101bc203ad318fd18efbb7c0a3b4057c08cfc3e03535825167c0255d4ef73495f80c60a8fd1352c1ec85b822f6f59201da10baa310dbb2 -Signature: 88ed45212439c0cb86f513026b72002cdae6317544b95fcf4dd1eeaf460edb6f5891080272a3b31c -Test: Verify -Message: b3b7c629f3f5e85b35f7b95d9757a8dd980a2acc68fd9f1b74ee82af328cd5a62ad2ccce45a1b8625a9c3706f6499a066c6597cb1e88309f0afae3a298d4130ca25bb6a5c5994181e73dd00109b59a074e8a95794cfb65f993dd8be27cb2cb863409dea709155933f391dd4466d38058562f7ccd8c8f17a02850d267775fd58c -Signature: b2101fe80d5d71592eae972be0cb7f67e0fc2950bf60fb12b91a1a63d9f4747c1d92d2712cc33300 -Test: Verify -Message: cbf84e9aefa950d9c997dcb571a50e25c09c7ba40e730a1c28e112109621b4090b057b442c3e339a86ea07afc95fde5f4a37f765b99cc34e1fd5039d1b1122405d74d5336360f17273058c25da2b5807633f3c181a9d3483421d6ad294e09550bb5c93bf0ca6423b8affa46e1aa232f603cd8113a90e13958ad080057925c612 -Signature: bb80dfc840147d79654ed993f5266da74985e2225e7f5d61266fb1caa2deb06fa3bebd930122cfe4 -Test: Verify -Message: 3f1ba8edcc9ff1dfe2c25c860202f927af2188fe5bde071b8fef797c5f42f96c0d75001bfc94f37ed912f06a040adaec45b6a3ebac30d901c96974960d67de3f80c34456a5621cdaab73f788d5a9893b2bbaf68162185f7f09efad07f6609df7f0fb0cd59e8284a8b0dd08194c591dcbbb2519f7540fb04ca97bbc06f1a44d4d -Signature: 06c8b4f82b1e5429a07857ad5a1753f1d7cb43b345bd935a1f203ca2e69fcbd2321b295b1ed3c2a2 -Test: Verify -Message: d0b56cf1a2bf4845544090bc5440efaf864b8ba6205a03e5cbffac3af8d50d067f28988a7fe0ab7472b3c7aa8f8b0f5664350432b44c80168f65f0bfb07cd6e11b9f7e70f7d9ff2ca961766b33047f2bcbd0f458bf02e95a8932e8e22ebd69f6dc73953bc3823d8333a21597f8833546f374d1aefa5438c9f1be0b3c2970c05d -Signature: 035b9d105cbcce5d24fc186ff52ca07663ca774e057e6de4f5cba8df8b24cbd361df4878c6ebd3c8 -Test: Verify -Message: 82f8b357919acf5ac548e01bbe97782acc131a157d1b616364ff6dd32c5993d1dea9453a6f343e518e1ef301abc636554b632d368cdc7363f3ec8cb67e768e95e6260eb7354a491989ef9440274005b0c31b63ac0ef54c3081efa52d6939470433a8e745fa9346a94ff39b4e47ba3d31cb7495f11c1c44c2a54190b0055a1416 -Signature: a4e3cd2cbd2151d2033d0a56fa7d388af1e050efbc23bdd5fd17061234244d0a9511b84525e719bc -Test: Verify -Message: 5e5dc7a9fad7608fa377eee0d126a5377bfc0b9c11cd19b3b7f88f25c36c984f78fb9f2a05e3707bb99a933b88dae649c4ed794e143aaff1b911923d02b3764f0da5d244bf375b61064f62854e7b6fcc42371f85c57b3b562f891aaeccf5396c93f518cd23ea579b032f12941b2279186e71b4181aa7f63b91f7df51194718fd -Signature: a96a7dffb16216ec93857df38b10fc73c4792e61055a3d5c2aea3e5193113b7d0bfd81f6c3b0d01c -Test: NotVerify -Message: 9f8215298027d29e4128e75b86e6343bdebfd7f0f60bf417ff57c49a5ce1e14b9154d0be68c5cf6765ede1f56ca818eeb1af228be19217d68ef98202e01cad0b7a7f328eabf3bfebd6ca2999245ab4c968b4a13e52a6f96cd8ef99d0e1c17f8f347d5352a1aa39616e36d6fe04f1a104db476cc0a33e3210b4b022bab7c9ed0f -Signature: 7956b42cf6762bfa1d84425dbde83554a598caeb6e3298db6c225befa59a9840faab00f16b662ca5 -Test: Verify -Message: c196e14d01a2abd6dc046801d766e076cae2539afa2ab5597af92c35c4bbcd8f9378923503069f2dec6fb6c17ba1f7cc1355dd4363417607c881e2e9e5430ffe80b2b326a0258ad7e589d22f270c043a530cd480823f6bd35a23e357aaa804d2411c3d360f58e66c7f29b56314017e5942df2f698f7c0b56eab727964b4222a2 -Signature: caee28fd1cc548ceeb7141e3255c6043751425f2c344e1ddfe08ee2d42ae77391ed03f9baa195aef -Test: Verify -Message: 7d8df5288388272a7473d757c078a6de15994fe827c215d0bf2f6aa50701e1e2141c566cb5445bcd7b78e6b0098d399c9d0f12f5df541530eae276569803ebbc13a7d101997a9d488f4686b7c98b7130185c1c4f157c8fa42ebac032ee8a852891e5c0dec862c513c9950f659aa824129f39c5ee63735ba4a36f9e31a1cd889d -Signature: 75bb8dd4118b861c56c6a56bf00f194b9296bb677ea7ca4f5cda2855253f880473d5aaa8196c39b3 -Test: Verify -Message: fca73579a6d91eabb3401ed9b9145c2bc94a7066a85eba514a62046a95485bca536c2a5678659828970d253c9fce805fda30ab5527a0514a7783677b867b0325dbf979ae0303bc120947f3913a615a9717695ceb9ac1ef1cae1d2f29e9d33e6f8c655bd8bd4c41420307c22e0365a4aa790fbc80795849a0e84993cb36e8c482 -Signature: bb488822df803c1b8b424169ebc82e4638af6d567a7d2adfeaff0861631adc4c602a95a7ea8a0c00 -Test: Verify -Message: 2e5dd807911f65df6c7b71c9727137156df8fe02af3c1e19bb1d51cb35e43d4e07483eb5d5a1784ea46b1d41c6fefc66088c4b661f5bb5165044a710606dd893bb43179de8ba59472cc902617d20744eab2cd621ca4e26f8e2578299da47b24ca247faf8a0e41f815e8eb8617150b785acd1376a868c8878c94c799e7debe530 -Signature: 02bd342623b4f7cadbd88af72c8ccfb29f85042d4d2d6853d6a7769f2ed879fbed85cc6c7440fcd3 -Test: Verify -Message: fd149580b4d7b1e3799006d6c37974de79658e074d2d1cf4585ed124f7204986e569464099642cbde21cbaf5c16d0a01872dccde2f96bf81fef7711c599b37b0e6fa6fd3e71ff5c4d359e4ac36258e37cb5bbe53d7992d48c8ed42f90fc60e793a1d88d156e00510849ffb94da79f7987d49dcfffc0e5d60ef98bd52d07ac6f9 -Signature: 52c97e4fd456b9a2141afde95fc0ebf4ee2a509f274e31f5a6ee2730194eb09532d7c12583b2413f -Test: Verify -Message: d1197e08ba9f4654452e42783e664e3c7ad5cd9de2565149c0aa8d5a49547d576cb9d369da79a5da560856d33e91c2565b0cae7ae59e6ee7da31d891815469b93954b621879c168e5f4a8e84b313fd3d3a5989eb828b493039bc33dab88749e3d12200a9dac0f16afa2dc303b3a557e9b0f53668d1d5381b748477ad07a573ce -Signature: 41b31f1faac06a781ce424ab9ec6cff44f1e015bc7237a3019af5d73774a0b60345b6ed2293b7fa3 -Test: Verify -Message: 78cb9e8764eae88cc7bcfecb525617286955348da2e9c0958124677a7285334108c0ee2475d0b3404940d6806fb5f7c965c06166bbe3a9b7cfe18316c74be80acf4766af95a4c765011ce6b839e8cd90d58a139a60d675f60f42b421c570ae2647fac001bb7d5b5367e8e44da806d2d6324a03ff87db5ea9b9e0af75630dbfed -Signature: 62a367ef341b27a22c1ecb52dcfc34180902479129796872ce1b0cdbb678fcb0df10b1f37da5ac9f -Test: Verify -Message: f0e673b363e13da716f3288bf4b4993d6ff109e72a28529ce9453a2eb69b3d5256249ff7ebfdb3e3ea1d659040550e46c08d7979d03d3165552a0ee8db63ffa0097b19454508e148a35cd6ad14834226cc7d4371f3bc14f391e1a196b3b44be0e361f854c7fa5f0d18299399c635cd1469387e86eb9f947e74e20dee9785ba4a -Signature: bd8054b1502e66908555110fc569ac6ddccdea0285a04c81b9ed46ff160a26eedfeb4a8255147239 -Test: NotVerify -Message: dcbaca556bcbfcc70d2164b348b037467071dc423c11a549aad8d06716ddbee49668724899a84daebf96084efb29f246e7bb6ca967bba2ca82948bca7dde246039c4e8e8cfb593af694f197d6488e164a41f46c8364250b02d81af4cb6f2f9c67da6254d454c4860c3248e58bb277c395d7564bae2fe299263753405f972b7af -Signature: cc52d6498a412d0b801d243e37a0291644135294bb91fd182f3458c59e60725b21436a401d534497 -Test: Verify -Message: 901bc4215934ede2f6835d615c38953a95cd48bc09a249a30edcb412b37f5cd4c9ca75d433d383da706382886614579471a97647acaed5377f511241697fe0c90f42b735865abca8dd1beefcef86930267abe2fd143ef25c6f79e2b86a314a0e7b3ce23ee90271c35661f9b58ec721fc8f8ae2d6d88b768cf70c7e704dce721b -Signature: 69fe1c37cddc2db194719f80d9db24c60618f5e99cda4d645d1be7c3c4ba192c5d8606dc9c2cdc61 -Test: Verify -Message: e524024ea5f5ef7baaf30efbfadbffd9ca00ccd03d91c23a612e8d3c67ab933023239253c4417cb0d5cb934c7370c193d0d23a03e8d75417832da6766c1c605df090eb4a9966c1ea2cf68e45e0e28828e11f0bd305417ae4ce0b5283a0378fcf438243899cfb75ffa88e383cbacc0c6ef5fd7a970c68ea7839e1c8bb7c94d760 -Signature: 41bfc6a00915f9a7e24e0d4a7a1220aa0c0f3127b0286f8333c9b002a4acba9673717ffb09368caa -Test: Verify -PublicElement: 1dd203bc368c505fafbc02d560b4b9f003d93be0f78a11fe60e94c406890ce920be3fab9d9ffe84b80f3fdb9071dc602d7c8165fb62e346847b3918d450b3dcccb4bcff0ab98e3052ae36d1a65caa37c7187bb620c5147870ef676091f5199be871dce4fcda065da9f3568fa70edd637450acaa7e42f128b6a3a0519d86784d4 -Test: PublicKeyValid -Message: 691699d5c945a8508a41c3c83f768406a904e3bcad75c75e76becc40e67857f0435fd8d61f0b5f0b88ee6276718fcd2d60064b0b5ab7d48d0c5377f23b0c69936d174f80d968c95c8ca93f7bde7cef3914f2379e574c202fd5f12c1735af62774136970acfd2fefdf068f20e5cb403e31dc140ad7caac5fd298f84e6aeda5855 -Signature: 9c2687d271c475a3ca252997642f12c2494e6e1612ca7c28dcebefb178a72071de741a27699cbb58 -Test: Verify -Message: ad15c247a6d92417670bb015e2c56b2170d449feaea127d898600517e37d88639f43b0f80ecfd52cbf34e83deff0e860208fa308fb9eaf7463d2a87cdb79ab9c1a221341ed8973544dc5d405c0b530d9f5a72ff69a4b20af81d83b4bf47c151b560a65bbfbdff6a74915ec020fec3ba325746462458072a12ac8351de75dbef7 -Signature: 3edf3214d7492ead518c21641cdeeaf11955cf2c9fd41dd6990a3d93b5b996dc65b4480102910be6 -Test: Verify -Message: fe8aa91c3ff17c55cfeb6ca7d7934f00e1ea15bb63b4fb9d8a94f410486b559ea1eebfb131865289026c0f7e8d058e780e7be2ac0d9dca9929f91942283868ad3cbafa9c9872ef8a3303ade9dc1c8b9b7f11c0afb6ba8b5d9391a444ac07e4e2682730548a6eab50fbe91c60dc909d61cce2853b76c398e25f926e8def8f2136 -Signature: 454f59ad954b584350b19484ee93f3fac35e5a21025acec86b4d2cedb998a838f9c3d801acf7ff52 -Test: Verify -Message: 53bd313ad31f55de5bf21a35c1a6291bca8e6e0b206736489726884da107c1770fd273f10a707fe051af70d0b5521b5fd25d75280f9fb5f2d880aa1a1b0c5e3e0140ec2bee959f09bccb4cc633f7f2c0ccd08fb6a73645f0ca04aeae9c177ccea19f55c277a5eeb212dd66ed34aee5963080758bdf452099e34a4bdf1b405280 -Signature: 7408d817a92cce7b17409ca4a522ee8d2a05bc6ab21cfaa6c48819dde84f86090139f18c389ec906 -Test: Verify -Message: 8d67b965319d7ea31ecc8f7538b0042c8175e4de45b0eb7d869b9e3aaa918d1964cae8d5e05846f63261b131009ef5006f152a824c137f957c6c4a31a6f64d081e444b5c159fcc20004b2c5245f8ea982d862f1906fd9d9f98cd5beaca425e57954bf9b22a6ca8585f00199160b47c2c93410c5ccb69ded3b135ea1d706d573e -Signature: 3c2251163492bf6e777793020a5010959d84a258b28ebc211aeffb54f4f99500f88cf0b2eee180ca -Test: NotVerify -Message: 8fa0b50bd675f973a529cb90f5a7be4302794ed969f31dda80a16e0ef6efe2d1ac177399d350aec5463535a82a7374d6c4b7a3ae9ad7fd28cd3f3fe0b69e6363c0d29eba861297352d5bea7a031cddcd582561a29dcd4c60bc63d678b7d751a683a92d8727132c5c1172e11db8fb6fc2789b80cdaa2e841b03e52ced2ff12632 -Signature: 4d6e667824358fe066bf44377146bf2f5f2d92d2adc0aa673fc3912c3ae67bf8d0c529fb1c25776d -Test: Verify -Message: 17aeab19d1ee54e4aaaa66144a82f1a348dc53f8f1fa9d1b575c44389e580c5883f8315b2d14d83838b1b679009800f12b3a92c179c4638ad07e28f4836a475fe21900e908d0d6a0e0dc44097a339ed18d4c45d24c400f496e22f556789bffb54dca6dbbf95b2794bae667bb508aa4bb86cac22401a779d049ff035715250ad1 -Signature: 570867e6fd129769612e82d31a833ddfbb9a07833815df754b1db1c729e7a85fa4bee867dbcd42ce -Test: Verify -Message: cbdcecd18c9984a189ddd576261b6aebaf3030639731cd79ef7a3faa2af4b9420fa6bb84ff7f701d69624ccb8b73e6496ba1137f157444e81618224339ab687d81c300de67436173556028bd62eff59850f1896dc3611d9cc43c052476d28695174df4383a7f107c43f0a0a4232750af5539c98719900f6ef0fe20a65802cb60 -Signature: bed7f5866b9ec24dc7f0ec818262aa7a2197926c314a353cfdb5d11c7e57685ddc0c1863b7915521 -Test: Verify -Message: e8cac9ce0ef12933d72bb5ec654590ae24739b0b378f75d32293d3acb85902ef4791b9c603032484b0072f45944210c79ca21787cd9dba1feea5dcdf74ef5dabae66e81531eaf9bb86ce2de21390ce5347da9f760abae4ad641eb5f46c9385b6733feef2721cbf8eb27748fbbaa8e40b7d13c80fc55f0c35daf6f82078bd90c9 -Signature: 35dc7ce798a62cf86653c31306ee9dc5a8ffef2a8c086ebe25b001f990e5f511f780ad9d7eeed027 -Test: Verify -Message: 95f01262b79dfb8fc98a0217a661456a8b97042d6dd524499daae53a9a70e096377c44dcee8a528083671634dce0677820eb21640f14a2b4a22b8316e32c98b10f6f2af6e91073aa61a15b34660f722408d22e05d359666567b50e225c8434f655203c46620958279c914bb1fbc65e897ba4a2a96f7c697325a0fff6bb50ae7f -Signature: 9e75e572e76eca4859c954248a01d31921da32e371ecee37eb40aa9c13ca2e65961359e4466e9e72 -Test: Verify -Message: 64414cf10d118df7436add5cbd54ba23e8af55f7f79d44a22b1369ce64ba21fce90cb1c274acee4981062d07d9276ab859debca30814f90b5969a5f3bd1120176ced102775ed0d4604a58cc3f42e0e179540891fbf8d179a1760dde6a1763ef7861d4298288b41e66481d30a2620fd36330b94e333bff649fe2fea1e28a3d493 -Signature: 212c24985e37ee89e71cbe6d6012b89fa181db569227db91fc0b6f557f377e380cc56c271f7cb77f -Test: Verify -Message: 8dcf3f1d21a4d1e15238b6db0e89798e66cc62b60e7d0eee15a550a2e56b47387ddec07aee02cd471418a77a9733c21b22f82ec5e1b4365741a533dfe382b1c3e24cc6314659aecac89eab8ac93c1cfb8d4edc9abcf2de891b95067786844acd32b0091b21c2abc2e65f7be29bbdc1862066230e954c3edd1a0e8044c68a49af -Signature: 7add75db81ef8d210f6dad09da3d11381324430bc473f003495c0288a42fd93957dfa5321bdc3d82 -Test: Verify -Message: 0ee654428677f6fd59e6cdcd1406dae8f753dcbca966a88e1db8ab5abf9bbde6e47528287040f8dac93f865cfd023fca2f9dba5d4725fa07da6b004a57fc955a73595573d773007c096afddd9987309e8c78fdc10dca9de053aca00bcde3c3dc9508f5dc1409a41bf1e04c0a408d429ce85abe9d554f285260f3a4527b46e0a4 -Signature: ccfd740744131a05fbfebb26edf96572d3475d6441c042287c109e0aaa4e9db694d074889cb55dfc -Test: Verify -Message: 1a21fb1ded7d167c9a590c8bfc4abc10ab1aab159476b834d9d91e24ebb8aa84e5ee3ee72c6b87214519fbd2f70f1630a2fad519dec7735857966237e8db8d46f6d6cd6b0f36aa2bc4095337c4e7e03a3a60c6e268a29b2d846f0cf6d33e1cbf04b09fc1cf37f631ce010cd59b2b91c82b2376896b5ea94b193c1278e438ce87 -Signature: a07b8566ada6bbd54b5fc36b4a3b698cbf60c1ee912a5197ba6e98bd4777a884d6bc66022020de8f -Test: Verify -Message: ffc7c4abcca3dae4c21b311e6fb51da2262e53dd491ed515d6cd216d34549a1c40f836ea93c36aec17645380c949258bd0fbd9f2bfb9135727585115615a5a7e9a4ee6541f678a86eb60e72c6e8f14c4a04848af4675cce784732002a42f6c6c25812be108c8132956c74718f6c0c0c5adcff80a7689d93c05d5e62c960aa95e -Signature: 60b09ca0f393d3398635c5075d114429b6cdc8bcc7e66888f49148be9a9f96edc5014b106de6afe6 -Test: Verify -Message: 88fb1d5c4fe552db3d7213c906f74702fc102d41cfe636138ac123fbcbce5fe743319fd36e4eb8bc9355c0c7fe0c69b27de19a7c182f4e5016d0b2b82de57aff08e284e7ffdcb18c1217009826cbeba9843706ff8fe9d66ac64bf073fa7253cad02307f07927f625b1d10994f6cd87bd0b2aac23acab8638934a1485ab0ea11e -Signature: a4e8a3e21168f000ced52e3a35573fb6ba82eaa164813969ad388163d2cb861f472e7cbee985e0e1 -Test: Verify -Message: 4593c65d5e569a3d1369a916c8e6d4f541080dc192e7e51447745056d5b7bc1c404852c00e0d8b406d32f75ca06e4aecaf74a87f4fb7323a0f63d1efc598427c38e963670f15bcb7fa0451151f05a724c747141d49954caf37562916c8c4ba7a866c908a38e7445912d74d781b240055e078e8d457f9492b1646ef03b5b43ccd -Signature: 8c8e17b621fc67bbf36704f2356e7755d960fce3a52357c84b778376dcca9f92c91b9be575daf7b0 -Test: Verify -Message: 6180fb71de61a23cbe0d4383386e0170da515bbd67512b41ef03e0bc2d63fbdf257fc89ffe625fbb1d43da8c84efd80d6974322a1a0ffd4d1158c02753acf7bc0edbc8b2721304dacf0d6100f176f6efb9a0f8c8fd69b385a16cccc9f667b5ea52ed7141f14c8ab10cc1507638db532f012d232fc6384700d7977b39ce6c2f82 -Signature: 4156c005b5e099e4cae1d24a4ef35ae0749e4cdeade8929a74ef00f4f57e18c864ae6a376d8bdb55 -Test: Verify -Message: e52be63c5733b8e9860af61ee50f73e7f679522cd72f31af10ec93469c938e5b35d0b7a1e4f14b18c9039f442831caa9b659908b22ef92e4e617b4a54ffecf32ca7a981872e2d011d72fae3a11538a9306d9cbb7f8bf12de5291a710b3c625ab3b5f621816bea1ca48c4fb78b82f0b9b7e32d92a71560994ec9145ffe1a4e7c0 -Signature: b07e9d17a45cc2ceeb1fde1299ba0d6b3bcbe7dcc50e823d12ae5d86972fc6e21d499d38120d7638 -Test: Verify -Message: 1b223eeb3cebfc1575b37c5eba339ca55ab86c9300a64fcfe94d4f6467f1c06f9714190d5f060f84abb0f3b0e89d4db0c04abad218af03bd480d7fdd9afaab1405ab079e2a82334590d84ac71c0c7f85d4ccf76dd5a3e62992c4ec894f15b22edd7fc0789775a2b29dc33c7d5099697a0ed7db3b2f9b2f6c40084f3e7e590d15 -Signature: 199d5f32d2645a1d46ef1cb3ecb15a34eab59b9a8c3cbf5810966097bb9c280e812c22ac298e156a -Test: Verify -Message: 7296f7fd229c0893a84a5b7ee87a034416e5ae1edf1e7416d6c9df5f20213cf564aa2175ed32403f220e6aca2893e747d5d3f579d8999ed427a7bfd5aa2f55a1258f0be16b5102dcc163e0d790931baa504e87a3b1991ea00b501067089f0b498fbeccf8f4f1e7a55fbfd35d7a7239a55fcf7d55c0178eb2583eebcf936af626 -Signature: 5e2044f956599ab077c91e0f9f9408dfd3c458c61fe6edfab105b1f711919c0b43bbb7557252b193 -Test: Verify -Message: 7279097dcfe09b8615d3275b713dced645da08ef435fe783c5e888676fa3daad07bb933594886f78b6f4ab914530c28d2e9967f48ae5c398ff92f09d5c90b6c9702d850d2b42b355f89cf68d5aad25f4c5742ba5bfaa4c62372e9ca425b3bce164a8d81dcc67deb494a20066e60b6da3c4434b191a06f87c249482950362658e -Signature: c2b345d1c28a149215db60952dac2854103f0260bd4994a0b35394474ab82958d7ceb406f6285f4c -Test: Verify -Message: 7c9b50842db0de693441a2c13323de1369e251c07cd49c41877ff69b672d142642ce53805a0e28cd11b7ca313c491e8facd7e382fa241e9d93ffc8df05dcb67a89b4cac6d01e587f12aedb47558ed958fb5b14898f43f284d15c2f46ff47c1d866050b4c2a1947fa52df2dfc172ce9e86d273ccdd368f070584f82c8eea60bb7 -Signature: 363c61fe40b4c0a4f06908df5c46d8a9c98dee71cd1c56f8d7a16c081712cb1b8c92cfd00464a3e7 -Test: Verify -Message: 0bf43670b5fe01cb48e75a19b519f324451ccbb3d85d8ef15c41311b906aca6efb48ad5027e4cdbd23e951f538f47564ea1da4d133c6d4cbfba32151db0aadc1137db703c975faf58471481ae93f677fb48a2ceffaa5d6579d97ad7c1067dbdb4da98ae01349404c659777e04093804f9b7b9a63a5934e6e3a340df4a7180d96 -Signature: bbefc869907609019f4a85294aa854961e51c4884c235f4cdf85c4c3e0ff34069183ebf0ef50bb9f -Test: Verify -Message: 419ff761987d7257a0bc8817abb4077986972726e6ac93f311cab67ac91747fa7d021871b37f1bf8b082b55e6bbf4709b1a0fa099986cc7d2b44d82b4cd9ea5bec6e43f47490a9da6aafb38767d753e83bada47a5eacf6a59aa11758f665e4e6e7db1121b22a35b5253b19c7767542ce7bb7bcb10c972922b6da0b3aa1334e56 -Signature: 29becc5afb5ea31a71b4169b91f9594d0819de2d409e4c0c3bfe8e2ea53e98dc1ad4a72f3e3081b9 -Test: NotVerify -Message: 31c4c31942471dd6583810807472b62ce7cbbddbac7de47f08d7bb4b6024973f5adcd3f4380a4ea571fd227f9133a22a53829698fc88ba0dfa55746fbe58d6d0d687d43a4fd3c7ba4acb21afdd8f72542df89c8cc90553ee4989d8112713f619dd1e3d82407a7d2c1cfa87a8115f20c1ad84454ecbcca6382bc95dc6532eef31 -Signature: 3c999e56f7ba49e48cb72c76bb7848d4562aa96dbb8c5a3adc19533b00cb2a421fa107b0b956452d -Test: Verify -Message: 64a5d78514c2e26b011e7bca8ae480a2770cb50b03bb6fac29db817c30fb6bb87a68c225898ddb885288bb62c70e43f19f8198646850d15dd08ee5ad30d6d34b595e1395a4593dcb3493f8c98e4825055d454dc87f4249b1537e3067469c869e9cbda24d7cdf602d3f760876fa497fd5498facb15f492d9f4be23c238d05dbaa -Signature: c3a0e8c6df40bb4d672d2438f4f770c141054f1e0b6cd25a0f9d0de138d6c8eb028ae0b23dbd2720 -Test: Verify -Message: c4d9d647a62a699ce00ac9c55b2197a796fd1e8e2120f2d75a50cadf671a9c2c74a8f7db2ec5a549802e81058d1c95f6ee0e78c92ddce79e82f9a3f3cc088ad0d3a2f934bd6661c0ce4327a26402c2c432171036bca8f8da13df464ed36dc31f5a5f942b4a25d55741e07673d8ec556adaae9caec69f5ee387996dca72617e71 -Signature: 1145693d535af4e7b13ed5801c2539db279007dca94800d15c4f2d184c71cf793feab7e46c52121b -Test: Verify -Message: 9981198067ce9d394f53f1233ee06b86075ed7d61142c04f3e54fdcf1ea280f454bf5b76494113c6107a2ae89a76e78e1b356876bc2aeb0582f459257e5b145b368e022d539bdab38d2fae7cd490baa4c1d86b333c74b3b86edd8c25e995cbee1664275ddfd489399eea969746277b00d0c0f8c5e919b09eda88af89b7473ce2 -Signature: 57f2c2fd72f077ef67ceaf46d99753bf796a4712a018b08a786d4c40136256ac0a8618db7dd1eb28 -Test: Verify -Message: bfcbe3e18f4423b9f21b33fadb4763c2e4221126f11b6c79099e6bd9714008000a2fc249edda520144dcacf16c2e3929488e540ee82a03a65c92f723d2dcc6aff61967778bf8eefa46b98a94eb55bc45aaecd9c7bc6fc3d13a8ee4a53de46be03c61cb82a2f8703cae8bc4fa901362b1c2149a6aa440258f5b6a2a76ebae712c -Signature: 5c141ab2f4ee5a513c4ee7e9a5e770f294859b1f6551d44ed78029dbbebe181a73e2726f1b553022 -Test: Verify -Message: 839331e55e6928503c36c0530394dea50f46f78d7bd8fea1ae7894c02a136b4e91b3fbaff91869067196b42fd32e22fbcdf0eaab2b9023af6747ec9f73eddd7bc555ae1fa4e8260ab2844750ba97b8ddbc7773ec3705afc6b68310c09eb20d6f362fa22ef71038d316bad1ae500678c2f594e847386e7c60b6e157194499d4a4 -Signature: 0ad3d7f5ea209ad35ba4a0a17e16483c50f5e4953a692ea71730d7c5c4c13feed38ed90759aa2e86 -Test: Verify -Message: d4fdc830db8cef7540b6b3ab242cfe3bb59004a3f3c61b60a37cda1890fc7108093249ae98f9dcb7ffaad62b79e76dd72fa4fdfbf878e8355523aeadac5f4882c5ecc97583d638d5e309a8aa3a189925ab4a9348e7e601d129c14b6d7005381bff4383dd13bcbba6e4ec6081df583bfe229afee237aa1d0e156eecb05485f9a9 -Signature: 189c08e378bc9feb81891706f80a9fcd1f10725564e3814342937391e39f8830eaed6702b8579e3d -Test: NotVerify -Message: 3fb043ac04c26a1d06fa3f3638e0ab0a218b5a74c36243f4ce1278c606d02b44f1d1027ec6069c17931c6463adb495be5de08e2fc8de583e1f187513085bebd04d579130c4589a607e445f1e33d57110ee17df67f524c4b4fb1f150a896fa955aa3d8afbd6307bb12168c99fa4b957b72c29e45222aca00dba1eefe460827d8c -Signature: 65ab093718776e0b945e5fa24014468ee40422b3688c00beb21593dd4785c90b350e9471a5dff538 -Test: Verify -Message: 155f0682c1d481571fd2d93a6bd70e5e2a6fee3702270f03d7b40d9c2c65057eb8c6521448968747d5ebac49e5a4be9f270f616d49dce8061d4287b4ed6fd7c41c368bd6fef47163f9c3ac8fdce330317f657e209c19a2c1eeba6ace8858e86877072a609cc638c2c3b24fa3086c5d2d6cc7bde8b3b6344b80762c83b4f73082 -Signature: 90e0b86567a2b176a74a817d52009c2bb553eb9ac3694f997c5f70ca3936b6d57f1908868ffc7518 -Test: Verify -Message: 4b03e4a77dd910d51e6c170faa228f3d5c258c96bc44cc986a0d244629292ca62ff8277aab6d353e982bbc62c1e113c815e371812d0916c41ccdb83076a03043a38c651b6511796ba83933c18afdadf6abdc3ef6b6baaab230f6896280d0f50040f97801c37c3456e7cd54a31c2eb3bfb54bcc6c6e0de2583fc270536071d3d3 -Signature: 999adeab789df72dab3c86e115140d0dbb4905adbebe59a1995fbc73fc678a8ca89d7b6cb644569f -Test: Verify -Message: a59d6636f5dc1fbe82ec2df71a90657f5ccbbcf1af6e69157de03b45b42e3c227f53877942c96770d450b1f500fd64683e877e87aece219a56ace7e19d01823b07f9981733a1dea012aa7324697c7fc68a7e0c654fa524cb573b2c1a84f18074b52850eac17cbba7b4932a5e4d24eef1b84b1d62880ba9fff824c2ca63186f26 -Signature: 30f81281e18c995d53f02e6d04eb988bb0b8bd3f1af1a7c8447c704f06d7379dae2ccf95ec13edd9 -Test: NotVerify diff --git a/embeddedcryptopp/TestVectors/dsa_1363.txt b/embeddedcryptopp/TestVectors/dsa_1363.txt deleted file mode 100644 index 712e5ea..0000000 --- a/embeddedcryptopp/TestVectors/dsa_1363.txt +++ /dev/null @@ -1,553 +0,0 @@ -AlgorithmType: Signature -Name: DSA-1363/EMSA1(SHA-1) -Source: generated by Wei Dai using Crypto++ 5.0 -KeyFormat: DER -Comment: 1024-bit DSA key -PrivateKey: \ - 3082014c0201003082012c06072a8648ce3804013082011f02818100bd670f79\ - b0cde98a84fd97e54d5d5c81525a016d222a3986dd7af3f32cde8a9f6564e43a\ - 559a0c9f8bad36cc25330548b347ac158a345631fa90f7b873c36effae2f7823\ - 227a3f580b5dd18304d5932751e743e922eebfbb4289c389d9019c36f96c6b81\ - fffbf20be062182104e3c4b7d02b872d9a21e0fb5f10ded64420951b021509b2\ - 940496d6d9a43bb7ec642c57b302e59b3a515502818100a1c379ba91fe1f9d52\ - 83807b809c698bce4aee6f405f4de8c46becf33c08a63bc5f8088f75b5b6bcfb\ - 0847ccbdee700e4e698652317bbd7a3056404c541136d7332c2b835ef0d1508e\ - f57b437de60675f20f75df0483f242ddeb57efacd180418790f4dec0a8250593\ - ba36f17316580d50db1383ea93a21247650a2e04af904d041702150355dc8843\ - 45c08fb399b23b161831e94dbe61571e -PublicKey: \ - 308201b73082012c06072a8648ce3804013082011f02818100bd670f79b0cde9\ - 8a84fd97e54d5d5c81525a016d222a3986dd7af3f32cde8a9f6564e43a559a0c\ - 9f8bad36cc25330548b347ac158a345631fa90f7b873c36effae2f7823227a3f\ - 580b5dd18304d5932751e743e922eebfbb4289c389d9019c36f96c6b81fffbf2\ - 0be062182104e3c4b7d02b872d9a21e0fb5f10ded64420951b021509b2940496\ - d6d9a43bb7ec642c57b302e59b3a515502818100a1c379ba91fe1f9d5283807b\ - 809c698bce4aee6f405f4de8c46becf33c08a63bc5f8088f75b5b6bcfb0847cc\ - bdee700e4e698652317bbd7a3056404c541136d7332c2b835ef0d1508ef57b43\ - 7de60675f20f75df0483f242ddeb57efacd180418790f4dec0a8250593ba36f1\ - 7316580d50db1383ea93a21247650a2e04af904d03818400028180255cf6b0a3\ - 3f80cab614eafd5f7b2a6d83b3eafe27cd97b77ae70c7b966707d823f0e6aaaa\ - 41dc005aaefd3a0c269e60a665d2642f5d631ff1a3b8701bc06be9c44ab7367f\ - 77fefeec4c5959cd07e50d74a05af60b059ad3fc75249ecf44774b88b46860d9\ - c3fa35d033bcfc7b0b2d48dc180d192d4918cddff4f7ebcdaaa198 -Test: KeyPairValidAndConsistent -Message: 66B92E1E2C44B80F7BFA -Signature: 06418D4F24A8059553951CA062BBD6E0833ED1745608E1158CA4B8F8FE1CD2AF087B5EEE08FCA0D7A63C -Test: Verify -Message: 973266BB0A492248082A -Signature: 02BA236FE800EECABB85698A76B5485865454B3016010755F0E1BF7CE26FB62BE4FD01141F5CA4144811 -Test: Verify -Message: 9A6D079ED0CA9D8B40E8 -Signature: 045BA3DB16E6B910DC89A2D26096625F757D62077D049886B85EBC7500884B4DDD1898BC52746C54F68D -Test: Verify -Message: AA34DCE67BCDAC927DA6 -Signature: 0835C94121313842ABF04D4960E711D1F0904612BC09840989EEAFF2071522B75957DEAC801574BD22EB -Test: Verify -Message: 4EDAC08816AFDBF284DA -Signature: 08E1574E5299C910694D17075136F41EBD558D1B1805CAA3B6E98DCCC3702F286E76BBD29435CA2CEA5C -Test: Verify -Message: D82F2E903230962B8174 -Signature: 0366F1AE94FD2CDEBA4EE879BB8923F0E49CFB921008E6A5C7457E88811D46DC7F297D6A96E909268244 -Test: Verify -Comment: 1025-bit DSA key -PrivateKey: \ - 3082014c0201003082012c06072a8648ce3804013082011f028181017310bf02\ - d70ef2cee45d1cc47ec8ce8cabdd6bf32a560975a42ef057bf9dfd553bc9368d\ - db154a55d855edaa755e69f511a4c69ba78571cc4b14ddbb0f32a4a9c56c2863\ - 05aa21ec4e35de7390747477b3bd574e7b87cbebde2f665703137a1172350ad2\ - f48a0884d076ada9db82f104e6b0ad86693cd4adbd0067639102fcf102150b39\ - 49dadf3196f08bca0606f06443afce2fb1d02f028181015f0f6d1729ef2af723\ - c00e36450a04c7e7681d65b74a6417a53b3eb6036989eff8e0ab11a7ec3ce234\ - 0b7c7a92e1a977aee52555c06c12c4cc28496ddc2598feeb7539ce90d3888e21\ - f61d7f14746cf67d9fed373afd97e2483700e300ed9da25e7200b363a4727ad2\ - 01194b36ea5f816cf83488c3e527d3a5515870d2da63d6041702150696b0f255\ - 468b7ac18e11632f208ca86383a46724 -PublicKey: \ - 308201b73082012c06072a8648ce3804013082011f028181017310bf02d70ef2\ - cee45d1cc47ec8ce8cabdd6bf32a560975a42ef057bf9dfd553bc9368ddb154a\ - 55d855edaa755e69f511a4c69ba78571cc4b14ddbb0f32a4a9c56c286305aa21\ - ec4e35de7390747477b3bd574e7b87cbebde2f665703137a1172350ad2f48a08\ - 84d076ada9db82f104e6b0ad86693cd4adbd0067639102fcf102150b3949dadf\ - 3196f08bca0606f06443afce2fb1d02f028181015f0f6d1729ef2af723c00e36\ - 450a04c7e7681d65b74a6417a53b3eb6036989eff8e0ab11a7ec3ce2340b7c7a\ - 92e1a977aee52555c06c12c4cc28496ddc2598feeb7539ce90d3888e21f61d7f\ - 14746cf67d9fed373afd97e2483700e300ed9da25e7200b363a4727ad201194b\ - 36ea5f816cf83488c3e527d3a5515870d2da63d60381840002818045bf83e62f\ - 50190374b23de5e4a1d0278e9e8e6c8335577d62e80662a380c206e326819c50\ - 82d321dfda1f905fa5a3ead9a2dc769885a27b1fd6a133185dc5a7876a76ab0a\ - 09fe02b7071a924169e4d2d2a67e67ed3628800134183b962c0b313463aa154e\ - 6437d644e025ab234e63d19c129842a61c5e5ea5a06466c858c81c -Test: KeyPairValidAndConsistent -Message: 2F585D0CE4FA1CD93880 -Signature: 0643ABF8D3C2F4BAB02CF79D698948A1A416BEC05D00F33CC3D41CA9117E6CD99E5DCBBD4425DA12E98E -Test: Verify -Message: 4F09A1F217B8393199EE -Signature: 052DE620B5628EECCF7C56410CAC2B72A5AD1B5A67072ABF369453BC28A386ACD5939C9985C09338FD03 -Test: Verify -Message: 03D7110A753B008A76A0 -Signature: 01D44D16B5FDFB8C39AACEA72391A889EECBFFB5E701EB8F46E4FAB96326F73E0CC698E1F66C32FE5C2E -Test: Verify -Message: 129F4781D417671F886D -Signature: 00CE142CE967BA951B9DE26DEFB5B341CB49247C1308515315449B5533ED469B6470C4E3A3751E35E7BB -Test: Verify -Message: 3E1594F559D1248D1112 -Signature: 07B192657E256B60567BF6EB399D8A2DE8FFF7AE8A031A655BEC911A82049155CDB4F2A76A8004AE646D -Test: Verify -Message: D6F0354F1B6B253B6997 -Signature: 07FE18E0C00F6AC3CBCB95874AB66A98E34DF74F37059178C920C5D13CE173B8D2832310B9587940F6D9 -Test: Verify -Comment: 1026-bit DSA key -PrivateKey: \ - 3082014c0201003082012c06072a8648ce3804013082011f0281810250988282\ - 17d00108030801e5f135fc6fd3010be39e49060a96addc8a081198803402c4b4\ - 6e4ce0750fcbab8cf084c7ca8cae09f1b5482d336fa3af47b96791d02d8143e2\ - 74b1325f2213e17f9384c805f479e52a3117cf84869d395f1bc025c918484478\ - d2da1880d32bc519f4e6b2fd2d46958795550ce1765f725626f3fc17021536bb\ - 68cd95dab195f14c4534283e7ea50b00cc31a302818100e2782ad6992f4b7e88\ - 787b4d616744b60e095575a177569c4a069e311e38b7240c43343367e23574c3\ - 0e4d9f05afe1fbe61423bab715915c4ccf28aa0ed2f52b092b86c8ec1f9d4795\ - d6e91c88ba41297625c11a9e1f4f182da13cf51e541038a1266bf32b2dd81ecd\ - 84bb80be8fdf97689942e944b7fbb6981e00cd680ee25f041702152db270c284\ - 328353f979cad99f4133c53acaa6ee71 -PublicKey: \ - 308201b83082012c06072a8648ce3804013082011f028181025098828217d001\ - 08030801e5f135fc6fd3010be39e49060a96addc8a081198803402c4b46e4ce0\ - 750fcbab8cf084c7ca8cae09f1b5482d336fa3af47b96791d02d8143e274b132\ - 5f2213e17f9384c805f479e52a3117cf84869d395f1bc025c918484478d2da18\ - 80d32bc519f4e6b2fd2d46958795550ce1765f725626f3fc17021536bb68cd95\ - dab195f14c4534283e7ea50b00cc31a302818100e2782ad6992f4b7e88787b4d\ - 616744b60e095575a177569c4a069e311e38b7240c43343367e23574c30e4d9f\ - 05afe1fbe61423bab715915c4ccf28aa0ed2f52b092b86c8ec1f9d4795d6e91c\ - 88ba41297625c11a9e1f4f182da13cf51e541038a1266bf32b2dd81ecd84bb80\ - be8fdf97689942e944b7fbb6981e00cd680ee25f038185000281810179b283f6\ - 7868aeded3a0c5633d0e6c18fad77174e2c89c03452593d05e77a9fb029c0ccb\ - 2b6f2328e79c286ee392713f12d9d45578348383b81d11b0e0f7e89965a7785d\ - 5ab64ea25bb73e8acaa8e84cb9897985015757a48c0b1dac3a6a606fe671ea07\ - 3ec434a46f227b8d4b02a46fbba2f6c6216736d669f55778d81004d8 -Test: KeyPairValidAndConsistent -Message: 7E4F2ED4E79062778A2D -Signature: 03DF91D560884BAA90258F0F78A7AB61F9A4A5CF3D363E8DE2EAAB389B9492C2B80C44509BF2372BDEE0 -Test: Verify -Message: A0E35846B5CF1B5BF560 -Signature: 21DF9C60877B6D7F531AAF1C39122779436029685109B2D736A45F51A80099041AA5F118D7D6025AD30E -Test: Verify -Message: 3B138785EFC6F520EAE0 -Signature: 10A38520BAC07202DD1CB5A9C88B15B9579B9A1344025E4C4B9D1BC3AAA8C97AA90121D52E42E59A0A99 -Test: Verify -Message: 0F6BE2AA764B485145D4 -Signature: 0233267173F284737B68D15A500D23F3C86988E3DB28DD55AE3DFEAAA7251D354CB44315D6024CBE3E36 -Test: Verify -Message: 6CD9FBD23EA58826FB04 -Signature: 15A1B0DDA6BDB62D96AC557E3F1F24DCAD0C51EF3523B01EA2A8FD93761D0E4D070BA6352A81F31B776A -Test: Verify -Message: 473A82649565109E9E89 -Signature: 1FE31C3A3EF6F57DE2586A5F2EBD48A5C707092D230E1D217EE0A752EFD9ACA8BF0B9EE9424184B8F8F2 -Test: Verify -Comment: 1027-bit DSA key -PrivateKey: \ - 3082014c0201003082012c06072a8648ce3804013082011f028181055402a8ab\ - e9cda3072ca8601d68032651feb0335856e57f8f8d4ec949098a6459151cefee\ - f91b7aa733668c8cf0e9b96c93c61f3528d4036daa6565646f65d74c4552817d\ - f7e5fb1cc421cfd885e27bb811ad227e81b3fa02f7a00bf01ee6e23fb5572a75\ - f8f29b58bd5f7db435e8a92a923f15d50f34213d29816921bf195b2d0215291d\ - 0ba731a4303070504d8b9615640a5e1345e00f028181051c9d0270b69ceef82a\ - f5aed5f91dc88d585096609d835d03d39cf3ce74f5a3402d4e8e192455493da6\ - 1cc58ee6f54dd941172be3d7642169cbc52273f4b725f1d6c820c3333336c64d\ - 32fb6238121b3ccb7c71b847764946bb0887a44ca9de802cda62efa9dda57375\ - 1084225353f11ed837f3dc25de8374b6fdbfb6e313e46d0417021513b27094d9\ - a5a3a9704cebdbe890da325fa26ad555 -PublicKey: \ - 308201b83082012c06072a8648ce3804013082011f028181055402a8abe9cda3\ - 072ca8601d68032651feb0335856e57f8f8d4ec949098a6459151cefeef91b7a\ - a733668c8cf0e9b96c93c61f3528d4036daa6565646f65d74c4552817df7e5fb\ - 1cc421cfd885e27bb811ad227e81b3fa02f7a00bf01ee6e23fb5572a75f8f29b\ - 58bd5f7db435e8a92a923f15d50f34213d29816921bf195b2d0215291d0ba731\ - a4303070504d8b9615640a5e1345e00f028181051c9d0270b69ceef82af5aed5\ - f91dc88d585096609d835d03d39cf3ce74f5a3402d4e8e192455493da61cc58e\ - e6f54dd941172be3d7642169cbc52273f4b725f1d6c820c3333336c64d32fb62\ - 38121b3ccb7c71b847764946bb0887a44ca9de802cda62efa9dda57375108422\ - 5353f11ed837f3dc25de8374b6fdbfb6e313e46d0381850002818103b06b9909\ - 7cd7145c7d7782b02e247a4741f3c7f39233627f17e13ebff89a18cad6a454c3\ - f32f7ef2910384030da71ae47e1c3fa79c2141dad107f8e715e47fb0bb626baa\ - fc35db769852ebbec2d339c3c3d5f2287cfdd20b3b78ea4607086c42558ae463\ - 7eddd6a74bc1072d0f34d9c0130cbc9e84f537e7ce50df502d17b5c3 -Test: KeyPairValidAndConsistent -Message: AE6DCD9535AEEE3ECC89 -Signature: 1BB090DC4573AA79F34181020C4D5B582BBA67062C23E5DD6913CE91482A05716784BA680F7F4AC1684B -Test: Verify -Message: C83A14EAC016D659F9FE -Signature: 182AC27BC4B77B145BF90E73A2CEEC5325941507F925279DF5B6280664CE82248348C3EDC59DCD428B64 -Test: Verify -Message: 745E02041EB487D16CE6 -Signature: 13C4F9AC03EA094CF7F60B96CAAA29053706E93DEC1024EAA1606E13B2C3062F2D6082846D29E6E60829 -Test: Verify -Message: 62F019655A83501FC4E7 -Signature: 077E19089B0BB32A7B21B0D27218C6E1F14AD432181BB76FF5E7EC35EC01CA47595F4C7ABB8ABD6064A9 -Test: Verify -Message: 351D37A4B5046E885EAA -Signature: 21962B09FF030A41251AD592F8D2AF24144B3AC713245AF18BE28F192FD29326D91F12A76A01477C8788 -Test: Verify -Message: 4073D33915F595F4FF9D -Signature: 1F4CF158E806AFE59139E2A9840BCEF79237800C521E49B7DBDF9830C86E7653FC716B43224EA00C883F -Test: Verify -Comment: 1028-bit DSA key -PrivateKey: \ - 3082014c0201003082012c06072a8648ce3804013082011f0281810abdeff64b\ - 6f28256e4562109bffed29cb5aa95d89cc0ec95da0e773dbff3467c271bbb1e1\ - fbb6af058517fdacdf26b5919674c625eced6317d8631c063f43b3ade2cd633d\ - 554913339071d6ebed5fd665fc5dd7d47b80721a976c3b14fbd253f0f988c354\ - 725289f2897df0a15985c92b2d4da8d087870c251c72d979b8304d5102152368\ - e2b864b250ad45406391e7eeaa3d27cd053c2b02818107c325695dfe315a77ad\ - 7b42f0d18f9d4821b5c153fee7385877602fa54477bb8c0639d2438f34352b97\ - c22d02a7295d2b53d5286a01caa919d6283614690624240af922675ccd4a0534\ - ec336cb79cde31b02b5988cc5a53ca17790d67d803a27bb927b9c59bdc6ac794\ - 175e285cafdece6778ab19a0b444747fee20d5bf929e70041702150771305163\ - 506b2b83bd5279935df1b5fcf180b004 -PublicKey: \ - 308201b83082012c06072a8648ce3804013082011f0281810abdeff64b6f2825\ - 6e4562109bffed29cb5aa95d89cc0ec95da0e773dbff3467c271bbb1e1fbb6af\ - 058517fdacdf26b5919674c625eced6317d8631c063f43b3ade2cd633d554913\ - 339071d6ebed5fd665fc5dd7d47b80721a976c3b14fbd253f0f988c354725289\ - f2897df0a15985c92b2d4da8d087870c251c72d979b8304d5102152368e2b864\ - b250ad45406391e7eeaa3d27cd053c2b02818107c325695dfe315a77ad7b42f0\ - d18f9d4821b5c153fee7385877602fa54477bb8c0639d2438f34352b97c22d02\ - a7295d2b53d5286a01caa919d6283614690624240af922675ccd4a0534ec336c\ - b79cde31b02b5988cc5a53ca17790d67d803a27bb927b9c59bdc6ac794175e28\ - 5cafdece6778ab19a0b444747fee20d5bf929e7003818500028181043e4ae624\ - 4408879264fe6b859b578218705b9a45af22efded27141b7f090cbcbe42dcf48\ - 1df3e41b13920ae02b694eaa6bfd62f2d3c5d677b8c4ce783cbe2789e088b044\ - 89ef535ad4a517351c8835cf128f7ec677a1b1dbe3ae9cc4198ddb6e1cef8e97\ - 8c0725f5063797bc43eb9ae496286cccbad5d4e026e9edb997d2f918 -Test: KeyPairValidAndConsistent -Message: 4867852C83F181CDD010 -Signature: 1D0F4F49AFA0448163604847C9308A824ECE928E05066D47892256DB725FCB31F93F38B9E02C71E100EE -Test: Verify -Message: DA6493C86D6B62C5961C -Signature: 1BB4A8A1B8D81EEE9AB291C49F688F27D2191EA51B15A5DA66A6367D931DAB338E595C80E70CEE4BB644 -Test: Verify -Message: AE2C1136BFE966794A6C -Signature: 02AFAB91234D08FCEC22E57AB5718FBF41A86D2469012F8476BFCF4EA4E03D9F7A6E467ABDD0B5626784 -Test: Verify -Message: B20160E0442E726BE749 -Signature: 140A45F4933F05807A533628962E42A8BEFAF5977917F2A8D8706B8BE83EE6B6CEBCC951553B4E3203B5 -Test: Verify -Message: 3638935C4492F5CA42F2 -Signature: 234F78EF68343E77710E17285E47994AB599F3646315C37B8CC01CF6BE9C803D6B81B232DE9171DA7967 -Test: Verify -Message: DFB674CA6E0FDC0CBE99 -Signature: 1DF9B1B9F78F5FCCCCC5F698EDDBC8EB28C0F4D10002A052284AA4FBA601D3047E3AA97F8CF73731A44B -Test: Verify -Comment: 1029-bit DSA key -PrivateKey: \ - 3082014c0201003082012c06072a8648ce3804013082011f0281811d0f176b67\ - 99b36724c92954c38d0288fa95400c2b14e064f76a6338fccaebca8d978b93bb\ - 76507bc150a50f9fe799fffe12ae2875b13ac1084ffcfde9f62b86185a72f04f\ - f80538d6eac177edc98d61a517b1275bcf4b57aa262e1702d623bc344db7e562\ - 1c949a9b12e9936e88fae9b200a1f8ad5b40ec8220aa301267f38dd702153357\ - 536531dec150be0ef8747f69ea30d987ff7df1028181067dd80dbc6b41f58d08\ - f077a9a3dcbfe12a62065fe6b4691c457f506b56dcab0433b3aad6ef96250163\ - 3d0f3947b491a1317e7e6b632f062c53104d609c9222b056f08a0c83662a7074\ - 4331fd09b2b42fb0768e52da27e92732106fbd41ec737373fd080b56b543d808\ - d49eeb6e1bb0a8619b1edee8fb8295dc042423f684af8a041702152dcdc00a86\ - ecc2a60ebfa6660a83af1d7c3e570b85 -PublicKey: \ - 308201b83082012c06072a8648ce3804013082011f0281811d0f176b6799b367\ - 24c92954c38d0288fa95400c2b14e064f76a6338fccaebca8d978b93bb76507b\ - c150a50f9fe799fffe12ae2875b13ac1084ffcfde9f62b86185a72f04ff80538\ - d6eac177edc98d61a517b1275bcf4b57aa262e1702d623bc344db7e5621c949a\ - 9b12e9936e88fae9b200a1f8ad5b40ec8220aa301267f38dd702153357536531\ - dec150be0ef8747f69ea30d987ff7df1028181067dd80dbc6b41f58d08f077a9\ - a3dcbfe12a62065fe6b4691c457f506b56dcab0433b3aad6ef962501633d0f39\ - 47b491a1317e7e6b632f062c53104d609c9222b056f08a0c83662a70744331fd\ - 09b2b42fb0768e52da27e92732106fbd41ec737373fd080b56b543d808d49eeb\ - 6e1bb0a8619b1edee8fb8295dc042423f684af8a0381850002818113834f0fa1\ - f42abf7dbd264cb7d2eb5798da8972df67f517c62d7ae5070fd588d61db62e49\ - 2f9654833e876ed5737df35069f5ee01a45de881d8f5e68ec52ad9ef32780e8c\ - 453a5f1e38cc17bc5cd061a3c122080f6e1b82d31877e8b08f634f497bd90b06\ - 824eaa0416c64104ce5622c272673d0dedb836ac7d47e0cea0673902 -Test: KeyPairValidAndConsistent -Message: 1E34034C47FE533F8FF5 -Signature: 04E171B845E602A871CD5DACA5738BC4585A452A86108D03D70C3D2D605FAE90DB8D339AADB692EB1ABE -Test: Verify -Message: 53D2CA23AF7DF95634F0 -Signature: 1327D4C32DFB874EA2104A9B30EAF288C7016146D1217C237E0201482E483EBC7F0A713748547F9B6B21 -Test: Verify -Message: 0F056E08AE77B3B30F33 -Signature: 1B4A688745F3D86B0D8A5D97FFA0E31C322EFAAD0A0FCD907B2D49EB8150539E81FF29341EC34440425C -Test: Verify -Message: F08C80E8FD38A3867B76 -Signature: 0972705B5E84A8BA57226C770CCB0ECDEBC816EA162FCB3BA5B3C235105EA75F379EE84187E27A86D21D -Test: Verify -Message: 6D392690B92B3E75020F -Signature: 185968475C67C936CB152F76E80EE22FB82A27ED120C5C0ADB2D750D2C38F0A9671EBFEC2815F675C24C -Test: Verify -Message: 10AE0E091A267641FACF -Signature: 1AC3C2010BFB10CA6889120A23F984FE0D4CF79D1B07578217E5A3C68EDF05006C1F3F1BFB3848E4ECE5 -Test: Verify -Comment: 1030-bit DSA key -PrivateKey: \ - 3082014c0201003082012c06072a8648ce3804013082011f0281812a32d68d31\ - 248024053bf628a94404b9a49d91ade4d7a45b071e93292a7f8c2661d9165f0a\ - b85491d4b0dc67d335fa7d7dd172cb17193390a55eb000aa97e2b8ed3ee64b73\ - aa43ea9b8979132c2d966ab03c42cc14782c96e4284ee1136b8515007ed1b1a5\ - 708b5e8d81304fa651edc715918e2299cfe9016dfec5f454d907f59f021527c7\ - 996c1d3729c4cf1de06529e5619771e27ad9eb0281810d87a4b01385da7f43b6\ - 277933c5f0dc8072dcacd5252e1b29f588114a7ac56e377050aa8174b5dda400\ - f043234e4a746442792734dc80274a00a3676101be94759fc2630b9a85896648\ - 8b12611d03d0b31e7243e124497a754544cee1db10bb0a81cf0b2a68045b76fe\ - 935f641c666fdc788a2b968c6668c669115756b961d9fe04170215091155581e\ - cb7a0a792ba95c772d9382298bfdfa6f -PublicKey: \ - 308201b83082012c06072a8648ce3804013082011f0281812a32d68d31248024\ - 053bf628a94404b9a49d91ade4d7a45b071e93292a7f8c2661d9165f0ab85491\ - d4b0dc67d335fa7d7dd172cb17193390a55eb000aa97e2b8ed3ee64b73aa43ea\ - 9b8979132c2d966ab03c42cc14782c96e4284ee1136b8515007ed1b1a5708b5e\ - 8d81304fa651edc715918e2299cfe9016dfec5f454d907f59f021527c7996c1d\ - 3729c4cf1de06529e5619771e27ad9eb0281810d87a4b01385da7f43b6277933\ - c5f0dc8072dcacd5252e1b29f588114a7ac56e377050aa8174b5dda400f04323\ - 4e4a746442792734dc80274a00a3676101be94759fc2630b9a858966488b1261\ - 1d03d0b31e7243e124497a754544cee1db10bb0a81cf0b2a68045b76fe935f64\ - 1c666fdc788a2b968c6668c669115756b961d9fe038185000281810d7d22c931\ - 422fc46505887559a51490c2e367cdb40242cdbaeb23024693fd5c68f6a3307c\ - a34b224457d5aa610b90eca3b39905481daaba7151318f09f974ad664546d14c\ - 87f797e38139ee1e07adba9c775e07b7f7b3edba87d886920d6b2cef5f084359\ - 566b0a3b8b940a65b9ad93fd7ccd1354cdcee3c43c6bd315180498ad -Test: KeyPairValidAndConsistent -Message: 23EEE1D0EA8950B8F322 -Signature: 1800356929B316D1E4FA886CAE0CAD56E32506522D0B8440BB7695D522F31CD87079BEA4CA9F18ED4288 -Test: Verify -Message: 13FA6F2816FB83190A21 -Signature: 207830C2DE87296BC39CD21630F26228F00CF60BC3150CBC82CFA9006534A6C5E354AA281C434A8C2077 -Test: Verify -Message: D071CCC0C6E4CAE82E5A -Signature: 054C9C0C30C6B73AAB9E54C11D4EFC82BD6E8680932501D78A58EE305930E72ACD3BB2565023455DEAEA -Test: Verify -Message: 22CE83F4803BF3EA2C48 -Signature: 07065A6F5C9A086CB83F2F113895730C1B2FE0DCD90FD6AA887B066D685D3DD6C3C0D95CB8C8A48FBFF1 -Test: Verify -Message: 7A927EC7BB9CA16C1B0A -Signature: 24BF344DC7B25F831428078AC0D929A72A29160B6205A1BD4B1B2C5BD8BEFCB650DE23652701DDD4F4EF -Test: Verify -Message: 9591B069993E10BC0B84 -Signature: 0E6E6BF91BBC9FB91FCD3CE32907F5B6AB5E88928C1E3BC92649EDFDFE672AFB654C765F2758DE4BD78F -Test: Verify -Comment: 1031-bit DSA key -PrivateKey: \ - 3082014c0201003082012c06072a8648ce3804013082011f0281814d58515f7b\ - 41c4fc87e4fcefe5cf6d84b2d74a9d6f498ae9605fcbf1c59217422001a272ef\ - 91dbd09e7af5ee54126dd4fc44bb1ed624d0dd5dafb984d52781140bba40600c\ - bd4752d2c32b43253efee57af6964c339570edb24195502e6d424b84bed65ac9\ - 8c6fc52ec90e40a525f1863a53f2fbe2a0a133342eff4337f26ceb93021526f8\ - 6a81a6bb530c2f9b63e3690e95a0894575f4450281811e24828adb4ebf2becdb\ - dcadf6706631293ad6566803d12479f04a7bb20b6086fe81df164f8bd02c5f41\ - 8c1140d143f11a71170b42d0753c952bfff951b9ca4204868375efaa4afad50b\ - 75787e41c5ab9ce8adcbccecd3716f350bb8aaeca9b6098bd0002d789e1f7db9\ - c19d9045499877b93ecb4e7c64808b742063bbecf60e29041702150e61a054ee\ - 6510734a80f67a54d8c4151c957ef16f -PublicKey: \ - 308201b83082012c06072a8648ce3804013082011f0281814d58515f7b41c4fc\ - 87e4fcefe5cf6d84b2d74a9d6f498ae9605fcbf1c59217422001a272ef91dbd0\ - 9e7af5ee54126dd4fc44bb1ed624d0dd5dafb984d52781140bba40600cbd4752\ - d2c32b43253efee57af6964c339570edb24195502e6d424b84bed65ac98c6fc5\ - 2ec90e40a525f1863a53f2fbe2a0a133342eff4337f26ceb93021526f86a81a6\ - bb530c2f9b63e3690e95a0894575f4450281811e24828adb4ebf2becdbdcadf6\ - 706631293ad6566803d12479f04a7bb20b6086fe81df164f8bd02c5f418c1140\ - d143f11a71170b42d0753c952bfff951b9ca4204868375efaa4afad50b75787e\ - 41c5ab9ce8adcbccecd3716f350bb8aaeca9b6098bd0002d789e1f7db9c19d90\ - 45499877b93ecb4e7c64808b742063bbecf60e290381850002818119b50f1eea\ - 45bfaa22352a38f3c3b86d6f670747ac2fd94359608e25f2bb9f602506bc3572\ - 45deeb4c3c702d435c557da4f4a9fd37330a75547c91681fdbb51f286adb498d\ - 1e489e89b2e6a4eb9ff30222c51fefbeac7435f629f536ac2d6b87664d80e5c9\ - 7398cf489a1d1ca217f7f21ea8e409f938378875cf5f528162e3bc07 -Test: KeyPairValidAndConsistent -Message: B4B3C8FBE82013228A21 -Signature: 0E08FE696A4C70B16A127CAE8C61E5B38B7A1F34402584D1F21F71016054E820E3B1BB866309D93A7DA5 -Test: Verify -Message: 17D2D18302173E2CE992 -Signature: 0203C3869E15F8847B58BD158CB746433AA05F201317C0541908ACD5EA78A02D1FAB79380619199CC5B8 -Test: Verify -Message: 8032AE177D6DF38C7E27 -Signature: 1F436F5BC73A3402221B539F1D7CCBD4C3AE948418216122809E062ACF5D6086546FCBB293B4C7510CBD -Test: Verify -Message: 768640A60A3C62E02428 -Signature: 0A5D52C534A9BF1175247538638077489537025975254955F8A96B0CA2E7985D5D6E3DD54EE298C90100 -Test: Verify -Message: B0999CA45B77ED63639D -Signature: 144DDD0C1BE6D96FC3AFFA240FCD6D2AD0748C848F0C8A25AE8AC2E55A38DE9DBBAFF90CF464547365E2 -Test: Verify -Message: 587EDB968FA82C12C930 -Signature: 01FC4F6F98898F3639E8D93E7C2E6F3945120AD19D15EA13EDC96BED7E73A7D5D161217F1C67F3048BE3 -Test: Verify -Comment: 1032-bit DSA key -PrivateKey: \ - 3082014e0201003082012e06072a8648ce3804013082012102818200d551680a\ - 62ebf98f0ed8930cc5b12de86d0a0c29a0d7e5524c24672a25428833f4c19ac8\ - 83ead22efcc0c6823f2e942c17adb7ab763ff2c7cc2698fa8b6448e514d4628b\ - 197721bdaec780e126ac80ac83f24fef5c154f7690ceba903748be5212e3180e\ - a718ca7a71a49dee939bf9bc5b7845c9648d074587ccd3724493b91f0902152e\ - 802b5369c3f1ddfa789bf8f2ad2e048ced3bf35502818200a9aebee7d29f90b0\ - 81afc4d496a6a78210e918bb57a8a21c5995586c0bf20f7a56bb10a97e05a3a7\ - 23e7db64612b12bb591b1fe7d2e46be8c96a7b2ce7c66076aeded938775ae222\ - 3900adaf52a93f52d62173c82d4b67388c85d4c1127e1edf4643cf09f5375b60\ - c19316c4f8f8fd7daea1d8b44a2d03e97c2741537f63d86b4a041702150f66e0\ - 4c5a75d3eac03d744e5432f23e3aea066a63 -PublicKey: \ - 308201ba3082012e06072a8648ce3804013082012102818200d551680a62ebf9\ - 8f0ed8930cc5b12de86d0a0c29a0d7e5524c24672a25428833f4c19ac883ead2\ - 2efcc0c6823f2e942c17adb7ab763ff2c7cc2698fa8b6448e514d4628b197721\ - bdaec780e126ac80ac83f24fef5c154f7690ceba903748be5212e3180ea718ca\ - 7a71a49dee939bf9bc5b7845c9648d074587ccd3724493b91f0902152e802b53\ - 69c3f1ddfa789bf8f2ad2e048ced3bf35502818200a9aebee7d29f90b081afc4\ - d496a6a78210e918bb57a8a21c5995586c0bf20f7a56bb10a97e05a3a723e7db\ - 64612b12bb591b1fe7d2e46be8c96a7b2ce7c66076aeded938775ae2223900ad\ - af52a93f52d62173c82d4b67388c85d4c1127e1edf4643cf09f5375b60c19316\ - c4f8f8fd7daea1d8b44a2d03e97c2741537f63d86b4a038185000281812640c1\ - 88055329f0b44aaf80f82f7fc7f0e421031834dfbd1fb6d6af6ab3e1c173c901\ - 370a4ce2793c1b88d12f764c58ff064905da9c5001f679c7508972f237bccca5\ - 6524787466a7c9c2d6bb6392963008ed1a3e4cf3b13e66086bce3a4ca04d8cab\ - cf0cadb4c403c7d02a858460d04350e730289cb5adf200b5fdf1198168b5 -Test: KeyPairValidAndConsistent -Message: 909068BEFFA43331FDC7 -Signature: 2CCCFF8A67073E5DF643B61A5AE7A5BC216FE267E713B9005F69797B44ECD33BA5DD87461B5C72C50390 -Test: Verify -Message: AC8AFC7A1D9105539E10 -Signature: 0A2BEB58D806EECDDCBD590EBE4AE5AE7BDA326EA0072ADB9FA6A6FEBF40488C80690A2B1DF141BACF91 -Test: Verify -Message: 310E40311BB3F77F9483 -Signature: 28726153B52FE75F1FAA4C97124EE042065D2C90B50B43F885FC45C42C3ED9BDC4EC2D36A2799A041C67 -Test: Verify -Message: 35455ABD53E6FB11ED9B -Signature: 15B3D6ACA9EAD5AA1501ED201335AF9B46657A4CBF00D19328018D82624D4BD9B22D645429B385DADBCA -Test: Verify -Message: 95FFA73B52F0D06A0C1E -Signature: 2904FA8F78B6DF0D15A08714C8F86B97532A9D13B617EC03F329DA20E42816CCF45DBACB432B1F5011C8 -Test: Verify -Message: 1E9934125DA6E9B4E975 -Signature: 1666A3B9DBE26F2AE3F9BF7CBF47989D87AF82F580147BEC8350E21D4DB0691074F63B85A3A7D8E82A8D -Test: Verify -Comment: 1536-bit DSA key -PrivateKey: \ - 308201d4020100308201b006072a8648ce380401308201a30281c100fada6e4b\ - ecef964a85caf9e129639a5616ac000dbac59bd50b84bc8d464114079c34c5b5\ - 8d7d40027faaf037c6a649c527cb002d3a716bdef62b6c94d7a47a8b65c2ebac\ - 05da09e40cdc417024cccba267a98f4eb69701a276b4f117662b566605c36054\ - e7f015d2e5f81331e5666ec17ebf71907788b40cbcea0f24aaffb029ef5c25c5\ - 5ae998f28a2ddb091d262c32ad324f4e64c7b4b50a19e9d92f6d8024188627cf\ - 5ce68674e7ec7da38fd6cf4ec29a6ce2f17e3188d8ef6b0e50d77d5b0219232c\ - f9bee9d56c8bd8252d1edb59d99c40cf32d07d9e5a48930281c100f028143e3f\ - 9d1317aafb814215ffda9c584da8943e96212c90a082c3d2f335e8a6b64d1c89\ - 0aa2224ebf158bec2b6fe6bad236417acd517a4907331e0be0dd0b801218ac27\ - 0acdd45579290be1b94bc418b8f82c651d82a19d2f0e1cbb0fbc0f054d95150a\ - f96f9a7488010787a799c544883ff76a4e3092f2ca9aa9000cecb88dda343c97\ - 2c8192a83820727b1945c1a270cf913ab932457e8e6e207d06cd0efdf265b762\ - b9fa15c9a14633af17204ba2b755ed1b3b421ac596a2a04e64be43041b02191d\ - 4cedc87d55eea31bd702139b90be08d58692a1f97628a01b -PublicKey: \ - 3082027c308201b006072a8648ce380401308201a30281c100fada6e4becef96\ - 4a85caf9e129639a5616ac000dbac59bd50b84bc8d464114079c34c5b58d7d40\ - 027faaf037c6a649c527cb002d3a716bdef62b6c94d7a47a8b65c2ebac05da09\ - e40cdc417024cccba267a98f4eb69701a276b4f117662b566605c36054e7f015\ - d2e5f81331e5666ec17ebf71907788b40cbcea0f24aaffb029ef5c25c55ae998\ - f28a2ddb091d262c32ad324f4e64c7b4b50a19e9d92f6d8024188627cf5ce686\ - 74e7ec7da38fd6cf4ec29a6ce2f17e3188d8ef6b0e50d77d5b0219232cf9bee9\ - d56c8bd8252d1edb59d99c40cf32d07d9e5a48930281c100f028143e3f9d1317\ - aafb814215ffda9c584da8943e96212c90a082c3d2f335e8a6b64d1c890aa222\ - 4ebf158bec2b6fe6bad236417acd517a4907331e0be0dd0b801218ac270acdd4\ - 5579290be1b94bc418b8f82c651d82a19d2f0e1cbb0fbc0f054d95150af96f9a\ - 7488010787a799c544883ff76a4e3092f2ca9aa9000cecb88dda343c972c8192\ - a83820727b1945c1a270cf913ab932457e8e6e207d06cd0efdf265b762b9fa15\ - c9a14633af17204ba2b755ed1b3b421ac596a2a04e64be430381c5000281c100\ - 819c8cedb9c014aa577e9046b90795accbebe81bef68b1b5c37c68cb357e1a5f\ - f92761bc26cb0953956b6c0aec05acfc9d1a27c50789793b13d9eaf2361760c9\ - 7a7d86e7d922f4809a5d2d01448e938190bbc24c150e03ef8305365ddbf5ca19\ - 6857314e3b3023f8ddc9d209bd7dad1ee763e7003fd1b0c53057d2e9acadd23a\ - a18f83d20143bc41a2dfa4a164c82621fc0f800052ec01bec7c99c66fe20ec57\ - 67e6fbbe8810cd5aa75eff3d8a4cb53e1259ebcfebcc2fcf21ba7f3589cd525a -Test: KeyPairValidAndConsistent -Message: 9F6DC301DF53FE22CAC0 -Signature: 15B22111FEFA4AC1E53F2FEC346559E3613BB94F7BB3E2B7551D8B982FA10C38E7F182834DFC7391155FFA42AB945A29E118 -Test: Verify -Message: 2D7B5B9A27EAB468331E -Signature: 029EEA97097FE926DD09821284BCA3F45750B1F8102380D20100596D914DBF6BEFBE1B7A938E3AA5D656B6FD99E8EEE7C606 -Test: Verify -Message: F552FCBBA04FFCCC5CB6 -Signature: 115DE3CC1553CD5E4D40CCED80146DB1D76C10D992AACBCBCB05375C5FDA9F65B9A19DF7E51E6A36A3F2830AEA433AFD4F8B -Test: Verify -Message: 0D52B894153A4BB74068 -Signature: 0F6B8CC28D82E22B9B87D62CFF5C7B2289BB2F8008C42F105B2322CF95BC6D443A9D89A292F482490D94693A44DDF7AC4BD3 -Test: Verify -Message: 294442E103CC0CBA32A6 -Signature: 0FBD8768A18C2B28CE95775AD734157C34C1C3961C1DBBAFDD0A3E92A312A7925AFC9F7F4760FB0C56B42A2042C6B8B37C0E -Test: Verify -Message: E993D8FE1E6F6C3914ED -Signature: 0559D66BAC906C607BBA769AAFEB93E9AEC55FDD4597E432870CDC8A3DF9778301A0B218C886F6B08A414C51BD2F8214201A -Test: Verify -Comment: 2048-bit DSA key -PrivateKey: \ - 3082025d0201003082023506072a8648ce3804013082022802820101009a0886\ - 5d2bc9e0cf03d2500b2a08402bb9dc953d5fcd73f04be61236efc0998a8f012f\ - 00e52f7a6e91e81b88a4c9f985a2da523cbe7caff08cae44963d2035eda72e1f\ - 31f82c8d64c86e686899d53c0200282f407ceb1507db480f1db223606a57466c\ - f60fe9fc5f7ea7d5fd82ed3ab2cf5e35491dfaef0aa2e10fbfa3cdfeb5ebf65e\ - 4dfc2837e1f6399db06cc2e0420c7b14a4c0d483b742ca58b31fec9f26a64e9b\ - fcaa82334e644f4b954e2a9c7eeae096b8864ecd223ead3bcf9e8c1f68f6678f\ - accdb7f26d8f33d8a5fb0cb156cc7daf4a96ec2b730c0d7f666d699f7345a37d\ - dc1ccdea6d8f439ddb23de04a941b246bc257b0aef544a8e868bc8444f021d03\ - f35f80fcd896f03eda9ff07f2e35295384c4f3b8f8c4821369ab541702820100\ - 75c5d8c8f72302d92be3bf486b8648330ff86954de5e6e83efef624a277574c1\ - 6757684d3874ee303fa08343fe82dae484e5dda6781280b434c4090044cc7ff9\ - b6e962594d3ca069815c0f0b6bfd25215a419420d0ef8a1595c6eb1b44a719b4\ - 0131081f75cc15cb09a5d5a029c8546230c30b4af2d4a9f4374c93a095c83b59\ - 4b1774d635d4aee965f1d094469f7bbf8bdc93216a6b8a6c5753b48962335bf2\ - 092aa583c897878c8a7ce61186b592b05d2aea710b673d5994cedb5f117fdb6b\ - 8ad4d89f443c4eb662b428a34a7522c69794cc0274f3eba837e90da86acbc707\ - 4ee3a0b029d970efa48b3d582b740ae0e585d175a5f63a385f8b6b8878b44e1a\ - 041f021d0212c34d3d17b96a899548ebf43bb886676acebd2f040f5b33a4e88d\ - 2d -PublicKey: \ - 308203423082023506072a8648ce3804013082022802820101009a08865d2bc9\ - e0cf03d2500b2a08402bb9dc953d5fcd73f04be61236efc0998a8f012f00e52f\ - 7a6e91e81b88a4c9f985a2da523cbe7caff08cae44963d2035eda72e1f31f82c\ - 8d64c86e686899d53c0200282f407ceb1507db480f1db223606a57466cf60fe9\ - fc5f7ea7d5fd82ed3ab2cf5e35491dfaef0aa2e10fbfa3cdfeb5ebf65e4dfc28\ - 37e1f6399db06cc2e0420c7b14a4c0d483b742ca58b31fec9f26a64e9bfcaa82\ - 334e644f4b954e2a9c7eeae096b8864ecd223ead3bcf9e8c1f68f6678faccdb7\ - f26d8f33d8a5fb0cb156cc7daf4a96ec2b730c0d7f666d699f7345a37ddc1ccd\ - ea6d8f439ddb23de04a941b246bc257b0aef544a8e868bc8444f021d03f35f80\ - fcd896f03eda9ff07f2e35295384c4f3b8f8c4821369ab54170282010075c5d8\ - c8f72302d92be3bf486b8648330ff86954de5e6e83efef624a277574c1675768\ - 4d3874ee303fa08343fe82dae484e5dda6781280b434c4090044cc7ff9b6e962\ - 594d3ca069815c0f0b6bfd25215a419420d0ef8a1595c6eb1b44a719b4013108\ - 1f75cc15cb09a5d5a029c8546230c30b4af2d4a9f4374c93a095c83b594b1774\ - d635d4aee965f1d094469f7bbf8bdc93216a6b8a6c5753b48962335bf2092aa5\ - 83c897878c8a7ce61186b592b05d2aea710b673d5994cedb5f117fdb6b8ad4d8\ - 9f443c4eb662b428a34a7522c69794cc0274f3eba837e90da86acbc7074ee3a0\ - b029d970efa48b3d582b740ae0e585d175a5f63a385f8b6b8878b44e1a038201\ - 050002820100267f9c3ff3ee3cbc0f9e94dc7e6837e1ff65175e967987b90b9a\ - ea7eef1de6e4c342bebb5dbd0c4e2f6514f2d487857a146dda6cfdbc8b56ed25\ - 4cd65754d84dd21a271cd15fc656274725643728b41ce3f0e6872b6dfb4c289e\ - 03f9b903880ce3d7d745dfbb641c8c42ec0bfb6951ca2611fd877c32248c9725\ - 2bdb42d7bd65ebc50653dff389526c546d1e6ebaf6bd8b3298c01935901b7efb\ - 288b78730d89fba7f46f2a642aee0dbc93aa29c190b201acf89d4f8ba28f3e3f\ - 54a1c5a48294dda908f904afb7db398682c809ce13abd49279221d5b40ad7621\ - 6bad7ca256d718d3552344c481b20da5aac3e637fb7edeaf7960b532ef761376\ - 489f02fa8c10 -Test: KeyPairValidAndConsistent -Message: 5F3914F7AE0F6C76D152 -Signature: 03D30B7EAADDCB384CECDBB7541DFE57187242C836A6C72AF6C2525E1A01DB97DF3F41156089162FAFC87361F2F28E55616A50633637FB13EFE3 -Test: Verify -Message: 769583D4E7EAD14C137A -Signature: 01DC2815FD4918B8D314526066A03AD6593C8CED9E1ED04252B1BBA59D019F1C965028DA88BF4DB35AEDBA2C3C963B7933E5C07C590EF78BDFA1 -Test: Verify -Message: 6441D5239F50C71DE0F5 -Signature: 013F6D395DE56832F72F17F7F7572BB6DD1C48BADCBDEA91F0A634486E034B617DA8F5AB5E6F78C691313F822C599B6400A0A119A5DA330C6830 -Test: Verify -Message: F1C2D4F7C3ECDF2C17B7 -Signature: 006441A8B3517613F950BC1C84504082C0C3EA10CC08DCC1DA22E05480036D78345B17244F0DE41DA8342AF3441489CF9880BAA01BF2745CAB3A -Test: Verify -Message: 752A1F2B8D9A717A882F -Signature: 0127027984402F5B8C7DB1B7666FFA787548E4200D26B9D3B20EA9B4370298A9BDC901F324844613E8B5F34F2BFE40D9E6513D0E207B5105A9B1 -Test: Verify -Message: 666DC6B1E871026EDE56 -Signature: 03E87B55A7E81318B6B7057C901F8E3DC564053C1EA08B1F1FD965453803F21C20CE7FCCF606FB1328EC987666E87AF16ABE6B42DB854BFAA019 -Test: Verify diff --git a/embeddedcryptopp/TestVectors/eax.txt b/embeddedcryptopp/TestVectors/eax.txt deleted file mode 100644 index 8b77f82..0000000 --- a/embeddedcryptopp/TestVectors/eax.txt +++ /dev/null @@ -1,75 +0,0 @@ -AlgorithmType: AuthenticatedSymmetricCipher -Name: AES/EAX -Source: http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf -Plaintext: -Key: 233952DEE4D5ED5F9B9C6D6FF80FF478 -IV: 62EC67F9C3A4A407FCB2A8C49031A8B3 -Header: 6BFB914FD07EAE6B -Ciphertext: E037830E8389F27B025A2D6527E79D01 -Test: Encrypt -Plaintext: F7FB -Key: 91945D3F4DCBEE0BF45EF52255F095A4 -IV: BECAF043B0A23D843194BA972C66DEBD -Header: FA3BFD4806EB53FA -Ciphertext: 19DD5C4C9331049D0BDAB0277408F67967E5 -Test: Encrypt -Plaintext: 1A47CB4933 -Key: 01F74AD64077F2E704C0F60ADA3DD523 -IV: 70C3DB4F0D26368400A10ED05D2BFF5E -Header: 234A3463C1264AC6 -Ciphertext: D851D5BAE03A59F238A23E39199DC9266626C40F80 -Test: Encrypt -Plaintext: 481C9E39B1 -Key: D07CF6CBB7F313BDDE66B727AFD3C5E8 -IV: 8408DFFF3C1A2B1292DC199E46B7D617 -Header: 33CCE2EABFF5A79D -Ciphertext: 632A9D131AD4C168A4225D8E1FF755939974A7BEDE -Test: Encrypt -Plaintext: 40D0C07DA5E4 -Key: 35B6D0580005BBC12B0587124557D2C2 -IV: FDB6B06676EEDC5C61D74276E1F8E816 -Header: AEB96EAEBE2970E9 -Ciphertext: 071DFE16C675CB0677E536F73AFE6A14B74EE49844DD -Test: Encrypt -Plaintext: 4DE3B35C3FC039245BD1FB7D -Key: BD8E6E11475E60B268784C38C62FEB22 -IV: 6EAC5C93072D8E8513F750935E46DA1B -Header: D4482D1CA78DCE0F -Ciphertext: 835BB4F15D743E350E728414ABB8644FD6CCB86947C5E10590210A4F -Test: Encrypt -Plaintext: 8B0A79306C9CE7ED99DAE4F87F8DD61636 -Key: 7C77D6E813BED5AC98BAA417477A2E7D -IV: 1A8C98DCD73D38393B2BF1569DEEFC19 -Header: 65D2017990D62528 -Ciphertext: 02083E3979DA014812F59F11D52630DA30137327D10649B0AA6E1C181DB617D7F2 -Test: Encrypt -Plaintext: 1BDA122BCE8A8DBAF1877D962B8592DD2D56 -Key: 5FFF20CAFAB119CA2FC73549E20F5B0D -IV: DDE59B97D722156D4D9AFF2BC7559826 -Header: 54B9F04E6A09189A -Ciphertext: 2EC47B2C4954A489AFC7BA4897EDCDAE8CC33B60450599BD02C96382902AEF7F832A -Test: Encrypt -Plaintext: 6CF36720872B8513F6EAB1A8A44438D5EF11 -Key: A4A4782BCFFD3EC5E7EF6D8C34A56123 -IV: B781FCF2F75FA5A8DE97A9CA48E522EC -Header: 899A175897561D7E -Ciphertext: 0DE18FD0FDD91E7AF19F1D8EE8733938B1E8E7F6D2231618102FDB7FE55FF1991700 -Test: Encrypt -Plaintext: CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7 -Key: 8395FCF1E95BEBD697BD010BC766AAC3 -IV: 22E7ADD93CFC6393C57EC0B3C17D6B44 -Header: 126735FCC320D25A -Ciphertext: CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC253B4652B1AF3795B124AB6E -Test: Encrypt -Plaintext: CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7 -Key: 8395FCF1E95BEBD697BD010BC766AAC3 -IV: 22E7ADD93CFC6393C57EC0B3C17D6B44 -Header: 126735FCC320D25A -Ciphertext: CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC253B4652B1AF3795B124AB6E -Test: Encrypt -Plaintext: CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7 -Key: 8395FCF1E95BEBD697BD010BC766AAC3 -IV: 22E7ADD93CFC6393C57EC0B3C17D6B44 -Header: 126735FCC320D25A -Ciphertext: 0B8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC253B4652B1AF3795B124AB6E -Test: NotVerify diff --git a/embeddedcryptopp/TestVectors/esign.txt b/embeddedcryptopp/TestVectors/esign.txt deleted file mode 100644 index 6370671..0000000 --- a/embeddedcryptopp/TestVectors/esign.txt +++ /dev/null @@ -1,93 +0,0 @@ -AlgorithmType: Signature -Name: ESIGN/EMSA5-MGF1(SHA-1) -Source: Crypto++ 5.0 test vectors, generated by Wei Dai -Comment: 1536-bit key -KeyFormat: DER -PrivateKey: \ - 3082014D0281C100E2A6788AB3CC986AEC06C51690143D3677141645D0628165EE924B9AFB7E6EDD\ - 52D90145B2F6031522C7A6CEC05E358F42B7837DACEA589F868F8DCA1C0F5FD8E5EDB8BBBAFCFF6D\ - 64CFCFBE68F46FBA6EFF45BC9D0CBB4F7F6075F5FFC2049C2F304B51C417764E18D182926E02D411\ - 6CE5C5C010E3D0AA6872A49B0D1FF4B37D54689C31F5821D04E9D4DB34D7536EE7F88B8C481B0EC1\ - F93193A0B70567E6FD76E9FAC4F67BB47DACD356D0C8015261E068DDF8C34C0CAFCF3FA775577FEB\ - 020120024100FAF0F292EE96D4F449024F86C0A104E0633C722586EC00AD33E0234629825D2081BA\ - 337597889CAC55DC6BEBDD8F13FE3AA2133D6371601A37D195DA7BC45EF3024100EBE16F88887A42\ - 5AA08E271467CC2220DC44012AB24ED4FF3512A96E8CB600C8BBCB771459FF0EE63D4B6786952A83\ - A7143A775073F0A1D69B6D0B5817755673 -PublicKey: \ - 3081C70281C100E2A6788AB3CC986AEC06C51690143D3677141645D0628165EE924B9AFB7E6EDD52\ - D90145B2F6031522C7A6CEC05E358F42B7837DACEA589F868F8DCA1C0F5FD8E5EDB8BBBAFCFF6D64\ - CFCFBE68F46FBA6EFF45BC9D0CBB4F7F6075F5FFC2049C2F304B51C417764E18D182926E02D4116C\ - E5C5C010E3D0AA6872A49B0D1FF4B37D54689C31F5821D04E9D4DB34D7536EE7F88B8C481B0EC1F9\ - 3193A0B70567E6FD76E9FAC4F67BB47DACD356D0C8015261E068DDF8C34C0CAFCF3FA775577FEB02\ - 0120 -Test: KeyPairValidAndConsistent -Message: "test" -Signature: \ - A3E32065DEDAE7EC05C1BFCD25797D99CDD5739D9DF3A4AA9AA45AC8233D0D37FEBC763FF184F659\ - 14914F0C341BAE9A5C2E2E38087877CBDC3C7EA034445B0F67D9352A79471A523771DB1267C1B6C6\ - 6673B3402ED6F21A840AB67B0FEB8B88AB33DDE4832190632D512AB16FABA75CFD7799F2E1EF671A\ - 7402370EED0A06ADF41565B8E1D145AE3919B4FF5DF1457BE0FE72ED11928F61414F0200F2766F7C\ - 79A2E552205D975EFE39AE2110FB35F480814113DDE85FCA1E4FF89BB268FB28 -Test: Verify -Message: "test1" -Test: NotVerify - -AlgorithmType: Signature -Name: ESIGN/EMSA5-MGF1(SHA-1) -Source: http://www.nttmcl.com/sec/Esign/esign_emsa5_data_ntt.txt, \ - ESIGN ( IFSSA-ESIGN-EMSA5 ) Test Vector No.1-3 ( 1152 bits ) -KeyFormat: Component -Prime1: ec8b4bdc9a56ae7b60619814ec45d617246063b5aac39c286f7c82ec2824c245001b678217a7cf178979c7270eb510db -Prime2: e7b1c3ae3494d0ac7b6868a53a5fe3ba19471437c54b25699e8c348a003e5e1d4c6d244d4f6a78f260c98fc54795a6a3 -Modulus: c5d0b8fac0cc6acc9d52c61200b541f7b4f8ff9f1bda97e0ebf78a3df768ba70ade59306d6ae65655bff7c6a94518c91e43dc0003b6f8730acc244799bdacb1e5070c6ea3089ea83bd5ef0a533adf3d9d63c0e88ce74545cfb21213fc33813fd913c6a6cf84b5adabc7d74751e9945521ac76a790bba95ad48d9d3fb2fbc4b0ed2ddee7d5ea6aa61633eccdac6381fab -PublicExponent: 0400 -Test: KeyPairValidAndConsistent -Message: 86f28c1cb5e640548309b85dc6e64c1a -Signature: 348dc9a0943b1e2ba7ef501cbe970a023b37ca4019b9a5cb35ffc3bcdb28dcbd4193d7817d418bbaf291d97a1eeb918a03ee65caa7ad26c24f9ef807c8798ade5b70d7328cd36ac0844bf63f511bb63067e8236d084cf8af68e88155ea94b978aab6bd0339c55d976434423fc779d549779e81f528d028c7343e060544410e528814fb0874417d1eedf38d6db4b97dd6 -Test: Verify -Message: 2fd87bfa6c8a965c9e1aaa8e3574202b -Signature: 561ad8bd11270c71f00af0e0cf256d858c757e8b55b9c4d6fb6bf71598ab59352992656348c1ff1ccda14fb7c5c3b53be49727c07422b78ffc380eeb03be7bdf07b279337af8a1eb7c5bdb725b33a82926b6afb7a1fff0750cc2532c6f96e28d7f1e621cf222b42bb850312f1a5fb7d99acd1c6f6d2347a121dd478374d6a40a7b0cd42e430f01b926135fc8d850366a -Test: Verify -Message: 888330ef1dc1588d578badde35c98d1e -Signature: 915d64d7b9b811fe8b58eaff4c2bf9ce2ad886eef95b28093f8c21f4ca950fdb2f6e77f97d0f2f8158445347f5b3ce33e082f3b5204522e15614d1891078d9557796726b5555cbd8d5489638ecf4738257dea70175fe27de54b1f45c0a96c229bd59260bebfb241e8eacb8a1a23b9a9a79b6d1f52cfed8cca2f1968e37d76c435ad1acd44131ef2c5f5e4ea8a33aee4e -Test: Verify - -AlgorithmType: Signature -Name: ESIGN/EMSA5-MGF1(SHA-1) -Source: http://www.nttmcl.com/sec/Esign/esign_emsa5_data_ntt.txt, \ - ESIGN ( IFSSA-ESIGN-EMSA5 ) Test Vector No.4-6 ( 1152 bits ) -KeyFormat: Component -Prime1: d64dac2fb3506111bbac11a04e138d2d6f32df119f2f259065cf5785a46aaf404ad887f0a310b36be4a3a1a33c8a054f -Prime2: d1158628ed1e0695c02a821ab8590f59fc1a3fb1e19ee192ab789e9d963766d78f55cfef9bf58c0c774a32d8a8943955 -Modulus: 92855120174c4a115bf525fa1f2ebf68d8328162149a5a6751b2512584eab7e5582d38d0e5029e01ece85a484030bb884a29121d8924f0195b22842b16436cd36c33bbe843e1cf7a585e89894b14595641d081a3077d667096df251bd93c86ebd94e0d555601794fa66fa2bcea920287c19922bed486a4f631390d1e36cc3635b509cb14c44d50313919a6cbb75eff35 -PublicExponent: 0400 -Test: KeyPairValidAndConsistent -Message: 16a3632339c463e243a4909f8a3810a8 -Signature: 7d8790ee852a4f3ba8bb3fa0f6fc30c29b6bc2bc538195826544138dcb92500122148ac2cf0dc77dd37182c2267a73317ce5b2ae26db79204abe0e10c7212ba8de99fdc5cf498f7ee689588541fb78291afb9b65242f725a4aa32b119957b4314a58b4239a0235b9b1a8a6efbaa3601961d4b0730a6d9e5659f20105931d473daf3d378b39b7f3f01516d72ade9ef68a -Test: Verify -Message: ef8bcad6c164a86b0e0a3c011d556744 -Signature: 6ce6024f64a7f04a0fe29b65cf2ec2ac49d9f90078a77db8bc260d3cfef233165a90b29d5787218b4d05a0e9321f2e802a8ed6d1a4201feb982a5d06bef051d60436d8c61a249432e662e625806526075f02b60d198142b96b67a4ac31d0071a1f971dae5a6a1b6db177591edfe80f7e51c7335441490f05f214b5a1aec94de572e3ec11ef4bebeb42f27037d38a186f -Test: Verify -Message: 29023889c79230c1c479820c5ff2e006 -Signature: 85f0b648ee0f6d30a18666e2da8bcda319ede91ca18e018548e2a1c21b0e0049b91528eba4da3be4551b26c4e59e6aba25312874f2320eaf7c94c541e17fb16fb0d9d9928ea526b0fc0c0fb2d12e425a5917e4039a5366585327bc3456107ff31c889c5e04259457dfe65952dc43cd35f4ca689272769096b9583bbffad4a057673f938fa7192bbca44598cf5600e3eb -Test: Verify - -AlgorithmType: Signature -Name: ESIGN/EMSA5-MGF1(SHA-1) -Source: http://www.nttmcl.com/sec/Esign/esign_emsa5_data_ntt.txt, \ - ESIGN ( IFSSA-ESIGN-EMSA5 ) Test Vector No.7-9 ( 1152 bits ) -KeyFormat: Component -Prime1: fd5708b30e8ee342bacaeb01c0d3baa91a833dacff2878c7df62e04a65afe770acdcefeaf8a72a5809387e5ed97756ef -Prime2: fa335563d5da151e3ab025f3b77d3f1eaf4a0d431012e79b12ca8ec433d347bd9a2b5179f2ed332a19ea2cad694c97dd -Modulus: f5072ba25e7df2c0e0a0abde031dda9534a493396ab895e6132abc90f993535ce55d6395e1fd548371228decc1cfefa9737344243ddb1eccbbc22d68571617afb23638c3f0222a84b0a8c9889ab934aa84cc92e14d972670db6d2105bbd0212c1843ff0ccbae19535ac01cf02ad98aa941fce32fac874cea7f1f83969fbaf025fb562a087efb4652210d45279312da7d -PublicExponent: 0400 -Test: KeyPairValidAndConsistent -Message: abbf5c71245af5d272e627ec845e9ed4 -Signature: b75e2869c052df20d6c008dd911a5bd752d5a23ee42ae47def37f76f6b2d5f04eb8d9b0783c502e0abd30bc567a6672292c3a6736fe8d4034fad857456cd599259d09f42f1d4c64d244fd149f6316f0b763be0de4f9da7f9649a76b984fe2ae99293d406904a9df59d28cc8a58b7ad0029657a47ac0e28d6353287df1ea8feef2fbb65d86425e80487420c1c9c1bda7e -Test: Verify -Message: cf2c943bc4c23175b43ba128c75339d1 -Signature: 64616eb627bf49c2a5a183479a66b7dae12cd1a0982baa0cc12329f594196b9de47909e6b5cf4653bfccdeeb5478fd88c31c197c9adc335a84ec58664ce5fc55c7b2f17b0f32ffac4ff3f3b4ddb3ce125ab7e43efc0be6ae8357895ab5f118a4ec71b57cc1b252373fecd4a1f404ed295f2d97868e3737fdd6fdf124bc2f1e083b57d5c237db775d429d08d5b5ced857 -Test: Verify -Message: 4d011f09f665d5f4a12595900e3827ec -Signature: 1911d3df18bdd9907b69ce6b655086c952c92d826bbef199fb1e0dcb7209a1b28d0a03beabc9e7d8df052febe26f691ff808caaac697c3005d524f3da8c700bf620aa37fd0793b3f22c6a488d733336d040642e0767755391951a754a1111345b912b4c0228ab154eb4baac0383a54023bd7c7ea2ed4bb894444b80d7e5f18407f51c3af858b9fa9198190b4b540fce8 -Test: Verify diff --git a/embeddedcryptopp/TestVectors/gcm.txt b/embeddedcryptopp/TestVectors/gcm.txt deleted file mode 100644 index e39ed36..0000000 --- a/embeddedcryptopp/TestVectors/gcm.txt +++ /dev/null @@ -1,139 +0,0 @@ -AlgorithmType: AuthenticatedSymmetricCipher -Name: AES/GCM -Source: aes-modes-src-07-10-08/Testvals/gcm.1, Basic Tests for GCM (compiled by B. R. Gladman) -Key: 00000000000000000000000000000000 -IV: 000000000000000000000000 -MAC: 00000000000000000000000000000000 -Test: NotVerify -Key: 00000000000000000000000000000000 -IV: 000000000000000000000000 -MAC: 58e2fccefa7e3061367f1d57a4e7455a -Test: Encrypt -Key: 00000000000000000000000000000000 -IV: 000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 0388dace60b6a392f328c2b971b2fe78 -MAC: ab6e47d42cec13bdf53a67b21257bddf -Test: Encrypt -Key: feffe9928665731c6d6a8f9467308308 -IV: cafebabefacedbaddecaf888 -Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255 -Ciphertext: 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e 21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985 -MAC: 4d5c2af327cd64a62cf35abd2ba6fab4 -Test: Encrypt -Key: feffe9928665731c6d6a8f9467308308 -IV: cafebabefacedbaddecaf888 -Header: feedfacedeadbeeffeedfacedeadbeefabaddad2 -Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 -Ciphertext: 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e 21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091 -MAC: 5bc94fbc3221a5db94fae95ae7121a47 -Test: Encrypt -Key: feffe9928665731c6d6a8f9467308308 -IV: cafebabefacedbad -Header: feedfacedeadbeeffeedfacedeadbeefabaddad2 -Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 -Ciphertext: 61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c7423 73806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598 -MAC: 3612d2e79e3b0785561be14aaca2fccb -Test: Encrypt -Key: feffe9928665731c6d6a8f9467308308 -IV: 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728 c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b -Header: feedfacedeadbeeffeedfacedeadbeefabaddad2 -Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 -Ciphertext: 8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca7 01e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5 -MAC: 619cc5aefffe0bfa462af43c1699d050 -Test: Encrypt -Header: -Plaintext: -Ciphertext: -Key: 000000000000000000000000000000000000000000000000 -IV: 000000000000000000000000 -MAC: cd33b28ac773f74ba00ed1f312572435 -Test: Encrypt -Key: 000000000000000000000000000000000000000000000000 -IV: 000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 98e7247c07f0fe411c267e4384b0f600 -MAC: 2ff58d80033927ab8ef4d4587514f0fb -Test: Encrypt -Key: feffe9928665731c6d6a8f9467308308feffe9928665731c -IV: cafebabefacedbaddecaf888 -Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255 -Ciphertext: 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c 7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256 -MAC: 9924a7c8587336bfb118024db8674a14 -Test: Encrypt -Key: feffe9928665731c6d6a8f9467308308feffe9928665731c -IV: cafebabefacedbaddecaf888 -Header: feedfacedeadbeeffeedfacedeadbeefabaddad2 -Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 -Ciphertext: 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c 7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710 -MAC: 2519498e80f1478f37ba55bd6d27618c -Test: Encrypt -Key: feffe9928665731c6d6a8f9467308308feffe9928665731c -IV: cafebabefacedbad -Header: feedfacedeadbeeffeedfacedeadbeefabaddad2 -Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 -Ciphertext: 0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057 fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7 -MAC: 65dcc57fcf623a24094fcca40d3533f8 -Test: Encrypt -Key: feffe9928665731c6d6a8f9467308308feffe9928665731c -IV: 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728 c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b -Header: feedfacedeadbeeffeedfacedeadbeefabaddad2 -Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 -Ciphertext: d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e45 81e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b -MAC: dcf566ff291c25bbb8568fc3d376a6d9 -Test: Encrypt -Header: -Plaintext: -Ciphertext: -Key: 0000000000000000000000000000000000000000000000000000000000000000 -IV: 000000000000000000000000 -MAC: 530f8afbc74536b9a963b4f1c4cb738b -Test: Encrypt -Key: 0000000000000000000000000000000000000000000000000000000000000000 -IV: 000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: cea7403d4d606b6e074ec5d3baf39d18 -MAC: d0d1c8a799996bf0265b98b5d48ab919 -Test: Encrypt -Key: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 -IV: cafebabefacedbaddecaf888 -Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255 -Ciphertext: 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa 8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad -MAC: b094dac5d93471bdec1a502270e3cc6c -Test: Encrypt -Key: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 -IV: cafebabefacedbaddecaf888 -Header: feedfacedeadbeeffeedfacedeadbeefabaddad2 -Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 -Ciphertext: 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa 8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662 -MAC: 76fc6ece0f4e1768cddf8853bb2d551b -Test: Encrypt -Key: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 -IV: cafebabefacedbad -Header: feedfacedeadbeeffeedfacedeadbeefabaddad2 -Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 -Ciphertext: c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0 feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f -MAC: 3a337dbf46a792c45e454913fe2ea8f2 -Test: Encrypt -Key: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 -IV: 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728 c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b -Header: feedfacedeadbeeffeedfacedeadbeefabaddad2 -Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 -Ciphertext: 5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf4 0fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f -MAC: a44a8266ee1c8eb0c8b5d4cf5ae9f19a -Test: Encrypt -Header: -Plaintext: -Ciphertext: -Key: 00000000000000000000000000000000 -IV: 000000000000000000000000 -Plaintext: 000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f 303132333435363738393a3b3c3d3e3f 404142434445464748494a4b4c4d4e4f 505152535455565758595a5b5c5d5e5f 606162636465666768696a6b6c6d6e6f 707172737475767778797a7b7c7d7e7f 808182838485868788898a8b8c8d8e8f 909192939495969798999a9b9c9d9e9f a0a1a2a3a4a5a6a7a8a9aaabacadaeaf b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf d0d1d2d3d4d5d6d7d8d9dadbdcdddedf -Ciphertext: 0389d8cd64b3a595fb21c8b27dbff077 e784b8b85d5e4f34efe493e48896dfff 002333026a56b2fd08a09c87fcbe85cf f97c902a25bb1f4a43478687f5feb6cd ca9f3fc6ecab732627386ee2996a4cde c5e91f48c293c6a87774b950aeb1d7bf 62321a0d76006297b2d06623cf6e4fb1 433494c3326b0ae914120085a195413f 5e3278e4107d7b08dd2107405610e67d 83ed5b5ba0b591e9e46b1029f5f6936f fdb0e788fc09f60d861a0b3e1ab6294a 76ebdf6663421ef7dd6c1bc448dfcdb7 a0c38bae72fa627ed327f2b46fcec25a 77ee5fd7e3354788643c0d7df15075d5 -MAC: 6b385f3012eafda4189da7ad3b6eafbf -Test: Encrypt -Key: 00000000000000000000000000000000 -IV: 000000000000000000000000 -Plaintext: 000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f 303132333435363738393a3b3c3d3e3f 404142434445464748494a4b4c4d4e4f 505152535455565758595a5b5c5d5e5f 606162636465666768696a6b6c6d6e6f 707172737475767778797a7b7c7d7e7f 808182838485868788898a8b8c8d8e8f 909192939495969798999a9b9c9d9e9f a0a1a2a3a4a5a6a7a8a9aaabacadaeaf b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf d0d1d2d3d4d5d6d7d8d9dadbdcdddedf -Ciphertext: 0389d8cd64b3a595fb21c8b27dbff077 e784b8b85d5e4f34efe493e48896dfff 002333026a56b2fd08a09c87fcbe85cf f97c902a25bb1f4a43478687f5feb6cd ca9f3fc6ecab732627386ee2996a4cde c5e91f48c293c6a87774b950aeb1d7bf 62321a0d76006297b2d06623cf6e4fb1 433494c3326b0ae914120085a195413f 5e3278e4107d7b08dd2107405610e67d 83ed5b5ba0b591e9e46b1029f5f6936f fdb0e788fc09f60d861a0b3e1ab6294a 76ebdf6663421ef7dd6c1bc448dfcdb7 a0c38bae72fa627ed327f2b46fcec25a 77ee5fd7e3354788643c0d7df15075d5 -MAC: 6b385f3012eafda4189da7ad3b6eafbf -Test: Encrypt diff --git a/embeddedcryptopp/TestVectors/hmac.txt b/embeddedcryptopp/TestVectors/hmac.txt deleted file mode 100644 index 52f85fd..0000000 --- a/embeddedcryptopp/TestVectors/hmac.txt +++ /dev/null @@ -1,125 +0,0 @@ -AlgorithmType: MAC -Name: HMAC(MD5) -Source: RFC 2202 -Comment: Test Case 1 -Key: 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b -Message: "Hi There" -MAC: 0x9294727a3638bb1c13f48ef8158bfc9d -Test: Verify -Comment: Test Case 2 -Key: "Jefe" -Message: "what do ya want for nothing?" -MAC: 0x750c783e6ab0b503eaa86e310a5db738 -Test: Verify -Comment: Test Case 3 -Key: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -Message: r50 0xdd -MAC: 0x56be34521d144c88dbb8c733f0e8b3f6 -Test: Verify -Comment: Test Case 4 -Key: 0x0102030405060708090a0b0c0d0e0f10111213141516171819 -Message: r50 0xcd -MAC: 0x697eaf0aca3a3aea3a75164746ffaa79 -Test: Verify -Comment: Test Case 5 -Key: 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c -Message: "Test With Truncation" -MAC: 0x56461ef2342edc00f9bab995690efd4c -Test: Verify -MAC: 0x56461ef2342edc00f9bab995 -#TruncatedSize: 12 -Test: VerifyTruncated -Comment: Test Case 6 -Key: r80 0xaa -Message: "Test Using Larger Than Block-Size Key - Hash Key First" -MAC: 0x6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd -Test: Verify -Comment: Test Case 7 -Key: r80 0xaa -Message: "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" -MAC: 0x6f630fad67cda0ee1fb1f562db3aa53e -Test: Verify - -AlgorithmType: MAC -Name: HMAC(SHA-1) -Source: RFC 2202 -Comment: Test Case 1 -Key: 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b -Message: "Hi There" -MAC: 0xb617318655057264e28bc0b6fb378c8ef146be00 -Test: Verify -Comment: Test Case 2 -Key: "Jefe" -Message: "what do ya want for nothing?" -MAC: 0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79 -Test: Verify -Comment: Test Case 3 -Key: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -Message: r50 0xdd -MAC: 0x125d7342b9ac11cd91a39af48aa17b4f63f175d3 -Test: Verify -Comment: Test Case 4 -Key: 0x0102030405060708090a0b0c0d0e0f10111213141516171819 -Message: r50 0xcd -MAC: 0x4c9007f4026250c6bc8414f9bf50c86c2d7235da -Test: Verify -Comment: Test Case 5 -Key: 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c -Message: "Test With Truncation" -MAC: 0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04 -Test: Verify -MAC: 0x4c1a03424b55e07fe7f27be1 -#TruncatedSize: 12 -Test: VerifyTruncated -Comment: Test Case 6 -Key: r80 0xaa -Message: "Test Using Larger Than Block-Size Key - Hash Key First" -MAC: 0xaa4ae5e15272d00e95705637ce8a3b55ed402112 -Test: Verify -Comment: Test Case 7 -Key: r80 0xaa -Message: "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" -MAC: 0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91 -Test: Verify - -AlgorithmType: MAC -Name: HMAC(RIPEMD-160) -Source: RFC 2286 -Comment: Test Case 1 -Key: 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b -Message: "Hi There" -MAC: 0x24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668 -Test: Verify -Comment: Test Case 2 -Key: "Jefe" -Message: "what do ya want for nothing?" -MAC: 0xdda6c0213a485a9e24f4742064a7f033b43c4069 -Test: Verify -Comment: Test Case 3 -Key: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -Message: r50 0xdd -MAC: 0xb0b105360de759960ab4f35298e116e295d8e7c1 -Test: Verify -Comment: Test Case 4 -Key: 0x0102030405060708090a0b0c0d0e0f10111213141516171819 -Message: r50 0xcd -MAC: 0xd5ca862f4d21d5e610e18b4cf1beb97a4365ecf4 -Test: Verify -Comment: Test Case 5 -Key: 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c -Message: "Test With Truncation" -MAC: 0x7619693978f91d90539ae786500ff3d8e0518e39 -Test: Verify -MAC: 0x7619693978f91d90539ae786 -#TruncatedSize: 12 -Test: VerifyTruncated -Comment: Test Case 6 -Key: r80 0xaa -Message: "Test Using Larger Than Block-Size Key - Hash Key First" -MAC: 0x6466ca07ac5eac29e1bd523e5ada7605b791fd8b -Test: Verify -Comment: Test Case 7 -Key: r80 0xaa -Message: "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" -MAC: 0x69ea60798d71616cce5fd0871e23754cd75d5a0a -Test: Verify diff --git a/embeddedcryptopp/TestVectors/mars.txt b/embeddedcryptopp/TestVectors/mars.txt deleted file mode 100644 index 3ed5a10..0000000 --- a/embeddedcryptopp/TestVectors/mars.txt +++ /dev/null @@ -1,66 +0,0 @@ -AlgorithmType: SymmetricCipher -Name: MARS/ECB -Key: 80000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: B3E2AD5608AC1B6733A7CB4FDF8F9952 -Test: Encrypt -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: DCC07B8DFB0738D6E30A22DFCF27E886 -Test: Encrypt -Key: 00000000000000000000000000000000 -Plaintext: DCC07B8DFB0738D6E30A22DFCF27E886 -Ciphertext: 33CAFFBDDC7F1DDA0F9C15FA2F30E2FF -Test: Encrypt -Key: CB14A1776ABBC1CDAFE7243DEF2CEA02 -Plaintext: F94512A9B42D034EC4792204D708A69B -Ciphertext: 225DA2CB64B73F79069F21A5E3CB8522 -Test: Encrypt -Key: 86EDF4DA31824CABEF6A4637C40B0BAB -Plaintext: 4DF955AD5B398D66408D620A2B27E1A9 -Ciphertext: A4B737340AE6D2CAFD930BA97D86129F -Test: Encrypt -Key: 000000000000000000000000000000000000000000000000 -Plaintext: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -Ciphertext: 97778747D60E425C2B4202599DB856FB -Test: Encrypt -Key: D158860838874D9500000000000000000000000000000000 -Plaintext: 93A953A82C10411DD158860838874D95 -Ciphertext: 4FA0E5F64893131712F01408D233E9F7 -Test: Encrypt -Key: 791739A58B04581A93A953A82C10411DD158860838874D95 -Plaintext: 6761C42D3E6142D2A84FBFADB383158F -Ciphertext: F706BC0FD97E28B6F1AF4E17D8755FFF -Test: Encrypt -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 62E45B4CF3477F1DD65063729D9ABA8F -Ciphertext: 0F4B897EA014D21FBC20F1054A42F719 -Test: Encrypt -Key: FBA167983E7AEF22317CE28C02AAE1A3E8E5CC3CEDBEA82A99DBC39AD65E7227 -Plaintext: 1344ABA4D3C44708A8A72116D4F49384 -Ciphertext: 458335D95EA42A9F4DCCD41AECC2390D -Test: Encrypt -Key: 00000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 3FE24DC09173D15F4616A849D396F7E3 -Test: EncryptionMCT -Key: 00000000000000000000000000000000 -Plaintext: 24BD3D2FC6FEE152D1D64545E2230584 -Ciphertext: 00000000000000000000000000000000 -Test: DecryptionMCT -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: 34EC834E2F30741ECB476DA7E9662BBD -Test: EncryptionMCT -Key: 000000000000000000000000000000000000000000000000 -Plaintext: 7F27C3397A8CEEF1BDF859459690FEA8 -Ciphertext: 00000000000000000000000000000000 -Test: DecryptionMCT -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 00000000000000000000000000000000 -Ciphertext: EDE145C10E279501D921C5E3B04420A6 -Test: EncryptionMCT -Key: 0000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 95615ADB0DDF6613A5E84F849AC8C00D -Ciphertext: 00000000000000000000000000000000 -Test: DecryptionMCT diff --git a/embeddedcryptopp/TestVectors/nr.txt b/embeddedcryptopp/TestVectors/nr.txt deleted file mode 100644 index f08bb6a..0000000 --- a/embeddedcryptopp/TestVectors/nr.txt +++ /dev/null @@ -1,615 +0,0 @@ -AlgorithmType: Signature -Name: NR(1363)/EMSA1(SHA-1) -Source: generated by Wei Dai using Crypto++ 5.0 -Comment: 1024-bit NR key -KeyFormat: Component -SubgroupOrder: \ - 09b2940496d6d9a43bb7ec642c57b302e59b3a5155 -SubgroupGenerator: \ - a1c379ba91fe1f9d5283807b809c698bce4aee6f405f4de8c46becf33c08a63b\ - c5f8088f75b5b6bcfb0847ccbdee700e4e698652317bbd7a3056404c541136d7\ - 332c2b835ef0d1508ef57b437de60675f20f75df0483f242ddeb57efacd18041\ - 8790f4dec0a8250593ba36f17316580d50db1383ea93a21247650a2e04af904d -Modulus: \ - bd670f79b0cde98a84fd97e54d5d5c81525a016d222a3986dd7af3f32cde8a9f\ - 6564e43a559a0c9f8bad36cc25330548b347ac158a345631fa90f7b873c36eff\ - ae2f7823227a3f580b5dd18304d5932751e743e922eebfbb4289c389d9019c36\ - f96c6b81fffbf20be062182104e3c4b7d02b872d9a21e0fb5f10ded64420951b -PrivateExponent: \ - 0355dc884345c08fb399b23b161831e94dbe61571e -PublicElement: \ - 255cf6b0a33f80cab614eafd5f7b2a6d83b3eafe27cd97b77ae70c7b966707d8\ - 23f0e6aaaa41dc005aaefd3a0c269e60a665d2642f5d631ff1a3b8701bc06be9\ - c44ab7367f77fefeec4c5959cd07e50d74a05af60b059ad3fc75249ecf44774b\ - 88b46860d9c3fa35d033bcfc7b0b2d48dc180d192d4918cddff4f7ebcdaaa198 -Test: KeyPairValidAndConsistent -Message: 66B92E1E2C44B80F7BFA -Signature: \ - 06e7586b76d5a8270155cce2d3ff4495237eed29a101eb1341fce0b43d95397b\ - 053d93772b0a9cf3117b -Test: Verify -Message: 973266BB0A492248082A -Signature: \ - 02de44ed2233f0f11dcf567217d2089ec039a211bf000d42e04900a66ce45c58\ - 526a97d7f4cfba29e43d -Test: Verify -Message: 9A6D079ED0CA9D8B40E8 -Signature: \ - 04f59dbb2712926b3bc1d3c428f16203f3443f88db0669adda94dcb54e1fff71\ - fb51bb603e7adff13f84 -Test: Verify -Message: AA34DCE67BCDAC927DA6 -Signature: \ - 08ad21bf9d0cc598a214329d3544685d39487988bb01aced68ad0a4831affbff\ - 3b14df6c0f4ac4d2e967 -Test: Verify -Message: 4EDAC08816AFDBF284DA -Signature: \ - 09a9d5aa9bd1b6b61fe8825128c8e52a6213692b2504c8c6951299b5ca51b03d\ - ea0a5e56f9a7c4cd44f7 -Test: Verify -Message: D82F2E903230962B8174 -Signature: \ - 0441c8d089e690a7fab391de07073326d443a0d9d806a3997ac1641175310890\ - 1e55582a582541330539 -Test: Verify -Comment: 1025-bit NR key -KeyFormat: Component -SubgroupOrder: \ - 0b3949dadf3196f08bca0606f06443afce2fb1d02f -SubgroupGenerator: \ - 015f0f6d1729ef2af723c00e36450a04c7e7681d65b74a6417a53b3eb6036989\ - eff8e0ab11a7ec3ce2340b7c7a92e1a977aee52555c06c12c4cc28496ddc2598\ - feeb7539ce90d3888e21f61d7f14746cf67d9fed373afd97e2483700e300ed9d\ - a25e7200b363a4727ad201194b36ea5f816cf83488c3e527d3a5515870d2da63\ - d6 -Modulus: \ - 017310bf02d70ef2cee45d1cc47ec8ce8cabdd6bf32a560975a42ef057bf9dfd\ - 553bc9368ddb154a55d855edaa755e69f511a4c69ba78571cc4b14ddbb0f32a4\ - a9c56c286305aa21ec4e35de7390747477b3bd574e7b87cbebde2f665703137a\ - 1172350ad2f48a0884d076ada9db82f104e6b0ad86693cd4adbd0067639102fc\ - f1 -PrivateExponent: \ - 0696b0f255468b7ac18e11632f208ca86383a46724 -PublicElement: \ - 45bf83e62f50190374b23de5e4a1d0278e9e8e6c8335577d62e80662a380c206\ - e326819c5082d321dfda1f905fa5a3ead9a2dc769885a27b1fd6a133185dc5a7\ - 876a76ab0a09fe02b7071a924169e4d2d2a67e67ed3628800134183b962c0b31\ - 3463aa154e6437d644e025ab234e63d19c129842a61c5e5ea5a06466c858c81c -Test: KeyPairValidAndConsistent -Message: 2F585D0CE4FA1CD93880 -Signature: \ - 06586d8a703cdc27200d5261853f50effa8ebbdfc905f5becb68b81eca506992\ - 50fb54e46d557c6095dd -Test: Verify -Message: 4F09A1F217B8393199EE -Signature: \ - 0622cd33b1d715829d8fae104759ed449f95becb5e03d36f5578fd6a2951d2e6\ - 26cfce85ba6563990d64 -Test: Verify -Message: 03D7110A753B008A76A0 -Signature: \ - 02925630b4c80e604fc1d8680bfd0e3d878e22b3a30ab8b10da7fc38816a8c5f\ - 1e06927c68f9d3db60d9 -Test: Verify -Message: 129F4781D417671F886D -Signature: \ - 016c2c4ce845b4d412828cbb8a396d080c7eb93bcb01f7010410198c8bac96df\ - 8ab8761cebdb7d87f3a2 -Test: Verify -Message: 3E1594F559D1248D1112 -Signature: \ - 080bab68c62be86ab2c1bfd0edf10387a7cd66b69f054e254218e01f650e4e8c\ - 6bfa10054e367893e59e -Test: Verify -Message: D6F0354F1B6B253B6997 -Signature: \ - 08755c7e8012e8160db75c6160686351e5c577207f01602b4dda2fa56b864374\ - 703c83bb323c7bb34f5f -Test: Verify -Comment: 1026-bit NR key -KeyFormat: Component -SubgroupOrder: \ - 36bb68cd95dab195f14c4534283e7ea50b00cc31a3 -SubgroupGenerator: \ - e2782ad6992f4b7e88787b4d616744b60e095575a177569c4a069e311e38b724\ - 0c43343367e23574c30e4d9f05afe1fbe61423bab715915c4ccf28aa0ed2f52b\ - 092b86c8ec1f9d4795d6e91c88ba41297625c11a9e1f4f182da13cf51e541038\ - a1266bf32b2dd81ecd84bb80be8fdf97689942e944b7fbb6981e00cd680ee25f -Modulus: \ - 025098828217d00108030801e5f135fc6fd3010be39e49060a96addc8a081198\ - 803402c4b46e4ce0750fcbab8cf084c7ca8cae09f1b5482d336fa3af47b96791\ - d02d8143e274b1325f2213e17f9384c805f479e52a3117cf84869d395f1bc025\ - c918484478d2da1880d32bc519f4e6b2fd2d46958795550ce1765f725626f3fc\ - 17 -PrivateExponent: \ - 2db270c284328353f979cad99f4133c53acaa6ee71 -PublicElement: \ - 0179b283f67868aeded3a0c5633d0e6c18fad77174e2c89c03452593d05e77a9\ - fb029c0ccb2b6f2328e79c286ee392713f12d9d45578348383b81d11b0e0f7e8\ - 9965a7785d5ab64ea25bb73e8acaa8e84cb9897985015757a48c0b1dac3a6a60\ - 6fe671ea073ec434a46f227b8d4b02a46fbba2f6c6216736d669f55778d81004\ - d8 -Test: KeyPairValidAndConsistent -Message: 7E4F2ED4E79062778A2D -Signature: \ - 03f523873462ee1513833e2853c3b62e30c5c1cc3224f1a42dc154fa84ecce04\ - 487069530d76e0574a38 -Test: Verify -Message: A0E35846B5CF1B5BF560 -Signature: \ - 2264285d75a55c431a7adb9347bc07d58efbeb1dd9354d01b0b86f2875f8dec0\ - 294d20289d39369c5afa -Test: Verify -Message: 3B138785EFC6F520EAE0 -Signature: \ - 116e45961ca73f3ccf08b35f94877fef88772cf0fa2ab196c85a91104d8fbde6\ - 65b7032b2fb4011a88cc -Test: Verify -Message: 0F6BE2AA764B485145D4 -Signature: \ - 027ad753bde13c7f2fcd7571e5558f8af756cdb9463237fb0e285cb633cc86be\ - 1b410188d701f6ca83c6 -Test: Verify -Message: 6CD9FBD23EA58826FB04 -Signature: \ - 1651decd376899104e3fdbe40ab2d9bfd3c8577f3b092b66e3760678ecb3fc35\ - 23a59107e0bdccb76a73 -Test: Verify -Message: 473A82649565109E9E89 -Signature: \ - 2045ef56d92f89a214d76cca6b591068ac5f0d008c121ec4e5c4c1e8ca9b67cd\ - bb5ecc776a23b6d54ba5 -Test: Verify -Comment: 1027-bit NR key -KeyFormat: Component -SubgroupOrder: \ - 291d0ba731a4303070504d8b9615640a5e1345e00f -SubgroupGenerator: \ - 051c9d0270b69ceef82af5aed5f91dc88d585096609d835d03d39cf3ce74f5a3\ - 402d4e8e192455493da61cc58ee6f54dd941172be3d7642169cbc52273f4b725\ - f1d6c820c3333336c64d32fb6238121b3ccb7c71b847764946bb0887a44ca9de\ - 802cda62efa9dda573751084225353f11ed837f3dc25de8374b6fdbfb6e313e4\ - 6d -Modulus: \ - 055402a8abe9cda3072ca8601d68032651feb0335856e57f8f8d4ec949098a64\ - 59151cefeef91b7aa733668c8cf0e9b96c93c61f3528d4036daa6565646f65d7\ - 4c4552817df7e5fb1cc421cfd885e27bb811ad227e81b3fa02f7a00bf01ee6e2\ - 3fb5572a75f8f29b58bd5f7db435e8a92a923f15d50f34213d29816921bf195b\ - 2d -PrivateExponent: \ - 13b27094d9a5a3a9704cebdbe890da325fa26ad555 -PublicElement: \ - 03b06b99097cd7145c7d7782b02e247a4741f3c7f39233627f17e13ebff89a18\ - cad6a454c3f32f7ef2910384030da71ae47e1c3fa79c2141dad107f8e715e47f\ - b0bb626baafc35db769852ebbec2d339c3c3d5f2287cfdd20b3b78ea4607086c\ - 42558ae4637eddd6a74bc1072d0f34d9c0130cbc9e84f537e7ce50df502d17b5\ - c3 -Test: KeyPairValidAndConsistent -Message: AE6DCD9535AEEE3ECC89 -Signature: \ - 1c6794878aabf07cf9f59b685d4a3a6e51c9135dc101a4a6a62c95a20902e2fa\ - 23db7d15293f595f86ab -Test: Verify -Message: C83A14EAC016D659F9FE -Signature: \ - 18ed4812925dca6a9c30e2e3566433e202be2d305414e1e6583905ad845cbc63\ - 2049804932aac79b858c -Test: Verify -Message: 745E02041EB487D16CE6 -Signature: \ - 13d4ef1de59ef0fe9bc4ecc6d382908642f6f5793e255b819e25ed124f7fa574\ - d91fc2e9b258f0514b15 -Test: Verify -Message: 62F019655A83501FC4E7 -Signature: \ - 07f797768984ecc792f366ece16f5102aec2aac6d31fdaf3972839cac2c99a2b\ - f5b347c887d37943383c -Test: Verify -Message: 351D37A4B5046E885EAA -Signature: \ - 22064cd5179ff1551dbf73c5220e17a9dfa1aa8f7f22f44a6c70f13c6d0a21f8\ - 7e53278251037a6cdc5e -Test: Verify -Message: 4073D33915F595F4FF9D -Signature: \ - 1f902ea2c9521b8c7f11619d35dd22a4667e2eb89a017194bb68ec0a9df762c9\ - 377c1c075b5f09566048 -Test: Verify -Comment: 1028-bit NR key -KeyFormat: Component -SubgroupOrder: \ - 2368e2b864b250ad45406391e7eeaa3d27cd053c2b -SubgroupGenerator: \ - 07c325695dfe315a77ad7b42f0d18f9d4821b5c153fee7385877602fa54477bb\ - 8c0639d2438f34352b97c22d02a7295d2b53d5286a01caa919d6283614690624\ - 240af922675ccd4a0534ec336cb79cde31b02b5988cc5a53ca17790d67d803a2\ - 7bb927b9c59bdc6ac794175e285cafdece6778ab19a0b444747fee20d5bf929e\ - 70 -Modulus: \ - 0abdeff64b6f28256e4562109bffed29cb5aa95d89cc0ec95da0e773dbff3467\ - c271bbb1e1fbb6af058517fdacdf26b5919674c625eced6317d8631c063f43b3\ - ade2cd633d554913339071d6ebed5fd665fc5dd7d47b80721a976c3b14fbd253\ - f0f988c354725289f2897df0a15985c92b2d4da8d087870c251c72d979b8304d\ - 51 -PrivateExponent: \ - 0771305163506b2b83bd5279935df1b5fcf180b004 -PublicElement: \ - 043e4ae6244408879264fe6b859b578218705b9a45af22efded27141b7f090cb\ - cbe42dcf481df3e41b13920ae02b694eaa6bfd62f2d3c5d677b8c4ce783cbe27\ - 89e088b04489ef535ad4a517351c8835cf128f7ec677a1b1dbe3ae9cc4198ddb\ - 6e1cef8e978c0725f5063797bc43eb9ae496286cccbad5d4e026e9edb997d2f9\ - 18 -Test: KeyPairValidAndConsistent -Message: 4867852C83F181CDD010 -Signature: \ - 1db6a5661b20c9289428c3b9ebf65d5a8f757f3a3b1eb15dfaf0c8cefc891954\ - b48279eb45910a141ec3 -Test: Verify -Message: DA6493C86D6B62C5961C -Signature: \ - 1c05300a56319ba4a8ace1206f5f37b5bbefc9d80a171a57b6da3c02aa1f3079\ - 70583c008f073996d932 -Test: Verify -Message: AE2C1136BFE966794A6C -Signature: \ - 02dfd79eb18f3a862b11a5d199a7db1dc53580ade90517a7739cbd8ab1849c44\ - 54ba17a69b8d03ecc4f9 -Test: Verify -Message: B20160E0442E726BE749 -Signature: \ - 14c0cf809174d39f1324b7dd0d6d1fb3be5b5577c10048b12def39772fa60cd5\ - a9d2cca9075f12e5a3c1 -Test: Verify -Message: 3638935C4492F5CA42F2 -Signature: \ - 0081d7216636bc6fb9bc7a637a377ebf4f9048826e0360c8faf03dd28c4ee4a4\ - da82689259f140b3d918 -Test: Verify -Message: DFB674CA6E0FDC0CBE99 -Signature: \ - 1e3e21aa3dcccddb8cf3e360631fc36956263951ff18fec553531252b4dbe753\ - 6ed5fc62897d51500c38 -Test: Verify -Comment: 1029-bit NR key -KeyFormat: Component -SubgroupOrder: \ - 3357536531dec150be0ef8747f69ea30d987ff7df1 -SubgroupGenerator: \ - 067dd80dbc6b41f58d08f077a9a3dcbfe12a62065fe6b4691c457f506b56dcab\ - 0433b3aad6ef962501633d0f3947b491a1317e7e6b632f062c53104d609c9222\ - b056f08a0c83662a70744331fd09b2b42fb0768e52da27e92732106fbd41ec73\ - 7373fd080b56b543d808d49eeb6e1bb0a8619b1edee8fb8295dc042423f684af\ - 8a -Modulus: \ - 1d0f176b6799b36724c92954c38d0288fa95400c2b14e064f76a6338fccaebca\ - 8d978b93bb76507bc150a50f9fe799fffe12ae2875b13ac1084ffcfde9f62b86\ - 185a72f04ff80538d6eac177edc98d61a517b1275bcf4b57aa262e1702d623bc\ - 344db7e5621c949a9b12e9936e88fae9b200a1f8ad5b40ec8220aa301267f38d\ - d7 -PrivateExponent: \ - 2dcdc00a86ecc2a60ebfa6660a83af1d7c3e570b85 -PublicElement: \ - 13834f0fa1f42abf7dbd264cb7d2eb5798da8972df67f517c62d7ae5070fd588\ - d61db62e492f9654833e876ed5737df35069f5ee01a45de881d8f5e68ec52ad9\ - ef32780e8c453a5f1e38cc17bc5cd061a3c122080f6e1b82d31877e8b08f634f\ - 497bd90b06824eaa0416c64104ce5622c272673d0dedb836ac7d47e0cea06739\ - 02 -Test: KeyPairValidAndConsistent -Message: 1E34034C47FE533F8FF5 -Signature: \ - 05c110848feacc9ac762ffa14943f9ce9a111777de0502d9f364ad9b2df4e1a8\ - 17bc15a602579b3a6a25 -Test: Verify -Message: 53D2CA23AF7DF95634F0 -Signature: \ - 14009997efeb3fd246956e44b5b0e48581ac5f414613b41fe5842c85b031ab8a\ - e68f66f8e1f1f9fc1d74 -Test: Verify -Message: 0F056E08AE77B3B30F33 -Signature: \ - 1beedf85b426d36a657f422ab9a9132986eaf415332816d33d70c726c3066158\ - c6481fd00503ffb65518 -Test: Verify -Message: F08C80E8FD38A3867B76 -Signature: \ - 0a23b8d8f920cfb0dec93725e4972080445647c54227fb987dd9f80fab446c75\ - 1c2594276168aa68f318 -Test: Verify -Message: 6D392690B92B3E75020F -Signature: \ - 18668f59c6974dad551a89bec5cacf0bf8617e8f43052eb97d7a1b12411b27b7\ - 4248b3d1f5070823e951 -Test: Verify -Message: 10AE0E091A267641FACF -Signature: \ - 1b3d10f74fdaed3d4d61fedfa3f6ad3a37c0cf6687166a312d5b280724c3545d\ - 225e1fe0639cfb1113d6 -Test: Verify -Comment: 1030-bit NR key -KeyFormat: Component -SubgroupOrder: \ - 27c7996c1d3729c4cf1de06529e5619771e27ad9eb -SubgroupGenerator: \ - 0d87a4b01385da7f43b6277933c5f0dc8072dcacd5252e1b29f588114a7ac56e\ - 377050aa8174b5dda400f043234e4a746442792734dc80274a00a3676101be94\ - 759fc2630b9a858966488b12611d03d0b31e7243e124497a754544cee1db10bb\ - 0a81cf0b2a68045b76fe935f641c666fdc788a2b968c6668c669115756b961d9\ - fe -Modulus: \ - 2a32d68d31248024053bf628a94404b9a49d91ade4d7a45b071e93292a7f8c26\ - 61d9165f0ab85491d4b0dc67d335fa7d7dd172cb17193390a55eb000aa97e2b8\ - ed3ee64b73aa43ea9b8979132c2d966ab03c42cc14782c96e4284ee1136b8515\ - 007ed1b1a5708b5e8d81304fa651edc715918e2299cfe9016dfec5f454d907f5\ - 9f -PrivateExponent: \ - 091155581ecb7a0a792ba95c772d9382298bfdfa6f -PublicElement: \ - 0d7d22c931422fc46505887559a51490c2e367cdb40242cdbaeb23024693fd5c\ - 68f6a3307ca34b224457d5aa610b90eca3b39905481daaba7151318f09f974ad\ - 664546d14c87f797e38139ee1e07adba9c775e07b7f7b3edba87d886920d6b2c\ - ef5f084359566b0a3b8b940a65b9ad93fd7ccd1354cdcee3c43c6bd315180498\ - ad -Test: KeyPairValidAndConsistent -Message: 23EEE1D0EA8950B8F322 -Signature: \ - 18fe1a5f61c4946810e82a1e30fb6c87ce4ad9cebb1ae27eebfa8779fe292b2a\ - 451be3506bb65519dfd0 -Test: Verify -Message: 13FA6F2816FB83190A21 -Signature: \ - 2161a5be85f7ffe806df00f4bd50915e4b0674e7591f1c0902153823f881bc7b\ - 3f093d92bf86b74b5b3e -Test: Verify -Message: D071CCC0C6E4CAE82E5A -Signature: \ - 059158b2cf143f38eb8c51088dd79bf45990e596c8026fa3de5e668368b9d8d7\ - fe9ffdbdecf66aaf02bb -Test: Verify -Message: 22CE83F4803BF3EA2C48 -Signature: \ - 073b56d72a5b706455cfdcbf85b75ee45c40e96dd21a5460542ade665e51a85c\ - 510315a50307c2bbdb2d -Test: Verify -Message: 7A927EC7BB9CA16C1B0A -Signature: \ - 254c7525aad9b4b3807b3900a963fbf42f9ff2144820ea69abe5ba2c80613510\ - e1429ebc726fd0a87a4c -Test: Verify -Message: 9591B069993E10BC0B84 -Signature: \ - 0ed4210e5e4f2f9546ea181c4a61d062a1158810071905b180dbf070b480f436\ - 0b1f66065ecf111741cf -Test: Verify -Comment: 1031-bit NR key -KeyFormat: Component -SubgroupOrder: \ - 26f86a81a6bb530c2f9b63e3690e95a0894575f445 -SubgroupGenerator: \ - 1e24828adb4ebf2becdbdcadf6706631293ad6566803d12479f04a7bb20b6086\ - fe81df164f8bd02c5f418c1140d143f11a71170b42d0753c952bfff951b9ca42\ - 04868375efaa4afad50b75787e41c5ab9ce8adcbccecd3716f350bb8aaeca9b6\ - 098bd0002d789e1f7db9c19d9045499877b93ecb4e7c64808b742063bbecf60e\ - 29 -Modulus: \ - 4d58515f7b41c4fc87e4fcefe5cf6d84b2d74a9d6f498ae9605fcbf1c5921742\ - 2001a272ef91dbd09e7af5ee54126dd4fc44bb1ed624d0dd5dafb984d5278114\ - 0bba40600cbd4752d2c32b43253efee57af6964c339570edb24195502e6d424b\ - 84bed65ac98c6fc52ec90e40a525f1863a53f2fbe2a0a133342eff4337f26ceb\ - 93 -PrivateExponent: \ - 0e61a054ee6510734a80f67a54d8c4151c957ef16f -PublicElement: \ - 19b50f1eea45bfaa22352a38f3c3b86d6f670747ac2fd94359608e25f2bb9f60\ - 2506bc357245deeb4c3c702d435c557da4f4a9fd37330a75547c91681fdbb51f\ - 286adb498d1e489e89b2e6a4eb9ff30222c51fefbeac7435f629f536ac2d6b87\ - 664d80e5c97398cf489a1d1ca217f7f21ea8e409f938378875cf5f528162e3bc\ - 07 -Test: KeyPairValidAndConsistent -Message: B4B3C8FBE82013228A21 -Signature: \ - 0e1003dd216194ded89f7d10b35a266ca7587d8cfb06a1fe3dd43f07dea4a6d6\ - acaa1477f2552c9b3114 -Test: Verify -Message: 17D2D18302173E2CE992 -Signature: \ - 027b40cd9a159257a57efae3a657399a3b6d8b06f707ba3a323abc383a93f919\ - 1246c38c03b028be05df -Test: Verify -Message: 8032AE177D6DF38C7E27 -Signature: \ - 1f5e3d759e3b832f5a6c57b055764ff5b8ad942dd819610ef94cfec296cd1b56\ - 4fd0b18bfa08c3645db3 -Test: Verify -Message: 768640A60A3C62E02428 -Signature: \ - 0abe2dfabc81ab677d2cbd781ef9768325a5d6d15a22f41b32972bd67058e617\ - e28c7e0dfbaae535d655 -Test: Verify -Message: B0999CA45B77ED63639D -Signature: \ - 1525539cd207d5f6f915eb2731b6451e38e11e0a031d7e420e0bb95d6616d8ef\ - 35d20eb43c111f8f9ca1 -Test: Verify -Message: 587EDB968FA82C12C930 -Signature: \ - 024ed20dc19a07e00158aa2fe9cb6353f0112b8fab0e6775667115e1c92e5eb4\ - 29876c12ed48e996f4f7 -Test: Verify -Comment: 1032-bit NR key -KeyFormat: Component -SubgroupOrder: \ - 2e802b5369c3f1ddfa789bf8f2ad2e048ced3bf355 -SubgroupGenerator: \ - a9aebee7d29f90b081afc4d496a6a78210e918bb57a8a21c5995586c0bf20f7a\ - 56bb10a97e05a3a723e7db64612b12bb591b1fe7d2e46be8c96a7b2ce7c66076\ - aeded938775ae2223900adaf52a93f52d62173c82d4b67388c85d4c1127e1edf\ - 4643cf09f5375b60c19316c4f8f8fd7daea1d8b44a2d03e97c2741537f63d86b\ - 4a -Modulus: \ - d551680a62ebf98f0ed8930cc5b12de86d0a0c29a0d7e5524c24672a25428833\ - f4c19ac883ead22efcc0c6823f2e942c17adb7ab763ff2c7cc2698fa8b6448e5\ - 14d4628b197721bdaec780e126ac80ac83f24fef5c154f7690ceba903748be52\ - 12e3180ea718ca7a71a49dee939bf9bc5b7845c9648d074587ccd3724493b91f\ - 09 -PrivateExponent: \ - 0f66e04c5a75d3eac03d744e5432f23e3aea066a63 -PublicElement: \ - 2640c188055329f0b44aaf80f82f7fc7f0e421031834dfbd1fb6d6af6ab3e1c1\ - 73c901370a4ce2793c1b88d12f764c58ff064905da9c5001f679c7508972f237\ - bccca56524787466a7c9c2d6bb6392963008ed1a3e4cf3b13e66086bce3a4ca0\ - 4d8cabcf0cadb4c403c7d02a858460d04350e730289cb5adf200b5fdf1198168\ - b5 -Test: KeyPairValidAndConsistent -Message: 909068BEFFA43331FDC7 -Signature: \ - 2d557d8fae420880640dd9f60a524db48980c80d8b0179dd3c1892f02e87c9f6\ - a04a8aa731be05aaffef -Test: Verify -Message: AC8AFC7A1D9105539E10 -Signature: \ - 0ae7f23328453fdb03c090c09ee69d787ee7dfaccd047445b1026a9a7cacdd1f\ - 91455db7299538817894 -Test: Verify -Message: 310E40311BB3F77F9483 -Signature: \ - 28a8d8de06dc0011b044d19a163d350535d6ca91a023c9687557690ddf102d8c\ - 7558246ced311f2fc444 -Test: Verify -Message: 35455ABD53E6FB11ED9B -Signature: \ - 162156e476cba65e767b4db942bb35cdc6293cf4360f1801a215bb2c726c22af\ - f3a711d3c6473f1eb985 -Test: Verify -Message: 95FFA73B52F0D06A0C1E -Signature: \ - 29bf4f13e6aff528aa1b060c2baed865c442e0472422b4bd485aa5ba2a09ad0d\ - 732637bb3ee520f6bc0b -Test: Verify -Message: 1E9934125DA6E9B4E975 -Signature: \ - 1674975d0a97e799d113ff9cad06b7f70a33f5ca5f1916cee07b525270284fbb\ - 1c0428666987ad7e2116 -Test: Verify -Comment: 1536-bit NR key -KeyFormat: Component -SubgroupOrder: \ - 232cf9bee9d56c8bd8252d1edb59d99c40cf32d07d9e5a4893 -SubgroupGenerator: \ - f028143e3f9d1317aafb814215ffda9c584da8943e96212c90a082c3d2f335e8\ - a6b64d1c890aa2224ebf158bec2b6fe6bad236417acd517a4907331e0be0dd0b\ - 801218ac270acdd45579290be1b94bc418b8f82c651d82a19d2f0e1cbb0fbc0f\ - 054d95150af96f9a7488010787a799c544883ff76a4e3092f2ca9aa9000cecb8\ - 8dda343c972c8192a83820727b1945c1a270cf913ab932457e8e6e207d06cd0e\ - fdf265b762b9fa15c9a14633af17204ba2b755ed1b3b421ac596a2a04e64be43 -Modulus: \ - fada6e4becef964a85caf9e129639a5616ac000dbac59bd50b84bc8d46411407\ - 9c34c5b58d7d40027faaf037c6a649c527cb002d3a716bdef62b6c94d7a47a8b\ - 65c2ebac05da09e40cdc417024cccba267a98f4eb69701a276b4f117662b5666\ - 05c36054e7f015d2e5f81331e5666ec17ebf71907788b40cbcea0f24aaffb029\ - ef5c25c55ae998f28a2ddb091d262c32ad324f4e64c7b4b50a19e9d92f6d8024\ - 188627cf5ce68674e7ec7da38fd6cf4ec29a6ce2f17e3188d8ef6b0e50d77d5b -PrivateExponent: \ - 1d4cedc87d55eea31bd702139b90be08d58692a1f97628a01b -PublicElement: \ - 819c8cedb9c014aa577e9046b90795accbebe81bef68b1b5c37c68cb357e1a5f\ - f92761bc26cb0953956b6c0aec05acfc9d1a27c50789793b13d9eaf2361760c9\ - 7a7d86e7d922f4809a5d2d01448e938190bbc24c150e03ef8305365ddbf5ca19\ - 6857314e3b3023f8ddc9d209bd7dad1ee763e7003fd1b0c53057d2e9acadd23a\ - a18f83d20143bc41a2dfa4a164c82621fc0f800052ec01bec7c99c66fe20ec57\ - 67e6fbbe8810cd5aa75eff3d8a4cb53e1259ebcfebcc2fcf21ba7f3589cd525a -Test: KeyPairValidAndConsistent -Message: 9F6DC301DF53FE22CAC0 -Signature: \ - 15b22111ffa1b733979cd9d8944b1291ce09468ccbd05040de0f83023c8fe083\ - 734ec39a542011643e448b01429c4bae06d1 -Test: Verify -Message: 2D7B5B9A27EAB468331E -Signature: \ - 029eea970a049ffcb4c6117c97d181bec7a27557ceb88d422b2212ca36238380\ - 87cd52d2445f539c9c03705ba4b485f56e19 -Test: Verify -Message: F552FCBBA04FFCCC5CB6 -Signature: \ - 115de3cc15d9a066c00fed43f583f6a9c984d4b8f4c93c3d72094a4b04dda506\ - 7d460c3d1ae33ba66ceaac676256c1e73001 -Test: Verify -Message: 0D52B894153A4BB74068 -Signature: \ - 0f6b8cc28e2068a3fe14d220177793daf3512ba6942e9d16ef1571fa34926c27\ - edd1bfa94723a663425f5c2d01eaddaa972e -Test: Verify -Message: 294442E103CC0CBA32A6 -Signature: \ - 0fbd8768a1b3025c0d0d309cc448320e086318772bb9485a5a0a2afa1eb2afb2\ - d1818aa7b1c55b9dc424e654524278f0ddbc -Test: Verify -Message: E993D8FE1E6F6C3914ED -Signature: \ - 0559d66bad3a51520bbb85827a257ab09dfa33938127c69bf40f08339b2f2251\ - c0e50b63d2a4d05225dea7f58f67de3071e9 -Test: Verify -Comment: 2048-bit NR key -KeyFormat: Component -SubgroupOrder: \ - 03f35f80fcd896f03eda9ff07f2e35295384c4f3b8f8c4821369ab5417 -SubgroupGenerator: \ - 75c5d8c8f72302d92be3bf486b8648330ff86954de5e6e83efef624a277574c1\ - 6757684d3874ee303fa08343fe82dae484e5dda6781280b434c4090044cc7ff9\ - b6e962594d3ca069815c0f0b6bfd25215a419420d0ef8a1595c6eb1b44a719b4\ - 0131081f75cc15cb09a5d5a029c8546230c30b4af2d4a9f4374c93a095c83b59\ - 4b1774d635d4aee965f1d094469f7bbf8bdc93216a6b8a6c5753b48962335bf2\ - 092aa583c897878c8a7ce61186b592b05d2aea710b673d5994cedb5f117fdb6b\ - 8ad4d89f443c4eb662b428a34a7522c69794cc0274f3eba837e90da86acbc707\ - 4ee3a0b029d970efa48b3d582b740ae0e585d175a5f63a385f8b6b8878b44e1a -Modulus: \ - 9a08865d2bc9e0cf03d2500b2a08402bb9dc953d5fcd73f04be61236efc0998a\ - 8f012f00e52f7a6e91e81b88a4c9f985a2da523cbe7caff08cae44963d2035ed\ - a72e1f31f82c8d64c86e686899d53c0200282f407ceb1507db480f1db223606a\ - 57466cf60fe9fc5f7ea7d5fd82ed3ab2cf5e35491dfaef0aa2e10fbfa3cdfeb5\ - ebf65e4dfc2837e1f6399db06cc2e0420c7b14a4c0d483b742ca58b31fec9f26\ - a64e9bfcaa82334e644f4b954e2a9c7eeae096b8864ecd223ead3bcf9e8c1f68\ - f6678faccdb7f26d8f33d8a5fb0cb156cc7daf4a96ec2b730c0d7f666d699f73\ - 45a37ddc1ccdea6d8f439ddb23de04a941b246bc257b0aef544a8e868bc8444f -PrivateExponent: \ - 0212c34d3d17b96a899548ebf43bb886676acebd2f040f5b33a4e88d2d -PublicElement: \ - 267f9c3ff3ee3cbc0f9e94dc7e6837e1ff65175e967987b90b9aea7eef1de6e4\ - c342bebb5dbd0c4e2f6514f2d487857a146dda6cfdbc8b56ed254cd65754d84d\ - d21a271cd15fc656274725643728b41ce3f0e6872b6dfb4c289e03f9b903880c\ - e3d7d745dfbb641c8c42ec0bfb6951ca2611fd877c32248c97252bdb42d7bd65\ - ebc50653dff389526c546d1e6ebaf6bd8b3298c01935901b7efb288b78730d89\ - fba7f46f2a642aee0dbc93aa29c190b201acf89d4f8ba28f3e3f54a1c5a48294\ - dda908f904afb7db398682c809ce13abd49279221d5b40ad76216bad7ca256d7\ - 18d3552344c481b20da5aac3e637fb7edeaf7960b532ef761376489f02fa8c10 -Test: KeyPairValidAndConsistent -Message: 5F3914F7AE0F6C76D152 -Signature: \ - 03d30b7eaaddcb384dce378f806e88d646419bbedbc2c0c5cae32f3c3b02e0e1\ - a3c3ab04b31e2c25db713db539a65c9419a846aea88aaa707cb4 -Test: Verify -Message: 769583D4E7EAD14C137A -Signature: \ - 01dc2815fd4918b8d3bd1743f5ab4546313b1fa8044b4737b2c485eeb0016bcc\ - cc084be064b6a8934a28011167eebbc33513ce609aa206810aa1 -Test: Verify -Message: 6441D5239F50C71DE0F5 -Signature: \ - 013f6d395de56832f82ee813b574002c36e551aaeffbb28ddebb84da7f01ff6f\ - 4c3d0f3519d548e2ec1a0b36f12ac1e4fedc83071bbbbce024a6 -Test: Verify -Message: F1C2D4F7C3ECDF2C17B7 -Signature: \ - 006441a8b3517613f9a8c2e7a89c492e7f49300d901ad01b92167c1fce02453d\ - 52b69dc1fc6532e792ad6366eae7fb14de3ad3f6f3132b0519fc -Test: Verify -Message: 752A1F2B8D9A717A882F -Signature: \ - 0127027984402f5b8cc069decc1bd611f0bb59c6eee86da7d334e3f8b903c5f3\ - 02c65aaf16a837963bf772931235f81e963e4d692699dfd4f7e1 -Test: Verify -Message: 666DC6B1E871026EDE56 -Signature: \ - 03e87b55a7e81318b7599da3fa8f18d46253b6546814fd1ae19318820100c297\ - 4de2624da0d54ca27e7fe3477913a6df35bf925de3f3d9a06849 -Test: Verify diff --git a/embeddedcryptopp/TestVectors/panama.txt b/embeddedcryptopp/TestVectors/panama.txt deleted file mode 100644 index bd4d4ee..0000000 --- a/embeddedcryptopp/TestVectors/panama.txt +++ /dev/null @@ -1,76 +0,0 @@ -AlgorithmType: MessageDigest -Name: Panama-LE -Source: Panama reference implementation -Message: "" -Digest: aa0cc954d757d7ac7779ca3342334ca471abd47d5952ac91ed837ecd5b16922b -Test: Verify -Message: "The quick brown fox jumps over the lazy dog" -Digest: 5f5ca355b90ac622b0aa7e654ef5f27e9e75111415b48b8afe3add1c6b89cba1 -Test: Verify -Source: generated by Crypto++ 5.2.1 -Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" -Digest: af9c66fb6058e2232a5dfba063ee14b0f86f0e334e165812559435464dd9bb60 -Test: Verify - -AlgorithmType: MessageDigest -Name: Panama-BE -Source: Panama reference implementation -Message: "" -Digest: e81aa04523532dd7267e5c5bc3ba0e289837a62ba032350351980e960a84b0af -Test: Verify -Message: "The quick brown fox jumps over the lazy dog" -Digest: 8fa7dadce0110f979a0b795e76b2c25628d8bda88747758149c42e3bc13f85bc -Test: Verify -Source: generated by Crypto++ 5.2.1 -Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" -Digest: cb34f0937e8d870d3bd7ff6311765f2c229a6c2154e4db119538db5159437cab -Test: Verify - -AlgorithmType: MAC -Name: Panama-LE -Source: modified from Panama hash test vectors -Key: "" -Message: "" -MAC: aa0cc954d757d7ac7779ca3342334ca471abd47d5952ac91ed837ecd5b16922b -Test: Verify -Message: "The quick brown fox jumps over the lazy dog" -MAC: 5f5ca355b90ac622b0aa7e654ef5f27e9e75111415b48b8afe3add1c6b89cba1 -Test: Verify -Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" -MAC: af9c66fb6058e2232a5dfba063ee14b0f86f0e334e165812559435464dd9bb60 -Test: Verify -Key: "The " -Message: "quick brown fox jumps over the lazy dog" -MAC: 5f5ca355b90ac622b0aa7e654ef5f27e9e75111415b48b8afe3add1c6b89cba1 -Test: Verify - -AlgorithmType: MAC -Name: Panama-BE -Source: modified from Panama hash test vectors -Key: "" -Message: "" -MAC: e81aa04523532dd7267e5c5bc3ba0e289837a62ba032350351980e960a84b0af -Test: Verify -Message: "The quick brown fox jumps over the lazy dog" -MAC: 8fa7dadce0110f979a0b795e76b2c25628d8bda88747758149c42e3bc13f85bc -Test: Verify -Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" -MAC: cb34f0937e8d870d3bd7ff6311765f2c229a6c2154e4db119538db5159437cab -Test: Verify -Key: "The " -Message: "quick brown fox jumps over the lazy dog" -MAC: 8fa7dadce0110f979a0b795e76b2c25628d8bda88747758149c42e3bc13f85bc -Test: Verify - -AlgorithmType: SymmetricCipher -Source: generated by Crypto++ 5.2.1 -Key: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f -IV: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f -Name: Panama-LE -Plaintext: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f -Ciphertext: F07F5FF2CCD01A0A7D44ACD6D239C2AF0DA1FF35275BAF5DFA6E09411B79D8B9 -Test: Encrypt -Name: Panama-BE -Plaintext: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f -Ciphertext: E12E2F6BA41AE832D888DA9FA6863BC37C0E996F190A1711330322D37BD98CA4 -Test: Encrypt diff --git a/embeddedcryptopp/TestVectors/rsa_oaep.txt b/embeddedcryptopp/TestVectors/rsa_oaep.txt deleted file mode 100644 index 4e4cdd3..0000000 --- a/embeddedcryptopp/TestVectors/rsa_oaep.txt +++ /dev/null @@ -1,1765 +0,0 @@ -AlgorithmType: AsymmetricCipher -Name: RSA/OAEP-MGF1(SHA-1) -Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors -KeyFormat: Component -Comment: Example 1: A 1024-bit RSA Key Pair -Modulus: \ -a8 b3 b2 84 af 8e b5 0b 38 70 34 a8 60 f1 46 c4 \ -91 9f 31 87 63 cd 6c 55 98 c8 ae 48 11 a1 e0 ab \ -c4 c7 e0 b0 82 d6 93 a5 e7 fc ed 67 5c f4 66 85 \ -12 77 2c 0c bc 64 a7 42 c6 c6 30 f5 33 c8 cc 72 \ -f6 2a e8 33 c4 0b f2 58 42 e9 84 bb 78 bd bf 97 \ -c0 10 7d 55 bd b6 62 f5 c4 e0 fa b9 84 5c b5 14 \ -8e f7 39 2d d3 aa ff 93 ae 1e 6b 66 7b b3 d4 24 \ -76 16 d4 f5 ba 10 d4 cf d2 26 de 88 d3 9f 16 fb -PublicExponent: 01 00 01 -PrivateExponent: \ -53 33 9c fd b7 9f c8 46 6a 65 5c 73 16 ac a8 5c \ -55 fd 8f 6d d8 98 fd af 11 95 17 ef 4f 52 e8 fd \ -8e 25 8d f9 3f ee 18 0f a0 e4 ab 29 69 3c d8 3b \ -15 2a 55 3d 4a c4 d1 81 2b 8b 9f a5 af 0e 7f 55 \ -fe 73 04 df 41 57 09 26 f3 31 1f 15 c4 d6 5a 73 \ -2c 48 31 16 ee 3d 3d 2d 0a f3 54 9a d9 bf 7c bf \ -b7 8a d8 84 f8 4d 5b eb 04 72 4d c7 36 9b 31 de \ -f3 7d 0c f5 39 e9 cf cd d3 de 65 37 29 ea d5 d1 -Prime1: \ -d3 27 37 e7 26 7f fe 13 41 b2 d5 c0 d1 50 a8 1b \ -58 6f b3 13 2b ed 2f 8d 52 62 86 4a 9c b9 f3 0a \ -f3 8b e4 48 59 8d 41 3a 17 2e fb 80 2c 21 ac f1 \ -c1 1c 52 0c 2f 26 a4 71 dc ad 21 2e ac 7c a3 9d -Prime2: \ -cc 88 53 d1 d5 4d a6 30 fa c0 04 f4 71 f2 81 c7 \ -b8 98 2d 82 24 a4 90 ed be b3 3d 3e 3d 5c c9 3c \ -47 65 70 3d 1d d7 91 64 2f 1f 11 6a 0d d8 52 be \ -24 19 b2 af 72 bf e9 a0 30 e8 60 b0 28 8b 5d 77 -ModPrime1PrivateExponent: \ -0e 12 bf 17 18 e9 ce f5 59 9b a1 c3 88 2f e8 04 \ -6a 90 87 4e ef ce 8f 2c cc 20 e4 f2 74 1f b0 a3 \ -3a 38 48 ae c9 c9 30 5f be cb d2 d7 68 19 96 7d \ -46 71 ac c6 43 1e 40 37 96 8d b3 78 78 e6 95 c1 -ModPrime2PrivateExponent: \ -95 29 7b 0f 95 a2 fa 67 d0 07 07 d6 09 df d4 fc \ -05 c8 9d af c2 ef 6d 6e a5 5b ec 77 1e a3 33 73 \ -4d 92 51 e7 90 82 ec da 86 6e fe f1 3c 45 9e 1a \ -63 13 86 b7 e3 54 c8 99 f5 f1 12 ca 85 d7 15 83 -MultiplicativeInverseOfPrime2ModPrime1: \ -4f 45 6c 50 24 93 bd c0 ed 2a b7 56 a3 a6 ed 4d \ -67 35 2a 69 7d 42 16 e9 32 12 b1 27 a6 3d 54 11 \ -ce 6f a9 8d 5d be fd 73 26 3e 37 28 14 27 43 81 \ -81 66 ed 7d d6 36 87 dd 2a 8c a1 d2 f4 fb d8 e1 -Test: KeyPairValidAndConsistent -Comment: RSAES-OAEP Encryption Example 1.1 -Plaintext: \ -66 28 19 4e 12 07 3d b0 3b a9 4c da 9e f9 53 23 \ -97 d5 0d ba 79 b9 87 00 4a fe fe 34 -Seed: # not used yet\ -18 b7 76 ea 21 06 9d 69 77 6a 33 e9 6b ad 48 e1 \ -dd a0 a5 ef -Ciphertext: \ -35 4f e6 7b 4a 12 6d 5d 35 fe 36 c7 77 79 1a 3f \ -7b a1 3d ef 48 4e 2d 39 08 af f7 22 fa d4 68 fb \ -21 69 6d e9 5d 0b e9 11 c2 d3 17 4f 8a fc c2 01 \ -03 5f 7b 6d 8e 69 40 2d e5 45 16 18 c2 1a 53 5f \ -a9 d7 bf c5 b8 dd 9f c2 43 f8 cf 92 7d b3 13 22 \ -d6 e8 81 ea a9 1a 99 61 70 e6 57 a0 5a 26 64 26 \ -d9 8c 88 00 3f 84 77 c1 22 70 94 a0 d9 fa 1e 8c \ -40 24 30 9c e1 ec cc b5 21 00 35 d4 7a c7 2e 8a -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 1.2 -Plaintext: \ -75 0c 40 47 f5 47 e8 e4 14 11 85 65 23 29 8a c9\ -ba e2 45 ef af 13 97 fb e5 6f 9d d5 -Seed: # not used yet\ -0c c7 42 ce 4a 9b 7f 32 f9 51 bc b2 51 ef d9 25\ -fe 4f e3 5f -Ciphertext: \ -64 0d b1 ac c5 8e 05 68 fe 54 07 e5 f9 b7 01 df\ -f8 c3 c9 1e 71 6c 53 6f c7 fc ec 6c b5 b7 1c 11\ -65 98 8d 4a 27 9e 15 77 d7 30 fc 7a 29 93 2e 3f\ -00 c8 15 15 23 6d 8d 8e 31 01 7a 7a 09 df 43 52\ -d9 04 cd eb 79 aa 58 3a dc c3 1e a6 98 a4 c0 52\ -83 da ba 90 89 be 54 91 f6 7c 1a 4e e4 8d c7 4b\ -bb e6 64 3a ef 84 66 79 b4 cb 39 5a 35 2d 5e d1\ -15 91 2d f6 96 ff e0 70 29 32 94 6d 71 49 2b 44 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 1.3 -Plaintext: \ -d9 4a e0 83 2e 64 45 ce 42 33 1c b0 6d 53 1a 82\ -b1 db 4b aa d3 0f 74 6d c9 16 df 24 d4 e3 c2 45\ -1f ff 59 a6 42 3e b0 e1 d0 2d 4f e6 46 cf 69 9d\ -fd 81 8c 6e 97 b0 51 -Seed: # not used yet\ -25 14 df 46 95 75 5a 67 b2 88 ea f4 90 5c 36 ee\ -c6 6f d2 fd -Ciphertext: \ -42 37 36 ed 03 5f 60 26 af 27 6c 35 c0 b3 74 1b\ -36 5e 5f 76 ca 09 1b 4e 8c 29 e2 f0 be fe e6 03\ -59 5a a8 32 2d 60 2d 2e 62 5e 95 eb 81 b2 f1 c9\ -72 4e 82 2e ca 76 db 86 18 cf 09 c5 34 35 03 a4\ -36 08 35 b5 90 3b c6 37 e3 87 9f b0 5e 0e f3 26\ -85 d5 ae c5 06 7c d7 cc 96 fe 4b 26 70 b6 ea c3\ -06 6b 1f cf 56 86 b6 85 89 aa fb 7d 62 9b 02 d8\ -f8 62 5c a3 83 36 24 d4 80 0f b0 81 b1 cf 94 eb -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 1.4 -Plaintext: \ -52 e6 50 d9 8e 7f 2a 04 8b 4f 86 85 21 53 b9 7e\ -01 dd 31 6f 34 6a 19 f6 7a 85 -Seed: # not used yet\ -c4 43 5a 3e 1a 18 a6 8b 68 20 43 62 90 a3 7c ef\ -b8 5d b3 fb -Ciphertext: \ -45 ea d4 ca 55 1e 66 2c 98 00 f1 ac a8 28 3b 05\ -25 e6 ab ae 30 be 4b 4a ba 76 2f a4 0f d3 d3 8e\ -22 ab ef c6 97 94 f6 eb bb c0 5d db b1 12 16 24\ -7d 2f 41 2f d0 fb a8 7c 6e 3a cd 88 88 13 64 6f\ -d0 e4 8e 78 52 04 f9 c3 f7 3d 6d 82 39 56 27 22\ -dd dd 87 71 fe c4 8b 83 a3 1e e6 f5 92 c4 cf d4\ -bc 88 17 4f 3b 13 a1 12 aa e3 b9 f7 b8 0e 0f c6\ -f7 25 5b a8 80 dc 7d 80 21 e2 2a d6 a8 5f 07 55 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 1.5 -Plaintext: \ -8d a8 9f d9 e5 f9 74 a2 9f ef fb 46 2b 49 18 0f\ -6c f9 e8 02 -Seed: # not used yet\ -b3 18 c4 2d f3 be 0f 83 fe a8 23 f5 a7 b4 7e d5\ -e4 25 a3 b5 -Ciphertext: \ -36 f6 e3 4d 94 a8 d3 4d aa cb a3 3a 21 39 d0 0a\ -d8 5a 93 45 a8 60 51 e7 30 71 62 00 56 b9 20 e2\ -19 00 58 55 a2 13 a0 f2 38 97 cd cd 73 1b 45 25\ -7c 77 7f e9 08 20 2b ef dd 0b 58 38 6b 12 44 ea\ -0c f5 39 a0 5d 5d 10 32 9d a4 4e 13 03 0f d7 60\ -dc d6 44 cf ef 20 94 d1 91 0d 3f 43 3e 1c 7c 6d\ -d1 8b c1 f2 df 7f 64 3d 66 2f b9 dd 37 ea d9 05\ -91 90 f4 fa 66 ca 39 e8 69 c4 eb 44 9c bd c4 39 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 1.6 -Plaintext: \ -26 52 10 50 84 42 71 -Seed: # not used yet\ -e4 ec 09 82 c2 33 6f 3a 67 7f 6a 35 61 74 eb 0c\ -e8 87 ab c2 -Ciphertext: \ -42 ce e2 61 7b 1e ce a4 db 3f 48 29 38 6f bd 61\ -da fb f0 38 e1 80 d8 37 c9 63 66 df 24 c0 97 b4\ -ab 0f ac 6b df 59 0d 82 1c 9f 10 64 2e 68 1a d0\ -5b 8d 78 b3 78 c0 f4 6c e2 fa d6 3f 74 e0 ad 3d\ -f0 6b 07 5d 7e b5 f5 63 6f 8d 40 3b 90 59 ca 76\ -1b 5c 62 bb 52 aa 45 00 2e a7 0b aa ce 08 de d2\ -43 b9 d8 cb d6 2a 68 ad e2 65 83 2b 56 56 4e 43\ -a6 fa 42 ed 19 9a 09 97 69 74 2d f1 53 9e 82 55 -Test: DecryptMatch - -AlgorithmType: AsymmetricCipher -Name: RSA/OAEP-MGF1(SHA-1) -Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors -KeyFormat: Component -Comment: Example 2: A 1025-bit RSA Key Pair -Modulus: \ -01 94 7c 7f ce 90 42 5f 47 27 9e 70 85 1f 25 d5\ -e6 23 16 fe 8a 1d f1 93 71 e3 e6 28 e2 60 54 3e\ -49 01 ef 60 81 f6 8c 0b 81 41 19 0d 2a e8 da ba\ -7d 12 50 ec 6d b6 36 e9 44 ec 37 22 87 7c 7c 1d\ -0a 67 f1 4b 16 94 c5 f0 37 94 51 a4 3e 49 a3 2d\ -de 83 67 0b 73 da 91 a1 c9 9b c2 3b 43 6a 60 05\ -5c 61 0f 0b af 99 c1 a0 79 56 5b 95 a3 f1 52 66\ -32 d1 d4 da 60 f2 0e da 25 e6 53 c4 f0 02 76 6f\ -45 -PublicExponent: \ -01 00 01 -PrivateExponent: \ -08 23 f2 0f ad b5 da 89 08 8a 9d 00 89 3e 21 fa\ -4a 1b 11 fb c9 3c 64 a3 be 0b aa ea 97 fb 3b 93\ -c3 ff 71 37 04 c1 9c 96 3c 1d 10 7a ae 99 05 47\ -39 f7 9e 02 e1 86 de 86 f8 7a 6d de fe a6 d8 cc\ -d1 d3 c8 1a 47 bf a7 25 5b e2 06 01 a4 a4 b2 f0\ -8a 16 7b 5e 27 9d 71 5b 1b 45 5b dd 7e ab 24 59\ -41 d9 76 8b 9a ce fb 3c cd a5 95 2d a3 ce e7 25\ -25 b4 50 16 63 a8 ee 15 c9 e9 92 d9 24 62 fe 39 -Prime1: \ -01 59 db de 04 a3 3e f0 6f b6 08 b8 0b 19 0f 4d\ -3e 22 bc c1 3a c8 e4 a0 81 03 3a bf a4 16 ed b0\ -b3 38 aa 08 b5 73 09 ea 5a 52 40 e7 dc 6e 54 37\ -8c 69 41 4c 31 d9 7d db 1f 40 6d b3 76 9c c4 1a\ -43 -Prime2: \ -01 2b 65 2f 30 40 3b 38 b4 09 95 fd 6f f4 1a 1a\ -cc 8a da 70 37 32 36 b7 20 2d 39 b2 ee 30 cf b4\ -6d b0 95 11 f6 f3 07 cc 61 cc 21 60 6c 18 a7 5b\ -8a 62 f8 22 df 03 1b a0 df 0d af d5 50 6f 56 8b\ -d7 -ModPrime1PrivateExponent: \ -43 6e f5 08 de 73 65 19 c2 da 4c 58 0d 98 c8 2c\ -b7 45 2a 3f b5 ef ad c3 b9 c7 78 9a 1b c6 58 4f\ -79 5a dd bb d3 24 39 c7 46 86 55 2e cb 6c 2c 30\ -7a 4d 3a f7 f5 39 ee c1 57 24 8c 7b 31 f1 a2 55 -ModPrime2PrivateExponent: \ -01 2b 15 a8 9f 3d fb 2b 39 07 3e 73 f0 2b dd 0c\ -1a 7b 37 9d d4 35 f0 5c dd e2 ef f9 e4 62 94 8b\ -7c ec 62 ee 90 50 d5 e0 81 6e 07 85 a8 56 b4 91\ -08 dc b7 5f 36 83 87 4d 1c a6 32 9a 19 01 30 66\ -ff -MultiplicativeInverseOfPrime2ModPrime1: \ -02 70 db 17 d5 91 4b 01 8d 76 11 8b 24 38 9a 73\ -50 ec 83 6b 00 63 a2 17 21 23 6f d8 ed b6 d8 9b\ -51 e7 ee b8 7b 61 1b 71 32 cb 7e a7 35 6c 23 15\ -1c 1e 77 51 50 7c 78 6d 9e e1 79 41 70 a8 c8 e8 -Test: KeyPairValidAndConsistent -Comment: RSAES-OAEP Encryption Example 2.1 -Plaintext: \ -8f f0 0c aa 60 5c 70 28 30 63 4d 9a 6c 3d 42 c6\ -52 b5 8c f1 d9 2f ec 57 0b ee e7 -Seed: # not used yet\ -8c 40 7b 5e c2 89 9e 50 99 c5 3e 8c e7 93 bf 94\ -e7 1b 17 82 -Ciphertext: \ -01 81 af 89 22 b9 fc b4 d7 9d 92 eb e1 98 15 99\ -2f c0 c1 43 9d 8b cd 49 13 98 a0 f4 ad 3a 32 9a\ -5b d9 38 55 60 db 53 26 83 c8 b7 da 04 e4 b1 2a\ -ed 6a ac df 47 1c 34 c9 cd a8 91 ad dc c2 df 34\ -56 65 3a a6 38 2e 9a e5 9b 54 45 52 57 eb 09 9d\ -56 2b be 10 45 3f 2b 6d 13 c5 9c 02 e1 0f 1f 8a\ -bb 5d a0 d0 57 09 32 da cf 2d 09 01 db 72 9d 0f\ -ef cc 05 4e 70 96 8e a5 40 c8 1b 04 bc ae fe 72\ -0e -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 2.2 -Plaintext: \ -2d -Seed: # not used yet\ -b6 00 cf 3c 2e 50 6d 7f 16 77 8c 91 0d 3a 8b 00\ -3e ee 61 d5 -Ciphertext: \ -01 87 59 ff 1d f6 3b 27 92 41 05 62 31 44 16 a8\ -ae af 2a c6 34 b4 6f 94 0a b8 2d 64 db f1 65 ee\ -e3 30 11 da 74 9d 4b ab 6e 2f cd 18 12 9c 9e 49\ -27 7d 84 53 11 2b 42 9a 22 2a 84 71 b0 70 99 39\ -98 e7 58 86 1c 4d 3f 6d 74 9d 91 c4 29 0d 33 2c\ -7a 4a b3 f7 ea 35 ff 3a 07 d4 97 c9 55 ff 0f fc\ -95 00 6b 62 c6 d2 96 81 0d 9b fa b0 24 19 6c 79\ -34 01 2c 2d f9 78 ef 29 9a ba 23 99 40 cb a1 02\ -45 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 2.3 -Plaintext: \ -74 fc 88 c5 1b c9 0f 77 af 9d 5e 9a 4a 70 13 3d\ -4b 4e 0b 34 da 3c 37 c7 ef 8e -Seed: # not used yet\ -a7 37 68 ae ea a9 1f 9d 8c 1e d6 f9 d2 b6 34 67\ -f0 7c ca e3 -Ciphertext: \ -01 88 02 ba b0 4c 60 32 5e 81 c4 96 23 11 f2 be\ -7c 2a dc e9 30 41 a0 07 19 c8 8f 95 75 75 f2 c7\ -9f 1b 7b c8 ce d1 15 c7 06 b3 11 c0 8a 2d 98 6c\ -a3 b6 a9 33 6b 14 7c 29 c6 f2 29 40 9d de c6 51\ -bd 1f dd 5a 0b 7f 61 0c 99 37 fd b4 a3 a7 62 36\ -4b 8b 32 06 b4 ea 48 5f d0 98 d0 8f 63 d4 aa 8b\ -b2 69 7d 02 7b 75 0c 32 d7 f7 4e af 51 80 d2 e9\ -b6 6b 17 cb 2f a5 55 23 bc 28 0d a1 0d 14 be 20\ -53 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 2.4 -Plaintext: \ -a7 eb 2a 50 36 93 1d 27 d4 e8 91 32 6d 99 69 2f\ -fa dd a9 bf 7e fd 3e 34 e6 22 c4 ad c0 85 f7 21\ -df e8 85 07 2c 78 a2 03 b1 51 73 9b e5 40 fa 8c\ -15 3a 10 f0 0a -Seed: # not used yet\ -9a 7b 3b 0e 70 8b d9 6f 81 90 ec ab 4f b9 b2 b3\ -80 5a 81 56 -Ciphertext: \ -00 a4 57 8c bc 17 63 18 a6 38 fb a7 d0 1d f1 57\ -46 af 44 d4 f6 cd 96 d7 e7 c4 95 cb f4 25 b0 9c\ -64 9d 32 bf 88 6d a4 8f ba f9 89 a2 11 71 87 ca\ -fb 1f b5 80 31 76 90 e3 cc d4 46 92 0b 7a f8 2b\ -31 db 58 04 d8 7d 01 51 4a cb fa 91 56 e7 82 f8\ -67 f6 be d9 44 9e 0e 9a 2c 09 bc ec c6 aa 08 76\ -36 96 5e 34 b3 ec 76 6f 2f e2 e4 30 18 a2 fd de\ -b1 40 61 6a 0e 9d 82 e5 33 10 24 ee 06 52 fc 76\ -41 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 2.5 -Plaintext: \ -2e f2 b0 66 f8 54 c3 3f 3b dc bb 59 94 a4 35 e7\ -3d 6c 6c -Seed: # not used yet\ -eb 3c eb bc 4a dc 16 bb 48 e8 8c 8a ec 0e 34 af\ -7f 42 7f d3 -Ciphertext: \ -00 eb c5 f5 fd a7 7c fd ad 3c 83 64 1a 90 25 e7\ -7d 72 d8 a6 fb 33 a8 10 f5 95 0f 8d 74 c7 3e 8d\ -93 1e 86 34 d8 6a b1 24 62 56 ae 07 b6 00 5b 71\ -b7 f2 fb 98 35 12 18 33 1c e6 9b 8f fb dc 9d a0\ -8b bc 9c 70 4f 87 6d eb 9d f9 fc 2e c0 65 ca d8\ -7f 90 90 b0 7a cc 17 aa 7f 99 7b 27 ac a4 88 06\ -e8 97 f7 71 d9 51 41 fe 45 26 d8 a5 30 1b 67 86\ -27 ef ab 70 7f d4 0f be bd 6e 79 2a 25 61 3e 7a\ -ec -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 2.6 -Plaintext: \ -8a 7f b3 44 c8 b6 cb 2c f2 ef 1f 64 3f 9a 32 18\ -f6 e1 9b ba 89 c0 -Seed: # not used yet\ -4c 45 cf 4d 57 c9 8e 3d 6d 20 95 ad c5 1c 48 9e\ -b5 0d ff 84 -Ciphertext: \ -01 08 39 ec 20 c2 7b 90 52 e5 5b ef b9 b7 7e 6f\ -c2 6e 90 75 d7 a5 43 78 c6 46 ab df 51 e4 45 bd\ -57 15 de 81 78 9f 56 f1 80 3d 91 70 76 4a 9e 93\ -cb 78 79 86 94 02 3e e7 39 3c e0 4b c5 d8 f8 c5\ -a5 2c 17 1d 43 83 7e 3a ca 62 f6 09 eb 0a a5 ff\ -b0 96 0e f0 41 98 dd 75 4f 57 f7 fb e6 ab f7 65\ -cf 11 8b 4c a4 43 b2 3b 5a ab 26 6f 95 23 26 ac\ -45 81 10 06 44 32 5f 8b 72 1a cd 5d 04 ff 14 ef\ -3a -Test: DecryptMatch - -AlgorithmType: AsymmetricCipher -Name: RSA/OAEP-MGF1(SHA-1) -Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors -KeyFormat: Component -Comment: Example 3: A 1026-bit RSA Key Pair -Modulus: \ -02 b5 8f ec 03 9a 86 07 00 a4 d7 b6 46 2f 93 e6\ -cd d4 91 16 1d dd 74 f4 e8 10 b4 0e 3c 16 52 00\ -6a 5c 27 7b 27 74 c1 13 05 a4 cb ab 5a 78 ef a5\ -7e 17 a8 6d f7 a3 fa 36 fc 4b 1d 22 49 f2 2e c7\ -c2 dd 6a 46 32 32 ac ce a9 06 d6 6e be 80 b5 70\ -4b 10 72 9d a6 f8 33 23 4a bb 5e fd d4 a2 92 cb\ -fa d3 3b 4d 33 fa 7a 14 b8 c3 97 b5 6e 3a cd 21\ -20 34 28 b7 7c df a3 3a 6d a7 06 b3 d8 b0 fc 43\ -e9 -PublicExponent: \ -01 00 01 -PrivateExponent: \ -15 b4 8a 5b 56 83 a9 46 70 e2 3b 57 18 f8 14 fa\ -0e 13 f8 50 38 f5 07 11 18 2c ba 61 51 05 81 f3\ -d2 2c 7e 23 2e f9 37 e2 2e 55 1d 68 b8 6e 2f 8c\ -b1 aa d8 be 2e 48 8f 5d f7 ef d2 79 e3 f5 68 d4\ -ea f3 6f 80 cf 71 41 ac e6 0f cc 91 13 fb 6c 4a\ -84 1f d5 0b bc 7c 51 2f fc be ff 21 48 7a a8 11\ -eb 3c a8 c6 20 05 34 6a 86 de 86 bf a1 d8 a9 48\ -fd 3f 34 8c 22 ea ad f3 33 c3 ce 6c e1 32 08 fd -Prime1: \ -01 bf 01 d2 16 d7 35 95 cf 02 70 c2 be b7 8d 40\ -a0 d8 44 7d 31 da 91 9a 98 3f 7e ea 78 1b 77 d8\ -5f e3 71 b3 e9 37 3e 7b 69 21 7d 31 50 a0 2d 89\ -58 de 7f ad 9d 55 51 60 95 8b 44 54 12 7e 0e 7e\ -af -Prime2: \ -01 8d 33 99 65 81 66 db 38 29 81 6d 7b 29 54 16\ -75 9e 9c 91 98 7f 5b 2d 8a ec d6 3b 04 b4 8b d7\ -b2 fc f2 29 bb 7f 8a 6d c8 8b a1 3d d2 e3 9a d5\ -5b 6d 1a 06 16 07 08 f9 70 0b e8 0b 8f d3 74 4c\ -e7 -ModPrime1PrivateExponent: \ -06 c0 a2 49 d2 0a 6f 2e e7 5c 88 b4 94 d5 3f 6a\ -ae 99 aa 42 7c 88 c2 8b 16 3a 76 94 45 e5 f3 90\ -cf 40 c2 74 fd 6e a6 32 9a 5c e7 c7 ce 03 a2 15\ -83 96 ee 2a 78 45 78 6e 09 e2 88 5a 97 28 e4 e5 -ModPrime2PrivateExponent: \ -d1 d2 7c 29 fe dd 92 d8 6c 34 8e dd 0c cb fa c1\ -4f 74 6e 05 1c e1 d1 81 1d f3 5d 61 f2 ee 1c 97\ -d4 bf 28 04 80 2f 64 27 18 7b a8 e9 0a 8a f4 42\ -43 b4 07 9b 03 44 5e 60 2e 29 fa 51 93 e6 4f e9 -MultiplicativeInverseOfPrime2ModPrime1: \ -8c b2 f7 56 bd 89 41 b1 d3 b7 70 e5 ad 31 ee 37\ -3b 28 ac da 69 ff 9b 6f 40 fe 57 8b 9f 1a fb 85\ -83 6f 96 27 d3 7a cf f7 3c 27 79 e6 34 bb 26 01\ -1c 2c 8f 7f 33 61 ae 2a 9e a6 5e d6 89 e3 63 9a -Test: KeyPairValidAndConsistent -Comment: RSAES-OAEP Encryption Example 3.1 -Plaintext: \ -08 78 20 b5 69 e8 fa 8d -Seed: # not used yet\ -8c ed 6b 19 62 90 80 57 90 e9 09 07 40 15 e6 a2\ -0b 0c 48 94 -Ciphertext: \ -02 6a 04 85 d9 6a eb d9 6b 43 82 08 50 99 b9 62\ -e6 a2 bd ec 3d 90 c8 db 62 5e 14 37 2d e8 5e 2d\ -5b 7b aa b6 5c 8f af 91 bb 55 04 fb 49 5a fc e5\ -c9 88 b3 f6 a5 2e 20 e1 d6 cb d3 56 6c 5c d1 f2\ -b8 31 8b b5 42 cc 0e a2 5c 4a ab 99 32 af a2 07\ -60 ea dd ec 78 43 96 a0 7e a0 ef 24 d4 e6 f4 d3\ -7e 50 52 a7 a3 1e 14 6a a4 80 a1 11 bb e9 26 40\ -13 07 e0 0f 41 00 33 84 2b 6d 82 fe 5c e4 df ae\ -80 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 3.2 -Plaintext: \ -46 53 ac af 17 19 60 b0 1f 52 a7 be 63 a3 ab 21\ -dc 36 8e c4 3b 50 d8 2e c3 78 1e 04 -Seed: # not used yet\ -b4 29 1d 65 67 55 08 48 cc 15 69 67 c8 09 ba ab\ -6c a5 07 f0 -Ciphertext: \ -02 4d b8 9c 78 02 98 9b e0 78 38 47 86 30 84 94\ -1b f2 09 d7 61 98 7e 38 f9 7c b5 f6 f1 bc 88 da\ -72 a5 0b 73 eb af 11 c8 79 c4 f9 5d f3 7b 85 0b\ -8f 65 d7 62 2e 25 b1 b8 89 e8 0f e8 0b ac a2 06\ -9d 6e 0e 1d 82 99 53 fc 45 90 69 de 98 ea 97 98\ -b4 51 e5 57 e9 9a bf 8f e3 d9 cc f9 09 6e bb f3\ -e5 25 5d 3b 4e 1c 6d 2e ca df 06 7a 35 9e ea 86\ -40 5a cd 47 d5 e1 65 51 7c ca fd 47 d6 db ee 4b\ -f5 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 3.3 -Plaintext: \ -d9 4c d0 e0 8f a4 04 ed 89 -Seed: # not used yet\ -ce 89 28 f6 05 95 58 25 40 08 ba dd 97 94 fa dc\ -d2 fd 1f 65 -Ciphertext: \ -02 39 bc e6 81 03 24 41 52 88 77 d6 d1 c8 bb 28\ -aa 3b c9 7f 1d f5 84 56 36 18 99 57 97 68 38 44\ -ca 86 66 47 32 f4 be d7 a0 aa b0 83 aa ab fb 72\ -38 f5 82 e3 09 58 c2 02 4e 44 e5 70 43 b9 79 50\ -fd 54 3d a9 77 c9 0c dd e5 33 7d 61 84 42 f9 9e\ -60 d7 78 3a b5 9c e6 dd 9d 69 c4 7a d1 e9 62 be\ -c2 2d 05 89 5c ff 8d 3f 64 ed 52 61 d9 2b 26 78\ -51 03 93 48 49 90 ba 3f 7f 06 81 8a e6 ff ce 8a\ -3a -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 3.4 -Plaintext: \ -6c c6 41 b6 b6 1e 6f 96 39 74 da d2 3a 90 13 28\ -4e f1 -Seed: # not used yet\ -6e 29 79 f5 2d 68 14 a5 7d 83 b0 90 05 48 88 f1\ -19 a5 b9 a3 -Ciphertext: \ -02 99 4c 62 af d7 6f 49 8b a1 fd 2c f6 42 85 7f\ -ca 81 f4 37 3c b0 8f 1c ba ee 6f 02 5c 3b 51 2b\ -42 c3 e8 77 91 13 47 66 48 03 9d be 04 93 f9 24\ -62 92 fa c2 89 50 60 0e 7c 0f 32 ed f9 c8 1b 9d\ -ec 45 c3 bd e0 cc 8d 88 47 59 01 69 90 7b 7d c5\ -99 1c eb 29 bb 07 14 d6 13 d9 6d f0 f1 2e c5 d8\ -d3 50 7c 8e e7 ae 78 dd 83 f2 16 fa 61 de 10 03\ -63 ac a4 8a 7e 91 4a e9 f4 2d df be 94 3b 09 d9\ -a0 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 3.5 -Plaintext: \ -df 51 51 83 2b 61 f4 f2 58 91 fb 41 72 f3 28 d2\ -ed df 83 71 ff cf db e9 97 93 92 95 f3 0e ca 69\ -18 01 7c fd a1 15 3b f7 a6 af 87 59 32 23 -Seed: # not used yet\ -2d 76 0b fe 38 c5 9d e3 4c dc 8b 8c 78 a3 8e 66\ -28 4a 2d 27 -Ciphertext: \ -01 62 04 2f f6 96 95 92 a6 16 70 31 81 1a 23 98\ -34 ce 63 8a bf 54 fe c8 b9 94 78 12 2a fe 2e e6\ -7f 8c 5b 18 b0 33 98 05 bf db c5 a4 e6 72 0b 37\ -c5 9c fb a9 42 46 4c 59 7f f5 32 a1 19 82 15 45\ -fd 2e 59 b1 14 e6 1d af 71 82 05 29 f5 02 9c f5\ -24 95 43 27 c3 4e c5 e6 f5 ba 7e fc c4 de 94 3a\ -b8 ad 4e d7 87 b1 45 43 29 f7 0d b7 98 a3 a8 f4\ -d9 2f 82 74 e2 b2 94 8a de 62 7c e8 ee 33 e4 3c\ -60 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 3.6 -Plaintext: \ -3c 3b ad 89 3c 54 4a 6d 52 0a b0 22 31 91 88 c8\ -d5 04 b7 a7 88 b8 50 90 3b 85 97 2e aa 18 55 2e\ -11 34 a7 ad 60 98 82 62 54 ff 7a b6 72 b3 d8 eb\ -31 58 fa c6 d4 cb ae f1 -Seed: # not used yet\ -f1 74 77 9c 5f d3 cf e0 07 ba dc b7 a3 6c 9b 55\ -bf cf bf 0e -Ciphertext: \ -00 11 20 51 e7 5d 06 49 43 bc 44 78 07 5e 43 48\ -2f d5 9c ee 06 79 de 68 93 ee c3 a9 43 da a4 90\ -b9 69 1c 93 df c0 46 4b 66 23 b9 f3 db d3 e7 00\ -83 26 4f 03 4b 37 4f 74 16 4e 1a 00 76 37 25 e5\ -74 74 4b a0 b9 db 83 43 4f 31 df 96 f6 e2 a2 6f\ -6d 8e ba 34 8b d4 68 6c 22 38 ac 07 c3 7a ac 37\ -85 d1 c7 ee a2 f8 19 fd 91 49 17 98 ed 8e 9c ef\ -5e 43 b7 81 b0 e0 27 6e 37 c4 3f f9 49 2d 00 57\ -30 -Test: DecryptMatch - -AlgorithmType: AsymmetricCipher -Name: RSA/OAEP-MGF1(SHA-1) -Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors -KeyFormat: Component -Comment: Example 4: A 1027-bit RSA Key Pair -Modulus: \ -05 12 40 b6 cc 00 04 fa 48 d0 13 46 71 c0 78 c7\ -c8 de c3 b3 e2 f2 5b c2 56 44 67 33 9d b3 88 53\ -d0 6b 85 ee a5 b2 de 35 3b ff 42 ac 2e 46 bc 97\ -fa e6 ac 96 18 da 95 37 a5 c8 f5 53 c1 e3 57 62\ -59 91 d6 10 8d cd 78 85 fb 3a 25 41 3f 53 ef ca\ -d9 48 cb 35 cd 9b 9a e9 c1 c6 76 26 d1 13 d5 7d\ -de 4c 5b ea 76 bb 5b b7 de 96 c0 0d 07 37 2e 96\ -85 a6 d7 5c f9 d2 39 fa 14 8d 70 93 1b 5f 3f b0\ -39 -PublicExponent: \ -01 00 01 -PrivateExponent: \ -04 11 ff ca 3b 7c a5 e9 e9 be 7f e3 8a 85 10 5e\ -35 38 96 db 05 c5 79 6a ec d2 a7 25 16 1e b3 65\ -1c 86 29 a9 b8 62 b9 04 d7 b0 c7 b3 7f 8c b5 a1\ -c2 b5 40 01 01 8a 00 a1 eb 2c af e4 ee 4e 94 92\ -c3 48 bc 2b ed ab 4b 9e bb f0 64 e8 ef f3 22 b9\ -00 9f 8e ec 65 39 05 f4 0d f8 8a 3c dc 49 d4 56\ -7f 75 62 7d 41 ac a6 24 12 9b 46 a0 b7 c6 98 e5\ -e6 5f 2b 7b a1 02 c7 49 a1 01 35 b6 54 0d 04 01 -Prime1: \ -02 74 58 c1 9e c1 63 69 19 e7 36 c9 af 25 d6 09\ -a5 1b 8f 56 1d 19 c6 bf 69 43 dd 1e e1 ab 8a 4a\ -3f 23 21 00 bd 40 b8 8d ec c6 ba 23 55 48 b6 ef\ -79 2a 11 c9 de 82 3d 0a 79 22 c7 09 5b 6e ba 57\ -01 -Prime2: \ -02 10 ee 9b 33 ab 61 71 6e 27 d2 51 bd 46 5f 4b\ -35 a1 a2 32 e2 da 00 90 1c 29 4b f2 23 50 ce 49\ -0d 09 9f 64 2b 53 75 61 2d b6 3b a1 f2 03 86 49\ -2b f0 4d 34 b3 c2 2b ce b9 09 d1 34 41 b5 3b 51\ -39 -ModPrime1PrivateExponent: \ -39 fa 02 8b 82 6e 88 c1 12 1b 75 0a 8b 24 2f a9\ -a3 5c 5b 66 bd fd 1f a6 37 d3 cc 48 a8 4a 4f 45\ -7a 19 4e 77 27 e4 9f 7b cc 6e 5a 5a 41 26 57 fc\ -47 0c 73 22 eb c3 74 16 ef 45 8c 30 7a 8c 09 01 -ModPrime2PrivateExponent: \ -01 5d 99 a8 41 95 94 39 79 fa 9e 1b e2 c3 c1 b6\ -9f 43 2f 46 fd 03 e4 7d 5b ef bb bf d6 b1 d1 37\ -1d 83 ef b3 30 a3 e0 20 94 2b 2f ed 11 5e 5d 02\ -be 24 fd 92 c9 01 9d 1c ec d6 dd 4c f1 e5 4c c8\ -99 -MultiplicativeInverseOfPrime2ModPrime1: \ -01 f0 b7 01 51 70 b3 f5 e4 22 23 ba 30 30 1c 41\ -a6 d8 7c bb 70 e3 0c b7 d3 c6 7d 25 47 3d b1 f6\ -cb f0 3e 3f 91 26 e3 e9 79 68 27 9a 86 5b 2c 2b\ -42 65 24 cf c5 2a 68 3d 31 ed 30 eb 98 4b e4 12\ -ba -Test: KeyPairValidAndConsistent -Comment: RSAES-OAEP Encryption Example 4.1 -Plaintext: \ -4a 86 60 95 34 ee 43 4a 6c bc a3 f7 e9 62 e7 6d\ -45 5e 32 64 c1 9f 60 5f 6e 5f f6 13 7c 65 c5 6d\ -7f b3 44 cd 52 bc 93 37 4f 3d 16 6c 9f 0c 6f 9c\ -50 6b ad 19 33 09 72 d2 -Seed: # not used yet\ -1c ac 19 ce 99 3d ef 55 f9 82 03 f6 85 28 96 c9\ -5c cc a1 f3 -Ciphertext: \ -04 cc e1 96 14 84 5e 09 41 52 a3 fe 18 e5 4e 33\ -30 c4 4e 5e fb c6 4a e1 68 86 cb 18 69 01 4c c5\ -78 1b 1f 8f 9e 04 53 84 d0 11 2a 13 5c a0 d1 2e\ -9c 88 a8 e4 06 34 16 de aa e3 84 4f 60 d6 e9 6f\ -e1 55 14 5f 45 25 b9 a3 44 31 ca 37 66 18 0f 70\ -e1 5a 5e 5d 8e 8b 1a 51 6f f8 70 60 9f 13 f8 96\ -93 5c ed 18 82 79 a5 8e d1 3d 07 11 42 77 d7 5c\ -65 68 60 7e 0a b0 92 fd 80 3a 22 3e 4a 8e e0 b1\ -a8 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 4.2 -Plaintext: \ -b0 ad c4 f3 fe 11 da 59 ce 99 27 73 d9 05 99 43\ -c0 30 46 49 7e e9 d9 f9 a0 6d f1 16 6d b4 6d 98\ -f5 8d 27 ec 07 4c 02 ee e6 cb e2 44 9c 8b 9f c5\ -08 0c 5c 3f 44 33 09 25 12 ec 46 aa 79 37 43 c8 -Seed: # not used yet\ -f5 45 d5 89 75 85 e3 db 71 aa 0c b8 da 76 c5 1d\ -03 2a e9 63 -Ciphertext: \ -00 97 b6 98 c6 16 56 45 b3 03 48 6f bf 5a 2a 44\ -79 c0 ee 85 88 9b 54 1a 6f 0b 85 8d 6b 65 97 b1\ -3b 85 4e b4 f8 39 af 03 39 9a 80 d7 9b da 65 78\ -c8 41 f9 0d 64 57 15 b2 80 d3 71 43 99 2d d1 86\ -c8 0b 94 9b 77 5c ae 97 37 0e 4e c9 74 43 13 6c\ -6d a4 84 e9 70 ff db 13 23 a2 08 47 82 1d 3b 18\ -38 1d e1 3b b4 9a ae a6 65 30 c4 a4 b8 27 1f 3e\ -ae 17 2c d3 66 e0 7e 66 36 f1 01 9d 2a 28 ae d1\ -5e -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 4.3 -Plaintext: \ -bf 6d 42 e7 01 70 7b 1d 02 06 b0 c8 b4 5a 1c 72\ -64 1f f1 28 89 21 9a 82 bd ea 96 5b 5e 79 a9 6b\ -0d 01 63 ed 9d 57 8e c9 ad a2 0f 2f bc f1 ea 3c\ -40 89 d8 34 19 ba 81 b0 c6 0f 36 06 da 99 -Seed: # not used yet\ -ad 99 7f ee f7 30 d6 ea 7b e6 0d 0d c5 2e 72 ea\ -cb fd d2 75 -Ciphertext: \ -03 01 f9 35 e9 c4 7a bc b4 8a cb be 09 89 5d 9f\ -59 71 af 14 83 9d a4 ff 95 41 7e e4 53 d1 fd 77\ -31 90 72 bb 72 97 e1 b5 5d 75 61 cd 9d 1b b2 4c\ -1a 9a 37 c6 19 86 43 08 24 28 04 87 9d 86 eb d0\ -01 dc e5 18 39 75 e1 50 69 89 b7 0e 5a 83 43 41\ -54 d5 cb fd 6a 24 78 7e 60 eb 0c 65 8d 2a c1 93\ -30 2d 11 92 c6 e6 22 d4 a1 2a d4 b5 39 23 bc a2\ -46 df 31 c6 39 5e 37 70 2c 6a 78 ae 08 1f b9 d0\ -65 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 4.4 -Plaintext: \ -fb 2e f1 12 f5 e7 66 eb 94 01 92 97 93 47 94 f7\ -be 2f 6f c1 c5 8e -Seed: # not used yet\ -13 64 54 df 57 30 f7 3c 80 7a 7e 40 d8 c1 a3 12\ -ac 5b 9d d3 -Ciphertext: \ -02 d1 10 ad 30 af b7 27 be b6 91 dd 0c f1 7d 0a\ -f1 a1 e7 fa 0c c0 40 ec 1a 4b a2 6a 42 c5 9d 0a\ -79 6a 2e 22 c8 f3 57 cc c9 8b 65 19 ac eb 68 2e\ -94 5e 62 cb 73 46 14 a5 29 40 7c d4 52 be e3 e4\ -4f ec e8 42 3c c1 9e 55 54 8b 8b 99 4b 84 9c 7e\ -cd e4 93 3e 76 03 7e 1d 0c e4 42 75 b0 87 10 c6\ -8e 43 01 30 b9 29 73 0e d7 7e 09 b0 15 64 2c 55\ -93 f0 4e 4f fb 94 10 79 81 02 a8 e9 6f fd fe 11\ -e4 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 4.5 -Plaintext: \ -28 cc d4 47 bb 9e 85 16 6d ab b9 e5 b7 d1 ad ad\ -c4 b9 d3 9f 20 4e 96 d5 e4 40 ce 9a d9 28 bc 1c\ -22 84 -Seed: # not used yet\ -bc a8 05 7f 82 4b 2e a2 57 f2 86 14 07 ee f6 3d\ -33 20 86 81 -Ciphertext: \ -00 db b8 a7 43 9d 90 ef d9 19 a3 77 c5 4f ae 8f\ -e1 1e c5 8c 3b 85 83 62 e2 3a d1 b8 a4 43 10 79\ -90 66 b9 93 47 aa 52 56 91 d2 ad c5 8d 9b 06 e3\ -4f 28 8c 17 03 90 c5 f0 e1 1c 0a a3 64 59 59 f1\ -8e e7 9e 8f 2b e8 d7 ac 5c 23 d0 61 f1 8d d7 4b\ -8c 5f 2a 58 fc b5 eb 0c 54 f9 9f 01 a8 32 47 56\ -82 92 53 65 83 34 09 48 d7 a8 c9 7c 4a cd 1e 98\ -d1 e2 9d c3 20 e9 7a 26 05 32 a8 aa 7a 75 8a 1e\ -c2 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 4.6 -Plaintext: \ -f2 22 42 75 1e c6 b1 -Seed: # not used yet\ -2e 7e 1e 17 f6 47 b5 dd d0 33 e1 54 72 f9 0f 68\ -12 f3 ac 4e -Ciphertext: \ -00 a5 ff a4 76 8c 8b be ca ee 2d b7 7e 8f 2e ec\ -99 59 59 33 54 55 20 83 5e 5b a7 db 94 93 d3 e1\ -7c dd ef e6 a5 f5 67 62 44 71 90 8d b4 e2 d8 3a\ -0f be e6 06 08 fc 84 04 95 03 b2 23 4a 07 dc 83\ -b2 7b 22 84 7a d8 92 0f f4 2f 67 4e f7 9b 76 28\ -0b 00 23 3d 2b 51 b8 cb 27 03 a9 d4 2b fb c8 25\ -0c 96 ec 32 c0 51 e5 7f 1b 4b a5 28 db 89 c3 7e\ -4c 54 e2 7e 6e 64 ac 69 63 5a e8 87 d9 54 16 19\ -a9 -Test: DecryptMatch - -AlgorithmType: AsymmetricCipher -Name: RSA/OAEP-MGF1(SHA-1) -Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors -KeyFormat: Component -Comment: Example 5: A 1028-bit RSA Key Pair -Modulus: \ -0a ad f3 f9 c1 25 e5 d8 91 f3 1a c4 48 e9 93 de\ -fe 58 0f 80 2b 45 f9 d7 f2 2b a5 02 1e 9c 47 57\ -6b 5a 1e 68 03 1b a9 db 4e 6d ab e4 d9 6a 1d 6f\ -3d 26 72 68 cf f4 08 00 5f 11 8e fc ad b9 98 88\ -d1 c2 34 46 71 66 b2 a2 b8 49 a0 5a 88 9c 06 0a\ -c0 da 0c 5f ae 8b 55 f3 09 ba 62 e7 03 74 2f a0\ -32 6f 2d 10 b0 11 02 14 89 ff 49 77 70 19 0d 89\ -5f d3 9f 52 29 3c 39 ef d7 3a 69 8b da b9 f1 0e\ -d9 -PublicExponent: \ -01 00 01 -PrivateExponent: \ -02 56 eb 4c ba 70 67 f2 d2 be 54 0d cd ff 45 82\ -a3 6b 7d 31 d1 c9 09 9b b2 14 b7 98 48 46 6a 26\ -8f 80 f5 8a 49 ac 04 c0 e3 64 89 34 a0 20 6c 04\ -53 7c 19 b2 36 64 3a 60 82 73 21 44 df 75 fa 21\ -75 88 f7 94 68 2b e8 91 68 27 6d c7 26 c5 c0 cb\ -db 84 d3 1b bf 26 d0 a4 3a f4 95 71 7f 7d 52 8a\ -cf ee 34 15 61 f6 ff 3c ae 05 c5 78 f8 47 0d 96\ -82 f9 c0 d0 72 f9 f6 06 8b 56 d5 88 0f 68 2b e2\ -c5 -Prime1: \ -03 b0 d3 96 2f 6d 17 54 9c bf ca 11 29 43 48 dc\ -f0 e7 e3 9f 8c 2b c6 82 4f 21 64 b6 06 d6 87 86\ -0d ae 1e 63 23 93 cf ed f5 13 22 82 29 06 9e 2f\ -60 e4 ac d7 e6 33 a4 36 06 3f 82 38 5f 48 99 37\ -07 -Prime2: \ -02 e4 c3 2e 2f 51 72 69 b7 07 23 09 f0 0c 0e 31\ -36 5f 7c e2 8b 23 6b 82 91 2d f2 39 ab f3 95 72\ -cf 0e d6 04 b0 29 82 e5 35 64 c5 2d 6a 05 39 7d\ -e5 c0 52 a2 fd dc 14 1e f7 18 98 36 34 6a eb 33\ -1f -ModPrime1PrivateExponent: \ -01 e8 4b 11 9d 25 16 1f a6 7b 00 25 6a 5b d9 b6\ -45 d2 b2 32 ec b0 5b 01 51 80 02 9a 88 62 2a dc\ -3f 09 b3 ae ac de 61 61 ab 7c de 22 c2 ad 26 e7\ -79 7d f5 4e 07 2c bd 3b 26 73 80 0b 3e 43 38 db\ -d5 -ModPrime2PrivateExponent: \ -eb 90 aa 1a 40 13 5b 4c ea 07 19 7c ed c8 81 9b\ -e1 e7 cb ff 25 47 66 21 16 f4 65 a4 a9 f4 87 ab\ -12 f3 ba 4f ef 13 82 22 65 a6 52 97 d9 8b 7b de\ -d9 37 2e 3f fe 81 a3 8b 3e 96 00 fe d0 55 75 4f -MultiplicativeInverseOfPrime2ModPrime1: \ -01 2f 7f 81 38 f9 40 40 62 eb 85 a4 29 24 52 0b\ -38 f5 bb 88 6a 01 96 f4 8b b8 dc ea 60 fd 92 cc\ -02 7f 18 e7 81 58 a3 4a 5c 5d 5f 86 0a 0f 6c 04\ -07 1a 7d 01 31 2c 06 50 62 f1 eb 48 b7 9d 1c 83\ -cb -Test: KeyPairValidAndConsistent -Comment: RSAES-OAEP Encryption Example 5.1 -Plaintext: \ -af 71 a9 01 e3 a6 1d 31 32 f0 fc 1f db 47 4f 9e\ -a6 57 92 57 ff c2 4d 16 41 70 14 5b 3d bd e8 -Seed: # not used yet\ -44 c9 2e 28 3f 77 b9 49 9c 60 3d 96 36 60 c8 7d\ -2f 93 94 61 -Ciphertext: \ -03 60 46 a4 a4 7d 9e d3 ba 9a 89 13 9c 10 50 38\ -eb 74 92 b0 5a 5d 68 bf d5 3a cc ff 45 97 f7 a6\ -86 51 b4 7b 4a 46 27 d9 27 e4 85 ee d7 b4 56 64\ -20 e8 b4 09 87 9e 5d 60 6e ae 25 1d 22 a5 df 79\ -9f 79 20 bf c1 17 b9 92 57 2a 53 b1 26 31 46 bc\ -ea 03 38 5c c5 e8 53 c9 a1 01 c8 c3 e1 bd a3 1a\ -51 98 07 49 6c 6c b5 e5 ef b4 08 82 3a 35 2b 8f\ -a0 66 1f b6 64 ef ad d5 93 de b9 9f ff 5e d0 00\ -e5 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 5.2 -Plaintext: \ -a3 b8 44 a0 82 39 a8 ac 41 60 5a f1 7a 6c fd a4\ -d3 50 13 65 85 90 3a 41 7a 79 26 87 60 51 9a 4b\ -4a c3 30 3e c7 3f 0f 87 cf b3 23 99 -Seed: # not used yet\ -cb 28 f5 86 06 59 fc ee e4 9c 3e ea fc e6 25 a7\ -08 03 bd 32 -Ciphertext: \ -03 d6 eb 65 4e dc e6 15 bc 59 f4 55 26 5e d4 e5\ -a1 82 23 cb b9 be 4e 40 69 b4 73 80 4d 5d e9 6f\ -54 dc aa a6 03 d0 49 c5 d9 4a a1 47 0d fc d2 25\ -40 66 b7 c7 b6 1f f1 f6 f6 77 0e 32 15 c5 13 99\ -fd 4e 34 ec 50 82 bc 48 f0 89 84 0a d0 43 54 ae\ -66 dc 0f 1b d1 8e 46 1a 33 cc 12 58 b4 43 a2 83\ -7a 6d f2 67 59 aa 23 02 33 49 86 f8 73 80 c9 cc\ -9d 53 be 9f 99 60 5d 2c 9a 97 da 7b 09 15 a4 a7\ -ad -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 5.3 -Plaintext: \ -30 8b 0e cb d2 c7 6c b7 7f c6 f7 0c 5e dd 23 3f\ -d2 f2 09 29 d6 29 f0 26 95 3b b6 2a 8f 4a 3a 31\ -4b de 19 5d e8 5b 5f 81 6d a2 aa b0 74 d2 6c b6\ -ac dd f3 23 ae 3b 9c 67 8a c3 cf 12 fb dd e7 -Seed: # not used yet\ -22 85 f4 0d 77 04 82 f9 a9 ef a2 c7 2c b3 ac 55\ -71 6d c0 ca -Ciphertext: \ -07 70 95 21 81 64 9f 9f 9f 07 ff 62 6f f3 a2 2c\ -35 c4 62 44 3d 90 5d 45 6a 9f d0 bf f4 3c ac 2c\ -a7 a9 f5 54 e9 47 8b 9a cc 3a c8 38 b0 20 40 ff\ -d3 e1 84 7d e2 e4 25 39 29 f9 dd 9e e4 04 43 25\ -a9 b0 5c ab b8 08 b2 ee 84 0d 34 e1 5d 10 5a 3f\ -1f 7b 27 69 5a 1a 07 a2 d7 3f e0 8e ca aa 3c 9c\ -9d 4d 5a 89 ff 89 0d 54 72 7d 7a e4 0c 0e c1 a8\ -dd 86 16 5d 8e e2 c6 36 81 41 01 6a 48 b5 5b 69\ -67 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 5.4 -Plaintext: \ -15 c5 b9 ee 11 85 -Seed: # not used yet\ -49 fa 45 d3 a7 8d d1 0d fd 57 73 99 d1 eb 00 af\ -7e ed 55 13 -Ciphertext: \ -08 12 b7 67 68 eb cb 64 2d 04 02 58 e5 f4 44 1a\ -01 85 21 bd 96 68 7e 6c 5e 89 9f cd 6c 17 58 8f\ -f5 9a 82 cc 8a e0 3a 4b 45 b3 12 99 af 17 88 c3\ -29 f7 dc d2 85 f8 cf 4c ed 82 60 6b 97 61 26 71\ -a4 5b ed ca 13 34 42 14 4d 16 17 d1 14 f8 02 85\ -7f 0f 9d 73 97 51 c5 7a 3f 9e e4 00 91 2c 61 e2\ -e6 99 2b e0 31 a4 3d d4 8f a6 ba 14 ee f7 c4 22\ -b5 ed c4 e7 af a0 4f dd 38 f4 02 d1 c8 bb 71 9a\ -bf -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 5.5 -Plaintext: \ -21 02 6e 68 00 c7 fa 72 8f ca ab a0 d1 96 ae 28\ -d7 a2 ac 4f fd 8a bc e7 94 f0 98 5f 60 c8 a6 73\ -72 77 36 5d 3f ea 11 db 89 23 a2 02 9a -Seed: # not used yet\ -f0 28 74 13 23 4c c5 03 47 24 a0 94 c4 58 6b 87\ -af f1 33 fc -Ciphertext: \ -07 b6 0e 14 ec 95 4b fd 29 e6 0d 00 47 e7 89 f5\ -1d 57 18 6c 63 58 99 03 30 67 93 ce d3 f6 82 41\ -c7 43 52 9a ba 6a 63 74 f9 2e 19 e0 16 3e fa 33\ -69 7e 19 6f 76 61 df aa a4 7a ac 6b de 5e 51 de\ -b5 07 c7 2c 58 9a 2c a1 69 3d 96 b1 46 03 81 24\ -9b 2c db 9e ac 44 76 9f 24 89 c5 d3 d2 f9 9f 0e\ -e3 c7 ee 5b f6 4a 5a c7 9c 42 bd 43 3f 14 9b e8\ -cb 59 54 83 61 64 05 95 51 3c 97 af 7b c2 50 97\ -23 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 5.6 -Plaintext: \ -54 1e 37 b6 8b 6c 88 72 b8 4c 02 -Seed: # not used yet\ -d9 fb a4 5c 96 f2 1e 6e 26 d2 9e b2 cd cb 65 85\ -be 9c b3 41 -Ciphertext: \ -08 c3 6d 4d da 33 42 3b 2e d6 83 0d 85 f6 41 1b\ -a1 dc f4 70 a1 fa e0 eb ef ee 7c 08 9f 25 6c ef\ -74 cb 96 ea 69 c3 8f 60 f3 9a be e4 41 29 bc b4\ -c9 2d e7 f7 97 62 3b 20 07 4e 3d 9c 28 99 70 1e\ -d9 07 1e 1e fa 0b dd 84 d4 c3 e5 13 03 02 d8 f0\ -24 0b ab a4 b8 4a 71 cc 03 2f 22 35 a5 ff 0f ae\ -27 7c 3e 8f 91 12 be f4 4c 9a e2 0d 17 5f c9 a4\ -05 8b fc 93 0b a3 1b 02 e2 e4 f4 44 48 37 10 f2\ -4a -Test: DecryptMatch - -AlgorithmType: AsymmetricCipher -Name: RSA/OAEP-MGF1(SHA-1) -Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors -KeyFormat: Component -Comment: Example 6: A 1029-bit RSA Key Pair -Modulus: \ -12 b1 7f 6d ad 2e cd 19 ff 46 dc 13 f7 86 0f 09\ -e0 e0 cf b6 77 b3 8a 52 59 23 05 ce af 02 2c 16\ -6d b9 0d 04 ac 29 e3 3f 7d d1 2d 9f af 66 e0 81\ -6b b6 3e ad 26 7c c7 d4 6c 17 c3 7b e2 14 bc a2\ -a2 2d 72 3a 64 e4 44 07 43 6b 6f c9 65 72 9a ef\ -c2 55 4f 37 6c d5 dc ea 68 29 37 80 a6 2b f3 9d\ -00 29 48 5a 16 0b bb 9e 5d c0 97 2d 21 a5 04 f5\ -2e 5e e0 28 aa 41 63 32 f5 10 b2 e9 cf f5 f7 22\ -af -PublicExponent: \ -01 00 01 -PrivateExponent: \ -02 95 ec a3 56 06 18 36 95 59 ce cd 30 3a a9 cf\ -da fc 1d 9f 06 95 9d f7 5f fe f9 29 aa 89 69 61\ -bc d1 90 dc 69 97 ed a7 f5 96 3e 72 4d 07 b4 dc\ -11 f3 06 5e 5a e9 7d 96 83 51 12 28 0b 90 84 bb\ -14 f2 a2 1e bd 4e 88 9d 41 b9 c4 13 2e c1 95 6f\ -ca b8 bb 2f ed 05 75 88 49 36 52 2c 5f f7 d3 32\ -61 90 48 24 e7 ca de e4 e0 bb 37 2d 24 57 cf 78\ -e2 bd 12 86 22 8f f8 3f 10 73 1c e6 3c 90 cf f3\ -f9 -Prime1: \ -04 a6 ce 8b 73 58 df a6 9b dc f7 42 61 70 05 af\ -b5 38 5f 5f 3a 58 a2 4e f7 4a 22 a8 c0 5c b7 cc\ -38 eb d4 cc 9d 9a 9d 78 9a 62 cd 0f 60 f0 cb 94\ -1d 34 23 c9 69 2e fa 4f e3 ad ff 29 0c 47 49 a3\ -8b -Prime2: \ -04 04 c9 a8 03 37 1f ed b4 c5 be 39 f3 c0 0b 00\ -9e 5e 08 a6 3b e1 e4 00 35 cd ac a5 01 1c c7 01\ -cf 7e eb cb 99 f0 ff e1 7c fd 0a 4b f7 be fd 2d\ -d5 36 ac 94 6d b7 97 fd bc 4a be 8f 29 34 9b 91\ -ed -ModPrime1PrivateExponent: \ -03 96 1c 8f 76 0a a2 bd 51 54 c7 aa fd 77 22 5b\ -3b ac d0 13 9a e7 b5 94 8e a3 31 1f cc d8 6f b9\ -5c 75 af a7 67 28 4b 9b 2d e5 59 57 2f 15 d8 d0\ -44 c7 eb 83 a1 be 5f ad f2 cc 37 7c 0d 84 75 29\ -4b -ModPrime2PrivateExponent: \ -02 21 97 e0 66 74 21 96 aa bc 03 fa 2f ee b4 e7\ -0b 15 cb 78 7d 61 7a cd 31 bb 75 c7 bc 23 4a d7\ -06 f7 c4 8d 21 82 d1 f0 ff 9c 22 8d cf 41 96 7b\ -6c 0b a6 d2 c0 ad 11 0a 1b 85 78 31 ec 24 5e 2c\ -b1 -MultiplicativeInverseOfPrime2ModPrime1: \ -04 01 c4 c0 c5 3d 45 db db 5e 9d 96 d0 fe cf 42\ -75 df 09 74 bc 4a 07 36 b4 a7 4c 32 69 05 3e fb\ -68 6a ce 24 06 e2 2c 9e 05 8d db 4a e5 40 62 7a\ -e2 fd b0 82 61 e8 e7 e4 bc bc 99 4d aa fa 30 5c\ -45 -Test: KeyPairValidAndConsistent -Comment: RSAES-OAEP Encryption Example 6.1 -Plaintext: \ -40 46 ca 8b aa 33 47 ca 27 f4 9e 0d 81 f9 cc 1d\ -71 be 9b a5 17 d4 -Seed: # not used yet\ -dd 0f 6c fe 41 5e 88 e5 a4 69 a5 1f bb a6 df d4\ -0a db 43 84 -Ciphertext: \ -06 30 ee bc d2 85 6c 24 f7 98 80 6e 41 f9 e6 73\ -45 ed a9 ce da 38 6a cc 9f ac ae a1 ee ed 06 ac\ -e5 83 70 97 18 d9 d1 69 fa df 41 4d 5c 76 f9 29\ -96 83 3e f3 05 b7 5b 1e 4b 95 f6 62 a2 0f ae dc\ -3b ae 0c 48 27 a8 bf 8a 88 ed bd 57 ec 20 3a 27\ -a8 41 f0 2e 43 a6 15 ba b1 a8 ca c0 70 1d e3 4d\ -eb de f6 2a 08 80 89 b5 5e c3 6e a7 52 2f d3 ec\ -8d 06 b6 a0 73 e6 df 83 31 53 bc 0a ef d9 3b d1\ -a3 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 6.2 -Plaintext: \ -5c c7 2c 60 23 1d f0 3b 3d 40 f9 b5 79 31 bc 31\ -10 9f 97 25 27 f2 8b 19 e7 48 0c 72 88 cb 3c 92\ -b2 25 12 21 4e 4b e6 c9 14 79 2d da bd f5 7f aa\ -8a a7 -Seed: # not used yet\ -8d 14 bd 94 6a 13 51 14 8f 5c ae 2e d9 a0 c6 53\ -e8 5e bd 85 -Ciphertext: \ -0e bc 37 37 61 73 a4 fd 2f 89 cc 55 c2 ca 62 b2\ -6b 11 d5 1c 3c 7c e4 9e 88 45 f7 4e 76 07 31 7c\ -43 6b c8 d2 3b 96 67 df eb 9d 08 72 34 b4 7b c6\ -83 71 75 ae 5c 05 59 f6 b8 1d 7d 22 41 6d 3e 50\ -f4 ac 53 3d 8f 08 12 f2 db 9e 79 1f e9 c7 75 ac\ -8b 6a d0 f5 35 ad 9c eb 23 a4 a0 20 14 c5 8a b3\ -f8 d3 16 14 99 a2 60 f3 93 48 e7 14 ae 2a 1d 34\ -43 20 8f d8 b7 22 cc fd fb 39 3e 98 01 1f 99 e6\ -3f -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 6.3 -Plaintext: \ -b2 0e 65 13 03 09 2f 4b cc b4 30 70 c0 f8 6d 23\ -04 93 62 ed 96 64 2f c5 63 2c 27 db 4a 52 e3 d8\ -31 f2 ab 06 8b 23 b1 49 87 9c 00 2f 6b f3 fe ee\ -97 59 11 12 56 2c -Seed: # not used yet\ -6c 07 5b c4 55 20 f1 65 c0 bf 5e a4 c5 df 19 1b\ -c9 ef 0e 44 -Ciphertext: \ -0a 98 bf 10 93 61 93 94 43 6c f6 8d 8f 38 e2 f1\ -58 fd e8 ea 54 f3 43 5f 23 9b 8d 06 b8 32 18 44\ -20 24 76 ae ed 96 00 94 92 48 0c e3 a8 d7 05 49\ -8c 4c 8c 68 f0 15 01 dc 81 db 60 8f 60 08 73 50\ -c8 c3 b0 bd 2e 9e f6 a8 14 58 b7 c8 01 b8 9f 2e\ -4f e9 9d 49 00 ba 6a 4b 5e 5a 96 d8 65 dc 67 6c\ -77 55 92 87 94 13 0d 62 80 a8 16 0a 19 0f 2d f3\ -ea 7c f9 aa 02 71 d8 8e 9e 69 05 ec f1 c5 15 2d\ -65 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 6.4 -Plaintext: \ -68 4e 30 38 c5 c0 41 f7 -Seed: # not used yet\ -3b bc 3b d6 63 7d fe 12 84 69 01 02 9b f5 b0 c0\ -71 03 43 9c -Ciphertext: \ -00 8e 7a 67 ca cf b5 c4 e2 4b ec 7d ee 14 91 17\ -f1 95 98 ce 8c 45 80 8f ef 88 c6 08 ff 9c d6 e6\ -95 26 3b 9a 3c 0a d4 b8 ba 4c 95 23 8e 96 a8 42\ -2b 85 35 62 9c 8d 53 82 37 44 79 ad 13 fa 39 97\ -4b 24 2f 9a 75 9e ea f9 c8 3a d5 a8 ca 18 94 0a\ -01 62 ba 75 58 76 df 26 3f 4b d5 0c 65 25 c5 60\ -90 26 7c 1f 0e 09 ce 08 99 a0 cf 35 9e 88 12 0a\ -bd 9b f8 93 44 5b 3c ae 77 d3 60 73 59 ae 9a 52\ -f8 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 6.5 -Plaintext: \ -32 48 8c b2 62 d0 41 d6 e4 dd 35 f9 87 bf 3c a6\ -96 db 1f 06 ac 29 a4 46 93 -Seed: # not used yet\ -b4 6b 41 89 3e 8b ef 32 6f 67 59 38 3a 83 07 1d\ -ae 7f ca bc -Ciphertext: \ -00 00 34 74 41 6c 7b 68 bd f9 61 c3 85 73 79 44\ -d7 f1 f4 0c b3 95 34 3c 69 3c c0 b4 fe 63 b3 1f\ -ed f1 ea ee ac 9c cc 06 78 b3 1d c3 2e 09 77 48\ -95 14 c4 f0 90 85 f6 29 8a 96 53 f0 1a ea 40 45\ -ff 58 2e e8 87 be 26 ae 57 5b 73 ee f7 f3 77 49\ -21 e3 75 a3 d1 9a dd a0 ca 31 aa 18 49 88 7c 1f\ -42 ca c9 67 7f 7a 2f 4e 92 3f 6e 5a 86 8b 38 c0\ -84 ef 18 75 94 dc 9f 7f 04 8f ea 2e 02 95 53 84\ -ab -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 6.6 -Plaintext: \ -50 ba 14 be 84 62 72 02 79 c3 06 ba -Seed: # not used yet\ -0a 24 03 31 2a 41 e3 d5 2f 06 0f bc 13 a6 7d e5\ -cf 76 09 a7 -Ciphertext: \ -0a 02 6d da 5f c8 78 5f 7b d9 bf 75 32 7b 63 e8\ -5e 2c 0f de e5 da db 65 eb dc ac 9a e1 de 95 c9\ -2c 67 2a b4 33 aa 7a 8e 69 ce 6a 6d 88 97 fa c4\ -ac 4a 54 de 84 1a e5 e5 bb ce 76 87 87 9d 79 63\ -4c ea 7a 30 68 40 65 c7 14 d5 24 09 b9 28 25 6b\ -bf 53 ea bc d5 23 1e b7 25 95 04 53 73 99 bd 29\ -16 4b 72 6d 33 a4 6d a7 01 36 0a 41 68 a0 91 cc\ -ab 72 d4 4a 62 fe d2 46 c0 ff ea 5b 13 48 ab 54\ -70 -Test: DecryptMatch - -AlgorithmType: AsymmetricCipher -Name: RSA/OAEP-MGF1(SHA-1) -Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors -KeyFormat: Component -Comment: Example 7: A 1030-bit RSA Key Pair -Modulus: \ -31 11 79 f0 bc fc 9b 9d 3c a3 15 d0 0e f3 0d 7b\ -dd 3a 2c fa e9 91 1b fe dc b9 48 b3 a4 78 2d 07\ -32 b6 ab 44 aa 4b f0 37 41 a6 44 dc 01 be c3 e6\ -9b 01 a0 33 e6 75 d8 ac d7 c4 92 5c 6b 1a ec 31\ -19 05 1d fd 89 76 2d 21 5d 45 47 5f fc b5 9f 90\ -81 48 62 3f 37 17 71 56 f6 ae 86 dd 7a 7c 5f 43\ -dc 1e 1f 90 82 54 05 8a 28 4a 5f 06 c0 02 17 93\ -a8 7f 1a c5 fe ff 7d ca ee 69 c5 e5 1a 37 89 e3\ -73 -PublicExponent: \ -01 00 01 -PrivateExponent: \ -07 0c fc ff 2f eb 82 76 e2 74 32 c4 5d fe e4 8f\ -49 b7 91 7d 65 30 e1 f0 ca 34 60 f3 2e 02 76 17\ -44 87 c5 6e 22 a4 5d 25 00 d7 77 54 95 21 9d 7d\ -16 5a 9c f3 bd 92 c3 2a f9 a9 8d 8d c9 cc 29 68\ -00 ad c9 4a 0a 54 fb 40 f3 42 91 bf 84 ee 8e a1\ -2b 6f 10 93 59 c6 d3 54 2a 50 f9 c7 67 f5 cf ff\ -05 a6 81 c2 e6 56 fb 77 ca aa db 4b e9 46 8d 8a\ -bc d4 df 98 f5 8e 86 d2 05 3f a1 34 9f 74 8e 21\ -b1 -Prime1: \ -07 49 26 2c 11 1c d4 70 ec 25 66 e6 b3 73 2f c0\ -93 29 46 9a a1 90 71 d3 b9 c0 19 06 51 4c 6f 1d\ -26 ba a1 4b ea b0 97 1c 8b 7e 61 1a 4f 79 00 9d\ -6f ea 77 69 28 ca 25 28 5b 0d e3 64 3d 1a 3f 8c\ -71 -Prime2: \ -06 bc 1e 50 e9 6c 02 bf 63 6e 9e ea 8b 89 9b be\ -bf 76 51 de 77 dd 47 4c 3e 9b c2 3b ad 81 82 b6\ -19 04 c7 d9 7d fb eb fb 1e 00 10 88 78 b6 e6 7e\ -41 53 91 d6 79 42 c2 b2 bf 9b 44 35 f8 8b 0c b0\ -23 -ModPrime1PrivateExponent: \ -03 bc 7e a7 f0 aa b1 43 ab c6 ce 8b 97 11 86 36\ -a3 01 72 e4 cf e0 2c 8f a0 dd a3 b7 ba af 90 f8\ -09 29 82 98 55 25 f4 88 bd fc b4 bd 72 6e 22 63\ -9a c6 4a 30 92 ab 7f fc bf 1d 53 34 cf a5 0b 5b\ -f1 -ModPrime2PrivateExponent: \ -02 62 a6 aa 29 c2 a3 c6 7d c5 34 6c 06 38 1a fd\ -98 7a a3 cc 93 cf bf ec f5 4f dd 9f 9d 78 7d 7f\ -59 a5 23 d3 98 97 9d a1 37 a2 f6 38 1f e9 48 01\ -f7 c9 4d a2 15 18 dc 34 cb 40 87 0c 46 97 99 4a\ -d9 -MultiplicativeInverseOfPrime2ModPrime1: \ -64 9d 4c 17 b6 ee 17 21 e7 72 d0 38 9a 55 9c 3d\ -3c df 95 50 d4 57 c4 6b 03 7b 74 64 1b 1d 52 16\ -6a f8 a2 13 c8 39 62 06 cd fb a4 42 2f 18 d6 f6\ -1d bc b5 d2 14 c9 71 bf 48 2a eb 97 6a 73 70 c2 -Test: KeyPairValidAndConsistent -Comment: RSAES-OAEP Encryption Example 7.1 -Plaintext: \ -47 aa e9 09 -Seed: # not used yet\ -43 dd 09 a0 7f f4 ca c7 1c aa 46 32 ee 5e 1c 1d\ -ae e4 cd 8f -Ciphertext: \ -16 88 e4 ce 77 94 bb a6 cb 70 14 16 9e cd 55 9c\ -ed e2 a3 0b 56 a5 2b 68 d9 fe 18 cf 19 73 ef 97\ -b2 a0 31 53 95 1c 75 5f 62 94 aa 49 ad bd b5 58\ -45 ab 68 75 fb 39 86 c9 3e cf 92 79 62 84 0d 28\ -2f 9e 54 ce 8b 69 0f 7c 0c b8 bb d7 34 40 d9 57\ -1d 1b 16 cd 92 60 f9 ea b4 78 3c c4 82 e5 22 3d\ -c6 09 73 87 17 83 ec 27 b0 ae 0f d4 77 32 cb c2\ -86 a1 73 fc 92 b0 0f b4 ba 68 24 64 7c d9 3c 85\ -c1 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 7.2 -Plaintext: \ -1d 9b 2e 22 23 d9 bc 13 bf b9 f1 62 ce 73 5d b4\ -8b a7 c6 8f 68 22 a0 a1 a7 b6 ae 16 58 34 e7 -Seed: # not used yet\ -3a 9c 3c ec 7b 84 f9 bd 3a de cb c6 73 ec 99 d5\ -4b 22 bc 9b -Ciphertext: \ -10 52 ed 39 7b 2e 01 e1 d0 ee 1c 50 bf 24 36 3f\ -95 e5 04 f4 a0 34 34 a0 8f d8 22 57 4e d6 b9 73\ -6e db b5 f3 90 db 10 32 14 79 a8 a1 39 35 0e 2b\ -d4 97 7c 37 78 ef 33 1f 3e 78 ae 11 8b 26 84 51\ -f2 0a 2f 01 d4 71 f5 d5 3c 56 69 37 17 1b 2d bc\ -2d 4b de 45 9a 57 99 f0 37 2d 65 74 23 9b 23 23\ -d2 45 d0 bb 81 c2 86 b6 3c 89 a3 61 01 73 37 e4\ -90 2f 88 a4 67 f4 c7 f2 44 bf d5 ab 46 43 7f f3\ -b6 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 7.3 -Plaintext: \ -d9 76 fc -Seed: # not used yet\ -76 a7 5e 5b 61 57 a5 56 cf 88 84 bb 2e 45 c2 93\ -dd 54 5c f5 -Ciphertext: \ -21 55 cd 84 3f f2 4a 4e e8 ba db 76 94 26 00 28\ -a4 90 81 3b a8 b3 69 a4 cb f1 06 ec 14 8e 52 98\ -70 7f 59 65 be 7d 10 1c 10 49 ea 85 84 c2 4c d6\ -34 55 ad 9c 10 4d 68 62 82 d3 fb 80 3a 4c 11 c1\ -c2 e9 b9 1c 71 78 80 1d 1b 66 40 f0 03 f5 72 8d\ -f0 07 b8 a4 cc c9 2b ce 05 e4 1a 27 27 8d 7c 85\ -01 8c 52 41 43 13 a5 07 77 89 00 1d 4f 01 91 0b\ -72 aa d0 5d 22 0a a1 4a 58 73 3a 74 89 bc 54 55\ -6b -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 7.4 -Plaintext: \ -d4 73 86 23 df 22 3a a4 38 43 df 84 67 53 4c 41\ -d0 13 e0 c8 03 c6 24 e2 63 66 6b 23 9b de 40 a5\ -f2 9a eb 8d e7 9e 3d aa 61 dd 03 70 f4 9b d4 b0\ -13 83 4b 98 21 2a ef 6b 1c 5e e3 73 b3 cb -Seed: # not used yet\ -78 66 31 4a 6a d6 f2 b2 50 a3 59 41 db 28 f5 86\ -4b 58 58 59 -Ciphertext: \ -0a b1 4c 37 3a eb 7d 43 28 d0 aa ad 8c 09 4d 88\ -b9 eb 09 8b 95 f2 10 54 a2 90 82 52 2b e7 c2 7a\ -31 28 78 b6 37 91 7e 3d 81 9e 6c 3c 56 8d b5 d8\ -43 80 2b 06 d5 1d 9e 98 a2 be 0b f4 0c 03 14 23\ -b0 0e df bf f8 32 0e fb 91 71 bd 20 44 65 3a 4c\ -b9 c5 12 2f 6c 65 e8 3c da 2e c3 c1 26 02 7a 9c\ -1a 56 ba 87 4d 0f ea 23 f3 80 b8 2c f2 40 b8 cf\ -54 00 04 75 8c 4c 77 d9 34 15 7a 74 f3 fc 12 bf\ -ac -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 7.5 -Plaintext: \ -bb 47 23 1c a5 ea 1d 3a d4 6c 99 34 5d 9a 8a 61 -Seed: # not used yet\ -b2 16 6e d4 72 d5 8d b1 0c ab 2c 6b 00 0c cc f1\ -0a 7d c5 09 -Ciphertext: \ -02 83 87 a3 18 27 74 34 79 8b 4d 97 f4 60 06 8d\ -f5 29 8f ab a5 04 1b a1 17 61 a1 cb 73 16 b2 41\ -84 11 4e c5 00 25 7e 25 89 ed 3b 60 7a 1e bb e9\ -7a 6c c2 e0 2b f1 b6 81 f4 23 12 a3 3b 7a 77 d8\ -e7 85 5c 4a 6d e0 3e 3c 04 64 3f 78 6b 91 a2 64\ -a0 d6 80 5e 2c ea 91 e6 81 77 eb 7a 64 d9 25 5e\ -4f 27 e7 13 b7 cc ec 00 dc 20 0e bd 21 c2 ea 2b\ -b8 90 fe ae 49 42 df 94 1d c3 f9 78 90 ed 34 74\ -78 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 7.6 -Plaintext: \ -21 84 82 70 95 d3 5c 3f 86 f6 00 e8 e5 97 54 01\ -32 96 -Seed: # not used yet\ -52 67 3b de 2c a1 66 c2 aa 46 13 1a c1 dc 80 8d\ -67 d7 d3 b1 -Ciphertext: \ -14 c6 78 a9 4a d6 05 25 ef 39 e9 59 b2 f3 ba 5c\ -09 7a 94 ff 91 2b 67 db ac e8 05 35 c1 87 ab d4\ -7d 07 54 20 b1 87 21 52 bb a0 8f 7f c3 1f 31 3b\ -bf 92 73 c9 12 fc 4c 01 49 a9 b0 cf b7 98 07 e3\ -46 eb 33 20 69 61 1b ec 0f f9 bc d1 68 f1 f7 c3\ -3e 77 31 3c ea 45 4b 94 e2 54 9e ec f0 02 e2 ac\ -f7 f6 f2 d2 84 5d 4f e0 aa b2 e5 a9 2d df 68 c4\ -80 ae 11 24 79 35 d1 f6 25 74 84 22 16 ae 67 41\ -15 -Test: DecryptMatch - -AlgorithmType: AsymmetricCipher -Name: RSA/OAEP-MGF1(SHA-1) -Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors -KeyFormat: Component -Comment: Example 8: A 1031-bit RSA Key Pair -Modulus: \ -5b df 0e 30 d3 21 dd a5 14 7f 88 24 08 fa 69 19\ -54 80 df 8f 80 d3 f6 e8 bf 58 18 50 4f 36 42 7c\ -a9 b1 f5 54 0b 9c 65 a8 f6 97 4c f8 44 7a 24 4d\ -92 80 20 1b b4 9f cb be 63 78 d1 94 4c d2 27 e2\ -30 f9 6e 3d 10 f8 19 dc ef 27 6c 64 a0 0b 2a 4b\ -67 01 e7 d0 1d e5 fa bd e3 b1 e9 a0 df 82 f4 63\ -13 59 cd 22 66 96 47 fb b1 71 72 46 13 4e d7 b4\ -97 cf ff bd c4 2b 59 c7 3a 96 ed 90 16 62 12 df\ -f7 -PublicExponent: \ -01 00 01 -PrivateExponent: \ -0f 7d 1e 9e 5a aa 25 fd 13 e4 a0 66 3a e1 44 e0\ -d1 5f 5c d1 8b cd b0 9d f2 cc 7e 64 e3 c5 e9 15\ -ad 62 64 53 04 16 1d 09 8c 71 5b b7 ab 8b d0 1d\ -07 ea f3 fe d7 c7 ed 08 af 2a 8a 62 ef 44 ab 16\ -b3 20 e1 4a f7 2a 48 f9 6a fe 26 2a 0a e4 cf 65\ -e6 35 e9 10 79 0c d4 ee 5c ea 76 8a 4b 26 39 f7\ -e6 f6 77 b3 f0 bb 6b e3 2b 75 74 7d 89 09 03 6f\ -02 64 f5 8d 40 1c db a1 31 71 61 57 a7 5e cf 63\ -31 -Prime1: \ -0a 02 ef 84 48 d9 fa d8 bb d0 d0 04 c8 c2 aa 97\ -51 ef 97 21 c1 b0 d0 32 36 a5 4b 0d f9 47 cb ae\ -d5 a2 55 ee 9e 8e 20 d4 91 ea 17 23 fe 09 47 04\ -a9 76 2e 88 af d1 6e bb 59 94 41 2c a9 66 dc 4f\ -9f -Prime2: \ -09 2d 36 2e 7e d3 a0 bf d9 e9 fd 0e 6c 03 01 b6\ -df 29 15 9c f5 0c c8 3b 9b 0c f4 d6 ee a7 1a 61\ -e0 02 b4 6e 0a e9 f2 de 62 d2 5b 5d 74 52 d4 98\ -b8 1c 9a c6 fc 58 59 3d 4c 3f b4 f5 d7 2d fb b0\ -a9 -ModPrime1PrivateExponent: \ -07 c7 14 10 af 10 39 62 db 36 74 04 e3 7a e8 50\ -ba a4 e9 c2 9d d9 21 45 81 52 94 a6 7c 7d 1c 6d\ -ed 26 3a a0 30 a9 b6 33 ae 50 30 3e 14 03 5d 1a\ -f0 14 12 3e ba 68 78 20 30 8d 8e bc 85 b6 95 7d\ -7d -ModPrime2PrivateExponent: \ -ae 2c 75 38 0c 02 c0 16 ad 05 89 1b 33 01 de 88\ -1f 28 ae 11 71 18 2b 6b 2c 83 be a7 c5 15 ec a9\ -ca 29 8c 7b 1c ab 58 17 a5 97 06 8f c8 50 60 de\ -4d a8 a0 16 37 8a ae 43 c7 f9 67 bc c3 79 04 b9 -MultiplicativeInverseOfPrime2ModPrime1: \ -05 98 d1 05 9e 3a da 4f 63 20 75 2c 09 d8 05 ff\ -7d 1f 1a e0 d0 17 ae ee e9 ce fa 0d 7d d7 ff 77\ -5e 44 b5 78 32 2f 64 05 d6 21 1d a1 95 19 66 6a\ -a8 7f dc 4c d8 c8 8f 6b 6e 3d 67 e9 61 dc bb a3\ -d0 -Test: KeyPairValidAndConsistent -Comment: RSAES-OAEP Encryption Example 8.1 -Plaintext: \ -05 0b 75 5e 5e 68 80 f7 b9 e9 d6 92 a7 4c 37 aa\ -e4 49 b3 1b fe a6 de ff 83 74 7a 89 7f 6c 2c 82\ -5b b1 ad bf 85 0a 3c 96 99 4b 5d e5 b3 3c bc 7d\ -4a 17 91 3a 79 67 -Seed: # not used yet\ -77 06 ff ca 1e cf b1 eb ee 2a 55 e5 c6 e2 4c d2\ -79 7a 41 25 -Ciphertext: \ -09 b3 68 3d 8a 2e b0 fb 29 5b 62 ed 1f b9 29 0b\ -71 44 57 b7 82 53 19 f4 64 78 72 af 88 9b 30 40\ -94 72 02 0a d1 29 12 bf 19 b1 1d 48 19 f4 96 14\ -82 4f fd 84 d0 9c 0a 17 e7 d1 73 09 d1 29 19 79\ -04 10 aa 29 95 69 9f 6a 86 db e3 24 2b 5a cc 23\ -af 45 69 10 80 d6 b1 ae 81 0f b3 e3 05 70 87 f0\ -97 00 92 ce 00 be 95 62 ff 40 53 b6 26 2c e0 ca\ -a9 3e 13 72 3d 2e 3a 5b a0 75 d4 5f 0d 61 b5 4b\ -61 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 8.2 -Plaintext: \ -4e b6 8d cd 93 ca 9b 19 df 11 1b d4 36 08 f5 57\ -02 6f e4 aa 1d 5c fa c2 27 a3 eb 5a b9 54 8c 18\ -a0 6d de d2 3f 81 82 59 86 b2 fc d7 11 09 ec ef\ -7e ff 88 87 3f 07 5c 2a a0 c4 69 f6 9c 92 bc -Seed: # not used yet\ -a3 71 7d a1 43 b4 dc ff bc 74 26 65 a8 fa 95 05\ -85 54 83 43 -Ciphertext: \ -2e cf 15 c9 7c 5a 15 b1 47 6a e9 86 b3 71 b5 7a\ -24 28 4f 4a 16 2a 8d 0c 81 82 e7 90 5e 79 22 56\ -f1 81 2b a5 f8 3f 1f 7a 13 0e 42 dc c0 22 32 84\ -4e dc 14 a3 1a 68 ee 97 ae 56 4a 38 3a 34 11 65\ -64 24 c5 f6 2d db 64 60 93 c3 67 be 1f cd a4 26\ -cf 00 a0 6d 8a cb 7e 57 77 6f bb d8 55 ac 3d f5\ -06 fc 16 b1 d7 c3 f2 11 0f 3d 80 68 e9 1e 18 63\ -63 83 1c 84 09 68 0d 8d a9 ec d8 cf 1f a2 0e e3\ -9d -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 8.3 -Plaintext: \ -86 04 ac 56 32 8c 1a b5 ad 91 78 61 -Seed: # not used yet\ -ee 06 20 90 73 cc a0 26 bb 26 4e 51 85 bf 8c 68\ -b7 73 9f 86 -Ciphertext: \ -4b c8 91 30 a5 b2 da bb 7c 2f cf 90 eb 5d 0e af\ -9e 68 1b 71 46 a3 8f 31 73 a3 d9 cf ec 52 ea 9e\ -0a 41 93 2e 64 8a 9d 69 34 4c 50 da 76 3f 51 a0\ -3c 95 76 21 31 e8 05 22 54 dc d2 24 8c ba 40 fd\ -31 66 77 86 ce 05 a2 b7 b5 31 ac 9d ac 9e d5 84\ -a5 9b 67 7c 1a 8a ed 8c 5d 15 d6 8c 05 56 9e 2b\ -e7 80 bf 7d b6 38 fd 2b fd 2a 85 ab 27 68 60 f3\ -77 73 38 fc a9 89 ff d7 43 d1 3e e0 8e 0c a9 89\ -3f -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 8.4 -Plaintext: \ -fd da 5f bf 6e c3 61 a9 d9 a4 ac 68 af 21 6a 06\ -86 f4 38 b1 e0 e5 c3 6b 95 5f 74 e1 07 f3 9c 0d\ -dd cc -Seed: # not used yet\ -99 0a d5 73 dc 48 a9 73 23 5b 6d 82 54 36 18 f2\ -e9 55 10 5d -Ciphertext: \ -2e 45 68 47 d8 fc 36 ff 01 47 d6 99 35 94 b9 39\ -72 27 d5 77 75 2c 79 d0 f9 04 fc b0 39 d4 d8 12\ -fe a6 05 a7 b5 74 dd 82 ca 78 6f 93 75 23 48 43\ -8e e9 f5 b5 45 49 85 d5 f0 e1 69 9e 3e 7a d1 75\ -a3 2e 15 f0 3d eb 04 2a b9 fe 1d d9 db 1b b8 6f\ -8c 08 9c cb 45 e7 ef 0c 5e e7 ca 9b 72 90 ca 6b\ -15 be d4 70 39 78 8a 8a 93 ff 83 e0 e8 d6 24 4c\ -71 00 63 62 de ef 69 b6 f4 16 fb 3c 68 43 83 fb\ -d0 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 8.5 -Plaintext: \ -4a 5f 49 14 be e2 5d e3 c6 93 41 de 07 -Seed: # not used yet\ -ec c6 3b 28 f0 75 6f 22 f5 2a c8 e6 ec 12 51 a6\ -ec 30 47 18 -Ciphertext: \ -1f b9 35 6f d5 c4 b1 79 6d b2 eb f7 d0 d3 93 cc\ -81 0a df 61 45 de fc 2f ce 71 4f 79 d9 38 00 d5\ -e2 ac 21 1e a8 bb ec ca 4b 65 4b 94 c3 b1 8b 30\ -dd 57 6c e3 4d c9 54 36 ef 57 a0 94 15 64 59 23\ -35 9a 5d 7b 41 71 ef 22 c2 46 70 f1 b2 29 d3 60\ -3e 91 f7 66 71 b7 df 97 e7 31 7c 97 73 44 76 d5\ -f3 d1 7d 21 cf 82 b5 ba 9f 83 df 2e 58 8d 36 98\ -4f d1 b5 84 46 8b d2 3b 2e 87 5f 32 f6 89 53 f7\ -b2 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 8.6 -Plaintext: \ -8e 07 d6 6f 7b 88 0a 72 56 3a bc d3 f3 50 92 bc\ -33 40 9f b7 f8 8f 24 72 be -Seed: # not used yet\ -39 25 c7 1b 36 2d 40 a0 a6 de 42 14 55 79 ba 1e\ -7d d4 59 fc -Ciphertext: \ -3a fd 9c 66 00 14 7b 21 79 8d 81 8c 65 5a 0f 4c\ -92 12 db 26 d0 b0 df dc 2a 75 94 cc b3 d2 2f 5b\ -f1 d7 c3 e1 12 cd 73 fc 7d 50 9c 7a 8b af dd 3c\ -27 4d 13 99 00 9f 96 09 ec 4b e6 47 7e 45 3f 07\ -5a a3 3d b3 82 87 0c 1c 34 09 ae f3 92 d7 38 6a\ -e3 a6 96 b9 9a 94 b4 da 05 89 44 7e 95 5d 16 c9\ -8b 17 60 2a 59 bd 73 62 79 fc d8 fb 28 0c 44 62\ -d5 90 bf a9 bf 13 fe d5 70 ea fd e9 73 30 a2 c2\ -10 -Test: DecryptMatch - -AlgorithmType: AsymmetricCipher -Name: RSA/OAEP-MGF1(SHA-1) -Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors -KeyFormat: Component -Comment: Example 9: A 1536-bit RSA Key Pair -Modulus: \ -cf 2c d4 1e 34 ca 3a 72 8e a5 cb 8a ff 64 c3 6d\ -27 bd ef 53 64 e3 36 fd 68 d3 12 3c 5a 19 6a 8c\ -28 70 13 e8 53 d5 15 6d 58 d1 51 95 45 20 fb 4f\ -6d 7b 17 ab b6 81 77 65 90 9c 57 61 19 65 9d 90\ -2b 19 06 ed 8a 2b 10 c1 55 c2 4d 12 45 28 da b9\ -ee ae 37 9b ea c6 6e 4a 41 17 86 dc b8 fd 00 62\ -eb c0 30 de 12 19 a0 4c 2a 8c 1b 7d d3 13 1e 4d\ -6b 6c ae e2 e3 1a 5e d4 1a c1 50 9b 2e f1 ee 2a\ -b1 83 64 be 56 8c a9 41 c2 5e cc 84 ff 9d 64 3b\ -5e c1 aa ae 10 2a 20 d7 3f 47 9b 78 0f d6 da 91\ -07 52 12 d9 ea c0 3a 06 74 d8 99 eb a2 e4 31 f4\ -c4 4b 61 5b 6b a2 23 2b d4 b3 3b ae d7 3d 62 5d -PublicExponent: \ -01 00 01 -PrivateExponent: \ -19 8c 14 1e 23 71 5a 92 bc cf 6a 11 9a 5b c1 13\ -89 46 8d 28 11 f5 48 d7 27 e1 7b 4a b0 eb 98 6d\ -6f 21 1e fb 53 b7 1f 7c cb ea 87 ee 69 c7 5e e6\ -15 00 8c 53 32 de b5 2b f3 90 ab df bf e3 7d 72\ -05 36 81 59 b2 63 8c 1d e3 26 e2 1d 22 25 1f 0f\ -b5 84 8b 3b f1 50 05 d2 a7 43 30 f0 af e9 16 ee\ -62 cc c1 34 4d 1d 83 a7 09 e6 06 76 27 38 40 f7\ -f3 77 42 4a 5e 0a 4d a7 5f 01 b3 1f f7 68 19 cf\ -9c bf dd 21 52 43 c3 91 7c 03 ef 38 19 93 12 e5\ -67 b3 bf 7a ed 3a b4 57 f3 71 ef 8a 14 23 f4 5b\ -68 c6 e2 82 ec 11 1b ba 28 33 b9 87 fd 69 fa d8\ -3b c1 b8 c6 13 c5 e1 ea 16 c1 1e d1 25 ea 7e c1 -Prime1: \ -fc 8d 6c 04 be c4 eb 9a 81 92 ca 79 00 cb e5 36\ -e2 e8 b5 19 de cf 33 b2 45 97 98 c6 90 9d f4 f1\ -76 db 7d 23 19 0f c7 2b 88 65 a7 18 af 89 5f 1b\ -cd 91 45 29 80 27 42 3b 60 5e 70 a4 7c f5 83 90\ -a8 c3 e8 8f c8 c4 8e 8b 32 e3 da 21 0d fb e3 e8\ -81 ea 56 74 b6 a3 48 c2 1e 93 f9 e5 5e a6 5e fd -Prime2: \ -d2 00 d4 5e 78 8a ac ea 60 6a 40 1d 04 60 f8 7d\ -d5 c1 02 7e 12 dc 1a 0d 75 86 e8 93 9d 9c f7 89\ -b4 0f 51 ac 04 42 96 1d e7 d2 1c c2 1e 05 c8 31\ -55 c1 f2 aa 91 93 38 7c fd f9 56 cb 48 d1 53 ba\ -27 04 06 f9 bb ba 53 7d 49 87 d9 e2 f9 94 2d 7a\ -14 cb ff fe a7 4f ec dd a9 28 d2 3e 25 9f 5e e1 -ModPrime1PrivateExponent: \ -db 16 80 2f 79 a2 f0 d4 5f 35 8d 69 fd 33 e4 4b\ -81 fa e8 28 62 2e 93 a5 42 53 e9 97 d0 1b 07 43\ -75 9d a0 e8 12 b4 aa 4e 6c 8b ea b2 32 8d 54 31\ -95 5a 41 8a 67 ff 26 a8 c5 c8 07 a5 da 35 4e 05\ -ef 31 cc 8c f7 58 f4 63 73 29 50 b0 3e 26 57 26\ -fb 94 e3 9d 6a 57 2a 26 24 4a b0 8d b7 57 52 ad -ModPrime2PrivateExponent: \ -a0 a3 17 cf e7 df 14 23 f8 7a 6d ee 84 51 f4 e2\ -b4 a6 7e 54 97 f2 9b 4f 1e 4e 83 0b 9f ad d9 40\ -11 67 02 6f 55 96 e5 a3 9c 97 81 7e 0f 5f 16 e2\ -7e 19 ec 99 02 e0 1d 7e a6 fb 9a a3 c7 60 af ee\ -1e 38 1b 69 de 6a c9 c0 75 85 a0 6a d9 c4 ba 00\ -bf 75 c8 ad 2f a8 98 a4 79 e8 0a e2 94 fe d2 a1 -MultiplicativeInverseOfPrime2ModPrime1: \ -0b 21 f3 35 c3 53 34 2e b4 4c 3a a2 44 45 78 0c\ -2d 65 5b 94 01 74 ca e3 8c 7c 8a 4e 64 93 c0 ba\ -9f d3 03 74 82 67 b0 83 b9 a7 a6 cb 61 e4 2d b3\ -62 b8 c9 89 6d b7 06 4e 02 ad 5a e6 15 87 da 15\ -b4 64 9c 90 59 49 09 fe b3 7d bc b6 54 be b7 26\ -8e c8 01 e5 a8 b4 aa 39 11 be bd 88 54 2f 05 be -Test: KeyPairValidAndConsistent -Comment: RSAES-OAEP Encryption Example 9.1 -Plaintext: \ -f7 35 fd 55 ba 92 59 2c 3b 52 b8 f9 c4 f6 9a aa\ -1c be f8 fe 88 ad d0 95 59 54 12 46 7f 9c f4 ec\ -0b 89 6c 59 ed a1 62 10 e7 54 9c 8a bb 10 cd bc\ -21 a1 2e c9 b6 b5 b8 fd 2f 10 39 9e b6 -Seed: # not used yet\ -8e c9 65 f1 34 a3 ec 99 31 e9 2a 1c a0 dc 81 69\ -d5 ea 70 5c -Ciphertext: \ -26 7b cd 11 8a ca b1 fc 8b a8 1c 85 d7 30 03 cb\ -86 10 fa 55 c1 d9 7d a8 d4 8a 7c 7f 06 89 6a 4d\ -b7 51 aa 28 42 55 b9 d3 6a d6 5f 37 65 3d 82 9f\ -1b 37 f9 7b 80 01 94 25 45 b2 fc 2c 55 a7 37 6c\ -a7 a1 be 4b 17 60 c8 e0 5a 33 e5 aa 25 26 b8 d9\ -8e 31 70 88 e7 83 4c 75 5b 2a 59 b1 26 31 a1 82\ -c0 5d 5d 43 ab 17 79 26 4f 84 56 f5 15 ce 57 df\ -df 51 2d 54 93 da b7 b7 33 8d c4 b7 d7 8d b9 c0\ -91 ac 3b af 53 7a 69 fc 7f 54 9d 97 9f 0e ff 9a\ -94 fd a4 16 9b d4 d1 d1 9a 69 c9 9e 33 c3 b5 54\ -90 d5 01 b3 9b 1e da e1 18 ff 67 93 a1 53 26 15\ -84 d3 a5 f3 9f 6e 68 2e 3d 17 c8 cd 12 61 fa 72 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 9.2 -Plaintext: \ -81 b9 06 60 50 15 a6 3a ab e4 2d df 11 e1 97 89\ -12 f5 40 4c 74 74 b2 6d ce 3e d4 82 bf 96 1e cc\ -81 8b f4 20 c5 46 59 -Seed: # not used yet\ -ec b1 b8 b2 5f a5 0c da b0 8e 56 04 28 67 f4 af\ -58 26 d1 6c -Ciphertext: \ -93 ac 9f 06 71 ec 29 ac bb 44 4e ff c1 a5 74 13\ -51 d6 0f db 0e 39 3f bf 75 4a cf 0d e4 97 61 a1\ -48 41 df 77 72 e9 bc 82 77 39 66 a1 58 4c 4d 72\ -ba ea 00 11 8f 83 f3 5c ca 6e 53 7c bd 4d 81 1f\ -55 83 b2 97 83 d8 a6 d9 4c d3 1b e7 0d 6f 52 6c\ -10 ff 09 c6 fa 7c e0 69 79 5a 3f cd 05 11 fd 5f\ -cb 56 4b cc 80 ea 9c 78 f3 8b 80 01 25 39 d8 a4\ -dd f6 fe 81 e9 cd db 7f 50 db bb bc c7 e5 d8 60\ -97 cc f4 ec 49 18 9f b8 bf 31 8b e6 d5 a0 71 5d\ -51 6b 49 af 19 12 58 cd 32 dc 83 3c e6 eb 46 73\ -c0 3a 19 bb ac e8 8c c5 48 95 f6 36 cc 0c 1e c8\ -90 96 d1 1c e2 35 a2 65 ca 17 64 23 2a 68 9a e8 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 9.3 -Plaintext: \ -fd 32 64 29 df 9b 89 0e 09 b5 4b 18 b8 f3 4f 1e\ -24 -Seed: # not used yet\ -e8 9b b0 32 c6 ce 62 2c bd b5 3b c9 46 60 14 ea\ -77 f7 77 c0 -Ciphertext: \ -81 eb dd 95 05 4b 0c 82 2e f9 ad 76 93 f5 a8 7a\ -df b4 b4 c4 ce 70 df 2d f8 4e d4 9c 04 da 58 ba\ -5f c2 0a 19 e1 a6 e8 b7 a3 90 0b 22 79 6d c4 e8\ -69 ee 6b 42 79 2d 15 a8 ec eb 56 c0 9c 69 91 4e\ -81 3c ea 8f 69 31 e4 b8 ed 6f 42 1a f2 98 d5 95\ -c9 7f 47 89 c7 ca a6 12 c7 ef 36 09 84 c2 1b 93\ -ed c5 40 10 68 b5 af 4c 78 a8 77 1b 98 4d 53 b8\ -ea 8a df 2f 6a 7d 4a 0b a7 6c 75 e1 dd 9f 65 8f\ -20 de d4 a4 60 71 d4 6d 77 91 b5 68 03 d8 fe a7\ -f0 b0 f8 e4 1a e3 f0 93 83 a6 f9 58 5f e7 75 3e\ -aa ff d2 bf 94 56 31 08 be ec c2 07 bb b5 35 f5\ -fc c7 05 f0 dd e9 f7 08 c6 2f 49 a9 c9 03 71 d3 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 9.4 -Plaintext: \ -f1 45 9b 5f 0c 92 f0 1a 0f 72 3a 2e 56 62 48 4d\ -8f 8c 0a 20 fc 29 da d6 ac d4 3b b5 f3 ef fd f4\ -e1 b6 3e 07 fd fe 66 28 d0 d7 4c a1 9b f2 d6 9e\ -4a 0a bf 86 d2 93 92 5a 79 67 72 f8 08 8e -Seed: # not used yet\ -60 6f 3b 99 c0 b9 cc d7 71 ea a2 9e a0 e4 c8 84\ -f3 18 9c cc -Ciphertext: \ -bc c3 5f 94 cd e6 6c b1 13 66 25 d6 25 b9 44 32\ -a3 5b 22 f3 d2 fa 11 a6 13 ff 0f ca 5b d5 7f 87\ -b9 02 cc dc 1c d0 ae bc b0 71 5e e8 69 d1 d1 fe\ -39 5f 67 93 00 3f 5e ca 46 50 59 c8 86 60 d4 46\ -ff 5f 08 18 55 20 22 55 7e 38 c0 8a 67 ea d9 91\ -26 22 54 f1 06 82 97 5e c5 63 97 76 85 37 f4 97\ -7a f6 d5 f6 aa ce b7 fb 25 de c5 93 72 30 23 1f\ -d8 97 8a f4 91 19 a2 9f 29 e4 24 ab 82 72 b4 75\ -62 79 2d 5c 94 f7 74 b8 82 9d 0b 0d 9f 1a 8c 9e\ -dd f3 75 74 d5 fa 24 8e ef a9 c5 27 1f c5 ec 25\ -79 c8 1b dd 61 b4 10 fa 61 fe 36 e4 24 22 1c 11\ -3a dd b2 75 66 4c 80 1d 34 ca 8c 63 51 e4 a8 58 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 9.5 -Plaintext: \ -53 e6 e8 c7 29 d6 f9 c3 19 dd 31 7e 74 b0 db 8e\ -4c cc a2 5f 3c 83 05 74 6e 13 7a c6 3a 63 ef 37\ -39 e7 b5 95 ab b9 6e 8d 55 e5 4f 7b d4 1a b4 33\ -37 8f fb 91 1d -Seed: # not used yet\ -fc bc 42 14 02 e9 ec ab c6 08 2a fa 40 ba 5f 26\ -52 2c 84 0e -Ciphertext: \ -23 2a fb c9 27 fa 08 c2 f6 a2 7b 87 d4 a5 cb 09\ -c0 7d c2 6f ae 73 d7 3a 90 55 88 39 f4 fd 66 d2\ -81 b8 7e c7 34 bc e2 37 ba 16 66 98 ed 82 91 06\ -a7 de 69 42 cd 6c dc e7 8f ed 8d 2e 4d 81 42 8e\ -66 49 0d 03 62 64 ce f9 2a f9 41 d3 e3 50 55 fe\ -39 81 e1 4d 29 cb b9 a4 f6 74 73 06 3b ae c7 9a\ -11 79 f5 a1 7c 9c 18 32 f2 83 8f d7 d5 e5 9b b9\ -65 9d 56 dc e8 a0 19 ed ef 1b b3 ac cc 69 7c c6\ -cc 7a 77 8f 60 a0 64 c7 f6 f5 d5 29 c6 21 02 62\ -e0 03 de 58 3e 81 e3 16 7b 89 97 1f b8 c0 e1 5d\ -44 ff fe f8 9b 53 d8 d6 4d d7 97 d1 59 b5 6d 2b\ -08 ea 53 07 ea 12 c2 41 bd 58 d4 ee 27 8a 1f 2e -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 9.6 -Plaintext: \ -b6 b2 8e a2 19 8d 0c 10 08 bc 64 -Seed: # not used yet\ -23 aa de 0e 1e 08 bb 9b 9a 78 d2 30 2a 52 f9 c2\ -1b 2e 1b a2 -Ciphertext: \ -43 8c c7 dc 08 a6 8d a2 49 e4 25 05 f8 57 3b a6\ -0e 2c 27 73 d5 b2 90 f4 cf 9d ff 71 8e 84 20 81\ -c3 83 e6 70 24 a0 f2 95 94 ea 98 7b 9d 25 e4 b7\ -38 f2 85 97 0d 19 5a bb 3a 8c 80 54 e3 d7 9d 6b\ -9c 9a 83 27 ba 59 6f 12 59 e2 71 26 67 47 66 90\ -7d 8d 58 2f f3 a8 47 61 54 92 9a db 1e 6d 12 35\ -b2 cc b4 ec 8f 66 3b a9 cc 67 0a 92 be bd 85 3c\ -8d bf 69 c6 43 6d 01 6f 61 ad d8 36 e9 47 32 45\ -04 34 20 7f 9f d4 c4 3d ec 2a 12 a9 58 ef a0 1e\ -fe 26 69 89 9b 5e 60 4c 25 5c 55 fb 71 66 de 55\ -89 e3 69 59 7b b0 91 68 c0 6d d5 db 17 7e 06 a1\ -74 0e b2 d5 c8 2f ae ca 6d 92 fc ee 99 31 ba 9f -Test: DecryptMatch - -AlgorithmType: AsymmetricCipher -Name: RSA/OAEP-MGF1(SHA-1) -Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors -KeyFormat: Component -Comment: Example 10: A 2048-bit RSA Key Pair -Modulus: \ -ae 45 ed 56 01 ce c6 b8 cc 05 f8 03 93 5c 67 4d\ -db e0 d7 5c 4c 09 fd 79 51 fc 6b 0c ae c3 13 a8\ -df 39 97 0c 51 8b ff ba 5e d6 8f 3f 0d 7f 22 a4\ -02 9d 41 3f 1a e0 7e 4e be 9e 41 77 ce 23 e7 f5\ -40 4b 56 9e 4e e1 bd cf 3c 1f b0 3e f1 13 80 2d\ -4f 85 5e b9 b5 13 4b 5a 7c 80 85 ad ca e6 fa 2f\ -a1 41 7e c3 76 3b e1 71 b0 c6 2b 76 0e de 23 c1\ -2a d9 2b 98 08 84 c6 41 f5 a8 fa c2 6b da d4 a0\ -33 81 a2 2f e1 b7 54 88 50 94 c8 25 06 d4 01 9a\ -53 5a 28 6a fe b2 71 bb 9b a5 92 de 18 dc f6 00\ -c2 ae ea e5 6e 02 f7 cf 79 fc 14 cf 3b dc 7c d8\ -4f eb bb f9 50 ca 90 30 4b 22 19 a7 aa 06 3a ef\ -a2 c3 c1 98 0e 56 0c d6 4a fe 77 95 85 b6 10 76\ -57 b9 57 85 7e fd e6 01 09 88 ab 7d e4 17 fc 88\ -d8 f3 84 c4 e6 e7 2c 3f 94 3e 0c 31 c0 c4 a5 cc\ -36 f8 79 d8 a3 ac 9d 7d 59 86 0e aa da 6b 83 bb -PublicExponent: \ -01 00 01 -PrivateExponent: \ -05 6b 04 21 6f e5 f3 54 ac 77 25 0a 4b 6b 0c 85\ -25 a8 5c 59 b0 bd 80 c5 64 50 a2 2d 5f 43 8e 59\ -6a 33 3a a8 75 e2 91 dd 43 f4 8c b8 8b 9d 5f c0\ -d4 99 f9 fc d1 c3 97 f9 af c0 70 cd 9e 39 8c 8d\ -19 e6 1d b7 c7 41 0a 6b 26 75 df bf 5d 34 5b 80\ -4d 20 1a dd 50 2d 5c e2 df cb 09 1c e9 99 7b be\ -be 57 30 6f 38 3e 4d 58 81 03 f0 36 f7 e8 5d 19\ -34 d1 52 a3 23 e4 a8 db 45 1d 6f 4a 5b 1b 0f 10\ -2c c1 50 e0 2f ee e2 b8 8d ea 4a d4 c1 ba cc b2\ -4d 84 07 2d 14 e1 d2 4a 67 71 f7 40 8e e3 05 64\ -fb 86 d4 39 3a 34 bc f0 b7 88 50 1d 19 33 03 f1\ -3a 22 84 b0 01 f0 f6 49 ea f7 93 28 d4 ac 5c 43\ -0a b4 41 49 20 a9 46 0e d1 b7 bc 40 ec 65 3e 87\ -6d 09 ab c5 09 ae 45 b5 25 19 01 16 a0 c2 61 01\ -84 82 98 50 9c 1c 3b f3 a4 83 e7 27 40 54 e1 5e\ -97 07 50 36 e9 89 f6 09 32 80 7b 52 57 75 1e 79 -Prime1: \ -ec f5 ae cd 1e 55 15 ff fa cb d7 5a 28 16 c6 eb\ -f4 90 18 cd fb 46 38 e1 85 d6 6a 73 96 b6 f8 09\ -0f 80 18 c7 fd 95 cc 34 b8 57 dc 17 f0 cc 65 16\ -bb 13 46 ab 4d 58 2c ad ad 7b 41 03 35 23 87 b7\ -03 38 d0 84 04 7c 9d 95 39 b6 49 62 04 b3 dd 6e\ -a4 42 49 92 07 be c0 1f 96 42 87 ff 63 36 c3 98\ -46 58 33 68 46 f5 6e 46 86 18 81 c1 02 33 d2 17\ -6b f1 5a 5e 96 dd c7 80 bc 86 8a a7 7d 3c e7 69 -Prime2: \ -bc 46 c4 64 fc 6a c4 ca 78 3b 0e b0 8a 3c 84 1b\ -77 2f 7e 9b 2f 28 ba bd 58 8a e8 85 e1 a0 c6 1e\ -48 58 a0 fb 25 ac 29 99 90 f3 5b e8 51 64 c2 59\ -ba 11 75 cd d7 19 27 07 13 51 84 99 2b 6c 29 b7\ -46 dd 0d 2c ab e1 42 83 5f 7d 14 8c c1 61 52 4b\ -4a 09 94 6d 48 b8 28 47 3f 1c e7 6b 6c b6 88 6c\ -34 5c 03 e0 5f 41 d5 1b 5c 3a 90 a3 f2 40 73 c7\ -d7 4a 4f e2 5d 9c f2 1c 75 96 0f 3f c3 86 31 83 -ModPrime1PrivateExponent: \ -c7 35 64 57 1d 00 fb 15 d0 8a 3d e9 95 7a 50 91\ -5d 71 26 e9 44 2d ac f4 2b c8 2e 86 2e 56 73 ff\ -6a 00 8e d4 d2 e3 74 61 7d f8 9f 17 a1 60 b4 3b\ -7f da 9c b6 b6 b7 42 18 60 98 15 f7 d4 5c a2 63\ -c1 59 aa 32 d2 72 d1 27 fa f4 bc 8c a2 d7 73 78\ -e8 ae b1 9b 0a d7 da 3c b3 de 0a e7 31 49 80 f6\ -2b 6d 4b 0a 87 5d 1d f0 3c 1b ae 39 cc d8 33 ef\ -6c d7 e2 d9 52 8b f0 84 d1 f9 69 e7 94 e9 f6 c1 -ModPrime2PrivateExponent: \ -26 58 b3 7f 6d f9 c1 03 0b e1 db 68 11 7f a9 d8\ -7e 39 ea 2b 69 3b 7e 6d 3a 2f 70 94 74 13 ee c6\ -14 2e 18 fb 8d fc b6 ac 54 5d 7c 86 a0 ad 48 f8\ -45 71 70 f0 ef b2 6b c4 81 26 c5 3e fd 1d 16 92\ -01 98 dc 2a 11 07 dc 28 2d b6 a8 0c d3 06 23 60\ -ba 3f a1 3f 70 e4 31 2f f1 a6 cd 6b 8f c4 cd 9c\ -5c 3d b1 7c 6d 6a 57 21 2f 73 ae 29 f6 19 32 7b\ -ad 59 b1 53 85 85 85 ba 4e 28 b6 0a 62 a4 5e 49 -MultiplicativeInverseOfPrime2ModPrime1: \ -6f 38 52 6b 39 25 08 55 34 ef 3e 41 5a 83 6e de\ -8b 86 15 8a 2c 7c bf ec cb 0b d8 34 30 4f ec 68\ -3b a8 d4 f4 79 c4 33 d4 34 16 e6 32 69 62 3c ea\ -10 07 76 d8 5a ff 40 1d 3f ff 61 0e e6 54 11 ce\ -3b 13 63 d6 3a 97 09 ee de 42 64 7c ea 56 14 93\ -d5 45 70 a8 79 c1 86 82 cd 97 71 0b 96 20 5e c3\ -11 17 d7 3b 5f 36 22 3f ad d6 e8 ba 90 dd 7c 0e\ -e6 1d 44 e1 63 25 1e 20 c7 f6 6e b3 05 11 7c b8 -Test: KeyPairValidAndConsistent -Comment: RSAES-OAEP Encryption Example 10.1 -Plaintext: \ -8b ba 6b f8 2a 6c 0f 86 d5 f1 75 6e 97 95 68 70\ -b0 89 53 b0 6b 4e b2 05 bc 16 94 ee -Seed: # not used yet\ -47 e1 ab 71 19 fe e5 6c 95 ee 5e aa d8 6f 40 d0\ -aa 63 bd 33 -Ciphertext: \ -53 ea 5d c0 8c d2 60 fb 3b 85 85 67 28 7f a9 15\ -52 c3 0b 2f eb fb a2 13 f0 ae 87 70 2d 06 8d 19\ -ba b0 7f e5 74 52 3d fb 42 13 9d 68 c3 c5 af ee\ -e0 bf e4 cb 79 69 cb f3 82 b8 04 d6 e6 13 96 14\ -4e 2d 0e 60 74 1f 89 93 c3 01 4b 58 b9 b1 95 7a\ -8b ab cd 23 af 85 4f 4c 35 6f b1 66 2a a7 2b fc\ -c7 e5 86 55 9d c4 28 0d 16 0c 12 67 85 a7 23 eb\ -ee be ff 71 f1 15 94 44 0a ae f8 7d 10 79 3a 87\ -74 a2 39 d4 a0 4c 87 fe 14 67 b9 da f8 52 08 ec\ -6c 72 55 79 4a 96 cc 29 14 2f 9a 8b d4 18 e3 c1\ -fd 67 34 4b 0c d0 82 9d f3 b2 be c6 02 53 19 62\ -93 c6 b3 4d 3f 75 d3 2f 21 3d d4 5c 62 73 d5 05\ -ad f4 cc ed 10 57 cb 75 8f c2 6a ee fa 44 12 55\ -ed 4e 64 c1 99 ee 07 5e 7f 16 64 61 82 fd b4 64\ -73 9b 68 ab 5d af f0 e6 3e 95 52 01 68 24 f0 54\ -bf 4d 3c 8c 90 a9 7b b6 b6 55 32 84 eb 42 9f cc -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 10.2 -Plaintext: \ -e6 ad 18 1f 05 3b 58 a9 04 f2 45 75 10 37 3e 57 -Seed: # not used yet\ -6d 17 f5 b4 c1 ff ac 35 1d 19 5b f7 b0 9d 09 f0\ -9a 40 79 cf -Ciphertext: \ -a2 b1 a4 30 a9 d6 57 e2 fa 1c 2b b5 ed 43 ff b2\ -5c 05 a3 08 fe 90 93 c0 10 31 79 5f 58 74 40 01\ -10 82 8a e5 8f b9 b5 81 ce 9d dd d3 e5 49 ae 04\ -a0 98 54 59 bd e6 c6 26 59 4e 7b 05 dc 42 78 b2\ -a1 46 5c 13 68 40 88 23 c8 5e 96 dc 66 c3 a3 09\ -83 c6 39 66 4f c4 56 9a 37 fe 21 e5 a1 95 b5 77\ -6e ed 2d f8 d8 d3 61 af 68 6e 75 02 29 bb d6 63\ -f1 61 86 8a 50 61 5e 0c 33 7b ec 0c a3 5f ec 0b\ -b1 9c 36 eb 2e 0b bc c0 58 2f a1 d9 3a ac db 06\ -10 63 f5 9f 2c e1 ee 43 60 5e 5d 89 ec a1 83 d2\ -ac df e9 f8 10 11 02 2a d3 b4 3a 3d d4 17 da c9\ -4b 4e 11 ea 81 b1 92 96 6e 96 6b 18 20 82 e7 19\ -64 60 7b 4f 80 02 f3 62 99 84 4a 11 f2 ae 0f ae\ -ac 2e ae 70 f8 f4 f9 80 88 ac dc d0 ac 55 6e 9f\ -cc c5 11 52 19 08 fa d2 6f 04 c6 42 01 45 03 05\ -77 87 58 b0 53 8b f8 b5 bb 14 4a 82 8e 62 97 95 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 10.3 -Plaintext: \ -51 0a 2c f6 0e 86 6f a2 34 05 53 c9 4e a3 9f bc\ -25 63 11 e8 3e 94 45 4b 41 24 -Seed: # not used yet\ -38 53 87 51 4d ec cc 7c 74 0d d8 cd f9 da ee 49\ -a1 cb fd 54 -Ciphertext: \ -98 86 c3 e6 76 4a 8b 9a 84 e8 41 48 eb d8 c3 b1\ -aa 80 50 38 1a 78 f6 68 71 4c 16 d9 cf d2 a6 ed\ -c5 69 79 c5 35 d9 de e3 b4 4b 85 c1 8b e8 92 89\ -92 37 17 11 47 22 16 d9 5d da 98 d2 ee 83 47 c9\ -b1 4d ff df f8 4a a4 8d 25 ac 06 f7 d7 e6 53 98\ -ac 96 7b 1c e9 09 25 f6 7d ce 04 9b 7f 81 2d b0\ -74 29 97 a7 4d 44 fe 81 db e0 e7 a3 fe af 2e 5c\ -40 af 88 8d 55 0d db be 3b c2 06 57 a2 95 43 f8\ -fc 29 13 b9 bd 1a 61 b2 ab 22 56 ec 40 9b bd 7d\ -c0 d1 77 17 ea 25 c4 3f 42 ed 27 df 87 38 bf 4a\ -fc 67 66 ff 7a ff 08 59 55 5e e2 83 92 0f 4c 8a\ -63 c4 a7 34 0c ba fd dc 33 9e cd b4 b0 51 50 02\ -f9 6c 93 2b 5b 79 16 7a f6 99 c0 ad 3f cc fd f0\ -f4 4e 85 a7 02 62 bf 2e 18 fe 34 b8 50 58 99 75\ -e8 67 ff 96 9d 48 ea bf 21 22 71 54 6c dc 05 a6\ -9e cb 52 6e 52 87 0c 83 6f 30 7b d7 98 78 0e de -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 10.4 -Plaintext: \ -bc dd 19 0d a3 b7 d3 00 df 9a 06 e2 2c aa e2 a7\ -5f 10 c9 1f f6 67 b7 c1 6b de 8b 53 06 4a 26 49\ -a9 40 45 c9 -Seed: # not used yet\ -5c ac a6 a0 f7 64 16 1a 96 84 f8 5d 92 b6 e0 ef\ -37 ca 8b 65 -Ciphertext: \ -63 18 e9 fb 5c 0d 05 e5 30 7e 16 83 43 6e 90 32\ -93 ac 46 42 35 8a aa 22 3d 71 63 01 3a ba 87 e2\ -df da 8e 60 c6 86 0e 29 a1 e9 26 86 16 3e a0 b9\ -17 5f 32 9c a3 b1 31 a1 ed d3 a7 77 59 a8 b9 7b\ -ad 6a 4f 8f 43 96 f2 8c f6 f3 9c a5 81 12 e4 81\ -60 d6 e2 03 da a5 85 6f 3a ca 5f fe d5 77 af 49\ -94 08 e3 df d2 33 e3 e6 04 db e3 4a 9c 4c 90 82\ -de 65 52 7c ac 63 31 d2 9d c8 0e 05 08 a0 fa 71\ -22 e7 f3 29 f6 cc a5 cf a3 4d 4d 1d a4 17 80 54\ -57 e0 08 be c5 49 e4 78 ff 9e 12 a7 63 c4 77 d1\ -5b bb 78 f5 b6 9b d5 78 30 fc 2c 4e d6 86 d7 9b\ -c7 2a 95 d8 5f 88 13 4c 6b 0a fe 56 a8 cc fb c8\ -55 82 8b b3 39 bd 17 90 9c f1 d7 0d e3 33 5a e0\ -70 39 09 3e 60 6d 65 53 65 de 65 50 b8 72 cd 6d\ -e1 d4 40 ee 03 1b 61 94 5f 62 9a d8 a3 53 b0 d4\ -09 39 e9 6a 3c 45 0d 2a 8d 5e ee 9f 67 80 93 c8 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 10.5 -Plaintext: \ -a7 dd 6c 7d c2 4b 46 f9 dd 5f 1e 91 ad a4 c3 b3\ -df 94 7e 87 72 32 a9 -Seed: # not used yet\ -95 bc a9 e3 85 98 94 b3 dd 86 9f a7 ec d5 bb c6\ -40 1b f3 e4 -Ciphertext: \ -75 29 08 72 cc fd 4a 45 05 66 0d 65 1f 56 da 6d\ -aa 09 ca 13 01 d8 90 63 2f 6a 99 2f 3d 56 5c ee\ -46 4a fd ed 40 ed 3b 5b e9 35 67 14 ea 5a a7 65\ -5f 4a 13 66 c2 f1 7c 72 8f 6f 2c 5a 5d 1f 8e 28\ -42 9b c4 e6 f8 f2 cf f8 da 8d c0 e0 a9 80 8e 45\ -fd 09 ea 2f a4 0c b2 b6 ce 6f ff f5 c0 e1 59 d1\ -1b 68 d9 0a 85 f7 b8 4e 10 3b 09 e6 82 66 64 80\ -c6 57 50 5c 09 29 25 94 68 a3 14 78 6d 74 ea b1\ -31 57 3c f2 34 bf 57 db 7d 9e 66 cc 67 48 19 2e\ -00 2d c0 de ea 93 05 85 f0 83 1f dc d9 bc 33 d5\ -1f 79 ed 2f fc 16 bc f4 d5 98 12 fc eb ca a3 f9\ -06 9b 0e 44 56 86 d6 44 c2 5c cf 63 b4 56 ee 5f\ -a6 ff e9 6f 19 cd f7 51 fe d9 ea f3 59 57 75 4d\ -bf 4b fe a5 21 6a a1 84 4d c5 07 cb 2d 08 0e 72\ -2e ba 15 03 08 c2 b5 ff 11 93 62 0f 17 66 ec f4\ -48 1b af b9 43 bd 29 28 77 f2 13 6c a4 94 ab a0 -Test: DecryptMatch -Comment: RSAES-OAEP Encryption Example 10.6 -Plaintext: \ -ea f1 a7 3a 1b 0c 46 09 53 7d e6 9c d9 22 8b bc\ -fb 9a 8c a8 c6 c3 ef af 05 6f e4 a7 f4 63 4e d0\ -0b 7c 39 ec 69 22 d7 b8 ea 2c 04 eb ac -Seed: # not used yet\ -9f 47 dd f4 2e 97 ee a8 56 a9 bd bc 71 4e b3 ac\ -22 f6 eb 32 -Ciphertext: \ -2d 20 7a 73 43 2a 8f b4 c0 30 51 b3 f7 3b 28 a6\ -17 64 09 8d fa 34 c4 7a 20 99 5f 81 15 aa 68 16\ -67 9b 55 7e 82 db ee 58 49 08 c6 e6 97 82 d7 de\ -b3 4d bd 65 af 06 3d 57 fc a7 6a 5f d0 69 49 2f\ -d6 06 8d 99 84 d2 09 35 05 65 a6 2e 5c 77 f2 30\ -38 c1 2c b1 0c 66 34 70 9b 54 7c 46 f6 b4 a7 09\ -bd 85 ca 12 2d 74 46 5e f9 77 62 c2 97 63 e0 6d\ -bc 7a 9e 73 8c 78 bf ca 01 02 dc 5e 79 d6 5b 97\ -3f 28 24 0c aa b2 e1 61 a7 8b 57 d2 62 45 7e d8\ -19 5d 53 e3 c7 ae 9d a0 21 88 3c 6d b7 c2 4a fd\ -d2 32 2e ac 97 2a d3 c3 54 c5 fc ef 1e 14 6c 3a\ -02 90 fb 67 ad f0 07 06 6e 00 42 8d 2c ec 18 ce\ -58 f9 32 86 98 de fe f4 b2 eb 5e c7 69 18 fd e1\ -c1 98 cb b3 8b 7a fc 67 62 6a 9a ef ec 43 22 bf\ -d9 0d 25 63 48 1c 9a 22 1f 78 c8 27 2c 82 d1 b6\ -2a b9 14 e1 c6 9f 6a f6 ef 30 ca 52 60 db 4a 46 -Test: DecryptMatch diff --git a/embeddedcryptopp/TestVectors/rsa_pkcs1_1_5.txt b/embeddedcryptopp/TestVectors/rsa_pkcs1_1_5.txt deleted file mode 100644 index 2272b7c..0000000 --- a/embeddedcryptopp/TestVectors/rsa_pkcs1_1_5.txt +++ /dev/null @@ -1,89 +0,0 @@ -AlgorithmType: Signature -Name: RSA/PKCS1-1.5(MD2) -KeyFormat: DER -Source: http://www.rsasecurity.com/rsalabs/pkcs/index.html, \ - Some Examples of the PKCS Standards -PrivateKey: \ - 30 82 01 50\ - 02 01 00 #version = 0\ - 30 0d #privateKeyAlgorithmIdentifier\ - 06 09 #algorithm = rsaEncryption\ - 2a 86 48 86 f7 0d 01 01 01\ - 05 00 #parameters = NULL\ - 04 82 01 3a #privateKey = RSAPrivateKey encoding\ - 30 82 01 36\ - 02 01 00 #version = 0\ - 02 40 #modulus = n\ - 0a 66 79 1d c6 98 81 68 de 7a b7 74 19 bb 7f b0\ - c0 01 c6 27 10 27 00 75 14 29 42 e1 9a 8d 8c 51\ - d0 53 b3 e3 78 2a 1d e5 dc 5a f4 eb e9 94 68 17\ - 01 14 a1 df e6 7c dc 9a 9a f5 5d 65 56 20 bb ab\ - 02 03 01 00 01 #publicExponent = e\ - 02 40 #privateExponent = d\ - 01 23 c5 b6 1b a3 6e db 1d 36 79 90 41 99 a8 9e\ - a8 0c 09 b9 12 2e 14 00 c0 9a dc f7 78 46 76 d0\ - 1d 23 35 6a 7d 44 d6 bd 8b d5 0e 94 bf c7 23 fa\ - 87 d8 86 2b 75 17 76 91 c1 1d 75 76 92 df 88 81\ - 02 20 #prime1 = p\ - 33 d4 84 45 c8 59 e5 23 40 de 70 4b cd da 06 5f\ - bb 40 58 d7 40 bd 1d 67 d2 9e 9c 14 6c 11 cf 61\ - 02 20 #prime2 = q\ - 33 5e 84 08 86 6b 0f d3 8d c7 00 2d 3f 97 2c 67\ - 38 9a 65 d5 d8 30 65 66 d5 c4 f2 a5 aa 52 62 8b\ - 02 20 #exponent1 = d mod p-1\ - 04 5e c9 00 71 52 53 25 d3 d4 6d b7 96 95 e9 af\ - ac c4 52 39 64 36 0e 02 b1 19 ba a3 66 31 62 41\ - 02 20 #exponent2 = d mod q-1\ - 15 eb 32 73 60 c7 b6 0d 12 e5 e2 d1 6b dc d9 79\ - 81 d1 7f ba 6b 70 db 13 b2 0b 43 6e 24 ea da 59\ - 02 20 #coefficient = q-1 mod p\ - 2c a6 36 6d 72 78 1d fa 24 d3 4a 9a 24 cb c2 ae\ - 92 7a 99 58 af 42 65 63 ff 63 fb 11 65 8a 46 1d -PublicKey: \ - 30 5b #subjectPublicKeyInfo\ - 30 0d #algorithm\ - 06 09 #algorithm = rsaEncryption\ - 2a 86 48 86 f7 0d 01 01 01\ - 05 00 #parameters = NULL\ - 03 4a #subjectPublicKey = RSAPublicKey encoding\ - 00\ - 30 47\ - 02 40 #modulus = n\ - 0a 66 79 1d c6 98 81 68 de 7a b7 74 19 bb 7f b0\ - c0 01 c6 27 10 27 00 75 14 29 42 e1 9a 8d 8c 51\ - d0 53 b3 e3 78 2a 1d e5 dc 5a f4 eb e9 94 68 17\ - 01 14 a1 df e6 7c dc 9a 9a f5 5d 65 56 20 bb ab\ - 02 03 01 00 01 #publicExponent = e -Test: KeyPairValidAndConsistent -Message: # "Everyone gets Friday off."\ - 45 76 65 72 79 6f 6e 65 20 67 65 74 73 20 46 72 69 64 61 79 20 6f 66 66 2e -Signature: \ - 05fa6a812fc7df8bf4f2542509e03e84\ - 6e11b9c620be2009efb440efbcc66921\ - 6994ac04f341b57d05202d428fb2a27b\ - 5c77dfd9b15bfc3d559353503410c1e1 -Test: Verify -Name: RSA/PKCS1-1.5(SHA-1) -Source: generated by Wei Dai using Crypto++ 5.0 -Signature: 0610761F95FFD1B8F29DA34212947EC2AA0E358866A722F03CC3C41487ADC604A48FF54F5C6BEDB9FB7BD59F82D6E55D8F3174BA361B2214B2D74E8825E04E81 -Test: Verify -Message: 00 -Test: NotVerify - -AlgorithmType: Signature -Name: RSA/PKCS1-1.5(SHA-1) -Source: http://islab.oregonstate.edu/emails/pkcs-tng-02/0152 -KeyFormat: Component -Modulus: A885B6F851A8079AB8A281DB0297148511EE0D8C07C0D4AE6D6FED461488E0D41E3FF8F281B06A3240B5007A5C2AB4FB6BE8AF88F119DB998368DDDC9710ABED -PublicExponent: 010001 -PrivateExponent: 2B259D2CA3DF851EE891F6F4678BDDFD9A131C95D3305C63D2723B4A5B9C960F5EC8BB7DCDDBEBD8B6A38767D64AD451E9383E0891E4EE7506100481F2B49323 -Prime1: D7103CD676E39824E2BE50B8E6533FE7CB7484348E283802AD2B8D00C80D19DF -Prime2: C89996DC169CEB3F227958275968804D4BE9FC4012C3219662F1A438C9950BB3 -ModPrime1PrivateExponent: 5D8EA4C8AF83A70634D5920C3DB66D908AC3AF57A597FD75BC9BBB856181C185 -ModPrime2PrivateExponent: C598E54DAEC8ABC1E907769A6C2BD01653ED0C9960E1EDB7E186FDA922883A99 -MultiplicativeInverseOfPrime2ModPrime1: 7C6F27B5B51B78AD80FB36E700990CF307866F2943124CBD93D97C137794C104 -Test: KeyPairValidAndConsistent -Source: generated by Wei Dai using Crypto++ 5.0 -Message: 74657374 # "test" -Signature: A7E00CE4391F914D82158D9B732759808E25A1C6383FE87A5199157650D4296CF612E9FF809E686A0AF328238306E79965F6D0138138829D9A1A22764306F6CE -Test: Verify diff --git a/embeddedcryptopp/TestVectors/rsa_pss.txt b/embeddedcryptopp/TestVectors/rsa_pss.txt deleted file mode 100644 index 1b5fc9c..0000000 --- a/embeddedcryptopp/TestVectors/rsa_pss.txt +++ /dev/null @@ -1,2083 +0,0 @@ -AlgorithmType: Signature -Name: RSA/PSS-MGF1(SHA-1) -Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors -KeyFormat: Component -Comment: Example 1: A 1024-bit RSA Key Pair -Modulus: \ -a5 6e 4a 0e 70 10 17 58 9a 51 87 dc 7e a8 41 d1\ -56 f2 ec 0e 36 ad 52 a4 4d fe b1 e6 1f 7a d9 91\ -d8 c5 10 56 ff ed b1 62 b4 c0 f2 83 a1 2a 88 a3\ -94 df f5 26 ab 72 91 cb b3 07 ce ab fc e0 b1 df\ -d5 cd 95 08 09 6d 5b 2b 8b 6d f5 d6 71 ef 63 77\ -c0 92 1c b2 3c 27 0a 70 e2 59 8e 6f f8 9d 19 f1\ -05 ac c2 d3 f0 cb 35 f2 92 80 e1 38 6b 6f 64 c4\ -ef 22 e1 e1 f2 0d 0c e8 cf fb 22 49 bd 9a 21 37 -PublicExponent: \ -01 00 01 -PrivateExponent: \ -33 a5 04 2a 90 b2 7d 4f 54 51 ca 9b bb d0 b4 47\ -71 a1 01 af 88 43 40 ae f9 88 5f 2a 4b be 92 e8\ -94 a7 24 ac 3c 56 8c 8f 97 85 3a d0 7c 02 66 c8\ -c6 a3 ca 09 29 f1 e8 f1 12 31 88 44 29 fc 4d 9a\ -e5 5f ee 89 6a 10 ce 70 7c 3e d7 e7 34 e4 47 27\ -a3 95 74 50 1a 53 26 83 10 9c 2a ba ca ba 28 3c\ -31 b4 bd 2f 53 c3 ee 37 e3 52 ce e3 4f 9e 50 3b\ -d8 0c 06 22 ad 79 c6 dc ee 88 35 47 c6 a3 b3 25 -Prime1: \ -e7 e8 94 27 20 a8 77 51 72 73 a3 56 05 3e a2 a1\ -bc 0c 94 aa 72 d5 5c 6e 86 29 6b 2d fc 96 79 48\ -c0 a7 2c bc cc a7 ea cb 35 70 6e 09 a1 df 55 a1\ -53 5b d9 b3 cc 34 16 0b 3b 6d cd 3e da 8e 64 43 -Prime2: \ -b6 9d ca 1c f7 d4 d7 ec 81 e7 5b 90 fc ca 87 4a\ -bc de 12 3f d2 70 01 80 aa 90 47 9b 6e 48 de 8d\ -67 ed 24 f9 f1 9d 85 ba 27 58 74 f5 42 cd 20 dc\ -72 3e 69 63 36 4a 1f 94 25 45 2b 26 9a 67 99 fd -ModPrime1PrivateExponent: \ -28 fa 13 93 86 55 be 1f 8a 15 9c ba ca 5a 72 ea\ -19 0c 30 08 9e 19 cd 27 4a 55 6f 36 c4 f6 e1 9f\ -55 4b 34 c0 77 79 04 27 bb dd 8d d3 ed e2 44 83\ -28 f3 85 d8 1b 30 e8 e4 3b 2f ff a0 27 86 19 79 -ModPrime2PrivateExponent: \ -1a 8b 38 f3 98 fa 71 20 49 89 8d 7f b7 9e e0 a7\ -76 68 79 12 99 cd fa 09 ef c0 e5 07 ac b2 1e d7\ -43 01 ef 5b fd 48 be 45 5e ae b6 e1 67 82 55 82\ -75 80 a8 e4 e8 e1 41 51 d1 51 0a 82 a3 f2 e7 29 -MultiplicativeInverseOfPrime2ModPrime1: \ -27 15 6a ba 41 26 d2 4a 81 f3 a5 28 cb fb 27 f5\ -68 86 f8 40 a9 f6 e8 6e 17 a4 4b 94 fe 93 19 58\ -4b 8e 22 fd de 1e 5a 2e 3b d8 aa 5b a8 d8 58 41\ -94 eb 21 90 ac f8 32 b8 47 f1 3a 3d 24 a7 9f 4d -Test: KeyPairValidAndConsistent -Comment: RSASSA-PSS Signature Example 1.1 -Message: \ -cd c8 7d a2 23 d7 86 df 3b 45 e0 bb bc 72 13 26\ -d1 ee 2a f8 06 cc 31 54 75 cc 6f 0d 9c 66 e1 b6\ -23 71 d4 5c e2 39 2e 1a c9 28 44 c3 10 10 2f 15\ -6a 0d 8d 52 c1 f4 c4 0b a3 aa 65 09 57 86 cb 76\ -97 57 a6 56 3b a9 58 fe d0 bc c9 84 e8 b5 17 a3\ -d5 f5 15 b2 3b 8a 41 e7 4a a8 67 69 3f 90 df b0\ -61 a6 e8 6d fa ae e6 44 72 c0 0e 5f 20 94 57 29\ -cb eb e7 7f 06 ce 78 e0 8f 40 98 fb a4 1f 9d 61\ -93 c0 31 7e 8b 60 d4 b6 08 4a cb 42 d2 9e 38 08\ -a3 bc 37 2d 85 e3 31 17 0f cb f7 cc 72 d0 b7 1c\ -29 66 48 b3 a4 d1 0f 41 62 95 d0 80 7a a6 25 ca\ -b2 74 4f d9 ea 8f d2 23 c4 25 37 02 98 28 bd 16\ -be 02 54 6f 13 0f d2 e3 3b 93 6d 26 76 e0 8a ed\ -1b 73 31 8b 75 0a 01 67 d0 -Salt: \ -de e9 59 c7 e0 64 11 36 14 20 ff 80 18 5e d5 7f\ -3e 67 76 af -Signature: \ -90 74 30 8f b5 98 e9 70 1b 22 94 38 8e 52 f9 71\ -fa ac 2b 60 a5 14 5a f1 85 df 52 87 b5 ed 28 87\ -e5 7c e7 fd 44 dc 86 34 e4 07 c8 e0 e4 36 0b c2\ -26 f3 ec 22 7f 9d 9e 54 63 8e 8d 31 f5 05 12 15\ -df 6e bb 9c 2f 95 79 aa 77 59 8a 38 f9 14 b5 b9\ -c1 bd 83 c4 e2 f9 f3 82 a0 d0 aa 35 42 ff ee 65\ -98 4a 60 1b c6 9e b2 8d eb 27 dc a1 2c 82 c2 d4\ -c3 f6 6c d5 00 f1 ff 2b 99 4d 8a 4e 30 cb b3 3c -Test: Verify -Comment: RSASSA-PSS Signature Example 1.2 -Message: \ -85 13 84 cd fe 81 9c 22 ed 6c 4c cb 30 da eb 5c\ -f0 59 bc 8e 11 66 b7 e3 53 0c 4c 23 3e 2b 5f 8f\ -71 a1 cc a5 82 d4 3e cc 72 b1 bc a1 6d fc 70 13\ -22 6b 9e -Salt: \ -ef 28 69 fa 40 c3 46 cb 18 3d ab 3d 7b ff c9 8f\ -d5 6d f4 2d -Signature: \ -3e f7 f4 6e 83 1b f9 2b 32 27 41 42 a5 85 ff ce\ -fb dc a7 b3 2a e9 0d 10 fb 0f 0c 72 99 84 f0 4e\ -f2 9a 9d f0 78 07 75 ce 43 73 9b 97 83 83 90 db\ -0a 55 05 e6 3d e9 27 02 8d 9d 29 b2 19 ca 2c 45\ -17 83 25 58 a5 5d 69 4a 6d 25 b9 da b6 60 03 c4\ -cc cd 90 78 02 19 3b e5 17 0d 26 14 7d 37 b9 35\ -90 24 1b e5 1c 25 05 5f 47 ef 62 75 2c fb e2 14\ -18 fa fe 98 c2 2c 4d 4d 47 72 4f db 56 69 e8 43 -Test: Verify -Comment: RSASSA-PSS Signature Example 1.3 -Message: \ -a4 b1 59 94 17 61 c4 0c 6a 82 f2 b8 0d 1b 94 f5\ -aa 26 54 fd 17 e1 2d 58 88 64 67 9b 54 cd 04 ef\ -8b d0 30 12 be 8d c3 7f 4b 83 af 79 63 fa ff 0d\ -fa 22 54 77 43 7c 48 01 7f f2 be 81 91 cf 39 55\ -fc 07 35 6e ab 3f 32 2f 7f 62 0e 21 d2 54 e5 db\ -43 24 27 9f e0 67 e0 91 0e 2e 81 ca 2c ab 31 c7\ -45 e6 7a 54 05 8e b5 0d 99 3c db 9e d0 b4 d0 29\ -c0 6d 21 a9 4c a6 61 c3 ce 27 fa e1 d6 cb 20 f4\ -56 4d 66 ce 47 67 58 3d 0e 5f 06 02 15 b5 90 17\ -be 85 ea 84 89 39 12 7b d8 c9 c4 d4 7b 51 05 6c\ -03 1c f3 36 f1 7c 99 80 f3 b8 f5 b9 b6 87 8e 8b\ -79 7a a4 3b 88 26 84 33 3e 17 89 3f e9 ca a6 aa\ -29 9f 7e d1 a1 8e e2 c5 48 64 b7 b2 b9 9b 72 61\ -8f b0 25 74 d1 39 ef 50 f0 19 c9 ee f4 16 97 13\ -38 e7 d4 70 -Salt: \ -71 0b 9c 47 47 d8 00 d4 de 87 f1 2a fd ce 6d f1\ -81 07 cc 77 -Signature: \ -66 60 26 fb a7 1b d3 e7 cf 13 15 7c c2 c5 1a 8e\ -4a a6 84 af 97 78 f9 18 49 f3 43 35 d1 41 c0 01\ -54 c4 19 76 21 f9 62 4a 67 5b 5a bc 22 ee 7d 5b\ -aa ff aa e1 c9 ba ca 2c c3 73 b3 f3 3e 78 e6 14\ -3c 39 5a 91 aa 7f ac a6 64 eb 73 3a fd 14 d8 82\ -72 59 d9 9a 75 50 fa ca 50 1e f2 b0 4e 33 c2 3a\ -a5 1f 4b 9e 82 82 ef db 72 8c c0 ab 09 40 5a 91\ -60 7c 63 69 96 1b c8 27 0d 2d 4f 39 fc e6 12 b1 -Test: Verify -Comment: RSASSA-PSS Signature Example 1.4 -Message: \ -bc 65 67 47 fa 9e af b3 f0 -Salt: \ -05 6f 00 98 5d e1 4d 8e f5 ce a9 e8 2f 8c 27 be\ -f7 20 33 5e -Signature: \ -46 09 79 3b 23 e9 d0 93 62 dc 21 bb 47 da 0b 4f\ -3a 76 22 64 9a 47 d4 64 01 9b 9a ea fe 53 35 9c\ -17 8c 91 cd 58 ba 6b cb 78 be 03 46 a7 bc 63 7f\ -4b 87 3d 4b ab 38 ee 66 1f 19 96 34 c5 47 a1 ad\ -84 42 e0 3d a0 15 b1 36 e5 43 f7 ab 07 c0 c1 3e\ -42 25 b8 de 8c ce 25 d4 f6 eb 84 00 f8 1f 7e 18\ -33 b7 ee 6e 33 4d 37 09 64 ca 79 fd b8 72 b4 d7\ -52 23 b5 ee b0 81 01 59 1f b5 32 d1 55 a6 de 87 -Test: Verify -Comment: RSASSA-PSS Signature Example 1.5 -Message: \ -b4 55 81 54 7e 54 27 77 0c 76 8e 8b 82 b7 55 64\ -e0 ea 4e 9c 32 59 4d 6b ff 70 65 44 de 0a 87 76\ -c7 a8 0b 45 76 55 0e ee 1b 2a ca bc 7e 8b 7d 3e\ -f7 bb 5b 03 e4 62 c1 10 47 ea dd 00 62 9a e5 75\ -48 0a c1 47 0f e0 46 f1 3a 2b f5 af 17 92 1d c4\ -b0 aa 8b 02 be e6 33 49 11 65 1d 7f 85 25 d1 0f\ -32 b5 1d 33 be 52 0d 3d df 5a 70 99 55 a3 df e7\ -82 83 b9 e0 ab 54 04 6d 15 0c 17 7f 03 7f dc cc\ -5b e4 ea 5f 68 b5 e5 a3 8c 9d 7e dc cc c4 97 5f\ -45 5a 69 09 b4 -Salt: \ -80 e7 0f f8 6a 08 de 3e c6 09 72 b3 9b 4f bf dc\ -ea 67 ae 8e -Signature: \ -1d 2a ad 22 1c a4 d3 1d df 13 50 92 39 01 93 98\ -e3 d1 4b 32 dc 34 dc 5a f4 ae ae a3 c0 95 af 73\ -47 9c f0 a4 5e 56 29 63 5a 53 a0 18 37 76 15 b1\ -6c b9 b1 3b 3e 09 d6 71 eb 71 e3 87 b8 54 5c 59\ -60 da 5a 64 77 6e 76 8e 82 b2 c9 35 83 bf 10 4c\ -3f db 23 51 2b 7b 4e 89 f6 33 dd 00 63 a5 30 db\ -45 24 b0 1c 3f 38 4c 09 31 0e 31 5a 79 dc d3 d6\ -84 02 2a 7f 31 c8 65 a6 64 e3 16 97 8b 75 9f ad -Test: Verify -Comment: RSASSA-PSS Signature Example 1.6 -Message: \ -10 aa e9 a0 ab 0b 59 5d 08 41 20 7b 70 0d 48 d7\ -5f ae dd e3 b7 75 cd 6b 4c c8 8a e0 6e 46 94 ec\ -74 ba 18 f8 52 0d 4f 5e a6 9c bb e7 cc 2b eb a4\ -3e fd c1 02 15 ac 4e b3 2d c3 02 a1 f5 3d c6 c4\ -35 22 67 e7 93 6c fe bf 7c 8d 67 03 57 84 a3 90\ -9f a8 59 c7 b7 b5 9b 8e 39 c5 c2 34 9f 18 86 b7\ -05 a3 02 67 d4 02 f7 48 6a b4 f5 8c ad 5d 69 ad\ -b1 7a b8 cd 0c e1 ca f5 02 5a f4 ae 24 b1 fb 87\ -94 c6 07 0c c0 9a 51 e2 f9 91 13 11 e3 87 7d 00\ -44 c7 1c 57 a9 93 39 50 08 80 6b 72 3a c3 83 73\ -d3 95 48 18 18 52 8c 1e 70 53 73 92 82 05 35 29\ -51 0e 93 5c d0 fa 77 b8 fa 53 cc 2d 47 4b d4 fb\ -3c c5 c6 72 d6 ff dc 90 a0 0f 98 48 71 2c 4b cf\ -e4 6c 60 57 36 59 b1 1e 64 57 e8 61 f0 f6 04 b6\ -13 8d 14 4f 8c e4 e2 da 73 -Salt: \ -a8 ab 69 dd 80 1f 00 74 c2 a1 fc 60 64 98 36 c6\ -16 d9 96 81 -Signature: \ -2a 34 f6 12 5e 1f 6b 0b f9 71 e8 4f bd 41 c6 32\ -be 8f 2c 2a ce 7d e8 b6 92 6e 31 ff 93 e9 af 98\ -7f bc 06 e5 1e 9b e1 4f 51 98 f9 1f 3f 95 3b d6\ -7d a6 0a 9d f5 97 64 c3 dc 0f e0 8e 1c be f0 b7\ -5f 86 8d 10 ad 3f ba 74 9f ef 59 fb 6d ac 46 a0\ -d6 e5 04 36 93 31 58 6f 58 e4 62 8f 39 aa 27 89\ -82 54 3b c0 ee b5 37 dc 61 95 80 19 b3 94 fb 27\ -3f 21 58 58 a0 a0 1a c4 d6 50 b9 55 c6 7f 4c 58 -Test: Verify -Comment: Example 2: A 1025-bit RSA Key Pair -Modulus: \ -01 d4 0c 1b cf 97 a6 8a e7 cd bd 8a 7b f3 e3 4f\ -a1 9d cc a4 ef 75 a4 74 54 37 5f 94 51 4d 88 fe\ -d0 06 fb 82 9f 84 19 ff 87 d6 31 5d a6 8a 1f f3\ -a0 93 8e 9a bb 34 64 01 1c 30 3a d9 91 99 cf 0c\ -7c 7a 8b 47 7d ce 82 9e 88 44 f6 25 b1 15 e5 e9\ -c4 a5 9c f8 f8 11 3b 68 34 33 6a 2f d2 68 9b 47\ -2c bb 5e 5c ab e6 74 35 0c 59 b6 c1 7e 17 68 74\ -fb 42 f8 fc 3d 17 6a 01 7e dc 61 fd 32 6c 4b 33\ -c9 -PublicExponent: \ -01 00 01 -PrivateExponent: \ -02 7d 14 7e 46 73 05 73 77 fd 1e a2 01 56 57 72\ -17 6a 7d c3 83 58 d3 76 04 56 85 a2 e7 87 c2 3c\ -15 57 6b c1 6b 9f 44 44 02 d6 bf c5 d9 8a 3e 88\ -ea 13 ef 67 c3 53 ec a0 c0 dd ba 92 55 bd 7b 8b\ -b5 0a 64 4a fd fd 1d d5 16 95 b2 52 d2 2e 73 18\ -d1 b6 68 7a 1c 10 ff 75 54 5f 3d b0 fe 60 2d 5f\ -2b 7f 29 4e 36 01 ea b7 b9 d1 ce cd 76 7f 64 69\ -2e 3e 53 6c a2 84 6c b0 c2 dd 48 6a 39 fa 75 b1 -Prime1: \ -01 66 01 e9 26 a0 f8 c9 e2 6e ca b7 69 ea 65 a5\ -e7 c5 2c c9 e0 80 ef 51 94 57 c6 44 da 68 91 c5\ -a1 04 d3 ea 79 55 92 9a 22 e7 c6 8a 7a f9 fc ad\ -77 7c 3c cc 2b 9e 3d 36 50 bc e4 04 39 9b 7e 59\ -d1 -Prime2: \ -01 4e af a1 d4 d0 18 4d a7 e3 1f 87 7d 12 81 dd\ -da 62 56 64 86 9e 83 79 e6 7a d3 b7 5e ae 74 a5\ -80 e9 82 7a bd 6e b7 a0 02 cb 54 11 f5 26 67 97\ -76 8f b8 e9 5a e4 0e 3e 8a 01 f3 5f f8 9e 56 c0\ -79 -ModPrime1PrivateExponent: \ -e2 47 cc e5 04 93 9b 8f 0a 36 09 0d e2 00 93 87\ -55 e2 44 4b 29 53 9a 7d a7 a9 02 f6 05 68 35 c0\ -db 7b 52 55 94 97 cf e2 c6 1a 80 86 d0 21 3c 47\ -2c 78 85 18 00 b1 71 f6 40 1d e2 e9 c2 75 6f 31 -ModPrime2PrivateExponent: \ -b1 2f ba 75 78 55 e5 86 e4 6f 64 c3 8a 70 c6 8b\ -3f 54 8d 93 d7 87 b3 99 99 9d 4c 8f 0b bd 25 81\ -c2 1e 19 ed 00 18 a6 d5 d3 df 86 42 4b 3a bc ad\ -40 19 9d 31 49 5b 61 30 9f 27 c1 bf 55 d4 87 c1 -MultiplicativeInverseOfPrime2ModPrime1: \ -56 4b 1e 1f a0 03 bd a9 1e 89 09 04 25 aa c0 5b\ -91 da 9e e2 50 61 e7 62 8d 5f 51 30 4a 84 99 2f\ -dc 33 76 2b d3 78 a5 9f 03 0a 33 4d 53 2b d0 da\ -e8 f2 98 ea 9e d8 44 63 6a d5 fb 8c bd c0 3c ad -Test: KeyPairValidAndConsistent -Comment: RSASSA-PSS Signature Example 2.1 -Message: \ -da ba 03 20 66 26 3f ae db 65 98 48 11 52 78 a5\ -2c 44 fa a3 a7 6f 37 51 5e d3 36 32 10 72 c4 0a\ -9d 9b 53 bc 05 01 40 78 ad f5 20 87 51 46 aa e7\ -0f f0 60 22 6d cb 7b 1f 1f c2 7e 93 60 -Salt: \ -57 bf 16 0b cb 02 bb 1d c7 28 0c f0 45 85 30 b7\ -d2 83 2f f7 -Signature: \ -01 4c 5b a5 33 83 28 cc c6 e7 a9 0b f1 c0 ab 3f\ -d6 06 ff 47 96 d3 c1 2e 4b 63 9e d9 13 6a 5f ec\ -6c 16 d8 88 4b dd 99 cf dc 52 14 56 b0 74 2b 73\ -68 68 cf 90 de 09 9a db 8d 5f fd 1d ef f3 9b a4\ -00 7a b7 46 ce fd b2 2d 7d f0 e2 25 f5 46 27 dc\ -65 46 61 31 72 1b 90 af 44 53 63 a8 35 8b 9f 60\ -76 42 f7 8f ab 0a b0 f4 3b 71 68 d6 4b ae 70 d8\ -82 78 48 d8 ef 1e 42 1c 57 54 dd f4 2c 25 89 b5\ -b3 -Test: Verify -Comment: RSASSA-PSS Signature Example 2.2 -Message: \ -e4 f8 60 1a 8a 6d a1 be 34 44 7c 09 59 c0 58 57\ -0c 36 68 cf d5 1d d5 f9 cc d6 ad 44 11 fe 82 13\ -48 6d 78 a6 c4 9f 93 ef c2 ca 22 88 ce bc 2b 9b\ -60 bd 04 b1 e2 20 d8 6e 3d 48 48 d7 09 d0 32 d1\ -e8 c6 a0 70 c6 af 9a 49 9f cf 95 35 4b 14 ba 61\ -27 c7 39 de 1b b0 fd 16 43 1e 46 93 8a ec 0c f8\ -ad 9e b7 2e 83 2a 70 35 de 9b 78 07 bd c0 ed 8b\ -68 eb 0f 5a c2 21 6b e4 0c e9 20 c0 db 0e dd d3\ -86 0e d7 88 ef ac ca ca 50 2d 8f 2b d6 d1 a7 c1\ -f4 1f f4 6f 16 81 c8 f1 f8 18 e9 c4 f6 d9 1a 0c\ -78 03 cc c6 3d 76 a6 54 4d 84 3e 08 4e 36 3b 8a\ -cc 55 aa 53 17 33 ed b5 de e5 b5 19 6e 9f 03 e8\ -b7 31 b3 77 64 28 d9 e4 57 fe 3f bc b3 db 72 74\ -44 2d 78 58 90 e9 cb 08 54 b6 44 4d ac e7 91 d7\ -27 3d e1 88 97 19 33 8a 77 fe -Salt: \ -7f 6d d3 59 e6 04 e6 08 70 e8 98 e4 7b 19 bf 2e\ -5a 7b 2a 90 -Signature: \ -01 09 91 65 6c ca 18 2b 7f 29 d2 db c0 07 e7 ae\ -0f ec 15 8e b6 75 9c b9 c4 5c 5f f8 7c 76 35 dd\ -46 d1 50 88 2f 4d e1 e9 ae 65 e7 f7 d9 01 8f 68\ -36 95 4a 47 c0 a8 1a 8a 6b 6f 83 f2 94 4d 60 81\ -b1 aa 7c 75 9b 25 4b 2c 34 b6 91 da 67 cc 02 26\ -e2 0b 2f 18 b4 22 12 76 1d cd 4b 90 8a 62 b3 71\ -b5 91 8c 57 42 af 4b 53 7e 29 69 17 67 4f b9 14\ -19 47 61 62 1c c1 9a 41 f6 fb 95 3f bc bb 64 9d\ -ea -Test: Verify -Comment: RSASSA-PSS Signature Example 2.3 -Message: \ -52 a1 d9 6c 8a c3 9e 41 e4 55 80 98 01 b9 27 a5\ -b4 45 c1 0d 90 2a 0d cd 38 50 d2 2a 66 d2 bb 07\ -03 e6 7d 58 67 11 45 95 aa bf 5a 7a eb 5a 8f 87\ -03 4b bb 30 e1 3c fd 48 17 a9 be 76 23 00 23 60\ -6d 02 86 a3 fa f8 a4 d2 2b 72 8e c5 18 07 9f 9e\ -64 52 6e 3a 0c c7 94 1a a3 38 c4 37 99 7c 68 0c\ -ca c6 7c 66 bf a1 -Salt: \ -fc a8 62 06 8b ce 22 46 72 4b 70 8a 05 19 da 17\ -e6 48 68 8c -Signature: \ -00 7f 00 30 01 8f 53 cd c7 1f 23 d0 36 59 fd e5\ -4d 42 41 f7 58 a7 50 b4 2f 18 5f 87 57 85 20 c3\ -07 42 af d8 43 59 b6 e6 e8 d3 ed 95 9d c6 fe 48\ -6b ed c8 e2 cf 00 1f 63 a7 ab e1 62 56 a1 b8 4d\ -f0 d2 49 fc 05 d3 19 4c e5 f0 91 27 42 db bf 80\ -dd 17 4f 6c 51 f6 ba d7 f1 6c f3 36 4e ba 09 5a\ -06 26 7d c3 79 38 03 ac 75 26 ae be 0a 47 5d 38\ -b8 c2 24 7a b5 1c 48 98 df 70 47 dc 6a df 52 c6\ -c4 -Test: Verify -Comment: RSASSA-PSS Signature Example 2.4 -Message: \ -a7 18 2c 83 ac 18 be 65 70 a1 06 aa 9d 5c 4e 3d\ -bb d4 af ae b0 c6 0c 4a 23 e1 96 9d 79 ff -Salt: \ -80 70 ef 2d e9 45 c0 23 87 68 4b a0 d3 30 96 73\ -22 35 d4 40 -Signature: \ -00 9c d2 f4 ed be 23 e1 23 46 ae 8c 76 dd 9a d3\ -23 0a 62 07 61 41 f1 6c 15 2b a1 85 13 a4 8e f6\ -f0 10 e0 e3 7f d3 df 10 a1 ec 62 9a 0c b5 a3 b5\ -d2 89 30 07 29 8c 30 93 6a 95 90 3b 6b a8 55 55\ -d9 ec 36 73 a0 61 08 fd 62 a2 fd a5 6d 1c e2 e8\ -5c 4d b6 b2 4a 81 ca 3b 49 6c 36 d4 fd 06 eb 7c\ -91 66 d8 e9 48 77 c4 2b ea 62 2b 3b fe 92 51 fd\ -c2 1d 8d 53 71 ba da d7 8a 48 82 14 79 63 35 b4\ -0b -Test: Verify -Comment: RSASSA-PSS Signature Example 2.5 -Message: \ -86 a8 3d 4a 72 ee 93 2a 4f 56 30 af 65 79 a3 86\ -b7 8f e8 89 99 e0 ab d2 d4 90 34 a4 bf c8 54 dd\ -94 f1 09 4e 2e 8c d7 a1 79 d1 95 88 e4 ae fc 1b\ -1b d2 5e 95 e3 dd 46 1f -Salt: \ -17 63 9a 4e 88 d7 22 c4 fc a2 4d 07 9a 8b 29 c3\ -24 33 b0 c9 -Signature: \ -00 ec 43 08 24 93 1e bd 3b aa 43 03 4d ae 98 ba\ -64 6b 8c 36 01 3d 16 71 c3 cf 1c f8 26 0c 37 4b\ -19 f8 e1 cc 8d 96 50 12 40 5e 7e 9b f7 37 86 12\ -df cc 85 fc e1 2c da 11 f9 50 bd 0b a8 87 67 40\ -43 6c 1d 25 95 a6 4a 1b 32 ef cf b7 4a 21 c8 73\ -b3 cc 33 aa f4 e3 dc 39 53 de 67 f0 67 4c 04 53\ -b4 fd 9f 60 44 06 d4 41 b8 16 09 8c b1 06 fe 34\ -72 bc 25 1f 81 5f 59 db 2e 43 78 a3 ad dc 18 1e\ -cf -Test: Verify -Comment: RSASSA-PSS Signature Example 2.6 -Message: \ -04 9f 91 54 d8 71 ac 4a 7c 7a b4 53 25 ba 75 45\ -a1 ed 08 f7 05 25 b2 66 7c f1 -Salt: \ -37 81 0d ef 10 55 ed 92 2b 06 3d f7 98 de 5d 0a\ -ab f8 86 ee -Signature: \ -00 47 5b 16 48 f8 14 a8 dc 0a bd c3 7b 55 27 f5\ -43 b6 66 bb 6e 39 d3 0e 5b 49 d3 b8 76 dc cc 58\ -ea c1 4e 32 a2 d5 5c 26 16 01 44 56 ad 2f 24 6f\ -c8 e3 d5 60 da 3d df 37 9a 1c 0b d2 00 f1 02 21\ -df 07 8c 21 9a 15 1b c8 d4 ec 9d 2f c2 56 44 67\ -81 10 14 ef 15 d8 ea 01 c2 eb bf f8 c2 c8 ef ab\ -38 09 6e 55 fc be 32 85 c7 aa 55 88 51 25 4f af\ -fa 92 c1 c7 2b 78 75 86 63 ef 45 82 84 31 39 d7\ -a6 -Test: Verify -Comment: Example 3: A 1026-bit RSA Key Pair -Modulus: \ -02 f2 46 ef 45 1e d3 ee bb 9a 31 02 00 cc 25 85\ -9c 04 8e 4b e7 98 30 29 91 11 2e b6 8c e6 db 67\ -4e 28 0d a2 1f ed ed 1a e7 48 80 ca 52 2b 18 db\ -24 93 85 01 28 27 c5 15 f0 e4 66 a1 ff a6 91 d9\ -81 70 57 4e 9d 0e ad b0 87 58 6c a4 89 33 da 3c\ -c9 53 d9 5b d0 ed 50 de 10 dd cb 67 36 10 7d 6c\ -83 1c 7f 66 3e 83 3c a4 c0 97 e7 00 ce 0f b9 45\ -f8 8f b8 5f e8 e5 a7 73 17 25 65 b9 14 a4 71 a4\ -43 -PublicExponent: \ -01 00 01 -PrivateExponent: \ -65 14 51 73 3b 56 de 5a c0 a6 89 a4 ae b6 e6 89\ -4a 69 01 4e 07 6c 88 dd 7a 66 7e ab 32 32 bb cc\ -d2 fc 44 ba 2f a9 c3 1d b4 6f 21 ed d1 fd b2 3c\ -5c 12 8a 5d a5 ba b9 1e 7f 95 2b 67 75 9c 7c ff\ -70 54 15 ac 9f a0 90 7c 7c a6 17 8f 66 8f b9 48\ -d8 69 da 4c c3 b7 35 6f 40 08 df d5 44 9d 32 ee\ -02 d9 a4 77 eb 69 fc 29 26 6e 5d 90 70 51 23 75\ -a5 0f bb cc 27 e2 38 ad 98 42 5f 6e bb f8 89 91 -Prime1: \ -01 bd 36 e1 8e ce 4b 0f db 2e 9c 9d 54 8b d1 a7\ -d6 e2 c2 1c 6f dc 35 07 4a 1d 05 b1 c6 c8 b3 d5\ -58 ea 26 39 c9 a9 a4 21 68 01 69 31 72 52 55 8b\ -d1 48 ad 21 5a ac 55 0e 2d cf 12 a8 2d 0e bf e8\ -53 -Prime2: \ -01 b1 b6 56 ad 86 d8 e1 9d 5d c8 62 92 b3 a1 92\ -fd f6 e0 dd 37 87 7b ad 14 82 2f a0 01 90 ca b2\ -65 f9 0d 3f 02 05 7b 6f 54 d6 ec b1 44 91 e5 ad\ -ea ce bc 48 bf 0e bd 2a 2a d2 6d 40 2e 54 f6 16\ -51 -ModPrime1PrivateExponent: \ -1f 27 79 fd 2e 3e 5e 6b ae 05 53 95 18 fb a0 cd\ -0e ad 1a a4 51 3a 7c ba 18 f1 cf 10 e3 f6 81 95\ -69 3d 27 8a 0f 0e e7 2f 89 f9 bc 76 0d 80 e2 f9\ -d0 26 1d 51 65 01 c6 ae 39 f1 4a 47 6c e2 cc f5 -ModPrime2PrivateExponent: \ -01 1a 0d 36 79 4b 04 a8 54 aa b4 b2 46 2d 43 9a\ -50 46 c9 1d 94 0b 2b c6 f7 5b 62 95 6f ef 35 a2\ -a6 e6 3c 53 09 81 7f 30 7b bf f9 d5 9e 7e 33 1b\ -d3 63 f6 d6 68 49 b1 83 46 ad ea 16 9f 0a e9 ae\ -c1 -MultiplicativeInverseOfPrime2ModPrime1: \ -0b 30 f0 ec f5 58 75 2f b3 a6 ce 4b a2 b8 c6 75\ -f6 59 eb a6 c3 76 58 5a 1b 39 71 2d 03 8a e3 d2\ -b4 6f cb 41 8a e1 5d 09 05 da 64 40 e1 51 3a 30\ -b9 b7 d6 66 8f bc 5e 88 e5 ab 7a 17 5e 73 ba 35 -Test: KeyPairValidAndConsistent -Comment: RSASSA-PSS Signature Example 3.1 -Message: \ -59 4b 37 33 3b bb 2c 84 52 4a 87 c1 a0 1f 75 fc\ -ec 0e 32 56 f1 08 e3 8d ca 36 d7 0d 00 57 -Salt: \ -f3 1a d6 c8 cf 89 df 78 ed 77 fe ac bc c2 f8 b0\ -a8 e4 cf aa -Signature: \ -00 88 b1 35 fb 17 94 b6 b9 6c 4a 3e 67 81 97 f8\ -ca c5 2b 64 b2 fe 90 7d 6f 27 de 76 11 24 96 4a\ -99 a0 1a 88 27 40 ec fa ed 6c 01 a4 74 64 bb 05\ -18 23 13 c0 13 38 a8 cd 09 72 14 cd 68 ca 10 3b\ -d5 7d 3b c9 e8 16 21 3e 61 d7 84 f1 82 46 7a bf\ -8a 01 cf 25 3e 99 a1 56 ea a8 e3 e1 f9 0e 3c 6e\ -4e 3a a2 d8 3e d0 34 5b 89 fa fc 9c 26 07 7c 14\ -b6 ac 51 45 4f a2 6e 44 6e 3a 2f 15 3b 2b 16 79\ -7f -Test: Verify -Comment: RSASSA-PSS Signature Example 3.2 -Message: \ -8b 76 95 28 88 4a 0d 1f fd 09 0c f1 02 99 3e 79\ -6d ad cf bd dd 38 e4 4f f6 32 4c a4 51 -Salt: \ -fc f9 f0 e1 f1 99 a3 d1 d0 da 68 1c 5b 86 06 fc\ -64 29 39 f7 -Signature: \ -02 a5 f0 a8 58 a0 86 4a 4f 65 01 7a 7d 69 45 4f\ -3f 97 3a 29 99 83 9b 7b bc 48 bf 78 64 11 69 17\ -95 56 f5 95 fa 41 f6 ff 18 e2 86 c2 78 30 79 bc\ -09 10 ee 9c c3 4f 49 ba 68 11 24 f9 23 df a8 8f\ -42 61 41 a3 68 a5 f5 a9 30 c6 28 c2 c3 c2 00 e1\ -8a 76 44 72 1a 0c be c6 dd 3f 62 79 bd e3 e8 f2\ -be 5e 2d 4e e5 6f 97 e7 ce af 33 05 4b e7 04 2b\ -d9 1a 63 bb 09 f8 97 bd 41 e8 11 97 de e9 9b 11\ -af -Test: Verify -Comment: RSASSA-PSS Signature Example 3.3 -Message: \ -1a bd ba 48 9c 5a da 2f 99 5e d1 6f 19 d5 a9 4d\ -9e 6e c3 4a 8d 84 f8 45 57 d2 6e 5e f9 b0 2b 22\ -88 7e 3f 9a 4b 69 0a d1 14 92 09 c2 0c 61 43 1f\ -0c 01 7c 36 c2 65 7b 35 d7 b0 7d 3f 5a d8 70 85\ -07 a9 c1 b8 31 df 83 5a 56 f8 31 07 18 14 ea 5d\ -3d 8d 8f 6a de 40 cb a3 8b 42 db 7a 2d 3d 7a 29\ -c8 f0 a7 9a 78 38 cf 58 a9 75 7f a2 fe 4c 40 df\ -9b aa 19 3b fc 6f 92 b1 23 ad 57 b0 7a ce 3e 6a\ -c0 68 c9 f1 06 af d9 ee b0 3b 4f 37 c2 5d bf bc\ -fb 30 71 f6 f9 77 17 66 d0 72 f3 bb 07 0a f6 60\ -55 32 97 3a e2 50 51 -Salt: \ -98 6e 7c 43 db b6 71 bd 41 b9 a7 f4 b6 af c8 0e\ -80 5f 24 23 -Signature: \ -02 44 bc d1 c8 c1 69 55 73 6c 80 3b e4 01 27 2e\ -18 cb 99 08 11 b1 4f 72 db 96 41 24 d5 fa 76 06\ -49 cb b5 7a fb 87 55 db b6 2b f5 1f 46 6c f2 3a\ -0a 16 07 57 6e 98 3d 77 8f ce ff a9 2d f7 54 8a\ -ea 8e a4 ec ad 2c 29 dd 9f 95 bc 07 fe 91 ec f8\ -be e2 55 bf e8 76 2f d7 69 0a a9 bf a4 fa 08 49\ -ef 72 8c 2c 42 c4 53 23 64 52 2d f2 ab 7f 9f 8a\ -03 b6 3f 7a 49 91 75 82 86 68 f5 ef 5a 29 e3 80\ -2c -Test: Verify -Comment: RSASSA-PSS Signature Example 3.4 -Message: \ -8f b4 31 f5 ee 79 2b 6c 2a c7 db 53 cc 42 86 55\ -ae b3 2d 03 f4 e8 89 c5 c2 5d e6 83 c4 61 b5 3a\ -cf 89 f9 f8 d3 aa bd f6 b9 f0 c2 a1 de 12 e1 5b\ -49 ed b3 91 9a 65 2f e9 49 1c 25 a7 fc e1 f7 22\ -c2 54 36 08 b6 9d c3 75 ec -Salt: \ -f8 31 2d 9c 8e ea 13 ec 0a 4c 7b 98 12 0c 87 50\ -90 87 c4 78 -Signature: \ -01 96 f1 2a 00 5b 98 12 9c 8d f1 3c 4c b1 6f 8a\ -a8 87 d3 c4 0d 96 df 3a 88 e7 53 2e f3 9c d9 92\ -f2 73 ab c3 70 bc 1b e6 f0 97 cf eb bf 01 18 fd\ -9e f4 b9 27 15 5f 3d f2 2b 90 4d 90 70 2d 1f 7b\ -a7 a5 2b ed 8b 89 42 f4 12 cd 7b d6 76 c9 d1 8e\ -17 03 91 dc d3 45 c0 6a 73 09 64 b3 f3 0b cc e0\ -bb 20 ba 10 6f 9a b0 ee b3 9c f8 a6 60 7f 75 c0\ -34 7f 0a f7 9f 16 af a0 81 d2 c9 2d 1e e6 f8 36\ -b8 -Test: Verify -Comment: RSASSA-PSS Signature Example 3.5 -Message: \ -fe f4 16 1d fa af 9c 52 95 05 1d fc 1f f3 81 0c\ -8c 9e c2 e8 66 f7 07 54 22 c8 ec 42 16 a9 c4 ff\ -49 42 7d 48 3c ae 10 c8 53 4a 41 b2 fd 15 fe e0\ -69 60 ec 6f b3 f7 a7 e9 4a 2f 8a 2e 3e 43 dc 4a\ -40 57 6c 30 97 ac 95 3b 1d e8 6f 0b 4e d3 6d 64\ -4f 23 ae 14 42 55 29 62 24 64 ca 0c bf 0b 17 41\ -34 72 38 15 7f ab 59 e4 de 55 24 09 6d 62 ba ec\ -63 ac 64 -Salt: \ -50 32 7e fe c6 29 2f 98 01 9f c6 7a 2a 66 38 56\ -3e 9b 6e 2d -Signature: \ -02 1e ca 3a b4 89 22 64 ec 22 41 1a 75 2d 92 22\ -10 76 d4 e0 1c 0e 6f 0d de 9a fd 26 ba 5a cf 6d\ -73 9e f9 87 54 5d 16 68 3e 56 74 c9 e7 0f 1d e6\ -49 d7 e6 1d 48 d0 ca eb 4f b4 d8 b2 4f ba 84 a6\ -e3 10 8f ee 7d 07 05 97 32 66 ac 52 4b 4a d2 80\ -f7 ae 17 dc 59 d9 6d 33 51 58 6b 5a 3b db 89 5d\ -1e 1f 78 20 ac 61 35 d8 75 34 80 99 83 82 ba 32\ -b7 34 95 59 60 8c 38 74 52 90 a8 5e f4 e9 f9 bd\ -83 -Test: Verify -Comment: RSASSA-PSS Signature Example 3.6 -Message: \ -ef d2 37 bb 09 8a 44 3a ee b2 bf 6c 3f 8c 81 b8\ -c0 1b 7f cb 3f eb -Salt: \ -b0 de 3f c2 5b 65 f5 af 96 b1 d5 cc 3b 27 d0 c6\ -05 30 87 b3 -Signature: \ -01 2f af ec 86 2f 56 e9 e9 2f 60 ab 0c 77 82 4f\ -42 99 a0 ca 73 4e d2 6e 06 44 d5 d2 22 c7 f0 bd\ -e0 39 64 f8 e7 0a 5c b6 5e d4 4e 44 d5 6a e0 ed\ -f1 ff 86 ca 03 2c c5 dd 44 04 db b7 6a b8 54 58\ -6c 44 ee d8 33 6d 08 d4 57 ce 6c 03 69 3b 45 c0\ -f1 ef ef 93 62 4b 95 b8 ec 16 9c 61 6d 20 e5 53\ -8e bc 0b 67 37 a6 f8 2b 4b c0 57 09 24 fc 6b 35\ -75 9a 33 48 42 62 79 f8 b3 d7 74 4e 2d 22 24 26\ -ce -Test: Verify -Comment: Example 4: A 1027-bit RSA Key Pair -Modulus: \ -05 4a db 78 86 44 7e fe 6f 57 e0 36 8f 06 cf 52\ -b0 a3 37 07 60 d1 61 ce f1 26 b9 1b e7 f8 9c 42\ -1b 62 a6 ec 1d a3 c3 11 d7 5e d5 0e 0a b5 ff f3\ -fd 33 8a cc 3a a8 a4 e7 7e e2 63 69 ac b8 1b a9\ -00 fa 83 f5 30 0c f9 bb 6c 53 ad 1d c8 a1 78 b8\ -15 db 42 35 a9 a9 da 0c 06 de 4e 61 5e a1 27 7c\ -e5 59 e9 c1 08 de 58 c1 4a 81 aa 77 f5 a6 f8 d1\ -33 54 94 49 88 48 c8 b9 59 40 74 0b e7 bf 7c 37\ -05 -PublicExponent: \ -01 00 01 -PrivateExponent: \ -fa 04 1f 8c d9 69 7c ee d3 8e c8 ca a2 75 52 3b\ -4d d7 2b 09 a3 01 d3 54 1d 72 f5 d3 1c 05 cb ce\ -2d 69 83 b3 61 83 af 10 69 0b d4 6c 46 13 1e 35\ -78 94 31 a5 56 77 1d d0 04 9b 57 46 1b f0 60 c1\ -f6 84 72 e8 a6 7c 25 f3 57 e5 b6 b4 73 8f a5 41\ -a7 30 34 6b 4a 07 64 9a 2d fa 80 6a 69 c9 75 b6\ -ab a6 46 78 ac c7 f5 91 3e 89 c6 22 f2 d8 ab b1\ -e3 e3 25 54 e3 9d f9 4b a6 0c 00 2e 38 7d 90 11 -Prime1: \ -02 92 32 33 6d 28 38 94 5d ba 9d d7 72 3f 4e 62\ -4a 05 f7 37 5b 92 7a 87 ab e6 a8 93 a1 65 8f d4\ -9f 47 f6 c7 b0 fa 59 6c 65 fa 68 a2 3f 0a b4 32\ -96 2d 18 d4 34 3b d6 fd 67 1a 5e a8 d1 48 41 39\ -95 -Prime2: \ -02 0e f5 ef e7 c5 39 4a ed 22 72 f7 e8 1a 74 f4\ -c0 2d 14 58 94 cb 1b 3c ab 23 a9 a0 71 0a 2a fc\ -7e 33 29 ac bb 74 3d 01 f6 80 c4 d0 2a fb 4c 8f\ -de 7e 20 93 08 11 bb 2b 99 57 88 b5 e8 72 c2 0b\ -b1 -ModPrime1PrivateExponent: \ -02 6e 7e 28 01 0e cf 24 12 d9 52 3a d7 04 64 7f\ -b4 fe 9b 66 b1 a6 81 58 1b 0e 15 55 3a 89 b1 54\ -28 28 89 8f 27 24 3e ba b4 5f f5 e1 ac b9 d4 df\ -1b 05 1f bc 62 82 4d bc 6f 6c 93 26 1a 78 b9 a7\ -59 -ModPrime2PrivateExponent: \ -01 2d dc c8 6e f6 55 99 8c 39 dd ae 11 71 86 69\ -e5 e4 6c f1 49 5b 07 e1 3b 10 14 cd 69 b3 af 68\ -30 4a d2 a6 b6 43 21 e7 8b f3 bb ca 9b b4 94 e9\ -1d 45 17 17 e2 d9 75 64 c6 54 94 65 d0 20 5c f4\ -21 -MultiplicativeInverseOfPrime2ModPrime1: \ -01 06 00 c4 c2 18 47 45 9f e5 76 70 3e 2e be ca\ -e8 a5 09 4e e6 3f 53 6b f4 ac 68 d3 c1 3e 5e 4f\ -12 ac 5c c1 0a b6 a2 d0 5a 19 92 14 d1 82 47 47\ -d5 51 90 96 36 b7 74 c2 2c ac 0b 83 75 99 ab cc\ -75 -Test: KeyPairValidAndConsistent -Comment: RSASSA-PSS Signature Example 4.1 -Message: \ -9f b0 3b 82 7c 82 17 d9 -Salt: \ -ed 7c 98 c9 5f 30 97 4f be 4f bd dc f0 f2 8d 60\ -21 c0 e9 1d -Signature: \ -03 23 d5 b7 bf 20 ba 45 39 28 9a e4 52 ae 42 97\ -08 0f ef f4 51 84 23 ff 48 11 a8 17 83 7e 7d 82\ -f1 83 6c df ab 54 51 4f f0 88 7b dd ee bf 40 bf\ -99 b0 47 ab c3 ec fa 6a 37 a3 ef 00 f4 a0 c4 a8\ -8a ae 09 04 b7 45 c8 46 c4 10 7e 87 97 72 3e 8a\ -c8 10 d9 e3 d9 5d fa 30 ff 49 66 f4 d7 5d 13 76\ -8d 20 85 7f 2b 14 06 f2 64 cf e7 5e 27 d7 65 2f\ -4b 5e d3 57 5f 28 a7 02 f8 c4 ed 9c f9 b2 d4 49\ -48 -Test: Verify -Comment: RSASSA-PSS Signature Example 4.2 -Message: \ -0c a2 ad 77 79 7e ce 86 de 5b f7 68 75 0d db 5e\ -d6 a3 11 6a d9 9b bd 17 ed f7 f7 82 f0 db 1c d0\ -5b 0f 67 74 68 c5 ea 42 0d c1 16 b1 0e 80 d1 10\ -de 2b 04 61 ea 14 a3 8b e6 86 20 39 2e 7e 89 3c\ -b4 ea 93 93 fb 88 6c 20 ff 79 06 42 30 5b f3 02\ -00 38 92 e5 4d f9 f6 67 50 9d c5 39 20 df 58 3f\ -50 a3 dd 61 ab b6 fa b7 5d 60 03 77 e3 83 e6 ac\ -a6 71 0e ee a2 71 56 e0 67 52 c9 4c e2 5a e9 9f\ -cb f8 59 2d be 2d 7e 27 45 3c b4 4d e0 71 00 eb\ -b1 a2 a1 98 11 a4 78 ad be ab 27 0f 94 e8 fe 36\ -9d 90 b3 ca 61 2f 9f -Salt: \ -22 d7 1d 54 36 3a 42 17 aa 55 11 3f 05 9b 33 84\ -e3 e5 7e 44 -Signature: \ -04 9d 01 85 84 5a 26 4d 28 fe b1 e6 9e da ec 09\ -06 09 e8 e4 6d 93 ab b3 83 71 ce 51 f4 aa 65 a5\ -99 bd aa a8 1d 24 fb a6 6a 08 a1 16 cb 64 4f 3f\ -1e 65 3d 95 c8 9d b8 bb d5 da ac 27 09 c8 98 40\ -00 17 84 10 a7 c6 aa 86 67 dd c3 8c 74 1f 71 0e\ -c8 66 5a a9 05 2b e9 29 d4 e3 b1 67 82 c1 66 21\ -14 c5 41 4b b0 35 34 55 c3 92 fc 28 f3 db 59 05\ -4b 5f 36 5c 49 e1 d1 56 f8 76 ee 10 cb 4f d7 05\ -98 -Test: Verify -Comment: RSASSA-PSS Signature Example 4.3 -Message: \ -28 80 62 af c0 8f cd b7 c5 f8 65 0b 29 83 73 00\ -46 1d d5 67 6c 17 a2 0a 3c 8f b5 14 89 49 e3 f7\ -3d 66 b3 ae 82 c7 24 0e 27 c5 b3 ec 43 28 ee 7d\ -6d df 6a 6a 0c 9b 5b 15 bc da 19 6a 9d 0c 76 b1\ -19 d5 34 d8 5a bd 12 39 62 d5 83 b7 6c e9 d1 80\ -bc e1 ca -Salt: \ -4a f8 70 fb c6 51 60 12 ca 91 6c 70 ba 86 2a c7\ -e8 24 36 17 -Signature: \ -03 fb c4 10 a2 ce d5 95 00 fb 99 f9 e2 af 27 81\ -ad a7 4e 13 14 56 24 60 27 82 e2 99 48 13 ee fc\ -a0 51 9e cd 25 3b 85 5f b6 26 a9 0d 77 1e ae 02\ -8b 0c 47 a1 99 cb d9 f8 e3 26 97 34 af 41 63 59\ -90 90 71 3a 3f a9 10 fa 09 60 65 27 21 43 2b 97\ -10 36 a7 18 1a 2b c0 ca b4 3b 0b 59 8b c6 21 74\ -61 d7 db 30 5f f7 e9 54 c5 b5 bb 23 1c 39 e7 91\ -af 6b cf a7 6b 14 7b 08 13 21 f7 26 41 48 2a 2a\ -ad -Test: Verify -Comment: RSASSA-PSS Signature Example 4.4 -Message: \ -6f 4f 9a b9 50 11 99 ce f5 5c 6c f4 08 fe 7b 36\ -c5 57 c4 9d 42 0a 47 63 d2 46 3c 8a d4 4b 3c fc\ -5b e2 74 2c 0e 7d 9b 0f 66 08 f0 8c 7f 47 b6 93\ -ee -Salt: \ -40 d2 e1 80 fa e1 ea c4 39 c1 90 b5 6c 2c 0e 14\ -dd f9 a2 26 -Signature: \ -04 86 64 4b c6 6b f7 5d 28 33 5a 61 79 b1 08 51\ -f4 3f 09 bd ed 9f ac 1a f3 32 52 bb 99 53 ba 42\ -98 cd 64 66 b2 75 39 a7 0a da a3 f8 9b 3d b3 c7\ -4a b6 35 d1 22 f4 ee 7c e5 57 a6 1e 59 b8 2f fb\ -78 66 30 e5 f9 db 53 c7 7d 9a 0c 12 fa b5 95 8d\ -4c 2c e7 da a8 07 cd 89 ba 2c c7 fc d0 2f f4 70\ -ca 67 b2 29 fc ce 81 4c 85 2c 73 cc 93 be a3 5b\ -e6 84 59 ce 47 8e 9d 46 55 d1 21 c8 47 2f 37 1d\ -4f -Test: Verify -Comment: RSASSA-PSS Signature Example 4.5 -Message: \ -e1 7d 20 38 5d 50 19 55 82 3c 3f 66 62 54 c1 d3\ -dd 36 ad 51 68 b8 f1 8d 28 6f dc f6 7a 7d ad 94\ -09 70 85 fa b7 ed 86 fe 21 42 a2 87 71 71 79 97\ -ef 1a 7a 08 88 4e fc 39 35 6d 76 07 7a af 82 45\ -9a 7f ad 45 84 88 75 f2 81 9b 09 89 37 fe 92 3b\ -cc 9d c4 42 d7 2d 75 4d 81 20 25 09 0c 9b c0 3d\ -b3 08 0c 13 8d d6 3b 35 5d 0b 4b 85 d6 68 8a c1\ -9f 4d e1 50 84 a0 ba 4e 37 3b 93 ef 4a 55 50 96\ -69 19 15 dc 23 c0 0e 95 4c de b2 0a 47 cd 55 d1\ -6c 3d 86 81 d4 6e d7 f2 ed 5e a4 27 95 be 17 ba\ -ed 25 f0 f4 d1 13 b3 63 6a dd d5 85 f1 6a 8b 5a\ -ec 0c 8f a9 c5 f0 3c bf 3b 9b 73 -Salt: \ -24 97 dc 2b 46 15 df ae 5a 66 3d 49 ff d5 6b f7\ -ef c1 13 04 -Signature: \ -02 2a 80 04 53 53 90 4c b3 0c bb 54 2d 7d 49 90\ -42 1a 6e ec 16 a8 02 9a 84 22 ad fd 22 d6 af f8\ -c4 cc 02 94 af 11 0a 0c 06 7e c8 6a 7d 36 41 34\ -45 9b b1 ae 8f f8 36 d5 a8 a2 57 98 40 99 6b 32\ -0b 19 f1 3a 13 fa d3 78 d9 31 a6 56 25 da e2 73\ -9f 0c 53 67 0b 35 d9 d3 cb ac 08 e7 33 e4 ec 2b\ -83 af 4b 91 96 d6 3e 7c 4f f1 dd ea e2 a1 22 79\ -1a 12 5b fe a8 de b0 de 8c cf 1f 4f fa f6 e6 fb\ -0a -Test: Verify -Comment: RSASSA-PSS Signature Example 4.6 -Message: \ -af bc 19 d4 79 24 90 18 fd f4 e0 9f 61 87 26 44\ -04 95 de 11 dd ee e3 88 72 d7 75 fc ea 74 a2 38\ -96 b5 34 3c 9c 38 d4 6a f0 db a2 24 d0 47 58 0c\ -c6 0a 65 e9 39 1c f9 b5 9b 36 a8 60 59 8d 4e 82\ -16 72 2f 99 3b 91 cf ae 87 bc 25 5a f8 9a 6a 19\ -9b ca 4a 39 1e ad bc 3a 24 90 3c 0b d6 67 36 8f\ -6b e7 8e 3f ea bf b4 ff d4 63 12 27 63 74 0f fb\ -be fe ab 9a 25 56 4b c5 d1 c2 4c 93 e4 22 f7 50\ -73 e2 ad 72 bf 45 b1 0d f0 0b 52 a1 47 12 8e 73\ -fe e3 3f a3 f0 57 7d 77 f8 0f bc 2d f1 be d3 13\ -29 0c 12 77 7f 50 -Salt: \ -a3 34 db 6f ae bf 11 08 1a 04 f8 7c 2d 62 1c de\ -c7 93 0b 9b -Signature: \ -00 93 8d cb 6d 58 30 46 06 5f 69 c7 8d a7 a1 f1\ -75 70 66 a7 fa 75 12 5a 9d 29 29 f0 b7 9a 60 b6\ -27 b0 82 f1 1f 5b 19 6f 28 eb 9d aa 6f 21 c0 5e\ -51 40 f6 ae f1 73 7d 20 23 07 5c 05 ec f0 4a 02\ -8c 68 6a 2a b3 e7 d5 a0 66 4f 29 5c e1 29 95 e8\ -90 90 8b 6a d2 1f 08 39 eb 65 b7 03 93 a7 b5 af\ -d9 87 1d e0 ca a0 ce de c5 b8 19 62 67 56 20 9d\ -13 ab 1e 7b b9 54 6a 26 ff 37 e9 a5 1a f9 fd 56\ -2e -Test: Verify -Comment: Example 5: A 1028-bit RSA Key Pair -Modulus: \ -0d 10 f6 61 f2 99 40 f5 ed 39 aa 26 09 66 de b4\ -78 43 67 9d 2b 6f b2 5b 3d e3 70 f3 ac 7c 19 91\ -63 91 fd 25 fb 52 7e bf a6 a4 b4 df 45 a1 75 9d\ -99 6c 4b b4 eb d1 88 28 c4 4f c5 2d 01 91 87 17\ -40 52 5f 47 a4 b0 cc 8d a3 25 ed 8a a6 76 b0 d0\ -f6 26 e0 a7 7f 07 69 21 70 ac ac 80 82 f4 2f aa\ -7d c7 cd 12 3e 73 0e 31 a8 79 85 20 4c ab cb e6\ -67 0d 43 a2 dd 2b 2d de f5 e0 53 92 fc 21 3b c5\ -07 -PublicExponent: \ -01 00 01 -PrivateExponent: \ -03 ce 08 b1 04 ff f3 96 a9 79 bd 3e 4e 46 92 5b\ -63 19 dd b6 3a cb cf d8 19 f1 7d 16 b8 07 7b 3a\ -87 10 1f f3 4b 77 fe 48 b8 b2 05 a9 6e 91 51 ba\ -8e ce a6 4d 0c ce 7b 23 c3 e6 a6 b8 30 58 bc 49\ -da e8 16 ae 73 6d b5 a4 70 8e 2a d4 35 23 2b 56\ -7f 90 96 ce 59 ff 28 06 1e 79 ab 1c 02 d7 17 e6\ -b2 3c ea 6d b8 eb 51 92 fa 7c 1e ab 22 7d ba 74\ -62 1c 45 60 18 96 ee f1 37 92 c8 44 0b eb 15 aa\ -c1 -Prime1: \ -03 f2 f3 31 f4 14 2d 4f 24 b4 3a a1 02 79 a8 96\ -52 d4 e7 53 72 21 a1 a7 b2 a2 5d eb 55 1e 5d e9\ -ac 49 74 11 c2 27 a9 4e 45 f9 1c 2d 1c 13 cc 04\ -6c f4 ce 14 e3 2d 05 87 34 21 0d 44 a8 7e e1 b7\ -3f -Prime2: \ -03 4f 09 0d 73 b5 58 03 03 0c f0 36 1a 5d 80 81\ -bf b7 9f 85 15 23 fe ac 0a 21 24 d0 8d 40 13 ff\ -08 48 77 71 a8 70 d0 47 9d c0 68 6c 62 f7 71 8d\ -fe cf 02 4b 17 c9 26 76 78 05 91 71 33 9c c0 08\ -39 -ModPrime1PrivateExponent: \ -02 aa 66 3a db f5 1a b8 87 a0 18 cb 42 6e 78 bc\ -2f e1 82 dc b2 f7 bc b5 04 41 d1 7f df 0f 06 79\ -8b 50 71 c6 e2 f5 fe b4 d5 4a d8 18 23 11 c1 ef\ -62 d4 c4 9f 18 d1 f5 1f 54 b2 d2 cf fb a4 da 1b\ -e5 -ModPrime2PrivateExponent: \ -02 bb e7 06 07 8b 5c 0b 39 15 12 d4 11 db 1b 19\ -9b 5a 56 64 b8 40 42 ea d3 7f e9 94 ae 72 b9 53\ -2d fb fb 3e 9e 69 81 a0 fb b8 06 51 31 41 b7 c2\ -16 3f e5 6c 39 5e 4b fa ee 57 e3 83 3f 9b 91 8d\ -f9 -MultiplicativeInverseOfPrime2ModPrime1: \ -02 42 b6 cd 00 d3 0a 76 7a ee 9a 89 8e ad 45 3c\ -8e ae a6 3d 50 0b 7d 1e 00 71 3e da e5 1c e3 6b\ -23 b6 64 df 26 e6 3e 26 6e c8 f7 6e 6e 63 ed 1b\ -a4 1e b0 33 b1 20 f7 ea 52 12 ae 21 a9 8f bc 16 -Test: KeyPairValidAndConsistent -Comment: RSASSA-PSS Signature Example 5.1 -Message: \ -30 c7 d5 57 45 8b 43 6d ec fd c1 4d 06 cb 7b 96\ -b0 67 18 c4 8d 7d e5 74 82 a8 68 ae 7f 06 58 70\ -a6 21 65 06 d1 1b 77 93 23 df df 04 6c f5 77 51\ -29 13 4b 4d 56 89 e4 d9 c0 ce 1e 12 d7 d4 b0 6c\ -b5 fc 58 20 de cf a4 1b af 59 bf 25 7b 32 f0 25\ -b7 67 9b 44 5b 94 99 c9 25 55 14 58 85 99 2f 1b\ -76 f8 48 91 ee 4d 3b e0 f5 15 0f d5 90 1e 3a 4c\ -8e d4 3f d3 6b 61 d0 22 e6 5a d5 00 8d bf 33 29\ -3c 22 bf bf d0 73 21 f0 f1 d5 fa 9f df 00 14 c2\ -fc b0 35 8a ad 0e 35 4b 0d 29 -Salt: \ -08 1b 23 3b 43 56 77 50 bd 6e 78 f3 96 a8 8b 9f\ -6a 44 51 51 -Signature: \ -0b a3 73 f7 6e 09 21 b7 0a 8f bf e6 22 f0 bf 77\ -b2 8a 3d b9 8e 36 10 51 c3 d7 cb 92 ad 04 52 91\ -5a 4d e9 c0 17 22 f6 82 3e eb 6a df 7e 0c a8 29\ -0f 5d e3 e5 49 89 0a c2 a3 c5 95 0a b2 17 ba 58\ -59 08 94 95 2d e9 6f 8d f1 11 b2 57 52 15 da 6c\ -16 15 90 c7 45 be 61 24 76 ee 57 8e d3 84 ab 33\ -e3 ec e9 74 81 a2 52 f5 c7 9a 98 b5 53 2a e0 0c\ -dd 62 f2 ec c0 cd 1b ae fe 80 d8 0b 96 21 93 ec\ -1d -Test: Verify -Comment: RSASSA-PSS Signature Example 5.2 -Message: \ -e7 b3 2e 15 56 ea 1b 27 95 04 6a c6 97 39 d2 2a\ -c8 96 6b f1 1c 11 6f 61 4b 16 67 40 e9 6b 90 65\ -3e 57 50 94 5f cf 77 21 86 c0 37 90 a0 7f da 32\ -3e 1a 61 91 6b 06 ee 21 57 db 3d ff 80 d6 7d 5e\ -39 a5 3a e2 68 c8 f0 9e d9 9a 73 20 05 b0 bc 6a\ -04 af 4e 08 d5 7a 00 e7 20 1b 30 60 ef aa db 73\ -11 3b fc 08 7f d8 37 09 3a a2 52 35 b8 c1 49 f5\ -62 15 f0 31 c2 4a d5 bd e7 f2 99 60 df 7d 52 40\ -70 f7 44 9c 6f 78 50 84 be 1a 0f 73 30 47 f3 36\ -f9 15 47 38 67 45 47 db 02 a9 f4 4d fc 6e 60 30\ -10 81 e1 ce 99 84 7f 3b 5b 60 1f f0 6b 4d 57 76\ -a9 74 0b 9a a0 d3 40 58 fd 3b 90 6e 4f 78 59 df\ -b0 7d 71 73 e5 e6 f6 35 0a da c2 1f 27 b2 30 74\ -69 -Salt: \ -bd 0c e1 95 49 d0 70 01 20 cb e5 10 77 db bb b0\ -0a 8d 8b 09 -Signature: \ -08 18 0d e8 25 e4 b8 b0 14 a3 2d a8 ba 76 15 55\ -92 12 04 f2 f9 0d 5f 24 b7 12 90 8f f8 4f 3e 22\ -0a d1 79 97 c0 dd 6e 70 66 30 ba 3e 84 ad d4 d5\ -e7 ab 00 4e 58 07 4b 54 97 09 56 5d 43 ad 9e 97\ -b5 a7 a1 a2 9e 85 b9 f9 0f 4a af cd f5 83 21 de\ -8c 59 74 ef 9a bf 2d 52 6f 33 c0 f2 f8 2e 95 d1\ -58 ea 6b 81 f1 73 6d b8 d1 af 3d 6a c6 a8 3b 32\ -d1 8b ae 0f f1 b2 fe 27 de 4c 76 ed 8c 79 80 a3\ -4e -Test: Verify -Comment: RSASSA-PSS Signature Example 5.3 -Message: \ -8d 83 96 e3 65 07 fe 1e f6 a1 90 17 54 8e 0c 71\ -66 74 c2 fe c2 33 ad b2 f7 75 66 5e c4 1f 2b d0\ -ba 39 6b 06 1a 9d aa 7e 86 6f 7c 23 fd 35 31 95\ -43 00 a3 42 f9 24 53 5e a1 49 8c 48 f6 c8 79 93\ -28 65 fc 02 00 0c 52 87 23 b7 ad 03 35 74 5b 51\ -20 9a 0a fe d9 32 af 8f 08 87 c2 19 00 4d 2a bd\ -89 4e a9 25 59 ee 31 98 af 3a 73 4f e9 b9 63 8c\ -26 3a 72 8a d9 5a 5a e8 ce 3e b1 58 39 f3 aa 78\ -52 bb 39 07 06 e7 76 0e 43 a7 12 91 a2 e3 f8 27\ -23 7d ed a8 51 87 4c 51 76 65 f5 45 f2 72 38 df\ -86 55 7f 37 5d 09 cc d8 bd 15 d8 cc f6 1f 5d 78\ -ca 5c 7f 5c de 78 2e 6b f5 d0 05 70 56 d4 ba d9\ -8b 3d 2f 95 75 e8 24 ab 7a 33 ff 57 b0 ac 10 0a\ -b0 d6 ea d7 aa 0b 50 f6 e4 d3 e5 ec 0b 96 6b -Salt: \ -81 57 79 a9 1b 3a 8b d0 49 bf 2a eb 92 01 42 77\ -22 22 c9 ca -Signature: \ -05 e0 fd bd f6 f7 56 ef 73 31 85 cc fa 8c ed 2e\ -b6 d0 29 d9 d5 6e 35 56 1b 5d b8 e7 02 57 ee 6f\ -d0 19 d2 f0 bb f6 69 fe 9b 98 21 e7 8d f6 d4 1e\ -31 60 8d 58 28 0f 31 8e e3 4f 55 99 41 c8 df 13\ -28 75 74 ba c0 00 b7 e5 8d c4 f4 14 ba 49 fb 12\ -7f 9d 0f 89 36 63 8c 76 e8 53 56 c9 94 f7 97 50\ -f7 fa 3c f4 fd 48 2d f7 5e 3f b9 97 8c d0 61 f7\ -ab b1 75 72 e6 e6 3e 0b de 12 cb dc f1 8c 68 b9\ -79 -Test: Verify -Comment: RSASSA-PSS Signature Example 5.4 -Message: \ -32 8c 65 9e 0a 64 37 43 3c ce b7 3c 14 -Salt: \ -9a ec 4a 74 80 d5 bb c4 29 20 d7 ca 23 5d b6 74\ -98 9c 9a ac -Signature: \ -0b c9 89 85 3b c2 ea 86 87 32 71 ce 18 3a 92 3a\ -b6 5e 8a 53 10 0e 6d f5 d8 7a 24 c4 19 4e b7 97\ -81 3e e2 a1 87 c0 97 dd 87 2d 59 1d a6 0c 56 86\ -05 dd 7e 74 2d 5a f4 e3 3b 11 67 8c cb 63 90 32\ -04 a3 d0 80 b0 90 2c 89 ab a8 86 8f 00 9c 0f 1c\ -0c b8 58 10 bb dd 29 12 1a bb 84 71 ff 2d 39 e4\ -9f d9 2d 56 c6 55 c8 e0 37 ad 18 fa fb dc 92 c9\ -58 63 f7 f6 1e a9 ef a2 8f ea 40 13 69 d1 9d ae\ -a1 -Test: Verify -Comment: RSASSA-PSS Signature Example 5.5 -Message: \ -f3 7b 96 23 79 a4 7d 41 5a 37 6e ec 89 73 15 0b\ -cb 34 ed d5 ab 65 40 41 b6 14 30 56 0c 21 44 58\ -2b a1 33 c8 67 d8 52 d6 b8 e2 33 21 90 13 02 ec\ -b4 5b 09 ec 88 b1 52 71 78 fa 04 32 63 f3 06 7d\ -9f fe 97 30 32 a9 9f 4c b0 8a d2 c7 e0 a2 45 6c\ -dd 57 a7 df 56 fe 60 53 52 7a 5a eb 67 d7 e5 52\ -06 3c 1c a9 7b 1b ef fa 7b 39 e9 97 ca f2 78 78\ -ea 0f 62 cb eb c8 c2 1d f4 c8 89 a2 02 85 1e 94\ -90 88 49 0c 24 9b 6e 9a cf 1d 80 63 f5 be 23 43\ -98 9b f9 5c 4d a0 1a 2b e7 8b 4a b6 b3 78 01 5b\ -c3 79 57 f7 69 48 b5 e5 8e 44 0c 28 45 3d 40 d7\ -cf d5 7e 7d 69 06 00 47 4a b5 e7 59 73 b1 ea 0c\ -5f 1e 45 d1 41 90 af e2 f4 eb 6d 3b df 71 f1 d2\ -f8 bb 15 6a 1c 29 5d 04 aa eb 9d 68 9d ce 79 ed\ -62 bc 44 3e -Salt: \ -e2 0c 1e 98 78 51 2c 39 97 0f 58 37 5e 15 49 a6\ -8b 64 f3 1d -Signature: \ -0a ef a9 43 b6 98 b9 60 9e df 89 8a d2 27 44 ac\ -28 dc 23 94 97 ce a3 69 cb bd 84 f6 5c 95 c0 ad\ -77 6b 59 47 40 16 4b 59 a7 39 c6 ff 7c 2f 07 c7\ -c0 77 a8 6d 95 23 8f e5 1e 1f cf 33 57 4a 4a e0\ -68 4b 42 a3 f6 bf 67 7d 91 82 0c a8 98 74 46 7b\ -2c 23 ad d7 79 69 c8 07 17 43 0d 0e fc 1d 36 95\ -89 2c e8 55 cb 7f 70 11 63 0f 4d f2 6d ef 8d df\ -36 fc 23 90 5f 57 fa 62 43 a4 85 c7 70 d5 68 1f\ -cd -Test: Verify -Comment: RSASSA-PSS Signature Example 5.6 -Message: \ -c6 10 3c 33 0c 1e f7 18 c1 41 e4 7b 8f a8 59 be\ -4d 5b 96 25 9e 7d 14 20 70 ec d4 85 83 9d ba 5a\ -83 69 c1 7c 11 14 03 5e 53 2d 19 5c 74 f4 4a 04\ -76 a2 d3 e8 a4 da 21 00 16 ca ce d0 e3 67 cb 86\ -77 10 a4 b5 aa 2d f2 b8 e5 da f5 fd c6 47 80 7d\ -4d 5e bb 6c 56 b9 76 3c cd ae 4d ea 33 08 eb 0a\ -c2 a8 95 01 cb 20 9d 26 39 fa 5b f8 7c e7 90 74\ -7d 3c b2 d2 95 e8 45 64 f2 f6 37 82 4f 0c 13 02\ -81 29 b0 aa 4a 42 2d 16 22 82 -Salt: \ -23 29 1e 4a 33 07 e8 bb b7 76 62 3a b3 4e 4a 5f\ -4c c8 a8 db -Signature: \ -02 80 2d cc fa 8d fa f5 27 9b f0 b4 a2 9b a1 b1\ -57 61 1f ae aa f4 19 b8 91 9d 15 94 19 00 c1 33\ -9e 7e 92 e6 fa e5 62 c5 3e 6c c8 e8 41 04 b1 10\ -bc e0 3a d1 85 25 e3 c4 9a 0e ad ad 5d 3f 28 f2\ -44 a8 ed 89 ed ba fb b6 86 27 7c fa 8a e9 09 71\ -4d 6b 28 f4 bf 8e 29 3a a0 4c 41 ef e7 c0 a8 12\ -66 d5 c0 61 e2 57 5b e0 32 aa 46 46 74 ff 71 62\ -62 19 bd 74 cc 45 f0 e7 ed 4e 3f f9 6e ee 75 8e\ -8f -Test: Verify -Comment: Example 6: A 1029-bit RSA Key Pair -Modulus: \ -16 4c a3 1c ff 60 9f 3a 0e 71 01 b0 39 f2 e4 fe\ -6d d3 75 19 ab 98 59 8d 17 9e 17 49 96 59 80 71\ -f4 7d 3a 04 55 91 58 d7 be 37 3c f1 aa 53 f0 aa\ -6e f0 90 39 e5 67 8c 2a 4c 63 90 05 14 c8 c4 f8\ -aa ed 5d e1 2a 5f 10 b0 9c 31 1a f8 c0 ff b5 b7\ -a2 97 f2 ef c6 3b 8d 6b 05 10 93 1f 0b 98 e4 8b\ -f5 fc 6e c4 e7 b8 db 1f fa eb 08 c3 8e 02 ad b8\ -f0 3a 48 22 9c 99 e9 69 43 1f 61 cb 8c 4d c6 98\ -d1 -PublicExponent: \ -01 00 01 -PrivateExponent: \ -03 b6 64 ee 3b 75 66 72 3f c6 ea f2 8a bb 43 0a\ -39 80 f1 12 6c 81 de 8a d7 09 ea b3 9a c9 dc d0\ -b1 55 0b 37 29 d8 70 68 e9 52 00 9d f5 44 53 4c\ -1f 50 82 9a 78 f4 59 1e b8 fd 57 14 04 26 a6 bb\ -04 05 b6 a6 f5 1a 57 d9 26 7b 7b bc 65 33 91 a6\ -99 a2 a9 0d ac 8a e2 26 bc c6 0f a8 cd 93 4c 73\ -c7 b0 3b 1f 6b 81 81 58 63 18 38 a8 61 2e 6e 6e\ -a9 2b e2 4f 83 24 fa f5 b1 fd 85 87 22 52 67 ba\ -6f -Prime1: \ -04 f0 54 8c 96 26 ab 1e bf 12 44 93 47 41 d9 9a\ -06 22 0e fa 2a 58 56 aa 0e 75 73 0b 2e c9 6a dc\ -86 be 89 4f a2 80 3b 53 a5 e8 5d 27 6a cb d2 9a\ -b8 23 f8 0a 73 91 bb 54 a5 05 16 72 fb 04 ee b5\ -43 -Prime2: \ -04 83 e0 ae 47 91 55 87 74 3f f3 45 36 2b 55 5d\ -39 62 d9 8b b6 f1 5f 84 8b 4c 92 b1 77 1c a8 ed\ -10 7d 8d 3e e6 5e c4 45 17 dd 0f aa 48 1a 38 7e\ -90 2f 7a 2e 74 7c 26 9e 7e a4 44 80 bc 53 8b 8e\ -5b -ModPrime1PrivateExponent: \ -03 a8 e8 ae a9 92 0c 1a a3 b2 f0 d8 46 e4 b8 50\ -d8 1c a3 06 a5 1c 83 54 4f 94 9f 64 f9 0d cf 3f\ -8e 26 61 f0 7e 56 12 20 a1 80 38 8f be 27 3e 70\ -e2 e5 dc a8 3a 0e 13 48 dd 64 90 c7 31 d6 ec e1\ -ab -ModPrime2PrivateExponent: \ -01 35 bd cd b6 0b f2 19 7c 43 6e d3 4b 32 cd 8b\ -4f c7 77 78 83 2b a7 67 03 55 1f b2 42 b3 01 69\ -95 93 af 77 fd 8f c3 94 a8 52 6a d2 3c c4 1a 03\ -80 6b d8 97 fe 4b 0e a6 46 55 8a ad dc c9 9e 8a\ -25 -MultiplicativeInverseOfPrime2ModPrime1: \ -03 04 c0 3d 9c 73 65 03 a9 84 ab bd 9b a2 23 01\ -40 7c 4a 2a b1 dd 85 76 64 81 b6 0d 45 40 11 52\ -e6 92 be 14 f4 12 1d 9a a3 fd 6e 0b 4d 1d 3a 97\ -35 38 a3 1d 42 ee 6e 1e 5e f6 20 23 1a 2b ba f3\ -5f -Test: KeyPairValidAndConsistent -Comment: RSASSA-PSS Signature Example 6.1 -Message: \ -0a 20 b7 74 ad dc 2f a5 12 45 ed 7c b9 da 60 9e\ -50 ca c6 63 6a 52 54 3f 97 45 8e ed 73 40 f8 d5\ -3f fc 64 91 8f 94 90 78 ee 03 ef 60 d4 2b 5f ec\ -24 60 50 bd 55 05 cd 8c b5 97 ba d3 c4 e7 13 b0\ -ef 30 64 4e 76 ad ab b0 de 01 a1 56 1e fb 25 51\ -58 c7 4f c8 01 e6 e9 19 e5 81 b4 6f 0f 0d dd 08\ -e4 f3 4c 78 10 b5 ed 83 18 f9 1d 7c 8c -Salt: \ -5b 4e a2 ef 62 9c c2 2f 3b 53 8e 01 69 04 b4 7b\ -1e 40 bf d5 -Signature: \ -04 c0 cf ac ec 04 e5 ba db ec e1 59 a5 a1 10 3f\ -69 b3 f3 2b a5 93 cb 4c c4 b1 b7 ab 45 59 16 a9\ -6a 27 cd 26 78 ea 0f 46 ba 37 f7 fc 9c 86 32 5f\ -29 73 3b 38 9f 1d 97 f4 3e 72 01 c0 f3 48 fc 45\ -fe 42 89 23 35 36 2e ee 01 8b 5b 16 1f 2f 93 93\ -03 12 25 c7 13 01 2a 57 6b c8 8e 23 05 24 89 86\ -8d 90 10 cb f0 33 ec c5 68 e8 bc 15 2b dc 59 d5\ -60 e4 12 91 91 5d 28 56 52 08 e2 2a ee c9 ef 85\ -d1 -Test: Verify -Comment: RSASSA-PSS Signature Example 6.2 -Message: \ -2a af f6 63 1f 62 1c e6 15 76 0a 9e bc e9 4b b3\ -33 07 7a d8 64 88 c8 61 d4 b7 6d 29 c1 f4 87 46\ -c6 11 ae 1e 03 ce d4 44 5d 7c fa 1f e5 f6 2e 1b\ -3f 08 45 2b de 3b 6e f8 19 73 ba fb b5 7f 97 bc\ -ee f8 73 98 53 95 b8 26 05 89 aa 88 cb 7d b5 0a\ -b4 69 26 2e 55 1b dc d9 a5 6f 27 5a 0a c4 fe 48\ -47 00 c3 5f 3d bf 2b 46 9e de 86 47 41 b8 6f a5\ -91 72 a3 60 ba 95 a0 2e 13 9b e5 0d df b7 cf 0b\ -42 fa ea bb fb ba a8 6a 44 97 69 9c 4f 2d fd 5b\ -08 40 6a f7 e1 41 44 42 7c 25 3e c0 ef a2 0e af\ -9a 8b e8 cd 49 ce 1f 1b c4 e9 3e 61 9c f2 aa 8e\ -d4 fb 39 bc 85 90 d0 f7 b9 64 88 f7 31 7a c9 ab\ -f7 be e4 e3 a0 e7 15 -Salt: \ -83 14 6a 9e 78 27 22 c2 8b 01 4f 98 b4 26 7b da\ -2a c9 50 4f -Signature: \ -0a 23 14 25 0c f5 2b 6e 4e 90 8d e5 b3 56 46 bc\ -aa 24 36 1d a8 16 0f b0 f9 25 75 90 ab 3a ce 42\ -b0 dc 3e 77 ad 2d b7 c2 03 a2 0b d9 52 fb b5 6b\ -15 67 04 6e cf aa 93 3d 7b 10 00 c3 de 9f f0 5b\ -7d 98 9b a4 6f d4 3b c4 c2 d0 a3 98 6b 7f fa 13\ -47 1d 37 eb 5b 47 d6 47 07 bd 29 0c fd 6a 9f 39\ -3a d0 8e c1 e3 bd 71 bb 57 92 61 50 35 cd af 2d\ -89 29 ae d3 be 09 83 79 37 7e 77 7c e7 9a aa 47\ -73 -Test: Verify -Comment: RSASSA-PSS Signature Example 6.3 -Message: \ -0f 61 95 d0 4a 6e 6f c7 e2 c9 60 0d bf 84 0c 39\ -ea 8d 4d 62 4f d5 35 07 01 6b 0e 26 85 8a 5e 0a\ -ec d7 ad a5 43 ae 5c 0a b3 a6 25 99 cb a0 a5 4e\ -6b f4 46 e2 62 f9 89 97 8f 9d df 5e 9a 41 -Salt: \ -a8 7b 8a ed 07 d7 b8 e2 da f1 4d dc a4 ac 68 c4\ -d0 aa bf f8 -Signature: \ -08 6d f6 b5 00 09 8c 12 0f 24 ff 84 23 f7 27 d9\ -c6 1a 5c 90 07 d3 b6 a3 1c e7 cf 8f 3c be c1 a2\ -6b b2 0e 2b d4 a0 46 79 32 99 e0 3e 37 a2 1b 40\ -19 4f b0 45 f9 0b 18 bf 20 a4 79 92 cc d7 99 cf\ -9c 05 9c 29 9c 05 26 85 49 54 aa de 8a 6a d9 d9\ -7e c9 1a 11 45 38 3f 42 46 8b 23 1f 4d 72 f2 37\ -06 d9 85 3c 3f a4 3c e8 ac e8 bf e7 48 49 87 a1\ -ec 6a 16 c8 da f8 1f 7c 8b f4 27 74 70 7a 9d f4\ -56 -Test: Verify -Comment: RSASSA-PSS Signature Example 6.4 -Message: \ -33 7d 25 fe 98 10 eb ca 0d e4 d4 65 8d 3c eb 8e\ -0f e4 c0 66 ab a3 bc c4 8b 10 5d 3b f7 e0 25 7d\ -44 fe ce a6 59 6f 4d 0c 59 a0 84 02 83 36 78 f7\ -06 20 f9 13 8d fe b7 de d9 05 e4 a6 d5 f0 5c 47\ -3d 55 93 66 52 e2 a5 df 43 c0 cf da 7b ac af 30\ -87 f4 52 4b 06 cf 42 15 7d 01 53 97 39 f7 fd de\ -c9 d5 81 25 df 31 a3 2e ab 06 c1 9b 71 f1 d5 bf -Salt: \ -a3 79 32 f8 a7 49 4a 94 2d 6f 76 74 38 e7 24 d6\ -d0 c0 ef 18 -Signature: \ -0b 5b 11 ad 54 98 63 ff a9 c5 1a 14 a1 10 6c 2a\ -72 cc 8b 64 6e 5c 72 62 50 97 86 10 5a 98 47 76\ -53 4c a9 b5 4c 1c c6 4b f2 d5 a4 4f d7 e8 a6 9d\ -b6 99 d5 ea 52 08 7a 47 48 fd 2a bc 1a fe d1 e5\ -d6 f7 c8 90 25 53 0b da a2 21 3d 7e 03 0f a5 5d\ -f6 f3 4b cf 1c e4 6d 2e df 4e 3a e4 f3 b0 18 91\ -a0 68 c9 e3 a4 4b bc 43 13 3e da d6 ec b9 f3 54\ -00 c4 25 2a 57 62 d6 57 44 b9 9c b9 f4 c5 59 32\ -9f -Test: Verify -Comment: RSASSA-PSS Signature Example 6.5 -Message: \ -84 ec 50 2b 07 2e 82 87 78 9d 8f 92 35 82 9e a3\ -b1 87 af d4 d4 c7 85 61 1b da 5f 9e b3 cb 96 71\ -7e fa 70 07 22 7f 1c 08 cb cb 97 2e 66 72 35 e0\ -fb 7d 43 1a 65 70 32 6d 2e cc e3 5a db 37 3d c7\ -53 b3 be 5f 82 9b 89 17 54 93 19 3f ab 16 ba db\ -41 37 1b 3a ac 0a e6 70 07 6f 24 be f4 20 c1 35\ -ad d7 ce e8 d3 5f bc 94 4d 79 fa fb 9e 30 7a 13\ -b0 f5 56 cb 65 4a 06 f9 73 ed 22 67 23 30 19 7e\ -f5 a7 48 bf 82 6a 5d b2 38 3a 25 36 4b 68 6b 93\ -72 bb 23 39 ae b1 ac 9e 98 89 32 7d 01 6f 16 70\ -77 6d b0 62 01 ad bd ca f8 a5 e3 b7 4e 10 8b 73 -Salt: \ -7b 79 0c 1d 62 f7 b8 4e 94 df 6a f2 89 17 cf 57\ -10 18 11 0e -Signature: \ -02 d7 1f a9 b5 3e 46 54 fe fb 7f 08 38 5c f6 b0\ -ae 3a 81 79 42 eb f6 6c 35 ac 67 f0 b0 69 95 2a\ -3c e9 c7 e1 f1 b0 2e 48 0a 95 00 83 6d e5 d6 4c\ -db 7e cd e0 45 42 f7 a7 99 88 78 7e 24 c2 ba 05\ -f5 fd 48 2c 02 3e d5 c3 0e 04 83 9d c4 4b ed 2a\ -3a 3a 4f ee 01 11 3c 89 1a 47 d3 2e b8 02 5c 28\ -cb 05 0b 5c db 57 6c 70 fe 76 ef 52 34 05 c0 84\ -17 fa f3 50 b0 37 a4 3c 37 93 39 fc b1 8d 3a 35\ -6b -Test: Verify -Comment: RSASSA-PSS Signature Example 6.6 -Message: \ -99 06 d8 9f 97 a9 fd ed d3 cc d8 24 db 68 73 26\ -f3 0f 00 aa 25 a7 fc a2 af cb 3b 0f 86 cd 41 e7\ -3f 0e 8f f7 d2 d8 3f 59 e2 8e d3 1a 5a 0d 55 15\ -23 37 4d e2 2e 4c 7e 8f f5 68 b3 86 ee 3d c4 11\ -63 f1 0b f6 7b b0 06 26 1c 90 82 f9 af 90 bf 1d\ -90 49 a6 b9 fa e7 1c 7f 84 fb e6 e5 5f 02 78 9d\ -e7 74 f2 30 f1 15 02 6a 4b 4e 96 c5 5b 04 a9 5d\ -a3 aa cb b2 ce ce 8f 81 76 4a 1f 1c 99 51 54 11\ -08 7c f7 d3 4a ed ed 09 32 c1 83 -Salt: \ -fb be 05 90 25 b6 9b 89 fb 14 ae 22 89 e7 aa af\ -e6 0c 0f cd -Signature: \ -0a 40 a1 6e 2f e2 b3 8d 1d f9 05 46 16 7c f9 46\ -9c 9e 3c 36 81 a3 44 2b 4b 2c 2f 58 1d eb 38 5c\ -e9 9f c6 18 8b b0 2a 84 1d 56 e7 6d 30 18 91 e2\ -45 60 55 0f cc 2a 26 b5 5f 4c cb 26 d8 37 d3 50\ -a1 54 bc ac a8 39 2d 98 fa 67 95 9e 97 27 b7 8c\ -ad 03 26 9f 56 96 8f c5 6b 68 bd 67 99 26 d8 3c\ -c9 cb 21 55 50 64 5c cd a3 1c 76 0f f3 58 88 94\ -3d 2d 8a 1d 35 1e 81 e5 d0 7b 86 18 2e 75 10 81\ -ef -Test: Verify -Comment: Example 7: A 1030-bit RSA Key Pair -Modulus: \ -37 c9 da 4a 66 c8 c4 08 b8 da 27 d0 c9 d7 9f 8c\ -cb 1e af c1 d2 fe 48 74 6d 94 0b 7c 4e f5 de e1\ -8a d1 26 47 ce fa a0 c4 b3 18 8b 22 1c 51 53 86\ -75 9b 93 f0 20 24 b2 5a b9 24 2f 83 57 d8 f3 fd\ -49 64 0e e5 e6 43 ea f6 c6 4d ee fa 70 89 72 7c\ -8f f0 39 93 33 39 15 c6 ef 21 bf 59 75 b6 e5 0d\ -11 8b 51 00 8e c3 3e 9f 01 a0 a5 45 a1 0a 83 6a\ -43 dd bc a9 d8 b5 c5 d3 54 80 22 d7 06 4e a2 9a\ -b3 -PublicExponent: \ -01 00 01 -PrivateExponent: \ -3b ed 99 90 52 d9 57 bc 06 d6 51 ee f6 e3 a9 80\ -94 b1 62 1b d3 8b 54 49 bd 6c 4a ea 3d e7 e0 84\ -67 9a 44 84 de d2 5b e0 f0 82 6c f3 37 78 25 41\ -4b 14 d4 d6 1d b1 4d e6 26 fb b8 0e 5f 4f ae c9\ -56 f9 a0 a2 d2 4f 99 57 63 80 f0 84 eb 62 e4 6a\ -57 d5 54 27 8b 53 56 26 19 3c e0 20 60 57 5e b6\ -6c 57 98 d3 6f 6c 5d 40 fb 00 d8 09 b4 2a 73 10\ -2c 1c 74 ee 95 bd 71 42 0f ff ef 63 18 b5 2c 29 -Prime1: \ -07 ee fb 42 4b 0e 3a 40 e4 20 8e e5 af b2 80 b2\ -23 17 30 81 14 dd e0 b4 b6 4f 73 01 84 ec 68 da\ -6c e2 86 7a 9f 48 ed 77 26 d5 e2 61 4e d0 4a 54\ -10 73 6c 8c 71 4e e7 02 47 42 98 c6 29 2a f0 75\ -35 -Prime2: \ -07 08 30 db f9 47 ea c0 22 8d e2 63 14 b5 9b 66\ -99 4c c6 0e 83 60 e7 5d 38 76 29 8f 8f 8a 7d 14\ -1d a0 64 e5 ca 02 6a 97 3e 28 f2 54 73 8c ee 66\ -9c 72 1b 03 4c b5 f8 e2 44 da dd 7c d1 e1 59 d5\ -47 -ModPrime1PrivateExponent: \ -05 24 d2 0c 3d 95 cf f7 5a f2 31 34 83 22 7d 87\ -02 71 7a a5 76 de 15 5f 96 05 15 50 1a db 1d 70\ -e1 c0 4d e9 1b 75 b1 61 db f0 39 83 56 12 7e de\ -da 7b bc 19 a3 2d c1 62 1c c9 f5 3c 26 5d 0c e3\ -31 -ModPrime2PrivateExponent: \ -05 f9 84 a1 f2 3c 93 8d 6a 0e 89 72 4b cf 3d d9\ -3f 99 46 92 60 37 fe 7c 6b 13 a2 9e 52 84 85 5f\ -89 08 95 91 d4 40 97 56 27 bf 5c 9e 3a 8b 5c a7\ -9c 77 2a d2 73 e4 0d 32 1a f4 a6 c9 7d fd ed 78\ -d3 -MultiplicativeInverseOfPrime2ModPrime1: \ -dd d9 18 ad ad a2 9d ca b9 81 ff 9a cb a4 25 70\ -23 c0 9a 38 01 cc ce 09 8c e2 68 f8 55 d0 df 57\ -0c d6 e7 b9 b1 4b d9 a5 a9 25 4c bc 31 5b e6 f8\ -ba 1e 25 46 dd d5 69 c5 ea 19 ee d8 35 3b de 5e -Test: KeyPairValidAndConsistent -Comment: RSASSA-PSS Signature Example 7.1 -Message: \ -9e ad 0e 01 94 56 40 67 4e b4 1c ad 43 5e 23 74\ -ea ef a8 ad 71 97 d9 79 13 c4 49 57 d8 d8 3f 40\ -d7 6e e6 0e 39 bf 9c 0f 9e af 30 21 42 1a 07 4d\ -1a de 96 2c 6e 9d 3d c3 bb 17 4f e4 df e6 52 b0\ -91 15 49 5b 8f d2 79 41 74 02 0a 06 02 b5 ca 51\ -84 8c fc 96 ce 5e b5 7f c0 a2 ad c1 dd a3 6a 7c\ -c4 52 64 1a 14 91 1b 37 e4 5b fa 11 da a5 c7 ec\ -db 74 f6 d0 10 0d 1d 3e 39 e7 52 80 0e 20 33 97\ -de 02 33 07 7b 9a 88 85 55 37 fa e9 27 f9 24 38\ -0d 78 0f 98 e1 8d cf f3 9c 5e a7 41 b1 7d 6f dd\ -18 85 bc 9d 58 14 82 d7 71 ce b5 62 d7 8a 8b f8\ -8f 0c 75 b1 13 63 e5 e3 6c d4 79 ce b0 54 5f 9d\ -a8 42 03 e0 e6 e5 08 37 5c c9 e8 44 b8 8b 7a c7\ -a0 a2 01 ea 0f 1b ee 9a 2c 57 79 20 ca 02 c0 1b\ -9d 83 20 e9 74 a5 6f 4e fb 57 63 b9 62 55 ab bf\ -80 37 bf 18 02 cf 01 8f 56 37 94 93 e5 69 a9 -Salt: \ -b7 86 7a 59 95 8c b5 43 28 f8 77 5e 65 46 ec 06\ -d2 7e aa 50 -Signature: \ -18 7f 39 07 23 c8 90 25 91 f0 15 4b ae 6d 4e cb\ -ff e0 67 f0 e8 b7 95 47 6e a4 f4 d5 1c cc 81 05\ -20 bb 3c a9 bc a7 d0 b1 f2 ea 8a 17 d8 73 fa 27\ -57 0a cd 64 2e 38 08 56 1c b9 e9 75 cc fd 80 b2\ -3d c5 77 1c db 33 06 a5 f2 31 59 da cb d3 aa 2d\ -b9 3d 46 d7 66 e0 9e d1 5d 90 0a d8 97 a8 d2 74\ -dc 26 b4 7e 99 4a 27 e9 7e 22 68 a7 66 53 3a e4\ -b5 e4 2a 2f ca f7 55 c1 c4 79 4b 29 4c 60 55 58\ -23 -Test: Verify -Comment: RSASSA-PSS Signature Example 7.2 -Message: \ -8d 80 d2 d0 8d bd 19 c1 54 df 3f 14 67 3a 14 bd\ -03 73 52 31 f2 4e 86 bf 15 3d 0e 69 e7 4c bf f7\ -b1 83 6e 66 4d e8 3f 68 01 24 37 0f c0 f9 6c 9b\ -65 c0 7a 36 6b 64 4c 4a b3 -Salt: \ -0c 09 58 22 66 df 08 63 10 82 1b a7 e1 8d f6 4d\ -fe e6 de 09 -Signature: \ -10 fd 89 76 8a 60 a6 77 88 ab b5 85 6a 78 7c 85\ -61 f3 ed cf 9a 83 e8 98 f7 dc 87 ab 8c ce 79 42\ -9b 43 e5 69 06 94 1a 88 61 94 f1 37 e5 91 fe 7c\ -33 95 55 36 1f bb e1 f2 4f eb 2d 4b cd b8 06 01\ -f3 09 6b c9 13 2d ee a6 0a e1 30 82 f4 4f 9a d4\ -1c d6 28 93 6a 4d 51 17 6e 42 fc 59 cb 76 db 81\ -5c e5 ab 4d b9 9a 10 4a af ea 68 f5 d3 30 32 9e\ -bf 25 8d 4e de 16 06 4b d1 d0 03 93 d5 e1 57 0e\ -b8 -Test: Verify -Comment: RSASSA-PSS Signature Example 7.3 -Message: \ -80 84 05 cd fc 1a 58 b9 bb 03 97 c7 20 72 2a 81\ -ff fb 76 27 8f 33 59 17 ef 9c 47 38 14 b3 e0 16\ -ba 29 73 cd 27 65 f8 f3 f8 2d 6c c3 8a a7 f8 55\ -18 27 fe 8d 1e 38 84 b7 e6 1c 94 68 3b 8f 82 f1\ -84 3b da e2 25 7e ee c9 81 2a d4 c2 cf 28 3c 34\ -e0 b0 ae 0f e3 cb 99 0c f8 8f 2e f9 -Salt: \ -28 03 9d cf e1 06 d3 b8 29 66 11 25 8c 4a 56 65\ -1c 9e 92 dd -Signature: \ -2b 31 fd e9 98 59 b9 77 aa 09 58 6d 8e 27 46 62\ -b2 5a 2a 64 06 40 b4 57 f5 94 05 1c b1 e7 f7 a9\ -11 86 54 55 24 29 26 cf 88 fe 80 df a3 a7 5b a9\ -68 98 44 a1 1e 63 4a 82 b0 75 af bd 69 c1 2a 0d\ -f9 d2 5f 84 ad 49 45 df 3d c8 fe 90 c3 ce fd f2\ -6e 95 f0 53 43 04 b5 bd ba 20 d3 e5 64 0a 2e bf\ -b8 98 aa c3 5a e4 0f 26 fc e5 56 3c 2f 9f 24 f3\ -04 2a f7 6f 3c 70 72 d6 87 bb fb 95 9a 88 46 0a\ -f1 -Test: Verify -Comment: RSASSA-PSS Signature Example 7.4 -Message: \ -f3 37 b9 ba d9 37 de 22 a1 a0 52 df f1 11 34 a8\ -ce 26 97 62 02 98 19 39 b9 1e 07 15 ae 5e 60 96\ -49 da 1a df ce f3 f4 cc a5 9b 23 83 60 e7 d1 e4\ -96 c7 bf 4b 20 4b 5a cf f9 bb d6 16 6a 1d 87 a3\ -6e f2 24 73 73 75 10 39 f8 a8 00 b8 39 98 07 b3\ -a8 5f 44 89 34 97 c0 d0 5f b7 01 7b 82 22 81 52\ -de 6f 25 e6 11 6d cc 75 03 c7 86 c8 75 c2 8f 3a\ -a6 07 e9 4a b0 f1 98 63 ab 1b 50 73 77 0b 0c d5\ -f5 33 ac de 30 c6 fb 95 3c f3 da 68 02 64 e3 0f\ -c1 1b ff 9a 19 bf fa b4 77 9b 62 23 c3 fb 3f e0\ -f7 1a ba de 4e b7 c0 9c 41 e2 4c 22 d2 3f a1 48\ -e6 a1 73 fe b6 39 84 d1 bc 6e e3 a0 2d 91 5b 75\ -2c ea f9 2a 30 15 ec eb 38 ca 58 6c 68 01 b3 7c\ -34 ce fb 2c ff 25 ea 23 c0 86 62 dc ab 26 a7 a9\ -3a 28 5d 05 d3 04 4c -Salt: \ -a7 78 21 eb bb ef 24 62 8e 4e 12 e1 d0 ea 96 de\ -39 8f 7b 0f -Signature: \ -32 c7 ca 38 ff 26 94 9a 15 00 0c 4b a0 4b 2b 13\ -b3 5a 38 10 e5 68 18 4d 7e ca ba a1 66 b7 ff ab\ -dd f2 b6 cf 4b a0 71 24 92 37 90 f2 e5 b1 a5 be\ -04 0a ea 36 fe 13 2e c1 30 e1 f1 05 67 98 2d 17\ -ac 3e 89 b8 d2 6c 30 94 03 4e 76 2d 2e 03 12 64\ -f0 11 70 be ec b3 d1 43 9e 05 84 6f 25 45 83 67\ -a7 d9 c0 20 60 44 46 72 67 1e 64 e8 77 86 45 59\ -ca 19 b2 07 4d 58 8a 28 1b 58 04 d2 37 72 fb be\ -19 -Test: Verify -Comment: RSASSA-PSS Signature Example 7.5 -Message: \ -45 01 3c eb af d9 60 b2 55 47 6a 8e 25 98 b9 aa\ -32 ef be 6d c1 f3 4f 4a 49 8d 8c f5 a2 b4 54 8d\ -08 c5 5d 5f 95 f7 bc c9 61 91 63 05 6f 2d 58 b5\ -2f a0 32 -Salt: \ -9d 5a d8 eb 45 21 34 b6 5d c3 a9 8b 6a 73 b5 f7\ -41 60 9c d6 -Signature: \ -07 eb 65 1d 75 f1 b5 2b c2 63 b2 e1 98 33 6e 99\ -fb eb c4 f3 32 04 9a 92 2a 10 81 56 07 ee 2d 98\ -9d b3 a4 49 5b 7d cc d3 8f 58 a2 11 fb 7e 19 31\ -71 a3 d8 91 13 24 37 eb ca 44 f3 18 b2 80 50 9e\ -52 b5 fa 98 fc ce 82 05 d9 69 7c 8e e4 b7 ff 59\ -d4 c5 9c 79 03 8a 19 70 bd 2a 0d 45 1e cd c5 ef\ -11 d9 97 9c 9d 35 f8 c7 0a 61 63 71 76 07 89 0d\ -58 6a 7c 6d c0 1c 79 f8 6a 8f 28 e8 52 35 f8 c2\ -f1 -Test: Verify -Comment: RSASSA-PSS Signature Example 7.6 -Message: \ -23 58 09 70 86 c8 99 32 3e 75 d9 c9 0d 0c 09 f1\ -2d 9d 54 ed fb df 70 a9 c2 eb 5a 04 d8 f3 6b 9b\ -2b df 2a ab e0 a5 bd a1 96 89 37 f9 d6 eb d3 b6\ -b2 57 ef b3 13 6d 41 31 f9 ac b5 9b 85 e2 60 2c\ -2a 3f cd c8 35 49 4a 1f 4e 5e c1 8b 22 6c 80 23\ -2b 36 a7 5a 45 fd f0 9a 7e a9 e9 8e fb de 14 50\ -d1 19 4b f1 2e 15 a4 c5 f9 eb 5c 0b ce 52 69 e0\ -c3 b2 8c fa b6 55 d8 1a 61 a2 0b 4b e2 f5 44 59\ -bb 25 a0 db 94 c5 22 18 be 10 9a 74 26 de 83 01\ -44 24 78 9a aa 90 e5 05 6e 63 2a 69 81 15 e2 82\ -c1 a5 64 10 f2 6c 20 72 f1 93 48 1a 9d cd 88 05\ -72 00 5e 64 f4 08 2e cf -Salt: \ -3f 2e fc 59 58 80 a7 d4 7f cf 3c ba 04 98 3e a5\ -4c 4b 73 fb -Signature: \ -18 da 3c dc fe 79 bf b7 7f d9 c3 2f 37 7a d3 99\ -14 6f 0a 8e 81 06 20 23 32 71 a6 e3 ed 32 48 90\ -3f 5c dc 92 dc 79 b5 5d 3e 11 61 5a a0 56 a7 95\ -85 37 92 a3 99 8c 34 9c a5 c4 57 e8 ca 7d 29 d7\ -96 aa 24 f8 34 91 70 9b ef cf b1 51 0e a5 13 c9\ -28 29 a3 f0 0b 10 4f 65 56 34 f3 20 75 2e 13 0e\ -c0 cc f6 75 4f f8 93 db 30 29 32 bb 02 5e b6 0e\ -87 82 25 98 fc 61 9e 0e 98 17 37 a9 a4 c4 15 2d\ -33 -Test: Verify -Comment: Example 8: A 1031-bit RSA Key Pair -Modulus: \ -49 53 70 a1 fb 18 54 3c 16 d3 63 1e 31 63 25 5d\ -f6 2b e6 ee e8 90 d5 f2 55 09 e4 f7 78 a8 ea 6f\ -bb bc df 85 df f6 4e 0d 97 20 03 ab 36 81 fb ba\ -6d d4 1f d5 41 82 9b 2e 58 2d e9 f2 a4 a4 e0 a2\ -d0 90 0b ef 47 53 db 3c ee 0e e0 6c 7d fa e8 b1\ -d5 3b 59 53 21 8f 9c ce ea 69 5b 08 66 8e de aa\ -dc ed 94 63 b1 d7 90 d5 eb f2 7e 91 15 b4 6c ad\ -4d 9a 2b 8e fa b0 56 1b 08 10 34 47 39 ad a0 73\ -3f -PublicExponent: \ -01 00 01 -PrivateExponent: \ -6c 66 ff e9 89 80 c3 8f cd ea b5 15 98 98 83 61\ -65 f4 b4 b8 17 c4 f6 a8 d4 86 ee 4e a9 13 0f e9\ -b9 09 2b d1 36 d1 84 f9 5f 50 4a 60 7e ac 56 58\ -46 d2 fd d6 59 7a 89 67 c7 39 6e f9 5a 6e ee bb\ -45 78 a6 43 96 6d ca 4d 8e e3 de 84 2d e6 32 79\ -c6 18 15 9c 1a b5 4a 89 43 7b 6a 61 20 e4 93 0a\ -fb 52 a4 ba 6c ed 8a 49 47 ac 64 b3 0a 34 97 cb\ -e7 01 c2 d6 26 6d 51 72 19 ad 0e c6 d3 47 db e9 -Prime1: \ -08 da d7 f1 13 63 fa a6 23 d5 d6 d5 e8 a3 19 32\ -8d 82 19 0d 71 27 d2 84 6c 43 9b 0a b7 26 19 b0\ -a4 3a 95 32 0e 4e c3 4f c3 a9 ce a8 76 42 23 05\ -bd 76 c5 ba 7b e9 e2 f4 10 c8 06 06 45 a1 d2 9e\ -db -Prime2: \ -08 47 e7 32 37 6f c7 90 0f 89 8e a8 2e b2 b0 fc\ -41 85 65 fd ae 62 f7 d9 ec 4c e2 21 7b 97 99 0d\ -d2 72 db 15 7f 99 f6 3c 0d cb b9 fb ac db d4 c4\ -da db 6d f6 77 56 35 8c a4 17 48 25 b4 8f 49 70\ -6d -ModPrime1PrivateExponent: \ -05 c2 a8 3c 12 4b 36 21 a2 aa 57 ea 2c 3e fe 03\ -5e ff 45 60 f3 3d de bb 7a da b8 1f ce 69 a0 c8\ -c2 ed c1 65 20 dd a8 3d 59 a2 3b e8 67 96 3a c6\ -5f 2c c7 10 bb cf b9 6e e1 03 de b7 71 d1 05 fd\ -85 -ModPrime2PrivateExponent: \ -04 ca e8 aa 0d 9f aa 16 5c 87 b6 82 ec 14 0b 8e\ -d3 b5 0b 24 59 4b 7a 3b 2c 22 0b 36 69 bb 81 9f\ -98 4f 55 31 0a 1a e7 82 36 51 d4 a0 2e 99 44 79\ -72 59 51 39 36 34 34 e5 e3 0a 7e 7d 24 15 51 e1\ -b9 -MultiplicativeInverseOfPrime2ModPrime1: \ -07 d3 e4 7b f6 86 60 0b 11 ac 28 3c e8 8d bb 3f\ -60 51 e8 ef d0 46 80 e4 4c 17 1e f5 31 b8 0b 2b\ -7c 39 fc 76 63 20 e2 cf 15 d8 d9 98 20 e9 6f f3\ -0d c6 96 91 83 9c 4b 40 d7 b0 6e 45 30 7d c9 1f\ -3f -Test: KeyPairValidAndConsistent -Comment: RSASSA-PSS Signature Example 8.1 -Message: \ -81 33 2f 4b e6 29 48 41 5e a1 d8 99 79 2e ea cf\ -6c 6e 1d b1 da 8b e1 3b 5c ea 41 db 2f ed 46 70\ -92 e1 ff 39 89 14 c7 14 25 97 75 f5 95 f8 54 7f\ -73 56 92 a5 75 e6 92 3a f7 8f 22 c6 99 7d db 90\ -fb 6f 72 d7 bb 0d d5 74 4a 31 de cd 3d c3 68 58\ -49 83 6e d3 4a ec 59 63 04 ad 11 84 3c 4f 88 48\ -9f 20 97 35 f5 fb 7f da f7 ce c8 ad dc 58 18 16\ -8f 88 0a cb f4 90 d5 10 05 b7 a8 e8 4e 43 e5 42\ -87 97 75 71 dd 99 ee a4 b1 61 eb 2d f1 f5 10 8f\ -12 a4 14 2a 83 32 2e db 05 a7 54 87 a3 43 5c 9a\ -78 ce 53 ed 93 bc 55 08 57 d7 a9 fb -Salt: \ -1d 65 49 1d 79 c8 64 b3 73 00 9b e6 f6 f2 46 7b\ -ac 4c 78 fa -Signature: \ -02 62 ac 25 4b fa 77 f3 c1 ac a2 2c 51 79 f8 f0\ -40 42 2b 3c 5b af d4 0a 8f 21 cf 0f a5 a6 67 cc\ -d5 99 3d 42 db af b4 09 c5 20 e2 5f ce 2b 1e e1\ -e7 16 57 7f 1e fa 17 f3 da 28 05 2f 40 f0 41 9b\ -23 10 6d 78 45 aa f0 11 25 b6 98 e7 a4 df e9 2d\ -39 67 bb 00 c4 d0 d3 5b a3 55 2a b9 a8 b3 ee f0\ -7c 7f ec db c5 42 4a c4 db 1e 20 cb 37 d0 b2 74\ -47 69 94 0e a9 07 e1 7f bb ca 67 3b 20 52 23 80\ -c5 -Test: Verify -Comment: RSASSA-PSS Signature Example 8.2 -Message: \ -e2 f9 6e af 0e 05 e7 ba 32 6e cc a0 ba 7f d2 f7\ -c0 23 56 f3 ce de 9d 0f aa bf 4f cc 8e 60 a9 73\ -e5 59 5f d9 ea 08 -Salt: \ -43 5c 09 8a a9 90 9e b2 37 7f 12 48 b0 91 b6 89\ -87 ff 18 38 -Signature: \ -27 07 b9 ad 51 15 c5 8c 94 e9 32 e8 ec 0a 28 0f\ -56 33 9e 44 a1 b5 8d 4d dc ff 2f 31 2e 5f 34 dc\ -fe 39 e8 9c 6a 94 dc ee 86 db bd ae 5b 79 ba 4e\ -08 19 a9 e7 bf d9 d9 82 e7 ee 6c 86 ee 68 39 6e\ -8b 3a 14 c9 c8 f3 4b 17 8e b7 41 f9 d3 f1 21 10\ -9b f5 c8 17 2f ad a2 e7 68 f9 ea 14 33 03 2c 00\ -4a 8a a0 7e b9 90 00 0a 48 dc 94 c8 ba c8 aa be\ -2b 09 b1 aa 46 c0 a2 aa 0e 12 f6 3f bb a7 75 ba\ -7e -Test: Verify -Comment: RSASSA-PSS Signature Example 8.3 -Message: \ -e3 5c 6e d9 8f 64 a6 d5 a6 48 fc ab 8a db 16 33\ -1d b3 2e 5d 15 c7 4a 40 ed f9 4c 3d c4 a4 de 79\ -2d 19 08 89 f2 0f 1e 24 ed 12 05 4a 6b 28 79 8f\ -cb 42 d1 c5 48 76 9b 73 4c 96 37 31 42 09 2a ed\ -27 76 03 f4 73 8d f4 dc 14 46 58 6d 0e c6 4d a4\ -fb 60 53 6d b2 ae 17 fc 7e 3c 04 bb fb bb d9 07\ -bf 11 7c 08 63 6f a1 6f 95 f5 1a 62 16 93 4d 3e\ -34 f8 50 30 f1 7b bb c5 ba 69 14 40 58 af f0 81\ -e0 b1 9c f0 3c 17 19 5c 5e 88 8b a5 8f 6f e0 a0\ -2e 5c 3b da 97 19 a7 -Salt: \ -c6 eb be 76 df 0c 4a ea 32 c4 74 17 5b 2f 13 68\ -62 d0 45 29 -Signature: \ -2a d2 05 09 d7 8c f2 6d 1b 6c 40 61 46 08 6e 4b\ -0c 91 a9 1c 2b d1 64 c8 7b 96 6b 8f aa 42 aa 0c\ -a4 46 02 23 23 ba 4b 1a 1b 89 70 6d 7f 4c 3b e5\ -7d 7b 69 70 2d 16 8a b5 95 5e e2 90 35 6b 8c 4a\ -29 ed 46 7d 54 7e c2 3c ba df 28 6c cb 58 63 c6\ -67 9d a4 67 fc 93 24 a1 51 c7 ec 55 aa c6 db 40\ -84 f8 27 26 82 5c fe 1a a4 21 bc 64 04 9f b4 2f\ -23 14 8f 9c 25 b2 dc 30 04 37 c3 8d 42 8a a7 5f\ -96 -Test: Verify -Comment: RSASSA-PSS Signature Example 8.4 -Message: \ -db c5 f7 50 a7 a1 4b e2 b9 3e 83 8d 18 d1 4a 86\ -95 e5 2e 8a dd 9c 0a c7 33 b8 f5 6d 27 47 e5 29\ -a0 cc a5 32 dd 49 b9 02 ae fe d5 14 44 7f 9e 81\ -d1 61 95 c2 85 38 68 cb 9b 30 f7 d0 d4 95 c6 9d\ -01 b5 c5 d5 0b 27 04 5d b3 86 6c 23 24 a4 4a 11\ -0b 17 17 74 6d e4 57 d1 c8 c4 5c 3c d2 a9 29 70\ -c3 d5 96 32 05 5d 4c 98 a4 1d 6e 99 e2 a3 dd d5\ -f7 f9 97 9a b3 cd 18 f3 75 05 d2 51 41 de 2a 1b\ -ff 17 b3 a7 dc e9 41 9e cc 38 5c f1 1d 72 84 0f\ -19 95 3f d0 50 92 51 f6 ca fd e2 89 3d 0e 75 c7\ -81 ba 7a 50 12 ca 40 1a 4f a9 9e 04 b3 c3 24 9f\ -92 6d 5a fe 82 cc 87 da b2 2c 3c 1b 10 5d e4 8e\ -34 ac e9 c9 12 4e 59 59 7a c7 eb f8 -Salt: \ -02 1f dc c6 eb b5 e1 9b 1c b1 6e 9c 67 f2 76 81\ -65 7f e2 0a -Signature: \ -1e 24 e6 e5 86 28 e5 17 50 44 a9 eb 6d 83 7d 48\ -af 12 60 b0 52 0e 87 32 7d e7 89 7e e4 d5 b9 f0\ -df 0b e3 e0 9e d4 de a8 c1 45 4f f3 42 3b b0 8e\ -17 93 24 5a 9d f8 bf 6a b3 96 8c 8e dd c3 b5 32\ -85 71 c7 7f 09 1c c5 78 57 69 12 df eb d1 64 b9\ -de 54 54 fe 0b e1 c1 f6 38 5b 32 83 60 ce 67 ec\ -7a 05 f6 e3 0e b4 5c 17 c4 8a c7 00 41 d2 ca b6\ -7f 0a 2a e7 aa fd cc 8d 24 5e a3 44 2a 63 00 cc\ -c7 -Test: Verify -Comment: RSASSA-PSS Signature Example 8.5 -Message: \ -04 dc 25 1b e7 2e 88 e5 72 34 85 b6 38 3a 63 7e\ -2f ef e0 76 60 c5 19 a5 60 b8 bc 18 bd ed b8 6e\ -ae 23 64 ea 53 ba 9d ca 6e b3 d2 e7 d6 b8 06 af\ -42 b3 e8 7f 29 1b 4a 88 81 d5 bf 57 2c c9 a8 5e\ -19 c8 6a cb 28 f0 98 f9 da 03 83 c5 66 d3 c0 f5\ -8c fd 8f 39 5d cf 60 2e 5c d4 0e 8c 71 83 f7 14\ -99 6e 22 97 ef -Salt: \ -c5 58 d7 16 7c bb 45 08 ad a0 42 97 1e 71 b1 37\ -7e ea 42 69 -Signature: \ -33 34 1b a3 57 6a 13 0a 50 e2 a5 cf 86 79 22 43\ -88 d5 69 3f 5a cc c2 35 ac 95 ad d6 8e 5e b1 ee\ -c3 16 66 d0 ca 7a 1c da 6f 70 a1 aa 76 2c 05 75\ -2a 51 95 0c db 8a f3 c5 37 9f 18 cf e6 b5 bc 55\ -a4 64 82 26 a1 5e 91 2e f1 9a d7 7a de ea 91 1d\ -67 cf ef d6 9b a4 3f a4 11 91 35 ff 64 21 17 ba\ -98 5a 7e 01 00 32 5e 95 19 f1 ca 6a 92 16 bd a0\ -55 b5 78 50 15 29 11 25 e9 0d cd 07 a2 ca 96 73\ -ee -Test: Verify -Comment: RSASSA-PSS Signature Example 8.6 -Message: \ -0e a3 7d f9 a6 fe a4 a8 b6 10 37 3c 24 cf 39 0c\ -20 fa 6e 21 35 c4 00 c8 a3 4f 5c 18 3a 7e 8e a4\ -c9 ae 09 0e d3 17 59 f4 2d c7 77 19 cc a4 00 ec\ -dc c5 17 ac fc 7a c6 90 26 75 b2 ef 30 c5 09 66\ -5f 33 21 48 2f c6 9a 9f b5 70 d1 5e 01 c8 45 d0\ -d8 e5 0d 2a 24 cb f1 cf 0e 71 49 75 a5 db 7b 18\ -d9 e9 e9 cb 91 b5 cb 16 86 90 60 ed 18 b7 b5 62\ -45 50 3f 0c af 90 35 2b 8d e8 1c b5 a1 d9 c6 33\ -60 92 f0 cd -Salt: \ -76 fd 4e 64 fd c9 8e b9 27 a0 40 3e 35 a0 84 e7\ -6b a9 f9 2a -Signature: \ -1e d1 d8 48 fb 1e db 44 12 9b d9 b3 54 79 5a f9\ -7a 06 9a 7a 00 d0 15 10 48 59 3e 0c 72 c3 51 7f\ -f9 ff 2a 41 d0 cb 5a 0a c8 60 d7 36 a1 99 70 4f\ -7c b6 a5 39 86 a8 8b bd 8a bc c0 07 6a 2c e8 47\ -88 00 31 52 5d 44 9d a2 ac 78 35 63 74 c5 36 e3\ -43 fa a7 cb a4 2a 5a aa 65 06 08 77 91 c0 6a 8e\ -98 93 35 ae d1 9b fa b2 d5 e6 7e 27 fb 0c 28 75\ -af 89 6c 21 b6 e8 e7 30 9d 04 e4 f6 72 7e 69 46\ -3e -Test: Verify -Comment: Example 9: A 1536-bit RSA Key Pair -Modulus: \ -e6 bd 69 2a c9 66 45 79 04 03 fd d0 f5 be b8 b9\ -bf 92 ed 10 00 7f c3 65 04 64 19 dd 06 c0 5c 5b\ -5b 2f 48 ec f9 89 e4 ce 26 91 09 97 9c bb 40 b4\ -a0 ad 24 d2 24 83 d1 ee 31 5a d4 cc b1 53 42 68\ -35 26 91 c5 24 f6 dd 8e 6c 29 d2 24 cf 24 69 73\ -ae c8 6c 5b f6 b1 40 1a 85 0d 1b 9a d1 bb 8c bc\ -ec 47 b0 6f 0f 8c 7f 45 d3 fc 8f 31 92 99 c5 43\ -3d db c2 b3 05 3b 47 de d2 ec d4 a4 ca ef d6 14\ -83 3d c8 bb 62 2f 31 7e d0 76 b8 05 7f e8 de 3f\ -84 48 0a d5 e8 3e 4a 61 90 4a 4f 24 8f b3 97 02\ -73 57 e1 d3 0e 46 31 39 81 5c 6f d4 fd 5a c5 b8\ -17 2a 45 23 0e cb 63 18 a0 4f 14 55 d8 4e 5a 8b -PublicExponent: \ -01 00 01 -PrivateExponent: \ -6a 7f d8 4f b8 5f ad 07 3b 34 40 6d b7 4f 8d 61\ -a6 ab c1 21 96 a9 61 dd 79 56 5e 9d a6 e5 18 7b\ -ce 2d 98 02 50 f7 35 95 75 35 92 70 d9 15 90 bb\ -0e 42 7c 71 46 0b 55 d5 14 10 b1 91 bc f3 09 fe\ -a1 31 a9 2c 8e 70 27 38 fa 71 9f 1e 00 41 f5 2e\ -40 e9 1f 22 9f 4d 96 a1 e6 f1 72 e1 55 96 b4 51\ -0a 6d ae c2 61 05 f2 be bc 53 31 6b 87 bd f2 13\ -11 66 60 70 e8 df ee 69 d5 2c 71 a9 76 ca ae 79\ -c7 2b 68 d2 85 80 dc 68 6d 9f 51 29 d2 25 f8 2b\ -3d 61 55 13 a8 82 b3 db 91 41 6b 48 ce 08 88 82\ -13 e3 7e eb 9a f8 00 d8 1c ab 32 8c e4 20 68 99\ -03 c0 0c 7b 5f d3 1b 75 50 3a 6d 41 96 84 d6 29 -Prime1: \ -f8 eb 97 e9 8d f1 26 64 ee fd b7 61 59 6a 69 dd\ -cd 0e 76 da ec e6 ed 4b f5 a1 b5 0a c0 86 f7 92\ -8a 4d 2f 87 26 a7 7e 51 5b 74 da 41 98 8f 22 0b\ -1c c8 7a a1 fc 81 0c e9 9a 82 f2 d1 ce 82 1e dc\ -ed 79 4c 69 41 f4 2c 7a 1a 0b 8c 4d 28 c7 5e c6\ -0b 65 22 79 f6 15 4a 76 2a ed 16 5d 47 de e3 67 -Prime2: \ -ed 4d 71 d0 a6 e2 4b 93 c2 e5 f6 b4 bb e0 5f 5f\ -b0 af a0 42 d2 04 fe 33 78 d3 65 c2 f2 88 b6 a8\ -da d7 ef e4 5d 15 3e ef 40 ca cc 7b 81 ff 93 40\ -02 d1 08 99 4b 94 a5 e4 72 8c d9 c9 63 37 5a e4\ -99 65 bd a5 5c bf 0e fe d8 d6 55 3b 40 27 f2 d8\ -62 08 a6 e6 b4 89 c1 76 12 80 92 d6 29 e4 9d 3d -ModPrime1PrivateExponent: \ -2b b6 8b dd fb 0c 4f 56 c8 55 8b ff af 89 2d 80\ -43 03 78 41 e7 fa 81 cf a6 1a 38 c5 e3 9b 90 1c\ -8e e7 11 22 a5 da 22 27 bd 6c de eb 48 14 52 c1\ -2a d3 d6 1d 5e 4f 77 6a 0a b5 56 59 1b ef e3 e5\ -9e 5a 7f dd b8 34 5e 1f 2f 35 b9 f4 ce e5 7c 32\ -41 4c 08 6a ec 99 3e 93 53 e4 80 d9 ee c6 28 9f -ModPrime2PrivateExponent: \ -4f f8 97 70 9f ad 07 97 46 49 45 78 e7 0f d8 54\ -61 30 ee ab 56 27 c4 9b 08 0f 05 ee 4a d9 f3 e4\ -b7 cb a9 d6 a5 df f1 13 a4 1c 34 09 33 68 33 f1\ -90 81 6d 8a 6b c4 2e 9b ec 56 b7 56 7d 0f 3c 9c\ -69 6d b6 19 b2 45 d9 01 dd 85 6d b7 c8 09 2e 77\ -e9 a1 cc cd 56 ee 4d ba 42 c5 fd b6 1a ec 26 69 -MultiplicativeInverseOfPrime2ModPrime1: \ -77 b9 d1 13 7b 50 40 4a 98 27 29 31 6e fa fc 7d\ -fe 66 d3 4e 5a 18 26 00 d5 f3 0a 0a 85 12 05 1c\ -56 0d 08 1d 4d 0a 18 35 ec 3d 25 a6 0f 4e 4d 6a\ -a9 48 b2 bf 3d bb 5b 12 4c bb c3 48 92 55 a3 a9\ -48 37 2f 69 78 49 67 45 f9 43 e1 db 4f 18 38 2c\ -ea a5 05 df c6 57 57 bb 3f 85 7a 58 dc e5 21 56 -Test: KeyPairValidAndConsistent -Comment: RSASSA-PSS Signature Example 9.1 -Message: \ -a8 8e 26 58 55 e9 d7 ca 36 c6 87 95 f0 b3 1b 59\ -1c d6 58 7c 71 d0 60 a0 b3 f7 f3 ea ef 43 79 59\ -22 02 8b c2 b6 ad 46 7c fc 2d 7f 65 9c 53 85 aa\ -70 ba 36 72 cd de 4c fe 49 70 cc 79 04 60 1b 27\ -88 72 bf 51 32 1c 4a 97 2f 3c 95 57 0f 34 45 d4\ -f5 79 80 e0 f2 0d f5 48 46 e6 a5 2c 66 8f 12 88\ -c0 3f 95 00 6e a3 2f 56 2d 40 d5 2a f9 fe b3 2f\ -0f a0 6d b6 5b 58 8a 23 7b 34 e5 92 d5 5c f9 79\ -f9 03 a6 42 ef 64 d2 ed 54 2a a8 c7 7d c1 dd 76\ -2f 45 a5 93 03 ed 75 e5 41 ca 27 1e 2b 60 ca 70\ -9e 44 fa 06 61 13 1e 8d 5d 41 63 fd 8d 39 85 66\ -ce 26 de 87 30 e7 2f 9c ca 73 76 41 c2 44 15 94\ -20 63 70 28 df 0a 18 07 9d 62 08 ea 8b 47 11 a2\ -c7 50 f5 -Salt: \ -c0 a4 25 31 3d f8 d7 56 4b d2 43 4d 31 15 23 d5\ -25 7e ed 80 -Signature: \ -58 61 07 22 6c 3c e0 13 a7 c8 f0 4d 1a 6a 29 59\ -bb 4b 8e 20 5b a4 3a 27 b5 0f 12 41 11 bc 35 ef\ -58 9b 03 9f 59 32 18 7c b6 96 d7 d9 a3 2c 0c 38\ -30 0a 5c dd a4 83 4b 62 d2 eb 24 0a f3 3f 79 d1\ -3d fb f0 95 bf 59 9e 0d 96 86 94 8c 19 64 74 7b\ -67 e8 9c 9a ba 5c d8 50 16 23 6f 56 6c c5 80 2c\ -b1 3e ad 51 bc 7c a6 be f3 b9 4d cb db b1 d5 70\ -46 97 71 df 0e 00 b1 a8 a0 67 77 47 2d 23 16 27\ -9e da e8 64 74 66 8d 4e 1e ff f9 5f 1d e6 1c 60\ -20 da 32 ae 92 bb f1 65 20 fe f3 cf 4d 88 f6 11\ -21 f2 4b bd 9f e9 1b 59 ca f1 23 5b 2a 93 ff 81\ -fc 40 3a dd f4 eb de a8 49 34 a9 cd af 8e 1a 9e -Test: Verify -Comment: RSASSA-PSS Signature Example 9.2 -Message: \ -c8 c9 c6 af 04 ac da 41 4d 22 7e f2 3e 08 20 c3\ -73 2c 50 0d c8 72 75 e9 5b 0d 09 54 13 99 3c 26\ -58 bc 1d 98 85 81 ba 87 9c 2d 20 1f 14 cb 88 ce\ -d1 53 a0 19 69 a7 bf 0a 7b e7 9c 84 c1 48 6b c1\ -2b 3f a6 c5 98 71 b6 82 7c 8c e2 53 ca 5f ef a8\ -a8 c6 90 bf 32 6e 8e 37 cd b9 6d 90 a8 2e ba b6\ -9f 86 35 0e 18 22 e8 bd 53 6a 2e -Salt: \ -b3 07 c4 3b 48 50 a8 da c2 f1 5f 32 e3 78 39 ef\ -8c 5c 0e 91 -Signature: \ -80 b6 d6 43 25 52 09 f0 a4 56 76 38 97 ac 9e d2\ -59 d4 59 b4 9c 28 87 e5 88 2e cb 44 34 cf d6 6d\ -d7 e1 69 93 75 38 1e 51 cd 7f 55 4f 2c 27 17 04\ -b3 99 d4 2b 4b e2 54 0a 0e ca 61 95 1f 55 26 7f\ -7c 28 78 c1 22 84 2d ad b2 8b 01 bd 5f 8c 02 5f\ -7e 22 84 18 a6 73 c0 3d 6b c0 c7 36 d0 a2 95 46\ -bd 67 f7 86 d9 d6 92 cc ea 77 8d 71 d9 8c 20 63\ -b7 a7 10 92 18 7a 4d 35 af 10 81 11 d8 3e 83 ea\ -e4 6c 46 aa 34 27 7e 06 04 45 89 90 37 88 f1 d5\ -e7 ce e2 5f b4 85 e9 29 49 11 88 14 d6 f2 c3 ee\ -36 14 89 01 6f 32 7f b5 bc 51 7e b5 04 70 bf fa\ -1a fa 5f 4c e9 aa 0c e5 b8 ee 19 bf 55 01 b9 58 -Test: Verify -Comment: RSASSA-PSS Signature Example 9.3 -Message: \ -0a fa d4 2c cd 4f c6 06 54 a5 50 02 d2 28 f5 2a\ -4a 5f e0 3b 8b bb 08 ca 82 da ca 55 8b 44 db e1\ -26 6e 50 c0 e7 45 a3 6d 9d 29 04 e3 40 8a bc d1\ -fd 56 99 94 06 3f 4a 75 cc 72 f2 fe e2 a0 cd 89\ -3a 43 af 1c 5b 8b 48 7d f0 a7 16 10 02 4e 4f 6d\ -df 9f 28 ad 08 13 c1 aa b9 1b cb 3c 90 64 d5 ff\ -74 2d ef fe a6 57 09 41 39 36 9e 5e a6 f4 a9 63\ -19 a5 cc 82 24 14 5b 54 50 62 75 8f ef d1 fe 34\ -09 ae 16 92 59 c6 cd fd 6b 5f 29 58 e3 14 fa ec\ -be 69 d2 ca ce 58 ee 55 17 9a b9 b3 e6 d1 ec c1\ -4a 55 7c 5f eb e9 88 59 52 64 fc 5d a1 c5 71 46\ -2e ca 79 8a 18 a1 a4 94 0c da b4 a3 e9 20 09 cc\ -d4 2e 1e 94 7b 13 14 e3 22 38 a2 de ce 7d 23 a8\ -9b 5b 30 c7 51 fd 0a 4a 43 0d 2c 54 85 94 -Salt: \ -9a 2b 00 7e 80 97 8b bb 19 2c 35 4e b7 da 9a ed\ -fc 74 db f5 -Signature: \ -48 44 08 f3 89 8c d5 f5 34 83 f8 08 19 ef bf 27\ -08 c3 4d 27 a8 b2 a6 fa e8 b3 22 f9 24 02 37 f9\ -81 81 7a ca 18 46 f1 08 4d aa 6d 7c 07 95 f6 e5\ -bf 1a f5 9c 38 e1 85 84 37 ce 1f 7e c4 19 b9 8c\ -87 36 ad f6 dd 9a 00 b1 80 6d 2b d3 ad 0a 73 77\ -5e 05 f5 2d fe f3 a5 9a b4 b0 81 43 f0 df 05 cd\ -1a d9 d0 4b ec ec a6 da a4 a2 12 98 03 e2 00 cb\ -c7 77 87 ca f4 c1 d0 66 3a 6c 59 87 b6 05 95 20\ -19 78 2c af 2e c1 42 6d 68 fb 94 ed 1d 4b e8 16\ -a7 ed 08 1b 77 e6 ab 33 0b 3f fc 07 38 20 fe cd\ -e3 72 7f cb e2 95 ee 61 a0 50 a3 43 65 86 37 c3\ -fd 65 9c fb 63 73 6d e3 2d 9f 90 d3 c2 f6 3e ca -Test: Verify -Comment: RSASSA-PSS Signature Example 9.4 -Message: \ -1d fd 43 b4 6c 93 db 82 62 9b da e2 bd 0a 12 b8\ -82 ea 04 c3 b4 65 f5 cf 93 02 3f 01 05 96 26 db\ -be 99 f2 6b b1 be 94 9d dd d1 6d c7 f3 de bb 19\ -a1 94 62 7f 0b 22 44 34 df 7d 87 00 e9 e9 8b 06\ -e3 60 c1 2f db e3 d1 9f 51 c9 68 4e b9 08 9e cb\ -b0 a2 f0 45 03 99 d3 f5 9e ac 72 94 08 5d 04 4f\ -53 93 c6 ce 73 74 23 d8 b8 6c 41 53 70 d3 89 e3\ -0b 9f 0a 3c 02 d2 5d 00 82 e8 ad 6f 3f 1e f2 4a\ -45 c3 cf 82 b3 83 36 70 63 a4 d4 61 3e 42 64 f0\ -1b 2d ac 2e 5a a4 20 43 f8 fb 5f 69 fa 87 1d 14\ -fb 27 3e 76 7a 53 1c 40 f0 2f 34 3b c2 fb 45 a0\ -c7 e0 f6 be 25 61 92 3a 77 21 1d 66 a6 e2 db b4\ -3c 36 63 50 be ae 22 da 3a c2 c1 f5 07 70 96 fc\ -b5 c4 bf 25 5f 75 74 35 1a e0 b1 e1 f0 36 32 81\ -7c 08 56 d4 a8 ba 97 af bd c8 b8 58 55 40 2b c5\ -69 26 fc ec 20 9f 9e a8 -Salt: \ -70 f3 82 bd df 4d 5d 2d d8 8b 3b c7 b7 30 8b e6\ -32 b8 40 45 -Signature: \ -84 eb eb 48 1b e5 98 45 b4 64 68 ba fb 47 1c 01\ -12 e0 2b 23 5d 84 b5 d9 11 cb d1 92 6e e5 07 4a\ -e0 42 44 95 cb 20 e8 23 08 b8 eb b6 5f 41 9a 03\ -fb 40 e7 2b 78 98 1d 88 aa d1 43 05 36 85 17 2c\ -97 b2 9c 8b 7b f0 ae 73 b5 b2 26 3c 40 3d a0 ed\ -2f 80 ff 74 50 af 78 28 eb 8b 86 f0 02 8b d2 a8\ -b1 76 a4 d2 28 cc ce a1 83 94 f2 38 b0 9f f7 58\ -cc 00 bc 04 30 11 52 35 57 42 f2 82 b5 4e 66 3a\ -91 9e 70 9d 8d a2 4a de 55 00 a7 b9 aa 50 22 6e\ -0c a5 29 23 e6 c2 d8 60 ec 50 ff 48 0f a5 74 77\ -e8 2b 05 65 f4 37 9f 79 c7 72 d5 c2 da 80 af 9f\ -bf 32 5e ce 6f c2 0b 00 96 16 14 be e8 9a 18 3e -Test: Verify -Comment: RSASSA-PSS Signature Example 9.5 -Message: \ -1b dc 6e 7c 98 fb 8c f5 4e 9b 09 7b 66 a8 31 e9\ -cf e5 2d 9d 48 88 44 8e e4 b0 97 80 93 ba 1d 7d\ -73 ae 78 b3 a6 2b a4 ad 95 cd 28 9c cb 9e 00 52\ -26 bb 3d 17 8b cc aa 82 1f b0 44 a4 e2 1e e9 76\ -96 c1 4d 06 78 c9 4c 2d ae 93 b0 ad 73 92 22 18\ -55 3d aa 7e 44 eb e5 77 25 a7 a4 5c c7 2b 9b 21\ -38 a6 b1 7c 8d b4 11 ce 82 79 ee 12 41 af f0 a8\ -be c6 f7 7f 87 ed b0 c6 9c b2 72 36 e3 43 5a 80\ -0b 19 2e 4f 11 e5 19 e3 fe 30 fc 30 ea cc ca 4f\ -bb 41 76 90 29 bf 70 8e 81 7a 9e 68 38 05 be 67\ -fa 10 09 84 68 3b 74 83 8e 3b cf fa 79 36 6e ed\ -1d 48 1c 76 72 91 18 83 8f 31 ba 8a 04 8a 93 c1\ -be 44 24 59 8e 8d f6 32 8b 7a 77 88 0a 3f 9c 7e\ -2e 8d fc a8 eb 5a 26 fb 86 bd c5 56 d4 2b be 01\ -d9 fa 6e d8 06 46 49 1c 93 41 -Salt: \ -d6 89 25 7a 86 ef fa 68 21 2c 5e 0c 61 9e ca 29\ -5f b9 1b 67 -Signature: \ -82 10 2d f8 cb 91 e7 17 99 19 a0 4d 26 d3 35 d6\ -4f bc 2f 87 2c 44 83 39 43 24 1d e8 45 48 10 27\ -4c df 3d b5 f4 2d 42 3d b1 52 af 71 35 f7 01 42\ -0e 39 b4 94 a6 7c bf d1 9f 91 19 da 23 3a 23 da\ -5c 64 39 b5 ba 0d 2b c3 73 ee e3 50 70 01 37 8d\ -4a 40 73 85 6b 7f e2 ab a0 b5 ee 93 b2 7f 4a fe\ -c7 d4 d1 20 92 1c 83 f6 06 76 5b 02 c1 9e 4d 6a\ -1a 3b 95 fa 4c 42 29 51 be 4f 52 13 10 77 ef 17\ -17 97 29 cd df bd b5 69 50 db ac ee fe 78 cb 16\ -64 0a 09 9e a5 6d 24 38 9e ef 10 f8 fe cb 31 ba\ -3e a3 b2 27 c0 a8 66 98 bb 89 e3 e9 36 39 05 bf\ -22 77 7b 2a 3a a5 21 b6 5b 4c ef 76 d8 3b de 4c -Test: Verify -Comment: RSASSA-PSS Signature Example 9.6 -Message: \ -88 c7 a9 f1 36 04 01 d9 0e 53 b1 01 b6 1c 53 25\ -c3 c7 5d b1 b4 11 fb eb 8e 83 0b 75 e9 6b 56 67\ -0a d2 45 40 4e 16 79 35 44 ee 35 4b c6 13 a9 0c\ -c9 84 87 15 a7 3d b5 89 3e 7f 6d 27 98 15 c0 c1\ -de 83 ef 8e 29 56 e3 a5 6e d2 6a 88 8d 7a 9c dc\ -d0 42 f4 b1 6b 7f a5 1e f1 a0 57 36 62 d1 6a 30\ -2d 0e c5 b2 85 d2 e0 3a d9 65 29 c8 7b 3d 37 4d\ -b3 72 d9 5b 24 43 d0 61 b6 b1 a3 50 ba 87 80 7e\ -d0 83 af d1 eb 05 c3 f5 2f 4e ba 5e d2 22 77 14\ -fd b5 0b 9d 9d 9d d6 81 4f 62 f6 27 2f cd 5c db\ -ce 7a 9e f7 97 -Salt: \ -c2 5f 13 bf 67 d0 81 67 1a 04 81 a1 f1 82 0d 61\ -3b ba 22 76 -Signature: \ -a7 fd b0 d2 59 16 5c a2 c8 8d 00 bb f1 02 8a 86\ -7d 33 76 99 d0 61 19 3b 17 a9 64 8e 14 cc bb aa\ -de ac aa cd ec 81 5e 75 71 29 4e bb 8a 11 7a f2\ -05 fa 07 8b 47 b0 71 2c 19 9e 3a d0 51 35 c5 04\ -c2 4b 81 70 51 15 74 08 02 48 79 92 ff d5 11 d4\ -af c6 b8 54 49 1e b3 f0 dd 52 31 39 54 2f f1 5c\ -31 01 ee 85 54 35 17 c6 a3 c7 94 17 c6 7e 2d d9\ -aa 74 1e 9a 29 b0 6d cb 59 3c 23 36 b3 67 0a e3\ -af ba c7 c3 e7 6e 21 54 73 e8 66 e3 38 ca 24 4d\ -e0 0b 62 62 4d 6b 94 26 82 2c ea e9 f8 cc 46 08\ -95 f4 12 50 07 3f d4 5c 5a 1e 7b 42 5c 20 4a 42\ -3a 69 91 59 f6 90 3e 71 0b 37 a7 bb 2b c8 04 9f -Test: Verify -Comment: Example 10: A 2048-bit RSA Key Pair -Modulus: \ -a5 dd 86 7a c4 cb 02 f9 0b 94 57 d4 8c 14 a7 70\ -ef 99 1c 56 c3 9c 0e c6 5f d1 1a fa 89 37 ce a5\ -7b 9b e7 ac 73 b4 5c 00 17 61 5b 82 d6 22 e3 18\ -75 3b 60 27 c0 fd 15 7b e1 2f 80 90 fe e2 a7 ad\ -cd 0e ef 75 9f 88 ba 49 97 c7 a4 2d 58 c9 aa 12\ -cb 99 ae 00 1f e5 21 c1 3b b5 43 14 45 a8 d5 ae\ -4f 5e 4c 7e 94 8a c2 27 d3 60 40 71 f2 0e 57 7e\ -90 5f be b1 5d fa f0 6d 1d e5 ae 62 53 d6 3a 6a\ -21 20 b3 1a 5d a5 da bc 95 50 60 0e 20 f2 7d 37\ -39 e2 62 79 25 fe a3 cc 50 9f 21 df f0 4e 6e ea\ -45 49 c5 40 d6 80 9f f9 30 7e ed e9 1f ff 58 73\ -3d 83 85 a2 37 d6 d3 70 5a 33 e3 91 90 09 92 07\ -0d f7 ad f1 35 7c f7 e3 70 0c e3 66 7d e8 3f 17\ -b8 df 17 78 db 38 1d ce 09 cb 4a d0 58 a5 11 00\ -1a 73 81 98 ee 27 cf 55 a1 3b 75 45 39 90 65 82\ -ec 8b 17 4b d5 8d 5d 1f 3d 76 7c 61 37 21 ae 05 -PublicExponent: \ -01 00 01 -PrivateExponent: \ -2d 2f f5 67 b3 fe 74 e0 61 91 b7 fd ed 6d e1 12\ -29 0c 67 06 92 43 0d 59 69 18 40 47 da 23 4c 96\ -93 de ed 16 73 ed 42 95 39 c9 69 d3 72 c0 4d 6b\ -47 e0 f5 b8 ce e0 84 3e 5c 22 83 5d bd 3b 05 a0\ -99 79 84 ae 60 58 b1 1b c4 90 7c bf 67 ed 84 fa\ -9a e2 52 df b0 d0 cd 49 e6 18 e3 5d fd fe 59 bc\ -a3 dd d6 6c 33 ce bb c7 7a d4 41 aa 69 5e 13 e3\ -24 b5 18 f0 1c 60 f5 a8 5c 99 4a d1 79 f2 a6 b5\ -fb e9 34 02 b1 17 67 be 01 bf 07 34 44 d6 ba 1d\ -d2 bc a5 bd 07 4d 4a 5f ae 35 31 ad 13 03 d8 4b\ -30 d8 97 31 8c bb ba 04 e0 3c 2e 66 de 6d 91 f8\ -2f 96 ea 1d 4b b5 4a 5a ae 10 2d 59 46 57 f5 c9\ -78 95 53 51 2b 29 6d ea 29 d8 02 31 96 35 7e 3e\ -3a 6e 95 8f 39 e3 c2 34 40 38 ea 60 4b 31 ed c6\ -f0 f7 ff 6e 71 81 a5 7c 92 82 6a 26 8f 86 76 8e\ -96 f8 78 56 2f c7 1d 85 d6 9e 44 86 12 f7 04 8f -Prime1: \ -cf d5 02 83 fe ee b9 7f 6f 08 d7 3c bc 7b 38 36\ -f8 2b bc d4 99 47 9f 5e 6f 76 fd fc b8 b3 8c 4f\ -71 dc 9e 88 bd 6a 6f 76 37 1a fd 65 d2 af 18 62\ -b3 2a fb 34 a9 5f 71 b8 b1 32 04 3f fe be 3a 95\ -2b af 75 92 44 81 48 c0 3f 9c 69 b1 d6 8e 4c e5\ -cf 32 c8 6b af 46 fe d3 01 ca 1a b4 03 06 9b 32\ -f4 56 b9 1f 71 89 8a b0 81 cd 8c 42 52 ef 52 71\ -91 5c 97 94 b8 f2 95 85 1d a7 51 0f 99 cb 73 eb -Prime2: \ -cc 4e 90 d2 a1 b3 a0 65 d3 b2 d1 f5 a8 fc e3 1b\ -54 44 75 66 4e ab 56 1d 29 71 b9 9f b7 be f8 44\ -e8 ec 1f 36 0b 8c 2a c8 35 96 92 97 1e a6 a3 8f\ -72 3f cc 21 1f 5d bc b1 77 a0 fd ac 51 64 a1 d4\ -ff 7f bb 4e 82 99 86 35 3c b9 83 65 9a 14 8c dd\ -42 0c 7d 31 ba 38 22 ea 90 a3 2b e4 6c 03 0e 8c\ -17 e1 fa 0a d3 78 59 e0 6b 0a a6 fa 3b 21 6d 9c\ -be 6c 0e 22 33 97 69 c0 a6 15 91 3e 5d a7 19 cf -ModPrime1PrivateExponent: \ -1c 2d 1f c3 2f 6b c4 00 4f d8 5d fd e0 fb bf 9a\ -4c 38 f9 c7 c4 e4 1d ea 1a a8 82 34 a2 01 cd 92\ -f3 b7 da 52 65 83 a9 8a d8 5b b3 60 fb 98 3b 71\ -1e 23 44 9d 56 1d 17 78 d7 a5 15 48 6b cb f4 7b\ -46 c9 e9 e1 a3 a1 f7 70 00 ef be b0 9a 8a fe 47\ -e5 b8 57 cd a9 9c b1 6d 7f ff 9b 71 2e 3b d6 0c\ -a9 6d 9c 79 73 d6 16 d4 69 34 a9 c0 50 28 1c 00\ -43 99 ce ff 1d b7 dd a7 87 66 a8 a9 b9 cb 08 73 -ModPrime2PrivateExponent: \ -cb 3b 3c 04 ca a5 8c 60 be 7d 9b 2d eb b3 e3 96\ -43 f4 f5 73 97 be 08 23 6a 1e 9e af aa 70 65 36\ -e7 1c 3a cf e0 1c c6 51 f2 3c 9e 05 85 8f ee 13\ -bb 6a 8a fc 47 df 4e dc 9a 4b a3 0b ce cb 73 d0\ -15 78 52 32 7e e7 89 01 5c 2e 8d ee 7b 9f 05 a0\ -f3 1a c9 4e b6 17 31 64 74 0c 5c 95 14 7c d5 f3\ -b5 ae 2c b4 a8 37 87 f0 1d 8a b3 1f 27 c2 d0 ee\ -a2 dd 8a 11 ab 90 6a ba 20 7c 43 c6 ee 12 53 31 -MultiplicativeInverseOfPrime2ModPrime1: \ -12 f6 b2 cf 13 74 a7 36 fa d0 56 16 05 0f 96 ab\ -4b 61 d1 17 7c 7f 9d 52 5a 29 f3 d1 80 e7 76 67\ -e9 9d 99 ab f0 52 5d 07 58 66 0f 37 52 65 5b 0f\ -25 b8 df 84 31 d9 a8 ff 77 c1 6c 12 a0 a5 12 2a\ -9f 0b f7 cf d5 a2 66 a3 5c 15 9f 99 12 08 b9 03\ -16 ff 44 4f 3e 0b 6b d0 e9 3b 8a 7a 24 48 e9 57\ -e3 dd a6 cf cf 22 66 b1 06 01 3a c4 68 08 d3 b3\ -88 7b 3b 00 34 4b aa c9 53 0b 4c e7 08 fc 32 b6 -Test: KeyPairValidAndConsistent -Comment: RSASSA-PSS Signature Example 10.1 -Message: \ -88 31 77 e5 12 6b 9b e2 d9 a9 68 03 27 d5 37 0c\ -6f 26 86 1f 58 20 c4 3d a6 7a 3a d6 09 -Salt: \ -04 e2 15 ee 6f f9 34 b9 da 70 d7 73 0c 87 34 ab\ -fc ec de 89 -Signature: \ -82 c2 b1 60 09 3b 8a a3 c0 f7 52 2b 19 f8 73 54\ -06 6c 77 84 7a bf 2a 9f ce 54 2d 0e 84 e9 20 c5\ -af b4 9f fd fd ac e1 65 60 ee 94 a1 36 96 01 14\ -8e ba d7 a0 e1 51 cf 16 33 17 91 a5 72 7d 05 f2\ -1e 74 e7 eb 81 14 40 20 69 35 d7 44 76 5a 15 e7\ -9f 01 5c b6 6c 53 2c 87 a6 a0 59 61 c8 bf ad 74\ -1a 9a 66 57 02 28 94 39 3e 72 23 73 97 96 c0 2a\ -77 45 5d 0f 55 5b 0e c0 1d df 25 9b 62 07 fd 0f\ -d5 76 14 ce f1 a5 57 3b aa ff 4e c0 00 69 95 16\ -59 b8 5f 24 30 0a 25 16 0c a8 52 2d c6 e6 72 7e\ -57 d0 19 d7 e6 36 29 b8 fe 5e 89 e2 5c c1 5b eb\ -3a 64 75 77 55 92 99 28 0b 9b 28 f7 9b 04 09 00\ -0b e2 5b bd 96 40 8b a3 b4 3c c4 86 18 4d d1 c8\ -e6 25 53 fa 1a f4 04 0f 60 66 3d e7 f5 e4 9c 04\ -38 8e 25 7f 1c e8 9c 95 da b4 8a 31 5d 9b 66 b1\ -b7 62 82 33 87 6f f2 38 52 30 d0 70 d0 7e 16 66 -Comment: RSASSA-PSS Signature Example 10.2 -Message: \ -dd 67 0a 01 46 58 68 ad c9 3f 26 13 19 57 a5 0c\ -52 fb 77 7c db aa 30 89 2c 9e 12 36 11 64 ec 13\ -97 9d 43 04 81 18 e4 44 5d b8 7b ee 58 dd 98 7b\ -34 25 d0 20 71 d8 db ae 80 70 8b 03 9d bb 64 db\ -d1 de 56 57 d9 fe d0 c1 18 a5 41 43 74 2e 0f f3\ -c8 7f 74 e4 58 57 64 7a f3 f7 9e b0 a1 4c 9d 75\ -ea 9a 1a 04 b7 cf 47 8a 89 7a 70 8f d9 88 f4 8e\ -80 1e db 0b 70 39 df 8c 23 bb 3c 56 f4 e8 21 ac -Salt: \ -8b 2b dd 4b 40 fa f5 45 c7 78 dd f9 bc 1a 49 cb\ -57 f9 b7 1b -Signature: \ -14 ae 35 d9 dd 06 ba 92 f7 f3 b8 97 97 8a ed 7c\ -d4 bf 5f f0 b5 85 a4 0b d4 6c e1 b4 2c d2 70 30\ -53 bb 90 44 d6 4e 81 3d 8f 96 db 2d d7 00 7d 10\ -11 8f 6f 8f 84 96 09 7a d7 5e 1f f6 92 34 1b 28\ -92 ad 55 a6 33 a1 c5 5e 7f 0a 0a d5 9a 0e 20 3a\ -5b 82 78 ae c5 4d d8 62 2e 28 31 d8 71 74 f8 ca\ -ff 43 ee 6c 46 44 53 45 d8 4a 59 65 9b fb 92 ec\ -d4 c8 18 66 86 95 f3 47 06 f6 68 28 a8 99 59 63\ -7f 2b f3 e3 25 1c 24 bd ba 4d 4b 76 49 da 00 22\ -21 8b 11 9c 84 e7 9a 65 27 ec 5b 8a 5f 86 1c 15\ -99 52 e2 3e c0 5e 1e 71 73 46 fa ef e8 b1 68 68\ -25 bd 2b 26 2f b2 53 10 66 c0 de 09 ac de 2e 42\ -31 69 07 28 b5 d8 5e 11 5a 2f 6b 92 b7 9c 25 ab\ -c9 bd 93 99 ff 8b cf 82 5a 52 ea 1f 56 ea 76 dd\ -26 f4 3b aa fa 18 bf a9 2a 50 4c bd 35 69 9e 26\ -d1 dc c5 a2 88 73 85 f3 c6 32 32 f0 6f 32 44 c3 -Comment: RSASSA-PSS Signature Example 10.3 -Message: \ -48 b2 b6 a5 7a 63 c8 4c ea 85 9d 65 c6 68 28 4b\ -08 d9 6b dc aa be 25 2d b0 e4 a9 6c b1 ba c6 01\ -93 41 db 6f be fb 8d 10 6b 0e 90 ed a6 bc c6 c6\ -26 2f 37 e7 ea 9c 7e 5d 22 6b d7 df 85 ec 5e 71\ -ef ff 2f 54 c5 db 57 7f f7 29 ff 91 b8 42 49 1d\ -e2 74 1d 0c 63 16 07 df 58 6b 90 5b 23 b9 1a f1\ -3d a1 23 04 bf 83 ec a8 a7 3e 87 1f f9 db -Salt: \ -4e 96 fc 1b 39 8f 92 b4 46 71 01 0c 0d c3 ef d6\ -e2 0c 2d 73 -Signature: \ -6e 3e 4d 7b 6b 15 d2 fb 46 01 3b 89 00 aa 5b bb\ -39 39 cf 2c 09 57 17 98 70 42 02 6e e6 2c 74 c5\ -4c ff d5 d7 d5 7e fb bf 95 0a 0f 5c 57 4f a0 9d\ -3f c1 c9 f5 13 b0 5b 4f f5 0d d8 df 7e df a2 01\ -02 85 4c 35 e5 92 18 01 19 a7 0c e5 b0 85 18 2a\ -a0 2d 9e a2 aa 90 d1 df 03 f2 da ae 88 5b a2 f5\ -d0 5a fd ac 97 47 6f 06 b9 3b 5b c9 4a 1a 80 aa\ -91 16 c4 d6 15 f3 33 b0 98 89 2b 25 ff ac e2 66\ -f5 db 5a 5a 3b cc 10 a8 24 ed 55 aa d3 5b 72 78\ -34 fb 8c 07 da 28 fc f4 16 a5 d9 b2 22 4f 1f 8b\ -44 2b 36 f9 1e 45 6f de a2 d7 cf e3 36 72 68 de\ -03 07 a4 c7 4e 92 41 59 ed 33 39 3d 5e 06 55 53\ -1c 77 32 7b 89 82 1b de df 88 01 61 c7 8c d4 19\ -6b 54 19 f7 ac c3 f1 3e 5e bf 16 1b 6e 7c 67 24\ -71 6c a3 3b 85 c2 e2 56 40 19 2a c2 85 96 51 d5\ -0b de 7e b9 76 e5 1c ec 82 8b 98 b6 56 3b 86 bb -Comment: RSASSA-PSS Signature Example 10.4 -Message: \ -0b 87 77 c7 f8 39 ba f0 a6 4b bb db c5 ce 79 75\ -5c 57 a2 05 b8 45 c1 74 e2 d2 e9 05 46 a0 89 c4\ -e6 ec 8a df fa 23 a7 ea 97 ba e6 b6 5d 78 2b 82\ -db 5d 2b 5a 56 d2 2a 29 a0 5e 7c 44 33 e2 b8 2a\ -62 1a bb a9 0a dd 05 ce 39 3f c4 8a 84 05 42 45\ -1a -Salt: \ -c7 cd 69 8d 84 b6 51 28 d8 83 5e 3a 8b 1e b0 e0\ -1c b5 41 ec -Signature: \ -34 04 7f f9 6c 4d c0 dc 90 b2 d4 ff 59 a1 a3 61\ -a4 75 4b 25 5d 2e e0 af 7d 8b f8 7c 9b c9 e7 dd\ -ee de 33 93 4c 63 ca 1c 0e 3d 26 2c b1 45 ef 93\ -2a 1f 2c 0a 99 7a a6 a3 4f 8e ae e7 47 7d 82 cc\ -f0 90 95 a6 b8 ac ad 38 d4 ee c9 fb 7e ab 7a d0\ -2d a1 d1 1d 8e 54 c1 82 5e 55 bf 58 c2 a2 32 34\ -b9 02 be 12 4f 9e 90 38 a8 f6 8f a4 5d ab 72 f6\ -6e 09 45 bf 1d 8b ac c9 04 4c 6f 07 09 8c 9f ce\ -c5 8a 3a ab 10 0c 80 51 78 15 5f 03 0a 12 4c 45\ -0e 5a cb da 47 d0 e4 f1 0b 80 a2 3f 80 3e 77 4d\ -02 3b 00 15 c2 0b 9f 9b be 7c 91 29 63 38 d5 ec\ -b4 71 ca fb 03 20 07 b6 7a 60 be 5f 69 50 4a 9f\ -01 ab b3 cb 46 7b 26 0e 2b ce 86 0b e8 d9 5b f9\ -2c 0c 8e 14 96 ed 1e 52 85 93 a4 ab b6 df 46 2d\ -de 8a 09 68 df fe 46 83 11 68 57 a2 32 f5 eb f6\ -c8 5b e2 38 74 5a d0 f3 8f 76 7a 5f db f4 86 fb -Comment: RSASSA-PSS Signature Example 10.5 -Message: \ -f1 03 6e 00 8e 71 e9 64 da dc 92 19 ed 30 e1 7f\ -06 b4 b6 8a 95 5c 16 b3 12 b1 ed df 02 8b 74 97\ -6b ed 6b 3f 6a 63 d4 e7 78 59 24 3c 9c cc dc 98\ -01 65 23 ab b0 24 83 b3 55 91 c3 3a ad 81 21 3b\ -b7 c7 bb 1a 47 0a ab c1 0d 44 25 6c 4d 45 59 d9\ -16 -Salt: \ -ef a8 bf f9 62 12 b2 f4 a3 f3 71 a1 0d 57 41 52\ -65 5f 5d fb -Signature: \ -7e 09 35 ea 18 f4 d6 c1 d1 7c e8 2e b2 b3 83 6c\ -55 b3 84 58 9c e1 9d fe 74 33 63 ac 99 48 d1 f3\ -46 b7 bf dd fe 92 ef d7 8a db 21 fa ef c8 9a de\ -42 b1 0f 37 40 03 fe 12 2e 67 42 9a 1c b8 cb d1\ -f8 d9 01 45 64 c4 4d 12 01 16 f4 99 0f 1a 6e 38\ -77 4c 19 4b d1 b8 21 32 86 b0 77 b0 49 9d 2e 7b\ -3f 43 4a b1 22 89 c5 56 68 4d ee d7 81 31 93 4b\ -b3 dd 65 37 23 6f 7c 6f 3d cb 09 d4 76 be 07 72\ -1e 37 e1 ce ed 9b 2f 7b 40 68 87 bd 53 15 73 05\ -e1 c8 b4 f8 4d 73 3b c1 e1 86 fe 06 cc 59 b6 ed\ -b8 f4 bd 7f fe fd f4 f7 ba 9c fb 9d 57 06 89 b5\ -a1 a4 10 9a 74 6a 69 08 93 db 37 99 25 5a 0c b9\ -21 5d 2d 1c d4 90 59 0e 95 2e 8c 87 86 aa 00 11\ -26 52 52 47 0c 04 1d fb c3 ee c7 c3 cb f7 1c 24\ -86 9d 11 5c 0c b4 a9 56 f5 6d 53 0b 80 ab 58 9a\ -cf ef c6 90 75 1d df 36 e8 d3 83 f8 3c ed d2 cc -Comment: RSASSA-PSS Signature Example 10.6 -Message: \ -25 f1 08 95 a8 77 16 c1 37 45 0b b9 51 9d fa a1\ -f2 07 fa a9 42 ea 88 ab f7 1e 9c 17 98 00 85 b5\ -55 ae ba b7 62 64 ae 2a 3a b9 3c 2d 12 98 11 91\ -dd ac 6f b5 94 9e b3 6a ee 3c 5d a9 40 f0 07 52\ -c9 16 d9 46 08 fa 7d 97 ba 6a 29 15 b6 88 f2 03\ -23 d4 e9 d9 68 01 d8 9a 72 ab 58 92 dc 21 17 c0\ -74 34 fc f9 72 e0 58 cf 8c 41 ca 4b 4f f5 54 f7\ -d5 06 8a d3 15 5f ce d0 f3 12 5b c0 4f 91 93 37\ -8a 8f 5c 4c 3b 8c b4 dd 6d 1c c6 9d 30 ec ca 6e\ -aa 51 e3 6a 05 73 0e 9e 34 2e 85 5b af 09 9d ef\ -b8 af d7 -Salt: \ -ad 8b 15 23 70 36 46 22 4b 66 0b 55 08 85 91 7c\ -a2 d1 df 28 -Signature: \ -6d 3b 5b 87 f6 7e a6 57 af 21 f7 54 41 97 7d 21\ -80 f9 1b 2c 5f 69 2d e8 29 55 69 6a 68 67 30 d9\ -b9 77 8d 97 07 58 cc b2 60 71 c2 20 9f fb d6 12\ -5b e2 e9 6e a8 1b 67 cb 9b 93 08 23 9f da 17 f7\ -b2 b6 4e cd a0 96 b6 b9 35 64 0a 5a 1c b4 2a 91\ -55 b1 c9 ef 7a 63 3a 02 c5 9f 0d 6e e5 9b 85 2c\ -43 b3 50 29 e7 3c 94 0f f0 41 0e 8f 11 4e ed 46\ -bb d0 fa e1 65 e4 2b e2 52 8a 40 1c 3b 28 fd 81\ -8e f3 23 2d ca 9f 4d 2a 0f 51 66 ec 59 c4 23 96\ -d6 c1 1d bc 12 15 a5 6f a1 71 69 db 95 75 34 3e\ -f3 4f 9d e3 2a 49 cd c3 17 49 22 f2 29 c2 3e 18\ -e4 5d f9 35 31 19 ec 43 19 ce dc e7 a1 7c 64 08\ -8c 1f 6f 52 be 29 63 41 00 b3 91 9d 38 f3 d1 ed\ -94 e6 89 1e 66 a7 3b 8f b8 49 f5 87 4d f5 94 59\ -e2 98 c7 bb ce 2e ee 78 2a 19 5a a6 6f e2 d0 73\ -2b 25 e5 95 f5 7d 3e 06 1b 1f c3 e4 06 3b f9 8f -Test: Verify diff --git a/embeddedcryptopp/TestVectors/rw.txt b/embeddedcryptopp/TestVectors/rw.txt deleted file mode 100644 index 2d932d0..0000000 --- a/embeddedcryptopp/TestVectors/rw.txt +++ /dev/null @@ -1,166 +0,0 @@ -AlgorithmType: Signature -Name: RW/EMSA2(SHA-1) -Source: generated by Wei Dai using Crypto++ 5.1 -Comment: 1024-bit RW key -KeyFormat: Component -Modulus: \ - e5eb47bc1f82db3001faaeabc5bbe71b7d307b431889ac10255262281ec5f5af\ - 8a790bd7bbec5efffa442cf2c3fd5ca4778763b9d15aeac0b9b71bdb13da8272\ - 7f4967ac685975f8ff05a763c864d100b7cc1142102aa2dd343ea1a0ab530255\ - 195c3a6400ecab7b27eff9b01ef6d37381fa6fb5401347f195354396772e8285 -Prime1: \ - ef86dd7af3f32cde8a9f6564e43a559a0c9f8bad36cc25330548b347ac158a34\ - 5631fa90f7b873c36effae2f7823227a3f580b5dd18304d5932751e743e9281b -Prime2: \ - f5bb4289c389d9019c36f96c6b81fffbf20be0620c6343e2b800aefb1b55a330\ - 8cc1402da7a2a558579a2a5146b30cb08e3f20b501081248f2f1de36cdfce9df -MultiplicativeInverseOfPrime2ModPrime1: \ - 88813a3d50b7c301948ee1985db19c9fd33a47c78c977024745e10483d9cc4f0\ - f573597ce564a91421d1d7457bc45a971f7d8b31403298da77799b57cf9a76de -PublicExponent: 02 -Test: KeyPairValidAndConsistent -Message: 2CA039854B55688740E3 -Signature: 1AF029CBEC9C692CE5096E73E4E9A52EC9A28D207A5511CCEC7681E5E3D867A4AE2E22DE4909D89196A272F1B50DE6FA3248BCA334D46E0D57171A790B6F4697E7BA7047DB79DECD47BD21995243DEBBF25915DDBC93C45875C14DE953792257C5C6825C905AFF40109C8CC7E793123D47AC1B5B6304A436CFA9BEEC8E0054E7 -Test: Verify -Message: 2A51DF4AF88613D91A37 -Signature: 6FF18F4471E1A8F850C910A181A9F28E69AACD8E8126969605E000A853197541AF9047E5D17315BF062B9CD8DF91196F0343285D9E31D5C72560C156782B6D0E5AF8F06D7DCDD8CABEC01B2438C168C40C21F6A8794648361BD2AEE13573A49ECA07A7EED97C0B9C5B1E508869E4CFD5FE1771924B1CF5A4BFF7D4379E5CD59F -Test: Verify -Message: 1CF8DDD95D780A89D7CF -Signature: 539C266B0313E0E256ED98EEF13E6AE64CED90C160A4999B3D47CBDA5285DAB0E0678C0E079CE9B8EB23E10EDFACFC19A80EEBB8F38ED5B5D6C8A988AB8CEC40A5A5BA102F75586167EAB6D5BF0CE8FF30C656895800F6F1B37D69FBBAF9055F7505DBEB537C0F986A1B5F0270DC12A640FFCB626F9763FDCFEFA1208C104003 -Test: Verify -Message: 2119A954F1AC0F3DCDB2 -Signature: 60C3CCF4F086B15B7F850B445F384333F7AE5A4B5EDE2820C7233239E1B86D6E4B4FCA4F50B087CE1DF17DA5D62672A17F2CF87A2875BBD9B138CAF6863821D6A4D553E9EB64C9254A8F9A6B960E57E39069D65E3F561AA1FA91643D42FEEFB9270D34AB0861DEA1E234EA587F580503D46A1989D413DAC2FFE0FC4CA663CE68 -Test: Verify -Message: F6959926E6D9D37D8BC0 -Signature: 249E1066542618CE0D236A7174708F801E7AB257931E9967A65C483ED66FB58598F99B6664AF0EAE221E2A6B271D7D17875ED02BF7FE35AA0786023858521CB79FEE0D134D9DDA609B0270FC9804BB6BF74AD90AE11EB339353533DC0D5A69E6B8758212B86024ED563767EA5D9B59655E0B8CC21244F720BA4ED663BF668E3A -Test: Verify -Message: 7A4C634DE6F16315BD5F -Signature: 308A5D65224201BED626CC83FB901EC84874EE03B2E7AB4E752EDBDE024C754E3CC9841CA062100A8843DE9183354B4E0596E8C68F1605828287884F0F9BA6968FC7A9F0CA09418A8485B90465E5D3F96CE4995A5FC7A6E5ABD9CC06BB8A2C3C8109F72EAE67FB4C108852C881CA645B3C5586F27F12FF3028ADE56E32AD9434 -Test: Verify -Comment: 1032-bit RW key -KeyFormat: Component -Modulus: \ - b660eb18786256c993ebc6dcb5892eac342f6d91229b73dc5d04f1afb9bb0dd4\ - eb0b48895f514b4c9afeaf86e91226f2299126d37528ce374e89cc312c06f47c\ - 81112bf5ca60ffc33b98318e04a17627269f1af461b6cb40f3be03b0113fb2d8\ - 404e154c7191306b36fd3efa73c784ad9189115d0bb1bd82b850d000e7cc8d20\ - 35 -Prime1: \ - 0bc31c063f43b3ade2cd633d554913339071d6ebed5fd665fc5dd7d47b80721a\ - 976c3b14fbd253f0f988c354725289f2897d7fb62c5c74af7d597a1e22aafba1\ - d3 -Prime2: \ - 0f816bf0add559afda38b008e4087f6a38b575c56fff453056eaaab3381c9552\ - 0969546f954d458d48e44850938b1db471cf4b40afc47e067fb5bce67ba98be8\ - d7 -MultiplicativeInverseOfPrime2ModPrime1: \ - 0b684eeec75b3e24e2d9947341b3f462258628af6f0b881396c887fe26a3408c\ - 40b13370710c82dd4a021a87bbaab5c0fc96cb1d015a783a764a8ab7b002903d\ - 21 -PublicExponent: 02 -Test: KeyPairValidAndConsistent -Message: EF0F1D56F4E5D587C212 -Signature: 3E544FEBB6623F5D392003B729FE2BFC20E2CB3ECAC22734DFCA55150254E616A41C5E54CE3B50FBC2FE2363EE9AF9B15C70615497B0A458F8AB6D850992EEEB56D65F87EA1BD6E2B4B7E40A0F5E1635C7DDB17110C61039CF712D3524C9C2C1F35D9163BE5C70276F46634514BE16EC09602782E88FE74EAEB2F50CBB0E3B5C4A -Test: Verify -Message: 2C9EA313EACF2C5DA43A -Signature: 1FEFF88814BB53E447E1E955AC8F1AF597C15C3866033E337AFBAB8627306F2EC1276621FF2176C89323CE32EA20F6AEC2CC271F1ED749408B2A3E43A23A44D6A3F38DCDDCAB696B239110AA7ECF12C6681B0E97E6FFF1B72F4F6D796BF82B9450AB8B3D28CA9D220BDF84ACCEA1DA5EDA0B470C3A82BBDD77B4C2723297608BD4 -Test: Verify -Message: EC5CC4228C3C70EE8F35 -Signature: 228BAA85062F10DCC9D99A23D340BC4B9E463D8AB86A6781A6D2143564303E2DC78772BF68449BE1E2711A68D5A15CF04A23573FB3870454308F583BBB5F2467069EF1395431E70F91BD56D846DC8DB2E88AB3D26A9770660B87A76D6C3575DE512BAFA8A0B901AD15B7D8E8BE2F176A182D16A9609F19A4298416245873175805 -Test: Verify -Message: D81F0C6F2D3D60EE19FE -Signature: 17EAA0C18178CD45A2B9100997F682E5F02BE09FBE4D8F345033951345CE98C8B3F13F2CA2A950CE7BDCBF83DBB700890E1F0B863D04C3ADB298F546A8F09F4DA4EF0DC6E7317207CB3CF691114E55D9EAA11C53BE55F7C214F62E6B0460DFA60C55B16EB55B29C9DBB908266C1BDBB03AD651EFB91905B142D852DCA0C4E3BBEE -Test: Verify -Message: FEF5EE07C74118DA30B9 -Signature: 2637E16E2599B6EC2F4728C73D3B29F483C2B881F1E1969C426027605EF080E9B17D258D5E1EBC6472A2501E04CF19C144537FCB38A1DA00D948EBD39FA11322D9230B62E2C12AEDB366BD85A2089588A8D52E941FD986D89828A342B83438A960B6FD87E9AD025AD75A692AA9DFEA873A9467B42D84879E85C5D11EFAB347FBED -Test: Verify -Message: 0B9554FFE4F6ADAB2C76 -Signature: 095952F24D9FBEF3A93A932865F4BDBB522CF24EBE153CE4BBB24CF301A1C7B51FE47B94F8F8B211CBC5A926FF6BAF9A6BBF7E15975D2DCCB95EF01AB7E641687870B0D01FC18B6B16FE17D3FC82931FBBCD4FD18C7F9588CEE8491876D72F98F2E7EEA90C12907210D6859053ADC7178B87BF8B4826954D6986FE761E71E1B7EA -Test: Verify -Comment: 1536-bit RW key -KeyFormat: Component -Modulus: \ - 9f8f8ab78ad635c71c9ef0fce9d4a958a9013ed69fcd67c385722668d4357c32\ - 3732c78179eaa17984531ba570aa0721a1e228957b1008010f1a2d6c42e09847\ - 9ffeaff9bbfeb3c8e101f968fc7ac74cfba210f76a6da160e65934d216368763\ - 8f59e414dc6f0448c0b4052c90f7dc565d32acae5da04e3e157dca184aba8362\ - bb28a2da6915d51d65f54fbeee69104a5a1b2304b87230c504b126dcf1c377cf\ - 1777b93be6903b50a44f054ae233b7cc24f950ded467cb8ffbdb17e7b6937605 -Prime1: \ - d0505c510a3b38a139d6d139818b04251d6ca46c2e717cfafbeebcd5fff8ae62\ - de4698e3241784f05e8c86f0f996db77259ebaac6983f092853639f619b75701\ - e562408cc1f5c543cada21fc26af36905b10a0df5b111efd754666bb3db4be63 -Prime2: \ - c41623ccb51e2474eb3dc5c2ef42cfd320a285ef7aefc1d1edcd5f566549cb79\ - 7285f01c89b9f749ca506b717c2a45b708fec2e7d611c5eee6af0a6d61219c7d\ - cab18961e98eea3b7797c61a75aed21d411de4fcf4a009a8238a832dd6e41277 -MultiplicativeInverseOfPrime2ModPrime1: \ - bc1ceeed917217387ead12254cfc183f82c79709499f510ce093d6d28bc1bf2b\ - fabc3d86d64a1c807605bd57f9ec533745d6e359270885c3eb7a36a02dff7137\ - 9bd453bf3fdc282afa2295d5e393f1c2c74edcbd2374c7740e8135ef0b8af258 -PublicExponent: 02 -Test: KeyPairValidAndConsistent -Message: 400AEF79EDBCEA796D71 -Signature: 15EB5A68CBCB0D6313BB2D14436237A716AC3159B059FBC29931933DB802D6925C01BDC6D90DD0DA25980F1C8199AB9CD3FD105A63D13B5C0101A0430455334492038FBE029BF4EE61F8A2F88D2A6D5424DE7C0CC314B5EA4F867B35224D574463BDE78B71904033C1455484865EB80AE1C2A7D1C229CD0A4D49C0F06A26E264AD42ACAA131F8C0C5EA4DC9EB5BD349D1EE12B3F91F4B9F2DABC3BCF0E216D4A34A3541169955BE45289CECE16DA6BC5352FF31D66538F64308D6FBB9C7DDE72 -Test: Verify -Message: 63F64BFAD5B830682F44 -Signature: 1003E58A73B018FF9F0F66D3BE9A8DD9D83097A0EB216AEEAA75B63C150AAE9E8BE2A5DE426D18FBC56865F4C9CA51A9BB6E99B70C59B7995246A1F4327C9E4A69517131DA66DDE98AE5D8355527D1C5E4D83CC7ED7B3B1F404F6FDF731DA615974F0777CD22C1E6FAA3569D1141900734C7F3262FE7B9ED291A934DE81A06EBF258F7159DE842737A32DAEC79EFE211C2739D3F5859CB9A633D2A16D78C347790241925C3E776F04B5D5F1900A7B48645DF16DC6F9E8C990AEFEE22FA1DA496 -Test: Verify -Message: B6AAE87E8D469A16A335 -Signature: 368EE32DDF9D5526E50B1645473DB79CE4B0EF3801F3DF050E8B6B10DFAA600A505FD1C91CAE1CD8CB8FA7BC2F81EDFEE7E74DCF7BDA9ED4FF87C39650E8A473672FD012A6A57C5DC44FFBBDA4A5DECD099A32791CEDC6170C8B367080792713041350D2483B27924822DD886A36EE575A3CD6C097162F758F5628D3EA301050AC848F0ACAEDAB8AD34D436E418AA53618AFAFC3168B7CFA641B1A88C86007FD1EDD8FE1D1A94FCE59B548DA3D8FE313A0A97719E19C857560763EFF1682CC14 -Test: Verify -Message: DB0F126516E3EDFF3D7C -Signature: 42076C3F6976EF4BBEAFEF0B4F7A8198CACE6F73436C59DF212474C94D00B0501C359CAB8950EB8937E8458964C817926A3181EED64EAB3A5274A9B3114406F62A62C51F4EDBEEF3BD948C21578996236D6D477B2701DD5A4818B08F5D4740CD23064798C3406133D0758D51717DB4575117DE887733D1E7170AA0845A81535444A962F2003A46361E8A8A1914DA6732C37334320F155E90E18D9E2A921034BEC81395AF69D61E22FEF90BC4F9127914B536BD2477552166C11F139519129864 -Test: Verify -Message: A58B1E5E98C44A8680BD -Signature: 100B8692C7A09EFB585A63B5D636EABFE9DDFE50D5235B11BDFD818D1810893B327ACC3B78942900C8F7498BDC1D2FB44330ADD3FEBC709046D8028F38AA7DCC768558E7D6469EDA306C0FCAE001C7B01544C80043864761355888C13960DD53BBD7854F2FBB7D9DE021BAD69769418712B6335A8C63143329363C65CB4170AA0C040559136EA9C19A6793024AF77BCF3EE793CAEDF07FD8A8E2C9C29B5F225F399BBA177D070314E319359394DB999D866A48D591EE8C662BA6394E396300FE -Test: Verify -Message: 7AF0498714B0D93AB959 -Signature: 35A959E3717468552590C26FA92009C3866955A1D14405AD33D3FA745D7591521A323BA031070B1FB60A1B6FE0C7198FC14EA41CE62EB6EB060FD073E816C9C85BB6251BF5235567E12951778A61D87F117137C347DE56337FBF9A3360D49330A98248233719FF862F83F772AC887F035820579F406D221191F4535ABA37401FF6E28216EC06AB8832D9AB3EAE4E1D3D780A1FA46883A79B657A7027597BCE4F21744CFC3704A449A204D3790F668E2EB710D5CF031BAA58359D35DDF92455D7 -Test: Verify -Comment: 2048-bit RW key -KeyFormat: Component -Modulus: \ - b6dee7375bf4385043b3cc2ac5cacbc14ad11a17574738dd2bd84d2d1e6c74e1\ - 6066c2a5c35bc3b87839858afb5ee5e8abfab408f38772866f6f833f39fab248\ - 3a2c34ed55ad7098f9f63d4ec70b7950f02daaaab10781a0008f993c4027e381\ - 6bfd45c52f59452a7b28873513dce415a84fc8bc06601567f91ec41647da2304\ - 5b6e01e24516724acc02947ad5aa2dba4d952bc4f49d18ada0b0f7cc5d488814\ - b921c0bc2b33d8828d80130df7d79b0992cec40d3bc7217d4a4dff3699345e44\ - dac968575194845aa7b60dcf3c712d9b0a384824c3579b40dba265457d50f69f\ - 02a140884d89b7fdee9f0a787e76a37c58c92cf2d3818c72097d41b3faa7aa95 -Prime1: \ - fa880a456f9c205a26e02c3357536531dec150be0ef8747f69ea30d987ff7dd8\ - 9e9a1075ebd39f04fa495bd26d8408a8de69113a9fbb52f20713d1d046a76b47\ - 8cf77c46454a7afda2ef418f63faf67c947d898bca109f3275999e8f2e60e2c0\ - eec133ff69e71a2d396632670b52d8ea03f7589d8144ab580b1d3e60efa1280b -Prime2: \ - badcc718dd2d761c4893c4831d56ada30fc5c7c148d473bedf7615b7e821b92f\ - 319676ce278349f1309fb3d264c1a22bde71b221354c7a4d31117b3ec3c9d480\ - 2e0a26bd8ec05d28b6502c65f35c687af7f8396b963ed029a2c5ae38dd7c5c96\ - 2a953c113c0f590957ab19a6e2afda6db84f22c0c31ae243debd2920fbe9fbdf -MultiplicativeInverseOfPrime2ModPrime1: \ - 48a56f93e044a8211861da6bde9ab61265c63e168e507b56cd6e6e5f4de57c2f\ - 5c0b626462d6c06790cf561fa12a350dc0c08767f2717914183fac90db36495a\ - 91c0e9c0fbcfef19c85075b3b744fc378a9f2045cd7fd144ecd39bd1a59f1483\ - 10f6982efb3ffe502b279c4c0cb2a7f9ef64ca8f38690c486afb5f659cf7f838 -PublicExponent: 02 -Test: KeyPairValidAndConsistent -Message: 00AA5515CDAE5CD0F0DC -Signature: 30EECA6B48D796552F5A6A3C11F28D730FA077422CAAB34FDEB879AE0F71DF21330E2F3BE5BF3A8CA372EBCD3DFA7C81B3398C31B0972D0B857926CB39732351AACEB8276D52B9D82F9C245FA0F1CF49E785A2BC00FF27FBCF777F84D05BEF17FCC0505820B029AC8F0CE17D2469372CE47E1428BB941004FE170EF87163E07298EFFCC1BFA7E7CB1F572C340CAA075A5962A15B69CE937BC7EFB492F501FC88CBF0119C351C8498782091EF6EFB19120195E5FF51DF86F90E90FAEB225AA2EE43AB4E8358101C0348C7E3859B9DEBA19464C74B74AC48A0B73FC8D2E7F8033E86208F0792B6E5B6DE36C99DEF604949811D1671EF6B0A4781B4E7A0A72AD855 -Test: Verify -Message: B8E2FB9EAE22FB2C0021 -Signature: 416D33F8C213CF81F805F54FC1D4E7C6A588A0965F1C9CAEEA1D41452E20935AAF2D30F957584B56621035430212A428E27A2F687CA9DBB596C19864AE692EF7BBA730F3D70CC2DDE15AB71E1E350C0C316EFA1A831ACD1441598B112482487DF72F58ED318182C7CD0906FE39C5655BF1313F29A15D60A6178CBF600C7FBFF8994840ED649C3C4026A463B3EA39C692B7D112B128BE49E1E32D4A7FF8D4513283D8DCD9CCB8FB7300BE0BDD4C44DAA2F7049B3AD83437093E623442AC69B48911CDA21E95E0775041F67F6E6AE01DCE646AEC20908E7C1B693600FE41ABA85AC0C778641E46C419083E41773C749DB3E1BD8FD764E271860D2D7F8E11BD6AB3 -Test: Verify -Message: 8C8C306A629373BAE647 -Signature: 0E9A00045FFD399D9DA9D0D7E543CF9FFD098BC23E72DD7763A64F22C7F0479CE866E31438B8F7DE31A18F35AF419BED6C67BE1540614D3310DD24F019E14FCC3AF73743F4C143D4B79CDF35C752A300F0A8251CCFF4AAF18785C533A7DF1A20AFE6770DEBD1B8BA2C83B2E345A04F833CD173E998FF9840C2F8A370FFDCFF5FD95CBD71B25FC9972192470FD145975344F64C2F6D68CB3513F48F9FC070021BEE8F6A4282D098C44DF655CE415E89B97994AE3ABE85986C7EE0AC348EF2A4F52D102EA80836E77E81AD3678803E53C83CF2F30D2D4950FB6B038CCB3F2690A9381EB34D6C09E88C090AB05E28047DC490EB8A1282FEB38E82FB0B18309284C4 -Test: Verify -Message: 15E7B7B7ED0F176B6799 -Signature: 39FF4B5FA50AE498F3C91A655E6865840D1FC401EE02DBC8460A59DEB8816E6680F712B7BAF8D4DC11A3B54BF906BE698306F0449BB43F3F223B944D930A1A3C718E8A9E2EEDEC5A07AB817C26A80CC2A2EE2846A597EAB8A999D38DB98490166F2574524038BBDF24B4E4622C843210C6B94987638C6976562EA9727385B152614C18349BD54AD95DE33D5354954B505E5259CCDA47E3CECEF3154F6E5481E536BAB568146A0BFCB66573714A7BA7ABE0385115720687F33D9C6EF6BB60272F1272CF349990E3A2FBCCE180B730792101089B164AE5A001F5263F7493AF148D6E0953E311AD12E4202D35F96DD30885663B5101F9B05675FCD2FCC4FCC4DDFF -Test: Verify -Message: B36724C92954C38D0288 -Signature: 3C8CD3614555568BBECA99174B7B203D0BC6FABE9E6FFE0C41EB4D9A2C601D2393CA1E01B7D7E99337758AC914C9F151311E5AE6708DAF1D8C825DA471652C6E13A8FE5802D7AE097BFC899A4EC8CA235B5982B9058C53AAD52823ACF692290EB8823C126635AB0BBF101C2B3149AB16183FA2DBB049DDB99C5E83723E4D4693CA3A08588AA868C677D42ABDAA6586EF192391D276C5E5AF0763ACCA6293F06250C51FDC2AD369CD44EB5F654E98761C881DDEC08E795FFB229B20522349B0714059E18B7B23A48875EAB12ED3F0A011D3A985DD7384B0046F39FA6C1A331F3D4C5125100BA58666935C68A7A10849D9C74850BAB82AE15EC950A283F3E7DAD8 -Test: Verify -Message: FA95400C2B14E064F76A -Signature: 3F67F9DBEB88E6AD057BEDC3D97030555A908867EC578A6CA572137CB61C21036AADE6DDC5592EC7CCB6B263E51B4C886A51904C858040E493D64B9ACE5BAA50C4A66D04ACCDFE0039D8541C4363DEFFCF93BDF5F5CC1FB64855D956B5EFD42D4C9B96B9CBAA97A32F02AAB307674E53404E6836DB5C96B59572ADBFD1113B87608ACE6D0898CB02E35575CC28D38A9FF8C1C4AD36BAA991DEFAB533F0A6C9C2F0F0815F1D659ED576E5DB18494A54B6817D9E34A134F3B9A0F1E8C77FC204B6EE087C0445A7036C935117E338D092F6E1FF4DF7605525C409456A5195233A176B29B2FD8FB2808D0412FCA0541B2BB6800BD8BB9DC9DC25230166071E8D961E -Test: Verify diff --git a/embeddedcryptopp/TestVectors/salsa.txt b/embeddedcryptopp/TestVectors/salsa.txt deleted file mode 100644 index b00ff96..0000000 --- a/embeddedcryptopp/TestVectors/salsa.txt +++ /dev/null @@ -1,463 +0,0 @@ -AlgorithmType: SymmetricCipher -Name: Salsa20 -Source: http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors?rev=161&view=markup -Comment: Set 1, vector# 0 -Key: 80000000000000000000000000000000 -IV: 0000000000000000 -Plaintext: r16 00000000 -Seek: 0 -Ciphertext: 4DFA5E481DA23EA09A31022050859936DA52FCEE218005164F267CB65F5CFD7F2B4F97E0FF16924A52DF269515110A07F9E460BC65EF95DA58F740B7D1DBB0AA -Test: Encrypt -Seek: 448 -Ciphertext: B375703739DACED4DD4059FD71C3C47FC2F9939670FAD4A46066ADCC6A5645783308B90FFB72BE04A6B147CBE38CC0C3B9267C296A92A7C69873F9F263BE9703 -Test: Encrypt -Seek: 192 -Plaintext: r32 00000000 -Ciphertext: DA9C1581F429E0A00F7D67E23B730676783B262E8EB43A25F55FB90B3E753AEF8C6713EC66C51881111593CCB3E8CB8F8DE124080501EEEB389C4BCB6977CF95\ -7D5789631EB4554400E1E025935DFA7B3E9039D61BDC58A8697D36815BF1985CEFDF7AE112E5BB81E37ECF0616CE7147FC08A93A367E08631F23C03B00A8DA2F -Test: Encrypt -Comment: Set 3, vector#243 -Key: F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112 -IV: 0000000000000000 -Plaintext: r16 00000000 -Seek: 0 -Ciphertext: B4C0AFA503BE7FC29A62058166D56F8F5D27DC246F75B9AD8760C8C39DFD87492D3B76D5D9637F009EADA14458A52DFB09815337E72672681DDDC24633750D83 -Test: Encrypt -Seek: 448 -Ciphertext: 5A5FB5C8F0AFEA471F0318A4A2792F7AA5C67B6D6E0F0DDB79961C34E3A564BA2EECE78D9AFF45E510FEAB1030B102D39DFCECB77F5798F7D2793C0AB09C7A04 -Test: Encrypt -Seek: 192 -Plaintext: r32 00000000 -Ciphertext: DBBA0683DF48C335A9802EEF0252256354C9F763C3FDE19131A6BB7B85040624B1D6CD4BF66D16F7482236C8602A6D58505EEDCCA0B77AED574AB583115124B9\ -F0C5F98BAE05E019764EF6B65E0694A904CB9EC9C10C297B1AB1A6052365BB78E55D3C6CB9F06184BA7D425A92E7E987757FC5D9AFD7082418DD64125CA6F2B6 -Test: Encrypt -Comment: Set 6, vector# 3 -Seek: 0 -Key: 0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C -IV: 288FF65DC42B92F9 -Plaintext: r131072 00 -CiphertextXorDigest: E00EBCCD70D69152725F9987982178A2E2E139C7BCBE04CA8A0E99E318D9AB76F988C8549F75ADD790BA4F81C176DA653C1A043F11A958E169B6D2319F4EEC1A -Test: EncryptXorDigest -AlgorithmType: SymmetricCipher -Name: Salsa20 -Source: http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/reduced/12-rounds/verified.test-vectors?rev=210&view=auto -Comment: Set 1, vector# 0 -Rounds: 12 -Key: 80000000000000000000000000000000 -IV: 0000000000000000 -Plaintext: r64 00 -Seek: 0 -Ciphertext: FC207DBFC76C5E1774961E7A5AAD09069B2225AC1CE0FE7A0CE77003E7E5BDF8B31AF821000813E6C56B8C1771D6EE7039B2FBD0A68E8AD70A3944B677937897 -Test: Encrypt -Seek: 192 -Ciphertext: 4B62A4881FA1AF9560586510D5527ED48A51ECAFA4DECEEBBDDC10E9918D44AB26B10C0A31ED242F146C72940C6E9C3753F641DA84E9F68B4F9E76B6C48CA5AC -Test: Encrypt -Source: http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/reduced/8-rounds/verified.test-vectors?rev=210&view=auto -Comment: Set 1, vector# 0 -Rounds: 8 -Key: 80000000000000000000000000000000 -IV: 0000000000000000 -Plaintext: r64 00 -Seek: 0 -Ciphertext: A9C9F888AB552A2D1BBFF9F36BEBEB337A8B4B107C75B63BAE26CB9A235BBA9D784F38BEFC3ADF4CD3E266687EA7B9F09BA650AE81EAC6063AE31FF12218DDC5 -Test: Encrypt -Seek: 192 -Ciphertext: BB5B6BB2CC8B8A0222DCCC1753ED4AEB23377ACCBD5D4C0B69A8A03BB115EF71871BC10559080ACA7C68F0DEF32A80DDBAF497259BB76A3853A7183B51CC4B9F -Test: Encrypt - -AlgorithmType: SymmetricCipher -Name: XSalsa20 -Source: created by Wei Dai using naclcrypto-20090308 -Key: 1b27556473e985d462cd51197a9a46c76009549eac6474f206c4ee0844f68389 -IV: 69696ee955b62b73cd62bda875fc73d68219e0036b7a0b37 -Plaintext: r139 00 -Ciphertext: \ -eea6a7251c1e72916d11c2cb214d3c252539121d8e234e652d651fa4c8cff880\ -309e645a74e9e0a60d8243acd9177ab51a1beb8d5a2f5d700c093c5e55855796\ -25337bd3ab619d615760d8c5b224a85b1d0efe0eb8a7ee163abb0376529fcc09\ -bab506c618e13ce777d82c3ae9d1a6f972d4160287cbfe60bf2130fc0a6ff604\ -9d0a5c8a82f429231f0080 -Key: a6a7251c1e72916d11c2cb214d3c252539121d8e234e652d651fa4c8cff88030 -IV: 9e645a74e9e0a60d8243acd9177ab51a1beb8d5a2f5d700c -Plaintext: 093c5e5585579625337bd3ab619d615760d8c5b224a85b1d0efe0eb8a7ee163abb0376529fcc09bab506c618e13ce777d82c3ae9d1a6f972d4160287cbfe60bf2130fc0a6ff6049d0a5c8a82f429231f008082e845d7e189d37f9ed2b464e6b919e6523a8c1210bd52a02a4c3fe406d3085f5068d1909eeeca6369abc981a42e87fe665583f0ab85ae71f6f84f528e6b397af86f6917d9754b7320dbdc2fea81496f2732f532ac78c4e9c6cfb18f8e9bdf74622eb126141416776971a84f94d156beaf67aecbf2ad412e76e66e8fad7633f5b6d7f3d64b5c6c69ce29003c6024465ae3b89be78e915d88b4b5621d -Ciphertext: b2af688e7d8fc4b508c05cc39dd583d6714322c64d7f3e63147aede2d9534934b04ff6f337b031815cd094bdbc6d7a92077dce709412286822ef0737ee47f6b7ffa22f9d53f11dd2b0a3bb9fc01d9a88f9d53c26e9365c2c3c063bc4840bfc812e4b80463e69d179530b25c158f543191cff993106511aa036043bbc75866ab7e34afc57e2cce4934a5faae6eabe4f221770183dd060467827c27a354159a081275a291f69d946d6fe28ed0b9ce08206cf484925a51b9498dbde178ddd3ae91a8581b91682d860f840782f6eea49dbb9bd721501d2c67122dea3b7283848c5f13e0c0de876bd227a856e4de593a3 -Test: Encrypt -IV: b2af688e7d8fc4b508c05cc39dd583d6714322c64d7f3e63 -Ciphertext: 418078fe843f5984dd3c7975d1ff51af4dceda640999aaa3c28618ae286ca15051cb4d55f9da22a213ef14a2b905b52c99a557854c7f2a6d6ed6f69c1c6649f3fb67b8628468029b3367920c2e1148aa1f3b9c695cb1426f09ce84045842946e0454e41ab1edb32cae4b95669de4e2ccaf00ba86ffeae6a9c5fce4153baddb0d8998a600537a9649939cb7d7a9c4e8cbca0fab77963abd516699879de0b1971dc7328668111ff5b77c253b9e6346d1a2ce6e390cd736156ad7f44b339cfb141f00e7a766c06e130b0c31d88980d2ad8814a2d641599162ab8af25d93067f06a49637eaf6523806b8fa07d56628bb -Test: Resync -Key: 9e1da239d155f52ad37f75c7368a536668b051952923ad44f57e75ab588e475a -IV: af06f17859dffa799891c4288f6635b5c5a45eee9017fd72 -Plaintext: feac9d54fc8c115ae247d9a7e919dd76cfcbc72d32cae4944860817cbdfb8c04e6b1df76a16517cd33ccf1acda9206389e9e318f5966c093cfb3ec2d9ee2de856437ed581f552f26ac2907609df8c613b9e33d44bfc21ff79153e9ef81a9d66cc317857f752cc175fd8891fefebb7d041e6517c3162d197e2112837d3bc4104312ad35b75ea686e7c70d4ec04746b52ff09c421451459fb59f -Ciphertext: 2c261a2f4e61a62e1b27689916bf03453fcbc97bb2af6f329391ef063b5a219bf984d07d70f602d85f6db61474e9d9f5a2deecb4fcd90184d16f3b5b5e168ee03ea8c93f3933a22bc3d1a5ae8c2d8b02757c87c073409052a2a8a41e7f487e041f9a49a0997b540e18621cad3a24f0a56d9b19227929057ab3ba950f6274b121f193e32e06e5388781a1cb57317c0ba6305e910961d01002f0 -Test: Encrypt -IV: 2c261a2f4e61a62e1b27689916bf03453fcbc97bb2af6f32 -Ciphertext: 7030af4a9db8a6b95f55f962efefcc60d8ceb0d5d920e808cebd8cf6f31542d227a67c9db8888cfcb9410ae357f8a3da06a608a93b7fd5513978c6b8b837f6ecaafd3366495cdd3ab719d9d4c2ac74d6ea2eb117f30369ea62727fa6dc7982f668fa3bf44c9da8e70ff8c18b07d63aa01afe1311bdafc457d06c69aaea0dfbb1fc89d1574ad1e7be8b459d4cf36bdd88db0363219652089c50 -Test: Resync -Key: d5c7f6797b7e7e9c1d7fd2610b2abf2bc5a7885fb3ff78092fb3abe8986d35e2 -IV: 744e17312b27969d826444640e9c4a378ae334f185369c95 -Plaintext: 7758298c628eb3a4b6963c5445ef66971222be5d1a4ad839715d1188071739b77cc6e05d5410f963a64167629757 -Ciphertext: 27b8cfe81416a76301fd1eec6a4d99675069b2da2776c360db1bdfea7c0aa613913e10f7a60fec04d11e65f2d64e -Test: Encrypt -IV: 27b8cfe81416a76301fd1eec6a4d99675069b2da2776c360 -Ciphertext: ed158a1dd07f4316d403af3e6977afaac8205d678b38fa5928c61e366ff27003143d5d20482a2ea76a50756225a4 -Test: Resync -Key: 737d7811ce96472efed12258b78122f11deaec8759ccbd71eac6bbefa627785c -IV: 6fb2ee3dda6dbd12f1274f126701ec75c35c86607adb3edd -Plaintext: 501325fb2645264864df11faa17bbd58312b77cad3d94ac8fb8542f0eb653ad73d7fce932bb874cb89ac39fc47f8267cf0f0c209f204b2d8578a3bdf461cb6a271a468bebaccd9685014ccbc9a73618c6a5e778a21cc8416c60ad24ddc417a130d53eda6dfbfe47d09170a7be1a708b7b5f3ad464310be36d9a2a95dc39e83d38667e842eb6411e8a23712297b165f690c2d7ca1b1346e3c1fccf5cafd4f8be0 -Ciphertext: 6724c372d2e9074da5e27a6c54b2d703dc1d4c9b1f8d90f00c122e692ace7700eadca942544507f1375b6581d5a8fb39981c1c0e6e1ff2140b082e9ec016fce141d5199647d43b0b68bfd0fea5e00f468962c7384dd6129aea6a3fdfe75abb210ed5607cef8fa0e152833d5ac37d52e557b91098a322e76a45bbbcf4899e790618aa3f4c2e5e0fc3de93269a577d77a5502e8ea02f717b1dd2df1ec69d8b61ca -Test: Encrypt -IV: 6724c372d2e9074da5e27a6c54b2d703dc1d4c9b1f8d90f0 -Ciphertext: cfb653dd50a04a8580847d5bb98dc15e27c60f5a70da635718ba6d589f47935ed476fc960ffaf3b8750a59171b1434429a977ba878aea7ace8dd083a9238585112591165d0948a86e89e6118d572aa85667cceffd78a60baa5a152dc5e29bdd93f7389edde1541eec2f3aac38ea2bfc812f73de7e2e7b1322468f823a2c7c16e30fe9283894ac057da5c45a67f4988b4edafeb51c1b4a51a849d188b15838552 -Test: Resync -Key: 760158da09f89bbab2c99e6997f9523a95fcef10239bcca2573b7105f6898d34 -IV: 43636b2cc346fc8b7c85a19bf507bdc3dafe953b88c69dba -Plaintext: d30a6d42dff49f0ed039a306bae9dec8d9e88366cc19e8c3642fd58fa0794ebf8029d949730339b0823a51f0f49f0d2c71f1051c1e0e2c86941f172789cdb1b0107413e70f982ff9761877bb526ef1c3eb1106a948d60ef21bd35d32cfd64f89b79ed63ecc5cca56246af736766f285d8e6b0da9cb1cd21020223ffacc5a32 -Ciphertext: c815b6b79b64f9369aec8dce8c753df8a50f2bc97c70ce2f014db33a65ac5816bac9e30ac08bdded308c65cb87e28e2e71b677dc25c5a6499c1553555daf1f55270a56959dffa0c66f24e0af00951ec4bb59ccc3a6c5f52e0981647e53e439313a52c40fa7004c855b6e6eb25b212a138e843a9ba46edb2a039ee82a263abe -Test: Encrypt -IV: c815b6b79b64f9369aec8dce8c753df8a50f2bc97c70ce2f -Ciphertext: ab7204ab4f995c2d87376c3586f0261250907ab2c25e2d232f10f51f0f3a3f11ff704ba188a508301fb9d5f7e4d55070631ecd2e3be5d79d4fa67f4f4acb3879afc2dc18c09446489b79dd3043f74027e9a24a54d8babe757c9a3470a95cb7b7b093331e32534b337d697046f7349bcfa89036b3cf50ecfc6f1e61300a49b6 -Test: Resync -Key: 27ba7e81e7edd4e71be53c07ce8e633138f287e155c7fa9e84c4ad804b7fa1b9 -IV: ea05f4ebcd2fb6b000da0612861ba54ff5c176fb601391aa -Plaintext: e09ff5d2cb050d69b2d42494bde5825238c756d6991d99d7a20d1ef0b83c371c89872690b2fc11d5369f4fc4971b6d3d6c078aef9b0f05c0e61ab89c025168054defeb03fef633858700c58b1262ce011300012673e893e44901dc18eee3105699c44c805897bdaf776af1833162a21a -Ciphertext: a23e7ef93c5d0667c96d9e404dcbe6be62026fa98f7a3ff9ba5d458643a16a1cef7272dc6097a9b52f35983557c77a11b314b4f7d5dc2cca15ee47616f861873cbfed1d32372171a61e38e447f3cf362b3abbb2ed4170d89dcb28187b7bfd206a3e026f084a7e0ed63d319de6bc9afc0 -Test: Encrypt -IV: a23e7ef93c5d0667c96d9e404dcbe6be62026fa98f7a3ff9 -Ciphertext: 5c77efcb16097df824bd58cd3498e07af1c761740b5539929115e2caf3bc10eed2a16254a4306f4e20827247900276ce887362990c070c0f79e15987473b7ad240e7a9f8e6e3f020fb337438cc3c8b81c4cdbfbdd7b543b13a48a4959744f3efcb99a939c0599ce32f816d12c2b47a2f -Test: Resync -Key: 6799d76e5ffb5b4920bc2768bafd3f8c16554e65efcf9a16f4683a7a06927c11 -IV: 61ab951921e54ff06d9b77f313a4e49df7a057d5fd627989 -Plaintext: 472766 -Ciphertext: 8fd7df -Test: Encrypt -IV: 8fd7dfcb16097df824bd58cd3498e07af1c761740b553992 -Ciphertext: 85e098 -Test: Resync -Key: f68238c08365bb293d26980a606488d09c2f109edafa0bbae9937b5cc219a49c -IV: 5190b51e9b708624820b5abdf4e40fad1fb950ad1adc2d26 -Plaintext: 47ec6b1f73c4b7ff5274a0bfd7f45f864812c85a12fbcb3c2cf8a3e90cf66ccf2eacb521e748363c77f52eb426ae57a0c6c78f75af71284569e79d1a92f949a9d69c4efc0b69902f1e36d7562765543e2d3942d9f6ff5948d8a312cff72c1afd9ea3088aff7640bfd265f7a9946e606abc77bcedae6bddc75a0dba0bd917d73e3bd1268f727e0096345da1ed25cf553ea7a98fea6b6f285732de37431561ee1b3064887fbcbd71935e02 -Ciphertext: 36160e88d3500529ba4edba17bc24d8cfaca9a0680b3b1fc97cf03f3675b7ac301c883a68c071bc54acdd3b63af4a2d72f985e51f9d60a4c7fd481af10b2fc75e252fdee7ea6b6453190617dcc6e2fe1cd56585fc2f0b0e97c5c3f8ad7eb4f31bc4890c03882aac24cc53acc1982296526690a220271c2f6e326750d3fbda5d5b63512c831f67830f59ac49aae330b3e0e02c9ea0091d19841f1b0e13d69c9fbfe8a12d6f30bb734d9d2 -Test: Encrypt -IV: 36160e88d3500529ba4edba17bc24d8cfaca9a0680b3b1fc -Ciphertext: f003b213737415a81894a3d3d8fe4e4434d4df2b253d60c44609bdc0414cedf8bae297ecdb1d0b92393dd6dd7027b555388ac8a66308082fc6327ad94ad96223003de15c48a06e9cd99b5561e7fc5949c6ba8cf11d6ba1374ec32062caef541e7252d168781aab4c637793433b3998c5a5013fd35c336600a02765ddbf52b97ae80dbfbbe55e43c6bd5f746a1c2df4c80611c76a90308c47b2807876249d6d3c507a1a96c2bbb8242ccd -Test: Resync -Key: 45b2bd0de4ed9293ec3e26c4840faaf64b7d619d51e9d7a2c7e36c83d584c3df -IV: 546c8c5d6be8f90952cab3f36d7c1957baaa7a59abe3d7e5 -Plaintext: 5007c8cd5b3c40e17d7fe423a87ae0ced86bec1c39dc07a25772f3e96dabd56cd3fd7319f6c9654925f2d87087a700e1b130da796895d1c9b9acd62b266144067d373ed51e787498b03c52faad16bb3826fa511b0ed2a19a8663f5ba2d6ea7c38e7212e9697d91486c49d8a000b9a1935d6a7ff7ef23e720a45855481440463b4ac8c4f6e7062adc1f1e1e25d3d65a31812f58a71160 -Ciphertext: 8eacfba568898b10c0957a7d44100685e8763a71a69a8d16bc7b3f88085bb9a2f09642e4d09a9f0ad09d0aad66b22610c8bd02ff6679bb92c2c026a216bf425c6be35fb8dae7ff0c72b0efd6a18037c70eed0ca90062a49a3c97fdc90a8f9c2ea536bfdc41918a7582c9927fae47efaa3dc87967b7887dee1bf071734c7665901d9105dae2fdf66b4918e51d8f4a48c60d19fbfbbcba -Test: Encrypt -IV: 8eacfba568898b10c0957a7d44100685e8763a71a69a8d16 -Ciphertext: f17808cf21dba4762ced5fcc264f615a4619d8d5ee3278dbdacf14a799f8ee5f8a38a7fd9d262b336e51a8790c90fb8f0b63a49edae81f9a200ad73d9ed5ce6257524b506d7a219013e3e44a1f2a264b7f7f121e5d4765d0bdfe4a36fc51e48ee21e9dcbc3dc2541405bbdb90490fd786b942a07786094fc990be21e5b746d522cad26269a76c85134ee654f33485807fc28cf87ac37 -Test: Resync -Key: fe559c9a282beb40814d016d6bfcb2c0c0d8bf077b1110b8703a3ce39d70e0e1 -IV: b076200cc7011259805e18b304092754002723ebec5d6200 -Plaintext: 6db65b9ec8b114a944137c821fd606be75478d928366d5284096cdef782fcff7e8f59cb8ffcda979757902c5ffa6bc477ceaa4cb5d5ea76f94d91e833f823a6bc78f1055dfa6a97bea8965c1cde67a668e001257334a585727d9e0f7c1a06e88d3d25a4e6d9096c968bf138e116a3ebeffd4bb4808adb1fd698164ba0a35c709a47f16f1f4435a2345a9194a00b95abd51851d505809a6077da9baca5831afff31578c487ee68f2767974a98a7e803aac788da98319c4ea8eaa3d394855651f484cef543f537e35158ee29 -Ciphertext: 4dce9c8f97a028051b0727f34e1b9ef21f06f0760f36e71713204027902090ba2bb6b13436ee778d9f50530efbd7a32b0d41443f58ccaee781c7b716d3a96fdec0e3764ed7959f34c3941278591ea033b5cbadc0f1916032e9bebbd1a8395b83fb63b1454bd775bd20b3a2a96f951246ac14daf68166ba62f6cbff8bd121ac9498ff8852fd2be975df52b5daef3829d18eda42e715022dcbf930d0a789ee6a146c2c7088c35773c63c06b4af4559856ac199ced86863e4294707825337c5857970eb7fddeb263781309011 -Test: Encrypt -IV: 4dce9c8f97a028051b0727f34e1b9ef21f06f0760f36e717 -Ciphertext: 534f5151319c299d7356be2275ed2137fab66742797370b511e5150dcf7bc75c06d5249e8e8bd7c16e563cc7d99368a7a7f47f811a2ae2b632c73e9f49641bf9954d4df19c2778221d780f799806757738b327e6aeebab6bb22137f8b994c1e08baff75bb2774576bce2deb599817fc7a69860c538efffe91439f4714e4629b00a25b5b1a6be8aa7da2be33bad953481926e0067a70d4ff1a7bd0111e605ef6a2d66fa7af43d746c24a5d464dd6f75773aa9b65bbdfad9b82fe80f182b144cea9211d0b2472de873008509 -Test: Resync -Key: 0ae10012d7e56614b03dcc89b14bae9242ffe630f3d7e35ce8bbb97bbc2c92c3 -IV: f96b025d6cf46a8a12ac2af1e2aef1fb83590adadaa5c5ea -Plaintext: ea0f354e96f12bc72bbaa3d12b4a8ed879b042f0689878f46b651cc4116d6f78409b11430b3aaa30b2076891e8e1fa528f2fd169ed93dc9f84e24409eec2101daf4d057be2492d11de640cbd7b355ad29fb70400fffd7cd6d425abeeb732a0eaa4330af4c656252c4173deab653eb85c58462d7ab0f35fd12b613d29d473d330310dc323d3c66348bbdbb68a326324657cae7b77a9e34358f2cec50c85609e73056856796e3be8d62b6e2fe9f953 -Ciphertext: e8abd48924b54e5b80866be7d4ebe5cf4274cafff08b39cb2d40a8f0b472398aedc776e0793812fbf1f60078635d2ed86b15efcdba60411ee23b07233592a44ec31b1013ce8964236675f8f183aef885e864f2a72edf4215b5338fa2b54653dfa1a8c55ce5d95cc605b9b311527f2e3463ffbec78a9d1d65dabad2f338769c9f43f133a791a11c7eca9af0b771a4ac32963dc8f631a2c11217ac6e1b9430c1aae1ceebe22703f429998a8fb8c641 -Test: Encrypt -IV: e8abd48924b54e5b80866be7d4ebe5cf4274cafff08b39cb -Ciphertext: e8c59b616dd10474930c432422d23d8df8dee1c626def1278eb6c9828435c0c8a98aea9d350752a78cf0cf1de7973436605f22b0d40b9059d777c55c8fd02cd9dbab6888161ed28979c64b700d7ea48038edf36af21078713f844f5f23a4f271aad3562ed2cd773de622fff2f0b5785672760a7064e5415c76ffec522eb1225868345e89a9fcbb4f12c1176b01550fe7a74f750dc43d6fa4718c33ba99b0084c7a1a8e245c8566056296aabe13af -Test: Resync -Key: 082c539bc5b20f97d767cd3f229eda80b2adc4fe49c86329b5cd6250a9877450 -IV: 845543502e8b64912d8f2c8d9fffb3c69365686587c08d0c -Plaintext: a96bb7e910281a6dfad7c8a9c370674f0ceec1ad8d4f0de32f9ae4a23ed329e3d6bc708f876640a229153ac0e7281a8188dd77695138f01cda5f41d5215fd5c6bdd46d982cb73b1efe2997970a9fdbdb1e768d7e5db712068d8ba1af6067b5753495e23e6e1963af012f9c7ce450bf2de619d3d59542fb55f3 -Ciphertext: 835da74fc6de08cbda277a7966a07c8dcd627e7b17adde6d930b6581e3124b8baad096f693991fedb1572930601fc7709541839b8e3ffd5f033d2060d999c6c6e3048276613e648000acb5212cc632a916afce290e20ebdf612d08a6aa4c79a74b070d3f872a861f8dc6bb07614db515d363349d3a8e3336a3 -Test: Encrypt -IV: 835da74fc6de08cbda277a7966a07c8dcd627e7b17adde6d -Ciphertext: a91f3039c37f753857510f121cbbab8f942b41a4d04815729361268c84abed9fd3dd2c0a84ea5dc3cab46245f720d8f0fd81ce4c7837aae561186f66ae70db9e5c2238f1b417b0ab001eada16d1f9bcc2ed74d335fe8da60bebd8b1c4ae4c51d8c46eec7d1fd575a5824bced85b02bfcb1e11d5686471b2791 -Test: Resync -Key: 3d02bff3375d403027356b94f514203737ee9a85d2052db3e4e5a217c259d18a -IV: 74216c95031895f48c1dba651555ebfa3ca326a755237025 -Plaintext: 0d4b0f54fd09ae39baa5fa4baccf2e6682e61b257e01f42b8f -Ciphertext: 16c4006c28365190411eb1593814cf15e74c22238f210afc3d -Test: Encrypt -IV: 16c4006c28365190411eb1593814cf15e74c22238f210afc -Ciphertext: c86458ffa23d50437f3385ea7d3fbae5cdc1df7a14658b8316 -Test: Resync -Key: ad1a5c47688874e6663a0f3fa16fa7efb7ecadc175c468e5432914bdb480ffc6 -IV: e489eed440f1aae1fac8fb7a9825635454f8f8f1f52e2fcc -Plaintext: aa6c1e53580f03a9abb73bfdadedfecada4c6b0ebe020ef10db745e54ba861caf65f0e40dfc520203bb54d29e0a8f78f16b3f1aa525d6bfa33c54726e59988cfbec78056 -Ciphertext: 02fe84ce81e178e7aabdd3ba925a766c3c24756eefae33942af75e8b464556b5997e616f3f2dfc7fce91848afd79912d9fb55201b5813a5a074d2c0d4292c1fd441807c5 -Test: Encrypt -IV: 02fe84ce81e178e7aabdd3ba925a766c3c24756eefae3394 -Ciphertext: 5526b8ff95272e95ad298c30f9f165353ecf0f68aa2943476ec53c386cf07c465b677be13d01279779965dda94d23fe9452dc4934e344c2ee0f6f5e32efc2b3f79630492 -Test: Resync -Key: 053a02bedd6368c1fb8afc7a1b199f7f7ea2220c9a4b642a6850091c9d20ab9c -IV: c713eea5c26dad75ad3f52451e003a9cb0d649f917c89dde -Plaintext: 8f0a8a164760426567e388840276de3f95cb5e3fadc6ed3f3e4fe8bc169d9388804dcb94b6587dbb66cb0bd5f87b8e98b52af37ba290629b858e0e2aa7378047a26602 -Ciphertext: 516710e59843e6fbd4f25d0d8ca0ec0d47d39d125e9dad987e0518d49107014cb0ae405e30c2eb3794750bca142ce95e290cf95abe15e822823e2e7d3ab21bc8fbd445 -Test: Encrypt -IV: 516710e59843e6fbd4f25d0d8ca0ec0d47d39d125e9dad98 -Ciphertext: aadb7c36647ded09fca7587edfa9bbe81911925fa8996330c8e7b77601075e5f94404db9f82c67e2cd39d1649062d4c30cf23bc28f9ddd6d5b9ec586a7de7f8ef45560 -Test: Resync -Key: 5b14ab0fbed4c58952548a6cb1e0000cf4481421f41288ea0aa84add9f7deb96 -IV: 54bf52b911231b952ba1a6af8e45b1c5a29d97e2abad7c83 -Plaintext: 37fb44a675978b560ff9a4a87011d6f3ad2d37a2c3815b45a3c0e6d1b1d8b1784cd468927c2ee39e1dccd4765e1c3d676a335be1ccd6900a45f5d41a317648315d8a8c24adc64eb285f6aeba05b9029586353d303f17a807658b9ff790474e1737bd5fdc604aeff8dfcaf1427dcc3aacbb0256badcd183ed75a2dc52452f87d3c1ed2aa583472b0ab91cda20614e9b6fdbda3b49b098c95823cc72d8e5b717f2314b0324e9ce -Ciphertext: ae6deb5d6ce43d4b09d0e6b1c0e9f46157bcd8ab50eaa3197ff9fa2bf7af649eb52c68544fd3adfe6b1eb316f1f23538d470c30dbfec7e57b60cbcd096c782e7736b669199c8253e70214cf2a098fda8eac5da79a9496a3aae754d03b17c6d70d1027f42bf7f95ce3d1d9c338854e158fcc803e4d6262fb639521e47116ef78a7a437ca9427ba645cd646832feab822a208278e45e93e118d780b988d65397eddfd7a819526e -Test: Encrypt -IV: ae6deb5d6ce43d4b09d0e6b1c0e9f46157bcd8ab50eaa319 -Ciphertext: 89e9c51abd31d6156b96c4e82ef0dfe5c376bd6324750fdbc46e5ae63897323c816fb5bb8e6bf4335853e512cc334dbbfecccfe4e5c8fe8289963ee7127f3ac56bc26b7bd4f0d1e0afb06bde930e7587eedf07995d5052bbff5453147c1555a7c8534111295bb5ab9e89645cc330ae3e0d9294c9e7d6d841579e93aefeaed879f8e8299459a3c07e3c9dee497360510668c5246970ad39077e8d8935b0d885f11d2f06dee0d7 -Test: Resync -Key: d74636e3413a88d85f322ca80fb0bd650bd0bf0134e2329160b69609cd58a4b0 -IV: efb606aa1d9d9f0f465eaa7f8165f1ac09f5cb46fecf2a57 -Plaintext: f85471b75f6ec81abac2799ec09e98e280b2ffd64ca285e5a0109cfb31ffab2d617b2c2952a2a8a788fc0da2af7f530758f74f1ab56391ab5ff2adbcc5be2d6c7f49fbe8118104c6ff9a23c6dfe52f57954e6a69dcee5db06f514f4a0a572a9a8525d961dae72269b987189d465df6107119c7fa790853e063cba0fab7800ca932e258880fd74c33c784675bedad0e7c09e9cc4d63dd5e9713d5d4a0196e6b562226ac31b4f57c04f90a181973737ddc7e80f364112a9fbb435ebdbcabf7d490ce52 -Ciphertext: b2b795fe6c1d4c83c1327e015a67d4465fd8e32813575cbab263e20ef05864d2dc17e0e4eb81436adfe9f638dcc1c8d78f6b0306baf938e5d2ab0b3e05e735cc6fff2d6e02e3d60484bea7c7a8e13e23197fea7b04d47d48f4a4e5944174539492800d3ef51e2ee5e4c8a0bdf050c2dd3dd74fce5e7e5c37364f7547a11480a3063b9a0a157b15b10a5a954de2731ced055aa2e2767f0891d4329c426f3808ee867bed0dc75b5922b7cfb895700fda016105a4c7b7f0bb90f029f6bbcb04ac36ac16 -Test: Encrypt -IV: b2b795fe6c1d4c83c1327e015a67d4465fd8e32813575cba -Ciphertext: 0a8a907dc7f30f6f68eec465ead25768383956a304aa32e4ccea6e3756cbb19f2751e3b68339ade1499004a88170e44620529d3c568cb1e014c16548830dfbce1b47a2dcdd28e59bb0daf5908c5ff51817bd119fe33bda07d63e93a3522685eb101d912b02d093780d10884959ae4a49e2fb7fca51b81394f09314879a41f6dc2f4a7dc34e88da4747a5a1fc15dcb207d13222f08f91f079eafbded0d6036325f607ff29ff2fc7635e8c3767d61a3b7814227d6a2798d623bfdf674604e4e9e03529 -Test: Resync -Key: ea060c72f6e0080fd4a9a2131c9d684902415cab34fce4e52d62273e3c385f37 -IV: 5826043957a27509423fdd82f34935928a4b23a84ede72c8 -Plaintext: 20ae58dbf5c20225c35518711a86a19a61d5ba47ab17e8c5fa9658333d40ed31bffb79cde927c36baf61ed8df37acac330f64471bd91d90bfafa72dc8cdb6ed95ec6610cd6e8f2859255216a3eb4b573410d5644a40e4f0fa785d556304489c0023a1991eb0d01b5 -Ciphertext: 6025c4d5bcc769cc3e67b88340b4101690eb283654c761f8a0af360926313129f16d1c9358ecbaf66acd85787c7c1f52a953bc05e91d43bf3d94d341bffc5913435fb3a8e6264ccd1c355472929a140fe30a22689b055082c70395e0b070a3f0967ab36848cdf3d9 -Test: Encrypt -IV: 6025c4d5bcc769cc3e67b88340b4101690eb283654c761f8 -Ciphertext: a420fde6c359342819ed9c07853c594c0098fd2a3c8da24713dbd12261b528e43af7dd52ddf1a1b553d08c20b0ab399c38a067fb115368c990d9e839735c8427aa885eacb5c2900d1d04afdd3d35793f11c78dd826c5d09351f39823a13976eaa5a49b0bdb054043 -Test: Resync -Key: 115aaaa3a3827fb05175412dc6478747d7c128ce2637b6afdfe3213f7b0b6991 -IV: f8cbe32bdb4c8eac3a571f186ef683b9eb902302ff7ac746 -Plaintext: b09472fbdaa3e4bdb7b04c8819fb3257f764154d09cea22e9a67b40f7e601a97c469811773d2733eb4ab0da6249f237d4c063012fd06714a726b24a512daa7e287d39818980a6720abc45f10aab7d71da318244507b5a9d0aeae76ec5efd3b5ce167c38196744d13b07a14805ee49dc4421e0c59d559e8518a9911682ce1d2b307ccba48dd98c003103421ae6253c6a2476dda5d11cb3d5e7d6dc2c02499d5731095ee89f77c7d4ef27231fd6e9e854d1ed84b0b47bc4794e68e055e1d83d75ab527a53ebefa4d363f952562ac1aa47635296d55e2d5d1b8e214c95445bd586c7f82b31839ff78a60f0063 -Ciphertext: 50c5e2584d473a696c797ff1668137e331bcd9a1ecd5c146422a9140de87c10996d407c5eb8335b5bdb7a9b1613ccc198d5157c6f89d409e1ce7958605d68d442e1b10179c13e12ec33f98d676ae4be95ac7a82786402b1491918a6526e9676037d04fa7aebfd9afd39f6d10dc663877ebbb67aa82c6089529218db9622bd0af7e722e72265e25524d827da8eea6d7e0daf94c516ba24ecca2d820959c0dc939252158903d97139f6fcd81752deb3e9108fc62178bf54797c428e0887d1849fb5004c3b76f0d466afffd47f5066d6dfcbe4782319738e90fa19de6b99861bfc9e8112df4573bb38b1b9e35 -Test: Encrypt -IV: 50c5e2584d473a696c797ff1668137e331bcd9a1ecd5c146 -Ciphertext: 280303c6467f6badc300961c549c33f249c6d2df0596a459383b4c995b296854dea2072d04e46cd47c3380c4be6f6456e8759a5ab2025bd20ae6d116b0bba77b4f03aaa118c73e50f48755a89474c4380e8bbecffc4d6c84514711094ef67c2ed8b81a07c2afa41a19709e69d0bea22067eb3ce3618d80066f9c9f333eea1a624cc4d4dbfb0134004d1d6d295751c7a134cfd29cc85045734e2a4400c261cca16bca4c7e4622837eeed6ddc64c0999347248081aedd3f4d911ad5c92aa491b05510adcb0bcd7c0711a964f176775f11d8b00d9e4264afbb4d6b6a81760d964ca495485895ebba1dd1d2bf9 -Test: Resync -Key: da4147528d2e7862009aa772051e60e309721eeef4b4bcd7f98ae8d0561960b3 -IV: b625057bd07c1385fc08bdc14d735e5832dce5aa0045d9e4 -Plaintext: 6db3a848beb8a6e9670ed91427364c9b042d000a14eb2ac4c6097625e20b2e8eb367c156f927262d2251974d5953f17d00b4ed6b4d93513a19ee6b4f1a159bec8ff94151a7bdd6074d12d343fd852fa69a26302a11caf57417e950723c5a5e795de4cb6523fede7af6b6cb68f41931a1eebea6079e8018fe4116e7b03df7 -Ciphertext: 399c5bf3b894e3dcb5881fdcd927d8cf4ececa5140b2425df5cb2cb993b6901f736e94fb847de41b7c32ae990510402ce5e99a34b5acbb3b5aefbe55be4707025ffcfd6605b6ebeffca3c1ed3c42cba900eb5f14c195e5c574eae67e7355b780403e44ebc91f81fb04f95759f78999fe619d5b8f9fb2185c0e14cadfa8dd -Test: Encrypt -IV: 399c5bf3b894e3dcb5881fdcd927d8cf4ececa5140b2425d -Ciphertext: ebb1d4ebb394e185fddd72fad5efa8434465a9ce758fbdae25cdc6b1278b2e137f5afa706c5a8e95684fcf6645c6c2f67f698621c7d6c7f1899be12e2f6c9e480315c12f02405b8bcf45f4a715eeb72f12e0fef15740734747764e698ee88d05ab30028c9ee237a48b50c8fc453b7d370daad88e57a572a9cb8091526861 -Test: Resync -Key: d61f8e75dc9295dc029292764f3ed08dfb6fd725cae4b0e47aceecaefcf654d8 -IV: a6046a92ad15e9f9d8027ff39bfbf534d46fec35bc9cd94f -Plaintext: c11f014781804645ca22ca213a5558a038090341f3f70aa1df0bf135fb8d0184d77783b519c9c2b2b0b748880a85bab986de7a37a4a11bcbb5c0c87676d7808fd41abbfd0d7a11a7c545405a4ae42f60baa22ccee6de0272e79610c7b885b70ba9bf027657abae393cc8f56735faab9f6fbe36e7a4d99ce15cdac24223880bfb5865ac7acf01ea833098fb148406e6 -Ciphertext: f3b2a1188c33e96124f383b8b75dcacbf782f728eaf436db05551ae2be1a77f09c9ea009d8651329d0a812580d1e11d0f64c44e245bf30dd9c8033b72d0e5049131063c5fc2a3f219e6c1bd993c8961cc174eebb655574dd45b73d0d804f5190f92e385dfd7c2a4ff430ed6dabd41db040aca8ece7f11de796478026f48337f763cf69aef12609384f0ae72ee38c8c -Test: Encrypt -IV: f3b2a1188c33e96124f383b8b75dcacbf782f728eaf436db -Ciphertext: a9b213db6c8e161687e1b63f32a806f15aa8b3ee60cd37d7d437f90b446c3361d37893b702dfe774e5e5ce486399cd408fbf6ca1005768bf7825130c061e43f6077080438514f1a8ecdc6ff7cc264122b1a55c849c76328e833667326f23670590b77f2bfb9a666bcc4c44c16efd6c506c37ec62de8e5365ee894670ac4264b807a8455d8df05ba45af51ff1fee343 -Test: Resync -Key: 0f2850f98634181f49e53bf49d2f822fbf75e5f77c6cd7487541c514a4101ce7 -IV: d6defb4e74c327d89123bdc1d1c6d2fce6b745079bc2c9ef -Plaintext: a064bd9bdab0ee26530c2d26be556cd67295180bca445dfc87954bc51b28a21b606a229cf5a41fa104c51c3f32003a65064ff73e66691e4d2b1a22d236232be18677d54aba7ad49edcc9284897a7f88945513460166e5dfd7650959c05328abc0a7e95c352dbc227ca17 -Ciphertext: 51de41664070aec657612a57641c0c83ae14f5b3b25b25d916e0cdfae1c1bd21f7b47d9ab02b6841e115394cad58a568c1d7c2559a1d3fcd9cb4b25529d26e475ae313e6487538d16376a6b24e5cf27d2dbf4c83bd18996594f60549f34a8683b04d05198893a816adbb -Test: Encrypt -IV: 51de41664070aec657612a57641c0c83ae14f5b3b25b25d9 -Ciphertext: b5f57b5f00d2bf5f48828a4e793997e6d12b0f14953f5b1634cba91867776f75d2d2d247799a46080372046518416c60a07a65b2aa1318238597c320360a279e7633045bc43cf41bf9d366eafc7613b090a41fd8db3f684afc03d96c82a40b46e2994438febf268020c4 -Test: Resync -Key: 5cf680e8a11eb005d03fdc3d4ec0e129e6aceb47262dee6c452a5b8b0ef1b450 -IV: 6a6920ddba39b5a2640976ca10c97bf308a8cdd70ea98260 -Plaintext: 1f322b31f5f577a596b0fbe567864c7ce2973b41f924205defe08e2866b7fb5c1814d664d33957614e91668bb15d9848ffb93dc08c1f74c5f5e1f88148d1a1a7ad47395b75834de4988adfbf7e58a38157544c2be5b913152c1d00 -Ciphertext: 64d6c9ca4db201d95afc0dce28f6e47d51c2856ccbbc8f4c2e2bd2d834aca165dedd117b0be9a7dcd21eb22b508f4ecd0236075b064a0ced23e324b18b2bf2cda1c4416f78c740e51ce687cd37842be368fc4e6ba7cb312d89ea7a -Test: Encrypt -IV: 64d6c9ca4db201d95afc0dce28f6e47d51c2856ccbbc8f4c -Ciphertext: 9f4090fc504efc0f6bb5f76ac9881e1379da9f700737d86e9636714debc5c4eb3276fcff90bf71c32a71e06c199b3431475ab77410e83a7eba158723efb383a5437731a136758aaf7d39f0def719b0dd46798d9d53a30cd1b91eb3 -Test: Resync -Key: 9d27327495159927d0dd93e258908590343a57f6583e0d8aca07070ce41fd37a -IV: a01d1d7d1d43de5fcd60277f84dd8b93d08d480a77961f71 -Plaintext: e2ce8d1f9ee9329c3599e1880b9e6cb75d52e86f48ca89b829d4d7ca16d3e1b496b8b46097501793cdf6764ffd44b44013c7aadbf0ccfa4eab012529373a9022480f58877332b81f3c703ca80a77f429d944d5a877d89c6f64214c9ea6d3a098d9057d519354cfbb71a4bcddaee65de22e4d782ef0065952b891c9494d8a509e86d08ca31594015d3c31931d417cd048e59945d42ab74983434d14ef4e078f30ec2fe9ceb7e247d557b1d2593ab35896082c1c218dd73a868bc5cae74862b898395681234b20fa1ae9cab6a49b94bcc38a3a4a91cefc7745d094d9d8cab730cda4079705e4afd0f5e401 -Ciphertext: 94e0d546dbdcedd76e26629484ffd9b67b9c15f61b07df7ef0efce41270bdc9039ffad321c5b2d2847f6f4d5d105676fde08b8c47df248850dee1272d51feb42d503e58d67b61fff0a20abd999a5ad5942676aca3f31ce08614106fb692ae230c2a74339eb38c074bb59cf5ab42fcc428a0d629c12fbc3d845e84ed76c3f774e92c1109be12f00aa8ebd2a137a914e655081e6e60176cc98e849165d9d93235c605c8562f51bb407aeb8f330692d6245297817eebd32fa2ee96520b560e37019e9aadaea40f25ac4c5446fe93c5b39fc90152f088a5a936ba4efb10db7f246143f2cd151b1f1155e05a8 -Test: Encrypt -IV: 94e0d546dbdcedd76e26629484ffd9b67b9c15f61b07df7e -Ciphertext: 33203e910f56c5e1a63f3a801fdd772dfd1c3b0f3e012772bf0796337d95f4562c349f65557e76dc0aadb982d1aa3a3a865db36418bd1efcae36095fdb3ad68e1df72622d45d5336224caeb237adf9c19b02e23a1b9d4b32a5b6f39595a93d495a74cceeb4254e0b75f54277b80b153f62c8b5bdccae8d3ce24d8ee258f6d4ec6d631f6d1c8e8daa049d33076bea38acc5fda4a8822a16a693c936b340eb7951cd1ab0f7f58206252b0ebe46c77214dc86db136f8e170fc402f31e1c7ef9bc409b19260e4164c145aca28846ead4dc91783bcb1bd914a23d7bdf83745cb74c7ba66eca45457c53f42280 -Test: Resync -Key: b1a6c9bc9870d808a81612d0f4b335cbfd8b305150a6140627df06d9f8b24c0e -IV: 7313e9e505147d4a4c2023259ba01197169bac01af0d5bb0 -Plaintext: 479d7baf87a385c781f0dee6e51ee4f94eb2ee3e93bdbb3f402b0252496225d4118511ff893f4ddebcd31149920e259006cc7353ec5a95da4bc61ee6863282edc341afe9541d44958c2855b6714625ed2fde62db387e114fe837bbecee398351d187e0c93e0a0618f9d923504dd662c11e43af794e7ac7c99816c180ccfe1779bd2dd476ed68eb1736f421922fdc6696 -Ciphertext: 30a86c8b6a55670856e6d1b31d59602e05819022f12df1c67294fa138d65d5fd9f5e9192ad09604e08005537832d07ad5f4743bdbf137b7e18b8811066c7e411291fffc6e6ab55744789a225f15086173495279a4c628ffe4b1f8bb4d886bf74ada7d783b143edda1675ca9493ac1da04ae62584ce41c8a2c4f9fae79d94363bcf79c343e51ce5694c639bdbd8405781 -Test: Encrypt -IV: 30a86c8b6a55670856e6d1b31d59602e05819022f12df1c6 -Ciphertext: 33c313c0da87030169b7da6963644cdd257891b14fc1e4387d35faadc39279cca215e7079ec4272bc259e6499b0cb6dd52c6dff5965c7ddc9e951ac5c0056b4065a6f8eb5cc8e5373633a4aa3aa1736a67be11ef63c3418b1fe57730d6cce0f40e5bf02e61f6aae1404a813fd2a2a870960833be71dc73bff4a98718d64cb146a2ca5d41fcba85a56fa3d0413d0a807b -Test: Resync -Key: 4f9f97fd4ba7db6365f5fec9fde4e752c8bbde48a7ea986b878302e4cc8af9d5 -IV: 05788b5db4e3711eca900a2bfe6f78de44e98a70362504d7 -Plaintext: eb50b1e352f3fae6921fa7884c99365411928a2ffa33e3106768a773246c31cb0bca5cc166819b3b05819017f06c8b8932607db6d66d58d6a2f7356e4666ff7bec3a2223c12777fa54d9ed1dc139d9512c52e1e53762badc7e6f8da576afd940fb4a29d89e76fcdc93e515d69a6ca9efe5d053b7600b458b6719852ec4ad3c59d0b0a69971ac6ae53118c186f2d1a57e350ac3c8ad7d4e087c8f32816462f0506122fc01caa8c93aeebf0edf0c8e1cb726bfc861 -Ciphertext: c63f829e84c1c9709c49780a445bbf0dd441acc5304e0433ce0cd70af3fe98d36bd9e6fab17e6e8b50fda157e3ce9d2a928e8c234dd1700999047db4a28ea40a9657172a471f962d872a1d3342c12965aa1f1484e760979181ec8fde5472f509f76748fb4557b9b73fd517f70b20795caa1cd19e4dd5ac65e8f4cdb65a4ad60e0dd64407dc5232a5a893ace71acb35700fe059bb641497a2db63caf083942b7fe530092e90014bc5b6f889710ba3fc50d086fc32 -Test: Encrypt -IV: c63f829e84c1c9709c49780a445bbf0dd441acc5304e0433 -Ciphertext: 625aa1ac285ed59cb4b17da0ddb32a772eaf95181d0587fa92be22d1f5b65e403de9c0caa3301aa569ef9396c4cd06cffb602d5b5e6d2238712e74de51b0620733e1ba802038de3735b2a08951cbf17759f90cb0c4c4eb6a1acf147b54b7ac7372bafa4377fe7510d06a9c4ed6f972a669e270610a7084b61d4b52d2931803b805440b3d5e333ccdb0f3e7c0d013f068b2b402680a83210d71051da3529299343813150fb0f26ec053a8dac9993568e9b0c703ed -Test: Resync -Key: eee68b65fafe9a5bf2f9f92512a716e5af3740efea15e596f4ea0b5aef23550a -IV: 4d312f84330a107250b68c0b1df417ef713615b704d99b71 -Plaintext: 95ccd08ed2ab0fb87f55786f1f10d33c7713bef4435c3699b13982235ed040c9d9cb1b1f335cac0faf8654812f6874408bf20b129558a2c342c07c7f42a30700b374d18b91d881fc0f153f4ec1a55633a92d637212a11d122a9a1eb085439ea1226ea7124e8bd1c644a1996fa6369dedcacd5c766d7dc9a8c8682c5729ccf4d59433ba8e1569fe826089995414afd576ffb9686a30725fb9e5d7 -Ciphertext: 6c832a8147658a1741af29b0f558fa3773c81429f91a5cef270f7154988f97d4b28549604909f726a8a6e89d625089ea387b2725861963480424d9835d7e2fea93a5bd3bf86c7827fb22e7a68efea1a05c45f9606d4ab7add687d9418ba60517cecb3503287fbc5b2c9f0f9b5faa991337b394dfac7514dc38ffe019a1e7c74e5ad23f4e3bddb74ffc8a81f521d0b6044f98238f7c2a38ab14c0 -Test: Encrypt -IV: 6c832a8147658a1741af29b0f558fa3773c81429f91a5cef -Ciphertext: 7e1ef21dad49405e2fc86c50bf045eb14c65e58acb64e210af9ad8ebb5679021721312b96514d8681fa9d52c01c83f7d871401ec345a334648e0fc2ca294ced407ff98f1d1bc4afd83bb325072a5367d9a014092bc99699713bf84587fe2ee998bf8df35aacf61a96be157bddfd52e5b5a1d4a2e3bb109502e608f286aa8f0d5f67b4072ad9b60971ee8cf9fe966015260e61802f19f4bc8a29c -Test: Resync -Key: 188fbb5bea95b5101e056b93d8890c68e1328966089ebf424defa1bcb96e88ff -IV: b51304a0194bbb2490fced46fd0f39c3e87ea5196ca67ce3 -Plaintext: cd78c7c8f308addbd9acb6352d1b5b8a6ddee8a6f51401556e612d4c18960d152e6973381f45b19693e8ab6643424f01e9ab27de29f4ea16465d95674f7c939b -Ciphertext: 81a468948c618db0de96ad5cdd8b577c8253df097128cea4ffc7044f3eefa1b486b9159545fe135ea8a862fefa015f663febbd9b9527cba516551949013e9601 -Test: Encrypt -IV: 81a468948c618db0de96ad5cdd8b577c8253df097128cea4 -Ciphertext: 0510193beecfda67addf420e9c52130dbc8883cbe27d3e013207dc0ef3ff4e0b92e9ea2a2b644ffbab55c942acd63ddb7f1cff8d51d27b0a7d2853584dcc0bd5 -Test: Resync -Key: 2fb88c256a737eacf97ce4e1d13f1e20e8b2426f19076d7901bf6696f38a81b4 -IV: 12a82872b47b2c5b73cbb38904a08d283701eba289c057b0 -Plaintext: 3caae8a0c99f38cb7b2e45ea91dd5dc1331f0efff9f69a5dab0164693e986ba0da48a84321f618cc7e4b4e4d66acd8a71b69e23dbfbc6bca0c4ae279f3583b08705100adb7a4aecc0d72955a7305f4e7e2765b0a1bebea9d7e044e360d44b402f01357dc9a3e83fb46b48a683c1ad450a255bf45fe801db33414d985fd3a337c857d370ddd05c3313ae2eee0c8cb1d12a2fb650ea6e4851f2ca27badaf36dede18a9f8a62a502f6c2ff94d591cc27438e7215ce6e6abf76c22190b7201763cbc8d3a2be1f366f69eca6e5386883f56bd1c -Ciphertext: d446cbadf5afb1f21d7748a5973e8650d1dbdceaf5b837cdecf972bd091734a71ee1692fca675f4972d1e8db716873a03f9a5516f409982316cdc9f66ca0a8018dd055af0086397a86cf7574253d53fabd3aeefdc54dc2eae48b5b61a31dfb8db6531d2185034b81f745a3b88fa11453df073343de8bbd35a45f9cdff45b52e5352081f1f1a003a58200a4aefe27c87e930b77b8dc5b0882dc848437892e1902d126813e31ee27526d947bad5e8f9cf16a302da1a8f3883e3c9b257091e708ad58f4e716bb49e660cbf1f6fa709d64857f -Test: Encrypt -IV: d446cbadf5afb1f21d7748a5973e8650d1dbdceaf5b837cd -Ciphertext: 4125c6831bd2d39c1b1a2e12c505ca077fede7c553d486ae9a87ca3232d27974fb35c9a18a6315e5feafbffa943e52e9c46aa0eff6bce2f2dbf703c641ac570a92551f8a6e9aee14e8bc433b36e06bbefb0a292279f688e5d06dcdf317eded20f9dab8fab19298b146e1555b772d9f9c95e920356282ae691436a8505051190bd840b234fde486726dabec5e0755f4335b8ff4e30c30bd4f473a6af3fa3e7542f2b720784da760753938a682e86cf7ee18c5b5f7f515ff0380134d375e434934508f7cdd7602ffe2039a376d443c048103 -Test: Resync -Key: 7066fe1125429407b653fd090262bed2a3f7f3be2fa8f160f3344f327b1e53da -IV: beec3787c335739fa5d7ad15b85b7e3e7c9438367434872a -Plaintext: 9dad7f5ca1 -Ciphertext: 014a1f27cc -Test: Encrypt -IV: 014a1f27ccd2d39c1b1a2e12c505ca077fede7c553d486ae -Ciphertext: 20539f2d9f -Test: Resync -Key: 3154d3f5bb56b00b34a255425057e99ed9effd1cb0168d16157fd769ddc665ba -IV: f7f9f18f9648f6dc06ac643ea77f1493a9fea3390a98bb0c -Plaintext: 80a488703cf316be904ac8394437ea02ae2c027b7880ebec58416429ea060db543839d781d82a0fa209077e4b1 -Ciphertext: a07abc8ef3641cf33179296ca401bb291a9547d3e6d1b0886ac31d26d2f3281a6a568cc042593132a3cc1082be -Test: Encrypt -IV: a07abc8ef3641cf33179296ca401bb291a9547d3e6d1b088 -Ciphertext: 27ff7646fa8c6b98b1a732841e1596caba7b87eb40508ef0f8ef390aa5e36c0296ba84b686701d5e3d34b16508 -Test: Resync -Key: 81426f03ae1578d8ec1407827db18640d9d90d2bb773971f4ef14f859bc19e06 -IV: 479961f75954ed4f8024108cdb149ca3fd53e6a239a01e86 -Plaintext: 9cd08cf58e13e94e02c9a40269875392251353223f5329412e2a5e34328ea18c414d4c730b4e1c0bc140953f4ecf4ffc8aec963e59305d4d -Ciphertext: db3ea5b5fdc9671ec56b3f1cecbb2a552b0ea4ce9be508863f3dfb3238d4fb91b896727357fe454a08114200ea7226787fd2ab154d53eac8 -Test: Encrypt -IV: db3ea5b5fdc9671ec56b3f1cecbb2a552b0ea4ce9be50886 -Ciphertext: a887b52b3e97e6c899e1d68e57f283633ec9392438d17fb645702ae3b0ae0aad3a7c6eff0baff9f5357328307f628f470891884c264973fd -Test: Resync -Key: b3c260036b79cd3345e04cbee474dfea3a7c773db2ccb29d4c36a1b8c8b252e7 -IV: 1277840fe82046c024e6f4f53b4ff761c7c9bd1fea6c855a -Plaintext: 6a6dac1bc93b9b5c0dde0d1e6a534914dc2a6d51e6f8af3e9d42b88bedc2173782a2314b33f795cc2e4536829871d77186168f5461d18130581664586256 -Ciphertext: ff5e71022c6522998a2d10843fda170796a70d186e5fca2afcf529c6d075c5212c793fb322c1675d0bd3cc6b18f2715678812e81a8727a2d6ac1158eacf6 -Test: Encrypt -IV: ff5e71022c6522998a2d10843fda170796a70d186e5fca2a -Ciphertext: 7e8b5b4d250c13e38b5dcaa5532295e649ab3669fa594cf30eb81a54b25b3fed4f35be97afe4a2a37b7404acb41ad31d737fa9f272e1c57b3754830b4823 -Test: Resync -Key: 14fabd52e0fff9dae88d54815d82a56c4d4a660db5f214288cec1982e56fae81 -IV: 55b8328a312dff104c7f0720af0b7624f9281731b9f5f4b6 -Plaintext: 71bfc290baeeb0380732aa4312982c0dd0cc06cf2ee53adb0ae61c64228b80c073e7687ad3d3f888151b4066f415b62cf851d2987a3c816255ac40b62f453f350da8c4e1ec6dd0985e721b45a063381e997f629a7fbcd44fead19adc289f58f104fd37ec93a35305ba6fa44844d22e80a853e6db1d466ba2ad09ee2d30b3f47dd01b4d7b5d498cffd934cd3e005dc91e9e951951d5b937b319de0a7ba23c7918b1d74d3551b6500d39e6d626fa9cac8ec4e744713a93d5edc8413e2fba1d3b9b0f70509e38a66a2a2d70c510b57e15ac0c4b2aa7c5d6eb088fcdf6cbfef2c6dad19d7f17437cd261636c6d -Ciphertext: 7fc8bc27994031b3c35632590a15607ccaf1be15c542eea5b71ea1f7fa3abee79cb1281a00adb05e6fee4e65e8cba616a5789629d8fc617fae9bde9d92f6c8779374b1cd32a8e9277d0cb052c7658b3ab24ee1e55e5dd88a76266e9fb5661f576000968a9af71a3edb59ef3974e76aceb41c3de2fcb204a0022f302316eb01a0a8d74378599a7f72987e9abbd6f1a8af152ee89455840584010da73b01bbd7b01093a8c38049dc7a5ee0ee80daa98de46803ed75d0a97083ca328e7642a07e1c037346a280a856a64bba53b050272b7ba9742ef62aa89e34500f0efd7bce800bcac91981556a878d102ceb -Test: Encrypt -IV: 7fc8bc27994031b3c35632590a15607ccaf1be15c542eea5 -Ciphertext: bfd5908a43916afa5e2709b2e43ac62f406a4e677b855d70b216ae92cd444fa47f5568558c3cedece54e8b436e904e927175b455d96672a8cbdb4316b9e48a704216e30e9955ae7107f9f7770768bfd3ce71416bd337710bdf4e8789c8537a37f7c995c616a437ee406ca20c8f333a7c2f84ef87dac8c32f5b9678e344645bd356dbff32089fd195d982d3bb94b06b5b232580b492cb754659df62c9b5186b26bc2485409ff95bdc0c1c4c80bfaae878abebd373b159507b5894c5a9f8402447559b5aa7c3b491b97adf202847d0f74605a2502b193b6440a6b1765d538e38a2206630dfda4123fbbe4da6 -Test: Resync -Key: 75fe951556aae3d6ee93670241b7adac6907fd9285dbdf165834fa0cbf741b00 -IV: fff3e1ebb2e48520be552d2f0b617291c42a946f38804243 -Plaintext: 2b56b7dfaf5969d84a88aaa10dd12682f15d8a9a942deb6eba04a9a7ff38f2d0a947b414cbf7f1fca82d74b4ef98880368ba58ab7da98e8d6a6c46cc47cf0536961920e46095627b73737ea19e393c2f19d1f252ddd74b8fe050d95d21004b8997678eb565db0e369cb8bd326942e634a20845c61265da8a21448357f3eb -Ciphertext: 4b3bbef56b4400b130f8df0ab25bb28ece9160c430417060e48e691e6cc4ba119b0c34f5e76d4f1b7963785b4c6a9fb0b42c9f4eed92f8d0989710456c7f8d228fb26359f6e2549439ff5610dacaeb1df4f43a39cb3802ab1c87ce73f731ab1127ea9c2e82fb372be407a8c2b1af40398b33582e842ef0862f120a96c75b -Test: Encrypt -IV: 4b3bbef56b4400b130f8df0ab25bb28ece9160c430417060 -Ciphertext: 76c77925fc94b86624decfd2014fa505a6343054ae55c5be6d12c43018944b5d1c2aa08b9c11ae00d0c8779e70f220ffa59847969e54228d89b4351471fcdb9f0f76f18fcb896983d09dc5e8d9ee666f5abcb4d9e7bebbba824092c65646c3bee46d07609057e44b36dedfc02ce576506aa1274d550afc57d973fbd60294 -Test: Resync -Key: ea7bcb7f8712f9aa149a311d906dbcba443319f68a441a68a263c7bd0fe10fbc -IV: 620e57a9ce4b3d438c968e603f3c1518ab70be5b7bbecc62 -Plaintext: e40ef8606c72444fd3feeb1873f7ccdd3900760af66c269ad1ee6bf1e4546b1a556d4a90f6397527b270021c226dad5353a142c22963bb818548c3ed504965b2e6eb9744a15ca3c00fef2835d34592b90cc4bef8be904987dfc35e92f835ba15f054ceb760ad903d56c65854fd21f6a03ce9f8f16c04ef7ad9507b5cfa4b373eb544f2bc61bc16e371db087fb7bb749463c16f75 -Ciphertext: a31ae696ac9d66241bf9c826a381c4610de7f6416b153d7f8cc17484f1eeb63b2bc25d7c9b8a486e3e8eed6d34b4604ab5dbca373a80c29d50f416bb4ffb8485bfc6f7b61328f7c708360cf93370b7224b7cba075becafeb5cb62938b396dcc789900d8cb8315ceb460a753f20baabb4c6f61526a012e305c28bcb59fed20565ad1afce39f98b354b67a33daa8425479a07c0dd0 -Test: Encrypt -IV: a31ae696ac9d66241bf9c826a381c4610de7f6416b153d7f -Ciphertext: be217c97aca7ee0c1be18f1d93ccdd0f26d751bbbc36ca29f12bbf4afe83bbf7a749d325aad3b6af4913dbb83b09ade5ec79d88b755f7b2ba63df6ec458627c83e28e4742bd49396f19463bd597902de42ac46ba675d2f0c9db8d39dcc56a5e9233264be90cfed284302b965ab0f0748dcadcd02354c1f81d640a359b8ee5aa58a1908de1356031432b6f12e22ae9ee9f847f0a0 -Test: Resync -Key: 017f97c643425ef0ce5c0a6a0c6dd67aa6181e6aed360adcb103bba88773e1b1 -IV: 8189c8cd17a945196321cb6147cf483d785eacbea352fe3e -Plaintext: 145a3d3ac4c5b57d68d26a1ddabc71289929b6dbf317acbb3d83313c9e4861fa9d9679de974e4f7eea83129cb8f4221df16cdf545e000e087735cb37cb321d097b7b2f4874b74af6a6da9c429b1e62d418066bdff5ea0ed7c3 -Ciphertext: 90551d5f8ebaa8c1aeb52d893ddec3e9cb95f77b8bd5f6d0b3f8a3fae5fd8d9c1e42a96360e8e7e6cc9b7711ee1d61b4d67e6c2d682215c59a72778756dcc3fa93068889219579b2a1ddd85b0e69880913cd2e9be47b93ea70 -Test: Encrypt -IV: 90551d5f8ebaa8c1aeb52d893ddec3e9cb95f77b8bd5f6d0 -Ciphertext: ef58a8589c2996e1fd990d7ec412353edcef7dff079ae0ffbf430f3a479818352647fd8640a518575a3210fa45f7df5bd63532273d54c442ff02918aa79176c137cfea1a6ae167464183ae716a0f6057be891537059ac3322b -Test: Resync -Key: e9a7e6aba47b1d9c1df629c6920ded6894b85d3e7fd211bbcc7a9335e5cbf7bb -IV: af86ca3a196464931fd579bff601c9fe7fcc7a10d7778d22 -Plaintext: ee681bb5ecd15201f433a8f89871109aff85ed5a4a16a7ffe032fff60f1acca78cee6532f7740be05438da05933c8d29fc880533d589f6029291cd0a965113e042b27734968784f871f9e9e6c2a7342bc01fba3ef666aa0e018957169f2213f492acd0d2ab82dec47d8afe7a6bedee72d0c5c7ac0d86d0af5238da822ad4e6346cf2ac76faa64d34051a91659009976d140534a4f2a80f2758a912eed692b62bda4a46649fe58563707478746c77d658f481ebf90c2cd5ff3276fa8dc36739084640e319282d74479084a15838b9822056e900f2050d0f48ed52a3a3ffbdfe3a1831 -Ciphertext: b049fa161f19691f3bfa783327d2663eb8b7f188b301b17336f68630d8e001349f659428fd29359c15e95aa3f5a9f46a92d214e0085ab661b511831d00fb6f496e171b8c139def92be2ad8f6d94c2fde48f9d77ea338b920b2d8d6ad380ce761faf170bbc05128e65149b29d32aeec45e2882362dd2d0e3c7cf9634b9f52c578cb2e1d51b5aad6447f4d1860b1a1f1b7e45bcc002a5f4f03dd7116216414b0be23876b35ffb58f466a4087c992340437e89b12151a7d8f1af04aed585f5feee36f60c1b0e19251c7587e8590e7b6bae774f3ba5f3be2d726c8da4da3824debffedc3 -Test: Encrypt -IV: b049fa161f19691f3bfa783327d2663eb8b7f188b301b173 -Ciphertext: 7cc5bceb953ed1acf44c3a448a15f07c4e4db33f863bbc2368acfe699cd18f0580e3ff8545b946c15dd0f5c15e355fc4a10e340035e91c60b757cb69bbee8d2a22b20066b15929bf3506f2b271326509552b6430f4b82cf9b38ae83124f9b448dbbe049d7b3a98bf25678a72965f9656df149bc068e4cbea8573befef8c70b32d1dae7dc9b74601db95866dc7b5a3b307ac6ab9d09f3c55b6aaeb34c8b0e77c724666a4cea694ee90129568a46bb0f8380d8bac4f6151e84d357f32488ef8d62a08cb02255de04612bec676db471ea2199b9e86fb8ad89b259c0d1ac487cd95a5430 -Test: Resync -Key: af768581d5e401b02de76e6986de0bedbfb7130b9014727194c1d3f02c747fd0 -IV: c4568db83cf9eed0c05629951afa4fe5b72c055d89421efa -Plaintext: b34095f5b7660a03edb3e2277dcd3241270c9a7b890cd682214ff979b725148b1d836346ad84bd776ad748f6fb063c15fb763ca5005e9af95840f2677c1904090a19d83dcbf1011a48c23b620eda573b4a61bb8b86fbb7260090ff6f788a9dc27b5c95c3a3ebff1dc6f72446a23740179bf4dcb0169624d1ce2bf17c79dfaa35c7e12e313488919adf7e56f2d61cad070c164797b9d2dbaf5b954b56fd43e15b61f2cddde618bff31ad545ff163f2482024388ec470329835a8deb0f230760 -Ciphertext: 5b132bc08ec5bb09b5c92587a661c25ec54b8f65a581ab5f788c97c959e39cfb93032c6f63a489deac9eacb0b1a40b14ed152077fdc7b8b6dd5f94501d319d1f5cdfac56dbbedf8a5430843ca36507a363d5694e277ad8c0dcd0c0bd729bbe4b64823acff976f39973ae2d3eaa415f32db86a207f3220054306d99558e27ced2a683699a65d13eb67abb38230137de63c5c758a2149a773d403442cb826d70064c57aa4a778cb3e00a36cc4ebba6ec83dc178a7e4a3fb07c22b77a9c00e889 -Test: Encrypt -IV: 5b132bc08ec5bb09b5c92587a661c25ec54b8f65a581ab5f -Ciphertext: 907a2c78d9e0064b600c1d20985b6268b48cb8e7af87f615f8c298316b186ef64470b1c3c05f46096697d84ac390a3d2e37cb2306b718e7c48fb624bb1c5b3855951444f83e0433e26bbe2e05d8ad375633447a9f1c0856e35c6996c4fe4a477f503a47818ccd364b099b8d640ff2540f892e6a8e915a90b96b3ec13ec18e81a5c5e9f6054e6c90b49892e22ad1f0911a33740fe0719845f5428b0911b220ccec09a73cd8a790afe1ad4b76480c5e7718755fd2c29ea2f5f3cd7608ecb7bbb -Test: Resync -Key: 215f4b041d68a316d29cbea833a9d4170c32c5ea0aa34e90b4381e642f74231b -IV: 0b9e85d8e3d62b0c5b45ef1ead0b180348c0c82b2325beb2 -Plaintext: 68a7cfb070a3ffbb5a1456ff96703d56f84fbf74d92573368def92bde3b49dc9cf8ea87dd8a51d4c12cd9b4e1d20d5939a20b86bdb9fe5c76a10bef983c871c559741ac89155eb6d1a226c2a371c03f3bdf2b4bc -Ciphertext: 68d6236f9df3727c9a457609c0b59e393864855160b1e2074257f72d8b122c99fda40d6092cc96c8134823ab93545a6f8b43e8efca9502b5db2ecb86af5798b45639dc41b34df49782388cad7d1826d9d165b79f -Test: Encrypt -IV: 68d6236f9df3727c9a457609c0b59e393864855160b1e207 -Ciphertext: ab148bbc10bdb9a086c2c94c641225bdd8bca6f04d11a7cc5ba7eb728f1fd84522d3861a648ccae4e03f34162058f560028680d986c4a71e5369a312af02d135684b348b2cf42df1ab7ca841d474b3b51b8b52bf -Test: Resync -Key: 2ecbb5a282ee515b3226952d11d0579607f653a708d18920d18dc5106f76074f -IV: 53f67a3bada58382426b7d2142c327c7a9fa75a8634463c7 -Plaintext: 0878ed1298af132502bb5144066d26042e4a2990 -Ciphertext: f8ef2dc3ffca9dfa4d006bd9d3c00d7517fe0971 -Test: Encrypt -IV: f8ef2dc3ffca9dfa4d006bd9d3c00d7517fe09714d11a7cc -Ciphertext: 488bfbb9058907da6218b81138c26f306b3e214c -Test: Resync -Key: 473ee670e4b93e070c69e4c9f9d1a1808aca67c02dc9b8250034b9a19f0a306f -IV: c7bc3457a0d5b3384ff35ac10c8b09a114b09ad8e3d1ef6b -Plaintext: 09ba3c2aa122ee53878bf46711922fc946d67085ff68c3c5f07da6749194737b715bdfd4d052366fc6761c5aad4931808033b620f7e47d3c6bb65e355d66f4f577ee42a1881a853acfa6e710673b72ba15cc169333aef8fc63635ae5a7af8154d19409f57121d6580d10796585236812bdee04346084c9a831aea5d4be2ea248a90b9d71fb00823c2fdb522ff00e7482bd9d178766ad26807d963002104d3e42d2 -Ciphertext: 12fa7fe0fa0791d6a1ccb22f025563a9f61b1dbaf825bb59ae7523b531da1d720b816f42c12adeebe8171309aa65a5357d46e719e260af1ed2eb2096ab59a00f08671acf0e3a4ca67843641a5d9be4e2c00f8da7d37349f2560dabd133dab9dfe2ff6f3c087099ebcd2c4420b6485a8e810392310a8dfb61eb850ae70680882e98d8c97c1c922e6358c0ff3a6cb6df77f0ff86f4b2697c698c0440305d3ff03c1e -Test: Encrypt -IV: 12fa7fe0fa0791d6a1ccb22f025563a9f61b1dbaf825bb59 -Ciphertext: b069c6b32e99129d65d0e17dc92106edb3949710ea7f84638137073b706d790f4c57db477f4f40161c029f1663ca17fa6ffbe8f6d1e10d94718cc7cb75549307c2e3da305bd33263d7f80d8da26ddeeecb95a241f0d0dd636ca54f7129ee35bd49c707c52aff4a6fb5f520575d693949b8a1ece03cf093663c86b8cf97c89b87fc76cf76d9dce6791c499208fcf7a2b7e868f625a940b5721bee984bf3ba0925cd -Test: Resync -Key: 95d049394412ccaaa002264f391f2448837b9a9eaeeec49ae73f21c3bfb83016 -IV: deb9499a1b4043f0c116133700eae22ea61f45ffad305c03 -Plaintext: fba6e561dbb8d9d3dca1b6073d29103b758c463c5ad756920f66dcfe88fe0e4fc21b6aa382b6b96ef5785d51bf4c6b2375f7ca4494e711a34fef708ec09dd10311d312f7aaef6828f112ffa786263f1f9507ecd5fc3a80bc3fa75c17d272ef1c7cac66097a46df791d0d61a22a68dc4217f7ce54abbf7d4fd3fcedfb4d92c4a87657e15aa3417b62 -Ciphertext: a081927e375175dc84df664d824c351c9417614523e0c30d9fc5b6ab5aadcbd9d3a2fc28cfd7c11a807dfbcfdc7d28a54a5c44e52f6e9806a1c08a5fb06f322d22a91f5aa5097b9cb12ac29d5bdbbf8312fcde98b79c6cae3a26c9828874f9c8e2b072b6c1c70f15a1b6464c722fe183fb1367e03bb3991d8de30396aafe160b4669462ace11bf46 -Test: Encrypt -IV: a081927e375175dc84df664d824c351c9417614523e0c30d -Ciphertext: 2629e5e9e550bcb2d80ad3134a2ceaa80ebc96a68d4cb9b0bfc1e78b8b9b06b6ee34e242a174f65f2c74688b740aa9d52f14e900436c020c10b860f7cc8063dffa9b5baf2202a8ca05a3b52bea40bf7dc3c9444989f33e2ff0cc841742df284ea75c6dcfc9a2eee78dd9ce6b29255979b4abd333ed1ed92d19661850d42ca425a30d3aaf95a201d3 -Test: Resync -Key: 9a1831352b9bd922b41cde1ad94b40b3c2f622ffdd633d03f5638d2ca01b892a -IV: 4539205c887f099743e9ebd3aa4ef88ca7eb0a957a1cf8a2 -Plaintext: b4a37464a37b3691c7fe66a81572f535d780925b3b28dbc85b574edc2b6753278994fbcdac780c6f09e153fcd8a2ffb6e873c440dabcbd081e7bb35098c29dc97248dae7781dbc3b00d7c097c75a2f3cc88bf6dd1989 -Ciphertext: abc902e1dc5c4e5d858597347ebf523cfa233ffa1c38b7d8e8df8cb5dc75f08e74cc7077352efccdd18e39820bf03a39ae1aa56b3f07d92b148b26d6214d710167004b338c1f9868b6932b3d999e60f84ec839dc09cd -Test: Encrypt -IV: abc902e1dc5c4e5d858597347ebf523cfa233ffa1c38b7d8 -Ciphertext: 7b2d46034c39cf770b075dbf8eaaa19492e51e451d1ba97a0f4a71c466dea5dfa1d506ff3c7cb90fe276dfd73a6c0ce88e0df56ec0429872dbcae451dd19d2f3e58ac420e83c97909dce9673e7785cf3a11df9a0b062 -Test: Resync -Key: beed63202b4bb586cadbbb8b6893bc6ca2c07217a3b9275b499245aaace55383 -IV: d22603bfe4fe47187d969fce3aefe24beafb9337ef886980 -Plaintext: 375fe2819168ed3a1bfa7f46e037af06f202f1927b78606a46a35f41e23806817a4151872a5738ba76fc6bc736208124d2da5aaa952276125eb5ee95ab9668a7e773a2c429acf296979436ab21bf8bd77f31ab3023bd7fdbe28b93fe92ddabf0bdb1d990d628bf43942d728cddd330c8b79ab6a270877b789a714095074823637880bb380ad826c3a5ec6fd46c0e2b5887dbcfb101fd84 -Ciphertext: a9b65651c6b7b3a6322c21538d9732f2f31beabe4e94c288aff4cc0bd18dea04f15215343a07e16eda6eb535a04f0fa6100bbafd8fb7e89ed087e662cd5537ed321351d19b56a6dc4a8cf50078f7bc9bb9d2982a0ffc8d24e1814935a9ca38edc6b04105a8ac488437946af107e1bf0838db8ec4066646692fc61b9d94d09a83d63913838c1e88ef6845de6b32e261ae972a6b70e72d6e -Test: Encrypt -IV: a9b65651c6b7b3a6322c21538d9732f2f31beabe4e94c288 -Ciphertext: 685c9adf5239c2f521ac91e3a335267b34ce2aad1760f8771c51ac8c48ae1b93938ae2fa2f988b7c87a43c8cd4a97b5e65c2d11aa878c69349308922bf63dff3a5579d549d22c0028a336aac48bdba88cd9654e37746d2728ddf653c7eed0b0404df6f5a4342d0d7e1df8841da0a249313e105e2863d63fbed1ee621ef5e57f48753dbe3d2fc08d15b5244bdf0369c1741fe92fe3b677e -Test: Resync -Key: 8d4b9a4e7e3107c54a75a7c74b93ddf9c44adeffb07a503a05d6a5f287244808 -IV: 7abba4d58cf460f394f80bc9a080a355961c4a2511f50947 -Plaintext: ed3eccc8be0e5ae6d90eed3b15357050171716c7ae56bc9ef7224db5740257361b83aec0d8c7dc7a9e1df44e0f3fd1b8275bb6c5d6fb8d172df4918f39bab0323a5fa7c4a98aef3a482394882daf5403767f639c0d651f01b9b294d511876c4c3c471f7b684900c54cbbc1143d8aa690d7ab98a41fd9236c31692b7d2406beab5202e1b617ee43a6b9c8324404c4862e5fc0301ba8ac7d7b65df1eb36bf038c85e51a03f1b38a6fa74b0163657eebe640343b83a94ef09308ea3f98cc30ad9 -Ciphertext: 5cf10e20d44ba83ba4b201c7176846976b1a10a98d37f006a9b1ba01b4c81db6e97514d0dad76855d95483f3765b26ecb5f8403f8bd65a79cdc220bbc39a35538dfc757431c20b22cc825633a9af1be926f1072b38d2e89dcc903f2d257592ca97520c869abd4f2ec41b10adf0a2f7c56296975869dbc3a2e1465d32b7781991747ad3d141fb0c343419b76c5ce4facfc257f666c1dd020bdc8f189aea79d5c77e63f42da60510ba86ec2b1c934b90d77793b5951faf1c94b5e3ce38d869b0 -Test: Encrypt -IV: 5cf10e20d44ba83ba4b201c7176846976b1a10a98d37f006 -Ciphertext: e23e817a9c4c2740922734bbe3cc5fad938020ed34c0fe401d4da9cee010d4d1056b71d28856ea327d495c643d819d2d4ba6d97820909a7ac222b892aac4ab130610fbe29311f28432303af69d3dbd3a696fb35582aef9b7040a7e85f6c48d31a3d0c3f1cddb5251bc01a5ce0ace8c95882228ddf7c57aaf1890d70b899631a09af5f4130b436a69ab8623e0260cadebad595ba3d27da5df9e62544876d4daa3fe7af8ba8bdbb7246af0289903d69928c43a1c720b948e2d5a0e8b0d062fca -Test: Resync -Key: 39efc9016ceab203c0e172a335d7dc2916ff577f168904648dce170abf5d21ba -IV: e4e0a36fd930f726ff81007cc919ba0da8aacb5abab72394 -Plaintext: c1229356fb463b251270dae5bfe6772135af17b0624454edee3490ae95616c8b4efaab8a6b6f2a83b083d4ef19a86950c6b570d9000e94255087ecaeb56fead57eb8c51ef71fc802f9fd9d14f462fb5568d4206815e7f3473442b5f9ccc730fbf86a45a008f2b784d14791dcda532578e3ba17a0a3733bd518e15d2a65eb6c79a2130d988db4ee07f1f557a9a08aaa77f28744cf928829c940f70ec541a07b2646f4860fbda22f95cd20018deb68159aec40a889e534dd071a076b46d29a3445c8cebdf2ae0ea6ca7ecdfd203e5941581db5a84e66828f2c3e1b -Ciphertext: c885db1a0c9211392f2cf3cd655170409d53fa559acc66faf0f75766b4501ce80b739f51b985ab10ebcaae7adc2b58c1315ded28b77a2c1c1e3bb65b7d9866827a8b4a39f316222bf0522f3c4cd1ab367c6135cd1b104fcaf4cc746e12d3c72a5cf781d487e1a297d83822c6b68c1b5a9a9505a9b64963d64b2d50ef487057aec172cd070533c400fe0d83f79f4affb1be18fd9429d5dda1ed35c71d674fe98788e3b488bb3b5a781fb6689f8732aa8e4674a5df2643b03a332fdc3d5e10bee7014753a745b4e7bd2b579b8885955d8141fca840204da3eeceef -Test: Encrypt -IV: c885db1a0c9211392f2cf3cd655170409d53fa559acc66fa -Ciphertext: a65f1a87049667811331f8305128b6c06fc3becedae1661dcbac3a627d27cf80429687178b1ff1577cc99bee4b311c480dc3053a74fa523660e9af670d852a032e69b65bb2af61af8a2db4d3aad0a4b27ee74bc2203ac502d188975463f050e3369259d676881b1b318a1cd26094923d2c6fb15c0b522952c176c3cbc01252a4d64f875aea09a9295957be06209ae896410f5665422df60dc4038dc9ad1a45f16350bb433054b9a14061b5eed9cde905ea59f15bd1f58811dd4df49531138431e9d57a8a9adbd4d4fa472077ccf40a2a61affb82242db08f3d27 -Test: Resync -Key: 3070f0db09c523507d36404dac79038a393e9f0e3cf5f870b16d2a06da68dcd3 -IV: 4afe87bf79eb938d786ba54c26fd6d7e62261eeae8b62202 -Plaintext: f4ea120b47d15466ade07df0f2ff508759d9cb1035ceeab43920e9094fa50b868673b07173557d4b994b1e9d35078c1c7369df6b6adb2ec0e6bfd280fea8ac31db44beb0c2a4ddc6198957bd0592e3e587d304863b893ff8eee0efc70ced5d712651c3e9dd1a0de0480fd8cccbae4c50dccbacb83dcdc3e2cef7dbc645f0af468163fb0e015ef48ad74694dfbce2db8430a6e91645fd16adbb72e21a0fbaedf5ecff829cea9cbc22f82902748aa52da5ce903d9f2bde77efef5fa3970c720e89f25dd05157247bf0de2d2129c3f856238d4fad -Ciphertext: 46f396f0d2d54189968bf56b5b2f35588c3ad851e00fac6507598f3ea0193a586c00b18677811cc305b0261d9aebbb9c0485a5800c940aa4f09c4fbdede12553824c429c7954e0b8dad889203d292517b98a64e8d7a37c1364eb0934751323d9b9f8498f50d729e977fb742880222f22ac5d7bfebe6905a4c344d82027398a70c334635792deb0f20b83861b05e731f5627aee17df20413c79957556e66a970085e9ad40a73d9a964381584976c6f111619a916fbb5f5d305df862d5a56bac9ff9b436f31c85f34ff890b5ad3299eda2b8642d -Test: Encrypt -IV: 46f396f0d2d54189968bf56b5b2f35588c3ad851e00fac65 -Ciphertext: 358a8f5e5c6fe93c3d6d7d2f90f5973ba2c0cf7c4579c92a52d1ce6203ddd90188d3e36ff7cbe94e7adb4ec7596e89edcf3a94dba1fe64eeb24e8bec5fed2ef6faa4f0d16faf5853e8f69ee0ca0e048658507bd155bfa13d487c3b994f3a1b8871996eedc2d899d9d79ecd8ff968000b863337dc04d9ad8d05696659f8a1cae880e471621ea13ec42d163eecfdf9cd07bf0b10d6f4634ff16d26c700c88831efc82ac0abd0269b93e302422cfc2dc4088e28bc22ed6c06c9b51774bf3aa4088a6a18fa3d3608f9927837efc3382b25a7ab873c -Test: Resync diff --git a/embeddedcryptopp/TestVectors/seal.txt b/embeddedcryptopp/TestVectors/seal.txt deleted file mode 100644 index a1ca35f..0000000 --- a/embeddedcryptopp/TestVectors/seal.txt +++ /dev/null @@ -1,137 +0,0 @@ -AlgorithmType: SymmetricCipher -Name: SEAL-3.0-BE -Source: generated by Crypto++ 5.2 -Comment: verified against partial ciphertext from 1997 SEAL paper by Rogaway and Coppersmith -Key: 67452301efcdab8998badcfe10325476c3d2e1f0 -IV: 013577af -Plaintext: r1024 00000000 -Ciphertext: \ -37a005959b84c49ca4be1e050673530f5fb097fdf6a13fbd6c2cdecd81fdee7c\ -2abdc3e764209aff00a12283ef675085c1634b53289059e6a7ab5ed9480c01eb\ -4c64569a8dce2a23feed0ef58f6f5ac3f74145127dbcaec4bcb6b1a459bdc287\ -58ba0523f721c3e154433dc7353f02ef487b07ad309ef5e44e6cc19026f5fd57\ -07cc32ec12b9c01fe0c58beb2fe73ea79e24093f05911663a76b21beab18cede\ -17275c54d18fcd3e4cf32279347b22f8751119fb56d92f55d511e4ecc1334085\ -e74934455a2daec3f1821c54b4cb809053b8d837de4186600afedf8bd72dd56e\ -223745c19f76edba01e9b5346666d01f677fbd68fa5010fd7db8b06829a90da0\ -e81b84756a70946a6c05e16d225a2e11af586bb1c5b1d21f5349f8e5e3ee41f4\ -232d554954d1bc86064754b86c1dc92d7a9de30086d8eb4a7c86db9c380f13b9\ -52e11c5b89f1be0a6b52c6e7a053da7359c5fd7f50c70232d86aff08c5ff1746\ -d3bd074d79ad6fc657e0cbbe5d02c4fce55d3c31fef4642ed738f751430f2f1c\ -f6e453ef6edeb9540cec52c697d4864201e141e06c3ddf5aaa64a1a984247e96\ -d2cf1e7fb2bc239919369f4a0bf9d111d0d8be64afae86214d5f62e64f25e8f1\ -3e12680ec170ad6234cbbda938df53cc17a12afea1eb4005122a65cb42bedb76\ -edf029db910fc81b81f3dd28341fed4064ce37648548e5852d4aebb7923016f9\ -afcb07ae7bc11800e217a0062f0b53ffa8d471aa78ca6a13b7f5647189106773\ -0a311d6fe4ff57f05f9a58aa742696b6cbb3ec539da0c2aadd6a60d2a33c26d5\ -8a343448ed912aafb98568c6ae1cb1efaeafd81a6e3e7c450f8e2be4c6cc18f9\ -5e8a1c6c59190a2798e912a614c1e7d0f7e74b1baf8e5682f5442f998b24fa86\ -d1e5f673002e2c92db8ebf7abb1c9d267a9763f4bd54f7bbf07c4466dac0bf3f\ -faf5666a43a52f0812e76df5f9d4da8ed1bc6d4ab29b34718facb4bebc11e907\ -fe9b0e3937de7769fc5b0cc52b3e50d57e02b9b4022949aaf3698bc58f696073\ -ec972a425caee9700864d3d166130ee09d51320b9d51bc9b4aa575c789786242\ -0698d9e1f6426fd141a32c9f55c24e5149e274983035ac1c44833b0179aed63e\ -a2b2b61afa54700155e55c7c343412584f7b0fe73d63c5ad88718dde3000ac1d\ -b4050ae2610032e6b389eec48952a1a2ed0016e525ccd9616706caba89ed07d5\ -4f15ecfaabbc91b7c82c5904bc0f83d44888997faa11fe8fa7333cb8c5b16e31\ -52233c80fbc9f71d9ee8fefa50d67a7e45b93d3469ba4078bb1ed5859e7a8e62\ -b26bacf538507fa6bd43e18d67d7aaf27baaa68d233ca392ce33e257d5ddf3fa\ -ef6a951430d686f65ee9afaf6aee0677b41098922b41fba202ef05a27d614612\ -5daebeb147d617c8df42dba0b91dfbf8ab5805ee9877e495881035fbb7342c24\ -e24f3b85c88671184152ab0d395a9a81afab3bf93bea49cb23ee6bd1c9fb84e6\ -4ecd462f60119ceeae7f1d2150bd36fe7ef2782b0fd12b55df119a517103d489\ -0a739b715d3d33e2ae9fe659df4bc0136c0b243538eaa8f9b813043d66ae15c8\ -261c94c0072afc802668b3151ad1c0ab0f034eb3e8f2fce0c9fbc8f68404fb93\ -a1cd11f4eb9a5eeb9117462ea602ae41fbfe0074323e56e15deb04d41f3510cd\ -1df417f759f4c2bee72bab88833e7d3d9837801f16901ee12581588fa7037f74\ -073b2166405d79098098fb196cc4b1733e45796fa7fc977cbd23853e5943b2ad\ -e154856565a455189198f6ba50b9cc6fda0c309a413ccc746bc8261fd6b060f0\ -5cfcc82894125b3f1e0b0c47257fd838cf295aa13102724163a9fc2598fe8572\ -d0bf844518dccc1ee16eb8e4c9935b78fb969b7c3104091079079a7688f1e833\ -0335f63eabfdd3224a506bae4ea3022a8a4959f4fa410ad7111488a39e3c1cd7\ -a28ce83255de2c4477fe62f660af3b7ba049240aa5212e4e9fffd8b66fd51b17\ -0bdf6c7e7214361a7efdceae86878f49716c0859ce2e24979bae82d98025720e\ -06d7904c9646f1b1058b1a7c93ee4fd728c4f19051adf2ca30f4d54cf65be23a\ -7198e5be5765c018bbc1d2344fa8d1aa908cb8f789ea793c6c60d9a7ba9eebcf\ -7aee50a54810cbe3b632144956a157c220e33a232c169cc9ae64d6aa3560a185\ -fc2d94f15b389eebad8d07662c2be6d6349ece8ef88aea27d430ec9512ff1bc0\ -c5560862fa4a833af750d968e9fb545e3879571ec021735761da937e294820c6\ -585ae00e8023f48a4e1f392217df763a09e540ca615188345512179f8889902f\ -38c626ea3a333fc367818b058dbb8d6aa474ff3438b2de2b32822fdb93f77618\ -83b89223e0e616c885fa3414905d098d82a5359f629ed11589974393cfaf4695\ -da7ee36346d088a6ea6ef21ad6245da8de9956fcefc930c4e2759b596e3f98d9\ -2483b2bd82b74269caae2014f796ffcfe5db58759f0cd4e527b16f989d9cbab7\ -f20282ee2e666cc19ad64aa7a36193ff248002c762280a98f3ad2bf07b32f26b\ -eff5a5586d967d844aba69f7297bb1e28075273f39aa6e7c6c7308728da8ad30\ -31a2d20ebe99940732f93d0440b6e3b481774b69eb76179496350983031c2611\ -a27d885d91ac37debc02512edd06e1d10061325c5e04269c0c14942d10f03f83\ -06ef173d645478d79c74990a82df4b13f2754f273227f96988c25bedaf392534\ -69d73d642305f8058ce4713f65a36b822cd98da3fd805c4408d18dde4ee8e794\ -72e38f8683edbbfdce8d085e005407666eefba25d8c3368c6cb656a699b30736\ -31b8024eb6859019feb76bdb5a0d7f17c92a37fe6bcd14630c1a62bdde1e41b5\ -e9ab7306183a16c31554821ad44229ebce2e552f9a09fd1607dec8c92a1e893a\ -b80c331cdc7860093503cedfd44b3403b3501415916303baef0c68d12efa7c54\ -a11af3a7df5d23df98cfba907dafad0a8989c710d4602fc75f663fb16039d94e\ -f860f358bbf05ac9c34865141030513c4cda32e9b777d9fd9e4ebdc1ad0b24f6\ -799f815e29b8e2259f94b0215b94b349938556736d3ed578cdcea9024d71f174\ -376f05b3c203cc56476dd92d07ecf7e283cc181225a2b690eeaf3cffd35bbda9\ -c4ed0456661e2e39f6be537d2446f65cae13a6dea668b04f8f223601629cd3d1\ -1b75180dfea19435bae5e0622c5005371d4198b8dc1e0c40adbbe08d3651d345\ -4d68507f7f0b56d4bf2a328bb68854064699d0a38d7468ef64ddb4139644fabb\ -d21ad79b5f28a5612e445dc5673b2038e3f7dcf17a12ab32da214fb28500ea79\ -00491554da45661a03e2a878d1006d4fba8e22a7e5dded9b02fb8b5e6d166aad\ -43f8ef3eec4a7050a0304d46cc0be3ec97f0bdd137eea7c001bd8519101ff3af\ -76d1d7710c22c5b0a69c10df3493283254f5afa2ce4b3959d3be512e6ddb78da\ -30cc0a338d675c8fc3fcbbd313b696c660a85fa13ec9fa13ac8e8dbce8335575\ -608d5962ecb516b9ac186206e1ffb971924e9301e6fc220d0769ea1cd954e2fd\ -dc591ea026e369509d427ad062b81ca5e8873432a0d7a031b7f26702840fbb5e\ -5e9e6c8794dbec841822ca92aea2a22709182a3cda136b7b3569d85be6213817\ -06b2852b7de3e20907739958726334ad0c2c3b7327d0060b3f6cd319bf6666e0\ -9de3ee588abb948a6df37d5ac2b18c82d63ca0a0dcc6f1c1e2ae609999f60738\ -714df767fbf14b12b7a002ce0dad86f8adf777ff7ccc9b08180faa0d96b44023\ -3ca5398525eaaa9afba9e0ea4f2cfbf5a3e868f99ddc1a86ee36baf2ab56f9b0\ -b1ff1ff591033e579847267b9557217e0991d2c90e61f7e58321d9bdaba96c9c\ -63e9d3924f0a8c7ac6d4fc94d74d7bc1a96aafad76fca0fa4017d76f00f5cb5e\ -96058fafb57caf07cbcf665fea359cfa2cd4084796e3ea2ccf30bbe6e8f7efea\ -60190fcf2700d1d27b80ff53d8071aeee1ed8708617c92d821f83c9a7ea90c72\ -f19a58e9179cbed5f4f86a80c28e0fbc3fac50d5eea3117df747ab076044f1ef\ -61c7bb95ab31ca2f4f6e61d19e906230694158df40a72fb748dd79d0fd0617b7\ -24b23c6d0569d170731ee07dfd637820f10fbe860a179f2a24775b1f27a2e528\ -a5808d13cc3f995d2cf0c4a832915e19bd6293bfae8eeabcf85de223c4dea84f\ -0d095815cd34ab885d6c50816bf8fd07d4e58aa8c8fbf34344fc3279c1efa142\ -68471ff263f121bc501439c9fe1ae45c946b348a00535ae451d17f3edcecea67\ -5a7dde387813246bb8312147163f813159413fd550e00204c441b0eaf4d12c79\ -520a3d3bd75b00e20a5284457fc3999ac7ce1f1202e5bd651047c74eac7ff92d\ -7f214d6583304f6dda309a01230198b1e656c9707f2f27663c1855771af7f449\ -0e3f3f8da53f0492654a3c40d15620e2fd2a68658ecaa8fb5601775a393878a3\ -110d75e6b968db8eb81c2ecba5852b2eaf7f9b8967b60f92ee4af138a5e777b7\ -aad802e39d7237a17b4a79d9a467a4be1be5121de907400ee5586f0f94bed1db\ -35dcd7995ec93b49b0f6dc7a1e3e4cc0ad1945e60dbe0d24948eb94ddbc45e20\ -fe0bea593df4e6d38647fb623df65f6fbd1e36f318decf77824abd6bdf95eb8f\ -a5f29b650f36b77a305bf9c15b034a7ce1f482ccba079171a6476863a70bf49f\ -cc488177e461837c64d5f5419ae0a344010df2d6edb170b1461ef27024199b15\ -44144dc327eb225f1ee99ab4f07bf2f934042f2df86252c4058212b2e5cf35dd\ -14df206c1dba5445d41f211911e1053813a09e7fea3d5de5cac92acfe36b3ef6\ -8d4767c52a31c8ccba0eaa85874892d813ae601db1ffd5cd42ec1e98534056e2\ -753b5fa30f993016b787de9620a1242986370e005ff4495315c2b1aedb59a32e\ -47be953ea41f15fbe7a115d10328f67e59c538948ceef3f4a338a030ad198b2f\ -c89f067b336f28085a4ca061a38ae6190de48981de1c942ea83a9143b1faf94c\ -2f462a9de5d14b915bfc52e916d16f11cf59a28a3d933fedb48ac06b7cdd29a0\ -720ed851863bafe7a149f403881afe46b940ca37c29b7e49a730b28404179449\ -73274553b70fb11da65acc1c5420677288c624e67542f230da340d1e9b8dc5a1\ -90b69bf5e67e77929250a802f07cdf0716db567209774367aae32e0c1e90928f\ -61c43eaa372f1e9ec70aa0dd506734d23825213edaf184a24a1bb128811db664\ -783cb27cac1edd074d79d1259f84da9e0e5c75923a4dbfaa8a6283dd2279ba69\ -bcd1d78970d7a54a0d31c44071cbf05527010e2ff808cadefd74d906a8ad8c32\ -a01845d3ad78bc6ed96a688dfff171d80d931409d94c83da2bc54ad9790e9a6b\ -a5093384850090a961572f6fdb929a1a6baa98c015e95b0a6da10de04b8471c1\ -aeac19b6c887c1c81dad641d55ab1a29250d14dc41a042f83eb8a6bddcb662a9\ -3e00cf6adaed95cb52b36692f43a8e9b85ba7723d70e5ada851a16fe102ee1c6\ -d3bf8be1634ade9fa6b44626c734788b3aed0c287ab7e80ae5fc1451ddb037c0\ -f729309209226022f13e6f8aa592445db33bb1f29101e0df15db15df0bab6411\ -5bc12f0bbf430551473dbd274db2eea9905eab75f290ecbd903b675f1ad9ac2f\ -2196d00139e7671ac8b95a8cc8e244511d481863b509e5bb7573b6ce49cf0fc9\ -53de75523ca31a64012d11bb7f60f1f67b199a4f2013f6ea3808e2639eb5f263\ -1c19568bcf36071235de8ae7b2d5815e2e0a2e81098a6b4d6179e29ed0a92bdf\ -585a2905f0496ba58eb3d740efa54b664d1a6134fed9fede636504aa691e08e4 -Test: Encrypt diff --git a/embeddedcryptopp/TestVectors/seed.txt b/embeddedcryptopp/TestVectors/seed.txt deleted file mode 100644 index a08a102..0000000 --- a/embeddedcryptopp/TestVectors/seed.txt +++ /dev/null @@ -1,19 +0,0 @@ -AlgorithmType: SymmetricCipher -Name: SEED/ECB -Source: RFC 4269 -Key: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -Plaintext: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F -Ciphertext: 5E BA C6 E0 05 4E 16 68 19 AF F1 CC 6D 34 6C DB -Test: Encrypt -Key: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F -Plaintext: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -Ciphertext: C1 1F 22 F2 01 40 50 50 84 48 35 97 E4 37 0F 43 -Test: Encrypt -Key: 47 06 48 08 51 E6 1B E8 5D 74 BF B3 FD 95 61 85 -Plaintext: 83 A2 F8 A2 88 64 1F B9 A4 E9 A5 CC 2F 13 1C 7D -Ciphertext: EE 54 D1 3E BC AE 70 6D 22 6B C3 14 2C D4 0D 4A -Test: Encrypt -Key: 28 DB C3 BC 49 FF D8 7D CF A5 09 B1 1D 42 2B E7 -Plaintext: B4 1E 6B E2 EB A8 4A 14 8E 2E ED 84 59 3C 5E C7 -Ciphertext: 9B 9B 7B FC D1 81 3C B9 5D 0B 36 18 F4 0F 51 22 -Test: Encrypt diff --git a/embeddedcryptopp/TestVectors/sha.txt b/embeddedcryptopp/TestVectors/sha.txt deleted file mode 100644 index 7980daa..0000000 --- a/embeddedcryptopp/TestVectors/sha.txt +++ /dev/null @@ -1,59 +0,0 @@ -AlgorithmType: MessageDigest -Name: SHA-1 -Message: "abc" -Digest: A9993E364706816ABA3E25717850C26C9CD0D89D -Test: Verify -Message: "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" -Digest: 84983E441C3BD26EBAAE4AA1F95129E5E54670F1 -Test: Verify -Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" -Digest: 34AA973CD4C4DAA4F61EEB2BDBAD27316534016F -Test: Verify - -AlgorithmType: MessageDigest -Name: SHA-224 -Message: "abc" -Digest: 23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7 -Test: Verify -Message: "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" -Digest: 75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525 -Test: Verify -Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" -Digest: 20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67 -Test: Verify - -AlgorithmType: MessageDigest -Name: SHA-256 -Message: "abc" -Digest: ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad -Test: Verify -Message: "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" -Digest: 248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1 -Test: Verify -Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" -Digest: cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0 -Test: Verify - -AlgorithmType: MessageDigest -Name: SHA-384 -Message: "abc" -Digest: cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7 -Test: Verify -Message: "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" -Digest: 09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039 -Test: Verify -Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" -Digest: 9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985 -Test: Verify - -AlgorithmType: MessageDigest -Name: SHA-512 -Message: "abc" -Digest: ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f -Test: Verify -Message: "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" -Digest: 8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909 -Test: Verify -Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" -Digest: e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b -Test: Verify diff --git a/embeddedcryptopp/TestVectors/shacal2.txt b/embeddedcryptopp/TestVectors/shacal2.txt deleted file mode 100644 index 19a3d86..0000000 --- a/embeddedcryptopp/TestVectors/shacal2.txt +++ /dev/null @@ -1,5123 +0,0 @@ -AlgorithmType: SymmetricCipher -Name: SHACAL-2/ECB -Source: NESSIE submission -Comment: Set 1, vector 0 -Key: 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 361AB6322FA9E7A7BB23818D839E01BDDAFDF47305426EDD297AEDB9F6202BAE -Test: Encrypt -Comment: Set 1, vector 1 -Key: 40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: F3BAF53E5301E08813F8BE6F651BB19E9722151FF15063BA42A6FEF7CF3BF3D7 -Test: Encrypt -Comment: Set 1, vector 2 -Key: 20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E485005217441B60EE5B48EE8AF924B268B6B952D7F593E6102AC83D7DA72838 -Test: Encrypt -Comment: Set 1, vector 3 -Key: 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: AE70E355CB7E26FF12421F46CDAD5CB98367FE0E86CC234EDF97481765CD1AD9 -Test: Encrypt -Comment: Set 1, vector 4 -Key: 08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 00CECD0B01311F881018E7A20BCE169766C089D91FF161346C4E1BD122EA199F -Test: Encrypt -Comment: Set 1, vector 5 -Key: 04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 47A879CB6785AD37119C450CD50E9A36FE318FA8E7B6C6E0FA963430122F33CD -Test: Encrypt -Comment: Set 1, vector 6 -Key: 02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: CF3D53B9F9F7CA2C66738A4C09CEA9212C056F525BDC26F263FBA1B482EDF503 -Test: Encrypt -Comment: Set 1, vector 7 -Key: 01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A274D404E83E82817389A2CB7B528C792A0E80DE879A5A67DE633B0B7DD57B7B -Test: Encrypt -Comment: Set 1, vector 8 -Key: 00800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 09B3AB9332301D4E3C239D192A4221AFD43F6829A705D396FA96BDE1E716BC38 -Test: Encrypt -Comment: Set 1, vector 9 -Key: 00400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: D3B9AB867A6868C4400D200979055C8F9E3A6BFB40D1F9E376B9EC89223D7050 -Test: Encrypt -Comment: Set 1, vector 10 -Key: 00200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 4F27041481DCF574586CD6D5B72F2E806B0DBC351FEEA624112897A8A64CDBA9 -Test: Encrypt -Comment: Set 1, vector 11 -Key: 00100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 77CEC8EA64BB7FAE966D030FE4CF318C318DBEBAEB896F31FAA3C9CBA0AE125D -Test: Encrypt -Comment: Set 1, vector 12 -Key: 00080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E6F96E0217B8BDC6BBF30CB91C05325F493EB076E505FC6469AAA2BBB3A8A60B -Test: Encrypt -Comment: Set 1, vector 13 -Key: 00040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: ED949C1CFC555EC7192464AE86EC0334AD1198C2DBA36DB38CDF7160C950D474 -Test: Encrypt -Comment: Set 1, vector 14 -Key: 00020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 41EB01CC3875F31A6C8D7008C958BBB164813C59435B01879199979FC4762B26 -Test: Encrypt -Comment: Set 1, vector 15 -Key: 00010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: CCE7C4F96A665DDD23F39A78A3C7898E5F945FE908F1707DBED08BA6BCA3A58E -Test: Encrypt -Comment: Set 1, vector 16 -Key: 00008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 5FDBD5741AB5BC53E8C75F4497E37D5BE92B89D2424A11BBF189449AE005E2E8 -Test: Encrypt -Comment: Set 1, vector 17 -Key: 00004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E6C00B21A5B89F4FE9251E53E7AFE30D6C8721678BF842575EEE185E85632778 -Test: Encrypt -Comment: Set 1, vector 18 -Key: 00002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: FC19871F6E933014D92721D77BDF4E0EF528A325D5DC979536D6C46457CA066F -Test: Encrypt -Comment: Set 1, vector 19 -Key: 00001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A195202A93364212B989EB2C667EE05881657AD95FB6B3EE62DD21EB73347E56 -Test: Encrypt -Comment: Set 1, vector 20 -Key: 00000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A25B4FB9B4F8418514A1A04078DFBDF73B83B936A887AD6B1B672F1C2AF128CF -Test: Encrypt -Comment: Set 1, vector 21 -Key: 00000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: ACB2AB0F22068D36C160D668ED300DCF32C66FB8447594878DE1B1A83B414E13 -Test: Encrypt -Comment: Set 1, vector 22 -Key: 00000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A5AD217E39C9B40A921B4E52B1B47649C72631E7A99FE4897A92CD1A65BF8BFF -Test: Encrypt -Comment: Set 1, vector 23 -Key: 00000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 1185C198ABA5AD97F5DF7850284CD5E34BBE5E0EEC3CE4ACC4FC0A3CE3FA3BEE -Test: Encrypt -Comment: Set 1, vector 24 -Key: 00000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7AC85AA2C5A9A219B8E437C65913738628EE442F56BD57292C8A1B36026B6664 -Test: Encrypt -Comment: Set 1, vector 25 -Key: 00000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 6140F926FA90F091603D23A4876A3A5598890CB1F2FDE64E43C50630BE4101D2 -Test: Encrypt -Comment: Set 1, vector 26 -Key: 00000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 365135682290CB40D83228B3F26FD63266EED9C72DAC991510FEFA9B56466E8F -Test: Encrypt -Comment: Set 1, vector 27 -Key: 00000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 928EED2E262D9E398ADA06151ADFB35F34018114E97414C75E390C8EDA8D2440 -Test: Encrypt -Comment: Set 1, vector 28 -Key: 00000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E362280E66204F47E8FB782D18522AA3E1D527C15EBA88E76DB5AF44E156BB45 -Test: Encrypt -Comment: Set 1, vector 29 -Key: 00000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 807E3938AF9C9F0233FDA70B0E26028B390101F238ECFBD53EAE8E2D86552DBF -Test: Encrypt -Comment: Set 1, vector 30 -Key: 00000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E7D3FA388C4E07ADD32E188BD09264A2BD19F0F7EC5712AC05C47B49C7FD6651 -Test: Encrypt -Comment: Set 1, vector 31 -Key: 00000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 891CFD4A18F35239FD4463DE95FE9CAF4569AC82766E457315C123FB5FE6A397 -Test: Encrypt -Comment: Set 1, vector 32 -Key: 00000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 5C8E12B2572ED949494B324383806FD61B7CF0479DEB5D62028E83B7091BB039 -Test: Encrypt -Comment: Set 1, vector 33 -Key: 00000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 6F071D68C107B19B9949A6B7AF2C79EDC40FBA9BD07674AB3B1DB8CDE0A9637D -Test: Encrypt -Comment: Set 1, vector 34 -Key: 00000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: FD720D4ECFB7B68BA48C52E2F69FE268773D73B41723AA51127895B14C516F34 -Test: Encrypt -Comment: Set 1, vector 35 -Key: 00000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 0D3D7DEB1F8742BB22C4A3FB88C7C07CDCC8165ECF624C95FD8838D90D465B0D -Test: Encrypt -Comment: Set 1, vector 36 -Key: 00000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 06A524998D1FEA6AF6E4015B9A16B7A447F50AE0A8902E6E3308D3B47E98C4F1 -Test: Encrypt -Comment: Set 1, vector 37 -Key: 00000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 9FBDF43AB1294164BC968E113673BB11195AE39267BF2537F0E429E3C10B5D2F -Test: Encrypt -Comment: Set 1, vector 38 -Key: 00000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 81C4C7F2144555C888D876787EE62BC03EBB57093DB3DDE806918707684C8C52 -Test: Encrypt -Comment: Set 1, vector 39 -Key: 00000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: F62E7B237C98C5727D4F267AE17932AAC4DAEF0CAF4C02176B4CBB902ED164D1 -Test: Encrypt -Comment: Set 1, vector 40 -Key: 00000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 99CAD86B7E78D9B2ED9DA56F27C9AECB49CBFFC287930CEBC1BF06EA94541E9B -Test: Encrypt -Comment: Set 1, vector 41 -Key: 00000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: ED1F4429D5C36B2C16D598A2CE52D9C84E9DE7CD0B4899E47ADCB999CAEDB0CA -Test: Encrypt -Comment: Set 1, vector 42 -Key: 00000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3FEF41084D9CFF6111C40F9656C46D3892323465630B0C1D082255222847D9D0 -Test: Encrypt -Comment: Set 1, vector 43 -Key: 00000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: AB7D2B41135ED54EC7AB11C67D20BC35F0C8652D209D675AAB3A33FA264C9380 -Test: Encrypt -Comment: Set 1, vector 44 -Key: 00000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 1208F63F213F1A55127900FFBFEB0569B693376D9310C9A9E36EA1DE22CB5A59 -Test: Encrypt -Comment: Set 1, vector 45 -Key: 00000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 10C38678BC2465923063E41B4339D96F3DC5A64CA77A9C9C132D75BC4EC517F1 -Test: Encrypt -Comment: Set 1, vector 46 -Key: 00000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 5342519F1181700EDC380133226AE072971AC1AC6DF72440FD817C9ACB862E68 -Test: Encrypt -Comment: Set 1, vector 47 -Key: 00000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 09D02729C71C6E5E852272B853E87C1BAB5E522875E5D8063501ECE10315B4D6 -Test: Encrypt -Comment: Set 1, vector 48 -Key: 00000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 33D7D4F58BDD14244621A960A076573892ABDDBEF36109289A3E8A4EC536E95F -Test: Encrypt -Comment: Set 1, vector 49 -Key: 00000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 81A4590D64E2140414B913AC73BECEC19CAC798C313196007E39EF4F75C7DDB5 -Test: Encrypt -Comment: Set 1, vector 50 -Key: 00000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 942ED16EC4A9D72D74ABFB7E79CDE840997DD2AD83C9DDFAD02528A9A7E0AAC3 -Test: Encrypt -Comment: Set 1, vector 51 -Key: 00000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 8376BF03EAE71EF035E18903AC0CC2CCC93610C48050DB096BE758743234CD63 -Test: Encrypt -Comment: Set 1, vector 52 -Key: 00000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: B5613234B5F9D1201A9A581D59BD744B8E59728E5E330B74CBF03B9E81C950E0 -Test: Encrypt -Comment: Set 1, vector 53 -Key: 00000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 4750E864B881A2764EC508D0DD4AF06B7B1B123FDCCCA141A74DEAF28070B408 -Test: Encrypt -Comment: Set 1, vector 54 -Key: 00000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: B3F29EE6BDF09A16C4EA8C1539CD033B17706436FC40DEBD95DA70BF05BF1856 -Test: Encrypt -Comment: Set 1, vector 55 -Key: 00000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3A91B7730E3FE044B75E75B9BB09BC1550AD5AC9F495AFFB524FAD90A51112D5 -Test: Encrypt -Comment: Set 1, vector 56 -Key: 00000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: D262DF12E3D8DA99A9F7F011D607905DCBE9AB03C317E81E4BCD076F3C55EBB2 -Test: Encrypt -Comment: Set 1, vector 57 -Key: 00000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 827BD4A79FD82594F645A02F9546906ADCBFF47E2F2D0D0DAF89A200389A5E00 -Test: Encrypt -Comment: Set 1, vector 58 -Key: 00000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E83B866B294780E36058CBCB62BC3C509604F9EB9A44F1CFAFD50F248359A106 -Test: Encrypt -Comment: Set 1, vector 59 -Key: 00000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 8695B4BC5DC6528183B94D5257DC668DCAA0E5A855B76555B65FCCF941A8CCAC -Test: Encrypt -Comment: Set 1, vector 60 -Key: 00000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3B5D549F736D15CFD0F39A42CB1ACBEA370ADAA9EBC7C012AF2E30463DF98E03 -Test: Encrypt -Comment: Set 1, vector 61 -Key: 00000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 1C29F7919784BDF30E566B75DBA4C911FC48C1CD7F845406B86DA540B71C572E -Test: Encrypt -Comment: Set 1, vector 62 -Key: 00000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: D530E5B30338589A6AE67E0C1E2C57AF02CCEFF84705BC4AAD0D93375E7F2DAB -Test: Encrypt -Comment: Set 1, vector 63 -Key: 00000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: AE92CD3DA2022DC9C91E381DA62D8FFA646FD02A1A5A3249AEAD35B729C48329 -Test: Encrypt -Comment: Set 1, vector 64 -Key: 00000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 111318C5C6DAE45DF4FAFF404AE2140300DBBF9361E926900F3ED7F731385A52 -Test: Encrypt -Comment: Set 1, vector 65 -Key: 00000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: AA0DAA9A0025B5B3243367C7FC22F56F65A52B3CEEA060825C1FD2813953BEF8 -Test: Encrypt -Comment: Set 1, vector 66 -Key: 00000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 11EA951B966D0B3DF0D6AA00059281E6944CBB9921F84209265938CCE91F4910 -Test: Encrypt -Comment: Set 1, vector 67 -Key: 00000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: DFDE0D41A657B700DADED5F9CB341481A0183AC1BB51291E8719F77251B478F6 -Test: Encrypt -Comment: Set 1, vector 68 -Key: 00000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A8A42F8E3C2BD71D415EF9FBDBB9DA86B32CFC24EBDADC656B7BFF17FC8BE365 -Test: Encrypt -Comment: Set 1, vector 69 -Key: 00000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 1755CB48D8057669C488DF3A2296651F3FB64AA173DC6FCBD2C1113A084679C1 -Test: Encrypt -Comment: Set 1, vector 70 -Key: 00000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: CEFD04E10B318145993C0AF4B4A64F623BCE0E04CE04E6D3DDE14EC6DFC0CDEE -Test: Encrypt -Comment: Set 1, vector 71 -Key: 00000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: D9C83924493AE365C6369317A4393F904D530C1D30B2FD1A2E4126D0A532A743 -Test: Encrypt -Comment: Set 1, vector 72 -Key: 00000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 9B8FC0A924382EBD28AA3F6871B17E1BA9C94418FC3533B446C2DE8C188EABB6 -Test: Encrypt -Comment: Set 1, vector 73 -Key: 00000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: F91346BFBC0E05A4076B8CD5640E9DD278D4A7755A6D870565AC2A7E60A7F5AE -Test: Encrypt -Comment: Set 1, vector 74 -Key: 00000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 58D205808D4A580FF8111B9EF06BEE613D51E3B2E026B296F5E9F8520C7319FE -Test: Encrypt -Comment: Set 1, vector 75 -Key: 00000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 15D0C54FC35621B206A4A50EC3DADCEDFE4CCA17C9C5396A18901099A3389086 -Test: Encrypt -Comment: Set 1, vector 76 -Key: 00000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 48DE43EC8F644BCCFF61A52D93BEDEEBA38C71C196203A4A5AD9145416EFF31E -Test: Encrypt -Comment: Set 1, vector 77 -Key: 00000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 253057DA247A8D7A1B4A23E87B67D49669ADE1FE5EF32E08058F2DA6E82D1C25 -Test: Encrypt -Comment: Set 1, vector 78 -Key: 00000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 6494B08A0B0CE628E34EC6D7EFBC436687D242131974789ECF20911C0CF16839 -Test: Encrypt -Comment: Set 1, vector 79 -Key: 00000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 5088AC91D68173FE292A64D04D9A8083535649D44D7F00F23F389810F5F2528E -Test: Encrypt -Comment: Set 1, vector 80 -Key: 00000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: FFF5D0D5296B0C3553DD43C429F51AF844EB6100E373A6A7A16B79A73392AC58 -Test: Encrypt -Comment: Set 1, vector 81 -Key: 00000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 4A805BF70CBBAC2FACF405789FE96C4EF097D36F6982B843246C353E77539863 -Test: Encrypt -Comment: Set 1, vector 82 -Key: 00000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 5F5F6828D3D2FDF24B4AC2F1F4080F40E9564CD8F9BAFC34E5567F96E2F057BA -Test: Encrypt -Comment: Set 1, vector 83 -Key: 00000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 5BFAD855773EF036BAE365C18B6C5784E8BD4673514B0499E7ACFA38F7832927 -Test: Encrypt -Comment: Set 1, vector 84 -Key: 00000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: B38604950FA73165F940D4DB527D09CD0B233276CD3808B5CADCCB9FA859AEEB -Test: Encrypt -Comment: Set 1, vector 85 -Key: 00000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: B96570996489A74726A70C02CD55FB9D4C3ADE0B69FAE7C37899E3D560A5132F -Test: Encrypt -Comment: Set 1, vector 86 -Key: 00000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 0B8612F83912A9EF1082E9D08C772738908BCCD20DE47D64ACA1500633163479 -Test: Encrypt -Comment: Set 1, vector 87 -Key: 00000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: CCC75B4A84D08B14495AA8349B0AF79480FF6D0695561710AA16739A54504E58 -Test: Encrypt -Comment: Set 1, vector 88 -Key: 00000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: BC3F95A0CB0DCAEDB78E3D6E855267E34F3168C436774E28035D144406E803DA -Test: Encrypt -Comment: Set 1, vector 89 -Key: 00000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: BD0A34B0509EFA39D9D091577FC4296F563AF5F3AF9E030FCC3661C0BD82738E -Test: Encrypt -Comment: Set 1, vector 90 -Key: 00000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: EC82DA0C15A50EB98E97532C509DBAC9C392DB79ADDC139F9ADC6091708CD726 -Test: Encrypt -Comment: Set 1, vector 91 -Key: 00000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7F164D165F7585E8306E38D44211325D0C6C177C523F13F69DB39DFEDF5BFD3F -Test: Encrypt -Comment: Set 1, vector 92 -Key: 00000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 73F36AF678E74D413BE851E77F5E55DE1DD92D5237DBAE75E3AB6364D1F181DF -Test: Encrypt -Comment: Set 1, vector 93 -Key: 00000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: BE25140C4E7804B22390822501718BE09E7F494594EBD2BCB35A36AC2F0CA095 -Test: Encrypt -Comment: Set 1, vector 94 -Key: 00000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 33171A271100D5CC5CF651ABF60977CD15B718863213DC243CAFA6CA86041094 -Test: Encrypt -Comment: Set 1, vector 95 -Key: 00000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 323FF7A80198298E438C833032CE609D4E6C5C107C9069E8B216080DE5C0880D -Test: Encrypt -Comment: Set 1, vector 96 -Key: 00000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: D8FB3E266B96E48524159A3BE04CC85B3DB70F2FE649A01259E4FCCBCD3E7BAF -Test: Encrypt -Comment: Set 1, vector 97 -Key: 00000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 88B2171E37F3E861B6A69397BCC46044EABBC424E3359D11C96A62CB33F6C56C -Test: Encrypt -Comment: Set 1, vector 98 -Key: 00000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 96168ED95200986AFF506D3C2F043DFE03356345C52AD205BDC91423C6079824 -Test: Encrypt -Comment: Set 1, vector 99 -Key: 00000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 4FDE2AD110847B5F4F2BD20CE5047913B12A682D119D9A8C8395B9958771FC22 -Test: Encrypt -Comment: Set 1, vector 100 -Key: 00000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: F703282E54592A5617E10618027BB67F639E43A90767150D8B7F5E83054B3CBD -Test: Encrypt -Comment: Set 1, vector 101 -Key: 00000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 6673138D1A64DD26CDD2F62CAB0BAB2318DE17507BAA307A189EC4997F9C3F89 -Test: Encrypt -Comment: Set 1, vector 102 -Key: 00000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 328B2F4069F398422D78E359F19938B8BFBC9E073C2162A0829265CFD48B89CA -Test: Encrypt -Comment: Set 1, vector 103 -Key: 00000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 02B14A28344C4164DDF0EDB594D581AE847FC0090EE6B933B8B8B91EAE90F5B3 -Test: Encrypt -Comment: Set 1, vector 104 -Key: 00000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 506221E93DBCBA6787757CCBBB0D5CDE9D06CFE3A23A8942A13C5B3849B2D2B9 -Test: Encrypt -Comment: Set 1, vector 105 -Key: 00000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 53A01AD91AE1C7F0DCBE19CF701A895E03FD866F77ABC7B174B327A0576D7719 -Test: Encrypt -Comment: Set 1, vector 106 -Key: 00000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: B27AB67ACB784CB231A76D05B2539F0146F5C2F330987DE2C91AEAF8511DB9D1 -Test: Encrypt -Comment: Set 1, vector 107 -Key: 00000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 682263AAD3FF0B227983D20CB8A8B572427A2EE1B85A7FBB0961C722A7DE70CE -Test: Encrypt -Comment: Set 1, vector 108 -Key: 00000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E8AA0C754FBFB2BAF1025C8C13101552FA32E4031843E3DC56D2D819476CBFA6 -Test: Encrypt -Comment: Set 1, vector 109 -Key: 00000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7952391AEB6094458B28B543B9A5AC1DDB0CB18AEB431BE7CC7A4D45CCBEBEB0 -Test: Encrypt -Comment: Set 1, vector 110 -Key: 00000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 138599B1B9406E932D6229A4FFD959EE02E626022342FF233269A00DA1F58384 -Test: Encrypt -Comment: Set 1, vector 111 -Key: 00000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 87FA25FEBEFB539BFA46F9FAF8D62DB8E3C126D7409813A3B2FFC760FF19D390 -Test: Encrypt -Comment: Set 1, vector 112 -Key: 00000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 943B778E6053E3CBC59E9423A6D8AE678D369D5E27AB56D668DAD944D0A238F4 -Test: Encrypt -Comment: Set 1, vector 113 -Key: 00000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 00D31AA7620BEE29169C62966C53058F05709CD7C6A6584AFA80D7B2B7D9414C -Test: Encrypt -Comment: Set 1, vector 114 -Key: 00000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 9A6DD9EAE3286D48A7548C0A8A4CE8FFFB61B362C95C897DCD1CB1D8BBF76DEB -Test: Encrypt -Comment: Set 1, vector 115 -Key: 00000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 8231E89C8C74641DA6CD862B98B5DE749D6751B44361B763DF888F3D2312FAD5 -Test: Encrypt -Comment: Set 1, vector 116 -Key: 00000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: AEE13BA9322E1089262CEB199FD96E8A3C1E29142C6542961CA0B70782A4FD65 -Test: Encrypt -Comment: Set 1, vector 117 -Key: 00000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 89EEFABFFF030B563CAA5965CFF0372E0518BA1BF9A6E07D279C20AF3D52B9E5 -Test: Encrypt -Comment: Set 1, vector 118 -Key: 00000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 9EB46332AE8F271D9613A5FD1D6E1B06ED7A553C874A44A6F3A0615D46AA079D -Test: Encrypt -Comment: Set 1, vector 119 -Key: 00000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: FDB79EB3D755AC9338093917F84742BB1D62197D9730AEFCBAA9B3A4CEEC0B5E -Test: Encrypt -Comment: Set 1, vector 120 -Key: 00000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 64D439442C3FB4B580E0C7BC212F5589B395F6D100AA8165E4599A34F288D31D -Test: Encrypt -Comment: Set 1, vector 121 -Key: 00000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 09F8A382936078076F496A14B7BFD77CF4E549171FBDD8106AD0C2F87FD9C151 -Test: Encrypt -Comment: Set 1, vector 122 -Key: 00000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: AEB59849B6291FC1B8917642088608C4B9EE364C8C1FAE502F1ECD5BFACBC96A -Test: Encrypt -Comment: Set 1, vector 123 -Key: 00000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 006136B68224BF8BF47C0298FE7E2A4B72964A6C9F36EB709C452F0319B6A104 -Test: Encrypt -Comment: Set 1, vector 124 -Key: 00000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 55912F44A9A3493CF0A4DEF2F77978ECE0868ABF30BBAB15A96AFE15575AA90A -Test: Encrypt -Comment: Set 1, vector 125 -Key: 00000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 81BA612B664481588AB16246226CC1B59A08A7FE0FD64B0111C67C4BF344D2C7 -Test: Encrypt -Comment: Set 1, vector 126 -Key: 00000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 6B7930B1609C35095BE581F8F73709A65781DC1D49381411F6474CEBE6D16182 -Test: Encrypt -Comment: Set 1, vector 127 -Key: 00000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7308AEC23D25A231B26448AFE78D5047804C5011B9B5F95C16DF2670551F0001 -Test: Encrypt -Comment: Set 1, vector 128 -Key: 00000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: FBE855BD6540594E2D90566E7A30F57516EE170817B66C2468615D5D3D5DF03B -Test: Encrypt -Comment: Set 1, vector 129 -Key: 00000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: B072D598869D6EFCC8856A2B4686EF05A37DDB3F26DFEDA2F9C406B7250801F5 -Test: Encrypt -Comment: Set 1, vector 130 -Key: 00000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 0CF58B2665B889C06836E699DC2B4C615106541987229D686D43614D3BFC290B -Test: Encrypt -Comment: Set 1, vector 131 -Key: 00000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: F591E78CE6A8A375CBF821D222A49C862A461DC52C74065BA6349598CC7CB6EC -Test: Encrypt -Comment: Set 1, vector 132 -Key: 00000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A32B883113DE96B7AFD4ABE8E1703C8D724397542527E27F0CA32C89332980D9 -Test: Encrypt -Comment: Set 1, vector 133 -Key: 00000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 9B2C992F4CA0E70E0DDB03400AD24C4F20AD5F32940537B33F375C7979968537 -Test: Encrypt -Comment: Set 1, vector 134 -Key: 00000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 0DDEEEBC428F117B094FD27B614F6BDFEC0D71D61F8F93F9A09E0443F2FEB659 -Test: Encrypt -Comment: Set 1, vector 135 -Key: 00000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: D58740E259B1C9A5DADD2FA5FFB768ACECD0DA6FE40D7D59F3CF6FCD4838FEDA -Test: Encrypt -Comment: Set 1, vector 136 -Key: 00000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E6F318C17501C28164BE9CA692E92D4CF4835E2778B126E9841CA0F132CCAA61 -Test: Encrypt -Comment: Set 1, vector 137 -Key: 00000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3776A0BB5880EB65386F20D11BCF308C2DA3B010F7E2DAF3FB8B55B523E7CBC3 -Test: Encrypt -Comment: Set 1, vector 138 -Key: 00000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3926539CFD76BB79E50A571D75AA51B94864A79CA5DCAF6CE451FC068E487625 -Test: Encrypt -Comment: Set 1, vector 139 -Key: 00000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A8D9B6254BCD0BC32CA3ECF7A7A80882DDC178F47D8E91F760883D589D94F45C -Test: Encrypt -Comment: Set 1, vector 140 -Key: 00000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A2C3810606AD6AAAA571C8A783A686E9F713D0A1238C3E621347622C569C7BB6 -Test: Encrypt -Comment: Set 1, vector 141 -Key: 00000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 902FF7C8DA5B1D171603F48C02E72B611C40E4B15F06BF4A7DB914AAA7E63036 -Test: Encrypt -Comment: Set 1, vector 142 -Key: 00000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 55AAAB17A700544B1384EA512146F65A2F871C30F8EF7AB84DD96E004E924403 -Test: Encrypt -Comment: Set 1, vector 143 -Key: 00000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E9F049D8DD032202BC5E16F061B0449AEFD91845A4786A045E35739826E283AE -Test: Encrypt -Comment: Set 1, vector 144 -Key: 00000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 6347929B2B5B6634C2674CC4AD3B04B321F7404101E79259A35053E552369548 -Test: Encrypt -Comment: Set 1, vector 145 -Key: 00000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3C8D318014177555818122F69A95BED7A175464310A9B53DD4AF3C5887970D39 -Test: Encrypt -Comment: Set 1, vector 146 -Key: 00000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A3CE794DEA39A03EB4337395E3713ACA02E15148CC9302083E9F2FD55A921BF5 -Test: Encrypt -Comment: Set 1, vector 147 -Key: 00000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 2EE444D85842D41D9AEFBB7ECE34EEB71720AFB04498F9B4CFB87C10AC842D3A -Test: Encrypt -Comment: Set 1, vector 148 -Key: 00000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 0050EF8A2E0EAC79CD1BCC82F52F04410DA08263A320DA47B500DD72FBAA3487 -Test: Encrypt -Comment: Set 1, vector 149 -Key: 00000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 51721D61A2032DB004C8B83F7509B045A5190892FBC5AEB9BAA4B27D7969C791 -Test: Encrypt -Comment: Set 1, vector 150 -Key: 00000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 016D3D0A0C9B1EA97A12AB7BFA23BD4A973D5F10C06581A6DA92668BF3B4026E -Test: Encrypt -Comment: Set 1, vector 151 -Key: 00000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 687DAF7B782EB92EE2F8812ABA81A1F8EC353797544602A8EF2D2D6C1AC7EB48 -Test: Encrypt -Comment: Set 1, vector 152 -Key: 00000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 538008D0A4465A705313E0A03DE02BDFF7D9F0F0226F630DAFEA5434D9ADD7EE -Test: Encrypt -Comment: Set 1, vector 153 -Key: 00000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 2F65E608EF3E4C202C347ADDB9733132350A7AC9E544C5D7D76F9527DB3640AE -Test: Encrypt -Comment: Set 1, vector 154 -Key: 00000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 1EF33EF878790A6E16E18377C474700E6AF64C0C56F5FE8E7A1A83D990BB7B9B -Test: Encrypt -Comment: Set 1, vector 155 -Key: 00000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3369751D8735C5B82164E9FDFAA8B224AA4BD3FC2CD3DC48C60A1C290AE189BD -Test: Encrypt -Comment: Set 1, vector 156 -Key: 00000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 428F02228A58756A94871F5DCB37F54AD21345ABEDECB6D12630E51ADF4D6128 -Test: Encrypt -Comment: Set 1, vector 157 -Key: 00000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 521221AE0F51055948753BAC7A30394DA0F3DCB485364AB512E62D9CDC24FE48 -Test: Encrypt -Comment: Set 1, vector 158 -Key: 00000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7E44783F40C4A3EBB40E5D4E22A9BECAD3008D8B1AE64929B666664D8D8680D9 -Test: Encrypt -Comment: Set 1, vector 159 -Key: 00000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 48F54AE18072D2E58922EB0B14E4C32CD72807BF436A01164B0B5027ADCE6121 -Test: Encrypt -Comment: Set 1, vector 160 -Key: 00000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 671E9014ABC8FBBA21A307FAFF3FC7C89231ACA932F58C2D79DA323F80B3F87B -Test: Encrypt -Comment: Set 1, vector 161 -Key: 00000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 4473A8EF3585DDC8AB5858DB58FD87FA42E724D2374D7888FCFA66D82B30145A -Test: Encrypt -Comment: Set 1, vector 162 -Key: 00000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A4AD8D6A847FF420E96E1E592852FC7B362F1E0DBBE417B0CFC80C1200C5BB97 -Test: Encrypt -Comment: Set 1, vector 163 -Key: 00000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: B10D378FB56687BDDE7462A91FD0C42C773097765AC4C332B5007D1D47670EE0 -Test: Encrypt -Comment: Set 1, vector 164 -Key: 00000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 788D00A54C0A6FB10067E08B8F2C60B4DBA05B58D3C8CEEABE49C2FD2FD7D6C2 -Test: Encrypt -Comment: Set 1, vector 165 -Key: 00000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: CC54D8465F9529077237703DF4DC136FCD7A9D2FF3B89FF0D226EA3B234B6113 -Test: Encrypt -Comment: Set 1, vector 166 -Key: 00000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A0DAF3D3568FA9134C9C1B6EC5137B72715271DEC644F1268FDFA88A89989371 -Test: Encrypt -Comment: Set 1, vector 167 -Key: 00000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 0BBCCB3D83D7B6D3AA96AD5687C4895CD990146E293733A649B4D7EC48E9A93C -Test: Encrypt -Comment: Set 1, vector 168 -Key: 00000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: DDF8388BA3EA8FDC869D54D38D6BFE47FB7C5B6D81B3D80AE8B7DE00F4581EC1 -Test: Encrypt -Comment: Set 1, vector 169 -Key: 00000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: FF4F175CADFA435B31D5766FE6FE73B88B33BF5A87D79A2B47FCEB6BFE6E39AF -Test: Encrypt -Comment: Set 1, vector 170 -Key: 00000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 9B28804310814CF3C9782CB23FAB7FE19D5BDA5E9553F23E7876A6426316365C -Test: Encrypt -Comment: Set 1, vector 171 -Key: 00000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 94831F56AC794746628AF8A0684ABFE6A1113EB5B95939A8223D5C0C08BF52FD -Test: Encrypt -Comment: Set 1, vector 172 -Key: 00000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 689C2CAC1FC6999B8BA48B767A995871D80AB561FADF20D8613274CFFD00BF32 -Test: Encrypt -Comment: Set 1, vector 173 -Key: 00000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 4CC4412727B69CE43E6B85D89F03DAC6982CF867FB98801DA1F0E8720123699E -Test: Encrypt -Comment: Set 1, vector 174 -Key: 00000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 8160A24A68E81E4A839E1C16086983BE98652856CC621B3F7612A8B1324FA33E -Test: Encrypt -Comment: Set 1, vector 175 -Key: 00000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 024B19F8BE7203D9E5589AB96B86BD68A488D7994813D0231C835637B9E59A64 -Test: Encrypt -Comment: Set 1, vector 176 -Key: 00000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 954714BFD736CB391604E77367C2875EF291C02EED35B6DD6A20D58FBADAFB84 -Test: Encrypt -Comment: Set 1, vector 177 -Key: 00000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 6E95756FEA083B4AB4E624B5CFB00E31CAEA9C03CE4A1F51104BF6E7A86495F3 -Test: Encrypt -Comment: Set 1, vector 178 -Key: 00000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 93176B234B0A25F30649FD3172F75F181CD47C75D795FCFD5A537F18B101B24D -Test: Encrypt -Comment: Set 1, vector 179 -Key: 00000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 51637CD02F79DA935C5A317C1F8AC79E47E255E4A83F3F04DBA2998DF5118D39 -Test: Encrypt -Comment: Set 1, vector 180 -Key: 00000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 15C15F38B0CDEC62A426CF4AED25096DCCF1B2C7CF49A223F4D3ED7E06CAD2D7 -Test: Encrypt -Comment: Set 1, vector 181 -Key: 00000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 14520B3D7B8734A8D4E07CAB93744560D60FE7C9122C97F2ADB97D811074D225 -Test: Encrypt -Comment: Set 1, vector 182 -Key: 00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: F16ED0E9813C694563BF3557D73085C8761642B6B003291B31C681D3A9421E73 -Test: Encrypt -Comment: Set 1, vector 183 -Key: 00000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: BD3B03B8DF1994DDD3BE4509BB2B4AED0F7D0F7638102C58B15ED9DC9FAD5261 -Test: Encrypt -Comment: Set 1, vector 184 -Key: 00000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 45813D3ABF443D14B8519A10BA667F16C2EC757B309B978E26FFE56EE0BA00B1 -Test: Encrypt -Comment: Set 1, vector 185 -Key: 00000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A13D32CA09C34BBA16813BE8F4D56AF772B67327C7CDE0756B3D5CECEF2BCD2D -Test: Encrypt -Comment: Set 1, vector 186 -Key: 00000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: EC7D07D6F3AD0351131F15816F8044CBB1592324F62903B9DD6180D88E09EF07 -Test: Encrypt -Comment: Set 1, vector 187 -Key: 00000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 873F46936C8CC3A23CCA3EA3288CA070CC41F128296FCE6E7AAD2B7381BBAEBB -Test: Encrypt -Comment: Set 1, vector 188 -Key: 00000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 0AF0BB23EFCF86B273A27D84435F53F9984183E4C0D2F69945E79BAC8674C3A5 -Test: Encrypt -Comment: Set 1, vector 189 -Key: 00000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7B9A8CD1942564414FE5C1237B680970A306CCB0CF73F1123D2E823D084F3126 -Test: Encrypt -Comment: Set 1, vector 190 -Key: 00000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: C21A4ABA37069F7173A704B16C2DB945301BD4B08D3202BCBCA4AF8E5BA8A963 -Test: Encrypt -Comment: Set 1, vector 191 -Key: 00000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 5B2F725ECF531E569AC6B69408259547B9B054CAAA20B6727FE7654FAE4386D2 -Test: Encrypt -Comment: Set 1, vector 192 -Key: 00000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 58E6E58AD73C9DA9A19CBCBCB6E89B44951781A027D5C5CBEAABD95D55BE1CDF -Test: Encrypt -Comment: Set 1, vector 193 -Key: 00000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 8F076E12AB23D9CABFD006D16E1D554AB367CE88B3FDD44717824387DC9D4B43 -Test: Encrypt -Comment: Set 1, vector 194 -Key: 00000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: C5A351191F18886099542CE6B3025D6F0F4EF8A9A1C804803166BC2699D4B3C2 -Test: Encrypt -Comment: Set 1, vector 195 -Key: 00000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 39BF10576DBE0BA332EF36C38CD96F4F0043B8A0C6CCCCD3521F169821CC4C0E -Test: Encrypt -Comment: Set 1, vector 196 -Key: 00000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 12EC53C9420154F7D5334D4BF94BE3B4CCB044FDF56B4A92E245F016BBE9C057 -Test: Encrypt -Comment: Set 1, vector 197 -Key: 00000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 569D436AFFBB65451ECFDDDC7BABD5608BC183E9437F30B5058C505158BCE7EE -Test: Encrypt -Comment: Set 1, vector 198 -Key: 00000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 4E53AA49C4A8E0A00FA51E3DBE4D6BD6ABC1505C2E3FDADAC282BBDF5987E075 -Test: Encrypt -Comment: Set 1, vector 199 -Key: 00000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E0BF45509232C9F66517F057FB01C2E0E08906842B59DA4980413F629388C088 -Test: Encrypt -Comment: Set 1, vector 200 -Key: 00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: CC5A42F9BBCD1A5BE0D8EAC69A184E1693AE5F1C9FDAA05B8CB5330D5D63A2C0 -Test: Encrypt -Comment: Set 1, vector 201 -Key: 00000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 4247A5AA925AEAF29EA9FCC3C942DC47FB1A13213B302FE0C6F33243C631D2A0 -Test: Encrypt -Comment: Set 1, vector 202 -Key: 00000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: DAC043890BB61728CFC30E3A860BFF9474DE05CA104C242BAF498344470319B5 -Test: Encrypt -Comment: Set 1, vector 203 -Key: 00000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 214703F986092730BDF01020A825628FD06CD22C9F385CE14BBB2738A38A1E94 -Test: Encrypt -Comment: Set 1, vector 204 -Key: 00000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: AD3EED667396E27E4EF749BE1BC2D222380AA5C070B7246EB3A8249D9003BE1E -Test: Encrypt -Comment: Set 1, vector 205 -Key: 00000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 57B33C626E776BAAB8D655DD93125D49BFE92177BB63AA9902A44E4CC6F90666 -Test: Encrypt -Comment: Set 1, vector 206 -Key: 00000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3ABEB777D6240D198677B50B14545714D71D2F46885513688406B201F689C3BD -Test: Encrypt -Comment: Set 1, vector 207 -Key: 00000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 0B9E5A4358BCD0CA1AF306274CA676B515499878D2ACA0AD7865139D36910018 -Test: Encrypt -Comment: Set 1, vector 208 -Key: 00000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 9EAB0FE92E1B83FAE87EF6369BD0EED91D10DCFC5810FA0188D06929CF927422 -Test: Encrypt -Comment: Set 1, vector 209 -Key: 00000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: BC205D90F13A69AA6C45979861B1E5737A69C61F726D252F773E528276B9F1B7 -Test: Encrypt -Comment: Set 1, vector 210 -Key: 00000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: CEB885427DF7C988804E7C2401BD703CBB8F3D3D50AFD6CE9F56D32F802F8219 -Test: Encrypt -Comment: Set 1, vector 211 -Key: 00000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: C61CE53D0A5E771E6AC98830D496079A34ECE8967D737D0EBE393E7549679BA3 -Test: Encrypt -Comment: Set 1, vector 212 -Key: 00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 842F934F9C3E9690F3AABC753B6C27F7F3EF7B199ABFDA287686F35E2884A2F5 -Test: Encrypt -Comment: Set 1, vector 213 -Key: 00000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: EE357FEC92355A11FDCE30B089E4F5918A90025832DB3562C762A8421F3B6625 -Test: Encrypt -Comment: Set 1, vector 214 -Key: 00000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: C9CC50B7CB29557DCDC64C995B24D2E0E8AD8FBB4906A8DF06D67A69B1AAB8A6 -Test: Encrypt -Comment: Set 1, vector 215 -Key: 00000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: D6DE0F6B51BCBDA8D44D7EEA5F91C85B78F42B6612A35662CE3AB3043E87701D -Test: Encrypt -Comment: Set 1, vector 216 -Key: 00000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E3F3E3A5317DCBE044E1A97CAD714449DF0F8E9C319F5C12C19917B2F47F1FD7 -Test: Encrypt -Comment: Set 1, vector 217 -Key: 00000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3A1A26993055B3B30BA84236212646D2622680117D2813316223EDFFA1BBB22B -Test: Encrypt -Comment: Set 1, vector 218 -Key: 00000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 192EE13F6909D98437E8F424DE7DC873D82330DE64B379F3F8985658B00033DA -Test: Encrypt -Comment: Set 1, vector 219 -Key: 00000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: DEB92C0159D40548317AEAF996819352F43CB1E487885A0851234A43E4C5CB2F -Test: Encrypt -Comment: Set 1, vector 220 -Key: 00000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: C671DF68881157258EF58E7C7E712351FC9D743A2C4ECAAC9D3ABE98F9701B3C -Test: Encrypt -Comment: Set 1, vector 221 -Key: 00000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7A8BA935035DFE8F1DE34EA373FB60E147E6D5572686212BF95B6E0C115D15B8 -Test: Encrypt -Comment: Set 1, vector 222 -Key: 00000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: AA95483043360A3CCD5E98C8D5088F9F7154DA3E36F517C459F03B94EA8B5DCF -Test: Encrypt -Comment: Set 1, vector 223 -Key: 00000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: F716EF1B45585282C50AD6EB1EAD2D19AFBF57235E5D56A015882C55EECC2044 -Test: Encrypt -Comment: Set 1, vector 224 -Key: 00000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: CECA215484E90CE7AF49BED4B5F84543D05CE120973EE8510E0A410FA391BE3F -Test: Encrypt -Comment: Set 1, vector 225 -Key: 00000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 5AF45DB110A67D0CC49D1A1BB5765ACDDD6482BD88664A4A511BEB8DCDDC08B3 -Test: Encrypt -Comment: Set 1, vector 226 -Key: 00000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E0AFCA91B3CCF0A0C4E332C4F75BC17E5956B0F3A438F0B0ACA0E9B08DA9A1C0 -Test: Encrypt -Comment: Set 1, vector 227 -Key: 00000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: C559C00EB5C49F2321975A264F855C291DB8FF942FC4617193236318D55DA27A -Test: Encrypt -Comment: Set 1, vector 228 -Key: 00000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 88BCDD04989FE085F888A57176463662C57DC70DD3888F427B68BD5A36C3297A -Test: Encrypt -Comment: Set 1, vector 229 -Key: 00000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3C6302F9C2C8997C41FA0F0187B9E19D14FC2196A001D39F56BF5200E76D4F66 -Test: Encrypt -Comment: Set 1, vector 230 -Key: 00000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 641DA3FF9CC2C5AD625FD131D91E1AE5AD3088DF404384BD885917FD1AFDB9AB -Test: Encrypt -Comment: Set 1, vector 231 -Key: 00000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 1A05DEF28E631857C796D665FA66F8A4743F9A340904EC1C084AB022E63E3A0A -Test: Encrypt -Comment: Set 1, vector 232 -Key: 00000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 04DF8F3469AFEA2F63ECA1FA64FC18F1E42B42F7666BDCBFE6CC1C68614D85A7 -Test: Encrypt -Comment: Set 1, vector 233 -Key: 00000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 21AA974CF45CF84383024A8E7D3427BCD9A0A4F4B2AA83FA44911615B2D9A27E -Test: Encrypt -Comment: Set 1, vector 234 -Key: 00000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 74533E9973B565E0B7F9DB65A63B70BC5840EE4E1B6D927033CC1F733BD78AD1 -Test: Encrypt -Comment: Set 1, vector 235 -Key: 00000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E818E22E590974A00FBF40C1A1DD100F5C2E3A76C594D129DDE0C9119CC1A836 -Test: Encrypt -Comment: Set 1, vector 236 -Key: 00000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 00BEF3BB9263863455A8736A114E7DF13C903D6D9FE065FED48E6634EE9B9156 -Test: Encrypt -Comment: Set 1, vector 237 -Key: 00000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A0D418EAA61D8B6234D8B07D4652F61EDA48B00764E124DE5D7545973E4BFB0D -Test: Encrypt -Comment: Set 1, vector 238 -Key: 00000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 21472EDC58EB9D2EDE5D8A24DE18784500420820C388408E2D09C8935D3208CA -Test: Encrypt -Comment: Set 1, vector 239 -Key: 00000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 278849105940CFDF61AB8DF9A37427A24BD452C244988E7CE85B8FF94A913F71 -Test: Encrypt -Comment: Set 1, vector 240 -Key: 00000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7B35DC73EBA6408C2486D59ADA0A17B89ADC10E405E029E51B8FA7096704DF23 -Test: Encrypt -Comment: Set 1, vector 241 -Key: 00000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: D81FC2305382B4110925F4EEEE6C93C3356B30F4E083B47C0FFB429DC8A317A5 -Test: Encrypt -Comment: Set 1, vector 242 -Key: 00000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: B1CC26F822DAA8B4EF2DC5C08792C21A985D285697C9BC49E038331996F2DE35 -Test: Encrypt -Comment: Set 1, vector 243 -Key: 00000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 565635B8CF39652AD3F94F9658FBF2310A08DC25975102D9E0A658574E5437C6 -Test: Encrypt -Comment: Set 1, vector 244 -Key: 00000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3A9E77725182484E375528415C99C9BB2795A0841FD9F7E7D2DDE20A6CD71C04 -Test: Encrypt -Comment: Set 1, vector 245 -Key: 00000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: BD3F45893A96EF8C218B3C22079E64BF847F3C41D87F1AC68E62B32E5A59D350 -Test: Encrypt -Comment: Set 1, vector 246 -Key: 00000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 44BBB67723B8FC5778D18FFA60F1A7DF16F2A4583BA07E3B2A9A4286765AF743 -Test: Encrypt -Comment: Set 1, vector 247 -Key: 00000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 06198963CE32DC41A3869CB3893E1602D21EA64DD206C2DEA9FA79F756260BF8 -Test: Encrypt -Comment: Set 1, vector 248 -Key: 00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 82EA3EC56648E3152D541EA5EA76F9C1D12A373D5183CFFDBC49C0FCE25AC9BA -Test: Encrypt -Comment: Set 1, vector 249 -Key: 00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 2D6F44E5104C9A6B28DA5731FE95AD5ED73051B4D405FCB77D2845A3306CD9EA -Test: Encrypt -Comment: Set 1, vector 250 -Key: 00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 360DF8BA5BA3F245E4751C6B1D81CCCC7160D6DE8CB12B496DEF04A78B0D3DD6 -Test: Encrypt -Comment: Set 1, vector 251 -Key: 00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: BE0B2DE97E0528C5A135A81F2DA7431C8BF01A456411CB826F1205A9E57A44D2 -Test: Encrypt -Comment: Set 1, vector 252 -Key: 00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 4CC729EFC23033F244182FBAE629ABF4386CDB279C6394C7CC914724604D8736 -Test: Encrypt -Comment: Set 1, vector 253 -Key: 00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: BA44E9372A4EDC847FE6601F0DDBCF40864B2BB5C4EFF9B3038F7EAD6672907B -Test: Encrypt -Comment: Set 1, vector 254 -Key: 00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: DF3109ACA9E8546F5140E6705EDD69EB5512F0C5B3567D6EE132700820839B77 -Test: Encrypt -Comment: Set 1, vector 255 -Key: 00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: D909866F49103120A46CD4F2A98B2A2169E3E9AE7BB5AD36CEBD675F62B73018 -Test: Encrypt -Comment: Set 1, vector 256 -Key: 00000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 63081A9DE55FA28CFF0089A3D4A52568BFC0D3A172B1750180A91BA12EC3E38A -Test: Encrypt -Comment: Set 1, vector 257 -Key: 00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7FBD9ADE476739C69CF906B611639D554ECF25BA26AC87A11EF30856DE890D28 -Test: Encrypt -Comment: Set 1, vector 258 -Key: 00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 495FB031327D3AE9CCA3F449E73571539EF9FD88589B5C3142F5A4461CAFF9F1 -Test: Encrypt -Comment: Set 1, vector 259 -Key: 00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 1E958BF17F89DD463B49BDE9B05D01DC2557DC4CE072C24D0527E45BA1C8026C -Test: Encrypt -Comment: Set 1, vector 260 -Key: 00000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 92093F21E7CFDCD81765E71ED960121F84C6FE1CDA50B00592ED0DB9A8808FFA -Test: Encrypt -Comment: Set 1, vector 261 -Key: 00000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 122E0C5E19B0636ADE10F1A14FF4CA69EC426B4F311C109F6B137BEE274B1912 -Test: Encrypt -Comment: Set 1, vector 262 -Key: 00000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 2CE82AD1BF9BDA86355188CF5605CEAB73E98BC617CDC3D5C8598F11BA96F6A5 -Test: Encrypt -Comment: Set 1, vector 263 -Key: 00000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: B14A656DB71E54DF9D443E899417FF4F79E033106AA34D8669EEF0E9918FF4C7 -Test: Encrypt -Comment: Set 1, vector 264 -Key: 00000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 47ECD5C02C3D702FC36817981781B1A4593E240773121F763EB788D46E990C5C -Test: Encrypt -Comment: Set 1, vector 265 -Key: 00000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 91B74FC5E6FC8C6C30F33CE83BC0055190373FC589C0516F248227531C6B853F -Test: Encrypt -Comment: Set 1, vector 266 -Key: 00000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: AC8F0393E6D8881EFF753E7CE47EC441106AFE1315E712BB439F2F2DD4318670 -Test: Encrypt -Comment: Set 1, vector 267 -Key: 00000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 5765316B484E3091FB5135ECD4A5356293BD87512688EF14C719B61857767E1C -Test: Encrypt -Comment: Set 1, vector 268 -Key: 00000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: FAD76A9798E8DD194095DACF92F83779DEDA70C413033DADEE55B4C94B98B426 -Test: Encrypt -Comment: Set 1, vector 269 -Key: 00000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 87F337C9D5763F38C679C5EB9A67F72B4581487ABC5ADCD5BABF4C71B5EB6F7C -Test: Encrypt -Comment: Set 1, vector 270 -Key: 00000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 526B4C3E3FE096F47D32A403A7D20EE269A42F68939B2FA8254A1812D9EC6069 -Test: Encrypt -Comment: Set 1, vector 271 -Key: 00000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 342C0D2D0A5048DC98F2E8CDBB84CC610E30BEBC12F7572CB416CBFCFA24039D -Test: Encrypt -Comment: Set 1, vector 272 -Key: 00000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 47D03635744E2D917F799F77A7E09E6F064CE224A4A1D507090DBE200DBD022A -Test: Encrypt -Comment: Set 1, vector 273 -Key: 00000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 0DCE2CCCD9628DD4F6552A020B9447D35DEEFCFE5D8CDD8223AB3BA9090D8141 -Test: Encrypt -Comment: Set 1, vector 274 -Key: 00000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: AC5622C3DDECDB0A46F796596ED595926B2783E6A884D18517F7344CCAB3A2C0 -Test: Encrypt -Comment: Set 1, vector 275 -Key: 00000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 80E59C358DC6F0B5749FEAF45A9BE7F884842839EE6B47024083F52A8636C2A6 -Test: Encrypt -Comment: Set 1, vector 276 -Key: 00000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 8E57504AD8F6DA6D8633D413362E961A6D69B18FA1B501DB846080A5A9C9C700 -Test: Encrypt -Comment: Set 1, vector 277 -Key: 00000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 4956C679E9B58DDE2185BB018A7D6C61C918FA0AA9D6102E7DEF1183DB768FB1 -Test: Encrypt -Comment: Set 1, vector 278 -Key: 00000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 2C25F9CD0DB2444EE43D0AD2C3AF0303D1487528F45AFD346617D164F80635B9 -Test: Encrypt -Comment: Set 1, vector 279 -Key: 00000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 5292E96CB2110AD3FD231C5B2BCD1A8986333787664D1A551B9B750B2AA39A11 -Test: Encrypt -Comment: Set 1, vector 280 -Key: 00000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: D189129077C79106AEACA4E3463FD0650AC493ED981DC252531C072F18E1E292 -Test: Encrypt -Comment: Set 1, vector 281 -Key: 00000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: F9490DB8BAE36E28E73419D1D57869D760D772DC8752D1DE948262755B4ED503 -Test: Encrypt -Comment: Set 1, vector 282 -Key: 00000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 994EB2D9BE7C9FD547426F295F15DE3BC8F4A2B3955C7028ED890B1DE0FBE21C -Test: Encrypt -Comment: Set 1, vector 283 -Key: 00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 464BFD1EB42B595AEF9700C7C4C184A2132B5F1E85625592E48A233FA7840EC3 -Test: Encrypt -Comment: Set 1, vector 284 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A097C32D58D5A932AC9DBEE942DCCE547222E37E97DC3B29A63AAF118D5B01CF -Test: Encrypt -Comment: Set 1, vector 285 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: D3D13CC4379D2817B8CF8E06312FC727A3BA3C58F96E478E4EC5BC7BAEDDCDE4 -Test: Encrypt -Comment: Set 1, vector 286 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 577C709C26BD52547BD7C0D3F9CDEBEC0F266178905C4C067B75A01D799EF910 -Test: Encrypt -Comment: Set 1, vector 287 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 08FCEF6A263916C53AEBB6CCD2623E7BA3C38C871C5A8B64106308B74A7AE1B6 -Test: Encrypt -Comment: Set 1, vector 288 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A22F794F4913B2B1CD930FA26EC219081F297DE4EC808771C9B375782F891D67 -Test: Encrypt -Comment: Set 1, vector 289 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 52F2C9714DAD06FCF5FD8962131D33952A6D68C2A90B8C08C3AB86B09A2C77C5 -Test: Encrypt -Comment: Set 1, vector 290 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 60BDED5533E692A9F073AAED43A5D5A81378E73A953514ACD5B0997B61848E3E -Test: Encrypt -Comment: Set 1, vector 291 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 38921BE2443A8101FBB44BCB4C5B87AB5026AA34C78B7FCDE07E102E142B6162 -Test: Encrypt -Comment: Set 1, vector 292 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: D49C075CC20268EE889A10E27F2D4EAA99A1764F765621FE97687ECB6067E5AA -Test: Encrypt -Comment: Set 1, vector 293 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 50FC6782B3285D35117C0FA81039A7F264FC4EB492F3B86A233D45F2834F153A -Test: Encrypt -Comment: Set 1, vector 294 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 1CC0B39D670A88D424F5D40B2F9256AF3736689BD82F0EB315AC9056F7EC63A0 -Test: Encrypt -Comment: Set 1, vector 295 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: CF66C3CD4B08CB0E4D25186BF84BE3AAAB1C435F07D12593AD001F70894030FE -Test: Encrypt -Comment: Set 1, vector 296 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 352572656D0EB6E0CE604C1A913ED733D465A480504B61B0F9BBA77122FD20D3 -Test: Encrypt -Comment: Set 1, vector 297 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 096E9F34E6E277EDB994954C3705F6904452001D3A3E799A1D0230D430E207D7 -Test: Encrypt -Comment: Set 1, vector 298 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 277BC612F90A6D0735B86168C021098F134D1627D0FEF38607038415D1BADF84 -Test: Encrypt -Comment: Set 1, vector 299 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 2376E2CE884AEC093E22A3C119D573609225FD5DC9B3EB7602C340D1AB51BDF2 -Test: Encrypt -Comment: Set 1, vector 300 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3EE2E39ADB49F92D09D55ACC817B5B2F22FB202951AEFB6DE8998D2932145669 -Test: Encrypt -Comment: Set 1, vector 301 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E508313113570BBB5A1E63F46AB52B57ED0676A061936F093961D34409F1B962 -Test: Encrypt -Comment: Set 1, vector 302 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 198A9A0A5B04AE936CB19E02A5B2A254A2DD5A4D71F6C676C0A826CD261CE8C0 -Test: Encrypt -Comment: Set 1, vector 303 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: EFEB9C3D34865B89275EFB9DCE1929697FC9E68ED9E9E32E2CF267DE57388E77 -Test: Encrypt -Comment: Set 1, vector 304 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 61016E27DF83D9DE642AE01D7D56C4BFE881C8BDEDD15C503BDC28D3F7107754 -Test: Encrypt -Comment: Set 1, vector 305 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 2FB5FDEC05BD94EF5A7F0DEA7A368F7C2B26ABC5789FEAE7B7B6A5E6C364041C -Test: Encrypt -Comment: Set 1, vector 306 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: F765AE08A03CF705D4BE6A6AF8A34CDE7A14F599B2CB7E2FCF2770F0CFD4F7AC -Test: Encrypt -Comment: Set 1, vector 307 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: D38105C4DE4742F16E6AE7C1C3C85A515DA8BC758456E4B5D64C0539B76D473B -Test: Encrypt -Comment: Set 1, vector 308 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: BFE3A705729C82DDE1297DF492A8F8ABAFBF2F436830B3716FC206D6931BBFEF -Test: Encrypt -Comment: Set 1, vector 309 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: B81E7CB312AC5FF0A1795FCD4AD8B3D84FE6C8B796584DE794B7E230823E6AF0 -Test: Encrypt -Comment: Set 1, vector 310 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 605C8D477420CF7D8218CB8A6B3624700BADE8D1384B04995F3C942DE38ABA6D -Test: Encrypt -Comment: Set 1, vector 311 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 87A3F6DC69A7675F27CD00D7A84251366CCCA92775D680EBEBB48B92A5781D7E -Test: Encrypt -Comment: Set 1, vector 312 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 71625BD75BF6A89C643553D382B325EDACCFB4BF5F1617DED0C44BAB96A9F72D -Test: Encrypt -Comment: Set 1, vector 313 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: ADF64E64C1A8D854C421F5AA8CCBE789F3643B0D769A2CDC68D7C3AC85FDB634 -Test: Encrypt -Comment: Set 1, vector 314 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3C1AB3A3A85B1EEAA057557DBB59FC28479B38BEE67F4CDA0CD49880DC15ED0F -Test: Encrypt -Comment: Set 1, vector 315 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 026071B93A8B85F000539539626BBF664273EA701B63D487208962F8CC14F1DA -Test: Encrypt -Comment: Set 1, vector 316 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 61EC580BC31488BD8993C9B9D6B430BEBAE04F9807F199808CF05B0B4F083F9A -Test: Encrypt -Comment: Set 1, vector 317 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: DF9093A33937B0B3ACAEAC1840C8E1358CC90FB0B6C0834D4CE4F442830127B7 -Test: Encrypt -Comment: Set 1, vector 318 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 5683A2E768F9E105E9ABF7B71DE48833367D19E961D9D95577D2C4E48716EE9E -Test: Encrypt -Comment: Set 1, vector 319 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 1D33978B4B75C10ACB850BBD98BB2CCB31F7D6F561E34AABAEB929C2F7762219 -Test: Encrypt -Comment: Set 1, vector 320 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 6197C557619E4B791888DFD695B4BF55B7F72258968E26B9B74A6A3814267DD2 -Test: Encrypt -Comment: Set 1, vector 321 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 9AD5C65433732C4ABF08BAE9015692F509775FC0450677CB1E76A060974B8807 -Test: Encrypt -Comment: Set 1, vector 322 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 44AA2FB88757EA695083CE00105D5B77C2DCE04EE1315D99040A1495E97EEB42 -Test: Encrypt -Comment: Set 1, vector 323 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 9C637BA9B011A62B15BE522D6C514092358222CDB01A2A35B895B1E57DF1303B -Test: Encrypt -Comment: Set 1, vector 324 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 21774A71C07FC295C4BF477A512445B2AC9AFD6619DCF0124CBD735BC823F945 -Test: Encrypt -Comment: Set 1, vector 325 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3D74A1E781FEE340DD9D912F6A681F85C0EF78BAE81D3E50A5DB8A311057DCB3 -Test: Encrypt -Comment: Set 1, vector 326 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 5B851E24E32EEB5BFAB09D26E86BBE4DA23C43C8E88635413516825D1F56DC43 -Test: Encrypt -Comment: Set 1, vector 327 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E79FAFD3076C0F879222F86A0671104F350B115A6AC107F5C66BB673CB047948 -Test: Encrypt -Comment: Set 1, vector 328 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 5E8EBDFCEF4F70640695CF76FE7912F5E77F55095F0A3EC15CE692AED2C7312E -Test: Encrypt -Comment: Set 1, vector 329 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 99EC9D6724631EBC582C22B1B002C8F63B386EF1A96A9E4D162F698F3EC13944 -Test: Encrypt -Comment: Set 1, vector 330 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 9DCF4937F7E089B09AF8F441538E2577E315212AA56EB20209F040BE602509C3 -Test: Encrypt -Comment: Set 1, vector 331 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 063CE595D4EEC463726FDB74E5254B5AFB965D2729D02F1890E70E33C4C7AE49 -Test: Encrypt -Comment: Set 1, vector 332 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 18F5B3F2F2B54FF37C354F3181228FBAA7D337791671988801C19333165EAD35 -Test: Encrypt -Comment: Set 1, vector 333 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 912671C8099032B1C0AE139D8F029B153B22B999DC30170DAAE3904CBDEFF083 -Test: Encrypt -Comment: Set 1, vector 334 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: CAE46BA93F81E1AD26A8FACE45566E162B8F4CAE831B4B80F93D2A809D3C557D -Test: Encrypt -Comment: Set 1, vector 335 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 31708CCF07D82433A61053273FBC5543BAA1A73B836624FF092361E55631531D -Test: Encrypt -Comment: Set 1, vector 336 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: B5F46BFA7B367DCE7998428525483F775D8F5F1A8DB9F7E3EB848F887283028A -Test: Encrypt -Comment: Set 1, vector 337 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 1D1B9489F66B8FDC1902C02CE15E94727352C2F6A302C12A6F9672BC44014F6F -Test: Encrypt -Comment: Set 1, vector 338 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 8EDD86FA2225D954B3F9F57A0433ED692E99F7ED55EF0A8D112468AEA58717A2 -Test: Encrypt -Comment: Set 1, vector 339 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 6F1414CBA350BB5DF73F7B23FCC0859BC2F081374BD4FBA7571DEC9343BD939A -Test: Encrypt -Comment: Set 1, vector 340 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 84535A21BFDE843B9E70AEEC9E5EB915FCEFF57449B7872142AA0669EFF250BF -Test: Encrypt -Comment: Set 1, vector 341 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: C4CC653F5CFA6C13C4693967D4CD1398B8808982F0C1D6D9B4CC9A6FCAF41E8B -Test: Encrypt -Comment: Set 1, vector 342 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 0949688EEF8CFBB88589CAB3EF58912A2C413E413EF122BB7F4C0E17BF723E71 -Test: Encrypt -Comment: Set 1, vector 343 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: AFF2976C45A69940BB88C71381DAEDD767BAF454331FCC5666624EB052CE05CD -Test: Encrypt -Comment: Set 1, vector 344 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A7D73428AA840EFCBFF0C856409C9B19CBDC19BE376EBC75DFC008A6BC9EAB37 -Test: Encrypt -Comment: Set 1, vector 345 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3C59AA18035D96933FB938DE0331DBE42DA57B539A77D660DBFA12B62611760A -Test: Encrypt -Comment: Set 1, vector 346 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 1F982024A86CEBEF27F0D19765907131C5EA1385761E92C7432D55A118AF2FD0 -Test: Encrypt -Comment: Set 1, vector 347 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 5D5CE5B2BCEC679BEE0B894E4E0FD2E5ABD345D8F8061A02BD4B1873C3A9B612 -Test: Encrypt -Comment: Set 1, vector 348 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 54C62940FC9BD4D96A0D19CE92F6880B5F45A422DF0400E868020ED5B42BC287 -Test: Encrypt -Comment: Set 1, vector 349 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 6A7B7E894CB7FE3A0153B5CC6E78351A07AEC726CCAF93A2C426C83760974035 -Test: Encrypt -Comment: Set 1, vector 350 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: D2DAC7485B1818A7A2976F164C80AB5FE47B7CBDA4048000D09DAC65857A8387 -Test: Encrypt -Comment: Set 1, vector 351 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7C545CC73456F1C1B06C5B5A05A9659F5D30A4D78E9D85C29A38735BEF098E0E -Test: Encrypt -Comment: Set 1, vector 352 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7E3FA28ABB96C7CFAC0DFAFA5BF2E469D75ECF690FA876F3307D851D3CF0AAC4 -Test: Encrypt -Comment: Set 1, vector 353 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 46FFBA6995D7D6A2B58AB5F995AE3A305CB0385242428FD092FE777556AB05B5 -Test: Encrypt -Comment: Set 1, vector 354 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 052E5126AEDA420CC39EEF255B816BD475DBD36635B090D04C43410F40236BE2 -Test: Encrypt -Comment: Set 1, vector 355 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 80BBBFF3EB0CE3976503A85240226D7FE177B4F30C753F081D7E1F3F8F0FC176 -Test: Encrypt -Comment: Set 1, vector 356 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 4A748837D0A7950876ABC89127A6D6FE5B646C7FE9DF8005CBBC3832DFE488EF -Test: Encrypt -Comment: Set 1, vector 357 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 84F35DFA249674C24E6DFB3947E3F3475817DF9548B301D4741B79EF9D26629A -Test: Encrypt -Comment: Set 1, vector 358 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: BEC48DE878DD3533F3614B3A0A4BDF5FB34DBA96AE94508FC0D3927032CC6E61 -Test: Encrypt -Comment: Set 1, vector 359 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 80DDDED6AF53DB0459359FE311F32C5DFE85F281C45365BEA7A2D6BA8A2D5EA9 -Test: Encrypt -Comment: Set 1, vector 360 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 43BA1E833A673FB760B13DA40C509EBB7170CA05E7BD2728A7FDA0EB8E3020B8 -Test: Encrypt -Comment: Set 1, vector 361 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 917FDDD2206E751DBAD9BD2EAA3E1FDD7C6CFC7782367B563DE6E116D0E4A3B9 -Test: Encrypt -Comment: Set 1, vector 362 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3AD03FD2841A7C8E8BA49100FCA794DAAF29995A9CDCC6D4F868914C890C3BFC -Test: Encrypt -Comment: Set 1, vector 363 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 79A9305A48A10F739B06EBD24DAACBF5289ED6A83415021DB1CAAB542E417DDB -Test: Encrypt -Comment: Set 1, vector 364 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 195DA96825A0F6B94A71E2EDD934FB184F375EEF66411567815A4A6E966CAC0C -Test: Encrypt -Comment: Set 1, vector 365 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 513239A738978DE007138E83F5CD13A0A9BE374CF61B09021767CAE284D5510E -Test: Encrypt -Comment: Set 1, vector 366 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 6BC70608C85D884873CDE727CF2B8A4E9563DA58242C907A3E87C2608AC0F1F7 -Test: Encrypt -Comment: Set 1, vector 367 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: F47D47E5D0013BF10141C7BF92642E4CCCF8020347B59F1FAB145849EEF0A2E1 -Test: Encrypt -Comment: Set 1, vector 368 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 879D4097A300F6575BC2021F218E9AE9FED113AF9B4FC9179C621244A9E2A090 -Test: Encrypt -Comment: Set 1, vector 369 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 91EF2BE82D9080A366AC7C4344E457E5F46DA5BD54DD50C97D2910D1478BFA21 -Test: Encrypt -Comment: Set 1, vector 370 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 0EED2315EF9B9278CCAD8EE2E33493F5A4FDAE31EC1DA863C017E8AEB77C2867 -Test: Encrypt -Comment: Set 1, vector 371 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: FE80FF0F839BE1F911A21C97B36D439ED66F9965293890D98D8A3A98F2CFAE1D -Test: Encrypt -Comment: Set 1, vector 372 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 4E241C22B26385E268F868E37873C36B173625048DAAE4ADE3C2E09D856A8AE9 -Test: Encrypt -Comment: Set 1, vector 373 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 71DA83DEC321D3160433BD8E2C2345921A6505444C9B1949B4D6CE400F1FBDBB -Test: Encrypt -Comment: Set 1, vector 374 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 21FF7AA748E96269211F129671E4F7A25BC55D92A144B7BEEB75F445FDCCDDB3 -Test: Encrypt -Comment: Set 1, vector 375 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 070290F0A10324414DCFD323822ABD2256ADDA0913FEDC70EA53F3F88EEB7AB2 -Test: Encrypt -Comment: Set 1, vector 376 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A112192AEDC7824247A9239BE92E45928416D086FEA09D4370DDFE862493AF4E -Test: Encrypt -Comment: Set 1, vector 377 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: B0CD1E1BF87C1C63C455C8A285DF739A85706A587CDF0726C4615590DD25BDDE -Test: Encrypt -Comment: Set 1, vector 378 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: F5EBFED2EF7706C5DEF09E94641FDA500100F500E431C601C879CC65CE260DF6 -Test: Encrypt -Comment: Set 1, vector 379 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 02CA5B7EAA7F906B706DD5B13A6C121927EAE22FB51C7259A781A916C5906E7D -Test: Encrypt -Comment: Set 1, vector 380 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 10569B20052606FEEB9956C2882702477F1D48F82B09C0BE1C97C3150F5F7D1F -Test: Encrypt -Comment: Set 1, vector 381 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 95C649C5B1ADCE59BE93F701C01D815D7A32D151179FC1B6610B3A2A98EE1295 -Test: Encrypt -Comment: Set 1, vector 382 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7E1DD644C151A0C1055E0AEB7A9DBE80BE09CCDE6C69797D00E7B391A6311D1D -Test: Encrypt -Comment: Set 1, vector 383 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 6A82511AEBE5A82B6392CCA180B10F77FF0C14A7CF8CED894E1C8EDF9BAB29DA -Test: Encrypt -Comment: Set 1, vector 384 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: AD05B4B2F644469BCCD1BE1D028B1FB26F270088E56D8B73364F958730B0C9D7 -Test: Encrypt -Comment: Set 1, vector 385 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 8B4110E53906CBD07EC61AC8DC8C97C475085AE6AE6418C45CAD7495B2C2F4A9 -Test: Encrypt -Comment: Set 1, vector 386 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: FC44F97B9B3791B98D941B460C585BC7A485024F2B15370605FA64BEB36F10F6 -Test: Encrypt -Comment: Set 1, vector 387 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 95E1B79F255E9E477D756B0123F22397C723D63F3D6AC710A1647E5D6229AC25 -Test: Encrypt -Comment: Set 1, vector 388 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 523D59EEA567CAE613403BE8C8769E9E375F290D7FA2DFF64C9B41120E96F0C0 -Test: Encrypt -Comment: Set 1, vector 389 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: DCD843BF9123A86C9938CB833C815217E37325B4ECF9A43E8E878ED2CDB257E3 -Test: Encrypt -Comment: Set 1, vector 390 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 4D737BB7B6B2EA155FA64CAA9124588594AD9D3239B03A0B5F1A1670EF37C309 -Test: Encrypt -Comment: Set 1, vector 391 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: D884858B07B3ADC2AB0067E24CEF443AF6D3CB691C7D3EDDFAF672763DF6991F -Test: Encrypt -Comment: Set 1, vector 392 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 24923E668BA92F02D0545738A1F3A81AD3EACC6F3E65A3C6879FEB3D55C3BEF5 -Test: Encrypt -Comment: Set 1, vector 393 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 98006EC6FFEE6DC3FE9D53FC632D1D82E8DC5BCB0BE0BBF1782701F858934432 -Test: Encrypt -Comment: Set 1, vector 394 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 1C7CD45E2FDF746F2F6B7FCE3510DD14CAC7420FDA6BC9C6D3287E894D2B9EF5 -Test: Encrypt -Comment: Set 1, vector 395 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: DF1B2CD5A9A7ADC85A257882E53150F9B3BAD4B5EFEEE8B4B212F8FB08F11194 -Test: Encrypt -Comment: Set 1, vector 396 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 5DF3202330B96E2C8D45284BC1D8CC34C076B18600495EC43F847D09B9AB08C2 -Test: Encrypt -Comment: Set 1, vector 397 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: CEE878EA6317D3B4E2CC695FCCC5EE04B7415B735F2D11B9A8891293D5D5E818 -Test: Encrypt -Comment: Set 1, vector 398 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3753BC3550155B6880CF1AAE6365FA5EA4F277B4E01FD26133A5C69F5620AC9F -Test: Encrypt -Comment: Set 1, vector 399 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 8FF623E4246D8B7D14904BFB478256CA55EBD9E383B672A91D512AFD606BA629 -Test: Encrypt -Comment: Set 1, vector 400 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: C823B856B5E462FAD71A1D9C8F02CE1FE48650BD53BD620D021ADB1C53C21B84 -Test: Encrypt -Comment: Set 1, vector 401 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 22D0CD94534D8DCC359095D77008069E57851298103A13ACB50BF6FA778CB9A3 -Test: Encrypt -Comment: Set 1, vector 402 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 413F7657C9E46D928AE307FE794D1B10FEEB433D7F829C66118E155227F811BD -Test: Encrypt -Comment: Set 1, vector 403 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 12A9E9ABCC1916594307C982852A6750FFD5D9DCFDA261EC54C2D465BBB0FB64 -Test: Encrypt -Comment: Set 1, vector 404 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: EEB4897AEABADA871D368A00748CB437801933D78A14687EDDB3D526BBC2BFF7 -Test: Encrypt -Comment: Set 1, vector 405 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 2444A95492348F7AB5C8EFE89839C6491833EF227637640F8199262DA70E5406 -Test: Encrypt -Comment: Set 1, vector 406 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: CD0F1C806CE40D9901A04A23B52BBCFF51D20E964BA2ADCFE9AEE7CC8FE4A3B5 -Test: Encrypt -Comment: Set 1, vector 407 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 30E58CD115B75139A5D2ECC5253F6467FDEF4DFA307D11132570F90E657BC254 -Test: Encrypt -Comment: Set 1, vector 408 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 563FF22D971BDFACD7A90EDE80F076126CB16A759FDE6DB83E0DEE71CA48F33F -Test: Encrypt -Comment: Set 1, vector 409 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: D235A2277B7D3A772C3D092D2E3D92248865EFED8C2577D3D087C5BE84891667 -Test: Encrypt -Comment: Set 1, vector 410 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3CD74A025D1C2044875FE1D97351608E0203CE65F2EB283633505AFDC3C6393B -Test: Encrypt -Comment: Set 1, vector 411 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: FDAAE4CA8FD698D4330AD8217D40C8368AE9A825BE3359CB881FA74315ADA4DD -Test: Encrypt -Comment: Set 1, vector 412 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A9BBBED3051D1EB40AA806CF6505EBB4A0D3BAE671AFA03BD2586B01ECC6B9AD -Test: Encrypt -Comment: Set 1, vector 413 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 468AC86525069F4A9F1F7036BB2FC3D042296707B9FE8328C9514DA52FCBBCC2 -Test: Encrypt -Comment: Set 1, vector 414 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 96498A45E45E26AA2A1DD58E7374BCDA71420627B332F94FE98E045251B432C0 -Test: Encrypt -Comment: Set 1, vector 415 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 36FB6B4DAE5EDE9971BC2F5A353A3D5954961D9C8F7D38063A9F8556881F1E1B -Test: Encrypt -Comment: Set 1, vector 416 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 4206BEA972707980637FCD2B990F2B8EAE3243C9178487047B1A9BE2C7F6225C -Test: Encrypt -Comment: Set 1, vector 417 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: BF2763F46F4EF8CF40E42B6E4F161785D3478BDD1EA0BFAB30763B98BBC64720 -Test: Encrypt -Comment: Set 1, vector 418 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E7B97A297B534B1842528055982B7C382CFFDD161D69725789BF0CC35339D0A8 -Test: Encrypt -Comment: Set 1, vector 419 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: F8E68E206729EDF06C9379DC6F87891FFB6D5DD75A040D4F0E17BDF28308E6E0 -Test: Encrypt -Comment: Set 1, vector 420 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: DA69958998715C7517B9864E3A81F5960A48E9071FEB047084683D95A8532751 -Test: Encrypt -Comment: Set 1, vector 421 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 99456A498166535817F3DD3B47696CC74777ADE25DFA5CB5A3DF1A47DBCF0F17 -Test: Encrypt -Comment: Set 1, vector 422 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: D2D061B7FEDCA0663FE8F738042D1CE7D0EFB3BCED73977087FAB06192A361C1 -Test: Encrypt -Comment: Set 1, vector 423 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: ABF4E053FD99A777A5C95F057A1D8D3BC433D212220FE2BD5074C7E7B4AAA636 -Test: Encrypt -Comment: Set 1, vector 424 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 335F971AF070B59191F61547DC555F2AD86B263B23AAD53A80D6DA0C8A73C6BB -Test: Encrypt -Comment: Set 1, vector 425 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: C2EE398458AD869FCFB5DBAD16CB66F2CDEBE8D9D2C0FC4B258553D7D648E281 -Test: Encrypt -Comment: Set 1, vector 426 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 659BDB67C3BB43D43CF53EF14411F9B5B2B3C8C9B961087622BF1F0412596D81 -Test: Encrypt -Comment: Set 1, vector 427 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 21E2DA7422F753B1B625D95BFE5FD1C52CB5DFEDF0F2662EF17416E44F671525 -Test: Encrypt -Comment: Set 1, vector 428 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: C14725058665DCF8D701BB4A3DD5490DDA85E2754D9B233C008B5FC3559837B0 -Test: Encrypt -Comment: Set 1, vector 429 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: BF0D7F94DF1C7CA59CAF588BEDB316CB4E31A578B76C1E5213EB663C0E850F97 -Test: Encrypt -Comment: Set 1, vector 430 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: C81ABCB56C58DB2D5A329C6777091857DA4A5CBCB9D05AD6B0D4A2D4E915A7F4 -Test: Encrypt -Comment: Set 1, vector 431 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: F9D7611F502D0CED242909E032173BAF5A43DAF7009F53E25E109D7F4FEF9981 -Test: Encrypt -Comment: Set 1, vector 432 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 4EC0E7F808A10BFD4676E5CCA67E1D48806F346B702B2827810487EE56907C71 -Test: Encrypt -Comment: Set 1, vector 433 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 34C183C96FE5D9D2B4ED564EE9726551B27E1AF24848B5D711503E88BECBE458 -Test: Encrypt -Comment: Set 1, vector 434 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3E5EA6B326751B501C91C4A575B0ED6AEA9D60A14908187ACB3FC145B5468131 -Test: Encrypt -Comment: Set 1, vector 435 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: DA3904568BC8844CB594F44FE13F5D663B55EE6995D2232A999D591F2FCE7812 -Test: Encrypt -Comment: Set 1, vector 436 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 9293ED1C3C5B1A91B54A43BC63603F2EAD345EF9A7D3E69BD955EF1B8D36FD13 -Test: Encrypt -Comment: Set 1, vector 437 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 65C5CE0CC96FA6085A23EF00299B6D8518673DC9B8BF764DB595A8A7F8E940C7 -Test: Encrypt -Comment: Set 1, vector 438 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: EF95E25669CF4079F8BA728F41BD115F2913D8CFE0116C86032CD133E4787011 -Test: Encrypt -Comment: Set 1, vector 439 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7860315B44671B93718FEAB94BBCEE6B1006354914A90C3BF2DA1B6FA62F48AB -Test: Encrypt -Comment: Set 1, vector 440 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 2AA9968D7011FB1F33B97DAD01C2708A6826C030AFCCA35B222B2E47C89F14E1 -Test: Encrypt -Comment: Set 1, vector 441 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: CA9DD4F0771447B9AD0664DDA2921192568C2012246CCF5E95CD6CF3FBC44DCA -Test: Encrypt -Comment: Set 1, vector 442 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 38D51B18372FD7E7A617D7BCBCC658CB16014B05ECA242AF52B40AEDF6952DE4 -Test: Encrypt -Comment: Set 1, vector 443 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 640D035CFD65FE70D089866A53F21D00F86FDB1CEE2880F9FA7D382D424978A1 -Test: Encrypt -Comment: Set 1, vector 444 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: B41B62EC90FA9CC037F1BC74AEED25226917DD3B2B2E5C11EC6AE7601CF3F0E2 -Test: Encrypt -Comment: Set 1, vector 445 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A4340A36C7E640C83D2401AAE6F9F103BC9B568EF5B7F67663E64B820974B235 -Test: Encrypt -Comment: Set 1, vector 446 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: CAEF6FE59B0C05DDFE4F233412A185038077B7138EE9BA5FF4815C63C2BE84D2 -Test: Encrypt -Comment: Set 1, vector 447 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: F5D76FAAF12F566711DAAAC0E1F71260354FBA7BC0DBC34D7A2B6FE8E19DC672 -Test: Encrypt -Comment: Set 1, vector 448 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: DB1B22D80BD5BEA8D3F5F445E296FF3506C98C6FAE617D6C8DD943BC535AF864 -Test: Encrypt -Comment: Set 1, vector 449 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: DA02BA2C706095D3EB008EFFEB5E501FFF78B59EC34CBCAF0D7CE82268CCAFBA -Test: Encrypt -Comment: Set 1, vector 450 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: F878759262E5C2BA6CBC2091406D4045F876767C475582965B185DC9437ADD1E -Test: Encrypt -Comment: Set 1, vector 451 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: CA268715277F1CABC2062D4EDFD667759829782F793715199EE172917DA35C5D -Test: Encrypt -Comment: Set 1, vector 452 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 01BACD8388BF42064C8E927B3629C0DA82A0FEC4883EC068DC48483C43512BC5 -Test: Encrypt -Comment: Set 1, vector 453 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3D782388FD4ECBFEBBD49F2FBCF80A687E4CC0B8FEF51F097DEB679F49CB8B06 -Test: Encrypt -Comment: Set 1, vector 454 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 392E11AF1FD4A97ED260B680930C95DF26679260EAE0C025C405CDCDBC8E810D -Test: Encrypt -Comment: Set 1, vector 455 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 10E6AA6CAA90220E6D8963837D9EC3D46F8E9679379345282573753F2093E0F2 -Test: Encrypt -Comment: Set 1, vector 456 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E3EF5E9644294206A5707EF83C54E5EF5F4DB9841383C3EB767DEA722E9B7D0E -Test: Encrypt -Comment: Set 1, vector 457 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 0EDD01B5FE46475139F14371B548B58C5E33830D6EA6864BFBAB36D25345F8F3 -Test: Encrypt -Comment: Set 1, vector 458 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7DB72BFBC00A04E38DD4B9F2EA5C0114D19B2956EB959BEAD3E29DFB9BFC9A2A -Test: Encrypt -Comment: Set 1, vector 459 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7DB561AF481CC8B010BFD18A0216E2554888BBDD4E90B00476809B48601C9306 -Test: Encrypt -Comment: Set 1, vector 460 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 4EAB74E6D12574BCDEF95BC0CAD67C7E04B24472431607EBAD5F915F1116C9CB -Test: Encrypt -Comment: Set 1, vector 461 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 5A48DE560FA1ABF0F85BFF9A0A1928020A6C51AD3FE7C1392C2A875401DE62F0 -Test: Encrypt -Comment: Set 1, vector 462 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 074956F37AF065DBEDB2D68C602A4B65B7D614F8A0B284539E234B307CFDC495 -Test: Encrypt -Comment: Set 1, vector 463 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 9BB4837A582A5CB30579DABEEC41ACCB3786AA9BE52DDC88065BE0FFD33917EC -Test: Encrypt -Comment: Set 1, vector 464 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E1E690D74FC254D1D2A8238096285CC100013E8A8BB55FE92F6DF69DB217773E -Test: Encrypt -Comment: Set 1, vector 465 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: DFE35C2BC6ADFEBE4D9E8F84160AD6315CA43F0F022DDC629106E008F29C81AE -Test: Encrypt -Comment: Set 1, vector 466 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 8106B2FE206F9F8738BEC324B531E6943F00B20EC35DEADCB508197EEEBA5473 -Test: Encrypt -Comment: Set 1, vector 467 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E46E36293B659E73FAA1722AF29651621598FF2E92694C99F7BB0C792B93BAB2 -Test: Encrypt -Comment: Set 1, vector 468 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: F3CAB9F84AF81A06F9F350C345B44E053C8F1EE36D62159B4993950BB76D0948 -Test: Encrypt -Comment: Set 1, vector 469 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E3381C1644BBBB29290D30F15C96956BF4AEFE443FBDA0DB3EF2CEE7081D1DB3 -Test: Encrypt -Comment: Set 1, vector 470 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A4DD97D2710285907527C4FAE5676774D937FEC609F8489A16384568FAAA699F -Test: Encrypt -Comment: Set 1, vector 471 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 43C608E43584C631E620672EB0A92707C396ACC12CBCE0810A28F7EA3491E0A3 -Test: Encrypt -Comment: Set 1, vector 472 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A1DC3C2AE54BB2FA291913562F05E021AF361E422D39C89D8CFDBE4B672B63ED -Test: Encrypt -Comment: Set 1, vector 473 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 890CB43DA15A1D69A10EA9322B8C14D61AD537462439A735472CEF9428C8A2D9 -Test: Encrypt -Comment: Set 1, vector 474 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 9119548582EB7EA7F4AA1B224A6825B786F316EAA7AAA18B61B56D64AA4CBA29 -Test: Encrypt -Comment: Set 1, vector 475 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 574DD7CA20662ECBC730FA7CE314094E427FB8250E0F636894B650DA35A7F0CE -Test: Encrypt -Comment: Set 1, vector 476 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 3575DEA861D0F97DA32438DB834020996820BE85EAE5ED15A7983A31C7669C70 -Test: Encrypt -Comment: Set 1, vector 477 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 27EA06CBD196073357F1F790191D14796FE2BEFBE18B8C48D7566528B3DDA4C6 -Test: Encrypt -Comment: Set 1, vector 478 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 11B190730F6EDE90C8B3FEE01E722ADDD21BEB4324A358F86F524E4B7F7AF975 -Test: Encrypt -Comment: Set 1, vector 479 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 07E3CDB5130D8FF7A2A31335AD478FEF10805E266C00646CFBBEE81F2B3C1711 -Test: Encrypt -Comment: Set 1, vector 480 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A0ED0FFEEBCBF4066EE550E63065B08569B92BCC938002A5469ABD1C397233A0 -Test: Encrypt -Comment: Set 1, vector 481 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 2C9CDE299A4C507EC03C617EACE2358E76BC1AD338FE5A66A9105F18788A8836 -Test: Encrypt -Comment: Set 1, vector 482 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 5163F9C4ECECD047E83BDF1D6EE233487646A96FE43B4B08C41324FD8ECB271B -Test: Encrypt -Comment: Set 1, vector 483 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: AA2AE4BF506AB3D7607A29C3EF90B4C7933EE58ED3AB3720817FE3C611A850AC -Test: Encrypt -Comment: Set 1, vector 484 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: B04B4C802D91D9ADE76EBAFCDBA0A96A8A83DAEB7069370D6E901A42291EB8C6 -Test: Encrypt -Comment: Set 1, vector 485 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 91A99BC40CF38388B4AA77798D720653492CCED5230382ED587A305A2A1A6BCF -Test: Encrypt -Comment: Set 1, vector 486 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 91FB386F3B9AF82F93836005CBD9ED6727B9BBF1F669EAE6D06DA6D04D1AC082 -Test: Encrypt -Comment: Set 1, vector 487 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 01F8956120BF068AE7241BB96FF086C2D67547B549A8743FC0569978F201678E -Test: Encrypt -Comment: Set 1, vector 488 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A8C562A616F918A669A29C0724B76E3D04B125E0AB5A09E8CE60F54E4816EC90 -Test: Encrypt -Comment: Set 1, vector 489 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: B41D3BC188419DC929D611197D17FB4D29B78CD7FBC03B904219DD8A2FEE210C -Test: Encrypt -Comment: Set 1, vector 490 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: B119861B67AFE45C0134E2336CAC90BAFD1EB94C557EBA6DFDCBE69367B37981 -Test: Encrypt -Comment: Set 1, vector 491 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A2317FD4C041AF4D87C46FC684FBEE8DB65E4D43E5EA74237988A7EB67404656 -Test: Encrypt -Comment: Set 1, vector 492 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 641794C292A1A590F909D01F175E012671AEBF1E432295AED662E74C1EEA5DD4 -Test: Encrypt -Comment: Set 1, vector 493 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7984AC47362281DF446BE46AEC5D9A94B842F6F5BCCB01FD564318A49F94042C -Test: Encrypt -Comment: Set 1, vector 494 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 74F84174C9E2EBBEE396727DBB1C9CFAE2809D802F7E7CF8F7515FA3A629ED98 -Test: Encrypt -Comment: Set 1, vector 495 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7A9E862E27444A492C91CA2EE5E93369FEB74BB881AAC74F895D97E61500FA99 -Test: Encrypt -Comment: Set 1, vector 496 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 638E347CEC7121A668AF985E56F7F3934D852FCF53283B767BAC213337AAE99A -Test: Encrypt -Comment: Set 1, vector 497 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 45DC398895DA1B415708B4BC8B7EF133849E0E8E99945AE4D9C894FDF6D2815D -Test: Encrypt -Comment: Set 1, vector 498 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 1ACF1203B698FE2E3375E251EBBC05D387FECABDE6A9194DF5195F3FBF1E3502 -Test: Encrypt -Comment: Set 1, vector 499 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: F6A064BDC6EE0777B09CC1A0154F28AD282D4D6E48F9DE11CA083B8A9F454891 -Test: Encrypt -Comment: Set 1, vector 500 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: FE68FB721E181EA8A62CDD3CA0278C6EB1344DF07E73676D3F0DC501D99721C3 -Test: Encrypt -Comment: Set 1, vector 501 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 72923AD92EF01BDB90B9639DD411E4540CE0F531A0AE401547FBA03CB850B63A -Test: Encrypt -Comment: Set 1, vector 502 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 0B1D0F485A4DE59658FE61F1F0010D9EF5A2BA97624CC3687D94EE4335777138 -Test: Encrypt -Comment: Set 1, vector 503 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7423264FBF5EA94BA461BD80B2518B1CAF3757CF5BAB4511144637F5DC917168 -Test: Encrypt -Comment: Set 1, vector 504 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 589FADA29BEA438C12CA96241AA492FCFED48C1C1C05C16C88CD7A8B46E16A0D -Test: Encrypt -Comment: Set 1, vector 505 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 319B5D23945A98C9480E6460CBCB86A8B36038A28500A36182B228060713F58B -Test: Encrypt -Comment: Set 1, vector 506 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: B81B723D3E18A074078B7D041E55B9B130953ECF70BF773273A28E11238651A5 -Test: Encrypt -Comment: Set 1, vector 507 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E660AC40BC4700D4CE85AA43A2A39A24D0F255E64A9251D7442AEFB6EDFD43A8 -Test: Encrypt -Comment: Set 1, vector 508 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: C27914CB70EA29C06B321E4F61730CE6679A342733738BE72C97EED40802EC17 -Test: Encrypt -Comment: Set 1, vector 509 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 764B78FA0EC12E017D9F7C69FF53FA8FA00E7185888F36DBC3CA9A10A6122FBA -Test: Encrypt -Comment: Set 1, vector 510 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E2F9F554823B38D2099DD27E0AD6AD69BE137626840B41B7CF081D7881C47CC7 -Test: Encrypt -Comment: Set 1, vector 511 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 403E453BBAF997A75C4517B588431C75BCF01208B378A4F4FBB138217A9CA4A2 -Test: Encrypt -Comment: Set 2, vector 0 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 8000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 2CAE7C0460EE2FC3200923A1B6C2ABEEA746C8B44F6C3FB941BD3AF02A3E6E3E -Test: Encrypt -Comment: Set 2, vector 1 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 4000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 45FAAFBEE792EA704EE3D08CFA9D9F5CF93FEB3443E0049DE5898A48F5A3D92B -Test: Encrypt -Comment: Set 2, vector 2 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 2000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 720F072E7796310AC1BDDD3714581EB95896723DA3E61E0892B43F65A4153965 -Test: Encrypt -Comment: Set 2, vector 3 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 1000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 5E6671D1F792673D63940E69D78A3471B3C150707DA72E6C25CBD2C4DA2B9778 -Test: Encrypt -Comment: Set 2, vector 4 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0800000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 2E96F027C2B62ED2D2EE692A992ACAB827D16FDA71DD98109A645E4094923D3B -Test: Encrypt -Comment: Set 2, vector 5 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0400000000000000000000000000000000000000000000000000000000000000 -Ciphertext: A38D7F334B21394B28A29FC9CBC68AD9F2AE85E7434D1C2F57AAA4C1A49DB759 -Test: Encrypt -Comment: Set 2, vector 6 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0200000000000000000000000000000000000000000000000000000000000000 -Ciphertext: F67B5037CE9193023095D43DE312523F99E6CBCDF43EC00A947284496E311DD6 -Test: Encrypt -Comment: Set 2, vector 7 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0100000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7DC030A91C39EC8558AC10044AF79D4CCA92BBC8093B3A2456E26350E35EEBDA -Test: Encrypt -Comment: Set 2, vector 8 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0080000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 99260425AA126953E04A3D959F9153404521EC64C3B35E61EEBA67AAD2C1295A -Test: Encrypt -Comment: Set 2, vector 9 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0040000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 65C380354899581B2B40EDDF40A0695FB608DCDD11C6B0C2CA6BB427DB1D2A9D -Test: Encrypt -Comment: Set 2, vector 10 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0020000000000000000000000000000000000000000000000000000000000000 -Ciphertext: BBD1C4488D41FB1B096E835AD29FC3DC5B97496BA638625D78B99C5ABBDFA13A -Test: Encrypt -Comment: Set 2, vector 11 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0010000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7AFDEE496D690233ED0717E2D92DE3A102FDF902E51E69FFCE244B84A69CA826 -Test: Encrypt -Comment: Set 2, vector 12 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0008000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 06D8C3E7AAC698D143013B364BD7ABC4E4EB6BA82BBAB2A4A0B486E70E24592C -Test: Encrypt -Comment: Set 2, vector 13 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0004000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 727A8BF64932039C3409ED31CFC0171651BA69D551E8073A4BD1D35F31F52336 -Test: Encrypt -Comment: Set 2, vector 14 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0002000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 9EE7CA05C4161860014BEA89FB2DED90B4F0B362AD67789C6045C9C71310A8AA -Test: Encrypt -Comment: Set 2, vector 15 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0001000000000000000000000000000000000000000000000000000000000000 -Ciphertext: E924224559E43960EC44165CAD471CFED381B279B3EA4AF96BDB071BE987DA0D -Test: Encrypt -Comment: Set 2, vector 16 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000800000000000000000000000000000000000000000000000000000000000 -Ciphertext: FF189222046B5F4FB491CDC9A98130D772629F3EF44A06894268C507C25061AF -Test: Encrypt -Comment: Set 2, vector 17 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000400000000000000000000000000000000000000000000000000000000000 -Ciphertext: 6B053BA7765F2A62595A1E83444B52FCF16C8BBBEB21B437E6FC8C5F03B3673F -Test: Encrypt -Comment: Set 2, vector 18 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000200000000000000000000000000000000000000000000000000000000000 -Ciphertext: 0FB836DC6BCDA1C2955CC7A6F25E72C5FFFDE1075D820217157051FB5BD3D3EF -Test: Encrypt -Comment: Set 2, vector 19 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000100000000000000000000000000000000000000000000000000000000000 -Ciphertext: 200EBC8B8217D9A6895253F9366543027E5F493DBA1A5AD4FC7AB66FB806308E -Test: Encrypt -Comment: Set 2, vector 20 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000080000000000000000000000000000000000000000000000000000000000 -Ciphertext: 45B33F2465C674941B7E26C5986E42F6814A71323B420E401DCC8DA200FC3C08 -Test: Encrypt -Comment: Set 2, vector 21 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000040000000000000000000000000000000000000000000000000000000000 -Ciphertext: D2BF0A074053A01A227DC439311BF8BD696203995285A3A2CD3674A0CC6A65B2 -Test: Encrypt -Comment: Set 2, vector 22 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000020000000000000000000000000000000000000000000000000000000000 -Ciphertext: 5FFFAB58BA2CB27AE92E10F36F99A8EFEDF9DE2446A9C2E82E48F22FB1ED8C5D -Test: Encrypt -Comment: Set 2, vector 23 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000010000000000000000000000000000000000000000000000000000000000 -Ciphertext: 835A1BD7A3688BA0F7C572417A06FCCBCE0A69C7FCDF10C8BCF4469AE80DF11E -Test: Encrypt -Comment: Set 2, vector 24 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000008000000000000000000000000000000000000000000000000000000000 -Ciphertext: 559D1BECB3DBBE40A7E31C66D97D292821B934818172553FC1CE68AD8E6A741F -Test: Encrypt -Comment: Set 2, vector 25 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000004000000000000000000000000000000000000000000000000000000000 -Ciphertext: D962BE9A9C4F8DDA6F0EC42DB8B48FA14A1E91E639BD85FF26A2543D9FDFA9A9 -Test: Encrypt -Comment: Set 2, vector 26 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000002000000000000000000000000000000000000000000000000000000000 -Ciphertext: 588B2319C62ED25ECEAB7C327B212F5FCD5D89DE8A85AA3713BF332CF5F715DF -Test: Encrypt -Comment: Set 2, vector 27 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000001000000000000000000000000000000000000000000000000000000000 -Ciphertext: 67EDE571C64AFF87D7AE5294E64F1709F920A10D278E1629FC8B2BE7EF5ABE0D -Test: Encrypt -Comment: Set 2, vector 28 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000800000000000000000000000000000000000000000000000000000000 -Ciphertext: 60D9E58A6828847F9644DC165EB508B5A2BC67219B969B605B3CFAE109C9CE47 -Test: Encrypt -Comment: Set 2, vector 29 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000400000000000000000000000000000000000000000000000000000000 -Ciphertext: 5A0C538CB78F13404BF8D8AF5C43A17F04AD0D35DAD45F88E26B9D1C204B5AFB -Test: Encrypt -Comment: Set 2, vector 30 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000200000000000000000000000000000000000000000000000000000000 -Ciphertext: 724EE8B7D7BCAC2587C42D92FFCDF7EDFF91F06AD43ED353F332E1FAC3B70F5F -Test: Encrypt -Comment: Set 2, vector 31 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000100000000000000000000000000000000000000000000000000000000 -Ciphertext: D50F11DACBF340C1315419D1983028DCED83F8350FE50DA4F9554DFA641E99E1 -Test: Encrypt -Comment: Set 2, vector 32 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000080000000000000000000000000000000000000000000000000000000 -Ciphertext: 9460ACD1B739015ED197B2659353AAC465339FAD9D1AFB845A337630332C1C55 -Test: Encrypt -Comment: Set 2, vector 33 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000040000000000000000000000000000000000000000000000000000000 -Ciphertext: 7D7A56F8A89463C4CE519B96854200C6E05703651CE3ACD5549B59D0B9788B93 -Test: Encrypt -Comment: Set 2, vector 34 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000020000000000000000000000000000000000000000000000000000000 -Ciphertext: D07E4F830ADF1DE4886C614CDB6B3D988884293AE65A63B3E9886A8727C022B2 -Test: Encrypt -Comment: Set 2, vector 35 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000010000000000000000000000000000000000000000000000000000000 -Ciphertext: 56CCEC1812B3B83086208DBF0C98119DC1CAE316E91B09F4F6F36BDCF73F8873 -Test: Encrypt -Comment: Set 2, vector 36 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000008000000000000000000000000000000000000000000000000000000 -Ciphertext: E8C3012B0EEB2D18DEA4C06BAC2906DF858BFB8A4D86D6841C02A9E45B2D0455 -Test: Encrypt -Comment: Set 2, vector 37 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000004000000000000000000000000000000000000000000000000000000 -Ciphertext: E10FB90CB2F5F830763FCEFA386A8E70052AB8994A55DC95FEDF8B71E11D2636 -Test: Encrypt -Comment: Set 2, vector 38 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000002000000000000000000000000000000000000000000000000000000 -Ciphertext: 848DFB81A0D4D13A40F9119AB77A3B6D2B96E76396B39984739FDF31ADBC376F -Test: Encrypt -Comment: Set 2, vector 39 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000001000000000000000000000000000000000000000000000000000000 -Ciphertext: 61068A490E20E07686D8A77B81718A3214508E3FE3DA6A6BBAA8ABD67B98623F -Test: Encrypt -Comment: Set 2, vector 40 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000800000000000000000000000000000000000000000000000000000 -Ciphertext: 9197E2A5212260324CA6E6FA0BBA56B4E5D9934C8B9E42D9F43E901C0994082C -Test: Encrypt -Comment: Set 2, vector 41 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000400000000000000000000000000000000000000000000000000000 -Ciphertext: E9DC3C1445CBFF1B863CF3FB6B338B4EC29F2C083E65A4BBCC2F1FAC22CCA8DD -Test: Encrypt -Comment: Set 2, vector 42 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000200000000000000000000000000000000000000000000000000000 -Ciphertext: 80039358C99E64A255D5E4E334C830FFEC8E0CBF2EB6030DE7DCE1A938821938 -Test: Encrypt -Comment: Set 2, vector 43 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000100000000000000000000000000000000000000000000000000000 -Ciphertext: E508D93429BBE95EE38672A2F653841701F391C68235391367F16415C2C84ADC -Test: Encrypt -Comment: Set 2, vector 44 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000080000000000000000000000000000000000000000000000000000 -Ciphertext: 710463874DF68B8930CC5CD6A00ABA2BCE27352997F2582EF472ED5F5AFE75A8 -Test: Encrypt -Comment: Set 2, vector 45 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000040000000000000000000000000000000000000000000000000000 -Ciphertext: E90AD04D26F4FF6D25D193CD2C34A2E1C6A1E570CCC705B873CACC94E61F79A7 -Test: Encrypt -Comment: Set 2, vector 46 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000020000000000000000000000000000000000000000000000000000 -Ciphertext: 8E19B69D55C9A2B2CCEACB50EC8007F39C81A0F261A8568D1298967C132BB790 -Test: Encrypt -Comment: Set 2, vector 47 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000010000000000000000000000000000000000000000000000000000 -Ciphertext: 4051E2FA9032676DC6E11CE947C64C9A0C0FC262AA41F40FA0C4093D1E4FA924 -Test: Encrypt -Comment: Set 2, vector 48 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000008000000000000000000000000000000000000000000000000000 -Ciphertext: 5DA6F415CCDF1A2D3335A0BEBB879D88CB9C871744111004C0E5AA6D27EB0311 -Test: Encrypt -Comment: Set 2, vector 49 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000004000000000000000000000000000000000000000000000000000 -Ciphertext: 684C24EC1DD06F6B565890190BE1F8BC7F4537CF5F9CF038ECB6D1D86164503A -Test: Encrypt -Comment: Set 2, vector 50 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000002000000000000000000000000000000000000000000000000000 -Ciphertext: 6D259C132726524987D4FD96C1ECD943D6B87BB98C61C4FFE41E282EC82F246A -Test: Encrypt -Comment: Set 2, vector 51 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000001000000000000000000000000000000000000000000000000000 -Ciphertext: 14707F80CC43E4E6321362B0ACFF84FE57E9D477B56637D01CAA09B232D726C5 -Test: Encrypt -Comment: Set 2, vector 52 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000800000000000000000000000000000000000000000000000000 -Ciphertext: FE98609B71F9CD65CD377C98BC4117EC8708E58D15361F9CAC02C64F0452B80D -Test: Encrypt -Comment: Set 2, vector 53 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000400000000000000000000000000000000000000000000000000 -Ciphertext: 1B78E77F935EBA86B28C9B37818245E2865AF84A73C9DAA735E42E6009AA07F3 -Test: Encrypt -Comment: Set 2, vector 54 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000200000000000000000000000000000000000000000000000000 -Ciphertext: F354ADD75ED9E121B1BFAD9483C6825AEF57BAA2DF08B519640E022E196B313F -Test: Encrypt -Comment: Set 2, vector 55 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000100000000000000000000000000000000000000000000000000 -Ciphertext: 7E0D7DCC0642CD5BF0C39460C4C183E5F321BCAB5EEA0AC7021E1AECE423E2A9 -Test: Encrypt -Comment: Set 2, vector 56 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000080000000000000000000000000000000000000000000000000 -Ciphertext: D1CCBD3EEA6ACF918569BEC2C900723B4359CA19C58E32ED65FDCBAA30A41C98 -Test: Encrypt -Comment: Set 2, vector 57 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000040000000000000000000000000000000000000000000000000 -Ciphertext: 361246D37645483C6D13C6500326694A0D577604CDF7CD36586B6C7F96FBE077 -Test: Encrypt -Comment: Set 2, vector 58 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000020000000000000000000000000000000000000000000000000 -Ciphertext: 0BC890CF369C233EDB99A51CEC75BFF60FB36BFB3EC15F253054F8865CB16DFF -Test: Encrypt -Comment: Set 2, vector 59 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000010000000000000000000000000000000000000000000000000 -Ciphertext: B5ED5183A00C882F8D213AFCE35C14E940407B7C2A8C9A5A19F289AED42DFAD7 -Test: Encrypt -Comment: Set 2, vector 60 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000008000000000000000000000000000000000000000000000000 -Ciphertext: 22B4EA3A5718D6CEE4EA78725F5BAC735C539C343D7B45121EDDA22CA39D9413 -Test: Encrypt -Comment: Set 2, vector 61 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000004000000000000000000000000000000000000000000000000 -Ciphertext: 94ECEC21BC3426C7214F266B6442F85B6AE765BD6206A951B2AA14505D19FBCA -Test: Encrypt -Comment: Set 2, vector 62 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000002000000000000000000000000000000000000000000000000 -Ciphertext: EF77932A5749126D65BD88330C18D91EDBB7FB53D7B3B675EE148EFC893559B9 -Test: Encrypt -Comment: Set 2, vector 63 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000001000000000000000000000000000000000000000000000000 -Ciphertext: BB9E132DC5DE8035433FBEAC46395E861BDA17A4892FFE6BD1B10D6B4D6AE0F3 -Test: Encrypt -Comment: Set 2, vector 64 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000800000000000000000000000000000000000000000000000 -Ciphertext: 7B536CF871F7FF406AD640683F405F0E14D72E77CDD2AB091D9A8E169155CE24 -Test: Encrypt -Comment: Set 2, vector 65 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000400000000000000000000000000000000000000000000000 -Ciphertext: 2417835AB4BD0A1D3439310480224C52796F3DB3536419F51A09551DFD4A6799 -Test: Encrypt -Comment: Set 2, vector 66 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000200000000000000000000000000000000000000000000000 -Ciphertext: 8E49C9819DFF2DEFCD8DF3E9EA910F79A9A932F43E4B763D6988CC0924C20544 -Test: Encrypt -Comment: Set 2, vector 67 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000100000000000000000000000000000000000000000000000 -Ciphertext: 1D364FDEFCB51560E4408CF25FC05E7698235D271E725590533CE24E3F3EC1EE -Test: Encrypt -Comment: Set 2, vector 68 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000080000000000000000000000000000000000000000000000 -Ciphertext: F1C0422AC64E4D566E799ADA6CE33B59C31051C55ED2212841460CE330F2763E -Test: Encrypt -Comment: Set 2, vector 69 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000040000000000000000000000000000000000000000000000 -Ciphertext: FA90883588183011F2748ADBC5217BA38CF6787FFD8BFCBEA06ADE193B1313C5 -Test: Encrypt -Comment: Set 2, vector 70 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000020000000000000000000000000000000000000000000000 -Ciphertext: 84EE69F947AEAAA0F1F2DA8C1508733D31F62FEBCF7085C68DEA5A602A566EBF -Test: Encrypt -Comment: Set 2, vector 71 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000010000000000000000000000000000000000000000000000 -Ciphertext: 260C06AB73B581E29C34FEE05363F532D4C693B5E8025291FC99C48F9CFCEFF8 -Test: Encrypt -Comment: Set 2, vector 72 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000008000000000000000000000000000000000000000000000 -Ciphertext: 98184C744C6A24B329A7827CE0F5B30AE709493A22F9064D1C3F7FED046D1C2A -Test: Encrypt -Comment: Set 2, vector 73 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000004000000000000000000000000000000000000000000000 -Ciphertext: 3CCDF1C3103B356E7A460410D91F1F00F749EB96F3E89F91248FB5E0949806EF -Test: Encrypt -Comment: Set 2, vector 74 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000002000000000000000000000000000000000000000000000 -Ciphertext: 49AB6245E93A6CF84BF66A7451D134535362CB8A8CE2E47012BF8B4EF02894D4 -Test: Encrypt -Comment: Set 2, vector 75 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000001000000000000000000000000000000000000000000000 -Ciphertext: 7A92C7BB97CB99AD15EA9DA3A629031901840D23EA4227C699944882E2E8F3CC -Test: Encrypt -Comment: Set 2, vector 76 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000800000000000000000000000000000000000000000000 -Ciphertext: 00FC7EBE56FCB696D9606FBBEEA6955871B7A03CDCAAE25DFC47D06145371AD3 -Test: Encrypt -Comment: Set 2, vector 77 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000400000000000000000000000000000000000000000000 -Ciphertext: FFF7327A979B527486052C1B99DECCFCC5E680D39613DE4107E8A04980DDFD70 -Test: Encrypt -Comment: Set 2, vector 78 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000200000000000000000000000000000000000000000000 -Ciphertext: 1E950B49D7D446867ED48272D220BCCC35B104A76A107880FB37D8AE55E69F58 -Test: Encrypt -Comment: Set 2, vector 79 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000100000000000000000000000000000000000000000000 -Ciphertext: 3B97EDED4E70497DAE02FD51E10AB26888096D2D182A7BC7EE55B6F3243E0144 -Test: Encrypt -Comment: Set 2, vector 80 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000080000000000000000000000000000000000000000000 -Ciphertext: 94414A0116665FFD8D1589B050A1663DBA15463206DA4E6A735B58FA7B4AA7ED -Test: Encrypt -Comment: Set 2, vector 81 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000040000000000000000000000000000000000000000000 -Ciphertext: D586FFCBBF32561B9659306068DD31C2A1FBC8DDF99CF0BDAB3DCC0664B403C7 -Test: Encrypt -Comment: Set 2, vector 82 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000020000000000000000000000000000000000000000000 -Ciphertext: 061E17DB1EAF9884C940B8C72E884C8D9D46819FDDF6724239168DDBEE170B9B -Test: Encrypt -Comment: Set 2, vector 83 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000010000000000000000000000000000000000000000000 -Ciphertext: D70F322E45E1D64B3D91249E9DE766DB7EF9084120C13D0215F31A6DE2E791C6 -Test: Encrypt -Comment: Set 2, vector 84 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000008000000000000000000000000000000000000000000 -Ciphertext: 5018967FCA5E67F24DCCE2190D24CD3E24A0B709B70DC38F1A4B4FE39CDCD2E5 -Test: Encrypt -Comment: Set 2, vector 85 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000004000000000000000000000000000000000000000000 -Ciphertext: 9108A0540D8D02658268185F06DFF6F2248681D0D9F9F4C6658942FC27C68246 -Test: Encrypt -Comment: Set 2, vector 86 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000002000000000000000000000000000000000000000000 -Ciphertext: 6595E74A5943DFE1A3FC19ADEBF190CDEC4C2EA0B7CCC6364E0AF7222CCEAA46 -Test: Encrypt -Comment: Set 2, vector 87 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000001000000000000000000000000000000000000000000 -Ciphertext: 5F156FB20AFD4BC0E4E4B2BA7700A38FFCAF9229E3CBA8C99915B692A76ACDEA -Test: Encrypt -Comment: Set 2, vector 88 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000800000000000000000000000000000000000000000 -Ciphertext: F0584D66033584791BED0EB67D2A73AA918E0F88F08683DC1F67DB7DD3375326 -Test: Encrypt -Comment: Set 2, vector 89 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000400000000000000000000000000000000000000000 -Ciphertext: 5EB0956E3DA8ECFC571D5BD1C4EF430FBB10117C6684B8530B6552B812780EBF -Test: Encrypt -Comment: Set 2, vector 90 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000200000000000000000000000000000000000000000 -Ciphertext: E8C8CB56ED63B5BA16DD833CC9C7AC77E425C284FFD547E8F9FE10410CA02FF3 -Test: Encrypt -Comment: Set 2, vector 91 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000100000000000000000000000000000000000000000 -Ciphertext: 68704A278A231ED468C1F0CFF43A4FC61253EACBE2BDCE1ED86D89F43263016D -Test: Encrypt -Comment: Set 2, vector 92 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000080000000000000000000000000000000000000000 -Ciphertext: CA16F899842EE79CBAC4D7CD67172C7DD537E6EA21D48C15B0B34B29BF87E79B -Test: Encrypt -Comment: Set 2, vector 93 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000040000000000000000000000000000000000000000 -Ciphertext: 9E6E7B31FF5D4D5C7D1C264273A27DA542BFCC6116B7DFDEF6332690B7304BDD -Test: Encrypt -Comment: Set 2, vector 94 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000020000000000000000000000000000000000000000 -Ciphertext: FE466983DED41AFB1908DF12A5532054C6DB320F0ECBDCE7610BBE2A07AA7F68 -Test: Encrypt -Comment: Set 2, vector 95 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000010000000000000000000000000000000000000000 -Ciphertext: D2D93C1B66FD710F8B72564A44ACA93995938FEE7C38DE482C9586E3413EB40C -Test: Encrypt -Comment: Set 2, vector 96 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000008000000000000000000000000000000000000000 -Ciphertext: 6623F853780833A60B60E6467CFA3D3D000228F2C8334F8B00CFE119133D41C7 -Test: Encrypt -Comment: Set 2, vector 97 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000004000000000000000000000000000000000000000 -Ciphertext: 1CED4727527E1C3107A89E77645241D240F3F113AC2BF8319E5D8EFF68997595 -Test: Encrypt -Comment: Set 2, vector 98 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000002000000000000000000000000000000000000000 -Ciphertext: FA450B3D8A7C03B643DF6EC70867D0502AE20235335AF5932A7016D71A6059A4 -Test: Encrypt -Comment: Set 2, vector 99 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000001000000000000000000000000000000000000000 -Ciphertext: A6F76AB74CE44538579369F5367B826C4EA72EB6EE08A0CFE1272EB435FDFEFC -Test: Encrypt -Comment: Set 2, vector 100 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000800000000000000000000000000000000000000 -Ciphertext: 8108B48A62A0E0CD58B066C10613E2B589CFB0BCEF4EB58BBF8C88E84A2CD258 -Test: Encrypt -Comment: Set 2, vector 101 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000400000000000000000000000000000000000000 -Ciphertext: F335D10835B018414786D30923663B77B2E0CA65423B96BFA885B9797138CF4F -Test: Encrypt -Comment: Set 2, vector 102 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000200000000000000000000000000000000000000 -Ciphertext: 87D8E75FEDA12025B9517BBF8421E837872E8978E48DA51BB8B8574C04731091 -Test: Encrypt -Comment: Set 2, vector 103 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000100000000000000000000000000000000000000 -Ciphertext: B8A50E6EDFF9711C6064812423F5DC5D77970BE65B545C042A02BACB30A4CD6F -Test: Encrypt -Comment: Set 2, vector 104 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000080000000000000000000000000000000000000 -Ciphertext: EB98815E5A9337DF35F98D7CF27183EC8423D5F9D145326638B864E0F994DD7D -Test: Encrypt -Comment: Set 2, vector 105 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000040000000000000000000000000000000000000 -Ciphertext: 3E5DDB36ABD739986483DE7A9EEF2468461A02B55CAA24100394442F0946F337 -Test: Encrypt -Comment: Set 2, vector 106 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000020000000000000000000000000000000000000 -Ciphertext: 809F726C3BB19BD09D4412B64777085D968ED4E612286008C4BAC69F671E7E31 -Test: Encrypt -Comment: Set 2, vector 107 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000010000000000000000000000000000000000000 -Ciphertext: 28F2EE8D382DF1AB0CF82B93C7A09B87180E8D19C35657302EFE1B1C4CA11ED4 -Test: Encrypt -Comment: Set 2, vector 108 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000008000000000000000000000000000000000000 -Ciphertext: 76E6887FC464215C9576BB233F5A3A7D98CA73F9B2D06E3BB81BC34AF02C8CE9 -Test: Encrypt -Comment: Set 2, vector 109 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000004000000000000000000000000000000000000 -Ciphertext: E8CEF712D7AF841C4FE7800CB04C27E25BDB41BECFA894588F73776CAAE2A0FA -Test: Encrypt -Comment: Set 2, vector 110 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000002000000000000000000000000000000000000 -Ciphertext: 868D3A678A216D01A765046E2991A21F9626493063AFE771E3369E5DA2BA7E9B -Test: Encrypt -Comment: Set 2, vector 111 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000001000000000000000000000000000000000000 -Ciphertext: D6465061FA1B143E1F6A3FCC1601D2D9FAEEF995C457E9EE301A27E8139D1AFE -Test: Encrypt -Comment: Set 2, vector 112 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000800000000000000000000000000000000000 -Ciphertext: B42BB57D2F25612AAB33EF3213D6D210D9831502A1C4D51C4E72148CBB9893D1 -Test: Encrypt -Comment: Set 2, vector 113 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000400000000000000000000000000000000000 -Ciphertext: CE0EC3C44BFAABE6E18B3506E01199B0F2E0BCA4EA6C29D367EDDD0E83A1C65F -Test: Encrypt -Comment: Set 2, vector 114 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000200000000000000000000000000000000000 -Ciphertext: 627101F50E134D6F33EF70AF0E32A3AF7C3237E3A5D99319719F175DD0392383 -Test: Encrypt -Comment: Set 2, vector 115 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000100000000000000000000000000000000000 -Ciphertext: CBCC83BE624059BD8B950BCF486AFBC342CF3575EBA6950FB39C03DB4822EDD9 -Test: Encrypt -Comment: Set 2, vector 116 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000080000000000000000000000000000000000 -Ciphertext: 5EAD7961798903C315DD89BE57105FEA164CA06A4ECDBB5CB10B76711C3E49A0 -Test: Encrypt -Comment: Set 2, vector 117 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000040000000000000000000000000000000000 -Ciphertext: 69169E6E11EAC935E12E6E30EFCEDD7236EAED9C5E1E3B215CD7167AB88B199D -Test: Encrypt -Comment: Set 2, vector 118 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000020000000000000000000000000000000000 -Ciphertext: 5B08F07728399920CA30DC57CE94CAE85A44530033B2AE6BB7F8E29D7934C437 -Test: Encrypt -Comment: Set 2, vector 119 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000010000000000000000000000000000000000 -Ciphertext: 8FAD35B4FBC3BBAB2F4BF00D8A1651BE3FD77085AC5E6C7F6E2EDF5048F86068 -Test: Encrypt -Comment: Set 2, vector 120 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000008000000000000000000000000000000000 -Ciphertext: 71B22D911D9E754A76EC052CD7DC503CDE9A16E9043A04CFA244D8EB19FC21AA -Test: Encrypt -Comment: Set 2, vector 121 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000004000000000000000000000000000000000 -Ciphertext: 062A10B7F5E3E8D7F3FC2C14E10EC9CA947A8FDC0EBC01E3A127BAFE689D6577 -Test: Encrypt -Comment: Set 2, vector 122 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000002000000000000000000000000000000000 -Ciphertext: 0FC375F0F68567F1827C7218132B434E84DA6377DB50AB330E8D9BD2754BD1B8 -Test: Encrypt -Comment: Set 2, vector 123 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000001000000000000000000000000000000000 -Ciphertext: 0E4C1117D462EEBCF5FCD7AC9807AF40C403910421CD19A4634B1C86113EB387 -Test: Encrypt -Comment: Set 2, vector 124 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000800000000000000000000000000000000 -Ciphertext: A9DB2CD2A23780D8BC5A2567961BCA24A41531157D4A229046B47DE48CAE0FDD -Test: Encrypt -Comment: Set 2, vector 125 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000400000000000000000000000000000000 -Ciphertext: 7195678F00F98B00706E7C497E5FA2BC648EDA00B4B7DFAC6234C8232DF8E071 -Test: Encrypt -Comment: Set 2, vector 126 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000200000000000000000000000000000000 -Ciphertext: E5C1970C7C0B8E7E1BF871219486359C2E5037BE6E8E637BDB9F11051FB36A16 -Test: Encrypt -Comment: Set 2, vector 127 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000100000000000000000000000000000000 -Ciphertext: 2426496DC3B09404B609157E2273D526C3E6909B82F65527B42ABDD6348CF602 -Test: Encrypt -Comment: Set 2, vector 128 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000080000000000000000000000000000000 -Ciphertext: F9870238947E1575AF11D14D12E593163B98BA12E79F05563CBFFBCFB23FDC38 -Test: Encrypt -Comment: Set 2, vector 129 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000040000000000000000000000000000000 -Ciphertext: 2B1E410ACE9E8875F965A29D90773B68CAC452AE98CEB5922B7BAD936ACC421B -Test: Encrypt -Comment: Set 2, vector 130 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000020000000000000000000000000000000 -Ciphertext: 180285A7AD7DD8FFD619970804F0FDB9706D5F5C467F815D0B1A455DED9D9300 -Test: Encrypt -Comment: Set 2, vector 131 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000010000000000000000000000000000000 -Ciphertext: BAEB5C1C68D72F1AE4735F6B75CDF9265E4F6F55DA934C4F118A3728AA2BC0D5 -Test: Encrypt -Comment: Set 2, vector 132 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000008000000000000000000000000000000 -Ciphertext: 9DEBFCC984F55E97C0064335C8A4B7489B7BDD75560EA51982114FCE4D481032 -Test: Encrypt -Comment: Set 2, vector 133 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000004000000000000000000000000000000 -Ciphertext: DF3B0B54DF4D1814A6F46B8F8B37E27AE8B9EC54B97BF9C523F1EC713EDDFFEE -Test: Encrypt -Comment: Set 2, vector 134 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000002000000000000000000000000000000 -Ciphertext: 37AA04C74A1E8ED165BC1B4C97265A32B5579D9B2A7B7C883A98B616D5C24FAE -Test: Encrypt -Comment: Set 2, vector 135 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000001000000000000000000000000000000 -Ciphertext: 83815356746186AE4CC327AB3A8CE04EF66ABD32D44D7089F1D7E301BFE006D6 -Test: Encrypt -Comment: Set 2, vector 136 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000800000000000000000000000000000 -Ciphertext: 2C6C7878E099F55653CA784A0BE4C9EC6201AFDCF99CDDC1ED862D4FE88CFDC8 -Test: Encrypt -Comment: Set 2, vector 137 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000400000000000000000000000000000 -Ciphertext: 424804513D38537C024955F2CCB29BECFD801FC06CD8EC5DE353872F0B50616F -Test: Encrypt -Comment: Set 2, vector 138 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000200000000000000000000000000000 -Ciphertext: 48C31A55ED4716825D43FF671C01A86CDD792AABF78703ADC58F5FD65B3C0DE1 -Test: Encrypt -Comment: Set 2, vector 139 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000100000000000000000000000000000 -Ciphertext: BF99E4263F2C512CDE33A91E04FACA55052444E40FF79F09716FC06D24FDDE1D -Test: Encrypt -Comment: Set 2, vector 140 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000080000000000000000000000000000 -Ciphertext: 1A40488BA16A5D0AE6381018F15ABF95C78FB05867E3D7E213CAD7BA3DC9EA3B -Test: Encrypt -Comment: Set 2, vector 141 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000040000000000000000000000000000 -Ciphertext: BEAD8979A1A485959C3E9C8BF9CCF7CF850EB205296E1E8FF8BCAFBB011FF21D -Test: Encrypt -Comment: Set 2, vector 142 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000020000000000000000000000000000 -Ciphertext: A8EDCC85F5A941B4434BD4DAD5E39EEAD102DA25BBB2C3D143572AC7425ED819 -Test: Encrypt -Comment: Set 2, vector 143 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000010000000000000000000000000000 -Ciphertext: 631126B3A837AA4C999EFE6A687BBA58751464A6395670213C8445CC8409C33F -Test: Encrypt -Comment: Set 2, vector 144 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000008000000000000000000000000000 -Ciphertext: CA4A5FD3A3D2DA973E16C0A849E374C5A293351A66415B45107BD228CB842B19 -Test: Encrypt -Comment: Set 2, vector 145 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000004000000000000000000000000000 -Ciphertext: A61FDF733DDEC4C3AE51BE778BDD6E34BED64449ABCA7A718EAA513A2A5A9014 -Test: Encrypt -Comment: Set 2, vector 146 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000002000000000000000000000000000 -Ciphertext: 2C632530E7FCD550B5F9D14E21409AFD07C7E1FBF04B3B3FEC8C61AC8A1591ED -Test: Encrypt -Comment: Set 2, vector 147 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000001000000000000000000000000000 -Ciphertext: B2D97A1D343D3D5E1A7E444BA6E57D2E5ED42E02F719ECA22BA47E796AB37B18 -Test: Encrypt -Comment: Set 2, vector 148 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000800000000000000000000000000 -Ciphertext: AC515AAC675C2C3E46A8F77578189149327413CF40B48E16BF83D3500C2B1355 -Test: Encrypt -Comment: Set 2, vector 149 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000400000000000000000000000000 -Ciphertext: C8ADC6079B92459A8E975FFFE2352A90629CF9E8D53630536D9EBC7DAC4C467E -Test: Encrypt -Comment: Set 2, vector 150 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000200000000000000000000000000 -Ciphertext: 97B2C40964B25AE5CBD092E36B37A3BB4520570A9920034C584C66600D3857D9 -Test: Encrypt -Comment: Set 2, vector 151 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000100000000000000000000000000 -Ciphertext: 99A017D3829CEFE10DDD33D33F53EA470A2A74A35ED3BED8B7E9D6EF3B790153 -Test: Encrypt -Comment: Set 2, vector 152 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000080000000000000000000000000 -Ciphertext: 6141854199F9E01CFE4A35DF918B805985ACC8F8A7456FFBF91D27D4E85E4C49 -Test: Encrypt -Comment: Set 2, vector 153 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000040000000000000000000000000 -Ciphertext: 28BC7571E7C921B31BC2D7BF55853C2CC5B815B39471907DAE152F685791378B -Test: Encrypt -Comment: Set 2, vector 154 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000020000000000000000000000000 -Ciphertext: AD751D4D9D635900C22B6166328ECD85FB4A1610D055793BF04A83CB6F5F02DB -Test: Encrypt -Comment: Set 2, vector 155 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000010000000000000000000000000 -Ciphertext: 8670009356A0A3BD402CF218664826C05BE1651C6E606C011967F8F9C3835017 -Test: Encrypt -Comment: Set 2, vector 156 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000008000000000000000000000000 -Ciphertext: 6CE35F565BC4F38D73116267C49D345B7B19D57D5C90136CAF512F76AF47FAAD -Test: Encrypt -Comment: Set 2, vector 157 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000004000000000000000000000000 -Ciphertext: FD0DF28AFE47414F99219AD120F33DCA6F8756B2264349911041B0AEC9D77A43 -Test: Encrypt -Comment: Set 2, vector 158 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000002000000000000000000000000 -Ciphertext: 49CE284D7A18A0608E5E3768286E919DE97DD81B369AB0A012AD7BDC491DED1A -Test: Encrypt -Comment: Set 2, vector 159 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000001000000000000000000000000 -Ciphertext: 12B27FEC757A809C68F670698E5CB40E762855022FC12DE2332DB9814FC6E5E2 -Test: Encrypt -Comment: Set 2, vector 160 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000800000000000000000000000 -Ciphertext: 53074884476D09C729F35C3906046C2DCBA7F12BF59CDD3CE73ABF91847C6369 -Test: Encrypt -Comment: Set 2, vector 161 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000400000000000000000000000 -Ciphertext: D29E3C55DD3D867D7263D2C961FDB6A97B8D827AB73A20479ACB06DF992AEC24 -Test: Encrypt -Comment: Set 2, vector 162 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000200000000000000000000000 -Ciphertext: 4BE421463C6F2CC8118A50684EB5FC98323EA27F03D4B98EC05727BA0FFA40E8 -Test: Encrypt -Comment: Set 2, vector 163 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000100000000000000000000000 -Ciphertext: A96EC7F07298F9D86A811D0110D60E65C80F3E913B575831A5E8533932196B24 -Test: Encrypt -Comment: Set 2, vector 164 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000080000000000000000000000 -Ciphertext: F12B579997BA4203D8A0FF36181E4C1B50C703FE32CF18D9BF84355BC404D135 -Test: Encrypt -Comment: Set 2, vector 165 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000040000000000000000000000 -Ciphertext: 35EBB3FE5FACC9B9D321E82A73C344CA05D0E73372579349A1F365DEA0105292 -Test: Encrypt -Comment: Set 2, vector 166 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000020000000000000000000000 -Ciphertext: 0F1F0518D57ADC91D810B5899EB7EE7900D05AD8AD2960FE07893F30859B636F -Test: Encrypt -Comment: Set 2, vector 167 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000010000000000000000000000 -Ciphertext: A6CAF97EF17BEFDCF3412D7F45F72C1F1726198ED3B5CD905DF9078DCD70F882 -Test: Encrypt -Comment: Set 2, vector 168 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000008000000000000000000000 -Ciphertext: E287019353E8C71C62178B3AF7A3ECA210D79F803F43C09B6C08F295367A30CA -Test: Encrypt -Comment: Set 2, vector 169 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000004000000000000000000000 -Ciphertext: CF7A7ECEA347875A7B9191BF9FFDC3FB53512052FA42370E39BF5D906EE82D4E -Test: Encrypt -Comment: Set 2, vector 170 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000002000000000000000000000 -Ciphertext: 7E362B5B5ED5CAB9A518320E498FDB915BFD72BB5C588495AC49FC2D5CEC2134 -Test: Encrypt -Comment: Set 2, vector 171 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000001000000000000000000000 -Ciphertext: 69254195C6A9A4D334F8F0558A6C9635EB8A397E5AB672E81DC194AFA5C3A8B7 -Test: Encrypt -Comment: Set 2, vector 172 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000800000000000000000000 -Ciphertext: 3934A6BA3DE9885771111CBA59D50EC684F8F612AAAE3E511C0A211D972723C4 -Test: Encrypt -Comment: Set 2, vector 173 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000400000000000000000000 -Ciphertext: BCEE40ADD3CFDE924F58786640A56A68FE83615EDD82873DF6908057AF39F74A -Test: Encrypt -Comment: Set 2, vector 174 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000200000000000000000000 -Ciphertext: 70F4E0381A989C486A45FAE5B108373E950843EE48DC2A43E7AA625BF3AC9838 -Test: Encrypt -Comment: Set 2, vector 175 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000100000000000000000000 -Ciphertext: FAED24C44DE7F447CD1169F4D8D734E55154B73F79B31AD1CD310C7F5529433A -Test: Encrypt -Comment: Set 2, vector 176 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000080000000000000000000 -Ciphertext: 887BA60DED98C75DADDC1CD0824E7E6C76D947617A919A3B870B489CD1B7F6B2 -Test: Encrypt -Comment: Set 2, vector 177 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000040000000000000000000 -Ciphertext: 33D833FFDB7BEB6BBAB4DDACA6784B88C4B76A49641AA01BC980AB31084F4351 -Test: Encrypt -Comment: Set 2, vector 178 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000020000000000000000000 -Ciphertext: 8CDEF08AB44C2CB2AB5EC94437E501A96999B30C045A79DE99E220595B95DA2F -Test: Encrypt -Comment: Set 2, vector 179 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000010000000000000000000 -Ciphertext: 029247C8EC0610E7F5B49FA4191E99CDECBC1E44DF123270901A57DE8ED64850 -Test: Encrypt -Comment: Set 2, vector 180 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000008000000000000000000 -Ciphertext: 08487E1E53C677CA34640459BDBF7C53247DD54624B9C2156A59F24A818A258E -Test: Encrypt -Comment: Set 2, vector 181 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000004000000000000000000 -Ciphertext: 2C7C0444738DB202D9236CF00E1B75F579E18CAD4341093675F66732746F8060 -Test: Encrypt -Comment: Set 2, vector 182 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000002000000000000000000 -Ciphertext: F493AF90C19A9EA6460AE35418D4857236D678B570352665092854CFF9FB684E -Test: Encrypt -Comment: Set 2, vector 183 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000001000000000000000000 -Ciphertext: 4575CF8865954F9FDCC9C2F7A41BFD52B1C770E2C7609151E41D9B1D0489500C -Test: Encrypt -Comment: Set 2, vector 184 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000800000000000000000 -Ciphertext: BA0606FA831D4EF759CF457F88B0EEDFDF13BD3ABF72547456052C877B9E3A3B -Test: Encrypt -Comment: Set 2, vector 185 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000400000000000000000 -Ciphertext: 10E979D310CAD332AA3DC860EF69B2BBD96E817BFB93393AD4D8B141C0A301E4 -Test: Encrypt -Comment: Set 2, vector 186 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000200000000000000000 -Ciphertext: B46DE2A7729FAF7CEE978353D4392EA23FE1BB36732D101377C603125125FE62 -Test: Encrypt -Comment: Set 2, vector 187 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000100000000000000000 -Ciphertext: F03E1B911C1EDD769CAD59A744FAD47CB5E19502C1E7F4F0B3197101F3B673C1 -Test: Encrypt -Comment: Set 2, vector 188 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000080000000000000000 -Ciphertext: A9128F8B0C1809095597110471DD7F10040AE71626E8C694BA529B4C9E1353A2 -Test: Encrypt -Comment: Set 2, vector 189 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000040000000000000000 -Ciphertext: B9EDCD81B2CFB461C1FC554ED71CCC958AF4B2B726C011173F4058C40211C496 -Test: Encrypt -Comment: Set 2, vector 190 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000020000000000000000 -Ciphertext: 400F0635E34B796116E3752A0EDA47C3ABC19641DDD60427B4CE3AA8700CEA8E -Test: Encrypt -Comment: Set 2, vector 191 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000010000000000000000 -Ciphertext: 0E526F1012B80F22F946FD51D776187DEFD554B1F5806102E7DD9277FE06B826 -Test: Encrypt -Comment: Set 2, vector 192 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000008000000000000000 -Ciphertext: 1FC0DA71F72D08CDD0F59120C4A88E793869A2C598BAB97C92D6C63C0FAEADA9 -Test: Encrypt -Comment: Set 2, vector 193 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000004000000000000000 -Ciphertext: C493FDECD4D49D5FC6D8590C70BEAAD97EB7694244201CA4CF1732E03D7A4251 -Test: Encrypt -Comment: Set 2, vector 194 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000002000000000000000 -Ciphertext: C532BFE04C6CA7E8B4ABFF9E8BD9C676CBC9AA78FEF4A2DC5CC907742B3ED64F -Test: Encrypt -Comment: Set 2, vector 195 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000001000000000000000 -Ciphertext: 5C8F3ECB07F0264162A9C01A6BB2BC5CF3C7B9ED315803BF86A72406C2655242 -Test: Encrypt -Comment: Set 2, vector 196 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000800000000000000 -Ciphertext: 8C13C039C13DF9C8D821D33E85AFE93EEAFCFC2A2F06D85B3BDE2743FC37AD3F -Test: Encrypt -Comment: Set 2, vector 197 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000400000000000000 -Ciphertext: 3D990835001730714D0880420F57041E37A7FAF1FCA991AA38C409C80F2DC61F -Test: Encrypt -Comment: Set 2, vector 198 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000200000000000000 -Ciphertext: EC44357D4F18EBE148B47AB546D6A5F3E08F8F6C9E2B8B6B99FF303814BF43BA -Test: Encrypt -Comment: Set 2, vector 199 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000100000000000000 -Ciphertext: 00C3B30C81FBC65B9E12C8D6429104FDF40D322D47A59E637FC8CE749725BDCC -Test: Encrypt -Comment: Set 2, vector 200 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000080000000000000 -Ciphertext: 6136C065D96E7F18AB296F86AF04BB264A6DA61DEA7C5413C9131B7EBE551B88 -Test: Encrypt -Comment: Set 2, vector 201 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000040000000000000 -Ciphertext: 2A363A08CAD79DF6A3F2DF5D842B14935C5D09C9D6C78C4989ADCB018A735A5D -Test: Encrypt -Comment: Set 2, vector 202 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000020000000000000 -Ciphertext: B25955B31CC449A42502D1AB61D699DE558BA2C7825BA06B17B239851E575880 -Test: Encrypt -Comment: Set 2, vector 203 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000010000000000000 -Ciphertext: CBE2FD81D74436E167D6A5CF8F7DC07338885146351483E4474CD213D853A6FE -Test: Encrypt -Comment: Set 2, vector 204 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000008000000000000 -Ciphertext: 66DE9DCBF2B85FF944EDD40B3D81F5F8699DB1982C045667FDE9A499A7777DD6 -Test: Encrypt -Comment: Set 2, vector 205 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000004000000000000 -Ciphertext: D940E3F69C42E847312E473E362FD609BE7780D99DAC30F8F095D58EFDC58D59 -Test: Encrypt -Comment: Set 2, vector 206 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000002000000000000 -Ciphertext: 60FBA04239A8C312E10C7773673E94678CB1E13B069759AF304C56CCA6F490DD -Test: Encrypt -Comment: Set 2, vector 207 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000001000000000000 -Ciphertext: D67E081F763F322BA82FA01E184C355A65DE8028E47BF0DB5FCAEDA8C2593F02 -Test: Encrypt -Comment: Set 2, vector 208 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000800000000000 -Ciphertext: 434868F9A6086D0F9218E02CB9534E9EEE88B90C6174A4306B0D0843A35CFDFD -Test: Encrypt -Comment: Set 2, vector 209 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000400000000000 -Ciphertext: B6CCB5899745E29FEE7870B22C2F989D84C98C4510DEA892666E187CDEF77E1A -Test: Encrypt -Comment: Set 2, vector 210 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000200000000000 -Ciphertext: E798F9255A21E0ECDC4BA638F0BF03BAA0AD7810844837582193D7FB3E11B5DF -Test: Encrypt -Comment: Set 2, vector 211 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000100000000000 -Ciphertext: 9BAE51C5C4DF9E55570EF0FE5F2C6AC0CF9FD953E65CD07ED12378BD5A0F2911 -Test: Encrypt -Comment: Set 2, vector 212 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000080000000000 -Ciphertext: 95ECC45EEDD4537D6A7D54D60A64CBFB6728982441C7EE10B7A84A80B51EE171 -Test: Encrypt -Comment: Set 2, vector 213 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000040000000000 -Ciphertext: D8D77750B38E522216DA0A1A9DB7C56788E504708A2048B66946FB83C1981FCB -Test: Encrypt -Comment: Set 2, vector 214 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000020000000000 -Ciphertext: 0CAA8435D051798DB289708EC6CC4C98F0018AB7F068FA0E40443A1F227002CD -Test: Encrypt -Comment: Set 2, vector 215 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000010000000000 -Ciphertext: 5410408C0306460E6033543669A26A63F7C7BBDFEF4273C9BAD8AC472EDAFB67 -Test: Encrypt -Comment: Set 2, vector 216 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000008000000000 -Ciphertext: DD3A0F7B61D056015B54A329882E942ECA3C5C3F64ACFE71E3255A8F53E1AD73 -Test: Encrypt -Comment: Set 2, vector 217 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000004000000000 -Ciphertext: 80A70BE4CC4C61C0F7F501E8068C75CEA78DC11A224D0C47C09D20361C99CF00 -Test: Encrypt -Comment: Set 2, vector 218 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000002000000000 -Ciphertext: BEF3417464A46BBD2B7E9FB967F4FBF406C2B5B9C8B076B770C199C003786A40 -Test: Encrypt -Comment: Set 2, vector 219 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000001000000000 -Ciphertext: C1756ADF6EEF9837B43C4B032B17A79C3A583EE37981CC495CA95893F34218A6 -Test: Encrypt -Comment: Set 2, vector 220 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000800000000 -Ciphertext: 90273FCA31968871BE3D5C76AFCB47D9ECC31A48B87988FD359E93AFF6815F4D -Test: Encrypt -Comment: Set 2, vector 221 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000400000000 -Ciphertext: D0A5F666F7A819EF8BA114C1872158179731F6989997E13AFD73DB252E5CD2A2 -Test: Encrypt -Comment: Set 2, vector 222 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000200000000 -Ciphertext: D4E3DA34C47E5A86A723ED5B9F615B283E4CD54E9F2ED9EAA98A7AB8DE41B14C -Test: Encrypt -Comment: Set 2, vector 223 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000100000000 -Ciphertext: 547227D086EBB538F5836B8E1E65601209AEB6DFD1C450C014C559D879D71862 -Test: Encrypt -Comment: Set 2, vector 224 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000080000000 -Ciphertext: 9E52F033EFE0762ED108095BDF6CD8A89F8E1028F0D3D9B39B601C1084F95F74 -Test: Encrypt -Comment: Set 2, vector 225 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000040000000 -Ciphertext: A049C5B9BD63EBEB23B34EA2F27813D29EDC044E2486D709AC7D2C731557066B -Test: Encrypt -Comment: Set 2, vector 226 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000020000000 -Ciphertext: 1A9CDD2A99C5ED7FB2A6A1870230B0BD6890567E0E4439E248548DF25CB6126E -Test: Encrypt -Comment: Set 2, vector 227 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000010000000 -Ciphertext: 41F2CDA0EFE97BCE8689CF33201B4E57E0600BBB1F274DF3D589915F8EA5C372 -Test: Encrypt -Comment: Set 2, vector 228 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000008000000 -Ciphertext: 1F4712D7AB6D127ABDA90DA977CFC60B44F84859AE4B705851CF687E01E1E250 -Test: Encrypt -Comment: Set 2, vector 229 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000004000000 -Ciphertext: DC93D915CBBC140EDB08B34406F71B4CD38274E92DE8FAF355D274AE7929BC28 -Test: Encrypt -Comment: Set 2, vector 230 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000002000000 -Ciphertext: D2D9A648EDAF9339D7EE52419CC33C42E4CA91AA670D14B78952F41F889122E5 -Test: Encrypt -Comment: Set 2, vector 231 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000001000000 -Ciphertext: F34BA77405D00CAFC3E6786CDB26263C10CDC4D6AFAEDF4C26566A51DB82F5F9 -Test: Encrypt -Comment: Set 2, vector 232 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000800000 -Ciphertext: 21A7EAD6D95FC7AB788206CEA15A25CC4AEB69BAA96C78D5E2851DDBA25523F0 -Test: Encrypt -Comment: Set 2, vector 233 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000400000 -Ciphertext: 822BC3900195E6F224805E77B2460A65FA1A11CFD473F1DFA65351CBB4EFDFEB -Test: Encrypt -Comment: Set 2, vector 234 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000200000 -Ciphertext: 648A71BE1E77866181F980B37690D5C8A37DF29BB2EBC3A41665CD0CCC2E8EF8 -Test: Encrypt -Comment: Set 2, vector 235 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000100000 -Ciphertext: 808E32C933955FF7C8D6F1A4C6754CB3B7311612CFF846D02C81B712C78EB63E -Test: Encrypt -Comment: Set 2, vector 236 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000080000 -Ciphertext: E074251CC7C5BFFCE2CA45933206B2EE8864156A4626C03EA030B71F8BD454BE -Test: Encrypt -Comment: Set 2, vector 237 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000040000 -Ciphertext: 72EBE213A06F63603B49A750808F348FF7C9E4EC72884FDA7C58968EC5A25EED -Test: Encrypt -Comment: Set 2, vector 238 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000020000 -Ciphertext: 20618612C2AF418DE3E185AF7973D508DC31DE1E9D9FB4FDF9E95FD592F567EF -Test: Encrypt -Comment: Set 2, vector 239 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000010000 -Ciphertext: F94C66D4884A657BF0A6A6EA31A90A07F193F55465575FF1BF8DE68F3441BF4E -Test: Encrypt -Comment: Set 2, vector 240 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000008000 -Ciphertext: 9636DCAB40FB991FC330D8EFD671FF83BAA0C9E33D7A146D5E7ADC53592B605F -Test: Encrypt -Comment: Set 2, vector 241 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000004000 -Ciphertext: FC21689B5F46A011ECFE1E314E03ED7105BAC620193714B2290087C17FB763B6 -Test: Encrypt -Comment: Set 2, vector 242 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000002000 -Ciphertext: ABD2583E0FCC95122FDC700AF9B1FDA50D91E752E19BE9D2EE4F5E22033D53C6 -Test: Encrypt -Comment: Set 2, vector 243 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000001000 -Ciphertext: 3501CD56EE5EA39AB32F38371E5C2CF6EEEB9DA82D210A8D88AE8F29917AE9F4 -Test: Encrypt -Comment: Set 2, vector 244 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000800 -Ciphertext: 7559A2AA6CBFA8A181565EDDDE323DB80CE740545FFEE13B4851980AD2451E24 -Test: Encrypt -Comment: Set 2, vector 245 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000400 -Ciphertext: CEF6DBFD1FBCCBB587BD748D6CC992F8EF671A829E2D6AD73D1DC1C1B2A9E8DD -Test: Encrypt -Comment: Set 2, vector 246 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000200 -Ciphertext: 46FBBCD26A1F879746BDF4FF7804A5C105F621837ABCF94F17123B700A58A08A -Test: Encrypt -Comment: Set 2, vector 247 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000100 -Ciphertext: 0B10D2DA0E0FB6F067D641FF7F8C9C8FF4E2D689450787B7136ADF38DC1F2948 -Test: Encrypt -Comment: Set 2, vector 248 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000080 -Ciphertext: 4492E09E73459BF74417FC0D7190DA719A891C9CAE14801944FFB24912E377A8 -Test: Encrypt -Comment: Set 2, vector 249 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000040 -Ciphertext: 76D72C3D3AF6F2FF6AFBC0C1A553E6F8171D81D6BB1CB3C3A6C43ED826A88FAA -Test: Encrypt -Comment: Set 2, vector 250 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000020 -Ciphertext: D912041134584B69AC01938EC88913DBCFF7CDBE93CDF7443BD465F1B2E3F7F5 -Test: Encrypt -Comment: Set 2, vector 251 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000010 -Ciphertext: F0883EB64A5345CC9A0055D4E882D199EFFC334C05B53BC4132AC1A51BA39A9F -Test: Encrypt -Comment: Set 2, vector 252 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000008 -Ciphertext: 276246B0D93A4E6FF05832F51D2BF60641B63594EB90A1E08A7D98C6DDAE1461 -Test: Encrypt -Comment: Set 2, vector 253 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000004 -Ciphertext: 6AA2B04BF65F4213583CED5347537123DC3BE0703209170D1D34B0B8A66C1C58 -Test: Encrypt -Comment: Set 2, vector 254 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000002 -Ciphertext: DC438414927E453DBFD91DC60C635EE4273A9921A134DB513AB2BBDBAE64A9AD -Test: Encrypt -Comment: Set 2, vector 255 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000001 -Ciphertext: 45D43E9288738C5AD1A683D8DE59CEDD22D666A2B7078EB1301B532A272D570B -Test: Encrypt -Comment: Set 3, vector 0 -Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 -Ciphertext: 7CA51614425C3BA8CE54DD2FC2020AE7B6E574D198136D0FAE7E26CCBF0BE7A6 -Test: Encrypt -Comment: Set 3, vector 1 -Key: 01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 -Plaintext: 0101010101010101010101010101010101010101010101010101010101010101 -Ciphertext: C4B7C6A9738C77EE28F7E685C8358E0AF88FB6D23955EE6DF49FE3F5DA16F826 -Test: Encrypt -Comment: Set 3, vector 2 -Key: 02020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202 -Plaintext: 0202020202020202020202020202020202020202020202020202020202020202 -Ciphertext: CD108DD9EC1000B79C75AA3DCC88F913E6F52773853035A5C44F3245B134CBFF -Test: Encrypt -Comment: Set 3, vector 3 -Key: 03030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303 -Plaintext: 0303030303030303030303030303030303030303030303030303030303030303 -Ciphertext: E8F9DE8F066B675AE90C919FC4981603485BBB92382D8C844CAF707973D5276D -Test: Encrypt -Comment: Set 3, vector 4 -Key: 04040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404 -Plaintext: 0404040404040404040404040404040404040404040404040404040404040404 -Ciphertext: 6AA777340200C1B65AB25193A8BB267C233DAC7E1B3C523D406FC5B567B7B586 -Test: Encrypt -Comment: Set 3, vector 5 -Key: 05050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505 -Plaintext: 0505050505050505050505050505050505050505050505050505050505050505 -Ciphertext: 6B14A9C454143376DBDC3C93FB8096B09C01456B0B55412FD9692CD7CB587069 -Test: Encrypt -Comment: Set 3, vector 6 -Key: 06060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606 -Plaintext: 0606060606060606060606060606060606060606060606060606060606060606 -Ciphertext: 3FED53DEF4FBC1D012B36562132AB40049818DA4E62E86716DE5EF70790B0D6A -Test: Encrypt -Comment: Set 3, vector 7 -Key: 07070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707 -Plaintext: 0707070707070707070707070707070707070707070707070707070707070707 -Ciphertext: 7A428F7A6841BC8F0E99335C5021C413D2639321DC8D9F280A2F0EF4B420A212 -Test: Encrypt -Comment: Set 3, vector 8 -Key: 08080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808 -Plaintext: 0808080808080808080808080808080808080808080808080808080808080808 -Ciphertext: A23BE32D37FA4054EC45D6A9CC643AF9124EDAA4AD9ABC7FAAB449D39D11B128 -Test: Encrypt -Comment: Set 3, vector 9 -Key: 09090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909 -Plaintext: 0909090909090909090909090909090909090909090909090909090909090909 -Ciphertext: 972195D6756F7D3A4D13BF49BFBCE7D164460355150C297A41CCC6AA9F31C5D6 -Test: Encrypt -Comment: Set 3, vector 10 -Key: 0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A -Plaintext: 0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A -Ciphertext: 2AA722C58EBDB7701225BA9C3B1F7C946D57DEDC74FEDDB637EB14E27A0F0CC9 -Test: Encrypt -Comment: Set 3, vector 11 -Key: 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B -Plaintext: 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B -Ciphertext: 1C9A0420B9F6EF013FB3ADB4F20C862B61702BA479276E3187322B33D4B128C2 -Test: Encrypt -Comment: Set 3, vector 12 -Key: 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C -Plaintext: 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C -Ciphertext: 666CC3862BAACADA4D35A9079D52438FB3B4416C9938397E61D48066B6476068 -Test: Encrypt -Comment: Set 3, vector 13 -Key: 0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D -Plaintext: 0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D -Ciphertext: DB94504EF884901FAA5778199329A2DCC9AA50A4453172CE8ADE11BFE54234E9 -Test: Encrypt -Comment: Set 3, vector 14 -Key: 0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E -Plaintext: 0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E -Ciphertext: DF0B4204DB7E0924BD2931C131E6DFEB013A5844F717DF7A2DEF86FBC2125DA6 -Test: Encrypt -Comment: Set 3, vector 15 -Key: 0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F -Plaintext: 0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F -Ciphertext: D7C2D4257254E7A05657047B43B65AB778C9E6ACDE53F14000FDFC346CEE4BA6 -Test: Encrypt -Comment: Set 3, vector 16 -Key: 10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010 -Plaintext: 1010101010101010101010101010101010101010101010101010101010101010 -Ciphertext: F64819DFBEBE0A6DB650E7072CE28EA606586418B317785FF0AD44212A84C82C -Test: Encrypt -Comment: Set 3, vector 17 -Key: 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 -Plaintext: 1111111111111111111111111111111111111111111111111111111111111111 -Ciphertext: 155B7E6FFCC0AA874E22494545374E97C08A3D1B1045A0F35FFC54B2842D02A4 -Test: Encrypt -Comment: Set 3, vector 18 -Key: 12121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212 -Plaintext: 1212121212121212121212121212121212121212121212121212121212121212 -Ciphertext: FEE12FD9E87DCB4FE5C5249E3EAEDA0514F6A4826C1A5ABC87E22B95D4A84851 -Test: Encrypt -Comment: Set 3, vector 19 -Key: 13131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313 -Plaintext: 1313131313131313131313131313131313131313131313131313131313131313 -Ciphertext: 1DA785C2A2CEFED459474EE5401F5B795F6ED468DBB924CFFCF65EF465DE9534 -Test: Encrypt -Comment: Set 3, vector 20 -Key: 14141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414 -Plaintext: 1414141414141414141414141414141414141414141414141414141414141414 -Ciphertext: 4434A4D83273B06B64AF4ED1D70EEAD50DBFC44C5931A7B7B98FF9F514B229E9 -Test: Encrypt -Comment: Set 3, vector 21 -Key: 15151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515 -Plaintext: 1515151515151515151515151515151515151515151515151515151515151515 -Ciphertext: 1AB982A6C64C2C42D05F9FB8ED9BE0EEB5B48CEE8EAB0250D98D43157E999EDC -Test: Encrypt -Comment: Set 3, vector 22 -Key: 16161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616 -Plaintext: 1616161616161616161616161616161616161616161616161616161616161616 -Ciphertext: 83291A3265ACAB71E5CCCF0281A433579F39AE6C2FB7CB7528D7F820158177FF -Test: Encrypt -Comment: Set 3, vector 23 -Key: 17171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717 -Plaintext: 1717171717171717171717171717171717171717171717171717171717171717 -Ciphertext: 90F1FF9F69854321CFC6D0A4541CCDF73C1A1DC737D96FB76F0DDD0BB0097BBA -Test: Encrypt -Comment: Set 3, vector 24 -Key: 18181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818 -Plaintext: 1818181818181818181818181818181818181818181818181818181818181818 -Ciphertext: ABF9813765AFBEA9BF26026716294D5C5B309243339ECC9F21CEADE6E7083266 -Test: Encrypt -Comment: Set 3, vector 25 -Key: 19191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919 -Plaintext: 1919191919191919191919191919191919191919191919191919191919191919 -Ciphertext: 7B5C8222D85392E82E703ADFB0FF02DBD2297791B84E26A3A1ED12309247D064 -Test: Encrypt -Comment: Set 3, vector 26 -Key: 1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A -Plaintext: 1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A -Ciphertext: 227355246FCC9106FA5572475E8C466F1140CD75A8A84DFCD2B0908392914FD7 -Test: Encrypt -Comment: Set 3, vector 27 -Key: 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B -Plaintext: 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B -Ciphertext: E5E5A887FA888691FF93014C2E368DC10775A447A5EF4B632A089DA82D245BE3 -Test: Encrypt -Comment: Set 3, vector 28 -Key: 1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C -Plaintext: 1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C -Ciphertext: BA417FC94107761C0969EF6EA7DDC74E5F85CAB61E2271CEB6D9C98B139F4576 -Test: Encrypt -Comment: Set 3, vector 29 -Key: 1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D -Plaintext: 1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D -Ciphertext: F3B85912DF6950B9AE28CE08E456D494E0C949A36FA102540C51827AEC9168AB -Test: Encrypt -Comment: Set 3, vector 30 -Key: 1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E -Plaintext: 1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E -Ciphertext: 1AC0ED993D24366380522B05F97B6FC64B199241A1D556B992632AEE400F0494 -Test: Encrypt -Comment: Set 3, vector 31 -Key: 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F -Plaintext: 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F -Ciphertext: 3550CD591130231B0F01F6860B699715B98B9497B4035C7323000D67C5F0B1B7 -Test: Encrypt -Comment: Set 3, vector 32 -Key: 20202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020 -Plaintext: 2020202020202020202020202020202020202020202020202020202020202020 -Ciphertext: E267D6113C27170A3EE6DF496E801A6131BBD3444365D7C03791E25610F1A0E4 -Test: Encrypt -Comment: Set 3, vector 33 -Key: 21212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121 -Plaintext: 2121212121212121212121212121212121212121212121212121212121212121 -Ciphertext: 3D71B778381E70BCC1A7B8411208225FC922857E862FC17312E3782CEA289B15 -Test: Encrypt -Comment: Set 3, vector 34 -Key: 22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222 -Plaintext: 2222222222222222222222222222222222222222222222222222222222222222 -Ciphertext: 16B41DE00DBF29B96CC59E246DE3188B786E097394E9EEE2250169AE00306FD8 -Test: Encrypt -Comment: Set 3, vector 35 -Key: 23232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323 -Plaintext: 2323232323232323232323232323232323232323232323232323232323232323 -Ciphertext: 99DDE88C9F26D270B3C507A25FE49955A0FEA6C8FEBAD133842DA1CE730EEB7F -Test: Encrypt -Comment: Set 3, vector 36 -Key: 24242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424 -Plaintext: 2424242424242424242424242424242424242424242424242424242424242424 -Ciphertext: 9766D3F9E73987EE10A20605C8338C0759A7024CF2DF549DE5084EC4902C550A -Test: Encrypt -Comment: Set 3, vector 37 -Key: 25252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525 -Plaintext: 2525252525252525252525252525252525252525252525252525252525252525 -Ciphertext: 0FFD89849C8EC5A46B8F43C799ED305AF602C73E810FC729A8C9BB0F5C55CD54 -Test: Encrypt -Comment: Set 3, vector 38 -Key: 26262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626 -Plaintext: 2626262626262626262626262626262626262626262626262626262626262626 -Ciphertext: 91956E101CE4546623A5BE49811F167476CB568972CEBF7A59EB27DA524A0C6B -Test: Encrypt -Comment: Set 3, vector 39 -Key: 27272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727 -Plaintext: 2727272727272727272727272727272727272727272727272727272727272727 -Ciphertext: 7DEC5ECE0D590EE3E099C07F2DD6A6A9C71632D277803FD007275B93369ABED0 -Test: Encrypt -Comment: Set 3, vector 40 -Key: 28282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828 -Plaintext: 2828282828282828282828282828282828282828282828282828282828282828 -Ciphertext: 039C192AFC54EFDE1ED3610B0E9F95AA08D7CDC6AE71A66B5C508E4D14C038CF -Test: Encrypt -Comment: Set 3, vector 41 -Key: 29292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929 -Plaintext: 2929292929292929292929292929292929292929292929292929292929292929 -Ciphertext: D558F8F4562BD8FE816FABF621556C8416C6FD00209028DF978F8915CC093E16 -Test: Encrypt -Comment: Set 3, vector 42 -Key: 2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A -Plaintext: 2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A -Ciphertext: 1AE21791ED4B610DD693012518759D6E9C1BBF206482EEA43470F02B493CFFB8 -Test: Encrypt -Comment: Set 3, vector 43 -Key: 2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B -Plaintext: 2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B -Ciphertext: 34F2112E8FBD1B373BA8400B05321F658FDFE0DC87C1304C36766DE71840A4DF -Test: Encrypt -Comment: Set 3, vector 44 -Key: 2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C -Plaintext: 2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C -Ciphertext: DBF9B56BBF2E50DF321CA687F8BE0E6222E7DF52B4A142174058CC119D9EC0DA -Test: Encrypt -Comment: Set 3, vector 45 -Key: 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D -Plaintext: 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D -Ciphertext: 8B2757374F778FE0B30D11AD7116CE37E2AB858A4E1C50D1115B6E328F3635F5 -Test: Encrypt -Comment: Set 3, vector 46 -Key: 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E -Plaintext: 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E -Ciphertext: 06588A873366FAA47323C9A098A759718DFB0E310C91A4E38B42CC56A0757811 -Test: Encrypt -Comment: Set 3, vector 47 -Key: 2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F -Plaintext: 2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F -Ciphertext: 7B861B18E3F322D8000BDDCBCE3B50405AA923375568F16AE84411E91DB879C3 -Test: Encrypt -Comment: Set 3, vector 48 -Key: 30303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030 -Plaintext: 3030303030303030303030303030303030303030303030303030303030303030 -Ciphertext: 170F74A4D692C302551EE17CD544D65185112D2A5E812D203B36FC39BF1DA9C7 -Test: Encrypt -Comment: Set 3, vector 49 -Key: 31313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131 -Plaintext: 3131313131313131313131313131313131313131313131313131313131313131 -Ciphertext: 0178F59DDAB05A4DFAF66FD406170E08227096EF9712CB481A26EBD82F470D7A -Test: Encrypt -Comment: Set 3, vector 50 -Key: 32323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232 -Plaintext: 3232323232323232323232323232323232323232323232323232323232323232 -Ciphertext: 8BAC479F3A92DF71F973AA457E19D75FB0F1A0FE68FF440A86154721BCC345D4 -Test: Encrypt -Comment: Set 3, vector 51 -Key: 33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333 -Plaintext: 3333333333333333333333333333333333333333333333333333333333333333 -Ciphertext: EB50A10C7A0ED9960CDE0C3EDB899A6B67324B1EE23DE4BB13F60D187C3CBA35 -Test: Encrypt -Comment: Set 3, vector 52 -Key: 34343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434 -Plaintext: 3434343434343434343434343434343434343434343434343434343434343434 -Ciphertext: 00AA782AC61FD06DC781E3C5662C65BD1043EC28D056C98F07074DA7C11C1E1F -Test: Encrypt -Comment: Set 3, vector 53 -Key: 35353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535 -Plaintext: 3535353535353535353535353535353535353535353535353535353535353535 -Ciphertext: 23B9F2F26CFC51ECC6DD1AFE614C2DAE8348DA033F9B67AEAA87B71F5377D95D -Test: Encrypt -Comment: Set 3, vector 54 -Key: 36363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636 -Plaintext: 3636363636363636363636363636363636363636363636363636363636363636 -Ciphertext: 9655D4B1CBEF855401274C3339C16DB9B5A9651F60579CFE8554B6EE25DCCA0E -Test: Encrypt -Comment: Set 3, vector 55 -Key: 37373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737 -Plaintext: 3737373737373737373737373737373737373737373737373737373737373737 -Ciphertext: E072ED2DAD79B07C48B50ED31E02FD9705562525D49DBF45DACCFDF35D5A6965 -Test: Encrypt -Comment: Set 3, vector 56 -Key: 38383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838 -Plaintext: 3838383838383838383838383838383838383838383838383838383838383838 -Ciphertext: 287638BAE945B88A95029155BC47D033B5C5C4C191F079C234C6E97683FFABA0 -Test: Encrypt -Comment: Set 3, vector 57 -Key: 39393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939 -Plaintext: 3939393939393939393939393939393939393939393939393939393939393939 -Ciphertext: 500CD3B02BF6FA8C66D1ADE0CE43B325A759CD3426096084A261F054D798F885 -Test: Encrypt -Comment: Set 3, vector 58 -Key: 3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A -Plaintext: 3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A -Ciphertext: 17614BAB583F2DCF809A2AEE973A4875251B571525521B3A8C47303450B6301F -Test: Encrypt -Comment: Set 3, vector 59 -Key: 3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B -Plaintext: 3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B -Ciphertext: 978C8DFD9AC74FF670CC8B31EDC8EC15DDBC2854375ED9BA07BB0F7B96C70BB3 -Test: Encrypt -Comment: Set 3, vector 60 -Key: 3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C -Plaintext: 3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C -Ciphertext: 994CA36F6230C7DB63CAD61342FAB3F155C361DAD458FC457AD09ACCAB2EB43F -Test: Encrypt -Comment: Set 3, vector 61 -Key: 3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D -Plaintext: 3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D -Ciphertext: AC06659932208AC1DD5F07448A7407232F1410CDAC92F7C5305C4043C559345F -Test: Encrypt -Comment: Set 3, vector 62 -Key: 3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E -Plaintext: 3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E -Ciphertext: B55616F0743A29655FEC468CD30C8C65F7925327665670BA9E41A2E09C05C63B -Test: Encrypt -Comment: Set 3, vector 63 -Key: 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F -Plaintext: 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F -Ciphertext: 78F4852712C3547547A114E73F52C6128EDD3F29E0B2C938D6F9F69AF2303FD2 -Test: Encrypt -Comment: Set 3, vector 64 -Key: 40404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040 -Plaintext: 4040404040404040404040404040404040404040404040404040404040404040 -Ciphertext: C97909916EE86FFDCE8A92903046109B53F788A53039434DF1A394DAD6F697A2 -Test: Encrypt -Comment: Set 3, vector 65 -Key: 41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141 -Plaintext: 4141414141414141414141414141414141414141414141414141414141414141 -Ciphertext: C3FD3C59D37D44AF9EE6B87AC0939A4A4B2FBAAC23E80E72B1CAC352FE30A8E2 -Test: Encrypt -Comment: Set 3, vector 66 -Key: 42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 -Plaintext: 4242424242424242424242424242424242424242424242424242424242424242 -Ciphertext: 94C70F7654479BC9DA9854129F57F3E69C31B63900A404F577AF1C83CD96E5D6 -Test: Encrypt -Comment: Set 3, vector 67 -Key: 43434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343 -Plaintext: 4343434343434343434343434343434343434343434343434343434343434343 -Ciphertext: 71DD024E9CE700B373A275AA870A68B5DAD9E47D38BC18F34073319041A1CADF -Test: Encrypt -Comment: Set 3, vector 68 -Key: 44444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444 -Plaintext: 4444444444444444444444444444444444444444444444444444444444444444 -Ciphertext: 274D101B2BD0E7CAFC9E5559DC68567DC8975056B84573C4294D78513B7406D8 -Test: Encrypt -Comment: Set 3, vector 69 -Key: 45454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545 -Plaintext: 4545454545454545454545454545454545454545454545454545454545454545 -Ciphertext: 8DCE5B5C376E42F11A322D8CBCEB8C0AE1EC24F3C65D72B326708FEAF13E3B51 -Test: Encrypt -Comment: Set 3, vector 70 -Key: 46464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646 -Plaintext: 4646464646464646464646464646464646464646464646464646464646464646 -Ciphertext: D62D3BA9BBD23F4424EB929AE7A4CD83A70FA7EFD2E6CCFED23E1176AFDB69CD -Test: Encrypt -Comment: Set 3, vector 71 -Key: 47474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747 -Plaintext: 4747474747474747474747474747474747474747474747474747474747474747 -Ciphertext: FE7670925FEA3AAE1F039590EA230C094C3E434BF1350B12D4EA26E48A6EF7F0 -Test: Encrypt -Comment: Set 3, vector 72 -Key: 48484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848 -Plaintext: 4848484848484848484848484848484848484848484848484848484848484848 -Ciphertext: 3A57E728BFA31AA36C8E4ED38A34B465BA233AD066225F31651C93B870AAFE6D -Test: Encrypt -Comment: Set 3, vector 73 -Key: 49494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949 -Plaintext: 4949494949494949494949494949494949494949494949494949494949494949 -Ciphertext: 3B56014035A28EA6F2F2B09429FED7FC0F5B76D5458F1EB4F3AAA7E7F6610C65 -Test: Encrypt -Comment: Set 3, vector 74 -Key: 4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A -Plaintext: 4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A -Ciphertext: 2D28A28ECABAC61B540CD933BE43AF16F11429EDE8E7B62121CD853054363730 -Test: Encrypt -Comment: Set 3, vector 75 -Key: 4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B -Plaintext: 4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B -Ciphertext: D8A892E3C24C6A2EB8446B3737A0E3AA1478811B819FFD3440B5307185906518 -Test: Encrypt -Comment: Set 3, vector 76 -Key: 4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C -Plaintext: 4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C -Ciphertext: 798AD5E43127299B61247059F508268CDBA78B46D4FD28C200AE1052C52294E7 -Test: Encrypt -Comment: Set 3, vector 77 -Key: 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D -Plaintext: 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D -Ciphertext: 63F43065BA1F262D950219D71B9CD5FA78D6798BCAA981FE3391FF8EA735E4C7 -Test: Encrypt -Comment: Set 3, vector 78 -Key: 4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E -Plaintext: 4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E -Ciphertext: E8E461EB5FD98011A37765ECA336B080D58B35C636AD6F423893EE768913255C -Test: Encrypt -Comment: Set 3, vector 79 -Key: 4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F -Plaintext: 4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F -Ciphertext: 7348E30FFC0C4F5569B6490622A34FB015C364944553582355887BC472279E8D -Test: Encrypt -Comment: Set 3, vector 80 -Key: 50505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050 -Plaintext: 5050505050505050505050505050505050505050505050505050505050505050 -Ciphertext: BE28CB05EEEEDA8FD8971E9970ECBCA25856F66E95AC8B987C69F04BE3276CD7 -Test: Encrypt -Comment: Set 3, vector 81 -Key: 51515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151 -Plaintext: 5151515151515151515151515151515151515151515151515151515151515151 -Ciphertext: 5D336C5E34D4EB95CFAB87C542C72A748AA45E7F77D841A738017927C7908804 -Test: Encrypt -Comment: Set 3, vector 82 -Key: 52525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252 -Plaintext: 5252525252525252525252525252525252525252525252525252525252525252 -Ciphertext: 2942A594A7964F41460EB6037DDE2C28FFBFFB3C21F7EFF43F06632DA980ED8B -Test: Encrypt -Comment: Set 3, vector 83 -Key: 53535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353 -Plaintext: 5353535353535353535353535353535353535353535353535353535353535353 -Ciphertext: 1C0F7A4E3147BC7F8150D8144ED31D0054FF15414E5DBF289BFEC160D22684AC -Test: Encrypt -Comment: Set 3, vector 84 -Key: 54545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454 -Plaintext: 5454545454545454545454545454545454545454545454545454545454545454 -Ciphertext: 7931C7B9D78CB50610B1BEF596268B94446FCDA44C3EE7CEE53121AC519C4001 -Test: Encrypt -Comment: Set 3, vector 85 -Key: 55555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555 -Plaintext: 5555555555555555555555555555555555555555555555555555555555555555 -Ciphertext: F4E331C357C603EE5ED5547D75B54631A68D7CD74C5075198D0FC38E5661F556 -Test: Encrypt -Comment: Set 3, vector 86 -Key: 56565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656 -Plaintext: 5656565656565656565656565656565656565656565656565656565656565656 -Ciphertext: 378C2887958E31971E8F59C882730E48407E4DA9C26D4C76B672CD53202AB1B8 -Test: Encrypt -Comment: Set 3, vector 87 -Key: 57575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757 -Plaintext: 5757575757575757575757575757575757575757575757575757575757575757 -Ciphertext: DBE68FE249F4A8D36E1CB49DBE20ED58649CCC502F85895875C1FE82269219DA -Test: Encrypt -Comment: Set 3, vector 88 -Key: 58585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858 -Plaintext: 5858585858585858585858585858585858585858585858585858585858585858 -Ciphertext: 103BD780F3B382C4B28E6E1CB41CBEE22CC1BB64E4A0147D658EDA96A6E7FEAB -Test: Encrypt -Comment: Set 3, vector 89 -Key: 59595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959 -Plaintext: 5959595959595959595959595959595959595959595959595959595959595959 -Ciphertext: 382EF838282E0F4BA729083542BB8CB48AB874FF568DFDA56AFC4ED266DD3243 -Test: Encrypt -Comment: Set 3, vector 90 -Key: 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A -Plaintext: 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A -Ciphertext: 088665DE8F9DC9298DEF4164C12526597F56859AAC2C96A95645A06014BA689A -Test: Encrypt -Comment: Set 3, vector 91 -Key: 5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B -Plaintext: 5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B -Ciphertext: EC988946646A1B2DCC7EDEC4FCAB11BF29055A226F4C75D28F9DFB8D2EB5C9B6 -Test: Encrypt -Comment: Set 3, vector 92 -Key: 5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C -Plaintext: 5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C -Ciphertext: B77221CE7F68292BD4E3A55E8EC7BD1FC68B1B6B02F1008586248833C1089F5C -Test: Encrypt -Comment: Set 3, vector 93 -Key: 5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D -Plaintext: 5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D -Ciphertext: B3E4AA5DE6D25A6237FDD97540191D669C64E54A7D3C544E949489355AFC82B5 -Test: Encrypt -Comment: Set 3, vector 94 -Key: 5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E -Plaintext: 5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E -Ciphertext: AAA6FA046AC4270B22A742C4C29445EB38511E5048414886EBF39523B7EAF76A -Test: Encrypt -Comment: Set 3, vector 95 -Key: 5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F -Plaintext: 5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F -Ciphertext: 4D23440171778573BE7B515C68FA99D0426A32111CA493337E7C55280A90F697 -Test: Encrypt -Comment: Set 3, vector 96 -Key: 60606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060 -Plaintext: 6060606060606060606060606060606060606060606060606060606060606060 -Ciphertext: 8EE711FB281CBAA99917C85F0623B68E2EDAFEFCC3B1B841883D71BA6683568A -Test: Encrypt -Comment: Set 3, vector 97 -Key: 61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 -Plaintext: 6161616161616161616161616161616161616161616161616161616161616161 -Ciphertext: EC29DAE53DB4475F8900311F425FE60CB834A82F2A6A2DB4810F95F4D6991B84 -Test: Encrypt -Comment: Set 3, vector 98 -Key: 62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262 -Plaintext: 6262626262626262626262626262626262626262626262626262626262626262 -Ciphertext: 91E58DDE741553572B5D6F3DAD25953906424FF217497226746A25C0CE1C7D0F -Test: Encrypt -Comment: Set 3, vector 99 -Key: 63636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363 -Plaintext: 6363636363636363636363636363636363636363636363636363636363636363 -Ciphertext: B6EC4D9421AB011D4EEDBC32B289E45AC44CAEB1DC5FAEA752DFFA0137325067 -Test: Encrypt -Comment: Set 3, vector 100 -Key: 64646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464 -Plaintext: 6464646464646464646464646464646464646464646464646464646464646464 -Ciphertext: D9CB13EA06CADF09AC446F9B09553FFE3BF4F1152997B171C03E609D4BD60ADB -Test: Encrypt -Comment: Set 3, vector 101 -Key: 65656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565 -Plaintext: 6565656565656565656565656565656565656565656565656565656565656565 -Ciphertext: 2D07CA161326ED154D9E3FF650963557EC369A91ABB0D49FC1F32AEF39A3B12E -Test: Encrypt -Comment: Set 3, vector 102 -Key: 66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666 -Plaintext: 6666666666666666666666666666666666666666666666666666666666666666 -Ciphertext: 28E8B606EE621D2C5B865B8208C7BD40C3596931CE3FF8FA5AD7EB8EE4480E95 -Test: Encrypt -Comment: Set 3, vector 103 -Key: 67676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767 -Plaintext: 6767676767676767676767676767676767676767676767676767676767676767 -Ciphertext: 9B9B3A23DA29539DA1E9BAA20449750EC192CE14A5063E1A2FFAF5039A665754 -Test: Encrypt -Comment: Set 3, vector 104 -Key: 68686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868 -Plaintext: 6868686868686868686868686868686868686868686868686868686868686868 -Ciphertext: D770E305A9C2D257759D8AE9E70C408D1CB090F976BBAFF3A56730A78BA8BF4F -Test: Encrypt -Comment: Set 3, vector 105 -Key: 69696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969 -Plaintext: 6969696969696969696969696969696969696969696969696969696969696969 -Ciphertext: 453988B10DFD852D1AFD11E96C50024571CCB0F19E7C3C4981F8B8BDCD11F720 -Test: Encrypt -Comment: Set 3, vector 106 -Key: 6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A -Plaintext: 6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A -Ciphertext: 17DFD98CB5C24610DD631C4E2749A679D68F854F21AABE8BF67605A256452AD8 -Test: Encrypt -Comment: Set 3, vector 107 -Key: 6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B -Plaintext: 6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B -Ciphertext: DA260145EC80E19C18685540AC71FA460DD4427168E37BC6E0F967D90C306FBB -Test: Encrypt -Comment: Set 3, vector 108 -Key: 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C -Plaintext: 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C -Ciphertext: 2AC246E2E384ECCC4BC69CE82EDB51C05DD864642F1E9A572DA6043DD1D56DF0 -Test: Encrypt -Comment: Set 3, vector 109 -Key: 6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D -Plaintext: 6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D -Ciphertext: D1A06B820071CC4122F0B0797A294F31922E26703CDEF15A6D8F511CDBD8BD3F -Test: Encrypt -Comment: Set 3, vector 110 -Key: 6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E -Plaintext: 6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E -Ciphertext: C8D23274A1FF6AEBDF0BA70FBA7A895277B1CC8040F8FB2814195E3A7E85BD01 -Test: Encrypt -Comment: Set 3, vector 111 -Key: 6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F -Plaintext: 6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F -Ciphertext: E0133DC7960953BABC7BFBA52E88DCF86EBD979D6D63EB19466EEADEDEDEEBB3 -Test: Encrypt -Comment: Set 3, vector 112 -Key: 70707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070 -Plaintext: 7070707070707070707070707070707070707070707070707070707070707070 -Ciphertext: A1A9527766EE54D566D97E7A0763A5AECE86F2816411AC2066439D6BDF02FEA7 -Test: Encrypt -Comment: Set 3, vector 113 -Key: 71717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171 -Plaintext: 7171717171717171717171717171717171717171717171717171717171717171 -Ciphertext: E1833EF5C2BA2EF192642164F0F2C02A7334EF5AEA37E9DD56D17AE6CB031004 -Test: Encrypt -Comment: Set 3, vector 114 -Key: 72727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272 -Plaintext: 7272727272727272727272727272727272727272727272727272727272727272 -Ciphertext: DD2CC0EECAA7E5364376FA73E12C64A0C42FB9FC7E94EFF0B22A051D6EDFE905 -Test: Encrypt -Comment: Set 3, vector 115 -Key: 73737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373 -Plaintext: 7373737373737373737373737373737373737373737373737373737373737373 -Ciphertext: 9A72F15B911E6A50A32EEEDF83B62B628E37ED403085180571DEBEA2F37CF49F -Test: Encrypt -Comment: Set 3, vector 116 -Key: 74747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474 -Plaintext: 7474747474747474747474747474747474747474747474747474747474747474 -Ciphertext: CD83CE7861EE8259A9C29BC3870EA1BF629ECD31F2E18F0BC12221F239207457 -Test: Encrypt -Comment: Set 3, vector 117 -Key: 75757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575 -Plaintext: 7575757575757575757575757575757575757575757575757575757575757575 -Ciphertext: 7B4218C5AEA4EEFE17E2AB110D8B63A947F21D5210162F6283EDDF00900CEE27 -Test: Encrypt -Comment: Set 3, vector 118 -Key: 76767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676 -Plaintext: 7676767676767676767676767676767676767676767676767676767676767676 -Ciphertext: 935DE2010B112937A233E7CB1023FB9D3C46D7C688A478A94F86AD3919FD2728 -Test: Encrypt -Comment: Set 3, vector 119 -Key: 77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777 -Plaintext: 7777777777777777777777777777777777777777777777777777777777777777 -Ciphertext: 416A91A68A520732E672ACB5A36599D9A99901F013CC460D9C2FB16AAB45996E -Test: Encrypt -Comment: Set 3, vector 120 -Key: 78787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878 -Plaintext: 7878787878787878787878787878787878787878787878787878787878787878 -Ciphertext: FD066F9C65CD3D61B43F5DA44F7B94C85541DC5E09D52B044DA963699C39FDA0 -Test: Encrypt -Comment: Set 3, vector 121 -Key: 79797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979 -Plaintext: 7979797979797979797979797979797979797979797979797979797979797979 -Ciphertext: 63937A7953E453B6E48539FACBD1BC489E03D209DB188837C5A09BA458FFFB92 -Test: Encrypt -Comment: Set 3, vector 122 -Key: 7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A -Plaintext: 7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A -Ciphertext: 68F9EA0F87112633611052A45BBF32B7069079EDB16A928CD2AA16BE464178E3 -Test: Encrypt -Comment: Set 3, vector 123 -Key: 7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B -Plaintext: 7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B -Ciphertext: 874D5ED6C8052C3B4AB830626A195F508DDA15388BA75B3D957B26BC134C9B30 -Test: Encrypt -Comment: Set 3, vector 124 -Key: 7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C -Plaintext: 7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C -Ciphertext: EC3EA8DC433E39B85E4C4D68AC6A854A1B943D99EB2E9A018EA27DC1874CA867 -Test: Encrypt -Comment: Set 3, vector 125 -Key: 7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D -Plaintext: 7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D -Ciphertext: 9CE2298362F1F234A73BECA011EC31B4BC7E143D87B4F118CDADE6AB8D1ED783 -Test: Encrypt -Comment: Set 3, vector 126 -Key: 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E -Plaintext: 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E -Ciphertext: 27973D9B510ED9C612CC770FC1AE25EE21B1A9616CB64617EDA477939BE98D04 -Test: Encrypt -Comment: Set 3, vector 127 -Key: 7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F -Plaintext: 7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F -Ciphertext: 82A0EB8C058E727EBD6032F0F77EE693342C97BD44E9538032652B1CA10403DE -Test: Encrypt -Comment: Set 3, vector 128 -Key: 80808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080 -Plaintext: 8080808080808080808080808080808080808080808080808080808080808080 -Ciphertext: C3C1CD5F3060B3EC4E6ABC0818B68449E1750FB482368C8F3305270E16F98735 -Test: Encrypt -Comment: Set 3, vector 129 -Key: 81818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181 -Plaintext: 8181818181818181818181818181818181818181818181818181818181818181 -Ciphertext: 26381852C68B646D80E53C958855293BDC6FAAA85C5F9CAAACABE7B8077E4F7A -Test: Encrypt -Comment: Set 3, vector 130 -Key: 82828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282 -Plaintext: 8282828282828282828282828282828282828282828282828282828282828282 -Ciphertext: E2EA924898ED40FBD8C633706AD7D698392DF1EF33A10FDFCBE51B58C3AE0668 -Test: Encrypt -Comment: Set 3, vector 131 -Key: 83838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383 -Plaintext: 8383838383838383838383838383838383838383838383838383838383838383 -Ciphertext: 15CBDDA36707819D0C7694AAD46B2345BDEFC9D4F26F03A4BF860CE46F7BB53A -Test: Encrypt -Comment: Set 3, vector 132 -Key: 84848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484 -Plaintext: 8484848484848484848484848484848484848484848484848484848484848484 -Ciphertext: F96318A42737AB884FAA82BBB7025063E9A25C5957F52A7342E0C03A1A64273C -Test: Encrypt -Comment: Set 3, vector 133 -Key: 85858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585 -Plaintext: 8585858585858585858585858585858585858585858585858585858585858585 -Ciphertext: 7813FEB148D103075C80ACDFC95E2437A560D9B2E6C910E3A59805338E498907 -Test: Encrypt -Comment: Set 3, vector 134 -Key: 86868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686 -Plaintext: 8686868686868686868686868686868686868686868686868686868686868686 -Ciphertext: C7E9D5FE3BA11096AB77E715DFF0D2EB67E9136F0393CD004A7E994B3F994FA4 -Test: Encrypt -Comment: Set 3, vector 135 -Key: 87878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787 -Plaintext: 8787878787878787878787878787878787878787878787878787878787878787 -Ciphertext: F7D2DD8DF86A0E985CF6E83AA5922A548C83856D88C2C9D49EA962C9E6497949 -Test: Encrypt -Comment: Set 3, vector 136 -Key: 88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 -Plaintext: 8888888888888888888888888888888888888888888888888888888888888888 -Ciphertext: C64887C6573E3D7F286C0353188FC93F05321C0C949ACDCB0237725576BCF77B -Test: Encrypt -Comment: Set 3, vector 137 -Key: 89898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989 -Plaintext: 8989898989898989898989898989898989898989898989898989898989898989 -Ciphertext: 77FB97C9C953BE6BD58044FB1E095BB5E3F4B3A51DAFE6F2F7ADED0FB707921F -Test: Encrypt -Comment: Set 3, vector 138 -Key: 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A -Plaintext: 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A -Ciphertext: 22DE5F20955357BA1BF70E4D6DA436CCDE28C228031E4A413882C918EF8082D1 -Test: Encrypt -Comment: Set 3, vector 139 -Key: 8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B -Plaintext: 8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B -Ciphertext: 146FF5907A3C58593C3FD3EB7498C4426CCE04DD0DA9138954BB97AAC821D87F -Test: Encrypt -Comment: Set 3, vector 140 -Key: 8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C -Plaintext: 8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C -Ciphertext: 474ADC5855C87504A7C859409E25154D94B05A925F1D9989AE653B5511710BD7 -Test: Encrypt -Comment: Set 3, vector 141 -Key: 8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D -Plaintext: 8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D -Ciphertext: 959B1090C1FF59998C100814E95E40EF94C6F2B7ED0425C78391192CFFFFA465 -Test: Encrypt -Comment: Set 3, vector 142 -Key: 8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E -Plaintext: 8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E -Ciphertext: 9DA473108FFCECB228F8809860CDA316F4E1FAC5ADC39BB0373F01DCEBCBF271 -Test: Encrypt -Comment: Set 3, vector 143 -Key: 8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F -Plaintext: 8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F -Ciphertext: 905FD0302F9F3C4296E15F94EDD72A8F9F4E9E4068F068099CAAE7247235847E -Test: Encrypt -Comment: Set 3, vector 144 -Key: 90909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090 -Plaintext: 9090909090909090909090909090909090909090909090909090909090909090 -Ciphertext: B63B82FB4B4961E4800FD13CAF145BEBF3625822AF7F5D3ACF2A4506471C636D -Test: Encrypt -Comment: Set 3, vector 145 -Key: 91919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191 -Plaintext: 9191919191919191919191919191919191919191919191919191919191919191 -Ciphertext: 63AA9822C7A5A6777D03F901E3BAF91FD566553C88835EF06DB9A983212288BF -Test: Encrypt -Comment: Set 3, vector 146 -Key: 92929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292 -Plaintext: 9292929292929292929292929292929292929292929292929292929292929292 -Ciphertext: 5417F10E4028BDE0F741114632E2090A1E6C83ACB1D03EA98D18D003838B4F0A -Test: Encrypt -Comment: Set 3, vector 147 -Key: 93939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393 -Plaintext: 9393939393939393939393939393939393939393939393939393939393939393 -Ciphertext: FD2C478FB17EE8520149E8A242BB07E0B32929536B191AC6DBCE05891C5E4BFC -Test: Encrypt -Comment: Set 3, vector 148 -Key: 94949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494 -Plaintext: 9494949494949494949494949494949494949494949494949494949494949494 -Ciphertext: 6A36A092BC0F029B60D40440F141EF0DC21A241547359FB618E9243C39AE3D7C -Test: Encrypt -Comment: Set 3, vector 149 -Key: 95959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595 -Plaintext: 9595959595959595959595959595959595959595959595959595959595959595 -Ciphertext: 605BC400A0FEE12092D369142E4D20C3A4F3D7623254BF9E242766946FC47ED1 -Test: Encrypt -Comment: Set 3, vector 150 -Key: 96969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696 -Plaintext: 9696969696969696969696969696969696969696969696969696969696969696 -Ciphertext: 6A5FA33652F946D7C93A56D15B5D3807401C667A9757495341F78526D58659D2 -Test: Encrypt -Comment: Set 3, vector 151 -Key: 97979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797 -Plaintext: 9797979797979797979797979797979797979797979797979797979797979797 -Ciphertext: 5C6AC175B74B9F7F7D6371A90B1F35E1276628DF6A82B0ECE38590C88B7B8DCA -Test: Encrypt -Comment: Set 3, vector 152 -Key: 98989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898 -Plaintext: 9898989898989898989898989898989898989898989898989898989898989898 -Ciphertext: 67BB4E7818FBE6CFAB113C1B2EC797E3164432BFF708450312422D5AEC70A8A8 -Test: Encrypt -Comment: Set 3, vector 153 -Key: 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 -Plaintext: 9999999999999999999999999999999999999999999999999999999999999999 -Ciphertext: BFDA13CA82E73FBF62B6F1BB7181916CE7FD7DC7608EB958A8246346DFBB04E9 -Test: Encrypt -Comment: Set 3, vector 154 -Key: 9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A -Plaintext: 9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A -Ciphertext: C30F3EF137BF7718F76C7E4D2366A48E7C3CE53735BBF8B56CD51609A23AC06C -Test: Encrypt -Comment: Set 3, vector 155 -Key: 9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B -Plaintext: 9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B -Ciphertext: D73795A681B4FBE858703C15D60299682F64C800E691D223C4BE51012DA4D3DA -Test: Encrypt -Comment: Set 3, vector 156 -Key: 9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C -Plaintext: 9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C -Ciphertext: 885A096C820E01E48E1A5F75DB0A007C2A96B66FCAB38AE80CF92DD8B6A35F6F -Test: Encrypt -Comment: Set 3, vector 157 -Key: 9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D -Plaintext: 9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D -Ciphertext: 8FBDD4939C31026305C575F1FDCED3DBAE320C56CF064E9F19B44A43898BFD5C -Test: Encrypt -Comment: Set 3, vector 158 -Key: 9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E -Plaintext: 9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E -Ciphertext: 2D9EC00B081BC1512EC11A0B8B898639415AEEA3270C4B49E4B47C601AB85875 -Test: Encrypt -Comment: Set 3, vector 159 -Key: 9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F -Plaintext: 9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F -Ciphertext: 59565FB9888519C77E9C4E86D72AD86205AB55488D5ED0B9A388FB2D301C4400 -Test: Encrypt -Comment: Set 3, vector 160 -Key: A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0 -Plaintext: A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0 -Ciphertext: 32D6CAA3D5E0A5D3CCD0FD8F2105CFF662FC4052FE348C2DFD0BC3EEFF3AB700 -Test: Encrypt -Comment: Set 3, vector 161 -Key: A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1 -Plaintext: A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1 -Ciphertext: 7C3276EA6BB6FDDDEC8B901C45978B7D4D34AACE9F2D02F7D7F5826A89809DE9 -Test: Encrypt -Comment: Set 3, vector 162 -Key: A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 -Plaintext: A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 -Ciphertext: C5ABC33559D828DD1464264F94D46A8519B4CE47EAA0EC9BF0504C876AC85451 -Test: Encrypt -Comment: Set 3, vector 163 -Key: A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3 -Plaintext: A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3 -Ciphertext: E63050ADB9F2789F91A192E089883D7346DD42DE4C654E1D4B72C77D6C09FDB0 -Test: Encrypt -Comment: Set 3, vector 164 -Key: A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4 -Plaintext: A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4 -Ciphertext: E7C58AF118E1DFD2A279DE640EDEF02FB4F3C78D778D145ECC6B2C4CCD065229 -Test: Encrypt -Comment: Set 3, vector 165 -Key: A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5 -Plaintext: A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5 -Ciphertext: 278D8C11ACFDB851131432B3E19C409F940F93E0F6CB49D076C62E70B9C27095 -Test: Encrypt -Comment: Set 3, vector 166 -Key: A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6 -Plaintext: A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6 -Ciphertext: D4839B5679FCA83189BB8C3681E83BAC871A02F297578855034E915F4EF04C12 -Test: Encrypt -Comment: Set 3, vector 167 -Key: A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7 -Plaintext: A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7 -Ciphertext: 91AFF6474168F1D113E3DC66E620CF2F7283CE84F5FDDECC7E79CC005859C1BA -Test: Encrypt -Comment: Set 3, vector 168 -Key: A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8 -Plaintext: A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8 -Ciphertext: 1374026DD442B1C1E0BA34570240F6A9E99781C8307A1544A9D3C91857C7E6E1 -Test: Encrypt -Comment: Set 3, vector 169 -Key: A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9 -Plaintext: A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9 -Ciphertext: C95E8163D47755E25E8A4BA1FDFF46E016F080F13A794FD21251CE238F28C52E -Test: Encrypt -Comment: Set 3, vector 170 -Key: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -Plaintext: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -Ciphertext: 5DA751854BEEDB19D767A09E2BD9C12D15E51A4409A1F70574496D0A0DA767F9 -Test: Encrypt -Comment: Set 3, vector 171 -Key: ABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB -Plaintext: ABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB -Ciphertext: C1A0ADDB98DA358D8F40CDB8FA427770D6BD5705D81A804A9BA27FFAE8790BD1 -Test: Encrypt -Comment: Set 3, vector 172 -Key: ACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACAC -Plaintext: ACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACAC -Ciphertext: 604830D513CB29E0E89A36EAB97FFDFC0855AE212F9DDAB62ABE7572CBCEBFC5 -Test: Encrypt -Comment: Set 3, vector 173 -Key: ADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADAD -Plaintext: ADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADAD -Ciphertext: 0DB5075E0B9727D439ED88030D31B532B61556D206220CAE70A7B42EE4C5F72E -Test: Encrypt -Comment: Set 3, vector 174 -Key: AEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAE -Plaintext: AEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAE -Ciphertext: A5167DC20ED3B1894B10C6AA754FDCF9FC1418439D9CA80C40974E9CB7630A12 -Test: Encrypt -Comment: Set 3, vector 175 -Key: AFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAF -Plaintext: AFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAF -Ciphertext: 1A90CCEA061A2FB58E4D1F363B6CEEC26BFB55F4F140A18991C8EF50E8DFB306 -Test: Encrypt -Comment: Set 3, vector 176 -Key: B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0 -Plaintext: B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0 -Ciphertext: 5CED17D75543C21AA1E020D4B084DB86A77BC445C7E77DA54DC6D786A0976A09 -Test: Encrypt -Comment: Set 3, vector 177 -Key: B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1 -Plaintext: B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1 -Ciphertext: BB28F1F9496ED578276F99F3A2D4657566DC2CDDDCF00AE44555DA614C64E54E -Test: Encrypt -Comment: Set 3, vector 178 -Key: B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2 -Plaintext: B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2 -Ciphertext: 30C28BF86BEAEBB25F4A667FB2B9C183B85B456527EB49B44AA4EA825A44E026 -Test: Encrypt -Comment: Set 3, vector 179 -Key: B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3 -Plaintext: B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3 -Ciphertext: C2B0DEB4BC6C28869675FB75D2C2081396601B1FA823185D2D9EDE0730BBEAEA -Test: Encrypt -Comment: Set 3, vector 180 -Key: B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 -Plaintext: B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 -Ciphertext: B3EDC667C3FD03CE50D05877C8A78C330F809DF5F8F7FB11968A3664C77CA78B -Test: Encrypt -Comment: Set 3, vector 181 -Key: B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5 -Plaintext: B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5 -Ciphertext: BC2FCF90C52B883CAC3F0A673FA093EEB48952F4DE50A9288464B84A920A1316 -Test: Encrypt -Comment: Set 3, vector 182 -Key: B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6 -Plaintext: B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6 -Ciphertext: 30BCF4063A59823CE94B14B6B65F1B4DBEED8FB30832765B5186F4B834DBEA89 -Test: Encrypt -Comment: Set 3, vector 183 -Key: B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7 -Plaintext: B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7 -Ciphertext: 51B4C7E8F697FACC24294A2CEB404C4BEC0CA41C76A6B50A824800EA4464C796 -Test: Encrypt -Comment: Set 3, vector 184 -Key: B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8 -Plaintext: B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8 -Ciphertext: 2CCFF61604C0881CCC6A69B885878D6D07CEA7DAB31719D89DC4ECB0063DF5D2 -Test: Encrypt -Comment: Set 3, vector 185 -Key: B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9 -Plaintext: B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9 -Ciphertext: 87998D9F16DC018B5DBD42A2E0C26D3774C2A41986E2D0A1504CE37B6EE71688 -Test: Encrypt -Comment: Set 3, vector 186 -Key: BABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABA -Plaintext: BABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABA -Ciphertext: D774451BB82A62A4C7708D0194F6C129C483CEFD182BAADF5A35EB77892F317A -Test: Encrypt -Comment: Set 3, vector 187 -Key: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB -Plaintext: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB -Ciphertext: B88CE3DF52572A1A1C8253E05D789BBF204E2CFC7A00389429F4C6B428EF8CD6 -Test: Encrypt -Comment: Set 3, vector 188 -Key: BCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC -Plaintext: BCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC -Ciphertext: B854E538E6674A1831F635AA6650A0A4D0730A9A4B12511509EFD49E34D57D62 -Test: Encrypt -Comment: Set 3, vector 189 -Key: BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD -Plaintext: BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD -Ciphertext: A69EF2348FEEF1EA09A2B29A6D977092ECD522A62EE906FA47624C92A872EB17 -Test: Encrypt -Comment: Set 3, vector 190 -Key: BEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBE -Plaintext: BEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBE -Ciphertext: A1AE0CBC3B5200F1D8AE165EE42D45F6CE8C4FF448F8127B6D9AB4936FC76CA8 -Test: Encrypt -Comment: Set 3, vector 191 -Key: BFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBF -Plaintext: BFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBF -Ciphertext: 91948E36B83E21FF8A5EEDAA48E50E3A292A3B68D20657FA7E11F50BC7A12205 -Test: Encrypt -Comment: Set 3, vector 192 -Key: C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0 -Plaintext: C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0 -Ciphertext: 56CD17219224C3103E3E3E5CABAB6C1E78DEA9AD27613E8D62901FFA31500BFF -Test: Encrypt -Comment: Set 3, vector 193 -Key: C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1 -Plaintext: C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1 -Ciphertext: 2E8FE5CAB2448B194387B160E9141E7D1B879BA1580B3D393B55436608EA2735 -Test: Encrypt -Comment: Set 3, vector 194 -Key: C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2 -Plaintext: C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2 -Ciphertext: 5DD74E1155DD90840C702145DF6912754FB74B47625EA4C5382326681DB3390E -Test: Encrypt -Comment: Set 3, vector 195 -Key: C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3 -Plaintext: C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3 -Ciphertext: 3A9F5962554037DCB1FA2AD04BFC0BF79699941500D5F9841320C6D8601310A2 -Test: Encrypt -Comment: Set 3, vector 196 -Key: C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4 -Plaintext: C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4 -Ciphertext: BB0F5B68087BBA51DBB700BA1860CC3D0A587E54D57F4014DE4E48E58E529F87 -Test: Encrypt -Comment: Set 3, vector 197 -Key: C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5 -Plaintext: C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5 -Ciphertext: 8384025D801AB8EC4D4416F5B7E862B6D9AC9E4AEE334C35FD0296B1402E4975 -Test: Encrypt -Comment: Set 3, vector 198 -Key: C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 -Plaintext: C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 -Ciphertext: BE3057511C5D0E51315D89671BB4E57E7B590EC3ECE8A14D728248ED8F5107BB -Test: Encrypt -Comment: Set 3, vector 199 -Key: C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7 -Plaintext: C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7 -Ciphertext: 18882618837D15B0B6BD77E1F37470EC58155A2788BDD9D91AEBD16B29A92A1B -Test: Encrypt -Comment: Set 3, vector 200 -Key: C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8 -Plaintext: C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8 -Ciphertext: 8FAFDDC7E04C1AF3BBE8428222DCA59D2EF8C9E0213430492ECAB7B414987FEF -Test: Encrypt -Comment: Set 3, vector 201 -Key: C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9 -Plaintext: C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9 -Ciphertext: 4D687992D4F9F515FE451AC967CBF75F906D637C3C261758E263A0DA0DEF69C2 -Test: Encrypt -Comment: Set 3, vector 202 -Key: CACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACA -Plaintext: CACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACA -Ciphertext: 9DDC94BFF87FDBAFDB0AB9DC17D3649231300E5E6270600856722324DC9CA39A -Test: Encrypt -Comment: Set 3, vector 203 -Key: CBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCB -Plaintext: CBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCB -Ciphertext: 86E9CCD90D7B902D23D82C085B1F886402DBD2D19C5A81A32F318C98C6E2A98A -Test: Encrypt -Comment: Set 3, vector 204 -Key: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC -Plaintext: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC -Ciphertext: 164FCD7D1FFE12FF1FDEE6384145EF546A5CD98C22817A5205FF2C2E18339779 -Test: Encrypt -Comment: Set 3, vector 205 -Key: CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD -Plaintext: CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD -Ciphertext: 4579935A483BAC6B4CCD8C25BCC9E6DEAF46EA8B53F8B5E37CC436EAB85A1330 -Test: Encrypt -Comment: Set 3, vector 206 -Key: CECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECE -Plaintext: CECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECE -Ciphertext: E5F810DF5B215F559E76EF925F2B795915A7B03A6F7019FAC8E9127A7CE93F09 -Test: Encrypt -Comment: Set 3, vector 207 -Key: CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF -Plaintext: CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF -Ciphertext: 2EA0892E2B2F29A63526B37DECD18E31DC970A60E60A4D8414A5BD0D2D5491EF -Test: Encrypt -Comment: Set 3, vector 208 -Key: D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0 -Plaintext: D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0 -Ciphertext: 900F155E80A716199EB062827CDDDC4DA857550BA1C265A46D47BE4024706F40 -Test: Encrypt -Comment: Set 3, vector 209 -Key: D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1 -Plaintext: D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1 -Ciphertext: 5B495546838A97D8DF4B9CA95EF8350210A3ECAB81469678EBDE1E5846C1F42D -Test: Encrypt -Comment: Set 3, vector 210 -Key: D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2 -Plaintext: D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2 -Ciphertext: 60E7E367347BC3F4091CE34CCA288C8AFC6375ED8F4394D904FD8489280D50F1 -Test: Encrypt -Comment: Set 3, vector 211 -Key: D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3 -Plaintext: D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3 -Ciphertext: F215EED91D35B7BA649F05C3D1E2B254CB1215588AB78DF54F3CA221AB4A3F1B -Test: Encrypt -Comment: Set 3, vector 212 -Key: D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4 -Plaintext: D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4 -Ciphertext: 6441A445D808842C6185B81ACBC5AF86386C54C79026BFC21C1DB5111362AA15 -Test: Encrypt -Comment: Set 3, vector 213 -Key: D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5 -Plaintext: D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5 -Ciphertext: 4EE459EDAC1FE0CB08E80C8C13FCE8C44CBFECF7A7F9F14C15B5A92BB7F34E71 -Test: Encrypt -Comment: Set 3, vector 214 -Key: D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6 -Plaintext: D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6 -Ciphertext: 78826499B0F2F402E6DA3CACA36EA35492B7BD2A4D84575D0432E16368E78808 -Test: Encrypt -Comment: Set 3, vector 215 -Key: D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7 -Plaintext: D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7 -Ciphertext: BDFBCAE2761BEF6A411156AE01A63F9321EE969C56043F2A44C5D3D4BB017BC0 -Test: Encrypt -Comment: Set 3, vector 216 -Key: D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 -Plaintext: D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 -Ciphertext: 926F2CD84035F9070C3506E6D7245FEA9A845F2D355785BB17E1D3C34FA81228 -Test: Encrypt -Comment: Set 3, vector 217 -Key: D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9 -Plaintext: D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9 -Ciphertext: 6C5F6B1C746967142D55FA3769A9417D5A44875D364DB4412B4F9EB254D9BB89 -Test: Encrypt -Comment: Set 3, vector 218 -Key: DADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADA -Plaintext: DADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADA -Ciphertext: 8329A1E54D9F45DB4E8CE6F1B481C3EE00D5511B52B3CDADCBD562A9F1B35770 -Test: Encrypt -Comment: Set 3, vector 219 -Key: DBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDB -Plaintext: DBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDB -Ciphertext: 7A7FEEDEF1950F1A60529743163406CAF167097358377E0650CF0BB35CD783F6 -Test: Encrypt -Comment: Set 3, vector 220 -Key: DCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDC -Plaintext: DCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDC -Ciphertext: C52CFB15D2F53156701AE4951AA46BCFC872252447BB14E1CE19CAC074926984 -Test: Encrypt -Comment: Set 3, vector 221 -Key: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD -Plaintext: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD -Ciphertext: 79DFF8DC12ABCEC71E7FAE55ABC8C374135ECE2D52834BC77B860252B756D54A -Test: Encrypt -Comment: Set 3, vector 222 -Key: DEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDE -Plaintext: DEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDE -Ciphertext: 62963B66E680BD5602EC86DB7267E15CB1FF6EA698B54EBA661D125400C7F2DD -Test: Encrypt -Comment: Set 3, vector 223 -Key: DFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDF -Plaintext: DFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDF -Ciphertext: 0C2E76743ACC9CC0525D6E2C519D12C369CFA9E27F13068F98D2F32FAD7220CB -Test: Encrypt -Comment: Set 3, vector 224 -Key: E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0 -Plaintext: E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0 -Ciphertext: B464640E72C30DF092A5BB00F34568A7C04B8620265EDA53F19F3A06164AF980 -Test: Encrypt -Comment: Set 3, vector 225 -Key: E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 -Plaintext: E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 -Ciphertext: 3725215E79F1FE3DC64B4316449FF98EB52D03330BFC848CD83A407475AADA3A -Test: Encrypt -Comment: Set 3, vector 226 -Key: E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2 -Plaintext: E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2 -Ciphertext: BA273F544C5076D523CC75F90E315A39E465D2B25434E6577FE629F27061BBA4 -Test: Encrypt -Comment: Set 3, vector 227 -Key: E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3 -Plaintext: E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3 -Ciphertext: 472161A0F42E64BD0FE6D448996C370E2C3A56BDE16B378EAA31740551121B4E -Test: Encrypt -Comment: Set 3, vector 228 -Key: E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4 -Plaintext: E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4 -Ciphertext: EA089A10A597504D057E1F03064C9465C1A707C9472A7C0DBAD6978F5BB83A46 -Test: Encrypt -Comment: Set 3, vector 229 -Key: E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5 -Plaintext: E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5 -Ciphertext: E91B3433426F88FA31A05E17906E55EA1D803ADFE080C51FBD98290CBF427BEF -Test: Encrypt -Comment: Set 3, vector 230 -Key: E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6 -Plaintext: E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6 -Ciphertext: 747C4999D0256384349A5FB132DE1AAD4D7FC48507FEC206B80ED429AF7FDBDB -Test: Encrypt -Comment: Set 3, vector 231 -Key: E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7 -Plaintext: E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7 -Ciphertext: 3F8058A1A9B7B0A9C31B4670EEAA6988BF2D41E9B3417EF899EF12CBBC9C77DE -Test: Encrypt -Comment: Set 3, vector 232 -Key: E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8 -Plaintext: E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8 -Ciphertext: 9DA431EC0DADDEC4A76B3830B20AA03D346AD09691FB98FC0E9A8987F7B70EDF -Test: Encrypt -Comment: Set 3, vector 233 -Key: E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9 -Plaintext: E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9 -Ciphertext: 63BF528E184A43EF807DC9169BDB9CD7B63EE144478A4735EC2EE3A5A7EE460A -Test: Encrypt -Comment: Set 3, vector 234 -Key: EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA -Plaintext: EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA -Ciphertext: 73DC5F8AFA9493AD7767D15A36E7741044EFC225136B4972DC5294E80071A64D -Test: Encrypt -Comment: Set 3, vector 235 -Key: EBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEB -Plaintext: EBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEB -Ciphertext: 7EEE75D690458A604D20CD21ED64B228F0C3563DB8FB925341FC02845B6E06BA -Test: Encrypt -Comment: Set 3, vector 236 -Key: ECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECEC -Plaintext: ECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECEC -Ciphertext: AA4D9E1A0157AC347DC7A1997718944427BD579DC18B94F181390E8C36A1305C -Test: Encrypt -Comment: Set 3, vector 237 -Key: EDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDED -Plaintext: EDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDED -Ciphertext: 1695BC5C3D63F4B0E0BC3225F00BB0B8E8D29F3DC09584353E11510002E2BE53 -Test: Encrypt -Comment: Set 3, vector 238 -Key: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE -Plaintext: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE -Ciphertext: C68C7A2FBDA419A515AE816480490BFB2A72A4B6534A19A8D8C6C85FAA949567 -Test: Encrypt -Comment: Set 3, vector 239 -Key: EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF -Plaintext: EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF -Ciphertext: 5F45E7F72A64C66269F83714A88A0701561C3E7AF33BB48887D4439F5DE4A82D -Test: Encrypt -Comment: Set 3, vector 240 -Key: F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -Plaintext: F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 -Ciphertext: AD49A5C8EB06256147F02301FB47710E915B5A8FC3219C0D56A19382977119FC -Test: Encrypt -Comment: Set 3, vector 241 -Key: F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1 -Plaintext: F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1 -Ciphertext: 2387AF70EE04E7F25277E81081B044EA24090D503CE8F64997BB610C762D8F6F -Test: Encrypt -Comment: Set 3, vector 242 -Key: F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2 -Plaintext: F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2 -Ciphertext: B5D496DD36BA0B47832C170A53760CE5E47B1FF5C28848F5F7A1827E94BC73CB -Test: Encrypt -Comment: Set 3, vector 243 -Key: F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 -Plaintext: F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 -Ciphertext: 77978F2EAB7E8B6B32C9293B83F51419785A0CD276276CB417ACA806A456A6AE -Test: Encrypt -Comment: Set 3, vector 244 -Key: F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4 -Plaintext: F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4 -Ciphertext: E3CBD41F80B27C9A684D7C7C27BBCA9FD59E5E81E93B7BC5BFDF66722EF68EEE -Test: Encrypt -Comment: Set 3, vector 245 -Key: F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5 -Plaintext: F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5 -Ciphertext: 4482F0C362CB423104CAA26E1415B0B7519E1189624D313E65D324C6DC95F516 -Test: Encrypt -Comment: Set 3, vector 246 -Key: F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6 -Plaintext: F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6 -Ciphertext: CD72EE9A6919348595286348C7E488DB3648458688F72BAD994B26FE6999E676 -Test: Encrypt -Comment: Set 3, vector 247 -Key: F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7 -Plaintext: F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7 -Ciphertext: 03EF38F91710AE8BCC8B9193F6A55A7C90C66300D20EDCF5B4946F3B38BEF6C5 -Test: Encrypt -Comment: Set 3, vector 248 -Key: F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8 -Plaintext: F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8 -Ciphertext: B67638D30578AB2319FE275D0B833B50D7ABF01E8760F566D0D441D8EAFDF8AA -Test: Encrypt -Comment: Set 3, vector 249 -Key: F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9 -Plaintext: F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9 -Ciphertext: 98B05FF6042436505C7163415E187E09F10C3B1A86FA4B458CE1EF31022F5D16 -Test: Encrypt -Comment: Set 3, vector 250 -Key: FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA -Plaintext: FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA -Ciphertext: B670A350A2CF0478412307EF00F97F8B30175CDB7593FF4686BD614B41444342 -Test: Encrypt -Comment: Set 3, vector 251 -Key: FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB -Plaintext: FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB -Ciphertext: D7FD492E6302265C24FAB910AA1335C29D53406147E853F7604F4AF1A9407E83 -Test: Encrypt -Comment: Set 3, vector 252 -Key: FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC -Plaintext: FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC -Ciphertext: 28926789363A4306E2C75FD1D8FDF0FE6B62FDB2AFAEDDA6F47A565C2781968B -Test: Encrypt -Comment: Set 3, vector 253 -Key: FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD -Plaintext: FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD -Ciphertext: 813C816CD4B18F20BD06E2E93CFAA717EBB6554B556CC33D67530608A9BF100F -Test: Encrypt -Comment: Set 3, vector 254 -Key: FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE -Plaintext: FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE -Ciphertext: 5DC15C83E7C4F5AAF8D8482ED1E443271B28B59288783DBCDDEC3544E3368A6E -Test: Encrypt -Comment: Set 3, vector 255 -Key: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -Plaintext: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -Ciphertext: 0598127BAF11706F77402000D730C54A0B84C868A98C6CA4D7F3C0FA06A78B7A -Test: Encrypt diff --git a/embeddedcryptopp/TestVectors/sosemanuk.txt b/embeddedcryptopp/TestVectors/sosemanuk.txt deleted file mode 100644 index 435d89b..0000000 --- a/embeddedcryptopp/TestVectors/sosemanuk.txt +++ /dev/null @@ -1,25 +0,0 @@ -AlgorithmType: SymmetricCipher -Source: Sosemanuk reference implementation, compiled with -DSOSEMANUK_VECTOR -Key: A7C083FEB7 -IV: 00112233445566778899AABBCCDDEEFF -Name: Sosemanuk -Plaintext: r160 00 -Ciphertext: \ - FE 81 D2 16 2C 9A 10 0D 04 89 5C 45 4A 77 51 5B\ - BE 6A 43 1A 93 5C B9 0E 22 21 EB B7 EF 50 23 28\ - 94 35 39 49 2E FF 63 10 C8 71 05 4C 28 89 CC 72\ - 8F 82 E8 6B 1A FF F4 33 4B 61 27 A1 3A 15 5C 75\ - 15 16 30 BD 48 2E B6 73 FF 5D B4 77 FA 6C 53 EB\ - E1 A4 EC 38 C2 3C 54 00 C3 15 45 5D 93 A2 AC ED\ - 95 98 60 47 27 FA 34 0D 5F 2A 8B D7 57 B7 78 33\ - F7 4B D2 BC 04 93 13 C8 06 16 B4 A0 62 68 AE 35\ - 0D B9 2E EC 4F A5 6C 17 13 74 A6 7A 80 C0 06 D0\ - EA D0 48 CE 7B 64 0F 17 D3 D5 A6 2D 1F 25 1C 21 -Test: Encrypt -Source: http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/sosemanuk/unverified.test-vectors?rev=189&view=auto -Comment: Set 6, vector# 3 -Key: 0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C -IV: 288FF65DC42B92F960C72E95FC63CA31 -Plaintext: r131072 00 -CiphertextXorDigest: CC09FB7405DD54BBF09407B1D2033FBBAC53F388DD387A46F2B8FCFF692A7838353523A621A55D08DA0CA5348AE96D8B0D6A028F309982EF6628054D01B9A368 -Test: EncryptXorDigest diff --git a/embeddedcryptopp/TestVectors/tea.txt b/embeddedcryptopp/TestVectors/tea.txt deleted file mode 100644 index dc46d3f..0000000 --- a/embeddedcryptopp/TestVectors/tea.txt +++ /dev/null @@ -1,711 +0,0 @@ -AlgorithmType: SymmetricCipher -Name: TEA/ECB -Source: http://www.cix.co.uk/~klockstone/teavect.htm -Comment: test 1 -Plaintext: 00000000 00000000 -Key: 00000000 00000000 00000000 00000000 -Ciphertext: 41ea3a0a 94baa940 -Test: Encrypt -Comment: test 2 -Plaintext: 94baa940 00000000 -Key: 00000000 00000000 00000000 41ea3a0a -Ciphertext: 4e8e7829 7d8236d8 -Test: Encrypt -Comment: test 3 -Plaintext: 7d8236d8 00000000 -Key: 00000000 00000000 41ea3a0a 4e8e7829 -Ciphertext: c88ba95e e7edac02 -Test: Encrypt -Comment: test 4 -Plaintext: e7edac02 00000000 -Key: 00000000 41ea3a0a 4e8e7829 c88ba95e -Ciphertext: b84e28af b6b62088 -Test: Encrypt -Comment: test 5 -Plaintext: b6b62088 00000000 -Key: 41ea3a0a 4e8e7829 c88ba95e b84e28af -Ciphertext: a0a47295 8fadf3b3 -Test: Encrypt -Comment: test 6 -Plaintext: 8fadf3b3 41ea3a0a -Key: 4e8e7829 c88ba95e b84e28af a0a47295 -Ciphertext: ed650698 cf9f2b79 -Test: Encrypt -Comment: test 7 -Plaintext: cf9f2b79 4e8e7829 -Key: c88ba95e b84e28af a0a47295 ed650698 -Ciphertext: 1024eea0 6220ae1c -Test: Encrypt -Comment: test 8 -Plaintext: 6220ae1c c88ba95e -Key: b84e28af a0a47295 ed650698 1024eea0 -Ciphertext: 5ddf75d9 7a4ce68f -Test: Encrypt -Comment: test 9 -Plaintext: 7a4ce68f b84e28af -Key: a0a47295 ed650698 1024eea0 5ddf75d9 -Ciphertext: f1be9d1e 8dd4a984 -Test: Encrypt -Comment: test 10 -Plaintext: 8dd4a984 a0a47295 -Key: ed650698 1024eea0 5ddf75d9 f1be9d1e -Ciphertext: d32c758c 092dabad -Test: Encrypt -Comment: test 11 -Plaintext: 092dabad ed650698 -Key: 1024eea0 5ddf75d9 f1be9d1e d32c758c -Ciphertext: bdb43728 f7183fc0 -Test: Encrypt -Comment: test 12 -Plaintext: f7183fc0 1024eea0 -Key: 5ddf75d9 f1be9d1e d32c758c bdb43728 -Ciphertext: a9c3801a d9dcfb4e -Test: Encrypt -Comment: test 13 -Plaintext: d9dcfb4e 5ddf75d9 -Key: f1be9d1e d32c758c bdb43728 a9c3801a -Ciphertext: 32a1e654 a9df917c -Test: Encrypt -Comment: test 14 -Plaintext: a9df917c f1be9d1e -Key: d32c758c bdb43728 a9c3801a 32a1e654 -Ciphertext: 08b63bb9 b20bd3e8 -Test: Encrypt -Comment: test 15 -Plaintext: b20bd3e8 d32c758c -Key: bdb43728 a9c3801a 32a1e654 08b63bb9 -Ciphertext: 21410574 cc4264c6 -Test: Encrypt -Comment: test 16 -Plaintext: cc4264c6 bdb43728 -Key: a9c3801a 32a1e654 08b63bb9 21410574 -Ciphertext: 4ec5d2e2 5ada1d89 -Test: Encrypt -Comment: test 17 -Plaintext: 5ada1d89 a9c3801a -Key: 32a1e654 08b63bb9 21410574 4ec5d2e2 -Ciphertext: dd46249e 28aa0b4b -Test: Encrypt -Comment: test 18 -Plaintext: 28aa0b4b 32a1e654 -Key: 08b63bb9 21410574 4ec5d2e2 dd46249e -Ciphertext: 2486dcba a713df03 -Test: Encrypt -Comment: test 19 -Plaintext: a713df03 08b63bb9 -Key: 21410574 4ec5d2e2 dd46249e 2486dcba -Ciphertext: b7c7af9d 1acb6cab -Test: Encrypt -Comment: test 20 -Plaintext: 1acb6cab 21410574 -Key: 4ec5d2e2 dd46249e 2486dcba b7c7af9d -Ciphertext: 8cc0400a 9aa49fbb -Test: Encrypt -Comment: test 21 -Plaintext: 9aa49fbb 4ec5d2e2 -Key: dd46249e 2486dcba b7c7af9d 8cc0400a -Ciphertext: 9c241876 6cbc8c66 -Test: Encrypt -Comment: test 22 -Plaintext: 6cbc8c66 dd46249e -Key: 2486dcba b7c7af9d 8cc0400a 9c241876 -Ciphertext: b59c5d45 a90066f9 -Test: Encrypt -Comment: test 23 -Plaintext: a90066f9 2486dcba -Key: b7c7af9d 8cc0400a 9c241876 b59c5d45 -Ciphertext: b765a1b3 64b37eb0 -Test: Encrypt -Comment: test 24 -Plaintext: 64b37eb0 b7c7af9d -Key: 8cc0400a 9c241876 b59c5d45 b765a1b3 -Ciphertext: 7b172fac f5ab4933 -Test: Encrypt -Comment: test 25 -Plaintext: f5ab4933 8cc0400a -Key: 9c241876 b59c5d45 b765a1b3 7b172fac -Ciphertext: fe48f4fb ada404b1 -Test: Encrypt -Comment: test 26 -Plaintext: ada404b1 9c241876 -Key: b59c5d45 b765a1b3 7b172fac fe48f4fb -Ciphertext: c5294093 c1d53e3d -Test: Encrypt -Comment: test 27 -Plaintext: c1d53e3d b59c5d45 -Key: b765a1b3 7b172fac fe48f4fb c5294093 -Ciphertext: 759ca8e2 77a96649 -Test: Encrypt -Comment: test 28 -Plaintext: 77a96649 b765a1b3 -Key: 7b172fac fe48f4fb c5294093 759ca8e2 -Ciphertext: 69c53e0f 3e979807 -Test: Encrypt -Comment: test 29 -Plaintext: 3e979807 7b172fac -Key: fe48f4fb c5294093 759ca8e2 69c53e0f -Ciphertext: 60388ada a21fa8e8 -Test: Encrypt -Comment: test 30 -Plaintext: a21fa8e8 fe48f4fb -Key: c5294093 759ca8e2 69c53e0f 60388ada -Ciphertext: df70a1f5 ac4aa407 -Test: Encrypt -Comment: test 31 -Plaintext: ac4aa407 c5294093 -Key: 759ca8e2 69c53e0f 60388ada df70a1f5 -Ciphertext: d9cb4e09 92636233 -Test: Encrypt -Comment: test 32 -Plaintext: 92636233 759ca8e2 -Key: 69c53e0f 60388ada df70a1f5 d9cb4e09 -Ciphertext: 7d2c6c57 7a6adb4d -Test: Encrypt -Comment: test 33 -Plaintext: 7a6adb4d 69c53e0f -Key: 60388ada df70a1f5 d9cb4e09 7d2c6c57 -Ciphertext: 44b71215 cf25368a -Test: Encrypt -Comment: test 34 -Plaintext: cf25368a 60388ada -Key: df70a1f5 d9cb4e09 7d2c6c57 44b71215 -Ciphertext: c10105a1 ef781a18 -Test: Encrypt -Comment: test 35 -Plaintext: ef781a18 df70a1f5 -Key: d9cb4e09 7d2c6c57 44b71215 c10105a1 -Ciphertext: bfdb29fa 9ece39b6 -Test: Encrypt -Comment: test 36 -Plaintext: 9ece39b6 d9cb4e09 -Key: 7d2c6c57 44b71215 c10105a1 bfdb29fa -Ciphertext: 9b0b256d dc04574c -Test: Encrypt -Comment: test 37 -Plaintext: dc04574c 7d2c6c57 -Key: 44b71215 c10105a1 bfdb29fa 9b0b256d -Ciphertext: f8295142 8c022711 -Test: Encrypt -Comment: test 38 -Plaintext: 8c022711 44b71215 -Key: c10105a1 bfdb29fa 9b0b256d f8295142 -Ciphertext: 61341d1c 3a85f2f0 -Test: Encrypt -Comment: test 39 -Plaintext: 3a85f2f0 c10105a1 -Key: bfdb29fa 9b0b256d f8295142 61341d1c -Ciphertext: f6a0d30c ad230209 -Test: Encrypt -Comment: test 40 -Plaintext: ad230209 bfdb29fa -Key: 9b0b256d f8295142 61341d1c f6a0d30c -Ciphertext: 3de21a3f aa0cf5c9 -Test: Encrypt -Comment: test 41 -Plaintext: aa0cf5c9 9b0b256d -Key: f8295142 61341d1c f6a0d30c 3de21a3f -Ciphertext: a7e307c6 bd52d939 -Test: Encrypt -Comment: test 42 -Plaintext: bd52d939 f8295142 -Key: 61341d1c f6a0d30c 3de21a3f a7e307c6 -Ciphertext: 017bc3a7 66fd8c77 -Test: Encrypt -Comment: test 43 -Plaintext: 66fd8c77 61341d1c -Key: f6a0d30c 3de21a3f a7e307c6 017bc3a7 -Ciphertext: d8f8fc86 d01b5761 -Test: Encrypt -Comment: test 44 -Plaintext: d01b5761 f6a0d30c -Key: 3de21a3f a7e307c6 017bc3a7 d8f8fc86 -Ciphertext: e186c41a 5e6e5a4d -Test: Encrypt -Comment: test 45 -Plaintext: 5e6e5a4d 3de21a3f -Key: a7e307c6 017bc3a7 d8f8fc86 e186c41a -Ciphertext: 4368d224 dbb4e677 -Test: Encrypt -Comment: test 46 -Plaintext: dbb4e677 a7e307c6 -Key: 017bc3a7 d8f8fc86 e186c41a 4368d224 -Ciphertext: 9bd0321e 84096523 -Test: Encrypt -Comment: test 47 -Plaintext: 84096523 017bc3a7 -Key: d8f8fc86 e186c41a 4368d224 9bd0321e -Ciphertext: b7c56d5b 97c65866 -Test: Encrypt -Comment: test 48 -Plaintext: 97c65866 d8f8fc86 -Key: e186c41a 4368d224 9bd0321e b7c56d5b -Ciphertext: 63a1bfac 5a5d7ca2 -Test: Encrypt -Comment: test 49 -Plaintext: 5a5d7ca2 e186c41a -Key: 4368d224 9bd0321e b7c56d5b 63a1bfac -Ciphertext: 91f56dff 7281794f -Test: Encrypt -Comment: test 50 -Plaintext: 7281794f 4368d224 -Key: 9bd0321e b7c56d5b 63a1bfac 91f56dff -Ciphertext: e4c63780 019aedf7 -Test: Encrypt -Comment: test 51 -Plaintext: 019aedf7 9bd0321e -Key: b7c56d5b 63a1bfac 91f56dff e4c63780 -Ciphertext: a9fb56e7 35f4aeca -Test: Encrypt -Comment: test 52 -Plaintext: 35f4aeca b7c56d5b -Key: 63a1bfac 91f56dff e4c63780 a9fb56e7 -Ciphertext: a6537187 f0f1ba93 -Test: Encrypt -Comment: test 53 -Plaintext: f0f1ba93 63a1bfac -Key: 91f56dff e4c63780 a9fb56e7 a6537187 -Ciphertext: cc960eda e44c6b8f -Test: Encrypt -Comment: test 54 -Plaintext: e44c6b8f 91f56dff -Key: e4c63780 a9fb56e7 a6537187 cc960eda -Ciphertext: e12f106d 4f1152d0 -Test: Encrypt -Comment: test 55 -Plaintext: 4f1152d0 e4c63780 -Key: a9fb56e7 a6537187 cc960eda e12f106d -Ciphertext: 556ad853 f79992fd -Test: Encrypt -Comment: test 56 -Plaintext: f79992fd a9fb56e7 -Key: a6537187 cc960eda e12f106d 556ad853 -Ciphertext: 78e8e265 128df6ad -Test: Encrypt -Comment: test 57 -Plaintext: 128df6ad a6537187 -Key: cc960eda e12f106d 556ad853 78e8e265 -Ciphertext: f23892aa 288cb926 -Test: Encrypt -Comment: test 58 -Plaintext: 288cb926 cc960eda -Key: e12f106d 556ad853 78e8e265 f23892aa -Ciphertext: 1d115839 6a117fca -Test: Encrypt -Comment: test 59 -Plaintext: 6a117fca e12f106d -Key: 556ad853 78e8e265 f23892aa 1d115839 -Ciphertext: cf899635 5b087e34 -Test: Encrypt -Comment: test 60 -Plaintext: 5b087e34 556ad853 -Key: 78e8e265 f23892aa 1d115839 cf899635 -Ciphertext: 5c60bff2 e68d88c2 -Test: Encrypt -Comment: test 61 -Plaintext: e68d88c2 78e8e265 -Key: f23892aa 1d115839 cf899635 5c60bff2 -Ciphertext: 7072d01c bffeb50a -Test: Encrypt -Comment: test 62 -Plaintext: bffeb50a f23892aa -Key: 1d115839 cf899635 5c60bff2 7072d01c -Ciphertext: 4513c5eb 9c99ae9e -Test: Encrypt -Comment: test 63 -Plaintext: 9c99ae9e 1d115839 -Key: cf899635 5c60bff2 7072d01c 4513c5eb -Ciphertext: 8f3a38ab 80d9c4ad -Test: Encrypt -Comment: test 64 -Plaintext: 80d9c4ad cf899635 -Key: 5c60bff2 7072d01c 4513c5eb 8f3a38ab -Ciphertext: 2bb0f1b3 c023ed11 -Test: Encrypt - -AlgorithmType: SymmetricCipher -Name: XTEA/ECB -Source: http://www.cix.co.uk/~klockstone/teavect.htm -Comment: test 1 -Plaintext: 00000000 00000000 -Key: 00000000 00000000 00000000 00000000 -Rounds: 1 -Ciphertext: 00000000 9e3779b9 -Test: Encrypt -Comment: test 2 -Plaintext: 9e3779b9 00000000 -Key: 00000000 00000000 00000000 00000000 -Rounds: 2 -Ciphertext: ec01a1de aaa0256d -Test: Encrypt -Comment: test 3 -Plaintext: aaa0256d 00000000 -Key: 00000000 00000000 00000000 ec01a1de -Rounds: 3 -Ciphertext: 114f6d74 a39e590c -Test: Encrypt -Comment: test 4 -Plaintext: a39e590c 00000000 -Key: 00000000 00000000 ec01a1de 114f6d74 -Rounds: 4 -Ciphertext: bc3a7de2 4e238eb9 -Test: Encrypt -Comment: test 5 -Plaintext: 4e238eb9 00000000 -Key: 00000000 ec01a1de 114f6d74 bc3a7de2 -Rounds: 5 -Ciphertext: 845846cf 2f36d07f -Test: Encrypt -Comment: test 6 -Plaintext: 2f36d07f 00000000 -Key: ec01a1de 114f6d74 bc3a7de2 845846cf -Rounds: 6 -Ciphertext: 2794a127 4f3e4b6a -Test: Encrypt -Comment: test 7 -Plaintext: 4f3e4b6a ec01a1de -Key: 114f6d74 bc3a7de2 845846cf 2794a127 -Rounds: 7 -Ciphertext: 6b8ea8b8 d99e66c3 -Test: Encrypt -Comment: test 8 -Plaintext: d99e66c3 114f6d74 -Key: bc3a7de2 845846cf 2794a127 6b8ea8b8 -Rounds: 8 -Ciphertext: 31c5fa6c 241756d6 -Test: Encrypt -Comment: test 9 -Plaintext: 241756d6 bc3a7de2 -Key: 845846cf 2794a127 6b8ea8b8 31c5fa6c -Rounds: 9 -Ciphertext: 4a581696 1fd58a6b -Test: Encrypt -Comment: test 10 -Plaintext: 1fd58a6b 845846cf -Key: 2794a127 6b8ea8b8 31c5fa6c 4a581696 -Rounds: 10 -Ciphertext: dfcd0451 df8822cd -Test: Encrypt -Comment: test 11 -Plaintext: df8822cd 2794a127 -Key: 6b8ea8b8 31c5fa6c 4a581696 dfcd0451 -Rounds: 11 -Ciphertext: 3ad1ff17 f465776c -Test: Encrypt -Comment: test 12 -Plaintext: f465776c 6b8ea8b8 -Key: 31c5fa6c 4a581696 dfcd0451 3ad1ff17 -Rounds: 12 -Ciphertext: 6a1d78c8 4d30bdb9 -Test: Encrypt -Comment: test 13 -Plaintext: 4d30bdb9 31c5fa6c -Key: 4a581696 dfcd0451 3ad1ff17 6a1d78c8 -Rounds: 13 -Ciphertext: 08c86d67 f6ef939b -Test: Encrypt -Comment: test 14 -Plaintext: f6ef939b 4a581696 -Key: dfcd0451 3ad1ff17 6a1d78c8 08c86d67 -Rounds: 14 -Ciphertext: 2a65bfbe f733428c -Test: Encrypt -Comment: test 15 -Plaintext: f733428c dfcd0451 -Key: 3ad1ff17 6a1d78c8 08c86d67 2a65bfbe -Rounds: 15 -Ciphertext: b4bd6e46 40672bcc -Test: Encrypt -Comment: test 16 -Plaintext: 40672bcc 3ad1ff17 -Key: 6a1d78c8 08c86d67 2a65bfbe b4bd6e46 -Rounds: 16 -Ciphertext: 1d8e6992 9a478905 -Test: Encrypt -Comment: test 17 -Plaintext: 9a478905 6a1d78c8 -Key: 08c86d67 2a65bfbe b4bd6e46 1d8e6992 -Rounds: 17 -Ciphertext: f8994ada 80dee76a -Test: Encrypt -Comment: test 18 -Plaintext: 80dee76a 08c86d67 -Key: 2a65bfbe b4bd6e46 1d8e6992 f8994ada -Rounds: 18 -Ciphertext: 0997e6ed cdfef370 -Test: Encrypt -Comment: test 19 -Plaintext: cdfef370 2a65bfbe -Key: b4bd6e46 1d8e6992 f8994ada 0997e6ed -Rounds: 19 -Ciphertext: ece50553 10b76c66 -Test: Encrypt -Comment: test 20 -Plaintext: 10b76c66 b4bd6e46 -Key: 1d8e6992 f8994ada 0997e6ed ece50553 -Rounds: 20 -Ciphertext: a6d39c7b dce1a473 -Test: Encrypt -Comment: test 21 -Plaintext: dce1a473 1d8e6992 -Key: f8994ada 0997e6ed ece50553 a6d39c7b -Rounds: 21 -Ciphertext: 21d06fb7 fbb98544 -Test: Encrypt -Comment: test 22 -Plaintext: fbb98544 f8994ada -Key: 0997e6ed ece50553 a6d39c7b 21d06fb7 -Rounds: 22 -Ciphertext: 72cdd36c e1115fb6 -Test: Encrypt -Comment: test 23 -Plaintext: e1115fb6 0997e6ed -Key: ece50553 a6d39c7b 21d06fb7 72cdd36c -Rounds: 23 -Ciphertext: 25bc6eb3 e4c28ab7 -Test: Encrypt -Comment: test 24 -Plaintext: e4c28ab7 ece50553 -Key: a6d39c7b 21d06fb7 72cdd36c 25bc6eb3 -Rounds: 24 -Ciphertext: 4932a288 78020b9e -Test: Encrypt -Comment: test 25 -Plaintext: 78020b9e a6d39c7b -Key: 21d06fb7 72cdd36c 25bc6eb3 4932a288 -Rounds: 25 -Ciphertext: 25285da1 b66c4459 -Test: Encrypt -Comment: test 26 -Plaintext: b66c4459 21d06fb7 -Key: 72cdd36c 25bc6eb3 4932a288 25285da1 -Rounds: 26 -Ciphertext: 39b0155c f227ab20 -Test: Encrypt -Comment: test 27 -Plaintext: f227ab20 72cdd36c -Key: 25bc6eb3 4932a288 25285da1 39b0155c -Rounds: 27 -Ciphertext: 547571aa f38f1e39 -Test: Encrypt -Comment: test 28 -Plaintext: f38f1e39 25bc6eb3 -Key: 4932a288 25285da1 39b0155c 547571aa -Rounds: 28 -Ciphertext: 27f917b1 e5796aee -Test: Encrypt -Comment: test 29 -Plaintext: e5796aee 4932a288 -Key: 25285da1 39b0155c 547571aa 27f917b1 -Rounds: 29 -Ciphertext: c1da8993 670f9fd2 -Test: Encrypt -Comment: test 30 -Plaintext: 670f9fd2 25285da1 -Key: 39b0155c 547571aa 27f917b1 c1da8993 -Rounds: 30 -Ciphertext: 60e2acaa d0a60db4 -Test: Encrypt -Comment: test 31 -Plaintext: d0a60db4 39b0155c -Key: 547571aa 27f917b1 c1da8993 60e2acaa -Rounds: 31 -Ciphertext: a6eb923d af20a390 -Test: Encrypt -Comment: test 32 -Plaintext: af20a390 547571aa -Key: 27f917b1 c1da8993 60e2acaa a6eb923d -Rounds: 32 -Ciphertext: d26428af 0a202283 -Test: Encrypt -Comment: test 33 -Plaintext: 0a202283 27f917b1 -Key: c1da8993 60e2acaa a6eb923d d26428af -Rounds: 33 -Ciphertext: 1c03ceb9 96e9f2d3 -Test: Encrypt -Comment: test 34 -Plaintext: 96e9f2d3 c1da8993 -Key: 60e2acaa a6eb923d d26428af 1c03ceb9 -Rounds: 34 -Ciphertext: e260b3c1 bbd7dff0 -Test: Encrypt -Comment: test 35 -Plaintext: bbd7dff0 60e2acaa -Key: a6eb923d d26428af 1c03ceb9 e260b3c1 -Rounds: 35 -Ciphertext: d33073f9 12841b97 -Test: Encrypt -Comment: test 36 -Plaintext: 12841b97 a6eb923d -Key: d26428af 1c03ceb9 e260b3c1 d33073f9 -Rounds: 36 -Ciphertext: 17b7ea05 1d723f18 -Test: Encrypt -Comment: test 37 -Plaintext: 1d723f18 d26428af -Key: 1c03ceb9 e260b3c1 d33073f9 17b7ea05 -Rounds: 37 -Ciphertext: 9f571045 31e849b9 -Test: Encrypt -Comment: test 38 -Plaintext: 31e849b9 1c03ceb9 -Key: e260b3c1 d33073f9 17b7ea05 9f571045 -Rounds: 38 -Ciphertext: 288351d2 bd0a0054 -Test: Encrypt -Comment: test 39 -Plaintext: bd0a0054 e260b3c1 -Key: d33073f9 17b7ea05 9f571045 288351d2 -Rounds: 39 -Ciphertext: 9236883a 2bd13143 -Test: Encrypt -Comment: test 40 -Plaintext: 2bd13143 d33073f9 -Key: 17b7ea05 9f571045 288351d2 9236883a -Rounds: 40 -Ciphertext: e91dcf23 7c3fd716 -Test: Encrypt -Comment: test 41 -Plaintext: 7c3fd716 17b7ea05 -Key: 9f571045 288351d2 9236883a e91dcf23 -Rounds: 41 -Ciphertext: 5c8ff51e c3abe43d -Test: Encrypt -Comment: test 42 -Plaintext: c3abe43d 9f571045 -Key: 288351d2 9236883a e91dcf23 5c8ff51e -Rounds: 42 -Ciphertext: 446e9f7c ecb0eb4d -Test: Encrypt -Comment: test 43 -Plaintext: ecb0eb4d 288351d2 -Key: 9236883a e91dcf23 5c8ff51e 446e9f7c -Rounds: 43 -Ciphertext: 86455f77 ffc74050 -Test: Encrypt -Comment: test 44 -Plaintext: ffc74050 9236883a -Key: e91dcf23 5c8ff51e 446e9f7c 86455f77 -Rounds: 44 -Ciphertext: ae85d873 e21ef8d3 -Test: Encrypt -Comment: test 45 -Plaintext: e21ef8d3 e91dcf23 -Key: 5c8ff51e 446e9f7c 86455f77 ae85d873 -Rounds: 45 -Ciphertext: cf411a68 18dce768 -Test: Encrypt -Comment: test 46 -Plaintext: 18dce768 5c8ff51e -Key: 446e9f7c 86455f77 ae85d873 cf411a68 -Rounds: 46 -Ciphertext: 4ef68794 07d2b1b3 -Test: Encrypt -Comment: test 47 -Plaintext: 07d2b1b3 446e9f7c -Key: 86455f77 ae85d873 cf411a68 4ef68794 -Rounds: 47 -Ciphertext: d75a1925 07476976 -Test: Encrypt -Comment: test 48 -Plaintext: 07476976 86455f77 -Key: ae85d873 cf411a68 4ef68794 d75a1925 -Rounds: 48 -Ciphertext: 909d29cb 16b37e1b -Test: Encrypt -Comment: test 49 -Plaintext: 16b37e1b ae85d873 -Key: cf411a68 4ef68794 d75a1925 909d29cb -Rounds: 49 -Ciphertext: e05578cd bd40cd0c -Test: Encrypt -Comment: test 50 -Plaintext: bd40cd0c cf411a68 -Key: 4ef68794 d75a1925 909d29cb e05578cd -Rounds: 50 -Ciphertext: 988b50e5 adf1b74c -Test: Encrypt -Comment: test 51 -Plaintext: adf1b74c 4ef68794 -Key: d75a1925 909d29cb e05578cd 988b50e5 -Rounds: 51 -Ciphertext: 90699d3d d2333c19 -Test: Encrypt -Comment: test 52 -Plaintext: d2333c19 d75a1925 -Key: 909d29cb e05578cd 988b50e5 90699d3d -Rounds: 52 -Ciphertext: a119eb2e 3488c65b -Test: Encrypt -Comment: test 53 -Plaintext: 3488c65b 909d29cb -Key: e05578cd 988b50e5 90699d3d a119eb2e -Rounds: 53 -Ciphertext: e4c43e62 e9c4894b -Test: Encrypt -Comment: test 54 -Plaintext: e9c4894b e05578cd -Key: 988b50e5 90699d3d a119eb2e e4c43e62 -Rounds: 54 -Ciphertext: e1aec3f2 1976c384 -Test: Encrypt -Comment: test 55 -Plaintext: 1976c384 988b50e5 -Key: 90699d3d a119eb2e e4c43e62 e1aec3f2 -Rounds: 55 -Ciphertext: 1b7b0e2b 0b392b46 -Test: Encrypt -Comment: test 56 -Plaintext: 0b392b46 90699d3d -Key: a119eb2e e4c43e62 e1aec3f2 1b7b0e2b -Rounds: 56 -Ciphertext: 1a6ffc0c 600f2ee0 -Test: Encrypt -Comment: test 57 -Plaintext: 600f2ee0 a119eb2e -Key: e4c43e62 e1aec3f2 1b7b0e2b 1a6ffc0c -Rounds: 57 -Ciphertext: 82ccc9d3 94ba3d77 -Test: Encrypt -Comment: test 58 -Plaintext: 94ba3d77 e4c43e62 -Key: e1aec3f2 1b7b0e2b 1a6ffc0c 82ccc9d3 -Rounds: 58 -Ciphertext: 38b5ebd1 c56af77e -Test: Encrypt -Comment: test 59 -Plaintext: c56af77e e1aec3f2 -Key: 1b7b0e2b 1a6ffc0c 82ccc9d3 38b5ebd1 -Rounds: 59 -Ciphertext: f5571f9d fe136a04 -Test: Encrypt -Comment: test 60 -Plaintext: fe136a04 1b7b0e2b -Key: 1a6ffc0c 82ccc9d3 38b5ebd1 f5571f9d -Rounds: 60 -Ciphertext: 62ee209f 08550367 -Test: Encrypt -Comment: test 61 -Plaintext: 08550367 1a6ffc0c -Key: 82ccc9d3 38b5ebd1 f5571f9d 62ee209f -Rounds: 61 -Ciphertext: 069b7afc b0fcde91 -Test: Encrypt -Comment: test 62 -Plaintext: b0fcde91 82ccc9d3 -Key: 38b5ebd1 f5571f9d 62ee209f 069b7afc -Rounds: 62 -Ciphertext: 376a8936 11b9c087 -Test: Encrypt -Comment: test 63 -Plaintext: 11b9c087 38b5ebd1 -Key: f5571f9d 62ee209f 069b7afc 376a8936 -Rounds: 63 -Ciphertext: cdc9e923 2e6c1fe7 -Test: Encrypt -Comment: test 64 -Plaintext: 2e6c1fe7 f5571f9d -Key: 62ee209f 069b7afc 376a8936 cdc9e923 -Rounds: 64 -Ciphertext: 7a01cbc9 b03d6068 -Test: Encrypt diff --git a/embeddedcryptopp/TestVectors/ttmac.txt b/embeddedcryptopp/TestVectors/ttmac.txt deleted file mode 100644 index ec2e683..0000000 --- a/embeddedcryptopp/TestVectors/ttmac.txt +++ /dev/null @@ -1,40 +0,0 @@ -AlgorithmType: MAC -Name: Two-Track-MAC -Source: NESSIE submission -Comment: Key for all test cases -Key: 00112233445566778899aabbccddeeff01234567 -Comment: Test Case 1 -Message: "" -MAC: 2dec8ed4a0fd712ed9fbf2ab466ec2df21215e4a -Test: Verify -Comment: Test Case 2 -Message: "a" -MAC: 5893e3e6e306704dd77ad6e6ed432cde321a7756 -Test: Verify -Comment: Test Case 3 -Message: "abc" -MAC: 70bfd1029797a5c16da5b557a1f0b2779b78497e -Test: Verify -Comment: Test Case 4 -Message: "message digest" -MAC: 8289f4f19ffe4f2af737de4bd71c829d93a972fa -Test: Verify -Comment: Test Case 5 -Message: "abcdefghijklmnopqrstuvwxyz" -MAC: 2186ca09c5533198b7371f245273504ca92bae60 -Test: Verify -Comment: Test Case 6 -Message: "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" -MAC: 8a7bf77aef62a2578497a27c0d6518a429e7c14d -Test: Verify -Comment: Test Case 7 -Message: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" -MAC: 54bac392a886806d169556fcbb6789b54fb364fb -Test: Verify -Comment: Test Case 8 -Message: r8 "1234567890" -MAC: 0ced2c9f8f0d9d03981ab5c8184bac43dd54c484 -Test: Verify -Comment: Test Case 9 -Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" -MAC: 27b3aedb5df8b629f0142194daa3846e1895f3d2 diff --git a/embeddedcryptopp/TestVectors/vmac.txt b/embeddedcryptopp/TestVectors/vmac.txt deleted file mode 100644 index 1d983cd..0000000 --- a/embeddedcryptopp/TestVectors/vmac.txt +++ /dev/null @@ -1,77 +0,0 @@ -AlgorithmType: MAC -Name: VMAC(AES)-64 -Source: http://www.fastcrypto.org/vmac/draft-krovetz-vmac-01.txt -Key: "abcdefghijklmnop" -IV: "bcdefghi" -Message: "" -MAC: 2576BE1C56D8B81B -Test: Verify -Message: "abc" -MAC: 2D376CF5B1813CE5 -Test: Verify -Message: r16 "abc" -MAC: E8421F61D573D298 -Test: Verify -Message: r100 "abc" -MAC: 4492DF6C5CAC1BBE -Test: Verify -Message: r1000000 "abc" -MAC: 09BA597DD7601113 -Test: Verify -Message: r42 "abc" "ab" -MAC: D638B73921F184DE -Test: Verify -Message: r170 "abc" "ab" -MAC: 9DA310281E6FD0A0 -Test: Verify -Message: r65 "a" -MAC: 90 ea 57 cb 51 bc 92 a3 -Test: Verify -Message: r129 "a" -MAC: 86 34 83 87 d1 3d 82 33 -Test: Verify -Message: r65 "abc" -MAC: E86A86EC77A8BF61 -Test: Verify -Message: "abc" -MAC: 2D376CF5B1813CE0 -Test: NotVerify - -AlgorithmType: MAC -Name: VMAC(AES)-128 -Source: http://www.fastcrypto.org/vmac/draft-krovetz-vmac-01.txt -Key: "abcdefghijklmnop" -IV: "bcdefghi" -Message: "" -MAC: 472766C70F74ED23481D6D7DE4E80DAC -Test: Verify -Message: "abc" -MAC: 4EE815A06A1D71EDD36FC75D51188A42 -Test: Verify -Message: r16 "abc" -MAC: 09F2C80C8E1007A0C12FAE19FE4504AE -Test: Verify -Message: r100 "abc" -MAC: 66438817154850C61D8A412164803BCB -Test: Verify -Message: r1000000 "abc" -MAC: 2B6B02288FFC461B75485DE893C629DC -Test: Verify -Message: r42 "abc" "ab" -MAC: F7E95FE3DA8DB9E6BB973E65D0B4CEA5 -Test: Verify -Message: r170 "abc" "ab" -MAC: BF53B8D2D70C05A85880C2E21CAF1299 -Test: Verify -Message: r65 "a" -MAC: b2 9b 00 76 0a 58 c7 ab 92 d6 60 24 d6 9c 1b 92 -Test: Verify -Message: r129 "a" -MAC: a7 e5 2c 32 89 d9 b7 3b 53 57 6f 05 95 85 ee 79 -Test: Verify -Message: r65 "abc" -MAC: 0A1B2F973044F469F405917E45010334 -Test: Verify -Message: "abc" -MAC: 4EE815A06A1D71EDD36FC75D51188A40 -Test: NotVerify diff --git a/embeddedcryptopp/TestVectors/whrlpool.txt b/embeddedcryptopp/TestVectors/whrlpool.txt deleted file mode 100644 index 9a4df8b..0000000 --- a/embeddedcryptopp/TestVectors/whrlpool.txt +++ /dev/null @@ -1,39 +0,0 @@ -AlgorithmType: MessageDigest -Name: Whirlpool -Source: ISO test vectors in http://planeta.terra.com.br/informatica/paulobarreto/whirlpool.zip -Message: "" -Digest: 19FA61D75522A466 9B44E39C1D2E1726 C530232130D407F8 9AFEE0964997F7A7\ - 3E83BE698B288FEB CF88E3E03C4F0757 EA8964E59B63D937 08B138CC42A66EB3 -Test: Verify -Message: "a" -Digest: 8ACA2602792AEC6F 11A67206531FB7D7 F0DFF59413145E69 73C45001D0087B42\ - D11BC645413AEFF6 3A42391A39145A59 1A92200D560195E5 3B478584FDAE231A -Test: Verify -Message: "abc" -Digest: 4E2448A4C6F486BB 16B6562C73B4020B F3043E3A731BCE72 1AE1B303D97E6D4C\ - 7181EEBDB6C57E27 7D0E34957114CBD6 C797FC9D95D8B582 D225292076D4EEF5 -Test: Verify -Message: "message digest" -Digest: 378C84A4126E2DC6 E56DCC7458377AAC 838D00032230F53C E1F5700C0FFB4D3B\ - 8421557659EF55C1 06B4B52AC5A4AAA6 92ED920052838F33 62E86DBD37A8903E -Test: Verify -Message: "abcdefghijklmnopqrstuvwxyz" -Digest: F1D754662636FFE9 2C82EBB9212A484A 8D38631EAD4238F5 442EE13B8054E41B\ - 08BF2A9251C30B6A 0B8AAE86177AB4A6 F68F673E7207865D 5D9819A3DBA4EB3B -Test: Verify -Message: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" -Digest: DC37E008CF9EE69B F11F00ED9ABA2690 1DD7C28CDEC066CC 6AF42E40F82F3A1E\ - 08EBA26629129D8F B7CB57211B9281A6 5517CC879D7B9621 42C65F5A7AF01467 -Test: Verify -Message: r8 "1234567890" -Digest: 466EF18BABB0154D 25B9D38A6414F5C0 8784372BCCB204D6 549C4AFADB601429\ - 4D5BD8DF2A6C44E5 38CD047B2681A51A 2C60481E88C5A20B 2C2A80CF3A9A083B -Test: Verify -Message: "abcdbcdecdefdefgefghfghighijhijk" -Digest: 2A987EA40F917061 F5D6F0A0E4644F48 8A7A5A52DEEE6562 07C562F988E95C69\ - 16BDC8031BC5BE1B 7B947639FE050B56 939BAAA0ADFF9AE6 745B7B181C3BE3FD -Test: Verify -Message: r1000000 "a" -Digest: 0C99005BEB57EFF5 0A7CF005560DDF5D 29057FD86B20BFD6 2DECA0F1CCEA4AF5\ - 1FC15490EDDC47AF 32BB2B66C34FF9AD 8C6008AD677F7712 6953B226E4ED8B01 -Test: Verify diff --git a/embeddedcryptopp/adhoc.cpp.proto b/embeddedcryptopp/adhoc.cpp.proto deleted file mode 100644 index df09f11..0000000 --- a/embeddedcryptopp/adhoc.cpp.proto +++ /dev/null @@ -1,17 +0,0 @@ -#include "filters.h" -#include "files.h" -#include "base64.h" -#include "hex.h" -#include - -USING_NAMESPACE(CryptoPP) -USING_NAMESPACE(std) - -extern int (*AdhocTest)(int argc, char *argv[]); - -int MyAdhocTest(int argc, char *argv[]) -{ - return 0; -} - -static int s_i = (AdhocTest = &MyAdhocTest, 0); diff --git a/embeddedcryptopp/aes.h b/embeddedcryptopp/aes.h deleted file mode 100644 index 0087542..0000000 --- a/embeddedcryptopp/aes.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef CRYPTOPP_AES_H -#define CRYPTOPP_AES_H - -#include "rijndael.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! AES winner, announced on 10/2/2000 -DOCUMENTED_TYPEDEF(Rijndael, AES); - -typedef RijndaelEncryption AESEncryption; -typedef RijndaelDecryption AESDecryption; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/algebra.cpp b/embeddedcryptopp/algebra.cpp deleted file mode 100644 index 78c3947..0000000 --- a/embeddedcryptopp/algebra.cpp +++ /dev/null @@ -1,340 +0,0 @@ -// algebra.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_ALGEBRA_CPP // SunCC workaround: compiler could cause this file to be included twice -#define CRYPTOPP_ALGEBRA_CPP - -#include "algebra.h" -#include "integer.h" - -#include - -NAMESPACE_BEGIN(CryptoPP) - -template const T& AbstractGroup::Double(const Element &a) const -{ - return Add(a, a); -} - -template const T& AbstractGroup::Subtract(const Element &a, const Element &b) const -{ - // make copy of a in case Inverse() overwrites it - Element a1(a); - return Add(a1, Inverse(b)); -} - -template T& AbstractGroup::Accumulate(Element &a, const Element &b) const -{ - return a = Add(a, b); -} - -template T& AbstractGroup::Reduce(Element &a, const Element &b) const -{ - return a = Subtract(a, b); -} - -template const T& AbstractRing::Square(const Element &a) const -{ - return Multiply(a, a); -} - -template const T& AbstractRing::Divide(const Element &a, const Element &b) const -{ - // make copy of a in case MultiplicativeInverse() overwrites it - Element a1(a); - return Multiply(a1, MultiplicativeInverse(b)); -} - -template const T& AbstractEuclideanDomain::Mod(const Element &a, const Element &b) const -{ - Element q; - DivisionAlgorithm(result, q, a, b); - return result; -} - -template const T& AbstractEuclideanDomain::Gcd(const Element &a, const Element &b) const -{ - Element g[3]={b, a}; - unsigned int i0=0, i1=1, i2=2; - - while (!Equal(g[i1], this->Identity())) - { - g[i2] = Mod(g[i0], g[i1]); - unsigned int t = i0; i0 = i1; i1 = i2; i2 = t; - } - - return result = g[i0]; -} - -template const typename QuotientRing::Element& QuotientRing::MultiplicativeInverse(const Element &a) const -{ - Element g[3]={m_modulus, a}; - Element v[3]={m_domain.Identity(), m_domain.MultiplicativeIdentity()}; - Element y; - unsigned int i0=0, i1=1, i2=2; - - while (!Equal(g[i1], Identity())) - { - // y = g[i0] / g[i1]; - // g[i2] = g[i0] % g[i1]; - m_domain.DivisionAlgorithm(g[i2], y, g[i0], g[i1]); - // v[i2] = v[i0] - (v[i1] * y); - v[i2] = m_domain.Subtract(v[i0], m_domain.Multiply(v[i1], y)); - unsigned int t = i0; i0 = i1; i1 = i2; i2 = t; - } - - return m_domain.IsUnit(g[i0]) ? m_domain.Divide(v[i0], g[i0]) : m_domain.Identity(); -} - -template T AbstractGroup::ScalarMultiply(const Element &base, const Integer &exponent) const -{ - Element result; - SimultaneousMultiply(&result, base, &exponent, 1); - return result; -} - -template T AbstractGroup::CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const -{ - const unsigned expLen = STDMAX(e1.BitCount(), e2.BitCount()); - if (expLen==0) - return Identity(); - - const unsigned w = (expLen <= 46 ? 1 : (expLen <= 260 ? 2 : 3)); - const unsigned tableSize = 1< powerTable(tableSize << w); - - powerTable[1] = x; - powerTable[tableSize] = y; - if (w==1) - powerTable[3] = Add(x,y); - else - { - powerTable[2] = Double(x); - powerTable[2*tableSize] = Double(y); - - unsigned i, j; - - for (i=3; i=0; i--) - { - power1 = 2*power1 + e1.GetBit(i); - power2 = 2*power2 + e2.GetBit(i); - - if (i==0 || 2*power1 >= tableSize || 2*power2 >= tableSize) - { - unsigned squaresBefore = prevPosition-i; - unsigned squaresAfter = 0; - prevPosition = i; - while ((power1 || power2) && power1%2 == 0 && power2%2==0) - { - power1 /= 2; - power2 /= 2; - squaresBefore--; - squaresAfter++; - } - if (firstTime) - { - result = powerTable[(power2< Element GeneralCascadeMultiplication(const AbstractGroup &group, Iterator begin, Iterator end) -{ - if (end-begin == 1) - return group.ScalarMultiply(begin->base, begin->exponent); - else if (end-begin == 2) - return group.CascadeScalarMultiply(begin->base, begin->exponent, (begin+1)->base, (begin+1)->exponent); - else - { - Integer q, t; - Iterator last = end; - --last; - - std::make_heap(begin, end); - std::pop_heap(begin, end); - - while (!!begin->exponent) - { - // last->exponent is largest exponent, begin->exponent is next largest - t = last->exponent; - Integer::Divide(last->exponent, q, t, begin->exponent); - - if (q == Integer::One()) - group.Accumulate(begin->base, last->base); // avoid overhead of ScalarMultiply() - else - group.Accumulate(begin->base, group.ScalarMultiply(last->base, q)); - - std::push_heap(begin, end); - std::pop_heap(begin, end); - } - - return group.ScalarMultiply(last->base, last->exponent); - } -} - -struct WindowSlider -{ - WindowSlider(const Integer &expIn, bool fastNegate, unsigned int windowSizeIn=0) - : exp(expIn), windowModulus(Integer::One()), windowSize(windowSizeIn), windowBegin(0), fastNegate(fastNegate), firstTime(true), finished(false) - { - if (windowSize == 0) - { - unsigned int expLen = exp.BitCount(); - windowSize = expLen <= 17 ? 1 : (expLen <= 24 ? 2 : (expLen <= 70 ? 3 : (expLen <= 197 ? 4 : (expLen <= 539 ? 5 : (expLen <= 1434 ? 6 : 7))))); - } - windowModulus <<= windowSize; - } - - void FindNextWindow() - { - unsigned int expLen = exp.WordCount() * WORD_BITS; - unsigned int skipCount = firstTime ? 0 : windowSize; - firstTime = false; - while (!exp.GetBit(skipCount)) - { - if (skipCount >= expLen) - { - finished = true; - return; - } - skipCount++; - } - - exp >>= skipCount; - windowBegin += skipCount; - expWindow = word32(exp % (word(1) << windowSize)); - - if (fastNegate && exp.GetBit(windowSize)) - { - negateNext = true; - expWindow = (word32(1) << windowSize) - expWindow; - exp += windowModulus; - } - else - negateNext = false; - } - - Integer exp, windowModulus; - unsigned int windowSize, windowBegin; - word32 expWindow; - bool fastNegate, negateNext, firstTime, finished; -}; - -template -void AbstractGroup::SimultaneousMultiply(T *results, const T &base, const Integer *expBegin, unsigned int expCount) const -{ - std::vector > buckets(expCount); - std::vector exponents; - exponents.reserve(expCount); - unsigned int i; - - for (i=0; iNotNegative()); - exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 0)); - exponents[i].FindNextWindow(); - buckets[i].resize(1<<(exponents[i].windowSize-1), Identity()); - } - - unsigned int expBitPosition = 0; - Element g = base; - bool notDone = true; - - while (notDone) - { - notDone = false; - for (i=0; i 1) - { - for (int j = (int)buckets[i].size()-2; j >= 1; j--) - { - Accumulate(buckets[i][j], buckets[i][j+1]); - Accumulate(r, buckets[i][j]); - } - Accumulate(buckets[i][0], buckets[i][1]); - r = Add(Double(r), buckets[i][0]); - } - } -} - -template T AbstractRing::Exponentiate(const Element &base, const Integer &exponent) const -{ - Element result; - SimultaneousExponentiate(&result, base, &exponent, 1); - return result; -} - -template T AbstractRing::CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const -{ - return MultiplicativeGroup().AbstractGroup::CascadeScalarMultiply(x, e1, y, e2); -} - -template Element GeneralCascadeExponentiation(const AbstractRing &ring, Iterator begin, Iterator end) -{ - return GeneralCascadeMultiplication(ring.MultiplicativeGroup(), begin, end); -} - -template -void AbstractRing::SimultaneousExponentiate(T *results, const T &base, const Integer *exponents, unsigned int expCount) const -{ - MultiplicativeGroup().AbstractGroup::SimultaneousMultiply(results, base, exponents, expCount); -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/algebra.h b/embeddedcryptopp/algebra.h deleted file mode 100644 index 13038bd..0000000 --- a/embeddedcryptopp/algebra.h +++ /dev/null @@ -1,285 +0,0 @@ -#ifndef CRYPTOPP_ALGEBRA_H -#define CRYPTOPP_ALGEBRA_H - -#include "config.h" - -NAMESPACE_BEGIN(CryptoPP) - -class Integer; - -// "const Element&" returned by member functions are references -// to internal data members. Since each object may have only -// one such data member for holding results, the following code -// will produce incorrect results: -// abcd = group.Add(group.Add(a,b), group.Add(c,d)); -// But this should be fine: -// abcd = group.Add(a, group.Add(b, group.Add(c,d)); - -//! Abstract Group -template class CRYPTOPP_NO_VTABLE AbstractGroup -{ -public: - typedef T Element; - - virtual ~AbstractGroup() {} - - virtual bool Equal(const Element &a, const Element &b) const =0; - virtual const Element& Identity() const =0; - virtual const Element& Add(const Element &a, const Element &b) const =0; - virtual const Element& Inverse(const Element &a) const =0; - virtual bool InversionIsFast() const {return false;} - - virtual const Element& Double(const Element &a) const; - virtual const Element& Subtract(const Element &a, const Element &b) const; - virtual Element& Accumulate(Element &a, const Element &b) const; - virtual Element& Reduce(Element &a, const Element &b) const; - - virtual Element ScalarMultiply(const Element &a, const Integer &e) const; - virtual Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const; - - virtual void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const; -}; - -//! Abstract Ring -template class CRYPTOPP_NO_VTABLE AbstractRing : public AbstractGroup -{ -public: - typedef T Element; - - AbstractRing() {m_mg.m_pRing = this;} - AbstractRing(const AbstractRing &source) {m_mg.m_pRing = this;} - AbstractRing& operator=(const AbstractRing &source) {return *this;} - - virtual bool IsUnit(const Element &a) const =0; - virtual const Element& MultiplicativeIdentity() const =0; - virtual const Element& Multiply(const Element &a, const Element &b) const =0; - virtual const Element& MultiplicativeInverse(const Element &a) const =0; - - virtual const Element& Square(const Element &a) const; - virtual const Element& Divide(const Element &a, const Element &b) const; - - virtual Element Exponentiate(const Element &a, const Integer &e) const; - virtual Element CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const; - - virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const; - - virtual const AbstractGroup& MultiplicativeGroup() const - {return m_mg;} - -private: - class MultiplicativeGroupT : public AbstractGroup - { - public: - const AbstractRing& GetRing() const - {return *m_pRing;} - - bool Equal(const Element &a, const Element &b) const - {return GetRing().Equal(a, b);} - - const Element& Identity() const - {return GetRing().MultiplicativeIdentity();} - - const Element& Add(const Element &a, const Element &b) const - {return GetRing().Multiply(a, b);} - - Element& Accumulate(Element &a, const Element &b) const - {return a = GetRing().Multiply(a, b);} - - const Element& Inverse(const Element &a) const - {return GetRing().MultiplicativeInverse(a);} - - const Element& Subtract(const Element &a, const Element &b) const - {return GetRing().Divide(a, b);} - - Element& Reduce(Element &a, const Element &b) const - {return a = GetRing().Divide(a, b);} - - const Element& Double(const Element &a) const - {return GetRing().Square(a);} - - Element ScalarMultiply(const Element &a, const Integer &e) const - {return GetRing().Exponentiate(a, e);} - - Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const - {return GetRing().CascadeExponentiate(x, e1, y, e2);} - - void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const - {GetRing().SimultaneousExponentiate(results, base, exponents, exponentsCount);} - - const AbstractRing *m_pRing; - }; - - MultiplicativeGroupT m_mg; -}; - -// ******************************************************** - -//! Base and Exponent -template -struct BaseAndExponent -{ -public: - BaseAndExponent() {} - BaseAndExponent(const T &base, const E &exponent) : base(base), exponent(exponent) {} - bool operator<(const BaseAndExponent &rhs) const {return exponent < rhs.exponent;} - T base; - E exponent; -}; - -// VC60 workaround: incomplete member template support -template - Element GeneralCascadeMultiplication(const AbstractGroup &group, Iterator begin, Iterator end); -template - Element GeneralCascadeExponentiation(const AbstractRing &ring, Iterator begin, Iterator end); - -// ******************************************************** - -//! Abstract Euclidean Domain -template class CRYPTOPP_NO_VTABLE AbstractEuclideanDomain : public AbstractRing -{ -public: - typedef T Element; - - virtual void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const =0; - - virtual const Element& Mod(const Element &a, const Element &b) const =0; - virtual const Element& Gcd(const Element &a, const Element &b) const; - -protected: - mutable Element result; -}; - -// ******************************************************** - -//! EuclideanDomainOf -template class EuclideanDomainOf : public AbstractEuclideanDomain -{ -public: - typedef T Element; - - EuclideanDomainOf() {} - - bool Equal(const Element &a, const Element &b) const - {return a==b;} - - const Element& Identity() const - {return Element::Zero();} - - const Element& Add(const Element &a, const Element &b) const - {return result = a+b;} - - Element& Accumulate(Element &a, const Element &b) const - {return a+=b;} - - const Element& Inverse(const Element &a) const - {return result = -a;} - - const Element& Subtract(const Element &a, const Element &b) const - {return result = a-b;} - - Element& Reduce(Element &a, const Element &b) const - {return a-=b;} - - const Element& Double(const Element &a) const - {return result = a.Doubled();} - - const Element& MultiplicativeIdentity() const - {return Element::One();} - - const Element& Multiply(const Element &a, const Element &b) const - {return result = a*b;} - - const Element& Square(const Element &a) const - {return result = a.Squared();} - - bool IsUnit(const Element &a) const - {return a.IsUnit();} - - const Element& MultiplicativeInverse(const Element &a) const - {return result = a.MultiplicativeInverse();} - - const Element& Divide(const Element &a, const Element &b) const - {return result = a/b;} - - const Element& Mod(const Element &a, const Element &b) const - {return result = a%b;} - - void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const - {Element::Divide(r, q, a, d);} - - bool operator==(const EuclideanDomainOf &rhs) const - {return true;} - -private: - mutable Element result; -}; - -//! Quotient Ring -template class QuotientRing : public AbstractRing -{ -public: - typedef T EuclideanDomain; - typedef typename T::Element Element; - - QuotientRing(const EuclideanDomain &domain, const Element &modulus) - : m_domain(domain), m_modulus(modulus) {} - - const EuclideanDomain & GetDomain() const - {return m_domain;} - - const Element& GetModulus() const - {return m_modulus;} - - bool Equal(const Element &a, const Element &b) const - {return m_domain.Equal(m_domain.Mod(m_domain.Subtract(a, b), m_modulus), m_domain.Identity());} - - const Element& Identity() const - {return m_domain.Identity();} - - const Element& Add(const Element &a, const Element &b) const - {return m_domain.Add(a, b);} - - Element& Accumulate(Element &a, const Element &b) const - {return m_domain.Accumulate(a, b);} - - const Element& Inverse(const Element &a) const - {return m_domain.Inverse(a);} - - const Element& Subtract(const Element &a, const Element &b) const - {return m_domain.Subtract(a, b);} - - Element& Reduce(Element &a, const Element &b) const - {return m_domain.Reduce(a, b);} - - const Element& Double(const Element &a) const - {return m_domain.Double(a);} - - bool IsUnit(const Element &a) const - {return m_domain.IsUnit(m_domain.Gcd(a, m_modulus));} - - const Element& MultiplicativeIdentity() const - {return m_domain.MultiplicativeIdentity();} - - const Element& Multiply(const Element &a, const Element &b) const - {return m_domain.Mod(m_domain.Multiply(a, b), m_modulus);} - - const Element& Square(const Element &a) const - {return m_domain.Mod(m_domain.Square(a), m_modulus);} - - const Element& MultiplicativeInverse(const Element &a) const; - - bool operator==(const QuotientRing &rhs) const - {return m_domain == rhs.m_domain && m_modulus == rhs.m_modulus;} - -protected: - EuclideanDomain m_domain; - Element m_modulus; -}; - -NAMESPACE_END - -#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES -#include "algebra.cpp" -#endif - -#endif diff --git a/embeddedcryptopp/algparam.cpp b/embeddedcryptopp/algparam.cpp deleted file mode 100644 index a70d5dd..0000000 --- a/embeddedcryptopp/algparam.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// algparam.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "algparam.h" - -NAMESPACE_BEGIN(CryptoPP) - -PAssignIntToInteger g_pAssignIntToInteger = NULL; - -bool CombinedNameValuePairs::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const -{ - if (strcmp(name, "ValueNames") == 0) - return m_pairs1.GetVoidValue(name, valueType, pValue) && m_pairs2.GetVoidValue(name, valueType, pValue); - else - return m_pairs1.GetVoidValue(name, valueType, pValue) || m_pairs2.GetVoidValue(name, valueType, pValue); -} - -void AlgorithmParametersBase::operator=(const AlgorithmParametersBase& rhs) -{ - assert(false); -} - -bool AlgorithmParametersBase::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const -{ - if (strcmp(name, "ValueNames") == 0) - { - NameValuePairs::ThrowIfTypeMismatch(name, typeid(std::string), valueType); - if (m_next.get()) - m_next->GetVoidValue(name, valueType, pValue); - (*reinterpret_cast(pValue) += m_name) += ";"; - return true; - } - else if (strcmp(name, m_name) == 0) - { - AssignValue(name, valueType, pValue); - m_used = true; - return true; - } - else if (m_next.get()) - return m_next->GetVoidValue(name, valueType, pValue); - else - return false; -} - -AlgorithmParameters::AlgorithmParameters() - : m_defaultThrowIfNotUsed(true) -{ -} - -AlgorithmParameters::AlgorithmParameters(const AlgorithmParameters &x) - : m_defaultThrowIfNotUsed(x.m_defaultThrowIfNotUsed) -{ - m_next.reset(const_cast(x).m_next.release()); -} - -AlgorithmParameters & AlgorithmParameters::operator=(const AlgorithmParameters &x) -{ - m_next.reset(const_cast(x).m_next.release()); - return *this; -} - -bool AlgorithmParameters::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const -{ - if (m_next.get()) - return m_next->GetVoidValue(name, valueType, pValue); - else - return false; -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/algparam.h b/embeddedcryptopp/algparam.h deleted file mode 100644 index ea5129c..0000000 --- a/embeddedcryptopp/algparam.h +++ /dev/null @@ -1,398 +0,0 @@ -#ifndef CRYPTOPP_ALGPARAM_H -#define CRYPTOPP_ALGPARAM_H - -#include "cryptlib.h" -#include "smartptr.h" -#include "secblock.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! used to pass byte array input as part of a NameValuePairs object -/*! the deepCopy option is used when the NameValuePairs object can't - keep a copy of the data available */ -class ConstByteArrayParameter -{ -public: - ConstByteArrayParameter(const char *data = NULL, bool deepCopy = false) - { - Assign((const byte *)data, data ? strlen(data) : 0, deepCopy); - } - ConstByteArrayParameter(const byte *data, size_t size, bool deepCopy = false) - { - Assign(data, size, deepCopy); - } - template ConstByteArrayParameter(const T &string, bool deepCopy = false) - { - CRYPTOPP_COMPILE_ASSERT(sizeof(CPP_TYPENAME T::value_type) == 1); - Assign((const byte *)string.data(), string.size(), deepCopy); - } - - void Assign(const byte *data, size_t size, bool deepCopy) - { - if (deepCopy) - m_block.Assign(data, size); - else - { - m_data = data; - m_size = size; - } - m_deepCopy = deepCopy; - } - - const byte *begin() const {return m_deepCopy ? m_block.begin() : m_data;} - const byte *end() const {return m_deepCopy ? m_block.end() : m_data + m_size;} - size_t size() const {return m_deepCopy ? m_block.size() : m_size;} - -private: - bool m_deepCopy; - const byte *m_data; - size_t m_size; - SecByteBlock m_block; -}; - -class ByteArrayParameter -{ -public: - ByteArrayParameter(byte *data = NULL, unsigned int size = 0) - : m_data(data), m_size(size) {} - ByteArrayParameter(SecByteBlock &block) - : m_data(block.begin()), m_size(block.size()) {} - - byte *begin() const {return m_data;} - byte *end() const {return m_data + m_size;} - size_t size() const {return m_size;} - -private: - byte *m_data; - size_t m_size; -}; - -class CRYPTOPP_DLL CombinedNameValuePairs : public NameValuePairs -{ -public: - CombinedNameValuePairs(const NameValuePairs &pairs1, const NameValuePairs &pairs2) - : m_pairs1(pairs1), m_pairs2(pairs2) {} - - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; - -private: - const NameValuePairs &m_pairs1, &m_pairs2; -}; - -template -class GetValueHelperClass -{ -public: - GetValueHelperClass(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst) - : m_pObject(pObject), m_name(name), m_valueType(&valueType), m_pValue(pValue), m_found(false), m_getValueNames(false) - { - if (strcmp(m_name, "ValueNames") == 0) - { - m_found = m_getValueNames = true; - NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(std::string), *m_valueType); - if (searchFirst) - searchFirst->GetVoidValue(m_name, valueType, pValue); - if (typeid(T) != typeid(BASE)) - pObject->BASE::GetVoidValue(m_name, valueType, pValue); - ((*reinterpret_cast(m_pValue) += "ThisPointer:") += typeid(T).name()) += ';'; - } - - if (!m_found && strncmp(m_name, "ThisPointer:", 12) == 0 && strcmp(m_name+12, typeid(T).name()) == 0) - { - NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T *), *m_valueType); - *reinterpret_cast(pValue) = pObject; - m_found = true; - return; - } - - if (!m_found && searchFirst) - m_found = searchFirst->GetVoidValue(m_name, valueType, pValue); - - if (!m_found && typeid(T) != typeid(BASE)) - m_found = pObject->BASE::GetVoidValue(m_name, valueType, pValue); - } - - operator bool() const {return m_found;} - - template - GetValueHelperClass & operator()(const char *name, const R & (T::*pm)() const) - { - if (m_getValueNames) - (*reinterpret_cast(m_pValue) += name) += ";"; - if (!m_found && strcmp(name, m_name) == 0) - { - NameValuePairs::ThrowIfTypeMismatch(name, typeid(R), *m_valueType); - *reinterpret_cast(m_pValue) = (m_pObject->*pm)(); - m_found = true; - } - return *this; - } - - GetValueHelperClass &Assignable() - { -#ifndef __INTEL_COMPILER // ICL 9.1 workaround: Intel compiler copies the vTable pointer for some reason - if (m_getValueNames) - ((*reinterpret_cast(m_pValue) += "ThisObject:") += typeid(T).name()) += ';'; - if (!m_found && strncmp(m_name, "ThisObject:", 11) == 0 && strcmp(m_name+11, typeid(T).name()) == 0) - { - NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T), *m_valueType); - *reinterpret_cast(m_pValue) = *m_pObject; - m_found = true; - } -#endif - return *this; - } - -private: - const T *m_pObject; - const char *m_name; - const std::type_info *m_valueType; - void *m_pValue; - bool m_found, m_getValueNames; -}; - -template -GetValueHelperClass GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL, BASE *dummy=NULL) -{ - return GetValueHelperClass(pObject, name, valueType, pValue, searchFirst); -} - -template -GetValueHelperClass GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL) -{ - return GetValueHelperClass(pObject, name, valueType, pValue, searchFirst); -} - -// ******************************************************** - -template -R Hack_DefaultValueFromConstReferenceType(const R &) -{ - return R(); -} - -template -bool Hack_GetValueIntoConstReference(const NameValuePairs &source, const char *name, const R &value) -{ - return source.GetValue(name, const_cast(value)); -} - -template -class AssignFromHelperClass -{ -public: - AssignFromHelperClass(T *pObject, const NameValuePairs &source) - : m_pObject(pObject), m_source(source), m_done(false) - { - if (source.GetThisObject(*pObject)) - m_done = true; - else if (typeid(BASE) != typeid(T)) - pObject->BASE::AssignFrom(source); - } - - template - AssignFromHelperClass & operator()(const char *name, void (T::*pm)(R)) // VC60 workaround: "const R &" here causes compiler error - { - if (!m_done) - { - R value = Hack_DefaultValueFromConstReferenceType(reinterpret_cast(*(int *)NULL)); - if (!Hack_GetValueIntoConstReference(m_source, name, value)) - throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name + "'"); - (m_pObject->*pm)(value); - } - return *this; - } - - template - AssignFromHelperClass & operator()(const char *name1, const char *name2, void (T::*pm)(R, S)) // VC60 workaround: "const R &" here causes compiler error - { - if (!m_done) - { - R value1 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast(*(int *)NULL)); - if (!Hack_GetValueIntoConstReference(m_source, name1, value1)) - throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name1 + "'"); - S value2 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast(*(int *)NULL)); - if (!Hack_GetValueIntoConstReference(m_source, name2, value2)) - throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name2 + "'"); - (m_pObject->*pm)(value1, value2); - } - return *this; - } - -private: - T *m_pObject; - const NameValuePairs &m_source; - bool m_done; -}; - -template -AssignFromHelperClass AssignFromHelper(T *pObject, const NameValuePairs &source, BASE *dummy=NULL) -{ - return AssignFromHelperClass(pObject, source); -} - -template -AssignFromHelperClass AssignFromHelper(T *pObject, const NameValuePairs &source) -{ - return AssignFromHelperClass(pObject, source); -} - -// ******************************************************** - -// to allow the linker to discard Integer code if not needed. -typedef bool (CRYPTOPP_API * PAssignIntToInteger)(const std::type_info &valueType, void *pInteger, const void *pInt); -CRYPTOPP_DLL extern PAssignIntToInteger g_pAssignIntToInteger; - -CRYPTOPP_DLL const std::type_info & CRYPTOPP_API IntegerTypeId(); - -class CRYPTOPP_DLL AlgorithmParametersBase -{ -public: - class ParameterNotUsed : public Exception - { - public: - ParameterNotUsed(const char *name) : Exception(OTHER_ERROR, std::string("AlgorithmParametersBase: parameter \"") + name + "\" not used") {} - }; - - // this is actually a move, not a copy - AlgorithmParametersBase(const AlgorithmParametersBase &x) - : m_name(x.m_name), m_throwIfNotUsed(x.m_throwIfNotUsed), m_used(x.m_used) - { - m_next.reset(const_cast(x).m_next.release()); - x.m_used = true; - } - - AlgorithmParametersBase(const char *name, bool throwIfNotUsed) - : m_name(name), m_throwIfNotUsed(throwIfNotUsed), m_used(false) {} - - virtual ~AlgorithmParametersBase() - { -#ifdef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE - if (!std::uncaught_exception()) -#else - try -#endif - { - if (m_throwIfNotUsed && !m_used) - throw ParameterNotUsed(m_name); - } -#ifndef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE - catch(...) - { - } -#endif - } - - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; - -protected: - friend class AlgorithmParameters; - void operator=(const AlgorithmParametersBase& rhs); // assignment not allowed, declare this for VC60 - - virtual void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const =0; - virtual void MoveInto(void *p) const =0; // not really const - - const char *m_name; - bool m_throwIfNotUsed; - mutable bool m_used; - member_ptr m_next; -}; - -template -class AlgorithmParametersTemplate : public AlgorithmParametersBase -{ -public: - AlgorithmParametersTemplate(const char *name, const T &value, bool throwIfNotUsed) - : AlgorithmParametersBase(name, throwIfNotUsed), m_value(value) - { - } - - void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const - { - // special case for retrieving an Integer parameter when an int was passed in - if (!(g_pAssignIntToInteger != NULL && typeid(T) == typeid(int) && g_pAssignIntToInteger(valueType, pValue, &m_value))) - { - NameValuePairs::ThrowIfTypeMismatch(name, typeid(T), valueType); - *reinterpret_cast(pValue) = m_value; - } - } - - void MoveInto(void *buffer) const - { - AlgorithmParametersTemplate* p = new(buffer) AlgorithmParametersTemplate(*this); - } - -protected: - T m_value; -}; - -CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate; -CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate; -CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate; - -class CRYPTOPP_DLL AlgorithmParameters : public NameValuePairs -{ -public: - AlgorithmParameters(); - -#ifdef __BORLANDC__ - template - AlgorithmParameters(const char *name, const T &value, bool throwIfNotUsed=true) - : m_next(new AlgorithmParametersTemplate(name, value, throwIfNotUsed)) - , m_defaultThrowIfNotUsed(throwIfNotUsed) - { - } -#endif - - AlgorithmParameters(const AlgorithmParameters &x); - - AlgorithmParameters & operator=(const AlgorithmParameters &x); - - template - AlgorithmParameters & operator()(const char *name, const T &value, bool throwIfNotUsed) - { - member_ptr p(new AlgorithmParametersTemplate(name, value, throwIfNotUsed)); - p->m_next.reset(m_next.release()); - m_next.reset(p.release()); - m_defaultThrowIfNotUsed = throwIfNotUsed; - return *this; - } - - template - AlgorithmParameters & operator()(const char *name, const T &value) - { - return operator()(name, value, m_defaultThrowIfNotUsed); - } - - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; - -protected: - member_ptr m_next; - bool m_defaultThrowIfNotUsed; -}; - -//! Create an object that implements NameValuePairs for passing parameters -/*! \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed - \note throwIfNotUsed is ignored if using a compiler that does not support std::uncaught_exception(), - such as MSVC 7.0 and earlier. - \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by - repeatedly using operator() on the object returned by MakeParameters, for example: - AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3); -*/ -#ifdef __BORLANDC__ -typedef AlgorithmParameters MakeParameters; -#else -template -AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed = true) -{ - return AlgorithmParameters()(name, value, throwIfNotUsed); -} -#endif - -#define CRYPTOPP_GET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Get##name) -#define CRYPTOPP_SET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Set##name) -#define CRYPTOPP_SET_FUNCTION_ENTRY2(name1, name2) (Name::name1(), Name::name2(), &ThisClass::Set##name1##And##name2) - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/argnames.h b/embeddedcryptopp/argnames.h deleted file mode 100644 index 23add3c..0000000 --- a/embeddedcryptopp/argnames.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef CRYPTOPP_ARGNAMES_H -#define CRYPTOPP_ARGNAMES_H - -#include "cryptlib.h" - -NAMESPACE_BEGIN(CryptoPP) - -DOCUMENTED_NAMESPACE_BEGIN(Name) - -#define CRYPTOPP_DEFINE_NAME_STRING(name) inline const char *name() {return #name;} - -CRYPTOPP_DEFINE_NAME_STRING(ValueNames) //!< string, a list of value names with a semicolon (';') after each name -CRYPTOPP_DEFINE_NAME_STRING(Version) //!< int -CRYPTOPP_DEFINE_NAME_STRING(Seed) //!< ConstByteArrayParameter -CRYPTOPP_DEFINE_NAME_STRING(Key) //!< ConstByteArrayParameter -CRYPTOPP_DEFINE_NAME_STRING(IV) //!< ConstByteArrayParameter, also accepts const byte * for backwards compatibility -CRYPTOPP_DEFINE_NAME_STRING(StolenIV) //!< byte * -CRYPTOPP_DEFINE_NAME_STRING(Rounds) //!< int -CRYPTOPP_DEFINE_NAME_STRING(FeedbackSize) //!< int -CRYPTOPP_DEFINE_NAME_STRING(WordSize) //!< int, in bytes -CRYPTOPP_DEFINE_NAME_STRING(BlockSize) //!< int, in bytes -CRYPTOPP_DEFINE_NAME_STRING(EffectiveKeyLength) //!< int, in bits -CRYPTOPP_DEFINE_NAME_STRING(KeySize) //!< int, in bits -CRYPTOPP_DEFINE_NAME_STRING(ModulusSize) //!< int, in bits -CRYPTOPP_DEFINE_NAME_STRING(SubgroupOrderSize) //!< int, in bits -CRYPTOPP_DEFINE_NAME_STRING(PrivateExponentSize)//!< int, in bits -CRYPTOPP_DEFINE_NAME_STRING(Modulus) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(PublicExponent) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(PrivateExponent) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(PublicElement) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(SubgroupOrder) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(Cofactor) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(SubgroupGenerator) //!< Integer, ECP::Point, or EC2N::Point -CRYPTOPP_DEFINE_NAME_STRING(Curve) //!< ECP or EC2N -CRYPTOPP_DEFINE_NAME_STRING(GroupOID) //!< OID -CRYPTOPP_DEFINE_NAME_STRING(PointerToPrimeSelector) //!< const PrimeSelector * -CRYPTOPP_DEFINE_NAME_STRING(Prime1) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(Prime2) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(ModPrime1PrivateExponent) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(ModPrime2PrivateExponent) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(MultiplicativeInverseOfPrime2ModPrime1) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime1) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime2) //!< Integer -CRYPTOPP_DEFINE_NAME_STRING(PutMessage) //!< bool -CRYPTOPP_DEFINE_NAME_STRING(TruncatedDigestSize) //!< int -CRYPTOPP_DEFINE_NAME_STRING(BlockPaddingScheme) //!< StreamTransformationFilter::BlockPaddingScheme -CRYPTOPP_DEFINE_NAME_STRING(HashVerificationFilterFlags) //!< word32 -CRYPTOPP_DEFINE_NAME_STRING(AuthenticatedDecryptionFilterFlags) //!< word32 -CRYPTOPP_DEFINE_NAME_STRING(SignatureVerificationFilterFlags) //!< word32 -CRYPTOPP_DEFINE_NAME_STRING(InputBuffer) //!< ConstByteArrayParameter -CRYPTOPP_DEFINE_NAME_STRING(OutputBuffer) //!< ByteArrayParameter -CRYPTOPP_DEFINE_NAME_STRING(InputFileName) //!< const char * -CRYPTOPP_DEFINE_NAME_STRING(InputStreamPointer) //!< std::istream * -CRYPTOPP_DEFINE_NAME_STRING(InputBinaryMode) //!< bool -CRYPTOPP_DEFINE_NAME_STRING(OutputFileName) //!< const char * -CRYPTOPP_DEFINE_NAME_STRING(OutputStreamPointer) //!< std::ostream * -CRYPTOPP_DEFINE_NAME_STRING(OutputBinaryMode) //!< bool -CRYPTOPP_DEFINE_NAME_STRING(EncodingParameters) //!< ConstByteArrayParameter -CRYPTOPP_DEFINE_NAME_STRING(KeyDerivationParameters) //!< ConstByteArrayParameter -CRYPTOPP_DEFINE_NAME_STRING(Separator) //< ConstByteArrayParameter -CRYPTOPP_DEFINE_NAME_STRING(Terminator) //< ConstByteArrayParameter -CRYPTOPP_DEFINE_NAME_STRING(Uppercase) //< bool -CRYPTOPP_DEFINE_NAME_STRING(GroupSize) //< int -CRYPTOPP_DEFINE_NAME_STRING(Pad) //< bool -CRYPTOPP_DEFINE_NAME_STRING(PaddingByte) //< byte -CRYPTOPP_DEFINE_NAME_STRING(Log2Base) //< int -CRYPTOPP_DEFINE_NAME_STRING(EncodingLookupArray) //< const byte * -CRYPTOPP_DEFINE_NAME_STRING(DecodingLookupArray) //< const byte * -CRYPTOPP_DEFINE_NAME_STRING(InsertLineBreaks) //< bool -CRYPTOPP_DEFINE_NAME_STRING(MaxLineLength) //< int -CRYPTOPP_DEFINE_NAME_STRING(DigestSize) //!< int, in bytes -CRYPTOPP_DEFINE_NAME_STRING(L1KeyLength) //!< int, in bytes -CRYPTOPP_DEFINE_NAME_STRING(TableSize) //!< int, in bytes - -DOCUMENTED_NAMESPACE_END - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/asn.cpp b/embeddedcryptopp/asn.cpp deleted file mode 100644 index 3ebbaf7..0000000 --- a/embeddedcryptopp/asn.cpp +++ /dev/null @@ -1,595 +0,0 @@ -// asn.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "asn.h" - -#include -#include - -NAMESPACE_BEGIN(CryptoPP) -USING_NAMESPACE(std) - -/// DER Length -size_t DERLengthEncode(BufferedTransformation &bt, lword length) -{ - size_t i=0; - if (length <= 0x7f) - { - bt.Put(byte(length)); - i++; - } - else - { - bt.Put(byte(BytePrecision(length) | 0x80)); - i++; - for (int j=BytePrecision(length); j; --j) - { - bt.Put(byte(length >> (j-1)*8)); - i++; - } - } - return i; -} - -bool BERLengthDecode(BufferedTransformation &bt, lword &length, bool &definiteLength) -{ - byte b; - - if (!bt.Get(b)) - return false; - - if (!(b & 0x80)) - { - definiteLength = true; - length = b; - } - else - { - unsigned int lengthBytes = b & 0x7f; - - if (lengthBytes == 0) - { - definiteLength = false; - return true; - } - - definiteLength = true; - length = 0; - while (lengthBytes--) - { - if (length >> (8*(sizeof(length)-1))) - BERDecodeError(); // length about to overflow - - if (!bt.Get(b)) - return false; - - length = (length << 8) | b; - } - } - return true; -} - -bool BERLengthDecode(BufferedTransformation &bt, size_t &length) -{ - lword lw; - bool definiteLength; - if (!BERLengthDecode(bt, lw, definiteLength)) - BERDecodeError(); - if (!SafeConvert(lw, length)) - BERDecodeError(); - return definiteLength; -} - -void DEREncodeNull(BufferedTransformation &out) -{ - out.Put(TAG_NULL); - out.Put(0); -} - -void BERDecodeNull(BufferedTransformation &in) -{ - byte b; - if (!in.Get(b) || b != TAG_NULL) - BERDecodeError(); - size_t length; - if (!BERLengthDecode(in, length) || length != 0) - BERDecodeError(); -} - -/// ASN Strings -size_t DEREncodeOctetString(BufferedTransformation &bt, const byte *str, size_t strLen) -{ - bt.Put(OCTET_STRING); - size_t lengthBytes = DERLengthEncode(bt, strLen); - bt.Put(str, strLen); - return 1+lengthBytes+strLen; -} - -size_t DEREncodeOctetString(BufferedTransformation &bt, const SecByteBlock &str) -{ - return DEREncodeOctetString(bt, str.begin(), str.size()); -} - -size_t BERDecodeOctetString(BufferedTransformation &bt, SecByteBlock &str) -{ - byte b; - if (!bt.Get(b) || b != OCTET_STRING) - BERDecodeError(); - - size_t bc; - if (!BERLengthDecode(bt, bc)) - BERDecodeError(); - - str.resize(bc); - if (bc != bt.Get(str, bc)) - BERDecodeError(); - return bc; -} - -size_t BERDecodeOctetString(BufferedTransformation &bt, BufferedTransformation &str) -{ - byte b; - if (!bt.Get(b) || b != OCTET_STRING) - BERDecodeError(); - - size_t bc; - if (!BERLengthDecode(bt, bc)) - BERDecodeError(); - - bt.TransferTo(str, bc); - return bc; -} - -size_t DEREncodeTextString(BufferedTransformation &bt, const std::string &str, byte asnTag) -{ - bt.Put(asnTag); - size_t lengthBytes = DERLengthEncode(bt, str.size()); - bt.Put((const byte *)str.data(), str.size()); - return 1+lengthBytes+str.size(); -} - -size_t BERDecodeTextString(BufferedTransformation &bt, std::string &str, byte asnTag) -{ - byte b; - if (!bt.Get(b) || b != asnTag) - BERDecodeError(); - - size_t bc; - if (!BERLengthDecode(bt, bc)) - BERDecodeError(); - - SecByteBlock temp(bc); - if (bc != bt.Get(temp, bc)) - BERDecodeError(); - str.assign((char *)temp.begin(), bc); - return bc; -} - -/// ASN BitString -size_t DEREncodeBitString(BufferedTransformation &bt, const byte *str, size_t strLen, unsigned int unusedBits) -{ - bt.Put(BIT_STRING); - size_t lengthBytes = DERLengthEncode(bt, strLen+1); - bt.Put((byte)unusedBits); - bt.Put(str, strLen); - return 2+lengthBytes+strLen; -} - -size_t BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits) -{ - byte b; - if (!bt.Get(b) || b != BIT_STRING) - BERDecodeError(); - - size_t bc; - if (!BERLengthDecode(bt, bc)) - BERDecodeError(); - - byte unused; - if (!bt.Get(unused)) - BERDecodeError(); - unusedBits = unused; - str.resize(bc-1); - if ((bc-1) != bt.Get(str, bc-1)) - BERDecodeError(); - return bc-1; -} - -void DERReencode(BufferedTransformation &source, BufferedTransformation &dest) -{ - byte tag; - source.Peek(tag); - BERGeneralDecoder decoder(source, tag); - DERGeneralEncoder encoder(dest, tag); - if (decoder.IsDefiniteLength()) - decoder.TransferTo(encoder, decoder.RemainingLength()); - else - { - while (!decoder.EndReached()) - DERReencode(decoder, encoder); - } - decoder.MessageEnd(); - encoder.MessageEnd(); -} - -void OID::EncodeValue(BufferedTransformation &bt, word32 v) -{ - for (unsigned int i=RoundUpToMultipleOf(STDMAX(7U,BitPrecision(v)), 7U)-7; i != 0; i-=7) - bt.Put((byte)(0x80 | ((v >> i) & 0x7f))); - bt.Put((byte)(v & 0x7f)); -} - -size_t OID::DecodeValue(BufferedTransformation &bt, word32 &v) -{ - byte b; - size_t i=0; - v = 0; - while (true) - { - if (!bt.Get(b)) - BERDecodeError(); - i++; - v <<= 7; - v += b & 0x7f; - if (!(b & 0x80)) - return i; - } -} - -void OID::DEREncode(BufferedTransformation &bt) const -{ - assert(m_values.size() >= 2); - ByteQueue temp; - temp.Put(byte(m_values[0] * 40 + m_values[1])); - for (size_t i=2; i 0) - { - word32 v; - size_t valueLen = DecodeValue(bt, v); - if (valueLen > length) - BERDecodeError(); - m_values.push_back(v); - length -= valueLen; - } -} - -void OID::BERDecodeAndCheck(BufferedTransformation &bt) const -{ - OID oid(bt); - if (*this != oid) - BERDecodeError(); -} - -inline BufferedTransformation & EncodedObjectFilter::CurrentTarget() -{ - if (m_flags & PUT_OBJECTS) - return *AttachedTransformation(); - else - return TheBitBucket(); -} - -void EncodedObjectFilter::Put(const byte *inString, size_t length) -{ - if (m_nCurrentObject == m_nObjects) - { - AttachedTransformation()->Put(inString, length); - return; - } - - LazyPutter lazyPutter(m_queue, inString, length); - - while (m_queue.AnyRetrievable()) - { - switch (m_state) - { - case IDENTIFIER: - if (!m_queue.Get(m_id)) - return; - m_queue.TransferTo(CurrentTarget(), 1); - m_state = LENGTH; // fall through - case LENGTH: - { - byte b; - if (m_level > 0 && m_id == 0 && m_queue.Peek(b) && b == 0) - { - m_queue.TransferTo(CurrentTarget(), 1); - m_level--; - m_state = IDENTIFIER; - break; - } - ByteQueue::Walker walker(m_queue); - bool definiteLength; - if (!BERLengthDecode(walker, m_lengthRemaining, definiteLength)) - return; - m_queue.TransferTo(CurrentTarget(), walker.GetCurrentPosition()); - if (!((m_id & CONSTRUCTED) || definiteLength)) - BERDecodeError(); - if (!definiteLength) - { - if (!(m_id & CONSTRUCTED)) - BERDecodeError(); - m_level++; - m_state = IDENTIFIER; - break; - } - m_state = BODY; // fall through - } - case BODY: - m_lengthRemaining -= m_queue.TransferTo(CurrentTarget(), m_lengthRemaining); - - if (m_lengthRemaining == 0) - m_state = IDENTIFIER; - } - - if (m_state == IDENTIFIER && m_level == 0) - { - // just finished processing a level 0 object - ++m_nCurrentObject; - - if (m_flags & PUT_MESSANGE_END_AFTER_EACH_OBJECT) - AttachedTransformation()->MessageEnd(); - - if (m_nCurrentObject == m_nObjects) - { - if (m_flags & PUT_MESSANGE_END_AFTER_ALL_OBJECTS) - AttachedTransformation()->MessageEnd(); - - if (m_flags & PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS) - AttachedTransformation()->MessageSeriesEnd(); - - m_queue.TransferAllTo(*AttachedTransformation()); - return; - } - } - } -} - -BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag) - : m_inQueue(inQueue), m_finished(false) -{ - Init(asnTag); -} - -BERGeneralDecoder::BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag) - : m_inQueue(inQueue), m_finished(false) -{ - Init(asnTag); -} - -void BERGeneralDecoder::Init(byte asnTag) -{ - byte b; - if (!m_inQueue.Get(b) || b != asnTag) - BERDecodeError(); - - if (!BERLengthDecode(m_inQueue, m_length, m_definiteLength)) - BERDecodeError(); - - if (!m_definiteLength && !(asnTag & CONSTRUCTED)) - BERDecodeError(); // cannot be primitive and have indefinite length -} - -BERGeneralDecoder::~BERGeneralDecoder() -{ - try // avoid throwing in constructor - { - if (!m_finished) - MessageEnd(); - } - catch (...) - { - } -} - -bool BERGeneralDecoder::EndReached() const -{ - if (m_definiteLength) - return m_length == 0; - else - { // check end-of-content octets - word16 i; - return (m_inQueue.PeekWord16(i)==2 && i==0); - } -} - -byte BERGeneralDecoder::PeekByte() const -{ - byte b; - if (!Peek(b)) - BERDecodeError(); - return b; -} - -void BERGeneralDecoder::CheckByte(byte check) -{ - byte b; - if (!Get(b) || b != check) - BERDecodeError(); -} - -void BERGeneralDecoder::MessageEnd() -{ - m_finished = true; - if (m_definiteLength) - { - if (m_length != 0) - BERDecodeError(); - } - else - { // remove end-of-content octets - word16 i; - if (m_inQueue.GetWord16(i) != 2 || i != 0) - BERDecodeError(); - } -} - -size_t BERGeneralDecoder::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) -{ - if (m_definiteLength && transferBytes > m_length) - transferBytes = m_length; - size_t blockedBytes = m_inQueue.TransferTo2(target, transferBytes, channel, blocking); - ReduceLength(transferBytes); - return blockedBytes; -} - -size_t BERGeneralDecoder::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const -{ - if (m_definiteLength) - end = STDMIN(m_length, end); - return m_inQueue.CopyRangeTo2(target, begin, end, channel, blocking); -} - -lword BERGeneralDecoder::ReduceLength(lword delta) -{ - if (m_definiteLength) - { - if (m_length < delta) - BERDecodeError(); - m_length -= delta; - } - return delta; -} - -DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag) - : m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag) -{ -} - -DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag) - : m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag) -{ -} - -DERGeneralEncoder::~DERGeneralEncoder() -{ - try // avoid throwing in constructor - { - if (!m_finished) - MessageEnd(); - } - catch (...) - { - } -} - -void DERGeneralEncoder::MessageEnd() -{ - m_finished = true; - lword length = CurrentSize(); - m_outQueue.Put(m_asnTag); - DERLengthEncode(m_outQueue, length); - TransferTo(m_outQueue); -} - -// ************************************************************* - -void X509PublicKey::BERDecode(BufferedTransformation &bt) -{ - BERSequenceDecoder subjectPublicKeyInfo(bt); - BERSequenceDecoder algorithm(subjectPublicKeyInfo); - GetAlgorithmID().BERDecodeAndCheck(algorithm); - bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm); - algorithm.MessageEnd(); - - BERGeneralDecoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING); - subjectPublicKey.CheckByte(0); // unused bits - BERDecodePublicKey(subjectPublicKey, parametersPresent, (size_t)subjectPublicKey.RemainingLength()); - subjectPublicKey.MessageEnd(); - subjectPublicKeyInfo.MessageEnd(); -} - -void X509PublicKey::DEREncode(BufferedTransformation &bt) const -{ - DERSequenceEncoder subjectPublicKeyInfo(bt); - - DERSequenceEncoder algorithm(subjectPublicKeyInfo); - GetAlgorithmID().DEREncode(algorithm); - DEREncodeAlgorithmParameters(algorithm); - algorithm.MessageEnd(); - - DERGeneralEncoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING); - subjectPublicKey.Put(0); // unused bits - DEREncodePublicKey(subjectPublicKey); - subjectPublicKey.MessageEnd(); - - subjectPublicKeyInfo.MessageEnd(); -} - -void PKCS8PrivateKey::BERDecode(BufferedTransformation &bt) -{ - BERSequenceDecoder privateKeyInfo(bt); - word32 version; - BERDecodeUnsigned(privateKeyInfo, version, INTEGER, 0, 0); // check version - - BERSequenceDecoder algorithm(privateKeyInfo); - GetAlgorithmID().BERDecodeAndCheck(algorithm); - bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm); - algorithm.MessageEnd(); - - BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING); - BERDecodePrivateKey(octetString, parametersPresent, (size_t)privateKeyInfo.RemainingLength()); - octetString.MessageEnd(); - - if (!privateKeyInfo.EndReached()) - BERDecodeOptionalAttributes(privateKeyInfo); - privateKeyInfo.MessageEnd(); -} - -void PKCS8PrivateKey::DEREncode(BufferedTransformation &bt) const -{ - DERSequenceEncoder privateKeyInfo(bt); - DEREncodeUnsigned(privateKeyInfo, 0); // version - - DERSequenceEncoder algorithm(privateKeyInfo); - GetAlgorithmID().DEREncode(algorithm); - DEREncodeAlgorithmParameters(algorithm); - algorithm.MessageEnd(); - - DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING); - DEREncodePrivateKey(octetString); - octetString.MessageEnd(); - - DEREncodeOptionalAttributes(privateKeyInfo); - privateKeyInfo.MessageEnd(); -} - -void PKCS8PrivateKey::BERDecodeOptionalAttributes(BufferedTransformation &bt) -{ - DERReencode(bt, m_optionalAttributes); -} - -void PKCS8PrivateKey::DEREncodeOptionalAttributes(BufferedTransformation &bt) const -{ - m_optionalAttributes.CopyTo(bt); -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/asn.h b/embeddedcryptopp/asn.h deleted file mode 100644 index c35126b..0000000 --- a/embeddedcryptopp/asn.h +++ /dev/null @@ -1,369 +0,0 @@ -#ifndef CRYPTOPP_ASN_H -#define CRYPTOPP_ASN_H - -#include "filters.h" -#include "queue.h" -#include - -NAMESPACE_BEGIN(CryptoPP) - -// these tags and flags are not complete -enum ASNTag -{ - BOOLEAN = 0x01, - INTEGER = 0x02, - BIT_STRING = 0x03, - OCTET_STRING = 0x04, - TAG_NULL = 0x05, - OBJECT_IDENTIFIER = 0x06, - OBJECT_DESCRIPTOR = 0x07, - EXTERNAL = 0x08, - REAL = 0x09, - ENUMERATED = 0x0a, - UTF8_STRING = 0x0c, - SEQUENCE = 0x10, - SET = 0x11, - NUMERIC_STRING = 0x12, - PRINTABLE_STRING = 0x13, - T61_STRING = 0x14, - VIDEOTEXT_STRING = 0x15, - IA5_STRING = 0x16, - UTC_TIME = 0x17, - GENERALIZED_TIME = 0x18, - GRAPHIC_STRING = 0x19, - VISIBLE_STRING = 0x1a, - GENERAL_STRING = 0x1b -}; - -enum ASNIdFlag -{ - UNIVERSAL = 0x00, -// DATA = 0x01, -// HEADER = 0x02, - CONSTRUCTED = 0x20, - APPLICATION = 0x40, - CONTEXT_SPECIFIC = 0x80, - PRIVATE = 0xc0 -}; - -inline void BERDecodeError() {throw BERDecodeErr();} - -class CRYPTOPP_DLL UnknownOID : public BERDecodeErr -{ -public: - UnknownOID() : BERDecodeErr("BER decode error: unknown object identifier") {} - UnknownOID(const char *err) : BERDecodeErr(err) {} -}; - -// unsigned int DERLengthEncode(unsigned int length, byte *output=0); -CRYPTOPP_DLL size_t CRYPTOPP_API DERLengthEncode(BufferedTransformation &out, lword length); -// returns false if indefinite length -CRYPTOPP_DLL bool CRYPTOPP_API BERLengthDecode(BufferedTransformation &in, size_t &length); - -CRYPTOPP_DLL void CRYPTOPP_API DEREncodeNull(BufferedTransformation &out); -CRYPTOPP_DLL void CRYPTOPP_API BERDecodeNull(BufferedTransformation &in); - -CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &out, const byte *str, size_t strLen); -CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &out, const SecByteBlock &str); -CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &in, SecByteBlock &str); -CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &in, BufferedTransformation &str); - -// for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING -CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeTextString(BufferedTransformation &out, const std::string &str, byte asnTag); -CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeTextString(BufferedTransformation &in, std::string &str, byte asnTag); - -CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeBitString(BufferedTransformation &out, const byte *str, size_t strLen, unsigned int unusedBits=0); -CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeBitString(BufferedTransformation &in, SecByteBlock &str, unsigned int &unusedBits); - -// BER decode from source and DER reencode into dest -CRYPTOPP_DLL void CRYPTOPP_API DERReencode(BufferedTransformation &source, BufferedTransformation &dest); - -//! Object Identifier -class CRYPTOPP_DLL OID -{ -public: - OID() {} - OID(word32 v) : m_values(1, v) {} - OID(BufferedTransformation &bt) {BERDecode(bt);} - - inline OID & operator+=(word32 rhs) {m_values.push_back(rhs); return *this;} - - void DEREncode(BufferedTransformation &bt) const; - void BERDecode(BufferedTransformation &bt); - - // throw BERDecodeErr() if decoded value doesn't equal this OID - void BERDecodeAndCheck(BufferedTransformation &bt) const; - - std::vector m_values; - -private: - static void EncodeValue(BufferedTransformation &bt, word32 v); - static size_t DecodeValue(BufferedTransformation &bt, word32 &v); -}; - -class EncodedObjectFilter : public Filter -{ -public: - enum Flag {PUT_OBJECTS=1, PUT_MESSANGE_END_AFTER_EACH_OBJECT=2, PUT_MESSANGE_END_AFTER_ALL_OBJECTS=4, PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS=8}; - EncodedObjectFilter(BufferedTransformation *attachment = NULL, unsigned int nObjects = 1, word32 flags = 0); - - void Put(const byte *inString, size_t length); - - unsigned int GetNumberOfCompletedObjects() const {return m_nCurrentObject;} - unsigned long GetPositionOfObject(unsigned int i) const {return m_positions[i];} - -private: - BufferedTransformation & CurrentTarget(); - - word32 m_flags; - unsigned int m_nObjects, m_nCurrentObject, m_level; - std::vector m_positions; - ByteQueue m_queue; - enum State {IDENTIFIER, LENGTH, BODY, TAIL, ALL_DONE} m_state; - byte m_id; - lword m_lengthRemaining; -}; - -//! BER General Decoder -class CRYPTOPP_DLL BERGeneralDecoder : public Store -{ -public: - explicit BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag); - explicit BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag); - ~BERGeneralDecoder(); - - bool IsDefiniteLength() const {return m_definiteLength;} - lword RemainingLength() const {assert(m_definiteLength); return m_length;} - bool EndReached() const; - byte PeekByte() const; - void CheckByte(byte b); - - size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); - size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const; - - // call this to denote end of sequence - void MessageEnd(); - -protected: - BufferedTransformation &m_inQueue; - bool m_finished, m_definiteLength; - lword m_length; - -private: - void Init(byte asnTag); - void StoreInitialize(const NameValuePairs ¶meters) {assert(false);} - lword ReduceLength(lword delta); -}; - -//! DER General Encoder -class CRYPTOPP_DLL DERGeneralEncoder : public ByteQueue -{ -public: - explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED); - explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED); - ~DERGeneralEncoder(); - - // call this to denote end of sequence - void MessageEnd(); - -private: - BufferedTransformation &m_outQueue; - bool m_finished; - - byte m_asnTag; -}; - -//! BER Sequence Decoder -class CRYPTOPP_DLL BERSequenceDecoder : public BERGeneralDecoder -{ -public: - explicit BERSequenceDecoder(BufferedTransformation &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED) - : BERGeneralDecoder(inQueue, asnTag) {} - explicit BERSequenceDecoder(BERSequenceDecoder &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED) - : BERGeneralDecoder(inQueue, asnTag) {} -}; - -//! DER Sequence Encoder -class CRYPTOPP_DLL DERSequenceEncoder : public DERGeneralEncoder -{ -public: - explicit DERSequenceEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED) - : DERGeneralEncoder(outQueue, asnTag) {} - explicit DERSequenceEncoder(DERSequenceEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED) - : DERGeneralEncoder(outQueue, asnTag) {} -}; - -//! BER Set Decoder -class CRYPTOPP_DLL BERSetDecoder : public BERGeneralDecoder -{ -public: - explicit BERSetDecoder(BufferedTransformation &inQueue, byte asnTag = SET | CONSTRUCTED) - : BERGeneralDecoder(inQueue, asnTag) {} - explicit BERSetDecoder(BERSetDecoder &inQueue, byte asnTag = SET | CONSTRUCTED) - : BERGeneralDecoder(inQueue, asnTag) {} -}; - -//! DER Set Encoder -class CRYPTOPP_DLL DERSetEncoder : public DERGeneralEncoder -{ -public: - explicit DERSetEncoder(BufferedTransformation &outQueue, byte asnTag = SET | CONSTRUCTED) - : DERGeneralEncoder(outQueue, asnTag) {} - explicit DERSetEncoder(DERSetEncoder &outQueue, byte asnTag = SET | CONSTRUCTED) - : DERGeneralEncoder(outQueue, asnTag) {} -}; - -template -class ASNOptional : public member_ptr -{ -public: - void BERDecode(BERSequenceDecoder &seqDecoder, byte tag, byte mask = ~CONSTRUCTED) - { - byte b; - if (seqDecoder.Peek(b) && (b & mask) == tag) - reset(new T(seqDecoder)); - } - void DEREncode(BufferedTransformation &out) - { - if (this->get() != NULL) - this->get()->DEREncode(out); - } -}; - -//! _ -template -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1CryptoMaterial : public ASN1Object, public BASE -{ -public: - void Save(BufferedTransformation &bt) const - {BEREncode(bt);} - void Load(BufferedTransformation &bt) - {BERDecode(bt);} -}; - -//! encodes/decodes subjectPublicKeyInfo -class CRYPTOPP_DLL X509PublicKey : public ASN1CryptoMaterial -{ -public: - void BERDecode(BufferedTransformation &bt); - void DEREncode(BufferedTransformation &bt) const; - - virtual OID GetAlgorithmID() const =0; - virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt) - {BERDecodeNull(bt); return false;} - virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const - {DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1 - - //! decode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header - virtual void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0; - //! encode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header - virtual void DEREncodePublicKey(BufferedTransformation &bt) const =0; -}; - -//! encodes/decodes privateKeyInfo -class CRYPTOPP_DLL PKCS8PrivateKey : public ASN1CryptoMaterial -{ -public: - void BERDecode(BufferedTransformation &bt); - void DEREncode(BufferedTransformation &bt) const; - - virtual OID GetAlgorithmID() const =0; - virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt) - {BERDecodeNull(bt); return false;} - virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const - {DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1 - - //! decode privateKey part of privateKeyInfo, without the OCTET STRING header - virtual void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0; - //! encode privateKey part of privateKeyInfo, without the OCTET STRING header - virtual void DEREncodePrivateKey(BufferedTransformation &bt) const =0; - - //! decode optional attributes including context-specific tag - /*! /note default implementation stores attributes to be output in DEREncodeOptionalAttributes */ - virtual void BERDecodeOptionalAttributes(BufferedTransformation &bt); - //! encode optional attributes including context-specific tag - virtual void DEREncodeOptionalAttributes(BufferedTransformation &bt) const; - -protected: - ByteQueue m_optionalAttributes; -}; - -// ******************************************************** - -//! DER Encode Unsigned -/*! for INTEGER, BOOLEAN, and ENUM */ -template -size_t DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag = INTEGER) -{ - byte buf[sizeof(w)+1]; - unsigned int bc; - if (asnTag == BOOLEAN) - { - buf[sizeof(w)] = w ? 0xff : 0; - bc = 1; - } - else - { - buf[0] = 0; - for (unsigned int i=0; i> (sizeof(w)-1-i)*8); - bc = sizeof(w); - while (bc > 1 && buf[sizeof(w)+1-bc] == 0) - --bc; - if (buf[sizeof(w)+1-bc] & 0x80) - ++bc; - } - out.Put(asnTag); - size_t lengthBytes = DERLengthEncode(out, bc); - out.Put(buf+sizeof(w)+1-bc, bc); - return 1+lengthBytes+bc; -} - -//! BER Decode Unsigned -// VC60 workaround: std::numeric_limits::max conflicts with MFC max macro -// CW41 workaround: std::numeric_limits::max causes a template error -template -void BERDecodeUnsigned(BufferedTransformation &in, T &w, byte asnTag = INTEGER, - T minValue = 0, T maxValue = 0xffffffff) -{ - byte b; - if (!in.Get(b) || b != asnTag) - BERDecodeError(); - - size_t bc; - BERLengthDecode(in, bc); - - SecByteBlock buf(bc); - - if (bc != in.Get(buf, bc)) - BERDecodeError(); - - const byte *ptr = buf; - while (bc > sizeof(w) && *ptr == 0) - { - bc--; - ptr++; - } - if (bc > sizeof(w)) - BERDecodeError(); - - w = 0; - for (unsigned int i=0; i maxValue) - BERDecodeError(); -} - -inline bool operator==(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) - {return lhs.m_values == rhs.m_values;} -inline bool operator!=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) - {return lhs.m_values != rhs.m_values;} -inline bool operator<(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) - {return std::lexicographical_compare(lhs.m_values.begin(), lhs.m_values.end(), rhs.m_values.begin(), rhs.m_values.end());} -inline ::CryptoPP::OID operator+(const ::CryptoPP::OID &lhs, unsigned long rhs) - {return ::CryptoPP::OID(lhs)+=rhs;} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/authenc.h b/embeddedcryptopp/authenc.h deleted file mode 100644 index f726716..0000000 --- a/embeddedcryptopp/authenc.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef CRYPTOPP_AUTHENC_H -#define CRYPTOPP_AUTHENC_H - -#include "cryptlib.h" -#include "secblock.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! . -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedSymmetricCipherBase : public AuthenticatedSymmetricCipher -{ -public: - AuthenticatedSymmetricCipherBase() : m_state(State_Start) {} - - bool IsRandomAccess() const {return false;} - bool IsSelfInverting() const {return true;} - void UncheckedSetKey(const byte *,unsigned int,const CryptoPP::NameValuePairs &) {assert(false);} - - void SetKey(const byte *userKey, size_t keylength, const NameValuePairs ¶ms); - void Restart() {if (m_state > State_KeySet) m_state = State_KeySet;} - void Resynchronize(const byte *iv, int length=-1); - void Update(const byte *input, size_t length); - void ProcessData(byte *outString, const byte *inString, size_t length); - void TruncatedFinal(byte *mac, size_t macSize); - -protected: - void AuthenticateData(const byte *data, size_t len); - const SymmetricCipher & GetSymmetricCipher() const {return const_cast(this)->AccessSymmetricCipher();}; - - virtual SymmetricCipher & AccessSymmetricCipher() =0; - virtual bool AuthenticationIsOnPlaintext() const =0; - virtual unsigned int AuthenticationBlockSize() const =0; - virtual void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms) =0; - virtual void Resync(const byte *iv, size_t len) =0; - virtual size_t AuthenticateBlocks(const byte *data, size_t len) =0; - virtual void AuthenticateLastHeaderBlock() =0; - virtual void AuthenticateLastConfidentialBlock() {} - virtual void AuthenticateLastFooterBlock(byte *mac, size_t macSize) =0; - - enum State {State_Start, State_KeySet, State_IVSet, State_AuthUntransformed, State_AuthTransformed, State_AuthFooter}; - State m_state; - unsigned int m_bufferedDataLength; - lword m_totalHeaderLength, m_totalMessageLength, m_totalFooterLength; - AlignedSecByteBlock m_buffer; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/basecode.cpp b/embeddedcryptopp/basecode.cpp deleted file mode 100644 index 0c98b22..0000000 --- a/embeddedcryptopp/basecode.cpp +++ /dev/null @@ -1,238 +0,0 @@ -// basecode.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "basecode.h" -#include "fltrimpl.h" -#include - -NAMESPACE_BEGIN(CryptoPP) - -void BaseN_Encoder::IsolatedInitialize(const NameValuePairs ¶meters) -{ - parameters.GetRequiredParameter("BaseN_Encoder", Name::EncodingLookupArray(), m_alphabet); - - parameters.GetRequiredIntParameter("BaseN_Encoder", Name::Log2Base(), m_bitsPerChar); - if (m_bitsPerChar <= 0 || m_bitsPerChar >= 8) - throw InvalidArgument("BaseN_Encoder: Log2Base must be between 1 and 7 inclusive"); - - byte padding; - bool pad; - if (parameters.GetValue(Name::PaddingByte(), padding)) - pad = parameters.GetValueWithDefault(Name::Pad(), true); - else - pad = false; - m_padding = pad ? padding : -1; - - m_bytePos = m_bitPos = 0; - - int i = 8; - while (i%m_bitsPerChar != 0) - i += 8; - m_outputBlockSize = i/m_bitsPerChar; - - m_outBuf.New(m_outputBlockSize); -} - -size_t BaseN_Encoder::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) -{ - FILTER_BEGIN; - while (m_inputPosition < length) - { - if (m_bytePos == 0) - memset(m_outBuf, 0, m_outputBlockSize); - - { - unsigned int b = begin[m_inputPosition++], bitsLeftInSource = 8; - while (true) - { - assert(m_bitPos < m_bitsPerChar); - unsigned int bitsLeftInTarget = m_bitsPerChar-m_bitPos; - m_outBuf[m_bytePos] |= b >> (8-bitsLeftInTarget); - if (bitsLeftInSource >= bitsLeftInTarget) - { - m_bitPos = 0; - ++m_bytePos; - bitsLeftInSource -= bitsLeftInTarget; - if (bitsLeftInSource == 0) - break; - b <<= bitsLeftInTarget; - b &= 0xff; - } - else - { - m_bitPos += bitsLeftInSource; - break; - } - } - } - - assert(m_bytePos <= m_outputBlockSize); - if (m_bytePos == m_outputBlockSize) - { - int i; - for (i=0; i 0) - ++m_bytePos; - - int i; - for (i=0; i 0) - { - memset(m_outBuf+m_bytePos, m_padding, m_outputBlockSize-m_bytePos); - m_bytePos = m_outputBlockSize; - } - FILTER_OUTPUT(2, m_outBuf, m_bytePos, messageEnd); - m_bytePos = m_bitPos = 0; - } - FILTER_END_NO_MESSAGE_END; -} - -void BaseN_Decoder::IsolatedInitialize(const NameValuePairs ¶meters) -{ - parameters.GetRequiredParameter("BaseN_Decoder", Name::DecodingLookupArray(), m_lookup); - - parameters.GetRequiredIntParameter("BaseN_Decoder", Name::Log2Base(), m_bitsPerChar); - if (m_bitsPerChar <= 0 || m_bitsPerChar >= 8) - throw InvalidArgument("BaseN_Decoder: Log2Base must be between 1 and 7 inclusive"); - - m_bytePos = m_bitPos = 0; - - int i = m_bitsPerChar; - while (i%8 != 0) - i += m_bitsPerChar; - m_outputBlockSize = i/8; - - m_outBuf.New(m_outputBlockSize); -} - -size_t BaseN_Decoder::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) -{ - FILTER_BEGIN; - while (m_inputPosition < length) - { - unsigned int value; - value = m_lookup[begin[m_inputPosition++]]; - if (value >= 256) - continue; - - if (m_bytePos == 0 && m_bitPos == 0) - memset(m_outBuf, 0, m_outputBlockSize); - - { - int newBitPos = m_bitPos + m_bitsPerChar; - if (newBitPos <= 8) - m_outBuf[m_bytePos] |= value << (8-newBitPos); - else - { - m_outBuf[m_bytePos] |= value >> (newBitPos-8); - m_outBuf[m_bytePos+1] |= value << (16-newBitPos); - } - - m_bitPos = newBitPos; - while (m_bitPos >= 8) - { - m_bitPos -= 8; - ++m_bytePos; - } - } - - if (m_bytePos == m_outputBlockSize) - { - FILTER_OUTPUT(1, m_outBuf, m_outputBlockSize, 0); - m_bytePos = m_bitPos = 0; - } - } - if (messageEnd) - { - FILTER_OUTPUT(2, m_outBuf, m_bytePos, messageEnd); - m_bytePos = m_bitPos = 0; - } - FILTER_END_NO_MESSAGE_END; -} - -void BaseN_Decoder::InitializeDecodingLookupArray(int *lookup, const byte *alphabet, unsigned int base, bool caseInsensitive) -{ - std::fill(lookup, lookup+256, -1); - - for (unsigned int i=0; i -{ -public: - BaseN_Encoder(BufferedTransformation *attachment=NULL) - {Detach(attachment);} - - BaseN_Encoder(const byte *alphabet, int log2base, BufferedTransformation *attachment=NULL, int padding=-1) - { - Detach(attachment); - IsolatedInitialize(MakeParameters(Name::EncodingLookupArray(), alphabet) - (Name::Log2Base(), log2base) - (Name::Pad(), padding != -1) - (Name::PaddingByte(), byte(padding))); - } - - void IsolatedInitialize(const NameValuePairs ¶meters); - size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); - -private: - const byte *m_alphabet; - int m_padding, m_bitsPerChar, m_outputBlockSize; - int m_bytePos, m_bitPos; - SecByteBlock m_outBuf; -}; - -//! base n decoder, where n is a power of 2 -class CRYPTOPP_DLL BaseN_Decoder : public Unflushable -{ -public: - BaseN_Decoder(BufferedTransformation *attachment=NULL) - {Detach(attachment);} - - BaseN_Decoder(const int *lookup, int log2base, BufferedTransformation *attachment=NULL) - { - Detach(attachment); - IsolatedInitialize(MakeParameters(Name::DecodingLookupArray(), lookup)(Name::Log2Base(), log2base)); - } - - void IsolatedInitialize(const NameValuePairs ¶meters); - size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); - - static void CRYPTOPP_API InitializeDecodingLookupArray(int *lookup, const byte *alphabet, unsigned int base, bool caseInsensitive); - -private: - const int *m_lookup; - int m_padding, m_bitsPerChar, m_outputBlockSize; - int m_bytePos, m_bitPos; - SecByteBlock m_outBuf; -}; - -//! filter that breaks input stream into groups of fixed size -class CRYPTOPP_DLL Grouper : public Bufferless -{ -public: - Grouper(BufferedTransformation *attachment=NULL) - {Detach(attachment);} - - Grouper(int groupSize, const std::string &separator, const std::string &terminator, BufferedTransformation *attachment=NULL) - { - Detach(attachment); - IsolatedInitialize(MakeParameters(Name::GroupSize(), groupSize) - (Name::Separator(), ConstByteArrayParameter(separator)) - (Name::Terminator(), ConstByteArrayParameter(terminator))); - } - - void IsolatedInitialize(const NameValuePairs ¶meters); - size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); - -private: - SecByteBlock m_separator, m_terminator; - size_t m_groupSize, m_counter; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/cbcmac.h b/embeddedcryptopp/cbcmac.h deleted file mode 100644 index 4675dcb..0000000 --- a/embeddedcryptopp/cbcmac.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef CRYPTOPP_CBCMAC_H -#define CRYPTOPP_CBCMAC_H - -#include "seckey.h" -#include "secblock.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! _ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_MAC_Base : public MessageAuthenticationCode -{ -public: - CBC_MAC_Base() {} - - void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); - void Update(const byte *input, size_t length); - void TruncatedFinal(byte *mac, size_t size); - unsigned int DigestSize() const {return const_cast(this)->AccessCipher().BlockSize();} - -protected: - virtual BlockCipher & AccessCipher() =0; - -private: - void ProcessBuf(); - SecByteBlock m_reg; - unsigned int m_counter; -}; - -//! CBC-MAC -/*! Compatible with FIPS 113. T should be a class derived from BlockCipherDocumentation. - Secure only for fixed length messages. For variable length messages use CMAC or DMAC. -*/ -template -class CBC_MAC : public MessageAuthenticationCodeImpl >, public SameKeyLengthAs -{ -public: - CBC_MAC() {} - CBC_MAC(const byte *key, size_t length=SameKeyLengthAs::DEFAULT_KEYLENGTH) - {this->SetKey(key, length);} - - static std::string StaticAlgorithmName() {return std::string("CBC-MAC(") + T::StaticAlgorithmName() + ")";} - -private: - BlockCipher & AccessCipher() {return m_cipher;} - typename T::Encryption m_cipher; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/ccm.h b/embeddedcryptopp/ccm.h deleted file mode 100644 index 2f3c56b..0000000 --- a/embeddedcryptopp/ccm.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef CRYPTOPP_CCM_H -#define CRYPTOPP_CCM_H - -#include "authenc.h" -#include "modes.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! . -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CCM_Base : public AuthenticatedSymmetricCipherBase -{ -public: - CCM_Base() - : m_digestSize(0), m_L(0) {} - - // AuthenticatedSymmetricCipher - std::string AlgorithmName() const - {return GetBlockCipher().AlgorithmName() + std::string("/CCM");} - size_t MinKeyLength() const - {return GetBlockCipher().MinKeyLength();} - size_t MaxKeyLength() const - {return GetBlockCipher().MaxKeyLength();} - size_t DefaultKeyLength() const - {return GetBlockCipher().DefaultKeyLength();} - size_t GetValidKeyLength(size_t n) const - {return GetBlockCipher().GetValidKeyLength(n);} - bool IsValidKeyLength(size_t n) const - {return GetBlockCipher().IsValidKeyLength(n);} - unsigned int OptimalDataAlignment() const - {return GetBlockCipher().OptimalDataAlignment();} - IV_Requirement IVRequirement() const - {return UNIQUE_IV;} - unsigned int IVSize() const - {return 8;} - unsigned int MinIVLength() const - {return 7;} - unsigned int MaxIVLength() const - {return 13;} - unsigned int DigestSize() const - {return m_digestSize;} - lword MaxHeaderLength() const - {return W64LIT(0)-1;} - lword MaxMessageLength() const - {return m_L<8 ? (W64LIT(1)<<(8*m_L))-1 : W64LIT(0)-1;} - bool NeedsPrespecifiedDataLengths() const - {return true;} - void UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength); - -protected: - // AuthenticatedSymmetricCipherBase - bool AuthenticationIsOnPlaintext() const - {return true;} - unsigned int AuthenticationBlockSize() const - {return GetBlockCipher().BlockSize();} - void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms); - void Resync(const byte *iv, size_t len); - size_t AuthenticateBlocks(const byte *data, size_t len); - void AuthenticateLastHeaderBlock(); - void AuthenticateLastConfidentialBlock(); - void AuthenticateLastFooterBlock(byte *mac, size_t macSize); - SymmetricCipher & AccessSymmetricCipher() {return m_ctr;} - - virtual BlockCipher & AccessBlockCipher() =0; - virtual int DefaultDigestSize() const =0; - - const BlockCipher & GetBlockCipher() const {return const_cast(this)->AccessBlockCipher();}; - byte *CBC_Buffer() {return m_buffer+REQUIRED_BLOCKSIZE;} - - enum {REQUIRED_BLOCKSIZE = 16}; - int m_digestSize, m_L; - word64 m_messageLength, m_aadLength; - CTR_Mode_ExternalCipher::Encryption m_ctr; -}; - -//! . -template -class CCM_Final : public CCM_Base -{ -public: - static std::string StaticAlgorithmName() - {return T_BlockCipher::StaticAlgorithmName() + std::string("/CCM");} - bool IsForwardTransformation() const - {return T_IsEncryption;} - -private: - BlockCipher & AccessBlockCipher() {return m_cipher;} - int DefaultDigestSize() const {return T_DefaultDigestSize;} - typename T_BlockCipher::Encryption m_cipher; -}; - -/// CCM -template -struct CCM : public AuthenticatedSymmetricCipherDocumentation -{ - typedef CCM_Final Encryption; - typedef CCM_Final Decryption; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/channels.h b/embeddedcryptopp/channels.h deleted file mode 100644 index 8374156..0000000 --- a/embeddedcryptopp/channels.h +++ /dev/null @@ -1,123 +0,0 @@ -#ifndef CRYPTOPP_CHANNELS_H -#define CRYPTOPP_CHANNELS_H - -#include "simple.h" -#include "smartptr.h" -#include -#include - -NAMESPACE_BEGIN(CryptoPP) - -#if 0 -//! Route input on default channel to different and/or multiple channels based on message sequence number -class MessageSwitch : public Sink -{ -public: - void AddDefaultRoute(BufferedTransformation &destination, const std::string &channel); - void AddRoute(unsigned int begin, unsigned int end, BufferedTransformation &destination, const std::string &channel); - - void Put(byte inByte); - void Put(const byte *inString, unsigned int length); - - void Flush(bool completeFlush, int propagation=-1); - void MessageEnd(int propagation=-1); - void PutMessageEnd(const byte *inString, unsigned int length, int propagation=-1); - void MessageSeriesEnd(int propagation=-1); - -private: - typedef std::pair Route; - struct RangeRoute - { - RangeRoute(unsigned int begin, unsigned int end, const Route &route) - : begin(begin), end(end), route(route) {} - bool operator<(const RangeRoute &rhs) const {return begin < rhs.begin;} - unsigned int begin, end; - Route route; - }; - - typedef std::list RouteList; - typedef std::list DefaultRouteList; - - RouteList m_routes; - DefaultRouteList m_defaultRoutes; - unsigned int m_nCurrentMessage; -}; -#endif - -class ChannelSwitchTypedefs -{ -public: - typedef std::pair Route; - typedef std::multimap RouteMap; - - typedef std::pair > DefaultRoute; - typedef std::list DefaultRouteList; - - // SunCC workaround: can't use const_iterator here - typedef RouteMap::iterator MapIterator; - typedef DefaultRouteList::iterator ListIterator; -}; - -class ChannelSwitch; - -class ChannelRouteIterator : public ChannelSwitchTypedefs -{ -public: - ChannelSwitch& m_cs; - std::string m_channel; - bool m_useDefault; - MapIterator m_itMapCurrent, m_itMapEnd; - ListIterator m_itListCurrent, m_itListEnd; - - ChannelRouteIterator(ChannelSwitch &cs) : m_cs(cs) {} - void Reset(const std::string &channel); - bool End() const; - void Next(); - BufferedTransformation & Destination(); - const std::string & Channel(); -}; - -//! Route input to different and/or multiple channels based on channel ID -class CRYPTOPP_DLL ChannelSwitch : public Multichannel, public ChannelSwitchTypedefs -{ -public: - ChannelSwitch() : m_it(*this), m_blocked(false) {} - ChannelSwitch(BufferedTransformation &destination) : m_it(*this), m_blocked(false) - { - AddDefaultRoute(destination); - } - ChannelSwitch(BufferedTransformation &destination, const std::string &outChannel) : m_it(*this), m_blocked(false) - { - AddDefaultRoute(destination, outChannel); - } - - void IsolatedInitialize(const NameValuePairs ¶meters=g_nullNameValuePairs); - - size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking); - size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking); - - bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true); - bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true); - - byte * ChannelCreatePutSpace(const std::string &channel, size_t &size); - - void AddDefaultRoute(BufferedTransformation &destination); - void RemoveDefaultRoute(BufferedTransformation &destination); - void AddDefaultRoute(BufferedTransformation &destination, const std::string &outChannel); - void RemoveDefaultRoute(BufferedTransformation &destination, const std::string &outChannel); - void AddRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel); - void RemoveRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel); - -private: - RouteMap m_routeMap; - DefaultRouteList m_defaultRoutes; - - ChannelRouteIterator m_it; - bool m_blocked; - - friend class ChannelRouteIterator; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/cmac.h b/embeddedcryptopp/cmac.h deleted file mode 100644 index ab3ecf8..0000000 --- a/embeddedcryptopp/cmac.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef CRYPTOPP_CMAC_H -#define CRYPTOPP_CMAC_H - -#include "seckey.h" -#include "secblock.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! _ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CMAC_Base : public MessageAuthenticationCode -{ -public: - CMAC_Base() {} - - void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); - void Update(const byte *input, size_t length); - void TruncatedFinal(byte *mac, size_t size); - unsigned int DigestSize() const {return GetCipher().BlockSize();} - unsigned int OptimalBlockSize() const {return GetCipher().BlockSize();} - unsigned int OptimalDataAlignment() const {return GetCipher().OptimalDataAlignment();} - -protected: - friend class EAX_Base; - - const BlockCipher & GetCipher() const {return const_cast(this)->AccessCipher();} - virtual BlockCipher & AccessCipher() =0; - - void ProcessBuf(); - SecByteBlock m_reg; - unsigned int m_counter; -}; - -/// CMAC -/*! Template parameter T should be a class derived from BlockCipherDocumentation, for example AES, with a block size of 8, 16, or 32 */ -template -class CMAC : public MessageAuthenticationCodeImpl >, public SameKeyLengthAs -{ -public: - CMAC() {} - CMAC(const byte *key, size_t length=SameKeyLengthAs::DEFAULT_KEYLENGTH) - {this->SetKey(key, length);} - - static std::string StaticAlgorithmName() {return std::string("CMAC(") + T::StaticAlgorithmName() + ")";} - -private: - BlockCipher & AccessCipher() {return m_cipher;} - typename T::Encryption m_cipher; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/config.h b/embeddedcryptopp/config.h deleted file mode 100644 index 4cab816..0000000 --- a/embeddedcryptopp/config.h +++ /dev/null @@ -1,457 +0,0 @@ -#ifndef CRYPTOPP_CONFIG_H -#define CRYPTOPP_CONFIG_H - -// ***************** Important Settings ******************** - -// define this if running on a big-endian CPU -#if !defined(IS_LITTLE_ENDIAN) && (defined(__BIG_ENDIAN__) || defined(__sparc) || defined(__sparc__) || defined(__hppa__) || defined(__mips__) || (defined(__MWERKS__) && !defined(__INTEL__))) -# define IS_BIG_ENDIAN -#endif - -// define this if running on a little-endian CPU -// big endian will be assumed if IS_LITTLE_ENDIAN is not defined -#ifndef IS_BIG_ENDIAN -# define IS_LITTLE_ENDIAN -#endif - -// define this if you want to disable all OS-dependent features, -// such as sockets and OS-provided random number generators -// #define NO_OS_DEPENDENCE - -// Define this to use features provided by Microsoft's CryptoAPI. -// Currently the only feature used is random number generation. -// This macro will be ignored if NO_OS_DEPENDENCE is defined. -#define USE_MS_CRYPTOAPI - -// Define this to 1 to enforce the requirement in FIPS 186-2 Change Notice 1 that only 1024 bit moduli be used -#ifndef DSA_1024_BIT_MODULUS_ONLY -# define DSA_1024_BIT_MODULUS_ONLY 1 -#endif - -// ***************** Less Important Settings *************** - -// define this to retain (as much as possible) old deprecated function and class names -// #define CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY - -#define GZIP_OS_CODE 0 - -// Try this if your CPU has 256K internal cache or a slow multiply instruction -// and you want a (possibly) faster IDEA implementation using log tables -// #define IDEA_LARGECACHE - -// Define this if, for the linear congruential RNG, you want to use -// the original constants as specified in S.K. Park and K.W. Miller's -// CACM paper. -// #define LCRNG_ORIGINAL_NUMBERS - -// choose which style of sockets to wrap (mostly useful for cygwin which has both) -#define PREFER_BERKELEY_STYLE_SOCKETS -// #define PREFER_WINDOWS_STYLE_SOCKETS - -// set the name of Rijndael cipher, was "Rijndael" before version 5.3 -#define CRYPTOPP_RIJNDAEL_NAME "AES" - -// ***************** Important Settings Again ******************** -// But the defaults should be ok. - -// namespace support is now required -#ifdef NO_NAMESPACE -# error namespace support is now required -#endif - -// Define this to workaround a Microsoft CryptoAPI bug where -// each call to CryptAcquireContext causes a 100 KB memory leak. -// Defining this will cause Crypto++ to make only one call to CryptAcquireContext. -#define WORKAROUND_MS_BUG_Q258000 - -#ifdef CRYPTOPP_DOXYGEN_PROCESSING -// Avoid putting "CryptoPP::" in front of everything in Doxygen output -# define CryptoPP -# define NAMESPACE_BEGIN(x) -# define NAMESPACE_END -// Get Doxygen to generate better documentation for these typedefs -# define DOCUMENTED_TYPEDEF(x, y) class y : public x {}; -#else -# define NAMESPACE_BEGIN(x) namespace x { -# define NAMESPACE_END } -# define DOCUMENTED_TYPEDEF(x, y) typedef x y; -#endif -#define ANONYMOUS_NAMESPACE_BEGIN namespace { -#define USING_NAMESPACE(x) using namespace x; -#define DOCUMENTED_NAMESPACE_BEGIN(x) namespace x { -#define DOCUMENTED_NAMESPACE_END } - -// What is the type of the third parameter to bind? -// For Unix, the new standard is ::socklen_t (typically unsigned int), and the old standard is int. -// Unfortunately there is no way to tell whether or not socklen_t is defined. -// To work around this, TYPE_OF_SOCKLEN_T is a macro so that you can change it from the makefile. -#ifndef TYPE_OF_SOCKLEN_T -# if defined(_WIN32) || defined(__CYGWIN__) -# define TYPE_OF_SOCKLEN_T int -# else -# define TYPE_OF_SOCKLEN_T ::socklen_t -# endif -#endif - -#if defined(__CYGWIN__) && defined(PREFER_WINDOWS_STYLE_SOCKETS) -# define __USE_W32_SOCKETS -#endif - -typedef unsigned char byte; // put in global namespace to avoid ambiguity with other byte typedefs - -NAMESPACE_BEGIN(CryptoPP) - -typedef unsigned short word16; -typedef unsigned int word32; - -#if defined(_MSC_VER) || defined(__BORLANDC__) - typedef unsigned __int64 word64; - #define W64LIT(x) x##ui64 -#else - typedef unsigned long long word64; - #define W64LIT(x) x##ULL -#endif - -// define large word type, used for file offsets and such -typedef word64 lword; -const lword LWORD_MAX = W64LIT(0xffffffffffffffff); - -#ifdef __GNUC__ - #define CRYPTOPP_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -#endif - -// define hword, word, and dword. these are used for multiprecision integer arithmetic -// Intel compiler won't have _umul128 until version 10.0. See http://softwarecommunity.intel.com/isn/Community/en-US/forums/thread/30231625.aspx -#if (defined(_MSC_VER) && (!defined(__INTEL_COMPILER) || __INTEL_COMPILER >= 1000) && (defined(_M_X64) || defined(_M_IA64))) || (defined(__DECCXX) && defined(__alpha__)) || (defined(__INTEL_COMPILER) && defined(__x86_64__)) || (defined(__SUNPRO_CC) && defined(__x86_64__)) - typedef word32 hword; - typedef word64 word; -#else - #define CRYPTOPP_NATIVE_DWORD_AVAILABLE - #if defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || defined(__x86_64__) || defined(__mips64) || defined(__sparc64__) - #if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !(CRYPTOPP_GCC_VERSION == 40001 && defined(__APPLE__)) && CRYPTOPP_GCC_VERSION >= 30400 - // GCC 4.0.1 on MacOS X is missing __umodti3 and __udivti3 - // mode(TI) division broken on amd64 with GCC earlier than GCC 3.4 - typedef word32 hword; - typedef word64 word; - typedef __uint128_t dword; - typedef __uint128_t word128; - #define CRYPTOPP_WORD128_AVAILABLE - #else - // if we're here, it means we're on a 64-bit CPU but we don't have a way to obtain 128-bit multiplication results - typedef word16 hword; - typedef word32 word; - typedef word64 dword; - #endif - #else - // being here means the native register size is probably 32 bits or less - #define CRYPTOPP_BOOL_SLOW_WORD64 1 - typedef word16 hword; - typedef word32 word; - typedef word64 dword; - #endif -#endif -#ifndef CRYPTOPP_BOOL_SLOW_WORD64 - #define CRYPTOPP_BOOL_SLOW_WORD64 0 -#endif - -const unsigned int WORD_SIZE = sizeof(word); -const unsigned int WORD_BITS = WORD_SIZE * 8; - -NAMESPACE_END - -#ifndef CRYPTOPP_L1_CACHE_LINE_SIZE - // This should be a lower bound on the L1 cache line size. It's used for defense against timing attacks. - #if defined(_M_X64) || defined(__x86_64__) - #define CRYPTOPP_L1_CACHE_LINE_SIZE 64 - #else - // L1 cache line size is 32 on Pentium III and earlier - #define CRYPTOPP_L1_CACHE_LINE_SIZE 32 - #endif -#endif - -#if defined(_MSC_VER) - #if _MSC_VER == 1200 - #include - #endif - #if _MSC_VER > 1200 || defined(_mm_free) - #define CRYPTOPP_MSVC6PP_OR_LATER // VC 6 processor pack or later - #else - #define CRYPTOPP_MSVC6_NO_PP // VC 6 without processor pack - #endif -#endif - -#ifndef CRYPTOPP_ALIGN_DATA - #if defined(CRYPTOPP_MSVC6PP_OR_LATER) - #define CRYPTOPP_ALIGN_DATA(x) __declspec(align(x)) - #elif defined(__GNUC__) - #define CRYPTOPP_ALIGN_DATA(x) __attribute__((aligned(x))) - #else - #define CRYPTOPP_ALIGN_DATA(x) - #endif -#endif - -#ifndef CRYPTOPP_SECTION_ALIGN16 - #if defined(__GNUC__) && !defined(__APPLE__) - // the alignment attribute doesn't seem to work without this section attribute when -fdata-sections is turned on - #define CRYPTOPP_SECTION_ALIGN16 __attribute__((section ("CryptoPP_Align16"))) - #else - #define CRYPTOPP_SECTION_ALIGN16 - #endif -#endif - -#if defined(_MSC_VER) || defined(__fastcall) - #define CRYPTOPP_FASTCALL __fastcall -#else - #define CRYPTOPP_FASTCALL -#endif - -// VC60 workaround: it doesn't allow typename in some places -#if defined(_MSC_VER) && (_MSC_VER < 1300) -#define CPP_TYPENAME -#else -#define CPP_TYPENAME typename -#endif - -// VC60 workaround: can't cast unsigned __int64 to float or double -#if defined(_MSC_VER) && !defined(CRYPTOPP_MSVC6PP_OR_LATER) -#define CRYPTOPP_VC6_INT64 (__int64) -#else -#define CRYPTOPP_VC6_INT64 -#endif - -#ifdef _MSC_VER -#define CRYPTOPP_NO_VTABLE __declspec(novtable) -#else -#define CRYPTOPP_NO_VTABLE -#endif - -#ifdef _MSC_VER - // 4231: nonstandard extension used : 'extern' before template explicit instantiation - // 4250: dominance - // 4251: member needs to have dll-interface - // 4275: base needs to have dll-interface - // 4660: explicitly instantiating a class that's already implicitly instantiated - // 4661: no suitable definition provided for explicit template instantiation request - // 4786: identifer was truncated in debug information - // 4355: 'this' : used in base member initializer list - // 4910: '__declspec(dllexport)' and 'extern' are incompatible on an explicit instantiation -# pragma warning(disable: 4231 4250 4251 4275 4660 4661 4786 4355 4910) -#endif - -#ifdef __BORLANDC__ -// 8037: non-const function called for const object. needed to work around BCB2006 bug -# pragma warn -8037 -#endif - -#if (defined(_MSC_VER) && _MSC_VER <= 1300) || defined(__MWERKS__) || defined(_STLPORT_VERSION) -#define CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION -#endif - -#ifndef CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION -#define CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE -#endif - -#ifdef CRYPTOPP_DISABLE_X86ASM // for backwards compatibility: this macro had both meanings -#define CRYPTOPP_DISABLE_ASM -#define CRYPTOPP_DISABLE_SSE2 -#endif - -#if !defined(CRYPTOPP_DISABLE_ASM) && ((defined(_MSC_VER) && defined(_M_IX86)) || (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))) - #define CRYPTOPP_X86_ASM_AVAILABLE - - #if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(CRYPTOPP_MSVC6PP_OR_LATER) || CRYPTOPP_GCC_VERSION >= 30300) - #define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 1 - #else - #define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 0 - #endif - - // SSSE3 was actually introduced in GNU as 2.17, which was released 6/23/2006, but we can't tell what version of binutils is installed. - // GCC 4.1.2 was released on 2/13/2007, so we'll use that as a proxy for the binutils version. - #if !defined(CRYPTOPP_DISABLE_SSSE3) && (_MSC_VER >= 1400 || CRYPTOPP_GCC_VERSION >= 40102) - #define CRYPTOPP_BOOL_SSSE3_ASM_AVAILABLE 1 - #else - #define CRYPTOPP_BOOL_SSSE3_ASM_AVAILABLE 0 - #endif -#endif - -#if !defined(CRYPTOPP_DISABLE_ASM) && defined(_MSC_VER) && defined(_M_X64) - #define CRYPTOPP_X64_MASM_AVAILABLE -#endif - -#if !defined(CRYPTOPP_DISABLE_ASM) && defined(__GNUC__) && defined(__x86_64__) - #define CRYPTOPP_X64_ASM_AVAILABLE -#endif - -#if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(CRYPTOPP_MSVC6PP_OR_LATER) || defined(__SSE2__)) - #define CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 1 -#else - #define CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 0 -#endif - -#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE) - #define CRYPTOPP_BOOL_ALIGN16_ENABLED 1 -#else - #define CRYPTOPP_BOOL_ALIGN16_ENABLED 0 -#endif - -// how to allocate 16-byte aligned memory (for SSE2) -#if defined(CRYPTOPP_MSVC6PP_OR_LATER) - #define CRYPTOPP_MM_MALLOC_AVAILABLE -#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) - #define CRYPTOPP_MALLOC_ALIGNMENT_IS_16 -#elif defined(__linux__) || defined(__sun__) || defined(__CYGWIN__) - #define CRYPTOPP_MEMALIGN_AVAILABLE -#else - #define CRYPTOPP_NO_ALIGNED_ALLOC -#endif - -// how to disable inlining -#if defined(_MSC_VER) && _MSC_VER >= 1300 -# define CRYPTOPP_NOINLINE_DOTDOTDOT -# define CRYPTOPP_NOINLINE __declspec(noinline) -#elif defined(__GNUC__) -# define CRYPTOPP_NOINLINE_DOTDOTDOT -# define CRYPTOPP_NOINLINE __attribute__((noinline)) -#else -# define CRYPTOPP_NOINLINE_DOTDOTDOT ... -# define CRYPTOPP_NOINLINE -#endif - -// how to declare class constants -#if (defined(_MSC_VER) && _MSC_VER <= 1300) || defined(__INTEL_COMPILER) -# define CRYPTOPP_CONSTANT(x) enum {x}; -#else -# define CRYPTOPP_CONSTANT(x) static const int x; -#endif - -#if defined(_M_X64) || defined(__x86_64__) - #define CRYPTOPP_BOOL_X64 1 -#else - #define CRYPTOPP_BOOL_X64 0 -#endif - -// see http://predef.sourceforge.net/prearch.html -#if defined(_M_IX86) || defined(__i386__) || defined(__i386) || defined(_X86_) || defined(__I86__) || defined(__INTEL__) - #define CRYPTOPP_BOOL_X86 1 -#else - #define CRYPTOPP_BOOL_X86 0 -#endif - -#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86 || defined(__powerpc__) - #define CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS -#endif - -#define CRYPTOPP_VERSION 560 - -#include "extraversion.h" - -// ***************** determine availability of OS features ******************** - -#ifndef NO_OS_DEPENDENCE - -#if defined(_WIN32) || defined(__CYGWIN__) -#define CRYPTOPP_WIN32_AVAILABLE -#endif - -#if defined(__unix__) || defined(__MACH__) || defined(__NetBSD__) || defined(__sun) -#define CRYPTOPP_UNIX_AVAILABLE -#endif - -#if defined(CRYPTOPP_WIN32_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE) -# define HIGHRES_TIMER_AVAILABLE -#endif - -#ifdef CRYPTOPP_UNIX_AVAILABLE -# define HAS_BERKELEY_STYLE_SOCKETS -#endif - -#ifdef CRYPTOPP_WIN32_AVAILABLE -# define HAS_WINDOWS_STYLE_SOCKETS -#endif - -#if defined(HIGHRES_TIMER_AVAILABLE) && (defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(HAS_WINDOWS_STYLE_SOCKETS)) -# define SOCKETS_AVAILABLE -#endif - -#if defined(HAS_WINDOWS_STYLE_SOCKETS) && (!defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(PREFER_WINDOWS_STYLE_SOCKETS)) -# define USE_WINDOWS_STYLE_SOCKETS -#else -# define USE_BERKELEY_STYLE_SOCKETS -#endif - -#if defined(HIGHRES_TIMER_AVAILABLE) && defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(USE_BERKELEY_STYLE_SOCKETS) -# define WINDOWS_PIPES_AVAILABLE -#endif - -#if defined(CRYPTOPP_WIN32_AVAILABLE) && defined(USE_MS_CRYPTOAPI) -# define NONBLOCKING_RNG_AVAILABLE -# define OS_RNG_AVAILABLE -#endif - -#if defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING) -# define NONBLOCKING_RNG_AVAILABLE -# define BLOCKING_RNG_AVAILABLE -# define OS_RNG_AVAILABLE -# define HAS_PTHREADS -# define THREADS_AVAILABLE -#endif - -#ifdef CRYPTOPP_WIN32_AVAILABLE -# define HAS_WINTHREADS -# define THREADS_AVAILABLE -#endif - -#endif // NO_OS_DEPENDENCE - -// ***************** DLL related ******************** - -#ifdef CRYPTOPP_WIN32_AVAILABLE - -#ifdef CRYPTOPP_EXPORTS -#define CRYPTOPP_IS_DLL -#define CRYPTOPP_DLL __declspec(dllexport) -#elif defined(CRYPTOPP_IMPORTS) -#define CRYPTOPP_IS_DLL -#define CRYPTOPP_DLL __declspec(dllimport) -#else -#define CRYPTOPP_DLL -#endif - -#define CRYPTOPP_API __cdecl - -#else // CRYPTOPP_WIN32_AVAILABLE - -#define CRYPTOPP_DLL -#define CRYPTOPP_API - -#endif // CRYPTOPP_WIN32_AVAILABLE - -#if defined(__MWERKS__) -#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern class CRYPTOPP_DLL -#elif defined(__BORLANDC__) || defined(__SUNPRO_CC) -#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL -#else -#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern template class CRYPTOPP_DLL -#endif - -#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_IMPORTS) -#define CRYPTOPP_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL -#else -#define CRYPTOPP_DLL_TEMPLATE_CLASS CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS -#endif - -#if defined(__MWERKS__) -#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern class -#elif defined(__BORLANDC__) || defined(__SUNPRO_CC) -#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS template class -#else -#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern template class -#endif - -#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_EXPORTS) -#define CRYPTOPP_STATIC_TEMPLATE_CLASS template class -#else -#define CRYPTOPP_STATIC_TEMPLATE_CLASS CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS -#endif - -#endif diff --git a/embeddedcryptopp/cpu.cpp b/embeddedcryptopp/cpu.cpp deleted file mode 100644 index 3e46804..0000000 --- a/embeddedcryptopp/cpu.cpp +++ /dev/null @@ -1,199 +0,0 @@ -// cpu.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "cpu.h" -#include "misc.h" -#include - -#ifdef __GNUC__ -#include -#include -#endif - -#ifdef CRYPTOPP_MSVC6PP_OR_LATER -#include -#endif - -NAMESPACE_BEGIN(CryptoPP) - -#ifdef CRYPTOPP_X86_ASM_AVAILABLE - -#ifndef _MSC_VER -typedef void (*SigHandler)(int); - -static jmp_buf s_jmpNoCPUID; -static void SigIllHandlerCPUID(int) -{ - longjmp(s_jmpNoCPUID, 1); -} -#endif - -bool CpuId(word32 input, word32 *output) -{ -#ifdef _MSC_VER - __try - { - __asm - { - mov eax, input - cpuid - mov edi, output - mov [edi], eax - mov [edi+4], ebx - mov [edi+8], ecx - mov [edi+12], edx - } - } - __except (1) - { - return false; - } - return true; -#else - SigHandler oldHandler = signal(SIGILL, SigIllHandlerCPUID); - if (oldHandler == SIG_ERR) - return false; - - bool result = true; - if (setjmp(s_jmpNoCPUID)) - result = false; - else - { - __asm__ - ( - // save ebx in case -fPIC is being used -#if CRYPTOPP_BOOL_X86 - "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx" -#else - "pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx" -#endif - : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3]) - : "a" (input) - ); - } - - signal(SIGILL, oldHandler); - return result; -#endif -} - -#ifndef _MSC_VER -static jmp_buf s_jmpNoSSE2; -static void SigIllHandlerSSE2(int) -{ - longjmp(s_jmpNoSSE2, 1); -} -#endif - -#elif _MSC_VER >= 1400 && CRYPTOPP_BOOL_X64 - -bool CpuId(word32 input, word32 *output) -{ - __cpuid((int *)output, input); - return true; -} - -#endif - -#ifdef CRYPTOPP_CPUID_AVAILABLE - -static bool TrySSE2() -{ -#if CRYPTOPP_BOOL_X64 - return true; -#elif defined(_MSC_VER) - __try - { -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE - AS2(por xmm0, xmm0) // executing SSE2 instruction -#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE - __mm128i x = _mm_setzero_si128(); - return _mm_cvtsi128_si32(x) == 0; -#endif - } - __except (1) - { - return false; - } - return true; -#elif defined(__GNUC__) - SigHandler oldHandler = signal(SIGILL, SigIllHandlerSSE2); - if (oldHandler == SIG_ERR) - return false; - - bool result = true; - if (setjmp(s_jmpNoSSE2)) - result = false; - else - { -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE - __asm __volatile ("por %xmm0, %xmm0"); -#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE - __mm128i x = _mm_setzero_si128(); - result = _mm_cvtsi128_si32(x) == 0; -#endif - } - - signal(SIGILL, oldHandler); - return result; -#else - return false; -#endif -} - -bool g_x86DetectionDone = false; -bool g_hasISSE = false, g_hasSSE2 = false, g_hasSSSE3 = false, g_hasMMX = false, g_isP4 = false; -word32 g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE; - -void DetectX86Features() -{ - word32 cpuid[4], cpuid1[4]; - if (!CpuId(0, cpuid)) - return; - if (!CpuId(1, cpuid1)) - return; - - g_hasMMX = (cpuid1[3] & (1 << 23)) != 0; - if ((cpuid1[3] & (1 << 26)) != 0) - g_hasSSE2 = TrySSE2(); - g_hasSSSE3 = g_hasSSE2 && (cpuid1[2] & (1<<9)); - - if ((cpuid1[3] & (1 << 25)) != 0) - g_hasISSE = true; - else - { - word32 cpuid2[4]; - CpuId(0x080000000, cpuid2); - if (cpuid2[0] >= 0x080000001) - { - CpuId(0x080000001, cpuid2); - g_hasISSE = (cpuid2[3] & (1 << 22)) != 0; - } - } - - std::swap(cpuid[2], cpuid[3]); - if (memcmp(cpuid+1, "GenuineIntel", 12) == 0) - { - g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf; - g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1); - } - else if (memcmp(cpuid+1, "AuthenticAMD", 12) == 0) - { - CpuId(0x80000005, cpuid); - g_cacheLineSize = GETBYTE(cpuid[2], 0); - } - - if (!g_cacheLineSize) - g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE; - - g_x86DetectionDone = true; -} - -#endif - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/cpu.h b/embeddedcryptopp/cpu.h deleted file mode 100644 index 7f01dad..0000000 --- a/embeddedcryptopp/cpu.h +++ /dev/null @@ -1,263 +0,0 @@ -#ifndef CRYPTOPP_CPU_H -#define CRYPTOPP_CPU_H - -#ifdef CRYPTOPP_GENERATE_X64_MASM - -#define CRYPTOPP_X86_ASM_AVAILABLE -#define CRYPTOPP_BOOL_X64 1 -#define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 1 -#define NAMESPACE_END - -#else - -#include "config.h" - -#ifdef CRYPTOPP_MSVC6PP_OR_LATER - #include -#endif - -NAMESPACE_BEGIN(CryptoPP) - -#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || (_MSC_VER >= 1400 && CRYPTOPP_BOOL_X64) - -#define CRYPTOPP_CPUID_AVAILABLE - -// these should not be used directly -extern CRYPTOPP_DLL bool g_x86DetectionDone; -extern CRYPTOPP_DLL bool g_hasSSE2; -extern CRYPTOPP_DLL bool g_hasISSE; -extern CRYPTOPP_DLL bool g_hasMMX; -extern CRYPTOPP_DLL bool g_hasSSSE3; -extern CRYPTOPP_DLL bool g_isP4; -extern CRYPTOPP_DLL word32 g_cacheLineSize; -CRYPTOPP_DLL void CRYPTOPP_API DetectX86Features(); - -CRYPTOPP_DLL bool CRYPTOPP_API CpuId(word32 input, word32 *output); - -#if CRYPTOPP_BOOL_X64 -inline bool HasSSE2() {return true;} -inline bool HasISSE() {return true;} -inline bool HasMMX() {return true;} -#else - -inline bool HasSSE2() -{ - if (!g_x86DetectionDone) - DetectX86Features(); - return g_hasSSE2; -} - -inline bool HasISSE() -{ - if (!g_x86DetectionDone) - DetectX86Features(); - return g_hasISSE; -} - -inline bool HasMMX() -{ - if (!g_x86DetectionDone) - DetectX86Features(); - return g_hasMMX; -} - -#endif - -inline bool HasSSSE3() -{ - if (!g_x86DetectionDone) - DetectX86Features(); - return g_hasSSSE3; -} - -inline bool IsP4() -{ - if (!g_x86DetectionDone) - DetectX86Features(); - return g_isP4; -} - -inline int GetCacheLineSize() -{ - if (!g_x86DetectionDone) - DetectX86Features(); - return g_cacheLineSize; -} - -#else - -inline int GetCacheLineSize() -{ - return CRYPTOPP_L1_CACHE_LINE_SIZE; -} - -inline bool HasSSSE3() {return false;} -inline bool IsP4() {return false;} - -// assume MMX and SSE2 if intrinsics are enabled -#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_X64 -inline bool HasSSE2() {return true;} -inline bool HasISSE() {return true;} -inline bool HasMMX() {return true;} -#else -inline bool HasSSE2() {return false;} -inline bool HasISSE() {return false;} -inline bool HasMMX() {return false;} -#endif - -#endif // #ifdef CRYPTOPP_X86_ASM_AVAILABLE || _MSC_VER >= 1400 - -#endif - -#ifdef CRYPTOPP_GENERATE_X64_MASM - #define AS1(x) x*newline* - #define AS2(x, y) x, y*newline* - #define AS3(x, y, z) x, y, z*newline* - #define ASS(x, y, a, b, c, d) x, y, a*64+b*16+c*4+d*newline* - #define ASL(x) label##x:*newline* - #define ASJ(x, y, z) x label##y*newline* - #define ASC(x, y) x label##y*newline* - #define AS_HEX(y) 0##y##h -#elif defined(__GNUC__) - // define these in two steps to allow arguments to be expanded - #define GNU_AS1(x) #x ";" - #define GNU_AS2(x, y) #x ", " #y ";" - #define GNU_AS3(x, y, z) #x ", " #y ", " #z ";" - #define GNU_ASL(x) "\n" #x ":" - #define GNU_ASJ(x, y, z) #x " " #y #z ";" - #define AS1(x) GNU_AS1(x) - #define AS2(x, y) GNU_AS2(x, y) - #define AS3(x, y, z) GNU_AS3(x, y, z) - #define ASS(x, y, a, b, c, d) #x ", " #y ", " #a "*64+" #b "*16+" #c "*4+" #d ";" - #define ASL(x) GNU_ASL(x) - #define ASJ(x, y, z) GNU_ASJ(x, y, z) - #define ASC(x, y) #x " " #y ";" - #define CRYPTOPP_NAKED - #define AS_HEX(y) 0x##y -#else - #define AS1(x) __asm {x} - #define AS2(x, y) __asm {x, y} - #define AS3(x, y, z) __asm {x, y, z} - #define ASS(x, y, a, b, c, d) __asm {x, y, _MM_SHUFFLE(a, b, c, d)} - #define ASL(x) __asm {label##x:} - #define ASJ(x, y, z) __asm {x label##y} - #define ASC(x, y) __asm {x label##y} - #define CRYPTOPP_NAKED __declspec(naked) - #define AS_HEX(y) 0x##y -#endif - -#define IF0(y) -#define IF1(y) y - -#ifdef CRYPTOPP_GENERATE_X64_MASM -#define ASM_MOD(x, y) ((x) MOD (y)) -#define XMMWORD_PTR XMMWORD PTR -#else -// GNU assembler doesn't seem to have mod operator -#define ASM_MOD(x, y) ((x)-((x)/(y))*(y)) -// GAS 2.15 doesn't support XMMWORD PTR. it seems necessary only for MASM -#define XMMWORD_PTR -#endif - -#if CRYPTOPP_BOOL_X86 - #define AS_REG_1 ecx - #define AS_REG_2 edx - #define AS_REG_3 esi - #define AS_REG_4 edi - #define AS_REG_5 eax - #define AS_REG_6 ebx - #define AS_REG_7 ebp - #define AS_REG_1d ecx - #define AS_REG_2d edx - #define AS_REG_3d esi - #define AS_REG_4d edi - #define AS_REG_5d eax - #define AS_REG_6d ebx - #define AS_REG_7d ebp - #define WORD_SZ 4 - #define WORD_REG(x) e##x - #define WORD_PTR DWORD PTR - #define AS_PUSH_IF86(x) AS1(push e##x) - #define AS_POP_IF86(x) AS1(pop e##x) - #define AS_JCXZ jecxz -#elif CRYPTOPP_BOOL_X64 - #ifdef CRYPTOPP_GENERATE_X64_MASM - #define AS_REG_1 rcx - #define AS_REG_2 rdx - #define AS_REG_3 r8 - #define AS_REG_4 r9 - #define AS_REG_5 rax - #define AS_REG_6 r10 - #define AS_REG_7 r11 - #define AS_REG_1d ecx - #define AS_REG_2d edx - #define AS_REG_3d r8d - #define AS_REG_4d r9d - #define AS_REG_5d eax - #define AS_REG_6d r10d - #define AS_REG_7d r11d - #else - #define AS_REG_1 rdi - #define AS_REG_2 rsi - #define AS_REG_3 rdx - #define AS_REG_4 rcx - #define AS_REG_5 r8 - #define AS_REG_6 r9 - #define AS_REG_7 r10 - #define AS_REG_1d edi - #define AS_REG_2d esi - #define AS_REG_3d edx - #define AS_REG_4d ecx - #define AS_REG_5d r8d - #define AS_REG_6d r9d - #define AS_REG_7d r10d - #endif - #define WORD_SZ 8 - #define WORD_REG(x) r##x - #define WORD_PTR QWORD PTR - #define AS_PUSH_IF86(x) - #define AS_POP_IF86(x) - #define AS_JCXZ jrcxz -#endif - -// helper macro for stream cipher output -#define AS_XMM_OUTPUT4(labelPrefix, inputPtr, outputPtr, x0, x1, x2, x3, t, p0, p1, p2, p3, increment)\ - AS2( test inputPtr, inputPtr)\ - ASC( jz, labelPrefix##3)\ - AS2( test inputPtr, 15)\ - ASC( jnz, labelPrefix##7)\ - AS2( pxor xmm##x0, [inputPtr+p0*16])\ - AS2( pxor xmm##x1, [inputPtr+p1*16])\ - AS2( pxor xmm##x2, [inputPtr+p2*16])\ - AS2( pxor xmm##x3, [inputPtr+p3*16])\ - AS2( add inputPtr, increment*16)\ - ASC( jmp, labelPrefix##3)\ - ASL(labelPrefix##7)\ - AS2( movdqu xmm##t, [inputPtr+p0*16])\ - AS2( pxor xmm##x0, xmm##t)\ - AS2( movdqu xmm##t, [inputPtr+p1*16])\ - AS2( pxor xmm##x1, xmm##t)\ - AS2( movdqu xmm##t, [inputPtr+p2*16])\ - AS2( pxor xmm##x2, xmm##t)\ - AS2( movdqu xmm##t, [inputPtr+p3*16])\ - AS2( pxor xmm##x3, xmm##t)\ - AS2( add inputPtr, increment*16)\ - ASL(labelPrefix##3)\ - AS2( test outputPtr, 15)\ - ASC( jnz, labelPrefix##8)\ - AS2( movdqa [outputPtr+p0*16], xmm##x0)\ - AS2( movdqa [outputPtr+p1*16], xmm##x1)\ - AS2( movdqa [outputPtr+p2*16], xmm##x2)\ - AS2( movdqa [outputPtr+p3*16], xmm##x3)\ - ASC( jmp, labelPrefix##9)\ - ASL(labelPrefix##8)\ - AS2( movdqu [outputPtr+p0*16], xmm##x0)\ - AS2( movdqu [outputPtr+p1*16], xmm##x1)\ - AS2( movdqu [outputPtr+p2*16], xmm##x2)\ - AS2( movdqu [outputPtr+p3*16], xmm##x3)\ - ASL(labelPrefix##9)\ - AS2( add outputPtr, increment*16) - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/cryptdll.dsp b/embeddedcryptopp/cryptdll.dsp deleted file mode 100644 index aad342e..0000000 --- a/embeddedcryptopp/cryptdll.dsp +++ /dev/null @@ -1,594 +0,0 @@ -# Microsoft Developer Studio Project File - Name="cryptdll" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=cryptdll - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "cryptdll.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "cryptdll.mak" CFG="cryptdll - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "cryptdll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "cryptdll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "cryptdll - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "cryptdll___Win32_Release" -# PROP BASE Intermediate_Dir "cryptdll___Win32_Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "DLL_Release" -# PROP Intermediate_Dir "DLL_Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CRYPTDLL_EXPORTS" /YX /FD /c -# ADD CPP /nologo /G5 /MT /W3 /GR /GX /Zi /O1 /Ob2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CRYPTOPP_EXPORTS" /D CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2=1 /D "USE_PRECOMPILED_HEADERS" /Yu"pch.h" /FD /Zm200 /c -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 advapi32.lib /nologo /base:"0x42900000" /dll /map /debug /machine:I386 /out:"DLL_Release/cryptopp.dll" /opt:ref -# SUBTRACT LINK32 /pdb:none -# Begin Custom Build -OutDir=.\DLL_Release -TargetPath=.\DLL_Release\cryptopp.dll -InputPath=.\DLL_Release\cryptopp.dll -SOURCE="$(InputPath)" - -"$(OutDir)\cryptopp.mac.done" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - CTRelease\cryptest mac_dll $(TargetPath) - echo mac done > $(OutDir)\cryptopp.mac.done - -# End Custom Build - -!ELSEIF "$(CFG)" == "cryptdll - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "cryptdll___Win32_Debug" -# PROP BASE Intermediate_Dir "cryptdll___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "DLL_Debug" -# PROP Intermediate_Dir "DLL_Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CRYPTDLL_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /G5 /MTd /W3 /Gm /GR /GX /Zi /Oi /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CRYPTOPP_EXPORTS" /D CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2=1 /D "USE_PRECOMPILED_HEADERS" /Yu"pch.h" /FD /GZ /Zm200 /c -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 advapi32.lib /nologo /base:"0x42900000" /dll /incremental:no /debug /machine:I386 /out:"DLL_Debug/cryptopp.dll" /opt:ref -# SUBTRACT LINK32 /pdb:none -# Begin Custom Build -OutDir=.\DLL_Debug -TargetPath=.\DLL_Debug\cryptopp.dll -InputPath=.\DLL_Debug\cryptopp.dll -SOURCE="$(InputPath)" - -"$(OutDir)\cryptopp.mac.done" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - CTDebug\cryptest mac_dll $(TargetPath) - echo mac done > $(OutDir)\cryptopp.mac.done - -# End Custom Build - -!ENDIF - -# Begin Target - -# Name "cryptdll - Win32 Release" -# Name "cryptdll - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\algebra.cpp -# End Source File -# Begin Source File - -SOURCE=.\algparam.cpp -# End Source File -# Begin Source File - -SOURCE=.\asn.cpp -# End Source File -# Begin Source File - -SOURCE=.\authenc.cpp -# End Source File -# Begin Source File - -SOURCE=.\basecode.cpp -# End Source File -# Begin Source File - -SOURCE=.\cbcmac.cpp -# End Source File -# Begin Source File - -SOURCE=.\ccm.cpp -# End Source File -# Begin Source File - -SOURCE=.\channels.cpp -# End Source File -# Begin Source File - -SOURCE=.\cmac.cpp -# End Source File -# Begin Source File - -SOURCE=.\cpu.cpp -# End Source File -# Begin Source File - -SOURCE=.\cryptlib.cpp -# End Source File -# Begin Source File - -SOURCE=.\des.cpp -# End Source File -# Begin Source File - -SOURCE=.\dessp.cpp -# End Source File -# Begin Source File - -SOURCE=.\dh.cpp -# End Source File -# Begin Source File - -SOURCE=.\dll.cpp -# SUBTRACT CPP /YX /Yc /Yu -# End Source File -# Begin Source File - -SOURCE=.\dsa.cpp -# End Source File -# Begin Source File - -SOURCE=.\ec2n.cpp -# End Source File -# Begin Source File - -SOURCE=.\eccrypto.cpp -# End Source File -# Begin Source File - -SOURCE=.\ecp.cpp -# End Source File -# Begin Source File - -SOURCE=.\emsa2.cpp -# End Source File -# Begin Source File - -SOURCE=.\eprecomp.cpp -# End Source File -# Begin Source File - -SOURCE=.\files.cpp -# End Source File -# Begin Source File - -SOURCE=.\filters.cpp -# End Source File -# Begin Source File - -SOURCE=.\fips140.cpp -# End Source File -# Begin Source File - -SOURCE=.\fipstest.cpp -# End Source File -# Begin Source File - -SOURCE=.\gcm.cpp -# End Source File -# Begin Source File - -SOURCE=.\gf2n.cpp -# End Source File -# Begin Source File - -SOURCE=.\gfpcrypt.cpp -# End Source File -# Begin Source File - -SOURCE=.\hex.cpp -# End Source File -# Begin Source File - -SOURCE=.\hmac.cpp -# End Source File -# Begin Source File - -SOURCE=.\hrtimer.cpp -# End Source File -# Begin Source File - -SOURCE=.\integer.cpp -# End Source File -# Begin Source File - -SOURCE=.\iterhash.cpp -# SUBTRACT CPP /YX /Yc /Yu -# End Source File -# Begin Source File - -SOURCE=.\misc.cpp -# End Source File -# Begin Source File - -SOURCE=.\modes.cpp -# End Source File -# Begin Source File - -SOURCE=.\mqueue.cpp -# End Source File -# Begin Source File - -SOURCE=.\nbtheory.cpp -# End Source File -# Begin Source File - -SOURCE=.\oaep.cpp -# End Source File -# Begin Source File - -SOURCE=.\osrng.cpp -# End Source File -# Begin Source File - -SOURCE=.\pch.cpp -# ADD CPP /Yc"pch.h" -# End Source File -# Begin Source File - -SOURCE=.\pkcspad.cpp -# End Source File -# Begin Source File - -SOURCE=.\pssr.cpp -# End Source File -# Begin Source File - -SOURCE=.\pubkey.cpp -# End Source File -# Begin Source File - -SOURCE=.\queue.cpp -# End Source File -# Begin Source File - -SOURCE=.\randpool.cpp -# End Source File -# Begin Source File - -SOURCE=.\rdtables.cpp -# End Source File -# Begin Source File - -SOURCE=.\rijndael.cpp -# End Source File -# Begin Source File - -SOURCE=.\rng.cpp -# End Source File -# Begin Source File - -SOURCE=.\rsa.cpp -# End Source File -# Begin Source File - -SOURCE=.\rw.cpp -# End Source File -# Begin Source File - -SOURCE=.\sha.cpp -# End Source File -# Begin Source File - -SOURCE=.\simple.cpp -# End Source File -# Begin Source File - -SOURCE=.\skipjack.cpp -# End Source File -# Begin Source File - -SOURCE=.\strciphr.cpp -# End Source File -# Begin Source File - -SOURCE=.\trdlocal.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter ".h" -# Begin Source File - -SOURCE=.\aes.h -# End Source File -# Begin Source File - -SOURCE=.\algebra.h -# End Source File -# Begin Source File - -SOURCE=.\algparam.h -# End Source File -# Begin Source File - -SOURCE=.\argnames.h -# End Source File -# Begin Source File - -SOURCE=.\asn.h -# End Source File -# Begin Source File - -SOURCE=.\authenc.h -# End Source File -# Begin Source File - -SOURCE=.\basecode.h -# End Source File -# Begin Source File - -SOURCE=.\cbcmac.h -# End Source File -# Begin Source File - -SOURCE=.\ccm.h -# End Source File -# Begin Source File - -SOURCE=.\channels.h -# End Source File -# Begin Source File - -SOURCE=.\cmac.h -# End Source File -# Begin Source File - -SOURCE=.\config.h -# End Source File -# Begin Source File - -SOURCE=.\cryptlib.h -# End Source File -# Begin Source File - -SOURCE=.\des.h -# End Source File -# Begin Source File - -SOURCE=.\dh.h -# End Source File -# Begin Source File - -SOURCE=.\dll.h -# End Source File -# Begin Source File - -SOURCE=.\dsa.h -# End Source File -# Begin Source File - -SOURCE=.\ec2n.h -# End Source File -# Begin Source File - -SOURCE=.\eccrypto.h -# End Source File -# Begin Source File - -SOURCE=.\ecp.h -# End Source File -# Begin Source File - -SOURCE=.\eprecomp.h -# End Source File -# Begin Source File - -SOURCE=.\files.h -# End Source File -# Begin Source File - -SOURCE=.\filters.h -# End Source File -# Begin Source File - -SOURCE=.\fips140.h -# End Source File -# Begin Source File - -SOURCE=.\fltrimpl.h -# End Source File -# Begin Source File - -SOURCE=.\gcm.h -# End Source File -# Begin Source File - -SOURCE=.\gf2n.h -# End Source File -# Begin Source File - -SOURCE=.\gfpcrypt.h -# End Source File -# Begin Source File - -SOURCE=.\hex.h -# End Source File -# Begin Source File - -SOURCE=.\hmac.h -# End Source File -# Begin Source File - -SOURCE=.\integer.h -# End Source File -# Begin Source File - -SOURCE=.\iterhash.h -# End Source File -# Begin Source File - -SOURCE=.\mdc.h -# End Source File -# Begin Source File - -SOURCE=.\misc.h -# End Source File -# Begin Source File - -SOURCE=.\modarith.h -# End Source File -# Begin Source File - -SOURCE=.\modes.h -# End Source File -# Begin Source File - -SOURCE=.\modexppc.h -# End Source File -# Begin Source File - -SOURCE=.\mqueue.h -# End Source File -# Begin Source File - -SOURCE=.\mqv.h -# End Source File -# Begin Source File - -SOURCE=.\nbtheory.h -# End Source File -# Begin Source File - -SOURCE=.\oaep.h -# End Source File -# Begin Source File - -SOURCE=.\oids.h -# End Source File -# Begin Source File - -SOURCE=.\osrng.h -# End Source File -# Begin Source File - -SOURCE=.\pch.h -# End Source File -# Begin Source File - -SOURCE=.\pkcspad.h -# End Source File -# Begin Source File - -SOURCE=.\pubkey.h -# End Source File -# Begin Source File - -SOURCE=.\queue.h -# End Source File -# Begin Source File - -SOURCE=.\randpool.h -# End Source File -# Begin Source File - -SOURCE=.\rijndael.h -# End Source File -# Begin Source File - -SOURCE=.\rng.h -# End Source File -# Begin Source File - -SOURCE=.\rsa.h -# End Source File -# Begin Source File - -SOURCE=.\secblock.h -# End Source File -# Begin Source File - -SOURCE=.\seckey.h -# End Source File -# Begin Source File - -SOURCE=.\sha.h -# End Source File -# Begin Source File - -SOURCE=.\simple.h -# End Source File -# Begin Source File - -SOURCE=.\skipjack.h -# End Source File -# Begin Source File - -SOURCE=.\smartptr.h -# End Source File -# Begin Source File - -SOURCE=.\stdcpp.h -# End Source File -# Begin Source File - -SOURCE=.\strciphr.h -# End Source File -# Begin Source File - -SOURCE=.\trdlocal.h -# End Source File -# Begin Source File - -SOURCE=.\words.h -# End Source File -# End Group -# Begin Source File - -SOURCE=.\cryptopp.rc -# End Source File -# End Target -# End Project diff --git a/embeddedcryptopp/cryptdll.vcproj b/embeddedcryptopp/cryptdll.vcproj deleted file mode 100644 index 5e7d799..0000000 --- a/embeddedcryptopp/cryptdll.vcproj +++ /dev/null @@ -1,2694 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/embeddedcryptopp/cryptest.dsp b/embeddedcryptopp/cryptest.dsp deleted file mode 100644 index a981642..0000000 --- a/embeddedcryptopp/cryptest.dsp +++ /dev/null @@ -1,207 +0,0 @@ -# Microsoft Developer Studio Project File - Name="cryptest" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=cryptest - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "cryptest.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "cryptest.mak" CFG="cryptest - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "cryptest - Win32 DLL-Import Release" (based on "Win32 (x86) Console Application") -!MESSAGE "cryptest - Win32 DLL-Import Debug" (based on "Win32 (x86) Console Application") -!MESSAGE "cryptest - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "cryptest - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "cryptest - Win32 DLL-Import Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "cryptest___Win32_FIPS_140_Release" -# PROP BASE Intermediate_Dir "cryptest___Win32_FIPS_140_Release" -# PROP BASE Ignore_Export_Lib 0 -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "CT_DLL_Import_Release" -# PROP Intermediate_Dir "CT_DLL_Import_Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /G5 /Gz /MT /W3 /GX /Zi /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /Zm200 /c -# ADD CPP /nologo /G5 /Gz /MT /W3 /GR /GX /Zi /O1 /Ob2 /D "NDEBUG" /D "CRYPTOPP_IMPORTS" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /Zm400 /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /OPT:NOWIN98 -# ADD LINK32 Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /out:"DLL_Release/cryptest.exe" /libpath:"DLL_Release" /OPT:NOWIN98 /OPT:REF /OPT:ICF -# SUBTRACT LINK32 /pdb:none /incremental:yes -# Begin Special Build Tool -SOURCE="$(InputPath)" -PreLink_Cmds=echo This configuration requires cryptopp.dll. echo You can build it yourself using the cryptdll project, or echo obtain a pre-built, FIPS 140-2 validated DLL. If you build it yourself echo the resulting DLL will not be considered FIPS validated echo unless it undergoes FIPS validation. -# End Special Build Tool - -!ELSEIF "$(CFG)" == "cryptest - Win32 DLL-Import Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "cryptest___Win32_FIPS_140_Debug" -# PROP BASE Intermediate_Dir "cryptest___Win32_FIPS_140_Debug" -# PROP BASE Ignore_Export_Lib 0 -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "CT_DLL_Import_Debug" -# PROP Intermediate_Dir "CT_DLL_Import_Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /Zm200 /c -# ADD CPP /nologo /G5 /Gz /MTd /W3 /GR /GX /Zi /Oi /D "_DEBUG" /D "CRYPTOPP_IMPORTS" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /Zm400 /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /OPT:NOWIN98 -# ADD LINK32 Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /out:"DLL_Debug/cryptest.exe" /pdbtype:sept /libpath:"DLL_Debug" /OPT:NOWIN98 -# Begin Special Build Tool -SOURCE="$(InputPath)" -PreLink_Cmds=echo This configuration requires cryptopp.dll. echo You can build it yourself using the cryptdll project, or echo obtain a pre-built, FIPS 140-2 validated DLL. If you build it yourself echo the resulting DLL will not be considered FIPS validated echo unless it undergoes FIPS validation. -# End Special Build Tool - -!ELSEIF "$(CFG)" == "cryptest - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "cryptes0" -# PROP BASE Intermediate_Dir "cryptes0" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "CTRelease" -# PROP Intermediate_Dir "CTRelease" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GR /GX /Zi /O1 /Ob2 /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "WIN32" /YX /FD /Zm400 /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 advapi32.lib Ws2_32.lib /nologo /subsystem:console /map /debug /machine:I386 /OPT:NOWIN98 /OPT:REF /OPT:ICF -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "cryptest - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "cryptes1" -# PROP BASE Intermediate_Dir "cryptes1" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "CTDebug" -# PROP Intermediate_Dir "CTDebug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MTd /W3 /GR /GX /Zi /Oi /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "WIN32" /YX /FD /Zm400 /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 advapi32.lib Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /OPT:NOWIN98 -# SUBTRACT LINK32 /pdb:none - -!ENDIF - -# Begin Target - -# Name "cryptest - Win32 DLL-Import Release" -# Name "cryptest - Win32 DLL-Import Debug" -# Name "cryptest - Win32 Release" -# Name "cryptest - Win32 Debug" -# Begin Group "Source Code" - -# PROP Default_Filter ".cpp;.h" -# Begin Source File - -SOURCE=.\adhoc.cpp -# End Source File -# Begin Source File - -SOURCE=.\bench.cpp -# End Source File -# Begin Source File - -SOURCE=.\bench.h -# End Source File -# Begin Source File - -SOURCE=.\bench2.cpp -# End Source File -# Begin Source File - -SOURCE=.\datatest.cpp -# End Source File -# Begin Source File - -SOURCE=.\dlltest.cpp -# End Source File -# Begin Source File - -SOURCE=.\fipsalgt.cpp -# End Source File -# Begin Source File - -SOURCE=.\regtest.cpp -# End Source File -# Begin Source File - -SOURCE=.\test.cpp -# End Source File -# Begin Source File - -SOURCE=.\validat1.cpp -# End Source File -# Begin Source File - -SOURCE=.\validat2.cpp -# End Source File -# Begin Source File - -SOURCE=.\validat3.cpp -# End Source File -# Begin Source File - -SOURCE=.\validate.h -# End Source File -# End Group -# End Target -# End Project diff --git a/embeddedcryptopp/cryptest.dsw b/embeddedcryptopp/cryptest.dsw deleted file mode 100644 index a2f1411..0000000 --- a/embeddedcryptopp/cryptest.dsw +++ /dev/null @@ -1,74 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "cryptdll"=.\cryptdll.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name cryptest - End Project Dependency -}}} - -############################################################################### - -Project: "cryptest"=.\cryptest.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name cryptlib - End Project Dependency -}}} - -############################################################################### - -Project: "cryptlib"=.\cryptlib.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "dlltest"=.\dlltest.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name cryptdll - End Project Dependency -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/embeddedcryptopp/cryptest.sln b/embeddedcryptopp/cryptest.sln deleted file mode 100644 index dea1776..0000000 --- a/embeddedcryptopp/cryptest.sln +++ /dev/null @@ -1,100 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cryptdll", "cryptdll.vcproj", "{EBD86293-69A9-456B-B814-916E12AA9BBF}" - ProjectSection(ProjectDependencies) = postProject - {9EAFA456-89B4-4879-AD4F-C2C341184CF5} = {9EAFA456-89B4-4879-AD4F-C2C341184CF5} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cryptest", "cryptest.vcproj", "{9EAFA456-89B4-4879-AD4F-C2C341184CF5}" - ProjectSection(ProjectDependencies) = postProject - {3423EC9A-52E4-4A4D-9753-EDEBC38785EF} = {3423EC9A-52E4-4A4D-9753-EDEBC38785EF} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cryptlib", "cryptlib.vcproj", "{3423EC9A-52E4-4A4D-9753-EDEBC38785EF}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dlltest", "dlltest.vcproj", "{A7483CE8-2784-46CE-8CB8-8C0C1D27E232}" - ProjectSection(ProjectDependencies) = postProject - {EBD86293-69A9-456B-B814-916E12AA9BBF} = {EBD86293-69A9-456B-B814-916E12AA9BBF} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - DLL-Import Debug|Win32 = DLL-Import Debug|Win32 - DLL-Import Debug|x64 = DLL-Import Debug|x64 - DLL-Import Release|Win32 = DLL-Import Release|Win32 - DLL-Import Release|x64 = DLL-Import Release|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {EBD86293-69A9-456B-B814-916E12AA9BBF}.Debug|Win32.ActiveCfg = Debug|Win32 - {EBD86293-69A9-456B-B814-916E12AA9BBF}.Debug|Win32.Build.0 = Debug|Win32 - {EBD86293-69A9-456B-B814-916E12AA9BBF}.Debug|x64.ActiveCfg = Debug|x64 - {EBD86293-69A9-456B-B814-916E12AA9BBF}.Debug|x64.Build.0 = Debug|x64 - {EBD86293-69A9-456B-B814-916E12AA9BBF}.DLL-Import Debug|Win32.ActiveCfg = Debug|Win32 - {EBD86293-69A9-456B-B814-916E12AA9BBF}.DLL-Import Debug|Win32.Build.0 = Debug|Win32 - {EBD86293-69A9-456B-B814-916E12AA9BBF}.DLL-Import Debug|x64.ActiveCfg = Debug|x64 - {EBD86293-69A9-456B-B814-916E12AA9BBF}.DLL-Import Debug|x64.Build.0 = Debug|x64 - {EBD86293-69A9-456B-B814-916E12AA9BBF}.DLL-Import Release|Win32.ActiveCfg = Release|Win32 - {EBD86293-69A9-456B-B814-916E12AA9BBF}.DLL-Import Release|Win32.Build.0 = Release|Win32 - {EBD86293-69A9-456B-B814-916E12AA9BBF}.DLL-Import Release|x64.ActiveCfg = Release|x64 - {EBD86293-69A9-456B-B814-916E12AA9BBF}.DLL-Import Release|x64.Build.0 = Release|x64 - {EBD86293-69A9-456B-B814-916E12AA9BBF}.Release|Win32.ActiveCfg = Release|Win32 - {EBD86293-69A9-456B-B814-916E12AA9BBF}.Release|Win32.Build.0 = Release|Win32 - {EBD86293-69A9-456B-B814-916E12AA9BBF}.Release|x64.ActiveCfg = Release|x64 - {EBD86293-69A9-456B-B814-916E12AA9BBF}.Release|x64.Build.0 = Release|x64 - {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.Debug|Win32.ActiveCfg = Debug|Win32 - {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.Debug|Win32.Build.0 = Debug|Win32 - {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.Debug|x64.ActiveCfg = Debug|x64 - {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.Debug|x64.Build.0 = Debug|x64 - {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.DLL-Import Debug|Win32.ActiveCfg = DLL-Import Debug|Win32 - {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.DLL-Import Debug|Win32.Build.0 = DLL-Import Debug|Win32 - {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.DLL-Import Debug|x64.ActiveCfg = DLL-Import Debug|x64 - {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.DLL-Import Debug|x64.Build.0 = DLL-Import Debug|x64 - {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.DLL-Import Release|Win32.ActiveCfg = DLL-Import Release|Win32 - {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.DLL-Import Release|Win32.Build.0 = DLL-Import Release|Win32 - {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.DLL-Import Release|x64.ActiveCfg = DLL-Import Release|x64 - {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.DLL-Import Release|x64.Build.0 = DLL-Import Release|x64 - {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.Release|Win32.ActiveCfg = Release|Win32 - {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.Release|Win32.Build.0 = Release|Win32 - {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.Release|x64.ActiveCfg = Release|x64 - {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.Release|x64.Build.0 = Release|x64 - {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.Debug|Win32.ActiveCfg = Debug|Win32 - {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.Debug|Win32.Build.0 = Debug|Win32 - {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.Debug|x64.ActiveCfg = Debug|x64 - {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.Debug|x64.Build.0 = Debug|x64 - {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.DLL-Import Debug|Win32.ActiveCfg = DLL-Import Debug|Win32 - {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.DLL-Import Debug|Win32.Build.0 = DLL-Import Debug|Win32 - {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.DLL-Import Debug|x64.ActiveCfg = DLL-Import Debug|x64 - {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.DLL-Import Debug|x64.Build.0 = DLL-Import Debug|x64 - {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.DLL-Import Release|Win32.ActiveCfg = DLL-Import Release|Win32 - {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.DLL-Import Release|Win32.Build.0 = DLL-Import Release|Win32 - {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.DLL-Import Release|x64.ActiveCfg = DLL-Import Release|x64 - {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.DLL-Import Release|x64.Build.0 = DLL-Import Release|x64 - {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.Release|Win32.ActiveCfg = Release|Win32 - {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.Release|Win32.Build.0 = Release|Win32 - {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.Release|x64.ActiveCfg = Release|x64 - {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.Release|x64.Build.0 = Release|x64 - {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.Debug|Win32.ActiveCfg = Debug|Win32 - {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.Debug|Win32.Build.0 = Debug|Win32 - {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.Debug|x64.ActiveCfg = Debug|x64 - {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.Debug|x64.Build.0 = Debug|x64 - {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.DLL-Import Debug|Win32.ActiveCfg = Debug|Win32 - {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.DLL-Import Debug|Win32.Build.0 = Debug|Win32 - {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.DLL-Import Debug|x64.ActiveCfg = Debug|x64 - {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.DLL-Import Debug|x64.Build.0 = Debug|x64 - {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.DLL-Import Release|Win32.ActiveCfg = Release|Win32 - {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.DLL-Import Release|Win32.Build.0 = Release|Win32 - {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.DLL-Import Release|x64.ActiveCfg = Release|x64 - {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.DLL-Import Release|x64.Build.0 = Release|x64 - {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.Release|Win32.ActiveCfg = Release|Win32 - {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.Release|Win32.Build.0 = Release|Win32 - {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.Release|x64.ActiveCfg = Release|x64 - {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/embeddedcryptopp/cryptest.vcproj b/embeddedcryptopp/cryptest.vcproj deleted file mode 100644 index 1d39fca..0000000 --- a/embeddedcryptopp/cryptest.vcproj +++ /dev/null @@ -1,1850 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/embeddedcryptopp/cryptest_bds.bdsgroup b/embeddedcryptopp/cryptest_bds.bdsgroup deleted file mode 100644 index bbb081a..0000000 --- a/embeddedcryptopp/cryptest_bds.bdsgroup +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - cryptest_bds.bdsproj - cryptlib_bds.bdsproj - cryptest_bds.exe cryptlib_bds.lib - - - - - - - - diff --git a/embeddedcryptopp/cryptest_bds.bdsproj b/embeddedcryptopp/cryptest_bds.bdsproj deleted file mode 100644 index 9086d30..0000000 --- a/embeddedcryptopp/cryptest_bds.bdsproj +++ /dev/null @@ -1,267 +0,0 @@ - - - - - - - - - - - - cryptest_bds.bpf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - False - False - 1 - 0 - 0 - 0 - False - False - False - False - False - 1033 - 1252 - - - - - 1.0.0.0 - - - - - - 1.0.0.0 - - - - - - - v - - True - . - D:\cvs\c5\Debug_Build\cryptest_bds.exe - - - - - False - - False - - True - False - - - Delphi 1.0 Compatibility Components - Borland C++Builder Internet Explorer 5 Components Package - - - - - - - - - - - diff --git a/embeddedcryptopp/cryptest_bds.bpf b/embeddedcryptopp/cryptest_bds.bpf deleted file mode 100644 index c30200b..0000000 --- a/embeddedcryptopp/cryptest_bds.bpf +++ /dev/null @@ -1,5 +0,0 @@ -This file is used by the project manager only and should be treated like the project file - -To add a file to this project use the Project menu 'Add to Project' - -main \ No newline at end of file diff --git a/embeddedcryptopp/cryptlib.cpp b/embeddedcryptopp/cryptlib.cpp deleted file mode 100644 index 0e5bd24..0000000 --- a/embeddedcryptopp/cryptlib.cpp +++ /dev/null @@ -1,821 +0,0 @@ -// cryptlib.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "cryptlib.h" -#include "misc.h" -#include "filters.h" -#include "algparam.h" -#include "fips140.h" -#include "argnames.h" -#include "fltrimpl.h" -#include "trdlocal.h" -#include "osrng.h" - -#include - -NAMESPACE_BEGIN(CryptoPP) - -CRYPTOPP_COMPILE_ASSERT(sizeof(byte) == 1); -CRYPTOPP_COMPILE_ASSERT(sizeof(word16) == 2); -CRYPTOPP_COMPILE_ASSERT(sizeof(word32) == 4); -CRYPTOPP_COMPILE_ASSERT(sizeof(word64) == 8); -#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE -CRYPTOPP_COMPILE_ASSERT(sizeof(dword) == 2*sizeof(word)); -#endif - -const std::string DEFAULT_CHANNEL; -const std::string AAD_CHANNEL = "AAD"; -const std::string &BufferedTransformation::NULL_CHANNEL = DEFAULT_CHANNEL; - -const NullNameValuePairs g_nullNameValuePairs; - -BufferedTransformation & TheBitBucket() -{ - static BitBucket bitBucket; - return bitBucket; -} - -Algorithm::Algorithm(bool checkSelfTestStatus) -{ - if (checkSelfTestStatus && FIPS_140_2_ComplianceEnabled()) - { - if (GetPowerUpSelfTestStatus() == POWER_UP_SELF_TEST_NOT_DONE && !PowerUpSelfTestInProgressOnThisThread()) - throw SelfTestFailure("Cryptographic algorithms are disabled before the power-up self tests are performed."); - - if (GetPowerUpSelfTestStatus() == POWER_UP_SELF_TEST_FAILED) - throw SelfTestFailure("Cryptographic algorithms are disabled after a power-up self test failed."); - } -} - -void SimpleKeyingInterface::SetKey(const byte *key, size_t length, const NameValuePairs ¶ms) -{ - this->ThrowIfInvalidKeyLength(length); - this->UncheckedSetKey(key, (unsigned int)length, params); -} - -void SimpleKeyingInterface::SetKeyWithRounds(const byte *key, size_t length, int rounds) -{ - SetKey(key, length, MakeParameters(Name::Rounds(), rounds)); -} - -void SimpleKeyingInterface::SetKeyWithIV(const byte *key, size_t length, const byte *iv, size_t ivLength) -{ - SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, ivLength))); -} - -void SimpleKeyingInterface::ThrowIfInvalidKeyLength(size_t length) -{ - if (!IsValidKeyLength(length)) - throw InvalidKeyLength(GetAlgorithm().AlgorithmName(), length); -} - -void SimpleKeyingInterface::ThrowIfResynchronizable() -{ - if (IsResynchronizable()) - throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": this object requires an IV"); -} - -void SimpleKeyingInterface::ThrowIfInvalidIV(const byte *iv) -{ - if (!iv && !(IVRequirement() == INTERNALLY_GENERATED_IV || IVRequirement() == UNIQUE_IV || !IsResynchronizable())) - throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": this object cannot use a null IV"); -} - -size_t SimpleKeyingInterface::ThrowIfInvalidIVLength(int size) -{ - if (size < 0) - return IVSize(); - else if ((size_t)size < MinIVLength()) - throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": IV length " + IntToString(size) + " is less than the minimum of " + IntToString(MinIVLength())); - else if ((size_t)size > MaxIVLength()) - throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": IV length " + IntToString(size) + " exceeds the maximum of " + IntToString(MaxIVLength())); - else - return size; -} - -const byte * SimpleKeyingInterface::GetIVAndThrowIfInvalid(const NameValuePairs ¶ms, size_t &size) -{ - ConstByteArrayParameter ivWithLength; - const byte *iv; - bool found = false; - - try {found = params.GetValue(Name::IV(), ivWithLength);} - catch (const NameValuePairs::ValueTypeMismatch &) {} - - if (found) - { - iv = ivWithLength.begin(); - ThrowIfInvalidIV(iv); - size = ThrowIfInvalidIVLength((int)ivWithLength.size()); - return iv; - } - else if (params.GetValue(Name::IV(), iv)) - { - ThrowIfInvalidIV(iv); - size = IVSize(); - return iv; - } - else - { - ThrowIfResynchronizable(); - size = 0; - return NULL; - } -} - -void SimpleKeyingInterface::GetNextIV(RandomNumberGenerator &rng, byte *IV) -{ - rng.GenerateBlock(IV, IVSize()); -} - -size_t BlockTransformation::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const -{ - size_t blockSize = BlockSize(); - size_t inIncrement = (flags & (BT_InBlockIsCounter|BT_DontIncrementInOutPointers)) ? 0 : blockSize; - size_t xorIncrement = xorBlocks ? blockSize : 0; - size_t outIncrement = (flags & BT_DontIncrementInOutPointers) ? 0 : blockSize; - - if (flags & BT_ReverseDirection) - { - assert(length % blockSize == 0); - inBlocks += length - blockSize; - xorBlocks += length - blockSize; - outBlocks += length - blockSize; - inIncrement = 0-inIncrement; - xorIncrement = 0-xorIncrement; - outIncrement = 0-outIncrement; - } - - while (length >= blockSize) - { - if (flags & BT_XorInput) - { - xorbuf(outBlocks, xorBlocks, inBlocks, blockSize); - ProcessBlock(outBlocks); - } - else - ProcessAndXorBlock(inBlocks, xorBlocks, outBlocks); - if (flags & BT_InBlockIsCounter) - const_cast(inBlocks)[blockSize-1]++; - inBlocks += inIncrement; - outBlocks += outIncrement; - xorBlocks += xorIncrement; - length -= blockSize; - } - - return length; -} - -unsigned int BlockTransformation::OptimalDataAlignment() const -{ - return GetAlignmentOf(); -} - -unsigned int StreamTransformation::OptimalDataAlignment() const -{ - return GetAlignmentOf(); -} - -unsigned int HashTransformation::OptimalDataAlignment() const -{ - return GetAlignmentOf(); -} - -void StreamTransformation::ProcessLastBlock(byte *outString, const byte *inString, size_t length) -{ - assert(MinLastBlockSize() == 0); // this function should be overriden otherwise - - if (length == MandatoryBlockSize()) - ProcessData(outString, inString, length); - else if (length != 0) - throw NotImplemented(AlgorithmName() + ": this object does't support a special last block"); -} - -void AuthenticatedSymmetricCipher::SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength) -{ - if (headerLength > MaxHeaderLength()) - throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": header length " + IntToString(headerLength) + " exceeds the maximum of " + IntToString(MaxHeaderLength())); - - if (messageLength > MaxMessageLength()) - throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": message length " + IntToString(messageLength) + " exceeds the maximum of " + IntToString(MaxMessageLength())); - - if (footerLength > MaxFooterLength()) - throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": footer length " + IntToString(footerLength) + " exceeds the maximum of " + IntToString(MaxFooterLength())); - - UncheckedSpecifyDataLengths(headerLength, messageLength, footerLength); -} - -void AuthenticatedSymmetricCipher::EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *message, size_t messageLength) -{ - Resynchronize(iv, ivLength); - SpecifyDataLengths(headerLength, messageLength); - Update(header, headerLength); - ProcessString(ciphertext, message, messageLength); - TruncatedFinal(mac, macSize); -} - -bool AuthenticatedSymmetricCipher::DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *ciphertext, size_t ciphertextLength) -{ - Resynchronize(iv, ivLength); - SpecifyDataLengths(headerLength, ciphertextLength); - Update(header, headerLength); - ProcessString(message, ciphertext, ciphertextLength); - return TruncatedVerify(mac, macLength); -} - -unsigned int RandomNumberGenerator::GenerateBit() -{ - return GenerateByte() & 1; -} - -byte RandomNumberGenerator::GenerateByte() -{ - byte b; - GenerateBlock(&b, 1); - return b; -} - -word32 RandomNumberGenerator::GenerateWord32(word32 min, word32 max) -{ - word32 range = max-min; - const int maxBits = BitPrecision(range); - - word32 value; - - do - { - GenerateBlock((byte *)&value, sizeof(value)); - value = Crop(value, maxBits); - } while (value > range); - - return value+min; -} - -void RandomNumberGenerator::GenerateBlock(byte *output, size_t size) -{ - ArraySink s(output, size); - GenerateIntoBufferedTransformation(s, DEFAULT_CHANNEL, size); -} - -void RandomNumberGenerator::DiscardBytes(size_t n) -{ - GenerateIntoBufferedTransformation(TheBitBucket(), DEFAULT_CHANNEL, n); -} - -void RandomNumberGenerator::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length) -{ - FixedSizeSecBlock buffer; - while (length) - { - size_t len = UnsignedMin(buffer.size(), length); - GenerateBlock(buffer, len); - target.ChannelPut(channel, buffer, len); - length -= len; - } -} - -//! see NullRNG() -class ClassNullRNG : public RandomNumberGenerator -{ -public: - std::string AlgorithmName() const {return "NullRNG";} - void GenerateBlock(byte *output, size_t size) {throw NotImplemented("NullRNG: NullRNG should only be passed to functions that don't need to generate random bytes");} -}; - -RandomNumberGenerator & NullRNG() -{ - static ClassNullRNG s_nullRNG; - return s_nullRNG; -} - -bool HashTransformation::TruncatedVerify(const byte *digestIn, size_t digestLength) -{ - ThrowIfInvalidTruncatedSize(digestLength); - SecByteBlock digest(digestLength); - TruncatedFinal(digest, digestLength); - return VerifyBufsEqual(digest, digestIn, digestLength); -} - -void HashTransformation::ThrowIfInvalidTruncatedSize(size_t size) const -{ - if (size > DigestSize()) - throw InvalidArgument("HashTransformation: can't truncate a " + IntToString(DigestSize()) + " byte digest to " + IntToString(size) + " bytes"); -} - -unsigned int BufferedTransformation::GetMaxWaitObjectCount() const -{ - const BufferedTransformation *t = AttachedTransformation(); - return t ? t->GetMaxWaitObjectCount() : 0; -} - -void BufferedTransformation::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack) -{ - BufferedTransformation *t = AttachedTransformation(); - if (t) - t->GetWaitObjects(container, callStack); // reduce clutter by not adding to stack here -} - -void BufferedTransformation::Initialize(const NameValuePairs ¶meters, int propagation) -{ - assert(!AttachedTransformation()); - IsolatedInitialize(parameters); -} - -bool BufferedTransformation::Flush(bool hardFlush, int propagation, bool blocking) -{ - assert(!AttachedTransformation()); - return IsolatedFlush(hardFlush, blocking); -} - -bool BufferedTransformation::MessageSeriesEnd(int propagation, bool blocking) -{ - assert(!AttachedTransformation()); - return IsolatedMessageSeriesEnd(blocking); -} - -byte * BufferedTransformation::ChannelCreatePutSpace(const std::string &channel, size_t &size) -{ - if (channel.empty()) - return CreatePutSpace(size); - else - throw NoChannelSupport(AlgorithmName()); -} - -size_t BufferedTransformation::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) -{ - if (channel.empty()) - return Put2(begin, length, messageEnd, blocking); - else - throw NoChannelSupport(AlgorithmName()); -} - -size_t BufferedTransformation::ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking) -{ - if (channel.empty()) - return PutModifiable2(begin, length, messageEnd, blocking); - else - return ChannelPut2(channel, begin, length, messageEnd, blocking); -} - -bool BufferedTransformation::ChannelFlush(const std::string &channel, bool completeFlush, int propagation, bool blocking) -{ - if (channel.empty()) - return Flush(completeFlush, propagation, blocking); - else - throw NoChannelSupport(AlgorithmName()); -} - -bool BufferedTransformation::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking) -{ - if (channel.empty()) - return MessageSeriesEnd(propagation, blocking); - else - throw NoChannelSupport(AlgorithmName()); -} - -lword BufferedTransformation::MaxRetrievable() const -{ - if (AttachedTransformation()) - return AttachedTransformation()->MaxRetrievable(); - else - return CopyTo(TheBitBucket()); -} - -bool BufferedTransformation::AnyRetrievable() const -{ - if (AttachedTransformation()) - return AttachedTransformation()->AnyRetrievable(); - else - { - byte b; - return Peek(b) != 0; - } -} - -size_t BufferedTransformation::Get(byte &outByte) -{ - if (AttachedTransformation()) - return AttachedTransformation()->Get(outByte); - else - return Get(&outByte, 1); -} - -size_t BufferedTransformation::Get(byte *outString, size_t getMax) -{ - if (AttachedTransformation()) - return AttachedTransformation()->Get(outString, getMax); - else - { - ArraySink arraySink(outString, getMax); - return (size_t)TransferTo(arraySink, getMax); - } -} - -size_t BufferedTransformation::Peek(byte &outByte) const -{ - if (AttachedTransformation()) - return AttachedTransformation()->Peek(outByte); - else - return Peek(&outByte, 1); -} - -size_t BufferedTransformation::Peek(byte *outString, size_t peekMax) const -{ - if (AttachedTransformation()) - return AttachedTransformation()->Peek(outString, peekMax); - else - { - ArraySink arraySink(outString, peekMax); - return (size_t)CopyTo(arraySink, peekMax); - } -} - -lword BufferedTransformation::Skip(lword skipMax) -{ - if (AttachedTransformation()) - return AttachedTransformation()->Skip(skipMax); - else - return TransferTo(TheBitBucket(), skipMax); -} - -lword BufferedTransformation::TotalBytesRetrievable() const -{ - if (AttachedTransformation()) - return AttachedTransformation()->TotalBytesRetrievable(); - else - return MaxRetrievable(); -} - -unsigned int BufferedTransformation::NumberOfMessages() const -{ - if (AttachedTransformation()) - return AttachedTransformation()->NumberOfMessages(); - else - return CopyMessagesTo(TheBitBucket()); -} - -bool BufferedTransformation::AnyMessages() const -{ - if (AttachedTransformation()) - return AttachedTransformation()->AnyMessages(); - else - return NumberOfMessages() != 0; -} - -bool BufferedTransformation::GetNextMessage() -{ - if (AttachedTransformation()) - return AttachedTransformation()->GetNextMessage(); - else - { - assert(!AnyMessages()); - return false; - } -} - -unsigned int BufferedTransformation::SkipMessages(unsigned int count) -{ - if (AttachedTransformation()) - return AttachedTransformation()->SkipMessages(count); - else - return TransferMessagesTo(TheBitBucket(), count); -} - -size_t BufferedTransformation::TransferMessagesTo2(BufferedTransformation &target, unsigned int &messageCount, const std::string &channel, bool blocking) -{ - if (AttachedTransformation()) - return AttachedTransformation()->TransferMessagesTo2(target, messageCount, channel, blocking); - else - { - unsigned int maxMessages = messageCount; - for (messageCount=0; messageCount < maxMessages && AnyMessages(); messageCount++) - { - size_t blockedBytes; - lword transferredBytes; - - while (AnyRetrievable()) - { - transferredBytes = LWORD_MAX; - blockedBytes = TransferTo2(target, transferredBytes, channel, blocking); - if (blockedBytes > 0) - return blockedBytes; - } - - if (target.ChannelMessageEnd(channel, GetAutoSignalPropagation(), blocking)) - return 1; - - bool result = GetNextMessage(); - assert(result); - } - return 0; - } -} - -unsigned int BufferedTransformation::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const -{ - if (AttachedTransformation()) - return AttachedTransformation()->CopyMessagesTo(target, count, channel); - else - return 0; -} - -void BufferedTransformation::SkipAll() -{ - if (AttachedTransformation()) - AttachedTransformation()->SkipAll(); - else - { - while (SkipMessages()) {} - while (Skip()) {} - } -} - -size_t BufferedTransformation::TransferAllTo2(BufferedTransformation &target, const std::string &channel, bool blocking) -{ - if (AttachedTransformation()) - return AttachedTransformation()->TransferAllTo2(target, channel, blocking); - else - { - assert(!NumberOfMessageSeries()); - - unsigned int messageCount; - do - { - messageCount = UINT_MAX; - size_t blockedBytes = TransferMessagesTo2(target, messageCount, channel, blocking); - if (blockedBytes) - return blockedBytes; - } - while (messageCount != 0); - - lword byteCount; - do - { - byteCount = ULONG_MAX; - size_t blockedBytes = TransferTo2(target, byteCount, channel, blocking); - if (blockedBytes) - return blockedBytes; - } - while (byteCount != 0); - - return 0; - } -} - -void BufferedTransformation::CopyAllTo(BufferedTransformation &target, const std::string &channel) const -{ - if (AttachedTransformation()) - AttachedTransformation()->CopyAllTo(target, channel); - else - { - assert(!NumberOfMessageSeries()); - while (CopyMessagesTo(target, UINT_MAX, channel)) {} - } -} - -void BufferedTransformation::SetRetrievalChannel(const std::string &channel) -{ - if (AttachedTransformation()) - AttachedTransformation()->SetRetrievalChannel(channel); -} - -size_t BufferedTransformation::ChannelPutWord16(const std::string &channel, word16 value, ByteOrder order, bool blocking) -{ - PutWord(false, order, m_buf, value); - return ChannelPut(channel, m_buf, 2, blocking); -} - -size_t BufferedTransformation::ChannelPutWord32(const std::string &channel, word32 value, ByteOrder order, bool blocking) -{ - PutWord(false, order, m_buf, value); - return ChannelPut(channel, m_buf, 4, blocking); -} - -size_t BufferedTransformation::PutWord16(word16 value, ByteOrder order, bool blocking) -{ - return ChannelPutWord16(DEFAULT_CHANNEL, value, order, blocking); -} - -size_t BufferedTransformation::PutWord32(word32 value, ByteOrder order, bool blocking) -{ - return ChannelPutWord32(DEFAULT_CHANNEL, value, order, blocking); -} - -size_t BufferedTransformation::PeekWord16(word16 &value, ByteOrder order) const -{ - byte buf[2] = {0, 0}; - size_t len = Peek(buf, 2); - - if (order) - value = (buf[0] << 8) | buf[1]; - else - value = (buf[1] << 8) | buf[0]; - - return len; -} - -size_t BufferedTransformation::PeekWord32(word32 &value, ByteOrder order) const -{ - byte buf[4] = {0, 0, 0, 0}; - size_t len = Peek(buf, 4); - - if (order) - value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf [3]; - else - value = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf [0]; - - return len; -} - -size_t BufferedTransformation::GetWord16(word16 &value, ByteOrder order) -{ - return (size_t)Skip(PeekWord16(value, order)); -} - -size_t BufferedTransformation::GetWord32(word32 &value, ByteOrder order) -{ - return (size_t)Skip(PeekWord32(value, order)); -} - -void BufferedTransformation::Attach(BufferedTransformation *newOut) -{ - if (AttachedTransformation() && AttachedTransformation()->Attachable()) - AttachedTransformation()->Attach(newOut); - else - Detach(newOut); -} - -void GeneratableCryptoMaterial::GenerateRandomWithKeySize(RandomNumberGenerator &rng, unsigned int keySize) -{ - GenerateRandom(rng, MakeParameters("KeySize", (int)keySize)); -} - -class PK_DefaultEncryptionFilter : public Unflushable -{ -public: - PK_DefaultEncryptionFilter(RandomNumberGenerator &rng, const PK_Encryptor &encryptor, BufferedTransformation *attachment, const NameValuePairs ¶meters) - : m_rng(rng), m_encryptor(encryptor), m_parameters(parameters) - { - Detach(attachment); - } - - size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) - { - FILTER_BEGIN; - m_plaintextQueue.Put(inString, length); - - if (messageEnd) - { - { - size_t plaintextLength; - if (!SafeConvert(m_plaintextQueue.CurrentSize(), plaintextLength)) - throw InvalidArgument("PK_DefaultEncryptionFilter: plaintext too long"); - size_t ciphertextLength = m_encryptor.CiphertextLength(plaintextLength); - - SecByteBlock plaintext(plaintextLength); - m_plaintextQueue.Get(plaintext, plaintextLength); - m_ciphertext.resize(ciphertextLength); - m_encryptor.Encrypt(m_rng, plaintext, plaintextLength, m_ciphertext, m_parameters); - } - - FILTER_OUTPUT(1, m_ciphertext, m_ciphertext.size(), messageEnd); - } - FILTER_END_NO_MESSAGE_END; - } - - RandomNumberGenerator &m_rng; - const PK_Encryptor &m_encryptor; - const NameValuePairs &m_parameters; - ByteQueue m_plaintextQueue; - SecByteBlock m_ciphertext; -}; - -BufferedTransformation * PK_Encryptor::CreateEncryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment, const NameValuePairs ¶meters) const -{ - return new PK_DefaultEncryptionFilter(rng, *this, attachment, parameters); -} - -class PK_DefaultDecryptionFilter : public Unflushable -{ -public: - PK_DefaultDecryptionFilter(RandomNumberGenerator &rng, const PK_Decryptor &decryptor, BufferedTransformation *attachment, const NameValuePairs ¶meters) - : m_rng(rng), m_decryptor(decryptor), m_parameters(parameters) - { - Detach(attachment); - } - - size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) - { - FILTER_BEGIN; - m_ciphertextQueue.Put(inString, length); - - if (messageEnd) - { - { - size_t ciphertextLength; - if (!SafeConvert(m_ciphertextQueue.CurrentSize(), ciphertextLength)) - throw InvalidArgument("PK_DefaultDecryptionFilter: ciphertext too long"); - size_t maxPlaintextLength = m_decryptor.MaxPlaintextLength(ciphertextLength); - - SecByteBlock ciphertext(ciphertextLength); - m_ciphertextQueue.Get(ciphertext, ciphertextLength); - m_plaintext.resize(maxPlaintextLength); - m_result = m_decryptor.Decrypt(m_rng, ciphertext, ciphertextLength, m_plaintext, m_parameters); - if (!m_result.isValidCoding) - throw InvalidCiphertext(m_decryptor.AlgorithmName() + ": invalid ciphertext"); - } - - FILTER_OUTPUT(1, m_plaintext, m_result.messageLength, messageEnd); - } - FILTER_END_NO_MESSAGE_END; - } - - RandomNumberGenerator &m_rng; - const PK_Decryptor &m_decryptor; - const NameValuePairs &m_parameters; - ByteQueue m_ciphertextQueue; - SecByteBlock m_plaintext; - DecodingResult m_result; -}; - -BufferedTransformation * PK_Decryptor::CreateDecryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment, const NameValuePairs ¶meters) const -{ - return new PK_DefaultDecryptionFilter(rng, *this, attachment, parameters); -} - -size_t PK_Signer::Sign(RandomNumberGenerator &rng, PK_MessageAccumulator *messageAccumulator, byte *signature) const -{ - std::auto_ptr m(messageAccumulator); - return SignAndRestart(rng, *m, signature, false); -} - -size_t PK_Signer::SignMessage(RandomNumberGenerator &rng, const byte *message, size_t messageLen, byte *signature) const -{ - std::auto_ptr m(NewSignatureAccumulator(rng)); - m->Update(message, messageLen); - return SignAndRestart(rng, *m, signature, false); -} - -size_t PK_Signer::SignMessageWithRecovery(RandomNumberGenerator &rng, const byte *recoverableMessage, size_t recoverableMessageLength, - const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, byte *signature) const -{ - std::auto_ptr m(NewSignatureAccumulator(rng)); - InputRecoverableMessage(*m, recoverableMessage, recoverableMessageLength); - m->Update(nonrecoverableMessage, nonrecoverableMessageLength); - return SignAndRestart(rng, *m, signature, false); -} - -bool PK_Verifier::Verify(PK_MessageAccumulator *messageAccumulator) const -{ - std::auto_ptr m(messageAccumulator); - return VerifyAndRestart(*m); -} - -bool PK_Verifier::VerifyMessage(const byte *message, size_t messageLen, const byte *signature, size_t signatureLength) const -{ - std::auto_ptr m(NewVerificationAccumulator()); - InputSignature(*m, signature, signatureLength); - m->Update(message, messageLen); - return VerifyAndRestart(*m); -} - -DecodingResult PK_Verifier::Recover(byte *recoveredMessage, PK_MessageAccumulator *messageAccumulator) const -{ - std::auto_ptr m(messageAccumulator); - return RecoverAndRestart(recoveredMessage, *m); -} - -DecodingResult PK_Verifier::RecoverMessage(byte *recoveredMessage, - const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, - const byte *signature, size_t signatureLength) const -{ - std::auto_ptr m(NewVerificationAccumulator()); - InputSignature(*m, signature, signatureLength); - m->Update(nonrecoverableMessage, nonrecoverableMessageLength); - return RecoverAndRestart(recoveredMessage, *m); -} - -void SimpleKeyAgreementDomain::GenerateKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const -{ - GeneratePrivateKey(rng, privateKey); - GeneratePublicKey(rng, privateKey, publicKey); -} - -void AuthenticatedKeyAgreementDomain::GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const -{ - GenerateStaticPrivateKey(rng, privateKey); - GenerateStaticPublicKey(rng, privateKey, publicKey); -} - -void AuthenticatedKeyAgreementDomain::GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const -{ - GenerateEphemeralPrivateKey(rng, privateKey); - GenerateEphemeralPublicKey(rng, privateKey, publicKey); -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/cryptlib.dsp b/embeddedcryptopp/cryptlib.dsp deleted file mode 100644 index 8bbb6ea..0000000 --- a/embeddedcryptopp/cryptlib.dsp +++ /dev/null @@ -1,1204 +0,0 @@ -# Microsoft Developer Studio Project File - Name="cryptlib" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -CFG=cryptlib - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "cryptlib.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "cryptlib.mak" CFG="cryptlib - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "cryptlib - Win32 DLL-Import Release" (based on "Win32 (x86) Static Library") -!MESSAGE "cryptlib - Win32 DLL-Import Debug" (based on "Win32 (x86) Static Library") -!MESSAGE "cryptlib - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "cryptlib - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "cryptlib - Win32 DLL-Import Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "cryptlib___Win32_FIPS_140_Release" -# PROP BASE Intermediate_Dir "cryptlib___Win32_FIPS_140_Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "DLL_Import_Release" -# PROP Intermediate_Dir "DLL_Import_Release" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /G5 /Gz /MT /W3 /GX /Zi /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /Yu"pch.h" /FD /c -# ADD CPP /nologo /G5 /Gz /MT /W3 /GR /GX /Zi /O2 /Ob2 /D "NDEBUG" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /D "WIN32" /D "CRYPTOPP_IMPORTS" /Yu"pch.h" /FD /Zm400 /c -# ADD BASE RSC /l 0x409 -# ADD RSC /l 0x409 -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo - -!ELSEIF "$(CFG)" == "cryptlib - Win32 DLL-Import Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "cryptlib___Win32_FIPS_140_Debug" -# PROP BASE Intermediate_Dir "cryptlib___Win32_FIPS_140_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "DLL_Import_Debug" -# PROP Intermediate_Dir "DLL_Import_Debug" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /Yu"pch.h" /FD /c -# ADD CPP /nologo /G5 /Gz /MTd /W3 /GR /GX /Zi /Oi /D "_DEBUG" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /D "WIN32" /D "CRYPTOPP_IMPORTS" /Yu"pch.h" /FD /Zm400 /c -# ADD BASE RSC /l 0x409 -# ADD RSC /l 0x409 -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo - -!ELSEIF "$(CFG)" == "cryptlib - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "cryptlib" -# PROP BASE Intermediate_Dir "cryptlib" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GR /GX /Zi /O2 /Ob2 /D "NDEBUG" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /D "WIN32" /Yu"pch.h" /FD /Zm400 /c -# ADD BASE RSC /l 0x409 -# ADD RSC /l 0x409 -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo - -!ELSEIF "$(CFG)" == "cryptlib - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "cryptli0" -# PROP BASE Intermediate_Dir "cryptli0" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c -# ADD CPP /nologo /MTd /W3 /GR /GX /Zi /Oi /D "_DEBUG" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /D "WIN32" /Yu"pch.h" /FD /Zm400 /c -# ADD BASE RSC /l 0x409 -# ADD RSC /l 0x409 -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo - -!ENDIF - -# Begin Target - -# Name "cryptlib - Win32 DLL-Import Release" -# Name "cryptlib - Win32 DLL-Import Debug" -# Name "cryptlib - Win32 Release" -# Name "cryptlib - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter ".cpp" -# Begin Source File - -SOURCE=.\3way.cpp -# End Source File -# Begin Source File - -SOURCE=.\adhoc.cpp.proto - -!IF "$(CFG)" == "cryptlib - Win32 DLL-Import Release" - -# Begin Custom Build -InputPath=.\adhoc.cpp.proto - -"adhoc.cpp.copied" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - if not exist adhoc.cpp copy "$(InputPath)" adhoc.cpp - echo: >> adhoc.cpp.copied - -# End Custom Build - -!ELSEIF "$(CFG)" == "cryptlib - Win32 DLL-Import Debug" - -# Begin Custom Build -InputPath=.\adhoc.cpp.proto - -"adhoc.cpp.copied" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - if not exist adhoc.cpp copy "$(InputPath)" adhoc.cpp - echo: >> adhoc.cpp.copied - -# End Custom Build - -!ELSEIF "$(CFG)" == "cryptlib - Win32 Release" - -# Begin Custom Build -InputPath=.\adhoc.cpp.proto - -"adhoc.cpp.copied" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - if not exist adhoc.cpp copy "$(InputPath)" adhoc.cpp - echo: >> adhoc.cpp.copied - -# End Custom Build - -!ELSEIF "$(CFG)" == "cryptlib - Win32 Debug" - -# Begin Custom Build -InputPath=.\adhoc.cpp.proto - -"adhoc.cpp.copied" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - if not exist adhoc.cpp copy "$(InputPath)" adhoc.cpp - echo: >> adhoc.cpp.copied - -# End Custom Build - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\adler32.cpp -# End Source File -# Begin Source File - -SOURCE=.\algebra.cpp -# End Source File -# Begin Source File - -SOURCE=.\algparam.cpp -# End Source File -# Begin Source File - -SOURCE=.\arc4.cpp -# End Source File -# Begin Source File - -SOURCE=.\asn.cpp -# End Source File -# Begin Source File - -SOURCE=.\authenc.cpp -# End Source File -# Begin Source File - -SOURCE=.\base32.cpp -# End Source File -# Begin Source File - -SOURCE=.\base64.cpp -# End Source File -# Begin Source File - -SOURCE=.\basecode.cpp -# End Source File -# Begin Source File - -SOURCE=.\bfinit.cpp -# End Source File -# Begin Source File - -SOURCE=.\blowfish.cpp -# End Source File -# Begin Source File - -SOURCE=.\blumshub.cpp -# End Source File -# Begin Source File - -SOURCE=.\camellia.cpp -# End Source File -# Begin Source File - -SOURCE=.\cast.cpp -# End Source File -# Begin Source File - -SOURCE=.\casts.cpp -# End Source File -# Begin Source File - -SOURCE=.\cbcmac.cpp -# End Source File -# Begin Source File - -SOURCE=.\ccm.cpp -# End Source File -# Begin Source File - -SOURCE=.\channels.cpp -# End Source File -# Begin Source File - -SOURCE=.\cmac.cpp -# End Source File -# Begin Source File - -SOURCE=.\cpu.cpp -# End Source File -# Begin Source File - -SOURCE=.\crc.cpp -# End Source File -# Begin Source File - -SOURCE=.\cryptlib.cpp -# End Source File -# Begin Source File - -SOURCE=.\default.cpp -# End Source File -# Begin Source File - -SOURCE=.\des.cpp -# End Source File -# Begin Source File - -SOURCE=.\dessp.cpp -# End Source File -# Begin Source File - -SOURCE=.\dh.cpp -# End Source File -# Begin Source File - -SOURCE=.\dh2.cpp -# End Source File -# Begin Source File - -SOURCE=.\dll.cpp -# SUBTRACT CPP /YX /Yc /Yu -# End Source File -# Begin Source File - -SOURCE=.\dsa.cpp -# End Source File -# Begin Source File - -SOURCE=.\eax.cpp -# End Source File -# Begin Source File - -SOURCE=.\ec2n.cpp -# End Source File -# Begin Source File - -SOURCE=.\eccrypto.cpp -# End Source File -# Begin Source File - -SOURCE=.\ecp.cpp -# End Source File -# Begin Source File - -SOURCE=.\elgamal.cpp -# End Source File -# Begin Source File - -SOURCE=.\emsa2.cpp -# End Source File -# Begin Source File - -SOURCE=.\eprecomp.cpp -# End Source File -# Begin Source File - -SOURCE=.\esign.cpp -# End Source File -# Begin Source File - -SOURCE=.\files.cpp -# End Source File -# Begin Source File - -SOURCE=.\filters.cpp -# End Source File -# Begin Source File - -SOURCE=.\fips140.cpp -# End Source File -# Begin Source File - -SOURCE=.\fipstest.cpp -# End Source File -# Begin Source File - -SOURCE=.\gcm.cpp -# End Source File -# Begin Source File - -SOURCE=.\gf256.cpp -# End Source File -# Begin Source File - -SOURCE=.\gf2_32.cpp -# End Source File -# Begin Source File - -SOURCE=.\gf2n.cpp -# End Source File -# Begin Source File - -SOURCE=.\gfpcrypt.cpp -# End Source File -# Begin Source File - -SOURCE=.\gost.cpp -# End Source File -# Begin Source File - -SOURCE=.\gzip.cpp -# End Source File -# Begin Source File - -SOURCE=.\hex.cpp -# End Source File -# Begin Source File - -SOURCE=.\hmac.cpp -# End Source File -# Begin Source File - -SOURCE=.\hrtimer.cpp -# End Source File -# Begin Source File - -SOURCE=.\ida.cpp -# End Source File -# Begin Source File - -SOURCE=.\idea.cpp -# End Source File -# Begin Source File - -SOURCE=.\integer.cpp -# End Source File -# Begin Source File - -SOURCE=.\iterhash.cpp -# SUBTRACT CPP /YX /Yc /Yu -# End Source File -# Begin Source File - -SOURCE=.\luc.cpp -# End Source File -# Begin Source File - -SOURCE=.\mars.cpp -# End Source File -# Begin Source File - -SOURCE=.\marss.cpp -# End Source File -# Begin Source File - -SOURCE=.\md2.cpp -# End Source File -# Begin Source File - -SOURCE=.\md4.cpp -# End Source File -# Begin Source File - -SOURCE=.\md5.cpp -# End Source File -# Begin Source File - -SOURCE=.\misc.cpp -# End Source File -# Begin Source File - -SOURCE=.\modes.cpp -# End Source File -# Begin Source File - -SOURCE=.\mqueue.cpp -# End Source File -# Begin Source File - -SOURCE=.\mqv.cpp -# End Source File -# Begin Source File - -SOURCE=.\nbtheory.cpp -# End Source File -# Begin Source File - -SOURCE=.\network.cpp -# End Source File -# Begin Source File - -SOURCE=.\oaep.cpp -# End Source File -# Begin Source File - -SOURCE=.\osrng.cpp -# End Source File -# Begin Source File - -SOURCE=.\panama.cpp -# End Source File -# Begin Source File - -SOURCE=.\pch.cpp -# ADD CPP /Yc"pch.h" -# End Source File -# Begin Source File - -SOURCE=.\pkcspad.cpp -# End Source File -# Begin Source File - -SOURCE=.\polynomi.cpp -# End Source File -# Begin Source File - -SOURCE=.\pssr.cpp -# End Source File -# Begin Source File - -SOURCE=.\pubkey.cpp -# End Source File -# Begin Source File - -SOURCE=.\queue.cpp -# End Source File -# Begin Source File - -SOURCE=.\rabin.cpp -# End Source File -# Begin Source File - -SOURCE=.\randpool.cpp -# End Source File -# Begin Source File - -SOURCE=.\rc2.cpp -# End Source File -# Begin Source File - -SOURCE=.\rc5.cpp -# End Source File -# Begin Source File - -SOURCE=.\rc6.cpp -# End Source File -# Begin Source File - -SOURCE=.\rdtables.cpp -# End Source File -# Begin Source File - -SOURCE=.\rijndael.cpp -# End Source File -# Begin Source File - -SOURCE=.\ripemd.cpp -# End Source File -# Begin Source File - -SOURCE=.\rng.cpp -# End Source File -# Begin Source File - -SOURCE=.\rsa.cpp -# End Source File -# Begin Source File - -SOURCE=.\rw.cpp -# End Source File -# Begin Source File - -SOURCE=.\safer.cpp -# End Source File -# Begin Source File - -SOURCE=.\salsa.cpp -# End Source File -# Begin Source File - -SOURCE=.\seal.cpp -# End Source File -# Begin Source File - -SOURCE=.\seed.cpp -# End Source File -# Begin Source File - -SOURCE=.\serpent.cpp -# End Source File -# Begin Source File - -SOURCE=.\sha.cpp -# End Source File -# Begin Source File - -SOURCE=.\shacal2.cpp -# End Source File -# Begin Source File - -SOURCE=.\shark.cpp -# End Source File -# Begin Source File - -SOURCE=.\sharkbox.cpp -# End Source File -# Begin Source File - -SOURCE=.\simple.cpp -# End Source File -# Begin Source File - -SOURCE=.\skipjack.cpp -# End Source File -# Begin Source File - -SOURCE=.\socketft.cpp -# End Source File -# Begin Source File - -SOURCE=.\sosemanuk.cpp -# End Source File -# Begin Source File - -SOURCE=.\square.cpp -# End Source File -# Begin Source File - -SOURCE=.\squaretb.cpp -# End Source File -# Begin Source File - -SOURCE=.\strciphr.cpp -# End Source File -# Begin Source File - -SOURCE=.\tea.cpp -# End Source File -# Begin Source File - -SOURCE=.\tftables.cpp -# End Source File -# Begin Source File - -SOURCE=.\tiger.cpp -# End Source File -# Begin Source File - -SOURCE=.\tigertab.cpp -# End Source File -# Begin Source File - -SOURCE=.\trdlocal.cpp -# End Source File -# Begin Source File - -SOURCE=.\ttmac.cpp -# End Source File -# Begin Source File - -SOURCE=.\twofish.cpp -# End Source File -# Begin Source File - -SOURCE=.\vmac.cpp -# End Source File -# Begin Source File - -SOURCE=.\wait.cpp -# End Source File -# Begin Source File - -SOURCE=.\wake.cpp -# End Source File -# Begin Source File - -SOURCE=.\whrlpool.cpp -# End Source File -# Begin Source File - -SOURCE=.\winpipes.cpp -# End Source File -# Begin Source File - -SOURCE=.\xtr.cpp -# End Source File -# Begin Source File - -SOURCE=.\xtrcrypt.cpp -# End Source File -# Begin Source File - -SOURCE=.\zdeflate.cpp -# End Source File -# Begin Source File - -SOURCE=.\zinflate.cpp -# End Source File -# Begin Source File - -SOURCE=.\zlib.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter ".;.h" -# Begin Source File - -SOURCE=.\3way.h -# End Source File -# Begin Source File - -SOURCE=.\adler32.h -# End Source File -# Begin Source File - -SOURCE=.\aes.h -# End Source File -# Begin Source File - -SOURCE=.\algebra.h -# End Source File -# Begin Source File - -SOURCE=.\algparam.h -# End Source File -# Begin Source File - -SOURCE=.\arc4.h -# End Source File -# Begin Source File - -SOURCE=.\argnames.h -# End Source File -# Begin Source File - -SOURCE=.\asn.h -# End Source File -# Begin Source File - -SOURCE=.\authenc.h -# End Source File -# Begin Source File - -SOURCE=.\base32.h -# End Source File -# Begin Source File - -SOURCE=.\base64.h -# End Source File -# Begin Source File - -SOURCE=.\basecode.h -# End Source File -# Begin Source File - -SOURCE=.\blowfish.h -# End Source File -# Begin Source File - -SOURCE=.\blumshub.h -# End Source File -# Begin Source File - -SOURCE=.\camellia.h -# End Source File -# Begin Source File - -SOURCE=.\cast.h -# End Source File -# Begin Source File - -SOURCE=.\cbcmac.h -# End Source File -# Begin Source File - -SOURCE=.\ccm.h -# End Source File -# Begin Source File - -SOURCE=.\channels.h -# End Source File -# Begin Source File - -SOURCE=.\cmac.h -# End Source File -# Begin Source File - -SOURCE=.\config.h -# End Source File -# Begin Source File - -SOURCE=.\crc.h -# End Source File -# Begin Source File - -SOURCE=.\cryptlib.h -# End Source File -# Begin Source File - -SOURCE=.\default.h -# End Source File -# Begin Source File - -SOURCE=.\des.h -# End Source File -# Begin Source File - -SOURCE=.\dh.h -# End Source File -# Begin Source File - -SOURCE=.\dh2.h -# End Source File -# Begin Source File - -SOURCE=.\dmac.h -# End Source File -# Begin Source File - -SOURCE=.\dsa.h -# End Source File -# Begin Source File - -SOURCE=.\dword.h -# End Source File -# Begin Source File - -SOURCE=.\eax.h -# End Source File -# Begin Source File - -SOURCE=.\ec2n.h -# End Source File -# Begin Source File - -SOURCE=.\eccrypto.h -# End Source File -# Begin Source File - -SOURCE=.\ecp.h -# End Source File -# Begin Source File - -SOURCE=.\elgamal.h -# End Source File -# Begin Source File - -SOURCE=.\emsa2.h -# End Source File -# Begin Source File - -SOURCE=.\eprecomp.h -# End Source File -# Begin Source File - -SOURCE=.\esign.h -# End Source File -# Begin Source File - -SOURCE=.\factory.h -# End Source File -# Begin Source File - -SOURCE=.\files.h -# End Source File -# Begin Source File - -SOURCE=.\filters.h -# End Source File -# Begin Source File - -SOURCE=.\fips140.h -# End Source File -# Begin Source File - -SOURCE=.\fltrimpl.h -# End Source File -# Begin Source File - -SOURCE=.\gcm.h -# End Source File -# Begin Source File - -SOURCE=.\gf256.h -# End Source File -# Begin Source File - -SOURCE=.\gf2_32.h -# End Source File -# Begin Source File - -SOURCE=.\gf2n.h -# End Source File -# Begin Source File - -SOURCE=.\gfpcrypt.h -# End Source File -# Begin Source File - -SOURCE=.\gost.h -# End Source File -# Begin Source File - -SOURCE=.\gzip.h -# End Source File -# Begin Source File - -SOURCE=.\hex.h -# End Source File -# Begin Source File - -SOURCE=.\hmac.h -# End Source File -# Begin Source File - -SOURCE=.\hrtimer.h -# End Source File -# Begin Source File - -SOURCE=.\ida.h -# End Source File -# Begin Source File - -SOURCE=.\idea.h -# End Source File -# Begin Source File - -SOURCE=.\integer.h -# End Source File -# Begin Source File - -SOURCE=.\iterhash.h -# End Source File -# Begin Source File - -SOURCE=.\lubyrack.h -# End Source File -# Begin Source File - -SOURCE=.\luc.h -# End Source File -# Begin Source File - -SOURCE=.\mars.h -# End Source File -# Begin Source File - -SOURCE=.\md2.h -# End Source File -# Begin Source File - -SOURCE=.\md4.h -# End Source File -# Begin Source File - -SOURCE=.\md5.h -# End Source File -# Begin Source File - -SOURCE=.\mdc.h -# End Source File -# Begin Source File - -SOURCE=.\misc.h -# End Source File -# Begin Source File - -SOURCE=.\modarith.h -# End Source File -# Begin Source File - -SOURCE=.\modes.h -# End Source File -# Begin Source File - -SOURCE=.\modexppc.h -# End Source File -# Begin Source File - -SOURCE=.\mqueue.h -# End Source File -# Begin Source File - -SOURCE=.\mqv.h -# End Source File -# Begin Source File - -SOURCE=.\nbtheory.h -# End Source File -# Begin Source File - -SOURCE=.\network.h -# End Source File -# Begin Source File - -SOURCE=.\nr.h -# End Source File -# Begin Source File - -SOURCE=.\oaep.h -# End Source File -# Begin Source File - -SOURCE=.\oids.h -# End Source File -# Begin Source File - -SOURCE=.\osrng.h -# End Source File -# Begin Source File - -SOURCE=.\panama.h -# End Source File -# Begin Source File - -SOURCE=.\pch.h -# End Source File -# Begin Source File - -SOURCE=.\pkcspad.h -# End Source File -# Begin Source File - -SOURCE=.\polynomi.h -# End Source File -# Begin Source File - -SOURCE=.\pssr.h -# End Source File -# Begin Source File - -SOURCE=.\pubkey.h -# End Source File -# Begin Source File - -SOURCE=.\pwdbased.h -# End Source File -# Begin Source File - -SOURCE=.\queue.h -# End Source File -# Begin Source File - -SOURCE=.\rabin.h -# End Source File -# Begin Source File - -SOURCE=.\randpool.h -# End Source File -# Begin Source File - -SOURCE=.\rc2.h -# End Source File -# Begin Source File - -SOURCE=.\rc5.h -# End Source File -# Begin Source File - -SOURCE=.\rc6.h -# End Source File -# Begin Source File - -SOURCE=.\rijndael.h -# End Source File -# Begin Source File - -SOURCE=.\ripemd.h -# End Source File -# Begin Source File - -SOURCE=.\rng.h -# End Source File -# Begin Source File - -SOURCE=.\rsa.h -# End Source File -# Begin Source File - -SOURCE=.\rw.h -# End Source File -# Begin Source File - -SOURCE=.\safer.h -# End Source File -# Begin Source File - -SOURCE=.\salsa.h -# End Source File -# Begin Source File - -SOURCE=.\seal.h -# End Source File -# Begin Source File - -SOURCE=.\secblock.h -# End Source File -# Begin Source File - -SOURCE=.\seckey.h -# End Source File -# Begin Source File - -SOURCE=.\seed.h -# End Source File -# Begin Source File - -SOURCE=.\serpent.h -# End Source File -# Begin Source File - -SOURCE=.\sha.h -# End Source File -# Begin Source File - -SOURCE=.\shacal2.h -# End Source File -# Begin Source File - -SOURCE=.\shark.h -# End Source File -# Begin Source File - -SOURCE=.\simple.h -# End Source File -# Begin Source File - -SOURCE=.\skipjack.h -# End Source File -# Begin Source File - -SOURCE=.\smartptr.h -# End Source File -# Begin Source File - -SOURCE=.\socketft.h -# End Source File -# Begin Source File - -SOURCE=.\square.h -# End Source File -# Begin Source File - -SOURCE=.\strciphr.h -# End Source File -# Begin Source File - -SOURCE=.\tea.h -# End Source File -# Begin Source File - -SOURCE=.\tiger.h -# End Source File -# Begin Source File - -SOURCE=.\trdlocal.h -# End Source File -# Begin Source File - -SOURCE=.\trunhash.h -# End Source File -# Begin Source File - -SOURCE=.\ttmac.h -# End Source File -# Begin Source File - -SOURCE=.\twofish.h -# End Source File -# Begin Source File - -SOURCE=.\wait.h -# End Source File -# Begin Source File - -SOURCE=.\wake.h -# End Source File -# Begin Source File - -SOURCE=.\whrlpool.h -# End Source File -# Begin Source File - -SOURCE=.\winpipes.h -# End Source File -# Begin Source File - -SOURCE=.\words.h -# End Source File -# Begin Source File - -SOURCE=.\xtr.h -# End Source File -# Begin Source File - -SOURCE=.\xtrcrypt.h -# End Source File -# Begin Source File - -SOURCE=.\zdeflate.h -# End Source File -# Begin Source File - -SOURCE=.\zinflate.h -# End Source File -# Begin Source File - -SOURCE=.\zlib.h -# End Source File -# End Group -# Begin Group "Miscellaneous" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\Doxyfile -# End Source File -# Begin Source File - -SOURCE=.\GNUmakefile -# End Source File -# Begin Source File - -SOURCE=.\license.txt -# End Source File -# Begin Source File - -SOURCE=.\readme.txt -# End Source File -# End Group -# End Target -# End Project diff --git a/embeddedcryptopp/cryptlib.h b/embeddedcryptopp/cryptlib.h deleted file mode 100644 index 15cd6da..0000000 --- a/embeddedcryptopp/cryptlib.h +++ /dev/null @@ -1,1668 +0,0 @@ -// cryptlib.h - written and placed in the public domain by Wei Dai -/*! \file - This file contains the declarations for the abstract base - classes that provide a uniform interface to this library. -*/ - -/*! \mainpage Crypto++ Library 5.6.0 API Reference -
-
Abstract Base Classes
- cryptlib.h -
Authenticated Encryption
- AuthenticatedSymmetricCipherDocumentation -
Symmetric Ciphers
- SymmetricCipherDocumentation -
Hash Functions
- SHA1, SHA224, SHA256, SHA384, SHA512, Tiger, Whirlpool, RIPEMD160, RIPEMD320, RIPEMD128, RIPEMD256, Weak1::MD2, Weak1::MD4, Weak1::MD5 -
Non-Cryptographic Checksums
- CRC32, Adler32 -
Message Authentication Codes
- VMAC, HMAC, CBC_MAC, CMAC, DMAC, TTMAC, GCM (GMAC) -
Random Number Generators
- NullRNG(), LC_RNG, RandomPool, BlockingRng, NonblockingRng, AutoSeededRandomPool, AutoSeededX917RNG, DefaultAutoSeededRNG -
Password-based Cryptography
- PasswordBasedKeyDerivationFunction -
Public Key Cryptosystems
- DLIES, ECIES, LUCES, RSAES, RabinES, LUC_IES -
Public Key Signature Schemes
- DSA, GDSA, ECDSA, NR, ECNR, LUCSS, RSASS, RSASS_ISO, RabinSS, RWSS, ESIGN -
Key Agreement
- #DH, DH2, #MQV, ECDH, ECMQV, XTR_DH -
Algebraic Structures
- Integer, PolynomialMod2, PolynomialOver, RingOfPolynomialsOver, - ModularArithmetic, MontgomeryRepresentation, GFP2_ONB, - GF2NP, GF256, GF2_32, EC2N, ECP -
Secret Sharing and Information Dispersal
- SecretSharing, SecretRecovery, InformationDispersal, InformationRecovery -
Compression
- Deflator, Inflator, Gzip, Gunzip, ZlibCompressor, ZlibDecompressor -
Input Source Classes
- StringSource, ArraySource, FileSource, SocketSource, WindowsPipeSource, RandomNumberSource -
Output Sink Classes
- StringSinkTemplate, ArraySink, FileSink, SocketSink, WindowsPipeSink, RandomNumberSink -
Filter Wrappers
- StreamTransformationFilter, HashFilter, HashVerificationFilter, SignerFilter, SignatureVerificationFilter -
Binary to Text Encoders and Decoders
- HexEncoder, HexDecoder, Base64Encoder, Base64Decoder, Base32Encoder, Base32Decoder -
Wrappers for OS features
- Timer, Socket, WindowsHandle, ThreadLocalStorage, ThreadUserTimer -
FIPS 140 related
- fips140.h -
- -In the FIPS 140-2 validated DLL version of Crypto++, only the following implementation class are available. -
-
Block Ciphers
- AES, DES_EDE2, DES_EDE3, SKIPJACK -
Cipher Modes (replace template parameter BC with one of the block ciphers above)
- ECB_Mode\, CTR_Mode\, CBC_Mode\, CFB_FIPS_Mode\, OFB_Mode\ -
Hash Functions
- SHA1, SHA224, SHA256, SHA384, SHA512 -
Public Key Signature Schemes (replace template parameter H with one of the hash functions above)
- RSASS\, RSASS\, RSASS_ISO\, RWSS\, DSA, ECDSA\, ECDSA\ -
Message Authentication Codes (replace template parameter H with one of the hash functions above)
- HMAC\, CBC_MAC\, CBC_MAC\ -
Random Number Generators
- DefaultAutoSeededRNG (AutoSeededX917RNG\) -
Key Agreement
- #DH -
Public Key Cryptosystems
- RSAES\ \> -
- -

This reference manual is a work in progress. Some classes are still lacking detailed descriptions. -

Click here to download a zip archive containing this manual. -

Thanks to Ryan Phillips for providing the Doxygen configuration file -and getting me started with this manual. -*/ - -#ifndef CRYPTOPP_CRYPTLIB_H -#define CRYPTOPP_CRYPTLIB_H - -#include "config.h" -#include "stdcpp.h" - -NAMESPACE_BEGIN(CryptoPP) - -// forward declarations -class Integer; -class RandomNumberGenerator; -class BufferedTransformation; - -//! used to specify a direction for a cipher to operate in (encrypt or decrypt) -enum CipherDir {ENCRYPTION, DECRYPTION}; - -//! used to represent infinite time -const unsigned long INFINITE_TIME = ULONG_MAX; - -// VC60 workaround: using enums as template parameters causes problems -template -struct EnumToType -{ - static ENUM_TYPE ToEnum() {return (ENUM_TYPE)VALUE;} -}; - -enum ByteOrder {LITTLE_ENDIAN_ORDER = 0, BIG_ENDIAN_ORDER = 1}; -typedef EnumToType LittleEndian; -typedef EnumToType BigEndian; - -//! base class for all exceptions thrown by Crypto++ -class CRYPTOPP_DLL Exception : public std::exception -{ -public: - //! error types - enum ErrorType { - //! a method is not implemented - NOT_IMPLEMENTED, - //! invalid function argument - INVALID_ARGUMENT, - //! BufferedTransformation received a Flush(true) signal but can't flush buffers - CANNOT_FLUSH, - //! data integerity check (such as CRC or MAC) failed - DATA_INTEGRITY_CHECK_FAILED, - //! received input data that doesn't conform to expected format - INVALID_DATA_FORMAT, - //! error reading from input device or writing to output device - IO_ERROR, - //! some error not belong to any of the above categories - OTHER_ERROR - }; - - explicit Exception(ErrorType errorType, const std::string &s) : m_errorType(errorType), m_what(s) {} - virtual ~Exception() throw() {} - const char *what() const throw() {return (m_what.c_str());} - const std::string &GetWhat() const {return m_what;} - void SetWhat(const std::string &s) {m_what = s;} - ErrorType GetErrorType() const {return m_errorType;} - void SetErrorType(ErrorType errorType) {m_errorType = errorType;} - -private: - ErrorType m_errorType; - std::string m_what; -}; - -//! exception thrown when an invalid argument is detected -class CRYPTOPP_DLL InvalidArgument : public Exception -{ -public: - explicit InvalidArgument(const std::string &s) : Exception(INVALID_ARGUMENT, s) {} -}; - -//! exception thrown when input data is received that doesn't conform to expected format -class CRYPTOPP_DLL InvalidDataFormat : public Exception -{ -public: - explicit InvalidDataFormat(const std::string &s) : Exception(INVALID_DATA_FORMAT, s) {} -}; - -//! exception thrown by decryption filters when trying to decrypt an invalid ciphertext -class CRYPTOPP_DLL InvalidCiphertext : public InvalidDataFormat -{ -public: - explicit InvalidCiphertext(const std::string &s) : InvalidDataFormat(s) {} -}; - -//! exception thrown by a class if a non-implemented method is called -class CRYPTOPP_DLL NotImplemented : public Exception -{ -public: - explicit NotImplemented(const std::string &s) : Exception(NOT_IMPLEMENTED, s) {} -}; - -//! exception thrown by a class when Flush(true) is called but it can't completely flush its buffers -class CRYPTOPP_DLL CannotFlush : public Exception -{ -public: - explicit CannotFlush(const std::string &s) : Exception(CANNOT_FLUSH, s) {} -}; - -//! error reported by the operating system -class CRYPTOPP_DLL OS_Error : public Exception -{ -public: - OS_Error(ErrorType errorType, const std::string &s, const std::string& operation, int errorCode) - : Exception(errorType, s), m_operation(operation), m_errorCode(errorCode) {} - ~OS_Error() throw() {} - - // the operating system API that reported the error - const std::string & GetOperation() const {return m_operation;} - // the error code return by the operating system - int GetErrorCode() const {return m_errorCode;} - -protected: - std::string m_operation; - int m_errorCode; -}; - -//! used to return decoding results -struct CRYPTOPP_DLL DecodingResult -{ - explicit DecodingResult() : isValidCoding(false), messageLength(0) {} - explicit DecodingResult(size_t len) : isValidCoding(true), messageLength(len) {} - - bool operator==(const DecodingResult &rhs) const {return isValidCoding == rhs.isValidCoding && messageLength == rhs.messageLength;} - bool operator!=(const DecodingResult &rhs) const {return !operator==(rhs);} - - bool isValidCoding; - size_t messageLength; - -#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY - operator size_t() const {return isValidCoding ? messageLength : 0;} -#endif -}; - -//! interface for retrieving values given their names -/*! \note This class is used to safely pass a variable number of arbitrarily typed arguments to functions - and to read values from keys and crypto parameters. - \note To obtain an object that implements NameValuePairs for the purpose of parameter - passing, use the MakeParameters() function. - \note To get a value from NameValuePairs, you need to know the name and the type of the value. - Call GetValueNames() on a NameValuePairs object to obtain a list of value names that it supports. - Then look at the Name namespace documentation to see what the type of each value is, or - alternatively, call GetIntValue() with the value name, and if the type is not int, a - ValueTypeMismatch exception will be thrown and you can get the actual type from the exception object. -*/ -class CRYPTOPP_NO_VTABLE NameValuePairs -{ -public: - virtual ~NameValuePairs() {} - - //! exception thrown when trying to retrieve a value using a different type than expected - class CRYPTOPP_DLL ValueTypeMismatch : public InvalidArgument - { - public: - ValueTypeMismatch(const std::string &name, const std::type_info &stored, const std::type_info &retrieving) - : InvalidArgument("NameValuePairs: type mismatch for '" + name + "', stored '" + stored.name() + "', trying to retrieve '" + retrieving.name() + "'") - , m_stored(stored), m_retrieving(retrieving) {} - - const std::type_info & GetStoredTypeInfo() const {return m_stored;} - const std::type_info & GetRetrievingTypeInfo() const {return m_retrieving;} - - private: - const std::type_info &m_stored; - const std::type_info &m_retrieving; - }; - - //! get a copy of this object or a subobject of it - template - bool GetThisObject(T &object) const - { - return GetValue((std::string("ThisObject:")+typeid(T).name()).c_str(), object); - } - - //! get a pointer to this object, as a pointer to T - template - bool GetThisPointer(T *&p) const - { - return GetValue((std::string("ThisPointer:")+typeid(T).name()).c_str(), p); - } - - //! get a named value, returns true if the name exists - template - bool GetValue(const char *name, T &value) const - { - return GetVoidValue(name, typeid(T), &value); - } - - //! get a named value, returns the default if the name doesn't exist - template - T GetValueWithDefault(const char *name, T defaultValue) const - { - GetValue(name, defaultValue); - return defaultValue; - } - - //! get a list of value names that can be retrieved - CRYPTOPP_DLL std::string GetValueNames() const - {std::string result; GetValue("ValueNames", result); return result;} - - //! get a named value with type int - /*! used to ensure we don't accidentally try to get an unsigned int - or some other type when we mean int (which is the most common case) */ - CRYPTOPP_DLL bool GetIntValue(const char *name, int &value) const - {return GetValue(name, value);} - - //! get a named value with type int, with default - CRYPTOPP_DLL int GetIntValueWithDefault(const char *name, int defaultValue) const - {return GetValueWithDefault(name, defaultValue);} - - //! used by derived classes to check for type mismatch - CRYPTOPP_DLL static void CRYPTOPP_API ThrowIfTypeMismatch(const char *name, const std::type_info &stored, const std::type_info &retrieving) - {if (stored != retrieving) throw ValueTypeMismatch(name, stored, retrieving);} - - template - void GetRequiredParameter(const char *className, const char *name, T &value) const - { - if (!GetValue(name, value)) - throw InvalidArgument(std::string(className) + ": missing required parameter '" + name + "'"); - } - - CRYPTOPP_DLL void GetRequiredIntParameter(const char *className, const char *name, int &value) const - { - if (!GetIntValue(name, value)) - throw InvalidArgument(std::string(className) + ": missing required parameter '" + name + "'"); - } - - //! to be implemented by derived classes, users should use one of the above functions instead - CRYPTOPP_DLL virtual bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const =0; -}; - -//! namespace containing value name definitions -/*! value names, types and semantics: - - ThisObject:ClassName (ClassName, copy of this object or a subobject) - ThisPointer:ClassName (const ClassName *, pointer to this object or a subobject) -*/ -DOCUMENTED_NAMESPACE_BEGIN(Name) -// more names defined in argnames.h -DOCUMENTED_NAMESPACE_END - -//! empty set of name-value pairs -class CRYPTOPP_DLL NullNameValuePairs : public NameValuePairs -{ -public: - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const {return false;} -}; - -//! _ -extern CRYPTOPP_DLL const NullNameValuePairs g_nullNameValuePairs; - -// ******************************************************** - -//! interface for cloning objects, this is not implemented by most classes yet -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Clonable -{ -public: - virtual ~Clonable() {} - //! this is not implemented by most classes yet - virtual Clonable* Clone() const {throw NotImplemented("Clone() is not implemented yet.");} // TODO: make this =0 -}; - -//! interface for all crypto algorithms - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Algorithm : public Clonable -{ -public: - /*! When FIPS 140-2 compliance is enabled and checkSelfTestStatus == true, - this constructor throws SelfTestFailure if the self test hasn't been run or fails. */ - Algorithm(bool checkSelfTestStatus = true); - //! returns name of this algorithm, not universally implemented yet - virtual std::string AlgorithmName() const {return "unknown";} -}; - -//! keying interface for crypto algorithms that take byte strings as keys -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SimpleKeyingInterface -{ -public: - virtual ~SimpleKeyingInterface() {} - - //! returns smallest valid key length in bytes */ - virtual size_t MinKeyLength() const =0; - //! returns largest valid key length in bytes */ - virtual size_t MaxKeyLength() const =0; - //! returns default (recommended) key length in bytes */ - virtual size_t DefaultKeyLength() const =0; - - //! returns the smallest valid key length in bytes that is >= min(n, GetMaxKeyLength()) - virtual size_t GetValidKeyLength(size_t n) const =0; - - //! returns whether n is a valid key length - virtual bool IsValidKeyLength(size_t n) const - {return n == GetValidKeyLength(n);} - - //! set or reset the key of this object - /*! \param params is used to specify Rounds, BlockSize, etc. */ - virtual void SetKey(const byte *key, size_t length, const NameValuePairs ¶ms = g_nullNameValuePairs); - - //! calls SetKey() with an NameValuePairs object that just specifies "Rounds" - void SetKeyWithRounds(const byte *key, size_t length, int rounds); - - //! calls SetKey() with an NameValuePairs object that just specifies "IV" - void SetKeyWithIV(const byte *key, size_t length, const byte *iv, size_t ivLength); - - //! calls SetKey() with an NameValuePairs object that just specifies "IV" - void SetKeyWithIV(const byte *key, size_t length, const byte *iv) - {SetKeyWithIV(key, length, iv, IVSize());} - - enum IV_Requirement {UNIQUE_IV = 0, RANDOM_IV, UNPREDICTABLE_RANDOM_IV, INTERNALLY_GENERATED_IV, NOT_RESYNCHRONIZABLE}; - //! returns the minimal requirement for secure IVs - virtual IV_Requirement IVRequirement() const =0; - - //! returns whether this object can be resynchronized (i.e. supports initialization vectors) - /*! If this function returns true, and no IV is passed to SetKey() and CanUseStructuredIVs()==true, an IV of all 0's will be assumed. */ - bool IsResynchronizable() const {return IVRequirement() < NOT_RESYNCHRONIZABLE;} - //! returns whether this object can use random IVs (in addition to ones returned by GetNextIV) - bool CanUseRandomIVs() const {return IVRequirement() <= UNPREDICTABLE_RANDOM_IV;} - //! returns whether this object can use random but possibly predictable IVs (in addition to ones returned by GetNextIV) - bool CanUsePredictableIVs() const {return IVRequirement() <= RANDOM_IV;} - //! returns whether this object can use structured IVs, for example a counter (in addition to ones returned by GetNextIV) - bool CanUseStructuredIVs() const {return IVRequirement() <= UNIQUE_IV;} - - virtual unsigned int IVSize() const {throw NotImplemented(GetAlgorithm().AlgorithmName() + ": this object doesn't support resynchronization");} - //! returns default length of IVs accepted by this object - unsigned int DefaultIVLength() const {return IVSize();} - //! returns minimal length of IVs accepted by this object - virtual unsigned int MinIVLength() const {return IVSize();} - //! returns maximal length of IVs accepted by this object - virtual unsigned int MaxIVLength() const {return IVSize();} - //! resynchronize with an IV. ivLength=-1 means use IVSize() - virtual void Resynchronize(const byte *iv, int ivLength=-1) {throw NotImplemented(GetAlgorithm().AlgorithmName() + ": this object doesn't support resynchronization");} - //! get a secure IV for the next message - /*! This method should be called after you finish encrypting one message and are ready to start the next one. - After calling it, you must call SetKey() or Resynchronize() before using this object again. - This method is not implemented on decryption objects. */ - virtual void GetNextIV(RandomNumberGenerator &rng, byte *IV); - -protected: - virtual const Algorithm & GetAlgorithm() const =0; - virtual void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) =0; - - void ThrowIfInvalidKeyLength(size_t length); - void ThrowIfResynchronizable(); // to be called when no IV is passed - void ThrowIfInvalidIV(const byte *iv); // check for NULL IV if it can't be used - size_t ThrowIfInvalidIVLength(int size); - const byte * GetIVAndThrowIfInvalid(const NameValuePairs ¶ms, size_t &size); - inline void AssertValidKeyLength(size_t length) const - {assert(IsValidKeyLength(length));} -}; - -//! interface for the data processing part of block ciphers - -/*! Classes derived from BlockTransformation are block ciphers - in ECB mode (for example the DES::Encryption class), which are stateless. - These classes should not be used directly, but only in combination with - a mode class (see CipherModeDocumentation in modes.h). -*/ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockTransformation : public Algorithm -{ -public: - //! encrypt or decrypt inBlock, xor with xorBlock, and write to outBlock - virtual void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const =0; - - //! encrypt or decrypt one block - /*! \pre size of inBlock and outBlock == BlockSize() */ - void ProcessBlock(const byte *inBlock, byte *outBlock) const - {ProcessAndXorBlock(inBlock, NULL, outBlock);} - - //! encrypt or decrypt one block in place - void ProcessBlock(byte *inoutBlock) const - {ProcessAndXorBlock(inoutBlock, NULL, inoutBlock);} - - //! block size of the cipher in bytes - virtual unsigned int BlockSize() const =0; - - //! returns how inputs and outputs should be aligned for optimal performance - virtual unsigned int OptimalDataAlignment() const; - - //! returns true if this is a permutation (i.e. there is an inverse transformation) - virtual bool IsPermutation() const {return true;} - - //! returns true if this is an encryption object - virtual bool IsForwardTransformation() const =0; - - //! return number of blocks that can be processed in parallel, for bit-slicing implementations - virtual unsigned int OptimalNumberOfParallelBlocks() const {return 1;} - - enum {BT_InBlockIsCounter=1, BT_DontIncrementInOutPointers=2, BT_XorInput=4, BT_ReverseDirection=8} FlagsForAdvancedProcessBlocks; - - //! encrypt and xor blocks according to flags (see FlagsForAdvancedProcessBlocks) - /*! /note If BT_InBlockIsCounter is set, last byte of inBlocks may be modified. */ - virtual size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const; - - inline CipherDir GetCipherDirection() const {return IsForwardTransformation() ? ENCRYPTION : DECRYPTION;} -}; - -//! interface for the data processing part of stream ciphers - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE StreamTransformation : public Algorithm -{ -public: - //! return a reference to this object, - /*! This function is useful for passing a temporary StreamTransformation object to a - function that takes a non-const reference. */ - StreamTransformation& Ref() {return *this;} - - //! returns block size, if input must be processed in blocks, otherwise 1 - virtual unsigned int MandatoryBlockSize() const {return 1;} - - //! returns the input block size that is most efficient for this cipher - /*! \note optimal input length is n * OptimalBlockSize() - GetOptimalBlockSizeUsed() for any n > 0 */ - virtual unsigned int OptimalBlockSize() const {return MandatoryBlockSize();} - //! returns how much of the current block is used up - virtual unsigned int GetOptimalBlockSizeUsed() const {return 0;} - - //! returns how input should be aligned for optimal performance - virtual unsigned int OptimalDataAlignment() const; - - //! encrypt or decrypt an array of bytes of specified length - /*! \note either inString == outString, or they don't overlap */ - virtual void ProcessData(byte *outString, const byte *inString, size_t length) =0; - - //! for ciphers where the last block of data is special, encrypt or decrypt the last block of data - /*! For now the only use of this function is for CBC-CTS mode. */ - virtual void ProcessLastBlock(byte *outString, const byte *inString, size_t length); - //! returns the minimum size of the last block, 0 indicating the last block is not special - virtual unsigned int MinLastBlockSize() const {return 0;} - - //! same as ProcessData(inoutString, inoutString, length) - inline void ProcessString(byte *inoutString, size_t length) - {ProcessData(inoutString, inoutString, length);} - //! same as ProcessData(outString, inString, length) - inline void ProcessString(byte *outString, const byte *inString, size_t length) - {ProcessData(outString, inString, length);} - //! implemented as {ProcessData(&input, &input, 1); return input;} - inline byte ProcessByte(byte input) - {ProcessData(&input, &input, 1); return input;} - - //! returns whether this cipher supports random access - virtual bool IsRandomAccess() const =0; - //! for random access ciphers, seek to an absolute position - virtual void Seek(lword n) - { - assert(!IsRandomAccess()); - throw NotImplemented("StreamTransformation: this object doesn't support random access"); - } - - //! returns whether this transformation is self-inverting (e.g. xor with a keystream) - virtual bool IsSelfInverting() const =0; - //! returns whether this is an encryption object - virtual bool IsForwardTransformation() const =0; -}; - -//! interface for hash functions and data processing part of MACs - -/*! HashTransformation objects are stateful. They are created in an initial state, - change state as Update() is called, and return to the initial - state when Final() is called. This interface allows a large message to - be hashed in pieces by calling Update() on each piece followed by - calling Final(). -*/ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE HashTransformation : public Algorithm -{ -public: - //! return a reference to this object, - /*! This function is useful for passing a temporary HashTransformation object to a - function that takes a non-const reference. */ - HashTransformation& Ref() {return *this;} - - //! process more input - virtual void Update(const byte *input, size_t length) =0; - - //! request space to write input into - virtual byte * CreateUpdateSpace(size_t &size) {size=0; return NULL;} - - //! compute hash for current message, then restart for a new message - /*! \pre size of digest == DigestSize(). */ - virtual void Final(byte *digest) - {TruncatedFinal(digest, DigestSize());} - - //! discard the current state, and restart with a new message - virtual void Restart() - {TruncatedFinal(NULL, 0);} - - //! size of the hash/digest/MAC returned by Final() - virtual unsigned int DigestSize() const =0; - - //! same as DigestSize() - unsigned int TagSize() const {return DigestSize();} - - - //! block size of underlying compression function, or 0 if not block based - virtual unsigned int BlockSize() const {return 0;} - - //! input to Update() should have length a multiple of this for optimal speed - virtual unsigned int OptimalBlockSize() const {return 1;} - - //! returns how input should be aligned for optimal performance - virtual unsigned int OptimalDataAlignment() const; - - //! use this if your input is in one piece and you don't want to call Update() and Final() separately - virtual void CalculateDigest(byte *digest, const byte *input, size_t length) - {Update(input, length); Final(digest);} - - //! verify that digest is a valid digest for the current message, then reinitialize the object - /*! Default implementation is to call Final() and do a bitwise comparison - between its output and digest. */ - virtual bool Verify(const byte *digest) - {return TruncatedVerify(digest, DigestSize());} - - //! use this if your input is in one piece and you don't want to call Update() and Verify() separately - virtual bool VerifyDigest(const byte *digest, const byte *input, size_t length) - {Update(input, length); return Verify(digest);} - - //! truncated version of Final() - virtual void TruncatedFinal(byte *digest, size_t digestSize) =0; - - //! truncated version of CalculateDigest() - virtual void CalculateTruncatedDigest(byte *digest, size_t digestSize, const byte *input, size_t length) - {Update(input, length); TruncatedFinal(digest, digestSize);} - - //! truncated version of Verify() - virtual bool TruncatedVerify(const byte *digest, size_t digestLength); - - //! truncated version of VerifyDigest() - virtual bool VerifyTruncatedDigest(const byte *digest, size_t digestLength, const byte *input, size_t length) - {Update(input, length); return TruncatedVerify(digest, digestLength);} - -protected: - void ThrowIfInvalidTruncatedSize(size_t size) const; -}; - -typedef HashTransformation HashFunction; - -//! interface for one direction (encryption or decryption) of a block cipher -/*! \note These objects usually should not be used directly. See BlockTransformation for more details. */ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockCipher : public SimpleKeyingInterface, public BlockTransformation -{ -protected: - const Algorithm & GetAlgorithm() const {return *this;} -}; - -//! interface for one direction (encryption or decryption) of a stream cipher or cipher mode -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SymmetricCipher : public SimpleKeyingInterface, public StreamTransformation -{ -protected: - const Algorithm & GetAlgorithm() const {return *this;} -}; - -//! interface for message authentication codes -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE MessageAuthenticationCode : public SimpleKeyingInterface, public HashTransformation -{ -protected: - const Algorithm & GetAlgorithm() const {return *this;} -}; - -//! interface for for one direction (encryption or decryption) of a stream cipher or block cipher mode with authentication -/*! The StreamTransformation part of this interface is used to encrypt/decrypt the data, and the MessageAuthenticationCode part of this - interface is used to input additional authenticated data (AAD, which is MAC'ed but not encrypted), and to generate/verify the MAC. */ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedSymmetricCipher : public MessageAuthenticationCode, public StreamTransformation -{ -public: - //! this indicates that a member function was called in the wrong state, for example trying to encrypt a message before having set the key or IV - class BadState : public Exception - { - public: - explicit BadState(const std::string &name, const char *message) : Exception(OTHER_ERROR, name + ": " + message) {} - explicit BadState(const std::string &name, const char *function, const char *state) : Exception(OTHER_ERROR, name + ": " + function + " was called before " + state) {} - }; - - //! the maximum length of AAD that can be input before the encrypted data - virtual lword MaxHeaderLength() const =0; - //! the maximum length of encrypted data - virtual lword MaxMessageLength() const =0; - //! the maximum length of AAD that can be input after the encrypted data - virtual lword MaxFooterLength() const {return 0;} - //! if this function returns true, SpecifyDataLengths() must be called before attempting to input data - /*! This is the case for some schemes, such as CCM. */ - virtual bool NeedsPrespecifiedDataLengths() const {return false;} - //! this function only needs to be called if NeedsPrespecifiedDataLengths() returns true - void SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength=0); - //! encrypt and generate MAC in one call. will truncate MAC if macSize < TagSize() - virtual void EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *message, size_t messageLength); - //! decrypt and verify MAC in one call, returning true iff MAC is valid. will assume MAC is truncated if macLength < TagSize() - virtual bool DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *ciphertext, size_t ciphertextLength); - - // redeclare this to avoid compiler ambiguity errors - virtual std::string AlgorithmName() const =0; - -protected: - const Algorithm & GetAlgorithm() const {return *static_cast(this);} - virtual void UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength) {} -}; - -#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY -typedef SymmetricCipher StreamCipher; -#endif - -//! interface for random number generators -/*! All return values are uniformly distributed over the range specified. -*/ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomNumberGenerator : public Algorithm -{ -public: - //! update RNG state with additional unpredictable values - virtual void IncorporateEntropy(const byte *input, size_t length) {throw NotImplemented("RandomNumberGenerator: IncorporateEntropy not implemented");} - - //! returns true if IncorporateEntropy is implemented - virtual bool CanIncorporateEntropy() const {return false;} - - //! generate new random byte and return it - virtual byte GenerateByte(); - - //! generate new random bit and return it - /*! Default implementation is to call GenerateByte() and return its lowest bit. */ - virtual unsigned int GenerateBit(); - - //! generate a random 32 bit word in the range min to max, inclusive - virtual word32 GenerateWord32(word32 a=0, word32 b=0xffffffffL); - - //! generate random array of bytes - virtual void GenerateBlock(byte *output, size_t size); - - //! generate and discard n bytes - virtual void DiscardBytes(size_t n); - - //! generate random bytes as input to a BufferedTransformation - virtual void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length); - - //! randomly shuffle the specified array, resulting permutation is uniformly distributed - template void Shuffle(IT begin, IT end) - { - for (; begin != end; ++begin) - std::iter_swap(begin, begin + GenerateWord32(0, end-begin-1)); - } - -#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY - byte GetByte() {return GenerateByte();} - unsigned int GetBit() {return GenerateBit();} - word32 GetLong(word32 a=0, word32 b=0xffffffffL) {return GenerateWord32(a, b);} - word16 GetShort(word16 a=0, word16 b=0xffff) {return (word16)GenerateWord32(a, b);} - void GetBlock(byte *output, size_t size) {GenerateBlock(output, size);} -#endif -}; - -//! returns a reference that can be passed to functions that ask for a RNG but doesn't actually use it -CRYPTOPP_DLL RandomNumberGenerator & CRYPTOPP_API NullRNG(); - -class WaitObjectContainer; -class CallStack; - -//! interface for objects that you can wait for - -class CRYPTOPP_NO_VTABLE Waitable -{ -public: - virtual ~Waitable() {} - - //! maximum number of wait objects that this object can return - virtual unsigned int GetMaxWaitObjectCount() const =0; - //! put wait objects into container - /*! \param callStack is used for tracing no wait loops, example: - something.GetWaitObjects(c, CallStack("my func after X", 0)); - - or in an outer GetWaitObjects() method that itself takes a callStack parameter: - innerThing.GetWaitObjects(c, CallStack("MyClass::GetWaitObjects at X", &callStack)); */ - virtual void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack) =0; - //! wait on this object - /*! same as creating an empty container, calling GetWaitObjects(), and calling Wait() on the container */ - bool Wait(unsigned long milliseconds, CallStack const& callStack); -}; - -//! the default channel for BufferedTransformation, equal to the empty string -extern CRYPTOPP_DLL const std::string DEFAULT_CHANNEL; - -//! channel for additional authenticated data, equal to "AAD" -extern CRYPTOPP_DLL const std::string AAD_CHANNEL; - -//! interface for buffered transformations - -/*! BufferedTransformation is a generalization of BlockTransformation, - StreamTransformation, and HashTransformation. - - A buffered transformation is an object that takes a stream of bytes - as input (this may be done in stages), does some computation on them, and - then places the result into an internal buffer for later retrieval. Any - partial result already in the output buffer is not modified by further - input. - - If a method takes a "blocking" parameter, and you - pass "false" for it, the method will return before all input has been processed if - the input cannot be processed without waiting (for network buffers to become available, for example). - In this case the method will return true - or a non-zero integer value. When this happens you must continue to call the method with the same - parameters until it returns false or zero, before calling any other method on it or - attached BufferedTransformation. The integer return value in this case is approximately - the number of bytes left to be processed, and can be used to implement a progress bar. - - For functions that take a "propagation" parameter, propagation != 0 means pass on the signal to attached - BufferedTransformation objects, with propagation decremented at each step until it reaches 0. - -1 means unlimited propagation. - - \nosubgrouping -*/ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BufferedTransformation : public Algorithm, public Waitable -{ -public: - // placed up here for CW8 - static const std::string &NULL_CHANNEL; // same as DEFAULT_CHANNEL, for backwards compatibility - - BufferedTransformation() : Algorithm(false) {} - - //! return a reference to this object - /*! This function is useful for passing a temporary BufferedTransformation object to a - function that takes a non-const reference. */ - BufferedTransformation& Ref() {return *this;} - - //! \name INPUT - //@{ - //! input a byte for processing - size_t Put(byte inByte, bool blocking=true) - {return Put(&inByte, 1, blocking);} - //! input multiple bytes - size_t Put(const byte *inString, size_t length, bool blocking=true) - {return Put2(inString, length, 0, blocking);} - - //! input a 16-bit word - size_t PutWord16(word16 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true); - //! input a 32-bit word - size_t PutWord32(word32 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true); - - //! request space which can be written into by the caller, and then used as input to Put() - /*! \param size is requested size (as a hint) for input, and size of the returned space for output */ - /*! \note The purpose of this method is to help avoid doing extra memory allocations. */ - virtual byte * CreatePutSpace(size_t &size) {size=0; return NULL;} - - virtual bool CanModifyInput() const {return false;} - - //! input multiple bytes that may be modified by callee - size_t PutModifiable(byte *inString, size_t length, bool blocking=true) - {return PutModifiable2(inString, length, 0, blocking);} - - bool MessageEnd(int propagation=-1, bool blocking=true) - {return !!Put2(NULL, 0, propagation < 0 ? -1 : propagation+1, blocking);} - size_t PutMessageEnd(const byte *inString, size_t length, int propagation=-1, bool blocking=true) - {return Put2(inString, length, propagation < 0 ? -1 : propagation+1, blocking);} - - //! input multiple bytes for blocking or non-blocking processing - /*! \param messageEnd means how many filters to signal MessageEnd to, including this one */ - virtual size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) =0; - //! input multiple bytes that may be modified by callee for blocking or non-blocking processing - /*! \param messageEnd means how many filters to signal MessageEnd to, including this one */ - virtual size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking) - {return Put2(inString, length, messageEnd, blocking);} - - //! thrown by objects that have not implemented nonblocking input processing - struct BlockingInputOnly : public NotImplemented - {BlockingInputOnly(const std::string &s) : NotImplemented(s + ": Nonblocking input is not implemented by this object.") {}}; - //@} - - //! \name WAITING - //@{ - unsigned int GetMaxWaitObjectCount() const; - void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack); - //@} - - //! \name SIGNALS - //@{ - virtual void IsolatedInitialize(const NameValuePairs ¶meters) {throw NotImplemented("BufferedTransformation: this object can't be reinitialized");} - virtual bool IsolatedFlush(bool hardFlush, bool blocking) =0; - virtual bool IsolatedMessageSeriesEnd(bool blocking) {return false;} - - //! initialize or reinitialize this object - virtual void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1); - //! flush buffered input and/or output - /*! \param hardFlush is used to indicate whether all data should be flushed - \note Hard flushes must be used with care. It means try to process and output everything, even if - there may not be enough data to complete the action. For example, hard flushing a HexDecoder would - cause an error if you do it after inputing an odd number of hex encoded characters. - For some types of filters, for example ZlibDecompressor, hard flushes can only - be done at "synchronization points". These synchronization points are positions in the data - stream that are created by hard flushes on the corresponding reverse filters, in this - example ZlibCompressor. This is useful when zlib compressed data is moved across a - network in packets and compression state is preserved across packets, as in the ssh2 protocol. - */ - virtual bool Flush(bool hardFlush, int propagation=-1, bool blocking=true); - //! mark end of a series of messages - /*! There should be a MessageEnd immediately before MessageSeriesEnd. */ - virtual bool MessageSeriesEnd(int propagation=-1, bool blocking=true); - - //! set propagation of automatically generated and transferred signals - /*! propagation == 0 means do not automaticly generate signals */ - virtual void SetAutoSignalPropagation(int propagation) {} - - //! - virtual int GetAutoSignalPropagation() const {return 0;} -public: - -#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY - void Close() {MessageEnd();} -#endif - //@} - - //! \name RETRIEVAL OF ONE MESSAGE - //@{ - //! returns number of bytes that is currently ready for retrieval - /*! All retrieval functions return the actual number of bytes - retrieved, which is the lesser of the request number and - MaxRetrievable(). */ - virtual lword MaxRetrievable() const; - - //! returns whether any bytes are currently ready for retrieval - virtual bool AnyRetrievable() const; - - //! try to retrieve a single byte - virtual size_t Get(byte &outByte); - //! try to retrieve multiple bytes - virtual size_t Get(byte *outString, size_t getMax); - - //! peek at the next byte without removing it from the output buffer - virtual size_t Peek(byte &outByte) const; - //! peek at multiple bytes without removing them from the output buffer - virtual size_t Peek(byte *outString, size_t peekMax) const; - - //! try to retrieve a 16-bit word - size_t GetWord16(word16 &value, ByteOrder order=BIG_ENDIAN_ORDER); - //! try to retrieve a 32-bit word - size_t GetWord32(word32 &value, ByteOrder order=BIG_ENDIAN_ORDER); - - //! try to peek at a 16-bit word - size_t PeekWord16(word16 &value, ByteOrder order=BIG_ENDIAN_ORDER) const; - //! try to peek at a 32-bit word - size_t PeekWord32(word32 &value, ByteOrder order=BIG_ENDIAN_ORDER) const; - - //! move transferMax bytes of the buffered output to target as input - lword TransferTo(BufferedTransformation &target, lword transferMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL) - {TransferTo2(target, transferMax, channel); return transferMax;} - - //! discard skipMax bytes from the output buffer - virtual lword Skip(lword skipMax=LWORD_MAX); - - //! copy copyMax bytes of the buffered output to target as input - lword CopyTo(BufferedTransformation &target, lword copyMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL) const - {return CopyRangeTo(target, 0, copyMax, channel);} - - //! copy copyMax bytes of the buffered output, starting at position (relative to current position), to target as input - lword CopyRangeTo(BufferedTransformation &target, lword position, lword copyMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL) const - {lword i = position; CopyRangeTo2(target, i, i+copyMax, channel); return i-position;} - -#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY - unsigned long MaxRetrieveable() const {return MaxRetrievable();} -#endif - //@} - - //! \name RETRIEVAL OF MULTIPLE MESSAGES - //@{ - //! - virtual lword TotalBytesRetrievable() const; - //! number of times MessageEnd() has been received minus messages retrieved or skipped - virtual unsigned int NumberOfMessages() const; - //! returns true if NumberOfMessages() > 0 - virtual bool AnyMessages() const; - //! start retrieving the next message - /*! - Returns false if no more messages exist or this message - is not completely retrieved. - */ - virtual bool GetNextMessage(); - //! skip count number of messages - virtual unsigned int SkipMessages(unsigned int count=UINT_MAX); - //! - unsigned int TransferMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL) - {TransferMessagesTo2(target, count, channel); return count;} - //! - unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL) const; - - //! - virtual void SkipAll(); - //! - void TransferAllTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL) - {TransferAllTo2(target, channel);} - //! - void CopyAllTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL) const; - - virtual bool GetNextMessageSeries() {return false;} - virtual unsigned int NumberOfMessagesInThisSeries() const {return NumberOfMessages();} - virtual unsigned int NumberOfMessageSeries() const {return 0;} - //@} - - //! \name NON-BLOCKING TRANSFER OF OUTPUT - //@{ - //! upon return, byteCount contains number of bytes that have finished being transfered, and returns the number of bytes left in the current transfer block - virtual size_t TransferTo2(BufferedTransformation &target, lword &byteCount, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) =0; - //! upon return, begin contains the start position of data yet to be finished copying, and returns the number of bytes left in the current transfer block - virtual size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const =0; - //! upon return, messageCount contains number of messages that have finished being transfered, and returns the number of bytes left in the current transfer block - size_t TransferMessagesTo2(BufferedTransformation &target, unsigned int &messageCount, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); - //! returns the number of bytes left in the current transfer block - size_t TransferAllTo2(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); - //@} - - //! \name CHANNELS - //@{ - struct NoChannelSupport : public NotImplemented - {NoChannelSupport(const std::string &name) : NotImplemented(name + ": this object doesn't support multiple channels") {}}; - struct InvalidChannelName : public InvalidArgument - {InvalidChannelName(const std::string &name, const std::string &channel) : InvalidArgument(name + ": unexpected channel name \"" + channel + "\"") {}}; - - size_t ChannelPut(const std::string &channel, byte inByte, bool blocking=true) - {return ChannelPut(channel, &inByte, 1, blocking);} - size_t ChannelPut(const std::string &channel, const byte *inString, size_t length, bool blocking=true) - {return ChannelPut2(channel, inString, length, 0, blocking);} - - size_t ChannelPutModifiable(const std::string &channel, byte *inString, size_t length, bool blocking=true) - {return ChannelPutModifiable2(channel, inString, length, 0, blocking);} - - size_t ChannelPutWord16(const std::string &channel, word16 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true); - size_t ChannelPutWord32(const std::string &channel, word32 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true); - - bool ChannelMessageEnd(const std::string &channel, int propagation=-1, bool blocking=true) - {return !!ChannelPut2(channel, NULL, 0, propagation < 0 ? -1 : propagation+1, blocking);} - size_t ChannelPutMessageEnd(const std::string &channel, const byte *inString, size_t length, int propagation=-1, bool blocking=true) - {return ChannelPut2(channel, inString, length, propagation < 0 ? -1 : propagation+1, blocking);} - - virtual byte * ChannelCreatePutSpace(const std::string &channel, size_t &size); - - virtual size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking); - virtual size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking); - - virtual bool ChannelFlush(const std::string &channel, bool hardFlush, int propagation=-1, bool blocking=true); - virtual bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true); - - virtual void SetRetrievalChannel(const std::string &channel); - //@} - - //! \name ATTACHMENT - /*! Some BufferedTransformation objects (e.g. Filter objects) - allow other BufferedTransformation objects to be attached. When - this is done, the first object instead of buffering its output, - sents that output to the attached object as input. The entire - attachment chain is deleted when the anchor object is destructed. - */ - //@{ - //! returns whether this object allows attachment - virtual bool Attachable() {return false;} - //! returns the object immediately attached to this object or NULL for no attachment - virtual BufferedTransformation *AttachedTransformation() {assert(!Attachable()); return 0;} - //! - virtual const BufferedTransformation *AttachedTransformation() const - {return const_cast(this)->AttachedTransformation();} - //! delete the current attachment chain and replace it with newAttachment - virtual void Detach(BufferedTransformation *newAttachment = 0) - {assert(!Attachable()); throw NotImplemented("BufferedTransformation: this object is not attachable");} - //! add newAttachment to the end of attachment chain - virtual void Attach(BufferedTransformation *newAttachment); - //@} - -protected: - static int DecrementPropagation(int propagation) - {return propagation != 0 ? propagation - 1 : 0;} - -private: - byte m_buf[4]; // for ChannelPutWord16 and ChannelPutWord32, to ensure buffer isn't deallocated before non-blocking operation completes -}; - -//! returns a reference to a BufferedTransformation object that discards all input -BufferedTransformation & TheBitBucket(); - -//! interface for crypto material, such as public and private keys, and crypto parameters - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CryptoMaterial : public NameValuePairs -{ -public: - //! exception thrown when invalid crypto material is detected - class CRYPTOPP_DLL InvalidMaterial : public InvalidDataFormat - { - public: - explicit InvalidMaterial(const std::string &s) : InvalidDataFormat(s) {} - }; - - //! assign values from source to this object - /*! \note This function can be used to create a public key from a private key. */ - virtual void AssignFrom(const NameValuePairs &source) =0; - - //! check this object for errors - /*! \param level denotes the level of thoroughness: - 0 - using this object won't cause a crash or exception (rng is ignored) - 1 - this object will probably function (encrypt, sign, etc.) correctly (but may not check for weak keys and such) - 2 - make sure this object will function correctly, and do reasonable security checks - 3 - do checks that may take a long time - \return true if the tests pass */ - virtual bool Validate(RandomNumberGenerator &rng, unsigned int level) const =0; - - //! throws InvalidMaterial if this object fails Validate() test - virtual void ThrowIfInvalid(RandomNumberGenerator &rng, unsigned int level) const - {if (!Validate(rng, level)) throw InvalidMaterial("CryptoMaterial: this object contains invalid values");} - -// virtual std::vector GetSupportedFormats(bool includeSaveOnly=false, bool includeLoadOnly=false); - - //! save key into a BufferedTransformation - virtual void Save(BufferedTransformation &bt) const - {throw NotImplemented("CryptoMaterial: this object does not support saving");} - - //! load key from a BufferedTransformation - /*! \throws KeyingErr if decode fails - \note Generally does not check that the key is valid. - Call ValidateKey() or ThrowIfInvalidKey() to check that. */ - virtual void Load(BufferedTransformation &bt) - {throw NotImplemented("CryptoMaterial: this object does not support loading");} - - //! \return whether this object supports precomputation - virtual bool SupportsPrecomputation() const {return false;} - //! do precomputation - /*! The exact semantics of Precompute() is varies, but - typically it means calculate a table of n objects - that can be used later to speed up computation. */ - virtual void Precompute(unsigned int n) - {assert(!SupportsPrecomputation()); throw NotImplemented("CryptoMaterial: this object does not support precomputation");} - //! retrieve previously saved precomputation - virtual void LoadPrecomputation(BufferedTransformation &storedPrecomputation) - {assert(!SupportsPrecomputation()); throw NotImplemented("CryptoMaterial: this object does not support precomputation");} - //! save precomputation for later use - virtual void SavePrecomputation(BufferedTransformation &storedPrecomputation) const - {assert(!SupportsPrecomputation()); throw NotImplemented("CryptoMaterial: this object does not support precomputation");} - - // for internal library use - void DoQuickSanityCheck() const {ThrowIfInvalid(NullRNG(), 0);} - -#if (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590) - // Sun Studio 11/CC 5.8 workaround: it generates incorrect code when casting to an empty virtual base class - char m_sunCCworkaround; -#endif -}; - -//! interface for generatable crypto material, such as private keys and crypto parameters - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE GeneratableCryptoMaterial : virtual public CryptoMaterial -{ -public: - //! generate a random key or crypto parameters - /*! \throws KeyingErr if algorithm parameters are invalid, or if a key can't be generated - (e.g., if this is a public key object) */ - virtual void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms = g_nullNameValuePairs) - {throw NotImplemented("GeneratableCryptoMaterial: this object does not support key/parameter generation");} - - //! calls the above function with a NameValuePairs object that just specifies "KeySize" - void GenerateRandomWithKeySize(RandomNumberGenerator &rng, unsigned int keySize); -}; - -//! interface for public keys - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PublicKey : virtual public CryptoMaterial -{ -}; - -//! interface for private keys - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PrivateKey : public GeneratableCryptoMaterial -{ -}; - -//! interface for crypto prameters - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CryptoParameters : public GeneratableCryptoMaterial -{ -}; - -//! interface for asymmetric algorithms - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AsymmetricAlgorithm : public Algorithm -{ -public: - //! returns a reference to the crypto material used by this object - virtual CryptoMaterial & AccessMaterial() =0; - //! returns a const reference to the crypto material used by this object - virtual const CryptoMaterial & GetMaterial() const =0; - - //! for backwards compatibility, calls AccessMaterial().Load(bt) - void BERDecode(BufferedTransformation &bt) - {AccessMaterial().Load(bt);} - //! for backwards compatibility, calls GetMaterial().Save(bt) - void DEREncode(BufferedTransformation &bt) const - {GetMaterial().Save(bt);} -}; - -//! interface for asymmetric algorithms using public keys - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PublicKeyAlgorithm : public AsymmetricAlgorithm -{ -public: - // VC60 workaround: no co-variant return type - CryptoMaterial & AccessMaterial() {return AccessPublicKey();} - const CryptoMaterial & GetMaterial() const {return GetPublicKey();} - - virtual PublicKey & AccessPublicKey() =0; - virtual const PublicKey & GetPublicKey() const {return const_cast(this)->AccessPublicKey();} -}; - -//! interface for asymmetric algorithms using private keys - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PrivateKeyAlgorithm : public AsymmetricAlgorithm -{ -public: - CryptoMaterial & AccessMaterial() {return AccessPrivateKey();} - const CryptoMaterial & GetMaterial() const {return GetPrivateKey();} - - virtual PrivateKey & AccessPrivateKey() =0; - virtual const PrivateKey & GetPrivateKey() const {return const_cast(this)->AccessPrivateKey();} -}; - -//! interface for key agreement algorithms - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE KeyAgreementAlgorithm : public AsymmetricAlgorithm -{ -public: - CryptoMaterial & AccessMaterial() {return AccessCryptoParameters();} - const CryptoMaterial & GetMaterial() const {return GetCryptoParameters();} - - virtual CryptoParameters & AccessCryptoParameters() =0; - virtual const CryptoParameters & GetCryptoParameters() const {return const_cast(this)->AccessCryptoParameters();} -}; - -//! interface for public-key encryptors and decryptors - -/*! This class provides an interface common to encryptors and decryptors - for querying their plaintext and ciphertext lengths. -*/ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_CryptoSystem -{ -public: - virtual ~PK_CryptoSystem() {} - - //! maximum length of plaintext for a given ciphertext length - /*! \note This function returns 0 if ciphertextLength is not valid (too long or too short). */ - virtual size_t MaxPlaintextLength(size_t ciphertextLength) const =0; - - //! calculate length of ciphertext given length of plaintext - /*! \note This function returns 0 if plaintextLength is not valid (too long). */ - virtual size_t CiphertextLength(size_t plaintextLength) const =0; - - //! this object supports the use of the parameter with the given name - /*! some possible parameter names: EncodingParameters, KeyDerivationParameters */ - virtual bool ParameterSupported(const char *name) const =0; - - //! return fixed ciphertext length, if one exists, otherwise return 0 - /*! \note "Fixed" here means length of ciphertext does not depend on length of plaintext. - It usually does depend on the key length. */ - virtual size_t FixedCiphertextLength() const {return 0;} - - //! return maximum plaintext length given the fixed ciphertext length, if one exists, otherwise return 0 - virtual size_t FixedMaxPlaintextLength() const {return 0;} - -#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY - size_t MaxPlainTextLength(size_t cipherTextLength) const {return MaxPlaintextLength(cipherTextLength);} - size_t CipherTextLength(size_t plainTextLength) const {return CiphertextLength(plainTextLength);} -#endif -}; - -//! interface for public-key encryptors -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Encryptor : public PK_CryptoSystem, public PublicKeyAlgorithm -{ -public: - //! exception thrown when trying to encrypt plaintext of invalid length - class CRYPTOPP_DLL InvalidPlaintextLength : public Exception - { - public: - InvalidPlaintextLength() : Exception(OTHER_ERROR, "PK_Encryptor: invalid plaintext length") {} - }; - - //! encrypt a byte string - /*! \pre CiphertextLength(plaintextLength) != 0 (i.e., plaintext isn't too long) - \pre size of ciphertext == CiphertextLength(plaintextLength) - */ - virtual void Encrypt(RandomNumberGenerator &rng, - const byte *plaintext, size_t plaintextLength, - byte *ciphertext, const NameValuePairs ¶meters = g_nullNameValuePairs) const =0; - - //! create a new encryption filter - /*! \note The caller is responsible for deleting the returned pointer. - \note Encoding parameters should be passed in the "EP" channel. - */ - virtual BufferedTransformation * CreateEncryptionFilter(RandomNumberGenerator &rng, - BufferedTransformation *attachment=NULL, const NameValuePairs ¶meters = g_nullNameValuePairs) const; -}; - -//! interface for public-key decryptors - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Decryptor : public PK_CryptoSystem, public PrivateKeyAlgorithm -{ -public: - //! decrypt a byte string, and return the length of plaintext - /*! \pre size of plaintext == MaxPlaintextLength(ciphertextLength) bytes. - \return the actual length of the plaintext, indication that decryption failed. - */ - virtual DecodingResult Decrypt(RandomNumberGenerator &rng, - const byte *ciphertext, size_t ciphertextLength, - byte *plaintext, const NameValuePairs ¶meters = g_nullNameValuePairs) const =0; - - //! create a new decryption filter - /*! \note caller is responsible for deleting the returned pointer - */ - virtual BufferedTransformation * CreateDecryptionFilter(RandomNumberGenerator &rng, - BufferedTransformation *attachment=NULL, const NameValuePairs ¶meters = g_nullNameValuePairs) const; - - //! decrypt a fixed size ciphertext - DecodingResult FixedLengthDecrypt(RandomNumberGenerator &rng, const byte *ciphertext, byte *plaintext, const NameValuePairs ¶meters = g_nullNameValuePairs) const - {return Decrypt(rng, ciphertext, FixedCiphertextLength(), plaintext, parameters);} -}; - -#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY -typedef PK_CryptoSystem PK_FixedLengthCryptoSystem; -typedef PK_Encryptor PK_FixedLengthEncryptor; -typedef PK_Decryptor PK_FixedLengthDecryptor; -#endif - -//! interface for public-key signers and verifiers - -/*! This class provides an interface common to signers and verifiers - for querying scheme properties. -*/ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_SignatureScheme -{ -public: - //! invalid key exception, may be thrown by any function in this class if the private or public key has a length that can't be used - class CRYPTOPP_DLL InvalidKeyLength : public Exception - { - public: - InvalidKeyLength(const std::string &message) : Exception(OTHER_ERROR, message) {} - }; - - //! key too short exception, may be thrown by any function in this class if the private or public key is too short to sign or verify anything - class CRYPTOPP_DLL KeyTooShort : public InvalidKeyLength - { - public: - KeyTooShort() : InvalidKeyLength("PK_Signer: key too short for this signature scheme") {} - }; - - virtual ~PK_SignatureScheme() {} - - //! signature length if it only depends on the key, otherwise 0 - virtual size_t SignatureLength() const =0; - - //! maximum signature length produced for a given length of recoverable message part - virtual size_t MaxSignatureLength(size_t recoverablePartLength = 0) const {return SignatureLength();} - - //! length of longest message that can be recovered, or 0 if this signature scheme does not support message recovery - virtual size_t MaxRecoverableLength() const =0; - - //! length of longest message that can be recovered from a signature of given length, or 0 if this signature scheme does not support message recovery - virtual size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const =0; - - //! requires a random number generator to sign - /*! if this returns false, NullRNG() can be passed to functions that take RandomNumberGenerator & */ - virtual bool IsProbabilistic() const =0; - - //! whether or not a non-recoverable message part can be signed - virtual bool AllowNonrecoverablePart() const =0; - - //! if this function returns true, during verification you must input the signature before the message, otherwise you can input it at anytime */ - virtual bool SignatureUpfront() const {return false;} - - //! whether you must input the recoverable part before the non-recoverable part during signing - virtual bool RecoverablePartFirst() const =0; -}; - -//! interface for accumulating messages to be signed or verified -/*! Only Update() should be called - on this class. No other functions inherited from HashTransformation should be called. -*/ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_MessageAccumulator : public HashTransformation -{ -public: - //! should not be called on PK_MessageAccumulator - unsigned int DigestSize() const - {throw NotImplemented("PK_MessageAccumulator: DigestSize() should not be called");} - //! should not be called on PK_MessageAccumulator - void TruncatedFinal(byte *digest, size_t digestSize) - {throw NotImplemented("PK_MessageAccumulator: TruncatedFinal() should not be called");} -}; - -//! interface for public-key signers - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Signer : public PK_SignatureScheme, public PrivateKeyAlgorithm -{ -public: - //! create a new HashTransformation to accumulate the message to be signed - virtual PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const =0; - - virtual void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const =0; - - //! sign and delete messageAccumulator (even in case of exception thrown) - /*! \pre size of signature == MaxSignatureLength() - \return actual signature length - */ - virtual size_t Sign(RandomNumberGenerator &rng, PK_MessageAccumulator *messageAccumulator, byte *signature) const; - - //! sign and restart messageAccumulator - /*! \pre size of signature == MaxSignatureLength() - \return actual signature length - */ - virtual size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart=true) const =0; - - //! sign a message - /*! \pre size of signature == MaxSignatureLength() - \return actual signature length - */ - virtual size_t SignMessage(RandomNumberGenerator &rng, const byte *message, size_t messageLen, byte *signature) const; - - //! sign a recoverable message - /*! \pre size of signature == MaxSignatureLength(recoverableMessageLength) - \return actual signature length - */ - virtual size_t SignMessageWithRecovery(RandomNumberGenerator &rng, const byte *recoverableMessage, size_t recoverableMessageLength, - const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, byte *signature) const; -}; - -//! interface for public-key signature verifiers -/*! The Recover* functions throw NotImplemented if the signature scheme does not support - message recovery. - The Verify* functions throw InvalidDataFormat if the scheme does support message - recovery and the signature contains a non-empty recoverable message part. The - Recovery* functions should be used in that case. -*/ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Verifier : public PK_SignatureScheme, public PublicKeyAlgorithm -{ -public: - //! create a new HashTransformation to accumulate the message to be verified - virtual PK_MessageAccumulator * NewVerificationAccumulator() const =0; - - //! input signature into a message accumulator - virtual void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const =0; - - //! check whether messageAccumulator contains a valid signature and message, and delete messageAccumulator (even in case of exception thrown) - virtual bool Verify(PK_MessageAccumulator *messageAccumulator) const; - - //! check whether messageAccumulator contains a valid signature and message, and restart messageAccumulator - virtual bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const =0; - - //! check whether input signature is a valid signature for input message - virtual bool VerifyMessage(const byte *message, size_t messageLen, - const byte *signature, size_t signatureLength) const; - - //! recover a message from its signature - /*! \pre size of recoveredMessage == MaxRecoverableLengthFromSignatureLength(signatureLength) - */ - virtual DecodingResult Recover(byte *recoveredMessage, PK_MessageAccumulator *messageAccumulator) const; - - //! recover a message from its signature - /*! \pre size of recoveredMessage == MaxRecoverableLengthFromSignatureLength(signatureLength) - */ - virtual DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const =0; - - //! recover a message from its signature - /*! \pre size of recoveredMessage == MaxRecoverableLengthFromSignatureLength(signatureLength) - */ - virtual DecodingResult RecoverMessage(byte *recoveredMessage, - const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, - const byte *signature, size_t signatureLength) const; -}; - -//! interface for domains of simple key agreement protocols - -/*! A key agreement domain is a set of parameters that must be shared - by two parties in a key agreement protocol, along with the algorithms - for generating key pairs and deriving agreed values. -*/ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SimpleKeyAgreementDomain : public KeyAgreementAlgorithm -{ -public: - //! return length of agreed value produced - virtual unsigned int AgreedValueLength() const =0; - //! return length of private keys in this domain - virtual unsigned int PrivateKeyLength() const =0; - //! return length of public keys in this domain - virtual unsigned int PublicKeyLength() const =0; - //! generate private key - /*! \pre size of privateKey == PrivateKeyLength() */ - virtual void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const =0; - //! generate public key - /*! \pre size of publicKey == PublicKeyLength() */ - virtual void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const =0; - //! generate private/public key pair - /*! \note equivalent to calling GeneratePrivateKey() and then GeneratePublicKey() */ - virtual void GenerateKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const; - //! derive agreed value from your private key and couterparty's public key, return false in case of failure - /*! \note If you have previously validated the public key, use validateOtherPublicKey=false to save time. - \pre size of agreedValue == AgreedValueLength() - \pre length of privateKey == PrivateKeyLength() - \pre length of otherPublicKey == PublicKeyLength() - */ - virtual bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const =0; - -#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY - bool ValidateDomainParameters(RandomNumberGenerator &rng) const - {return GetCryptoParameters().Validate(rng, 2);} -#endif -}; - -//! interface for domains of authenticated key agreement protocols - -/*! In an authenticated key agreement protocol, each party has two - key pairs. The long-lived key pair is called the static key pair, - and the short-lived key pair is called the ephemeral key pair. -*/ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedKeyAgreementDomain : public KeyAgreementAlgorithm -{ -public: - //! return length of agreed value produced - virtual unsigned int AgreedValueLength() const =0; - - //! return length of static private keys in this domain - virtual unsigned int StaticPrivateKeyLength() const =0; - //! return length of static public keys in this domain - virtual unsigned int StaticPublicKeyLength() const =0; - //! generate static private key - /*! \pre size of privateKey == PrivateStaticKeyLength() */ - virtual void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const =0; - //! generate static public key - /*! \pre size of publicKey == PublicStaticKeyLength() */ - virtual void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const =0; - //! generate private/public key pair - /*! \note equivalent to calling GenerateStaticPrivateKey() and then GenerateStaticPublicKey() */ - virtual void GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const; - - //! return length of ephemeral private keys in this domain - virtual unsigned int EphemeralPrivateKeyLength() const =0; - //! return length of ephemeral public keys in this domain - virtual unsigned int EphemeralPublicKeyLength() const =0; - //! generate ephemeral private key - /*! \pre size of privateKey == PrivateEphemeralKeyLength() */ - virtual void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const =0; - //! generate ephemeral public key - /*! \pre size of publicKey == PublicEphemeralKeyLength() */ - virtual void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const =0; - //! generate private/public key pair - /*! \note equivalent to calling GenerateEphemeralPrivateKey() and then GenerateEphemeralPublicKey() */ - virtual void GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const; - - //! derive agreed value from your private keys and couterparty's public keys, return false in case of failure - /*! \note The ephemeral public key will always be validated. - If you have previously validated the static public key, use validateStaticOtherPublicKey=false to save time. - \pre size of agreedValue == AgreedValueLength() - \pre length of staticPrivateKey == StaticPrivateKeyLength() - \pre length of ephemeralPrivateKey == EphemeralPrivateKeyLength() - \pre length of staticOtherPublicKey == StaticPublicKeyLength() - \pre length of ephemeralOtherPublicKey == EphemeralPublicKeyLength() - */ - virtual bool Agree(byte *agreedValue, - const byte *staticPrivateKey, const byte *ephemeralPrivateKey, - const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey, - bool validateStaticOtherPublicKey=true) const =0; - -#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY - bool ValidateDomainParameters(RandomNumberGenerator &rng) const - {return GetCryptoParameters().Validate(rng, 2);} -#endif -}; - -// interface for password authenticated key agreement protocols, not implemented yet -#if 0 -//! interface for protocol sessions -/*! The methods should be called in the following order: - - InitializeSession(rng, parameters); // or call initialize method in derived class - while (true) - { - if (OutgoingMessageAvailable()) - { - length = GetOutgoingMessageLength(); - GetOutgoingMessage(message); - ; // send outgoing message - } - - if (LastMessageProcessed()) - break; - - ; // receive incoming message - ProcessIncomingMessage(message); - } - ; // call methods in derived class to obtain result of protocol session -*/ -class ProtocolSession -{ -public: - //! exception thrown when an invalid protocol message is processed - class ProtocolError : public Exception - { - public: - ProtocolError(ErrorType errorType, const std::string &s) : Exception(errorType, s) {} - }; - - //! exception thrown when a function is called unexpectedly - /*! for example calling ProcessIncomingMessage() when ProcessedLastMessage() == true */ - class UnexpectedMethodCall : public Exception - { - public: - UnexpectedMethodCall(const std::string &s) : Exception(OTHER_ERROR, s) {} - }; - - ProtocolSession() : m_rng(NULL), m_throwOnProtocolError(true), m_validState(false) {} - virtual ~ProtocolSession() {} - - virtual void InitializeSession(RandomNumberGenerator &rng, const NameValuePairs ¶meters) =0; - - bool GetThrowOnProtocolError() const {return m_throwOnProtocolError;} - void SetThrowOnProtocolError(bool throwOnProtocolError) {m_throwOnProtocolError = throwOnProtocolError;} - - bool HasValidState() const {return m_validState;} - - virtual bool OutgoingMessageAvailable() const =0; - virtual unsigned int GetOutgoingMessageLength() const =0; - virtual void GetOutgoingMessage(byte *message) =0; - - virtual bool LastMessageProcessed() const =0; - virtual void ProcessIncomingMessage(const byte *message, unsigned int messageLength) =0; - -protected: - void HandleProtocolError(Exception::ErrorType errorType, const std::string &s) const; - void CheckAndHandleInvalidState() const; - void SetValidState(bool valid) {m_validState = valid;} - - RandomNumberGenerator *m_rng; - -private: - bool m_throwOnProtocolError, m_validState; -}; - -class KeyAgreementSession : public ProtocolSession -{ -public: - virtual unsigned int GetAgreedValueLength() const =0; - virtual void GetAgreedValue(byte *agreedValue) const =0; -}; - -class PasswordAuthenticatedKeyAgreementSession : public KeyAgreementSession -{ -public: - void InitializePasswordAuthenticatedKeyAgreementSession(RandomNumberGenerator &rng, - const byte *myId, unsigned int myIdLength, - const byte *counterPartyId, unsigned int counterPartyIdLength, - const byte *passwordOrVerifier, unsigned int passwordOrVerifierLength); -}; - -class PasswordAuthenticatedKeyAgreementDomain : public KeyAgreementAlgorithm -{ -public: - //! return whether the domain parameters stored in this object are valid - virtual bool ValidateDomainParameters(RandomNumberGenerator &rng) const - {return GetCryptoParameters().Validate(rng, 2);} - - virtual unsigned int GetPasswordVerifierLength(const byte *password, unsigned int passwordLength) const =0; - virtual void GeneratePasswordVerifier(RandomNumberGenerator &rng, const byte *userId, unsigned int userIdLength, const byte *password, unsigned int passwordLength, byte *verifier) const =0; - - enum RoleFlags {CLIENT=1, SERVER=2, INITIATOR=4, RESPONDER=8}; - - virtual bool IsValidRole(unsigned int role) =0; - virtual PasswordAuthenticatedKeyAgreementSession * CreateProtocolSession(unsigned int role) const =0; -}; -#endif - -//! BER Decode Exception Class, may be thrown during an ASN1 BER decode operation -class CRYPTOPP_DLL BERDecodeErr : public InvalidArgument -{ -public: - BERDecodeErr() : InvalidArgument("BER decode error") {} - BERDecodeErr(const std::string &s) : InvalidArgument(s) {} -}; - -//! interface for encoding and decoding ASN1 objects -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1Object -{ -public: - virtual ~ASN1Object() {} - //! decode this object from a BufferedTransformation, using BER (Basic Encoding Rules) - virtual void BERDecode(BufferedTransformation &bt) =0; - //! encode this object into a BufferedTransformation, using DER (Distinguished Encoding Rules) - virtual void DEREncode(BufferedTransformation &bt) const =0; - //! encode this object into a BufferedTransformation, using BER - /*! this may be useful if DEREncode() would be too inefficient */ - virtual void BEREncode(BufferedTransformation &bt) const {DEREncode(bt);} -}; - -#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY -typedef PK_SignatureScheme PK_SignatureSystem; -typedef SimpleKeyAgreementDomain PK_SimpleKeyAgreementDomain; -typedef AuthenticatedKeyAgreementDomain PK_AuthenticatedKeyAgreementDomain; -#endif - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/cryptlib.vcproj b/embeddedcryptopp/cryptlib.vcproj deleted file mode 100644 index 210401e..0000000 --- a/embeddedcryptopp/cryptlib.vcproj +++ /dev/null @@ -1,9580 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/embeddedcryptopp/cryptlib_bds.bdsproj b/embeddedcryptopp/cryptlib_bds.bdsproj deleted file mode 100644 index 9b9c7b2..0000000 --- a/embeddedcryptopp/cryptlib_bds.bdsproj +++ /dev/null @@ -1,377 +0,0 @@ - - - - - - - - - - - - cryptlib_bds.cpp - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - False - False - 1 - 0 - 0 - 0 - False - False - False - False - False - 1033 - 1252 - - - - - 1.0.0.0 - - - - - - 1.0.0.0 - - - - - - - - - False - - - - - - - False - - False - - True - False - - - - - - - - - - - diff --git a/embeddedcryptopp/cryptopp.rc b/embeddedcryptopp/cryptopp.rc deleted file mode 100644 index c33dc98..0000000 --- a/embeddedcryptopp/cryptopp.rc +++ /dev/null @@ -1,104 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 5,6,0,0 - PRODUCTVERSION 5,6,0,0 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "Comments", "free crypto library, more information available at www.cryptopp.com" - VALUE "CompanyName", "Wei Dai" - VALUE "FileDescription", "Crypto++® Library DLL" - VALUE "FileVersion", "5, 6, 0, 0" - VALUE "InternalName", "cryptopp" - VALUE "LegalCopyright", "Copyright © 1995-2009 by Wei Dai" - VALUE "LegalTrademarks", "Crypto++®" - VALUE "OriginalFilename", "cryptopp.dll" - VALUE "ProductName", "Crypto++® Library" - VALUE "ProductVersion", "5, 6, 0, 0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/embeddedcryptopp/des.cpp b/embeddedcryptopp/des.cpp deleted file mode 100644 index a6e0c51..0000000 --- a/embeddedcryptopp/des.cpp +++ /dev/null @@ -1,449 +0,0 @@ -// des.cpp - modified by Wei Dai from Phil Karn's des.c -// The original code and all modifications are in the public domain. - -/* - * This is a major rewrite of my old public domain DES code written - * circa 1987, which in turn borrowed heavily from Jim Gillogly's 1977 - * public domain code. I pretty much kept my key scheduling code, but - * the actual encrypt/decrypt routines are taken from from Richard - * Outerbridge's DES code as printed in Schneier's "Applied Cryptography." - * - * This code is in the public domain. I would appreciate bug reports and - * enhancements. - * - * Phil Karn KA9Q, karn@unix.ka9q.ampr.org, August 1994. - */ - -#include "pch.h" -#include "misc.h" -#include "des.h" - -NAMESPACE_BEGIN(CryptoPP) - -typedef BlockGetAndPut Block; - -// Richard Outerbridge's initial permutation algorithm -/* -inline void IPERM(word32 &left, word32 &right) -{ - word32 work; - - work = ((left >> 4) ^ right) & 0x0f0f0f0f; - right ^= work; - left ^= work << 4; - work = ((left >> 16) ^ right) & 0xffff; - right ^= work; - left ^= work << 16; - work = ((right >> 2) ^ left) & 0x33333333; - left ^= work; - right ^= (work << 2); - work = ((right >> 8) ^ left) & 0xff00ff; - left ^= work; - right ^= (work << 8); - right = rotl(right, 1); - work = (left ^ right) & 0xaaaaaaaa; - left ^= work; - right ^= work; - left = rotl(left, 1); -} -inline void FPERM(word32 &left, word32 &right) -{ - word32 work; - - right = rotr(right, 1); - work = (left ^ right) & 0xaaaaaaaa; - left ^= work; - right ^= work; - left = rotr(left, 1); - work = ((left >> 8) ^ right) & 0xff00ff; - right ^= work; - left ^= work << 8; - work = ((left >> 2) ^ right) & 0x33333333; - right ^= work; - left ^= work << 2; - work = ((right >> 16) ^ left) & 0xffff; - left ^= work; - right ^= work << 16; - work = ((right >> 4) ^ left) & 0x0f0f0f0f; - left ^= work; - right ^= work << 4; -} -*/ - -// Wei Dai's modification to Richard Outerbridge's initial permutation -// algorithm, this one is faster if you have access to rotate instructions -// (like in MSVC) -static inline void IPERM(word32 &left, word32 &right) -{ - word32 work; - - right = rotlFixed(right, 4U); - work = (left ^ right) & 0xf0f0f0f0; - left ^= work; - right = rotrFixed(right^work, 20U); - work = (left ^ right) & 0xffff0000; - left ^= work; - right = rotrFixed(right^work, 18U); - work = (left ^ right) & 0x33333333; - left ^= work; - right = rotrFixed(right^work, 6U); - work = (left ^ right) & 0x00ff00ff; - left ^= work; - right = rotlFixed(right^work, 9U); - work = (left ^ right) & 0xaaaaaaaa; - left = rotlFixed(left^work, 1U); - right ^= work; -} - -static inline void FPERM(word32 &left, word32 &right) -{ - word32 work; - - right = rotrFixed(right, 1U); - work = (left ^ right) & 0xaaaaaaaa; - right ^= work; - left = rotrFixed(left^work, 9U); - work = (left ^ right) & 0x00ff00ff; - right ^= work; - left = rotlFixed(left^work, 6U); - work = (left ^ right) & 0x33333333; - right ^= work; - left = rotlFixed(left^work, 18U); - work = (left ^ right) & 0xffff0000; - right ^= work; - left = rotlFixed(left^work, 20U); - work = (left ^ right) & 0xf0f0f0f0; - right ^= work; - left = rotrFixed(left^work, 4U); -} - -void DES::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) -{ - AssertValidKeyLength(length); - - RawSetKey(GetCipherDirection(), userKey); -} - -#ifndef CRYPTOPP_IMPORTS - -/* Tables defined in the Data Encryption Standard documents - * Three of these tables, the initial permutation, the final - * permutation and the expansion operator, are regular enough that - * for speed, we hard-code them. They're here for reference only. - * Also, the S and P boxes are used by a separate program, gensp.c, - * to build the combined SP box, Spbox[]. They're also here just - * for reference. - */ -#ifdef notdef -/* initial permutation IP */ -static byte ip[] = { - 58, 50, 42, 34, 26, 18, 10, 2, - 60, 52, 44, 36, 28, 20, 12, 4, - 62, 54, 46, 38, 30, 22, 14, 6, - 64, 56, 48, 40, 32, 24, 16, 8, - 57, 49, 41, 33, 25, 17, 9, 1, - 59, 51, 43, 35, 27, 19, 11, 3, - 61, 53, 45, 37, 29, 21, 13, 5, - 63, 55, 47, 39, 31, 23, 15, 7 -}; - -/* final permutation IP^-1 */ -static byte fp[] = { - 40, 8, 48, 16, 56, 24, 64, 32, - 39, 7, 47, 15, 55, 23, 63, 31, - 38, 6, 46, 14, 54, 22, 62, 30, - 37, 5, 45, 13, 53, 21, 61, 29, - 36, 4, 44, 12, 52, 20, 60, 28, - 35, 3, 43, 11, 51, 19, 59, 27, - 34, 2, 42, 10, 50, 18, 58, 26, - 33, 1, 41, 9, 49, 17, 57, 25 -}; -/* expansion operation matrix */ -static byte ei[] = { - 32, 1, 2, 3, 4, 5, - 4, 5, 6, 7, 8, 9, - 8, 9, 10, 11, 12, 13, - 12, 13, 14, 15, 16, 17, - 16, 17, 18, 19, 20, 21, - 20, 21, 22, 23, 24, 25, - 24, 25, 26, 27, 28, 29, - 28, 29, 30, 31, 32, 1 -}; -/* The (in)famous S-boxes */ -static byte sbox[8][64] = { - /* S1 */ - 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, - 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, - 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, - 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13, - - /* S2 */ - 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, - 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, - 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, - 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9, - - /* S3 */ - 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, - 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, - 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, - 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12, - - /* S4 */ - 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, - 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, - 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, - 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14, - - /* S5 */ - 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, - 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, - 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, - 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3, - - /* S6 */ - 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, - 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, - 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, - 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13, - - /* S7 */ - 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, - 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, - 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, - 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12, - - /* S8 */ - 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, - 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, - 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, - 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 -}; - -/* 32-bit permutation function P used on the output of the S-boxes */ -static byte p32i[] = { - 16, 7, 20, 21, - 29, 12, 28, 17, - 1, 15, 23, 26, - 5, 18, 31, 10, - 2, 8, 24, 14, - 32, 27, 3, 9, - 19, 13, 30, 6, - 22, 11, 4, 25 -}; -#endif - -/* permuted choice table (key) */ -static const byte pc1[] = { - 57, 49, 41, 33, 25, 17, 9, - 1, 58, 50, 42, 34, 26, 18, - 10, 2, 59, 51, 43, 35, 27, - 19, 11, 3, 60, 52, 44, 36, - - 63, 55, 47, 39, 31, 23, 15, - 7, 62, 54, 46, 38, 30, 22, - 14, 6, 61, 53, 45, 37, 29, - 21, 13, 5, 28, 20, 12, 4 -}; - -/* number left rotations of pc1 */ -static const byte totrot[] = { - 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 -}; - -/* permuted choice key (table) */ -static const byte pc2[] = { - 14, 17, 11, 24, 1, 5, - 3, 28, 15, 6, 21, 10, - 23, 19, 12, 4, 26, 8, - 16, 7, 27, 20, 13, 2, - 41, 52, 31, 37, 47, 55, - 30, 40, 51, 45, 33, 48, - 44, 49, 39, 56, 34, 53, - 46, 42, 50, 36, 29, 32 -}; - -/* End of DES-defined tables */ - -/* bit 0 is left-most in byte */ -static const int bytebit[] = { - 0200,0100,040,020,010,04,02,01 -}; - -/* Set key (initialize key schedule array) */ -void RawDES::RawSetKey(CipherDir dir, const byte *key) -{ - SecByteBlock buffer(56+56+8); - byte *const pc1m=buffer; /* place to modify pc1 into */ - byte *const pcr=pc1m+56; /* place to rotate pc1 into */ - byte *const ks=pcr+56; - register int i,j,l; - int m; - - for (j=0; j<56; j++) { /* convert pc1 to bits of key */ - l=pc1[j]-1; /* integer bit location */ - m = l & 07; /* find bit */ - pc1m[j]=(key[l>>3] & /* find which key byte l is in */ - bytebit[m]) /* and which bit of that byte */ - ? 1 : 0; /* and store 1-bit result */ - } - for (i=0; i<16; i++) { /* key chunk for each iteration */ - memset(ks,0,8); /* Clear key schedule */ - for (j=0; j<56; j++) /* rotate pc1 the right amount */ - pcr[j] = pc1m[(l=j+totrot[i])<(j<28? 28 : 56) ? l: l-28]; - /* rotate left and right halves independently */ - for (j=0; j<48; j++){ /* select bits individually */ - /* check bit that goes to ks[j] */ - if (pcr[pc2[j]-1]){ - /* mask it in if it's there */ - l= j % 6; - ks[j/6] |= bytebit[l] >> 2; - } - } - /* Now convert to odd/even interleaved form for use in F */ - k[2*i] = ((word32)ks[0] << 24) - | ((word32)ks[2] << 16) - | ((word32)ks[4] << 8) - | ((word32)ks[6]); - k[2*i+1] = ((word32)ks[1] << 24) - | ((word32)ks[3] << 16) - | ((word32)ks[5] << 8) - | ((word32)ks[7]); - } - - if (dir==DECRYPTION) // reverse key schedule order - for (i=0; i<16; i+=2) - { - std::swap(k[i], k[32-2-i]); - std::swap(k[i+1], k[32-1-i]); - } -} - -void RawDES::RawProcessBlock(word32 &l_, word32 &r_) const -{ - word32 l = l_, r = r_; - const word32 *kptr=k; - - for (unsigned i=0; i<8; i++) - { - word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0]; - l ^= Spbox[6][(work) & 0x3f] - ^ Spbox[4][(work >> 8) & 0x3f] - ^ Spbox[2][(work >> 16) & 0x3f] - ^ Spbox[0][(work >> 24) & 0x3f]; - work = r ^ kptr[4*i+1]; - l ^= Spbox[7][(work) & 0x3f] - ^ Spbox[5][(work >> 8) & 0x3f] - ^ Spbox[3][(work >> 16) & 0x3f] - ^ Spbox[1][(work >> 24) & 0x3f]; - - work = rotrFixed(l, 4U) ^ kptr[4*i+2]; - r ^= Spbox[6][(work) & 0x3f] - ^ Spbox[4][(work >> 8) & 0x3f] - ^ Spbox[2][(work >> 16) & 0x3f] - ^ Spbox[0][(work >> 24) & 0x3f]; - work = l ^ kptr[4*i+3]; - r ^= Spbox[7][(work) & 0x3f] - ^ Spbox[5][(work >> 8) & 0x3f] - ^ Spbox[3][(work >> 16) & 0x3f] - ^ Spbox[1][(work >> 24) & 0x3f]; - } - - l_ = l; r_ = r; -} - -void DES_EDE2::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) -{ - AssertValidKeyLength(length); - - m_des1.RawSetKey(GetCipherDirection(), userKey); - m_des2.RawSetKey(ReverseCipherDir(GetCipherDirection()), userKey+8); -} - -void DES_EDE2::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const -{ - word32 l,r; - Block::Get(inBlock)(l)(r); - IPERM(l,r); - m_des1.RawProcessBlock(l, r); - m_des2.RawProcessBlock(r, l); - m_des1.RawProcessBlock(l, r); - FPERM(l,r); - Block::Put(xorBlock, outBlock)(r)(l); -} - -void DES_EDE3::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) -{ - AssertValidKeyLength(length); - - m_des1.RawSetKey(GetCipherDirection(), userKey + (IsForwardTransformation() ? 0 : 16)); - m_des2.RawSetKey(ReverseCipherDir(GetCipherDirection()), userKey + 8); - m_des3.RawSetKey(GetCipherDirection(), userKey + (IsForwardTransformation() ? 16 : 0)); -} - -void DES_EDE3::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const -{ - word32 l,r; - Block::Get(inBlock)(l)(r); - IPERM(l,r); - m_des1.RawProcessBlock(l, r); - m_des2.RawProcessBlock(r, l); - m_des3.RawProcessBlock(l, r); - FPERM(l,r); - Block::Put(xorBlock, outBlock)(r)(l); -} - -#endif // #ifndef CRYPTOPP_IMPORTS - -static inline bool CheckParity(byte b) -{ - unsigned int a = b ^ (b >> 4); - return ((a ^ (a>>1) ^ (a>>2) ^ (a>>3)) & 1) == 1; -} - -bool DES::CheckKeyParityBits(const byte *key) -{ - for (unsigned int i=0; i<8; i++) - if (!CheckParity(key[i])) - return false; - return true; -} - -void DES::CorrectKeyParityBits(byte *key) -{ - for (unsigned int i=0; i<8; i++) - if (!CheckParity(key[i])) - key[i] ^= 1; -} - -// Encrypt or decrypt a block of data in ECB mode -void DES::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const -{ - word32 l,r; - Block::Get(inBlock)(l)(r); - IPERM(l,r); - RawProcessBlock(l, r); - FPERM(l,r); - Block::Put(xorBlock, outBlock)(r)(l); -} - -void DES_XEX3::Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &) -{ - AssertValidKeyLength(length); - - if (!m_des.get()) - m_des.reset(new DES::Encryption); - - memcpy(m_x1, key + (IsForwardTransformation() ? 0 : 16), BLOCKSIZE); - m_des->RawSetKey(GetCipherDirection(), key + 8); - memcpy(m_x3, key + (IsForwardTransformation() ? 16 : 0), BLOCKSIZE); -} - -void DES_XEX3::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const -{ - xorbuf(outBlock, inBlock, m_x1, BLOCKSIZE); - m_des->ProcessAndXorBlock(outBlock, xorBlock, outBlock); - xorbuf(outBlock, m_x3, BLOCKSIZE); -} - -NAMESPACE_END diff --git a/embeddedcryptopp/des.h b/embeddedcryptopp/des.h deleted file mode 100644 index 62f6288..0000000 --- a/embeddedcryptopp/des.h +++ /dev/null @@ -1,144 +0,0 @@ -#ifndef CRYPTOPP_DES_H -#define CRYPTOPP_DES_H - -/** \file -*/ - -#include "seckey.h" -#include "secblock.h" - -NAMESPACE_BEGIN(CryptoPP) - -class CRYPTOPP_DLL RawDES -{ -public: - void RawSetKey(CipherDir direction, const byte *userKey); - void RawProcessBlock(word32 &l, word32 &r) const; - -protected: - static const word32 Spbox[8][64]; - - FixedSizeSecBlock k; -}; - -//! _ -struct DES_Info : public FixedBlockSize<8>, public FixedKeyLength<8> -{ - // disable DES in DLL version by not exporting this function - static const char * StaticAlgorithmName() {return "DES";} -}; - -/// DES -/*! The DES implementation in Crypto++ ignores the parity bits - (the least significant bits of each byte) in the key. However - you can use CheckKeyParityBits() and CorrectKeyParityBits() to - check or correct the parity bits if you wish. */ -class DES : public DES_Info, public BlockCipherDocumentation -{ - class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl, public RawDES - { - public: - void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); - void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; - }; - -public: - //! check DES key parity bits - static bool CheckKeyParityBits(const byte *key); - //! correct DES key parity bits - static void CorrectKeyParityBits(byte *key); - - typedef BlockCipherFinal Encryption; - typedef BlockCipherFinal Decryption; -}; - -//! _ -struct DES_EDE2_Info : public FixedBlockSize<8>, public FixedKeyLength<16> -{ - CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return "DES-EDE2";} -}; - -/// DES-EDE2 -class DES_EDE2 : public DES_EDE2_Info, public BlockCipherDocumentation -{ - class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl - { - public: - void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); - void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; - - protected: - RawDES m_des1, m_des2; - }; - -public: - typedef BlockCipherFinal Encryption; - typedef BlockCipherFinal Decryption; -}; - -//! _ -struct DES_EDE3_Info : public FixedBlockSize<8>, public FixedKeyLength<24> -{ - CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return "DES-EDE3";} -}; - -/// DES-EDE3 -class DES_EDE3 : public DES_EDE3_Info, public BlockCipherDocumentation -{ - class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl - { - public: - void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); - void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; - - protected: - RawDES m_des1, m_des2, m_des3; - }; - -public: - typedef BlockCipherFinal Encryption; - typedef BlockCipherFinal Decryption; -}; - -//! _ -struct DES_XEX3_Info : public FixedBlockSize<8>, public FixedKeyLength<24> -{ - static const char *StaticAlgorithmName() {return "DES-XEX3";} -}; - -/// DES-XEX3, AKA DESX -class DES_XEX3 : public DES_XEX3_Info, public BlockCipherDocumentation -{ - class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl - { - public: - void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); - void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; - - protected: - FixedSizeSecBlock m_x1, m_x3; - // VS2005 workaround: calling modules compiled with /clr gets unresolved external symbol DES::Base::ProcessAndXorBlock - // if we use DES::Encryption here directly without value_ptr. - value_ptr m_des; - }; - -public: - typedef BlockCipherFinal Encryption; - typedef BlockCipherFinal Decryption; -}; - -typedef DES::Encryption DESEncryption; -typedef DES::Decryption DESDecryption; - -typedef DES_EDE2::Encryption DES_EDE2_Encryption; -typedef DES_EDE2::Decryption DES_EDE2_Decryption; - -typedef DES_EDE3::Encryption DES_EDE3_Encryption; -typedef DES_EDE3::Decryption DES_EDE3_Decryption; - -typedef DES_XEX3::Encryption DES_XEX3_Encryption; -typedef DES_XEX3::Decryption DES_XEX3_Decryption; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/dessp.cpp b/embeddedcryptopp/dessp.cpp deleted file mode 100644 index 49ed1d2..0000000 --- a/embeddedcryptopp/dessp.cpp +++ /dev/null @@ -1,95 +0,0 @@ -// This file is mostly generated by Phil Karn's gensp.c - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "des.h" - -NAMESPACE_BEGIN(CryptoPP) - -// VC60 workaround: gives a C4786 warning without this function -// when runtime lib is set to multithread debug DLL -// even though warning 4786 is disabled! -void DES_VC60Workaround() -{ -} - -const word32 RawDES::Spbox[8][64] = { -{ -0x01010400,0x00000000,0x00010000,0x01010404, 0x01010004,0x00010404,0x00000004,0x00010000, -0x00000400,0x01010400,0x01010404,0x00000400, 0x01000404,0x01010004,0x01000000,0x00000004, -0x00000404,0x01000400,0x01000400,0x00010400, 0x00010400,0x01010000,0x01010000,0x01000404, -0x00010004,0x01000004,0x01000004,0x00010004, 0x00000000,0x00000404,0x00010404,0x01000000, -0x00010000,0x01010404,0x00000004,0x01010000, 0x01010400,0x01000000,0x01000000,0x00000400, -0x01010004,0x00010000,0x00010400,0x01000004, 0x00000400,0x00000004,0x01000404,0x00010404, -0x01010404,0x00010004,0x01010000,0x01000404, 0x01000004,0x00000404,0x00010404,0x01010400, -0x00000404,0x01000400,0x01000400,0x00000000, 0x00010004,0x00010400,0x00000000,0x01010004}, -{ -0x80108020,0x80008000,0x00008000,0x00108020, 0x00100000,0x00000020,0x80100020,0x80008020, -0x80000020,0x80108020,0x80108000,0x80000000, 0x80008000,0x00100000,0x00000020,0x80100020, -0x00108000,0x00100020,0x80008020,0x00000000, 0x80000000,0x00008000,0x00108020,0x80100000, -0x00100020,0x80000020,0x00000000,0x00108000, 0x00008020,0x80108000,0x80100000,0x00008020, -0x00000000,0x00108020,0x80100020,0x00100000, 0x80008020,0x80100000,0x80108000,0x00008000, -0x80100000,0x80008000,0x00000020,0x80108020, 0x00108020,0x00000020,0x00008000,0x80000000, -0x00008020,0x80108000,0x00100000,0x80000020, 0x00100020,0x80008020,0x80000020,0x00100020, -0x00108000,0x00000000,0x80008000,0x00008020, 0x80000000,0x80100020,0x80108020,0x00108000}, -{ -0x00000208,0x08020200,0x00000000,0x08020008, 0x08000200,0x00000000,0x00020208,0x08000200, -0x00020008,0x08000008,0x08000008,0x00020000, 0x08020208,0x00020008,0x08020000,0x00000208, -0x08000000,0x00000008,0x08020200,0x00000200, 0x00020200,0x08020000,0x08020008,0x00020208, -0x08000208,0x00020200,0x00020000,0x08000208, 0x00000008,0x08020208,0x00000200,0x08000000, -0x08020200,0x08000000,0x00020008,0x00000208, 0x00020000,0x08020200,0x08000200,0x00000000, -0x00000200,0x00020008,0x08020208,0x08000200, 0x08000008,0x00000200,0x00000000,0x08020008, -0x08000208,0x00020000,0x08000000,0x08020208, 0x00000008,0x00020208,0x00020200,0x08000008, -0x08020000,0x08000208,0x00000208,0x08020000, 0x00020208,0x00000008,0x08020008,0x00020200}, -{ -0x00802001,0x00002081,0x00002081,0x00000080, 0x00802080,0x00800081,0x00800001,0x00002001, -0x00000000,0x00802000,0x00802000,0x00802081, 0x00000081,0x00000000,0x00800080,0x00800001, -0x00000001,0x00002000,0x00800000,0x00802001, 0x00000080,0x00800000,0x00002001,0x00002080, -0x00800081,0x00000001,0x00002080,0x00800080, 0x00002000,0x00802080,0x00802081,0x00000081, -0x00800080,0x00800001,0x00802000,0x00802081, 0x00000081,0x00000000,0x00000000,0x00802000, -0x00002080,0x00800080,0x00800081,0x00000001, 0x00802001,0x00002081,0x00002081,0x00000080, -0x00802081,0x00000081,0x00000001,0x00002000, 0x00800001,0x00002001,0x00802080,0x00800081, -0x00002001,0x00002080,0x00800000,0x00802001, 0x00000080,0x00800000,0x00002000,0x00802080}, -{ -0x00000100,0x02080100,0x02080000,0x42000100, 0x00080000,0x00000100,0x40000000,0x02080000, -0x40080100,0x00080000,0x02000100,0x40080100, 0x42000100,0x42080000,0x00080100,0x40000000, -0x02000000,0x40080000,0x40080000,0x00000000, 0x40000100,0x42080100,0x42080100,0x02000100, -0x42080000,0x40000100,0x00000000,0x42000000, 0x02080100,0x02000000,0x42000000,0x00080100, -0x00080000,0x42000100,0x00000100,0x02000000, 0x40000000,0x02080000,0x42000100,0x40080100, -0x02000100,0x40000000,0x42080000,0x02080100, 0x40080100,0x00000100,0x02000000,0x42080000, -0x42080100,0x00080100,0x42000000,0x42080100, 0x02080000,0x00000000,0x40080000,0x42000000, -0x00080100,0x02000100,0x40000100,0x00080000, 0x00000000,0x40080000,0x02080100,0x40000100}, -{ -0x20000010,0x20400000,0x00004000,0x20404010, 0x20400000,0x00000010,0x20404010,0x00400000, -0x20004000,0x00404010,0x00400000,0x20000010, 0x00400010,0x20004000,0x20000000,0x00004010, -0x00000000,0x00400010,0x20004010,0x00004000, 0x00404000,0x20004010,0x00000010,0x20400010, -0x20400010,0x00000000,0x00404010,0x20404000, 0x00004010,0x00404000,0x20404000,0x20000000, -0x20004000,0x00000010,0x20400010,0x00404000, 0x20404010,0x00400000,0x00004010,0x20000010, -0x00400000,0x20004000,0x20000000,0x00004010, 0x20000010,0x20404010,0x00404000,0x20400000, -0x00404010,0x20404000,0x00000000,0x20400010, 0x00000010,0x00004000,0x20400000,0x00404010, -0x00004000,0x00400010,0x20004010,0x00000000, 0x20404000,0x20000000,0x00400010,0x20004010}, -{ -0x00200000,0x04200002,0x04000802,0x00000000, 0x00000800,0x04000802,0x00200802,0x04200800, -0x04200802,0x00200000,0x00000000,0x04000002, 0x00000002,0x04000000,0x04200002,0x00000802, -0x04000800,0x00200802,0x00200002,0x04000800, 0x04000002,0x04200000,0x04200800,0x00200002, -0x04200000,0x00000800,0x00000802,0x04200802, 0x00200800,0x00000002,0x04000000,0x00200800, -0x04000000,0x00200800,0x00200000,0x04000802, 0x04000802,0x04200002,0x04200002,0x00000002, -0x00200002,0x04000000,0x04000800,0x00200000, 0x04200800,0x00000802,0x00200802,0x04200800, -0x00000802,0x04000002,0x04200802,0x04200000, 0x00200800,0x00000000,0x00000002,0x04200802, -0x00000000,0x00200802,0x04200000,0x00000800, 0x04000002,0x04000800,0x00000800,0x00200002}, -{ -0x10001040,0x00001000,0x00040000,0x10041040, 0x10000000,0x10001040,0x00000040,0x10000000, -0x00040040,0x10040000,0x10041040,0x00041000, 0x10041000,0x00041040,0x00001000,0x00000040, -0x10040000,0x10000040,0x10001000,0x00001040, 0x00041000,0x00040040,0x10040040,0x10041000, -0x00001040,0x00000000,0x00000000,0x10040040, 0x10000040,0x10001000,0x00041040,0x00040000, -0x00041040,0x00040000,0x10041000,0x00001000, 0x00000040,0x10040040,0x00001000,0x00041040, -0x10001000,0x00000040,0x10000040,0x10040000, 0x10040040,0x10000000,0x00040000,0x10001040, -0x00000000,0x10041040,0x00040040,0x10000040, 0x10040000,0x10001000,0x10001040,0x00000000, -0x10041040,0x00041000,0x00041000,0x00001040, 0x00001040,0x00040040,0x10000000,0x10041000} -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/dh.h b/embeddedcryptopp/dh.h deleted file mode 100644 index 10e8d14..0000000 --- a/embeddedcryptopp/dh.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef CRYPTOPP_DH_H -#define CRYPTOPP_DH_H - -/** \file -*/ - -#include "gfpcrypt.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! , -template -class DH_Domain : public DL_SimpleKeyAgreementDomainBase -{ - typedef DL_SimpleKeyAgreementDomainBase Base; - -public: - typedef GROUP_PARAMETERS GroupParameters; - typedef typename GroupParameters::Element Element; - typedef DL_KeyAgreementAlgorithm_DH DH_Algorithm; - typedef DH_Domain Domain; - - DH_Domain() {} - - DH_Domain(const GroupParameters ¶ms) - : m_groupParameters(params) {} - - DH_Domain(BufferedTransformation &bt) - {m_groupParameters.BERDecode(bt);} - - template - DH_Domain(RandomNumberGenerator &v1, const T2 &v2) - {m_groupParameters.Initialize(v1, v2);} - - template - DH_Domain(RandomNumberGenerator &v1, const T2 &v2, const T3 &v3) - {m_groupParameters.Initialize(v1, v2, v3);} - - template - DH_Domain(RandomNumberGenerator &v1, const T2 &v2, const T3 &v3, const T4 &v4) - {m_groupParameters.Initialize(v1, v2, v3, v4);} - - template - DH_Domain(const T1 &v1, const T2 &v2) - {m_groupParameters.Initialize(v1, v2);} - - template - DH_Domain(const T1 &v1, const T2 &v2, const T3 &v3) - {m_groupParameters.Initialize(v1, v2, v3);} - - template - DH_Domain(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) - {m_groupParameters.Initialize(v1, v2, v3, v4);} - - const GroupParameters & GetGroupParameters() const {return m_groupParameters;} - GroupParameters & AccessGroupParameters() {return m_groupParameters;} - - void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const - { - Base::GeneratePublicKey(rng, privateKey, publicKey); - - if (FIPS_140_2_ComplianceEnabled()) - { - SecByteBlock privateKey2(this->PrivateKeyLength()); - this->GeneratePrivateKey(rng, privateKey2); - - SecByteBlock publicKey2(this->PublicKeyLength()); - Base::GeneratePublicKey(rng, privateKey2, publicKey2); - - SecByteBlock agreedValue(this->AgreedValueLength()), agreedValue2(this->AgreedValueLength()); - bool agreed1 = this->Agree(agreedValue, privateKey, publicKey2); - bool agreed2 = this->Agree(agreedValue2, privateKey2, publicKey); - - if (!agreed1 || !agreed2 || agreedValue != agreedValue2) - throw SelfTestFailure(this->AlgorithmName() + ": pairwise consistency test failed"); - } - } - - static std::string CRYPTOPP_API StaticAlgorithmName() - {return GroupParameters::StaticAlgorithmNamePrefix() + DH_Algorithm::StaticAlgorithmName();} - std::string AlgorithmName() const {return StaticAlgorithmName();} - -private: - const DL_KeyAgreementAlgorithm & GetKeyAgreementAlgorithm() const - {return Singleton().Ref();} - DL_GroupParameters & AccessAbstractGroupParameters() - {return m_groupParameters;} - - GroupParameters m_groupParameters; -}; - -CRYPTOPP_DLL_TEMPLATE_CLASS DH_Domain; - -//! Diffie-Hellman in GF(p) with key validation -typedef DH_Domain DH; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/dll.cpp b/embeddedcryptopp/dll.cpp deleted file mode 100644 index 2b4ef7a..0000000 --- a/embeddedcryptopp/dll.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// dll.cpp - written and placed in the public domain by Wei Dai - -#define CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES -#define CRYPTOPP_DEFAULT_NO_DLL - -#include "dll.h" -#pragma warning(default: 4660) - -#if defined(CRYPTOPP_EXPORTS) && defined(CRYPTOPP_WIN32_AVAILABLE) -#include -#endif - -#ifndef CRYPTOPP_IMPORTS - -NAMESPACE_BEGIN(CryptoPP) - -template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14}; -template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); - -template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x2d,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x04,0x05,0x00,0x04,0x1c}; -template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); - -template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20}; -template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); - -template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30}; -template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); - -template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40}; -template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); - -template<> const byte EMSA2HashId::id = 0x33; -template<> const byte EMSA2HashId::id = 0x38; -template<> const byte EMSA2HashId::id = 0x34; -template<> const byte EMSA2HashId::id = 0x36; -template<> const byte EMSA2HashId::id = 0x35; - -NAMESPACE_END - -#endif - -#ifdef CRYPTOPP_EXPORTS - -USING_NAMESPACE(CryptoPP) - -#if !(defined(_MSC_VER) && (_MSC_VER < 1300)) -using std::set_new_handler; -#endif - -static PNew s_pNew = NULL; -static PDelete s_pDelete = NULL; - -static void * New (size_t size) -{ - void *p; - while (!(p = malloc(size))) - CallNewHandler(); - - return p; -} - -static void SetNewAndDeleteFunctionPointers() -{ - void *p = NULL; - HMODULE hModule = NULL; - MEMORY_BASIC_INFORMATION mbi; - - while (true) - { - VirtualQuery(p, &mbi, sizeof(mbi)); - - if (p >= (char *)mbi.BaseAddress + mbi.RegionSize) - break; - - p = (char *)mbi.BaseAddress + mbi.RegionSize; - - if (!mbi.AllocationBase || mbi.AllocationBase == hModule) - continue; - - hModule = HMODULE(mbi.AllocationBase); - - PGetNewAndDelete pGetNewAndDelete = (PGetNewAndDelete)GetProcAddress(hModule, "GetNewAndDeleteForCryptoPP"); - if (pGetNewAndDelete) - { - pGetNewAndDelete(s_pNew, s_pDelete); - return; - } - - PSetNewAndDelete pSetNewAndDelete = (PSetNewAndDelete)GetProcAddress(hModule, "SetNewAndDeleteFromCryptoPP"); - if (pSetNewAndDelete) - { - s_pNew = &New; - s_pDelete = &free; - pSetNewAndDelete(s_pNew, s_pDelete, &set_new_handler); - return; - } - } - - // try getting these directly using mangled names of new and delete operators - - hModule = GetModuleHandle("msvcrtd"); - if (!hModule) - hModule = GetModuleHandle("msvcrt"); - if (hModule) - { - // 32-bit versions - s_pNew = (PNew)GetProcAddress(hModule, "??2@YAPAXI@Z"); - s_pDelete = (PDelete)GetProcAddress(hModule, "??3@YAXPAX@Z"); - if (s_pNew && s_pDelete) - return; - - // 64-bit versions - s_pNew = (PNew)GetProcAddress(hModule, "??2@YAPEAX_K@Z"); - s_pDelete = (PDelete)GetProcAddress(hModule, "??3@YAXPEAX@Z"); - if (s_pNew && s_pDelete) - return; - } - - OutputDebugString("Crypto++ was not able to obtain new and delete function pointers.\n"); - throw 0; -} - -void * operator new (size_t size) -{ - if (!s_pNew) - SetNewAndDeleteFunctionPointers(); - - return s_pNew(size); -} - -void operator delete (void * p) -{ - s_pDelete(p); -} - -void * operator new [] (size_t size) -{ - return operator new (size); -} - -void operator delete [] (void * p) -{ - operator delete (p); -} - -#endif // #ifdef CRYPTOPP_EXPORTS diff --git a/embeddedcryptopp/dll.h b/embeddedcryptopp/dll.h deleted file mode 100644 index 5e42d46..0000000 --- a/embeddedcryptopp/dll.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef CRYPTOPP_DLL_H -#define CRYPTOPP_DLL_H - -#if !defined(CRYPTOPP_IMPORTS) && !defined(CRYPTOPP_EXPORTS) && !defined(CRYPTOPP_DEFAULT_NO_DLL) -#ifdef CRYPTOPP_CONFIG_H -#error To use the DLL version of Crypto++, this file must be included before any other Crypto++ header files. -#endif -#define CRYPTOPP_IMPORTS -#endif - -#include "aes.h" -#include "cbcmac.h" -#include "ccm.h" -#include "cmac.h" -#include "channels.h" -#include "des.h" -#include "dh.h" -#include "dsa.h" -#include "ec2n.h" -#include "eccrypto.h" -#include "ecp.h" -#include "files.h" -#include "fips140.h" -#include "gcm.h" -#include "hex.h" -#include "hmac.h" -#include "modes.h" -#include "mqueue.h" -#include "nbtheory.h" -#include "osrng.h" -#include "pkcspad.h" -#include "pssr.h" -#include "randpool.h" -#include "rsa.h" -#include "rw.h" -#include "sha.h" -#include "skipjack.h" -#include "trdlocal.h" - -#ifdef CRYPTOPP_IMPORTS - -#ifdef _DLL -// cause CRT DLL to be initialized before Crypto++ so that we can use malloc and free during DllMain() -#ifdef NDEBUG -#pragma comment(lib, "msvcrt") -#else -#pragma comment(lib, "msvcrtd") -#endif -#endif - -#pragma comment(lib, "cryptopp") - -#endif // #ifdef CRYPTOPP_IMPORTS - -#include // for new_handler - -NAMESPACE_BEGIN(CryptoPP) - -#if !(defined(_MSC_VER) && (_MSC_VER < 1300)) -using std::new_handler; -#endif - -typedef void * (CRYPTOPP_API * PNew)(size_t); -typedef void (CRYPTOPP_API * PDelete)(void *); -typedef void (CRYPTOPP_API * PGetNewAndDelete)(PNew &, PDelete &); -typedef new_handler (CRYPTOPP_API * PSetNewHandler)(new_handler); -typedef void (CRYPTOPP_API * PSetNewAndDelete)(PNew, PDelete, PSetNewHandler); - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/dlltest.dsp b/embeddedcryptopp/dlltest.dsp deleted file mode 100644 index b980b7f..0000000 --- a/embeddedcryptopp/dlltest.dsp +++ /dev/null @@ -1,90 +0,0 @@ -# Microsoft Developer Studio Project File - Name="dlltest" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=dlltest - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "dlltest.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "dlltest.mak" CFG="dlltest - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "dlltest - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "dlltest - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "dlltest - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "dlltest___Win32_Release" -# PROP BASE Intermediate_Dir "dlltest___Win32_Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "dlltest___Win32_Release" -# PROP Intermediate_Dir "dlltest___Win32_Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /Gz /MT /W3 /GR /GX /Zi /O1 /Ob2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "CRYPTOPP_DLL_ONLY" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 /nologo /subsystem:console /map /debug /machine:I386 /out:"DLL_Release/dlltest.exe" /libpath:"DLL_Release" - -!ELSEIF "$(CFG)" == "dlltest - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "dlltest___Win32_Debug" -# PROP BASE Intermediate_Dir "dlltest___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "dlltest___Win32_Debug" -# PROP Intermediate_Dir "dlltest___Win32_Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /Gz /MTd /W3 /Gm /GR /GX /Zi /Oi /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "CRYPTOPP_DLL_ONLY" /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /out:"DLL_Debug/dlltest.exe" /pdbtype:sept /libpath:"DLL_Debug" - -!ENDIF - -# Begin Target - -# Name "dlltest - Win32 Release" -# Name "dlltest - Win32 Debug" -# Begin Source File - -SOURCE=.\dlltest.cpp -# End Source File -# End Target -# End Project diff --git a/embeddedcryptopp/dlltest.vcproj b/embeddedcryptopp/dlltest.vcproj deleted file mode 100644 index 0bf11ff..0000000 --- a/embeddedcryptopp/dlltest.vcproj +++ /dev/null @@ -1,419 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/embeddedcryptopp/dsa.cpp b/embeddedcryptopp/dsa.cpp deleted file mode 100644 index ac9e1f8..0000000 --- a/embeddedcryptopp/dsa.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// dsa.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "dsa.h" -#include "nbtheory.h" - -NAMESPACE_BEGIN(CryptoPP) - -size_t DSAConvertSignatureFormat(byte *buffer, size_t bufferSize, DSASignatureFormat toFormat, const byte *signature, size_t signatureLen, DSASignatureFormat fromFormat) -{ - Integer r, s; - StringStore store(signature, signatureLen); - ArraySink sink(buffer, bufferSize); - - switch (fromFormat) - { - case DSA_P1363: - r.Decode(store, signatureLen/2); - s.Decode(store, signatureLen/2); - break; - case DSA_DER: - { - BERSequenceDecoder seq(store); - r.BERDecode(seq); - s.BERDecode(seq); - seq.MessageEnd(); - break; - } - case DSA_OPENPGP: - r.OpenPGPDecode(store); - s.OpenPGPDecode(store); - break; - } - - switch (toFormat) - { - case DSA_P1363: - r.Encode(sink, bufferSize/2); - s.Encode(sink, bufferSize/2); - break; - case DSA_DER: - { - DERSequenceEncoder seq(sink); - r.DEREncode(seq); - s.DEREncode(seq); - seq.MessageEnd(); - break; - } - case DSA_OPENPGP: - r.OpenPGPEncode(sink); - s.OpenPGPEncode(sink); - break; - } - - return (size_t)sink.TotalPutLength(); -} - -bool DSA::GeneratePrimes(const byte *seedIn, unsigned int g, int &counter, - Integer &p, unsigned int L, Integer &q, bool useInputCounterValue) -{ - assert(g%8 == 0); - - SHA sha; - SecByteBlock seed(seedIn, g/8); - SecByteBlock U(SHA::DIGESTSIZE); - SecByteBlock temp(SHA::DIGESTSIZE); - SecByteBlock W(((L-1)/160+1) * SHA::DIGESTSIZE); - const int n = (L-1) / 160; - const int b = (L-1) % 160; - Integer X; - - sha.CalculateDigest(U, seed, g/8); - - for (int i=g/8-1, carry=true; i>=0 && carry; i--) - carry=!++seed[i]; - - sha.CalculateDigest(temp, seed, g/8); - xorbuf(U, temp, SHA::DIGESTSIZE); - - U[0] |= 0x80; - U[SHA::DIGESTSIZE-1] |= 1; - q.Decode(U, SHA::DIGESTSIZE); - - if (!IsPrime(q)) - return false; - - int counterEnd = useInputCounterValue ? counter+1 : 4096; - - for (int c = 0; c < counterEnd; c++) - { - for (int k=0; k<=n; k++) - { - for (int i=g/8-1, carry=true; i>=0 && carry; i--) - carry=!++seed[i]; - if (!useInputCounterValue || c == counter) - sha.CalculateDigest(W+(n-k)*SHA::DIGESTSIZE, seed, g/8); - } - if (!useInputCounterValue || c == counter) - { - W[SHA::DIGESTSIZE - 1 - b/8] |= 0x80; - X.Decode(W + SHA::DIGESTSIZE - 1 - b/8, L/8); - p = X-((X % (2*q))-1); - - if (p.GetBit(L-1) && IsPrime(p)) - { - counter = c; - return true; - } - } - } - return false; -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/dsa.h b/embeddedcryptopp/dsa.h deleted file mode 100644 index 6ae0387..0000000 --- a/embeddedcryptopp/dsa.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef CRYPTOPP_DSA_H -#define CRYPTOPP_DSA_H - -/** \file -*/ - -#include "gfpcrypt.h" - -NAMESPACE_BEGIN(CryptoPP) - -/*! The DSA signature format used by Crypto++ is as defined by IEEE P1363. - Java uses the DER format, and OpenPGP uses the OpenPGP format. */ -enum DSASignatureFormat {DSA_P1363, DSA_DER, DSA_OPENPGP}; -/** This function converts between these formats, and returns length of signature in the target format. - If toFormat == DSA_P1363, bufferSize must equal publicKey.SignatureLength() */ -size_t DSAConvertSignatureFormat(byte *buffer, size_t bufferSize, DSASignatureFormat toFormat, - const byte *signature, size_t signatureLen, DSASignatureFormat fromFormat); - -#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY - -typedef DSA::Signer DSAPrivateKey; -typedef DSA::Verifier DSAPublicKey; - -const int MIN_DSA_PRIME_LENGTH = DSA::MIN_PRIME_LENGTH; -const int MAX_DSA_PRIME_LENGTH = DSA::MAX_PRIME_LENGTH; -const int DSA_PRIME_LENGTH_MULTIPLE = DSA::PRIME_LENGTH_MULTIPLE; - -inline bool GenerateDSAPrimes(const byte *seed, size_t seedLength, int &counter, Integer &p, unsigned int primeLength, Integer &q) - {return DSA::GeneratePrimes(seed, seedLength, counter, p, primeLength, q);} - -#endif - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/ec2n.cpp b/embeddedcryptopp/ec2n.cpp deleted file mode 100644 index dbab31a..0000000 --- a/embeddedcryptopp/ec2n.cpp +++ /dev/null @@ -1,288 +0,0 @@ -// ec2n.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "ec2n.h" -#include "asn.h" - -#include "algebra.cpp" -#include "eprecomp.cpp" - -NAMESPACE_BEGIN(CryptoPP) - -EC2N::EC2N(BufferedTransformation &bt) - : m_field(BERDecodeGF2NP(bt)) -{ - BERSequenceDecoder seq(bt); - m_field->BERDecodeElement(seq, m_a); - m_field->BERDecodeElement(seq, m_b); - // skip optional seed - if (!seq.EndReached()) - BERDecodeOctetString(seq, TheBitBucket()); - seq.MessageEnd(); -} - -void EC2N::DEREncode(BufferedTransformation &bt) const -{ - m_field->DEREncode(bt); - DERSequenceEncoder seq(bt); - m_field->DEREncodeElement(seq, m_a); - m_field->DEREncodeElement(seq, m_b); - seq.MessageEnd(); -} - -bool EC2N::DecodePoint(EC2N::Point &P, const byte *encodedPoint, size_t encodedPointLen) const -{ - StringStore store(encodedPoint, encodedPointLen); - return DecodePoint(P, store, encodedPointLen); -} - -bool EC2N::DecodePoint(EC2N::Point &P, BufferedTransformation &bt, size_t encodedPointLen) const -{ - byte type; - if (encodedPointLen < 1 || !bt.Get(type)) - return false; - - switch (type) - { - case 0: - P.identity = true; - return true; - case 2: - case 3: - { - if (encodedPointLen != EncodedPointSize(true)) - return false; - - P.identity = false; - P.x.Decode(bt, m_field->MaxElementByteLength()); - - if (P.x.IsZero()) - { - P.y = m_field->SquareRoot(m_b); - return true; - } - - FieldElement z = m_field->Square(P.x); - assert(P.x == m_field->SquareRoot(z)); - P.y = m_field->Divide(m_field->Add(m_field->Multiply(z, m_field->Add(P.x, m_a)), m_b), z); - assert(P.x == m_field->Subtract(m_field->Divide(m_field->Subtract(m_field->Multiply(P.y, z), m_b), z), m_a)); - z = m_field->SolveQuadraticEquation(P.y); - assert(m_field->Add(m_field->Square(z), z) == P.y); - z.SetCoefficient(0, type & 1); - - P.y = m_field->Multiply(z, P.x); - return true; - } - case 4: - { - if (encodedPointLen != EncodedPointSize(false)) - return false; - - unsigned int len = m_field->MaxElementByteLength(); - P.identity = false; - P.x.Decode(bt, len); - P.y.Decode(bt, len); - return true; - } - default: - return false; - } -} - -void EC2N::EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const -{ - if (P.identity) - NullStore().TransferTo(bt, EncodedPointSize(compressed)); - else if (compressed) - { - bt.Put(2 + (!P.x ? 0 : m_field->Divide(P.y, P.x).GetBit(0))); - P.x.Encode(bt, m_field->MaxElementByteLength()); - } - else - { - unsigned int len = m_field->MaxElementByteLength(); - bt.Put(4); // uncompressed - P.x.Encode(bt, len); - P.y.Encode(bt, len); - } -} - -void EC2N::EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const -{ - ArraySink sink(encodedPoint, EncodedPointSize(compressed)); - EncodePoint(sink, P, compressed); - assert(sink.TotalPutLength() == EncodedPointSize(compressed)); -} - -EC2N::Point EC2N::BERDecodePoint(BufferedTransformation &bt) const -{ - SecByteBlock str; - BERDecodeOctetString(bt, str); - Point P; - if (!DecodePoint(P, str, str.size())) - BERDecodeError(); - return P; -} - -void EC2N::DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const -{ - SecByteBlock str(EncodedPointSize(compressed)); - EncodePoint(str, P, compressed); - DEREncodeOctetString(bt, str); -} - -bool EC2N::ValidateParameters(RandomNumberGenerator &rng, unsigned int level) const -{ - bool pass = !!m_b; - pass = pass && m_a.CoefficientCount() <= m_field->MaxElementBitLength(); - pass = pass && m_b.CoefficientCount() <= m_field->MaxElementBitLength(); - - if (level >= 1) - pass = pass && m_field->GetModulus().IsIrreducible(); - - return pass; -} - -bool EC2N::VerifyPoint(const Point &P) const -{ - const FieldElement &x = P.x, &y = P.y; - return P.identity || - (x.CoefficientCount() <= m_field->MaxElementBitLength() - && y.CoefficientCount() <= m_field->MaxElementBitLength() - && !(((x+m_a)*x*x+m_b-(x+y)*y)%m_field->GetModulus())); -} - -bool EC2N::Equal(const Point &P, const Point &Q) const -{ - if (P.identity && Q.identity) - return true; - - if (P.identity && !Q.identity) - return false; - - if (!P.identity && Q.identity) - return false; - - return (m_field->Equal(P.x,Q.x) && m_field->Equal(P.y,Q.y)); -} - -const EC2N::Point& EC2N::Identity() const -{ - return Singleton().Ref(); -} - -const EC2N::Point& EC2N::Inverse(const Point &P) const -{ - if (P.identity) - return P; - else - { - m_R.identity = false; - m_R.y = m_field->Add(P.x, P.y); - m_R.x = P.x; - return m_R; - } -} - -const EC2N::Point& EC2N::Add(const Point &P, const Point &Q) const -{ - if (P.identity) return Q; - if (Q.identity) return P; - if (Equal(P, Q)) return Double(P); - if (m_field->Equal(P.x, Q.x) && m_field->Equal(P.y, m_field->Add(Q.x, Q.y))) return Identity(); - - FieldElement t = m_field->Add(P.y, Q.y); - t = m_field->Divide(t, m_field->Add(P.x, Q.x)); - FieldElement x = m_field->Square(t); - m_field->Accumulate(x, t); - m_field->Accumulate(x, Q.x); - m_field->Accumulate(x, m_a); - m_R.y = m_field->Add(P.y, m_field->Multiply(t, x)); - m_field->Accumulate(x, P.x); - m_field->Accumulate(m_R.y, x); - - m_R.x.swap(x); - m_R.identity = false; - return m_R; -} - -const EC2N::Point& EC2N::Double(const Point &P) const -{ - if (P.identity) return P; - if (!m_field->IsUnit(P.x)) return Identity(); - - FieldElement t = m_field->Divide(P.y, P.x); - m_field->Accumulate(t, P.x); - m_R.y = m_field->Square(P.x); - m_R.x = m_field->Square(t); - m_field->Accumulate(m_R.x, t); - m_field->Accumulate(m_R.x, m_a); - m_field->Accumulate(m_R.y, m_field->Multiply(t, m_R.x)); - m_field->Accumulate(m_R.y, m_R.x); - - m_R.identity = false; - return m_R; -} - -// ******************************************************** - -/* -EcPrecomputation& EcPrecomputation::operator=(const EcPrecomputation &rhs) -{ - m_ec = rhs.m_ec; - m_ep = rhs.m_ep; - m_ep.m_group = m_ec.get(); - return *this; -} - -void EcPrecomputation::SetCurveAndBase(const EC2N &ec, const EC2N::Point &base) -{ - m_ec.reset(new EC2N(ec)); - m_ep.SetGroupAndBase(*m_ec, base); -} - -void EcPrecomputation::Precompute(unsigned int maxExpBits, unsigned int storage) -{ - m_ep.Precompute(maxExpBits, storage); -} - -void EcPrecomputation::Load(BufferedTransformation &bt) -{ - BERSequenceDecoder seq(bt); - word32 version; - BERDecodeUnsigned(seq, version, INTEGER, 1, 1); - m_ep.m_exponentBase.BERDecode(seq); - m_ep.m_windowSize = m_ep.m_exponentBase.BitCount() - 1; - m_ep.m_bases.clear(); - while (!seq.EndReached()) - m_ep.m_bases.push_back(m_ec->BERDecodePoint(seq)); - seq.MessageEnd(); -} - -void EcPrecomputation::Save(BufferedTransformation &bt) const -{ - DERSequenceEncoder seq(bt); - DEREncodeUnsigned(seq, 1); // version - m_ep.m_exponentBase.DEREncode(seq); - for (unsigned i=0; iDEREncodePoint(seq, m_ep.m_bases[i]); - seq.MessageEnd(); -} - -EC2N::Point EcPrecomputation::Exponentiate(const Integer &exponent) const -{ - return m_ep.Exponentiate(exponent); -} - -EC2N::Point EcPrecomputation::CascadeExponentiate(const Integer &exponent, const DL_FixedBasePrecomputation &pc2, const Integer &exponent2) const -{ - return m_ep.CascadeExponentiate(exponent, static_cast &>(pc2).m_ep, exponent2); -} -*/ - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/ec2n.h b/embeddedcryptopp/ec2n.h deleted file mode 100644 index ae4007c..0000000 --- a/embeddedcryptopp/ec2n.h +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef CRYPTOPP_EC2N_H -#define CRYPTOPP_EC2N_H - -#include "gf2n.h" -#include "eprecomp.h" -#include "smartptr.h" -#include "pubkey.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! Elliptic Curve Point -struct CRYPTOPP_DLL EC2NPoint -{ - EC2NPoint() : identity(true) {} - EC2NPoint(const PolynomialMod2 &x, const PolynomialMod2 &y) - : identity(false), x(x), y(y) {} - - bool operator==(const EC2NPoint &t) const - {return (identity && t.identity) || (!identity && !t.identity && x==t.x && y==t.y);} - bool operator< (const EC2NPoint &t) const - {return identity ? !t.identity : (!t.identity && (x; - -//! Elliptic Curve over GF(2^n) -class CRYPTOPP_DLL EC2N : public AbstractGroup -{ -public: - typedef GF2NP Field; - typedef Field::Element FieldElement; - typedef EC2NPoint Point; - - EC2N() {} - EC2N(const Field &field, const Field::Element &a, const Field::Element &b) - : m_field(field), m_a(a), m_b(b) {} - // construct from BER encoded parameters - // this constructor will decode and extract the the fields fieldID and curve of the sequence ECParameters - EC2N(BufferedTransformation &bt); - - // encode the fields fieldID and curve of the sequence ECParameters - void DEREncode(BufferedTransformation &bt) const; - - bool Equal(const Point &P, const Point &Q) const; - const Point& Identity() const; - const Point& Inverse(const Point &P) const; - bool InversionIsFast() const {return true;} - const Point& Add(const Point &P, const Point &Q) const; - const Point& Double(const Point &P) const; - - Point Multiply(const Integer &k, const Point &P) const - {return ScalarMultiply(P, k);} - Point CascadeMultiply(const Integer &k1, const Point &P, const Integer &k2, const Point &Q) const - {return CascadeScalarMultiply(P, k1, Q, k2);} - - bool ValidateParameters(RandomNumberGenerator &rng, unsigned int level=3) const; - bool VerifyPoint(const Point &P) const; - - unsigned int EncodedPointSize(bool compressed = false) const - {return 1 + (compressed?1:2)*m_field->MaxElementByteLength();} - // returns false if point is compressed and not valid (doesn't check if uncompressed) - bool DecodePoint(Point &P, BufferedTransformation &bt, size_t len) const; - bool DecodePoint(Point &P, const byte *encodedPoint, size_t len) const; - void EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const; - void EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const; - - Point BERDecodePoint(BufferedTransformation &bt) const; - void DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const; - - Integer FieldSize() const {return Integer::Power2(m_field->MaxElementBitLength());} - const Field & GetField() const {return *m_field;} - const FieldElement & GetA() const {return m_a;} - const FieldElement & GetB() const {return m_b;} - - bool operator==(const EC2N &rhs) const - {return GetField() == rhs.GetField() && m_a == rhs.m_a && m_b == rhs.m_b;} - -private: - clonable_ptr m_field; - FieldElement m_a, m_b; - mutable Point m_R; -}; - -CRYPTOPP_DLL_TEMPLATE_CLASS DL_FixedBasePrecomputationImpl; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupPrecomputation; - -template class EcPrecomputation; - -//! EC2N precomputation -template<> class EcPrecomputation : public DL_GroupPrecomputation -{ -public: - typedef EC2N EllipticCurve; - - // DL_GroupPrecomputation - const AbstractGroup & GetGroup() const {return m_ec;} - Element BERDecodeElement(BufferedTransformation &bt) const {return m_ec.BERDecodePoint(bt);} - void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {m_ec.DEREncodePoint(bt, v, false);} - - // non-inherited - void SetCurve(const EC2N &ec) {m_ec = ec;} - const EC2N & GetCurve() const {return m_ec;} - -private: - EC2N m_ec; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/eccrypto.cpp b/embeddedcryptopp/eccrypto.cpp deleted file mode 100644 index fd8462f..0000000 --- a/embeddedcryptopp/eccrypto.cpp +++ /dev/null @@ -1,694 +0,0 @@ -// eccrypto.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "eccrypto.h" -#include "nbtheory.h" -#include "oids.h" -#include "hex.h" -#include "argnames.h" -#include "ec2n.h" - -NAMESPACE_BEGIN(CryptoPP) - -#if 0 -static void ECDSA_TestInstantiations() -{ - ECDSA::Signer t1; - ECDSA::Verifier t2(t1); - ECNR::Signer t3; - ECNR::Verifier t4(t3); - ECIES::Encryptor t5; - ECIES::Decryptor t6; - ECDH::Domain t7; - ECMQV::Domain t8; -} -#endif - -// VC60 workaround: complains when these functions are put into an anonymous namespace -static Integer ConvertToInteger(const PolynomialMod2 &x) -{ - unsigned int l = x.ByteCount(); - SecByteBlock temp(l); - x.Encode(temp, l); - return Integer(temp, l); -} - -static inline Integer ConvertToInteger(const Integer &x) -{ - return x; -} - -static bool CheckMOVCondition(const Integer &q, const Integer &r) -{ - // see "Updated standards for validating elliptic curves", http://eprint.iacr.org/2007/343 - Integer t = 1; - unsigned int n = q.IsEven() ? 1 : q.BitCount(), m = r.BitCount(); - - for (unsigned int i=n; DiscreteLogWorkFactor(i) struct EcRecommendedParameters; - -template<> struct EcRecommendedParameters -{ - EcRecommendedParameters(const OID &oid, unsigned int t2, unsigned int t3, unsigned int t4, const char *a, const char *b, const char *g, const char *n, unsigned int h) - : oid(oid), t0(0), t1(0), t2(t2), t3(t3), t4(t4), a(a), b(b), g(g), n(n), h(h) {} - EcRecommendedParameters(const OID &oid, unsigned int t0, unsigned int t1, unsigned int t2, unsigned int t3, unsigned int t4, const char *a, const char *b, const char *g, const char *n, unsigned int h) - : oid(oid), t0(t0), t1(t1), t2(t2), t3(t3), t4(t4), a(a), b(b), g(g), n(n), h(h) {} - EC2N *NewEC() const - { - StringSource ssA(a, true, new HexDecoder); - StringSource ssB(b, true, new HexDecoder); - if (t0 == 0) - return new EC2N(GF2NT(t2, t3, t4), EC2N::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), EC2N::FieldElement(ssB, (size_t)ssB.MaxRetrievable())); - else - return new EC2N(GF2NPP(t0, t1, t2, t3, t4), EC2N::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), EC2N::FieldElement(ssB, (size_t)ssB.MaxRetrievable())); - }; - - OID oid; - unsigned int t0, t1, t2, t3, t4; - const char *a, *b, *g, *n; - unsigned int h; -}; - -template<> struct EcRecommendedParameters -{ - EcRecommendedParameters(const OID &oid, const char *p, const char *a, const char *b, const char *g, const char *n, unsigned int h) - : oid(oid), p(p), a(a), b(b), g(g), n(n), h(h) {} - ECP *NewEC() const - { - StringSource ssP(p, true, new HexDecoder); - StringSource ssA(a, true, new HexDecoder); - StringSource ssB(b, true, new HexDecoder); - return new ECP(Integer(ssP, (size_t)ssP.MaxRetrievable()), ECP::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), ECP::FieldElement(ssB, (size_t)ssB.MaxRetrievable())); - }; - - OID oid; - const char *p; - const char *a, *b, *g, *n; - unsigned int h; -}; - -struct OIDLessThan -{ - template - inline bool operator()(const EcRecommendedParameters& a, const OID& b) {return a.oid < b;} - template - inline bool operator()(const OID& a, const EcRecommendedParameters& b) {return a < b.oid;} - template - inline bool operator()(const EcRecommendedParameters& a, const EcRecommendedParameters& b) {return a.oid < b.oid;} -}; - -static void GetRecommendedParameters(const EcRecommendedParameters *&begin, const EcRecommendedParameters *&end) -{ - // this array must be sorted by OID - static const EcRecommendedParameters rec[] = { - EcRecommendedParameters(ASN1::sect163k1(), - 163, 7, 6, 3, 0, - "000000000000000000000000000000000000000001", - "000000000000000000000000000000000000000001", - "0402FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE80289070FB05D38FF58321F2E800536D538CCDAA3D9", - "04000000000000000000020108A2E0CC0D99F8A5EF", - 2), - EcRecommendedParameters(ASN1::sect163r1(), - 163, 7, 6, 3, 0, - "07B6882CAAEFA84F9554FF8428BD88E246D2782AE2", - "0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9", - "040369979697AB43897789566789567F787A7876A65400435EDB42EFAFB2989D51FEFCE3C80988F41FF883", - "03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B", - 2), - EcRecommendedParameters(ASN1::sect239k1(), - 239, 158, 0, - "000000000000000000000000000000000000000000000000000000000000", - "000000000000000000000000000000000000000000000000000000000001", - "0429A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA", - "2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5", - 4), - EcRecommendedParameters(ASN1::sect113r1(), - 113, 9, 0, - "003088250CA6E7C7FE649CE85820F7", - "00E8BEE4D3E2260744188BE0E9C723", - "04009D73616F35F4AB1407D73562C10F00A52830277958EE84D1315ED31886", - "0100000000000000D9CCEC8A39E56F", - 2), - EcRecommendedParameters(ASN1::sect113r2(), - 113, 9, 0, - "00689918DBEC7E5A0DD6DFC0AA55C7", - "0095E9A9EC9B297BD4BF36E059184F", - "0401A57A6A7B26CA5EF52FCDB816479700B3ADC94ED1FE674C06E695BABA1D", - "010000000000000108789B2496AF93", - 2), - EcRecommendedParameters(ASN1::sect163r2(), - 163, 7, 6, 3, 0, - "000000000000000000000000000000000000000001", - "020A601907B8C953CA1481EB10512F78744A3205FD", - "0403F0EBA16286A2D57EA0991168D4994637E8343E3600D51FBC6C71A0094FA2CDD545B11C5C0C797324F1", - "040000000000000000000292FE77E70C12A4234C33", - 2), - EcRecommendedParameters(ASN1::sect283k1(), - 283, 12, 7, 5, 0, - "000000000000000000000000000000000000000000000000000000000000000000000000", - "000000000000000000000000000000000000000000000000000000000000000000000001", - "040503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC245849283601CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259", - "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61", - 4), - EcRecommendedParameters(ASN1::sect283r1(), - 283, 12, 7, 5, 0, - "000000000000000000000000000000000000000000000000000000000000000000000001", - "027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5", - "0405F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B1205303676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4", - "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307", - 2), - EcRecommendedParameters(ASN1::sect131r1(), - 131, 8, 3, 2, 0, - "07A11B09A76B562144418FF3FF8C2570B8", - "0217C05610884B63B9C6C7291678F9D341", - "040081BAF91FDF9833C40F9C181343638399078C6E7EA38C001F73C8134B1B4EF9E150", - "0400000000000000023123953A9464B54D", - 2), - EcRecommendedParameters(ASN1::sect131r2(), - 131, 8, 3, 2, 0, - "03E5A88919D7CAFCBF415F07C2176573B2", - "04B8266A46C55657AC734CE38F018F2192", - "040356DCD8F2F95031AD652D23951BB366A80648F06D867940A5366D9E265DE9EB240F", - "0400000000000000016954A233049BA98F", - 2), - EcRecommendedParameters(ASN1::sect193r1(), - 193, 15, 0, - "0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01", - "00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814", - "0401F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E10025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05", - "01000000000000000000000000C7F34A778F443ACC920EBA49", - 2), - EcRecommendedParameters(ASN1::sect193r2(), - 193, 15, 0, - "0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B", - "00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE", - "0400D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C", - "010000000000000000000000015AAB561B005413CCD4EE99D5", - 2), - EcRecommendedParameters(ASN1::sect233k1(), - 233, 74, 0, - "000000000000000000000000000000000000000000000000000000000000", - "000000000000000000000000000000000000000000000000000000000001", - "04017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD612601DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3", - "8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF", - 4), - EcRecommendedParameters(ASN1::sect233r1(), - 233, 74, 0, - "000000000000000000000000000000000000000000000000000000000001", - "0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD", - "0400FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052", - "01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", - 2), - EcRecommendedParameters(ASN1::sect409k1(), - 409, 87, 0, - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", - "040060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE902374601E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B", - "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF", - 4), - EcRecommendedParameters(ASN1::sect409r1(), - 409, 87, 0, - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", - "0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F", - "04015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A70061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706", - "010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173", - 2), - EcRecommendedParameters(ASN1::sect571k1(), - 571, 10, 5, 2, 0, - "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", - "04026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C89720349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3", - "020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001", - 4), - EcRecommendedParameters(ASN1::sect571r1(), - 571, 10, 5, 2, 0, - "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", - "02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A", - "040303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B", - "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47", - 2), - }; - begin = rec; - end = rec + sizeof(rec)/sizeof(rec[0]); -} - -static void GetRecommendedParameters(const EcRecommendedParameters *&begin, const EcRecommendedParameters *&end) -{ - // this array must be sorted by OID - static const EcRecommendedParameters rec[] = { - EcRecommendedParameters(ASN1::secp192r1(), - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", - "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", - "04188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF101207192B95FFC8DA78631011ED6B24CDD573F977A11E794811", - "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", - 1), - EcRecommendedParameters(ASN1::secp256r1(), - "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", - "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", - "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", - "046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", - "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", - 1), - EcRecommendedParameters(ASN1::brainpoolP160r1(), - "E95E4A5F737059DC60DFC7AD95B3D8139515620F", - "340E7BE2A280EB74E2BE61BADA745D97E8F7C300", - "1E589A8595423412134FAA2DBDEC95C8D8675E58", - "04BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC31667CB477A1A8EC338F94741669C976316DA6321", - "E95E4A5F737059DC60DF5991D45029409E60FC09", - 1), - EcRecommendedParameters(ASN1::brainpoolP192r1(), - "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", - "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", - "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", - "04C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD614B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F", - "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", - 1), - EcRecommendedParameters(ASN1::brainpoolP224r1(), - "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", - "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", - "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", - "040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD", - "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", - 1), - EcRecommendedParameters(ASN1::brainpoolP256r1(), - "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", - "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", - "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", - "048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", - "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", - 1), - EcRecommendedParameters(ASN1::brainpoolP320r1(), - "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", - "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", - "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", - "0443BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E2061114FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1", - "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", - 1), - EcRecommendedParameters(ASN1::brainpoolP384r1(), - "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", - "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", - "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", - "041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", - "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", - 1), - EcRecommendedParameters(ASN1::brainpoolP512r1(), - "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", - "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", - "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", - "0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", - "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", - 1), - EcRecommendedParameters(ASN1::secp112r1(), - "DB7C2ABF62E35E668076BEAD208B", - "DB7C2ABF62E35E668076BEAD2088", - "659EF8BA043916EEDE8911702B22", - "0409487239995A5EE76B55F9C2F098A89CE5AF8724C0A23E0E0FF77500", - "DB7C2ABF62E35E7628DFAC6561C5", - 1), - EcRecommendedParameters(ASN1::secp112r2(), - "DB7C2ABF62E35E668076BEAD208B", - "6127C24C05F38A0AAAF65C0EF02C", - "51DEF1815DB5ED74FCC34C85D709", - "044BA30AB5E892B4E1649DD0928643ADCD46F5882E3747DEF36E956E97", - "36DF0AAFD8B8D7597CA10520D04B", - 4), - EcRecommendedParameters(ASN1::secp160r1(), - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", - "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", - "044A96B5688EF573284664698968C38BB913CBFC8223A628553168947D59DCC912042351377AC5FB32", - "0100000000000000000001F4C8F927AED3CA752257", - 1), - EcRecommendedParameters(ASN1::secp160k1(), - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", - "0000000000000000000000000000000000000000", - "0000000000000000000000000000000000000007", - "043B4C382CE37AA192A4019E763036F4F5DD4D7EBB938CF935318FDCED6BC28286531733C3F03C4FEE", - "0100000000000000000001B8FA16DFAB9ACA16B6B3", - 1), - EcRecommendedParameters(ASN1::secp256k1(), - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", - "0000000000000000000000000000000000000000000000000000000000000000", - "0000000000000000000000000000000000000000000000000000000000000007", - "0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", - 1), - EcRecommendedParameters(ASN1::secp128r1(), - "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", - "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", - "E87579C11079F43DD824993C2CEE5ED3", - "04161FF7528B899B2D0C28607CA52C5B86CF5AC8395BAFEB13C02DA292DDED7A83", - "FFFFFFFE0000000075A30D1B9038A115", - 1), - EcRecommendedParameters(ASN1::secp128r2(), - "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", - "D6031998D1B3BBFEBF59CC9BBFF9AEE1", - "5EEEFCA380D02919DC2C6558BB6D8A5D", - "047B6AA5D85E572983E6FB32A7CDEBC14027B6916A894D3AEE7106FE805FC34B44", - "3FFFFFFF7FFFFFFFBE0024720613B5A3", - 4), - EcRecommendedParameters(ASN1::secp160r2(), - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70", - "B4E134D3FB59EB8BAB57274904664D5AF50388BA", - "0452DCB034293A117E1F4FF11B30F7199D3144CE6DFEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E", - "0100000000000000000000351EE786A818F3A1A16B", - 1), - EcRecommendedParameters(ASN1::secp192k1(), - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", - "000000000000000000000000000000000000000000000000", - "000000000000000000000000000000000000000000000003", - "04DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", - "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", - 1), - EcRecommendedParameters(ASN1::secp224k1(), - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", - "00000000000000000000000000000000000000000000000000000000", - "00000000000000000000000000000000000000000000000000000005", - "04A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", - "010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", - 1), - EcRecommendedParameters(ASN1::secp224r1(), - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", - "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", - "04B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", - 1), - EcRecommendedParameters(ASN1::secp384r1(), - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", - "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", - "04AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB73617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", - 1), - EcRecommendedParameters(ASN1::secp521r1(), - "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", - "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", - "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", - "0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", - "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", - 1), - }; - begin = rec; - end = rec + sizeof(rec)/sizeof(rec[0]); -} - -template OID DL_GroupParameters_EC::GetNextRecommendedParametersOID(const OID &oid) -{ - const EcRecommendedParameters *begin, *end; - GetRecommendedParameters(begin, end); - const EcRecommendedParameters *it = std::upper_bound(begin, end, oid, OIDLessThan()); - return (it == end ? OID() : it->oid); -} - -template void DL_GroupParameters_EC::Initialize(const OID &oid) -{ - const EcRecommendedParameters *begin, *end; - GetRecommendedParameters(begin, end); - const EcRecommendedParameters *it = std::lower_bound(begin, end, oid, OIDLessThan()); - if (it == end || it->oid != oid) - throw UnknownOID(); - - const EcRecommendedParameters ¶m = *it; - m_oid = oid; - std::auto_ptr ec(param.NewEC()); - this->m_groupPrecomputation.SetCurve(*ec); - - StringSource ssG(param.g, true, new HexDecoder); - Element G; - bool result = GetCurve().DecodePoint(G, ssG, (size_t)ssG.MaxRetrievable()); - SetSubgroupGenerator(G); - assert(result); - - StringSource ssN(param.n, true, new HexDecoder); - m_n.Decode(ssN, (size_t)ssN.MaxRetrievable()); - m_k = param.h; -} - -template -bool DL_GroupParameters_EC::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const -{ - if (strcmp(name, Name::GroupOID()) == 0) - { - if (m_oid.m_values.empty()) - return false; - - this->ThrowIfTypeMismatch(name, typeid(OID), valueType); - *reinterpret_cast(pValue) = m_oid; - return true; - } - else - return GetValueHelper >(this, name, valueType, pValue).Assignable() - CRYPTOPP_GET_FUNCTION_ENTRY(Curve); -} - -template -void DL_GroupParameters_EC::AssignFrom(const NameValuePairs &source) -{ - OID oid; - if (source.GetValue(Name::GroupOID(), oid)) - Initialize(oid); - else - { - EllipticCurve ec; - Point G; - Integer n; - - source.GetRequiredParameter("DL_GroupParameters_EC", Name::Curve(), ec); - source.GetRequiredParameter("DL_GroupParameters_EC", Name::SubgroupGenerator(), G); - source.GetRequiredParameter("DL_GroupParameters_EC", Name::SubgroupOrder(), n); - Integer k = source.GetValueWithDefault(Name::Cofactor(), Integer::Zero()); - - Initialize(ec, G, n, k); - } -} - -template -void DL_GroupParameters_EC::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg) -{ - try - { - AssignFrom(alg); - } - catch (InvalidArgument &) - { - throw NotImplemented("DL_GroupParameters_EC: curve generation is not implemented yet"); - } -} - -template -void DL_GroupParameters_EC::BERDecode(BufferedTransformation &bt) -{ - byte b; - if (!bt.Peek(b)) - BERDecodeError(); - if (b == OBJECT_IDENTIFIER) - Initialize(OID(bt)); - else - { - BERSequenceDecoder seq(bt); - word32 version; - BERDecodeUnsigned(seq, version, INTEGER, 1, 1); // check version - EllipticCurve ec(seq); - Point G = ec.BERDecodePoint(seq); - Integer n(seq); - Integer k; - bool cofactorPresent = !seq.EndReached(); - if (cofactorPresent) - k.BERDecode(seq); - else - k = Integer::Zero(); - seq.MessageEnd(); - - Initialize(ec, G, n, k); - } -} - -template -void DL_GroupParameters_EC::DEREncode(BufferedTransformation &bt) const -{ - if (m_encodeAsOID && !m_oid.m_values.empty()) - m_oid.DEREncode(bt); - else - { - DERSequenceEncoder seq(bt); - DEREncodeUnsigned(seq, 1); // version - GetCurve().DEREncode(seq); - GetCurve().DEREncodePoint(seq, this->GetSubgroupGenerator(), m_compress); - m_n.DEREncode(seq); - if (m_k.NotZero()) - m_k.DEREncode(seq); - seq.MessageEnd(); - } -} - -template -Integer DL_GroupParameters_EC::GetCofactor() const -{ - if (!m_k) - { - Integer q = GetCurve().FieldSize(); - Integer qSqrt = q.SquareRoot(); - m_k = (q+2*qSqrt+1)/m_n; - } - - return m_k; -} - -template -Integer DL_GroupParameters_EC::ConvertElementToInteger(const Element &element) const -{ - return ConvertToInteger(element.x); -}; - -template -bool DL_GroupParameters_EC::ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const -{ - bool pass = GetCurve().ValidateParameters(rng, level); - - Integer q = GetCurve().FieldSize(); - pass = pass && m_n!=q; - - if (level >= 2) - { - Integer qSqrt = q.SquareRoot(); - pass = pass && m_n>4*qSqrt; - pass = pass && VerifyPrime(rng, m_n, level-2); - pass = pass && (m_k.IsZero() || m_k == (q+2*qSqrt+1)/m_n); - pass = pass && CheckMOVCondition(q, m_n); - } - - return pass; -} - -template -bool DL_GroupParameters_EC::ValidateElement(unsigned int level, const Element &g, const DL_FixedBasePrecomputation *gpc) const -{ - bool pass = !IsIdentity(g) && GetCurve().VerifyPoint(g); - if (level >= 1) - { - if (gpc) - pass = pass && gpc->Exponentiate(this->GetGroupPrecomputation(), Integer::One()) == g; - } - if (level >= 2 && pass) - { - const Integer &q = GetSubgroupOrder(); - Element gq = gpc ? gpc->Exponentiate(this->GetGroupPrecomputation(), q) : ExponentiateElement(g, q); - pass = pass && IsIdentity(gq); - } - return pass; -} - -template -void DL_GroupParameters_EC::SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const -{ - GetCurve().SimultaneousMultiply(results, base, exponents, exponentsCount); -} - -template -CPP_TYPENAME DL_GroupParameters_EC::Element DL_GroupParameters_EC::MultiplyElements(const Element &a, const Element &b) const -{ - return GetCurve().Add(a, b); -} - -template -CPP_TYPENAME DL_GroupParameters_EC::Element DL_GroupParameters_EC::CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const -{ - return GetCurve().CascadeMultiply(exponent1, element1, exponent2, element2); -} - -template -OID DL_GroupParameters_EC::GetAlgorithmID() const -{ - return ASN1::id_ecPublicKey(); -} - -// ****************************************************************** - -template -void DL_PublicKey_EC::BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size) -{ - typename EC::Point P; - if (!this->GetGroupParameters().GetCurve().DecodePoint(P, bt, size)) - BERDecodeError(); - SetPublicElement(P); -} - -template -void DL_PublicKey_EC::DEREncodePublicKey(BufferedTransformation &bt) const -{ - this->GetGroupParameters().GetCurve().EncodePoint(bt, this->GetPublicElement(), this->GetGroupParameters().GetPointCompression()); -} - -// ****************************************************************** - -template -void DL_PrivateKey_EC::BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size) -{ - BERSequenceDecoder seq(bt); - word32 version; - BERDecodeUnsigned(seq, version, INTEGER, 1, 1); // check version - - BERGeneralDecoder dec(seq, OCTET_STRING); - if (!dec.IsDefiniteLength()) - BERDecodeError(); - Integer x; - x.Decode(dec, (size_t)dec.RemainingLength()); - dec.MessageEnd(); - if (!parametersPresent && seq.PeekByte() != (CONTEXT_SPECIFIC | CONSTRUCTED | 0)) - BERDecodeError(); - if (!seq.EndReached() && seq.PeekByte() == (CONTEXT_SPECIFIC | CONSTRUCTED | 0)) - { - BERGeneralDecoder parameters(seq, CONTEXT_SPECIFIC | CONSTRUCTED | 0); - this->AccessGroupParameters().BERDecode(parameters); - parameters.MessageEnd(); - } - if (!seq.EndReached()) - { - // skip over the public element - SecByteBlock subjectPublicKey; - unsigned int unusedBits; - BERGeneralDecoder publicKey(seq, CONTEXT_SPECIFIC | CONSTRUCTED | 1); - BERDecodeBitString(publicKey, subjectPublicKey, unusedBits); - publicKey.MessageEnd(); - Element Q; - if (!(unusedBits == 0 && this->GetGroupParameters().GetCurve().DecodePoint(Q, subjectPublicKey, subjectPublicKey.size()))) - BERDecodeError(); - } - seq.MessageEnd(); - - this->SetPrivateExponent(x); -} - -template -void DL_PrivateKey_EC::DEREncodePrivateKey(BufferedTransformation &bt) const -{ - DERSequenceEncoder privateKey(bt); - DEREncodeUnsigned(privateKey, 1); // version - // SEC 1 ver 1.0 says privateKey (m_d) has the same length as order of the curve - // this will be changed to order of base point in a future version - this->GetPrivateExponent().DEREncodeAsOctetString(privateKey, this->GetGroupParameters().GetSubgroupOrder().ByteCount()); - privateKey.MessageEnd(); -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/eccrypto.h b/embeddedcryptopp/eccrypto.h deleted file mode 100644 index 8d95780..0000000 --- a/embeddedcryptopp/eccrypto.h +++ /dev/null @@ -1,280 +0,0 @@ -#ifndef CRYPTOPP_ECCRYPTO_H -#define CRYPTOPP_ECCRYPTO_H - -/*! \file -*/ - -#include "pubkey.h" -#include "integer.h" -#include "asn.h" -#include "hmac.h" -#include "sha.h" -#include "gfpcrypt.h" -#include "dh.h" -#include "mqv.h" -#include "ecp.h" -#include "ec2n.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! Elliptic Curve Parameters -/*! This class corresponds to the ASN.1 sequence of the same name - in ANSI X9.62 (also SEC 1). -*/ -template -class DL_GroupParameters_EC : public DL_GroupParametersImpl > -{ - typedef DL_GroupParameters_EC ThisClass; - -public: - typedef EC EllipticCurve; - typedef typename EllipticCurve::Point Point; - typedef Point Element; - typedef IncompatibleCofactorMultiplication DefaultCofactorOption; - - DL_GroupParameters_EC() : m_compress(false), m_encodeAsOID(false) {} - DL_GroupParameters_EC(const OID &oid) - : m_compress(false), m_encodeAsOID(false) {Initialize(oid);} - DL_GroupParameters_EC(const EllipticCurve &ec, const Point &G, const Integer &n, const Integer &k = Integer::Zero()) - : m_compress(false), m_encodeAsOID(false) {Initialize(ec, G, n, k);} - DL_GroupParameters_EC(BufferedTransformation &bt) - : m_compress(false), m_encodeAsOID(false) {BERDecode(bt);} - - void Initialize(const EllipticCurve &ec, const Point &G, const Integer &n, const Integer &k = Integer::Zero()) - { - this->m_groupPrecomputation.SetCurve(ec); - SetSubgroupGenerator(G); - m_n = n; - m_k = k; - } - void Initialize(const OID &oid); - - // NameValuePairs - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; - void AssignFrom(const NameValuePairs &source); - - // GeneratibleCryptoMaterial interface - //! this implementation doesn't actually generate a curve, it just initializes the parameters with existing values - /*! parameters: (Curve, SubgroupGenerator, SubgroupOrder, Cofactor (optional)), or (GroupOID) */ - void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg); - - // DL_GroupParameters - const DL_FixedBasePrecomputation & GetBasePrecomputation() const {return this->m_gpc;} - DL_FixedBasePrecomputation & AccessBasePrecomputation() {return this->m_gpc;} - const Integer & GetSubgroupOrder() const {return m_n;} - Integer GetCofactor() const; - bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const; - bool ValidateElement(unsigned int level, const Element &element, const DL_FixedBasePrecomputation *precomp) const; - bool FastSubgroupCheckAvailable() const {return false;} - void EncodeElement(bool reversible, const Element &element, byte *encoded) const - { - if (reversible) - GetCurve().EncodePoint(encoded, element, m_compress); - else - element.x.Encode(encoded, GetEncodedElementSize(false)); - } - unsigned int GetEncodedElementSize(bool reversible) const - { - if (reversible) - return GetCurve().EncodedPointSize(m_compress); - else - return GetCurve().GetField().MaxElementByteLength(); - } - Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const - { - Point result; - if (!GetCurve().DecodePoint(result, encoded, GetEncodedElementSize(true))) - throw DL_BadElement(); - if (checkForGroupMembership && !ValidateElement(1, result, NULL)) - throw DL_BadElement(); - return result; - } - Integer ConvertElementToInteger(const Element &element) const; - Integer GetMaxExponent() const {return GetSubgroupOrder()-1;} - bool IsIdentity(const Element &element) const {return element.identity;} - void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const; - static std::string CRYPTOPP_API StaticAlgorithmNamePrefix() {return "EC";} - - // ASN1Key - OID GetAlgorithmID() const; - - // used by MQV - Element MultiplyElements(const Element &a, const Element &b) const; - Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const; - - // non-inherited - - // enumerate OIDs for recommended parameters, use OID() to get first one - static OID CRYPTOPP_API GetNextRecommendedParametersOID(const OID &oid); - - void BERDecode(BufferedTransformation &bt); - void DEREncode(BufferedTransformation &bt) const; - - void SetPointCompression(bool compress) {m_compress = compress;} - bool GetPointCompression() const {return m_compress;} - - void SetEncodeAsOID(bool encodeAsOID) {m_encodeAsOID = encodeAsOID;} - bool GetEncodeAsOID() const {return m_encodeAsOID;} - - const EllipticCurve& GetCurve() const {return this->m_groupPrecomputation.GetCurve();} - - bool operator==(const ThisClass &rhs) const - {return this->m_groupPrecomputation.GetCurve() == rhs.m_groupPrecomputation.GetCurve() && this->m_gpc.GetBase(this->m_groupPrecomputation) == rhs.m_gpc.GetBase(rhs.m_groupPrecomputation);} - -#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY - const Point& GetBasePoint() const {return GetSubgroupGenerator();} - const Integer& GetBasePointOrder() const {return GetSubgroupOrder();} - void LoadRecommendedParameters(const OID &oid) {Initialize(oid);} -#endif - -protected: - unsigned int FieldElementLength() const {return GetCurve().GetField().MaxElementByteLength();} - unsigned int ExponentLength() const {return m_n.ByteCount();} - - OID m_oid; // set if parameters loaded from a recommended curve - Integer m_n; // order of base point - bool m_compress, m_encodeAsOID; - mutable Integer m_k; // cofactor -}; - -//! EC public key -template -class DL_PublicKey_EC : public DL_PublicKeyImpl > -{ -public: - typedef typename EC::Point Element; - - void Initialize(const DL_GroupParameters_EC ¶ms, const Element &Q) - {this->AccessGroupParameters() = params; SetPublicElement(Q);} - void Initialize(const EC &ec, const Element &G, const Integer &n, const Element &Q) - {this->AccessGroupParameters().Initialize(ec, G, n); SetPublicElement(Q);} - - // X509PublicKey - void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size); - void DEREncodePublicKey(BufferedTransformation &bt) const; -}; - -//! EC private key -template -class DL_PrivateKey_EC : public DL_PrivateKeyImpl > -{ -public: - typedef typename EC::Point Element; - - void Initialize(const DL_GroupParameters_EC ¶ms, const Integer &x) - {this->AccessGroupParameters() = params; this->SetPrivateExponent(x);} - void Initialize(const EC &ec, const Element &G, const Integer &n, const Integer &x) - {this->AccessGroupParameters().Initialize(ec, G, n); this->SetPrivateExponent(x);} - void Initialize(RandomNumberGenerator &rng, const DL_GroupParameters_EC ¶ms) - {GenerateRandom(rng, params);} - void Initialize(RandomNumberGenerator &rng, const EC &ec, const Element &G, const Integer &n) - {GenerateRandom(rng, DL_GroupParameters_EC(ec, G, n));} - - // PKCS8PrivateKey - void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size); - void DEREncodePrivateKey(BufferedTransformation &bt) const; -}; - -//! Elliptic Curve Diffie-Hellman, AKA ECDH -template ::DefaultCofactorOption> -struct ECDH -{ - typedef DH_Domain, COFACTOR_OPTION> Domain; -}; - -/// Elliptic Curve Menezes-Qu-Vanstone, AKA ECMQV -template ::DefaultCofactorOption> -struct ECMQV -{ - typedef MQV_Domain, COFACTOR_OPTION> Domain; -}; - -//! EC keys -template -struct DL_Keys_EC -{ - typedef DL_PublicKey_EC PublicKey; - typedef DL_PrivateKey_EC PrivateKey; -}; - -template -struct ECDSA; - -//! ECDSA keys -template -struct DL_Keys_ECDSA -{ - typedef DL_PublicKey_EC PublicKey; - typedef DL_PrivateKey_WithSignaturePairwiseConsistencyTest, ECDSA > PrivateKey; -}; - -//! ECDSA algorithm -template -class DL_Algorithm_ECDSA : public DL_Algorithm_GDSA -{ -public: - static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECDSA";} -}; - -//! ECNR algorithm -template -class DL_Algorithm_ECNR : public DL_Algorithm_NR -{ -public: - static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECNR";} -}; - -//! ECDSA -template -struct ECDSA : public DL_SS, DL_Algorithm_ECDSA, DL_SignatureMessageEncodingMethod_DSA, H> -{ -}; - -//! ECNR -template -struct ECNR : public DL_SS, DL_Algorithm_ECNR, DL_SignatureMessageEncodingMethod_NR, H> -{ -}; - -//! Elliptic Curve Integrated Encryption Scheme, AKA ECIES -/*! Default to (NoCofactorMultiplication and DHAES_MODE = false) for compatibilty with SEC1 and Crypto++ 4.2. - The combination of (IncompatibleCofactorMultiplication and DHAES_MODE = true) is recommended for best - efficiency and security. */ -template -struct ECIES - : public DL_ES< - DL_Keys_EC, - DL_KeyAgreementAlgorithm_DH, - DL_KeyDerivationAlgorithm_P1363 >, - DL_EncryptionAlgorithm_Xor, DHAES_MODE>, - ECIES > -{ - static std::string CRYPTOPP_API StaticAlgorithmName() {return "ECIES";} // TODO: fix this after name is standardized -}; - -NAMESPACE_END - -#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES -#include "eccrypto.cpp" -#endif - -NAMESPACE_BEGIN(CryptoPP) - -CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl >; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl >; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl >; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl >; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest, ECDSA >; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest, ECDSA >; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/ecp.cpp b/embeddedcryptopp/ecp.cpp deleted file mode 100644 index 55a7cc1..0000000 --- a/embeddedcryptopp/ecp.cpp +++ /dev/null @@ -1,473 +0,0 @@ -// ecp.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "ecp.h" -#include "asn.h" -#include "nbtheory.h" - -#include "algebra.cpp" - -NAMESPACE_BEGIN(CryptoPP) - -ANONYMOUS_NAMESPACE_BEGIN -static inline ECP::Point ToMontgomery(const ModularArithmetic &mr, const ECP::Point &P) -{ - return P.identity ? P : ECP::Point(mr.ConvertIn(P.x), mr.ConvertIn(P.y)); -} - -static inline ECP::Point FromMontgomery(const ModularArithmetic &mr, const ECP::Point &P) -{ - return P.identity ? P : ECP::Point(mr.ConvertOut(P.x), mr.ConvertOut(P.y)); -} -NAMESPACE_END - -ECP::ECP(const ECP &ecp, bool convertToMontgomeryRepresentation) -{ - if (convertToMontgomeryRepresentation && !ecp.GetField().IsMontgomeryRepresentation()) - { - m_fieldPtr.reset(new MontgomeryRepresentation(ecp.GetField().GetModulus())); - m_a = GetField().ConvertIn(ecp.m_a); - m_b = GetField().ConvertIn(ecp.m_b); - } - else - operator=(ecp); -} - -ECP::ECP(BufferedTransformation &bt) - : m_fieldPtr(new Field(bt)) -{ - BERSequenceDecoder seq(bt); - GetField().BERDecodeElement(seq, m_a); - GetField().BERDecodeElement(seq, m_b); - // skip optional seed - if (!seq.EndReached()) - { - SecByteBlock seed; - unsigned int unused; - BERDecodeBitString(seq, seed, unused); - } - seq.MessageEnd(); -} - -void ECP::DEREncode(BufferedTransformation &bt) const -{ - GetField().DEREncode(bt); - DERSequenceEncoder seq(bt); - GetField().DEREncodeElement(seq, m_a); - GetField().DEREncodeElement(seq, m_b); - seq.MessageEnd(); -} - -bool ECP::DecodePoint(ECP::Point &P, const byte *encodedPoint, size_t encodedPointLen) const -{ - StringStore store(encodedPoint, encodedPointLen); - return DecodePoint(P, store, encodedPointLen); -} - -bool ECP::DecodePoint(ECP::Point &P, BufferedTransformation &bt, size_t encodedPointLen) const -{ - byte type; - if (encodedPointLen < 1 || !bt.Get(type)) - return false; - - switch (type) - { - case 0: - P.identity = true; - return true; - case 2: - case 3: - { - if (encodedPointLen != EncodedPointSize(true)) - return false; - - Integer p = FieldSize(); - - P.identity = false; - P.x.Decode(bt, GetField().MaxElementByteLength()); - P.y = ((P.x*P.x+m_a)*P.x+m_b) % p; - - if (Jacobi(P.y, p) !=1) - return false; - - P.y = ModularSquareRoot(P.y, p); - - if ((type & 1) != P.y.GetBit(0)) - P.y = p-P.y; - - return true; - } - case 4: - { - if (encodedPointLen != EncodedPointSize(false)) - return false; - - unsigned int len = GetField().MaxElementByteLength(); - P.identity = false; - P.x.Decode(bt, len); - P.y.Decode(bt, len); - return true; - } - default: - return false; - } -} - -void ECP::EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const -{ - if (P.identity) - NullStore().TransferTo(bt, EncodedPointSize(compressed)); - else if (compressed) - { - bt.Put(2 + P.y.GetBit(0)); - P.x.Encode(bt, GetField().MaxElementByteLength()); - } - else - { - unsigned int len = GetField().MaxElementByteLength(); - bt.Put(4); // uncompressed - P.x.Encode(bt, len); - P.y.Encode(bt, len); - } -} - -void ECP::EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const -{ - ArraySink sink(encodedPoint, EncodedPointSize(compressed)); - EncodePoint(sink, P, compressed); - assert(sink.TotalPutLength() == EncodedPointSize(compressed)); -} - -ECP::Point ECP::BERDecodePoint(BufferedTransformation &bt) const -{ - SecByteBlock str; - BERDecodeOctetString(bt, str); - Point P; - if (!DecodePoint(P, str, str.size())) - BERDecodeError(); - return P; -} - -void ECP::DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const -{ - SecByteBlock str(EncodedPointSize(compressed)); - EncodePoint(str, P, compressed); - DEREncodeOctetString(bt, str); -} - -bool ECP::ValidateParameters(RandomNumberGenerator &rng, unsigned int level) const -{ - Integer p = FieldSize(); - - bool pass = p.IsOdd(); - pass = pass && !m_a.IsNegative() && m_a

= 1) - pass = pass && ((4*m_a*m_a*m_a+27*m_b*m_b)%p).IsPositive(); - - if (level >= 2) - pass = pass && VerifyPrime(rng, p); - - return pass; -} - -bool ECP::VerifyPoint(const Point &P) const -{ - const FieldElement &x = P.x, &y = P.y; - Integer p = FieldSize(); - return P.identity || - (!x.IsNegative() && x

().Ref(); -} - -const ECP::Point& ECP::Inverse(const Point &P) const -{ - if (P.identity) - return P; - else - { - m_R.identity = false; - m_R.x = P.x; - m_R.y = GetField().Inverse(P.y); - return m_R; - } -} - -const ECP::Point& ECP::Add(const Point &P, const Point &Q) const -{ - if (P.identity) return Q; - if (Q.identity) return P; - if (GetField().Equal(P.x, Q.x)) - return GetField().Equal(P.y, Q.y) ? Double(P) : Identity(); - - FieldElement t = GetField().Subtract(Q.y, P.y); - t = GetField().Divide(t, GetField().Subtract(Q.x, P.x)); - FieldElement x = GetField().Subtract(GetField().Subtract(GetField().Square(t), P.x), Q.x); - m_R.y = GetField().Subtract(GetField().Multiply(t, GetField().Subtract(P.x, x)), P.y); - - m_R.x.swap(x); - m_R.identity = false; - return m_R; -} - -const ECP::Point& ECP::Double(const Point &P) const -{ - if (P.identity || P.y==GetField().Identity()) return Identity(); - - FieldElement t = GetField().Square(P.x); - t = GetField().Add(GetField().Add(GetField().Double(t), t), m_a); - t = GetField().Divide(t, GetField().Double(P.y)); - FieldElement x = GetField().Subtract(GetField().Subtract(GetField().Square(t), P.x), P.x); - m_R.y = GetField().Subtract(GetField().Multiply(t, GetField().Subtract(P.x, x)), P.y); - - m_R.x.swap(x); - m_R.identity = false; - return m_R; -} - -template void ParallelInvert(const AbstractRing &ring, Iterator begin, Iterator end) -{ - size_t n = end-begin; - if (n == 1) - *begin = ring.MultiplicativeInverse(*begin); - else if (n > 1) - { - std::vector vec((n+1)/2); - unsigned int i; - Iterator it; - - for (i=0, it=begin; i::iterator it) : it(it) {} - Integer& operator*() {return it->z;} - int operator-(ZIterator it2) {return int(it-it2.it);} - ZIterator operator+(int i) {return ZIterator(it+i);} - ZIterator& operator+=(int i) {it+=i; return *this;} - std::vector::iterator it; -}; - -ECP::Point ECP::ScalarMultiply(const Point &P, const Integer &k) const -{ - Element result; - if (k.BitCount() <= 5) - AbstractGroup::SimultaneousMultiply(&result, P, &k, 1); - else - ECP::SimultaneousMultiply(&result, P, &k, 1); - return result; -} - -void ECP::SimultaneousMultiply(ECP::Point *results, const ECP::Point &P, const Integer *expBegin, unsigned int expCount) const -{ - if (!GetField().IsMontgomeryRepresentation()) - { - ECP ecpmr(*this, true); - const ModularArithmetic &mr = ecpmr.GetField(); - ecpmr.SimultaneousMultiply(results, ToMontgomery(mr, P), expBegin, expCount); - for (unsigned int i=0; i bases; - std::vector exponents; - exponents.reserve(expCount); - std::vector > baseIndices(expCount); - std::vector > negateBase(expCount); - std::vector > exponentWindows(expCount); - unsigned int i; - - for (i=0; iNotNegative()); - exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 5)); - exponents[i].FindNextWindow(); - } - - unsigned int expBitPosition = 0; - bool notDone = true; - - while (notDone) - { - notDone = false; - bool baseAdded = false; - for (i=0; i > finalCascade; - for (i=0; i::CascadeScalarMultiply(P, k1, Q, k2); -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/ecp.h b/embeddedcryptopp/ecp.h deleted file mode 100644 index d946be6..0000000 --- a/embeddedcryptopp/ecp.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef CRYPTOPP_ECP_H -#define CRYPTOPP_ECP_H - -#include "modarith.h" -#include "eprecomp.h" -#include "smartptr.h" -#include "pubkey.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! Elliptical Curve Point -struct CRYPTOPP_DLL ECPPoint -{ - ECPPoint() : identity(true) {} - ECPPoint(const Integer &x, const Integer &y) - : identity(false), x(x), y(y) {} - - bool operator==(const ECPPoint &t) const - {return (identity && t.identity) || (!identity && !t.identity && x==t.x && y==t.y);} - bool operator< (const ECPPoint &t) const - {return identity ? !t.identity : (!t.identity && (x; - -//! Elliptic Curve over GF(p), where p is prime -class CRYPTOPP_DLL ECP : public AbstractGroup -{ -public: - typedef ModularArithmetic Field; - typedef Integer FieldElement; - typedef ECPPoint Point; - - ECP() {} - ECP(const ECP &ecp, bool convertToMontgomeryRepresentation = false); - ECP(const Integer &modulus, const FieldElement &a, const FieldElement &b) - : m_fieldPtr(new Field(modulus)), m_a(a.IsNegative() ? modulus+a : a), m_b(b) {} - // construct from BER encoded parameters - // this constructor will decode and extract the the fields fieldID and curve of the sequence ECParameters - ECP(BufferedTransformation &bt); - - // encode the fields fieldID and curve of the sequence ECParameters - void DEREncode(BufferedTransformation &bt) const; - - bool Equal(const Point &P, const Point &Q) const; - const Point& Identity() const; - const Point& Inverse(const Point &P) const; - bool InversionIsFast() const {return true;} - const Point& Add(const Point &P, const Point &Q) const; - const Point& Double(const Point &P) const; - Point ScalarMultiply(const Point &P, const Integer &k) const; - Point CascadeScalarMultiply(const Point &P, const Integer &k1, const Point &Q, const Integer &k2) const; - void SimultaneousMultiply(Point *results, const Point &base, const Integer *exponents, unsigned int exponentsCount) const; - - Point Multiply(const Integer &k, const Point &P) const - {return ScalarMultiply(P, k);} - Point CascadeMultiply(const Integer &k1, const Point &P, const Integer &k2, const Point &Q) const - {return CascadeScalarMultiply(P, k1, Q, k2);} - - bool ValidateParameters(RandomNumberGenerator &rng, unsigned int level=3) const; - bool VerifyPoint(const Point &P) const; - - unsigned int EncodedPointSize(bool compressed = false) const - {return 1 + (compressed?1:2)*GetField().MaxElementByteLength();} - // returns false if point is compressed and not valid (doesn't check if uncompressed) - bool DecodePoint(Point &P, BufferedTransformation &bt, size_t len) const; - bool DecodePoint(Point &P, const byte *encodedPoint, size_t len) const; - void EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const; - void EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const; - - Point BERDecodePoint(BufferedTransformation &bt) const; - void DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const; - - Integer FieldSize() const {return GetField().GetModulus();} - const Field & GetField() const {return *m_fieldPtr;} - const FieldElement & GetA() const {return m_a;} - const FieldElement & GetB() const {return m_b;} - - bool operator==(const ECP &rhs) const - {return GetField() == rhs.GetField() && m_a == rhs.m_a && m_b == rhs.m_b;} - -private: - clonable_ptr m_fieldPtr; - FieldElement m_a, m_b; - mutable Point m_R; -}; - -CRYPTOPP_DLL_TEMPLATE_CLASS DL_FixedBasePrecomputationImpl; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupPrecomputation; - -template class EcPrecomputation; - -//! ECP precomputation -template<> class EcPrecomputation : public DL_GroupPrecomputation -{ -public: - typedef ECP EllipticCurve; - - // DL_GroupPrecomputation - bool NeedConversions() const {return true;} - Element ConvertIn(const Element &P) const - {return P.identity ? P : ECP::Point(m_ec->GetField().ConvertIn(P.x), m_ec->GetField().ConvertIn(P.y));}; - Element ConvertOut(const Element &P) const - {return P.identity ? P : ECP::Point(m_ec->GetField().ConvertOut(P.x), m_ec->GetField().ConvertOut(P.y));} - const AbstractGroup & GetGroup() const {return *m_ec;} - Element BERDecodeElement(BufferedTransformation &bt) const {return m_ec->BERDecodePoint(bt);} - void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {m_ec->DEREncodePoint(bt, v, false);} - - // non-inherited - void SetCurve(const ECP &ec) - { - m_ec.reset(new ECP(ec, true)); - m_ecOriginal = ec; - } - const ECP & GetCurve() const {return *m_ecOriginal;} - -private: - value_ptr m_ec, m_ecOriginal; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/emsa2.h b/embeddedcryptopp/emsa2.h deleted file mode 100644 index 49109e6..0000000 --- a/embeddedcryptopp/emsa2.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef CRYPTOPP_EMSA2_H -#define CRYPTOPP_EMSA2_H - -/** \file - This file contains various padding schemes for public key algorithms. -*/ - -#include "cryptlib.h" -#include "pubkey.h" - -#ifdef CRYPTOPP_IS_DLL -#include "sha.h" -#endif - -NAMESPACE_BEGIN(CryptoPP) - -template class EMSA2HashId -{ -public: - static const byte id; -}; - -template -class EMSA2HashIdLookup : public BASE -{ -public: - struct HashIdentifierLookup - { - template struct HashIdentifierLookup2 - { - static HashIdentifier Lookup() - { - return HashIdentifier(&EMSA2HashId::id, 1); - } - }; - }; -}; - -// EMSA2HashId can be instantiated with the following classes. -class SHA1; -class RIPEMD160; -class RIPEMD128; -class SHA256; -class SHA384; -class SHA512; -class Whirlpool; -class SHA224; -// end of list - -#ifdef CRYPTOPP_IS_DLL -CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId; -CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId; -CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId; -CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId; -CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId; -#endif - -//! _ -class CRYPTOPP_DLL EMSA2Pad : public EMSA2HashIdLookup -{ -public: - static const char * CRYPTOPP_API StaticAlgorithmName() {return "EMSA2";} - - size_t MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const - {return 8*digestLength + 31;} - - void ComputeMessageRepresentative(RandomNumberGenerator &rng, - const byte *recoverableMessage, size_t recoverableMessageLength, - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, size_t representativeBitLength) const; -}; - -//! EMSA2, for use with RWSS and RSA_ISO -/*! Only the following hash functions are supported by this signature standard: - \dontinclude emsa2.h - \skip EMSA2HashId can be instantiated - \until end of list -*/ -struct P1363_EMSA2 : public SignatureStandard -{ - typedef EMSA2Pad SignatureMessageEncodingMethod; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/eprecomp.cpp b/embeddedcryptopp/eprecomp.cpp deleted file mode 100644 index a061cf6..0000000 --- a/embeddedcryptopp/eprecomp.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// eprecomp.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "eprecomp.h" -#include "asn.h" - -NAMESPACE_BEGIN(CryptoPP) - -template void DL_FixedBasePrecomputationImpl::SetBase(const DL_GroupPrecomputation &group, const Element &i_base) -{ - m_base = group.NeedConversions() ? group.ConvertIn(i_base) : i_base; - - if (m_bases.empty() || !(m_base == m_bases[0])) - { - m_bases.resize(1); - m_bases[0] = m_base; - } - - if (group.NeedConversions()) - m_base = i_base; -} - -template void DL_FixedBasePrecomputationImpl::Precompute(const DL_GroupPrecomputation &group, unsigned int maxExpBits, unsigned int storage) -{ - assert(m_bases.size() > 0); - assert(storage <= maxExpBits); - - if (storage > 1) - { - m_windowSize = (maxExpBits+storage-1)/storage; - m_exponentBase = Integer::Power2(m_windowSize); - } - - m_bases.resize(storage); - for (unsigned i=1; i void DL_FixedBasePrecomputationImpl::Load(const DL_GroupPrecomputation &group, BufferedTransformation &bt) -{ - BERSequenceDecoder seq(bt); - word32 version; - BERDecodeUnsigned(seq, version, INTEGER, 1, 1); - m_exponentBase.BERDecode(seq); - m_windowSize = m_exponentBase.BitCount() - 1; - m_bases.clear(); - while (!seq.EndReached()) - m_bases.push_back(group.BERDecodeElement(seq)); - if (!m_bases.empty() && group.NeedConversions()) - m_base = group.ConvertOut(m_bases[0]); - seq.MessageEnd(); -} - -template void DL_FixedBasePrecomputationImpl::Save(const DL_GroupPrecomputation &group, BufferedTransformation &bt) const -{ - DERSequenceEncoder seq(bt); - DEREncodeUnsigned(seq, 1); // version - m_exponentBase.DEREncode(seq); - for (unsigned i=0; i void DL_FixedBasePrecomputationImpl::PrepareCascade(const DL_GroupPrecomputation &i_group, std::vector > &eb, const Integer &exponent) const -{ - const AbstractGroup &group = i_group.GetGroup(); - - Integer r, q, e = exponent; - bool fastNegate = group.InversionIsFast() && m_windowSize > 1; - unsigned int i; - - for (i=0; i+1(group.Inverse(m_bases[i]), m_exponentBase - r)); - } - else - eb.push_back(BaseAndExponent(m_bases[i], r)); - } - eb.push_back(BaseAndExponent(m_bases[i], e)); -} - -template T DL_FixedBasePrecomputationImpl::Exponentiate(const DL_GroupPrecomputation &group, const Integer &exponent) const -{ - std::vector > eb; // array of segments of the exponent and precalculated bases - eb.reserve(m_bases.size()); - PrepareCascade(group, eb, exponent); - return group.ConvertOut(GeneralCascadeMultiplication(group.GetGroup(), eb.begin(), eb.end())); -} - -template T - DL_FixedBasePrecomputationImpl::CascadeExponentiate(const DL_GroupPrecomputation &group, const Integer &exponent, - const DL_FixedBasePrecomputation &i_pc2, const Integer &exponent2) const -{ - std::vector > eb; // array of segments of the exponent and precalculated bases - const DL_FixedBasePrecomputationImpl &pc2 = static_cast &>(i_pc2); - eb.reserve(m_bases.size() + pc2.m_bases.size()); - PrepareCascade(group, eb, exponent); - pc2.PrepareCascade(group, eb, exponent2); - return group.ConvertOut(GeneralCascadeMultiplication(group.GetGroup(), eb.begin(), eb.end())); -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/eprecomp.h b/embeddedcryptopp/eprecomp.h deleted file mode 100644 index 1f32567..0000000 --- a/embeddedcryptopp/eprecomp.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef CRYPTOPP_EPRECOMP_H -#define CRYPTOPP_EPRECOMP_H - -#include "integer.h" -#include "algebra.h" -#include - -NAMESPACE_BEGIN(CryptoPP) - -template -class DL_GroupPrecomputation -{ -public: - typedef T Element; - - virtual bool NeedConversions() const {return false;} - virtual Element ConvertIn(const Element &v) const {return v;} - virtual Element ConvertOut(const Element &v) const {return v;} - virtual const AbstractGroup & GetGroup() const =0; - virtual Element BERDecodeElement(BufferedTransformation &bt) const =0; - virtual void DEREncodeElement(BufferedTransformation &bt, const Element &P) const =0; -}; - -template -class DL_FixedBasePrecomputation -{ -public: - typedef T Element; - - virtual bool IsInitialized() const =0; - virtual void SetBase(const DL_GroupPrecomputation &group, const Element &base) =0; - virtual const Element & GetBase(const DL_GroupPrecomputation &group) const =0; - virtual void Precompute(const DL_GroupPrecomputation &group, unsigned int maxExpBits, unsigned int storage) =0; - virtual void Load(const DL_GroupPrecomputation &group, BufferedTransformation &storedPrecomputation) =0; - virtual void Save(const DL_GroupPrecomputation &group, BufferedTransformation &storedPrecomputation) const =0; - virtual Element Exponentiate(const DL_GroupPrecomputation &group, const Integer &exponent) const =0; - virtual Element CascadeExponentiate(const DL_GroupPrecomputation &group, const Integer &exponent, const DL_FixedBasePrecomputation &pc2, const Integer &exponent2) const =0; -}; - -template -class DL_FixedBasePrecomputationImpl : public DL_FixedBasePrecomputation -{ -public: - typedef T Element; - - DL_FixedBasePrecomputationImpl() : m_windowSize(0) {} - - // DL_FixedBasePrecomputation - bool IsInitialized() const - {return !m_bases.empty();} - void SetBase(const DL_GroupPrecomputation &group, const Element &base); - const Element & GetBase(const DL_GroupPrecomputation &group) const - {return group.NeedConversions() ? m_base : m_bases[0];} - void Precompute(const DL_GroupPrecomputation &group, unsigned int maxExpBits, unsigned int storage); - void Load(const DL_GroupPrecomputation &group, BufferedTransformation &storedPrecomputation); - void Save(const DL_GroupPrecomputation &group, BufferedTransformation &storedPrecomputation) const; - Element Exponentiate(const DL_GroupPrecomputation &group, const Integer &exponent) const; - Element CascadeExponentiate(const DL_GroupPrecomputation &group, const Integer &exponent, const DL_FixedBasePrecomputation &pc2, const Integer &exponent2) const; - -private: - void PrepareCascade(const DL_GroupPrecomputation &group, std::vector > &eb, const Integer &exponent) const; - - Element m_base; - unsigned int m_windowSize; - Integer m_exponentBase; // what base to represent the exponent in - std::vector m_bases; // precalculated bases -}; - -NAMESPACE_END - -#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES -#include "eprecomp.cpp" -#endif - -#endif diff --git a/embeddedcryptopp/extraversion.h b/embeddedcryptopp/extraversion.h deleted file mode 100644 index d3130fb..0000000 --- a/embeddedcryptopp/extraversion.h +++ /dev/null @@ -1,9 +0,0 @@ - -/* This is the version of this tree, as created by setup.py darcsver from the darcs patch - * information: the main version number is taken from the most recent release - * tag. If some patches have been added since the last release, this will have a - * -NN "build number" suffix, or else a -rNN "revision number" suffix. Please see - * pyutil.version_class for a description of what the different fields mean. - */ - -#define CRYPTOPP_EXTRA_VERSION "pycryptopp-0.5.29" diff --git a/embeddedcryptopp/files.h b/embeddedcryptopp/files.h deleted file mode 100644 index 2c4e2b8..0000000 --- a/embeddedcryptopp/files.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef CRYPTOPP_FILES_H -#define CRYPTOPP_FILES_H - -#include "cryptlib.h" -#include "filters.h" -#include "argnames.h" - -#include -#include - -NAMESPACE_BEGIN(CryptoPP) - -//! file-based implementation of Store interface -class CRYPTOPP_DLL FileStore : public Store, private FilterPutSpaceHelper, public NotCopyable -{ -public: - class Err : public Exception - { - public: - Err(const std::string &s) : Exception(IO_ERROR, s) {} - }; - class OpenErr : public Err {public: OpenErr(const std::string &filename) : Err("FileStore: error opening file for reading: " + filename) {}}; - class ReadErr : public Err {public: ReadErr() : Err("FileStore: error reading file") {}}; - - FileStore() : m_stream(NULL) {} - FileStore(std::istream &in) - {StoreInitialize(MakeParameters(Name::InputStreamPointer(), &in));} - FileStore(const char *filename) - {StoreInitialize(MakeParameters(Name::InputFileName(), filename));} - - std::istream* GetStream() {return m_stream;} - - lword MaxRetrievable() const; - size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); - size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const; - lword Skip(lword skipMax=ULONG_MAX); - -private: - void StoreInitialize(const NameValuePairs ¶meters); - - member_ptr m_file; - std::istream *m_stream; - byte *m_space; - size_t m_len; - bool m_waiting; -}; - -//! file-based implementation of Source interface -class CRYPTOPP_DLL FileSource : public SourceTemplate -{ -public: - typedef FileStore::Err Err; - typedef FileStore::OpenErr OpenErr; - typedef FileStore::ReadErr ReadErr; - - FileSource(BufferedTransformation *attachment = NULL) - : SourceTemplate(attachment) {} - FileSource(std::istream &in, bool pumpAll, BufferedTransformation *attachment = NULL) - : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputStreamPointer(), &in));} - FileSource(const char *filename, bool pumpAll, BufferedTransformation *attachment = NULL, bool binary=true) - : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputFileName(), filename)(Name::InputBinaryMode(), binary));} - - std::istream* GetStream() {return m_store.GetStream();} -}; - -//! file-based implementation of Sink interface -class CRYPTOPP_DLL FileSink : public Sink, public NotCopyable -{ -public: - class Err : public Exception - { - public: - Err(const std::string &s) : Exception(IO_ERROR, s) {} - }; - class OpenErr : public Err {public: OpenErr(const std::string &filename) : Err("FileSink: error opening file for writing: " + filename) {}}; - class WriteErr : public Err {public: WriteErr() : Err("FileSink: error writing file") {}}; - - FileSink() : m_stream(NULL) {} - FileSink(std::ostream &out) - {IsolatedInitialize(MakeParameters(Name::OutputStreamPointer(), &out));} - FileSink(const char *filename, bool binary=true) - {IsolatedInitialize(MakeParameters(Name::OutputFileName(), filename)("OutputBinaryMode", binary));} - - std::ostream* GetStream() {return m_stream;} - - void IsolatedInitialize(const NameValuePairs ¶meters); - size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking); - bool IsolatedFlush(bool hardFlush, bool blocking); - -private: - member_ptr m_file; - std::ostream *m_stream; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/filters.cpp b/embeddedcryptopp/filters.cpp deleted file mode 100644 index 083dfd3..0000000 --- a/embeddedcryptopp/filters.cpp +++ /dev/null @@ -1,1120 +0,0 @@ -// filters.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "filters.h" -#include "mqueue.h" -#include "fltrimpl.h" -#include "argnames.h" -#include -#include - -NAMESPACE_BEGIN(CryptoPP) - -Filter::Filter(BufferedTransformation *attachment) - : m_attachment(attachment), m_continueAt(0) -{ -} - -BufferedTransformation * Filter::NewDefaultAttachment() const -{ - return new MessageQueue; -} - -BufferedTransformation * Filter::AttachedTransformation() -{ - if (m_attachment.get() == NULL) - m_attachment.reset(NewDefaultAttachment()); - return m_attachment.get(); -} - -const BufferedTransformation *Filter::AttachedTransformation() const -{ - if (m_attachment.get() == NULL) - const_cast(this)->m_attachment.reset(NewDefaultAttachment()); - return m_attachment.get(); -} - -void Filter::Detach(BufferedTransformation *newOut) -{ - m_attachment.reset(newOut); -} - -void Filter::Insert(Filter *filter) -{ - filter->m_attachment.reset(m_attachment.release()); - m_attachment.reset(filter); -} - -size_t Filter::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const -{ - return AttachedTransformation()->CopyRangeTo2(target, begin, end, channel, blocking); -} - -size_t Filter::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) -{ - return AttachedTransformation()->TransferTo2(target, transferBytes, channel, blocking); -} - -void Filter::Initialize(const NameValuePairs ¶meters, int propagation) -{ - m_continueAt = 0; - IsolatedInitialize(parameters); - PropagateInitialize(parameters, propagation); -} - -bool Filter::Flush(bool hardFlush, int propagation, bool blocking) -{ - switch (m_continueAt) - { - case 0: - if (IsolatedFlush(hardFlush, blocking)) - return true; - case 1: - if (OutputFlush(1, hardFlush, propagation, blocking)) - return true; - } - return false; -} - -bool Filter::MessageSeriesEnd(int propagation, bool blocking) -{ - switch (m_continueAt) - { - case 0: - if (IsolatedMessageSeriesEnd(blocking)) - return true; - case 1: - if (ShouldPropagateMessageSeriesEnd() && OutputMessageSeriesEnd(1, propagation, blocking)) - return true; - } - return false; -} - -void Filter::PropagateInitialize(const NameValuePairs ¶meters, int propagation) -{ - if (propagation) - AttachedTransformation()->Initialize(parameters, propagation-1); -} - -size_t Filter::OutputModifiable(int outputSite, byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel) -{ - if (messageEnd) - messageEnd--; - size_t result = AttachedTransformation()->ChannelPutModifiable2(channel, inString, length, messageEnd, blocking); - m_continueAt = result ? outputSite : 0; - return result; -} - -size_t Filter::Output(int outputSite, const byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel) -{ - if (messageEnd) - messageEnd--; - size_t result = AttachedTransformation()->ChannelPut2(channel, inString, length, messageEnd, blocking); - m_continueAt = result ? outputSite : 0; - return result; -} - -bool Filter::OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel) -{ - if (propagation && AttachedTransformation()->ChannelFlush(channel, hardFlush, propagation-1, blocking)) - { - m_continueAt = outputSite; - return true; - } - m_continueAt = 0; - return false; -} - -bool Filter::OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel) -{ - if (propagation && AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation-1, blocking)) - { - m_continueAt = outputSite; - return true; - } - m_continueAt = 0; - return false; -} - -// ************************************************************* - -void MeterFilter::ResetMeter() -{ - m_currentMessageBytes = m_totalBytes = m_currentSeriesMessages = m_totalMessages = m_totalMessageSeries = 0; - m_rangesToSkip.clear(); -} - -void MeterFilter::AddRangeToSkip(unsigned int message, lword position, lword size, bool sortNow) -{ - MessageRange r = {message, position, size}; - m_rangesToSkip.push_back(r); - if (sortNow) - std::sort(m_rangesToSkip.begin(), m_rangesToSkip.end()); -} - -size_t MeterFilter::PutMaybeModifiable(byte *begin, size_t length, int messageEnd, bool blocking, bool modifiable) -{ - if (!m_transparent) - return 0; - - size_t t; - FILTER_BEGIN; - - m_begin = begin; - m_length = length; - - while (m_length > 0 || messageEnd) - { - if (m_length > 0 && !m_rangesToSkip.empty() && m_rangesToSkip.front().message == m_totalMessages && m_currentMessageBytes + m_length > m_rangesToSkip.front().position) - { - FILTER_OUTPUT_MAYBE_MODIFIABLE(1, m_begin, t = (size_t)SaturatingSubtract(m_rangesToSkip.front().position, m_currentMessageBytes), false, modifiable); - - assert(t < m_length); - m_begin += t; - m_length -= t; - m_currentMessageBytes += t; - m_totalBytes += t; - - if (m_currentMessageBytes + m_length < m_rangesToSkip.front().position + m_rangesToSkip.front().size) - t = m_length; - else - { - t = (size_t)SaturatingSubtract(m_rangesToSkip.front().position + m_rangesToSkip.front().size, m_currentMessageBytes); - assert(t <= m_length); - m_rangesToSkip.pop_front(); - } - - m_begin += t; - m_length -= t; - m_currentMessageBytes += t; - m_totalBytes += t; - } - else - { - FILTER_OUTPUT_MAYBE_MODIFIABLE(2, m_begin, m_length, messageEnd, modifiable); - - m_currentMessageBytes += m_length; - m_totalBytes += m_length; - m_length = 0; - - if (messageEnd) - { - m_currentMessageBytes = 0; - m_currentSeriesMessages++; - m_totalMessages++; - messageEnd = false; - } - } - } - - FILTER_END_NO_MESSAGE_END; -} - -size_t MeterFilter::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) -{ - return PutMaybeModifiable(const_cast(begin), length, messageEnd, blocking, false); -} - -size_t MeterFilter::PutModifiable2(byte *begin, size_t length, int messageEnd, bool blocking) -{ - return PutMaybeModifiable(begin, length, messageEnd, blocking, true); -} - -bool MeterFilter::IsolatedMessageSeriesEnd(bool blocking) -{ - m_currentMessageBytes = 0; - m_currentSeriesMessages = 0; - m_totalMessageSeries++; - return false; -} - -// ************************************************************* - -void FilterWithBufferedInput::BlockQueue::ResetQueue(size_t blockSize, size_t maxBlocks) -{ - m_buffer.New(blockSize * maxBlocks); - m_blockSize = blockSize; - m_maxBlocks = maxBlocks; - m_size = 0; - m_begin = m_buffer; -} - -byte *FilterWithBufferedInput::BlockQueue::GetBlock() -{ - if (m_size >= m_blockSize) - { - byte *ptr = m_begin; - if ((m_begin+=m_blockSize) == m_buffer.end()) - m_begin = m_buffer; - m_size -= m_blockSize; - return ptr; - } - else - return NULL; -} - -byte *FilterWithBufferedInput::BlockQueue::GetContigousBlocks(size_t &numberOfBytes) -{ - numberOfBytes = STDMIN(numberOfBytes, STDMIN(size_t(m_buffer.end()-m_begin), m_size)); - byte *ptr = m_begin; - m_begin += numberOfBytes; - m_size -= numberOfBytes; - if (m_size == 0 || m_begin == m_buffer.end()) - m_begin = m_buffer; - return ptr; -} - -size_t FilterWithBufferedInput::BlockQueue::GetAll(byte *outString) -{ - size_t size = m_size; - size_t numberOfBytes = m_maxBlocks*m_blockSize; - const byte *ptr = GetContigousBlocks(numberOfBytes); - memcpy(outString, ptr, numberOfBytes); - memcpy(outString+numberOfBytes, m_begin, m_size); - m_size = 0; - return size; -} - -void FilterWithBufferedInput::BlockQueue::Put(const byte *inString, size_t length) -{ - assert(m_size + length <= m_buffer.size()); - byte *end = (m_size < size_t(m_buffer.end()-m_begin)) ? m_begin + m_size : m_begin + m_size - m_buffer.size(); - size_t len = STDMIN(length, size_t(m_buffer.end()-end)); - memcpy(end, inString, len); - if (len < length) - memcpy(m_buffer, inString+len, length-len); - m_size += length; -} - -FilterWithBufferedInput::FilterWithBufferedInput(BufferedTransformation *attachment) - : Filter(attachment) -{ -} - -FilterWithBufferedInput::FilterWithBufferedInput(size_t firstSize, size_t blockSize, size_t lastSize, BufferedTransformation *attachment) - : Filter(attachment), m_firstSize(firstSize), m_blockSize(blockSize), m_lastSize(lastSize) - , m_firstInputDone(false) -{ - if (m_firstSize < 0 || m_blockSize < 1 || m_lastSize < 0) - throw InvalidArgument("FilterWithBufferedInput: invalid buffer size"); - - m_queue.ResetQueue(1, m_firstSize); -} - -void FilterWithBufferedInput::IsolatedInitialize(const NameValuePairs ¶meters) -{ - InitializeDerivedAndReturnNewSizes(parameters, m_firstSize, m_blockSize, m_lastSize); - if (m_firstSize < 0 || m_blockSize < 1 || m_lastSize < 0) - throw InvalidArgument("FilterWithBufferedInput: invalid buffer size"); - m_queue.ResetQueue(1, m_firstSize); - m_firstInputDone = false; -} - -bool FilterWithBufferedInput::IsolatedFlush(bool hardFlush, bool blocking) -{ - if (!blocking) - throw BlockingInputOnly("FilterWithBufferedInput"); - - if (hardFlush) - ForceNextPut(); - FlushDerived(); - - return false; -} - -size_t FilterWithBufferedInput::PutMaybeModifiable(byte *inString, size_t length, int messageEnd, bool blocking, bool modifiable) -{ - if (!blocking) - throw BlockingInputOnly("FilterWithBufferedInput"); - - if (length != 0) - { - size_t newLength = m_queue.CurrentSize() + length; - - if (!m_firstInputDone && newLength >= m_firstSize) - { - size_t len = m_firstSize - m_queue.CurrentSize(); - m_queue.Put(inString, len); - FirstPut(m_queue.GetContigousBlocks(m_firstSize)); - assert(m_queue.CurrentSize() == 0); - m_queue.ResetQueue(m_blockSize, (2*m_blockSize+m_lastSize-2)/m_blockSize); - - inString += len; - newLength -= m_firstSize; - m_firstInputDone = true; - } - - if (m_firstInputDone) - { - if (m_blockSize == 1) - { - while (newLength > m_lastSize && m_queue.CurrentSize() > 0) - { - size_t len = newLength - m_lastSize; - byte *ptr = m_queue.GetContigousBlocks(len); - NextPutModifiable(ptr, len); - newLength -= len; - } - - if (newLength > m_lastSize) - { - size_t len = newLength - m_lastSize; - NextPutMaybeModifiable(inString, len, modifiable); - inString += len; - newLength -= len; - } - } - else - { - while (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() >= m_blockSize) - { - NextPutModifiable(m_queue.GetBlock(), m_blockSize); - newLength -= m_blockSize; - } - - if (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() > 0) - { - assert(m_queue.CurrentSize() < m_blockSize); - size_t len = m_blockSize - m_queue.CurrentSize(); - m_queue.Put(inString, len); - inString += len; - NextPutModifiable(m_queue.GetBlock(), m_blockSize); - newLength -= m_blockSize; - } - - if (newLength >= m_blockSize + m_lastSize) - { - size_t len = RoundDownToMultipleOf(newLength - m_lastSize, m_blockSize); - NextPutMaybeModifiable(inString, len, modifiable); - inString += len; - newLength -= len; - } - } - } - - m_queue.Put(inString, newLength - m_queue.CurrentSize()); - } - - if (messageEnd) - { - if (!m_firstInputDone && m_firstSize==0) - FirstPut(NULL); - - SecByteBlock temp(m_queue.CurrentSize()); - m_queue.GetAll(temp); - LastPut(temp, temp.size()); - - m_firstInputDone = false; - m_queue.ResetQueue(1, m_firstSize); - - Output(1, NULL, 0, messageEnd, blocking); - } - return 0; -} - -void FilterWithBufferedInput::ForceNextPut() -{ - if (!m_firstInputDone) - return; - - if (m_blockSize > 1) - { - while (m_queue.CurrentSize() >= m_blockSize) - NextPutModifiable(m_queue.GetBlock(), m_blockSize); - } - else - { - size_t len; - while ((len = m_queue.CurrentSize()) > 0) - NextPutModifiable(m_queue.GetContigousBlocks(len), len); - } -} - -void FilterWithBufferedInput::NextPutMultiple(const byte *inString, size_t length) -{ - assert(m_blockSize > 1); // m_blockSize = 1 should always override this function - while (length > 0) - { - assert(length >= m_blockSize); - NextPutSingle(inString); - inString += m_blockSize; - length -= m_blockSize; - } -} - -// ************************************************************* - -void Redirector::Initialize(const NameValuePairs ¶meters, int propagation) -{ - m_target = parameters.GetValueWithDefault("RedirectionTargetPointer", (BufferedTransformation*)NULL); - m_behavior = parameters.GetIntValueWithDefault("RedirectionBehavior", PASS_EVERYTHING); - - if (m_target && GetPassSignals()) - m_target->Initialize(parameters, propagation); -} - -// ************************************************************* - -ProxyFilter::ProxyFilter(BufferedTransformation *filter, size_t firstSize, size_t lastSize, BufferedTransformation *attachment) - : FilterWithBufferedInput(firstSize, 1, lastSize, attachment), m_filter(filter) -{ - if (m_filter.get()) - m_filter->Attach(new OutputProxy(*this, false)); -} - -bool ProxyFilter::IsolatedFlush(bool hardFlush, bool blocking) -{ - return m_filter.get() ? m_filter->Flush(hardFlush, -1, blocking) : false; -} - -void ProxyFilter::SetFilter(Filter *filter) -{ - m_filter.reset(filter); - if (filter) - { - OutputProxy *proxy; - std::auto_ptr temp(proxy = new OutputProxy(*this, false)); - m_filter->TransferAllTo(*proxy); - m_filter->Attach(temp.release()); - } -} - -void ProxyFilter::NextPutMultiple(const byte *s, size_t len) -{ - if (m_filter.get()) - m_filter->Put(s, len); -} - -void ProxyFilter::NextPutModifiable(byte *s, size_t len) -{ - if (m_filter.get()) - m_filter->PutModifiable(s, len); -} - -// ************************************************************* - -void RandomNumberSink::IsolatedInitialize(const NameValuePairs ¶meters) -{ - parameters.GetRequiredParameter("RandomNumberSink", "RandomNumberGeneratorPointer", m_rng); -} - -size_t RandomNumberSink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) -{ - m_rng->IncorporateEntropy(begin, length); - return 0; -} - -size_t ArraySink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) -{ - if (m_buf+m_total != begin) - memcpy(m_buf+m_total, begin, STDMIN(length, SaturatingSubtract(m_size, m_total))); - m_total += length; - return 0; -} - -byte * ArraySink::CreatePutSpace(size_t &size) -{ - size = SaturatingSubtract(m_size, m_total); - return m_buf + m_total; -} - -void ArraySink::IsolatedInitialize(const NameValuePairs ¶meters) -{ - ByteArrayParameter array; - if (!parameters.GetValue(Name::OutputBuffer(), array)) - throw InvalidArgument("ArraySink: missing OutputBuffer argument"); - m_buf = array.begin(); - m_size = array.size(); - m_total = 0; -} - -size_t ArrayXorSink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) -{ - xorbuf(m_buf+m_total, begin, STDMIN(length, SaturatingSubtract(m_size, m_total))); - m_total += length; - return 0; -} - -// ************************************************************* - -StreamTransformationFilter::StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment, BlockPaddingScheme padding, bool allowAuthenticatedSymmetricCipher) - : FilterWithBufferedInput(attachment) - , m_cipher(c) -{ - assert(c.MinLastBlockSize() == 0 || c.MinLastBlockSize() > c.MandatoryBlockSize()); - - if (!allowAuthenticatedSymmetricCipher && dynamic_cast(&c) != 0) - throw InvalidArgument("StreamTransformationFilter: please use AuthenticatedEncryptionFilter and AuthenticatedDecryptionFilter for AuthenticatedSymmetricCipher"); - - IsolatedInitialize(MakeParameters(Name::BlockPaddingScheme(), padding)); -} - -size_t StreamTransformationFilter::LastBlockSize(StreamTransformation &c, BlockPaddingScheme padding) -{ - if (c.MinLastBlockSize() > 0) - return c.MinLastBlockSize(); - else if (c.MandatoryBlockSize() > 1 && !c.IsForwardTransformation() && padding != NO_PADDING && padding != ZEROS_PADDING) - return c.MandatoryBlockSize(); - else - return 0; -} - -void StreamTransformationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize) -{ - BlockPaddingScheme padding = parameters.GetValueWithDefault(Name::BlockPaddingScheme(), DEFAULT_PADDING); - bool isBlockCipher = (m_cipher.MandatoryBlockSize() > 1 && m_cipher.MinLastBlockSize() == 0); - - if (padding == DEFAULT_PADDING) - m_padding = isBlockCipher ? PKCS_PADDING : NO_PADDING; - else - m_padding = padding; - - if (!isBlockCipher && (m_padding == PKCS_PADDING || m_padding == ONE_AND_ZEROS_PADDING)) - throw InvalidArgument("StreamTransformationFilter: PKCS_PADDING and ONE_AND_ZEROS_PADDING cannot be used with " + m_cipher.AlgorithmName()); - - firstSize = 0; - blockSize = m_cipher.MandatoryBlockSize(); - lastSize = LastBlockSize(m_cipher, m_padding); -} - -void StreamTransformationFilter::FirstPut(const byte *inString) -{ - m_optimalBufferSize = m_cipher.OptimalBlockSize(); - m_optimalBufferSize = (unsigned int)STDMAX(m_optimalBufferSize, RoundDownToMultipleOf(4096U, m_optimalBufferSize)); -} - -void StreamTransformationFilter::NextPutMultiple(const byte *inString, size_t length) -{ - if (!length) - return; - - size_t s = m_cipher.MandatoryBlockSize(); - - do - { - size_t len = m_optimalBufferSize; - byte *space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, s, length, len); - if (len < length) - { - if (len == m_optimalBufferSize) - len -= m_cipher.GetOptimalBlockSizeUsed(); - len = RoundDownToMultipleOf(len, s); - } - else - len = length; - m_cipher.ProcessString(space, inString, len); - AttachedTransformation()->PutModifiable(space, len); - inString += len; - length -= len; - } - while (length > 0); -} - -void StreamTransformationFilter::NextPutModifiable(byte *inString, size_t length) -{ - m_cipher.ProcessString(inString, length); - AttachedTransformation()->PutModifiable(inString, length); -} - -void StreamTransformationFilter::LastPut(const byte *inString, size_t length) -{ - byte *space = NULL; - - switch (m_padding) - { - case NO_PADDING: - case ZEROS_PADDING: - if (length > 0) - { - size_t minLastBlockSize = m_cipher.MinLastBlockSize(); - bool isForwardTransformation = m_cipher.IsForwardTransformation(); - - if (isForwardTransformation && m_padding == ZEROS_PADDING && (minLastBlockSize == 0 || length < minLastBlockSize)) - { - // do padding - size_t blockSize = STDMAX(minLastBlockSize, (size_t)m_cipher.MandatoryBlockSize()); - space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, blockSize); - memcpy(space, inString, length); - memset(space + length, 0, blockSize - length); - m_cipher.ProcessLastBlock(space, space, blockSize); - AttachedTransformation()->Put(space, blockSize); - } - else - { - if (minLastBlockSize == 0) - { - if (isForwardTransformation) - throw InvalidDataFormat("StreamTransformationFilter: plaintext length is not a multiple of block size and NO_PADDING is specified"); - else - throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size"); - } - - space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, length, m_optimalBufferSize); - m_cipher.ProcessLastBlock(space, inString, length); - AttachedTransformation()->Put(space, length); - } - } - break; - - case PKCS_PADDING: - case ONE_AND_ZEROS_PADDING: - unsigned int s; - s = m_cipher.MandatoryBlockSize(); - assert(s > 1); - space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, s, m_optimalBufferSize); - if (m_cipher.IsForwardTransformation()) - { - assert(length < s); - memcpy(space, inString, length); - if (m_padding == PKCS_PADDING) - { - assert(s < 256); - byte pad = byte(s-length); - memset(space+length, pad, s-length); - } - else - { - space[length] = 0x80; - memset(space+length+1, 0, s-length-1); - } - m_cipher.ProcessData(space, space, s); - AttachedTransformation()->Put(space, s); - } - else - { - if (length != s) - throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size"); - m_cipher.ProcessData(space, inString, s); - if (m_padding == PKCS_PADDING) - { - byte pad = space[s-1]; - if (pad < 1 || pad > s || std::find_if(space+s-pad, space+s, std::bind2nd(std::not_equal_to(), pad)) != space+s) - throw InvalidCiphertext("StreamTransformationFilter: invalid PKCS #7 block padding found"); - length = s-pad; - } - else - { - while (length > 1 && space[length-1] == 0) - --length; - if (space[--length] != 0x80) - throw InvalidCiphertext("StreamTransformationFilter: invalid ones-and-zeros padding found"); - } - AttachedTransformation()->Put(space, length); - } - break; - - default: - assert(false); - } -} - -// ************************************************************* - -HashFilter::HashFilter(HashTransformation &hm, BufferedTransformation *attachment, bool putMessage, int truncatedDigestSize, const std::string &messagePutChannel, const std::string &hashPutChannel) - : m_hashModule(hm), m_putMessage(putMessage), m_messagePutChannel(messagePutChannel), m_hashPutChannel(hashPutChannel) -{ - m_digestSize = truncatedDigestSize < 0 ? m_hashModule.DigestSize() : truncatedDigestSize; - Detach(attachment); -} - -void HashFilter::IsolatedInitialize(const NameValuePairs ¶meters) -{ - m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false); - int s = parameters.GetIntValueWithDefault(Name::TruncatedDigestSize(), -1); - m_digestSize = s < 0 ? m_hashModule.DigestSize() : s; -} - -size_t HashFilter::Put2(const byte *inString, size_t length, int messageEnd, bool blocking) -{ - FILTER_BEGIN; - if (m_putMessage) - FILTER_OUTPUT3(1, 0, inString, length, 0, m_messagePutChannel); - m_hashModule.Update(inString, length); - if (messageEnd) - { - { - size_t size; - m_space = HelpCreatePutSpace(*AttachedTransformation(), m_hashPutChannel, m_digestSize, m_digestSize, size = m_digestSize); - m_hashModule.TruncatedFinal(m_space, m_digestSize); - } - FILTER_OUTPUT3(2, 0, m_space, m_digestSize, messageEnd, m_hashPutChannel); - } - FILTER_END_NO_MESSAGE_END; -} - -// ************************************************************* - -HashVerificationFilter::HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment, word32 flags, int truncatedDigestSize) - : FilterWithBufferedInput(attachment) - , m_hashModule(hm) -{ - IsolatedInitialize(MakeParameters(Name::HashVerificationFilterFlags(), flags)(Name::TruncatedDigestSize(), truncatedDigestSize)); -} - -void HashVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize) -{ - m_flags = parameters.GetValueWithDefault(Name::HashVerificationFilterFlags(), (word32)DEFAULT_FLAGS); - int s = parameters.GetIntValueWithDefault(Name::TruncatedDigestSize(), -1); - m_digestSize = s < 0 ? m_hashModule.DigestSize() : s; - m_verified = false; - firstSize = m_flags & HASH_AT_BEGIN ? m_digestSize : 0; - blockSize = 1; - lastSize = m_flags & HASH_AT_BEGIN ? 0 : m_digestSize; -} - -void HashVerificationFilter::FirstPut(const byte *inString) -{ - if (m_flags & HASH_AT_BEGIN) - { - m_expectedHash.New(m_digestSize); - memcpy(m_expectedHash, inString, m_expectedHash.size()); - if (m_flags & PUT_HASH) - AttachedTransformation()->Put(inString, m_expectedHash.size()); - } -} - -void HashVerificationFilter::NextPutMultiple(const byte *inString, size_t length) -{ - m_hashModule.Update(inString, length); - if (m_flags & PUT_MESSAGE) - AttachedTransformation()->Put(inString, length); -} - -void HashVerificationFilter::LastPut(const byte *inString, size_t length) -{ - if (m_flags & HASH_AT_BEGIN) - { - assert(length == 0); - m_verified = m_hashModule.TruncatedVerify(m_expectedHash, m_digestSize); - } - else - { - m_verified = (length==m_digestSize && m_hashModule.TruncatedVerify(inString, length)); - if (m_flags & PUT_HASH) - AttachedTransformation()->Put(inString, length); - } - - if (m_flags & PUT_RESULT) - AttachedTransformation()->Put(m_verified); - - if ((m_flags & THROW_EXCEPTION) && !m_verified) - throw HashVerificationFailed(); -} - -// ************************************************************* - -AuthenticatedEncryptionFilter::AuthenticatedEncryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment, - bool putAAD, int truncatedDigestSize, const std::string &macChannel, BlockPaddingScheme padding) - : StreamTransformationFilter(c, attachment, padding, true) - , m_hf(c, new OutputProxy(*this, false), putAAD, truncatedDigestSize, AAD_CHANNEL, macChannel) -{ - assert(c.IsForwardTransformation()); -} - -void AuthenticatedEncryptionFilter::IsolatedInitialize(const NameValuePairs ¶meters) -{ - m_hf.IsolatedInitialize(parameters); - StreamTransformationFilter::IsolatedInitialize(parameters); -} - -byte * AuthenticatedEncryptionFilter::ChannelCreatePutSpace(const std::string &channel, size_t &size) -{ - if (channel.empty()) - return StreamTransformationFilter::CreatePutSpace(size); - - if (channel == AAD_CHANNEL) - return m_hf.CreatePutSpace(size); - - throw InvalidChannelName("AuthenticatedEncryptionFilter", channel); -} - -size_t AuthenticatedEncryptionFilter::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) -{ - if (channel.empty()) - return StreamTransformationFilter::Put2(begin, length, messageEnd, blocking); - - if (channel == AAD_CHANNEL) - return m_hf.Put2(begin, length, 0, blocking); - - throw InvalidChannelName("AuthenticatedEncryptionFilter", channel); -} - -void AuthenticatedEncryptionFilter::LastPut(const byte *inString, size_t length) -{ - StreamTransformationFilter::LastPut(inString, length); - m_hf.MessageEnd(); -} - -// ************************************************************* - -AuthenticatedDecryptionFilter::AuthenticatedDecryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment, word32 flags, int truncatedDigestSize, BlockPaddingScheme padding) - : FilterWithBufferedInput(attachment) - , m_hashVerifier(c, new OutputProxy(*this, false)) - , m_streamFilter(c, new OutputProxy(*this, false), padding, true) -{ - assert(!c.IsForwardTransformation() || c.IsSelfInverting()); - IsolatedInitialize(MakeParameters(Name::BlockPaddingScheme(), padding)(Name::AuthenticatedDecryptionFilterFlags(), flags)(Name::TruncatedDigestSize(), truncatedDigestSize)); -} - -void AuthenticatedDecryptionFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize) -{ - word32 flags = parameters.GetValueWithDefault(Name::AuthenticatedDecryptionFilterFlags(), (word32)DEFAULT_FLAGS); - - m_hashVerifier.Initialize(CombinedNameValuePairs(parameters, MakeParameters(Name::HashVerificationFilterFlags(), flags))); - m_streamFilter.Initialize(parameters); - - firstSize = m_hashVerifier.m_firstSize; - blockSize = 1; - lastSize = m_hashVerifier.m_lastSize; -} - -byte * AuthenticatedDecryptionFilter::ChannelCreatePutSpace(const std::string &channel, size_t &size) -{ - if (channel.empty()) - return m_streamFilter.CreatePutSpace(size); - - if (channel == AAD_CHANNEL) - return m_hashVerifier.CreatePutSpace(size); - - throw InvalidChannelName("AuthenticatedDecryptionFilter", channel); -} - -size_t AuthenticatedDecryptionFilter::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) -{ - if (channel.empty()) - { - if (m_lastSize > 0) - m_hashVerifier.ForceNextPut(); - return FilterWithBufferedInput::Put2(begin, length, messageEnd, blocking); - } - - if (channel == AAD_CHANNEL) - return m_hashVerifier.Put2(begin, length, 0, blocking); - - throw InvalidChannelName("AuthenticatedDecryptionFilter", channel); -} - -void AuthenticatedDecryptionFilter::FirstPut(const byte *inString) -{ - m_hashVerifier.Put(inString, m_firstSize); -} - -void AuthenticatedDecryptionFilter::NextPutMultiple(const byte *inString, size_t length) -{ - m_streamFilter.Put(inString, length); -} - -void AuthenticatedDecryptionFilter::LastPut(const byte *inString, size_t length) -{ - m_streamFilter.MessageEnd(); - m_hashVerifier.PutMessageEnd(inString, length); -} - -// ************************************************************* - -void SignerFilter::IsolatedInitialize(const NameValuePairs ¶meters) -{ - m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false); - m_messageAccumulator.reset(m_signer.NewSignatureAccumulator(m_rng)); -} - -size_t SignerFilter::Put2(const byte *inString, size_t length, int messageEnd, bool blocking) -{ - FILTER_BEGIN; - m_messageAccumulator->Update(inString, length); - if (m_putMessage) - FILTER_OUTPUT(1, inString, length, 0); - if (messageEnd) - { - m_buf.New(m_signer.SignatureLength()); - m_signer.Sign(m_rng, m_messageAccumulator.release(), m_buf); - FILTER_OUTPUT(2, m_buf, m_buf.size(), messageEnd); - m_messageAccumulator.reset(m_signer.NewSignatureAccumulator(m_rng)); - } - FILTER_END_NO_MESSAGE_END; -} - -SignatureVerificationFilter::SignatureVerificationFilter(const PK_Verifier &verifier, BufferedTransformation *attachment, word32 flags) - : FilterWithBufferedInput(attachment) - , m_verifier(verifier) -{ - IsolatedInitialize(MakeParameters(Name::SignatureVerificationFilterFlags(), flags)); -} - -void SignatureVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize) -{ - m_flags = parameters.GetValueWithDefault(Name::SignatureVerificationFilterFlags(), (word32)DEFAULT_FLAGS); - m_messageAccumulator.reset(m_verifier.NewVerificationAccumulator()); - size_t size = m_verifier.SignatureLength(); - assert(size != 0); // TODO: handle recoverable signature scheme - m_verified = false; - firstSize = m_flags & SIGNATURE_AT_BEGIN ? size : 0; - blockSize = 1; - lastSize = m_flags & SIGNATURE_AT_BEGIN ? 0 : size; -} - -void SignatureVerificationFilter::FirstPut(const byte *inString) -{ - if (m_flags & SIGNATURE_AT_BEGIN) - { - if (m_verifier.SignatureUpfront()) - m_verifier.InputSignature(*m_messageAccumulator, inString, m_verifier.SignatureLength()); - else - { - m_signature.New(m_verifier.SignatureLength()); - memcpy(m_signature, inString, m_signature.size()); - } - - if (m_flags & PUT_SIGNATURE) - AttachedTransformation()->Put(inString, m_signature.size()); - } - else - { - assert(!m_verifier.SignatureUpfront()); - } -} - -void SignatureVerificationFilter::NextPutMultiple(const byte *inString, size_t length) -{ - m_messageAccumulator->Update(inString, length); - if (m_flags & PUT_MESSAGE) - AttachedTransformation()->Put(inString, length); -} - -void SignatureVerificationFilter::LastPut(const byte *inString, size_t length) -{ - if (m_flags & SIGNATURE_AT_BEGIN) - { - assert(length == 0); - m_verifier.InputSignature(*m_messageAccumulator, m_signature, m_signature.size()); - m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator); - } - else - { - m_verifier.InputSignature(*m_messageAccumulator, inString, length); - m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator); - if (m_flags & PUT_SIGNATURE) - AttachedTransformation()->Put(inString, length); - } - - if (m_flags & PUT_RESULT) - AttachedTransformation()->Put(m_verified); - - if ((m_flags & THROW_EXCEPTION) && !m_verified) - throw SignatureVerificationFailed(); -} - -// ************************************************************* - -size_t Source::PumpAll2(bool blocking) -{ - unsigned int messageCount = UINT_MAX; - do { - RETURN_IF_NONZERO(PumpMessages2(messageCount, blocking)); - } while(messageCount == UINT_MAX); - - return 0; -} - -bool Store::GetNextMessage() -{ - if (!m_messageEnd && !AnyRetrievable()) - { - m_messageEnd=true; - return true; - } - else - return false; -} - -unsigned int Store::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const -{ - if (m_messageEnd || count == 0) - return 0; - else - { - CopyTo(target, ULONG_MAX, channel); - if (GetAutoSignalPropagation()) - target.ChannelMessageEnd(channel, GetAutoSignalPropagation()-1); - return 1; - } -} - -void StringStore::StoreInitialize(const NameValuePairs ¶meters) -{ - ConstByteArrayParameter array; - if (!parameters.GetValue(Name::InputBuffer(), array)) - throw InvalidArgument("StringStore: missing InputBuffer argument"); - m_store = array.begin(); - m_length = array.size(); - m_count = 0; -} - -size_t StringStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) -{ - lword position = 0; - size_t blockedBytes = CopyRangeTo2(target, position, transferBytes, channel, blocking); - m_count += (size_t)position; - transferBytes = position; - return blockedBytes; -} - -size_t StringStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const -{ - size_t i = UnsignedMin(m_length, m_count+begin); - size_t len = UnsignedMin(m_length-i, end-begin); - size_t blockedBytes = target.ChannelPut2(channel, m_store+i, len, 0, blocking); - if (!blockedBytes) - begin += len; - return blockedBytes; -} - -void RandomNumberStore::StoreInitialize(const NameValuePairs ¶meters) -{ - parameters.GetRequiredParameter("RandomNumberStore", "RandomNumberGeneratorPointer", m_rng); - int length; - parameters.GetRequiredIntParameter("RandomNumberStore", "RandomNumberStoreSize", length); - m_length = length; -} - -size_t RandomNumberStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) -{ - if (!blocking) - throw NotImplemented("RandomNumberStore: nonblocking transfer is not implemented by this object"); - - transferBytes = UnsignedMin(transferBytes, m_length - m_count); - m_rng->GenerateIntoBufferedTransformation(target, channel, transferBytes); - m_count += transferBytes; - - return 0; -} - -size_t NullStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const -{ - static const byte nullBytes[128] = {0}; - while (begin < end) - { - size_t len = (size_t)STDMIN(end-begin, lword(128)); - size_t blockedBytes = target.ChannelPut2(channel, nullBytes, len, 0, blocking); - if (blockedBytes) - return blockedBytes; - begin += len; - } - return 0; -} - -size_t NullStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) -{ - lword begin = 0; - size_t blockedBytes = NullStore::CopyRangeTo2(target, begin, transferBytes, channel, blocking); - transferBytes = begin; - m_size -= begin; - return blockedBytes; -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/filters.h b/embeddedcryptopp/filters.h deleted file mode 100644 index b2194ca..0000000 --- a/embeddedcryptopp/filters.h +++ /dev/null @@ -1,808 +0,0 @@ -#ifndef CRYPTOPP_FILTERS_H -#define CRYPTOPP_FILTERS_H - -#include "simple.h" -#include "secblock.h" -#include "misc.h" -#include "smartptr.h" -#include "queue.h" -#include "algparam.h" -#include - -NAMESPACE_BEGIN(CryptoPP) - -/// provides an implementation of BufferedTransformation's attachment interface -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Filter : public BufferedTransformation, public NotCopyable -{ -public: - Filter(BufferedTransformation *attachment = NULL); - - bool Attachable() {return true;} - BufferedTransformation *AttachedTransformation(); - const BufferedTransformation *AttachedTransformation() const; - void Detach(BufferedTransformation *newAttachment = NULL); - - size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); - size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const; - - void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1); - bool Flush(bool hardFlush, int propagation=-1, bool blocking=true); - bool MessageSeriesEnd(int propagation=-1, bool blocking=true); - -protected: - virtual BufferedTransformation * NewDefaultAttachment() const; - void Insert(Filter *nextFilter); // insert filter after this one - - virtual bool ShouldPropagateMessageEnd() const {return true;} - virtual bool ShouldPropagateMessageSeriesEnd() const {return true;} - - void PropagateInitialize(const NameValuePairs ¶meters, int propagation); - - size_t Output(int outputSite, const byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel=DEFAULT_CHANNEL); - size_t OutputModifiable(int outputSite, byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel=DEFAULT_CHANNEL); - bool OutputMessageEnd(int outputSite, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL); - bool OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL); - bool OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL); - -private: - member_ptr m_attachment; - -protected: - size_t m_inputPosition; - int m_continueAt; -}; - -struct CRYPTOPP_DLL FilterPutSpaceHelper -{ - // desiredSize is how much to ask target, bufferSize is how much to allocate in m_tempSpace - byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize, size_t desiredSize, size_t &bufferSize) - { - assert(desiredSize >= minSize && bufferSize >= minSize); - if (m_tempSpace.size() < minSize) - { - byte *result = target.ChannelCreatePutSpace(channel, desiredSize); - if (desiredSize >= minSize) - { - bufferSize = desiredSize; - return result; - } - m_tempSpace.New(bufferSize); - } - - bufferSize = m_tempSpace.size(); - return m_tempSpace.begin(); - } - byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize) - {return HelpCreatePutSpace(target, channel, minSize, minSize, minSize);} - byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize, size_t bufferSize) - {return HelpCreatePutSpace(target, channel, minSize, minSize, bufferSize);} - SecByteBlock m_tempSpace; -}; - -//! measure how many byte and messages pass through, also serves as valve -class CRYPTOPP_DLL MeterFilter : public Bufferless -{ -public: - MeterFilter(BufferedTransformation *attachment=NULL, bool transparent=true) - : m_transparent(transparent) {Detach(attachment); ResetMeter();} - - void SetTransparent(bool transparent) {m_transparent = transparent;} - void AddRangeToSkip(unsigned int message, lword position, lword size, bool sortNow = true); - void ResetMeter(); - void IsolatedInitialize(const NameValuePairs ¶meters) {ResetMeter();} - - lword GetCurrentMessageBytes() const {return m_currentMessageBytes;} - lword GetTotalBytes() {return m_totalBytes;} - unsigned int GetCurrentSeriesMessages() {return m_currentSeriesMessages;} - unsigned int GetTotalMessages() {return m_totalMessages;} - unsigned int GetTotalMessageSeries() {return m_totalMessageSeries;} - - byte * CreatePutSpace(size_t &size) - {return AttachedTransformation()->CreatePutSpace(size);} - size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); - size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking); - bool IsolatedMessageSeriesEnd(bool blocking); - -private: - size_t PutMaybeModifiable(byte *inString, size_t length, int messageEnd, bool blocking, bool modifiable); - bool ShouldPropagateMessageEnd() const {return m_transparent;} - bool ShouldPropagateMessageSeriesEnd() const {return m_transparent;} - - struct MessageRange - { - inline bool operator<(const MessageRange &b) const // BCB2006 workaround: this has to be a member function - {return message < b.message || (message == b.message && position < b.position);} - unsigned int message; lword position; lword size; - }; - - bool m_transparent; - lword m_currentMessageBytes, m_totalBytes; - unsigned int m_currentSeriesMessages, m_totalMessages, m_totalMessageSeries; - std::deque m_rangesToSkip; - byte *m_begin; - size_t m_length; -}; - -//! _ -class CRYPTOPP_DLL TransparentFilter : public MeterFilter -{ -public: - TransparentFilter(BufferedTransformation *attachment=NULL) : MeterFilter(attachment, true) {} -}; - -//! _ -class CRYPTOPP_DLL OpaqueFilter : public MeterFilter -{ -public: - OpaqueFilter(BufferedTransformation *attachment=NULL) : MeterFilter(attachment, false) {} -}; - -/*! FilterWithBufferedInput divides up the input stream into - a first block, a number of middle blocks, and a last block. - First and last blocks are optional, and middle blocks may - be a stream instead (i.e. blockSize == 1). -*/ -class CRYPTOPP_DLL FilterWithBufferedInput : public Filter -{ -public: - FilterWithBufferedInput(BufferedTransformation *attachment); - //! firstSize and lastSize may be 0, blockSize must be at least 1 - FilterWithBufferedInput(size_t firstSize, size_t blockSize, size_t lastSize, BufferedTransformation *attachment); - - void IsolatedInitialize(const NameValuePairs ¶meters); - size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) - { - return PutMaybeModifiable(const_cast(inString), length, messageEnd, blocking, false); - } - size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking) - { - return PutMaybeModifiable(inString, length, messageEnd, blocking, true); - } - /*! calls ForceNextPut() if hardFlush is true */ - bool IsolatedFlush(bool hardFlush, bool blocking); - - /*! The input buffer may contain more than blockSize bytes if lastSize != 0. - ForceNextPut() forces a call to NextPut() if this is the case. - */ - void ForceNextPut(); - -protected: - bool DidFirstPut() {return m_firstInputDone;} - - virtual void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize) - {InitializeDerived(parameters);} - virtual void InitializeDerived(const NameValuePairs ¶meters) {} - // FirstPut() is called if (firstSize != 0 and totalLength >= firstSize) - // or (firstSize == 0 and (totalLength > 0 or a MessageEnd() is received)) - virtual void FirstPut(const byte *inString) =0; - // NextPut() is called if totalLength >= firstSize+blockSize+lastSize - virtual void NextPutSingle(const byte *inString) {assert(false);} - // Same as NextPut() except length can be a multiple of blockSize - // Either NextPut() or NextPutMultiple() must be overriden - virtual void NextPutMultiple(const byte *inString, size_t length); - // Same as NextPutMultiple(), but inString can be modified - virtual void NextPutModifiable(byte *inString, size_t length) - {NextPutMultiple(inString, length);} - // LastPut() is always called - // if totalLength < firstSize then length == totalLength - // else if totalLength <= firstSize+lastSize then length == totalLength-firstSize - // else lastSize <= length < lastSize+blockSize - virtual void LastPut(const byte *inString, size_t length) =0; - virtual void FlushDerived() {} - -protected: - size_t PutMaybeModifiable(byte *begin, size_t length, int messageEnd, bool blocking, bool modifiable); - void NextPutMaybeModifiable(byte *inString, size_t length, bool modifiable) - { - if (modifiable) NextPutModifiable(inString, length); - else NextPutMultiple(inString, length); - } - - // This function should no longer be used, put this here to cause a compiler error - // if someone tries to override NextPut(). - virtual int NextPut(const byte *inString, size_t length) {assert(false); return 0;} - - class BlockQueue - { - public: - void ResetQueue(size_t blockSize, size_t maxBlocks); - byte *GetBlock(); - byte *GetContigousBlocks(size_t &numberOfBytes); - size_t GetAll(byte *outString); - void Put(const byte *inString, size_t length); - size_t CurrentSize() const {return m_size;} - size_t MaxSize() const {return m_buffer.size();} - - private: - SecByteBlock m_buffer; - size_t m_blockSize, m_maxBlocks, m_size; - byte *m_begin; - }; - - size_t m_firstSize, m_blockSize, m_lastSize; - bool m_firstInputDone; - BlockQueue m_queue; -}; - -//! _ -class CRYPTOPP_DLL FilterWithInputQueue : public Filter -{ -public: - FilterWithInputQueue(BufferedTransformation *attachment=NULL) : Filter(attachment) {} - - size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) - { - if (!blocking) - throw BlockingInputOnly("FilterWithInputQueue"); - - m_inQueue.Put(inString, length); - if (messageEnd) - { - IsolatedMessageEnd(blocking); - Output(0, NULL, 0, messageEnd, blocking); - } - return 0; - } - -protected: - virtual bool IsolatedMessageEnd(bool blocking) =0; - void IsolatedInitialize(const NameValuePairs ¶meters) {m_inQueue.Clear();} - - ByteQueue m_inQueue; -}; - -struct BlockPaddingSchemeDef -{ - enum BlockPaddingScheme {NO_PADDING, ZEROS_PADDING, PKCS_PADDING, ONE_AND_ZEROS_PADDING, DEFAULT_PADDING}; -}; - -//! Filter Wrapper for StreamTransformation, optionally handling padding/unpadding when needed -class CRYPTOPP_DLL StreamTransformationFilter : public FilterWithBufferedInput, public BlockPaddingSchemeDef, private FilterPutSpaceHelper -{ -public: - /*! DEFAULT_PADDING means PKCS_PADDING if c.MandatoryBlockSize() > 1 && c.MinLastBlockSize() == 0 (e.g. ECB or CBC mode), - otherwise NO_PADDING (OFB, CFB, CTR, CBC-CTS modes). - See http://www.weidai.com/scan-mirror/csp.html for details of the padding schemes. */ - StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment = NULL, BlockPaddingScheme padding = DEFAULT_PADDING, bool allowAuthenticatedSymmetricCipher = false); - - std::string AlgorithmName() const {return m_cipher.AlgorithmName();} - -protected: - void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize); - void FirstPut(const byte *inString); - void NextPutMultiple(const byte *inString, size_t length); - void NextPutModifiable(byte *inString, size_t length); - void LastPut(const byte *inString, size_t length); - - static size_t LastBlockSize(StreamTransformation &c, BlockPaddingScheme padding); - - StreamTransformation &m_cipher; - BlockPaddingScheme m_padding; - unsigned int m_optimalBufferSize; -}; - -#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY -typedef StreamTransformationFilter StreamCipherFilter; -#endif - -//! Filter Wrapper for HashTransformation -class CRYPTOPP_DLL HashFilter : public Bufferless, private FilterPutSpaceHelper -{ -public: - HashFilter(HashTransformation &hm, BufferedTransformation *attachment = NULL, bool putMessage=false, int truncatedDigestSize=-1, const std::string &messagePutChannel=DEFAULT_CHANNEL, const std::string &hashPutChannel=DEFAULT_CHANNEL); - - std::string AlgorithmName() const {return m_hashModule.AlgorithmName();} - void IsolatedInitialize(const NameValuePairs ¶meters); - size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); - byte * CreatePutSpace(size_t &size) {return m_hashModule.CreateUpdateSpace(size);} - -private: - HashTransformation &m_hashModule; - bool m_putMessage; - unsigned int m_digestSize; - byte *m_space; - std::string m_messagePutChannel, m_hashPutChannel; -}; - -//! Filter Wrapper for HashTransformation -class CRYPTOPP_DLL HashVerificationFilter : public FilterWithBufferedInput -{ -public: - class HashVerificationFailed : public Exception - { - public: - HashVerificationFailed() - : Exception(DATA_INTEGRITY_CHECK_FAILED, "HashVerificationFilter: message hash or MAC not valid") {} - }; - - enum Flags {HASH_AT_END=0, HASH_AT_BEGIN=1, PUT_MESSAGE=2, PUT_HASH=4, PUT_RESULT=8, THROW_EXCEPTION=16, DEFAULT_FLAGS = HASH_AT_BEGIN | PUT_RESULT}; - HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS, int truncatedDigestSize=-1); - - std::string AlgorithmName() const {return m_hashModule.AlgorithmName();} - bool GetLastResult() const {return m_verified;} - -protected: - void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize); - void FirstPut(const byte *inString); - void NextPutMultiple(const byte *inString, size_t length); - void LastPut(const byte *inString, size_t length); - -private: - friend class AuthenticatedDecryptionFilter; - - HashTransformation &m_hashModule; - word32 m_flags; - unsigned int m_digestSize; - bool m_verified; - SecByteBlock m_expectedHash; -}; - -typedef HashVerificationFilter HashVerifier; // for backwards compatibility - -//! Filter wrapper for encrypting with AuthenticatedSymmetricCipher, optionally handling padding/unpadding when needed -/*! Additional authenticated data should be given in channel "AAD". If putAAD is true, AAD will be Put() to the attached BufferedTransformation in channel "AAD". */ -class CRYPTOPP_DLL AuthenticatedEncryptionFilter : public StreamTransformationFilter -{ -public: - /*! See StreamTransformationFilter for documentation on BlockPaddingScheme */ - AuthenticatedEncryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment = NULL, bool putAAD=false, int truncatedDigestSize=-1, const std::string &macChannel=DEFAULT_CHANNEL, BlockPaddingScheme padding = DEFAULT_PADDING); - - void IsolatedInitialize(const NameValuePairs ¶meters); - byte * ChannelCreatePutSpace(const std::string &channel, size_t &size); - size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking); - void LastPut(const byte *inString, size_t length); - -protected: - HashFilter m_hf; -}; - -//! Filter wrapper for decrypting with AuthenticatedSymmetricCipher, optionally handling padding/unpadding when needed -/*! Additional authenticated data should be given in channel "AAD". */ -class CRYPTOPP_DLL AuthenticatedDecryptionFilter : public FilterWithBufferedInput, public BlockPaddingSchemeDef -{ -public: - enum Flags {MAC_AT_END=0, MAC_AT_BEGIN=1, THROW_EXCEPTION=16, DEFAULT_FLAGS = THROW_EXCEPTION}; - - /*! See StreamTransformationFilter for documentation on BlockPaddingScheme */ - AuthenticatedDecryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS, int truncatedDigestSize=-1, BlockPaddingScheme padding = DEFAULT_PADDING); - - std::string AlgorithmName() const {return m_hashVerifier.AlgorithmName();} - byte * ChannelCreatePutSpace(const std::string &channel, size_t &size); - size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking); - bool GetLastResult() const {return m_hashVerifier.GetLastResult();} - -protected: - void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize); - void FirstPut(const byte *inString); - void NextPutMultiple(const byte *inString, size_t length); - void LastPut(const byte *inString, size_t length); - - HashVerificationFilter m_hashVerifier; - StreamTransformationFilter m_streamFilter; -}; - -//! Filter Wrapper for PK_Signer -class CRYPTOPP_DLL SignerFilter : public Unflushable -{ -public: - SignerFilter(RandomNumberGenerator &rng, const PK_Signer &signer, BufferedTransformation *attachment = NULL, bool putMessage=false) - : m_rng(rng), m_signer(signer), m_messageAccumulator(signer.NewSignatureAccumulator(rng)), m_putMessage(putMessage) {Detach(attachment);} - - std::string AlgorithmName() const {return m_signer.AlgorithmName();} - - void IsolatedInitialize(const NameValuePairs ¶meters); - size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); - -private: - RandomNumberGenerator &m_rng; - const PK_Signer &m_signer; - member_ptr m_messageAccumulator; - bool m_putMessage; - SecByteBlock m_buf; -}; - -//! Filter Wrapper for PK_Verifier -class CRYPTOPP_DLL SignatureVerificationFilter : public FilterWithBufferedInput -{ -public: - class SignatureVerificationFailed : public Exception - { - public: - SignatureVerificationFailed() - : Exception(DATA_INTEGRITY_CHECK_FAILED, "VerifierFilter: digital signature not valid") {} - }; - - enum Flags {SIGNATURE_AT_END=0, SIGNATURE_AT_BEGIN=1, PUT_MESSAGE=2, PUT_SIGNATURE=4, PUT_RESULT=8, THROW_EXCEPTION=16, DEFAULT_FLAGS = SIGNATURE_AT_BEGIN | PUT_RESULT}; - SignatureVerificationFilter(const PK_Verifier &verifier, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS); - - std::string AlgorithmName() const {return m_verifier.AlgorithmName();} - - bool GetLastResult() const {return m_verified;} - -protected: - void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize); - void FirstPut(const byte *inString); - void NextPutMultiple(const byte *inString, size_t length); - void LastPut(const byte *inString, size_t length); - -private: - const PK_Verifier &m_verifier; - member_ptr m_messageAccumulator; - word32 m_flags; - SecByteBlock m_signature; - bool m_verified; -}; - -typedef SignatureVerificationFilter VerifierFilter; // for backwards compatibility - -//! Redirect input to another BufferedTransformation without owning it -class CRYPTOPP_DLL Redirector : public CustomSignalPropagation -{ -public: - enum Behavior - { - DATA_ONLY = 0x00, - PASS_SIGNALS = 0x01, - PASS_WAIT_OBJECTS = 0x02, - PASS_EVERYTHING = PASS_SIGNALS | PASS_WAIT_OBJECTS - }; - - Redirector() : m_target(NULL), m_behavior(PASS_EVERYTHING) {} - Redirector(BufferedTransformation &target, Behavior behavior=PASS_EVERYTHING) - : m_target(&target), m_behavior(behavior) {} - - void Redirect(BufferedTransformation &target) {m_target = ⌖} - void StopRedirection() {m_target = NULL;} - - Behavior GetBehavior() {return (Behavior) m_behavior;} - void SetBehavior(Behavior behavior) {m_behavior=behavior;} - bool GetPassSignals() const {return (m_behavior & PASS_SIGNALS) != 0;} - void SetPassSignals(bool pass) { if (pass) m_behavior |= PASS_SIGNALS; else m_behavior &= ~(word32) PASS_SIGNALS; } - bool GetPassWaitObjects() const {return (m_behavior & PASS_WAIT_OBJECTS) != 0;} - void SetPassWaitObjects(bool pass) { if (pass) m_behavior |= PASS_WAIT_OBJECTS; else m_behavior &= ~(word32) PASS_WAIT_OBJECTS; } - - bool CanModifyInput() const - {return m_target ? m_target->CanModifyInput() : false;} - - void Initialize(const NameValuePairs ¶meters, int propagation); - byte * CreatePutSpace(size_t &size) - {return m_target ? m_target->CreatePutSpace(size) : (byte *)(size=0, NULL);} - size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking) - {return m_target ? m_target->Put2(begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;} - bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) - {return m_target && GetPassSignals() ? m_target->Flush(hardFlush, propagation, blocking) : false;} - bool MessageSeriesEnd(int propagation=-1, bool blocking=true) - {return m_target && GetPassSignals() ? m_target->MessageSeriesEnd(propagation, blocking) : false;} - - byte * ChannelCreatePutSpace(const std::string &channel, size_t &size) - {return m_target ? m_target->ChannelCreatePutSpace(channel, size) : (byte *)(size=0, NULL);} - size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) - {return m_target ? m_target->ChannelPut2(channel, begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;} - size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking) - {return m_target ? m_target->ChannelPutModifiable2(channel, begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;} - bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true) - {return m_target && GetPassSignals() ? m_target->ChannelFlush(channel, completeFlush, propagation, blocking) : false;} - bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true) - {return m_target && GetPassSignals() ? m_target->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;} - - unsigned int GetMaxWaitObjectCount() const - { return m_target && GetPassWaitObjects() ? m_target->GetMaxWaitObjectCount() : 0; } - void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack) - { if (m_target && GetPassWaitObjects()) m_target->GetWaitObjects(container, callStack); } - -private: - BufferedTransformation *m_target; - word32 m_behavior; -}; - -// Used By ProxyFilter -class CRYPTOPP_DLL OutputProxy : public CustomSignalPropagation -{ -public: - OutputProxy(BufferedTransformation &owner, bool passSignal) : m_owner(owner), m_passSignal(passSignal) {} - - bool GetPassSignal() const {return m_passSignal;} - void SetPassSignal(bool passSignal) {m_passSignal = passSignal;} - - byte * CreatePutSpace(size_t &size) - {return m_owner.AttachedTransformation()->CreatePutSpace(size);} - size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking) - {return m_owner.AttachedTransformation()->Put2(begin, length, m_passSignal ? messageEnd : 0, blocking);} - size_t PutModifiable2(byte *begin, size_t length, int messageEnd, bool blocking) - {return m_owner.AttachedTransformation()->PutModifiable2(begin, length, m_passSignal ? messageEnd : 0, blocking);} - void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1) - {if (m_passSignal) m_owner.AttachedTransformation()->Initialize(parameters, propagation);} - bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) - {return m_passSignal ? m_owner.AttachedTransformation()->Flush(hardFlush, propagation, blocking) : false;} - bool MessageSeriesEnd(int propagation=-1, bool blocking=true) - {return m_passSignal ? m_owner.AttachedTransformation()->MessageSeriesEnd(propagation, blocking) : false;} - - byte * ChannelCreatePutSpace(const std::string &channel, size_t &size) - {return m_owner.AttachedTransformation()->ChannelCreatePutSpace(channel, size);} - size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) - {return m_owner.AttachedTransformation()->ChannelPut2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking);} - size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking) - {return m_owner.AttachedTransformation()->ChannelPutModifiable2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking);} - bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true) - {return m_passSignal ? m_owner.AttachedTransformation()->ChannelFlush(channel, completeFlush, propagation, blocking) : false;} - bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true) - {return m_passSignal ? m_owner.AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;} - -private: - BufferedTransformation &m_owner; - bool m_passSignal; -}; - -//! Base class for Filter classes that are proxies for a chain of other filters. -class CRYPTOPP_DLL ProxyFilter : public FilterWithBufferedInput -{ -public: - ProxyFilter(BufferedTransformation *filter, size_t firstSize, size_t lastSize, BufferedTransformation *attachment); - - bool IsolatedFlush(bool hardFlush, bool blocking); - - void SetFilter(Filter *filter); - void NextPutMultiple(const byte *s, size_t len); - void NextPutModifiable(byte *inString, size_t length); - -protected: - member_ptr m_filter; -}; - -//! simple proxy filter that doesn't modify the underlying filter's input or output -class CRYPTOPP_DLL SimpleProxyFilter : public ProxyFilter -{ -public: - SimpleProxyFilter(BufferedTransformation *filter, BufferedTransformation *attachment) - : ProxyFilter(filter, 0, 0, attachment) {} - - void FirstPut(const byte *) {} - void LastPut(const byte *, size_t) {m_filter->MessageEnd();} -}; - -//! proxy for the filter created by PK_Encryptor::CreateEncryptionFilter -/*! This class is here just to provide symmetry with VerifierFilter. */ -class CRYPTOPP_DLL PK_EncryptorFilter : public SimpleProxyFilter -{ -public: - PK_EncryptorFilter(RandomNumberGenerator &rng, const PK_Encryptor &encryptor, BufferedTransformation *attachment = NULL) - : SimpleProxyFilter(encryptor.CreateEncryptionFilter(rng), attachment) {} -}; - -//! proxy for the filter created by PK_Decryptor::CreateDecryptionFilter -/*! This class is here just to provide symmetry with SignerFilter. */ -class CRYPTOPP_DLL PK_DecryptorFilter : public SimpleProxyFilter -{ -public: - PK_DecryptorFilter(RandomNumberGenerator &rng, const PK_Decryptor &decryptor, BufferedTransformation *attachment = NULL) - : SimpleProxyFilter(decryptor.CreateDecryptionFilter(rng), attachment) {} -}; - -//! Append input to a string object -template -class StringSinkTemplate : public Bufferless -{ -public: - // VC60 workaround: no T::char_type - typedef typename T::traits_type::char_type char_type; - - StringSinkTemplate(T &output) - : m_output(&output) {assert(sizeof(output[0])==1);} - - void IsolatedInitialize(const NameValuePairs ¶meters) - {if (!parameters.GetValue("OutputStringPointer", m_output)) throw InvalidArgument("StringSink: OutputStringPointer not specified");} - - size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking) - { - if (length > 0) - { - typename T::size_type size = m_output->size(); - if (length < size && size + length > m_output->capacity()) - m_output->reserve(2*size); - m_output->append((const char_type *)begin, (const char_type *)begin+length); - } - return 0; - } - -private: - T *m_output; -}; - -//! Append input to an std::string -CRYPTOPP_DLL_TEMPLATE_CLASS StringSinkTemplate; -typedef StringSinkTemplate StringSink; - -//! incorporates input into RNG as additional entropy -class RandomNumberSink : public Bufferless -{ -public: - RandomNumberSink() - : m_rng(NULL) {} - - RandomNumberSink(RandomNumberGenerator &rng) - : m_rng(&rng) {} - - void IsolatedInitialize(const NameValuePairs ¶meters); - size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); - -private: - RandomNumberGenerator *m_rng; -}; - -//! Copy input to a memory buffer -class CRYPTOPP_DLL ArraySink : public Bufferless -{ -public: - ArraySink(const NameValuePairs ¶meters = g_nullNameValuePairs) {IsolatedInitialize(parameters);} - ArraySink(byte *buf, size_t size) : m_buf(buf), m_size(size), m_total(0) {} - - size_t AvailableSize() {return SaturatingSubtract(m_size, m_total);} - lword TotalPutLength() {return m_total;} - - void IsolatedInitialize(const NameValuePairs ¶meters); - byte * CreatePutSpace(size_t &size); - size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); - -protected: - byte *m_buf; - size_t m_size; - lword m_total; -}; - -//! Xor input to a memory buffer -class CRYPTOPP_DLL ArrayXorSink : public ArraySink -{ -public: - ArrayXorSink(byte *buf, size_t size) - : ArraySink(buf, size) {} - - size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); - byte * CreatePutSpace(size_t &size) {return BufferedTransformation::CreatePutSpace(size);} -}; - -//! string-based implementation of Store interface -class StringStore : public Store -{ -public: - StringStore(const char *string = NULL) - {StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string)));} - StringStore(const byte *string, size_t length) - {StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));} - template StringStore(const T &string) - {StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string)));} - - CRYPTOPP_DLL size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); - CRYPTOPP_DLL size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const; - -private: - CRYPTOPP_DLL void StoreInitialize(const NameValuePairs ¶meters); - - const byte *m_store; - size_t m_length, m_count; -}; - -//! RNG-based implementation of Source interface -class CRYPTOPP_DLL RandomNumberStore : public Store -{ -public: - RandomNumberStore() - : m_rng(NULL), m_length(0), m_count(0) {} - - RandomNumberStore(RandomNumberGenerator &rng, lword length) - : m_rng(&rng), m_length(length), m_count(0) {} - - bool AnyRetrievable() const {return MaxRetrievable() != 0;} - lword MaxRetrievable() const {return m_length-m_count;} - - size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); - size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const - { - throw NotImplemented("RandomNumberStore: CopyRangeTo2() is not supported by this store"); - } - -private: - void StoreInitialize(const NameValuePairs ¶meters); - - RandomNumberGenerator *m_rng; - lword m_length, m_count; -}; - -//! empty store -class CRYPTOPP_DLL NullStore : public Store -{ -public: - NullStore(lword size = ULONG_MAX) : m_size(size) {} - void StoreInitialize(const NameValuePairs ¶meters) {} - lword MaxRetrievable() const {return m_size;} - size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); - size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const; - -private: - lword m_size; -}; - -//! A Filter that pumps data into its attachment as input -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Source : public InputRejecting -{ -public: - Source(BufferedTransformation *attachment = NULL) - {Source::Detach(attachment);} - - lword Pump(lword pumpMax=size_t(0)-1) - {Pump2(pumpMax); return pumpMax;} - unsigned int PumpMessages(unsigned int count=UINT_MAX) - {PumpMessages2(count); return count;} - void PumpAll() - {PumpAll2();} - virtual size_t Pump2(lword &byteCount, bool blocking=true) =0; - virtual size_t PumpMessages2(unsigned int &messageCount, bool blocking=true) =0; - virtual size_t PumpAll2(bool blocking=true); - virtual bool SourceExhausted() const =0; - -protected: - void SourceInitialize(bool pumpAll, const NameValuePairs ¶meters) - { - IsolatedInitialize(parameters); - if (pumpAll) - PumpAll(); - } -}; - -//! Turn a Store into a Source -template -class SourceTemplate : public Source -{ -public: - SourceTemplate(BufferedTransformation *attachment) - : Source(attachment) {} - void IsolatedInitialize(const NameValuePairs ¶meters) - {m_store.IsolatedInitialize(parameters);} - size_t Pump2(lword &byteCount, bool blocking=true) - {return m_store.TransferTo2(*AttachedTransformation(), byteCount, DEFAULT_CHANNEL, blocking);} - size_t PumpMessages2(unsigned int &messageCount, bool blocking=true) - {return m_store.TransferMessagesTo2(*AttachedTransformation(), messageCount, DEFAULT_CHANNEL, blocking);} - size_t PumpAll2(bool blocking=true) - {return m_store.TransferAllTo2(*AttachedTransformation(), DEFAULT_CHANNEL, blocking);} - bool SourceExhausted() const - {return !m_store.AnyRetrievable() && !m_store.AnyMessages();} - void SetAutoSignalPropagation(int propagation) - {m_store.SetAutoSignalPropagation(propagation);} - int GetAutoSignalPropagation() const - {return m_store.GetAutoSignalPropagation();} - -protected: - T m_store; -}; - -//! string-based implementation of Source interface -class CRYPTOPP_DLL StringSource : public SourceTemplate -{ -public: - StringSource(BufferedTransformation *attachment = NULL) - : SourceTemplate(attachment) {} - //! zero terminated string as source - StringSource(const char *string, bool pumpAll, BufferedTransformation *attachment = NULL) - : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));} - //! binary byte array as source - StringSource(const byte *string, size_t length, bool pumpAll, BufferedTransformation *attachment = NULL) - : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));} - //! std::string as source - StringSource(const std::string &string, bool pumpAll, BufferedTransformation *attachment = NULL) - : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));} -}; - -//! use the third constructor for an array source -typedef StringSource ArraySource; - -//! RNG-based implementation of Source interface -class CRYPTOPP_DLL RandomNumberSource : public SourceTemplate -{ -public: - RandomNumberSource(RandomNumberGenerator &rng, int length, bool pumpAll, BufferedTransformation *attachment = NULL) - : SourceTemplate(attachment) - {SourceInitialize(pumpAll, MakeParameters("RandomNumberGeneratorPointer", &rng)("RandomNumberStoreSize", length));} -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/fips140.cpp b/embeddedcryptopp/fips140.cpp deleted file mode 100644 index 1fcf590..0000000 --- a/embeddedcryptopp/fips140.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// fips140.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "fips140.h" -#include "trdlocal.h" // needs to be included last for cygwin - -NAMESPACE_BEGIN(CryptoPP) - -// Define this to 1 to turn on FIPS 140-2 compliance features, including additional tests during -// startup, random number generation, and key generation. These tests may affect performance. -#ifndef CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 -#define CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 0 -#endif - -#if (CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 && !defined(THREADS_AVAILABLE)) -#error FIPS 140-2 compliance requires the availability of thread local storage. -#endif - -#if (CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 && !defined(OS_RNG_AVAILABLE)) -#error FIPS 140-2 compliance requires the availability of OS provided RNG. -#endif - -PowerUpSelfTestStatus g_powerUpSelfTestStatus = POWER_UP_SELF_TEST_NOT_DONE; - -bool FIPS_140_2_ComplianceEnabled() -{ - return CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2; -} - -void SimulatePowerUpSelfTestFailure() -{ - g_powerUpSelfTestStatus = POWER_UP_SELF_TEST_FAILED; -} - -PowerUpSelfTestStatus CRYPTOPP_API GetPowerUpSelfTestStatus() -{ - return g_powerUpSelfTestStatus; -} - -#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 -ThreadLocalStorage & AccessPowerUpSelfTestInProgress() -{ - static ThreadLocalStorage selfTestInProgress; - return selfTestInProgress; -} -#endif - -bool PowerUpSelfTestInProgressOnThisThread() -{ -#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 - return AccessPowerUpSelfTestInProgress().GetValue() != NULL; -#else - assert(false); // should not be called - return false; -#endif -} - -void SetPowerUpSelfTestInProgressOnThisThread(bool inProgress) -{ -#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 - AccessPowerUpSelfTestInProgress().SetValue((void *)inProgress); -#endif -} - -void EncryptionPairwiseConsistencyTest_FIPS_140_Only(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor) -{ -#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 - EncryptionPairwiseConsistencyTest(encryptor, decryptor); -#endif -} - -void SignaturePairwiseConsistencyTest_FIPS_140_Only(const PK_Signer &signer, const PK_Verifier &verifier) -{ -#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 - SignaturePairwiseConsistencyTest(signer, verifier); -#endif -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/fips140.h b/embeddedcryptopp/fips140.h deleted file mode 100644 index a3e5386..0000000 --- a/embeddedcryptopp/fips140.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef CRYPTOPP_FIPS140_H -#define CRYPTOPP_FIPS140_H - -/*! \file - FIPS 140 related functions and classes. -*/ - -#include "cryptlib.h" -#include "secblock.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! exception thrown when a crypto algorithm is used after a self test fails -class CRYPTOPP_DLL SelfTestFailure : public Exception -{ -public: - explicit SelfTestFailure(const std::string &s) : Exception(OTHER_ERROR, s) {} -}; - -//! returns whether FIPS 140-2 compliance features were enabled at compile time -CRYPTOPP_DLL bool CRYPTOPP_API FIPS_140_2_ComplianceEnabled(); - -//! enum values representing status of the power-up self test -enum PowerUpSelfTestStatus {POWER_UP_SELF_TEST_NOT_DONE, POWER_UP_SELF_TEST_FAILED, POWER_UP_SELF_TEST_PASSED}; - -//! perform the power-up self test, and set the self test status -CRYPTOPP_DLL void CRYPTOPP_API DoPowerUpSelfTest(const char *moduleFilename, const byte *expectedModuleMac); - -//! perform the power-up self test using the filename of this DLL and the embedded module MAC -CRYPTOPP_DLL void CRYPTOPP_API DoDllPowerUpSelfTest(); - -//! set the power-up self test status to POWER_UP_SELF_TEST_FAILED -CRYPTOPP_DLL void CRYPTOPP_API SimulatePowerUpSelfTestFailure(); - -//! return the current power-up self test status -CRYPTOPP_DLL PowerUpSelfTestStatus CRYPTOPP_API GetPowerUpSelfTestStatus(); - -typedef PowerUpSelfTestStatus (CRYPTOPP_API * PGetPowerUpSelfTestStatus)(); - -CRYPTOPP_DLL MessageAuthenticationCode * CRYPTOPP_API NewIntegrityCheckingMAC(); - -CRYPTOPP_DLL bool CRYPTOPP_API IntegrityCheckModule(const char *moduleFilename, const byte *expectedModuleMac, SecByteBlock *pActualMac = NULL, unsigned long *pMacFileLocation = NULL); - -// this is used by Algorithm constructor to allow Algorithm objects to be constructed for the self test -bool PowerUpSelfTestInProgressOnThisThread(); - -void SetPowerUpSelfTestInProgressOnThisThread(bool inProgress); - -void SignaturePairwiseConsistencyTest(const PK_Signer &signer, const PK_Verifier &verifier); -void EncryptionPairwiseConsistencyTest(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor); - -void SignaturePairwiseConsistencyTest_FIPS_140_Only(const PK_Signer &signer, const PK_Verifier &verifier); -void EncryptionPairwiseConsistencyTest_FIPS_140_Only(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor); - -#define CRYPTOPP_DUMMY_DLL_MAC "MAC_51f34b8db820ae8" - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/fltrimpl.h b/embeddedcryptopp/fltrimpl.h deleted file mode 100644 index 4087d7d..0000000 --- a/embeddedcryptopp/fltrimpl.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef CRYPTOPP_FLTRIMPL_H -#define CRYPTOPP_FLTRIMPL_H - -#define FILTER_BEGIN \ - switch (m_continueAt) \ - { \ - case 0: \ - m_inputPosition = 0; - -#define FILTER_END_NO_MESSAGE_END_NO_RETURN \ - break; \ - default: \ - assert(false); \ - } - -#define FILTER_END_NO_MESSAGE_END \ - FILTER_END_NO_MESSAGE_END_NO_RETURN \ - return 0; - -/* -#define FILTER_END \ - case -1: \ - if (messageEnd && Output(-1, NULL, 0, messageEnd, blocking)) \ - return 1; \ - FILTER_END_NO_MESSAGE_END -*/ - -#define FILTER_OUTPUT3(site, statement, output, length, messageEnd, channel) \ - {\ - case site: \ - statement; \ - if (Output(site, output, length, messageEnd, blocking, channel)) \ - return STDMAX(size_t(1), length-m_inputPosition);\ - } - -#define FILTER_OUTPUT2(site, statement, output, length, messageEnd) \ - FILTER_OUTPUT3(site, statement, output, length, messageEnd, DEFAULT_CHANNEL) - -#define FILTER_OUTPUT(site, output, length, messageEnd) \ - FILTER_OUTPUT2(site, 0, output, length, messageEnd) - -#define FILTER_OUTPUT_BYTE(site, output) \ - FILTER_OUTPUT(site, &(const byte &)(byte)output, 1, 0) - -#define FILTER_OUTPUT2_MODIFIABLE(site, statement, output, length, messageEnd) \ - {\ - case site: \ - statement; \ - if (OutputModifiable(site, output, length, messageEnd, blocking)) \ - return STDMAX(size_t(1), length-m_inputPosition);\ - } - -#define FILTER_OUTPUT_MODIFIABLE(site, output, length, messageEnd) \ - FILTER_OUTPUT2_MODIFIABLE(site, 0, output, length, messageEnd) - -#define FILTER_OUTPUT2_MAYBE_MODIFIABLE(site, statement, output, length, messageEnd, modifiable) \ - {\ - case site: \ - statement; \ - if (modifiable ? OutputModifiable(site, output, length, messageEnd, blocking) : Output(site, output, length, messageEnd, blocking)) \ - return STDMAX(size_t(1), length-m_inputPosition);\ - } - -#define FILTER_OUTPUT_MAYBE_MODIFIABLE(site, output, length, messageEnd, modifiable) \ - FILTER_OUTPUT2_MAYBE_MODIFIABLE(site, 0, output, length, messageEnd, modifiable) - -#endif diff --git a/embeddedcryptopp/gcm.h b/embeddedcryptopp/gcm.h deleted file mode 100644 index 851ae80..0000000 --- a/embeddedcryptopp/gcm.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef CRYPTOPP_GCM_H -#define CRYPTOPP_GCM_H - -#include "authenc.h" -#include "modes.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! . -enum GCM_TablesOption {GCM_2K_Tables, GCM_64K_Tables}; - -//! . -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE GCM_Base : public AuthenticatedSymmetricCipherBase -{ -public: - // AuthenticatedSymmetricCipher - std::string AlgorithmName() const - {return GetBlockCipher().AlgorithmName() + std::string("/GCM");} - size_t MinKeyLength() const - {return GetBlockCipher().MinKeyLength();} - size_t MaxKeyLength() const - {return GetBlockCipher().MaxKeyLength();} - size_t DefaultKeyLength() const - {return GetBlockCipher().DefaultKeyLength();} - size_t GetValidKeyLength(size_t n) const - {return GetBlockCipher().GetValidKeyLength(n);} - bool IsValidKeyLength(size_t n) const - {return GetBlockCipher().IsValidKeyLength(n);} - unsigned int OptimalDataAlignment() const; - IV_Requirement IVRequirement() const - {return UNIQUE_IV;} - unsigned int IVSize() const - {return 12;} - unsigned int MinIVLength() const - {return 1;} - unsigned int MaxIVLength() const - {return UINT_MAX;} // (W64LIT(1)<<61)-1 in the standard - unsigned int DigestSize() const - {return 16;} - lword MaxHeaderLength() const - {return (W64LIT(1)<<61)-1;} - lword MaxMessageLength() const - {return ((W64LIT(1)<<39)-256)/8;} - -protected: - // AuthenticatedSymmetricCipherBase - bool AuthenticationIsOnPlaintext() const - {return false;} - unsigned int AuthenticationBlockSize() const - {return HASH_BLOCKSIZE;} - void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms); - void Resync(const byte *iv, size_t len); - size_t AuthenticateBlocks(const byte *data, size_t len); - void AuthenticateLastHeaderBlock(); - void AuthenticateLastConfidentialBlock(); - void AuthenticateLastFooterBlock(byte *mac, size_t macSize); - SymmetricCipher & AccessSymmetricCipher() {return m_ctr;} - - virtual BlockCipher & AccessBlockCipher() =0; - virtual GCM_TablesOption GetTablesOption() const =0; - - const BlockCipher & GetBlockCipher() const {return const_cast(this)->AccessBlockCipher();}; - byte *HashBuffer() {return m_buffer+REQUIRED_BLOCKSIZE;} - byte *HashKey() {return m_buffer+2*REQUIRED_BLOCKSIZE;} - byte *MulTable() {return m_buffer+3*REQUIRED_BLOCKSIZE;} - - class GCTR : public CTR_Mode_ExternalCipher::Encryption - { - protected: - void IncrementCounterBy256(); - }; - - GCTR m_ctr; - static word16 s_reductionTable[256]; - static bool s_reductionTableInitialized; - enum {REQUIRED_BLOCKSIZE = 16, HASH_BLOCKSIZE = 16}; -}; - -//! . -template -class GCM_Final : public GCM_Base -{ -public: - static std::string StaticAlgorithmName() - {return T_BlockCipher::StaticAlgorithmName() + std::string("/GCM");} - bool IsForwardTransformation() const - {return T_IsEncryption;} - -private: - GCM_TablesOption GetTablesOption() const {return T_TablesOption;} - BlockCipher & AccessBlockCipher() {return m_cipher;} - typename T_BlockCipher::Encryption m_cipher; -}; - -//! GCM -template -struct GCM : public AuthenticatedSymmetricCipherDocumentation -{ - typedef GCM_Final Encryption; - typedef GCM_Final Decryption; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/gf2n.cpp b/embeddedcryptopp/gf2n.cpp deleted file mode 100644 index 0fac46a..0000000 --- a/embeddedcryptopp/gf2n.cpp +++ /dev/null @@ -1,879 +0,0 @@ -// gf2n.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "gf2n.h" -#include "algebra.h" -#include "words.h" -#include "randpool.h" -#include "asn.h" -#include "oids.h" - -#include - -NAMESPACE_BEGIN(CryptoPP) - -PolynomialMod2::PolynomialMod2() -{ -} - -PolynomialMod2::PolynomialMod2(word value, size_t bitLength) - : reg(BitsToWords(bitLength)) -{ - assert(value==0 || reg.size()>0); - - if (reg.size() > 0) - { - reg[0] = value; - SetWords(reg+1, 0, reg.size()-1); - } -} - -PolynomialMod2::PolynomialMod2(const PolynomialMod2& t) - : reg(t.reg.size()) -{ - CopyWords(reg, t.reg, reg.size()); -} - -void PolynomialMod2::Randomize(RandomNumberGenerator &rng, size_t nbits) -{ - const size_t nbytes = nbits/8 + 1; - SecByteBlock buf(nbytes); - rng.GenerateBlock(buf, nbytes); - buf[0] = (byte)Crop(buf[0], nbits % 8); - Decode(buf, nbytes); -} - -PolynomialMod2 PolynomialMod2::AllOnes(size_t bitLength) -{ - PolynomialMod2 result((word)0, bitLength); - SetWords(result.reg, ~(word)0, result.reg.size()); - if (bitLength%WORD_BITS) - result.reg[result.reg.size()-1] = (word)Crop(result.reg[result.reg.size()-1], bitLength%WORD_BITS); - return result; -} - -void PolynomialMod2::SetBit(size_t n, int value) -{ - if (value) - { - reg.CleanGrow(n/WORD_BITS + 1); - reg[n/WORD_BITS] |= (word(1) << (n%WORD_BITS)); - } - else - { - if (n/WORD_BITS < reg.size()) - reg[n/WORD_BITS] &= ~(word(1) << (n%WORD_BITS)); - } -} - -byte PolynomialMod2::GetByte(size_t n) const -{ - if (n/WORD_SIZE >= reg.size()) - return 0; - else - return byte(reg[n/WORD_SIZE] >> ((n%WORD_SIZE)*8)); -} - -void PolynomialMod2::SetByte(size_t n, byte value) -{ - reg.CleanGrow(BytesToWords(n+1)); - reg[n/WORD_SIZE] &= ~(word(0xff) << 8*(n%WORD_SIZE)); - reg[n/WORD_SIZE] |= (word(value) << 8*(n%WORD_SIZE)); -} - -PolynomialMod2 PolynomialMod2::Monomial(size_t i) -{ - PolynomialMod2 r((word)0, i+1); - r.SetBit(i); - return r; -} - -PolynomialMod2 PolynomialMod2::Trinomial(size_t t0, size_t t1, size_t t2) -{ - PolynomialMod2 r((word)0, t0+1); - r.SetBit(t0); - r.SetBit(t1); - r.SetBit(t2); - return r; -} - -PolynomialMod2 PolynomialMod2::Pentanomial(size_t t0, size_t t1, size_t t2, size_t t3, size_t t4) -{ - PolynomialMod2 r((word)0, t0+1); - r.SetBit(t0); - r.SetBit(t1); - r.SetBit(t2); - r.SetBit(t3); - r.SetBit(t4); - return r; -} - -template -struct NewPolynomialMod2 -{ - PolynomialMod2 * operator()() const - { - return new PolynomialMod2(i); - } -}; - -const PolynomialMod2 &PolynomialMod2::Zero() -{ - return Singleton().Ref(); -} - -const PolynomialMod2 &PolynomialMod2::One() -{ - return Singleton >().Ref(); -} - -void PolynomialMod2::Decode(const byte *input, size_t inputLen) -{ - StringStore store(input, inputLen); - Decode(store, inputLen); -} - -void PolynomialMod2::Encode(byte *output, size_t outputLen) const -{ - ArraySink sink(output, outputLen); - Encode(sink, outputLen); -} - -void PolynomialMod2::Decode(BufferedTransformation &bt, size_t inputLen) -{ - reg.CleanNew(BytesToWords(inputLen)); - - for (size_t i=inputLen; i > 0; i--) - { - byte b; - bt.Get(b); - reg[(i-1)/WORD_SIZE] |= word(b) << ((i-1)%WORD_SIZE)*8; - } -} - -void PolynomialMod2::Encode(BufferedTransformation &bt, size_t outputLen) const -{ - for (size_t i=outputLen; i > 0; i--) - bt.Put(GetByte(i-1)); -} - -void PolynomialMod2::DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const -{ - DERGeneralEncoder enc(bt, OCTET_STRING); - Encode(enc, length); - enc.MessageEnd(); -} - -void PolynomialMod2::BERDecodeAsOctetString(BufferedTransformation &bt, size_t length) -{ - BERGeneralDecoder dec(bt, OCTET_STRING); - if (!dec.IsDefiniteLength() || dec.RemainingLength() != length) - BERDecodeError(); - Decode(dec, length); - dec.MessageEnd(); -} - -unsigned int PolynomialMod2::WordCount() const -{ - return (unsigned int)CountWords(reg, reg.size()); -} - -unsigned int PolynomialMod2::ByteCount() const -{ - unsigned wordCount = WordCount(); - if (wordCount) - return (wordCount-1)*WORD_SIZE + BytePrecision(reg[wordCount-1]); - else - return 0; -} - -unsigned int PolynomialMod2::BitCount() const -{ - unsigned wordCount = WordCount(); - if (wordCount) - return (wordCount-1)*WORD_BITS + BitPrecision(reg[wordCount-1]); - else - return 0; -} - -unsigned int PolynomialMod2::Parity() const -{ - unsigned i; - word temp=0; - for (i=0; i= reg.size()) - { - PolynomialMod2 result((word)0, b.reg.size()*WORD_BITS); - XorWords(result.reg, reg, b.reg, reg.size()); - CopyWords(result.reg+reg.size(), b.reg+reg.size(), b.reg.size()-reg.size()); - return result; - } - else - { - PolynomialMod2 result((word)0, reg.size()*WORD_BITS); - XorWords(result.reg, reg, b.reg, b.reg.size()); - CopyWords(result.reg+b.reg.size(), reg+b.reg.size(), reg.size()-b.reg.size()); - return result; - } -} - -PolynomialMod2 PolynomialMod2::And(const PolynomialMod2 &b) const -{ - PolynomialMod2 result((word)0, WORD_BITS*STDMIN(reg.size(), b.reg.size())); - AndWords(result.reg, reg, b.reg, result.reg.size()); - return result; -} - -PolynomialMod2 PolynomialMod2::Times(const PolynomialMod2 &b) const -{ - PolynomialMod2 result((word)0, BitCount() + b.BitCount()); - - for (int i=b.Degree(); i>=0; i--) - { - result <<= 1; - if (b[i]) - XorWords(result.reg, reg, reg.size()); - } - return result; -} - -PolynomialMod2 PolynomialMod2::Squared() const -{ - static const word map[16] = {0, 1, 4, 5, 16, 17, 20, 21, 64, 65, 68, 69, 80, 81, 84, 85}; - - PolynomialMod2 result((word)0, 2*reg.size()*WORD_BITS); - - for (unsigned i=0; i> (j/2)) % 16] << j; - - for (j=0; j> (j/2 + WORD_BITS/2)) % 16] << j; - } - - return result; -} - -void PolynomialMod2::Divide(PolynomialMod2 &remainder, PolynomialMod2 "ient, - const PolynomialMod2 ÷nd, const PolynomialMod2 &divisor) -{ - if (!divisor) - throw PolynomialMod2::DivideByZero(); - - int degree = divisor.Degree(); - remainder.reg.CleanNew(BitsToWords(degree+1)); - if (dividend.BitCount() >= divisor.BitCount()) - quotient.reg.CleanNew(BitsToWords(dividend.BitCount() - divisor.BitCount() + 1)); - else - quotient.reg.CleanNew(0); - - for (int i=dividend.Degree(); i>=0; i--) - { - remainder <<= 1; - remainder.reg[0] |= dividend[i]; - if (remainder[degree]) - { - remainder -= divisor; - quotient.SetBit(i); - } - } -} - -PolynomialMod2 PolynomialMod2::DividedBy(const PolynomialMod2 &b) const -{ - PolynomialMod2 remainder, quotient; - PolynomialMod2::Divide(remainder, quotient, *this, b); - return quotient; -} - -PolynomialMod2 PolynomialMod2::Modulo(const PolynomialMod2 &b) const -{ - PolynomialMod2 remainder, quotient; - PolynomialMod2::Divide(remainder, quotient, *this, b); - return remainder; -} - -PolynomialMod2& PolynomialMod2::operator<<=(unsigned int n) -{ - if (!reg.size()) - return *this; - - int i; - word u; - word carry=0; - word *r=reg; - - if (n==1) // special case code for most frequent case - { - i = (int)reg.size(); - while (i--) - { - u = *r; - *r = (u << 1) | carry; - carry = u >> (WORD_BITS-1); - r++; - } - - if (carry) - { - reg.Grow(reg.size()+1); - reg[reg.size()-1] = carry; - } - - return *this; - } - - int shiftWords = n / WORD_BITS; - int shiftBits = n % WORD_BITS; - - if (shiftBits) - { - i = (int)reg.size(); - while (i--) - { - u = *r; - *r = (u << shiftBits) | carry; - carry = u >> (WORD_BITS-shiftBits); - r++; - } - } - - if (carry) - { - reg.Grow(reg.size()+shiftWords+1); - reg[reg.size()-1] = carry; - } - else - reg.Grow(reg.size()+shiftWords); - - if (shiftWords) - { - for (i = (int)reg.size()-1; i>=shiftWords; i--) - reg[i] = reg[i-shiftWords]; - for (; i>=0; i--) - reg[i] = 0; - } - - return *this; -} - -PolynomialMod2& PolynomialMod2::operator>>=(unsigned int n) -{ - if (!reg.size()) - return *this; - - int shiftWords = n / WORD_BITS; - int shiftBits = n % WORD_BITS; - - size_t i; - word u; - word carry=0; - word *r=reg+reg.size()-1; - - if (shiftBits) - { - i = reg.size(); - while (i--) - { - u = *r; - *r = (u >> shiftBits) | carry; - carry = u << (WORD_BITS-shiftBits); - r--; - } - } - - if (shiftWords) - { - for (i=0; i>(unsigned int n) const -{ - PolynomialMod2 result(*this); - return result>>=n; -} - -bool PolynomialMod2::operator!() const -{ - for (unsigned i=0; i s(a.BitCount()/bits+1); - unsigned i; - const char vec[]="0123456789ABCDEF"; - - for (i=0; i*bits < a.BitCount(); i++) - { - int digit=0; - for (int j=0; j().Gcd(a, b); -} - -PolynomialMod2 PolynomialMod2::InverseMod(const PolynomialMod2 &modulus) const -{ - typedef EuclideanDomainOf Domain; - return QuotientRing(Domain(), modulus).MultiplicativeInverse(*this); -} - -bool PolynomialMod2::IsIrreducible() const -{ - signed int d = Degree(); - if (d <= 0) - return false; - - PolynomialMod2 t(2), u(t); - for (int i=1; i<=d/2; i++) - { - u = u.Squared()%(*this); - if (!Gcd(u+t, *this).IsUnit()) - return false; - } - return true; -} - -// ******************************************************** - -GF2NP::GF2NP(const PolynomialMod2 &modulus) - : QuotientRing >(EuclideanDomainOf(), modulus), m(modulus.Degree()) -{ -} - -GF2NP::Element GF2NP::SquareRoot(const Element &a) const -{ - Element r = a; - for (unsigned int i=1; i t1 && t1 > t2 && t2==0); -} - -const GF2NT::Element& GF2NT::MultiplicativeInverse(const Element &a) const -{ - if (t0-t1 < WORD_BITS) - return GF2NP::MultiplicativeInverse(a); - - SecWordBlock T(m_modulus.reg.size() * 4); - word *b = T; - word *c = T+m_modulus.reg.size(); - word *f = T+2*m_modulus.reg.size(); - word *g = T+3*m_modulus.reg.size(); - size_t bcLen=1, fgLen=m_modulus.reg.size(); - unsigned int k=0; - - SetWords(T, 0, 3*m_modulus.reg.size()); - b[0]=1; - assert(a.reg.size() <= m_modulus.reg.size()); - CopyWords(f, a.reg, a.reg.size()); - CopyWords(g, m_modulus.reg, m_modulus.reg.size()); - - while (1) - { - word t=f[0]; - while (!t) - { - ShiftWordsRightByWords(f, fgLen, 1); - if (c[bcLen-1]) - bcLen++; - assert(bcLen <= m_modulus.reg.size()); - ShiftWordsLeftByWords(c, bcLen, 1); - k+=WORD_BITS; - t=f[0]; - } - - unsigned int i=0; - while (t%2 == 0) - { - t>>=1; - i++; - } - k+=i; - - if (t==1 && CountWords(f, fgLen)==1) - break; - - if (i==1) - { - ShiftWordsRightByBits(f, fgLen, 1); - t=ShiftWordsLeftByBits(c, bcLen, 1); - } - else - { - ShiftWordsRightByBits(f, fgLen, i); - t=ShiftWordsLeftByBits(c, bcLen, i); - } - if (t) - { - c[bcLen] = t; - bcLen++; - assert(bcLen <= m_modulus.reg.size()); - } - - if (f[fgLen-1]==0 && g[fgLen-1]==0) - fgLen--; - - if (f[fgLen-1] < g[fgLen-1]) - { - std::swap(f, g); - std::swap(b, c); - } - - XorWords(f, g, fgLen); - XorWords(b, c, bcLen); - } - - while (k >= WORD_BITS) - { - word temp = b[0]; - // right shift b - for (unsigned i=0; i+1> j) & 1) << (t1 + j); - else - b[t1/WORD_BITS-1] ^= temp << t1%WORD_BITS; - - if (t1 % WORD_BITS) - b[t1/WORD_BITS] ^= temp >> (WORD_BITS - t1%WORD_BITS); - - if (t0%WORD_BITS) - { - b[t0/WORD_BITS-1] ^= temp << t0%WORD_BITS; - b[t0/WORD_BITS] ^= temp >> (WORD_BITS - t0%WORD_BITS); - } - else - b[t0/WORD_BITS-1] ^= temp; - - k -= WORD_BITS; - } - - if (k) - { - word temp = b[0] << (WORD_BITS - k); - ShiftWordsRightByBits(b, BitsToWords(m), k); - - if (t1 < WORD_BITS) - for (unsigned int j=0; j> j) & 1) << (t1 + j); - else - b[t1/WORD_BITS-1] ^= temp << t1%WORD_BITS; - - if (t1 % WORD_BITS) - b[t1/WORD_BITS] ^= temp >> (WORD_BITS - t1%WORD_BITS); - - if (t0%WORD_BITS) - { - b[t0/WORD_BITS-1] ^= temp << t0%WORD_BITS; - b[t0/WORD_BITS] ^= temp >> (WORD_BITS - t0%WORD_BITS); - } - else - b[t0/WORD_BITS-1] ^= temp; - } - - CopyWords(result.reg.begin(), b, result.reg.size()); - return result; -} - -const GF2NT::Element& GF2NT::Multiply(const Element &a, const Element &b) const -{ - size_t aSize = STDMIN(a.reg.size(), result.reg.size()); - Element r((word)0, m); - - for (int i=m-1; i>=0; i--) - { - if (r[m-1]) - { - ShiftWordsLeftByBits(r.reg.begin(), r.reg.size(), 1); - XorWords(r.reg.begin(), m_modulus.reg, r.reg.size()); - } - else - ShiftWordsLeftByBits(r.reg.begin(), r.reg.size(), 1); - - if (b[i]) - XorWords(r.reg.begin(), a.reg, aSize); - } - - if (m%WORD_BITS) - r.reg.begin()[r.reg.size()-1] = (word)Crop(r.reg[r.reg.size()-1], m%WORD_BITS); - - CopyWords(result.reg.begin(), r.reg.begin(), result.reg.size()); - return result; -} - -const GF2NT::Element& GF2NT::Reduced(const Element &a) const -{ - if (t0-t1 < WORD_BITS) - return m_domain.Mod(a, m_modulus); - - SecWordBlock b(a.reg); - - size_t i; - for (i=b.size()-1; i>=BitsToWords(t0); i--) - { - word temp = b[i]; - - if (t0%WORD_BITS) - { - b[i-t0/WORD_BITS] ^= temp >> t0%WORD_BITS; - b[i-t0/WORD_BITS-1] ^= temp << (WORD_BITS - t0%WORD_BITS); - } - else - b[i-t0/WORD_BITS] ^= temp; - - if ((t0-t1)%WORD_BITS) - { - b[i-(t0-t1)/WORD_BITS] ^= temp >> (t0-t1)%WORD_BITS; - b[i-(t0-t1)/WORD_BITS-1] ^= temp << (WORD_BITS - (t0-t1)%WORD_BITS); - } - else - b[i-(t0-t1)/WORD_BITS] ^= temp; - } - - if (i==BitsToWords(t0)-1 && t0%WORD_BITS) - { - word mask = ((word)1<<(t0%WORD_BITS))-1; - word temp = b[i] & ~mask; - b[i] &= mask; - - b[i-t0/WORD_BITS] ^= temp >> t0%WORD_BITS; - - if ((t0-t1)%WORD_BITS) - { - b[i-(t0-t1)/WORD_BITS] ^= temp >> (t0-t1)%WORD_BITS; - if ((t0-t1)%WORD_BITS > t0%WORD_BITS) - b[i-(t0-t1)/WORD_BITS-1] ^= temp << (WORD_BITS - (t0-t1)%WORD_BITS); - else - assert(temp << (WORD_BITS - (t0-t1)%WORD_BITS) == 0); - } - else - b[i-(t0-t1)/WORD_BITS] ^= temp; - } - - SetWords(result.reg.begin(), 0, result.reg.size()); - CopyWords(result.reg.begin(), b, STDMIN(b.size(), result.reg.size())); - return result; -} - -void GF2NP::DEREncodeElement(BufferedTransformation &out, const Element &a) const -{ - a.DEREncodeAsOctetString(out, MaxElementByteLength()); -} - -void GF2NP::BERDecodeElement(BufferedTransformation &in, Element &a) const -{ - a.BERDecodeAsOctetString(in, MaxElementByteLength()); -} - -void GF2NT::DEREncode(BufferedTransformation &bt) const -{ - DERSequenceEncoder seq(bt); - ASN1::characteristic_two_field().DEREncode(seq); - DERSequenceEncoder parameters(seq); - DEREncodeUnsigned(parameters, m); - ASN1::tpBasis().DEREncode(parameters); - DEREncodeUnsigned(parameters, t1); - parameters.MessageEnd(); - seq.MessageEnd(); -} - -void GF2NPP::DEREncode(BufferedTransformation &bt) const -{ - DERSequenceEncoder seq(bt); - ASN1::characteristic_two_field().DEREncode(seq); - DERSequenceEncoder parameters(seq); - DEREncodeUnsigned(parameters, m); - ASN1::ppBasis().DEREncode(parameters); - DERSequenceEncoder pentanomial(parameters); - DEREncodeUnsigned(pentanomial, t3); - DEREncodeUnsigned(pentanomial, t2); - DEREncodeUnsigned(pentanomial, t1); - pentanomial.MessageEnd(); - parameters.MessageEnd(); - seq.MessageEnd(); -} - -GF2NP * BERDecodeGF2NP(BufferedTransformation &bt) -{ - // VC60 workaround: auto_ptr lacks reset() - member_ptr result; - - BERSequenceDecoder seq(bt); - if (OID(seq) != ASN1::characteristic_two_field()) - BERDecodeError(); - BERSequenceDecoder parameters(seq); - unsigned int m; - BERDecodeUnsigned(parameters, m); - OID oid(parameters); - if (oid == ASN1::tpBasis()) - { - unsigned int t1; - BERDecodeUnsigned(parameters, t1); - result.reset(new GF2NT(m, t1, 0)); - } - else if (oid == ASN1::ppBasis()) - { - unsigned int t1, t2, t3; - BERSequenceDecoder pentanomial(parameters); - BERDecodeUnsigned(pentanomial, t3); - BERDecodeUnsigned(pentanomial, t2); - BERDecodeUnsigned(pentanomial, t1); - pentanomial.MessageEnd(); - result.reset(new GF2NPP(m, t3, t2, t1, 0)); - } - else - { - BERDecodeError(); - return NULL; - } - parameters.MessageEnd(); - seq.MessageEnd(); - - return result.release(); -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/gf2n.h b/embeddedcryptopp/gf2n.h deleted file mode 100644 index 67ade64..0000000 --- a/embeddedcryptopp/gf2n.h +++ /dev/null @@ -1,369 +0,0 @@ -#ifndef CRYPTOPP_GF2N_H -#define CRYPTOPP_GF2N_H - -/*! \file */ - -#include "cryptlib.h" -#include "secblock.h" -#include "misc.h" -#include "algebra.h" - -#include - -NAMESPACE_BEGIN(CryptoPP) - -//! Polynomial with Coefficients in GF(2) -/*! \nosubgrouping */ -class CRYPTOPP_DLL PolynomialMod2 -{ -public: - //! \name ENUMS, EXCEPTIONS, and TYPEDEFS - //@{ - //! divide by zero exception - class DivideByZero : public Exception - { - public: - DivideByZero() : Exception(OTHER_ERROR, "PolynomialMod2: division by zero") {} - }; - - typedef unsigned int RandomizationParameter; - //@} - - //! \name CREATORS - //@{ - //! creates the zero polynomial - PolynomialMod2(); - //! copy constructor - PolynomialMod2(const PolynomialMod2& t); - - //! convert from word - /*! value should be encoded with the least significant bit as coefficient to x^0 - and most significant bit as coefficient to x^(WORD_BITS-1) - bitLength denotes how much memory to allocate initially - */ - PolynomialMod2(word value, size_t bitLength=WORD_BITS); - - //! convert from big-endian byte array - PolynomialMod2(const byte *encodedPoly, size_t byteCount) - {Decode(encodedPoly, byteCount);} - - //! convert from big-endian form stored in a BufferedTransformation - PolynomialMod2(BufferedTransformation &encodedPoly, size_t byteCount) - {Decode(encodedPoly, byteCount);} - - //! create a random polynomial uniformly distributed over all polynomials with degree less than bitcount - PolynomialMod2(RandomNumberGenerator &rng, size_t bitcount) - {Randomize(rng, bitcount);} - - //! return x^i - static PolynomialMod2 CRYPTOPP_API Monomial(size_t i); - //! return x^t0 + x^t1 + x^t2 - static PolynomialMod2 CRYPTOPP_API Trinomial(size_t t0, size_t t1, size_t t2); - //! return x^t0 + x^t1 + x^t2 + x^t3 + x^t4 - static PolynomialMod2 CRYPTOPP_API Pentanomial(size_t t0, size_t t1, size_t t2, size_t t3, size_t t4); - //! return x^(n-1) + ... + x + 1 - static PolynomialMod2 CRYPTOPP_API AllOnes(size_t n); - - //! - static const PolynomialMod2 & CRYPTOPP_API Zero(); - //! - static const PolynomialMod2 & CRYPTOPP_API One(); - //@} - - //! \name ENCODE/DECODE - //@{ - //! minimum number of bytes to encode this polynomial - /*! MinEncodedSize of 0 is 1 */ - unsigned int MinEncodedSize() const {return STDMAX(1U, ByteCount());} - - //! encode in big-endian format - /*! if outputLen < MinEncodedSize, the most significant bytes will be dropped - if outputLen > MinEncodedSize, the most significant bytes will be padded - */ - void Encode(byte *output, size_t outputLen) const; - //! - void Encode(BufferedTransformation &bt, size_t outputLen) const; - - //! - void Decode(const byte *input, size_t inputLen); - //! - //* Precondition: bt.MaxRetrievable() >= inputLen - void Decode(BufferedTransformation &bt, size_t inputLen); - - //! encode value as big-endian octet string - void DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const; - //! decode value as big-endian octet string - void BERDecodeAsOctetString(BufferedTransformation &bt, size_t length); - //@} - - //! \name ACCESSORS - //@{ - //! number of significant bits = Degree() + 1 - unsigned int BitCount() const; - //! number of significant bytes = ceiling(BitCount()/8) - unsigned int ByteCount() const; - //! number of significant words = ceiling(ByteCount()/sizeof(word)) - unsigned int WordCount() const; - - //! return the n-th bit, n=0 being the least significant bit - bool GetBit(size_t n) const {return GetCoefficient(n)!=0;} - //! return the n-th byte - byte GetByte(size_t n) const; - - //! the zero polynomial will return a degree of -1 - signed int Degree() const {return BitCount()-1;} - //! degree + 1 - unsigned int CoefficientCount() const {return BitCount();} - //! return coefficient for x^i - int GetCoefficient(size_t i) const - {return (i/WORD_BITS < reg.size()) ? int(reg[i/WORD_BITS] >> (i % WORD_BITS)) & 1 : 0;} - //! return coefficient for x^i - int operator[](unsigned int i) const {return GetCoefficient(i);} - - //! - bool IsZero() const {return !*this;} - //! - bool Equals(const PolynomialMod2 &rhs) const; - //@} - - //! \name MANIPULATORS - //@{ - //! - PolynomialMod2& operator=(const PolynomialMod2& t); - //! - PolynomialMod2& operator&=(const PolynomialMod2& t); - //! - PolynomialMod2& operator^=(const PolynomialMod2& t); - //! - PolynomialMod2& operator+=(const PolynomialMod2& t) {return *this ^= t;} - //! - PolynomialMod2& operator-=(const PolynomialMod2& t) {return *this ^= t;} - //! - PolynomialMod2& operator*=(const PolynomialMod2& t); - //! - PolynomialMod2& operator/=(const PolynomialMod2& t); - //! - PolynomialMod2& operator%=(const PolynomialMod2& t); - //! - PolynomialMod2& operator<<=(unsigned int); - //! - PolynomialMod2& operator>>=(unsigned int); - - //! - void Randomize(RandomNumberGenerator &rng, size_t bitcount); - - //! - void SetBit(size_t i, int value = 1); - //! set the n-th byte to value - void SetByte(size_t n, byte value); - - //! - void SetCoefficient(size_t i, int value) {SetBit(i, value);} - - //! - void swap(PolynomialMod2 &a) {reg.swap(a.reg);} - //@} - - //! \name UNARY OPERATORS - //@{ - //! - bool operator!() const; - //! - PolynomialMod2 operator+() const {return *this;} - //! - PolynomialMod2 operator-() const {return *this;} - //@} - - //! \name BINARY OPERATORS - //@{ - //! - PolynomialMod2 And(const PolynomialMod2 &b) const; - //! - PolynomialMod2 Xor(const PolynomialMod2 &b) const; - //! - PolynomialMod2 Plus(const PolynomialMod2 &b) const {return Xor(b);} - //! - PolynomialMod2 Minus(const PolynomialMod2 &b) const {return Xor(b);} - //! - PolynomialMod2 Times(const PolynomialMod2 &b) const; - //! - PolynomialMod2 DividedBy(const PolynomialMod2 &b) const; - //! - PolynomialMod2 Modulo(const PolynomialMod2 &b) const; - - //! - PolynomialMod2 operator>>(unsigned int n) const; - //! - PolynomialMod2 operator<<(unsigned int n) const; - //@} - - //! \name OTHER ARITHMETIC FUNCTIONS - //@{ - //! sum modulo 2 of all coefficients - unsigned int Parity() const; - - //! check for irreducibility - bool IsIrreducible() const; - - //! is always zero since we're working modulo 2 - PolynomialMod2 Doubled() const {return Zero();} - //! - PolynomialMod2 Squared() const; - - //! only 1 is a unit - bool IsUnit() const {return Equals(One());} - //! return inverse if *this is a unit, otherwise return 0 - PolynomialMod2 MultiplicativeInverse() const {return IsUnit() ? One() : Zero();} - - //! greatest common divisor - static PolynomialMod2 CRYPTOPP_API Gcd(const PolynomialMod2 &a, const PolynomialMod2 &n); - //! calculate multiplicative inverse of *this mod n - PolynomialMod2 InverseMod(const PolynomialMod2 &) const; - - //! calculate r and q such that (a == d*q + r) && (deg(r) < deg(d)) - static void CRYPTOPP_API Divide(PolynomialMod2 &r, PolynomialMod2 &q, const PolynomialMod2 &a, const PolynomialMod2 &d); - //@} - - //! \name INPUT/OUTPUT - //@{ - //! - friend std::ostream& operator<<(std::ostream& out, const PolynomialMod2 &a); - //@} - -private: - friend class GF2NT; - - SecWordBlock reg; -}; - -//! -inline bool operator==(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) -{return a.Equals(b);} -//! -inline bool operator!=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) -{return !(a==b);} -//! compares degree -inline bool operator> (const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) -{return a.Degree() > b.Degree();} -//! compares degree -inline bool operator>=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) -{return a.Degree() >= b.Degree();} -//! compares degree -inline bool operator< (const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) -{return a.Degree() < b.Degree();} -//! compares degree -inline bool operator<=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) -{return a.Degree() <= b.Degree();} -//! -inline CryptoPP::PolynomialMod2 operator&(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.And(b);} -//! -inline CryptoPP::PolynomialMod2 operator^(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Xor(b);} -//! -inline CryptoPP::PolynomialMod2 operator+(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Plus(b);} -//! -inline CryptoPP::PolynomialMod2 operator-(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Minus(b);} -//! -inline CryptoPP::PolynomialMod2 operator*(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Times(b);} -//! -inline CryptoPP::PolynomialMod2 operator/(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.DividedBy(b);} -//! -inline CryptoPP::PolynomialMod2 operator%(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Modulo(b);} - -// CodeWarrior 8 workaround: put these template instantiations after overloaded operator declarations, -// but before the use of QuotientRing > for VC .NET 2003 -CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup; -CRYPTOPP_DLL_TEMPLATE_CLASS AbstractRing; -CRYPTOPP_DLL_TEMPLATE_CLASS AbstractEuclideanDomain; -CRYPTOPP_DLL_TEMPLATE_CLASS EuclideanDomainOf; -CRYPTOPP_DLL_TEMPLATE_CLASS QuotientRing >; - -//! GF(2^n) with Polynomial Basis -class CRYPTOPP_DLL GF2NP : public QuotientRing > -{ -public: - GF2NP(const PolynomialMod2 &modulus); - - virtual GF2NP * Clone() const {return new GF2NP(*this);} - virtual void DEREncode(BufferedTransformation &bt) const - {assert(false);} // no ASN.1 syntax yet for general polynomial basis - - void DEREncodeElement(BufferedTransformation &out, const Element &a) const; - void BERDecodeElement(BufferedTransformation &in, Element &a) const; - - bool Equal(const Element &a, const Element &b) const - {assert(a.Degree() < m_modulus.Degree() && b.Degree() < m_modulus.Degree()); return a.Equals(b);} - - bool IsUnit(const Element &a) const - {assert(a.Degree() < m_modulus.Degree()); return !!a;} - - unsigned int MaxElementBitLength() const - {return m;} - - unsigned int MaxElementByteLength() const - {return (unsigned int)BitsToBytes(MaxElementBitLength());} - - Element SquareRoot(const Element &a) const; - - Element HalfTrace(const Element &a) const; - - // returns z such that z^2 + z == a - Element SolveQuadraticEquation(const Element &a) const; - -protected: - unsigned int m; -}; - -//! GF(2^n) with Trinomial Basis -class CRYPTOPP_DLL GF2NT : public GF2NP -{ -public: - // polynomial modulus = x^t0 + x^t1 + x^t2, t0 > t1 > t2 - GF2NT(unsigned int t0, unsigned int t1, unsigned int t2); - - GF2NP * Clone() const {return new GF2NT(*this);} - void DEREncode(BufferedTransformation &bt) const; - - const Element& Multiply(const Element &a, const Element &b) const; - - const Element& Square(const Element &a) const - {return Reduced(a.Squared());} - - const Element& MultiplicativeInverse(const Element &a) const; - -private: - const Element& Reduced(const Element &a) const; - - unsigned int t0, t1; - mutable PolynomialMod2 result; -}; - -//! GF(2^n) with Pentanomial Basis -class CRYPTOPP_DLL GF2NPP : public GF2NP -{ -public: - // polynomial modulus = x^t0 + x^t1 + x^t2 + x^t3 + x^t4, t0 > t1 > t2 > t3 > t4 - GF2NPP(unsigned int t0, unsigned int t1, unsigned int t2, unsigned int t3, unsigned int t4) - : GF2NP(PolynomialMod2::Pentanomial(t0, t1, t2, t3, t4)), t0(t0), t1(t1), t2(t2), t3(t3) {} - - GF2NP * Clone() const {return new GF2NPP(*this);} - void DEREncode(BufferedTransformation &bt) const; - -private: - unsigned int t0, t1, t2, t3; -}; - -// construct new GF2NP from the ASN.1 sequence Characteristic-two -CRYPTOPP_DLL GF2NP * CRYPTOPP_API BERDecodeGF2NP(BufferedTransformation &bt); - -NAMESPACE_END - -#ifndef __BORLANDC__ -NAMESPACE_BEGIN(std) -template<> inline void swap(CryptoPP::PolynomialMod2 &a, CryptoPP::PolynomialMod2 &b) -{ - a.swap(b); -} -NAMESPACE_END -#endif - -#endif diff --git a/embeddedcryptopp/gfpcrypt.cpp b/embeddedcryptopp/gfpcrypt.cpp deleted file mode 100644 index 6d9ffce..0000000 --- a/embeddedcryptopp/gfpcrypt.cpp +++ /dev/null @@ -1,275 +0,0 @@ -// dsa.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "gfpcrypt.h" -#include "asn.h" -#include "oids.h" -#include "nbtheory.h" - -NAMESPACE_BEGIN(CryptoPP) - -void TestInstantiations_gfpcrypt() -{ - GDSA::Signer test; - GDSA::Verifier test1; - DSA::Signer test5(NullRNG(), 100); - DSA::Signer test2(test5); - NR::Signer test3; - NR::Verifier test4; - DLIES<>::Encryptor test6; - DLIES<>::Decryptor test7; -} - -void DL_GroupParameters_DSA::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg) -{ - Integer p, q, g; - - if (alg.GetValue("Modulus", p) && alg.GetValue("SubgroupGenerator", g)) - { - q = alg.GetValueWithDefault("SubgroupOrder", ComputeGroupOrder(p)/2); - } - else - { - int modulusSize = 1024; - alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize); - - if (!DSA::IsValidPrimeLength(modulusSize)) - throw InvalidArgument("DSA: not a valid prime length"); - - SecByteBlock seed(SHA::DIGESTSIZE); - Integer h; - int c; - - do - { - rng.GenerateBlock(seed, SHA::DIGESTSIZE); - } while (!DSA::GeneratePrimes(seed, SHA::DIGESTSIZE*8, c, p, modulusSize, q)); - - do - { - h.Randomize(rng, 2, p-2); - g = a_exp_b_mod_c(h, (p-1)/q, p); - } while (g <= 1); - } - - Initialize(p, q, g); -} - -bool DL_GroupParameters_DSA::ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const -{ - bool pass = DL_GroupParameters_GFP::ValidateGroup(rng, level); - pass = pass && DSA::IsValidPrimeLength(GetModulus().BitCount()); - pass = pass && GetSubgroupOrder().BitCount() == 160; - return pass; -} - -void DL_SignatureMessageEncodingMethod_DSA::ComputeMessageRepresentative(RandomNumberGenerator &rng, - const byte *recoverableMessage, size_t recoverableMessageLength, - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, size_t representativeBitLength) const -{ - assert(recoverableMessageLength == 0); - assert(hashIdentifier.second == 0); - const size_t representativeByteLength = BitsToBytes(representativeBitLength); - const size_t digestSize = hash.DigestSize(); - const size_t paddingLength = SaturatingSubtract(representativeByteLength, digestSize); - - memset(representative, 0, paddingLength); - hash.TruncatedFinal(representative+paddingLength, STDMIN(representativeByteLength, digestSize)); - - if (digestSize*8 > representativeBitLength) - { - Integer h(representative, representativeByteLength); - h >>= representativeByteLength*8 - representativeBitLength; - h.Encode(representative, representativeByteLength); - } -} - -void DL_SignatureMessageEncodingMethod_NR::ComputeMessageRepresentative(RandomNumberGenerator &rng, - const byte *recoverableMessage, size_t recoverableMessageLength, - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, size_t representativeBitLength) const -{ - assert(recoverableMessageLength == 0); - assert(hashIdentifier.second == 0); - const size_t representativeByteLength = BitsToBytes(representativeBitLength); - const size_t digestSize = hash.DigestSize(); - const size_t paddingLength = SaturatingSubtract(representativeByteLength, digestSize); - - memset(representative, 0, paddingLength); - hash.TruncatedFinal(representative+paddingLength, STDMIN(representativeByteLength, digestSize)); - - if (digestSize*8 >= representativeBitLength) - { - Integer h(representative, representativeByteLength); - h >>= representativeByteLength*8 - representativeBitLength + 1; - h.Encode(representative, representativeByteLength); - } -} - -bool DL_GroupParameters_IntegerBased::ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const -{ - const Integer &p = GetModulus(), &q = GetSubgroupOrder(); - - bool pass = true; - pass = pass && p > Integer::One() && p.IsOdd(); - pass = pass && q > Integer::One() && q.IsOdd(); - - if (level >= 1) - pass = pass && GetCofactor() > Integer::One() && GetGroupOrder() % q == Integer::Zero(); - if (level >= 2) - pass = pass && VerifyPrime(rng, q, level-2) && VerifyPrime(rng, p, level-2); - - return pass; -} - -bool DL_GroupParameters_IntegerBased::ValidateElement(unsigned int level, const Integer &g, const DL_FixedBasePrecomputation *gpc) const -{ - const Integer &p = GetModulus(), &q = GetSubgroupOrder(); - - bool pass = true; - pass = pass && GetFieldType() == 1 ? g.IsPositive() : g.NotNegative(); - pass = pass && g < p && !IsIdentity(g); - - if (level >= 1) - { - if (gpc) - pass = pass && gpc->Exponentiate(GetGroupPrecomputation(), Integer::One()) == g; - } - if (level >= 2) - { - if (GetFieldType() == 2) - pass = pass && Jacobi(g*g-4, p)==-1; - - // verifying that Lucas((p+1)/2, w, p)==2 is omitted because it's too costly - // and at most 1 bit is leaked if it's false - bool fullValidate = (GetFieldType() == 2 && level >= 3) || !FastSubgroupCheckAvailable(); - - if (fullValidate && pass) - { - Integer gp = gpc ? gpc->Exponentiate(GetGroupPrecomputation(), q) : ExponentiateElement(g, q); - pass = pass && IsIdentity(gp); - } - else if (GetFieldType() == 1) - pass = pass && Jacobi(g, p) == 1; - } - - return pass; -} - -void DL_GroupParameters_IntegerBased::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg) -{ - Integer p, q, g; - - if (alg.GetValue("Modulus", p) && alg.GetValue("SubgroupGenerator", g)) - { - q = alg.GetValueWithDefault("SubgroupOrder", ComputeGroupOrder(p)/2); - } - else - { - int modulusSize, subgroupOrderSize; - - if (!alg.GetIntValue("ModulusSize", modulusSize)) - modulusSize = alg.GetIntValueWithDefault("KeySize", 2048); - - if (!alg.GetIntValue("SubgroupOrderSize", subgroupOrderSize)) - subgroupOrderSize = GetDefaultSubgroupOrderSize(modulusSize); - - PrimeAndGenerator pg; - pg.Generate(GetFieldType() == 1 ? 1 : -1, rng, modulusSize, subgroupOrderSize); - p = pg.Prime(); - q = pg.SubPrime(); - g = pg.Generator(); - } - - Initialize(p, q, g); -} - -Integer DL_GroupParameters_IntegerBased::DecodeElement(const byte *encoded, bool checkForGroupMembership) const -{ - Integer g(encoded, GetModulus().ByteCount()); - if (!ValidateElement(1, g, NULL)) - throw DL_BadElement(); - return g; -} - -void DL_GroupParameters_IntegerBased::BERDecode(BufferedTransformation &bt) -{ - BERSequenceDecoder parameters(bt); - Integer p(parameters); - Integer q(parameters); - Integer g; - if (parameters.EndReached()) - { - g = q; - q = ComputeGroupOrder(p) / 2; - } - else - g.BERDecode(parameters); - parameters.MessageEnd(); - - SetModulusAndSubgroupGenerator(p, g); - SetSubgroupOrder(q); -} - -void DL_GroupParameters_IntegerBased::DEREncode(BufferedTransformation &bt) const -{ - DERSequenceEncoder parameters(bt); - GetModulus().DEREncode(parameters); - m_q.DEREncode(parameters); - GetSubgroupGenerator().DEREncode(parameters); - parameters.MessageEnd(); -} - -bool DL_GroupParameters_IntegerBased::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const -{ - return GetValueHelper >(this, name, valueType, pValue) - CRYPTOPP_GET_FUNCTION_ENTRY(Modulus); -} - -void DL_GroupParameters_IntegerBased::AssignFrom(const NameValuePairs &source) -{ - AssignFromHelper(this, source) - CRYPTOPP_SET_FUNCTION_ENTRY2(Modulus, SubgroupGenerator) - CRYPTOPP_SET_FUNCTION_ENTRY(SubgroupOrder) - ; -} - -OID DL_GroupParameters_IntegerBased::GetAlgorithmID() const -{ - return ASN1::id_dsa(); -} - -void DL_GroupParameters_GFP::SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const -{ - ModularArithmetic ma(GetModulus()); - ma.SimultaneousExponentiate(results, base, exponents, exponentsCount); -} - -DL_GroupParameters_GFP::Element DL_GroupParameters_GFP::MultiplyElements(const Element &a, const Element &b) const -{ - return a_times_b_mod_c(a, b, GetModulus()); -} - -DL_GroupParameters_GFP::Element DL_GroupParameters_GFP::CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const -{ - ModularArithmetic ma(GetModulus()); - return ma.CascadeExponentiate(element1, exponent1, element2, exponent2); -} - -Integer DL_GroupParameters_IntegerBased::GetMaxExponent() const -{ - return STDMIN(GetSubgroupOrder()-1, Integer::Power2(2*DiscreteLogWorkFactor(GetFieldType()*GetModulus().BitCount()))); -} - -unsigned int DL_GroupParameters_IntegerBased::GetDefaultSubgroupOrderSize(unsigned int modulusSize) const -{ - return 2*DiscreteLogWorkFactor(GetFieldType()*modulusSize); -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/gfpcrypt.h b/embeddedcryptopp/gfpcrypt.h deleted file mode 100644 index 5e9c635..0000000 --- a/embeddedcryptopp/gfpcrypt.h +++ /dev/null @@ -1,536 +0,0 @@ -#ifndef CRYPTOPP_GFPCRYPT_H -#define CRYPTOPP_GFPCRYPT_H - -/** \file - Implementation of schemes based on DL over GF(p) -*/ - -#include "pubkey.h" -#include "modexppc.h" -#include "sha.h" -#include "algparam.h" -#include "asn.h" -#include "smartptr.h" -#include "hmac.h" - -#include - -NAMESPACE_BEGIN(CryptoPP) - -CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters; - -//! _ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBased : public ASN1CryptoMaterial > -{ - typedef DL_GroupParameters_IntegerBased ThisClass; - -public: - void Initialize(const DL_GroupParameters_IntegerBased ¶ms) - {Initialize(params.GetModulus(), params.GetSubgroupOrder(), params.GetSubgroupGenerator());} - void Initialize(RandomNumberGenerator &rng, unsigned int pbits) - {GenerateRandom(rng, MakeParameters("ModulusSize", (int)pbits));} - void Initialize(const Integer &p, const Integer &g) - {SetModulusAndSubgroupGenerator(p, g); SetSubgroupOrder(ComputeGroupOrder(p)/2);} - void Initialize(const Integer &p, const Integer &q, const Integer &g) - {SetModulusAndSubgroupGenerator(p, g); SetSubgroupOrder(q);} - - // ASN1Object interface - void BERDecode(BufferedTransformation &bt); - void DEREncode(BufferedTransformation &bt) const; - - // GeneratibleCryptoMaterial interface - /*! parameters: (ModulusSize, SubgroupOrderSize (optional)) */ - void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg); - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; - void AssignFrom(const NameValuePairs &source); - - // DL_GroupParameters - const Integer & GetSubgroupOrder() const {return m_q;} - Integer GetGroupOrder() const {return GetFieldType() == 1 ? GetModulus()-Integer::One() : GetModulus()+Integer::One();} - bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const; - bool ValidateElement(unsigned int level, const Integer &element, const DL_FixedBasePrecomputation *precomp) const; - bool FastSubgroupCheckAvailable() const {return GetCofactor() == 2;} - void EncodeElement(bool reversible, const Element &element, byte *encoded) const - {element.Encode(encoded, GetModulus().ByteCount());} - unsigned int GetEncodedElementSize(bool reversible) const {return GetModulus().ByteCount();} - Integer DecodeElement(const byte *encoded, bool checkForGroupMembership) const; - Integer ConvertElementToInteger(const Element &element) const - {return element;} - Integer GetMaxExponent() const; - static std::string CRYPTOPP_API StaticAlgorithmNamePrefix() {return "";} - - OID GetAlgorithmID() const; - - virtual const Integer & GetModulus() const =0; - virtual void SetModulusAndSubgroupGenerator(const Integer &p, const Integer &g) =0; - - void SetSubgroupOrder(const Integer &q) - {m_q = q; ParametersChanged();} - -protected: - Integer ComputeGroupOrder(const Integer &modulus) const - {return modulus-(GetFieldType() == 1 ? 1 : -1);} - - // GF(p) = 1, GF(p^2) = 2 - virtual int GetFieldType() const =0; - virtual unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const; - -private: - Integer m_q; -}; - -//! _ -template > -class CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBasedImpl : public DL_GroupParametersImpl -{ - typedef DL_GroupParameters_IntegerBasedImpl ThisClass; - -public: - typedef typename GROUP_PRECOMP::Element Element; - - // GeneratibleCryptoMaterial interface - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const - {return GetValueHelper(this, name, valueType, pValue).Assignable();} - - void AssignFrom(const NameValuePairs &source) - {AssignFromHelper(this, source);} - - // DL_GroupParameters - const DL_FixedBasePrecomputation & GetBasePrecomputation() const {return this->m_gpc;} - DL_FixedBasePrecomputation & AccessBasePrecomputation() {return this->m_gpc;} - - // IntegerGroupParameters - const Integer & GetModulus() const {return this->m_groupPrecomputation.GetModulus();} - const Integer & GetGenerator() const {return this->m_gpc.GetBase(this->GetGroupPrecomputation());} - - void SetModulusAndSubgroupGenerator(const Integer &p, const Integer &g) // these have to be set together - {this->m_groupPrecomputation.SetModulus(p); this->m_gpc.SetBase(this->GetGroupPrecomputation(), g); this->ParametersChanged();} - - // non-inherited - bool operator==(const DL_GroupParameters_IntegerBasedImpl &rhs) const - {return GetModulus() == rhs.GetModulus() && GetGenerator() == rhs.GetGenerator() && this->GetSubgroupOrder() == rhs.GetSubgroupOrder();} - bool operator!=(const DL_GroupParameters_IntegerBasedImpl &rhs) const - {return !operator==(rhs);} -}; - -CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_IntegerBasedImpl; - -//! GF(p) group parameters -class CRYPTOPP_DLL DL_GroupParameters_GFP : public DL_GroupParameters_IntegerBasedImpl -{ -public: - // DL_GroupParameters - bool IsIdentity(const Integer &element) const {return element == Integer::One();} - void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const; - - // NameValuePairs interface - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const - { - return GetValueHelper(this, name, valueType, pValue).Assignable(); - } - - // used by MQV - Element MultiplyElements(const Element &a, const Element &b) const; - Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const; - -protected: - int GetFieldType() const {return 1;} -}; - -//! GF(p) group parameters that default to same primes -class CRYPTOPP_DLL DL_GroupParameters_GFP_DefaultSafePrime : public DL_GroupParameters_GFP -{ -public: - typedef NoCofactorMultiplication DefaultCofactorOption; - -protected: - unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const {return modulusSize-1;} -}; - -//! GDSA algorithm -template -class DL_Algorithm_GDSA : public DL_ElgamalLikeSignatureAlgorithm -{ -public: - static const char * CRYPTOPP_API StaticAlgorithmName() {return "DSA-1363";} - - void Sign(const DL_GroupParameters ¶ms, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const - { - const Integer &q = params.GetSubgroupOrder(); - r %= q; - Integer kInv = k.InverseMod(q); - s = (kInv * (x*r + e)) % q; - assert(!!r && !!s); - } - - bool Verify(const DL_GroupParameters ¶ms, const DL_PublicKey &publicKey, const Integer &e, const Integer &r, const Integer &s) const - { - const Integer &q = params.GetSubgroupOrder(); - if (r>=q || r<1 || s>=q || s<1) - return false; - - Integer w = s.InverseMod(q); - Integer u1 = (e * w) % q; - Integer u2 = (r * w) % q; - // verify r == (g^u1 * y^u2 mod p) mod q - return r == params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(u1, u2)) % q; - } -}; - -CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA; - -//! NR algorithm -template -class DL_Algorithm_NR : public DL_ElgamalLikeSignatureAlgorithm -{ -public: - static const char * CRYPTOPP_API StaticAlgorithmName() {return "NR";} - - void Sign(const DL_GroupParameters ¶ms, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const - { - const Integer &q = params.GetSubgroupOrder(); - r = (r + e) % q; - s = (k - x*r) % q; - assert(!!r); - } - - bool Verify(const DL_GroupParameters ¶ms, const DL_PublicKey &publicKey, const Integer &e, const Integer &r, const Integer &s) const - { - const Integer &q = params.GetSubgroupOrder(); - if (r>=q || r<1 || s>=q) - return false; - - // check r == (m_g^s * m_y^r + m) mod m_q - return r == (params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(s, r)) + e) % q; - } -}; - -/*! DSA public key format is defined in 7.3.3 of RFC 2459. The - private key format is defined in 12.9 of PKCS #11 v2.10. */ -template -class DL_PublicKey_GFP : public DL_PublicKeyImpl -{ -public: - void Initialize(const DL_GroupParameters_IntegerBased ¶ms, const Integer &y) - {this->AccessGroupParameters().Initialize(params); this->SetPublicElement(y);} - void Initialize(const Integer &p, const Integer &g, const Integer &y) - {this->AccessGroupParameters().Initialize(p, g); this->SetPublicElement(y);} - void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &y) - {this->AccessGroupParameters().Initialize(p, q, g); this->SetPublicElement(y);} - - // X509PublicKey - void BERDecodePublicKey(BufferedTransformation &bt, bool, size_t) - {this->SetPublicElement(Integer(bt));} - void DEREncodePublicKey(BufferedTransformation &bt) const - {this->GetPublicElement().DEREncode(bt);} -}; - -//! DL private key (in GF(p) groups) -template -class DL_PrivateKey_GFP : public DL_PrivateKeyImpl -{ -public: - void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits) - {this->GenerateRandomWithKeySize(rng, modulusBits);} - void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &g) - {this->GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupGenerator", g));} - void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &q, const Integer &g) - {this->GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupOrder", q)("SubgroupGenerator", g));} - void Initialize(const DL_GroupParameters_IntegerBased ¶ms, const Integer &x) - {this->AccessGroupParameters().Initialize(params); this->SetPrivateExponent(x);} - void Initialize(const Integer &p, const Integer &g, const Integer &x) - {this->AccessGroupParameters().Initialize(p, g); this->SetPrivateExponent(x);} - void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &x) - {this->AccessGroupParameters().Initialize(p, q, g); this->SetPrivateExponent(x);} -}; - -//! DL signing/verification keys (in GF(p) groups) -struct DL_SignatureKeys_GFP -{ - typedef DL_GroupParameters_GFP GroupParameters; - typedef DL_PublicKey_GFP PublicKey; - typedef DL_PrivateKey_GFP PrivateKey; -}; - -//! DL encryption/decryption keys (in GF(p) groups) -struct DL_CryptoKeys_GFP -{ - typedef DL_GroupParameters_GFP_DefaultSafePrime GroupParameters; - typedef DL_PublicKey_GFP PublicKey; - typedef DL_PrivateKey_GFP PrivateKey; -}; - -//! provided for backwards compatibility, this class uses the old non-standard Crypto++ key format -template -class DL_PublicKey_GFP_OldFormat : public BASE -{ -public: - void BERDecode(BufferedTransformation &bt) - { - BERSequenceDecoder seq(bt); - Integer v1(seq); - Integer v2(seq); - Integer v3(seq); - - if (seq.EndReached()) - { - this->AccessGroupParameters().Initialize(v1, v1/2, v2); - this->SetPublicElement(v3); - } - else - { - Integer v4(seq); - this->AccessGroupParameters().Initialize(v1, v2, v3); - this->SetPublicElement(v4); - } - - seq.MessageEnd(); - } - - void DEREncode(BufferedTransformation &bt) const - { - DERSequenceEncoder seq(bt); - this->GetGroupParameters().GetModulus().DEREncode(seq); - if (this->GetGroupParameters().GetCofactor() != 2) - this->GetGroupParameters().GetSubgroupOrder().DEREncode(seq); - this->GetGroupParameters().GetGenerator().DEREncode(seq); - this->GetPublicElement().DEREncode(seq); - seq.MessageEnd(); - } -}; - -//! provided for backwards compatibility, this class uses the old non-standard Crypto++ key format -template -class DL_PrivateKey_GFP_OldFormat : public BASE -{ -public: - void BERDecode(BufferedTransformation &bt) - { - BERSequenceDecoder seq(bt); - Integer v1(seq); - Integer v2(seq); - Integer v3(seq); - Integer v4(seq); - - if (seq.EndReached()) - { - this->AccessGroupParameters().Initialize(v1, v1/2, v2); - this->SetPrivateExponent(v4 % (v1/2)); // some old keys may have x >= q - } - else - { - Integer v5(seq); - this->AccessGroupParameters().Initialize(v1, v2, v3); - this->SetPrivateExponent(v5); - } - - seq.MessageEnd(); - } - - void DEREncode(BufferedTransformation &bt) const - { - DERSequenceEncoder seq(bt); - this->GetGroupParameters().GetModulus().DEREncode(seq); - if (this->GetGroupParameters().GetCofactor() != 2) - this->GetGroupParameters().GetSubgroupOrder().DEREncode(seq); - this->GetGroupParameters().GetGenerator().DEREncode(seq); - this->GetGroupParameters().ExponentiateBase(this->GetPrivateExponent()).DEREncode(seq); - this->GetPrivateExponent().DEREncode(seq); - seq.MessageEnd(); - } -}; - -//! DSA-1363 -template -struct GDSA : public DL_SS< - DL_SignatureKeys_GFP, - DL_Algorithm_GDSA, - DL_SignatureMessageEncodingMethod_DSA, - H> -{ -}; - -//! NR -template -struct NR : public DL_SS< - DL_SignatureKeys_GFP, - DL_Algorithm_NR, - DL_SignatureMessageEncodingMethod_NR, - H> -{ -}; - -//! DSA group parameters, these are GF(p) group parameters that are allowed by the DSA standard -class CRYPTOPP_DLL DL_GroupParameters_DSA : public DL_GroupParameters_GFP -{ -public: - /*! also checks that the lengths of p and q are allowed by the DSA standard */ - bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const; - /*! parameters: (ModulusSize), or (Modulus, SubgroupOrder, SubgroupGenerator) */ - /*! ModulusSize must be between DSA::MIN_PRIME_LENGTH and DSA::MAX_PRIME_LENGTH, and divisible by DSA::PRIME_LENGTH_MULTIPLE */ - void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg); -}; - -struct DSA; - -//! DSA keys -struct DL_Keys_DSA -{ - typedef DL_PublicKey_GFP PublicKey; - typedef DL_PrivateKey_WithSignaturePairwiseConsistencyTest, DSA> PrivateKey; -}; - -//! DSA -struct CRYPTOPP_DLL DSA : public DL_SS< - DL_Keys_DSA, - DL_Algorithm_GDSA, - DL_SignatureMessageEncodingMethod_DSA, - SHA, - DSA> -{ - static const char * CRYPTOPP_API StaticAlgorithmName() {return "DSA";} - - //! Generate DSA primes according to NIST standard - /*! Both seedLength and primeLength are in bits, but seedLength should - be a multiple of 8. - If useInputCounterValue == true, the counter parameter is taken as input, otherwise it's used for output - */ - static bool CRYPTOPP_API GeneratePrimes(const byte *seed, unsigned int seedLength, int &counter, - Integer &p, unsigned int primeLength, Integer &q, bool useInputCounterValue = false); - - static bool CRYPTOPP_API IsValidPrimeLength(unsigned int pbits) - {return pbits >= MIN_PRIME_LENGTH && pbits <= MAX_PRIME_LENGTH && pbits % PRIME_LENGTH_MULTIPLE == 0;} - - //! FIPS 186-2 Change Notice 1 changed the minimum modulus length to 1024 - enum { -#if (DSA_1024_BIT_MODULUS_ONLY) - MIN_PRIME_LENGTH = 1024, -#else - MIN_PRIME_LENGTH = 512, -#endif - MAX_PRIME_LENGTH = 1024, PRIME_LENGTH_MULTIPLE = 64}; -}; - -CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_GFP; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_GFP; -CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest, DSA>; - -//! the XOR encryption method, for use with DL-based cryptosystems -template -class DL_EncryptionAlgorithm_Xor : public DL_SymmetricEncryptionAlgorithm -{ -public: - bool ParameterSupported(const char *name) const {return strcmp(name, Name::EncodingParameters()) == 0;} - size_t GetSymmetricKeyLength(size_t plaintextLength) const - {return plaintextLength + MAC::DEFAULT_KEYLENGTH;} - size_t GetSymmetricCiphertextLength(size_t plaintextLength) const - {return plaintextLength + MAC::DIGESTSIZE;} - size_t GetMaxSymmetricPlaintextLength(size_t ciphertextLength) const - {return (unsigned int)SaturatingSubtract(ciphertextLength, (unsigned int)MAC::DIGESTSIZE);} - void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters) const - { - const byte *cipherKey, *macKey; - if (DHAES_MODE) - { - macKey = key; - cipherKey = key + MAC::DEFAULT_KEYLENGTH; - } - else - { - cipherKey = key; - macKey = key + plaintextLength; - } - - ConstByteArrayParameter encodingParameters; - parameters.GetValue(Name::EncodingParameters(), encodingParameters); - - xorbuf(ciphertext, plaintext, cipherKey, plaintextLength); - MAC mac(macKey); - mac.Update(ciphertext, plaintextLength); - mac.Update(encodingParameters.begin(), encodingParameters.size()); - if (DHAES_MODE) - { - byte L[8] = {0,0,0,0}; - PutWord(false, BIG_ENDIAN_ORDER, L+4, word32(encodingParameters.size())); - mac.Update(L, 8); - } - mac.Final(ciphertext + plaintextLength); - } - DecodingResult SymmetricDecrypt(const byte *key, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters) const - { - size_t plaintextLength = GetMaxSymmetricPlaintextLength(ciphertextLength); - const byte *cipherKey, *macKey; - if (DHAES_MODE) - { - macKey = key; - cipherKey = key + MAC::DEFAULT_KEYLENGTH; - } - else - { - cipherKey = key; - macKey = key + plaintextLength; - } - - ConstByteArrayParameter encodingParameters; - parameters.GetValue(Name::EncodingParameters(), encodingParameters); - - MAC mac(macKey); - mac.Update(ciphertext, plaintextLength); - mac.Update(encodingParameters.begin(), encodingParameters.size()); - if (DHAES_MODE) - { - byte L[8] = {0,0,0,0}; - PutWord(false, BIG_ENDIAN_ORDER, L+4, word32(encodingParameters.size())); - mac.Update(L, 8); - } - if (!mac.Verify(ciphertext + plaintextLength)) - return DecodingResult(); - - xorbuf(plaintext, ciphertext, cipherKey, plaintextLength); - return DecodingResult(plaintextLength); - } -}; - -//! _ -template -class DL_KeyDerivationAlgorithm_P1363 : public DL_KeyDerivationAlgorithm -{ -public: - bool ParameterSupported(const char *name) const {return strcmp(name, Name::KeyDerivationParameters()) == 0;} - void Derive(const DL_GroupParameters ¶ms, byte *derivedKey, size_t derivedLength, const T &agreedElement, const T &ephemeralPublicKey, const NameValuePairs ¶meters) const - { - SecByteBlock agreedSecret; - if (DHAES_MODE) - { - agreedSecret.New(params.GetEncodedElementSize(true) + params.GetEncodedElementSize(false)); - params.EncodeElement(true, ephemeralPublicKey, agreedSecret); - params.EncodeElement(false, agreedElement, agreedSecret + params.GetEncodedElementSize(true)); - } - else - { - agreedSecret.New(params.GetEncodedElementSize(false)); - params.EncodeElement(false, agreedElement, agreedSecret); - } - - ConstByteArrayParameter derivationParameters; - parameters.GetValue(Name::KeyDerivationParameters(), derivationParameters); - KDF::DeriveKey(derivedKey, derivedLength, agreedSecret, agreedSecret.size(), derivationParameters.begin(), derivationParameters.size()); - } -}; - -//! Discrete Log Integrated Encryption Scheme, AKA DLIES -template -struct DLIES - : public DL_ES< - DL_CryptoKeys_GFP, - DL_KeyAgreementAlgorithm_DH, - DL_KeyDerivationAlgorithm_P1363 >, - DL_EncryptionAlgorithm_Xor, DHAES_MODE>, - DLIES<> > -{ - static std::string CRYPTOPP_API StaticAlgorithmName() {return "DLIES";} // TODO: fix this after name is standardized -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/hex.cpp b/embeddedcryptopp/hex.cpp deleted file mode 100644 index b6484a5..0000000 --- a/embeddedcryptopp/hex.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// hex.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "hex.h" - -NAMESPACE_BEGIN(CryptoPP) - -static const byte s_vecUpper[] = "0123456789ABCDEF"; -static const byte s_vecLower[] = "0123456789abcdef"; - -void HexEncoder::IsolatedInitialize(const NameValuePairs ¶meters) -{ - bool uppercase = parameters.GetValueWithDefault(Name::Uppercase(), true); - m_filter->Initialize(CombinedNameValuePairs( - parameters, - MakeParameters(Name::EncodingLookupArray(), uppercase ? &s_vecUpper[0] : &s_vecLower[0], false)(Name::Log2Base(), 4, true))); -} - -void HexDecoder::IsolatedInitialize(const NameValuePairs ¶meters) -{ - BaseN_Decoder::IsolatedInitialize(CombinedNameValuePairs( - parameters, - MakeParameters(Name::DecodingLookupArray(), GetDefaultDecodingLookupArray(), false)(Name::Log2Base(), 4, true))); -} - -const int *HexDecoder::GetDefaultDecodingLookupArray() -{ - static bool s_initialized = false; - static int s_array[256]; - - if (!s_initialized) - { - InitializeDecodingLookupArray(s_array, s_vecUpper, 16, true); - s_initialized = true; - } - return s_array; -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/hex.h b/embeddedcryptopp/hex.h deleted file mode 100644 index 006914c..0000000 --- a/embeddedcryptopp/hex.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef CRYPTOPP_HEX_H -#define CRYPTOPP_HEX_H - -#include "basecode.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! Converts given data to base 16 -class CRYPTOPP_DLL HexEncoder : public SimpleProxyFilter -{ -public: - HexEncoder(BufferedTransformation *attachment = NULL, bool uppercase = true, int outputGroupSize = 0, const std::string &separator = ":", const std::string &terminator = "") - : SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment) - { - IsolatedInitialize(MakeParameters(Name::Uppercase(), uppercase)(Name::GroupSize(), outputGroupSize)(Name::Separator(), ConstByteArrayParameter(separator))(Name::Terminator(), ConstByteArrayParameter(terminator))); - } - - void IsolatedInitialize(const NameValuePairs ¶meters); -}; - -//! Decode base 16 data back to bytes -class CRYPTOPP_DLL HexDecoder : public BaseN_Decoder -{ -public: - HexDecoder(BufferedTransformation *attachment = NULL) - : BaseN_Decoder(GetDefaultDecodingLookupArray(), 4, attachment) {} - - void IsolatedInitialize(const NameValuePairs ¶meters); - -private: - static const int * CRYPTOPP_API GetDefaultDecodingLookupArray(); -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/hmac.cpp b/embeddedcryptopp/hmac.cpp deleted file mode 100644 index d4a649c..0000000 --- a/embeddedcryptopp/hmac.cpp +++ /dev/null @@ -1,86 +0,0 @@ -// hmac.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "hmac.h" - -NAMESPACE_BEGIN(CryptoPP) - -void HMAC_Base::UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs &) -{ - AssertValidKeyLength(keylength); - - Restart(); - - HashTransformation &hash = AccessHash(); - unsigned int blockSize = hash.BlockSize(); - - if (!blockSize) - throw InvalidArgument("HMAC: can only be used with a block-based hash function"); - - m_buf.resize(2*AccessHash().BlockSize() + AccessHash().DigestSize()); - - if (keylength <= blockSize) - memcpy(AccessIpad(), userKey, keylength); - else - { - AccessHash().CalculateDigest(AccessIpad(), userKey, keylength); - keylength = hash.DigestSize(); - } - - assert(keylength <= blockSize); - memset(AccessIpad()+keylength, 0, blockSize-keylength); - - for (unsigned int i=0; i, public MessageAuthenticationCode -{ -public: - HMAC_Base() : m_innerHashKeyed(false) {} - void UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs ¶ms); - - void Restart(); - void Update(const byte *input, size_t length); - void TruncatedFinal(byte *mac, size_t size); - unsigned int OptimalBlockSize() const {return const_cast(this)->AccessHash().OptimalBlockSize();} - unsigned int DigestSize() const {return const_cast(this)->AccessHash().DigestSize();} - -protected: - virtual HashTransformation & AccessHash() =0; - byte * AccessIpad() {return m_buf;} - byte * AccessOpad() {return m_buf + AccessHash().BlockSize();} - byte * AccessInnerHash() {return m_buf + 2*AccessHash().BlockSize();} - -private: - void KeyInnerHash(); - - SecByteBlock m_buf; - bool m_innerHashKeyed; -}; - -//! HMAC -/*! HMAC(K, text) = H(K XOR opad, H(K XOR ipad, text)) */ -template -class HMAC : public MessageAuthenticationCodeImpl > -{ -public: - CRYPTOPP_CONSTANT(DIGESTSIZE=T::DIGESTSIZE) - CRYPTOPP_CONSTANT(BLOCKSIZE=T::BLOCKSIZE) - - HMAC() {} - HMAC(const byte *key, size_t length=HMAC_Base::DEFAULT_KEYLENGTH) - {this->SetKey(key, length);} - - static std::string StaticAlgorithmName() {return std::string("HMAC(") + T::StaticAlgorithmName() + ")";} - std::string AlgorithmName() const {return std::string("HMAC(") + m_hash.AlgorithmName() + ")";} - -private: - HashTransformation & AccessHash() {return m_hash;} - - T m_hash; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/integer.cpp b/embeddedcryptopp/integer.cpp deleted file mode 100644 index 9adb745..0000000 --- a/embeddedcryptopp/integer.cpp +++ /dev/null @@ -1,4245 +0,0 @@ -// integer.cpp - written and placed in the public domain by Wei Dai -// contains public domain code contributed by Alister Lee and Leonard Janke - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "integer.h" -#include "modarith.h" -#include "nbtheory.h" -#include "asn.h" -#include "oids.h" -#include "words.h" -#include "algparam.h" -#include "pubkey.h" // for P1363_KDF2 -#include "sha.h" -#include "cpu.h" - -#include - -#if _MSC_VER >= 1400 - #include -#endif - -#ifdef __DECCXX - #include -#endif - -#ifdef CRYPTOPP_MSVC6_NO_PP - #pragma message("You do not seem to have the Visual C++ Processor Pack installed, so use of SSE2 instructions will be disabled.") -#endif - -#define CRYPTOPP_INTEGER_SSE2 (CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86) - -NAMESPACE_BEGIN(CryptoPP) - -bool AssignIntToInteger(const std::type_info &valueType, void *pInteger, const void *pInt) -{ - if (valueType != typeid(Integer)) - return false; - *reinterpret_cast(pInteger) = *reinterpret_cast(pInt); - return true; -} - -inline static int Compare(const word *A, const word *B, size_t N) -{ - while (N--) - if (A[N] > B[N]) - return 1; - else if (A[N] < B[N]) - return -1; - - return 0; -} - -inline static int Increment(word *A, size_t N, word B=1) -{ - assert(N); - word t = A[0]; - A[0] = t+B; - if (A[0] >= t) - return 0; - for (unsigned i=1; i>(WORD_BITS-1)); d##0 = 2*d##0 + (c>>(WORD_BITS-1)); c *= 2; - #endif - #ifndef Acc2WordsBy2 - #define Acc2WordsBy2(a, b) a##0 += b##0; a##1 += a##0 < b##0; a##1 += b##1; - #endif - #define AddWithCarry(u, a, b) {word t = a+b; u##0 = t + u##1; u##1 = (ta) + (u##0>t);} - #define GetCarry(u) u##1 - #define GetBorrow(u) u##1 -#else - #define Declare2Words(x) dword x; - #if _MSC_VER >= 1400 && !defined(__INTEL_COMPILER) - #define MultiplyWords(p, a, b) p = __emulu(a, b); - #else - #define MultiplyWords(p, a, b) p = (dword)a*b; - #endif - #define AssignWord(a, b) a = b; - #define Add2WordsBy1(a, b, c) a = b + c; - #define Acc2WordsBy2(a, b) a += b; - #define LowWord(a) word(a) - #define HighWord(a) word(a>>WORD_BITS) - #define Double3Words(c, d) d = 2*d + (c>>(WORD_BITS-1)); c *= 2; - #define AddWithCarry(u, a, b) u = dword(a) + b + GetCarry(u); - #define SubtractWithBorrow(u, a, b) u = dword(a) - b - GetBorrow(u); - #define GetCarry(u) HighWord(u) - #define GetBorrow(u) word(u>>(WORD_BITS*2-1)) -#endif -#ifndef MulAcc - #define MulAcc(c, d, a, b) MultiplyWords(p, a, b); Acc2WordsBy1(p, c); c = LowWord(p); Acc2WordsBy1(d, HighWord(p)); -#endif -#ifndef Acc2WordsBy1 - #define Acc2WordsBy1(a, b) Add2WordsBy1(a, a, b) -#endif -#ifndef Acc3WordsBy2 - #define Acc3WordsBy2(c, d, e) Acc2WordsBy1(e, c); c = LowWord(e); Add2WordsBy1(e, d, HighWord(e)); -#endif - -class DWord -{ -public: - DWord() {} - -#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE - explicit DWord(word low) - { - m_whole = low; - } -#else - explicit DWord(word low) - { - m_halfs.low = low; - m_halfs.high = 0; - } -#endif - - DWord(word low, word high) - { - m_halfs.low = low; - m_halfs.high = high; - } - - static DWord Multiply(word a, word b) - { - DWord r; - #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE - r.m_whole = (dword)a * b; - #elif defined(MultiplyWordsLoHi) - MultiplyWordsLoHi(r.m_halfs.low, r.m_halfs.high, a, b); - #endif - return r; - } - - static DWord MultiplyAndAdd(word a, word b, word c) - { - DWord r = Multiply(a, b); - return r += c; - } - - DWord & operator+=(word a) - { - #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE - m_whole = m_whole + a; - #else - m_halfs.low += a; - m_halfs.high += (m_halfs.low < a); - #endif - return *this; - } - - DWord operator+(word a) - { - DWord r; - #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE - r.m_whole = m_whole + a; - #else - r.m_halfs.low = m_halfs.low + a; - r.m_halfs.high = m_halfs.high + (r.m_halfs.low < a); - #endif - return r; - } - - DWord operator-(DWord a) - { - DWord r; - #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE - r.m_whole = m_whole - a.m_whole; - #else - r.m_halfs.low = m_halfs.low - a.m_halfs.low; - r.m_halfs.high = m_halfs.high - a.m_halfs.high - (r.m_halfs.low > m_halfs.low); - #endif - return r; - } - - DWord operator-(word a) - { - DWord r; - #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE - r.m_whole = m_whole - a; - #else - r.m_halfs.low = m_halfs.low - a; - r.m_halfs.high = m_halfs.high - (r.m_halfs.low > m_halfs.low); - #endif - return r; - } - - // returns quotient, which must fit in a word - word operator/(word divisor); - - word operator%(word a); - - bool operator!() const - { - #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE - return !m_whole; - #else - return !m_halfs.high && !m_halfs.low; - #endif - } - - word GetLowHalf() const {return m_halfs.low;} - word GetHighHalf() const {return m_halfs.high;} - word GetHighHalfAsBorrow() const {return 0-m_halfs.high;} - -private: - union - { - #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE - dword m_whole; - #endif - struct - { - #ifdef IS_LITTLE_ENDIAN - word low; - word high; - #else - word high; - word low; - #endif - } m_halfs; - }; -}; - -class Word -{ -public: - Word() {} - - Word(word value) - { - m_whole = value; - } - - Word(hword low, hword high) - { - m_whole = low | (word(high) << (WORD_BITS/2)); - } - - static Word Multiply(hword a, hword b) - { - Word r; - r.m_whole = (word)a * b; - return r; - } - - Word operator-(Word a) - { - Word r; - r.m_whole = m_whole - a.m_whole; - return r; - } - - Word operator-(hword a) - { - Word r; - r.m_whole = m_whole - a; - return r; - } - - // returns quotient, which must fit in a word - hword operator/(hword divisor) - { - return hword(m_whole / divisor); - } - - bool operator!() const - { - return !m_whole; - } - - word GetWhole() const {return m_whole;} - hword GetLowHalf() const {return hword(m_whole);} - hword GetHighHalf() const {return hword(m_whole>>(WORD_BITS/2));} - hword GetHighHalfAsBorrow() const {return 0-hword(m_whole>>(WORD_BITS/2));} - -private: - word m_whole; -}; - -// do a 3 word by 2 word divide, returns quotient and leaves remainder in A -template -S DivideThreeWordsByTwo(S *A, S B0, S B1, D *dummy=NULL) -{ - // assert {A[2],A[1]} < {B1,B0}, so quotient can fit in a S - assert(A[2] < B1 || (A[2]==B1 && A[1] < B0)); - - // estimate the quotient: do a 2 S by 1 S divide - S Q; - if (S(B1+1) == 0) - Q = A[2]; - else - Q = D(A[1], A[2]) / S(B1+1); - - // now subtract Q*B from A - D p = D::Multiply(B0, Q); - D u = (D) A[0] - p.GetLowHalf(); - A[0] = u.GetLowHalf(); - u = (D) A[1] - p.GetHighHalf() - u.GetHighHalfAsBorrow() - D::Multiply(B1, Q); - A[1] = u.GetLowHalf(); - A[2] += u.GetHighHalf(); - - // Q <= actual quotient, so fix it - while (A[2] || A[1] > B1 || (A[1]==B1 && A[0]>=B0)) - { - u = (D) A[0] - B0; - A[0] = u.GetLowHalf(); - u = (D) A[1] - B1 - u.GetHighHalfAsBorrow(); - A[1] = u.GetLowHalf(); - A[2] += u.GetHighHalf(); - Q++; - assert(Q); // shouldn't overflow - } - - return Q; -} - -// do a 4 word by 2 word divide, returns 2 word quotient in Q0 and Q1 -template -inline D DivideFourWordsByTwo(S *T, const D &Al, const D &Ah, const D &B) -{ - if (!B) // if divisor is 0, we assume divisor==2**(2*WORD_BITS) - return D(Ah.GetLowHalf(), Ah.GetHighHalf()); - else - { - S Q[2]; - T[0] = Al.GetLowHalf(); - T[1] = Al.GetHighHalf(); - T[2] = Ah.GetLowHalf(); - T[3] = Ah.GetHighHalf(); - Q[1] = DivideThreeWordsByTwo(T+1, B.GetLowHalf(), B.GetHighHalf()); - Q[0] = DivideThreeWordsByTwo(T, B.GetLowHalf(), B.GetHighHalf()); - return D(Q[0], Q[1]); - } -} - -// returns quotient, which must fit in a word -inline word DWord::operator/(word a) -{ - #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE - return word(m_whole / a); - #else - hword r[4]; - return DivideFourWordsByTwo(r, m_halfs.low, m_halfs.high, a).GetWhole(); - #endif -} - -inline word DWord::operator%(word a) -{ - #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE - return word(m_whole % a); - #else - if (a < (word(1) << (WORD_BITS/2))) - { - hword h = hword(a); - word r = m_halfs.high % h; - r = ((m_halfs.low >> (WORD_BITS/2)) + (r << (WORD_BITS/2))) % h; - return hword((hword(m_halfs.low) + (r << (WORD_BITS/2))) % h); - } - else - { - hword r[4]; - DivideFourWordsByTwo(r, m_halfs.low, m_halfs.high, a); - return Word(r[0], r[1]).GetWhole(); - } - #endif -} - -// ******************************************************** - -// use some tricks to share assembly code between MSVC and GCC -#if defined(__GNUC__) - #define AddPrologue \ - int result; \ - __asm__ __volatile__ \ - ( \ - ".intel_syntax noprefix;" - #define AddEpilogue \ - ".att_syntax prefix;" \ - : "=a" (result)\ - : "d" (C), "a" (A), "D" (B), "c" (N) \ - : "%esi", "memory", "cc" \ - );\ - return result; - #define MulPrologue \ - __asm__ __volatile__ \ - ( \ - ".intel_syntax noprefix;" \ - AS1( push ebx) \ - AS2( mov ebx, edx) - #define MulEpilogue \ - AS1( pop ebx) \ - ".att_syntax prefix;" \ - : \ - : "d" (s_maskLow16), "c" (C), "a" (A), "D" (B) \ - : "%esi", "memory", "cc" \ - ); - #define SquPrologue MulPrologue - #define SquEpilogue \ - AS1( pop ebx) \ - ".att_syntax prefix;" \ - : \ - : "d" (s_maskLow16), "c" (C), "a" (A) \ - : "%esi", "%edi", "memory", "cc" \ - ); - #define TopPrologue MulPrologue - #define TopEpilogue \ - AS1( pop ebx) \ - ".att_syntax prefix;" \ - : \ - : "d" (s_maskLow16), "c" (C), "a" (A), "D" (B), "S" (L) \ - : "memory", "cc" \ - ); -#else - #define AddPrologue \ - __asm push edi \ - __asm push esi \ - __asm mov eax, [esp+12] \ - __asm mov edi, [esp+16] - #define AddEpilogue \ - __asm pop esi \ - __asm pop edi \ - __asm ret 8 -#if _MSC_VER < 1300 - #define SaveEBX __asm push ebx - #define RestoreEBX __asm pop ebx -#else - #define SaveEBX - #define RestoreEBX -#endif - #define SquPrologue \ - AS2( mov eax, A) \ - AS2( mov ecx, C) \ - SaveEBX \ - AS2( lea ebx, s_maskLow16) - #define MulPrologue \ - AS2( mov eax, A) \ - AS2( mov edi, B) \ - AS2( mov ecx, C) \ - SaveEBX \ - AS2( lea ebx, s_maskLow16) - #define TopPrologue \ - AS2( mov eax, A) \ - AS2( mov edi, B) \ - AS2( mov ecx, C) \ - AS2( mov esi, L) \ - SaveEBX \ - AS2( lea ebx, s_maskLow16) - #define SquEpilogue RestoreEBX - #define MulEpilogue RestoreEBX - #define TopEpilogue RestoreEBX -#endif - -#ifdef CRYPTOPP_X64_MASM_AVAILABLE -extern "C" { -int Baseline_Add(size_t N, word *C, const word *A, const word *B); -int Baseline_Sub(size_t N, word *C, const word *A, const word *B); -} -#elif defined(CRYPTOPP_X64_ASM_AVAILABLE) && defined(__GNUC__) && defined(CRYPTOPP_WORD128_AVAILABLE) -int Baseline_Add(size_t N, word *C, const word *A, const word *B) -{ - word result; - __asm__ __volatile__ - ( - ".intel_syntax;" - AS1( neg %1) - ASJ( jz, 1, f) - AS2( mov %0,[%3+8*%1]) - AS2( add %0,[%4+8*%1]) - AS2( mov [%2+8*%1],%0) - ASL(0) - AS2( mov %0,[%3+8*%1+8]) - AS2( adc %0,[%4+8*%1+8]) - AS2( mov [%2+8*%1+8],%0) - AS2( lea %1,[%1+2]) - ASJ( jrcxz, 1, f) - AS2( mov %0,[%3+8*%1]) - AS2( adc %0,[%4+8*%1]) - AS2( mov [%2+8*%1],%0) - ASJ( jmp, 0, b) - ASL(1) - AS2( mov %0, 0) - AS2( adc %0, %0) - ".att_syntax;" - : "=&r" (result), "+c" (N) - : "r" (C+N), "r" (A+N), "r" (B+N) - : "memory", "cc" - ); - return (int)result; -} - -int Baseline_Sub(size_t N, word *C, const word *A, const word *B) -{ - word result; - __asm__ __volatile__ - ( - ".intel_syntax;" - AS1( neg %1) - ASJ( jz, 1, f) - AS2( mov %0,[%3+8*%1]) - AS2( sub %0,[%4+8*%1]) - AS2( mov [%2+8*%1],%0) - ASL(0) - AS2( mov %0,[%3+8*%1+8]) - AS2( sbb %0,[%4+8*%1+8]) - AS2( mov [%2+8*%1+8],%0) - AS2( lea %1,[%1+2]) - ASJ( jrcxz, 1, f) - AS2( mov %0,[%3+8*%1]) - AS2( sbb %0,[%4+8*%1]) - AS2( mov [%2+8*%1],%0) - ASJ( jmp, 0, b) - ASL(1) - AS2( mov %0, 0) - AS2( adc %0, %0) - ".att_syntax;" - : "=&r" (result), "+c" (N) - : "r" (C+N), "r" (A+N), "r" (B+N) - : "memory", "cc" - ); - return (int)result; -} -#elif defined(CRYPTOPP_X86_ASM_AVAILABLE) && CRYPTOPP_BOOL_X86 -CRYPTOPP_NAKED int CRYPTOPP_FASTCALL Baseline_Add(size_t N, word *C, const word *A, const word *B) -{ - AddPrologue - - // now: eax = A, edi = B, edx = C, ecx = N - AS2( lea eax, [eax+4*ecx]) - AS2( lea edi, [edi+4*ecx]) - AS2( lea edx, [edx+4*ecx]) - - AS1( neg ecx) // ecx is negative index - AS2( test ecx, 2) // this clears carry flag - ASJ( jz, 0, f) - AS2( sub ecx, 2) - ASJ( jmp, 1, f) - - ASL(0) - ASJ( jecxz, 2, f) // loop until ecx overflows and becomes zero - AS2( mov esi,[eax+4*ecx]) - AS2( adc esi,[edi+4*ecx]) - AS2( mov [edx+4*ecx],esi) - AS2( mov esi,[eax+4*ecx+4]) - AS2( adc esi,[edi+4*ecx+4]) - AS2( mov [edx+4*ecx+4],esi) - ASL(1) - AS2( mov esi,[eax+4*ecx+8]) - AS2( adc esi,[edi+4*ecx+8]) - AS2( mov [edx+4*ecx+8],esi) - AS2( mov esi,[eax+4*ecx+12]) - AS2( adc esi,[edi+4*ecx+12]) - AS2( mov [edx+4*ecx+12],esi) - - AS2( lea ecx,[ecx+4]) // advance index, avoid inc which causes slowdown on Intel Core 2 - ASJ( jmp, 0, b) - - ASL(2) - AS2( mov eax, 0) - AS1( setc al) // store carry into eax (return result register) - - AddEpilogue -} - -CRYPTOPP_NAKED int CRYPTOPP_FASTCALL Baseline_Sub(size_t N, word *C, const word *A, const word *B) -{ - AddPrologue - - // now: eax = A, edi = B, edx = C, ecx = N - AS2( lea eax, [eax+4*ecx]) - AS2( lea edi, [edi+4*ecx]) - AS2( lea edx, [edx+4*ecx]) - - AS1( neg ecx) // ecx is negative index - AS2( test ecx, 2) // this clears carry flag - ASJ( jz, 0, f) - AS2( sub ecx, 2) - ASJ( jmp, 1, f) - - ASL(0) - ASJ( jecxz, 2, f) // loop until ecx overflows and becomes zero - AS2( mov esi,[eax+4*ecx]) - AS2( sbb esi,[edi+4*ecx]) - AS2( mov [edx+4*ecx],esi) - AS2( mov esi,[eax+4*ecx+4]) - AS2( sbb esi,[edi+4*ecx+4]) - AS2( mov [edx+4*ecx+4],esi) - ASL(1) - AS2( mov esi,[eax+4*ecx+8]) - AS2( sbb esi,[edi+4*ecx+8]) - AS2( mov [edx+4*ecx+8],esi) - AS2( mov esi,[eax+4*ecx+12]) - AS2( sbb esi,[edi+4*ecx+12]) - AS2( mov [edx+4*ecx+12],esi) - - AS2( lea ecx,[ecx+4]) // advance index, avoid inc which causes slowdown on Intel Core 2 - ASJ( jmp, 0, b) - - ASL(2) - AS2( mov eax, 0) - AS1( setc al) // store carry into eax (return result register) - - AddEpilogue -} - -#if CRYPTOPP_INTEGER_SSE2 -CRYPTOPP_NAKED int CRYPTOPP_FASTCALL SSE2_Add(size_t N, word *C, const word *A, const word *B) -{ - AddPrologue - - // now: eax = A, edi = B, edx = C, ecx = N - AS2( lea eax, [eax+4*ecx]) - AS2( lea edi, [edi+4*ecx]) - AS2( lea edx, [edx+4*ecx]) - - AS1( neg ecx) // ecx is negative index - AS2( pxor mm2, mm2) - ASJ( jz, 2, f) - AS2( test ecx, 2) // this clears carry flag - ASJ( jz, 0, f) - AS2( sub ecx, 2) - ASJ( jmp, 1, f) - - ASL(0) - AS2( movd mm0, DWORD PTR [eax+4*ecx]) - AS2( movd mm1, DWORD PTR [edi+4*ecx]) - AS2( paddq mm0, mm1) - AS2( paddq mm2, mm0) - AS2( movd DWORD PTR [edx+4*ecx], mm2) - AS2( psrlq mm2, 32) - - AS2( movd mm0, DWORD PTR [eax+4*ecx+4]) - AS2( movd mm1, DWORD PTR [edi+4*ecx+4]) - AS2( paddq mm0, mm1) - AS2( paddq mm2, mm0) - AS2( movd DWORD PTR [edx+4*ecx+4], mm2) - AS2( psrlq mm2, 32) - - ASL(1) - AS2( movd mm0, DWORD PTR [eax+4*ecx+8]) - AS2( movd mm1, DWORD PTR [edi+4*ecx+8]) - AS2( paddq mm0, mm1) - AS2( paddq mm2, mm0) - AS2( movd DWORD PTR [edx+4*ecx+8], mm2) - AS2( psrlq mm2, 32) - - AS2( movd mm0, DWORD PTR [eax+4*ecx+12]) - AS2( movd mm1, DWORD PTR [edi+4*ecx+12]) - AS2( paddq mm0, mm1) - AS2( paddq mm2, mm0) - AS2( movd DWORD PTR [edx+4*ecx+12], mm2) - AS2( psrlq mm2, 32) - - AS2( add ecx, 4) - ASJ( jnz, 0, b) - - ASL(2) - AS2( movd eax, mm2) - AS1( emms) - - AddEpilogue -} -CRYPTOPP_NAKED int CRYPTOPP_FASTCALL SSE2_Sub(size_t N, word *C, const word *A, const word *B) -{ - AddPrologue - - // now: eax = A, edi = B, edx = C, ecx = N - AS2( lea eax, [eax+4*ecx]) - AS2( lea edi, [edi+4*ecx]) - AS2( lea edx, [edx+4*ecx]) - - AS1( neg ecx) // ecx is negative index - AS2( pxor mm2, mm2) - ASJ( jz, 2, f) - AS2( test ecx, 2) // this clears carry flag - ASJ( jz, 0, f) - AS2( sub ecx, 2) - ASJ( jmp, 1, f) - - ASL(0) - AS2( movd mm0, DWORD PTR [eax+4*ecx]) - AS2( movd mm1, DWORD PTR [edi+4*ecx]) - AS2( psubq mm0, mm1) - AS2( psubq mm0, mm2) - AS2( movd DWORD PTR [edx+4*ecx], mm0) - AS2( psrlq mm0, 63) - - AS2( movd mm2, DWORD PTR [eax+4*ecx+4]) - AS2( movd mm1, DWORD PTR [edi+4*ecx+4]) - AS2( psubq mm2, mm1) - AS2( psubq mm2, mm0) - AS2( movd DWORD PTR [edx+4*ecx+4], mm2) - AS2( psrlq mm2, 63) - - ASL(1) - AS2( movd mm0, DWORD PTR [eax+4*ecx+8]) - AS2( movd mm1, DWORD PTR [edi+4*ecx+8]) - AS2( psubq mm0, mm1) - AS2( psubq mm0, mm2) - AS2( movd DWORD PTR [edx+4*ecx+8], mm0) - AS2( psrlq mm0, 63) - - AS2( movd mm2, DWORD PTR [eax+4*ecx+12]) - AS2( movd mm1, DWORD PTR [edi+4*ecx+12]) - AS2( psubq mm2, mm1) - AS2( psubq mm2, mm0) - AS2( movd DWORD PTR [edx+4*ecx+12], mm2) - AS2( psrlq mm2, 63) - - AS2( add ecx, 4) - ASJ( jnz, 0, b) - - ASL(2) - AS2( movd eax, mm2) - AS1( emms) - - AddEpilogue -} -#endif // #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE -#else -int CRYPTOPP_FASTCALL Baseline_Add(size_t N, word *C, const word *A, const word *B) -{ - assert (N%2 == 0); - - Declare2Words(u); - AssignWord(u, 0); - for (size_t i=0; i=2 && N%2==0); - - if (N <= s_recursionLimit) - s_pMul[N/4](R, A, B); - else - { - const size_t N2 = N/2; - - size_t AN2 = Compare(A0, A1, N2) > 0 ? 0 : N2; - Subtract(R0, A + AN2, A + (N2 ^ AN2), N2); - - size_t BN2 = Compare(B0, B1, N2) > 0 ? 0 : N2; - Subtract(R1, B + BN2, B + (N2 ^ BN2), N2); - - RecursiveMultiply(R2, T2, A1, B1, N2); - RecursiveMultiply(T0, T2, R0, R1, N2); - RecursiveMultiply(R0, T2, A0, B0, N2); - - // now T[01] holds (A1-A0)*(B0-B1), R[01] holds A0*B0, R[23] holds A1*B1 - - int c2 = Add(R2, R2, R1, N2); - int c3 = c2; - c2 += Add(R1, R2, R0, N2); - c3 += Add(R2, R2, R3, N2); - - if (AN2 == BN2) - c3 -= Subtract(R1, R1, T0, N); - else - c3 += Add(R1, R1, T0, N); - - c3 += Increment(R2, N2, c2); - assert (c3 >= 0 && c3 <= 2); - Increment(R3, N2, c3); - } -} - -// R[2*N] - result = A*A -// T[2*N] - temporary work space -// A[N] --- number to be squared - -void RecursiveSquare(word *R, word *T, const word *A, size_t N) -{ - assert(N && N%2==0); - - if (N <= s_recursionLimit) - s_pSqu[N/4](R, A); - else - { - const size_t N2 = N/2; - - RecursiveSquare(R0, T2, A0, N2); - RecursiveSquare(R2, T2, A1, N2); - RecursiveMultiply(T0, T2, A0, A1, N2); - - int carry = Add(R1, R1, T0, N); - carry += Add(R1, R1, T0, N); - Increment(R3, N2, carry); - } -} - -// R[N] - bottom half of A*B -// T[3*N/2] - temporary work space -// A[N] - multiplier -// B[N] - multiplicant - -void RecursiveMultiplyBottom(word *R, word *T, const word *A, const word *B, size_t N) -{ - assert(N>=2 && N%2==0); - - if (N <= s_recursionLimit) - s_pBot[N/4](R, A, B); - else - { - const size_t N2 = N/2; - - RecursiveMultiply(R, T, A0, B0, N2); - RecursiveMultiplyBottom(T0, T1, A1, B0, N2); - Add(R1, R1, T0, N2); - RecursiveMultiplyBottom(T0, T1, A0, B1, N2); - Add(R1, R1, T0, N2); - } -} - -// R[N] --- upper half of A*B -// T[2*N] - temporary work space -// L[N] --- lower half of A*B -// A[N] --- multiplier -// B[N] --- multiplicant - -void MultiplyTop(word *R, word *T, const word *L, const word *A, const word *B, size_t N) -{ - assert(N>=2 && N%2==0); - - if (N <= s_recursionLimit) - s_pTop[N/4](R, A, B, L[N-1]); - else - { - const size_t N2 = N/2; - - size_t AN2 = Compare(A0, A1, N2) > 0 ? 0 : N2; - Subtract(R0, A + AN2, A + (N2 ^ AN2), N2); - - size_t BN2 = Compare(B0, B1, N2) > 0 ? 0 : N2; - Subtract(R1, B + BN2, B + (N2 ^ BN2), N2); - - RecursiveMultiply(T0, T2, R0, R1, N2); - RecursiveMultiply(R0, T2, A1, B1, N2); - - // now T[01] holds (A1-A0)*(B0-B1) = A1*B0+A0*B1-A1*B1-A0*B0, R[01] holds A1*B1 - - int t, c3; - int c2 = Subtract(T2, L+N2, L, N2); - - if (AN2 == BN2) - { - c2 -= Add(T2, T2, T0, N2); - t = (Compare(T2, R0, N2) == -1); - c3 = t - Subtract(T2, T2, T1, N2); - } - else - { - c2 += Subtract(T2, T2, T0, N2); - t = (Compare(T2, R0, N2) == -1); - c3 = t + Add(T2, T2, T1, N2); - } - - c2 += t; - if (c2 >= 0) - c3 += Increment(T2, N2, c2); - else - c3 -= Decrement(T2, N2, -c2); - c3 += Add(R0, T2, R1, N2); - - assert (c3 >= 0 && c3 <= 2); - Increment(R1, N2, c3); - } -} - -inline void Multiply(word *R, word *T, const word *A, const word *B, size_t N) -{ - RecursiveMultiply(R, T, A, B, N); -} - -inline void Square(word *R, word *T, const word *A, size_t N) -{ - RecursiveSquare(R, T, A, N); -} - -inline void MultiplyBottom(word *R, word *T, const word *A, const word *B, size_t N) -{ - RecursiveMultiplyBottom(R, T, A, B, N); -} - -// R[NA+NB] - result = A*B -// T[NA+NB] - temporary work space -// A[NA] ---- multiplier -// B[NB] ---- multiplicant - -void AsymmetricMultiply(word *R, word *T, const word *A, size_t NA, const word *B, size_t NB) -{ - if (NA == NB) - { - if (A == B) - Square(R, T, A, NA); - else - Multiply(R, T, A, B, NA); - - return; - } - - if (NA > NB) - { - std::swap(A, B); - std::swap(NA, NB); - } - - assert(NB % NA == 0); - - if (NA==2 && !A[1]) - { - switch (A[0]) - { - case 0: - SetWords(R, 0, NB+2); - return; - case 1: - CopyWords(R, B, NB); - R[NB] = R[NB+1] = 0; - return; - default: - R[NB] = LinearMultiply(R, B, A[0], NB); - R[NB+1] = 0; - return; - } - } - - size_t i; - if ((NB/NA)%2 == 0) - { - Multiply(R, T, A, B, NA); - CopyWords(T+2*NA, R+NA, NA); - - for (i=2*NA; i=4); - -#define M0 M -#define M1 (M+N2) -#define V0 V -#define V1 (V+N2) - -#define X0 X -#define X1 (X+N2) -#define X2 (X+N) -#define X3 (X+N+N2) - - const size_t N2 = N/2; - Multiply(T0, T2, V0, X3, N2); - int c2 = Add(T0, T0, X0, N); - MultiplyBottom(T3, T2, T0, U, N2); - MultiplyTop(T2, R, T0, T3, M0, N2); - c2 -= Subtract(T2, T1, T2, N2); - Multiply(T0, R, T3, M1, N2); - c2 -= Subtract(T0, T2, T0, N2); - int c3 = -(int)Subtract(T1, X2, T1, N2); - Multiply(R0, T2, V1, X3, N2); - c3 += Add(R, R, T, N); - - if (c2>0) - c3 += Increment(R1, N2); - else if (c2<0) - c3 -= Decrement(R1, N2, -c2); - - assert(c3>=-1 && c3<=1); - if (c3>0) - Subtract(R, R, M, N); - else if (c3<0) - Add(R, R, M, N); - -#undef M0 -#undef M1 -#undef V0 -#undef V1 - -#undef X0 -#undef X1 -#undef X2 -#undef X3 -} - -#undef A0 -#undef A1 -#undef B0 -#undef B1 - -#undef T0 -#undef T1 -#undef T2 -#undef T3 - -#undef R0 -#undef R1 -#undef R2 -#undef R3 - -/* -// do a 3 word by 2 word divide, returns quotient and leaves remainder in A -static word SubatomicDivide(word *A, word B0, word B1) -{ - // assert {A[2],A[1]} < {B1,B0}, so quotient can fit in a word - assert(A[2] < B1 || (A[2]==B1 && A[1] < B0)); - - // estimate the quotient: do a 2 word by 1 word divide - word Q; - if (B1+1 == 0) - Q = A[2]; - else - Q = DWord(A[1], A[2]).DividedBy(B1+1); - - // now subtract Q*B from A - DWord p = DWord::Multiply(B0, Q); - DWord u = (DWord) A[0] - p.GetLowHalf(); - A[0] = u.GetLowHalf(); - u = (DWord) A[1] - p.GetHighHalf() - u.GetHighHalfAsBorrow() - DWord::Multiply(B1, Q); - A[1] = u.GetLowHalf(); - A[2] += u.GetHighHalf(); - - // Q <= actual quotient, so fix it - while (A[2] || A[1] > B1 || (A[1]==B1 && A[0]>=B0)) - { - u = (DWord) A[0] - B0; - A[0] = u.GetLowHalf(); - u = (DWord) A[1] - B1 - u.GetHighHalfAsBorrow(); - A[1] = u.GetLowHalf(); - A[2] += u.GetHighHalf(); - Q++; - assert(Q); // shouldn't overflow - } - - return Q; -} - -// do a 4 word by 2 word divide, returns 2 word quotient in Q0 and Q1 -static inline void AtomicDivide(word *Q, const word *A, const word *B) -{ - if (!B[0] && !B[1]) // if divisor is 0, we assume divisor==2**(2*WORD_BITS) - { - Q[0] = A[2]; - Q[1] = A[3]; - } - else - { - word T[4]; - T[0] = A[0]; T[1] = A[1]; T[2] = A[2]; T[3] = A[3]; - Q[1] = SubatomicDivide(T+1, B[0], B[1]); - Q[0] = SubatomicDivide(T, B[0], B[1]); - -#ifndef NDEBUG - // multiply quotient and divisor and add remainder, make sure it equals dividend - assert(!T[2] && !T[3] && (T[1] < B[1] || (T[1]==B[1] && T[0](T, DWord(A[0], A[1]), DWord(A[2], A[3]), DWord(B[0], B[1])); - Q[0] = q.GetLowHalf(); - Q[1] = q.GetHighHalf(); - -#ifndef NDEBUG - if (B[0] || B[1]) - { - // multiply quotient and divisor and add remainder, make sure it equals dividend - assert(!T[2] && !T[3] && (T[1] < B[1] || (T[1]==B[1] && T[0]= 0) - { - R[N] -= Subtract(R, R, B, N); - Q[1] += (++Q[0]==0); - assert(Q[0] || Q[1]); // no overflow - } -} - -// R[NB] -------- remainder = A%B -// Q[NA-NB+2] --- quotient = A/B -// T[NA+3*(NB+2)] - temp work space -// A[NA] -------- dividend -// B[NB] -------- divisor - -void Divide(word *R, word *Q, word *T, const word *A, size_t NA, const word *B, size_t NB) -{ - assert(NA && NB && NA%2==0 && NB%2==0); - assert(B[NB-1] || B[NB-2]); - assert(NB <= NA); - - // set up temporary work space - word *const TA=T; - word *const TB=T+NA+2; - word *const TP=T+NA+2+NB; - - // copy B into TB and normalize it so that TB has highest bit set to 1 - unsigned shiftWords = (B[NB-1]==0); - TB[0] = TB[NB-1] = 0; - CopyWords(TB+shiftWords, B, NB-shiftWords); - unsigned shiftBits = WORD_BITS - BitPrecision(TB[NB-1]); - assert(shiftBits < WORD_BITS); - ShiftWordsLeftByBits(TB, NB, shiftBits); - - // copy A into TA and normalize it - TA[0] = TA[NA] = TA[NA+1] = 0; - CopyWords(TA+shiftWords, A, NA); - ShiftWordsLeftByBits(TA, NA+2, shiftBits); - - if (TA[NA+1]==0 && TA[NA] <= 1) - { - Q[NA-NB+1] = Q[NA-NB] = 0; - while (TA[NA] || Compare(TA+NA-NB, TB, NB) >= 0) - { - TA[NA] -= Subtract(TA+NA-NB, TA+NA-NB, TB, NB); - ++Q[NA-NB]; - } - } - else - { - NA+=2; - assert(Compare(TA+NA-NB, TB, NB) < 0); - } - - word BT[2]; - BT[0] = TB[NB-2] + 1; - BT[1] = TB[NB-1] + (BT[0]==0); - - // start reducing TA mod TB, 2 words at a time - for (size_t i=NA-2; i>=NB; i-=2) - { - AtomicDivide(Q+i-NB, TA+i-2, BT); - CorrectQuotientEstimate(TA+i-NB, TP, Q+i-NB, TB, NB); - } - - // copy TA into R, and denormalize it - CopyWords(R, TA+shiftWords, NB); - ShiftWordsRightByBits(R, NB, shiftBits); -} - -static inline size_t EvenWordCount(const word *X, size_t N) -{ - while (N && X[N-2]==0 && X[N-1]==0) - N-=2; - return N; -} - -// return k -// R[N] --- result = A^(-1) * 2^k mod M -// T[4*N] - temporary work space -// A[NA] -- number to take inverse of -// M[N] --- modulus - -unsigned int AlmostInverse(word *R, word *T, const word *A, size_t NA, const word *M, size_t N) -{ - assert(NA<=N && N && N%2==0); - - word *b = T; - word *c = T+N; - word *f = T+2*N; - word *g = T+3*N; - size_t bcLen=2, fgLen=EvenWordCount(M, N); - unsigned int k=0, s=0; - - SetWords(T, 0, 3*N); - b[0]=1; - CopyWords(f, A, NA); - CopyWords(g, M, N); - - while (1) - { - word t=f[0]; - while (!t) - { - if (EvenWordCount(f, fgLen)==0) - { - SetWords(R, 0, N); - return 0; - } - - ShiftWordsRightByWords(f, fgLen, 1); - if (c[bcLen-1]) bcLen+=2; - assert(bcLen <= N); - ShiftWordsLeftByWords(c, bcLen, 1); - k+=WORD_BITS; - t=f[0]; - } - - unsigned int i=0; - while (t%2 == 0) - { - t>>=1; - i++; - } - k+=i; - - if (t==1 && f[1]==0 && EvenWordCount(f, fgLen)==2) - { - if (s%2==0) - CopyWords(R, b, N); - else - Subtract(R, M, b, N); - return k; - } - - ShiftWordsRightByBits(f, fgLen, i); - t=ShiftWordsLeftByBits(c, bcLen, i); - if (t) - { - c[bcLen] = t; - bcLen+=2; - assert(bcLen <= N); - } - - if (f[fgLen-2]==0 && g[fgLen-2]==0 && f[fgLen-1]==0 && g[fgLen-1]==0) - fgLen-=2; - - if (Compare(f, g, fgLen)==-1) - { - std::swap(f, g); - std::swap(b, c); - s++; - } - - Subtract(f, f, g, fgLen); - - if (Add(b, b, c, bcLen)) - { - b[bcLen] = 1; - bcLen+=2; - assert(bcLen <= N); - } - } -} - -// R[N] - result = A/(2^k) mod M -// A[N] - input -// M[N] - modulus - -void DivideByPower2Mod(word *R, const word *A, size_t k, const word *M, size_t N) -{ - CopyWords(R, A, N); - - while (k--) - { - if (R[0]%2==0) - ShiftWordsRightByBits(R, N, 1); - else - { - word carry = Add(R, R, M, N); - ShiftWordsRightByBits(R, N, 1); - R[N-1] += carry<<(WORD_BITS-1); - } - } -} - -// R[N] - result = A*(2^k) mod M -// A[N] - input -// M[N] - modulus - -void MultiplyByPower2Mod(word *R, const word *A, size_t k, const word *M, size_t N) -{ - CopyWords(R, A, N); - - while (k--) - if (ShiftWordsLeftByBits(R, N, 1) || Compare(R, M, N)>=0) - Subtract(R, R, M, N); -} - -// ****************************************************************** - -InitializeInteger::InitializeInteger() -{ - if (!g_pAssignIntToInteger) - { - SetFunctionPointers(); - g_pAssignIntToInteger = AssignIntToInteger; - } -} - -static const unsigned int RoundupSizeTable[] = {2, 2, 2, 4, 4, 8, 8, 8, 8}; - -static inline size_t RoundupSize(size_t n) -{ - if (n<=8) - return RoundupSizeTable[n]; - else if (n<=16) - return 16; - else if (n<=32) - return 32; - else if (n<=64) - return 64; - else return size_t(1) << BitPrecision(n-1); -} - -Integer::Integer() - : reg(2), sign(POSITIVE) -{ - reg[0] = reg[1] = 0; -} - -Integer::Integer(const Integer& t) - : reg(RoundupSize(t.WordCount())), sign(t.sign) -{ - CopyWords(reg, t.reg, reg.size()); -} - -Integer::Integer(Sign s, lword value) - : reg(2), sign(s) -{ - reg[0] = word(value); - reg[1] = word(SafeRightShift(value)); -} - -Integer::Integer(signed long value) - : reg(2) -{ - if (value >= 0) - sign = POSITIVE; - else - { - sign = NEGATIVE; - value = -value; - } - reg[0] = word(value); - reg[1] = word(SafeRightShift((unsigned long)value)); -} - -Integer::Integer(Sign s, word high, word low) - : reg(2), sign(s) -{ - reg[0] = low; - reg[1] = high; -} - -bool Integer::IsConvertableToLong() const -{ - if (ByteCount() > sizeof(long)) - return false; - - unsigned long value = (unsigned long)reg[0]; - value += SafeLeftShift((unsigned long)reg[1]); - - if (sign==POSITIVE) - return (signed long)value >= 0; - else - return -(signed long)value < 0; -} - -signed long Integer::ConvertToLong() const -{ - assert(IsConvertableToLong()); - - unsigned long value = (unsigned long)reg[0]; - value += SafeLeftShift((unsigned long)reg[1]); - return sign==POSITIVE ? value : -(signed long)value; -} - -Integer::Integer(BufferedTransformation &encodedInteger, size_t byteCount, Signedness s) -{ - Decode(encodedInteger, byteCount, s); -} - -Integer::Integer(const byte *encodedInteger, size_t byteCount, Signedness s) -{ - Decode(encodedInteger, byteCount, s); -} - -Integer::Integer(BufferedTransformation &bt) -{ - BERDecode(bt); -} - -Integer::Integer(RandomNumberGenerator &rng, size_t bitcount) -{ - Randomize(rng, bitcount); -} - -Integer::Integer(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType, const Integer &equiv, const Integer &mod) -{ - if (!Randomize(rng, min, max, rnType, equiv, mod)) - throw Integer::RandomNumberNotFound(); -} - -Integer Integer::Power2(size_t e) -{ - Integer r((word)0, BitsToWords(e+1)); - r.SetBit(e); - return r; -} - -template -struct NewInteger -{ - Integer * operator()() const - { - return new Integer(i); - } -}; - -const Integer &Integer::Zero() -{ - return Singleton().Ref(); -} - -const Integer &Integer::One() -{ - return Singleton >().Ref(); -} - -const Integer &Integer::Two() -{ - return Singleton >().Ref(); -} - -bool Integer::operator!() const -{ - return IsNegative() ? false : (reg[0]==0 && WordCount()==0); -} - -Integer& Integer::operator=(const Integer& t) -{ - if (this != &t) - { - if (reg.size() != t.reg.size() || t.reg[t.reg.size()/2] == 0) - reg.New(RoundupSize(t.WordCount())); - CopyWords(reg, t.reg, reg.size()); - sign = t.sign; - } - return *this; -} - -bool Integer::GetBit(size_t n) const -{ - if (n/WORD_BITS >= reg.size()) - return 0; - else - return bool((reg[n/WORD_BITS] >> (n % WORD_BITS)) & 1); -} - -void Integer::SetBit(size_t n, bool value) -{ - if (value) - { - reg.CleanGrow(RoundupSize(BitsToWords(n+1))); - reg[n/WORD_BITS] |= (word(1) << (n%WORD_BITS)); - } - else - { - if (n/WORD_BITS < reg.size()) - reg[n/WORD_BITS] &= ~(word(1) << (n%WORD_BITS)); - } -} - -byte Integer::GetByte(size_t n) const -{ - if (n/WORD_SIZE >= reg.size()) - return 0; - else - return byte(reg[n/WORD_SIZE] >> ((n%WORD_SIZE)*8)); -} - -void Integer::SetByte(size_t n, byte value) -{ - reg.CleanGrow(RoundupSize(BytesToWords(n+1))); - reg[n/WORD_SIZE] &= ~(word(0xff) << 8*(n%WORD_SIZE)); - reg[n/WORD_SIZE] |= (word(value) << 8*(n%WORD_SIZE)); -} - -lword Integer::GetBits(size_t i, size_t n) const -{ - lword v = 0; - assert(n <= sizeof(v)*8); - for (unsigned int j=0; j -static Integer StringToInteger(const T *str) -{ - int radix; - // GCC workaround - // std::char_traits::length() not defined in GCC 3.2 and STLport 4.5.3 - unsigned int length; - for (length = 0; str[length] != 0; length++) {} - - Integer v; - - if (length == 0) - return v; - - switch (str[length-1]) - { - case 'h': - case 'H': - radix=16; - break; - case 'o': - case 'O': - radix=8; - break; - case 'b': - case 'B': - radix=2; - break; - default: - radix=10; - } - - if (length > 2 && str[0] == '0' && str[1] == 'x') - radix = 16; - - for (unsigned i=0; i= '0' && str[i] <= '9') - digit = str[i] - '0'; - else if (str[i] >= 'A' && str[i] <= 'F') - digit = str[i] - 'A' + 10; - else if (str[i] >= 'a' && str[i] <= 'f') - digit = str[i] - 'a' + 10; - else - digit = radix; - - if (digit < radix) - { - v *= radix; - v += digit; - } - } - - if (str[0] == '-') - v.Negate(); - - return v; -} - -Integer::Integer(const char *str) - : reg(2), sign(POSITIVE) -{ - *this = StringToInteger(str); -} - -Integer::Integer(const wchar_t *str) - : reg(2), sign(POSITIVE) -{ - *this = StringToInteger(str); -} - -unsigned int Integer::WordCount() const -{ - return (unsigned int)CountWords(reg, reg.size()); -} - -unsigned int Integer::ByteCount() const -{ - unsigned wordCount = WordCount(); - if (wordCount) - return (wordCount-1)*WORD_SIZE + BytePrecision(reg[wordCount-1]); - else - return 0; -} - -unsigned int Integer::BitCount() const -{ - unsigned wordCount = WordCount(); - if (wordCount) - return (wordCount-1)*WORD_BITS + BitPrecision(reg[wordCount-1]); - else - return 0; -} - -void Integer::Decode(const byte *input, size_t inputLen, Signedness s) -{ - StringStore store(input, inputLen); - Decode(store, inputLen, s); -} - -void Integer::Decode(BufferedTransformation &bt, size_t inputLen, Signedness s) -{ - assert(bt.MaxRetrievable() >= inputLen); - - byte b; - bt.Peek(b); - sign = ((s==SIGNED) && (b & 0x80)) ? NEGATIVE : POSITIVE; - - while (inputLen>0 && (sign==POSITIVE ? b==0 : b==0xff)) - { - bt.Skip(1); - inputLen--; - bt.Peek(b); - } - - reg.CleanNew(RoundupSize(BytesToWords(inputLen))); - - for (size_t i=inputLen; i > 0; i--) - { - bt.Get(b); - reg[(i-1)/WORD_SIZE] |= word(b) << ((i-1)%WORD_SIZE)*8; - } - - if (sign == NEGATIVE) - { - for (size_t i=inputLen; i 0; i--) - bt.Put(GetByte(i-1)); - } - else - { - // take two's complement of *this - Integer temp = Integer::Power2(8*STDMAX((size_t)ByteCount(), outputLen)) + *this; - temp.Encode(bt, outputLen, UNSIGNED); - } -} - -void Integer::DEREncode(BufferedTransformation &bt) const -{ - DERGeneralEncoder enc(bt, INTEGER); - Encode(enc, MinEncodedSize(SIGNED), SIGNED); - enc.MessageEnd(); -} - -void Integer::BERDecode(const byte *input, size_t len) -{ - StringStore store(input, len); - BERDecode(store); -} - -void Integer::BERDecode(BufferedTransformation &bt) -{ - BERGeneralDecoder dec(bt, INTEGER); - if (!dec.IsDefiniteLength() || dec.MaxRetrievable() < dec.RemainingLength()) - BERDecodeError(); - Decode(dec, (size_t)dec.RemainingLength(), SIGNED); - dec.MessageEnd(); -} - -void Integer::DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const -{ - DERGeneralEncoder enc(bt, OCTET_STRING); - Encode(enc, length); - enc.MessageEnd(); -} - -void Integer::BERDecodeAsOctetString(BufferedTransformation &bt, size_t length) -{ - BERGeneralDecoder dec(bt, OCTET_STRING); - if (!dec.IsDefiniteLength() || dec.RemainingLength() != length) - BERDecodeError(); - Decode(dec, length); - dec.MessageEnd(); -} - -size_t Integer::OpenPGPEncode(byte *output, size_t len) const -{ - ArraySink sink(output, len); - return OpenPGPEncode(sink); -} - -size_t Integer::OpenPGPEncode(BufferedTransformation &bt) const -{ - word16 bitCount = BitCount(); - bt.PutWord16(bitCount); - size_t byteCount = BitsToBytes(bitCount); - Encode(bt, byteCount); - return 2 + byteCount; -} - -void Integer::OpenPGPDecode(const byte *input, size_t len) -{ - StringStore store(input, len); - OpenPGPDecode(store); -} - -void Integer::OpenPGPDecode(BufferedTransformation &bt) -{ - word16 bitCount; - if (bt.GetWord16(bitCount) != 2 || bt.MaxRetrievable() < BitsToBytes(bitCount)) - throw OpenPGPDecodeErr(); - Decode(bt, BitsToBytes(bitCount)); -} - -void Integer::Randomize(RandomNumberGenerator &rng, size_t nbits) -{ - const size_t nbytes = nbits/8 + 1; - SecByteBlock buf(nbytes); - rng.GenerateBlock(buf, nbytes); - if (nbytes) - buf[0] = (byte)Crop(buf[0], nbits % 8); - Decode(buf, nbytes, UNSIGNED); -} - -void Integer::Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max) -{ - if (min > max) - throw InvalidArgument("Integer: Min must be no greater than Max"); - - Integer range = max - min; - const unsigned int nbits = range.BitCount(); - - do - { - Randomize(rng, nbits); - } - while (*this > range); - - *this += min; -} - -bool Integer::Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType, const Integer &equiv, const Integer &mod) -{ - return GenerateRandomNoThrow(rng, MakeParameters("Min", min)("Max", max)("RandomNumberType", rnType)("EquivalentTo", equiv)("Mod", mod)); -} - -class KDF2_RNG : public RandomNumberGenerator -{ -public: - KDF2_RNG(const byte *seed, size_t seedSize) - : m_counter(0), m_counterAndSeed(seedSize + 4) - { - memcpy(m_counterAndSeed + 4, seed, seedSize); - } - - void GenerateBlock(byte *output, size_t size) - { - PutWord(false, BIG_ENDIAN_ORDER, m_counterAndSeed, m_counter); - ++m_counter; - P1363_KDF2::DeriveKey(output, size, m_counterAndSeed, m_counterAndSeed.size(), NULL, 0); - } - -private: - word32 m_counter; - SecByteBlock m_counterAndSeed; -}; - -bool Integer::GenerateRandomNoThrow(RandomNumberGenerator &i_rng, const NameValuePairs ¶ms) -{ - Integer min = params.GetValueWithDefault("Min", Integer::Zero()); - Integer max; - if (!params.GetValue("Max", max)) - { - int bitLength; - if (params.GetIntValue("BitLength", bitLength)) - max = Integer::Power2(bitLength); - else - throw InvalidArgument("Integer: missing Max argument"); - } - if (min > max) - throw InvalidArgument("Integer: Min must be no greater than Max"); - - Integer equiv = params.GetValueWithDefault("EquivalentTo", Integer::Zero()); - Integer mod = params.GetValueWithDefault("Mod", Integer::One()); - - if (equiv.IsNegative() || equiv >= mod) - throw InvalidArgument("Integer: invalid EquivalentTo and/or Mod argument"); - - Integer::RandomNumberType rnType = params.GetValueWithDefault("RandomNumberType", Integer::ANY); - - member_ptr kdf2Rng; - ConstByteArrayParameter seed; - if (params.GetValue(Name::Seed(), seed)) - { - ByteQueue bq; - DERSequenceEncoder seq(bq); - min.DEREncode(seq); - max.DEREncode(seq); - equiv.DEREncode(seq); - mod.DEREncode(seq); - DEREncodeUnsigned(seq, rnType); - DEREncodeOctetString(seq, seed.begin(), seed.size()); - seq.MessageEnd(); - - SecByteBlock finalSeed((size_t)bq.MaxRetrievable()); - bq.Get(finalSeed, finalSeed.size()); - kdf2Rng.reset(new KDF2_RNG(finalSeed.begin(), finalSeed.size())); - } - RandomNumberGenerator &rng = kdf2Rng.get() ? (RandomNumberGenerator &)*kdf2Rng : i_rng; - - switch (rnType) - { - case ANY: - if (mod == One()) - Randomize(rng, min, max); - else - { - Integer min1 = min + (equiv-min)%mod; - if (max < min1) - return false; - Randomize(rng, Zero(), (max - min1) / mod); - *this *= mod; - *this += min1; - } - return true; - - case PRIME: - { - const PrimeSelector *pSelector = params.GetValueWithDefault(Name::PointerToPrimeSelector(), (const PrimeSelector *)NULL); - - int i; - i = 0; - while (1) - { - if (++i==16) - { - // check if there are any suitable primes in [min, max] - Integer first = min; - if (FirstPrime(first, max, equiv, mod, pSelector)) - { - // if there is only one suitable prime, we're done - *this = first; - if (!FirstPrime(first, max, equiv, mod, pSelector)) - return true; - } - else - return false; - } - - Randomize(rng, min, max); - if (FirstPrime(*this, STDMIN(*this+mod*PrimeSearchInterval(max), max), equiv, mod, pSelector)) - return true; - } - } - - default: - throw InvalidArgument("Integer: invalid RandomNumberType argument"); - } -} - -std::istream& operator>>(std::istream& in, Integer &a) -{ - char c; - unsigned int length = 0; - SecBlock str(length + 16); - - std::ws(in); - - do - { - in.read(&c, 1); - str[length++] = c; - if (length >= str.size()) - str.Grow(length + 16); - } - while (in && (c=='-' || c=='x' || (c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F') || c=='h' || c=='H' || c=='o' || c=='O' || c==',' || c=='.')); - - if (in.gcount()) - in.putback(c); - str[length-1] = '\0'; - a = Integer(str); - - return in; -} - -std::ostream& operator<<(std::ostream& out, const Integer &a) -{ - // Get relevant conversion specifications from ostream. - long f = out.flags() & std::ios::basefield; // Get base digits. - int base, block; - char suffix; - switch(f) - { - case std::ios::oct : - base = 8; - block = 8; - suffix = 'o'; - break; - case std::ios::hex : - base = 16; - block = 4; - suffix = 'h'; - break; - default : - base = 10; - block = 3; - suffix = '.'; - } - - Integer temp1=a, temp2; - - if (a.IsNegative()) - { - out << '-'; - temp1.Negate(); - } - - if (!a) - out << '0'; - - static const char upper[]="0123456789ABCDEF"; - static const char lower[]="0123456789abcdef"; - - const char* vec = (out.flags() & std::ios::uppercase) ? upper : lower; - unsigned i=0; - SecBlock s(a.BitCount() / (BitPrecision(base)-1) + 1); - - while (!!temp1) - { - word digit; - Integer::Divide(digit, temp2, temp1, base); - s[i++]=vec[digit]; - temp1.swap(temp2); - } - - while (i--) - { - out << s[i]; -// if (i && !(i%block)) -// out << ","; - } - return out << suffix; -} - -Integer& Integer::operator++() -{ - if (NotNegative()) - { - if (Increment(reg, reg.size())) - { - reg.CleanGrow(2*reg.size()); - reg[reg.size()/2]=1; - } - } - else - { - word borrow = Decrement(reg, reg.size()); - assert(!borrow); - if (WordCount()==0) - *this = Zero(); - } - return *this; -} - -Integer& Integer::operator--() -{ - if (IsNegative()) - { - if (Increment(reg, reg.size())) - { - reg.CleanGrow(2*reg.size()); - reg[reg.size()/2]=1; - } - } - else - { - if (Decrement(reg, reg.size())) - *this = -One(); - } - return *this; -} - -void PositiveAdd(Integer &sum, const Integer &a, const Integer& b) -{ - int carry; - if (a.reg.size() == b.reg.size()) - carry = Add(sum.reg, a.reg, b.reg, a.reg.size()); - else if (a.reg.size() > b.reg.size()) - { - carry = Add(sum.reg, a.reg, b.reg, b.reg.size()); - CopyWords(sum.reg+b.reg.size(), a.reg+b.reg.size(), a.reg.size()-b.reg.size()); - carry = Increment(sum.reg+b.reg.size(), a.reg.size()-b.reg.size(), carry); - } - else - { - carry = Add(sum.reg, a.reg, b.reg, a.reg.size()); - CopyWords(sum.reg+a.reg.size(), b.reg+a.reg.size(), b.reg.size()-a.reg.size()); - carry = Increment(sum.reg+a.reg.size(), b.reg.size()-a.reg.size(), carry); - } - - if (carry) - { - sum.reg.CleanGrow(2*sum.reg.size()); - sum.reg[sum.reg.size()/2] = 1; - } - sum.sign = Integer::POSITIVE; -} - -void PositiveSubtract(Integer &diff, const Integer &a, const Integer& b) -{ - unsigned aSize = a.WordCount(); - aSize += aSize%2; - unsigned bSize = b.WordCount(); - bSize += bSize%2; - - if (aSize == bSize) - { - if (Compare(a.reg, b.reg, aSize) >= 0) - { - Subtract(diff.reg, a.reg, b.reg, aSize); - diff.sign = Integer::POSITIVE; - } - else - { - Subtract(diff.reg, b.reg, a.reg, aSize); - diff.sign = Integer::NEGATIVE; - } - } - else if (aSize > bSize) - { - word borrow = Subtract(diff.reg, a.reg, b.reg, bSize); - CopyWords(diff.reg+bSize, a.reg+bSize, aSize-bSize); - borrow = Decrement(diff.reg+bSize, aSize-bSize, borrow); - assert(!borrow); - diff.sign = Integer::POSITIVE; - } - else - { - word borrow = Subtract(diff.reg, b.reg, a.reg, aSize); - CopyWords(diff.reg+aSize, b.reg+aSize, bSize-aSize); - borrow = Decrement(diff.reg+aSize, bSize-aSize, borrow); - assert(!borrow); - diff.sign = Integer::NEGATIVE; - } -} - -// MSVC .NET 2003 workaround -template inline const T& STDMAX2(const T& a, const T& b) -{ - return a < b ? b : a; -} - -Integer Integer::Plus(const Integer& b) const -{ - Integer sum((word)0, STDMAX2(reg.size(), b.reg.size())); - if (NotNegative()) - { - if (b.NotNegative()) - PositiveAdd(sum, *this, b); - else - PositiveSubtract(sum, *this, b); - } - else - { - if (b.NotNegative()) - PositiveSubtract(sum, b, *this); - else - { - PositiveAdd(sum, *this, b); - sum.sign = Integer::NEGATIVE; - } - } - return sum; -} - -Integer& Integer::operator+=(const Integer& t) -{ - reg.CleanGrow(t.reg.size()); - if (NotNegative()) - { - if (t.NotNegative()) - PositiveAdd(*this, *this, t); - else - PositiveSubtract(*this, *this, t); - } - else - { - if (t.NotNegative()) - PositiveSubtract(*this, t, *this); - else - { - PositiveAdd(*this, *this, t); - sign = Integer::NEGATIVE; - } - } - return *this; -} - -Integer Integer::Minus(const Integer& b) const -{ - Integer diff((word)0, STDMAX2(reg.size(), b.reg.size())); - if (NotNegative()) - { - if (b.NotNegative()) - PositiveSubtract(diff, *this, b); - else - PositiveAdd(diff, *this, b); - } - else - { - if (b.NotNegative()) - { - PositiveAdd(diff, *this, b); - diff.sign = Integer::NEGATIVE; - } - else - PositiveSubtract(diff, b, *this); - } - return diff; -} - -Integer& Integer::operator-=(const Integer& t) -{ - reg.CleanGrow(t.reg.size()); - if (NotNegative()) - { - if (t.NotNegative()) - PositiveSubtract(*this, *this, t); - else - PositiveAdd(*this, *this, t); - } - else - { - if (t.NotNegative()) - { - PositiveAdd(*this, *this, t); - sign = Integer::NEGATIVE; - } - else - PositiveSubtract(*this, t, *this); - } - return *this; -} - -Integer& Integer::operator<<=(size_t n) -{ - const size_t wordCount = WordCount(); - const size_t shiftWords = n / WORD_BITS; - const unsigned int shiftBits = (unsigned int)(n % WORD_BITS); - - reg.CleanGrow(RoundupSize(wordCount+BitsToWords(n))); - ShiftWordsLeftByWords(reg, wordCount + shiftWords, shiftWords); - ShiftWordsLeftByBits(reg+shiftWords, wordCount+BitsToWords(shiftBits), shiftBits); - return *this; -} - -Integer& Integer::operator>>=(size_t n) -{ - const size_t wordCount = WordCount(); - const size_t shiftWords = n / WORD_BITS; - const unsigned int shiftBits = (unsigned int)(n % WORD_BITS); - - ShiftWordsRightByWords(reg, wordCount, shiftWords); - if (wordCount > shiftWords) - ShiftWordsRightByBits(reg, wordCount-shiftWords, shiftBits); - if (IsNegative() && WordCount()==0) // avoid -0 - *this = Zero(); - return *this; -} - -void PositiveMultiply(Integer &product, const Integer &a, const Integer &b) -{ - size_t aSize = RoundupSize(a.WordCount()); - size_t bSize = RoundupSize(b.WordCount()); - - product.reg.CleanNew(RoundupSize(aSize+bSize)); - product.sign = Integer::POSITIVE; - - IntegerSecBlock workspace(aSize + bSize); - AsymmetricMultiply(product.reg, workspace, a.reg, aSize, b.reg, bSize); -} - -void Multiply(Integer &product, const Integer &a, const Integer &b) -{ - PositiveMultiply(product, a, b); - - if (a.NotNegative() != b.NotNegative()) - product.Negate(); -} - -Integer Integer::Times(const Integer &b) const -{ - Integer product; - Multiply(product, *this, b); - return product; -} - -/* -void PositiveDivide(Integer &remainder, Integer "ient, - const Integer ÷nd, const Integer &divisor) -{ - remainder.reg.CleanNew(divisor.reg.size()); - remainder.sign = Integer::POSITIVE; - quotient.reg.New(0); - quotient.sign = Integer::POSITIVE; - unsigned i=dividend.BitCount(); - while (i--) - { - word overflow = ShiftWordsLeftByBits(remainder.reg, remainder.reg.size(), 1); - remainder.reg[0] |= dividend[i]; - if (overflow || remainder >= divisor) - { - Subtract(remainder.reg, remainder.reg, divisor.reg, remainder.reg.size()); - quotient.SetBit(i); - } - } -} -*/ - -void PositiveDivide(Integer &remainder, Integer "ient, - const Integer &a, const Integer &b) -{ - unsigned aSize = a.WordCount(); - unsigned bSize = b.WordCount(); - - if (!bSize) - throw Integer::DivideByZero(); - - if (aSize < bSize) - { - remainder = a; - remainder.sign = Integer::POSITIVE; - quotient = Integer::Zero(); - return; - } - - aSize += aSize%2; // round up to next even number - bSize += bSize%2; - - remainder.reg.CleanNew(RoundupSize(bSize)); - remainder.sign = Integer::POSITIVE; - quotient.reg.CleanNew(RoundupSize(aSize-bSize+2)); - quotient.sign = Integer::POSITIVE; - - IntegerSecBlock T(aSize+3*(bSize+2)); - Divide(remainder.reg, quotient.reg, T, a.reg, aSize, b.reg, bSize); -} - -void Integer::Divide(Integer &remainder, Integer "ient, const Integer ÷nd, const Integer &divisor) -{ - PositiveDivide(remainder, quotient, dividend, divisor); - - if (dividend.IsNegative()) - { - quotient.Negate(); - if (remainder.NotZero()) - { - --quotient; - remainder = divisor.AbsoluteValue() - remainder; - } - } - - if (divisor.IsNegative()) - quotient.Negate(); -} - -void Integer::DivideByPowerOf2(Integer &r, Integer &q, const Integer &a, unsigned int n) -{ - q = a; - q >>= n; - - const size_t wordCount = BitsToWords(n); - if (wordCount <= a.WordCount()) - { - r.reg.resize(RoundupSize(wordCount)); - CopyWords(r.reg, a.reg, wordCount); - SetWords(r.reg+wordCount, 0, r.reg.size()-wordCount); - if (n % WORD_BITS != 0) - r.reg[wordCount-1] %= (word(1) << (n % WORD_BITS)); - } - else - { - r.reg.resize(RoundupSize(a.WordCount())); - CopyWords(r.reg, a.reg, r.reg.size()); - } - r.sign = POSITIVE; - - if (a.IsNegative() && r.NotZero()) - { - --q; - r = Power2(n) - r; - } -} - -Integer Integer::DividedBy(const Integer &b) const -{ - Integer remainder, quotient; - Integer::Divide(remainder, quotient, *this, b); - return quotient; -} - -Integer Integer::Modulo(const Integer &b) const -{ - Integer remainder, quotient; - Integer::Divide(remainder, quotient, *this, b); - return remainder; -} - -void Integer::Divide(word &remainder, Integer "ient, const Integer ÷nd, word divisor) -{ - if (!divisor) - throw Integer::DivideByZero(); - - assert(divisor); - - if ((divisor & (divisor-1)) == 0) // divisor is a power of 2 - { - quotient = dividend >> (BitPrecision(divisor)-1); - remainder = dividend.reg[0] & (divisor-1); - return; - } - - unsigned int i = dividend.WordCount(); - quotient.reg.CleanNew(RoundupSize(i)); - remainder = 0; - while (i--) - { - quotient.reg[i] = DWord(dividend.reg[i], remainder) / divisor; - remainder = DWord(dividend.reg[i], remainder) % divisor; - } - - if (dividend.NotNegative()) - quotient.sign = POSITIVE; - else - { - quotient.sign = NEGATIVE; - if (remainder) - { - --quotient; - remainder = divisor - remainder; - } - } -} - -Integer Integer::DividedBy(word b) const -{ - word remainder; - Integer quotient; - Integer::Divide(remainder, quotient, *this, b); - return quotient; -} - -word Integer::Modulo(word divisor) const -{ - if (!divisor) - throw Integer::DivideByZero(); - - assert(divisor); - - word remainder; - - if ((divisor & (divisor-1)) == 0) // divisor is a power of 2 - remainder = reg[0] & (divisor-1); - else - { - unsigned int i = WordCount(); - - if (divisor <= 5) - { - DWord sum(0, 0); - while (i--) - sum += reg[i]; - remainder = sum % divisor; - } - else - { - remainder = 0; - while (i--) - remainder = DWord(reg[i], remainder) % divisor; - } - } - - if (IsNegative() && remainder) - remainder = divisor - remainder; - - return remainder; -} - -void Integer::Negate() -{ - if (!!(*this)) // don't flip sign if *this==0 - sign = Sign(1-sign); -} - -int Integer::PositiveCompare(const Integer& t) const -{ - unsigned size = WordCount(), tSize = t.WordCount(); - - if (size == tSize) - return CryptoPP::Compare(reg, t.reg, size); - else - return size > tSize ? 1 : -1; -} - -int Integer::Compare(const Integer& t) const -{ - if (NotNegative()) - { - if (t.NotNegative()) - return PositiveCompare(t); - else - return 1; - } - else - { - if (t.NotNegative()) - return -1; - else - return -PositiveCompare(t); - } -} - -Integer Integer::SquareRoot() const -{ - if (!IsPositive()) - return Zero(); - - // overestimate square root - Integer x, y = Power2((BitCount()+1)/2); - assert(y*y >= *this); - - do - { - x = y; - y = (x + *this/x) >> 1; - } while (y().Gcd(a, b); -} - -Integer Integer::InverseMod(const Integer &m) const -{ - assert(m.NotNegative()); - - if (IsNegative()) - return Modulo(m).InverseMod(m); - - if (m.IsEven()) - { - if (!m || IsEven()) - return Zero(); // no inverse - if (*this == One()) - return One(); - - Integer u = m.Modulo(*this).InverseMod(*this); - return !u ? Zero() : (m*(*this-u)+1)/(*this); - } - - SecBlock T(m.reg.size() * 4); - Integer r((word)0, m.reg.size()); - unsigned k = AlmostInverse(r.reg, T, reg, reg.size(), m.reg, m.reg.size()); - DivideByPower2Mod(r.reg, r.reg, k, m.reg, m.reg.size()); - return r; -} - -word Integer::InverseMod(word mod) const -{ - word g0 = mod, g1 = *this % mod; - word v0 = 0, v1 = 1; - word y; - - while (g1) - { - if (g1 == 1) - return v1; - y = g0 / g1; - g0 = g0 % g1; - v0 += y * v1; - - if (!g0) - break; - if (g0 == 1) - return mod-v0; - y = g1 / g0; - g1 = g1 % g0; - v1 += y * v0; - } - return 0; -} - -// ******************************************************** - -ModularArithmetic::ModularArithmetic(BufferedTransformation &bt) -{ - BERSequenceDecoder seq(bt); - OID oid(seq); - if (oid != ASN1::prime_field()) - BERDecodeError(); - m_modulus.BERDecode(seq); - seq.MessageEnd(); - m_result.reg.resize(m_modulus.reg.size()); -} - -void ModularArithmetic::DEREncode(BufferedTransformation &bt) const -{ - DERSequenceEncoder seq(bt); - ASN1::prime_field().DEREncode(seq); - m_modulus.DEREncode(seq); - seq.MessageEnd(); -} - -void ModularArithmetic::DEREncodeElement(BufferedTransformation &out, const Element &a) const -{ - a.DEREncodeAsOctetString(out, MaxElementByteLength()); -} - -void ModularArithmetic::BERDecodeElement(BufferedTransformation &in, Element &a) const -{ - a.BERDecodeAsOctetString(in, MaxElementByteLength()); -} - -const Integer& ModularArithmetic::Half(const Integer &a) const -{ - if (a.reg.size()==m_modulus.reg.size()) - { - CryptoPP::DivideByPower2Mod(m_result.reg.begin(), a.reg, 1, m_modulus.reg, a.reg.size()); - return m_result; - } - else - return m_result1 = (a.IsEven() ? (a >> 1) : ((a+m_modulus) >> 1)); -} - -const Integer& ModularArithmetic::Add(const Integer &a, const Integer &b) const -{ - if (a.reg.size()==m_modulus.reg.size() && b.reg.size()==m_modulus.reg.size()) - { - if (CryptoPP::Add(m_result.reg.begin(), a.reg, b.reg, a.reg.size()) - || Compare(m_result.reg, m_modulus.reg, a.reg.size()) >= 0) - { - CryptoPP::Subtract(m_result.reg.begin(), m_result.reg, m_modulus.reg, a.reg.size()); - } - return m_result; - } - else - { - m_result1 = a+b; - if (m_result1 >= m_modulus) - m_result1 -= m_modulus; - return m_result1; - } -} - -Integer& ModularArithmetic::Accumulate(Integer &a, const Integer &b) const -{ - if (a.reg.size()==m_modulus.reg.size() && b.reg.size()==m_modulus.reg.size()) - { - if (CryptoPP::Add(a.reg, a.reg, b.reg, a.reg.size()) - || Compare(a.reg, m_modulus.reg, a.reg.size()) >= 0) - { - CryptoPP::Subtract(a.reg, a.reg, m_modulus.reg, a.reg.size()); - } - } - else - { - a+=b; - if (a>=m_modulus) - a-=m_modulus; - } - - return a; -} - -const Integer& ModularArithmetic::Subtract(const Integer &a, const Integer &b) const -{ - if (a.reg.size()==m_modulus.reg.size() && b.reg.size()==m_modulus.reg.size()) - { - if (CryptoPP::Subtract(m_result.reg.begin(), a.reg, b.reg, a.reg.size())) - CryptoPP::Add(m_result.reg.begin(), m_result.reg, m_modulus.reg, a.reg.size()); - return m_result; - } - else - { - m_result1 = a-b; - if (m_result1.IsNegative()) - m_result1 += m_modulus; - return m_result1; - } -} - -Integer& ModularArithmetic::Reduce(Integer &a, const Integer &b) const -{ - if (a.reg.size()==m_modulus.reg.size() && b.reg.size()==m_modulus.reg.size()) - { - if (CryptoPP::Subtract(a.reg, a.reg, b.reg, a.reg.size())) - CryptoPP::Add(a.reg, a.reg, m_modulus.reg, a.reg.size()); - } - else - { - a-=b; - if (a.IsNegative()) - a+=m_modulus; - } - - return a; -} - -const Integer& ModularArithmetic::Inverse(const Integer &a) const -{ - if (!a) - return a; - - CopyWords(m_result.reg.begin(), m_modulus.reg, m_modulus.reg.size()); - if (CryptoPP::Subtract(m_result.reg.begin(), m_result.reg, a.reg, a.reg.size())) - Decrement(m_result.reg.begin()+a.reg.size(), m_modulus.reg.size()-a.reg.size()); - - return m_result; -} - -Integer ModularArithmetic::CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const -{ - if (m_modulus.IsOdd()) - { - MontgomeryRepresentation dr(m_modulus); - return dr.ConvertOut(dr.CascadeExponentiate(dr.ConvertIn(x), e1, dr.ConvertIn(y), e2)); - } - else - return AbstractRing::CascadeExponentiate(x, e1, y, e2); -} - -void ModularArithmetic::SimultaneousExponentiate(Integer *results, const Integer &base, const Integer *exponents, unsigned int exponentsCount) const -{ - if (m_modulus.IsOdd()) - { - MontgomeryRepresentation dr(m_modulus); - dr.SimultaneousExponentiate(results, dr.ConvertIn(base), exponents, exponentsCount); - for (unsigned int i=0; i::SimultaneousExponentiate(results, base, exponents, exponentsCount); -} - -MontgomeryRepresentation::MontgomeryRepresentation(const Integer &m) // modulus must be odd - : ModularArithmetic(m), - m_u((word)0, m_modulus.reg.size()), - m_workspace(5*m_modulus.reg.size()) -{ - if (!m_modulus.IsOdd()) - throw InvalidArgument("MontgomeryRepresentation: Montgomery representation requires an odd modulus"); - - RecursiveInverseModPower2(m_u.reg, m_workspace, m_modulus.reg, m_modulus.reg.size()); -} - -const Integer& MontgomeryRepresentation::Multiply(const Integer &a, const Integer &b) const -{ - word *const T = m_workspace.begin(); - word *const R = m_result.reg.begin(); - const size_t N = m_modulus.reg.size(); - assert(a.reg.size()<=N && b.reg.size()<=N); - - AsymmetricMultiply(T, T+2*N, a.reg, a.reg.size(), b.reg, b.reg.size()); - SetWords(T+a.reg.size()+b.reg.size(), 0, 2*N-a.reg.size()-b.reg.size()); - MontgomeryReduce(R, T+2*N, T, m_modulus.reg, m_u.reg, N); - return m_result; -} - -const Integer& MontgomeryRepresentation::Square(const Integer &a) const -{ - word *const T = m_workspace.begin(); - word *const R = m_result.reg.begin(); - const size_t N = m_modulus.reg.size(); - assert(a.reg.size()<=N); - - CryptoPP::Square(T, T+2*N, a.reg, a.reg.size()); - SetWords(T+2*a.reg.size(), 0, 2*N-2*a.reg.size()); - MontgomeryReduce(R, T+2*N, T, m_modulus.reg, m_u.reg, N); - return m_result; -} - -Integer MontgomeryRepresentation::ConvertOut(const Integer &a) const -{ - word *const T = m_workspace.begin(); - word *const R = m_result.reg.begin(); - const size_t N = m_modulus.reg.size(); - assert(a.reg.size()<=N); - - CopyWords(T, a.reg, a.reg.size()); - SetWords(T+a.reg.size(), 0, 2*N-a.reg.size()); - MontgomeryReduce(R, T+2*N, T, m_modulus.reg, m_u.reg, N); - return m_result; -} - -const Integer& MontgomeryRepresentation::MultiplicativeInverse(const Integer &a) const -{ -// return (EuclideanMultiplicativeInverse(a, modulus)<<(2*WORD_BITS*modulus.reg.size()))%modulus; - word *const T = m_workspace.begin(); - word *const R = m_result.reg.begin(); - const size_t N = m_modulus.reg.size(); - assert(a.reg.size()<=N); - - CopyWords(T, a.reg, a.reg.size()); - SetWords(T+a.reg.size(), 0, 2*N-a.reg.size()); - MontgomeryReduce(R, T+2*N, T, m_modulus.reg, m_u.reg, N); - unsigned k = AlmostInverse(R, T, R, N, m_modulus.reg, N); - -// cout << "k=" << k << " N*32=" << 32*N << endl; - - if (k>N*WORD_BITS) - DivideByPower2Mod(R, R, k-N*WORD_BITS, m_modulus.reg, N); - else - MultiplyByPower2Mod(R, R, N*WORD_BITS-k, m_modulus.reg, N); - - return m_result; -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/integer.h b/embeddedcryptopp/integer.h deleted file mode 100644 index 6d844fa..0000000 --- a/embeddedcryptopp/integer.h +++ /dev/null @@ -1,420 +0,0 @@ -#ifndef CRYPTOPP_INTEGER_H -#define CRYPTOPP_INTEGER_H - -/** \file */ - -#include "cryptlib.h" -#include "secblock.h" - -#include -#include - -NAMESPACE_BEGIN(CryptoPP) - -struct InitializeInteger // used to initialize static variables -{ - InitializeInteger(); -}; - -typedef SecBlock > IntegerSecBlock; - -//! multiple precision integer and basic arithmetics -/*! This class can represent positive and negative integers - with absolute value less than (256**sizeof(word)) ** (256**sizeof(int)). - \nosubgrouping -*/ -class CRYPTOPP_DLL Integer : private InitializeInteger, public ASN1Object -{ -public: - //! \name ENUMS, EXCEPTIONS, and TYPEDEFS - //@{ - //! division by zero exception - class DivideByZero : public Exception - { - public: - DivideByZero() : Exception(OTHER_ERROR, "Integer: division by zero") {} - }; - - //! - class RandomNumberNotFound : public Exception - { - public: - RandomNumberNotFound() : Exception(OTHER_ERROR, "Integer: no integer satisfies the given parameters") {} - }; - - //! - enum Sign {POSITIVE=0, NEGATIVE=1}; - - //! - enum Signedness { - //! - UNSIGNED, - //! - SIGNED}; - - //! - enum RandomNumberType { - //! - ANY, - //! - PRIME}; - //@} - - //! \name CREATORS - //@{ - //! creates the zero integer - Integer(); - - //! copy constructor - Integer(const Integer& t); - - //! convert from signed long - Integer(signed long value); - - //! convert from lword - Integer(Sign s, lword value); - - //! convert from two words - Integer(Sign s, word highWord, word lowWord); - - //! convert from string - /*! str can be in base 2, 8, 10, or 16. Base is determined by a - case insensitive suffix of 'h', 'o', or 'b'. No suffix means base 10. - */ - explicit Integer(const char *str); - explicit Integer(const wchar_t *str); - - //! convert from big-endian byte array - Integer(const byte *encodedInteger, size_t byteCount, Signedness s=UNSIGNED); - - //! convert from big-endian form stored in a BufferedTransformation - Integer(BufferedTransformation &bt, size_t byteCount, Signedness s=UNSIGNED); - - //! convert from BER encoded byte array stored in a BufferedTransformation object - explicit Integer(BufferedTransformation &bt); - - //! create a random integer - /*! The random integer created is uniformly distributed over [0, 2**bitcount). */ - Integer(RandomNumberGenerator &rng, size_t bitcount); - - //! avoid calling constructors for these frequently used integers - static const Integer & CRYPTOPP_API Zero(); - //! avoid calling constructors for these frequently used integers - static const Integer & CRYPTOPP_API One(); - //! avoid calling constructors for these frequently used integers - static const Integer & CRYPTOPP_API Two(); - - //! create a random integer of special type - /*! Ideally, the random integer created should be uniformly distributed - over {x | min <= x <= max and x is of rnType and x % mod == equiv}. - However the actual distribution may not be uniform because sequential - search is used to find an appropriate number from a random starting - point. - May return (with very small probability) a pseudoprime when a prime - is requested and max > lastSmallPrime*lastSmallPrime (lastSmallPrime - is declared in nbtheory.h). - \throw RandomNumberNotFound if the set is empty. - */ - Integer(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType=ANY, const Integer &equiv=Zero(), const Integer &mod=One()); - - //! return the integer 2**e - static Integer CRYPTOPP_API Power2(size_t e); - //@} - - //! \name ENCODE/DECODE - //@{ - //! minimum number of bytes to encode this integer - /*! MinEncodedSize of 0 is 1 */ - size_t MinEncodedSize(Signedness=UNSIGNED) const; - //! encode in big-endian format - /*! unsigned means encode absolute value, signed means encode two's complement if negative. - if outputLen < MinEncodedSize, the most significant bytes will be dropped - if outputLen > MinEncodedSize, the most significant bytes will be padded - */ - void Encode(byte *output, size_t outputLen, Signedness=UNSIGNED) const; - //! - void Encode(BufferedTransformation &bt, size_t outputLen, Signedness=UNSIGNED) const; - - //! encode using Distinguished Encoding Rules, put result into a BufferedTransformation object - void DEREncode(BufferedTransformation &bt) const; - - //! encode absolute value as big-endian octet string - void DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const; - - //! encode absolute value in OpenPGP format, return length of output - size_t OpenPGPEncode(byte *output, size_t bufferSize) const; - //! encode absolute value in OpenPGP format, put result into a BufferedTransformation object - size_t OpenPGPEncode(BufferedTransformation &bt) const; - - //! - void Decode(const byte *input, size_t inputLen, Signedness=UNSIGNED); - //! - //* Precondition: bt.MaxRetrievable() >= inputLen - void Decode(BufferedTransformation &bt, size_t inputLen, Signedness=UNSIGNED); - - //! - void BERDecode(const byte *input, size_t inputLen); - //! - void BERDecode(BufferedTransformation &bt); - - //! decode nonnegative value as big-endian octet string - void BERDecodeAsOctetString(BufferedTransformation &bt, size_t length); - - class OpenPGPDecodeErr : public Exception - { - public: - OpenPGPDecodeErr() : Exception(INVALID_DATA_FORMAT, "OpenPGP decode error") {} - }; - - //! - void OpenPGPDecode(const byte *input, size_t inputLen); - //! - void OpenPGPDecode(BufferedTransformation &bt); - //@} - - //! \name ACCESSORS - //@{ - //! return true if *this can be represented as a signed long - bool IsConvertableToLong() const; - //! return equivalent signed long if possible, otherwise undefined - signed long ConvertToLong() const; - - //! number of significant bits = floor(log2(abs(*this))) + 1 - unsigned int BitCount() const; - //! number of significant bytes = ceiling(BitCount()/8) - unsigned int ByteCount() const; - //! number of significant words = ceiling(ByteCount()/sizeof(word)) - unsigned int WordCount() const; - - //! return the i-th bit, i=0 being the least significant bit - bool GetBit(size_t i) const; - //! return the i-th byte - byte GetByte(size_t i) const; - //! return n lowest bits of *this >> i - lword GetBits(size_t i, size_t n) const; - - //! - bool IsZero() const {return !*this;} - //! - bool NotZero() const {return !IsZero();} - //! - bool IsNegative() const {return sign == NEGATIVE;} - //! - bool NotNegative() const {return !IsNegative();} - //! - bool IsPositive() const {return NotNegative() && NotZero();} - //! - bool NotPositive() const {return !IsPositive();} - //! - bool IsEven() const {return GetBit(0) == 0;} - //! - bool IsOdd() const {return GetBit(0) == 1;} - //@} - - //! \name MANIPULATORS - //@{ - //! - Integer& operator=(const Integer& t); - - //! - Integer& operator+=(const Integer& t); - //! - Integer& operator-=(const Integer& t); - //! - Integer& operator*=(const Integer& t) {return *this = Times(t);} - //! - Integer& operator/=(const Integer& t) {return *this = DividedBy(t);} - //! - Integer& operator%=(const Integer& t) {return *this = Modulo(t);} - //! - Integer& operator/=(word t) {return *this = DividedBy(t);} - //! - Integer& operator%=(word t) {return *this = Integer(POSITIVE, 0, Modulo(t));} - - //! - Integer& operator<<=(size_t); - //! - Integer& operator>>=(size_t); - - //! - void Randomize(RandomNumberGenerator &rng, size_t bitcount); - //! - void Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max); - //! set this Integer to a random element of {x | min <= x <= max and x is of rnType and x % mod == equiv} - /*! returns false if the set is empty */ - bool Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType, const Integer &equiv=Zero(), const Integer &mod=One()); - - bool GenerateRandomNoThrow(RandomNumberGenerator &rng, const NameValuePairs ¶ms = g_nullNameValuePairs); - void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms = g_nullNameValuePairs) - { - if (!GenerateRandomNoThrow(rng, params)) - throw RandomNumberNotFound(); - } - - //! set the n-th bit to value - void SetBit(size_t n, bool value=1); - //! set the n-th byte to value - void SetByte(size_t n, byte value); - - //! - void Negate(); - //! - void SetPositive() {sign = POSITIVE;} - //! - void SetNegative() {if (!!(*this)) sign = NEGATIVE;} - - //! - void swap(Integer &a); - //@} - - //! \name UNARY OPERATORS - //@{ - //! - bool operator!() const; - //! - Integer operator+() const {return *this;} - //! - Integer operator-() const; - //! - Integer& operator++(); - //! - Integer& operator--(); - //! - Integer operator++(int) {Integer temp = *this; ++*this; return temp;} - //! - Integer operator--(int) {Integer temp = *this; --*this; return temp;} - //@} - - //! \name BINARY OPERATORS - //@{ - //! signed comparison - /*! \retval -1 if *this < a - \retval 0 if *this = a - \retval 1 if *this > a - */ - int Compare(const Integer& a) const; - - //! - Integer Plus(const Integer &b) const; - //! - Integer Minus(const Integer &b) const; - //! - Integer Times(const Integer &b) const; - //! - Integer DividedBy(const Integer &b) const; - //! - Integer Modulo(const Integer &b) const; - //! - Integer DividedBy(word b) const; - //! - word Modulo(word b) const; - - //! - Integer operator>>(size_t n) const {return Integer(*this)>>=n;} - //! - Integer operator<<(size_t n) const {return Integer(*this)<<=n;} - //@} - - //! \name OTHER ARITHMETIC FUNCTIONS - //@{ - //! - Integer AbsoluteValue() const; - //! - Integer Doubled() const {return Plus(*this);} - //! - Integer Squared() const {return Times(*this);} - //! extract square root, if negative return 0, else return floor of square root - Integer SquareRoot() const; - //! return whether this integer is a perfect square - bool IsSquare() const; - - //! is 1 or -1 - bool IsUnit() const; - //! return inverse if 1 or -1, otherwise return 0 - Integer MultiplicativeInverse() const; - - //! modular multiplication - CRYPTOPP_DLL friend Integer CRYPTOPP_API a_times_b_mod_c(const Integer &x, const Integer& y, const Integer& m); - //! modular exponentiation - CRYPTOPP_DLL friend Integer CRYPTOPP_API a_exp_b_mod_c(const Integer &x, const Integer& e, const Integer& m); - - //! calculate r and q such that (a == d*q + r) && (0 <= r < abs(d)) - static void CRYPTOPP_API Divide(Integer &r, Integer &q, const Integer &a, const Integer &d); - //! use a faster division algorithm when divisor is short - static void CRYPTOPP_API Divide(word &r, Integer &q, const Integer &a, word d); - - //! returns same result as Divide(r, q, a, Power2(n)), but faster - static void CRYPTOPP_API DivideByPowerOf2(Integer &r, Integer &q, const Integer &a, unsigned int n); - - //! greatest common divisor - static Integer CRYPTOPP_API Gcd(const Integer &a, const Integer &n); - //! calculate multiplicative inverse of *this mod n - Integer InverseMod(const Integer &n) const; - //! - word InverseMod(word n) const; - //@} - - //! \name INPUT/OUTPUT - //@{ - //! - friend CRYPTOPP_DLL std::istream& CRYPTOPP_API operator>>(std::istream& in, Integer &a); - //! - friend CRYPTOPP_DLL std::ostream& CRYPTOPP_API operator<<(std::ostream& out, const Integer &a); - //@} - -private: - friend class ModularArithmetic; - friend class MontgomeryRepresentation; - friend class HalfMontgomeryRepresentation; - - Integer(word value, size_t length); - - int PositiveCompare(const Integer &t) const; - friend void PositiveAdd(Integer &sum, const Integer &a, const Integer &b); - friend void PositiveSubtract(Integer &diff, const Integer &a, const Integer &b); - friend void PositiveMultiply(Integer &product, const Integer &a, const Integer &b); - friend void PositiveDivide(Integer &remainder, Integer "ient, const Integer ÷nd, const Integer &divisor); - - IntegerSecBlock reg; - Sign sign; -}; - -//! -inline bool operator==(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)==0;} -//! -inline bool operator!=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)!=0;} -//! -inline bool operator> (const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)> 0;} -//! -inline bool operator>=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)>=0;} -//! -inline bool operator< (const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)< 0;} -//! -inline bool operator<=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)<=0;} -//! -inline CryptoPP::Integer operator+(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Plus(b);} -//! -inline CryptoPP::Integer operator-(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Minus(b);} -//! -inline CryptoPP::Integer operator*(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Times(b);} -//! -inline CryptoPP::Integer operator/(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.DividedBy(b);} -//! -inline CryptoPP::Integer operator%(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Modulo(b);} -//! -inline CryptoPP::Integer operator/(const CryptoPP::Integer &a, CryptoPP::word b) {return a.DividedBy(b);} -//! -inline CryptoPP::word operator%(const CryptoPP::Integer &a, CryptoPP::word b) {return a.Modulo(b);} - -NAMESPACE_END - -#ifndef __BORLANDC__ -NAMESPACE_BEGIN(std) -inline void swap(CryptoPP::Integer &a, CryptoPP::Integer &b) -{ - a.swap(b); -} -NAMESPACE_END -#endif - -#endif diff --git a/embeddedcryptopp/iterhash.cpp b/embeddedcryptopp/iterhash.cpp deleted file mode 100644 index 478950c..0000000 --- a/embeddedcryptopp/iterhash.cpp +++ /dev/null @@ -1,159 +0,0 @@ -// iterhash.cpp - written and placed in the public domain by Wei Dai - -#ifndef __GNUC__ -#define CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES -#endif - -#include "iterhash.h" -#include "misc.h" - -NAMESPACE_BEGIN(CryptoPP) - -template void IteratedHashBase::Update(const byte *input, size_t len) -{ - HashWordType oldCountLo = m_countLo, oldCountHi = m_countHi; - if ((m_countLo = oldCountLo + HashWordType(len)) < oldCountLo) - m_countHi++; // carry from low to high - m_countHi += (HashWordType)SafeRightShift<8*sizeof(HashWordType)>(len); - if (m_countHi < oldCountHi || SafeRightShift<2*8*sizeof(HashWordType)>(len) != 0) - throw HashInputTooLong(this->AlgorithmName()); - - unsigned int blockSize = this->BlockSize(); - unsigned int num = ModPowerOf2(oldCountLo, blockSize); - T* dataBuf = this->DataBuf(); - byte* data = (byte *)dataBuf; - - if (num != 0) // process left over data - { - if (num+len >= blockSize) - { - memcpy(data+num, input, blockSize-num); - HashBlock(dataBuf); - input += (blockSize-num); - len -= (blockSize-num); - num = 0; - // drop through and do the rest - } - else - { - memcpy(data+num, input, len); - return; - } - } - - // now process the input data in blocks of blockSize bytes and save the leftovers to m_data - if (len >= blockSize) - { - if (input == data) - { - assert(len == blockSize); - HashBlock(dataBuf); - return; - } - else if (IsAligned(input)) - { - size_t leftOver = HashMultipleBlocks((T *)input, len); - input += (len - leftOver); - len = leftOver; - } - else - do - { // copy input first if it's not aligned correctly - memcpy(data, input, blockSize); - HashBlock(dataBuf); - input+=blockSize; - len-=blockSize; - } while (len >= blockSize); - } - - memcpy(data, input, len); -} - -template byte * IteratedHashBase::CreateUpdateSpace(size_t &size) -{ - unsigned int blockSize = this->BlockSize(); - unsigned int num = ModPowerOf2(m_countLo, blockSize); - size = blockSize - num; - return (byte *)DataBuf() + num; -} - -template size_t IteratedHashBase::HashMultipleBlocks(const T *input, size_t length) -{ - unsigned int blockSize = this->BlockSize(); - bool noReverse = NativeByteOrderIs(this->GetByteOrder()); - T* dataBuf = this->DataBuf(); - do - { - if (noReverse) - this->HashEndianCorrectedBlock(input); - else - { - ByteReverse(dataBuf, input, this->BlockSize()); - this->HashEndianCorrectedBlock(dataBuf); - } - - input += blockSize/sizeof(T); - length -= blockSize; - } - while (length >= blockSize); - return length; -} - -template void IteratedHashBase::PadLastBlock(unsigned int lastBlockSize, byte padFirst) -{ - unsigned int blockSize = this->BlockSize(); - unsigned int num = ModPowerOf2(m_countLo, blockSize); - T* dataBuf = this->DataBuf(); - byte* data = (byte *)dataBuf; - data[num++] = padFirst; - if (num <= lastBlockSize) - memset(data+num, 0, lastBlockSize-num); - else - { - memset(data+num, 0, blockSize-num); - HashBlock(dataBuf); - memset(data, 0, lastBlockSize); - } -} - -template void IteratedHashBase::Restart() -{ - m_countLo = m_countHi = 0; - Init(); -} - -template void IteratedHashBase::TruncatedFinal(byte *digest, size_t size) -{ - this->ThrowIfInvalidTruncatedSize(size); - - T* dataBuf = this->DataBuf(); - T* stateBuf = this->StateBuf(); - unsigned int blockSize = this->BlockSize(); - ByteOrder order = this->GetByteOrder(); - - PadLastBlock(blockSize - 2*sizeof(HashWordType)); - dataBuf[blockSize/sizeof(T)-2+order] = ConditionalByteReverse(order, this->GetBitCountLo()); - dataBuf[blockSize/sizeof(T)-1-order] = ConditionalByteReverse(order, this->GetBitCountHi()); - - HashBlock(dataBuf); - - if (IsAligned(digest) && size%sizeof(HashWordType)==0) - ConditionalByteReverse(order, (HashWordType *)digest, stateBuf, size); - else - { - ConditionalByteReverse(order, stateBuf, stateBuf, this->DigestSize()); - memcpy(digest, stateBuf, size); - } - - this->Restart(); // reinit for next use -} - -#ifdef __GNUC__ - template class IteratedHashBase; - template class IteratedHashBase; - - template class IteratedHashBase; - template class IteratedHashBase; -#endif - -NAMESPACE_END diff --git a/embeddedcryptopp/iterhash.h b/embeddedcryptopp/iterhash.h deleted file mode 100644 index cce9e82..0000000 --- a/embeddedcryptopp/iterhash.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef CRYPTOPP_ITERHASH_H -#define CRYPTOPP_ITERHASH_H - -#include "cryptlib.h" -#include "secblock.h" -#include "misc.h" -#include "simple.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! exception thrown when trying to hash more data than is allowed by a hash function -class CRYPTOPP_DLL HashInputTooLong : public InvalidDataFormat -{ -public: - explicit HashInputTooLong(const std::string &alg) - : InvalidDataFormat("IteratedHashBase: input data exceeds maximum allowed by hash function " + alg) {} -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE IteratedHashBase : public BASE -{ -public: - typedef T HashWordType; - - IteratedHashBase() : m_countLo(0), m_countHi(0) {} - unsigned int OptimalBlockSize() const {return this->BlockSize();} - unsigned int OptimalDataAlignment() const {return GetAlignmentOf();} - void Update(const byte *input, size_t length); - byte * CreateUpdateSpace(size_t &size); - void Restart(); - void TruncatedFinal(byte *digest, size_t size); - -protected: - inline T GetBitCountHi() const {return (m_countLo >> (8*sizeof(T)-3)) + (m_countHi << 3);} - inline T GetBitCountLo() const {return m_countLo << 3;} - - void PadLastBlock(unsigned int lastBlockSize, byte padFirst=0x80); - virtual void Init() =0; - - virtual ByteOrder GetByteOrder() const =0; - virtual void HashEndianCorrectedBlock(const HashWordType *data) =0; - virtual size_t HashMultipleBlocks(const T *input, size_t length); - void HashBlock(const HashWordType *input) {HashMultipleBlocks(input, this->BlockSize());} - - virtual T* DataBuf() =0; - virtual T* StateBuf() =0; - -private: - T m_countLo, m_countHi; -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE IteratedHash : public IteratedHashBase -{ -public: - typedef T_Endianness ByteOrderClass; - typedef T_HashWordType HashWordType; - - CRYPTOPP_CONSTANT(BLOCKSIZE = T_BlockSize) - // BCB2006 workaround: can't use BLOCKSIZE here - CRYPTOPP_COMPILE_ASSERT((T_BlockSize & (T_BlockSize - 1)) == 0); // blockSize is a power of 2 - unsigned int BlockSize() const {return T_BlockSize;} - - ByteOrder GetByteOrder() const {return T_Endianness::ToEnum();} - - inline static void CorrectEndianess(HashWordType *out, const HashWordType *in, size_t byteCount) - { - ConditionalByteReverse(T_Endianness::ToEnum(), out, in, byteCount); - } - -protected: - T_HashWordType* DataBuf() {return this->m_data;} - FixedSizeSecBlock m_data; -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE IteratedHashWithStaticTransform - : public ClonableImpl, T_Transform> > -{ -public: - CRYPTOPP_CONSTANT(DIGESTSIZE = T_DigestSize ? T_DigestSize : T_StateSize) - unsigned int DigestSize() const {return DIGESTSIZE;}; - -protected: - IteratedHashWithStaticTransform() {this->Init();} - void HashEndianCorrectedBlock(const T_HashWordType *data) {T_Transform::Transform(this->m_state, data);} - void Init() {T_Transform::InitState(this->m_state);} - - T_HashWordType* StateBuf() {return this->m_state;} - FixedSizeAlignedSecBlock m_state; -}; - -#ifndef __GNUC__ - CRYPTOPP_DLL_TEMPLATE_CLASS IteratedHashBase; - CRYPTOPP_STATIC_TEMPLATE_CLASS IteratedHashBase; - - CRYPTOPP_DLL_TEMPLATE_CLASS IteratedHashBase; - CRYPTOPP_STATIC_TEMPLATE_CLASS IteratedHashBase; -#endif - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/misc.cpp b/embeddedcryptopp/misc.cpp deleted file mode 100644 index 7e4fa89..0000000 --- a/embeddedcryptopp/misc.cpp +++ /dev/null @@ -1,130 +0,0 @@ -// misc.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "misc.h" -#include "words.h" -#include - -NAMESPACE_BEGIN(CryptoPP) - -void xorbuf(byte *buf, const byte *mask, size_t count) -{ - size_t i; - - if (IsAligned(buf) && IsAligned(mask)) - { - if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned(buf) && IsAligned(mask)) - { - for (i=0; i(output) && IsAligned(input) && IsAligned(mask)) - { - if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned(output) && IsAligned(input) && IsAligned(mask)) - { - for (i=0; i(buf) && IsAligned(mask)) - { - word32 acc32 = 0; - if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned(buf) && IsAligned(mask)) - { - word64 acc64 = 0; - for (i=0; i>32); - } - - for (i=0; i>8) | byte(acc32>>16) | byte(acc32>>24); - } - - for (i=0; i // for memcpy and memmove - -#ifdef _MSC_VER - #include - #if _MSC_VER >= 1400 - // VC2005 workaround: disable declarations that conflict with winnt.h - #define _interlockedbittestandset CRYPTOPP_DISABLED_INTRINSIC_1 - #define _interlockedbittestandreset CRYPTOPP_DISABLED_INTRINSIC_2 - #define _interlockedbittestandset64 CRYPTOPP_DISABLED_INTRINSIC_3 - #define _interlockedbittestandreset64 CRYPTOPP_DISABLED_INTRINSIC_4 - #include - #undef _interlockedbittestandset - #undef _interlockedbittestandreset - #undef _interlockedbittestandset64 - #undef _interlockedbittestandreset64 - #define CRYPTOPP_FAST_ROTATE(x) 1 - #elif _MSC_VER >= 1300 - #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32 | (x) == 64) - #else - #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32) - #endif -#elif (defined(__MWERKS__) && TARGET_CPU_PPC) || \ - (defined(__GNUC__) && (defined(_ARCH_PWR2) || defined(_ARCH_PWR) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(_ARCH_COM))) - #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32) -#elif defined(__GNUC__) && (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86) // depend on GCC's peephole optimization to generate rotate instructions - #define CRYPTOPP_FAST_ROTATE(x) 1 -#else - #define CRYPTOPP_FAST_ROTATE(x) 0 -#endif - -#ifdef __BORLANDC__ -#include -#endif - -#if defined(__GNUC__) && defined(__linux__) -#define CRYPTOPP_BYTESWAP_AVAILABLE -#include -#endif - -NAMESPACE_BEGIN(CryptoPP) - -// ************** compile-time assertion *************** - -template -struct CompileAssert -{ - static char dummy[2*b-1]; -}; - -#define CRYPTOPP_COMPILE_ASSERT(assertion) CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, __LINE__) -#if defined(CRYPTOPP_EXPORTS) || defined(CRYPTOPP_IMPORTS) -#define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance) -#else -#define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance) static CompileAssert<(assertion)> CRYPTOPP_ASSERT_JOIN(cryptopp_assert_, instance) -#endif -#define CRYPTOPP_ASSERT_JOIN(X, Y) CRYPTOPP_DO_ASSERT_JOIN(X, Y) -#define CRYPTOPP_DO_ASSERT_JOIN(X, Y) X##Y - -// ************** misc classes *************** - -class CRYPTOPP_DLL Empty -{ -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE TwoBases : public BASE1, public BASE2 -{ -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE ThreeBases : public BASE1, public BASE2, public BASE3 -{ -}; - -template -class ObjectHolder -{ -protected: - T m_object; -}; - -class NotCopyable -{ -public: - NotCopyable() {} -private: - NotCopyable(const NotCopyable &); - void operator=(const NotCopyable &); -}; - -template -struct NewObject -{ - T* operator()() const {return new T;} -}; - -/*! This function safely initializes a static object in a multithreaded environment without using locks. - It may leak memory when two threads try to initialize the static object at the same time - but this should be acceptable since each static object is only initialized once per session. -*/ -template , int instance=0> -class Singleton -{ -public: - Singleton(F objectFactory = F()) : m_objectFactory(objectFactory) {} - - // prevent this function from being inlined - CRYPTOPP_NOINLINE const T & Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const; - -private: - F m_objectFactory; -}; - -template -const T & Singleton::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const -{ - static simple_ptr s_pObject; - static char s_objectState = 0; - -retry: - switch (s_objectState) - { - case 0: - s_objectState = 1; - try - { - s_pObject.m_p = m_objectFactory(); - } - catch(...) - { - s_objectState = 0; - throw; - } - s_objectState = 2; - break; - case 1: - goto retry; - default: - break; - } - return *s_pObject.m_p; -} - -// ************** misc functions *************** - -#if (!__STDC_WANT_SECURE_LIB__) -inline void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t count) -{ - if (count > sizeInBytes) - throw InvalidArgument("memcpy_s: buffer overflow"); - memcpy(dest, src, count); -} - -inline void memmove_s(void *dest, size_t sizeInBytes, const void *src, size_t count) -{ - if (count > sizeInBytes) - throw InvalidArgument("memmove_s: buffer overflow"); - memmove(dest, src, count); -} -#endif - -inline void * memset_z(void *ptr, int value, size_t num) -{ -// avoid extranous warning on GCC 4.3.2 Ubuntu 8.10 -#if CRYPTOPP_GCC_VERSION >= 30001 - if (__builtin_constant_p(num) && num==0) - return ptr; -#endif - return memset(ptr, value, num); -} - -// can't use std::min or std::max in MSVC60 or Cygwin 1.1.0 -template inline const T& STDMIN(const T& a, const T& b) -{ - return b < a ? b : a; -} - -template inline const T1 UnsignedMin(const T1& a, const T2& b) -{ - CRYPTOPP_COMPILE_ASSERT((sizeof(T1)<=sizeof(T2) && T2(-1)>0) || (sizeof(T1)>sizeof(T2) && T1(-1)>0)); - assert(a==0 || a>0); // GCC workaround: get rid of the warning "comparison is always true due to limited range of data type" - assert(b>=0); - - if (sizeof(T1)<=sizeof(T2)) - return b < (T2)a ? (T1)b : a; - else - return (T1)b < a ? (T1)b : a; -} - -template inline const T& STDMAX(const T& a, const T& b) -{ - return a < b ? b : a; -} - -#define RETURN_IF_NONZERO(x) size_t returnedValue = x; if (returnedValue) return returnedValue - -// this version of the macro is fastest on Pentium 3 and Pentium 4 with MSVC 6 SP5 w/ Processor Pack -#define GETBYTE(x, y) (unsigned int)byte((x)>>(8*(y))) -// these may be faster on other CPUs/compilers -// #define GETBYTE(x, y) (unsigned int)(((x)>>(8*(y)))&255) -// #define GETBYTE(x, y) (((byte *)&(x))[y]) - -#define CRYPTOPP_GET_BYTE_AS_BYTE(x, y) byte((x)>>(8*(y))) - -template -unsigned int Parity(T value) -{ - for (unsigned int i=8*sizeof(value)/2; i>0; i/=2) - value ^= value >> i; - return (unsigned int)value&1; -} - -template -unsigned int BytePrecision(const T &value) -{ - if (!value) - return 0; - - unsigned int l=0, h=8*sizeof(value); - - while (h-l > 8) - { - unsigned int t = (l+h)/2; - if (value >> t) - l = t; - else - h = t; - } - - return h/8; -} - -template -unsigned int BitPrecision(const T &value) -{ - if (!value) - return 0; - - unsigned int l=0, h=8*sizeof(value); - - while (h-l > 1) - { - unsigned int t = (l+h)/2; - if (value >> t) - l = t; - else - h = t; - } - - return h; -} - -template -inline T Crop(T value, size_t size) -{ - if (size < 8*sizeof(value)) - return T(value & ((T(1) << size) - 1)); - else - return value; -} - -template -inline bool SafeConvert(T1 from, T2 &to) -{ - to = (T2)from; - if (from != to || (from > 0) != (to > 0)) - return false; - return true; -} - -inline size_t BitsToBytes(size_t bitCount) -{ - return ((bitCount+7)/(8)); -} - -inline size_t BytesToWords(size_t byteCount) -{ - return ((byteCount+WORD_SIZE-1)/WORD_SIZE); -} - -inline size_t BitsToWords(size_t bitCount) -{ - return ((bitCount+WORD_BITS-1)/(WORD_BITS)); -} - -inline size_t BitsToDwords(size_t bitCount) -{ - return ((bitCount+2*WORD_BITS-1)/(2*WORD_BITS)); -} - -CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *buf, const byte *mask, size_t count); -CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *output, const byte *input, const byte *mask, size_t count); - -CRYPTOPP_DLL bool CRYPTOPP_API VerifyBufsEqual(const byte *buf1, const byte *buf2, size_t count); - -template -inline bool IsPowerOf2(const T &n) -{ - return n > 0 && (n & (n-1)) == 0; -} - -template -inline T2 ModPowerOf2(const T1 &a, const T2 &b) -{ - assert(IsPowerOf2(b)); - return T2(a) & (b-1); -} - -template -inline T1 RoundDownToMultipleOf(const T1 &n, const T2 &m) -{ - if (IsPowerOf2(m)) - return n - ModPowerOf2(n, m); - else - return n - n%m; -} - -template -inline T1 RoundUpToMultipleOf(const T1 &n, const T2 &m) -{ - if (n+m-1 < n) - throw InvalidArgument("RoundUpToMultipleOf: integer overflow"); - return RoundDownToMultipleOf(n+m-1, m); -} - -template -inline unsigned int GetAlignmentOf(T *dummy=NULL) // VC60 workaround -{ -#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS - if (sizeof(T) < 16) - return 1; -#endif - -#if (_MSC_VER >= 1300) - return __alignof(T); -#elif defined(__GNUC__) - return __alignof__(T); -#elif CRYPTOPP_BOOL_SLOW_WORD64 - return UnsignedMin(4U, sizeof(T)); -#else - return sizeof(T); -#endif -} - -inline bool IsAlignedOn(const void *p, unsigned int alignment) -{ - return alignment==1 || (IsPowerOf2(alignment) ? ModPowerOf2((size_t)p, alignment) == 0 : (size_t)p % alignment == 0); -} - -template -inline bool IsAligned(const void *p, T *dummy=NULL) // VC60 workaround -{ - return IsAlignedOn(p, GetAlignmentOf()); -} - -#ifdef IS_LITTLE_ENDIAN - typedef LittleEndian NativeByteOrder; -#else - typedef BigEndian NativeByteOrder; -#endif - -inline ByteOrder GetNativeByteOrder() -{ - return NativeByteOrder::ToEnum(); -} - -inline bool NativeByteOrderIs(ByteOrder order) -{ - return order == GetNativeByteOrder(); -} - -template -std::string IntToString(T a, unsigned int base = 10) -{ - if (a == 0) - return "0"; - bool negate = false; - if (a < 0) - { - negate = true; - a = 0-a; // VC .NET does not like -a - } - std::string result; - while (a > 0) - { - T digit = a % base; - result = char((digit < 10 ? '0' : ('a' - 10)) + digit) + result; - a /= base; - } - if (negate) - result = "-" + result; - return result; -} - -template -inline T1 SaturatingSubtract(const T1 &a, const T2 &b) -{ - return T1((a > b) ? (a - b) : 0); -} - -template -inline CipherDir GetCipherDir(const T &obj) -{ - return obj.IsForwardTransformation() ? ENCRYPTION : DECRYPTION; -} - -CRYPTOPP_DLL void CRYPTOPP_API CallNewHandler(); - -inline void IncrementCounterByOne(byte *inout, unsigned int s) -{ - for (int i=s-1, carry=1; i>=0 && carry; i--) - carry = !++inout[i]; -} - -inline void IncrementCounterByOne(byte *output, const byte *input, unsigned int s) -{ - int i, carry; - for (i=s-1, carry=1; i>=0 && carry; i--) - carry = ((output[i] = input[i]+1) == 0); - memcpy_s(output, s, input, i+1); -} - -// ************** rotate functions *************** - -template inline T rotlFixed(T x, unsigned int y) -{ - assert(y < sizeof(T)*8); - return T((x<>(sizeof(T)*8-y))); -} - -template inline T rotrFixed(T x, unsigned int y) -{ - assert(y < sizeof(T)*8); - return T((x>>y) | (x<<(sizeof(T)*8-y))); -} - -template inline T rotlVariable(T x, unsigned int y) -{ - assert(y < sizeof(T)*8); - return T((x<>(sizeof(T)*8-y))); -} - -template inline T rotrVariable(T x, unsigned int y) -{ - assert(y < sizeof(T)*8); - return T((x>>y) | (x<<(sizeof(T)*8-y))); -} - -template inline T rotlMod(T x, unsigned int y) -{ - y %= sizeof(T)*8; - return T((x<>(sizeof(T)*8-y))); -} - -template inline T rotrMod(T x, unsigned int y) -{ - y %= sizeof(T)*8; - return T((x>>y) | (x<<(sizeof(T)*8-y))); -} - -#ifdef _MSC_VER - -template<> inline word32 rotlFixed(word32 x, unsigned int y) -{ - assert(y < 8*sizeof(x)); - return y ? _lrotl(x, y) : x; -} - -template<> inline word32 rotrFixed(word32 x, unsigned int y) -{ - assert(y < 8*sizeof(x)); - return y ? _lrotr(x, y) : x; -} - -template<> inline word32 rotlVariable(word32 x, unsigned int y) -{ - assert(y < 8*sizeof(x)); - return _lrotl(x, y); -} - -template<> inline word32 rotrVariable(word32 x, unsigned int y) -{ - assert(y < 8*sizeof(x)); - return _lrotr(x, y); -} - -template<> inline word32 rotlMod(word32 x, unsigned int y) -{ - return _lrotl(x, y); -} - -template<> inline word32 rotrMod(word32 x, unsigned int y) -{ - return _lrotr(x, y); -} - -#endif // #ifdef _MSC_VER - -#if _MSC_VER >= 1300 && !defined(__INTEL_COMPILER) -// Intel C++ Compiler 10.0 calls a function instead of using the rotate instruction when using these instructions - -template<> inline word64 rotlFixed(word64 x, unsigned int y) -{ - assert(y < 8*sizeof(x)); - return y ? _rotl64(x, y) : x; -} - -template<> inline word64 rotrFixed(word64 x, unsigned int y) -{ - assert(y < 8*sizeof(x)); - return y ? _rotr64(x, y) : x; -} - -template<> inline word64 rotlVariable(word64 x, unsigned int y) -{ - assert(y < 8*sizeof(x)); - return _rotl64(x, y); -} - -template<> inline word64 rotrVariable(word64 x, unsigned int y) -{ - assert(y < 8*sizeof(x)); - return _rotr64(x, y); -} - -template<> inline word64 rotlMod(word64 x, unsigned int y) -{ - return _rotl64(x, y); -} - -template<> inline word64 rotrMod(word64 x, unsigned int y) -{ - return _rotr64(x, y); -} - -#endif // #if _MSC_VER >= 1310 - -#if _MSC_VER >= 1400 && !defined(__INTEL_COMPILER) -// Intel C++ Compiler 10.0 gives undefined externals with these - -template<> inline word16 rotlFixed(word16 x, unsigned int y) -{ - assert(y < 8*sizeof(x)); - return y ? _rotl16(x, y) : x; -} - -template<> inline word16 rotrFixed(word16 x, unsigned int y) -{ - assert(y < 8*sizeof(x)); - return y ? _rotr16(x, y) : x; -} - -template<> inline word16 rotlVariable(word16 x, unsigned int y) -{ - assert(y < 8*sizeof(x)); - return _rotl16(x, y); -} - -template<> inline word16 rotrVariable(word16 x, unsigned int y) -{ - assert(y < 8*sizeof(x)); - return _rotr16(x, y); -} - -template<> inline word16 rotlMod(word16 x, unsigned int y) -{ - return _rotl16(x, y); -} - -template<> inline word16 rotrMod(word16 x, unsigned int y) -{ - return _rotr16(x, y); -} - -template<> inline byte rotlFixed(byte x, unsigned int y) -{ - assert(y < 8*sizeof(x)); - return y ? _rotl8(x, y) : x; -} - -template<> inline byte rotrFixed(byte x, unsigned int y) -{ - assert(y < 8*sizeof(x)); - return y ? _rotr8(x, y) : x; -} - -template<> inline byte rotlVariable(byte x, unsigned int y) -{ - assert(y < 8*sizeof(x)); - return _rotl8(x, y); -} - -template<> inline byte rotrVariable(byte x, unsigned int y) -{ - assert(y < 8*sizeof(x)); - return _rotr8(x, y); -} - -template<> inline byte rotlMod(byte x, unsigned int y) -{ - return _rotl8(x, y); -} - -template<> inline byte rotrMod(byte x, unsigned int y) -{ - return _rotr8(x, y); -} - -#endif // #if _MSC_VER >= 1400 - -#if (defined(__MWERKS__) && TARGET_CPU_PPC) - -template<> inline word32 rotlFixed(word32 x, unsigned int y) -{ - assert(y < 32); - return y ? __rlwinm(x,y,0,31) : x; -} - -template<> inline word32 rotrFixed(word32 x, unsigned int y) -{ - assert(y < 32); - return y ? __rlwinm(x,32-y,0,31) : x; -} - -template<> inline word32 rotlVariable(word32 x, unsigned int y) -{ - assert(y < 32); - return (__rlwnm(x,y,0,31)); -} - -template<> inline word32 rotrVariable(word32 x, unsigned int y) -{ - assert(y < 32); - return (__rlwnm(x,32-y,0,31)); -} - -template<> inline word32 rotlMod(word32 x, unsigned int y) -{ - return (__rlwnm(x,y,0,31)); -} - -template<> inline word32 rotrMod(word32 x, unsigned int y) -{ - return (__rlwnm(x,32-y,0,31)); -} - -#endif // #if (defined(__MWERKS__) && TARGET_CPU_PPC) - -// ************** endian reversal *************** - -template -inline unsigned int GetByte(ByteOrder order, T value, unsigned int index) -{ - if (order == LITTLE_ENDIAN_ORDER) - return GETBYTE(value, index); - else - return GETBYTE(value, sizeof(T)-index-1); -} - -inline byte ByteReverse(byte value) -{ - return value; -} - -inline word16 ByteReverse(word16 value) -{ -#ifdef CRYPTOPP_BYTESWAP_AVAILABLE - return bswap_16(value); -#elif defined(_MSC_VER) && _MSC_VER >= 1300 - return _byteswap_ushort(value); -#else - return rotlFixed(value, 8U); -#endif -} - -inline word32 ByteReverse(word32 value) -{ -#if defined(__GNUC__) && defined(CRYPTOPP_X86_ASM_AVAILABLE) - __asm__ ("bswap %0" : "=r" (value) : "0" (value)); - return value; -#elif defined(CRYPTOPP_BYTESWAP_AVAILABLE) - return bswap_32(value); -#elif defined(__MWERKS__) && TARGET_CPU_PPC - return (word32)__lwbrx(&value,0); -#elif _MSC_VER >= 1400 || (_MSC_VER >= 1300 && !defined(_DLL)) - return _byteswap_ulong(value); -#elif CRYPTOPP_FAST_ROTATE(32) - // 5 instructions with rotate instruction, 9 without - return (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff); -#else - // 6 instructions with rotate instruction, 8 without - value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8); - return rotlFixed(value, 16U); -#endif -} - -inline word64 ByteReverse(word64 value) -{ -#if defined(__GNUC__) && defined(CRYPTOPP_X86_ASM_AVAILABLE) && defined(__x86_64__) - __asm__ ("bswap %0" : "=r" (value) : "0" (value)); - return value; -#elif defined(CRYPTOPP_BYTESWAP_AVAILABLE) - return bswap_64(value); -#elif defined(_MSC_VER) && _MSC_VER >= 1300 - return _byteswap_uint64(value); -#elif CRYPTOPP_BOOL_SLOW_WORD64 - return (word64(ByteReverse(word32(value))) << 32) | ByteReverse(word32(value>>32)); -#else - value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | ((value & W64LIT(0x00FF00FF00FF00FF)) << 8); - value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) | ((value & W64LIT(0x0000FFFF0000FFFF)) << 16); - return rotlFixed(value, 32U); -#endif -} - -inline byte BitReverse(byte value) -{ - value = ((value & 0xAA) >> 1) | ((value & 0x55) << 1); - value = ((value & 0xCC) >> 2) | ((value & 0x33) << 2); - return rotlFixed(value, 4U); -} - -inline word16 BitReverse(word16 value) -{ - value = ((value & 0xAAAA) >> 1) | ((value & 0x5555) << 1); - value = ((value & 0xCCCC) >> 2) | ((value & 0x3333) << 2); - value = ((value & 0xF0F0) >> 4) | ((value & 0x0F0F) << 4); - return ByteReverse(value); -} - -inline word32 BitReverse(word32 value) -{ - value = ((value & 0xAAAAAAAA) >> 1) | ((value & 0x55555555) << 1); - value = ((value & 0xCCCCCCCC) >> 2) | ((value & 0x33333333) << 2); - value = ((value & 0xF0F0F0F0) >> 4) | ((value & 0x0F0F0F0F) << 4); - return ByteReverse(value); -} - -inline word64 BitReverse(word64 value) -{ -#if CRYPTOPP_BOOL_SLOW_WORD64 - return (word64(BitReverse(word32(value))) << 32) | BitReverse(word32(value>>32)); -#else - value = ((value & W64LIT(0xAAAAAAAAAAAAAAAA)) >> 1) | ((value & W64LIT(0x5555555555555555)) << 1); - value = ((value & W64LIT(0xCCCCCCCCCCCCCCCC)) >> 2) | ((value & W64LIT(0x3333333333333333)) << 2); - value = ((value & W64LIT(0xF0F0F0F0F0F0F0F0)) >> 4) | ((value & W64LIT(0x0F0F0F0F0F0F0F0F)) << 4); - return ByteReverse(value); -#endif -} - -template -inline T BitReverse(T value) -{ - if (sizeof(T) == 1) - return (T)BitReverse((byte)value); - else if (sizeof(T) == 2) - return (T)BitReverse((word16)value); - else if (sizeof(T) == 4) - return (T)BitReverse((word32)value); - else - { - assert(sizeof(T) == 8); - return (T)BitReverse((word64)value); - } -} - -template -inline T ConditionalByteReverse(ByteOrder order, T value) -{ - return NativeByteOrderIs(order) ? value : ByteReverse(value); -} - -template -void ByteReverse(T *out, const T *in, size_t byteCount) -{ - assert(byteCount % sizeof(T) == 0); - size_t count = byteCount/sizeof(T); - for (size_t i=0; i -inline void ConditionalByteReverse(ByteOrder order, T *out, const T *in, size_t byteCount) -{ - if (!NativeByteOrderIs(order)) - ByteReverse(out, in, byteCount); - else if (in != out) - memcpy_s(out, byteCount, in, byteCount); -} - -template -inline void GetUserKey(ByteOrder order, T *out, size_t outlen, const byte *in, size_t inlen) -{ - const size_t U = sizeof(T); - assert(inlen <= outlen*U); - memcpy_s(out, outlen*U, in, inlen); - memset_z((byte *)out+inlen, 0, outlen*U-inlen); - ConditionalByteReverse(order, out, out, RoundUpToMultipleOf(inlen, U)); -} - -#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS -inline byte UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const byte *) -{ - return block[0]; -} - -inline word16 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word16 *) -{ - return (order == BIG_ENDIAN_ORDER) - ? block[1] | (block[0] << 8) - : block[0] | (block[1] << 8); -} - -inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word32 *) -{ - return (order == BIG_ENDIAN_ORDER) - ? word32(block[3]) | (word32(block[2]) << 8) | (word32(block[1]) << 16) | (word32(block[0]) << 24) - : word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16) | (word32(block[3]) << 24); -} - -inline word64 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word64 *) -{ - return (order == BIG_ENDIAN_ORDER) - ? - (word64(block[7]) | - (word64(block[6]) << 8) | - (word64(block[5]) << 16) | - (word64(block[4]) << 24) | - (word64(block[3]) << 32) | - (word64(block[2]) << 40) | - (word64(block[1]) << 48) | - (word64(block[0]) << 56)) - : - (word64(block[0]) | - (word64(block[1]) << 8) | - (word64(block[2]) << 16) | - (word64(block[3]) << 24) | - (word64(block[4]) << 32) | - (word64(block[5]) << 40) | - (word64(block[6]) << 48) | - (word64(block[7]) << 56)); -} - -inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, byte value, const byte *xorBlock) -{ - block[0] = xorBlock ? (value ^ xorBlock[0]) : value; -} - -inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word16 value, const byte *xorBlock) -{ - if (order == BIG_ENDIAN_ORDER) - { - if (xorBlock) - { - block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); - block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); - } - else - { - block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); - block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); - } - } - else - { - if (xorBlock) - { - block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); - block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); - } - else - { - block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); - block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); - } - } -} - -inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word32 value, const byte *xorBlock) -{ - if (order == BIG_ENDIAN_ORDER) - { - if (xorBlock) - { - block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); - block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); - block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); - block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); - } - else - { - block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); - block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); - block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); - block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); - } - } - else - { - if (xorBlock) - { - block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); - block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); - block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); - block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); - } - else - { - block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); - block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); - block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); - block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); - } - } -} - -inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word64 value, const byte *xorBlock) -{ - if (order == BIG_ENDIAN_ORDER) - { - if (xorBlock) - { - block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 7); - block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 6); - block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 5); - block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 4); - block[4] = xorBlock[4] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); - block[5] = xorBlock[5] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); - block[6] = xorBlock[6] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); - block[7] = xorBlock[7] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); - } - else - { - block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 7); - block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 6); - block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 5); - block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 4); - block[4] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); - block[5] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); - block[6] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); - block[7] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); - } - } - else - { - if (xorBlock) - { - block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); - block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); - block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); - block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); - block[4] = xorBlock[4] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 4); - block[5] = xorBlock[5] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 5); - block[6] = xorBlock[6] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 6); - block[7] = xorBlock[7] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 7); - } - else - { - block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); - block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); - block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); - block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); - block[4] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 4); - block[5] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 5); - block[6] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 6); - block[7] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 7); - } - } -} -#endif // #ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS - -template -inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block) -{ -#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS - if (!assumeAligned) - return UnalignedGetWordNonTemplate(order, block, (T*)NULL); - assert(IsAligned(block)); -#endif - return ConditionalByteReverse(order, *reinterpret_cast(block)); -} - -template -inline void GetWord(bool assumeAligned, ByteOrder order, T &result, const byte *block) -{ - result = GetWord(assumeAligned, order, block); -} - -template -inline void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock = NULL) -{ -#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS - if (!assumeAligned) - return UnalignedPutWordNonTemplate(order, block, value, xorBlock); - assert(IsAligned(block)); - assert(IsAligned(xorBlock)); -#endif - *reinterpret_cast(block) = ConditionalByteReverse(order, value) ^ (xorBlock ? *reinterpret_cast(xorBlock) : 0); -} - -template -class GetBlock -{ -public: - GetBlock(const void *block) - : m_block((const byte *)block) {} - - template - inline GetBlock & operator()(U &x) - { - CRYPTOPP_COMPILE_ASSERT(sizeof(U) >= sizeof(T)); - x = GetWord(A, B::ToEnum(), m_block); - m_block += sizeof(T); - return *this; - } - -private: - const byte *m_block; -}; - -template -class PutBlock -{ -public: - PutBlock(const void *xorBlock, void *block) - : m_xorBlock((const byte *)xorBlock), m_block((byte *)block) {} - - template - inline PutBlock & operator()(U x) - { - PutWord(A, B::ToEnum(), m_block, (T)x, m_xorBlock); - m_block += sizeof(T); - if (m_xorBlock) - m_xorBlock += sizeof(T); - return *this; - } - -private: - const byte *m_xorBlock; - byte *m_block; -}; - -template -struct BlockGetAndPut -{ - // function needed because of C++ grammatical ambiguity between expression-statements and declarations - static inline GetBlock Get(const void *block) {return GetBlock(block);} - typedef PutBlock Put; -}; - -template -std::string WordToString(T value, ByteOrder order = BIG_ENDIAN_ORDER) -{ - if (!NativeByteOrderIs(order)) - value = ByteReverse(value); - - return std::string((char *)&value, sizeof(value)); -} - -template -T StringToWord(const std::string &str, ByteOrder order = BIG_ENDIAN_ORDER) -{ - T value = 0; - memcpy_s(&value, sizeof(value), str.data(), UnsignedMin(str.size(), sizeof(value))); - return NativeByteOrderIs(order) ? value : ByteReverse(value); -} - -// ************** help remove warning on g++ *************** - -template struct SafeShifter; - -template<> struct SafeShifter -{ - template - static inline T RightShift(T value, unsigned int bits) - { - return 0; - } - - template - static inline T LeftShift(T value, unsigned int bits) - { - return 0; - } -}; - -template<> struct SafeShifter -{ - template - static inline T RightShift(T value, unsigned int bits) - { - return value >> bits; - } - - template - static inline T LeftShift(T value, unsigned int bits) - { - return value << bits; - } -}; - -template -inline T SafeRightShift(T value) -{ - return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits); -} - -template -inline T SafeLeftShift(T value) -{ - return SafeShifter<(bits>=(8*sizeof(T)))>::LeftShift(value, bits); -} - -// ************** use one buffer for multiple data members *************** - -#define CRYPTOPP_BLOCK_1(n, t, s) t* m_##n() {return (t *)(m_aggregate+0);} size_t SS1() {return sizeof(t)*(s);} size_t m_##n##Size() {return (s);} -#define CRYPTOPP_BLOCK_2(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS1());} size_t SS2() {return SS1()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} -#define CRYPTOPP_BLOCK_3(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS2());} size_t SS3() {return SS2()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} -#define CRYPTOPP_BLOCK_4(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS3());} size_t SS4() {return SS3()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} -#define CRYPTOPP_BLOCK_5(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS4());} size_t SS5() {return SS4()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} -#define CRYPTOPP_BLOCK_6(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS5());} size_t SS6() {return SS5()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} -#define CRYPTOPP_BLOCK_7(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS6());} size_t SS7() {return SS6()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} -#define CRYPTOPP_BLOCK_8(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS7());} size_t SS8() {return SS7()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} -#define CRYPTOPP_BLOCKS_END(i) size_t SST() {return SS##i();} void AllocateBlocks() {m_aggregate.New(SST());} AlignedSecByteBlock m_aggregate; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/modarith.h b/embeddedcryptopp/modarith.h deleted file mode 100644 index c0368e3..0000000 --- a/embeddedcryptopp/modarith.h +++ /dev/null @@ -1,158 +0,0 @@ -#ifndef CRYPTOPP_MODARITH_H -#define CRYPTOPP_MODARITH_H - -// implementations are in integer.cpp - -#include "cryptlib.h" -#include "misc.h" -#include "integer.h" -#include "algebra.h" - -NAMESPACE_BEGIN(CryptoPP) - -CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup; -CRYPTOPP_DLL_TEMPLATE_CLASS AbstractRing; -CRYPTOPP_DLL_TEMPLATE_CLASS AbstractEuclideanDomain; - -//! ring of congruence classes modulo n -/*! \note this implementation represents each congruence class as the smallest non-negative integer in that class */ -class CRYPTOPP_DLL ModularArithmetic : public AbstractRing -{ -public: - - typedef int RandomizationParameter; - typedef Integer Element; - - ModularArithmetic(const Integer &modulus = Integer::One()) - : m_modulus(modulus), m_result((word)0, modulus.reg.size()) {} - - ModularArithmetic(const ModularArithmetic &ma) - : m_modulus(ma.m_modulus), m_result((word)0, m_modulus.reg.size()) {} - - ModularArithmetic(BufferedTransformation &bt); // construct from BER encoded parameters - - virtual ModularArithmetic * Clone() const {return new ModularArithmetic(*this);} - - void DEREncode(BufferedTransformation &bt) const; - - void DEREncodeElement(BufferedTransformation &out, const Element &a) const; - void BERDecodeElement(BufferedTransformation &in, Element &a) const; - - const Integer& GetModulus() const {return m_modulus;} - void SetModulus(const Integer &newModulus) {m_modulus = newModulus; m_result.reg.resize(m_modulus.reg.size());} - - virtual bool IsMontgomeryRepresentation() const {return false;} - - virtual Integer ConvertIn(const Integer &a) const - {return a%m_modulus;} - - virtual Integer ConvertOut(const Integer &a) const - {return a;} - - const Integer& Half(const Integer &a) const; - - bool Equal(const Integer &a, const Integer &b) const - {return a==b;} - - const Integer& Identity() const - {return Integer::Zero();} - - const Integer& Add(const Integer &a, const Integer &b) const; - - Integer& Accumulate(Integer &a, const Integer &b) const; - - const Integer& Inverse(const Integer &a) const; - - const Integer& Subtract(const Integer &a, const Integer &b) const; - - Integer& Reduce(Integer &a, const Integer &b) const; - - const Integer& Double(const Integer &a) const - {return Add(a, a);} - - const Integer& MultiplicativeIdentity() const - {return Integer::One();} - - const Integer& Multiply(const Integer &a, const Integer &b) const - {return m_result1 = a*b%m_modulus;} - - const Integer& Square(const Integer &a) const - {return m_result1 = a.Squared()%m_modulus;} - - bool IsUnit(const Integer &a) const - {return Integer::Gcd(a, m_modulus).IsUnit();} - - const Integer& MultiplicativeInverse(const Integer &a) const - {return m_result1 = a.InverseMod(m_modulus);} - - const Integer& Divide(const Integer &a, const Integer &b) const - {return Multiply(a, MultiplicativeInverse(b));} - - Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const; - - void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const; - - unsigned int MaxElementBitLength() const - {return (m_modulus-1).BitCount();} - - unsigned int MaxElementByteLength() const - {return (m_modulus-1).ByteCount();} - - Element RandomElement( RandomNumberGenerator &rng , const RandomizationParameter &ignore_for_now = 0 ) const - // left RandomizationParameter arg as ref in case RandomizationParameter becomes a more complicated struct - { - return Element( rng , Integer( (long) 0) , m_modulus - Integer( (long) 1 ) ) ; - } - - bool operator==(const ModularArithmetic &rhs) const - {return m_modulus == rhs.m_modulus;} - - static const RandomizationParameter DefaultRandomizationParameter ; - -protected: - Integer m_modulus; - mutable Integer m_result, m_result1; - -}; - -// const ModularArithmetic::RandomizationParameter ModularArithmetic::DefaultRandomizationParameter = 0 ; - -//! do modular arithmetics in Montgomery representation for increased speed -/*! \note the Montgomery representation represents each congruence class [a] as a*r%n, where r is a convenient power of 2 */ -class CRYPTOPP_DLL MontgomeryRepresentation : public ModularArithmetic -{ -public: - MontgomeryRepresentation(const Integer &modulus); // modulus must be odd - - virtual ModularArithmetic * Clone() const {return new MontgomeryRepresentation(*this);} - - bool IsMontgomeryRepresentation() const {return true;} - - Integer ConvertIn(const Integer &a) const - {return (a<<(WORD_BITS*m_modulus.reg.size()))%m_modulus;} - - Integer ConvertOut(const Integer &a) const; - - const Integer& MultiplicativeIdentity() const - {return m_result1 = Integer::Power2(WORD_BITS*m_modulus.reg.size())%m_modulus;} - - const Integer& Multiply(const Integer &a, const Integer &b) const; - - const Integer& Square(const Integer &a) const; - - const Integer& MultiplicativeInverse(const Integer &a) const; - - Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const - {return AbstractRing::CascadeExponentiate(x, e1, y, e2);} - - void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const - {AbstractRing::SimultaneousExponentiate(results, base, exponents, exponentsCount);} - -private: - Integer m_u; - mutable IntegerSecBlock m_workspace; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/modes.cpp b/embeddedcryptopp/modes.cpp deleted file mode 100644 index 81bf4de..0000000 --- a/embeddedcryptopp/modes.cpp +++ /dev/null @@ -1,243 +0,0 @@ -// modes.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "modes.h" - -#ifndef NDEBUG -#include "des.h" -#endif - -NAMESPACE_BEGIN(CryptoPP) - -#ifndef NDEBUG -void Modes_TestInstantiations() -{ - CFB_Mode::Encryption m0; - CFB_Mode::Decryption m1; - OFB_Mode::Encryption m2; - CTR_Mode::Encryption m3; - ECB_Mode::Encryption m4; - CBC_Mode::Encryption m5; -} -#endif - -void CFB_ModePolicy::Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount) -{ - assert(m_cipher->IsForwardTransformation()); // CFB mode needs the "encrypt" direction of the underlying block cipher, even to decrypt - assert(m_feedbackSize == BlockSize()); - - unsigned int s = BlockSize(); - if (dir == ENCRYPTION) - { - m_cipher->ProcessAndXorBlock(m_register, input, output); - m_cipher->AdvancedProcessBlocks(output, input+s, output+s, (iterationCount-1)*s, 0); - memcpy(m_register, output+(iterationCount-1)*s, s); - } - else - { - memcpy(m_temp, input+(iterationCount-1)*s, s); // make copy first in case of in-place decryption - m_cipher->AdvancedProcessBlocks(input, input+s, output+s, (iterationCount-1)*s, BlockTransformation::BT_ReverseDirection); - m_cipher->ProcessAndXorBlock(m_register, input, output); - memcpy(m_register, m_temp, s); - } -} - -void CFB_ModePolicy::TransformRegister() -{ - assert(m_cipher->IsForwardTransformation()); // CFB mode needs the "encrypt" direction of the underlying block cipher, even to decrypt - m_cipher->ProcessBlock(m_register, m_temp); - unsigned int updateSize = BlockSize()-m_feedbackSize; - memmove_s(m_register, m_register.size(), m_register+m_feedbackSize, updateSize); - memcpy_s(m_register+updateSize, m_register.size()-updateSize, m_temp, m_feedbackSize); -} - -void CFB_ModePolicy::CipherResynchronize(const byte *iv, size_t length) -{ - memcpy_s(m_register, m_register.size(), iv, BlockSize()); - TransformRegister(); -} - -void CFB_ModePolicy::SetFeedbackSize(unsigned int feedbackSize) -{ - if (feedbackSize > BlockSize()) - throw InvalidArgument("CFB_Mode: invalid feedback size"); - m_feedbackSize = feedbackSize ? feedbackSize : BlockSize(); -} - -void CFB_ModePolicy::ResizeBuffers() -{ - CipherModeBase::ResizeBuffers(); - m_temp.New(BlockSize()); -} - -void OFB_ModePolicy::WriteKeystream(byte *keystreamBuffer, size_t iterationCount) -{ - assert(m_cipher->IsForwardTransformation()); // OFB mode needs the "encrypt" direction of the underlying block cipher, even to decrypt - unsigned int s = BlockSize(); - m_cipher->ProcessBlock(m_register, keystreamBuffer); - if (iterationCount > 1) - m_cipher->AdvancedProcessBlocks(keystreamBuffer, NULL, keystreamBuffer+s, s*(iterationCount-1), 0); - memcpy(m_register, keystreamBuffer+s*(iterationCount-1), s); -} - -void OFB_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) -{ - CopyOrZero(m_register, iv, length); -} - -void CTR_ModePolicy::SeekToIteration(lword iterationCount) -{ - int carry=0; - for (int i=BlockSize()-1; i>=0; i--) - { - unsigned int sum = m_register[i] + byte(iterationCount) + carry; - m_counterArray[i] = (byte) sum; - carry = sum >> 8; - iterationCount >>= 8; - } -} - -void CTR_ModePolicy::IncrementCounterBy256() -{ - IncrementCounterByOne(m_counterArray, BlockSize()-1); -} - -void CTR_ModePolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) -{ - assert(m_cipher->IsForwardTransformation()); // CTR mode needs the "encrypt" direction of the underlying block cipher, even to decrypt - unsigned int s = BlockSize(); - unsigned int inputIncrement = input ? s : 0; - - while (iterationCount) - { - byte lsb = m_counterArray[s-1]; - size_t blocks = UnsignedMin(iterationCount, 256U-lsb); - m_cipher->AdvancedProcessBlocks(m_counterArray, input, output, blocks*s, BlockTransformation::BT_InBlockIsCounter); - if ((m_counterArray[s-1] = lsb + (byte)blocks) == 0) - IncrementCounterBy256(); - - output += blocks*s; - input += blocks*inputIncrement; - iterationCount -= blocks; - } -} - -void CTR_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) -{ - assert(length == BlockSize()); - CopyOrZero(m_register, iv, length); - m_counterArray = m_register; -} - -void BlockOrientedCipherModeBase::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) -{ - m_cipher->SetKey(key, length, params); - ResizeBuffers(); - if (IsResynchronizable()) - { - size_t ivLength; - const byte *iv = GetIVAndThrowIfInvalid(params, ivLength); - Resynchronize(iv, (int)ivLength); - } -} - -void ECB_OneWay::ProcessData(byte *outString, const byte *inString, size_t length) -{ - assert(length%BlockSize()==0); - m_cipher->AdvancedProcessBlocks(inString, NULL, outString, length, 0); -} - -void CBC_Encryption::ProcessData(byte *outString, const byte *inString, size_t length) -{ - if (!length) - return; - assert(length%BlockSize()==0); - - unsigned int blockSize = BlockSize(); - m_cipher->AdvancedProcessBlocks(inString, m_register, outString, blockSize, BlockTransformation::BT_XorInput); - if (length > blockSize) - m_cipher->AdvancedProcessBlocks(inString+blockSize, outString, outString+blockSize, length-blockSize, BlockTransformation::BT_XorInput); - memcpy(m_register, outString + length - blockSize, blockSize); -} - -void CBC_CTS_Encryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length) -{ - if (length <= BlockSize()) - { - if (!m_stolenIV) - throw InvalidArgument("CBC_Encryption: message is too short for ciphertext stealing"); - - // steal from IV - memcpy(outString, m_register, length); - outString = m_stolenIV; - } - else - { - // steal from next to last block - xorbuf(m_register, inString, BlockSize()); - m_cipher->ProcessBlock(m_register); - inString += BlockSize(); - length -= BlockSize(); - memcpy(outString+BlockSize(), m_register, length); - } - - // output last full ciphertext block - xorbuf(m_register, inString, length); - m_cipher->ProcessBlock(m_register); - memcpy(outString, m_register, BlockSize()); -} - -void CBC_Decryption::ProcessData(byte *outString, const byte *inString, size_t length) -{ - if (!length) - return; - assert(length%BlockSize()==0); - - unsigned int blockSize = BlockSize(); - memcpy(m_temp, inString+length-blockSize, blockSize); // save copy now in case of in-place decryption - if (length > blockSize) - m_cipher->AdvancedProcessBlocks(inString+blockSize, inString, outString+blockSize, length-blockSize, BlockTransformation::BT_ReverseDirection); - m_cipher->ProcessAndXorBlock(inString, m_register, outString); - m_register.swap(m_temp); -} - -void CBC_CTS_Decryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length) -{ - const byte *pn, *pn1; - bool stealIV = length <= BlockSize(); - - if (stealIV) - { - pn = inString; - pn1 = m_register; - } - else - { - pn = inString + BlockSize(); - pn1 = inString; - length -= BlockSize(); - } - - // decrypt last partial plaintext block - memcpy(m_temp, pn1, BlockSize()); - m_cipher->ProcessBlock(m_temp); - xorbuf(m_temp, pn, length); - - if (stealIV) - memcpy(outString, m_temp, length); - else - { - memcpy(outString+BlockSize(), m_temp, length); - // decrypt next to last plaintext block - memcpy(m_temp, pn, length); - m_cipher->ProcessBlock(m_temp); - xorbuf(outString, m_temp, m_register, BlockSize()); - } -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/modes.h b/embeddedcryptopp/modes.h deleted file mode 100644 index ff88d31..0000000 --- a/embeddedcryptopp/modes.h +++ /dev/null @@ -1,421 +0,0 @@ -#ifndef CRYPTOPP_MODES_H -#define CRYPTOPP_MODES_H - -/*! \file -*/ - -#include "cryptlib.h" -#include "secblock.h" -#include "misc.h" -#include "strciphr.h" -#include "argnames.h" -#include "algparam.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! Cipher modes documentation. See NIST SP 800-38A for definitions of these modes. See AuthenticatedSymmetricCipherDocumentation for authenticated encryption modes. - -/*! Each class derived from this one defines two types, Encryption and Decryption, - both of which implement the SymmetricCipher interface. - For each mode there are two classes, one of which is a template class, - and the other one has a name that ends in "_ExternalCipher". - The "external cipher" mode objects hold a reference to the underlying block cipher, - instead of holding an instance of it. The reference must be passed in to the constructor. - For the "cipher holder" classes, the CIPHER template parameter should be a class - derived from BlockCipherDocumentation, for example DES or AES. -*/ -struct CipherModeDocumentation : public SymmetricCipherDocumentation -{ -}; - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CipherModeBase : public SymmetricCipher -{ -public: - size_t MinKeyLength() const {return m_cipher->MinKeyLength();} - size_t MaxKeyLength() const {return m_cipher->MaxKeyLength();} - size_t DefaultKeyLength() const {return m_cipher->DefaultKeyLength();} - size_t GetValidKeyLength(size_t n) const {return m_cipher->GetValidKeyLength(n);} - bool IsValidKeyLength(size_t n) const {return m_cipher->IsValidKeyLength(n);} - - unsigned int OptimalDataAlignment() const {return m_cipher->OptimalDataAlignment();} - - unsigned int IVSize() const {return BlockSize();} - virtual IV_Requirement IVRequirement() const =0; - - void SetCipher(BlockCipher &cipher) - { - this->ThrowIfResynchronizable(); - this->m_cipher = &cipher; - this->ResizeBuffers(); - } - - void SetCipherWithIV(BlockCipher &cipher, const byte *iv, int feedbackSize = 0) - { - this->ThrowIfInvalidIV(iv); - this->m_cipher = &cipher; - this->ResizeBuffers(); - this->SetFeedbackSize(feedbackSize); - if (this->IsResynchronizable()) - this->Resynchronize(iv); - } - -protected: - CipherModeBase() : m_cipher(NULL) {} - inline unsigned int BlockSize() const {assert(m_register.size() > 0); return (unsigned int)m_register.size();} - virtual void SetFeedbackSize(unsigned int feedbackSize) - { - if (!(feedbackSize == 0 || feedbackSize == BlockSize())) - throw InvalidArgument("CipherModeBase: feedback size cannot be specified for this cipher mode"); - } - virtual void ResizeBuffers() - { - m_register.New(m_cipher->BlockSize()); - } - - BlockCipher *m_cipher; - AlignedSecByteBlock m_register; -}; - -template -class CRYPTOPP_NO_VTABLE ModePolicyCommonTemplate : public CipherModeBase, public POLICY_INTERFACE -{ - unsigned int GetAlignment() const {return m_cipher->OptimalDataAlignment();} - void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length); -}; - -template -void ModePolicyCommonTemplate::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) -{ - m_cipher->SetKey(key, length, params); - ResizeBuffers(); - int feedbackSize = params.GetIntValueWithDefault(Name::FeedbackSize(), 0); - SetFeedbackSize(feedbackSize); -} - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_ModePolicy : public ModePolicyCommonTemplate -{ -public: - IV_Requirement IVRequirement() const {return RANDOM_IV;} - static const char * CRYPTOPP_API StaticAlgorithmName() {return "CFB";} - -protected: - unsigned int GetBytesPerIteration() const {return m_feedbackSize;} - byte * GetRegisterBegin() {return m_register + BlockSize() - m_feedbackSize;} - bool CanIterate() const {return m_feedbackSize == BlockSize();} - void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount); - void TransformRegister(); - void CipherResynchronize(const byte *iv, size_t length); - void SetFeedbackSize(unsigned int feedbackSize); - void ResizeBuffers(); - - SecByteBlock m_temp; - unsigned int m_feedbackSize; -}; - -inline void CopyOrZero(void *dest, const void *src, size_t s) -{ - if (src) - memcpy_s(dest, s, src, s); - else - memset(dest, 0, s); -} - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE OFB_ModePolicy : public ModePolicyCommonTemplate -{ -public: - bool CipherIsRandomAccess() const {return false;} - IV_Requirement IVRequirement() const {return UNIQUE_IV;} - static const char * CRYPTOPP_API StaticAlgorithmName() {return "OFB";} - -private: - unsigned int GetBytesPerIteration() const {return BlockSize();} - unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();} - void WriteKeystream(byte *keystreamBuffer, size_t iterationCount); - void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length); -}; - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CTR_ModePolicy : public ModePolicyCommonTemplate -{ -public: - bool CipherIsRandomAccess() const {return true;} - IV_Requirement IVRequirement() const {return RANDOM_IV;} - static const char * CRYPTOPP_API StaticAlgorithmName() {return "CTR";} - -protected: - virtual void IncrementCounterBy256(); - - unsigned int GetAlignment() const {return m_cipher->OptimalDataAlignment();} - unsigned int GetBytesPerIteration() const {return BlockSize();} - unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();} - void WriteKeystream(byte *buffer, size_t iterationCount) - {OperateKeystream(WRITE_KEYSTREAM, buffer, NULL, iterationCount);} - bool CanOperateKeystream() const {return true;} - void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount); - void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length); - void SeekToIteration(lword iterationCount); - - AlignedSecByteBlock m_counterArray; -}; - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockOrientedCipherModeBase : public CipherModeBase -{ -public: - void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); - unsigned int MandatoryBlockSize() const {return BlockSize();} - bool IsRandomAccess() const {return false;} - bool IsSelfInverting() const {return false;} - bool IsForwardTransformation() const {return m_cipher->IsForwardTransformation();} - void Resynchronize(const byte *iv, int length=-1) {memcpy_s(m_register, m_register.size(), iv, ThrowIfInvalidIVLength(length));} - -protected: - bool RequireAlignedInput() const {return true;} - void ResizeBuffers() - { - CipherModeBase::ResizeBuffers(); - m_buffer.New(BlockSize()); - } - - SecByteBlock m_buffer; -}; - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ECB_OneWay : public BlockOrientedCipherModeBase -{ -public: - void SetKey(const byte *key, size_t length, const NameValuePairs ¶ms = g_nullNameValuePairs) - {m_cipher->SetKey(key, length, params); BlockOrientedCipherModeBase::ResizeBuffers();} - IV_Requirement IVRequirement() const {return NOT_RESYNCHRONIZABLE;} - unsigned int OptimalBlockSize() const {return BlockSize() * m_cipher->OptimalNumberOfParallelBlocks();} - void ProcessData(byte *outString, const byte *inString, size_t length); - static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECB";} -}; - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_ModeBase : public BlockOrientedCipherModeBase -{ -public: - IV_Requirement IVRequirement() const {return UNPREDICTABLE_RANDOM_IV;} - bool RequireAlignedInput() const {return false;} - unsigned int MinLastBlockSize() const {return 0;} - static const char * CRYPTOPP_API StaticAlgorithmName() {return "CBC";} -}; - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Encryption : public CBC_ModeBase -{ -public: - void ProcessData(byte *outString, const byte *inString, size_t length); -}; - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Encryption : public CBC_Encryption -{ -public: - void SetStolenIV(byte *iv) {m_stolenIV = iv;} - unsigned int MinLastBlockSize() const {return BlockSize()+1;} - void ProcessLastBlock(byte *outString, const byte *inString, size_t length); - static const char * CRYPTOPP_API StaticAlgorithmName() {return "CBC/CTS";} - -protected: - void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) - { - CBC_Encryption::UncheckedSetKey(key, length, params); - m_stolenIV = params.GetValueWithDefault(Name::StolenIV(), (byte *)NULL); - } - - byte *m_stolenIV; -}; - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Decryption : public CBC_ModeBase -{ -public: - void ProcessData(byte *outString, const byte *inString, size_t length); - -protected: - void ResizeBuffers() - { - BlockOrientedCipherModeBase::ResizeBuffers(); - m_temp.New(BlockSize()); - } - AlignedSecByteBlock m_temp; -}; - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Decryption : public CBC_Decryption -{ -public: - unsigned int MinLastBlockSize() const {return BlockSize()+1;} - void ProcessLastBlock(byte *outString, const byte *inString, size_t length); -}; - -//! _ -template -class CipherModeFinalTemplate_CipherHolder : protected ObjectHolder, public AlgorithmImpl > -{ -public: - CipherModeFinalTemplate_CipherHolder() - { - this->m_cipher = &this->m_object; - this->ResizeBuffers(); - } - CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length) - { - this->m_cipher = &this->m_object; - this->SetKey(key, length); - } - CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length, const byte *iv) - { - this->m_cipher = &this->m_object; - this->SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, this->m_cipher->BlockSize()))); - } - CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length, const byte *iv, int feedbackSize) - { - this->m_cipher = &this->m_object; - this->SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, this->m_cipher->BlockSize()))(Name::FeedbackSize(), feedbackSize)); - } - - static std::string CRYPTOPP_API StaticAlgorithmName() - {return CIPHER::StaticAlgorithmName() + "/" + BASE::StaticAlgorithmName();} -}; - -//! _ -template -class CipherModeFinalTemplate_ExternalCipher : public BASE -{ -public: - CipherModeFinalTemplate_ExternalCipher() {} - CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher) - {this->SetCipher(cipher);} - CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher, const byte *iv, int feedbackSize = 0) - {this->SetCipherWithIV(cipher, iv, feedbackSize);} - - std::string AlgorithmName() const - {return (this->m_cipher ? this->m_cipher->AlgorithmName() + "/" : std::string("")) + BASE::StaticAlgorithmName();} -}; - -CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate >; -CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate >; -CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate >; - -//! CFB mode -template -struct CFB_Mode : public CipherModeDocumentation -{ - typedef CipherModeFinalTemplate_CipherHolder > > > Encryption; - typedef CipherModeFinalTemplate_CipherHolder > > > Decryption; -}; - -//! CFB mode, external cipher -struct CFB_Mode_ExternalCipher : public CipherModeDocumentation -{ - typedef CipherModeFinalTemplate_ExternalCipher > > > Encryption; - typedef CipherModeFinalTemplate_ExternalCipher > > > Decryption; -}; - -//! CFB mode FIPS variant, requiring full block plaintext according to FIPS 800-38A -template -struct CFB_FIPS_Mode : public CipherModeDocumentation -{ - typedef CipherModeFinalTemplate_CipherHolder > > > > Encryption; - typedef CipherModeFinalTemplate_CipherHolder > > > > Decryption; -}; - -//! CFB mode FIPS variant, requiring full block plaintext according to FIPS 800-38A, external cipher -struct CFB_FIPS_Mode_ExternalCipher : public CipherModeDocumentation -{ - typedef CipherModeFinalTemplate_ExternalCipher > > > > Encryption; - typedef CipherModeFinalTemplate_ExternalCipher > > > > Decryption; -}; - -CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate >; - -//! OFB mode -template -struct OFB_Mode : public CipherModeDocumentation -{ - typedef CipherModeFinalTemplate_CipherHolder > > > Encryption; - typedef Encryption Decryption; -}; - -//! OFB mode, external cipher -struct OFB_Mode_ExternalCipher : public CipherModeDocumentation -{ - typedef CipherModeFinalTemplate_ExternalCipher > > > Encryption; - typedef Encryption Decryption; -}; - -CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate >; - -//! CTR mode -template -struct CTR_Mode : public CipherModeDocumentation -{ - typedef CipherModeFinalTemplate_CipherHolder > > > Encryption; - typedef Encryption Decryption; -}; - -//! CTR mode, external cipher -struct CTR_Mode_ExternalCipher : public CipherModeDocumentation -{ - typedef CipherModeFinalTemplate_ExternalCipher > > > Encryption; - typedef Encryption Decryption; -}; - -//! ECB mode -template -struct ECB_Mode : public CipherModeDocumentation -{ - typedef CipherModeFinalTemplate_CipherHolder Encryption; - typedef CipherModeFinalTemplate_CipherHolder Decryption; -}; - -CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher; - -//! ECB mode, external cipher -struct ECB_Mode_ExternalCipher : public CipherModeDocumentation -{ - typedef CipherModeFinalTemplate_ExternalCipher Encryption; - typedef Encryption Decryption; -}; - -//! CBC mode -template -struct CBC_Mode : public CipherModeDocumentation -{ - typedef CipherModeFinalTemplate_CipherHolder Encryption; - typedef CipherModeFinalTemplate_CipherHolder Decryption; -}; - -CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher; -CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher; - -//! CBC mode, external cipher -struct CBC_Mode_ExternalCipher : public CipherModeDocumentation -{ - typedef CipherModeFinalTemplate_ExternalCipher Encryption; - typedef CipherModeFinalTemplate_ExternalCipher Decryption; -}; - -//! CBC mode with ciphertext stealing -template -struct CBC_CTS_Mode : public CipherModeDocumentation -{ - typedef CipherModeFinalTemplate_CipherHolder Encryption; - typedef CipherModeFinalTemplate_CipherHolder Decryption; -}; - -CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher; -CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher; - -//! CBC mode with ciphertext stealing, external cipher -struct CBC_CTS_Mode_ExternalCipher : public CipherModeDocumentation -{ - typedef CipherModeFinalTemplate_ExternalCipher Encryption; - typedef CipherModeFinalTemplate_ExternalCipher Decryption; -}; - -#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY -typedef CFB_Mode_ExternalCipher::Encryption CFBEncryption; -typedef CFB_Mode_ExternalCipher::Decryption CFBDecryption; -typedef OFB_Mode_ExternalCipher::Encryption OFB; -typedef CTR_Mode_ExternalCipher::Encryption CounterMode; -#endif - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/modexppc.h b/embeddedcryptopp/modexppc.h deleted file mode 100644 index fbe7012..0000000 --- a/embeddedcryptopp/modexppc.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef CRYPTOPP_MODEXPPC_H -#define CRYPTOPP_MODEXPPC_H - -#include "modarith.h" -#include "eprecomp.h" -#include "smartptr.h" -#include "pubkey.h" - -NAMESPACE_BEGIN(CryptoPP) - -CRYPTOPP_DLL_TEMPLATE_CLASS DL_FixedBasePrecomputationImpl; - -class ModExpPrecomputation : public DL_GroupPrecomputation -{ -public: - // DL_GroupPrecomputation - bool NeedConversions() const {return true;} - Element ConvertIn(const Element &v) const {return m_mr->ConvertIn(v);} - virtual Element ConvertOut(const Element &v) const {return m_mr->ConvertOut(v);} - const AbstractGroup & GetGroup() const {return m_mr->MultiplicativeGroup();} - Element BERDecodeElement(BufferedTransformation &bt) const {return Integer(bt);} - void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {v.DEREncode(bt);} - - // non-inherited - void SetModulus(const Integer &v) {m_mr.reset(new MontgomeryRepresentation(v));} - const Integer & GetModulus() const {return m_mr->GetModulus();} - -private: - value_ptr m_mr; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/mqueue.cpp b/embeddedcryptopp/mqueue.cpp deleted file mode 100644 index 1d645d8..0000000 --- a/embeddedcryptopp/mqueue.cpp +++ /dev/null @@ -1,174 +0,0 @@ -// mqueue.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "mqueue.h" - -NAMESPACE_BEGIN(CryptoPP) - -MessageQueue::MessageQueue(unsigned int nodeSize) - : m_queue(nodeSize), m_lengths(1, 0U), m_messageCounts(1, 0U) -{ -} - -size_t MessageQueue::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const -{ - if (begin >= MaxRetrievable()) - return 0; - - return m_queue.CopyRangeTo2(target, begin, STDMIN(MaxRetrievable(), end), channel, blocking); -} - -size_t MessageQueue::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) -{ - transferBytes = STDMIN(MaxRetrievable(), transferBytes); - size_t blockedBytes = m_queue.TransferTo2(target, transferBytes, channel, blocking); - m_lengths.front() -= transferBytes; - return blockedBytes; -} - -bool MessageQueue::GetNextMessage() -{ - if (NumberOfMessages() > 0 && !AnyRetrievable()) - { - m_lengths.pop_front(); - if (m_messageCounts[0] == 0 && m_messageCounts.size() > 1) - m_messageCounts.pop_front(); - return true; - } - else - return false; -} - -unsigned int MessageQueue::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const -{ - ByteQueue::Walker walker(m_queue); - std::deque::const_iterator it = m_lengths.begin(); - unsigned int i; - for (i=0; i 0 && q2.AnyRetrievable()) - { - size_t len = length; - const byte *data = q2.Spy(len); - len = STDMIN(len, length); - if (memcmp(inString, data, len) != 0) - goto mismatch; - inString += len; - length -= len; - q2.Skip(len); - } - - q1.Put(inString, length); - - if (messageEnd) - { - if (q2.AnyRetrievable()) - goto mismatch; - else if (q2.AnyMessages()) - q2.GetNextMessage(); - else if (q2.NumberOfMessageSeries() > 0) - goto mismatch; - else - q1.MessageEnd(); - } - - return 0; - -mismatch: - return HandleMismatchDetected(blocking); - } -} - -bool EqualityComparisonFilter::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking) -{ - unsigned int i = MapChannel(channel); - - if (i == 2) - { - OutputMessageSeriesEnd(4, propagation, blocking, channel); - return false; - } - else if (m_mismatchDetected) - return false; - else - { - MessageQueue &q1 = m_q[i], &q2 = m_q[1-i]; - - if (q2.AnyRetrievable() || q2.AnyMessages()) - goto mismatch; - else if (q2.NumberOfMessageSeries() > 0) - return Output(2, (const byte *)"\1", 1, 0, blocking) != 0; - else - q1.MessageSeriesEnd(); - - return false; - -mismatch: - return HandleMismatchDetected(blocking); - } -} - -bool EqualityComparisonFilter::HandleMismatchDetected(bool blocking) -{ - m_mismatchDetected = true; - if (m_throwIfNotEqual) - throw MismatchDetected(); - return Output(1, (const byte *)"\0", 1, 0, blocking) != 0; -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/mqueue.h b/embeddedcryptopp/mqueue.h deleted file mode 100644 index efa57a7..0000000 --- a/embeddedcryptopp/mqueue.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef CRYPTOPP_MQUEUE_H -#define CRYPTOPP_MQUEUE_H - -#include "queue.h" -#include "filters.h" -#include - -NAMESPACE_BEGIN(CryptoPP) - -//! Message Queue -class CRYPTOPP_DLL MessageQueue : public AutoSignaling -{ -public: - MessageQueue(unsigned int nodeSize=256); - - void IsolatedInitialize(const NameValuePairs ¶meters) - {m_queue.IsolatedInitialize(parameters); m_lengths.assign(1, 0U); m_messageCounts.assign(1, 0U);} - size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking) - { - m_queue.Put(begin, length); - m_lengths.back() += length; - if (messageEnd) - { - m_lengths.push_back(0); - m_messageCounts.back()++; - } - return 0; - } - bool IsolatedFlush(bool hardFlush, bool blocking) {return false;} - bool IsolatedMessageSeriesEnd(bool blocking) - {m_messageCounts.push_back(0); return false;} - - lword MaxRetrievable() const - {return m_lengths.front();} - bool AnyRetrievable() const - {return m_lengths.front() > 0;} - - size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); - size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const; - - lword TotalBytesRetrievable() const - {return m_queue.MaxRetrievable();} - unsigned int NumberOfMessages() const - {return (unsigned int)m_lengths.size()-1;} - bool GetNextMessage(); - - unsigned int NumberOfMessagesInThisSeries() const - {return m_messageCounts[0];} - unsigned int NumberOfMessageSeries() const - {return (unsigned int)m_messageCounts.size()-1;} - - unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL) const; - - const byte * Spy(size_t &contiguousSize) const; - - void swap(MessageQueue &rhs); - -private: - ByteQueue m_queue; - std::deque m_lengths; - std::deque m_messageCounts; -}; - - -//! A filter that checks messages on two channels for equality -class CRYPTOPP_DLL EqualityComparisonFilter : public Unflushable > -{ -public: - struct MismatchDetected : public Exception {MismatchDetected() : Exception(DATA_INTEGRITY_CHECK_FAILED, "EqualityComparisonFilter: did not receive the same data on two channels") {}}; - - /*! if throwIfNotEqual is false, this filter will output a '\\0' byte when it detects a mismatch, '\\1' otherwise */ - EqualityComparisonFilter(BufferedTransformation *attachment=NULL, bool throwIfNotEqual=true, const std::string &firstChannel="0", const std::string &secondChannel="1") - : m_throwIfNotEqual(throwIfNotEqual), m_mismatchDetected(false) - , m_firstChannel(firstChannel), m_secondChannel(secondChannel) - {Detach(attachment);} - - size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking); - bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true); - -private: - unsigned int MapChannel(const std::string &channel) const; - bool HandleMismatchDetected(bool blocking); - - bool m_throwIfNotEqual, m_mismatchDetected; - std::string m_firstChannel, m_secondChannel; - MessageQueue m_q[2]; -}; - -NAMESPACE_END - -#ifndef __BORLANDC__ -NAMESPACE_BEGIN(std) -template<> inline void swap(CryptoPP::MessageQueue &a, CryptoPP::MessageQueue &b) -{ - a.swap(b); -} -NAMESPACE_END -#endif - -#endif diff --git a/embeddedcryptopp/mqv.h b/embeddedcryptopp/mqv.h deleted file mode 100644 index 2683817..0000000 --- a/embeddedcryptopp/mqv.h +++ /dev/null @@ -1,141 +0,0 @@ -#ifndef CRYPTOPP_MQV_H -#define CRYPTOPP_MQV_H - -/** \file -*/ - -#include "gfpcrypt.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! _ -template -class MQV_Domain : public AuthenticatedKeyAgreementDomain -{ -public: - typedef GROUP_PARAMETERS GroupParameters; - typedef typename GroupParameters::Element Element; - typedef MQV_Domain Domain; - - MQV_Domain() {} - - MQV_Domain(const GroupParameters ¶ms) - : m_groupParameters(params) {} - - MQV_Domain(BufferedTransformation &bt) - {m_groupParameters.BERDecode(bt);} - - template - MQV_Domain(T1 v1, T2 v2) - {m_groupParameters.Initialize(v1, v2);} - - template - MQV_Domain(T1 v1, T2 v2, T3 v3) - {m_groupParameters.Initialize(v1, v2, v3);} - - template - MQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4) - {m_groupParameters.Initialize(v1, v2, v3, v4);} - - const GroupParameters & GetGroupParameters() const {return m_groupParameters;} - GroupParameters & AccessGroupParameters() {return m_groupParameters;} - - CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();} - - unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);} - unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();} - unsigned int StaticPublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);} - - void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const - { - Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent()); - x.Encode(privateKey, StaticPrivateKeyLength()); - } - - void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const - { - const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); - Integer x(privateKey, StaticPrivateKeyLength()); - Element y = params.ExponentiateBase(x); - params.EncodeElement(true, y, publicKey); - } - - unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();} - unsigned int EphemeralPublicKeyLength() const {return StaticPublicKeyLength();} - - void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const - { - const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); - Integer x(rng, Integer::One(), params.GetMaxExponent()); - x.Encode(privateKey, StaticPrivateKeyLength()); - Element y = params.ExponentiateBase(x); - params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength()); - } - - void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const - { - memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength()); - } - - bool Agree(byte *agreedValue, - const byte *staticPrivateKey, const byte *ephemeralPrivateKey, - const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey, - bool validateStaticOtherPublicKey=true) const - { - try - { - const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); - Element WW = params.DecodeElement(staticOtherPublicKey, validateStaticOtherPublicKey); - Element VV = params.DecodeElement(ephemeralOtherPublicKey, true); - - Integer s(staticPrivateKey, StaticPrivateKeyLength()); - Integer u(ephemeralPrivateKey, StaticPrivateKeyLength()); - Element V = params.DecodeElement(ephemeralPrivateKey+StaticPrivateKeyLength(), false); - - const Integer &r = params.GetSubgroupOrder(); - Integer h2 = Integer::Power2((r.BitCount()+1)/2); - Integer e = ((h2+params.ConvertElementToInteger(V)%h2)*s+u) % r; - Integer tt = h2 + params.ConvertElementToInteger(VV) % h2; - - if (COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION) - { - Element P = params.ExponentiateElement(WW, tt); - P = m_groupParameters.MultiplyElements(P, VV); - Element R[2]; - const Integer e2[2] = {r, e}; - params.SimultaneousExponentiate(R, P, e2, 2); - if (!params.IsIdentity(R[0]) || params.IsIdentity(R[1])) - return false; - params.EncodeElement(false, R[1], agreedValue); - } - else - { - const Integer &k = params.GetCofactor(); - if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION) - e = ModularArithmetic(r).Divide(e, k); - Element P = m_groupParameters.CascadeExponentiate(VV, k*e, WW, k*(e*tt%r)); - if (params.IsIdentity(P)) - return false; - params.EncodeElement(false, P, agreedValue); - } - } - catch (DL_BadElement &) - { - return false; - } - return true; - } - -private: - DL_GroupParameters & AccessAbstractGroupParameters() {return m_groupParameters;} - const DL_GroupParameters & GetAbstractGroupParameters() const {return m_groupParameters;} - - GroupParameters m_groupParameters; -}; - -//! Menezes-Qu-Vanstone in GF(p) with key validation, AKA MQV -typedef MQV_Domain MQV; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/nbtheory.cpp b/embeddedcryptopp/nbtheory.cpp deleted file mode 100644 index 3fdea4e..0000000 --- a/embeddedcryptopp/nbtheory.cpp +++ /dev/null @@ -1,1123 +0,0 @@ -// nbtheory.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "nbtheory.h" -#include "modarith.h" -#include "algparam.h" - -#include -#include - -#ifdef _OPENMP -// needed in MSVC 2005 to generate correct manifest -#include -#endif - -NAMESPACE_BEGIN(CryptoPP) - -const word s_lastSmallPrime = 32719; - -struct NewPrimeTable -{ - std::vector * operator()() const - { - const unsigned int maxPrimeTableSize = 3511; - - std::auto_ptr > pPrimeTable(new std::vector); - std::vector &primeTable = *pPrimeTable; - primeTable.reserve(maxPrimeTableSize); - - primeTable.push_back(2); - unsigned int testEntriesEnd = 1; - - for (unsigned int p=3; p<=s_lastSmallPrime; p+=2) - { - unsigned int j; - for (j=1; j &primeTable = Singleton, NewPrimeTable>().Ref(); - size = (unsigned int)primeTable.size(); - return &primeTable[0]; -} - -bool IsSmallPrime(const Integer &p) -{ - unsigned int primeTableSize; - const word16 * primeTable = GetPrimeTable(primeTableSize); - - if (p.IsPositive() && p <= primeTable[primeTableSize-1]) - return std::binary_search(primeTable, primeTable+primeTableSize, (word16)p.ConvertToLong()); - else - return false; -} - -bool TrialDivision(const Integer &p, unsigned bound) -{ - unsigned int primeTableSize; - const word16 * primeTable = GetPrimeTable(primeTableSize); - - assert(primeTable[primeTableSize-1] >= bound); - - unsigned int i; - for (i = 0; primeTable[i]3 && b>1 && b3 && b>1 && b>a; - - Integer z = a_exp_b_mod_c(b, m, n); - if (z==1 || z==nminus1) - return true; - for (unsigned j=1; j3); - - Integer b; - for (unsigned int i=0; i2); - - Integer b=3; - unsigned int i=0; - int j; - - while ((j=Jacobi(b.Squared()-4, n)) == 1) - { - if (++i==64 && n.IsSquare()) // avoid infinite loop if n is a square - return false; - ++b; ++b; - } - - if (j==0) - return false; - else - return Lucas(n+1, b, n)==2; -} - -bool IsStrongLucasProbablePrime(const Integer &n) -{ - if (n <= 1) - return false; - - if (n.IsEven()) - return n==2; - - assert(n>2); - - Integer b=3; - unsigned int i=0; - int j; - - while ((j=Jacobi(b.Squared()-4, n)) == 1) - { - if (++i==64 && n.IsSquare()) // avoid infinite loop if n is a square - return false; - ++b; ++b; - } - - if (j==0) - return false; - - Integer n1 = n+1; - unsigned int a; - - // calculate a = largest power of 2 that divides n1 - for (a=0; ; a++) - if (n1.GetBit(a)) - break; - Integer m = n1>>a; - - Integer z = Lucas(m, b, n); - if (z==2 || z==n-2) - return true; - for (i=1; i().Ref()) - return SmallDivisorsTest(p); - else - return SmallDivisorsTest(p) && IsStrongProbablePrime(p, 3) && IsStrongLucasProbablePrime(p); -} - -bool VerifyPrime(RandomNumberGenerator &rng, const Integer &p, unsigned int level) -{ - bool pass = IsPrime(p) && RabinMillerTest(rng, p, 1); - if (level >= 1) - pass = pass && RabinMillerTest(rng, p, 10); - return pass; -} - -unsigned int PrimeSearchInterval(const Integer &max) -{ - return max.BitCount(); -} - -static inline bool FastProbablePrimeTest(const Integer &n) -{ - return IsStrongProbablePrime(n,2); -} - -AlgorithmParameters MakeParametersForTwoPrimesOfEqualSize(unsigned int productBitLength) -{ - if (productBitLength < 16) - throw InvalidArgument("invalid bit length"); - - Integer minP, maxP; - - if (productBitLength%2==0) - { - minP = Integer(182) << (productBitLength/2-8); - maxP = Integer::Power2(productBitLength/2)-1; - } - else - { - minP = Integer::Power2((productBitLength-1)/2); - maxP = Integer(181) << ((productBitLength+1)/2-8); - } - - return MakeParameters("RandomNumberType", Integer::PRIME)("Min", minP)("Max", maxP); -} - -class PrimeSieve -{ -public: - // delta == 1 or -1 means double sieve with p = 2*q + delta - PrimeSieve(const Integer &first, const Integer &last, const Integer &step, signed int delta=0); - bool NextCandidate(Integer &c); - - void DoSieve(); - static void SieveSingle(std::vector &sieve, word16 p, const Integer &first, const Integer &step, word16 stepInv); - - Integer m_first, m_last, m_step; - signed int m_delta; - word m_next; - std::vector m_sieve; -}; - -PrimeSieve::PrimeSieve(const Integer &first, const Integer &last, const Integer &step, signed int delta) - : m_first(first), m_last(last), m_step(step), m_delta(delta), m_next(0) -{ - DoSieve(); -} - -bool PrimeSieve::NextCandidate(Integer &c) -{ - bool safe = SafeConvert(std::find(m_sieve.begin()+m_next, m_sieve.end(), false) - m_sieve.begin(), m_next); - assert(safe); - if (m_next == m_sieve.size()) - { - m_first += long(m_sieve.size())*m_step; - if (m_first > m_last) - return false; - else - { - m_next = 0; - DoSieve(); - return NextCandidate(c); - } - } - else - { - c = m_first + long(m_next)*m_step; - ++m_next; - return true; - } -} - -void PrimeSieve::SieveSingle(std::vector &sieve, word16 p, const Integer &first, const Integer &step, word16 stepInv) -{ - if (stepInv) - { - size_t sieveSize = sieve.size(); - size_t j = (word32(p-(first%p))*stepInv) % p; - // if the first multiple of p is p, skip it - if (first.WordCount() <= 1 && first + step*long(j) == p) - j += p; - for (; j < sieveSize; j += p) - sieve[j] = true; - } -} - -void PrimeSieve::DoSieve() -{ - unsigned int primeTableSize; - const word16 * primeTable = GetPrimeTable(primeTableSize); - - const unsigned int maxSieveSize = 32768; - unsigned int sieveSize = STDMIN(Integer(maxSieveSize), (m_last-m_first)/m_step+1).ConvertToLong(); - - m_sieve.clear(); - m_sieve.resize(sieveSize, false); - - if (m_delta == 0) - { - for (unsigned int i = 0; i < primeTableSize; ++i) - SieveSingle(m_sieve, primeTable[i], m_first, m_step, (word16)m_step.InverseMod(primeTable[i])); - } - else - { - assert(m_step%2==0); - Integer qFirst = (m_first-m_delta) >> 1; - Integer halfStep = m_step >> 1; - for (unsigned int i = 0; i < primeTableSize; ++i) - { - word16 p = primeTable[i]; - word16 stepInv = (word16)m_step.InverseMod(p); - SieveSingle(m_sieve, p, m_first, m_step, stepInv); - - word16 halfStepInv = 2*stepInv < p ? 2*stepInv : 2*stepInv-p; - SieveSingle(m_sieve, p, qFirst, halfStep, halfStepInv); - } - } -} - -bool FirstPrime(Integer &p, const Integer &max, const Integer &equiv, const Integer &mod, const PrimeSelector *pSelector) -{ - assert(!equiv.IsNegative() && equiv < mod); - - Integer gcd = GCD(equiv, mod); - if (gcd != Integer::One()) - { - // the only possible prime p such that p%mod==equiv where GCD(mod,equiv)!=1 is GCD(mod,equiv) - if (p <= gcd && gcd <= max && IsPrime(gcd) && (!pSelector || pSelector->IsAcceptable(gcd))) - { - p = gcd; - return true; - } - else - return false; - } - - unsigned int primeTableSize; - const word16 * primeTable = GetPrimeTable(primeTableSize); - - if (p <= primeTable[primeTableSize-1]) - { - const word16 *pItr; - - --p; - if (p.IsPositive()) - pItr = std::upper_bound(primeTable, primeTable+primeTableSize, (word)p.ConvertToLong()); - else - pItr = primeTable; - - while (pItr < primeTable+primeTableSize && !(*pItr%mod == equiv && (!pSelector || pSelector->IsAcceptable(*pItr)))) - ++pItr; - - if (pItr < primeTable+primeTableSize) - { - p = *pItr; - return p <= max; - } - - p = primeTable[primeTableSize-1]+1; - } - - assert(p > primeTable[primeTableSize-1]); - - if (mod.IsOdd()) - return FirstPrime(p, max, CRT(equiv, mod, 1, 2, 1), mod<<1, pSelector); - - p += (equiv-p)%mod; - - if (p>max) - return false; - - PrimeSieve sieve(p, max, mod); - - while (sieve.NextCandidate(p)) - { - if ((!pSelector || pSelector->IsAcceptable(p)) && FastProbablePrimeTest(p) && IsPrime(p)) - return true; - } - - return false; -} - -// the following two functions are based on code and comments provided by Preda Mihailescu -static bool ProvePrime(const Integer &p, const Integer &q) -{ - assert(p < q*q*q); - assert(p % q == 1); - -// this is the Quisquater test. Numbers p having passed the Lucas - Lehmer test -// for q and verifying p < q^3 can only be built up of two factors, both = 1 mod q, -// or be prime. The next two lines build the discriminant of a quadratic equation -// which holds iff p is built up of two factors (excercise ... ) - - Integer r = (p-1)/q; - if (((r%q).Squared()-4*(r/q)).IsSquare()) - return false; - - unsigned int primeTableSize; - const word16 * primeTable = GetPrimeTable(primeTableSize); - - assert(primeTableSize >= 50); - for (int i=0; i<50; i++) - { - Integer b = a_exp_b_mod_c(primeTable[i], r, p); - if (b != 1) - return a_exp_b_mod_c(b, q, p) == 1; - } - return false; -} - -Integer MihailescuProvablePrime(RandomNumberGenerator &rng, unsigned int pbits) -{ - Integer p; - Integer minP = Integer::Power2(pbits-1); - Integer maxP = Integer::Power2(pbits) - 1; - - if (maxP <= Integer(s_lastSmallPrime).Squared()) - { - // Randomize() will generate a prime provable by trial division - p.Randomize(rng, minP, maxP, Integer::PRIME); - return p; - } - - unsigned int qbits = (pbits+2)/3 + 1 + rng.GenerateWord32(0, pbits/36); - Integer q = MihailescuProvablePrime(rng, qbits); - Integer q2 = q<<1; - - while (true) - { - // this initializes the sieve to search in the arithmetic - // progression p = p_0 + \lambda * q2 = p_0 + 2 * \lambda * q, - // with q the recursively generated prime above. We will be able - // to use Lucas tets for proving primality. A trick of Quisquater - // allows taking q > cubic_root(p) rather then square_root: this - // decreases the recursion. - - p.Randomize(rng, minP, maxP, Integer::ANY, 1, q2); - PrimeSieve sieve(p, STDMIN(p+PrimeSearchInterval(maxP)*q2, maxP), q2); - - while (sieve.NextCandidate(p)) - { - if (FastProbablePrimeTest(p) && ProvePrime(p, q)) - return p; - } - } - - // not reached - return p; -} - -Integer MaurerProvablePrime(RandomNumberGenerator &rng, unsigned int bits) -{ - const unsigned smallPrimeBound = 29, c_opt=10; - Integer p; - - unsigned int primeTableSize; - const word16 * primeTable = GetPrimeTable(primeTableSize); - - if (bits < smallPrimeBound) - { - do - p.Randomize(rng, Integer::Power2(bits-1), Integer::Power2(bits)-1, Integer::ANY, 1, 2); - while (TrialDivision(p, 1 << ((bits+1)/2))); - } - else - { - const unsigned margin = bits > 50 ? 20 : (bits-10)/2; - double relativeSize; - do - relativeSize = pow(2.0, double(rng.GenerateWord32())/0xffffffff - 1); - while (bits * relativeSize >= bits - margin); - - Integer a,b; - Integer q = MaurerProvablePrime(rng, unsigned(bits*relativeSize)); - Integer I = Integer::Power2(bits-2)/q; - Integer I2 = I << 1; - unsigned int trialDivisorBound = (unsigned int)STDMIN((unsigned long)primeTable[primeTableSize-1], (unsigned long)bits*bits/c_opt); - bool success = false; - while (!success) - { - p.Randomize(rng, I, I2, Integer::ANY); - p *= q; p <<= 1; ++p; - if (!TrialDivision(p, trialDivisorBound)) - { - a.Randomize(rng, 2, p-1, Integer::ANY); - b = a_exp_b_mod_c(a, (p-1)/q, p); - success = (GCD(b-1, p) == 1) && (a_exp_b_mod_c(b, q, p) == 1); - } - } - } - return p; -} - -Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q, const Integer &u) -{ - // isn't operator overloading great? - return p * (u * (xq-xp) % q) + xp; -/* - Integer t1 = xq-xp; - cout << hex << t1 << endl; - Integer t2 = u * t1; - cout << hex << t2 << endl; - Integer t3 = t2 % q; - cout << hex << t3 << endl; - Integer t4 = p * t3; - cout << hex << t4 << endl; - Integer t5 = t4 + xp; - cout << hex << t5 << endl; - return t5; -*/ -} - -Integer ModularSquareRoot(const Integer &a, const Integer &p) -{ - if (p%4 == 3) - return a_exp_b_mod_c(a, (p+1)/4, p); - - Integer q=p-1; - unsigned int r=0; - while (q.IsEven()) - { - r++; - q >>= 1; - } - - Integer n=2; - while (Jacobi(n, p) != -1) - ++n; - - Integer y = a_exp_b_mod_c(n, q, p); - Integer x = a_exp_b_mod_c(a, (q-1)/2, p); - Integer b = (x.Squared()%p)*a%p; - x = a*x%p; - Integer tempb, t; - - while (b != 1) - { - unsigned m=0; - tempb = b; - do - { - m++; - b = b.Squared()%p; - if (m==r) - return Integer::Zero(); - } - while (b != 1); - - t = y; - for (unsigned i=0; i>= 1; - b >>= 1; - k++; - } - - while (a[0]==0) - a >>= 1; - - while (b[0]==0) - b >>= 1; - - while (1) - { - switch (a.Compare(b)) - { - case -1: - b -= a; - while (b[0]==0) - b >>= 1; - break; - - case 0: - return (a <<= k); - - case 1: - a -= b; - while (a[0]==0) - a >>= 1; - break; - - default: - assert(false); - } - } -} - -Integer EuclideanMultiplicativeInverse(const Integer &a, const Integer &b) -{ - assert(b.Positive()); - - if (a.Negative()) - return EuclideanMultiplicativeInverse(a%b, b); - - if (b[0]==0) - { - if (!b || a[0]==0) - return Integer::Zero(); // no inverse - if (a==1) - return 1; - Integer u = EuclideanMultiplicativeInverse(b, a); - if (!u) - return Integer::Zero(); // no inverse - else - return (b*(a-u)+1)/a; - } - - Integer u=1, d=a, v1=b, v3=b, t1, t3, b2=(b+1)>>1; - - if (a[0]) - { - t1 = Integer::Zero(); - t3 = -b; - } - else - { - t1 = b2; - t3 = a>>1; - } - - while (!!t3) - { - while (t3[0]==0) - { - t3 >>= 1; - if (t1[0]==0) - t1 >>= 1; - else - { - t1 >>= 1; - t1 += b2; - } - } - if (t3.Positive()) - { - u = t1; - d = t3; - } - else - { - v1 = b-t1; - v3 = -t3; - } - t1 = u-v1; - t3 = d-v3; - if (t1.Negative()) - t1 += b; - } - if (d==1) - return u; - else - return Integer::Zero(); // no inverse -} -*/ - -int Jacobi(const Integer &aIn, const Integer &bIn) -{ - assert(bIn.IsOdd()); - - Integer b = bIn, a = aIn%bIn; - int result = 1; - - while (!!a) - { - unsigned i=0; - while (a.GetBit(i)==0) - i++; - a>>=i; - - if (i%2==1 && (b%8==3 || b%8==5)) - result = -result; - - if (a%4==3 && b%4==3) - result = -result; - - std::swap(a, b); - a %= b; - } - - return (b==1) ? result : 0; -} - -Integer Lucas(const Integer &e, const Integer &pIn, const Integer &n) -{ - unsigned i = e.BitCount(); - if (i==0) - return Integer::Two(); - - MontgomeryRepresentation m(n); - Integer p=m.ConvertIn(pIn%n), two=m.ConvertIn(Integer::Two()); - Integer v=p, v1=m.Subtract(m.Square(p), two); - - i--; - while (i--) - { - if (e.GetBit(i)) - { - // v = (v*v1 - p) % m; - v = m.Subtract(m.Multiply(v,v1), p); - // v1 = (v1*v1 - 2) % m; - v1 = m.Subtract(m.Square(v1), two); - } - else - { - // v1 = (v*v1 - p) % m; - v1 = m.Subtract(m.Multiply(v,v1), p); - // v = (v*v - 2) % m; - v = m.Subtract(m.Square(v), two); - } - } - return m.ConvertOut(v); -} - -// This is Peter Montgomery's unpublished Lucas sequence evalutation algorithm. -// The total number of multiplies and squares used is less than the binary -// algorithm (see above). Unfortunately I can't get it to run as fast as -// the binary algorithm because of the extra overhead. -/* -Integer Lucas(const Integer &n, const Integer &P, const Integer &modulus) -{ - if (!n) - return 2; - -#define f(A, B, C) m.Subtract(m.Multiply(A, B), C) -#define X2(A) m.Subtract(m.Square(A), two) -#define X3(A) m.Multiply(A, m.Subtract(m.Square(A), three)) - - MontgomeryRepresentation m(modulus); - Integer two=m.ConvertIn(2), three=m.ConvertIn(3); - Integer A=m.ConvertIn(P), B, C, p, d=n, e, r, t, T, U; - - while (d!=1) - { - p = d; - unsigned int b = WORD_BITS * p.WordCount(); - Integer alpha = (Integer(5)<<(2*b-2)).SquareRoot() - Integer::Power2(b-1); - r = (p*alpha)>>b; - e = d-r; - B = A; - C = two; - d = r; - - while (d!=e) - { - if (d>2)) - if ((dm3+em3==0 || dm3+em3==3) && (t = e, t >>= 2, t += e, d <= t)) - { - // #1 -// t = (d+d-e)/3; -// t = d; t += d; t -= e; t /= 3; -// e = (e+e-d)/3; -// e += e; e -= d; e /= 3; -// d = t; - -// t = (d+e)/3 - t = d; t += e; t /= 3; - e -= t; - d -= t; - - T = f(A, B, C); - U = f(T, A, B); - B = f(T, B, A); - A = U; - continue; - } - -// if (dm6 == em6 && d <= e + (e>>2)) - if (dm3 == em3 && dm2 == em2 && (t = e, t >>= 2, t += e, d <= t)) - { - // #2 -// d = (d-e)>>1; - d -= e; d >>= 1; - B = f(A, B, C); - A = X2(A); - continue; - } - -// if (d <= (e<<2)) - if (d <= (t = e, t <<= 2)) - { - // #3 - d -= e; - C = f(A, B, C); - swap(B, C); - continue; - } - - if (dm2 == em2) - { - // #4 -// d = (d-e)>>1; - d -= e; d >>= 1; - B = f(A, B, C); - A = X2(A); - continue; - } - - if (dm2 == 0) - { - // #5 - d >>= 1; - C = f(A, C, B); - A = X2(A); - continue; - } - - if (dm3 == 0) - { - // #6 -// d = d/3 - e; - d /= 3; d -= e; - T = X2(A); - C = f(T, f(A, B, C), C); - swap(B, C); - A = f(T, A, A); - continue; - } - - if (dm3+em3==0 || dm3+em3==3) - { - // #7 -// d = (d-e-e)/3; - d -= e; d -= e; d /= 3; - T = f(A, B, C); - B = f(T, A, B); - A = X3(A); - continue; - } - - if (dm3 == em3) - { - // #8 -// d = (d-e)/3; - d -= e; d /= 3; - T = f(A, B, C); - C = f(A, C, B); - B = T; - A = X3(A); - continue; - } - - assert(em2 == 0); - // #9 - e >>= 1; - C = f(C, B, A); - B = X2(B); - } - - A = f(A, B, C); - } - -#undef f -#undef X2 -#undef X3 - - return m.ConvertOut(A); -} -*/ - -Integer InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q, const Integer &u) -{ - Integer d = (m*m-4); - Integer p2, q2; - #pragma omp parallel - #pragma omp sections - { - #pragma omp section - { - p2 = p-Jacobi(d,p); - p2 = Lucas(EuclideanMultiplicativeInverse(e,p2), m, p); - } - #pragma omp section - { - q2 = q-Jacobi(d,q); - q2 = Lucas(EuclideanMultiplicativeInverse(e,q2), m, q); - } - } - return CRT(p2, p, q2, q, u); -} - -unsigned int FactoringWorkFactor(unsigned int n) -{ - // extrapolated from the table in Odlyzko's "The Future of Integer Factorization" - // updated to reflect the factoring of RSA-130 - if (n<5) return 0; - else return (unsigned int)(2.4 * pow((double)n, 1.0/3.0) * pow(log(double(n)), 2.0/3.0) - 5); -} - -unsigned int DiscreteLogWorkFactor(unsigned int n) -{ - // assuming discrete log takes about the same time as factoring - if (n<5) return 0; - else return (unsigned int)(2.4 * pow((double)n, 1.0/3.0) * pow(log(double(n)), 2.0/3.0) - 5); -} - -// ******************************************************** - -void PrimeAndGenerator::Generate(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned int qbits) -{ - // no prime exists for delta = -1, qbits = 4, and pbits = 5 - assert(qbits > 4); - assert(pbits > qbits); - - if (qbits+1 == pbits) - { - Integer minP = Integer::Power2(pbits-1); - Integer maxP = Integer::Power2(pbits) - 1; - bool success = false; - - while (!success) - { - p.Randomize(rng, minP, maxP, Integer::ANY, 6+5*delta, 12); - PrimeSieve sieve(p, STDMIN(p+PrimeSearchInterval(maxP)*12, maxP), 12, delta); - - while (sieve.NextCandidate(p)) - { - assert(IsSmallPrime(p) || SmallDivisorsTest(p)); - q = (p-delta) >> 1; - assert(IsSmallPrime(q) || SmallDivisorsTest(q)); - if (FastProbablePrimeTest(q) && FastProbablePrimeTest(p) && IsPrime(q) && IsPrime(p)) - { - success = true; - break; - } - } - } - - if (delta == 1) - { - // find g such that g is a quadratic residue mod p, then g has order q - // g=4 always works, but this way we get the smallest quadratic residue (other than 1) - for (g=2; Jacobi(g, p) != 1; ++g) {} - // contributed by Walt Tuvell: g should be the following according to the Law of Quadratic Reciprocity - assert((p%8==1 || p%8==7) ? g==2 : (p%12==1 || p%12==11) ? g==3 : g==4); - } - else - { - assert(delta == -1); - // find g such that g*g-4 is a quadratic non-residue, - // and such that g has order q - for (g=3; ; ++g) - if (Jacobi(g*g-4, p)==-1 && Lucas(q, g, p)==2) - break; - } - } - else - { - Integer minQ = Integer::Power2(qbits-1); - Integer maxQ = Integer::Power2(qbits) - 1; - Integer minP = Integer::Power2(pbits-1); - Integer maxP = Integer::Power2(pbits) - 1; - - do - { - q.Randomize(rng, minQ, maxQ, Integer::PRIME); - } while (!p.Randomize(rng, minP, maxP, Integer::PRIME, delta%q, q)); - - // find a random g of order q - if (delta==1) - { - do - { - Integer h(rng, 2, p-2, Integer::ANY); - g = a_exp_b_mod_c(h, (p-1)/q, p); - } while (g <= 1); - assert(a_exp_b_mod_c(g, q, p)==1); - } - else - { - assert(delta==-1); - do - { - Integer h(rng, 3, p-1, Integer::ANY); - if (Jacobi(h*h-4, p)==1) - continue; - g = Lucas((p+1)/q, h, p); - } while (g <= 2); - assert(Lucas(q, g, p) == 2); - } - } -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/nbtheory.h b/embeddedcryptopp/nbtheory.h deleted file mode 100644 index 6364792..0000000 --- a/embeddedcryptopp/nbtheory.h +++ /dev/null @@ -1,131 +0,0 @@ -// nbtheory.h - written and placed in the public domain by Wei Dai - -#ifndef CRYPTOPP_NBTHEORY_H -#define CRYPTOPP_NBTHEORY_H - -#include "integer.h" -#include "algparam.h" - -NAMESPACE_BEGIN(CryptoPP) - -// obtain pointer to small prime table and get its size -CRYPTOPP_DLL const word16 * CRYPTOPP_API GetPrimeTable(unsigned int &size); - -// ************ primality testing **************** - -// generate a provable prime -CRYPTOPP_DLL Integer CRYPTOPP_API MaurerProvablePrime(RandomNumberGenerator &rng, unsigned int bits); -CRYPTOPP_DLL Integer CRYPTOPP_API MihailescuProvablePrime(RandomNumberGenerator &rng, unsigned int bits); - -CRYPTOPP_DLL bool CRYPTOPP_API IsSmallPrime(const Integer &p); - -// returns true if p is divisible by some prime less than bound -// bound not be greater than the largest entry in the prime table -CRYPTOPP_DLL bool CRYPTOPP_API TrialDivision(const Integer &p, unsigned bound); - -// returns true if p is NOT divisible by small primes -CRYPTOPP_DLL bool CRYPTOPP_API SmallDivisorsTest(const Integer &p); - -// These is no reason to use these two, use the ones below instead -CRYPTOPP_DLL bool CRYPTOPP_API IsFermatProbablePrime(const Integer &n, const Integer &b); -CRYPTOPP_DLL bool CRYPTOPP_API IsLucasProbablePrime(const Integer &n); - -CRYPTOPP_DLL bool CRYPTOPP_API IsStrongProbablePrime(const Integer &n, const Integer &b); -CRYPTOPP_DLL bool CRYPTOPP_API IsStrongLucasProbablePrime(const Integer &n); - -// Rabin-Miller primality test, i.e. repeating the strong probable prime test -// for several rounds with random bases -CRYPTOPP_DLL bool CRYPTOPP_API RabinMillerTest(RandomNumberGenerator &rng, const Integer &w, unsigned int rounds); - -// primality test, used to generate primes -CRYPTOPP_DLL bool CRYPTOPP_API IsPrime(const Integer &p); - -// more reliable than IsPrime(), used to verify primes generated by others -CRYPTOPP_DLL bool CRYPTOPP_API VerifyPrime(RandomNumberGenerator &rng, const Integer &p, unsigned int level = 1); - -class CRYPTOPP_DLL PrimeSelector -{ -public: - const PrimeSelector *GetSelectorPointer() const {return this;} - virtual bool IsAcceptable(const Integer &candidate) const =0; -}; - -// use a fast sieve to find the first probable prime in {x | p<=x<=max and x%mod==equiv} -// returns true iff successful, value of p is undefined if no such prime exists -CRYPTOPP_DLL bool CRYPTOPP_API FirstPrime(Integer &p, const Integer &max, const Integer &equiv, const Integer &mod, const PrimeSelector *pSelector); - -CRYPTOPP_DLL unsigned int CRYPTOPP_API PrimeSearchInterval(const Integer &max); - -CRYPTOPP_DLL AlgorithmParameters CRYPTOPP_API MakeParametersForTwoPrimesOfEqualSize(unsigned int productBitLength); - -// ********** other number theoretic functions ************ - -inline Integer GCD(const Integer &a, const Integer &b) - {return Integer::Gcd(a,b);} -inline bool RelativelyPrime(const Integer &a, const Integer &b) - {return Integer::Gcd(a,b) == Integer::One();} -inline Integer LCM(const Integer &a, const Integer &b) - {return a/Integer::Gcd(a,b)*b;} -inline Integer EuclideanMultiplicativeInverse(const Integer &a, const Integer &b) - {return a.InverseMod(b);} - -// use Chinese Remainder Theorem to calculate x given x mod p and x mod q, and u = inverse of p mod q -CRYPTOPP_DLL Integer CRYPTOPP_API CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q, const Integer &u); - -// if b is prime, then Jacobi(a, b) returns 0 if a%b==0, 1 if a is quadratic residue mod b, -1 otherwise -// check a number theory book for what Jacobi symbol means when b is not prime -CRYPTOPP_DLL int CRYPTOPP_API Jacobi(const Integer &a, const Integer &b); - -// calculates the Lucas function V_e(p, 1) mod n -CRYPTOPP_DLL Integer CRYPTOPP_API Lucas(const Integer &e, const Integer &p, const Integer &n); -// calculates x such that m==Lucas(e, x, p*q), p q primes, u=inverse of p mod q -CRYPTOPP_DLL Integer CRYPTOPP_API InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q, const Integer &u); - -inline Integer ModularExponentiation(const Integer &a, const Integer &e, const Integer &m) - {return a_exp_b_mod_c(a, e, m);} -// returns x such that x*x%p == a, p prime -CRYPTOPP_DLL Integer CRYPTOPP_API ModularSquareRoot(const Integer &a, const Integer &p); -// returns x such that a==ModularExponentiation(x, e, p*q), p q primes, -// and e relatively prime to (p-1)*(q-1) -// dp=d%(p-1), dq=d%(q-1), (d is inverse of e mod (p-1)*(q-1)) -// and u=inverse of p mod q -CRYPTOPP_DLL Integer CRYPTOPP_API ModularRoot(const Integer &a, const Integer &dp, const Integer &dq, const Integer &p, const Integer &q, const Integer &u); - -// find r1 and r2 such that ax^2 + bx + c == 0 (mod p) for x in {r1, r2}, p prime -// returns true if solutions exist -CRYPTOPP_DLL bool CRYPTOPP_API SolveModularQuadraticEquation(Integer &r1, Integer &r2, const Integer &a, const Integer &b, const Integer &c, const Integer &p); - -// returns log base 2 of estimated number of operations to calculate discrete log or factor a number -CRYPTOPP_DLL unsigned int CRYPTOPP_API DiscreteLogWorkFactor(unsigned int bitlength); -CRYPTOPP_DLL unsigned int CRYPTOPP_API FactoringWorkFactor(unsigned int bitlength); - -// ******************************************************** - -//! generator of prime numbers of special forms -class CRYPTOPP_DLL PrimeAndGenerator -{ -public: - PrimeAndGenerator() {} - // generate a random prime p of the form 2*q+delta, where delta is 1 or -1 and q is also prime - // Precondition: pbits > 5 - // warning: this is slow, because primes of this form are harder to find - PrimeAndGenerator(signed int delta, RandomNumberGenerator &rng, unsigned int pbits) - {Generate(delta, rng, pbits, pbits-1);} - // generate a random prime p of the form 2*r*q+delta, where q is also prime - // Precondition: qbits > 4 && pbits > qbits - PrimeAndGenerator(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned qbits) - {Generate(delta, rng, pbits, qbits);} - - void Generate(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned qbits); - - const Integer& Prime() const {return p;} - const Integer& SubPrime() const {return q;} - const Integer& Generator() const {return g;} - -private: - Integer p, q, g; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/oaep.cpp b/embeddedcryptopp/oaep.cpp deleted file mode 100644 index 1d474be..0000000 --- a/embeddedcryptopp/oaep.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// oaep.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "oaep.h" -#include - -NAMESPACE_BEGIN(CryptoPP) - -// ******************************************************** - -size_t OAEP_Base::MaxUnpaddedLength(size_t paddedLength) const -{ - return SaturatingSubtract(paddedLength/8, 1+2*DigestSize()); -} - -void OAEP_Base::Pad(RandomNumberGenerator &rng, const byte *input, size_t inputLength, byte *oaepBlock, size_t oaepBlockLen, const NameValuePairs ¶meters) const -{ - assert (inputLength <= MaxUnpaddedLength(oaepBlockLen)); - - // convert from bit length to byte length - if (oaepBlockLen % 8 != 0) - { - oaepBlock[0] = 0; - oaepBlock++; - } - oaepBlockLen /= 8; - - std::auto_ptr pHash(NewHash()); - const size_t hLen = pHash->DigestSize(); - const size_t seedLen = hLen, dbLen = oaepBlockLen-seedLen; - byte *const maskedSeed = oaepBlock; - byte *const maskedDB = oaepBlock+seedLen; - - ConstByteArrayParameter encodingParameters; - parameters.GetValue(Name::EncodingParameters(), encodingParameters); - - // DB = pHash || 00 ... || 01 || M - pHash->CalculateDigest(maskedDB, encodingParameters.begin(), encodingParameters.size()); - memset(maskedDB+hLen, 0, dbLen-hLen-inputLength-1); - maskedDB[dbLen-inputLength-1] = 0x01; - memcpy(maskedDB+dbLen-inputLength, input, inputLength); - - rng.GenerateBlock(maskedSeed, seedLen); - std::auto_ptr pMGF(NewMGF()); - pMGF->GenerateAndMask(*pHash, maskedDB, dbLen, maskedSeed, seedLen); - pMGF->GenerateAndMask(*pHash, maskedSeed, seedLen, maskedDB, dbLen); -} - -DecodingResult OAEP_Base::Unpad(const byte *oaepBlock, size_t oaepBlockLen, byte *output, const NameValuePairs ¶meters) const -{ - bool invalid = false; - - // convert from bit length to byte length - if (oaepBlockLen % 8 != 0) - { - invalid = (oaepBlock[0] != 0) || invalid; - oaepBlock++; - } - oaepBlockLen /= 8; - - std::auto_ptr pHash(NewHash()); - const size_t hLen = pHash->DigestSize(); - const size_t seedLen = hLen, dbLen = oaepBlockLen-seedLen; - - invalid = (oaepBlockLen < 2*hLen+1) || invalid; - - SecByteBlock t(oaepBlock, oaepBlockLen); - byte *const maskedSeed = t; - byte *const maskedDB = t+seedLen; - - std::auto_ptr pMGF(NewMGF()); - pMGF->GenerateAndMask(*pHash, maskedSeed, seedLen, maskedDB, dbLen); - pMGF->GenerateAndMask(*pHash, maskedDB, dbLen, maskedSeed, seedLen); - - ConstByteArrayParameter encodingParameters; - parameters.GetValue(Name::EncodingParameters(), encodingParameters); - - // DB = pHash' || 00 ... || 01 || M - byte *M = std::find(maskedDB+hLen, maskedDB+dbLen, 0x01); - invalid = (M == maskedDB+dbLen) || invalid; - invalid = (std::find_if(maskedDB+hLen, M, std::bind2nd(std::not_equal_to(), 0)) != M) || invalid; - invalid = !pHash->VerifyDigest(maskedDB, encodingParameters.begin(), encodingParameters.size()) || invalid; - - if (invalid) - return DecodingResult(); - - M++; - memcpy(output, M, maskedDB+dbLen-M); - return DecodingResult(maskedDB+dbLen-M); -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/oaep.h b/embeddedcryptopp/oaep.h deleted file mode 100644 index 4bf6b0d..0000000 --- a/embeddedcryptopp/oaep.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef CRYPTOPP_OAEP_H -#define CRYPTOPP_OAEP_H - -#include "pubkey.h" -#include "sha.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! _ -class CRYPTOPP_DLL OAEP_Base : public PK_EncryptionMessageEncodingMethod -{ -public: - bool ParameterSupported(const char *name) const {return strcmp(name, Name::EncodingParameters()) == 0;} - size_t MaxUnpaddedLength(size_t paddedLength) const; - void Pad(RandomNumberGenerator &rng, const byte *raw, size_t inputLength, byte *padded, size_t paddedLength, const NameValuePairs ¶meters) const; - DecodingResult Unpad(const byte *padded, size_t paddedLength, byte *raw, const NameValuePairs ¶meters) const; - -protected: - virtual unsigned int DigestSize() const =0; - virtual HashTransformation * NewHash() const =0; - virtual MaskGeneratingFunction * NewMGF() const =0; -}; - -//! EME-OAEP, for use with classes derived from TF_ES -template -class OAEP : public OAEP_Base, public EncryptionStandard -{ -public: - static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string("OAEP-") + MGF::StaticAlgorithmName() + "(" + H::StaticAlgorithmName() + ")";} - typedef OAEP EncryptionMessageEncodingMethod; - -protected: - unsigned int DigestSize() const {return H::DIGESTSIZE;} - HashTransformation * NewHash() const {return new H;} - MaskGeneratingFunction * NewMGF() const {return new MGF;} -}; - -CRYPTOPP_DLL_TEMPLATE_CLASS OAEP; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/oids.h b/embeddedcryptopp/oids.h deleted file mode 100644 index 9911ec2..0000000 --- a/embeddedcryptopp/oids.h +++ /dev/null @@ -1,123 +0,0 @@ -#ifndef CRYPTOPP_OIDS_H -#define CRYPTOPP_OIDS_H - -// crypto-related ASN.1 object identifiers - -#include "asn.h" - -NAMESPACE_BEGIN(CryptoPP) - -NAMESPACE_BEGIN(ASN1) - -#define DEFINE_OID(value, name) inline OID name() {return value;} - -DEFINE_OID(1, iso) - DEFINE_OID(iso()+2, member_body) - DEFINE_OID(member_body()+840, iso_us) - DEFINE_OID(iso_us()+10040, ansi_x9_57) - DEFINE_OID(ansi_x9_57()+4+1, id_dsa) - DEFINE_OID(iso_us()+10045, ansi_x9_62) - DEFINE_OID(ansi_x9_62()+1, id_fieldType) - DEFINE_OID(id_fieldType()+1, prime_field) - DEFINE_OID(id_fieldType()+2, characteristic_two_field) - DEFINE_OID(characteristic_two_field()+3, id_characteristic_two_basis) - DEFINE_OID(id_characteristic_two_basis()+1, gnBasis) - DEFINE_OID(id_characteristic_two_basis()+2, tpBasis) - DEFINE_OID(id_characteristic_two_basis()+3, ppBasis) - DEFINE_OID(ansi_x9_62()+2, id_publicKeyType) - DEFINE_OID(id_publicKeyType()+1, id_ecPublicKey) - DEFINE_OID(ansi_x9_62()+3, ansi_x9_62_curves) - DEFINE_OID(ansi_x9_62_curves()+1, ansi_x9_62_curves_prime) - DEFINE_OID(ansi_x9_62_curves_prime()+1, secp192r1) - DEFINE_OID(ansi_x9_62_curves_prime()+7, secp256r1) - DEFINE_OID(iso_us()+113549, rsadsi) - DEFINE_OID(rsadsi()+1, pkcs) - DEFINE_OID(pkcs()+1, pkcs_1) - DEFINE_OID(pkcs_1()+1, rsaEncryption); - DEFINE_OID(rsadsi()+2, rsadsi_digestAlgorithm) - DEFINE_OID(rsadsi_digestAlgorithm()+2, id_md2) - DEFINE_OID(rsadsi_digestAlgorithm()+5, id_md5) - DEFINE_OID(iso()+3, identified_organization); - DEFINE_OID(identified_organization()+14, oiw); - DEFINE_OID(oiw()+14, oiw_secsig); - DEFINE_OID(oiw_secsig()+2, oiw_secsig_algorithms); - DEFINE_OID(oiw_secsig_algorithms()+26, id_sha1); - - DEFINE_OID(identified_organization()+36, teletrust); - DEFINE_OID(teletrust()+3, teletrust_algorithm) - DEFINE_OID(teletrust_algorithm()+2+1, id_ripemd160) - DEFINE_OID(teletrust_algorithm()+3+2+8+1, teletrust_ellipticCurve) - DEFINE_OID(teletrust_ellipticCurve()+1+1, brainpoolP160r1) - DEFINE_OID(teletrust_ellipticCurve()+1+3, brainpoolP192r1) - DEFINE_OID(teletrust_ellipticCurve()+1+5, brainpoolP224r1) - DEFINE_OID(teletrust_ellipticCurve()+1+7, brainpoolP256r1) - DEFINE_OID(teletrust_ellipticCurve()+1+9, brainpoolP320r1) - DEFINE_OID(teletrust_ellipticCurve()+1+11, brainpoolP384r1) - DEFINE_OID(teletrust_ellipticCurve()+1+13, brainpoolP512r1) - - DEFINE_OID(identified_organization()+132, certicom); - DEFINE_OID(certicom()+0, certicom_ellipticCurve); - // these are sorted by curve type and then by OID - // first curves based on GF(p) - DEFINE_OID(certicom_ellipticCurve()+6, secp112r1); - DEFINE_OID(certicom_ellipticCurve()+7, secp112r2); - DEFINE_OID(certicom_ellipticCurve()+8, secp160r1); - DEFINE_OID(certicom_ellipticCurve()+9, secp160k1); - DEFINE_OID(certicom_ellipticCurve()+10, secp256k1); - DEFINE_OID(certicom_ellipticCurve()+28, secp128r1); - DEFINE_OID(certicom_ellipticCurve()+29, secp128r2); - DEFINE_OID(certicom_ellipticCurve()+30, secp160r2); - DEFINE_OID(certicom_ellipticCurve()+31, secp192k1); - DEFINE_OID(certicom_ellipticCurve()+32, secp224k1); - DEFINE_OID(certicom_ellipticCurve()+33, secp224r1); - DEFINE_OID(certicom_ellipticCurve()+34, secp384r1); - DEFINE_OID(certicom_ellipticCurve()+35, secp521r1); - // then curves based on GF(2^n) - DEFINE_OID(certicom_ellipticCurve()+1, sect163k1); - DEFINE_OID(certicom_ellipticCurve()+2, sect163r1); - DEFINE_OID(certicom_ellipticCurve()+3, sect239k1); - DEFINE_OID(certicom_ellipticCurve()+4, sect113r1); - DEFINE_OID(certicom_ellipticCurve()+5, sect113r2); - DEFINE_OID(certicom_ellipticCurve()+15, sect163r2); - DEFINE_OID(certicom_ellipticCurve()+16, sect283k1); - DEFINE_OID(certicom_ellipticCurve()+17, sect283r1); - DEFINE_OID(certicom_ellipticCurve()+22, sect131r1); - DEFINE_OID(certicom_ellipticCurve()+23, sect131r2); - DEFINE_OID(certicom_ellipticCurve()+24, sect193r1); - DEFINE_OID(certicom_ellipticCurve()+25, sect193r2); - DEFINE_OID(certicom_ellipticCurve()+26, sect233k1); - DEFINE_OID(certicom_ellipticCurve()+27, sect233r1); - DEFINE_OID(certicom_ellipticCurve()+36, sect409k1); - DEFINE_OID(certicom_ellipticCurve()+37, sect409r1); - DEFINE_OID(certicom_ellipticCurve()+38, sect571k1); - DEFINE_OID(certicom_ellipticCurve()+39, sect571r1); -DEFINE_OID(2, joint_iso_ccitt) - DEFINE_OID(joint_iso_ccitt()+16, country) - DEFINE_OID(country()+840, joint_iso_ccitt_us) - DEFINE_OID(joint_iso_ccitt_us()+1, us_organization) - DEFINE_OID(us_organization()+101, us_gov) - DEFINE_OID(us_gov()+3, csor) - DEFINE_OID(csor()+4, nistalgorithms) - DEFINE_OID(nistalgorithms()+1, aes) - DEFINE_OID(aes()+1, id_aes128_ECB) - DEFINE_OID(aes()+2, id_aes128_cbc) - DEFINE_OID(aes()+3, id_aes128_ofb) - DEFINE_OID(aes()+4, id_aes128_cfb) - DEFINE_OID(aes()+21, id_aes192_ECB) - DEFINE_OID(aes()+22, id_aes192_cbc) - DEFINE_OID(aes()+23, id_aes192_ofb) - DEFINE_OID(aes()+24, id_aes192_cfb) - DEFINE_OID(aes()+41, id_aes256_ECB) - DEFINE_OID(aes()+42, id_aes256_cbc) - DEFINE_OID(aes()+43, id_aes256_ofb) - DEFINE_OID(aes()+44, id_aes256_cfb) - DEFINE_OID(nistalgorithms()+2, nist_hashalgs) - DEFINE_OID(nist_hashalgs()+1, id_sha256) - DEFINE_OID(nist_hashalgs()+2, id_sha384) - DEFINE_OID(nist_hashalgs()+3, id_sha512) - -NAMESPACE_END - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/osrng.cpp b/embeddedcryptopp/osrng.cpp deleted file mode 100644 index fa6dd36..0000000 --- a/embeddedcryptopp/osrng.cpp +++ /dev/null @@ -1,171 +0,0 @@ -// osrng.cpp - written and placed in the public domain by Wei Dai - -// Thanks to Leonard Janke for the suggestion for AutoSeededRandomPool. - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "osrng.h" - -#ifdef OS_RNG_AVAILABLE - -#include "rng.h" - -#ifdef CRYPTOPP_WIN32_AVAILABLE -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0400 -#endif -#include -#include -#endif - -#ifdef CRYPTOPP_UNIX_AVAILABLE -#include -#include -#include -#endif - -NAMESPACE_BEGIN(CryptoPP) - -#if defined(NONBLOCKING_RNG_AVAILABLE) || defined(BLOCKING_RNG_AVAILABLE) -OS_RNG_Err::OS_RNG_Err(const std::string &operation) - : Exception(OTHER_ERROR, "OS_Rng: " + operation + " operation failed with error " + -#ifdef CRYPTOPP_WIN32_AVAILABLE - "0x" + IntToString(GetLastError(), 16) -#else - IntToString(errno) -#endif - ) -{ -} -#endif - -#ifdef NONBLOCKING_RNG_AVAILABLE - -#ifdef CRYPTOPP_WIN32_AVAILABLE - -MicrosoftCryptoProvider::MicrosoftCryptoProvider() -{ - if(!CryptAcquireContext(&m_hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) - throw OS_RNG_Err("CryptAcquireContext"); -} - -MicrosoftCryptoProvider::~MicrosoftCryptoProvider() -{ - CryptReleaseContext(m_hProvider, 0); -} - -#endif - -NonblockingRng::NonblockingRng() -{ -#ifndef CRYPTOPP_WIN32_AVAILABLE - m_fd = open("/dev/urandom",O_RDONLY); - if (m_fd == -1) - throw OS_RNG_Err("open /dev/urandom"); -#endif -} - -NonblockingRng::~NonblockingRng() -{ -#ifndef CRYPTOPP_WIN32_AVAILABLE - close(m_fd); -#endif -} - -void NonblockingRng::GenerateBlock(byte *output, size_t size) -{ -#ifdef CRYPTOPP_WIN32_AVAILABLE -# ifdef WORKAROUND_MS_BUG_Q258000 - const MicrosoftCryptoProvider &m_Provider = Singleton().Ref(); -# endif - if (!CryptGenRandom(m_Provider.GetProviderHandle(), (DWORD)size, output)) - throw OS_RNG_Err("CryptGenRandom"); -#else - if (read(m_fd, output, size) != size) - throw OS_RNG_Err("read /dev/urandom"); -#endif -} - -#endif - -// ************************************************************* - -#ifdef BLOCKING_RNG_AVAILABLE - -#ifndef CRYPTOPP_BLOCKING_RNG_FILENAME -#ifdef __OpenBSD__ -#define CRYPTOPP_BLOCKING_RNG_FILENAME "/dev/srandom" -#else -#define CRYPTOPP_BLOCKING_RNG_FILENAME "/dev/random" -#endif -#endif - -BlockingRng::BlockingRng() -{ - m_fd = open(CRYPTOPP_BLOCKING_RNG_FILENAME,O_RDONLY); - if (m_fd == -1) - throw OS_RNG_Err("open " CRYPTOPP_BLOCKING_RNG_FILENAME); -} - -BlockingRng::~BlockingRng() -{ - close(m_fd); -} - -void BlockingRng::GenerateBlock(byte *output, size_t size) -{ - while (size) - { - // on some systems /dev/random will block until all bytes - // are available, on others it will returns immediately - ssize_t len = read(m_fd, output, size); - if (len < 0) - throw OS_RNG_Err("read " CRYPTOPP_BLOCKING_RNG_FILENAME); - size -= len; - output += len; - if (size) - sleep(1); - } -} - -#endif - -// ************************************************************* - -void OS_GenerateRandomBlock(bool blocking, byte *output, size_t size) -{ -#ifdef NONBLOCKING_RNG_AVAILABLE - if (blocking) -#endif - { -#ifdef BLOCKING_RNG_AVAILABLE - BlockingRng rng; - rng.GenerateBlock(output, size); -#endif - } - -#ifdef BLOCKING_RNG_AVAILABLE - if (!blocking) -#endif - { -#ifdef NONBLOCKING_RNG_AVAILABLE - NonblockingRng rng; - rng.GenerateBlock(output, size); -#endif - } -} - -void AutoSeededRandomPool::Reseed(bool blocking, unsigned int seedSize) -{ - SecByteBlock seed(seedSize); - OS_GenerateRandomBlock(blocking, seed, seedSize); - IncorporateEntropy(seed, seedSize); -} - -NAMESPACE_END - -#endif - -#endif diff --git a/embeddedcryptopp/osrng.h b/embeddedcryptopp/osrng.h deleted file mode 100644 index eb4e6e2..0000000 --- a/embeddedcryptopp/osrng.h +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef CRYPTOPP_OSRNG_H -#define CRYPTOPP_OSRNG_H - -#include "config.h" - -#ifdef OS_RNG_AVAILABLE - -#include "randpool.h" -#include "rng.h" -#include "aes.h" -#include "sha.h" -#include "fips140.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! Exception class for Operating-System Random Number Generator. -class CRYPTOPP_DLL OS_RNG_Err : public Exception -{ -public: - OS_RNG_Err(const std::string &operation); -}; - -#ifdef NONBLOCKING_RNG_AVAILABLE - -#ifdef CRYPTOPP_WIN32_AVAILABLE -class CRYPTOPP_DLL MicrosoftCryptoProvider -{ -public: - MicrosoftCryptoProvider(); - ~MicrosoftCryptoProvider(); -#if defined(_WIN64) - typedef unsigned __int64 ProviderHandle; // type HCRYPTPROV, avoid #include -#else - typedef unsigned long ProviderHandle; -#endif - ProviderHandle GetProviderHandle() const {return m_hProvider;} -private: - ProviderHandle m_hProvider; -}; - -#pragma comment(lib, "advapi32.lib") -#endif - -//! encapsulate CryptoAPI's CryptGenRandom or /dev/urandom -class CRYPTOPP_DLL NonblockingRng : public RandomNumberGenerator -{ -public: - NonblockingRng(); - ~NonblockingRng(); - void GenerateBlock(byte *output, size_t size); - -protected: -#ifdef CRYPTOPP_WIN32_AVAILABLE -# ifndef WORKAROUND_MS_BUG_Q258000 - MicrosoftCryptoProvider m_Provider; -# endif -#else - int m_fd; -#endif -}; - -#endif - -#ifdef BLOCKING_RNG_AVAILABLE - -//! encapsulate /dev/random, or /dev/srandom on OpenBSD -class CRYPTOPP_DLL BlockingRng : public RandomNumberGenerator -{ -public: - BlockingRng(); - ~BlockingRng(); - void GenerateBlock(byte *output, size_t size); - -protected: - int m_fd; -}; - -#endif - -CRYPTOPP_DLL void CRYPTOPP_API OS_GenerateRandomBlock(bool blocking, byte *output, size_t size); - -//! Automaticly Seeded Randomness Pool -/*! This class seeds itself using an operating system provided RNG. */ -class CRYPTOPP_DLL AutoSeededRandomPool : public RandomPool -{ -public: - //! use blocking to choose seeding with BlockingRng or NonblockingRng. the parameter is ignored if only one of these is available - explicit AutoSeededRandomPool(bool blocking = false, unsigned int seedSize = 32) - {Reseed(blocking, seedSize);} - void Reseed(bool blocking = false, unsigned int seedSize = 32); -}; - -//! RNG from ANSI X9.17 Appendix C, seeded using an OS provided RNG -template -class AutoSeededX917RNG : public RandomNumberGenerator, public NotCopyable -{ -public: - //! use blocking to choose seeding with BlockingRng or NonblockingRng. the parameter is ignored if only one of these is available - explicit AutoSeededX917RNG(bool blocking = false) - {Reseed(blocking);} - void Reseed(bool blocking = false, const byte *additionalEntropy = NULL, size_t length = 0); - // exposed for testing - void Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector); - - bool CanIncorporateEntropy() const {return true;} - void IncorporateEntropy(const byte *input, size_t length) {Reseed(false, input, length);} - void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length) {m_rng->GenerateIntoBufferedTransformation(target, channel, length);} - -private: - member_ptr m_rng; -}; - -template -void AutoSeededX917RNG::Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector) -{ - m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, keylength), seed, timeVector)); -} - -template -void AutoSeededX917RNG::Reseed(bool blocking, const byte *input, size_t length) -{ - SecByteBlock seed(BLOCK_CIPHER::BLOCKSIZE + BLOCK_CIPHER::DEFAULT_KEYLENGTH); - const byte *key; - do - { - OS_GenerateRandomBlock(blocking, seed, seed.size()); - if (length > 0) - { - SHA256 hash; - hash.Update(seed, seed.size()); - hash.Update(input, length); - hash.TruncatedFinal(seed, UnsignedMin(hash.DigestSize(), seed.size())); - } - key = seed + BLOCK_CIPHER::BLOCKSIZE; - } // check that seed and key don't have same value - while (memcmp(key, seed, STDMIN((unsigned int)BLOCK_CIPHER::BLOCKSIZE, (unsigned int)BLOCK_CIPHER::DEFAULT_KEYLENGTH)) == 0); - - Reseed(key, BLOCK_CIPHER::DEFAULT_KEYLENGTH, seed, NULL); -} - -CRYPTOPP_DLL_TEMPLATE_CLASS AutoSeededX917RNG; - -#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 -typedef AutoSeededX917RNG DefaultAutoSeededRNG; -#else -typedef AutoSeededRandomPool DefaultAutoSeededRNG; -#endif - -NAMESPACE_END - -#endif - -#endif diff --git a/embeddedcryptopp/pch.h b/embeddedcryptopp/pch.h deleted file mode 100644 index 418c390..0000000 --- a/embeddedcryptopp/pch.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef CRYPTOPP_PCH_H -#define CRYPTOPP_PCH_H - -#ifdef CRYPTOPP_GENERATE_X64_MASM - - #include "cpu.h" - -#else - - #include "config.h" - - #ifdef USE_PRECOMPILED_HEADERS - #include "simple.h" - #include "secblock.h" - #include "misc.h" - #include "smartptr.h" - #endif - -#endif - -#endif diff --git a/embeddedcryptopp/pkcspad.cpp b/embeddedcryptopp/pkcspad.cpp deleted file mode 100644 index e1f1d1e..0000000 --- a/embeddedcryptopp/pkcspad.cpp +++ /dev/null @@ -1,124 +0,0 @@ -// pkcspad.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_PKCSPAD_CPP // SunCC workaround: compiler could cause this file to be included twice -#define CRYPTOPP_PKCSPAD_CPP - -#include "pkcspad.h" -#include - -NAMESPACE_BEGIN(CryptoPP) - -// more in dll.cpp -template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x02,0x05,0x00,0x04,0x10}; -template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); - -template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x04,0x10}; -template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); - -template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x24,0x03,0x02,0x01,0x05,0x00,0x04,0x14}; -template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); - -template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x29,0x30,0x0D,0x06,0x09,0x2B,0x06,0x01,0x04,0x01,0xDA,0x47,0x0C,0x02,0x05,0x00,0x04,0x18}; -template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); - -size_t PKCS_EncryptionPaddingScheme::MaxUnpaddedLength(size_t paddedLength) const -{ - return SaturatingSubtract(paddedLength/8, 10U); -} - -void PKCS_EncryptionPaddingScheme::Pad(RandomNumberGenerator &rng, const byte *input, size_t inputLen, byte *pkcsBlock, size_t pkcsBlockLen, const NameValuePairs ¶meters) const -{ - assert (inputLen <= MaxUnpaddedLength(pkcsBlockLen)); // this should be checked by caller - - // convert from bit length to byte length - if (pkcsBlockLen % 8 != 0) - { - pkcsBlock[0] = 0; - pkcsBlock++; - } - pkcsBlockLen /= 8; - - pkcsBlock[0] = 2; // block type 2 - - // pad with non-zero random bytes - for (unsigned i = 1; i < pkcsBlockLen-inputLen-1; i++) - pkcsBlock[i] = (byte)rng.GenerateWord32(1, 0xff); - - pkcsBlock[pkcsBlockLen-inputLen-1] = 0; // separator - memcpy(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen); -} - -DecodingResult PKCS_EncryptionPaddingScheme::Unpad(const byte *pkcsBlock, size_t pkcsBlockLen, byte *output, const NameValuePairs ¶meters) const -{ - bool invalid = false; - size_t maxOutputLen = MaxUnpaddedLength(pkcsBlockLen); - - // convert from bit length to byte length - if (pkcsBlockLen % 8 != 0) - { - invalid = (pkcsBlock[0] != 0) || invalid; - pkcsBlock++; - } - pkcsBlockLen /= 8; - - // Require block type 2. - invalid = (pkcsBlock[0] != 2) || invalid; - - // skip past the padding until we find the separator - size_t i=1; - while (i maxOutputLen) || invalid; - - if (invalid) - return DecodingResult(); - - memcpy (output, pkcsBlock+i, outputLen); - return DecodingResult(outputLen); -} - -// ******************************************************** - -#ifndef CRYPTOPP_IMPORTS - -void PKCS1v15_SignatureMessageEncodingMethod::ComputeMessageRepresentative(RandomNumberGenerator &rng, - const byte *recoverableMessage, size_t recoverableMessageLength, - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, size_t representativeBitLength) const -{ - assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize())); - - size_t pkcsBlockLen = representativeBitLength; - // convert from bit length to byte length - if (pkcsBlockLen % 8 != 0) - { - representative[0] = 0; - representative++; - } - pkcsBlockLen /= 8; - - representative[0] = 1; // block type 1 - - unsigned int digestSize = hash.DigestSize(); - byte *pPadding = representative + 1; - byte *pDigest = representative + pkcsBlockLen - digestSize; - byte *pHashId = pDigest - hashIdentifier.second; - byte *pSeparator = pHashId - 1; - - // pad with 0xff - memset(pPadding, 0xff, pSeparator-pPadding); - *pSeparator = 0; - memcpy(pHashId, hashIdentifier.first, hashIdentifier.second); - hash.Final(pDigest); -} - -#endif - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/pkcspad.h b/embeddedcryptopp/pkcspad.h deleted file mode 100644 index 6371c76..0000000 --- a/embeddedcryptopp/pkcspad.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef CRYPTOPP_PKCSPAD_H -#define CRYPTOPP_PKCSPAD_H - -#include "cryptlib.h" -#include "pubkey.h" - -#ifdef CRYPTOPP_IS_DLL -#include "sha.h" -#endif - -NAMESPACE_BEGIN(CryptoPP) - -//! EME-PKCS1-v1_5 -class PKCS_EncryptionPaddingScheme : public PK_EncryptionMessageEncodingMethod -{ -public: - static const char * StaticAlgorithmName() {return "EME-PKCS1-v1_5";} - - size_t MaxUnpaddedLength(size_t paddedLength) const; - void Pad(RandomNumberGenerator &rng, const byte *raw, size_t inputLength, byte *padded, size_t paddedLength, const NameValuePairs ¶meters) const; - DecodingResult Unpad(const byte *padded, size_t paddedLength, byte *raw, const NameValuePairs ¶meters) const; -}; - -template class PKCS_DigestDecoration -{ -public: - static const byte decoration[]; - static const unsigned int length; -}; - -// PKCS_DigestDecoration can be instantiated with the following -// classes as specified in PKCS#1 v2.0 and P1363a -class SHA1; -class RIPEMD160; -class Tiger; -class SHA224; -class SHA256; -class SHA384; -class SHA512; -namespace Weak1 { -class MD2; -class MD5; -} -// end of list - -#ifdef CRYPTOPP_IS_DLL -CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; -CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; -CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; -CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; -CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; -#endif - -//! EMSA-PKCS1-v1_5 -class CRYPTOPP_DLL PKCS1v15_SignatureMessageEncodingMethod : public PK_DeterministicSignatureMessageEncodingMethod -{ -public: - static const char * CRYPTOPP_API StaticAlgorithmName() {return "EMSA-PKCS1-v1_5";} - - size_t MinRepresentativeBitLength(size_t hashIdentifierSize, size_t digestSize) const - {return 8 * (digestSize + hashIdentifierSize + 10);} - - void ComputeMessageRepresentative(RandomNumberGenerator &rng, - const byte *recoverableMessage, size_t recoverableMessageLength, - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, size_t representativeBitLength) const; - - struct HashIdentifierLookup - { - template struct HashIdentifierLookup2 - { - static HashIdentifier Lookup() - { - return HashIdentifier(PKCS_DigestDecoration::decoration, PKCS_DigestDecoration::length); - } - }; - }; -}; - -//! PKCS #1 version 1.5, for use with RSAES and RSASS -/*! Only the following hash functions are supported by this signature standard: - \dontinclude pkcspad.h - \skip can be instantiated - \until end of list -*/ -struct PKCS1v15 : public SignatureStandard, public EncryptionStandard -{ - typedef PKCS_EncryptionPaddingScheme EncryptionMessageEncodingMethod; - typedef PKCS1v15_SignatureMessageEncodingMethod SignatureMessageEncodingMethod; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/pssr.cpp b/embeddedcryptopp/pssr.cpp deleted file mode 100644 index ccbe4ee..0000000 --- a/embeddedcryptopp/pssr.cpp +++ /dev/null @@ -1,145 +0,0 @@ -// pssr.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" -#include "pssr.h" -#include - -NAMESPACE_BEGIN(CryptoPP) - -// more in dll.cpp -template<> const byte EMSA2HashId::id = 0x31; -template<> const byte EMSA2HashId::id = 0x32; -template<> const byte EMSA2HashId::id = 0x37; - -#ifndef CRYPTOPP_IMPORTS - -size_t PSSR_MEM_Base::MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const -{ - size_t saltLen = SaltLen(digestLength); - size_t minPadLen = MinPadLen(digestLength); - return 9 + 8*(minPadLen + saltLen + digestLength + hashIdentifierLength); -} - -size_t PSSR_MEM_Base::MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const -{ - if (AllowRecovery()) - return SaturatingSubtract(representativeBitLength, MinRepresentativeBitLength(hashIdentifierLength, digestLength)) / 8; - return 0; -} - -bool PSSR_MEM_Base::IsProbabilistic() const -{ - return SaltLen(1) > 0; -} - -bool PSSR_MEM_Base::AllowNonrecoverablePart() const -{ - return true; -} - -bool PSSR_MEM_Base::RecoverablePartFirst() const -{ - return false; -} - -void PSSR_MEM_Base::ComputeMessageRepresentative(RandomNumberGenerator &rng, - const byte *recoverableMessage, size_t recoverableMessageLength, - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, size_t representativeBitLength) const -{ - assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize())); - - const size_t u = hashIdentifier.second + 1; - const size_t representativeByteLength = BitsToBytes(representativeBitLength); - const size_t digestSize = hash.DigestSize(); - const size_t saltSize = SaltLen(digestSize); - byte *const h = representative + representativeByteLength - u - digestSize; - - SecByteBlock digest(digestSize), salt(saltSize); - hash.Final(digest); - rng.GenerateBlock(salt, saltSize); - - // compute H = hash of M' - byte c[8]; - PutWord(false, BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength)); - PutWord(false, BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3)); - hash.Update(c, 8); - hash.Update(recoverableMessage, recoverableMessageLength); - hash.Update(digest, digestSize); - hash.Update(salt, saltSize); - hash.Final(h); - - // compute representative - GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize, false); - byte *xorStart = representative + representativeByteLength - u - digestSize - salt.size() - recoverableMessageLength - 1; - xorStart[0] ^= 1; - xorbuf(xorStart + 1, recoverableMessage, recoverableMessageLength); - xorbuf(xorStart + 1 + recoverableMessageLength, salt, salt.size()); - memcpy(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second); - representative[representativeByteLength - 1] = hashIdentifier.second ? 0xcc : 0xbc; - if (representativeBitLength % 8 != 0) - representative[0] = (byte)Crop(representative[0], representativeBitLength % 8); -} - -DecodingResult PSSR_MEM_Base::RecoverMessageFromRepresentative( - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, size_t representativeBitLength, - byte *recoverableMessage) const -{ - assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize())); - - const size_t u = hashIdentifier.second + 1; - const size_t representativeByteLength = BitsToBytes(representativeBitLength); - const size_t digestSize = hash.DigestSize(); - const size_t saltSize = SaltLen(digestSize); - const byte *const h = representative + representativeByteLength - u - digestSize; - - SecByteBlock digest(digestSize); - hash.Final(digest); - - DecodingResult result(0); - bool &valid = result.isValidCoding; - size_t &recoverableMessageLength = result.messageLength; - - valid = (representative[representativeByteLength - 1] == (hashIdentifier.second ? 0xcc : 0xbc)) && valid; - valid = VerifyBufsEqual(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second) && valid; - - GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize); - if (representativeBitLength % 8 != 0) - representative[0] = (byte)Crop(representative[0], representativeBitLength % 8); - - // extract salt and recoverableMessage from DB = 00 ... || 01 || M || salt - byte *salt = representative + representativeByteLength - u - digestSize - saltSize; - byte *M = std::find_if(representative, salt-1, std::bind2nd(std::not_equal_to(), 0)); - recoverableMessageLength = salt-M-1; - if (*M == 0x01 - && (size_t)(M - representative - (representativeBitLength % 8 != 0)) >= MinPadLen(digestSize) - && recoverableMessageLength <= MaxRecoverableLength(representativeBitLength, hashIdentifier.second, digestSize)) - { - memcpy(recoverableMessage, M+1, recoverableMessageLength); - } - else - { - recoverableMessageLength = 0; - valid = false; - } - - // verify H = hash of M' - byte c[8]; - PutWord(false, BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength)); - PutWord(false, BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3)); - hash.Update(c, 8); - hash.Update(recoverableMessage, recoverableMessageLength); - hash.Update(digest, digestSize); - hash.Update(salt, saltSize); - valid = hash.Verify(h) && valid; - - if (!AllowRecovery() && valid && recoverableMessageLength != 0) - {throw NotImplemented("PSSR_MEM: message recovery disabled");} - - return result; -} - -#endif - -NAMESPACE_END diff --git a/embeddedcryptopp/pssr.h b/embeddedcryptopp/pssr.h deleted file mode 100644 index 6ec6936..0000000 --- a/embeddedcryptopp/pssr.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef CRYPTOPP_PSSR_H -#define CRYPTOPP_PSSR_H - -#include "pubkey.h" -#include "emsa2.h" - -#ifdef CRYPTOPP_IS_DLL -#include "sha.h" -#endif - -NAMESPACE_BEGIN(CryptoPP) - -class CRYPTOPP_DLL PSSR_MEM_Base : public PK_RecoverableSignatureMessageEncodingMethod -{ - virtual bool AllowRecovery() const =0; - virtual size_t SaltLen(size_t hashLen) const =0; - virtual size_t MinPadLen(size_t hashLen) const =0; - virtual const MaskGeneratingFunction & GetMGF() const =0; - -public: - size_t MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const; - size_t MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const; - bool IsProbabilistic() const; - bool AllowNonrecoverablePart() const; - bool RecoverablePartFirst() const; - void ComputeMessageRepresentative(RandomNumberGenerator &rng, - const byte *recoverableMessage, size_t recoverableMessageLength, - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, size_t representativeBitLength) const; - DecodingResult RecoverMessageFromRepresentative( - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, size_t representativeBitLength, - byte *recoverableMessage) const; -}; - -template class PSSR_MEM_BaseWithHashId; -template<> class PSSR_MEM_BaseWithHashId : public EMSA2HashIdLookup {}; -template<> class PSSR_MEM_BaseWithHashId : public PSSR_MEM_Base {}; - -template -class PSSR_MEM : public PSSR_MEM_BaseWithHashId -{ - virtual bool AllowRecovery() const {return ALLOW_RECOVERY;} - virtual size_t SaltLen(size_t hashLen) const {return SALT_LEN < 0 ? hashLen : SALT_LEN;} - virtual size_t MinPadLen(size_t hashLen) const {return MIN_PAD_LEN < 0 ? hashLen : MIN_PAD_LEN;} - virtual const MaskGeneratingFunction & GetMGF() const {static MGF mgf; return mgf;} - -public: - static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(ALLOW_RECOVERY ? "PSSR-" : "PSS-") + MGF::StaticAlgorithmName();} -}; - -//! PSSR-MGF1 -struct PSSR : public SignatureStandard -{ - typedef PSSR_MEM SignatureMessageEncodingMethod; -}; - -//! PSS-MGF1 -struct PSS : public SignatureStandard -{ - typedef PSSR_MEM SignatureMessageEncodingMethod; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/pubkey.cpp b/embeddedcryptopp/pubkey.cpp deleted file mode 100644 index 7336e8b..0000000 --- a/embeddedcryptopp/pubkey.cpp +++ /dev/null @@ -1,162 +0,0 @@ -// pubkey.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "pubkey.h" - -NAMESPACE_BEGIN(CryptoPP) - -void P1363_MGF1KDF2_Common(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, const byte *derivationParams, size_t derivationParamsLength, bool mask, unsigned int counterStart) -{ - ArraySink *sink; - HashFilter filter(hash, sink = mask ? new ArrayXorSink(output, outputLength) : new ArraySink(output, outputLength)); - word32 counter = counterStart; - while (sink->AvailableSize() > 0) - { - filter.Put(input, inputLength); - filter.PutWord32(counter++); - filter.Put(derivationParams, derivationParamsLength); - filter.MessageEnd(); - } -} - -bool PK_DeterministicSignatureMessageEncodingMethod::VerifyMessageRepresentative( - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, size_t representativeBitLength) const -{ - SecByteBlock computedRepresentative(BitsToBytes(representativeBitLength)); - ComputeMessageRepresentative(NullRNG(), NULL, 0, hash, hashIdentifier, messageEmpty, computedRepresentative, representativeBitLength); - return VerifyBufsEqual(representative, computedRepresentative, computedRepresentative.size()); -} - -bool PK_RecoverableSignatureMessageEncodingMethod::VerifyMessageRepresentative( - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, size_t representativeBitLength) const -{ - SecByteBlock recoveredMessage(MaxRecoverableLength(representativeBitLength, hashIdentifier.second, hash.DigestSize())); - DecodingResult result = RecoverMessageFromRepresentative( - hash, hashIdentifier, messageEmpty, representative, representativeBitLength, recoveredMessage); - return result.isValidCoding && result.messageLength == 0; -} - -void TF_SignerBase::InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const -{ - PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); - HashIdentifier id = GetHashIdentifier(); - const MessageEncodingInterface &encoding = GetMessageEncodingInterface(); - - if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize())) - throw PK_SignatureScheme::KeyTooShort(); - - size_t maxRecoverableLength = encoding.MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, ma.AccessHash().DigestSize()); - - if (maxRecoverableLength == 0) - {throw NotImplemented("TF_SignerBase: this algorithm does not support messsage recovery or the key is too short");} - if (recoverableMessageLength > maxRecoverableLength) - throw InvalidArgument("TF_SignerBase: the recoverable message part is too long for the given key and algorithm"); - - ma.m_recoverableMessage.Assign(recoverableMessage, recoverableMessageLength); - encoding.ProcessRecoverableMessage( - ma.AccessHash(), - recoverableMessage, recoverableMessageLength, - NULL, 0, ma.m_semisignature); -} - -size_t TF_SignerBase::SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const -{ - PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); - HashIdentifier id = GetHashIdentifier(); - const MessageEncodingInterface &encoding = GetMessageEncodingInterface(); - - if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize())) - throw PK_SignatureScheme::KeyTooShort(); - - SecByteBlock representative(MessageRepresentativeLength()); - encoding.ComputeMessageRepresentative(rng, - ma.m_recoverableMessage, ma.m_recoverableMessage.size(), - ma.AccessHash(), id, ma.m_empty, - representative, MessageRepresentativeBitLength()); - ma.m_empty = true; - - Integer r(representative, representative.size()); - size_t signatureLength = SignatureLength(); - GetTrapdoorFunctionInterface().CalculateRandomizedInverse(rng, r).Encode(signature, signatureLength); - return signatureLength; -} - -void TF_VerifierBase::InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const -{ - PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); - HashIdentifier id = GetHashIdentifier(); - const MessageEncodingInterface &encoding = GetMessageEncodingInterface(); - - if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize())) - throw PK_SignatureScheme::KeyTooShort(); - - ma.m_representative.New(MessageRepresentativeLength()); - Integer x = GetTrapdoorFunctionInterface().ApplyFunction(Integer(signature, signatureLength)); - if (x.BitCount() > MessageRepresentativeBitLength()) - x = Integer::Zero(); // don't return false here to prevent timing attack - x.Encode(ma.m_representative, ma.m_representative.size()); -} - -bool TF_VerifierBase::VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const -{ - PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); - HashIdentifier id = GetHashIdentifier(); - const MessageEncodingInterface &encoding = GetMessageEncodingInterface(); - - if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize())) - throw PK_SignatureScheme::KeyTooShort(); - - bool result = encoding.VerifyMessageRepresentative( - ma.AccessHash(), id, ma.m_empty, ma.m_representative, MessageRepresentativeBitLength()); - ma.m_empty = true; - return result; -} - -DecodingResult TF_VerifierBase::RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const -{ - PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); - HashIdentifier id = GetHashIdentifier(); - const MessageEncodingInterface &encoding = GetMessageEncodingInterface(); - - if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize())) - throw PK_SignatureScheme::KeyTooShort(); - - DecodingResult result = encoding.RecoverMessageFromRepresentative( - ma.AccessHash(), id, ma.m_empty, ma.m_representative, MessageRepresentativeBitLength(), recoveredMessage); - ma.m_empty = true; - return result; -} - -DecodingResult TF_DecryptorBase::Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters) const -{ - SecByteBlock paddedBlock(PaddedBlockByteLength()); - Integer x = GetTrapdoorFunctionInterface().CalculateInverse(rng, Integer(ciphertext, FixedCiphertextLength())); - if (x.ByteCount() > paddedBlock.size()) - x = Integer::Zero(); // don't return false here to prevent timing attack - x.Encode(paddedBlock, paddedBlock.size()); - return GetMessageEncodingInterface().Unpad(paddedBlock, PaddedBlockBitLength(), plaintext, parameters); -} - -void TF_EncryptorBase::Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters) const -{ - if (plaintextLength > FixedMaxPlaintextLength()) - { - if (FixedMaxPlaintextLength() < 1) - throw InvalidArgument(AlgorithmName() + ": this key is too short to encrypt any messages"); - else - throw InvalidArgument(AlgorithmName() + ": message length of " + IntToString(plaintextLength) + " exceeds the maximum of " + IntToString(FixedMaxPlaintextLength()) + " for this public key"); - } - - SecByteBlock paddedBlock(PaddedBlockByteLength()); - GetMessageEncodingInterface().Pad(rng, plaintext, plaintextLength, paddedBlock, PaddedBlockBitLength(), parameters); - GetTrapdoorFunctionInterface().ApplyRandomizedFunction(rng, Integer(paddedBlock, paddedBlock.size())).Encode(ciphertext, FixedCiphertextLength()); -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/pubkey.h b/embeddedcryptopp/pubkey.h deleted file mode 100644 index bdf0035..0000000 --- a/embeddedcryptopp/pubkey.h +++ /dev/null @@ -1,1678 +0,0 @@ -// pubkey.h - written and placed in the public domain by Wei Dai - -#ifndef CRYPTOPP_PUBKEY_H -#define CRYPTOPP_PUBKEY_H - -/** \file - - This file contains helper classes/functions for implementing public key algorithms. - - The class hierachies in this .h file tend to look like this: -

-                  x1
-                 / \
-                y1  z1
-                 |  |
-            x2  x2
-                 |  |
-                y2  z2
-                 |  |
-            x3  x3
-                 |  |
-                y3  z3
-
- - x1, y1, z1 are abstract interface classes defined in cryptlib.h - - x2, y2, z2 are implementations of the interfaces using "abstract policies", which - are pure virtual functions that should return interfaces to interchangeable algorithms. - These classes have "Base" suffixes. - - x3, y3, z3 hold actual algorithms and implement those virtual functions. - These classes have "Impl" suffixes. - - The "TF_" prefix means an implementation using trapdoor functions on integers. - The "DL_" prefix means an implementation using group operations (in groups where discrete log is hard). -*/ - -#include "modarith.h" -#include "filters.h" -#include "eprecomp.h" -#include "fips140.h" -#include "argnames.h" -#include - -// VC60 workaround: this macro is defined in shlobj.h and conflicts with a template parameter used in this file -#undef INTERFACE - -NAMESPACE_BEGIN(CryptoPP) - -//! _ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionBounds -{ -public: - virtual ~TrapdoorFunctionBounds() {} - - virtual Integer PreimageBound() const =0; - virtual Integer ImageBound() const =0; - virtual Integer MaxPreimage() const {return --PreimageBound();} - virtual Integer MaxImage() const {return --ImageBound();} -}; - -//! _ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunction : public TrapdoorFunctionBounds -{ -public: - virtual Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const =0; - virtual bool IsRandomized() const {return true;} -}; - -//! _ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunction : public RandomizedTrapdoorFunction -{ -public: - Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const - {return ApplyFunction(x);} - bool IsRandomized() const {return false;} - - virtual Integer ApplyFunction(const Integer &x) const =0; -}; - -//! _ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunctionInverse -{ -public: - virtual ~RandomizedTrapdoorFunctionInverse() {} - - virtual Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const =0; - virtual bool IsRandomized() const {return true;} -}; - -//! _ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionInverse : public RandomizedTrapdoorFunctionInverse -{ -public: - virtual ~TrapdoorFunctionInverse() {} - - Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const - {return CalculateInverse(rng, x);} - bool IsRandomized() const {return false;} - - virtual Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const =0; -}; - -// ******************************************************** - -//! message encoding method for public key encryption -class CRYPTOPP_NO_VTABLE PK_EncryptionMessageEncodingMethod -{ -public: - virtual ~PK_EncryptionMessageEncodingMethod() {} - - virtual bool ParameterSupported(const char *name) const {return false;} - - //! max size of unpadded message in bytes, given max size of padded message in bits (1 less than size of modulus) - virtual size_t MaxUnpaddedLength(size_t paddedLength) const =0; - - virtual void Pad(RandomNumberGenerator &rng, const byte *raw, size_t inputLength, byte *padded, size_t paddedBitLength, const NameValuePairs ¶meters) const =0; - - virtual DecodingResult Unpad(const byte *padded, size_t paddedBitLength, byte *raw, const NameValuePairs ¶meters) const =0; -}; - -// ******************************************************** - -//! _ -template -class CRYPTOPP_NO_VTABLE TF_Base -{ -protected: - virtual const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const =0; - - typedef TFI TrapdoorFunctionInterface; - virtual const TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const =0; - - typedef MEI MessageEncodingInterface; - virtual const MessageEncodingInterface & GetMessageEncodingInterface() const =0; -}; - -// ******************************************************** - -//! _ -template -class CRYPTOPP_NO_VTABLE PK_FixedLengthCryptoSystemImpl : public BASE -{ -public: - size_t MaxPlaintextLength(size_t ciphertextLength) const - {return ciphertextLength == FixedCiphertextLength() ? FixedMaxPlaintextLength() : 0;} - size_t CiphertextLength(size_t plaintextLength) const - {return plaintextLength <= FixedMaxPlaintextLength() ? FixedCiphertextLength() : 0;} - - virtual size_t FixedMaxPlaintextLength() const =0; - virtual size_t FixedCiphertextLength() const =0; -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE TF_CryptoSystemBase : public PK_FixedLengthCryptoSystemImpl, protected BASE -{ -public: - bool ParameterSupported(const char *name) const {return this->GetMessageEncodingInterface().ParameterSupported(name);} - size_t FixedMaxPlaintextLength() const {return this->GetMessageEncodingInterface().MaxUnpaddedLength(PaddedBlockBitLength());} - size_t FixedCiphertextLength() const {return this->GetTrapdoorFunctionBounds().MaxImage().ByteCount();} - -protected: - size_t PaddedBlockByteLength() const {return BitsToBytes(PaddedBlockBitLength());} - size_t PaddedBlockBitLength() const {return this->GetTrapdoorFunctionBounds().PreimageBound().BitCount()-1;} -}; - -//! _ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_DecryptorBase : public TF_CryptoSystemBase > -{ -public: - DecodingResult Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters = g_nullNameValuePairs) const; -}; - -//! _ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_EncryptorBase : public TF_CryptoSystemBase > -{ -public: - void Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters = g_nullNameValuePairs) const; -}; - -// ******************************************************** - -typedef std::pair HashIdentifier; - -//! interface for message encoding method for public key signature schemes -class CRYPTOPP_NO_VTABLE PK_SignatureMessageEncodingMethod -{ -public: - virtual ~PK_SignatureMessageEncodingMethod() {} - - virtual size_t MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const - {return 0;} - virtual size_t MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const - {return 0;} - - bool IsProbabilistic() const - {return true;} - bool AllowNonrecoverablePart() const - {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} - virtual bool RecoverablePartFirst() const - {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} - - // for verification, DL - virtual void ProcessSemisignature(HashTransformation &hash, const byte *semisignature, size_t semisignatureLength) const {} - - // for signature - virtual void ProcessRecoverableMessage(HashTransformation &hash, - const byte *recoverableMessage, size_t recoverableMessageLength, - const byte *presignature, size_t presignatureLength, - SecByteBlock &semisignature) const - { - if (RecoverablePartFirst()) - assert(!"ProcessRecoverableMessage() not implemented"); - } - - virtual void ComputeMessageRepresentative(RandomNumberGenerator &rng, - const byte *recoverableMessage, size_t recoverableMessageLength, - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, size_t representativeBitLength) const =0; - - virtual bool VerifyMessageRepresentative( - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, size_t representativeBitLength) const =0; - - virtual DecodingResult RecoverMessageFromRepresentative( // for TF - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, size_t representativeBitLength, - byte *recoveredMessage) const - {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} - - virtual DecodingResult RecoverMessageFromSemisignature( // for DL - HashTransformation &hash, HashIdentifier hashIdentifier, - const byte *presignature, size_t presignatureLength, - const byte *semisignature, size_t semisignatureLength, - byte *recoveredMessage) const - {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} - - // VC60 workaround - struct HashIdentifierLookup - { - template struct HashIdentifierLookup2 - { - static HashIdentifier CRYPTOPP_API Lookup() - { - return HashIdentifier(NULL, 0); - } - }; - }; -}; - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_DeterministicSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod -{ -public: - bool VerifyMessageRepresentative( - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, size_t representativeBitLength) const; -}; - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_RecoverableSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod -{ -public: - bool VerifyMessageRepresentative( - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, size_t representativeBitLength) const; -}; - -class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_DSA : public PK_DeterministicSignatureMessageEncodingMethod -{ -public: - void ComputeMessageRepresentative(RandomNumberGenerator &rng, - const byte *recoverableMessage, size_t recoverableMessageLength, - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, size_t representativeBitLength) const; -}; - -class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_NR : public PK_DeterministicSignatureMessageEncodingMethod -{ -public: - void ComputeMessageRepresentative(RandomNumberGenerator &rng, - const byte *recoverableMessage, size_t recoverableMessageLength, - HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, - byte *representative, size_t representativeBitLength) const; -}; - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_MessageAccumulatorBase : public PK_MessageAccumulator -{ -public: - PK_MessageAccumulatorBase() : m_empty(true) {} - - virtual HashTransformation & AccessHash() =0; - - void Update(const byte *input, size_t length) - { - AccessHash().Update(input, length); - m_empty = m_empty && length == 0; - } - - SecByteBlock m_recoverableMessage, m_representative, m_presignature, m_semisignature; - Integer m_k, m_s; - bool m_empty; -}; - -template -class PK_MessageAccumulatorImpl : public PK_MessageAccumulatorBase, protected ObjectHolder -{ -public: - HashTransformation & AccessHash() {return this->m_object;} -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE TF_SignatureSchemeBase : public INTERFACE, protected BASE -{ -public: - size_t SignatureLength() const - {return this->GetTrapdoorFunctionBounds().MaxPreimage().ByteCount();} - size_t MaxRecoverableLength() const - {return this->GetMessageEncodingInterface().MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, GetDigestSize());} - size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const - {return this->MaxRecoverableLength();} - - bool IsProbabilistic() const - {return this->GetTrapdoorFunctionInterface().IsRandomized() || this->GetMessageEncodingInterface().IsProbabilistic();} - bool AllowNonrecoverablePart() const - {return this->GetMessageEncodingInterface().AllowNonrecoverablePart();} - bool RecoverablePartFirst() const - {return this->GetMessageEncodingInterface().RecoverablePartFirst();} - -protected: - size_t MessageRepresentativeLength() const {return BitsToBytes(MessageRepresentativeBitLength());} - size_t MessageRepresentativeBitLength() const {return this->GetTrapdoorFunctionBounds().ImageBound().BitCount()-1;} - virtual HashIdentifier GetHashIdentifier() const =0; - virtual size_t GetDigestSize() const =0; -}; - -//! _ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_SignerBase : public TF_SignatureSchemeBase > -{ -public: - void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const; - size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart=true) const; -}; - -//! _ -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_VerifierBase : public TF_SignatureSchemeBase > -{ -public: - void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const; - bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const; - DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &recoveryAccumulator) const; -}; - -// ******************************************************** - -//! _ -template -struct TF_CryptoSchemeOptions -{ - typedef T1 AlgorithmInfo; - typedef T2 Keys; - typedef typename Keys::PrivateKey PrivateKey; - typedef typename Keys::PublicKey PublicKey; - typedef T3 MessageEncodingMethod; -}; - -//! _ -template -struct TF_SignatureSchemeOptions : public TF_CryptoSchemeOptions -{ - typedef T4 HashFunction; -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE TF_ObjectImplBase : public AlgorithmImpl -{ -public: - typedef SCHEME_OPTIONS SchemeOptions; - typedef KEY_CLASS KeyClass; - - PublicKey & AccessPublicKey() {return AccessKey();} - const PublicKey & GetPublicKey() const {return GetKey();} - - PrivateKey & AccessPrivateKey() {return AccessKey();} - const PrivateKey & GetPrivateKey() const {return GetKey();} - - virtual const KeyClass & GetKey() const =0; - virtual KeyClass & AccessKey() =0; - - const KeyClass & GetTrapdoorFunction() const {return GetKey();} - - PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const - { - return new PK_MessageAccumulatorImpl; - } - PK_MessageAccumulator * NewVerificationAccumulator() const - { - return new PK_MessageAccumulatorImpl; - } - -protected: - const typename BASE::MessageEncodingInterface & GetMessageEncodingInterface() const - {return Singleton().Ref();} - const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const - {return GetKey();} - const typename BASE::TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const - {return GetKey();} - - // for signature scheme - HashIdentifier GetHashIdentifier() const - { - typedef CPP_TYPENAME SchemeOptions::MessageEncodingMethod::HashIdentifierLookup::template HashIdentifierLookup2 L; - return L::Lookup(); - } - size_t GetDigestSize() const - { - typedef CPP_TYPENAME SchemeOptions::HashFunction H; - return H::DIGESTSIZE; - } -}; - -//! _ -template -class TF_ObjectImplExtRef : public TF_ObjectImplBase -{ -public: - TF_ObjectImplExtRef(const KEY *pKey = NULL) : m_pKey(pKey) {} - void SetKeyPtr(const KEY *pKey) {m_pKey = pKey;} - - const KEY & GetKey() const {return *m_pKey;} - KEY & AccessKey() {throw NotImplemented("TF_ObjectImplExtRef: cannot modify refererenced key");} - -private: - const KEY * m_pKey; -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE TF_ObjectImpl : public TF_ObjectImplBase -{ -public: - typedef KEY_CLASS KeyClass; - - const KeyClass & GetKey() const {return m_trapdoorFunction;} - KeyClass & AccessKey() {return m_trapdoorFunction;} - -private: - KeyClass m_trapdoorFunction; -}; - -//! _ -template -class TF_DecryptorImpl : public TF_ObjectImpl -{ -}; - -//! _ -template -class TF_EncryptorImpl : public TF_ObjectImpl -{ -}; - -//! _ -template -class TF_SignerImpl : public TF_ObjectImpl -{ -}; - -//! _ -template -class TF_VerifierImpl : public TF_ObjectImpl -{ -}; - -// ******************************************************** - -//! _ -class CRYPTOPP_NO_VTABLE MaskGeneratingFunction -{ -public: - virtual ~MaskGeneratingFunction() {} - virtual void GenerateAndMask(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, bool mask = true) const =0; -}; - -CRYPTOPP_DLL void CRYPTOPP_API P1363_MGF1KDF2_Common(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, const byte *derivationParams, size_t derivationParamsLength, bool mask, unsigned int counterStart); - -//! _ -class P1363_MGF1 : public MaskGeneratingFunction -{ -public: - static const char * CRYPTOPP_API StaticAlgorithmName() {return "MGF1";} - void GenerateAndMask(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, bool mask = true) const - { - P1363_MGF1KDF2_Common(hash, output, outputLength, input, inputLength, NULL, 0, mask, 0); - } -}; - -// ******************************************************** - -//! _ -template -class P1363_KDF2 -{ -public: - static void CRYPTOPP_API DeriveKey(byte *output, size_t outputLength, const byte *input, size_t inputLength, const byte *derivationParams, size_t derivationParamsLength) - { - H h; - P1363_MGF1KDF2_Common(h, output, outputLength, input, inputLength, derivationParams, derivationParamsLength, false, 1); - } -}; - -// ******************************************************** - -//! to be thrown by DecodeElement and AgreeWithStaticPrivateKey -class DL_BadElement : public InvalidDataFormat -{ -public: - DL_BadElement() : InvalidDataFormat("CryptoPP: invalid group element") {} -}; - -//! interface for DL group parameters -template -class CRYPTOPP_NO_VTABLE DL_GroupParameters : public CryptoParameters -{ - typedef DL_GroupParameters ThisClass; - -public: - typedef T Element; - - DL_GroupParameters() : m_validationLevel(0) {} - - // CryptoMaterial - bool Validate(RandomNumberGenerator &rng, unsigned int level) const - { - if (!GetBasePrecomputation().IsInitialized()) - return false; - - if (m_validationLevel > level) - return true; - - bool pass = ValidateGroup(rng, level); - pass = pass && ValidateElement(level, GetSubgroupGenerator(), &GetBasePrecomputation()); - - m_validationLevel = pass ? level+1 : 0; - - return pass; - } - - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const - { - return GetValueHelper(this, name, valueType, pValue) - CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupOrder) - CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupGenerator) - ; - } - - bool SupportsPrecomputation() const {return true;} - - void Precompute(unsigned int precomputationStorage=16) - { - AccessBasePrecomputation().Precompute(GetGroupPrecomputation(), GetSubgroupOrder().BitCount(), precomputationStorage); - } - - void LoadPrecomputation(BufferedTransformation &storedPrecomputation) - { - AccessBasePrecomputation().Load(GetGroupPrecomputation(), storedPrecomputation); - m_validationLevel = 0; - } - - void SavePrecomputation(BufferedTransformation &storedPrecomputation) const - { - GetBasePrecomputation().Save(GetGroupPrecomputation(), storedPrecomputation); - } - - // non-inherited - virtual const Element & GetSubgroupGenerator() const {return GetBasePrecomputation().GetBase(GetGroupPrecomputation());} - virtual void SetSubgroupGenerator(const Element &base) {AccessBasePrecomputation().SetBase(GetGroupPrecomputation(), base);} - virtual Element ExponentiateBase(const Integer &exponent) const - { - return GetBasePrecomputation().Exponentiate(GetGroupPrecomputation(), exponent); - } - virtual Element ExponentiateElement(const Element &base, const Integer &exponent) const - { - Element result; - SimultaneousExponentiate(&result, base, &exponent, 1); - return result; - } - - virtual const DL_GroupPrecomputation & GetGroupPrecomputation() const =0; - virtual const DL_FixedBasePrecomputation & GetBasePrecomputation() const =0; - virtual DL_FixedBasePrecomputation & AccessBasePrecomputation() =0; - virtual const Integer & GetSubgroupOrder() const =0; // order of subgroup generated by base element - virtual Integer GetMaxExponent() const =0; - virtual Integer GetGroupOrder() const {return GetSubgroupOrder()*GetCofactor();} // one of these two needs to be overriden - virtual Integer GetCofactor() const {return GetGroupOrder()/GetSubgroupOrder();} - virtual unsigned int GetEncodedElementSize(bool reversible) const =0; - virtual void EncodeElement(bool reversible, const Element &element, byte *encoded) const =0; - virtual Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const =0; - virtual Integer ConvertElementToInteger(const Element &element) const =0; - virtual bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const =0; - virtual bool ValidateElement(unsigned int level, const Element &element, const DL_FixedBasePrecomputation *precomp) const =0; - virtual bool FastSubgroupCheckAvailable() const =0; - virtual bool IsIdentity(const Element &element) const =0; - virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const =0; - -protected: - void ParametersChanged() {m_validationLevel = 0;} - -private: - mutable unsigned int m_validationLevel; -}; - -//! _ -template , class BASE = DL_GroupParameters > -class DL_GroupParametersImpl : public BASE -{ -public: - typedef GROUP_PRECOMP GroupPrecomputation; - typedef typename GROUP_PRECOMP::Element Element; - typedef BASE_PRECOMP BasePrecomputation; - - const DL_GroupPrecomputation & GetGroupPrecomputation() const {return m_groupPrecomputation;} - const DL_FixedBasePrecomputation & GetBasePrecomputation() const {return m_gpc;} - DL_FixedBasePrecomputation & AccessBasePrecomputation() {return m_gpc;} - -protected: - GROUP_PRECOMP m_groupPrecomputation; - BASE_PRECOMP m_gpc; -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE DL_Key -{ -public: - virtual const DL_GroupParameters & GetAbstractGroupParameters() const =0; - virtual DL_GroupParameters & AccessAbstractGroupParameters() =0; -}; - -//! interface for DL public keys -template -class CRYPTOPP_NO_VTABLE DL_PublicKey : public DL_Key -{ - typedef DL_PublicKey ThisClass; - -public: - typedef T Element; - - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const - { - return GetValueHelper(this, name, valueType, pValue, &this->GetAbstractGroupParameters()) - CRYPTOPP_GET_FUNCTION_ENTRY(PublicElement); - } - - void AssignFrom(const NameValuePairs &source); - - // non-inherited - virtual const Element & GetPublicElement() const {return GetPublicPrecomputation().GetBase(this->GetAbstractGroupParameters().GetGroupPrecomputation());} - virtual void SetPublicElement(const Element &y) {AccessPublicPrecomputation().SetBase(this->GetAbstractGroupParameters().GetGroupPrecomputation(), y);} - virtual Element ExponentiatePublicElement(const Integer &exponent) const - { - const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); - return GetPublicPrecomputation().Exponentiate(params.GetGroupPrecomputation(), exponent); - } - virtual Element CascadeExponentiateBaseAndPublicElement(const Integer &baseExp, const Integer &publicExp) const - { - const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); - return params.GetBasePrecomputation().CascadeExponentiate(params.GetGroupPrecomputation(), baseExp, GetPublicPrecomputation(), publicExp); - } - - virtual const DL_FixedBasePrecomputation & GetPublicPrecomputation() const =0; - virtual DL_FixedBasePrecomputation & AccessPublicPrecomputation() =0; -}; - -//! interface for DL private keys -template -class CRYPTOPP_NO_VTABLE DL_PrivateKey : public DL_Key -{ - typedef DL_PrivateKey ThisClass; - -public: - typedef T Element; - - void MakePublicKey(DL_PublicKey &pub) const - { - pub.AccessAbstractGroupParameters().AssignFrom(this->GetAbstractGroupParameters()); - pub.SetPublicElement(this->GetAbstractGroupParameters().ExponentiateBase(GetPrivateExponent())); - } - - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const - { - return GetValueHelper(this, name, valueType, pValue, &this->GetAbstractGroupParameters()) - CRYPTOPP_GET_FUNCTION_ENTRY(PrivateExponent); - } - - void AssignFrom(const NameValuePairs &source) - { - this->AccessAbstractGroupParameters().AssignFrom(source); - AssignFromHelper(this, source) - CRYPTOPP_SET_FUNCTION_ENTRY(PrivateExponent); - } - - virtual const Integer & GetPrivateExponent() const =0; - virtual void SetPrivateExponent(const Integer &x) =0; -}; - -template -void DL_PublicKey::AssignFrom(const NameValuePairs &source) -{ - DL_PrivateKey *pPrivateKey = NULL; - if (source.GetThisPointer(pPrivateKey)) - pPrivateKey->MakePublicKey(*this); - else - { - this->AccessAbstractGroupParameters().AssignFrom(source); - AssignFromHelper(this, source) - CRYPTOPP_SET_FUNCTION_ENTRY(PublicElement); - } -} - -class OID; - -//! _ -template -class DL_KeyImpl : public PK -{ -public: - typedef GP GroupParameters; - - O GetAlgorithmID() const {return GetGroupParameters().GetAlgorithmID();} -// void BERDecode(BufferedTransformation &bt) -// {PK::BERDecode(bt);} -// void DEREncode(BufferedTransformation &bt) const -// {PK::DEREncode(bt);} - bool BERDecodeAlgorithmParameters(BufferedTransformation &bt) - {AccessGroupParameters().BERDecode(bt); return true;} - bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const - {GetGroupParameters().DEREncode(bt); return true;} - - const GP & GetGroupParameters() const {return m_groupParameters;} - GP & AccessGroupParameters() {return m_groupParameters;} - -private: - GP m_groupParameters; -}; - -class X509PublicKey; -class PKCS8PrivateKey; - -//! _ -template -class DL_PrivateKeyImpl : public DL_PrivateKey, public DL_KeyImpl -{ -public: - typedef typename GP::Element Element; - - // GeneratableCryptoMaterial - bool Validate(RandomNumberGenerator &rng, unsigned int level) const - { - bool pass = GetAbstractGroupParameters().Validate(rng, level); - - const Integer &q = GetAbstractGroupParameters().GetSubgroupOrder(); - const Integer &x = GetPrivateExponent(); - - pass = pass && x.IsPositive() && x < q; - if (level >= 1) - pass = pass && Integer::Gcd(x, q) == Integer::One(); - return pass; - } - - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const - { - return GetValueHelper >(this, name, valueType, pValue).Assignable(); - } - - void AssignFrom(const NameValuePairs &source) - { - AssignFromHelper >(this, source); - } - - void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms) - { - if (!params.GetThisObject(this->AccessGroupParameters())) - this->AccessGroupParameters().GenerateRandom(rng, params); -// std::pair seed; - Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent()); -// Integer::ANY, Integer::Zero(), Integer::One(), -// params.GetValue("DeterministicKeyGenerationSeed", seed) ? &seed : NULL); - SetPrivateExponent(x); - } - - bool SupportsPrecomputation() const {return true;} - - void Precompute(unsigned int precomputationStorage=16) - {AccessAbstractGroupParameters().Precompute(precomputationStorage);} - - void LoadPrecomputation(BufferedTransformation &storedPrecomputation) - {AccessAbstractGroupParameters().LoadPrecomputation(storedPrecomputation);} - - void SavePrecomputation(BufferedTransformation &storedPrecomputation) const - {GetAbstractGroupParameters().SavePrecomputation(storedPrecomputation);} - - // DL_Key - const DL_GroupParameters & GetAbstractGroupParameters() const {return this->GetGroupParameters();} - DL_GroupParameters & AccessAbstractGroupParameters() {return this->AccessGroupParameters();} - - // DL_PrivateKey - const Integer & GetPrivateExponent() const {return m_x;} - void SetPrivateExponent(const Integer &x) {m_x = x;} - - // PKCS8PrivateKey - void BERDecodePrivateKey(BufferedTransformation &bt, bool, size_t) - {m_x.BERDecode(bt);} - void DEREncodePrivateKey(BufferedTransformation &bt) const - {m_x.DEREncode(bt);} - -private: - Integer m_x; -}; - -//! _ -template -class DL_PrivateKey_WithSignaturePairwiseConsistencyTest : public BASE -{ -public: - void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms) - { - BASE::GenerateRandom(rng, params); - - if (FIPS_140_2_ComplianceEnabled()) - { - typename SIGNATURE_SCHEME::Signer signer(*this); - typename SIGNATURE_SCHEME::Verifier verifier(signer); - SignaturePairwiseConsistencyTest_FIPS_140_Only(signer, verifier); - } - } -}; - -//! _ -template -class DL_PublicKeyImpl : public DL_PublicKey, public DL_KeyImpl -{ -public: - typedef typename GP::Element Element; - - // CryptoMaterial - bool Validate(RandomNumberGenerator &rng, unsigned int level) const - { - bool pass = GetAbstractGroupParameters().Validate(rng, level); - pass = pass && GetAbstractGroupParameters().ValidateElement(level, this->GetPublicElement(), &GetPublicPrecomputation()); - return pass; - } - - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const - { - return GetValueHelper >(this, name, valueType, pValue).Assignable(); - } - - void AssignFrom(const NameValuePairs &source) - { - AssignFromHelper >(this, source); - } - - bool SupportsPrecomputation() const {return true;} - - void Precompute(unsigned int precomputationStorage=16) - { - AccessAbstractGroupParameters().Precompute(precomputationStorage); - AccessPublicPrecomputation().Precompute(GetAbstractGroupParameters().GetGroupPrecomputation(), GetAbstractGroupParameters().GetSubgroupOrder().BitCount(), precomputationStorage); - } - - void LoadPrecomputation(BufferedTransformation &storedPrecomputation) - { - AccessAbstractGroupParameters().LoadPrecomputation(storedPrecomputation); - AccessPublicPrecomputation().Load(GetAbstractGroupParameters().GetGroupPrecomputation(), storedPrecomputation); - } - - void SavePrecomputation(BufferedTransformation &storedPrecomputation) const - { - GetAbstractGroupParameters().SavePrecomputation(storedPrecomputation); - GetPublicPrecomputation().Save(GetAbstractGroupParameters().GetGroupPrecomputation(), storedPrecomputation); - } - - // DL_Key - const DL_GroupParameters & GetAbstractGroupParameters() const {return this->GetGroupParameters();} - DL_GroupParameters & AccessAbstractGroupParameters() {return this->AccessGroupParameters();} - - // DL_PublicKey - const DL_FixedBasePrecomputation & GetPublicPrecomputation() const {return m_ypc;} - DL_FixedBasePrecomputation & AccessPublicPrecomputation() {return m_ypc;} - - // non-inherited - bool operator==(const DL_PublicKeyImpl &rhs) const - {return this->GetGroupParameters() == rhs.GetGroupParameters() && this->GetPublicElement() == rhs.GetPublicElement();} - -private: - typename GP::BasePrecomputation m_ypc; -}; - -//! interface for Elgamal-like signature algorithms -template -class CRYPTOPP_NO_VTABLE DL_ElgamalLikeSignatureAlgorithm -{ -public: - virtual void Sign(const DL_GroupParameters ¶ms, const Integer &privateKey, const Integer &k, const Integer &e, Integer &r, Integer &s) const =0; - virtual bool Verify(const DL_GroupParameters ¶ms, const DL_PublicKey &publicKey, const Integer &e, const Integer &r, const Integer &s) const =0; - virtual Integer RecoverPresignature(const DL_GroupParameters ¶ms, const DL_PublicKey &publicKey, const Integer &r, const Integer &s) const - {throw NotImplemented("DL_ElgamalLikeSignatureAlgorithm: this signature scheme does not support message recovery");} - virtual size_t RLen(const DL_GroupParameters ¶ms) const - {return params.GetSubgroupOrder().ByteCount();} - virtual size_t SLen(const DL_GroupParameters ¶ms) const - {return params.GetSubgroupOrder().ByteCount();} -}; - -//! interface for DL key agreement algorithms -template -class CRYPTOPP_NO_VTABLE DL_KeyAgreementAlgorithm -{ -public: - typedef T Element; - - virtual Element AgreeWithEphemeralPrivateKey(const DL_GroupParameters ¶ms, const DL_FixedBasePrecomputation &publicPrecomputation, const Integer &privateExponent) const =0; - virtual Element AgreeWithStaticPrivateKey(const DL_GroupParameters ¶ms, const Element &publicElement, bool validateOtherPublicKey, const Integer &privateExponent) const =0; -}; - -//! interface for key derivation algorithms used in DL cryptosystems -template -class CRYPTOPP_NO_VTABLE DL_KeyDerivationAlgorithm -{ -public: - virtual bool ParameterSupported(const char *name) const {return false;} - virtual void Derive(const DL_GroupParameters &groupParams, byte *derivedKey, size_t derivedLength, const T &agreedElement, const T &ephemeralPublicKey, const NameValuePairs &derivationParams) const =0; -}; - -//! interface for symmetric encryption algorithms used in DL cryptosystems -class CRYPTOPP_NO_VTABLE DL_SymmetricEncryptionAlgorithm -{ -public: - virtual bool ParameterSupported(const char *name) const {return false;} - virtual size_t GetSymmetricKeyLength(size_t plaintextLength) const =0; - virtual size_t GetSymmetricCiphertextLength(size_t plaintextLength) const =0; - virtual size_t GetMaxSymmetricPlaintextLength(size_t ciphertextLength) const =0; - virtual void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters) const =0; - virtual DecodingResult SymmetricDecrypt(const byte *key, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters) const =0; -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE DL_Base -{ -protected: - typedef KI KeyInterface; - typedef typename KI::Element Element; - - const DL_GroupParameters & GetAbstractGroupParameters() const {return GetKeyInterface().GetAbstractGroupParameters();} - DL_GroupParameters & AccessAbstractGroupParameters() {return AccessKeyInterface().AccessAbstractGroupParameters();} - - virtual KeyInterface & AccessKeyInterface() =0; - virtual const KeyInterface & GetKeyInterface() const =0; -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE DL_SignatureSchemeBase : public INTERFACE, public DL_Base -{ -public: - size_t SignatureLength() const - { - return GetSignatureAlgorithm().RLen(this->GetAbstractGroupParameters()) - + GetSignatureAlgorithm().SLen(this->GetAbstractGroupParameters()); - } - size_t MaxRecoverableLength() const - {return GetMessageEncodingInterface().MaxRecoverableLength(0, GetHashIdentifier().second, GetDigestSize());} - size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const - {assert(false); return 0;} // TODO - - bool IsProbabilistic() const - {return true;} - bool AllowNonrecoverablePart() const - {return GetMessageEncodingInterface().AllowNonrecoverablePart();} - bool RecoverablePartFirst() const - {return GetMessageEncodingInterface().RecoverablePartFirst();} - -protected: - size_t MessageRepresentativeLength() const {return BitsToBytes(MessageRepresentativeBitLength());} - size_t MessageRepresentativeBitLength() const {return this->GetAbstractGroupParameters().GetSubgroupOrder().BitCount();} - - virtual const DL_ElgamalLikeSignatureAlgorithm & GetSignatureAlgorithm() const =0; - virtual const PK_SignatureMessageEncodingMethod & GetMessageEncodingInterface() const =0; - virtual HashIdentifier GetHashIdentifier() const =0; - virtual size_t GetDigestSize() const =0; -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE DL_SignerBase : public DL_SignatureSchemeBase > -{ -public: - // for validation testing - void RawSign(const Integer &k, const Integer &e, Integer &r, Integer &s) const - { - const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); - const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); - const DL_PrivateKey &key = this->GetKeyInterface(); - - r = params.ConvertElementToInteger(params.ExponentiateBase(k)); - alg.Sign(params, key.GetPrivateExponent(), k, e, r, s); - } - - void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const - { - PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); - ma.m_recoverableMessage.Assign(recoverableMessage, recoverableMessageLength); - this->GetMessageEncodingInterface().ProcessRecoverableMessage(ma.AccessHash(), - recoverableMessage, recoverableMessageLength, - ma.m_presignature, ma.m_presignature.size(), - ma.m_semisignature); - } - - size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const - { - this->GetMaterial().DoQuickSanityCheck(); - - PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); - const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); - const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); - const DL_PrivateKey &key = this->GetKeyInterface(); - - SecByteBlock representative(this->MessageRepresentativeLength()); - this->GetMessageEncodingInterface().ComputeMessageRepresentative( - rng, - ma.m_recoverableMessage, ma.m_recoverableMessage.size(), - ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty, - representative, this->MessageRepresentativeBitLength()); - ma.m_empty = true; - Integer e(representative, representative.size()); - - // hash message digest into random number k to prevent reusing the same k on a different messages - // after virtual machine rollback - if (rng.CanIncorporateEntropy()) - rng.IncorporateEntropy(representative, representative.size()); - Integer k(rng, 1, params.GetSubgroupOrder()-1); - Integer r, s; - r = params.ConvertElementToInteger(params.ExponentiateBase(k)); - alg.Sign(params, key.GetPrivateExponent(), k, e, r, s); - - /* - Integer r, s; - if (this->MaxRecoverableLength() > 0) - r.Decode(ma.m_semisignature, ma.m_semisignature.size()); - else - r.Decode(ma.m_presignature, ma.m_presignature.size()); - alg.Sign(params, key.GetPrivateExponent(), ma.m_k, e, r, s); - */ - - size_t rLen = alg.RLen(params); - r.Encode(signature, rLen); - s.Encode(signature+rLen, alg.SLen(params)); - - if (restart) - RestartMessageAccumulator(rng, ma); - - return this->SignatureLength(); - } - -protected: - void RestartMessageAccumulator(RandomNumberGenerator &rng, PK_MessageAccumulatorBase &ma) const - { - // k needs to be generated before hashing for signature schemes with recovery - // but to defend against VM rollbacks we need to generate k after hashing. - // so this code is commented out, since no DL-based signature scheme with recovery - // has been implemented in Crypto++ anyway - /* - const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); - const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); - ma.m_k.Randomize(rng, 1, params.GetSubgroupOrder()-1); - ma.m_presignature.New(params.GetEncodedElementSize(false)); - params.ConvertElementToInteger(params.ExponentiateBase(ma.m_k)).Encode(ma.m_presignature, ma.m_presignature.size()); - */ - } -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE DL_VerifierBase : public DL_SignatureSchemeBase > -{ -public: - void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const - { - PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); - const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); - const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); - - size_t rLen = alg.RLen(params); - ma.m_semisignature.Assign(signature, rLen); - ma.m_s.Decode(signature+rLen, alg.SLen(params)); - - this->GetMessageEncodingInterface().ProcessSemisignature(ma.AccessHash(), ma.m_semisignature, ma.m_semisignature.size()); - } - - bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const - { - this->GetMaterial().DoQuickSanityCheck(); - - PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); - const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); - const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); - const DL_PublicKey &key = this->GetKeyInterface(); - - SecByteBlock representative(this->MessageRepresentativeLength()); - this->GetMessageEncodingInterface().ComputeMessageRepresentative(NullRNG(), ma.m_recoverableMessage, ma.m_recoverableMessage.size(), - ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty, - representative, this->MessageRepresentativeBitLength()); - ma.m_empty = true; - Integer e(representative, representative.size()); - - Integer r(ma.m_semisignature, ma.m_semisignature.size()); - return alg.Verify(params, key, e, r, ma.m_s); - } - - DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const - { - this->GetMaterial().DoQuickSanityCheck(); - - PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); - const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); - const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); - const DL_PublicKey &key = this->GetKeyInterface(); - - SecByteBlock representative(this->MessageRepresentativeLength()); - this->GetMessageEncodingInterface().ComputeMessageRepresentative( - NullRNG(), - ma.m_recoverableMessage, ma.m_recoverableMessage.size(), - ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty, - representative, this->MessageRepresentativeBitLength()); - ma.m_empty = true; - Integer e(representative, representative.size()); - - ma.m_presignature.New(params.GetEncodedElementSize(false)); - Integer r(ma.m_semisignature, ma.m_semisignature.size()); - alg.RecoverPresignature(params, key, r, ma.m_s).Encode(ma.m_presignature, ma.m_presignature.size()); - - return this->GetMessageEncodingInterface().RecoverMessageFromSemisignature( - ma.AccessHash(), this->GetHashIdentifier(), - ma.m_presignature, ma.m_presignature.size(), - ma.m_semisignature, ma.m_semisignature.size(), - recoveredMessage); - } -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE DL_CryptoSystemBase : public PK, public DL_Base -{ -public: - typedef typename DL_Base::Element Element; - - size_t MaxPlaintextLength(size_t ciphertextLength) const - { - unsigned int minLen = this->GetAbstractGroupParameters().GetEncodedElementSize(true); - return ciphertextLength < minLen ? 0 : GetSymmetricEncryptionAlgorithm().GetMaxSymmetricPlaintextLength(ciphertextLength - minLen); - } - - size_t CiphertextLength(size_t plaintextLength) const - { - size_t len = GetSymmetricEncryptionAlgorithm().GetSymmetricCiphertextLength(plaintextLength); - return len == 0 ? 0 : this->GetAbstractGroupParameters().GetEncodedElementSize(true) + len; - } - - bool ParameterSupported(const char *name) const - {return GetKeyDerivationAlgorithm().ParameterSupported(name) || GetSymmetricEncryptionAlgorithm().ParameterSupported(name);} - -protected: - virtual const DL_KeyAgreementAlgorithm & GetKeyAgreementAlgorithm() const =0; - virtual const DL_KeyDerivationAlgorithm & GetKeyDerivationAlgorithm() const =0; - virtual const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const =0; -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE DL_DecryptorBase : public DL_CryptoSystemBase > -{ -public: - typedef T Element; - - DecodingResult Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters = g_nullNameValuePairs) const - { - try - { - const DL_KeyAgreementAlgorithm &agreeAlg = this->GetKeyAgreementAlgorithm(); - const DL_KeyDerivationAlgorithm &derivAlg = this->GetKeyDerivationAlgorithm(); - const DL_SymmetricEncryptionAlgorithm &encAlg = this->GetSymmetricEncryptionAlgorithm(); - const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); - const DL_PrivateKey &key = this->GetKeyInterface(); - - Element q = params.DecodeElement(ciphertext, true); - size_t elementSize = params.GetEncodedElementSize(true); - ciphertext += elementSize; - ciphertextLength -= elementSize; - - Element z = agreeAlg.AgreeWithStaticPrivateKey(params, q, true, key.GetPrivateExponent()); - - SecByteBlock derivedKey(encAlg.GetSymmetricKeyLength(encAlg.GetMaxSymmetricPlaintextLength(ciphertextLength))); - derivAlg.Derive(params, derivedKey, derivedKey.size(), z, q, parameters); - - return encAlg.SymmetricDecrypt(derivedKey, ciphertext, ciphertextLength, plaintext, parameters); - } - catch (DL_BadElement &) - { - return DecodingResult(); - } - } -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE DL_EncryptorBase : public DL_CryptoSystemBase > -{ -public: - typedef T Element; - - void Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters = g_nullNameValuePairs) const - { - const DL_KeyAgreementAlgorithm &agreeAlg = this->GetKeyAgreementAlgorithm(); - const DL_KeyDerivationAlgorithm &derivAlg = this->GetKeyDerivationAlgorithm(); - const DL_SymmetricEncryptionAlgorithm &encAlg = this->GetSymmetricEncryptionAlgorithm(); - const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); - const DL_PublicKey &key = this->GetKeyInterface(); - - Integer x(rng, Integer::One(), params.GetMaxExponent()); - Element q = params.ExponentiateBase(x); - params.EncodeElement(true, q, ciphertext); - unsigned int elementSize = params.GetEncodedElementSize(true); - ciphertext += elementSize; - - Element z = agreeAlg.AgreeWithEphemeralPrivateKey(params, key.GetPublicPrecomputation(), x); - - SecByteBlock derivedKey(encAlg.GetSymmetricKeyLength(plaintextLength)); - derivAlg.Derive(params, derivedKey, derivedKey.size(), z, q, parameters); - - encAlg.SymmetricEncrypt(rng, derivedKey, plaintext, plaintextLength, ciphertext, parameters); - } -}; - -//! _ -template -struct DL_SchemeOptionsBase -{ - typedef T1 AlgorithmInfo; - typedef T2 GroupParameters; - typedef typename GroupParameters::Element Element; -}; - -//! _ -template -struct DL_KeyedSchemeOptions : public DL_SchemeOptionsBase -{ - typedef T2 Keys; - typedef typename Keys::PrivateKey PrivateKey; - typedef typename Keys::PublicKey PublicKey; -}; - -//! _ -template -struct DL_SignatureSchemeOptions : public DL_KeyedSchemeOptions -{ - typedef T3 SignatureAlgorithm; - typedef T4 MessageEncodingMethod; - typedef T5 HashFunction; -}; - -//! _ -template -struct DL_CryptoSchemeOptions : public DL_KeyedSchemeOptions -{ - typedef T3 KeyAgreementAlgorithm; - typedef T4 KeyDerivationAlgorithm; - typedef T5 SymmetricEncryptionAlgorithm; -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE DL_ObjectImplBase : public AlgorithmImpl -{ -public: - typedef SCHEME_OPTIONS SchemeOptions; - typedef typename KEY::Element Element; - - PrivateKey & AccessPrivateKey() {return m_key;} - PublicKey & AccessPublicKey() {return m_key;} - - // KeyAccessor - const KEY & GetKey() const {return m_key;} - KEY & AccessKey() {return m_key;} - -protected: - typename BASE::KeyInterface & AccessKeyInterface() {return m_key;} - const typename BASE::KeyInterface & GetKeyInterface() const {return m_key;} - - // for signature scheme - HashIdentifier GetHashIdentifier() const - { - typedef typename SchemeOptions::MessageEncodingMethod::HashIdentifierLookup HashLookup; - return HashLookup::template HashIdentifierLookup2::Lookup(); - } - size_t GetDigestSize() const - { - typedef CPP_TYPENAME SchemeOptions::HashFunction H; - return H::DIGESTSIZE; - } - -private: - KEY m_key; -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE DL_ObjectImpl : public DL_ObjectImplBase -{ -public: - typedef typename KEY::Element Element; - -protected: - const DL_ElgamalLikeSignatureAlgorithm & GetSignatureAlgorithm() const - {return Singleton().Ref();} - const DL_KeyAgreementAlgorithm & GetKeyAgreementAlgorithm() const - {return Singleton().Ref();} - const DL_KeyDerivationAlgorithm & GetKeyDerivationAlgorithm() const - {return Singleton().Ref();} - const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const - {return Singleton().Ref();} - HashIdentifier GetHashIdentifier() const - {return HashIdentifier();} - const PK_SignatureMessageEncodingMethod & GetMessageEncodingInterface() const - {return Singleton().Ref();} -}; - -//! _ -template -class DL_SignerImpl : public DL_ObjectImpl, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey> -{ -public: - PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const - { - std::auto_ptr p(new PK_MessageAccumulatorImpl); - this->RestartMessageAccumulator(rng, *p); - return p.release(); - } -}; - -//! _ -template -class DL_VerifierImpl : public DL_ObjectImpl, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey> -{ -public: - PK_MessageAccumulator * NewVerificationAccumulator() const - { - return new PK_MessageAccumulatorImpl; - } -}; - -//! _ -template -class DL_EncryptorImpl : public DL_ObjectImpl, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey> -{ -}; - -//! _ -template -class DL_DecryptorImpl : public DL_ObjectImpl, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey> -{ -}; - -// ******************************************************** - -//! _ -template -class CRYPTOPP_NO_VTABLE DL_SimpleKeyAgreementDomainBase : public SimpleKeyAgreementDomain -{ -public: - typedef T Element; - - CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();} - unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);} - unsigned int PrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();} - unsigned int PublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);} - - void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const - { - Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent()); - x.Encode(privateKey, PrivateKeyLength()); - } - - void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const - { - const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); - Integer x(privateKey, PrivateKeyLength()); - Element y = params.ExponentiateBase(x); - params.EncodeElement(true, y, publicKey); - } - - bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const - { - try - { - const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); - Integer x(privateKey, PrivateKeyLength()); - Element w = params.DecodeElement(otherPublicKey, validateOtherPublicKey); - - Element z = GetKeyAgreementAlgorithm().AgreeWithStaticPrivateKey( - GetAbstractGroupParameters(), w, validateOtherPublicKey, x); - params.EncodeElement(false, z, agreedValue); - } - catch (DL_BadElement &) - { - return false; - } - return true; - } - - const Element &GetGenerator() const {return GetAbstractGroupParameters().GetSubgroupGenerator();} - -protected: - virtual const DL_KeyAgreementAlgorithm & GetKeyAgreementAlgorithm() const =0; - virtual DL_GroupParameters & AccessAbstractGroupParameters() =0; - const DL_GroupParameters & GetAbstractGroupParameters() const {return const_cast *>(this)->AccessAbstractGroupParameters();} -}; - -enum CofactorMultiplicationOption {NO_COFACTOR_MULTIPLICTION, COMPATIBLE_COFACTOR_MULTIPLICTION, INCOMPATIBLE_COFACTOR_MULTIPLICTION}; -typedef EnumToType NoCofactorMultiplication; -typedef EnumToType CompatibleCofactorMultiplication; -typedef EnumToType IncompatibleCofactorMultiplication; - -//! DH key agreement algorithm -template -class DL_KeyAgreementAlgorithm_DH : public DL_KeyAgreementAlgorithm -{ -public: - typedef ELEMENT Element; - - static const char * CRYPTOPP_API StaticAlgorithmName() - {return COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION ? "DHC" : "DH";} - - Element AgreeWithEphemeralPrivateKey(const DL_GroupParameters ¶ms, const DL_FixedBasePrecomputation &publicPrecomputation, const Integer &privateExponent) const - { - return publicPrecomputation.Exponentiate(params.GetGroupPrecomputation(), - COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION ? privateExponent*params.GetCofactor() : privateExponent); - } - - Element AgreeWithStaticPrivateKey(const DL_GroupParameters ¶ms, const Element &publicElement, bool validateOtherPublicKey, const Integer &privateExponent) const - { - if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION) - { - const Integer &k = params.GetCofactor(); - return params.ExponentiateElement(publicElement, - ModularArithmetic(params.GetSubgroupOrder()).Divide(privateExponent, k)*k); - } - else if (COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION) - return params.ExponentiateElement(publicElement, privateExponent*params.GetCofactor()); - else - { - assert(COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION); - - if (!validateOtherPublicKey) - return params.ExponentiateElement(publicElement, privateExponent); - - if (params.FastSubgroupCheckAvailable()) - { - if (!params.ValidateElement(2, publicElement, NULL)) - throw DL_BadElement(); - return params.ExponentiateElement(publicElement, privateExponent); - } - else - { - const Integer e[2] = {params.GetSubgroupOrder(), privateExponent}; - Element r[2]; - params.SimultaneousExponentiate(r, publicElement, e, 2); - if (!params.IsIdentity(r[0])) - throw DL_BadElement(); - return r[1]; - } - } - } -}; - -// ******************************************************** - -//! A template implementing constructors for public key algorithm classes -template -class CRYPTOPP_NO_VTABLE PK_FinalTemplate : public BASE -{ -public: - PK_FinalTemplate() {} - - PK_FinalTemplate(const CryptoMaterial &key) - {this->AccessKey().AssignFrom(key);} - - PK_FinalTemplate(BufferedTransformation &bt) - {this->AccessKey().BERDecode(bt);} - - PK_FinalTemplate(const AsymmetricAlgorithm &algorithm) - {this->AccessKey().AssignFrom(algorithm.GetMaterial());} - - PK_FinalTemplate(const Integer &v1) - {this->AccessKey().Initialize(v1);} - -#if (defined(_MSC_VER) && _MSC_VER < 1300) - - template - PK_FinalTemplate(T1 &v1, T2 &v2) - {this->AccessKey().Initialize(v1, v2);} - - template - PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3) - {this->AccessKey().Initialize(v1, v2, v3);} - - template - PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4) - {this->AccessKey().Initialize(v1, v2, v3, v4);} - - template - PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5);} - - template - PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);} - - template - PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6, T7 &v7) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);} - - template - PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6, T7 &v7, T8 &v8) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);} - -#else - - template - PK_FinalTemplate(const T1 &v1, const T2 &v2) - {this->AccessKey().Initialize(v1, v2);} - - template - PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3) - {this->AccessKey().Initialize(v1, v2, v3);} - - template - PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) - {this->AccessKey().Initialize(v1, v2, v3, v4);} - - template - PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5);} - - template - PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);} - - template - PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);} - - template - PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);} - - template - PK_FinalTemplate(T1 &v1, const T2 &v2) - {this->AccessKey().Initialize(v1, v2);} - - template - PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3) - {this->AccessKey().Initialize(v1, v2, v3);} - - template - PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) - {this->AccessKey().Initialize(v1, v2, v3, v4);} - - template - PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5);} - - template - PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);} - - template - PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);} - - template - PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8) - {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);} - -#endif -}; - -//! Base class for public key encryption standard classes. These classes are used to select from variants of algorithms. Note that not all standards apply to all algorithms. -struct EncryptionStandard {}; - -//! Base class for public key signature standard classes. These classes are used to select from variants of algorithms. Note that not all standards apply to all algorithms. -struct SignatureStandard {}; - -template -class TF_ES; - -//! Trapdoor Function Based Encryption Scheme -template > -class TF_ES : public KEYS -{ - typedef typename STANDARD::EncryptionMessageEncodingMethod MessageEncodingMethod; - -public: - //! see EncryptionStandard for a list of standards - typedef STANDARD Standard; - typedef TF_CryptoSchemeOptions SchemeOptions; - - static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(KEYS::StaticAlgorithmName()) + "/" + MessageEncodingMethod::StaticAlgorithmName();} - - //! implements PK_Decryptor interface - typedef PK_FinalTemplate > Decryptor; - //! implements PK_Encryptor interface - typedef PK_FinalTemplate > Encryptor; -}; - -template // VC60 workaround: doesn't work if KEYS is first parameter -class TF_SS; - -//! Trapdoor Function Based Signature Scheme -template > // VC60 workaround: doesn't work if KEYS is first parameter -class TF_SS : public KEYS -{ -public: - //! see SignatureStandard for a list of standards - typedef STANDARD Standard; - typedef typename Standard::SignatureMessageEncodingMethod MessageEncodingMethod; - typedef TF_SignatureSchemeOptions SchemeOptions; - - static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(KEYS::StaticAlgorithmName()) + "/" + MessageEncodingMethod::StaticAlgorithmName() + "(" + H::StaticAlgorithmName() + ")";} - - //! implements PK_Signer interface - typedef PK_FinalTemplate > Signer; - //! implements PK_Verifier interface - typedef PK_FinalTemplate > Verifier; -}; - -template -class DL_SS; - -//! Discrete Log Based Signature Scheme -template > -class DL_SS : public KEYS -{ - typedef DL_SignatureSchemeOptions SchemeOptions; - -public: - static std::string StaticAlgorithmName() {return SA::StaticAlgorithmName() + std::string("/EMSA1(") + H::StaticAlgorithmName() + ")";} - - //! implements PK_Signer interface - typedef PK_FinalTemplate > Signer; - //! implements PK_Verifier interface - typedef PK_FinalTemplate > Verifier; -}; - -//! Discrete Log Based Encryption Scheme -template -class DL_ES : public KEYS -{ - typedef DL_CryptoSchemeOptions SchemeOptions; - -public: - //! implements PK_Decryptor interface - typedef PK_FinalTemplate > Decryptor; - //! implements PK_Encryptor interface - typedef PK_FinalTemplate > Encryptor; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/queue.cpp b/embeddedcryptopp/queue.cpp deleted file mode 100644 index ae05a78..0000000 --- a/embeddedcryptopp/queue.cpp +++ /dev/null @@ -1,564 +0,0 @@ -// queue.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "queue.h" -#include "filters.h" - -NAMESPACE_BEGIN(CryptoPP) - -static const unsigned int s_maxAutoNodeSize = 16*1024; - -// this class for use by ByteQueue only -class ByteQueueNode -{ -public: - ByteQueueNode(size_t maxSize) - : buf(maxSize) - { - m_head = m_tail = 0; - next = 0; - } - - inline size_t MaxSize() const {return buf.size();} - - inline size_t CurrentSize() const - { - return m_tail-m_head; - } - - inline bool UsedUp() const - { - return (m_head==MaxSize()); - } - - inline void Clear() - { - m_head = m_tail = 0; - } - - inline size_t Put(const byte *begin, size_t length) - { - size_t l = STDMIN(length, MaxSize()-m_tail); - if (buf+m_tail != begin) - memcpy(buf+m_tail, begin, l); - m_tail += l; - return l; - } - - inline size_t Peek(byte &outByte) const - { - if (m_tail==m_head) - return 0; - - outByte=buf[m_head]; - return 1; - } - - inline size_t Peek(byte *target, size_t copyMax) const - { - size_t len = STDMIN(copyMax, m_tail-m_head); - memcpy(target, buf+m_head, len); - return len; - } - - inline size_t CopyTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL) const - { - size_t len = m_tail-m_head; - target.ChannelPut(channel, buf+m_head, len); - return len; - } - - inline size_t CopyTo(BufferedTransformation &target, size_t copyMax, const std::string &channel=DEFAULT_CHANNEL) const - { - size_t len = STDMIN(copyMax, m_tail-m_head); - target.ChannelPut(channel, buf+m_head, len); - return len; - } - - inline size_t Get(byte &outByte) - { - size_t len = Peek(outByte); - m_head += len; - return len; - } - - inline size_t Get(byte *outString, size_t getMax) - { - size_t len = Peek(outString, getMax); - m_head += len; - return len; - } - - inline size_t TransferTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL) - { - size_t len = m_tail-m_head; - target.ChannelPutModifiable(channel, buf+m_head, len); - m_head = m_tail; - return len; - } - - inline size_t TransferTo(BufferedTransformation &target, lword transferMax, const std::string &channel=DEFAULT_CHANNEL) - { - size_t len = UnsignedMin(m_tail-m_head, transferMax); - target.ChannelPutModifiable(channel, buf+m_head, len); - m_head += len; - return len; - } - - inline size_t Skip(size_t skipMax) - { - size_t len = STDMIN(skipMax, m_tail-m_head); - m_head += len; - return len; - } - - inline byte operator[](size_t i) const - { - return buf[m_head+i]; - } - - ByteQueueNode *next; - - SecByteBlock buf; - size_t m_head, m_tail; -}; - -// ******************************************************** - -ByteQueue::ByteQueue(size_t nodeSize) - : m_lazyLength(0) -{ - SetNodeSize(nodeSize); - m_head = m_tail = new ByteQueueNode(m_nodeSize); -} - -void ByteQueue::SetNodeSize(size_t nodeSize) -{ - m_autoNodeSize = !nodeSize; - m_nodeSize = m_autoNodeSize ? 256 : nodeSize; -} - -ByteQueue::ByteQueue(const ByteQueue ©) -{ - CopyFrom(copy); -} - -void ByteQueue::CopyFrom(const ByteQueue ©) -{ - m_lazyLength = 0; - m_autoNodeSize = copy.m_autoNodeSize; - m_nodeSize = copy.m_nodeSize; - m_head = m_tail = new ByteQueueNode(*copy.m_head); - - for (ByteQueueNode *current=copy.m_head->next; current; current=current->next) - { - m_tail->next = new ByteQueueNode(*current); - m_tail = m_tail->next; - } - - m_tail->next = NULL; - - Put(copy.m_lazyString, copy.m_lazyLength); -} - -ByteQueue::~ByteQueue() -{ - Destroy(); -} - -void ByteQueue::Destroy() -{ - for (ByteQueueNode *next, *current=m_head; current; current=next) - { - next=current->next; - delete current; - } -} - -void ByteQueue::IsolatedInitialize(const NameValuePairs ¶meters) -{ - m_nodeSize = parameters.GetIntValueWithDefault("NodeSize", 256); - Clear(); -} - -lword ByteQueue::CurrentSize() const -{ - lword size=0; - - for (ByteQueueNode *current=m_head; current; current=current->next) - size += current->CurrentSize(); - - return size + m_lazyLength; -} - -bool ByteQueue::IsEmpty() const -{ - return m_head==m_tail && m_head->CurrentSize()==0 && m_lazyLength==0; -} - -void ByteQueue::Clear() -{ - for (ByteQueueNode *next, *current=m_head->next; current; current=next) - { - next=current->next; - delete current; - } - - m_tail = m_head; - m_head->Clear(); - m_head->next = NULL; - m_lazyLength = 0; -} - -size_t ByteQueue::Put2(const byte *inString, size_t length, int messageEnd, bool blocking) -{ - if (m_lazyLength > 0) - FinalizeLazyPut(); - - size_t len; - while ((len=m_tail->Put(inString, length)) < length) - { - inString += len; - length -= len; - if (m_autoNodeSize && m_nodeSize < s_maxAutoNodeSize) - do - { - m_nodeSize *= 2; - } - while (m_nodeSize < length && m_nodeSize < s_maxAutoNodeSize); - m_tail->next = new ByteQueueNode(STDMAX(m_nodeSize, length)); - m_tail = m_tail->next; - } - - return 0; -} - -void ByteQueue::CleanupUsedNodes() -{ - while (m_head != m_tail && m_head->UsedUp()) - { - ByteQueueNode *temp=m_head; - m_head=m_head->next; - delete temp; - } - - if (m_head->CurrentSize() == 0) - m_head->Clear(); -} - -void ByteQueue::LazyPut(const byte *inString, size_t size) -{ - if (m_lazyLength > 0) - FinalizeLazyPut(); - - if (inString == m_tail->buf+m_tail->m_tail) - Put(inString, size); - else - { - m_lazyString = const_cast(inString); - m_lazyLength = size; - m_lazyStringModifiable = false; - } -} - -void ByteQueue::LazyPutModifiable(byte *inString, size_t size) -{ - if (m_lazyLength > 0) - FinalizeLazyPut(); - m_lazyString = inString; - m_lazyLength = size; - m_lazyStringModifiable = true; -} - -void ByteQueue::UndoLazyPut(size_t size) -{ - if (m_lazyLength < size) - throw InvalidArgument("ByteQueue: size specified for UndoLazyPut is too large"); - - m_lazyLength -= size; -} - -void ByteQueue::FinalizeLazyPut() -{ - size_t len = m_lazyLength; - m_lazyLength = 0; - if (len) - Put(m_lazyString, len); -} - -size_t ByteQueue::Get(byte &outByte) -{ - if (m_head->Get(outByte)) - { - if (m_head->UsedUp()) - CleanupUsedNodes(); - return 1; - } - else if (m_lazyLength > 0) - { - outByte = *m_lazyString++; - m_lazyLength--; - return 1; - } - else - return 0; -} - -size_t ByteQueue::Get(byte *outString, size_t getMax) -{ - ArraySink sink(outString, getMax); - return (size_t)TransferTo(sink, getMax); -} - -size_t ByteQueue::Peek(byte &outByte) const -{ - if (m_head->Peek(outByte)) - return 1; - else if (m_lazyLength > 0) - { - outByte = *m_lazyString; - return 1; - } - else - return 0; -} - -size_t ByteQueue::Peek(byte *outString, size_t peekMax) const -{ - ArraySink sink(outString, peekMax); - return (size_t)CopyTo(sink, peekMax); -} - -size_t ByteQueue::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) -{ - if (blocking) - { - lword bytesLeft = transferBytes; - for (ByteQueueNode *current=m_head; bytesLeft && current; current=current->next) - bytesLeft -= current->TransferTo(target, bytesLeft, channel); - CleanupUsedNodes(); - - size_t len = (size_t)STDMIN(bytesLeft, (lword)m_lazyLength); - if (len) - { - if (m_lazyStringModifiable) - target.ChannelPutModifiable(channel, m_lazyString, len); - else - target.ChannelPut(channel, m_lazyString, len); - m_lazyString += len; - m_lazyLength -= len; - bytesLeft -= len; - } - transferBytes -= bytesLeft; - return 0; - } - else - { - Walker walker(*this); - size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking); - Skip(transferBytes); - return blockedBytes; - } -} - -size_t ByteQueue::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const -{ - Walker walker(*this); - walker.Skip(begin); - lword transferBytes = end-begin; - size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking); - begin += transferBytes; - return blockedBytes; -} - -void ByteQueue::Unget(byte inByte) -{ - Unget(&inByte, 1); -} - -void ByteQueue::Unget(const byte *inString, size_t length) -{ - size_t len = STDMIN(length, m_head->m_head); - length -= len; - m_head->m_head -= len; - memcpy(m_head->buf + m_head->m_head, inString + length, len); - - if (length > 0) - { - ByteQueueNode *newHead = new ByteQueueNode(length); - newHead->next = m_head; - m_head = newHead; - m_head->Put(inString, length); - } -} - -const byte * ByteQueue::Spy(size_t &contiguousSize) const -{ - contiguousSize = m_head->m_tail - m_head->m_head; - if (contiguousSize == 0 && m_lazyLength > 0) - { - contiguousSize = m_lazyLength; - return m_lazyString; - } - else - return m_head->buf + m_head->m_head; -} - -byte * ByteQueue::CreatePutSpace(size_t &size) -{ - if (m_lazyLength > 0) - FinalizeLazyPut(); - - if (m_tail->m_tail == m_tail->MaxSize()) - { - m_tail->next = new ByteQueueNode(STDMAX(m_nodeSize, size)); - m_tail = m_tail->next; - } - - size = m_tail->MaxSize() - m_tail->m_tail; - return m_tail->buf + m_tail->m_tail; -} - -ByteQueue & ByteQueue::operator=(const ByteQueue &rhs) -{ - Destroy(); - CopyFrom(rhs); - return *this; -} - -bool ByteQueue::operator==(const ByteQueue &rhs) const -{ - const lword currentSize = CurrentSize(); - - if (currentSize != rhs.CurrentSize()) - return false; - - Walker walker1(*this), walker2(rhs); - byte b1, b2; - - while (walker1.Get(b1) && walker2.Get(b2)) - if (b1 != b2) - return false; - - return true; -} - -byte ByteQueue::operator[](lword i) const -{ - for (ByteQueueNode *current=m_head; current; current=current->next) - { - if (i < current->CurrentSize()) - return (*current)[(size_t)i]; - - i -= current->CurrentSize(); - } - - assert(i < m_lazyLength); - return m_lazyString[i]; -} - -void ByteQueue::swap(ByteQueue &rhs) -{ - std::swap(m_autoNodeSize, rhs.m_autoNodeSize); - std::swap(m_nodeSize, rhs.m_nodeSize); - std::swap(m_head, rhs.m_head); - std::swap(m_tail, rhs.m_tail); - std::swap(m_lazyString, rhs.m_lazyString); - std::swap(m_lazyLength, rhs.m_lazyLength); - std::swap(m_lazyStringModifiable, rhs.m_lazyStringModifiable); -} - -// ******************************************************** - -void ByteQueue::Walker::IsolatedInitialize(const NameValuePairs ¶meters) -{ - m_node = m_queue.m_head; - m_position = 0; - m_offset = 0; - m_lazyString = m_queue.m_lazyString; - m_lazyLength = m_queue.m_lazyLength; -} - -size_t ByteQueue::Walker::Get(byte &outByte) -{ - ArraySink sink(&outByte, 1); - return (size_t)TransferTo(sink, 1); -} - -size_t ByteQueue::Walker::Get(byte *outString, size_t getMax) -{ - ArraySink sink(outString, getMax); - return (size_t)TransferTo(sink, getMax); -} - -size_t ByteQueue::Walker::Peek(byte &outByte) const -{ - ArraySink sink(&outByte, 1); - return (size_t)CopyTo(sink, 1); -} - -size_t ByteQueue::Walker::Peek(byte *outString, size_t peekMax) const -{ - ArraySink sink(outString, peekMax); - return (size_t)CopyTo(sink, peekMax); -} - -size_t ByteQueue::Walker::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) -{ - lword bytesLeft = transferBytes; - size_t blockedBytes = 0; - - while (m_node) - { - size_t len = (size_t)STDMIN(bytesLeft, (lword)m_node->CurrentSize()-m_offset); - blockedBytes = target.ChannelPut2(channel, m_node->buf+m_node->m_head+m_offset, len, 0, blocking); - - if (blockedBytes) - goto done; - - m_position += len; - bytesLeft -= len; - - if (!bytesLeft) - { - m_offset += len; - goto done; - } - - m_node = m_node->next; - m_offset = 0; - } - - if (bytesLeft && m_lazyLength) - { - size_t len = (size_t)STDMIN(bytesLeft, (lword)m_lazyLength); - blockedBytes = target.ChannelPut2(channel, m_lazyString, len, 0, blocking); - if (blockedBytes) - goto done; - - m_lazyString += len; - m_lazyLength -= len; - bytesLeft -= len; - } - -done: - transferBytes -= bytesLeft; - return blockedBytes; -} - -size_t ByteQueue::Walker::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const -{ - Walker walker(*this); - walker.Skip(begin); - lword transferBytes = end-begin; - size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking); - begin += transferBytes; - return blockedBytes; -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/queue.h b/embeddedcryptopp/queue.h deleted file mode 100644 index 75f7807..0000000 --- a/embeddedcryptopp/queue.h +++ /dev/null @@ -1,143 +0,0 @@ -// specification file for an unlimited queue for storing bytes - -#ifndef CRYPTOPP_QUEUE_H -#define CRYPTOPP_QUEUE_H - -#include "simple.h" -//#include - -NAMESPACE_BEGIN(CryptoPP) - -/** The queue is implemented as a linked list of byte arrays, but you don't need to - know about that. So just ignore this next line. :) */ -class ByteQueueNode; - -//! Byte Queue -class CRYPTOPP_DLL ByteQueue : public Bufferless -{ -public: - ByteQueue(size_t nodeSize=0); - ByteQueue(const ByteQueue ©); - ~ByteQueue(); - - lword MaxRetrievable() const - {return CurrentSize();} - bool AnyRetrievable() const - {return !IsEmpty();} - - void IsolatedInitialize(const NameValuePairs ¶meters); - byte * CreatePutSpace(size_t &size); - size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking); - - size_t Get(byte &outByte); - size_t Get(byte *outString, size_t getMax); - - size_t Peek(byte &outByte) const; - size_t Peek(byte *outString, size_t peekMax) const; - - size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); - size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const; - - // these member functions are not inherited - void SetNodeSize(size_t nodeSize); - - lword CurrentSize() const; - bool IsEmpty() const; - - void Clear(); - - void Unget(byte inByte); - void Unget(const byte *inString, size_t length); - - const byte * Spy(size_t &contiguousSize) const; - - void LazyPut(const byte *inString, size_t size); - void LazyPutModifiable(byte *inString, size_t size); - void UndoLazyPut(size_t size); - void FinalizeLazyPut(); - - ByteQueue & operator=(const ByteQueue &rhs); - bool operator==(const ByteQueue &rhs) const; - byte operator[](lword i) const; - void swap(ByteQueue &rhs); - - class Walker : public InputRejecting - { - public: - Walker(const ByteQueue &queue) - : m_queue(queue) {Initialize();} - - lword GetCurrentPosition() {return m_position;} - - lword MaxRetrievable() const - {return m_queue.CurrentSize() - m_position;} - - void IsolatedInitialize(const NameValuePairs ¶meters); - - size_t Get(byte &outByte); - size_t Get(byte *outString, size_t getMax); - - size_t Peek(byte &outByte) const; - size_t Peek(byte *outString, size_t peekMax) const; - - size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); - size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const; - - private: - const ByteQueue &m_queue; - const ByteQueueNode *m_node; - lword m_position; - size_t m_offset; - const byte *m_lazyString; - size_t m_lazyLength; - }; - - friend class Walker; - -private: - void CleanupUsedNodes(); - void CopyFrom(const ByteQueue ©); - void Destroy(); - - bool m_autoNodeSize; - size_t m_nodeSize; - ByteQueueNode *m_head, *m_tail; - byte *m_lazyString; - size_t m_lazyLength; - bool m_lazyStringModifiable; -}; - -//! use this to make sure LazyPut is finalized in event of exception -class CRYPTOPP_DLL LazyPutter -{ -public: - LazyPutter(ByteQueue &bq, const byte *inString, size_t size) - : m_bq(bq) {bq.LazyPut(inString, size);} - ~LazyPutter() - {try {m_bq.FinalizeLazyPut();} catch(...) {}} -protected: - LazyPutter(ByteQueue &bq) : m_bq(bq) {} -private: - ByteQueue &m_bq; -}; - -//! like LazyPutter, but does a LazyPutModifiable instead -class LazyPutterModifiable : public LazyPutter -{ -public: - LazyPutterModifiable(ByteQueue &bq, byte *inString, size_t size) - : LazyPutter(bq) {bq.LazyPutModifiable(inString, size);} -}; - -NAMESPACE_END - -#ifndef __BORLANDC__ -NAMESPACE_BEGIN(std) -template<> inline void swap(CryptoPP::ByteQueue &a, CryptoPP::ByteQueue &b) -{ - a.swap(b); -} -NAMESPACE_END -#endif - -#endif diff --git a/embeddedcryptopp/randpool.cpp b/embeddedcryptopp/randpool.cpp deleted file mode 100644 index 4e935fe..0000000 --- a/embeddedcryptopp/randpool.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// randpool.cpp - written and placed in the public domain by Wei Dai -// RandomPool used to follow the design of randpool in PGP 2.6.x, -// but as of version 5.5 it has been redesigned to reduce the risk -// of reusing random numbers after state rollback (which may occur -// when running in a virtual machine like VMware). - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "randpool.h" -#include "aes.h" -#include "sha.h" - -NAMESPACE_BEGIN(CryptoPP) - -RandomPool::RandomPool() - : m_pCipher(new AES::Encryption), m_keySet(false) -{ - memset(m_key, 0, m_key.SizeInBytes()); - memset(m_seed, 0, m_seed.SizeInBytes()); -} - -void RandomPool::IncorporateEntropy(const byte *input, size_t length) -{ - SHA256 hash; - hash.Update(m_key, 32); - hash.Update(input, length); - hash.Final(m_key); - m_keySet = false; -} - -void RandomPool::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size) -{ - if (size > 0) - { - if (!m_keySet) - m_pCipher->SetKey(m_key, 32); - - do - { - m_pCipher->ProcessBlock(m_seed); - size_t len = UnsignedMin(16, size); - target.ChannelPut(channel, m_seed, len); - size -= len; - } while (size > 0); - } -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/randpool.h b/embeddedcryptopp/randpool.h deleted file mode 100644 index c25bc9b..0000000 --- a/embeddedcryptopp/randpool.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef CRYPTOPP_RANDPOOL_H -#define CRYPTOPP_RANDPOOL_H - -#include "cryptlib.h" -#include "filters.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! Randomness Pool -/*! This class can be used to generate cryptographic quality - pseudorandom bytes after seeding the pool with IncorporateEntropy() */ -class CRYPTOPP_DLL RandomPool : public RandomNumberGenerator, public NotCopyable -{ -public: - RandomPool(); - - bool CanIncorporateEntropy() const {return true;} - void IncorporateEntropy(const byte *input, size_t length); - void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size); - - // for backwards compatibility. use RandomNumberSource, RandomNumberStore, and RandomNumberSink for other BufferTransformation functionality - void Put(const byte *input, size_t length) {IncorporateEntropy(input, length);} - -private: - FixedSizeSecBlock m_key; - FixedSizeSecBlock m_seed; - member_ptr m_pCipher; - bool m_keySet; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/rdtables.cpp b/embeddedcryptopp/rdtables.cpp deleted file mode 100644 index 4937932..0000000 --- a/embeddedcryptopp/rdtables.cpp +++ /dev/null @@ -1,172 +0,0 @@ -// Rijndael tables - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "rijndael.h" - -// VC60 workaround: gives a C4786 warning without this function -// when runtime lib is set to multithread debug DLL -// even though warning 4786 is disabled! -void Rijndael_VC60Workaround() -{ -} - -NAMESPACE_BEGIN(CryptoPP) - -/* -Te0[x] = S [x].[02, 01, 01, 03]; -Te1[x] = S [x].[03, 02, 01, 01]; -Te2[x] = S [x].[01, 03, 02, 01]; -Te3[x] = S [x].[01, 01, 03, 02]; - -Td0[x] = Si[x].[0e, 09, 0d, 0b]; -Td1[x] = Si[x].[0b, 0e, 09, 0d]; -Td2[x] = Si[x].[0d, 0b, 0e, 09]; -Td3[x] = Si[x].[09, 0d, 0b, 0e]; -*/ - -const byte Rijndael::Base::Se[256] = { - 0x63, 0x7c, 0x77, 0x7b, - 0xf2, 0x6b, 0x6f, 0xc5, - 0x30, 0x01, 0x67, 0x2b, - 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, - 0xfa, 0x59, 0x47, 0xf0, - 0xad, 0xd4, 0xa2, 0xaf, - 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, - 0x36, 0x3f, 0xf7, 0xcc, - 0x34, 0xa5, 0xe5, 0xf1, - 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, - 0x18, 0x96, 0x05, 0x9a, - 0x07, 0x12, 0x80, 0xe2, - 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, - 0x1b, 0x6e, 0x5a, 0xa0, - 0x52, 0x3b, 0xd6, 0xb3, - 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, - 0x20, 0xfc, 0xb1, 0x5b, - 0x6a, 0xcb, 0xbe, 0x39, - 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, - 0x43, 0x4d, 0x33, 0x85, - 0x45, 0xf9, 0x02, 0x7f, - 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, - 0x92, 0x9d, 0x38, 0xf5, - 0xbc, 0xb6, 0xda, 0x21, - 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, - 0x5f, 0x97, 0x44, 0x17, - 0xc4, 0xa7, 0x7e, 0x3d, - 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, - 0x22, 0x2a, 0x90, 0x88, - 0x46, 0xee, 0xb8, 0x14, - 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, - 0x49, 0x06, 0x24, 0x5c, - 0xc2, 0xd3, 0xac, 0x62, - 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, - 0x8d, 0xd5, 0x4e, 0xa9, - 0x6c, 0x56, 0xf4, 0xea, - 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, - 0x1c, 0xa6, 0xb4, 0xc6, - 0xe8, 0xdd, 0x74, 0x1f, - 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, - 0x48, 0x03, 0xf6, 0x0e, - 0x61, 0x35, 0x57, 0xb9, - 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, - 0x69, 0xd9, 0x8e, 0x94, - 0x9b, 0x1e, 0x87, 0xe9, - 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, - 0xbf, 0xe6, 0x42, 0x68, - 0x41, 0x99, 0x2d, 0x0f, - 0xb0, 0x54, 0xbb, 0x16, -}; - -const byte Rijndael::Base::Sd[256] = { - 0x52, 0x09, 0x6a, 0xd5, - 0x30, 0x36, 0xa5, 0x38, - 0xbf, 0x40, 0xa3, 0x9e, - 0x81, 0xf3, 0xd7, 0xfb, - 0x7c, 0xe3, 0x39, 0x82, - 0x9b, 0x2f, 0xff, 0x87, - 0x34, 0x8e, 0x43, 0x44, - 0xc4, 0xde, 0xe9, 0xcb, - 0x54, 0x7b, 0x94, 0x32, - 0xa6, 0xc2, 0x23, 0x3d, - 0xee, 0x4c, 0x95, 0x0b, - 0x42, 0xfa, 0xc3, 0x4e, - 0x08, 0x2e, 0xa1, 0x66, - 0x28, 0xd9, 0x24, 0xb2, - 0x76, 0x5b, 0xa2, 0x49, - 0x6d, 0x8b, 0xd1, 0x25, - 0x72, 0xf8, 0xf6, 0x64, - 0x86, 0x68, 0x98, 0x16, - 0xd4, 0xa4, 0x5c, 0xcc, - 0x5d, 0x65, 0xb6, 0x92, - 0x6c, 0x70, 0x48, 0x50, - 0xfd, 0xed, 0xb9, 0xda, - 0x5e, 0x15, 0x46, 0x57, - 0xa7, 0x8d, 0x9d, 0x84, - 0x90, 0xd8, 0xab, 0x00, - 0x8c, 0xbc, 0xd3, 0x0a, - 0xf7, 0xe4, 0x58, 0x05, - 0xb8, 0xb3, 0x45, 0x06, - 0xd0, 0x2c, 0x1e, 0x8f, - 0xca, 0x3f, 0x0f, 0x02, - 0xc1, 0xaf, 0xbd, 0x03, - 0x01, 0x13, 0x8a, 0x6b, - 0x3a, 0x91, 0x11, 0x41, - 0x4f, 0x67, 0xdc, 0xea, - 0x97, 0xf2, 0xcf, 0xce, - 0xf0, 0xb4, 0xe6, 0x73, - 0x96, 0xac, 0x74, 0x22, - 0xe7, 0xad, 0x35, 0x85, - 0xe2, 0xf9, 0x37, 0xe8, - 0x1c, 0x75, 0xdf, 0x6e, - 0x47, 0xf1, 0x1a, 0x71, - 0x1d, 0x29, 0xc5, 0x89, - 0x6f, 0xb7, 0x62, 0x0e, - 0xaa, 0x18, 0xbe, 0x1b, - 0xfc, 0x56, 0x3e, 0x4b, - 0xc6, 0xd2, 0x79, 0x20, - 0x9a, 0xdb, 0xc0, 0xfe, - 0x78, 0xcd, 0x5a, 0xf4, - 0x1f, 0xdd, 0xa8, 0x33, - 0x88, 0x07, 0xc7, 0x31, - 0xb1, 0x12, 0x10, 0x59, - 0x27, 0x80, 0xec, 0x5f, - 0x60, 0x51, 0x7f, 0xa9, - 0x19, 0xb5, 0x4a, 0x0d, - 0x2d, 0xe5, 0x7a, 0x9f, - 0x93, 0xc9, 0x9c, 0xef, - 0xa0, 0xe0, 0x3b, 0x4d, - 0xae, 0x2a, 0xf5, 0xb0, - 0xc8, 0xeb, 0xbb, 0x3c, - 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2b, 0x04, 0x7e, - 0xba, 0x77, 0xd6, 0x26, - 0xe1, 0x69, 0x14, 0x63, - 0x55, 0x21, 0x0c, 0x7d, -}; - -const word32 Rijndael::Base::rcon[] = { - 0x01000000, 0x02000000, 0x04000000, 0x08000000, - 0x10000000, 0x20000000, 0x40000000, 0x80000000, - 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/rijndael.cpp b/embeddedcryptopp/rijndael.cpp deleted file mode 100644 index 1699e1f..0000000 --- a/embeddedcryptopp/rijndael.cpp +++ /dev/null @@ -1,989 +0,0 @@ -// rijndael.cpp - modified by Chris Morgan -// and Wei Dai from Paulo Baretto's Rijndael implementation -// The original code and all modifications are in the public domain. - -// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM rijndael.cpp" to generate MASM code - -/* -Feb 2009: The x86/x64 assembly code was rewritten in by Wei Dai to do counter mode -caching, which was invented by Hongjun Wu and popularized by Daniel J. Bernstein -and Peter Schwabe in their paper "New AES software speed records". The round -function was also modified to include a trick similar to one in Brian Gladman's -x86 assembly code, doing an 8-bit register move to minimize the number of -register spills. Also switched to compressed tables and copying round keys to -the stack. - -The C++ implementation now uses compressed tables if -CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS is defined. -*/ - -/* -July 2006: Defense against timing attacks was added in by Wei Dai. - -The code now uses smaller tables in the first and last rounds, -and preloads them into L1 cache before usage (by loading at least -one element in each cache line). - -We try to delay subsequent accesses to each table (used in the first -and last rounds) until all of the table has been preloaded. Hopefully -the compiler isn't smart enough to optimize that code away. - -After preloading the table, we also try not to access any memory location -other than the table and the stack, in order to prevent table entries from -being unloaded from L1 cache, until that round is finished. -(Some popular CPUs have 2-way associative caches.) -*/ - -// This is the original introductory comment: - -/** - * version 3.0 (December 2000) - * - * Optimised ANSI C code for the Rijndael cipher (now AES) - * - * author Vincent Rijmen - * author Antoon Bosselaers - * author Paulo Barreto - * - * This code is hereby placed in the public domain. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS -#ifndef CRYPTOPP_GENERATE_X64_MASM - -#include "rijndael.h" -#include "misc.h" -#include "cpu.h" - -#ifdef __sun -#include -#endif - -#ifdef __MINGW32__ -#include -#endif - -NAMESPACE_BEGIN(CryptoPP) - -#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE) -namespace rdtable {CRYPTOPP_ALIGN_DATA(16) word64 Te[256+2];} -using namespace rdtable; -#else -static word64 Te[256]; -#endif -static word64 Td[256]; -#else -static word32 Te[256*4], Td[256*4]; -#endif -static volatile bool s_TeFilled = false, s_TdFilled = false; - -// ************************* Portable Code ************************************ - -#define QUARTER_ROUND(L, T, t, a, b, c, d) \ - a ^= L(T, 3, byte(t)); t >>= 8;\ - b ^= L(T, 2, byte(t)); t >>= 8;\ - c ^= L(T, 1, byte(t)); t >>= 8;\ - d ^= L(T, 0, t); - -#define QUARTER_ROUND_LE(t, a, b, c, d) \ - tempBlock[a] = ((byte *)(Te+byte(t)))[1]; t >>= 8;\ - tempBlock[b] = ((byte *)(Te+byte(t)))[1]; t >>= 8;\ - tempBlock[c] = ((byte *)(Te+byte(t)))[1]; t >>= 8;\ - tempBlock[d] = ((byte *)(Te+t))[1]; - -#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS - #define QUARTER_ROUND_LD(t, a, b, c, d) \ - tempBlock[a] = ((byte *)(Td+byte(t)))[GetNativeByteOrder()*7]; t >>= 8;\ - tempBlock[b] = ((byte *)(Td+byte(t)))[GetNativeByteOrder()*7]; t >>= 8;\ - tempBlock[c] = ((byte *)(Td+byte(t)))[GetNativeByteOrder()*7]; t >>= 8;\ - tempBlock[d] = ((byte *)(Td+t))[GetNativeByteOrder()*7]; -#else - #define QUARTER_ROUND_LD(t, a, b, c, d) \ - tempBlock[a] = Sd[byte(t)]; t >>= 8;\ - tempBlock[b] = Sd[byte(t)]; t >>= 8;\ - tempBlock[c] = Sd[byte(t)]; t >>= 8;\ - tempBlock[d] = Sd[t]; -#endif - -#define QUARTER_ROUND_E(t, a, b, c, d) QUARTER_ROUND(TL_M, Te, t, a, b, c, d) -#define QUARTER_ROUND_D(t, a, b, c, d) QUARTER_ROUND(TL_M, Td, t, a, b, c, d) - -#ifdef IS_LITTLE_ENDIAN - #define QUARTER_ROUND_FE(t, a, b, c, d) QUARTER_ROUND(TL_F, Te, t, d, c, b, a) - #define QUARTER_ROUND_FD(t, a, b, c, d) QUARTER_ROUND(TL_F, Td, t, d, c, b, a) - #ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS - #define TL_F(T, i, x) (*(word32 *)((byte *)T + x*8 + (6-i)%4+1)) - #define TL_M(T, i, x) (*(word32 *)((byte *)T + x*8 + (i+3)%4+1)) - #else - #define TL_F(T, i, x) rotrFixed(T[x], (3-i)*8) - #define TL_M(T, i, x) T[i*256 + x] - #endif -#else - #define QUARTER_ROUND_FE(t, a, b, c, d) QUARTER_ROUND(TL_F, Te, t, a, b, c, d) - #define QUARTER_ROUND_FD(t, a, b, c, d) QUARTER_ROUND(TL_F, Td, t, a, b, c, d) - #ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS - #define TL_F(T, i, x) (*(word32 *)((byte *)T + x*8 + (4-i)%4)) - #define TL_M TL_F - #else - #define TL_F(T, i, x) rotrFixed(T[x], i*8) - #define TL_M(T, i, x) T[i*256 + x] - #endif -#endif - - -#define f2(x) ((x<<1)^(((x>>7)&1)*0x11b)) -#define f4(x) ((x<<2)^(((x>>6)&1)*0x11b)^(((x>>6)&2)*0x11b)) -#define f8(x) ((x<<3)^(((x>>5)&1)*0x11b)^(((x>>5)&2)*0x11b)^(((x>>5)&4)*0x11b)) - -#define f3(x) (f2(x) ^ x) -#define f9(x) (f8(x) ^ x) -#define fb(x) (f8(x) ^ f2(x) ^ x) -#define fd(x) (f8(x) ^ f4(x) ^ x) -#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) - -void Rijndael::Base::FillEncTable() -{ - for (int i=0; i<256; i++) - { - byte x = Se[i]; -#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS - word32 y = word32(x)<<8 | word32(x)<<16 | word32(f2(x))<<24; - Te[i] = word64(y | f3(x))<<32 | y; -#else - word32 y = f3(x) | word32(x)<<8 | word32(x)<<16 | word32(f2(x))<<24; - for (int j=0; j<4; j++) - { - Te[i+j*256] = y; - y = rotrFixed(y, 8); - } -#endif - } -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE) - Te[256] = Te[257] = 0; -#endif - s_TeFilled = true; -} - -void Rijndael::Base::FillDecTable() -{ - for (int i=0; i<256; i++) - { - byte x = Sd[i]; -#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS - word32 y = word32(fd(x))<<8 | word32(f9(x))<<16 | word32(fe(x))<<24; - Td[i] = word64(y | fb(x))<<32 | y | x; -#else - word32 y = fb(x) | word32(fd(x))<<8 | word32(f9(x))<<16 | word32(fe(x))<<24;; - for (int j=0; j<4; j++) - { - Td[i+j*256] = y; - y = rotrFixed(y, 8); - } -#endif - } - s_TdFilled = true; -} - -void Rijndael::Base::UncheckedSetKey(const byte *userKey, unsigned int keylen, const NameValuePairs &) -{ - AssertValidKeyLength(keylen); - - m_rounds = keylen/4 + 6; - m_key.New(4*(m_rounds+1)); - - word32 temp, *rk = m_key; - const word32 *rc = rcon; - - GetUserKey(BIG_ENDIAN_ORDER, rk, keylen/4, userKey, keylen); - - while (true) - { - temp = rk[keylen/4-1]; - rk[keylen/4] = rk[0] ^ - (word32(Se[GETBYTE(temp, 2)]) << 24) ^ - (word32(Se[GETBYTE(temp, 1)]) << 16) ^ - (word32(Se[GETBYTE(temp, 0)]) << 8) ^ - Se[GETBYTE(temp, 3)] ^ - *(rc++); - rk[keylen/4+1] = rk[1] ^ rk[keylen/4]; - rk[keylen/4+2] = rk[2] ^ rk[keylen/4+1]; - rk[keylen/4+3] = rk[3] ^ rk[keylen/4+2]; - - if (rk + keylen/4 + 4 == m_key.end()) - break; - - if (keylen == 24) - { - rk[10] = rk[ 4] ^ rk[ 9]; - rk[11] = rk[ 5] ^ rk[10]; - } - else if (keylen == 32) - { - temp = rk[11]; - rk[12] = rk[ 4] ^ - (word32(Se[GETBYTE(temp, 3)]) << 24) ^ - (word32(Se[GETBYTE(temp, 2)]) << 16) ^ - (word32(Se[GETBYTE(temp, 1)]) << 8) ^ - Se[GETBYTE(temp, 0)]; - rk[13] = rk[ 5] ^ rk[12]; - rk[14] = rk[ 6] ^ rk[13]; - rk[15] = rk[ 7] ^ rk[14]; - } - rk += keylen/4; - } - - if (IsForwardTransformation()) - { - if (!s_TeFilled) - FillEncTable(); - } - else - { - if (!s_TdFilled) - FillDecTable(); - - unsigned int i, j; - rk = m_key; - - /* invert the order of the round keys: */ - for (i = 0, j = 4*m_rounds; i < j; i += 4, j -= 4) { - temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; - temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; - temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; - temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; - } - -#define InverseMixColumn(x) x = TL_M(Td, 0, Se[GETBYTE(x, 3)]) ^ TL_M(Td, 1, Se[GETBYTE(x, 2)]) ^ TL_M(Td, 2, Se[GETBYTE(x, 1)]) ^ TL_M(Td, 3, Se[GETBYTE(x, 0)]) - - /* apply the inverse MixColumn transform to all round keys but the first and the last: */ - for (i = 1; i < m_rounds; i++) { - rk += 4; - InverseMixColumn(rk[0]); - InverseMixColumn(rk[1]); - InverseMixColumn(rk[2]); - InverseMixColumn(rk[3]); - } - } - - ConditionalByteReverse(BIG_ENDIAN_ORDER, m_key.begin(), m_key.begin(), 16); - ConditionalByteReverse(BIG_ENDIAN_ORDER, m_key + m_rounds*4, m_key + m_rounds*4, 16); -} - -void Rijndael::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const -{ -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE) - if (HasSSE2()) - { - Rijndael::Enc::AdvancedProcessBlocks(inBlock, xorBlock, outBlock, 16, 0); - return; - } -#endif - - typedef BlockGetAndPut Block; - - word32 s0, s1, s2, s3, t0, t1, t2, t3; - Block::Get(inBlock)(s0)(s1)(s2)(s3); - - const word32 *rk = m_key; - s0 ^= rk[0]; - s1 ^= rk[1]; - s2 ^= rk[2]; - s3 ^= rk[3]; - t0 = rk[4]; - t1 = rk[5]; - t2 = rk[6]; - t3 = rk[7]; - rk += 8; - - // timing attack countermeasure. see comments at top for more details - const int cacheLineSize = GetCacheLineSize(); - unsigned int i; - word32 u = 0; -#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS - for (i=0; i<2048; i+=cacheLineSize) -#else - for (i=0; i<1024; i+=cacheLineSize) -#endif - u &= *(const word32 *)(((const byte *)Te)+i); - u &= Te[255]; - s0 |= u; s1 |= u; s2 |= u; s3 |= u; - - QUARTER_ROUND_FE(s3, t0, t1, t2, t3) - QUARTER_ROUND_FE(s2, t3, t0, t1, t2) - QUARTER_ROUND_FE(s1, t2, t3, t0, t1) - QUARTER_ROUND_FE(s0, t1, t2, t3, t0) - - // Nr - 2 full rounds: - unsigned int r = m_rounds/2 - 1; - do - { - s0 = rk[0]; s1 = rk[1]; s2 = rk[2]; s3 = rk[3]; - - QUARTER_ROUND_E(t3, s0, s1, s2, s3) - QUARTER_ROUND_E(t2, s3, s0, s1, s2) - QUARTER_ROUND_E(t1, s2, s3, s0, s1) - QUARTER_ROUND_E(t0, s1, s2, s3, s0) - - t0 = rk[4]; t1 = rk[5]; t2 = rk[6]; t3 = rk[7]; - - QUARTER_ROUND_E(s3, t0, t1, t2, t3) - QUARTER_ROUND_E(s2, t3, t0, t1, t2) - QUARTER_ROUND_E(s1, t2, t3, t0, t1) - QUARTER_ROUND_E(s0, t1, t2, t3, t0) - - rk += 8; - } while (--r); - - word32 tbw[4]; - byte *const tempBlock = (byte *)tbw; - - QUARTER_ROUND_LE(t2, 15, 2, 5, 8) - QUARTER_ROUND_LE(t1, 11, 14, 1, 4) - QUARTER_ROUND_LE(t0, 7, 10, 13, 0) - QUARTER_ROUND_LE(t3, 3, 6, 9, 12) - - Block::Put(xorBlock, outBlock)(tbw[0]^rk[0])(tbw[1]^rk[1])(tbw[2]^rk[2])(tbw[3]^rk[3]); -} - -void Rijndael::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const -{ - typedef BlockGetAndPut Block; - - word32 s0, s1, s2, s3, t0, t1, t2, t3; - Block::Get(inBlock)(s0)(s1)(s2)(s3); - - const word32 *rk = m_key; - s0 ^= rk[0]; - s1 ^= rk[1]; - s2 ^= rk[2]; - s3 ^= rk[3]; - t0 = rk[4]; - t1 = rk[5]; - t2 = rk[6]; - t3 = rk[7]; - rk += 8; - - // timing attack countermeasure. see comments at top for more details - const int cacheLineSize = GetCacheLineSize(); - unsigned int i; - word32 u = 0; -#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS - for (i=0; i<2048; i+=cacheLineSize) -#else - for (i=0; i<1024; i+=cacheLineSize) -#endif - u &= *(const word32 *)(((const byte *)Td)+i); - u &= Td[255]; - s0 |= u; s1 |= u; s2 |= u; s3 |= u; - - QUARTER_ROUND_FD(s3, t2, t1, t0, t3) - QUARTER_ROUND_FD(s2, t1, t0, t3, t2) - QUARTER_ROUND_FD(s1, t0, t3, t2, t1) - QUARTER_ROUND_FD(s0, t3, t2, t1, t0) - - // Nr - 2 full rounds: - unsigned int r = m_rounds/2 - 1; - do - { - s0 = rk[0]; s1 = rk[1]; s2 = rk[2]; s3 = rk[3]; - - QUARTER_ROUND_D(t3, s2, s1, s0, s3) - QUARTER_ROUND_D(t2, s1, s0, s3, s2) - QUARTER_ROUND_D(t1, s0, s3, s2, s1) - QUARTER_ROUND_D(t0, s3, s2, s1, s0) - - t0 = rk[4]; t1 = rk[5]; t2 = rk[6]; t3 = rk[7]; - - QUARTER_ROUND_D(s3, t2, t1, t0, t3) - QUARTER_ROUND_D(s2, t1, t0, t3, t2) - QUARTER_ROUND_D(s1, t0, t3, t2, t1) - QUARTER_ROUND_D(s0, t3, t2, t1, t0) - - rk += 8; - } while (--r); - -#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS - // timing attack countermeasure. see comments at top for more details - // If CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS is defined, - // QUARTER_ROUND_LD will use Td, which is already preloaded. - u = 0; - for (i=0; i<256; i+=cacheLineSize) - u &= *(const word32 *)(Sd+i); - u &= *(const word32 *)(Sd+252); - t0 |= u; t1 |= u; t2 |= u; t3 |= u; -#endif - - word32 tbw[4]; - byte *const tempBlock = (byte *)tbw; - - QUARTER_ROUND_LD(t2, 7, 2, 13, 8) - QUARTER_ROUND_LD(t1, 3, 14, 9, 4) - QUARTER_ROUND_LD(t0, 15, 10, 5, 0) - QUARTER_ROUND_LD(t3, 11, 6, 1, 12) - - Block::Put(xorBlock, outBlock)(tbw[0]^rk[0])(tbw[1]^rk[1])(tbw[2]^rk[2])(tbw[3]^rk[3]); -} - -// ************************* Assembly Code ************************************ - -#pragma warning(disable: 4731) // frame pointer register 'ebp' modified by inline assembly code - -#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM - -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE - -CRYPTOPP_NAKED void CRYPTOPP_FASTCALL Rijndael_Enc_AdvancedProcessBlocks(void *locals, const word32 *k) -{ -#if CRYPTOPP_BOOL_X86 - -#define L_REG esp -#define L_INDEX(i) (L_REG+768+i) -#define L_INXORBLOCKS L_INBLOCKS+4 -#define L_OUTXORBLOCKS L_INBLOCKS+8 -#define L_OUTBLOCKS L_INBLOCKS+12 -#define L_INCREMENTS L_INDEX(16*15) -#define L_SP L_INDEX(16*16) -#define L_LENGTH L_INDEX(16*16+4) -#define L_KEYS_BEGIN L_INDEX(16*16+8) - -#define MOVD movd -#define MM(i) mm##i - -#define MXOR(a,b,c) \ - AS2( movzx esi, b)\ - AS2( movd mm7, DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\ - AS2( pxor MM(a), mm7)\ - -#define MMOV(a,b,c) \ - AS2( movzx esi, b)\ - AS2( movd MM(a), DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\ - -#else - -#define L_REG r8 -#define L_INDEX(i) (L_REG+i) -#define L_INXORBLOCKS L_INBLOCKS+8 -#define L_OUTXORBLOCKS L_INBLOCKS+16 -#define L_OUTBLOCKS L_INBLOCKS+24 -#define L_INCREMENTS L_INDEX(16*16) -#define L_LENGTH L_INDEX(16*18+8) -#define L_KEYS_BEGIN L_INDEX(16*19) - -#define MOVD mov -#define MM_0 r9d -#define MM_1 r12d -#ifdef __GNUC__ -#define MM_2 r11d -#else -#define MM_2 r10d -#endif -#define MM(i) MM_##i - -#define MXOR(a,b,c) \ - AS2( movzx esi, b)\ - AS2( xor MM(a), DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\ - -#define MMOV(a,b,c) \ - AS2( movzx esi, b)\ - AS2( mov MM(a), DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\ - -#endif - -#define L_SUBKEYS L_INDEX(0) -#define L_SAVED_X L_SUBKEYS -#define L_KEY12 L_INDEX(16*12) -#define L_LASTROUND L_INDEX(16*13) -#define L_INBLOCKS L_INDEX(16*14) -#define MAP0TO4(i) (ASM_MOD(i+3,4)+1) - -#define XOR(a,b,c) \ - AS2( movzx esi, b)\ - AS2( xor a, DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\ - -#define MOV(a,b,c) \ - AS2( movzx esi, b)\ - AS2( mov a, DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\ - -#ifdef CRYPTOPP_GENERATE_X64_MASM - ALIGN 8 - Rijndael_Enc_AdvancedProcessBlocks PROC FRAME - rex_push_reg rsi - push_reg rdi - push_reg rbx - push_reg r12 - .endprolog - mov L_REG, rcx - mov AS_REG_7, ?Te@rdtable@CryptoPP@@3PA_KA - mov edi, DWORD PTR [?g_cacheLineSize@CryptoPP@@3IA] -#elif defined(__GNUC__) - __asm__ __volatile__ - ( - ".intel_syntax noprefix;" - #if CRYPTOPP_BOOL_X64 - AS2( mov L_REG, rcx) - #endif - AS_PUSH_IF86(bx) - AS_PUSH_IF86(bp) - AS2( mov AS_REG_7, WORD_REG(si)) -#else - AS_PUSH_IF86(si) - AS_PUSH_IF86(di) - AS_PUSH_IF86(bx) - AS_PUSH_IF86(bp) - AS2( lea AS_REG_7, [Te]) - AS2( mov edi, [g_cacheLineSize]) -#endif - -#if CRYPTOPP_BOOL_X86 - AS2( mov [ecx+16*12+16*4], esp) // save esp to L_SP - AS2( lea esp, [ecx-768]) -#endif - - // copy subkeys to stack - AS2( mov WORD_REG(si), [L_KEYS_BEGIN]) - AS2( mov WORD_REG(ax), 16) - AS2( and WORD_REG(ax), WORD_REG(si)) - AS2( movdqa xmm3, XMMWORD_PTR [WORD_REG(dx)+16+WORD_REG(ax)]) // subkey 1 (non-counter) or 2 (counter) - AS2( movdqa [L_KEY12], xmm3) - AS2( lea WORD_REG(ax), [WORD_REG(dx)+WORD_REG(ax)+2*16]) - AS2( sub WORD_REG(ax), WORD_REG(si)) - ASL(0) - AS2( movdqa xmm0, [WORD_REG(ax)+WORD_REG(si)]) - AS2( movdqa XMMWORD_PTR [L_SUBKEYS+WORD_REG(si)], xmm0) - AS2( add WORD_REG(si), 16) - AS2( cmp WORD_REG(si), 16*12) - ASJ( jl, 0, b) - - // read subkeys 0, 1 and last - AS2( movdqa xmm4, [WORD_REG(ax)+WORD_REG(si)]) // last subkey - AS2( movdqa xmm1, [WORD_REG(dx)]) // subkey 0 - AS2( MOVD MM(1), [WORD_REG(dx)+4*4]) // 0,1,2,3 - AS2( mov ebx, [WORD_REG(dx)+5*4]) // 4,5,6,7 - AS2( mov ecx, [WORD_REG(dx)+6*4]) // 8,9,10,11 - AS2( mov edx, [WORD_REG(dx)+7*4]) // 12,13,14,15 - - // load table into cache - AS2( xor WORD_REG(ax), WORD_REG(ax)) - ASL(9) - AS2( mov esi, [AS_REG_7+WORD_REG(ax)]) - AS2( add WORD_REG(ax), WORD_REG(di)) - AS2( mov esi, [AS_REG_7+WORD_REG(ax)]) - AS2( add WORD_REG(ax), WORD_REG(di)) - AS2( mov esi, [AS_REG_7+WORD_REG(ax)]) - AS2( add WORD_REG(ax), WORD_REG(di)) - AS2( mov esi, [AS_REG_7+WORD_REG(ax)]) - AS2( add WORD_REG(ax), WORD_REG(di)) - AS2( cmp WORD_REG(ax), 2048) - ASJ( jl, 9, b) - AS1( lfence) - - AS2( test DWORD PTR [L_LENGTH], 1) - ASJ( jz, 8, f) - - // counter mode one-time setup - AS2( mov WORD_REG(si), [L_INBLOCKS]) - AS2( movdqu xmm2, [WORD_REG(si)]) // counter - AS2( pxor xmm2, xmm1) - AS2( psrldq xmm1, 14) - AS2( movd eax, xmm1) - AS2( mov al, BYTE PTR [WORD_REG(si)+15]) - AS2( MOVD MM(2), eax) -#if CRYPTOPP_BOOL_X86 - AS2( mov eax, 1) - AS2( movd mm3, eax) -#endif - - // partial first round, in: xmm2(15,14,13,12;11,10,9,8;7,6,5,4;3,2,1,0), out: mm1, ebx, ecx, edx - AS2( movd eax, xmm2) - AS2( psrldq xmm2, 4) - AS2( movd edi, xmm2) - AS2( psrldq xmm2, 4) - MXOR( 1, al, 0) // 0 - XOR( edx, ah, 1) // 1 - AS2( shr eax, 16) - XOR( ecx, al, 2) // 2 - XOR( ebx, ah, 3) // 3 - AS2( mov eax, edi) - AS2( movd edi, xmm2) - AS2( psrldq xmm2, 4) - XOR( ebx, al, 0) // 4 - MXOR( 1, ah, 1) // 5 - AS2( shr eax, 16) - XOR( edx, al, 2) // 6 - XOR( ecx, ah, 3) // 7 - AS2( mov eax, edi) - AS2( movd edi, xmm2) - XOR( ecx, al, 0) // 8 - XOR( ebx, ah, 1) // 9 - AS2( shr eax, 16) - MXOR( 1, al, 2) // 10 - XOR( edx, ah, 3) // 11 - AS2( mov eax, edi) - XOR( edx, al, 0) // 12 - XOR( ecx, ah, 1) // 13 - AS2( shr eax, 16) - XOR( ebx, al, 2) // 14 - AS2( psrldq xmm2, 3) - - // partial second round, in: ebx(4,5,6,7), ecx(8,9,10,11), edx(12,13,14,15), out: eax, ebx, edi, mm0 - AS2( mov eax, [L_KEY12+0*4]) - AS2( mov edi, [L_KEY12+2*4]) - AS2( MOVD MM(0), [L_KEY12+3*4]) - MXOR( 0, cl, 3) /* 11 */ - XOR( edi, bl, 3) /* 7 */ - MXOR( 0, bh, 2) /* 6 */ - AS2( shr ebx, 16) /* 4,5 */ - XOR( eax, bl, 1) /* 5 */ - MOV( ebx, bh, 0) /* 4 */ - AS2( xor ebx, [L_KEY12+1*4]) - XOR( eax, ch, 2) /* 10 */ - AS2( shr ecx, 16) /* 8,9 */ - XOR( eax, dl, 3) /* 15 */ - XOR( ebx, dh, 2) /* 14 */ - AS2( shr edx, 16) /* 12,13 */ - XOR( edi, ch, 0) /* 8 */ - XOR( ebx, cl, 1) /* 9 */ - XOR( edi, dl, 1) /* 13 */ - MXOR( 0, dh, 0) /* 12 */ - - AS2( movd ecx, xmm2) - AS2( MOVD edx, MM(1)) - AS2( MOVD [L_SAVED_X+3*4], MM(0)) - AS2( mov [L_SAVED_X+0*4], eax) - AS2( mov [L_SAVED_X+1*4], ebx) - AS2( mov [L_SAVED_X+2*4], edi) - ASJ( jmp, 5, f) - - ASL(3) - // non-counter mode per-block setup - AS2( MOVD MM(1), [L_KEY12+0*4]) // 0,1,2,3 - AS2( mov ebx, [L_KEY12+1*4]) // 4,5,6,7 - AS2( mov ecx, [L_KEY12+2*4]) // 8,9,10,11 - AS2( mov edx, [L_KEY12+3*4]) // 12,13,14,15 - ASL(8) - AS2( mov WORD_REG(ax), [L_INBLOCKS]) - AS2( movdqu xmm2, [WORD_REG(ax)]) - AS2( mov WORD_REG(si), [L_INXORBLOCKS]) - AS2( movdqu xmm5, [WORD_REG(si)]) - AS2( pxor xmm2, xmm1) - AS2( pxor xmm2, xmm5) - - // first round, in: xmm2(15,14,13,12;11,10,9,8;7,6,5,4;3,2,1,0), out: eax, ebx, ecx, edx - AS2( movd eax, xmm2) - AS2( psrldq xmm2, 4) - AS2( movd edi, xmm2) - AS2( psrldq xmm2, 4) - MXOR( 1, al, 0) // 0 - XOR( edx, ah, 1) // 1 - AS2( shr eax, 16) - XOR( ecx, al, 2) // 2 - XOR( ebx, ah, 3) // 3 - AS2( mov eax, edi) - AS2( movd edi, xmm2) - AS2( psrldq xmm2, 4) - XOR( ebx, al, 0) // 4 - MXOR( 1, ah, 1) // 5 - AS2( shr eax, 16) - XOR( edx, al, 2) // 6 - XOR( ecx, ah, 3) // 7 - AS2( mov eax, edi) - AS2( movd edi, xmm2) - XOR( ecx, al, 0) // 8 - XOR( ebx, ah, 1) // 9 - AS2( shr eax, 16) - MXOR( 1, al, 2) // 10 - XOR( edx, ah, 3) // 11 - AS2( mov eax, edi) - XOR( edx, al, 0) // 12 - XOR( ecx, ah, 1) // 13 - AS2( shr eax, 16) - XOR( ebx, al, 2) // 14 - MXOR( 1, ah, 3) // 15 - AS2( MOVD eax, MM(1)) - - AS2( add L_REG, [L_KEYS_BEGIN]) - AS2( add L_REG, 4*16) - ASJ( jmp, 2, f) - - ASL(1) - // counter-mode per-block setup - AS2( MOVD ecx, MM(2)) - AS2( MOVD edx, MM(1)) - AS2( mov eax, [L_SAVED_X+0*4]) - AS2( mov ebx, [L_SAVED_X+1*4]) - AS2( xor cl, ch) - AS2( and WORD_REG(cx), 255) - ASL(5) -#if CRYPTOPP_BOOL_X86 - AS2( paddb MM(2), mm3) -#else - AS2( add MM(2), 1) -#endif - // remaining part of second round, in: edx(previous round),esi(keyed counter byte) eax,ebx,[L_SAVED_X+2*4],[L_SAVED_X+3*4], out: eax,ebx,ecx,edx - AS2( xor edx, DWORD PTR [AS_REG_7+WORD_REG(cx)*8+3]) - XOR( ebx, dl, 3) - MOV( ecx, dh, 2) - AS2( shr edx, 16) - AS2( xor ecx, [L_SAVED_X+2*4]) - XOR( eax, dh, 0) - MOV( edx, dl, 1) - AS2( xor edx, [L_SAVED_X+3*4]) - - AS2( add L_REG, [L_KEYS_BEGIN]) - AS2( add L_REG, 3*16) - ASJ( jmp, 4, f) - -// in: eax(0,1,2,3), ebx(4,5,6,7), ecx(8,9,10,11), edx(12,13,14,15) -// out: eax, ebx, edi, mm0 -#define ROUND() \ - MXOR( 0, cl, 3) /* 11 */\ - AS2( mov cl, al) /* 8,9,10,3 */\ - XOR( edi, ah, 2) /* 2 */\ - AS2( shr eax, 16) /* 0,1 */\ - XOR( edi, bl, 3) /* 7 */\ - MXOR( 0, bh, 2) /* 6 */\ - AS2( shr ebx, 16) /* 4,5 */\ - MXOR( 0, al, 1) /* 1 */\ - MOV( eax, ah, 0) /* 0 */\ - XOR( eax, bl, 1) /* 5 */\ - MOV( ebx, bh, 0) /* 4 */\ - XOR( eax, ch, 2) /* 10 */\ - XOR( ebx, cl, 3) /* 3 */\ - AS2( shr ecx, 16) /* 8,9 */\ - XOR( eax, dl, 3) /* 15 */\ - XOR( ebx, dh, 2) /* 14 */\ - AS2( shr edx, 16) /* 12,13 */\ - XOR( edi, ch, 0) /* 8 */\ - XOR( ebx, cl, 1) /* 9 */\ - XOR( edi, dl, 1) /* 13 */\ - MXOR( 0, dh, 0) /* 12 */\ - - ASL(2) // 2-round loop - AS2( MOVD MM(0), [L_SUBKEYS-4*16+3*4]) - AS2( mov edi, [L_SUBKEYS-4*16+2*4]) - ROUND() - AS2( mov ecx, edi) - AS2( xor eax, [L_SUBKEYS-4*16+0*4]) - AS2( xor ebx, [L_SUBKEYS-4*16+1*4]) - AS2( MOVD edx, MM(0)) - - ASL(4) - AS2( MOVD MM(0), [L_SUBKEYS-4*16+7*4]) - AS2( mov edi, [L_SUBKEYS-4*16+6*4]) - ROUND() - AS2( mov ecx, edi) - AS2( xor eax, [L_SUBKEYS-4*16+4*4]) - AS2( xor ebx, [L_SUBKEYS-4*16+5*4]) - AS2( MOVD edx, MM(0)) - - AS2( add L_REG, 32) - AS2( test L_REG, 255) - ASJ( jnz, 2, b) - AS2( sub L_REG, 16*16) - -#define LAST(a, b, c) \ - AS2( movzx esi, a )\ - AS2( movzx edi, BYTE PTR [AS_REG_7+WORD_REG(si)*8+1] )\ - AS2( movzx esi, b )\ - AS2( xor edi, DWORD PTR [AS_REG_7+WORD_REG(si)*8+0] )\ - AS2( mov WORD PTR [L_LASTROUND+c], di )\ - - // last round - LAST(ch, dl, 2) - LAST(dh, al, 6) - AS2( shr edx, 16) - LAST(ah, bl, 10) - AS2( shr eax, 16) - LAST(bh, cl, 14) - AS2( shr ebx, 16) - LAST(dh, al, 12) - AS2( shr ecx, 16) - LAST(ah, bl, 0) - LAST(bh, cl, 4) - LAST(ch, dl, 8) - - AS2( mov WORD_REG(ax), [L_OUTXORBLOCKS]) - AS2( mov WORD_REG(bx), [L_OUTBLOCKS]) - - AS2( mov WORD_REG(cx), [L_LENGTH]) - AS2( sub WORD_REG(cx), 16) - - AS2( movdqu xmm2, [WORD_REG(ax)]) - AS2( pxor xmm2, xmm4) - -#if CRYPTOPP_BOOL_X86 - AS2( movdqa xmm0, [L_INCREMENTS]) - AS2( paddd xmm0, [L_INBLOCKS]) - AS2( movdqa [L_INBLOCKS], xmm0) -#else - AS2( movdqa xmm0, [L_INCREMENTS+16]) - AS2( paddq xmm0, [L_INBLOCKS+16]) - AS2( movdqa [L_INBLOCKS+16], xmm0) -#endif - - AS2( pxor xmm2, [L_LASTROUND]) - AS2( movdqu [WORD_REG(bx)], xmm2) - - ASJ( jle, 7, f) - AS2( mov [L_LENGTH], WORD_REG(cx)) - AS2( test WORD_REG(cx), 1) - ASJ( jnz, 1, b) -#if CRYPTOPP_BOOL_X64 - AS2( movdqa xmm0, [L_INCREMENTS]) - AS2( paddq xmm0, [L_INBLOCKS]) - AS2( movdqa [L_INBLOCKS], xmm0) -#endif - ASJ( jmp, 3, b) - - ASL(7) - // erase keys on stack - AS2( xorps xmm0, xmm0) - AS2( lea WORD_REG(ax), [L_SUBKEYS+7*16]) - AS2( movaps [WORD_REG(ax)-7*16], xmm0) - AS2( movaps [WORD_REG(ax)-6*16], xmm0) - AS2( movaps [WORD_REG(ax)-5*16], xmm0) - AS2( movaps [WORD_REG(ax)-4*16], xmm0) - AS2( movaps [WORD_REG(ax)-3*16], xmm0) - AS2( movaps [WORD_REG(ax)-2*16], xmm0) - AS2( movaps [WORD_REG(ax)-1*16], xmm0) - AS2( movaps [WORD_REG(ax)+0*16], xmm0) - AS2( movaps [WORD_REG(ax)+1*16], xmm0) - AS2( movaps [WORD_REG(ax)+2*16], xmm0) - AS2( movaps [WORD_REG(ax)+3*16], xmm0) - AS2( movaps [WORD_REG(ax)+4*16], xmm0) - AS2( movaps [WORD_REG(ax)+5*16], xmm0) - AS2( movaps [WORD_REG(ax)+6*16], xmm0) -#if CRYPTOPP_BOOL_X86 - AS2( mov esp, [L_SP]) - AS1( emms) -#endif - AS_POP_IF86(bp) - AS_POP_IF86(bx) -#if defined(_MSC_VER) && CRYPTOPP_BOOL_X86 - AS_POP_IF86(di) - AS_POP_IF86(si) - AS1(ret) -#endif -#ifdef CRYPTOPP_GENERATE_X64_MASM - pop r12 - pop rbx - pop rdi - pop rsi - ret - Rijndael_Enc_AdvancedProcessBlocks ENDP -#endif -#ifdef __GNUC__ - ".att_syntax prefix;" - : - : "c" (locals), "d" (k), "S" (Te), "D" (g_cacheLineSize) - : "memory", "cc", "%eax" - #if CRYPTOPP_BOOL_X64 - , "%rbx", "%r8", "%r9", "%r10", "%r11", "%r12" - #endif - ); -#endif -} - -#endif - -#ifndef CRYPTOPP_GENERATE_X64_MASM - -#ifdef CRYPTOPP_X64_MASM_AVAILABLE -extern "C" { -void Rijndael_Enc_AdvancedProcessBlocks(void *locals, const word32 *k); -} -#endif - -#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86 - -static inline bool AliasedWithTable(const byte *begin, const byte *end) -{ - size_t s0 = size_t(begin)%4096, s1 = size_t(end)%4096; - size_t t0 = size_t(Te)%4096, t1 = (size_t(Te)+sizeof(Te))%4096; - if (t1 > t0) - return (s0 >= t0 && s0 < t1) || (s1 > t0 && s1 <= t1); - else - return (s0 < t1 || s1 <= t1) || (s0 >= t0 || s1 > t0); -} - -size_t Rijndael::Enc::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const -{ -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE) - if (length < BLOCKSIZE) - return length; - - if (HasSSE2()) - { - struct Locals - { - word32 subkeys[4*12], workspace[8]; - const byte *inBlocks, *inXorBlocks, *outXorBlocks; - byte *outBlocks; - size_t inIncrement, inXorIncrement, outXorIncrement, outIncrement; - size_t regSpill, lengthAndCounterFlag, keysBegin; - }; - - size_t increment = BLOCKSIZE; - const byte* zeros = (byte *)(Te+256); - byte *space; - - do { - space = (byte *)alloca(255+sizeof(Locals)); - space += (256-(size_t)space%256)%256; - } - while (AliasedWithTable(space, space+sizeof(Locals))); - - if (flags & BT_ReverseDirection) - { - assert(length % BLOCKSIZE == 0); - inBlocks += length - BLOCKSIZE; - xorBlocks += length - BLOCKSIZE; - outBlocks += length - BLOCKSIZE; - increment = 0-increment; - } - - Locals &locals = *(Locals *)space; - - locals.inBlocks = inBlocks; - locals.inXorBlocks = (flags & BT_XorInput) && xorBlocks ? xorBlocks : zeros; - locals.outXorBlocks = (flags & BT_XorInput) || !xorBlocks ? zeros : xorBlocks; - locals.outBlocks = outBlocks; - - locals.inIncrement = (flags & BT_DontIncrementInOutPointers) ? 0 : increment; - locals.inXorIncrement = (flags & BT_XorInput) && xorBlocks ? increment : 0; - locals.outXorIncrement = (flags & BT_XorInput) || !xorBlocks ? 0 : increment; - locals.outIncrement = (flags & BT_DontIncrementInOutPointers) ? 0 : increment; - - locals.lengthAndCounterFlag = length - (length%16) - bool(flags & BT_InBlockIsCounter); - int keysToCopy = m_rounds - (flags & BT_InBlockIsCounter ? 3 : 2); - locals.keysBegin = (12-keysToCopy)*16; - - Rijndael_Enc_AdvancedProcessBlocks(&locals, m_key); - return length%16; - } - else -#endif - return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags); -} - -#endif - -NAMESPACE_END - -#endif -#endif diff --git a/embeddedcryptopp/rijndael.h b/embeddedcryptopp/rijndael.h deleted file mode 100644 index d602186..0000000 --- a/embeddedcryptopp/rijndael.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef CRYPTOPP_RIJNDAEL_H -#define CRYPTOPP_RIJNDAEL_H - -/** \file -*/ - -#include "seckey.h" -#include "secblock.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! _ -struct Rijndael_Info : public FixedBlockSize<16>, public VariableKeyLength<16, 16, 32, 8> -{ - CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return CRYPTOPP_RIJNDAEL_NAME;} -}; - -/// Rijndael -class CRYPTOPP_DLL Rijndael : public Rijndael_Info, public BlockCipherDocumentation -{ - class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl - { - public: - void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); - - protected: - static void FillEncTable(); - static void FillDecTable(); - - // VS2005 workaround: have to put these on seperate lines, or error C2487 is triggered in DLL build - static const byte Se[256]; - static const byte Sd[256]; - - static const word32 rcon[]; - - unsigned int m_rounds; - FixedSizeAlignedSecBlock m_key; - }; - - class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Enc : public Base - { - public: - void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; -#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86 - size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const; -#endif - }; - - class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Dec : public Base - { - public: - void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; - }; - -public: - typedef BlockCipherFinal Encryption; - typedef BlockCipherFinal Decryption; -}; - -typedef Rijndael::Encryption RijndaelEncryption; -typedef Rijndael::Decryption RijndaelDecryption; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/rng.cpp b/embeddedcryptopp/rng.cpp deleted file mode 100644 index 6ddbc50..0000000 --- a/embeddedcryptopp/rng.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// rng.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#include "rng.h" -#include "fips140.h" - -#include - -NAMESPACE_BEGIN(CryptoPP) - -// linear congruential generator -// originally by William S. England - -// do not use for cryptographic purposes - -/* -** Original_numbers are the original published m and q in the -** ACM article above. John Burton has furnished numbers for -** a reportedly better generator. The new numbers are now -** used in this program by default. -*/ - -#ifndef LCRNG_ORIGINAL_NUMBERS -const word32 LC_RNG::m=2147483647L; -const word32 LC_RNG::q=44488L; - -const word16 LC_RNG::a=(unsigned int)48271L; -const word16 LC_RNG::r=3399; -#else -const word32 LC_RNG::m=2147483647L; -const word32 LC_RNG::q=127773L; - -const word16 LC_RNG::a=16807; -const word16 LC_RNG::r=2836; -#endif - -void LC_RNG::GenerateBlock(byte *output, size_t size) -{ - while (size--) - { - word32 hi = seed/q; - word32 lo = seed%q; - - long test = a*lo - r*hi; - - if (test > 0) - seed = test; - else - seed = test+ m; - - *output++ = (GETBYTE(seed, 0) ^ GETBYTE(seed, 1) ^ GETBYTE(seed, 2) ^ GETBYTE(seed, 3)); - } -} - -// ******************************************************** - -#ifndef CRYPTOPP_IMPORTS - -X917RNG::X917RNG(BlockTransformation *c, const byte *seed, const byte *deterministicTimeVector) - : cipher(c), - S(cipher->BlockSize()), - dtbuf(S), - randseed(seed, S), - m_lastBlock(S), - m_deterministicTimeVector(deterministicTimeVector, deterministicTimeVector ? S : 0) -{ - assert (deterministicTimeVector); - - // for FIPS 140-2 - GenerateBlock(m_lastBlock, S); -} - -void X917RNG::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size) -{ - while (size > 0) - { - // calculate new enciphered timestamp - if (m_deterministicTimeVector.size()) - { - cipher->ProcessBlock(m_deterministicTimeVector, dtbuf); - IncrementCounterByOne(m_deterministicTimeVector, S); - } - else - { - assert(false); - } - - // combine enciphered timestamp with seed - xorbuf(randseed, dtbuf, S); - - // generate a new block of random bytes - cipher->ProcessBlock(randseed); - if (memcmp(m_lastBlock, randseed, S) == 0) - throw SelfTestFailure("X917RNG: Continuous random number generator test failed."); - - // output random bytes - size_t len = UnsignedMin(S, size); - target.ChannelPut(channel, randseed, len); - size -= len; - - // compute new seed vector - memcpy(m_lastBlock, randseed, S); - xorbuf(randseed, dtbuf, S); - cipher->ProcessBlock(randseed); - } -} - -#endif - -MaurerRandomnessTest::MaurerRandomnessTest() - : sum(0.0), n(0) -{ - for (unsigned i=0; i= Q) - sum += log(double(n - tab[inByte])); - tab[inByte] = n; - n++; - } - return 0; -} - -double MaurerRandomnessTest::GetTestValue() const -{ - if (BytesNeeded() > 0) - throw Exception(Exception::OTHER_ERROR, "MaurerRandomnessTest: " + IntToString(BytesNeeded()) + " more bytes of input needed"); - - double fTu = (sum/(n-Q))/log(2.0); // this is the test value defined by Maurer - - double value = fTu * 0.1392; // arbitrarily normalize it to - return value > 1.0 ? 1.0 : value; // a number between 0 and 1 -} - -NAMESPACE_END diff --git a/embeddedcryptopp/rng.h b/embeddedcryptopp/rng.h deleted file mode 100644 index 2439dee..0000000 --- a/embeddedcryptopp/rng.h +++ /dev/null @@ -1,77 +0,0 @@ -// rng.h - misc RNG related classes, see also osrng.h, randpool.h - -#ifndef CRYPTOPP_RNG_H -#define CRYPTOPP_RNG_H - -#include "cryptlib.h" -#include "filters.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! linear congruential generator -/*! originally by William S. England, do not use for cryptographic purposes */ -class LC_RNG : public RandomNumberGenerator -{ -public: - LC_RNG(word32 init_seed) - : seed(init_seed) {} - - void GenerateBlock(byte *output, size_t size); - - word32 GetSeed() {return seed;} - -private: - word32 seed; - - static const word32 m; - static const word32 q; - static const word16 a; - static const word16 r; -}; - -//! RNG derived from ANSI X9.17 Appendix C - -class CRYPTOPP_DLL X917RNG : public RandomNumberGenerator, public NotCopyable -{ -public: - // cipher will be deleted by destructor, deterministicTimeVector = 0 means obtain time vector from system - X917RNG(BlockTransformation *cipher, const byte *seed, const byte *deterministicTimeVector = 0); - - void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size); - -private: - member_ptr cipher; - unsigned int S; // blocksize of cipher - SecByteBlock dtbuf; // buffer for enciphered timestamp - SecByteBlock randseed, m_lastBlock, m_deterministicTimeVector; -}; - -/** This class implements Maurer's Universal Statistical Test for Random Bit Generators - it is intended for measuring the randomness of *PHYSICAL* RNGs. - For more details see his paper in Journal of Cryptology, 1992. */ - -class MaurerRandomnessTest : public Bufferless -{ -public: - MaurerRandomnessTest(); - - size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking); - - // BytesNeeded() returns how many more bytes of input is needed by the test - // GetTestValue() should not be called before BytesNeeded()==0 - unsigned int BytesNeeded() const {return n >= (Q+K) ? 0 : Q+K-n;} - - // returns a number between 0.0 and 1.0, describing the quality of the - // random numbers entered - double GetTestValue() const; - -private: - enum {L=8, V=256, Q=2000, K=2000}; - double sum; - unsigned int n; - unsigned int tab[V]; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/rsa.cpp b/embeddedcryptopp/rsa.cpp deleted file mode 100644 index 59449c4..0000000 --- a/embeddedcryptopp/rsa.cpp +++ /dev/null @@ -1,304 +0,0 @@ -// rsa.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" -#include "rsa.h" -#include "asn.h" -#include "oids.h" -#include "modarith.h" -#include "nbtheory.h" -#include "sha.h" -#include "algparam.h" -#include "fips140.h" - -#if !defined(NDEBUG) && !defined(CRYPTOPP_IS_DLL) -#include "pssr.h" -NAMESPACE_BEGIN(CryptoPP) -void RSA_TestInstantiations() -{ - RSASS::Verifier x1(1, 1); - RSASS::Signer x2(NullRNG(), 1); - RSASS::Verifier x3(x2); - RSASS::Verifier x4(x2.GetKey()); - RSASS::Verifier x5(x3); -#ifndef __MWERKS__ - RSASS::Signer x6 = x2; - x3 = x2; - x6 = x2; -#endif - RSAES::Encryptor x7(x2); -#ifndef __GNUC__ - RSAES::Encryptor x8(x3); -#endif - RSAES >::Encryptor x9(x2); - - x4 = x2.GetKey(); -} -NAMESPACE_END -#endif - -#ifndef CRYPTOPP_IMPORTS - -NAMESPACE_BEGIN(CryptoPP) - -OID RSAFunction::GetAlgorithmID() const -{ - return ASN1::rsaEncryption(); -} - -void RSAFunction::BERDecodePublicKey(BufferedTransformation &bt, bool, size_t) -{ - BERSequenceDecoder seq(bt); - m_n.BERDecode(seq); - m_e.BERDecode(seq); - seq.MessageEnd(); -} - -void RSAFunction::DEREncodePublicKey(BufferedTransformation &bt) const -{ - DERSequenceEncoder seq(bt); - m_n.DEREncode(seq); - m_e.DEREncode(seq); - seq.MessageEnd(); -} - -Integer RSAFunction::ApplyFunction(const Integer &x) const -{ - DoQuickSanityCheck(); - return a_exp_b_mod_c(x, m_e, m_n); -} - -bool RSAFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const -{ - bool pass = true; - pass = pass && m_n > Integer::One() && m_n.IsOdd(); - pass = pass && m_e > Integer::One() && m_e.IsOdd() && m_e < m_n; - return pass; -} - -bool RSAFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const -{ - return GetValueHelper(this, name, valueType, pValue).Assignable() - CRYPTOPP_GET_FUNCTION_ENTRY(Modulus) - CRYPTOPP_GET_FUNCTION_ENTRY(PublicExponent) - ; -} - -void RSAFunction::AssignFrom(const NameValuePairs &source) -{ - AssignFromHelper(this, source) - CRYPTOPP_SET_FUNCTION_ENTRY(Modulus) - CRYPTOPP_SET_FUNCTION_ENTRY(PublicExponent) - ; -} - -// ***************************************************************************** - -class RSAPrimeSelector : public PrimeSelector -{ -public: - RSAPrimeSelector(const Integer &e) : m_e(e) {} - bool IsAcceptable(const Integer &candidate) const {return RelativelyPrime(m_e, candidate-Integer::One());} - Integer m_e; -}; - -void InvertibleRSAFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg) -{ - int modulusSize = 2048; - alg.GetIntValue(Name::ModulusSize(), modulusSize) || alg.GetIntValue(Name::KeySize(), modulusSize); - - if (modulusSize < 16) - throw InvalidArgument("InvertibleRSAFunction: specified modulus size is too small"); - - m_e = alg.GetValueWithDefault(Name::PublicExponent(), Integer(17)); - - if (m_e < 3 || m_e.IsEven()) - throw InvalidArgument("InvertibleRSAFunction: invalid public exponent"); - - RSAPrimeSelector selector(m_e); - AlgorithmParameters primeParam = MakeParametersForTwoPrimesOfEqualSize(modulusSize) - (Name::PointerToPrimeSelector(), selector.GetSelectorPointer()); - m_p.GenerateRandom(rng, primeParam); - m_q.GenerateRandom(rng, primeParam); - - m_d = m_e.InverseMod(LCM(m_p-1, m_q-1)); - assert(m_d.IsPositive()); - - m_dp = m_d % (m_p-1); - m_dq = m_d % (m_q-1); - m_n = m_p * m_q; - m_u = m_q.InverseMod(m_p); - - if (FIPS_140_2_ComplianceEnabled()) - { - RSASS::Signer signer(*this); - RSASS::Verifier verifier(signer); - SignaturePairwiseConsistencyTest_FIPS_140_Only(signer, verifier); - - RSAES >::Decryptor decryptor(*this); - RSAES >::Encryptor encryptor(decryptor); - EncryptionPairwiseConsistencyTest_FIPS_140_Only(encryptor, decryptor); - } -} - -void InvertibleRSAFunction::Initialize(RandomNumberGenerator &rng, unsigned int keybits, const Integer &e) -{ - GenerateRandom(rng, MakeParameters(Name::ModulusSize(), (int)keybits)(Name::PublicExponent(), e+e.IsEven())); -} - -void InvertibleRSAFunction::Initialize(const Integer &n, const Integer &e, const Integer &d) -{ - if (n.IsEven() || e.IsEven() | d.IsEven()) - throw InvalidArgument("InvertibleRSAFunction: input is not a valid RSA private key"); - - m_n = n; - m_e = e; - m_d = d; - - Integer r = --(d*e); - unsigned int s = 0; - while (r.IsEven()) - { - r >>= 1; - s++; - } - - ModularArithmetic modn(n); - for (Integer i = 2; ; ++i) - { - Integer a = modn.Exponentiate(i, r); - if (a == 1) - continue; - Integer b; - unsigned int j = 0; - while (a != n-1) - { - b = modn.Square(a); - if (b == 1) - { - m_p = GCD(a-1, n); - m_q = n/m_p; - m_dp = m_d % (m_p-1); - m_dq = m_d % (m_q-1); - m_u = m_q.InverseMod(m_p); - return; - } - if (++j == s) - throw InvalidArgument("InvertibleRSAFunction: input is not a valid RSA private key"); - a = b; - } - } -} - -void InvertibleRSAFunction::BERDecodePrivateKey(BufferedTransformation &bt, bool, size_t) -{ - BERSequenceDecoder privateKey(bt); - word32 version; - BERDecodeUnsigned(privateKey, version, INTEGER, 0, 0); // check version - m_n.BERDecode(privateKey); - m_e.BERDecode(privateKey); - m_d.BERDecode(privateKey); - m_p.BERDecode(privateKey); - m_q.BERDecode(privateKey); - m_dp.BERDecode(privateKey); - m_dq.BERDecode(privateKey); - m_u.BERDecode(privateKey); - privateKey.MessageEnd(); -} - -void InvertibleRSAFunction::DEREncodePrivateKey(BufferedTransformation &bt) const -{ - DERSequenceEncoder privateKey(bt); - DEREncodeUnsigned(privateKey, 0); // version - m_n.DEREncode(privateKey); - m_e.DEREncode(privateKey); - m_d.DEREncode(privateKey); - m_p.DEREncode(privateKey); - m_q.DEREncode(privateKey); - m_dp.DEREncode(privateKey); - m_dq.DEREncode(privateKey); - m_u.DEREncode(privateKey); - privateKey.MessageEnd(); -} - -Integer InvertibleRSAFunction::CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const -{ - DoQuickSanityCheck(); - ModularArithmetic modn(m_n); - Integer r, rInv; - do { // do this in a loop for people using small numbers for testing - r.Randomize(rng, Integer::One(), m_n - Integer::One()); - rInv = modn.MultiplicativeInverse(r); - } while (rInv.IsZero()); - Integer re = modn.Exponentiate(r, m_e); - re = modn.Multiply(re, x); // blind - // here we follow the notation of PKCS #1 and let u=q inverse mod p - // but in ModRoot, u=p inverse mod q, so we reverse the order of p and q - Integer y = ModularRoot(re, m_dq, m_dp, m_q, m_p, m_u); - y = modn.Multiply(y, rInv); // unblind - if (modn.Exponentiate(y, m_e) != x) // check - throw Exception(Exception::OTHER_ERROR, "InvertibleRSAFunction: computational error during private key operation"); - return y; -} - -bool InvertibleRSAFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const -{ - bool pass = RSAFunction::Validate(rng, level); - pass = pass && m_p > Integer::One() && m_p.IsOdd() && m_p < m_n; - pass = pass && m_q > Integer::One() && m_q.IsOdd() && m_q < m_n; - pass = pass && m_d > Integer::One() && m_d.IsOdd() && m_d < m_n; - pass = pass && m_dp > Integer::One() && m_dp.IsOdd() && m_dp < m_p; - pass = pass && m_dq > Integer::One() && m_dq.IsOdd() && m_dq < m_q; - pass = pass && m_u.IsPositive() && m_u < m_p; - if (level >= 1) - { - pass = pass && m_p * m_q == m_n; - pass = pass && m_e*m_d % LCM(m_p-1, m_q-1) == 1; - pass = pass && m_dp == m_d%(m_p-1) && m_dq == m_d%(m_q-1); - pass = pass && m_u * m_q % m_p == 1; - } - if (level >= 2) - pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2); - return pass; -} - -bool InvertibleRSAFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const -{ - return GetValueHelper(this, name, valueType, pValue).Assignable() - CRYPTOPP_GET_FUNCTION_ENTRY(Prime1) - CRYPTOPP_GET_FUNCTION_ENTRY(Prime2) - CRYPTOPP_GET_FUNCTION_ENTRY(PrivateExponent) - CRYPTOPP_GET_FUNCTION_ENTRY(ModPrime1PrivateExponent) - CRYPTOPP_GET_FUNCTION_ENTRY(ModPrime2PrivateExponent) - CRYPTOPP_GET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1) - ; -} - -void InvertibleRSAFunction::AssignFrom(const NameValuePairs &source) -{ - AssignFromHelper(this, source) - CRYPTOPP_SET_FUNCTION_ENTRY(Prime1) - CRYPTOPP_SET_FUNCTION_ENTRY(Prime2) - CRYPTOPP_SET_FUNCTION_ENTRY(PrivateExponent) - CRYPTOPP_SET_FUNCTION_ENTRY(ModPrime1PrivateExponent) - CRYPTOPP_SET_FUNCTION_ENTRY(ModPrime2PrivateExponent) - CRYPTOPP_SET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1) - ; -} - -// ***************************************************************************** - -Integer RSAFunction_ISO::ApplyFunction(const Integer &x) const -{ - Integer t = RSAFunction::ApplyFunction(x); - return t % 16 == 12 ? t : m_n - t; -} - -Integer InvertibleRSAFunction_ISO::CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const -{ - Integer t = InvertibleRSAFunction::CalculateInverse(rng, x); - return STDMIN(t, m_n-t); -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/rsa.h b/embeddedcryptopp/rsa.h deleted file mode 100644 index 6a8b185..0000000 --- a/embeddedcryptopp/rsa.h +++ /dev/null @@ -1,174 +0,0 @@ -#ifndef CRYPTOPP_RSA_H -#define CRYPTOPP_RSA_H - -/** \file - This file contains classes that implement the RSA - ciphers and signature schemes as defined in PKCS #1 v2.0. -*/ - -#include "pubkey.h" -#include "asn.h" -#include "pkcspad.h" -#include "oaep.h" -#include "emsa2.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! _ -class CRYPTOPP_DLL RSAFunction : public TrapdoorFunction, public X509PublicKey -{ - typedef RSAFunction ThisClass; - -public: - void Initialize(const Integer &n, const Integer &e) - {m_n = n; m_e = e;} - - // X509PublicKey - OID GetAlgorithmID() const; - void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size); - void DEREncodePublicKey(BufferedTransformation &bt) const; - - // CryptoMaterial - bool Validate(RandomNumberGenerator &rng, unsigned int level) const; - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; - void AssignFrom(const NameValuePairs &source); - - // TrapdoorFunction - Integer ApplyFunction(const Integer &x) const; - Integer PreimageBound() const {return m_n;} - Integer ImageBound() const {return m_n;} - - // non-derived - const Integer & GetModulus() const {return m_n;} - const Integer & GetPublicExponent() const {return m_e;} - - void SetModulus(const Integer &n) {m_n = n;} - void SetPublicExponent(const Integer &e) {m_e = e;} - -protected: - Integer m_n, m_e; -}; - -//! _ -class CRYPTOPP_DLL InvertibleRSAFunction : public RSAFunction, public TrapdoorFunctionInverse, public PKCS8PrivateKey -{ - typedef InvertibleRSAFunction ThisClass; - -public: - void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits, const Integer &e = 17); - void Initialize(const Integer &n, const Integer &e, const Integer &d, const Integer &p, const Integer &q, const Integer &dp, const Integer &dq, const Integer &u) - {m_n = n; m_e = e; m_d = d; m_p = p; m_q = q; m_dp = dp; m_dq = dq; m_u = u;} - //! factor n given private exponent - void Initialize(const Integer &n, const Integer &e, const Integer &d); - - // PKCS8PrivateKey - void BERDecode(BufferedTransformation &bt) - {PKCS8PrivateKey::BERDecode(bt);} - void DEREncode(BufferedTransformation &bt) const - {PKCS8PrivateKey::DEREncode(bt);} - void Load(BufferedTransformation &bt) - {PKCS8PrivateKey::BERDecode(bt);} - void Save(BufferedTransformation &bt) const - {PKCS8PrivateKey::DEREncode(bt);} - OID GetAlgorithmID() const {return RSAFunction::GetAlgorithmID();} - void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size); - void DEREncodePrivateKey(BufferedTransformation &bt) const; - - // TrapdoorFunctionInverse - Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const; - - // GeneratableCryptoMaterial - bool Validate(RandomNumberGenerator &rng, unsigned int level) const; - /*! parameters: (ModulusSize, PublicExponent (default 17)) */ - void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg); - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; - void AssignFrom(const NameValuePairs &source); - - // non-derived interface - const Integer& GetPrime1() const {return m_p;} - const Integer& GetPrime2() const {return m_q;} - const Integer& GetPrivateExponent() const {return m_d;} - const Integer& GetModPrime1PrivateExponent() const {return m_dp;} - const Integer& GetModPrime2PrivateExponent() const {return m_dq;} - const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const {return m_u;} - - void SetPrime1(const Integer &p) {m_p = p;} - void SetPrime2(const Integer &q) {m_q = q;} - void SetPrivateExponent(const Integer &d) {m_d = d;} - void SetModPrime1PrivateExponent(const Integer &dp) {m_dp = dp;} - void SetModPrime2PrivateExponent(const Integer &dq) {m_dq = dq;} - void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer &u) {m_u = u;} - -protected: - Integer m_d, m_p, m_q, m_dp, m_dq, m_u; -}; - -class CRYPTOPP_DLL RSAFunction_ISO : public RSAFunction -{ -public: - Integer ApplyFunction(const Integer &x) const; - Integer PreimageBound() const {return ++(m_n>>1);} -}; - -class CRYPTOPP_DLL InvertibleRSAFunction_ISO : public InvertibleRSAFunction -{ -public: - Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const; - Integer PreimageBound() const {return ++(m_n>>1);} -}; - -//! RSA -struct CRYPTOPP_DLL RSA -{ - static const char * CRYPTOPP_API StaticAlgorithmName() {return "RSA";} - typedef RSAFunction PublicKey; - typedef InvertibleRSAFunction PrivateKey; -}; - -//! RSA cryptosystem -template -struct RSAES : public TF_ES -{ -}; - -//! RSA signature scheme with appendix -/*! See documentation of PKCS1v15 for a list of hash functions that can be used with it. */ -template -struct RSASS : public TF_SS -{ -}; - -struct CRYPTOPP_DLL RSA_ISO -{ - static const char * CRYPTOPP_API StaticAlgorithmName() {return "RSA-ISO";} - typedef RSAFunction_ISO PublicKey; - typedef InvertibleRSAFunction_ISO PrivateKey; -}; - -template -struct RSASS_ISO : public TF_SS -{ -}; - -// The two RSA encryption schemes defined in PKCS #1 v2.0 -typedef RSAES::Decryptor RSAES_PKCS1v15_Decryptor; -typedef RSAES::Encryptor RSAES_PKCS1v15_Encryptor; - -typedef RSAES >::Decryptor RSAES_OAEP_SHA_Decryptor; -typedef RSAES >::Encryptor RSAES_OAEP_SHA_Encryptor; - -// The three RSA signature schemes defined in PKCS #1 v2.0 -typedef RSASS::Signer RSASSA_PKCS1v15_SHA_Signer; -typedef RSASS::Verifier RSASSA_PKCS1v15_SHA_Verifier; - -namespace Weak { -typedef RSASS::Signer RSASSA_PKCS1v15_MD2_Signer; -typedef RSASS::Verifier RSASSA_PKCS1v15_MD2_Verifier; - -typedef RSASS::Signer RSASSA_PKCS1v15_MD5_Signer; -typedef RSASS::Verifier RSASSA_PKCS1v15_MD5_Verifier; -} - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/rw.h b/embeddedcryptopp/rw.h deleted file mode 100644 index ec8b850..0000000 --- a/embeddedcryptopp/rw.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef CRYPTOPP_RW_H -#define CRYPTOPP_RW_H - -/** \file - This file contains classes that implement the - Rabin-Williams signature schemes as defined in IEEE P1363. -*/ - -#include "pubkey.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! _ -class CRYPTOPP_DLL RWFunction : public TrapdoorFunction, public PublicKey -{ - typedef RWFunction ThisClass; - -public: - void Initialize(const Integer &n) - {m_n = n;} - - void BERDecode(BufferedTransformation &bt); - void DEREncode(BufferedTransformation &bt) const; - - Integer ApplyFunction(const Integer &x) const; - Integer PreimageBound() const {return ++(m_n>>1);} - Integer ImageBound() const {return m_n;} - - bool Validate(RandomNumberGenerator &rng, unsigned int level) const; - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; - void AssignFrom(const NameValuePairs &source); - - const Integer& GetModulus() const {return m_n;} - void SetModulus(const Integer &n) {m_n = n;} - -protected: - Integer m_n; -}; - -//! _ -class CRYPTOPP_DLL InvertibleRWFunction : public RWFunction, public TrapdoorFunctionInverse, public PrivateKey -{ - typedef InvertibleRWFunction ThisClass; - -public: - void Initialize(const Integer &n, const Integer &p, const Integer &q, const Integer &u) - {m_n = n; m_p = p; m_q = q; m_u = u;} - // generate a random private key - void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits) - {GenerateRandomWithKeySize(rng, modulusBits);} - - void BERDecode(BufferedTransformation &bt); - void DEREncode(BufferedTransformation &bt) const; - - Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const; - - // GeneratibleCryptoMaterial - bool Validate(RandomNumberGenerator &rng, unsigned int level) const; - bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; - void AssignFrom(const NameValuePairs &source); - /*! parameters: (ModulusSize) */ - void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg); - - const Integer& GetPrime1() const {return m_p;} - const Integer& GetPrime2() const {return m_q;} - const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const {return m_u;} - - void SetPrime1(const Integer &p) {m_p = p;} - void SetPrime2(const Integer &q) {m_q = q;} - void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer &u) {m_u = u;} - -protected: - Integer m_p, m_q, m_u; -}; - -//! RW -struct RW -{ - static std::string StaticAlgorithmName() {return "RW";} - typedef RWFunction PublicKey; - typedef InvertibleRWFunction PrivateKey; -}; - -//! RWSS -template -struct RWSS : public TF_SS -{ -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/secblock.h b/embeddedcryptopp/secblock.h deleted file mode 100644 index d66470e..0000000 --- a/embeddedcryptopp/secblock.h +++ /dev/null @@ -1,500 +0,0 @@ -// secblock.h - written and placed in the public domain by Wei Dai - -#ifndef CRYPTOPP_SECBLOCK_H -#define CRYPTOPP_SECBLOCK_H - -#include "config.h" -#include "misc.h" -#include - -#if defined(CRYPTOPP_MEMALIGN_AVAILABLE) || defined(CRYPTOPP_MM_MALLOC_AVAILABLE) || defined(QNX) - #include -#else - #include -#endif - -NAMESPACE_BEGIN(CryptoPP) - -// ************** secure memory allocation *************** - -template -class AllocatorBase -{ -public: - typedef T value_type; - typedef size_t size_type; -#ifdef CRYPTOPP_MSVCRT6 - typedef ptrdiff_t difference_type; -#else - typedef std::ptrdiff_t difference_type; -#endif - typedef T * pointer; - typedef const T * const_pointer; - typedef T & reference; - typedef const T & const_reference; - - pointer address(reference r) const {return (&r);} - const_pointer address(const_reference r) const {return (&r); } - void construct(pointer p, const T& val) {new (p) T(val);} - void destroy(pointer p) {p->~T();} - size_type max_size() const {return ~size_type(0)/sizeof(T);} // switch to std::numeric_limits::max later - -protected: - static void CheckSize(size_t n) - { - if (n > ~size_t(0) / sizeof(T)) - throw InvalidArgument("AllocatorBase: requested size would cause integer overflow"); - } -}; - -#define CRYPTOPP_INHERIT_ALLOCATOR_TYPES \ -typedef typename AllocatorBase::value_type value_type;\ -typedef typename AllocatorBase::size_type size_type;\ -typedef typename AllocatorBase::difference_type difference_type;\ -typedef typename AllocatorBase::pointer pointer;\ -typedef typename AllocatorBase::const_pointer const_pointer;\ -typedef typename AllocatorBase::reference reference;\ -typedef typename AllocatorBase::const_reference const_reference; - -#if defined(_MSC_VER) && (_MSC_VER < 1300) -// this pragma causes an internal compiler error if placed immediately before std::swap(a, b) -#pragma warning(push) -#pragma warning(disable: 4700) // VC60 workaround: don't know how to get rid of this warning -#endif - -template -typename A::pointer StandardReallocate(A& a, T *p, typename A::size_type oldSize, typename A::size_type newSize, bool preserve) -{ - if (oldSize == newSize) - return p; - - if (preserve) - { - typename A::pointer newPointer = a.allocate(newSize, NULL); - memcpy_s(newPointer, sizeof(T)*newSize, p, sizeof(T)*STDMIN(oldSize, newSize)); - a.deallocate(p, oldSize); - return newPointer; - } - else - { - a.deallocate(p, oldSize); - return a.allocate(newSize, NULL); - } -} - -#if defined(_MSC_VER) && (_MSC_VER < 1300) -#pragma warning(pop) -#endif - -template -class AllocatorWithCleanup : public AllocatorBase -{ -public: - CRYPTOPP_INHERIT_ALLOCATOR_TYPES - - pointer allocate(size_type n, const void * = NULL) - { - CheckSize(n); - if (n == 0) - return NULL; - - if (CRYPTOPP_BOOL_ALIGN16_ENABLED && T_Align16 && n*sizeof(T) >= 16) - { - byte *p; - #ifdef CRYPTOPP_MM_MALLOC_AVAILABLE - while (!(p = (byte *)_mm_malloc(sizeof(T)*n, 16))) - #elif defined(CRYPTOPP_MEMALIGN_AVAILABLE) - while (!(p = (byte *)memalign(16, sizeof(T)*n))) - #elif defined(CRYPTOPP_MALLOC_ALIGNMENT_IS_16) - while (!(p = (byte *)malloc(sizeof(T)*n))) - #else - while (!(p = (byte *)malloc(sizeof(T)*n + 16))) - #endif - CallNewHandler(); - - #ifdef CRYPTOPP_NO_ALIGNED_ALLOC - size_t adjustment = 16-((size_t)p%16); - p += adjustment; - p[-1] = (byte)adjustment; - #endif - - assert(IsAlignedOn(p, 16)); - return (pointer)p; - } - - pointer p; - while (!(p = (pointer)malloc(sizeof(T)*n))) - CallNewHandler(); - return p; - } - - void deallocate(void *p, size_type n) - { - memset_z(p, 0, n*sizeof(T)); - - if (CRYPTOPP_BOOL_ALIGN16_ENABLED && T_Align16 && n*sizeof(T) >= 16) - { - #ifdef CRYPTOPP_MM_MALLOC_AVAILABLE - _mm_free(p); - #elif defined(CRYPTOPP_NO_ALIGNED_ALLOC) - p = (byte *)p - ((byte *)p)[-1]; - free(p); - #else - free(p); - #endif - return; - } - - free(p); - } - - pointer reallocate(T *p, size_type oldSize, size_type newSize, bool preserve) - { - return StandardReallocate(*this, p, oldSize, newSize, preserve); - } - - // VS.NET STL enforces the policy of "All STL-compliant allocators have to provide a - // template class member called rebind". - template struct rebind { typedef AllocatorWithCleanup other; }; -#if _MSC_VER >= 1500 - AllocatorWithCleanup() {} - template AllocatorWithCleanup(const AllocatorWithCleanup &) {} -#endif -}; - -CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; -CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; -CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; -CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; -#if CRYPTOPP_BOOL_X86 -CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; // for Integer -#endif - -template -class NullAllocator : public AllocatorBase -{ -public: - CRYPTOPP_INHERIT_ALLOCATOR_TYPES - - pointer allocate(size_type n, const void * = NULL) - { - assert(false); - return NULL; - } - - void deallocate(void *p, size_type n) - { - assert(false); - } - - size_type max_size() const {return 0;} -}; - -// This allocator can't be used with standard collections because -// they require that all objects of the same allocator type are equivalent. -// So this is for use with SecBlock only. -template , bool T_Align16 = false> -class FixedSizeAllocatorWithCleanup : public AllocatorBase -{ -public: - CRYPTOPP_INHERIT_ALLOCATOR_TYPES - - FixedSizeAllocatorWithCleanup() : m_allocated(false) {} - - pointer allocate(size_type n) - { - assert(IsAlignedOn(m_array, 8)); - - if (n <= S && !m_allocated) - { - m_allocated = true; - return GetAlignedArray(); - } - else - return m_fallbackAllocator.allocate(n); - } - - pointer allocate(size_type n, const void *hint) - { - if (n <= S && !m_allocated) - { - m_allocated = true; - return GetAlignedArray(); - } - else - return m_fallbackAllocator.allocate(n, hint); - } - - void deallocate(void *p, size_type n) - { - if (p == GetAlignedArray()) - { - assert(n <= S); - assert(m_allocated); - m_allocated = false; - memset(p, 0, n*sizeof(T)); - } - else - m_fallbackAllocator.deallocate(p, n); - } - - pointer reallocate(pointer p, size_type oldSize, size_type newSize, bool preserve) - { - if (p == GetAlignedArray() && newSize <= S) - { - assert(oldSize <= S); - if (oldSize > newSize) - memset(p + newSize, 0, (oldSize-newSize)*sizeof(T)); - return p; - } - - pointer newPointer = allocate(newSize, NULL); - if (preserve) - memcpy(newPointer, p, sizeof(T)*STDMIN(oldSize, newSize)); - deallocate(p, oldSize); - return newPointer; - } - - size_type max_size() const {return STDMAX(m_fallbackAllocator.max_size(), S);} - -private: -#ifdef __BORLANDC__ - T* GetAlignedArray() {return m_array;} - T m_array[S]; -#else - T* GetAlignedArray() {return (CRYPTOPP_BOOL_ALIGN16_ENABLED && T_Align16) ? (T*)(((byte *)m_array) + (0-(size_t)m_array)%16) : m_array;} - CRYPTOPP_ALIGN_DATA(8) T m_array[(CRYPTOPP_BOOL_ALIGN16_ENABLED && T_Align16) ? S+8/sizeof(T) : S]; -#endif - A m_fallbackAllocator; - bool m_allocated; -}; - -//! a block of memory allocated using A -template > -class SecBlock -{ -public: - typedef typename A::value_type value_type; - typedef typename A::pointer iterator; - typedef typename A::const_pointer const_iterator; - typedef typename A::size_type size_type; - - explicit SecBlock(size_type size=0) - : m_size(size) {m_ptr = m_alloc.allocate(size, NULL);} - SecBlock(const SecBlock &t) - : m_size(t.m_size) {m_ptr = m_alloc.allocate(m_size, NULL); memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, m_size*sizeof(T));} - SecBlock(const T *t, size_type len) - : m_size(len) - { - m_ptr = m_alloc.allocate(len, NULL); - if (t == NULL) - memset_z(m_ptr, 0, len*sizeof(T)); - else - memcpy(m_ptr, t, len*sizeof(T)); - } - - ~SecBlock() - {m_alloc.deallocate(m_ptr, m_size);} - -#ifdef __BORLANDC__ - operator T *() const - {return (T*)m_ptr;} -#else - operator const void *() const - {return m_ptr;} - operator void *() - {return m_ptr;} - - operator const T *() const - {return m_ptr;} - operator T *() - {return m_ptr;} -#endif - -// T *operator +(size_type offset) -// {return m_ptr+offset;} - -// const T *operator +(size_type offset) const -// {return m_ptr+offset;} - -// T& operator[](size_type index) -// {assert(index >= 0 && index < m_size); return m_ptr[index];} - -// const T& operator[](size_type index) const -// {assert(index >= 0 && index < m_size); return m_ptr[index];} - - iterator begin() - {return m_ptr;} - const_iterator begin() const - {return m_ptr;} - iterator end() - {return m_ptr+m_size;} - const_iterator end() const - {return m_ptr+m_size;} - - typename A::pointer data() {return m_ptr;} - typename A::const_pointer data() const {return m_ptr;} - - size_type size() const {return m_size;} - bool empty() const {return m_size == 0;} - - byte * BytePtr() {return (byte *)m_ptr;} - const byte * BytePtr() const {return (const byte *)m_ptr;} - size_type SizeInBytes() const {return m_size*sizeof(T);} - - //! set contents and size - void Assign(const T *t, size_type len) - { - New(len); - memcpy_s(m_ptr, m_size*sizeof(T), t, len*sizeof(T)); - } - - //! copy contents and size from another SecBlock - void Assign(const SecBlock &t) - { - New(t.m_size); - memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, m_size*sizeof(T)); - } - - SecBlock& operator=(const SecBlock &t) - { - Assign(t); - return *this; - } - - // append to this object - SecBlock& operator+=(const SecBlock &t) - { - size_type oldSize = m_size; - Grow(m_size+t.m_size); - memcpy_s(m_ptr+oldSize, m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T)); - return *this; - } - - // append operator - SecBlock operator+(const SecBlock &t) - { - SecBlock result(m_size+t.m_size); - memcpy_s(result.m_ptr, result.m_size*sizeof(T), m_ptr, m_size*sizeof(T)); - memcpy_s(result.m_ptr+m_size, t.m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T)); - return result; - } - - bool operator==(const SecBlock &t) const - { - return m_size == t.m_size && VerifyBufsEqual(m_ptr, t.m_ptr, m_size*sizeof(T)); - } - - bool operator!=(const SecBlock &t) const - { - return !operator==(t); - } - - //! change size, without preserving contents - void New(size_type newSize) - { - m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false); - m_size = newSize; - } - - //! change size and set contents to 0 - void CleanNew(size_type newSize) - { - New(newSize); - memset_z(m_ptr, 0, m_size*sizeof(T)); - } - - //! change size only if newSize > current size. contents are preserved - void Grow(size_type newSize) - { - if (newSize > m_size) - { - m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true); - m_size = newSize; - } - } - - //! change size only if newSize > current size. contents are preserved and additional area is set to 0 - void CleanGrow(size_type newSize) - { - if (newSize > m_size) - { - m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true); - memset(m_ptr+m_size, 0, (newSize-m_size)*sizeof(T)); - m_size = newSize; - } - } - - //! change size and preserve contents - void resize(size_type newSize) - { - m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true); - m_size = newSize; - } - - //! swap contents and size with another SecBlock - void swap(SecBlock &b) - { - std::swap(m_alloc, b.m_alloc); - std::swap(m_size, b.m_size); - std::swap(m_ptr, b.m_ptr); - } - -//private: - A m_alloc; - size_type m_size; - T *m_ptr; -}; - -typedef SecBlock SecByteBlock; -typedef SecBlock > AlignedSecByteBlock; -typedef SecBlock SecWordBlock; - -//! a SecBlock with fixed size, allocated statically -template > -class FixedSizeSecBlock : public SecBlock -{ -public: - explicit FixedSizeSecBlock() : SecBlock(S) {} -}; - -template -class FixedSizeAlignedSecBlock : public FixedSizeSecBlock, T_Align16> > -{ -}; - -//! a SecBlock that preallocates size S statically, and uses the heap when this size is exceeded -template > > -class SecBlockWithHint : public SecBlock -{ -public: - explicit SecBlockWithHint(size_t size) : SecBlock(size) {} -}; - -template -inline bool operator==(const CryptoPP::AllocatorWithCleanup&, const CryptoPP::AllocatorWithCleanup&) {return (true);} -template -inline bool operator!=(const CryptoPP::AllocatorWithCleanup&, const CryptoPP::AllocatorWithCleanup&) {return (false);} - -NAMESPACE_END - -NAMESPACE_BEGIN(std) -template -inline void swap(CryptoPP::SecBlock &a, CryptoPP::SecBlock &b) -{ - a.swap(b); -} - -#if defined(_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE) || (defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES)) -// working for STLport 5.1.3 and MSVC 6 SP5 -template -inline CryptoPP::AllocatorWithCleanup<_Tp2>& -__stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*) -{ - return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a); -} -#endif - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/seckey.h b/embeddedcryptopp/seckey.h deleted file mode 100644 index 35046a6..0000000 --- a/embeddedcryptopp/seckey.h +++ /dev/null @@ -1,221 +0,0 @@ -// seckey.h - written and placed in the public domain by Wei Dai - -// This file contains helper classes/functions for implementing secret key algorithms. - -#ifndef CRYPTOPP_SECKEY_H -#define CRYPTOPP_SECKEY_H - -#include "cryptlib.h" -#include "misc.h" -#include "simple.h" - -NAMESPACE_BEGIN(CryptoPP) - -inline CipherDir ReverseCipherDir(CipherDir dir) -{ - return (dir == ENCRYPTION) ? DECRYPTION : ENCRYPTION; -} - -//! to be inherited by block ciphers with fixed block size -template -class FixedBlockSize -{ -public: - CRYPTOPP_CONSTANT(BLOCKSIZE = N) -}; - -// ************** rounds *************** - -//! to be inherited by ciphers with fixed number of rounds -template -class FixedRounds -{ -public: - CRYPTOPP_CONSTANT(ROUNDS = R) -}; - -//! to be inherited by ciphers with variable number of rounds -template // use INT_MAX here because enums are treated as signed ints -class VariableRounds -{ -public: - CRYPTOPP_CONSTANT(DEFAULT_ROUNDS = D) - CRYPTOPP_CONSTANT(MIN_ROUNDS = N) - CRYPTOPP_CONSTANT(MAX_ROUNDS = M) - static unsigned int StaticGetDefaultRounds(size_t keylength) {return DEFAULT_ROUNDS;} - -protected: - inline void ThrowIfInvalidRounds(int rounds, const Algorithm *alg) - { - if (rounds < MIN_ROUNDS || rounds > MAX_ROUNDS) - throw InvalidRounds(alg->AlgorithmName(), rounds); - } - - inline unsigned int GetRoundsAndThrowIfInvalid(const NameValuePairs ¶m, const Algorithm *alg) - { - int rounds = param.GetIntValueWithDefault("Rounds", DEFAULT_ROUNDS); - ThrowIfInvalidRounds(rounds, alg); - return (unsigned int)rounds; - } -}; - -// ************** key length *************** - -//! to be inherited by keyed algorithms with fixed key length -template -class FixedKeyLength -{ -public: - CRYPTOPP_CONSTANT(KEYLENGTH=N) - CRYPTOPP_CONSTANT(MIN_KEYLENGTH=N) - CRYPTOPP_CONSTANT(MAX_KEYLENGTH=N) - CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH=N) - CRYPTOPP_CONSTANT(IV_REQUIREMENT = IV_REQ) - CRYPTOPP_CONSTANT(IV_LENGTH = IV_L) - static size_t CRYPTOPP_API StaticGetValidKeyLength(size_t) {return KEYLENGTH;} -}; - -/// support query of variable key length, template parameters are default, min, max, multiple (default multiple 1) -template -class VariableKeyLength -{ - // make these private to avoid Doxygen documenting them in all derived classes - CRYPTOPP_COMPILE_ASSERT(Q > 0); - CRYPTOPP_COMPILE_ASSERT(N % Q == 0); - CRYPTOPP_COMPILE_ASSERT(M % Q == 0); - CRYPTOPP_COMPILE_ASSERT(N < M); - CRYPTOPP_COMPILE_ASSERT(D >= N); - CRYPTOPP_COMPILE_ASSERT(M >= D); - -public: - CRYPTOPP_CONSTANT(MIN_KEYLENGTH=N) - CRYPTOPP_CONSTANT(MAX_KEYLENGTH=M) - CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH=D) - CRYPTOPP_CONSTANT(KEYLENGTH_MULTIPLE=Q) - CRYPTOPP_CONSTANT(IV_REQUIREMENT=IV_REQ) - CRYPTOPP_CONSTANT(IV_LENGTH=IV_L) - - static size_t CRYPTOPP_API StaticGetValidKeyLength(size_t n) - { - if (n < (size_t)MIN_KEYLENGTH) - return MIN_KEYLENGTH; - else if (n > (size_t)MAX_KEYLENGTH) - return (size_t)MAX_KEYLENGTH; - else - { - n += KEYLENGTH_MULTIPLE-1; - return n - n%KEYLENGTH_MULTIPLE; - } - } -}; - -/// support query of key length that's the same as another class -template -class SameKeyLengthAs -{ -public: - CRYPTOPP_CONSTANT(MIN_KEYLENGTH=T::MIN_KEYLENGTH) - CRYPTOPP_CONSTANT(MAX_KEYLENGTH=T::MAX_KEYLENGTH) - CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH=T::DEFAULT_KEYLENGTH) - CRYPTOPP_CONSTANT(IV_REQUIREMENT=IV_REQ) - CRYPTOPP_CONSTANT(IV_LENGTH=IV_L) - - static size_t CRYPTOPP_API StaticGetValidKeyLength(size_t keylength) - {return T::StaticGetValidKeyLength(keylength);} -}; - -// ************** implementation helper for SimpleKeyed *************** - -//! _ -template -class CRYPTOPP_NO_VTABLE SimpleKeyingInterfaceImpl : public BASE -{ -public: - size_t MinKeyLength() const {return INFO::MIN_KEYLENGTH;} - size_t MaxKeyLength() const {return (size_t)INFO::MAX_KEYLENGTH;} - size_t DefaultKeyLength() const {return INFO::DEFAULT_KEYLENGTH;} - size_t GetValidKeyLength(size_t n) const {return INFO::StaticGetValidKeyLength(n);} - SimpleKeyingInterface::IV_Requirement IVRequirement() const {return (SimpleKeyingInterface::IV_Requirement)INFO::IV_REQUIREMENT;} - unsigned int IVSize() const {return INFO::IV_LENGTH;} -}; - -template -class CRYPTOPP_NO_VTABLE BlockCipherImpl : public AlgorithmImpl > > -{ -public: - unsigned int BlockSize() const {return this->BLOCKSIZE;} -}; - -//! _ -template -class BlockCipherFinal : public ClonableImpl, BASE> -{ -public: - BlockCipherFinal() {} - BlockCipherFinal(const byte *key) - {this->SetKey(key, this->DEFAULT_KEYLENGTH);} - BlockCipherFinal(const byte *key, size_t length) - {this->SetKey(key, length);} - BlockCipherFinal(const byte *key, size_t length, unsigned int rounds) - {this->SetKeyWithRounds(key, length, rounds);} - - bool IsForwardTransformation() const {return DIR == ENCRYPTION;} -}; - -//! _ -template -class MessageAuthenticationCodeImpl : public AlgorithmImpl, INFO> -{ -}; - -//! _ -template -class MessageAuthenticationCodeFinal : public ClonableImpl, MessageAuthenticationCodeImpl > -{ -public: - MessageAuthenticationCodeFinal() {} - MessageAuthenticationCodeFinal(const byte *key) - {this->SetKey(key, this->DEFAULT_KEYLENGTH);} - MessageAuthenticationCodeFinal(const byte *key, size_t length) - {this->SetKey(key, length);} -}; - -// ************** documentation *************** - -//! These objects usually should not be used directly. See CipherModeDocumentation instead. -/*! Each class derived from this one defines two types, Encryption and Decryption, - both of which implement the BlockCipher interface. */ -struct BlockCipherDocumentation -{ - //! implements the BlockCipher interface - typedef BlockCipher Encryption; - //! implements the BlockCipher interface - typedef BlockCipher Decryption; -}; - -/*! \brief Each class derived from this one defines two types, Encryption and Decryption, - both of which implement the SymmetricCipher interface. Two types of classes derive - from this class: stream ciphers and block cipher modes. Stream ciphers can be used - alone, cipher mode classes need to be used with a block cipher. See CipherModeDocumentation - for more for information about using cipher modes and block ciphers. */ -struct SymmetricCipherDocumentation -{ - //! implements the SymmetricCipher interface - typedef SymmetricCipher Encryption; - //! implements the SymmetricCipher interface - typedef SymmetricCipher Decryption; -}; - -/*! \brief Each class derived from this one defines two types, Encryption and Decryption, - both of which implement the AuthenticatedSymmetricCipher interface. */ -struct AuthenticatedSymmetricCipherDocumentation -{ - //! implements the AuthenticatedSymmetricCipher interface - typedef AuthenticatedSymmetricCipher Encryption; - //! implements the AuthenticatedSymmetricCipher interface - typedef AuthenticatedSymmetricCipher Decryption; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/serpent.cpp b/embeddedcryptopp/serpent.cpp deleted file mode 100644 index 40fab23..0000000 --- a/embeddedcryptopp/serpent.cpp +++ /dev/null @@ -1,123 +0,0 @@ -// serpent.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" -#include "serpent.h" -#include "misc.h" - -#include "serpentp.h" - -NAMESPACE_BEGIN(CryptoPP) - -void Serpent_KeySchedule(word32 *k, unsigned int rounds, const byte *userKey, size_t keylen) -{ - FixedSizeSecBlock k0; - GetUserKey(LITTLE_ENDIAN_ORDER, k0.begin(), 8, userKey, keylen); - if (keylen < 32) - k0[keylen/4] |= word32(1) << ((keylen%4)*8); - - word32 t = k0[7]; - unsigned int i; - for (i = 0; i < 8; ++i) - k[i] = k0[i] = t = rotlFixed(k0[i] ^ k0[(i+3)%8] ^ k0[(i+5)%8] ^ t ^ 0x9e3779b9 ^ i, 11); - for (i = 8; i < 4*(rounds+1); ++i) - k[i] = t = rotlFixed(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11); - k -= 20; - - word32 a,b,c,d,e; - for (i=0; i Block; - -void Serpent::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const -{ - word32 a, b, c, d, e; - - Block::Get(inBlock)(a)(b)(c)(d); - - const word32 *k = m_key; - unsigned int i=1; - - do - { - beforeS0(KX); beforeS0(S0); afterS0(LT); - afterS0(KX); afterS0(S1); afterS1(LT); - afterS1(KX); afterS1(S2); afterS2(LT); - afterS2(KX); afterS2(S3); afterS3(LT); - afterS3(KX); afterS3(S4); afterS4(LT); - afterS4(KX); afterS4(S5); afterS5(LT); - afterS5(KX); afterS5(S6); afterS6(LT); - afterS6(KX); afterS6(S7); - - if (i == 4) - break; - - ++i; - c = b; - b = e; - e = d; - d = a; - a = e; - k += 32; - beforeS0(LT); - } - while (true); - - afterS7(KX); - - Block::Put(xorBlock, outBlock)(d)(e)(b)(a); -} - -void Serpent::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const -{ - word32 a, b, c, d, e; - - Block::Get(inBlock)(a)(b)(c)(d); - - const word32 *k = m_key + 96; - unsigned int i=4; - - beforeI7(KX); - goto start; - - do - { - c = b; - b = d; - d = e; - k -= 32; - beforeI7(ILT); -start: - beforeI7(I7); afterI7(KX); - afterI7(ILT); afterI7(I6); afterI6(KX); - afterI6(ILT); afterI6(I5); afterI5(KX); - afterI5(ILT); afterI5(I4); afterI4(KX); - afterI4(ILT); afterI4(I3); afterI3(KX); - afterI3(ILT); afterI3(I2); afterI2(KX); - afterI2(ILT); afterI2(I1); afterI1(KX); - afterI1(ILT); afterI1(I0); afterI0(KX); - } - while (--i != 0); - - Block::Put(xorBlock, outBlock)(a)(d)(b)(e); -} - -NAMESPACE_END diff --git a/embeddedcryptopp/serpent.h b/embeddedcryptopp/serpent.h deleted file mode 100644 index f7ee8d6..0000000 --- a/embeddedcryptopp/serpent.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef CRYPTOPP_SERPENT_H -#define CRYPTOPP_SERPENT_H - -/** \file -*/ - -#include "seckey.h" -#include "secblock.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! _ -struct Serpent_Info : public FixedBlockSize<16>, public VariableKeyLength<16, 0, 32>, public FixedRounds<32> -{ - static const char *StaticAlgorithmName() {return "Serpent";} -}; - -/// Serpent -class Serpent : public Serpent_Info, public BlockCipherDocumentation -{ - class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl - { - public: - void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); - - protected: - FixedSizeSecBlock m_key; - }; - - class CRYPTOPP_NO_VTABLE Enc : public Base - { - public: - void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; - }; - - class CRYPTOPP_NO_VTABLE Dec : public Base - { - public: - void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; - }; - -public: - typedef BlockCipherFinal Encryption; - typedef BlockCipherFinal Decryption; -}; - -typedef Serpent::Encryption SerpentEncryption; -typedef Serpent::Decryption SerpentDecryption; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/serpentp.h b/embeddedcryptopp/serpentp.h deleted file mode 100644 index 7869a3f..0000000 --- a/embeddedcryptopp/serpentp.h +++ /dev/null @@ -1,434 +0,0 @@ -// private header for Serpent and Sosemanuk - -NAMESPACE_BEGIN(CryptoPP) - -// linear transformation -#define LT(i,a,b,c,d,e) {\ - a = rotlFixed(a, 13); \ - c = rotlFixed(c, 3); \ - d = rotlFixed(d ^ c ^ (a << 3), 7); \ - b = rotlFixed(b ^ a ^ c, 1); \ - a = rotlFixed(a ^ b ^ d, 5); \ - c = rotlFixed(c ^ d ^ (b << 7), 22);} - -// inverse linear transformation -#define ILT(i,a,b,c,d,e) {\ - c = rotrFixed(c, 22); \ - a = rotrFixed(a, 5); \ - c ^= d ^ (b << 7); \ - a ^= b ^ d; \ - b = rotrFixed(b, 1); \ - d = rotrFixed(d, 7) ^ c ^ (a << 3); \ - b ^= a ^ c; \ - c = rotrFixed(c, 3); \ - a = rotrFixed(a, 13);} - -// order of output from S-box functions -#define beforeS0(f) f(0,a,b,c,d,e) -#define afterS0(f) f(1,b,e,c,a,d) -#define afterS1(f) f(2,c,b,a,e,d) -#define afterS2(f) f(3,a,e,b,d,c) -#define afterS3(f) f(4,e,b,d,c,a) -#define afterS4(f) f(5,b,a,e,c,d) -#define afterS5(f) f(6,a,c,b,e,d) -#define afterS6(f) f(7,a,c,d,b,e) -#define afterS7(f) f(8,d,e,b,a,c) - -// order of output from inverse S-box functions -#define beforeI7(f) f(8,a,b,c,d,e) -#define afterI7(f) f(7,d,a,b,e,c) -#define afterI6(f) f(6,a,b,c,e,d) -#define afterI5(f) f(5,b,d,e,c,a) -#define afterI4(f) f(4,b,c,e,a,d) -#define afterI3(f) f(3,a,b,e,c,d) -#define afterI2(f) f(2,b,d,e,c,a) -#define afterI1(f) f(1,a,b,c,e,d) -#define afterI0(f) f(0,a,d,b,e,c) - -// The instruction sequences for the S-box functions -// come from Dag Arne Osvik's paper "Speeding up Serpent". - -#define S0(i, r0, r1, r2, r3, r4) \ - { \ - r3 ^= r0; \ - r4 = r1; \ - r1 &= r3; \ - r4 ^= r2; \ - r1 ^= r0; \ - r0 |= r3; \ - r0 ^= r4; \ - r4 ^= r3; \ - r3 ^= r2; \ - r2 |= r1; \ - r2 ^= r4; \ - r4 = ~r4; \ - r4 |= r1; \ - r1 ^= r3; \ - r1 ^= r4; \ - r3 |= r0; \ - r1 ^= r3; \ - r4 ^= r3; \ - } - -#define I0(i, r0, r1, r2, r3, r4) \ - { \ - r2 = ~r2; \ - r4 = r1; \ - r1 |= r0; \ - r4 = ~r4; \ - r1 ^= r2; \ - r2 |= r4; \ - r1 ^= r3; \ - r0 ^= r4; \ - r2 ^= r0; \ - r0 &= r3; \ - r4 ^= r0; \ - r0 |= r1; \ - r0 ^= r2; \ - r3 ^= r4; \ - r2 ^= r1; \ - r3 ^= r0; \ - r3 ^= r1; \ - r2 &= r3; \ - r4 ^= r2; \ - } - -#define S1(i, r0, r1, r2, r3, r4) \ - { \ - r0 = ~r0; \ - r2 = ~r2; \ - r4 = r0; \ - r0 &= r1; \ - r2 ^= r0; \ - r0 |= r3; \ - r3 ^= r2; \ - r1 ^= r0; \ - r0 ^= r4; \ - r4 |= r1; \ - r1 ^= r3; \ - r2 |= r0; \ - r2 &= r4; \ - r0 ^= r1; \ - r1 &= r2; \ - r1 ^= r0; \ - r0 &= r2; \ - r0 ^= r4; \ - } - -#define I1(i, r0, r1, r2, r3, r4) \ - { \ - r4 = r1; \ - r1 ^= r3; \ - r3 &= r1; \ - r4 ^= r2; \ - r3 ^= r0; \ - r0 |= r1; \ - r2 ^= r3; \ - r0 ^= r4; \ - r0 |= r2; \ - r1 ^= r3; \ - r0 ^= r1; \ - r1 |= r3; \ - r1 ^= r0; \ - r4 = ~r4; \ - r4 ^= r1; \ - r1 |= r0; \ - r1 ^= r0; \ - r1 |= r4; \ - r3 ^= r1; \ - } - -#define S2(i, r0, r1, r2, r3, r4) \ - { \ - r4 = r0; \ - r0 &= r2; \ - r0 ^= r3; \ - r2 ^= r1; \ - r2 ^= r0; \ - r3 |= r4; \ - r3 ^= r1; \ - r4 ^= r2; \ - r1 = r3; \ - r3 |= r4; \ - r3 ^= r0; \ - r0 &= r1; \ - r4 ^= r0; \ - r1 ^= r3; \ - r1 ^= r4; \ - r4 = ~r4; \ - } - -#define I2(i, r0, r1, r2, r3, r4) \ - { \ - r2 ^= r3; \ - r3 ^= r0; \ - r4 = r3; \ - r3 &= r2; \ - r3 ^= r1; \ - r1 |= r2; \ - r1 ^= r4; \ - r4 &= r3; \ - r2 ^= r3; \ - r4 &= r0; \ - r4 ^= r2; \ - r2 &= r1; \ - r2 |= r0; \ - r3 = ~r3; \ - r2 ^= r3; \ - r0 ^= r3; \ - r0 &= r1; \ - r3 ^= r4; \ - r3 ^= r0; \ - } - -#define S3(i, r0, r1, r2, r3, r4) \ - { \ - r4 = r0; \ - r0 |= r3; \ - r3 ^= r1; \ - r1 &= r4; \ - r4 ^= r2; \ - r2 ^= r3; \ - r3 &= r0; \ - r4 |= r1; \ - r3 ^= r4; \ - r0 ^= r1; \ - r4 &= r0; \ - r1 ^= r3; \ - r4 ^= r2; \ - r1 |= r0; \ - r1 ^= r2; \ - r0 ^= r3; \ - r2 = r1; \ - r1 |= r3; \ - r1 ^= r0; \ - } - -#define I3(i, r0, r1, r2, r3, r4) \ - { \ - r4 = r2; \ - r2 ^= r1; \ - r1 &= r2; \ - r1 ^= r0; \ - r0 &= r4; \ - r4 ^= r3; \ - r3 |= r1; \ - r3 ^= r2; \ - r0 ^= r4; \ - r2 ^= r0; \ - r0 |= r3; \ - r0 ^= r1; \ - r4 ^= r2; \ - r2 &= r3; \ - r1 |= r3; \ - r1 ^= r2; \ - r4 ^= r0; \ - r2 ^= r4; \ - } - -#define S4(i, r0, r1, r2, r3, r4) \ - { \ - r1 ^= r3; \ - r3 = ~r3; \ - r2 ^= r3; \ - r3 ^= r0; \ - r4 = r1; \ - r1 &= r3; \ - r1 ^= r2; \ - r4 ^= r3; \ - r0 ^= r4; \ - r2 &= r4; \ - r2 ^= r0; \ - r0 &= r1; \ - r3 ^= r0; \ - r4 |= r1; \ - r4 ^= r0; \ - r0 |= r3; \ - r0 ^= r2; \ - r2 &= r3; \ - r0 = ~r0; \ - r4 ^= r2; \ - } - -#define I4(i, r0, r1, r2, r3, r4) \ - { \ - r4 = r2; \ - r2 &= r3; \ - r2 ^= r1; \ - r1 |= r3; \ - r1 &= r0; \ - r4 ^= r2; \ - r4 ^= r1; \ - r1 &= r2; \ - r0 = ~r0; \ - r3 ^= r4; \ - r1 ^= r3; \ - r3 &= r0; \ - r3 ^= r2; \ - r0 ^= r1; \ - r2 &= r0; \ - r3 ^= r0; \ - r2 ^= r4; \ - r2 |= r3; \ - r3 ^= r0; \ - r2 ^= r1; \ - } - -#define S5(i, r0, r1, r2, r3, r4) \ - { \ - r0 ^= r1; \ - r1 ^= r3; \ - r3 = ~r3; \ - r4 = r1; \ - r1 &= r0; \ - r2 ^= r3; \ - r1 ^= r2; \ - r2 |= r4; \ - r4 ^= r3; \ - r3 &= r1; \ - r3 ^= r0; \ - r4 ^= r1; \ - r4 ^= r2; \ - r2 ^= r0; \ - r0 &= r3; \ - r2 = ~r2; \ - r0 ^= r4; \ - r4 |= r3; \ - r2 ^= r4; \ - } - -#define I5(i, r0, r1, r2, r3, r4) \ - { \ - r1 = ~r1; \ - r4 = r3; \ - r2 ^= r1; \ - r3 |= r0; \ - r3 ^= r2; \ - r2 |= r1; \ - r2 &= r0; \ - r4 ^= r3; \ - r2 ^= r4; \ - r4 |= r0; \ - r4 ^= r1; \ - r1 &= r2; \ - r1 ^= r3; \ - r4 ^= r2; \ - r3 &= r4; \ - r4 ^= r1; \ - r3 ^= r0; \ - r3 ^= r4; \ - r4 = ~r4; \ - } - -#define S6(i, r0, r1, r2, r3, r4) \ - { \ - r2 = ~r2; \ - r4 = r3; \ - r3 &= r0; \ - r0 ^= r4; \ - r3 ^= r2; \ - r2 |= r4; \ - r1 ^= r3; \ - r2 ^= r0; \ - r0 |= r1; \ - r2 ^= r1; \ - r4 ^= r0; \ - r0 |= r3; \ - r0 ^= r2; \ - r4 ^= r3; \ - r4 ^= r0; \ - r3 = ~r3; \ - r2 &= r4; \ - r2 ^= r3; \ - } - -#define I6(i, r0, r1, r2, r3, r4) \ - { \ - r0 ^= r2; \ - r4 = r2; \ - r2 &= r0; \ - r4 ^= r3; \ - r2 = ~r2; \ - r3 ^= r1; \ - r2 ^= r3; \ - r4 |= r0; \ - r0 ^= r2; \ - r3 ^= r4; \ - r4 ^= r1; \ - r1 &= r3; \ - r1 ^= r0; \ - r0 ^= r3; \ - r0 |= r2; \ - r3 ^= r1; \ - r4 ^= r0; \ - } - -#define S7(i, r0, r1, r2, r3, r4) \ - { \ - r4 = r2; \ - r2 &= r1; \ - r2 ^= r3; \ - r3 &= r1; \ - r4 ^= r2; \ - r2 ^= r1; \ - r1 ^= r0; \ - r0 |= r4; \ - r0 ^= r2; \ - r3 ^= r1; \ - r2 ^= r3; \ - r3 &= r0; \ - r3 ^= r4; \ - r4 ^= r2; \ - r2 &= r0; \ - r4 = ~r4; \ - r2 ^= r4; \ - r4 &= r0; \ - r1 ^= r3; \ - r4 ^= r1; \ - } - -#define I7(i, r0, r1, r2, r3, r4) \ - { \ - r4 = r2; \ - r2 ^= r0; \ - r0 &= r3; \ - r2 = ~r2; \ - r4 |= r3; \ - r3 ^= r1; \ - r1 |= r0; \ - r0 ^= r2; \ - r2 &= r4; \ - r1 ^= r2; \ - r2 ^= r0; \ - r0 |= r2; \ - r3 &= r4; \ - r0 ^= r3; \ - r4 ^= r1; \ - r3 ^= r4; \ - r4 |= r0; \ - r3 ^= r2; \ - r4 ^= r2; \ - } - -// key xor -#define KX(r, a, b, c, d, e) {\ - a ^= k[4 * r + 0]; \ - b ^= k[4 * r + 1]; \ - c ^= k[4 * r + 2]; \ - d ^= k[4 * r + 3];} - -#define LK(r, a, b, c, d, e) {\ - a = k[(8-r)*4 + 0]; \ - b = k[(8-r)*4 + 1]; \ - c = k[(8-r)*4 + 2]; \ - d = k[(8-r)*4 + 3];} - -#define SK(r, a, b, c, d, e) {\ - k[(8-r)*4 + 4] = a; \ - k[(8-r)*4 + 5] = b; \ - k[(8-r)*4 + 6] = c; \ - k[(8-r)*4 + 7] = d;} - -void Serpent_KeySchedule(word32 *k, unsigned int rounds, const byte *userKey, size_t keylen); - -NAMESPACE_END diff --git a/embeddedcryptopp/sha.cpp b/embeddedcryptopp/sha.cpp deleted file mode 100644 index df947ad..0000000 --- a/embeddedcryptopp/sha.cpp +++ /dev/null @@ -1,900 +0,0 @@ -// sha.cpp - modified by Wei Dai from Steve Reid's public domain sha1.c - -// Steve Reid implemented SHA-1. Wei Dai implemented SHA-2. -// Both are in the public domain. - -// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM sha.cpp" to generate MASM code - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS -#ifndef CRYPTOPP_GENERATE_X64_MASM - -#include "sha.h" -#include "misc.h" -#include "cpu.h" - -NAMESPACE_BEGIN(CryptoPP) - -// start of Steve Reid's code - -#define blk0(i) (W[i] = data[i]) -#define blk1(i) (W[i&15] = rotlFixed(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1)) - -void SHA1::InitState(HashWordType *state) -{ - state[0] = 0x67452301L; - state[1] = 0xEFCDAB89L; - state[2] = 0x98BADCFEL; - state[3] = 0x10325476L; - state[4] = 0xC3D2E1F0L; -} - -#define f1(x,y,z) (z^(x&(y^z))) -#define f2(x,y,z) (x^y^z) -#define f3(x,y,z) ((x&y)|(z&(x|y))) -#define f4(x,y,z) (x^y^z) - -/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ -#define R0(v,w,x,y,z,i) z+=f1(w,x,y)+blk0(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30); -#define R1(v,w,x,y,z,i) z+=f1(w,x,y)+blk1(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30); -#define R2(v,w,x,y,z,i) z+=f2(w,x,y)+blk1(i)+0x6ED9EBA1+rotlFixed(v,5);w=rotlFixed(w,30); -#define R3(v,w,x,y,z,i) z+=f3(w,x,y)+blk1(i)+0x8F1BBCDC+rotlFixed(v,5);w=rotlFixed(w,30); -#define R4(v,w,x,y,z,i) z+=f4(w,x,y)+blk1(i)+0xCA62C1D6+rotlFixed(v,5);w=rotlFixed(w,30); - -void SHA1::Transform(word32 *state, const word32 *data) -{ - word32 W[16]; - /* Copy context->state[] to working vars */ - word32 a = state[0]; - word32 b = state[1]; - word32 c = state[2]; - word32 d = state[3]; - word32 e = state[4]; - /* 4 rounds of 20 operations each. Loop unrolled. */ - R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); - R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); - R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); - R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); - R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); - R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); - R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); - R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); - R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); - R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); - R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); - R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); - R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); - R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); - R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); - R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); - R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); - R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); - R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); - R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); - /* Add the working vars back into context.state[] */ - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; -} - -// end of Steve Reid's code - -// ************************************************************* - -void SHA224::InitState(HashWordType *state) -{ - static const word32 s[8] = {0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4}; - memcpy(state, s, sizeof(s)); -} - -void SHA256::InitState(HashWordType *state) -{ - static const word32 s[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; - memcpy(state, s, sizeof(s)); -} - -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE -CRYPTOPP_ALIGN_DATA(16) extern const word32 SHA256_K[64] CRYPTOPP_SECTION_ALIGN16 = { -#else -extern const word32 SHA256_K[64] = { -#endif - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM - -#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_GENERATE_X64_MASM) - -#pragma warning(disable: 4731) // frame pointer register 'ebp' modified by inline assembly code - -static void CRYPTOPP_FASTCALL X86_SHA256_HashBlocks(word32 *state, const word32 *data, size_t len -#if defined(_MSC_VER) && (_MSC_VER == 1200) - , ... // VC60 workaround: prevent VC 6 from inlining this function -#endif - ) -{ -#if defined(_MSC_VER) && (_MSC_VER == 1200) - AS2(mov ecx, [state]) - AS2(mov edx, [data]) -#endif - - #define LOCALS_SIZE 8*4 + 16*4 + 4*WORD_SZ - #define H(i) [BASE+ASM_MOD(1024+7-(i),8)*4] - #define G(i) H(i+1) - #define F(i) H(i+2) - #define E(i) H(i+3) - #define D(i) H(i+4) - #define C(i) H(i+5) - #define B(i) H(i+6) - #define A(i) H(i+7) - #define Wt(i) BASE+8*4+ASM_MOD(1024+15-(i),16)*4 - #define Wt_2(i) Wt((i)-2) - #define Wt_15(i) Wt((i)-15) - #define Wt_7(i) Wt((i)-7) - #define K_END [BASE+8*4+16*4+0*WORD_SZ] - #define STATE_SAVE [BASE+8*4+16*4+1*WORD_SZ] - #define DATA_SAVE [BASE+8*4+16*4+2*WORD_SZ] - #define DATA_END [BASE+8*4+16*4+3*WORD_SZ] - #define Kt(i) WORD_REG(si)+(i)*4 -#if CRYPTOPP_BOOL_X86 - #define BASE esp+4 -#elif defined(__GNUC__) - #define BASE r8 -#else - #define BASE rsp -#endif - -#define RA0(i, edx, edi) \ - AS2( add edx, [Kt(i)] )\ - AS2( add edx, [Wt(i)] )\ - AS2( add edx, H(i) )\ - -#define RA1(i, edx, edi) - -#define RB0(i, edx, edi) - -#define RB1(i, edx, edi) \ - AS2( mov AS_REG_7d, [Wt_2(i)] )\ - AS2( mov edi, [Wt_15(i)])\ - AS2( mov ebx, AS_REG_7d )\ - AS2( shr AS_REG_7d, 10 )\ - AS2( ror ebx, 17 )\ - AS2( xor AS_REG_7d, ebx )\ - AS2( ror ebx, 2 )\ - AS2( xor ebx, AS_REG_7d )/* s1(W_t-2) */\ - AS2( add ebx, [Wt_7(i)])\ - AS2( mov AS_REG_7d, edi )\ - AS2( shr AS_REG_7d, 3 )\ - AS2( ror edi, 7 )\ - AS2( add ebx, [Wt(i)])/* s1(W_t-2) + W_t-7 + W_t-16 */\ - AS2( xor AS_REG_7d, edi )\ - AS2( add edx, [Kt(i)])\ - AS2( ror edi, 11 )\ - AS2( add edx, H(i) )\ - AS2( xor AS_REG_7d, edi )/* s0(W_t-15) */\ - AS2( add AS_REG_7d, ebx )/* W_t = s1(W_t-2) + W_t-7 + s0(W_t-15) W_t-16*/\ - AS2( mov [Wt(i)], AS_REG_7d)\ - AS2( add edx, AS_REG_7d )\ - -#define ROUND(i, r, eax, ecx, edi, edx)\ - /* in: edi = E */\ - /* unused: eax, ecx, temp: ebx, AS_REG_7d, out: edx = T1 */\ - AS2( mov edx, F(i) )\ - AS2( xor edx, G(i) )\ - AS2( and edx, edi )\ - AS2( xor edx, G(i) )/* Ch(E,F,G) = (G^(E&(F^G))) */\ - AS2( mov AS_REG_7d, edi )\ - AS2( ror edi, 6 )\ - AS2( ror AS_REG_7d, 25 )\ - RA##r(i, edx, edi )/* H + Wt + Kt + Ch(E,F,G) */\ - AS2( xor AS_REG_7d, edi )\ - AS2( ror edi, 5 )\ - AS2( xor AS_REG_7d, edi )/* S1(E) */\ - AS2( add edx, AS_REG_7d )/* T1 = S1(E) + Ch(E,F,G) + H + Wt + Kt */\ - RB##r(i, edx, edi )/* H + Wt + Kt + Ch(E,F,G) */\ - /* in: ecx = A, eax = B^C, edx = T1 */\ - /* unused: edx, temp: ebx, AS_REG_7d, out: eax = A, ecx = B^C, edx = E */\ - AS2( mov ebx, ecx )\ - AS2( xor ecx, B(i) )/* A^B */\ - AS2( and eax, ecx )\ - AS2( xor eax, B(i) )/* Maj(A,B,C) = B^((A^B)&(B^C) */\ - AS2( mov AS_REG_7d, ebx )\ - AS2( ror ebx, 2 )\ - AS2( add eax, edx )/* T1 + Maj(A,B,C) */\ - AS2( add edx, D(i) )\ - AS2( mov D(i), edx )\ - AS2( ror AS_REG_7d, 22 )\ - AS2( xor AS_REG_7d, ebx )\ - AS2( ror ebx, 11 )\ - AS2( xor AS_REG_7d, ebx )\ - AS2( add eax, AS_REG_7d )/* T1 + S0(A) + Maj(A,B,C) */\ - AS2( mov H(i), eax )\ - -#define SWAP_COPY(i) \ - AS2( mov WORD_REG(bx), [WORD_REG(dx)+i*WORD_SZ])\ - AS1( bswap WORD_REG(bx))\ - AS2( mov [Wt(i*(1+CRYPTOPP_BOOL_X64)+CRYPTOPP_BOOL_X64)], WORD_REG(bx)) - -#if defined(__GNUC__) - #if CRYPTOPP_BOOL_X64 - FixedSizeAlignedSecBlock workspace; - #endif - __asm__ __volatile__ - ( - #if CRYPTOPP_BOOL_X64 - "lea %4, %%r8;" - #endif - ".intel_syntax noprefix;" -#elif defined(CRYPTOPP_GENERATE_X64_MASM) - ALIGN 8 - X86_SHA256_HashBlocks PROC FRAME - rex_push_reg rsi - push_reg rdi - push_reg rbx - push_reg rbp - alloc_stack(LOCALS_SIZE+8) - .endprolog - mov rdi, r8 - lea rsi, [?SHA256_K@CryptoPP@@3QBIB + 48*4] -#endif - -#if CRYPTOPP_BOOL_X86 - #ifndef __GNUC__ - AS2( mov edi, [len]) - AS2( lea WORD_REG(si), [SHA256_K+48*4]) - #endif - #if !defined(_MSC_VER) || (_MSC_VER < 1400) - AS_PUSH_IF86(bx) - #endif - - AS_PUSH_IF86(bp) - AS2( mov ebx, esp) - AS2( and esp, -16) - AS2( sub WORD_REG(sp), LOCALS_SIZE) - AS_PUSH_IF86(bx) -#endif - AS2( mov STATE_SAVE, WORD_REG(cx)) - AS2( mov DATA_SAVE, WORD_REG(dx)) - AS2( lea WORD_REG(ax), [WORD_REG(di) + WORD_REG(dx)]) - AS2( mov DATA_END, WORD_REG(ax)) - AS2( mov K_END, WORD_REG(si)) - -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE -#if CRYPTOPP_BOOL_X86 - AS2( test edi, 1) - ASJ( jnz, 2, f) - AS1( dec DWORD PTR K_END) -#endif - AS2( movdqa xmm0, XMMWORD_PTR [WORD_REG(cx)+0*16]) - AS2( movdqa xmm1, XMMWORD_PTR [WORD_REG(cx)+1*16]) -#endif - -#if CRYPTOPP_BOOL_X86 -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE - ASJ( jmp, 0, f) -#endif - ASL(2) // non-SSE2 - AS2( mov esi, ecx) - AS2( lea edi, A(0)) - AS2( mov ecx, 8) - AS1( rep movsd) - AS2( mov esi, K_END) - ASJ( jmp, 3, f) -#endif - -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE - ASL(0) - AS2( movdqa E(0), xmm1) - AS2( movdqa A(0), xmm0) -#endif -#if CRYPTOPP_BOOL_X86 - ASL(3) -#endif - AS2( sub WORD_REG(si), 48*4) - SWAP_COPY(0) SWAP_COPY(1) SWAP_COPY(2) SWAP_COPY(3) - SWAP_COPY(4) SWAP_COPY(5) SWAP_COPY(6) SWAP_COPY(7) -#if CRYPTOPP_BOOL_X86 - SWAP_COPY(8) SWAP_COPY(9) SWAP_COPY(10) SWAP_COPY(11) - SWAP_COPY(12) SWAP_COPY(13) SWAP_COPY(14) SWAP_COPY(15) -#endif - AS2( mov edi, E(0)) // E - AS2( mov eax, B(0)) // B - AS2( xor eax, C(0)) // B^C - AS2( mov ecx, A(0)) // A - - ROUND(0, 0, eax, ecx, edi, edx) - ROUND(1, 0, ecx, eax, edx, edi) - ROUND(2, 0, eax, ecx, edi, edx) - ROUND(3, 0, ecx, eax, edx, edi) - ROUND(4, 0, eax, ecx, edi, edx) - ROUND(5, 0, ecx, eax, edx, edi) - ROUND(6, 0, eax, ecx, edi, edx) - ROUND(7, 0, ecx, eax, edx, edi) - ROUND(8, 0, eax, ecx, edi, edx) - ROUND(9, 0, ecx, eax, edx, edi) - ROUND(10, 0, eax, ecx, edi, edx) - ROUND(11, 0, ecx, eax, edx, edi) - ROUND(12, 0, eax, ecx, edi, edx) - ROUND(13, 0, ecx, eax, edx, edi) - ROUND(14, 0, eax, ecx, edi, edx) - ROUND(15, 0, ecx, eax, edx, edi) - - ASL(1) - AS2(add WORD_REG(si), 4*16) - ROUND(0, 1, eax, ecx, edi, edx) - ROUND(1, 1, ecx, eax, edx, edi) - ROUND(2, 1, eax, ecx, edi, edx) - ROUND(3, 1, ecx, eax, edx, edi) - ROUND(4, 1, eax, ecx, edi, edx) - ROUND(5, 1, ecx, eax, edx, edi) - ROUND(6, 1, eax, ecx, edi, edx) - ROUND(7, 1, ecx, eax, edx, edi) - ROUND(8, 1, eax, ecx, edi, edx) - ROUND(9, 1, ecx, eax, edx, edi) - ROUND(10, 1, eax, ecx, edi, edx) - ROUND(11, 1, ecx, eax, edx, edi) - ROUND(12, 1, eax, ecx, edi, edx) - ROUND(13, 1, ecx, eax, edx, edi) - ROUND(14, 1, eax, ecx, edi, edx) - ROUND(15, 1, ecx, eax, edx, edi) - AS2( cmp WORD_REG(si), K_END) - ASJ( jb, 1, b) - - AS2( mov WORD_REG(dx), DATA_SAVE) - AS2( add WORD_REG(dx), 64) - AS2( mov AS_REG_7, STATE_SAVE) - AS2( mov DATA_SAVE, WORD_REG(dx)) - -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE -#if CRYPTOPP_BOOL_X86 - AS2( test DWORD PTR K_END, 1) - ASJ( jz, 4, f) -#endif - AS2( movdqa xmm1, XMMWORD_PTR [AS_REG_7+1*16]) - AS2( movdqa xmm0, XMMWORD_PTR [AS_REG_7+0*16]) - AS2( paddd xmm1, E(0)) - AS2( paddd xmm0, A(0)) - AS2( movdqa [AS_REG_7+1*16], xmm1) - AS2( movdqa [AS_REG_7+0*16], xmm0) - AS2( cmp WORD_REG(dx), DATA_END) - ASJ( jb, 0, b) -#endif - -#if CRYPTOPP_BOOL_X86 -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE - ASJ( jmp, 5, f) - ASL(4) // non-SSE2 -#endif - AS2( add [AS_REG_7+0*4], ecx) // A - AS2( add [AS_REG_7+4*4], edi) // E - AS2( mov eax, B(0)) - AS2( mov ebx, C(0)) - AS2( mov ecx, D(0)) - AS2( add [AS_REG_7+1*4], eax) - AS2( add [AS_REG_7+2*4], ebx) - AS2( add [AS_REG_7+3*4], ecx) - AS2( mov eax, F(0)) - AS2( mov ebx, G(0)) - AS2( mov ecx, H(0)) - AS2( add [AS_REG_7+5*4], eax) - AS2( add [AS_REG_7+6*4], ebx) - AS2( add [AS_REG_7+7*4], ecx) - AS2( mov ecx, AS_REG_7d) - AS2( cmp WORD_REG(dx), DATA_END) - ASJ( jb, 2, b) -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE - ASL(5) -#endif -#endif - - AS_POP_IF86(sp) - AS_POP_IF86(bp) - #if !defined(_MSC_VER) || (_MSC_VER < 1400) - AS_POP_IF86(bx) - #endif - -#ifdef CRYPTOPP_GENERATE_X64_MASM - add rsp, LOCALS_SIZE+8 - pop rbp - pop rbx - pop rdi - pop rsi - ret - X86_SHA256_HashBlocks ENDP -#endif - -#ifdef __GNUC__ - ".att_syntax prefix;" - : - : "c" (state), "d" (data), "S" (SHA256_K+48), "D" (len) - #if CRYPTOPP_BOOL_X64 - , "m" (workspace[0]) - #endif - : "memory", "cc", "%eax" - #if CRYPTOPP_BOOL_X64 - , "%rbx", "%r8", "%r10" - #endif - ); -#endif -} - -#endif // #if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_GENERATE_X64_MASM) - -#ifndef CRYPTOPP_GENERATE_X64_MASM - -#ifdef CRYPTOPP_X64_MASM_AVAILABLE -extern "C" { -void CRYPTOPP_FASTCALL X86_SHA256_HashBlocks(word32 *state, const word32 *data, size_t len); -} -#endif - -#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE) - -size_t SHA256::HashMultipleBlocks(const word32 *input, size_t length) -{ - X86_SHA256_HashBlocks(m_state, input, (length&(size_t(0)-BLOCKSIZE)) - !HasSSE2()); - return length % BLOCKSIZE; -} - -size_t SHA224::HashMultipleBlocks(const word32 *input, size_t length) -{ - X86_SHA256_HashBlocks(m_state, input, (length&(size_t(0)-BLOCKSIZE)) - !HasSSE2()); - return length % BLOCKSIZE; -} - -#endif - -#define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15])) - -#define Ch(x,y,z) (z^(x&(y^z))) -#define Maj(x,y,z) (y^((x^y)&(y^z))) - -#define a(i) T[(0-i)&7] -#define b(i) T[(1-i)&7] -#define c(i) T[(2-i)&7] -#define d(i) T[(3-i)&7] -#define e(i) T[(4-i)&7] -#define f(i) T[(5-i)&7] -#define g(i) T[(6-i)&7] -#define h(i) T[(7-i)&7] - -#define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA256_K[i+j]+(j?blk2(i):blk0(i));\ - d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)) - -// for SHA256 -#define S0(x) (rotrFixed(x,2)^rotrFixed(x,13)^rotrFixed(x,22)) -#define S1(x) (rotrFixed(x,6)^rotrFixed(x,11)^rotrFixed(x,25)) -#define s0(x) (rotrFixed(x,7)^rotrFixed(x,18)^(x>>3)) -#define s1(x) (rotrFixed(x,17)^rotrFixed(x,19)^(x>>10)) - -void SHA256::Transform(word32 *state, const word32 *data) -{ - word32 W[16]; -#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE) - // this byte reverse is a waste of time, but this function is only called by MDC - ByteReverse(W, data, BLOCKSIZE); - X86_SHA256_HashBlocks(state, W, BLOCKSIZE - !HasSSE2()); -#else - word32 T[8]; - /* Copy context->state[] to working vars */ - memcpy(T, state, sizeof(T)); - /* 64 operations, partially loop unrolled */ - for (unsigned int j=0; j<64; j+=16) - { - R( 0); R( 1); R( 2); R( 3); - R( 4); R( 5); R( 6); R( 7); - R( 8); R( 9); R(10); R(11); - R(12); R(13); R(14); R(15); - } - /* Add the working vars back into context.state[] */ - state[0] += a(0); - state[1] += b(0); - state[2] += c(0); - state[3] += d(0); - state[4] += e(0); - state[5] += f(0); - state[6] += g(0); - state[7] += h(0); -#endif -} - -/* -// smaller but slower -void SHA256::Transform(word32 *state, const word32 *data) -{ - word32 T[20]; - word32 W[32]; - unsigned int i = 0, j = 0; - word32 *t = T+8; - - memcpy(t, state, 8*4); - word32 e = t[4], a = t[0]; - - do - { - word32 w = data[j]; - W[j] = w; - w += SHA256_K[j]; - w += t[7]; - w += S1(e); - w += Ch(e, t[5], t[6]); - e = t[3] + w; - t[3] = t[3+8] = e; - w += S0(t[0]); - a = w + Maj(a, t[1], t[2]); - t[-1] = t[7] = a; - --t; - ++j; - if (j%8 == 0) - t += 8; - } while (j<16); - - do - { - i = j&0xf; - word32 w = s1(W[i+16-2]) + s0(W[i+16-15]) + W[i] + W[i+16-7]; - W[i+16] = W[i] = w; - w += SHA256_K[j]; - w += t[7]; - w += S1(e); - w += Ch(e, t[5], t[6]); - e = t[3] + w; - t[3] = t[3+8] = e; - w += S0(t[0]); - a = w + Maj(a, t[1], t[2]); - t[-1] = t[7] = a; - - w = s1(W[(i+1)+16-2]) + s0(W[(i+1)+16-15]) + W[(i+1)] + W[(i+1)+16-7]; - W[(i+1)+16] = W[(i+1)] = w; - w += SHA256_K[j+1]; - w += (t-1)[7]; - w += S1(e); - w += Ch(e, (t-1)[5], (t-1)[6]); - e = (t-1)[3] + w; - (t-1)[3] = (t-1)[3+8] = e; - w += S0((t-1)[0]); - a = w + Maj(a, (t-1)[1], (t-1)[2]); - (t-1)[-1] = (t-1)[7] = a; - - t-=2; - j+=2; - if (j%8 == 0) - t += 8; - } while (j<64); - - state[0] += a; - state[1] += t[1]; - state[2] += t[2]; - state[3] += t[3]; - state[4] += e; - state[5] += t[5]; - state[6] += t[6]; - state[7] += t[7]; -} -*/ - -#undef S0 -#undef S1 -#undef s0 -#undef s1 -#undef R - -// ************************************************************* - -void SHA384::InitState(HashWordType *state) -{ - static const word64 s[8] = { - W64LIT(0xcbbb9d5dc1059ed8), W64LIT(0x629a292a367cd507), - W64LIT(0x9159015a3070dd17), W64LIT(0x152fecd8f70e5939), - W64LIT(0x67332667ffc00b31), W64LIT(0x8eb44a8768581511), - W64LIT(0xdb0c2e0d64f98fa7), W64LIT(0x47b5481dbefa4fa4)}; - memcpy(state, s, sizeof(s)); -} - -void SHA512::InitState(HashWordType *state) -{ - static const word64 s[8] = { - W64LIT(0x6a09e667f3bcc908), W64LIT(0xbb67ae8584caa73b), - W64LIT(0x3c6ef372fe94f82b), W64LIT(0xa54ff53a5f1d36f1), - W64LIT(0x510e527fade682d1), W64LIT(0x9b05688c2b3e6c1f), - W64LIT(0x1f83d9abfb41bd6b), W64LIT(0x5be0cd19137e2179)}; - memcpy(state, s, sizeof(s)); -} - -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86 -CRYPTOPP_ALIGN_DATA(16) static const word64 SHA512_K[80] CRYPTOPP_SECTION_ALIGN16 = { -#else -static const word64 SHA512_K[80] = { -#endif - W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd), - W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc), - W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019), - W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118), - W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe), - W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2), - W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1), - W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694), - W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3), - W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65), - W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483), - W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5), - W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210), - W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4), - W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725), - W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70), - W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926), - W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df), - W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8), - W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b), - W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001), - W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30), - W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910), - W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8), - W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53), - W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8), - W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb), - W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3), - W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60), - W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec), - W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9), - W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b), - W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207), - W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178), - W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6), - W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b), - W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493), - W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c), - W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a), - W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817) -}; - -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86 -// put assembly version in separate function, otherwise MSVC 2005 SP1 doesn't generate correct code for the non-assembly version -CRYPTOPP_NAKED static void CRYPTOPP_FASTCALL SHA512_SSE2_Transform(word64 *state, const word64 *data) -{ -#ifdef __GNUC__ - __asm__ __volatile__ - ( - ".intel_syntax noprefix;" - AS1( push ebx) - AS2( mov ebx, eax) -#else - AS1( push ebx) - AS1( push esi) - AS1( push edi) - AS2( lea ebx, SHA512_K) -#endif - - AS2( mov eax, esp) - AS2( and esp, 0xfffffff0) - AS2( sub esp, 27*16) // 17*16 for expanded data, 20*8 for state - AS1( push eax) - AS2( xor eax, eax) - AS2( lea edi, [esp+4+8*8]) // start at middle of state buffer. will decrement pointer each round to avoid copying - AS2( lea esi, [esp+4+20*8+8]) // 16-byte alignment, then add 8 - - AS2( movdqa xmm0, [ecx+0*16]) - AS2( movdq2q mm4, xmm0) - AS2( movdqa [edi+0*16], xmm0) - AS2( movdqa xmm0, [ecx+1*16]) - AS2( movdqa [edi+1*16], xmm0) - AS2( movdqa xmm0, [ecx+2*16]) - AS2( movdq2q mm5, xmm0) - AS2( movdqa [edi+2*16], xmm0) - AS2( movdqa xmm0, [ecx+3*16]) - AS2( movdqa [edi+3*16], xmm0) - ASJ( jmp, 0, f) - -#define SSE2_S0_S1(r, a, b, c) \ - AS2( movq mm6, r)\ - AS2( psrlq r, a)\ - AS2( movq mm7, r)\ - AS2( psllq mm6, 64-c)\ - AS2( pxor mm7, mm6)\ - AS2( psrlq r, b-a)\ - AS2( pxor mm7, r)\ - AS2( psllq mm6, c-b)\ - AS2( pxor mm7, mm6)\ - AS2( psrlq r, c-b)\ - AS2( pxor r, mm7)\ - AS2( psllq mm6, b-a)\ - AS2( pxor r, mm6) - -#define SSE2_s0(r, a, b, c) \ - AS2( movdqa xmm6, r)\ - AS2( psrlq r, a)\ - AS2( movdqa xmm7, r)\ - AS2( psllq xmm6, 64-c)\ - AS2( pxor xmm7, xmm6)\ - AS2( psrlq r, b-a)\ - AS2( pxor xmm7, r)\ - AS2( psrlq r, c-b)\ - AS2( pxor r, xmm7)\ - AS2( psllq xmm6, c-a)\ - AS2( pxor r, xmm6) - -#define SSE2_s1(r, a, b, c) \ - AS2( movdqa xmm6, r)\ - AS2( psrlq r, a)\ - AS2( movdqa xmm7, r)\ - AS2( psllq xmm6, 64-c)\ - AS2( pxor xmm7, xmm6)\ - AS2( psrlq r, b-a)\ - AS2( pxor xmm7, r)\ - AS2( psllq xmm6, c-b)\ - AS2( pxor xmm7, xmm6)\ - AS2( psrlq r, c-b)\ - AS2( pxor r, xmm7) - - ASL(SHA512_Round) - // k + w is in mm0, a is in mm4, e is in mm5 - AS2( paddq mm0, [edi+7*8]) // h - AS2( movq mm2, [edi+5*8]) // f - AS2( movq mm3, [edi+6*8]) // g - AS2( pxor mm2, mm3) - AS2( pand mm2, mm5) - SSE2_S0_S1(mm5,14,18,41) - AS2( pxor mm2, mm3) - AS2( paddq mm0, mm2) // h += Ch(e,f,g) - AS2( paddq mm5, mm0) // h += S1(e) - AS2( movq mm2, [edi+1*8]) // b - AS2( movq mm1, mm2) - AS2( por mm2, mm4) - AS2( pand mm2, [edi+2*8]) // c - AS2( pand mm1, mm4) - AS2( por mm1, mm2) - AS2( paddq mm1, mm5) // temp = h + Maj(a,b,c) - AS2( paddq mm5, [edi+3*8]) // e = d + h - AS2( movq [edi+3*8], mm5) - AS2( movq [edi+11*8], mm5) - SSE2_S0_S1(mm4,28,34,39) // S0(a) - AS2( paddq mm4, mm1) // a = temp + S0(a) - AS2( movq [edi-8], mm4) - AS2( movq [edi+7*8], mm4) - AS1( ret) - - // first 16 rounds - ASL(0) - AS2( movq mm0, [edx+eax*8]) - AS2( movq [esi+eax*8], mm0) - AS2( movq [esi+eax*8+16*8], mm0) - AS2( paddq mm0, [ebx+eax*8]) - ASC( call, SHA512_Round) - AS1( inc eax) - AS2( sub edi, 8) - AS2( test eax, 7) - ASJ( jnz, 0, b) - AS2( add edi, 8*8) - AS2( cmp eax, 16) - ASJ( jne, 0, b) - - // rest of the rounds - AS2( movdqu xmm0, [esi+(16-2)*8]) - ASL(1) - // data expansion, W[i-2] already in xmm0 - AS2( movdqu xmm3, [esi]) - AS2( paddq xmm3, [esi+(16-7)*8]) - AS2( movdqa xmm2, [esi+(16-15)*8]) - SSE2_s1(xmm0, 6, 19, 61) - AS2( paddq xmm0, xmm3) - SSE2_s0(xmm2, 1, 7, 8) - AS2( paddq xmm0, xmm2) - AS2( movdq2q mm0, xmm0) - AS2( movhlps xmm1, xmm0) - AS2( paddq mm0, [ebx+eax*8]) - AS2( movlps [esi], xmm0) - AS2( movlps [esi+8], xmm1) - AS2( movlps [esi+8*16], xmm0) - AS2( movlps [esi+8*17], xmm1) - // 2 rounds - ASC( call, SHA512_Round) - AS2( sub edi, 8) - AS2( movdq2q mm0, xmm1) - AS2( paddq mm0, [ebx+eax*8+8]) - ASC( call, SHA512_Round) - // update indices and loop - AS2( add esi, 16) - AS2( add eax, 2) - AS2( sub edi, 8) - AS2( test eax, 7) - ASJ( jnz, 1, b) - // do housekeeping every 8 rounds - AS2( mov esi, 0xf) - AS2( and esi, eax) - AS2( lea esi, [esp+4+20*8+8+esi*8]) - AS2( add edi, 8*8) - AS2( cmp eax, 80) - ASJ( jne, 1, b) - -#define SSE2_CombineState(i) \ - AS2( movdqa xmm0, [edi+i*16])\ - AS2( paddq xmm0, [ecx+i*16])\ - AS2( movdqa [ecx+i*16], xmm0) - - SSE2_CombineState(0) - SSE2_CombineState(1) - SSE2_CombineState(2) - SSE2_CombineState(3) - - AS1( pop esp) - AS1( emms) - -#if defined(__GNUC__) - AS1( pop ebx) - ".att_syntax prefix;" - : - : "a" (SHA512_K), "c" (state), "d" (data) - : "%esi", "%edi", "memory", "cc" - ); -#else - AS1( pop edi) - AS1( pop esi) - AS1( pop ebx) - AS1( ret) -#endif -} -#endif // #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE - -void SHA512::Transform(word64 *state, const word64 *data) -{ -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86 - if (HasSSE2()) - { - SHA512_SSE2_Transform(state, data); - return; - } -#endif - -#define S0(x) (rotrFixed(x,28)^rotrFixed(x,34)^rotrFixed(x,39)) -#define S1(x) (rotrFixed(x,14)^rotrFixed(x,18)^rotrFixed(x,41)) -#define s0(x) (rotrFixed(x,1)^rotrFixed(x,8)^(x>>7)) -#define s1(x) (rotrFixed(x,19)^rotrFixed(x,61)^(x>>6)) - -#define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA512_K[i+j]+(j?blk2(i):blk0(i));\ - d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)) - - word64 W[16]; - word64 T[8]; - /* Copy context->state[] to working vars */ - memcpy(T, state, sizeof(T)); - /* 80 operations, partially loop unrolled */ - for (unsigned int j=0; j<80; j+=16) - { - R( 0); R( 1); R( 2); R( 3); - R( 4); R( 5); R( 6); R( 7); - R( 8); R( 9); R(10); R(11); - R(12); R(13); R(14); R(15); - } - /* Add the working vars back into context.state[] */ - state[0] += a(0); - state[1] += b(0); - state[2] += c(0); - state[3] += d(0); - state[4] += e(0); - state[5] += f(0); - state[6] += g(0); - state[7] += h(0); -} - -NAMESPACE_END - -#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM -#endif // #ifndef CRYPTOPP_IMPORTS diff --git a/embeddedcryptopp/sha.h b/embeddedcryptopp/sha.h deleted file mode 100644 index 679081e..0000000 --- a/embeddedcryptopp/sha.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef CRYPTOPP_SHA_H -#define CRYPTOPP_SHA_H - -#include "iterhash.h" - -NAMESPACE_BEGIN(CryptoPP) - -/// SHA-1 -class CRYPTOPP_DLL SHA1 : public IteratedHashWithStaticTransform -{ -public: - static void CRYPTOPP_API InitState(HashWordType *state); - static void CRYPTOPP_API Transform(word32 *digest, const word32 *data); - static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-1";} -}; - -typedef SHA1 SHA; // for backwards compatibility - -//! implements the SHA-256 standard -class CRYPTOPP_DLL SHA256 : public IteratedHashWithStaticTransform -{ -public: -#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE) - size_t HashMultipleBlocks(const word32 *input, size_t length); -#endif - static void CRYPTOPP_API InitState(HashWordType *state); - static void CRYPTOPP_API Transform(word32 *digest, const word32 *data); - static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-256";} -}; - -//! implements the SHA-224 standard -class CRYPTOPP_DLL SHA224 : public IteratedHashWithStaticTransform -{ -public: -#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE) - size_t HashMultipleBlocks(const word32 *input, size_t length); -#endif - static void CRYPTOPP_API InitState(HashWordType *state); - static void CRYPTOPP_API Transform(word32 *digest, const word32 *data) {SHA256::Transform(digest, data);} - static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-224";} -}; - -//! implements the SHA-512 standard -class CRYPTOPP_DLL SHA512 : public IteratedHashWithStaticTransform -{ -public: - static void CRYPTOPP_API InitState(HashWordType *state); - static void CRYPTOPP_API Transform(word64 *digest, const word64 *data); - static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-512";} -}; - -//! implements the SHA-384 standard -class CRYPTOPP_DLL SHA384 : public IteratedHashWithStaticTransform -{ -public: - static void CRYPTOPP_API InitState(HashWordType *state); - static void CRYPTOPP_API Transform(word64 *digest, const word64 *data) {SHA512::Transform(digest, data);} - static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-384";} -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/simple.h b/embeddedcryptopp/simple.h deleted file mode 100644 index 35fd65a..0000000 --- a/embeddedcryptopp/simple.h +++ /dev/null @@ -1,209 +0,0 @@ -// simple.h - written and placed in the public domain by Wei Dai -/*! \file - Simple non-interface classes derived from classes in cryptlib.h. -*/ - -#ifndef CRYPTOPP_SIMPLE_H -#define CRYPTOPP_SIMPLE_H - -#include "cryptlib.h" -#include "misc.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! _ -template -class CRYPTOPP_NO_VTABLE ClonableImpl : public BASE -{ -public: - Clonable * Clone() const {return new DERIVED(*static_cast(this));} -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE AlgorithmImpl : public BASE -{ -public: - static std::string CRYPTOPP_API StaticAlgorithmName() {return ALGORITHM_INFO::StaticAlgorithmName();} - std::string AlgorithmName() const {return ALGORITHM_INFO::StaticAlgorithmName();} -}; - -//! _ -class CRYPTOPP_DLL InvalidKeyLength : public InvalidArgument -{ -public: - explicit InvalidKeyLength(const std::string &algorithm, size_t length) : InvalidArgument(algorithm + ": " + IntToString(length) + " is not a valid key length") {} -}; - -//! _ -class CRYPTOPP_DLL InvalidRounds : public InvalidArgument -{ -public: - explicit InvalidRounds(const std::string &algorithm, unsigned int rounds) : InvalidArgument(algorithm + ": " + IntToString(rounds) + " is not a valid number of rounds") {} -}; - -// ***************************** - -//! _ -template -class CRYPTOPP_NO_VTABLE Bufferless : public T -{ -public: - bool IsolatedFlush(bool hardFlush, bool blocking) {return false;} -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE Unflushable : public T -{ -public: - bool Flush(bool completeFlush, int propagation=-1, bool blocking=true) - {return ChannelFlush(DEFAULT_CHANNEL, completeFlush, propagation, blocking);} - bool IsolatedFlush(bool hardFlush, bool blocking) - {assert(false); return false;} - bool ChannelFlush(const std::string &channel, bool hardFlush, int propagation=-1, bool blocking=true) - { - if (hardFlush && !InputBufferIsEmpty()) - throw CannotFlush("Unflushable: this object has buffered input that cannot be flushed"); - else - { - BufferedTransformation *attached = this->AttachedTransformation(); - return attached && propagation ? attached->ChannelFlush(channel, hardFlush, propagation-1, blocking) : false; - } - } - -protected: - virtual bool InputBufferIsEmpty() const {return false;} -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE InputRejecting : public T -{ -public: - struct InputRejected : public NotImplemented - {InputRejected() : NotImplemented("BufferedTransformation: this object doesn't allow input") {}}; - - // shouldn't be calling these functions on this class - size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking) - {throw InputRejected();} - bool IsolatedFlush(bool, bool) {return false;} - bool IsolatedMessageSeriesEnd(bool) {throw InputRejected();} - - size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) - {throw InputRejected();} - bool ChannelMessageSeriesEnd(const std::string &, int, bool) {throw InputRejected();} -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE CustomFlushPropagation : public T -{ -public: - virtual bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) =0; - -private: - bool IsolatedFlush(bool hardFlush, bool blocking) {assert(false); return false;} -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE CustomSignalPropagation : public CustomFlushPropagation -{ -public: - virtual void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1) =0; - -private: - void IsolatedInitialize(const NameValuePairs ¶meters) {assert(false);} -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE Multichannel : public CustomFlushPropagation -{ -public: - bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) - {return this->ChannelFlush(DEFAULT_CHANNEL, hardFlush, propagation, blocking);} - bool MessageSeriesEnd(int propagation=-1, bool blocking=true) - {return this->ChannelMessageSeriesEnd(DEFAULT_CHANNEL, propagation, blocking);} - byte * CreatePutSpace(size_t &size) - {return this->ChannelCreatePutSpace(DEFAULT_CHANNEL, size);} - size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking) - {return this->ChannelPut2(DEFAULT_CHANNEL, begin, length, messageEnd, blocking);} - size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking) - {return this->ChannelPutModifiable2(DEFAULT_CHANNEL, inString, length, messageEnd, blocking);} - -// void ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1) -// {PropagateMessageSeriesEnd(propagation, channel);} - byte * ChannelCreatePutSpace(const std::string &channel, size_t &size) - {size = 0; return NULL;} - bool ChannelPutModifiable(const std::string &channel, byte *inString, size_t length) - {this->ChannelPut(channel, inString, length); return false;} - - virtual size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) =0; - size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking) - {return ChannelPut2(channel, begin, length, messageEnd, blocking);} - - virtual bool ChannelFlush(const std::string &channel, bool hardFlush, int propagation=-1, bool blocking=true) =0; -}; - -//! _ -template -class CRYPTOPP_NO_VTABLE AutoSignaling : public T -{ -public: - AutoSignaling(int propagation=-1) : m_autoSignalPropagation(propagation) {} - - void SetAutoSignalPropagation(int propagation) - {m_autoSignalPropagation = propagation;} - int GetAutoSignalPropagation() const - {return m_autoSignalPropagation;} - -private: - int m_autoSignalPropagation; -}; - -//! A BufferedTransformation that only contains pre-existing data as "output" -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Store : public AutoSignaling > -{ -public: - Store() : m_messageEnd(false) {} - - void IsolatedInitialize(const NameValuePairs ¶meters) - { - m_messageEnd = false; - StoreInitialize(parameters); - } - - unsigned int NumberOfMessages() const {return m_messageEnd ? 0 : 1;} - bool GetNextMessage(); - unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL) const; - -protected: - virtual void StoreInitialize(const NameValuePairs ¶meters) =0; - - bool m_messageEnd; -}; - -//! A BufferedTransformation that doesn't produce any retrievable output -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Sink : public BufferedTransformation -{ -public: - size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) - {transferBytes = 0; return 0;} - size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const - {return 0;} -}; - -class CRYPTOPP_DLL BitBucket : public Bufferless -{ -public: - std::string AlgorithmName() const {return "BitBucket";} - void IsolatedInitialize(const NameValuePairs ¶meters) {} - size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking) - {return 0;} -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/skipjack.h b/embeddedcryptopp/skipjack.h deleted file mode 100644 index 2cf10d2..0000000 --- a/embeddedcryptopp/skipjack.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef CRYPTOPP_SKIPJACK_H -#define CRYPTOPP_SKIPJACK_H - -/** \file -*/ - -#include "seckey.h" -#include "secblock.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! _ -struct SKIPJACK_Info : public FixedBlockSize<8>, public FixedKeyLength<10> -{ - CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return "SKIPJACK";} -}; - -/// SKIPJACK -class SKIPJACK : public SKIPJACK_Info, public BlockCipherDocumentation -{ - class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl - { - public: - void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); - unsigned int OptimalDataAlignment() const {return GetAlignmentOf();} - - protected: - static const byte fTable[256]; - - FixedSizeSecBlock tab; - }; - - class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Enc : public Base - { - public: - void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; - private: - static const byte Se[256]; - static const word32 Te[4][256]; - }; - - class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Dec : public Base - { - public: - void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; - private: - static const byte Sd[256]; - static const word32 Td[4][256]; - }; - -public: - typedef BlockCipherFinal Encryption; - typedef BlockCipherFinal Decryption; -}; - -typedef SKIPJACK::Encryption SKIPJACKEncryption; -typedef SKIPJACK::Decryption SKIPJACKDecryption; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/smartptr.h b/embeddedcryptopp/smartptr.h deleted file mode 100644 index 6b4040e..0000000 --- a/embeddedcryptopp/smartptr.h +++ /dev/null @@ -1,223 +0,0 @@ -#ifndef CRYPTOPP_SMARTPTR_H -#define CRYPTOPP_SMARTPTR_H - -#include "config.h" -#include - -NAMESPACE_BEGIN(CryptoPP) - -template class simple_ptr -{ -public: - simple_ptr() : m_p(NULL) {} - ~simple_ptr() {delete m_p;} - T *m_p; -}; - -template class member_ptr -{ -public: - explicit member_ptr(T *p = NULL) : m_p(p) {} - - ~member_ptr(); - - const T& operator*() const { return *m_p; } - T& operator*() { return *m_p; } - - const T* operator->() const { return m_p; } - T* operator->() { return m_p; } - - const T* get() const { return m_p; } - T* get() { return m_p; } - - T* release() - { - T *old_p = m_p; - m_p = 0; - return old_p; - } - - void reset(T *p = 0); - -protected: - member_ptr(const member_ptr& rhs); // copy not allowed - void operator=(const member_ptr& rhs); // assignment not allowed - - T *m_p; -}; - -template member_ptr::~member_ptr() {delete m_p;} -template void member_ptr::reset(T *p) {delete m_p; m_p = p;} - -// ******************************************************** - -template class value_ptr : public member_ptr -{ -public: - value_ptr(const T &obj) : member_ptr(new T(obj)) {} - value_ptr(T *p = NULL) : member_ptr(p) {} - value_ptr(const value_ptr& rhs) - : member_ptr(rhs.m_p ? new T(*rhs.m_p) : NULL) {} - - value_ptr& operator=(const value_ptr& rhs); - bool operator==(const value_ptr& rhs) - { - return (!this->m_p && !rhs.m_p) || (this->m_p && rhs.m_p && *this->m_p == *rhs.m_p); - } -}; - -template value_ptr& value_ptr::operator=(const value_ptr& rhs) -{ - T *old_p = this->m_p; - this->m_p = rhs.m_p ? new T(*rhs.m_p) : NULL; - delete old_p; - return *this; -} - -// ******************************************************** - -template class clonable_ptr : public member_ptr -{ -public: - clonable_ptr(const T &obj) : member_ptr(obj.Clone()) {} - clonable_ptr(T *p = NULL) : member_ptr(p) {} - clonable_ptr(const clonable_ptr& rhs) - : member_ptr(rhs.m_p ? rhs.m_p->Clone() : NULL) {} - - clonable_ptr& operator=(const clonable_ptr& rhs); -}; - -template clonable_ptr& clonable_ptr::operator=(const clonable_ptr& rhs) -{ - T *old_p = this->m_p; - this->m_p = rhs.m_p ? rhs.m_p->Clone() : NULL; - delete old_p; - return *this; -} - -// ******************************************************** - -template class counted_ptr -{ -public: - explicit counted_ptr(T *p = 0); - counted_ptr(const T &r) : m_p(0) {attach(r);} - counted_ptr(const counted_ptr& rhs); - - ~counted_ptr(); - - const T& operator*() const { return *m_p; } - T& operator*() { return *m_p; } - - const T* operator->() const { return m_p; } - T* operator->() { return get(); } - - const T* get() const { return m_p; } - T* get(); - - void attach(const T &p); - - counted_ptr & operator=(const counted_ptr& rhs); - -private: - T *m_p; -}; - -template counted_ptr::counted_ptr(T *p) - : m_p(p) -{ - if (m_p) - m_p->m_referenceCount = 1; -} - -template counted_ptr::counted_ptr(const counted_ptr& rhs) - : m_p(rhs.m_p) -{ - if (m_p) - m_p->m_referenceCount++; -} - -template counted_ptr::~counted_ptr() -{ - if (m_p && --m_p->m_referenceCount == 0) - delete m_p; -} - -template void counted_ptr::attach(const T &r) -{ - if (m_p && --m_p->m_referenceCount == 0) - delete m_p; - if (r.m_referenceCount == 0) - { - m_p = r.clone(); - m_p->m_referenceCount = 1; - } - else - { - m_p = const_cast(&r); - m_p->m_referenceCount++; - } -} - -template T* counted_ptr::get() -{ - if (m_p && m_p->m_referenceCount > 1) - { - T *temp = m_p->clone(); - m_p->m_referenceCount--; - m_p = temp; - m_p->m_referenceCount = 1; - } - return m_p; -} - -template counted_ptr & counted_ptr::operator=(const counted_ptr& rhs) -{ - if (m_p != rhs.m_p) - { - if (m_p && --m_p->m_referenceCount == 0) - delete m_p; - m_p = rhs.m_p; - if (m_p) - m_p->m_referenceCount++; - } - return *this; -} - -// ******************************************************** - -template class vector_member_ptrs -{ -public: - vector_member_ptrs(size_t size=0) - : m_size(size), m_ptr(new member_ptr[size]) {} - ~vector_member_ptrs() - {delete [] this->m_ptr;} - - member_ptr& operator[](size_t index) - {assert(indexm_size); return this->m_ptr[index];} - const member_ptr& operator[](size_t index) const - {assert(indexm_size); return this->m_ptr[index];} - - size_t size() const {return this->m_size;} - void resize(size_t newSize) - { - member_ptr *newPtr = new member_ptr[newSize]; - for (size_t i=0; im_size && im_ptr[i].release()); - delete [] this->m_ptr; - this->m_size = newSize; - this->m_ptr = newPtr; - } - -private: - vector_member_ptrs(const vector_member_ptrs &c); // copy not allowed - void operator=(const vector_member_ptrs &x); // assignment not allowed - - size_t m_size; - member_ptr *m_ptr; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/sosemanuk.cpp b/embeddedcryptopp/sosemanuk.cpp deleted file mode 100644 index 0863675..0000000 --- a/embeddedcryptopp/sosemanuk.cpp +++ /dev/null @@ -1,711 +0,0 @@ -// sosemanuk.cpp - written and placed in the public domain by Wei Dai - -// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM sosemanuk.cpp" to generate MASM code - -#include "pch.h" - -#ifndef CRYPTOPP_GENERATE_X64_MASM - -#include "sosemanuk.h" -#include "misc.h" -#include "cpu.h" - -#include "serpentp.h" - -NAMESPACE_BEGIN(CryptoPP) - -void SosemanukPolicy::CipherSetKey(const NameValuePairs ¶ms, const byte *userKey, size_t keylen) -{ - Serpent_KeySchedule(m_key, 24, userKey, keylen); -} - -void SosemanukPolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) -{ - assert(length==16); - - word32 a, b, c, d, e; - - typedef BlockGetAndPut Block; - Block::Get(iv)(a)(b)(c)(d); - - const word32 *k = m_key; - unsigned int i=1; - - do - { - beforeS0(KX); beforeS0(S0); afterS0(LT); - afterS0(KX); afterS0(S1); afterS1(LT); - if (i == 3) // after 18th round - { - m_state[4] = b; - m_state[5] = e; - m_state[10] = c; - m_state[11] = a; - } - afterS1(KX); afterS1(S2); afterS2(LT); - afterS2(KX); afterS2(S3); afterS3(LT); - if (i == 2) // after 12th round - { - m_state[6] = c; - m_state[7] = d; - m_state[8] = b; - m_state[9] = e; - } - afterS3(KX); afterS3(S4); afterS4(LT); - afterS4(KX); afterS4(S5); afterS5(LT); - afterS5(KX); afterS5(S6); afterS6(LT); - afterS6(KX); afterS6(S7); afterS7(LT); - - if (i == 3) - break; - - ++i; - c = b; - b = e; - e = d; - d = a; - a = e; - k += 32; - } - while (true); - - afterS7(KX); - - m_state[0] = a; - m_state[1] = b; - m_state[2] = e; - m_state[3] = d; - -#define XMUX(c, x, y) (x ^ (y & (0 - (c & 1)))) - m_state[11] += XMUX(m_state[10], m_state[1], m_state[8]); - m_state[10] = rotlFixed(m_state[10] * 0x54655307, 7); -} - -extern "C" { -word32 s_sosemanukMulTables[512] = { -#if CRYPTOPP_BOOL_X86 | CRYPTOPP_BOOL_X64 - 0x00000000, 0xE19FCF12, 0x6B973724, 0x8A08F836, - 0xD6876E48, 0x3718A15A, 0xBD10596C, 0x5C8F967E, - 0x05A7DC90, 0xE4381382, 0x6E30EBB4, 0x8FAF24A6, - 0xD320B2D8, 0x32BF7DCA, 0xB8B785FC, 0x59284AEE, - 0x0AE71189, 0xEB78DE9B, 0x617026AD, 0x80EFE9BF, - 0xDC607FC1, 0x3DFFB0D3, 0xB7F748E5, 0x566887F7, - 0x0F40CD19, 0xEEDF020B, 0x64D7FA3D, 0x8548352F, - 0xD9C7A351, 0x38586C43, 0xB2509475, 0x53CF5B67, - 0x146722BB, 0xF5F8EDA9, 0x7FF0159F, 0x9E6FDA8D, - 0xC2E04CF3, 0x237F83E1, 0xA9777BD7, 0x48E8B4C5, - 0x11C0FE2B, 0xF05F3139, 0x7A57C90F, 0x9BC8061D, - 0xC7479063, 0x26D85F71, 0xACD0A747, 0x4D4F6855, - 0x1E803332, 0xFF1FFC20, 0x75170416, 0x9488CB04, - 0xC8075D7A, 0x29989268, 0xA3906A5E, 0x420FA54C, - 0x1B27EFA2, 0xFAB820B0, 0x70B0D886, 0x912F1794, - 0xCDA081EA, 0x2C3F4EF8, 0xA637B6CE, 0x47A879DC, - 0x28CE44DF, 0xC9518BCD, 0x435973FB, 0xA2C6BCE9, - 0xFE492A97, 0x1FD6E585, 0x95DE1DB3, 0x7441D2A1, - 0x2D69984F, 0xCCF6575D, 0x46FEAF6B, 0xA7616079, - 0xFBEEF607, 0x1A713915, 0x9079C123, 0x71E60E31, - 0x22295556, 0xC3B69A44, 0x49BE6272, 0xA821AD60, - 0xF4AE3B1E, 0x1531F40C, 0x9F390C3A, 0x7EA6C328, - 0x278E89C6, 0xC61146D4, 0x4C19BEE2, 0xAD8671F0, - 0xF109E78E, 0x1096289C, 0x9A9ED0AA, 0x7B011FB8, - 0x3CA96664, 0xDD36A976, 0x573E5140, 0xB6A19E52, - 0xEA2E082C, 0x0BB1C73E, 0x81B93F08, 0x6026F01A, - 0x390EBAF4, 0xD89175E6, 0x52998DD0, 0xB30642C2, - 0xEF89D4BC, 0x0E161BAE, 0x841EE398, 0x65812C8A, - 0x364E77ED, 0xD7D1B8FF, 0x5DD940C9, 0xBC468FDB, - 0xE0C919A5, 0x0156D6B7, 0x8B5E2E81, 0x6AC1E193, - 0x33E9AB7D, 0xD276646F, 0x587E9C59, 0xB9E1534B, - 0xE56EC535, 0x04F10A27, 0x8EF9F211, 0x6F663D03, - 0x50358817, 0xB1AA4705, 0x3BA2BF33, 0xDA3D7021, - 0x86B2E65F, 0x672D294D, 0xED25D17B, 0x0CBA1E69, - 0x55925487, 0xB40D9B95, 0x3E0563A3, 0xDF9AACB1, - 0x83153ACF, 0x628AF5DD, 0xE8820DEB, 0x091DC2F9, - 0x5AD2999E, 0xBB4D568C, 0x3145AEBA, 0xD0DA61A8, - 0x8C55F7D6, 0x6DCA38C4, 0xE7C2C0F2, 0x065D0FE0, - 0x5F75450E, 0xBEEA8A1C, 0x34E2722A, 0xD57DBD38, - 0x89F22B46, 0x686DE454, 0xE2651C62, 0x03FAD370, - 0x4452AAAC, 0xA5CD65BE, 0x2FC59D88, 0xCE5A529A, - 0x92D5C4E4, 0x734A0BF6, 0xF942F3C0, 0x18DD3CD2, - 0x41F5763C, 0xA06AB92E, 0x2A624118, 0xCBFD8E0A, - 0x97721874, 0x76EDD766, 0xFCE52F50, 0x1D7AE042, - 0x4EB5BB25, 0xAF2A7437, 0x25228C01, 0xC4BD4313, - 0x9832D56D, 0x79AD1A7F, 0xF3A5E249, 0x123A2D5B, - 0x4B1267B5, 0xAA8DA8A7, 0x20855091, 0xC11A9F83, - 0x9D9509FD, 0x7C0AC6EF, 0xF6023ED9, 0x179DF1CB, - 0x78FBCCC8, 0x996403DA, 0x136CFBEC, 0xF2F334FE, - 0xAE7CA280, 0x4FE36D92, 0xC5EB95A4, 0x24745AB6, - 0x7D5C1058, 0x9CC3DF4A, 0x16CB277C, 0xF754E86E, - 0xABDB7E10, 0x4A44B102, 0xC04C4934, 0x21D38626, - 0x721CDD41, 0x93831253, 0x198BEA65, 0xF8142577, - 0xA49BB309, 0x45047C1B, 0xCF0C842D, 0x2E934B3F, - 0x77BB01D1, 0x9624CEC3, 0x1C2C36F5, 0xFDB3F9E7, - 0xA13C6F99, 0x40A3A08B, 0xCAAB58BD, 0x2B3497AF, - 0x6C9CEE73, 0x8D032161, 0x070BD957, 0xE6941645, - 0xBA1B803B, 0x5B844F29, 0xD18CB71F, 0x3013780D, - 0x693B32E3, 0x88A4FDF1, 0x02AC05C7, 0xE333CAD5, - 0xBFBC5CAB, 0x5E2393B9, 0xD42B6B8F, 0x35B4A49D, - 0x667BFFFA, 0x87E430E8, 0x0DECC8DE, 0xEC7307CC, - 0xB0FC91B2, 0x51635EA0, 0xDB6BA696, 0x3AF46984, - 0x63DC236A, 0x8243EC78, 0x084B144E, 0xE9D4DB5C, - 0xB55B4D22, 0x54C48230, 0xDECC7A06, 0x3F53B514, -#else - 0x00000000, 0xE19FCF13, 0x6B973726, 0x8A08F835, - 0xD6876E4C, 0x3718A15F, 0xBD10596A, 0x5C8F9679, - 0x05A7DC98, 0xE438138B, 0x6E30EBBE, 0x8FAF24AD, - 0xD320B2D4, 0x32BF7DC7, 0xB8B785F2, 0x59284AE1, - 0x0AE71199, 0xEB78DE8A, 0x617026BF, 0x80EFE9AC, - 0xDC607FD5, 0x3DFFB0C6, 0xB7F748F3, 0x566887E0, - 0x0F40CD01, 0xEEDF0212, 0x64D7FA27, 0x85483534, - 0xD9C7A34D, 0x38586C5E, 0xB250946B, 0x53CF5B78, - 0x1467229B, 0xF5F8ED88, 0x7FF015BD, 0x9E6FDAAE, - 0xC2E04CD7, 0x237F83C4, 0xA9777BF1, 0x48E8B4E2, - 0x11C0FE03, 0xF05F3110, 0x7A57C925, 0x9BC80636, - 0xC747904F, 0x26D85F5C, 0xACD0A769, 0x4D4F687A, - 0x1E803302, 0xFF1FFC11, 0x75170424, 0x9488CB37, - 0xC8075D4E, 0x2998925D, 0xA3906A68, 0x420FA57B, - 0x1B27EF9A, 0xFAB82089, 0x70B0D8BC, 0x912F17AF, - 0xCDA081D6, 0x2C3F4EC5, 0xA637B6F0, 0x47A879E3, - 0x28CE449F, 0xC9518B8C, 0x435973B9, 0xA2C6BCAA, - 0xFE492AD3, 0x1FD6E5C0, 0x95DE1DF5, 0x7441D2E6, - 0x2D699807, 0xCCF65714, 0x46FEAF21, 0xA7616032, - 0xFBEEF64B, 0x1A713958, 0x9079C16D, 0x71E60E7E, - 0x22295506, 0xC3B69A15, 0x49BE6220, 0xA821AD33, - 0xF4AE3B4A, 0x1531F459, 0x9F390C6C, 0x7EA6C37F, - 0x278E899E, 0xC611468D, 0x4C19BEB8, 0xAD8671AB, - 0xF109E7D2, 0x109628C1, 0x9A9ED0F4, 0x7B011FE7, - 0x3CA96604, 0xDD36A917, 0x573E5122, 0xB6A19E31, - 0xEA2E0848, 0x0BB1C75B, 0x81B93F6E, 0x6026F07D, - 0x390EBA9C, 0xD891758F, 0x52998DBA, 0xB30642A9, - 0xEF89D4D0, 0x0E161BC3, 0x841EE3F6, 0x65812CE5, - 0x364E779D, 0xD7D1B88E, 0x5DD940BB, 0xBC468FA8, - 0xE0C919D1, 0x0156D6C2, 0x8B5E2EF7, 0x6AC1E1E4, - 0x33E9AB05, 0xD2766416, 0x587E9C23, 0xB9E15330, - 0xE56EC549, 0x04F10A5A, 0x8EF9F26F, 0x6F663D7C, - 0x50358897, 0xB1AA4784, 0x3BA2BFB1, 0xDA3D70A2, - 0x86B2E6DB, 0x672D29C8, 0xED25D1FD, 0x0CBA1EEE, - 0x5592540F, 0xB40D9B1C, 0x3E056329, 0xDF9AAC3A, - 0x83153A43, 0x628AF550, 0xE8820D65, 0x091DC276, - 0x5AD2990E, 0xBB4D561D, 0x3145AE28, 0xD0DA613B, - 0x8C55F742, 0x6DCA3851, 0xE7C2C064, 0x065D0F77, - 0x5F754596, 0xBEEA8A85, 0x34E272B0, 0xD57DBDA3, - 0x89F22BDA, 0x686DE4C9, 0xE2651CFC, 0x03FAD3EF, - 0x4452AA0C, 0xA5CD651F, 0x2FC59D2A, 0xCE5A5239, - 0x92D5C440, 0x734A0B53, 0xF942F366, 0x18DD3C75, - 0x41F57694, 0xA06AB987, 0x2A6241B2, 0xCBFD8EA1, - 0x977218D8, 0x76EDD7CB, 0xFCE52FFE, 0x1D7AE0ED, - 0x4EB5BB95, 0xAF2A7486, 0x25228CB3, 0xC4BD43A0, - 0x9832D5D9, 0x79AD1ACA, 0xF3A5E2FF, 0x123A2DEC, - 0x4B12670D, 0xAA8DA81E, 0x2085502B, 0xC11A9F38, - 0x9D950941, 0x7C0AC652, 0xF6023E67, 0x179DF174, - 0x78FBCC08, 0x9964031B, 0x136CFB2E, 0xF2F3343D, - 0xAE7CA244, 0x4FE36D57, 0xC5EB9562, 0x24745A71, - 0x7D5C1090, 0x9CC3DF83, 0x16CB27B6, 0xF754E8A5, - 0xABDB7EDC, 0x4A44B1CF, 0xC04C49FA, 0x21D386E9, - 0x721CDD91, 0x93831282, 0x198BEAB7, 0xF81425A4, - 0xA49BB3DD, 0x45047CCE, 0xCF0C84FB, 0x2E934BE8, - 0x77BB0109, 0x9624CE1A, 0x1C2C362F, 0xFDB3F93C, - 0xA13C6F45, 0x40A3A056, 0xCAAB5863, 0x2B349770, - 0x6C9CEE93, 0x8D032180, 0x070BD9B5, 0xE69416A6, - 0xBA1B80DF, 0x5B844FCC, 0xD18CB7F9, 0x301378EA, - 0x693B320B, 0x88A4FD18, 0x02AC052D, 0xE333CA3E, - 0xBFBC5C47, 0x5E239354, 0xD42B6B61, 0x35B4A472, - 0x667BFF0A, 0x87E43019, 0x0DECC82C, 0xEC73073F, - 0xB0FC9146, 0x51635E55, 0xDB6BA660, 0x3AF46973, - 0x63DC2392, 0x8243EC81, 0x084B14B4, 0xE9D4DBA7, - 0xB55B4DDE, 0x54C482CD, 0xDECC7AF8, 0x3F53B5EB, -#endif - 0x00000000, 0x180F40CD, 0x301E8033, 0x2811C0FE, - 0x603CA966, 0x7833E9AB, 0x50222955, 0x482D6998, - 0xC078FBCC, 0xD877BB01, 0xF0667BFF, 0xE8693B32, - 0xA04452AA, 0xB84B1267, 0x905AD299, 0x88559254, - 0x29F05F31, 0x31FF1FFC, 0x19EEDF02, 0x01E19FCF, - 0x49CCF657, 0x51C3B69A, 0x79D27664, 0x61DD36A9, - 0xE988A4FD, 0xF187E430, 0xD99624CE, 0xC1996403, - 0x89B40D9B, 0x91BB4D56, 0xB9AA8DA8, 0xA1A5CD65, - 0x5249BE62, 0x4A46FEAF, 0x62573E51, 0x7A587E9C, - 0x32751704, 0x2A7A57C9, 0x026B9737, 0x1A64D7FA, - 0x923145AE, 0x8A3E0563, 0xA22FC59D, 0xBA208550, - 0xF20DECC8, 0xEA02AC05, 0xC2136CFB, 0xDA1C2C36, - 0x7BB9E153, 0x63B6A19E, 0x4BA76160, 0x53A821AD, - 0x1B854835, 0x038A08F8, 0x2B9BC806, 0x339488CB, - 0xBBC11A9F, 0xA3CE5A52, 0x8BDF9AAC, 0x93D0DA61, - 0xDBFDB3F9, 0xC3F2F334, 0xEBE333CA, 0xF3EC7307, - 0xA492D5C4, 0xBC9D9509, 0x948C55F7, 0x8C83153A, - 0xC4AE7CA2, 0xDCA13C6F, 0xF4B0FC91, 0xECBFBC5C, - 0x64EA2E08, 0x7CE56EC5, 0x54F4AE3B, 0x4CFBEEF6, - 0x04D6876E, 0x1CD9C7A3, 0x34C8075D, 0x2CC74790, - 0x8D628AF5, 0x956DCA38, 0xBD7C0AC6, 0xA5734A0B, - 0xED5E2393, 0xF551635E, 0xDD40A3A0, 0xC54FE36D, - 0x4D1A7139, 0x551531F4, 0x7D04F10A, 0x650BB1C7, - 0x2D26D85F, 0x35299892, 0x1D38586C, 0x053718A1, - 0xF6DB6BA6, 0xEED42B6B, 0xC6C5EB95, 0xDECAAB58, - 0x96E7C2C0, 0x8EE8820D, 0xA6F942F3, 0xBEF6023E, - 0x36A3906A, 0x2EACD0A7, 0x06BD1059, 0x1EB25094, - 0x569F390C, 0x4E9079C1, 0x6681B93F, 0x7E8EF9F2, - 0xDF2B3497, 0xC724745A, 0xEF35B4A4, 0xF73AF469, - 0xBF179DF1, 0xA718DD3C, 0x8F091DC2, 0x97065D0F, - 0x1F53CF5B, 0x075C8F96, 0x2F4D4F68, 0x37420FA5, - 0x7F6F663D, 0x676026F0, 0x4F71E60E, 0x577EA6C3, - 0xE18D0321, 0xF98243EC, 0xD1938312, 0xC99CC3DF, - 0x81B1AA47, 0x99BEEA8A, 0xB1AF2A74, 0xA9A06AB9, - 0x21F5F8ED, 0x39FAB820, 0x11EB78DE, 0x09E43813, - 0x41C9518B, 0x59C61146, 0x71D7D1B8, 0x69D89175, - 0xC87D5C10, 0xD0721CDD, 0xF863DC23, 0xE06C9CEE, - 0xA841F576, 0xB04EB5BB, 0x985F7545, 0x80503588, - 0x0805A7DC, 0x100AE711, 0x381B27EF, 0x20146722, - 0x68390EBA, 0x70364E77, 0x58278E89, 0x4028CE44, - 0xB3C4BD43, 0xABCBFD8E, 0x83DA3D70, 0x9BD57DBD, - 0xD3F81425, 0xCBF754E8, 0xE3E69416, 0xFBE9D4DB, - 0x73BC468F, 0x6BB30642, 0x43A2C6BC, 0x5BAD8671, - 0x1380EFE9, 0x0B8FAF24, 0x239E6FDA, 0x3B912F17, - 0x9A34E272, 0x823BA2BF, 0xAA2A6241, 0xB225228C, - 0xFA084B14, 0xE2070BD9, 0xCA16CB27, 0xD2198BEA, - 0x5A4C19BE, 0x42435973, 0x6A52998D, 0x725DD940, - 0x3A70B0D8, 0x227FF015, 0x0A6E30EB, 0x12617026, - 0x451FD6E5, 0x5D109628, 0x750156D6, 0x6D0E161B, - 0x25237F83, 0x3D2C3F4E, 0x153DFFB0, 0x0D32BF7D, - 0x85672D29, 0x9D686DE4, 0xB579AD1A, 0xAD76EDD7, - 0xE55B844F, 0xFD54C482, 0xD545047C, 0xCD4A44B1, - 0x6CEF89D4, 0x74E0C919, 0x5CF109E7, 0x44FE492A, - 0x0CD320B2, 0x14DC607F, 0x3CCDA081, 0x24C2E04C, - 0xAC977218, 0xB49832D5, 0x9C89F22B, 0x8486B2E6, - 0xCCABDB7E, 0xD4A49BB3, 0xFCB55B4D, 0xE4BA1B80, - 0x17566887, 0x0F59284A, 0x2748E8B4, 0x3F47A879, - 0x776AC1E1, 0x6F65812C, 0x477441D2, 0x5F7B011F, - 0xD72E934B, 0xCF21D386, 0xE7301378, 0xFF3F53B5, - 0xB7123A2D, 0xAF1D7AE0, 0x870CBA1E, 0x9F03FAD3, - 0x3EA637B6, 0x26A9777B, 0x0EB8B785, 0x16B7F748, - 0x5E9A9ED0, 0x4695DE1D, 0x6E841EE3, 0x768B5E2E, - 0xFEDECC7A, 0xE6D18CB7, 0xCEC04C49, 0xD6CF0C84, - 0x9EE2651C, 0x86ED25D1, 0xAEFCE52F, 0xB6F3A5E2 -}; -} - -#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64 -unsigned int SosemanukPolicy::GetAlignment() const -{ -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE -#ifdef __INTEL_COMPILER - if (HasSSE2() && !IsP4()) // Intel compiler produces faster code for this algorithm on the P4 -#else - if (HasSSE2()) -#endif - return 16; - else -#endif - return GetAlignmentOf(); -} - -unsigned int SosemanukPolicy::GetOptimalBlockSize() const -{ -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE -#ifdef __INTEL_COMPILER - if (HasSSE2() && !IsP4()) // Intel compiler produces faster code for this algorithm on the P4 -#else - if (HasSSE2()) -#endif - return 4*BYTES_PER_ITERATION; - else -#endif - return BYTES_PER_ITERATION; -} -#endif - -#ifdef CRYPTOPP_X64_MASM_AVAILABLE -extern "C" { -void Sosemanuk_OperateKeystream(size_t iterationCount, const byte *input, byte *output, word32 *state); -} -#endif - -#pragma warning(disable: 4731) // frame pointer register 'ebp' modified by inline assembly code - -void SosemanukPolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) -{ -#endif // #ifdef CRYPTOPP_GENERATE_X64_MASM - -#ifdef CRYPTOPP_X64_MASM_AVAILABLE - Sosemanuk_OperateKeystream(iterationCount, input, output, m_state.data()); - return; -#endif - -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE -#ifdef CRYPTOPP_GENERATE_X64_MASM - ALIGN 8 - Sosemanuk_OperateKeystream PROC FRAME - rex_push_reg rsi - push_reg rdi - alloc_stack(80*4*2+12*4+8*WORD_SZ + 2*16+8) - save_xmm128 xmm6, 02f0h - save_xmm128 xmm7, 0300h - .endprolog - mov rdi, r8 - mov rax, r9 -#else -#ifdef __INTEL_COMPILER - if (HasSSE2() && !IsP4()) // Intel compiler produces faster code for this algorithm on the P4 -#else - if (HasSSE2()) -#endif - { -#ifdef __GNUC__ - #if CRYPTOPP_BOOL_X64 - FixedSizeAlignedSecBlock workspace; - #endif - __asm__ __volatile__ - ( - ".intel_syntax noprefix;" - AS_PUSH_IF86( bx) -#else - word32 *state = m_state; - AS2( mov WORD_REG(ax), state) - AS2( mov WORD_REG(di), output) - AS2( mov WORD_REG(dx), input) - AS2( mov WORD_REG(cx), iterationCount) -#endif -#endif // #ifdef CRYPTOPP_GENERATE_X64_MASM - -#if defined(__GNUC__) && CRYPTOPP_BOOL_X64 - #define SSE2_workspace %5 -#else - #define SSE2_workspace WORD_REG(sp) -#endif - -#define SSE2_output WORD_PTR [SSE2_workspace+1*WORD_SZ] -#define SSE2_input WORD_PTR [SSE2_workspace+2*WORD_SZ] -#define SSE2_wordsLeft WORD_PTR [SSE2_workspace+3*WORD_SZ] -#define SSE2_diEnd WORD_PTR [SSE2_workspace+4*WORD_SZ] -#define SSE2_pMulTables WORD_PTR [SSE2_workspace+5*WORD_SZ] -#define SSE2_state WORD_PTR [SSE2_workspace+6*WORD_SZ] -#define SSE2_wordsLeft2 WORD_PTR [SSE2_workspace+7*WORD_SZ] -#define SSE2_stateCopy SSE2_workspace + 8*WORD_SZ -#define SSE2_uvStart SSE2_stateCopy + 12*4 - -#if CRYPTOPP_BOOL_X86 - AS_PUSH_IF86( bp) - AS2( mov AS_REG_6, esp) - AS2( and esp, -16) - AS2( sub esp, 80*4*2+12*4+8*WORD_SZ) // 80 v's, 80 u's, 12 state, 8 locals - AS2( mov [esp], AS_REG_6) -#endif - AS2( mov SSE2_output, WORD_REG(di)) - AS2( mov SSE2_input, WORD_REG(dx)) - AS2( mov SSE2_state, WORD_REG(ax)) -#ifndef _MSC_VER - AS2( mov SSE2_pMulTables, WORD_REG(si)) -#endif - AS2( lea WORD_REG(cx), [4*WORD_REG(cx)+WORD_REG(cx)]) - AS2( lea WORD_REG(si), [4*WORD_REG(cx)]) - AS2( mov SSE2_wordsLeft, WORD_REG(si)) - AS2( movdqa xmm0, [WORD_REG(ax)+0*16]) // copy state to stack to save a register - AS2( movdqa [SSE2_stateCopy+0*16], xmm0) - AS2( movdqa xmm0, [WORD_REG(ax)+1*16]) - AS2( movdqa [SSE2_stateCopy+1*16], xmm0) - AS2( movq xmm0, QWORD PTR [WORD_REG(ax)+2*16]) - AS2( movq QWORD PTR [SSE2_stateCopy+2*16], xmm0) - AS2( psrlq xmm0, 32) - AS2( movd AS_REG_6d, xmm0) // s(9) - AS2( mov ecx, [WORD_REG(ax)+10*4]) - AS2( mov edx, [WORD_REG(ax)+11*4]) - AS2( pcmpeqb xmm7, xmm7) // all ones - -#define s(i) SSE2_stateCopy + ASM_MOD(i,10)*4 -#define u(j) WORD_REG(di) + (ASM_MOD(j,4)*20 + (j/4)) * 4 -#define v(j) WORD_REG(di) + (ASM_MOD(j,4)*20 + (j/4)) * 4 + 80*4 - -#define R10 ecx -#define R11 edx -#define R20 edx -#define R21 ecx -// workaround bug in GAS 2.15 -#define R20r WORD_REG(dx) -#define R21r WORD_REG(cx) - -#define SSE2_STEP(i, j) \ - AS2( mov eax, [s(i+0)])\ - AS2( mov [v(i)], eax)\ - AS2( rol eax, 8)\ - AS2( lea AS_REG_7, [AS_REG_6 + R2##j##r])\ - AS2( xor AS_REG_7d, R1##j)\ - AS2( mov [u(i)], AS_REG_7d)\ - AS2( mov AS_REG_7d, 1)\ - AS2( and AS_REG_7d, R2##j)\ - AS1( neg AS_REG_7d)\ - AS2( and AS_REG_7d, AS_REG_6d)\ - AS2( xor AS_REG_6d, eax)\ - AS2( movzx eax, al)\ - AS2( xor AS_REG_6d, [WORD_REG(si)+WORD_REG(ax)*4])\ - AS2( mov eax, [s(i+3)])\ - AS2( xor AS_REG_7d, [s(i+2)])\ - AS2( add R1##j, AS_REG_7d)\ - AS2( movzx AS_REG_7d, al)\ - AS2( shr eax, 8)\ - AS2( xor AS_REG_6d, [WORD_REG(si)+1024+AS_REG_7*4])\ - AS2( xor AS_REG_6d, eax)\ - AS2( imul R2##j, AS_HEX(54655307))\ - AS2( rol R2##j, 7)\ - AS2( mov [s(i+0)], AS_REG_6d)\ - - ASL(2) // outer loop, each iteration of this processes 80 words - AS2( lea WORD_REG(di), [SSE2_uvStart]) // start of v and u - AS2( mov WORD_REG(ax), 80) - AS2( cmp WORD_REG(si), 80) - AS2( cmovg WORD_REG(si), WORD_REG(ax)) - AS2( mov SSE2_wordsLeft2, WORD_REG(si)) - AS2( lea WORD_REG(si), [WORD_REG(di)+WORD_REG(si)]) // use to end first inner loop - AS2( mov SSE2_diEnd, WORD_REG(si)) -#ifdef _MSC_VER - AS2( lea WORD_REG(si), s_sosemanukMulTables) -#else - AS2( mov WORD_REG(si), SSE2_pMulTables) -#endif - - ASL(0) // first inner loop, 20 words each, 4 iterations - SSE2_STEP(0, 0) - SSE2_STEP(1, 1) - SSE2_STEP(2, 0) - SSE2_STEP(3, 1) - SSE2_STEP(4, 0) - SSE2_STEP(5, 1) - SSE2_STEP(6, 0) - SSE2_STEP(7, 1) - SSE2_STEP(8, 0) - SSE2_STEP(9, 1) - SSE2_STEP(10, 0) - SSE2_STEP(11, 1) - SSE2_STEP(12, 0) - SSE2_STEP(13, 1) - SSE2_STEP(14, 0) - SSE2_STEP(15, 1) - SSE2_STEP(16, 0) - SSE2_STEP(17, 1) - SSE2_STEP(18, 0) - SSE2_STEP(19, 1) - // loop - AS2( add WORD_REG(di), 5*4) - AS2( cmp WORD_REG(di), SSE2_diEnd) - ASJ( jne, 0, b) - - AS2( mov WORD_REG(ax), SSE2_input) - AS2( mov AS_REG_7, SSE2_output) - AS2( lea WORD_REG(di), [SSE2_uvStart]) // start of v and u - AS2( mov WORD_REG(si), SSE2_wordsLeft2) - - ASL(1) // second inner loop, 16 words each, 5 iterations - AS2( movdqa xmm0, [WORD_REG(di)+0*20*4]) - AS2( movdqa xmm2, [WORD_REG(di)+2*20*4]) - AS2( movdqa xmm3, [WORD_REG(di)+3*20*4]) - AS2( movdqa xmm1, [WORD_REG(di)+1*20*4]) - // S2 - AS2( movdqa xmm4, xmm0) - AS2( pand xmm0, xmm2) - AS2( pxor xmm0, xmm3) - AS2( pxor xmm2, xmm1) - AS2( pxor xmm2, xmm0) - AS2( por xmm3, xmm4) - AS2( pxor xmm3, xmm1) - AS2( pxor xmm4, xmm2) - AS2( movdqa xmm1, xmm3) - AS2( por xmm3, xmm4) - AS2( pxor xmm3, xmm0) - AS2( pand xmm0, xmm1) - AS2( pxor xmm4, xmm0) - AS2( pxor xmm1, xmm3) - AS2( pxor xmm1, xmm4) - AS2( pxor xmm4, xmm7) - // xor with v - AS2( pxor xmm2, [WORD_REG(di)+80*4]) - AS2( pxor xmm3, [WORD_REG(di)+80*5]) - AS2( pxor xmm1, [WORD_REG(di)+80*6]) - AS2( pxor xmm4, [WORD_REG(di)+80*7]) - // exit loop early if less than 16 words left to output - // this is necessary because block size is 20 words, and we output 16 words in each iteration of this loop - AS2( cmp WORD_REG(si), 16) - ASJ( jl, 4, f) - // unpack - AS2( movdqa xmm6, xmm2) - AS2( punpckldq xmm2, xmm3) - AS2( movdqa xmm5, xmm1) - AS2( punpckldq xmm1, xmm4) - AS2( movdqa xmm0, xmm2) - AS2( punpcklqdq xmm2, xmm1) - AS2( punpckhqdq xmm0, xmm1) - AS2( punpckhdq xmm6, xmm3) - AS2( punpckhdq xmm5, xmm4) - AS2( movdqa xmm3, xmm6) - AS2( punpcklqdq xmm6, xmm5) - AS2( punpckhqdq xmm3, xmm5) - // output keystream - AS_XMM_OUTPUT4(SSE2_Sosemanuk_Output, WORD_REG(ax), AS_REG_7, 2,0,6,3, 1, 0,1,2,3, 4) - - // loop - AS2( add WORD_REG(di), 4*4) - AS2( sub WORD_REG(si), 16) - ASJ( jnz, 1, b) - - // outer loop - AS2( mov WORD_REG(si), SSE2_wordsLeft) - AS2( sub WORD_REG(si), 80) - ASJ( jz, 6, f) - AS2( mov SSE2_wordsLeft, WORD_REG(si)) - AS2( mov SSE2_input, WORD_REG(ax)) - AS2( mov SSE2_output, AS_REG_7) - ASJ( jmp, 2, b) - - ASL(4) // final output of less than 16 words - AS2( test WORD_REG(ax), WORD_REG(ax)) - ASJ( jz, 5, f) - AS2( movd xmm0, dword ptr [WORD_REG(ax)+0*4]) - AS2( pxor xmm2, xmm0) - AS2( movd xmm0, dword ptr [WORD_REG(ax)+1*4]) - AS2( pxor xmm3, xmm0) - AS2( movd xmm0, dword ptr [WORD_REG(ax)+2*4]) - AS2( pxor xmm1, xmm0) - AS2( movd xmm0, dword ptr [WORD_REG(ax)+3*4]) - AS2( pxor xmm4, xmm0) - AS2( add WORD_REG(ax), 16) - ASL(5) - AS2( movd dword ptr [AS_REG_7+0*4], xmm2) - AS2( movd dword ptr [AS_REG_7+1*4], xmm3) - AS2( movd dword ptr [AS_REG_7+2*4], xmm1) - AS2( movd dword ptr [AS_REG_7+3*4], xmm4) - AS2( sub WORD_REG(si), 4) - ASJ( jz, 6, f) - AS2( add AS_REG_7, 16) - AS2( psrldq xmm2, 4) - AS2( psrldq xmm3, 4) - AS2( psrldq xmm1, 4) - AS2( psrldq xmm4, 4) - ASJ( jmp, 4, b) - - ASL(6) // save state - AS2( mov AS_REG_6, SSE2_state) - AS2( movdqa xmm0, [SSE2_stateCopy+0*16]) - AS2( movdqa [AS_REG_6+0*16], xmm0) - AS2( movdqa xmm0, [SSE2_stateCopy+1*16]) - AS2( movdqa [AS_REG_6+1*16], xmm0) - AS2( movq xmm0, QWORD PTR [SSE2_stateCopy+2*16]) - AS2( movq QWORD PTR [AS_REG_6+2*16], xmm0) - AS2( mov [AS_REG_6+10*4], ecx) - AS2( mov [AS_REG_6+11*4], edx) - - AS_POP_IF86( sp) - AS_POP_IF86( bp) - -#ifdef __GNUC__ - AS_POP_IF86( bx) - ".att_syntax prefix;" - : - : "a" (m_state.m_ptr), "c" (iterationCount), "S" (s_sosemanukMulTables), "D" (output), "d" (input) - #if CRYPTOPP_BOOL_X64 - , "r" (workspace.m_ptr) - : "memory", "cc", "%r9", "%r10", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7" - #else - : "memory", "cc" - #endif - ); -#endif -#ifdef CRYPTOPP_GENERATE_X64_MASM - movdqa xmm6, [rsp + 02f0h] - movdqa xmm7, [rsp + 0300h] - add rsp, 80*4*2+12*4+8*WORD_SZ + 2*16+8 - pop rdi - pop rsi - ret - Sosemanuk_OperateKeystream ENDP -#else - } - else -#endif -#endif -#ifndef CRYPTOPP_GENERATE_X64_MASM - { -#if CRYPTOPP_BOOL_X86 | CRYPTOPP_BOOL_X64 -#define MUL_A(x) (x = rotlFixed(x, 8), x ^ s_sosemanukMulTables[byte(x)]) -#else -#define MUL_A(x) (((x) << 8) ^ s_sosemanukMulTables[(x) >> 24]) -#endif - -#define DIV_A(x) (((x) >> 8) ^ s_sosemanukMulTables[256 + byte(x)]) - -#define r1(i) ((i%2) ? reg2 : reg1) -#define r2(i) ((i%2) ? reg1 : reg2) - -#define STEP(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, v, u) \ - u = (s##x9 + r2(x0)) ^ r1(x0);\ - v = s##x0;\ - s##x0 = MUL_A(s##x0) ^ DIV_A(s##x3) ^ s##x9;\ - r1(x0) += XMUX(r2(x0), s##x2, s##x9);\ - r2(x0) = rotlFixed(r2(x0) * 0x54655307, 7);\ - -#define SOSEMANUK_OUTPUT(x) \ - CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 0, u2 ^ v0);\ - CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 1, u3 ^ v1);\ - CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 2, u1 ^ v2);\ - CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 3, u4 ^ v3); - -#define OUTPUT4 \ - S2(0, u0, u1, u2, u3, u4);\ - CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(SOSEMANUK_OUTPUT, 4*4); - - word32 s0 = m_state[0]; - word32 s1 = m_state[1]; - word32 s2 = m_state[2]; - word32 s3 = m_state[3]; - word32 s4 = m_state[4]; - word32 s5 = m_state[5]; - word32 s6 = m_state[6]; - word32 s7 = m_state[7]; - word32 s8 = m_state[8]; - word32 s9 = m_state[9]; - word32 reg1 = m_state[10]; - word32 reg2 = m_state[11]; - word32 u0, u1, u2, u3, u4, v0, v1, v2, v3; - - do - { - STEP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, v0, u0) - STEP(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, v1, u1) - STEP(2, 3, 4, 5, 6, 7, 8, 9, 0, 1, v2, u2) - STEP(3, 4, 5, 6, 7, 8, 9, 0, 1, 2, v3, u3) - OUTPUT4 - STEP(4, 5, 6, 7, 8, 9, 0, 1, 2, 3, v0, u0) - STEP(5, 6, 7, 8, 9, 0, 1, 2, 3, 4, v1, u1) - STEP(6, 7, 8, 9, 0, 1, 2, 3, 4, 5, v2, u2) - STEP(7, 8, 9, 0, 1, 2, 3, 4, 5, 6, v3, u3) - OUTPUT4 - STEP(8, 9, 0, 1, 2, 3, 4, 5, 6, 7, v0, u0) - STEP(9, 0, 1, 2, 3, 4, 5, 6, 7, 8, v1, u1) - STEP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, v2, u2) - STEP(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, v3, u3) - OUTPUT4 - STEP(2, 3, 4, 5, 6, 7, 8, 9, 0, 1, v0, u0) - STEP(3, 4, 5, 6, 7, 8, 9, 0, 1, 2, v1, u1) - STEP(4, 5, 6, 7, 8, 9, 0, 1, 2, 3, v2, u2) - STEP(5, 6, 7, 8, 9, 0, 1, 2, 3, 4, v3, u3) - OUTPUT4 - STEP(6, 7, 8, 9, 0, 1, 2, 3, 4, 5, v0, u0) - STEP(7, 8, 9, 0, 1, 2, 3, 4, 5, 6, v1, u1) - STEP(8, 9, 0, 1, 2, 3, 4, 5, 6, 7, v2, u2) - STEP(9, 0, 1, 2, 3, 4, 5, 6, 7, 8, v3, u3) - OUTPUT4 - } - while (--iterationCount); - - m_state[0] = s0; - m_state[1] = s1; - m_state[2] = s2; - m_state[3] = s3; - m_state[4] = s4; - m_state[5] = s5; - m_state[6] = s6; - m_state[7] = s7; - m_state[8] = s8; - m_state[9] = s9; - m_state[10] = reg1; - m_state[11] = reg2; - } -} - -NAMESPACE_END - -#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM diff --git a/embeddedcryptopp/sosemanuk.h b/embeddedcryptopp/sosemanuk.h deleted file mode 100644 index ff1d820..0000000 --- a/embeddedcryptopp/sosemanuk.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef CRYPTOPP_SOSEMANUK_H -#define CRYPTOPP_SOSEMANUK_H - -#include "strciphr.h" - -NAMESPACE_BEGIN(CryptoPP) - -//! algorithm info -struct SosemanukInfo : public VariableKeyLength<16, 1, 32, 1, SimpleKeyingInterface::UNIQUE_IV, 16> -{ - static const char * StaticAlgorithmName() {return "Sosemanuk";} -}; - -//! _ -class SosemanukPolicy : public AdditiveCipherConcretePolicy, public SosemanukInfo -{ -protected: - void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length); - void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount); - void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length); - bool CipherIsRandomAccess() const {return false;} -#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64 - unsigned int GetAlignment() const; - unsigned int GetOptimalBlockSize() const; -#endif - - FixedSizeSecBlock m_key; - FixedSizeAlignedSecBlock m_state; -}; - -//! Sosemanuk -struct Sosemanuk : public SosemanukInfo, public SymmetricCipherDocumentation -{ - typedef SymmetricCipherFinal >, SosemanukInfo> Encryption; - typedef Encryption Decryption; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/stdcpp.h b/embeddedcryptopp/stdcpp.h deleted file mode 100644 index 9a468ab..0000000 --- a/embeddedcryptopp/stdcpp.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef CRYPTOPP_STDCPP_H -#define CRYPTOPP_STDCPP_H - -#include -#include -#include -#include -#include -#include -#include - - -#ifdef _MSC_VER -#include // CodeWarrior doesn't have memory.h -#include -#include -#include - -// re-disable this -#pragma warning(disable: 4231) -#endif - -#if defined(_MSC_VER) && defined(_CRTAPI1) -#define CRYPTOPP_MSVCRT6 -#endif - -#endif diff --git a/embeddedcryptopp/strciphr.cpp b/embeddedcryptopp/strciphr.cpp deleted file mode 100644 index 53e0073..0000000 --- a/embeddedcryptopp/strciphr.cpp +++ /dev/null @@ -1,252 +0,0 @@ -// strciphr.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" - -#ifndef CRYPTOPP_IMPORTS - -#include "strciphr.h" - -NAMESPACE_BEGIN(CryptoPP) - -template -void AdditiveCipherTemplate::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) -{ - PolicyInterface &policy = this->AccessPolicy(); - policy.CipherSetKey(params, key, length); - m_leftOver = 0; - unsigned int bufferByteSize = policy.CanOperateKeystream() ? GetBufferByteSize(policy) : RoundUpToMultipleOf(1024U, GetBufferByteSize(policy)); - m_buffer.New(bufferByteSize); - - if (this->IsResynchronizable()) - { - size_t ivLength; - const byte *iv = this->GetIVAndThrowIfInvalid(params, ivLength); - policy.CipherResynchronize(m_buffer, iv, ivLength); - } -} - -template -void AdditiveCipherTemplate::GenerateBlock(byte *outString, size_t length) -{ - if (m_leftOver > 0) - { - size_t len = STDMIN(m_leftOver, length); - memcpy(outString, KeystreamBufferEnd()-m_leftOver, len); - length -= len; - m_leftOver -= len; - outString += len; - - if (!length) - return; - } - assert(m_leftOver == 0); - - PolicyInterface &policy = this->AccessPolicy(); - unsigned int bytesPerIteration = policy.GetBytesPerIteration(); - - if (length >= bytesPerIteration) - { - size_t iterations = length / bytesPerIteration; - policy.WriteKeystream(outString, iterations); - outString += iterations * bytesPerIteration; - length -= iterations * bytesPerIteration; - } - - if (length > 0) - { - size_t bufferByteSize = RoundUpToMultipleOf(length, bytesPerIteration); - size_t bufferIterations = bufferByteSize / bytesPerIteration; - - policy.WriteKeystream(KeystreamBufferEnd()-bufferByteSize, bufferIterations); - memcpy(outString, KeystreamBufferEnd()-bufferByteSize, length); - m_leftOver = bufferByteSize - length; - } -} - -template -void AdditiveCipherTemplate::ProcessData(byte *outString, const byte *inString, size_t length) -{ - if (m_leftOver > 0) - { - size_t len = STDMIN(m_leftOver, length); - xorbuf(outString, inString, KeystreamBufferEnd()-m_leftOver, len); - length -= len; - m_leftOver -= len; - inString += len; - outString += len; - - if (!length) - return; - } - assert(m_leftOver == 0); - - PolicyInterface &policy = this->AccessPolicy(); - unsigned int bytesPerIteration = policy.GetBytesPerIteration(); - - if (policy.CanOperateKeystream() && length >= bytesPerIteration) - { - size_t iterations = length / bytesPerIteration; - unsigned int alignment = policy.GetAlignment(); - KeystreamOperation operation = KeystreamOperation((IsAlignedOn(inString, alignment) * 2) | (int)IsAlignedOn(outString, alignment)); - - policy.OperateKeystream(operation, outString, inString, iterations); - - inString += iterations * bytesPerIteration; - outString += iterations * bytesPerIteration; - length -= iterations * bytesPerIteration; - - if (!length) - return; - } - - size_t bufferByteSize = m_buffer.size(); - size_t bufferIterations = bufferByteSize / bytesPerIteration; - - while (length >= bufferByteSize) - { - policy.WriteKeystream(m_buffer, bufferIterations); - xorbuf(outString, inString, KeystreamBufferBegin(), bufferByteSize); - length -= bufferByteSize; - inString += bufferByteSize; - outString += bufferByteSize; - } - - if (length > 0) - { - bufferByteSize = RoundUpToMultipleOf(length, bytesPerIteration); - bufferIterations = bufferByteSize / bytesPerIteration; - - policy.WriteKeystream(KeystreamBufferEnd()-bufferByteSize, bufferIterations); - xorbuf(outString, inString, KeystreamBufferEnd()-bufferByteSize, length); - m_leftOver = bufferByteSize - length; - } -} - -template -void AdditiveCipherTemplate::Resynchronize(const byte *iv, int length) -{ - PolicyInterface &policy = this->AccessPolicy(); - m_leftOver = 0; - m_buffer.New(GetBufferByteSize(policy)); - policy.CipherResynchronize(m_buffer, iv, this->ThrowIfInvalidIVLength(length)); -} - -template -void AdditiveCipherTemplate::Seek(lword position) -{ - PolicyInterface &policy = this->AccessPolicy(); - unsigned int bytesPerIteration = policy.GetBytesPerIteration(); - - policy.SeekToIteration(position / bytesPerIteration); - position %= bytesPerIteration; - - if (position > 0) - { - policy.WriteKeystream(KeystreamBufferEnd()-bytesPerIteration, 1); - m_leftOver = bytesPerIteration - (unsigned int)position; - } - else - m_leftOver = 0; -} - -template -void CFB_CipherTemplate::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) -{ - PolicyInterface &policy = this->AccessPolicy(); - policy.CipherSetKey(params, key, length); - - if (this->IsResynchronizable()) - { - size_t ivLength; - const byte *iv = this->GetIVAndThrowIfInvalid(params, ivLength); - policy.CipherResynchronize(iv, ivLength); - } - - m_leftOver = policy.GetBytesPerIteration(); -} - -template -void CFB_CipherTemplate::Resynchronize(const byte *iv, int length) -{ - PolicyInterface &policy = this->AccessPolicy(); - policy.CipherResynchronize(iv, this->ThrowIfInvalidIVLength(length)); - m_leftOver = policy.GetBytesPerIteration(); -} - -template -void CFB_CipherTemplate::ProcessData(byte *outString, const byte *inString, size_t length) -{ - assert(length % this->MandatoryBlockSize() == 0); - - PolicyInterface &policy = this->AccessPolicy(); - unsigned int bytesPerIteration = policy.GetBytesPerIteration(); - unsigned int alignment = policy.GetAlignment(); - byte *reg = policy.GetRegisterBegin(); - - if (m_leftOver) - { - size_t len = STDMIN(m_leftOver, length); - CombineMessageAndShiftRegister(outString, reg + bytesPerIteration - m_leftOver, inString, len); - m_leftOver -= len; - length -= len; - inString += len; - outString += len; - } - - if (!length) - return; - - assert(m_leftOver == 0); - - if (policy.CanIterate() && length >= bytesPerIteration && IsAlignedOn(outString, alignment)) - { - if (IsAlignedOn(inString, alignment)) - policy.Iterate(outString, inString, GetCipherDir(*this), length / bytesPerIteration); - else - { - memcpy(outString, inString, length); - policy.Iterate(outString, outString, GetCipherDir(*this), length / bytesPerIteration); - } - inString += length - length % bytesPerIteration; - outString += length - length % bytesPerIteration; - length %= bytesPerIteration; - } - - while (length >= bytesPerIteration) - { - policy.TransformRegister(); - CombineMessageAndShiftRegister(outString, reg, inString, bytesPerIteration); - length -= bytesPerIteration; - inString += bytesPerIteration; - outString += bytesPerIteration; - } - - if (length > 0) - { - policy.TransformRegister(); - CombineMessageAndShiftRegister(outString, reg, inString, length); - m_leftOver = bytesPerIteration - length; - } -} - -template -void CFB_EncryptionTemplate::CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) -{ - xorbuf(reg, message, length); - memcpy(output, reg, length); -} - -template -void CFB_DecryptionTemplate::CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) -{ - for (unsigned int i=0; i, AdditiveCipherTemplate\<\> \> \> Encryption; - - AdditiveCipherTemplate and CFB_CipherTemplate are designed so that they don't need - to take a policy class as a template parameter (although this is allowed), so that - their code is not duplicated for each new cipher. Instead they each - get a reference to an abstract policy interface by calling AccessPolicy() on itself, so - AccessPolicy() must be overriden to return the actual policy reference. This is done - by the ConceretePolicyHolder class. Finally, SymmetricCipherFinal implements the constructors and - other functions that must be implemented by the most derived class. -*/ - -#ifndef CRYPTOPP_STRCIPHR_H -#define CRYPTOPP_STRCIPHR_H - -#include "seckey.h" -#include "secblock.h" -#include "argnames.h" - -NAMESPACE_BEGIN(CryptoPP) - -template -class CRYPTOPP_NO_VTABLE AbstractPolicyHolder : public BASE -{ -public: - typedef POLICY_INTERFACE PolicyInterface; - virtual ~AbstractPolicyHolder() {} - -protected: - virtual const POLICY_INTERFACE & GetPolicy() const =0; - virtual POLICY_INTERFACE & AccessPolicy() =0; -}; - -template -class ConcretePolicyHolder : public BASE, protected POLICY -{ -protected: - const POLICY_INTERFACE & GetPolicy() const {return *this;} - POLICY_INTERFACE & AccessPolicy() {return *this;} -}; - -enum KeystreamOperationFlags {OUTPUT_ALIGNED=1, INPUT_ALIGNED=2, INPUT_NULL = 4}; -enum KeystreamOperation { - WRITE_KEYSTREAM = INPUT_NULL, - WRITE_KEYSTREAM_ALIGNED = INPUT_NULL | OUTPUT_ALIGNED, - XOR_KEYSTREAM = 0, - XOR_KEYSTREAM_INPUT_ALIGNED = INPUT_ALIGNED, - XOR_KEYSTREAM_OUTPUT_ALIGNED= OUTPUT_ALIGNED, - XOR_KEYSTREAM_BOTH_ALIGNED = OUTPUT_ALIGNED | INPUT_ALIGNED}; - -struct CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AdditiveCipherAbstractPolicy -{ - virtual ~AdditiveCipherAbstractPolicy() {} - virtual unsigned int GetAlignment() const {return 1;} - virtual unsigned int GetBytesPerIteration() const =0; - virtual unsigned int GetOptimalBlockSize() const {return GetBytesPerIteration();} - virtual unsigned int GetIterationsToBuffer() const =0; - virtual void WriteKeystream(byte *keystream, size_t iterationCount) - {OperateKeystream(KeystreamOperation(INPUT_NULL | (KeystreamOperationFlags)IsAlignedOn(keystream, GetAlignment())), keystream, NULL, iterationCount);} - virtual bool CanOperateKeystream() const {return false;} - virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) {assert(false);} - virtual void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) =0; - virtual void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");} - virtual bool CipherIsRandomAccess() const =0; - virtual void SeekToIteration(lword iterationCount) {assert(!CipherIsRandomAccess()); throw NotImplemented("StreamTransformation: this object doesn't support random access");} -}; - -template -struct CRYPTOPP_NO_VTABLE AdditiveCipherConcretePolicy : public BASE -{ - typedef WT WordType; - CRYPTOPP_CONSTANT(BYTES_PER_ITERATION = sizeof(WordType) * W) - -#if !(CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64) - unsigned int GetAlignment() const {return GetAlignmentOf();} -#endif - unsigned int GetBytesPerIteration() const {return BYTES_PER_ITERATION;} - unsigned int GetIterationsToBuffer() const {return X;} - bool CanOperateKeystream() const {return true;} - virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) =0; -}; - -// use these to implement OperateKeystream -#define CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, b, i, a) \ - PutWord(bool(x & OUTPUT_ALIGNED), b, output+i*sizeof(WordType), (x & INPUT_NULL) ? a : a ^ GetWord(bool(x & INPUT_ALIGNED), b, input+i*sizeof(WordType))); -#define CRYPTOPP_KEYSTREAM_OUTPUT_XMM(x, i, a) {\ - __m128i t = (x & INPUT_NULL) ? a : _mm_xor_si128(a, (x & INPUT_ALIGNED) ? _mm_load_si128((__m128i *)input+i) : _mm_loadu_si128((__m128i *)input+i));\ - if (x & OUTPUT_ALIGNED) _mm_store_si128((__m128i *)output+i, t);\ - else _mm_storeu_si128((__m128i *)output+i, t);} -#define CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(x, y) \ - switch (operation) \ - { \ - case WRITE_KEYSTREAM: \ - x(WRITE_KEYSTREAM) \ - break; \ - case XOR_KEYSTREAM: \ - x(XOR_KEYSTREAM) \ - input += y; \ - break; \ - case XOR_KEYSTREAM_INPUT_ALIGNED: \ - x(XOR_KEYSTREAM_INPUT_ALIGNED) \ - input += y; \ - break; \ - case XOR_KEYSTREAM_OUTPUT_ALIGNED: \ - x(XOR_KEYSTREAM_OUTPUT_ALIGNED) \ - input += y; \ - break; \ - case WRITE_KEYSTREAM_ALIGNED: \ - x(WRITE_KEYSTREAM_ALIGNED) \ - break; \ - case XOR_KEYSTREAM_BOTH_ALIGNED: \ - x(XOR_KEYSTREAM_BOTH_ALIGNED) \ - input += y; \ - break; \ - } \ - output += y; - -template > -class CRYPTOPP_NO_VTABLE AdditiveCipherTemplate : public BASE, public RandomNumberGenerator -{ -public: - void GenerateBlock(byte *output, size_t size); - void ProcessData(byte *outString, const byte *inString, size_t length); - void Resynchronize(const byte *iv, int length=-1); - unsigned int OptimalBlockSize() const {return this->GetPolicy().GetOptimalBlockSize();} - unsigned int GetOptimalNextBlockSize() const {return (unsigned int)this->m_leftOver;} - unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();} - bool IsSelfInverting() const {return true;} - bool IsForwardTransformation() const {return true;} - bool IsRandomAccess() const {return this->GetPolicy().CipherIsRandomAccess();} - void Seek(lword position); - - typedef typename BASE::PolicyInterface PolicyInterface; - -protected: - void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); - - unsigned int GetBufferByteSize(const PolicyInterface &policy) const {return policy.GetBytesPerIteration() * policy.GetIterationsToBuffer();} - - inline byte * KeystreamBufferBegin() {return this->m_buffer.data();} - inline byte * KeystreamBufferEnd() {return (this->m_buffer.data() + this->m_buffer.size());} - - SecByteBlock m_buffer; - size_t m_leftOver; -}; - -class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_CipherAbstractPolicy -{ -public: - virtual ~CFB_CipherAbstractPolicy() {} - virtual unsigned int GetAlignment() const =0; - virtual unsigned int GetBytesPerIteration() const =0; - virtual byte * GetRegisterBegin() =0; - virtual void TransformRegister() =0; - virtual bool CanIterate() const {return false;} - virtual void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount) {assert(false); throw 0;} - virtual void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) =0; - virtual void CipherResynchronize(const byte *iv, size_t length) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");} -}; - -template -struct CRYPTOPP_NO_VTABLE CFB_CipherConcretePolicy : public BASE -{ - typedef WT WordType; - - unsigned int GetAlignment() const {return sizeof(WordType);} - unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;} - bool CanIterate() const {return true;} - void TransformRegister() {this->Iterate(NULL, NULL, ENCRYPTION, 1);} - - template - struct RegisterOutput - { - RegisterOutput(byte *output, const byte *input, CipherDir dir) - : m_output(output), m_input(input), m_dir(dir) {} - - inline RegisterOutput& operator()(WordType ®isterWord) - { - assert(IsAligned(m_output)); - assert(IsAligned(m_input)); - - if (!NativeByteOrderIs(B::ToEnum())) - registerWord = ByteReverse(registerWord); - - if (m_dir == ENCRYPTION) - { - if (m_input == NULL) - assert(m_output == NULL); - else - { - WordType ct = *(const WordType *)m_input ^ registerWord; - registerWord = ct; - *(WordType*)m_output = ct; - m_input += sizeof(WordType); - m_output += sizeof(WordType); - } - } - else - { - WordType ct = *(const WordType *)m_input; - *(WordType*)m_output = registerWord ^ ct; - registerWord = ct; - m_input += sizeof(WordType); - m_output += sizeof(WordType); - } - - // registerWord is left unreversed so it can be xor-ed with further input - - return *this; - } - - byte *m_output; - const byte *m_input; - CipherDir m_dir; - }; -}; - -template -class CRYPTOPP_NO_VTABLE CFB_CipherTemplate : public BASE -{ -public: - void ProcessData(byte *outString, const byte *inString, size_t length); - void Resynchronize(const byte *iv, int length=-1); - unsigned int OptimalBlockSize() const {return this->GetPolicy().GetBytesPerIteration();} - unsigned int GetOptimalNextBlockSize() const {return (unsigned int)m_leftOver;} - unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();} - bool IsRandomAccess() const {return false;} - bool IsSelfInverting() const {return false;} - - typedef typename BASE::PolicyInterface PolicyInterface; - -protected: - virtual void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) =0; - - void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); - - size_t m_leftOver; -}; - -template > -class CRYPTOPP_NO_VTABLE CFB_EncryptionTemplate : public CFB_CipherTemplate -{ - bool IsForwardTransformation() const {return true;} - void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length); -}; - -template > -class CRYPTOPP_NO_VTABLE CFB_DecryptionTemplate : public CFB_CipherTemplate -{ - bool IsForwardTransformation() const {return false;} - void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length); -}; - -template -class CFB_RequireFullDataBlocks : public BASE -{ -public: - unsigned int MandatoryBlockSize() const {return this->OptimalBlockSize();} -}; - -//! _ -template -class SymmetricCipherFinal : public AlgorithmImpl, INFO> -{ -public: - SymmetricCipherFinal() {} - SymmetricCipherFinal(const byte *key) - {this->SetKey(key, this->DEFAULT_KEYLENGTH);} - SymmetricCipherFinal(const byte *key, size_t length) - {this->SetKey(key, length);} - SymmetricCipherFinal(const byte *key, size_t length, const byte *iv) - {this->SetKeyWithIV(key, length, iv);} - - Clonable * Clone() const {return static_cast(new SymmetricCipherFinal(*this));} -}; - -NAMESPACE_END - -#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES -#include "strciphr.cpp" -#endif - -NAMESPACE_BEGIN(CryptoPP) -CRYPTOPP_DLL_TEMPLATE_CLASS AbstractPolicyHolder; -CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate >; -CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate >; -CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate >; -CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate >; -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/tiger.cpp b/embeddedcryptopp/tiger.cpp deleted file mode 100644 index c6c05ca..0000000 --- a/embeddedcryptopp/tiger.cpp +++ /dev/null @@ -1,265 +0,0 @@ -// tiger.cpp - written and placed in the public domain by Wei Dai - -#include "pch.h" -#include "tiger.h" -#include "misc.h" -#include "cpu.h" - -NAMESPACE_BEGIN(CryptoPP) - -void Tiger::InitState(HashWordType *state) -{ - state[0] = W64LIT(0x0123456789ABCDEF); - state[1] = W64LIT(0xFEDCBA9876543210); - state[2] = W64LIT(0xF096A5B4C3B2E187); -} - -void Tiger::TruncatedFinal(byte *hash, size_t size) -{ - ThrowIfInvalidTruncatedSize(size); - - PadLastBlock(56, 0x01); - CorrectEndianess(m_data, m_data, 56); - - m_data[7] = GetBitCountLo(); - - Transform(m_state, m_data); - CorrectEndianess(m_state, m_state, DigestSize()); - memcpy(hash, m_state, size); - - Restart(); // reinit for next use -} - -void Tiger::Transform (word64 *digest, const word64 *X) -{ -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86 - if (HasSSE2()) - { -#ifdef __GNUC__ - __asm__ __volatile__ - ( - ".intel_syntax noprefix;" - AS1( push ebx) -#else - #if _MSC_VER < 1300 - const word64 *t = table; - AS2( mov edx, t) - #else - AS2( lea edx, [table]) - #endif - AS2( mov eax, digest) - AS2( mov esi, X) -#endif - AS2( movq mm0, [eax]) - AS2( movq mm1, [eax+1*8]) - AS2( movq mm5, mm1) - AS2( movq mm2, [eax+2*8]) - AS2( movq mm7, [edx+4*2048+0*8]) - AS2( movq mm6, [edx+4*2048+1*8]) - AS2( mov ecx, esp) - AS2( and esp, 0xfffffff0) - AS2( sub esp, 8*8) - AS1( push ecx) - -#define SSE2_round(a,b,c,x,mul) \ - AS2( pxor c, [x])\ - AS2( movd ecx, c)\ - AS2( movzx edi, cl)\ - AS2( movq mm3, [edx+0*2048+edi*8])\ - AS2( movzx edi, ch)\ - AS2( movq mm4, [edx+3*2048+edi*8])\ - AS2( shr ecx, 16)\ - AS2( movzx edi, cl)\ - AS2( pxor mm3, [edx+1*2048+edi*8])\ - AS2( movzx edi, ch)\ - AS2( pxor mm4, [edx+2*2048+edi*8])\ - AS3( pextrw ecx, c, 2)\ - AS2( movzx edi, cl)\ - AS2( pxor mm3, [edx+2*2048+edi*8])\ - AS2( movzx edi, ch)\ - AS2( pxor mm4, [edx+1*2048+edi*8])\ - AS3( pextrw ecx, c, 3)\ - AS2( movzx edi, cl)\ - AS2( pxor mm3, [edx+3*2048+edi*8])\ - AS2( psubq a, mm3)\ - AS2( movzx edi, ch)\ - AS2( pxor mm4, [edx+0*2048+edi*8])\ - AS2( paddq b, mm4)\ - SSE2_mul_##mul(b) - -#define SSE2_mul_5(b) \ - AS2( movq mm3, b)\ - AS2( psllq b, 2)\ - AS2( paddq b, mm3) - -#define SSE2_mul_7(b) \ - AS2( movq mm3, b)\ - AS2( psllq b, 3)\ - AS2( psubq b, mm3) - -#define SSE2_mul_9(b) \ - AS2( movq mm3, b)\ - AS2( psllq b, 3)\ - AS2( paddq b, mm3) - -#define label2_5 1 -#define label2_7 2 -#define label2_9 3 - -#define SSE2_pass(A,B,C,mul,X) \ - AS2( xor ebx, ebx)\ - ASL(mul)\ - SSE2_round(A,B,C,X+0*8+ebx,mul)\ - SSE2_round(B,C,A,X+1*8+ebx,mul)\ - AS2( cmp ebx, 6*8)\ - ASJ( je, label2_##mul, f)\ - SSE2_round(C,A,B,X+2*8+ebx,mul)\ - AS2( add ebx, 3*8)\ - ASJ( jmp, mul, b)\ - ASL(label2_##mul) - -#define SSE2_key_schedule(Y,X) \ - AS2( movq mm3, [X+7*8])\ - AS2( pxor mm3, mm6)\ - AS2( movq mm4, [X+0*8])\ - AS2( psubq mm4, mm3)\ - AS2( movq [Y+0*8], mm4)\ - AS2( pxor mm4, [X+1*8])\ - AS2( movq mm3, mm4)\ - AS2( movq [Y+1*8], mm4)\ - AS2( paddq mm4, [X+2*8])\ - AS2( pxor mm3, mm7)\ - AS2( psllq mm3, 19)\ - AS2( movq [Y+2*8], mm4)\ - AS2( pxor mm3, mm4)\ - AS2( movq mm4, [X+3*8])\ - AS2( psubq mm4, mm3)\ - AS2( movq [Y+3*8], mm4)\ - AS2( pxor mm4, [X+4*8])\ - AS2( movq mm3, mm4)\ - AS2( movq [Y+4*8], mm4)\ - AS2( paddq mm4, [X+5*8])\ - AS2( pxor mm3, mm7)\ - AS2( psrlq mm3, 23)\ - AS2( movq [Y+5*8], mm4)\ - AS2( pxor mm3, mm4)\ - AS2( movq mm4, [X+6*8])\ - AS2( psubq mm4, mm3)\ - AS2( movq [Y+6*8], mm4)\ - AS2( pxor mm4, [X+7*8])\ - AS2( movq mm3, mm4)\ - AS2( movq [Y+7*8], mm4)\ - AS2( paddq mm4, [Y+0*8])\ - AS2( pxor mm3, mm7)\ - AS2( psllq mm3, 19)\ - AS2( movq [Y+0*8], mm4)\ - AS2( pxor mm3, mm4)\ - AS2( movq mm4, [Y+1*8])\ - AS2( psubq mm4, mm3)\ - AS2( movq [Y+1*8], mm4)\ - AS2( pxor mm4, [Y+2*8])\ - AS2( movq mm3, mm4)\ - AS2( movq [Y+2*8], mm4)\ - AS2( paddq mm4, [Y+3*8])\ - AS2( pxor mm3, mm7)\ - AS2( psrlq mm3, 23)\ - AS2( movq [Y+3*8], mm4)\ - AS2( pxor mm3, mm4)\ - AS2( movq mm4, [Y+4*8])\ - AS2( psubq mm4, mm3)\ - AS2( movq [Y+4*8], mm4)\ - AS2( pxor mm4, [Y+5*8])\ - AS2( movq [Y+5*8], mm4)\ - AS2( paddq mm4, [Y+6*8])\ - AS2( movq [Y+6*8], mm4)\ - AS2( pxor mm4, [edx+4*2048+2*8])\ - AS2( movq mm3, [Y+7*8])\ - AS2( psubq mm3, mm4)\ - AS2( movq [Y+7*8], mm3) - - SSE2_pass(mm0, mm1, mm2, 5, esi) - SSE2_key_schedule(esp+4, esi) - SSE2_pass(mm2, mm0, mm1, 7, esp+4) - SSE2_key_schedule(esp+4, esp+4) - SSE2_pass(mm1, mm2, mm0, 9, esp+4) - - AS2( pxor mm0, [eax+0*8]) - AS2( movq [eax+0*8], mm0) - AS2( psubq mm1, mm5) - AS2( movq [eax+1*8], mm1) - AS2( paddq mm2, [eax+2*8]) - AS2( movq [eax+2*8], mm2) - - AS1( pop esp) - AS1( emms) -#ifdef __GNUC__ - AS1( pop ebx) - ".att_syntax prefix;" - : - : "a" (digest), "S" (X), "d" (table) - : "%ecx", "%edi", "memory", "cc" - ); -#endif - } - else -#endif - { - word64 a = digest[0]; - word64 b = digest[1]; - word64 c = digest[2]; - word64 Y[8]; - -#define t1 (table) -#define t2 (table+256) -#define t3 (table+256*2) -#define t4 (table+256*3) - -#define round(a,b,c,x,mul) \ - c ^= x; \ - a -= t1[GETBYTE(c,0)] ^ t2[GETBYTE(c,2)] ^ t3[GETBYTE(c,4)] ^ t4[GETBYTE(c,6)]; \ - b += t4[GETBYTE(c,1)] ^ t3[GETBYTE(c,3)] ^ t2[GETBYTE(c,5)] ^ t1[GETBYTE(c,7)]; \ - b *= mul - -#define pass(a,b,c,mul,X) {\ - int i=0;\ - while (true)\ - {\ - round(a,b,c,X[i+0],mul); \ - round(b,c,a,X[i+1],mul); \ - if (i==6)\ - break;\ - round(c,a,b,X[i+2],mul); \ - i+=3;\ - }} - -#define key_schedule(Y,X) \ - Y[0] = X[0] - (X[7]^W64LIT(0xA5A5A5A5A5A5A5A5)); \ - Y[1] = X[1] ^ Y[0]; \ - Y[2] = X[2] + Y[1]; \ - Y[3] = X[3] - (Y[2] ^ ((~Y[1])<<19)); \ - Y[4] = X[4] ^ Y[3]; \ - Y[5] = X[5] + Y[4]; \ - Y[6] = X[6] - (Y[5] ^ ((~Y[4])>>23)); \ - Y[7] = X[7] ^ Y[6]; \ - Y[0] += Y[7]; \ - Y[1] -= Y[0] ^ ((~Y[7])<<19); \ - Y[2] ^= Y[1]; \ - Y[3] += Y[2]; \ - Y[4] -= Y[3] ^ ((~Y[2])>>23); \ - Y[5] ^= Y[4]; \ - Y[6] += Y[5]; \ - Y[7] -= Y[6] ^ W64LIT(0x0123456789ABCDEF) - - pass(a,b,c,5,X); - key_schedule(Y,X); - pass(c,a,b,7,Y); - key_schedule(Y,Y); - pass(b,c,a,9,Y); - - digest[0] = a ^ digest[0]; - digest[1] = b - digest[1]; - digest[2] = c + digest[2]; - } -} - -NAMESPACE_END diff --git a/embeddedcryptopp/tiger.h b/embeddedcryptopp/tiger.h deleted file mode 100644 index 5f6e941..0000000 --- a/embeddedcryptopp/tiger.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef CRYPTOPP_TIGER_H -#define CRYPTOPP_TIGER_H - -#include "config.h" -#include "iterhash.h" - -NAMESPACE_BEGIN(CryptoPP) - -/// Tiger -class Tiger : public IteratedHashWithStaticTransform -{ -public: - static void InitState(HashWordType *state); - static void Transform(word64 *digest, const word64 *data); - void TruncatedFinal(byte *hash, size_t size); - static const char * StaticAlgorithmName() {return "Tiger";} - -protected: - static const word64 table[4*256+3]; -}; - -NAMESPACE_END - -#endif diff --git a/embeddedcryptopp/tigertab.cpp b/embeddedcryptopp/tigertab.cpp deleted file mode 100644 index 5c1595b..0000000 --- a/embeddedcryptopp/tigertab.cpp +++ /dev/null @@ -1,525 +0,0 @@ -#include "pch.h" -#include "tiger.h" - -NAMESPACE_BEGIN(CryptoPP) - -const word64 Tiger::table[4*256+3] = -{ - W64LIT(0x02AAB17CF7E90C5E) /* 0 */, W64LIT(0xAC424B03E243A8EC) /* 1 */, - W64LIT(0x72CD5BE30DD5FCD3) /* 2 */, W64LIT(0x6D019B93F6F97F3A) /* 3 */, - W64LIT(0xCD9978FFD21F9193) /* 4 */, W64LIT(0x7573A1C9708029E2) /* 5 */, - W64LIT(0xB164326B922A83C3) /* 6 */, W64LIT(0x46883EEE04915870) /* 7 */, - W64LIT(0xEAACE3057103ECE6) /* 8 */, W64LIT(0xC54169B808A3535C) /* 9 */, - W64LIT(0x4CE754918DDEC47C) /* 10 */, W64LIT(0x0AA2F4DFDC0DF40C) /* 11 */, - W64LIT(0x10B76F18A74DBEFA) /* 12 */, W64LIT(0xC6CCB6235AD1AB6A) /* 13 */, - W64LIT(0x13726121572FE2FF) /* 14 */, W64LIT(0x1A488C6F199D921E) /* 15 */, - W64LIT(0x4BC9F9F4DA0007CA) /* 16 */, W64LIT(0x26F5E6F6E85241C7) /* 17 */, - W64LIT(0x859079DBEA5947B6) /* 18 */, W64LIT(0x4F1885C5C99E8C92) /* 19 */, - W64LIT(0xD78E761EA96F864B) /* 20 */, W64LIT(0x8E36428C52B5C17D) /* 21 */, - W64LIT(0x69CF6827373063C1) /* 22 */, W64LIT(0xB607C93D9BB4C56E) /* 23 */, - W64LIT(0x7D820E760E76B5EA) /* 24 */, W64LIT(0x645C9CC6F07FDC42) /* 25 */, - W64LIT(0xBF38A078243342E0) /* 26 */, W64LIT(0x5F6B343C9D2E7D04) /* 27 */, - W64LIT(0xF2C28AEB600B0EC6) /* 28 */, W64LIT(0x6C0ED85F7254BCAC) /* 29 */, - W64LIT(0x71592281A4DB4FE5) /* 30 */, W64LIT(0x1967FA69CE0FED9F) /* 31 */, - W64LIT(0xFD5293F8B96545DB) /* 32 */, W64LIT(0xC879E9D7F2A7600B) /* 33 */, - W64LIT(0x860248920193194E) /* 34 */, W64LIT(0xA4F9533B2D9CC0B3) /* 35 */, - W64LIT(0x9053836C15957613) /* 36 */, W64LIT(0xDB6DCF8AFC357BF1) /* 37 */, - W64LIT(0x18BEEA7A7A370F57) /* 38 */, W64LIT(0x037117CA50B99066) /* 39 */, - W64LIT(0x6AB30A9774424A35) /* 40 */, W64LIT(0xF4E92F02E325249B) /* 41 */, - W64LIT(0x7739DB07061CCAE1) /* 42 */, W64LIT(0xD8F3B49CECA42A05) /* 43 */, - W64LIT(0xBD56BE3F51382F73) /* 44 */, W64LIT(0x45FAED5843B0BB28) /* 45 */, - W64LIT(0x1C813D5C11BF1F83) /* 46 */, W64LIT(0x8AF0E4B6D75FA169) /* 47 */, - W64LIT(0x33EE18A487AD9999) /* 48 */, W64LIT(0x3C26E8EAB1C94410) /* 49 */, - W64LIT(0xB510102BC0A822F9) /* 50 */, W64LIT(0x141EEF310CE6123B) /* 51 */, - W64LIT(0xFC65B90059DDB154) /* 52 */, W64LIT(0xE0158640C5E0E607) /* 53 */, - W64LIT(0x884E079826C3A3CF) /* 54 */, W64LIT(0x930D0D9523C535FD) /* 55 */, - W64LIT(0x35638D754E9A2B00) /* 56 */, W64LIT(0x4085FCCF40469DD5) /* 57 */, - W64LIT(0xC4B17AD28BE23A4C) /* 58 */, W64LIT(0xCAB2F0FC6A3E6A2E) /* 59 */, - W64LIT(0x2860971A6B943FCD) /* 60 */, W64LIT(0x3DDE6EE212E30446) /* 61 */, - W64LIT(0x6222F32AE01765AE) /* 62 */, W64LIT(0x5D550BB5478308FE) /* 63 */, - W64LIT(0xA9EFA98DA0EDA22A) /* 64 */, W64LIT(0xC351A71686C40DA7) /* 65 */, - W64LIT(0x1105586D9C867C84) /* 66 */, W64LIT(0xDCFFEE85FDA22853) /* 67 */, - W64LIT(0xCCFBD0262C5EEF76) /* 68 */, W64LIT(0xBAF294CB8990D201) /* 69 */, - W64LIT(0xE69464F52AFAD975) /* 70 */, W64LIT(0x94B013AFDF133E14) /* 71 */, - W64LIT(0x06A7D1A32823C958) /* 72 */, W64LIT(0x6F95FE5130F61119) /* 73 */, - W64LIT(0xD92AB34E462C06C0) /* 74 */, W64LIT(0xED7BDE33887C71D2) /* 75 */, - W64LIT(0x79746D6E6518393E) /* 76 */, W64LIT(0x5BA419385D713329) /* 77 */, - W64LIT(0x7C1BA6B948A97564) /* 78 */, W64LIT(0x31987C197BFDAC67) /* 79 */, - W64LIT(0xDE6C23C44B053D02) /* 80 */, W64LIT(0x581C49FED002D64D) /* 81 */, - W64LIT(0xDD474D6338261571) /* 82 */, W64LIT(0xAA4546C3E473D062) /* 83 */, - W64LIT(0x928FCE349455F860) /* 84 */, W64LIT(0x48161BBACAAB94D9) /* 85 */, - W64LIT(0x63912430770E6F68) /* 86 */, W64LIT(0x6EC8A5E602C6641C) /* 87 */, - W64LIT(0x87282515337DDD2B) /* 88 */, W64LIT(0x2CDA6B42034B701B) /* 89 */, - W64LIT(0xB03D37C181CB096D) /* 90 */, W64LIT(0xE108438266C71C6F) /* 91 */, - W64LIT(0x2B3180C7EB51B255) /* 92 */, W64LIT(0xDF92B82F96C08BBC) /* 93 */, - W64LIT(0x5C68C8C0A632F3BA) /* 94 */, W64LIT(0x5504CC861C3D0556) /* 95 */, - W64LIT(0xABBFA4E55FB26B8F) /* 96 */, W64LIT(0x41848B0AB3BACEB4) /* 97 */, - W64LIT(0xB334A273AA445D32) /* 98 */, W64LIT(0xBCA696F0A85AD881) /* 99 */, - W64LIT(0x24F6EC65B528D56C) /* 100 */, W64LIT(0x0CE1512E90F4524A) /* 101 */, - W64LIT(0x4E9DD79D5506D35A) /* 102 */, W64LIT(0x258905FAC6CE9779) /* 103 */, - W64LIT(0x2019295B3E109B33) /* 104 */, W64LIT(0xF8A9478B73A054CC) /* 105 */, - W64LIT(0x2924F2F934417EB0) /* 106 */, W64LIT(0x3993357D536D1BC4) /* 107 */, - W64LIT(0x38A81AC21DB6FF8B) /* 108 */, W64LIT(0x47C4FBF17D6016BF) /* 109 */, - W64LIT(0x1E0FAADD7667E3F5) /* 110 */, W64LIT(0x7ABCFF62938BEB96) /* 111 */, - W64LIT(0xA78DAD948FC179C9) /* 112 */, W64LIT(0x8F1F98B72911E50D) /* 113 */, - W64LIT(0x61E48EAE27121A91) /* 114 */, W64LIT(0x4D62F7AD31859808) /* 115 */, - W64LIT(0xECEBA345EF5CEAEB) /* 116 */, W64LIT(0xF5CEB25EBC9684CE) /* 117 */, - W64LIT(0xF633E20CB7F76221) /* 118 */, W64LIT(0xA32CDF06AB8293E4) /* 119 */, - W64LIT(0x985A202CA5EE2CA4) /* 120 */, W64LIT(0xCF0B8447CC8A8FB1) /* 121 */, - W64LIT(0x9F765244979859A3) /* 122 */, W64LIT(0xA8D516B1A1240017) /* 123 */, - W64LIT(0x0BD7BA3EBB5DC726) /* 124 */, W64LIT(0xE54BCA55B86ADB39) /* 125 */, - W64LIT(0x1D7A3AFD6C478063) /* 126 */, W64LIT(0x519EC608E7669EDD) /* 127 */, - W64LIT(0x0E5715A2D149AA23) /* 128 */, W64LIT(0x177D4571848FF194) /* 129 */, - W64LIT(0xEEB55F3241014C22) /* 130 */, W64LIT(0x0F5E5CA13A6E2EC2) /* 131 */, - W64LIT(0x8029927B75F5C361) /* 132 */, W64LIT(0xAD139FABC3D6E436) /* 133 */, - W64LIT(0x0D5DF1A94CCF402F) /* 134 */, W64LIT(0x3E8BD948BEA5DFC8) /* 135 */, - W64LIT(0xA5A0D357BD3FF77E) /* 136 */, W64LIT(0xA2D12E251F74F645) /* 137 */, - W64LIT(0x66FD9E525E81A082) /* 138 */, W64LIT(0x2E0C90CE7F687A49) /* 139 */, - W64LIT(0xC2E8BCBEBA973BC5) /* 140 */, W64LIT(0x000001BCE509745F) /* 141 */, - W64LIT(0x423777BBE6DAB3D6) /* 142 */, W64LIT(0xD1661C7EAEF06EB5) /* 143 */, - W64LIT(0xA1781F354DAACFD8) /* 144 */, W64LIT(0x2D11284A2B16AFFC) /* 145 */, - W64LIT(0xF1FC4F67FA891D1F) /* 146 */, W64LIT(0x73ECC25DCB920ADA) /* 147 */, - W64LIT(0xAE610C22C2A12651) /* 148 */, W64LIT(0x96E0A810D356B78A) /* 149 */, - W64LIT(0x5A9A381F2FE7870F) /* 150 */, W64LIT(0xD5AD62EDE94E5530) /* 151 */, - W64LIT(0xD225E5E8368D1427) /* 152 */, W64LIT(0x65977B70C7AF4631) /* 153 */, - W64LIT(0x99F889B2DE39D74F) /* 154 */, W64LIT(0x233F30BF54E1D143) /* 155 */, - W64LIT(0x9A9675D3D9A63C97) /* 156 */, W64LIT(0x5470554FF334F9A8) /* 157 */, - W64LIT(0x166ACB744A4F5688) /* 158 */, W64LIT(0x70C74CAAB2E4AEAD) /* 159 */, - W64LIT(0xF0D091646F294D12) /* 160 */, W64LIT(0x57B82A89684031D1) /* 161 */, - W64LIT(0xEFD95A5A61BE0B6B) /* 162 */, W64LIT(0x2FBD12E969F2F29A) /* 163 */, - W64LIT(0x9BD37013FEFF9FE8) /* 164 */, W64LIT(0x3F9B0404D6085A06) /* 165 */, - W64LIT(0x4940C1F3166CFE15) /* 166 */, W64LIT(0x09542C4DCDF3DEFB) /* 167 */, - W64LIT(0xB4C5218385CD5CE3) /* 168 */, W64LIT(0xC935B7DC4462A641) /* 169 */, - W64LIT(0x3417F8A68ED3B63F) /* 170 */, W64LIT(0xB80959295B215B40) /* 171 */, - W64LIT(0xF99CDAEF3B8C8572) /* 172 */, W64LIT(0x018C0614F8FCB95D) /* 173 */, - W64LIT(0x1B14ACCD1A3ACDF3) /* 174 */, W64LIT(0x84D471F200BB732D) /* 175 */, - W64LIT(0xC1A3110E95E8DA16) /* 176 */, W64LIT(0x430A7220BF1A82B8) /* 177 */, - W64LIT(0xB77E090D39DF210E) /* 178 */, W64LIT(0x5EF4BD9F3CD05E9D) /* 179 */, - W64LIT(0x9D4FF6DA7E57A444) /* 180 */, W64LIT(0xDA1D60E183D4A5F8) /* 181 */, - W64LIT(0xB287C38417998E47) /* 182 */, W64LIT(0xFE3EDC121BB31886) /* 183 */, - W64LIT(0xC7FE3CCC980CCBEF) /* 184 */, W64LIT(0xE46FB590189BFD03) /* 185 */, - W64LIT(0x3732FD469A4C57DC) /* 186 */, W64LIT(0x7EF700A07CF1AD65) /* 187 */, - W64LIT(0x59C64468A31D8859) /* 188 */, W64LIT(0x762FB0B4D45B61F6) /* 189 */, - W64LIT(0x155BAED099047718) /* 190 */, W64LIT(0x68755E4C3D50BAA6) /* 191 */, - W64LIT(0xE9214E7F22D8B4DF) /* 192 */, W64LIT(0x2ADDBF532EAC95F4) /* 193 */, - W64LIT(0x32AE3909B4BD0109) /* 194 */, W64LIT(0x834DF537B08E3450) /* 195 */, - W64LIT(0xFA209DA84220728D) /* 196 */, W64LIT(0x9E691D9B9EFE23F7) /* 197 */, - W64LIT(0x0446D288C4AE8D7F) /* 198 */, W64LIT(0x7B4CC524E169785B) /* 199 */, - W64LIT(0x21D87F0135CA1385) /* 200 */, W64LIT(0xCEBB400F137B8AA5) /* 201 */, - W64LIT(0x272E2B66580796BE) /* 202 */, W64LIT(0x3612264125C2B0DE) /* 203 */, - W64LIT(0x057702BDAD1EFBB2) /* 204 */, W64LIT(0xD4BABB8EACF84BE9) /* 205 */, - W64LIT(0x91583139641BC67B) /* 206 */, W64LIT(0x8BDC2DE08036E024) /* 207 */, - W64LIT(0x603C8156F49F68ED) /* 208 */, W64LIT(0xF7D236F7DBEF5111) /* 209 */, - W64LIT(0x9727C4598AD21E80) /* 210 */, W64LIT(0xA08A0896670A5FD7) /* 211 */, - W64LIT(0xCB4A8F4309EBA9CB) /* 212 */, W64LIT(0x81AF564B0F7036A1) /* 213 */, - W64LIT(0xC0B99AA778199ABD) /* 214 */, W64LIT(0x959F1EC83FC8E952) /* 215 */, - W64LIT(0x8C505077794A81B9) /* 216 */, W64LIT(0x3ACAAF8F056338F0) /* 217 */, - W64LIT(0x07B43F50627A6778) /* 218 */, W64LIT(0x4A44AB49F5ECCC77) /* 219 */, - W64LIT(0x3BC3D6E4B679EE98) /* 220 */, W64LIT(0x9CC0D4D1CF14108C) /* 221 */, - W64LIT(0x4406C00B206BC8A0) /* 222 */, W64LIT(0x82A18854C8D72D89) /* 223 */, - W64LIT(0x67E366B35C3C432C) /* 224 */, W64LIT(0xB923DD61102B37F2) /* 225 */, - W64LIT(0x56AB2779D884271D) /* 226 */, W64LIT(0xBE83E1B0FF1525AF) /* 227 */, - W64LIT(0xFB7C65D4217E49A9) /* 228 */, W64LIT(0x6BDBE0E76D48E7D4) /* 229 */, - W64LIT(0x08DF828745D9179E) /* 230 */, W64LIT(0x22EA6A9ADD53BD34) /* 231 */, - W64LIT(0xE36E141C5622200A) /* 232 */, W64LIT(0x7F805D1B8CB750EE) /* 233 */, - W64LIT(0xAFE5C7A59F58E837) /* 234 */, W64LIT(0xE27F996A4FB1C23C) /* 235 */, - W64LIT(0xD3867DFB0775F0D0) /* 236 */, W64LIT(0xD0E673DE6E88891A) /* 237 */, - W64LIT(0x123AEB9EAFB86C25) /* 238 */, W64LIT(0x30F1D5D5C145B895) /* 239 */, - W64LIT(0xBB434A2DEE7269E7) /* 240 */, W64LIT(0x78CB67ECF931FA38) /* 241 */, - W64LIT(0xF33B0372323BBF9C) /* 242 */, W64LIT(0x52D66336FB279C74) /* 243 */, - W64LIT(0x505F33AC0AFB4EAA) /* 244 */, W64LIT(0xE8A5CD99A2CCE187) /* 245 */, - W64LIT(0x534974801E2D30BB) /* 246 */, W64LIT(0x8D2D5711D5876D90) /* 247 */, - W64LIT(0x1F1A412891BC038E) /* 248 */, W64LIT(0xD6E2E71D82E56648) /* 249 */, - W64LIT(0x74036C3A497732B7) /* 250 */, W64LIT(0x89B67ED96361F5AB) /* 251 */, - W64LIT(0xFFED95D8F1EA02A2) /* 252 */, W64LIT(0xE72B3BD61464D43D) /* 253 */, - W64LIT(0xA6300F170BDC4820) /* 254 */, W64LIT(0xEBC18760ED78A77A) /* 255 */, - W64LIT(0xE6A6BE5A05A12138) /* 256 */, W64LIT(0xB5A122A5B4F87C98) /* 257 */, - W64LIT(0x563C6089140B6990) /* 258 */, W64LIT(0x4C46CB2E391F5DD5) /* 259 */, - W64LIT(0xD932ADDBC9B79434) /* 260 */, W64LIT(0x08EA70E42015AFF5) /* 261 */, - W64LIT(0xD765A6673E478CF1) /* 262 */, W64LIT(0xC4FB757EAB278D99) /* 263 */, - W64LIT(0xDF11C6862D6E0692) /* 264 */, W64LIT(0xDDEB84F10D7F3B16) /* 265 */, - W64LIT(0x6F2EF604A665EA04) /* 266 */, W64LIT(0x4A8E0F0FF0E0DFB3) /* 267 */, - W64LIT(0xA5EDEEF83DBCBA51) /* 268 */, W64LIT(0xFC4F0A2A0EA4371E) /* 269 */, - W64LIT(0xE83E1DA85CB38429) /* 270 */, W64LIT(0xDC8FF882BA1B1CE2) /* 271 */, - W64LIT(0xCD45505E8353E80D) /* 272 */, W64LIT(0x18D19A00D4DB0717) /* 273 */, - W64LIT(0x34A0CFEDA5F38101) /* 274 */, W64LIT(0x0BE77E518887CAF2) /* 275 */, - W64LIT(0x1E341438B3C45136) /* 276 */, W64LIT(0xE05797F49089CCF9) /* 277 */, - W64LIT(0xFFD23F9DF2591D14) /* 278 */, W64LIT(0x543DDA228595C5CD) /* 279 */, - W64LIT(0x661F81FD99052A33) /* 280 */, W64LIT(0x8736E641DB0F7B76) /* 281 */, - W64LIT(0x15227725418E5307) /* 282 */, W64LIT(0xE25F7F46162EB2FA) /* 283 */, - W64LIT(0x48A8B2126C13D9FE) /* 284 */, W64LIT(0xAFDC541792E76EEA) /* 285 */, - W64LIT(0x03D912BFC6D1898F) /* 286 */, W64LIT(0x31B1AAFA1B83F51B) /* 287 */, - W64LIT(0xF1AC2796E42AB7D9) /* 288 */, W64LIT(0x40A3A7D7FCD2EBAC) /* 289 */, - W64LIT(0x1056136D0AFBBCC5) /* 290 */, W64LIT(0x7889E1DD9A6D0C85) /* 291 */, - W64LIT(0xD33525782A7974AA) /* 292 */, W64LIT(0xA7E25D09078AC09B) /* 293 */, - W64LIT(0xBD4138B3EAC6EDD0) /* 294 */, W64LIT(0x920ABFBE71EB9E70) /* 295 */, - W64LIT(0xA2A5D0F54FC2625C) /* 296 */, W64LIT(0xC054E36B0B1290A3) /* 297 */, - W64LIT(0xF6DD59FF62FE932B) /* 298 */, W64LIT(0x3537354511A8AC7D) /* 299 */, - W64LIT(0xCA845E9172FADCD4) /* 300 */, W64LIT(0x84F82B60329D20DC) /* 301 */, - W64LIT(0x79C62CE1CD672F18) /* 302 */, W64LIT(0x8B09A2ADD124642C) /* 303 */, - W64LIT(0xD0C1E96A19D9E726) /* 304 */, W64LIT(0x5A786A9B4BA9500C) /* 305 */, - W64LIT(0x0E020336634C43F3) /* 306 */, W64LIT(0xC17B474AEB66D822) /* 307 */, - W64LIT(0x6A731AE3EC9BAAC2) /* 308 */, W64LIT(0x8226667AE0840258) /* 309 */, - W64LIT(0x67D4567691CAECA5) /* 310 */, W64LIT(0x1D94155C4875ADB5) /* 311 */, - W64LIT(0x6D00FD985B813FDF) /* 312 */, W64LIT(0x51286EFCB774CD06) /* 313 */, - W64LIT(0x5E8834471FA744AF) /* 314 */, W64LIT(0xF72CA0AEE761AE2E) /* 315 */, - W64LIT(0xBE40E4CDAEE8E09A) /* 316 */, W64LIT(0xE9970BBB5118F665) /* 317 */, - W64LIT(0x726E4BEB33DF1964) /* 318 */, W64LIT(0x703B000729199762) /* 319 */, - W64LIT(0x4631D816F5EF30A7) /* 320 */, W64LIT(0xB880B5B51504A6BE) /* 321 */, - W64LIT(0x641793C37ED84B6C) /* 322 */, W64LIT(0x7B21ED77F6E97D96) /* 323 */, - W64LIT(0x776306312EF96B73) /* 324 */, W64LIT(0xAE528948E86FF3F4) /* 325 */, - W64LIT(0x53DBD7F286A3F8F8) /* 326 */, W64LIT(0x16CADCE74CFC1063) /* 327 */, - W64LIT(0x005C19BDFA52C6DD) /* 328 */, W64LIT(0x68868F5D64D46AD3) /* 329 */, - W64LIT(0x3A9D512CCF1E186A) /* 330 */, W64LIT(0x367E62C2385660AE) /* 331 */, - W64LIT(0xE359E7EA77DCB1D7) /* 332 */, W64LIT(0x526C0773749ABE6E) /* 333 */, - W64LIT(0x735AE5F9D09F734B) /* 334 */, W64LIT(0x493FC7CC8A558BA8) /* 335 */, - W64LIT(0xB0B9C1533041AB45) /* 336 */, W64LIT(0x321958BA470A59BD) /* 337 */, - W64LIT(0x852DB00B5F46C393) /* 338 */, W64LIT(0x91209B2BD336B0E5) /* 339 */, - W64LIT(0x6E604F7D659EF19F) /* 340 */, W64LIT(0xB99A8AE2782CCB24) /* 341 */, - W64LIT(0xCCF52AB6C814C4C7) /* 342 */, W64LIT(0x4727D9AFBE11727B) /* 343 */, - W64LIT(0x7E950D0C0121B34D) /* 344 */, W64LIT(0x756F435670AD471F) /* 345 */, - W64LIT(0xF5ADD442615A6849) /* 346 */, W64LIT(0x4E87E09980B9957A) /* 347 */, - W64LIT(0x2ACFA1DF50AEE355) /* 348 */, W64LIT(0xD898263AFD2FD556) /* 349 */, - W64LIT(0xC8F4924DD80C8FD6) /* 350 */, W64LIT(0xCF99CA3D754A173A) /* 351 */, - W64LIT(0xFE477BACAF91BF3C) /* 352 */, W64LIT(0xED5371F6D690C12D) /* 353 */, - W64LIT(0x831A5C285E687094) /* 354 */, W64LIT(0xC5D3C90A3708A0A4) /* 355 */, - W64LIT(0x0F7F903717D06580) /* 356 */, W64LIT(0x19F9BB13B8FDF27F) /* 357 */, - W64LIT(0xB1BD6F1B4D502843) /* 358 */, W64LIT(0x1C761BA38FFF4012) /* 359 */, - W64LIT(0x0D1530C4E2E21F3B) /* 360 */, W64LIT(0x8943CE69A7372C8A) /* 361 */, - W64LIT(0xE5184E11FEB5CE66) /* 362 */, W64LIT(0x618BDB80BD736621) /* 363 */, - W64LIT(0x7D29BAD68B574D0B) /* 364 */, W64LIT(0x81BB613E25E6FE5B) /* 365 */, - W64LIT(0x071C9C10BC07913F) /* 366 */, W64LIT(0xC7BEEB7909AC2D97) /* 367 */, - W64LIT(0xC3E58D353BC5D757) /* 368 */, W64LIT(0xEB017892F38F61E8) /* 369 */, - W64LIT(0xD4EFFB9C9B1CC21A) /* 370 */, W64LIT(0x99727D26F494F7AB) /* 371 */, - W64LIT(0xA3E063A2956B3E03) /* 372 */, W64LIT(0x9D4A8B9A4AA09C30) /* 373 */, - W64LIT(0x3F6AB7D500090FB4) /* 374 */, W64LIT(0x9CC0F2A057268AC0) /* 375 */, - W64LIT(0x3DEE9D2DEDBF42D1) /* 376 */, W64LIT(0x330F49C87960A972) /* 377 */, - W64LIT(0xC6B2720287421B41) /* 378 */, W64LIT(0x0AC59EC07C00369C) /* 379 */, - W64LIT(0xEF4EAC49CB353425) /* 380 */, W64LIT(0xF450244EEF0129D8) /* 381 */, - W64LIT(0x8ACC46E5CAF4DEB6) /* 382 */, W64LIT(0x2FFEAB63989263F7) /* 383 */, - W64LIT(0x8F7CB9FE5D7A4578) /* 384 */, W64LIT(0x5BD8F7644E634635) /* 385 */, - W64LIT(0x427A7315BF2DC900) /* 386 */, W64LIT(0x17D0C4AA2125261C) /* 387 */, - W64LIT(0x3992486C93518E50) /* 388 */, W64LIT(0xB4CBFEE0A2D7D4C3) /* 389 */, - W64LIT(0x7C75D6202C5DDD8D) /* 390 */, W64LIT(0xDBC295D8E35B6C61) /* 391 */, - W64LIT(0x60B369D302032B19) /* 392 */, W64LIT(0xCE42685FDCE44132) /* 393 */, - W64LIT(0x06F3DDB9DDF65610) /* 394 */, W64LIT(0x8EA4D21DB5E148F0) /* 395 */, - W64LIT(0x20B0FCE62FCD496F) /* 396 */, W64LIT(0x2C1B912358B0EE31) /* 397 */, - W64LIT(0xB28317B818F5A308) /* 398 */, W64LIT(0xA89C1E189CA6D2CF) /* 399 */, - W64LIT(0x0C6B18576AAADBC8) /* 400 */, W64LIT(0xB65DEAA91299FAE3) /* 401 */, - W64LIT(0xFB2B794B7F1027E7) /* 402 */, W64LIT(0x04E4317F443B5BEB) /* 403 */, - W64LIT(0x4B852D325939D0A6) /* 404 */, W64LIT(0xD5AE6BEEFB207FFC) /* 405 */, - W64LIT(0x309682B281C7D374) /* 406 */, W64LIT(0xBAE309A194C3B475) /* 407 */, - W64LIT(0x8CC3F97B13B49F05) /* 408 */, W64LIT(0x98A9422FF8293967) /* 409 */, - W64LIT(0x244B16B01076FF7C) /* 410 */, W64LIT(0xF8BF571C663D67EE) /* 411 */, - W64LIT(0x1F0D6758EEE30DA1) /* 412 */, W64LIT(0xC9B611D97ADEB9B7) /* 413 */, - W64LIT(0xB7AFD5887B6C57A2) /* 414 */, W64LIT(0x6290AE846B984FE1) /* 415 */, - W64LIT(0x94DF4CDEACC1A5FD) /* 416 */, W64LIT(0x058A5BD1C5483AFF) /* 417 */, - W64LIT(0x63166CC142BA3C37) /* 418 */, W64LIT(0x8DB8526EB2F76F40) /* 419 */, - W64LIT(0xE10880036F0D6D4E) /* 420 */, W64LIT(0x9E0523C9971D311D) /* 421 */, - W64LIT(0x45EC2824CC7CD691) /* 422 */, W64LIT(0x575B8359E62382C9) /* 423 */, - W64LIT(0xFA9E400DC4889995) /* 424 */, W64LIT(0xD1823ECB45721568) /* 425 */, - W64LIT(0xDAFD983B8206082F) /* 426 */, W64LIT(0xAA7D29082386A8CB) /* 427 */, - W64LIT(0x269FCD4403B87588) /* 428 */, W64LIT(0x1B91F5F728BDD1E0) /* 429 */, - W64LIT(0xE4669F39040201F6) /* 430 */, W64LIT(0x7A1D7C218CF04ADE) /* 431 */, - W64LIT(0x65623C29D79CE5CE) /* 432 */, W64LIT(0x2368449096C00BB1) /* 433 */, - W64LIT(0xAB9BF1879DA503BA) /* 434 */, W64LIT(0xBC23ECB1A458058E) /* 435 */, - W64LIT(0x9A58DF01BB401ECC) /* 436 */, W64LIT(0xA070E868A85F143D) /* 437 */, - W64LIT(0x4FF188307DF2239E) /* 438 */, W64LIT(0x14D565B41A641183) /* 439 */, - W64LIT(0xEE13337452701602) /* 440 */, W64LIT(0x950E3DCF3F285E09) /* 441 */, - W64LIT(0x59930254B9C80953) /* 442 */, W64LIT(0x3BF299408930DA6D) /* 443 */, - W64LIT(0xA955943F53691387) /* 444 */, W64LIT(0xA15EDECAA9CB8784) /* 445 */, - W64LIT(0x29142127352BE9A0) /* 446 */, W64LIT(0x76F0371FFF4E7AFB) /* 447 */, - W64LIT(0x0239F450274F2228) /* 448 */, W64LIT(0xBB073AF01D5E868B) /* 449 */, - W64LIT(0xBFC80571C10E96C1) /* 450 */, W64LIT(0xD267088568222E23) /* 451 */, - W64LIT(0x9671A3D48E80B5B0) /* 452 */, W64LIT(0x55B5D38AE193BB81) /* 453 */, - W64LIT(0x693AE2D0A18B04B8) /* 454 */, W64LIT(0x5C48B4ECADD5335F) /* 455 */, - W64LIT(0xFD743B194916A1CA) /* 456 */, W64LIT(0x2577018134BE98C4) /* 457 */, - W64LIT(0xE77987E83C54A4AD) /* 458 */, W64LIT(0x28E11014DA33E1B9) /* 459 */, - W64LIT(0x270CC59E226AA213) /* 460 */, W64LIT(0x71495F756D1A5F60) /* 461 */, - W64LIT(0x9BE853FB60AFEF77) /* 462 */, W64LIT(0xADC786A7F7443DBF) /* 463 */, - W64LIT(0x0904456173B29A82) /* 464 */, W64LIT(0x58BC7A66C232BD5E) /* 465 */, - W64LIT(0xF306558C673AC8B2) /* 466 */, W64LIT(0x41F639C6B6C9772A) /* 467 */, - W64LIT(0x216DEFE99FDA35DA) /* 468 */, W64LIT(0x11640CC71C7BE615) /* 469 */, - W64LIT(0x93C43694565C5527) /* 470 */, W64LIT(0xEA038E6246777839) /* 471 */, - W64LIT(0xF9ABF3CE5A3E2469) /* 472 */, W64LIT(0x741E768D0FD312D2) /* 473 */, - W64LIT(0x0144B883CED652C6) /* 474 */, W64LIT(0xC20B5A5BA33F8552) /* 475 */, - W64LIT(0x1AE69633C3435A9D) /* 476 */, W64LIT(0x97A28CA4088CFDEC) /* 477 */, - W64LIT(0x8824A43C1E96F420) /* 478 */, W64LIT(0x37612FA66EEEA746) /* 479 */, - W64LIT(0x6B4CB165F9CF0E5A) /* 480 */, W64LIT(0x43AA1C06A0ABFB4A) /* 481 */, - W64LIT(0x7F4DC26FF162796B) /* 482 */, W64LIT(0x6CBACC8E54ED9B0F) /* 483 */, - W64LIT(0xA6B7FFEFD2BB253E) /* 484 */, W64LIT(0x2E25BC95B0A29D4F) /* 485 */, - W64LIT(0x86D6A58BDEF1388C) /* 486 */, W64LIT(0xDED74AC576B6F054) /* 487 */, - W64LIT(0x8030BDBC2B45805D) /* 488 */, W64LIT(0x3C81AF70E94D9289) /* 489 */, - W64LIT(0x3EFF6DDA9E3100DB) /* 490 */, W64LIT(0xB38DC39FDFCC8847) /* 491 */, - W64LIT(0x123885528D17B87E) /* 492 */, W64LIT(0xF2DA0ED240B1B642) /* 493 */, - W64LIT(0x44CEFADCD54BF9A9) /* 494 */, W64LIT(0x1312200E433C7EE6) /* 495 */, - W64LIT(0x9FFCC84F3A78C748) /* 496 */, W64LIT(0xF0CD1F72248576BB) /* 497 */, - W64LIT(0xEC6974053638CFE4) /* 498 */, W64LIT(0x2BA7B67C0CEC4E4C) /* 499 */, - W64LIT(0xAC2F4DF3E5CE32ED) /* 500 */, W64LIT(0xCB33D14326EA4C11) /* 501 */, - W64LIT(0xA4E9044CC77E58BC) /* 502 */, W64LIT(0x5F513293D934FCEF) /* 503 */, - W64LIT(0x5DC9645506E55444) /* 504 */, W64LIT(0x50DE418F317DE40A) /* 505 */, - W64LIT(0x388CB31A69DDE259) /* 506 */, W64LIT(0x2DB4A83455820A86) /* 507 */, - W64LIT(0x9010A91E84711AE9) /* 508 */, W64LIT(0x4DF7F0B7B1498371) /* 509 */, - W64LIT(0xD62A2EABC0977179) /* 510 */, W64LIT(0x22FAC097AA8D5C0E) /* 511 */, - W64LIT(0xF49FCC2FF1DAF39B) /* 512 */, W64LIT(0x487FD5C66FF29281) /* 513 */, - W64LIT(0xE8A30667FCDCA83F) /* 514 */, W64LIT(0x2C9B4BE3D2FCCE63) /* 515 */, - W64LIT(0xDA3FF74B93FBBBC2) /* 516 */, W64LIT(0x2FA165D2FE70BA66) /* 517 */, - W64LIT(0xA103E279970E93D4) /* 518 */, W64LIT(0xBECDEC77B0E45E71) /* 519 */, - W64LIT(0xCFB41E723985E497) /* 520 */, W64LIT(0xB70AAA025EF75017) /* 521 */, - W64LIT(0xD42309F03840B8E0) /* 522 */, W64LIT(0x8EFC1AD035898579) /* 523 */, - W64LIT(0x96C6920BE2B2ABC5) /* 524 */, W64LIT(0x66AF4163375A9172) /* 525 */, - W64LIT(0x2174ABDCCA7127FB) /* 526 */, W64LIT(0xB33CCEA64A72FF41) /* 527 */, - W64LIT(0xF04A4933083066A5) /* 528 */, W64LIT(0x8D970ACDD7289AF5) /* 529 */, - W64LIT(0x8F96E8E031C8C25E) /* 530 */, W64LIT(0xF3FEC02276875D47) /* 531 */, - W64LIT(0xEC7BF310056190DD) /* 532 */, W64LIT(0xF5ADB0AEBB0F1491) /* 533 */, - W64LIT(0x9B50F8850FD58892) /* 534 */, W64LIT(0x4975488358B74DE8) /* 535 */, - W64LIT(0xA3354FF691531C61) /* 536 */, W64LIT(0x0702BBE481D2C6EE) /* 537 */, - W64LIT(0x89FB24057DEDED98) /* 538 */, W64LIT(0xAC3075138596E902) /* 539 */, - W64LIT(0x1D2D3580172772ED) /* 540 */, W64LIT(0xEB738FC28E6BC30D) /* 541 */, - W64LIT(0x5854EF8F63044326) /* 542 */, W64LIT(0x9E5C52325ADD3BBE) /* 543 */, - W64LIT(0x90AA53CF325C4623) /* 544 */, W64LIT(0xC1D24D51349DD067) /* 545 */, - W64LIT(0x2051CFEEA69EA624) /* 546 */, W64LIT(0x13220F0A862E7E4F) /* 547 */, - W64LIT(0xCE39399404E04864) /* 548 */, W64LIT(0xD9C42CA47086FCB7) /* 549 */, - W64LIT(0x685AD2238A03E7CC) /* 550 */, W64LIT(0x066484B2AB2FF1DB) /* 551 */, - W64LIT(0xFE9D5D70EFBF79EC) /* 552 */, W64LIT(0x5B13B9DD9C481854) /* 553 */, - W64LIT(0x15F0D475ED1509AD) /* 554 */, W64LIT(0x0BEBCD060EC79851) /* 555 */, - W64LIT(0xD58C6791183AB7F8) /* 556 */, W64LIT(0xD1187C5052F3EEE4) /* 557 */, - W64LIT(0xC95D1192E54E82FF) /* 558 */, W64LIT(0x86EEA14CB9AC6CA2) /* 559 */, - W64LIT(0x3485BEB153677D5D) /* 560 */, W64LIT(0xDD191D781F8C492A) /* 561 */, - W64LIT(0xF60866BAA784EBF9) /* 562 */, W64LIT(0x518F643BA2D08C74) /* 563 */, - W64LIT(0x8852E956E1087C22) /* 564 */, W64LIT(0xA768CB8DC410AE8D) /* 565 */, - W64LIT(0x38047726BFEC8E1A) /* 566 */, W64LIT(0xA67738B4CD3B45AA) /* 567 */, - W64LIT(0xAD16691CEC0DDE19) /* 568 */, W64LIT(0xC6D4319380462E07) /* 569 */, - W64LIT(0xC5A5876D0BA61938) /* 570 */, W64LIT(0x16B9FA1FA58FD840) /* 571 */, - W64LIT(0x188AB1173CA74F18) /* 572 */, W64LIT(0xABDA2F98C99C021F) /* 573 */, - W64LIT(0x3E0580AB134AE816) /* 574 */, W64LIT(0x5F3B05B773645ABB) /* 575 */, - W64LIT(0x2501A2BE5575F2F6) /* 576 */, W64LIT(0x1B2F74004E7E8BA9) /* 577 */, - W64LIT(0x1CD7580371E8D953) /* 578 */, W64LIT(0x7F6ED89562764E30) /* 579 */, - W64LIT(0xB15926FF596F003D) /* 580 */, W64LIT(0x9F65293DA8C5D6B9) /* 581 */, - W64LIT(0x6ECEF04DD690F84C) /* 582 */, W64LIT(0x4782275FFF33AF88) /* 583 */, - W64LIT(0xE41433083F820801) /* 584 */, W64LIT(0xFD0DFE409A1AF9B5) /* 585 */, - W64LIT(0x4325A3342CDB396B) /* 586 */, W64LIT(0x8AE77E62B301B252) /* 587 */, - W64LIT(0xC36F9E9F6655615A) /* 588 */, W64LIT(0x85455A2D92D32C09) /* 589 */, - W64LIT(0xF2C7DEA949477485) /* 590 */, W64LIT(0x63CFB4C133A39EBA) /* 591 */, - W64LIT(0x83B040CC6EBC5462) /* 592 */, W64LIT(0x3B9454C8FDB326B0) /* 593 */, - W64LIT(0x56F56A9E87FFD78C) /* 594 */, W64LIT(0x2DC2940D99F42BC6) /* 595 */, - W64LIT(0x98F7DF096B096E2D) /* 596 */, W64LIT(0x19A6E01E3AD852BF) /* 597 */, - W64LIT(0x42A99CCBDBD4B40B) /* 598 */, W64LIT(0xA59998AF45E9C559) /* 599 */, - W64LIT(0x366295E807D93186) /* 600 */, W64LIT(0x6B48181BFAA1F773) /* 601 */, - W64LIT(0x1FEC57E2157A0A1D) /* 602 */, W64LIT(0x4667446AF6201AD5) /* 603 */, - W64LIT(0xE615EBCACFB0F075) /* 604 */, W64LIT(0xB8F31F4F68290778) /* 605 */, - W64LIT(0x22713ED6CE22D11E) /* 606 */, W64LIT(0x3057C1A72EC3C93B) /* 607 */, - W64LIT(0xCB46ACC37C3F1F2F) /* 608 */, W64LIT(0xDBB893FD02AAF50E) /* 609 */, - W64LIT(0x331FD92E600B9FCF) /* 610 */, W64LIT(0xA498F96148EA3AD6) /* 611 */, - W64LIT(0xA8D8426E8B6A83EA) /* 612 */, W64LIT(0xA089B274B7735CDC) /* 613 */, - W64LIT(0x87F6B3731E524A11) /* 614 */, W64LIT(0x118808E5CBC96749) /* 615 */, - W64LIT(0x9906E4C7B19BD394) /* 616 */, W64LIT(0xAFED7F7E9B24A20C) /* 617 */, - W64LIT(0x6509EADEEB3644A7) /* 618 */, W64LIT(0x6C1EF1D3E8EF0EDE) /* 619 */, - W64LIT(0xB9C97D43E9798FB4) /* 620 */, W64LIT(0xA2F2D784740C28A3) /* 621 */, - W64LIT(0x7B8496476197566F) /* 622 */, W64LIT(0x7A5BE3E6B65F069D) /* 623 */, - W64LIT(0xF96330ED78BE6F10) /* 624 */, W64LIT(0xEEE60DE77A076A15) /* 625 */, - W64LIT(0x2B4BEE4AA08B9BD0) /* 626 */, W64LIT(0x6A56A63EC7B8894E) /* 627 */, - W64LIT(0x02121359BA34FEF4) /* 628 */, W64LIT(0x4CBF99F8283703FC) /* 629 */, - W64LIT(0x398071350CAF30C8) /* 630 */, W64LIT(0xD0A77A89F017687A) /* 631 */, - W64LIT(0xF1C1A9EB9E423569) /* 632 */, W64LIT(0x8C7976282DEE8199) /* 633 */, - W64LIT(0x5D1737A5DD1F7ABD) /* 634 */, W64LIT(0x4F53433C09A9FA80) /* 635 */, - W64LIT(0xFA8B0C53DF7CA1D9) /* 636 */, W64LIT(0x3FD9DCBC886CCB77) /* 637 */, - W64LIT(0xC040917CA91B4720) /* 638 */, W64LIT(0x7DD00142F9D1DCDF) /* 639 */, - W64LIT(0x8476FC1D4F387B58) /* 640 */, W64LIT(0x23F8E7C5F3316503) /* 641 */, - W64LIT(0x032A2244E7E37339) /* 642 */, W64LIT(0x5C87A5D750F5A74B) /* 643 */, - W64LIT(0x082B4CC43698992E) /* 644 */, W64LIT(0xDF917BECB858F63C) /* 645 */, - W64LIT(0x3270B8FC5BF86DDA) /* 646 */, W64LIT(0x10AE72BB29B5DD76) /* 647 */, - W64LIT(0x576AC94E7700362B) /* 648 */, W64LIT(0x1AD112DAC61EFB8F) /* 649 */, - W64LIT(0x691BC30EC5FAA427) /* 650 */, W64LIT(0xFF246311CC327143) /* 651 */, - W64LIT(0x3142368E30E53206) /* 652 */, W64LIT(0x71380E31E02CA396) /* 653 */, - W64LIT(0x958D5C960AAD76F1) /* 654 */, W64LIT(0xF8D6F430C16DA536) /* 655 */, - W64LIT(0xC8FFD13F1BE7E1D2) /* 656 */, W64LIT(0x7578AE66004DDBE1) /* 657 */, - W64LIT(0x05833F01067BE646) /* 658 */, W64LIT(0xBB34B5AD3BFE586D) /* 659 */, - W64LIT(0x095F34C9A12B97F0) /* 660 */, W64LIT(0x247AB64525D60CA8) /* 661 */, - W64LIT(0xDCDBC6F3017477D1) /* 662 */, W64LIT(0x4A2E14D4DECAD24D) /* 663 */, - W64LIT(0xBDB5E6D9BE0A1EEB) /* 664 */, W64LIT(0x2A7E70F7794301AB) /* 665 */, - W64LIT(0xDEF42D8A270540FD) /* 666 */, W64LIT(0x01078EC0A34C22C1) /* 667 */, - W64LIT(0xE5DE511AF4C16387) /* 668 */, W64LIT(0x7EBB3A52BD9A330A) /* 669 */, - W64LIT(0x77697857AA7D6435) /* 670 */, W64LIT(0x004E831603AE4C32) /* 671 */, - W64LIT(0xE7A21020AD78E312) /* 672 */, W64LIT(0x9D41A70C6AB420F2) /* 673 */, - W64LIT(0x28E06C18EA1141E6) /* 674 */, W64LIT(0xD2B28CBD984F6B28) /* 675 */, - W64LIT(0x26B75F6C446E9D83) /* 676 */, W64LIT(0xBA47568C4D418D7F) /* 677 */, - W64LIT(0xD80BADBFE6183D8E) /* 678 */, W64LIT(0x0E206D7F5F166044) /* 679 */, - W64LIT(0xE258A43911CBCA3E) /* 680 */, W64LIT(0x723A1746B21DC0BC) /* 681 */, - W64LIT(0xC7CAA854F5D7CDD3) /* 682 */, W64LIT(0x7CAC32883D261D9C) /* 683 */, - W64LIT(0x7690C26423BA942C) /* 684 */, W64LIT(0x17E55524478042B8) /* 685 */, - W64LIT(0xE0BE477656A2389F) /* 686 */, W64LIT(0x4D289B5E67AB2DA0) /* 687 */, - W64LIT(0x44862B9C8FBBFD31) /* 688 */, W64LIT(0xB47CC8049D141365) /* 689 */, - W64LIT(0x822C1B362B91C793) /* 690 */, W64LIT(0x4EB14655FB13DFD8) /* 691 */, - W64LIT(0x1ECBBA0714E2A97B) /* 692 */, W64LIT(0x6143459D5CDE5F14) /* 693 */, - W64LIT(0x53A8FBF1D5F0AC89) /* 694 */, W64LIT(0x97EA04D81C5E5B00) /* 695 */, - W64LIT(0x622181A8D4FDB3F3) /* 696 */, W64LIT(0xE9BCD341572A1208) /* 697 */, - W64LIT(0x1411258643CCE58A) /* 698 */, W64LIT(0x9144C5FEA4C6E0A4) /* 699 */, - W64LIT(0x0D33D06565CF620F) /* 700 */, W64LIT(0x54A48D489F219CA1) /* 701 */, - W64LIT(0xC43E5EAC6D63C821) /* 702 */, W64LIT(0xA9728B3A72770DAF) /* 703 */, - W64LIT(0xD7934E7B20DF87EF) /* 704 */, W64LIT(0xE35503B61A3E86E5) /* 705 */, - W64LIT(0xCAE321FBC819D504) /* 706 */, W64LIT(0x129A50B3AC60BFA6) /* 707 */, - W64LIT(0xCD5E68EA7E9FB6C3) /* 708 */, W64LIT(0xB01C90199483B1C7) /* 709 */, - W64LIT(0x3DE93CD5C295376C) /* 710 */, W64LIT(0xAED52EDF2AB9AD13) /* 711 */, - W64LIT(0x2E60F512C0A07884) /* 712 */, W64LIT(0xBC3D86A3E36210C9) /* 713 */, - W64LIT(0x35269D9B163951CE) /* 714 */, W64LIT(0x0C7D6E2AD0CDB5FA) /* 715 */, - W64LIT(0x59E86297D87F5733) /* 716 */, W64LIT(0x298EF221898DB0E7) /* 717 */, - W64LIT(0x55000029D1A5AA7E) /* 718 */, W64LIT(0x8BC08AE1B5061B45) /* 719 */, - W64LIT(0xC2C31C2B6C92703A) /* 720 */, W64LIT(0x94CC596BAF25EF42) /* 721 */, - W64LIT(0x0A1D73DB22540456) /* 722 */, W64LIT(0x04B6A0F9D9C4179A) /* 723 */, - W64LIT(0xEFFDAFA2AE3D3C60) /* 724 */, W64LIT(0xF7C8075BB49496C4) /* 725 */, - W64LIT(0x9CC5C7141D1CD4E3) /* 726 */, W64LIT(0x78BD1638218E5534) /* 727 */, - W64LIT(0xB2F11568F850246A) /* 728 */, W64LIT(0xEDFABCFA9502BC29) /* 729 */, - W64LIT(0x796CE5F2DA23051B) /* 730 */, W64LIT(0xAAE128B0DC93537C) /* 731 */, - W64LIT(0x3A493DA0EE4B29AE) /* 732 */, W64LIT(0xB5DF6B2C416895D7) /* 733 */, - W64LIT(0xFCABBD25122D7F37) /* 734 */, W64LIT(0x70810B58105DC4B1) /* 735 */, - W64LIT(0xE10FDD37F7882A90) /* 736 */, W64LIT(0x524DCAB5518A3F5C) /* 737 */, - W64LIT(0x3C9E85878451255B) /* 738 */, W64LIT(0x4029828119BD34E2) /* 739 */, - W64LIT(0x74A05B6F5D3CECCB) /* 740 */, W64LIT(0xB610021542E13ECA) /* 741 */, - W64LIT(0x0FF979D12F59E2AC) /* 742 */, W64LIT(0x6037DA27E4F9CC50) /* 743 */, - W64LIT(0x5E92975A0DF1847D) /* 744 */, W64LIT(0xD66DE190D3E623FE) /* 745 */, - W64LIT(0x5032D6B87B568048) /* 746 */, W64LIT(0x9A36B7CE8235216E) /* 747 */, - W64LIT(0x80272A7A24F64B4A) /* 748 */, W64LIT(0x93EFED8B8C6916F7) /* 749 */, - W64LIT(0x37DDBFF44CCE1555) /* 750 */, W64LIT(0x4B95DB5D4B99BD25) /* 751 */, - W64LIT(0x92D3FDA169812FC0) /* 752 */, W64LIT(0xFB1A4A9A90660BB6) /* 753 */, - W64LIT(0x730C196946A4B9B2) /* 754 */, W64LIT(0x81E289AA7F49DA68) /* 755 */, - W64LIT(0x64669A0F83B1A05F) /* 756 */, W64LIT(0x27B3FF7D9644F48B) /* 757 */, - W64LIT(0xCC6B615C8DB675B3) /* 758 */, W64LIT(0x674F20B9BCEBBE95) /* 759 */, - W64LIT(0x6F31238275655982) /* 760 */, W64LIT(0x5AE488713E45CF05) /* 761 */, - W64LIT(0xBF619F9954C21157) /* 762 */, W64LIT(0xEABAC46040A8EAE9) /* 763 */, - W64LIT(0x454C6FE9F2C0C1CD) /* 764 */, W64LIT(0x419CF6496412691C) /* 765 */, - W64LIT(0xD3DC3BEF265B0F70) /* 766 */, W64LIT(0x6D0E60F5C3578A9E) /* 767 */, - W64LIT(0x5B0E608526323C55) /* 768 */, W64LIT(0x1A46C1A9FA1B59F5) /* 769 */, - W64LIT(0xA9E245A17C4C8FFA) /* 770 */, W64LIT(0x65CA5159DB2955D7) /* 771 */, - W64LIT(0x05DB0A76CE35AFC2) /* 772 */, W64LIT(0x81EAC77EA9113D45) /* 773 */, - W64LIT(0x528EF88AB6AC0A0D) /* 774 */, W64LIT(0xA09EA253597BE3FF) /* 775 */, - W64LIT(0x430DDFB3AC48CD56) /* 776 */, W64LIT(0xC4B3A67AF45CE46F) /* 777 */, - W64LIT(0x4ECECFD8FBE2D05E) /* 778 */, W64LIT(0x3EF56F10B39935F0) /* 779 */, - W64LIT(0x0B22D6829CD619C6) /* 780 */, W64LIT(0x17FD460A74DF2069) /* 781 */, - W64LIT(0x6CF8CC8E8510ED40) /* 782 */, W64LIT(0xD6C824BF3A6ECAA7) /* 783 */, - W64LIT(0x61243D581A817049) /* 784 */, W64LIT(0x048BACB6BBC163A2) /* 785 */, - W64LIT(0xD9A38AC27D44CC32) /* 786 */, W64LIT(0x7FDDFF5BAAF410AB) /* 787 */, - W64LIT(0xAD6D495AA804824B) /* 788 */, W64LIT(0xE1A6A74F2D8C9F94) /* 789 */, - W64LIT(0xD4F7851235DEE8E3) /* 790 */, W64LIT(0xFD4B7F886540D893) /* 791 */, - W64LIT(0x247C20042AA4BFDA) /* 792 */, W64LIT(0x096EA1C517D1327C) /* 793 */, - W64LIT(0xD56966B4361A6685) /* 794 */, W64LIT(0x277DA5C31221057D) /* 795 */, - W64LIT(0x94D59893A43ACFF7) /* 796 */, W64LIT(0x64F0C51CCDC02281) /* 797 */, - W64LIT(0x3D33BCC4FF6189DB) /* 798 */, W64LIT(0xE005CB184CE66AF1) /* 799 */, - W64LIT(0xFF5CCD1D1DB99BEA) /* 800 */, W64LIT(0xB0B854A7FE42980F) /* 801 */, - W64LIT(0x7BD46A6A718D4B9F) /* 802 */, W64LIT(0xD10FA8CC22A5FD8C) /* 803 */, - W64LIT(0xD31484952BE4BD31) /* 804 */, W64LIT(0xC7FA975FCB243847) /* 805 */, - W64LIT(0x4886ED1E5846C407) /* 806 */, W64LIT(0x28CDDB791EB70B04) /* 807 */, - W64LIT(0xC2B00BE2F573417F) /* 808 */, W64LIT(0x5C9590452180F877) /* 809 */, - W64LIT(0x7A6BDDFFF370EB00) /* 810 */, W64LIT(0xCE509E38D6D9D6A4) /* 811 */, - W64LIT(0xEBEB0F00647FA702) /* 812 */, W64LIT(0x1DCC06CF76606F06) /* 813 */, - W64LIT(0xE4D9F28BA286FF0A) /* 814 */, W64LIT(0xD85A305DC918C262) /* 815 */, - W64LIT(0x475B1D8732225F54) /* 816 */, W64LIT(0x2D4FB51668CCB5FE) /* 817 */, - W64LIT(0xA679B9D9D72BBA20) /* 818 */, W64LIT(0x53841C0D912D43A5) /* 819 */, - W64LIT(0x3B7EAA48BF12A4E8) /* 820 */, W64LIT(0x781E0E47F22F1DDF) /* 821 */, - W64LIT(0xEFF20CE60AB50973) /* 822 */, W64LIT(0x20D261D19DFFB742) /* 823 */, - W64LIT(0x16A12B03062A2E39) /* 824 */, W64LIT(0x1960EB2239650495) /* 825 */, - W64LIT(0x251C16FED50EB8B8) /* 826 */, W64LIT(0x9AC0C330F826016E) /* 827 */, - W64LIT(0xED152665953E7671) /* 828 */, W64LIT(0x02D63194A6369570) /* 829 */, - W64LIT(0x5074F08394B1C987) /* 830 */, W64LIT(0x70BA598C90B25CE1) /* 831 */, - W64LIT(0x794A15810B9742F6) /* 832 */, W64LIT(0x0D5925E9FCAF8C6C) /* 833 */, - W64LIT(0x3067716CD868744E) /* 834 */, W64LIT(0x910AB077E8D7731B) /* 835 */, - W64LIT(0x6A61BBDB5AC42F61) /* 836 */, W64LIT(0x93513EFBF0851567) /* 837 */, - W64LIT(0xF494724B9E83E9D5) /* 838 */, W64LIT(0xE887E1985C09648D) /* 839 */, - W64LIT(0x34B1D3C675370CFD) /* 840 */, W64LIT(0xDC35E433BC0D255D) /* 841 */, - W64LIT(0xD0AAB84234131BE0) /* 842 */, W64LIT(0x08042A50B48B7EAF) /* 843 */, - W64LIT(0x9997C4EE44A3AB35) /* 844 */, W64LIT(0x829A7B49201799D0) /* 845 */, - W64LIT(0x263B8307B7C54441) /* 846 */, W64LIT(0x752F95F4FD6A6CA6) /* 847 */, - W64LIT(0x927217402C08C6E5) /* 848 */, W64LIT(0x2A8AB754A795D9EE) /* 849 */, - W64LIT(0xA442F7552F72943D) /* 850 */, W64LIT(0x2C31334E19781208) /* 851 */, - W64LIT(0x4FA98D7CEAEE6291) /* 852 */, W64LIT(0x55C3862F665DB309) /* 853 */, - W64LIT(0xBD0610175D53B1F3) /* 854 */, W64LIT(0x46FE6CB840413F27) /* 855 */, - W64LIT(0x3FE03792DF0CFA59) /* 856 */, W64LIT(0xCFE700372EB85E8F) /* 857 */, - W64LIT(0xA7BE29E7ADBCE118) /* 858 */, W64LIT(0xE544EE5CDE8431DD) /* 859 */, - W64LIT(0x8A781B1B41F1873E) /* 860 */, W64LIT(0xA5C94C78A0D2F0E7) /* 861 */, - W64LIT(0x39412E2877B60728) /* 862 */, W64LIT(0xA1265EF3AFC9A62C) /* 863 */, - W64LIT(0xBCC2770C6A2506C5) /* 864 */, W64LIT(0x3AB66DD5DCE1CE12) /* 865 */, - W64LIT(0xE65499D04A675B37) /* 866 */, W64LIT(0x7D8F523481BFD216) /* 867 */, - W64LIT(0x0F6F64FCEC15F389) /* 868 */, W64LIT(0x74EFBE618B5B13C8) /* 869 */, - W64LIT(0xACDC82B714273E1D) /* 870 */, W64LIT(0xDD40BFE003199D17) /* 871 */, - W64LIT(0x37E99257E7E061F8) /* 872 */, W64LIT(0xFA52626904775AAA) /* 873 */, - W64LIT(0x8BBBF63A463D56F9) /* 874 */, W64LIT(0xF0013F1543A26E64) /* 875 */, - W64LIT(0xA8307E9F879EC898) /* 876 */, W64LIT(0xCC4C27A4150177CC) /* 877 */, - W64LIT(0x1B432F2CCA1D3348) /* 878 */, W64LIT(0xDE1D1F8F9F6FA013) /* 879 */, - W64LIT(0x606602A047A7DDD6) /* 880 */, W64LIT(0xD237AB64CC1CB2C7) /* 881 */, - W64LIT(0x9B938E7225FCD1D3) /* 882 */, W64LIT(0xEC4E03708E0FF476) /* 883 */, - W64LIT(0xFEB2FBDA3D03C12D) /* 884 */, W64LIT(0xAE0BCED2EE43889A) /* 885 */, - W64LIT(0x22CB8923EBFB4F43) /* 886 */, W64LIT(0x69360D013CF7396D) /* 887 */, - W64LIT(0x855E3602D2D4E022) /* 888 */, W64LIT(0x073805BAD01F784C) /* 889 */, - W64LIT(0x33E17A133852F546) /* 890 */, W64LIT(0xDF4874058AC7B638) /* 891 */, - W64LIT(0xBA92B29C678AA14A) /* 892 */, W64LIT(0x0CE89FC76CFAADCD) /* 893 */, - W64LIT(0x5F9D4E0908339E34) /* 894 */, W64LIT(0xF1AFE9291F5923B9) /* 895 */, - W64LIT(0x6E3480F60F4A265F) /* 896 */, W64LIT(0xEEBF3A2AB29B841C) /* 897 */, - W64LIT(0xE21938A88F91B4AD) /* 898 */, W64LIT(0x57DFEFF845C6D3C3) /* 899 */, - W64LIT(0x2F006B0BF62CAAF2) /* 900 */, W64LIT(0x62F479EF6F75EE78) /* 901 */, - W64LIT(0x11A55AD41C8916A9) /* 902 */, W64LIT(0xF229D29084FED453) /* 903 */, - W64LIT(0x42F1C27B16B000E6) /* 904 */, W64LIT(0x2B1F76749823C074) /* 905 */, - W64LIT(0x4B76ECA3C2745360) /* 906 */, W64LIT(0x8C98F463B91691BD) /* 907 */, - W64LIT(0x14BCC93CF1ADE66A) /* 908 */, W64LIT(0x8885213E6D458397) /* 909 */, - W64LIT(0x8E177DF0274D4711) /* 910 */, W64LIT(0xB49B73B5503F2951) /* 911 */, - W64LIT(0x10168168C3F96B6B) /* 912 */, W64LIT(0x0E3D963B63CAB0AE) /* 913 */, - W64LIT(0x8DFC4B5655A1DB14) /* 914 */, W64LIT(0xF789F1356E14DE5C) /* 915 */, - W64LIT(0x683E68AF4E51DAC1) /* 916 */, W64LIT(0xC9A84F9D8D4B0FD9) /* 917 */, - W64LIT(0x3691E03F52A0F9D1) /* 918 */, W64LIT(0x5ED86E46E1878E80) /* 919 */, - W64LIT(0x3C711A0E99D07150) /* 920 */, W64LIT(0x5A0865B20C4E9310) /* 921 */, - W64LIT(0x56FBFC1FE4F0682E) /* 922 */, W64LIT(0xEA8D5DE3105EDF9B) /* 923 */, - W64LIT(0x71ABFDB12379187A) /* 924 */, W64LIT(0x2EB99DE1BEE77B9C) /* 925 */, - W64LIT(0x21ECC0EA33CF4523) /* 926 */, W64LIT(0x59A4D7521805C7A1) /* 927 */, - W64LIT(0x3896F5EB56AE7C72) /* 928 */, W64LIT(0xAA638F3DB18F75DC) /* 929 */, - W64LIT(0x9F39358DABE9808E) /* 930 */, W64LIT(0xB7DEFA91C00B72AC) /* 931 */, - W64LIT(0x6B5541FD62492D92) /* 932 */, W64LIT(0x6DC6DEE8F92E4D5B) /* 933 */, - W64LIT(0x353F57ABC4BEEA7E) /* 934 */, W64LIT(0x735769D6DA5690CE) /* 935 */, - W64LIT(0x0A234AA642391484) /* 936 */, W64LIT(0xF6F9508028F80D9D) /* 937 */, - W64LIT(0xB8E319A27AB3F215) /* 938 */, W64LIT(0x31AD9C1151341A4D) /* 939 */, - W64LIT(0x773C22A57BEF5805) /* 940 */, W64LIT(0x45C7561A07968633) /* 941 */, - W64LIT(0xF913DA9E249DBE36) /* 942 */, W64LIT(0xDA652D9B78A64C68) /* 943 */, - W64LIT(0x4C27A97F3BC334EF) /* 944 */, W64LIT(0x76621220E66B17F4) /* 945 */, - W64LIT(0x967743899ACD7D0B) /* 946 */, W64LIT(0xF3EE5BCAE0ED6782) /* 947 */, - W64LIT(0x409F753600C879FC) /* 948 */, W64LIT(0x06D09A39B5926DB6) /* 949 */, - W64LIT(0x6F83AEB0317AC588) /* 950 */, W64LIT(0x01E6CA4A86381F21) /* 951 */, - W64LIT(0x66FF3462D19F3025) /* 952 */, W64LIT(0x72207C24DDFD3BFB) /* 953 */, - W64LIT(0x4AF6B6D3E2ECE2EB) /* 954 */, W64LIT(0x9C994DBEC7EA08DE) /* 955 */, - W64LIT(0x49ACE597B09A8BC4) /* 956 */, W64LIT(0xB38C4766CF0797BA) /* 957 */, - W64LIT(0x131B9373C57C2A75) /* 958 */, W64LIT(0xB1822CCE61931E58) /* 959 */, - W64LIT(0x9D7555B909BA1C0C) /* 960 */, W64LIT(0x127FAFDD937D11D2) /* 961 */, - W64LIT(0x29DA3BADC66D92E4) /* 962 */, W64LIT(0xA2C1D57154C2ECBC) /* 963 */, - W64LIT(0x58C5134D82F6FE24) /* 964 */, W64LIT(0x1C3AE3515B62274F) /* 965 */, - W64LIT(0xE907C82E01CB8126) /* 966 */, W64LIT(0xF8ED091913E37FCB) /* 967 */, - W64LIT(0x3249D8F9C80046C9) /* 968 */, W64LIT(0x80CF9BEDE388FB63) /* 969 */, - W64LIT(0x1881539A116CF19E) /* 970 */, W64LIT(0x5103F3F76BD52457) /* 971 */, - W64LIT(0x15B7E6F5AE47F7A8) /* 972 */, W64LIT(0xDBD7C6DED47E9CCF) /* 973 */, - W64LIT(0x44E55C410228BB1A) /* 974 */, W64LIT(0xB647D4255EDB4E99) /* 975 */, - W64LIT(0x5D11882BB8AAFC30) /* 976 */, W64LIT(0xF5098BBB29D3212A) /* 977 */, - W64LIT(0x8FB5EA14E90296B3) /* 978 */, W64LIT(0x677B942157DD025A) /* 979 */, - W64LIT(0xFB58E7C0A390ACB5) /* 980 */, W64LIT(0x89D3674C83BD4A01) /* 981 */, - W64LIT(0x9E2DA4DF4BF3B93B) /* 982 */, W64LIT(0xFCC41E328CAB4829) /* 983 */, - W64LIT(0x03F38C96BA582C52) /* 984 */, W64LIT(0xCAD1BDBD7FD85DB2) /* 985 */, - W64LIT(0xBBB442C16082AE83) /* 986 */, W64LIT(0xB95FE86BA5DA9AB0) /* 987 */, - W64LIT(0xB22E04673771A93F) /* 988 */, W64LIT(0x845358C9493152D8) /* 989 */, - W64LIT(0xBE2A488697B4541E) /* 990 */, W64LIT(0x95A2DC2DD38E6966) /* 991 */, - W64LIT(0xC02C11AC923C852B) /* 992 */, W64LIT(0x2388B1990DF2A87B) /* 993 */, - W64LIT(0x7C8008FA1B4F37BE) /* 994 */, W64LIT(0x1F70D0C84D54E503) /* 995 */, - W64LIT(0x5490ADEC7ECE57D4) /* 996 */, W64LIT(0x002B3C27D9063A3A) /* 997 */, - W64LIT(0x7EAEA3848030A2BF) /* 998 */, W64LIT(0xC602326DED2003C0) /* 999 */, - W64LIT(0x83A7287D69A94086) /* 1000 */, W64LIT(0xC57A5FCB30F57A8A) /* 1001 */, - W64LIT(0xB56844E479EBE779) /* 1002 */, W64LIT(0xA373B40F05DCBCE9) /* 1003 */, - W64LIT(0xD71A786E88570EE2) /* 1004 */, W64LIT(0x879CBACDBDE8F6A0) /* 1005 */, - W64LIT(0x976AD1BCC164A32F) /* 1006 */, W64LIT(0xAB21E25E9666D78B) /* 1007 */, - W64LIT(0x901063AAE5E5C33C) /* 1008 */, W64LIT(0x9818B34448698D90) /* 1009 */, - W64LIT(0xE36487AE3E1E8ABB) /* 1010 */, W64LIT(0xAFBDF931893BDCB4) /* 1011 */, - W64LIT(0x6345A0DC5FBBD519) /* 1012 */, W64LIT(0x8628FE269B9465CA) /* 1013 */, - W64LIT(0x1E5D01603F9C51EC) /* 1014 */, W64LIT(0x4DE44006A15049B7) /* 1015 */, - W64LIT(0xBF6C70E5F776CBB1) /* 1016 */, W64LIT(0x411218F2EF552BED) /* 1017 */, - W64LIT(0xCB0C0708705A36A3) /* 1018 */, W64LIT(0xE74D14754F986044) /* 1019 */, - W64LIT(0xCD56D9430EA8280E) /* 1020 */, W64LIT(0xC12591D7535F5065) /* 1021 */, - W64LIT(0xC83223F1720AEF96) /* 1022 */, W64LIT(0xC3A0396F7363A51F) /* 1023 */, - W64LIT(0xffffffffffffffff), - W64LIT(0xA5A5A5A5A5A5A5A5), - W64LIT(0x0123456789ABCDEF), -}; - -NAMESPACE_END diff --git a/embeddedcryptopp/trdlocal.h b/embeddedcryptopp/trdlocal.h deleted file mode 100644 index 92d244a..0000000 --- a/embeddedcryptopp/trdlocal.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef CRYPTOPP_TRDLOCAL_H -#define CRYPTOPP_TRDLOCAL_H - -#include "config.h" - -#ifdef THREADS_AVAILABLE - -#include "misc.h" - -#ifdef HAS_WINTHREADS -typedef unsigned long ThreadLocalIndexType; -#else -#include -typedef pthread_key_t ThreadLocalIndexType; -#endif - -NAMESPACE_BEGIN(CryptoPP) - -//! thread local storage -class CRYPTOPP_DLL ThreadLocalStorage : public NotCopyable -{ -public: - //! exception thrown by ThreadLocalStorage class - class Err : public OS_Error - { - public: - Err(const std::string& operation, int error); - }; - - ThreadLocalStorage(); - ~ThreadLocalStorage(); - - void SetValue(void *value); - void *GetValue() const; - -private: - ThreadLocalIndexType m_index; -}; - -NAMESPACE_END - -#endif // #ifdef THREADS_AVAILABLE - -#endif diff --git a/embeddedcryptopp/words.h b/embeddedcryptopp/words.h deleted file mode 100644 index d5fda71..0000000 --- a/embeddedcryptopp/words.h +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef CRYPTOPP_WORDS_H -#define CRYPTOPP_WORDS_H - -#include "misc.h" - -NAMESPACE_BEGIN(CryptoPP) - -inline size_t CountWords(const word *X, size_t N) -{ - while (N && X[N-1]==0) - N--; - return N; -} - -inline void SetWords(word *r, word a, size_t n) -{ - for (size_t i=0; i> (WORD_BITS-shiftBits); - } - return carry; -} - -inline word ShiftWordsRightByBits(word *r, size_t n, unsigned int shiftBits) -{ - assert (shiftBits0; i--) - { - u = r[i-1]; - r[i-1] = (u >> shiftBits) | carry; - carry = u << (WORD_BITS-shiftBits); - } - return carry; -} - -inline void ShiftWordsLeftByWords(word *r, size_t n, size_t shiftWords) -{ - shiftWords = STDMIN(shiftWords, n); - if (shiftWords) - { - for (size_t i=n-1; i>=shiftWords; i--) - r[i] = r[i-shiftWords]; - SetWords(r, 0, shiftWords); - } -} - -inline void ShiftWordsRightByWords(word *r, size_t n, size_t shiftWords) -{ - shiftWords = STDMIN(shiftWords, n); - if (shiftWords) - { - for (size_t i=0; i+shiftWords - -#include "publickey/ecdsamodule.hpp" -#include "publickey/rsamodule.hpp" -#include "hash/sha256module.hpp" -#include "cipher/aesmodule.hpp" - -/* from Crypto++ */ -#ifdef DISABLE_EMBEDDED_CRYPTOPP -#include -#else -#include -#endif - -PyDoc_STRVAR(_pycryptopp__doc__, -"_pycryptopp -- Python wrappers for a few algorithms from Crypto++\n\ -\n\ -from pycryptopp import publickey\n\ -from pycryptopp.publickey import ecdsa\n\ -from pycryptopp.publickey import rsa\n\ -from pycryptopp import cipher\n\ -from pycryptopp.cipher import aes\n\ -from pycryptopp import hash\n\ -from pycryptopp.hash import sha256"); - -static PyMethodDef _pycryptopp_functions[] = { - {"rsa_generate", reinterpret_cast(rsa_generate), METH_KEYWORDS, const_cast(rsa_generate__doc__)}, - {"rsa_create_verifying_key_from_string", reinterpret_cast(rsa_create_verifying_key_from_string), METH_KEYWORDS, const_cast(rsa_create_verifying_key_from_string__doc__)}, - {"rsa_create_signing_key_from_string", reinterpret_cast(rsa_create_signing_key_from_string), METH_KEYWORDS, const_cast(rsa_create_signing_key_from_string__doc__)}, - {NULL, NULL, 0, NULL} /* sentinel */ -}; - -#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ -#define PyMODINIT_FUNC void -#endif -PyMODINIT_FUNC -init_pycryptopp(void) { - PyObject *module; - - module = Py_InitModule3("_pycryptopp", _pycryptopp_functions, _pycryptopp__doc__); - if (!module) - return; - - PyObject* version; - - /* a tuple of (Crypto++ version, extra-version) */ - #ifdef CRYPTOPP_EXTRA_VERSION - version = Py_BuildValue("is", CRYPTOPP_VERSION, CRYPTOPP_EXTRA_VERSION); - #else - version = Py_BuildValue("iO", CRYPTOPP_VERSION, Py_None); - #endif - - int succ = PyModule_AddObject(module, "cryptopp_version", version); - if (succ != 0) - return; - - - init_ecdsa(module); - init_rsa(module); - init_sha256(module); - init_aes(module); -} diff --git a/pycryptopp/_version.py b/pycryptopp/_version.py deleted file mode 100644 index 40d866f..0000000 --- a/pycryptopp/_version.py +++ /dev/null @@ -1,17 +0,0 @@ - -# This is the version of this tree, as created by setup.py darcsver from the darcs patch -# information: the main version number is taken from the most recent release -# tag. If some patches have been added since the last release, this will have a -# -NN "build number" suffix, or else a -rNN "revision number" suffix. Please see -# pyutil.version_class for a description of what the different fields mean. - -__pkgname__ = "pycryptopp" -verstr = "0.5.29" -try: - from pyutil.version_class import Version as pyutil_Version - __version__ = pyutil_Version(verstr) -except (ImportError, ValueError): - # Maybe there is no pyutil installed, or this may be an older version of - # pyutil.version_class which does not support SVN-alike revision numbers. - from distutils.version import LooseVersion as distutils_Version - __version__ = distutils_Version(verstr) diff --git a/pycryptopp/cipher/__init__.py b/pycryptopp/cipher/__init__.py deleted file mode 100644 index 9033868..0000000 --- a/pycryptopp/cipher/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -import aes - -quiet_pyflakes=[aes] diff --git a/pycryptopp/cipher/aes.py b/pycryptopp/cipher/aes.py deleted file mode 100644 index 7280063..0000000 --- a/pycryptopp/cipher/aes.py +++ /dev/null @@ -1,68 +0,0 @@ - -from pycryptopp import _import_my_names - -# These initializations to None are just to pacify pyflakes, which -# doesn't understand that we have to do some funky import trickery -# below in _import_my_names() in order to get sensible namespaces. -AES=None -Error=None - -_import_my_names(globals(), "aes_") - -del _import_my_names - -def start_up_self_test(): - """ - This is a quick test intended to detect major errors such as the library being - miscompiled and segfaulting or returning incorrect answers. We've had problems - of that kind many times, thus justifying running this self-test on import. - This idea was suggested to me by the second edition of "Practical - Cryptography" by Ferguson, Schneier, and Kohno. - These tests were copied from pycryptopp/test/test_aes.py on 2009-10-30. - """ - enc0 = "dc95c078a2408989ad48a21492842087530f8afbc74536b9a963b4f1c4cb738b" - from binascii import a2b_hex, b2a_hex - - cryptor = AES(key="\x00"*32) - ct = cryptor.process("\x00"*32) - if enc0 != b2a_hex(ct): - raise Error("pycryptopp failed startup self-test. Please run pycryptopp unit tests.") - - cryptor = AES(key="\x00"*32) - ct1 = cryptor.process("\x00"*15) - ct2 = cryptor.process("\x00"*17) - if enc0 != b2a_hex(ct1+ct2): - raise Error("pycryptopp failed startup self-test. Please run pycryptopp unit tests.") - - enc0 = "66e94bd4ef8a2c3b884cfa59ca342b2e" - cryptor = AES(key="\x00"*16) - ct = cryptor.process("\x00"*16) - if enc0 != b2a_hex(ct): - raise Error("pycryptopp failed startup self-test. Please run pycryptopp unit tests.") - - cryptor = AES(key="\x00"*16) - ct1 = cryptor.process("\x00"*8) - ct2 = cryptor.process("\x00"*8) - if enc0 != b2a_hex(ct1+ct2): - raise Error("pycryptopp failed startup self-test. Please run pycryptopp unit tests.") - - def _test_from_Niels_AES(keysize, result): - def fake_ecb_using_ctr(k, p): - return AES(key=k, iv=p).process('\x00'*16) - - E = fake_ecb_using_ctr - b = 16 - k = keysize - S = '\x00' * (k+b) - for i in range(1000): - K = S[-k:] - P = S[-k-b:-k] - S += E(K, E(K, P)) - - if S[-b:] != a2b_hex(result): - raise Error("pycryptopp failed startup self-test. Please run pycryptopp unit tests.") - - _test_from_Niels_AES(16, 'bd883f01035e58f42f9d812f2dacbcd8') - _test_from_Niels_AES(32, 'c84b0f3a2c76dd9871900b07f09bdd3e') - -start_up_self_test() diff --git a/pycryptopp/cipher/aesmodule.cpp b/pycryptopp/cipher/aesmodule.cpp deleted file mode 100644 index cca48f4..0000000 --- a/pycryptopp/cipher/aesmodule.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/** - * aesmodule.cpp -- Python wrappers around Crypto++'s AES-CTR - */ - -#define PY_SSIZE_T_CLEAN -#include -#if (PY_VERSION_HEX < 0x02050000) -typedef int Py_ssize_t; -#endif - -#include "aesmodule.hpp" - - -/* from Crypto++ */ -#ifdef DISABLE_EMBEDDED_CRYPTOPP -#include -#include -#else -#include -#include -#endif - -static const char*const aes___doc__ = "_aes counter mode cipher\n\ -You are advised to run aes.start_up_self_test() after importing this module."; - -static PyObject *aes_error; - -typedef struct { - PyObject_HEAD - - /* internal */ - CryptoPP::CTR_Mode::Encryption * e; -} AES; - -PyDoc_STRVAR(AES__doc__, -"An AES cipher object.\n\ -\n\ -This object encrypts/decrypts in CTR mode, using a counter that is initialized\n\ -to zero when you instantiate the object. Successive calls to .process() will\n\ -use the current counter value and increment it.\n\ -\n\ -Note that you must never encrypt different data with the same key, or you\n\ -will leak information about your data. Therefore the only safe way to use\n\ -this class is to use a different AES key every time you are going to encrypt\n\ -different data. A good way to generate a different AES key is using AES, like\n\ -this:\n\ -\n\ - onetimekey = AES(key=masterkey).process(nonce)\n\ -\n\ -Where 'masterkey' is a secret key used only for generating onetimekeys this\ -way, and 'nonce' is a value that is guaranteed to never repeat.\ -\n\ -@param key: the symmetric encryption key; a string of exactly 16 bytes\ -"); - -static PyObject * -AES_process(AES* self, PyObject* msgobj) { - if (!PyString_CheckExact(msgobj)) { - PyStringObject* typerepr = reinterpret_cast(PyObject_Repr(reinterpret_cast(msgobj->ob_type))); - if (typerepr) { - PyErr_Format(aes_error, "Precondition violation: you are required to pass a Python string object (not a unicode, a subclass of string, or anything else), but you passed %s.", PyString_AS_STRING(reinterpret_cast(typerepr))); - Py_DECREF(typerepr); - } else - PyErr_Format(aes_error, "Precondition violation: you are required to pass a Python string object (not a unicode, a subclass of string, or anything else)."); - return NULL; - } - - const char *msg; - Py_ssize_t msgsize; - if (PyString_AsStringAndSize(msgobj, const_cast(&msg), &msgsize)) - return NULL; - assert (msgsize >= 0); - - PyStringObject* result = reinterpret_cast(PyString_FromStringAndSize(NULL, msgsize)); - if (!result) - return NULL; - - self->e->ProcessData(reinterpret_cast(PyString_AS_STRING(result)), reinterpret_cast(msg), msgsize); - return reinterpret_cast(result); -} - -PyDoc_STRVAR(AES_process__doc__, -"Encrypt or decrypt the next bytes, returning the result."); - -static PyMethodDef AES_methods[] = { - {"process", reinterpret_cast(AES_process), METH_O, AES_process__doc__}, - {NULL}, -}; - -static PyObject * -AES_new(PyTypeObject* type, PyObject *args, PyObject *kwdict) { - AES* self = reinterpret_cast(type->tp_alloc(type, 0)); - if (!self) - return NULL; - self->e = NULL; - return reinterpret_cast(self); -} - -static void -AES_dealloc(PyObject* self) { - if (reinterpret_cast(self)->e) - delete reinterpret_cast(self)->e; - self->ob_type->tp_free(self); -} - -static int -AES_init(PyObject* self, PyObject *args, PyObject *kwdict) { - static const char *kwlist[] = { "key", "iv", NULL }; - const char *key = NULL; - Py_ssize_t keysize = 0; - const char *iv = NULL; - const char defaultiv[CryptoPP::AES::BLOCKSIZE] = {0}; - Py_ssize_t ivsize = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#|t#:AES.__init__", const_cast(kwlist), &key, &keysize, &iv, &ivsize)) - return -1; - assert (keysize >= 0); - assert (ivsize >= 0); - - if (!iv) - iv = defaultiv; - try { - reinterpret_cast(self)->e = new CryptoPP::CTR_Mode::Encryption(reinterpret_cast(key), keysize, reinterpret_cast(iv)); - } catch (CryptoPP::InvalidKeyLength le) { - PyErr_Format(aes_error, "Precondition violation: you are required to pass a valid key size. Crypto++ gave this exception: %s", le.what()); - return -1; - } - if (!reinterpret_cast(self)->e) { - PyErr_NoMemory(); - return -1; - } - return 0; -} - -static PyTypeObject AES_type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "_aes.AES", /*tp_name*/ - sizeof(AES), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - AES_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - AES__doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - AES_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - AES_init, /* tp_init */ - 0, /* tp_alloc */ - AES_new, /* tp_new */ -}; - -void -init_aes(PyObject*const module) { - if (PyType_Ready(&AES_type) < 0) - return; - Py_INCREF(&AES_type); - PyModule_AddObject(module, "aes_AES", (PyObject *)&AES_type); - - aes_error = PyErr_NewException(const_cast("_aes.Error"), NULL, NULL); - PyModule_AddObject(module, "aes_Error", aes_error); - - PyModule_AddStringConstant(module, "aes___doc__", const_cast(aes___doc__)); -} diff --git a/pycryptopp/cipher/aesmodule.hpp b/pycryptopp/cipher/aesmodule.hpp deleted file mode 100644 index d10f44f..0000000 --- a/pycryptopp/cipher/aesmodule.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __INCL_AESMODULE_HPP -#define __INCL_AESMODULE_HPP - -extern void -init_aes(PyObject* module); - -#endif /* #ifndef __INCL_AESMODULE_HPP */ diff --git a/pycryptopp/hash/__init__.py b/pycryptopp/hash/__init__.py deleted file mode 100644 index 5399f81..0000000 --- a/pycryptopp/hash/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -import sha256 - -quiet_pyflakes=[sha256] diff --git a/pycryptopp/hash/sha256.py b/pycryptopp/hash/sha256.py deleted file mode 100644 index cf52a31..0000000 --- a/pycryptopp/hash/sha256.py +++ /dev/null @@ -1,43 +0,0 @@ -from pycryptopp import _import_my_names - -# These initializations to None are just to pacify pyflakes, which -# doesn't understand that we have to do some funky import trickery -# below in _import_my_names() in order to get sensible namespaces. -SHA256=None -Error=None - -_import_my_names(globals(), "sha256_") - -del _import_my_names - -def start_up_self_test(): - """ - This is a quick test intended to detect major errors such as the library being - miscompiled and segfaulting or returning incorrect answers. We've had problems - of that kind many times, thus justifying running this self-test on import. - This idea was suggested to me by the second edition of "Practical - Cryptography" by Ferguson, Schneier, and Kohno. - This test was copied from pycryptopp/test/test_sha256.py on 2010-09-04. - - This test takes up to 1.5 milliseconds on a VirtualBox instance on - my Macbook Pro (fast 64-bit Intel dual-core). - - Test that updating a hasher with various sized inputs yields - the expected answer. This is somewhat redundant with - test_chunksize(), but that's okay. This one exercises some - slightly different situations (such as finalizing a hash after - different length inputs.) This one is recursive so that there - is a single fixed result that we expect. - """ - hx = SHA256() - s = ''.join([ chr(c) for c in range(65) ]) - for i in range(0, 65): - hy = SHA256(s[:i]).digest() - hx.update(hy) - for i in range(0, 65): - hx.update(chr(0xFE)) - hx.update(s[:64]) - if hx.hexdigest().lower() != '5191c7841dd4e16aa454d40af924585dffc67157ffdbfd0236acddd07901629d': - raise Error("pycryptopp failed startup self-test. Please run pycryptopp unit tests.") - -start_up_self_test() diff --git a/pycryptopp/hash/sha256module.cpp b/pycryptopp/hash/sha256module.cpp deleted file mode 100644 index 2e13353..0000000 --- a/pycryptopp/hash/sha256module.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/** - * sha256module.cpp -- Python wrappers around Crypto++'s SHA-256 - */ - -#define PY_SSIZE_T_CLEAN -#include -#if (PY_VERSION_HEX < 0x02050000) -typedef int Py_ssize_t; -#endif - -#include - -/* from Crypto++ */ -#ifdef DISABLE_EMBEDDED_CRYPTOPP -#include -#include -#include -#else -#include -#include -#include -#endif - -static const char*const sha256___doc__ = "_sha256 hash function"; - -static PyObject *sha256_error; - -typedef struct { - PyObject_HEAD - - /* internal */ - CryptoPP::SHA256* h; - PyStringObject* digest; -} SHA256; - -PyDoc_STRVAR(SHA256__doc__, -"a SHA256 hash object\n\ -Its constructor takes an optional string, which has the same effect as\n\ -calling .update() with that string."); - -static PyObject * -SHA256_update(SHA256* self, PyObject* msgobj) { - if (self->digest) - return PyErr_Format(sha256_error, "Precondition violation: once .digest() has been called you are required to never call .update() again."); - - const char *msg; - Py_ssize_t msgsize; - if (PyString_AsStringAndSize(msgobj, const_cast(&msg), &msgsize)) - return NULL; - self->h->Update(reinterpret_cast(msg), msgsize); - Py_RETURN_NONE; -} - -PyDoc_STRVAR(SHA256_update__doc__, -"Update the hash object with the string msg. Repeated calls are equivalent to\n\ -a single call with the concatenation of all the messages."); - -static PyObject * -SHA256_digest(SHA256* self, PyObject* dummy) { - if (!self->digest) { - assert (self->h); - self->digest = reinterpret_cast(PyString_FromStringAndSize(NULL, self->h->DigestSize())); - if (!self->digest) - return NULL; - self->h->Final(reinterpret_cast(PyString_AS_STRING(self->digest))); - } - - Py_INCREF(self->digest); - return reinterpret_cast(self->digest); -} - -PyDoc_STRVAR(SHA256_digest__doc__, -"Return the binary digest of the messages that were passed to the update()\n\ -method (including the initial message if any)."); - -static PyObject * -SHA256_hexdigest(SHA256* self, PyObject* dummy) { - PyObject* digest = SHA256_digest(self, NULL); - if (!digest) - return NULL; - Py_ssize_t dsize = PyString_GET_SIZE(digest); - PyStringObject* hexdigest = reinterpret_cast(PyString_FromStringAndSize(NULL, dsize*2)); - CryptoPP::ArraySink* as = new CryptoPP::ArraySink(reinterpret_cast(PyString_AS_STRING(hexdigest)), dsize*2); - CryptoPP::HexEncoder enc; - enc.Attach(as); - enc.Put(reinterpret_cast(PyString_AS_STRING(digest)), static_cast(dsize)); - Py_DECREF(digest); digest = NULL; - - return reinterpret_cast(hexdigest); -} - -PyDoc_STRVAR(SHA256_hexdigest__doc__, -"Return the hex-encoded digest of the messages that were passed to the update()\n\ -method (including the initial message if any)."); - -static PyMethodDef SHA256_methods[] = { - {"update", reinterpret_cast(SHA256_update), METH_O, SHA256_update__doc__}, - {"digest", reinterpret_cast(SHA256_digest), METH_NOARGS, SHA256_digest__doc__}, - {"hexdigest", reinterpret_cast(SHA256_hexdigest), METH_NOARGS, SHA256_hexdigest__doc__}, - {NULL}, -}; - -static PyObject * -SHA256_new(PyTypeObject* type, PyObject *args, PyObject *kwdict) { - SHA256* self = reinterpret_cast(type->tp_alloc(type, 0)); - if (!self) - return NULL; - self->h = new CryptoPP::SHA256(); - if (!self->h) - return PyErr_NoMemory(); - self->digest = NULL; - return reinterpret_cast(self); -} - -static void -SHA256_dealloc(SHA256* self) { - Py_XDECREF(self->digest); - delete self->h; - self->ob_type->tp_free((PyObject*)self); -} - -static int -SHA256_init(PyObject* self, PyObject *args, PyObject *kwdict) { - static const char *kwlist[] = { "msg", NULL }; - const char *msg = NULL; - Py_ssize_t msgsize = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|t#", const_cast(kwlist), &msg, &msgsize)) - return -1; - - if (msg) - reinterpret_cast(self)->h->Update(reinterpret_cast(msg), msgsize); - return 0; -} - -static PyTypeObject SHA256_type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "_sha256.SHA256", /*tp_name*/ - sizeof(SHA256), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - reinterpret_cast(SHA256_dealloc), /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - SHA256__doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - SHA256_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - //reinterpret_cast(SHA256_init), /* tp_init */ - SHA256_init, /* tp_init */ - 0, /* tp_alloc */ - SHA256_new, /* tp_new */ -}; - -void -init_sha256(PyObject* module) { - if (PyType_Ready(&SHA256_type) < 0) - return; - Py_INCREF(&SHA256_type); - PyModule_AddObject(module, "sha256_SHA256", (PyObject *)&SHA256_type); - - sha256_error = PyErr_NewException(const_cast("_sha256.Error"), NULL, NULL); - PyModule_AddObject(module, "sha256_Error", sha256_error); - - PyModule_AddStringConstant(module, "sha256___doc__", const_cast(sha256___doc__)); -} diff --git a/pycryptopp/hash/sha256module.hpp b/pycryptopp/hash/sha256module.hpp deleted file mode 100644 index 2dac9b5..0000000 --- a/pycryptopp/hash/sha256module.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __INCL_SHA256MODULE_HPP -#define __INCL_SHA256MODULE_HPP - -extern void -init_sha256(PyObject* module); - -#endif /* #ifndef __INCL_SHA256MODULE_HPP */ diff --git a/pycryptopp/publickey/__init__.py b/pycryptopp/publickey/__init__.py deleted file mode 100644 index a76075f..0000000 --- a/pycryptopp/publickey/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -import ecdsa, rsa - -quiet_pyflakes=[ecdsa, rsa] diff --git a/pycryptopp/publickey/ecdsa.py b/pycryptopp/publickey/ecdsa.py deleted file mode 100644 index c25ba33..0000000 --- a/pycryptopp/publickey/ecdsa.py +++ /dev/null @@ -1,5 +0,0 @@ -from pycryptopp import _import_my_names - -_import_my_names(globals(), "ecdsa_") - -del _import_my_names diff --git a/pycryptopp/publickey/ecdsamodule.cpp b/pycryptopp/publickey/ecdsamodule.cpp deleted file mode 100644 index 95df348..0000000 --- a/pycryptopp/publickey/ecdsamodule.cpp +++ /dev/null @@ -1,523 +0,0 @@ -/** -* Things to do: -* Make it work and pass tests. -* compressed pub keys -- check out Wei Dai's example code on mailinglist as linked to from pycryptopp trac by Brian -* Make new KDF (standard, Crypto++-compatible). -* in C++ -* in Python -* use Crypto++ Randomize()'s -* provide RNG class which is P1363-SHA-256 - -* Profit! -* Migrate pair-programming to Bespin. -* Put a Tahoe backend under Bespin. -*/ - -/** - * ecdsamodule.cpp -- Python wrappers around Crypto++'s - * ECDSA(1363)/EMSA1(SHA-256) -- ECDSA. - * - * The keys (192-bit) use the curve ASN1::secp192r1() and SHA-256 as the - * hash function. The Key Derivation Protocol is P1363_KDF2 - * http://www.users.zetnet.co.uk/hopwood/crypto/scan/prf.html#KDF2 - * to generate private (signing) keys from unguessable seeds -- see - * source code for details and doc string for usage. - */ - -#define PY_SSIZE_T_CLEAN -#include -#if (PY_VERSION_HEX < 0x02050000) -typedef int Py_ssize_t; -#endif - -#include - -#include "ecdsamodule.hpp" - -/* from Crypto++ */ -#ifdef DISABLE_EMBEDDED_CRYPTOPP -#include -#include -#include -#include -#include -#include -#include -// only needed for debugging -- the _dump() function -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -#include -// only needed for debugging -- the _dump() function -#include -#include -#include -#endif - -static const int KEY_SIZE_BITS=192; - -USING_NAMESPACE(CryptoPP) - -static const char*const ecdsa___doc__ = "ecdsa -- ECDSA(1363)/EMSA1(Tiger) signatures\n\ -\n\ -To create a new ECDSA signing key (deterministically from a 12-byte seed), construct an instance of the class, passing the seed as argument, i.e. SigningKey(seed).\n\ -\n\ -To get a verifying key from a signing key, call get_verifying_key() on the signing key instance.\n\ -\n\ -To deserialize an ECDSA verifying key from a string, call VerifyingKey(serialized_verifying_key)."; - -static PyObject *ecdsa_error; - -typedef struct { - PyObject_HEAD - - /* internal */ - ECDSA::Verifier *k; -} VerifyingKey; - -PyDoc_STRVAR(VerifyingKey__doc__, -"an ECDSA verifying key"); - -static int -VerifyingKey___init__(PyObject* self, PyObject* args, PyObject* kwdict) { - static const char *kwlist[] = { "serializedverifyingkey", NULL }; - const char *serializedverifyingkey; - Py_ssize_t serializedverifyingkeysize = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#:VerifyingKey__init__", const_cast(kwlist), &serializedverifyingkey, &serializedverifyingkeysize)) - return NULL; - assert (serializedverifyingkeysize >= 0); - - if (serializedverifyingkeysize != 25) { - PyErr_Format(ecdsa_error, "Precondition violation: size in bits is required to be %d (for %d-bit key), but it was %Zd", 25, KEY_SIZE_BITS, serializedverifyingkeysize); - return -1; - } - - VerifyingKey *mself = reinterpret_cast(self); - - StringSource ss(reinterpret_cast(serializedverifyingkey), serializedverifyingkeysize, true); - - ECP::Element element; - DL_GroupParameters_EC params(ASN1::secp192r1()); - params.SetPointCompression(true); - try { - element = params.DecodeElement(reinterpret_cast(serializedverifyingkey), true); - mself->k = new ECDSA::Verifier(params, element); - if (!mself->k) { - PyErr_NoMemory(); - return -1; - } - } catch (InvalidDataFormat le) { - PyErr_Format(ecdsa_error, "Serialized verifying key was corrupted. Crypto++ gave this exception: %s", le.what()); - return -1; - } - - return 0; -} - -static void -VerifyingKey_dealloc(VerifyingKey* self) { - if (self->k) - delete self->k; - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject * -VerifyingKey_verify(VerifyingKey *self, PyObject *args, PyObject *kwdict) { - static const char *kwlist[] = { "msg", "signature", NULL }; - const char *msg; - Py_ssize_t msgsize; - const char *signature; - Py_ssize_t signaturesize = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#t#:verify", const_cast(kwlist), &msg, &msgsize, &signature, &signaturesize)) - return NULL; - assert (msgsize >= 0); - assert (signaturesize >= 0); - - if (self->k->VerifyMessage(reinterpret_cast(msg), msgsize, reinterpret_cast(signature), signaturesize)) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - -PyDoc_STRVAR(VerifyingKey_verify__doc__, -"Return whether the signature is a valid signature on the msg."); - -static PyObject * -VerifyingKey_serialize(VerifyingKey *self, PyObject *dummy) { - ECDSA::Verifier *pubkey; - pubkey = new ECDSA::Verifier(*(self->k)); - const DL_GroupParameters_EC& params = pubkey->GetKey().GetGroupParameters(); - - Py_ssize_t len = params.GetEncodedElementSize(true); - PyObject* result = PyString_FromStringAndSize(NULL, len); - if (!result) - return NULL; - - params.EncodeElement(true, pubkey->GetKey().GetPublicElement(), - reinterpret_cast(PyString_AS_STRING(result))); - - return result; -} - -PyDoc_STRVAR(VerifyingKey_serialize__doc__, -"Return a string containing the key material. The string can be passed to \n\ -the constructor of VerifyingKey to instantiate a new copy of this key."); - -static PyMethodDef VerifyingKey_methods[] = { - {"verify", reinterpret_cast(VerifyingKey_verify), METH_KEYWORDS, VerifyingKey_verify__doc__}, - {"serialize", reinterpret_cast(VerifyingKey_serialize), METH_NOARGS, VerifyingKey_serialize__doc__}, - {NULL}, -}; - -static PyTypeObject VerifyingKey_type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "ecdsa.VerifyingKey", /*tp_name*/ - sizeof(VerifyingKey), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)VerifyingKey_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - VerifyingKey__doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - VerifyingKey_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - VerifyingKey___init__, /* tp_init */ -}; - -typedef struct { - PyObject_HEAD - - /* internal */ - ECDSA::Signer *k; -} SigningKey; - -static void -SigningKey_dealloc(SigningKey* self) { - if (self->k) - delete self->k; - self->ob_type->tp_free((PyObject*)self); -} - -static const char* TAG_AND_SALT = "102:pycryptopp v0.5.3 key derivation algorithm using Tiger hash to generate ECDSA 192-bit secret exponents," \ - "16:H1yGNvUONoc0FD1d,"; -static const size_t TAG_AND_SALT_len = 127; - -/** copied from Crypto++'s integer.cpp */ -/** The following is in Crypto++'s integer.cpp and we use them: -* void Integer::Randomize(RandomNumberGenerator &rng, size_t nbits) -* { -* const size_t nbytes = nbits/8 + 1; -* SecByteBlock buf(nbytes); -* rng.GenerateBlock(buf, nbytes); -* if (nbytes) -* buf[0] = (byte)Crop(buf[0], nbits % 8); -* Decode(buf, nbytes, UNSIGNED); -* } -* void Integer::Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max) -* { -* if (min > max) -* throw InvalidArgument("Integer: Min must be no greater than Max"); -* -* Integer range = max - min; -* const unsigned int nbits = range.BitCount(); -* -* do -* { -* Randomize(rng, nbits); -* } -* while (*this > range); -* -* *this += min; -* } -* -*/ - -static int -SigningKey___init__(PyObject* self, PyObject* args, PyObject* kwdict) { - static const char *kwlist[] = { "seed", NULL }; - const char* seed; - Py_ssize_t seedlen; - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#:SigningKey___init__", const_cast(kwlist), &seed, &seedlen)) { - return -1; - } - - if (seedlen != 12) { - PyErr_Format(ecdsa_error, "Precondition violation: seed is required to be of length 12, but it was %zd", seedlen); - return -1; - } - - OID curve; - Integer grouporderm1; - byte privexpbytes[24] = {0}; - Integer privexponentm1; - privexponentm1.Decode(privexpbytes, sizeof(privexpbytes)); assert (privexponentm1 == 0); // just checking.. - - DL_GroupParameters_EC params(ASN1::secp192r1()); - params.SetPointCompression(true); - grouporderm1 = params.GetGroupOrder() - 1; - Tiger t; - - t.Update(reinterpret_cast(TAG_AND_SALT), TAG_AND_SALT_len); - t.Update(reinterpret_cast(seed), seedlen); - t.TruncatedFinal(privexpbytes, Tiger::DIGESTSIZE); - privexponentm1.Decode(privexpbytes, sizeof(privexpbytes)); - - while (privexponentm1 >= grouporderm1) { - Tiger t2; - t2.Update(reinterpret_cast(TAG_AND_SALT), TAG_AND_SALT_len); - std::cerr << "WHEE " << sizeof(privexpbytes) << "\n";std::cerr.flush(); - t2.Update(privexpbytes, sizeof(privexpbytes)); - t2.TruncatedFinal(privexpbytes, Tiger::DIGESTSIZE); - privexponentm1.Decode(privexpbytes, sizeof(privexpbytes)); - } - - SigningKey* mself = reinterpret_cast(self); - - mself->k = new ECDSA::Signer(params, privexponentm1+1); - - if (!mself->k) { - PyErr_NoMemory(); - return -1; - } - - return 0; -} - -PyDoc_STRVAR(SigningKey__init____doc__, -"Create a signing key (192 bits) deterministically from the given seed.\n\ -\n\ -This implies that if someone can guess the seed then they can learn the signing key. A good way to get an unguessable seed is os.urandom(12).\n\ -\n\ -@param seed seed\n\ -\n\ -@precondition len(seed) >= ceil(sizeinbits/16.0)"); - -static PyObject * -SigningKey__dump(SigningKey *self, PyObject *dummy) { - const DL_GroupParameters_EC& gp = self->k->GetKey().GetGroupParameters(); - std::cout << "whee " << gp.GetEncodedElementSize(true) << "\a"; - std::cout << "booo " << gp.GetEncodedElementSize(false) << "\n"; - - ECPPoint p = gp.GetSubgroupGenerator(); - std::cout << "generator " << p.x << ", " << p.y << "\n"; - - std::cout << "GroupOrder: "; - std::cout << gp.GetGroupOrder(); - std::cout << "\n"; - - std::string s; - StringSink* ss = new StringSink(s); - HexEncoder he(ss); - std::cout << "AlgorithmID: "; - gp.GetAlgorithmID().DEREncode(he); - std::cout << s << "\n"; - - const ECP& ec = gp.GetCurve(); - Integer fieldsize = ec.FieldSize(); - std::cout << "field size " << fieldsize.BitCount() << " " << fieldsize.ByteCount() << " " << ec.FieldSize() << "\n"; - std::cout << "Curve: "; - std::cout << "curve field max element bit length: " << ec.GetField().MaxElementBitLength() << "\n"; - std::cout << "curve field modulus: " << ec.GetField().GetModulus() << "\n"; - std::cout << "curve A: " << ec.GetA() << ", curve B: " << ec.GetB(); - - const ECP::Field& f = ec.GetField(); - std::cout << "curve field modulus: " << f.GetModulus() << "\n"; - std::cout << "curve field identity: " << f.Identity() << "\n"; - - std::string cfs; - StringSink* cfss = new StringSink(cfs); - HexEncoder cfhe(cfss); - f.DEREncode(cfhe); - std::cout << "curve field derencoding: " << cfs << "\n"; - - const CryptoMaterial& cm = self->k->GetMaterial(); - Integer i; - cm.GetValue("SubgroupOrder", i); - std::cout << "\n"; - std::cout << "SubgroupOrder: "; - std::cout << i; - std::cout << "\n"; - ECP::Element e; - cm.GetValue("SubgroupGenerator", e); - std::cout << "SubgroupGenerator: "; - std::cout << e.x << ", " << e.y; - std::cout << "\n"; - - std::cout << "private key: "; - - const PrivateKey& privkey = self->k->GetPrivateKey(); - - std::cout << privkey.GetValueNames() << "\n"; - - Integer privi; - privkey.GetValue("PrivateExponent", privi); - std::cout << privi << "\n"; - std::cout << "numbits: " << privi.BitCount() << "\n"; - std::cout << "numbytes: " << privi.ByteCount() << "\n"; - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(SigningKey__dump__doc__, -"Print to stdout some descriptions of the math pieces."); - -static PyObject * -SigningKey_sign(SigningKey *self, PyObject *msgobj) { - const char *msg; - Py_ssize_t msgsize; - PyString_AsStringAndSize(msgobj, const_cast(&msg), reinterpret_cast(&msgsize)); - assert (msgsize >= 0); - - Py_ssize_t sigsize; - sigsize = self->k->SignatureLength(); - - PyStringObject* result = reinterpret_cast(PyString_FromStringAndSize(NULL, sigsize)); - if (!result) - return NULL; - assert (sigsize >= 0); - - AutoSeededRandomPool randpool(false); //XXX - - Py_ssize_t siglengthwritten; - try { - siglengthwritten = self->k->SignMessage( - randpool, - reinterpret_cast(msg), - msgsize, - reinterpret_cast(PyString_AS_STRING(result))); - } catch (InvalidDataFormat le) { - Py_DECREF(result); - return PyErr_Format(ecdsa_error, "Signing key was corrupted. Crypto++ gave this exception: %s", le.what()); - } - - if (siglengthwritten < sigsize) - fprintf(stderr, "%s: %d: %s: %s", __FILE__, __LINE__, "SigningKey_sign", "INTERNAL ERROR: signature was shorter than expected."); - else if (siglengthwritten > sigsize) { - fprintf(stderr, "%s: %d: %s: %s", __FILE__, __LINE__, "SigningKey_sign", "INTERNAL ERROR: signature was longer than expected, so memory was invalidly overwritten."); - abort(); - } - assert (siglengthwritten >= 0); - - return reinterpret_cast(result); -} - -PyDoc_STRVAR(SigningKey_sign__doc__, - "Return a signature on the argument."); //XXX If randseed is not None then it is required to be an "); // XXX randseed! - -static PyObject * -SigningKey_get_verifying_key(SigningKey *self, PyObject *dummy) { - VerifyingKey *verifier = PyObject_New(VerifyingKey, &VerifyingKey_type); - if (!verifier) - return NULL; - - verifier->k = new ECDSA::Verifier(*(self->k)); - if (!verifier->k) - return PyErr_NoMemory(); - verifier->k->AccessKey().AccessGroupParameters().SetPointCompression(true); - - return reinterpret_cast(verifier); -} - -PyDoc_STRVAR(SigningKey_get_verifying_key__doc__, -"Return the corresponding verifying key."); - -static PyMethodDef SigningKey_methods[] = { - {"sign", reinterpret_cast(SigningKey_sign), METH_O, SigningKey_sign__doc__}, - {"_dump", reinterpret_cast(SigningKey__dump), METH_NOARGS, SigningKey__dump__doc__}, - {"get_verifying_key", reinterpret_cast(SigningKey_get_verifying_key), METH_NOARGS, SigningKey_get_verifying_key__doc__}, - {NULL}, -}; - -static PyTypeObject SigningKey_type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "ecdsa.SigningKey", /*tp_name*/ - sizeof(SigningKey), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)SigningKey_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - SigningKey__init____doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - SigningKey_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - SigningKey___init__, /* tp_init */ -}; - -void -init_ecdsa(PyObject*const module) { - VerifyingKey_type.tp_new = PyType_GenericNew; - if (PyType_Ready(&VerifyingKey_type) < 0) - return; - Py_INCREF(&VerifyingKey_type); - PyModule_AddObject(module, "ecdsa_VerifyingKey", (PyObject *)&VerifyingKey_type); - - SigningKey_type.tp_new = PyType_GenericNew; - if (PyType_Ready(&SigningKey_type) < 0) - return; - Py_INCREF(&SigningKey_type); - PyModule_AddObject(module, "ecdsa_SigningKey", (PyObject *)&SigningKey_type); - - ecdsa_error = PyErr_NewException(const_cast("_ecdsa.Error"), NULL, NULL); - PyModule_AddObject(module, "ecdsa_Error", ecdsa_error); - - PyModule_AddStringConstant(module, "ecdsa___doc__", const_cast(ecdsa___doc__)); -} diff --git a/pycryptopp/publickey/ecdsamodule.hpp b/pycryptopp/publickey/ecdsamodule.hpp deleted file mode 100644 index ad3c4fc..0000000 --- a/pycryptopp/publickey/ecdsamodule.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __INCL_ECDSAMODULE_HPP -#define __INCL_ECDSAMODULE_HPP - -void -init_ecdsa(PyObject* module); - -#endif /* #ifndef __INCL_ECDSAMODULE_HPP */ diff --git a/pycryptopp/publickey/rsa.py b/pycryptopp/publickey/rsa.py deleted file mode 100644 index bb498a5..0000000 --- a/pycryptopp/publickey/rsa.py +++ /dev/null @@ -1,5 +0,0 @@ -from pycryptopp import _import_my_names - -_import_my_names(globals(), "rsa_") - -del _import_my_names diff --git a/pycryptopp/publickey/rsamodule.cpp b/pycryptopp/publickey/rsamodule.cpp deleted file mode 100644 index d6b7d9f..0000000 --- a/pycryptopp/publickey/rsamodule.cpp +++ /dev/null @@ -1,383 +0,0 @@ -/** - * rsamodule.cpp -- Python wrappers around Crypto++'s RSA-PSS-SHA256 - * more precisely: - * PSS-MGF1 - * with RSA as the public key algorithm and SHA-256 as the hash function - */ - -#define PY_SSIZE_T_CLEAN -#include -#if (PY_VERSION_HEX < 0x02050000) -typedef int Py_ssize_t; -#endif - -#include "rsamodule.hpp" - -/* from Crypto++ */ -#ifdef DISABLE_EMBEDDED_CRYPTOPP -#include -#include -#include -#include -#else -#include -#include -#include -#include -#endif - -USING_NAMESPACE(CryptoPP) - -static const char*const rsa___doc__ = "_rsa -- RSA-PSS-SHA256 signatures\n\ -\n\ -To create a new RSA signing key from the operating system's random number generator, call generate().\n\ -To deserialize an RSA signing key from a string, call create_signing_key_from_string().\n\ -\n\ -To get an RSA verifying key from an RSA signing key, call get_verifying_key() on the signing key.\n\ -To deserialize an RSA verifying key from a string, call create_verifying_key_from_string()."; - -static PyObject *rsa_error; - -typedef struct { - PyObject_HEAD - - /* internal */ - RSASS::Verifier *k; -} VerifyingKey; - -PyDoc_STRVAR(VerifyingKey__doc__, -"an RSA verifying key"); - -static void -VerifyingKey_dealloc(VerifyingKey* self) { - if (self->k) - delete self->k; - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject * -VerifyingKey_verify(VerifyingKey *self, PyObject *args, PyObject *kwdict) { - static const char *kwlist[] = { "msg", "signature", NULL }; - const char *msg; - Py_ssize_t msgsize; - const char *signature; - Py_ssize_t signaturesize = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#t#:verify", const_cast(kwlist), &msg, &msgsize, &signature, &signaturesize)) - return NULL; - assert (msgsize >= 0); - assert (signaturesize >= 0); - - Py_ssize_t sigsize = self->k->SignatureLength(); - if (sigsize != signaturesize) - return PyErr_Format(rsa_error, "Precondition violation: signatures are required to be of size %zu, but it was %zu", sigsize, signaturesize); - assert (sigsize >= 0); - - assert (signaturesize == sigsize); - - if (self->k->VerifyMessage(reinterpret_cast(msg), msgsize, reinterpret_cast(signature), signaturesize)) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - -PyDoc_STRVAR(VerifyingKey_verify__doc__, -"Return whether the signature is a valid signature on the msg."); - -static PyObject * -VerifyingKey_serialize(VerifyingKey *self, PyObject *dummy) { - std::string outstr; - StringSink ss(outstr); - self->k->DEREncode(ss); - PyStringObject* result = reinterpret_cast(PyString_FromStringAndSize(outstr.c_str(), outstr.size())); - if (!result) - return NULL; - - return reinterpret_cast(result); -} - -PyDoc_STRVAR(VerifyingKey_serialize__doc__, -"Return a string containing the key material. The string can be passed to \n\ -create_verifying_key_from_string() to instantiate a new copy of this key."); - -static PyMethodDef VerifyingKey_methods[] = { - {"verify", reinterpret_cast(VerifyingKey_verify), METH_KEYWORDS, VerifyingKey_verify__doc__}, - {"serialize", reinterpret_cast(VerifyingKey_serialize), METH_NOARGS, VerifyingKey_serialize__doc__}, - {NULL}, -}; - -static PyTypeObject VerifyingKey_type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "_rsa.VerifyingKey", /*tp_name*/ - sizeof(VerifyingKey), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - reinterpret_cast(VerifyingKey_dealloc), /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - VerifyingKey__doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - VerifyingKey_methods, /* tp_methods */ -}; - -/** This function is only for internal use by rsamodule.cpp. */ -static VerifyingKey* -VerifyingKey_construct() { - VerifyingKey *self = reinterpret_cast(VerifyingKey_type.tp_alloc(&VerifyingKey_type, 0)); - if (!self) - return NULL; - self->k = NULL; - return self; -} - -PyDoc_STRVAR(SigningKey__doc__, -"an RSA signing key"); - -typedef struct { - PyObject_HEAD - - /* internal */ - RSASS::Signer *k; -} SigningKey; - -static void -SigningKey_dealloc(SigningKey* self) { - if (self->k) - delete self->k; - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject * -SigningKey_sign(SigningKey *self, PyObject *msgobj) { - const char *msg; - Py_ssize_t msgsize; - PyString_AsStringAndSize(msgobj, const_cast(&msg), reinterpret_cast(&msgsize)); - assert (msgsize >= 0); - - Py_ssize_t sigsize = self->k->SignatureLength(); - PyStringObject* result = reinterpret_cast(PyString_FromStringAndSize(NULL, sigsize)); - if (!result) - return NULL; - assert (sigsize >= 0); - - AutoSeededRandomPool randpool(false); - Py_ssize_t siglengthwritten = self->k->SignMessage( - randpool, - reinterpret_cast(msg), - msgsize, - reinterpret_cast(PyString_AS_STRING(result))); - if (siglengthwritten < sigsize) - fprintf(stderr, "%s: %d: %s: %s", __FILE__, __LINE__, "SigningKey_sign", "INTERNAL ERROR: signature was shorter than expected."); - else if (siglengthwritten > sigsize) { - fprintf(stderr, "%s: %d: %s: %s", __FILE__, __LINE__, "SigningKey_sign", "INTERNAL ERROR: signature was longer than expected, so invalid memory was overwritten."); - abort(); - } - assert (siglengthwritten >= 0); - - return reinterpret_cast(result); -} - -PyDoc_STRVAR(SigningKey_sign__doc__, -"Return a signature on the argument."); - -static PyObject * -SigningKey_get_verifying_key(SigningKey *self, PyObject *dummy) { - VerifyingKey *verifier = reinterpret_cast(VerifyingKey_construct()); - if (!verifier) - return NULL; - - verifier->k = new RSASS::Verifier(*(self->k)); - if (!verifier->k) - return PyErr_NoMemory(); - return reinterpret_cast(verifier); -} - -PyDoc_STRVAR(SigningKey_get_verifying_key__doc__, -"Return the corresponding verifying key."); - -static PyObject * -SigningKey_serialize(SigningKey *self, PyObject *dummy) { - std::string outstr; - StringSink ss(outstr); - self->k->DEREncode(ss); - PyStringObject* result = reinterpret_cast(PyString_FromStringAndSize(outstr.c_str(), outstr.size())); - if (!result) - return NULL; - - return reinterpret_cast(result); -} - -PyDoc_STRVAR(SigningKey_serialize__doc__, -"Return a string containing the key material. The string can be passed to \n\ -create_signing_key_from_string() to instantiate a new copy of this key."); - -static PyMethodDef SigningKey_methods[] = { - {"sign", reinterpret_cast(SigningKey_sign), METH_O, SigningKey_sign__doc__}, - {"get_verifying_key", reinterpret_cast(SigningKey_get_verifying_key), METH_NOARGS, SigningKey_get_verifying_key__doc__}, - {"serialize", reinterpret_cast(SigningKey_serialize), METH_NOARGS, SigningKey_serialize__doc__}, - {NULL}, -}; - -static PyTypeObject SigningKey_type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "_rsa.SigningKey", /*tp_name*/ - sizeof(SigningKey), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)SigningKey_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - SigningKey__doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - SigningKey_methods /* tp_methods */ -}; - -/** This function is only for internal use by rsamodule.cpp. */ -static SigningKey* -SigningKey_construct() { - SigningKey *self = reinterpret_cast(SigningKey_type.tp_alloc(&SigningKey_type, 0)); - if (!self) - return NULL; - self->k = NULL; - return self; -} - -// static const int MIN_KEY_SIZE_BITS=3675; /* according to Lenstra 2001 "Unbelievable security: Matching AES security using public key systems", you should use RSA keys of length 3675 bits if you want it to be as hard to factor your RSA key as to brute-force your AES-128 key in the year 2030. */ -static const int MIN_KEY_SIZE_BITS=522; /* minimum that can do PSS-SHA256 -- totally insecure and allowed only for faster unit tests */ - -PyObject * -rsa_generate(PyObject *dummy, PyObject *args, PyObject *kwdict) { - static const char *kwlist[] = { - "sizeinbits", - NULL - }; - int sizeinbits; - - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "i:generate", const_cast(kwlist), &sizeinbits)) - return NULL; - - if (sizeinbits < MIN_KEY_SIZE_BITS) - return PyErr_Format(rsa_error, "Precondition violation: size in bits is required to be >= %d, but it was %d", MIN_KEY_SIZE_BITS, sizeinbits); - - AutoSeededRandomPool osrng(false); - SigningKey *signer = SigningKey_construct(); - if (!signer) - return NULL; - signer->k = new RSASS::Signer(osrng, sizeinbits); - if (!signer->k) - return PyErr_NoMemory(); - return reinterpret_cast(signer); -} - -const char*const rsa_generate__doc__ = "Create a signing key using the operating system's random number generator.\n\ -\n\ -@param sizeinbits size of the key in bits\n\ -\n\ -@precondition sizeinbits >= 522"; - -PyObject * -rsa_create_verifying_key_from_string(PyObject *dummy, PyObject *args, PyObject *kwdict) { - static const char *kwlist[] = { - "serializedverifyingkey", - NULL - }; - const char *serializedverifyingkey; - Py_ssize_t serializedverifyingkeysize = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#:create_verifying_key_from_string", const_cast(kwlist), &serializedverifyingkey, &serializedverifyingkeysize)) - return NULL; - assert (serializedverifyingkeysize >= 0); - - VerifyingKey *verifier = reinterpret_cast(VerifyingKey_construct()); - if (!verifier) - return NULL; - StringSource ss(reinterpret_cast(serializedverifyingkey), serializedverifyingkeysize, true); - - verifier->k = new RSASS::Verifier(ss); - if (!verifier->k) - return PyErr_NoMemory(); - return reinterpret_cast(verifier); -} - -const char*const rsa_create_verifying_key_from_string__doc__ = "Create a verifying key from its serialized state."; - -PyObject * -rsa_create_signing_key_from_string(PyObject *dummy, PyObject *args, PyObject *kwdict) { - static const char *kwlist[] = { - "serializedsigningkey", - NULL - }; - const char *serializedsigningkey; - Py_ssize_t serializedsigningkeysize = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#:create_signing_key_from_string", const_cast(kwlist), &serializedsigningkey, &serializedsigningkeysize)) - return NULL; - assert (serializedsigningkeysize >= 0); - - SigningKey *verifier = SigningKey_construct(); - if (!verifier) - return NULL; - StringSource ss(reinterpret_cast(serializedsigningkey), serializedsigningkeysize, true); - - verifier->k = new RSASS::Signer(ss); - if (!verifier->k) - return PyErr_NoMemory(); - return reinterpret_cast(verifier); -} - -const char*const rsa_create_signing_key_from_string__doc__ = "Create a signing key from its serialized state."; - -void -init_rsa(PyObject*const module) { - VerifyingKey_type.tp_new = PyType_GenericNew; - if (PyType_Ready(&VerifyingKey_type) < 0) - return; - Py_INCREF(&VerifyingKey_type); - PyModule_AddObject(module, "rsa_VerifyingKey", (PyObject *)&VerifyingKey_type); - - SigningKey_type.tp_new = PyType_GenericNew; - if (PyType_Ready(&SigningKey_type) < 0) - return; - Py_INCREF(&SigningKey_type); - PyModule_AddObject(module, "rsa_SigningKey", (PyObject *)&SigningKey_type); - - rsa_error = PyErr_NewException(const_cast("_rsa.Error"), NULL, NULL); - PyModule_AddObject(module, "rsa_Error", rsa_error); - - PyModule_AddStringConstant(module, "rsa___doc__", const_cast(rsa___doc__)); -} diff --git a/pycryptopp/publickey/rsamodule.hpp b/pycryptopp/publickey/rsamodule.hpp deleted file mode 100644 index 30849a2..0000000 --- a/pycryptopp/publickey/rsamodule.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __INCL_RSAMODULE_HPP -#define __INCL_RSAMODULE_HPP - -void -init_rsa(PyObject* module); - -extern PyMethodDef rsa_functions[]; - -extern PyObject * -rsa_generate(PyObject *dummy, PyObject *args, PyObject *kwdict); -extern const char*const rsa_generate__doc__; - -extern PyObject * -rsa_create_verifying_key_from_string(PyObject *dummy, PyObject *args, PyObject *kwdict); -extern const char*const rsa_create_verifying_key_from_string__doc__; - -extern PyObject * -rsa_create_signing_key_from_string(PyObject *dummy, PyObject *args, PyObject *kwdict); -extern const char*const rsa_create_signing_key_from_string__doc__; - -#endif /* #ifndef __INCL_RSAMODULE_HPP */ diff --git a/pycryptopp/test/__init__.py b/pycryptopp/test/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/pycryptopp/test/test_aes.py b/pycryptopp/test/test_aes.py deleted file mode 100644 index d4e2c44..0000000 --- a/pycryptopp/test/test_aes.py +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env python - -import random, re - -import unittest - -from binascii import a2b_hex, b2a_hex - -global VERBOSE -VERBOSE=False - -from pycryptopp.cipher import aes - -from pkg_resources import resource_string, resource_listdir - -from base64 import b32encode -def ab(x): # debuggery - if len(x) >= 3: - return "%s:%s" % (len(x), b32encode(x[-3:]),) - elif len(x) == 2: - return "%s:%s" % (len(x), b32encode(x[-2:]),) - elif len(x) == 1: - return "%s:%s" % (len(x), b32encode(x[-1:]),) - elif len(x) == 0: - return "%s:%s" % (len(x), "--empty--",) - -def randstr(n): - return ''.join(map(chr, map(random.randrange, [0]*n, [256]*n))) - -class AES256(unittest.TestCase): - enc0 = "dc95c078a2408989ad48a21492842087530f8afbc74536b9a963b4f1c4cb738b" - - def test_encrypt_zeroes(self): - cryptor = aes.AES(key="\x00"*32) - ct = cryptor.process("\x00"*32) - self.failUnlessEqual(self.enc0, b2a_hex(ct)) - - def test_init_type_check(self): - self.failUnlessRaises(TypeError, aes.AES, None) - self.failUnlessRaises(aes.Error, aes.AES, "a"*1) # too short - self.failUnlessRaises(aes.Error, aes.AES, "a"*17) # not one of the valid key sizes for AES (16, 24, 32) - - def test_encrypt_zeroes_in_two_parts(self): - cryptor = aes.AES(key="\x00"*32) - ct1 = cryptor.process("\x00"*15) - ct2 = cryptor.process("\x00"*17) - self.failUnlessEqual(self.enc0, b2a_hex(ct1+ct2)) - -class AES128(unittest.TestCase): - enc0 = "66e94bd4ef8a2c3b884cfa59ca342b2e" - - def test_encrypt_zeroes(self): - cryptor = aes.AES(key="\x00"*16) - ct = cryptor.process("\x00"*16) - self.failUnlessEqual(self.enc0, b2a_hex(ct)) - - def test_init_type_check(self): - self.failUnlessRaises(TypeError, aes.AES, None) - self.failUnlessRaises(aes.Error, aes.AES, "a") # too short - - def test_encrypt_zeroes_in_two_parts(self): - cryptor = aes.AES(key="\x00"*16) - ct1 = cryptor.process("\x00"*8) - ct2 = cryptor.process("\x00"*8) - self.failUnlessEqual(self.enc0, b2a_hex(ct1+ct2)) - -def fake_ecb_using_ctr(k, p): - return aes.AES(key=k, iv=p).process('\x00'*16) - -NIST_KAT_VECTS_RE=re.compile("\nCOUNT = ([0-9]+)\nKEY = ([0-9a-f]+)\nPLAINTEXT = ([0-9a-f]+)\nCIPHERTEXT = ([0-9a-f]+)") - -class AES_from_NIST_KAT(unittest.TestCase): - def test_NIST_KAT(self): - for vectname in resource_listdir('pycryptopp', 'testvectors/KAT_AES'): - self._test_KAT_file(resource_string('pycryptopp', '/'.join(['testvectors/KAT_AES', vectname]))) - - def _test_KAT_file(self, vects_str): - for mo in NIST_KAT_VECTS_RE.finditer(vects_str): - key = a2b_hex(mo.group(2)) - plaintext = a2b_hex(mo.group(3)) - ciphertext = a2b_hex(mo.group(4)) - - computedciphertext = fake_ecb_using_ctr(key, plaintext) - self.failUnlessEqual(computedciphertext, ciphertext, "computedciphertext: %s, ciphertext: %s, key: %s, plaintext: %s" % (b2a_hex(computedciphertext), b2a_hex(ciphertext), b2a_hex(key), b2a_hex(plaintext))) - -class AES_from_Niels_Ferguson(unittest.TestCase): - # http://blogs.msdn.com/si_team/archive/2006/05/19/aes-test-vectors.aspx - def _test_from_Niels_AES(self, keysize, result): - E = fake_ecb_using_ctr - b = 16 - k = keysize - S = '\x00' * (k+b) - for i in range(1000): - K = S[-k:] - P = S[-k-b:-k] - S += E(K, E(K, P)) - - self.failUnlessEqual(S[-b:], a2b_hex(result)) - - def test_from_Niels_AES128(self): - return self._test_from_Niels_AES(16, 'bd883f01035e58f42f9d812f2dacbcd8') - - def test_from_Niels_AES256(self): - return self._test_from_Niels_AES(32, 'c84b0f3a2c76dd9871900b07f09bdd3e') - -if __name__ == "__main__": - unittest.main() diff --git a/pycryptopp/test/test_ecdsa.py b/pycryptopp/test/test_ecdsa.py deleted file mode 100644 index d70a000..0000000 --- a/pycryptopp/test/test_ecdsa.py +++ /dev/null @@ -1,263 +0,0 @@ -#!/usr/bin/env python - -import random -import base64 - -import os -SEED = os.environ.get('REPEATABLE_RANDOMNESS_SEED', None) - -if SEED is None: - # Generate a seed which is fairly short (to ease cut-and-paste, writing it - # down, etc.). Note that Python's random module's seed() function is going - # to take the hash() of this seed, which is a 32-bit value (currently) so - # there is no point in making this seed larger than 32 bits. Make it 30 - # bits, which conveniently fits into six base-32 chars. Include a separator - # because chunking facilitates memory (including working and short-term - # memory) in humans. - chars = "ybndrfg8ejkmcpqxot1uwisza345h769" # Zooko's choice, rationale in "DESIGN" doc in z-base-32 project - SEED = ''.join([random.choice(chars) for x in range(3)] + ['-'] + [random.choice(chars) for x in range(3)]) - -import logging -logging.info("REPEATABLE_RANDOMNESS_SEED: %s\n" % SEED) -logging.info("In order to reproduce this run of the code, set the environment variable \"REPEATABLE_RANDOMNESS_SEED\" to %s before executing.\n" % SEED) -random.seed(SEED) - -def seed_which_refuses(a): - logging.warn("I refuse to reseed to %s -- I already seeded with %s.\n" % (a, SEED,)) - return -random.seed = seed_which_refuses - -from random import randrange - -import unittest - -from pycryptopp.publickey import ecdsa - -def randstr(n, rr=randrange): - return ''.join([chr(rr(0, 256)) for x in xrange(n)]) - -from base64 import b32encode -def ab(x): # debuggery - if len(x) >= 3: - return "%s:%s" % (len(x), b32encode(x[-3:]),) - elif len(x) == 2: - return "%s:%s" % (len(x), b32encode(x[-2:]),) - elif len(x) == 1: - return "%s:%s" % (len(x), b32encode(x[-1:]),) - elif len(x) == 0: - return "%s:%s" % (len(x), "--empty--",) - -def div_ceil(n, d): - """ - The smallest integer k such that k*d >= n. - """ - return (n/d) + (n%d != 0) - -KEYBITS=192 - -# The number of bytes required for a seed to have the same security level as a -# key in this elliptic curve: 2 bits of public key per bit of security. -SEEDBITS=div_ceil(192, 2) -SEEDBYTES=div_ceil(SEEDBITS, 8) - -# The number of bytes required to encode a public key in this elliptic curve. -PUBKEYBYTES=div_ceil(KEYBITS, 8)+1 # 1 byte for the sign of the y component - -# The number of bytes requires to encode a signature in this elliptic curve. -SIGBITS=KEYBITS*2 -SIGBYTES=div_ceil(SIGBITS, 8) - -class Signer(unittest.TestCase): - def test_construct(self): - seed = randstr(SEEDBYTES) - ecdsa.SigningKey(seed) - - def test_sign(self): - seed = randstr(SEEDBYTES) - signer = ecdsa.SigningKey(seed) - sig = signer.sign("message") - self.failUnlessEqual(len(sig), SIGBYTES) - - def test_sign_and_verify(self): - seed = randstr(SEEDBYTES) - signer = ecdsa.SigningKey(seed) - sig = signer.sign("message") - v = signer.get_verifying_key() - self.failUnless(v.verify("message", sig)) - - def test_sign_and_verify_emptymsg(self): - seed = randstr(SEEDBYTES) - signer = ecdsa.SigningKey(seed) - sig = signer.sign("") - v = signer.get_verifying_key() - self.failUnless(v.verify("", sig)) - - def test_construct_from_same_seed_is_reproducible(self): - seed = randstr(SEEDBYTES) - signer1 = ecdsa.SigningKey(seed) - signer2 = ecdsa.SigningKey(seed) - self.failUnlessEqual(signer1.get_verifying_key().serialize(), signer2.get_verifying_key().serialize()) - - # ... and using different seeds constructs a different private key. - seed3 = randstr(SEEDBYTES) - assert seed3 != seed, "Internal error in Python random module's PRNG (or in pycryptopp's hacks to it to facilitate testing) -- got two identical strings from randstr(%s)" % SEEDBYTES - signer3 = ecdsa.SigningKey(seed3) - self.failIfEqual(signer1.get_verifying_key().serialize(), signer3.get_verifying_key().serialize()) - - # Also try the all-zeroes string just because bugs sometimes are - # data-dependent on zero or cause bogus zeroes. - seed4 = '\x00'*SEEDBYTES - assert seed4 != seed, "Internal error in Python random module's PRNG (or in pycryptopp's hacks to it to facilitate testing) -- got the all-zeroes string from randstr(%s)" % SEEDBYTES - signer4 = ecdsa.SigningKey(seed4) - self.failIfEqual(signer4.get_verifying_key().serialize(), signer1.get_verifying_key().serialize()) - - signer5 = ecdsa.SigningKey(seed4) - self.failUnlessEqual(signer5.get_verifying_key().serialize(), signer4.get_verifying_key().serialize()) - - def test_construct_short_seed(self): - try: - ecdsa.SigningKey("\x00\x00\x00") - except ecdsa.Error, le: - self.failUnless("seed is required to be of length " in str(le), le) - else: - self.fail("Should have raised error from seed being too short.") - - def test_construct_bad_arg_type(self): - try: - ecdsa.SigningKey(1) - except TypeError, le: - self.failUnless("must be string" in str(le), le) - else: - self.fail("Should have raised error from seed being of the wrong type.") - -class Verifier(unittest.TestCase): - def test_from_signer_and_serialize_and_deserialize(self): - seed = randstr(SEEDBYTES) - signer = ecdsa.SigningKey(seed) - - verifier = signer.get_verifying_key() - s1 = verifier.serialize() - self.failUnlessEqual(len(s1), PUBKEYBYTES) - ecdsa.VerifyingKey(s1) - s2 = verifier.serialize() - self.failUnlessEqual(s1, s2) - -def flip_one_bit(s): - assert s - i = randrange(0, len(s)) - result = s[:i] + chr(ord(s[i])^(0x01<= 3: - return "%s:%s" % (len(x), b32encode(x[-3:]),) - elif len(x) == 2: - return "%s:%s" % (len(x), b32encode(x[-2:]),) - elif len(x) == 1: - return "%s:%s" % (len(x), b32encode(x[-1:]),) - elif len(x) == 0: - return "%s:%s" % (len(x), "--empty--",) - -def randstr(n): - return ''.join(map(chr, map(random.randrange, [0]*n, [256]*n))) - -KEYSIZE=522 # 522 bits is far too few for actual security -- it is used only for faster unit tests - -class Signer(unittest.TestCase): - def test_generate_bad_size(self): - try: - rsa.generate(KEYSIZE-1) - except rsa.Error, le: - self.failUnless("size in bits is required to be >=" in str(le), le) - else: - self.fail("Should have raised error from size being too small.") - try: - rsa.generate(sizeinbits=KEYSIZE-1) - except rsa.Error, le: - self.failUnless("size in bits is required to be >=" in str(le), le) - else: - self.fail("Should have raised error from size being too small.") - - def test_generate(self): - rsa.generate(KEYSIZE) - # Hooray! It didn't raise an exception! We win! - rsa.generate(sizeinbits=KEYSIZE) - # Hooray! It didn't raise an exception! We win! - - def test_sign(self): - signer = rsa.generate(KEYSIZE) - result = signer.sign("abc") - self.failUnlessEqual(len(result), ((KEYSIZE+7)/8)) - # TODO: test against RSAInc. test vectors. - -class SignAndVerify(unittest.TestCase): - def _help_test_sign_and_check(self, signer, verifier, msg): - sig = signer.sign(msg) - self.failUnlessEqual(len(sig), ((KEYSIZE+7)/8)) - self.failUnless(verifier.verify(msg, sig)) - - def test_sign_and_check_a(self): - signer = rsa.generate(KEYSIZE) - verifier = signer.get_verifying_key() - return self._help_test_sign_and_check(signer, verifier, "a") - - def _help_test_sign_and_check_random(self, signer, verifier): - for i in range(3): - l = random.randrange(0, 2**10) - msg = randstr(l) - self._help_test_sign_and_check(signer, verifier, msg) - - def test_sign_and_check_random(self): - signer = rsa.generate(KEYSIZE) - verifier = signer.get_verifying_key() - return self._help_test_sign_and_check_random(signer, verifier) - - def _help_test_sign_and_failcheck(self, signer, verifier, msg): - sig = signer.sign("a") - sig = sig[:-1] + chr(ord(sig[-1])^0x01) - self.failUnless(not verifier.verify(msg, sig)) - - def test_sign_and_failcheck_a(self): - signer = rsa.generate(KEYSIZE) - verifier = signer.get_verifying_key() - return self._help_test_sign_and_failcheck(signer, verifier, "a") - - def _help_test_sign_and_failcheck_random(self, signer, verifier): - for i in range(3): - l = random.randrange(0, 2**10) - msg = randstr(l) - self._help_test_sign_and_failcheck(signer, verifier, msg) - - def test_sign_and_failcheck_random(self): - signer = rsa.generate(KEYSIZE) - verifier = signer.get_verifying_key() - return self._help_test_sign_and_failcheck_random(signer, verifier) - - def test_serialize_and_deserialize_verifying_key_and_test(self): - signer = rsa.generate(KEYSIZE) - verifier = signer.get_verifying_key() - serstr = verifier.serialize() - verifier = None - newverifier = rsa.create_verifying_key_from_string(serstr) - self._help_test_sign_and_check(signer, newverifier, "a") - self._help_test_sign_and_check_random(signer, newverifier) - self._help_test_sign_and_failcheck(signer, newverifier, "a") - self._help_test_sign_and_failcheck_random(signer, newverifier) - - def test_serialize_and_deserialize_signing_key_and_test(self): - signer = rsa.generate(KEYSIZE) - verifier = signer.get_verifying_key() - serstr = signer.serialize() - signer = None - newsigner = rsa.create_signing_key_from_string(serstr) - self._help_test_sign_and_check(newsigner, verifier, "a") - self._help_test_sign_and_check_random(newsigner, verifier) - self._help_test_sign_and_failcheck(newsigner, verifier, "a") - self._help_test_sign_and_failcheck_random(newsigner, verifier) - - -if __name__ == "__main__": - unittest.main() diff --git a/pycryptopp/test/test_sha256.py b/pycryptopp/test/test_sha256.py deleted file mode 100644 index 5e982dc..0000000 --- a/pycryptopp/test/test_sha256.py +++ /dev/null @@ -1,181 +0,0 @@ -#!/usr/bin/env python - -import random, re - -import unittest - -from binascii import b2a_hex, a2b_hex - -global VERBOSE -VERBOSE=False - -from pycryptopp.hash import sha256 - -from pkg_resources import resource_string - -def resource_string_lines(pkgname, resname): - return split_on_newlines(resource_string(pkgname, resname)) - -from base64 import b32encode -def ab(x): # debuggery - if len(x) >= 3: - return "%s:%s" % (len(x), b32encode(x[-3:]),) - elif len(x) == 2: - return "%s:%s" % (len(x), b32encode(x[-2:]),) - elif len(x) == 1: - return "%s:%s" % (len(x), b32encode(x[-1:]),) - elif len(x) == 0: - return "%s:%s" % (len(x), "--empty--",) - -def randstr(n): - return ''.join(map(chr, map(random.randrange, [0]*n, [256]*n))) - -h0 = a2b_hex("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") -h_bd = a2b_hex("68325720aabd7c82f30f554b313d0570c95accbb7dc4b5aae11204c08ffe732b") -h_5fd4 = a2b_hex("7c4fbf484498d21b487b9d61de8914b2eadaf2698712936d47c3ada2558f6788") - -class SHA256(unittest.TestCase): - def test_digest(self): - empty_digest = sha256.SHA256().digest() - self.failUnless(isinstance(empty_digest, str)) - self.failUnlessEqual(len(empty_digest), 32) - self.failUnlessEqual(empty_digest, h0) - - def test_hexdigest(self): - empty_hexdigest = sha256.SHA256().hexdigest() - self.failUnlessEqual(a2b_hex(empty_hexdigest), h0) - test_hexdigest.todo = "Not yet implemented: SHA256.hexdigest()." - - def test_onebyte_1(self): - d = sha256.SHA256("\xbd").digest() - self.failUnlessEqual(d, h_bd) - - def test_onebyte_2(self): - s = sha256.SHA256() - s.update("\xbd") - d = s.digest() - self.failUnlessEqual(d, h_bd) - - def test_update(self): - s = sha256.SHA256("\x5f") - s.update("\xd4") - d = s.digest() - self.failUnlessEqual(d, h_5fd4) - - def test_constructor_type_check(self): - self.failUnlessRaises(TypeError, sha256.SHA256, None) - - def test_update_type_check(self): - h = sha256.SHA256() - self.failUnlessRaises(TypeError, h.update, None) - - def test_digest_twice(self): - h = sha256.SHA256() - d1 = h.digest() - self.failUnless(isinstance(d1, str)) - d2 = h.digest() - self.failUnlessEqual(d1, d2) - - def test_digest_then_update_fail(self): - h = sha256.SHA256() - h.digest() - try: - h.update("oops") - except sha256.Error, le: - self.failUnless("digest() has been called" in str(le), le) - - def test_chunksize(self): - # hashes can be computed on arbitrarily-sized chunks - problems = False - for length in range(2, 140): - s = "a"*length - expected = sha256.SHA256(s).hexdigest() - for a in range(0, length): - h = sha256.SHA256() - h.update(s[:a]) - h.update(s[a:]) - got = h.hexdigest() - if got != expected: - problems = True - print len(s[:a]), len(s[a:]), len(s), got, expected - self.failIf(problems) - - def test_recursive_different_chunksizes(self): - """ - Test that updating a hasher with various sized inputs yields - the expected answer. This is somewhat redundant with - test_chunksize(), but that's okay. This one exercises some - slightly different situations (such as finalizing a hash after - different length inputs.) This one is recursive so that there - is a single fixed result that we expect. - """ - hx = sha256.SHA256() - s = ''.join([ chr(c) for c in range(65) ]) - for i in range(0, 65): - hy = sha256.SHA256(s[:i]).digest() - hx.update(hy) - for i in range(0, 65): - hx.update(chr(0xFE)) - hx.update(s[:64]) - self.failUnlessEqual(hx.hexdigest().lower(), '5191c7841dd4e16aa454d40af924585dffc67157ffdbfd0236acddd07901629d') - - -VECTS_RE=re.compile("\nLen = ([0-9]+)\nMsg = ([0-9a-f]+)\nMD = ([0-9a-f]+)") - -# split_on_newlines() copied from pyutil.strutil -def split_on_newlines(s): - """ - Splits s on all of the three newline sequences: "\r\n", "\r", or "\n". - """ - res = [] - for x in s.split('\r\n'): - for y in x.split('\r'): - res.extend(y.split('\n')) - return res - -class SHSVectors(unittest.TestCase): - """ - All of the SHA-256 test vectors from the NIST SHS, in the files distributed - by NIST. (NIST distributes them in a .zip, but we expect them to be - unpacked and in a subdirectory named 'testvectors'). - """ - def test_short(self): - return self._test_vect(resource_string('pycryptopp', 'testvectors/SHA256ShortMsg.txt')) - - def test_long(self): - return self._test_vect(resource_string('pycryptopp', 'testvectors/SHA256LongMsg.txt')) - - def _test_vect(self, vects_str): - for mo in VECTS_RE.finditer(vects_str): - msglenbits = int(mo.group(1)) - assert msglenbits % 8 == 0 - msglen = msglenbits / 8 - msg = a2b_hex(mo.group(2))[:msglen] # The slice is necessary because NIST seems to think that "00" is a reasonable representation for the zero-length string. - assert len(msg) == msglen, (len(msg), msglen) - md = a2b_hex(mo.group(3)) - - computed_md = sha256.SHA256(msg).digest() - self.failUnlessEqual(computed_md, md) - - def test_monte(self): - inlines = resource_string_lines('pycryptopp', 'testvectors/SHA256Monte.txt') - for line in inlines: - line = line.strip() - if line[:7] == 'Seed = ': - seed = a2b_hex(line[7:]) - break - - j = 0 - for line in inlines: - line = line.strip() - if line[:8] == 'COUNT = ': - assert int(line[8:]) == j - elif line[:5] == 'MD = ': - mds = [] - mds.append(seed);mds.append(seed);mds.append(seed); - for i in range(1000): - m = mds[-3]+mds[-2]+mds[-1] - mds.append(sha256.SHA256(m).digest()) - seed = mds[-1] - self.failUnlessEqual(line[5:], b2a_hex(seed)) - j += 1 diff --git a/pycryptopp/test/test_startup.py b/pycryptopp/test/test_startup.py deleted file mode 100644 index 3160feb..0000000 --- a/pycryptopp/test/test_startup.py +++ /dev/null @@ -1,5 +0,0 @@ -import unittest - -class T(unittest.TestCase): - def test_load_dll_twice(self): - pass diff --git a/pycryptopp/testvectors/KAT_AES/ECBGFSbox128e.txt b/pycryptopp/testvectors/KAT_AES/ECBGFSbox128e.txt deleted file mode 100644 index 346f347..0000000 --- a/pycryptopp/testvectors/KAT_AES/ECBGFSbox128e.txt +++ /dev/null @@ -1,36 +0,0 @@ -[ENCRYPT] - -COUNT = 0 -KEY = 00000000000000000000000000000000 -PLAINTEXT = f34481ec3cc627bacd5dc3fb08f273e6 -CIPHERTEXT = 0336763e966d92595a567cc9ce537f5e - -COUNT = 1 -KEY = 00000000000000000000000000000000 -PLAINTEXT = 9798c4640bad75c7c3227db910174e72 -CIPHERTEXT = a9a1631bf4996954ebc093957b234589 - -COUNT = 2 -KEY = 00000000000000000000000000000000 -PLAINTEXT = 96ab5c2ff612d9dfaae8c31f30c42168 -CIPHERTEXT = ff4f8391a6a40ca5b25d23bedd44a597 - -COUNT = 3 -KEY = 00000000000000000000000000000000 -PLAINTEXT = 6a118a874519e64e9963798a503f1d35 -CIPHERTEXT = dc43be40be0e53712f7e2bf5ca707209 - -COUNT = 4 -KEY = 00000000000000000000000000000000 -PLAINTEXT = cb9fceec81286ca3e989bd979b0cb284 -CIPHERTEXT = 92beedab1895a94faa69b632e5cc47ce - -COUNT = 5 -KEY = 00000000000000000000000000000000 -PLAINTEXT = b26aeb1874e47ca8358ff22378f09144 -CIPHERTEXT = 459264f4798f6a78bacb89c15ed3d601 - -COUNT = 6 -KEY = 00000000000000000000000000000000 -PLAINTEXT = 58c8e00b2631686d54eab84b91f0aca1 -CIPHERTEXT = 08a4e2efec8a8e3312ca7460b9040bbf diff --git a/pycryptopp/testvectors/KAT_AES/ECBGFSbox256e.txt b/pycryptopp/testvectors/KAT_AES/ECBGFSbox256e.txt deleted file mode 100644 index 66bd7f8..0000000 --- a/pycryptopp/testvectors/KAT_AES/ECBGFSbox256e.txt +++ /dev/null @@ -1,26 +0,0 @@ -[ENCRYPT] - -COUNT = 0 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 014730f80ac625fe84f026c60bfd547d -CIPHERTEXT = 5c9d844ed46f9885085e5d6a4f94c7d7 - -COUNT = 1 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 0b24af36193ce4665f2825d7b4749c98 -CIPHERTEXT = a9ff75bd7cf6613d3731c77c3b6d0c04 - -COUNT = 2 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 761c1fe41a18acf20d241650611d90f1 -CIPHERTEXT = 623a52fcea5d443e48d9181ab32c7421 - -COUNT = 3 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 8a560769d605868ad80d819bdba03771 -CIPHERTEXT = 38f2c7ae10612415d27ca190d27da8b4 - -COUNT = 4 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 91fbef2d15a97816060bee1feaa49afe -CIPHERTEXT = 1bc704f1bce135ceb810341b216d7abe diff --git a/pycryptopp/testvectors/KAT_AES/ECBKeySbox128e.txt b/pycryptopp/testvectors/KAT_AES/ECBKeySbox128e.txt deleted file mode 100644 index 09efbbe..0000000 --- a/pycryptopp/testvectors/KAT_AES/ECBKeySbox128e.txt +++ /dev/null @@ -1,106 +0,0 @@ -[ENCRYPT] - -COUNT = 0 -KEY = 10a58869d74be5a374cf867cfb473859 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6d251e6944b051e04eaa6fb4dbf78465 - -COUNT = 1 -KEY = caea65cdbb75e9169ecd22ebe6e54675 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6e29201190152df4ee058139def610bb - -COUNT = 2 -KEY = a2e2fa9baf7d20822ca9f0542f764a41 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = c3b44b95d9d2f25670eee9a0de099fa3 - -COUNT = 3 -KEY = b6364ac4e1de1e285eaf144a2415f7a0 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 5d9b05578fc944b3cf1ccf0e746cd581 - -COUNT = 4 -KEY = 64cf9c7abc50b888af65f49d521944b2 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = f7efc89d5dba578104016ce5ad659c05 - -COUNT = 5 -KEY = 47d6742eefcc0465dc96355e851b64d9 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 0306194f666d183624aa230a8b264ae7 - -COUNT = 6 -KEY = 3eb39790678c56bee34bbcdeccf6cdb5 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 858075d536d79ccee571f7d7204b1f67 - -COUNT = 7 -KEY = 64110a924f0743d500ccadae72c13427 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 35870c6a57e9e92314bcb8087cde72ce - -COUNT = 8 -KEY = 18d8126516f8a12ab1a36d9f04d68e51 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6c68e9be5ec41e22c825b7c7affb4363 - -COUNT = 9 -KEY = f530357968578480b398a3c251cd1093 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = f5df39990fc688f1b07224cc03e86cea - -COUNT = 10 -KEY = da84367f325d42d601b4326964802e8e -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = bba071bcb470f8f6586e5d3add18bc66 - -COUNT = 11 -KEY = e37b1c6aa2846f6fdb413f238b089f23 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 43c9f7e62f5d288bb27aa40ef8fe1ea8 - -COUNT = 12 -KEY = 6c002b682483e0cabcc731c253be5674 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 3580d19cff44f1014a7c966a69059de5 - -COUNT = 13 -KEY = 143ae8ed6555aba96110ab58893a8ae1 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 806da864dd29d48deafbe764f8202aef - -COUNT = 14 -KEY = b69418a85332240dc82492353956ae0c -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = a303d940ded8f0baff6f75414cac5243 - -COUNT = 15 -KEY = 71b5c08a1993e1362e4d0ce9b22b78d5 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = c2dabd117f8a3ecabfbb11d12194d9d0 - -COUNT = 16 -KEY = e234cdca2606b81f29408d5f6da21206 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = fff60a4740086b3b9c56195b98d91a7b - -COUNT = 17 -KEY = 13237c49074a3da078dc1d828bb78c6f -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 8146a08e2357f0caa30ca8c94d1a0544 - -COUNT = 18 -KEY = 3071a2a48fe6cbd04f1a129098e308f8 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 4b98e06d356deb07ebb824e5713f7be3 - -COUNT = 19 -KEY = 90f42ec0f68385f2ffc5dfc03a654dce -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 7a20a53d460fc9ce0423a7a0764c6cf2 - -COUNT = 20 -KEY = febd9a24d8b65c1c787d50a4ed3619a9 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = f4a70d8af877f9b02b4c40df57d45b17 diff --git a/pycryptopp/testvectors/KAT_AES/ECBKeySbox256e.txt b/pycryptopp/testvectors/KAT_AES/ECBKeySbox256e.txt deleted file mode 100644 index a633884..0000000 --- a/pycryptopp/testvectors/KAT_AES/ECBKeySbox256e.txt +++ /dev/null @@ -1,81 +0,0 @@ -[ENCRYPT] - -COUNT = 0 -KEY = c47b0294dbbbee0fec4757f22ffeee3587ca4730c3d33b691df38bab076bc558 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 46f2fb342d6f0ab477476fc501242c5f - -COUNT = 1 -KEY = 28d46cffa158533194214a91e712fc2b45b518076675affd910edeca5f41ac64 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 4bf3b0a69aeb6657794f2901b1440ad4 - -COUNT = 2 -KEY = c1cc358b449909a19436cfbb3f852ef8bcb5ed12ac7058325f56e6099aab1a1c -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 352065272169abf9856843927d0674fd - -COUNT = 3 -KEY = 984ca75f4ee8d706f46c2d98c0bf4a45f5b00d791c2dfeb191b5ed8e420fd627 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 4307456a9e67813b452e15fa8fffe398 - -COUNT = 4 -KEY = b43d08a447ac8609baadae4ff12918b9f68fc1653f1269222f123981ded7a92f -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 4663446607354989477a5c6f0f007ef4 - -COUNT = 5 -KEY = 1d85a181b54cde51f0e098095b2962fdc93b51fe9b88602b3f54130bf76a5bd9 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 531c2c38344578b84d50b3c917bbb6e1 - -COUNT = 6 -KEY = dc0eba1f2232a7879ded34ed8428eeb8769b056bbaf8ad77cb65c3541430b4cf -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = fc6aec906323480005c58e7e1ab004ad - -COUNT = 7 -KEY = f8be9ba615c5a952cabbca24f68f8593039624d524c816acda2c9183bd917cb9 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = a3944b95ca0b52043584ef02151926a8 - -COUNT = 8 -KEY = 797f8b3d176dac5b7e34a2d539c4ef367a16f8635f6264737591c5c07bf57a3e -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = a74289fe73a4c123ca189ea1e1b49ad5 - -COUNT = 9 -KEY = 6838d40caf927749c13f0329d331f448e202c73ef52c5f73a37ca635d4c47707 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = b91d4ea4488644b56cf0812fa7fcf5fc - -COUNT = 10 -KEY = ccd1bc3c659cd3c59bc437484e3c5c724441da8d6e90ce556cd57d0752663bbc -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 304f81ab61a80c2e743b94d5002a126b - -COUNT = 11 -KEY = 13428b5e4c005e0636dd338405d173ab135dec2a25c22c5df0722d69dcc43887 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 649a71545378c783e368c9ade7114f6c - -COUNT = 12 -KEY = 07eb03a08d291d1b07408bf3512ab40c91097ac77461aad4bb859647f74f00ee -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 47cb030da2ab051dfc6c4bf6910d12bb - -COUNT = 13 -KEY = 90143ae20cd78c5d8ebdd6cb9dc1762427a96c78c639bccc41a61424564eafe1 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 798c7c005dee432b2c8ea5dfa381ecc3 - -COUNT = 14 -KEY = b7a5794d52737475d53d5a377200849be0260a67a2b22ced8bbef12882270d07 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 637c31dc2591a07636f646b72daabbe7 - -COUNT = 15 -KEY = fca02f3d5011cfc5c1e23165d413a049d4526a991827424d896fe3435e0bf68e -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 179a49c712154bbffbe6e7a84a18e220 diff --git a/pycryptopp/testvectors/KAT_AES/ECBVarKey128e.txt b/pycryptopp/testvectors/KAT_AES/ECBVarKey128e.txt deleted file mode 100644 index 27d6dd8..0000000 --- a/pycryptopp/testvectors/KAT_AES/ECBVarKey128e.txt +++ /dev/null @@ -1,641 +0,0 @@ -[ENCRYPT] - -COUNT = 0 -KEY = 80000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 0edd33d3c621e546455bd8ba1418bec8 - -COUNT = 1 -KEY = c0000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 4bc3f883450c113c64ca42e1112a9e87 - -COUNT = 2 -KEY = e0000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 72a1da770f5d7ac4c9ef94d822affd97 - -COUNT = 3 -KEY = f0000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 970014d634e2b7650777e8e84d03ccd8 - -COUNT = 4 -KEY = f8000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = f17e79aed0db7e279e955b5f493875a7 - -COUNT = 5 -KEY = fc000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 9ed5a75136a940d0963da379db4af26a - -COUNT = 6 -KEY = fe000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = c4295f83465c7755e8fa364bac6a7ea5 - -COUNT = 7 -KEY = ff000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = b1d758256b28fd850ad4944208cf1155 - -COUNT = 8 -KEY = ff800000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 42ffb34c743de4d88ca38011c990890b - -COUNT = 9 -KEY = ffc00000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 9958f0ecea8b2172c0c1995f9182c0f3 - -COUNT = 10 -KEY = ffe00000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 956d7798fac20f82a8823f984d06f7f5 - -COUNT = 11 -KEY = fff00000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = a01bf44f2d16be928ca44aaf7b9b106b - -COUNT = 12 -KEY = fff80000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = b5f1a33e50d40d103764c76bd4c6b6f8 - -COUNT = 13 -KEY = fffc0000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 2637050c9fc0d4817e2d69de878aee8d - -COUNT = 14 -KEY = fffe0000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 113ecbe4a453269a0dd26069467fb5b5 - -COUNT = 15 -KEY = ffff0000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 97d0754fe68f11b9e375d070a608c884 - -COUNT = 16 -KEY = ffff8000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = c6a0b3e998d05068a5399778405200b4 - -COUNT = 17 -KEY = ffffc000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = df556a33438db87bc41b1752c55e5e49 - -COUNT = 18 -KEY = ffffe000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 90fb128d3a1af6e548521bb962bf1f05 - -COUNT = 19 -KEY = fffff000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 26298e9c1db517c215fadfb7d2a8d691 - -COUNT = 20 -KEY = fffff800000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = a6cb761d61f8292d0df393a279ad0380 - -COUNT = 21 -KEY = fffffc00000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 12acd89b13cd5f8726e34d44fd486108 - -COUNT = 22 -KEY = fffffe00000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 95b1703fc57ba09fe0c3580febdd7ed4 - -COUNT = 23 -KEY = ffffff00000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = de11722d893e9f9121c381becc1da59a - -COUNT = 24 -KEY = ffffff80000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6d114ccb27bf391012e8974c546d9bf2 - -COUNT = 25 -KEY = ffffffc0000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 5ce37e17eb4646ecfac29b9cc38d9340 - -COUNT = 26 -KEY = ffffffe0000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 18c1b6e2157122056d0243d8a165cddb - -COUNT = 27 -KEY = fffffff0000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 99693e6a59d1366c74d823562d7e1431 - -COUNT = 28 -KEY = fffffff8000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6c7c64dc84a8bba758ed17eb025a57e3 - -COUNT = 29 -KEY = fffffffc000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = e17bc79f30eaab2fac2cbbe3458d687a - -COUNT = 30 -KEY = fffffffe000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 1114bc2028009b923f0b01915ce5e7c4 - -COUNT = 31 -KEY = ffffffff000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 9c28524a16a1e1c1452971caa8d13476 - -COUNT = 32 -KEY = ffffffff800000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ed62e16363638360fdd6ad62112794f0 - -COUNT = 33 -KEY = ffffffffc00000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 5a8688f0b2a2c16224c161658ffd4044 - -COUNT = 34 -KEY = ffffffffe00000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 23f710842b9bb9c32f26648c786807ca - -COUNT = 35 -KEY = fffffffff00000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 44a98bf11e163f632c47ec6a49683a89 - -COUNT = 36 -KEY = fffffffff80000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 0f18aff94274696d9b61848bd50ac5e5 - -COUNT = 37 -KEY = fffffffffc0000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 82408571c3e2424540207f833b6dda69 - -COUNT = 38 -KEY = fffffffffe0000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 303ff996947f0c7d1f43c8f3027b9b75 - -COUNT = 39 -KEY = ffffffffff0000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 7df4daf4ad29a3615a9b6ece5c99518a - -COUNT = 40 -KEY = ffffffffff8000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = c72954a48d0774db0b4971c526260415 - -COUNT = 41 -KEY = ffffffffffc000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 1df9b76112dc6531e07d2cfda04411f0 - -COUNT = 42 -KEY = ffffffffffe000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 8e4d8e699119e1fc87545a647fb1d34f - -COUNT = 43 -KEY = fffffffffff000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = e6c4807ae11f36f091c57d9fb68548d1 - -COUNT = 44 -KEY = fffffffffff800000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 8ebf73aad49c82007f77a5c1ccec6ab4 - -COUNT = 45 -KEY = fffffffffffc00000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 4fb288cc2040049001d2c7585ad123fc - -COUNT = 46 -KEY = fffffffffffe00000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 04497110efb9dceb13e2b13fb4465564 - -COUNT = 47 -KEY = ffffffffffff00000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 75550e6cb5a88e49634c9ab69eda0430 - -COUNT = 48 -KEY = ffffffffffff80000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = b6768473ce9843ea66a81405dd50b345 - -COUNT = 49 -KEY = ffffffffffffc0000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = cb2f430383f9084e03a653571e065de6 - -COUNT = 50 -KEY = ffffffffffffe0000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ff4e66c07bae3e79fb7d210847a3b0ba - -COUNT = 51 -KEY = fffffffffffff0000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 7b90785125505fad59b13c186dd66ce3 - -COUNT = 52 -KEY = fffffffffffff8000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 8b527a6aebdaec9eaef8eda2cb7783e5 - -COUNT = 53 -KEY = fffffffffffffc000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 43fdaf53ebbc9880c228617d6a9b548b - -COUNT = 54 -KEY = fffffffffffffe000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 53786104b9744b98f052c46f1c850d0b - -COUNT = 55 -KEY = ffffffffffffff000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = b5ab3013dd1e61df06cbaf34ca2aee78 - -COUNT = 56 -KEY = ffffffffffffff800000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 7470469be9723030fdcc73a8cd4fbb10 - -COUNT = 57 -KEY = ffffffffffffffc00000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = a35a63f5343ebe9ef8167bcb48ad122e - -COUNT = 58 -KEY = ffffffffffffffe00000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = fd8687f0757a210e9fdf181204c30863 - -COUNT = 59 -KEY = fffffffffffffff00000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 7a181e84bd5457d26a88fbae96018fb0 - -COUNT = 60 -KEY = fffffffffffffff80000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 653317b9362b6f9b9e1a580e68d494b5 - -COUNT = 61 -KEY = fffffffffffffffc0000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 995c9dc0b689f03c45867b5faa5c18d1 - -COUNT = 62 -KEY = fffffffffffffffe0000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 77a4d96d56dda398b9aabecfc75729fd - -COUNT = 63 -KEY = ffffffffffffffff0000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 84be19e053635f09f2665e7bae85b42d - -COUNT = 64 -KEY = ffffffffffffffff8000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 32cd652842926aea4aa6137bb2be2b5e - -COUNT = 65 -KEY = ffffffffffffffffc000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 493d4a4f38ebb337d10aa84e9171a554 - -COUNT = 66 -KEY = ffffffffffffffffe000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = d9bff7ff454b0ec5a4a2a69566e2cb84 - -COUNT = 67 -KEY = fffffffffffffffff000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 3535d565ace3f31eb249ba2cc6765d7a - -COUNT = 68 -KEY = fffffffffffffffff800000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = f60e91fc3269eecf3231c6e9945697c6 - -COUNT = 69 -KEY = fffffffffffffffffc00000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ab69cfadf51f8e604d9cc37182f6635a - -COUNT = 70 -KEY = fffffffffffffffffe00000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 7866373f24a0b6ed56e0d96fcdafb877 - -COUNT = 71 -KEY = ffffffffffffffffff00000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 1ea448c2aac954f5d812e9d78494446a - -COUNT = 72 -KEY = ffffffffffffffffff80000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = acc5599dd8ac02239a0fef4a36dd1668 - -COUNT = 73 -KEY = ffffffffffffffffffc0000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = d8764468bb103828cf7e1473ce895073 - -COUNT = 74 -KEY = ffffffffffffffffffe0000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 1b0d02893683b9f180458e4aa6b73982 - -COUNT = 75 -KEY = fffffffffffffffffff0000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 96d9b017d302df410a937dcdb8bb6e43 - -COUNT = 76 -KEY = fffffffffffffffffff8000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ef1623cc44313cff440b1594a7e21cc6 - -COUNT = 77 -KEY = fffffffffffffffffffc000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 284ca2fa35807b8b0ae4d19e11d7dbd7 - -COUNT = 78 -KEY = fffffffffffffffffffe000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = f2e976875755f9401d54f36e2a23a594 - -COUNT = 79 -KEY = ffffffffffffffffffff000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ec198a18e10e532403b7e20887c8dd80 - -COUNT = 80 -KEY = ffffffffffffffffffff800000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 545d50ebd919e4a6949d96ad47e46a80 - -COUNT = 81 -KEY = ffffffffffffffffffffc00000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = dbdfb527060e0a71009c7bb0c68f1d44 - -COUNT = 82 -KEY = ffffffffffffffffffffe00000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 9cfa1322ea33da2173a024f2ff0d896d - -COUNT = 83 -KEY = fffffffffffffffffffff00000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 8785b1a75b0f3bd958dcd0e29318c521 - -COUNT = 84 -KEY = fffffffffffffffffffff80000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 38f67b9e98e4a97b6df030a9fcdd0104 - -COUNT = 85 -KEY = fffffffffffffffffffffc0000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 192afffb2c880e82b05926d0fc6c448b - -COUNT = 86 -KEY = fffffffffffffffffffffe0000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6a7980ce7b105cf530952d74daaf798c - -COUNT = 87 -KEY = ffffffffffffffffffffff0000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ea3695e1351b9d6858bd958cf513ef6c - -COUNT = 88 -KEY = ffffffffffffffffffffff8000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6da0490ba0ba0343b935681d2cce5ba1 - -COUNT = 89 -KEY = ffffffffffffffffffffffc000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = f0ea23af08534011c60009ab29ada2f1 - -COUNT = 90 -KEY = ffffffffffffffffffffffe000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ff13806cf19cc38721554d7c0fcdcd4b - -COUNT = 91 -KEY = fffffffffffffffffffffff000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6838af1f4f69bae9d85dd188dcdf0688 - -COUNT = 92 -KEY = fffffffffffffffffffffff800000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 36cf44c92d550bfb1ed28ef583ddf5d7 - -COUNT = 93 -KEY = fffffffffffffffffffffffc00000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = d06e3195b5376f109d5c4ec6c5d62ced - -COUNT = 94 -KEY = fffffffffffffffffffffffe00000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = c440de014d3d610707279b13242a5c36 - -COUNT = 95 -KEY = ffffffffffffffffffffffff00000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = f0c5c6ffa5e0bd3a94c88f6b6f7c16b9 - -COUNT = 96 -KEY = ffffffffffffffffffffffff80000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 3e40c3901cd7effc22bffc35dee0b4d9 - -COUNT = 97 -KEY = ffffffffffffffffffffffffc0000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = b63305c72bedfab97382c406d0c49bc6 - -COUNT = 98 -KEY = ffffffffffffffffffffffffe0000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 36bbaab22a6bd4925a99a2b408d2dbae - -COUNT = 99 -KEY = fffffffffffffffffffffffff0000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 307c5b8fcd0533ab98bc51e27a6ce461 - -COUNT = 100 -KEY = fffffffffffffffffffffffff8000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 829c04ff4c07513c0b3ef05c03e337b5 - -COUNT = 101 -KEY = fffffffffffffffffffffffffc000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = f17af0e895dda5eb98efc68066e84c54 - -COUNT = 102 -KEY = fffffffffffffffffffffffffe000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 277167f3812afff1ffacb4a934379fc3 - -COUNT = 103 -KEY = ffffffffffffffffffffffffff000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 2cb1dc3a9c72972e425ae2ef3eb597cd - -COUNT = 104 -KEY = ffffffffffffffffffffffffff800000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 36aeaa3a213e968d4b5b679d3a2c97fe - -COUNT = 105 -KEY = ffffffffffffffffffffffffffc00000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 9241daca4fdd034a82372db50e1a0f3f - -COUNT = 106 -KEY = ffffffffffffffffffffffffffe00000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = c14574d9cd00cf2b5a7f77e53cd57885 - -COUNT = 107 -KEY = fffffffffffffffffffffffffff00000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 793de39236570aba83ab9b737cb521c9 - -COUNT = 108 -KEY = fffffffffffffffffffffffffff80000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 16591c0f27d60e29b85a96c33861a7ef - -COUNT = 109 -KEY = fffffffffffffffffffffffffffc0000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 44fb5c4d4f5cb79be5c174a3b1c97348 - -COUNT = 110 -KEY = fffffffffffffffffffffffffffe0000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 674d2b61633d162be59dde04222f4740 - -COUNT = 111 -KEY = ffffffffffffffffffffffffffff0000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = b4750ff263a65e1f9e924ccfd98f3e37 - -COUNT = 112 -KEY = ffffffffffffffffffffffffffff8000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 62d0662d6eaeddedebae7f7ea3a4f6b6 - -COUNT = 113 -KEY = ffffffffffffffffffffffffffffc000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 70c46bb30692be657f7eaa93ebad9897 - -COUNT = 114 -KEY = ffffffffffffffffffffffffffffe000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 323994cfb9da285a5d9642e1759b224a - -COUNT = 115 -KEY = fffffffffffffffffffffffffffff000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 1dbf57877b7b17385c85d0b54851e371 - -COUNT = 116 -KEY = fffffffffffffffffffffffffffff800 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = dfa5c097cdc1532ac071d57b1d28d1bd - -COUNT = 117 -KEY = fffffffffffffffffffffffffffffc00 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 3a0c53fa37311fc10bd2a9981f513174 - -COUNT = 118 -KEY = fffffffffffffffffffffffffffffe00 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ba4f970c0a25c41814bdae2e506be3b4 - -COUNT = 119 -KEY = ffffffffffffffffffffffffffffff00 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 2dce3acb727cd13ccd76d425ea56e4f6 - -COUNT = 120 -KEY = ffffffffffffffffffffffffffffff80 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 5160474d504b9b3eefb68d35f245f4b3 - -COUNT = 121 -KEY = ffffffffffffffffffffffffffffffc0 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 41a8a947766635dec37553d9a6c0cbb7 - -COUNT = 122 -KEY = ffffffffffffffffffffffffffffffe0 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 25d6cfe6881f2bf497dd14cd4ddf445b - -COUNT = 123 -KEY = fffffffffffffffffffffffffffffff0 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 41c78c135ed9e98c096640647265da1e - -COUNT = 124 -KEY = fffffffffffffffffffffffffffffff8 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 5a4d404d8917e353e92a21072c3b2305 - -COUNT = 125 -KEY = fffffffffffffffffffffffffffffffc -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 02bc96846b3fdc71643f384cd3cc3eaf - -COUNT = 126 -KEY = fffffffffffffffffffffffffffffffe -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 9ba4a9143f4e5d4048521c4f8877d88e - -COUNT = 127 -KEY = ffffffffffffffffffffffffffffffff -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = a1f6258c877d5fcd8964484538bfc92c diff --git a/pycryptopp/testvectors/KAT_AES/ECBVarKey256e.txt b/pycryptopp/testvectors/KAT_AES/ECBVarKey256e.txt deleted file mode 100644 index 3b7a986..0000000 --- a/pycryptopp/testvectors/KAT_AES/ECBVarKey256e.txt +++ /dev/null @@ -1,1281 +0,0 @@ -[ENCRYPT] - -COUNT = 0 -KEY = 8000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = e35a6dcb19b201a01ebcfa8aa22b5759 - -COUNT = 1 -KEY = c000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = b29169cdcf2d83e838125a12ee6aa400 - -COUNT = 2 -KEY = e000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = d8f3a72fc3cdf74dfaf6c3e6b97b2fa6 - -COUNT = 3 -KEY = f000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 1c777679d50037c79491a94da76a9a35 - -COUNT = 4 -KEY = f800000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 9cf4893ecafa0a0247a898e040691559 - -COUNT = 5 -KEY = fc00000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 8fbb413703735326310a269bd3aa94b2 - -COUNT = 6 -KEY = fe00000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 60e32246bed2b0e859e55c1cc6b26502 - -COUNT = 7 -KEY = ff00000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ec52a212f80a09df6317021bc2a9819e - -COUNT = 8 -KEY = ff80000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = f23e5b600eb70dbccf6c0b1d9a68182c - -COUNT = 9 -KEY = ffc0000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = a3f599d63a82a968c33fe26590745970 - -COUNT = 10 -KEY = ffe0000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = d1ccb9b1337002cbac42c520b5d67722 - -COUNT = 11 -KEY = fff0000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = cc111f6c37cf40a1159d00fb59fb0488 - -COUNT = 12 -KEY = fff8000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = dc43b51ab609052372989a26e9cdd714 - -COUNT = 13 -KEY = fffc000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 4dcede8da9e2578f39703d4433dc6459 - -COUNT = 14 -KEY = fffe000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 1a4c1c263bbccfafc11782894685e3a8 - -COUNT = 15 -KEY = ffff000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 937ad84880db50613423d6d527a2823d - -COUNT = 16 -KEY = ffff800000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 610b71dfc688e150d8152c5b35ebc14d - -COUNT = 17 -KEY = ffffc00000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 27ef2495dabf323885aab39c80f18d8b - -COUNT = 18 -KEY = ffffe00000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 633cafea395bc03adae3a1e2068e4b4e - -COUNT = 19 -KEY = fffff00000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6e1b482b53761cf631819b749a6f3724 - -COUNT = 20 -KEY = fffff80000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 976e6f851ab52c771998dbb2d71c75a9 - -COUNT = 21 -KEY = fffffc0000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 85f2ba84f8c307cf525e124c3e22e6cc - -COUNT = 22 -KEY = fffffe0000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6bcca98bf6a835fa64955f72de4115fe - -COUNT = 23 -KEY = ffffff0000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 2c75e2d36eebd65411f14fd0eb1d2a06 - -COUNT = 24 -KEY = ffffff8000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = bd49295006250ffca5100b6007a0eade - -COUNT = 25 -KEY = ffffffc000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = a190527d0ef7c70f459cd3940df316ec - -COUNT = 26 -KEY = ffffffe000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = bbd1097a62433f79449fa97d4ee80dbf - -COUNT = 27 -KEY = fffffff000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 07058e408f5b99b0e0f061a1761b5b3b - -COUNT = 28 -KEY = fffffff800000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 5fd1f13fa0f31e37fabde328f894eac2 - -COUNT = 29 -KEY = fffffffc00000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = fc4af7c948df26e2ef3e01c1ee5b8f6f - -COUNT = 30 -KEY = fffffffe00000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 829fd7208fb92d44a074a677ee9861ac - -COUNT = 31 -KEY = ffffffff00000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ad9fc613a703251b54c64a0e76431711 - -COUNT = 32 -KEY = ffffffff80000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 33ac9eccc4cc75e2711618f80b1548e8 - -COUNT = 33 -KEY = ffffffffc0000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 2025c74b8ad8f4cda17ee2049c4c902d - -COUNT = 34 -KEY = ffffffffe0000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = f85ca05fe528f1ce9b790166e8d551e7 - -COUNT = 35 -KEY = fffffffff0000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6f6238d8966048d4967154e0dad5a6c9 - -COUNT = 36 -KEY = fffffffff8000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = f2b21b4e7640a9b3346de8b82fb41e49 - -COUNT = 37 -KEY = fffffffffc000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = f836f251ad1d11d49dc344628b1884e1 - -COUNT = 38 -KEY = fffffffffe000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 077e9470ae7abea5a9769d49182628c3 - -COUNT = 39 -KEY = ffffffffff000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = e0dcc2d27fc9865633f85223cf0d611f - -COUNT = 40 -KEY = ffffffffff800000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = be66cfea2fecd6bf0ec7b4352c99bcaa - -COUNT = 41 -KEY = ffffffffffc00000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = df31144f87a2ef523facdcf21a427804 - -COUNT = 42 -KEY = ffffffffffe00000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = b5bb0f5629fb6aae5e1839a3c3625d63 - -COUNT = 43 -KEY = fffffffffff00000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 3c9db3335306fe1ec612bdbfae6b6028 - -COUNT = 44 -KEY = fffffffffff80000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 3dd5c34634a79d3cfcc8339760e6f5f4 - -COUNT = 45 -KEY = fffffffffffc0000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 82bda118a3ed7af314fa2ccc5c07b761 - -COUNT = 46 -KEY = fffffffffffe0000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 2937a64f7d4f46fe6fea3b349ec78e38 - -COUNT = 47 -KEY = ffffffffffff0000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 225f068c28476605735ad671bb8f39f3 - -COUNT = 48 -KEY = ffffffffffff8000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ae682c5ecd71898e08942ac9aa89875c - -COUNT = 49 -KEY = ffffffffffffc000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 5e031cb9d676c3022d7f26227e85c38f - -COUNT = 50 -KEY = ffffffffffffe000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = a78463fb064db5d52bb64bfef64f2dda - -COUNT = 51 -KEY = fffffffffffff000000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 8aa9b75e784593876c53a00eae5af52b - -COUNT = 52 -KEY = fffffffffffff800000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 3f84566df23da48af692722fe980573a - -COUNT = 53 -KEY = fffffffffffffc00000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 31690b5ed41c7eb42a1e83270a7ff0e6 - -COUNT = 54 -KEY = fffffffffffffe00000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 77dd7702646d55f08365e477d3590eda - -COUNT = 55 -KEY = ffffffffffffff00000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 4c022ac62b3cb78d739cc67b3e20bb7e - -COUNT = 56 -KEY = ffffffffffffff80000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 092fa137ce18b5dfe7906f550bb13370 - -COUNT = 57 -KEY = ffffffffffffffc0000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 3e0cdadf2e68353c0027672c97144dd3 - -COUNT = 58 -KEY = ffffffffffffffe0000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = d8c4b200b383fc1f2b2ea677618a1d27 - -COUNT = 59 -KEY = fffffffffffffff0000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 11825f99b0e9bb3477c1c0713b015aac - -COUNT = 60 -KEY = fffffffffffffff8000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = f8b9fffb5c187f7ddc7ab10f4fb77576 - -COUNT = 61 -KEY = fffffffffffffffc000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ffb4e87a32b37d6f2c8328d3b5377802 - -COUNT = 62 -KEY = fffffffffffffffe000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = d276c13a5d220f4da9224e74896391ce - -COUNT = 63 -KEY = ffffffffffffffff000000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 94efe7a0e2e031e2536da01df799c927 - -COUNT = 64 -KEY = ffffffffffffffff800000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 8f8fd822680a85974e53a5a8eb9d38de - -COUNT = 65 -KEY = ffffffffffffffffc00000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = e0f0a91b2e45f8cc37b7805a3042588d - -COUNT = 66 -KEY = ffffffffffffffffe00000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 597a6252255e46d6364dbeeda31e279c - -COUNT = 67 -KEY = fffffffffffffffff00000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = f51a0f694442b8f05571797fec7ee8bf - -COUNT = 68 -KEY = fffffffffffffffff80000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 9ff071b165b5198a93dddeebc54d09b5 - -COUNT = 69 -KEY = fffffffffffffffffc0000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = c20a19fd5758b0c4bc1a5df89cf73877 - -COUNT = 70 -KEY = fffffffffffffffffe0000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 97120166307119ca2280e9315668e96f - -COUNT = 71 -KEY = ffffffffffffffffff0000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 4b3b9f1e099c2a09dc091e90e4f18f0a - -COUNT = 72 -KEY = ffffffffffffffffff8000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = eb040b891d4b37f6851f7ec219cd3f6d - -COUNT = 73 -KEY = ffffffffffffffffffc000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 9f0fdec08b7fd79aa39535bea42db92a - -COUNT = 74 -KEY = ffffffffffffffffffe000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 2e70f168fc74bf911df240bcd2cef236 - -COUNT = 75 -KEY = fffffffffffffffffff000000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 462ccd7f5fd1108dbc152f3cacad328b - -COUNT = 76 -KEY = fffffffffffffffffff800000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = a4af534a7d0b643a01868785d86dfb95 - -COUNT = 77 -KEY = fffffffffffffffffffc00000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ab980296197e1a5022326c31da4bf6f3 - -COUNT = 78 -KEY = fffffffffffffffffffe00000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = f97d57b3333b6281b07d486db2d4e20c - -COUNT = 79 -KEY = ffffffffffffffffffff00000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = f33fa36720231afe4c759ade6bd62eb6 - -COUNT = 80 -KEY = ffffffffffffffffffff80000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = fdcfac0c02ca538343c68117e0a15938 - -COUNT = 81 -KEY = ffffffffffffffffffffc0000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ad4916f5ee5772be764fc027b8a6e539 - -COUNT = 82 -KEY = ffffffffffffffffffffe0000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 2e16873e1678610d7e14c02d002ea845 - -COUNT = 83 -KEY = fffffffffffffffffffff0000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 4e6e627c1acc51340053a8236d579576 - -COUNT = 84 -KEY = fffffffffffffffffffff8000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ab0c8410aeeead92feec1eb430d652cb - -COUNT = 85 -KEY = fffffffffffffffffffffc000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = e86f7e23e835e114977f60e1a592202e - -COUNT = 86 -KEY = fffffffffffffffffffffe000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = e68ad5055a367041fade09d9a70a794b - -COUNT = 87 -KEY = ffffffffffffffffffffff000000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 0791823a3c666bb6162825e78606a7fe - -COUNT = 88 -KEY = ffffffffffffffffffffff800000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = dcca366a9bf47b7b868b77e25c18a364 - -COUNT = 89 -KEY = ffffffffffffffffffffffc00000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 684c9efc237e4a442965f84bce20247a - -COUNT = 90 -KEY = ffffffffffffffffffffffe00000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = a858411ffbe63fdb9c8aa1bfaed67b52 - -COUNT = 91 -KEY = fffffffffffffffffffffff00000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 04bc3da2179c3015498b0e03910db5b8 - -COUNT = 92 -KEY = fffffffffffffffffffffff80000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 40071eeab3f935dbc25d00841460260f - -COUNT = 93 -KEY = fffffffffffffffffffffffc0000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 0ebd7c30ed2016e08ba806ddb008bcc8 - -COUNT = 94 -KEY = fffffffffffffffffffffffe0000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 15c6becf0f4cec7129cbd22d1a79b1b8 - -COUNT = 95 -KEY = ffffffffffffffffffffffff0000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 0aeede5b91f721700e9e62edbf60b781 - -COUNT = 96 -KEY = ffffffffffffffffffffffff8000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 266581af0dcfbed1585e0a242c64b8df - -COUNT = 97 -KEY = ffffffffffffffffffffffffc000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6693dc911662ae473216ba22189a511a - -COUNT = 98 -KEY = ffffffffffffffffffffffffe000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 7606fa36d86473e6fb3a1bb0e2c0adf5 - -COUNT = 99 -KEY = fffffffffffffffffffffffff000000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 112078e9e11fbb78e26ffb8899e96b9a - -COUNT = 100 -KEY = fffffffffffffffffffffffff800000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 40b264e921e9e4a82694589ef3798262 - -COUNT = 101 -KEY = fffffffffffffffffffffffffc00000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 8d4595cb4fa7026715f55bd68e2882f9 - -COUNT = 102 -KEY = fffffffffffffffffffffffffe00000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = b588a302bdbc09197df1edae68926ed9 - -COUNT = 103 -KEY = ffffffffffffffffffffffffff00000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 33f7502390b8a4a221cfecd0666624ba - -COUNT = 104 -KEY = ffffffffffffffffffffffffff80000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 3d20253adbce3be2373767c4d822c566 - -COUNT = 105 -KEY = ffffffffffffffffffffffffffc0000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = a42734a3929bf84cf0116c9856a3c18c - -COUNT = 106 -KEY = ffffffffffffffffffffffffffe0000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = e3abc4939457422bb957da3c56938c6d - -COUNT = 107 -KEY = fffffffffffffffffffffffffff0000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 972bdd2e7c525130fadc8f76fc6f4b3f - -COUNT = 108 -KEY = fffffffffffffffffffffffffff8000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 84a83d7b94c699cbcb8a7d9b61f64093 - -COUNT = 109 -KEY = fffffffffffffffffffffffffffc000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ce61d63514aded03d43e6ebfc3a9001f - -COUNT = 110 -KEY = fffffffffffffffffffffffffffe000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6c839dd58eeae6b8a36af48ed63d2dc9 - -COUNT = 111 -KEY = ffffffffffffffffffffffffffff000000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = cd5ece55b8da3bf622c4100df5de46f9 - -COUNT = 112 -KEY = ffffffffffffffffffffffffffff800000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 3b6f46f40e0ac5fc0a9c1105f800f48d - -COUNT = 113 -KEY = ffffffffffffffffffffffffffffc00000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ba26d47da3aeb028de4fb5b3a854a24b - -COUNT = 114 -KEY = ffffffffffffffffffffffffffffe00000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 87f53bf620d3677268445212904389d5 - -COUNT = 115 -KEY = fffffffffffffffffffffffffffff00000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 10617d28b5e0f4605492b182a5d7f9f6 - -COUNT = 116 -KEY = fffffffffffffffffffffffffffff80000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 9aaec4fabbf6fae2a71feff02e372b39 - -COUNT = 117 -KEY = fffffffffffffffffffffffffffffc0000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 3a90c62d88b5c42809abf782488ed130 - -COUNT = 118 -KEY = fffffffffffffffffffffffffffffe0000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = f1f1c5a40899e15772857ccb65c7a09a - -COUNT = 119 -KEY = ffffffffffffffffffffffffffffff0000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 190843d29b25a3897c692ce1dd81ee52 - -COUNT = 120 -KEY = ffffffffffffffffffffffffffffff8000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = a866bc65b6941d86e8420a7ffb0964db - -COUNT = 121 -KEY = ffffffffffffffffffffffffffffffc000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 8193c6ff85225ced4255e92f6e078a14 - -COUNT = 122 -KEY = ffffffffffffffffffffffffffffffe000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 9661cb2424d7d4a380d547f9e7ec1cb9 - -COUNT = 123 -KEY = fffffffffffffffffffffffffffffff000000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 86f93d9ec08453a071e2e2877877a9c8 - -COUNT = 124 -KEY = fffffffffffffffffffffffffffffff800000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 27eefa80ce6a4a9d598e3fec365434d2 - -COUNT = 125 -KEY = fffffffffffffffffffffffffffffffc00000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = d62068444578e3ab39ce7ec95dd045dc - -COUNT = 126 -KEY = fffffffffffffffffffffffffffffffe00000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = b5f71d4dd9a71fe5d8bc8ba7e6ea3048 - -COUNT = 127 -KEY = ffffffffffffffffffffffffffffffff00000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6825a347ac479d4f9d95c5cb8d3fd7e9 - -COUNT = 128 -KEY = ffffffffffffffffffffffffffffffff80000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = e3714e94a5778955cc0346358e94783a - -COUNT = 129 -KEY = ffffffffffffffffffffffffffffffffc0000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = d836b44bb29e0c7d89fa4b2d4b677d2a - -COUNT = 130 -KEY = ffffffffffffffffffffffffffffffffe0000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 5d454b75021d76d4b84f873a8f877b92 - -COUNT = 131 -KEY = fffffffffffffffffffffffffffffffff0000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = c3498f7eced2095314fc28115885b33f - -COUNT = 132 -KEY = fffffffffffffffffffffffffffffffff8000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6e668856539ad8e405bd123fe6c88530 - -COUNT = 133 -KEY = fffffffffffffffffffffffffffffffffc000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 8680db7f3a87b8605543cfdbe6754076 - -COUNT = 134 -KEY = fffffffffffffffffffffffffffffffffe000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6c5d03b13069c3658b3179be91b0800c - -COUNT = 135 -KEY = ffffffffffffffffffffffffffffffffff000000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ef1b384ac4d93eda00c92add0995ea5f - -COUNT = 136 -KEY = ffffffffffffffffffffffffffffffffff800000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = bf8115805471741bd5ad20a03944790f - -COUNT = 137 -KEY = ffffffffffffffffffffffffffffffffffc00000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = c64c24b6894b038b3c0d09b1df068b0b - -COUNT = 138 -KEY = ffffffffffffffffffffffffffffffffffe00000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 3967a10cffe27d0178545fbf6a40544b - -COUNT = 139 -KEY = fffffffffffffffffffffffffffffffffff00000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 7c85e9c95de1a9ec5a5363a8a053472d - -COUNT = 140 -KEY = fffffffffffffffffffffffffffffffffff80000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = a9eec03c8abec7ba68315c2c8c2316e0 - -COUNT = 141 -KEY = fffffffffffffffffffffffffffffffffffc0000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = cac8e414c2f388227ae14986fc983524 - -COUNT = 142 -KEY = fffffffffffffffffffffffffffffffffffe0000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 5d942b7f4622ce056c3ce3ce5f1dd9d6 - -COUNT = 143 -KEY = ffffffffffffffffffffffffffffffffffff0000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = d240d648ce21a3020282c3f1b528a0b6 - -COUNT = 144 -KEY = ffffffffffffffffffffffffffffffffffff8000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 45d089c36d5c5a4efc689e3b0de10dd5 - -COUNT = 145 -KEY = ffffffffffffffffffffffffffffffffffffc000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = b4da5df4becb5462e03a0ed00d295629 - -COUNT = 146 -KEY = ffffffffffffffffffffffffffffffffffffe000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = dcf4e129136c1a4b7a0f38935cc34b2b - -COUNT = 147 -KEY = fffffffffffffffffffffffffffffffffffff000000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = d9a4c7618b0ce48a3d5aee1a1c0114c4 - -COUNT = 148 -KEY = fffffffffffffffffffffffffffffffffffff800000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ca352df025c65c7b0bf306fbee0f36ba - -COUNT = 149 -KEY = fffffffffffffffffffffffffffffffffffffc00000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 238aca23fd3409f38af63378ed2f5473 - -COUNT = 150 -KEY = fffffffffffffffffffffffffffffffffffffe00000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 59836a0e06a79691b36667d5380d8188 - -COUNT = 151 -KEY = ffffffffffffffffffffffffffffffffffffff00000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 33905080f7acf1cdae0a91fc3e85aee4 - -COUNT = 152 -KEY = ffffffffffffffffffffffffffffffffffffff80000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 72c9e4646dbc3d6320fc6689d93e8833 - -COUNT = 153 -KEY = ffffffffffffffffffffffffffffffffffffffc0000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ba77413dea5925b7f5417ea47ff19f59 - -COUNT = 154 -KEY = ffffffffffffffffffffffffffffffffffffffe0000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6cae8129f843d86dc786a0fb1a184970 - -COUNT = 155 -KEY = fffffffffffffffffffffffffffffffffffffff0000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = fcfefb534100796eebbd990206754e19 - -COUNT = 156 -KEY = fffffffffffffffffffffffffffffffffffffff8000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 8c791d5fdddf470da04f3e6dc4a5b5b5 - -COUNT = 157 -KEY = fffffffffffffffffffffffffffffffffffffffc000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = c93bbdc07a4611ae4bb266ea5034a387 - -COUNT = 158 -KEY = fffffffffffffffffffffffffffffffffffffffe000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = c102e38e489aa74762f3efc5bb23205a - -COUNT = 159 -KEY = ffffffffffffffffffffffffffffffffffffffff000000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 93201481665cbafc1fcc220bc545fb3d - -COUNT = 160 -KEY = ffffffffffffffffffffffffffffffffffffffff800000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 4960757ec6ce68cf195e454cfd0f32ca - -COUNT = 161 -KEY = ffffffffffffffffffffffffffffffffffffffffc00000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = feec7ce6a6cbd07c043416737f1bbb33 - -COUNT = 162 -KEY = ffffffffffffffffffffffffffffffffffffffffe00000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 11c5413904487a805d70a8edd9c35527 - -COUNT = 163 -KEY = fffffffffffffffffffffffffffffffffffffffff00000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 347846b2b2e36f1f0324c86f7f1b98e2 - -COUNT = 164 -KEY = fffffffffffffffffffffffffffffffffffffffff80000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 332eee1a0cbd19ca2d69b426894044f0 - -COUNT = 165 -KEY = fffffffffffffffffffffffffffffffffffffffffc0000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 866b5b3977ba6efa5128efbda9ff03cd - -COUNT = 166 -KEY = fffffffffffffffffffffffffffffffffffffffffe0000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = cc1445ee94c0f08cdee5c344ecd1e233 - -COUNT = 167 -KEY = ffffffffffffffffffffffffffffffffffffffffff0000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = be288319029363c2622feba4b05dfdfe - -COUNT = 168 -KEY = ffffffffffffffffffffffffffffffffffffffffff8000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = cfd1875523f3cd21c395651e6ee15e56 - -COUNT = 169 -KEY = ffffffffffffffffffffffffffffffffffffffffffc000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = cb5a408657837c53bf16f9d8465dce19 - -COUNT = 170 -KEY = ffffffffffffffffffffffffffffffffffffffffffe000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ca0bf42cb107f55ccff2fc09ee08ca15 - -COUNT = 171 -KEY = fffffffffffffffffffffffffffffffffffffffffff000000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = fdd9bbb4a7dc2e4a23536a5880a2db67 - -COUNT = 172 -KEY = fffffffffffffffffffffffffffffffffffffffffff800000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ede447b362c484993dec9442a3b46aef - -COUNT = 173 -KEY = fffffffffffffffffffffffffffffffffffffffffffc00000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 10dffb05904bff7c4781df780ad26837 - -COUNT = 174 -KEY = fffffffffffffffffffffffffffffffffffffffffffe00000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = c33bc13e8de88ac25232aa7496398783 - -COUNT = 175 -KEY = ffffffffffffffffffffffffffffffffffffffffffff00000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ca359c70803a3b2a3d542e8781dea975 - -COUNT = 176 -KEY = ffffffffffffffffffffffffffffffffffffffffffff80000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = bcc65b526f88d05b89ce8a52021fdb06 - -COUNT = 177 -KEY = ffffffffffffffffffffffffffffffffffffffffffffc0000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = db91a38855c8c4643851fbfb358b0109 - -COUNT = 178 -KEY = ffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ca6e8893a114ae8e27d5ab03a5499610 - -COUNT = 179 -KEY = fffffffffffffffffffffffffffffffffffffffffffff0000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6629d2b8df97da728cdd8b1e7f945077 - -COUNT = 180 -KEY = fffffffffffffffffffffffffffffffffffffffffffff8000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 4570a5a18cfc0dd582f1d88d5c9a1720 - -COUNT = 181 -KEY = fffffffffffffffffffffffffffffffffffffffffffffc000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 72bc65aa8e89562e3f274d45af1cd10b - -COUNT = 182 -KEY = fffffffffffffffffffffffffffffffffffffffffffffe000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 98551da1a6503276ae1c77625f9ea615 - -COUNT = 183 -KEY = ffffffffffffffffffffffffffffffffffffffffffffff000000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 0ddfe51ced7e3f4ae927daa3fe452cee - -COUNT = 184 -KEY = ffffffffffffffffffffffffffffffffffffffffffffff800000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = db826251e4ce384b80218b0e1da1dd4c - -COUNT = 185 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffc00000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 2cacf728b88abbad7011ed0e64a1680c - -COUNT = 186 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffe00000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 330d8ee7c5677e099ac74c9994ee4cfb - -COUNT = 187 -KEY = fffffffffffffffffffffffffffffffffffffffffffffff00000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = edf61ae362e882ddc0167474a7a77f3a - -COUNT = 188 -KEY = fffffffffffffffffffffffffffffffffffffffffffffff80000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6168b00ba7859e0970ecfd757efecf7c - -COUNT = 189 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffc0000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = d1415447866230d28bb1ea18a4cdfd02 - -COUNT = 190 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 516183392f7a8763afec68a060264141 - -COUNT = 191 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 77565c8d73cfd4130b4aa14d8911710f - -COUNT = 192 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 37232a4ed21ccc27c19c9610078cabac - -COUNT = 193 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffc000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 804f32ea71828c7d329077e712231666 - -COUNT = 194 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = d64424f23cb97215e9c2c6f28d29eab7 - -COUNT = 195 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 023e82b533f68c75c238cebdb2ee89a2 - -COUNT = 196 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffff800000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 193a3d24157a51f1ee0893f6777417e7 - -COUNT = 197 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffc00000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 84ecacfcd400084d078612b1945f2ef5 - -COUNT = 198 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffe00000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 1dcd8bb173259eb33a5242b0de31a455 - -COUNT = 199 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 35e9eddbc375e792c19992c19165012b - -COUNT = 200 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 8a772231c01dfdd7c98e4cfddcc0807a - -COUNT = 201 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffc0000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6eda7ff6b8319180ff0d6e65629d01c3 - -COUNT = 202 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = c267ef0e2d01a993944dd397101413cb - -COUNT = 203 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = e9f80e9d845bcc0f62926af72eabca39 - -COUNT = 204 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffff8000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 6702990727aa0878637b45dcd3a3b074 - -COUNT = 205 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffc000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 2e2e647d5360e09230a5d738ca33471e - -COUNT = 206 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 1f56413c7add6f43d1d56e4f02190330 - -COUNT = 207 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 69cd0606e15af729d6bca143016d9842 - -COUNT = 208 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffff800000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = a085d7c1a500873a20099c4caa3c3f5b - -COUNT = 209 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 4fc0d230f8891415b87b83f95f2e09d1 - -COUNT = 210 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 4327d08c523d8eba697a4336507d1f42 - -COUNT = 211 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 7a15aab82701efa5ae36ab1d6b76290f - -COUNT = 212 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 5bf0051893a18bb30e139a58fed0fa54 - -COUNT = 213 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffc0000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 97e8adf65638fd9cdf3bc22c17fe4dbd - -COUNT = 214 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 1ee6ee326583a0586491c96418d1a35d - -COUNT = 215 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 26b549c2ec756f82ecc48008e529956b - -COUNT = 216 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 70377b6da669b072129e057cc28e9ca5 - -COUNT = 217 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffc000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 9c94b8b0cb8bcc919072262b3fa05ad9 - -COUNT = 218 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 2fbb83dfd0d7abcb05cd28cad2dfb523 - -COUNT = 219 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 96877803de77744bb970d0a91f4debae - -COUNT = 220 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffff800000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 7379f3370cf6e5ce12ae5969c8eea312 - -COUNT = 221 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 02dc99fa3d4f98ce80985e7233889313 - -COUNT = 222 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 1e38e759075ba5cab6457da51844295a - -COUNT = 223 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 70bed8dbf615868a1f9d9b05d3e7a267 - -COUNT = 224 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 234b148b8cb1d8c32b287e896903d150 - -COUNT = 225 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 294b033df4da853f4be3e243f7e513f4 - -COUNT = 226 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 3f58c950f0367160adec45f2441e7411 - -COUNT = 227 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 37f655536a704e5ace182d742a820cf4 - -COUNT = 228 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ea7bd6bb63418731aeac790fe42d61e8 - -COUNT = 229 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffc000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = e74a4c999b4c064e48bb1e413f51e5ea - -COUNT = 230 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = ba9ebefdb4ccf30f296cecb3bc1943e8 - -COUNT = 231 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 3194367a4898c502c13bb7478640a72d - -COUNT = 232 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = da797713263d6f33a5478a65ef60d412 - -COUNT = 233 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = d1ac39bb1ef86b9c1344f214679aa376 - -COUNT = 234 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 2fdea9e650532be5bc0e7325337fd363 - -COUNT = 235 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = d3a204dbd9c2af158b6ca67a5156ce4a - -COUNT = 236 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 3a0a0e75a8da36735aee6684d965a778 - -COUNT = 237 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 52fc3e620492ea99641ea168da5b6d52 - -COUNT = 238 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = d2e0c7f15b4772467d2cfc873000b2ca - -COUNT = 239 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 563531135e0c4d70a38f8bdb190ba04e - -COUNT = 240 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = a8a39a0f5663f4c0fe5f2d3cafff421a - -COUNT = 241 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = d94b5e90db354c1e42f61fabe167b2c0 - -COUNT = 242 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 50e6d3c9b6698a7cd276f96b1473f35a - -COUNT = 243 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 9338f08e0ebee96905d8f2e825208f43 - -COUNT = 244 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 8b378c86672aa54a3a266ba19d2580ca - -COUNT = 245 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = cca7c3086f5f9511b31233da7cab9160 - -COUNT = 246 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 5b40ff4ec9be536ba23035fa4f06064c - -COUNT = 247 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 60eb5af8416b257149372194e8b88749 - -COUNT = 248 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 2f005a8aed8a361c92e440c15520cbd1 - -COUNT = 249 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 7b03627611678a997717578807a800e2 - -COUNT = 250 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = cf78618f74f6f3696e0a4779b90b5a77 - -COUNT = 251 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 03720371a04962eaea0a852e69972858 - -COUNT = 252 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8 -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 1f8a8133aa8ccf70e2bd3285831ca6b7 - -COUNT = 253 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 27936bd27fb1468fc8b48bc483321725 - -COUNT = 254 -KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = b07d4f3e2cd2ef2eb545980754dfea0f - -COUNT = 255 -KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff -PLAINTEXT = 00000000000000000000000000000000 -CIPHERTEXT = 4bf85f1b5d54adbc307b0a048389adcb diff --git a/pycryptopp/testvectors/KAT_AES/ECBVarTxt128e.txt b/pycryptopp/testvectors/KAT_AES/ECBVarTxt128e.txt deleted file mode 100644 index 52dc52c..0000000 --- a/pycryptopp/testvectors/KAT_AES/ECBVarTxt128e.txt +++ /dev/null @@ -1,641 +0,0 @@ -[ENCRYPT] - -COUNT = 0 -KEY = 00000000000000000000000000000000 -PLAINTEXT = 80000000000000000000000000000000 -CIPHERTEXT = 3ad78e726c1ec02b7ebfe92b23d9ec34 - -COUNT = 1 -KEY = 00000000000000000000000000000000 -PLAINTEXT = c0000000000000000000000000000000 -CIPHERTEXT = aae5939c8efdf2f04e60b9fe7117b2c2 - -COUNT = 2 -KEY = 00000000000000000000000000000000 -PLAINTEXT = e0000000000000000000000000000000 -CIPHERTEXT = f031d4d74f5dcbf39daaf8ca3af6e527 - -COUNT = 3 -KEY = 00000000000000000000000000000000 -PLAINTEXT = f0000000000000000000000000000000 -CIPHERTEXT = 96d9fd5cc4f07441727df0f33e401a36 - -COUNT = 4 -KEY = 00000000000000000000000000000000 -PLAINTEXT = f8000000000000000000000000000000 -CIPHERTEXT = 30ccdb044646d7e1f3ccea3dca08b8c0 - -COUNT = 5 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fc000000000000000000000000000000 -CIPHERTEXT = 16ae4ce5042a67ee8e177b7c587ecc82 - -COUNT = 6 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fe000000000000000000000000000000 -CIPHERTEXT = b6da0bb11a23855d9c5cb1b4c6412e0a - -COUNT = 7 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ff000000000000000000000000000000 -CIPHERTEXT = db4f1aa530967d6732ce4715eb0ee24b - -COUNT = 8 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ff800000000000000000000000000000 -CIPHERTEXT = a81738252621dd180a34f3455b4baa2f - -COUNT = 9 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffc00000000000000000000000000000 -CIPHERTEXT = 77e2b508db7fd89234caf7939ee5621a - -COUNT = 10 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffe00000000000000000000000000000 -CIPHERTEXT = b8499c251f8442ee13f0933b688fcd19 - -COUNT = 11 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fff00000000000000000000000000000 -CIPHERTEXT = 965135f8a81f25c9d630b17502f68e53 - -COUNT = 12 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fff80000000000000000000000000000 -CIPHERTEXT = 8b87145a01ad1c6cede995ea3670454f - -COUNT = 13 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffc0000000000000000000000000000 -CIPHERTEXT = 8eae3b10a0c8ca6d1d3b0fa61e56b0b2 - -COUNT = 14 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffe0000000000000000000000000000 -CIPHERTEXT = 64b4d629810fda6bafdf08f3b0d8d2c5 - -COUNT = 15 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffff0000000000000000000000000000 -CIPHERTEXT = d7e5dbd3324595f8fdc7d7c571da6c2a - -COUNT = 16 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffff8000000000000000000000000000 -CIPHERTEXT = f3f72375264e167fca9de2c1527d9606 - -COUNT = 17 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffc000000000000000000000000000 -CIPHERTEXT = 8ee79dd4f401ff9b7ea945d86666c13b - -COUNT = 18 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffe000000000000000000000000000 -CIPHERTEXT = dd35cea2799940b40db3f819cb94c08b - -COUNT = 19 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffff000000000000000000000000000 -CIPHERTEXT = 6941cb6b3e08c2b7afa581ebdd607b87 - -COUNT = 20 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffff800000000000000000000000000 -CIPHERTEXT = 2c20f439f6bb097b29b8bd6d99aad799 - -COUNT = 21 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffc00000000000000000000000000 -CIPHERTEXT = 625d01f058e565f77ae86378bd2c49b3 - -COUNT = 22 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffe00000000000000000000000000 -CIPHERTEXT = c0b5fd98190ef45fbb4301438d095950 - -COUNT = 23 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffff00000000000000000000000000 -CIPHERTEXT = 13001ff5d99806efd25da34f56be854b - -COUNT = 24 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffff80000000000000000000000000 -CIPHERTEXT = 3b594c60f5c8277a5113677f94208d82 - -COUNT = 25 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffc0000000000000000000000000 -CIPHERTEXT = e9c0fc1818e4aa46bd2e39d638f89e05 - -COUNT = 26 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffe0000000000000000000000000 -CIPHERTEXT = f8023ee9c3fdc45a019b4e985c7e1a54 - -COUNT = 27 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffff0000000000000000000000000 -CIPHERTEXT = 35f40182ab4662f3023baec1ee796b57 - -COUNT = 28 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffff8000000000000000000000000 -CIPHERTEXT = 3aebbad7303649b4194a6945c6cc3694 - -COUNT = 29 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffc000000000000000000000000 -CIPHERTEXT = a2124bea53ec2834279bed7f7eb0f938 - -COUNT = 30 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffe000000000000000000000000 -CIPHERTEXT = b9fb4399fa4facc7309e14ec98360b0a - -COUNT = 31 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffff000000000000000000000000 -CIPHERTEXT = c26277437420c5d634f715aea81a9132 - -COUNT = 32 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffff800000000000000000000000 -CIPHERTEXT = 171a0e1b2dd424f0e089af2c4c10f32f - -COUNT = 33 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffc00000000000000000000000 -CIPHERTEXT = 7cadbe402d1b208fe735edce00aee7ce - -COUNT = 34 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffe00000000000000000000000 -CIPHERTEXT = 43b02ff929a1485af6f5c6d6558baa0f - -COUNT = 35 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffff00000000000000000000000 -CIPHERTEXT = 092faacc9bf43508bf8fa8613ca75dea - -COUNT = 36 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffff80000000000000000000000 -CIPHERTEXT = cb2bf8280f3f9742c7ed513fe802629c - -COUNT = 37 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffc0000000000000000000000 -CIPHERTEXT = 215a41ee442fa992a6e323986ded3f68 - -COUNT = 38 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffe0000000000000000000000 -CIPHERTEXT = f21e99cf4f0f77cea836e11a2fe75fb1 - -COUNT = 39 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffff0000000000000000000000 -CIPHERTEXT = 95e3a0ca9079e646331df8b4e70d2cd6 - -COUNT = 40 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffff8000000000000000000000 -CIPHERTEXT = 4afe7f120ce7613f74fc12a01a828073 - -COUNT = 41 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffc000000000000000000000 -CIPHERTEXT = 827f000e75e2c8b9d479beed913fe678 - -COUNT = 42 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffe000000000000000000000 -CIPHERTEXT = 35830c8e7aaefe2d30310ef381cbf691 - -COUNT = 43 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffff000000000000000000000 -CIPHERTEXT = 191aa0f2c8570144f38657ea4085ebe5 - -COUNT = 44 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffff800000000000000000000 -CIPHERTEXT = 85062c2c909f15d9269b6c18ce99c4f0 - -COUNT = 45 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffc00000000000000000000 -CIPHERTEXT = 678034dc9e41b5a560ed239eeab1bc78 - -COUNT = 46 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffe00000000000000000000 -CIPHERTEXT = c2f93a4ce5ab6d5d56f1b93cf19911c1 - -COUNT = 47 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffff00000000000000000000 -CIPHERTEXT = 1c3112bcb0c1dcc749d799743691bf82 - -COUNT = 48 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffff80000000000000000000 -CIPHERTEXT = 00c55bd75c7f9c881989d3ec1911c0d4 - -COUNT = 49 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffc0000000000000000000 -CIPHERTEXT = ea2e6b5ef182b7dff3629abd6a12045f - -COUNT = 50 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffe0000000000000000000 -CIPHERTEXT = 22322327e01780b17397f24087f8cc6f - -COUNT = 51 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffff0000000000000000000 -CIPHERTEXT = c9cacb5cd11692c373b2411768149ee7 - -COUNT = 52 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffff8000000000000000000 -CIPHERTEXT = a18e3dbbca577860dab6b80da3139256 - -COUNT = 53 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffc000000000000000000 -CIPHERTEXT = 79b61c37bf328ecca8d743265a3d425c - -COUNT = 54 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffe000000000000000000 -CIPHERTEXT = d2d99c6bcc1f06fda8e27e8ae3f1ccc7 - -COUNT = 55 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffff000000000000000000 -CIPHERTEXT = 1bfd4b91c701fd6b61b7f997829d663b - -COUNT = 56 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffff800000000000000000 -CIPHERTEXT = 11005d52f25f16bdc9545a876a63490a - -COUNT = 57 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffc00000000000000000 -CIPHERTEXT = 3a4d354f02bb5a5e47d39666867f246a - -COUNT = 58 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffe00000000000000000 -CIPHERTEXT = d451b8d6e1e1a0ebb155fbbf6e7b7dc3 - -COUNT = 59 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffff00000000000000000 -CIPHERTEXT = 6898d4f42fa7ba6a10ac05e87b9f2080 - -COUNT = 60 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffff80000000000000000 -CIPHERTEXT = b611295e739ca7d9b50f8e4c0e754a3f - -COUNT = 61 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffc0000000000000000 -CIPHERTEXT = 7d33fc7d8abe3ca1936759f8f5deaf20 - -COUNT = 62 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffe0000000000000000 -CIPHERTEXT = 3b5e0f566dc96c298f0c12637539b25c - -COUNT = 63 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffff0000000000000000 -CIPHERTEXT = f807c3e7985fe0f5a50e2cdb25c5109e - -COUNT = 64 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffff8000000000000000 -CIPHERTEXT = 41f992a856fb278b389a62f5d274d7e9 - -COUNT = 65 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffc000000000000000 -CIPHERTEXT = 10d3ed7a6fe15ab4d91acbc7d0767ab1 - -COUNT = 66 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffe000000000000000 -CIPHERTEXT = 21feecd45b2e675973ac33bf0c5424fc - -COUNT = 67 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffff000000000000000 -CIPHERTEXT = 1480cb3955ba62d09eea668f7c708817 - -COUNT = 68 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffff800000000000000 -CIPHERTEXT = 66404033d6b72b609354d5496e7eb511 - -COUNT = 69 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffc00000000000000 -CIPHERTEXT = 1c317a220a7d700da2b1e075b00266e1 - -COUNT = 70 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffe00000000000000 -CIPHERTEXT = ab3b89542233f1271bf8fd0c0f403545 - -COUNT = 71 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffff00000000000000 -CIPHERTEXT = d93eae966fac46dca927d6b114fa3f9e - -COUNT = 72 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffff80000000000000 -CIPHERTEXT = 1bdec521316503d9d5ee65df3ea94ddf - -COUNT = 73 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffc0000000000000 -CIPHERTEXT = eef456431dea8b4acf83bdae3717f75f - -COUNT = 74 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffe0000000000000 -CIPHERTEXT = 06f2519a2fafaa596bfef5cfa15c21b9 - -COUNT = 75 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffff0000000000000 -CIPHERTEXT = 251a7eac7e2fe809e4aa8d0d7012531a - -COUNT = 76 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffff8000000000000 -CIPHERTEXT = 3bffc16e4c49b268a20f8d96a60b4058 - -COUNT = 77 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffc000000000000 -CIPHERTEXT = e886f9281999c5bb3b3e8862e2f7c988 - -COUNT = 78 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffe000000000000 -CIPHERTEXT = 563bf90d61beef39f48dd625fcef1361 - -COUNT = 79 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffff000000000000 -CIPHERTEXT = 4d37c850644563c69fd0acd9a049325b - -COUNT = 80 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffff800000000000 -CIPHERTEXT = b87c921b91829ef3b13ca541ee1130a6 - -COUNT = 81 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffc00000000000 -CIPHERTEXT = 2e65eb6b6ea383e109accce8326b0393 - -COUNT = 82 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffe00000000000 -CIPHERTEXT = 9ca547f7439edc3e255c0f4d49aa8990 - -COUNT = 83 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffff00000000000 -CIPHERTEXT = a5e652614c9300f37816b1f9fd0c87f9 - -COUNT = 84 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffff80000000000 -CIPHERTEXT = 14954f0b4697776f44494fe458d814ed - -COUNT = 85 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffc0000000000 -CIPHERTEXT = 7c8d9ab6c2761723fe42f8bb506cbcf7 - -COUNT = 86 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffe0000000000 -CIPHERTEXT = db7e1932679fdd99742aab04aa0d5a80 - -COUNT = 87 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffff0000000000 -CIPHERTEXT = 4c6a1c83e568cd10f27c2d73ded19c28 - -COUNT = 88 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffff8000000000 -CIPHERTEXT = 90ecbe6177e674c98de412413f7ac915 - -COUNT = 89 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffc000000000 -CIPHERTEXT = 90684a2ac55fe1ec2b8ebd5622520b73 - -COUNT = 90 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffe000000000 -CIPHERTEXT = 7472f9a7988607ca79707795991035e6 - -COUNT = 91 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffff000000000 -CIPHERTEXT = 56aff089878bf3352f8df172a3ae47d8 - -COUNT = 92 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffff800000000 -CIPHERTEXT = 65c0526cbe40161b8019a2a3171abd23 - -COUNT = 93 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffc00000000 -CIPHERTEXT = 377be0be33b4e3e310b4aabda173f84f - -COUNT = 94 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffe00000000 -CIPHERTEXT = 9402e9aa6f69de6504da8d20c4fcaa2f - -COUNT = 95 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffff00000000 -CIPHERTEXT = 123c1f4af313ad8c2ce648b2e71fb6e1 - -COUNT = 96 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffff80000000 -CIPHERTEXT = 1ffc626d30203dcdb0019fb80f726cf4 - -COUNT = 97 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffc0000000 -CIPHERTEXT = 76da1fbe3a50728c50fd2e621b5ad885 - -COUNT = 98 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffe0000000 -CIPHERTEXT = 082eb8be35f442fb52668e16a591d1d6 - -COUNT = 99 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffff0000000 -CIPHERTEXT = e656f9ecf5fe27ec3e4a73d00c282fb3 - -COUNT = 100 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffff8000000 -CIPHERTEXT = 2ca8209d63274cd9a29bb74bcd77683a - -COUNT = 101 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffc000000 -CIPHERTEXT = 79bf5dce14bb7dd73a8e3611de7ce026 - -COUNT = 102 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffe000000 -CIPHERTEXT = 3c849939a5d29399f344c4a0eca8a576 - -COUNT = 103 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffff000000 -CIPHERTEXT = ed3c0a94d59bece98835da7aa4f07ca2 - -COUNT = 104 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffff800000 -CIPHERTEXT = 63919ed4ce10196438b6ad09d99cd795 - -COUNT = 105 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffc00000 -CIPHERTEXT = 7678f3a833f19fea95f3c6029e2bc610 - -COUNT = 106 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffe00000 -CIPHERTEXT = 3aa426831067d36b92be7c5f81c13c56 - -COUNT = 107 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffff00000 -CIPHERTEXT = 9272e2d2cdd11050998c845077a30ea0 - -COUNT = 108 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffff80000 -CIPHERTEXT = 088c4b53f5ec0ff814c19adae7f6246c - -COUNT = 109 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffffc0000 -CIPHERTEXT = 4010a5e401fdf0a0354ddbcc0d012b17 - -COUNT = 110 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffffe0000 -CIPHERTEXT = a87a385736c0a6189bd6589bd8445a93 - -COUNT = 111 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffff0000 -CIPHERTEXT = 545f2b83d9616dccf60fa9830e9cd287 - -COUNT = 112 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffff8000 -CIPHERTEXT = 4b706f7f92406352394037a6d4f4688d - -COUNT = 113 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffffc000 -CIPHERTEXT = b7972b3941c44b90afa7b264bfba7387 - -COUNT = 114 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffffe000 -CIPHERTEXT = 6f45732cf10881546f0fd23896d2bb60 - -COUNT = 115 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffffff000 -CIPHERTEXT = 2e3579ca15af27f64b3c955a5bfc30ba - -COUNT = 116 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffffff800 -CIPHERTEXT = 34a2c5a91ae2aec99b7d1b5fa6780447 - -COUNT = 117 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffffffc00 -CIPHERTEXT = a4d6616bd04f87335b0e53351227a9ee - -COUNT = 118 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffffffe00 -CIPHERTEXT = 7f692b03945867d16179a8cefc83ea3f - -COUNT = 119 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffffff00 -CIPHERTEXT = 3bd141ee84a0e6414a26e7a4f281f8a2 - -COUNT = 120 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffffff80 -CIPHERTEXT = d1788f572d98b2b16ec5d5f3922b99bc - -COUNT = 121 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffffffc0 -CIPHERTEXT = 0833ff6f61d98a57b288e8c3586b85a6 - -COUNT = 122 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffffffe0 -CIPHERTEXT = 8568261797de176bf0b43becc6285afb - -COUNT = 123 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffffffff0 -CIPHERTEXT = f9b0fda0c4a898f5b9e6f661c4ce4d07 - -COUNT = 124 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffffffff8 -CIPHERTEXT = 8ade895913685c67c5269f8aae42983e - -COUNT = 125 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffffffffc -CIPHERTEXT = 39bde67d5c8ed8a8b1c37eb8fa9f5ac0 - -COUNT = 126 -KEY = 00000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffffffffe -CIPHERTEXT = 5c005e72c1418c44f569f2ea33ba54f3 - -COUNT = 127 -KEY = 00000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffffffff -CIPHERTEXT = 3f5b8cc9ea855a0afa7347d23e8d664e diff --git a/pycryptopp/testvectors/KAT_AES/ECBVarTxt256e.txt b/pycryptopp/testvectors/KAT_AES/ECBVarTxt256e.txt deleted file mode 100644 index 2f804e4..0000000 --- a/pycryptopp/testvectors/KAT_AES/ECBVarTxt256e.txt +++ /dev/null @@ -1,641 +0,0 @@ -[ENCRYPT] - -COUNT = 0 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = 80000000000000000000000000000000 -CIPHERTEXT = ddc6bf790c15760d8d9aeb6f9a75fd4e - -COUNT = 1 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = c0000000000000000000000000000000 -CIPHERTEXT = 0a6bdc6d4c1e6280301fd8e97ddbe601 - -COUNT = 2 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = e0000000000000000000000000000000 -CIPHERTEXT = 9b80eefb7ebe2d2b16247aa0efc72f5d - -COUNT = 3 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = f0000000000000000000000000000000 -CIPHERTEXT = 7f2c5ece07a98d8bee13c51177395ff7 - -COUNT = 4 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = f8000000000000000000000000000000 -CIPHERTEXT = 7818d800dcf6f4be1e0e94f403d1e4c2 - -COUNT = 5 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fc000000000000000000000000000000 -CIPHERTEXT = e74cd1c92f0919c35a0324123d6177d3 - -COUNT = 6 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fe000000000000000000000000000000 -CIPHERTEXT = 8092a4dcf2da7e77e93bdd371dfed82e - -COUNT = 7 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ff000000000000000000000000000000 -CIPHERTEXT = 49af6b372135acef10132e548f217b17 - -COUNT = 8 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ff800000000000000000000000000000 -CIPHERTEXT = 8bcd40f94ebb63b9f7909676e667f1e7 - -COUNT = 9 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffc00000000000000000000000000000 -CIPHERTEXT = fe1cffb83f45dcfb38b29be438dbd3ab - -COUNT = 10 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffe00000000000000000000000000000 -CIPHERTEXT = 0dc58a8d886623705aec15cb1e70dc0e - -COUNT = 11 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fff00000000000000000000000000000 -CIPHERTEXT = c218faa16056bd0774c3e8d79c35a5e4 - -COUNT = 12 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fff80000000000000000000000000000 -CIPHERTEXT = 047bba83f7aa841731504e012208fc9e - -COUNT = 13 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffc0000000000000000000000000000 -CIPHERTEXT = dc8f0e4915fd81ba70a331310882f6da - -COUNT = 14 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffe0000000000000000000000000000 -CIPHERTEXT = 1569859ea6b7206c30bf4fd0cbfac33c - -COUNT = 15 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffff0000000000000000000000000000 -CIPHERTEXT = 300ade92f88f48fa2df730ec16ef44cd - -COUNT = 16 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffff8000000000000000000000000000 -CIPHERTEXT = 1fe6cc3c05965dc08eb0590c95ac71d0 - -COUNT = 17 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffc000000000000000000000000000 -CIPHERTEXT = 59e858eaaa97fec38111275b6cf5abc0 - -COUNT = 18 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffe000000000000000000000000000 -CIPHERTEXT = 2239455e7afe3b0616100288cc5a723b - -COUNT = 19 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffff000000000000000000000000000 -CIPHERTEXT = 3ee500c5c8d63479717163e55c5c4522 - -COUNT = 20 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffff800000000000000000000000000 -CIPHERTEXT = d5e38bf15f16d90e3e214041d774daa8 - -COUNT = 21 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffc00000000000000000000000000 -CIPHERTEXT = b1f4066e6f4f187dfe5f2ad1b17819d0 - -COUNT = 22 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffe00000000000000000000000000 -CIPHERTEXT = 6ef4cc4de49b11065d7af2909854794a - -COUNT = 23 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffff00000000000000000000000000 -CIPHERTEXT = ac86bc606b6640c309e782f232bf367f - -COUNT = 24 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffff80000000000000000000000000 -CIPHERTEXT = 36aff0ef7bf3280772cf4cac80a0d2b2 - -COUNT = 25 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffc0000000000000000000000000 -CIPHERTEXT = 1f8eedea0f62a1406d58cfc3ecea72cf - -COUNT = 26 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffe0000000000000000000000000 -CIPHERTEXT = abf4154a3375a1d3e6b1d454438f95a6 - -COUNT = 27 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffff0000000000000000000000000 -CIPHERTEXT = 96f96e9d607f6615fc192061ee648b07 - -COUNT = 28 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffff8000000000000000000000000 -CIPHERTEXT = cf37cdaaa0d2d536c71857634c792064 - -COUNT = 29 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffc000000000000000000000000 -CIPHERTEXT = fbd6640c80245c2b805373f130703127 - -COUNT = 30 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffe000000000000000000000000 -CIPHERTEXT = 8d6a8afe55a6e481badae0d146f436db - -COUNT = 31 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffff000000000000000000000000 -CIPHERTEXT = 6a4981f2915e3e68af6c22385dd06756 - -COUNT = 32 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffff800000000000000000000000 -CIPHERTEXT = 42a1136e5f8d8d21d3101998642d573b - -COUNT = 33 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffc00000000000000000000000 -CIPHERTEXT = 9b471596dc69ae1586cee6158b0b0181 - -COUNT = 34 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffe00000000000000000000000 -CIPHERTEXT = 753665c4af1eff33aa8b628bf8741cfd - -COUNT = 35 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffff00000000000000000000000 -CIPHERTEXT = 9a682acf40be01f5b2a4193c9a82404d - -COUNT = 36 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffff80000000000000000000000 -CIPHERTEXT = 54fafe26e4287f17d1935f87eb9ade01 - -COUNT = 37 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffc0000000000000000000000 -CIPHERTEXT = 49d541b2e74cfe73e6a8e8225f7bd449 - -COUNT = 38 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffe0000000000000000000000 -CIPHERTEXT = 11a45530f624ff6f76a1b3826626ff7b - -COUNT = 39 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffff0000000000000000000000 -CIPHERTEXT = f96b0c4a8bc6c86130289f60b43b8fba - -COUNT = 40 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffff8000000000000000000000 -CIPHERTEXT = 48c7d0e80834ebdc35b6735f76b46c8b - -COUNT = 41 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffc000000000000000000000 -CIPHERTEXT = 2463531ab54d66955e73edc4cb8eaa45 - -COUNT = 42 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffe000000000000000000000 -CIPHERTEXT = ac9bd8e2530469134b9d5b065d4f565b - -COUNT = 43 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffff000000000000000000000 -CIPHERTEXT = 3f5f9106d0e52f973d4890e6f37e8a00 - -COUNT = 44 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffff800000000000000000000 -CIPHERTEXT = 20ebc86f1304d272e2e207e59db639f0 - -COUNT = 45 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffc00000000000000000000 -CIPHERTEXT = e67ae6426bf9526c972cff072b52252c - -COUNT = 46 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffe00000000000000000000 -CIPHERTEXT = 1a518dddaf9efa0d002cc58d107edfc8 - -COUNT = 47 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffff00000000000000000000 -CIPHERTEXT = ead731af4d3a2fe3b34bed047942a49f - -COUNT = 48 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffff80000000000000000000 -CIPHERTEXT = b1d4efe40242f83e93b6c8d7efb5eae9 - -COUNT = 49 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffc0000000000000000000 -CIPHERTEXT = cd2b1fec11fd906c5c7630099443610a - -COUNT = 50 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffe0000000000000000000 -CIPHERTEXT = a1853fe47fe29289d153161d06387d21 - -COUNT = 51 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffff0000000000000000000 -CIPHERTEXT = 4632154179a555c17ea604d0889fab14 - -COUNT = 52 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffff8000000000000000000 -CIPHERTEXT = dd27cac6401a022e8f38f9f93e774417 - -COUNT = 53 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffc000000000000000000 -CIPHERTEXT = c090313eb98674f35f3123385fb95d4d - -COUNT = 54 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffe000000000000000000 -CIPHERTEXT = cc3526262b92f02edce548f716b9f45c - -COUNT = 55 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffff000000000000000000 -CIPHERTEXT = c0838d1a2b16a7c7f0dfcc433c399c33 - -COUNT = 56 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffff800000000000000000 -CIPHERTEXT = 0d9ac756eb297695eed4d382eb126d26 - -COUNT = 57 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffc00000000000000000 -CIPHERTEXT = 56ede9dda3f6f141bff1757fa689c3e1 - -COUNT = 58 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffe00000000000000000 -CIPHERTEXT = 768f520efe0f23e61d3ec8ad9ce91774 - -COUNT = 59 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffff00000000000000000 -CIPHERTEXT = b1144ddfa75755213390e7c596660490 - -COUNT = 60 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffff80000000000000000 -CIPHERTEXT = 1d7c0c4040b355b9d107a99325e3b050 - -COUNT = 61 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffc0000000000000000 -CIPHERTEXT = d8e2bb1ae8ee3dcf5bf7d6c38da82a1a - -COUNT = 62 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffe0000000000000000 -CIPHERTEXT = faf82d178af25a9886a47e7f789b98d7 - -COUNT = 63 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffff0000000000000000 -CIPHERTEXT = 9b58dbfd77fe5aca9cfc190cd1b82d19 - -COUNT = 64 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffff8000000000000000 -CIPHERTEXT = 77f392089042e478ac16c0c86a0b5db5 - -COUNT = 65 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffc000000000000000 -CIPHERTEXT = 19f08e3420ee69b477ca1420281c4782 - -COUNT = 66 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffe000000000000000 -CIPHERTEXT = a1b19beee4e117139f74b3c53fdcb875 - -COUNT = 67 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffff000000000000000 -CIPHERTEXT = a37a5869b218a9f3a0868d19aea0ad6a - -COUNT = 68 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffff800000000000000 -CIPHERTEXT = bc3594e865bcd0261b13202731f33580 - -COUNT = 69 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffc00000000000000 -CIPHERTEXT = 811441ce1d309eee7185e8c752c07557 - -COUNT = 70 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffe00000000000000 -CIPHERTEXT = 959971ce4134190563518e700b9874d1 - -COUNT = 71 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffff00000000000000 -CIPHERTEXT = 76b5614a042707c98e2132e2e805fe63 - -COUNT = 72 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffff80000000000000 -CIPHERTEXT = 7d9fa6a57530d0f036fec31c230b0cc6 - -COUNT = 73 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffc0000000000000 -CIPHERTEXT = 964153a83bf6989a4ba80daa91c3e081 - -COUNT = 74 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffe0000000000000 -CIPHERTEXT = a013014d4ce8054cf2591d06f6f2f176 - -COUNT = 75 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffff0000000000000 -CIPHERTEXT = d1c5f6399bf382502e385eee1474a869 - -COUNT = 76 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffff8000000000000 -CIPHERTEXT = 0007e20b8298ec354f0f5fe7470f36bd - -COUNT = 77 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffc000000000000 -CIPHERTEXT = b95ba05b332da61ef63a2b31fcad9879 - -COUNT = 78 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffe000000000000 -CIPHERTEXT = 4620a49bd967491561669ab25dce45f4 - -COUNT = 79 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffff000000000000 -CIPHERTEXT = 12e71214ae8e04f0bb63d7425c6f14d5 - -COUNT = 80 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffff800000000000 -CIPHERTEXT = 4cc42fc1407b008fe350907c092e80ac - -COUNT = 81 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffc00000000000 -CIPHERTEXT = 08b244ce7cbc8ee97fbba808cb146fda - -COUNT = 82 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffe00000000000 -CIPHERTEXT = 39b333e8694f21546ad1edd9d87ed95b - -COUNT = 83 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffff00000000000 -CIPHERTEXT = 3b271f8ab2e6e4a20ba8090f43ba78f3 - -COUNT = 84 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffff80000000000 -CIPHERTEXT = 9ad983f3bf651cd0393f0a73cccdea50 - -COUNT = 85 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffc0000000000 -CIPHERTEXT = 8f476cbff75c1f725ce18e4bbcd19b32 - -COUNT = 86 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffe0000000000 -CIPHERTEXT = 905b6267f1d6ab5320835a133f096f2a - -COUNT = 87 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffff0000000000 -CIPHERTEXT = 145b60d6d0193c23f4221848a892d61a - -COUNT = 88 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffff8000000000 -CIPHERTEXT = 55cfb3fb6d75cad0445bbc8dafa25b0f - -COUNT = 89 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffc000000000 -CIPHERTEXT = 7b8e7098e357ef71237d46d8b075b0f5 - -COUNT = 90 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffe000000000 -CIPHERTEXT = 2bf27229901eb40f2df9d8398d1505ae - -COUNT = 91 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffff000000000 -CIPHERTEXT = 83a63402a77f9ad5c1e931a931ecd706 - -COUNT = 92 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffff800000000 -CIPHERTEXT = 6f8ba6521152d31f2bada1843e26b973 - -COUNT = 93 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffc00000000 -CIPHERTEXT = e5c3b8e30fd2d8e6239b17b44bd23bbd - -COUNT = 94 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffe00000000 -CIPHERTEXT = 1ac1f7102c59933e8b2ddc3f14e94baa - -COUNT = 95 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffff00000000 -CIPHERTEXT = 21d9ba49f276b45f11af8fc71a088e3d - -COUNT = 96 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffff80000000 -CIPHERTEXT = 649f1cddc3792b4638635a392bc9bade - -COUNT = 97 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffc0000000 -CIPHERTEXT = e2775e4b59c1bc2e31a2078c11b5a08c - -COUNT = 98 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffe0000000 -CIPHERTEXT = 2be1fae5048a25582a679ca10905eb80 - -COUNT = 99 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffff0000000 -CIPHERTEXT = da86f292c6f41ea34fb2068df75ecc29 - -COUNT = 100 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffff8000000 -CIPHERTEXT = 220df19f85d69b1b562fa69a3c5beca5 - -COUNT = 101 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffc000000 -CIPHERTEXT = 1f11d5d0355e0b556ccdb6c7f5083b4d - -COUNT = 102 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffe000000 -CIPHERTEXT = 62526b78be79cb384633c91f83b4151b - -COUNT = 103 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffff000000 -CIPHERTEXT = 90ddbcb950843592dd47bbef00fdc876 - -COUNT = 104 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffff800000 -CIPHERTEXT = 2fd0e41c5b8402277354a7391d2618e2 - -COUNT = 105 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffc00000 -CIPHERTEXT = 3cdf13e72dee4c581bafec70b85f9660 - -COUNT = 106 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffe00000 -CIPHERTEXT = afa2ffc137577092e2b654fa199d2c43 - -COUNT = 107 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffff00000 -CIPHERTEXT = 8d683ee63e60d208e343ce48dbc44cac - -COUNT = 108 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffff80000 -CIPHERTEXT = 705a4ef8ba2133729c20185c3d3a4763 - -COUNT = 109 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffffc0000 -CIPHERTEXT = 0861a861c3db4e94194211b77ed761b9 - -COUNT = 110 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffffe0000 -CIPHERTEXT = 4b00c27e8b26da7eab9d3a88dec8b031 - -COUNT = 111 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffff0000 -CIPHERTEXT = 5f397bf03084820cc8810d52e5b666e9 - -COUNT = 112 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffff8000 -CIPHERTEXT = 63fafabb72c07bfbd3ddc9b1203104b8 - -COUNT = 113 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffffc000 -CIPHERTEXT = 683e2140585b18452dd4ffbb93c95df9 - -COUNT = 114 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffffe000 -CIPHERTEXT = 286894e48e537f8763b56707d7d155c8 - -COUNT = 115 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffffff000 -CIPHERTEXT = a423deabc173dcf7e2c4c53e77d37cd1 - -COUNT = 116 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffffff800 -CIPHERTEXT = eb8168313e1cfdfdb5e986d5429cf172 - -COUNT = 117 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffffffc00 -CIPHERTEXT = 27127daafc9accd2fb334ec3eba52323 - -COUNT = 118 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffffffe00 -CIPHERTEXT = ee0715b96f72e3f7a22a5064fc592f4c - -COUNT = 119 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffffff00 -CIPHERTEXT = 29ee526770f2a11dcfa989d1ce88830f - -COUNT = 120 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffffff80 -CIPHERTEXT = 0493370e054b09871130fe49af730a5a - -COUNT = 121 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffffffc0 -CIPHERTEXT = 9b7b940f6c509f9e44a4ee140448ee46 - -COUNT = 122 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffffffe0 -CIPHERTEXT = 2915be4a1ecfdcbe3e023811a12bb6c7 - -COUNT = 123 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffffffff0 -CIPHERTEXT = 7240e524bc51d8c4d440b1be55d1062c - -COUNT = 124 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffffffff8 -CIPHERTEXT = da63039d38cb4612b2dc36ba26684b93 - -COUNT = 125 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffffffffc -CIPHERTEXT = 0f59cb5a4b522e2ac56c1a64f558ad9a - -COUNT = 126 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = fffffffffffffffffffffffffffffffe -CIPHERTEXT = 7bfe9d876c6d63c1d035da8fe21c409d - -COUNT = 127 -KEY = 0000000000000000000000000000000000000000000000000000000000000000 -PLAINTEXT = ffffffffffffffffffffffffffffffff -CIPHERTEXT = acdace8078a32b1a182bfa4987ca1347 diff --git a/pycryptopp/testvectors/SHA256LongMsg.txt b/pycryptopp/testvectors/SHA256LongMsg.txt deleted file mode 100644 index 47943d9..0000000 --- a/pycryptopp/testvectors/SHA256LongMsg.txt +++ /dev/null @@ -1,263 +0,0 @@ -# CAVS 5.0 -# "SHA-256 LongMsg" information for "s" -# SHA-256 tests are configured for BYTE oriented implementations -# Generated on Wed Feb 08 14:59:33 2006 - -[L = 32] - -Len = 1304 -Msg = ebaccc34d6d6d3d21ed0ad2ba7c07c21d253c4814f4ad89d32369237497f47a1adabfa2398ddd09d769cc46d3fd69c9303251c13c750799b8f151166bc2658609871168b30a4d0a162f183fb360f99b172811503681a11f813c16a446272ba6fd48586344533b9280856519c357059c344ef1718dbaf86fae5c10799e46b5316886fb4e68090757890539617e403c511a4f78a19c818c2ea2e9d4e2de9190c9dddb806 -MD = c907180443dee3cbccb4c31328e625158527a593b878de1b8e4ba37f1d69fb66 - -Len = 2096 -Msg = f6ce8221bf64273c91c4cb41ebba1bfcfa12c043c701317eb0c0cb66157a230c53689b1df63b33652abaa29373aca63c9ef89822f80b43b5bd7af6dad3e8d8ecb82b7c00baaab56e6609ac8d42092fbdbfa94cab69921fd061b1e83b0d2660910e5d4e52727a555d2bfb10b7c0986188436e0566835d6cd682afc8102afa65033b4738998873ba3c63d6f7995623e1a4148febdcae36d3d00ababfe2922d8c4b2931635f635d8d12f5e388bc6a705a191854259453e3fcc5e01bf538ac877f70be62f62b6b0075e8c96aeca7664972f03905dc16d82d8ebdec1a919ae2cfe67ae4241a8608241bc5c7b34ae2b074d1305de937eba7dc32c116febc909bcf687282bdf7f7a290 -MD = efd35c0d49e6a22c2b54599abb0dfa419435a5b749ef1c7123d59a2fb5db8f75 - -Len = 2888 -Msg = 1c5b8bdf2aa1a8feb0acf02f3fda16ebbc8bccaf053386aad7ae80b9f0d40296704ee34d85a84cef47a6be89e1dc5657f27950363364cb58598acb3b3d7684dc3a22d628d60c14b3a58d09ac6b663d11819c741f7a87780d052518f915b47123407f6c5965f888b29207da7f25a2527f319e3f5223c41530a5286edbc2b650d24b0eaec87a923154d6bc38ea56b61d0ac924bab775442b2bff3ad6c98ba5a9532376a35d5d02960238562bd548ca261a13d9eb37ba2f4165dc0457abb7a9050d9060530155713f22827abb284107f618d562dcb838ade046032df9698fe9ea685a74c79aac07b51e7ad2f1cb8a94146ad86a952339e48f363e5ec4ec5b8ee3cc48590611a8eb7f5ce906d4a76b9a087ae4971c6103ffd69d533fc11a63bf75a124b8184f9246254696be6ca22b415bafc1917b59de243de30b77f7dceea52a4fb438063bb23f30424ba1c2a514b094703601baf2147c4d702eaf6f1b4567893ec182d7bc4fff27bace -MD = 9d2bc3b2987a7274e05e74e3cc566440296832a28643884b49bfcd6ede1057ff - -Len = 3680 -Msg = 2ddf06cb013f9267b1e5c0bb535d7d54572ad06d170a0e58ae7c4d1f0e801a6a4d9e6fa34029df594bc514e277277b45c51c3e57c3cd73235c41938ff4232d3db5c6dbb0236676b0f7b186ef2a85fcec50fc241827a6d5387015eb0afd9ff62b0c5f3438d37dbd335caffe29930068129ed169f96c1d9c5d91013dd6517bdffcfa72618478f61eac23ca64dadb1f287f57a3f742baba305b670b713c173f4f7729054adc395affe1f307a048296ba2fb247ab53b3806f9f99b3e6f847874ae653e23d7873e30ca9c75709abba66b3f4ead5f8b2b0f886001d59f1ff69ba1638ee4d1f0cfb000e6a3510c3b7d7aa7673f9959615c66c8cb39bc3869daa94ed8bac1197dfab753bbbe2ee369d5cca7839890711f14664fa36bf9103677c90374b17d0266517aafb1b7b4fe0d0ac4f4f91f3caeae9c37a4515d342f6c1624499f3ac194931c229f30558c6410658c15339d4218f43c00503bd8149ef5ffe1a7c11f35d8eca3d6a8a05f5e1d582e499297d94db7da3bead9cba34164b77a29a6422680d55a2dbf54699ed132cfad26f48f9d039448e31cc9688864899ccf24cc8b184a94c304042af3da8eaa5c2949c182af0cb6277abea7794d25168b45f9a402bc3d1b116ecfb2a7da3d8de6ec -MD = f14720e0e460e1b0c4be8e44b25bf4bfae05267749c1ef4f33e0ac35176712f4 - -Len = 4472 -Msg = 5ba171c9571cf2b394b38724eedca061e72955ad021cefbe6c3eaa72e16bb9bfce708be8b3d84df7cc02b067f077ec21b97b05aae5e24c9afc252a5033b519e4918ff35d50116f24860ce8b9051a61a57f32c7b0ee797553325bfe70fcdb2641ec27318ff67061240af8ba82f46d08d581752327e38a72d35608ae3c0484e8be2660cee56d9c2adda0efab2a8617e899066da2778dbc4900b053c21a13596844896151c97c3ed2399019451983c109da5841cb08b4b804c48865c374f002adb95b5342a2edfe621f219d0fb8b312747ebd1a26422026ab06256639b16426bf07e55d2ad78683e1769ca4916dddb3306f7e203c8e98ac44aed07daa39376da7146fa88fd210765728495554a1cb4b4593e27a9452e5f5d9a3d1d2a07431816cca415cfcfa527ecc1c70d9dfbd4383bcd43351b7f7cfa771cf708ea2ca1907160fa2a0f6b71644493a5957ba270e039c19b7cc2be61e6b1519f5d939a3b9aaaecddc9c07712270d56a4cf86e49f472ed49b8147a869ae8cc69a7daeb67d7103beb3579b6903fa9799490e4828abc78b84e7c502b3e0bc79ea7cfba437e3ce1c551f65f8b7c35973ca06e427e5130be040f4ca9c77838af93bbb5a0c650b0c655e766750f9ecce326762e3aeb0816ecd9746f47d59bea49b48ea1b5fe45fb66f195cfe4c95ccc353fff18f6501637aa3f652f51dd0fe93d0806db2172c6e46ba44377d3421ffc349021739b35e35b9e3fcad2f0683bfd32970caa0baa39347a73d9a76b0050258920c5895422d74973e0 -MD = 81197ebe77012c262a00d99888e261dd28fe6ff91aa1f7cb4e487f3561aad9f0 - -Len = 5264 -Msg = 19172bbbd984215e9c6e0508dc3c34f2f5a710477cc1f640d335708dfad0abf8a8402b459b1cbd5c2c25adaa26cc3ac4d8f4474d69f8531b6cf0ab95b430de5f6a12723a5cf6d525988696c83a3fd513822df9232af5a165f619dcfd8c789c6986146861c6185202091a292cbf9def291bda8d8f66c0c66798396a8e29afcc5c25cf75847f8c1a3ba767cc9d5eee6f4cca836d5ac55fac697bd7bd1034dd56816ec902692f5a171899f7e8e2bf3b3dc5b7b1004cf1dc39b2c67b3d4b540a21208a8c75d97f882fe10852e6c4898b41dc0bebae2c8f3e578ca2ad5207323f1781a0a0389c16204cdd1bfe2c0b65e763d8eebadfc44a8eed3d37f6640b76841febd98bb17a9e295555fb85247ffa568b0387a5fbdac7d3e20eacdddb20c7df21a85dd74a3bbcac3291cf6f35e7f1e0a1a3ff346a37b11520472aeb1f0ecd5a06fe530b6aa61ab0cbd9c042c60df18d8d017def95a3ae5d8e30d8a6989d31fcb436e3b07885603d0875f68841b7a36637652a5fe2e566b21411df98ae949bcd1497374dde9e365bd1ac98c80daeae7287162e0bbac7831c9a316649cabdb2d60e6b746a03b942130ec8cf8b92babcba665eb07b860faaa308d9964052de1f1e8bf8c5904fa02f6ca70fc25838a27244ba83d838ac86855046519705b0c08aad718850452a1aa36f84ca9ab767307a1a6dcecfc996f4bc2a3de190204a2b998caa613d14fcee46238d407e30872a7c446587bdb6aa21f739d3d1a91a8ae7f7c21ccbb5822de5c290abbb974c00591fc88cf6ca8852d4dd86f1680c79d7bb4a57b110e01925c7bcbec4810c923a850cb0c8631cc6f5d7161880efdec898703b544f77e5604d5cdfb6c1db068b9e76eb040315def8faf04bf866ae4a8c37ce71c0e047ecdf0b6bd07f8b11adbd92f363ca245536a7 -MD = 8dfdfb63612074044698085316cb4ee2032127c72425269eca374173aa60df95 - -Len = 6056 -Msg = b37f522011a07e325b88bae54cd1c64ac6aaa89e21d8a06ec3fb5efef01373ece44206111fd4c8a8017c2ab296e0cd99b358391342f3d349dabc0939933bd058183e507cfdd9ddfa53ab2a0b7a63b97537839667066445a4b27af9e322da077676f9992b53b7a7707a9c23baa06174277ab226621732e0c772c096c748f9ff8e27fd4ae4c8760d519ed77e85afe2e5f6a36d51cb1a658af9431348acab9ea2e852d2c970041ff6e7e6e5a13550eff42cda3d7f6cba062d834dfd7759f3d4d7cc20fe8097b0ba4c787b4df6922a8e891049a8180b9d1cb0adb7058b97c9a08681b90bd520744df64d8597e363e6ca8ce9153884716baffbbfaab4ec2ed50c9750448132d5f7e2dcae2b4cd2722ba8e50069752c66cdc8f6014d9002e6be1ff381e9e6fe7ce280e6e295f32a85a2327d9d6be676b16a6d89bbc92336872ce1805cd2c4a1dedc30fc33ec145365f26f3a074313cb1ceca99c3445f5eed8c95b272824a283c38ef906e75837b5dac46705881a84946df88117b5ea8c93a23a94d12f0a090cf39fe3ec4700e5b8abc023c76618c2376d39ffe286df728ead2a9464b7aa80a435b8f6969b0da5c4a28daa66ea64541ee4542ae5ef4d2f45c13f64ca092c8fb352813bec2ba6004185d404cc5c27c2af9af40a09385c4922a6210be96db9bea113a1b9d73ef47d971d3c3adf0488955456bfa834a8334a8c237991ab2a7996d63dc1783d1e1fa42e326e538929b05474e25d0b4f88fbbaeb02effff68a939eba9b888108114efd6e8c1157b015c6877604773b4320db1fa6092a5cb4d32f5eb5f49fdb1e60a911c0f2ce4f3e0ef3b6c485b541f6b8fc032701d3b0cc4e775f300fad8e695359678a2d4d421a5d5f6ac52cbe24529886edd5b191042643912891b55ba3cf318687350635382c4a312ae1c33bec3e08a06618e30d5faafaa54242ae51213a4457fa2a422f395c1c927f8010d3a2a14f72f5585defc940badc33a9c2361091d2f547d0ace24e921da9f00add2f4d65b62522fde8de4ad0cd5d8530b9b379bc2488f68e0bf77eb6939f05e7f0f6 -MD = 54e0c23db7b3fd43e6c7b947d2585480475c2080815744ea40268fd0886e7954 - -Len = 6848 -Msg = a10c4b7bd10fc6bd35a7f0ab6951614de7ef81397a6e9d5af5a63bf02481abd80360df0e2eba7d70990631c481dc48fda2577bbaabbd0810ef6208895dc9fc6cb20da93fed7f268b039133dfd5f3cc175ffbfede324afa7224ad68a84641fd2f16db5018f6a6e996dd0e9b034ddd152485a4b3aef75d9a09fc4e0353c731d7a897917da13177ef1a8e461439d1e44aac7c1a4131e23e105ce00f8295c8e0b1609ef9d7e1873a609f7e014488494e9335ab255270dc3485f336b68d733197b4dd91d907e0de3664ab1507d3f89d6419497c8d8b71cb882157670ccbf7ea9e08a9dafab4a620b421c8bb1f6a91b56e046f5619963e99830b0fdcd9e528db3dd44cdf24873c33fcc27dd813b15c79b47c30a1931bdf2c6a6ca3fce5820eedbc404c0a1e27a901566d52d4a94f60d27da812c6c1c15a6e886b9c2ef74bb206627633c2b23ef5700a4bd017aaeda5a613b09f2b6b31b945243181dcd9e81b0f789b886ea671296a5f837e09dd3234dfbcbd5f395b13049b85e5da6d510051f146dad478c36a4bd69e3de5130cc71463c1f7d958580e4157f4b03049283b5d9214599e47d1d1669b10a38b9bfd534d1c6a8595f129ca7a61b9ba09d8264346dc2a406e43984d7fa3fadafa0b797fe8f0fe8f1b6a97f0b6a11c2af08112bd14b6cfb8ccd4df87a0d5a70dbac948f3ecc9c73ff42d6a28feff65286aafb554d0074de941627027d0195e62513f3256618e0bbba7a06a195963dbde01c7d8ae81b9eafa545511d41857660149d3ff505027132bbc2d5e6ccfb5c7723c3241732fb3ef138e158b367e7708132aef768bc07b27b8bb3b10c868dd710ca358b94ce2dda45e760aa6f60d628cc07afa61acb9748e8a2d3146d62dc321d5bfa107e1a31f5000949d29bccafe3a2fc35c865e43f992c89a79c93e254f1ff41776f5d979613c247034de2fbf3459898c7cad4767f3799a887a61a7586ab292343d49dc6d8bb1f093398bf8f3ed33f55ec4a00f2c488c29819cd5b9cffa24d79c60cc948685f58c8412f9bf6e0f0e9cc09b265f9be1139d0c47ef1d91e8bbead94546a6cc375021cb29f02b398333a63a6906dfbaa6561eb2e3757ba61dc0f473567fbd478a0cd7f1e438e45b32ea3a54970936937f9cd2f9d8307a17807a1cf0f93e7f006470d57dad9893dc037b80978bf70c2e552fe46c8fe8c3ebf8338bda -MD = b057d3eebc727da07a2dfbdbd6b4d6617dd7195771daf7de563c2919c8632cfd - -Len = 7640 -Msg = 8390cf0be07661cc7669aac54ce09a37733a629d45f5d983ef201f9b2d13800e555d9b1097fec3b783d7a50dcb5e2b644b96a1e9463f177cf34906bf388f366db5c2deee04a30e283f764a97c3b377a034fefc22c259214faa99babaff160ab0aaa7e2ccb0ce09c6b32fe08cbc474694375aba703fadbfa31cf685b30a11c57f3cf4edd321e57d3ae6ebb1133c8260e75b9224fa47a2bb205249add2e2e62f817491482ae152322be0900355cdcc8d42a98f82e961a0dc6f537b7b410eff105f59673bfb787bf042aa071f7af68d944d27371c64160fe9382772372516c230c1f45c0d6b6cca7f274b394da9402d3eafdf733994ec58ab22d71829a98399574d4b5908a447a5a681cb0dd50a31145311d92c22a16de1ead66a5499f2dceb4cae694772ce90762ef8336afec653aa9b1a1c4820b221136dfce80dce2ba920d88a530c9410d0a4e0358a3a11052e58dd73b0b179ef8f56fe3b5a2d117a73a0c38a1392b6938e9782e0d86456ee4884e3c39d4d75813f13633bc79baa07c0d2d555afbf207f52b7dca126d015aa2b9873b3eb065e90b9b065a5373fe1fb1b20d594327d19fba56cb81e7b6696605ffa56eba3c27a438697cc21b201fd7e09f18deea1b3ea2f0d1edc02df0e20396a145412cd6b13c32d2e605641c948b714aec30c0649dc44143511f35ab0fd5dd64c34d06fe86f3836dfe9edeb7f08cfc3bd40956826356242191f99f53473f32b0cc0cf9321d6c92a112e8db90b86ee9e87cc32d0343db01e32ce9eb782cb24efbbbeb440fe929e8f2bf8dfb1550a3a2e742e8b455a3e5730e9e6a7a9824d17acc0f72a7f67eae0f0970f8bde46dcdefaed3047cf807e7f00a42e5fd11d40f5e98533d7574425b7d2bc3b3845c443008b58980e768e464e17cc6f6b3939eee52f713963d07d8c4abf02448ef0b889c9671e2f8a436ddeeffcca7176e9bf9d1005ecd377f2fa67c23ed1f137e60bf46018a8bd613d038e883704fc26e798969df35ec7bbc6a4fe46d8910bd82fa3cded265d0a3b6d399e4251e4d8233daa21b5812fded6536198ff13aa5a1cd46a5b9a17a4ddc1d9f85544d1d1cc16f3df858038c8e071a11a7e157a85a6a8dc47e88d75e7009a8b26fdb73f33a2a70f1e0c259f8f9533b9b8f9af9288b7274f21baeec78d396f8bacdcc22471207d9b4efccd3fedc5c5a2214ff5e51c553f35e21ae696fe51e8df733a8e06f50f419e599e9f9e4b37ce643fc810faaa47989771509d69a110ac916261427026369a21263ac4460fb4f708f8ae28599856db7cb6a43ac8e03d64a9609807e76c5f312b9d1863bfa304e8953647648b4f4ab0ed995e -MD = 4109cdbec3240ad74cc6c37f39300f70fede16e21efc77f7865998714aad0b5e - -Len = 8432 -Msg = 491b02a46a098a5c96c4d541d1961c7e2b9a15bb37690de6bff63733b6b744616e0633400cc66b703849076b197171c5801632b363a808cb8e16390a95ee281b0dc526d6fbd98a088df5047208952e14024b64abd161d67843c0db43901089a08c218271218a10acfd90755e88497cf0190154a969dc9e7548bdc5e58e678e7655e2f016652125e4f0e1013880d483e32dffaab81360894b03d59ef879396027ced017cfafe5f039ceb15107d77f6a74a60e0dddb737bf81decf0f8538cf263b61b2a0a3e71f9a32ffc80cd377925a2cecf625223da7679f3f75bf92b37109387552329bf6174a58ebeedba447557a91677f9b8e8df9aa2d908d572ad26731a8717676bdc2152931fbeb66832f0ff32d807017299075afb438e07e527df8c512bfe7131334615f4795865477170aec889d9340fc2c629fbc9f36dd149c6dedffc66db2a53442132223884e89e78c8e2828aebf0e4a0aa1cb2d571b77170ed3f6eecffb79ab026e480bbafbc087de0097878a3b68d3b3de6b4a0ae183d6239c7f9fd795997fe79743b7e10424e0486b5d24ef5d10ada67d235e18d741c1f47322414b290d9a3ab69b8dc810bdd811f70065a5cd10c22ba77bd14aa4b8c1c97e683cf45edbe242f5d6f736c8945883cb0ab4733270f88984fc0b66f1f1bce9e5d8f99add0d41497a7e5bf2d3b049e4100378223536390a3b2d753465f29b9dd1fbde054eab9e956d1a23c5db19917ded71187a7d6c6cf4f597757ea9c5472d6a5754fc57bbe06ff733b67785d81a968bdefe43b3197990d9c0740a6472a7e1d776c449a347f11f40507cd07bf4ca7712d191457e4647261032dba13fffa20041e094b2d856b8ed6ff9dd9865758b67a9d3394887fac0fec175100be27622d4cf1b2e009ff11d21acb74196ea6444b0786b5e13753dcb5f150f7d10f4de0ea3aab1f8fb9f1f080221101093b3c8dd98a821686ff1175093348a88781e404db6f92a5c6a81e861d9f38eb25768a93d68617dc024a39138e0456e9b0a07a3c955e50cc016ec5410ee4db990aab00f4e67ca08ccfa32b2698f70411d8f570f69c896e18ec8896cfe89551810543303f7df0c49f5b94783cce7df8d76d0b88d155633302d46003711f233339b1c9a8c20164ec8a328890a4932b7d90d92d023b548e4820558f8bd327010929acb8db3b155b90e3f10a151c9b623ae4ca047dc32e6d35e7ec819074a4d14be7329b37f93e475a22f39366032bd49939ac1c6bd7278254c005d0c1c3fcf663e90feb5f8ac0ba90cdd6bf13d6e8d51105fbcf5d05e4605d4f3de7905fb3f2f9a57123a26e5127ed5af6e7af2636e64ad045a7b1cde98997fbf1407c864e5965b322deb1227401b840f097887fbaaaaf3ef6301a9dbb509d4ccc75f6f6408c408881670c358dfa8a1640693021c884a69899f2e803be67e5c83be2901e2f1e029c096704161354fb5162b746db04f6c983ad5aba8e873 -MD = f2aae44efd3e8c207b27ea2c85e99b9d3f66610b4749488782580fe2bf58c2f4 - -Len = 9224 -Msg = 5eed6c988deff49afc8ab1f95a3a8030096d663fdd3876fb2049f5a8d91dbdc94d73df37c7008c7195643633535df24a6c3a21a6dd934fb13c385bdff967d886e542b4f1f07f17b037628e313ee86995794662bc12917fa2e6bf39efd1ceddc92b4333ed92d65efeea6c031ca345adb93a7770a8039bcd7725c6d6ffe6bb9239295ea354346c2604b76adb1c0adb865fb7b69593381702d802357b38c294c17fe67c4e4d5fa93a69a5445f58fc12bc2ff7ec17a53a6fe66c83f470c2ecc230436a837a019af561d6bde2d7f9005216d002ff3f05900941dcb3ebfdc4ecaea82cbe5d70976db862f3062c8b269f035debe0d955dcc24fdbcf97036a664bbff0e2e9f07838605a0667880bc208608d59279a60a15159a77cee3922fed2905cd20ef326d90cfc4315db4b65c6c7cb59d22d367e6a8ddc7bebe1a031022d43ef1458e5e5dd3ac8dc57f65824dd8a68cd90a4bf1afab8d332f14fd419bea2ecdf7f67c617caeb4d8b9361b62e5079c0525a353a1b97f9c63456e1dec07a561494dbe49ea3e94611b993c36d6d67be5a51fa88b16b8a783ee9e23ec5107e744276f076757182749ecf1dc586c7697ebe3036442bf11b5ec3b95c0e91f01122ffed85c65469dd9c7c33fa0f0826a0e47559d711b19591d3db0c8efb4a477d88d261647b427341e7314ff248fb7152150632a5994a3f36fe104a3eabf9ff08d0433a533e4877f87d478acc186790c83cf9256781fed75008e9db35c6a6fffb1fdae01bb76d5d4885464b5229556a4a7fd798e774d5452818ee273bf5572f9ea020bb848db90d7a27b4fc4a20cce91f0627f5eb18d8710657a89718e0167738789c335569346fd58d1b047da8d5f491fa71a33c150e4431ed9e91932eeabf13d2d7b158f2e76ca3dc02cbb3677773e6833e0aa21480a4f301587e7587dcef75d4579b53d1d9ea2a3ff2b9b305ba4f67c81492e4bd347a92bb5fc78695f2efa7a6a65b0fad12d2b4dc7236472ba66e5cf27ea3ccb734af57443ad28efd36a7f1714c57542f9b0d87db0aaa358144b90d2801a520ab88298ac47109556ab0009a5dcff9e9ff7b82eb65427d46ae9b18c1932700a94036d273628dd3a28267e0ec91b9a898c4ba182aa2a317425bb374c25b771c2f1f48915a4715973fed63312d3691cb272661b98bb9b4e0f12f95b356a779627aefc54d869b91bff254acd9a673e0cc5fcf774c55d2fd411bd348bfc69fb6385159b6f040858ab2845f4bc29f712d12086404b8d11707a087eed47e5a6db5077d052261d02d87d8bdb547d25f570005ea9011e747ae5966fe2942da5936fe38c79a11887ebc109964ffa8f3304ee10dccf9a4c0febf7cfc482c99ba0d251a31f4c18c4d925aad5d43e4760c587e59927847c82b4073f6c82d9ee105bc5f905ccf219998532ee78c200dba04200eeffcb423821053f15134752723a5af0fe8201f6343510a61458ec4217cc5d0272cb34935dc57806214a7e77066812e5babe4ab2e8f60ff1a50cbf7c9c236b0f0971fff24dde90feec8894c21b281806b60123c2b87ad7a828eac80ad963f0892b8a99d988dac48bcf4416ce20f8def688f119a013221c3c189972974ffc81f3417b7ed3bf5 -MD = 8ea50b0ea8a41452b2a95125bfd10baf240db4b1764e11aa3693e07fa014c5ed - -Len = 10016 -Msg = 6726764e237d11dd9020a5eb4799a4f268d35cd7d47fcb6f9cb7b442b9e1f28ffdd70d9049450bfe015288d8bd82096141da8e68b04666cbfc39473ea1939e4993c72490743db2570bf55645f26ea6688ec6547a44220363ea5059fe7cab5620113fe4d70d2eafef975336bb4e24231237ddd797fadb4a3d4f45120bb3f2c11d5f8774ec7ae0a9cf8eb251c1396e276425683f463938e263116099ecac30884765e7fd57251b49fdd65bcfdf1b125a683eaeb4106a0274dd1ae91729d12d52a70ca7a7a174a737835996d79d5cd965256bf95d7bf301a7b15028b34b89b0c8433a0e9951d14b1a69fdaa9184648bf0a3958f62113dfd24e99d6596d93b839225d865fcefa3d09ab5ace1261b9bf0a2eba2b9ec5ab0be928de8e7e75b516c5755cff4f70352ff60714d81beea6acf24047cbf23ddb40b9aa319f7cf5a3234bfd90503b316469e14a4c8d3807a37f21df609e92e22b2aee43517dd765d46a374bb64da58afe6755e57051f95526b1f36ca337f35b1106d174acce103ecf5801b03d3c10d579c4ee491ebad25fb6f1f1787e0c862133811dbeb1f4b9f8fa7955fb739fffa95d0ef515a64c457fbaaba6735fa0ddbcf9062da1ff86271cfc4a8e5e180dd48f1e8214bba58ad53dc83b7cfdd6896c86d8227b9ee3f6fa233b48258888fa31ff34dac7abaadb1422564e0f68512ab5275752a2360dcba5944dfeb5eb54e99a624675888614c164c5fb4fb8538e094a170d131be7eb88bbf88aeaa9f6fa506060b9eed1ab81d249811dad123fbba98dce6fd05324fb92afc898789c5be7c3466315b32dbc508254fc3402a79d888012b5d636e28dbc8de37cfd34e75aabb69ef1c04f07092f65f98fe4dce2ed63215b75f6a33482bcef198e0fbc2593c4aeec95603ef8427cd1b9c486984ebfda01da8737a1e3946b1a9484665ad197b110b1b67bef7bd8a77a1822cfc155856bb602622fbf5a4345b4f6f897bd75d70f9070dd59fd0c3c5da39732f6e4a1ce8692858f2558130feb22a342fa407cc21e82cc92a0c413fe0e02b97db28e9e0bc93bb666df18a86aba084c0c247070e98c7c074ed6f14d9e170be15b790ba4bd82262791b35d84d430ca33bcace9dccdd7f0c39a72f0f38d2713c164b0f870646fc65b9838a322ecfddd0cccda092aef6f6583edfb4fb05bacdebc1200e16b80e0b0c4d2d5961d156fd539b5525ad5bed16ecab1d669fe7a26b143fbdf3300a36359f5da1082edde05374d1e9c5b87ccac60fa9eaadc5879133feb7aa279da4c864651368015efb76c77b9612e879b893ed0a60ccf1338c8f0df3527013252dcb7fa79509aabcd21e41af1156f6bab8527525f74d9ab29fa5e13938961e904e486ead0b0c6d0f0be2a95a6b405741230e45a896f5100a68d9971990a4afa5ae4619bf9efab11e4dcae7c2cb5573d6a2d045db674bbb038e3517db8223302df6cd68257559ddb241dde42f5a1fb343dd9f5d068fd70465bac149c7389a08f1cde64326bab45b938e2386eb40257d4f7b837570392151f793841625d7919fb6dc97920c92909289dda4b63da4ef3ac1258475628bb20b82c286643c8a905d47caea3d1d2777ea5cd6695d6cae06536282ab4524ad119bceeecf1d557720aa6b40e72ca2a1f0cbd3207961c188f12efa3bffcefec8c667a3c06827b8c6c8eee9e69547e228849db864dcac8457383551f788f638045ad9c9e0586cada011918a63fc7727e2b9c8d1499b24fd4664cf2e5f4fa6198854 -MD = 83e3d216d72dfa9cc5d076f6e6606ab276fee722df341ef3050c10a80358fa72 - -Len = 10808 -Msg = e254dae65dd3d1e9def3c3550b571ef84f494d9821f424cf8ad37e1ae169242cda33f188bfdb344efcae5655e150bd7ba4aeef39a535fb7bf64215ae1bd9801a0e99b17287efb1a9798bc308e010477eba10de375337cf6fc6c6a989c1432a5b886f60cd3d790ea25e7151958fff83a89a5560b9b4626756024983d25b11eb98509e47c069e014e0b24a492576863ba24b67bee74e1f8dd6b0b2ecb272aa8b796c0dae74948c8b0c7dfdf3df1e0b3513d52c40eaacd40797dae92a518d76d2a5e6a3dc1045e53bcdc87297ec0ef83aa4418e2dea53eb9e4287d585d634dd88c5c64a1bbd0553ebcc9a917d73ceb312fd9674cf0ecdca1a7fc0604769ef47748012e9b1a35b3e65b1fb42ed9de7a685c5dcc56c7fa0db43f58c71b634471c5f7fd467e7e9cf0e6f23f36d2e92e0375ba41b6b4d655784e14df3f11c5cc3c4116a13ae05b8e92bd2ca8bfa897941d05b445c4dbae7772fbb2ffdc6bf0ceca852e8d8a5533732fd564fcad1467a93d84f4aa653fa2d8a439a41b3d9e86a482eeaa12a34198f31edc25ab9daadbf5db7fd61026557601828462e1c12de9e61bfa03e11439ee76e61e0925efe056d27d42d2f776b17a8a745879c4059ebd1bfc43d6795ba2b6872c276a0c32398af7a99a95c0d4d832cc10425342897552be8a38ac3bf810839c4794d2bf032acabdc6d3891ccf3e315edcce79ddbb265d366c64cfb96817d84edec2ddceb148a89d8b8a176bd467f8ab406967f619463f2c1934eb622a0d26e7385dd5bbeaf7a72f3e3adb2e72c9eb49c18fa84c32397af7f74579d6cc74e21e0ab274f71edc38eb75424ee538e8abb2f6bdb52084948332ad02e587bdf3ac5bbc5d1610ab5af04ab74ced1075589c6f567019138edc0a5490e9c8e58cede818d3da43893ee84fd57ab72040d67e4fd757434ea5cf7452e659869e7097e827edd7a687d13828ba04462da2e6daee38937fb3b047b4e20f605d55d0d98d56ee433e4e5d793580c16f9ffccf82d11cd92c362df899ddc9924b12d3fa50cbde9da17e3e2ef1a584f86feec11095777ec3fa213e81eca88f7e1f208d95a6e1d3d8812df296cb06a9b19dc8f710bf2ca86b95b741e6d0b3a84544ecef1d1c5dcb017ab4080f75d763af61a52b3a307f1e42876ef481e67da86a64fe750b519e48baf6b6eb0382a647247409ca17b9dd44eb37beb30d9e75146fe7dbcbeac731c1677d9d281d61e1c8c31d7d4013bbc5b0b82f3d09c4592850c855fb3035eda6c98987dd2ba7a4287cfde66649c8b6c6e65be6605550a705f20627d35e67556bc5b3adfd725cb9c8b857675b33a11b6f5a28f5af423d189c7c9be5fab3096eff4a583884a88723711f4208c29a378a1d80b1c5904cd42e6a650c18e7ba96baefdbf9eff91ac1618026605342e9e6636ffe88eea9d1d048ee2fd92910f199c9abdf1b1cc1659604944214df42af4847c52810c9627d9c08965185af0cd48d1bb1d82e5783f56f7d1c16e1f55856d797bba1dbfe30aca1de015e940341ffeb11a05bc618a766d85b85f94a3dea7d1ed3b1d06cf5bafb8c49adcb86de46c02e4be5ee54e8a2264af0608dd0317f9e88ac5658263867c6b5cbfa1cc09881b1d13b00e46d300aa041fc4a38f6488e17af52078daa3ebdaaa8e584c6e3ba89617e6f6ff27197578157dfa18f3f1bac84ed9544056b812323e026bc4e62bcd44b8049a17d04771f35f70ae4f51cf34172ddc6aa33dca83eaf05f03f37c027e8dc716a34088867a83a9a1ea2ff1297e34dfa6698bd900c76c864d25c078e844d90ec31a6198fe1a90bdb8b5a21a2521892ce059df7083651ec876db132104a69053b4066248d6d882615c189015eba47cdc3242874b7be56a807f2cd4c07f2c1a5f906f2ae0373cc25e -MD = 5f3a2c2f3feab3dcc0757db4b07a3ae06fd928b7be833696fb2aebd31db18372 - -Len = 11600 -Msg = cefd0d77197e9cca59549d833dbf5b8d92a533a3b937a61259d2acc051234a6df18f663969d2db6681e6c9608b262efa96b3bbfbe517e0d9a0282ac4c82fcee6704a86ea2b0f9bbbc172438e26e92e22acce5c467704319d31ddcb9e003b93deb5f61292477e074f7fc2b615f450828c3abdbe8d5747c1e476b93855e08fc1dd275bb539a46744ad249cc8fedfa253c0aa498ad86d28b739d68419f14f737f692e4015e82c127d5a19c92150ce29c847623a682da1ee3b21b905157b372ef50c326fdaa7c6c6d8dfc5116a13a82b0aa8cc58ff96dbe377268705d5fa7f094c4d9baead7c5acd7dc58f3b4b4f57f1406b4e6af81a034d90cfa94c01760f4cacb4d2c63671d16d9594e1116b0dc2c39319523afac10175b1a485a240f7cf3f3cca3d7f1c8d11ef48d222597355d1e82b393f8eae94bda3002e84cf3a86a729251645a007d8039bbd09b9dc0a2d6caa2f537d2fbc9a1f1fa5f40e9a982a7f548e2152f3a15b8fb81dc01062d99f7b4fc8f074e5cbdc1030c97f8ccc02ec3f06a071cd3e8f1d9e908f808eb388b2e6201d978c778360761f9455642d1fd2cf8883901c4a7c2616693cd09b96be6e956557d02daf8e303b352d00008598e717225e06a9df0e7fe18c4c389fd423dc71669d23bf53915445b7bd08c69c1430ff1b5959dbc4ed2fe541e64002356003606a1819aa2c37d27ef06bf3203a3cb770bd9e1319c3c23e0ccf32712d811dec4bbbef39560225b4cc27604b7526b883504e52bbcda235b53c8059528680019d1b9f4b0b2b9d060219a3c3972d292f9c8917a0da5e2aed9b5f9a836c76fab520b65f541892c480c24cadbd60b00b4a0b0160aef7342393f85c66d74566b6e17d064331e7f1413bfe4d8d762d6594b0d7a271a49ab755ced51b2c7e67bc7d2cbaf2920b01b1dae0bd048b1586b68b09085291ab4c4f8847398434a05ae2173ee1619609ec3b58170859efc3f30abaffa7fb09eb936483a62c7fc563a43e4cc0f93d955432f68287e63400a7fdcae738ba84228bfa5e0f92b6f428f2cf3ae45a0b6dd8135a4922d95f7d07ea2b5cdb5c4cd521b306a5f4b3e0cba673633ca6b31ed9a76fed9efeb57b1c4cb306295e1462d6518d41a1fab2b1ec850fe6ae5b743a694a90725ce0c143f9172b15993808066ff93e32bae837323f0dede2f7cb446705089d71ea8ea8befcb079e01530df3f8860f1615988e969ad8836de7fbeccae952abf73b2d010f40e5ec7ef030f411609cfcc57e4a071601c3c1163aefcb41601f81dff1b70a2ee156b3acbcc9dd891da8ef79bc5f9761f7572a7f8ec4ca3a831bae09d8d3405b3fa1dfcfbd9a249bbe3e59bb5625ba1aca1721f25a178416b0db82fd570e6e14ba6bd350791e63f990d1ce02e258e9a118784a272354637677e3a33302d4ce0bf00920c785b3060353e7aed8d755908560ef05868107f2da46a8713352a2fa816efe6aad4a14a54965f48eb5ab985948120fd688e9aebca2bbbe8f86dd056e1585dff37a6cafac4c459cf011e5bdae59ca4f5fb6c3c51b70357a50a5e878b348e3126da733e0958c81254585fc220a4ae811e388b5c7a9c3428067092b89448bf53a3bbc5643fb7a9742217a8561f78c0a1c14872642f1fc714525391c93ac7f3aabe0323a6638a6f6680677e7f9f0ad9eb2552a9ba36ebc305d3dae12445563220bfda166b3f7822cfb5706ba567010147947fb9c857a630e2cf2e0c2f7d9f859ced67251c992acb990a59f6304006409d54f729f45cf916938f769a54aa4af30792d3d81f3a4772abc74ba888f2c19fd5aee181a80b8b7eff5bdb11fa93ff8547f445b7ddea781ded346d071545d925d8ea654a4b2e056f107b85fb88016542455be64bbe7065d64798e89d4001f7db8c50ad0b458b0ef2ad369bdf68bc2432e911de1b2b96b5a4a13de3f26fedc2c7da28de4cfdeb4f0ebed54646018ce55d1c5d54af8a221190e369878c0bd2e3f3aab92396dd156fcb2ca0adb7bb3950ccc486709044dd20a0f565fcf57d780167e54ca26f4cd3 -MD = 2328026cc8289db308359222e9ab8f13ccbff7f53fa1f9f579a52cfb5c46b267 - -Len = 12392 -Msg = 1d4243dd682c6036925438fd8db2748a64f597a5cec730eb03515474ce024bb2e48c8a9c7430e10cff3cf6666ad2f27b52ea7aad9f9ae1535c969c5fc6f3f63ea23005ffd476dcb82e1f0225867623930bbd06fcd975bf74cad926c38fac875400349b4eb187b700c605448208266f99387621dca3dd3215f624daea54b568bda6a236d032e9dcad70f7a4c5186a3e57801bb593255ca200877ea01b3b97ff413b81bdce8026b187d3fb0a35e0cbf8938cb6a96a887977fb26f0609d6cd9b6a768da1790c2c6a055981c5e1b85d00516034ee5a9f4bd19cf7b8002b91003f4b9d4b42e5e214f10e1665f88bf3202cea88eec519890aef1442d386eb74f9d203d2717e980c54b69f1e6ce70690de7b910d597d57f85d66521e5208cdf5030a4fc0b0c303dd541124ebf70ff613e092f187f5759a5fabdde304a3f45783c43e7be2699ebdf7aba75c09a4d1beeeef099863534c55318e9c537059d7fcc3a5f514a20c902acdb3df90e1f6ead5a45225d239e3701d107e480ffbd422321730b4a6aa2a15eed21520602f5da9eeb6a29e5b76367f567ee3679501b371ac00fcf3ae4542be5e973810462c599d4ea868d970a2bcd8a5df56516f1c7834af135338981dd6e80eafa535bf736b4399fc0d4dde39f6fa6fa46fbc1ac682e9dfc0dc09f09e6721836dd4f7489f132b45141881e0c665732870680e147a641fa28c0fde5441640931645feb5e09d1b2c493030c14b298d174c607add8b2bc348be7673c1fa16dfdbd25ae687c3e3788bd0b655306990173b917a731f409cbc710656a89cf28d57d6b2439153fb6b50b82cfb7ed22e42ff889e7cf20e2ea4345c488926dff524b16efe29877f51dcab9ba526330f61e84de5ba8f80121ce934f1cc3775f0cb83f48afd334e758adf911c8560fd4fcc2907392fdba493d413c318d9861b393c512811f88a709b711b0b2312d062fa35ae376e4387e6f91ccbeab9b9a1a220103655ed3755755bcd392098969fec78651fe46b3fbbceadbdb9b0bcb2ae920f0edc840502bde31c65e0d96357f42332242317186ba1e5157f841d090dd6716dffe8bd41a1ea444502b93c6c9ef88e8e3962d75d0e5eb29a29d439891240c9a2ab0506895b031f406c6b549cb2d2b5f56e852c22711dbda485530d2208152116dad969c57a31fd746b9f26d9ddab20d089341e4fdd048f9c59a7a0bd397c0231540ceddd449b6549c7fdbc0c65ab58855316b6cc983bafe86e78fa43eb9ef35be0479ab9026adf27472c1d1e93f9e47e94d4fb81eaeba5f28c6f249a67a27cfc48327942fbc5f376b5d551f5afbe4c211415f6571d3cfa217a3325acf5b1257c5274915e79d52a9ed79f617b012119d89a82ad34785535dc026d055fdcf37743c7b5ebf6c2c10b0775335496d04bd20af0c32a02425fde8deac5cd9d668ff9b96e9f8df31fb21f1a593832306664ff1edc7f75a7c4817e9bfbe2844dd9ae344611d8813bd8d0ec3d4a5703300993287e275e940d46e49c6efd6d32577e77ae537608cfb83542fcd90f38d07e0200d691990a911a0fafc06eb80ddfa29d13f14666d87d507e31d7577182a00299d490bff92873b8690b7203f46b94187ea98589a9ef95edfac4031d38de7ca41537df70116343ce9a203b95782f59a06862f08207f71e76f2240a952cf36b4cc0504a0ca7600843eb15a28c0d003422a566bc9b489521d3ae787426146a75e2e04859fb84caca01a41330507b862f877bdc703b3373a5ec76e9c737baeaa24ebe4694a6704792ef0d416b498a6a51b533ec95c99239b2a9929f8d32e41cfb78a2738473327f67f56ec8dddf0154a29514c0b2af2b8f50f249c14d7e5ba78748d3f7b0cb941c51fb0ecf0e7baaeb2b0f687d4f54c61b88afe5789083e7354fa79bf9a0175cc358e9367f85834bd8f30c754ef5202d8861c8acebdda94f6b597b40a1ddbd531e85a72e00ca61adc3027285592a7b277ce425e743bc585df3afae0b18ee2741d5df1e3e79657b9852612bdec679cd7b9f18aedda7b5f8d775592644865bbbee906e34ae12df3bd430171dc8be677ef29b054cd84051f186985dcd3313ade321f63bd2c5f5be0828032c328d697ef65415b3e51e3517ab3205c58920e56b06a4af4de1cc478d495d74a95074ee459e69b82b62f8af908fa36499445227 -MD = 09622f3ab1fadfe0b034fd22adeae053ebeab7720537dc8f6eb586d17b1a0bb7 - -Len = 13184 -Msg = 04364d756936036f67ba3abfd5919843af141ccd0b50b26b4f6705eca233959fa02d095e528dc6cb5db3c0da79c69090259bc80a9ad883c0fd59400bd8d2f0e5cbb64df07f586ebbdc5198407c2158b15f19ce74e0784c6ce7d4207a61bbad43ed9bc134d8df22c44c5b6af9c4ea152ec355d913c67736f5779f4d402336f5426ea20c3146690b70159add0e3b69f290bb198ff0341f68e514847065088bf068b794d6f0af4050469fd69a86c8e5155dae2b981213b60ac3254931f2f701c5402e38c977fdaa1bce53d6496952a8a62004549d814985461814b737eed7e19d4f3c588bd016f09191976491c0c3f8ce5e245c4646c0d4426b48962b6192739f1f49bac403e45adc16d4461a92021eb4a1780b3a685eeb264429aeb4530ffff437be271d164d2f24e573458de7f7628270672922ef0d111b2b1fc67bcd36cdc31f01673d133bb99087da2992c78a0b5d54597da5e4b48f49a992a827d6ef2535607c42ce01953e498373bad03ba3636fd4b6d06c4e3badd745ea1a6177224e7281968075e943077761a5c0f04a2ab0e078e7ea1e3589b3ed888fe5d1b7b791a10ab6e8dcd22c5c40aad70299fd073bd8c8529364a188e9b5f9ead11e9e9636ea834644abc43a84cfe57349745b224c7e4d6093e69b1f97542061a5f134a8857675ad5a8ac854c94a9ae05d296c632afa8e79b14b2a3604f5855d2bf182d3c56d6853f21fe46271da5286065f38b31f751306b63c57b679beb14729c78f0040f7e2a0d615224dc5a693cd0cbec8f87117656d6b6029853ed72b85681a63183c3a6dfccd128afb0dd7e81d36f0231c69070b189560a88c9b697b81b0930701026190cf9ebe23559194d6de4d9a51054f6e8d6dffe3dcb3d89c2aa1c8da82a5da92d48112c3f5439806e7781a675b9d6b7374d67092cee33c97bf4f7a96dcea0bf5bf7af1c608ae6c54a25362fc48ca043f47baaf1585021083c2f28c6f1ebadfb4db220372657c53a78fd7f004207664f98e81851309f99c87bbf1c70f4ffc9cf4b0e20f6c13979627376d8b25eb88d1cad292ba3463b128cc33b6f31b77988be0c420df5f1ae57dfb217bfa07b2e894da995716219a11fc7ab2a8d83e9e75f49da24539f183504f4cd56b06537d7ef5506e376182b60060b8be2f3d1ecd7d1f56cfbae6ca55bf5641dca377b152323b54d69a62fec0689baee1b3ec630c975331d4e6ae939819d803bd8d15c83becb0105be8e23ebf30f685a29cabb661abda563a3058f454481eb9008fa7413f949aa9848aa9eabb40b965895343bfd6a2faee8902ae949233708c2e13f7c36612424ad9e67fa9bc802c751f3e7c257262fc2147c3761c5ac215a4ce80cbf7b94ef019e3652c23cbd896deebc61d903dd42816feda7933b2dd5728683eec853f30ec3e296f7701ef3041c77653f0aa40e0c5f635b17f82a46c7c4185b5221401a17de2346d29eb31707359464ebb18826f1de875af50b13757cd16ac4d344c0587ec2d8ac50a88978075bce51d47850b677615453cb367738692d0656eecd755cc8246b5e1e2812c488f17db2a5c97e4b219a52dc0714c61e213963880105af95684563d27797df5b00892aedcc1f614364ebfb5a3520908519791aeeb6980f70f3d84a8019725fca12a57e89a404ba3dd5c8b664e1e4671bc68e84e17bfee59ddf4f980d6032148013b8b10ce9f3e9a8d8d32c7279daaa20cccc4a06cda4f27aaf0dc4c0e8618e1ba8459afdfa776003027dc619797dea5270c4d2d538149675d7a569511e8b3d0b24de74c35209cddad73b0ba07d38a82f770aa7c327e8423deda8fe246f1991cd3de5d6f38d2573aecb9d75cdd1a553f633f04167297a9621558aebb176872cd037ee4a15085501ed54179cf8334e7e652c382817c95602dea3cdca8eb17e8ec2c76a468e5002f915052bc995fe9e97eae424d47b73f508b45cd40322bc4a17f350fc44f5f0c9b9b4535cb44db0103105e058cef8a5f22840e5403e03d384591068e6cdb26713c459c33cc585d43dca34a5468025fbb7e202d194c3b8a3b7d27873ec696a2f7bb963d92e85b4f781d3f5a7709079d1d0a688a6444ca7a95f14ba066f7073b65c097109a46d718686dec76b59686ab4b71630d7d1215760d4804394d2ab65a85f24efe950f5320db75b386573808f30d59199fabe0a4e46c2a5b3a3c852c651dfac5edc96a58cf99dd9b72a51614dc2d6b932638d3002d7a41568b7b30f0c6f67f04c67f806d8d694cad22e75932ce714ed88b6a15b0baff32001452548ae3d82a1172ff781ac2156af07e6528ea31a3aaf0b78ace3c -MD = 4228ed1c7ef246538e4be2584b7c60308565a25d35d128963fe8d340d40e125f - -Len = 13976 -Msg = 738d923a0b694b60e246cecff04c6d1cc6d9e1b270d347c79f3c688f08063daf0729b3f488f4ab4527a045d6962b5e9f3f64570d2b4218f7237955d3154f102ab9ac60497371703a7c0bcaf23d48d6ccfb699d36b978d3aa5adc15e1072a6f43d03e21a1968ba32628afe68bac4add8b41113c97e21e80ca8d8a2f1fa53e61e296067f64b7e84bf374b32009acda7bc45883bb966edc253e05ae2bf7b934eeef512d01fa9f307088a84001d505a0b95f89e8a29d2459ccee076e92d009b31e524ada30cc160c1acd0c7d10557f439e441c687a13cd3e7cc2def2eb115f64faf3c9369240e42452aae793d5f2e16c335c592aca6031323ea2d163be2481ef89ba1569b1bfd01f1f0783a9d814f5c27f8d87571aeb18de197627e9947037fbd490789a15b2a3a58acc26e8a22481ee8ac0f016f31e4ae9152629abf35d4b30e15b38f2447f25609ae11978ba884e975cdeda90db608efc3a9a1fd266538338ba059e98c8901ef5572ea480a8aa2466fecd8eed5c1aaebf91bb518572baa9b86774f2b4294b560fc99c0e28f5f1cb0377775454feb270d9216f06eda1fa835bee927c70ed1a9554f911a19a28c40a15cfc273ed48919df3f29f87327a7bdac6594583f29e64a26cee76a3fbc98daa440e9835e1c21ffdb40d341d7b85a675a4b0775162c3904600b0b45d7660b3743a3de0e058f4c457c579140ef04be11e9bf90f2ce9e50849b848b11730769e2d9c6482bd7967e974cd3e29a2bb53959b533ef55daf8b33733bbd57195492b5a0158965146da2f41d7565592301252bb57686112cdb3d798b32178daa083d62944bb6732d5c2d4f1865f58ed7ed4a0934a9da4be09584425b445f3a1374fe0dd0e6f2934f6d91602d44f6af08a44999e096418bc307e6f6a91a9c489dc25d1c1d8f46adc4c8559126bb71a4fc51aa4281e5c3b91b56edfd3e5bd69e8d17e2f843eeb8aad2960149ca716c55fb1af66bde3e68bd31ad21c0e2b015242e9e16090aaa5370c2ff1eefe00ff2aa4f27b47ec047397f4d3209a55cc162c2c77c80b73a6b1ce8dc2a33ed313c088b3fa16ce2efab3de7b70d2d157635c4609fdca96b9adb1dfa6740c8aa85a1b8e012b0a7ff33107cdeb6671579f6b544e6ffe4178bf3a05d8fad68658ea3e50991117beb3d541fff4a93684a37a5e8e93c2fbc54810d62e48df4cb930155b10486842bc304197fcd15973753b94b77bb4b778de8b3b0cabbde8590d96b61adafa7b3e7b4bc4bd8ee2507fdb865b009c2f91f7f598ba47fe968a8e0c034908014dde5d848cdb2d46b642ee102a59b47072f6eb9316fb02a7615a4e3cfc4aad33b0e6326069f16194bb8530cb8e0d6d891d6ad64f7c99e736bcbc3c08e84774d2a2376f8769a3f4f960bbda5627d276668d425a734003401cf744ba085dabf97eb0564762127f51f5544b5d588e6579695131bab6f7c3b7daaf785aa3d2f4958869a75ca8eacff318f4b83c4b3822e121f79da9730a57a8e043cb9073decde3901ccf3194593262c4c086f996ab973820ef0a99400e3bbdde62b2fde0d7746e26682248ecf4232b89463c17d36f3f08d6b5fcfca659ec41257ac2e58363a49fabda4524eb323eb7e7044c0979e986bdc3dad9560e93e5ed460a7ff9d3f9bae2a0c19c384799c1826e793b5102a10ad178cc4437f142b51cb0804ebd4b0043f195dcbbf56aa1783580238e80f62c47ee5608b214e6dcd65a057ab382612dcc26fb7a190eccdfbf2bbc81ba1bdcf1aa5eec2ea76f67c8d62fb55842ebaeb8b00d623837d6f6ab02ef741242841f87becdbb9c98c9ec9d10f830b7817b9c679c1f4a759cd070a9effb5753cc4c4655019544e10a96fdd0235e1806d394a280ecd714e0bc9db342d2c9d6d49bf6e9ffff50088a716913f899cbdbc4cde969bb2ebf61d82b91470c57f5630345f662df248886f771b2b77cc0cbdc8fe4cc4a6cde52b1ea4e5d946cebe89c6e6edd5978fda930b66ff650e354d8cab6acbfdd2c781b7585a94533fb0b2dd3846b0e2664072ca655d0c688b2b26d06d77a569a5088843d38d0faae2d323fb8d3bf2b6216cdad58445885c76156132170f202fa9f8c17698239f05b79fd98acdaff978507ad85b7004bc69585dc459b019867866fff6f9ae068a8c477d9b3300890f517cd435043284f0b5b76a18ee407c1d6b6386ed731d1c186919d3329e2fb17a692ce1b87ad1ab6c6b1ea42498d0222e3128f36f8dee4f93c1b60a6772620e82e7e8092b62556377b11273b20066f200f13db044ef288541bfa48b00579f8a71f438b45467c7935aaf1d3f88cd0dd4ddd42b233440d3a86c886dbdc5f7f00c8db7a54afd2f2e235e8fc6706fa8cab00b0279b60728f89f5a47980780f75c7d2059b633ec6292fac876956e2f39a76ed3a2afd084519d525322aed3f702ebc37001f4d8eaa9fb02e38e13a29027abf77ddc55 -MD = 070a01b15b49be7fbc5707b3a3350555fab1abd7ba57bfc71b3b6e8c8b9556f6 - -Len = 14768 -Msg = a0e1e1c6ddfa6af33d5cf86e9f01ef1a250b345880fe93d86e2d5eaf807257a92122d0e0d440118dbdf1fa1f6330ea8ab4c3dfe24a6ede28ec66956458083ff33fcbc823927431fdfc893762b0072f5a645735a89d7f85a22e96293ffb7ad57203c50fb69efc92ea020af5600ced88313eb07fd3049952ed3ba36369f32ee2cb74f6edc28042fcfdd85e7d40024abbb748b4048a04240bb11b778b0ac88e2da99b47ac6fc1ac37de856b172b178791958c4c0ef627887998d7f8e949000180b27ea093e4e8a40a34111b0a49d50ad2731261e33ef42d64487610c44f25eea18e27eae94a7d913fa88554a0c1c33c46f8e0d9cc8cf37c946900a66644bebf59e69e0bf7c808db9ce1e8001fbc6985b4cd009e1105addbd0a47ea1154f54db7062e9ed058712e9ea884206d061504ee69a7a96fad3a9b3e1a1f7eb1a986eaaaea912765aaf2225f0449c4efbd9fffda20654abcf1e6f6d9007736bbd489494db6421904067c1f678befdc0e84bfefcb1b998c4d70d886fa37efa0945874f01be3a1c22fdd776c4489d6d44dee0d6b1db5c4ec85bc97b23e2b095adfc7c255920d40d14da28c9f82a8af4c227c00e86e7977ca1a37ad0f017424b3f2850a004c9d9fb4e1f8242f8e32d9b2209122ee19f112c36f746103d08df25a7122a486a81f2efb7140c6a2d3e2d694ccdffbf2cc973656f9f58c2747e2d29cd0233a4f410c7f03901efc8ff02336728baae48ce2e643034e2d66efc41d4619a3f933c083dff06bb2d52e5d7f6e69b9f1a47512f968d946d0ae99d3d197dd5f413719810d1433926e15e471be4ef0f9733f462b7c99599025db8d59fced08cc5c4f54172953a9260653b783592f5cbf94fdb04ce8e2647db246ca18a27748ef39b49be984e8d18520110008bc8a1d5aeb424bedcaee5a7e1a62c8666ee12e367e09297e8c7e3d4e4fd056587509b379daaf81949f27cc0fa2d210e9be951940adbfb55ccc7e5ccffa044318ff18af9ad7b7f9c7d1f939a0fff72c091e1daa7c3d4a97fab153b0a8933f2eb0d721621c86de0cfe100d13e09654824b09d54277912c79dec7a8c966cfe3a1c689ce8b9d5ca443adb5cdfb3cea7cbc361e7681916de7b37f9be80768e49424b0837a8c8bbd8d266d4fa6401480d22240a85be878180edd639a9c0b4d95c3200550bfe5764e0b3da35a309315ddf76d01540fd78a24047011402f458337e33c4b7df906db7290e1e641f764af764ee4de8e0cdf56165ae41f293c46886f96d1d967c09129cfd0cbbcb365254fde5b325ed2dd805a6394c1d3b22d6eeb91307965aab0f4efba2d538d0b0465857aaecdf8aefc3b05902491d5778d5f1b41529b46b324a2abc61901ddd54f95cedfbc20429ed39fe6209cdc9af5d677a5f47fd0131d964adc88265f359eb146ba7205d1b31f0e0f8a996ffaaa9993490a2f0a804156a02e0054d7d40ac3d3e8a6d60e4ac0ac060a517f10747aef3e53b655955457dabcfc95c0a008f3d1220c3270580401b25620e92610e282734228390cb2a4dd2667072b50016657632611dbd55585ecee78e39032f3cd67a2492710b8c4fa37d6190e3f978e54cbe65aaa11799958e8acd8b3053a4b8d8118bde0cbee4edcfe465d5230eba98cb7d72a3551d185e58b8a002fb6806abb65231ae5d911d2c5a7139e739de0e556b1c22f343b81cdc45be289aa02c9d3cf9a7dea86a6d7e33cb8ba76f3050bc44b2013d4373ceeb36dc052dfc2986b394287759773d384e2baa9975150d4b0b8f2a958b3aeb48ce95a5f577cf9d5d8edacb296bc1dedcd63b80056c80dab9455b5b40d381b50f0d2129f6cdbc059b77376b27dc2f533f5e8cd33654599f81b0d3cc6bdfbfd90af001ef71f96b6827b6d38fd87468a64b2d462e94f547628b941c057c759d5d20bf5e80ccc183cee993d5bfa4fa15dfe68d90168716f32dbf3b618edd5ec34b3bc15f6271eead40c9566583f338dd04fac492157781040705ecc8f0f462d8aa423f2d1fc64890c4af46ad642df4691f6e1b75b2ccfc23f945ee79b22b4885831c81ef3f3596d56583acd2e9baf760372ada6176ee50f809678a9d5ce9da71ddb3cfce4825a223282dd0ff9b03096b5516497de746452a4153085c7695de44c0ee71f2c4fe32231795fa5a006ef132801ab0f28f3aa262a9f1b0dd89991da835b5ae823a270f7c39a4720ba264795cc01e56e7f6333147482ac9491c5c5f4342f0d0a7330a01d796407f3b094e67921d0a8485a29ab88226e49dc7b8466bbdf2871d88360ecfdc37526b12bb92847ba0c682f41dd500ba4b087280e4bf0bbf4a63de4ecb9b433223c37cb7429a98c0503a985bef4ed198c07f919c282f05f1546a5a207a1923826279fb5326cc6b08364f0ee29e6bf2c48c2f42420cfe22fa1785db27ccf03873fd5e300ded92c4fc58eb2bb3b4962de5b702cd9a19942a839b9da78a48894aaefb59620e21536d43c0f738f3b93648a34adf79cdd65ae533e9980772774a21da6451da7d49762c86765c7dcd33b20ca84cad8f03ccb61bb308604307df9c84a04130e183ee65ca6d80004267ac744199c5565763811193aa00dba3700ae8 -MD = 9e4c602ce1eca142f4334587312e5af9b08bfd18c333c5e31f5484992312aad0 - -Len = 15560 -Msg = 7c7c49a8a31b68934e15cac10a53018d95246ce9e9355bf575be75d0aef957adc6d87e2abbf767de94d0f431e82e12719fe49922fcbe7495dcb801bc386eba3cf1d416c4cd27aa9dbc239483617719b4cd768d468e0f73bde8ffe6dd624538bd85d6d81de09379f94f78705f7d165e7da84310fea410a39723fbecdc3366175908488ddefc231c1ad436526b45f329f5b7b3eaf248a94b481414da61b4b99f370491fdae29bfda27d3c40052c0f6c243822fe2c981c2b2fb43b37a13eb271a800019f036704ffc49d58c42baf6087091911dc12b584321d6393e929be296ce5b85482e1ed8bbcaa761f5e24cf00f7d046de64fc2d314e0017d1feba0a1ef04f11a867e0d6aeb8c6aff67a6afb5f42fc69df35433fd1d37a597bc4dcb2e1b0469473baaab2dc78ab9374a588b4da0cfffa9ab9829db476eea107f80c4930116ec94cf78a129380cbd9207be8ac1faa4d61a75e24a7778ccf76fcf4b32d88882a28aaab1976624599d9704a15218e9f87476bbfc3ed8999af53c1377be039a8fb2b0341d34ed75ba82cfaac88b5a57110148e4acae0693210b00b5cc0f1e1e87458ed68321c5117794c061fdde902b38a41558bb420a4ca662411c12ce30fbb082adf6ac06f6e2d8faf49206f2c14db585677ef1a1ebae74218ab011a2421b539294fe618989ce24ddf3a3ac71f5a4d0cdc5c01574b1a0d27160d991345b65b79ccb54685585bfa56443feb700341ad1a4b885f1626409077a4dff592b83c126c9db628910f29ca1b86e09ef498796ff31c7364b140dd35c63d88a3230c217e6414b8e8e63d84d6100fc2e1cf4f501a49d7a39ec31b4e519558ae2e4eb214f402ba3423df540b92d6573d405a98741060f59f79c625f278677e96f3703a7527caf6ce5606f31ca4d0f5d62730f443f6db0edd8224f1881eaf27f9af3215d06e2f72ddfbd78b467082541422ece34e323a8bd45489fe6db8fedd4c9dfec4954ba286e971db9d078a7d0a8dbfe8f5f166f1e51a4d4fbd21dbb916e65c40d75244b6db87747d98de672371995abfacebe983a325e8f0ae22fb706d7d76a2be95fdeec91e60581f397b1831cd8fcb688c4e726e7dc417520f9cb73978699efacebbbcd844c1d590b74acdb390cba6c9511a407f885b2e394643e0034d91900c5b22a3916125808dc65ab68f999adc3fe8c1708eec0a9fd45565ad7383ab1083f9b7358d19e7e376e53f551e3e89d64ca1c874e50f7f06b3bb8651d2b102bac1f8ddd513c59578dca24d3bf805f52f601ab3e04a6914dd47e73a8fd93c24d966f72b14ddfabaab3f7c28dda56679322ac20825079f689e0176d6b9dfabae06e3731387343fd4150fd136bc9ef692a90d1629c5a4f8d6c380d90f625e75fabdb7db2b7ecefb5e20de501b4b5d3cbdde77b5bd44bb3c0bd8468c390bee31978864bdd79df6b3d5692b673b2c588f775cfaff2714b2af6466b30ed829075500d17a89ac57540fb65867850ab229853baf2770fbd813e98cd966ef815c2256c33359dd1e2d5f559d6923482e8f38b4973f5da9afe16760c1bad2acb8e7c7bd5b288306a192912bd735df1f0b161e73f6a83e17c7d325abbf8576a4e38e800f452b96b4db29620910290b7824e94369f6542929b82fb730d2b3c38695a2b3b2fdb705662f546a63c4cd28e2006b3ffd02ddaf7e0549c486b7e059b043b70b4ef1454f89229612c2619cc7fb222e7cb3a8af418333d3b623bb75a9c0724ddf49dc60e59c3980e3ab731259120ea5721454338fb7d830147e69fe2415a5d9a829fb94681de887659575b86cd52a62c8959224daaa46f1581d5fe4694e62ed0e65fb5a379cc42c1106e619739319e8d8bdeeddc2d92499f986f9c2e9d91dfa7a94382cd48730e16e86409ffe0a31aa3b03c6d8c8a2d59c9121b40406344b74652b5e76df6bd339d68a11c67c79161957fdb6a06cb5fe6b97943b427eee8ffd6691cae2b8c91fb80188d6176f8e4bc8c8124acf1f80f3a97544ebe894663007e77e09dae11d6ace48091a2d57a8273b03c7dfaf617259b8c2ca4270f749fff6703687d9f8d768ff32913a52b5555ce283a4f1dbd328852c088adb6607f8247b8951e15a50858ecd59a7d33219144141d0303deed5022a75af0d035256ff61f9ab5692f698b640bb25b35145f37368fb61dff032e7adae182ec786a054ce2ce35ecb191921d8233b1f5a5108c4f15851c12ad542ab7984a62050a1fa91f2d9db0c15f04c9c79aaefaef33ef50dfc83f766a749b860f44281fc2ef1ab8f0c1d434bdd950b69094c2b6d1497855f13705edabbb9eed8ac7c4e4ac8f24dbc585bbe866883d008058b80d244e74408c4a1fa95fec2605310766d7495204baa86199f547d493509fcfd8266eaaacbcb9e9d4d10d6efb760bed562024a184fca03db882e526194df6df692a3ac4e56f7ffc6d8e3ea9e5e92061dbe8c2e26a49b5015eb8cae498a08c71b5400d06ea01e66b32077905ac06794c3e57ad7f7f4bf096d4bf7d78d9f0696e029171d7821bf61e6b6546ea17741d94c8946cde8ba758e262be8648a1e696bc9945ed9f7465b8fd60cf2dc0f0dc1423bec887695608f6ce4fdd6ebebb2a1a45c2830ac7898633f1596eb7effde567df6b1a8686a714d042e546bb40ee63fdefc4734eb589276fe09d696bdf07381db216b3f29f4773f1276a1ef838013948a4e93e43d23cef75b475e9d2f8d57c3e8306ba531bffce5e632790aa -MD = fff5357ab834e99ef46b094d6faf459f779137b419a102da8161d5531cdc7f6e - -Len = 16352 -Msg = b02f6bfd27f4e096b586b89f25d049e79db6f0268940a73bd5fbdab75f9c779face7456edacf765ad5df7fd8ced82762e99cde78364a51e5e3ab3b43b0cd7ec1a2ed7224fc9a7d0c6b18e4798103e08d6434f594c8e97f411a1f8e3afe43f3d8fc0a9b27769e1c35defa8e8926979cf17748da8125625ad8e3217aa53347ff6a2106688031207c5c964d2610a4dd8214889e384737000931a477a78b3621ca0179a98036146bc409fbd95317e51dbb800100b5efe40ab4d4c6eabef4ef197b246cbb8c5106c61dc47565bea4d09f6ebd4834f97f16c7854ab24267e946773b5c620333daf178af166cbb0ec24daac451c702ad02b480a21acf4749702382312fc34a1ed8bccaa18648a1ec764487e5c6e434797da67e33cc84c10d946e838627f758f4534f041c9d71e000ca9d7ff8a4099004fad40661e93b775a5a0fc261cc66f55e54926e47e14f40f1c540d826719de0f780266353f85b32d9ccee87eba579e904e16d4f4bdc4a88686f16da96b708eaf91884db33814cba32f1f41a4b3a96fb8d05c8f14f16cb820cd105cf71fdb177b3c9d6b8260c75d70cd107c2aa1327f5a2c58b9a7c1638f486f2f6fddecc024ecd9b0440562240510f7510c930b9929dea2b9e93fa64fba77ddbd2ad06ab6239ee96f6bceb4a14efe4e4f87504b341bc0e3ee924f0887a639a927f28102239febec394730d0d597a3326a50f4f899a19b5065494860a1fef8521e7b325b9f066e729c7afe2f278bba34401de38c4077e888cc82de6735115e58ff0996df9ed390ed075b69581d777dd45f32ce8ebeeb12ed72b35354b779b62e584200f69993fdec187d24c42df798931623f8786b97b50ef67f59e18fb4aa52a8a9234925c3ffc03e6482fbef8884e1138613c1dcfa496dd62b5476444ea5666ea3503fa9f03139e7863687c8b6bd4ec5cd72f3998f4a7a806bd58b6ba431da28c52a52bc851c99b276a1c04feebc4cab6ec89617c332c583954fa97c51ca0e5583041ad41f2c601daa476dfbbd0c6b32ee7721ee328ccf6e5c3548ecd3f8a373619000670aeb3d8795a9b9428e281b0ac0f11f7359c3089f15390233a7281a00e530ac0bf4c3829ebd5b6abafe89ec818ae8f74da5700194549d3de747e2d29c82786629596fcfb1a5aedadb7acc4045a0a131d3b21e3afc9f04848e32b38d94cdd9c755952a856ed346821a7f49c6a5a6bc67bbec28151658f14e8f04047b982bd76807549e3424ca9508fe989ce05011bd015cc01830a016d6246018705cf520f390b504356c81f03cd7fe43301da35615873cea791df85d358eb80c61725a51a109f5208a9ef4e88067a00b9ddf3df84861e2a7c52dad9091e5ed3c628c3612721c3e35f83c0c2812407a5e50c57e8cd839d4a486f02e557dd27644fdeaf707e94ff6b118c4161354eaf3b7d330e3684777894d38f5f9205bdcf9929e1f3b86792db52e76d7c14eeadf92a4afd21b3f18a3872e55bfac65ae5dddc1bda97232a43e000a6ce79c4f2696ddb140f97455be2644b457bda6a9f7ed994ee71a1980ece95de19563f578ba993b4a31478d60caa8486bc9607671daf4c286a4d1bfe5c5b825207aed6b7fe95f41ebeb2cc4d4a08218d12548aa319a1bd0257170c3f5d1430c5377e46ca965717822f919c925e24c2c70f5f6a08de7bb4897d767d42561f26a0726d977a9a148446bc5aef8d9027ef9c7a5caf7db366b925a41375ef92a4ec498023d2ad51f7c4d42eb5ce26273930741df662e9df8a553e9395fc2e58cc0b2a2949ff4d04255e924c4940456d810eb7bed38a36ab0e0f3c13a51ae7efbe0aa935872441fcc9daeae0bf4dd2a82810cd269b2f4b5f1b7088ecebd802a0a371306b844b717e09c143b0befdb52155bf1f1df7591043d8ff88e60e3d67b3a3c92694e97bc5d50d9a0486ef59d62031a1136b8f116d9e6e44a5c8b752ff70e599f3785dbd2548feed9728fa681dece44012d70a5e4aba04c7475c8d1eb01e9269fedf8918791e0443635e863373cf9524852a10498fddc311d76839a96307d1c2b1911494a9a04622d0f23bc0be0f6dd3d22c4bd92450d3a9bbb562fb0171cb2a7355a7399d16ed1546aac319e8f593d763a56016f15b5b175d0bb11d70a5a82badf5ea103ec820a12d50c346d7c92fb89e5dfa08df4583e42432ce169aeb8f4dc537842072fd0850edaae64d75d36bfced1cbfb8d458759777f160ee658aa81724e41e7122fecda9ee81d138a85a6d2db7a9572db9da56b8c0110fadbbcc1c1132c45f0c37149634999c2f0f5aa85dd263cd6b6f771451cf665b855c83f713c3579ef0f897858b7a54c5a6d8720364745b50a387f44e8b65d1946703a554b4b6fc3b783d2c99d60288c2de9dd8b4aa9a06faa67c1ad02f01688760a8082b28718764a0e4dc9a9c549e5c8165740356cccc921d56d0e1632c95fb165596c4977c62df10f491ce08f9fc5b34392e37909315e2af1efdca4f6dc0b7311136662860f3746f75327f3f780c87a120ee9a827549b005db8bd41d4c4f845ae5d05b03a4a4ed6670a7f36c5935a870229c7251fcd0c5c6956144f251ab2a39d74de951d0dc119cebd872b525de854947200828b013e99b546765f9053c7175f293593a6d02a7baf1ad46426371e7d29862a42d1878e32c21857e57ef6a21b63b8bf3e502807867870eb63c9b5596b61c4a8e88bc687d2003a3d637989e01a6bc1dfe7b17bd4c4cb7e309cb56f25a9bdbc10d62244c7d2003a9b6bf863edaeb7c32c4233421ea10881488161ab0fb2adead6ae3d98aacd3287f661743b4742d83b08b06e2141c5c03897b4672f7400a2cf8ee32628cd2e27a0e2e6857669715da819c4ba8fea8d82e2a2a82e32ff2e3cd -MD = 40c943edd4867c0e53b5d6deffb13e48907d85a64c5dc10270272f3bd4f4abae - -Len = 17144 -Msg = 42110a204d2c48f945f42022fb8982dc74664c963594b6c1bd1dede054c4fede03f3f6a5e4f547ec9c656e5025e7d3a7d116f1918bbdb64f60492dd93f7e5a2afd6a66df9c97fc00cd85f21eb3572c9eeacdbd54c8725054e317c704d37f2176395ca1f5007a2cdee23bf4b22e435368c974f908731d4a754c6e028a97301b69bdb3f0109507a22ee26ebb341e1211ae76f4eed415256d5ca538279313f70fac93559b58e5a42597d60890cd092c2e18f733e1e135f281b1f65c7e46d03dc7e7c32ceaf477ba7cc1c5f0bba479f9724d561b1d565bec4e1b45c24fcc556b09c1531e240dd3b27055b70e84e3f5e1a5f69b93e95c107b9b439c52e24d2ae79ee24d1593ca82f2c9fbb54a32af064c8ebacc828c1bda0732d102f47ef0d81b4ef3b8f87d540be44f5ac58c0f3332a2f642f3d24fba44f8d96c80906ddde66de09c9daf2bd2f6efc91bf2bc6194044ba536176a7a62d3b659bc1c0ef53ddc471e840321e56dcc7a01e541c271fd01af633d4132553a11a97a6ae0565f384310ce54f238f34d13efbd61bc868794b336f8ff7812276b8539031ed450f3f5a230b9b373db9c9956b5c6376af1eb81a1492b25c4f23a1cb7cfbe7fffe5f89d810fa74a8cf2297a1a34e40e53e9e4ed534ec5572dbad47630d1713669fbb857681560c14766e217e9d4de8e8057bb0052af8f3cbc523ea177a9e5eb1a7b794ce0aaabbfac1d0f994afd7e60f824b9e125d24e7d78a2c0c414bde2451b4e84a3703651ecc200f827c6178a2cc33623b95421cdc16a93a107907730ec735a2185a1211bf191f7e5eae48acb99ea7744af6802d3b1980b2b93723e96892a89971afad3ce7621eb1d092cbe095074ce63ece8df27f50cf3a4904279ddc449c2308903b435227bc2e9ad261c0cf96922c7975c1f9234ce3455268992cd44d6ec32fb442d179ea66691fe5b0a9b3bd25db9d94c2adc16e4b4867bcdf02eb2dcf1e69746a43b91aabd5d2352f180beb66681da4168cd45585d7fba99fbc8b560b8948690826aa490b19445933a812b1d2567c1c3412c6632168709721b63f66c2984efaa306c7f5f29808ba74b672a0f82b3b7581dc32478c6e790e2b8c61c072cfdfb1d1409c91f0c671e158ef9629565ace38a6458243457e879703abad03aa949d27098092bd84492256569017cb6b69b6ee07eb4116db0d0e9a50907ba0c88ae9b2b23334c93b849c92046451f7b5dc87fe2d39f912cb9e70a078d758185b1757fd71c50d55850d432cd8c8ff4ea427b3f19cbe14c785a7704202fcbcead0de5a5fbed286d2df47a87f4a3a5a30e4efcd50ccf41ec597bc6ff7855d3488d8248351ffd83bd1c8c84f11df34fd3ec67926a44458816d7041d22956953982cf9e459cbb4296c2c003a97d1e4572c8e76872647977e74fbddc49501d11465925b0337887ae2236538e4a297de8458fb6421309f2bebaeccef038144f7de58c88eebf7ddb7758ad01dca39f8499dfc3b17a9b1d36b976c5220220ee4417919d57ce4c253d3ab48749534857b8d6bc3577966d06cbe4a55965968636b19ac4fc10b38c071364c065a8969ada812b6525671a2b6f18bcb119f831fa961e640a295252d18bf49206b88e2b2da0740455440e6a38aea3ce34976848d074c0ffebc58b10df3c572ee20088657342180e26f1dc2b375e0385aa52146faa6b6feab4212971e780c1a80cce25fa0e27d38534bf6ec189f5ae7f8ccaaafb0ad261a12dfcbbfa9d01baa9c181c54d40da3d26191d24c1a2fe0b1846718a9f64525cbfa398c11f5227a880bacc04c3ddc1cb4d4e9baca034efafec81d741b13963a792af85c754c97b21e942fd53121786f4874fab54e192331368a97c5ec50c7ed8c6bc544d3f4574ad3014a64eac90824f4096dcbc0a6d70cc1937c1306f501c66c85484b133689ca0e19a4745f7db5c4225ae90408f0911407ab7567504a6b4e824028791d5a55ba39a3e60d7885a7d6393017690e407acf71992ac8b2962e0c34640dd6d9a8e4a3bb68b7371d2805e2a1539f01bbddbac76527423e14237188ebb8a16b2f685e0dfc30c0fb36aff770c18b28d5f51178844c1b66d15e375d4b1005893f08e1eb7e64c2a860ab62a70903a05aeba522dc8c8f3e3d8a781b1adc0913705a4a5cb1805be8186f64893a34ce59df4db4590f69945870704b17cfc340aafcc5df21db9a4968b82f496cdb7a8b7f5c0308fe39a3c531a68bbd72a4891b92d587ad788f55960b2fa84353b062a0da7c138b5981c0899088e4b776c2b50492a4a89ea9f537aa9926e23885e1747632e48723b1104a473fbd82226951cf6274113199fb37caedda44e6124b9738754f3f66ba500ec96904ee6ee49478609dfec32985b87a96c89632bbb7edfa3705f933b9377ca2c356a8c3aee73f60ef1df963984c26e922a194976911b331f88ff76887827ef4c276f3e34c11b23104492c9887d58da9f6e19d1cf906e46503791288d8839e2d4d31acf74f4c3412278b610bfc0837e59af179697280cabde12d1238b5222375edef9da6c07f0e2be14a5e6402cd6bc39737f025dc66ab621911bf22244757f328188c99a69289a5b9efec4a9e0c706b731dc9f83fa0d07b338fe0ee30da80d089144278096ceba838e0d365daad8f06b90ace8ca4158131b80e3f44dec3e733954b87eaf2f77c5be486db5ebd9810bcee66c58612af06ac2ff6a2ca38ead445d6262297671a86e74849ccdd4fb63bb49c9877919255a61320aed22b45378e2ed30bdd2873bd4f74e9926d8999ed57174a0aac532befaa8e13a0970d0d935f1514637e451bc8202951c7870ba226ae0c81232c74e5665a479133b81999e48d222297ce956924412e0752e20a734a86bcc84bbe9dc8a0fe6321cffff6f014617f840d95c164b7faac9399462f123f284fa7ea2c76dd86de0d4cdc324c1a092351c22f9b70146a93cb7e067b2289efdceca6683ca62b00426b99c21ac520ad1bc36564a74b822653b24eff488ae040eabb4e2eb7 -MD = 29cf92662574e34f87f056f66104497cd0a0966cc2164db8b525cc514364951d - -Len = 17936 -Msg = 68948be01fdab2bed3182ef08b45e162d4ce5cf264a1a225fc842e1893ac38bab08b353918e99dbaa936f04d861ffb20745f58f384d834cbf3e254eb4ee35a00d920459c32d238e5327d7c8f147dc707d9e1bff1ea7dbad5003bc81541b2f323acfac5f0b6be0ba83592d99c7e87ce80cafd99d6dfb9bcaaec389080b4428a8beec2bc1fecd49f697c200f5e0c6797f1115bef89a9b4c3b27e80b612eebaa7a06a1f33101c3d7b91cdcd27bb0542abc374a2c8f29095565580bc42b53943d3c9e7ba31ab8e202789f141289db343905fbc7b2df9de85fefbb8933a50db0594712c3abed88aa62cb8b0251aeb5c8fd02bb18d2586d9ab420cf0aea8cb1d2775fd0248e27f57f71185d121068d4951f3911a81b881cb30aaf0eeb4930e47d2fbd6318ca6883e3a5e5a1edcf36ac2af7ff8c0feeed2fa3bbe0f7b4e0400a12db06481ad11db87989c9e5dffe96c0ed1fec86cadd061aff507d25e24028b73611b0fba542c617a3852b85731f07a77e0f768e435651631850c9f61dd95960495c440a328fe005e430812d41b117c4304f342f040b6daca1455df4a21c50a9df2345d05d28fa17de046139c65535bbb6479bd5a73c993c0ca6bfbe29a9bcd86a0f2d0a8f9e72d1d38952376b6bffd27291141e978a82b5cced559f1ee1ec807c686ff54460f8a87727caa2bb65b4bcf7a433664f75b88e6491b633fc557e3688c7954d1600ea203b78410840e312dfa8098059497e894a662c68093c84c07f01b5235e6f1ec5bd82f33be4666498cf263971441015935e3425d17b69e071ae89b990c5d9eb19f5001141a3c65a94efd4ac9cc32ddb655e710689271f090059834d740fc116655b156ac8d2db45b5d645db49531d205dbf8f570588a66edb1480c92398cf2136544558580e0fb679f6fc6e2d8048850af5f19fcd1c9a72805404e555fd4e8beb6512726591ee1d3fe65aadbfb74a89eb964a39465f85c49e8c720a51a9e9c713220f31782af0ea9619034256849daf8e14ebcc07cdd2c564427aa0cd2b0b633c0f8e2e1615b2bf1af36894a854bc5650f678b097e42c05900a61511efd3dd0d48231c0b60eae0b1d2a0d4d2bc4212ed2bf539f6d3edbf59048d893dd9cfb905b3e7c81de523d4f3b1163b4374f568981d41ed10e3a6d25f38242d16f86cf326e78d0e9f5acfb0be34dfe627142d706fcd93d0dd1737a17284b22a26b5723375cd5c171a26b61b1b4345fe0506b2d27923330ae7d567d39ad081a8f576a820fc4d9e0b16b1a0be10c68eab66b14c35be0868c2b686fd11df04d7ce09a4d763c250991219635540a8a50314d17dc34147627b20d093c2024a08fdc4eca8c7a4cfbc9752ada49c4be8c8ec62ced2de9f1b1bb44dbf627e4fe2c43bb326e8408a2c7bdef659dc3f84da1891bce51866f742195b710b5df89fb020d8c33dce0abde073b624a6730495857b394b9fb724f0c546b8b33aebfa9bba051e1bbbc1ece6f38e69041ad1b426f1da2e378317dd33ab88133cd6734aeb0a5953e42828b0ad6eb23ec03f5e17de271eb6a71aa15c68fcc9b334675fb136a806c0450a6d1cb958c97c7d9d83f4662e2d1ac3eabb6836c1f0e1c27316f7249af2ad67ebf7f9b3b9ba6c66baa614650ef1a2b57dcec84501e5e50e8400e45eea076171522e0e42996d56a020314084d05195a25b43453ec49007412185408ca02b268cc87a250f01ca8256578a3e6b7b343db50a80a7c912d98f83d30dd256c24842e0d44304c1f8b937aee51bd6c11784e01314efb68df4a8c4fb200063625a45fe94fef174018722bed0544ad22fad28c7e701f7393371e5efd293c6bb5b6f0aa2d1ceec3d77b5ed5fe52c81f95c43083a5757fffa629278582fb1c7a2e70a7f76becd9d27ca8a026215f32712f1e40c808ba071bfc35e49473b046ce0ae328cc284826afaa30e490f8733a3e695951ce3ac63b451fedd40041e131b3c59ef19cd4a75bc7da94aabae64735f3df16020a9e2293078ba1746d6ff663d8090490ee0392ffc7985450e86d33cc2deac4c001b54794dfb9f15410706863b72fa495343793790b7de075ce0fd1534936f61a4812bdb73a456de1bdd5dfa7bdb40f6d03e3115e2fc5d997b040a861d22e2a8f4238ed70a39877abaa1294a67820a596e1989525813aa02553a2117e654ac28d948a6f67a83daf2089a95ff6631ff78131baa755cc36c4ad0ca6a51f5f176ea393a9bbf2b4af54deb12c6a0dfaec75da88dbc0655d34b7ad6fb0ebbb3c1e7f4fe3f94bb865683934d4fe7b53cc20b1016b7e68eab0cf1994e1735de888ba8500ea0b970f16e2acc159a1ec6e435739743e15194c53603af1f640640dd19600653a53368d55c92012b3b935c3fcfa6fc195325a00d192cc5332baa6b1831b81cb3952a2b9be6643a777a70feb5584d477f54893aea7c12e171b349e7a39c589c18bac53fa9d5487de09fda35ae970f7e5c2ea5ebc4285d0ec146093ae422e78d695a2d2e69f0e5d451f1fb88925595ab9a27a23a04e6b6510b2a15ee458a0ef88ebe8a804101e446afb9fb7fc95a86d52088a8b0107cc5b437a8938b2c9e74e46e2e03bb9bceecdbe34002a2bb6e8b05d699ded351b2313e2e08ac970324c259f3f1c069de21a69cd5cb377ad1594c42a4a16d2e2f52a2f7d692879c31e59f600451ea1172c0ba906da5c28e71e2709472ea7d461322c2e8188e4d211ea9b4ff8994a93cbf73cfc09415cc6604d3a00328ba35a563ec3618dd4325af3238a8406b0324712d048d3230627d8bf3f28398ae5abdd28976a98f0bfa38cdd559242b90e6843824399ef02ad5fc84a508c25aec123e55eb89c1568bfbad036fd6d0c7e185f0190cdca7026bb672d981dc0452cb29e0b7f3ec2674468eadd96875531c4627919d4db3536eda4d0613f138f28631e9ca7f076981f123fb60d828ff5632a8168f4b4f87473e5ee1e1b95be233000798253591c67ad60989ed87173b8012ed9811ac7a1f2e7ae1bb2a5329a370c8367f1861f8ccb82ae2817d6e9ef37ac3fff63f463745ae284a240a6ac24351e4a5e6cc8ca443e4f5952b371623edeb4dc47842a4ecbf6f528162a9858e8a7d5e3b14683dfdf3a5400acf440610f27cb92665424b03561aff6dbd2e2cf5409d3ee25315fd6ba3a4 -MD = aca454a02aba8dff7251f3dc3372f4a4953e81593325e69a1aa1d53df5ded02f - -Len = 18728 -Msg = 42b849668cd7341092ff4d5652481c2d415d6fbd35d25a5a83b87cb7646f84569ebcf443601b25026d578bc67c573be4df3baa8664a8b8a4795fed3093150291d07fa353dbac731d109751e3e0fdda5c776c2eb79d9df78ada03a80bdea403821f28defec42f2647c2e8241545e0ff7f511783b6a95920f3f0cb36ae0ec59011d5df2eace54f476acc728ec472a8b534b5652fed50853bc901e01e83eb1faf2639ce19c504b2dd6d765c165830fe0163ea7ebcc259c94ef3566ae8f03c5b6ba9921a29b1ea00f03808cf4539478aedf43989b29f8ecc635937901d5fcb20c98229eee6d95fe289b3caf2a1cf7ff380d0eaae97ebb53781e3eb7a44375e17d39a4670d7a32affaec604eeb483a0e1c2dd4517f50e97b1b179bc51e5e0bee790d730c8847815016a59fdea06bb71febc0491e95370fce3fa03f03d88c2b3390822311f75c1e68dc254fe0f1de0bbef752e184f3a79ac746469d065b64504b544648f9d33e4664ec09f4f84835b465ff541206f31916e0df793a4f2f6d17b024b839369454b5de96b223872c092daf44527f271c0200b56bc69b40bd1cedec9256985ac335c9309cbc601015aef3f566cc6d67e6f8e4cf6bad447d9cea4f6b1dbfcad8d8681cf54e971f158dbd93c2e720813bec743f696f9baa78475bb8b6374265235c521db72cc0c51a0cbb89b2460d3f3584fa7d4dd82051a334e7b6586f8cdbecb78a37d0c7c806900b0f322df3d11bc748f22ad745c9be90ee24d4bc370db377827717eca02b381a114f49a0811a9b73c101d48028f665c3eb89706c2e33706645bf2a553658fe1ab7e22ca46e5832cd659fe6e30244cbaeb58c25f2a59c973b69b8ebc50adfbd14577e57c42c087636af32fe7a622374d3c4b371ba4da79c59770ad8968e3de989786a576a4aa9da32164167b0b910e5b5a185d05d76f2f462e61b7d6440e227fca33ca8113abad3622361df2087ab92d6d479be46c1fd33ca4f614698b36aece0606bc6537cc9f6296f0ab1344e41f0b9c615b7f0af34df020b72d0ae6636acd7288e4eab9145b70a51b27a768d72a3c0fed049f5af185aacb2d6883fd9e3ec33740a8d8418cc9a8763efb761b5bc10aef73fe0c032364b2ccdf2e9b77ee12fa7cb671f6763ad25132e18e480679ccbb647bb08eae91d04f4c55e819fd5cceb86a73a80d01285cb4008d48e5d0383498958e84ed0342b2ca7318fcc636ef5a4629feb3e5895e501a09c8911522a1dfe9ab33e1f0a93ef36b68afd46acbaf9eece0dffc46b7e297c9751dd19fa4bab6f6cdf32f61498d797a54a2d6cd63a483f1b89fe9f833be170a6b11704cfd8da1062455d7068a382e3f5e7a6cb6a7d7ef9fd8c5e4c2a4faba24132ed6e4d6228963d8e13fa71545f902afbefdee3e4fcb3c68d9546eb39c676196fb6c2fd67f5453101fd00e91bfc10a6ef6f03ed21400119264a1c207ae06071c0098f4a6aeec1ff498f202a7ab70a0c4abaf6c082f75667ced328749377e5fccc6c3fdedb7370fadd30e4aff13ed0cd963a1408aa711834efc71842040b9b1cfd4561054a01f6a63588aaf40fe2096d4a92e840084beaf3119c58335d09e454db2b7f683738b7a3db0d0f91375f186de02befe11cf63334dcd964a2fef15626de9507721386285646246f01f7f48231ef8b977668fe757c99f4da3b7a506515700885ad6f58ed400f6565b0d240db6bd1288b8a7cc3463cd18505475fb595b347fc6694cb4f6af38f56704846c2887e2d991867b8e319f83be082510f8f6c62cef746a287c825d34e6e0b12d6081deb6d33dac8adec653111cdde031a5c6da66d7f92615561a281d512b2bb0070103618af4f07dc3dbc69fb7384b7f08afe10bbfbd65b948a6561bbeaf3ab46a8e3d0a861f1cfc46584156197f30a32c9a21422f28eebc5d0e3055b6d4a5e18f11d6d94d24f6ae6e250c5dc91c55441670e334b0a28bc79a3afef4c00236e0807314f7696d473c432b6fdd4f75820bd0176f08c99302820913081f65a1b359459a408c6260d64dcd50b2fe34f4819f61790de703631c94b17f95ff2c19e5f3e470a1bfbe676d8a157d1ce7ffff19aad17d05f9e57aa1a69a67efbc9dd3945767dc81b907e9d29b229bf6c1380011d1280a9e65f740595fcdb45c7d4035882dd5c526a2c44ece27fc9088b3675e32be6f0a2254c11e0c68514c256a9ea8881c3715d9a17efd29d6ac461ae615814419ae64d7edcc7a81682e1992ac3e955ecc94b3e2debc60ab5239a3f482c9d10f89eb0006599fbd81086d02ea6ba862d0e6f487898206de1c40ab915eae0cb65ab730c6f6bfc250d4f015ee77ce6579a712607916b5e4df434b0bf79f926598ef4b849ef148be9942c72ec77ffefc40aaf7de71d09edfcbe91960bc00575cdf94ecf0703d1c1a029335c1744b23f521a33e795701667e0bd652b2cac92579f312427a2423625ef28ee4d4dd2364d982588e3613ef344a05d29f09084223453c30f62da2eb4313d1fc7972ea4ee92fcd93901f8de231ca22a5a86e5eb27a4723b8b00ed2dde6c006a59fa08316db7f691aec3bae248586ca1614e8b46351070e7017279c4174edfb51fc6890c16252beb549925cfc570666ef8b80f29bd10e6622d47fe95e142217c838d1f998a52e342e4f2d80b1cfd35cf6b73d01a322e394948f1e9f7defe8c2d1fce3a6e3cd9e334ca713038c177416f43d27c7c36b0ffe8fef0da8e62cc66436f0a77fea012723d6f94ccbd55471fab0c8462d42d5180eda9c53eae1f44565bdbb246df46a536c95ece1c2d4b15372f4fea31b6a87882b3f3ff84fb66feb2e2f0563564b2fa9765129d9cfd054a0e58687457a81a9e6bc848005beacc4432553786a24357ab1aad1583cd91365e3bb2f0c3430d065bb2b7206811e0c1cd2b3f3ba43bdfb70f46edf2013cae30da15bb73579279fe18edfd17a74591e9e2240d573f60be53bf92b412965898973642fe6a91b453645e7406983e6562a73ba35c24c89f43a03484ac01c3afe4dc1b39e84112274dcba4eb601cae0fd78c222f882ec066244ef6a3124a19a11761c17105814979bda684ca963f6693650b4e3f3ddfd743c4928e64a355f8eaa4eae17ed2b5b81a27876688155b08ae9f971848d9b24dc6a92d644fcbbff1db11b9f3b9ec58de870fe0c2ba6a0a04afebc208d2d830b45d3671f0dae7d28500e26170b89ee53d4efb4541c810c6db15de1e9863d5f5ab7610f2ec8ca44832ea9b73d10176e554e06e273c37860c0c7efb0f5f824f5b93bfbd429fdb7d8b8bf6a1539d1b00c -MD = 05e57bccda00a36aeb23c6958e1dcf7a162454e8b72860029ce32869da48baf5 - -Len = 19520 -Msg = b67a27e6468229d4decf44bbbeb1598a67b4934fff75eda9f8b5f580edaccff3cc9f7c923ab55dce3307f2adf1f6e8c310c1535def5738ff59694e1165c405d59adec89c57ae7f3a72c159b7208bc84715fbcd7cec5275bbc834a4ed3cff1176685d926b65159affe427ff3f11170100be898915bd0eaec58d3e7d7c3a07fac07e4462672c91b307ce5e6eaf8d439cd452930f8e2b34ea05f0ae64252681c89a23bcc0f873cbd4397b912e6d5cb7a0ad1b43e851fe6c326339acde53c91884eba1ed3586046b047d32e6c5e3461a15725fbf9bc4fe5d8dc7af62756bec72359d3efe4879a5184cbb3a85bd771314040b672fb051f2b003199bf6b0d65537e397431782391f7ab2dbdc979e938a4f745f7bbcaf5fa40c9c41459017fccd1096c1f8626a2e3a3a41c66044ee9e75706d58e28e2155da1a6127f55933451ba55703a40488c1bd00fe620eb337009a22f7dde6cc8e9d5d8259b3f3788b1a099d2d45902864587273f3982d0d0020c10b1bd7cd9e7c9ef5eb8cce8616a8e15da0216f05f4875d1f3c27510779d268b4d3e02ce02d75c069fd035ef85b1004e0583a69499078368d03a273e220343f3a234fc567a1006b8361c54c8f6e4de95a6a801ba425bf4d846f6de7072aae0d1aa36e8aaa22a60709bfda819478e7fa9381fb6e60dbe508cc288f96bebec83b1dfa4763f0d6edfcc4be4be44ea0649d5243b448c4d971d12cd710674f040b2f0bd0e23983e860b37c071f5c070f4e3c6158b2931748eb0f6d24f9410125fe52accf45f2a97e8492f9425ed305ec2c3e8669fd35a24fdb2957b6510e1d492a0cc79d7a78abc1e302021611309260870b8a1e9e18ad17ca89b23620b5eb9715c626e289b1d1d8046c612b3f5bf493e60b341e9c227fc84096464b6e1eb33849e68f47788762eb6f36dc2af03b73acd1a64e12ff3d6289c3b8db9e4431bd544ed6cb7351e1a824adca3cbb2cba59d4d0449ea1d0509c82dd5738d6a9d65012aafca2101ca6e9a9458e4885fcbfec326c4dee74164276dc15db269ca6f5b69ae7c2dbc3dfc06ea2bfecca31673376ef2c290432d9fd38bff3ad6d98427635158c8f4036a4167f38a44b886676fc3d329940a88421682a520033d571854116ab22ca9711729063927a124ccd30038a2439faa412f76b94bec3d626d0773ea18330dda9fb521664daccabdc0e9d30a4ec97c0bf8362eebd2ac5fe275c21561dc63e2f3e9d4a90c8351f7d00d0c56cd5b438f8c0806bd9eebf8c14a1be8a6fd49bd5281e9f65e6d8cdfdf082bbb19d63a1a60c70b019146fa5a27e5c9dba720c2b7c3010a8a801dccaed6c297868ac97dd686297bc748888038fa620a2ba480e9dbbafdd601dc71c547859bcaff282b9900664fd4b841b8101d9f2b57591d7221a1a0d4d71cb21df91241f0407580511e10878690652b6a1c90acce2bd47098fca22b22880baf76fac7c26c929a11fe6f9f708a494e5423180a99b7022e5c59fd45a073638f33212cb05d7d2bdd5b782005b7b779f45a579513fc7284e72f298614a723f3e7db811174998e96afdb52b1dba39a7cc7bc9c16253b8cfe6f67ac3987b5c0a3d6073b4b7cfd2d4d81f002a789eaaffc58e9451db6dd530957a4468a2742e60dba54a42d31fee5cb04682c73a8e36463286f070e5168812010438cfa6bd4e09c053240595c252499a7722498b134543ba6cc468a8d4393cd29f3e3fcddf26cd9572eb43233f68633dbcc8fa92b43fbf0647f87f4b324e77b1503e023f611c74020b8645a51e9772421c5c2078f98c82be1f73fef6b5308b4621205e23cb9ac5ae24dd5344e8463d50a0c704646a945489fc1f2dd3e747403819cc9ca1a6078942c8d8b42724df8d104eefee7f90bffd0fe7e353074ffb5e2f402b03e379cb8865fc5fb2785ac92a2a30bd25f1f27644f9e7a7b9bd75b5acd59f23dd0ecc4e8ac0ca5a935c126cdc454e19f3e1181ff3ef0553a81be2dbf3cf3d9d704d28f757fb39b1a0fdd5306b09aeec9e778b24d09848d066491dd7fbc8238206c61330b6bd514c21832a7d9e205a1c6fddd2eba49db8043b70ae0f8c6657b8e5a1176171ae1b135e169abb3e2f5a93ae3875de36a55dd871b81eed6e51e3295507bcf04e779eef9edcac5213e1b437a3b3fd63505940344f48f4d76832cebba020894616c0e3c62b00e8aae5db72f29673f1e4b86168011c49b83744b121580d1306cb9030f0824ba8d62b7cc89cabcea3d9c83764dd2521e2f374c875e3e7e309bbe78670cf0947fdff3ea04e384a94693e77950ba88aa63c2cf6bd271c506b293103be2888456726ea49181550b630eda6599afdd016f27eeb25ea6ed57bed9cef8502ff211cf24b1fb6adc6ebd9ea589cd60ee25db34fd1b86919f31550b0897dd7189da478329627eb2709129a09d2a556b8645848035d1c2a105ee4b7fe19645fc8ab18406d2d89524e85cce1d7824b416129c8bd57499ed098564a981d732b87dcd1865cec38cd51e9e321969a9115ffd1d9b5fa93bec7c3798350db56c15ab61ab6f5b3f7e07c52c2ca19a29b278bf8d01d27e6ffe31d6b7b8efd68f1287a534c036d2fd54c1dbc9fe3bdeb226a3694269d276be3e12a31661f5a2736d212c8385ff7b7d0a638f749d6145a77859d3c9a00bc7086df767b01dd6d006de7aa7ca77399342e13556b884a26d7e19e4956f6eeefde310687b2157140dcdd8ecad760e75d8c38bdfd8023e8fc4ba9dec04c0011c79b2c7ee73f6a82dba1cff0fb412d624ba836ccb79ee4579d9c186c8c84810e4c90bf6e1e88c8b944398b35c422d48c6a7070680c2d913f11b474713468409086a532feb2f7f7be858a5984aee21e0ec2cc2db78395f34a61790514415e073d7ec3cc582df3be38a67e810540e9d3905ba5b7e4a43ed21e94d5157e3ad09cbd3bd0d6a117e3e7d0adfc4ae202a0bbb93ee15415f790f663b2afead6a725c8b9c5b59804f631382da4ebfe407c6d9d32726a4d7305f426c2c4eecd4511c553d9255b5aa754447af89235e34a37b943a2ff26ea2555d02ce2d17c06f3ff1805c462a964b2b88474d880c14125baed73b2eeff72536f8dce6de140dd07f986a6238486fd4eab59f076757762fc8d6ff60a46dc2f27dc94d508fd229aa98777fd9d94dc6fa3b42bb479793f8df539a994510fa467c7234c085d2b0a84033253d3db989200d85b628a8a94010938450114305141635bcc1c311475e0e43a8182f0849b90f91528663851cfa51fee39e1404e159a6b0c606e16d5e38c0279fd6c1c41a2bea284a4a086753113173f9eb0de546297c60166a981477cf726e62c791fbab704424a56763e9fc3343952fad6b7e94120be6466343812480798a99812c096e14a2292c65126768ceecc50d8bb93b6b91d995ae87903df4fa59febc99dc87e29788b827d9a08a3942a -MD = d64f8f18ceb845e9097e41e4ca3fe0d0e491de285aac85e18c11b5fdf2c5a60e - -Len = 20312 -Msg = 27d608665d73b02b1b55f7d6d4337f13db25d6c9c970f9921ea0166e2bd896b82f675b59c09b463b6cdafd01a1eeebf5caa18841bb8ada634f263cdb4f2b5e2696188df0731134864feaa38a908210eabd52db12e245176136ca45dafb28621da6132595407c82f20cad72da6a94f6dbfb5f59a5064ab6761ab5bbd5f57aac83a57dabafed853669ea4af159f6cfa6b1cdf18a60ef40c289450f253306c74442dc81a7a643d35ad232e9a96ffed827527b30f5ac64d04081fdff0c5cf6b830409344a2e10a0ff5142db42085485a81a84d4322f22ea23a488badf7b88df47a6712f124ca0ae0101920d1e0019efbbd9a8a539998155db7c537426eaf93242a9da0aeb3c80aefb2c85668714dc663e20f7c87e308e1aac0e048e6f9a9cfef46cc86a3d943d4e3e30916a259cf883bf8f1690887a85a305c8108c0210e0afed8db0dfa1da32e65abc4a7a622f1ae2b08279afd0de248989390bdf96d460cf8e7b27ad80751e11d13e1529d531afeda1899578ffe1d72896df5b0b866b99d867c39186720b3b5b222495faf75b142f1332fe8e6e0c0a1acf398292692cf85509e582ecfef3271cde1e216030f2040175ed194293e359da92c626f6b7bf18bfd55f70338fd37df155695bec2a9cec1f5a367a4819de32e272139ccaea9857935a9fee0c9d028c5338b4ba113cc238c3309d9601587321cced8078617a3f515a2a3550daaf26eecce88ea051ffe876b78980f100e838a2e475bb2e6d0f1a728ea4ae4d204eb721c8f535b330eca62246c59f1fc931a532d3ab22334fe1b0579b5a79477ff419b1c1df6877307b51c80b853686ccdd2f5e24ee343b8cca975d2acc04b43c27e50b62279550d32491d47048f5aa7e336d8122cf8f9ba602461f9769ff27f7629fbb043e2ac48b80dce41f713b1f6fecb65887cf82c81e21430b7bc4c727442cb03d32a3b766dc18995353ae953a1461b020be5ecc6567bff4ad426cdb1674febd0e77f8c9ac47446dbed75192af0e2ad18620fdbae81526f17185b2c99a3c411cab4e9db0095facb092f4fa91c2afb091056a3cdcc4a91ebff4b0471116fcac65901113290287ba085c470a31399b8b850af49cb08f85dfc6a34c8a200128990e5989f9832c41e4eb974810ef68342414235a8db4ad5e128c09c50c950d528fad63f3a16ceb30b5c0b062af3ad31c02c4daf69087a2742fa694b44ede800d08994bf8ab24c3b6b52e54412591feb5b02d8e733578037abf7cd094b17b0dba8c787e0387694a566b9aef4e24836f93b494da3afd2444d42a9549e0d4e90add93b1769ec6a8e392318cedf41c9d9a2878c13ac8580afb12f9767d1339a70c08a6dad244d95233ecbf7adcdd8e2f02f685092ca5c69a7aa9b496c6b6503385ae4e6afd704ff39fe85deb3864f9d64e8051f32c4dc961581ae48cd354a92d0c40f2d874bb9b0b9bf7a5648d14d021b1587805b64ae0ee27f8f1bf0f48b4e204632ca9b4813b18ccad1e6d4777a18fefe15fc75707ad9f4e9674a3f73cf40112775465596ba099867b317bf417fe7f5ebd81ae8b1e700350a5d5e2079bf6e89b101281cfc57c0c7dd487071f40477e923f7621cef9e8a8c299adefdcd03e2712afef8574392df0076b779525bb0d1c0ef9b5c7af2477fe08d45523d3842a4b2db943f7033126c2a7829bacb3d2cfc6497ec91688189e81b7f8742488224ba320ce983ce9480722f2cc5bc42611f00bb6311884f660ccc244788378673532edb05284fd92e83f6f6dab406209032e6af9a33c998677933e32d6fb95fd27408940d7728f9c9c40267ca1d20ce920db5278679dda94d78254079654e3b69324e446dfe98962cea9d6a432993b22f57750a6d0c4becdfb0ab2372918082fe320ad56ee72618209ed0e78f00e6362fb92e4298139bc7e7cacc74611cd69c5a1f432e56575be76d88a2c6f4c9a1c159dae9b64fb756a42b6d911b8e2dd8f1459f02376d78bd6bdb4f1befbbad4dba7663ae4eda2003ea7542000041ed0fe9875a4ed8fd72d60d319c434b2bd3718b4efb83f280752a018bf1240cc28302ede7fa2ff94c6d2e33391623c08e63959ba94b728a8adf53513521022558183a632e24ad82a3904b47b966c2372a8741524ffa82fe408507423d7aa4344dd43db52482d15b4a03b7af7a3328994965fe1808b1bb36ea90cd3c6aa61122e7de954991bca26d89effad544265ecc312553559b18261bd0272ea7834a51d56f5fc9893d7a289ea87c9a1fdfe76bba2af0c971d1d6ca933a73b1eb51116d372c7e62dcf0636cd7eed121f7121d57497eeee7d47294b0876f9bde709ca06c2f6864e7a9711f7501a51717c4a6702b63734635e746f9dee0b8c83d9e2ba256a46938e05a89574c02137502ed648aeeef53213b1014ae5e845d2257dec8bd33807923d65600b3f7c480146cdc1110a8d564a682b8a65a385da6d0b39639990caade4d50059eda802d361bdcf878ad61fdeffe9148c2a67252dafbd93047dfe80ae0ddd6cf2a75ee277cb3dba96007224f3b50f026313a164a43ca5212ba37d088c9fcf01c6e2b4a999904f05790c6f2b392c528bcbabd2b2f2766a5a65a48cb0cdfd1275430a59b6ad635a36ad193da113a85c07127d8bae8cff65a52efbbe17e6c8502df398ae9847b6f7c4aeb16e1517cb740ac3f32ca5d83a3fa8040371ac6b63f0a2551833dced0d90460a6f60f5ba08330d7c97463768b950c9716657fcc0628c58f3f389e301c9cc212cadb6c17ee1219598e458d1b2ef318ff39ed1779a368bd83cd501492a9df3ec91e6f016dae8c839a564e5134b5e5a61f7176ebb3d7267a6ac174a7dcbdcb01ee6b57d5462719f402e836b6a968953f6186a80163e88a82ade44b60f6a18892e7793ef088a2dff6f90ea6c5628f286a2c3f2d63721fbd5fb2fe7e46c99d3d791e10ca5b1d670910e78e46854772c9b0e965aa19c6c4e799e3d7b4613bf8123ff9f8a31debbebdcb3431bdfe41599e98fec0ca29491f2fb6a73696ba35fc306be2f8723edcef23ad48bfb438368bcfaad418329de177be4065e5cb58a0efbf8540dadfc7d74165408b00d23c1051856ed3358d7c7816bcbf87aafc44621ae6167b6491bfc3fea80c66bcc011b5f3e86d63df81cff54250b9744ed18465c5cea5fb5f312e8a6c17983fba25bf0fb91f2eedddb69d4044a2b89499f1228f389fba2792661d13d3d76c7fc3aa4f04ea5339d7f8d6ee4164db434f520525caba80dd69c7d992467d13108f9ff7c87ed0ab178bf886cbe0e923e30d43b496fd94999728c432980bb1f10dd516b33264b1504f6fa5703a051da11e3632a77c100f136fcd5218344ab699e9bbef86959ed66969edc63c4698467e7f32e886dfea7116eebe393370ebd5342fa8f41afa13871fee6c2592f481ade18b692df8c87502c99a64412c53d656ea6404eb1468ad0c9a655488184ea89af3cc44c8a53d980c55fe2732abe5f481e212369d1fe853ac01560cb8795bf554dcc9298336493bd5e29f70d3572f2b9d45c0a8d2e181edb07c49fe7d5b235125c30a812453f146a69707a5edd93864f43af7 -MD = 31348f741d49adb56427575dd984fd8fae7d9d6c3e8089f4c54f2a07102191dc - -Len = 21104 -Msg = 262c1abe379063c5c4447a28e3534dee0da13fc2d1d17af6c96582c9ce2710e568c81d2c88c83db47a952e1015f7b1d235ab984d6b4f21a0f27e82f0e53bc5f4b093d6b7c57edb999007c397acac22cd57083c3923af5fc2ef5a77791644dc1ee6d36ee6547be47bede06145103a48e85bfe520e63bbde66a84188edc809fc6cf2d10d419e8701637b682fa1a969cd2a29d6035292394393057dddd26253cee4bcd5d9510b69da5821e95633e001569ca9d8768f17f23952ee559fb34eeafa912d27fd9d04eb1662c7a9fe831bc98e44c44bd44c5cae66aa4b10f615f39627782b0e9faeefd35d8955f14d1ac38a1a2c60794412c83472a304f70982b91ffda39fd4e80a35ea59d6b4096e7f410ca55c66a8ef68c34e064501520181084c261972bfff3b3ff8b050ca39873afb17d5dabf21fcd6b5c2ca992b69059b48e647e28a180cc974c50a0080c9c1d45b7352b0512c94e4065965a668833e56e1b50b07d126393a3b1810ecbf0043d4c8e7c5e60610df1b1fdb8074a1e9d43d3c81178f2e33ac18febb691e6d2836c2aa3dd682c51704026610c20cbfe4eed5bf12168288858dea2474be9e7387c127683b2c8e75872c2244c0d475a8bab4a8d330aee8c9650539150cb772ba650d896caa701100a97e0122b25db746b34f3de1a287cad81b3c8c384bfba4290c41731d5149144dc5232966af06db7f19e71c4f314a2f9def596bf7f8333ca7c3866ae3fa609e442342227a7f77e83d32a3ce86a59f200029845eb9dd06401ed104f8266b5cb7cd0a0472c4ea57e66748acdaefc62da4e910e7eee7c01dba757fe2a44e6de767d0c491a3aeb84edee5a12ac8f15b9dc340eda7a2e76a1fb1941549f6c3c8a6b73597103d9eb006d79f854421f32e9685ed08ef0322a3b52e63db6077ee4443aee4cca9c6fe9b24d97c3e226b5f05c1f3d8a9e59800328738c91850ae35a96655c6aa86c8354153ec6713ed319ca9c614ea18b1e9eae13cd7b116402401beb6b2c17bcccaab6a3919454bcdf812e24cf1099c7c7e46767d13001b595fbb4cdcd0be85a655c8de7e67ff2fe94a2977fb901e7f6ee07dbaf1f59f70c2e9c91b7fb4a6123af0f464cbdf7d076aae49327dfb1207ae96f8754184765da44a95f348685f68b02397c6c887a71b77addad9773acb7d65281e6f14c96d292708859cdff3d3cf317619ca1c6965b239ce443594533329ba1f566f13ca6d1e72ad03ddeb5de891e572e2396f8da015d899ef0e79503152d6010a3fe6915c82aec1768015ae88f5f39e5ada6bf93e8d7b96442cd138ac41e059a1a53426249e02ca464b04ef9a428382ea77b6b729604a4ea95642148e3f01ac836aa58fabba9752da07602806c1bfa7f8d6f8cf47d66e48875674ebbe9261841756e2d6db1e95e09c7cd35fb4bacd94eec0da4782390f0c47f211c524822768c73093039a1123fdf371039e8c74d5d132fd0329c1cf54234ff3beaba8597ce1fbc2601cd2dc692f47af98ec753900e72e551d7dece26614092025a3325d877619d2ef2b6ac8900101ff3b525a4f755d4890cd49eab86d67db43eeb8aad871af8a29eb374a1bc0f8872794d620ff5dbbea75bd97a59990a52f22c1eff8106114b68ffa495a1d209e42ef4a83b091e08a7bce956e04cff7556c874452044e802e05cbc4688218d97a9a21065ef24d25516361fcd7efa1cbfffa3822e8b6d9f584e0a7f29caa521214f8836f71ce7b559809f79bd84e56342b41fd01b9f7fbe99eade92cedba14f4f5c2df2ec32d6297e8d7571a7c09375962a9a08aceadfa8405d55a19649aa6a7a462fbea5cf54b14c7344b20c8098c632b9ae7642ec21fed40c1c26208325052a93e9f4c45107ef4c0889955c6349d790f7c9c37e11cb24dd7d8e9afe26a5a1e8dc095fb8564435e583c0a637d73b1c495b785adf0a5fbcb538196a7f82b0b32d74ea4a024dbe27a19b666eff5af116c45b36b6c624341903b2693f2545badb70f5293e32b5ca2718a5f75a437ce0698a7d8151c3fe0cec4172ea639fee486d4be332b6ba1cecd6b339ffe274abad670448f4d669063e88d70019824fcacdfb26b5934e18e1ba98f9ddfcb233659c91da33ed9f25cb4d816cc07305a589dff789e2c76ecfa2a7f064f85a23e049529c74c4f8267abbbe685b6a838841a9e304fdf14b835eee396f8d1fb4c20bb543c95c828106d85605903b34c76494896b85fb779c464712e388caca7917263804cb09e334baef38b7bb74d5bb452ec6fe0cfadc360208cf3abea67f338dc05009f4056d6fbcffc2492ca0b3db8460d10f0c84a5a5511461a383b8a460b05a7bc7d6c797be77ba913e763755a4aceb461307114a66ae0a78b27a79e07d096549c305c8e89d8580140c2ab141a3492e84ae7f395106935b72fc0552aa050361188ff391d68960e0c936aca6fe63d39b1b35f7555fe18b77fec4b6eb678538ee868312bae7fe946d2f529e70f242c6c1784de20dbd9410f06ab0f19caf7a146e0240f59ca3899a85c4c452a7a3ecad223a5ad1baf0aaae55455557fef85010501a4e1ecf8fa6ddbb18207bc3a9adf14dcfe148f59f71ce072d065c7ac8a3c7354d1ef0bc12e2e88d97db7c5d7a233d94b785aa4610a5ea86706871a8a6e1a39e09180dfac3aa456dd279d6cd7bc8dca76f9c98150aa3ae63bdd03a0109963ffaecddd90418797eec46601dac452b68e676aa74fae3e7642f73f2080c674df6cc46e4f45087dcff796242a3725cb77ce26b43d350130db63a21327e3346556292c5a1c268a84131a5b4861aa838f9632b9bdd35cd3e731f2444160f0e3d58fdeee7b8c5c4e052dff1cbaee5b6506db612a6fb1ecabcb4096e6b013d05a2d533210b7e90fdc66e34de16219735398100481b11e0c1244cff88e4a88aa21d36acd9cf87966bd11feacb0282a1ad5adfbc2c46a64e48fbaa8bf47f607a7c1319c589925868a786c46c693f4687774ad6644fd84c99daa959194169cd7efc1adb17b102656a395e1824091ae1cb3b700173233e6965feb3d531f052541a9a9b170dd08e331d89dd77cc5b23e8ef5270ed6336f781251db1bb6071b778dfe02a4a2278943615117b6fafbff8c06664a3f6defb822879c019581f5607b031552ee0f009c312d378be5c58a7f80cc2eabfca20f16cc3b67e5147e90dd19ea1724f77f114792dcb281cea51b3b032774cfab3f3b915e77db10017381993a8c2bfd26ba02944fb7e982d8615639fb616040b60a1a32c0832009c2296f9cc42f7a67e5877a8b500605156bc3e28352c01c8583cc5500dba75d58c16803efa11c2be99cb021337d112dc3ef916821ee8dcd267c4c9303952bbb8664f7e599b79b670cb1fba094be1f8a13cc948f19b90f9eab07547d44d756611a15a0bca2f0f356568d319fb6fc79448d6b9400759990b59d8eaabbca8a72779c3b293013326e1f51981ac5a21d6882b93259623d78563a847817f49e94c527953d5bebf36752eb853a7dbb5f0b326c208aaa5e773daa56e62d63d0c6df98978c85fe924a76e8e179dc2329f5ac1f2b49dc509c2dd0d4304d1556f94c5132ef097adad02147782ab5e4d5b56dea79e7bc8e14c366191cf24098b81437d4dd589484b64a7fc24aedc1bc590aceac86c7020abc7b2bffcac1481e50cc904fdffab60b5cab6ccfa55326ca77ce20d990f4a2b6106e836d25c8ec0fe7c65ea981fcf67792 -MD = bbfe5ce52c9d8a4715c2e22b99a78a5548f6b3912593391e5869e5658f876949 - -Len = 21896 -Msg = 5c6a4129d88584e6514ae5f1e7a8a84f15803b85e4060f135e6ba73e46b9ef1206fecea8e9acfea58a401c038d22fb148ccc3ec3542f261e5252a811483dc37444151049d3889b3e726cf17a45a27a950c4109e852f0b208e794dc8d912c9618fff82f94fee100bbf0158ddc79f2cddc7b25c57c45135cd907786a39894d12041df05211d37fd823eb8417b490d89bf1c3c19905955ecb9a99457a9d996add428843a149b829c97f4d02b887f21d8cdaca5dae0da99aa7538544364227499fda263945c316a97bd6fdd598df068949a17a412c1beb8f9a0ab3bdc4af9db301d2e11c660756c59830e345de4336e37a4eb9b43ab8c2044ac90bf74c6c6170aa34a0322b9ede46c596e79cb33ceaf5c7e771ff006a96c25f97743cf702dd4844084bc5bd0f18f3ac0ef1203e518885d676896ba7bcd092827dd9d2ecf877037454c91b44e26a96f5a3e91ba80a795c5202e93e5733d63a5b811f0254d69968e422047ce7a03ef5485ab7d318ef2542e19479c03759118291ae2f145725aa413c79e332ced0fbda4b3d4391b789f4fe2b33213b70b5e934cd09f1501c6c125423624e8422fa090ba953759cac5f4f5ad9e7c9f529cfc716b69c4dfecc33386a42e32db90ba6d05008a4363e20f99c1c93b859378b3011f2f56e2c658e03864a4107681ab05db87311396cbd3be0440d00afb949be5f318e318774ce8b6263bec7d3e8ef3aa6293a6b190162249bb0f5c9d3d173e9e48db213f00f81ebdb378c7c519380d00a8b6fbe4cdb7504b2479c962d89fd35488f2842b0e3c6d5f36b7d0a8852149b1046d8b4dbe43e02ae70c90ec3ca2ec9129db767cfdae57134655916800ef4c340c23ef3cd020447169546d99f7a50ceca21262a56db25e8258ee84b42ad696f226768232a1f11fb721dd9a0c983a96bf9823e324ccdd0624e4ef14ed519b9c73f9e20edfb22ab444b704b0b47cb82c92628c728b99a2c06380e3eca41382cf41ecd2cf947f31b4d27f663c1233c220fd97b89b3a52982fd6a3495658ff40c1e475e55ee167aa93c9117eb6b65bdd3669ae34b7c1962196f6c2abfc7c6339f6c43b76374709f9c3a0e3ba9b01335dbf6f2c8d72b1c2d3b83c7568499eedf2f0799421e355e4a3e6e28ca6739378e83e66892f367b7722e610222ab8310df0217d1654ed6e763d501662cebadd8af135f85a968d8f1193b32a5f5fe2c321b60c3748aba0214d2aa1a50c9fdb5ff80d388cf75fd27d20aaa1e3936433d5f7b933309182b5fec7f05e26f0967f9b3e90a8ad05f7cfc622ec34c454f435d9ce7e2901877699577522d814a55f020fcd2028c10cdabfeaa6bcee551a7c635f3479402290e3c4dbd346c1e6a135fd3e22301b7162854d6b1aa1210e5a6946d6b83f2b0c5476c2fc70b08e155ad7db96ec450326ad93d2c7fd4d8f68ab474ac0c8344c37389c0e29cc14af39589127ba79d372694462fa71dcf68bec7392f9adf30d262bc3d010f443c7a7cb211e6c09697fdbb1cd9f1ef92850a91259d8de0eb70e3b627c9f75dc866e0a332abc0314198ec188bf94dade6dc06972b485626392cc0e73c966a752f25c4919fc16975b2894a66690d098922bea3f761a35213cf4db21c830c22fe81636d6e80baaa35f15360cc3c7fee2a4d122ada4f144950b7b9ff7d8593e6a1c60724615efe491904dc76738eb6c4396fc0e3677e040285f95aef33c994800607f93192c0f50ec8f50ed483e61a535d91af16c775dc46599b16cc66d775b6d44c21dc2a2e07c3ebccd0c123cd13623fb9c90b21bc02dd74a7d7dc3d38a051b39b676d51309c2e298f09877bca09bb86f2f50a9edce08f7f248469e1737b194dfeb32b2e4f1c192b48a36cb4656424db411b5a665cdc24221b05b97a1070d5477ced5fea12ef4a99fe85b9f6268c66e6b02444a0c46063049342142f98e64f4c1dfd51ac027d891aba97b56896ea494e46f610759dd315ce9422c42892454d02eacb499da52ea05683c1aa333ce494bc0b7a060c6d9d02272790108e86f49811ea3f8fe5866b55f661ebde7ea0e311d708986d8ebf26f2b852713f89fc5df82226426aab2a9a72a25cfd9a724b50864844398f2218d5ad291fae9a407de734dda4ba24171b25bd017ddf2637c491bcb6c743b2f10214fa21962f69dc90fa16e96e910353e072ffbccb7acaf493107bca9aa01f22044ba348bedcf484befe64ef8cad508401ebff7a4eb4ced241338a2cc4361edea7e06e479f9d82618e5be79604f852d506f687e40f7679f85564b3834deff64d713c24c6415b5c9b887a6787e058536c78fd5da215a9158e570abc773eb1f196ecc78d6cadfccb5934c1ac6928b79971df674a5b6933e8bed08c6eb29e6655e2a0e970e2ea6a15c31b997de5e2fc6d0dc19c16b711fe3bae475491d975f56b58140b96d0008b8202c46ba3a3180f1767a804896017f0558644c9ed97cc467b21d093c8dcf8495c3eb79de74ad1d8dfa91b076bfb82f3806f4f534991aa41cd645cebccb1d98be99e7d990f82163e0df8a30d83335bee0291f15a6f7217cea84a41796af5ab38734b9dc5e3f5ee2ce87fc77e9aada9c82413b14625e01bd556fb06a76c51763a406d9f8b2d496187b9630fc27814746b2e1d18803483bf3e1d9e33dc986c4378982b0c52b3267738c8cf0341e50ec5be68d9ad6e64050af1465b507fb8ef19dac5ad6b813e3539275de92c63a943a3a9196df8797c0b05d6185be6fa928101480e1c4482961dae3cc0d911918b5d16148b0181094640b6d6ddc67cb4efcb02aabaa020bc8387de6038c83a31550126e704bed187884927d7dbc49b15967424e812608597cd1bd2790fde30adcdd9dc0acdcb6f590bd160c25c7bca8551256feb5e85fe7b3b8091708b427a6bbc8d3f662e51e3e9977e6780a616916ce686ec99e63610d0975f232ef51da0d5e9c557e16e78b69ef4f846f801bb78321e3ea2dbf19c45fea75f919a95962b511e282d64d7676fdfe9e80511b793083fc1f69a9ac8de246d3429e29bb2d6a249215ec8d8af4796163ff6aab50fc5c8fc9755dabcb426358605641e1b95048d24bb1031233f3fb3aabec93fcb507941cf67046c2afb9901afe4b94e018749754ab4e66e2fcf784f032e0acb3ac3d9f921fbaa57cde5610f5197d07935cecde023d48789e2a71af189576057ecb00a7a5b19f0a48cbca6e7d5e750a79eb2b75917e39c89260e4c22a40174eac85f374ce38a7e5a4ec68f12a19ce2e0267d2f658ea8cc77e24e3669bcf3ee8cb61786f52316fb81fd4d45171f7e2d2db4755f8ef0ecc05afead014e39f675459e211fff818410228097f07eb654da9531e46d5ba5771f3a6174d55983d2b11e68c52bf2679e6444bfecb6d0cde890218310815415119220f5ead913024f4b1efd4bd2543c2aa0efa296c294ce00f8d89342c402a882c112a15936031e34eb4e43fb3baf68f16b2b11dc3a522065b9c249c15decc791531b4d0713b2404b38b4231d8f8a53bb6e01f40547932bdf7ce78dd7759bd808f140e13d99a6ce5adb5a85f8f56e65505078335a10dd5736e95048ca349545ad428b4643f069322a7b4852d596e20677ba99b623bebb0c31a70460e3c1647449ef0362613f83d283c18570fc9a6e9efa546b65a878b2b2995f0bbf6a458fcfa39fb01edfae7a182d5519c9b5289a959fc5f62930674cb136b86e4ba7e79fbc85fb9b630467d86befde0c444868ef532fb642e804b21071d05b34eee1d01ba5b5aacb171a8f2432920566c8fc83f44071ce588c6d83865b2fef658f62278bf1fc5548236751e7d7df71303f1ba132c42fb63ffbb1ff37d51a1d0a167015780822a41b70 -MD = ae61d634df38ba68aedda7a4effaba658acf82c0d1b7203f643b852701a95820 - -Len = 22688 -Msg = 6969dc58d6367ab563e89af7f95605d34af6ab8d5951430e3cb432372029ae758fa52395ee83d5da4a31c84d542add55a9243d87578afabf9d2cf470f336fa384a5e32b89562bba288b29013a069b02463827cbce94960a89b0fb5ed3b22e65c25fdd268d4bb7235a7d2bcf1e5fdc767007a2fd11676bbeebdc63d5500d7ba09a5e8cb4db27643ba2ff8128e2ccd6a4706732071e7f954bc8cb754514b3cbe665488e510377c7659a68e5c937cc1e0ecffd5154262ba73388f4bc28923393a9cb945e8596bb3533c96fb60a7dec1737d7207d7ec91a2608a4eea4ea490b675d25c889bcf5704228886a7e77359b56922e8732e187c9762db51fdc24b9a9bb831c6b7c71b02572a68fffab89ff5850b05e880e16e2a82c25321eae4254ad04be17e3c34e57495b402885c9dd2ba1aa14bfa96ba95a34cc919451b7ddba73e76090c7daad4b6a4087ea9355cb4b15a731fa61d7f36efdbbc5645f65414b9cb81d2f9e4f190cf6e6e05eaedbeeee12ec8a7757df9f81719e631aae533798960b363ccd7d0c2c7da2ebfd4ec8b28537eea0bee1ff08422ed8ed3fa4fe0b11ee655e50dc01112a7cf8fd3ee9a8b090d331f749a692c81183efb63c09c24658143af7f45067a277637da69c060853a1933b00affc4749801f6760a8133c73db861095afb11d4aa3cf958abd3a443637f68e5f4a7999171e6fc47f0c77e91e0cd26ab9db749e64201fd4ebfaecf8b2b45b9055b1a4e4cb3ce38b63c19e44af7c77cdc7101167a98ce2b07cdda4a263a750d5a66de4d6b06c2920b1700cdb929af4ae6fe62e05653aa6bcafedd7cdc39164e2a3e7dfcb614c9f28da803a1a71f8c780f6b610f431c9ea5de7941cc74d03163be0a7fc5f782eb408518aac9dc8166eda0e1870b099bb1c18c678da4b8a6cd345ef36a0ff4fb30643b8e7dab20f64693e0875a3c7077eba71cf04a6b6e64f2a95121c8417625a146f73305b03b2633511986640b4059543fd63bff885fb1a8aae1bb20c545a845cf012ec940f4ba350f91052dde40e8f572017134655336f81f54e9fb02292d25e5a0a851c4145a54b5922d3b1e39cdd526e7b97269129be9f0f3d5e060ea5c47711ec926a264ad992c62251834f4affc44ce3c3ffc6387840506a457474fdcb55cc1b8cf44a95c0b5a49164c86363773b5ff2226860fa2d046d581e81f2256778cd29ed410ae0eb22891285d7eca0d415fc292ac6fdf95d59ca7921c50297193eb98a2be703a6c977e8082d58377d86e2c5fb45b2098089bedc6ff7a422dd613605ded14cb141ec145604d3cfc044003031db1baff05a22b2378f18b5ef52cfed267a65e8905cb386377b018533aef07cb45b15175ed0c8c240690d50a4b1c5d2b00f62511d51b05c20ed4f3efe18a826e1fdba9eb17eec6dab803e2aff54e37526e05efcd4cb82f486ce15438c1bc7dd3f35849c74ceee22bd5733ab6bc69942ff9fa47243147bedfdbfec496a12afee20950b97254b7e701a707638568167daaebfeb27e4e73bb6ea153ca714a7f1083a8ea8255f7efdd4374e8e786c1fcf8ab8a38ba4369e12ddd0709ee318561b89e1a4e2bd7fd3fccd9853d4e208ec4101a20d1e6dc4b3c1c145548b83e1879001ba5a53c5f2d4ebdaa222f1eba9915cadff3f0beafbc2a91fad337b101cb6eefe292173e5750c5b7a092e6e1bea89830e24bbecb2584539279c9ff60e068e88ddc29cbb8262e4bc3a21f891e9384f4490c726394a76a612a787ec74d44b591e3efb1ea32348f89e8990f405ea1f5d21d43af06a29b37f95ee03bb801967c0ef804749b34e93b262e6bab352850c3dab57049cf7b6ab3c5389748fa033c830ad504b80747adf9cb9d013b8d0408b5b3187c89e7a97da66dbf86edb4dba0932b80d5c655f2e893203e4307737a3194064e4db776b43bd899fb95720f122873190361e6aebe02cfcc1819560d1333287a60cd1ba3220b11f0f5ad1e322f3eed7d668e5f3a32637678336c7283567639b855e2fc977d57181ab4b43a45ba49c7ffaf467b20d67350cb9822a1fecc638f673576a47a4c86b6c040940e723cb1ca46e8708089329b246e4e252ca6fb60f130097059731800b38aa233e2df3cddbefb18f4b79ccf41bc085d5b5ba26dd629bbd8b864aa682cd71fe17bfeb442376bc548ba688234cfde42ceae751baa2efdafaa360d48c474e9280552a91ad626984d7fa9db62e9ab53c4a805c43838ce36b587d29b75b43fb34c17a22d3981120f3bc5ab5765773fe235f3478e22a1209c7478745858c1f6fb341e52d038ca63963622a726b365f1553eb85e1c006d8af69584048a1a72ff8a87224adb3f3a82f6e69f868e733b2b7386fe31b6fb22760ebfb46a7ae250c328ee2c72967857d5f7f4432ed8ce825403b6cda8a33b4a4baa9b0f8e70d9e2aa9c1142b24809acc5600817884bebc1d3ce752dab2de76c7193d09d58b327b01db0976ff23a1abebbfbc9217c31f380129c6c27229a271150910766b18df342822a29b81ab5d4171d8ee06bf3d00d47783442c2f53325c0506be8737f44652142d36e2712ff5e3e54e2f4fdd372629f6d60a0070d400601d9eb1acbac21a7d4c6730fc3c260e1bbc9bfaedd065d190f59e62efc5009f55c53d746761e6cdee375d2b39412228517e3ecb61572d95b20a58f93aba7d5185a26f8137dbf6d35d7b6b703a3eb8c71d90933b3ad01305058b723781cfaee9782ba162ae7756cd236f3eca6f733e5ce89a55a4eab9aa81f42f86a8456329a9b5d77f932bc2ab0dd8b93374598d476c3af1e2a2e19248bf163d02c606135224c71c668d404c5827f5bfe61888fb48779d4dc6bfbfe891fed45a830b345edced1490d2cb8c82e2adf309b3216e3bd5f187f47e55f63b0ad3c6fe63f260a41e5536ab50d85104df02791d471989cd548c739c75f004f817c0569f42161b918b1f95e27d3e4e20a1b7c0710e8b5c3e688ae89c4a386cae4d671bc389e0b5a5c78ecacca467c484df50819b85d165fd768f6f7a6779addc101a8ef1c7dccf3f48353dc052ef649fec4f34f329963789030c70bd5a4e48e0046d18a06884e8ec81a57764252f9ed05d16531e7644317f928484eb9f20be789ed141560853632c0842003e87b2e3d4a6485483f855e42fa98a247ba28b8f0443e9a19913d2fe8c40bd50b5f713c40b5c57b1ba3c65d047bc7fc7f411092b01a818b1e0178dfb7bcf59e140efccdff2f3b703279ede86264fe7f7cb470422ff1fd0faa18feeea7908ba4a85fe486809e0f8c162ac3a6669d8553c87d116f75b3fb4c473e9605c028150f4eb9f011cdec8af64e1f1040170ea49feb02bbc28b46c36d7cdb0acc0b6cdb078f84ea16eefff1d762bf9c5d7da0a38b6bad35e278949d98d15720ea8f4524b3f129983ce9c18f56db712ea6a139c941d2e549794483d1f6cf1aa10854993a3bfe0ec22cc818ab9c409f90c38ac25fe6a711bd2cf8fda6aefd8c54cd635263c83e9c328e93ee8cd019b0885b4024ada5739b5aa59ae965e8e41603e2c356e882383baf09502a7b1bef0cdf16cc45fba4bdeae88c352e57ce0a1e74ee7c8f11907454004509b4c0a5481b5d9e350f910b0d662f88ceb6c185f90e709a97e3251a7a4deeebc574a395af44c9988369b603eb77f6426f68ee38394cbf8e1b3c6e4ad39041a38d526c13a9f2ecafbf3ab4b4e08507621f2c250d50422971108132460683c11468366249c08a8f89f06cd14573f8288fe7eaad2cc85676eb7f9aba369b9035e75e08ce5d7b7578ce1ee656de2d382271cd8acfbe29f26da66f6e4e431a1e67c377b0f877621b702751908ba995adbdb1dcf5d3ebf97dd847e8e735950c941d51bc1628c0fee43e3c9252b7cb33c0c0f7191101dac25f7d79f2ecb953f95c20393422a65fd639acb4e814236f8fd7f5ea8ec7a0b40bff24e2966620a567dd3822e7bdb97d738080375cbe18bb325c22334200faa05dc7972adb3bb3b4e07f2cb4 -MD = 83cc6bc59acd9a8c5ab212c8857c81fecfc89eedaa584165abc0d9020c1f6187 - -Len = 23480 -Msg = 79a8f244af767d0585ef5fb6a82042ecaf4f2632478ba8448d88837ebbaa57930760a982c8b32bc6db1f3ecd45a1b6ac1911dd119db2ba79a80893a34ee9b044bfd762fc6d8d44896dd8c13b20a8d6a7126719a02289fb63e4654a124343fa646bb6249ae62c4fb504c3efe6815e2b4662f9e3c72039f26a0847b0b3e2dfbb5bd1a4f8447ab7d4b26887d0b7afeb3cefd06e426edde927f7de58ce6e72e67e90ba4ae4e272565ce761cd6c96f476910b266e3f7da2c223702c3dab2c3d7fc86ded4ff35c16336ebeb73dcc6c9627b3032aa3e1dcb7ec6d3fbba14fd389d32359345d2a9aae73929e317ef71fde27293da5b23074648e8dca532ac34d9f0a16bc55199385824150ef9939f599149e7b235e46342bf1d10c7bbb800e80c74b2aff192d3503dac3311ab515cfc080b4321c1f05f6eaa5dc71b9bd4c385649bee588484118fdfd21bc854ebb8c7e6a8fd58fae977d9acad844eb1f364ab66c8cd2c0aafc455c34847a992bd234ba195aece6d4a5d121a6ec0e7baae54b8779dd760f0607c306c714f1be1603d05cd63b008859d7fb69814155d0260243b3b8d85bde26099ae5fef8ab5dd5f6664be95a98dd05d40258a5fea4525b343b2171a60893d0abd3e0205930dc315201719ae03c4da045eed8594c8069112439b9ec6e0598cd9575de775e06a5f2c0a6b531f57440f1d1c8d0e453737d0f7a48637059db53e56e88c94930b71ee0e75ffff5c0c91ec12197278f3a04f61edd6d07478f112edfdf1588dff6cbb1c27033372f6ac24fd8dc63c7a22abc3c06f5b28db7372f8f858f220381d9c8c562022b46271ae83bfeab3497654a21b78f6b1edd097abde09d27ba22770138c186464d1225f9c14bfb36137f1fc3bdd080e7b9e0857f4488f04ee2cd0895a20ff7e3a384712fd7e5962407671abc18eda3108c7c726f4cef46ada4ec7dbd8f167d82358452e3b273981e19379c5eb878be8f9e9a1a715b7d67eb07671ea3863edfcb09fb123ed85bcacb50d7eed027d79a0bf823c3aefb9a1ab11326336c0fefe76529cff767d307f1d4b430583bed74ff2da0fdb64db3ae28a7d1110443b2915bf99dea4a862bddd8e04d2821c790b5b59da0123b770b215a744811d94ef88c042e6b3252c56647469824a8939b9a048302004899548c5b76c1810cf9b56849aaad9d91594a0eab02a34099f4e093c83205c6891a0bbdc5443582ebada18b2e151e3beea53daa73d5aba9e18dbd01688a4dfcbc04c527c58e7955973d3ae7a40c274b307fc7c3068755686aa65b6e4e5383a9c9a0a950c41a3402f7f1a706145973d7412f10e0cce04b841a87e261e1554ed69736e0c22bb10f8ff2101170e4c2a8e608fd3f892da83505db7779638958578a100e9105601bb20672e49fab7e106f816d317c4791a6baf494c048fbae2345cd1b6fe59fcd20c46e5eb37a41480b6faf5812f1a060a383582da878b1b87fc1a7a0a3041ad888eed09dc6c9baac7a5178b1e9c31e026738398d78310d1034732188f015feeb1ad7331965b59c1026bce460fe1d49e0ba809f9e779a981c0a0242b99f40d16d9f279fb9d86671ded859fc4e9925a86064039347efdcd945c917131cf7af1dc6e0881d656603c07d56d0c7610203c3eb2c6a1c70261e58f338599a994287695da2a0b30558b4125568c84d8280e022eadb5d430165899e8f2071e119c6f33e9cb0176c82f6a3eeced8e9979a5de44ec339830fe3f445327f4906f082cd1923ead1964dc288f5dc506ddcac8fdf36cee00e8588fc1b799c2d7bc1cdbe9d21a0afccc560ae56d56443ee49954b4fff2aa7220ab635224e65ff7e4a82b37e343d546a4bac2ea8690f0f24d758b4f566eb823dbba27750eb145f1948174bba7a833f73d1392bc5d9641cd72fffb4189498d8264053a8ef7831b41663926c981af9d9affe108bf64eecd3cef9913201b0b910a640d1b1451f45663b44fd005f3c288ae57b383883f02d9ad3dc1715f9e3d6948564257b9b06d7dd51935fee580a96bbdfefb918b4e6b1daac809847465578cb8b5356ed38556f801ff7c11ecba9cdd263039c15d05900fc228e1caf302d261d7fb56cee663595b96f192a78ff4455393a5fe8162170a066fdaeac35019469f22b3470686bced2f007a1a2e43e01b4562caaa502ed541b8205874ec1ffb1c8b2557669429047ad8bb036324ace087493008cdbc37d2cf9b702c20c3b74adcbc5c6235f641dc8aff33280e092f8821c5780af93401921c06cbb06ee8ba6affa9446e45ab65a7b5e905529b6a40497350972b8d561095bfa0bf9fcfb9adee0de859d61631f8e8645cae1d6bc683a6e46139f52a70e94012efb844c3b4e6367fe019241818a0311e90a9d31f9c7e230d7dccf23132f033be5a4249db6907f6de271ee2cbddcff45d4b652e275a7430471ccc9d320ac9e33a66ea1977549781a133b79cc1efecb498d38c89138f2a6139b4b570bd66dad0ef9c1c2e37f5f979518c9fbc6acd8af469cf6c7e54b8e5385ddc13f733e5b78f766055029dcbc240779813cc56f52f2648a5a1786b5659281bf964ab25f5c471476a2141095466797bfcd036f7055decaddca7f1d7e5dab2fca3240714259618db000d341b1e7a76e71141a6cb6c7b9a120b0c952af60e5b885fee957ed3b0f8b9d87586438862eb317bd47654992cc10d873bbcc4e558a4478600d0d6ae89936c3a06a20330a428f3a325302329c5f408f7b1e346623e0fa2cc1733ac14a47b5acb1d01da95d2c2a61da06ea78cfba59cc30b931fcb43003288ae487f8486031e0245304a26634ab141d27c62311248218fa566c1aefc187f421289b19c92ed1e55fbb7d260da13bdb63803d3c4ce7e3fa41bb8cc7bcddad19f007202bb7f7be45ccd02f3e3abd013f14d7f8c96749a5fa6db13a0c03ca9d1e5d49bb37f9041f88d159c3f1d5ce26c798f59ed54a93f0a0e6001ef0acd1808bd2b51644779d1d34d820e048c61dd1fc58a2d865dd0ceb751470df7ba03a7ee9b614d95a190ae0d348eb2f49f5f22b64baa54e8308febf0060c926b5c54dbebf712eac81c7928fec898358fe4b955c8927c8a736b3af93c930d29aa7045269956bcb35c2697e520803b0026fae4d8bf308d18c87c6689059ed54e4584690a6f40bb31f24e71653ae1e39d5a30763e028c389a47c2971de370018abd071509e62bbad10b029a2b76642e87ba23f1f84b2c2b89820c412a4ebcfe398186eda7869e383b06d176aa9b9d78399743cc99f196b260f787f930bfec480533726765d91e9fba9639ab64f2d45d3da22e8a958e3289ab28e433b3af746b58335806c756136dea09a98cdd14cf4a0e3b22a07d89a60de2969f654595ebc4cd01b6303e76132f3401bfaf8589e4cb25f2fe92a47c57ab81b11822492bc900be4f0b984dc1945042eeda97f0caab6d0f49e0f5bccede0f1308fcdf40b9829bb64bc69377b12d8d715188caa14f898c44a0983e28f99f95111eac10bec7aef24fb875b64edd351369ba58ac098105b540a772d07b9512d9f662a45b35eea4a0d4f5a775359e41ae7689b8d0bc27b6849dcf1f512729ee4a5d65840328971a23f083ca54ce8ce99b225027cd1b8c0266a677ec34ae10686290a7a9cd194965f83cf36cd96c21838617ae23e5ba267fc8154267ff82f137bf4aa9b40d8a7e2e99f4c4fd77a0e4a5eba0e44bdf1a9f854544af11164834d2cce5dc0148fecdca95b268fab40f5ed72878a2fe0dbf5fc95adf2e861d6063bff7ecbf3003d880c058105fe31309e88de8e95ac8f60adfb2652f4125896e0655dce9d3bec2ca6fa66d793a5529131a30998d8c2b2c9f97b710bf778dceb3853af847ba1c0a26c2f3527758bf4add8c65b6cfb79325e0206dda2a320d61f368e5b690c2b64e80232d83756b800cab97a3cd4a5d9f567f023d2dda2142f78049dcb45f9e3c046918bb9cfdc355f31fc4614967eebe42ceb5bb886995ccd3fc70865e0e9d1bd0341c33eb9af09f72acab34b7b2fb6e7f51a34f86333fe9abbaa58930185fc41693961d1bc783cb2fc4b48494b6042e709a538f83d16047d36d214bc72756c35bea2edd99fdfd777f1a68d77ceb898cab1b5ef21dbea755df66ac447f96029824ba3ef -MD = 08f73cb073693da1efa1a308a377daf15208e2102bde446fa2d599257d8e46ba - -Len = 24272 -Msg = 0b3c5e8b34d68a5439ec20523f1914397ad7d2594d0881cdb3cf84f6dda447281da838a2023513c4c5ba637ce3c646020c6270c53ca472a528813c62dbe3e154a1fb9b5d24d90f1dd53ad2648da12bed74a91b4923999a190539248003e474d860df90a4e1e905c6321374f385d24d637c53dbcd490e8192149e43399cd0871b22fa1d5f838e7e29a4ee510f128234cdea09b839f72cad791b59a173f0cea385aef44d7650ef01adf27372a17ed966918772bb75751ba834e311461745074f7ece7625d2913516bae649de920ffe6d191b37eb690b02fa2d346f3b0ee4a3136e4828af598d8745b846199dc80e1ad1cb6eff51fe010929cad51b873e15c977bde5b1f2f48e0e170fdb8ab82dc35418114773f31a9e5abf7590bc329120a104d36dbaf68cdaf113286d4536a875d5cc52703adba62b1a44952bfa45ee4c544119a8eac407ba59c269c4f11f206dc474f5affd118bf0743e916f7fc73ce20ab7f55eea634f766eaa3ba7377c7ff44a9964cd649baf358e37d324f0c0652aeaecd05661db4a56575507dfbf54ac508fc206921683fc4290b6c212f838506c1d6a1359f835e2a23d4b333530af8fc9ba7743c5bcd1595ea344c6003d38e5f0cbb9242f5778fea14712296e339510a9f4418330fd8badd3ef6847b867c70cfd1a5f6da025ac859c9e344f556f0f173664a62e9982bbe2e79baaad001feeaddd35e654740ad961db69390fb18d248cba3330acc9f368dfe3cf9261a10db4b0d642d64372b00879a6d1a7d04934dd577b88676688f79b8c0fb5a9c963d821fd316ab5a163bc41b545fe08f9e60d4060c28cd2c29d365bd1b272764e0d283d7d36d40dd60fd98afdff17e3f450bf5890d666f929d259b0961531815869a711162ca9654a3eaded391e45c1284ff32acd013f6404ed08a2c3811853503dfba4b15d104665b8e07151e8af29fdab51c000893f9cb9b7ea3a403c4f739c52ccfe370f32378f441b1e2da67ea3db2b802112b78d28b2f8a87ff58eff69a670c3288e8b36c030ac06fdb69fd9b72a992955e9d352905578e97acbc150bed55e8729a0194569b0b64815d21de9ee52bbf3656f25b55d0cfe5631a81c69f990e6c109530087bb772b896f6a66d5cfbb5987588af4df163e5497ae76e673a241ce19d1918a233dedd2731167c3c6e3ce3d8c36248af843524053f91b6895424fdf368841fd42787a75ac05af7ce4b0f12eab07242d276cb28b321881eaf86022e1c1364ba20bf287dadc532cd956c08df38cd47226941ac5fdde158eb3c384229c61e396c1a7357acaac01c422459b0b55d6a4f6bd68d4f35dfcf72c0d1f36b7d8bf980ca23dc9bd0dc319619ed8c7d11c32809839cb23a47537c7423e34ff495c835d948cf634b66bcba2ea9638ce4910476f40e4e48e400b348cb78f296640f1543816c9fa00cfac69a547528c38daf8be79d604dc9d2fe89e4e754827f4045fda337b9f70b46f974729601afd8beb9e3ea642e2dad8dad41b1663b1552ffd6ebe55a95780d9fdf60d361d36b351e6c870ff6cc607c8a79653eb6912dca193e5a8a6893854f6e38f63d466edd511323ffb8b3cf78bf4fff8f0d56fb2e3d22f8e3f2f038c1193882aef0c23898c5437cb89539bbf8de44bc097dc5dda9349372f2cf70099e23954915ce53c50ffa15d33bf5d6f643521f1b7f2091bd2148e1591170666a9ed6eaf8b5068998b57800c4147b3a22fac325ba5a96392e28d292f7ca6651f025abd01df739c2281bb79acbbc95d1a681a9fef5264f2a85226a3efb8841b11ec52abb2566f89c07c5415a56aec61c157a7f11785cabf46690982bc0c573026b1fdc22ab8e93759c249db5f1659c97d4479af3a0883d155705b51fd41c8ad44988289d2cd8cafd69cc3544387b89d3876bb61bfa13831bbaf47951c1f7e9955e80988105cfdf82052ea06b784b0e3d9369390101991e5626ef2d8806e22fc40eabc484d2fe71a1d2ce57b24d7e9a548cc29c3943735f730f587a191f65bdfede6c150f20cf01eb772dd3bf3460cea6d80a682b3c5cd6e0f8b2c79b77fd2494423402865bcc00bd56bf9cc8a9ac1bb30993255d5890053e67a09e75ad02e422deb6259100700e95f6062b8539aaf1f7961f4c5624d77ad9c084873e2b218d290844e6a5ab458c03c993f87b4107f1e301e1559c2d7d9841b7e0ea5b7ed380255372de3aa8d6f99565eb9bf17c2d8c03d19bc9a5eefcfe14a248606414935d9644c274d6a58ee7b94f7f8eae37a630e889a120e9c5f01cb1141d51de98eb85fa50b632f01de7c6fdeab238f80fec80ff9e93f3fe5ee164a581e26721583689d01bc0a11d7e7c27c1cc463375616aecb794d6ab5a263b76607049f8e2ef1ee9a5ea6437b543b68aa3688df69cd8cbd4bee10bcf639878b28073968f89da0f15fa61237f6e0a115011540c0ad4d279e9642785c8c14223b973e05aa38c9581af2bf480e09e3e2718a9f332d8b3eaef9b45bce72ff99fc6ebb95b28dd719e1115d9390ef3dc5c6254cbdab4f8c08ea75ae235928d532dccd9df487385cf7027da808320219ee15d94f58ee4d3713a3bb8b8063a498468bff4444cbd44fca8506d908757125c697349c56455015c7a073535c320ecf3cd2adb86bc78839f93055fa7aa361e9b614df3aa1f880ac8dab440f9e0f8f037e777f0253c37da1eecc12124502fcee245382311f4f0487cb8ad6c62e424fbb73421c29e206da0f1020e52a53db6abb791dc48aba92052bea06d280f413757f83fd2d3502dac80bc7f674498b75d3d81e3a4d4c5808aa2253e7e045d7ca29d7166e592f9a856f1e7b146a77d51a5ece7972c67fe3fa1cf36df5a71ec2ae954c945f491e9250f6cf94436dbc19103324f48dd72c42b082269ff8d0129a08de656696a50ad28386a77a4b25213fa07b62f652275a5d72054353b7022a48202fabf2db14fc4166462d96f43cad30125e11e68a5f111c88cdd3f0fbe66db43eaea5a1f83efac9415fe94e065769d2ae03b82efd26596739015ede8c24e3c6aa83dbdbb3cc0f515bf8630b48215b0ebc93df3573253b26cfca6a8432639467abd7d509d66640c2fd3a2436833f8dcd83350e63b404be41904f814cb54b897d8bd21c9127b397026f4db3357f5c07f54c12ce20876aeba0c5b92a9ddc85c9f1909b37dd6f5c1bfaf9589872041ecf6f5f51a6d4b6ffc82cb52feedf70b95cac035bae537508d492e3835c53da2def24041c1fe7076c60cbaada537b3a8e4b952c390a5d0360cbb374f88642c8326ffb8398bfc24359b866eae1e3d7ffad9d93525ed162df0c0743f5dc9ea698d555db23ef11cb326ddae6be6d265c8abe5a90bef18ecad2b3902bae5a2ce710bdabae2d499a6b9b51cd316ea6a372a2688a73b91bc6fca4fd6f54e797b96df993795be9cde40a47ad993142b3e2820e533624890403621d94aba5e8becc9f1afec5ca9fa47611ff2847cc82bd6bf29728668a76d3cc63051d4c05f8f5eee73da799e397f5d8e6896addec75ebc72c058f208fcab1aa6723435b5e6164a6ac2835fc8e18e993f3ad1c667864667d96202f6e1acbc524d640abdf9769357c57a451f7b36ca82e9f35e6e7589755159aafb15714c338c2192400e098598df84e79a3903ad9593151e76f6a7456e1179f7cbce463f8310c9697e867497997a3fa6fd2d10ba82524738d60f6b4e9320c0d4df91bf0b3d98bb6610b7a92107804c34e87c20e2133906ced609400976f7c4beb1006a33b57c6e14913245b685ba412dd696a2c8bacfda4d0184b40aac1edc31ea8ad64dad4458019a56a8cc766094de521d14b30b7f183fd2f235c684fe9dcad69161cd67891f9976c560d76c1bdde2e56ff54567df6713e4e243c1a42f7fe62fd4bb1786a31b68c0defc6bd95482b80b1fd30462593d6591d57c807c1a0910309540d08d3ad1dbf333d9fe30a309ea3dad2c548d8511a1743c3e979f56afd59383716ceda8e98fa8449813247ff9d5e7886fda3beb6a540697085b605dfab2c2ffeb611a85b8e03a81a52f0753c927b3322bfa1fe4cdf9c366785071a87014499b1d41b649c67a348b8fc66bb70e4c0b5acf288c19b31f253afd2b45ce968681c56583237da8aa20c2c65dc4222fbf6a32f80a12e2a010c67505205f28d496260f7299f499b61c89b7d779931da3fe5a8b050346e81b8b01b53ef4205fb0af80e9b31aac16a53dd9eb318e7b12118546a394a89a828bfa717bf90b2bcbc15f3ce4b579ac8ccc8a8bcd7320cea7dee0c91 -MD = d9f3869427a8ee975ad34192b53ae37559350ba9bd01299af917503f710e591a - -Len = 25064 -Msg = 2ff9fc3a5e47bc3ccdd7b3a6ecaaed1b5c2a3ff4a60d93402c7c800960751eda336e187dd13b02098b31ed1d148c3966f10eab672be9bf7947df401077a8154112945e814271c0b0fdaffc5636c2c72c54c8d6dee36c380f890ae89d3c14a327b3b4f7cd1ab29d370a9908d9b8153e756da0e7e1365da30adc44a13916806e95fe150aeac2c641a89c36382f044d474924dd06f88c86ab7327d7936b6db51e92db01c05ea075550a9acfb5df803289b161c95dac4dadf6515209e5bbaa7c5c2732be41b31e878166ebaca771968badb40caa1184e19b2cac4423c0b1339bd05beb95b470a3c36cc37915356dad225a5b0dc94d09b018f68ce76c4bd671da2136eece411e96f2bf292b52875c2cbd39ad4c6e37c123ecfcfa222eafb1cc03f7c023b1124461dc21a1e9aac6c67d25f1b2b1e1f736a0dee5fdddaf13cbaddcfc0273864c6a6b493b319b671a3107222b722569b6f090b7599e0039a0aa7a2fd603c4941a191c01b5e429cfaa27327c8ff68e4f9c765c3f02e474127dd89dc22dcb0024a2d7dccb36bf7c2b9f2f66fac445d6dcd04f6a3e85d71f82d4dd7c5daa630d7e0c2f137166cc7ac220d20b657367e3557b06247c8d7fead3ca3f81caf4d2d5ea81a629b9ee120cde5696898543659f05c420f1c0c0e5bd4b898812d0b4203eb029c6866c76991bc569064922dd46f033d42738d4c6108134393f9936925632172b169352a56a8dc080a7b104e812c026d2a3637e48081cd401ed7dc5357b9868af1eb632248c4c17c3032af20dd1f627e71ad987eed678740a192645469757ecdf6758d59a073e125ba11db6f48c7a7e3b1602b75f817c5b7c4bfc7e6cb359e8e178e204b0e44df97009f016444b3473f51e46d544110fd37e0c673750d585a7ddd9ba850e2a601329c40ddba6140c4e3ebb0dab448f1b2238e2cf3a9a08c370fc134a205be15ea9af59dacdc1f1ea563d73bfff08028791d3589c4df151fb8a65adf99f401131032a50c1b33ee9b6d41bd1c49a37723b6877f33639fdba153e422f2ec864c3c069c1322856c4045810ff5a84447ae71eef4b3d05c5674afad4b822536570fff3239c85797ffc4bb852129868c4796a1a6e78bd72bbd7099094f10dcf3c0bcbb278e4d41bf48dc5bee27b12d6e4db02162c25fbe3e1f400c0c515780a16de31e5b2c1a4767e217b53076350376a49b8fb727b80c101673673b14beb6cba903874175a7ff2e45d735d0bf2dbf41f6a93af88a2d375e1d7b38f9ebcef5df2cae847f0d8ecf7f0ebb7c5344f3a73cbe79b1bb6c17c654aed80fdd5900b4584344a47846274ed68734f74cba3f51e3667d827440104fb0351a4a69eeec88c3975655a1d219d3c159c41511715955c279353bc7989f29ed6aa277140fead9ad9364269013df24cbf0f974362cea194681313c09e82ceb589a1124505ea42d72c1ee75d79ddf8862d745934f2f6a130bf8e201dfb1321aae5dd6c0c33d70facf9d65e1ccd29395029728d0b11b41d97f5ac83b9d86571e4b2073dad13ef9d7f0a05af90454a3c1379b13db005309e31d216437e7d9f49cbb8c68e10ed5a73b92554e09f29688938e6da700a1693ab661d74685231ea2ec7bec3661d094019c3136bfb33c0aaa92538952f038e05cd9ea06dfb1f3e6eaa408ea5cdbcaec818039cf107335339234437898182b3ad8b4121aa02ccea52449eee15cbd5261af7e3878f0d872a3d7ffcab5f6e70cfb46db769d388417ebf8549a7bb6950b75f3eca9eec14178ddd46b45bbefeb32841fb68408f926641dcf3aa813eae15aabf7620a7b124cbc441ffd6104f3a34067dbebd6d862a237dd218274347a30c4761264c6b85458b169232c992ba29dbb3903d1cba61576078c87c29b77d4e1ed56ed6b8b211803fcdf867f5a9a6d39176a100eeedc822057ce7a519a389b9319e0d0ecb44fcdccf2f9a27c21dbb413c96d8909ccf6291facf561d5dd012ec2ee86757ede8ef622385a1f998b5a27ac55c5e748c28d8af27b93e6c5f06c1edfefca4388668921923163466df3a038615105b3428c0d1817484c718850c3ec68722eb3afe8a8c09b82c7cf5ff75856e13faf659d75ef611ca7618ab39ac307fb3a164e3be17863ac80da12e602bd139a661586a00ccef660fd95aade2ac3f1e69c338be2cd627b53c02ca996a278fefb88fa9ef0dd063882df3b4a4e7d514ad91ce8f50b1911881fd531fbf8630669930ca10716533fb800a0d4f1ab2ef5733120b9023b60e00a6f248c9271a0dfe3ef55bb57770bc5e55906e5396aac2b0b9d6c264bea116882d0229f059908700e6f18ac1899635340fa560e7a13715c546c43b32a9db71581d173dbbde4e6614990b9e5c2f3f6427b7332933c2c1b241e2c4bd236dcde7177e18cd533dbe72e1602be1adf2d313dd5321126081b05fca95be915f91de406d58ec21e0fe467210423999dd59ba08feee576396666de508689a000d9d754304b47d8189aa503048481e0f13ed5c0c338dbd64fcfa5e0ca56240505619fcba8199b23576c843723279c08b783422e6243a3b5dbbc4ec9b468c99c9618eda6b8f107384d0e0870176dd085434b8726078fcb995fa4c7f5c95ec8bb55784771ed420a8b8bf7a84a5bb7cdeb46e01b540d7dc1f55e21b80153a8dff5a5f813b9df8d139176a1fa225a95f2bf14f95544febe055e59bb8558fdd74de02a20f8eafa42b0feafa56494be98dd554fefeb5555912438d4cab689225ab0ef347b5d81b8037107896a8e1dd230ec625a3c4421acc7ad2951e7d20e6ba39797577fc81aa33fc250b679cd2a4feebe4ac686d6265ea1fe84438b5e452452605d25a6af124668237e995ba8468232b193173837cff5b096ee3c2db1e9f6e7a9c5017899051c0d22c5b478a5ff13ad64cfbec8efab1c8404dbae6783595dc3e2539d7e1c7f8eaf3eea9a595cc06eaf56553fc144341d9cd6b11ca1391fc387a88d3c1f8fce38bed631bd8623171db8e4b81cb9fbf7735b7b23096349a9c2934ad67fe5898d84cc975f90879f7f8b6ace8cd80b6d61d8506095e7363b83d58767c3cb58904a0d58e0b8a5c6387642354237e43e2f0f970c257e5892953a66c47dd9c0f11a703cd440c17fda7477cc990e4de3ea975d59ff4860bff0dd3a00eb0b8cd347ae8c8dcf462e813cda10a516713339696cd77b9a47d19fd98a0f3e6b7f5184b4c31b9aba5f445c55efcd462e299c6762e60a767d82456ad5022679b677cc57c0de99ce25faa763be1c0a4a5075cdf04fb972f519a630c35bfc1c3d6c5351cf147773a292a6cc29ede5440c2e045c66884d8d61ef12281bd6de6d13edb0865cf81455b260f227316dd227060753cc2cb518c6377e649ff6ee1f7577cb0dee74144bac68415b4cfca6791fe27cc2a1c55eb1c9f037fc0cc6fa35e1e374c9deb6d173e45e9450a1fe30309b0c1eff51d2dd9ee526bc66f30e93b81ee18b82fb97b82399efea50daa883af250d3e6870a7ca36c4356c33f750432ca8fc7fb7a99940d139a6a40a3bae293b5a408b7c62e69d2fd3c6d7d16e1e70ea0c8eb1d68d3e0413501d51bb5951996b875056c9cd01ded080358fcdebebb5a6a622c27e0ae86a5059be9402c8454cb648a750df037bf7cf762be487d52a79b92263420c973aec2ec304bb6eecfbbbb21adfea0a9ac7807311e476adde6d45b7fd9a8100d6b821e5387a685e5be77ed58a4482fb17770171e029c69e4c16a21994633ff93db2743a069a0b6f799b0e96f38fcc1efe0ce3326d5654d7c2d907648347bf6430ec8b93d9ee14f0ea78d38d031c25f4b2fbbe4b15e491e8c706ee1f46a28fc054b8b0690ee125b11313761e1574110adab5eb12766f1e5fbd32dea05b1e31ac1d998b40321dbdfe87fd6ec0c7222dcfd9de022f0b505aab39ef519e3d154575f01184bfcfee3e57bd99162b8490ccb234d68bf74132c739b19edf7f69222bbc70b3351e54ed374b287904a4ca5a8e608031f111c480e4a9b8c3e0ba7bcf54ee23f105025d9529575d0fc2c324e9e3492072c9f4e1b54369b3e0fdd5c16771996e4d8cf2467094facfefd90d10c95bdaaa0b8f17356a640837889f67e694e23cc44b2574ac0a0aa3f57baff91a7368a3918eb90f4bfab6e3b82d4dd767d22746da5c76fffabbeae16245c01dae628a225b5ec03371f0ccaaca4171aab1a9c155f503f9fabf20b6419ac0a1c1492130e58c0e4d2a63d715cbc267b368408630d8c8d416fb65b31d33139eddaa773a1d4b880fa86a8e3802b544f27b86b0e2064daa4f56888afd50344112dc2fc5178fe2f3f57a6a4d7e43f5d684328c7f67b2333dc841189b5a2fd3b7df15c79f44093a44322ba04e243a0bdb9f90fff861b517e7e16f222373dc8ffc561318724a29cfed6844b2fcc46575e8a6ff47d -MD = ef1d670ceaacabcd5296230756429cdad36d12d5a04abe8f342065a550c97d8f - -Len = 25856 -Msg = 97691986f3fca44e9c434b25f3e99dae223e326caf81e327525f3a9104b7282959a0f6600fad7efae7709bb8b33cde34b12f830c1770a342efb6abe3250a0ce7dfcd34590cfcbeb840b3e59cbff03f9cd89aa87074c27b53ee2809ab250143ecd0f7baba1272ca4e4f16111a3d8d26b03e8688e0edfdd520f6bd3d322c243500d52770cb48950b84bba0087a5699fd368cfb0da3aaab1873b07e2fbd61fc4beb96643ed3d7f0e9242c59b004319e2bf769021e03d453ac12c472c797ec10eb74bab60c1ce708cdf44c4af200f72318bb7ea1a346937ef9c5d9a2ee07f6e87e65ea25c2ec9f671dbec07ab7b5cfb12c4a72e285b50eb3675697148a54a70d6d84cdba488c2794434833f1e56ce2cfcf6beecdaa986e7a5e8ba8d284c726061f9a0c7c8644a817a55b4bb8656d570569e89a69fb37da5b462eb1e4c5a89c5bfb6e4e74655b4a79adbeb0d6200057db62871dbe60d97bdf87055d50343f30956bca3ca8cb1b3441c13b0b53fd6d0ada221120d4c2c8798d89d95120b8d30b3bd5747d22a1ca8ff74b980438e3fb9789114d4ab4074afbeeb471385c3bad54d5a335baead0b18223b29e428cbcf327709805446519a829887197b80aa41634ec3cd59b063f18364e5e156e576f9de1181dffb5efde2a2ce626117934db54d307081cc780d546d2ffb7c52fa2e441ee080a04465b40172c8d3da824e1c7af58ae6fd2e7607c857fbf25752e74032775c8c5dc9fb026b950071c24611a5271eb69d9bea2ac1b1b651510ef13d5b4979fe1b84f67f67756c1da2d4dd7e663e0b6c1aea9a16e9951ab89e0f985cddfd894da492546351d37a791d6eb2f4de346de3d565b8cade06f7aa3fd5c2c656c337b3be225e676ffa429b181c51157b8e98e663a9c0a72d7bdf9eccfe0b1a443f07c8dea19ecc005e46fc495a4230dcb12ecc2c034c3c4668351ebbf4cbc934c57c157c9c7031c1741a2527a501076040820db51ea60ab7508a928336af43870af6f21e6f7d1911d01eae197917e9a4b1553395687892fec952a2c9400029d9542b174ab73fe27ff6d6efb562f1682897fad6235d4e559b372fb7e4bd78dcaa456add67f0233e6a5cd57271ef17f35a48f55e058961d30b3e746a7beb73ec586348bd2ca6b18d7f869ccee58a061bb868d743b2598d8bcd23c302d5767bd98212474edf5775401de88f6d66a04661d15c131f906a1bf06f9b8e39a7db1b14b5f6d90b166ee906d4074fd69bde534623b72b5a462787a1511a48775975bc3e4275906a5869873210773082fb90b7392dfea27c3a0e6b0f2004843470f2e9a6d602eff51bd3ca62719ce3fafc63eccb6e96fb0df2ab309a3b0ec40974cf2dfedf435a23e74a4d08760cdcb714d45e6d5404a787f67a72f3207d8a6edb66f396dcab618f311969a47c3b7d4fdb4e96bf7cec3a62bbf89c7a6ef539cd1b56c51f4caf988f8fedbab7129d681dc65f200247a21636c9a237c084fa74accb1b3ce8adc451bd6a13bad0c7c70fb95c6284f652caed6c8603bf35f0e1ad965120a5937e8e4f814647d4521a3ce6ab0415200c1ccb028c9799ad7b316f57125403a9a04d61c493aae6b1db78638f5b53d3abb41437080f74e08ce0d4e803993a40b38f88e3633d1e6cbddd60df5c42d22a627ec773607d9454d80749e025a37a444dc1cf979e06076662d86204f00a0575fecca514ae4f7c73097f0eec5fc99a9af2d76fd2f786fc504b3d0a78cd194462db3e3b9f340d93d7ab889260f45421c12d411839e22863b6d1abb8af55e9356d72440987a43080df38d482f2960b9633678f27410072e40680850b1d2d024ef27e6e8d427140ba163be34ef5b7386e8e3c223b6cb4fee3cbe2696046b4ed079e3a2e35742dc6a5f92f3554feca73211e059ab3318214f97371b956c07011d5cd4ff3a0713c2aeb148d3b43726234448f7e792d13ea5d8b99b8f55cff0119501c2a6f4cee2ef5efe4c0658904f1044f4ee11e07a8705110bb22cdf176ca5c0ce753e1993f68b02ad67354a40b095ba7c8e819e15396682f344973a2ac4e5252cb470b23e98bd22286108903191db2f4a9fdfd48a9df3b4da187b6ef240fa4c8448e4c5b610ad47d6022634493a092bc5e9d288c1fbd12e29f77e8455270cbd3cfa415de5a684f81f11383d72f24834553303c4a19b2b7846a948833dc34201be902f7fb2a26abe6b58e5b49302c0d462471a8f14c4271b9bf68273915ac59f70d25835054b8620229dd6a094b2989254ebbef202bfed9e8ea6d45c3935bd1fbc8a6186c6ea01a6aca9b2095c4af9f694e897f351d5a6898980e5471c9c510a097ef57bddc702d8724422f8d5120a8988064e9dea4b7a65f34d5e3b24d6a9e6be77ba1a332ab23fda35ce73e652f4d2990c8bf5b56c90b834d5e641382dee3e453d586dae5b39624d465d857751de5a2fc4f5059a7f110db4e0266040e748970598787c37a1bec9343d78337158f1a7b3f435d482cb24e9da36c6a0254dde7b6650c24db74669fdf5e3c687baaf54438b65f36a5399f2d6109e6d09cda7d971d02cddeb14906385fa00f0883b9e30b621dfd6d0f731a35bbee2c3a4213d6002abf6725b38c8d4e9a95c9d3edc6dad86dc2a860d54db5e014ac8727809569cb45f7428a60935e4b26cbe76b28663f23d230dac2954df4b4e1d191f8d6e3cb512546fa8d57121b967aaf022eb1fc928626051f02dde8493cc9f9c74ec3635d2a1f3ae99f057d27e90cab84af190e7767efabef920d9145e03381b199c4b8a1beba2fba4fda29159b636df96cdc2050518591c700a2fd5d37a515cb6a59383b977ca1c71063ca67260552dad869c6bfdb8e533fcf3c7101bb95029f210f867d4cdd4daa7120c59f2168f693824056185e706cb46e4890c5d489f4875e46180937626fdee2afaf201604c5ddeb0e72ec52b24abf5e45d13c2b0a481e829b5141ff92a4df055eeb8c6c7f4cf4831291be60fa79cb2fc2b6b7278c99ef3e8de6ca0de4792529bd0f46ad2ef881eafb3701018f7662533db5d942875653d28c3d03daee493bf0488ef140aa65007336d756ad07cd1f591553151480fa06ff14c871ef06b19dd99ffeeedf57feeabc33f711dbe9ea5cb1e812fd0610115304b61db6c2c43ec54611b3c1d1de32cb36a11ae506ac6a94ee3489f3afab28d293fea124fead4d4cd64c520cb0a3bd0c72dcb722c5d5aa627e790c8b69c8acf02d4cf75eeb38699f0abe6e12042eda38e165506d91ec464fd3243f36dcef1a56213f84c720ec102643d64c8434f636db12c97b27e356aab79cd476886184fd5f1024edf0284edd8d223291d5cb903f6d77779bd442bb64343bf866f2a020c2858acb775c79c72e3e1631b2895063705a900e47152870ef30210e650811590663f161c58e9deb8eb3a07243014c06664cfcebe14d1d1dc845ec95152b2d844574d4a66ce8fd228b884162b7f016ef7d9f0e9f1efe89287bf01f1aebee6d48ec22b4f7b20e10128116899175b8599542db45a634ac05077699090e5dc448fd771812d459608f221c08e97d20dc8c8e428c528fe6d8096144db6afddf4f593882af6ecab772c2d7c8b9d1843dcf1830f91c85ba89f51e9c6321954804e206807b63295940d743b9f3b3e25521228533d3268fc4b295bd3f5df618ab532ee94beddde30ea9e09a3f49818c4e7f697bed6d14b12ce53c5db091d375664e787a11366a2c3947313ede169d400eacf634e423719a51965b88a6ab443c275b61217701b25587ad4b9a2d07819de43e6b78bea2c7bbe14a75b66806c2cd5d1e7b77c3cc210f684082349288b9068db83b9fc34771863a761d7f9b40d9a975ec2a05adf240aa69a597a6a516be0a598ed912989e29a9fbada53cb6c5e3711058ef238c109bc6fa40de68db3e0b29d636e689a5233a677355bf8621128a84aaf95d89f4a39cd598a6d8e3bb6b1ae59254c66d8f533e7f5002ced480c33984a421d7816e27be66c34c19bfbc2a87be0c4d0b26adcaa022003955b05c347ad1aa86ffa25f198afb18a5134563f8bc23a2a4275d86d60a20027de6a1fa02c8fc1c7d38754df59cf2f756482d395232a703dead6ab121c6d9e524e41200aa9e7478990472c1483efeedb44adfa2c385c89e70ffe6a32a80b016d2e099069885db5d4f06134f8e1b6f7a637dc536c92ff8d0efb149d34ca253161c6e9f5248f98129239fdf4f33acd51bc863767bef8bc859cf441cc824b6337145e0ad9a5874166aab445f56e55db040779e7bd88333b787843ad8083f26c1a703e94c35337ffba04a95fbecffb89196d5714dd330c236e8a307f409f89e9e25caeae3c96697b15886073d880f47f97d86ae55028481d6fba02e0953ed68198bff580cbd6e35d7f1e20aac9e70864862ff8839dceb2d084f003f706c8a3dd43835c33f87b6e4c00ae332b1b6effe1ef5a4a164c8c11e5b41479ed1ba5b6a4eb8f2bef4bedd2f0a120df1f557ca09dd940a8c5e6cc2c03080eade95c3ed77f98cbaadb4d95d7f2695c6dae0078b4414ccb59b8f2f5ccd386c6e71452f9d0 -MD = e4969dc07650252ffe1d6cf6c84d16c0233ee3adb98a7577266b4448ac57f4a0 - -Len = 26648 -Msg = 2cf74ed39d611a8e49076d0cab863bfe052e6845fe118daa905afad021e1f766f0fc50a1b39710ea7f878cd4e71ba35068f44524051732992e410474e67b702825edc94a7bf7c545f77e844f4784ce9c20fc9dd1e1dcdbbb73736c4173fd6f979375c1b53daac3087a955e6713ea4448f6ed7834da87107826993a1e0f907d1b013a41ca41d89299d074210392748bbeaf70de353a415a38115a74f2045c211c39e45071cea7b862c1c2d50a0d4b2d64162cd8bc47313f63fa5f24a79888e302011cf7922e42bfc915278266cc96b2a4f2ca6db14b804961aa505124143c4b36228a3d15a7cf2f38934d31fe177ea0e50af1a6fc8c55009be9d40451c0a2e21e64d52ae282778e1604d9eaba362b818e274a898553d9eb777e934416e3df2f238ea5c6e2076166cb3076b38270c4dc09117c2135e733925e3336195bc61ebaad6aa41afb7db63ebfdfca963e0f723abd903073f2928c7db9ce658b08b2850c25be782d162e9d9f5ad97d9ad6595c22126c0e89a59a0c35ee18c7a305ed3cacf153c9071c603f1004e538c73297ab1c706cbd6a3748da4167d905683abf6c227bf140b1f35cc31925cda3263b1086b03f5ae61e8ee41f298ad9c6e390723df72a5f8432856a5242255765bed70e1667e7fc30ae94b60276c1dfb31aed4dd6b265673e92b8d114146c4c2698efd782c8d01a44212f05acaf73b574173b9760db96cf16da76db3016627390ba6cb4f35c637ec97f491b455c0721b0e2609902fb2460b311a6cecfd16f96492e34ed91a906ef68d0c93ef405e7ec0f81469be59977e2be3f30f318cbfc7bf9fc31ca83392234c91d97b7e1337ade3bfed3e4303df71dde6cfb92348e6feb492a4993f2942016936d9bce356d28bed960f1be0c6f0cd9bca1f1f34aa232aee0c2668f0540665d6fc9bdca183c595694b0876fa1b81edd00e6f95d838dab8c68cb6f07e5c75ed10438e5f5b127756c11f57c40169f95f25141fb1a07d9444d864e4c43b9b16f39fbc2fb9529b6e4c9fb37ba7994add9e057bce070fd0d64b8e452e58baa84005ffb6fe7f3a7710f35f87f28624268526fbb5e8ea88db272972adf2227e0ca7b09ad48915754e15c77b0d4ae43495a6866252fee09e14fd8b000fdeb5e820a4700b854e108588d3459cd3e3463d00b848f3c38e8dd1e6cfdcb0cb5287ab9cdcc0cc69cc050dafd00a1f4c5a20b00020cb0a980656a6f9249b2f90ec1c1ac9a72f47c26147502ba2618cf72e08301c76a92140f4bfafa47242c6d119e7c84f9a18284fcc7c0f94b1086064cd713fae204fd23ee84d3e716f60010c5a7f26872c17c8626bf79e73824b3415b6d0313dc44b98124f63d5f8427f78c32c56d818e3aab29aae6e8f40acc6627a88b9a763b918dd4b98b828a1b1fd98660de33f6d474d71692225546486f69603a1a21488a5242c5b629e98f62476ea958db8df0cdd8c8f5e65d07087a7482951a00e0b44ef1a0fb22bab996e1057d9a21a5c397ffcc456dac7e476029457a6e4e271fdf11d56f1f05253bc921c2d004c3221d12f4b91826ee6d5d76dc491892e07526f45a6677d86852b74ea9e72d8d473ce38a340807c9b31291731be826aad7d43c19b20c80cf5229744d01da5dddb4da5c26451fdbfe04552a7f6e8a6a5d3c2bab76a02f51abcb92bcefb205289d12e4d10fb1685b6ce81e72c15e97ae541661b935ac37b315db75d55b43cf557569418a6c004951bc6755af627277b8366d60af7b5e8c6eb58bba08ba3c9fae0cc2dbcf66b82c839589e22a89339350ac4a0fd5733f964a32e2499d3426dff90b2499e8256378bba057ad2b5f2751405eb4567242d6be0f35e80adcf088f6ff1998631cd08895bf85d89efa0cd81a4ff3b31dcf13ab6a8465a6e60d17ea4c88df2521b590b0eb57eb149edeb7ce5744144f4c350c4703726b23c377d0d4495c05d3bbf98c62e24d7a149321898f6ee86891ccea5531f2a1ee688b6344cf554232aa1a31ed26e268dbdf6709a9a5c9039880833617f19ed9977b24199b62d8030eb324a4da84536fb67d00df3f98ce5d4b245a637a106ee20e6678e1fc163a6742f5c29c7c059d2bb2f748ea75eee7bd2a8639b8a515cc83fa316d038f72e3367678dd5ffa3028647854257471317becdcad097cc1881f8603e2edc67efe3b3851455b367d8e5ce1b09c81c35be8f1b30aa1b0f8f5f2ceb1d283df74ee42ab357c6326692da5a26c01d843205c9cb3d85c6b18746ada43cd0f1b2a5309c799f49fda2440310060cb130f53d39cd428237912273747c8e5a162b3b8acf7146e3e61b33f03b224ffc78f4999244218b85e0a9ec78bb5441cf7715270c6e0b193db6af55df9d79be8281d8efc5b76f0cb4fb618dfb6dcd75095e7003aebeb276e9363a8686bc9ec82b664e767bf62e5c9c026875701e308e9446ac5fe6140fd692ef4d547a1af9f34390d5bbf992b7e1b7702f317b4f3604fcca2aaa47108bbeb73c483e2e3b23c6878bff3ed31fc44273cf16506173366ebf539b615636bea5b2b7cba2179fa4c853c23b6d9cffbbe56d99be30e72cca22387d4f2377f9011231ec382ecaaae57f34de1ac6bbb50741014a978160ce59c60491e64f30da0b8aa1442e42bc0f7e31973a0dd8c3c24eebeb7c329072ea7dd0b04bc163254c26758d5a1e7c601fc7a61760852229c9fb5c6889000c7203aec8a805910da9d1fa795288794a5b6e6a3321dc2121621e8509250b9043f2ac55147859b58d430deffc9d79cf1b126dce7f43176255114284788d6e53d57947095a8db2af8095529f85ca88909d09b07cc107bcb94babd862312e4bdb4f8a5653f1749aff860542518b764f6e1eb5b8edcecc06a6638632b6a9740e97008a6c9d7fb99d25ec074fcea40d38a83ebaf9a9ff1cbfba3b54f3ea77fb3107970dfc7e5bc913a3413fed6f360bceef6b6df539c8763255318cae85f3105dad8199884f2c2fa9082403adabd7fe8ca423633e05b174f907f491a511c17fef194ea192b85749b7b4e2f7031cf0620c57051f36a640758e52f2f87a0659866fab5caa9e2273c3ea4a2c8e802b15b2a8786f1661840c146cc69b45bfec31c04a044a392d15f81a9b285f3e976ece8ceb98ffdd51376abe1ec37bfdc92bd0ba188485c1a22b5aca54e0098bdb50714d603905d88828e2ff0eea0395485dbce055dc9dd8afab123fa20199faae68a46080c93f9c78e10b43d79ad0809fea5cbf8c5d00e2a84dc4f70cfdaf0f932fde82e7d9fb9da5f85a28e3664154426a46b426863d741e5bd98cf044b73f2c0e9610efdbd85081c7560accdcf484c245f16aaf08d201948dd67de667311dcb9d6197135f4459bee66585fe5f6896b215e35fa0253d1f8d3c222669e5ab001444a781ecc4ce1d9fce2f16e26dfc1e7452a2ef849bfd227aef6332f530839a78acfe6df6bcd410b6f7093a33a94d609b74a6b6d6ad80bee020100012e869517b2eccb7aba804d786e99a6c4c61db219a046522010a66494f769f3a4d7dbaa99e52a8fb8606cee6a22e3929a75803b5f27a74ddbe132c663b4b872dff50f62744b0f9a6106990a27b2d8c0edecc75b2275f4c364858317a16275e77c302ba4f20b25543d53108af847009685d6faf9acb1b51c84a5a141972829b941323557594ef42613f0d8572509e27d29d91ffd430473bf03e9952a8d2f5b50f7a03865f23b0376ad84f957f61f06dea39d404e3096b416a9f866bcca9e9314662539b505fbdaadd1b87c74b3b2f41fb9cb64d6bb8e03883e7b1cdd989e5a6d5567422fdab5013448346895a3e935aa340b947c2b15e57d8919c0773d5736c38d0e5abbb8920171da9fc5a20fed50e5db04d728ca52e45d537b597102f0b27ed7c38a41e9ba60ce4ea29c823fe5cd3a785f35c2de6e87916448efb32f925306f92ed9a9b354a9b26ee4f41f7bfa3510d1c3b633b090567f84298b250c64a3c3bbf64fdb5f886185000ed5600b540eceb0d9636188e1da907bc633afe18f291ee7c3f4c0348012aecdc7472d361ae3dedb494335ae899a2c10c6f239f53a6d7d433fd13e7c6143979db8536e467539a71aba5e9769af1fbc0dd2cdab918ef8499910ed3e7d567da73888000b818c9a9137d5bd70027befa63891ceedfdb351ebafde50a98184474665e057ed30888d04f84167a6c116945459acfce781d000c94d520365ce1629dcee685efa9a909b6827a66423eea8962c3aca5f82650d8e4d3d130d5cac32abd199c71f1b09cd4a258aaebdcdd1587b98a29400a4f09382de46ca76746501568e2fa6a239c36625a3eaff798eb24fcdff58b1e6366b8a64e32f1f479740aab17977aced3a1184b14b0e41a04dd8b513c925ca19211e1abdc6c1b987ac845545fb3b820a083b4f7883c01d3bf28cb1d65dd187a24b516913eec4413e9b7a2c987d41cf018989ee01b4c63a5164166b9d25248f889e4ca2f1c3005e744c6a543465523cd8a7438ad447e942ea8dbe0cf088e68bd30156ebdcad3cb932a69bf8a11c36719948b04a7aa2f1da0e54ccbc57eede228c5bb96c5e1442fa7f93573e650bb5154c5619577a2fa6acc6a187a25bbfd5fdba96bb4ffe60d8c864fbe44e0a9997d0f7b8c6d85c55d060195c38e7836493c46599a5b945f9c7cbe8c48b51182da34ca456fff6a97b369e106e27b25843e01e954cbfd4b948d6ac13 -MD = 70f11edf0cb3977c317cc4ccaa9da562c59e452e2cdfc7375c1530c70c37655a - -Len = 27440 -Msg = bc8905d2d9eee4553473d3495a3ff68fb3ea0d3e12cda3fd8b7d88b1859282590fad403578b98f2e1970d1727621aa5f86b1fca24ee116a0b5ce281593befafa0b19dead1bb6e44c71584c61807941c5d446c4bea2eae66ba40f3a6223a28a9756d7c980ea6e4976e2342e5fa1cc238a45af4bda37727a270048a6e15fc798f698efe7f60e682776140b5eb201a4b77682f67b3e35003c9c737f54da6db48ee07a672259af2ce712b1e5c4a2c788675033233a31c31d9391a3be2c9475f1d21da34961eff443ef135ecb48791c019be2003c72fc094fe7cf380c1559a007ce75bd9d8c020634a940c5c3d27d2796b9f28f4b0ae83021a11fdb72fa6f157de8b06d698ad80d877b638ed84af811cf2a498b57ea3b6018274734f6c01ffddb8a955db745b930c5cf42610f9830013456af9a69fa3dc0bee20feaa350b180aa1bee358ea4ef97750ca7e472a46e204ea5eb64882238799a3a41a67e926dc57103819cf78fc16b1f9a58c20856f995a480c792bc4a72b23498a30f916e9bf5b8a9173bf8ee76d44be11da1d9971b89be4d09cc0d5a34941562ffcee3cd8237087777ba9ca957f98249c02aee4d1a2425757ab9843ac647c4021b8a7c956bb4e7d46bc0e8a9ac034b3a07044e623f8d6061e20228d270f2c9debfec65b09e94e028b9f5e6d4bd192f1cbcd701bcd2edf778094f020a7abead60b59ba50463fe78dc2a039d13d164b557a54d10451b6b7321b64718cb2bd2f7eec440447b021a3956868f154f310c65538b0c82e361305bc6b39274fbcd572ff2b3834bfcc211aaff9544576e2638c77835bc5f80ee6437cec6d91e84a674ded34b0bc16eed0b533f1ec76a5af610642f6d06b003082d90a1b8c41c4cff528bf95481aebbc92fbd7febc356f9e9bdc3def9927c54f8b6eca750fa783d1f18becc968c1aca9fa66f25c2de243549676cefa207cb5b0625d64858243a3e50efffb4d8d50e83b698f19b6cc0dbf45c35e8c8300da50079a3d3ec96e96836d8ffd719e40491ce582ccc47b11283206c50bed36b4e132b9b576dfbd4f20c0f006fcd6380c0ac93cb8a8793587c25a0bfe076761b6f1cc4b26a2bddd8e62db010686afa75b166ba58dbaae62ba5c75c9d0c991b071bc9b3070395fa6a6ed401501134468a80c72b4747bea7f036743c50fcae29f8f821e0e24b34ba543208ea0793b5b089d5d7cfe0f54a4070d631281fd93d08b6ae2c338a6a8f865dd9d1537f15759e38579f8c6b0ed618732e080851cbce1f09e6f29549872fc44c0c3724fec0fb7961af264b2fb9ea97c1e600c42ff9ead8b9487cec65ca9adeea724345cdbbcfaaca8574f5751f0f2521a52144018c189a8d7bd122275c5a3affb4fc9e342f79973c8092708567cc2a5c1374710fabe1ce4e28f91dd765f74253796b187a4481aa7e4887a6a7baaa0e3ad90031a07fccdac4f6fdc7bd0cf75cad6a9699e921704a5a865b7d23403039839fce6dfd306127b78ee406217ae4f2d62e870ac7efcede96e217df4020e614ff0ce40e6fe5281def97b6c44ad7456b976e46545dd521d0fb03c2b34783540576c94cfa3cc6aa2433ba7be8814aa32fb6d2d95df3fcf387519264e180900375af7e0e1bacfc6ea54d9f3c5a0efb85a6fb014a0fd18ccb6b6036065033707acd73d2305709affc0603ed01023913733830a4a1513eac32e4ef98aeeaa84a41738a6dbc989906ddb11e4cd0c84abaf54d1b62e40a8484af5ac85f67962747e1d1bcf8b9c5a62a980c6666b3948817944d86e41d24e93dca35b134363cf78fe14dd11b30c67643b581a2e0b14e3c53d7a037d25386b6ff0bdd73bf25c56149c951907d28835178bd779c65d2deae9547aef6d38f1832f1fbbbd6a73b17ad9e2244c2c7a9e381f137561a9b1f2c26066adf8d8fd8c2a73c2135a195801b23b5728e2fa0bcd14dd7ab85e52a9f20eccecb9cc2af366c5b0705b49e30fdb90ab744979fb16732fc52a16ec5bb5ba34714ef4b5fdbb1fe977b30a19321b9daaccb1dc6daa2b4efd789a27881f6599b810060562aba5260a3c02962490fbc644f1a8785a71aabf026a5350be382a3f2e0bca523ecf5207bc7fd786188a30f413ccb093cd0c1531d31cde38fb108418ead6d461c6c3323354b5ba6041785b957bb072c511b40b45e3f2a336cb42f39592f3ecba7741d647776013ab5c05cc29013f6762d513fd69c99e4ad0bb4a09539b055bd2eca5bea2a9217bcdb49d033d28ebf71383a65c2bd8822d9d279025d1876daa4183794be34e5c7b5dd7b8b1307728ba5da9d5b7fab520c402acafe97ddcaf606cd8370e67fb837ac251e326a160881997c43c9154c3fcb697c703c4d70f4d06db576996cf1528f291afa7041e798cad584f5558d8a9987dc2e346386b93c926038d8b45774fdf8b424d6ea9f626a8de15c79aaee4ca66722aadc1b4b9fea6168be706cb0efff9ad6ab7c4b8c6fc5f3466a976e4079b094c256300ea30d45680caf07667e49a19c1617b23910f6f3248b18194a8bfbfd36449cfae296e896ccd473654dc96c2b26fdd1415c34df3a4738cdc5e5d8b9d57431e3003f2c1925b8487252c79a3fe562123ff15eff12e384d5f065e82e9b827610920bce6e883a52f114967cf8aa1676ddca89e47a773504ebebbffa96894b656913e336631d1dc256c2f816eb95088ae6dad399abf77aef01259cc4176b7769c5cd502013c11531ffe2423a7be801c7b6d895229c78f86da006c3edb9294fa9aa281a34875a6cc775de3a92b18b4a54d42a982a55e3f9a44ff6fe1e84ac1b4ea38c0819c6d168ab3f1ca9c694672b5ac83aa457dc21c3bf965d13ff81da237f3561e478d80f5206e506567e2c62eb011b6f81513b199ee4fda3cb37b79cae65ea0f74f8c6fb72fff0020b618265d4705430f6c17ab2d43c0d30ee6f2fdb052749fe8142977c0fbfe77a8e179d592cd0fbe7cc4f9fd6acee4d6d444eef7d71efda97d2fd537c726d52d5a84986243c4898fbcba2b46c6d2246c0947d016b38e2264031d203e2e432ba7b219f43b04c01b4d4bb63c05b60027e92a8a36c8ea22ab4626469ae96ab36a5d4c1c0dee3a423d6da6439cc8dcdb37f4c466939cdf9ef0c6634695c7f0fa09e4850555ea78bd587758ecddfe9fc60d15437776f0f8358b7b2697b15875a982a3f9505cce34b3f4e0d00c70157342ffa144374163e8a8e3cb0cb46e295d248d32159792f7f2a8ab30a83ce3abfbe4884f23109374154b923c72173ca92c1d6205664588f6271de3ed4df8a9309e2d4f758cbddd90029fff55e35a9d6646d6a99467e4bf576676278d3dca4131ee8fbd9add7990463538b39dfcd910df41f2dc7596ffa67a2563fe86f41c4c3e418e4b4591ee4c052198377b1b2d2772a1e4631f8fe0cf0ce849c1711d891a944bab80fc4686716b5c210383cac151ceeb4de6089f52a95e23aa28b1f67b4cf26159e73567dc90d74975902e883020529271dda761afb60c7c079ce03b7d43d7372bf677724b3ae77e087601dfe4039c1c02a2925362858635e486823909afa111943738f27cd00a6e5c1d743e678c0a0c72ed4001058859f5c37dfe9baae0eea52511f064cbe0beaed30f1c20351a3ac8450646d7234f0640170bdbcfcb781e56511f4445c2fd72941fb35021d74e9cf3eb960d62263a098971889031f5e5be999ac79b11ec76d4d2a4c2b6cfc889af03f9050a2e98e9d24645acc28ec4aa5e0384a37b55c2fd43cee485c666736bff7cdfebd398f5df0f1b15c0d92282367b18812b4b9dc0e14e0d5194f5928265ecb312b2e03dc77a0e6c546d4a99e93a744d22d7a23670d361f29e78cae05ff8256b33e2b689885b5eaea41aad515406f815dc3115dc5d440e330d99ccbc76a307f9a603cd08a2e38e76675157e54d2c65073fbffcdbe0a3d133418061a360e722e30b8eaa37b1b30c482099f0c24f2b5995afdcedd1a5732977bcb520119944f4bbb6fbc4933f4a5698625d0e74d4842445bf205f4a06529574d1b09ea39a3d0bf84ac3b2a7a60a0bebaf32f77977b7839be022d7919d9293af430b23c5fe4fb70d398edae180727aa65984425ca345c60cb54cdd64e5e3b2ab731d55f51feda47f05b5c3ed4924518d13f9757ad1af8a1ca116d72049a660fdd47fbbbd89a752c221c104077a9ffed440eb17609d653e5026096b50635b2cfaf99abb8bb60d208b203901ec9f35f12072d19eba60f7512bc6ace071bd8275375506dbec4f7fbc1e839643e92196c6f62c5571d4c6e67124056a0d00a2bce837793c935b908f8410ce6140a9ac22eec9cfef473c39a30cbd64d91789cd5ae47fc8b4885633acf6e663128e8a997ae72ffff7757d23cd827c6772b67997fcf884e5f71168a368a323e4329428640f3e7d1f1683043fc680d57fbf506c9d03a2cb338cc50f6a43174db449f7ffa6405355bfb5065dc81e764d20277bbf371f61d743ee29c6e2aca1c865b1007cdabed42e546b56066745d167fb33aefe1090b41d8983a60bb735f1187b00642c7bfb2f8b7fa2288a87cd20aa637c50b59418282296f5d05a525f73d266c0898af455c3d183e1c456c424f288fb5a07524c162c7adead1f4f4e99b87abb79f714fe8f4fb523a2dff786edb58825654970a30b3f7ae322094706652d75db851356d4e8119ab17dc1e95a77f82c64268d8d2367efc726ed14ce14524158598a94cd21f0b7f6cfdb10a8b95428ea4a0649f467ccabd42c76d860e2d19296b7e2c1e46049b15dc13352c22e12c646498d1562caa9f2265657ba9c0c73afc5793641391a437c34582efea223345ed4e5436644d680513256f83 -MD = 95c2851523aff68fa1e7fd197d0bc9dd0b09ecb9d8872a82bc9d7dba909e397e - -Len = 28232 -Msg = 15d403a2f26bf3edfccb98f34a00d9d019a6f497bd0a1496de8c25dce048e7f9a3f541056d0cd9e4242de1c7c1c034f601d8a1ce5d5c86053d68a13669f12499c0a807112c21a26dd5357be795a55df1adffaa32b6c6f1cbdacdc3de43e4c351d4b6fdcf17f2791077a90f5bb0f87c4983e6b6cbae8f7d6e1b8333de5869eda947e8ca4617c7845672524429f800bb84ed546ea22e0151786a51983e8ec7ca2a8104177f12e7ebc62ff8c35b5707402c511079be1f6296712e009b04cf48815bebd28b80f19bd7e9146334f9b45333c819e3812767fb73dfce58e33a02323bc5eb1ccf539d2b70458a5a3d09f62dbde1ac952be6f014114cb42119e70fce1feeeaa88a00fddfdd64faa7899507dd06fe72ee2102a0f5983f4723e414dd645660513f658df8fe47ceca10bea4ceab35a7d3b60b8361e52f41ef26edc8563c07a386a9080478d2d509645e853f33df726537b490721a2efed914f1db0b619d5b3df3ae1a6c64a1b09f2e59856d1ec0e7be06b159d6b3162e8f1e4d57e5e6d17ab8fe1644cea3b4ff1892c867367797b93ca8750eb713e6e7eb7602095fce1e8b9c11a82d311f53ebfaf674d2a226ac136786c8561d24e5507682d89880ffcdb66f932d7d9dbfc69ccfc4266fba14471bc60672d911cd5d92b7ab97ad51622525bbec6ede1b6b54391e63a4e68527b0f9e1913a409af694d4365906efd8df70fd078330f6b10b46ea703bb6de0b482ed64090e933c187d33f7cf5ee071f5ff469dcc23e6d6a88e4d94cb426ff55600bda6c6947598d6962fb10e5179c2ec8fb8fc1105fec4bc8762b3a36bbf26a558d2cec861c5b0682892f7a9349570b04cb973ed55a1b5eb4440bc2293c5f5311fdf5484d30e034bb900443654ce0c0f9acaadb7af8a1aa34969f6df572ed167aa35c09284b9120fdbea1f2c5e7de5591e8f0216501273731b30fc2022545bd7ac68ab67e3416d12e5d2e0f1ae4f9d0b2c69097ff3d540e91e4844ab91c0f4ff8afa6d7b6b4164f37b3d523cc09da3b468db2c6b073d1363e71268b8021f2d5dba7d9f43a933aa30109bcb5431f299d34868034e16d45b71ea21c0fc0fa96560df44b96719929d473a60b4de6ed8dff64f91f6bf8f1599a1bbe8f5ee270a4da75de2344c38d8bea74d4eb731f3daf68be2dbaf35fc8b5e61c0fa6fe4c4bc46afbaf8a8798390aeeeed984b056d537e02a6c77527cba00a308db8a7968539d0c87ada7e658634ce7c8fefd8bf17ecc7090fc7e12b98ee2d9c96b62579d50d8ca0122a3e96bd4f9ddea8b7e8d5900161ed826f8ba7d0e05914607571e52091cac5154a5183a54bad83cc8313cf623bff4ea320dd32f000ed367f79158f14712b9608cd6fc2bab37e1a5fc3c2330af6cfaae68e4e4392da8a51482378ce1d262f914115d1ca7a017ff1071c7c7706bc7370d10a675025d791135f171438a72b374562d630017fc023b626dfbb21c2078b3ed717a0ff257291eb28c690454efad330f261031e187a29c8439ff6b9e96277638d4893971e561d4739b4457a710f93d25458b366f099c2a5e1dfc7a5c957b89d481fb7be7cdc93c61662dc4eb9e3f9a82d2fd97274a9bedd8601a68c0e51cf3abc0f75dbcd8085d62354ad4886226530c158ddd731145eedb4c80bb304db3bca3d9a56858cec7405f4fc30ee621576fad55648fba2842344d2757fe1697e8eda6132e232477adeb41fdc1fb6da67af64cdca93563553bc7183ac6b6d989628c9bb8ba16869b6368ee876c2186b836f1d0f08558d861d8b022cdf66de1eccaa4690e70cae70190bf5035eb0a971e336723da207f8014c0f655280faa9687c73afa5e79c6b072ddf64e4e673e0aa11a602ce2a132c3359ca1979238f66024025835effd9247b6f117cf1c0743450993e4d34f31f9098e13bad25599d8a7892205020b23b716957629bde5f4a3b21e45fc006bf75dbae5ce47edb75bd8d37fd04a49f813bc83d71135fff255e6b7a7d9af9b7c1ce53e037453d001a67e4cceb42ef2fff629f8436c427d8b5392be6ef6068ccbc71afeb0aee3637aa1537a3e75b9e668f487dca22f581ff816312e394507bba0218260b324018e6c75dec697bcf30b7b345d97bc027fcd80c54a6fd16ebc114352a7cdd67db4391d49a796a030e54a80df3391598bc06f6c8866e9fe182d74fb8111aedf62054cd6463753227a968cbe1c9231417522ed04890c0487eb61cd11d64669977afaafdf941566e6410eb77e1400e13b66ae2f90edc42836916005cd7ad068c66e9e4a805ac935b12e56b408ee070911066b1d58df17bdd1af32027795371134e5f60501c1dc2a4ee9756ca4d32f0f89ff61a0a4858b2b21f0e0ae574e01cea8880cc9a9f0d5ac831973c69aebff5c6cf6989ebb07aadaeef970f0b5ceb806ecffe77cc20f3c221a6659a9315dff5881961900e68efc320075edafd83de320c6f18f0892489af6d97a2effb252b76b9284ebaf6d42089c1e0a5cd509c20b86ff060d5362c1768f89fafaaf65f1b0fe656b1692984a567e1260c7499085b79f5fe7684779a25855f291c5a192637177c4f1a390aece6e41a22035f3b5af6fd3ad3ca8cb2114c8b0dbe598bd81cf824075be9993f9f8d94e97f2afbbc068bc8ab3acd6c6a03f4f080d9e7aeb7a5e6cbf407b0082bfee1e0cb87d3c89f8d7242c37e0f8223f4a74c551657413c438b65eefd0e04449d8c5e2cf6ae445a6253121028019c6465dc04f6de28d1da884e884486442c3dfdf563aa260afd712796bd2dc333e9afda2ba0f29bccdf16e6b8b9815e02de6c92b5a7bfb08a62784fc59a58ca17186ab3eea6b4f9b3c775e1426041cebaa954ee3590ca00ad01e44d68303dc73b9729a5cd8cca529e398bfa7412f262ec0b8b72fd957590d36a2992e715592511f4610220d9bf50bc93adb4e6481fa5177384c3864c3f0b9de9ccd2cac0177e2a9ea56b8103e05ecf646f82f186262fbd7fb552681b82bb8d2f526fabb7153cf6146b447691f9d7273a55f72e43a24d4e9ea1a21b99ed4af1a93edbd260beebf4f4371f7a1a48745473d584051710985b4ede35092deb149bc6069a076390f5b7ac7d7ef3f378a0e7af82ac1e66fd9b640edf7db96de8b2cc243e4c83262804beabb2c58cb3f6d7515bd1f1c2b9d5c0e96d09feb4d0729003323a460e2ed0736a708b959cd24f9211f737d7aa8615936bd8023a83ec1556e18eaf28e0e446dc5ba94c61bce4df6bba0048d02e6249ad6bde3cb39f175d51d787f167a3fce799f2a499bc656242ceaa15797dd6c4fe5959fe3dec6ee8972b75bca584efcf3f56cff0e7f81eb1062572854e332c248031b6a67a679be67f4e1cab3002fce1ba7d641cabc74177962aa40e3b82a7179bc1126566978e8752345cb2255473cae5983f96798c861c7f28aeeec60ed0048d71fdc9a70ebf41dc78b69ffa0bece14d11b2fcc5ca55163db9f3c5721a2f71f1eec931a03fb6ac6a75ba93229bc0cb6d847e9e14f3270b3e492310c4471df65572153be6acfd3d78c5b95a338687ffa35af318ebb984520d70bd5f410833e824b65246eec91b7ba3e36343b15eaae49b2fa0ebbe6fe59137bb131f5cf009fdec2610f12d2669cd685928ee0086b210c15d08950198d32f2972d4cf8c71087e184bd1b9265780c932918ac7b581361a927dba8359c6d5a26f4262fe642d980f3582051d6eaef8e59f16f95f54e09f58ab0c07553b7c559185a45e0a58686117c0732b7c7acf3ab90a63f513432766515782af890b2bdb52f9032691fdb3dc3e45a9c584bf2aae9a01032e9224c813ab446bf38d5d47ff8d26094d13a8b261c931606394b033fd3f2f7ee64a6e353fbcee3273d0b6730a96b901421e0dd6ba6f1061764b028d8eeec231bcaa7401330ca180b0f18b1fb5161e95960f81831e967f178e060a99ec4f75c62240facea6212ab13b7e6fb06771c330c966a85a36c5b9ed1b545ceb8dc7c696b79c56d00180d64e63c5b8c79a30436d4cc1e6ce6b736d6c9ec46df4ebee113ddd1b1cb7cda230d2da661ae7d5e81b95a09fb1525526161088b4a238af390226034bb108630bc6c8ffddfa73a2efb864555ebc786c64207379d3be39202ef5e9eabcb8248a3404bb54abcc0d79eda633eb8d6cb31994390fe2700678e73688e3c3dc96be7ba17704695e2417c338619ed3ba26a4f56cbc3043381f7a7cf617ce5f39d118efeaaa3ebe4387253776770f9e538e908824169f2c8a6db049c44ee3fd32fbd63f55fae4c41a69a81f1e52f0bbf809383a70f4a6fef575acf6578adf2e867b68e299f5810b3140331296920cacf62afe94c9c2e24af7cbd2daf6581a7372e463822d368e0436af389a85909df1fc78461fa50ddb810fd4d4804733106ca6ab3896661a763f790b3b1f51fb3f1b7955b1438931ed41ac24f48eb0a87b6a80546a87fb3dd42d96f8bd29821e6a99db67c2a8ecdbb20d6b30e55ed924960d9e547bef52fd124f1edc2141ac969afdb102fca84667a434bb9d195917340ab66f4fef24e3f4db245f3a29e027e06aa798dbc1ca3c624e681badf335f1534405618b26d144a1794e06a7199d8a783427d146a49725681b0819f8155dfe1edc6b13bad56ceb8f871c738782c25aea920f18c83797a7c584a5251ff249a3d32e67f4435d605f0b8f10447ff806ffa40ecdcdf4dd341a1725bfcb7a1c71792cc48c91b9315405c1fbd9d7d4ebc41f3104d47f41180512e988c88b8af66de49849397a80f3a0763f57d9dc4ac092001e0ec39b316a832899085fd3e702b78c8206fefd3f06ee26d01d80903638f968c7a71ba04a6716a1c22ed63302d3c6c796886db8480d85ae20c77eb22b9752afca483d2cf0706834e186dc3752ec142c3267d62a305a1f62bde024a08f7e465b927ca8afc828d058639ac24f7bbe3830d20ff8c18c8f03fae3f202f9f6403cd2bcbf0e9735f2f762e4c538e9d1cc9b6c1 -MD = 58475763bc0a97d5434e97401924ffd219e4da9beef778dd0384dba227739d5e - -Len = 29024 -Msg = 9bce10abe974b342df9871c946b46c2c64c246d216ffd8801fef277ac0a193eb893452866e9a1d6e1d9c29538f1e59dedda5b25056160f66cec1167f389d6a0078d522f872847b0067bdc96681cfb48aacc7a087a8366d165c3461b06ea462f310ba69471dbb33c164043a48444ee3f67930f9c035e55a5a7250f055873de38bfaea0dbc96c6af79bd786241ff2350ebebe9a34324ae3ef8b81eabb6aef1558fde6df89f062d55f019222a9bdad76130aaf988589e1681b9d5a57b1a094721c8634c103894798fed21087a9cfef1808f5f688f47cba78b6572ed46cbc0c7adfe328e3fce6931c43a7d343b8e93f914ceb23f9f57d2e8c5c436fff60ffcf962f8f33b6cabacdd5b9dd4ae53b7c07885b64a85a2d2dc61959dcae2712fe566a8804d5c7f158606bedfce7cac60aef53a0fd0427ffe109b64bad59ea172a295e85ce8f85f551f3354c814a82dd085f89da1eb7e1e24971d9be1003c6c225c0e88556d17f6b39eec851f4e3abd516c0915334442678b986fa0dbf3c3bc853a5af23384c12b762bb9b9ae243846298bb10a8f8295427d3c1add70553b78e565008cbed4ffe6e8f023583b3cacafa10b77e47b4e809740aba5b867cfad88880488c0be06d80f4f12b1ca8f419de00114e40cc0500a4e1d0c989b8a0820d4b7407bf5fac1558ff4bcec7872d914c091cd7fe8262f3b4f5c877ced9fa99c43b94160923bae7d4c1f145ac8abac1839995fd0e174941b824546d8166f5929bfd82ebf014975582f184285230463b13260f25f607426b3cf206e347ec2c1d0305a2f21a9ecbdee20266ff5f243a6e7942facb5cbec8e0a1f342a188d6088987c886e0cf2ec2e480892c3309b311cc3454eb8598ba5732858caa00dab10578a8caa100b4410716dcda565c088966e4c2e053cd309677e16642af89a409bd6ac480840a307212e6559a47e2d1f3a448b379c61acacf957db299c5b48b4caac0898e9245ea3e80c3992da35fdcae44486495a4e6bdb25a57f9168f19e6f6382a66597e4c3812ab4f0628eb3baf05e19474a882c9800b1100b83d5e124d92eff8c9558a95a07b2ce92b0071febf86e69d6246e22bb82664286e62c54625af5ccc412759bac9e470128638ea2194cdddd39bd54595dc90ce0f8a4b671e15b7e9056c236e140aeb0f5b8656b64cb53721c7aff82f8053d6b956aa4b861284292f4488fe2a49ea0b6534d9de68c8975f7cfa1d03f283c464a06e2ce7d4bbf79f9a0a460c30b4fda21c3ecf34743dc1a329db41ad511894c73de6b0a4c582f667b3b721c1f3fdac6b9ec9f4fd5b04aaaed2fbdc48ada74b7acc30a406cafff73e06db8ad3f67c7cb45776d99d9fc5d8dee2cc3b6a7ac85efbe5ec958267ab707efe080fa6bac9f508f0b5fb99b4e9d2cfe3dcfd873ae455c7156af3ac2dee0897139d1ebea36e9bf5d517b9863cf91ede40ae81238093b668c53c4cf880501632f23b468062c2d7f78f1cb1c79a6c1396a3a164c3ce4f076d9ff11fdbf17a2fcee442f5905b6f4f8a892572e24fdb5795675616ec968eaf21eff9dadb13b4bbc79444da630fec492b4dc25b7aef9f6137165d26025bcb34424fe71c8a49a850b97cc1338cf2928b56679409d5dc40b7183b0700a980ad3d2b3a29334e15cd7510f848bf52a62a5c9840eadca7a867cf954fe44546c77d00693930ddbb0a8caf6aa13bcc688cfc536d74675244c66d215abf85427e72d34478b7ae7a358a6e5623022ae9333980f6427c6a1951d8d942c5145aa69535486fc64ff27762380b0fe69586a4571e60bbc3c39390433234aa50f8e4e04f6134f8fe6c9d73b575bb3301c5ef7c28be142a4dd454358d84f7ceaab7b46de19931667d981feda3d62776113db5df4c9b03b85d492c97b5139b362edb39ce103fc63ec05cea53a1dba83fa1478a5c2727c7ec8e7c9d254e90a76759fdf58f4fe75bf863259d3453f8e5f61e8ddd613d06c94d3df9267cbe7ea4e8b87a680fe5026b09d27ca90e2ea04940057b1f8d129a9041083948fc89200c20c6fb11ee94238c099adc8e4f96844a93e289c14e3c65a56e59d78523334755a601da8399c1cd377e28cfbd873ff77268225483031efa813bcf3e5b8f413709ef05931daff261e5ce08c0c7336f8c59436145a57a3ebbbc2fc4f84caf4771a1722edf708faa842f7fc74a3be2b9b5579c1be7d8e2104baeb0d77fd8f19aa9b4c5f9fa0cb75e967d09c0e67bf3a2f50608beb57df9380cd175733f70f4cf31ac51039d52b5832b3702a2001804cfeddcefc629051e1a81ecc424d1b537699bf0b9b813d318bcb515e0c731809474e254d7cedd1ecf3c4d295368b10627de5b4a56a4081e4f6fc6722accf5560156850647352c2b9b11c14f79bb77e454b1f1e1be33d484d820d1e4570fc608f9c94859c495a0abf04f70a7cd9970f02c68f28f670423b7215459d4ec2c1e09ec619ec7b66cd5107d29fdcab58f469a3d87cf7bd7815025d98ed0dc509e77e937941ae8b32734197055ab30c8095342f6830b6f8637f4416f44d9532ac37e1789f52f354161480798371b728ba4419af5df18b309848a9a30fad5e1e1576b1541f95e25d7877b6b5362c0f866cc7bf2aa1089eeb8138db0ed3558f11ab6f9830e152a42ec1658c5104d2e4af00e7d0a81bbd18b485177f5f278c5191d6e93c13cdd1604f5aa6a957d7ad5d29dc6cf132b35721100cac409cf29ccc28feab4505cb593f49a902b7ce9603a37e6a1eccce5120e0897ec0c3cf1ecb275d8b7e5c0fc33369a218415bbf291ddd3510c50987dd5e7ea6441bb3ff92628bb8e52a29379da805e50e2a3f31774334d7382850623f5a23efc485b63536a81fc27577538741fe3c97f3860b2c6abcd0eb49104769605cf5ed67c67478f2e70c02a12d8307977d35422e1d67b9e9d2d8f9ab4599a326ab1f2795a597d0ae657901d21360be886f196d29b7f9deddcb748ac58fec187a91c726b7ecc445526c8f4571f293b4fa1a0fa14b1c6ca52cf0ce2501b6e9d1455416703361a5e0c6427558e492c3f1d6c84065fc136616bf890b52c68137d56d3d338f73cde2a8f22f54c295bb997e05bfd341a4668f387ede56997db97e2cdc94460bddf723a6bf7d5409ea35bc626e47f1bdabdb91135136d5838c2668df78a1796adba90fe013729cb74dc7d6a5f8aac2627a3b11af21dbb0975c909bf52babf236d4a94e60d8585553253b8c508d2e6db7774dba15d413105d55bfbf76dbfcd9f630c0892ef475a666da578869141d1b450bdb314c54271d5edf7b7d6b72da573356b668505112b877d4e472fb74bdf3929eab215c875ffe21638b7ddbd78e9474b05392d0d576b30e7aa9f10b97571e289987304e5702dc2f47b866cef260b741a55fb0b56aebbeb43670aea36432c38f62350629ab5ade0ef5cae04cab97e8229da16908f7b701ef6fff51cac3980b4d637d4cf56aad2d48d389955eea7d51a000e266d06323a54a8e1f81899ccf1eec0329aaba7e44f0654bbc2a0b9758174237ea4e159877d24af998e6e7d72023f4a9ffc781ce6750ebc42d4a5c9a716591a881cae07dfbaf79193229ec5dd342ebbfc94c51425d7564a6a29b57db106114bc6f8238faf7655e56b5f2a01430a55bac4de033c270865758e4c506437d3353db7b1d25f7b21b8119e8e80ce57f71cbd8542c2e36e6ab4d44bb7171b8ff04d66e6f44af5c75fa6bc894b437b807d1c4aba5d84a86080ecdd1ee479f23dffc26db119edf11882aa3cd81fe297611ebcd8d0a8b8f9b1ed45f6747ee986d6642ca8c2ad4bcff33d2b18e776deb05e5e76ee649ed065b70288b6e8c0f647cd9ff4ae7818d4e0cbe1b1e753ea9844fcbee2f1e2ba7b6af4530da4e86510c3a835a2f56e0729e21702c71e89d5bfc3b0b28999d7861a87fe714d370fd5d978eab7cff400d2ab327922e32515e2b5cb0ecbc33cbf8c2e2b49cfdff3ab9da0d5f988c450dd15e96046c48ea1747c0ab98b7d2851172736e34ad13e4158171769793b38624f4b64da246a320a221c3f1dab59418d5b01c54e9627d0c6a1ecadb1de4194cef3ed9e2e768665c5ab3db365e2b28738078649aba0264ff9f598c43d9d3e51ed577705cbd19ba26a7c7b1830c64b61f7b93f34a8ed7ef431ef85fb7b3a840853e6622c40ba3c707f123ecdfcca767a22dc9726b4f2747624dc3ed3e93aa510892d49821b94cb486a0903553863b6286fde18906e43b93e49684dbe06122412f3a897a7bae5daa2c1cd634e62269d05255a5df22355bfc4f6001d4a5055837829c4d6fdbd41dd07fcdbd90a08879d98f9cdb1dc72aceaa2d12037e9667945c8a21e81f4812d64f091c0df289a0b3a4c4394ceafdabdec405165281ba701ed7ce312133ca50ce4e526f8d01aa535e5a7996c0efcda0d17260d3b6861a063dd1d635c15369764ff6e02f06660a87c422371affd43ef1f0dec5b1f735bc123b722b9391262e6d9f6e3dc541c8b1252b25842dd0405986832dbc18dc35aa7d5ee154b55655201b06dff19703d0a816dc8beb37fcdb2547d28acd702f2fec2def47d901db874769ce71820f1726f6401f7bf1a04c4eaa1d241b8121b6ca880c35cb43e1e765ac3f3d4b7a944471a38d3c1d20d18541f0eec3085f933aaf88017a9619bc419756869d96618d5159b8e47a9aff30725b00a4f57af02f8285f3f304cfe3fab2c44d243479bd6407883c2c221a1626da45e1250399ba5b58f5d2cc1d9f2a0202949a034b1d18802ea3374f7cc4ee1c84a79b5b358c478082a72c730b2e743ef9b1440929aaf9498e55b234d0c10e783927372cd27c1f07c94209d016a34c155ec053201847e927ee43b3c36639fea3c170bc822490c856f56f72cb882737effb6cd02f5e1c6f82171845e485534706e428324471f1ccd7ced56d4ca7e1bf34965ac21e445213c2d27a6d7f773770086af8a15a02c6b3f11b1d053bbdfa6b4df83531d512115d4fe512357c820e01101a8712ab1f38030ba6ee3f801099c3a0e9a3263b1080d6921887a4c3ef008388bd7e8c210f6f468f35f12503e8e75096314ca73a86c805f13581c23d06347dd71b8418a31c9203e491cdbead8f0c999897dabfb9bb -MD = 9d1ab78a86f0bc7139e8827816e619e0c154c262aac57e1e115e2376c78ec29e - -Len = 29816 -Msg = 7a427181eb8df8f0cc9cf6b96a19bafd3051ad916ee834545acbd8bf5567a5bd6f19cfbd2ce59c06896a7d4b3a157e803696e1ec7590067ef8958f640b51c1dac7052c40da388e708ba9f54ef88724a1a2e438212c688bd06042d98e7364a1e88af0ce327ced97d5da3fa4e92dd672077e25f8581cd68bf299bcff6516090f90c0c1feba9b6e7fde7f16d345606a315ad2406abbcb43cd8cabe948107ba6d17a72600400be220e328114c98a19ab2844a41dd66fc3181a459fb3feb82aa5b04da8b4282d6d710b7ae823d0dfe001216bfea4849f8cbb3ac57c016784ac6c74b268a7b26931c3405dbc2a2e6c3ed4e277e7bdbb71ac96f5b54abacd9d8865e550bc20e9db9080738406102c5aba8c35116850c50dad0f13bd12c8762a46f6cad0ab0817ac14106d96cebf12d1dd91e0e18745e89c17905b84db12ab546f89edd93d45820345dcf63c1a1e28f82d4bab8e4e846d46708096b3ad80b3438a8514147bc07209aa4ad61ef415b5f8342360c1c5f59c3242478cf190fad81e1f5208286c6131e6cbc3d4e3638c03f97a7fc521f381bc89144d05e78d68600eb65891be191106c130b0b933706b582286c8a457e00e17726ff9c93dabb2943ad8fe767e88b638c262774db8219afd9be067c30a9485f316dab59f9af3c1bccb0cae810fc3391013e882581780023a8d10c2eae318cf999ddde951a66b7b20e8dbd0781ad283d6d94a37a2fb958956209e43e38973d2512e00fba50a1dc907baccca2446bb7bd23f1100f20a67189b7b135175a6ad7862f1cc54646e1194bb6867054d3c88084b6ac44412ecfe984fc7f75367dfcfa8160fc85c56794ec2821b34e9bba441148b85eb6ac84a62efbb2bd0b382dedf4ab3b07d7b42d4dc3ca5fbbcdf3525ec86d8b60edcddcc9c0727d028d88e4be84582fb711af127c3eb6b2f864d856793467b25b6011919b2c6dbdd862a53cdef83cb192e9f2c190bb61ee01a9c71133d3bbcfc6a4143daaf161e7b7311980dfeebd6323c74b952bd8404350135c2d1f34fe260b30425b698de3ad276f527b31c65ea6d21ff607be13f6757c27e3f48bc69377b18b2855677067509173ec66652d950f267aaeb3c7dce8d6de5e1b221a071017521b32c6153751849de543ecea72f51ea95dc203c9b19bfa0f3c5e103a75089765670e28035156ab954a05694234f337d34fcc9244208441873929697daec17a5404f6e5b24cdb5820088d860ce223ed2cb74ac9b7b8366fcedaf9785402ef22a66b99a9928853fcb6a758ad9b18ebc12e2ab924a4d726b74e986ac74e1fe642e50172ce3492552bd1bd036a8d37cf364020942d8c0bd9caaf07e9f0cc645b3d987cfede0909634809affa2753cd52cf1b1f686eedc4c41c389ff37f6f6e92852924ba53904be2d3b6f6c97e7f57fafe07ada2434aa07a2ea3d713bda79d40bc2f9f11c95ae868716237ddca60564c45ae21de55131d70645933d745f58eca450452b199d94d6883a3d9c3b5b746bb387732791ee79a2b7fc13c9aa2e9a1b3a25fd6066f9c0977acf45307aae4b7bc38eb461f0b28b52fb38457ea4ef47481768a9f7c9503aafa3fcc4a16246917e3e982d31c9466ecd1b21b2c42c49685b8142d25a0b4a08084cea4156bbcc4e5b6acc6700e6512afd5edee10408e4043bc1dbfff0f4903489bcc144b94de78afa9053e9370d7cc8c80e985aa4016923d21f5ab8214bcac6193da85531df404e43f7543b3c076f4f187176a60edf80cd07e2e78555daa0c4a215c7fd263b7ea11ee9f8e6799cd1c7d4d1a14ca86ad00bc254aceff467b8380b8d47c300274a8c73ac677154934b39e47440d4dc6a02e4ebbbce7d66bbbd293ced5030286c4c162a89c86437b684ac30a37cc711a6bd616b6078b8149e55a01c7d09cb04d22b472bc8434889cb25289fa57dacaee7aa89288bd02664d728a495859b1cfd2090275eb102a4b29bd5b51bc46a0b1df571640b84fe51bf30df3d8e4c2eab7c2022bfab8c2a001aee3d5c8c466b6dc598b9fafc922bc18e6f2273f01be801e7988a16fba0e6e4298c0424d874aa580e982a54e4fe7ffc375d984fa13af4a5a7516f3434365cd9473cd316e8964c5760bc6d79a911218c24c2ead88af1781f25137a224096b466dcc75238a4f47cef23cd2a7135103af9bb66c01793889df8c8a553e70508171450f62894f4d560aabf9408456e46f1c96610c012a5468ab7f7d1a18b6dd4ad6a0b8ffe32c183200f9dd6b0fc3efa6f868c8a95d3a67468e41c5d0c175f419df0755a7b18f144e5a6235eca9e8c73dbb7949ae562805a5e079e123e92c298102ef62148506e61d7f8baf3fd343ffa5ee5e80959c5194095a9e5b8dc0480222dadf7aa0ce21e221d8cca5cf1c441d72097ef9e98065b6e34515917917680241df4debe70d4ebcee0eabc624f597952485511234b2d2c2b648862f602eeaae9078b15251c30bcaf479bf6cdbff8cfb3ffa8b65e194076c14dd5681fda77e6b814fb02a7b7fe780b7b26e265e8ab2b416c164619ab49207616c0d358bf161cd86bcb0f0ce944092ba313e7f173797545b829291aa84f1293e8d10b6a5ad534923683a31b5c0c5657e8eb6c3b076b95070a69c82ab95b345fea91781d52bb162e9aac259db55d47d67235db094d8774cf8b5d891086746e24458782384fd0abf4c1cdff5b9f40c4f268799b24edd7f8e5628dd596b6a2a828203c9285fb1dd92bd36e981ac0bbb5f1f24014548e630a90b9811582f1edcab5a4360ecafba9891df71758a5c0d9021c3a10ae60d831931ab5c2af9de15ebc11f8ff60d0fa7da4105651a7c3489f94bb6574d112754c79c980d70daf2cfc6684461fee5f9e9f104d18a3ed3b001751169ef1e5300ab9a6e6424895807ad0b058b31c223f8f19b71c649692d68f4822740b115283428100b8229eb1d774e083d36980633776f37fc462b1fe5c9e3aef1fd45b80d3c2ad71894960c87dc136c53f90d21810fb33528f3c7c9a95d4f6a15d2257d8e83545e09fdf16413b0ada60e24f9bab92c5e317c3177fcc48da831e771d8ec089414f34440b4886d7f7d23a05cf6283857d0ab6a91e43fd3f57e950b5ec87a1808ed557bdf57ffe192f283def38af08b1cab11689764f9640f4311e5eb8cae493c5de3055c64211cb5be450eab10ba2de55df21ab4a2bfd1459626fbca8e0ef8b8e73a753a61a27b3220c5a3c62fcb9d3c69cbe56c0609c832d842d15e5502c2f909ba4febc8ea89b2daa452e740cb559c4f0d5d40075da5418a03fb296a20149745e0fa03126fc4924c5f8080fc3fe38f7e44f6b33f21e51c4bc8ddbe45fd89fe1c4d07f2c6a8c85ad665b125aa8fc38087f12648160d240d6e3ffd7f70e18fb80d6d0e3d6e3be19739456947e4318209fca070711455deaf91a7df0f6372923f99bf5165718fbcb1c57d1d5a31cb8ba63cb169b0c2c2717d36bef6c096373dff31b285fd691ac6551b7b41eefbc46ccfd8c286a999a988e0cdd3d945a185ef9175f52057bd737adb9bde7b78daa281f141523bae11918194d784fb00ee152370c6e59517071066cfd7052e8a36ec87b516cf1d40c300f7e3e450d085043b7637a51278bdae77f69c4d9def95a918ca85c9b78004168e586864b60e346c8f5430b0ea2fbe4c20c6eb7fe7131d99ade6ddcaaa285a84702f9cd932e8b18f774a065afb4e8b38914417ee9f4d9491125937a9f55ad6a57ce9fbd236146ef589c41303b449c72c4ffabc0a25039d17ec8e3dd847bbeaf20b240fc05df5df374d6f015bb395d47fc3474252f6b999a6a3122ad60fb019e2914a3324192184bd28873bb367d745ab71d64579a2f41cb5dc71b943cbdbe60fa5d9108dd60be20fb1c93ccb4f729d4802143fbeb83788dddf295381fa93d1c1bf6d225e333999975f818ed3e8fc3dddca8d8bc284e8808741a574111a7c5fb15452e335af2efdfca86cac8da2d8c9c551aec3f5b7ab763a9a72a581b9f9f256eb46dd74b850919812c710593b9ca3a72e0472f8bee4ec70401d625437914c1b1aa56bbbdd32f702354d44c6e1bc6dfbb60b132c192945b0e91234f931d6af8638fb287b8c6a80c3765bc43753cc8b1b903f2f0044ed3484ebdd97f1373e9f10eca49e34545be1445c7f195af0217dbf331d1135c0a51b54deebf5cca64dbd539c5e3756a39b7b0d6e13be82456fd83f2531840d1ae58cb918d9e8fc0d686cb6de748e83188dc0a711d62e5dd21c0d23ccf8d216c222eb1a4003ebffdb234fc31983fe2a21b75479ee22d33e149a9ef5b0ff95e344e1b900eb167958ae12b8f0d40920bc4daca92e599657a38b80002d779239f321b69905506e1b86e4ab3ad8947070d9fad2211cfa8d264eb540d353677d58b6c6f5ed8036973d2b1d4167e2e16678d3b7dc7ece3783c97010717ae0270d5caec3444919f41e7885c699a2983137936a130ff4ca9716bbb82b76895c2ccec05ba5061e2b2f6038475f089d711a707add8b01359aafb2779774e4613fff2e2e4dcadfef4c3f0906e075029af5e3ad79de8e34b3a6d7f3779e7b3fa50404c7f0e5c3162ef5a9655ed1773c3daf435b3acdab3ee187b636462dacecc730d418b2c41c6d7fa00521caaaf409e7f5bfe6182b507461a5a1176dc588703a4ee39cde59453a33d3b8bab4dd69f04c719ffa9c881c6996994ef35916ac6e90d6c9c0ee25cbf0fe196aacb7d95783bdab89f552646da302cb16768261773c4d30ed316caa1f4630e961544e2f3b38cdfc0452b430d2a538c37e0d9466876dd215d44ad466cd9e7ebc535de25f8393ffeb75bf5c8dd9e49b1b0c24e9763b77c1de0589bfec456e3a1aa7261eeacf09c612748795cbf1e5cc2a37490c1121fe9ef1f77a799b1539e57cd3594e418c1eb2d977480a8ba92d2e79960676d7d946bc0a20a9bc03bb86136b7e440b04394738d9047d154d6e2f44a19ed9a43abff4bb8f2773d1a6b6d7466efe92dfa35527da7992936071bf70a10ab83f3eaa449d2fe96285650485b1f0efdaa2369f7e151a33a82756992b75c64d78a380b705845bb1683ad09da68aa576a91eaa5902b37aafbba5723420b316c266a324d1816ef16fbf20cee2a7d5c68bd044957081777e46539a4dd34dbd3501f8ca959a36a1738cbdc39a63f837e6a7e6d0a27688c5878ff67243e6e1088394b5665d6193b044811a9fdda226058843633f3bcb774238e51ad9eeffa90994f30312d6d8273ff6f52c02032d9fe32df6cbecd -MD = b65f97c19c96192c0adafc3d3e976ccc6492fd8383a7e2ad938c70f282bdc7ac - -Len = 30608 -Msg = 3d0519876d99292e2d796a06199e82692ee07a8ddfb87164644a92c056a343bb793f9f56d9ce27601837b49a06deb118722386ea402b57fcbce2ef3b2e40f7f9afcc6c933a5f5051062b9f8d13fb841803bccdd92c3d9db7eb3360ba3b80046c86b56786bbd50bc8a05c11296a7f65308bb636a2cb78a95d9a45ce84a4ead3dca701777681b7c28f8ed2f3b430f2bb2aaf16a88c4463e4b670211fe29207ca11b9b886adb78ddc6c77952e7790daedcc19e60de0c086b68916ce3d1c2d5d52d265e37b7183e0c12803aea8bab0c165df712e4ce7666a88a033540e7a9c76d4e953883d0b0d36d88bdb244bc5b82e8a2a5ef44de65f96c0c170bc7c4308dab61c2ab2b6c37e1a8b5ca7fffedfd1aac4778942f828d292c8b5750d6ec1980f62349266cde0fe1141650e47a85123bc7b8c9a1f35f4e8e70644e94fcb3a759f3ef935ae6aacb4a5636cb9053364d5ec17323894ec91c81ce435758b7df7c612b432b891756dc95d573a5041865d0fc200310ba705489cb9c852c0c86b40b4ee2aa9c618d76c65c186977a018987fbc79f51bc62686189471c61730e7d5d67bd0a24054976f1ae5a584adf4f2429be825a5af3cdfd24b94d472b35659b950606bb6c1d2e3b43cfaf361d28323f8a837b9a1357efadd85453b178afd6ad31ba52a549b7cf0eacee4986d6fdb3c2f3703bc84591d05ec781e1c21088689b79aa2830827b32d87234aeb13e05d895acad494ab84978f9376980e2ba69244db5ff10c4e110617fdec868201de9aba1fd632d8a3426f0677134b77940fa10ac2de092c92c1f64ed38d2ff3a3b5134cc2eba70ee81d03f8ebd090fef68e2379e297637a72c4f4108c87cf9665fe37aff86d999e066f06d5862100facfbca9e0cf0e886c6a94902bad5ece00e534a85234ee930c7ad2e83acaa733f18c0594fdfcb5f088f6bb4afeaa94a3b99dd2c5d1ecf11be0b1c318871db57279c813851fd0203436839394e808abf936fc6320bda4e7aca137ca284913ee6509e040eac50ddfbc1badc80e963c1736ff8d503963d164bdc4994287ff31b484188128468bfa3700aee1d30877d968d579bd44806316ead7c142e6c827fbaa582c073428e319e89a46ac2f131b55035d3c389a8639d9dc833dc1015941d62249cb0efef2690146f1998936deef339956cd5beccb668ecc3880a03ccbeb55ded16be4e3336c34e49f1df5a49c61f97d2a93a395b077ca3c70404cf39072ff129785457b8c8b29440b2a6dd30c122b317135ac3fe5cc00afb2d333c03777367004bd9d323e3452e7ce657e5c8e8e2d58a309d235dbf1c68888eff12d3166a079915b58b1f9064632414593ab9424845538b6c231f37780795acd11850edfa181d614f4452d6f77c61c514a4acd73c4a9ba92d89ecccbc2d4b110f1723030ce4b3b411c964bde6c15a80f0eb49b0a72d8a144a1e6e87d123d24423d8f36089b1849862e1fe4d197a38cd55d637d46f37475329aa4a6f9d3151cd7320690d57c8b894aa53c88f78ef2234ab2f1f4b7eadfbee34f52b8d099ef03569ba2d116071763152e8698aec68413e5abca81ebadacd6dd1c6b7e7fdb4d9026b6de6748af3e6f5c0688a465b2cbc72ca467b540d05e6596ae6968862b931bfe3003c3fbf98316a5d9bd2ccaf84bc5963943ff55e756d3a661e71751ef623f1383cd979e6a67f189148ea23ceb869798e709d0a94738b962d34f0b71bb3d422d2e9622ae766f786c5397953a210ea5db1a03d9a994768f727f0ba573f386fd919cf825aaa20c23c5f34286511d3688a36edc6ad54392be4bc1c785d74cc1a9f75b5df12161c07c2c9029f60054b0a8a831fe14bad91fde6547ed1cfa1b8fdfb4e64215915a1efa1696b854c65bef9e302fe357d8c96058457e06eb7ae4542750ca5f1388ff8a260a936823219755c2019516b4ad9916c462d08f61c82b80e95173ef7b66a6a4787f02d401908b85cc632e22abb7cca59b43ebe1207075c8ce4d7f7dadb8f3d079ea51664091ccf215fb4771bd75e89f557f2cc6a7f2478e1e9b59a42afe6b9092e32ba990a3c01d27307d9e5a6651667b6b2f9a58cc153382c17edd93b572876befee185255097988893d031307ab8d859e40c6c36c736b73666ba4486cbd075d77152d06141d99a28bf24a77e86b970c9f2ce66861c69868e0bc72e9828fb2f00f3d723c7f50f01daf59cee976f5f568d42073c83a934cebc6cdc3d7a58efcbc1ec36265d5581f4279d01af831ff3b32d3e7e953656dfb749f3c3193341f472a2c438802d49779c951d1b914b7cbcae324cfd1aa50cb168bc07436bcbcd544c2ce3a5d93fba3820aedeb23df670047023d64a73dab1f30a9d0f23db4be35580e6b245db998e0da9fa488e5a8ce2112188432e47dd2eeec475752c10ba6a41375997e02c45af3e5f00c4769116b92de7eafb713eb46ce7bfcba026b3204c5e980bfb3d744b03136948b8348a9adf9eedcf66db016952292227f8d96b8670f5cc8647255cb174d3f05a8d8eec233bac59c2ec343804c7fb1611e50ce1f3be4dfa52e1608b81e9c81bbfac4d60b6b5a15448f5438b8bb5a4c312cf89bd6f1eb04bf533b6abc3493813fe7b398d5d35c305ebe9d1a008036d50b11e16a6027864e7f9a3ef617d7e6cff9f64191c1fa35c953230a62282999ee6773a7c44b5b4b2f5e69bd257b96fac082aceb6b405e7b22ba5328ab7025f7faceb8c82408fbae29d428228357e0440562821d9fe15ea0df0cd5745078f3d57cb957af24298723c0997c0b9a2d5256f1021c448a15992b70c31089ebb311b706afd6d93f1d9c5085e6cbd4d47c4ba825f9b21cc46d9c8f7a65aab5f7bf0e110b2acce2cf659998dc74ae0accc56abc16a209f2c959c7514e6ceaa4eeed57780cb290386f821d8146ab8939dd890e0745a37a63235aa7f57f5176b34bde7c508dcfc7669a03768e56f3e3eea137c42e356699ea4cf0bd008fbbd58d8902fb3ef0dae8d9c96a53348ff6447592721b756873cef4b0ac84e6f1f46d7040db32a7f88c6b2e981731f8542b317b3b9872814143a02ef8fe7e3d38a3c527edf7d10fe72cc4c160aa716e35fb216bf74b77e6626eb3d580573767e6426300fac954fb5f648c3ecd84bffab7eeaac47fdb89f94e5d6094d1571eeb6d48dd97f1d01cdec39c37e339466c126c9e14211ff9275e67883cf9767eb35c402f8b596d9cb74eb66c5e7b3e501469966213ee7204ee7a3087af5fea2e832f017ef2c1c89fb2af9a3d465337423754f7d320a8f08f3dc15bc44e54a6f71cd813bfaa6d8d497d95f187a607de8d4368f379a0cd160893e82bd680543758deec195a28b9363a96866ef3e4057ea1c71a0bbe3ae77d019f433326ebfb15d447df64e6e4315dd38bf534da86e8a22040ecb32945747ffa9e67044df7a5bce9e62698de73626eb4dc6715c4150de3793f658c4366e0b9644fc811b419d0a71a485627b93cc8e35ef650744904f1ad2d20f8f98505d893cef1eadde1f9286ee5dcf2840fc6e146226845c2d1ed4089ac742b7d76a8b8a9ab4343db6fec097ecd2260503aa82821afa0bb93e71456e387c781aa80d60d5589a2679ca688f051309743fec24729e0774e2669f130b1553f997fe34bf44341da9dca943e467970c0c9f1f25f2a431cf9bf1ab798c8fc5944488aca30b9f6d91ea3e1548fbb0167fe390edd39c82021a7821d0f4623845a267346c1c76d9495d6435050233d24b139430f121aa72db9111581c371f6d5f276a8286c78a5a902920a7c0981735fb7129667335a5de82db707fd86b4a98d9c8535941cdce8b0a9c247e8f332c42f141a919ba37152dc0a19d7f4db76c207c2f2ca3e656cad27e5f7aa0bafbfc5ff42a1d330f5080c75d8b9e3ec0440c6d1004fd47bd890798b61a2af789170ef5cbd48c9bbaa7701421407da67c39b2e75deecc2d0e8f0c4678743a6943b0ea6d3fe8fe3903666c7cd469429ec8bfe7f62a96a33d219061428d15b4e032ed192d180e7cf531b2fd673dadf30debfe310241a4895f3db38ff6bda69f439cf7229f1eed0cb78eb6a93d25b59add2e1d1b7368bf877bac201dc8cfcf047acaf58d2a182eb9676097fb6654293ef5d9452ab1688fa379b40093228d37ea6c0410e335d07888edf080784a92b0e83d349de82409bde7419e7b7a6bbd8759039270aa2a0c7483318697aa51a7f29f9d864edc3412f15bbbb2b8590b28665a26bb3c6d7095cab11c6a0418e45a986bfd197f8e4a4dd206d037e0b86a967df3bdc89db16f33211a94e3f04a69744a5445335987cc8009f066771a1ff0cf742eb101ba008fad21c7823a83c94abeaf635d1d044e24743e2166b88f17059af213e8aebce138cd73bfcfb8e41cedfd709f2d1fa76bb8f118a2b943662711c09fa94b17caddd259bf0a61a23ccbbcfc34119e806a67f2bf3f7a4560c8d87c0a24f8c2840d7bc51aacb12243b25f1d82a4bf968a76c939a55cb1f456ddb1ae3d2908363cac4379d8e3bbf9e26f5f7a5668b3fe83f319f46c1750ad6fcc3a0f2455e28d88d0bd575b0c30cdc69a533a4127f5bfb409e08ddc175d57f1befb0886518db1b0a172c56ace1988385cc3c50b898bbf65dea46bbd05e3dc25da7dff2ac41188fc46e92ccfd17d1180dd38837c387fe8de9df0f6d788e7235349475dd95777fcb3e8aaf550be6450e6443adc5bd9d921666c4996f2497314c332e18b5bb2c6f41fae3e86b63dd62db2ba4f3872179f51467339b3d5ef8e97bcbed4ef787c065786c12c49c8f5dc902b6601ff8797db62c7dc47b5492341948815a7f3f85e3f0f3148fca4508f7d619a71d7996304943b2fccfc04168d93f36d5ee2fea2ff7a03686c370114b2c2884702596ece04d3c4c66dde0804d48c9cb4c20e773f08bf1b735564c7de07b1ed7a4210e6903f9fe5d6e7772adaa13478a468b2c89720143f992a0b5e743655797b58836a705f0086a5624fd0629b946d8778565872f083572314b42e9ee6b312916d3b603709fe8f7c05ec64626bb364a31c828f981f134b593ae89f26bfd5a106a9be32ade7a2e8a3f8d84ca3b89946427abfd5d156cc0383c52e19d36bc20f203396469aa1f37a62649bf2ed2b4ff9aaba9492e43db768e9dc0f046c8f824228344a06c6dff92b0171bbbc086cdc6723058a2e9a7bdb60d3a812c8bad61e2465d363d9f948bde4c746c214bb224876f7832811bbb941d48850bfcd85e59d9c21396826fa84468efe0c3861cff59c106c5bf6a40f9eefad51fd9e7b94670791a28de157923c9d0feceaa30a0d8fdf1cccb67c4d5dd3efd176d7383bb10264ed32f857d38918c851d9098d793a9519825dbb43756fff492a3f051473a25ebd9717a25102a7bfd13a0f907d1521b252 -MD = a93bd433938d777293ba34f15bcde4155bd5d7ba9344b126f9f458acd732dee9 - -Len = 31400 -Msg = be4afc96a800c0db6a4c6a702ac9fae981be6be6dcf3368b23c317309973135904c2bae80dc1aa91e9e5548f395b03952f9b1a08f3409c6b4517f21b6376e93c2dcffbf38784cfd5fffd03a0b0f9282965210e9602e342cd207dd62df858607b8298451fdef13890f2bcfd0d554a738e6b78d1fad283309afd1e4ace1fc281fe4b4623d4d9afeca80b49cc3cf1f7ebaa89c7eb9a2bc96db82422d666a25c53add0001a7a4167f30792cdf7974ba798660736e2e0d55d0111ddb0025d47cdde7158efb479dec05693cf6f07842d0383ab2cef403397e6f48c70f0571bd7be2a302c3a783978631c360958836d5db2b35f42178cfa3a0d4e10240b5c0819d640d4950bee23d7f74dd78aaff3b9a45d306b8fd94f9f8779188743299a8cd7be2743d9879f9dc225f25e989de0d0caac03b85c5b108943d25ad813719710d71de76740d81210039511b27c4ad11a9746332df0c5572039c21aebdd0cddfae29c89261426cfe560eeb5bd7edd4effd3d4c8b19540adcc30ef62a8e822f4b4c0e3136a9b985f82a2d9e366e57fdfe745fdcb2e91f498f5ef0139f77eda62a43999901a1f57495191fda595fb570d3ab66a438b2d08a2033fa1a8c0e55cb1341566051ee68a15b8f4030232068e5f60eec338b0b1a4535ee877b5eb66d168cb1bf47c5e385a4c21949203264f4b5ec1b5afb38565f2326eb22a6b60496110d014e8fcc15fef75f33a53ae571eb790c5d3d6baf19017c79c6563cf07d63330adc9ed8e31a2701896aced0daebbfa7fd50fe158df7c3e9a4ec8c9ebc8557050c9ffa939964806be72b30928136d3bb357327892346f8d34eda405c68c0d3ff98c81c405d69ad8eeef164f056f7da2b3b5044272d9b22c1ce2c1be683947c9b15e16e7fadae00f30759f66aea8335807554de8ffb68d44da94e79ddab94b3503a785ba218a62d20c6c14f72ba8d78537a1d51141b347fdf76ade4923f261ac74cf97e481ce674a0b3c3ea98255b150cbff646641b92a7eface6d6b4bced1568e3e140e228f399eb44de525bd9909e24cd9c18f06ae7cf06b275eab5b34e25ad85dc4df0db31ef78f07d113e45b26634296b533987c867ad3dc77b05a0bdde1da926e0049245f7d25d3c919fd8351fa339e08fa00099045b8578123503d0a121d46dc18dec84357fd1796e212f8d2cfa959828e453fe279a5ff43ab45b1b11628e2d4d0d58914aea03c00142aa4f10b2b2fea946f04c33d1f3c87f1424f1a1483cc1fd0354e18a994abcf584e6ef6d642880ab787427db9b076139d4eff8d35b76e85bf06fe997163cbcb55853e285774cca89d94e05616df15b05672a951a14b2fcd455183dd2d9403bcb4d7fcd0b74c638dee9ec6977c348126c4b535af7fc776c10b1dc42d06b0bd691c4c90361d4fb58153aedc871238233d901f8beff7b4ad27b972a9d0243e609b36ede3a2b2072a4c73ca0a70017261bd62b8945933993bc8f7581a10aec6541aaac1db5c9efb2bb5f8fd3898706ba46de189363458fe886c6bd8ff33cdd100ae1fd061ab08b31e85874c4e4888a95516b6995aca916bfcdac0f94082a8e6ce1f3d235ed918b86d84cbc134c871b6da8089f0e9610469ffdc9cc4c645688d2534adc1b82cf8917e7a6963d260521a9d730197c942d97ff938a83f77c4344e6db617b259edcdc6bb2f0c3a1058535b04b7c695e4b5393652b78b743c4635b20f6e22ff2763c2e08b6b5a4fd7f79e03791381f220014c157221ed6bfe159240712177af0cd8fc6655f5fba90d87589a6351dab7677039a4c13e782ba3777481fc9abecaef92a6e0839698509c4eaca62a3778eba048296ba8d6d2bc14b503fb18a09e59b7dae6d67c16d94d6a95c0b1358e0496b3d243f38db0a3263a1666382efabf634ef8e4d1a83d65a761a3bc42ee1d25c08756b0c3d9959471fce4c6c0a471caf09b34ca596fd2e56668c2c9e2bcae8472061c9763f54d4ca641654a19e4cd670986d6bdf4399f009366380f170707c8b4176b215c47a074cdf3e31bcd54d63db4f725e72c6e6a5f35454eb56c38f19a8ca28d75353956b4ecf9a460645e53f5fbd66a708876fca954ec4ce366b534a20490c8bd763236b30d3bf14264690e36e60bee8090b91d87f8437ac38fe7988723c7651ea89a091a37a111e957dccda97c7ff63dcda094a12a321f7a6e36e5f2f130abc252d8979073134e7cc42159f6c518cdd2c6912b9ef1a185338b0be28a77b3e4d1fc56a8bec879ee24349f7ac4c9bfba6503f5a8275678f2146fcc58f8bc3956722e7b044c3ebb3a082ebef7bb915d041f0d35d4e3609faf45a1e310e3c8a84bce71af72e1ddc17a513ae69a8424d8f4276bb7777b17fe04efa9b6cff4a4ea090d4c5abc25ae73f626e07f29c78a1ad2a6a5e55996837e383a10af60d357e5d85648e4a8c2b8baf5b0a9f16d2bcc09e6c3442641ddad05954d5d348a27e98302d1ebb6ff5d037cc1161ca52e59f18f77a7cfe1f9f79c7c615118af149863aacea8c03688a198a3a081c20134f90193ce79ce80478e58cce56dca87c7d0cc4483004ccd0d337e15db19216e46b205fc3462ca6af447eadb69cafa246b742c386a0419e354bebdbcb905c3552e2c03b4ef8a4a07c8cc5993358f30eec82f8c6ecbd9aee127e85e7e846e301cb21006a24718d6bf8ac5addb90e5f44da5a6f3ceeeaa932d4c596845827bee2d9b0613ae8634f6fa04d9ef9ac4f4cfa9cb8469401a9d51318bbae3f8fd5587eeb0b534c0f2083320fcb126ba17e3486a036ff6ac98da6f54aeb3d87f3b2383c9bbc670c0d5b914993bf55a22d2dbe8f8130fa3fab18a75fd7beb4ec2850e682582e0d096757222cd894c93ba3c0335bbc30e7712aad5eb96bc0b4da8223ec069cfac5a2b1b59e325ad5eda6a9f84b91cdd117bdccee25a8637badd1b5cda12ff68d218650e96e10771d4361a4185fc8127c3b54164da4a35b5a10703790be74e15f9122d9852a4dc9b56b0b26c2f85536bc92f27b3e4410bfd68d246c2f8c6bea0c94f6cffb5b20df48b4f1a66aadcfb6fcef1780429c970d9b647cd7fca37b7cfecd7088ce69500441c1b3b771d89dffc78011a9fd169cc0f336c80f8a8c2a16c07b2eb870ed51f53b01cfbe9b01469d96f69f7cc03aa8768884b4774bbf0e43dc5e9fb3854f8d1e8f05b43028d0600d05c31f5d3e71209ac5dec0b3d2a48e80bcb8222e6e1887dcd84dffc0cd9e70ba7e75ffefba62bbaa35955b2991e53169dc48846dbdc0d8dc813b00c4dbf3df427b7fdf98e687d0314259026d1bf97d4bd5600515d6e0d68a245d75d0e659222187512cdd2548e4ac969a54d2c349e8b3129f42ab5bf127623c45bd596f36dfd42c8a7641093e9f888cc9a11f4a6f0a4c2e66bb92bf6a31f1235445e2f9257ed6c59c3a58f4c13761af679596f3c138538356ee6063c49cb38439bdf1f6ad75a60d06e7899a8952b47904a0ce71f91985bbd049990b88ae25e94673fafa275ace4d4b0c574cff87ed6421314a276f244f32735ba0f93f1cc4ad0b0682762b94bc10d927469e8c4d991b3de58e96abcf0c71a0931ccf403f1c5a07e41cfd42ca0bf241b6ec01c7fa33e8cb2c003237906a03f89e60f044aba96acdab2ee1d5511a5c15499c192b343a67498343ac8b0ed463ebcc220ea4d8d879bcba3ce68bc073d8b43deb473e7239114969cd482ea0d81beabab46cf94d35e155afcb5dbeaeb4d2bf226e0e6a4aac714b7e01a78aece19675c8acadba8f5e4c48ea5ec9e66239e4869578e1471400f1b00e954d38498d5e3d948f4351059e14d6f87bbdab819f88baf5a0624d64d32d17b9dcabaf4d37ed72acb0c0654691d5b058869b76933229ccb18903f5b39f9df2fe5c35687e7dcee55fd5a75fd8c5f945991405c00dbe622c878748d896d29ed24aa89cec43cb7ce64c526ab922970a0728b86f205780ac6ab61f935e74f8da263d2624b343ad71f5e0ab7d09baa1928585c84a00171572f7ebd6860fe48eca7f34697f55d4a048a4cb6560ba07620d414ee828f7b3095054973093554c10da3dcef6ff3c9d205b635b04b842af54d4bad27c8e6fb1c8cf2126b24dd7320b93f27b4346e003ca34d21e0de64c08f6a362bf19dce099d039ce38d017fe3ceb823db7c2c8d88eea6f4192e57d3ebac3d3c97334b6f2e1bc4abc3c1e8442a34d2f60031a179eb52d6552382fdf832b49006f8d518f0f1fe95c8bbef2054d2b9cf619fbad959b1cefa184ac419fc1d0f293b56be4d7adbaf3f9bd1fff2d663c4760bbeff1d5660ccdce593dcf3063425d084b9d8313473948acb0fd9a6f263bf909d68e8b49882b3426208b2d33f005f4f892a0a0e4741163d017d6584d25c11e5bea25de8469eebf53ab02f01cf08236df1b03c2adacd9d22e4228cd39bd5223d177646ff893ddcbd139339c4ddd4daf1655456cf16a092ff1d0634dd78575a604feb8b4288e6ee6196bab96691ededa48c1d414323415b9d533146e88f6921160f0914f96c2189ab6a2c982d14dac24e0f13e3ce283862c42facab3d0893df26ffd9c96c5c76156137f1bc628e23c3b7953e25ba4d0e0e3b587e49240c5dfc59c66293e2816efa4ca7120f4c265157a6c7a7ef4dbc4ac6cc77af0ae4c350e0770dad58a50290a0346096783505ebe5e44d552ad19a74f43d3448d5c754f3f3487bc002fb08656fe10a85de635379d73ace50bc8c1214ff57364f9113e7ce9e93b9a5772dbb74d01a4ee82b1f3784946df2a18fc749b34fe226cf2811a66a47226e64a182424529a8d4c646b1d9938448624f8ac96ad84ca6abcd8109b74e58bb43036644c660e35443271761622e0f92c66294dc9b0c5e6b6e53844342023727e08cb0b96e4e67e443138677fadd9d12c5e3974604d6edf817681906700f4e2eec06662b63961c207e937b3ac829969108d97a50cfbe61164d15289c68fc0397107a70e0ccc069d299aedef3f59962d7374c2542214c228db861994b5351c02cf3efb621d254b8c03f6d97eba8b669acf9447f64250998250154545c5997ecb33e6d1f359ddb70b316d68e670a0614d8f6ca72fd007c2ba5d0f64217a155eef598fd956654ddf873c6f4acb24313c922d7e5e657dd2e44d7cc5049c3541330baaaa500fa20e0bac8f8ccd7137a65f154449ec1b8e2a549819e6952a9995a19c91b6f463a286e1d7a5468f8d1d882f534e4fcec69376ba46cee49461299b011ec9463506e950e895081cff83584f43b8b60074fb20508bb6063f90b447ca080e9bd8806de8e4966142809bd87a6432d205fc7d2da7402f825a5808b8869afce893de650d13ca51d8cf01f310f68f532bd8a455e2babe3c2825de6ac2588676494bd851791c6ac148182183b14f094b1288988d9ebd332804033345865024fa8d2e46e416455e6b4ba85fcc2e066a8142a03982d6313789c27ce71768effef030b5ba8b89311da6501a2d3b0b9f3b7c28ba17e40db943c7dffd7a5eee9a6d0de06c93b62652110901c81a6ece8bf4b23130a41fc9b7d068b90 -MD = de6b6fdf8b6b83ba756cbe0e714d3dc0160df45c372d8b198cf0455b52f49831 - -Len = 32192 -Msg = 95530985e73134f6fef027c8c61f4b9308afd67de19ce70173d0d2efda44b8b461685cdcf6c531d5dce0b8f6a06208bf4e77ae63e474b88307bc0d3df5e40065bb152412a8b2615d013b4765f672a397d5bc502c7ec950f217771b5001f437840a230930e442eb15d6c97f1eb19542a0064564e096e5d7d60acaa630e4bc889ab65bb53d91bbf885c1520528b7140e6447dc9188140e74b5487a53e68884192e2782cd419966af362b9d848bf2372e6a01477f2adf8d4f193952cc79d39412c8c463fc45e38b39af7d73a2504945ca3a9d4fd7d1e1aa91894519b9f1af339cf1f7c5e84f5772bd781d9c077ea3880c5d81bc418201ac628ed496c15703abdf2f286f396add62641a75e05c1dea461a5a1756644727dde9af4e928db2b742020dbd2a989b5da5561ceb07493605c81cb9c6e5e9273b834f741bd5c50ab2412d101fbeadecbf81ba06e9d875cfdc563b03f530772b26e7bb65a3271067def08ac2b6f31f64eb3fb861d61c89f357379ebf0e00b759ce51560b4e5016d222963eaaea91960bca267ab41a9b2ca75eb56f75781d51bb1c0848ed85178052667c7450245fbcea428025871d1d07f5d916d3ad9b4fec59f856b893ae46f6f092eb523dca2636083c93e463466ac2e4b0a3f4f0df5e30394b81ce8633a31fb38f2900f846aeaf6ea1a9ddceff49047ccba4fac5ac11c765fbd2b44d7af7a4a3437ea709febfcd2257083852b08475c612610db56a3156e5f2918f70ed092cc897346ff95c21382e48f81e77bfe1bec96e215347818688bf16068a78f2a3602b73927f4fc69b99995ac3b7c49529878ec52ef70359d802fd5179caecf38be8d3c0df0093a6f7986c77b02ac19a23771b01ce1f715aef6fa78a317a54578a6bc86464194e63fbdcae8606a0f63699377a084af41aed9375c3a977c039866892134969f30765700e676f0e40ecd2516fb3c4ea9d85788bbc5b9593c421e8ed04bb5535b546141dd5a01a10332ad415c6cc1bf5423a65a0ed7638cdaf97e5e169c872128893d8ccda606f53a038a6abe4cff7b50dc21a9ab01d796ca920e50b6b43874694771943c5af5621b09faedb72c33f7024a40141ac5740bad9465034b0337c1a00793f4b3d95b7c08ae6566f18b1db6faf68805c8a2c75fd68908e24e0a039d6f522b2acea1b7a795895052d7da0b2fad79701b5f1a4017e7e8607a3a492a5c29af8da2e754887943f3522df4a98ae58c3b8eb128ac8ca8541b12379a412aa26188520998625c659694d174b26a2b6d39d53a63cfd9fb95adc984b6d87272f499651eab4c4b81f10fe654b3abac4b3b18af09afbf131b64475c4e549f5da1d743de2a148d80b7b0025052673ae088b3bb4182f160f87aa8c35bb5bd398325aef35c2ae1d6926c07207b610c0a97627b94352cd57fea87b7b430713d41537cf02a57977fb200fd8aeccff71e753156f735f27dc84669c1357c82f771317f164f5b58d66aaa5d0a9fc9b69b1b155ed4bb02e1ec466f16c5868ebbced5a4469020f8f88e2f19f711da49c7b38e65706a4badbbfedc5451f34f8d535df6f44a68f9958f2529ab7f81bedf9bd6f4e006960d78c92bf690abd8e4dad22b41bc0b0f4db3b51206b946f8a21d7b7bcb0f91d69506a20a319e94f4db09c0cd42660901a1d5e2fb32ddfdd548661f288d6e92aa56d9cf0ff9f89dc5b69ca7aa758cb4de8a7e91373a73f4b6064bcf53c867999fe754a8a3cc1946c9fc05ef49579aaef45c00586c8a35dc0960513483e8951715bb29e77c348af0801fd80020650a47f1bb2da0f1ae7e044deb08c74f8a718baa36abe3efbfb84b669675a2d62a6620351c38f36d13d71df20ac4f00d0a7777cc0e6d2674ba4bb80bf4711fc11438b86cf3c4c83556bb89a44428574305315c0996e037b1d09fc6eebe5d0f87befc80d7d653b7f0f395c7c32ba56597f719b8d16497801d8f4ee87d689bda70872c1a2438581b16571068ed35ce93525cab0ec1fc15b81e32b39d3667b009321931d4c09e549a1c0d95dd70d6f67938a26fde49c1cd183a876865a8402c2442c1b8514b7ceb9d8893b0a5fc93df7f8164d297d75a304908e9f7d2519682b4193d3a0003586f9dd265db42ef00cc2ee3106ddbf939e1c2ffd6cc53b0bf36212bc80171b6b5532380107044d6825f0fc431ac1b3dc5540e95da707a444ec903f11ed916a41858c728003a1c31bd0a8abb4527c60390f99451716ea69aa9bdc50f8e1b7f7a05d2e120d183598ef551281ec74b7cf92164fcb9182179127476fcedb2331c96e2441a00f0d65d4cefb570853481906d0b0890334b23524a2397041217ca6e89523eca5eeabdb809f0b9fc851984b0fd9266f766870ed2b02ba082f32b4be5dfba258a811ba3fa44acd11484f2af4f297c02bab9682e7ac31105f227693222f8ae8ac31e2023846b689d610b3c7bdb5f1c5e22a24b1cab216839ca155e17a66283f11c8c84a6f70cd8715a8e7374e62ce7fbf7c7cc53e42995de83537656d0bbfedaff62b5c8c29760ef79951424e001834e7280486ed66a2e46a6484e8a424363bad4273fe367a9968a4695bb06698b62d85b626bc7c2519624bb9a432c7bc7571343509f915691fdb43a36c483d3190b2bfaf492e9688e61db2b9ff0b7dd864d76b555314d201eeb0fdccebd37cd38e0abd9ad4a5e195f25ec8eefd3b6e82ebb57b2dba191547ef2ff96e421aca86987fa8ff31e90556236cb4df078943c1f2528b42a7ce85450a9f6010d8e2d0539657a866c7c2abd362919f1483bea49e61f7c41e80fdcb02284a593b15f6354170dbe458fef87b139813b116dba2381f20ec4e48ae6c8f862f760d76611da2590e53855c3e521c1eab3b116c75fda84f177950489ae478da096ca349241ebfa25807b2fbef9937fc8551e89ebb979b332fe6f2a7ab2c2e059c74443cc6c23324373e94bc799573b60c9d5d351338bad54e7a5eec480e5a0fd2d518d8afd1a7e791425327450e79522a6699b8e7a7ad3c5d7eb99fdb50a40191d946a44813c2f4505916c4b9ccf0dbc6f6c4af9ead1b70453a2e48cbbbb3e2c3c6f729f74f2d525acc051c3e968156c79305a2a012ad7aecf6e270801730ba4fe552ed254f8f0999e34ab63d36d4cd1786841a559e0a613cfa009e622cc2911d7e807a3bd99122f3e50a1a1c7290479d176a9f2518da2d1c8dae5bd9c1127015d9a8589fb6dba4521c70d145135dcd418ddfb7784ac7e673f9142e4da0c75e1f3df30dbbae14979dcea1621ee1e566eb320aecb6fa77952b845c9f268f8a6423f48923f688e403bc44c85511a3cd1a834c14c547f192422b77ab36cc57038909449122b70ef5f196c60b338423c0f1f12424ca93f7c1f35b1a2c7ca7c0d9d5b97633906806ec68159b9283e12764f41d02638403d4acb2a3b404f81f91b5501bd199f770397471200d86cd8f78612af02df97afd4ffa86eb8f5e339d943e03189fe8de376f33139f620f9af6de609c50ef0d34ea3153781bf160b3878f1df596264bce256fd1567be354707e200950268ec73b3342618e1b233202474bf92e7eb0e84ea203f7429ad87eda8f0803505b5350163e4ac9d2d36dfda843907bb7b983e7e616f14de0e589b45d915cf7a4d586d04d7511364c2c16e92be5254b972ee7711ee9027a37443d1f83ece58c527e6f6e693f5e4e030c681d1594d410d6c426ae7f83fe274fa03ee7d3086b6b643d5653f103fbb9ff5da9c2edb763727d6587c5904cadfb31dfd233d54eb63be1f982a76d2bae20480522ff3cb89b1b93f851ded9add79fe4eb422b12248da5d29c3c91661e402be7ee1bfd89fe44b02064cd23e30c43ba70aad6f911f3b9513e0dcc3963447981e3fedbe35cf126dc2d9343ba35d2baf5de06d5c25a2403e62d347ac8ec0520cb441facda3df90845c06cfacb586804f835e689b1761d300da8f98e6689c9ffb01238d40ab57eb493e4d73c7fd234e96a7d3138ebec480b6db5444f3ac3f8dcd956309c9a4be8f06f9ebc4ffd2da031f3bfd12b9b440c5baf5ffd066d21fa80ed18f14cb3889f8581f8037c6ef013a33c02adaae707d0e77aab0cfb262c37b3955e622c7cf30b3b70f9950bfaa4f508ed4eadfcf7bcfe7877a359768e6a183c79326b841e1495d9e4a95844c8d0ad28aeabb96bf4ebfdd64d4ecdbfcd6503e5409bf49bc073a3298711356f01fca5cb2522b93d061d35c9a5b44e1d0aa5617493a2e5ba8b999ff1fe3814d3ccb144b9fdba95bb54d80e1927dec5da6eb09bb2194d2629a70deffaf427deb95275f2b9dc7c352d07a7f08d7ad31b3c201017677ba6a0303b57fd0c0fe47969bbd317956b6e82db460f43ef479b368c484d3f5b60b539176f002feff779cf2b2e501b13519a620c3a9a6f05353f001110ed7a557181da256c8fef6a55edc747d37667fc3608be0a0bcfdc98edc660159e7a2f1f56126ca35a8ca446d1494804d3cc6117c4bf7f1be036f26f16383dde1a7cc87fb670d5d9617fb54b12943cac56da722ea1c78b88e1581a54599e81b5ad79ac3e39a4ff0fa7f18c41c1d68a85832902077528cc9938bcba0d5eff13e27ffb432488b5d08d576a90f085181ad883407a6ce9ea29950aeb3c63cc63dbadb789f5f84bab329a977029200761d4ec7ea74023a41689c6826b061e4cd2c15e7dac2a84298e0c808f8dbf98efb9a00b9be7bef44fb4d672c5c682068555ad3cfbea4a8ecb6745856948ba21e428667b02875ba992caf7e2fe8316e220f3879056cebddfd93dc7f24a2983838eb70e85dc0f7e081462d45e532b2c7cc4b537a2b9ddeb3ffa19790f5cb98086966d8071510891db7e83552dec452b9a1aa1a5ba4aa13d75d6024323c77f1af1a453a48788f9fbe877366299f2597b05c9c2ba2031a1194b16000d78b304b98e5f6f620faa6a24f8a882e3e88df084857a1d5c1b9765e887621bbf5447cec62370cba350dee374d2b96fc063e491ade2d5bc74f5a47613f2615c4200ab67a7797e6f4d934ded53405105e15220c460e381a6ebf47f5b0054bcca7cc40857c65832614a201e0f2908184d2efd6811055127e3a761519c19751b6e56e786248a8834ab803f7ad25ef3b84e90abe50102f46e7c928441c2c51c244eb8b34c585ad02b55d93889bd5ac9d610eda6bf1bc094ff7893a478546b1382748b6e837aa0f9c0653c52725885521d9c2f341de7a7f981df910a1dda7520dbe8b5615213c3cc9ae590d65e2b485532f93c9e27ee20ea9db976ff59dc4a0cd8b020d4e2aa2b0e62dcbf0c74bf099cc02ffe2c07b79131fb0f29c954e3529e20d6b20e5ac7408abf53b03cdd9b31ed6d475b25e2cb639442e892b03576f5a05c625559e3f369075a514baec0472911e1483dd3e3b0ffdc1b4d99fe251e9bd8335af0fba5b4114cdade78aa464c58d0c53a8b7c2ff0cbd12d4526f94b62ac104ec86b3dc7959d22e8021f77973125f1c1262d69f113313a21d821ebd0ca900e54b3ae67721b76512cc6285eda7efa3e7c130ae24f9f98e09e0e721adbdeaf9bee24a0c1cdd004a14d317ba738bc3e7d9f090c2e711e688c4df001cf9527727ec4222b93013bafdaf44c019ad8725877d1101a9780170804d585b651252c3f817db5362435e4e0c3c81ea07ee328b2f4bb311c63a413e210e0d67aeab475 -MD = 7d42d418cbd32cd65e2222ac5bcfd5a3c77caee2b2c231234567621f569c351a - -Len = 32984 -Msg = b33ca16381699941cb1b15582957976e56c2c3e53f61169a5aa4d40c39a342c15fa716e552ec2c35f2a57a1b0841461a22ed966d9f5ae9eb06c0242e9c23cff435d581c54a3c99d74cd52f2e38794b076cdf5477b963cb50b905394462b5654ddccecb4c90e04af082b21dd9e0870cfddba1e34bb504248f1b7cf996b6e16c92fd9adabf4d60a5473b442a6429f4f3c4173a2d31bcc55c71d52c4d6bbe304c8c3f429869a84514a620943f163a476623c9b21971f62fdbbe8f1e1d0da2296e034bcdec91ca15fed3d8a945383c08cfe499128e528ac9093ef05852c28b5538bfc843bd7eda5bcb970c8c221256c095cd2e61761da01b4fb8a1e4d2d3a13a13875facf579019ce2ba6443c0ecb1f620a731a7b81b62ae13f64aca87880b626824b8117bca6762ad0487d8050e7432d83949ec3c91f609bebe92105828f2559d5f7a7937b93334933d1e52dbbfc8fc254d1f39eaca84b5b9d921c02cfd7d991cfe4ded118e8e9bfc2cd0ba2949d5dd6fa95a95aa0d35386b0fa0e1ed4dd5b84bc9db74f1909f1e509a4617d7f2c25c1e16a30964a1301c3b27b77c8261213a948ac916bf088f45f84f2871cc03b8029a5ca29c00cf9ee893eb0d98d3818aa55e07c2db633e85985a131dd1f2c3de554b43fe5666dfa725da214b3dc8f4388310096cccc57aaaa0dfaecd3e307c5ddf9a93603f7e19725a779218734904525b14586ff0ce0425e4efe7e1c06e745c28ed136f6031c4280fd4061d433ef700b6d1bc745064231fecf387015f94f504b6ad8cd4c0652af0cd584502b48f166c1baffd23f27021c0415157d4248b457c1343c736670391f31a6b166ecf24a9bb1216e223e0db442f6a731c031639acedc715893e5ef44259817542099be5f818236e351d228bd595efbfa1353d87747f588d9d94ac1e854987de927c20bb4aa9d71fbcb8be6a1b19599fad13a25de3595012cadf596ba2ebb60fcb6f668ce996b591409dbe5f60e42f7a07454ca443a4370bd7c76ec2e068956eb88976421b08462d88732951ea1df9b878724342da8793e28df6f20a88e8ac64207357c3292710595ee3082a03ed40c0c8429021f12beefeb411ed2de292845acad511f95b1a9d7e889562d1f17c8afcbf5f3a27cfb8cfc714c36812368fa4b67f55adcaf80a7505cf303f2efcf162d3246e493ebe55bfa574b169a1cc0794e1079e32204a1e1e54fb5da8296e754dadc11ac64d042a45009d86fbc2eb21dd442a56a8e2977f22d5d4c3a3aa8d2fd5f25c08b83cea60e94058e8235ddd050646b02617f8285409ef210b3b99a348810bbee327f3b81f33cd6b80eb5ae8dc974e60b5884945c65909acdc75def6e7d95eaf511c59b68eac109ef55aa155ce19c603ac02bf35fd9c8d3bdf5b61ce356654f7fa9d582cd6db6fbbef781b6c02131561b28e41422059e297bbf40b755aaf565d88b5d7611e485388184eae74a10da3427033b8b2571970881948c2327d3dcaaaa069bf9e8f7c25cf15e343b7d28fd86e8df90acecc639fd6a1606f4cc69619a6ecc3f62b51fe4b569140c37bbe221cacb2e820dea4bfd748fa43fb0c5e44ac1914ca65508b562fe6326b14098c4dd7c68709e22a0ab580a7cdf94cba6dcfeacbc086f455660d3746a06e20a965997182b36338f924ce02bbc18b4c9e1abd3a8497008c8109aacd408451cda2718d52a9dffe0b951a91c54c7f00e1ff8e98060b413f131d9cb5589a861a053ed7b1e203b2e3414415873222ae60f527f1e7b529674b737149b7401d4dd3afc3c08d8a57d519c44f3d36af04f7b46f5c6a33afa6b12d92c53637ec918283b37a53aab06fefa87afeb928a5bc020337e721035b4ac6ec5a618bbdc6becc33f9abb98fbe11a9994d98b2e57d10765535103fdf23dc4f90b18c71d1356bd4ea689e19c41a06abf324674ff39dc9fcb2511eec4f6e26f322819010fca16242b0ea9a9cd22e159cbee6b1b9dc6faf3b23735b4fdca5ee5ba9b1b38fc57269bd8d66e96a40600825037dbf17285989dcaf830d910d2efd2e2d293e16b51149ed8ac5d1aa961aa6edc9d0d9925dc521865f697dd96b721b15b7d179cf52e4ca7baeed9b855dc3b69d18c74652051a3de23a0df3507dd90fb84d91abe02754b30f02c78e221cc201dcf84a507ea7c0a6974857b61ecbcca3befa511d71b9cace508c3bf4aa5b814f5372413d3ecc1f244e9130106addb19dd0c3f918ab92ace1e756321344a26767a98d9456bcfb9f7eaf1e7e475c3cf1c695b271e2b53963b57b689235197adc1387522ce31dbca87e61f62ba41e6ff5e6b6cea1c3b8365812b5c845a0506a481995c7ef2c8c97a2ea0d211d6fd5fe24c5da1f7105dc12f2bf3d80319c12fb14427af6c6782f15f58b5aa83ef0ac72e52aaaaecaef48549886ba98407387b3a656dfe799112ebd0929f192746fc951a2dfcd8292c82584b42dd516596bd61d671d6ba1513db218468c79e7a9335426c2aaeca3b3d99a2aad7d350463ce28bebf5fc72cd445e3ac157b9bafc4857676ad54af1a136ad0cfeb3e826948e2a42017e39a900c71e804dcbffff3adad56cbcaa5bdee9cc2effad638664eeff073cad5728dd5e008eaa504204cbb4cf31eac8364bf27342b1e34d63287ba403fbc4463d4480437541019f6662b0d899ef3a23f5b5ccec5eb850453f68db52319a81727d17225fb9b83e7195943f34cf8ff3467503dea364b4df2b54a214880c45fca8b30b33e13266a97d4c13d747d476aea610c0a836f939e8664f7eb793f8908e5f5bbb559673deeb19165c09804d45c4c96576aa2580b9f49c8c5925248b0cbf0cf381d7ddf2737beb70e7568c9e7fce36ef8054dd9fb79c2497bbfdb8381d174807096b3632e6c46ae8403ebb4c8723652b9848fdaaa537a50e3191bd94442f9702bc602db98b5cfdd8f142aaebee7cda8608f6d436156f743c3491a30404605073155722fae3be3aef74d2b9d128331d9b6cdf1fc68aac38ce4f6e072be0322ad49ec0b47b82609888358f86b0d6de94e83e722ed077666910ec9768506a4d7ca3d33d60bfe9ecad3fddd99fef4ce7d6e8f8408ff86e266bc0869e353604facc6d3d1da64c7caacf82b83144012cd76a0a14dac182c184d749c802fc2142d2a09d46f1f385dd2395dd5f37317ae935b4e83ea1521423da22090b363bc6965d8fb07b4ae7106dff96bc5d5be6d0f47b4dffb024b03107cee2aadac8528a81f3f0536498ef50b19738ac2d0fb297e120abbd23d57a4defbb8f9bb13a0ed1a85e58d27d5c7aeb4a72f23938c3433431ce34ad04540eef4e288f5828fb9f504bc54fda301628248b1b59c01b27073a68ccaf3bcbf0ec8995ae686c9c9da27b1ef14bb7275665b11618e5fd4eab8d1ef8a44215f56ca19178b5b145a690a6b6844ab315cd8db2055dd41d2d4db13356540db3982b07bcbb49c6e07fb1652a970e3a3c529d2cab95d4d565fc82e898751d416a4eb7529c5b9b5a8c77578b8c912f584e1a00d3a0d71da556d7a8a22affb6e7dca634edcef6e0090bc903847b496a2d4ec8b2e3306d8acc763b098e795ab379913b1e39d311aa2ae4f13fe045044111d4eb0e0bd8bdcea34ab3300df21a956f1e89fdb737306c68ae6c871f986636be66ed7c9e185c3bc22accb69123c3cf40eaff3de679d7b92adeb753a2d3f3dd7b8b6ca91a6dad64b1bce3f7b89ccae3976d276968097bf2e9ec4e301a861187e1a8d50e115735dbfa67959df4bba454cb3b7f0a8c6491ac3e5dbda6d73d53d88945b30613438a0404c15df3d60ef4a564dc829bf419cd6790b9622269584f41cae8933b80d11e6f4930a9a3cd152047eca6be881fa763a77975f82d516558562f17d218ea8e7790606c15285a5cabdedb40af796f8c18de6119dc322ff2f3783e4a0c28d0ba09f9c2aa0cfc0e441bbca920c1ca7436318ed01b7adb457fc53a7105add5b4026a1df8910d894979e483eedd9205ce44623b5f017083426a321f5fb143ca04f5fc7f6aa7a37a9c5c9aa714cd9ca5ce250f56666249c49740ce9962f34a5053e3558091544b2a876a9298a3774e450456bd827e946319c4a1ff3b23424e131178f9e4253d81239b2280fb2361234df167e122003e58ed4afc48670904ab8cee254dfc7eb9c1e03822da210d21b84b25c70ec7a3b697c9aace3ecf8cd10f181a56e64c065faa0afeda12ccd92f79a701f2bae5d193bc39648646b7372dd56f46ac475564a595ee4fc6af310ff0e3ec26796a0f026c12b6f8b2f4c090818adcf383e59b02020224bb67140029fc83a503d990a5ce9647cce7d2cd7e1162bbfb918c45af872b9b28c239e5acafd8e55c1a81c33c8eb8c7d5a27445324247d545b103ebe53c58bd64e4bda8b929ec656beb107645db2a2f7bc905d0af9bb76345d2b94ceeba3fe5839370b197f0cda06ee5f42e543c80cb29bc0604289627e26666eafd2e8937afff6ee1a4dbbce302dfabab6fea1b53476a0c03644fba1fdf31ee37512721e67922d78f06f6e6c329389ca49f79fff800b7397c55878005b632f91cfd5afca2dda85de73c7bf6e46ff4498e41767305a38bb4df7c52808003e3e80a565ca22349fa7278d9cd75dd63ad22b70a71ecf29c620ebb3d53240554cf6b9e008e9abe5a83b5b2538dec1490ddd8bd3efef65557e4c78e0cebf30c055fc43660735efa6bfe88323e1fb20073d0ac1f73700794625e4fc68f9f661aa20fb2621aad575e0aa56a56ee05604789503d4c2c7799363869380329e005a7c76996bf838f1c5fc322eccf07d18f404dc70cc1ee6833c1668ff0a260504a39c1f7e19d2fbb368601f18fd90ff697913d9f8b2f2de46fac792d0a52c752bc574e35338993941e57639bb4236b0701a0d55448d26f5e958dccdaf562c389d476a8ac0d1343bc3c4a548c0a2cad6565f5a18fc65a17494dbbee144270e9481b1e8db6cea8b49628e5413ce2635ba42d062eac7424da3710dd596361fbad2ff8c559f008e86aa45caed638ed45da45df68d934d2d11c9a57589b42d461939415f199e23c20da89600d700a8b62bdbcf5844da372dd52f5b9b4302d3a511136cb29ca07e9008897ab87ab2c3d487a9bf7eed892d4b811eb9086949cd438ba6ab0e456db9ff5f961b7b3e4187345a5455f1f266d68efedce7436551c629703c24f97ecc7b17fa17a1d08b749ee08a25bb38b93adbfe32b10ed49de2645da61bfffdaf876ce1c1543440c914ade0016416dbaccce3a306e756447bc44fe9178b65a23e6435649d94fa5260e95f3aa559916331e6978662c5e61a65be30d4a9d67e6f942c7ea974211e8eb8bb59f8604c5157b24e9fae2f92e7dec59aaf27464371ec19a6eeb63041c67c395246221984813f96cda22353978019021e73e9d51967a1359c2e95b73d1ba54c76ccbeb84a47a4452b49eeb81cda52841325223ea1871751d4e64ef35d449057ee93d624e6cb0c27303b1644681c11b3406cdb6923fad5d318bde7cae869c5c483447147a03602a4a420a3e1c56fdef76ff11b3ee6e763252e5b6a2628b4cdf9fd879808bfb00b244ea29e7679fb42b8665ceaa534774aadde69deee634b2f602403524f8d60b10ff7670eebcde7c45eee54508653d111d5f28f4c0ae256735fbf61a704506f7bcd6717fb28095ced51cf8156c98c1f40043074bb61edfe226098489f105105f1c6665b6d14758143f9d18c0356278660a162c133ddcb6ac3ca75614359d8489c62bcdb6d99597f50bfbc1d60156c30f8164e1dbd65c6c4de051f549ac82d63030a303e029efc7d9c0957db73eea34590cabd315fe2 -MD = 8ba9a76cc804d89ff99f96fc6d3130e4066e8ce2ddf61a94db67e5d7ac9bd3e9 - -Len = 33776 -Msg = 9c354b967e201bb8a63b49eb151a6e76c45df8212c28cd470bd3312d66e2e992ca37a087d8868b81010a49ad8d760d83e22ffe9e03b8decb576dea60ac7502cf7bf20a7a6d7a90c91fcbaf7a22ba3339476dfd7119caaa61aa2f6f72936447c836ce511746e573b88ae844fcddcf29c07a81be41764777328e80870c239700a683333c056aad7d75c9c7d0d8c59b373f03d106b723158e668ac8f9d665f67590ea8995ede1bcf32964d21bb9e307a4de6bc7a07b271e372427708e77606aeeaff4382276b4f820fbe36fec453dfbbac738c953348a48b994ebde0e981cd9b22a28a8ac49ea4b4b14cf080c24de60bf1ff541e68a557d5edf607b41e0a22d0a2a0f41fa0d8b9cbb9bb00444ffcb1cfc11279622278fa46c2d0eafeef8f94c3ed72f6cd66ba0d2b9b90ccb5a7e0d19b9c25830cfb040a52ca57ce3df8729209658138f060b30d78d966dc51648ad3d3e5d0f77b5d07068e670327dda363b8f59d64014539443927f595a5a4206b372d208d5d39b2d28d4e2b5b8e7a8ad3683d178406185afe1ebd72b5cf2a45f259fbeeb31ac4a6f6fd3679d9787119322e3446799e0640313cadc33faf506fc0dac4b30ab6a8b3f4e4dbe5056c7dc900897fbcad6f7b739e017d79abccb2e847280befccb752445cc2830f57d0ed34eef863eca7c1048f851ba10872adce4a05d05627a1a35dd28f14d03b594c3bc72df9a558f1592dde96d9ccf23cd90f2f8d5227ecf1f138090c5a47fb7245060a7e0ba874029e53fb33ca35c952c501f33e2bf59266275d3275115ee24b41c8793fbce1d063e7136ffc6b8fe06cf8232fa8cc53ca56cc4a0929c899623cd8ff8de37bf5f08de9d8a7514c4ff9e3f90f4f4dc1a6f74c469ad7caee6c1ddf6117d319d73956f90d302bc2dada58403e02dcad9a73abcf2cac28b9016b579b70adc3433d30762dd7b677d195d39e1a3dca4238c54e5a57f51a96749ffba2098e2de8e03c7fd0a4bfb815fe1ba02dca8ea23a8fb0ab756f26529b9e18b1afa22014be71538be8e64bc180b8cae4a9e9974700130aff9f8d36d092961a11b2edcd0ebe96f0c9317b026f4282220574ffee154d5332cf4b2abd3125ed02807e54fb5863a1b2dc4cdb6a2dc5facf77315609997cc0a6aedad01fe0c01360a24460119e382218199d7fe969a58301de41b4504018fbf502f105d56bfb99c2ebb7a7c65cb6a87f2595e106bf4bab979f287388a5ac65ac501044743f22f097c13a848ff069957674e89758ab32e4cf3e782be936919e1b3aab1482d6f0b85dc76f9eb515cb999c7be81b4599f5bf37309336187f72e5e01733ee77cfcf418362a95efc1956f53fcf26d55427feab5e1a2c3a8ceccb0d897a4d4ad986292cb7278a3dcb978658fed3276e0ac1c829b25f8591bd0b045585d859a21ea688ea578a84b38a0ce435482c6c4deff3fccab28531e43f56b95e53b5db9cbd8d890ae3002b78dde5fb0aba3f57ed7a2ae6fefd0fd3aa7a6c4498719765833cb793fef83ce0c62dbf3559a3808cd51ff32146f063dd4d049850946df16a0e22c12446f57537540fe52da2c2947d8d67d926332b35a144448747c2b7586b95f616c463796da18aeb143e6665efac8ed84980340bd9d238d095a4b3dc30eca32d44fee4d26ab1d345c902152c069c41f7c0a9da10e4e2933f6fe1e85b1f5fbe4eb82e4bbf10ead5a65ff35f735dcf5f2cdb1d85e8cb54dbc752a9b09288576fc10cfcf89dd4bf0a93559c75da69a82f0e0555d7d2119b8b2f0a46dd30e046002aafc58bdd4a90da83465828dfcec94a11bbed309b4c4929cce353aeb4dbbe47e21d22661bd712ce0caed0b8e1d1a538ce7b3e3072cfc020377a5ab57cbf227f9dc19e27c7fec77d760b70d68f36ce639adfd3581730a306e53bc672172f154fb45993317045f14175c8d2e2465297630d364707e70364565ca42175128ff910ac319c23933152b28283516c95a9b2afac3b03d070bc7697044fe62edd76506b0be6336eaf455e5902a776e5fbc082b1ee3a943232c07c31829b9f1ff666cdd749e3d38322f6669d9cc1ddeef72b9a0249d172bdabb3c7ce4e13b6b8ebd593bdecc70701acc91e08a75ed0d7f64f6b29558c19c34a0afbb5dd44c79a3c4774a77aec485a9b41e722c8cb1a41a7a0789f77b703f3ac3a8a9096ab4c345630d32c6ad0020e8cd5546467b2f4ac59c334cd570ecbcf30d6e6e720c3af07c82621b5432eee8dd007d8560a930a88ab2c324b49efdba68644b312020a8a85009bf2ca7a354869236e056037e7b6670a4ff381e6d6be19fb2851a9a10c495cae06c8d4969fba10f55c4e2b562da2b7f5a2fb19a45fddaa2dd65536842575df1efb167c2edabe25a46725101bd139fc0bc9bb6b18e7c4d79ce3301122028a8ce1fd6e298962bf07df232ca6cf7ef6b3ab38b70e9b0b1e12a6e374f2010011f6756222555cb457580404c7580783637f6254606cd13613fbfa4b9631b7ca869c67dde5980f6bf166917077bc4a9b0aafafc15a1e220570f3f5700658bcbe62ff37d53a5a27e627d4261ac04c0f0246d501e4069b23d5af8b371557ef6658319f43cc63242cbf65213058337fdb65c2800750f85c4d331a222d900d5e6b247ced3a48227e845433ce2ebd43d02641e8210e7c91ea04ba5b694774994e21afaf7989ccead1d5410e4b9fbe73e576033238a5eb85bcf0b7edc123377e07305633b490bf1ec676027f29f1d0361851463b475c12265d87d84bba2f5d4e41fdb4b43f0db340b51d14e0d9d3972ce13e675dddaf8506343087efc4fa5a6c571047ab794f3df33600f4eddb9377aae89403345c0ea8a7e991336461e2b36aeeee8b83e3e3b3a8b1e82ef0bfdff6429708963952f8118de60087242196fccc520efcd80f59b8c3c1292f83f717978664f29ce7430a441aa234efb98475ab0328e828026c1fb1f6dc4a833201c8efd8eae883c8bc93b4e0b674d99efb0d2291ec0079ad8aa433947bd2a665706243dc8150e7582042f8728b66d13ef5dc080b13fe8e43db95b23f284825a8c37247e3d0d234000e966342a97163341550dfe12928b23fef52b2595a116d766b87709141d2f66ad7fc99d3893b0bf8da09fe86a415a22c2679c86589d50a58d90032676ce9ab032ce400a7b31a3807a476089e0d5bba83215949064ff978baac7b21c8ba7cce337deb4c21af9573eb15137289dd5187cf609fc89e14f525265666b357a302dca63b80b0e3e7335c1dac60b0cc8c9d867b54bbdbaf716ebc2657315b76cf1262c5f632f360f28a3d09cafc67e8a39633117e1bd6bccdac9a353f99aeb88731dd0d2e70682b49f0a359f134fc60bae21a2c6d5e6e48b2654bdd6fde119f73d7b7f654d7a395660d3b68cfa8e2c72b07a81672f1f6c5a7ff4d89789d289e0d7a901c09c72a51cf4641c0b6c6bf8e8c5d698a5f54f4c616f11bb3da455826cca0d1e8adcd50c2fe2272ec372ce7194779dad253160cdca7d132f7157524ec39d119e6c158db7b6b282b65d139fe09f4d378992ea3935ba3262fcdba9b1330cd81c480d5081eedaeddf7a8058c68d30cf0cf49229c2cc5b1466ea22a25a7a700495e5169599f9c31aa544d5472bc0708684b6cdf5e3dcd5ad88c0ef4a366a16a8e63d2eeabd1f98c13cda04ebb7c186f90896ed5684ab50852e48e9aa2b4d264c7618fe59d5a9826a0c04b44950d79bb1fe5d97548d82f322c248b9c92269ca78ad3e2de9c9dfa89e7d8c8d6bdf4cd734d0d375f8e6a9e60eaa8906af040828b5f37764a2810933e4f73939584d66610ce4c02f49786852d150d37965b770688ab08a4b8de66f4ac5e2d25d18806e62c0a4ec6d4f29075ff11aeebaf225e9b3804c4089b1de5916c8a620a4b462ab01d9771fd613e2cd34f872a1705e34bd311e2f61c717520ebe75abebb333da6767dec420129c8c04fa6ebfb543b2ce3209ecc2b5acc52bd76b5459fa359dcfe8bb57f5b8caf30df2d8d968f3ddf5da9264726b03e1c54ffc45ee1917d0fa2b7826cd71afa61e4fdff7c3d720e32f4023693993150d1fa8c573ca51082c53d55dd0c7a0cd4d2738157eb373070068e82e41c8a3b1d9d91d791e706b96f2afb5dfe0cdead96815b2db9632a46fdaa9bafa13a701a0edfd95626d69cd89ca17b3487f67b79d9ef1a47867c7d21f19f99ed1085f17a9f092fac6893ce1a95b92b7ded41e6fdf98c2f53518fa65e066617cf948774c968ba133ee99710dbe4e28a9eb08797a68fd908f5ad253c57a69e83cbbfa77072e65312822c691bb8f4ae171b5420140007664592fbc5b5bb5c996c65f46e7b238274ac1aa382352e5f8c6f785ab3c2a6eab453bfbff998d592e73022d5550b47d78f4e6cd16af3a8800de24a26bb49e7c433b1d08c295c42d4288d86d4f3a75c501387fd488bdda400932de56a9f105f0e74ee79c2ed869faaadc31665c2b5dd7691d7407b8d69cd5bbc80ee78d79c8933e8781006be9e2881177f361a2add47d59acadaecb81e70ec0aa9d9e40d64d2df1edd47ca050999f1d6208a64c47427d79ec1211ec4724b4bde071c3ea90fe86a788c657f596f40776a4567d80820fa070e58c7841afb98f5d70749eb22d4265096140db93425d87c545c72e66e4a3aee79f012af2410f6745648c76c1378094be7f2b4ea2dc3be9b24e420028f7666f85235b7028858e0420c3a3953f3622d96feb6df949edf6f3e4c6ae3deb43c1abf37880920b049e2e9496a04153b08ffdc4abf024b1fcf66e04b5f52bda4f1a29d8a65ad8c245a8ac49e46bc3252f2fc864c99a170291a221b924fe121aa3dab2ddb6cf8976d01247e9b5ec63de3a6a01f84c5519633464d6ac19b13cd6c76a0eaaafc9ef4e2e46c719120b68a65aa872273d0873fc6ea353859ff6f034443005e6992f5073e6aaf48301b01ca41551e19aa39b6ef6c6c861ebbbb5755ca0965e397ce9f50c80a895cf8dc3c501f6cd17f986f55079c539c88677d614776603e34d61de264285a774a5bb2cace48284dcebef0061acf15f50ffda4115ad1bdf5ac74ff82b3d7c0f57ab95d3197643dff718e4a3ebb8d5a2c1feecdfc02549918c524f1e4b24ed47078c22a053dfc044322970c634c5f66be22ab6965c08778341946838cf1f60b94cee6a7ca446811c53c6985185fade207c2c3f4f337d2e1c4135a22fff585ecced7a764d52d30fd02396662d267f142b57ab90f38badf5c453de05e923f46ee8b4d74dfda6b0f1c66a42e1405f7d20f23b50af68adc054e341379a4f831e197567adf772e802af68f0711173781c8bdff0c3a698e1ddd3e1d1e7684967fce6dbcfa67d9660f4d21d7cccffafb883db583dab7d696f2cfb27cc9777c016b65d83b468e64f56abe14cd8fbb2da69db9bc7ecb13ac59ed6531bf9eed09ad97506d3de9b3a871152645fcaa532ddd14b5093c37ce793b703642622957ac1f8616a3414e88225da0fe3bd1b7288a138fc84248bb58bbb02dab4b10d337d1bbba1100f20f7c511f90ae7ce930cbb0de815bee20b032f24c784cd228371e292695e80cac86f0b33b66df7faf918d30828bf87350d0fdab84e2937e24cf7b00d4cbf43cfd5f85c73585d9ca91741d97c3f2266855780945edeef785a306cef73aaede0840e3cc1b929045d43b32cd4507665e33ab3ff65fec1011af1f778a8aecc0fdf533de041ed6f8ac2309684cc6c15b186bce73456813d85a50e68c4e2a5fa4ec9a3288fe5f7731753d888efcab8642dd873bbc66ecd9ba49f1b4df8a5407cd225db98efb4bf7dd199a45015d41caa0260c8f95eb6cb2385927f6cbcf96799c27b6555a8b62dd5e31bfab8a0f5803157a62167a334631c5105a28db6e7029a4654a82763f32ac2736143863532cc3f5533e7cf3ef27ed02f81ec7a9176f9c788360cd6c8749c8daaf4e8837e95e81d238e83f7d6f80285488dc5faf3af34 -MD = e106b1dc3882faa7b7f3a0fecabb21b5b9f4474662318d7102f16ea42b527413 - -Len = 34568 -Msg = 3c346f85602ca0ef6e595076518e5a9d4997a8b7337099b50bb5a53daf5a43fce69c0a3ca03717b980dab0b097d8263a732000d8586f554fcdc47ab65a15decd914031904b44cc0c34b14d728a5d816a215988a9ab2333c6361db149f63e6b0645082ca9e8ba859194c670e2b08533d55d2a8753b4f5fac34ea992200a3fb34e0adc42aeff010bf0a701602894b903242e7b47fdfb4b71ed1e4e64601e7f7e4ee9a4bdc7198126d0754b676dbb5fbbff9d340ed0098e62edadf57134bb6693ade948e31ebda19dd9078acbd9afe1210db03d25f46527936a0487ffc2685cbc1413b0fdd873cc3ab464a8d593f7a5fef7717ed490977ccc0d29ea5732adc9bf2b6dc55220c367c309948bcdc41b151964e8e062cd28f7d77e2608c1ad12156599026d2c1c36db017fa01dfb93a3973cfd1c4919d29fff7b6403c7845b20a87607d791d1f45390bcbf8f44a62918952d6a15a23fc884fb7f67c611ea635eebba1cf61a8ad1a2eebc7169ea18ad0276b552dbd41dd66055ac3079cd39ed5444f98166ee9fdbac5ec83c37f69748e7a29c5e77c6fb25b974ca6723e3ba238b1cfadd2ff75839f846aac800506c225181aa35f05f21dc1ac0a1b4cd3ab52b8adc86d95a1bfd140f0f28becce0df62c77ba77f4e89d62408a1f8bd7ebc722dd9ea651ded44d59377220bc6a38e3731d2f85ae6992b63250d7f982d3e50385201b05f50f35929dfbae51a878e42beb6f9608c10da2c1006b0c24aaa15de51c189943b1a7142411f5fc21faa94e4ba1ac41b05a5197625f07ad2d4dc0c4f03a3f900c32571e7657cef20e0d6be5c7484bb918d4e5cf0ea0af118fe6d2a899720da5bbd16fa30dd1ef16727b41392341d672aecb3ad82a77d9ffa92027875555fb30df2981505f02cedfebaec9b6e420c4f4fe97b1314a3700ce15646fcfb84890c7e2a51c94ee8ce6c4f61255ed9e57afb664e4e978e270cbe3614dec0046dc56d162de91ef30b2ef5c1e60765b9668ff4d9e1d63fd87b783f5f9275cc76593c5f3dc2091cdca27110bc103cb7f80d72c10e6bb815dbe7dd17c699b1263b8e16695bb359ccf1f4c245a8a6695c7c224cea6fb39f217db363ccd1f03ad839557a14d8c680351b4b471dee71395d2fed44f86283316aa72631e8ea61b9ea5af590e71cc4275f40ed281ff43951c1f7b6837251a116f8428970f378b2d66284b8816a8f74f55349238ed423c55c90bec431e0a3d6f7d334244773e3ac384aa1e4752599a093181f35a1c2e3df00d26b6075cac0ea7c04673fdff2921788a998c293a1a30ea8b6a86b88739d4de590e6d277b910a54c92c12260f7efbb6d88519a04651387dd36ce0d6c6fb7d8b4d217626035fbcf10852c15f10b615f90eeb4b4f0f953d3da9f7862743c9b48159ee65858c4e92f6fe58f5fbab550cd98e3a9577ee6c9ba46f98eb3c964af65affe3bfb86f0428e12bbd149e47d24cb2e7018ccd6b3df04c94df748926f5df72bf9fe9413406eb4a00edc1b97eb4622fa9be95c21e8fc780ca29d69f8e30cc53097176b263cd569c2e7971dfa881c9aa36e044c870e87e0b700675e234a239867e16ec8e86ddf75204dea9636db0ffad2f151e72facea02726f3d6e3a2b0c3878deebf3815af59f6148bdd0726c880c2e2bb974424a8ca6e3f807e3650f2e6d0a977733188c7db02ee0f811d7c4ed966024223ae770d596b5a2ad03ce7df1ffc512f8d2d589e1712e1e84a28d6aa7610fe4768247a72d998e7618179afdbdb553595816e1db87a70a0947cbbbe61f35e4749b948976fc76177a2e66f417fa5859747d486409d91d69aa2ad38ac1bcd987db7bb8d766aaf6f7b8d83a025410b0826951af859c3d9af40715042182e5179f21fc3656fe9fe1d638ffd9ec3b68857342ba956d1b1de5532af1a4a9b104b5d44f085530c644ff5e01898cdb55689fd707a240440ee0c72d1ba4fc49d7807cd06b865f8d46ff17351a609bf72879c654bef0f931feee082ae018542a7bc13438805d9a940739f3038e6a4e673e04c192718c085c72af70f38333f473252fa5b793774f6e905b59716291ed541f6f593a275db5eef28bc6300cdf234d5d3296f3aebbc54269cb1226a0bbbfe5512356f4e94d480f06ead48881032ae0ac32d194d81146391bf3e6cb50d20d435e898067be4308e6373460a4ec87515399971c431a61187b2d3a9c0878bd1f95ce089e3cae283f9c0cd1332c5452e0ceadc940a87b93842f2707fe8422643d0427077a1bc1e233580e2915c7c24e1f7b6e30056a0390d27e92c4d2e855afafb8f3f0daaa005a2c43c3a4ce1d3d62568066343231ba3e4a8ff4d8e1db1a86bcd8b92a879472787485b5ab25d7cd76cc051d3e91a7a986348bd8abf30678d1ae8c021d497f1f2552456ca4e39d7a73ca331ab4e872d750d799c3a5d0117778cbfe5531e71410470dab6ff9d0164d3f9831e500003a4c857ce23f2e3fa31f635c533ace2bfa4cc7eee14610b4eb4dc37e280688a1a8110b6b8dd3ae0964797ba8b6395cdbd9db8e3d0c795357c483e7c44005b692632dccecc3088df6fe8ca6f94ddb43c05bc683425790288147f594b1a06bf19d14a8af47ac6433ce1660cd9540a7eba226148d44e814f9f91fadb08e71c0a088638b9bc36f71085957fed9c5b826bd49e2cd968de78d2d88f2b324a3da8a2d1cf7dd7aa935b7755f666db0d1ddde1f7c38fa85637d812cf6690dd9380453ff2179a6334125bde0a7eeb53c01d6597a05cfa2420fd27a5e0b2bc5b69517a27e5f90eeaed3680bb2fa95df639dcc1f37aa51cdb4d80dff2b8ee1e3a2023a00129ee5bed3a72529542003f20fece6b6bc346383c5085699fb49326d87c695f423a5201d8a0585a02ce1e1f627374da8736aafcd5ce6d7ce3602c76d4c2a5106193de814bb34b0f6a405d7f493c6287dc216ddb261b9b529448247ead97696be5c2ee5aa4e7dcdb623538cf23be1a0bb13fe953bbdca1b2f8d915bed16f28ba55440c0e72b2804651094a9fb07d0ddeccdeb7e6f56612f6a7af6ab7debe559426a3a21d33a7d7f8dd590d514dfda069758a6405615c51961717bdea24099271d04e6af7764c363b5d90fb947ab4943451cf484f8e240029cdbe69c64fd541ebf8c0a13da8f44db6684d9fd9b5363be7d81a0f25ea61812a421008fcc0a5f66af686ff504a4460c273eb54819bf719cc7ef70318f47967000a9915de14f02267502ddfbfe8c1221806f6d42c7d7ba08abce2eea93af024538dd61aeacb484879ac01cd0cf2df040f97fc794af848828b286a0c473c4a4b8d524372b33222fb0a50cf31a7f7127921bd78ce6d9ac2124637f8f683670c3f25ee5dd7b807f49c91e4d2b82173f013e6ddd84df4b38ce254721c27de49aa91a5b8a19479bb51bfc8eea8caf9e7ec46c78fa76280f11d753e4d503ac862a9c59547ab4378aaaed6f7c4dde4a1c18b946c2962b692d1d84d5c501189d2207e5d7d21d76f25748074a70dde9fa9af428f1d51a6c49ab461dd46f0fcaf7c31bccbb5cdb26210a75b0b6f20275681efa599839ecff709373e9776c65e1626e4d982e7b1c8e6ba91b31db8b24493bb31293617476ac87ed8c31e7426d25882d859357b64874793e21d2e0c2ab2e1c5e242074101f3d36bf783d4b7c8d5e0e07ab035f95c7a1f2d06fdbed2000ecb3291846fa954e7824132155cc9f2f539f05a8316da001dd7f68ed942c2c894ba71bd64e1b896d27faf06ec19235bacde12d6265aa605fefc80d8345c36eaf13a13c4780fe76e3105f5f47c8c4c696947c89c2e73d5c47a174c71935da6eda0b48955123cce318fcfc6694b48ad82a701921b0fe4f1c22b92c9e97ad9ab573fc452ddd81ac5974b279103dcb0df5e02960fb15f308295900979be5f52acae0ae3f0dd4e0c75f5ffc7d622b5675a41f86f821d70e8f0a523e5ec5eb55b3358be9df3b1c89457d41a0b066449cea6e50508a9be0970d47773b282592155d7fda75cdc19fc44d3b8267bb2371e793d9d94fbd6f16d6a9692fbe9ec1c07c4f2f3719b0a743d807228a1946a19b7d986f234b3aa763138cf7e19168a35ed3b2cd099e30f3f20f9cb9c17ef8e9a8a722b8960ca84bae95dd79f77a2dd35562ade1b8cdf6af93af3488905d7a0282ad593b9a59b061dfa5c578d84295578b7169f4ac6caae20e01f6185d8073f40fd7648098fcfaf3dd8b6c7becb14a39ea480e8d4c43f4954b4d0bf091ad8cc8396d6b0ff6bb2d08928ff90a9b8ef181592fc335021c7acf31db9b9995ad6d85e6b698711e5ff1a9e5f995ad4da33535bf6db07336bde798aaf2cd99d048bd3300fb112d76b0f0ddbe1067ed6ab6bb5f064bfecf4eefe1f89edbc97aa94525db6e84fecb6875cfac051d98515a902e061511d5d1b37a10f8f3dfb8c38a6e4c83189988d35b78391ea2684f6285f93433d4075c02cd261e9f9244c2fdda89db36e682d7ceb77fd43c7e39b5a654b875ed2b74bce904bbb0f663520eaf005f79f9c0861244e353480d7fd8f2a72d979b3c02a21c0fc10071034e53c56166b8cfd68eef61bb49bc3e998e8c2ded795c4b2841d7a5fa6abe06d03c8d0e9c735c84d43803edbd50815ee9949f8efea1d02fbad05c7f3469bd1a65134912e68f1241fba60bded1606c4f0477573e640bbbeff99779d14524c553c8bdcff8ca22a3ae54c14e5c80e143baf221fd65a721e533ee7f75c3b3059e59032067e9cd94d872e66f168e503bcf46bc78d82a4d4a15a29f6e9a7f08720fd51e26590d794e7736ba99a99ccbd7d89c696632b6e0ed15e4164d2e2acbd5e26f1fb6ec8b55b648a1d62850af791b266301d25131e874aba25b057aef8595ddce10b76a8ce935155c440253efe17080448da37ec2eb46a084747cc6f4bd1ac99bf8131937be34a40e0c11fa838b3fafe714c3019173cbbb316b9c5a61fbcc6d7de0b142b55b19be60343b8d93ffee7cf39e1922c7076bc652484c7d5fc813931dcf792c2d484d2bfac66a5349c6e7ac11348d298c308e878e11737816aa570122cd5321c80e39b383c98595cb67900ae8dc075d07749cc88ed0fb93ad2b008035e32767ae34441ea446749b416a535d21a06f08615efd4ff98ccb164cd376d8fe17dd470642d53304441fadd458976c6388ad70c17319e4784ecb491d2921d124735d09f8c156bb4ccb6e13abb7c300579baadd503d5951b31de37445b56a3350ff8ff5ae382e7f23e44914f01241e1a4e14c993643235d5101fbdeefffb7c529c25c534d2fc544329598fac8ee78d7f3627ceb9a0de0cffb02fbd04190715058c4aa6a002e83d520e8430b5dd5d0aaec27231aa424f9705829cb9263ef019c840d6383edbed0f996e53290d74eb1213637276f7e0fd408117d546c7ea4cd7156a66de63c6614773c934dd05ee283067a9a72324d56db5fcd067ca6ba383f977696b2db16afb718b9fa7d151817ae1f5f59eaab3c82753c35cd2c873e32bed58be518aaa32021a4b622a8a530789a358e7b7921701a0968f0d94d58331ab1f53d9b899a0a41bae3da14b7c9cc8ab00fae0806de14a601aca733c562c07982bd36c1ecf4749aeb9cced793c915d75677680978284eaec4ce02e17eea0ed598f61b5f280108b41a99397322ed32e6f5336485b94846bbba96a8ed5e3b45b95b68977b2706ef16b1a0c4f14e7d4b3ff60c4984b08626544bce425e4f9c8caa33da501fd04e5048167a1758fec08a6bbfcac00e45291302df3c773d38540b328815ee520b2054d3b3efd9b01aff15f1ba35702c607b374cdeaaf09100acebd8c2e21a1dc0c3223eeec6b201898214594e1402e5e9c2babab0de556291ec542449077c86d780e41131c94c543591b02ce2311d42c847c4d4bda04db9d25c6d9f864cbb98399fbfd5e3be4cb0057410f0e0526a49e6527b236eba809dab435fd0df7b7f58cc68dd116b6e5d1ee1725e30af409004292a0a2e29f2971604eb5140bd5a72d07922664d33a125a5b1d5bf71b7c3387b7a19977d57123a2cc59a6c7589b33a0729178211a21e4c4d5de35d3d60a20ab5c2654b9961e010e8d799d8f9a94c7f05c28d57e620af7b1e -MD = f765505e0b86e82a2b0a0c07a10399635ebe888422d747ad087fd69145850857 - -Len = 35360 -Msg = e139e47cda78e7723cccc68a180cc9799fb741df438bc97a1954cc9a820347d50affd0fb90c0d84da8992de93dd5c2897b06b36deb9a8496e0afaa3513294c638a014a12bedf7f44fcec437b0ce1347011653707b095b98374e43bf671250dfc28e659a9ab0064c0026c1126cc58a796297ad395d8a5f1a99d9a87c6e6201209ad5706a9a049102a80c29ed3c762a1638df09100acf1b2702379978bb842e4f0e2fb58f8e5e20ae83f95f26b4325ac3f046d792e74a28740cd2b722f30b20a1b8c7b577fc2f4da64078e16d489cc4f925599920878dff5816455209896990cf0767e0b267fa709049f5511f8e17d13c4491ee476ffd1869bb1a2aab0321e73d967ad7dd663221e32d191ebbd92607e3da8a17761539fc1f679b7175d4b6ac63d26b0b475b78ea15563eaad0de69f1a653acd54afba722efa873f6f892ba48d847c2eb8ecc3121ad41e0a5ecf235f6fa5c647824a7d725610a2e0ba1b18f5511531cf9224cfd71219ca9606eb92cb036316ba0918e4c6c09e914201fb5b85985a0d3c49042305118b2f39ad487b086108f0ccf2033697f40e1d0e4c113c7bedbad81de57307c39d9214995cd026410efd1d2544f2bd0c7bc60eeca14502ffd59d59196f5bc2394096435e1b6ada9c93a9656e07ccbf4edc302c830a7ff73bda6b59d9eea39d9081ff8231f0fee14179738f4f437b85849fb23e7c8ea76154838da0056a33e0f0e8369abae575815948c5656f01e657d74db60e7e35a589755869f644ebf3d380fea153a001b5030c8606ad7749f57c6f6da362320861b7c4e268233e7acbbd694aa9748b4ca7af81bd9d300e21903e7387e103400ec33369a8f2ee9c1ea3e8d255b6c725cf33cce174f4b6dd939fe30c24d8b94f50b4448d33702006e0639ae4a53112139142a4533472078ca60ab461cbf04b07d41a335809488123c6f31cc7c4801e009aba7d00847feac262b9f99b04918312a4df49f1b4e4d99cdb3bb6a23a0db392f385a010ec832827d095fae157232715c8e9cb81bcaaf0182423af9d8d3f9871a38955aaf4e68964f784fe5c4d0e00bb4622042fa7048e40ab9451e2477d9746b2b0e3f62511d521e06f4f336dbad6a928703b24ff597abc7774e296ef3176b929e0941d066ad405913f338f3f8f718a76bdb7874b117d3390adabe40ec2fe710f03ae47205a4eb914daf3984cf6980436f0c18114945f4eff25f4f22b98f7176c007a9bf94a0ae5712ad7751b5515bf72f1a13ae149e8b4cbc605e8ce1b295249bf40421ba0d130ae16264f3515ae6431a89fd93a9adf0dfc7625ef80b35ccbad2848640ec66b42d5852a4d209f2c9b7cfd0387a7ee0e039b1f9d2fc7c8572aa023d9275822a0c4ed612998665a560b5ad8146bb1ae3b3caea8b6cf2ec2e3162a983cb6831e385eff916c578eadf65dd3211baedf402f6040f9b5f73a09c837546fba371720fab712fd3bb32102d239efc06077ba0db21856fae5d17505ce36259099d39a92af782e8dded4a6c0b445b79d2befc97d8c0cfa938d82661ebcbba6e321b196db1f485b299ce1a54e622c32a0c43d94f984e333acf43595bd5c6ddd519cfa926312d0a2b9be03a716a49468b2728ba3e763450a2d63108b4874f5d4c050d5179250b80a258c61337f442662b97ffe7fb0f1dc85fe223bcf29cdfa9319866bacd0a0a79c554e24d1f10889279e31c0afbdf64daf0779dfe9c62f25204586e3d985cc455f314c7309d4ba65bf4ad1f9bb753a438d31b0246289621e852b986626199a3b5ba2ce776491206433a4a6d02c3f846429620e31c1d92d8ccab2041c1cf4d331988e1b57698e032c8a93fa6e88859e588a83dc2f8e1d5918f5c4112c427e3fce1fdf7c3ca1342a65cc0113fb5aae4ec8b87d634552bfae69104809bf2020a5bbf77b394e92eb5fb802d53a9e27225d5cbc36e89c9326f428222532fc3f40cea0284c9ab4c61c68cc33f7b77f794893bb9d98b65bdcbaf3fc3445d50c26488323bb38e697c52d0e4b674ed2c7d78ab78e638a14abb2e3738e4d8f39165d9e8aefb729671e158819daa6c4d39eca4f937c16f349b49f093b8575eba8436dacabaa2406637240935123f940012bd900ed2ebfbd9e9d2a94148ab44168bbddd8b0fd0ab723baceb87ece67aba6978c038e4b66cf5b8fdcecc6451379c2a5358c5f8f7223ef1f455e6783f9eb08096bc13e7c1111c8b13b79195d997cfe29fe2f820963340fc92fecd5e9b6e96faaffa2c469ca6b2c2cd1a4d57b4f306471bf29df12e6d1cadf13cc90a8a68d25a2cf0feab998c5d12726d3c1463b7e3ca200e13f5302e2698a7a656069d1c07118636e76158407fdcbc06fa667674ecde74ac16973bf5034f1eb1f0dd440689a34442831249419f94029e14c85db8960662330271b2501733dee625e90fa6ee920f9a6e38fd2e30dade9907b499e153d4716963ff33dde6e950b961c4607bba6010a4f54fd464e803a86e3fb5ab7dcacb3a85c7aa20ecf6d22cb230f9d70361902008a4b17f7409c118a44936231c5f5d263e8a0d1a0bdb70bb572ff3e3cc6894862c19285eda2a7577d1a0d0611b75fcbcea37927fc8e957952e9b4d0735540feb85befee305dea37e5cc2ff0619c33c771f5cc4d292c4f9428f1f5fc1eca844a8bc02bfac957add74cc4c2c8295bbaedd54763ea2f7d2d83c1f38c6a430c9e5461570e52bf7a385f39698d356fdc396681ff04a7176b766fa5553fc1ed05d645c58a5f9e1aadd2f835235ae03d07fb59fd87782ce8dd747f5a81d7a9219c73453cc0e885e2d7c4cac75aef719ac447efd2458720aaba6ddc6add1ccce9b9bf7b50626fb020e257fc7776158f8ffb644f87a3f82c66ecaaad5dd3d5cf4c44001088d6bdc7dcb5d0b6cddf94e222949ba3a40795f7235a731bb9c9cc5d53267f2c6c859a711c387a2252fe34135d773410b2db242ae9ec104e0829c71c044584f585d7cd56ea539c658d39bdca488c77c038866e6cc08ac86dd15a8fb4698a56965a35201f4dee7daa06f9f6aeeabcabdbbe703b66b11ce4a19dc4ecce8add3f35740559744ef1661746a7a8684bed1a88cc0153bfc38aac11f3cfa5126d2785fb59b041fcf3449fd4d4a99ba073080af0eba17d20ffbc68e65be384271c4e710f939fa06046d0700a386997fd6bf6c43ba2b883316b9b60475d684fb69f3c4b99aa393e484f7b21e1fb4d64273a9d90907aae2b99120ddc5d82c6cf66fcd75bc324e5e25a152ef980a4bfc9c7e8e7b517faeb3e01f9fb234f5165cce03d09e8b38b0d5641a0d24110bb2690857ebb7dfaaad783102a4e7e4653ae0ecb6ab93c91661860a3f84d42b8c9ea7f0803002e5e12dbc46facec356a0e075cd089cf9d863e6ec929268941a155725ff97fa0116dbb5dc7c587bf90e20cd97f97a43254ba9a77587a316c89f2e728f7fffa826e4f2cc755bbc3aed6d7d58d40c7c2cca954029ad73f21e061d4077311c37d8e8d2ced7f36f969a05170ef896508ec84e37cfe420c1ffecc106f3ebb73ec0facb52b87ef3226817f47d6e437b60429424c5c17d4c1c3d117dfea1369e623b9c43074817d11ea113201303cfefd6081ee2a19d4b9bcd2a2ab166e0fe3321082be443063939aef23a1c7a77d4500c7fc71c6debe59c6f5776ffd22b8921f5a72823a87b69896dabeb4e163317688dfa3b168d15b1ca6d45a4bdb2f99de75aa91f95aa000f4ce56eb53968bdff85d507d97581a366b26165227fabc3730fba7e809eba4cc0e0709b1662f48103347c3920bdde2d4ac0c6367eba0f21cee7afa7e9b37ba9f500c9b18d5f4c14b8f0ee0ebf64051bf492165a28016f9cf82bb4a5b98840b0321a4b528882d1f1874794e8f3eca8e7ea82dc10acca4f8d852834088e61bbf7fe996ffea672289ff4a52b686cdc0c29933f822a8b89117c0c89d840c6f44fd9c11ab20655b1b2889795fbfd9896d149850492e822c27800d4ad0bdef1946ede0ffabc1a14a5f233d6969128f5c18ad0469e98da311ac584a42e3933ace6bb8d51c5e89a71e37a3a4823756b02d08b465e5a1e8104d69cafc179fb0f475f98603d08b217ebdebd0442d933445e38652412c37e7d2caa6fbad31ccb925f6397ef184fc302e11c3d1a8d043545568daaf22a67331f26eab16e4f83259d53973c9279e775fc00006cf55d5105de8a34cf28fbb1f6f7823bf412ad498360d25ef8e2d88c5563b74fef1d5a2c2f8067c244411d301486ad02ba4062dc7f8d4a4f4f68ca8aebca754f160aea121ccb8dba9cc2f56e365d25d3869006b8848339ecb29cb68f9390d8828436b38f48205a824b371ac8b6db7b12bb5a0f6a1ce31f9bd4e722f707774f7ebc391d105c1f6cbdd205f3dc10922b64fb36f36da31d69e108e0964d91be48b8208aad31a32922d1c3c82714fe11a53eb88f494fd192a750c101971fdd0652b34393ea6fc7ce1b4292e61b1fc9ca770465fb776d0303666fbfd29bda43c00bf4a7fd3b27348eb494b1f84638fe3d1f6a95e41451d1b015a237cc2b09507bc300c01f35e473eb9d5cc3774f1d15da1cb5cad196aaa859337ceb66bb29adaa264c2e825143f05523ef29db8c18ab31ed8a775c74b3f14f5e742d2ac2b795db844b45bf23c2446be6e067ad83d818c5105d2ded452a6702e50c7f90d83fb3708b82a83e03cbea8064b4ff55dcb8091403b240fc7e6a642465ca7531722e8109aa96b87797dd5d431bf1737ced54d6af560e631286e063246f228075171089274fdc0904567317147b1a468b3c2b1be785d616b80548fe735f9943e44d62363a09e71c6cb639928510840ae95fa7435cf1bdae656ff090a1b5b311f76ba002b2672c65093d7d7a155ae3134fae55e7804819cc932d73c4201ff48d3718668930c630657252cb1835e8abf206deb372f1f76ee3d9c44ef38eecd2081bda023425c587b020acbf0777184349b7374c60226e4176a1daeec94eaad0352e072f9e21e386b7ac91a5c249884d6cc96e8d49723b260773c7df9fdfd87376e6462b21858ed1fe6ea83bc33da72efdc5daf29991dc8118d8219df1b304305fcd1da158e145edf6ff56dd94b4036c5f250318dae1d0e72d376eb65978ac9b524ad41ebec5973f33d73407c15d0b9a037f8d6c87e2a6cca72a059551913018f1082fffcd93014a277ec636b3894e1cad3dc07a1b24cca639188cc7648d4d4dbe5d77c10fe9f293546e6406f5d94978aed852ae2f28b108359b7ad8fcdd428e0ce351fef03b19af4d1eb3e4f2cd7c427ad79a951e5f02673f2b462694f1ce7e7f12352608f6b4f274182c5d54c654eea3c42eab73482f47b830755cc77b2f73876297d2d4ad73116bd343dc766461f1bc26857db874a62e23439ec7feda0421b86cf061cdefc26096e870eee21831d0266715687844e59f22fd1914c58eeaed8499e56f6f0e217477b05a112262232e651e75181d698bff19957abf961a225b6e61dd5822b92ed190d365cfb1c2e4511ab51af9223307e289d53a24fafc68efe85d5eb8a34138ec74ca1a870acac3dc99b38d882141c7cdf604edd16eb61d0f9504c01d4b66de4995fceee3a7ea60457492334195066a35e0dd0c616bc7cd5ec6d0c7d2a57a9d6d66f45942139238103de9a2b1f8016d9ecca5fc416cb1e8422049dc952bfce4bc8a38f04ed862c9c148225255b4b3208d2bf853fe0bf4fc5e23e854b1497e42db52433a4660cc83dd45c4d8a965ac4175916c99f3a41178073424e6d3a87f463e619b9de5474ff4c899599c29854d3eec6f4b34dedf97f9d1e397f968a3604d5a3abaa197e65d9b17c54923529e268756483ccafc18e8e052b4ba12dce4d1f6b34028cbcad885f54f5c2be4b11ac8a947aeb9b2e7da94d9ee29f3b9ccc734a0de045ea31a985981e3b07a76d175941334f54a933ebf1c2518a5ed54a4d518fa3f09d49df3a038df5984ad5010591953a2ce57c24d10ff7076daff89f188ff515ac31332e28aa44c352b3cf71a1fe8f9159c69e6af8aaf4a6d1bb2a03f7d4844b5c2a2f863a23c76eb26c1d23b44636201e20976e286bbf17ffaaf6deb0c8452d48afc64f39161edf009a4781051193d0c31bed9728f962433fa3e1980c143fa4b8e97ef1ee2a4fff8468d5f15e08ac878fde2a4cc2fee511d9ce7599d3607b96f3ffe2d41e0864b586fc50dd85d28b2ecb92d5f7bc1f4e681454394acd53ffed421a7761945864e84d7e40ac431838ae -MD = 227873c9cf295ea7ecd033ad887ae817e6264234111acb502bbcdb088917f3ab - -Len = 36152 -Msg = d520072ba3414ab550976e18fd542e33d77ccd4de299fe61f6b102b8077510bda9bbf90ed22e0ccfe2443743e271709d099b531385cd0d35782f787d40368727fb18e5424a83d908568e6d6b11f0cff0bf6ff7c0b49c8afd5fbeff52870c00ced51f13f293a67908b35c56b7133713d5ffe2017cf86e3f60b345dd5f655f415a3eb8ca443301b47801953c506fb004f3d3dbb86ed7abf2077dab5bcd619714743fcb5460b4fa52004923655dadc169f3424366bfdbbb6c99c5dac1c4041c3fc4de40f76f9efb1a4792ed1a0756d40c7c540051968c0775bf91b9576bd4568af125fffc99776bd5f6e4dba276f150b33712fbc11c71f5d521eb3064eb5baebfa41cf0ab05c9b24bb447d547d1069d27cb831c007912ee5366da27326c218aa484cafc4bdc1b38442ac4c34f411d2330e1b04c55d4f75bb83667860715ad53033a37092645f6648800628d03edbf4995219f710755a9a2cc3b98352c0e8772a26d6b008269e1a0dedd2a1cabfe737920325a745f26af2d571a771de980374d49c66fcaa8706454106922568f9bc21b97bde93ea56c9162217e0c248593454ec2ec4a4de08107e6e44d5424f6ed3395c36952b62152d8abf10d5e334a6e3adcd489047371c453bf2331c86f2a1b4e506cdf9fc31afd0b6f916f75337e3a9e5e4642a623a562cf4795bc851d714e9bb45ac7d84fda98b215c74d590a6a1ef73ee1c13645c28304e60197931714aea32a54c80341a74955075c4f13a25643cfe36daebfc0114e7805306afa465a62ed18248a2a81ca387dac181ca9e18ad0adb5b2b0467edaecb50aebdcc2918d9301e790b654f68b8fb16cc25d26b14dee1a1c7770d5666585435ff895f4dff368680061f48a8a31737aaf24b98ff9e9c59d8086967360f940a86a1f3e981ad60aa9c95eebd324060e5fdd04d9eea1a47cbe49a5c92954df456e952a7fb4297ca04cac514437ac5088e85e2b644a90c73c05df9db1fe2a60bd1c47dfff52f42e53da1000a6be0b58099d9b6103acb0992cfbab35f7facac2d03be708677963334bda5d35ba712766b807fa6d5e1be8647527133743251d4da552df6b5e325ed5afd4fab62857e9c1bdade4191c9f206e3e1180693c88094b65e996d18d84cd5aa750514b977839b34117c22be6404001b0425b958b2a7702378974019b77980b5dd7c9beafdd00826ccefa6c63073163f3410a81d81350bb44b8e1c53113a730f6f0cad6198d24776559f6a43cfbd9dc2e96f7f6ca4c7abeb30145e3f761e2119d24bc5a7d908fda55401c9b182521b689ca88bb09dcdf53ade90824946832f578fa081382ef27f3630cd618a08bf1372d64279a3ecb66c25afa9250b1307d26affa14c9d1b1d609b8448be57c3732a942ec3b591122f652e1bb4c2ff5c2adea6bac494312de83667b70a2c85331ca52efeb2cc129e8794d6bb49c880925a88ad4990f4bec7f1650d519858acd7fa37b5de8619a2f25d6f91f6eeb259461584d1148cfa7079b7610eec69bf3932ba46bb46b44accae1f59f2670a2cc3f7fa37d4b41ef200c3a8deeedff4cca4d3db46c1bfc3cbea325be86a7422746b2867360a90dd97ea3644231fa4c00d9a3bbbdc4ba24b19a61f819f8cb6de45b947eaf405433f38973227d233f361fe63bafa6bcba6a0b06ad63ee3bba783fd28e703f63733ba709257b260ae14411bac020579c4357b3cb2f6d25989beba27547630b122fae5cc56078262f0bff3f1dd817b7ac7c720fb18e1ea657964f740a685ffa94b0137986cd2063dae3ed0fd62b9bb0348e43887f737e59c0d52b1d5a986cf6331df26814147bc6539198eaaf62b4297ba15287ff8596261b7d07052d8093e7359ed49037dc9137e13e88396e256a0bcadb2872f76d6df6afb96b944bc7dbb3e35d3f59b7cd6b9fcd124362dc1bc63c69674cb230d20bafc5afe0327b164d43857fbe2b5b9010e4603453cfc1edcfa5a06b46b0725d793ba587ed478615ef7f632fd66eeccd88f0dfcd40e6e5438e2eb7109fd384b6be80976a1b3b356bcb4fc493118a332bdca9950490110fc309c0f57dde823084e268e380f1764ec1e99cf2d3f6e8f55313f9c902cdb709184a41a3db8b273c6feedad0f0f76099be4f4c33180deefded35c7c2ee7e3f99e8599b09512e297121e9bda7e3b561e00b0749d08adf0512a04bfac9f12c1388dc3cb46f0850f0973fdbfbb180b4e2e94f19791150f395fb145b7c26335e9a9d9bfd761d2778e47674cd7b33f07b497d338bc63d93d10781f2703421db9c3ca2cea4c75ad72f6dd565c525785a9200645f67179e7a02c16ce28f0a02126f615d1c37917040fcf37ebdcee1c7e7826d667ab5537a2e0d2d848bc2e610ff5d71982ec0bba58967de3722ed9767bed2fa4b2c7b641ad67ab2909610b094cbf0d419ab462d42dbf896c93d2c2fa1090a0eda1fc331c69bd2b75aaa8250d69db0f3a93cd2cf8e5d3883fcb59291bdedb310dcf894a2c5a59ca6a8701eaf1e9e24340f896b89d338ae0d973227a60394546a1a62f79f611b60e64390eeb3b4f5d400153919435793e39d645ef454ba2675835903f210e025a7dff3b1fa45dfcc48c081f4e4e564975d9929de00842cca9ec3648390dd8bedf7f97f7b484ee94809da1c64d557406ba66baf5d541f9fa95892028bd6efaa98db9cb198e3b418939eb8ae2ff38133394679be81f60b5ceb2a58fac3ce2c8551d8304fadd061b5d58fc0fffd474b8726c32d1ef2f032abb79d7d15d27f7d633e781d2265183b0735655cd677d79e825ca7ee96594a7ad33538691b61f1ca8e8742cbf265c42c58dca7f3fc44ad606e037923ef5e0acd1e8f8385d4172dfc4c55bea38758dc1beef2ddec3a0dd17b9142c236f1a83a12d2ea0637079d3af9e6d0750ba8e466ef139e8fb1567a49d53442098e64e0e13138714ae87e9a20aba41fee6c1fb16c920c0846a918321f589e2bd69310ad08119849d601ffb7e8f9cd6bb12fb268f5eb2459893c4ade5beb1924b2adbdb8b69c3a9d32e8539c99caabdb47ba2ab10ae2a2b9e1d2b2250375eb55234432a9f3b96593e70742f03b08849837774e33b25fcd4fd5d31ab021e05de7b3c03827c75063537cc5935bd79aa1c909cce897f54aef44eda74827bc13b702ea8997da3b4a7a067989108773684a974623be84db8b4ebfb1b70430ddf641cd4f07176b568df3d467bd7f191a5ac62a75e39aa36d0b32e9aa6918768b7143716aa37f82210216e4ccc8a9bcd1585fa91e74429cb2b0e5ea5f264a9fce6c0416c3c399c6a2912a5f33125616a24a5b3cca3e7e16b263aee958576454aecfcde2e3d12be0e323796c21034dcf9418030dffa918ba760dd40e1e622c3c3482e6005133fe77ec9e493420035890afaa9f41481dd62f0594a08338b16b00676d97969553da34c3ece3dfb77a3d01fce877032a02821d68e25a6d2eaae847507928cd389787bf72f38f946fd0c5c982bbd2792fc0e22ea5dd4af789b76dbaf58ce0ccc169ccbf019d947bce6db8904a09facbdebfbf08c66fb746d03fc001608f08bcb83072dd76d03cbd5eb9de005abc3522bf67e053d27feb858baaaac3996be8c4a55342c0db76cd82a71dffbfbcbacca65b210fb8d2f42cda435ff3a8a606c80d113c0110377690f130ffe27578ed077e395312decdb8c36d7ec8635a914af0be84527a7793b8cd3381c850cb943b2dd3e267b26fcbb2f867c74cc27e621ea70084fd749bf624cc6f22e111681a8e88ccdcc3b710d5ca12f0a353d7bf1f6937fb9ba5b62468a2d4ce9cb0edf611cd5e92b1d1e96bf1e85b2f9c456bc2d215e6d650b209bbf21a2e78759fac1a82e0f84ce8f710282af4194d398b46328209fdba2b8c35089a7423943815157e74ae9e230a9ff3ef85d69572028b30b5382dc3ceb59c02b26a98f94b6a7af1caef21973f9e305b660c7717c480aef1f3fb69823b754838626a6ef8c4953508a6fc202dc72c121038c6bde66e3a5c5096d3a58028f4f99ebfa1df6a2840b022b8a194a6e33dacda0bbb914c96b9fe1743c8c907beb818fd7217d1959ef45207abe8634bbd58688188f4dc8f6583fa0ca4e3bd5d244b0b1d22d42dc34f38837e25d976647a05adcc567884f80222baf8612b69ca83353cc678e1dc3a6294ab51ce7bb53945cce4841d4f73cf951ea4a222a9b69803fc11c01b45c5420090324650d608114436737187828f5c48fd22d48e638a0dcb2af4d2b508cf2551b5812650f258369fcac35b3a18c2e641499b544d63cf7304464cc6eb33e4297c8afeb879d88bee7f103c0ade19f2b7a88977eb08b16b10d5d9816267cceb98aa9812c6708f8b820c9146461c8e0915a6461d616753482d676afb6fd1decbb802652516e01f3e3a6dd44ad69c7eee496307f77e11534c11e28121b4d06e6ed2ad7ba0726f918e5dcb62ae8305f1899b06546c0aafb861066da75dfb0d86bb2dd262e9a0c5ec62354dc1dc15ffefc252b7b5e4cce88b6e523062160a302d9a139aa06a688b38a1081c7b3a54348181b8a0b3c78d65d35a3e543db5aae06cf3ca2dbf8a94697d351f5f18320749aeae13e6d57e15cd980f1201bda0a3c54aae9bb247b0ea06c405c23f1e2bf8e97f31acb4a46f2cc9e374165e6c40bd88cfb4ce51be46340b14f938e4178dedbafaf2cb30a7039a01bb719294d1fdc0d103ebab34aeb3381f76f9cb758abfaf6429dab88266a2261c28eecdca74407347ef3c7a809e5fbfebf1edc11a002b069014cfbad369b59ac332d31029de6f9f939a8f826017b290178dbd63fd0038b9e6c2ba1a4b39a2bc9de208a3d996f40c5d0ccd0cfaa014754a5252f943124e920d3b8421115dd355533f76ce012435824c4edc6076c1ed342c4992cb17bed557ae8713144e5dae2c8c5103d9ca119cc90867a6c6fd02a596667966209f8d35d170af513e29c29d0bf121980b5be48fa83a5f1286b7eca463a0ebb6420306d7c8fcba25e6cb1207b829b61eaddd2578e98a3f07e7cb06526381a56b776cb22104f9b076535bd854fcdd197b07775dbe529f0e6f3261d8185db2b16b0802177c4c10992ece0299eb9fb55099615213c9ac22d431b0a3eb5c1bdb17a03decbf5169e97e349fe8df366958655e0395cf01beba9935a6b7c68763a3ddf15d533206242b66700e34319c226f5fb4346919ce521066635fc5f202feb20d45b25ef605437e5aca630f188591a147823ef67a982ecb42a322f6f534b4b1ae86823695b48e8c612ae5a01b597f9724b0676379c71b9436dd367159844c48c99b1602977dcffa8378dd10c281b4f9fe25f8d99fc3e11349f9e45fa55c901e656cb6eb82c7cc73c89c93869563f86edecb387f72f448ef83df74e8622346dc8ae1a919e0f94e9d397e4f2b1d68139ecb89717e7cc318d1ec772e331740372940e239b3387d1d20dd075926e1f8cc32cd47e9fd459618608daa59694c1d2bae9057ace113ba01a5bd1df8a0697cecd2ecedea2553d611456d5e3fb18a21ea1381284bcdf818c2d4dfa976c13e5a3c253164ba1d30eccc27947c263457b43bff1c3d5e9c6fff27544d9419b0e7fc81d4a392a10e643e0eaf0bed571a3e3ee71a687e2d7900d7face0fc42a96ecc886864a60e9207536a285d9971a8ac427b70d6dd4ff8a340801e92b23f09ad62812e42fb6d87aed3b4f500664b7ac73d8708033251ef792fa054eab98b5e52c83ec96597db84554b4dcb89b3b75a9d2b7dd1ac35bd0e9a316cda4960abf9e7641dd43d09bcfa8300b12679f039da9692dc584245c5e88edc22394f56358ee3dc9ad939dfa66cc0ba7b9021aa677d3c1a3ef665e1210fbfa67cdc6cf8ac6fd07852430c780c4d96cf09934150b4b50617f24667a632d6b526e94e12c6751f25fdc09bf561733f6dc4e79a2961a6148d12a2c2f7f39ffff7b3d408e15e243f6ca3626eb53a6f94be22922f7a8bb00e29a0dcf67757bcce0ff3e997490e3e230d2fb4159c5155f0106e95dd950d67246438fd5b76411dd3566d8663ca85278c9fe9423b4b44cad40d0f6f0f19853fd9d541705c655e27a273672718d62174be8d66794a229322b2fc9b9a3e6871aea0f560f283d4fd8eadef9768010c81aa3b6e3dd5ccb2ab121f778984060251481c3d0de06c35bda7781364b5c6ce144ca5bac5f42d9c2b0d6bf65fc8d097b2709e24aec670180d167387659cd4ab57b07feba530f71f61893b0194e5486903ccc934ca1139ec6a3032d40089b524da8a1c793228b3dd0cfa0f21bf45b826d3c10ff5f65d143353993851cc08d2bb0b4e1dfc1357ee557be45acf3586ba3180d1e4d0aa06b98d67b5f6b92e96c7ee6850f6eccf3b01193cdca072ae04b919b993ea6d6baa7 -MD = b5bcde1cc2926424b7d76aec3e6c33b793af22049a5fc8f8cb0a8546231c7cec - -Len = 36944 -Msg = 7eea1a63703cecd59f5dc1eadf5eb857e2bda5b1b6dcb4818fb24f9ac7c141aa23481b1058b9d6edce6dbb7ea39780a9f377b4d557d05dffab9bdf0a15fd1f574277e996f35d8fdcb989d3f5fc5007fb42b57327aeddf7e8c7c3f2327c2d621964df4c9e4a0e5ec9e817d3f8f371977658e0ab4fc6eccc636c924fba0439501710e80bd063b58adce481812e8fe27641bc6124f5a4e622992170c049b509327acefaf0d3483b5c3f342da540d88bec86f69ea6c052b142b26ec50b8798864f69267dc15001861c17608509d5d655436a8f01f958d73774d5dbf9f91eb496f10da1d947ee9480128ff1ef74969226c1170ef1e4663b5eff2af17452b311225e8ec6764a560b1085cc6ed5ad2a13e8b0b5fbd6319286102dda379fdef1b813df131ebc922f6d1dbff95f9e7d3b6181566bdf17a683c134440d36e0647db04fbcc43014e622c391063c4cb2ac6e85dbfc62411e0ce2f4b28dea74a0ae0201c03dca84e40fd71453a3bdbe79026d86dce9c2a9522a562572509a7b488226b44daa4da295d6f5684bdea53d5b47e06c6e67b29f1bca885e5bd545d33ea991d0dd4a7413900125c861fe1c4fc0426e4078bc5aace1b21fa657631102ecebec5d5a66685e3c580e3a7d4d497e10bcc009e131e3570cabc4064e432992b80fdf64ab46510b00a559c987115551b37d7ecf930e7529047d1f8426beb30b0cdf11ebb83256a246aead7a67936850114d4f9a759b37a932f0d72bc81ad8f34f212bfd69729fac753cb357051ba80492f4db736f20525ffccc95001c9fbfd4e99ed49fa64d55b1f417126749f040f49f39cb6169e4eed3cbd8000d0a979135421eb5db570da0372d0773b21c5c56a99ee5c76d4b30318e08ddc1597b48759fc26976b864f8a7c887d47e4164a513a9f9c0769efd4c461719a37fec55fb9499d146be3fb55793eb6a45da1b0b149e7e169281fc688053f668f2e3cf82f915abd77e357632718b293e243048f7f120af5f238f8f721481b45b929509e887215d3cd98467c490b8086c3727d11284c0c53a3b4960044ff7d85c4a3ca271f0e038681f531a51fa42125a4768bd4214a74711a15776077adeead2e480a3047a79c3c3184995c2f850cf711b9a1471ebfcbd4b1e60d961dd5d7225260b13886f1586b68c0fe200d20ac6197d66df864fe8b0507a0c92fcc09df9bcd982fae715db0aa7424d09f2d0997fbb337425698993a7887d05a8be6bc50601c5906008b5f4d6ff03aa107f3a2582bd066bee02e1242a5beef0239125fe225bb1db4ed39687732797ce019157d55889bef442399ec3c13197780c5c3870d432660bcb3002bd6785c662e30f70d2888523b62af60a9af5723e436a07ea42a4efadc9e0073fbe3c83580ebfe0cd449a1bfc5aad216bce4d86acf94579849d1af84cbd944096b1798814799ceeb65216b21387d4a20a8a52d5a943a59c4da8bfb60b8eefc34fbea7fbc34c8220732485b12ee6a6612ff48ac8fdc993578f8c1a91b4e4f978b20f4d462d2e7a5e4be36f82161e2b4622347fc56f3216929070b4f20d69bb4807c9f3d01ac88a9088b75a8c93d86b3a2a73b935c82637359a7d133fe0c33c199517220152c2bd9e70c7d0376dbc6f2390d9bf81d04ffd29f3dac1e2f39a84d5a51f60419cc318714c3c58eb6b713eeb9d8d180f4f527054e3b146410e979c627f0938f8c273a5ef633d7b1056a0e07896b84f490dda989fb42728c6fb618baa6bfe2f8e8a7b6b01fff3bf0ef6f05eb4c681e996d18d7ef2ac66f1d781a15993b126cf6bbd8372906686af4e130abf857411705d65132936159628de67ff0f0798a89ff82332c382e11dd03675950bd5e78f6c088f15a15135de56427622b4ed69ac279b833165c1b8e0ac2fe33a4a8b682463fe183bef2d5567026b76b3502c6d5cf0bda627603333f8caa227a1858f3ff8dfa7c82c1ab1bc59b4c12f59ecaee9de81c755bdbdc29a8db2f50771c4c9b432676b66912ac4b4dbf5ac68bd8e5a285a621f569b835534c6ed924c530d210ffb84b2bc11285083154b94eb87411871f91c2f7168bad34acc02dfbeee6a7f977abce490551b3c723041e17e5e0ad00be2365e70cd6a2624c7794624ebe2cb95d89a69ab040b70c9545cfbeaeaf36a3f3f381319719c350adedb2d47f17ded513ca3a9d5c700d3d0a8264af6d403cf5535abb836fd58e84439aefef0a944cd13cf610dd546034fcf5526376cc442e595ee16b48d18a42719017d20e5ba3e5323b85bfb75281bcb0d82e4281261b9954692016fe76b8adad35ecdfbefce7468c82019dc7b165130d358e986b2546fc8b248f4510b9d11e9b87728f7d58aecf24c2f2419b0b7ac6469ffbcba12446c641f3978c2c357413c1175157c6198b0daf50c0318dcb43450179ee52afbdab952d68d142ad54123bc257f1df259a0c8090ce03e43c7b4f1dc255eed4034be5d7b1f6b51f10a02be4f3ebec6c186493a66d8d25e013860ecf1da665b63879760c641fbb67f2a431bdea25a9b51b03c10d8a30beab9f9602c757fdfb7faba0ecb1a8667cb3cfdab40529a7a210b9e215249b3b36ad5d05bb9525cf08a6f96caa56134d418914ae337916e46e2551a9f06a052f166bc86f99c6eb9c25a29e374f682946c26e4db92088566e76598ea5e36c5c6ed67d6e3e3dcb3de7cb29069b3c765ee577c9e7661b914ca85323dd707e99f57d0f48baec181071247170cef301ff28abda228e4f85428e147d2aaa94228184fc29643b13a94549f4b13053f920611afc521e8edfee0a8f456cc4928b6fa17f4ead466b2f71b81cbaf2de31f8284aaa7978048581c667c4bdaa8811c0c67859071365c7aa02176df9cee0e58a8a2a5b85c47afeff9ed8c2efaefb94ceb7748697e448dd1dcab1b2239dcefb2ab67ea2b3cff85783e7dc0e5de285b81fc3349c73a87627e53c358deaf81ecf434dc61485e2f31bc921e00b7afdbce83e7a270f4cd86414bae70155925656ee8ea07f356eb5f1d839ed934ee95907a1a53cca6375ec993fe95bb3addc40ede5476f2869f0a17b09509b544d0b7d0c70ee8bad1d715d9c160afaaafb0b306a2017fa50369e4e052b97cbb18a63e221d264f73da1d1b3d3139a5485c1a1bd524b7ae2653fda1416bb99ff298b7510fe42b30ffaa51987d4d511e9a29652401ca3dab7f5ca368c3635b1962ad4d191e84e6326728bbb3227c6fc3aaffd7f514fe5d1db808a261eca36893133daebed7651cfeb23ba295b3255d3c7fc4bab79627ddacd73e44b54791a7b40e312367c2ef983ce8cd5066b8b2e130216254910dac8601e6e6cf8c5996e2255a72f43c688b219312c50b4dba8ac44899bfeeac03f720c4ece78c0dac1bdf8dffe76966509f7eab370a1c724015cd2beec5cf30ff6f739df22bc361c78667950677ca0d0295782d5f86cbfed2bbc681285a41448a7c4632ff99bcaf324042e5760c5e5807d3d7c192205f19f8e475f450688a102b86632e1b19be2076b23824578d6e70e6c3630ed9c022ea3bf8a42a6cd6f3bd6af590374e9312dc1a4311fab1e1427d27cbe3bd3b4e5a9a225f19cb878cc473cf3296f5a1ef010aa65a94118df222a653552175c1b3505036819d80a6724559e3a33d121b15d1d3a2618b0ef2a75613f1c8e3df72d54c35fdc7f7f1d370be982db14c33c5eeca5e97bfbc9ce9e825ed898cf2a3569d95710197f1c5156e765735c48d02a56036d40ddcef61799dd95ca309166875f3752bca5a51a47554b6bf8445c627c6545b5c8a20ee05aaaeb887c8a716d6d8c0328cde79e038f90ac6f8a19ac04a2db3831f98f3803184040b977fcebc9686ea15bbc75a6626ab78ee29142d4312e463f444bebd6c8d108519b351e6ce50875b66e00d67ab199387767b66651727f24ef6f485e67bc0551a2c04c55715abe4f96d25360776b7b81da5151ea903325f5ad35773d675735bac8ab263895950a4ae72b0cca190a82223c41fc463d0db3371d19412f5224d2b217ce4b3e462e7cf61bca9579fc295d9821bc3e1fa46c9777a3ad4eaac49f7cc634ac23ed1f7176efa94395d68d226e620f227fcd62da5335d543e8161b41846583c758bb6e288876042886864880250e791739d5f4d166d0268fb617d2959a2ea9a2522fce9e3257d0ebdfffbaed21fbe3fd04cfd6ec52f51bd3212697162e700abf98c0cd5d04d383f00ab950a3d5b8c46669218575980329d0c1a8c54da1d81b81a504c6df609791f7bf29a66ec0d3bec5cf618d17b698d4eb1034d99694d5709b0f6267bfe6028f4535f7288863db27ada0165a4d3f04a194855160ab87e69e6e20701c58f5b2e07b3778538b4f1d9370a39679808205146f9964e6d6fb89f97d80a4515520071a0c1c43c401e33986d12288674c3fe8a1dee505c8b3603e163bb875931ef59da07a5cdfd676b0ad7621a562b02ab94dde64c0aaa2cb3681794b306a7e10d6e5183881a3174447f7e604b4abc0869e933e83e4d9f1791ee2970e71096ef5445bf5d92344130509875adcc8ca34fa405726ceaa0a316769eff40802c8e216ee80adeeaa29363385fa491c6a4469f05f184ba788b1eef0b7e824ba5e3f741005f1c4bb9ec91d4a3dcf456611b0fc034b44f1a1196786bf79998db7fbc3a15b5b0dbef269ba24d3a164b42c4776579d856bdd4dd4a1a52e2f42a36363fbd6632e531115a362d94a515939f1843af9399e0b52f032e6a6c769921a5f1f4e9fb220605f87c459c738be1b2b3840457d721591e74abcbd181588f6370d864269e2b193eedb55056af948392c73144c40a15c9e2ecffa7b85833dedadf1416dd15f528c6382de0c31369021922478a5ef72038e8dc244c85baad8f6c3acd927429293a84210b7c4b66b266310eed5f8d65e8af188f4542a26f6ea803c82a6155a26f5860f078ad566f16b7c1d14b4ab91b15355a4c880f753f1f3486d2540ae6486e8942ec9bfa4cf73efeb0b48ad34ae250d3965a153d68f26838dda0731591e3cfd5125e9deb95c6d243e8ffd282a8824190b4021554e14ff0bef07aae0bbd3a3944b88ea50899a4798c50fa4ae03bc38f749c8cb0da4a1f60cda7a82d73d11655df1dc4dcdac159dbe3d0ed1b746c6de28737400d590a2a5f6eea7119d5373fcbad274869e873aca14f501f6cc6a147e4d26b655558893896a8a11f9ab9567d42b6bf6175ba186773d9b8d9665f431a3b5c2145af602f11ad83b4f8d7a896986303ce5928d91950f887f06331c6bbae8f2d422644f8647c4b070b45f92a5f57d59b3a76a9ccdc30d963e105f48370cb894eb4513ca89043183d8e4d27c519834087ed01211bcbcebe757107d81fc939d0c6610ebef81b2cbe2c265a8a032ce44ecdcd41b74f4df44dc489b0042130bf0d9d2fa5f2716d00e2dcb9b24a6b0142a577c48094efc96831581249a0110c27e8dc085d019aee862f56309e8e85fe65ed8cb904df83a9f31039f21ad678c437088ad37f13fb07884aa174667eda8c15cf159317c194545d9370136bccddc2b816af78534f1d1eccdec56c5243f11419f2193cff62a9326e61035b84aac86d71b954de21de879d1c91cbffaa0552fc3a00a09b04e94aabee23fdb4ac99c12d2c9a7fef31e8c1ea3e0bba17b5eb86ad409eb398707fff27a48063052dc1516aaf613b92ca94546ffaf59a9bbc1e1490f376581b894b510e59213f364d49ff8cc3b58daf360ac7921af7747207c6840c1a30990c9976c7c8d5ad982e555954fb303e7f2fbb73a2bd64b84f86de095f887f747e53e627eabde0cd77d78d1bd720bea518f8a2f76e57a2e133be89122c6ee8e80ed9b98740564229e3183cb51061359260f333bdb2c89a1928024f0773251e37518459be53f9c268e4d9ab4f87275cac6008b5eef6771509373a7a11bd15e9074f3d10f3ab0f2a3282022312c5dbfc9c1f2072b1c3ceda59674e505790a6100111ed244ece014031c67cea2551e3dd09a521b02f9f34b3b0c1271a0277405dcc9e7adef84635cd0ab72d48b1b3a9c79cfbf5b88f151166b64bab1f39f74b9610fece86199b1598685efe87de749382fd2882d2faaacebc140fc3a9259a2f84773acf64d853086bf1c1d7eed31b0bd5d334b24598e8d17d721558feede754efa75967bf5ef8750c4deaa1c4b930788ac7286b5b9056837177635067bb66239f48637de1d311c64425e14252b73b4267800b975a0b7c4c5fcc03952cb4a0025b0361f8105e2762db21aca4e0f6c5d035a7e51d8b30e3951119fd0d95021c5aec805ac29527c1b199e855adb59e558cbbe3bfe5362812c44d0557a2eacd62941b6656c2b857671b4623e4471bd674ddc3dda0d7a31a9143dc381b3b723cfb16ae5d5de0c016a208a9795f5958c6a92b133c90db192fe978865b51bf76786e4a6d0f7804f78bf8e08b93d0cbb5977cdf75a997d9e28fa1cd1216ff183ea943972221ae16a3dff30bb4183e857a71755faeccbeb9446141a84a102f2d12f50364933e08fe0d391bf1 -MD = 04d080afc2b26faf57e3b91ba0202f187ea08b64e7ac3560b9af97db98fed4d9 - -Len = 37736 -Msg = a67ec4b7fd790a754c35248931604c4d7044fd62f3b213480f382e2b099a5700d980e6d12d6da255b1f02bc48e1e95e9303f56794dc862a3238a94e80128502d08ce670f33203a769571236de236103131ba7187001355537954cf67f4049f99bccf0e18167c1a007f1fd32b3690054bfa1b17351579338099ffa84fea168c6b7ceba595de688a1af86205a79114bc5f14cc102b93e446510cf4e449eb465eccd18af22d94cbd1ec87a27f89fbaa7c9605332410823bd4ef599a4efc007c5fe34214bf893f8f389fb4470a787c3a8f1757ba1b8deb6626820858ad1130a0d5d957f1d250e79b075b07b96e1c1dac3b0b91c8bc49d54c8431a298c82f849a09d5988af32b94d786470961731ee5e8c99a3cc4d0ed48d73524aec168ff025243008e45ecc24f2bfc8c41a5e126ddd681ebdf181f204cee8384b43b5528b4b1cb81c08b84bc1f7fb35137ee7fdb0b5faa27022b718bea79b4793c6d5753a29de881b6c582c20dbbf1bf74a516e679698d752e658ed52961112acfc13628d3ffe328f959af7b20c7fffe7f306eee2fdd73fee92e3ea7128ce2c0f49eb94e4fc0049d10b1d390608b2535e0f94f9c33a4a2eabeee48a9abe36f62346caa6e1ec693098333b6a8d5f0aa8d206681988fa46360320d7582fe4eff391694cf2f49fbd893db491f6c88dcd82dc6e1cb894bc7fd88cff38ddb13b6dc6d227cf03ad6461b649f5ad7838038f53d5ad1f7186df4ba8b1c09585bf0014c25e08dd736d08ea3a357cda797c5ed4ae7659ecbecff13e091a1b59dab9f199889d92f4bcc3cbdb9798c0c554d60e21f516eaf10ae080bb8c1e760267228e408c294cb13a424baa50ec47ea94f58febca3fd6e8d0591c68a447573b959914ce3f899c7f8658f6daf898a8b6d45b52b68069a420c9aa12b9e42d3541f08e4387352718dc2b886be1f13639b67d680506ca2ce93531440223be28a6d2026298ffef9a383394410953cd3d91660abc054109e20ca2c1c7693aa4c2125835b663bcd15b71324b235da4ff27365216c7d219c22194d5d5a4c6634a920e31251a52328cd36a44da9fd75a097baee6fc0bf9e58583f85ae75c9831f21101193aded2f5649a79d7ad2714e77eb341a154f8fb38c661ddae916f6d3b3db7816cf1a4747a1b2926874d5984e1c166b51d9c2f4487f7438b5d4e4d93c3a00e05a8e3eb9534f307f6c03597b5bd63fe7fc85c1f7457aab1a7c39887da7fab7d04597c14e3ba9eaf711ee06205eef8e2e81dff39f92c5324a99dea9e7fd3c29d13fb44c0be7f70981bfff859140ad2cca4ab001f418a83250728bf02124487d6ab0ab87fa4081b4a6defc7ed6e7594143bdbf92febd6bd3b5710a04320666dc24004519222c8e14edd6ae98f53d3af41f44d64fc66a553c00fc228f228ade6e86974aab8b946851de10dd7cf8299a6ee846bbe05308af96b97d9a36f997f75a18dd82e43e61559201f251d2e692bfd7252b37ecad7dc108685b3ba3c017fbc9623bb56d42799effdfe5d141c862f2565f5a121bddb3d3bb96fecd7e7ff130e2ed17aaed9fc68bc1ff522771a5807b131d3d1417ea902dd7cace186e3c0ddfce40da2a0d5e2f6300e99f190b85d4a237e73b0585dcfe17838d33e31c01534fb4e3edfd75869b70e3263670b77146afea45bcac10bce4d8e76695f830d5abcabd5fb6ebcc1ff4f8933d7df31c6fbee953c028d25e9129b92cdd5c1d51c1fd96113b9fbcba32214438b6de6ce38a249a9bdfe83f1763b7027a7af01b27cb31fcd7ff0f37e9c50a9cf91abfa1b3c76008e92b62bbe43a75fbf8c6b9b95bfe2f4438346e25fee39747fef08a5c35305a7b662bff0e6d1f4bebcf4820c1955fdfb65b61234ea491b08f70c0a66311ccfb3d3a6727ff5919211c26888bf97cf8299a690e987a81d93dba77137b7eeea329958c6743585031dfd4260f632bb9d0f63789c334713dc226113a6f717774becdca84b4b9dffc6e6e5cf764111df4ef2cd6e4095ffa815453dce25ff0154c24d0254cd5f35d02d8b4fcc010fb98d45eb5bfa16781dff598ac639668601f1edd18ee095257990d779afbaa998b630124773ae96602e640951aed7f14295e91f28f6de6b44f5dc35408a3dc89284824495c8fe48c4bd80a5483c4c4eab39a4e6a1ce90981426fcc76e73a7e67390de5d64b05b964c27cfddbd12e8f72679afd4da6ac9a449898d1e51d09babc287bebd22be59173d09cbf34ea740535ab2845a417fcc282b8a07aaa9458b60f5c5adf45e6779343ddfef867b8de50bae80ace765622a8c50c4f6ecc326f9ae83d7268376303e85b526b517a21b39889870941cb4b667694fb6d5653e1958fcf338a2fb18ad1b74395ab71770f3d042beeed46abde0f5178edc1d9488813bd4da66cdbba432929841086026569c2bd27877e841ff76763f84a14a0b20f314be9fede155b765266a52ac4a94d178beb05b984a42e7eb4d49c7b2e52995d37612ca3a9859b0b95952e4a2c103600e0b44eebc64de15b3fccece6d798055c6d299dfe95d282ea3adea7da88df280e084389870d283f76507271f4d71afff31bc8c47569a518fc896a99419ebe2c284dbe3ef421dd50b72eeeb20df57f8e0a88692971efa56627c9618ce736534836f54ef69aca131c072369379afa70bb8afd32555bed7b735444eb06341a498621491a37e1d072ac4c750b8901af948d59c24bcf992cce476c402e91901146eecf914b8c31faa407706dfb2facd9940c601fdd1f957447eb550655b463e2f2872915087af2114e35595362b101431740875c10ceb58c8e66f9de86f81556f759171c7a8b8cde1b3ff16f67986ab4c632b7c00b63633e4ac03e0fe9e30e35fa6c82f0c8466726b02c1e08336b4ef349e9d694f766065023020ee3a8ffb647a6c950d71b33ebb4b804ca68edb215c9476dcd20fb5f058bc33350a0e8d47653a0776b1a9bdb814fd9cfdcd5bef626fe68c785ac40d7cab7cf5bec8fd4e8b423937eb9016fc58fbebb963c98cebdeb5a55fee580ee56bc9cf282c9f891c6d97d25e724d3c0797fca0761d2f94492cba5b61ad4e42c624301d2b1d1234af34e2afeb993dab580b73b6536863f48fa2ea632243c1f2285c7b017f0eb5725f87af2c7fced5c7761a1d97c1f40b4047f7c267223047af946b06f6a45ffde4a5ec49c28b81ca22da4a36bf523e89e9da81eed1e1f143dd92d670773baf6fee2ad96f2c8f607f400d227bb774a66463efd7ac3dd2054b0e9c35240d956b600156b57ba50be96991872948fab9da2f40d07f970572fac1a528fdae14421282c0a226ebd6716b1db9c0c52b0392384f0324d03bb355304c53b1a67b45e2434c9ea5945c3b6084000b529c9e6c8e5f581d658016d1f9544f7cdea627fcc66c321dc994394e59b2b518a5061f800e9dbf021ae594ebcfb54f93089310b39efbb7a0969d0f79bd75a16440982b08b3920863ad97526b5901c138b7f3e204bc8061d995154b580c5b6970adc94d40eddaa884a61bbbdb159848c0652f085aaf88a52b3d937963d6c251b0552ff2d34db634178cc95db596075aecb8cae04ff8731607f8ae2627ad590ec5cf22b83a23d31f8eda46a4755acd5bfffb4e263f27ee19126ebbbe1de06e0503844809e030bfef4d070a2ca4c458e08cd53f36b2ae4842bd0852bdb1209fb90c1d16745fd4bb17e4ab9a52ce73486d15bf049e450c10177a4de9b17bee6cbf41e204642380732de8306da35cd80a762d1134c960b1e40bdcb80715e89a337c378ba865b5d46695ca2dfabaca631d70258456449040229456df317781b4a2647f625905914113e40d0cc7f5b1c5000fa180cf9c4e375a456b0bdf32d1de282c6c1ebcb03046f99d13456bf08d5e3099338f373d04f7f9939bf686f453774328900939e23d6686258f704d17c79f5da12e07f3a35f029f037c07cf18710071ed8dca6737f3204811d405f1e7fb18b5bc23a3ab6bb6f7a9196dc7fe3bc51a32efb7dabb1e1be4cde6838ee0ed925af74ea6bab4f29747b649e3afbacaca1504a390a2abf0f2547618106390a517c680dd19e5a6e49a63252990377b41fa9175adbacac07d10dfdf3afd4c878b05ebf0ec0f9d079e1aea941cd5e7c63dd11ff46298ab8f0f11f777a3cc724c1be75ba5fffa494daba33e81a83749121ad8011f66bcdd6e23502bcdf6e09d44e436664e8d6c82ef79cdef5c6036c3e56599e5452e99c8e45675ed40b8ec2608607dcc2928d8d273a4f57da2c956f0b6aa714d043eb2069824dddc8e5e31951d0d17dde436b1a060a9a459f3381a581c5608a8dafb880eeffb0259f54b7372d966bf1bfe4b99853ce46514ac50e3527cf4ca7948099e5a62557de614250447f3f9be16d5ec02e97f01b22e5c9864885f13214ec9cd677175c0cb11796f767cc332af5f197c50558d7e16177262f052491db799dedb75dcb0d9545c838f4c89ed9e0d45279134421eb60b509c652958b19107cb05983c04a9ebb447c0f8f907c9b842798ebf114779460c7a290361f42ef97c82cca84c71a7946533b0510e7efe0e095cbd4a69de43aa83e4a6c25ccd27d38031927009bc504fe1c0e01bef47e11bac7f41e7b06ef4501c3094265c4c229bdd67f584063d3a9ab47fcece3e0b194db641bb0b878211d33fee8fa3f2e9a5dece867448c48cacf147c0eacc5d210d20b154672a51a002a0696ee7dfb32e3808fe2d8d52c7234dd02624b2aacf3243311827f4c891516d5423424b1e1fa24fa6c6bdbf26708983d3da1bb4ee26b7420b752cd26ae90eb84ae7f907f39abe5324c2c778386337f568de26601ae6188ffc32e39e85ab405a013203ccf4a70af92f6ccb471d11a7090bacd552957fde939febdc97ad6a9ee9239be308a5d6f088134f49aa290e6f3538b098faf26691e3730a887c46a962ec1e8027396bad07b67cc4c32ff0bbe9007c93f1c7c63caaf6021967baf5da34b94e8930cdda9bc8dad877b83708acbd0143c160577564b251b9830ac21f9facf75001b0646725bc8b92d2a95de54343ae3ac375187461107d25f1e220384c042cbfa3f66b85cd4b3f48600712fb22257dae14908967d47ddec3c07e53e47202afd9ca9361db050d6c659a61e4decbdad62a2f5338b411330d1f893feb88a401175af017e5cb7f6ba9870c3a41e4a2cc6e4b9e3d84ddb9d86e85b6b745b95487e9afaee445db6efe6d091000c8c13982ac6ecba02c6930e6a9b2c374f0eaf61fad447199208f862e2d885055d7e91285f720422b6ddb08e6151359e97b821b30c8b5c2a6f45c478371614799fdb0a05ef4ec9c5fe7a7c44f5733c49554334653c2702c8e4fc61586cf40505db8dc75662c40248e1853d59ad670ae091962d9f1210019bf715182c09d82250187b10443e3a795668e73cf51196670a5199578b17af214cb2783119972c31035e8d2df70d1af4959986c13eaa681a6f9f34f94ed26a2a831d0df4499d57fbc5b5ab659656cb3cad7e4b135fff46edb8824f5a13cbaae3e73fbda8e4a3c1483f26bd014aa2b519471f1e7c7e9996a68d03d2c3008bd81521206e971131d2e018b8ab493a7840520b82e842c4fec10e9528a57c3d995a88d9c80907f9d0f28af9745d858f60d4b1a0b18fae58b830ed79fbb1cdf37d9a04b6407741c40789108a60bcfd70e2d9fcafb4fd08624f4a0be184dcfe4ac0fe51608f9e8d995fff387287aef90687b7fcdf9118980c49762f73ca0f5669e9f03680bd6832a05fbccb5aee1cc078d6d679d952caa57c301e23dad5331e7980d77dbed3bc7a038f2890e99fef9bef589f3b44fffa79da8ba9adbcad2e9fa10e1becc1d881abe777ac51c8a10dd293937809c99e905a4fe37f96c25bea1e0a1a234c32d4a10e76a0aed49efc60ad8b11caac1039739103bf08a593e64de6db2c5964b8cf03ebd89198e214b8cf73005afeedc0d78d661da7aba4d856413e3dcc24fefcd28f8a35d2d043d2de416e19f47a928181c520c523d35938b3ad6d5883ece0a5e42d32b4ecc0bf7f76a0e4ff69a863fd3e030925bce58e5c0678bc53d81ad35c0ec52d7d66ce1ec386d31ed941ef2ad9162f6762f94a09eb578c735754149fc9573fc1b9c864274818c264d002b6adc0113283a7636a938eacd0da8b7d430c93c78337909be9a3b33355fe0c3667b55838f2a51a80adf3ed0f2c3818de0fe263667ad72965c55bafe07433b464690a49925815e3db7cf3af8788d725fce1e8e03d0ae8adb15f14e226074cf11524743c274c1a2bf93d597c1cccfddb611fe7b3531cb443042199f40df691ead000bbd900b7fd1a645aeefed7e1f3629433a883b0998114e872b18e9d294ac81d65a6c7247f07d7a3397adabfad01e11d83f0f95d679848e4ba2358df88bfb284bbffaf9b8e7d8b3e44c5bbdd196e8085798abd617041068162b8f9dafc38d18e6a8c386ecaaa5dbde19647370d8469527b3d76c49ac37645d0381a966bfc4cc2da160ba41dd576a97ab626d87289c10ff3d0cc8fcf68c1ba6d6b621cbf544ca97364cf456e45fd8a76ee01c52ec6b341480c69c9f6760f68a1187a73de88f9c99e402d5aa4431be63d0480072b836472e2b9f27af73687d6d50909a3b2e07aadc170cdeaa917f84737c04aa74f08ff29299f12aa -MD = df8b6db68dd4dfebdd1a7b8faa80b3835d561119200da32210e5d4bc7a8a4bb2 - -Len = 38528 -Msg = 84a4e5f24fdeb35dd247d807c7ca6c39a70952d9103abedd6a34f505cac954ca165794926b9a4c25bbc4b764bbd0b839fc131bca57141ef28f9d30f13212f862c002996e0ffc3540eea4b0b80905b6640d29ffac0ce7d14c22fdc708595fd29acace7df005ab7594b30e486c7a136da3217485e7f55de0d56b7b43b10657e85b7be2c77e1450140b522a09e6d69fe5df811c35e3db1c5273b1402b5603a2448b1d67ff8203931b8c12217a8fe55427fe7648970885cc2f103e74075e16e9ee14f684ae639b1b91fe3d1b23cf6ed73aea462034bfbd168093583d603108d4ecdc4f625b89a4917e4b193f8d0f3bd3268939cd936e49a24ce448c6bc37a00a48cd6f288e5ce69cea5aefb63fb512eef4c599773c7ff2179beb5635a6d8a8340acea0ffcf4428e5de1306a8c12bbcd0ab84ac45b858801d7590c9b3a37ce6f938c6280fa7a93414615ea83c9cd7012253b0bc608e63bb5ee3bbeb673d8b2402dc9f507f9df3d0d07c231b9a5723a88cf5300ff046066b7fec54027afb6d28f6fd4060783a8ac5c1364aa8eb7a767bb597eced1c69ab572b99435713658aba7ea491a02104d6da9097bb97578e37404644cca00c7eb94808f170325b044aa442d87a57a38540d9e5a75f30051ad0c0e601b86fe90d9806befcc3da7a5f16ade9a1e3cf25452e88676f1cbb1ea6a8c33ed898a1db9eaf59f6c2259997ff549c1c07b44ed0cb09b1bff6db7fc9ba2711f6d0547f09ba6809584c7cb5da6a6e3a8213d51dcb9f3a1a954485c52fdfb571b5f1d4519ce82add8ba1b2776c2aca4fc4cc2e843f49278c906200d5779cbaac2344015fbbb15e9e38c9ad2775c7d2a3893ba8ca54513ace585736f7ca7a9e8ae9d0c1f08f9c6a1406cd570d1cc7ecfd7a6629393140daaa962b0d735000c9d3af9efd4d4031b7079eb496718ab482263e579a17ff9e6ee6f2e76f9030b6a44f1cb49ebff5f8ad3fa786549ae715fbe77e16e4ade5f1604b13924397932495c6d91c8a8cd67ab483ca4b78d15a73bf06e2a9ed430cc317a1a23471d0a0d305ff8edeabfc0c3e359daf0cea5e0b55364b111a9f219c9bfbb046d6e083804a5dc3e200e759bfcc9653fdd192892343c880b471e18ebc02743fa87e7af85a1103da7d8c28e916ad416e5ca0589acac5dd6b72b49ad4947fea186f37267757b1610c088955f63a689cb6768324d82764ddd6f4edb4394d9ac5014406cc479fb1dd212b0056c6538511f2f081de8c63a73087e22316060fdb6dc3cff555b15999e1e08df813a1888d07ec75a26efea5173e46e35fa88201cb4b26b70ba7fdaef2d412d77973d10107e66aabefbc76163a6fdd9fa852f74cf1c5f1a550ab73c5421e7fb08c619de77b15353a6fb03cde9b2c12bf06fcab17d544ee40cd495ac71427efc137c24c6271fe15cb2b339724bfdbafeb818ee78b0031e331896afcdbed562ab2847f27997208d106292bd11030e67aca22f0f3d0f9f2991f8cf49f2a5715f72a7b8076b5059b3392738230cc75b33c05f00b170d48f1d8b3dfd18cdbd9cc20d123ad81ddb31f0118111efd7d16acbc43f3c59b6b7694679589e70b17fce16b5084ee8f3a03fc043f09e97f4e9b37c42d3407c6110a45106c9220630646bda14fa62ce9f47d9b04b065c900658dbe1a6bbabae2278c6b99e00362decf41c88a75924dd832a962c9122da8c6ea74a887a48ec435d7856dcb9be397c29b756aed6b4f3ba21c10ba1a0e676d1a06d65dd380b60f08477cb56e423aa65891690c93d9e5dc8fdb390cc04c1d0044e03d45c6a93c81a29ff9aa4a801177e8daa51445655d1ae997acbe847356498ca230c828c427044d0884b426fa6ff2ba9db1ecc9babedcf677f23a2c2b1b2f3a71384ec07c807f4faaa63bcc5b5cff150316fae77e100900a492e6801e739d9578dc3f57764ed9f1ace6a70249e08643345ba8695a5b8b4d46142c4af26678e6dca403b55d99fc7b36cd61916c046f8a57085d15f5a84925840173504ffca975c81802a2d76acf3572e2cf416ecfa23394a580b5f8fe2bd286e0225bde3e188a62c1a4e68cc83a6686ad5ad9f44a078514bb7b0f0a66199b7539a3334633ad6dd226524826bb25589ab66a23a97b87caffd1b5ecd4e7fbc779955da030e3516541cf72924a4b7851d78668e5326c08487d709613fd89b99fb97ab86a4457eabcd7456e8aa2811b9a64a4bae83a257349b41f864e2e543c6b5e731c58299661b8bb0facf9d664f77b6a98caf467acb113cf66ed630f516a738f05f13488a89fa216b596a68efcf23b11ebffd1610ba9eef4cd331b47872cfe75ba9fc408968bc20fc0925b7152f5248024c046d14a42244cddc03e7fff6b5537198ed152670c5fcfb70ade276de97ce0cb771c5f6f66fcfe1dfd945ebf0dc1ffaa27220d230cc27d2265f85956b48c58688b1bb284fcbd321650e48dd1fb88f2f6d081e2d37234428a0b71af13409c1184640b7390ebb0124e22f8b33c1ef23a84f2b4797e26fb46756411d0ae73f433a66ab4499c1d1dc34fdc9679095d49ffdcf684792c0f5fb06ed8a0652e37dbe55705deddaf794c70a1e487873f9fd3688742b98be517aaa8facfe5159c739b4f1e9d50d7d1e7843fcaa49384e6ceda9e0c401b56b2252258a3b1a989ff0f7a9a839ad3de0a4f0e585482811907d1a4c9f35771839a2211e6f0e6b4685ff2c1ee0e642f9a639932e4c7e81beda990790fc5ee85b9a6f4bd7a69d6ce5bc506b77248632cb4e3ae380ba93d27a9d4f3a39b096f1da1dd846f3d97e9bf0a3732a64fb8ff91d4937468f484e96ef490e26993474102e247ba6e5601884e1cc05ed4ace7a128a179d40ac8df54b877e645122008ccfc25ec7e04ee3019453a65728ab25bafb7c49fb665ae43e6cdd9dd04e769d278d312d5b9772daa066a0b305710899e9307e40d03c2cf370774c37e07309730ad4e500951103af9b5863828f3ae5838b3e0aacaa16953431f77ddd03635d1a7d336889030173ea4906068552fac47af790abede7aa261ef969ccedb7a3d40c1525361733cd46034fdc244c0f451808d4c4cc75175b521c4d4ac3fa7b9910b05926d84b95f8ec9306672737028e72859936f6e2b79e9bc49416ed73ddd7a5cfbfc4c986a808fa02032399e6db4b46a9cb83c5a7570885a0745ac3fa4cc3e582cf6b7468f871d0e8dc9df6dc081016cdd2278333741d82284492c1ee47025291fe978362e5b813bfe932c8770761556a439eea377d4223d4ab3b71d06af79f75c3e550f52e6034efbf8e895857a3a517a6565503f11add3e1ed15e4107380e96c5b177a000fea700c60da3e0877b685e50ea4e296e0c30bcf5d0e1a0da38428d6aa861e42be80c8ba33cb2b0054d2196f9c74028529aa0d9e6d6a670227cbdb229169a41fdb0b7f8cd9830475f9d635a0779d5812d4ab02d584f075f9e79d2bd97a89b3a04fd4bc0bbaca70704e0a03ff07e78b48c90e12fd0969e9f9ca444082ccaff4cb0023a8bd3e6817f73ab5a814b51a442cf01b649d669e6e0bba0741a5efa10eaad7406b2cce24a215a8214f67e7fd2ac8311a213d0254aa369f2d57cb4b28aa45bc722ce0d0c7b9cf7d941e810659e62375527066455645825fffa97b480b70a298021360ae19032fa2573de97bf61f45a20c7a9e976be8f7e3c5603d4e1407cb51384934cee2293cffb2d527ad9c7e37a2906670605a3b9e13c7a399c50918c8d15cf6e49aead2fe7cec0ec40313aa005b265d6108ece57ed74c9b1815b34a9ffeb641f878f9a77e024f0f47e7224ca8b71687fbf7e98f9f189e6f41a6da465ac28e53f9d2d650c377210138c0930c389da70bc59619e00abc03489ce046b401042b546f0f4a74d5c5ab0b20f52c91b7f42212474b4381c6adc44eb22cbe3a9aacd66be0971dbbbdd2355685f0b6842da6cfc30a7f3119dbd128a80af00b832fa1d7c0d6d217cf8288070af218f88ca29af647959ba9515212797f2d95f535c7cd767cd828ff552ccd684eecd5bc521fb8dfc5700574d13257fdfaa18444f96b17fbc76f019ff8c48ba24afd8fc87eabe8d26624275a408387fe42f024c0762267adc821c5bd5e51a9fb27acaee5b74f121652386822464e8cc27ea1dc3155f4a5d5a879dc222fdb0fbc0d819adba5121ef4b0342f968c9a4d92d73d165e3de9b9bb8efcae96146ba52c2305bc72f1fcf4b4a8a1e67cba6fb2b5754b3910d70a8ca7a334a3e1b407539592bf7a7243157d9e6406f49d78d5a3757f53ad0fcb5e04e10fa824cab9ba013d81383da242669ff909ebc1c16cd508181eded923c0ed0ab0f9e0971ac889976d19f66ecb97f6430fc2d8b5af4176c9e7797327145ec0875e896566998c7efd6d828373b5eacd5226b55638319dc1cf2ab99afea94ede6131e9bef70faaa01b85e367b628e2f4b2870aecb20d29bc002905dbc6ab384f82723e73b444cdf7d9fd64289dec27724d7aea238b0c8c71452b86bfe8e3c31cd068b30d04009b8c201c2f5092c8624f09467d822bf66ee8877a63cdca16984c355d6d134e0abc66d62c6967fc863b94d035ea91fa937928ac5cc58ed50f5fe79897970dfc2bd98de5733df343ec5948898d5ad861ab53399d1ad4887195bff6e05f5783752b9a0a333ad17ecec365731c97f4e0c605a42343fbb745076f6080f7fdd5fe21d2a6e4aac84d8f07d2061d709be130926a15ee8549974dfd66eb8dc4b93b0668e7a6233167daaf55e3e54f6fe148502ea24da34a4a9b26bd4208262fdbae21b23441d0af5da06420bca91100b052c90075f54a7c48ec5aadcb5e5120aa58d9677f20f20ef3c639d126fb690b52262272abb5e90289b17137c896187f6f61b5ef91ea91357174b3cee98361790deee3eb0b348ac45613f1c20357833473f13db23248b50c1fd45c80cde800302acf95d35e1b34aaf63a64b5424a9928fb2efa1929e2677b440bbb4f9ad34e19f0f3bf916c11f09cb34d517a4e1762415243738a405fae6a2a4458a417eb541ca982e98ffdbfc582d3754178ef65e668bf56306e3d6893c117a5bce50dd919229ba39b34d9cdbb449fd9bb17ecdc2e868990ba2ee9a41d6854566e7c4544a511107f5ee8c7e2daca5fa247bf0f254181f91898300cbc54472980f6cf84d501d34e3eb91391a62bfc5bf76dd81ee82743571752de6e574047dd4bdd489534344e9d07351dfdc3b5c3da01b6cae2cce9b2ebb4719fd61eea4ebadeaa4d3f08466c4702586fd4de800526e7a9fe237a8eb8fc187cda0eb859450662e54849f940139359ad6fdda295ac85d2cfdaa99a1e3cd36afbf9dccf95150afe17a07cb1292dc831b986e2b4fb9e40eaaec73bd3a225b9d377630908a7a40edbc7bda0d509a12fb5061ca9bfbac59e56d02ea3cd205df47b77805d0d96dc5a207d077d10e957100a1b9afc69db07e93fbd75a731a3cbcc8983b89f866aa435f6c1e6da07d037b35b8066a15a654e67ccfb0610a730578b252373991a2ce3e9851cc28065c6295fcebeea603b608162261447a5d6d1e97779e0191172e383bcf4150338d0d3155d8b5c8d03b4d588207490a230678d69daaa4112d036976bf76c3511c8f000e3f6bbe2b6506ccb4beadff57e77016dbffae3cfc69e0d5083e1140254f86f547b6f86d8cf110c4ab1078fcd42444d77d4204a109e429f17b3c415063592f2d8c51313c73f0c3b5aa4c1ab9f585df3b58e93078e008695f3e3e696c91a5c2492aa298b376e0aa2040c5e5cf4278a9a2fd69d43d1553097edfb91c0d26c20aa8c10f815aec4d2e94fcf27c9531795eaec9584265f06094c0ce30bbba994a42fcee1c9dab6a92eb744d6641b4490448df4b191d7c279d95d58849caed6f8b1595e03e402d685e4b4e9095d794ffa61284f140c7f82186871d9c48ec1e1020ed0466091b497c0bd894850590cfdbdb26606a43d45254a7d31988c271e5319853d8ede18187fc281de6994a2fbd54100ec1f4b6b523576e2459cc5b1eab4a4dc483c67c05718f3f85a52bb7e6f60ef1265a5efe0cd3a065d54ed5572508a0ddc985ae2d399eabce9a60daf3690242db2779d7ae2dfba61b7069426b3765fbb4dd6ef3697057b831e6aa2561185ab64a6ca11d3bab03fefb805981ebb84ba16f7a9044d55c456b15d4d179a59777dfdb70708e2b067501827f60127d4a32486a1baa00e54fd00af6ff77662548d205eadd68b8f0b2d7644cd84d82844fb247315b1cb61ded902e41c11c7954cf01ef150dea1c2152937db7355240854b3424519358d2e3980e5b72b43101d87c7ff1d68c8526314841e45df11edb14cf3066476eeef5dae19319266345be14e3b4949bc3ba65a5165b0eada613b0a74e5f939f485f8d785cd6cdc938dafc9e87486df15e0a68f14f577332bed17fb13aea22a5aa2b18206c320fc7bf515bd9f993d463b5f59eba55bfa869c5c886c737989a072ec20477924d45ce61593a5b9d3f7e6f65fc8544bc0c14cf3569745da6c3704020c4f0f251711639c9534697f493b270e88f9b34f4c55eef9854b6e91af33bcd3a946c053c55e79641cfdf2392491714a84f6f1f9263dd2768eacd0e06b0532ad6c0c434b5543060752f8262f8b812c73f8c7f491770162321cc2510ec836cc57fda88155f048724ee02ceea8a794c0518f72a65f662a05f4d596da65ed4df49b032561b9bef626fe6ea133ee9f5195acef01eeab1c3f2285612f542b03d2113f2788cabee6d488e2a360db479c41134cc07bb3bcc1c823ae6995a5a9314e8a0c10dba6ad916b01c12870cf -MD = 0d184f0a28e8c8ca71c00c8b25aeeb663d73dd0c31a2e334021ce9f7494e3bda - -Len = 39320 -Msg = 2a63bbde60c8ba994ceec43c572d29efdeffc23032fc1d6ae309daca3ecc554e1463861fbd5525205dc811c766f5f22c5eda1d5fe32eb9ffec9a2008512688ed8ef2e3e7c426048c002b02a3c01ce137b3776feac1196d8c4b69efecb4d306ee20789bde7b239e04be7f61796d883e3964408078d4a3813a89dc0f1e6eb9147a525d76adec353db11d2df4f076235159fa9b18b225b53c302d5d474587c2fdb9ad093cfc1f4227bba79b84b1e2d361c0fcf2fe40bb38e797bf53610908d507d2b8e4b5721a33a549e432d863b982b895f2acfbc99e12ca96c7262314f8d97ceefb57a9b8e7f1ff835b5abaaf04179c016531d7f5d72d2d56ce3d560b5fb8a234ffc8df768e637d92947cf03dca7a562cdce95a6e6d6f58fe5b02c2994559c2cd4ba020531570679e17fe43b413932e3ddf3c4bd968c292b7f7dc2e64b3a423e0684834f7860204ce6d4a7bbde74a6b5cf69274e1d10d25a929336314b0810f96dc26e30be8009d4b1dc660ff4f8757b3aa539b2caf3857fb79702a5245d8cc1731a4f53744517a3dafdcb9235232386782e789620a2a71d66ff949c67991a38aee293122a1dfe3cbabf350d0f93357a307b6062ceacdba61943788175494dc179c1c60750791201d9a72ebaf4b72fc8dbf29da3258087cc56f92b1eddec9bfe8c2e74ad77f4f785c04c3536750d76f4d34a6cc1b5bc3fd2989738af220199422e8f1b7f10f0135b06f4d50a1104bf70cee96a58ffce687b66840ddcc216aa2f097a26f6bc28f9d406578aa0594b4ddf274622d38425a609396637023e9a63278556239ec9de2f9356dac283ae3fc6a264d702cbb3505d0ea9b420ba081b38ce2ad99df1caae090b6105193e90509e3d1042a6ac3ddd021e0fd4778eaf07bf85724af27a4f072acecd4cfb3b903c5931a1ef7aef643a3999f46d87eaa3ee4beff440cda2c778193ff448f5053e416c12a253ec2fc6e67824ffd5fe48874d825019419c05b48f38e16e5f7325eb0e6b428a1696c7e66022217ab43732b993e76859c3ca0da6ab2e559417020836f1cb53d18df7524345ec220d7ecf33cb5fdfab5e5de4350e5a4e0f1df63e46a2aa00c911408a595df62a99209c22c62d1fff6b7f6687266c2b3c706473644bae95a014b1c4cc37a6ff52194ca2de546f32bb5b35740f3c408c6e1bf0253091cb232dc94b913997aed01704ea095e89026697ed291d08e11bfc477459720fb378f10e49371c5ed3e606ddfe91662fbe76fa1983b2b7f0df6ef97d1c08e07e1b487dc6271cfca886dd021b68db1fce7f3d8bb4c18adb4361aa1263757706e843aa27e9e55588a32b045043d61fbcb735d68a0e28ea0d9d326dd59f132c3bfad72e9dee068966eb2afc800bc8e7b3869cd2736a2c78b55aac1a918467a1261220363e470d110dcd21160fc7a3bb9a98fea1e66d3ebf69084940f4b8057e2bcac97197995b94e3d587f16e1c0913e87af5d5419bf2169f2284616dae5f0bd3812d311839948d9fa0da0f195d6b8913b8fcdd135ac926de36080c6adbe6e2a3d1e6155ebc2a53879b91df90104d73a2bf8e39ea3e36689cbf2ea28ad52f8b23396e9ed9a59f9f324249d360d9217c2c1b147c24cacc44612a72b43c0ebb7db824312df77a56b936215c9b1a2c79fb06484a045174ed42b2047ec20cfcfd33092ed853569f0249f9a564971a6ec988c7b379730eb13c0c05d9ad4c5c3477336cc5beaf75a804c9f36adc47e034929df7093d38ab241ad8d32678c3c829bbf779657e82b319f0a1b9de3e2e19f267b2faa60fd5b5321c51b0578bb8df613e07a59a727dbd693869c37c04ca164cbb5079166bcacb6fb30f13f930abe05f7fec77e14500e30a4e9a96c0baac6387f00ec8d6cb984c3171697498121d9998e40e76b660bcd291c5bcba48ea359058c8468063c9beb62bc9e96890aa7e59921cf618a65ff1fa8410389470fe060b2386802649c0be97b34f07569f545ebedf8d3bd42d9d50c965d0a6bbd5709e627ccd5430f55b187f6c535bc500ca2f27d5b7384fa89349cd9b697f96e2ec5f04c8ff2b1702f34ccbbb895f4a61567023192d73d1c3ec5d85a94d3bcc35bbc8809cbe8d6edf13dc1b25537a4d2d93b23f1e428700fc030c70141e63b22a897b546c6de3aef65736cc4e344543e20c75ea59b8ea53bd71c71b704f7fef4dbfe80ebcafd63df517fd7d7ace38c51b2b2ba35fd3065084b31df62242e8ea2bd98efe01d6cdb237e080ad4f63dd57356a54089533737dee31818ebeab47292160e0d0d07542a25b4b70ba40a7ab60cd648f789e4caa4256879243b9eb1322eae07df5ad2ddd64bba34e42d30c1b884f842e71efa123345a3fb0c39884c57dd4c2c6fb0c42e69ff5a269d59af3a6144853c182edb376ca65947d7ccefae6806ba25c4f527706ba85a353c0fd10e3cb244dd93a2d060d7b055058dde1dffed13be99e61341ca62ad830acb37dc65ce37ffce5f6321b5fdcc5edc375658666f6b2131def05b65d8789d4d51b81966a13c7cb68458165f65603b74dc1be90b7576aa94b376bc69547070a6d77cd03a3c27843e0b68f78697d6b57684171817879c236a6d8baefd5ffdc3bb646a49082761df0efb7d0b511c94948a37312cb22d45525d1519774980876037006acbf9eb5355cd5c7e9be97b04a057fe516f03f0d90113b10760763f760dc0b3649f350f64ae233652ef763c8ca086e05f273357c0f6344c3db1ac243393fe86400ee31bfbb1ba92e34f1fe8965ebee6449d69eb62fa69eba3b212b824ba9b80e65e2c978228377718030c0689a0a817e619ce3228d45a9821abd182b2493caa3fd7370c60d945eed952661ecd2fec7b2ee28ab6784eae5a9fe3100a450a8b0a31c32d02fd8c8afe0e8655b8cad3311a0442c4ffbb2e0d3a05a3f8d946c330aba56835ffc10baeaf9fe5005de8531ffd517fa5935a3d213e3b33b1761b3dd3928410788d141d5a0975b890948f795f2bfbe254fcbb438f7029db62692e401bc9b4011d335e89361576462ce6270b99acecb3f9c2480802d8b8e3343be694b0571f834d7a0718e9da8bd9fdda18d274890a3abe6b6853207dce924e73aa003b44abe030e877921c609db72bf8ca9699c93fbfc98182ed91675431d899e44d6498425eed0716bf76b09229ddc8a51fb0747289428c009ffe9e3308fc36fb43d25ccb47ad5f4d66a0d154773bd3123460938be15212492f0f2b515fe0d157aa2e982ee19776825141cbc9e96ea0779f512c710f219dc5656b15987eacf2604a1f525375d4d61e4602a7dbc79eb73d262c4a0e5bd6b4dc0bbb64efac89217eeb4e94224a8b078a0e8b6c7158f2a1cd9299f2490c99e0f6e7a6203d339fe71954626583aae58f2d71832272e593e58daa3f2e0a6c94a77bc3d5526c5915cb994e04ce5edb0af86e3692d2c8b6a90be738c70539c1ec94d365ef026367135666a1dcd59b2621cab72761835a135b9c4202d880bf54cc2c66959d360aa4c30ee815918522d3528b6f0a983d1044d11f06d21ba5826d5af99d1d87f8495a4b7d8771cce3db2ac7c5fda8df08d290341c9a6e387e6b54be82dec4544f08cfd32bac7f34f9ae73a5ffcbc9dced8841ac1b689ed6136250214f9251ad442f4d849fbd0572ce84f517c240343af31a9d60a5d72c9d6a50aaabe9228d39dda61a856124cc2d6a43f94395c4b39f2370ed79414fde378d1bab83d7f440a124557efff9479c0ed6d5c75100bf0cb48373781e78387e4984ad98d2a172318c2125c31af0903dbd1920a76a8b9908201e098878d1fbd27e55ecbcbfd0032aa3dbfc2ffdcc6676e13b0ee1b6bfbb6f8bf91b63afd4fea37b0ac25e73eb0ef18e5ac40cd1183010224586bc5c238b099f1e9252ea09aab8ebab16c5157afd50f4a663a0bd5958d42a3e6f818440729e0194549d51f967db743ecf3ace05370c7dc8c334ea1945879e2eb379589cd9f55c634b8c0d2b9ed2becdd705c61524f0d2c7ca0f80df5ff4291d39e9fdc126d756945d674627b566725f156e24312cc39bab627ba6340ee27114e91c9e37c30c972d74752376165f38fd71bd11e2b74c7f7c72be849fba181e1aab596184165cc83977ffcd9f2785b7aed339b4af2d542743e12143a8cb5fd93867e76e32898f91bd4e4d6c2a52a0987a232b3620f6a33b0899ec0bd7a97f4a75050feec9826c99c3e1a727a0fe77826949dbbebd7a0162d1816703b5bc4018d96d1909cf6bbc89521855268892d31e842e91750f223644a881da54c96d6aeb6c884de6ceab470873db9e926a787c14d2b895829d54098a94818c259b22c46d373cf2ae4daad5bf2d12cc93ce173a0b5bd02e0eef7944dc9e69c69fb444174441725288d5d02e5688a525503dd7d5ac285fa6418efaade1cc21d0ea9b3c2b189213b39ded8519748c7cf2f23f20149e404b4342013d0d422892f22dd871c89233055e151d3160c1427f7aa05a5ac089ac7e4e3ad0ac2ba7baa27491f44ab6592b329b17ed3cc9e7b197078318eda11772de0e5084aed1b6893a9d3d7631bc168280b2cbe60e1d8be1aadfc300427fee9c55cdada4aac51a9d43b659e68da47141d9ea5a8f0f2358dba14b879abf22b631cad178b80ad079fea3070fcdc534116f248cec70a8a5f3a66593f76fcd52183a2464da4935ba7cb544d885b243359f1449e0a8123f69074addff3c06d5d6bbbe4dccfbde934bcac80c71e31d6e6ec2392f2eb7fc3e393ad0f0d77ee73d7749c52c5102ff8c4b0c42e5195296aea923e4c0be41b60bdb343f8862e49b6efd6758a93d18348881e928b61afaa66bac6a20e3d76dc910179e9f8ce997a9d130bf7dacd66406efb60a8467ba02d40d403ef280c363bcb3b720f9e3b4bf99cdd7f93e1d660ffc29b2165ddf4292a9fc2d476480c84c175e816154770b82f4c9bcbda3e433409f9e3db6bc08fad4aca13b2e7dc92f5063783f0ab82f360b412fa5b1b3ea862075b71f92a8c929ee6562329b454440962769b7c22df37c8008665b807615a6d708da1f51290a18085ca8d935c5d94247eb98b232bcab270ad2d6a6d0f44edd8ce070079b47b3104b1adcf9a504717f8a386ff7026c3f7dd025e74d4a367e716783e29d1a0bad57de26645a920af23d88945550d94698c7fb8c011a95438bab917b96aa737cde35ea08aac4a5e046c5688ab2835f509c4cb28c8cd359235fd33250f6f551a32ff4974914ff868d535f539fef593d9434561eaff04140dfe031718869485a8688db0c700cd2dc190352715d729a1b1a492b667c952cf07ef80c77ad5669362fd2317205f907508d3ce8e94ba40ea0e8c114b47be45c11088eae6c4627218ea6f33ff090436489f0e867e4f1ed7c750886592d3543984c86895d77dc43380af1d54daf9a51b2304aee1889d8b6ae42827e42fb311ba949ffd362c0f61276511a5ea2d7aa8db8eca436430187656aae5c931746f7d558af7b5305701cfca30c2978888f495e406605a8307386647961a0ac1f3510d76b2602f18dafd76986e2240a45fffe2c1045752c26085e19a30456b0a3f1038baa589d9544a4adc1e87c15fc22505160f232fcaa6fe896eeaf3f8489eba25858dfea53277078286c9181033667aaca60abd5a30a513ab64967b9341e3f6e98a5d0872d8f5a52d0d2499af79f5c34f29506d5713415274794911b6d57e7804adc46d531b54a5b2c5cd86ff82149175067cadb6f1002d6d036f60c381c2afef664097c698287bbc47005a70ea3757a6d3fbe8ea387626fd9975e359c55521125a5e125dddc5b99207899eb410e2986cf83ac97177f7b1cea1f913da1eaa5e05d07967894ad0c1dc9da5de29a48ad63009d5a9dd3e197038c3656ce4fc36c9429f2ef1c96dbe37146001635203a493888f39049dd96fc4c4644768dafc9ee540eceb6baeb4f28ba1f508f8bdccc452dedef18433f85f220a1b1ba24c8e275499603b1f99cf22323dd348f8dd4e7e86cb9f7b9320195c3a724e5e73ba2f7479a48f9a982afab1cd10713dde312717b1a73753abe29b0b5085749c87946f1ad70ac1865fc2f615aef255442349e544662a4d06490c1bd126cc2432487bbb6eff34bc9af1021fe26a3bf6186287e76916ad370ff50d0a320faee3cc20c0930554aac724d668f69c8155ea17168bcc1a45a88bdd3a65f4c28db629d6bb13945279e587d08a5808a886f897cca9c601bc65b4c1fa738759f7136a6cce71e52dfac16d550a875fd49add6c95a5b6c706e4195a5fe44b11a8445344333fefa5ce52ddbad55f5800d8e8174a5a3ea7ef6a15b2f1ec273b756e3eafdc03878ee603ff21467f2b76bb8414a71a5bf407df99c5d513cd3faf232a4a9b8a5451ca164d543ea8c91b5e1064a51f55117250f82478f258999a10cb5b0ca8d7bc1b3bc738f6885a399b8880091de27321161dc988a38d08c7d32aae8ed95a5c81405e69255a80c34728808adff392fcf16bb8d434da17dcde57377d144522817a5dac8cb0f4da8c883ed0a167aa936b08ffcca8b781352d53a2e187a9d483eeddefa0925a59d80e636af3641eb77645ee2ec3a79f3d4772be52938ebe1c00dd4262d52a9ffe1bd16f29533383bece06079538614a62c15574c2d7d2bf602c053e53a4b5d056086e02068aa03504ed33ebaf95665796554e2d9018f41c6567df384ea9b4ba06404cd26f042a814e564810fa6507255c65b53f36f173838046c3a6905eb7bb6335e646df5a4316efbbcb0df211f4520965332013dbd153353b7b2fd53e2f33016bd2d5d3f77a545d60253913369e6c41e63086d3428e2a18d83e3a89b29bdf75549b15e95640d83bf5ff38fa4d75b27a6b45b9e1c01a769f8fb54d3a767e1f2382977d9c113700ffefb17403c10ae33756eb6fcbdef6a73dc448de43d45650807860834892bd6d1dbfd470cc2 -MD = a248734b02b14f0c26119dc57caa8072b390826a3d36f05cc8c9d429f87fe698 - -Len = 40112 -Msg = 21876510eda9ac6f736d9b2dd0ce50c526b61f07911e2a615d76315c7647ab691f1715dee78d8a3cd9d594b3f44642e8db427af5cd5e91b1d6c3193347d5fa916512c5ed5e3c44b381ba561cad3cf9f70a9ea9a8f80fe97145721ff0a304a4e9593f1c4638ff035cd1e48970e5f7a07a1d905328fb7759261149ea9d711dd1fa6468c3f05f1eefc0321ad6b883c05df97be1207ebfde0a5aa21123419968a84aef5361f3b9e12f660d26e5fb6fdf58fd8c59bab12b8e2394609171e5022d526360c99f58308fecd6c8ce5d41919cbb0db8bfc6c926cecd5db3937d9096b4f7cd20922526ab724d99cddbe692d13eabb267ddefcf9ae5303c03ddee4a3c44bd0e98769a6511d07b3682142af7170f52730179daca6e1c73b9b8396d1bdc27cfb02f3da61e4cf29d355143ce774b55d8d8ee5c32c28abbbf5c3a6da20c5fa3533b4caef2584320dc1fa12e7d1b55596569964e9dc0d60a3baef1413424ab0172355993261bdea2607bd99eddea1d631faf6216c3ca3a501036467fcc6ca9895328bdb2ea6f05bf50d1635b96ec8bbb3131b87e4eeb9ed7657c9fed11ea41821f9be0d3e45da0c0d4aaa62d512988a8c177014ce328eae563096555aca85c36fd172ac0bfec97ed168c0adcb6aafa73f80aa6492c8b06c33164017d44aee0eb162303402125d28e3b02f72f6c76cb65fd710d3dd11bdab9f915d92d8202b7ea9147d31ab30e3aeb6e91d5f01c95e1c4f934a0f07ae04e0ee0a5572f0eaec77b970b02171cb2b54cd5c30ce56d1026d813dcc629cee34b0c109be24a8fbafae550f8f8ff04162cf8981f04d708ee80eb74f0e6b2752bb7f9b17fe145ad2c3672e3951d9a15448838e02d268d9437d94343f86a5118c07c1eeadabee9110e6568796adaaff543af54d576d8d1baf31829a97db9cf5fab80c3e433e0fe63676e10390095084c1b8b949e818369222b25e5ce063bf3f1f3ad30c712af4c4a4039b24cdeb76bc3d5033f64d6901e73e7e8bfd91b588777a0e9acbaff939a6fa0ae96d98da9a10177fe9f4efe65b8552d49fff244785198bb1e80e583f4b17a8fb5030993d272af0c66fa85806cff720730ec430a031bfd4b33f571253a5a12163643047a99a57599229930e40cbb6f7c85cff1f461ab4d581051866ecd5bdf3b199cf1c96804fa281ac478b3acb3f79430f0278bfac931eb9ddc4be5167c8b084657f809a655e7c036c38574b6b0b05819970b55373f510ac2e0e9127b87bb85a5bb43c1ba61e36a5edd7eaf917a42cf280cc5dc7ed454c067a3887d654219b91f12f7790ef0972d7a5b8beda5d9560246967ea8384fe312746e4eaf3d774dac9aa23fba09caab117285d6b45a9594f7597f5e3fce79a50ad189662f69ecff66ffb5410a13b6c61e2ea3848f1875a3b84a0d8c2ba61a43af663cf685536ad6f0379125f4947d905d96fdc00347422c4d028931f42afa64091bcf273a61b87a51297e14fdf4e7b3d593dbb09a4fc4d6bc683b7420c1e0b121d98920d5fda09491bcc636af9cbcd48e0b847cdb98c34a0f636a7e39d295d1fe86b40ade8ee8ccb9dab0b291f2c49e91e8414d4e8a072f4edd5f76c7c7e26da80c960cdd7c59c9cf6a83b02b5fc7b6e5105a4b7c8e572e7fbd638550078d2d2851774f5b2ebb34de53885a064c8cc7926d179dec0a7defacebbcd35efa5eb8853fa1fae00ed6b4eb7f07d6a91fdc77a1e5bf6c26683f19dc4eb28778081fb7c7bd5b36f28371f200d5474c9c427f6e19629cdfb30e665418d08fca279996d1f7b2ec2b1bf55695243d92e5681b3d5502cbf41f1a66ba4a675899c3f1158caf1c089d00e2cc4b46609f2ec89414ded465081053e3d602a0d1cf1a9b61e4caf93ea6b6decf7119adbbe3641fa8932992490038a497c808015e1b5879fc6e155665747fec6b4a88713df27c0f2d02e738b69db43abda3921317259c864c1c386e9a5a3f533dc05f3beeb2bec2aac8e06db4c6cb3cddcf697e03d52de9d854f9eae440403ace3c68b2d70c7260a74ddcda4c63c6d280b455eb2a1455cb287f22724c0ec8caa424697fffe8df10acf9a327855ded262dba1d0295c85a54c50679add9ac202a49e12b496e2f4efb4234fcfb689a885d6c498b6a4bda85ab364fc7449302908445dc76b92dc70749f066b1fefb03dfa2c5c965cc54331ef903c4d3de82f95ffd1e7c1177439a52213ff788d948803a1bc1a274cfb9b96d65b5cc6724af77d7bf5e28c62ab88f77abb64f4a3457fae0f0e73c801c8156b918d3ce49be21653ef28c4a5b7a958dbd11ddd6bfb62e571a4abfff515ab4f14c3ae5344253e0acddbd31499911e17e6e783cf5ae08d7813051d254ae325b726cf273651a8bf532fc49d48d4894a449d00a5c12e0d25a5e6a2ca7a1604c7dc0626806c9991067e1e3befd7e30aee6d62cefc4971ebbbdd80f04c74f304f22c576c525c887873ea0d94335841805b00dc94ffcea2e6b0ad66900b8c7e3e45268ef3159caab9b835627000207ca4109d6f1518d75d88b493fbe49047044b2169117d32937cef23ded161eef6f0c0bfa19ea1dfe9ee6c380fd570632b11a62752834d41d77b834744cecc58124a70b8abefddcd7cf1ebab9f77c60cbf42c9b78168f5bbdf2310a305bf11c428e63e8c1ad72b6a16f4a19fb15757f56a04306264170919211011c7a026f4cb915074aa7ce91d2e2e630874f3f898a5b1d274a87921e9e233aef115929ac7c6e225ddb4509a159259b99adbb5d01a963d2a010a3f1e3a9f8d6c591d6b8f1d5ea1b2b40a247ec72eff84c324a572506f5297600834705da9a4e4946f897867fb46a3a24c66eb846ca6413c001153dc6998970c12e7acd5a900844d5c7afb3a15475522dba684efd3d47b4fcea809114d75a58fcac748351626e7de94be6c06453a63a03851bf6bed10af8900c7e69163805f458061b6fe799e7be288d25f4ef3864bc4f2f71f8b10c13a7246ff80cf443f00d7e4359d942bcdacd3a9455996b8b169eb9c1519bff79cb895f1cd7c3d781846a156b15088d53b173c8685cf5ffd526a9e842a228d09d9a65ea1a01d6e77829d5c6873745eee7d3787a122450d49cfba585ba4ee74b02e9056c71608d4bb24814399da6d88dffa8a4f79993f4116bfd5a37323c20992f1e2f8e2adb2f2cb747f015b84c09932398bfe8059328dfc79490a7b0541be1aca3acf84c5906b10d903103dd102028db0b90f45f0b33663a280e7d3f7e1f4c02de4451dfc458033e899faa16da6473b069e0c4aee25ecd4b219d60e4a27602b839be42ec036e49d29c01b36a921e9d291a77fffa02f13d83e705f8a9a8662a561ae47279fe90ac4f3021c5e22196cdcf861d4e4b5234dd68e20eee957838ed64eb7c8a919d06543facc589846d142c28169a59aaba6ed6847b7feab0fb34726b134f3139c81768297ab6a65a5fe0e2be30b5c71e22e94f5f1822930317a1e2f3fa25107b670c109601bcc56cdf4116193e3741b072eb717f23bd9295b5c9648208c6ce5e622d760da99e8ec0d681f1bfa6e96e6792bd636e02198e6fbef221a2a5f914eaa1c2bf16da26a8602ae69a3ad290f74b6ba74eb41ffe3097186540da39878a280c131639fc1abc54c5b9391228f78364e3f05ad7e0342017ad6aeab22c39d71f8c68a1ff774371a28d41f8cd12e5bbbbe3e2ae61af8205f7634847b3e6d5a4d8070888efb46970546cc8fdf5f621465754c373daf3b1883d24497e64d0239859663cf49219546172499470113e74ce401cdcd0c8138950f3d7b3b84e50ed5cac924c0d6e0fcbea020bee7aaa51a6f87f2575eeb579d2062064cf1cf7cff997d97280fa0dff98b60e9c1e4347977f6e1b55d6f5288c5451cdb2e5d3e9b610f2e6ed1fe4f74f816b9de36cf27078c7d81c96460caab4d7da01ab3d04ac6bfa15dded73f2b2694fb2b8c820afae5c45dd8bcf0f5bc2592248c4361ed8c6587fa7c559c24dc8b3ca32663381a487abc2266fe8770bf8e3fe441e3bd277c1e36751a718551cc197b994af0cd8f685cd065bd0c8c744d4bb337618a39f08257679ba8a147488237be57f9b3b6dd0302bd923b659462ddf478985b954ceb378787e8a763467b978c9179c33a988580f2b03262a823eefa0f0c81a0a37a6a244513f6b746075d647e815937e3c71b6aa364b0d332bf5b19f1eb7dc113471fa106881038a80e7071940a70b84dd6f1389b57a80da3cb49c653a1f74d83475e665270ffac37d0576753997ac4e75cc97350e5826269ec3d879aac889671dfc8ccaf5b0f9243d1748e33bac1fe3eace6935abada81f376a8c63d87ac4c4d94c14c73a2ba8b7a965a8ebaead0c4c26beb211f241adcdf0f1e1ac2afdcdf94eada7e45f49ae83a937bc16fa631a8f0fe499524ddcde39b29ffedb0a184b0e66696daacad2b49026d4aceb8796f2b68f87477f2345e36a63be0b78df95e60907c78da0e48e61e70685a1f3be0d3cc88df0e320db456368ec94320c113a47f41b0e2f4f15445e8f3392c3b405929fcef06896bddfa4073c366a991e08d016d689877d3dc6be5290934339b8c5ebc3cfa23588df962a76ed288768362b1efab8397a9cf45dc2e6f310df2c8767e151d38a9fe00d689e5883a935c8dce4ee9ca1132eb7fc4419c2bf91b0c3a7513cf1e390f0c7d0bdca5707a3bae1999b06a499ffedf4dbe18b8dfcfdfc27a2edc44a059c6e64affd741980fd5fdaf4b62fb9a9e5fd7b1b9edfefb23e0c7f00a24105439663e032906546f69f6cdb769e3183d7ada77543e2df92ea3b28f447d77ac9a5661562e1df65877171290ea5bbd4ac2d3f330adc14511bacdc98ae01f6383f32f5cd1345503c84fa5add990c75e0d9b383e9616d9efe35fe09a3d4b566430ff229d21ae54cb1e49845d2a430351cb4706211a37ee7ae86eaaa928eec8f63e0edeb6ea0493c8d4f54174e589b6151e56cc2f2f7985728b677a7ad062dd9605a2c24e7cdfa86986f35b99adcd4634714af8dd5864256366eade83c6100ac0126b6ba86c87f949ae94313fe5963a1c6e842a90278044c9e56955687caed700fec939793ba60cc5b68860dc1f7d18596092c00c1f466a1291536d7d6677d8d5353cca156ca2698a29207902ddda4757e2075785a22f1bd9f5499547060376b920468c21621585f390fcd82883467db48d526fb142b2c09c8bac4b69edea47297a76fe11de67e88e688e0cd1b239f1ebacf457039379feb6cf0c1e3a8094a0b29e3eae5b142217d72a549572ed3d6a69db7ddbe0f6dd3cc529d98c5d608b39c0f60e0b81b5dc8a5a50d0f0a096c93dbb834f3cfdff64f15436a4f436f04678f12c75941a35efb6846693accf3155f25d5ef918af0fa9b2c07fef044bd24ec4afac05d68906e422e1f60d38736f6c1ecba8fbed78ca0407b660382b20691cc378ff2f5152cb4265ff69be0221838419830bd839ef910c568281e0e7493728fbc98062830bd592e6394c16c85e2036791ff21e7c78073b25d14f99b72acf0bb43dfa3ffa18c84e3a3c17b7c98db7ebc3fef62f23b69f190c1f33c31949933da332a728050e15ecb8544711a434dd2c70bc829ace0fcb1e6fc8d8fd8c2a16273f4421bb526040f7072e74a4d6e7e26105b511d1e9f81dc3c76aa9899e40da50feeef45a6093cbe5ad370af1e01b7a3209853e74f613f991b9612027be225263589f8985ae2d2930f0ea84793e440717e2b972e470c7f1109c68c7387a4310a6d2d27bed99a0eb7198d57bbb7ff61b7b27ae29b0f89896b906ee293c412797c4042425c2b17385200b645b28f3a629e45efffd6aec1a5d038f4da0c3a1545a23430121d5943988b4af339d5257e8a4dbef1b4862c9b1b6888c13d83f193dca4d35f5fa66905768b81abfdcc80b123eca5e7cb5392fe325a083dd2a3f27587aba537f1a26644197a2c45573ea8bd73a5833b0ae7e7d433cf40d0631144a48edf31218fb755eaca7fd42b10d3a688c39edf543ae7330466eeb9e3b678ef073967ff83038d40ded1c200c4f03481fc5aff419a23fe7e7613e0fadc957efc85cf6b97c613cd2e08766c3878be09410082f131758cd2d11282cc8b25c6cb72089a158253881f285001a505af44f9ef7b819c384d3e0b33c0fbdbf52411085977e08b4791292a359eb994edd148ad9157a027dd8a0252ad68c535bf4340ddb9b9eaf56ee7c0975ddae7627a4693cd327b27baa9949e4f46f2290171e919f19bb8007c7fbf130da8ecd3363477ed00d7cf5e7f23d4daa906466f68947d66ed065b6a480380ec351fbcc539a2ca1dee8a3b8c9bd3b08008f54cdf91af69ed78038a6f80829111b7c93305934ca8ed4052a7fb39419156161cedc0a44a14773b992d584c825c4a3aaf37da6bba7a239e38fbf17ff6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb7957903b6d92f9bf92c2147b308b070f6432abd1ce54b8a67370496e41c7afb95a45264cedf2c7ae0ef6d9ff56142df3bbee223455c13a8ae7aefb0ff8ce878d2d40a6938328092593d5a565a928d62846d3be3a27635f5aaddbf5ea0a8937cb84c287cbb7b33cdab3e6fd4aa4399e21878bf63fcd9bb58a585fb07911883f08d3534041e624e1220193482ad1b6f454008f60c1a2dacb8e59d2b129883c0bd9ab6b6692a8ed848fef731c62ac3167544456746c61b11ffb34bd7e97e9253c927f83712a7a8d9598effef09ebe396586c569a7ac64af11457b788f30aec43fe7c233f695d575a2c185af5b4b622f8d8ff63170ee36454df190bc59806399843e05e54d5134461a9e42fcb2d542843dc4796676ce50e4348416c174038235a7f9dd100be9317f9b839a7fade8d9e7f4b8a1511fa94f2c437160405536a50929cf9a5ca8ca377274161ea092d282cb50f11089d22b8b8e294e1fb1739626848813d023aa80c0cf52ca21f8084ef79ec0f2498934b1808a247ea79d55be9148216b00fd978957f6a61456ee84aa82e2c330bec7cdc7d880e3879a5c81fc6fc4a439cf52e6508788ec99100c7e71cf27d630d2ee03fafe32d50d6a777eec3c7a7f047 -MD = 49ffb48c3b64584e0945d92c7c783cd55eed7f749f3fdc534b5e41239f1136eb - -Len = 40904 -Msg = 972567cf3d7301bd86a19bb77671891b09c4b0817fa583e6f789320a3fd51d16eba18f82a4bca936c3f09cef1f871ce5220d11ab23588f56efc608e1a9c6c0d0d59a8214af5b922fc13de298b4148861671770173ee44eeabdc5d70d553231607d97a84d0557a2efa710d57ae021b7d7fe69368e7952aae9860e0857ea21580e0c2069f44fb8c3c09ef1dd5c49b4908e0f8cccd87ca98a9d752a0184119c1d22aabd2dd33486dce8ce69620897d8fbd0c30698bdeef1d54cafa02c5f71a968e37ef75cb05dcad4b05effcc447392e0e3416104057733753f5ff8f0afb353219ab1555e54718c9560773c83d985ec2710b2247777c07651beabbbb43b7e9f308f6a609b8719d2064040a7ef8f74edb99f3ed859dc71c25110bb70e2cc7b977d0ad29e7c10fda60f98e2c8792de89d7cd80c0411fc321f5d7fb89fe12a5142f153119967b9c40f98af8427877d8b0559034530099fa9965d51cad1191da9a872b14ed9c548171689ce4f4d8345022c386710e5a88d812e39cf188cf26d2bd2e96eb2e4ff869dc1ca3d6bc1d34ef81b024d96a9568d60f0d941cb5bd4e17ec73fd064447b3bff1a4444ff0be16013d89dfdff077b69efe226ef0ac327434b8f5a208c81a32fe429dd2b33b41343fb6df3bf72847fe7d50e0620fe4e5359393324a55421de29f5f57e393043d3be59e1ebdb17aacbd0ba7c621ecf83c0ecf1ba84a9e2ae93f3da8610b71e40889ad53d6c981700c5eb4833232fa4ead6c31a2c61725eb02c533ae479ed2533999f168860409a0ed602253b2f9ca50cfea85d92a549f1ad1012bd18a3236ba57095c5caae19c75d66dbf99c70adfc709e6162f33776c32fa7f80c2974a11b1e7444890c3e6cc774de406d5ecda9ce9f20b7d057ff41fbbd59cccf1fd6ae5b240d740b55f880c2dba4f7288a2dda461fea7250c6e5f2c1e08e58ad02b0945341a3ecf3adc49fdf1b22c8d3287a86897a665a8949d1d03f1eae624fdbe9992dfc9e75e81c8a0f46bbbf7d163e9bf6c237fa3624e7ab249a0221b35db16b060edd67d792ab32192043e2dc98d6787217df10d0c8a95b36fd114f137e8d1d23206d64da9a61a405953cf5af02f7f941b0f90fee1e95c94e8ed5a1495a76e7378b33fe45a847c81bcc2d5fbcfbaa06adb60d5f59cdb6deb475d57d1f9a74b18c77b89de2636386a3ee9e88cc2cf687fc51a468d97e1180afdb994c5be68f63680b82aa7774bfc7e42217d8a63de36477a8459136d9b09889e8aa77c6e5d0e6146f1b8bcd826371279121b714d5798566e4784437859a0f88c38f6428403e20d8cc0baaac36556eb462438ddc9cc1d2112cc5e9a52bd7cbf595d07d499fe2fafb4ad86edc389fa4d3be06c2c73cc234bfa9b5e6487270b61885f629f0a8c25cc7100c3e242f49fdcccdf1be9d5a8491ba83cfa4e8036cb738bc88cfe706e82f82472e844dc45960e6b68ce926a110d348e19b8b4d85d3b59e610ed9f45f5c597516c7a7209ed9b46aa25fac29b66de0b2eba2043ea1ad9a939d10aee05c24c4e8a65e0f6266d0e3a0b8f36d7044a3a240cb6b7585ff034d5d9817b672a44a56221e7b24dec347d4d021cf95c1f1bbff39a67f47e846dcb64479aa5974e0d6f96da7a74d5b5e456f42047b8de565bce1e7a764e3301f41bd926952ffacb7ce940f6968f5a0ded29c3e8a80bca449ae2f90f3a4af2531394a8d8f9610e4d23c0f518b498176ecf6430bdb6589c5459ad17db5c7158e25cc457f14fef4e2d827527b36cf5aa530ba4cf21eb25e120087aef613537c34a20296ae1f12136f729844d59184e8f551259f3b7cf0a251237db04235d24ce051e42563d95bd6524896cfa7c5ef932ef840252e1ca6bc4b5584beab44cbec58d979dae56960a3550129da38f998c417cc12c412275c16c83fa5c07768c7c664e4ca9e7ef8a9e33e45594ed15608e17976a36531c49a179089e79fefc84d41ce17dd5774aebfffd6be2f11ba04c6541c9dfbf1d11ce9276ada53415b8de5c55d1cbcef10b2295de512b20c3b2a5a83c8ea234e3b56d0ae1fdaef8f03de17bad89b6f4c9a2d6f6733e9eb279cf04dd845042266b79bd8147832c5712ee46c89083bfc585a461a8487ece04b247f26b95a95001f8c1387c23a8addd026c76b98b5a56df99726b11baac29b5e1cff6d90d142c56304e5681e30893d9231ae9d50a681ca199bf4bc9665142449cc98abc470b57a19653a009121d8efa198c18819a576199facd9c45c7e8a81f57c7066bd00962729f839d984d41ffbe3a32ab65c782c647313fd50d5bdcbbc4974b229e3488cd27a050b7a5d12056742990eaf7fe84cb27d1887e869ec80dd2cfb84799e124085f6d4d76b86a3323da5c498f9ecbd7e0ca502a01480d150ea885b0ee056245a4784acc635654f4f85f36aed1e09bf6979d31b6f5d8236e4ed44da79e5734781210cd7005f64de044516d438a640b6b601efa91d4ad7e1e3ed48c1ed115d435d19779bac71e917f887f54a9f17f8690cace1f5d164e79af6f37c5891ea7ce0973aab41f2f35ec3d45278134afb98a114839147b4311b2bc506c8e68efa39e6d7899110fb6e2aaa3faf877962d98a26768de7e7ee3bd95bf72e14b50cc9fa1cc4101152ef6ab594e2a40ac20f3a35c0d9d2cc1ca60a8af13573480b32dd284b07d6144df66d6749643ce93778a50137e55b262f042497b626de4c3128c02c3b48e3804b3601a8906f7c0c20c6a25652432fdf68311366727376086f17fa6cb42e403f92daade033a86e5cc520b99cda9b56dd0f555f61ecc344640c2711527e61f4376a08fa77f8b919bf6daf733b9894d90a6c978eefeebf4e49527f8f45608a07521de86ed5a84a851e629b579b51d7bf4cc7202a773e0f9e9d8748fcac24518276f2a493620b02bb62ea0bee25d00c108d6718bb63a55a3c4af4a9def1905d6c8d3061f187e88ac2714e27be3fdcdad5b495a6c71aeb482e36e1cbbf7b6d57cd7e204a0eaa0889a235d61951523ce915a999f2d804d8827e4b95d526b282e6ad310a84743534a86495c9062fc7b9e2d854bb25758934b0346f5af09cfe99b3158e363aab8e328f0f787119de041b6d269d43672711c67a568c7644a8c778650c7deb92391fcae5abc81477e8732a31086c78df74045786ee8932f8d275e8a59be672b4a84ec653416cfb4bd57badd785a9a3b6e7caaf7f034ed635a270b11bc9b113c98085ed80d74c6ebb2b836e06a63c0c1305cb960b9ec3aa22a1219b6e9ec616f9472b06157850b4ef74f53367720dfb1f5870d4d2c6d0f6e856ee6e47220dc36b87a7dab9296017103738c5a2f104b802671f307d835d01ae4940f14d5e6f6248c7633115f464dd46fdb4ec5e2b0a8ae3ba4174b4dd52149d0380ed2959d23ab790c6d2d0e0444fb84dd16f432905bbeada3f661edd9777dd0b142b821b2094e169388793f5e8b58faff718faf2df91414e7fcf648a147295e9667001ad3fb8eeda2116063c3857f2ab8ead2b8e7e550d9e6b762eedb24ded26dc874e1619ee056bea48d0bc1d7c0acafef77e06cc4e79536a25230c574f0e49e037105e947e4ea5f9e59a7e7d6eff93afbe9961afc6aaf4e3a2ebf1ecc120dad947ef8e9aaff20fb7b50b884273f88f0aca27a71103cb0940b62fa45aeb4a622f8095ad12cb19328c7fcce452d41d4475e2cee0d94e021ae829972b8715b56849aaa7c3e318ea94e10d849a97d9973c59d03615efef77b043c3ca905d878974918dd0d9f7df8ebf1c25dcb0f7c98eff1f5a084e3b2e5452b94c71dbc388ed0e6ef0b6f535672d3ba7907c305cee29132d49ec91a453be89b28b3312a06209bf489c012285faed8ee8160b21ad8e9102ed6489e815a5dfdc9649b93fde5b060e885a5a65cfdef942497e328cd2f2ee54c575885a736ddfd3cd4eaa6964bc0c8494f069c8fb5c77df30929878b262678f1f4290efa7f4e6f6bf62af991acd42a7d526d552f2bc90eb0718e6ed3725243d62954ab0997f1bced54d70d6e8d5d102b3c6460b9a466bf035d9c3f448854ee5f6345ea43159a6e275d69428b61ee11a979666fcdc423175229dd893cdc80d1043e773d458c9b0ba08c7c4976cee9979e760da2ca1f70903362cccd4af378845b1783146f41661dff7e6a72cf28e21a60dea4da3cfae1c21d94d48bfd41ae80ca8ad4204ee89e0d8a9fce6ee3046a2296ffd656a4faf915773caf45b25b954ed90504b162f6a562d85d028e60f5d448b7760ca880a42912d6c6977b08a5bf571d127f7829e01ea67f52c161a751d2e538bdd2505e7af442c2cf37ac6ec4af31fd3fbeb522295c50d5fd657944bcc8909153a1eeacd3dd1db1b2fa4a631cc7580fe93d28ea56f0ea72d97945c7ab37c357c405c3ea63561c2a2e79e57432aa31abbb9523c0ed8eebec6377578e91a306028b7880959df1b6a27e10fe108aca6787033136645168dd9927ea1f27f48cc1181674954ce83285a14e6a04d6a99a61f87cabe1331711280f934c1d2268779d1ef174826ed69af1acfbef9a2503bca996646fb4cbc33a53b63207c1ec51d5f27da912d879ed9d933c231c1e8a1d83b6c776f7118cda27093380b7be04353a59baa9b9f7fc91ace2c5307a02747b92123200dc97f4d08980fe0bd661f8a7174b5c7fe46175675b58dec0740682926a343cbe7ab8922ab4838c4fee4e481bff3fe9982cb562d32b6dff4fb46b22f66e956dfc6bd3f35d4a6944a969d3610854bfd89eed6453699fba9d3a95d0e41c31ce4c472aaa86ecadaaddb4c3a1d1f0aa33afd0c0eea5af1a973f0d92b8347836473e1b318ccb5d70d0be0e963a19697243e5ea21c4f7f84ebc6b555581929efe88da051b0b4f3416734bf36bfcb5d74f5901579a77c8e98e72889e48dd8cf4fd1b9681319670e510fb2e2f8f7a25de940b9885958777076c524d44d72c922eb4680a2c2fbedf04f2e0daffab22e7c3e2a3f2109d74a0b66ae3fff59aef3080a7068b426004f7f83ebcb90039978a3baddac4753cbfd49afca0370d0ea5f6af677fb0707ce94a5346f76ecda5487bba6818761fddd96119b40f7907acd1331f582c1032d0dc449ace1952a488a64aa4a3d59d9d0b41f4a7039a3c71e00194350b941106066e853316ab1b415e3155aee3aa91694f99fde77dc907e862a798a4f450397678007aa0c3251f10909a4b1daa0ff8011531fb4f852451b78f439ed394e8ffe0b0529388560fd49eba118995596e37f0e6ba6b43bc24a08bd05635358fb6eaf149a56e4e31d3e2485567af9a944de7b55e83cc6875528ab1d07fea6f27527104ae9979670909aea9dcdd1b81cd377dcac73e9d22632666e5f9f13cd50e4428b749af33672e29b03fcb125c0f76b370adcb4b6c05e838cb84d77a9b0ba6f47875c5573ad323ac9d86aa87ff88233a56ead52aa78786d23f0ad37c837773ebf6cc8c11ee1f8c1abcfaf5ae6480454496ee6f6cee3bb1ab2804887784ad17a32a18186fcbb0c9ec95192716298c7f6ab73514728e771b2c1cfe60dc2d10e4b26904f4d1523b5faabc7dc92fbd0113f54e6b4eec36de05cd8454f74adb477d825a0f9be72023cfdda975567bad92b5acb2dd892a45e5241804a4a6242db544ab63949801a3ee9cedd2bc598a6995d6d98b285dcd5a00d894046a080882eedc862c3053c15c104963ce9f4cdc7f9eea144db82735d1d5a5ba1a119758796897bafa6f6996c71d57c803baaad26e1281d5612990144bb80df2ac37de947f9728b274be4402638a4a93088aee0ca3a510a56be902b9264c93f63159486d141ee1f521897d84bfdb845d437c90fbceab28fcc46309b50ff7ba0d4fd26f12c54465fb776d60ae4a85a77f4b2c3e202db93d5411441f98674df2d06e4fad5601cc274dece6a7ef720d26719606400a6f33c033d8f8bec3aab3d0b8033d9d8767fa9864f861cdb8f4f683ecaa97312af1cf442461fd51d768bdd65ca508ba2756745bc9308b2c9b11c642490f5babf263d04bae62ce93441fe06616da5d8dc65bbdc3f31baf4f2676f0d40f2acffb0123eb492a41e8dd8a4ec0127f098882e4e63b737b106acfbb830acbb78360b8c7b064cf3085e8ab1a53b17e0db93623f39461ecb9c53a08fad4789bcaafca6fc6a7f14049b52a8684fd48db4b7fd2fb82d4e5823780899544c9dec6c116497a8e59054eee463aea5a79faeca0a3eb7403362af68d08f5ff29f181df334d7a837f72153d86cf9660fb784c14b5fbec280526a69c2294fba12aea163789bbe9f52a51b5aebb97d964f866c0d5e3be41820924fcf580db0725c7f210823cf7f45a0f964b14e5555070d1c3ddb2c281a80c7fbf72953031a4e771d7e521d578462cafae5a02ac8eb81f082e173ddadc8c41d964bbfda94f5180c8da28a8ebb33be77b0866fa798a6cca0bf3e1d985354aacc6a33d81646a996c2d873f79e84f62050243065ec4fedafc6db3e2185a027fb797f98be2fa49e914207dbe373393452fc5dc9cb22742af30adfc8c6cd1ea97ecede60b74c333dd03322c1943862541a24633ae97090c46013d2c356985542fd738e750c957dec1d3e2f0c531388c041703f6c07ff2a23be8abc19170dcc5b3e1097bd053309143e0b38a6682c32df8f87f8466df7caafd516a5b152550b5a0b4c0222e94e5f1efc4144761bace819cb1296af637ff9d06d6096734e979aa92acfd68b020d08701f885c64b4bb32d6bfb8229130bf3dee4d0f964755fc02ae63421bdf96998b746f8a87587a80997e3122a3d31de021713eccae15adaccad3804dda08ee1a7091b4eccd3ab624a479eaf8215d720a2ac1083fe5c59fce7a7f47971aed52b7402eb55936f2b1cedc30b2e1a5177764e246730f433f738b9a1982c9e376099882b53b77cb69b0a7c709508535e97317d06847e5d06b710ab30bf78a3d8b5de6be8d0eee9385fed7ef6d8e8ddcbbb04a7c904b689532e1744cbc6f83311494c97c1ef667962fe285dcc532a19f7574266f244841997a0af0ee94b15cc6f9f76845d0bb8add50a3da1477056888ff08d3308e0617e42d35a720fb87bc0522ceeca00b24fe6fce8afd21edcf8b9e41b47847344d937f31aac06a59b74bf478617c1637fa6c5593df168b8d58b1e923bf3e3d80e55d7170b16454160ab29ee1f7412ebc057b9585ea4fd8c16783728e734c99d8951cc2d092bb679a48990846da63 -MD = 91293d4167a5ef272fc7d01713f24e25f1d7df45f4ff5e764362eaed32f21f6f - -Len = 41696 -Msg = 87f6c62fd6ed70c0b9bed0699fac69b5b5be7603ac72cedcbcb00b84e9fdebcf85f1f736f6eb622ab90333a9a740a70e770cd02d85e4839fd154715b4b2394864ecbcd8d6a2bcb7066802e618592ec8d092bf43af6cd121218a413be47ba29b7ea6a9159ba17723ac91e09b9c20803da72052a51879644dc988938d6662a730a62b88ac56f16212fe8c30bdae50cb39cba80ba9ac1a5e1a65ae92acb2fdb3a25bd9b02f6108f9ef7cd587dec7605c37bea86eb3e2b63b11764ae2fc42b3646b303fd3f1725ecb23b80c6a716fe5bfc2109fe07654e387bd8c0be90e9e0a15e5a3cc58a4e369425a307f3d181047526331fcf5436b08d099076039563d8854cc271db2bc3ccefbfd66cc9435510bd095c35e31bdadbc821e88c63855a9b4bd694aa276aa06e65487db72f44b9aa9a6c425121a37957538c880cc8aaf5af59c578ed908f0aa55e873fee0c1ed55b74188d7e713639aa941217fd194a5d9e19e0154401e12bf84245c51b4a17d2aab4d6e6c1bb1a455ef57a3e683eaebaf0f1f114b65fa92bef794ab645d078d820c06cf524e798c3fbdc8ea4541e1e332b4bbe1c4b933032126b5ebb7586890e4301a261aedef8dc07b314f2c9a3e1f0d98e11d60c85bb67ea81497cb254919d9edf42d2678682b70ce1d5cfd0b4411a8122b0ea001d95f2fe21d2a00422daadb6c312f258c87e7d91ce99e46f3984d9ac6f63ff304405fcd6b4c3d073d8aa651513dc66888d33551fe228d8b01bf354e1ddf4bda2e052adfba3e2b3085e4aed423966d9ffbbea683d8549549b40d6b4a8d429ce60dac52cf455f8f2ca9c026ec59b79f1c63bebdd731fc6003791752089bcccd7721ba6a24931cc34c27b191027a3dc56e4f67edd491865838cf617c10dfda383de8a3d3683a12822f6e1d9faefb759b161d3eb9048d8ef86a25806bfbbff7777ae0ed111290bd26370b78855a541b6aa46b9791df7c72bb0829d88411c2a0f5eea91ab5ac3d993a038e66f48d1a8bce89a9271adde4ee3aa33afe66fb6e735de98fa143ada7233815455d6fcfc54331465451b6786d3dd1bbd746872149caf9fc23152d9f53e7aadceeb0498adade3d5b0babf7476c0e2ac29d65572bbb3464a6f1dad5e9ca530cdae9243456d1b93d482d9a5fb367bba057ebcf7963592c287a8a86ff1570f1c88fa31d92bc3060db9e38a15254f6e2dcdc40d940708a3ebfd74b9debcafe40787bcaf0f7137d6172bdbb5561a48ff03ac03b375edbf4c8955db3944e42b8cb972fbf62d4051f37ad27342b101a998034c4495e26fdff76337e50ee7945470faf0c0ed7bbf9ac5fe57b2196e02fba0f7528e9b22b5f20b42499b2110f2b0f692a9127c411799b56a62a122d547c57fa569eaad7fe880f0ee36045a0626c9874846f98bc66fd629889a46462df58f9cd5375fb33f300f0d2fa428a11359278ce56f7d0253f0da8a1ea8ab6bc037e2615164f595abb429cccd3c10df7db3506b32cba7c930c12c41f533d87ad4334435e099b43b0b9d55948fa5c3fa8d5bce8ef4037ec9a50c55b4d5e4d35cb2114080497ea58ea7121cce3e8749dc8b7a295bf6be0ae8faf6db4d8563a6f7a2fa5bab55bacf74c63c04e0a28cab6bbf37e73cffa5540f76a94873cf575935eb161f1cccf63bd6b2439733835af09170bb9298d6606327624d238d7969f2fdd78c133c76d9ef9db14e5d2fa9992035e82db1d6449640160609f5054c407b36ac85bf731a0cf5af0c85dd3cdcf2443f6db6cd6011eff1c6aa0645421085fbcab328ac2a823655f60b119fc3e30c6396487e6d9d0515801d966c9bac8ddf7ba0349e61c774001559f51a2b2a87918524c1ac19f5e7adf40511627fab8af702a0770e66b4b9113fbf14c70adb9026b2d01f695ad08162566565107aa7d17498b2c3a144571913da12ae41c33cc675f382acdcb69699d9ad24d89f130828ff45be627e821a5babef390cb0deb7f0264f22ae2eb7aff8bd012cb337d336584012ac9acfa8644983851c763be3b3d8e1cf996e86e58466b45b643eff419a29de0664b4b93f9ca943a4a3330a5b98444d7acd340dc77bab66c2b4c020e59a62822acff766ce2c449354b68d46cecdfd1258a748eae5fd8e7d3e0483c2479fcdd384d3adfedd7be2199e3dca17c2bccbd9710ff146c773d89ed73ccd0bf012307a1f591ca8f4f14b80892033a4c1cc754aceee7849f64351739645e7266759541e004a8e8d9cf6466e1e4710165265c50c762a251af9d7c1a48205193934de0168318c49d55cf29c8c649aa994feef81c871ad40e25895f0d9a365aa6de007feffb90996a7bd4d1581630245474bd27225c85d11c89ce7a6b9024de4e9f23e158da0a7bc2b466f79f523652e57c37760cc8224e0f54c34aaeca6a60dd6f2ea0cb7ee50058b7fc19092adadaaebee441364a7e9f491f0e3c51b98566e5b6872ac27acebb7ecf0a922fd08c0022b53a25296409496c3105ebfeede474fa1dd40bd85e2601b792290f6e13c887e407afae60a530c0eb3350c600c825ff8cfd9bb0778969779579cdfd5e452eb6552ebb29867eb3ba48ae6556f1e8b88b00ee24b51a9d27719b1e6fc87ae51d301882f342e550d08a070aca1b6cb02a9c086825865c09dea42ad8951d4e84127980bcde6707ec35b498c0e58fbbceeaa705e404a096400d83d730c44843a2acf73034d322887141ce80794e20798577208bfa48a063d0127532cf73f5e4b15b2da97387f1c1b0933c508c6a8a20846ebd0d0377e24f4abc0c900d3a92bc409ba14ef143415e0a88928b82d1093b4c1fc10ba808f2a31038bea1626eab34c0fce6b346cbbdb7efb04593f5083a443d38d0fa40825e29b1370fd977b6abe8c2ed6258ec57b369e0a8d9fc4b76a9b5e818716b755a912dbe25849aa5790142c6ebb8b24a9dceee8db0d446feb2b41acd5d06d1af18183997829177844c67cd3d763e51f9f46ca03796a8e6973305ed6d6515cf66417fd7cdecdaf29c974c02972b77ba630219498e98ec6dad7dfba838cf22b7334d2482c1b2a59e46f00a6d8469f94e2e2d5124e345f33eaa0a21c5c009c21b8eb192b52372a5dd1bcd3f7855b047afb40ca0dce63c71fbf55e04e08393587ee10566f963bb402193a557adabacc7318cf694cbf7eadd0847e0016303fa6a53c2cf0dc9f2eaf92e471eef97f6ae1c861191899ca8bf88f5fa46c3d7c1bd8c3cbc64f3a1618055359e8073a1c7329c1ffa540ba979492a4784e8b8b93d4b229c366db51a2019d8ea127060758de8ea51afb4a78cda06257f804c5c71e721b1f4b95fce9ecf25f8ae3b65526dbb2f7bed9a49c9b14b850f0074e82bbc4fefdec8bd91ac99bf23391481e5a5f4ef74b526527a0eb16e344b6ccb52a2d2e7f3fd9acbd9dba580a01e9f8e67f7c59b674aae60cbd30782926f270c025e604fdc92ed6c6ed84cb41b1db1a962b43a3f6590e83dc5a31e592deed1af8dcaeed818333307e72ef9b9f2bafd7b6c57ed5bfe2c5641ee1b7032755ecf3e3b54c9111552fe36c94c3712c57ad56cfb7f39619f719b25ab98a7aef713a230b198a99b8276c1618bcc7f4f11e1dc068686b8f0d805095184a72f3f21b1ed1f8712ead7be130f20b50c4cdf566463c0a40ad68a265b334e1fc3716393cdf2630230174646bc49fccba82a3401971f33ca783c8e18e8ab83c37a08acbbac6493d99cb977aad7044e360c91fdb1de60c8605b357d0e41d48b26376f8b17f1b62a73954bdc58f7b0ad9ac61e9cd5cedb070c206be7a4db30dcae88107f171269bf46d638f4efa2f18350411a81ebcce07834644a5e4b2962f0c2e8960957a2e1aae9cc2b51cd4d2977fd2a204d727d03846fa35b318fc0cd5009e56aaa4817d075c2d37d63707adae407ddda7ff843c6c4244a0911d115e272f9eaf8e276d598b878a8b9aa8790886fe6d87369ebb5acafd8d4fe7fbdbd44e20975eb425280bceb61a86ab76142b46440a6b5cbdb3727b013e085cba41b5725bf229c3a699daf77145efaea9be5d1797bc50bf6256cca6d6bd9498632a4bba6915d964b3a8102e4173904e4a61e72181ebfd07988bb0740274bb44fe80dc4fd16a363e523df49dac0c2f3160e4118b89ff3bdd643a650d0fc94408912ab1591b5707fa8e40cd693c7895fff32f237e3860d2e9d04b34988526f98b261012ffd046163f6c99e4bd79208a610c2a652114768ad2e3a7653deaf2a076c41a4669779e29b6f63181bfea6ad5feb1bd1f9da7aa2b40a5344026c8950270743097c098c7090633eeeb9717bf4080edd0981979627cdd1fdb0c78a677e7223d3a4b2cbb297ed82bb96c6e8888918cc54b19be1007464e5885135e0d0017332720abd4692c4fd4e77b4a6cc62b91cd4316eab3f602513e58189bfe8498594c3acaffe1293846a16e1aceb8581208e86e195321b3b96553287eed8093a776157f208f7a84b529e8c880407bc6a3be884e3d9c30cd964a35cf9d510dc2953735fd0ba2c8010bc150fe93e8dc99487a53ec680c07ce00c78d555f0ecd9aca6155bc7182f328a2d682173d0d04586806f14f83eccf3e5fa603c3aa6ee7a2aebf1cc53c752281e230251b64f91a8b6a280b7f7784afa31aad3e2068b78362a918331f52c47d953496e213f2f247bab8a949852a1cd0879ba5e7748032cb63243341d29db72debfed16106ce41b36eb950526886fc5a714955a5c8da27e52c85d9efe703955a0ba9aa49fce02e852ed5e7cf30726c74ea8c8721235edef94636d2e5656ea82b7e9ee643fd1000e683743467e6d5b34679cc01038df49e30379de6ca54c536c9cb4450f6124601fdf4fe01c391991af9a6718cf20e84b1b18924dd47bdf0885c7a02af0b426a77f309db148a39a5e9b5f9e3f096aff65da5c3327e03a7d6e60b1442ca299664abef4a743565e6e168a1fb8bf5987732eb346e2e92a71a6197fe206b6af9141ce51a402f2efca135dee633cf63a06f20a3851182e1da1e78e55e26e55722c67b6d9b7275c6f6718995ab291801559da9ccc134953345bc031653ae17594db4678a9b68afc4fc5fc5d31966cf98600bb3af0f60cf508ffbeb7304416b3822e5c98542ab43f1b572d1e158715af068c12795981b980061e416449a6648bb48618aa6b7c29b15cab295078fd223d116c5eec484f0580a637d6dd13ca616ac6830903523351df8e227fa8ce71290031221ee85fa6477373cd0d86113883ed1295bc57aad8d3361a6dae6ba87b80b4d03dd111f22015d4f95e5403e479426f234e810bd7e514419bdd242d7974cfb7992ff3edc254e731a15c28baeff5237d930e25845bd09b7e9d117f72c4157c84d66915d022bd31f5f6571a3fa634bd94dc64e875b933ef69787b2ec01ab60d992289a55da5b19cae82cfa6e6a9c0675159e368447287668eb89aa089efdef980f7f2310acdea7dd7b1363d645d20b71fa5fa13751a33c75af7f07354a608c6c8e143375c0dc05bee1c2b6c2d52ce337c4b29888c12d1585a910d25a4efcc0bdd58ed26c5d7cbcd7e2e0fb1960d3152d3b3e225fdeed8b00a2e5125ef2f812f4ae9608ddcce6538f451538c52fef29bd26ac47a4f10c254f63a6cf2b7e7c0b77dfd4deb05643524dd40b77ad8aa7a84e4fa30f3f42b16cd8b1fa11a83ab231af30ef5bcd41bb427b5567bfb9b82319477ccc83181905e6045789e1bd6ec00f046b90881dd575aa8091d419d1038c041276cfaa18be301d3b1bfc465261ce2adf565e6b865c9a12c450f88bddb10af11605538d25785999e6c7fb494f5c050ca6bb020ff11c5102af597b20c50bc469bbf000322891a8e06b212df19ca78c3cc3602379475ec303a97606dd7159e3f369017fa30a4f467c34f23b46228a8c429c0d6ab36e6a179c1a6d41cccae38e1888fe78e8b1fb5bf5a701cc50c74d2da79b8c7ec4508876566a07d3f4b6f0ee5f80b0920707dc0ed12e188918743796f226a409b4d40008b8010c655d1eca2b50badf760af33c889a30fd1aa51291f0aba71cb08be119f44a47449e10ebb76c739c53ccf85c61f1d7157926ff87a3625a85bd1d52611d6394a57727140300d9518fd33bda2c9470114454552fbdb51588284ff8113b527c1f816ca77150ed9b71fc296bb74a1d2dcf2756513c9a0f31bcf89ae8ce5701687244ecc730b9c5da5b491b05979e4451992547bf2e08f9dd7f5d6596939d714e1557bf2f5825d2bd98e072b183105104f7a6ee4a0eeeba4158bf7aaa67f5ec579120ad86f17e5a6daf27f51681888b6d72121498e3339b86cf869fcb5347b8ab6d097e7404aba61228886edd9cee3cb591d28151b5c1e4d46c1a9da15d7b1e713179f9a39794fed38c69a3add92aaa03dd4cfd1e8c7fdd52b8e33bd5907966d266d8e7b8b521a9d862345e2f42241d80dde950a77155cd293a4a430ff129d8f5938d105e633af14a3250650bdec5df54191141936b2bfe807ab57bf68a73bc0340023c3babc71c51852580e8b5f337a6192d9a8a83e9b680018dad3362405923f59e33f794b07314e11b796ed0976c9e66a32136c0783e51563b9f6e8176f87e3bc9bc3b26dd3ebcd19a1746369ac76687dd9f3c2abede1a02251a4ef0ffe13b99eba1af6a36c570da0a2118efe290230441db47c9a4dd048bb5e57bb6c15c83986ca8fa67a44f5986d3608b04590f0066399ffda61285367b52ca9edba6b17ebeb59ac4260d269e5c5d9c487ce68b23332cb106c8f11cd859638f5f68952753962c3eb7ad5b9069e4119cf75f704eb4f682da0b3727eb14ae52fd656475072ba53a5e790674d6dfa7552a3fb6e19edc34a2e2b4fc9e3a100186dc59d730992d7547c0b23942402a2c920cc88820c4c277f691a81e3c51f4da67f4e2c9ad25828dbc2d0b4cab1572fb310b3bdd15089046e5af90a5eb77e9c15d0ca943d4f35175ff6d2b49999fde9d98ef40bda8b16b2ad703139a92f5173fd0ee554c8d4bc3b67a48bc37f324979931807e31c1097daa3456da041913a5db28608fedc07400d79486631fa1edc57763869e404856ee4e65708ceb6719bb1ecd2bff2d55b72f60b4eeca088a428ec095c847f325e1e69ed019d257664f838f28174c14345c78d9444a99fa986a1dfb310f225140f28c23de195451fdfd22b69feb1faa46ab04cbab6078feb2af98b09e23d76281d00864f737b9e0146ac31b9b711ff871ebfbbe51f80d1ac057286844cc0d2ed1c583e9843caa0d94df8c47856ff5059e6685389edc0358ababf4a98bd26cbe1617253bebf1cedf63a4a5c1c3ae48d9b662c8c3fad300c059f325fedbfc9e193a0f15e1961bce5e6a013711bff6c17d9f28efe6cda4ac59b377e2 -MD = 491b5da9bdbafb93924090114bf8ab7ad14e7b771248ddf06ce6cfcd9a55a196 - -Len = 42488 -Msg = b51e73f84965d85ca8ef84b9b2aef2aa6929de10f87262abf5585fe8e3dd1efafbeb372c2c42b27660b56d4e0196bdc0bb6f58c184f273c1da33277f4c1519213c025a84e3e08cd19640475147d8bb824e33966a6aa7282b0288c4d8b19b6a8702cda4a77825ae94d2f8d9698c5c3116a9de5eb2b078c812f5bdff9a19575953d4b3dd3ef2fb5fe89c45ed3fd90a6aa455d97941604c9d9d393c9e6d8d312eae3b1cccf05a49e9f57d8f497a35caad55d88bafc0810dedf5586b69fb141130bfbe703a66b7f792e2fc3eb6c3a9844150bc5bc7d71ca20141dab42ae9b6dfa8afe518ef4811eca3d8a2bafcc23c206fbe88b38b2d38f321aa457ea7e27b83dea5387ab33d711263fef56be31ef6867fc7c5fac16bdde894582330a98c6ce51aca40ff4eedde501c7d7fba3380df9eb992fa9732381369a472fb34f88f90eea445840f8701608e147cc80db38f00516448aff4a63de35e972056f15c94f084c33f8c132721ffb4952456cd2cf46085ca106d78e52254afb68cbbcf9d439290c1e0e171f7f4c4abe59cb363675607233113ba8bb68e6f4449dbb236824380fbe44f0a93bc23b6594c0d6735295efe14e2792195e2293b059838c38ed53dc2ab75b58fdf4155dda7149ff8ad3db44c3e256927fe329cc0dbeac9773f5cd85e8abb39f9bf4d33427d8379f0326afff98b420b562f6b8f06ac89b655b1e0bd5e7f0004cf9aa765ecc4e3c4d72b77e70ee28088358e58a91662bb28e64d2893c9718a3d99d81892e3627aa733022d16922a28084c84c093f7e3c947b079fe03a84aa30de0e068623041914b8e1e54318d4d82b2247a6af5b119fb3a3d9e28b502f1919c2a1c5f7fda476fd86fe7b4e30832d6af44d61f754dea982a15256f50df4e9c1102f3c48ee95e5e755fc514d109c16c273401a7bed240ea3ebe749b7d48490e95edcd613a666da44ae5203da69be28b417d64ca764802379fc2f574e343ca2d4f7512fc28585c8a808960f808c37d7d25a6665046b718c874a90fc12bdbb94368212b5e03c713583fd3ed0ba08b7a88fc376e00d52869e5e6f9294cfc15fe9607797e4f71bc7956ae4c303e15fac1f5eeb9e6a3cca2dfd51d3caddbfffb816e550674971a3d78ccf67b8f5b0f183b0c22b33501d22e61e240f90237db942b157a4f76fda855f7013ee8732838eece14c1adc3e290d3d85277b9902839e8e2d29dddea4ac009df3eaf1c456f35836357f22ff80ead992a6eec03bf76c1008fece63639460c6316cb719e6bf6b1e0e31bdec23c4cd288407ec45ff7e81ae31bac7ee4ccb9346a85f0abf64f86520b34a9acedf766a7a902ca2a55a047ed996c5a8d6f0a6be02614f586ad57e6c00e404985399122d3035899446e225be12b6c3e3a5d5a24b7a0ac21294aede0a4f1ed42912d7249ff9e2b353a31e5ec9fa0019fae3826ab61df33bdbc55783aa6ba25def75102a3d28361e4352752c2ce0015c71187d5c987eb9311695760bd6d73cf63e02daaf7f5b9e4ef5dd6cfa417548ffc8ad3cf46d1cdb26556d70c31a223d31a734ad00f0f489a9ed9c8c55c22a3578741a37beae68c7a01ab5de65eecd3194bd92fdeb1c9396d38d2859db096f555b05f7f437c6f30d12c9171550bf48a883e39643aa6cb9344076f93bd691c5271be0cef8ec613c2a130309cc10262500a3abc724eb5bc5e0651d97c8f4f5bc393fb6f7cc58e7b49d153af659209dd2d86898ae080a845a39d5f37c87929fc4fa3adb1ad4e9d4ecd49de365531e90d2ae571ca363a460d69f079b2fde5c1a6ff891df90b92bb3557f119eff2046a9b4e0d3ba5fde356bdb8e7e672a53add02da2d93701df9afd8edb14b00c774532fa2e72e42bce2a1fc986af09e47e046b7e877563e6bec43de9a71bd9159ea6e702c5b94cafba1ef731261dd5e6c3fc46e3150b08a7dd13df06319b8cb32cc8107f652b364428707c92db4f6dc9bbf1ecfbe9ee77cdc1166b5529182d5d983559b08b2d5391afcb3a7f24c833d5cc81e81964b443e0f1586d66ec163d8d678b2d5686540700a68b9b5670fccac37c28a2dc13d0ff59e4465fabf91a5fcb2125f5d20513c329b34e29a96e6184fb5152b7a485e90cc1205caca4eea8f68f4b826da386013a753c6f6ff87b9b14e5d29c91132940fe9f1c27fed22b2684524d4cdf5b6790bf6bd87bd8b4171ddd2b8662c9987c9d374c6e24a0c43d379bacacd1d55a4836e485edfffe7ccf4e5034c351bbb4fe4259616cdf4cfba330af06f0bdea2096882c4c03783ba302c1108a4fc5f1f93cd4d766bea45dd8ebc620f9af6d886ee0f90936af512ad7500a80a4524c06c5b6c933e4ca304dfc754cb3ed4f6d2a75a60dfdce4837468a457f430b916064bada93e13425ffb7c6ee58ba5a47396ad5543b9c8b7477192c51b3ba38739f963936c981fd487f05d8a56eb6d92d5ea41e8a0647f6aabd0d3de33c68a37f4615d149de78a8a81ac2a238f33be2684970b195f292885155bd5f987dd0e51b105e03824747cecb6f78a4278abbfe9e865b2f26850eb90efd83d1dffc7575ed7ae9508e9871c838e9825edf99b9962691bdf7ba321f114a010b65383ce8ce6ce24238bd46892d67259a42ffa4a731a708339bbf9e4629990cbe6a2fb38d56ffd2f34cace5e076dc800af0d63017697636369ba50e066a527d175124f4e5b83ce976dcbbdb2a3d1f956ed911c08ca63ac841680925e23c2cde90cab675846a9a82378988bad8d896e2307c20da79606b1aee916a5a6c477eadd53762b9ebe6af39dfd391e94ee1d8e2fa4a81f260206dca8898373006f4ce673f17a8467ea4c18cba3b460b2ed16c0416d4c38cc38ed943ca0cfe2b44dca29748fbf58fdf2d97d751313374eb3fb6e230ab541e25d424030d303dc0985781ba7d44e91a6ff998b65f55e8daf6754ff9b22eb23b09c8e4a4dcc2548483fdf25d6692e15ab3913aa62f09b491e32aadb725df7c47e1b58195b33400dbaa585adc7f567ce54c7cf4333acd453e33c836a7065e00e9402281522af5915a4dcf41d432102a2e8d155bca1d2109346ac6a135cdfaee8397a86a669e97a47510fb4db1295067bb1812e7f740a58f18faae441ff766a39b7abfb34fa89aa8b08644b51fcf87b40f5fde1f274fbb35505607b5922d01beb54bc0e279b36f2c9100343e5c9f26ad9fd6df67f684e29a7f1f4b6c48b95c9e559d548e7159858e9b2152401402dda2d11faf58d1aaac2cf9b8e1dea036e7c0f0e2030dc3058e7d436c2740c2b4ed32678cc678350b887b54b57393351033d51bac24e6fb31ea470e431bd6e50005dab7c0ad4cbd3207f41497691083ffb1393a6e62a06689199a6038b868e77e981a563dcc2cc6b89b25cdc14aecf93fe07bd1bb24d0b155acd5fddf758d66ab146fa766bbbeedf9b29ec4e5916f216b620b75f4e3ee483214881b89ebaadf001b593fddf4699f9ffebdae56c53d790c86669bae385fb7a8d13f5dda8347bd081d4584060ec357f5d000fea76ede8c9dfe1bc7699abb6c24635a4943c4ea9d3d8ad318614332a3a5c7172a49e6a8b88a19a96da97377f22f5b6752582919dc1ae48071926a6e1f2a545ea5d0d542a97b698e12d06b1bd63429f4fd7a384c062adabc03fbccac06fe084615bea322cbcc7e383b80da1d74dd4f71cf3c7b07a7d7be04641ff293078b437bee85e8df9c07c8466c3d59037a854c6c3c1159b34dcc0ef7f67164a9ad7c965e94a91ecf96a7c8270958606443c69142c89b6cf544525de55f829b56452c816c9c9aad7948470e58b78478966d1bcea3f93d2d4448151b7af3e62f3f8b2595248afd2d632d4ffb69eb240a3052ef44fe42690306a58ee82747fe78bbcbe23224d4230723b24d2fc908c9adb891cba4c038c186d3091a1458e04e0051a40cf8dc1cced32173a90bf4b4e7db95b63b6e8840b9312fdf6140ae41576ea79fe049c8a93309f2edee207b64010c6e1cb8f2b4fec29a8384defd85ef9d0c040c26b5691e0223fe8da70ddb9aa7c89841cee1d4c7701b64b5fd9b8e4fa1812d952acc3befaea9daef5e1483cd3e88bac1d7ac764f344c49df47bb05e5e7365ab766eebfa2bb23ee6f6de5127047d52c297dc307daa195b96d47dcbb46e0b431ef859d72bb99facfaa60eff628563682c52bb6080e2a9029ec6860ecf7208339a9f168e3aeddb6e50cd1a5ad69ec1555416c06056e41b411d933e8395b292be87324d18100f8e0c5233a96a6997bf9fa0ab9337e5f898a07b034f31ef75cf6a4d7aa57e9367df0e669f643804b787d07ad8dbed176548a820de5e20c505eac2543fc7c7ad3cf7fdf6daf2cb90473e6f4966408bd37552e075ec165900a8094b05485bfb45d8fe6169adfd2bf38f0f05751e6c18006edfd0e0f51ce386a7558fc65f082343811bc027dd2a6117d7201966c5049c88991601cac01bc6414af515004a76458e8076a498352374e26799338326b320523e20fa9c16b90b18d811651cd24e6c101d3894247c906c3e86a3dc36081faa46a52443bcbf9eb9f29bd30880bf389db09f891933791852127e669ae732f0454c154b65948373d8b9d9618596d9dbe2565090ba2df5642d469509f8fc6dcff64cd8bde78a2ae07154dbe364c5e8e042ea7676ff7ab81c05c114b47bde8164c72e34a151087b8c8aabe9822e74b3eec6555a6270828ae7e26d4391adf53656bfda721f2c753f202ea64a656a0d03ae747d447d96ad336dcd3169c515a9544de639d961ff393e43622d48b6a0f7a0c8564b7beff8647a57cdf5cf7b3b63a2f34531b38c52bc409e3028299a589a52e374a749df1e0d294deba1bed9a889e9ede3ab46cbae650dd99f7f363b1b5ee1a7d47af475911206f62e1e7c07e385f1e6c990dc44999e6c9bb71ab7c170ab14be80aac5dbd8d9dafb9e52512e74bd8284fdc6bb1f9dcf278c81e1f454e0e9b4cd802104367bcc6c0343268776e49b646f89372b85425e045504bd341af280897fdac5f9b1035186b726826506ba855e5074c9769e0fb4cc9e4994c13e2ed85b799880ec71f7d2eebf4e4f32077ee53acfc766e3918c39460e5650e1e61c59f266c23924a1dfb66dc2c37337a0b922be9389f5b98741553c4e35d7dd3b456c16ec5ed8ea674465cb698ed8bcfaf2a4b345c25e41a7b7717406ee13fd6430778eb3764486ebac47d05bb664083cb1d3e08c7b89c31a75f3b8dd87ea888965e4236411674056a2c444404301658f7e170f11bb5e86070345ce7b0a46c8d46d199da738285fd0ab44eec23e96191be2d8067c8ac5d497eacd7e897e0e036bcf80c423f26f2d80512f9787ae0b6d07647e8e74f0a6f3f1b1f592afec2a8276137f5f814724f08f1bed07379b48a97c8d716fa1f6e92c3fe024d0945b818d1ec28038683f30f12591e6067b0d3415a1e31971aca376c7a600c102e1d3fd6b8a63ea1581e37978683c825cfb0db9f99ff0df5c3d00350c509836ee3d5d8566e47e25bf743ae8cd83a32ad05ea2be9c9d3c29f7fb130e436530ea5d51ff02c4519b99fee84c65379c4f442c4cd52c47c44d600b8fe6eab30c504516c5c35acefb43ae998622d9ffdcc63a366fade9423caded60a081afa56e81afe340b176cc0afdcc5af5c32a6e6a9272b76c32ded52ce436bed7ea4761b34a908a6ad03e06a6525b07dd3742ca6f3a5676ee6cf348bc78a5eddc2b982f023450d4ec289ac3f5c9c369e887075b12474c3d9b6411e216f3a1b4564c8c5783c657896ec1734d22ea6c48bcba636b7c40bed21b211eec5fdd91ddee530a2060880e7197a4afea533dbe6c01d83d40d4ad13fe17ab03aec2bcdf2e4b4af9d4be02db5310d838e3b14b229c60ea7c234317b389370ba970651af270163843b9c8bd27f98065f480639bfea280f70a5cf105063b2248f77a707e326af626cf17a3405b299054cd0891b5bb440b07ce3305ff74dc816ad4130c7107e6941b85387a13ddace8acaac56522c24ba623b0f0a78d6533fb7a2a85617ad9aa971f4d6373bf174a2f7572fd05697a7efb5198da01384109397ee01696211080a83a0fdfb6cb6fca0eb70ff999124aa7b29b6e3a38877026e281de0fd3ee142e6f75b3f56cbf4ff62c7b68014aa69c8c73091a5877035a529f880cb8426a4e7c93d721edbd241e9432c8655c3facd7f7e5a2857ce4326755189d5258081c2434bd69420fd080446dc7a7ee54a2ac62aeb06e95eea79e00f6f4c79838508cff1c9432fca2ce5e2949941feb2f982ea7797d7533f5e9cf8bfedc0fc6a1404348fec13a38f0de4335f0403844364bbb0d22f4c048dbd24c7236777bc4d900c865a0eb89df3f29b9d02974fae2b1e3dafc6fbc56bae6899d1b636e167a28b9a3c0cabb28d7d8d74762bdd86eabe88714dc2a7e3f735f374af05068e5d0d8935dbf46d81e0a030f765375139b882260f01619e184598e03db57c40ef2af30b57dccdbec735e08f9cc0b17ce8a61a996f610058e2c56ba16d9ba860844fd77488b4e509c2fbd2ebed3f26bb0411fc350ae33b52c3f512c97cc805ffde3a4f67310ad6e925b0ebe8613703b62caa8b9b6a1e7f364c6312daf3a111795d88af55f9350fd76ff39007813ee4d8b2de6d3f2569585dec7e00386add576792a99bb339ca1c5ef21253cbd5bd26ad470c0582955a334414d45f643ac344451e1b79218b3078da6cbbcba7c73865ae59d1d9286277bc8355d48500fc09648c406cec03661ea1f4304e5c1dee470e565bbe7c72e5383096401d157116f634b7b9fc58eb42db2416dd5889b0b34fad3fdd305404c6125bf7340c855724403151eb78444bba0c8bccc448e8e2aee8beb54ec5f4506dac8b10d23159059c4de6e5453f32a72409257095cdde364978af6130edd1d8445d3a8d8b0a151ef795c1ec57dfa88029879dccc225ee2e0b961bde1416712ef2ab06c7cf152df5beae6ec1a3c81a5922de611bca0f9d2c7db7705678ee56a6f11c6c5a2ee1184c69fe2a1fb9970ca4b893fc082dd97fd408634994cfc3f6e2b837d7bf2aec7865821ba050f9aaf3f5533edafc6e11ea97441004039945d664c073d5513395a2e38f7d4e0ff4a264cd7b359a72fb5781f8a9443c1d65d279af9266e1cae97b4c48fa99afa72aebe39f992ea6f65608ba7ab0765e5ca5f86515b6778986ad1bb9084c0721b11d05d4de55707d111ea4188ff23ce74bea260d59a52c491f0ed59d940c3c60a84b7ecd1c08a1a93db5c800cad6fe736592f9f6cdd6fb8cfe7f675e9eb3afd90726b540db5b38a7e6abd3279de7416f2440d295f4c47bd19f8f1f606acad7f7584f57b49e95bbf5a67153e18b9b8c4722644e8f611613c39cbe8c679aba5b481615c4bcd870921ef796c8c3167c55a7ca8ddc27851459bf507e2cc8a11aa047bb1a8abe0b546180449cb040c0f233ed972dfa12f377c441654e8f0800642d72d1ee182cc9b990c637e398ef0da58da512b526c61e88d9d645c011aa5 -MD = 787904b92d11b4be88c6728765190713532d134f7e846925f9ac6a6667ad7df0 - -Len = 43280 -Msg = 783dcfe6eee019b3c5e1c3e9c63406ae0ed4fe7dbfab0026f5b22d16fc5947d9c029c4dd84a82179d77d792dc4d4562c4a04c7170c6fb30c48aa6cdf0ddf87a7a96fec7d61db298066e40c1d04f1708d1bb2579ed30339b78c139c1614c5e55d1d566e4dee41d8d1585fa33eec53fbd96b25d59a7e2d3b2fa733e44478d40802032772d591a1d7739736661ae5c1a01821a66a9174b6617d83536df0a1d4999e422b229eb3c4cd6e09b17e3858050753257d3e0d1d6652a807ba5fa2f78d3f3ac4a7a42fbd7363cb98181320abe5d7925ff27895e104b7b81ab2e1e3e2c6a3dc70e62010157441912bb24c5b482ab9dbb74d41b2285a37b6a6811b39ca496d8f2e2fbfca258f0ec8a9c85270959c543815d5c0ea5a2e7ba99270362f17dc4458e6c9a8e4548e7378fca24de7fc0251b061d31ec8df492a99c6c75a4a3148d04180fd05e6093717aa0b886449e325574b838f82d11f73ed8e29ceae148054ba51e513fb59ae54a366bec2bf1cb4ce0f126351158f83736c91a5cd5b146dcaaa90fb53b4c4aaabbeb2fd9787ebd6c3200ce961fe8971134ea9210b88d25e704707ab0458af65051198b051e43bb1cd3442fe06664752193cdf86d15ed7bc103abdde700ea24729431fbf36fd96adb3f0ba888a75528f4edd3aba6705aaf0702aba7addff26b8e1fd4f128ffb83323ffe7e703352318e7adac2a615a4d36059c007689453c220f3e73192a3058ba83706969f4a266cb965da7f322364db7692a4ab91dd31ffe728a8cc25bc44347764af08fc16188c77d6867a47d86c4999e57daedcffc1647548e929b420e009078ea2de6ee151182f9786bacb7de5a53018f41930442d79321b514e2818008fc17c8720dff1f9984b6e8147a85af678a5f4b0f377f29ac68768894567eccc500bf805d43690379432241f2ac4b7c8485f415a44985232d4daf938165be46dd34ec8c4045b0433954c81096a09dc82a0c6c799157bac1d2a949407c7ea480ba0f3b56db735951622014ce70f5d104d05424d166d084883501e029e62fe5fcd406087a8f6ae8d08c4b94f6022aa9d51013b9d7854276d8bcfde0ba4ee7e72dc3aff061cc8ad323002dc501da9d7c9b51b197d68d2c0655d2e3e76c27452c9601637fa72351bceb764d218c6afccdda2dc44b68ef0bb7622f5a50d9ffb62ac805d6f2a5145dea7c472036f023971203fca251091b500e902ad7b96e48b96636496115f6201df0580b5d81c7951aedcb56f22521a2a770624dd27da382cd635354984614d70063213b4b7e9d4fe6b572b53a446d0550914b10d13a144e70a6c1bfe30f8b99a3c75a4f7099cbb4990dbcafc14b25c409c5dd0c5a6b3afc31a4e3d3e7dec4e8867155b0737fed53805aeb9f4d85f65f31927aa8e48d722c9ee24c490d304b541705b616ba7d7cbd6b21821c35a15947469bb67ef61d745006e35d77d9a0996cd408fdeabc3ef44287f632aef009b91cd72612e715979bf7083cb9f8c3ac49835bef9f950f20de93855d5fb0234bb03061e60279a99863921132c44451bfa6480d1e0dbe19bfb620d1ab8bd845d3b922554027bf587c55a1c07a1ed30a576a2b6638eace6287f56afb85297fbe2e4e734fc8d52078c00cb684872c2d641fff9e05b4993e800626e2715ecb2f12d7eaa3afd4ad35a11fd330dbde7ecbe555c1105a05ab86e8b6b517c1bcd36eda5d18340418127757c853b144d4893704b56932d1c0944003164a7b6b03f4a78b2a4184daf7a75e036608b84e2dcde7589b52760b69d5f265a131adebe881619bcc114692f7ce624a856ca6563ecf654794174a7566030696e4250fa2cf1c3582bee1d9ca9d0a2c8392fa0bfb7c0039581c12309e498e050d5b7f115e2c279bd68f4dbef05bfd05450b2b79bc8a02cc10bffdb8f498e9664f73ba634c8435fd1d99bf8692b8f995057a9b4007dd4995f7ec145406b8a7b2b3d951761c6bc9e1be7aa191304882445b5da42f7bea373f742d0092433d3b72f0d8feba3c4745d23faebe8f376f49abbd20d07877357e211bff4ce4389b371f8d0efca03aab4c5727b240d146a192238160cabb884360d365df43ca65670d20cef7e5e8760c4fe8fd01e307bc941e546e99ed792da891ded849afc54805301f5d0044c39ceec2f0263a1f83279b20a6cb38a331e5b9739bf9cacb655f1a4263bdd493f21dd7481549b750d4064b4ba33dc996663f0aa8a330df311b28fab6b647d14dd4673a31b0cdf6118ad70911d21cc931969820838d13f37b67244b0f6fa172eceb079c225b2992ec181878f5ac0eb40f339f7fa6a219a404d9df7faef851560bb67d819c9cf30a4afc590f89a98a2679dda39c848ac87d57d3c90d27f8bde704c7476f02dea0c8b8b817312042f57d2be542ebafbf96cc0ee55f680ce96da2628de3d8f798b95abfcbb1826c10f7347ffb0c018ab90b2c749f3134c032d714cf8ad143dd63a33ccab7d677bf8c05f8f08f5d6297ffac2b3361bce7d46d90ba863e9e2446c804eb53fce485bd2c88272802b5736a0be024b5cd70f5dc1201004129b91ea62e44e2f61b7a30c77b143b70f5b2d873664dc59642ebe32998de826accb0878e0ef9b02b93e60d70e030c285e8c3f646875b7a3f529c445f9a5fbd6da7f2f3510279df6ee6e6704bf44448b15c675155e78fbf3b8ce07de07f2b2de44c1ee6b1816bcd2a94ca0dbb4fe52a9dc11b7e141f50f0f55277045ebfb730591982d602044616091e2f3a412b8a04a5976ed1239745dbf733ce7c1ce48a7126a0dd45e5138f2664f3749a604fb953537fcffee6d7e4ccdba13559bd862b7ce7626cbabd27ad9ad8a53882ab04e99341cacd5be069a44ffd4b6a01c30d009015eedfa8fcc927cfdeb3f9a783e39140db18c58c92b51ad1f662db289ff1a0772c96a4a546709451e1a0265d8d7446e899da76e59052af0f31b7e712d6cc918eb60a4a140ca659bd7bea4d392a3f81070880200b4bcad734498b3c74fa064a332cba3e99d1e31e5f17f2ecbedc9dc608a1ca7f72377629fd988d49b36c2731211b16f08b18af28d3507a734327179c79ffe9d39ee5ed2dc7c91e7d42bfb7ecc4dba11e8c53732fa68fb17f8aac555ae76d9ecb05d9a8493f35bf65c76730e39b18f906f204d7894550686fe9aeafa7bd8539d42b853002a078f081a5f51aac104d8f4870cf34dc3c3cefd2e4d0bf0988d14b6d946b0cf0b80d526f62ebedbcc0d3c4517cf5138ef79fb83700a4ebd6b5dc5425c50da789c26d457d82ae128c295648c06b290c180403621ac18dbeb5e100e46b31ef98347c135a3a89ce3190b64f8d13efdd870dee027decac0db02d76d96ccc6f8347973189f124ecceb360f429f1aa6f850ce712175c2b24a7688403d06db7d26b3e187f4bbadb302220837f7017126eb2162a2cbc8d54dfed3070048057cc0ef9f43ed1d317bbd86af16e94ac7dda61d72b4d7a5ca2081231b067f563cb6779d20270c5ba884559fbbe88e0599670ed76c4d797821aa3703750e252f53918a765d164c76c9d164976e078fee1e15466137b4f10c757b58e40aa65a9af115e1c37f9815353b69d0b4effa52cefff13703fa71a6296f9cca0f02568661be4b64cbad33cf61a655833f6749416ce403c705de0dff97b61477cc84a6114a643afcd81071e2c2b49b637ffd7dc3927352dfae0a0f661df3eb4563b81f631e88ea8f30d0d9b7200b455abeda1d3f0657e66847a6ff4285ce2a1e1bc748e4a4d564061c14f3b443535a4f4225b11f9136c74818dc66fa95eed8e93dd9a9fda6f0af4ae4044842f335e3295507c2cafbb9fe6969d2cbf816fcfd8e1115cb14ea84d342d0c95fcaf758e7d23da8d7a80c8791b182b0b6a3cf9fa2f4dfa435933a37d9d5288bc0b218666e31422f78218c498b0aaa9faf638a80cd05efae6fe05cb1c8ed3371f4631e04812eaec52d9d42a6f15b2bc73fa00d4789a8885a0265189ba8713aa48246d1dc26b1c7917f84f747cd8c4b4fedc2219bdbc5f4d07588389d8248854cf2c2f89667a2d7bcf53e73d32684535f42318e24cd45793950b3825e5d5c5c8fcd3e5dda4ce9246d18337ef3052d8b21c5561c8b660e60bd1c4dc087419407989a24c64edc6ff7cd6ecce04f716e3abbfe979378ae09f18360beb8bf36d8cd8de1dbfc9d1f1a9704816f608e722fa955755dba92ae1e73b4a46d33af4510f8972bcbc76d1dd34e39d985c85810582118b3115a826d36307771c4f8ff7524ceddfe5cee67df836294fc77de5754d2e82b3f193beff3376ef54d2ad156cffd9888e5f63b326c101c3e74ab6b30458346b7a1df2582490b7655c307845c59819dbf65017476cc64c45fc98b368eec5485e462c9e0e3769890c058c4daba1d9927ab08e562dd0865a21e817e09174f2decd9094133b982c8035e96c79b18232e7c73550acd0d27fdfda426ebaa7378f7c2bf1eaee8ad7681195604798f1d7126e541d4d97dae31131f193f3ce24b6f9850bd2978c56659ad18d12a427d72116baa3a0eb839692f8e4ea455d879473afadefcb306938d333349f6918b2fbf0be313888a10cae62858d36def27370ee303b3a443c219c90dfbf4eec0ba6bab65786853d04af9cc2458f69d9591e449729d19dc621321c3eeed61e03f39fade2911f0c269cc8cc32b76fe5cd07e479fedaf56cc97617122def1d7f5976ea4015f95f4fedc004b75469a35d1265629b95e21b39d6a15d38fe5efa0554fc330bc0deebc2fb14d00877cace1252181523eccdb787763950cb20ccf0227ef9e68b63d03907b711a71a4d6944b7f49678ad740c4ed810b4ae7325a79469400691298f6bcb80da3d167725a3abb082571992cc1c65ae4e99c2bb8d8d5b3c3098bf70941017b0bcfd9aa99128778e83d0546e457c806c786f49feb8ccc93dc926cdfb225ba239e7e9a02c20661cc46198d5aa80ab33a5368b80d7480442c092374923aaacff6ed367c37953db2fd4a426f9e1fe36d3eb019523bfabc26c870450bd74bd8283d2182e710b9bf60541e3f15d7f2e9df5a052128f126465bad397f99778ab8ae3f61e74357d7945419e798e5d0c825f1d67a06a4f9a028ca238d5a863ba1514746d6eff8d296c57794d0d649504a9d8cf939522c1a0f6a5a74945d3ae838abdc98a7216e4a9f58b00dfe80a81e205b960c678c2a1b1b12f5e675101e49f6cf567efd050d869958e6cb9c1e6903f167f9572f3d05c56d2a82c359fb982584c49b4000243e502dca0317d038f6c765c79b22b7ec25e0adb9e85167a7114389929526d705676e03b8ee39c257b632258566b52721f23483c811d9c89bf26cae422a78ab31f2a9c2298f799c02110bd9a94057a865d488955ee4a2a35fa1689bdb447da32e45c91226ce1e83c26f1c29391352623e33a58e8349f6217c88fff765ca7ee886ca969db69372a11e382bbb3fc6ec7c377754143f281b6a790df96be9a4c3a1c0e7d808e1c6bb1e9ed4013ac2416e1ed5085bcf9b695aa5de9a1d9e6dba94f7650656feaf4f4222caac664ccb6c2072a24e82699ef5fbfa34963439fcf43912fc8ed92529164fd42b262299612f499d25b2938751b24692016906e39b3af9190de7292556042a5c48abfcca8c7232cae69a54d4ba898395d07a5b4554741e3521780ea73fff1ae3a9a4bd87541d241f6e6f8ff5e362f92b2633fb062e8aee8dbfab5053eaf06891d7772d77c21865c4449a0a95d426f17a8dfbaecf3264b24a6fe7b6d061c05d8d598e1443dd4b3de2f0818e5a94bbb3ad8c3a3b4866eab193b99509c7ac553f00b74f3a93ae9ef6a1fb8ee2ec2a0b87eaac596b18d4053591261b11dfd19956117a24670d3bfad728ec28d0f4a1fdb55973be06e8849b846b3de296c1da73ece92974625c8e4527a04bb61e1afe7884246bd2d45f7c95e74a86526014ceca47af4ca6f426af692f30a1a295054b663e701cfd9c26c6dca6568ad33681b688b08c6c24e514a44c37017453fd5e90ae29680da828e46a5709b6d0cee2b099946fa81055fdcd77d8863b4f311eccd3388d31c6393e426eed5893e1a92a487fd6cc2ac0a103fa30f36605b7a4bff81eecb4f6cf1aa7e8dc88da1443ced7f271360f3a0470c142d5871d873614aa8978b2e5ddb1b12b7dbb0fd86280a3b155759c7f02652afd4e707bf4ea53e9a528ea72670ef36891aa14699aa420927f1a96f065a76a3780c508b73356978b797d7a1483b21da6a316ee806803a9020be8d91a09549c001250a62322f28863ee2f328081f1b7d22769513b8aa7a55b1b684802b32f81eb7a9751a709e7b0d7cbe71a9ea9f24a56e64d468247b79b047841ea91ab60a3618241112b2f5c9750da4c395742de5d99a868d33de95c1467ea1cc7ad38108acbf0f7ee97dd7ac337e107979196dc790334620354b6bd97eb38a1e83fa467bc8f8d60f1d35b69bef2a9bf3c35eb1525fc54e4dbb0f703acf82c775430358cc317212521c7f15010ebfa1d312c8ab1e9ecce966537f355dbf68c47136634a827c974ed875ce7573f889bc97d5cbbd74d3b6b1fa8d2f4dcad4d21b82ecbe9e26e0f4d61297884a8d533566a28afc6afda51f328ac6a40bfa966b373ac469b6322507628110411685a53f1a83b0cf26217972e587ae5202758a70a1f95be9352caf3b5eb47e9d6c2544f352dbd5a88188d73e458192ddc3c4079ed65f21d1ad8ef62d352d10d1bdc4d91ea9eb683d0f8c24edccf9128bc25eb4525edca4a761d18049804b95a28decc80d8a62e6e122b4091df66ebc0080be1717b5e252def48cd41cbaa07b744f15a84c6eb2e0396d98fa2b5c52edc0715a867b4610baecf82978136ebc10bb93d7e057e15bd2aa32835eb26936263026cca8d9b9d85b55cf2fc2c9f70f140cde9c06bc6cde4cb8343bcd2fa788f3f4137cf4df7bb9a2ae0c186aacfe19e3dc91da81f67bbaace7c50acc1f81ebe570c9f3d0e8f6253f5a116bd648ee5d1eaf503bf872986171bd7788b1fe92af793abcc9e372c3bb6fee81a28c0a324912f98c08c0cd3d6339bdce2e354954740db65e5793296edce2efcf44f27d847e6f4fb7f97162f550734d2b73bc8c41ba317841357669521a06b27cdba02f3f6d8216766690e03a99acf031e1ce33e4e272f4e7dbf3bf17f369eafcdf2b7bdd8709e229d895a187af455b5400d0dca89d40b0c4c391971ae97b0dd1b7eb0fe96b553744d7f6436711eac314496ae3274b39405a74d68df57cb87f9e0e6537ed7b029a79ed49324351fbebf533f2e3cb6cbb083b784900121db0d4b43b30a0444670602b70f4eac6fff71a69591f5b1f72548cca365f99fb5ce281a6d6c3c5a85e4d4ccc1b8ff94c7c7af3031136b58e1c7452994790c83baacc2b086995046412f794ee3580da5e47e5fa3504ef8fb1abb8de2b2462f74d97dc253b5c2b091204edfd04676e0a76f2c694819c805604a090a3f2456cb39ba4a104c2270c303cc4bec99119ae0620fd9b467b50bf8501ab7a2881331499b041a94e3f62af163ea2d8af36d4c759e6d8e2a484b9f3b9331cf3f04a65d0f6260f6365f5979a27b25fda024821507223153b232040a34f13958c8fc0664875675e5de0a72e43e1122c21575777cfeb7022e346f -MD = a42ae5e146b8736668d7836e5d1fe82e5525d9b0631ef2a8866a9a492b2fed39 - -Len = 44072 -Msg = 009e12ffcd53e104a45c553a8f3353fe4b283456939e25caa277cd75f3cd315b4be3d5fdf95b242b5ca9121aa7c700b6e12ae03930f699fd566ead8e7cae19042f9c7d90a81c7c5450836678834f147a941514c512ba07864ae646bb0db6cc8cb4b150df60feb12787d4977cac3158f16dcf1822c354350c86c8e2222f4d119de20a9713ac698a4b0982ee50a9d791c473413477cb2aeb3810fdc7eb69dbb1dcc290995311c5d169de76b31902a78a9aaf53b0ecb0a6f3b2f26c3d3f44c875f35b29a0c8197a4c280f992e02400b0a1c27eed3abfc2e142134fc8e46477c228ab5bef2994bf0c431a2d2a730ea6ad8f2e5f8e6d9362c152ddc970027fa608348d938d8ef2f8f002ba20865ce882bbdc3f15b31a1e707bf7ff424dd0be5da5fd6ce7d9af24ec0cabf1425b102a2b8813751fdfc299627dabf838a6b1991537ddb9c7780c92fe9e8950210d3f4c178ecf70fc88f99cbf42e9592b3f37a8534a6004c0cd29d5b74235473b113ce6cd3c5ab33a2311a0fd682a72886bc5549e3a2ede526d79558c743a470f0b8b52c31d6fbc3752cd4e8359fa04deb10d366ca39496facd8dab04c102f00b50cd388fae58dc928c6eee1794e2609ca351c634f33bdf3861d93ea69529a2be855500896bb0c4ca348907f0a55e1650b7457c8dc57f0779ceee98f88d090f971dc54346e201e55cefae44c507c7b689715ac1ed86e8b06d69304261053b77338e90695e8dc6beb91230fcfb48d991b546044ebab4035a51c530b3769a3b7a026c48eb26db69c16d40c3c909c4ee6842b9d47babc95975e5678274bfa88398921b41513667759de7ffe9118718907ad0413dd10753558386c487fe92dcae5341202c34139e7494c7a3f36ee9c04a79ec80b2c773de8213c460c3c99693062abe2f7bfc350ce1567ad17549a83886c5e5dcd5f767c759a70cc0b85e3178359f677d9322111f4653800d013a590dcfef4ada19c969ba56adee78f83509d8b711bbbf043e4e621dfc55cb19a962aca066b9fcf0b5d00403a8e7dde5d676410532495861b93361c2e18a70112f5b8182cc81a9ed655140eb18677413cb0d4daa618ece1e1b668aef839cb09a24ba48f1715085822063fd678d0be0048b455b01300aa4abed6e69fe62eae11731e55f7705a50431af7ea6236743963a8fa505c42e3b609da7a17b79f013a60adf93318de9ddaa7e3b07b789478cfb2850b2ba4dac9f8665c2a63bdccba55407761a6b90ae88ecea8b95ce13ae66a34066d505184bb58a96c6e327b145fe9f7f9e016a49b4254ff8f9bf365cfc5f13254aa252be7bfbe1934cfecb720faddce5cfdeb9f3ab41481c0ddaacbfc1e4bf4964a14f9ace012ffd9d4f93a9792190dc8418d738f44b69d6407e8dd68f862c2f5d384857a233ca38606c2cc223085fc643265e841fc229ba3a11461bb5b1de499cfdd95fa92244d61ebad3469db09e3595ad9c5f9e440c3a43498209f5064a1a9c586f2d334b345920d233c139b8d09ce4152d45e03f95c9047dbe2badd1f434e3ee964ae11cfd242f48daac978f9b7ec6d39db196133b08e63456eb40d3610afc16db23332613e99265147327b3535db68f4a3d106d705c70f3e8e36e59251f5d67aa6099e52cfbe2dd9dbf7ab29cbc2baedf42ffbcea463d32e08e86f194d47057806d95d88ceda918b2ebf11bec1c9e98a95db47fed589377da571b2b44eced7cf9b4a78ed8314d8d10733b3da5e1a7f35507cf251e061c4932d7ab64c9ab1d3e82d05f66835958c1230fa9b66ebda0455ebba05ae0c1401d968aa84c77a19822984b1dfe02d8434b56fbdd14bb034fe512f3f87fca2ca77b51eaa230f362e6afb67f73c3fb40a59248d245b6ff54ef793e4b08025eaaaac9016219b0a161715c79f7f146c104f82c652d643bc02507682d2b8f8102cdd2ad319b8f5a262fd0bf3f5f06f4f897a3703857c91191e630486c0fdf8a5b08b79e4ef1738be6107d2e92ef355d069b40143f0bd4b6d93af2807782787ccbdda1f2d60e56c455c5ef40f152fcfd7f62466ee59427ba2a75b6a6dc0dfae6d9df5a61434ca99219b29f9cf714de44c7af3f06c89b3289fa38f522161cd7470960296033270c8396691679009f49d173b48272648b75b4ccf7569892398e1bdf12a7561237c017505bec8b9a6cd0020824c92825df61b917232360ecde8fd3df694cd96cf994abdbfd7a3b4107f18509626b9e992197056d5f141182967d1d6ec69250afe6dadf9de0581e80fb3ea8dc1ff24c4adc8628341d81310fdbb64711dd0062578a03111a86fe9bd6b1180c049ff5c7977aafa00fc0f335c128cbef7cff2f74f04dbdeed663e639beb40e1d2774de872b8683fb54ebf29663083e84e4bf680f06cc6bd765f9977ea59e915a99312501538a93a8b81107e951e47e960d90529707608d592dda9ae127bb3252fe5751dccbe16f168dc29b950a681c913c0477b37eb492f2a26958f7b1947184ab49fd6fe14576e36a63362018ed991514ae3fdad9233d1278386a38efd4cf6e44ab803120013b9db2855020f9ff64801bd02383a356cc56f3ca470b1ee6bc7e4ede72c724bf2d841aab820e2a181f60b62cbb2479a9c13ec9916804db34c9432e654da85bd9ed54e738344e25c21a3568167f53a8a6cc184e2055bcb159664b67d2894b31dbcb7eccddff677987f58cc62fd897dcd83d9215e988791dcf24058f98be36435f78702fef4bf091c431d544cb6f4762b8b62aa56f88e09d0072f00a4a44e00cbf44c774fe92600b114f8d689bac08f6c296507124cf89ab87e3996c49c5defa85e0e3508e7b4c41f9af33b5f30742f5707e920dabd4bab5efe6602a29a989a94dbd6237115efbd2e7e1569174099bdb6cdf6ddf67311a68830bf2c86c788675613ab29d29c6153a5686649f814b6a34f239426ad95d1f2ffbb4bfcb74bb4bfb8b0952f72a392ef4effefc34cd15348eaafcce3494c14f78b49135b7f4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10bf611df37f1d2f24f5e1b177b2c9db92d44ed551d7c62669ad2e6f4b1028594b1740cc01077362ef6cf21b65692352a24de9ef3c6625dfc21a7dc19f335ce2417b396c7b891dda28da5faf1224b26812e663af7844dbd1ac126b72162f49803c14d5652aac21811767b1d7458a7f0629c9427ccc17f0e671bd82ea78a9f71982099b1fd619893d04396ffac8439115301b11bd01886d04584249928d4c6f965c83140347785df8367b217f61f8f17b6f0755dcdf3e5915a8c948d01cbdb8e012aac6774470a399f65350d0d951a5222eb298402ee2bc00aa7c080defa7daddeca53be497a965088ce98354f7f5b7f0b5476151b61b9fada68110b2ccb0de77329dfbb306ccaa2d40664273858d2ecf4bec39773f920904e300e8257c80cb952bb98c4a5a817bf059f2159549c013a63ac9a71a90ee02edab2219d0c7c0a91f202278135a6fdf3921b485220d376d5cc80833a272d89250440e2a1a741880fc59ff4774d03fdef0ded51982979944db3ece6577adf8c215f7eda36a4d2f59161e797fd7829880fdd97c5a1eaf8fa10ae446c60109f599240ce70d2a18ae3b54b7b8aaa33a23ce485ad2ce5c1fc18bd10195dda94e781f65cb23efc19e3c2f9e6be34f40be88cfb9a9ffffa5aed60a18dee632d543285dc17ccad197a7823cdc8423f716d66e8b390d2a7562237726c7c45f4eeeb1ae5a1e66033b14fb286af6489f298d4c7d0baed07cb6f9474be8c7f928b85d60b11f66d2f7b6a061d5c1d500806d0de75e5602381c4cd4e2fb57fec56af88918dab27f08cec9a3a2314a5ff3ed4bfe6eb9741b8e32bf59bc2e7b55724d97d9a1d11d5350affd8586e50c7d6b0f4cc8aa356ee319e895f29c8d5db447f81cb7c23d68c8f2c2d9aed5990f18ae0df7d3637b4b40236458064bbf04048b940f8a45c699c83531e58657f45c160510d5876033131cf2ce8ffc926d782b8748f9b9f015ba3a6321a976d49ffa61b8406c4d6b04cf5ecf4fc33e373fc213833d61ae8cd2d205c2bcaee41342f1df0fc4478b4a9686ee020f7b3302dce9a2c69acfd0e0a5ea139b2a7b39dd844a7a52c5ebaac69240b4d3353f43bdedf5c29a88cb87b634094b359398defa0d0c18c86ae213a7a005978ae997d62e19ef5a452fde3bd42a3795da1e8e3932863fa3badcb32db567de826e550c541f09de5210b68f54032d7cd9d0f3e4b44d97ec027042e65fb890d25ac89e25265665ca924346673a0be5e1ff603b22b612e71a1d32c5031377c2ea08e0ef6bb29bd4bc012606ed56b4fc6df0d21ed1a64a1fd1dc488d93b0bba62d74fe6e6561b8feba89011fa90ec61729926ec378eebde61927f9c11e9e4ce4a3866a439b9b738ccf111bb823cb08e11bce7c539ff533e5fbe68f8a2a44f22354276b9795c996260082bdfae4f643ff4d8d43f5ce2374c47e01500f410c750b493d4b92dc51e77357c22f0d73f53f1cc7b50cd28ee0472aab608579ea5d9c4589b1505bf79d2f1cdbbab9185832c4de8f2f1f11669476bf88ec75efae9f30791c6cc31b6e1335c89452a3431c139aedafe4c4dcdfa7c72c208b6a9a133bfa4e0b55ecf9ca1dc3208b7334b8460288f22fbb43587f8203197826aaa1a397bf6d5d53121e91229fccc703b59c5e665895159be3afd18bf22d9aa67e2de61c4a7e1a507eb14e8a927350eb6e1aeca7d07d6b6eed095a2b5b118df12e66633262284a3379db86bc64bd2f14a757792db953391ba98da4ca076d59f10273a242ce13f6e449c4c322dd546b65a87e8c5fdabe858a5f6436d1bfe8078c427d2bb257e8264a36938c23c5dd0cc5b8b5aea7fd6759a357b598a6492a9dac35ab87ecc54fe04f8a716a27e3031b1e2124666ce8f5bc4ed8a953b36ddc263824263d56e0ef2eda8b85e496006b9f5729f53c176411b7732c68ee5ff5a6a7185715d55a6f7117d483f882d9e4c0a058194db80e396350fa9919f111a72f2a3416a1d75f3c7ca423b8f1cc5657a82709395763ba2f9291cb68e5e4334d20b674a9f2cccd0db9dbb073994b7621cb3a52d038c4830e4782cee1f3502cad2054c0572f3c0babd0c663fb1786a109d3e41b281b64d29d292aec4b6cbd6490d80b006a81ad83de686d249a940540d9652a4c8726c90da5e1910bf077b143bdefe31c280fa99c6d29d6dc963851b9572c16cd36817d9eee16bf14163db631fe0ee4fcda02b7be22bd0b71382af1764ccdaf867d5508eb4071bdf006e5539619dd1788c7816051c3c914cdc8936ddd7ff3fd5fa3caf05e639a9285089811dad70383a939b52abd19f8f7d68e9a4e58ba440941f207bf5d1e3846bd637e76650029304576c59f6becefbe76d1681b4ec368da12b035fc523bf3e27f61be0c9f5cf62745c7da47c104597194db245c27630878bc267b30a480756cb248815bf1b2136f92741ca92828dc1618f2f79a4a62ccec259c02e2bbb663ef4061eeeac1cc271012c5b24d092220b7e95f095b21885b3d3759f19affa5687010f42e417870db13af02c5bbcab8ce5bf16a812a139d5e73d8a771e1d8142af90a4968e87f67d77f50727c7cd5b38e0b175a888c88687c97f2ccaa3daecc519116a7c5683c79c25cdd5e001790da07ce4379450be8b25eb06c11c339e99686411c586d47196d45b33d0e781465f7e2ac5d0de12e9c43abc62ebee55af138711004a287107d0d078b5aca0dfcbbd0c6ad4e5f837d0ae30ce2201b372a2e7ab906b6ce3b48d01fb1ec1bdae755f92f5cdafcb754819b5a290a2a70e2300926062b1b23b379796ceade68852daa89da4c3a505d7cc1b76fa94934040df4e802028819eb142ae2bc5b6a29150880d2993dd5329822c6c7ec35a42620e1ff34d85324996c89e472d7ab9746d09f613c36d8b48bb16e1631977425e80c86d8566ea10784f0372e9184836ea8ff1bd42f77c4de41f0893b5f380fd362102307b48c953ac0bd4990a78d8bf535e9a3621326a95b3e9d9bbdb799adb67d74e015b8fcd6c4371be5921cb86a36d6d86091500931346800cb22a381f7d71f7fe689c9850dadcf5434bd59cec939741279ec4ee90270a96142f48ab7943d317a5deb4eeee2fe72af5d98c4964f04f5e017f8768dc417e80728bad4042df09cad6dc4b100fcbe077388acc6daa5a1438a623f2ebf20320d3ba4fde8306af946603c9a598304f576e9df7fc860721844588148df45bdc8ff45de443003f25f19dbf5f8ae3fa1aba759879b30f15f6fe2929d9bf2e845e1a86dff1713456e2afc65be6318fb7ce9810aab88675514b0037fddc1cd705d85effb2ffef9bd8563d648bf65ff813db6ee4671ccd65438e391686a41daa5afbdbc3695824a34e01191ca2285cb978b1bd65301f1e4b6730e73956ba3804fe390f7675a2a6f72273c14340c4ce4060e1f1f7a847ff8426f3b914e09702635a10789d6a57fce3f01ec47cea740b3956fcab20322fc7cc1d171d3db6c2f3620902958cb9f08d063162a12df1beb9e0e5624773602f2d7fc44b92183bb6817d858fe4d8e704ddda50ffd5db190d50e376a36565b4de871b86e1a63901fa33125a28e50663fd65ece946e108a2d846cda540738b92a67b2c0f79c8148bf69eccf16e24a9d342cb9a64c8413b31a821ebdbc9f0399c2f602db884763f4c441b09d5b01217979d658f5e0474e7480578ea94807a1433d1dc9d0c924f2db55b4e5581af3bf43335ca183f7bfaa1487892265a346f8ffc2646f68613a14479b49f3c8fac10a428d47fe183af50ddd56a244bb7364f21579545c6bf991b27ebd8842b5a472ecc0ad1dd67b51f06115162a5b71616a76cc8b74f8a13832b5c9e4f93ae7bf0e4c03bb699175e3b88c05eea7cf50145f6b6e204cacd1c724037038254425f49e1154e0b096ce985678f507a30720354bbb415f65dec54d6f86bbe093c639eb2825fb437c4f4e1ad10b2c88a56da96b374d8e7146f843731c24f205cb2ae94bb76f400e5423bc0e312ff49a3668b25f2a099c7e776014e132c75cce56d6febc50d76b66c17ae21f7fcb9365dd6005b82cd7b5ad8180003eb9564264bb3440e8fd45c3754abd86f3c2c6521022bd681f459f1f26ebbece32bab9ecee82aa7674c5a1916377527132020a79c48de8a43c7e4923123d8448673bd8a29534a26a0bb1d31d58d0a26b85477e50a8a74781b6debd099900393482479bac815883e253c7c4af7bde153c949a0a1fe5f743c6366de419e2bb445b2ee3ea51d976b5a7f4115a8ff42814ab0602962da205453d6334a49b16f60f851119addbc616a08197977e05ec36058183880ac3085ab3ace63ae6d65c3a0179d3f0cc906fc1ac37e46019588b915186b5334e293f7df6dc66889313dd0d82011d712fb9fdfe4193827411d1f8c06182410b4ba76ef677958c24919ac0fafae397a2be9d9756c75b1adb50b85c4b9c3dd218e785bd4e9d9e0018cab32e86d1e8e88d62866650a658539dbc55debb697e0e630b0a550ccfc1696c24a64f3b70d8b83a01ba91744652d6c33fefa797320f9df3a07f5eb877c46f2689ba4aa03d7bb1af8482414a0f114a55c0cfde675eb628d08c2cffdbfc70bb50e038483da19979f6d4269e5b6a5c5859263eacb4553c5703b95961fcc68df5f11168709b05f9b817d7eecf2ebdfca8d95b8239047e69d1930d4eaca33de3c5120392eb41cf6417187722fd4b71bae1dc46e3ace243043f8872520758c939d1baa0fee0b769a23d039b094f3b -MD = 9f513f678eaaeeba2f7cedf1b455f8e318cba538e66833946be8d1a346623512 - -Len = 44864 -Msg = 95f07516d6214c9782c7973c43bb60368f6104c2c675e5087a0860420dc5ff208279ef6b8dd3b4eaec681b82faf970a082f9f2dcd14a84d60f48a564cf08a2f0e4e10a1b762c63a656491b938fe3c2873e747673a30b9e73774ddbf780b93b206431b06dbbb6c196677480b828febcb36bda77d063409aa85b1fe8414b613179a970c8a881f93781c8f03039eed4c7ecb234df3c3a72e23b63c7b68b5687ecc35ca63a15f37c2b2e21c5155e08ec4cf9bb8995fd5028ddf4364c2b1cc9b3d4c624dceefc36c7066619fc166f9eceb1a32de1815bcceaf39d7db6313ecd6e5149aa19cba5756231f1589b1ab3da0360b2b0448ba0d6408cfcdf0daf378a3ecb169565bb57d6d6129787ad0b73e212bfeeeebb9b1298b310db055a8c5027aeaaf38ec8a65b81a913204e37d0f7de83381e8c4d99fb37cae70096a5b2d1cc4356a93d4b72fa9f669b5354435187f7df310c35036da1de0e7a333bf40802a387370049f50879589211f942d8766b54ac147e8fe3ff4db3052f3e9c51762ad101b5bf5bcf5023d3b7dfdabfff27ea1f75483d42f83746de396fe860c3e493813939b01adf323f395c6cbe74bf4c4d7dbf3511f747fed68832a3f830533a83d9b829992f2f9714b10a206d0820cddd981443c156da3a43d9763137b30760430105ef4341c765eb644863ae242a92df98fbda1706b8d5d6f88f836d92e93f1b22a8f176f9ad860c7a9e9d4b70e6839ea5fd62d9b0e9b5d70e05ff617401bd52642a99f9ffebe0bf1a94360a935b8961e5a143d0fb76c48e425e0fdd0255c332ee124e96fa895d4c6cb396b436918a6f836fe5c49066e842bd241aa7e4f03a01e9e87713928de4fa9982261100916f11a5efb17d16c10b3da6de8888c1d708087c357e3970015c13c98a4ce89a62218f74aa0dc2368f14c52615c0484114178fd07fcad03cecafdd23517102ab0c87311727625c98d9eb2365502caf0dad4dde0c51c3a09d57c4a1d061fe28dc98883fb6ee1914e3a7789f8a173385cdad943c5930d1703c4983a6f8425920d50d0e007b8898b0bfffa380bef23d912819d3f3dfa65c0ac1cad436c17aecb23d7300bd8c7c49f8d6eb5410286ab29cc7fbf249c53acc34d3e29f9756931ea8bdd345be115293b6cd727395f106fb6e525ad887347589b71a9acc12dd1556c9fc34c74b3393ddb04f9ce858404f7ecf703f6ff453ddfb5b40f943ef7f86fedca39e6dac19c691af02729ba13ecca487c9b19eda4bfc8be7ea08ed7663707daa59191f28ed73167b8efb74b81205d55d06b84d7f435a9f25c2ceb0efb25a3bfbc7aec508d422d4dc9c405ce4e6827a1bcf5c642c647da1db705375a193cda09694644895f85c339ad447396edfccf987cba6cc29d6eff7d29c9f25d52f50144569448e1481a89b7cdd1af59e276abc6aa39d6bbec0380bd2edbba6d3ad6bffceee5480d0978f744c60c176bce6e4298bff4a2a334ade43a30baee2e336a6c9faca9e0610609826d00442a61043c3aab485b3f1cf9e6b090c9f80bf4df28ada91a62a091b074b19d172a76be2678da6abe0e2a9dce167c4d651392758089e9a5b29fe6f3ab230b51651f8af797acd8539b6df38a03e58dbc9c8e2014da16a7220fc2422b58ad063694a3b591ea308ae26b0b08864dbc8b8adad833574e477c8a7c6a408d4b6b28990057a51190ac88b3a755f806fe03ec24aa722aa15fa4c05b930840bdf5e5e915429bc7fb2d894833daef4070b764361685fc94a780a72921ee2ce121dac5de17d5e0acb3135f5fef60275077ec55efdce7c7ffce53d6fd59e838a04d7c636e3d34e6b1ddd4872642e1aec6711f417fe45a74da8a3bbcd3800bbbecb55d471fd1e9fe75dff3a931ead9d600f0c2bf6cd95883936fbab13220e34744edfff979925f98673df32e0923b34dae6b79484d086c64e8f3535cafb8e93b375bd6e2f1eb1055147c559e229a08761d659544870df0a91999983792a49838428364bc1f48a6a4fc1f9d7204ba33dfdc73c96ca156afb0c3d6ebaa81907aaed4f93bbd58378d188cac2d322610efeb69fa6809328ed42c664fe05e02f90b0f9d21de8f43243e205486a7571d1a7749547e03a2a0f3186c7f48f8aa7d4ab3ead9919faa56bb244cd2537e794053745a1a732ed1734fe7018d76a71887022fc138dd21971968ea0e847724e13638519e3a7e3c1e3fd1ca8c0f3d7e3086bbb9132948f6bdf199f9d5f9862d577555b9961303ddd15d452d5c7321d08b12e3fa61297971b775dade439fe51a147427f6c2528866a3520699f367a86070a1f75e2bc7f334fc1ca801c7e6385dd0b92ba3b3779078fcc492ab014b558089ba727ee3732ab3046c9dfee37ae47af4cacd4ae9d09087561b75aad69cadc35ed2f1b718b9a47e58dc094026bc7df3f90fa956c61c2d1437cd1c4413da15ab4871d1a14c19e4f961e1865ff229695b662e3c51e8b8aa922a5012f1299221aadf1daec7fe0250a6d823a1b8e6402b13c47cf2b6b214bda3a65af62c884356349b4cf5959f019c18f408c7e563af57af8c92690fc2decaab24341260c07c27faf5763294afa61bc27e0785500ab5739136f51bc78b65562b3c820438629b1b40962fd23fc04e5435beb656a33c00e37b5c1b67788c56e49647ab481ddf2ea4b7c5e071114198d9e53e8bb83988003b90448be89d4611fa9eee465a8b96a558b32d2e8b93d3e4114385fe169d6f31e0a2b8bd1b9039250c8788b9c7fc49adbbe534608e31d7de9ee32d841e496214871501358d0be60e9f02bf9bfcfa389622a0642cf595cdd6d7568dc42bb801367359c66b997acd4d2672fb53860013fd319744fa5e2a367b5ee03f24cb83bd0649f360e5ed376f5f375ab476dfa84c517d1c5f4f2459a21a9a42aa3c7a1706028f74693ad4fc3cc3464c738c865d422149b20ba1e4be81532de06761b3fc6cc9a85f67b10d23c5f7e7aad0eaf689a5eb4bead2891bc354b36e3bff3b15ae61ba1906c50ee2389b8b70182548ccd7e82de8496c6b3602bc99efc7ca2efba77552762d099af0b51dfc93f718fc65a27957a33001cedfe70995371650c3e26228313414bdfba523cda9a7d9f49c5d83e9f6f1415b3a560acc33c8aa4b807678fab4d7605a979c0f4b314023709f10e6aa9a76ffd12444c884d408f5e2eb04565d8bc48257f531c1e721e185f58b2c654b9098ce0c1338bab4149c7bef7a3884d0f4a01d3e9b030651d9f053fbd70c6a4da7db2e549d9e5bfa63e7be99a46f8ee5adee83970f8c26ebe811201c093d70111eb2a34319d21698506f30a9f035df1c060447c9b949be45cab87cae983c113683b3df601e90953e58b77478f417efd4ab95ec7f3ea836d0005acc5c1a84c83e655305342246325ceb44fc8f16724bbfecf7e40ff6342b1b177c817cf6b40f993224e727bb5f8864969c2b64ddf17d2e68beb0f47679f5a77e925eb9b32641c7888de7c3406901f5c9219392c101feb0ad5ef5d535f630d5a430967ae6681959c702798f57ef39812189d78146204ae7096d052acb15674636dbdb38f705f0b08c372ef4785e89870e1939c903d8dc222b4d715d9c74037994f89f8c6b6c627c26707a9b18338c780d646cc250984d028194ccf6208e9fe05d2b45edca27e91d4462eedbce0abcf49dffd315d2eaf7f88ab77a7d0db1970addc880c589b4ef045472fe3ee050955d3e5fff3bf14d6784c549fc6a9aa97359b564b2bc20800ed1e5151b4d2581a0427ce9539d324c3637cfb0e5378dc2cf6d72946e2a3535a2f664ede88ed42a6814c84072b22c43de71e880a77c2d9a05b673bc15a82e3255f25251c86c92c74774aed9df3335d0bac3ce2dc5a1108bb0b557604bae720282464be54d7ed7c4d8c2af39fb68e58f65bddf3cc23ecd344afa9c1562b5a722d272a01cda2e19cf968f37d549fbc1bc69c0aa221fbdca105ee690301d56441fa0f7fd6d1102ef240b4ad7205d344104316cad7250968dbc4719f264bdf8cf559856b25a6495be8ea1860bcfa7dae9e3472257a1e7618e74adf52117d725bf60f31f7d69574f0e4be3b15427bc3832c635723745569742e5fe18bacdeb558ade7ba2ad1e6ba755085c6d4ecd0cd4a24966ecdab120b0518ca1f51dfb8d10b80a8c90dfee14273930760a3a240c48bed965f2a089d83520e5540ac9251edfcd81905a645ce3572150cb28c4c14d0cfef2bd142733dfae376c6eda4adf332b41e0417ff8ff4baf83e5c6496d295189c921c6c1ed53b9841b9e6cd4218e4c8bab82fa620c29cfa8f76be1dc91c08c57d3e33d9c514df84f3407d898dbc6cd69610625b0fc80e1cbe25fc852e13b8fef75b36c03f1a71e7817253c88e7fd584d18c67ded68792490eb3dc45cc9decec9451eec895cd39e874b62f334b4a65fcf29605d67de970a905882705aca3ebb7db88239ace177fb05376db71ce066663819503eb0ad5ef632d0ca46cd40efe8654699ddef2df8a66a6191d2b1f991ee406f12ac6873258a00ea81d234ec46d81885a233b0a0da333f607be0944edd6a40a11420ffbeaf3872ec258d222af80d2fec47f591d88123fc9a786b247e8d5ce155f136d6fe4084117c41f2056b67f9e3e1077e1333a1fb1aa633ccf2f746588ad426489ea08dff5511438b5f4c0b110d1a4d47b540a12b21ea2aa070578ccfa5c22fe0b743ec0cc621c6b3a03b75f4d3eea5dce89e03269afcd9603d0db534ea968aa9a156ef2eed44282578c82d1800d48dc83d9a4c8ffe44ac96b988742a91c7a2eded680be822ff043b396094fcfc72817414d3e1c9b45820be66663e1353ec15281be5c6cb0f98d78f729342162f3f1d8b1ec9776665bdd231c4157771a96a5e028d6eb44a2bc81e7ca4deb8e62190be57bbe951e88adc4dbb6314b4e80ad8f9e7d25138d7dff3359d50b16dff7c2de0646cb215b28c49df95c3e27ac8e09e55628b3bd916c4b0d95c06a9d5d4875d205ba1c24776e26d146b571d3da6c3410ced188d296952776653273684d7eba4fa980b884b8835dc98a6ad1382043b679cf1fad38e5201bd68fd32d5ffac019bdb940a72b678ff1ec8d22663cc53b158720ba29d9c636af96dc4ca06bab371b84fea1f2ffcbb968a1168639c8137bdba18b4b049b80ff6c1c1445d472a70b470c404ca0ea2e2a4c52ef3e51c5502c8f31d67a46685da2d9d1ff65d25d376325bd46e9b9d3d60a2466def1b719c575ba9ecaeef827a3477f1d6455a115a3673e00da1f46a10c807945ac4771aeba7fe3502f5022c09b18e4690dbd49813341193bc2964d3e18b4d25721ea896a777192afcd47ca1a8d3a921bc043d3882f163fd8c7f7d99142cfb703047f0637437450236b7cfa1fc1d8119d46924614de11363db1eaef82d2f9b0b41fb1f1fc68b0a314d396b9b67e18e7556750aa0c895788d4481699f90f5946cf382551a12c4c16eacb3e10c70e229eadea2607577813bc035424dede431800bd18862e0dd8712e0d1c1c053bb71fbe0b99bb66dff36b5b349cbbc719b45d67e6877a912ab34675e58ed7a3f8c237cdd93ab8ce8b4287eccee9845a93aa5101b24ca981df07f472dbe818efe77791557e96c44843ac90f7390327a1326f1c598a31bd06141aa2ad55f486f3f01d56dd627588dbef7aae05dcb24ba4df4ae5f4d4fc5b28b13679afbc78cab6fcfdadeeed9fab8f78f5089d21be986a8382d45cf9762df09fa1a1ff793d8b40f160bf0f87dbd66cc462c7476feeb8fb046013186267db65c4a34125f20b729ab98cb4c898f2b17bbc0c128b2f0b505f4c2cc7b076970d8f098681aa91a927cb3acab3a188ade3c3483a12f2c7dd0b9e412e1bac9ccd6a7756908a15bde151db5e61e423bfd2154c5133ef03a02c8ec1cdad35953ed39a24940b84eedd7998d30b9b70d5a629ee1fbd40d04722c084d0d7f33df3c36f469ea93d97be5b3aa6ba2bbe7f3fa37c174376a9dd44b56193d146465c4c936a16ee7f6fe90b9eec2098a51338ea1f9137c062b64084c2d663ce04efb92a168bb11bfde8a5600e57b17561e2c45d8331f79f6baf1e8fafe89dcef8357e14b49cc02d0af2f1421342ff5a47734b203524ffe778dba2ebe65fe9da0a62d093d563ea2d90d3f53b1577b24e3f0df4bc9f32f6a07083f122cd03eef922bdd92ee1aad82276d4dbd27cbc735a31f9e7b8272385d33def36bcce9b5533288dc16d40373114a43dc890b0daea8505804d9c37be5387c667973f50f1c590041bb0d85ad29e0c0156e6fb1999bed7a3e84ef136cc09c4f3333c35bbcbe7199fafcdf89745c71077665d9d20c09758f379113e8c154e92ac9a4e2576f263d5df9040546057532bedb755fe2b191f11de7dbf0ba061cbfad9e5f598eb2ee0cdad0832741bcfeb624c8ff5a4a46afb094a3a7fe1dc782703625d581581460607f25dcbe1327636bf7a376519f17cd64821f97a46a7220bb62f47a024a0047f8d94d832220b14dd4960f7cee57c1756d74902d7c569261f1929eef44db02ef0677dc190bf10718708e616588eab0223bdac9dbfe38b4d0a3736997d19198d049b93600c41a754dd05f5de2a9ee807e60230125a2a735f75153f8f630f44e96133c0fccf2f3a86864773956d9d9aec47afbfa8cf218a2407bd2d19cdb8970aaf36eadf001130d02bd64a844811287aedcb40a9475038636936e67fe39a7bb797adfb4fc870f1f874bb60f3e484fc79815e9a5be940e6e642885409cf3f59bac09fda954fd2e5c608fd9f2a687d7db1aa71b707de78fa733bbc5effb62f97d9d4146ff9bcc2740490a4ed70fd8513ea110a7ef44d80ded3fcd8eba8c3f09fdd7815a2c237c50678b3b9340fcb2326eb5e34d76c5fe1f8ce2ce7e54d1b0cd78d56a85b3aea6503eb1a435b4df9df1e7d38f4aab53c22b22b73ee3336e90ba9b316d882a7fb29d3266d4a4a73b04164684754df180bcb73b47bf7bdab53737c1560aaff529299deee53d7e9c817d25e74345b5fddf565a22fe9096bf481ceb77dda28ba83d83e8c0e74f0209657197568a711104c2177a965682d25589ca3c4b12f599c82f49f464c79a0d723979e110e477fdbadb789ef1e9e6ad320cc7b0a7905458b960f4572720aecf6b900ea9b2cbdaca847e123dc2133c85d9538ddf19f05f5700851b67a46cede659eba84798bb0a16063c5ced838d04fabfc0951e1e9d6703420e17cc4916e7d0c1aecf415f3c964e9498b114b291d08a5a0665f422120bebd26e81fba1a91d1d377bec3d62cb0ff2d415c759dbdc1fa34c878907c0d8de8f5628d25c2abe0e3a3fb597823fd0c791393608136bc652d3ebb676bf776c3f5c31cf918460a03ba62f0e59b662f86db8286bebd7feeb0aaacc25a791c236aed0e9b537fad00a15efa9c89b5068ac52c64639fb1de1b4b786725794051de2bd9c028c4e35f5562d851486e4d6bd67274a0722ae6bc0add9f562ced4aff6daec0c00b74cbc4d1f02f513bbcebfddb34bc1efb88e382840f28601fde1f8f999aaaf68c8abf443cf06be1bf9a172461b40bc646e0309651891a6f457345672a979f4af32f47475d0d95e81a305a482f9969809b5b566239f27d6ae7d546f1e84fa8a4878aec35fdedb45095a73bd10e8cde344121dc4c04f25a384d2caa949b67ccec91c43576e438d00078274327c63573ca81594abe7933b8c3bf9ff7b70a8a140a5904ab72da97f2e00bd7f8b21f3b2f2aa32b291f615a9ff28556b7c4fe5e86e62773d491a7b120d896e0e4dae1471b3cefc0ffd7841217ade67a71223f8b2d6943393b3c123064d0606a8f08d3003de9ac40574eaa0129dc2b33ae3995ba0e79f47d65d9e5b9c6b0b29c80a2be0f9f1724d3b6eb9bcfdc689da8f571c89333ff8467dcd2e6f74d60d49e3f126a1b49af9d9fa6181e -MD = 1e0a456193c2501c2f050b88f8f319f2422ac4e4a434b53de5ba3b8ad53982af - -Len = 45656 -Msg = 7129497dd7d8df1b23c2eec5dea451bbdb50a4fbb15157046ece02df8ab1f8601a071faa46aafff1fd1e1884e8ba790a9c088e0b136e3ab35d0d25d393e958290d4a07e1d463ad5b5a325f2f69a7596f5a08de2c87943f3b03673938889d83ccb0baa82c684a13e2a2c468d04bb41b727d193b63f50c8e23c7a3e3175015a4d16d1fab92eaa6560d3e9dde6e7529e49b6d034dba451f50f3138bcd77d599e1c1ab40b71c43c0a16594856712cf4edf73928ebd385f12ad344ee59f60fe716223d1e675d059e01a710d44abc3416a3181558233e52c30cc6ddf7a00dbb3e4507f49d98cb8154de9b911a15489b3c7054d1ca656ca92c0d626301299eedc3bd35e7ae1a5dc5f5137c50965076c0dab816050c3cfee7a09f2e7a87512a462bf1246ccc6684220322c1e5b586e75375fcd415aa1455acd544939af6a12022bb536c2a74f7cf43e39ef4b714231ab192b1278a008611471e903a3adba41122068665773468afaa3aea9d4b2ebf8179c56788e8cc0cb26501047ae0a2d49db291fcb8f9871395a35d98142851b6abfa62a260a85902a9751113de02f8bcf652f218df17e98321ede01a01b54992fad20ed4574f24227705b330ec4829c7eb918b7d3058e851d4e85702dea862ef0e9f3e8fc553d9c69b858c0e2df6c28fbdece29c5542effa1f0126c513483a2557905637434cd6799772ffee0bb56f6f1dc37bf8d65c7cd660e6c3e3483b2bd056740a6d4990a6a5eb6c83631dfa6cf06bc3dc150c0c2b815af7d2efd5e7d46a9bb8bf8450c5c6f617c0baffcd3c67be285c77639ee858856dc2c83d54e4b07e87bcda3ef162b3c49d1e0b36a201cc22e3fbc276d767a05d09c6187e3da85c66bb1f0edf93edf9bbfbd2f88a34d126c92f2061c17e008f62cf70480508a914cd964db1f8c0de0516b49e077cee20e40b5a78c9d5db5962511f5feb743e6d861db9d7680cf0a9729f47cdbc814677a07406636f2677c8e58289f3574e577c2cc1963a95aebbd6aea035f08c39c65bd89da35ec625ebd575819fc92ff5dc4b8573abe5cf307aec25b3ff84fb08f643f8e2c1e96366a0159ed8b14fd9fd45520c8e7b677954c660846515199d614ea68dede281cb7b2cefcde26f05f9d72b363e8c754e286e26ca271e072cc7e5481a040975b662a5fafa8f593979e415e65ea7f839f860ef048faa49561d2f076b04f7effc05dda9829c5f87a11a4d3c1f31c55c2a049779e8376a918289174a300dd5ebf5ee70e86c6bbb08267579bc2e660312d5d140716a4804710cff35203f7b2a97f3eed0d510df2e554a0a1e18ac520dd6be0d0087d337f45255cdfd1bd1f3626e66658202086d35f98c469ec4018c31f253163c0feb8db6c00d93c3afa00d29f9de00e8f1bbac4e5f5dc97050d68b1c00356b778bebcfb84494df4d5e120ecda4cb4f9a26c302e4113ef1274193b5188ac59b277e8c74955a7c1eeea9b09eea19ae800a138707a399b05c4818b1c0d3ec9413e07a25f2ca6c33c12c14f433eba2f860ad3aa030e96352694748c904cac0117426e140e0c4045c648a2265446edb4950181e770541f885b6a9443217798fde2a5f5685b52ecd46778d448c66c04d11eccf31a3fb29e3dab2e2ad956f4cb65aa51e4c3ce647018288aa0dc211ac52d28537169f992d9fb1fc87e75b72c0de0782d834ff0ab94bb10664e0aebb7fa71bb7e43fc255b9a6bbe21d840cd87251653211934488f226228f526fcaeab6944df35b0fc4b75a735901f80621f6eddb04315f09a5f79e0b7771d6fd7f15ddb4f9d600191f448c8009dabbd023647fb5650f14ea8bbcf986205c773c63d37173afce77fe2a73cc774eeaed948987b48af839d7c86e6fa100bdadc78ef19a0e7ac05b26f18ecb96b3a8a0e1a5dcf738c64e302c25d68631159ff42c77a0d00114dbfa91c5a4b277bfa79b5c96963968f1c78066755c77162f47be3a890a1c05ec632b5cdd14deec05bc4892d93da4b18804b92b5958d8bcd8556a562595e4696bf66bcc9a57976020672749004befcf138638ff246411b18b498723ffccbfb81df64a759fd572708a38b5d38e49610e0ebc9e3678f6c880c284a3185a17147e6cf335fc501706a9cd9182b6e5aebefae4183785c99953a718a74ca7d72d6938f37dbcb55db4ba584501fc87a8e440123e49b34198b44990f811c246f94844542bd65d251b0714289b1ab1ba4a929ad06791801e58e020dadb64c29a33203c7c80cd85e00ab68a773a4c10c34d3225e21ab03c60aca55fe15d00bc06072d97fe9ca3c56abf1ba3e0ad06b837133b8793a1f636bce66c8d40d7862d1f07c90d76ca099a19aadee6d16deb068a5f272671a8040d77a8be0f75e5657459979b0351b35f82915058d9e5e7599a31637d9908974a3f4556027cfd011f502a491bf03bc3260d564211e38ab3e2c1d0c2b735c4ea393a9a90e24c52a5241f159eb47a8183eda8dce2a29a3c5e173bcd1f6cb3433b718debcbc5f3f36c045faffb0cf8cf7026d399c48374674057669acbf667efe553a7bd89361a6ba040806df07e017212521c217a2cf8b80523c0de4aecea37827026943bbb1637fc592fb421901b15d50fe0e846179d9b072cd8ec2ed8a0c69d5778e455bd7dc4dacecc36e0ebac2742b0d062eacbd99cd0a31d68ea122209907a1d3289b5c7beb611d44ac0d93b22f5d55925cac24319fc570cb90f51e46cf64892032a4c7a7238b2d68433e15e9548fde9b5589350aee4893570f0f07e8d594365ead9ea0c7bbd225157dcac7d0ab68b107626a798c823ea2615517656d7140b073dfb170457ce00c35a0d931cdfe91d5c0cb77761f234da3d0a836be3d6c1000491103bd882e5aeaaff592dc4913b152acd8dab62c981da08e51939cc08dab2dc78abf12f899ebc76bc41e4fadb37131b5d1b8c119aa57a0829758865e9eba3fd4940bf4fd8439ac5155a5125fa67979c2fd3c1d5021a3ac94c4aa057f65e43f5a750fedffb9eca049ef4eaec9b47032baa58b5437c5a8cbac1fb3a08bacd2344076f58466feadac3bdb41aa51a5ff658711d0ee385d0f05b2ef9bdfea392b266edfe2429a1c24d70f62a78e6140cd1910893171bab37f628e7d8a4a04d4981ecbf800ad03dbf829adcaa8e3604e83563d55d667258da1eb2911a76a4147c1224108774f0a02d1aafd5b6b30b697c824f6bce857e0b41da769f21ac60a594d3db7596fb0155b5963e85f19fdcae3458c23078fca55f09a9f376a0ce6c5d1e57416310f568eac355b541cd9d306faa195ac7ff247eb08c0d97cbfa553dc7830d144d97fcbdbbe109a2bdbd438d1a4854879693a560ac6395f1e3a0c94b516d75b2a99e8976659902953e431b793a899ab73108e7f1af0aa3907236a31ba73811ab0b8724095445d0fb67f19d5b5cf84c980bb174b834fbe6d1dc2e6b35156d717bf804450d24920543af4b41c9de1efa789b1fd41aeab1b054a5ea9a1e48880593d37874f842e8101c98a2913b4a6814f773b67ea01cc69087441da83dad225e8142662c312bc271d4a8ba14262e5e3c830a17dcce579517f85b1a2e29bfa6ecd2a95fe36e6bbbbb0a43d43321068bc1a9e2b6971c37c7a7164f729448fc8020f69cc822f67f3e4c3c1e9386a24f5b54ea8215061019b8ee6f95b96341e068ab6b7121737fd2c4b5c88d6a7720855766a35ca5d22099f32e72c241137b07aadcbfeb1e5d5102d9886e14eb9d32250a6792f6fb53e414f107ae59cc4d7aded145525ef139108bf7246b4979614dcaded807d58833d1375d0aa0c09d59b7d28675c1415caf34eaa81a6e9fa65bd9d36f58907cdeda5e6d71a7c89b46c0b88f04de9b36a318448b66ead69bf4f57ccb1639bb5161b00213f94fa44e5b2b036106e02ea3871cb5faae1631a2e7b69d3e7e2bf6f7a36d52e73e92b26e4ce11f04e73b2a1c5b150fb5081d1e58f117b19a018fc1d4266ad743bbf1715f8e9b71c7404fec05b1a9c856ef7feb2293b1506a3ad5aa7b7d20f5b61bfc7fa6a2b282448c8f02f40d43663cdeaf36a451fc002ba4ae1f51ea3834bab9042be82bbee6e93688fd6bc06a6ff3503b6f32be50375ab979aefc20091ace3da904788c291641c8be39d19d875c06eea513723b667c73f3b8c7eea12c2e6cf47ba7fc467976caddaf56d9d732a0d3f46cb1d75ba73603edfbf88dd019d61387dc74d7ed38af00cfdcc2c92ff4d5071c02d8c6818afa9702a3cf6e4f4ab86e524bf98fd2df157029b70c43ea367f0ccff7e6e45f9a3089dc50ab1471372bba0e5ab4a8a9e5509575cea1bea88ff5518acc6aa5484d8e68c5731a04e877c692f68924a6d4e3d6ed3ea411bddd69de71d6e0e28dde2d5ac0689baaa417851f95b547c80ee6431ee3eea7dab61b4c90ea3ee5dd0283a22c0d303acb9670d77d1ec5171d45509b9f15f07a7b2bc4a0c3271d3bb8a7db5488cbb6c0fb4096f785baa097a2ee9645edfffe7c61a37c1edbb50c6303e237bce76866cec826fc6dcfe5d219e76f39ea720e632e2ca1a41f511086fc5d463b33ce8fbad4a0de1392921cc44e694bbde1d1cdc9104aaadf1aa9c6175813485851b49e3d4313ca7f0e92ec0185870894d463ba9ab32a238fa96c423816d46d11af101068ca9f70814a38c0145fff3a513ade6142a769a028441f2153a8ff38e9a49782c7bbb264dcde0a35774e0035657d783e7b3d87a54b6328c0049f121062da8151d496eb2bf4227db8a4d0589e6414e7ce8f15f2a76b8f1fcac559bb97ff99842a09fcb81a39c009c6177756e9bfa9937e0891392b0b306a8e10793a44229a0677f25d87c4402f34ea59b3898beaa401e9626fc9b4acffafa6707e3c897e349ea80829f8be99d89591e6057f19678cb97d46e232b8b33535805fc930fc54f19346c5e2897d9954925946fd9606d8dc30c60098f2bbc089c2c858ea96016979aad0a6379865d11bc1acf6fc6cc8911b0e403a0488425755addad662fa2d0e054bd24379c42bd3968a19609261f332b188785db571c0ea317d3462c2cbf3c55cecd808299b14136d720b3e50240b303855dae61c3ddbfb95a761788a99ea21b9043e8ed76bd31309101ecaa611751c27ece46db94ae7fe0ac2eea20ad274a5d2289211f3d4dd44e1caa0a004c8c55908c4214f0d37698409463859f40427b410d05f6c1f64873b90285d591ca8706943521e149871f50009a7db1ab6ad77fefd8212e7ba7985699cbf81402e3f0aef704d3758db890f04946e436ec34ce9c900b4490f45a24c515fd6d91fe9faf93e07ec098656eb1bf422100dc0ca50f1b4c2ed5e6d516d40855224b122b07acfd782d501279b26a0714b23a6bb0c683444aca3ef6c5e4906682c1fa603122d036e798ecaa708ba30ee681f8aa829d105eb366e6896dcb4029c463e243b9f901855447fa2af302441ee117a3622a359fb3ae8b356675d3cc97428f6b826b922831e7c3e458a91e357d2cfba45b5093198964c0935784041cf925cdfde7eef72e83ca9310fc3be75e73f1b5615d9bc16429fd8d68224267199694a50038eb30f9c3223fe8e05065a84a55ce4430b3c66adba07a1c905903a9b8b8a0dc3e094373391a50d2cb91a1f94882cdb49b41aa11e6751017696ee0b5a5b945f9c1f13a832cd74d3884a5a23bb7a03a1968ed754394a5d6c2752c0726a6be1dbf894a1c10e684be81d4367054ddd69eda5d5e30e72b5855837b387fe203efaf975dbdf204ad472b1583e9142e034d8061433de3e5f4b513c3453d50d3047583e706f2c346ca481d5c596895af702d6815e131942537e59aeb99e183e0f17821184d9097be85b01cbe1e5bfbc16e9dde5e01e34d8e3c10726140cc1ff0111f1293f840775425a7aea399694f4b43c56ba469fa150a4a5c218f02a72cedad93ddbfcfa969f0f4545d73933b983438ce964fe21ff581aaf431dba61ab3be0dfc0a039c74787a38e0b096d479de6695e0e8c734faf3d9a5fe2aaff6ccba4b798121c92548a9da3a732f7424ca29c8a222e87527321afb81a39272b8664c7c394aab7833ce06f8423363754bd68242a7bd1ebf83706fcf860af38cb58f6e39948030778ead96bc974bd3021046f0bcebd9120e0f5bfc3dfe5cd465b5f02a6ad44b3630fe8e610f83e108813cc27c1eb79c4dcb949cc82e2fc0be65803187f73fd2470a4b1970d74c1e885c97f12d505331565cdadadb88625f38f4ddf98ec81e3eea6d3cf5cafe3b29ddf9e97c0b3b07beb52ba9be3e35e060ca7a95f045c5b8b6a8c19bcb776a982b8ec2fa0a1ec51b6cf39ec9f0f81beeecfc5f70bfb6d75763076f2e428005ab4b241d92446fd7d662971f01171124d72b570b360ee9e4416d91ddbe03ecb5bbb2267478d2055a81c929151bdb9237e14462e6af84e4d5bffbce7412b5c36412871c2e755be83464c831e8dde6823b5660a559a3cab1931935459cf4010ef9f6f38fb35187214fc78838ff10dde91a7ca6a9cad988580597447ebe2a8fd45cb01e066bd400b791f230c5c47c6bcfbb9c3ff5a21a65df12815001407d061d75882f09bec56bb2e42ce9619ee8363d06fd52124a2e0950a41e80578cb50ff12cc54e2014ee731b2fbfdb93f51de63ae3e9088628dd1db2a2b7fd07089a515969b1a5d4d515bef95af12de332e424cf3aa689dba6ef490ef394ef991ef3755c149259ac6903f4544c0b08d9bb039803f37dfc982b2b346b81fd7d95358a220315b195313880be34ef5493fef942e9def6b689461e5a87d1333acf84b425015554567fe9ab54c4a22a16f7d9546bbf682b995a6ce944e949f1920eee058db95ab9c93f5e2846ada5e5975bf33544c4aa7b6e9492f3b103d9a34f62598f8af31a2d51fe18181f21460821e8d202979eabcc7c6241a4697d8c31b7f24fbae4579e9637e49ee4a7ca8c7cfac500252af573080ceaff6433fe678413e757ee628ceddec41877f2a64d7f276a1c0504c5720b156654579bd92e7482aa68fa93cd3b0feb3dc32eace45527f2bb12670932bc7addd2c9ceb121b6ba14c69ebe11ed0b0da7ed0c487928888dc533d1b09a387cc8469871ee0ed43e4123adb12ed18aa5eef81b1c4fc03c8eb8891c8167219e5afe3aff733e1bba6d1295a8c8cf396cb0bac80e1acbebe610b024bc4915052dfd23a050f7463e9aec3454ff0b2bb25ad579fe0f2f4261efb67e805c5241aead0e3f5fd4278fe03d62af46faa3c9a51ebc348266833e8a1f27298443c47384e6345b61d029a06a6c788c55e1b831787e0cf33c5b3d46ce3d0cb917bbc634ef9f187d8d8f250142edd6d268fb71ec95436ebc143686e395130c37230a800a57a262b0cb58443bd28823896691f78162358999f23e859b4767d0aa8f791b8024b5b9f90372add5810708b939eb7278491b0691bebc63f94c02ff1a4350bf1bbea1c5621d268a57b6302c6bc851095ab0be8cac60f847820cac428f26d793658d2d2ff202bc004adbcd38a7fb0be4ad01e7c4f3c03a5ac0f02c41122256c0e5fa239fb1987c393557a4d373ba602cfca35c556dc6cac33a5e4ca3aa1e146d236b49bca8c8ad5da0927ea6d9ed9a09ccfee6e9235befab78bfd21160035ac3a849692fde7b999313f42258e07cffa2a77a4c251b65f33a037c87323bb770eafbfd499f5b97860417e55a92904fd820147f58b35fcd1c9762fb33af43239e09a4edb2b52805bdd833cdecfcf24f6caa9c75d03bf77cb3eb1da69e2f802f2c492c836b194cae8636f014a13d0d620569c5c47d64e959ff5dbde48f5bfbc461d11a263e72cf792846d52241feea71e9851ad427d73f4b4a16c91cd0dbbbc886caf63df169ba4ded326a5f94e68f656125200e953c013cda3ec9b82756c825e35b49324da514141b1f3734619e0624b57161d8913a3513f9fc451f5d742bc1c0ad996c1acfe5b5fb37c50772cd57982d92649be179e5b8ed78c6b93adeeb8665e77153208e3618d5a29b418d1c88a711b0b1c04ea21812fedbd3ee853c105a1932564f268b0e25f188414b7b33a33ba8f2d1ada05dd70b764df5260835 -MD = 763c5409e919b477735af72977fbac1ab79a6cefac081ef8edd4aa2a42bec9d5 - -Len = 46448 -Msg = a25f26cc1cd56088e4c8ea094c11c49884f6ae4869ad9b919e1c633bdee3b87d909c5b679c618f7d7e8fcfa599cabc43cd4259a24b347a96a8b37a5f31a82dd17f1815b24ba5d9648358f2c39c9da8512b8f3d91af7668b0b18e056a100b0a2c9659bd76cea824841aa8bd2d0091700bc567c2dc3d7c4b28e1366a25221237d7fde9b97bd0735a266c0997aa6baffcb9c451504d9c4d0d465f32135510c79c1add507389f70c6192a002e80186fe34a34fd64faa75f19452540a66c58132223c5e145168eb7d2310df1c19fbf88601108f7c27bc6f71ca94e747cd3c1e5aaf87a7bfbddf55ce86e851dd9060694f494aabce404b33d495544170af818f472c41e1d91eb8dd0574611dcfb6f88362f697cc51031f6822dfd9890d735d7b0182b333e8dcb92a2cd4c46c7af38aebc6ee401a8fd6ffb7648f6ce8a783988a919725c6765fabe54a8d596565b0e04c831b8cbc0f22b4c8a18d5586c546fa65fe55dfc10a0e55b5688968311853c04ca263c5db59500742e1c1dc8aef244bb450a3284d2d5381438daf39f71b46f3932ab0319ef6c6bdce2c13491dad85521e8f684a926595f537c1e714e0f7ef41ca23e91a2e6deea1138b6be36688d1d84cc48e8bb73d3d7a380c19401433b8719995f6c6b2462f7aba05b1f38e0770a5e6f7fc34e53ab1d8ee772d06ba57084da789bf7e530af00f6aa3cdc1bcb3cb81932e9a8c43e65ad702090caefaeb469b9d062b8939409b29cc6ca79519124834fb7350ddfac8a03f1ccb9c80fd78dc24221524318b709790876827b7cdae5085c7cd066d3168ecd7e3c3c6c3eb8631b0dfbd92bc72224c0c449f366eff0f4c3d9f45a486114fa46800fb73c1ec9bad077c065b7315df2265ab1aba04d7bba2242ae1126ec20432ba1a7b89c02641b8f0a0f8689e9d2e816263e09cbf7e3cbc0211ab386d6b0ffc95da49f209c4ffba34f39ca1853198d1cd15f9c5e81c1a009ffbabffcd34f96cc1e86f94e4ec5d1b9b1ff9ee6ffaa47a6c686e1cc6d8dbd8c391e84dd44649e805ebf55998c7e443edc91738a61fdae408054688a3db09ab357b6a0cccc987da2b8ce1276f7c1b9bf29bff6570c9c277689389f3c54d2be0be603922fbe43ca9f9723de8af338b89723db85f1620e59c56bb3f447555cae126e95e79aac0efbd38451183a116ba7634574a0cdf4bcab998257163fb1b6d1535bde0f72085287eafaf63e08d4a32cb0190be561573f938f77827379fc89ce4b285c786a75a6f5428563de7bbfa7beea1901b24febffb7f3b5d67aaa984e0b667e81b0d85674da769e2a680724c1b49dc00695de45857f82c7b3ba36076bff31a8fe57303d549df3cfca793fc689c427a88b1eb0d659509917baa0b0ec7c30394212da269ccec64674c46089f77864342cffab5c20f3e1c3404bcc8f99e744f9d47f981ff73bc9eb2798dc7a4a15fb3fd7e4ca34a7ed998dbbf7ac36924593dfda953f80cf343f6e72c84b8530db1fa733caf9defd9eee54f53ebe4a881fa367bee42efda7409d2cc0c32c4f3e403806cb22c8bf749056b58691814fddcdfa3e0becf4eaf1d959b2bc29fd1ce4ddeacb088ca55abf5a791bda90739af5d91eaf4c300fdd4166fbacaf5d3c82a71c9e8066592e453065bc148bac23c072e97757fa2dfe591881f95714ed79250784c9c38f18a1e37a3aa63bf4551064d7479aa490674ec2d9b2d96ea74b2158889ef2e0cd5bcec9ef51bddebf1ba7ec95ac0f31995c6fbf2762224fc116c3b19cc3b074bb93037d22336989467078bc205f3b7b9f7ddfb264286a66eca0eeb4d6ab78fbd44ede5195683fc824f401782a09a5defd5c1d21226df8609499e0d6a8bec2e291ffbdfbcb68b727c506b094f513d4f84d77b6afe4bb72b95362788b956604d58f2620e026ad5604c129249724065f440a411a932d895fdda38ae4682f49d5213642a59359be92fb83ebcbe339799b4eae58e79f5f602649ff83d2e0d8d2ba7201d5ca79b705048897cf252d97b62f74c41f7c191cd85c8ae1edb28a14890b247c600e27e12911186733becae1647252c6156694c84a691cd51911c874d56dd52071cf124a834f479cc9f74f890d0a653ecb2586f44ed27c53966f208c5048f0787babcd65bc258282e26d3001185e3898b14784134e3f35d7f62926ad8232f30efe12bdb53c2a55d42d9ef0ec0ef4295e683b00c7d0f5b5fcb8de5f5ad3a2793e69a267db7bc42deb0bfb169c5952c41a407e81646f9c891c4f0d1f36dd1def915ec9502af3899731fe0015b49ff0a536ea808a9b82aa3bd13923faa3f71bc2923df60b365bf11e63745c82a74b64294eb6ff90bfb2952a9607b18634ca029edb97b6fd8fed812fea1f5ec1f6d413eccc463a184367e3f1e52b44266bbe98d0b7fc9aab9a50c048205f857825d2864c3a08de95e91b2d0e39144a7fbb5d1504c1cd0fa9d80e2503b0a57ef9b6bf41e4028f3b9df354c6fc2c6332e6a62e2da78399845ceb7e25cf159199eb1c02cd30d049ffa514ad48381998abefae9a394577d2a75927394916b9a464b0e8358eaf0db9992faf7d374e9b15041f5739ce4b0918d7032dc81577374e7def8dd01cdb255e76b2365d0a9c2b78d9ea12756334d1cc920f5193017cf8f033eb8f6aee31b1b936c13bc538cd45249bd472e58eaf4c7e76b255329374894a25596f5e794f2d5a57c1423e484e62b8d862eaf2a6f6e3aee3b08b1f521a62bcc0ad9023448012b23856cc20cf9c2e960e1a0d3552c831ce677e85c1b3bb1fb8a45cb471e670ec3176e64c252532e35cbb6e3c26087fa16d8070b7b23ef31ade3eeb2e92c59e248881f444b3ffbf3b7d5ed40a3d3ea9dcfcbd3ba3796a4ede8e0eed713e78745607f7f54845a57d916866eff9e37bc32f0c7c23cb8fbc1ae55882b82ebd557feb30378dc962bd0a7fbe62168dd13658220d4bedb25dab03c9ce38efb998032d7ea1cf123a93acf270dfeeec385ef4d5508fbafdda6bcd85f64f9ff8946708196add2d372e310ba1ff5d5be57c153dc734f437b8b6527a1df55d367751a2baa04a32e04116f34fa585a73776db7c87aa39eb50b2d87a673831878ac083c3b17e975376d48732ef89ae5e1034d8fd58fae9d57470b37beb61455f0b887d5282e0dcbf6f65f18871bac3e26483f7203835df333176c9bf9d25bb344713d0c7859374b71889d85c6ca580c4a308b88d9be764951649adbde301ddb7bc1710ab5ff31a0b2094be3736f64f756a278f8dfa8c146b714db20f53625759d8f6af66687c170c163b159167199a951854feb9da908936f117892c74d3a28b3c271f9145bb064a47c17103838bfc743c359889c2a11d78141b958dbdd239cc344ce3b46e2c523653ec52f602c9efc3543dbf86391a5bbf38ee59bb94fa97ad8fcc9e38484ca560c8f02df17b5fded2ded20627a488ce7cfdf4682ea09946af7d2aa1a57a985a49f591848e43ba64536a96fef6ab58e021d1b2236f575ac132aaeb80745b9c0b628834d914f265faa555f0fc6ba4273b4e32cc2de62fab81e78783cd3d81c4133aef5eae3e0def1c594f74911f25602a72bf96ea3baff8232ea187ea5983bd1c43a97366520cb243dfa5965f59b580480fc6a6dad84eed0f88677c6a60c7c3711d3517b409655bfba8f6eab9c3cb242ea5f670923482e6b18567b5cfdbc483dc1810bff9bcbe58ce65c1c622e5dcb818b5ad8882d8f271b39620d87d43008a97c4cad0c9f45e15166684cd4d2860b8c0bf8a533f5df41a703b0169150f12244ec3d1fe8738eb3d7e5bce747b140da2a133eb752a0c3e4d9204b7cc09b8600d6b75b49db412ec1e6095ed304f312a0224b36f42d59c078773538295ddd77082785af132f2eab75467a58fa53bf85c53d5ae7450b4660654aed8003af3d4da4feff3f662a648f36bee1b2427b3d20b143e95992368f2a131aed2cf400e48f3b24cc1528160b616b17e67295c6976bcdfc9f95c4f45da6ebafe044e396fac53462953943394aaa7e1930a2da7af2ee7f2f25a2c18ed85d53d06cceb7bba677f97e02b19ddc4af1d68c6849f9e0793230a62288734c27d6b44739d45ab4102ef140ba87204633bedb383570d94051be49273f50c175739977daf05db3cc6171847266c3b3c12c9af5e5401e64e2a51a307b24019253e32f02523972aa4ac1c91adaad6b3d935d0b8c5a315b810d9bcf4f6a78a3d02ca01fbf76bb1a277557bd1b423889a805ef9b0860af2f180b5b640dbbe33f6249d1f114101f5d12974cd5ef70af24db5f0ad2d1bf62a312220e61d1380fdb30f29f2e6be60c4353f6c799ff2cb845bee9d5374f3ff3be559bdc4f05a7a182226e325d2bc22bd5d3daf192b140fef339eb7952eba70a89cabeecb410d144392007b106bc6a241a788df2476e72273634ac1eab0bc14e0a59d2671b5a7e9e0a120344b286a69e1a2b56f1409f8cdc169775eacb1953684beb2174094b7557fce0ab15e7f14042ded57c1606aa54c49c4a8e08397b26ff5466f13c084b8018177247493065feb76d5c488b20f99388cf353f9e7d9b02bc2bb48be79fc2658964b01f0b124aaaa5d0aa027516f210cfb841d0d520dfaf47dabb379c5718ed51ea837a8117080ab60da5f2ff71ff95425d5488d4a9b1f44769653c83b6b5e018b2d1a2d3c607e7902e375f4eb887e889c857b0c4a0789a65de98e4c546010688c284dd2aa7af08db3a47938d73f2d24b013390cc8d9b6a48433e758a8f652747248274ae436937403abcd4e22ba71b300ece7015f98429989f3e38f918470afde0b5af86219b3a6635806b7566108be2f91298c66c9aa2fffb80753b69107853fc03d5dbcaafdaf7337aa06faf94ea06cae64f086c459c235eec74770a2939f0825630d4c40bdf983d92baf88b9bff478731df0383eddeacd06a7cd684f8157e7995069a991911f359b00337848d934a3add8ede38fa31435ae2d6805de7d4a2eaa8a054d03f38b092bcc15521d36ebaead1a5c213d45d90023ccb9c205d3d06dc76462bf2e71b77ed9e3d7aead3583da0f56bd69de42a3ad260a15352c2195257e93f47867883ee743fbfcc68f6197b63312a435d9060ead236a0cc7d7d302e64e8d5cf145a38c02e858e7622a4781e3b6d2830dc41c64709a7123028f84a40095c4eeb25f402932359f49ea1463fcb3091afc6a06025fa7f993da6dc9a2f33502bf3c540b0a9105ca4376d6b42342c4b85052c335345aa3cf56b5720cba6ad413e0c82edf5f4dee04ca00a0a0220e99331728b1d84ee0049a4e26a7cf37956e37de14db42caca5b73b779d06eccaaa117e400be459e8a3ad8dea08787a6ed83ed0b94c1ebb990fea570450e56afc16cb52b5d3123cfa3d7097cd599dc94ed85a20dea7b20b83c2808a8e4931e37cd5cb971b0c2e94ee739bacd1847246e00140539687f884326681ba5fb071bf13901933b8ddc1c98aef34b340b2805aeef8f7532a14798e6ea4f6d1bdae2e6589efbb10d56f524397594693600a4d6d3e688706e275bc92fe24e6b6f16bef3fa699bb14b9ea6969dc58d6367ab563e89af7f95605d34af6ab8d5951430e3cb432372029ae758fa52395ee83d5da4a31c84d542add55a9243d87578afabf9d2cf470f336fa384a5e32b89562bba288b29013a069b02463827cbce94960a89b0fb5ed3b22e65c25fdd268d4bb7235a7d2bcf1e5fdc767007a2fd11676bbeebdc63d5500d7ba09a5e8cb4db27643ba2ff8128e2ccd6a4706732071e7f954bc8cb754514b3cbe665488e510377c7659a68e5c937cc1e0ecffd5154262ba73388f4bc28923393a9cb945e8596bb3533c96fb60a7dec1737d7207d7ec91a2608a4eea4ea490b675d25c889bcf5704228886a7e77359b56922e8732e187c9762db51fdc24b9a9bb831c6b7c71b02572a68fffab89ff5850b05e880e16e2a82c25321eae4254ad04be17e3c34e57495b402885c9dd2ba1aa14bfa96ba95a34cc919451b7ddba73e76090c7daad4b6a4087ea9355cb4b15a731fa61d7f36efdbbc5645f65414b9cb81d2f9e4f190cf6e6e05eaedbeeee12ec8a7757df9f81719e631aae533798960b363ccd7d0c2c7da2ebfd4ec8b28537eea0bee1ff08422ed8ed3fa4fe0b11ee655e50dc01112a7cf8fd3ee9a8b090d331f749a692c81183efb63c09c24658143af7f45067a277637da69c060853a1933b00affc4749801f6760a8133c73db861095afb11d4aa3cf958abd3a443637f68e5f4a7999171e6fc47f0c77e91e0cd26ab9db749e64201fd4ebfaecf8b2b45b9055b1a4e4cb3ce38b63c19e44af7c77cdc7101167a98ce2b07cdda4a263a750d5a66de4d6b06c2920b1700cdb929af4ae6fe62e05653aa6bcafedd7cdc39164e2a3e7dfcb614c9f28da803a1a71f8c780f6b610f431c9ea5de7941cc74d03163be0a7fc5f782eb408518aac9dc8166eda0e1870b099bb1c18c678da4b8a6cd345ef36a0ff4fb30643b8e7dab20f64693e0875a3c7077eba71cf04a6b6e64f2a95121c8417625a146f73305b03b2633511986640b4059543fd63bff885fb1a8aae1bb20c545a845cf012ec940f4ba350f91052dde40e8f572017134655336f81f54e9fb02292d25e5a0a851c4145a54b5922d3b1e39cdd526e7b97269129be9f0f3d5e060ea5c47711ec926a264ad992c62251834f4affc44ce3c3ffc6387840506a457474fdcb55cc1b8cf44a95c0b5a49164c86363773b5ff2226860fa2d046d581e81f2256778cd29ed410ae0eb22891285d7eca0d415fc292ac6fdf95d59ca7921c50297193eb98a2be703a6c977e8082d58377d86e2c5fb45b2098089bedc6ff7a422dd613605ded14cb141ec145604d3cfc044003031db1baff05a22b2378f18b5ef52cfed267a65e8905cb386377b018533aef07cb45b15175ed0c8c240690d50a4b1c5d2b00f62511d51b05c20ed4f3efe18a826e1fdba9eb17eec6dab803e2aff54e37526e05efcd4cb82f486ce15438c1bc7dd3f35849c74ceee22bd5733ab6bc69942ff9fa47243147bedfdbfec496a12afee20950b97254b7e701a707638568167daaebfeb27e4e73bb6ea153ca714a7f1083a8ea8255f7efdd4374e8e786c1fcf8ab8a38ba4369e12ddd0709ee318561b89e1a4e2bd7fd3fccd9853d4e208ec4101a20d1e6dc4b3c1c145548b83e1879001ba5a53c5f2d4ebdaa222f1eba9915cadff3f0beafbc2a91fad337b101cb6eefe292173e5750c5b7a092e6e1bea89830e24bbecb2584539279c9ff60e068e88ddc29cbb8262e4bc3a21f891e9384f4490c726394a76a612a787ec74d44b591e3efb1ea32348f89e8990f405ea1f5d21d43af06a29b37f95ee03bb801967c0ef804749b34e93b262e6bab352850c3dab57049cf7b6ab3c5389748fa033c830ad504b80747adf9cb9d013b8d0408b5b3187c89e7a97da66dbf86edb4dba0932b80d5c655f2e893203e4307737a3194064e4db776b43bd899fb95720f122873190361e6aebe02cfcc1819560d1333287a60cd1ba3220b11f0f5ad1e322f3eed7d668e5f3a32637678336c7283567639b855e2fc977d57181ab4b43a45ba49c7ffaf467b20d67350cb9822a1fecc638f673576a47a4c86b6c040940e723cb1ca46e8708089329b246e4e252ca6fb60f130097059731800b38aa233e2df3cddbefb18f4b79ccf41bc085d5b5ba26dd629bbd8b864aa682cd71fe17bfeb442376bc548ba688234cfde42ceae751baa2efdafaa360d48c474e9280552a91ad626984d7fa9db62e9ab53c4a805c43838ce36b587d29b75b43fb34c17a22d3981120f3bc5ab5765773fe235f3478e22a1209c7478745858c1f6fb341e52d038ca63963622a726b365f1553eb85e1c006d8af69584048a1a72ff8a87224adb3f3a82f6e69f868e733b2b7386fe31b6fb22760ebfb46a7ae250c328ee2c72967857d5f7f4432ed8ce825403b6cda8a33b4a4baa9b0f8e70d9e2aa9c1142b24809acc5600817884bebc1d3ce752dab2de76c7193d09d58b327b01db0976ff23a1abebbfbc9217c31f380129c6c27229a271150910766b18df342822a29b81ab5d4171d8ee06bf3d00d47783442c2f53325c0506be8737f44652142d36e2712ff5e3e54e2f4fdd372629f6d60a0070d400601d9eb1acbac21a7d4c6730fc3c260e1bbc9bfaedd065d190f59e62efc -MD = 8dd79361e81666bccdca844e7229c88b66bfdb559bb0511379f85f5bded35938 - -Len = 47240 -Msg = e3cc8337029dca793c2f8c0463a2be0ea5f7acc157c5e08ff12d45c6590f8c64647ecf2c9a7274f939bd55537d411d401f5ff55c1bb3612cb7fe64b0c163eb3718d769776ed3bedd4b4b5d2255e4ae1fd062b1e2615fe5011743682eab705f0c07bd984206266ecd7bc2ed9a74f53754c0e6267bae3333b618e4976aa09eb08b3a19a5b2ebd44d70d0084de361da8186f7d49e4d8c9615f2c2c93a892755a55bb8d4d8f1a446236f5206c524a4fd545e7e155f8382f0515d1edb98b6c9fd072589d47927b9e3b87109a49d85c6c478845c8fb14319aab0a03300fb170dfe9e90b603d07bb212d31ffecb1c2f4e99b49f992cdeb5d72afa630a21a9d47bc1324546482516183d3e2138618b4ac4e3d1573ed32d0347d9f74da927eb169bac8beb418abf2073cbbf1ebf4f32fdb1099856516ce552ee1f6e071af80905f628702bb0b3e7c049241fbf9c7e59719c75ce41ddde4fcd56652939657e4bc8139eabad9aaae51e24b025abd6d548ce0d8e3ec3e713b3990611ee8a909ff9887a740218075701638bd69b8a753b463b8cbcaf8279f259e1868d86a2a5455a6cb4143e15ffa283b707014706829a9de0a267e8269a6388cb5f3fb92aab57b79d48e4274b8b73b2411f96f3c503d993e6d6f7b258534e897f18914ecaabbd5842be4e8463b2b2d72a5bfe656f03e07175b1d4d5c0ab9ba52639ea0f29ac5f85849fb81f047d473a9943a166ad87977fb4ba671905aa3321e84ab1c2f0b625868b728cbed7f21a23b760e7bd2799e604cc791646cf58fc48ecd45030c6d1f7a27ebf312a831c14daac3939348440b54ae5764a23c8bedf615b5f2e215406bd23850f0f2bb1001ba69f56fd916c85ec97253a6c7996e3c4b35c71b35d425c5f4fcae88e8809a818d1b8409d9d896e7334b74ce210e1cf9487189447ab37dcc56f72d5160b321bf4a1217e7f2080063269c13416b0528b3525b74f52d4db8dd7caa85b0f7ad561955fff980de2fc52117d6c7b6e21901e91d5602a3ca1d7777eaa9204e19e9983e5527d17adaaa35cf9badfa8542a44908fdf3bae6dd7d3a2a0555857f43f2788cbc4c082c9411d2bd06643432f9516ea168a71624e417617261423dcb12526782efbf361c87013c780cabfd46728ad3310202acf45a669ddf92f1b1c7e173f5bf8403c3d12fd2d39ef2e7ce464acb27364e78d7bbbcd54fcffee679ec4de1a3a10dbc39c0fb0128807d9a1fa8de8ccb2fa28c3f0197fdd7d229930eaec425e1c5e14b10927536bbcae15579f4ca6a4f9ba2af3b6c584af6749779d895c0bb40aca332e09c2acdfdece28c65a08ace24f8c37465329a470c25cd1d7027e01c30b3c7f6126488517f44e5b15b32ac32dbd5895e451aba7c99642ef05ddb9ec34279c4173e721a4ba0916f66d3218b32d4a068df438b55461ece51950a37493ae66d2c28cd4b5d171220e41f5603b448bfe7e679f8eae74e1cb2c97e0db19bfdad1c647d2766cd6e4491e84d6c4fb3eefe1a86b0cddfecff03cffb0dc0d0f385f6f611b7054af7aba852e0637e7c16800fc6ce164ac0c2d374646ae6cc2bec6e74989858cf7e4849cdf2610414ff38b6756b310ce8442565df1e9d7ba808e31176527cc4fe575bd315deeea1b86fb6fccf7634173ec07110b45d174ebd2e74099cd2439e0a8c8ed220a6edcef143fdcd5e866bc7a6cc328e94be4cc2a3d31bd1589661467c847dc16eb8f2ee27f299a2d30a2c90c8cdf619e0a0b299d4bd46e329fd7a50ecb5851b60a37271e511f707ad701b051d5c185d38a2fd16c83381b99195e33fb3b6515aa6e4f10cb118b2865e66ab870ced25c2fd4360dc06dc58ef2fee208569fd5f1991fc0311048d4889564c42a92007aad5bef0a25c192e48ee4574d6a488010aa2b2670d2167d6259b359f94edef12242fee391619679fbe2172b86a2f9657e0b098a493b05389d6266cef06c7d2b30e1c1b9b50968ab7453348275f790d687dbdb5332b40402ed6d57c991cc96360e534c785c645eaeb5a9e36502b3355b93e1488912843b61ba402d55c4b65298225f462870bba10c28accbda151c127d0ae6f935d3f4d3df6ca591777171d9dbd6cf58d2d856584c332395ec967c4cc354b2965f5c4cf4046b612b3980465286916a297d7c7dacf740d8e8a06d190eb6d90dc60d95d4c5571f3fa2a2d97de522baf762314478c594b6916d00823c7edc01bf314966d36f60f1069fba655ebc36bb3faaf6188ecaabfd17cc13bd2cc4c0358f801ab79319a7477dc98a0a30fc4afb0aaad5e009e3c57d32ace1073309e7db475b89705aecb58a6ec919b13dd0e7e21f09d5842f3a699da9b573469775db5dad699c79711011239f467043cb5e94d84870ffec49f41fc84690d064a12f23218a535dba20ac4378d8e995a623ced9454b8759019e3c6f63cfe5004799604791a5c0d41caee9d4f3e35a92c48d493e91f1f5eea97838e2d70d5b0cd9c72fcf13c859088565ee4bfb87406f8350f74c240263c3cd1d10ff8cc89bfb0072c54411b9c601de8be430f78b4332cdb6ff8a674678e256d6ed4eeac84dd5a6e4492ef241aec71069f20c51b80ce589058980c085dd522aebf7585ad418a3b263e4131e28ba630247416570d6438f9f86bfb79886391b33a455a442b6a46c0c38be7dfd3691dc9b6df8c6bcad9039f681c7b658123546574930bb0b349a389cabfef3f733db3ac52240b49d0499ea783ec90566f179d98021af231e17a20f4a03cdfe74e6428567af41b97ba409aa0c04ee2d2cebacdf9575fb66e12663fafe8a5225dc186cc6685c225cbe5686819a1d5db510c7765d7e8d3b0bbe2b8600a086b6f097910105b2710c26cee0b8780bcf3f257c4f815d23b1989b1cecb22a184020e70d19aa482c36269d140a49964563bc06d74972e66c293a9d6333907f4e00b993a6780f99bef3994bf69edee43121fbdf897ef401413c4899fac6c8072a0ea87bcb75d7ff50ef8cb8dd622268b7502538fab6adb58a34ea184b6d01ca95b11627e2daaa83ca73286a3220ba2cc039619992b9450a2f574aa1bdf2e3d175322b20556d322b14c794eb5b9e51383225d88bb94e650818ee8dbcb81c1823b4d90eed8af714011733f9c3c2a58d92f75ab295d73fb5b82d40def1a4b245c838eee816eb3ffb0db9ff7f78cdfc1644f52116405452dc21579763c9ea7d15c9ebb9e024de0f8d56e3724d94e66d955616c12c139850834b7c3944cbf0452d2db3821f9ecd2d72e47ed58c9f74beb2ce40841d960b00513f856faa801fd138fc7a90cd0c1f6253bf7070631fdfb814b65db01151152cef045b81bd6edfebdc3e272c11f63c76d8f0a38bfb9e8e236415548e2fcd1f9a04a2e4b7a41f9959c1fca29e13e58c31a87efd6e7ca3ebc749f40d66a0918f1339220a59881bb3e4903ed32efc61775b6c7168610db75d6b6c5a70808c25cf5f368bb4ae90e89754f10aa224f4f065bbcbd1cbabd6614cd9744f65231a124546a2e5caffe510ab718b6af7c7221cbe1a6ea70d95002920d70adcd49872df5b9025393394ae1b59030765ba60af6cea40fcfa1867b397422ed607a528bd147804688ed9b5148f08d10c03d337c26851f51ed3d369163418a67fdac018233a036c13eca3aa3ff61fa4434d2a9484995b017c3926e252870b06ae5d0db3cbd8668ece5b79ba56d70844544aa7bf1d86712bbd34f91c8e1884180a977540de7608323fe4432f81bb2a79e60333ffb4b8f93c8acc345df370e9a23c90de06839c5122118ee94fea29ed0ba17eb49e71b55dfd8a0ac0eea916a36deb50324ee3d3a925ea625463b6a9b9c12fc514e27d07033366f58317d7921b41c0e0576025a2780273666ab210c3f66435e03914003555a9c596661fa66db8e5634737847392268253a414861e000cbc5ed50d7b21c8b92650f351503d2ee1237b8db802f22a1b6d32243b2508e764914fae766109479971af162df0c55d00c1b0bbc421ccf2c08bbaedc5d8f70164abb3735e0ce03a5c538907e04865837c88acd7422b29727ba391069ce713d475d2302aacc5cd2a6a9486cc54a04627bd4014ec19663033b57f5f7aa69a83ea00cd6edd48d4f89e2bfc4f6f6f408fd12bb193ff331b0abcd7e5cd4ecd3970cb6b65169319818a1e07528cf81b6f69092ea2cf1a7791de95479e828cf70b01fd1f62d0550914ab326660e46d3f76fc582edd7044cd12d5476f72273c0e595f0a858c432affd48263b0ec00d8c39d6f4593281f861de41759b6286464f96bb17a04aa181ae40b38384dbf88408e2cea59c54c84e74f50cb53838ae00ea08920d30386f72d9efff43aa5a123ae8a6b971a2c11466f4c9e1abe405e4441ebfbd49fece6866c16f8dfef205a79299ea29c12303e0d26fa162b20546d3706c208f465269370de344021e127b133b9b21821c93a9d831542002704277f62640dfaa8ae19555b8be11ee198206ff966af164fc6b0f44e430ca335ef215c6d63b4171a012df3f07c03d9479b755c72397be44d91fc0c16b841487e6baacbff0b9fa86fe6ca37d6b883ba7d728c404739ffca44b284ad847dc73729ff2a95c065b7f4d2e558e7b5474a09a8a5cfe3206f23105cb1b29e3f9988b85f3409825a78e24569873fcc37323f0ef3bca40da3e1d0fdbc17eda9f0146b134890af5a724c09e15c53e7ae02804910844075857b99ecda8d6c9c943ff7578f0b9d84e5b3ea1511d4d2b955be39525983b9a9144e9f60eff6362928d3493675d1e3f1ebc259ec1df98a1b881466412f19ada882c5f9158420fffb2d5512ef0dc1e95c334aa1784df2057611ab0efedb6ea6da9787b1f2e1334e7a6b6c5a6a9f04372e86f1cb9fe9e8cb33b62d3970a4a92ba71a3dcfde4e56ac0eaac12a8f73c155d0ac5fde4b380262b8403fef81d4f2c577d58e59c312b1a01fb1fc8946d121cca86d3de2638369546f768b3918b273fab28e235988766db21549c48077004c22209133e0cf124429be22b91e1d855155c00ea3d615c2b26a583ac1160a4969e29fdfe8de772dbc670f0a71a77996b75b091db7d9523ea751504c9c53e7f4a0918c2005e7431cf998c9f75adb122dcb96f6820769273175ee6646fd3ff6491bb9511c31001b26224354b21cc2d191b58ded073a8e7ce543c900f28be3208fffe1559b1533e7955ff1180060649e0c9ec85772f85039a03a6b8816ef464b107792006559878fafda297dacceca62e4aed09d8cebb846ab825b647bd1706012a853ba41a405fbbdb873eb7c0dfb03620c2c251db9cd8b4e4221fee9d76a48debdacebf99eb313062457ca3ac6ff6bcee16459ed0a98f0d0a346bc28ac3be9bcdc25fb53f09bc0d4445e82aca0df80705401a0c3871f5e7bcc5108fff6eb2df32e47531842c5e86d400f7b9b44a22c8f8e8a6169d76cbb95e5ca49375e83fbcdda9959103b37741a41f31dce59505675b68706a5a387f167183ae6988b0a3a9008a4760284fb4d236f90d10f88f2e668f580f6409376e6398b2849ea2688d485e2ee12b7c51959d0f171fd24798ec3b173fe99024e438453661cd9f5d606b0f48d0196f8a5978269f01b0bd6d32fd798578857b27df6b1fcd29efe81448ab6253465688bcc7faf35931861ed3eda0964caa7981ac795577df7372055171fce5ffda0f238e3d9c87d03ee69316499415ff3e2c400d52a5d1efc6ea73af8cae0ec103c9bc992abb4896728896aea7367cffbc1432d4ebcab2709ccfcf88f95d41296c1ca0480ff5da1e84b2b5f7b7164fd09cc7d69db5429e048d885578387921ab7b5e9b356dcaa0daee1b6d9bd991e31468cdb7b24f9bf91df1aab1f7da8034c9aa25f9cbb4b8314e07292a058f57eb3d988c32dd0b35581f61ad61724010def680f94885852d000a684267cf58d6ccaeb489e45888ad3f9b6616f082199994d4885f03ed5fc791729a1dc353c67d1bfa455d58cf38721414676dcba1b7990ac638bdb88d94e67a291501b92d48d93da2b36cecabab127a1cfe187f5bba7d855e1a9bd2c0c5280e8061a4c5c66079c63a973f3c78411ce61792bd681a92d5b90e967fef3170fad33af85d55b99dbd2a24595ab4afaadfcc86bdb33258c13ffa4a34e06a5a28dd7c9b41b1f5716131fdf28235d1dc48f9a1fce7905aa0c5faedb38e53d0a54d5e4f33e64921884b76a6179a5730689bf91aec98db4d9d21b4f7bd0b40ce9d6eebef975e796658ccd9b7161a454cef143c7bd85a0a878864ecacd9244d90ccfe04b23802c9408d65f995708a7683da62526942a39484fd0010719a71c0d39e8b475b987bbf2c709744e5b9536171a4d6d957bdfe1fe28563beda737c51139c9712202b41d1a6bcd15a1c531d9c92f9121fbb9cc1f32c9c30466be69c54cd4191f3c472dd972bccc497adc0319e642174b42971a7b4afbbd645aa765a625d181c7aad01a776481ab18c1e9347dd61c8af2515df17daf86ec64afab54ef06faa86f54e5a47f5784158a5e34eb8e0185901f105378aec932fa0b4e105e295615372222cef37ab38bb0a83a0551d2d044d1d967c0d89500c78c621f1eaadb7cebd5e5fcd22ef0df5f24793ba48ed3a923f7283eee38bbbd0c4d6f0a1f618de2442bc2ca3b7d6745c81a054a58c919f5e8a7147d23c1a666cae23cf859aac8efe8e0c0744f09694c8d3a55506b2a2a1d5c8ba60ca89be065c9f6d1cf15ae120b9e9de7e257fa7d5c782b703323da9087474be5d3c5edf120d12f34799b94f69e2f0a40fd9a782cdd4f965eddc901d39d718fdabbc1df5f01aa356fdc3385f91064ced2ab62aafc37db222834a4c679c6a1fe8baae69bb46e1bb18ae225a9a5ca0392a6d5f5b877d3e478d522fe520c69a14002897a4677d1ee4b8b72b8278132d4fdc2649ccb2517323f6d8e1dcd14f037fe4741c60b3191e9aa7c73362815b1a1b8303e9f0b8d6c8c20f95f4a5e17c22ce060b812106916d57764cfe5d3eab0306af84d469f373bbbc3807fcd2d9f47478d57d8a67da7c879594c6d0e5187954abc2077d9afabea88cf0ad5ee6333e752ae3488c97b740f9ff93b35f8c974c9b756b2a69f6572e3b8eda049f5285c0a13eafdafc43256530dfe390fed643ab53fdfb5c1e1e7138c16c448c329a3a01854eabc37dfc9d7fc8c114fe3334a60c0aa0032b0e75d164f69fd0c2bd4fd8a79db55780762687f72e4da839913a26e51bf60305bf9f00493783ff4693c5d9f9570d43a079539d51ddd00df19d594edd247a8b7aa5fc763bf0c330766a9ec69d5dd0f091fc06161663f2c6b4bc14a64aa0b7fd085600cbe3ded804d0865d26f9fe9aded372a0babb3d1052e181fe95b41d08e81d446e49a74e3cfce38b736395c5b57ee371c5d3c6d5c343066369c5aff617cd47f577981ccb6c893dfe6405075fcb41507de7f9bfda860791f4f89ea4c85f2d16edcf3faad2d12a3e33b1a3b50946d6990b89a50c97d321229b2d8929003987f891c7a8e7f1256062efee98257eb29f2b8f2d6e43ba352026ea7b2db33a415e6b96134c3aa2b3bc5a677d8aef1c891b968d35adebae16751d4763f4c9d30120ee4f14c2496416ae735ed0c4685f44cc589a44fc6ad0119074566a66d366f3600f315e836ac1b8a74c2aab0d27d38031f01aedc257ec9122da8c010c667282ac3cf1531835283447534f4eada405a5ecdba362a819402f7cbe4cda4e09625955f5e394e92f13f40f17514e2e7362204d99a876165577473e7e3d28b422d2c20dd8ac967ebf21825f06c52c280c75a9e4a8be8a8562fe62c8b8c1aec74920673443a0ca617bbd69c7a01f5af2e5bc8d32974a027de8421cabec7ecf0ff2f7b359c564b319db6414c981c47d3785a364c7d3cf80784beeef6897c8fbe6a6a520eedc5ce30054a20de51a58e56e62c6ab14ecd3870d0451358f2934c803dad55a84071ddccd8de3df9ae84136000392ca9a50ea8894b82589704f56b5b015f4aa89c41c02c9cdc5e46b5a21e174fea46dc89e78f7b7cdb875bc48834793de7fab90a1dbe7adcab4c6c70e5f6a65aa57ef30240376decb9664e3c35ee0279af2d8191ed21db1db3cf14e736e533a9d39e961801e6882185bf1673e5e31e3d1eaaa839992f79e95caee6217e31e7c5dd6c6cd413e5f4a5a5585b717e59f3129c3bd70a0a317cc70eb38926a323e93529b11e3d5c7cd80083f9c63fe999ac7f91a6b60d266e0c4031a4a6fe8f0362812134535bc5f25cb8856cfee40feb6f0d65b4ec49d6304fdb2d4ae4b2281979322cbfb4373691aa571578ac68d7966442812d22c603bd70206a6dec4858ac57cfb118e9d8989fe7659ae478d4 -MD = d00b3e79de1aba35bb386d6e939bcd0d407eb5e6a09bfbc50524587acfd057c5 - -Len = 48032 -Msg = 50bf7a65c2fd46ab2e4221646a9b2e3063d1653e629bf11b8e13d6c7b367d70e41d1971598c9fe348279de030171d7b84c9c78b01472a64b0b7042fda7c506a2234fb012c8c563f66a364ada35b27e83aa472a82e42fed0920477ffe7cc3984eff200d84da5b3c9aed61ab0e8dc6ec3985b9c4dd5a388cfdd480d6f1b9c854b9dc2ef69256f253c714e24aca9215e983e5dc8de8fff64bce2f038ffee73b038cc260b364c5f16e26e6a16f34ca083d09d397cfcc5ad1f42439b8f24f8d866d6eba9e8b23afc2565e6b866274bf05af7256d2d0b0f4324da9fb88470933105a08cad0c8f79accd318ab7a6ab3f97508667775dabd537f20037c59d55762419202fddeb0071077adfcaf63d019ffc1108f3d69331a012233dac415e55fa081dc0358b18c7c982babb17e2bddcd584f8f92b09423f186814ed7dca2bf49783802b3e52fa37dbb5096e020b8d6f88f894d1ad8dff46768063ba1cbeaab3e6fcecabbab413f33ff4e36309ef406c129d611cdbe32eca63117c1e199d3f1660fabfdc3b2d0a6c6ef8e534affc5b451b09da553697655d6681ea73f4f47d8e8df38637203c2215d1076b5d54b1527cfac48cf55e191751e9682b662f42da9ec67dbc371a501f820ec6f237a8acba864a33e587b2f6d95a742abb6f3906cad9c30fde667a07373380ae267e1c5cf7f381fe7086c5af1fc99f4016f992cee291ec10795fdfd02dacdf23547b10409f472a7aba6d16a04f41b35eca8fdce9a689aa25f96dbc39574062dd28c934d614f3bc4f2fc516890c3558bd42bc78158b1395c6fb1a8fa138a0c421ffe2eaabfd7bafc24d0955b7cb2708121be9e4a104b22769eb00daa666407b986642b220bd518daa9eb444bb009949c3b2a2a33aa7f7f785359b1dc754a1e1b6d8731bd2d917ce3e91507401310e8668a3614430f9575ebf8763d98288479ee3e30e9840d530fa14d1586438f0f956677ac048225d52e56f4cd58e4675941bd6025fa7e9363f89b3bb5685b0b4dc2246852a1f9d586d241af27abca1a139e0d3b2f0eb4a80860591cbb569170139829c6f294af08f28834914bdd5129f8b7683715ca2c328c6f6459f0f7eca4a93ffcfa5284aca45f79b8020397817c51b555bca1d8f01a354c43581cf4749057de256a3b1af99216cd546a158163fc65bf5d3299e008494c207e8307f4311c659e2d8074fe9dbb5fab91314a42fe8f7efe0601c6897aa618129e4178a02c311aa69ba3c7d7a006813bf6bf6a835b1ee29adb91f07c5018e34b2af939a06cb5bf1ff73afa4e0b5ac6a70b7c3deb8092daba614bde619289f3f3aa15109bf9929c30caafd60ae5a1741458d18a2377d1ae8622955adf46e09231a6fcc639dcaef9029a6923b436c2d4ac66241bd248c5a627a5d82a9e7605062da71623231cf31ebcf2d0a9f307a52e97bcdeb6a1f9540ac5727d174729df971034cbee01c1475287574c2f705f32cafde26824389468218712eae98268588f02d683f17ad494df8b53457fd24651ef0561282d3e20e834960c8968f63a57342a14a6f2375bc10bef6d235fc2c4eae7d7c088985ca6bc8b1ae8c15c4ca7c5d0b1769cbae061b61fdc2e4e98e8e2e5f89c87ef2f392dcc6e3a2ff98c2bb788a9be84cd111ceb5b62791c2ff2eba72a6b7c3fc5b87ebd00251e689bc13c7389077ac7a2be9303981eefc12c34741ca1889e6f71fcd25e40f7ef1b0ec327e2b0340dc6818beeb0559965a5ae282a4733962b9f5dc3de19742ed5d0ba5a930ce6779e09d33ed5fb7a1d044e1e94b632c6df4a57f0d549f58410f710074e28fa1117551901a0efeaeff0f346e241bfe543a9242092f9bcfb58e67e625d668fb31a5d5b7d7179e5889c5a5b1564f7ee66933de181abf9df32d8f7914f246b703fea91d8bd8d915eda69a564410a7debbf9ce3a803a39b59a2ed8d595ec42672a768fbf362bcaf03ea3f1735543e9d5df848e2a12ce3a8d3537deefe17a55c3ef27be2d5f3659d7cbf04faf7d6671dec177e84f587d1e7f44e7163a7022fd87c280d90a6f8f2217061a294d14decc64126260fcc99d622659ab2347ca8cb61d352054b8dfaca0488d9ff2eec433760042c27cc4dec5b1fcd3f27a9a690dfbeeb774a5cb280550d6b2e050f703fafb3dd326b03a107c6a7d546b70a4d42d5b86d9fc60b3e12fb06c1689a8184cabc86723fd9fcef72808225b64c9e9847131701d2609f593824b53490a8ca506bc6a36e5b59fe60b6f2786497cdaeb02603a34e1900622a7b38e46aac1633fdaa35d0778ed3521c5a83513af12182bd670b23fd7b8e9ada629f590bc7cc04b30f72d635e12f414ae69ad451cd3262e6939561b501f3909076c1ddc0e6b2859923e37d525b551113e2a1cb4e32e796533108231fb2158c753d07373113b0fed86df18c73052e0a9ed7fffcdc2928652dc9cc32e396ddd5b141d7310555aeb6977504cd42e5a076144d1c2fa1b9dd199ce34956a8b533b56b0a9a91e4b594f6ffc485066706949b9cca602e45eaeef8c708e75616180072cc1eb92078394a0638e1da008a6df3c35fd833c071c4444bd7bf0efcd6c62a55fb079aa666ebb82e69546d835224a33484fefdaccd50c559f391260e90c79ba6204da7eb59d3c7b6bba6a55767328e3634c526bb00955a6c44059755eb2439ad657647b6f7f85de5555ee943729f9a1397b316b5b39beccaf2a3c99990e4eeb2f00ce1d0e86263045f04a3101b73b111d45235628d6b61bc24f324a2270fa1fce997df02d519c25b03213a8609b7ba7a142aec89370ca38a027e113757ae3ad4799da81266266032673c166de5739d947ec1a1f45886987cb5cbf622c8c7a082c8a8a4c8429027d1b3dd9f8d56ad42a83ba1bd6999e22ada65623c292365bd4efd3f3bee125ffe7f108c3dae056f91fd7252a9b1a22740eb39cc4c15108d787f40ebd54a7d9bcc86a6d2589799c072dd4c5acc941a5dc1f85a908cad3649b95fbb32daa62c4d7b2c9c365811bba9cd8ef1438dd9a98d9749f03666bb3ea06834939fb2c8c67df2ba1a41a5e413308a598895564af8bea92622474105cf9b6e47f3b7c578f43119774a79a7d84860918639d68eadaff8dfd7184a85559240b1e001047c805e73d8ad5268c6b4033eca5d2e909ccb764321a3fbc799712f991a47e50d3da7ab4a17a25a966b42ebd41d268c4aea6cf3a857d4f346e7214dae91c3c85a71b484bfbea08b8afc48a92973287e8ddf57d12e69b02750d62f9485ff9dd274817090d8b5ed0ccce38fe445b2ac2ae0e356b6de3f80c06cce61ae284a1e2ae2d3a3789fe4d106e486df4531c4fab8cb5e2f4bbec28be5233781409f5c8bf92cd114e31c3496a15b4f0074f48f5a51d6b8ab37d9d81bbffc7a55f5f01b2f66dbe28d7a568b8204b7a5b91896fd141d8a5a9222346a76767ffda6722571519a766dd4e555d3df5883efd3d920f56f436eaaacb6d961e53134293b62464538bc85dcb3cb21f2f3c444971761995eb4eb0b11c198cfa3b018a466de6b597e2df59096efd4c3d2077184044a5509222c3fe7f898731e1a1f54561d55356806786d200353a942596287ca9e376078281c648cc5faedcfac7a0dd2b469697ac4614bbc8ba6f2a6714e2d9fcda528ef58cf8582e2afaee843086aa195e2af98a030b8ed96af56f701118b8af95b55759a8cc84fb57f5f74c612944a2688aec9822cdb3a8c377e3ef0f4ca138a229013d69a557da832a8781de0b355d1230f15529edd2bd5061283283f12c2e8c281d0f4425594218f30fe30baee4bfd7a7984f8cee548d9e4b9cc903a8a207b03cfb4dcccf01a8a5fa00de7e86db31156951f5d041c1a01991b23102d5bb4acad22c777804d994a6a9fae2ab15915777f0bed6788a928b3ece18f905fac06e1872412aba59598c978d6e8e15fdaf996bd82f6ffa1b5fa58a7b319f819a69f835a7b9c6185efa06f51edc3f43817e8d6d8a3430e996819599038c730a37106fbeecf6d82668438a4bc8b474b85396a9f9715db7ab6e90c1c7019a3214534c3b00bc98ef4917ce8d083587dce8d670559c380c72d41615b0b0efeb5b147185f09791006a14efe385b6cfe6c669aca436c248e0d0d81f78f8d348d04c9f0446170ff4ddd6fe532b1ad40221cf9f28aab4182e5b704c0d42f09a871985289e0514c67281c489d41da2ec66f9670decec53ea52dccf9441fc3e9335079325a16b8047748ca13bf533b47c88ae1b4a6be1acc550f55d35701d4949dd3b053ab0c1d02f856efb8938f5d5e0c1e05ac928331545932597c3fa2e972aea1439bc4ea08adb1f9941e611ec7dd5cd10b3fea45923c7a40e0db44298aeb2e633df4ecd9016d6cdabf2f7128012a7e4bfa57f52bc6ed80def3d8b0bf3f67e4c0a3456d0191aaefa17bd20ad494af3a35dadbfc5e54d033b6985bc98b914e99617f768d893fcc03f5cdef764a07d25a37b4b24706c44c5a70d94cd9b6070815edd86e9599943b707ebf6ffbb3e2fda4f88fc61e499fc8bfb4be9326672afd200db717cd5b1760fee55838e237ae97e22173fec9526cae28284e19f9c78096826923587cf550a175d2a03373fdf208da5968428f47b3655e7791c499fe933902a82419eb8fc7679ceca048f52e36b75549777aba51fd5529478f7d5033eb4f6a72c2426352051b3cdc5f60b2f1030e1a99a78e9097d0e65041512d648e0e41807106bc2a6591231d49e561f06fdf74f3f001675a42b7809d0cdeba1e3886750d4af76d88f1f3e907dc3b35f8cf5551a6f68beb5f79378bd6503e0ec659db55d8a89e3ec71eb4d3c23d68c2123aea0efc544f03e965da6fc4b77a0fa4189348ab3101172e135b4b151374f285d82811bdb255983e2d27942fe799a7ff9e38b54c8d2ae104f970b8ca0768ab9bd096c3b1b7a390a7fba663df88a3bd211351068465218292f77b82a7c04bd79a4bbc8c9f0c43d56cf4e0429b43a138509e67a21b61ece42036051075e7255dcb7023d551593d4dd5425c9a2cc09a02d56701f1d92895edf5de95ccfb23ff25766852048d4597e22a0da2d45ba69602f897a75b866324875b16b41d031de017e35ad1831c785b7bb27c3b56ee9d9d200056e248e9b99f999806e96b537cd01b596f29b8c69b91ffb6b8ae8aad4fb84437cb3820cbd3100bf5d7bc1fb5e9d71922cfe10d52563f587ee983d76261ee56e31f334bf4587ec5bab1b59fee0cfef984a181e88a506f6d523543a4d37e483e4d795b312cf1f2ae2fbb5d54c98c4ca3c80e92b3343228267ac7755bc94ccce4bd02373b3b4673b09c1e3ba60d12caff353d9bd519a3736b3dc5a1630c7384317ae24fcfe8fe09b24801d8fe81457ef6155624b6014c5724e5585024649c780bce402b57fcc2bc9d7c8dbac2efce726eae83b5beb4d4dc39b8a70806996faf5cff4454394039955780ea6b5c1d54ae504aead755f9e50a92ffdb54717293310a561851df790c9bc99c3f7332d38038852fb311e39924ea18011bb9cdb9b106fe1be1aaaf72e2d7db18b458aedbfa1af4a507ecd05d3b83b10890c1823470372196cae813f2644f763b73a436fc695c84f60eef840ad2dd465a61f3f8ac79ca5a0ff89272c03a0d804ea1de34fd75041f68efa2686b9001c040b7d797e873ca90cd963033a50b19e399698f0fa7c71cac45d38de2471ef60502baf6c8b2073cad19ca4ac0697f798564f13e2fc207ab12d3e1395b6523c4ffe891d7f1d0dd2a983bbc6980d43f3750f76173fc16ddba3b5b422d3c8e4874943a65037c0b9c9b397b9614dbadf35b2a99e2b7de6aef500e241df1eb8a350dae3f5d00cf2bec9878207dd439be43ebfd949c903d87e87573789b0ed22191973440a25854f877283d749b3002cdd5f1b02eb68981366e31529de40b571b051b0e855b92713ae25370bd18b09ea354742bb05827123d298d93dc1f70e43f389f2456b13790b8d821f9441cdc7608667d5662acf45864c3901f7d74c6e056d32e5efbccce183bff9bc051ce3df0c4b313198bd777bc75e143dcc80c93b3287dcda4bbd3df718bffc8ae2c565a759ee43e5c740438a4362eacb3050f62c47ddf86dee0eff3027081b1a91cddbb6e5fa106076659c079714fd58c7ba5b87d1da060f4b0479135b22d5c9a6a8be941cf917402a7fe96a4ecefc65073f41f45d06964ce7404417118aad36a5f876b58b65d8f357f1c428b70b486e535271e845de29854734d8b1f6ba11eff41fac919dcad608838db4d98c4461c3509643ea38db2066ff74bf8a573b94343580b8cee0927ede419623e32b24e932737d305082882b60546250f6cf89b4c1deee33b3e0476402f69da9dc00074f0a2069efd1cf6f9aeffa90458dcc2ee407449a95e7096406153716af3ac775f3d90c0eaae47bec0f84668105c5d985b2832b2867eee872e5636793bc65ddfb882d8abe29ff24a7e9cc1cb70a258448a0b3e71a2221f9fe729c2c875a13b0026c5620fab588360dca0571a4db3338c22f180ce24d26ba514e2dda83f09aea152101636706164c9820ef29cce155839cce3e01134163a635c87715fc1881e8ce36adc675743fb4d17ed799a1c522d132fe74681fc77f49f6822653624a5f38782dc9ce98885b2b34446d35c5ef21ce1f4089a67a17c0122dfbaa17590e9955bd76c3e052caff0c5b020ea2abd7b8c6dc24bc40b4eaecab46a580d642cda6dd08924aa036b491c490383a54c6177e57d42baacb52993b51cb103914b2102e1ad410cc82b6cdca008e778ec09716d8eda1b5c3bad5ab52b245bc3157196e95abca62b81c458efe3ca0205a7ab16e6f14cf639573a0a9c959211a0811fb41541c36189bb18560b4d56fc35be787769759a7b5ae9a661ce592f7aa3bd9da310fc8b192e5f6d8fb746767e0d1ab9bd7e828e51c6da3786d5e1c33fd3b1338a62f5dc7723560c2b7b36f03097a1b50fad80ee21851036a2399316073946299191927d236f863d51df858db9da3cb6967fd78392a075ebdc80d9ef7bdb62c6e2273d38c41ad948296c9b15c2ded402797bf0154d1ef09d5d341a1842c3ee53a2ac5dd3022d3674dca9e150f2ac4fe2e12a316cf90768954cdcbd5705f9d318fca6591787af840a921fbd06f24b979ef612034f3f64c71cd2012c756c83f75d169f9bccf8a8ad52725498fe69c3927edfbdcf87c73cf478172ace3a1e6b446a181e8aba00209894a5d2db01001d2acac5b3fbdd3897d7f142df0b6dc4b9a1862bac8ea845202d185321ecd75f6046c9cf7af1163b7d58d17ca94bd80573f5fb77d00f606faf5425a2c735482d94cdc4269c17fd77f75f5eec0ef6418aa32a0f231275a827d6f505bd4e1c1c12c1a903f1a1d759950cd4e2bb987471fb50270b57fa2949159cf8feca3e0b1ab8f0c1ce590f98f13cc59fa310cf2e30ff83d4373d11910be0094559f21d690bc429fd6d8670c18e1528a8ea143a8a453e4319dafade16b53025c55e5c759eb7e17245279f4bbcf8c740d8feee61f17a6198de3db9e92011aff95e5431cd12e6b5d58146cd29f0f7fb121529c7cccc95108a0ba9a0bb18e5038cf98598ae2d60e85999103791c55359a848b1c704815ff2228864d7db64fad4e67f37ba9f57ec230675ce060ba3d388095adf15907aa0b0673db687d16e18cb10d6b3be28f8540ee5fec7611ff241313d31fbdaf81d20f16213e9d8269d068f11e841cdd1785e50fd1a4571561a63fb4db74d3dc5d4a65e19f044f161588ec9f19b280f233fd39157b28e5d3783018f40d21c677e06fc9f96be0efb0a097621b9d9b2aba5b57a7bf9afeb4e4b96e5941e6cb280ab1ae85be163901daa17873e708925cae0421db4edf7a46c18b9d6b3ef6c55afd47a333a00c91280c8ea89c91e93ca935a4f82e43b7401de28559b94bcba4e1c828da5e6fdd6db4becea4469cbdee92f9d4272b4e90c4acd03d3fdde8c3ee5f03cbb0504df7435a79e7f80c78054cac53185b5cb01a9c6602f99c43a68e061538b6c1d3faf8a66bc6711048b45dcb47e9c7e13d38a32bec03611b84f57880c6cf608b33c74ffb7b1ce08995c205ef182689754718d8f7a14a0a2a0c6611e2c6405f790a636bd70af5ccc07e21bc3c7f81c373f4f11a84285f3b346468e8a0a6240a27c23feabd9dd97c516c63df17f0841c59e151e655e3bb9ae7078e7b4ee8f306f3e5bd3b13a64095b8db08ed160dc5eab376bbcae155d79fae70373841f135cc7a0f8bdb7da6b3af73647174bb499fb50d2f7f46bb114bcff73913be3e7154c13689fc4a5021bb1ffd734df48c16aa11c3964cd8478870925dbc745b78cbd89b95ffaf163fa9cf6dd391feeaed175d677335850e1b3dfe8d4e94f9bea57349a234db14bda0a1591f724ae4d672ae225c9877b846aa943e17463d1456290a207b7fa6cdaf07aae0bb7608c035914da137afe777108a4dc7d6d12f449097f2f59df2dd2a78e9191 -MD = 4915a5b5c893cd4ef6a7b3aefbeb997c00c240c5b40091759d9d52944a89e419 - -Len = 48824 -Msg = 51d87c952fe3b233d4b43cd953236635f17336c48828f2442918e26d05c557dc8eeaed50d9540c1847f3b5cc64317b3c0f82cfa6dc3d812cb6aa8484c95cf2f29fc14f7388f7123b40e16162cc7b1ddba56a1ea518d8c045ed7e9e7347029d14cb842d680474cb8506a6ca0452a854fafa53ac2a06a0b57815bdb8a14860622a5b5c0c96157240dce3697818c06028815764ff9b6c3e6aae788e5b76931e481c977076658399772a1d52f208dc4da25804c5a1611359e7cd5c1a0d5af2e357d2c7e9f23d15927a55fd8bc03a6f15c967499f1ae5c39a32be0a8959b52b57983433ee098694055146cb396a184060a6976e1af08e43a8556aca02c4ef0723122b23a841a8c99902e6cf87780819d73fceba5dadc35d2d58b8e4add8704eefce9dde3e250b79f7971c519b7374c0219ef57691d8eed7ce418f9fb31ca1c862d274add93a186fc717cf989de3c3fee7cbf5ebddfa767a351ad9443c18e83c252896d8a10a3572b08be9edb64e5d9bd1ccb45e6a9ac30e0aeb7d1b6f55ae74e0d8eda7bd1ccb495afa51980d3eaa5f86ab1c1a5f403d5bf4ba636c755a5c363ae85f6156f843bd6e6cefe1cc3a1212af701466e5754c289c91737f76af584bdb62d6509327039694eaab0f18cbfd7bf321838924bf583faa77959b99dd0c7b6c4d39ba9d30759c737a6d6c1c77d363fbc853cc43a9c966c575b10a066bde8d95b270e89b9b0096b4271d3efdc9fc926f6c6b776bb807669591af12e6e1384bfd986222b6f10b4efef6a3cee646e0d0f616b3d2c3767a07c3d577fc61c8817b4d07f9b016b8008afaf1e764fd78e7e538cd1324746a8a10f749f1109ea721e62c081cd9e27b4613501fd2486ae67a98de9973b7a51ca04bd8f40695c606805443a1b3e643bf45b1a7884ac15618ffb29082bbd17f15227e0fde9cd5006d068d3adca71f600e652ba7353818e997e0fcf591d3bb2adc7a72440f9c1675651b58b8c1decc62ef0e4bf92d85964aea833bb6cda3bdcdf90eef1e90efa14c75277e6557413570eba8d745781780a299523a7a3f141e90f548bd45687bbeae2692c8eaa6b8a2b3899b98321fd821182db3c0eaed0c289c578fa3629f2ab4c3ffc4fbefb62c5a52514f566929afc0d52d1094aee1742119a74a6a1d3ee3cdb28825e21b9083a676cb2dd9929e83a40021d07f6d2335522f6ee3da1d4b8d4fa4491e44173ba7ce47809be854873e16c2915b49cfb935030432c1bb0bd11283c0cb15e88abf7e1aecf7024d57ebc75e430619ba7ead5e7cc37e4cd58ed559b12f9573971d25f2d18eb8cbce44d206c4aa0872991f07970492d7ecf04f614a21182fa1197874ea3d544c5c34c344e390201dceb05dcdc7e499c709d3f57ccd1aa422053642b44da4673a1f467b4a4609cccf95c5dd09d86502d50b47292fcae6fbf509b624ed054fee0a7ace15eb1778d7a52fa14ac2b1cdf28a5a14938129cb44301460c528f9861245d79238303e256827040c4a013a64936c5e02da7ad212a85c8dfdce6d1191fb729d5c8d1fa358a8de7cce85cd5b740d0580d8a722ae024e00de55e6c235b7d01934f2bcc32f59be5100aea52efc4388dd2660a182a3e55ea46e30b6314d41bac2041c6c21c86fd309f6754f2c051a2b7aba6071a19a0102d0a556e5c14177e0f675a4454357e40f8cc8eb2dd05e411e66a2a1be877ca0600deb8f1c7af9a16b3cef51f130c5fe9964dcd8e721f0008a2948eb313d2f08a0e2a8a203655e07821ddaea15f0f8069a189c042527a19f9749120672ca9d81ebd84458418956f14e209e385c8cda4339316f378eeb5a656c506ab92836ac55697627797fefcaa6f6cda3036b0b52ff9f36bc38ca74049c32c6b7cdfb8a46ca4144bacd649da36fa3ac5112ed754780f3afedd082cb858a1031600b95cd522a9cca631b999dc7947d46112f88d2a3105e2569c75ef6c7772f1bcf389b07b8bba1918b2dc5f7205dab224920e42b4df5081f98e505ffb0adb60b6b1fb84060c679209bc991b1951156c863aeaa872d771825e2f120ed2a73ce8a9c87928132924bfff9b8a5d50dfaa5c1c5a182ef2be0b7bfafb556c91c109f1fca37d1d1166940b70fc1a86a725ec194d9c1136a2f760c7667f7509a6dcd50525df81e39f49180cf44ae4379ab86d1c905d60600218340d17280b56807f20aabbd9221c0b45332cfff461d09a0bafee9b3a702b9e94d7a5938182e3cd1c7f4b353cd816e3ef77e3faa50df223942707b4afdb09e6f1de3942286631db39337f18571e64b7ac58da8ac9530cc5e654e0732a0b8b69c3aa30c9694fb1395a0faedbc45fa60500587926dddb910f76cc015d258c10a56eee149fd089f265f346630611262b4a9fe948355ef21f5ec9ff02e94ed73a0867fc5d1c0abf65ff998a341daa0c94f6bf9da05cc951184254603d9df2678821536782e4545a9c54c14d8a891b7d53a803e849f3a9531c48aa9249f1ccc75b8e95b22e8f69e5f603eef2deeec1f2e7cce15b8da07b828bd04107907b1a71548ec36ea853a7dc139b873cb9a559f7d1d3fc69e3c9bc69f7779c22a99077ffd3c040ef98f78ac7657a3e6da3433016a26ba98604f5e873dfbd30860dd861cd89b1b2d778e1af127c3e5918145ee0b9c9e26d5239bb9c3ab50f82a435c96464c6e18d98b0887157c8368bce954ee86bc8d6dc312a71241907ed270fa9da0c401bce35b5d8727e01ca112af3ae99a3971fc76aa52fbd2ca958e4721ae280a5fa18d64fb16926219b024cdb19b8c5cee64f129d40e1f62266287418786863edfd1ea8300deb2a08adf15800b34c69b6b3d776e886c9c281d9e71a7e8ab3ea20c3bd928b4dc6d49f9527b13062e1ec079a3932d0d94f88e76f154618d44d8a0ad87653b5d394ec52fb15e6de8b11d31e03e4f4eacafbefbfb053956be7add9f8c5d93a4441cda7cf4a3c778f9e4495768b7b2b9ade573d7727f2770c375d4076f636d4bb1ae9bd70fd0bc1b83f02d9ad9b6c457585da189a40a2796e35c453f1f44fa18eb17183c4ae1483eccfd4e63fae28e0ef440cf7b594c40b06757b8b164a642f43c7ed9146b7e70c91d32361894e417c7cbb5861459ed7aa79790b6c405324ec5ea0b67c83b4e3ea5beb76c236f63686b23e54dbc6b96dd61bb2cc6e0cc8f25753ee849be82fab9b8f7b578ea530887e045f8acdb59ef72c71b56716d7f65cfea803a07600829e9eb1054e3d7087b7e1079152bd9e99f40c1ff343ed3e75e550ef82c2a159484d72750bb3350556355e10764531fe44f4f38aeeeb57bcc20bec7eee33944f0b38a520113f3bf0469123d360eab1311a6a81271ad5ecbf65312ffa98abc57e25d0a556983a88bdb34bf0b4f3bbc1e3a4d52399099c22c2ca05a9d72473bb5332a6019d034dc1ca36d63339a120ca925eb559353d9680738af9d8991423fc6abc49385804d16da23bb079c5fbc251a9b29ba0a0196d8c2e027e3ab4ea54ff211d0ab80c0f7df2d25c7b230e6618fda64af8885e4f79bc7edb034ebf095f4a12ff9b1f4d75abe7d6f386cd67627d0524824c7eb4225387c26f49931c13cb53bcbe4acc80e9d3b32cbb73d76593972e90f3080266447374b5598196507c21a28ae3ca4e4ade9deb4ffec2ef9d5bdfd06807cba1d9286219b4047bd6f0b4fabd0a0a7a230fc65306bd37e464533dcf71365b07db8140a7dd3b0a78c371509f19c68cdac94423ab8c011168e43bbbdea778474d1df31fad35d6d608ea56d1b73f2d058cdf8c98ffe197f5b0cdbb4895d9aa56ebf7a327eaca03f1bcba25aabb93b9eed0a44d78d8bdfe7f6caf66867d9e492494e715fc08e04ee804c1425e24ce09b366d60b55be67b0f8ed07a1d80e5bd12ab87ac00e504f1413618e517e7b3478fdbfd34ab239753bfcc24511cfb098dec3d70145d1893cf02e637fb76e376da4284c2a8000a27d1c158d061ad01cdbce9a6148fbe7fc506f737b2408afd1e007bd8c5a5fe3a1d5cdcd9dc9417babab2d18e78066a4221fee9d2909a9d5e3220047f0d11ebdb015bd7f74ed0a44d57d76c9fa662aa8a2f209f5ed9f3f52d3aa4a322a2d610145c387b5b30ff9ae32c94817fa589c67f78d2e3849532db93bff321698ddab50eb55a90ad890842a3c24fdad67d650648837d7beccd3f97b8487545fbd50722f19429de9462d3e4b6a0713d4d37ddb10ed88a303d890271c35d92d98182439ee4810d2cb9c248c8434f63738bd9d811f8005fca1fcf63b1dc86b2a3a29d78720f056e43c4b14f3573558c44396e406c2f8266113ca94a9e2d4c3d6d072d8de79ba7b4ec5c38d0756e3c5377fffbfc0bdae606cd391e9f81db369bfd573a6a43b0f047ed295db3ce5b8b22d6848af43622b5a6c5c1364aa211cd341b3bcdf7ce7567900ed52ae08962cb6027712210352f76b0c27afa3349f59771915bec1cd21394f51905a73fedad8374336dcc384f28b18b8c0c7142beaf1eb8265ea2c195b2ffdfd463dbb944613bc8c2218f54cd35ef9feb20a4604868ea72a1edf4ce607831b70997ce34d4a97cc39c35734cf780b654a75e997331488108cbafec2b7b90b1e37e498899e7abcccd88508008152e9112876d5a64bf766de06c4d91c02e2007cdfc2012d1c38fb64e4f1abf706f6a054154f6ef1c3b1b36644c6eeb75c151bcdb4ac473c3b07ebfaeb93d376d4d5a9c49d6a05e82ed5e62fb32bb03337b4a577732deb356f8a071568e5ef0e5f626dd92d514b17d1c687b0ce7dbe0e0a63460087a16db74e21c53ac9628f3c2b3f7508419f9f0f71160090134778a6688365ff6eb13f104b51aed19994047eaccf57e8869f821d7156f9241df370aab6979dda84d7e00edbac4c8065e51f4478947ee048fb94e056ebda034b0c267999324628868fe0d1939406bd9ae0103bf3116286251e37e686471ba4271c1a9174d6074fd033c226f79b65efc51f87b3c0e89b508781ebaea41b469d3e8dbd90cde559d6fe8df46d7c44f2ad50fdf64a566c91c60cc1409724bad334fdeb9fe628f2a6446dd908239603256ceb05ec7e282fde5d0146a73e9cc85a31e1c032000a80851ebabf7dd7d96896a4dfb1cabdaaa4e99c21acb00350a633ea8676047ce7116edc41abb5f8cae79efbcb9c2187726e4bf9da4ddb93f4e708e568a787cb4317dbf3af185104cf02c6c82b2f716a03de6dfc97b48a5efdfd31a8e4bf4c69a326450b6fafcf9a6a4ca6907ae64ae3d387c82ae67b5cc2e07b56ab9747c2e68baf4269efbc92182117a6eb375b1e7375fd02fb42fcc37e20c3e0740cbb7bb061254cb5bbd9390c9806504eece85ca74fa076e439d34edf437957889194e755c82aec75608034f6139b3b22083885ddd514cc7c37796f64dd0e345fe25e864535127a0f6a3c16534848b01b15a63aa5aacc5c39c86995bd31f4ff706b92e91d1c9e9e0a25874da29a91578091cbeb9d4529ae93692e623706b0215089bc803bf301c0ec4edc4b727ef7b9f90914090318cf4c1f96324560bfe24276e945dc206cfe7b3c32b5b0318a0e2feaf8092395ba2fbd44ec0fcfd8c1edcb59f6c95d78cee735607dadec6e302741eccb25cbc38dcd6a99b72161fda14524803eb1a493bd5e87ff8c2f808705e598651f0451fb281aec9494219c4df28af6702d99120facb6db7feaa4fd2a7fbb9bea400f56cb0dbaabac1f5aef482a11b9b04fda565b0192a84815c8b2b7023bb4f2faa15ab1930f3066a567cb8abc9bd6b7120fc1f47084871e99e551cb31c87c058b84de2d7c9b034ab2c2c1742e6be5fb10a3e56a6deef039e3955ac582f469989f0441bd1ee0acdee3e651a304145ff2c831412b5e346c408f532e347a42063291ca35defe729589a55d0c85b227bd44b53265c5c61763b8f9994c968c33ca4a00211b119fb345d17391429acd0886574411b3b839ea6f09cef2567a3d3c3e7556b371d37735365ccb2da450b95933a10179bb812e3ff6c95bd8ac4e11edcb1b21ebcac3197b0f72388ca2561b7c4dc889b50daf178a936e4cc6ee808eab08c1ee54a63efaf709b83828bd0947f44d24296dfa909a5cbd6efe477dc028067ff0186864c5a03bed9546ac64e8e353ba4a8cff32d40b28ed520cc4da7b5282893c4ca1a6e58dbc03aff0622a83521d1db2110326f7fe619bade4e99510b2a1bcecd79aed1d27e9e45ea1f48e5738b2cfe141f4476af8b950d903003e3ebcd693b855be97eb13581837e7cdf0d2fba7795ebc5d24ab6e72957a03b32643c5a3a5f5437747cdb48917a23e7902951f7d8290dca84f47e42fe1e7537cfdce819b5c4a3d7f6d33afff5b44226033fc08a7741e2f6017bede63bed77ec8154d65203f1d801188cb5a1d6b94102df5a66bb7d65d211f2e7ed1a09490e22f1d2ee4d4b6e5d7e82ae33785b0f8a43cd7f2ad2121d45e2fe41652590bca2a0c7611851b6c49816db419ecaad4083b174b8f4165df2a332ce903c50f7cd9b2faa063ca86c7af390cc4edde0f3d496137d0cacd0876b54c909dc5ce36705619742cb42989418d4b6fcdbd80256512a338f843b48b711c06f582dac2607ea5ca038b7126a5726a54e14f37778fe41a6d7532687c6166a50ec638c14600006f51134d29566dc2dcd21bb9ba289122b74c870fc7992cc006a07d1007cdb79e192b4dd25b1d34cb5b4f79add417eba98fbce8f0ef9f3005b78894b92ccdd9b019d4fdcb74ffbce44c29858c03c9f200fa3b05862f033db01e03b7849ecaf8df07cabd89158248b645fcb9e4c7b346918d43872024498847c0ce2012dc599783699907ab9b297aa9cf359148ae685c03bf62c86f6df6b235462498d463de284595ac66a39479c5474e60b618166da4b0171553b44a7f3e20f4c37c59d3dd4d8e329144f19fd7ab175a0a72e3ae17a32f1ae7b3af6867ae73730735039aeb59d5c6d43d25fbe7be8268af522bb40ae9e9413662b1463465a5378c6d82276cefa4a8d1b9a1571e522100abfe60e6cbeb77009ddb4a425a064ec8bf802617f671837f3645042fe0186b989cb213b4cf2a40ff9aa80b0b6d02d89d1d178fdafc81faa06e69bef4c173dab70e27c48c7918ef94993353ffd1edcb2b219e2fef038362c2e692423456f6e6e25cc9f3fc7e59cb463617c5ae2d299f09697e76d29018544d3b492e6d0504288125131273334f7caaddcfc084d338ec9e51430514269357a5d908e40d504e1839d39db09f2c7c6c391cb5e51268ae0c7075865b222b96e5635c5c03a3dd172e7304b44eceee6322575f7493d551fba72652b2d98b3385761c11bcfdbee001d3a325014d80ed9637ac32966d5c33a42516555300cdc3019226a5a642cd1d80c060b11f5d63ae78049e2275d205623a0ec709d171585e7db2198492633cea364d222538dec5a59b11b3ab9d526f721fdcbefcc8abc96a6c6e7b4b1befacea75027e1e184255777207733a976f08f7e817748aa3008f8b502fb245ad389b72ef68caf8283861789f2e535bee98504805377e5ffb201915cb6e5520c0ee6737e7e89f4fd321983d752eda8bfd6ee40709c532c93b7af4ae30b2ea48f171be8df11a6191b38e583a96618f475e43129968394872ee81b0c91285d84aa9530009bd76c84a43ef2004656ed81a8bc58a93931c15d97ed4cbdb035fa5927302ba1f9f7629e60eb49e0f74bf5b81f066aa7a2cd6215976d4a46865c8e8bcc9116b5409911cf16e8f10d046db6ffa469700a1a80ff19f6111e905cc3a0826260f823b9e7ff8090dcf26db5e3babffd8d71bce77221d07c80cf827992b8a5b044dad3ac06b617947055ea51d68961f31b75a451ca4fa2f062650327f25e5e80e6c3ad6021befeeb4c216b226da94b4ebb85aaa2b112f71c61e9fdac0b1b1598eebb991f5e9d9b5d175ed76ed1a4e7d614a7b6204ef137c623625751047630c103cb7f2fe5dd58b17914187e29029c53cfe5b015ca74cab750d8f95e05f818c3cdf947d9df059cb11c4c159a9e49d18c934780c74c2319b79153cb1b38273566f64fd965749ece23a50eb60a5803f04a09d40f7ffd878a8e8edcb4cfc38eef7223d51d1bcb2f58d0bf60e3157eb76055d994438404278603ee7a9fc4ceb2afaefe92fc430d40a180104c840438ee8975aa8f05208a8b76df59367140821ddbe32f8e5c24615a11fa40d9811fb02fd37224ce3e99b73cc0ea7917138c0656ddd95ed12707f0041008f80fc2ae0b02a613f058d438b2c1ceecf3256df083e51b5832644334e2c60670e0f730f974ef6a21b635b145a4a206ad726867b32153ff28534e9af35e285bfb9f98b148117f87651d6ebb08b468d2f49ce9ea1f0726ef106a97128c8cb37771defb2ee20a3965a4ce0adcc80b9a998b19afdc7a5ee955da1f48954695eec39a4426901088a66ca97111fbcfd0c0c23892c2270d4d21984c19670a6ba161a53e7a23bd1ab34c053bad8cff632c63b7c4af2bb120fd58202f01ff5841d795862427fa9f48b2b596212a82d2cd470adff717f164fb9615554a7e1569116011cf15f4b11de1ae69892491fb5b55483da298731c26e53fe19f6739b32422645de6d988521e2fceee440c8aff8242588468716ab5e1282043664cd9e0 -MD = 099332a09450c58f4e5a2d172c00cbc490997954f6d74c7a6f50462e58eda142 - -Len = 49616 -Msg = f35acbf8a106e87dc1dc058ba92b4686c20974e2393c4f2ef75b2652d430a6150761f0e2e14feecbbc3fe6ce2eb84f57822be40768daf8b4ebf209b1a4fa974f2d7136a3d9b3e38aa21d94eb6371133c487c0b4882f6632f3fa9ccaed9d696a04dd4c8c5f0fa6fc35dbf366ab220373cfc42112def593ba7dbc898d1db8a4b1150d0ccd08deb3b7dd46df5d4828b666086c61e3e17cb2625a79794a312de5da91cae6b4a1a50efc0ef6ff9b03a7b46afce5058046313ccaf8b5de9abe79c75719ab6ccbdfeef3394960c698644b87f31bc28ea0639fbd7506f64be71c08a3a6fb22f18b0a190ad02b18d6ddf070abaee3995facc0249ec0d3bf23c7e067255ad4d6376ac6bfd0811283a2f41eb399fef2be0b1df27c6b5f0d7508a59221a6d3351980f38c4fdeacae35bd437580cd53b7c5236c60e3ada002bc6d28a7a4a2b07a8170adc1457fc33cb388746b64d05da1231b209216d03451f9b399a78cc373338289020c3d4e557c6196ef86dc2d6d5d7c54c31c726d7c89c19e910836738bfeb12c98d393c4d3bbd45b1d4e534f133b1582dc5672ffe9088860a7402e2d6b1a71fdcaade57dee999057962876afdfc8a307c4d6b4e21a5cd2bc34f5f06ba135695f2ff1bec3e6840a1ee2bb92ea338499662523a4ce81051503d28019b8cecdfbd321556c515c09c6137b6e4468bf0d6d2075b3cf0fad8fe3da0875069f3452adfc573f8a80cfa948c7d8b717b5c2c192c92f0d9040005ba3913f4b43798251f43d2a26a5eca1c0f6ce733c695bef2faec2b99794ea1a06f8dbef895ce2394a630822813aff831f7479e354d5c5b4c6159fcdf849886b00482ca1a5bf73b9ba7f0fd8f5a623e3e3366c9196d98d84136bc2a4962a8563d615e5fe36e7888400ac96a5ea941434dab1191688d10e0d9615de0607b46ba506e69a4da3719b48db704f11e6712b06547901ea9178d191dca8444aa383c5aef13edc2871ca4648a96e8bc56fb9e2c8fef2a976472d72b1459797eb1ff51dd253830e17286df423e90bff08ecfad60d28b28242206b6bfc7f783b7fd394cecf7c57b2724de94f6b18bcfb84f4a07f43603d2ef693bf27d3c8aec17144ff62e6fa216bf248a8928eb70623a1fd4738fc33f701dc479520c7dfbfac580a7174c94b749cffaf4877ff528be9e89d5bad982274ad9b8289f159233f6eac9ab77ed6eec5c802f8255a3d69a2b0d12b5a47c7aa4a849cfb0a13f811928ad75c2ddba062a96f94a9ebd3d96adf3af44ddf91db39cd195907920335494d7370e53125a63574163d3af85f53e4b5daba6b3816736f90ee683ebe498138e4caf1cc8df768d5da3e5521d7672d45bb029c0a004ff0aa1a764316fb417c4eed03e25880ab68d2204a8504f585d63c435531b0d4990377ee436216b5a58719ca90cb3fb5bc16a90aed355aff35df070344f3e6019c0c6760c85db499c02217f1f404d899c402c8ee88fe7a40e1b8546f445b1033c37be736978e86f43bddd817c037c9a93dadc03f9049096733e292ebf5efd5c7a9e275c4138cf471733ac89067cc696093881d92a59d7ede86fe510dbc1a9d59b9d0a19ddec1837df09968007d4b6e5c70223f7c3b744123656c0d491983dd466db6e9185bd4ca965eaa34cc532d1ef92dfca450c45606b259ac263290842c3a4015bae81d3f2046f7cdcd689bfa11d35777fab4c2cb2617ce4f3a3eb3b3f091db6d957185592b0c66748069aa2add576734911cd93c35d05db5c7d1f59bc0e99a3f174936bb5153254efc542047d801f7b315fd5a319c5862804d90c89413ae070aaee3a3fe29b7aebdaf9c70d9a87f6363e7dad833e02c872f3a0fbf457f5b9c40dab55f6a1aa68d3108b72e48b50c44d78539d5dba7d936232b834c285a7ee4720942cbb7aaac2b599648bb2d8455067e7caec56139daea0c80bff1a54b845a2ed9107b4f60351387e6a5a9e0acd642d94c8e498d3c9e3d3bd80a4244b90877d7c8b2d099c1ddd05c68726d1a84fc6478636cb4b816bf8a31afe6a0af2977c7fd368e7e3f4602ec379a239733a353f5cc5fdea96a6eab6bae66f9bf1d136eb51fc127d6a87350b1ba0a3d9ab48e697145a0389a2c9aee5bd29ba7d0371d39d9bff6f37c5dc023db542714fa15bca96194c32f097721f4d57ebc7596859d85b04e2695c1d7c308d3867f6e37efa490410a371669c2aa5b52e357e764811abeb34afe73699ed28c04d1719dc6aaecba8a468a734d977a8e7ea0ec71eca22b615d46ed00b62b951a19b5bc2848cfeb84b7ba2bea377e490a9347f8a9716135fa38c250e249f6712f7cb3ad9210d7278b53d599df99ef6c5c4b48faf2a556c105b03de88c97980d58984bd47fc149273ae93952c7e7537af0011461e1fafb63007e2a02642188b01206febf25dcae712fe255f537c252eb624f3acbfbe4b77276dd074d0d6a310fe8433ccc38b57f8bb6c9abefa39d56343fa04ca7a4e523a5c5676606ece4298337d7968a2d0e24dd7c29abb09feae5fbc48e9a73819eb8439897b6fe8721faa0ad3e9c87872936fcfc6cf5d6813d8a98bd74d4bdf653fdf25d089a6260a5fceea4d2af32bba93e50941deac00c07ac9166fd6bf597b76d288f1450f11de2d8c3bb5e5f1a5f00a37effa72b0b74dbd48c7d72c0a8ca3b7e6cbb559b18f36af6d66d1c1cbcc5c20eee8bb31727601c8ad05d9f83462252aa154e46d9489590df8d16a67888a46fb915b4ac3f92626c480373be246c248f88e8c4628c1e89070b6e5477e30c6f5c6a8b270d14dad02d84ac7c6914793554932dba2333f9223002d0a32afcc68b2a7bc54f50377f5dd2d911c42ae3fbf944417aac23516715ae4e7a9f1a26257c5c654a9a1007ee401eae09e77e0372d4d12c45f6cd74f6c7c456c284dfefd7d764cf8193c716a64b538bcb52dd035c5c8dac16469c1f16ad34a42f10e6ca2c10d61300c8dfd445c403fafc92b26446f4cc5971f819a0455a51cf36afc935b0bd12c85ea5d4d13b3eb2640423a89691323fbcdfa7b0b91143be207fdde1c2f430bd67e1b7408df53fe16f88822a1ae9993a3eb5b21bb9e8fddc504117eae27520386a4079ad7b023c1365d03ab171ae9e5e679ac395336aed3ed740da2f2491e01657d1797628f0b7baff91c9c93b5ec61eb00548c7a5e596481de5b138f9f904d9b93b1325083f376a85439bfbc88884edb08bbe2d92078d9a9cb62992e31902e4f6e3f344a95c3f84af4c4da3b9aa6f6dd1749031783f37a8fc28afb770507eeaa942766f7cc634abc6323b6b7f42f9f1ab766b6dd8fb28f584b3b031125dbd3d38fd38d0030bcb42729c01bd99c0992b96f7ac4d34d9d602feedd77a599f626f2e7a9740cc9b47db3cc01d1499c1e17e3c7edf6a0c49d353a34d820da673e2e312213e2c4a034ef87d6509faefc5475c0482712edfd9855a1a495c659999d35b6ca779ecfbc2550cccf144eb1c295f6777991e061fe77098dc77a31ca37fa81a9663f71d7256de9a93db4a6f9f8c8e031e3912aa5d123992623f028d3473c5b337fd22381e4f60247aa9a6f2fa5d57c150c90b6607e834d934260751fd34d0b7c9c987c7700a6e3ce9d2d71fad2a3124c7ef74d3b0b7e6cfdac30de54e214d9ab45f944618167d3659fd57403861ceafdc12cb7de82fe408be7ca2c1b7d790de8035d42e670201c3437fa3ff1c9274b515b99bcf0eaea0f667d94271bab64ee5d5c2c3fafd4b90464ed049b6da3ac7f70d6a4241a4c2922b5f6f896fd74bdc52fdace0364b519d41d495c501f1d94cc81bab7b603afa5c1a1d85c4268e06cda8905ac56ac1b2ad386d46826ae3ec57bac8d393b531b453452ad2af405f85a7591642c002f0fd34bc81591e5c30f28d31bd9927cb499f1c2effcc9727cc36dde6f7fb7c89698fc820a943f540596a51ef325293ecc2f91b4a04ea18474498e5c4cdeb67789bf8dc175dadb3c1ddd25a25ffa684c43e80e528f2a1af49593a639500a8fd5af8b6f50316ecb65b2ec8ea985dfb66dc2c94ee4e1189c8988a89bbba28aacaab104887765d879976dc9ca798d5c7b68f1dc3ab2c1a08f0af591572b6be673be3632c17e3aa14b9af67ebf5aa0f920067728ba04554b5b408354c0d1d2a74ed9e71e03acd750ab35f4135796e63f0b0ffdb5b721c5a068f3dbfbc0f40054a4c26ccf344b646d00320f8e787486b5a54b2a8c17523a281feaa58d3edd1c75dc426c4d3da10b81b257f0f90c3ba8e45681a7b4c4dfdc69e6ef881321d54f92602190a107f7f213296d3f5bfa347652877b1b35a410d2ed26c82c945322c13497277fd2799441abcc3ba3bd2aa715899eff2f18a12c453c483e3a18bb0c99e2e91be1e87ac221d1058bc52684dbb01105d68b64a27d5cdcb2195aa841dd0025bec760ecf4c7ba0e3c234d9ef01a6d7022c8d6218e494057ce21334acddb1d847ef1a2e5ceec33e9d7cce22e56aa74305f9cb8574fd91835031e6e084750198791624fdbf079b4eb3f4e2cdc9ed4eed8231cdb0fcc750dfcb8d7b2ea97821bb660e210d642b6679adc71d5b2b0e003f1d50ee451ed6547365715a8f7a6ba4c9a51398ddfabea728116fd82b87416da02df3b7e239af0ed6a47a0f8375a3fd3bacd2e6dfd165ffd2556b9ddf5d3be9c93a86b4f8fbb5f2721f04049b29c5bd99e3d8a5839685b3110026e8e71b31f702d9865ff9c38fa1fe2babd4371555486cf0715f89a8a2735c984e43d34fe827f5717f33752f909fa350dde8f7b6b7301d49597f228640b32d842e391479a2ff1998ddb9fbae7d4e3a2516cd5d8c80073354dd8f1ebde4e50c6a63332b1716eed7b62e6dedbe8a300b2ee30bc915243037b999f9bece13ab619169bc97a69879b86fedc9dbee5bd79ec4cefedadf383da2de0b6983253158d5cfce5feab6cc12441ca858369c76b77d9d3741034920a1fd389e391c51e28fc14bfd7784a6166b0342ca939e674f522ffec86cc2f161efbf6feef2eae28bb2ccbc73ae0622fbc66e88d0f663dd6a3a1e8fdecc9a56908961da6a216f45b1645087cd5ddf8c00c6fe45680b374d4bc1d1c706fb09e721017d0e9c3f29f9d806e5446721816fb9df3b0edc4c795558abd21abd72922197da7972f1c69b8d843cf368dd738c3c8b919d5bca34ca74353aa8118ecdb3a46996dfbe0732445f3a59136b9cde6080fa609da29e5e7b385600bc41d756fede1aa92836491ca51d6efdcdc321ccaecb8adec479e5142c003f90970243c8c44d2f93db8243e04e16968d7b1608c8b77ac16eaa582b005d6a566cc0f9407db4501ce972086417aff945aab3cace5d2b1d1292a7b3dcad8fd53ee7b28d59f04fa5771c845f364d3b23f0b7f057cee46a3102ed5513767613ef5da3e444fccae6bba29f7afd46db80352c47c9539709054526c12b0d74f4ba073723fea6a55819f133f4ce48f25d0f8b5cdca734c3457cc7d2c0a1e87493c2cb5fea3a28e04279e4bfbf06e8e54c49c506e90271bff44147ab6e425af1fdce9a3c695f5239f457048a50bd537c23bf40beff73a109cff333252c94db597d5df26123b6991ef861ef485c49ff436de0acf97263392d12f318c48e11d027acc162429bd8840bc8fae36e344562c7a55e582b0459a08687c176fdf531dfe8f6c97865444da98ce0b2bf506b3814654478d0e807ef8dc2790ecc56048d511a05a6935dbf8e602eca09a1b3738a9ac8d5c0b5950f7d475d710b87513e7cea473419418060034e4e0f6058fbefb55c5ed3d664d67d8b63b40a7836740598f1dd2c721161c844ca770b67339e3250df93b92a6d10f4a269629fb56832fc5a0e68394171967aeb7b46588ed01eede5ab04102d4cc8e75adee5bb438b128548a654e517e082da4fc7286137acf264dc252c536f6282d80d2ab9f7b32d9722ed404fda65ecab78ea3489d00228bd49bcf4790d617cc34931e35bbf84be3567a062a563ac0494d9534a070f6ed1d40ef09f86a893ca0ebd818f577d28bb71c61a93e23b6ab6c37e138e1c99ee46db272f7cb1af76f8c997448519db1fa3d0c0a44aa2ac1281bbc9937726ea00e64724c21296ac9b778889236b2f33fa15e6d9d5fd534043e3e25e5b7bd27a374e8c7a40f7b20a71d4cfe586b8143218700894482270827f5bebaee4229be4f1ce2fba24a270538a7f044ee6e245302b40ca625360870d15581c3dc5f1ef94e103b54705997e1255f4ca27dc705eb88316b0d6802e032aa677088d79704a24558d91b33c4317c154d495f2dff8ad55b050306366f17175b3273510670447fdffaa69716145f9db178cdc5259d1dd82438bed8b70415e78cbe736591744459c20089123ed0880ea1e8c11a8e2925bb8bd383cd1249436ae414560da12b6df7967169d2d68013958ca50ea78f2b0a4737dd392b70c607670c3b06915e1c27230456302004ac6afb1bb89ab4512c3344d15eca3bf804caa8ac3b6939efcfdba3b3b6c544f0ddf407f5284f89fcb40a7a005f1d45d38af5f36b1d694c7cccef404d991086c49a1983c2fd146db749f6b06de61a9128e0ee11f1e8ed142f9ccdc27708f92ea56c41352c3fd0aaaa755fb0c0fea966208f1fcae7a4dcd72ec6dbf1db096883bddad4e7d9f76d86febfad40a0acb20ee31eeee5f55a20dea1d2839521a745ce346c3a5f712dd24adbaf4929b5fa1dcf9815c52cc211a071b1482c75f1e7785732aadc669de7e73d68ce9932a8efd2f267fd0b65f7d144d885b13d5af1d3e966de1d20c3052f94a9cea306252193babe795c28593ba2f45a4795200ccc728143604c6f40500cc1d434b7f9c9c7efbb7df6bd84d0378d98401c7a3c5328cc2636e1bf32a326875607c390d8e5430abe7506a58792939918d32eeaf9f7aeeac18689ffcfb531a63b8aa3b80c423cedacf0cf9e9966f6cf5c58a56cbfbf05d33b7c7f93b03e167359a5fbb7fea85b9e6b347c2f221508354d1aa989f674d58f7a60ec033b0680f696a0f31315de4827e58933e18a6872d6d16060c706dec827687af7d8dad41536dbc2b556b8aeaa8f00391c3a3924dcb7d171f5b158c584a2ec11c999f4717d3b1155660751de2adfa68b61c49714ede236968ecc52f1b108ed6e89cef0a6610d1e9f31af47376f1ebec627070dff4e5ee61754a25d2af86255da6000383969b5ece93cd5028122543033998a01aca733cb3c6ebae23701b70b9b76b633f23c3a617aaf01ea84ea8ae41adcd5dce49f6acc4d049c47e1730ff7f9f278499b83a4679cb3bc670770c7c1c31b70076fde09d09140d1f6f0f672013efccee2fae5fbe595708ce1d45b13b1757ce4e8150d1bc15148e0552c34e911b0be4166d90b48c2ae0dfcc0b154769c7927b7e99ed4a586d54451ce5cd27b0f995d583dfe9c93e82fb2916c6703f96818457471d1dab107655dadc74a7b31e33f049cd03141e23e6089d54dbe0fa3fe97fea0e777c8462c49ba7aaabcd51175ebd993853ca23fac88b74fcb7d217d464179c5b558456dddc88543de7b8826ade404c7c5e666b11af167874f6ee08d285ddf6a423cfa2d022be38dcb4f3d757474aec0f9f6364170e1bf063f57f5dd8d325718f6eb8e8e83bbfee2d9ff9c08b0e1ff048735b9f596a1e753050107755b090a56392caa9848bdfec970554ce64b741e1dd96b98d7757908f60734bf5b7c2a20ac73c9f654397c0bcbf817f6172b753493555f7aeff3b04a78afb7c599d6ddc0a20c8819c93f3f4b6fd90e41a43a2c68ec65db0843f990d4606454c037536a12c16c32bcff404de93d7b02d6945ee0e3b270a5eade705fcf368dd1583bda183f90fc8f86ff25ef0bbd47bb5cef81dbcc6cde86c7c53e66628394f736af52316f98226620d0d76dda78a3007cbd8a634ca3164647024dedb6cde08e029aa5fbc95f4780317a3d0f7df5f89ade0761c18bde82ad139b833cf29fd95e6305babf766fd4a662063e1d1cbcaf5229d5ee3db0a58983d39bca9a3f7ee72e02f779c49e502f9e5b7bc4dee1562eee052d191ee480938f2e070951c5f472c88778ca546788c230c3e1b69bf24adf361c19caae4ef8089acde928a7ab88e2f2999095b5fca1f4264341fb9c772029f413a0e9331794516c58480ee51ac39f75e048c23083232c4782a27d29996173ee95ca5ef666ddd4cd762da552392b111906a7390d2594d45a290c238a7f9427ed48a0113f645afa85cf9fd438314aa1a5b0b6e394097e5328df87d5065341acb9d429ea5638932b5b0ca683dd29a8b5e3887ca60d586811794d1c7be63af06a1ae26ed2820c10d019d54a9a8a4acbb79936016bbf39db76141ad2fe735e2ac9d81a75af0c055a4f85d1940287bc3d0d90624d1bf3d55eeac3efb244f2e77631ba23486b3c4df81268a98ba11ca6862190b3699cf15379d54c74c236aefd5d0a8aa6efec5a0c727f8905386091302c5961d15cd801dcb49f78500cbceec666bc0e4a701cae695100b28ba1272d84b91fca652eb56b9898b00f2c98bff96d19af0fb8d5e1808d1bfca9e6d0df3ac7b5da9417e71d76aeac70d9af6c251818fe4b5497262517a05bdb37bccd6efe24a6f1878e90f76b4778489e8292d893f09ef9a79069cfbcc9960424b69ebec2c116ce6b73312b928a859e254c12beb21c801fce4ba8c7b73056e1387b4db6cdc68cd8086dd0a033a05adb37b6f2c1bdc42c27926feaf550fe22d93bb4e23d695c91772625774096b080689c683cc8fb122b77bba43841cf5b8354f408633ddc -MD = 892c9210b31ed9b387c75d41922378235fe9681e48a8367428cf77d09636bfe4 - -Len = 50408 -Msg = 4edfa1e99865265892e2a91e9324540e362ab7c5ad2bbdd558dbde2396e9978ddccc17d004bf3ca9e70abd3b2d84a9b1645610245001ffbf82a3b2212c76060234992d1a8713a53eb0156bcda97f6c4af1a63c4ade540a913511d478f8a1d7927fce4a8eca684b5f16891a9bae1d852104a2a3ff002dc59398aeaaf0a174f282e5f4d5f675c6155441f0316ee567dc7ec6d3ad0b5e93180cd4019d50d0f73f1d8d9238183035eb6458d11a0ef66459a95fc0c3359f8eeb46109216622c31a7aaa030dabca1beb5d983b53c43881de5e9f6f24b466c26268775ea7bec5e2a1070455623ac73685bf9ec23ffd543986688b3efaf076c64b2182b9035b70dea64b8a58d7baf4c3cc60db8a3cb8bd1dfc6ccbf41553d484f7541590cad8be27a89cae75c4a8cd540dc5c12bd082ed7faebfe426fa7b3a7f0584928e74a2f85e169ee354cf80cb57e863020fa1e8600efbf6563020b30324d437abfa8736d9d27ea6cb4e4edf794feadcf0ae1765bf1c8284b4b81eb7b91701f1a47d7920bd255f68b8eac92151cc73782f9fb7675558d10f62274ae5d6b61d272e7fd0ed2ce717495eb2c4d2df3e00e9115ce879cd2445eaf0f64bc9e682646cac8a14f8a36864bd0f2ed8709c154184485e4129710f7fabe3ad87d0631c9616a114bbdfbb5996585cc76a96f2f283fe372c57d2fb8adcb6bcc58595c6e520d99eb83c0ecf1b4a9fba04f1928e46669b503f7312c726fbbfeed6cb86ac6c731a07ed2c02792deff7c970141fc8916800361049756e544b1bec49d02f6e232b5c7f1bf257241204f4ed91388b2c63e6b15b3741674ba3496f57a729fc96a9a80566cd35796a68181ba8d0d551442e8123322cd1550994750e93674f7ab05087c951994be5b68097e08dc7812e8a61b5da5d699feb02886c8e2212972645b8390cc1e8cc2882fc02c80edda26f799e034b2f65f385d12f8e62a631b79bb1513a442a343cce7a5af746ae9bef909c43e7fa4aaa82b1ffda5930823d27279dbc0a140d140423e70dd3e0df7a9f3e6cf3d26c11cfb3fbd9296b5c389d5c76654936d0ecf0b8e56385273b240257c5561e5115271e0dc0178d235a4bfacde4a2993f1f4c62c16f7a617f9a1ebb9fc1f223f299ed4df6ab15761fcf3eadf21ed02c9153ade2b44e86133ba2221eedb0cbc5254ef6b815196d94cf1f835f6f617853bc2273e917ff312ae9d7d0a4a81e4d4267b8b5e4df978a49afbfac67ac78f5df3de040fe62ede619189f9cd57566f15c487bbd6cccb1f60530443c5f3fb1e30f9521978b0bb72f5e368df939dc37524335ec7fb842d52b680f3195be7fa8ca75307aea2798d7777ac217783a32ebdac7beaf7f4ff88db4d28b0c5b0e02ca1690be40bb5c80cb58ef49c09c6f1001053a51193eac54580cf53228eeb65f9241f29d078d826a0f4e3c4c1dd830fa236c1b8bde2045cca0ae10933be34ffc9df70b3b53c331ab1fb1e23783be3867af79fbcd52d6b4e81402d53ca9cb534049805b37aa0ef2ca793e61aa96a0edcf21b95ba41bc4623d0ec5b38cf6f938f1218853007ec34e4ea84e3b03cb32b9c71694ab8e9d7be6121d413c12b80f9955b279933446829cbe296beed195e624b5eaa67c1b5c6fb92dbc1fcf5c4170dd0488ce9c3195bf768f8901fd928b3dd7323a693da8dd0243d667cbedc837bf7c73f111ce86e0fc543923cad7d52f9c19b2725770d593f61eb2aca027e50f6e002a97cdaaa2bcabce51a6011e07d7a394cd2efbb610159dc238f7670e414cef00aef96cd1238d504d5f6c5f30a927c6a0d8ccb06df6d67ba6dfd46af15b54c4e6677279b277d78c49b9033f9047a487f66bd83008d85b02651dc0468191db8239eabf7ecf2e2fa25c04e72ced51b269edfcddd5275327e4658947642f9325a963bf2cd697950a54ecb9a4918855f5df00125a2a49f5a1742098d65e6bcde79d0c4b373b9c6adbf6744db81801d2d379c532b9a9d11e6c443ed2f98fb6a085ff8c158af85e1e3919ab478e2ada46cfaca5e488ce6d5bfcd718ae3d92a0c985237ba484a75d0d8630da2db34482206efa4a8e44127f3cb7af36b0fee1ba8759bb538eb0c309d767de8966b3ff8a0e25e4fbb68820771f413f2151da07549898299c2a9bc5f50a326541890cb6624e88ff61f3a152e5921df951273b7e0f4bb4e0ce1ea24a9ef49a779b1b29f39b900c9bf5ac4c245b33a2705e87bfb06b3f349351c160ab7844f487ee839841a641256d2f66d53f485263369229b348c8d19b93dfb953730169d518b468e42b12f067c587b9c8ee2d9cf4bea453d291d8b16e74b06cf73bdae1b0aca5217a1a521c484796fbb3db8b61cb7b0dbc8a35fb3d01b88c62d850653b1bb61943d699f4235b65c5c31261d25f5bee26ca46afa0f309d1bc21537b20d47ab78946861469b3f592ac96612ba2c42aaa87e384697a71eb42d82f04f6ae4c52338db01524333cbb70a3fc2c837d6ebc12b9beeffde8183a9e68f2796d5e1136bc8f06e043d13c2162545ad123b28d94c934a2d5c76a745c46d7020d49c0b19cb515b193fdd410abfa3638fb66e2cf29208145e2608214e4debad45d1666bc08bfba568cbcbc78dfaab21d07d79e91fddb17fe7253bf5848c87cffd54dc07eef2ed55c56faead310e6508d82f04674973b6153121b82dd1c96a5daf27a6e98c4950f397f42ef9e045fa9f0f94b6af569d405ea4e226d11c4bbbdfc5106b1983d84b074623f4b581e5926ede7338c830a377e1a82f2ee74d5ba3dea6d8d39db9e7071a3ac2a8e8fc3754feab9631babdcd8226a6d278794b414ae1ba47887f18beacb3da99f29b398369d6dfc34a8ee76389b50491ab8e0045d77069242fc787a5615b907278d51f11f97fe3c32b4b94acb6172c356f2f53af73131b39737bede34e99c413e59e98282b7f1e5e7bf9aef12fd384866e632cc64553384cf9a534c19cf5dc45dffe8c112760f75be3a11c7a1c71764b4d3273d376b728266c4c438773f741d00efee11516a9d8840a49c68fa679694eb7a4101e2dc8538f7279027dfa285b7c1ca5807a20e3289f99fc9478f574c55552c2ecef930c224eb33359ea5a0f9211aefc51886c954e7537bf6e7c30eaf129c693ed8ed00dfb2dd9823018ba354f566f093c892347b4ce8d9c3ce57f615792bc1ffc420b5347f2896e6f4d4320f81404d62ac36c82c172429ae6f90b635e57dc6f02556c646f666d00fed21d5af713186b017f70ccdd28ffc15401fc776e42cd8ae50d1ccad9512d3fc5ef6f6bb21b51ceab0556b070b96c1a6f447a26ef1938788fb3430def7b7134adeb61d993f457090e9d47b3e2ee30ac1d0cacf649a5c442e68e08b318abe0e59c101d2e0065d324148f6b5f9c8df480479fba71e5ae1aefd4e89446bbab225c7ba4c8f163386d25a422e93b045e5f9cd646cd1f29fce18740070f4e4241e0a133f08dab2333cc16a5a0eacf832b1a0ab0490d877e56c2131134a0511436c2baaa3c92e3a81f99fe014f95a482baccd2bff0a1314d85659a31b76fd999516fb1cad0ff215ac37be69f78134167d41efae983b1a5fc52712487d8a56d395c908e7af3fdeea1e91bd567628b2e9b41b88c1849676cf5828fbafbdf6a965c1dcc57a1eeb4d0e55720d3415726f487c9418f338be90d9ee066627513e5da6a5ecc1629094b518ed633e9159d0c1a9234620c22915f1061339f26ddbe3fc4cbe537d2f98ceaf9042efc1dcb7d64282349c20acda3f2fea542e10e1b269fd9e77ab694f9bfbb4faf2722794b3f56a7a4d10a911c09c95dd1d6d52118932ea327e7f16311eae3dbf8894e057d2b0c1e7c95e1aaf70a0eb84fb72267ba4f14a9f1f38f4729548d25451b27c84a89ab15135af05b46f0e69486ad71e8eaa17873ae6539482946dfb6ffa656ca98a05e14d1ebdeaef1017b7bde806aad91d0828ac706966ff90801158ff2821351b94ba41e0f54abe086f5f4bff7b4bd95255c75a29e4fc382e21cca5bc754ac5b1c9a4c628dfa59fbc67c8891dcf820e0e82bbca9f50b4caa1c585ecded749ca0117495052e77c02b0b36bdbcf5dddf58611ae843d273135afddc584c2b89eb06e001066fba74e8569b4e1ea80b0c01e7d74e80d7fe2e1f7bced1403f4b3ba177d0682708f998da65bfea30bee52c8e7494f20ccf42e579f3d85e9f101334c7da2ad28039b28c9d41bf337d644de68fe6de2c1492644027ac60acfb264c19651637669a68aff739d0e3508c0309e20b27fe2421882ce6338cb1e3dfe9be9581153c4dfcffb682b7fc7369e504e2c70a1e3c04ba196480a47d122ad0c1304e25be84ae2e6490d51eacb6a811cda03e94b3dff168add2b58366caa958166bec58f956b2b901059776c8f53397c80beeb2ce3115b2ac402ed72e2289fe50381823aef980243cdc70c7377832ff5cea806b577898207e7493a8bf62f24ad75d7a8cc5b642f77fdf0a1ae387ced2f0079bc836fda23a8b368bff00d20bc514a2b99e27d51dbb31d40a76b36a2e96ee28e8cf540859893c50bee3d9b9fdf66dd17d5eba9e3bf7b9841be48f687cd6bd160e8a97e0e894f788d55c3261ef664bb070d66758c43381b7e36b5fcbdd17c599b601e8cf75e325a87872f3100a9b1709380d174de0f7f0340a130bd97be36e78883b301b29ff2f764e2e050f761f37a27d0bb0c3b5cc6ec539e47cdb7ec1207d2b40550d2b6f7bbb00974ea65a7a1543e8d91b036e39633018e798180e3a436e481841eda4bb733e35b5b71cde3217b6207e415531c7373e4e2348da51d53f1486ccda03bb6c7ec9969128bb2cd1a7c2ce02090026fc53b784a07567721a7c378e620a9699090322cb328ac969df2c2e9a6e5a4e77631d63616705099791639f07e5b7f0651a6c127ba1c38fc0e20ec32bc91e854981fe0a8e7fe205e9c35a139a5acb57482820614ee4bd555764b4492a1b3ceec7e05f73b2f0f2a68f37ca5defcb2d146aba87d7ee055e6356ec88883e6c9cd11607a66776c31f33b1751c43ad3fc56ff258093c000b9000e603f14710c52676617e3dae82ff4ff37906b68e7dbf7baf088a0e572fff3a752f2f5750482dc224cece8a107dac6c2f0d7102060652371ed6d9fef120e8440b58fb22698dad5825857ef7550fd35d30953e6672f100e10281cc41d27ece950789ecbb5b874cd0bfaf16ea44e17b0a3b3af64c9be5d161a434ec3fc2efba17b4ec8c88eddf12123b741ecda69bac5b9b23201b4a8bce9f4c15bf61891bb2b159a662f2e93d0706e1fb1f0743e56e38967a443b458bfe84424ccf0deeacc14b3de2f66215483495f86da100e365ca897664ea14548c6af6cd02a4acbb47eccea9c6d13e3ba9a0a5caf12a204ec6c736810b9b0e413618de365fc4a7b6963d20e57a7aef2108531f9db044cf4bae6e270097de91d3321225c68ab964a841bb2a392779de900b56ecbad27675a4c6c6453a303c05d12860b1c2ac0b4d58f06ed4edf557724f5db0f2697e487a1fb5d77679fc3cd204bf086c75ec40c9904a5f07480b9b1228a4691bf1dc43468523a9a30326666034a0143d2673e23f16f795a99392cd28e1898a4e9c15ee419dba45b522d4421728738b0b1c687919b3a018a317b1761b43b31a73b051d2d4311fb2921b2f5960aadf76c0a0f48bbe2fedf1de19911d5316cb217176b7756507fdf824395e32a1808cdc43fa3fa29652852741e4594a382278a8323670615ee9fa2051c38955437323c57c72704509e411c2b3bf3285322e63b59d38a31e259dbe300300da4baf4b4c3a5350b0fd7fac38cb1ef14457a90433539ac3793224ebf2332139779b4cd0ae41b0db26506073a34969c3b647056a918711201a27c19d3e2e93b788cd81caf2e57b5cfbc81401f9447c7db1deae29255bea98ad856679492b41bf366ab800bf2b9c1b56ed031ee3c53f675ca20c0996d60d715bd27a49bc31139ca8f9583bbe1dfb606046969209d29ac8e01d87d18d0063f34b9865d33e49f1940802c94397c28173405b3324127675ea64d7884bb1e2d268a65e8ee0787ac3f17b0d72e0f122149b1fb4449ea7b6b8131157753dab83431693ad5f3712cc71f92ba3bdda74469d2225da2fc66f9c4b8c0f25b87022ec9f463b0c3fa2b347e3f5404b11f8c935054e79545e65132f169d85c9b7acbf23cc41c50396e703f4012ce28ed60398f7326844aa37423a77018d9bcbdcb82a32b44c5a1acdcfacdab4e837f375c488950eb7ad6524278d7df5a67bb48e5e0a203db222da4a225301e26f6a02540042168085dd0c8bdab348d82e4a0c346407f651b944ca76a8a372740ba143dc826e826f18fc27d62455e0946e33593893cabbd7abe973b92841345301043f7511b3e2c5ba313e6ccd1b4e0fae5c2501b3fb77b7ce385b7c6cd84f659cbd7d8874b93d69b0a4dab59dac993336edf7f78c4233d96b5a0c253a0ecc9423f1857b74299b43457e82195cb1c9e64d0f5882e545f625c9760e1e5b8bb2c7ddcbe0b8d9ab043bc0e7bf00d1d1e7123ce9cf0a88afc88332b5e7cd97f809e6137015a56be68139680618d2c5b5fa9e4ca5e4f73b26b1dbec3f219cb5fddad80e0bacacf1831925870415f700050a72c2681fb1c752ba15403b43f27f412c8713c22e343529d5e763083ed84a682076e95d09a0f4ddea1976d1d636bb6d07da6dbd22a4fd81bb67443b1cdb6b86429208a9292d896c4acfd62b61d2322873b9622510661233d68e74c536692a087bae667707be50aae01fa86e6c2dac1b790c3c2280e13ce62b423acd14eb5096d0b24ced2cbd0f3cb6f233c580aff1ee20bb41dbfb7d4242c46cdd7b3fc7a5d74b8602331f908fcdd42ec05624c0c84871afba7908a2eef1a8f5a6f83e67f174f312d07268a1980340bd9749e0c8fad172ceee2330b80698dfc3dd6c9931fc14d03ffed29056f286048500c73c2f50322d012702fa2753e272c0caffd98f8e60ebf3d37a1e1964ff287043f8c15d8f13aa31ab3eee589d7468d2b4d785e86e004b1798939a51b716b265a703f6bb821bf044c4fe94b1acf9c9e3e51f25a3659bf89496448d65b372ac4b751063aff0f30724b76a759b47179ddaa3fd422a3bd9fb5012b67ebf20bc1d0cf64991a2a043f7b7cfac187f3876ed9f379963e4b8645b355710f5c6c69b0e8f6fd407fd5bb2c8e753e905c345bfc01ae91c1039a3e1202aac7b7ae26db886bc2bd94d26e9e8839a8a4cc5d1379a1f3300aed191c6fb5316581f967bdcba8d7b7181ec87128e30babdfadf0fd5ae11d2c6762f54e758fbe3a423d0f9dc4a2bb488f36b869e4cd52e351edbe7e9a49edf819db1eacfa02078d8b0b1c53510694fb958528d54c97cde37de42c03923ce427a4ae0bc467ccabd3cedc045afb34e344cd82a03fdae2cb20e629b018fd4aae3f9a642301494029a170385e211dce34c899a7a5061a2ee9201d36e14b15f39aa45d961af008fcff7b319880425322f7db7c7cadb484ec96657594460676b8480a80ac5a2d3153abc56585214b15e3ab02086a30e7a59c516591ba34d7ba0914b6862f46f55d04ad149e86a787e070cce0a008b50be6cea8a4f421643b3a86af5ce0878804e65071ed4f0589a54d6aebdbe5d0c0ade2f41ab81f522aad92817642224d93b867f798c3e98a5e1fb73276784c4aea2a049d15f365d51eab3cb9e82ace09d0ac5c4a901d10ad8b43a857fb2a35df881cd63a28fb7a22a6b0a360935b3624e54d2dc9e66d36b797ddab4be886551720f2d24bd244deb3596a514606781d27380767060a48de610a3a4aaedd010c8a4b4873529043e60fbd14e0ba9ff5c5995f87928f8a147a0268e5d0c1472ede917d9a43dee19d22b0385cbc3eee58d1f3b23a3ab6d4749c442a5d085395544dd52e44de515495371d51be5e636015c4bed69bba2c77dda78ed52c4bb66635dccdd3f48d5a57e075dfaf964198a3b100534328bb40f2a43e4aefd0056a2837fdd41505db4a69f3814f9891006f17bf37796e6d98a4c38cd320d0c4dfff69df4380581562b21942cc15a32b15573a94bc69ded6ecb868ebd8792e8735e689a0206b139fae11c452b8aa65b0eae18ad611dd1b01220c5145e0ec6f93a1a0360f26fcedf107fa29a7f97646ef0b7e96f7da2b9958c3112b2f7ec30a76adbccd80c9ae3dd61acb87b6f111cd21f1bedd7e77ddd05a6a57450cf4c595bca4bcdea97b0789ab51168d0422057ef63802ccee6d7c5692625f4d62f54c77b23100d7fddd8157ed355b98141eb9b2d848faf3ac3d8fa27d558992c5f2c04713dd2947d243b43f18521b476b49b73f449ef7d05c7a703a97be76b3ba7fd98a3e03a6bceb500895b911d5f97e35764ac7b489e15376d6855e07972e94fef097bd4ef9958d8507024c0f0c4cd1548f8bde2441b545e51b295cbb7b71f9e29e15fe09a2605d4537fb4da43ebfe9396b68f4689fba8837c68d0064841c6ddd4a7b9cee31bbbf3303e74a7bdda13a668268a6fbf46fbed15126d57d618c45517e4f064717f647b1035caef079bf594e6d117258f0534e54538d6870645034b1b1f6c6bed5ae7b51aed1f79c8368aa53a3e9c2fa13f3bb33463725e82cf690a07e095aafeb42ce977eddc0ea9b1bc2389f583569cfcf89f091aa9a3f2bee0d904b0d3eb4d961b5f4ebd677652167254fe7f3262284453f1ede6e320fd1b4fff3a158ef482079c5ec8e62a796a6d9482be63131bee2034f0074e889b4ced9dc5d0992e8e4410972f0def8bde9abc09f3f4298c48969783e580da00dd873cb473efc41b813bb8f41b4460f46f890dbbefc65a07b3c8b228187f12b4ae55107b51be1dbd9510079b6896c2ccf2df6791c05c7deb222b780bd12d7f0ad55e72daa6662c7d926b -MD = 569cde2d4311abaa60118ddb5e5d4768a986394817626e9f24d79c3446123bbf - -Len = 51200 -Msg = f60b4d76d90c920f1b5c966147b24875d4f9f43299f55d2387280b7a96f7e65500090441aef0c0fcef0b0c8070aa083c6974d3a51406a0ed63dd0d12f276b11b3bb3f49f098124862fb8c51379432823e3803faf09e9af98dff527a4a239f0c30ed3c698d208e734412c69254ac2d0afaae5e05960e7b0ac613700378e88ccd6e32f2234f1cd308f8e2fa1bbcb722a6a266b5faa0146ccaf536c41d39eab6ddb2191ae7c4e18281e7e8915dfe49a5bdbbfd964abd44e2a2b1c5c9180bae9fa5a2fbf1577d131f6697a016c987d818e8adef99662c249f3a724cf9947ca8b9cdc7781fd2d635fc4f8e8604eef7e70e900e9919ed9b17d4eacd38d012fb6d97ae860a10fa7eaecb754316e65eacfaf94c44a6a23188a3364c1915d7041661bbd0652e5f2ec4f1ef904bef356945886b85e674cce2536b35c6ec6098e84c2998cbeb5174e047b3eb290f6b7ccf2023d7d57aaff470a9c455f3bda570400b39b1099f2fdcdf85593098140816d0eb31b0a367a4a35cfa33195b135107abd1f68701e6f6015cfc467275d061be1ef546988833ef6417a35be25573ffc97c4f049d5d69507ce91b20034afaf4bd19dce701ec760cb1215393638b561e2041c0c866747ccbca14706a757fca3dae5210775f588479151a796dff554018b69cd5d674dfb7d4535f8a8a4b8ce4990c482e9c334515b10a539360285bb89c06ce0c933b07a0e6b34ac7f3f80ac0b3417c85ba104a70410b7d200e60f725f47b85c3a34b74ae9f6436b75c0d71f509085fb44568d14aa582e7adcd5bc02ede8f34997b08bf574ae0c3e716ee4ae816ab7248e2bf61fb5b1b339b215b4f2996dc6afc8f05303195b372c5c93d0e1048b544b206868518de3ee186aef1ecacd9cd897b43c38fa3fc46c3e1c75c24042bb0576e2550a309ab6861eedab2213f03fd20845dc62644db2527b9a5ce354a3c172afbc39054645f224542191ea546a1c5b0b6217f8c8aded91ebbe925ba4906742fd965e801bf45e6fc0efe99b15a2fc1ca7f33623afc63dd296715e51b86f731e69580aa43510c3106c3ffa60df02a6bce4e1810aa0006abd859907ed19a9aeadf9ea86991e02e9ae60fa0d5f38f1e4e4ca1240d623c33bf9bf1fd6594ea7e098b7341a865e3198f2a3066ac0abd77c3c626fbbaec077792f4cec13badfd0d186ab1f0d937b0498833c4d59acbd1d376bb3e03abb0084ec0635e7063b558b4820dc91a9eaffe5b00b36b6224bf829dd1ac54e04246a535c2781f7f60137420f0e527334b0723baa2f96280cc4e36436f0a19f6212874a913938062d370d5cecf715aef7105a6d4c99668d6040063609964ebd9cadddd252e563fbf1036041a8832e283a3041e55ff1aecc67e6ea0820b3d48efa1cf65469d308bd8b8db6580b5ba4cb4538ae0aaade74cd66df164041f03cfcc3885a369caa323643fe9a0bdc277f7e5f512a44f709c278a852124835f58dee41188fe2b412e64d607e91c1e58ec728d1a33cfb0c1a9fb574686786c469cf4bbaf51fbe79b52eea2c3425e3ec3985b3e4556c97b2b8146c11489c64b5f50bfd77469234b23811f5ed49ddd7bad0c106dd8f4280b18b2785c81c3948d24048ebc0346eaa29469857ece5410617fa8109077b471fd13ce2e8e109c79ce1f38efddde73d8aa485c9f6712edad8ca5fcfa4a93e02dada734d7da439cdc7abb5e51b1586863bec9daebbc34f2fb69da8b2bf0a03fb1a93d76f2d58d4d331f82f562db13ad225c9374f8e2c6ec906567d334273f0bb48c51150de470161429008e81bf92aa8b002fbb258f2b42e31be8558152c2dc9ca38c9f879b7e900623ae9a4cd357f90446190e1ff5e48e8a09d692b217de3ad0ab4a670e7f1b437f9c07a902cad601249ac9fe46db8527fbabbd1b44cae3af06e0150bf0e3d898f6fe862b71ea9f6b727accfc18848fc79e6df63fa7f06591960e670edd8e2908f2c7b4a1e8c7068064629c9823a556c608ed3ca05a3ce69b0472dae032c2af3bf9840d9cf5f4bdf880feb342f6a29cabb195dacdd9e4f913e8b9cb108f15bd7a71c01b8d17d8283c3e8b9b9ce000a3f13ef46b28b5acefa4a93fc220411be66d01e848e2cd05d7b413a5c0069e341f3ef78558316bd96cb5cc914a8ff739bc8c1089204e83f23f08a6e9db007fd160dd71b54c886b1ee2dfc94aeec02ff3a250240f3c20eb11e0924ea4271b135d0b553430928e31d1d48b35c9095149de2a41c306f6fa61094ef991813ed6e73b915ec553e4c36e86c43088a834c3e35dd6d963eceb3b643cec9715fdac9469f175229bab9db87fc234784844fb987af71a9f8d4d738483214c032265db041a2339793da437edc408a7badb3bc83f7f3e780cb5953a363c5aefc66d765486862550ab01da3dd3f9ce8080e7f925396ea871995350b9f10e4e3a494d9ba39c2c8c5d30beca39fb7f887152c5198d06d7a989de1cfc4d25677fce14594242c57bcca1b29ad096c4c3cadcb918f97a3838c6433349149e43d6641da00706bc93027ad0a94ca9eee0751a352c4a35873e009310418e2617ecd99fab84dd556b754efb7c7d3a92acaef1db1d14df3a0e98dd74838142ad3480ff86fa2b42baf9fcbfe2d7b6eb475ab0d891e70b5e93aad91e0f1f6b1d268e90a6ce8c1beda3c289e3a5a4ded514637677d345982ebed66f40a73667540e80ac6dbac3cf24ac6fbd48d8566d9ea661608e239b13f6380bcbf3f18b1eadd1b524c2f043cd9e314bf75def5edbae69ef1f59e76a371b8bc59f96626ff9811c86aa34e38e9f90ef01d8a14f30b16adb470379b3354a25269e2aa67e6770645b9f9d322906add3120bd1a19c7e877a7703ad7bfb8ef59994f02da2aa042bcdfb4a8e59153e80ab66d462dd4b9ab643c9cf8ddf44c9a1ff5355f92969c874249821fe085cb8a0a039f61cb2d117d66d4fe514f21387d7bcee4a1d995216f21e9eb05cce53e7963827eb5fd0c168504d760ee372ec5c2f58c2571b80f7822e029b602b299f5dca099d1ebca5911ecc6ad88769c02388e1597be7736eaeac70770adc0998838dc46b262aa3bfc4ad934be3e928787dc0c6457775a5b0fbd871e2596e4899c4fa1df34f79b57de0975d7724ceaffa4f86169351ac22f663989aeb23a198abc8152f387596526e596e7363279250c41d3b8ac976d59bbd7a8f63e7e6105a5d01718081350b1b0fa3858d9648cecb647b637b6e63ac4064b50f557f1d250e1c1591aa83fa427fe0639f049724ee6069ce9060e8b47ae18a87baf807357a347758f815a751c6e17efdfd60dc287bc0329b44e3cec5cbdfad86f4b416cb6a6ddd50174a71d812f039f7333adbefe15b6d65f37c9734399b3c174f22244b800adc9f71c159d9b11cbfc3c2eb2cc7d9a258c31e83c87c3eb4b4dd4ccac632559bf3ab8a02e5e32bd76f084f0a356caf35a31738a1d8fa35bcb63d5006632c55b190e8d297ac80eda0c6291a108c3aec75dae6e44f5f5ac903aeac1b7d91760acc52fbedf8044f6119639ad676a7bf1be34ec673f4b20a633a0ccde188b7bbdf4cb8393e9c838b40a1a5f1e6d4fe65b81e9d2a9a2a77859eb06f0754c06c7a5dc31f45370da0d0e6ca3bb2cd9426cb4b884477b9691658c61733ecd7ad261e00b0169489b3f2ccde0363521d4c875c30b0b352443924f093def9e30cb75b3362b43c9b8937efbb90dddb543856b6951208883edd0319e962682f8e46779236fe1fdfeec7f1fe4999c9f23dc15b2b026a202191e66f7bafcc435343275661b52d739ef2c88aa4e3634856732ab25b20a3782dfff2c6b0c02c00f3a621dc202a8b5fe84c0d6a8a1597e956a8d704dd7c5870fbdd74b15fa72c218f2bc891740392255a5ef90a144c821d912378cb1881e3bb19bf0ea7ded1371594588deec3dcdc7443a02df1ba14cc659487726da2bdffb706190322c4eac76d9190d47ca602c4cd62b41eaa01fac151cf594664e2ace6e55f7004ba9830678a15894ea38131d581060f4dab726b2b52affd77597ebb43d6745885c7cf6e920b7e865efbebe6a93fcc263d6e91e244f8b50887b3dd85810af336f8d2e0d1c1625b3c87fe4c7d9a7a137d607bc6fcb8a48ceef9fc657848d33aaff0846326901f39f05c23397333907a89494ba826f0f6763530abcd2fe5ffd907ef24ccc968a279663df32963ff437fee6a66bbdd885f3f6fee4a6b08f2c15cf3576c8436c58cb7f2bfe6a2cc77d381f14655689cd95f16e36540d59ff9d814d6cb943feb314e641a64961c2917f12f566f8034f17e76bb54482783516594bf46be64567336581c619e6a1be67a0ce672388fa757e2268b270976fac9c097baa792354e5b3f4a3f5cffdb28a0f88735c953cc465caeff14d01bb7a2658541759df98fae0fd6854b60fb71a8c51e009be023de885c3f50d6e4115220b13e329e8e66fbec0d76a9cf1203b632ef7509974b3b2ee3f31ddc4fd76ceeec3955db83fd3cd28ee0aa2848e4bb214d7c77f2966f0c45ffadb4e1ee2e90d67b6a66bcd46f1dcc1d05eb71376d844b6ee8b16c47c019bc11d8af12405e2fb134c0eb56fe587c410cf9a52528f0f18d0dd09bc6f9e2d5e9f12066edd4fa8c07cee94e2a604dcad9e54881a47c23757ea0b0a1a34b4bd367e40176c52a685832a02029a7a8b39bef1c5eeb8fcf89a288de055d81aa6f94ae80f859389f4bf6ca4f21e87f462e61f938b95d379177eb43fc4b49d295c29c364e7178c8c1f9fa57224b14f1b712bf90c0f4514c4082c238b1fed116abe95c87b3096ff63106d531c02829af8a15074e2b8c522e7b4ec9cf659c9dde4b58582b352cb9314b071a12af25b1191d89cb79feddfa7ea0206470ada10a9a027401897b57bf1a9e6f3b5255e025bf0ff58ebca185948d3d9c14d4e0b8a1ca4fe0fb3acc271c129993ab795ad40211dffcd37eca0fcafac2366d64a52fedffa203a7b7cdf74aa9db38fd00047dd0b1ebe40c48ced90847dc73d098718369aaa7709978e754b540c1b3a27f094a1c0fd26fcb93267dd6e4cad8e0f8cc6f8f4bae9c3306aedbf687eb983e6ecfc54e9c21e483f6776aa1623bda110e1c20d953460b26d99ad988efc75b1327de7bd2d738d6b7eb182c12409dfbd330f763d261fc31c77a21f9e6d8c370e3629bda5351a5dae9d9bf3e83f07fb2ca09d484f4f84fa4a750daa98ae39e7e0177be6d4a9be7559c5aa31e80f23f9348013a20db76aec849063b550f8086d7000f8ca123068bdb41d68a4893d67c11efbfaeb3d07d98312f02aaa8cf403b106172ad127721f1d06ce5cb49271db3b3238d98ba8e6daa63bbcedf0154a319cea849864da18eb7d99ff0ecacd528650b76038ea16fd733d481d31efb3a19a146370cae9f4cad4c5b3d9074c008970e6f79a9f704ff4ae31813a800f2da14702ba0349ca3e2fe3dd9d84cea4f4bea1e6380f97851a7293682e3c61b84df33f4f38649c6d7df01fad9f27eb3871982239c3e6a791401f29cb974a5d52d93f8ae122bc4b3c7cb4911e00eae7723fbffac5e04858fc8aa47842048dfb459a2c31a2c332df9d02243f160af649b925dc3174d65d312ebda988b6bc2cc3f958633b7962efdffad6e8337e03739974ec97d02def4cba8fa4d5620d08503dd7db8cb04d461ad3bac1a7753f3489600d5c97ddd7713e7b8806d10d313021f245ea4e9908b8dc43458b090b3fe55e24eb3d85635ca55afd7faa4491087cc669ac4f51fd91005db803fcb8ff685e1d7076570867a3d3c9c7dd59d7f77c33682a75d03ee4d066c4ba5cdb5959a1e6ecc91672c9f39443b2610bdb3246749f2ebe0636bd56ad323acfb8f2971fd1c6f3b933556f0e173c3e546ff8fc86d70641acc948755c10abe6817f07175be2475cc735c9a3c1140895277378debf8fb1c87c24d00ffde11af15719e38414bbaf4c7c84960d1373edde627e227ffa83e8ecb78194324208c782d9ee4e84534446ed5e8884540c1c34428ef7bf883f9bf3d5e4475e87316dfac2906610bf1f655667f7aa5a21b4f824e8324817a094bf19aa8bdef4b6d5f9fbd803eaf0df800625e2cf50e21b14ed07f8d6d8f27003d7a39434ae1e66339211edbbe0b7897e0ffc856ce4e2eb33e4239c020f189f93cbd9ba681fa63f552186293eb22d672268237858cc233819c6c2fa3f5551d64c830345ae9953eb428fa0b316c61a2173fae2e41b726dabcf792a3a141264bd37e8695c8f84ec0f02c2a8b4ca86465f79ab81f13b3c88ec5ce7a3850aae1afb5be0532892483a569ea4e553e35979c83d6447c642943ba2c8f67703a8913b39c15408d03f4d05651d1ca1b9e8a67a04c60e7e8cb8e14f751c90ecdb76248f1e6f2dd17d1efb14e78711220d61d712bc1d8f6c6a238a8d0f5f9c4c36fccddd536f51f657b8bb3182e46db278d753099848d159890df9ba159902dd3bc3f5ef7fc9aabf8594f322de3d179722d182273f51ba8f10fd95a132d2aae81352058b4b831f73303a0db0a499f71932d7cc335a3f3455287cc6090c137cb4e531637a5fa7975c7f336fa37c01f582d17199f7901b26f2f911f4b94b63608bdae97983623cfcc09b0683c30d7cf918262851398aec77afaa44877a98cb3eb31a01ae70fd4b35e8ab3bafd80012eb255a835cc2efba11d4649de7149b52fe75cc016908d7db2a1cd85b5da9fccbb3ef940b225a688edba94ea57d4ffb0088191871141299f4c3a44aedf4ffaab039bffd460cc89d6fbd7591e3aff360ddc4e727da1657ea9ee8c72879dca2b2c866dcbdbe80d635659f8254dfe6c774f29a2721c4d79f73e281ce9a877c5abb1c2090fbfbe74ad9786916c0228b94dc46f3202eb5bfb1dbc77601caa03eef6db25021df83aaed30b1037afd33042243e1b51b74373657cb56afa8dd4b89287294dfd892e02f87e31756f6329abb394fccca601ed1a457eb96140bfe11c6ce6fcab3fd3c9ae0e099b248d187e016a1a80e1837520c717ae28f8e7253795ba90f5ab6d8043724bffb8bc255258c7f21f7af89e8386e058859490324040bb181f74eceb0134162eeb0a9adc834265d83e4b804bafa81c849f7cd5d6a3a4f301ed2ade5cf914004336115ef73db37188d163070f7bdcd23856522828c1dce40484680e27ba5ba7157b6d5729e43461808361fb7e5acd97c034a505cd2d40f4ac6fbceadfd7739112256f31c9194dbc4bbeb8ec0ccec2d3c8c4f60d183889ab4619b9f2e9d30444c5bea76d793f57e8670de8373f6a851cce81c59cbe960f8e8e1cbfc4da2f8648acc19678aed8eb8c5edb709b8aa06ce92df5843314a85b04c0e35ebf256f61f333b8ccd1de88810eafb1d25772f2e2af838ab26ebef1e4a4aaf817705ff5300af71ebb077ca0b0f5b62b8e198ce49f065bdbf0be020544f498e57a56ee6368c6636dd1982db3e3b81ea314403cf7fa5413439f9fa254f46b1715d7f1553c84dc1510a0e25654a1fc45b3056a17af7d3f366c4f9204536b7e9213e0ce28d31ca268c1b9a48ae57408d7c5c205816da01e51b06123ac9312a5b66a054bede988bfeadb8c2d3ff8c2842165ea911ed4fb87e1ba74c31f96a286e072c608f8c2519b27d8890afa0115e4df1ddfab5457f7f262d50afeb1d06388ace89373fe002fba8c4340bc2d90f6a14d582192a6792de451ba944517d30e317815fe1b42254b94a4a633bf5f2aed5018af5105a9baf5d43ab59124b610eb07de95867d89a46dcffd6be29313215257ad7dde72b29fe8589a60921c210c82725ce1ad09190fdeb2e32eddc5ce36de5e986e3a48758a8dd7dd3607a9cd387d075f84d24c94ba46e4124975c5f4bdd9ab55dae515571d5ee88fc0724c3f27334d62e9a6c671461ed9f7564b223b28ece4625e7f57dbcac3e13e7a5271db5b3dab13aa9af53335cf1b0edfee58f62a70804a53599e6815657845de38c9463704a6ce221f575f0bf01dc530afd8aa251d157a741447a08fbc14426695a0f46d10d71efaa46b592afa68b713303feb9b4b0a7f1b2fe2098c102bc0ade9975a4ffaa2628eeabfb635667250d1efed2f0f72d5c4d31cfc07bd3a453d1ea52b0c621a9f557922b2fa9dccc12f076f6ee8f43d0de8166c043f7572f7042368ca7f46093454241cf39ad695dbae2e1f43adebf229555f8d88f5576297d276a4f4276e4ef7db2a19e01b723a386aa07fe9e2494aaea9390208ddd571ce1462ea36993d445076f5aa06f0f3525dc12921f02abe9f04301d59e25d6238f046728910494581e4a4115dd6cfcc56b25e0275c4eb9e77d0969705c408a010b4e540320fbc19a00aef07a5edec7fcfecadd70bf6a97b5d8a5910862c43f1a1727d465593662bf769b43302aafb9016531d1154f3e8d7d897d4146b69b3e953bf7aef7429ebff2057904e049c518fd28c484be14b2e26419fb43d262abcf9bff26ab60e619205937b0f931c40a2c17d0eabd1217afe0940f865e536ede3954ec1c93484a90cc1c93a8ebcca2643f78e40a46b95f1bcd35f3855971e01ac6e789412e5978ec0c64a1caa158ebbd9747ec8ee55cf4e0f26e4e62fdd5c249bc7d5efe433977132859ea7ce57ea7fc7dad71dd63a3dfe49768a78412271b52643df4b99c904fef6822f5277de6df0939d2fa5f87352711044b8653600ef41d0650d2dbff07096713e84a3432379bcc13dd0f7c1bbbd44d803e7337ae335492eadd81cd3545ab6273d27209cc19e12d53f6389ce5dcef825469f798c53e4399570d87f606f340cace09f4101336bb144047fe27af417f97c9f599de6ed6ca1a97086ebd39b9cd866db458b0cf33306923f5e8853f918c74250ae2716fa3effdf0f5bd8c983e5c7e98fc2750c7bb4814442b7f1e5d751f01b0cf59ba904fbc2aabfcfdcae92bf49a9709e85ac4740cfdeb0f495bd3953e26b46d861f9b7f39890f47b5def5279ec2b10223358e06830c60c9d0a26898f4cb770cf10956dd6d0366fb6d3284db61de2f0f6149ed1ab62aea829c5ce32746d842d223e18b11607ef643ae2d5eef45d6595a28 -MD = 776b9d5aa2f2be8fd77632a62627dd5e690b8c283243c469e7c22c7df3f5ca1a - diff --git a/pycryptopp/testvectors/SHA256Monte.txt b/pycryptopp/testvectors/SHA256Monte.txt deleted file mode 100644 index e96396d..0000000 --- a/pycryptopp/testvectors/SHA256Monte.txt +++ /dev/null @@ -1,309 +0,0 @@ -# CAVS 5.0 -# "SHA-256 Monte" information for "s" -# SHA-256 tests are configured for BYTE oriented implementations -# Generated on Wed Feb 08 14:59:33 2006 - -[L = 32] - -Seed = f8ae5b970f4f0630b3584e681b2edbd6d14b0ceeccd63b30d877429f3f693d75 - -COUNT = 0 -MD = 09ee2a32d22292aa0824b3bf94cd541a257d20c1a04b974540982a282489054e - -COUNT = 1 -MD = ba7be8f8df73cf7af75fee72edd757c5d4c2caef1a6671079841565b98a43e7b - -COUNT = 2 -MD = 6e628c0a11e0fe3f25e0f6ae7a7fed0c4cd768f9e152735e4791fada9ae53155 - -COUNT = 3 -MD = 5638936e971f778fa3c4265d39afbc443569c549b34c1a3a7333a78ccb2f2177 - -COUNT = 4 -MD = 231cd2497dd4316bcc5dedca7c1c49eeb530f5012fb3eff909cd44f24902ed09 - -COUNT = 5 -MD = 07597b37cd575dc0c85658ee99cd9b94d587f48d627f12ce4acc2b2c15f1c1be - -COUNT = 6 -MD = e61f9624f6e95770b34ef6fb41ef71910efdf30030ce5710f2b466050182848e - -COUNT = 7 -MD = 2367e6b4948d2b7e4c8dc881988799927c5494e572f0e0973412581adb680091 - -COUNT = 8 -MD = 2ad0dc580ec372f6c5d51ae963f6a916332e5bab7943de967d22ddde2c410b5f - -COUNT = 9 -MD = 68fe11a2f396c16331206d4b34a66bbd2e18ebf56959e5753c1c474fe01b3361 - -COUNT = 10 -MD = f4c4bd653944a3782de1dc03848576e7df0f4088e03f1a33c50cbf084718f108 - -COUNT = 11 -MD = 892824f520dae3f505b3c7597769fde7c83809e9512123a8f1cb51452240dec0 - -COUNT = 12 -MD = ce53b5caea0595133218a9697e5a19c39e24b47703df4e27ed1603588f632308 - -COUNT = 13 -MD = 00f76278f86deecf65fb8d625086d262fbc92452f18facb690b723a315245bc0 - -COUNT = 14 -MD = dad692604724b15a7bda74f4fb314030a7e41dad74b85dedf7d80fa6519ee1fe - -COUNT = 15 -MD = 747b9769d7c8a38295413c2158acdb58352b7a6b5d96b28ed19bd69c1bd73288 - -COUNT = 16 -MD = 7c0df1c6ee57c2699c734fca01f34294be4eb3d3593137cced9072f4848769d1 - -COUNT = 17 -MD = 4a8ba3e99a23c13755ea87a9cff35ff819b25b05c95ca9ac60a0fa3fabae7896 - -COUNT = 18 -MD = b896a76e6da426a571985588f6a8ef3cd2472a0c523dcfec16028839246e8549 - -COUNT = 19 -MD = 6362feff7380064c763eefed1695aa1319ff4bc53baa5b1b990105607393c655 - -COUNT = 20 -MD = 158a21edd73b735a9553e67422969c98959a7db85c90b7668b6ea0daad65bd64 - -COUNT = 21 -MD = 5b19a6e1070b9e11add233fc9ea5220904ac94d6314c344495173bdbb45f3866 - -COUNT = 22 -MD = 50def9a51f9e1bf9139e7e7f8ff6e9f5235f02e9c5b354e8f5ca2c7e13c2ce34 - -COUNT = 23 -MD = ff1005549276b4d7bb9f38a112de25298471a9cf3314056f46c11e73a351f0fe - -COUNT = 24 -MD = 3402617e1e0e7708d83a52fa092b6aa909908576aed1d26b1227f339ffebfab4 - -COUNT = 25 -MD = 13cf2cf2cf15541b63982bbf519d77aa09b483a974b2bc4697527fafa62dc189 - -COUNT = 26 -MD = c9c3218c1c4d7427339680cc0453eee73623fb2e3263070d4c88208f920518b6 - -COUNT = 27 -MD = 354181b335df0fb7e6ed168fd39b7846adb2d0ba80e9042c9e0c2c60ba9cdf29 - -COUNT = 28 -MD = 1d7b7a3a5132fa30ca4320238a5ad21e6fd5db73df2fe86038654ad5b1bfc84f - -COUNT = 29 -MD = 16e37238d08a22215eb0a1c6c6091a2a3bb58033252f0111dae92e5e7235b4c0 - -COUNT = 30 -MD = 5e27313155783b27e9d807ddee76abdee5cd46092fc7643cb35fc40ef4a96673 - -COUNT = 31 -MD = efb9f27b1dead16decf8f12d6e2448a2532e2a8bc7335d84c7ab12ed8e02fb6b - -COUNT = 32 -MD = 44760c03d905b13f3c30317c3640f46dffe6666e14e15cbbe51f32021071e59a - -COUNT = 33 -MD = 6f3904cc784f30cec50af89b7ebd55c2eae42b466bf9cc0bb25d8d726896a4c5 - -COUNT = 34 -MD = 7c0143342e2f349c9a6f672ffc84497a066e489cb6daa6420c1402ce2d4ff621 - -COUNT = 35 -MD = e89ddce4e1180323dc91046f0fafab6d6c9f58635b83236e8417651473da7403 - -COUNT = 36 -MD = a6264c5fa97d90727b3c6eedde63dd98b406ccfdcc9412a02a22164581acd1dc - -COUNT = 37 -MD = 1ace95b10c616735eac1418845b517ef90ee720b16437f402b41f5ff155c3a03 - -COUNT = 38 -MD = 9bf8bb64cc4932b79ed5ef3931f804f010aa75907b327ec0dad2e1aeb0c513cd - -COUNT = 39 -MD = d1fd03544852358ed4aa7a34d9ba725465fa0e6276347808b716ae20b6142e7d - -COUNT = 40 -MD = 83d60511c5d40671dad61cc6ff7276765185155d94c5b4207b4d1efcc9445af3 - -COUNT = 41 -MD = e7dfcb3bee49d94e7fe69ef6e18810e6ca7714c9e6a30860b375e877ffc4899c - -COUNT = 42 -MD = 85bae087e9fd30bfdc4ac661628aa13041cbad8b754a8ef649722c87fcd8271c - -COUNT = 43 -MD = b638925c3d3d01a69ee8c3d49037929c2b0ce40b2d947ad569a9bada6377c9f1 - -COUNT = 44 -MD = 94021cb567befbcb39896da53c2652bdf45bbf11a8558c96b2c78b48f0e2e8f9 - -COUNT = 45 -MD = a80a47a151fac789971406cf564bd495023e22bbb1692c2a371e206bc15a81ed - -COUNT = 46 -MD = e01b864141592511803e8af245d4cd5a03d87c7fa92c675378bc6b82983bc83b - -COUNT = 47 -MD = e4b8f81ea92b63555116fcd1ec5ceb4eab5211e47233f877ca496eabf3bc7a50 - -COUNT = 48 -MD = 29a7339e8944af2550d0f0aebf7ff3daa9b48e8e56832661e7ed339ebf03fe33 - -COUNT = 49 -MD = 273c9b49e7ac633f8764d78ce3c93da0a9ca0ebc977112ce418e3be108f2a193 - -COUNT = 50 -MD = f0730c968990642f31983c78079c10838facdad31f9d4bebacf114a70f0f9ed8 - -COUNT = 51 -MD = 11e9c8c01be733bea0f5e8b2c818c2dfc2595dc438d8b079615a56e7cd22e4ce - -COUNT = 52 -MD = c2d150a802f57ebd346c8d18ef2b2f16adf0e8e5b3d7f51ad38fc868c6afcb09 - -COUNT = 53 -MD = f5f873e2c00c71f850ca400f0d83d24d3c89285a4dfa51c5faa6597190414134 - -COUNT = 54 -MD = 6ac1adbaabbda9bdc6a5eee91865effb6d77bbeff368b8081030a6c1a9abfcfc - -COUNT = 55 -MD = 9122b914fda8edc3343496fa97221011d6a6ee601f9ceacdd47a9acdce5b5c48 - -COUNT = 56 -MD = e7554826e969494bd2e51d9696cdc3acdcfaf3e40595b8975f3c41c636bdaf15 - -COUNT = 57 -MD = f99581ba1dbaebfb0d36662c87789587814b0ac59713be372dc3a275b4944e5f - -COUNT = 58 -MD = b3eeedded2c1d0faa0d98559eb39e632c64aa5fc907e2363e4a4b1991284f630 - -COUNT = 59 -MD = 6da9d793de479d8776bb97e934ef4b60ce05402db9b4e01d8da9a1f7e58538db - -COUNT = 60 -MD = 6d2e2dc25ae12e221fb90267c7c8f38986be70c3016299bc43f8331e92243d97 - -COUNT = 61 -MD = ffa69b8370840ad7a899b593079caf266be680560323ab3b5c06308576576634 - -COUNT = 62 -MD = 26cdbb571cc6428b40b70f705599afdfaf11b0400a7a59c5233e64cb39721ad4 - -COUNT = 63 -MD = d1f1c0b2cd13bd370d7ffea815fda3e16f33a0977088d7351d35f02cd2aec150 - -COUNT = 64 -MD = 8f28c49126339b44f0b4b39b3dfd454fabf21578e2c16af0bbc1ddb7b6d2ed8c - -COUNT = 65 -MD = 1ce2820507b8fa01764eaa846def8ec67848d7088405905d2f141d755a8ab98c - -COUNT = 66 -MD = c15ce1637d55784423140f5f5b8ebb94e459872c04cc431cf48a573e54120ac3 - -COUNT = 67 -MD = 66eb577bd140e0f04de9369d18835fe2f7c0b1c5eca7a2061156a855053a52e0 - -COUNT = 68 -MD = 8550df9ac711398138a2112b01a8b84dc05dd76d56029bfd3e4de1a9d1cfde29 - -COUNT = 69 -MD = bb3678468a71042d91609a23c61b09b8e495724a572382a9be0d1fba60bc8486 - -COUNT = 70 -MD = 4f1607c64b1fab340ddeaa4788399eb3490b50b5578452c8a7ef1b5e77bd2554 - -COUNT = 71 -MD = 5d8dc29cda8d327b670079bb3a7b0ed85274173ccbefef9c55b0abd2744f844f - -COUNT = 72 -MD = 47cf16deb9329e32e394aa7a21cc9ba751a3a28565d99c7446e291504ade4450 - -COUNT = 73 -MD = 4bded81824986b7c00a6b033992e85b581c375369d293642014c998dad1cd0d8 - -COUNT = 74 -MD = 6c0b1fa62d160897b7eab9a66d2d95523f920d753504f55b67b57c3cd8e9209c - -COUNT = 75 -MD = d7f1854c446e07095d7a43a43dbc426be36627c839985a624e62eb72ac805a87 - -COUNT = 76 -MD = 8b1e6d1e6c7622edec8d79cb6148b9a426cd39be50d8c3466ba0694fa8c50dcc - -COUNT = 77 -MD = ab59f72305f4d6ff6aa59a56c2019cd1395e09048e0084048ffe9b71ae90cd01 - -COUNT = 78 -MD = 7516a477b87f681e09860ed1d733c13ec950e99e5f368af288fedf6d626edd14 - -COUNT = 79 -MD = c36e14b9e2113a97fa4af6dfbab1cc459c8b51b88af67092447fa0e6b655f847 - -COUNT = 80 -MD = 6857b96120b5162b28270d3a4d494cbb85eaa561d7944b3e9c82fd194d8e21d6 - -COUNT = 81 -MD = a92f35c6bc90606f21eb1ab2c1ff5686bcf16d17396c8791e6d04b933ae65a52 - -COUNT = 82 -MD = 2eb7b3fe45f98255f0b0f9c06b22491e4529b443bc3f3469aaa86d094cebfde2 - -COUNT = 83 -MD = f9c4f44331bce44c374e70a01ffbb0c68fa8294d5a1b644cec589efebdeba8af - -COUNT = 84 -MD = 197f8dc01ec7dd651d427c3dff0f7ee92c48d2b3e8eefea3446241aa85d7149f - -COUNT = 85 -MD = faf152566f1147f26d10e1a5ba17aed6f0de76c1a732bbcd739ee492d944f208 - -COUNT = 86 -MD = 5ec46420a6db67f05849d9824ba14f18544e8ff3aab0d47f28096e497dac3a21 - -COUNT = 87 -MD = 590f1bc2bed8d47f5fdd4610ddc7f424c7a928730d41985100e04d5033f7339f - -COUNT = 88 -MD = e246ab37d4b2a2b4adfb0e0d4b2da2e06e9e46d30f5e0c0dcfa6e267fe3566ac - -COUNT = 89 -MD = 6f8fb3f1a68a78f3246f500d988b3e40511a01f4dc3c8b5f1744d3ea54e6e1ca - -COUNT = 90 -MD = dd9a32c79c216a69a1d11c7403845592980125153b68f78f1ac07a311ecab1fd - -COUNT = 91 -MD = 0bc729d8ad18522c27468e5bafc2c056264492e6bf9806a38f7555c585a10b82 - -COUNT = 92 -MD = 870347b7cbfe42a151f9e895b1b2acab394ee75cf65814a19d2d49ac7f5eebdc - -COUNT = 93 -MD = 7180ec50dd7e6c36dc84070ba715cfe31c2a928070b90f3367319029e8ae75f1 - -COUNT = 94 -MD = eb07ebb21f1733a9535fdde391670cba3770836c194bdddb8909d2d56bb95ebb - -COUNT = 95 -MD = e40479c983a83a4d675af2085be9c37d9e376073eeed91d51915ad34ca720608 - -COUNT = 96 -MD = 62d496f020d1ad5866e99162f8e8b2de33d6b4be69440b6b6dceb8a170daf9b3 - -COUNT = 97 -MD = 8ee2f635187ba7ae412f5372eae2cc4b43e88be59e1deed354dfae9c0c45de87 - -COUNT = 98 -MD = a0e64d2ce09db5fc47300d30e9f8292bff2232f3ac29ece64e9f80d0d0029205 - -COUNT = 99 -MD = 17d79c61aec50de7b7cc0a2cd6fb50fb16af40ff985fd5d5f39cb0672c3f0bf5 - diff --git a/pycryptopp/testvectors/SHA256ShortMsg.txt b/pycryptopp/testvectors/SHA256ShortMsg.txt deleted file mode 100644 index 4eef712..0000000 --- a/pycryptopp/testvectors/SHA256ShortMsg.txt +++ /dev/null @@ -1,267 +0,0 @@ -# CAVS 5.0 -# "SHA-256 ShortMsg" information for "s" -# SHA-256 tests are configured for BYTE oriented implementations -# Generated on Wed Feb 08 14:59:33 2006 - -[L = 32] - -Len = 0 -Msg = 00 -MD = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 - -Len = 8 -Msg = bd -MD = 68325720aabd7c82f30f554b313d0570c95accbb7dc4b5aae11204c08ffe732b - -Len = 16 -Msg = 5fd4 -MD = 7c4fbf484498d21b487b9d61de8914b2eadaf2698712936d47c3ada2558f6788 - -Len = 24 -Msg = b0bd69 -MD = 4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803 - -Len = 32 -Msg = c98c8e55 -MD = 7abc22c0ae5af26ce93dbb94433a0e0b2e119d014f8e7f65bd56c61ccccd9504 - -Len = 40 -Msg = 81a723d966 -MD = 7516fb8bb11350df2bf386bc3c33bd0f52cb4c67c6e4745e0488e62c2aea2605 - -Len = 48 -Msg = c97a2db566e5 -MD = 0eb0281b27a4604709b0513b43ad29fdcff9a7a958554abc689d7fe35af703e4 - -Len = 56 -Msg = f53210aa6ed72e -MD = dee684641421d1ba5a65c71f986a117cbb3d619a052a0b3409306c629575c00f - -Len = 64 -Msg = 0df1cd526b5a4edd -MD = 47f527210d6e8f940b5082fec01b7305908fa2b49ea3ae597c19a3986097153c - -Len = 72 -Msg = b80233e2c53ab32cc3 -MD = c60d239cc6da3ad31f4de0c2d58a73ccf3f9279e504fa60ad55a31dcf686f3ca - -Len = 80 -Msg = 5d54ed5b52d879aeb5dd -MD = e0164d90dbfcf173bb88044fac596ccd03b8d247c79907aaa5701767fad7b576 - -Len = 88 -Msg = df866ecb67ab00515f6247 -MD = dc990ef3109a7bcf626199db9ab7801213ceb0ad2ee398963b5061e39c05c7b5 - -Len = 96 -Msg = 0757de9485a2eaea51126077 -MD = c1c9a4daadcc8678835872c7f1f8824376ac7b412e1fc2285069b41afd51397e - -Len = 104 -Msg = 7c66f5d443c11cfb39dd0aa715 -MD = 6840619417b4d8ecaa7902f8eaf2e82be2638dec97cb7e8fcc377007cc176718 - -Len = 112 -Msg = 329624fed35639fe54957b7d47a9 -MD = 0f5308ff22b828e18bd65afbc427e3c1a678962832519df5f2f803f68f55e10b - -Len = 120 -Msg = c34e59652acc043873ecf6a4ab1060 -MD = 0fdf1604ac0d717ec9587b4de5444aaade807589d90eb326eaf6acb58a051e79 - -Len = 128 -Msg = fdf4700984ee11b70af1880d0e0fefd4 -MD = b01ae16eed3b4a770f127b98469ba26fe3d8e9f59d8a2983214afe6cff0e6b6c - -Len = 136 -Msg = ea40aadbefedb0e0d78d067c6cd65c2c87 -MD = 36157bbe61931d58a3a644953eaf131bbc2591c673a1f20353f51ca5054fc1c2 - -Len = 144 -Msg = 6d1092004670efab3af483d265d8e7b3da73 -MD = 67fbf35d360d72b101410794ccf197106c0e784afa9c80206a550b600dbf1f16 - -Len = 152 -Msg = 55a10148ae7b09ac4e71df438135bc70e873eb -MD = cbe7965513af46dfd596dc5839cb82a5c6c7328034b1dd0042a9f4b71fb14430 - -Len = 160 -Msg = a03f8fcd777bd933b4b0af8c5ce3d61308565649 -MD = ddfce4e8c7b38845e2a81b7fc27a06366467a9e111316014013f9701e2413ce0 - -Len = 168 -Msg = 8e5d6cba8d4b206381e33ca7339bec504f3d6119ba -MD = 92f678a3e59d0dd3610eec3222b8c6ebd28eead530723fbd226747534da22b6c - -Len = 176 -Msg = 96db1b62eed85f2628d0c25da534401fe80d13d09beb -MD = 725bab4457c789d6a4cc4736b9c2c662cda18407150844d74d6aa4efd72dbb05 - -Len = 184 -Msg = 1c482a45dfbcda549729126b533477edfaf7476fde498f -MD = 6523f24f225b996aad1a8b317e6e0f8e97673dcff3fd62a27ff9f3888ea1302d - -Len = 192 -Msg = 0f677d8e4c6d6a057492670d99adb870adf68a36ead37919 -MD = 44acbbc6b48bf37ee088b9c8546fc46e5a5f0d637b5e444f628de186144087fd - -Len = 200 -Msg = c09056d597816542bffe4bb33e475dfb2d6293016906ddc18c -MD = f4baeaef70588a0820d63c2401dd84f98adf7366782d196f8698d7dfd3db1c29 - -Len = 208 -Msg = 72f313fdcf52d0749c9937cc2e53f50b44d65a544876bab7d2f8 -MD = cfa67aa52fd675fca985f69f9ca58af62baead8c39723bb6bfbae8a5d4bb9beb - -Len = 216 -Msg = 09f6fe6cbe6744149f792a4a827e4e8909627abf75301bf7bbd7f5 -MD = 657633891dc6274d6aeda78e7313dfb960eac9a24d29293a057b9746a18de4ec - -Len = 224 -Msg = 9e1cfeb335bc331744247df4bbd56876a7f69298aaf6b9e7a8731889 -MD = 930058dd21cb48b2cf90eaca55322ddf48582687838a584928440504a2fde578 - -Len = 232 -Msg = b8913001efb1b7f4bd975e349c5b2cbe66045bf0d2fb019b3bc0f059a4 -MD = a0eb0b7fad1d1b6de4f9096724a621720538a9c3f2f6d11134d68cb9ee52fc88 - -Len = 240 -Msg = 8f08537d50928c911a68b071d65b9e8f038264d3b62c5f33de18a484cde9 -MD = 10aad5cd4484387373577a881974f1a550782108bc88b4e2e8085e9c3e938bbb - -Len = 248 -Msg = fd846162c4da936d004ffe0cbe844d940f1c2953157cf4765dceba2a6f4c64 -MD = c13ba769aea0e478816f2f608b5cec3fe14672ea033088a8641cfe69b4ff57cb - -Len = 256 -Msg = 8cf53d90077df9a043bf8d10b470b144784411c93a4d504556834dae3ea4a5bb -MD = 56059e8cb3c2978b198208bf5ca1e1ea5659b737a506324b7cec75b5ebaf057d - -Len = 264 -Msg = 1bbc2b15253c126e301f9f64b97be4ce13e96337687e2e78fbfd4c8daf4a5fa1cd -MD = d973b5dcdae4cf2599f4db4068e4aa354f22d8901adc463ca3938c465578147b - -Len = 272 -Msg = c1bdb3bfc65dfe9a393331266c58d05fb9c8b7476bb717dadc29bc43dabd91504fc9 -MD = 57844e1d762e6b7bb86dbfcc5c5a59578d39cc665d1ddbe4de03a61778061af1 - -Len = 280 -Msg = 26eb621a45bd9c9c764ccbb672b99f2a8379c7bbf4fb07eec58a8b0ea4747b72196ccf -MD = 73dc27bd45daccd0f811381230cf7f2a1d3ed1202e9a770af733146b1e166315 - -Len = 288 -Msg = 7e3e3986109162e0c56357048bbd86ff49b93644b7fb064e7280968650978466f02c9adf -MD = 682c474799f5103252c3e2efef7f747783e514b54e93b8303b0e07ee4218f78e - -Len = 296 -Msg = 763c1a9ea50bd72bfc516989ddf3eff2f208f64fccea3cf0ca8dba7f3d10e237c99226510f -MD = 54d6cb2b09825eab064c8952113b9897a3344737cd186a8e6be0a0b258da3e57 - -Len = 304 -Msg = e1a7ffea8417e7cd49b96e355fd44f3f7a150fab6dd8343dfba3b262eaf3a6175a3c4607552b -MD = 83baa80caade404c446833ecef2e595bba6dce2cb7f7422fad2972a9fe327aca - -Len = 312 -Msg = 692a18effad8317a11a5cddb917f7389e1be6dba34572a300e52e056047e758bc363a0be53784c -MD = 0c0c6a6b27a6d7a7a5130d70db3b8bc1bd8001d103efe72f45b082cadbd03742 - -Len = 320 -Msg = 73fda1e1cb7dc9a9ece858d040d7105cc126eab153fb0bb55703f4317dfff97bd980f4523aee3a09 -MD = 9878f8804e00828b39261843f2b3eda19a7e9b9ff4cc2e23f7ea1f62f4491ff2 - -Len = 328 -Msg = 2321d88c19e3e6a8309a09a5428c01991e16446823f13b2f0db4ade30e9a7c3521868fb99b440f4802 -MD = f1bd3a8a74c8f0093038499ef63794d86fc6d82602a802a435718e61e7b396cc - -Len = 336 -Msg = b9eaebda29172b052bcc1e3a9c7f2eced43c084a86f89f61e7237425137c167aac29e4cac4071afafd3f -MD = ea43ec91285145d8f29915b227a0e35c89f90d968f9a14332dad275cfd52d619 - -Len = 344 -Msg = 332daf07d3a6775b18572549a6e12b8a27d81b7c4abcc5bd0b2b9ff936546b0026af131cd3ecd8a10c29ab -MD = a573959ba6b1c3bebfd6288c806b72a65650d23bd46d123816a2a6a0e47d1e66 - -Len = 352 -Msg = 30ac7eace1f2e41034c25a3d3e2db979c23dfaa7a4914b0da147625b3e1f12e9fedc1c41d8ee47dde84fb332 -MD = c0c3f40d34e711bfadf517b3a78140e379fba5f7edf2c1bc3ce82469dae4d2d5 - -Len = 360 -Msg = 02c3964c4ad9c4af97d373099302c2cd770ad06c7d8bd11c970161d861e917a854265e223da28031ee38041534 -MD = c13c622bf08a3d3cf1fd6fa5e26e505e551b1643bc5a0f59ed29541235218f77 - -Len = 368 -Msg = b9eed82edcf0c7ba69f6f6ac5722cb61daecaf30437511582117ad36ad410ebc6582511ef6e32dce5f7a30ab543c -MD = 6ac64caaeda4763d28a44b363823a6b819285410fb4162af6ca657396f6028d0 - -Len = 376 -Msg = b574865024828bf651df070ac0cec1849aa6470901d2e30fa01dcb43862d9827344cf900f46fa9ef6d709e5e759f84 -MD = 4c839e8f8f373c25a9a3351257c6152258ff8e6a88dad42f30f2bbecab56c20b - -Len = 384 -Msg = eebcf5cd6b12c90db64ff71a0e08ccd956e170a50dad769480d6b1fb3eff4934cde90f9e9b930ee637a66285c10f4e8a -MD = c117b9dce689c399ec99008788cd5d24d8396fab7d96315c4f3fe6d56da63bb3 - -Len = 392 -Msg = 1b7a73770d168da45bf2e512eee45153e02f4dfe3b42e50304a3d63d7826f0469562be8fdc6569b056a7dafcd53d1f597c -MD = 0b42cfc3dd3d3198f06c30e087837ec6a6dd35d08e54e886c682709f8f42457a - -Len = 400 -Msg = 0072ae2f3bda67736b9c66e2130260b3a4847bc3968e037cb6835efcc2014273336725cd5a94f592aef20a0a65b459a4415b -MD = 217cf25b8b343c28336b1c1e9bed29e0c96045bc93daf426e490b608b0905c90 - -Len = 408 -Msg = 2ac748680f3bc1bf098c4be38c7194643b0d009e51c43630404cdfaf9807aa9b299094916c9466c31fe37fa630c6d3eadc9434 -MD = 3ea59e2e79513679a22e962f22408306f7e8f6e562c2f1f210e279fad8eaacc6 - -Len = 416 -Msg = 893d1a8863d234ee50e5a8c7650a4de047230ad03d268dde8921401ff97b79dfb97cf2426b0f782b79c7e75daa2155e1f4098ea7 -MD = f7808e03e5d5af43c2bffb66e35d1ecbd79f4d8fec44f821f73a235d17c70a89 - -Len = 424 -Msg = cf673b96eaf241cfa3e262dc6fe65f08bcc2be56d8a2c9710eaddae212ded6859f0ff83e5e57d0e80a968b8ed24e74defeb5bbdad6 -MD = 9bdb7cf0492ace4620a47660acd127f951767b0738b5504451d6ed56e4fa3cbd - -Len = 432 -Msg = 0d545be1f47b966214691c21278704e89a17d52dd96aeeeacc5325a9a1ddafdecd39407a4dfa72bd32856b4c5cc2ba838618830c8399 -MD = ad53e0db7e63211c8b00947908ce29660c4376e244e19cd30a659af65dc6f1fe - -Len = 440 -Msg = 9eabfcd3603337df3dcd119d6287a9bc8bb94d650ef29bcf1b32e60d425adc2a35e06577d0c7ce2456cf260efee9e8d8aeeddb3d068f37 -MD = 83eeed2dfeb8d2604ab5ec1ac9b5dcab8cc2222518468bc5c24c16ce72e70687 - -Len = 448 -Msg = 2fc7b9e8b8dcaac64ecef4c5f91877543ac36ae494d9faf84b1d347b6cf925570db84043d6f500dcc153cef81d6f2437d913f3dbffad42d9 -MD = 6ef7e9f12267ebc4901267da147effdcdebcd6ec5393c7f62ec4c4f06ca72649 - -Len = 456 -Msg = cf95929ab732f9ef5e8c3e6b4ed753852ee74e4fddf31b56c29a6ec95d23fcde2209eb7288b787f05d9036735c32ae2f01fc650d9cce4995a5 -MD = 3e5854169da065407fa465a4694f3fcb1d141480a8f84c970a0f63364ec8f590 - -Len = 464 -Msg = 826378013988684c40f4d917c7ed8b72aba66fd68f085d0b2eb20948ef3f349dbbc71f8e0ba845014586495a48902ee44505c673d2f76d473950 -MD = 5b506b823ef6658939aca22f52bbe5a4b849c31b8fa1d09139352e501137bc04 - -Len = 472 -Msg = 0cab6d38ce9849fcbd589f7235a6d2c2cb933e26e1ca6f4e78189104452c280c069b024e162769373f409d5cd0cb8160f0239418325d23ee6ad1bd -MD = 92943076cda4c46718e55df64d7580e12b8fb2c2911e87851246ccf6791fa3e6 - -Len = 480 -Msg = 3fb4a8c5b57c14731179256608614c95c9725ddad5fbfa99111d4fa319d3015ad830601556e8e4c6d012d7da0e2c4f60f1605f6e4c058ec0f46988a3 -MD = 8e90da3eb146935264576f874fcc5a64b7a90ab6c8a36c15d855b0179f52f899 - -Len = 488 -Msg = 9050a6d002c90f6036c592b0f6b866713e7894d29645f4a19e0858b3ebd8078711c26d2601ca104d962dc6ce6ae92634ee7f3ca6baf8810e2126097a09 -MD = 03c516677735ae83dbe5a7e4c22c1ac1bfedcd46e7dd785f8bfe38e148eda632 - -Len = 496 -Msg = d659ec136bacfa0b5c906aabedc93c01c5f1efa3f370a1432ea8778461703f0c67c454da12bac2da73b8abb755e5eaf10bddf52f6ca908d61bee80da0c64 -MD = fff2852957a0eeb577e73fd7d827f650261dfb9a8a65f52df4bbbc9b2d0ae50e - -Len = 504 -Msg = b498555658332b197bc5cb7adc5c1997aabbdcf1f7ffcc2b6b82eb0f350019d247f8e399c3559d3bb04eb049f28b344c7989c24db83f839b59028dc82fa670 -MD = bfbbf242f79bff4ae0aafb4ccf69b24fdca4342d83db1dfd1822c74a9e218e8d - -Len = 512 -Msg = 3592ecfd1eac618fd390e7a9c24b656532509367c21a0eac1212ac83c0b20cd896eb72b801c4d212c5452bbbf09317b50c5c9fb1997553d2bbc29bb42f5748ad -MD = 105a60865830ac3a371d3843324d4bb5fa8ec0e02ddaa389ad8da4f10215c454 - diff --git a/setup.cfg b/setup.cfg index 730bf08..89482e3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,17 +1,17 @@ [easy_install] zip_ok = False +[aliases] +build = build +test = build test +sdist = build sdist +install = build install +bdist_egg = build bdist_egg +trial = build trial +sdist_dsc = build sdist_dsc + [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 -[aliases] -sdist_dsc = darcsver --count-all-patches sdist_dsc -sdist = darcsver --count-all-patches sdist -trial = darcsver --count-all-patches trial -build = darcsver --count-all-patches build -install = darcsver --count-all-patches install -test = darcsver --count-all-patches test -bdist_egg = darcsver --count-all-patches bdist_egg - diff --git a/setup.py b/setup.py index 450f1e5..34143d5 100644 --- a/setup.py +++ b/setup.py @@ -1,17 +1,23 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- -# pycryptopp -- Python wrappers for Crypto++ -# -# Copyright (C) 2009-2010 Zooko Wilcox-O'Hearn +# Copyright © 2009-2012 Zooko Wilcox-O'Hearn # Author: Zooko Wilcox-O'Hearn -# See README.txt for licensing information. +# +# See README.rst for licensing information. -import glob, os, platform, re, subprocess, sys +import os, platform, re, subprocess, sys -egg = os.path.realpath(glob.glob('darcsver-*.egg')[0]) -sys.path.insert(0, egg) +from setuptools import Extension, setup +from setuptools import Command +from distutils.util import get_platform +from setuptools.command.test import ScanningLoader +import unittest -from setuptools import Extension, find_packages, setup +PKG='pycryptopp' +VERSION_PY_FNAME = os.path.join('src', PKG, '_version.py') + +import versioneer # ECDSA=False ECDSA=True @@ -33,12 +39,13 @@ if "--disable-embedded-cryptopp" in sys.argv: if os.environ.get('PYCRYPTOPP_DISABLE_EMBEDDED_CRYPTOPP') == "1": DISABLE_EMBEDDED_CRYPTOPP=True -EMBEDDED_CRYPTOPP_DIR='embeddedcryptopp' +EMBEDDED_CRYPTOPP_DIR='src-cryptopp' -TEST_DOUBLE_LOAD=False -if "--test-double-load" in sys.argv: - TEST_DOUBLE_LOAD=True - sys.argv.remove("--test-double-load") +BUILD_DOUBLE_LOAD_TESTER=False +BDLTARG="--build-double-load-tester" +if BDLTARG in sys.argv: + BUILD_DOUBLE_LOAD_TESTER=True + sys.argv.remove(BDLTARG) # There are two ways that this setup.py script can build pycryptopp, either by using the # Crypto++ source code bundled in the pycryptopp source tree, or by linking to a copy of the @@ -161,7 +168,7 @@ else: trove_classifiers=[ "Environment :: Console", - "License :: OSI Approved :: GNU General Public License (GPL)", + "License :: OSI Approved :: GNU General Public License (GPL)", # See README.rst for alternative licensing. "License :: DFSG approved", "License :: Other/Proprietary License", "Intended Audience :: Developers", @@ -176,38 +183,39 @@ trove_classifiers=[ "Programming Language :: Python :: 2.4", "Programming Language :: Python :: 2.5", "Programming Language :: Python :: 2.6", + "Programming Language :: Python :: 2.7", "Topic :: Software Development :: Libraries", ] -PKG='pycryptopp' -VERSIONFILE = os.path.join(PKG, "_version.py") -verstr = "unknown" -try: - verstrline = open(VERSIONFILE, "rt").read() -except EnvironmentError: - pass # Okay, there is no version file. -else: - VSRE = r"^verstr = ['\"]([^'\"]*)['\"]" - mo = re.search(VSRE, verstrline, re.M) - if mo: - verstr = mo.group(1) - else: - print "unable to find version in %s" % (VERSIONFILE,) - raise RuntimeError("if %s.py exists, it is required to be well-formed" % (VERSIONFILE,)) - -srcs = ['pycryptopp/_pycryptoppmodule.cpp', 'pycryptopp/publickey/rsamodule.cpp', 'pycryptopp/hash/sha256module.cpp', 'pycryptopp/cipher/aesmodule.cpp'] +srcs = ['src/pycryptopp/_pycryptoppmodule.cpp', + 'src/pycryptopp/publickey/rsamodule.cpp', + 'src/pycryptopp/hash/sha256module.cpp', + 'src/pycryptopp/cipher/aesmodule.cpp', + 'src/pycryptopp/cipher/xsalsa20module.cpp', + ] if ECDSA: - srcs.append('pycryptopp/publickey/ecdsamodule.cpp') -if TEST_DOUBLE_LOAD: - srcs.append('_testdoubleloadmodule.cpp', ) + srcs.append('src/pycryptopp/publickey/ecdsamodule.cpp') +if BUILD_DOUBLE_LOAD_TESTER: + srcs.append('_doubleloadtester.cpp', ) ext_modules.append( Extension('pycryptopp._pycryptopp', extra_srcs + srcs, include_dirs=include_dirs, library_dirs=library_dirs, libraries=libraries, extra_link_args=extra_link_args, extra_compile_args=extra_compile_args, define_macros=define_macros, undef_macros=undef_macros) ) -if TEST_DOUBLE_LOAD: +# python-ed25519 +sources = [os.path.join("src-ed25519","glue","ed25519module.c")] +sources.extend([os.path.join("src-ed25519","supercop-ref",s) + for s in os.listdir(os.path.join("src-ed25519","supercop-ref")) + if s.endswith(".c") and s!="test.c"]) +m = Extension("pycryptopp.publickey.ed25519._ed25519", + include_dirs=[os.path.join("src-ed25519","supercop-ref")], + sources=sources) +ext_modules.append(m) + + +if BUILD_DOUBLE_LOAD_TESTER: ext_modules.append( - Extension('_testdoubleload', extra_srcs + srcs, include_dirs=include_dirs, library_dirs=library_dirs, libraries=libraries, extra_link_args=extra_link_args, extra_compile_args=extra_compile_args, define_macros=define_macros, undef_macros=undef_macros) + Extension('_doubleloadtester', extra_srcs + srcs, include_dirs=include_dirs, library_dirs=library_dirs, libraries=libraries, extra_link_args=extra_link_args, extra_compile_args=extra_compile_args, define_macros=define_macros, undef_macros=undef_macros) ) miscdeps=os.path.join(os.getcwd(), 'misc', 'dependencies') @@ -215,102 +223,208 @@ dependency_links=[os.path.join(miscdeps, t) for t in os.listdir(miscdeps) if t.e setup_requires = [] install_requires = ['setuptools >= 0.6a9'] # for pkg_resources for loading test vectors for unit tests -# The darcsver command from the darcsver plugin is needed to initialize the -# distribution's .version attribute. (It does this either by examining darcs -# history, or if that fails by reading the pycryptopp/_version.py -# file). darcsver will also write a new version stamp in -# pycryptopp/_version.py, with a version number derived from darcs -# history. Note that the setup.cfg file has an "[aliases]" section which -# enumerates commands that you might run and specifies that it will run -# darcsver before each one. If you add different commands (or if I forgot some -# that are already in use), you may need to add it to setup.cfg and configure -# it to run darcsver before your command, if you want the version number to be -# correct when that command runs. http://pypi.python.org/pypi/darcsver -setup_requires.append('darcsver >= 1.6.3') - # setuptools_pyflakes is needed only if you want "./setup.py flakes" to run # pyflakes on all the pycryptopp modules. if 'flakes' in sys.argv[1:]: setup_requires.append('setuptools_pyflakes >= 1.0.0') -# setuptools_darcs is required to produce complete distributions (such -# as with "sdist" or "bdist_egg"), unless there is a -# pycryptopp.egg-info/SOURCE.txt file present which contains a complete -# list of files that should be included. -# http://pypi.python.org/pypi/setuptools_darcs However, requiring it -# runs afoul of a bug in Distribute, which was shipped in Ubuntu -# Lucid, so for now you have to manually install it before building -# sdists or eggs: -# http://bitbucket.org/tarek/distribute/issue/55/revision-control-plugin-automatically-installed-as-a-build-dependency-is-not-present-when-another-build-dependency-is-being -if False: - setup_requires.append('setuptools_darcs >= 1.1.0') - # stdeb is required to produce Debian files with "sdist_dsc". # http://github.com/astraw/stdeb/tree/master if "sdist_dsc" in sys.argv: setup_requires.append('stdeb') -data_fnames=['COPYING.GPL', 'COPYING.TGPPL.html', 'README.txt'] +data_fnames=['COPYING.GPL', 'COPYING.TGPPL.html', 'README.rst'] + +readmetext = open('README.rst').read() # In case we are building for a .deb with stdeb's sdist_dsc command, we put the # docs in "share/doc/pycryptopp". doc_loc = "share/doc/" + PKG data_files = [(doc_loc, data_fnames)] -# Note that due to a bug in distutils we also have to maintain a -# MANIFEST.in file specifying embeddedcryptopp/extraversion.h. This bug was -# fixed in Python 2.7 -data_files.append((EMBEDDED_CRYPTOPP_DIR, [EMBEDDED_CRYPTOPP_DIR+'/extraversion.h'])) +commands = {} -if ECDSA: - long_description='RSA-PSS-SHA256 signatures, ECDSA(1363)/EMSA1(SHA-256) signatures, SHA-256 hashes, and AES-CTR encryption' -else: - long_description='RSA-PSS-SHA256 signatures, SHA-256 hashes, and AES-CTR encryption' +###### Version updating code -PY_VERSION_BODY=''' -# This is the version of this tree, as created by %(versiontool)s from the darcs patch -# information: the main version number is taken from the most recent release -# tag. If some patches have been added since the last release, this will have a -# -NN "build number" suffix, or else a -rNN "revision number" suffix. Please see -# pyutil.version_class for a description of what the different fields mean. +CPP_GIT_VERSION_BODY = ''' +/* This _version.py is generated from git metadata by the pycryptopp + * setup.py. The main version number is taken from the most recent release + * tag. If some patches have been added since the last release, this will + * have a -NN "build number" suffix, or else a -rNN "revision number" suffix. + */ -__pkgname__ = "%(pkgname)s" -verstr = "%(pkgversion)s" -try: - from pyutil.version_class import Version as pyutil_Version - __version__ = pyutil_Version(verstr) -except (ImportError, ValueError): - # Maybe there is no pyutil installed, or this may be an older version of - # pyutil.version_class which does not support SVN-alike revision numbers. - from distutils.version import LooseVersion as distutils_Version - __version__ = distutils_Version(verstr) +#define CRYPTOPP_EXTRA_VERSION "%(pkgname)s-%(pkgversion)s" ''' -CPP_VERSION_BODY=''' -/* This is the version of this tree, as created by %(versiontool)s from the darcs patch - * information: the main version number is taken from the most recent release - * tag. If some patches have been added since the last release, this will have a - * -NN "build number" suffix, or else a -rNN "revision number" suffix. Please see - * pyutil.version_class for a description of what the different fields mean. - */ +def get_normalized_version(versions): + pieces = versions['version'].split("-") + +# examples: versions: {'version': '2.3.4-dirty', 'full': '5ebdca46cf83a185710ecb9b29d46ec8ac70de61-dirty'} +# examples versions: {'version': '0.5.29-108-g5ebdca4-dirty', 'full': '5ebdca46cf83a185710ecb9b29d46ec8ac70de61-dirty'} +# examples: pieces: ['0.5.29', '108', 'g5ebdca4', 'dirty'] +# examples: pieces: ['2.3.4', 'dirty'] +# examples: pieces: ['2.3.4'] + + normalized_version = [] + normalized_version.append(pieces.pop(0)) + + postrelease = None + dirty = False + + while len(pieces) > 0: + nextpiece = pieces.pop(0) + if re.match('\d+$', nextpiece): + postrelease = nextpiece + normalized_version.append('.'+postrelease) + elif nextpiece.startswith('g'): + continue + # Use the full version instead ,below + elif nextpiece == 'dirty': + dirty = True + + fullvhex = versions['full'].split('-')[0] + full = int(fullvhex, 16) + normalized_version.append('.'+str(full)) + + if postrelease is not None: + normalized_version.append('.post'+postrelease) + if dirty is True: + normalized_version.append('.dev0') + + return ''.join(normalized_version) + +def read_version_py(infname): + try: + verstrline = open(infname, "rt").read() + except EnvironmentError: + return None + else: + VSRE = r"^__version__ = ['\"]([^'\"]*)['\"]" + mo = re.search(VSRE, verstrline, re.M) + if mo: + return mo.group(1) -#define CRYPTOPP_EXTRA_VERSION "%(pkgname)s-%(pkgversion)s" +EXTRAVERSION_H_FNAME = os.path.join(EMBEDDED_CRYPTOPP_DIR, 'extraversion.h') + +VERSION_BODY = ''' +# This is the version of this tree, as created by %(versiontool)s from the +# git information: the main version number is taken from the most recent +# release tag. If some patches have been added since the last release, this +# will have a -NN "build number" suffix, followed by -gXXX "revid" suffix. + +__pkgname__ = "%(pkgname)s" +__version__ = "%(pkgversion)s" ''' +class UpdateVersion(object): + def run(self): + + versions = versioneer.versions_from_vcs(PKG+'-', '.') + assert isinstance(versions, dict) + + vers_f_file = read_version_py(VERSION_PY_FNAME) + + if not versions and vers_f_file is None: + raise Exception("problem: couldn't get version information from revision control history, and there is no version information in '%s'. Stopping." % (VERSION_PY_FNAME,)) + + if versions: + version = get_normalized_version(versions) + else: + version = vers_f_file + + # Let's avoid touching the change time (ctime) on the files unless + # they actually need to be updated. + + if self.read_extraversion_h(EXTRAVERSION_H_FNAME) != version: + self.write_extraversion_h( + PKG, + version, + EXTRAVERSION_H_FNAME, + CPP_GIT_VERSION_BODY + ) + + if read_version_py(VERSION_PY_FNAME) != version: + self.write_version_py( + PKG, + version, + VERSION_PY_FNAME, + VERSION_BODY, + "pycryptopp's setup.py" + ) + + return version + + def write_version_py(self, pkgname, version, outfname, body, EXE_NAME): + f = open(outfname, "wb+") + f.write(body % { + 'versiontool': EXE_NAME, + 'pkgversion': version, + 'pkgname': pkgname, + }) + f.close() + + def write_extraversion_h(self, pkgname, version, outfname, body): + f = open(outfname, "wb") + f.write(body % {"pkgname": pkgname, "pkgversion": version}) + f.close() + + def read_extraversion_h(self, infname): + try: + verstrline = open(infname, "rt").read() + except EnvironmentError: + return None + else: + VSRE = r"^#define CRYPTOPP_EXTRA_VERSION +\"([^\"]*)\"" + mo = re.search(VSRE, verstrline, re.M) + if mo: + return mo.group(1) + +version = UpdateVersion().run() + +class Test(Command): + description = "run tests" + user_options = [] + def initialize_options(self): + self.test_suite = None + def finalize_options(self): + if self.test_suite is None: + self.test_suite = self.distribution.test_suite + def setup_path(self): + # copied from distutils/command/build.py + self.plat_name = get_platform() + plat_specifier = ".%s-%s" % (self.plat_name, sys.version[0:3]) + self.build_lib = os.path.join("build", "lib"+plat_specifier) + sys.path.insert(0, self.build_lib) + def run(self): + self.setup_path() + loader = ScanningLoader() + test = loader.loadTestsFromName(self.test_suite) + runner = unittest.TextTestRunner(verbosity=2) + result = runner.run(test) + sys.exit(not result.wasSuccessful()) +commands["test"] = Test + setup(name=PKG, - version=verstr, + version=version, description='Python wrappers for a few algorithms from the Crypto++ library', - long_description=long_description, - author='Zooko O\'Whielacronx', + long_description=readmetext, + author='Zooko Wilcox-O\'Hearn', author_email='zooko@zooko.com', - url='http://tahoe-lafs.org/trac/' + PKG, - license='GNU GPL', # see README.txt for details -- there is also an alternative licence - packages=find_packages(), + url='https://tahoe-lafs.org/trac/' + PKG, + license='GNU GPL', # see README.rst for details -- there is also an alternative licence + packages=["pycryptopp", + "pycryptopp.cipher", + "pycryptopp.hash", + "pycryptopp.publickey", + "pycryptopp.publickey.ed25519", + "pycryptopp.test", + ], include_package_data=True, exclude_package_data={ '': [ '*.cpp', '*.hpp', ] }, data_files=data_files, + package_dir={"pycryptopp": "src/pycryptopp"}, setup_requires=setup_requires, install_requires=install_requires, dependency_links=dependency_links, @@ -318,6 +432,5 @@ setup(name=PKG, ext_modules=ext_modules, test_suite=PKG+".test", zip_safe=False, # I prefer unzipped for easier access. - versionfiles=[os.path.join('pycryptopp', '_version.py'), os.path.join(EMBEDDED_CRYPTOPP_DIR, 'extraversion.h')], - versionbodies=[PY_VERSION_BODY, CPP_VERSION_BODY], + cmdclass=commands, ) diff --git a/setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/PKG-INFO b/setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/PKG-INFO deleted file mode 100644 index 200a803..0000000 --- a/setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/PKG-INFO +++ /dev/null @@ -1,32 +0,0 @@ -Metadata-Version: 1.0 -Name: setuptools-darcs -Version: 1.2.11 -Summary: setuptools plugin for darcs -Home-page: http://tahoe-lafs.org/trac/setuptools_darcs -Author: Zooko O'Whielacronx -Author-email: zooko@zooko.com -License: BSD -Description: UNKNOWN -Keywords: distutils setuptools setup darcs -Platform: UNKNOWN -Classifier: Framework :: Setuptools Plugin -Classifier: Development Status :: 5 - Production/Stable -Classifier: License :: OSI Approved :: BSD License -Classifier: License :: DFSG approved -Classifier: Intended Audience :: Developers -Classifier: Operating System :: Microsoft -Classifier: Operating System :: Microsoft :: Windows -Classifier: Operating System :: Unix -Classifier: Operating System :: POSIX :: Linux -Classifier: Operating System :: POSIX -Classifier: Operating System :: MacOS :: MacOS X -Classifier: Operating System :: Microsoft :: Windows :: Windows NT/2000 -Classifier: Operating System :: OS Independent -Classifier: Natural Language :: English -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.4 -Classifier: Programming Language :: Python :: 2.5 -Classifier: Programming Language :: Python :: 2.6 -Classifier: Topic :: Utilities -Classifier: Topic :: Software Development :: Libraries diff --git a/setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/SOURCES.txt b/setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/SOURCES.txt deleted file mode 100644 index f3d9ab9..0000000 --- a/setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/SOURCES.txt +++ /dev/null @@ -1,13 +0,0 @@ - -README.txt -setup.cfg -setup.py -setuptools_darcs/__init__.py -setuptools_darcs/_version.py -setuptools_darcs/setuptools_darcs.py -setuptools_darcs.egg-info/PKG-INFO -setuptools_darcs.egg-info/SOURCES.txt -setuptools_darcs.egg-info/dependency_links.txt -setuptools_darcs.egg-info/entry_points.txt -setuptools_darcs.egg-info/not-zip-safe -setuptools_darcs.egg-info/top_level.txt \ No newline at end of file diff --git a/setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/dependency_links.txt b/setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/entry_points.txt b/setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/entry_points.txt deleted file mode 100644 index 51f2125..0000000 --- a/setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/entry_points.txt +++ /dev/null @@ -1,3 +0,0 @@ -[setuptools.file_finders] -darcs = setuptools_darcs.setuptools_darcs:find_files_for_darcs - diff --git a/setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/not-zip-safe b/setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/not-zip-safe deleted file mode 100644 index 8b13789..0000000 --- a/setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/not-zip-safe +++ /dev/null @@ -1 +0,0 @@ - diff --git a/setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/top_level.txt b/setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/top_level.txt deleted file mode 100644 index de95482..0000000 --- a/setuptools_darcs-1.2.11-py2.6.egg/EGG-INFO/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -setuptools_darcs diff --git a/setuptools_darcs-1.2.11-py2.6.egg/setuptools_darcs/__init__.py b/setuptools_darcs-1.2.11-py2.6.egg/setuptools_darcs/__init__.py deleted file mode 100644 index 03549d3..0000000 --- a/setuptools_darcs-1.2.11-py2.6.egg/setuptools_darcs/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -__version__ = "unknown" -try: - from _version import __version__ -except ImportError: - # We're running in a tree that hasn't run darcsver from the pyutil library, - # and didn't come with a _version.py, so we don't know what our version - # is. This should not happen very often. - pass diff --git a/setuptools_darcs-1.2.11-py2.6.egg/setuptools_darcs/_version.py b/setuptools_darcs-1.2.11-py2.6.egg/setuptools_darcs/_version.py deleted file mode 100644 index a3a73be..0000000 --- a/setuptools_darcs-1.2.11-py2.6.egg/setuptools_darcs/_version.py +++ /dev/null @@ -1,16 +0,0 @@ - -# This is the version of this tree, as created by setup.py darcsver from the Darcs patch -# information: the main version number is taken from the most recent release -# tag. If some patches have been added since the last release, this will have a -# -NN "build number" suffix, or else a -rNN "revision number" suffix. Please see -# pyutil.version_class for a description of what the different fields mean. - -verstr = "1.2.11" -try: - from pyutil.version_class import Version as pyutil_Version - __version__ = pyutil_Version(verstr) -except (ImportError, ValueError): - # Maybe there is no pyutil installed, or this may be an older version of - # pyutil.version_class which does not support SVN-alike revision numbers. - from distutils.version import LooseVersion as distutils_Version - __version__ = distutils_Version(verstr) diff --git a/setuptools_darcs-1.2.11-py2.6.egg/setuptools_darcs/setuptools_darcs.py b/setuptools_darcs-1.2.11-py2.6.egg/setuptools_darcs/setuptools_darcs.py deleted file mode 100644 index 30a36ce..0000000 --- a/setuptools_darcs-1.2.11-py2.6.egg/setuptools_darcs/setuptools_darcs.py +++ /dev/null @@ -1,79 +0,0 @@ -import os, re - -from subprocess import Popen, PIPE - -THISDIR_RE=re.compile("What's new in \"(.*)\"") - -def exec_darcs(darcscmd): - cmd = ['darcs'] + darcscmd - try: - p = Popen(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True) - except EnvironmentError: - cmd = ['realdarcs.exe'] + darcscmd - p = Popen(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True) - - output = p.communicate()[0] - return (p.returncode, output) - -def run_darcs_query_manifest(): - return exec_darcs(['query', 'manifest']) - -def run_darcs_whatsnew_dot(): - return exec_darcs(['whatsnew', '.']) - -def find_files_for_darcs(dirname): - try: - unused, whatsnewoutput = run_darcs_whatsnew_dot() - queryretcode, queryoutput = run_darcs_query_manifest() - except EnvironmentError: - if not os.path.exists('PKG-INFO'): - from distutils import log - log.warn("Unable to execute darcs -- if you are building a package with 'setup.py sdist', 'setup.py bdist_egg', or other package-building commands, then the resulting package might be missing some files. If you are not building a package then you can ignore this warning.") - # Oh well -- just return None. - return - - if queryretcode != 0: - if not os.path.exists('PKG-INFO'): - from distutils import log - log.warn("Failure to get the list of managed files from darcs -- if you are building a package with 'setup.py sdist', 'setup.py bdist_egg', or other package-building commands, then the resulting package might be missing some files. If you are not building a package then you can ignore this warning.") - # Oh well -- just return None. - return - - # We got output. - mo = THISDIR_RE.search(whatsnewoutput) - if mo: - curdirname = mo.group(1) - while curdirname.endswith('/'): - curdirname = curdirname[:-1] - curdirname += "/" - else: - curdirname = "" - - # Prepend this directory. - rel_to_repo_dirname = curdirname + dirname - - # Normalize rel_to_repo_dirname from local form to the form that setuptools uses to the form that "darcs query manifest" outputs (unix form). - rel_to_repo_dirname = rel_to_repo_dirname.replace('\\', '/') - while rel_to_repo_dirname.endswith('/'): - rel_to_repo_dirname = rel_to_repo_dirname[:-1] - - # Append a '/' to make sure we don't match "foobar" when rel_to_repo_dirname is "foo". - if rel_to_repo_dirname: - rel_to_repo_dirname += '/' - - warn = True - for fn in queryoutput.split('\n'): - if fn == ".": - continue - if fn.startswith('./'): - fn = fn[2:] - if fn.startswith(rel_to_repo_dirname): - fn = fn[len(rel_to_repo_dirname):] - warn = False - # We need to replace "/" by "\\" because setuptools can't includes web/*.xhtml files on Windows, due of path separator - # This correct ticket #1033 - yield fn.replace('/', os.sep) - - if warn and not os.path.exists('PKG-INFO'): - from distutils import log - log.warn("Didn't find any files in directory \"%s\" (full path: \"%s\") that were managed by darcs revision control -- if you are building a package with 'setup.py sdist', 'setup.py bdist_egg', or other package-building commands, then the resulting package might be missing some files. If you are not building a package then you can ignore this warning." % (dirname, os.path.abspath(rel_to_repo_dirname),)) diff --git a/setuptools_darcs-1.2.11-py2.6.egg/share/doc/python-setuptools_darcs/README.txt b/setuptools_darcs-1.2.11-py2.6.egg/share/doc/python-setuptools_darcs/README.txt deleted file mode 100644 index b881110..0000000 --- a/setuptools_darcs-1.2.11-py2.6.egg/share/doc/python-setuptools_darcs/README.txt +++ /dev/null @@ -1,143 +0,0 @@ - -setuptools_darcs Manual -======================= - -About ------ - -This is a plugin for setuptools that integrates darcs. Once -installed, Setuptools can be told to include in a package distribution -all the files tracked by darcs. This is an alternative to explicit -inclusion specifications with `MANIFEST.in`. - -A distribution here refers to a package that you create using -setup.py, ex: - - python setup.py sdist - python setup.py bdist_egg - python setup.py bdist_rpm - -This package was formerly known as setuptools_darcs_plugin. The name -change is the result of an agreement by the setuptools plugin -developers to provide a uniform naming convention. - - -Installation ------------- - -With easy_install: - - easy_install setuptools_darcs - -Alternative manual installation: - - tar -zxvf setuptools_darcs-X.Y.Z.tar.gz - cd setuptools_darcs-X.Y.Z - python setup.py install - -Where X.Y.Z is a version number. - -Alternative to make a specific package use setuptools_darcs without -installing setuptools_darcs into the system: - - Put "setup_requires=['setuptools_darcs']" in the call to setup() in - the package's setup.py file. - - -Usage ------ - -To use this plugin, you must first package your python module with -`setup.py` and use setuptools. The former is well documented in the -distutils manual: - - http://docs.python.org/dist/dist.html - -To use setuptools instead of distutils, just edit `setup.py` and -change - - from distutils.core import setup - -to - - from setuptools import setup - -When setuptools builds a source package, it always includes all files -tracked by your revision control system, if it knows how to learn what -those files are. - -When setuptools builds a binary package, you can ask it to include all -files tracked by your revision control system, by adding this argument -to your invocation of `setup()`: - - setup(..., - include_package_data=True, - ...) - -This plugin lets setuptools know what files are tracked by your darcs -revision control tool. setuptools ships with support for cvs and -subversion. Other plugins like this one are available for bzr, git, -monotone, and mercurial, at least. - -It might happen that you track files with your revision control system -that you don't want to include in your packages. In that case, you -can prevent setuptools from packaging those files with a directive in -your `MANIFEST.in`, ex: - - exclude .darcs-boringfile - recursive-exclude images *.xcf *.blend - -In this example, we prevent setuptools from packaging -`.darcs-boringfile` and the Gimp and Blender source files found under -the `images` directory. - -Alternatively, files to exclude from the package can be listed in the -`setup()` directive: - - setup(..., - exclude_package_data = {'': ['.darcs-boringfile'], - 'images': ['*.xcf', '*.blend']}, - ...) - - -Gotchas -------- - -If someone clones your darcs repository using darcs but does not -install this plugin, then when they run a package building command -they will not get all the right files. On the other hand if someone -gets a source distribution that was created by "./setup.py sdist", -then it will come with a list of all files, so they will not need -darcs in order to build a distribution themselves. - -You can make sure that anyone who uses your setup.py file has this -plugin by adding a `setup_requires` argument. - - setup_requires=[] - # setuptools_darcs is required to produce complete distributions (such as with - # "sdist" or "bdist_egg"), unless there is a ${PKG}.egg-info/SOURCES.txt file - # present which contains a complete list of files that should be included in - # distributions. - # http://pypi.python.org/pypi/setuptools_darcs - setup_requires.append('setuptools_darcs >= 1.1.0') - - setup(..., - setup_requires = setup_requires, - ...) - - -References ----------- - -How to distribute Python modules with Distutils: - - http://docs.python.org/dist/dist.html - - -Setuptools complete manual: - - http://peak.telecommunity.com/DevCenter/setuptools - - -Thanks to Yannick Gingras for providing the prototype for this -README.txt. diff --git a/src-cryptopp/Doxyfile b/src-cryptopp/Doxyfile new file mode 100644 index 0000000..1fb9d81 --- /dev/null +++ b/src-cryptopp/Doxyfile @@ -0,0 +1,1109 @@ +# Doxyfile 1.3.7 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = Crypto++ + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = doc + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 2 levels of 10 sub-directories under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of source +# files, where putting all generated files in the same directory would otherwise +# cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, +# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en +# (Japanese with English messages), Korean, Korean-en, Norwegian, Polish, Portuguese, +# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is used +# as the annotated text. Otherwise, the brief description is used as-is. If left +# blank, the following values are used ("$name" is automatically replaced with the +# name of the entity): "The $name class" "The $name widget" "The $name file" +# "is" "provides" "specifies" "contains" "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited +# members of a class in the documentation of that class as if those members were +# ordinary class members. Constructors, destructors and assignment operators of +# the base classes will not be shown. + +INLINE_INHERITED_MEMB = YES + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = YES + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = Yes + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = NO + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = No + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = No + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = . + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp +# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm + +FILE_PATTERNS = *.h \ + *.cpp + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = adhoc.cpp + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories +# that are symbolic links (a Unix filesystem feature) are excluded from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = . + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 3 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = YES + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = . + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = _WIN32 \ + _WINDOWS \ + __FreeBSD__ \ + CRYPTOPP_DOXYGEN_PROCESSING + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse the +# parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. Note that this +# option is superseded by the HAVE_DOT option below. This is only a fallback. It is +# recommended to install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/src-cryptopp/GNUmakefile b/src-cryptopp/GNUmakefile new file mode 100644 index 0000000..291eb60 --- /dev/null +++ b/src-cryptopp/GNUmakefile @@ -0,0 +1,168 @@ +CXXFLAGS = -DNDEBUG -g -O2 +#CXXFLAGS = -g +# -fPIC is supported. Please report any breakage of -fPIC as a bug. +# CXXFLAGS += -fPIC +# the following options reduce code size, but breaks link or makes link very slow on some systems +# CXXFLAGS += -ffunction-sections -fdata-sections +# LDFLAGS += -Wl,--gc-sections +ARFLAGS = -cr # ar needs the dash on OpenBSD +RANLIB = ranlib +CP = cp +MKDIR = mkdir +EGREP = egrep +UNAME = $(shell uname) +ISX86 = $(shell uname -m | $(EGREP) -c "i.86|x86|i86|amd64") + +# Default prefix for make install +ifeq ($(PREFIX),) +PREFIX = /usr +endif + +ifeq ($(CXX),gcc) # for some reason CXX is gcc on cygwin 1.1.4 +CXX = g++ +endif + +ifeq ($(ISX86),1) + +GCC42_OR_LATER = $(shell $(CXX) --version 2>&1 | $(EGREP) -c "\(GCC\) (4.[2-9]|[5-9])") +INTEL_COMPILER = $(shell $(CXX) --version 2>&1 | $(EGREP) -c "\(ICC\)") +GAS210_OR_LATER = $(shell echo "" | $(AS) -v 2>&1 | $(EGREP) -c "GNU assembler version (2\.[1-9][0-9]|[3-9])") +GAS217_OR_LATER = $(shell echo "" | $(AS) -v 2>&1 | $(EGREP) -c "GNU assembler version (2\.1[7-9]|2\.[2-9]|[3-9])") +ISMINGW = $(shell $(CXX) --version 2>&1 | $(EGREP) -c "mingw") + +ifneq ($(GCC42_OR_LATER),0) +ifneq ($(UNAME),Darwin) +CXXFLAGS += -march=native -mtune=native +endif +endif + +ifneq ($(INTEL_COMPILER),0) +# "internal error: backend signals" occurs on some x86 inline assembly with ICC 9 and some x64 inline assembly with ICC 11 +# if you want to use Crypto++'s assembly code with ICC, try enabling it on individual files +CXXFLAGS += -DCRYPTOPP_DISABLE_ASM +endif + +ifeq ($(GAS210_OR_LATER),0) # .intel_syntax wasn't supported until GNU assembler 2.10 +CXXFLAGS += -DCRYPTOPP_DISABLE_ASM +else +ifeq ($(GAS217_OR_LATER),0) +CXXFLAGS += -DCRYPTOPP_DISABLE_SSSE3 +endif +ifeq ($(UNAME),SunOS) +CXXFLAGS += -Wa,--divide # allow use of "/" operator +endif +endif + +ifeq ($(ISMINGW),1) +LDLIBS += -lws2_32 +endif + +endif # ISX86 + +ifeq ($(UNAME),) # for DJGPP, where uname doesn't exist +CXXFLAGS += -mbnu210 +else +CXXFLAGS += -pipe +endif + +ifeq ($(UNAME),Linux) +LDFLAGS += -pthread +endif + +ifeq ($(UNAME),Darwin) +AR = libtool +ARFLAGS = -static -o +CXX = c++ +IS_GCC2 = $(shell $(CXX) -v 2>&1 | $(EGREP) -c gcc-932) +ifeq ($(IS_GCC2),1) +CXXFLAGS += -fno-coalesce-templates -fno-coalesce-static-vtables +LDLIBS += -lstdc++ +LDFLAGS += -flat_namespace -undefined suppress -m +endif +endif + +ifeq ($(UNAME),SunOS) +LDLIBS += -lnsl -lsocket +ifeq ($(CXX),CC) # override flags for CC (Solaris native C++ compiler) +CXXFLAGS = -DNDEBUG -O -g0 -native -template=no%extdef -m$(shell isainfo -b) +LDFLAGS = +ifeq ($(ISX86),1) +# SSE2 intrinsics should work in Sun Studio 12, but we're not using SSE2 intrinsics anymore +# CXXFLAGS += -xarch=sse2 -D__SSE2__ +endif +endif +endif + +SRCS = $(wildcard *.cpp) +ifeq ($(SRCS),) # workaround wildcard function bug in GNU Make 3.77 +SRCS = $(shell echo *.cpp) +endif + +OBJS = $(SRCS:.cpp=.o) +# test.o needs to be after bench.o for cygwin 1.1.4 (possible ld bug?) +TESTOBJS = bench.o bench2.o test.o validat1.o validat2.o validat3.o adhoc.o datatest.o regtest.o fipsalgt.o dlltest.o +LIBOBJS = $(filter-out $(TESTOBJS),$(OBJS)) + +DLLSRCS = algebra.cpp algparam.cpp asn.cpp basecode.cpp cbcmac.cpp channels.cpp cryptlib.cpp des.cpp dessp.cpp dh.cpp dll.cpp dsa.cpp ec2n.cpp eccrypto.cpp ecp.cpp eprecomp.cpp files.cpp filters.cpp fips140.cpp fipstest.cpp gf2n.cpp gfpcrypt.cpp hex.cpp hmac.cpp integer.cpp iterhash.cpp misc.cpp modes.cpp modexppc.cpp mqueue.cpp nbtheory.cpp oaep.cpp osrng.cpp pch.cpp pkcspad.cpp pubkey.cpp queue.cpp randpool.cpp rdtables.cpp rijndael.cpp rng.cpp rsa.cpp sha.cpp simple.cpp skipjack.cpp strciphr.cpp trdlocal.cpp +DLLOBJS = $(DLLSRCS:.cpp=.export.o) +LIBIMPORTOBJS = $(LIBOBJS:.o=.import.o) +TESTIMPORTOBJS = $(TESTOBJS:.o=.import.o) +DLLTESTOBJS = dlltest.dllonly.o + +all: cryptest.exe + +test: cryptest.exe + ./cryptest.exe v + +clean: + $(RM) cryptest.exe libcryptopp.a $(LIBOBJS) $(TESTOBJS) cryptopp.dll libcryptopp.dll.a libcryptopp.import.a cryptest.import.exe dlltest.exe $(DLLOBJS) $(LIBIMPORTOBJS) $(TESTIMPORTOBJS) $(DLLTESTOBJS) + +install: + $(MKDIR) -p $(PREFIX)/include/cryptopp $(PREFIX)/lib $(PREFIX)/bin + $(CP) *.h $(PREFIX)/include/cryptopp + $(CP) *.a $(PREFIX)/lib + $(CP) *.exe $(PREFIX)/bin + +libcryptopp.a: $(LIBOBJS) + $(AR) $(ARFLAGS) $@ $(LIBOBJS) + $(RANLIB) $@ + +cryptest.exe: libcryptopp.a $(TESTOBJS) + $(CXX) -o $@ $(CXXFLAGS) $(TESTOBJS) -L. -lcryptopp $(LDFLAGS) $(LDLIBS) + +nolib: $(OBJS) # makes it faster to test changes + $(CXX) -o ct $(CXXFLAGS) $(OBJS) $(LDFLAGS) $(LDLIBS) + +dll: cryptest.import.exe dlltest.exe + +cryptopp.dll: $(DLLOBJS) + $(CXX) -shared -o $@ $(CXXFLAGS) $(DLLOBJS) $(LDFLAGS) $(LDLIBS) -Wl,--out-implib=libcryptopp.dll.a + +libcryptopp.import.a: $(LIBIMPORTOBJS) + $(AR) $(ARFLAGS) $@ $(LIBIMPORTOBJS) + $(RANLIB) $@ + +cryptest.import.exe: cryptopp.dll libcryptopp.import.a $(TESTIMPORTOBJS) + $(CXX) -o $@ $(CXXFLAGS) $(TESTIMPORTOBJS) -L. -lcryptopp.dll -lcryptopp.import $(LDFLAGS) $(LDLIBS) + +dlltest.exe: cryptopp.dll $(DLLTESTOBJS) + $(CXX) -o $@ $(CXXFLAGS) $(DLLTESTOBJS) -L. -lcryptopp.dll $(LDFLAGS) $(LDLIBS) + +adhoc.cpp: adhoc.cpp.proto +ifeq ($(wildcard adhoc.cpp),) + cp adhoc.cpp.proto adhoc.cpp +else + touch adhoc.cpp +endif + +%.dllonly.o : %.cpp + $(CXX) $(CXXFLAGS) -DCRYPTOPP_DLL_ONLY -c $< -o $@ + +%.import.o : %.cpp + $(CXX) $(CXXFLAGS) -DCRYPTOPP_IMPORTS -c $< -o $@ + +%.export.o : %.cpp + $(CXX) $(CXXFLAGS) -DCRYPTOPP_EXPORTS -c $< -o $@ + +%.o : %.cpp + $(CXX) $(CXXFLAGS) -c $< diff --git a/src-cryptopp/License.txt b/src-cryptopp/License.txt new file mode 100644 index 0000000..fc3f054 --- /dev/null +++ b/src-cryptopp/License.txt @@ -0,0 +1,67 @@ +Compilation Copyright (c) 1995-2009 by Wei Dai. All rights reserved. +This copyright applies only to this software distribution package +as a compilation, and does not imply a copyright on any particular +file in the package. + +The following files are copyrighted by their respective original authors, +and their use is subject to additional licenses included in these files. + +mars.cpp - Copyright 1998 Brian Gladman. + +All other files in this compilation are placed in the public domain by +Wei Dai and other contributors. + +I would like to thank the following authors for placing their works into +the public domain: + +Joan Daemen - 3way.cpp +Leonard Janke - cast.cpp, seal.cpp +Steve Reid - cast.cpp +Phil Karn - des.cpp +Andrew M. Kuchling - md2.cpp, md4.cpp +Colin Plumb - md5.cpp +Seal Woods - rc6.cpp +Chris Morgan - rijndael.cpp +Paulo Baretto - rijndael.cpp, skipjack.cpp, square.cpp +Richard De Moliner - safer.cpp +Matthew Skala - twofish.cpp +Kevin Springle - camellia.cpp, shacal2.cpp, ttmac.cpp, whrlpool.cpp, ripemd.cpp + +Permission to use, copy, modify, and distribute this compilation for +any purpose, including commercial applications, is hereby granted +without fee, subject to the following restrictions: + +1. Any copy or modification of this compilation in any form, except +in object code form as part of an application software, must include +the above copyright notice and this license. + +2. Users of this software agree that any modification or extension +they provide to Wei Dai will be considered public domain and not +copyrighted unless it includes an explicit copyright notice. + +3. Wei Dai makes no warranty or representation that the operation of the +software in this compilation will be error-free, and Wei Dai is under no +obligation to provide any services, by way of maintenance, update, or +otherwise. THE SOFTWARE AND ANY DOCUMENTATION ARE PROVIDED "AS IS" +WITHOUT EXPRESS OR IMPLIED WARRANTY INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. IN NO EVENT WILL WEI DAI OR ANY OTHER CONTRIBUTOR BE LIABLE FOR +DIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +4. Users will not use Wei Dai or any other contributor's name in any +publicity or advertising, without prior written consent in each case. + +5. Export of this software from the United States may require a +specific license from the United States Government. It is the +responsibility of any person or organization contemplating export +to obtain such a license before exporting. + +6. Certain parts of this software may be protected by patents. It +is the users' responsibility to obtain the appropriate +licenses before using those parts. + +If this compilation is used in object code form in an application +software, acknowledgement of the author is not required but would be +appreciated. The contribution of any useful modifications or extensions +to Wei Dai is not required but would also be appreciated. diff --git a/src-cryptopp/Readme.txt b/src-cryptopp/Readme.txt new file mode 100644 index 0000000..861c036 --- /dev/null +++ b/src-cryptopp/Readme.txt @@ -0,0 +1,429 @@ +Crypto++: a C++ Class Library of Cryptographic Schemes +Version 5.6.0 (3/15/2009) + +Crypto++ Library is a free C++ class library of cryptographic schemes. +Currently the library contains the following algorithms: + + algorithm type name + + authenticated encryption schemes GCM, CCM, EAX + + high speed stream ciphers Panama, Sosemanuk, Salsa20, XSalsa20 + + AES and AES candidates AES (Rijndael), RC6, MARS, Twofish, Serpent, + CAST-256 + + IDEA, Triple-DES (DES-EDE2 and DES-EDE3), + other block ciphers Camellia, SEED, RC5, Blowfish, TEA, XTEA, + Skipjack, SHACAL-2 + + block cipher modes of operation ECB, CBC, CBC ciphertext stealing (CTS), + CFB, OFB, counter mode (CTR) + + message authentication codes VMAC, HMAC, CMAC, CBC-MAC, DMAC, + Two-Track-MAC + + SHA-1, SHA-2 (SHA-224, SHA-256, SHA-384, and + hash functions SHA-512), Tiger, WHIRLPOOL, RIPEMD-128, + RIPEMD-256, RIPEMD-160, RIPEMD-320 + + RSA, DSA, ElGamal, Nyberg-Rueppel (NR), + public-key cryptography Rabin, Rabin-Williams (RW), LUC, LUCELG, + DLIES (variants of DHAES), ESIGN + + padding schemes for public-key PKCS#1 v2.0, OAEP, PSS, PSSR, IEEE P1363 + systems EMSA2 and EMSA5 + + Diffie-Hellman (DH), Unified Diffie-Hellman + key agreement schemes (DH2), Menezes-Qu-Vanstone (MQV), LUCDIF, + XTR-DH + + elliptic curve cryptography ECDSA, ECNR, ECIES, ECDH, ECMQV + + insecure or obsolescent MD2, MD4, MD5, Panama Hash, DES, ARC4, SEAL +algorithms retained for backwards 3.0, WAKE, WAKE-OFB, DESX (DES-XEX3), RC2, + compatibility and historical SAFER, 3-WAY, GOST, SHARK, CAST-128, Square + value + +Other features include: + + * pseudo random number generators (PRNG): ANSI X9.17 appendix C, RandomPool + * password based key derivation functions: PBKDF1 and PBKDF2 from PKCS #5, + PBKDF from PKCS #12 appendix B + * Shamir's secret sharing scheme and Rabin's information dispersal algorithm + (IDA) + * fast multi-precision integer (bignum) and polynomial operations + * finite field arithmetics, including GF(p) and GF(2^n) + * prime number generation and verification + * useful non-cryptographic algorithms + + DEFLATE (RFC 1951) compression/decompression with gzip (RFC 1952) and + zlib (RFC 1950) format support + + hex, base-32, and base-64 coding/decoding + + 32-bit CRC and Adler32 checksum + * class wrappers for these operating system features (optional): + + high resolution timers on Windows, Unix, and Mac OS + + Berkeley and Windows style sockets + + Windows named pipes + + /dev/random, /dev/urandom, /dev/srandom + + Microsoft's CryptGenRandom on Windows + * A high level interface for most of the above, using a filter/pipeline + metaphor + * benchmarks and validation testing + * x86, x86-64 (x64), MMX, and SSE2 assembly code for the most commonly used + algorithms, with run-time CPU feature detection and code selection + * some versions are available in FIPS 140-2 validated form + +You are welcome to use it for any purpose without paying me, but see +License.txt for the fine print. + +The following compilers are supported for this release. Please visit +http://www.cryptopp.com the most up to date build instructions and porting notes. + + * MSVC 6.0 - 2008 + * GCC 3.3 - 4.3 + * C++Builder 2009 + * Intel C++ Compiler 9 - 11 + * Sun Studio 12 (CC 5.9) + +*** Important Usage Notes *** + +1. If a constructor for A takes a pointer to an object B (except primitive +types such as int and char), then A owns B and will delete B at A's +destruction. If a constructor for A takes a reference to an object B, +then the caller retains ownership of B and should not destroy it until +A no longer needs it. + +2. Crypto++ is thread safe at the class level. This means you can use +Crypto++ safely in a multithreaded application, but you must provide +synchronization when multiple threads access a common Crypto++ object. + +*** MSVC-Specific Information *** + +On Windows, Crypto++ can be compiled into 3 forms: a static library +including all algorithms, a DLL with only FIPS Approved algorithms, and +a static library with only algorithms not in the DLL. +(FIPS Approved means Approved according to the FIPS 140-2 standard.) +The DLL may be used by itself, or it may be used together with the second +form of the static library. MSVC project files are included to build +all three forms, and sample applications using each of the three forms +are also included. + +To compile Crypto++ with MSVC, open the "cryptest.dsw" (for MSVC 6 and MSVC .NET +2003) or "cryptest.sln" (for MSVC .NET 2005) workspace file and build one or +more of the following projects: + +cryptdll - This builds the DLL. Please note that if you wish to use Crypto++ + as a FIPS validated module, you must use a pre-built DLL that has undergone + the FIPS validation process instead of building your own. +dlltest - This builds a sample application that only uses the DLL. +cryptest Non-DLL-Import Configuration - This builds the full static library + along with a full test driver. +cryptest DLL-Import Configuration - This builds a static library containing + only algorithms not in the DLL, along with a full test driver that uses + both the DLL and the static library. + +To use the Crypto++ DLL in your application, #include "dll.h" before including +any other Crypto++ header files, and place the DLL in the same directory as +your .exe file. dll.h includes the line #pragma comment(lib, "cryptopp") +so you don't have to explicitly list the import library in your project +settings. To use a static library form of Crypto++, specify it as +an additional library to link with in your project settings. +In either case you should check the compiler options to +make sure that the library and your application are using the same C++ +run-time libraries and calling conventions. + +*** DLL Memory Management *** + +Because it's possible for the Crypto++ DLL to delete objects allocated +by the calling application, they must use the same C++ memory heap. Three +methods are provided to achieve this. +1. The calling application can tell Crypto++ what heap to use. This method + is required when the calling application uses a non-standard heap. +2. Crypto++ can tell the calling application what heap to use. This method + is required when the calling application uses a statically linked C++ Run + Time Library. (Method 1 does not work in this case because the Crypto++ DLL + is initialized before the calling application's heap is initialized.) +3. Crypto++ can automatically use the heap provided by the calling application's + dynamically linked C++ Run Time Library. The calling application must + make sure that the dynamically linked C++ Run Time Library is initialized + before Crypto++ is loaded. (At this time it is not clear if it is possible + to control the order in which DLLs are initialized on Windows 9x machines, + so it might be best to avoid using this method.) + +When Crypto++ attaches to a new process, it searches all modules loaded +into the process space for exported functions "GetNewAndDeleteForCryptoPP" +and "SetNewAndDeleteFromCryptoPP". If one of these functions is found, +Crypto++ uses methods 1 or 2, respectively, by calling the function. +Otherwise, method 3 is used. + +*** GCC-Specific Information *** + +A makefile is included for you to compile Crypto++ with GCC. Make sure +you are using GNU Make and GNU ld. The make process will produce two files, +libcryptopp.a and cryptest.exe. Run "cryptest.exe v" for the validation +suite. + +*** Documentation and Support *** + +Crypto++ is documented through inline comments in header files, which are +processed through Doxygen to produce an HTML reference manual. You can find +a link to the manual from http://www.cryptopp.com. Also at that site is +the Crypto++ FAQ, which you should browse through before attempting to +use this library, because it will likely answer many of questions that +may come up. + +If you run into any problems, please try the Crypto++ mailing list. +The subscription information and the list archive are available on +http://www.cryptopp.com. You can also email me directly by visiting +http://www.weidai.com, but you will probably get a faster response through +the mailing list. + +*** History *** + +1.0 - First public release. Withdrawn at the request of RSA DSI. + - included Blowfish, BBS, DES, DH, Diamond, DSA, ElGamal, IDEA, + MD5, RC4, RC5, RSA, SHA, WAKE, secret sharing, DEFLATE compression + - had a serious bug in the RSA key generation code. + +1.1 - Removed RSA, RC4, RC5 + - Disabled calls to RSAREF's non-public functions + - Minor bugs fixed + +2.0 - a completely new, faster multiprecision integer class + - added MD5-MAC, HAVAL, 3-WAY, TEA, SAFER, LUC, Rabin, BlumGoldwasser, + elliptic curve algorithms + - added the Lucas strong probable primality test + - ElGamal encryption and signature schemes modified to avoid weaknesses + - Diamond changed to Diamond2 because of key schedule weakness + - fixed bug in WAKE key setup + - SHS class renamed to SHA + - lots of miscellaneous optimizations + +2.1 - added Tiger, HMAC, GOST, RIPE-MD160, LUCELG, LUCDIF, XOR-MAC, + OAEP, PSSR, SHARK + - added precomputation to DH, ElGamal, DSA, and elliptic curve algorithms + - added back RC5 and a new RSA + - optimizations in elliptic curves over GF(p) + - changed Rabin to use OAEP and PSSR + - changed many classes to allow copy constructors to work correctly + - improved exception generation and handling + +2.2 - added SEAL, CAST-128, Square + - fixed bug in HAVAL (padding problem) + - fixed bug in triple-DES (decryption order was reversed) + - fixed bug in RC5 (couldn't handle key length not a multiple of 4) + - changed HMAC to conform to RFC-2104 (which is not compatible + with the original HMAC) + - changed secret sharing and information dispersal to use GF(2^32) + instead of GF(65521) + - removed zero knowledge prover/verifier for graph isomorphism + - removed several utility classes in favor of the C++ standard library + +2.3 - ported to EGCS + - fixed incomplete workaround of min/max conflict in MSVC + +3.0 - placed all names into the "CryptoPP" namespace + - added MD2, RC2, RC6, MARS, RW, DH2, MQV, ECDHC, CBC-CTS + - added abstract base classes PK_SimpleKeyAgreementDomain and + PK_AuthenticatedKeyAgreementDomain + - changed DH and LUCDIF to implement the PK_SimpleKeyAgreementDomain + interface and to perform domain parameter and key validation + - changed interfaces of PK_Signer and PK_Verifier to sign and verify + messages instead of message digests + - changed OAEP to conform to PKCS#1 v2.0 + - changed benchmark code to produce HTML tables as output + - changed PSSR to track IEEE P1363a + - renamed ElGamalSignature to NR and changed it to track IEEE P1363 + - renamed ECKEP to ECMQVC and changed it to track IEEE P1363 + - renamed several other classes for clarity + - removed support for calling RSAREF + - removed option to compile old SHA (SHA-0) + - removed option not to throw exceptions + +3.1 - added ARC4, Rijndael, Twofish, Serpent, CBC-MAC, DMAC + - added interface for querying supported key lengths of symmetric ciphers + and MACs + - added sample code for RSA signature and verification + - changed CBC-CTS to be compatible with RFC 2040 + - updated SEAL to version 3.0 of the cipher specification + - optimized multiprecision squaring and elliptic curves over GF(p) + - fixed bug in MARS key setup + - fixed bug with attaching objects to Deflator + +3.2 - added DES-XEX3, ECDSA, DefaultEncryptorWithMAC + - renamed DES-EDE to DES-EDE2 and TripleDES to DES-EDE3 + - optimized ARC4 + - generalized DSA to allow keys longer than 1024 bits + - fixed bugs in GF2N and ModularArithmetic that can cause calculation errors + - fixed crashing bug in Inflator when given invalid inputs + - fixed endian bug in Serpent + - fixed padding bug in Tiger + +4.0 - added Skipjack, CAST-256, Panama, SHA-2 (SHA-256, SHA-384, and SHA-512), + and XTR-DH + - added a faster variant of Rabin's Information Dispersal Algorithm (IDA) + - added class wrappers for these operating system features: + - high resolution timers on Windows, Unix, and MacOS + - Berkeley and Windows style sockets + - Windows named pipes + - /dev/random and /dev/urandom on Linux and FreeBSD + - Microsoft's CryptGenRandom on Windows + - added support for SEC 1 elliptic curve key format and compressed points + - added support for X.509 public key format (subjectPublicKeyInfo) for + RSA, DSA, and elliptic curve schemes + - added support for DER and OpenPGP signature format for DSA + - added support for ZLIB compressed data format (RFC 1950) + - changed elliptic curve encryption to use ECIES (as defined in SEC 1) + - changed MARS key schedule to reflect the latest specification + - changed BufferedTransformation interface to support multiple channels + and messages + - changed CAST and SHA-1 implementations to use public domain source code + - fixed bug in StringSource + - optmized multi-precision integer code for better performance + +4.1 - added more support for the recommended elliptic curve parameters in SEC 2 + - added Panama MAC, MARC4 + - added IV stealing feature to CTS mode + - added support for PKCS #8 private key format for RSA, DSA, and elliptic + curve schemes + - changed Deflate, MD5, Rijndael, and Twofish to use public domain code + - fixed a bug with flushing compressed streams + - fixed a bug with decompressing stored blocks + - fixed a bug with EC point decompression using non-trinomial basis + - fixed a bug in NetworkSource::GeneralPump() + - fixed a performance issue with EC over GF(p) decryption + - fixed syntax to allow GCC to compile without -fpermissive + - relaxed some restrictions in the license + +4.2 - added support for longer HMAC keys + - added MD4 (which is not secure so use for compatibility purposes only) + - added compatibility fixes/workarounds for STLport 4.5, GCC 3.0.2, + and MSVC 7.0 + - changed MD2 to use public domain code + - fixed a bug with decompressing multiple messages with the same object + - fixed a bug in CBC-MAC with MACing multiple messages with the same object + - fixed a bug in RC5 and RC6 with zero-length keys + - fixed a bug in Adler32 where incorrect checksum may be generated + +5.0 - added ESIGN, DLIES, WAKE-OFB, PBKDF1 and PBKDF2 from PKCS #5 + - added key validation for encryption and signature public/private keys + - renamed StreamCipher interface to SymmetricCipher, which is now implemented + by both stream ciphers and block cipher modes including ECB and CBC + - added keying interfaces to support resetting of keys and IVs without + having to destroy and recreate objects + - changed filter interface to support non-blocking input/output + - changed SocketSource and SocketSink to use overlapped I/O on Microsoft Windows + - grouped related classes inside structs to help templates, for example + AESEncryption and AESDecryption are now AES::Encryption and AES::Decryption + - where possible, typedefs have been added to improve backwards + compatibility when the CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY macro is defined + - changed Serpent, HAVAL and IDEA to use public domain code + - implemented SSE2 optimizations for Integer operations + - fixed a bug in HMAC::TruncatedFinal() + - fixed SKIPJACK byte ordering following NIST clarification dated 5/9/02 + +5.01 - added known answer test for X9.17 RNG in FIPS 140 power-up self test + - submitted to NIST/CSE, but not publicly released + +5.02 - changed EDC test to MAC integrity check using HMAC/SHA1 + - improved performance of integrity check + - added blinding to defend against RSA timing attack + +5.03 - created DLL version of Crypto++ for FIPS 140-2 validation + - fixed vulnerabilities in GetNextIV for CTR and OFB modes + +5.0.4 - Removed DES, SHA-256, SHA-384, SHA-512 from DLL + +5.1 - added PSS padding and changed PSSR to track IEEE P1363a draft standard + - added blinding for RSA and Rabin to defend against timing attacks + on decryption operations + - changed signing and decryption APIs to support the above + - changed WaitObjectContainer to allow waiting for more than 64 + objects at a time on Win32 platforms + - fixed a bug in CBC and ECB modes with processing non-aligned data + - fixed standard conformance bugs in DLIES (DHAES mode) and RW/EMSA2 + signature scheme (these fixes are not backwards compatible) + - fixed a number of compiler warnings, minor bugs, and portability problems + - removed Sapphire + +5.2 - merged in changes for 5.01 - 5.0.4 + - added support for using encoding parameters and key derivation parameters + with public key encryption (implemented by OAEP and DL/ECIES) + - added Camellia, SHACAL-2, Two-Track-MAC, Whirlpool, RIPEMD-320, + RIPEMD-128, RIPEMD-256, Base-32 coding, FIPS variant of CFB mode + - added ThreadUserTimer for timing thread CPU usage + - added option for password-based key derivation functions + to iterate until a mimimum elapsed thread CPU time is reached + - added option (on by default) for DEFLATE compression to detect + uncompressible files and process them more quickly + - improved compatibility and performance on 64-bit platforms, + including Alpha, IA-64, x86-64, PPC64, Sparc64, and MIPS64 + - fixed ONE_AND_ZEROS_PADDING to use 0x80 instead 0x01 as padding. + - fixed encoding/decoding of PKCS #8 privateKeyInfo to properly + handle optional attributes + +5.2.1 - fixed bug in the "dlltest" DLL testing program + - fixed compiling with STLport using VC .NET + - fixed compiling with -fPIC using GCC + - fixed compiling with -msse2 on systems without memalign() + - fixed inability to instantiate PanamaMAC + - fixed problems with inline documentation + +5.2.2 - added SHA-224 + - put SHA-256, SHA-384, SHA-512, RSASSA-PSS into DLL + +5.2.3 - fixed issues with FIPS algorithm test vectors + - put RSASSA-ISO into DLL + +5.3 - ported to MSVC 2005 with support for x86-64 + - added defense against AES timing attacks, and more AES test vectors + - changed StaticAlgorithmName() of Rijndael to "AES", CTR to "CTR" + +5.4 - added Salsa20 + - updated Whirlpool to version 3.0 + - ported to GCC 4.1, Sun C++ 5.8, and Borland C++Builder 2006 + +5.5 - added VMAC and Sosemanuk (with x86-64 and SSE2 assembly) + - improved speed of integer arithmetic, AES, SHA-512, Tiger, Salsa20, + Whirlpool, and PANAMA cipher using assembly (x86-64, MMX, SSE2) + - optimized Camellia and added defense against timing attacks + - updated benchmarks code to show cycles per byte and to time key/IV setup + - started using OpenMP for increased multi-core speed + - enabled GCC optimization flags by default in GNUmakefile + - added blinding and computational error checking for RW signing + - changed RandomPool, X917RNG, GetNextIV, DSA/NR/ECDSA/ECNR to reduce + the risk of reusing random numbers and IVs after virtual machine state + rollback + - changed default FIPS mode RNG from AutoSeededX917RNG to + AutoSeededX917RNG + - fixed PANAMA cipher interface to accept 256-bit key and 256-bit IV + - moved MD2, MD4, MD5, PanamaHash, ARC4, WAKE_CFB into the namespace "Weak" + - removed HAVAL, MD5-MAC, XMAC + +5.5.1 - fixed VMAC validation failure on 32-bit big-endian machines + +5.5.2 - ported x64 assembly language code for AES, Salsa20, Sosemanuk, and Panama + to MSVC 2005 (using MASM since MSVC doesn't support inline assembly on x64) + - fixed Salsa20 initialization crash on non-SSE2 machines + - fixed Whirlpool crash on Pentium 2 machines + - fixed possible branch prediction analysis (BPA) vulnerability in + MontgomeryReduce(), which may affect security of RSA, RW, LUC + - fixed link error with MSVC 2003 when using "debug DLL" form of runtime library + - fixed crash in SSE2_Add on P4 machines when compiled with + MSVC 6.0 SP5 with Processor Pack + - ported to MSVC 2008, GCC 4.2, Sun CC 5.9, Intel C++ Compiler 10.0, + and Borland C++Builder 2007 + +5.6 - added AuthenticatedSymmetricCipher interface class and Filter wrappers + - added CCM, GCM (with SSE2 assembly), EAX, CMAC, XSalsa20, and SEED + - added support for variable length IVs + - improved AES and SHA-256 speed on x86 and x64 + - fixed incorrect VMAC computation on message lengths + that are >64 mod 128 (x86 assembly version is not affected) + - fixed compiler error in vmac.cpp on x86 with GCC -fPIC + - fixed run-time validation error on x86-64 with GCC 4.3.2 -O2 + - fixed HashFilter bug when putMessage=true + - removed WORD64_AVAILABLE; compiler support for 64-bit int is now required + - ported to GCC 4.3, C++Builder 2009, Sun CC 5.10, Intel C++ Compiler 11 + +Written by Wei Dai diff --git a/src-cryptopp/TestVectors/Readme.txt b/src-cryptopp/TestVectors/Readme.txt new file mode 100644 index 0000000..755a046 --- /dev/null +++ b/src-cryptopp/TestVectors/Readme.txt @@ -0,0 +1,72 @@ +Test Data Format + +A test data file is an ASCII text file composed of sections separated by +blank lines. Each section is stand-alone and independent of other +sections that may be in the same file, and contains one or more tests. + +A section is composed of a sequence of fields. Each field is one or more +lines composed of a field name, followed by a colon (":"), followed by a +field body. All but the last line of a field must end with a backslash +("\"). If any line contains a hash mark ("#"), the hash mark and +everything after it on the same line is not considered part of the field +body. + +Each section must contain fields named AlgorithmType, Name, Source, and +Test. The presence and semantics of other fields depend on the algorithm +being tested and the tests to be run. + +Each section may contain more than one test and therefore more than one +field named Test. In that case the order of the fields is significant. A +test should always use the last field with any given name that occurs +before the Test field. + +Data Types + +int - small integer (less than 2^32) in decimal representation +string - human readable string +encoded string - can be one of the following + - quoted string: "message" means "message" without the quotes + or terminating '\0' + - hex encoded string: 0x74657374 or 74657374 means "test" + - repeated string: r100 "message" to repeat "message" 100 times, or + r256 0x0011 to repeat 0x0011 256 times + +Field Types + +AlgorithmType - string, for example "Signature", "AsymmetricCipher", +"SymmetricCipher", "MAC", "MessageDigest", or "KeyFactory" +Name - string, an algorithm name from SCAN +Test - string, identifies the test to run +Source - string, text explaining where the test data came from +Comment - string, other comments about the test data +KeyFormat - string, specifies the key format. "Component" here means +each component of the key or key pair is specified separately as a name, +value pair, with the names depending on the algorithm being tested. +Otherwise the value names "Key", or "PublicKey" and "PrivateKey" are +used. +Key - encoded string +PublicKey - encoded string +PrivateKey - encoded string +Message - encoded string, message to be signed or verified +Signature - encoded string, signature to be verified or compared +with +Plaintext - encoded string +Ciphertext - encoded string +Digest - encoded string +TruncatedSize - int, size of truncated digest in bytes +Seek - int, seek location for random access ciphers +(more to come here) + +Possible Tests + +KeyPairValidAndConsistent - public and private keys are both valid and +consistent with each other +PublicKeyInvalid - public key validation should not pass +PrivateKeyInvalid - private key validation should not pass +Verify - signature/digest/MAC verification should pass +VerifyTruncated - truncated digest/MAC verification should pass +NotVerify - signature/digest/MAC verification should not pass +DeterministicSign - sign message using given seed, and the resulting +signature should be equal to the given signature +DecryptMatch - ciphertext decrypts to plaintext +(more to come here) diff --git a/src-cryptopp/TestVectors/aes.txt b/src-cryptopp/TestVectors/aes.txt new file mode 100644 index 0000000..0012629 --- /dev/null +++ b/src-cryptopp/TestVectors/aes.txt @@ -0,0 +1,189 @@ +AlgorithmType: SymmetricCipher +Name: AES/ECB +Source: NIST Special Publication 800-38A +Plaintext: 6bc1bee22e409f96e93d7e117393172a ae2d8a571e03ac9c9eb76fac45af8e51 30c81c46a35ce411e5fbc1191a0a52ef f69f2445df4f9b17ad2b417be66c3710 +Comment: F.1.1 ECB-AES128.Encrypt +Key: 2b7e151628aed2a6abf7158809cf4f3c +Ciphertext: 3ad77bb40d7a3660a89ecaf32466ef97 f5d3d58503b9699de785895a96fdbaaf 43b1cd7f598ece23881b00e3ed030688 7b0c785e27e8ad3f8223207104725dd4 +Test: Encrypt +Comment: F.1.3 ECB-AES192.Encrypt +Key: 8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b +Ciphertext: bd334f1d6e45f25ff712a214571fa5cc 974104846d0ad3ad7734ecb3ecee4eef ef7afd2270e2e60adce0ba2face6444e 9a4b41ba738d6c72fb16691603c18e0e +Test: Encrypt +Comment: F.1.5 ECB-AES256.Encrypt +Key: 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4 +Ciphertext: f3eed1bdb5d2a03c064b5a7e3db181f8 591ccb10d410ed26dc5ba74a31362870 b6ed21b99ca6f4f9f153e7b1beafed1d 23304b7a39f9f3ff067d8d8f9e24ecc7 +Test: Encrypt + +AlgorithmType: SymmetricCipher +Name: AES/CBC +Source: NIST Special Publication 800-38A +IV: 000102030405060708090a0b0c0d0e0f +Plaintext: 6bc1bee22e409f96e93d7e117393172a ae2d8a571e03ac9c9eb76fac45af8e51 30c81c46a35ce411e5fbc1191a0a52ef f69f2445df4f9b17ad2b417be66c3710 +Comment: F.2.1 CBC-AES128.Encrypt +Key: 2b7e151628aed2a6abf7158809cf4f3c +Ciphertext: 7649abac8119b246cee98e9b12e9197d 5086cb9b507219ee95db113a917678b2 73bed6b8e3c1743b7116e69e22229516 3ff1caa1681fac09120eca307586e1a7 +Test: Encrypt +Comment: F.2.3 CBC-AES192.Encrypt +Key: 8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b +Ciphertext: 4f021db243bc633d7178183a9fa071e8 b4d9ada9ad7dedf4e5e738763f69145a 571b242012fb7ae07fa9baac3df102e0 08b0e27988598881d920a9e64f5615cd +Test: Encrypt +Comment: F.2.5 CBC-AES256.Encrypt +Key: 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4 +Ciphertext: f58c4c04d6e5f1ba779eabfb5f7bfbd6 9cfc4e967edb808d679f777bc6702c7d 39f23369a9d9bacfa530e26304231461 b2eb05e2c39be9fcda6c19078c6a9d1b +Test: Encrypt + +AlgorithmType: SymmetricCipher +Name: AES/CBC +Source: RFC 3602 +Comment: Case 1: Encrypting 16 bytes (1 block) using AES-CBC with 128-bit key +Key : 0x06a9214036b8a15b512e03d534120006 +IV : 0x3dafba429d9eb430b422da802c9fac41 +Plaintext : "Single block msg" +Ciphertext: 0xe353779c1079aeb82708942dbe77181a +Test: Encrypt +Comment: Case 2: Encrypting 32 bytes (2 blocks) using AES-CBC with 128-bit key +Key : 0xc286696d887c9aa0611bbb3e2025a45a +IV : 0x562e17996d093d28ddb3ba695a2e6f58 +Plaintext : 0x000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f +Ciphertext: 0xd296cd94c2cccf8a3a863028b5e1dc0a 7586602d253cfff91b8266bea6d61ab1 +Test: Encrypt +Comment: Case 3: Encrypting 48 bytes (3 blocks) using AES-CBC with 128-bit key +Key : 0x6c3ea0477630ce21a2ce334aa746c2cd +IV : 0xc782dc4c098c66cbd9cd27d825682c81 +Plaintext : "This is a 48-byte message (exactly 3 AES blocks)" +Ciphertext: 0xd0a02b3836451753d493665d33f0e886 2dea54cdb293abc7506939276772f8d5 021c19216bad525c8579695d83ba2684 +Test: Encrypt +Comment: Case 4: Encrypting 64 bytes (4 blocks) using AES-CBC with 128-bit key +Key : 0x56e47a38c5598974bc46903dba290349 +IV : 0x8ce82eefbea0da3c44699ed7db51b7d9 +Plaintext : 0xa0a1a2a3a4a5a6a7a8a9aaabacadaeaf b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf d0d1d2d3d4d5d6d7d8d9dadbdcdddedf +Ciphertext: 0xc30e32ffedc0774e6aff6af0869f71aa 0f3af07a9a31a9c684db207eb0ef8e4e 35907aa632c3ffdf868bb7b29d3d46ad 83ce9f9a102ee99d49a53e87f4c3da55 +Test: Encrypt + +AlgorithmType: SymmetricCipher +Name: AES/CFB +Source: NIST Special Publication 800-38A +IV: 000102030405060708090a0b0c0d0e0f +Plaintext: 6bc1bee22e409f96e93d7e117393172aae2d8 +FeedbackSize: 1 +Comment: F.3.7 CFB8-AES128.Encrypt +Key: 2b7e151628aed2a6abf7158809cf4f3c +Ciphertext: 3b79424c9c0dd436bace9e0ed4586a4f32b9 +Test: Encrypt +Comment: F.3.9 CFB8-AES192.Encrypt +Key: 8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b +Ciphertext: cda2521ef0a905ca44cd057cbf0d47a0678a +Test: Encrypt +Comment: F.3.11 CFB8-AES256.Encrypt +Key: 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4 +Ciphertext: dc1f1a8520a64db55fcc8ac554844e889700 +Test: Encrypt +Plaintext: 6bc1bee22e409f96e93d7e117393172a ae2d8a571e03ac9c9eb76fac45af8e51 30c81c46a35ce411e5fbc1191a0a52ef f69f2445df4f9b17ad2b417be66c3710 +FeedbackSize: 16 +Comment: F.3.13 CFB128-AES128.Encrypt +Key: 2b7e151628aed2a6abf7158809cf4f3c +Ciphertext: 3b3fd92eb72dad20333449f8e83cfb4a c8a64537a0b3a93fcde3cdad9f1ce58b 26751f67a3cbb140b1808cf187a4f4df c04b05357c5d1c0eeac4c66f9ff7f2e6 +Test: Encrypt +Comment: F.3.15 CFB128-AES192.Encrypt +Key: 8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b +Ciphertext: cdc80d6fddf18cab34c25909c99a4174 67ce7f7f81173621961a2b70171d3d7a 2e1e8a1dd59b88b1c8e60fed1efac4c9 c05f9f9ca9834fa042ae8fba584b09ff +Test: Encrypt +Comment: F.3.17 CFB128-AES256.Encrypt +Key: 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4 +Ciphertext: dc7e84bfda79164b7ecd8486985d3860 39ffed143b28b1c832113c6331e5407b df10132415e54b92a13ed0a8267ae2f9 75a385741ab9cef82031623d55b1e471 +Test: Encrypt + +AlgorithmType: SymmetricCipher +Name: AES/OFB +Source: NIST Special Publication 800-38A +IV: 000102030405060708090a0b0c0d0e0f +Plaintext: 6bc1bee22e409f96e93d7e117393172a ae2d8a571e03ac9c9eb76fac45af8e51 30c81c46a35ce411e5fbc1191a0a52ef f69f2445df4f9b17ad2b417be66c3710 +Comment: F.4.1 OFB-AES128.Encrypt +Key: 2b7e151628aed2a6abf7158809cf4f3c +Ciphertext: 3b3fd92eb72dad20333449f8e83cfb4a 7789508d16918f03f53c52dac54ed825 9740051e9c5fecf64344f7a82260edcc 304c6528f659c77866a510d9c1d6ae5e +Test: Encrypt +Comment: F.4.3 OFB-AES192.Encrypt +Key: 8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b +Ciphertext: cdc80d6fddf18cab34c25909c99a4174 fcc28b8d4c63837c09e81700c1100401 8d9a9aeac0f6596f559c6d4daf59a5f2 6d9f200857ca6c3e9cac524bd9acc92a +Test: Encrypt +Comment: F.4.5 OFB-AES256.Encrypt +Key: 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4 +Ciphertext: dc7e84bfda79164b7ecd8486985d3860 4febdc6740d20b3ac88f6ad82a4fb08d 71ab47a086e86eedf39d1c5bba97c408 0126141d67f37be8538f5a8be740e484 +Test: Encrypt + +AlgorithmType: SymmetricCipher +Name: AES/CTR +Source: NIST Special Publication 800-38A +IV: f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff +Plaintext: 6bc1bee22e409f96e93d7e117393172a ae2d8a571e03ac9c9eb76fac45af8e51 30c81c46a35ce411e5fbc1191a0a52ef f69f2445df4f9b17ad2b417be66c3710 +Comment: F.5.1 CTR-AES128.Encrypt +Key: 2b7e151628aed2a6abf7158809cf4f3c +Ciphertext: 874d6191b620e3261bef6864990db6ce 9806f66b7970fdff8617187bb9fffdff 5ae4df3edbd5d35e5b4f09020db03eab 1e031dda2fbe03d1792170a0f3009cee +Test: Encrypt +Comment: F.5.3 CTR-AES192.Encrypt +Key: 8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b +Ciphertext: 1abc932417521ca24f2b0459fe7e6e0b 090339ec0aa6faefd5ccc2c6f4ce8e94 1e36b26bd1ebc670d1bd1d665620abf7 4f78a7f6d29809585a97daec58c6b050 +Test: Encrypt +Comment: F.5.5 CTR-AES256.Encrypt +Key: 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4 +Ciphertext: 601ec313775789a5b7a7f504bbf3d228 f443e3ca4d62b59aca84e990cacaf5c5 2b0930daa23de94ce87017ba2d84988d dfc9c58db67aada613c2dd08457941a6 +Test: Encrypt + +AlgorithmType: SymmetricCipher +Name: AES/CTR +Source: RFC 3686 +#Test Vector #1: Encrypting 16 octets using AES-CTR with 128-bit key +Key : AE 68 52 F8 12 10 67 CC 4B F7 A5 76 55 77 F3 9E +Plaintext : 53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67 +IV: 00 00 00 30 00 00 00 00 00 00 00 00 00 00 00 01 +Ciphertext : E4 09 5D 4F B7 A7 B3 79 2D 61 75 A3 26 13 11 B8 +Test: Encrypt +#Test Vector #2: Encrypting 32 octets using AES-CTR with 128-bit key +Key : 7E 24 06 78 17 FA E0 D7 43 D6 CE 1F 32 53 91 63 +Plaintext : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F +IV: 00 6C B6 DB C0 54 3B 59 DA 48 D9 0B 00 00 00 01 +Ciphertext : 51 04 A1 06 16 8A 72 D9 79 0D 41 EE 8E DA D3 88 EB 2E 1E FC 46 DA 57 C8 FC E6 30 DF 91 41 BE 28 +Test: Encrypt +#Test Vector #3: Encrypting 36 octets using AES-CTR with 128-bit key +Key : 76 91 BE 03 5E 50 20 A8 AC 6E 61 85 29 F9 A0 DC +Plaintext : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 +IV: 00 E0 01 7B 27 77 7F 3F 4A 17 86 F0 00 00 00 01 +Ciphertext : C1 CF 48 A8 9F 2F FD D9 CF 46 52 E9 EF DB 72 D7 45 40 A4 2B DE 6D 78 36 D5 9A 5C EA AE F3 10 53 25 B2 07 2F +Test: Encrypt +#Test Vector #4: Encrypting 16 octets using AES-CTR with 192-bit key +Key : 16 AF 5B 14 5F C9 F5 79 C1 75 F9 3E 3B FB 0E ED 86 3D 06 CC FD B7 85 15 +Plaintext : 53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67 +IV: 00 00 00 48 36 73 3C 14 7D 6D 93 CB 00 00 00 01 +Ciphertext : 4B 55 38 4F E2 59 C9 C8 4E 79 35 A0 03 CB E9 28 +Test: Encrypt +#Test Vector #5: Encrypting 32 octets using AES-CTR with 192-bit key +Key : 7C 5C B2 40 1B 3D C3 3C 19 E7 34 08 19 E0 F6 9C 67 8C 3D B8 E6 F6 A9 1A +Plaintext : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F +IV: 00 96 B0 3B 02 0C 6E AD C2 CB 50 0D 00 00 00 01 +Ciphertext : 45 32 43 FC 60 9B 23 32 7E DF AA FA 71 31 CD 9F 84 90 70 1C 5A D4 A7 9C FC 1F E0 FF 42 F4 FB 00 +Test: Encrypt +#Test Vector #6: Encrypting 36 octets using AES-CTR with 192-bit key +Key : 02 BF 39 1E E8 EC B1 59 B9 59 61 7B 09 65 27 9B F5 9B 60 A7 86 D3 E0 FE +Plaintext : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 +IV: 00 07 BD FD 5C BD 60 27 8D CC 09 12 00 00 00 01 +Ciphertext : 96 89 3F C5 5E 5C 72 2F 54 0B 7D D1 DD F7 E7 58 D2 88 BC 95 C6 91 65 88 45 36 C8 11 66 2F 21 88 AB EE 09 35 +Test: Encrypt +#Test Vector #7: Encrypting 16 octets using AES-CTR with 256-bit key +Key : 77 6B EF F2 85 1D B0 6F 4C 8A 05 42 C8 69 6F 6C 6A 81 AF 1E EC 96 B4 D3 7F C1 D6 89 E6 C1 C1 04 +Plaintext : 53 69 6E 67 6C 65 20 62 6C 6F 63 6B 20 6D 73 67 +IV: 00 00 00 60 DB 56 72 C9 7A A8 F0 B2 00 00 00 01 +Ciphertext : 14 5A D0 1D BF 82 4E C7 56 08 63 DC 71 E3 E0 C0 +Test: Encrypt +#Test Vector #8: Encrypting 32 octets using AES-CTR with 256-bit key +Key : F6 D6 6D 6B D5 2D 59 BB 07 96 36 58 79 EF F8 86 C6 6D D5 1A 5B 6A 99 74 4B 50 59 0C 87 A2 38 84 +Plaintext : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F +IV: 00 FA AC 24 C1 58 5E F1 5A 43 D8 75 00 00 00 01 +Ciphertext : F0 5E 23 1B 38 94 61 2C 49 EE 00 0B 80 4E B2 A9 B8 30 6B 50 8F 83 9D 6A 55 30 83 1D 93 44 AF 1C +Test: Encrypt +#Test Vector #9: Encrypting 36 octets using AES-CTR with 256-bit key +Key : FF 7A 61 7C E6 91 48 E4 F1 72 6E 2F 43 58 1D E2 AA 62 D9 F8 05 53 2E DF F1 EE D6 87 FB 54 15 3D +Plaintext : 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 +IV: 00 1C C5 B7 51 A5 1D 70 A1 C1 11 48 00 00 00 01 +Ciphertext : EB 6C 52 82 1D 0B BB F7 CE 75 94 46 2A CA 4F AA B4 07 DF 86 65 69 FD 07 F4 8C C0 B5 83 D6 07 1F 1E C0 E6 B8 +Test: Encrypt diff --git a/src-cryptopp/TestVectors/all.txt b/src-cryptopp/TestVectors/all.txt new file mode 100644 index 0000000..3f06e78 --- /dev/null +++ b/src-cryptopp/TestVectors/all.txt @@ -0,0 +1,29 @@ +AlgorithmType: FileList +Name: all.txt collection +Test: TestVectors/tea.txt +Test: TestVectors/camellia.txt +Test: TestVectors/shacal2.txt +Test: TestVectors/ttmac.txt +Test: TestVectors/whrlpool.txt +Test: TestVectors/dlies.txt +Test: TestVectors/dsa.txt +Test: TestVectors/dsa_1363.txt +Test: TestVectors/esign.txt +Test: TestVectors/hmac.txt +Test: TestVectors/nr.txt +Test: TestVectors/rsa_oaep.txt +Test: TestVectors/rsa_pkcs1_1_5.txt +Test: TestVectors/rsa_pss.txt +Test: TestVectors/rw.txt +Test: TestVectors/seal.txt +Test: TestVectors/sha.txt +Test: TestVectors/panama.txt +Test: TestVectors/aes.txt +Test: TestVectors/salsa.txt +Test: TestVectors/vmac.txt +Test: TestVectors/sosemanuk.txt +Test: TestVectors/ccm.txt +Test: TestVectors/gcm.txt +Test: TestVectors/cmac.txt +Test: TestVectors/eax.txt +Test: TestVectors/mars.txt diff --git a/src-cryptopp/TestVectors/camellia.txt b/src-cryptopp/TestVectors/camellia.txt new file mode 100644 index 0000000..f88d05b --- /dev/null +++ b/src-cryptopp/TestVectors/camellia.txt @@ -0,0 +1,8646 @@ +AlgorithmType: SymmetricCipher +Name: Camellia/ECB +Source: NESSIE submission +Comment: Tests with 128-bit keys +Comment: Set 1, vector 0 +Key: 80000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 6C227F749319A3AA7DA235A9BBA05A2C +Test: Encrypt +Comment: Set 1, vector 1 +Key: 40000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F04D51E45E70FB6DEE0D16A204FBBA16 +Test: Encrypt +Comment: Set 1, vector 2 +Key: 20000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: ED44242E619F8C32EAA2D3641DA47EA4 +Test: Encrypt +Comment: Set 1, vector 3 +Key: 10000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: AC640BBBF84CD3B8E8258BF66C210AE2 +Test: Encrypt +Comment: Set 1, vector 4 +Key: 08000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 8A42BDA76C84B8960B23530100AFB748 +Test: Encrypt +Comment: Set 1, vector 5 +Key: 04000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 1D20D15F3EE21EE6051803ADF83E31D7 +Test: Encrypt +Comment: Set 1, vector 6 +Key: 02000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 6896B2FB85D26A243BB5697F6A764307 +Test: Encrypt +Comment: Set 1, vector 7 +Key: 01000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 43A865A61E1117008372932EA9CE8BB2 +Test: Encrypt +Comment: Set 1, vector 8 +Key: 00800000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: CB5ECC200DDE8E9076A8AEA2250F49E4 +Test: Encrypt +Comment: Set 1, vector 9 +Key: 00400000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0B2A489718DC0B0E11F11C1D3913F4A8 +Test: Encrypt +Comment: Set 1, vector 10 +Key: 00200000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 1D28A0A70B3C72ADC5B77487AD442873 +Test: Encrypt +Comment: Set 1, vector 11 +Key: 00100000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 26D344959095765A3DD6986B656F353D +Test: Encrypt +Comment: Set 1, vector 12 +Key: 00080000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 048248D32A74DB80DAF5642417F7832A +Test: Encrypt +Comment: Set 1, vector 13 +Key: 00040000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 44D400F8752F16B20DB95A959917B650 +Test: Encrypt +Comment: Set 1, vector 14 +Key: 00020000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E885DD9B2794459B2133BC84B59C2DED +Test: Encrypt +Comment: Set 1, vector 15 +Key: 00010000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 89D6E4182FD0DD7E4038710F597DD242 +Test: Encrypt +Comment: Set 1, vector 16 +Key: 00008000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7FE5BA5FF1D0EB81132A3DA0CD8E829D +Test: Encrypt +Comment: Set 1, vector 17 +Key: 00004000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 470FEDAAA6FFFCBC48AF8B3859B1E45F +Test: Encrypt +Comment: Set 1, vector 18 +Key: 00002000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B6FA2D9F41110E6914890AF888C36091 +Test: Encrypt +Comment: Set 1, vector 19 +Key: 00001000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 46D2C0FD0C3A4D2B5CA6BA5E14382DCA +Test: Encrypt +Comment: Set 1, vector 20 +Key: 00000800000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 730D700DCC5AB632DD9D92C6D1C18E5A +Test: Encrypt +Comment: Set 1, vector 21 +Key: 00000400000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 067D56D80AF5D2F24D84F518B8FC7920 +Test: Encrypt +Comment: Set 1, vector 22 +Key: 00000200000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 027F6EE9F54534E4C21F9263B68BAEA0 +Test: Encrypt +Comment: Set 1, vector 23 +Key: 00000100000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: D115CB2324E8FDA3576DEE57E49CC315 +Test: Encrypt +Comment: Set 1, vector 24 +Key: 00000080000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0976DB57B27E4136743E58BCECFBC056 +Test: Encrypt +Comment: Set 1, vector 25 +Key: 00000040000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0C889DF89972EB42DB2BD2AAC335CCC8 +Test: Encrypt +Comment: Set 1, vector 26 +Key: 00000020000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: CB6B80177047A3B2AC290A41B94174EF +Test: Encrypt +Comment: Set 1, vector 27 +Key: 00000010000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F816631F8FBC54ECDC1AB5323FF8424E +Test: Encrypt +Comment: Set 1, vector 28 +Key: 00000008000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 40CB64DF57D2A6BBCBD82DFCC749707D +Test: Encrypt +Comment: Set 1, vector 29 +Key: 00000004000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 885BD3C2DD560765B11F5A2D238E9F9A +Test: Encrypt +Comment: Set 1, vector 30 +Key: 00000002000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 877AAEF064555DE89C99B7C5A1326C62 +Test: Encrypt +Comment: Set 1, vector 31 +Key: 00000001000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: AA4FBBE7A02020F5D81030E0EF7A460D +Test: Encrypt +Comment: Set 1, vector 32 +Key: 00000000800000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: AA2759BC215E49F26008206F6F65B7AC +Test: Encrypt +Comment: Set 1, vector 33 +Key: 00000000400000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 419A8069C3D531475FF7F29AE049D57C +Test: Encrypt +Comment: Set 1, vector 34 +Key: 00000000200000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 455588067DB9088130C861F5BE9E15BF +Test: Encrypt +Comment: Set 1, vector 35 +Key: 00000000100000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: FDD6967ADA65ED3E20718C451AE5AE34 +Test: Encrypt +Comment: Set 1, vector 36 +Key: 00000000080000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 1C74228D2A82248CD29800B64BEFF97A +Test: Encrypt +Comment: Set 1, vector 37 +Key: 00000000040000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 4B88B7FFB32B05840BE7B497377AFDAA +Test: Encrypt +Comment: Set 1, vector 38 +Key: 00000000020000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 4D4EC4C728524DA2F366FC272AB2666A +Test: Encrypt +Comment: Set 1, vector 39 +Key: 00000000010000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 4FA8A27ED16BF36FA296D8AB2B423C77 +Test: Encrypt +Comment: Set 1, vector 40 +Key: 00000000008000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 943B9D570D371A3D823B680BBDA9477D +Test: Encrypt +Comment: Set 1, vector 41 +Key: 00000000004000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: DCC390F5E1CAADBE061D02929473D084 +Test: Encrypt +Comment: Set 1, vector 42 +Key: 00000000002000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 9655F00C4A5C40DF401A3FF806575834 +Test: Encrypt +Comment: Set 1, vector 43 +Key: 00000000001000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: FCC9F6B36DE6DD6AA578AD0B59DF5996 +Test: Encrypt +Comment: Set 1, vector 44 +Key: 00000000000800000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F573FF52ACAA16609E5B3C3C7353DA75 +Test: Encrypt +Comment: Set 1, vector 45 +Key: 00000000000400000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 203EF49006A7FC856FF7A7A3B953D999 +Test: Encrypt +Comment: Set 1, vector 46 +Key: 00000000000200000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 16659E823D942E99C83926C4055D896D +Test: Encrypt +Comment: Set 1, vector 47 +Key: 00000000000100000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 139D5DB9EF0119F4E5D11256C5ECB8B0 +Test: Encrypt +Comment: Set 1, vector 48 +Key: 00000000000080000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 63FB244962CCE915425EF1B31DE6AAE2 +Test: Encrypt +Comment: Set 1, vector 49 +Key: 00000000000040000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 6F771C2DC848A106E907A990DABA0272 +Test: Encrypt +Comment: Set 1, vector 50 +Key: 00000000000020000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: CFA1F114CF0D9C7DAD301B833962ABF2 +Test: Encrypt +Comment: Set 1, vector 51 +Key: 00000000000010000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 58A3BE61DA53D0AA8F33DE95E6F38A3F +Test: Encrypt +Comment: Set 1, vector 52 +Key: 00000000000008000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 2FE96FCB3D845B568AE804B217F3498F +Test: Encrypt +Comment: Set 1, vector 53 +Key: 00000000000004000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: FD74EB6621127D58FA44BA3E6EE7835D +Test: Encrypt +Comment: Set 1, vector 54 +Key: 00000000000002000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 834C0C5D8D88EE63C989AA1E66F4E18C +Test: Encrypt +Comment: Set 1, vector 55 +Key: 00000000000001000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: FEF8E0097B9EB5CE6DE710F5742F7E4F +Test: Encrypt +Comment: Set 1, vector 56 +Key: 00000000000000800000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 75FCC55F284311B81D967618C2D35700 +Test: Encrypt +Comment: Set 1, vector 57 +Key: 00000000000000400000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 91AE4E35623A7F10383BF7448F1F74AD +Test: Encrypt +Comment: Set 1, vector 58 +Key: 00000000000000200000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 8928B2B6967BA1B4230AA1EBA49D1A08 +Test: Encrypt +Comment: Set 1, vector 59 +Key: 00000000000000100000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 707EA08174ED5C0AD0A74363B403F02D +Test: Encrypt +Comment: Set 1, vector 60 +Key: 00000000000000080000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7C0C13410DDE30C0AD3565FFAA33E8AD +Test: Encrypt +Comment: Set 1, vector 61 +Key: 00000000000000040000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 56DA72C545C490A749C66BCC5D90AACD +Test: Encrypt +Comment: Set 1, vector 62 +Key: 00000000000000020000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 2CC0CF6E2AAA7916AF636B1546BA1179 +Test: Encrypt +Comment: Set 1, vector 63 +Key: 00000000000000010000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: A19FE617883D409B1F78882E0D5EF39C +Test: Encrypt +Comment: Set 1, vector 64 +Key: 00000000000000008000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 2B8586BBB979CFFAC5A76C25D77C1E2C +Test: Encrypt +Comment: Set 1, vector 65 +Key: 00000000000000004000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 5A08C9B5A2940E3ACD1086867E3E4733 +Test: Encrypt +Comment: Set 1, vector 66 +Key: 00000000000000002000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7443F1072833BFC8AA38CBF6963CF880 +Test: Encrypt +Comment: Set 1, vector 67 +Key: 00000000000000001000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 6809A1F2D2B5367D5E8442E7972BD1D4 +Test: Encrypt +Comment: Set 1, vector 68 +Key: 00000000000000000800000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: A61D4FE41D5DBB7A6BCE5984502CD767 +Test: Encrypt +Comment: Set 1, vector 69 +Key: 00000000000000000400000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 30D86F43B81F4D2098A4D43AB2637549 +Test: Encrypt +Comment: Set 1, vector 70 +Key: 00000000000000000200000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 5B16E9033FA40BF141D3EE73FF7E2564 +Test: Encrypt +Comment: Set 1, vector 71 +Key: 00000000000000000100000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 15574EF70C880682DBFBD93FAE8023F6 +Test: Encrypt +Comment: Set 1, vector 72 +Key: 00000000000000000080000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0D8D220DB69B15FFE2001B3F42E910EA +Test: Encrypt +Comment: Set 1, vector 73 +Key: 00000000000000000040000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 030AB24DA9E4ADD4E350E692077A948C +Test: Encrypt +Comment: Set 1, vector 74 +Key: 00000000000000000020000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7F6509A9FD8525126BFB69AFE8624A96 +Test: Encrypt +Comment: Set 1, vector 75 +Key: 00000000000000000010000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 9600EB0B7E38A5ABEBBDADD3DFC70298 +Test: Encrypt +Comment: Set 1, vector 76 +Key: 00000000000000000008000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3CF0F71B4687AAABEB9FA8CDE00B17D7 +Test: Encrypt +Comment: Set 1, vector 77 +Key: 00000000000000000004000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 8B1C549A655C0041D866B7875A2736CB +Test: Encrypt +Comment: Set 1, vector 78 +Key: 00000000000000000002000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 8F507233FBC9E1DBF716FB4C828DBF06 +Test: Encrypt +Comment: Set 1, vector 79 +Key: 00000000000000000001000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 14A45A121DC8996020C29A040FE8E52D +Test: Encrypt +Comment: Set 1, vector 80 +Key: 00000000000000000000800000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 32390FB6FC15BB4B37D1CD8817BAEB09 +Test: Encrypt +Comment: Set 1, vector 81 +Key: 00000000000000000000400000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 9E61986F3F4C31132D436CCFCF751043 +Test: Encrypt +Comment: Set 1, vector 82 +Key: 00000000000000000000200000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 24E63FAD370974C60330F7C3071938F1 +Test: Encrypt +Comment: Set 1, vector 83 +Key: 00000000000000000000100000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3CE71D4E9F2F7EF9A6F9F2548C5489CC +Test: Encrypt +Comment: Set 1, vector 84 +Key: 00000000000000000000080000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E42436B8E076A00600DFD67B8C427DB1 +Test: Encrypt +Comment: Set 1, vector 85 +Key: 00000000000000000000040000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 5C2577FA8104DCC58ACE852B4D11FE24 +Test: Encrypt +Comment: Set 1, vector 86 +Key: 00000000000000000000020000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 12FC9DD7132B3BB346C53FD193531638 +Test: Encrypt +Comment: Set 1, vector 87 +Key: 00000000000000000000010000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 5D91F775E26599F26B21F9FB1F67DA38 +Test: Encrypt +Comment: Set 1, vector 88 +Key: 00000000000000000000008000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: D4B3683AA62D2EF0331A960A0BF01A29 +Test: Encrypt +Comment: Set 1, vector 89 +Key: 00000000000000000000004000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: EE32582D35DDF3A82142ED18FEE38014 +Test: Encrypt +Comment: Set 1, vector 90 +Key: 00000000000000000000002000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 148632AE69514D5776DA4AF38E1AE4FD +Test: Encrypt +Comment: Set 1, vector 91 +Key: 00000000000000000000001000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 30A3EE1AA1CA17B128DAAF06AF9025BD +Test: Encrypt +Comment: Set 1, vector 92 +Key: 00000000000000000000000800000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 88D82D9E508CBFB392E47E524BB33019 +Test: Encrypt +Comment: Set 1, vector 93 +Key: 00000000000000000000000400000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0C20870A9FC751F6E41F92305B7C4D92 +Test: Encrypt +Comment: Set 1, vector 94 +Key: 00000000000000000000000200000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 6A4EDE5FD13F3676C1BCF8B73AB273CB +Test: Encrypt +Comment: Set 1, vector 95 +Key: 00000000000000000000000100000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 5A62CE50EA837CA4FD0F7304D1572D22 +Test: Encrypt +Comment: Set 1, vector 96 +Key: 00000000000000000000000080000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 84DB8599B48ED4F39E872F13F7FCDF0B +Test: Encrypt +Comment: Set 1, vector 97 +Key: 00000000000000000000000040000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: CDD25F8276411E892035C9703C7588EE +Test: Encrypt +Comment: Set 1, vector 98 +Key: 00000000000000000000000020000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 73BCFB16436B5C52CD4BC9629F75C5C8 +Test: Encrypt +Comment: Set 1, vector 99 +Key: 00000000000000000000000010000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 03752D935029B09699C29CA5C6E79553 +Test: Encrypt +Comment: Set 1, vector 100 +Key: 00000000000000000000000008000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: EF439A1B86698409E91D992BDB3F54E5 +Test: Encrypt +Comment: Set 1, vector 101 +Key: 00000000000000000000000004000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 2A34BDE7EC74221BFF58B251E54F089F +Test: Encrypt +Comment: Set 1, vector 102 +Key: 00000000000000000000000002000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 35FBB78716B78FB57F96BC8A5D869B72 +Test: Encrypt +Comment: Set 1, vector 103 +Key: 00000000000000000000000001000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: AC3A7363DFB6C3F06CCCA1A46F44A5F8 +Test: Encrypt +Comment: Set 1, vector 104 +Key: 00000000000000000000000000800000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 4895E1B7E54CA168CE42E3994D564B62 +Test: Encrypt +Comment: Set 1, vector 105 +Key: 00000000000000000000000000400000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E98956EFC457FE8AA103DB303A3B1DF1 +Test: Encrypt +Comment: Set 1, vector 106 +Key: 00000000000000000000000000200000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 276646992D6E752A649183DB05073422 +Test: Encrypt +Comment: Set 1, vector 107 +Key: 00000000000000000000000000100000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 82F36DE401E21D01A476A163A92F4B16 +Test: Encrypt +Comment: Set 1, vector 108 +Key: 00000000000000000000000000080000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E54DD90800B92153C314F8B1590B17E5 +Test: Encrypt +Comment: Set 1, vector 109 +Key: 00000000000000000000000000040000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F4A146DFB33405EC6B8F37AEB10F5198 +Test: Encrypt +Comment: Set 1, vector 110 +Key: 00000000000000000000000000020000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: C332ADBC2D44FA1A1A4F7C8EAE2CED29 +Test: Encrypt +Comment: Set 1, vector 111 +Key: 00000000000000000000000000010000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 21AA542624DA9F2363404CE42BC2BAEF +Test: Encrypt +Comment: Set 1, vector 112 +Key: 00000000000000000000000000008000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E101DBEF627038AE819441D133AEE068 +Test: Encrypt +Comment: Set 1, vector 113 +Key: 00000000000000000000000000004000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7A9B635E6AA5D273DE697747FE6BB08E +Test: Encrypt +Comment: Set 1, vector 114 +Key: 00000000000000000000000000002000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0541AA347D36F03D9177FC91398874DB +Test: Encrypt +Comment: Set 1, vector 115 +Key: 00000000000000000000000000001000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: BE27D6FE099AB98BF07A74A1ABF5C945 +Test: Encrypt +Comment: Set 1, vector 116 +Key: 00000000000000000000000000000800 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 472ACD81A6626822E220F431C4491704 +Test: Encrypt +Comment: Set 1, vector 117 +Key: 00000000000000000000000000000400 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 2D5152F19E29AD7D5823CDCA188E0CD8 +Test: Encrypt +Comment: Set 1, vector 118 +Key: 00000000000000000000000000000200 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 875C90B3669DF8F4867B6769689656E7 +Test: Encrypt +Comment: Set 1, vector 119 +Key: 00000000000000000000000000000100 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 59641CA52EEBC2C229930CE42529277F +Test: Encrypt +Comment: Set 1, vector 120 +Key: 00000000000000000000000000000080 +Plaintext: 00000000000000000000000000000000 +Ciphertext: A3B4D666AC56C284D40DC27FDB0F787C +Test: Encrypt +Comment: Set 1, vector 121 +Key: 00000000000000000000000000000040 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0511D526FC5F255F51F1914B4B12AD84 +Test: Encrypt +Comment: Set 1, vector 122 +Key: 00000000000000000000000000000020 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 2D14332989F629DA4720ECC916B4DAF0 +Test: Encrypt +Comment: Set 1, vector 123 +Key: 00000000000000000000000000000010 +Plaintext: 00000000000000000000000000000000 +Ciphertext: C44EAC8457E2F17E9BC86EB4C436E8DB +Test: Encrypt +Comment: Set 1, vector 124 +Key: 00000000000000000000000000000008 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 022F3EB45AAA39F785FF80B6A3006BF6 +Test: Encrypt +Comment: Set 1, vector 125 +Key: 00000000000000000000000000000004 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B8A714C8F8427767B384B0E2F6BAF619 +Test: Encrypt +Comment: Set 1, vector 126 +Key: 00000000000000000000000000000002 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 01F745A7C09FECD3497F087BD52A9A0F +Test: Encrypt +Comment: Set 1, vector 127 +Key: 00000000000000000000000000000001 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 41E0E6DC2DDEC65D8B8120E60977B82D +Test: Encrypt +Comment: Set 2, vector 0 +Key: 00000000000000000000000000000000 +Plaintext: 80000000000000000000000000000000 +Ciphertext: 07923A39EB0A817D1C4D87BDB82D1F1C +Test: Encrypt +Comment: Set 2, vector 1 +Key: 00000000000000000000000000000000 +Plaintext: 40000000000000000000000000000000 +Ciphertext: 48CD6419809672D2349260D89A08D3D3 +Test: Encrypt +Comment: Set 2, vector 2 +Key: 00000000000000000000000000000000 +Plaintext: 20000000000000000000000000000000 +Ciphertext: D07493CCB2E95CE0B4945A05ACC97D82 +Test: Encrypt +Comment: Set 2, vector 3 +Key: 00000000000000000000000000000000 +Plaintext: 10000000000000000000000000000000 +Ciphertext: 5DBE1EAC9F7080A88DBED7F6DA101448 +Test: Encrypt +Comment: Set 2, vector 4 +Key: 00000000000000000000000000000000 +Plaintext: 08000000000000000000000000000000 +Ciphertext: F01EE477D199DF2701027034B229622F +Test: Encrypt +Comment: Set 2, vector 5 +Key: 00000000000000000000000000000000 +Plaintext: 04000000000000000000000000000000 +Ciphertext: C841587ABD9A912E563774CB569D051E +Test: Encrypt +Comment: Set 2, vector 6 +Key: 00000000000000000000000000000000 +Plaintext: 02000000000000000000000000000000 +Ciphertext: 1D9BC0C04546F0915C8CCD11391A455C +Test: Encrypt +Comment: Set 2, vector 7 +Key: 00000000000000000000000000000000 +Plaintext: 01000000000000000000000000000000 +Ciphertext: 05E6EBB4BA167F5C479CEFF3152F943B +Test: Encrypt +Comment: Set 2, vector 8 +Key: 00000000000000000000000000000000 +Plaintext: 00800000000000000000000000000000 +Ciphertext: 93211E0F788845B9FC0E4551FFE92AC9 +Test: Encrypt +Comment: Set 2, vector 9 +Key: 00000000000000000000000000000000 +Plaintext: 00400000000000000000000000000000 +Ciphertext: B6D35701CD8FADDE383BBE8E6B70BAF7 +Test: Encrypt +Comment: Set 2, vector 10 +Key: 00000000000000000000000000000000 +Plaintext: 00200000000000000000000000000000 +Ciphertext: 8358F9F4EBCFEE348CB30551ACB151A0 +Test: Encrypt +Comment: Set 2, vector 11 +Key: 00000000000000000000000000000000 +Plaintext: 00100000000000000000000000000000 +Ciphertext: D57516EB5AD93C523E40521BF447AFCE +Test: Encrypt +Comment: Set 2, vector 12 +Key: 00000000000000000000000000000000 +Plaintext: 00080000000000000000000000000000 +Ciphertext: 66B2534C279C439133F52E5AD8B439A9 +Test: Encrypt +Comment: Set 2, vector 13 +Key: 00000000000000000000000000000000 +Plaintext: 00040000000000000000000000000000 +Ciphertext: A71C69184A9F63C2992A5F18F77C1FE9 +Test: Encrypt +Comment: Set 2, vector 14 +Key: 00000000000000000000000000000000 +Plaintext: 00020000000000000000000000000000 +Ciphertext: 1ADCBE49AEACB9ECEBBD492B10E82C7B +Test: Encrypt +Comment: Set 2, vector 15 +Key: 00000000000000000000000000000000 +Plaintext: 00010000000000000000000000000000 +Ciphertext: 27E3BCFB227C5561DB6CF7FC30387036 +Test: Encrypt +Comment: Set 2, vector 16 +Key: 00000000000000000000000000000000 +Plaintext: 00008000000000000000000000000000 +Ciphertext: F4AE20365CC9D06B0CAE6B695ED2CEC1 +Test: Encrypt +Comment: Set 2, vector 17 +Key: 00000000000000000000000000000000 +Plaintext: 00004000000000000000000000000000 +Ciphertext: 3DD682F0B641ED32AD3D43EA2A0456E4 +Test: Encrypt +Comment: Set 2, vector 18 +Key: 00000000000000000000000000000000 +Plaintext: 00002000000000000000000000000000 +Ciphertext: 6E5D14A95ECC290B509EA6B673652E3A +Test: Encrypt +Comment: Set 2, vector 19 +Key: 00000000000000000000000000000000 +Plaintext: 00001000000000000000000000000000 +Ciphertext: F1CDF0F8D7B3FFD95422D7CC0CF40B7B +Test: Encrypt +Comment: Set 2, vector 20 +Key: 00000000000000000000000000000000 +Plaintext: 00000800000000000000000000000000 +Ciphertext: A9253D459A34C385A1F1B2CFFA3935C5 +Test: Encrypt +Comment: Set 2, vector 21 +Key: 00000000000000000000000000000000 +Plaintext: 00000400000000000000000000000000 +Ciphertext: 291024D99FF09A47A1DEE45BA700AE52 +Test: Encrypt +Comment: Set 2, vector 22 +Key: 00000000000000000000000000000000 +Plaintext: 00000200000000000000000000000000 +Ciphertext: 49241D9459B277187BB10081C60361C0 +Test: Encrypt +Comment: Set 2, vector 23 +Key: 00000000000000000000000000000000 +Plaintext: 00000100000000000000000000000000 +Ciphertext: AD9BA365CC4DD5553D2D9FE303841D88 +Test: Encrypt +Comment: Set 2, vector 24 +Key: 00000000000000000000000000000000 +Plaintext: 00000080000000000000000000000000 +Ciphertext: C2ECA616664A249DC622CC11196B4AE1 +Test: Encrypt +Comment: Set 2, vector 25 +Key: 00000000000000000000000000000000 +Plaintext: 00000040000000000000000000000000 +Ciphertext: 6E1A2D4794BB0DC08777A0BC7523E70E +Test: Encrypt +Comment: Set 2, vector 26 +Key: 00000000000000000000000000000000 +Plaintext: 00000020000000000000000000000000 +Ciphertext: 6DB1F0CF59656BDD235E82B8CEF0BE8E +Test: Encrypt +Comment: Set 2, vector 27 +Key: 00000000000000000000000000000000 +Plaintext: 00000010000000000000000000000000 +Ciphertext: 52F239C5EAF401EBDC54D2F011FF4B6A +Test: Encrypt +Comment: Set 2, vector 28 +Key: 00000000000000000000000000000000 +Plaintext: 00000008000000000000000000000000 +Ciphertext: 6B58A08F648414B67FD6847D2AA51CBF +Test: Encrypt +Comment: Set 2, vector 29 +Key: 00000000000000000000000000000000 +Plaintext: 00000004000000000000000000000000 +Ciphertext: 2959DD5367885A75EB48053CF3251A36 +Test: Encrypt +Comment: Set 2, vector 30 +Key: 00000000000000000000000000000000 +Plaintext: 00000002000000000000000000000000 +Ciphertext: 630B292E3B88EF641CDFD531E206605E +Test: Encrypt +Comment: Set 2, vector 31 +Key: 00000000000000000000000000000000 +Plaintext: 00000001000000000000000000000000 +Ciphertext: 4BBB88EF82B70593FCC56AFD91540FDB +Test: Encrypt +Comment: Set 2, vector 32 +Key: 00000000000000000000000000000000 +Plaintext: 00000000800000000000000000000000 +Ciphertext: 0A13055B118A45C606999257BD191426 +Test: Encrypt +Comment: Set 2, vector 33 +Key: 00000000000000000000000000000000 +Plaintext: 00000000400000000000000000000000 +Ciphertext: 5CF8E5C9F15D7E4F865020224853EB77 +Test: Encrypt +Comment: Set 2, vector 34 +Key: 00000000000000000000000000000000 +Plaintext: 00000000200000000000000000000000 +Ciphertext: 3898805042C7A4315C5EE51AF2DE47E2 +Test: Encrypt +Comment: Set 2, vector 35 +Key: 00000000000000000000000000000000 +Plaintext: 00000000100000000000000000000000 +Ciphertext: 8D3F96372E87CBB0B375425B3A10B9E7 +Test: Encrypt +Comment: Set 2, vector 36 +Key: 00000000000000000000000000000000 +Plaintext: 00000000080000000000000000000000 +Ciphertext: 4D9510A378BD784A70A66BCC75B7D3C8 +Test: Encrypt +Comment: Set 2, vector 37 +Key: 00000000000000000000000000000000 +Plaintext: 00000000040000000000000000000000 +Ciphertext: 70DB1902D37CFBDFB98F7C516F79D416 +Test: Encrypt +Comment: Set 2, vector 38 +Key: 00000000000000000000000000000000 +Plaintext: 00000000020000000000000000000000 +Ciphertext: 383C6C2AABEF7FDE25CD470BF774A331 +Test: Encrypt +Comment: Set 2, vector 39 +Key: 00000000000000000000000000000000 +Plaintext: 00000000010000000000000000000000 +Ciphertext: 47CBCB5288349B1A15DC9F81FBEE6B8F +Test: Encrypt +Comment: Set 2, vector 40 +Key: 00000000000000000000000000000000 +Plaintext: 00000000008000000000000000000000 +Ciphertext: 21DA34D4468EEB13AED95DAE0FF48310 +Test: Encrypt +Comment: Set 2, vector 41 +Key: 00000000000000000000000000000000 +Plaintext: 00000000004000000000000000000000 +Ciphertext: 021C9A8E6BD36FBD036411E5D852A80F +Test: Encrypt +Comment: Set 2, vector 42 +Key: 00000000000000000000000000000000 +Plaintext: 00000000002000000000000000000000 +Ciphertext: 6A459E2F839AF60ACDE83774D0BB5574 +Test: Encrypt +Comment: Set 2, vector 43 +Key: 00000000000000000000000000000000 +Plaintext: 00000000001000000000000000000000 +Ciphertext: C19255121F1B933CAE09E58AEC0E9977 +Test: Encrypt +Comment: Set 2, vector 44 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000800000000000000000000 +Ciphertext: 7BA949E27B2BE148A6B801F9305F43D5 +Test: Encrypt +Comment: Set 2, vector 45 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000400000000000000000000 +Ciphertext: E8CEB1026BCF7BCEA32E8A380EA76DB7 +Test: Encrypt +Comment: Set 2, vector 46 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000200000000000000000000 +Ciphertext: 63F97747ED56A8F521B20CC65F6F9465 +Test: Encrypt +Comment: Set 2, vector 47 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000100000000000000000000 +Ciphertext: 2091CFDC629819106188424AC694F75B +Test: Encrypt +Comment: Set 2, vector 48 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000080000000000000000000 +Ciphertext: A91BDF8E8B88407942423CCE000527C4 +Test: Encrypt +Comment: Set 2, vector 49 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000040000000000000000000 +Ciphertext: 73F9B44B9635A3FD683DBF8D49E9825B +Test: Encrypt +Comment: Set 2, vector 50 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000020000000000000000000 +Ciphertext: 9DC64B2133FAD5069FD9A7CC2FFFD1CC +Test: Encrypt +Comment: Set 2, vector 51 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000010000000000000000000 +Ciphertext: 28240F81FEC36B71E13F1FEA7A7641E3 +Test: Encrypt +Comment: Set 2, vector 52 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000008000000000000000000 +Ciphertext: 20DD39FEE96CD2EFF972872A692B28FD +Test: Encrypt +Comment: Set 2, vector 53 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000004000000000000000000 +Ciphertext: 47A9E40483EC1925B635E47E964E8E93 +Test: Encrypt +Comment: Set 2, vector 54 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000002000000000000000000 +Ciphertext: 9C0EBD822C49FB3D853DF5B315A87BA0 +Test: Encrypt +Comment: Set 2, vector 55 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000001000000000000000000 +Ciphertext: C18D813FDB45A594C6DC24E5A1F6CE32 +Test: Encrypt +Comment: Set 2, vector 56 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000800000000000000000 +Ciphertext: 7E5467FF245ECF80CB55C2D8E91F0711 +Test: Encrypt +Comment: Set 2, vector 57 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000400000000000000000 +Ciphertext: 394D4365B77954FDEA4145FCF7A7A041 +Test: Encrypt +Comment: Set 2, vector 58 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000200000000000000000 +Ciphertext: B1D8311A492ED11F11E57B29221610C4 +Test: Encrypt +Comment: Set 2, vector 59 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000100000000000000000 +Ciphertext: E5FBB947A63AEA90163AF04AD6951EF8 +Test: Encrypt +Comment: Set 2, vector 60 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000080000000000000000 +Ciphertext: CA0627DDF580F0E7D59562825C9D0492 +Test: Encrypt +Comment: Set 2, vector 61 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000040000000000000000 +Ciphertext: EF98FFD1AED295AAE1860F0274C8F555 +Test: Encrypt +Comment: Set 2, vector 62 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000020000000000000000 +Ciphertext: 8C698E5CFFF08FACE10C2DC5FF1E2A81 +Test: Encrypt +Comment: Set 2, vector 63 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000010000000000000000 +Ciphertext: 35A7767E02032C35B5CE1A6F49C57C28 +Test: Encrypt +Comment: Set 2, vector 64 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000008000000000000000 +Ciphertext: AB36F8734E76EBA306CF00D6763D90B0 +Test: Encrypt +Comment: Set 2, vector 65 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000004000000000000000 +Ciphertext: E854EB66D4EC66889B5E6CD4F44A5806 +Test: Encrypt +Comment: Set 2, vector 66 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000002000000000000000 +Ciphertext: 15B66DF1455ACD640B8716BCF5DB2D69 +Test: Encrypt +Comment: Set 2, vector 67 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000001000000000000000 +Ciphertext: 4C57AB5333E5C2D4B7E30A007E449F48 +Test: Encrypt +Comment: Set 2, vector 68 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000800000000000000 +Ciphertext: BA3E7FF28EB38EA09D8DB1440A9A3552 +Test: Encrypt +Comment: Set 2, vector 69 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000400000000000000 +Ciphertext: 64E60227AFD80C40C70186CC94804C1A +Test: Encrypt +Comment: Set 2, vector 70 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000200000000000000 +Ciphertext: CEB4423C20B4C91C2551F6FC227C9514 +Test: Encrypt +Comment: Set 2, vector 71 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000100000000000000 +Ciphertext: F736894B843EF32DA28576DE500D448C +Test: Encrypt +Comment: Set 2, vector 72 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000080000000000000 +Ciphertext: 58FDA98B678D15053D4B6C060368108C +Test: Encrypt +Comment: Set 2, vector 73 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000040000000000000 +Ciphertext: E28CAE384E578F47657755EBCD97996C +Test: Encrypt +Comment: Set 2, vector 74 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000020000000000000 +Ciphertext: 0A64617BD4B5B166668240D105B7B6A2 +Test: Encrypt +Comment: Set 2, vector 75 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000010000000000000 +Ciphertext: 4BD090C7E3D365B5EA80F19B4798881E +Test: Encrypt +Comment: Set 2, vector 76 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000008000000000000 +Ciphertext: BC7B6CB9BFF4F72973BB2CD20A512C06 +Test: Encrypt +Comment: Set 2, vector 77 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000004000000000000 +Ciphertext: 4C7ADDC5C867594E9EE75F0AA6AB9C23 +Test: Encrypt +Comment: Set 2, vector 78 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000002000000000000 +Ciphertext: 1FBD05C71A36691AC6566A5298101D53 +Test: Encrypt +Comment: Set 2, vector 79 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000001000000000000 +Ciphertext: 42D7D6B1F499D412F8793972BD968DA2 +Test: Encrypt +Comment: Set 2, vector 80 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000800000000000 +Ciphertext: 260EC86E2786FC68824576B934F32814 +Test: Encrypt +Comment: Set 2, vector 81 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000400000000000 +Ciphertext: 576C26DFD7046F9357F34BEA7DFB26A0 +Test: Encrypt +Comment: Set 2, vector 82 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000200000000000 +Ciphertext: 6D55E54BFB6F927174A02294C95E0F8F +Test: Encrypt +Comment: Set 2, vector 83 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000100000000000 +Ciphertext: 1A6CE91DD458229C7675A34950D10E23 +Test: Encrypt +Comment: Set 2, vector 84 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000080000000000 +Ciphertext: DAD0D5E7E000652825AA34D228EA8D8F +Test: Encrypt +Comment: Set 2, vector 85 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000040000000000 +Ciphertext: E68013F48D75EAD2BBC0B0BDA5E690BF +Test: Encrypt +Comment: Set 2, vector 86 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000020000000000 +Ciphertext: A07D92312FBAE37BFE8A834210AE4F9C +Test: Encrypt +Comment: Set 2, vector 87 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000010000000000 +Ciphertext: 6EEE5F8544CD7D456366EB448813989A +Test: Encrypt +Comment: Set 2, vector 88 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000008000000000 +Ciphertext: F8E5C7FF4B79D7ABE8BFA2DD148820A8 +Test: Encrypt +Comment: Set 2, vector 89 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000004000000000 +Ciphertext: C6349D75C7472BBD66F95B3A07C79C91 +Test: Encrypt +Comment: Set 2, vector 90 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000002000000000 +Ciphertext: B85713C12D8658951CD1AD21C74D2CD2 +Test: Encrypt +Comment: Set 2, vector 91 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000001000000000 +Ciphertext: 907AA00B9F7D47A97623FB55BA911F29 +Test: Encrypt +Comment: Set 2, vector 92 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000800000000 +Ciphertext: DC3CD0ED23D11776FAB43A2A6A8F3557 +Test: Encrypt +Comment: Set 2, vector 93 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000400000000 +Ciphertext: 4BFE58A8FD69179C14765B09AB70B705 +Test: Encrypt +Comment: Set 2, vector 94 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000200000000 +Ciphertext: A23996E0EA67EC280356E5F77130A551 +Test: Encrypt +Comment: Set 2, vector 95 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000100000000 +Ciphertext: CDEADE859B3AACD273CCA85A3E2E45F2 +Test: Encrypt +Comment: Set 2, vector 96 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000080000000 +Ciphertext: E0FC78489857D84DA03F40CE97147174 +Test: Encrypt +Comment: Set 2, vector 97 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000040000000 +Ciphertext: 7615EA6351F6BB12855E8579C6995D8E +Test: Encrypt +Comment: Set 2, vector 98 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000020000000 +Ciphertext: 13E184344FE28C2E70ED0E4D0A8037F9 +Test: Encrypt +Comment: Set 2, vector 99 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000010000000 +Ciphertext: A5FE395F568482B87BC3EB208C81C942 +Test: Encrypt +Comment: Set 2, vector 100 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000008000000 +Ciphertext: B3103E11AF06C85565823F8CAA3159F6 +Test: Encrypt +Comment: Set 2, vector 101 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000004000000 +Ciphertext: 7EBC2234D271B89C519C396985300030 +Test: Encrypt +Comment: Set 2, vector 102 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000002000000 +Ciphertext: 0661D338F2E0C939BA1687820A768467 +Test: Encrypt +Comment: Set 2, vector 103 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000001000000 +Ciphertext: EC2B42667C0195A90715499617884DA5 +Test: Encrypt +Comment: Set 2, vector 104 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000800000 +Ciphertext: AE077BA19D24E7188DDD3682FF196892 +Test: Encrypt +Comment: Set 2, vector 105 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000400000 +Ciphertext: 98823C24B9C65A66073C7952DC2B4B5E +Test: Encrypt +Comment: Set 2, vector 106 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000200000 +Ciphertext: 6AB58432CBB3C2F503DA2D16796CC297 +Test: Encrypt +Comment: Set 2, vector 107 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000100000 +Ciphertext: EEB5EBB3A53E4196C2F22BC1A4DDF5E8 +Test: Encrypt +Comment: Set 2, vector 108 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000080000 +Ciphertext: 33DC40AC5FDC126D38878416AF6C0FA6 +Test: Encrypt +Comment: Set 2, vector 109 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000040000 +Ciphertext: 38EDDC08E18B4AD982CEA921D2765A9A +Test: Encrypt +Comment: Set 2, vector 110 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000020000 +Ciphertext: 7D6BEA038E9347C642E18631660A9558 +Test: Encrypt +Comment: Set 2, vector 111 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000010000 +Ciphertext: FDA57921A473B5EE3700AD5ADF035019 +Test: Encrypt +Comment: Set 2, vector 112 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000008000 +Ciphertext: 699B4812E200337E9C1D2C397F0DFE4E +Test: Encrypt +Comment: Set 2, vector 113 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000004000 +Ciphertext: 7A1EADF68B0807145D6C414852DECFC8 +Test: Encrypt +Comment: Set 2, vector 114 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000002000 +Ciphertext: 1645FFAA8AD76689C01DA8C40882781F +Test: Encrypt +Comment: Set 2, vector 115 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000001000 +Ciphertext: BA0C053BE702FA62FC66D8FEB12FC97E +Test: Encrypt +Comment: Set 2, vector 116 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000000800 +Ciphertext: 841FD8AF69CF2C31F7D4D7B6959662B5 +Test: Encrypt +Comment: Set 2, vector 117 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000000400 +Ciphertext: F675D59BDB33231861268F539829DA0B +Test: Encrypt +Comment: Set 2, vector 118 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000000200 +Ciphertext: A4967F45ABB4E8C7DC5E3806680F35E0 +Test: Encrypt +Comment: Set 2, vector 119 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000000100 +Ciphertext: 4D7E08081CC82F92ABA7C58C99F8343F +Test: Encrypt +Comment: Set 2, vector 120 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000000080 +Ciphertext: 9AEFDB287C119B82353612B60ECCBFD8 +Test: Encrypt +Comment: Set 2, vector 121 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000000040 +Ciphertext: 979BB6A1553A17592A86E78DF144A699 +Test: Encrypt +Comment: Set 2, vector 122 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000000020 +Ciphertext: A6FA8CAB06FD2E5BF3A858983C01757A +Test: Encrypt +Comment: Set 2, vector 123 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000000010 +Ciphertext: BE8511254C31E25420B91D6FEF1710ED +Test: Encrypt +Comment: Set 2, vector 124 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000000008 +Ciphertext: F589A908D18A21894971C0433581E1A5 +Test: Encrypt +Comment: Set 2, vector 125 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000000004 +Ciphertext: 4237585130E7C9F715235EB1D8C94DE7 +Test: Encrypt +Comment: Set 2, vector 126 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000000002 +Ciphertext: DEFE3E0B5C54C94B4F2A0F5A46F6210D +Test: Encrypt +Comment: Set 2, vector 127 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000000001 +Ciphertext: F5574ACC3148DFCB9015200631024DF9 +Test: Encrypt +Comment: Set 3, vector 0 +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3D028025B156327C17F762C1F2CBCA71 +Test: Encrypt +Comment: Set 3, vector 1 +Key: 01010101010101010101010101010101 +Plaintext: 01010101010101010101010101010101 +Ciphertext: 637084CB1120D6F25DB618893040AA27 +Test: Encrypt +Comment: Set 3, vector 2 +Key: 02020202020202020202020202020202 +Plaintext: 02020202020202020202020202020202 +Ciphertext: 612834AAC9EF906BAEAA076E1C75179D +Test: Encrypt +Comment: Set 3, vector 3 +Key: 03030303030303030303030303030303 +Plaintext: 03030303030303030303030303030303 +Ciphertext: AECEE4C59E91366360923654C17140A9 +Test: Encrypt +Comment: Set 3, vector 4 +Key: 04040404040404040404040404040404 +Plaintext: 04040404040404040404040404040404 +Ciphertext: B24FAF8A579E4EFE986571FB2F68B5B4 +Test: Encrypt +Comment: Set 3, vector 5 +Key: 05050505050505050505050505050505 +Plaintext: 05050505050505050505050505050505 +Ciphertext: C102E40B5E584CF6AA16108D93DA26E3 +Test: Encrypt +Comment: Set 3, vector 6 +Key: 06060606060606060606060606060606 +Plaintext: 06060606060606060606060606060606 +Ciphertext: 962F98098E6CEA968FA568C5A32ADA50 +Test: Encrypt +Comment: Set 3, vector 7 +Key: 07070707070707070707070707070707 +Plaintext: 07070707070707070707070707070707 +Ciphertext: 27E9AB0117A37D228B77B29B38B3836F +Test: Encrypt +Comment: Set 3, vector 8 +Key: 08080808080808080808080808080808 +Plaintext: 08080808080808080808080808080808 +Ciphertext: 3E5CAFBB70545AABB1109293A1C44C14 +Test: Encrypt +Comment: Set 3, vector 9 +Key: 09090909090909090909090909090909 +Plaintext: 09090909090909090909090909090909 +Ciphertext: E4AC7417ECB8B2871B0EF12CECD20F46 +Test: Encrypt +Comment: Set 3, vector 10 +Key: 0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A +Plaintext: 0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A +Ciphertext: B29D18DD34C1CC00257838F1B8BD43DB +Test: Encrypt +Comment: Set 3, vector 11 +Key: 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +Plaintext: 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +Ciphertext: FC1094A0A2850499D874B6DDC1EBA0B7 +Test: Encrypt +Comment: Set 3, vector 12 +Key: 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C +Plaintext: 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C +Ciphertext: AD062A5D53BB0478F17DA5528839F9FF +Test: Encrypt +Comment: Set 3, vector 13 +Key: 0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D +Plaintext: 0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D +Ciphertext: 2C9DFEC27363BD0E651CC91FC05FDADF +Test: Encrypt +Comment: Set 3, vector 14 +Key: 0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E +Plaintext: 0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E +Ciphertext: 487C72BD251D4566AE6119A70A95B79F +Test: Encrypt +Comment: Set 3, vector 15 +Key: 0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F +Plaintext: 0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F +Ciphertext: 18CE9F8E752F787051CB8E407EB16C12 +Test: Encrypt +Comment: Set 3, vector 16 +Key: 10101010101010101010101010101010 +Plaintext: 10101010101010101010101010101010 +Ciphertext: E1FA5FD3F40B766BBE3DF469AF41B420 +Test: Encrypt +Comment: Set 3, vector 17 +Key: 11111111111111111111111111111111 +Plaintext: 11111111111111111111111111111111 +Ciphertext: 09628EDC6CD69F4F85483DC37633F732 +Test: Encrypt +Comment: Set 3, vector 18 +Key: 12121212121212121212121212121212 +Plaintext: 12121212121212121212121212121212 +Ciphertext: 2E6C94A96F6744C4E8D4146B4ECCD815 +Test: Encrypt +Comment: Set 3, vector 19 +Key: 13131313131313131313131313131313 +Plaintext: 13131313131313131313131313131313 +Ciphertext: 800996B5B363ACAB3FB8982F9BBE767F +Test: Encrypt +Comment: Set 3, vector 20 +Key: 14141414141414141414141414141414 +Plaintext: 14141414141414141414141414141414 +Ciphertext: C254C27642167B8FF363EAAD41A165A8 +Test: Encrypt +Comment: Set 3, vector 21 +Key: 15151515151515151515151515151515 +Plaintext: 15151515151515151515151515151515 +Ciphertext: 0B43A548CFFE916BAD7AB58B5F51B1E2 +Test: Encrypt +Comment: Set 3, vector 22 +Key: 16161616161616161616161616161616 +Plaintext: 16161616161616161616161616161616 +Ciphertext: 6C753853277756B8E0578FDC371A8738 +Test: Encrypt +Comment: Set 3, vector 23 +Key: 17171717171717171717171717171717 +Plaintext: 17171717171717171717171717171717 +Ciphertext: A278A500B02D8B2C7E829F1816872B1A +Test: Encrypt +Comment: Set 3, vector 24 +Key: 18181818181818181818181818181818 +Plaintext: 18181818181818181818181818181818 +Ciphertext: 67DD5353E13CDD51FC52716BC6BAB258 +Test: Encrypt +Comment: Set 3, vector 25 +Key: 19191919191919191919191919191919 +Plaintext: 19191919191919191919191919191919 +Ciphertext: 1B2DF65083662590F49719D7721D7C61 +Test: Encrypt +Comment: Set 3, vector 26 +Key: 1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A +Plaintext: 1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A +Ciphertext: B12E384030DE7B77866E758FB251CCFF +Test: Encrypt +Comment: Set 3, vector 27 +Key: 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B +Plaintext: 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B +Ciphertext: C37B3145C36FE5B95AC1392BEB81C9D8 +Test: Encrypt +Comment: Set 3, vector 28 +Key: 1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C +Plaintext: 1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C +Ciphertext: 5C25502EF79A5792DEE9359EDF7BA8BC +Test: Encrypt +Comment: Set 3, vector 29 +Key: 1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D +Plaintext: 1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D +Ciphertext: F0D899AEF42F226605E6A61A650F00A1 +Test: Encrypt +Comment: Set 3, vector 30 +Key: 1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E +Plaintext: 1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E +Ciphertext: 12096937A3474FE4D87C77581C09380B +Test: Encrypt +Comment: Set 3, vector 31 +Key: 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F +Plaintext: 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F +Ciphertext: CFC3A30819A45111983ABBF16CC61E9A +Test: Encrypt +Comment: Set 3, vector 32 +Key: 20202020202020202020202020202020 +Plaintext: 20202020202020202020202020202020 +Ciphertext: 7E724027BB2F591C63254D936FCC4B43 +Test: Encrypt +Comment: Set 3, vector 33 +Key: 21212121212121212121212121212121 +Plaintext: 21212121212121212121212121212121 +Ciphertext: FC9893DACCE806419957685270D5BF13 +Test: Encrypt +Comment: Set 3, vector 34 +Key: 22222222222222222222222222222222 +Plaintext: 22222222222222222222222222222222 +Ciphertext: F6C372A2AE2C03D7A9E0597DBEDFE961 +Test: Encrypt +Comment: Set 3, vector 35 +Key: 23232323232323232323232323232323 +Plaintext: 23232323232323232323232323232323 +Ciphertext: 4EE3CD585BD7A498DE93DDE42FDCBE73 +Test: Encrypt +Comment: Set 3, vector 36 +Key: 24242424242424242424242424242424 +Plaintext: 24242424242424242424242424242424 +Ciphertext: 71D0FFA714D70B5A3CDCE26BC91D93EE +Test: Encrypt +Comment: Set 3, vector 37 +Key: 25252525252525252525252525252525 +Plaintext: 25252525252525252525252525252525 +Ciphertext: 918EB6A7FA54EE795DE68EB5C0011BFD +Test: Encrypt +Comment: Set 3, vector 38 +Key: 26262626262626262626262626262626 +Plaintext: 26262626262626262626262626262626 +Ciphertext: 3A3DBFD37FB057816485BA948034E25E +Test: Encrypt +Comment: Set 3, vector 39 +Key: 27272727272727272727272727272727 +Plaintext: 27272727272727272727272727272727 +Ciphertext: 1FAD9F63890CF5475F3557B83924427C +Test: Encrypt +Comment: Set 3, vector 40 +Key: 28282828282828282828282828282828 +Plaintext: 28282828282828282828282828282828 +Ciphertext: 63F70DD87B9D63FC79628DECC6F34605 +Test: Encrypt +Comment: Set 3, vector 41 +Key: 29292929292929292929292929292929 +Plaintext: 29292929292929292929292929292929 +Ciphertext: D8FE7DF75B51024B69BDAB4844233CBB +Test: Encrypt +Comment: Set 3, vector 42 +Key: 2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A +Plaintext: 2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A +Ciphertext: D927B8DB454BEECFEE2F89ACD2D26F1A +Test: Encrypt +Comment: Set 3, vector 43 +Key: 2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B +Plaintext: 2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B +Ciphertext: 958B7CFABED67123D21541083FA90EB8 +Test: Encrypt +Comment: Set 3, vector 44 +Key: 2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C +Plaintext: 2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C +Ciphertext: 2F220AA3BB400736F3D0295E3C6D9052 +Test: Encrypt +Comment: Set 3, vector 45 +Key: 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D +Plaintext: 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D +Ciphertext: A14F57CE4D9EA4C5E282108DF8FDE00E +Test: Encrypt +Comment: Set 3, vector 46 +Key: 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E +Plaintext: 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E +Ciphertext: 23E437F93E0BE22B4C54BC187D70BCC1 +Test: Encrypt +Comment: Set 3, vector 47 +Key: 2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F +Plaintext: 2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F +Ciphertext: 615B6706E39E4A55EA8BFA4EFB8EBAEA +Test: Encrypt +Comment: Set 3, vector 48 +Key: 30303030303030303030303030303030 +Plaintext: 30303030303030303030303030303030 +Ciphertext: 5354CC9F7CAA08298C9A8AD471B39235 +Test: Encrypt +Comment: Set 3, vector 49 +Key: 31313131313131313131313131313131 +Plaintext: 31313131313131313131313131313131 +Ciphertext: DA2512B115E748580B7D198BFF01A537 +Test: Encrypt +Comment: Set 3, vector 50 +Key: 32323232323232323232323232323232 +Plaintext: 32323232323232323232323232323232 +Ciphertext: AEF890FCDEC04BFB0C4724558688810B +Test: Encrypt +Comment: Set 3, vector 51 +Key: 33333333333333333333333333333333 +Plaintext: 33333333333333333333333333333333 +Ciphertext: AEC153899584F8B9FC9836B86A40BA4A +Test: Encrypt +Comment: Set 3, vector 52 +Key: 34343434343434343434343434343434 +Plaintext: 34343434343434343434343434343434 +Ciphertext: E86D0DBEBD69030C0654656E0D348A8E +Test: Encrypt +Comment: Set 3, vector 53 +Key: 35353535353535353535353535353535 +Plaintext: 35353535353535353535353535353535 +Ciphertext: 3EFFEE758220F7138D31564D5CDA82EF +Test: Encrypt +Comment: Set 3, vector 54 +Key: 36363636363636363636363636363636 +Plaintext: 36363636363636363636363636363636 +Ciphertext: A0A57A825008700B246CEE9821803321 +Test: Encrypt +Comment: Set 3, vector 55 +Key: 37373737373737373737373737373737 +Plaintext: 37373737373737373737373737373737 +Ciphertext: 318692397CD421D958D142299AE24E5E +Test: Encrypt +Comment: Set 3, vector 56 +Key: 38383838383838383838383838383838 +Plaintext: 38383838383838383838383838383838 +Ciphertext: 1B949505033DB5554BBBBBB9488970DE +Test: Encrypt +Comment: Set 3, vector 57 +Key: 39393939393939393939393939393939 +Plaintext: 39393939393939393939393939393939 +Ciphertext: 20600DB3471001F93837F8EB50F7EB2B +Test: Encrypt +Comment: Set 3, vector 58 +Key: 3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A +Plaintext: 3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A +Ciphertext: 004C126190B7D20ADCA7331EA26AC487 +Test: Encrypt +Comment: Set 3, vector 59 +Key: 3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B +Plaintext: 3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B +Ciphertext: 7F535656FE3113A61D21BE216365D9FD +Test: Encrypt +Comment: Set 3, vector 60 +Key: 3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C +Plaintext: 3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C +Ciphertext: A7DA48E8AD71B1DC583A895A8CC85FF2 +Test: Encrypt +Comment: Set 3, vector 61 +Key: 3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D +Plaintext: 3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D +Ciphertext: 02E8CB85E9DDEDFAB4D9DB7106C6C38F +Test: Encrypt +Comment: Set 3, vector 62 +Key: 3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E +Plaintext: 3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E +Ciphertext: 44ACE8B20DF2DBA70C0287362D51ED5C +Test: Encrypt +Comment: Set 3, vector 63 +Key: 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F +Plaintext: 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F +Ciphertext: 8ABDD80D977FAF208FDFC69AA70E9810 +Test: Encrypt +Comment: Set 3, vector 64 +Key: 40404040404040404040404040404040 +Plaintext: 40404040404040404040404040404040 +Ciphertext: 538ADCBE104A3483B3C2A3D8CE72FBD6 +Test: Encrypt +Comment: Set 3, vector 65 +Key: 41414141414141414141414141414141 +Plaintext: 41414141414141414141414141414141 +Ciphertext: 7F757894F1A04645BCB523E925A937C7 +Test: Encrypt +Comment: Set 3, vector 66 +Key: 42424242424242424242424242424242 +Plaintext: 42424242424242424242424242424242 +Ciphertext: FA4304C7D16E164E000461B2550207B1 +Test: Encrypt +Comment: Set 3, vector 67 +Key: 43434343434343434343434343434343 +Plaintext: 43434343434343434343434343434343 +Ciphertext: 5B8E43BF0CACBCB80933B4061F9702B2 +Test: Encrypt +Comment: Set 3, vector 68 +Key: 44444444444444444444444444444444 +Plaintext: 44444444444444444444444444444444 +Ciphertext: 4DB11630D8CD9390797EE30EE9A25CB3 +Test: Encrypt +Comment: Set 3, vector 69 +Key: 45454545454545454545454545454545 +Plaintext: 45454545454545454545454545454545 +Ciphertext: 61150375D22621E9DD7AB45227E4ADC1 +Test: Encrypt +Comment: Set 3, vector 70 +Key: 46464646464646464646464646464646 +Plaintext: 46464646464646464646464646464646 +Ciphertext: 825AA0A2275496EA00BE2C75982EC24E +Test: Encrypt +Comment: Set 3, vector 71 +Key: 47474747474747474747474747474747 +Plaintext: 47474747474747474747474747474747 +Ciphertext: 1EA3F70E26F079CE37801787B5F3655C +Test: Encrypt +Comment: Set 3, vector 72 +Key: 48484848484848484848484848484848 +Plaintext: 48484848484848484848484848484848 +Ciphertext: F46E712267A6CA8DA8AC044A4E3ADC69 +Test: Encrypt +Comment: Set 3, vector 73 +Key: 49494949494949494949494949494949 +Plaintext: 49494949494949494949494949494949 +Ciphertext: 00FCF96BD11DB90E045B948C2658FC07 +Test: Encrypt +Comment: Set 3, vector 74 +Key: 4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A +Plaintext: 4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A +Ciphertext: 08E264CCDA07442DD6FB5BC8AF05A9C1 +Test: Encrypt +Comment: Set 3, vector 75 +Key: 4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B +Plaintext: 4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B +Ciphertext: 35C189E86440D125B0CAF6C62CA0E4F9 +Test: Encrypt +Comment: Set 3, vector 76 +Key: 4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C +Plaintext: 4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C +Ciphertext: 7FC2F545C0DE78664218F4F635CC8D10 +Test: Encrypt +Comment: Set 3, vector 77 +Key: 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D +Plaintext: 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D +Ciphertext: 9DC067581AD80555C6E46C6594A626F5 +Test: Encrypt +Comment: Set 3, vector 78 +Key: 4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E +Plaintext: 4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E +Ciphertext: D33A3E8035B42D76A483BE06B62054A6 +Test: Encrypt +Comment: Set 3, vector 79 +Key: 4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F +Plaintext: 4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F +Ciphertext: 7CA26FD5D6DB7EAA785FCCA1E2854910 +Test: Encrypt +Comment: Set 3, vector 80 +Key: 50505050505050505050505050505050 +Plaintext: 50505050505050505050505050505050 +Ciphertext: E9A672BD5401539C1C8F2AB21A83B26B +Test: Encrypt +Comment: Set 3, vector 81 +Key: 51515151515151515151515151515151 +Plaintext: 51515151515151515151515151515151 +Ciphertext: 2948CB8989780E74BA525CC2FDDC42CF +Test: Encrypt +Comment: Set 3, vector 82 +Key: 52525252525252525252525252525252 +Plaintext: 52525252525252525252525252525252 +Ciphertext: A3A8308145C318D42F4E8310DF6D97E0 +Test: Encrypt +Comment: Set 3, vector 83 +Key: 53535353535353535353535353535353 +Plaintext: 53535353535353535353535353535353 +Ciphertext: 1757125D19851062D7782A2200A813E9 +Test: Encrypt +Comment: Set 3, vector 84 +Key: 54545454545454545454545454545454 +Plaintext: 54545454545454545454545454545454 +Ciphertext: 9BC4FC94FF7A09F9D4C23A3BDEAF498E +Test: Encrypt +Comment: Set 3, vector 85 +Key: 55555555555555555555555555555555 +Plaintext: 55555555555555555555555555555555 +Ciphertext: B36C8A8DC251A4D08B38160011498AB2 +Test: Encrypt +Comment: Set 3, vector 86 +Key: 56565656565656565656565656565656 +Plaintext: 56565656565656565656565656565656 +Ciphertext: 6C6058C8D5F2A32E31988239C4A657F1 +Test: Encrypt +Comment: Set 3, vector 87 +Key: 57575757575757575757575757575757 +Plaintext: 57575757575757575757575757575757 +Ciphertext: B8B914785FD465FB0F83FE4A676C3A6B +Test: Encrypt +Comment: Set 3, vector 88 +Key: 58585858585858585858585858585858 +Plaintext: 58585858585858585858585858585858 +Ciphertext: 00BBEEC24412F8A2C4291B5F1F32E662 +Test: Encrypt +Comment: Set 3, vector 89 +Key: 59595959595959595959595959595959 +Plaintext: 59595959595959595959595959595959 +Ciphertext: AF8353C84504526068884176D45CC8A0 +Test: Encrypt +Comment: Set 3, vector 90 +Key: 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A +Plaintext: 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A +Ciphertext: F84DF1519736174F6F23B4CC3FC939F1 +Test: Encrypt +Comment: Set 3, vector 91 +Key: 5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B +Plaintext: 5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B +Ciphertext: 320326E1024C9156B0E4C483065F0D94 +Test: Encrypt +Comment: Set 3, vector 92 +Key: 5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C +Plaintext: 5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C +Ciphertext: 80AFE13AEC30894E8B772E73F367A148 +Test: Encrypt +Comment: Set 3, vector 93 +Key: 5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D +Plaintext: 5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D +Ciphertext: 5F0D8BE9294D27DB7E6CD4D4F8A08D48 +Test: Encrypt +Comment: Set 3, vector 94 +Key: 5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E +Plaintext: 5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E +Ciphertext: B6D8E7EF37171F6271AC274411E26867 +Test: Encrypt +Comment: Set 3, vector 95 +Key: 5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F +Plaintext: 5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F +Ciphertext: 23DEBDDF60703AE0F8E9337C73C6FDC3 +Test: Encrypt +Comment: Set 3, vector 96 +Key: 60606060606060606060606060606060 +Plaintext: 60606060606060606060606060606060 +Ciphertext: D03B4696B0DCC56C37F7038747BEF222 +Test: Encrypt +Comment: Set 3, vector 97 +Key: 61616161616161616161616161616161 +Plaintext: 61616161616161616161616161616161 +Ciphertext: 201E6A1FA7898892DA1D3148766F7939 +Test: Encrypt +Comment: Set 3, vector 98 +Key: 62626262626262626262626262626262 +Plaintext: 62626262626262626262626262626262 +Ciphertext: D9643DBC3C373D300DB5AC3E699F7DDE +Test: Encrypt +Comment: Set 3, vector 99 +Key: 63636363636363636363636363636363 +Plaintext: 63636363636363636363636363636363 +Ciphertext: 1B04DAF08A764C09DFFE140403F4EC5D +Test: Encrypt +Comment: Set 3, vector 100 +Key: 64646464646464646464646464646464 +Plaintext: 64646464646464646464646464646464 +Ciphertext: 0510AA045E35862885AEEB1752328032 +Test: Encrypt +Comment: Set 3, vector 101 +Key: 65656565656565656565656565656565 +Plaintext: 65656565656565656565656565656565 +Ciphertext: 894E5FE4164A0B9CC2C50D95F18329E6 +Test: Encrypt +Comment: Set 3, vector 102 +Key: 66666666666666666666666666666666 +Plaintext: 66666666666666666666666666666666 +Ciphertext: 99D16D251893E474CD8A18C10798D418 +Test: Encrypt +Comment: Set 3, vector 103 +Key: 67676767676767676767676767676767 +Plaintext: 67676767676767676767676767676767 +Ciphertext: B41A0DEEA15FCB419E00318752503FA8 +Test: Encrypt +Comment: Set 3, vector 104 +Key: 68686868686868686868686868686868 +Plaintext: 68686868686868686868686868686868 +Ciphertext: 8BDDFBD29844F3EED1E02FB76628E877 +Test: Encrypt +Comment: Set 3, vector 105 +Key: 69696969696969696969696969696969 +Plaintext: 69696969696969696969696969696969 +Ciphertext: E71C41B95412E2ED6BC6B5693BC445E5 +Test: Encrypt +Comment: Set 3, vector 106 +Key: 6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A +Plaintext: 6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A +Ciphertext: 566E5667E9BDDCE13F3B6DE0DEF06305 +Test: Encrypt +Comment: Set 3, vector 107 +Key: 6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B +Plaintext: 6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B +Ciphertext: 49372FDCE8DC81E45A9E6FBFB8952F76 +Test: Encrypt +Comment: Set 3, vector 108 +Key: 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C +Plaintext: 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C +Ciphertext: 034EAB9E0E881ABF0C4F9B7933E7F1B2 +Test: Encrypt +Comment: Set 3, vector 109 +Key: 6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D +Plaintext: 6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D +Ciphertext: 56FFE171E45816C5808380530F3F9F23 +Test: Encrypt +Comment: Set 3, vector 110 +Key: 6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E +Plaintext: 6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E +Ciphertext: 5FE59EE65A0321F3B09A1748CF18CC02 +Test: Encrypt +Comment: Set 3, vector 111 +Key: 6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F +Plaintext: 6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F +Ciphertext: 8C13790203280B652614D224178C4289 +Test: Encrypt +Comment: Set 3, vector 112 +Key: 70707070707070707070707070707070 +Plaintext: 70707070707070707070707070707070 +Ciphertext: 52D7C5111B52E5356C8EF2B629BA6166 +Test: Encrypt +Comment: Set 3, vector 113 +Key: 71717171717171717171717171717171 +Plaintext: 71717171717171717171717171717171 +Ciphertext: 4FB997235548FB5C202A1514FF408068 +Test: Encrypt +Comment: Set 3, vector 114 +Key: 72727272727272727272727272727272 +Plaintext: 72727272727272727272727272727272 +Ciphertext: 8DDE9345FEDAB8D8D2DE5E2577756F16 +Test: Encrypt +Comment: Set 3, vector 115 +Key: 73737373737373737373737373737373 +Plaintext: 73737373737373737373737373737373 +Ciphertext: C1B39136F69B2044C30E38023EB6E7D2 +Test: Encrypt +Comment: Set 3, vector 116 +Key: 74747474747474747474747474747474 +Plaintext: 74747474747474747474747474747474 +Ciphertext: 6032D1B3844BEA4ACE81142A013C42BC +Test: Encrypt +Comment: Set 3, vector 117 +Key: 75757575757575757575757575757575 +Plaintext: 75757575757575757575757575757575 +Ciphertext: 985A9D8DDE048107368028AA24F5D70B +Test: Encrypt +Comment: Set 3, vector 118 +Key: 76767676767676767676767676767676 +Plaintext: 76767676767676767676767676767676 +Ciphertext: 5343E03D587A538475BB92F23E96FDF8 +Test: Encrypt +Comment: Set 3, vector 119 +Key: 77777777777777777777777777777777 +Plaintext: 77777777777777777777777777777777 +Ciphertext: 98253AF78B8DA7E5AE98E7B4E9FA74F9 +Test: Encrypt +Comment: Set 3, vector 120 +Key: 78787878787878787878787878787878 +Plaintext: 78787878787878787878787878787878 +Ciphertext: 8404DDA01CC702790B8B31408205E128 +Test: Encrypt +Comment: Set 3, vector 121 +Key: 79797979797979797979797979797979 +Plaintext: 79797979797979797979797979797979 +Ciphertext: C782C96911F30723AB90E3A0BA59B808 +Test: Encrypt +Comment: Set 3, vector 122 +Key: 7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A +Plaintext: 7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A +Ciphertext: 471270191B1BB659804CEAE818793167 +Test: Encrypt +Comment: Set 3, vector 123 +Key: 7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B +Plaintext: 7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B +Ciphertext: 2B27BBF7E47DA05F72EED52D038A3241 +Test: Encrypt +Comment: Set 3, vector 124 +Key: 7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C +Plaintext: 7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C +Ciphertext: 0BD3B3F3F6F404B6B7C6D436605640B7 +Test: Encrypt +Comment: Set 3, vector 125 +Key: 7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D +Plaintext: 7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D +Ciphertext: 74578268B9D9AD5D9819E51CA288F81D +Test: Encrypt +Comment: Set 3, vector 126 +Key: 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E +Plaintext: 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E +Ciphertext: A77A67CC08111CE41B817176859675B5 +Test: Encrypt +Comment: Set 3, vector 127 +Key: 7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F +Plaintext: 7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F +Ciphertext: 9BE99EFDAF9CCCB4D879173EA2197FEF +Test: Encrypt +Comment: Set 3, vector 128 +Key: 80808080808080808080808080808080 +Plaintext: 80808080808080808080808080808080 +Ciphertext: AA7627F70F6B54C217C3EF232D362459 +Test: Encrypt +Comment: Set 3, vector 129 +Key: 81818181818181818181818181818181 +Plaintext: 81818181818181818181818181818181 +Ciphertext: EE41F8DC661C2A8B95667CB1F908367A +Test: Encrypt +Comment: Set 3, vector 130 +Key: 82828282828282828282828282828282 +Plaintext: 82828282828282828282828282828282 +Ciphertext: AF2D71AC4D7E482E8134A65F2841101A +Test: Encrypt +Comment: Set 3, vector 131 +Key: 83838383838383838383838383838383 +Plaintext: 83838383838383838383838383838383 +Ciphertext: 98CFCAA37D3B1825C55FA94825BBC91A +Test: Encrypt +Comment: Set 3, vector 132 +Key: 84848484848484848484848484848484 +Plaintext: 84848484848484848484848484848484 +Ciphertext: 2ACFCBC772417EBD445F8B272857578C +Test: Encrypt +Comment: Set 3, vector 133 +Key: 85858585858585858585858585858585 +Plaintext: 85858585858585858585858585858585 +Ciphertext: 424DE49A69767A539E26581A19CD4F17 +Test: Encrypt +Comment: Set 3, vector 134 +Key: 86868686868686868686868686868686 +Plaintext: 86868686868686868686868686868686 +Ciphertext: F25ED7239B234E58AE40F7612E3CE6BA +Test: Encrypt +Comment: Set 3, vector 135 +Key: 87878787878787878787878787878787 +Plaintext: 87878787878787878787878787878787 +Ciphertext: 4BF44DBA1E6E80DE3554F7EEF0621EBF +Test: Encrypt +Comment: Set 3, vector 136 +Key: 88888888888888888888888888888888 +Plaintext: 88888888888888888888888888888888 +Ciphertext: 6B87409975816BC8480985D079B08594 +Test: Encrypt +Comment: Set 3, vector 137 +Key: 89898989898989898989898989898989 +Plaintext: 89898989898989898989898989898989 +Ciphertext: D026A866DD55C02EE77DF1E93405A751 +Test: Encrypt +Comment: Set 3, vector 138 +Key: 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A +Plaintext: 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A +Ciphertext: A45F7212DD04352DEF319D58922C44CE +Test: Encrypt +Comment: Set 3, vector 139 +Key: 8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B +Plaintext: 8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B +Ciphertext: 4600AD219EE97A7BFF629D8F6E337C79 +Test: Encrypt +Comment: Set 3, vector 140 +Key: 8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C +Plaintext: 8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C +Ciphertext: A26CEFEC7612A89E8543503A678D921F +Test: Encrypt +Comment: Set 3, vector 141 +Key: 8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D +Plaintext: 8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D +Ciphertext: 5CA126B9342723816C82AC1D41F97EFB +Test: Encrypt +Comment: Set 3, vector 142 +Key: 8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E +Plaintext: 8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E +Ciphertext: 76DC82C091F5691C35E8735EB901B788 +Test: Encrypt +Comment: Set 3, vector 143 +Key: 8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F +Plaintext: 8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F +Ciphertext: 2F8AA5E8D7D90B3E7FCC20128F462AAD +Test: Encrypt +Comment: Set 3, vector 144 +Key: 90909090909090909090909090909090 +Plaintext: 90909090909090909090909090909090 +Ciphertext: 67B8B189FCD886FD2160005C93D9F3B2 +Test: Encrypt +Comment: Set 3, vector 145 +Key: 91919191919191919191919191919191 +Plaintext: 91919191919191919191919191919191 +Ciphertext: 8DFBD0B7D8B614E15B56571A6A5B443D +Test: Encrypt +Comment: Set 3, vector 146 +Key: 92929292929292929292929292929292 +Plaintext: 92929292929292929292929292929292 +Ciphertext: F10DA9ABD28359461A3BB271C2037D1A +Test: Encrypt +Comment: Set 3, vector 147 +Key: 93939393939393939393939393939393 +Plaintext: 93939393939393939393939393939393 +Ciphertext: 5A53C6ADF38E807BC03CC53193133CDE +Test: Encrypt +Comment: Set 3, vector 148 +Key: 94949494949494949494949494949494 +Plaintext: 94949494949494949494949494949494 +Ciphertext: 298AF9909A89241F34DB6BF6ACC6A909 +Test: Encrypt +Comment: Set 3, vector 149 +Key: 95959595959595959595959595959595 +Plaintext: 95959595959595959595959595959595 +Ciphertext: DAA5C134BDD34A775DEC219F6DE219BE +Test: Encrypt +Comment: Set 3, vector 150 +Key: 96969696969696969696969696969696 +Plaintext: 96969696969696969696969696969696 +Ciphertext: 2514903F8ABA0F65CA22C8AD82FF2574 +Test: Encrypt +Comment: Set 3, vector 151 +Key: 97979797979797979797979797979797 +Plaintext: 97979797979797979797979797979797 +Ciphertext: 11696CB06D2F97B1A2CB380E2887AB7E +Test: Encrypt +Comment: Set 3, vector 152 +Key: 98989898989898989898989898989898 +Plaintext: 98989898989898989898989898989898 +Ciphertext: E70BAE913D953A66AC35DE9CAA6D205D +Test: Encrypt +Comment: Set 3, vector 153 +Key: 99999999999999999999999999999999 +Plaintext: 99999999999999999999999999999999 +Ciphertext: 20BC3C8F4E81EEA320189E6063017706 +Test: Encrypt +Comment: Set 3, vector 154 +Key: 9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A +Plaintext: 9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A +Ciphertext: 53A956A32B4B532F5E9BE8C94278EC57 +Test: Encrypt +Comment: Set 3, vector 155 +Key: 9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B +Plaintext: 9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B +Ciphertext: 2562236E541426B29A4232E592237CAD +Test: Encrypt +Comment: Set 3, vector 156 +Key: 9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C +Plaintext: 9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C +Ciphertext: 0F8A9DEDA85B0A1CF7487C6ED823B869 +Test: Encrypt +Comment: Set 3, vector 157 +Key: 9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D +Plaintext: 9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D +Ciphertext: 8917CF4F1A25A500440CF0665BB517A0 +Test: Encrypt +Comment: Set 3, vector 158 +Key: 9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E +Plaintext: 9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E +Ciphertext: F5C065F3821FA664724BF6AFF1039430 +Test: Encrypt +Comment: Set 3, vector 159 +Key: 9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F +Plaintext: 9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F +Ciphertext: F5D5131F0D2F4859EC38F8999A93E74D +Test: Encrypt +Comment: Set 3, vector 160 +Key: A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0 +Plaintext: A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0 +Ciphertext: 9A02DF44F2194E94B7E34F1DCC234685 +Test: Encrypt +Comment: Set 3, vector 161 +Key: A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1 +Plaintext: A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1 +Ciphertext: 59491E467432E6147EAFE37BCD93DA01 +Test: Encrypt +Comment: Set 3, vector 162 +Key: A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 +Plaintext: A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 +Ciphertext: 4D0B317CE4AE577CF87B225C53DDF352 +Test: Encrypt +Comment: Set 3, vector 163 +Key: A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3 +Plaintext: A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3 +Ciphertext: 73E082DC996995BDDD1F5544326D56D6 +Test: Encrypt +Comment: Set 3, vector 164 +Key: A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4 +Plaintext: A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4 +Ciphertext: 46C5C6E23A72C9DF410EF979F93CF266 +Test: Encrypt +Comment: Set 3, vector 165 +Key: A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5 +Plaintext: A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5 +Ciphertext: 1F55093C234648C5C9C781E8C9FD42C4 +Test: Encrypt +Comment: Set 3, vector 166 +Key: A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6 +Plaintext: A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6 +Ciphertext: BFA2702CF3DAE25705D1DE1CCDBDC49E +Test: Encrypt +Comment: Set 3, vector 167 +Key: A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7 +Plaintext: A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7 +Ciphertext: 3223365425C1ADE87FF766AB048D9ADB +Test: Encrypt +Comment: Set 3, vector 168 +Key: A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8 +Plaintext: A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8 +Ciphertext: 5449889254C565DF3ADDFB7A86A93DA9 +Test: Encrypt +Comment: Set 3, vector 169 +Key: A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9 +Plaintext: A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9 +Ciphertext: 7D21880CCA919B0CE3917A8C598025FA +Test: Encrypt +Comment: Set 3, vector 170 +Key: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +Plaintext: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +Ciphertext: 5EE203A6739E822A54D9678B604EFD4F +Test: Encrypt +Comment: Set 3, vector 171 +Key: ABABABABABABABABABABABABABABABAB +Plaintext: ABABABABABABABABABABABABABABABAB +Ciphertext: 07038EFBEFDE2228F79A6B526306483A +Test: Encrypt +Comment: Set 3, vector 172 +Key: ACACACACACACACACACACACACACACACAC +Plaintext: ACACACACACACACACACACACACACACACAC +Ciphertext: 78447EBF959FFBD120283CE319FF6005 +Test: Encrypt +Comment: Set 3, vector 173 +Key: ADADADADADADADADADADADADADADADAD +Plaintext: ADADADADADADADADADADADADADADADAD +Ciphertext: 76769D40A286F0FD1C1C6F8895000DE8 +Test: Encrypt +Comment: Set 3, vector 174 +Key: AEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAE +Plaintext: AEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAE +Ciphertext: 7E163343CA44FADFAFDE5386CC111437 +Test: Encrypt +Comment: Set 3, vector 175 +Key: AFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAF +Plaintext: AFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAF +Ciphertext: 4B1E7FE684222BF783142B5DC396F61D +Test: Encrypt +Comment: Set 3, vector 176 +Key: B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0 +Plaintext: B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0 +Ciphertext: 4ECF97472658AC941EC99B255CF95535 +Test: Encrypt +Comment: Set 3, vector 177 +Key: B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1 +Plaintext: B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1 +Ciphertext: 23EE9DF24C8DC126A04586EFF27DBEAC +Test: Encrypt +Comment: Set 3, vector 178 +Key: B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2 +Plaintext: B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2 +Ciphertext: 4B06EE28B7769C4318D509F91D691F39 +Test: Encrypt +Comment: Set 3, vector 179 +Key: B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3 +Plaintext: B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3 +Ciphertext: 51994EF8283D1D29711F602A7ACDA3CA +Test: Encrypt +Comment: Set 3, vector 180 +Key: B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 +Plaintext: B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 +Ciphertext: DCBFBE6BE3234BBB61EA68218C89D098 +Test: Encrypt +Comment: Set 3, vector 181 +Key: B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5 +Plaintext: B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5 +Ciphertext: B84BFA0883546D912BD14807253F8892 +Test: Encrypt +Comment: Set 3, vector 182 +Key: B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6 +Plaintext: B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6 +Ciphertext: 90C1745C0DB97E70BA362CF2C1D376DF +Test: Encrypt +Comment: Set 3, vector 183 +Key: B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7 +Plaintext: B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7 +Ciphertext: 064743C2E8293C1B7619F6E6DEC13B04 +Test: Encrypt +Comment: Set 3, vector 184 +Key: B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8 +Plaintext: B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8 +Ciphertext: 38D913C68ABEE287368CBA38D8FE9F0D +Test: Encrypt +Comment: Set 3, vector 185 +Key: B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9 +Plaintext: B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9 +Ciphertext: B2279D520B33258B7DB221ECDD3C4EBB +Test: Encrypt +Comment: Set 3, vector 186 +Key: BABABABABABABABABABABABABABABABA +Plaintext: BABABABABABABABABABABABABABABABA +Ciphertext: 8AD710DDAE51BE6D4BE7ABC5443B7F9B +Test: Encrypt +Comment: Set 3, vector 187 +Key: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB +Plaintext: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB +Ciphertext: 246BA7624BBF83702764CC1B214A0691 +Test: Encrypt +Comment: Set 3, vector 188 +Key: BCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC +Plaintext: BCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC +Ciphertext: 80E0360B03FA048A892CD47BD7FE948A +Test: Encrypt +Comment: Set 3, vector 189 +Key: BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD +Plaintext: BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD +Ciphertext: 09D5D35BB6DBAE0CC9982D6955EAA01C +Test: Encrypt +Comment: Set 3, vector 190 +Key: BEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBE +Plaintext: BEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBE +Ciphertext: EEBDCE2BDE1F25A40184B9C57DD4E49D +Test: Encrypt +Comment: Set 3, vector 191 +Key: BFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBF +Plaintext: BFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBF +Ciphertext: 22706CFCCD2B0BB15ED30E373FA4E945 +Test: Encrypt +Comment: Set 3, vector 192 +Key: C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0 +Plaintext: C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0 +Ciphertext: D2A4EEACB5F41D12908DD1E069EC14DC +Test: Encrypt +Comment: Set 3, vector 193 +Key: C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1 +Plaintext: C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1 +Ciphertext: E78F614BC7F53C9298098DFEE8ADFB09 +Test: Encrypt +Comment: Set 3, vector 194 +Key: C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2 +Plaintext: C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2 +Ciphertext: B53E3865A8B28A36EF3A505102A6329D +Test: Encrypt +Comment: Set 3, vector 195 +Key: C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3 +Plaintext: C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3 +Ciphertext: 9B32AA8673DFFC47CF8C9B35DDE08DD3 +Test: Encrypt +Comment: Set 3, vector 196 +Key: C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4 +Plaintext: C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4 +Ciphertext: CE70E7257E6C8686C7407E22ACB3E94B +Test: Encrypt +Comment: Set 3, vector 197 +Key: C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5 +Plaintext: C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5 +Ciphertext: 677DB939CA272D717DB4B03EFB70F988 +Test: Encrypt +Comment: Set 3, vector 198 +Key: C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 +Plaintext: C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 +Ciphertext: 6582B069058FA86898A3B12B617C27FD +Test: Encrypt +Comment: Set 3, vector 199 +Key: C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7 +Plaintext: C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7 +Ciphertext: 4DFB68486ECF9833FCE74BD663E20768 +Test: Encrypt +Comment: Set 3, vector 200 +Key: C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8 +Plaintext: C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8 +Ciphertext: 6A3840D2780BABD68A73FAC89C4E8D91 +Test: Encrypt +Comment: Set 3, vector 201 +Key: C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9 +Plaintext: C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9 +Ciphertext: 44C79926D7EAB9DE5A2B95472A79A7BC +Test: Encrypt +Comment: Set 3, vector 202 +Key: CACACACACACACACACACACACACACACACA +Plaintext: CACACACACACACACACACACACACACACACA +Ciphertext: 3813E774EE9EFA8FDB2646E607B2A434 +Test: Encrypt +Comment: Set 3, vector 203 +Key: CBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCB +Plaintext: CBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCB +Ciphertext: FCA748E6AE5678A047E806F8FF103A65 +Test: Encrypt +Comment: Set 3, vector 204 +Key: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +Plaintext: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +Ciphertext: 3E3CC9CBE6952AB968FBBEE0C08BF667 +Test: Encrypt +Comment: Set 3, vector 205 +Key: CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD +Plaintext: CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD +Ciphertext: 4FFF3EDC7BCB70E7846DCC4688F9CB3A +Test: Encrypt +Comment: Set 3, vector 206 +Key: CECECECECECECECECECECECECECECECE +Plaintext: CECECECECECECECECECECECECECECECE +Ciphertext: 5728481E82E0DC1631EC611F63B9DD3C +Test: Encrypt +Comment: Set 3, vector 207 +Key: CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF +Plaintext: CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF +Ciphertext: 182BB0D3C52E56248FDA1D343844891D +Test: Encrypt +Comment: Set 3, vector 208 +Key: D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0 +Plaintext: D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0 +Ciphertext: 6B984FC45D0352F3336E7895ECB6DE0E +Test: Encrypt +Comment: Set 3, vector 209 +Key: D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1 +Plaintext: D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1 +Ciphertext: 8DD24A1B23D845E7A6C6D416C7C5B595 +Test: Encrypt +Comment: Set 3, vector 210 +Key: D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2 +Plaintext: D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2 +Ciphertext: 4F4D69B4563373962007945C3197806C +Test: Encrypt +Comment: Set 3, vector 211 +Key: D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3 +Plaintext: D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3 +Ciphertext: DD333390213EB632A51EAE0334A5AEA2 +Test: Encrypt +Comment: Set 3, vector 212 +Key: D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4 +Plaintext: D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4 +Ciphertext: D352ACE83BF6A3BC39EA10D751853009 +Test: Encrypt +Comment: Set 3, vector 213 +Key: D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5 +Plaintext: D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5 +Ciphertext: F2E118276BFCCF6DCDD47E1EAB919BDC +Test: Encrypt +Comment: Set 3, vector 214 +Key: D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6 +Plaintext: D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6 +Ciphertext: 688E877D8B69050F2736D0768571E9A0 +Test: Encrypt +Comment: Set 3, vector 215 +Key: D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7 +Plaintext: D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7 +Ciphertext: DE6F098E56985B7DCFEC52C897F2E735 +Test: Encrypt +Comment: Set 3, vector 216 +Key: D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 +Plaintext: D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 +Ciphertext: 398FA1FE47E3971DA3F9DFD479C9B1AA +Test: Encrypt +Comment: Set 3, vector 217 +Key: D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9 +Plaintext: D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9 +Ciphertext: 6F17B7D7C899B48DAEAD1E90F22AB180 +Test: Encrypt +Comment: Set 3, vector 218 +Key: DADADADADADADADADADADADADADADADA +Plaintext: DADADADADADADADADADADADADADADADA +Ciphertext: D39EBBA5B742F15FCB75D6E656BBF2DA +Test: Encrypt +Comment: Set 3, vector 219 +Key: DBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDB +Plaintext: DBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDB +Ciphertext: 1C6D82247D0BAB18B52CA5293A2C1050 +Test: Encrypt +Comment: Set 3, vector 220 +Key: DCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDC +Plaintext: DCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDC +Ciphertext: B54F248DF57060E40A6A2FA4688C7082 +Test: Encrypt +Comment: Set 3, vector 221 +Key: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD +Plaintext: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD +Ciphertext: 1BB5EB8732CBAB2E3FC334FAAB8BBFBC +Test: Encrypt +Comment: Set 3, vector 222 +Key: DEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDE +Plaintext: DEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDE +Ciphertext: 3734B4B21B50C4740B90FD863EF8627B +Test: Encrypt +Comment: Set 3, vector 223 +Key: DFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDF +Plaintext: DFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDF +Ciphertext: E22E22E60F981D64B7CB341F12F2B362 +Test: Encrypt +Comment: Set 3, vector 224 +Key: E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0 +Plaintext: E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0 +Ciphertext: A2A40EB448D87E39B20460E8CB07515A +Test: Encrypt +Comment: Set 3, vector 225 +Key: E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 +Plaintext: E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 +Ciphertext: 88E6AC929D4D7858015B35D509882C5C +Test: Encrypt +Comment: Set 3, vector 226 +Key: E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2 +Plaintext: E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2 +Ciphertext: FFE4B3B5D0E8229F5428FA2945DBD5EE +Test: Encrypt +Comment: Set 3, vector 227 +Key: E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3 +Plaintext: E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3 +Ciphertext: FCD5F897398A7796A0DAA1809CA7D870 +Test: Encrypt +Comment: Set 3, vector 228 +Key: E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4 +Plaintext: E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4 +Ciphertext: 7F3556B18EC8F04D953DCD27549AF1FC +Test: Encrypt +Comment: Set 3, vector 229 +Key: E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5 +Plaintext: E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5 +Ciphertext: 4433546A8E63AE841CD78B074ED0B91F +Test: Encrypt +Comment: Set 3, vector 230 +Key: E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6 +Plaintext: E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6 +Ciphertext: 2E04671C718BD6C3D115DB2D827A6669 +Test: Encrypt +Comment: Set 3, vector 231 +Key: E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7 +Plaintext: E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7 +Ciphertext: AAE7DA4B977F5EED28F9AF01F8FD47B4 +Test: Encrypt +Comment: Set 3, vector 232 +Key: E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8 +Plaintext: E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8 +Ciphertext: 84AD8F52D51BD3D8E4D8318AF6DB9786 +Test: Encrypt +Comment: Set 3, vector 233 +Key: E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9 +Plaintext: E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9 +Ciphertext: 95EFA65090BD603A1F65A21A43104F79 +Test: Encrypt +Comment: Set 3, vector 234 +Key: EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA +Plaintext: EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA +Ciphertext: 1B83F51E157BBA004CC5BD05986017C8 +Test: Encrypt +Comment: Set 3, vector 235 +Key: EBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEB +Plaintext: EBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEB +Ciphertext: A0C37A641126D5801C4259DFD38E8E8A +Test: Encrypt +Comment: Set 3, vector 236 +Key: ECECECECECECECECECECECECECECECEC +Plaintext: ECECECECECECECECECECECECECECECEC +Ciphertext: 3153A212C2E4727C1032223134342B31 +Test: Encrypt +Comment: Set 3, vector 237 +Key: EDEDEDEDEDEDEDEDEDEDEDEDEDEDEDED +Plaintext: EDEDEDEDEDEDEDEDEDEDEDEDEDEDEDED +Ciphertext: C680D98CAF4409CF31BABCF67352E1D5 +Test: Encrypt +Comment: Set 3, vector 238 +Key: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE +Plaintext: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE +Ciphertext: A7FC85C8459274B836B6F0CBED80AF49 +Test: Encrypt +Comment: Set 3, vector 239 +Key: EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF +Plaintext: EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF +Ciphertext: 5CA8B8A4B8AF15A6184259831B18BBB5 +Test: Encrypt +Comment: Set 3, vector 240 +Key: F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +Plaintext: F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +Ciphertext: F118089963B9AB37776B10B0D4CCEBA4 +Test: Encrypt +Comment: Set 3, vector 241 +Key: F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1 +Plaintext: F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1 +Ciphertext: C233B864E78E9EC272112A34FF7AADBA +Test: Encrypt +Comment: Set 3, vector 242 +Key: F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2 +Plaintext: F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2 +Ciphertext: 2B1C503E7F755A47CC4C57BEB4135B46 +Test: Encrypt +Comment: Set 3, vector 243 +Key: F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 +Plaintext: F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 +Ciphertext: 60D8177BE1044FC5F46DA2B3CAA33102 +Test: Encrypt +Comment: Set 3, vector 244 +Key: F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4 +Plaintext: F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4 +Ciphertext: BA1CBC06977ECE57C5CBC12D99324E00 +Test: Encrypt +Comment: Set 3, vector 245 +Key: F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5 +Plaintext: F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5 +Ciphertext: 01C8561E24A32F53FBAF8864AEE803E3 +Test: Encrypt +Comment: Set 3, vector 246 +Key: F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6 +Plaintext: F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6 +Ciphertext: 797ECFA429014F26B9E62D58B4C1B84E +Test: Encrypt +Comment: Set 3, vector 247 +Key: F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7 +Plaintext: F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7 +Ciphertext: 6AD7FA698A7F3EA8AE13B1DF537BF6EA +Test: Encrypt +Comment: Set 3, vector 248 +Key: F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8 +Plaintext: F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8 +Ciphertext: 49157343BE8B8ED4E59C1AEC3CAB1B94 +Test: Encrypt +Comment: Set 3, vector 249 +Key: F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9 +Plaintext: F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9 +Ciphertext: D33C742DEA4A2C64983766E3068EC200 +Test: Encrypt +Comment: Set 3, vector 250 +Key: FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA +Plaintext: FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA +Ciphertext: 66AE1EAFB45091982E40000BADE002C9 +Test: Encrypt +Comment: Set 3, vector 251 +Key: FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB +Plaintext: FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB +Ciphertext: B6614B0FF5924D0C1EB2C461560BFC01 +Test: Encrypt +Comment: Set 3, vector 252 +Key: FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC +Plaintext: FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC +Ciphertext: 5B4DFBE2BB7666425A858C4769D8DAD0 +Test: Encrypt +Comment: Set 3, vector 253 +Key: FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD +Plaintext: FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD +Ciphertext: 2F142B9044DEC39915ED9347E7B0ED1E +Test: Encrypt +Comment: Set 3, vector 254 +Key: FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE +Plaintext: FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE +Ciphertext: 17E02528D6655CEA7BE6B8548FC2DA65 +Test: Encrypt +Comment: Set 3, vector 255 +Key: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +Plaintext: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +Ciphertext: 25DD9EB9DD67FBC6E8431F56F4FBE651 +Test: Encrypt +Comment: Tests with 192-bit keys +Comment: Set 1, vector 0 +Key: 800000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 1B6220D365C2176C1D41A5826520FCA1 +Test: Encrypt +Comment: Set 1, vector 1 +Key: 400000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0F6DAEEA95CFC8925F23AFA932DF489B +Test: Encrypt +Comment: Set 1, vector 2 +Key: 200000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7330199225AD384F8DD39582D61389BB +Test: Encrypt +Comment: Set 1, vector 3 +Key: 100000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 2CC5A47D5C62F70634E27BA332D37D53 +Test: Encrypt +Comment: Set 1, vector 4 +Key: 080000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: CDF1D23AB15E20AE8E9A2FE380920897 +Test: Encrypt +Comment: Set 1, vector 5 +Key: 040000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: CE995A8AF1FD7E0F5FA07ED654841EEE +Test: Encrypt +Comment: Set 1, vector 6 +Key: 020000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0678BA4335E44354363005F278AF83A4 +Test: Encrypt +Comment: Set 1, vector 7 +Key: 010000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 6162ED593434D738B44D642254066FB4 +Test: Encrypt +Comment: Set 1, vector 8 +Key: 008000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F7F146E61396EC9AB9F7D04BFA6D37F5 +Test: Encrypt +Comment: Set 1, vector 9 +Key: 004000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 8BF96FE41906AF2CC702726B963E56A6 +Test: Encrypt +Comment: Set 1, vector 10 +Key: 002000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B164168F7D6BADBCCBE19B2BCF4EAA91 +Test: Encrypt +Comment: Set 1, vector 11 +Key: 001000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 5A81508260797F7BCFD4E0DB62F5E3A7 +Test: Encrypt +Comment: Set 1, vector 12 +Key: 000800000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 36641169D53E61CB32B97B98C37DF262 +Test: Encrypt +Comment: Set 1, vector 13 +Key: 000400000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: EFFEC137ECEE5D439F8B21ACE1D863F8 +Test: Encrypt +Comment: Set 1, vector 14 +Key: 000200000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7462DEB8C153EECB6C78CE690E764B53 +Test: Encrypt +Comment: Set 1, vector 15 +Key: 000100000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 34F873BD3D6FF62B18C3778B123B15C5 +Test: Encrypt +Comment: Set 1, vector 16 +Key: 000080000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 9850C8E08F952EE1D173B1A4A78686F5 +Test: Encrypt +Comment: Set 1, vector 17 +Key: 000040000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3285534795E8547B68580343DC5BF330 +Test: Encrypt +Comment: Set 1, vector 18 +Key: 000020000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E0495AA72CB3C27233850F3192254232 +Test: Encrypt +Comment: Set 1, vector 19 +Key: 000010000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 33ED350E83B7FE34E74C22A883EC6728 +Test: Encrypt +Comment: Set 1, vector 20 +Key: 000008000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 912D73428CBA7F631AE577854C111C91 +Test: Encrypt +Comment: Set 1, vector 21 +Key: 000004000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 76E747DC49B25D8E6EBE5DE83980AB57 +Test: Encrypt +Comment: Set 1, vector 22 +Key: 000002000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 82A2ED3BE0371C98C176AA7E7DF9FF8D +Test: Encrypt +Comment: Set 1, vector 23 +Key: 000001000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 96282A04DD3405294F9714B396D5219A +Test: Encrypt +Comment: Set 1, vector 24 +Key: 000000800000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 86ECD349003006A6DE29D4AAC1ACE296 +Test: Encrypt +Comment: Set 1, vector 25 +Key: 000000400000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7A9A9F2BBEA203ECE7C9F531B6D41B6A +Test: Encrypt +Comment: Set 1, vector 26 +Key: 000000200000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: BA5FE8CD976DEA118728C2950D325042 +Test: Encrypt +Comment: Set 1, vector 27 +Key: 000000100000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 46F29ADE35C839AE69454CB0C9EEBF71 +Test: Encrypt +Comment: Set 1, vector 28 +Key: 000000080000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E5B83E23535FC32DD8153C46EC894FAD +Test: Encrypt +Comment: Set 1, vector 29 +Key: 000000040000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 877CC6280A8E7740F710AEA535DADFD4 +Test: Encrypt +Comment: Set 1, vector 30 +Key: 000000020000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 284D6EEC89721D40BDCFD260AF4FF052 +Test: Encrypt +Comment: Set 1, vector 31 +Key: 000000010000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 6482ED6C71B60F1ED92B9913B5EAF6B3 +Test: Encrypt +Comment: Set 1, vector 32 +Key: 000000008000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 30135C97C9C23C8C64612D6BB813AD61 +Test: Encrypt +Comment: Set 1, vector 33 +Key: 000000004000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 336F70CF867920BBC00699CA8DBDF6DA +Test: Encrypt +Comment: Set 1, vector 34 +Key: 000000002000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3F4003C9600469670DE0B1B20ED5F33D +Test: Encrypt +Comment: Set 1, vector 35 +Key: 000000001000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 9D5FFEDF7166F74DCAF2D643E2934ABE +Test: Encrypt +Comment: Set 1, vector 36 +Key: 000000000800000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 9BFAC0EEB78A21F006DB6847CC7D7929 +Test: Encrypt +Comment: Set 1, vector 37 +Key: 000000000400000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B64332DC813BE982897C1E14DA808F5D +Test: Encrypt +Comment: Set 1, vector 38 +Key: 000000000200000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: AB8FCEB76C37E5FE5737DA4382F14347 +Test: Encrypt +Comment: Set 1, vector 39 +Key: 000000000100000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: C9C121859975147145AF6CAE313BA00D +Test: Encrypt +Comment: Set 1, vector 40 +Key: 000000000080000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 9B1307BF36B6FF5BA4AD9C6574B63955 +Test: Encrypt +Comment: Set 1, vector 41 +Key: 000000000040000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 8842C3EBB26C1863440D52DC3B26414B +Test: Encrypt +Comment: Set 1, vector 42 +Key: 000000000020000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: ADEADD3E035D591B2197D5B9C9B06ADA +Test: Encrypt +Comment: Set 1, vector 43 +Key: 000000000010000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 4F36AD57F9BA5FB6624E504D0FC2DC93 +Test: Encrypt +Comment: Set 1, vector 44 +Key: 000000000008000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 92A364EEB2D964949210C7FF14BAE7B5 +Test: Encrypt +Comment: Set 1, vector 45 +Key: 000000000004000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: EA027B9653456B8A41910FE19A90FD50 +Test: Encrypt +Comment: Set 1, vector 46 +Key: 000000000002000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 254A41CA04427C9E87F65BB52A0ACF74 +Test: Encrypt +Comment: Set 1, vector 47 +Key: 000000000001000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F935FD318C08AC6CD57A028384FA447B +Test: Encrypt +Comment: Set 1, vector 48 +Key: 000000000000800000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E5BA10850CBCFF8F42FEC0E658685096 +Test: Encrypt +Comment: Set 1, vector 49 +Key: 000000000000400000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 6F145C7015923CE515D78CEF0157CCC6 +Test: Encrypt +Comment: Set 1, vector 50 +Key: 000000000000200000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3A6FCA03EA6DBF6996FD2CE99EC17C31 +Test: Encrypt +Comment: Set 1, vector 51 +Key: 000000000000100000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 21E2ED82498B110EAEAD90F1BBEA03A6 +Test: Encrypt +Comment: Set 1, vector 52 +Key: 000000000000080000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 6B16ED3CBADC3151323891C373C43DFB +Test: Encrypt +Comment: Set 1, vector 53 +Key: 000000000000040000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B621A20E0CA41620C2A483154DB6102C +Test: Encrypt +Comment: Set 1, vector 54 +Key: 000000000000020000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 8C754011BD3B87AA1EB3607B98E6CE86 +Test: Encrypt +Comment: Set 1, vector 55 +Key: 000000000000010000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: FEEE2DFBA1DD3DBF4017B13833117816 +Test: Encrypt +Comment: Set 1, vector 56 +Key: 000000000000008000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 62A9C6CC76519FCF8FAD9EED0552CEB3 +Test: Encrypt +Comment: Set 1, vector 57 +Key: 000000000000004000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: FF822FAFB79035AB813246BA5234D675 +Test: Encrypt +Comment: Set 1, vector 58 +Key: 000000000000002000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F3E17F2406DF31E7074DF97B062396B9 +Test: Encrypt +Comment: Set 1, vector 59 +Key: 000000000000001000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3F4F81B3573B6756ADD3005087EDE501 +Test: Encrypt +Comment: Set 1, vector 60 +Key: 000000000000000800000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 65A03A1A1C44191B73D576B7C75B5C32 +Test: Encrypt +Comment: Set 1, vector 61 +Key: 000000000000000400000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B08EBB2097DA76C34E2D8A869DCD3D7D +Test: Encrypt +Comment: Set 1, vector 62 +Key: 000000000000000200000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: BA7B88E1B1FCFA03C3DBB2EDE047F5DC +Test: Encrypt +Comment: Set 1, vector 63 +Key: 000000000000000100000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 1B3CB3884C12691CC66202EDB0838106 +Test: Encrypt +Comment: Set 1, vector 64 +Key: 000000000000000080000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 4A85BE25546958B1E91801A35C7386E2 +Test: Encrypt +Comment: Set 1, vector 65 +Key: 000000000000000040000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F14CAACDD919872396DBCDCBEF9A384C +Test: Encrypt +Comment: Set 1, vector 66 +Key: 000000000000000020000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 23B0D4FC870309DFEF7AFC04C46AF26A +Test: Encrypt +Comment: Set 1, vector 67 +Key: 000000000000000010000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: C93604723C3DBBC66AFF87AB1864C76C +Test: Encrypt +Comment: Set 1, vector 68 +Key: 000000000000000008000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 6C14E822857BA0983AAC42995D973092 +Test: Encrypt +Comment: Set 1, vector 69 +Key: 000000000000000004000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 700AFEA175DBEAE688F90B8D32990560 +Test: Encrypt +Comment: Set 1, vector 70 +Key: 000000000000000002000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 54AE9EFA09FC70A852212752B83AF1F2 +Test: Encrypt +Comment: Set 1, vector 71 +Key: 000000000000000001000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 2474EF8E660333FC9763E137DDB1AA1F +Test: Encrypt +Comment: Set 1, vector 72 +Key: 000000000000000000800000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E52ECE1281186644B6A2228A89BD2304 +Test: Encrypt +Comment: Set 1, vector 73 +Key: 000000000000000000400000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 610A02ECEC1B5BA0C6EC7CE8D6197722 +Test: Encrypt +Comment: Set 1, vector 74 +Key: 000000000000000000200000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 8A8AB3DA5CE37E1D68B496F110E4F941 +Test: Encrypt +Comment: Set 1, vector 75 +Key: 000000000000000000100000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 6961F3A7E6550753C55E4C03FA7869E9 +Test: Encrypt +Comment: Set 1, vector 76 +Key: 000000000000000000080000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: D8F149C207FAD4480BA2FC609BEB4471 +Test: Encrypt +Comment: Set 1, vector 77 +Key: 000000000000000000040000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: DE9DC95336F2088935881DD57C0A4B98 +Test: Encrypt +Comment: Set 1, vector 78 +Key: 000000000000000000020000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: DC4EA3B0F76439DB8847FE61C1A64F7A +Test: Encrypt +Comment: Set 1, vector 79 +Key: 000000000000000000010000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 21D4802EB72232AD2B0B46C50C98445B +Test: Encrypt +Comment: Set 1, vector 80 +Key: 000000000000000000008000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: D6C32522B546BAC316E5F3A07F83FFE6 +Test: Encrypt +Comment: Set 1, vector 81 +Key: 000000000000000000004000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 4B07B02C86B579A0C68D916DF8A1EB76 +Test: Encrypt +Comment: Set 1, vector 82 +Key: 000000000000000000002000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 060B15735C978DF9F4F3ED503B95D6C3 +Test: Encrypt +Comment: Set 1, vector 83 +Key: 000000000000000000001000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3040B3C9C560C968FE14664E3496D5D1 +Test: Encrypt +Comment: Set 1, vector 84 +Key: 000000000000000000000800000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 8971CFB236598BBD46E47E172B0690F7 +Test: Encrypt +Comment: Set 1, vector 85 +Key: 000000000000000000000400000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 8D7FAB4985A0BAC4CAEE341972D49CF4 +Test: Encrypt +Comment: Set 1, vector 86 +Key: 000000000000000000000200000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: ED29003D83CB7D7747C17A8691323021 +Test: Encrypt +Comment: Set 1, vector 87 +Key: 000000000000000000000100000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 98EBFDA32C99438F0A549B7BFAAC0635 +Test: Encrypt +Comment: Set 1, vector 88 +Key: 000000000000000000000080000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: A59AB8EAF03BCDFD7CB0A9650E59F27B +Test: Encrypt +Comment: Set 1, vector 89 +Key: 000000000000000000000040000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 71422297CE93952D46FFC27530D6255D +Test: Encrypt +Comment: Set 1, vector 90 +Key: 000000000000000000000020000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 519E2607543C3AFE49190EBCA12ADBBC +Test: Encrypt +Comment: Set 1, vector 91 +Key: 000000000000000000000010000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 8989C908C50E008E70EA5B897DC3544C +Test: Encrypt +Comment: Set 1, vector 92 +Key: 000000000000000000000008000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 981C174277F29F8DD06E1D4C97D9816F +Test: Encrypt +Comment: Set 1, vector 93 +Key: 000000000000000000000004000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0279DEC16A532E160AA5B4FF7682F696 +Test: Encrypt +Comment: Set 1, vector 94 +Key: 000000000000000000000002000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: C3BFFB31FCB0A61188DE9AA606CB286C +Test: Encrypt +Comment: Set 1, vector 95 +Key: 000000000000000000000001000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 5C1C4966B387A41D52F83BBF322D25DF +Test: Encrypt +Comment: Set 1, vector 96 +Key: 000000000000000000000000800000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 6602ECC6AF62EF1EB4D17E2487A64F7A +Test: Encrypt +Comment: Set 1, vector 97 +Key: 000000000000000000000000400000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 2DA725366BD7774BA235183CC9B273B4 +Test: Encrypt +Comment: Set 1, vector 98 +Key: 000000000000000000000000200000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 71B29CF87C313F0B89B75251EFC4FF7F +Test: Encrypt +Comment: Set 1, vector 99 +Key: 000000000000000000000000100000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 4D9BDBCBA04C54AEAA7F48470428ECA2 +Test: Encrypt +Comment: Set 1, vector 100 +Key: 000000000000000000000000080000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: C6BC53A3C6D6C8A6F12B97B151BFBB3F +Test: Encrypt +Comment: Set 1, vector 101 +Key: 000000000000000000000000040000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: FD3E8D6732BBC2AA13F03F9AB0BCEC14 +Test: Encrypt +Comment: Set 1, vector 102 +Key: 000000000000000000000000020000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7D5ED8FEF289FF7F8953278E0A0297A1 +Test: Encrypt +Comment: Set 1, vector 103 +Key: 000000000000000000000000010000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 84A20023EF5E31771802E8A2FFBA485B +Test: Encrypt +Comment: Set 1, vector 104 +Key: 000000000000000000000000008000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7BD6E573AE79F0FA9FE38ECF6011D756 +Test: Encrypt +Comment: Set 1, vector 105 +Key: 000000000000000000000000004000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: EB58EA6B6DE1282A7BB9EA1A2254A542 +Test: Encrypt +Comment: Set 1, vector 106 +Key: 000000000000000000000000002000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 30A697E325C4D3BEC8E69A2DAD2AE5BB +Test: Encrypt +Comment: Set 1, vector 107 +Key: 000000000000000000000000001000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3205F6FEAA38500AC74BE66FEDF3231E +Test: Encrypt +Comment: Set 1, vector 108 +Key: 000000000000000000000000000800000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 83C007676041E81B836886ABED807A71 +Test: Encrypt +Comment: Set 1, vector 109 +Key: 000000000000000000000000000400000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 24B33B3138855437CC11D3792A1FD00F +Test: Encrypt +Comment: Set 1, vector 110 +Key: 000000000000000000000000000200000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 26324D7E2C055366910464699D73608A +Test: Encrypt +Comment: Set 1, vector 111 +Key: 000000000000000000000000000100000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F9A94A959AE7CD2A9D5FB7274703906B +Test: Encrypt +Comment: Set 1, vector 112 +Key: 000000000000000000000000000080000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: AD13D85E47EFC76B67ED25791E119A5C +Test: Encrypt +Comment: Set 1, vector 113 +Key: 000000000000000000000000000040000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 5FB689176B296F2E579FC69A18FA07EB +Test: Encrypt +Comment: Set 1, vector 114 +Key: 000000000000000000000000000020000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 936DFBA0A052A299C195F34A66C0CEDF +Test: Encrypt +Comment: Set 1, vector 115 +Key: 000000000000000000000000000010000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 486C03278BB30F26D25AE0D6348C9491 +Test: Encrypt +Comment: Set 1, vector 116 +Key: 000000000000000000000000000008000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: FCE14E6CE2073B5E8D1572A1EC1BD502 +Test: Encrypt +Comment: Set 1, vector 117 +Key: 000000000000000000000000000004000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 5F15B8A64EDBF0E55C3B8BB67BC9B2E1 +Test: Encrypt +Comment: Set 1, vector 118 +Key: 000000000000000000000000000002000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7BDC738A342891C7BE06E87E12F71418 +Test: Encrypt +Comment: Set 1, vector 119 +Key: 000000000000000000000000000001000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 31C6FEDABBC8C8AD64C27505F02BC7CC +Test: Encrypt +Comment: Set 1, vector 120 +Key: 000000000000000000000000000000800000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 33CCD97EB8C3C06B7BCD16659E1F9837 +Test: Encrypt +Comment: Set 1, vector 121 +Key: 000000000000000000000000000000400000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 12C3089895D4A1C1D03DB0071F88AB1B +Test: Encrypt +Comment: Set 1, vector 122 +Key: 000000000000000000000000000000200000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 8EB4796C7F7C3B0858750EBE3BAA335C +Test: Encrypt +Comment: Set 1, vector 123 +Key: 000000000000000000000000000000100000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 67169AF324151E92C6B7C31687B83783 +Test: Encrypt +Comment: Set 1, vector 124 +Key: 000000000000000000000000000000080000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: AB0E10564D41594B55CE3D5B088D93B4 +Test: Encrypt +Comment: Set 1, vector 125 +Key: 000000000000000000000000000000040000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 45228986B08E63728239ADC9C249E475 +Test: Encrypt +Comment: Set 1, vector 126 +Key: 000000000000000000000000000000020000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: CA7E48D5A4CD15984CA9EF99EC789EFD +Test: Encrypt +Comment: Set 1, vector 127 +Key: 000000000000000000000000000000010000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B4DD56FF85F7ABBEB9E0F5AE6B0E491D +Test: Encrypt +Comment: Set 1, vector 128 +Key: 000000000000000000000000000000008000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 044BE36D2F5A3D0FEA74443538F55393 +Test: Encrypt +Comment: Set 1, vector 129 +Key: 000000000000000000000000000000004000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 531EC401FB7C3BFADF64BB08E0DD9992 +Test: Encrypt +Comment: Set 1, vector 130 +Key: 000000000000000000000000000000002000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: EA8D6B6963EC2267050F8CF5D1D1D939 +Test: Encrypt +Comment: Set 1, vector 131 +Key: 000000000000000000000000000000001000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: CF5D7F27462FF7415D4E5ECBAEE0797C +Test: Encrypt +Comment: Set 1, vector 132 +Key: 000000000000000000000000000000000800000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: DF28B8322D4B8606FF3EFF09D39697B0 +Test: Encrypt +Comment: Set 1, vector 133 +Key: 000000000000000000000000000000000400000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 956EF889AAB218E21FAF8E9CC2AE41F9 +Test: Encrypt +Comment: Set 1, vector 134 +Key: 000000000000000000000000000000000200000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: AD0CF3C46F420E96B876DD55515B4B80 +Test: Encrypt +Comment: Set 1, vector 135 +Key: 000000000000000000000000000000000100000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: EC8620D3B9B456633AD174573CF82ABD +Test: Encrypt +Comment: Set 1, vector 136 +Key: 000000000000000000000000000000000080000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: A7CC6C810C1433B8D130594A48A36F69 +Test: Encrypt +Comment: Set 1, vector 137 +Key: 000000000000000000000000000000000040000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B02C5AF13D523A2A62E9F3829F9E3364 +Test: Encrypt +Comment: Set 1, vector 138 +Key: 000000000000000000000000000000000020000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 5AC8368EC6150F08CC2C44DBA8A9D84F +Test: Encrypt +Comment: Set 1, vector 139 +Key: 000000000000000000000000000000000010000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3BD51735D6087217EEF17B40750D701F +Test: Encrypt +Comment: Set 1, vector 140 +Key: 000000000000000000000000000000000008000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 330CC76A5529364B08F722C6206214E7 +Test: Encrypt +Comment: Set 1, vector 141 +Key: 000000000000000000000000000000000004000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 13CA2152CB81267D8429670A8D983592 +Test: Encrypt +Comment: Set 1, vector 142 +Key: 000000000000000000000000000000000002000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3943D67CE79CB8519EB9A5D1021988ED +Test: Encrypt +Comment: Set 1, vector 143 +Key: 000000000000000000000000000000000001000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 642858D825E8640718ABE6174BD04A32 +Test: Encrypt +Comment: Set 1, vector 144 +Key: 000000000000000000000000000000000000800000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F22616DE88A4CCBF97CF2DB709237EC7 +Test: Encrypt +Comment: Set 1, vector 145 +Key: 000000000000000000000000000000000000400000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B90D7F6BF0D9FC11A01F2B33194806DB +Test: Encrypt +Comment: Set 1, vector 146 +Key: 000000000000000000000000000000000000200000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: C161D350DC897B210D0D0CE8CE78F4B4 +Test: Encrypt +Comment: Set 1, vector 147 +Key: 000000000000000000000000000000000000100000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 66E46482150E7CF9BCBE60AF7BCA6892 +Test: Encrypt +Comment: Set 1, vector 148 +Key: 000000000000000000000000000000000000080000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B17C912E085D8854F220555EB0FA89BD +Test: Encrypt +Comment: Set 1, vector 149 +Key: 000000000000000000000000000000000000040000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 6FD6A99633FBD3A6D238CADF37824AD2 +Test: Encrypt +Comment: Set 1, vector 150 +Key: 000000000000000000000000000000000000020000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 9DE6D76D9A7E4AAB7A58EECE0E153D73 +Test: Encrypt +Comment: Set 1, vector 151 +Key: 000000000000000000000000000000000000010000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B4716A7DB10E3B8D1475C7EFB929F93A +Test: Encrypt +Comment: Set 1, vector 152 +Key: 000000000000000000000000000000000000008000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3D0F65F16AD143FB2FABDF4DFE621398 +Test: Encrypt +Comment: Set 1, vector 153 +Key: 000000000000000000000000000000000000004000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 249F1415D963DE146F4141C200B81D1D +Test: Encrypt +Comment: Set 1, vector 154 +Key: 000000000000000000000000000000000000002000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 454CD7040ED3851C3894F6259CE0D3FE +Test: Encrypt +Comment: Set 1, vector 155 +Key: 000000000000000000000000000000000000001000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 4D613EE6FA78A573ECBE989A64193E0C +Test: Encrypt +Comment: Set 1, vector 156 +Key: 000000000000000000000000000000000000000800000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B39384E429291B9C22005BC9B3FF2DEF +Test: Encrypt +Comment: Set 1, vector 157 +Key: 000000000000000000000000000000000000000400000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 957D0B27740C952E45DB97C8814F49C0 +Test: Encrypt +Comment: Set 1, vector 158 +Key: 000000000000000000000000000000000000000200000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 2879F58F238865D877D8C276CA9E9102 +Test: Encrypt +Comment: Set 1, vector 159 +Key: 000000000000000000000000000000000000000100000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: EA5B920037608FC9D51F39488D4666F7 +Test: Encrypt +Comment: Set 1, vector 160 +Key: 000000000000000000000000000000000000000080000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7659A705ABCA25205078541E713088BC +Test: Encrypt +Comment: Set 1, vector 161 +Key: 000000000000000000000000000000000000000040000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 47E340BB8BF2E8E1015BEFB68C7B1100 +Test: Encrypt +Comment: Set 1, vector 162 +Key: 000000000000000000000000000000000000000020000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 777E3E572CA33076B2CB34226CC70158 +Test: Encrypt +Comment: Set 1, vector 163 +Key: 000000000000000000000000000000000000000010000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 1FEC7C6719C7CA2E9A981851C5CEE204 +Test: Encrypt +Comment: Set 1, vector 164 +Key: 000000000000000000000000000000000000000008000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 9AF07DABE083EFDA75708A36AEB74CAF +Test: Encrypt +Comment: Set 1, vector 165 +Key: 000000000000000000000000000000000000000004000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 5D1482F8EF9CB18911BB7F78BC3B89FC +Test: Encrypt +Comment: Set 1, vector 166 +Key: 000000000000000000000000000000000000000002000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 5242753E01D470DD8C2B73A986BA009F +Test: Encrypt +Comment: Set 1, vector 167 +Key: 000000000000000000000000000000000000000001000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 83AE5BC112B73AB7978D13DD534B770B +Test: Encrypt +Comment: Set 1, vector 168 +Key: 000000000000000000000000000000000000000000800000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 848EB7330A82B91D36FBEFF6E6CE1347 +Test: Encrypt +Comment: Set 1, vector 169 +Key: 000000000000000000000000000000000000000000400000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F1B14465EFFD3E14DD1BAC6E0FA4E5BD +Test: Encrypt +Comment: Set 1, vector 170 +Key: 000000000000000000000000000000000000000000200000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 5ACD25AA05AFD21F43F6A51709FD0B6A +Test: Encrypt +Comment: Set 1, vector 171 +Key: 000000000000000000000000000000000000000000100000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 12321AEFA53F1503E3A473F729388CBD +Test: Encrypt +Comment: Set 1, vector 172 +Key: 000000000000000000000000000000000000000000080000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 1602DBA20E2ACFDDCC78390B473B322B +Test: Encrypt +Comment: Set 1, vector 173 +Key: 000000000000000000000000000000000000000000040000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 14C1853C3CF3CDFCE3799D5C130138EC +Test: Encrypt +Comment: Set 1, vector 174 +Key: 000000000000000000000000000000000000000000020000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: DC17F9E8236350BDC285F9B2F88F670F +Test: Encrypt +Comment: Set 1, vector 175 +Key: 000000000000000000000000000000000000000000010000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: ABA03FEE8133DD4ED9B8194B643E20CE +Test: Encrypt +Comment: Set 1, vector 176 +Key: 000000000000000000000000000000000000000000008000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 5822E80530C7CECCE4F56CF1691B386F +Test: Encrypt +Comment: Set 1, vector 177 +Key: 000000000000000000000000000000000000000000004000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 25CFA6F1B9BE5E14DFAF87A44B3B2E3D +Test: Encrypt +Comment: Set 1, vector 178 +Key: 000000000000000000000000000000000000000000002000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 5ED866CBC298B4DEE46C1A02F958F1F5 +Test: Encrypt +Comment: Set 1, vector 179 +Key: 000000000000000000000000000000000000000000001000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: BD2B63C026EB0E58D26ED16D2ED64A3E +Test: Encrypt +Comment: Set 1, vector 180 +Key: 000000000000000000000000000000000000000000000800 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 9FFCFF9CF9E1483BC7971888246AF9FE +Test: Encrypt +Comment: Set 1, vector 181 +Key: 000000000000000000000000000000000000000000000400 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 367C409AEE218E02DEAC8751698BA1B8 +Test: Encrypt +Comment: Set 1, vector 182 +Key: 000000000000000000000000000000000000000000000200 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 248E3A3C0360B44C512A9AC3CAAEC21B +Test: Encrypt +Comment: Set 1, vector 183 +Key: 000000000000000000000000000000000000000000000100 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 49B47C542CA396260B53A34372985612 +Test: Encrypt +Comment: Set 1, vector 184 +Key: 000000000000000000000000000000000000000000000080 +Plaintext: 00000000000000000000000000000000 +Ciphertext: CE35FDBDBE086EA8A501A4571925A95F +Test: Encrypt +Comment: Set 1, vector 185 +Key: 000000000000000000000000000000000000000000000040 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 873442FAE891B0767220742B84A32A4E +Test: Encrypt +Comment: Set 1, vector 186 +Key: 000000000000000000000000000000000000000000000020 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 2C90E17AD13E4E84686BC5B369F0FA8F +Test: Encrypt +Comment: Set 1, vector 187 +Key: 000000000000000000000000000000000000000000000010 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0E7AAAA67D8593A9DFC55083B48B381A +Test: Encrypt +Comment: Set 1, vector 188 +Key: 000000000000000000000000000000000000000000000008 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 1D8B58EE529AB17B10AC15D0E6E7ECB2 +Test: Encrypt +Comment: Set 1, vector 189 +Key: 000000000000000000000000000000000000000000000004 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 1C10FAC725B905AD93B6F4B2430A8D18 +Test: Encrypt +Comment: Set 1, vector 190 +Key: 000000000000000000000000000000000000000000000002 +Plaintext: 00000000000000000000000000000000 +Ciphertext: D36CF625EE94AB029CD23253C77C0E15 +Test: Encrypt +Comment: Set 1, vector 191 +Key: 000000000000000000000000000000000000000000000001 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E37577F71E0E643C4D3F55219ABA1394 +Test: Encrypt +Comment: Set 2, vector 0 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 80000000000000000000000000000000 +Ciphertext: 3EB6CC5618EFC98455B5992050D474E7 +Test: Encrypt +Comment: Set 2, vector 1 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 40000000000000000000000000000000 +Ciphertext: A2C645044CBC74DE5A4A161C6B2E98B9 +Test: Encrypt +Comment: Set 2, vector 2 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 20000000000000000000000000000000 +Ciphertext: 36A9A8C164BD90D4972AB1BE56C96A0B +Test: Encrypt +Comment: Set 2, vector 3 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 10000000000000000000000000000000 +Ciphertext: 38965592D728F9B765140C0A36A1BCCD +Test: Encrypt +Comment: Set 2, vector 4 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 08000000000000000000000000000000 +Ciphertext: 94CDECA78E10827914A49B5AE7F15643 +Test: Encrypt +Comment: Set 2, vector 5 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 04000000000000000000000000000000 +Ciphertext: 11C0DF672B45CDCD311EB86A7560EDA1 +Test: Encrypt +Comment: Set 2, vector 6 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 02000000000000000000000000000000 +Ciphertext: 030CAA9B8DE6F8AB88882F9596D9B1B4 +Test: Encrypt +Comment: Set 2, vector 7 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 01000000000000000000000000000000 +Ciphertext: FA02C8D1CDDD08B1FE3650DBD8E43C4F +Test: Encrypt +Comment: Set 2, vector 8 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00800000000000000000000000000000 +Ciphertext: 10ACEC25736340600D712338357C7FD4 +Test: Encrypt +Comment: Set 2, vector 9 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00400000000000000000000000000000 +Ciphertext: BBEF172E9E18679C6546EA2D9357BDD1 +Test: Encrypt +Comment: Set 2, vector 10 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00200000000000000000000000000000 +Ciphertext: 707CF6F582F5921765DBC6E1C79C45B6 +Test: Encrypt +Comment: Set 2, vector 11 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00100000000000000000000000000000 +Ciphertext: 3E9206A85F9FE99CD5538FA196E58147 +Test: Encrypt +Comment: Set 2, vector 12 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00080000000000000000000000000000 +Ciphertext: 6758B118659E9BB40BB7DC8C3D15ECEC +Test: Encrypt +Comment: Set 2, vector 13 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00040000000000000000000000000000 +Ciphertext: 9BCA6C88B928C1B0F57F99866583A9BC +Test: Encrypt +Comment: Set 2, vector 14 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00020000000000000000000000000000 +Ciphertext: 53D60CF8CA0B41B3991EF892917FA26F +Test: Encrypt +Comment: Set 2, vector 15 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00010000000000000000000000000000 +Ciphertext: 49E438685E189FB95791C655FBF40B3B +Test: Encrypt +Comment: Set 2, vector 16 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00008000000000000000000000000000 +Ciphertext: 6BFE6661C074077EF95DC499CA30A6B9 +Test: Encrypt +Comment: Set 2, vector 17 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00004000000000000000000000000000 +Ciphertext: FE82A6754DD56ACBD1895F8257597B74 +Test: Encrypt +Comment: Set 2, vector 18 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00002000000000000000000000000000 +Ciphertext: AF4551CFCEAEF2AEE1933C4AB5F036F5 +Test: Encrypt +Comment: Set 2, vector 19 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00001000000000000000000000000000 +Ciphertext: 5175E53EA4CA77E085363B2948B77B17 +Test: Encrypt +Comment: Set 2, vector 20 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000800000000000000000000000000 +Ciphertext: 19F544B2B2AAE4AF00DE2853F83349A5 +Test: Encrypt +Comment: Set 2, vector 21 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000400000000000000000000000000 +Ciphertext: 45A4379AC855738F6FEE3AFFBB2D839F +Test: Encrypt +Comment: Set 2, vector 22 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000200000000000000000000000000 +Ciphertext: 73A390407DD07D4ABEB299A5051A8DD1 +Test: Encrypt +Comment: Set 2, vector 23 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000100000000000000000000000000 +Ciphertext: 923B1E3525217E5C7A41CE3BCAE7C083 +Test: Encrypt +Comment: Set 2, vector 24 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000080000000000000000000000000 +Ciphertext: F58098D6E68E975C922B05354C0E2094 +Test: Encrypt +Comment: Set 2, vector 25 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000040000000000000000000000000 +Ciphertext: 371631601CE2BED9B7706FA4254BBAE5 +Test: Encrypt +Comment: Set 2, vector 26 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000020000000000000000000000000 +Ciphertext: 794F34CD64B44095BAB5C470B36E60BE +Test: Encrypt +Comment: Set 2, vector 27 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000010000000000000000000000000 +Ciphertext: 1A4CE8CBFEDB4F64B1A64D926B9BE3A1 +Test: Encrypt +Comment: Set 2, vector 28 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000008000000000000000000000000 +Ciphertext: 11C391C85F8FCF72EB03E1C4CC40B529 +Test: Encrypt +Comment: Set 2, vector 29 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000004000000000000000000000000 +Ciphertext: 9D8ADDC48EC36BB449234C7C06BEDC0F +Test: Encrypt +Comment: Set 2, vector 30 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000002000000000000000000000000 +Ciphertext: 952A1FAD7FAEA148FA31B50C244CF5C4 +Test: Encrypt +Comment: Set 2, vector 31 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000001000000000000000000000000 +Ciphertext: 613E5E9BBBF1B9943B3B5CBD3E69C98F +Test: Encrypt +Comment: Set 2, vector 32 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000800000000000000000000000 +Ciphertext: 5ABF9CB600BB50DB64211DE2DEAEEDBA +Test: Encrypt +Comment: Set 2, vector 33 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000400000000000000000000000 +Ciphertext: 14697658FDA5B1F14C3303F5951CAE70 +Test: Encrypt +Comment: Set 2, vector 34 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000200000000000000000000000 +Ciphertext: 2A29179C05F2F5F5909A34130B92BB25 +Test: Encrypt +Comment: Set 2, vector 35 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000100000000000000000000000 +Ciphertext: 60A9DAB8068CC085F3B9853D0C1FCF07 +Test: Encrypt +Comment: Set 2, vector 36 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000080000000000000000000000 +Ciphertext: D625356ACCE7B9F874754AE52FD1C7BF +Test: Encrypt +Comment: Set 2, vector 37 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000040000000000000000000000 +Ciphertext: 31196A29DAA0A41E982819C26AF0567A +Test: Encrypt +Comment: Set 2, vector 38 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000020000000000000000000000 +Ciphertext: D1763FC019D77CC930BFF2A56F7C9364 +Test: Encrypt +Comment: Set 2, vector 39 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000010000000000000000000000 +Ciphertext: BBC9D3C96666B01D0C33CC067ADDA228 +Test: Encrypt +Comment: Set 2, vector 40 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000008000000000000000000000 +Ciphertext: 4FC9284574F433DD6C5ADEAB6DC64A06 +Test: Encrypt +Comment: Set 2, vector 41 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000004000000000000000000000 +Ciphertext: 7176B9E3628380ADDCF02493DB254B01 +Test: Encrypt +Comment: Set 2, vector 42 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000002000000000000000000000 +Ciphertext: C6B124A17B3AB55A983DC2B6E8253FF1 +Test: Encrypt +Comment: Set 2, vector 43 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000001000000000000000000000 +Ciphertext: 5853A6B6AB0FC47DEBA33526B628DF6E +Test: Encrypt +Comment: Set 2, vector 44 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000800000000000000000000 +Ciphertext: 416945C1D1902238C42955CFF166D705 +Test: Encrypt +Comment: Set 2, vector 45 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000400000000000000000000 +Ciphertext: 2478F40DC7B7FA98E59DA21F1D2140F9 +Test: Encrypt +Comment: Set 2, vector 46 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000200000000000000000000 +Ciphertext: 6A912316499FBECA17D1683EAF79FDC9 +Test: Encrypt +Comment: Set 2, vector 47 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000100000000000000000000 +Ciphertext: 8A41DB2271FD345BC1DDE61A427E4E3E +Test: Encrypt +Comment: Set 2, vector 48 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000080000000000000000000 +Ciphertext: B6C62C6A14D2276C8FE8D1062C1E8080 +Test: Encrypt +Comment: Set 2, vector 49 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000040000000000000000000 +Ciphertext: D23F90169810210A45BD9B8681B24C34 +Test: Encrypt +Comment: Set 2, vector 50 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000020000000000000000000 +Ciphertext: EDB2A77815A074B50D88C6C2B15AF814 +Test: Encrypt +Comment: Set 2, vector 51 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000010000000000000000000 +Ciphertext: 2D6D81C8FDD2C7D5B98317488846969D +Test: Encrypt +Comment: Set 2, vector 52 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000008000000000000000000 +Ciphertext: 92F2805613A82EE25568B32ED7550DCC +Test: Encrypt +Comment: Set 2, vector 53 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000004000000000000000000 +Ciphertext: E321480A1DE5F36040F1FD170F24802B +Test: Encrypt +Comment: Set 2, vector 54 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000002000000000000000000 +Ciphertext: 3188FFADE35652067E6E2228130762D6 +Test: Encrypt +Comment: Set 2, vector 55 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000001000000000000000000 +Ciphertext: B3A3A43D68A82EC54B5D437346375584 +Test: Encrypt +Comment: Set 2, vector 56 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000800000000000000000 +Ciphertext: 023ECF3BD9FEB4891366ABE45EC1728B +Test: Encrypt +Comment: Set 2, vector 57 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000400000000000000000 +Ciphertext: 50D8160676748E1718A030F4F512C1C2 +Test: Encrypt +Comment: Set 2, vector 58 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000200000000000000000 +Ciphertext: 30DF20541978D9C96D43D609DEF39C00 +Test: Encrypt +Comment: Set 2, vector 59 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000100000000000000000 +Ciphertext: BA1AA1682750C0CEB2A87E1A46A7CE0E +Test: Encrypt +Comment: Set 2, vector 60 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000080000000000000000 +Ciphertext: 03AC8261D8F98C90B9CE9C9E47A39AA5 +Test: Encrypt +Comment: Set 2, vector 61 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000040000000000000000 +Ciphertext: 4C6C2FDC2693F2A43EAEB180AD8190F8 +Test: Encrypt +Comment: Set 2, vector 62 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000020000000000000000 +Ciphertext: B65D2C8CEE12BB4FA127356632CB0ECA +Test: Encrypt +Comment: Set 2, vector 63 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000010000000000000000 +Ciphertext: 6D785867F379BCE03580ED9DE83C0EFD +Test: Encrypt +Comment: Set 2, vector 64 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000008000000000000000 +Ciphertext: D2B25B3EECB454DCE070D11C408D73B2 +Test: Encrypt +Comment: Set 2, vector 65 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000004000000000000000 +Ciphertext: 8035FF5E625955D6328F570D53188C0C +Test: Encrypt +Comment: Set 2, vector 66 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000002000000000000000 +Ciphertext: A8BECF868B0D964E04012BE5F8121A9C +Test: Encrypt +Comment: Set 2, vector 67 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000001000000000000000 +Ciphertext: AA76DF2E83C0D31ECFE66A62E16A91D3 +Test: Encrypt +Comment: Set 2, vector 68 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000800000000000000 +Ciphertext: BAA324177EA5AF61ADBD27F594297278 +Test: Encrypt +Comment: Set 2, vector 69 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000400000000000000 +Ciphertext: 40BBEB33938AFA9BD566991B53B0FDA7 +Test: Encrypt +Comment: Set 2, vector 70 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000200000000000000 +Ciphertext: 6F58204780BEA9102506C477CBB3C8FE +Test: Encrypt +Comment: Set 2, vector 71 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000100000000000000 +Ciphertext: D296BCA9261A3410E47FA289BD70B955 +Test: Encrypt +Comment: Set 2, vector 72 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000080000000000000 +Ciphertext: 4C57FB4234A64462C6D441A782723777 +Test: Encrypt +Comment: Set 2, vector 73 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000040000000000000 +Ciphertext: 33478DE51DBDA949E17CB82373DAF866 +Test: Encrypt +Comment: Set 2, vector 74 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000020000000000000 +Ciphertext: 7CC11B9A6A9E2CE13D3596686C624AF0 +Test: Encrypt +Comment: Set 2, vector 75 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000010000000000000 +Ciphertext: 0C55ACA2BDA80E8F84A3879FF077802A +Test: Encrypt +Comment: Set 2, vector 76 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000008000000000000 +Ciphertext: 885B84843BADC6501CBDCBEA4386AB7F +Test: Encrypt +Comment: Set 2, vector 77 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000004000000000000 +Ciphertext: DCF23815FEF1697B0618E205B637648A +Test: Encrypt +Comment: Set 2, vector 78 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000002000000000000 +Ciphertext: BF5EBE09157E65743AAD033473B0DFED +Test: Encrypt +Comment: Set 2, vector 79 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000001000000000000 +Ciphertext: 1E9E5E1032307B75915E9BD48205FEB8 +Test: Encrypt +Comment: Set 2, vector 80 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000800000000000 +Ciphertext: 0EB8AC09A10303A7CE9762C1B029F0E0 +Test: Encrypt +Comment: Set 2, vector 81 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000400000000000 +Ciphertext: 2A42627713BFC603A88AD1D66292B80C +Test: Encrypt +Comment: Set 2, vector 82 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000200000000000 +Ciphertext: D7E9512485B9E5E409FB51E26D269795 +Test: Encrypt +Comment: Set 2, vector 83 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000100000000000 +Ciphertext: 57CC59F8B92D73E1B38EEE405A8EC12F +Test: Encrypt +Comment: Set 2, vector 84 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000080000000000 +Ciphertext: 161783F5FFC9A383E36B80A2032A71F1 +Test: Encrypt +Comment: Set 2, vector 85 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000040000000000 +Ciphertext: F5B24CE20FFD8702AC63F9C844BC5730 +Test: Encrypt +Comment: Set 2, vector 86 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000020000000000 +Ciphertext: 440930601D4013076587D882A1958280 +Test: Encrypt +Comment: Set 2, vector 87 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000010000000000 +Ciphertext: AEA4C3F9E520651C5FE38B915423843F +Test: Encrypt +Comment: Set 2, vector 88 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000008000000000 +Ciphertext: E300D7417C4F547DBCD5FC84E3833A7B +Test: Encrypt +Comment: Set 2, vector 89 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000004000000000 +Ciphertext: 5543860CE9247B38E8D0E7B216C0B5A5 +Test: Encrypt +Comment: Set 2, vector 90 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000002000000000 +Ciphertext: C20449053BF90C899899EE02794DB3C5 +Test: Encrypt +Comment: Set 2, vector 91 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000001000000000 +Ciphertext: AC0CB3B34AC32244CF196AE49E94D380 +Test: Encrypt +Comment: Set 2, vector 92 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000800000000 +Ciphertext: 0CDF3F25852287E3BAFAF490DE18D125 +Test: Encrypt +Comment: Set 2, vector 93 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000400000000 +Ciphertext: 583BB44512CE75268F72E6BC6682901B +Test: Encrypt +Comment: Set 2, vector 94 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000200000000 +Ciphertext: 217140522F0C505FDAC4BFDE6E9D9A81 +Test: Encrypt +Comment: Set 2, vector 95 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000100000000 +Ciphertext: CFA59EB13DDD780A2EAEF89E83737C9A +Test: Encrypt +Comment: Set 2, vector 96 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000080000000 +Ciphertext: 75E473CCD4D116426753B44900D919A6 +Test: Encrypt +Comment: Set 2, vector 97 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000040000000 +Ciphertext: E15E4627F7F8A3F09424D3D5CAC1C777 +Test: Encrypt +Comment: Set 2, vector 98 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000020000000 +Ciphertext: B83E20A23802D8755A2E850242B64EEF +Test: Encrypt +Comment: Set 2, vector 99 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000010000000 +Ciphertext: E6790AF3911360F28FD17886DD311F88 +Test: Encrypt +Comment: Set 2, vector 100 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000008000000 +Ciphertext: 0A6304DF33E409C8A21E1C19187183FF +Test: Encrypt +Comment: Set 2, vector 101 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000004000000 +Ciphertext: 51966561DA7ED5F30130B55CD108B5BE +Test: Encrypt +Comment: Set 2, vector 102 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000002000000 +Ciphertext: 0ECA40693BF4CB41FDD15BCFD8C9D9B9 +Test: Encrypt +Comment: Set 2, vector 103 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000001000000 +Ciphertext: 8731B42742ADBA2D89C9BA90EBD4E42A +Test: Encrypt +Comment: Set 2, vector 104 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000800000 +Ciphertext: BE4C6C18AA231E9BB13909242CC92EE3 +Test: Encrypt +Comment: Set 2, vector 105 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000400000 +Ciphertext: 39AC45537E9AFDC6C8BDD4204039A218 +Test: Encrypt +Comment: Set 2, vector 106 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000200000 +Ciphertext: AEA354F16E1E8EECEB5A98D88418B1A0 +Test: Encrypt +Comment: Set 2, vector 107 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000100000 +Ciphertext: 4F5D37D7D0DC7714E62BE4A0331DB07B +Test: Encrypt +Comment: Set 2, vector 108 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000080000 +Ciphertext: 9603F03C3CAA8C2F0ECFBA1374891007 +Test: Encrypt +Comment: Set 2, vector 109 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000040000 +Ciphertext: C58768944996884B46A8FFDDB9AB87EF +Test: Encrypt +Comment: Set 2, vector 110 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000020000 +Ciphertext: 3BCCF2396A97FC1C0CFFFB6ED41716DB +Test: Encrypt +Comment: Set 2, vector 111 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000010000 +Ciphertext: DC299278DCA45AC1B6B08ED4B62D9BC9 +Test: Encrypt +Comment: Set 2, vector 112 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000008000 +Ciphertext: E195AECA31E10241BD0EC4AC5418A25D +Test: Encrypt +Comment: Set 2, vector 113 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000004000 +Ciphertext: B397A4983ED647A0EB806ACDFE7BCB34 +Test: Encrypt +Comment: Set 2, vector 114 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000002000 +Ciphertext: BC8F7224B0447E8A1CF0F5506A060F3C +Test: Encrypt +Comment: Set 2, vector 115 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000001000 +Ciphertext: FFD3ED02E7F64A5D6B37A9DC5E531646 +Test: Encrypt +Comment: Set 2, vector 116 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000800 +Ciphertext: BC6019EB208B7AF8EFA6AE7B4CA0556B +Test: Encrypt +Comment: Set 2, vector 117 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000400 +Ciphertext: D2915AE2779F8F70E17CE953C6C1A380 +Test: Encrypt +Comment: Set 2, vector 118 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000200 +Ciphertext: B2AA4B1ED2285C9DA4088B6E9681C690 +Test: Encrypt +Comment: Set 2, vector 119 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000100 +Ciphertext: BE0D64EA88A3FF27C8DFCE13F13A4E1F +Test: Encrypt +Comment: Set 2, vector 120 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000080 +Ciphertext: D7629F1DD395A985AF9497F6ACB4EDA1 +Test: Encrypt +Comment: Set 2, vector 121 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000040 +Ciphertext: 33FDF72DA1D8815DE2DBE81D97DDC6F8 +Test: Encrypt +Comment: Set 2, vector 122 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000020 +Ciphertext: D35742045F3DF8D184D6CC58EB9DE323 +Test: Encrypt +Comment: Set 2, vector 123 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000010 +Ciphertext: DE6469D10C044ED53CFEB523C8DF34A2 +Test: Encrypt +Comment: Set 2, vector 124 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000008 +Ciphertext: 2FAEAC3A41CCEABA8140BDA9C7AC7740 +Test: Encrypt +Comment: Set 2, vector 125 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000004 +Ciphertext: 7BA6691787BF0C526F3697E2ED659B0D +Test: Encrypt +Comment: Set 2, vector 126 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000002 +Ciphertext: 8F9C0AA2549714C88BB2665E8AF86D41 +Test: Encrypt +Comment: Set 2, vector 127 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000001 +Ciphertext: BA9AE89FDDCE4B51131E17C4D65CE587 +Test: Encrypt +Comment: Set 3, vector 0 +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 56E1E129CA5C02C7F9AC6AFDEF86ADC3 +Test: Encrypt +Comment: Set 3, vector 1 +Key: 010101010101010101010101010101010101010101010101 +Plaintext: 01010101010101010101010101010101 +Ciphertext: 8F764397C10BE84BA876CEEFA4225BFF +Test: Encrypt +Comment: Set 3, vector 2 +Key: 020202020202020202020202020202020202020202020202 +Plaintext: 02020202020202020202020202020202 +Ciphertext: 60B00674BFD444D07B5A19851E6151CD +Test: Encrypt +Comment: Set 3, vector 3 +Key: 030303030303030303030303030303030303030303030303 +Plaintext: 03030303030303030303030303030303 +Ciphertext: CF431D70E25D5450B9979C52E4ECF590 +Test: Encrypt +Comment: Set 3, vector 4 +Key: 040404040404040404040404040404040404040404040404 +Plaintext: 04040404040404040404040404040404 +Ciphertext: 81B26FF4F6B4377CC555873504B3A38B +Test: Encrypt +Comment: Set 3, vector 5 +Key: 050505050505050505050505050505050505050505050505 +Plaintext: 05050505050505050505050505050505 +Ciphertext: 8C864C445E6B9312E6F3843C53BF7870 +Test: Encrypt +Comment: Set 3, vector 6 +Key: 060606060606060606060606060606060606060606060606 +Plaintext: 06060606060606060606060606060606 +Ciphertext: 28C1EABB23C2A04E7A37BB0EF42D45A2 +Test: Encrypt +Comment: Set 3, vector 7 +Key: 070707070707070707070707070707070707070707070707 +Plaintext: 07070707070707070707070707070707 +Ciphertext: 0068C08827CBD904A3C0AF89A35CD8E6 +Test: Encrypt +Comment: Set 3, vector 8 +Key: 080808080808080808080808080808080808080808080808 +Plaintext: 08080808080808080808080808080808 +Ciphertext: A2AA1C6693DC2B70D75C9B39B9B214D0 +Test: Encrypt +Comment: Set 3, vector 9 +Key: 090909090909090909090909090909090909090909090909 +Plaintext: 09090909090909090909090909090909 +Ciphertext: 0423A756A133734C66944536033B978C +Test: Encrypt +Comment: Set 3, vector 10 +Key: 0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A +Plaintext: 0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A +Ciphertext: 279B7FA09352F4194B2C33089267BD2E +Test: Encrypt +Comment: Set 3, vector 11 +Key: 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +Plaintext: 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +Ciphertext: 7788EEE46AC2927434A93D3B5D295DF3 +Test: Encrypt +Comment: Set 3, vector 12 +Key: 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C +Plaintext: 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C +Ciphertext: 3A2D0C1F30AE1E50A61102D2DF5BEAE5 +Test: Encrypt +Comment: Set 3, vector 13 +Key: 0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D +Plaintext: 0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D +Ciphertext: 320FB708B47319484538CD73F8773526 +Test: Encrypt +Comment: Set 3, vector 14 +Key: 0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E +Plaintext: 0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E +Ciphertext: 6213EB688C8CDA5152A65BFC007BCAEA +Test: Encrypt +Comment: Set 3, vector 15 +Key: 0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F +Plaintext: 0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F +Ciphertext: D1904ACDB021DDCCCBE436CA7B5A4264 +Test: Encrypt +Comment: Set 3, vector 16 +Key: 101010101010101010101010101010101010101010101010 +Plaintext: 10101010101010101010101010101010 +Ciphertext: A907BFDAEEF8C81D05855235E8D3BE08 +Test: Encrypt +Comment: Set 3, vector 17 +Key: 111111111111111111111111111111111111111111111111 +Plaintext: 11111111111111111111111111111111 +Ciphertext: DB23D9326A998A4CB06AE04A8C592217 +Test: Encrypt +Comment: Set 3, vector 18 +Key: 121212121212121212121212121212121212121212121212 +Plaintext: 12121212121212121212121212121212 +Ciphertext: 472427C234EAE3082E84F493C9559792 +Test: Encrypt +Comment: Set 3, vector 19 +Key: 131313131313131313131313131313131313131313131313 +Plaintext: 13131313131313131313131313131313 +Ciphertext: EE4E318D27820F691BD3BDA9617561A0 +Test: Encrypt +Comment: Set 3, vector 20 +Key: 141414141414141414141414141414141414141414141414 +Plaintext: 14141414141414141414141414141414 +Ciphertext: 221E909D7B259C098480DBDE71BCF9BF +Test: Encrypt +Comment: Set 3, vector 21 +Key: 151515151515151515151515151515151515151515151515 +Plaintext: 15151515151515151515151515151515 +Ciphertext: 8702C6A150F2DD2E1736F09518C1A267 +Test: Encrypt +Comment: Set 3, vector 22 +Key: 161616161616161616161616161616161616161616161616 +Plaintext: 16161616161616161616161616161616 +Ciphertext: 7E8DAEBBA15C7B9705B501998F61CC6E +Test: Encrypt +Comment: Set 3, vector 23 +Key: 171717171717171717171717171717171717171717171717 +Plaintext: 17171717171717171717171717171717 +Ciphertext: 3DD555C7277FA156330D05CD621394D5 +Test: Encrypt +Comment: Set 3, vector 24 +Key: 181818181818181818181818181818181818181818181818 +Plaintext: 18181818181818181818181818181818 +Ciphertext: E5575CDC315F1C244441E6D1DE25ED20 +Test: Encrypt +Comment: Set 3, vector 25 +Key: 191919191919191919191919191919191919191919191919 +Plaintext: 19191919191919191919191919191919 +Ciphertext: 434859EB42087F83B9849DC23ABB7C1D +Test: Encrypt +Comment: Set 3, vector 26 +Key: 1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A +Plaintext: 1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A +Ciphertext: 1EA1A5CC662DCA0B56B2BBF560A1B032 +Test: Encrypt +Comment: Set 3, vector 27 +Key: 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B +Plaintext: 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B +Ciphertext: A3AC0CD9342242A72005F8E6DBF50DE8 +Test: Encrypt +Comment: Set 3, vector 28 +Key: 1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C +Plaintext: 1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C +Ciphertext: AF6251A285EBEA9408315822F2072D86 +Test: Encrypt +Comment: Set 3, vector 29 +Key: 1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D +Plaintext: 1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D +Ciphertext: FA084220DB82A88E6D7B6E7849550183 +Test: Encrypt +Comment: Set 3, vector 30 +Key: 1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E +Plaintext: 1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E +Ciphertext: E7AABEAA3F669E0D963A19C3BDE43676 +Test: Encrypt +Comment: Set 3, vector 31 +Key: 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F +Plaintext: 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F +Ciphertext: ED7C11A689A72FF834A777013DBEC50A +Test: Encrypt +Comment: Set 3, vector 32 +Key: 202020202020202020202020202020202020202020202020 +Plaintext: 20202020202020202020202020202020 +Ciphertext: 87F8EA30332036F17CEAC0097CE33BC1 +Test: Encrypt +Comment: Set 3, vector 33 +Key: 212121212121212121212121212121212121212121212121 +Plaintext: 21212121212121212121212121212121 +Ciphertext: E83CC178B21703D1BDFA0A1350A587F3 +Test: Encrypt +Comment: Set 3, vector 34 +Key: 222222222222222222222222222222222222222222222222 +Plaintext: 22222222222222222222222222222222 +Ciphertext: 581CF260A93B67E27BBA6D6D68C645B6 +Test: Encrypt +Comment: Set 3, vector 35 +Key: 232323232323232323232323232323232323232323232323 +Plaintext: 23232323232323232323232323232323 +Ciphertext: D7155FD4BABA5DAA1E0576BAF4BB3BDE +Test: Encrypt +Comment: Set 3, vector 36 +Key: 242424242424242424242424242424242424242424242424 +Plaintext: 24242424242424242424242424242424 +Ciphertext: 0C2382377892DC0CA4B1C7753CDB2753 +Test: Encrypt +Comment: Set 3, vector 37 +Key: 252525252525252525252525252525252525252525252525 +Plaintext: 25252525252525252525252525252525 +Ciphertext: 9E568ACFE44E1926BE207D25107EBD90 +Test: Encrypt +Comment: Set 3, vector 38 +Key: 262626262626262626262626262626262626262626262626 +Plaintext: 26262626262626262626262626262626 +Ciphertext: 1F9C7FEF0BA7D4C38555B957FA9FDAC8 +Test: Encrypt +Comment: Set 3, vector 39 +Key: 272727272727272727272727272727272727272727272727 +Plaintext: 27272727272727272727272727272727 +Ciphertext: 2C00730AAB18247D4F79C8BA0107E759 +Test: Encrypt +Comment: Set 3, vector 40 +Key: 282828282828282828282828282828282828282828282828 +Plaintext: 28282828282828282828282828282828 +Ciphertext: 26150BB68C5529903D3624CB8F36D717 +Test: Encrypt +Comment: Set 3, vector 41 +Key: 292929292929292929292929292929292929292929292929 +Plaintext: 29292929292929292929292929292929 +Ciphertext: C6F9CD75F9DC3DF5C945E028038660AB +Test: Encrypt +Comment: Set 3, vector 42 +Key: 2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A +Plaintext: 2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A +Ciphertext: 9D90F692A1149E3E7F19BE419038F42F +Test: Encrypt +Comment: Set 3, vector 43 +Key: 2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B +Plaintext: 2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B +Ciphertext: 9981F6F8C071F4CAF3E25884B8749FD3 +Test: Encrypt +Comment: Set 3, vector 44 +Key: 2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C +Plaintext: 2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C +Ciphertext: 62957FC449C78B7EABA9C41B335F731E +Test: Encrypt +Comment: Set 3, vector 45 +Key: 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D +Plaintext: 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D +Ciphertext: 265E17BD08B2E34BC879D5BC801D1217 +Test: Encrypt +Comment: Set 3, vector 46 +Key: 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E +Plaintext: 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E +Ciphertext: 55BBE8CE99907AC77D4F009EABA6B8D9 +Test: Encrypt +Comment: Set 3, vector 47 +Key: 2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F +Plaintext: 2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F +Ciphertext: EECB495C2F81243857D0A1A8919F9C7E +Test: Encrypt +Comment: Set 3, vector 48 +Key: 303030303030303030303030303030303030303030303030 +Plaintext: 30303030303030303030303030303030 +Ciphertext: E3BA996DF81895C86E30500CE9F7ED01 +Test: Encrypt +Comment: Set 3, vector 49 +Key: 313131313131313131313131313131313131313131313131 +Plaintext: 31313131313131313131313131313131 +Ciphertext: E507914B7CDDB2A3A915EB5663CE43CE +Test: Encrypt +Comment: Set 3, vector 50 +Key: 323232323232323232323232323232323232323232323232 +Plaintext: 32323232323232323232323232323232 +Ciphertext: AA2E53FC2D073DE62554691F507B23FF +Test: Encrypt +Comment: Set 3, vector 51 +Key: 333333333333333333333333333333333333333333333333 +Plaintext: 33333333333333333333333333333333 +Ciphertext: 875707D7E4FA8028D878DFB8338160FF +Test: Encrypt +Comment: Set 3, vector 52 +Key: 343434343434343434343434343434343434343434343434 +Plaintext: 34343434343434343434343434343434 +Ciphertext: 1158285A6787F8B6500E9FB046D88FB7 +Test: Encrypt +Comment: Set 3, vector 53 +Key: 353535353535353535353535353535353535353535353535 +Plaintext: 35353535353535353535353535353535 +Ciphertext: 6BFF4FB554ADD3F4321E6BA6029CD48A +Test: Encrypt +Comment: Set 3, vector 54 +Key: 363636363636363636363636363636363636363636363636 +Plaintext: 36363636363636363636363636363636 +Ciphertext: 8F2077CE672419A3AE15CA8800D5ACF8 +Test: Encrypt +Comment: Set 3, vector 55 +Key: 373737373737373737373737373737373737373737373737 +Plaintext: 37373737373737373737373737373737 +Ciphertext: 80ECE69E3EEBD391FCAEA8B3B38578D9 +Test: Encrypt +Comment: Set 3, vector 56 +Key: 383838383838383838383838383838383838383838383838 +Plaintext: 38383838383838383838383838383838 +Ciphertext: A23A2ADDE21BDB44EF99072331FA8EAB +Test: Encrypt +Comment: Set 3, vector 57 +Key: 393939393939393939393939393939393939393939393939 +Plaintext: 39393939393939393939393939393939 +Ciphertext: 8E41065415264354D4DC276F6ED582B9 +Test: Encrypt +Comment: Set 3, vector 58 +Key: 3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A +Plaintext: 3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A +Ciphertext: D591D51BA578836C7D3945991FD0184A +Test: Encrypt +Comment: Set 3, vector 59 +Key: 3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B +Plaintext: 3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B +Ciphertext: B88105C11F9FFCA9037E1F90FAE1C61E +Test: Encrypt +Comment: Set 3, vector 60 +Key: 3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C +Plaintext: 3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C +Ciphertext: F8A1A047994B4363028BC1B3B6339954 +Test: Encrypt +Comment: Set 3, vector 61 +Key: 3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D +Plaintext: 3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D +Ciphertext: EFB57CEA359E1F9F68729B156BEBDCB8 +Test: Encrypt +Comment: Set 3, vector 62 +Key: 3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E +Plaintext: 3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E +Ciphertext: 2323D15570873D4E5616CDDC466B1D34 +Test: Encrypt +Comment: Set 3, vector 63 +Key: 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F +Plaintext: 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F +Ciphertext: 842C7B6C67BB38B508558058531B37FE +Test: Encrypt +Comment: Set 3, vector 64 +Key: 404040404040404040404040404040404040404040404040 +Plaintext: 40404040404040404040404040404040 +Ciphertext: A2C32EA499E41A248565253BACC11E3B +Test: Encrypt +Comment: Set 3, vector 65 +Key: 414141414141414141414141414141414141414141414141 +Plaintext: 41414141414141414141414141414141 +Ciphertext: CF72033A0BA3E03A8B1E336F85100489 +Test: Encrypt +Comment: Set 3, vector 66 +Key: 424242424242424242424242424242424242424242424242 +Plaintext: 42424242424242424242424242424242 +Ciphertext: 0A194208C1B722A5719C14231EE4C532 +Test: Encrypt +Comment: Set 3, vector 67 +Key: 434343434343434343434343434343434343434343434343 +Plaintext: 43434343434343434343434343434343 +Ciphertext: 7365018F7A2564165EC162F948C4824A +Test: Encrypt +Comment: Set 3, vector 68 +Key: 444444444444444444444444444444444444444444444444 +Plaintext: 44444444444444444444444444444444 +Ciphertext: 20AC87CE21C47D99D6D2202B0C62E52D +Test: Encrypt +Comment: Set 3, vector 69 +Key: 454545454545454545454545454545454545454545454545 +Plaintext: 45454545454545454545454545454545 +Ciphertext: 72D32F7C4D03529C7DBF6865E36E7C84 +Test: Encrypt +Comment: Set 3, vector 70 +Key: 464646464646464646464646464646464646464646464646 +Plaintext: 46464646464646464646464646464646 +Ciphertext: 18E88EF941A7D1793B8D545323CCBD7E +Test: Encrypt +Comment: Set 3, vector 71 +Key: 474747474747474747474747474747474747474747474747 +Plaintext: 47474747474747474747474747474747 +Ciphertext: C87B12CD28646842FCE0C8658EA8A6C9 +Test: Encrypt +Comment: Set 3, vector 72 +Key: 484848484848484848484848484848484848484848484848 +Plaintext: 48484848484848484848484848484848 +Ciphertext: 03347AC4B4D0AE9C208B1B12802E6562 +Test: Encrypt +Comment: Set 3, vector 73 +Key: 494949494949494949494949494949494949494949494949 +Plaintext: 49494949494949494949494949494949 +Ciphertext: A5F9E726E53A74C9CF59E7CBBCE507D1 +Test: Encrypt +Comment: Set 3, vector 74 +Key: 4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A +Plaintext: 4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A +Ciphertext: 228C852461BBB0BB12B3F9192311DFDD +Test: Encrypt +Comment: Set 3, vector 75 +Key: 4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B +Plaintext: 4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B +Ciphertext: DFD5B30B1401FBE49EA0C725E64B91A3 +Test: Encrypt +Comment: Set 3, vector 76 +Key: 4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C +Plaintext: 4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C +Ciphertext: 38D59DD18C98488451070B28F91A15C0 +Test: Encrypt +Comment: Set 3, vector 77 +Key: 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D +Plaintext: 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D +Ciphertext: E6A73709A37C7B00484BD54EED3A6128 +Test: Encrypt +Comment: Set 3, vector 78 +Key: 4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E +Plaintext: 4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E +Ciphertext: 12A6AD3ED9A3BA4FBA285B64D4823706 +Test: Encrypt +Comment: Set 3, vector 79 +Key: 4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F +Plaintext: 4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F +Ciphertext: CCB3FFAD253207DFB312A8B4FE0F390D +Test: Encrypt +Comment: Set 3, vector 80 +Key: 505050505050505050505050505050505050505050505050 +Plaintext: 50505050505050505050505050505050 +Ciphertext: A1C7DFA83502CE5558242F83CC12BF82 +Test: Encrypt +Comment: Set 3, vector 81 +Key: 515151515151515151515151515151515151515151515151 +Plaintext: 51515151515151515151515151515151 +Ciphertext: C9C8FCD1E4E482AF47555FEA823DE62A +Test: Encrypt +Comment: Set 3, vector 82 +Key: 525252525252525252525252525252525252525252525252 +Plaintext: 52525252525252525252525252525252 +Ciphertext: 5F9DD3265B6B043BF4CE8E11A3DAE4E1 +Test: Encrypt +Comment: Set 3, vector 83 +Key: 535353535353535353535353535353535353535353535353 +Plaintext: 53535353535353535353535353535353 +Ciphertext: 79D02BFAD35C67C8586694A068662F1D +Test: Encrypt +Comment: Set 3, vector 84 +Key: 545454545454545454545454545454545454545454545454 +Plaintext: 54545454545454545454545454545454 +Ciphertext: 361AC03A4827F590A5DDE28A5FFF723A +Test: Encrypt +Comment: Set 3, vector 85 +Key: 555555555555555555555555555555555555555555555555 +Plaintext: 55555555555555555555555555555555 +Ciphertext: 1758AC2E8DDE2126621AEB5759FC93D0 +Test: Encrypt +Comment: Set 3, vector 86 +Key: 565656565656565656565656565656565656565656565656 +Plaintext: 56565656565656565656565656565656 +Ciphertext: 14422A052A86DC0033B70F77D46A7E3C +Test: Encrypt +Comment: Set 3, vector 87 +Key: 575757575757575757575757575757575757575757575757 +Plaintext: 57575757575757575757575757575757 +Ciphertext: 154457A732BC11F0A4C43BEC607B9B91 +Test: Encrypt +Comment: Set 3, vector 88 +Key: 585858585858585858585858585858585858585858585858 +Plaintext: 58585858585858585858585858585858 +Ciphertext: 789BBC53CBE8A7D6119F61C8DC5DAEAB +Test: Encrypt +Comment: Set 3, vector 89 +Key: 595959595959595959595959595959595959595959595959 +Plaintext: 59595959595959595959595959595959 +Ciphertext: 6F8CDA92BF849BE59858544689DA2ACE +Test: Encrypt +Comment: Set 3, vector 90 +Key: 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A +Plaintext: 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A +Ciphertext: CCA696D494AF8877C0753106D5AD07A6 +Test: Encrypt +Comment: Set 3, vector 91 +Key: 5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B +Plaintext: 5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B +Ciphertext: E76884CA9F00DCF95BBB15C5FBB26D1C +Test: Encrypt +Comment: Set 3, vector 92 +Key: 5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C +Plaintext: 5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C +Ciphertext: CD3FA7BC9EC9EC0B0CF4F5A82A98550E +Test: Encrypt +Comment: Set 3, vector 93 +Key: 5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D +Plaintext: 5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D +Ciphertext: BC2FB535DC0D8C86682E32AC3761F299 +Test: Encrypt +Comment: Set 3, vector 94 +Key: 5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E +Plaintext: 5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E +Ciphertext: AB19152E1788D8B2878357484832BB27 +Test: Encrypt +Comment: Set 3, vector 95 +Key: 5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F +Plaintext: 5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F +Ciphertext: 87D1D7E297CED2C6606A171794FE1BB2 +Test: Encrypt +Comment: Set 3, vector 96 +Key: 606060606060606060606060606060606060606060606060 +Plaintext: 60606060606060606060606060606060 +Ciphertext: 6BF6F1728474F1050F712A0FF3F59319 +Test: Encrypt +Comment: Set 3, vector 97 +Key: 616161616161616161616161616161616161616161616161 +Plaintext: 61616161616161616161616161616161 +Ciphertext: 46646FF0ED8A8EDB395BA4B3DC97A35F +Test: Encrypt +Comment: Set 3, vector 98 +Key: 626262626262626262626262626262626262626262626262 +Plaintext: 62626262626262626262626262626262 +Ciphertext: F558C5F67CDF59374F5426D5846A622E +Test: Encrypt +Comment: Set 3, vector 99 +Key: 636363636363636363636363636363636363636363636363 +Plaintext: 63636363636363636363636363636363 +Ciphertext: E06CC0A3436C80F5F0271ACFC8F535D3 +Test: Encrypt +Comment: Set 3, vector 100 +Key: 646464646464646464646464646464646464646464646464 +Plaintext: 64646464646464646464646464646464 +Ciphertext: 903AA2EA9F99C3CCDD1EF1CD906FC800 +Test: Encrypt +Comment: Set 3, vector 101 +Key: 656565656565656565656565656565656565656565656565 +Plaintext: 65656565656565656565656565656565 +Ciphertext: EAE1010E86CF45476CEB180E78608841 +Test: Encrypt +Comment: Set 3, vector 102 +Key: 666666666666666666666666666666666666666666666666 +Plaintext: 66666666666666666666666666666666 +Ciphertext: 341F33B7FB7C5807BFB4C2C497565817 +Test: Encrypt +Comment: Set 3, vector 103 +Key: 676767676767676767676767676767676767676767676767 +Plaintext: 67676767676767676767676767676767 +Ciphertext: 4DA345AB1B3F7575F8D01BED5C17AF26 +Test: Encrypt +Comment: Set 3, vector 104 +Key: 686868686868686868686868686868686868686868686868 +Plaintext: 68686868686868686868686868686868 +Ciphertext: 1613C2DE21E7082312BF414C88310FAB +Test: Encrypt +Comment: Set 3, vector 105 +Key: 696969696969696969696969696969696969696969696969 +Plaintext: 69696969696969696969696969696969 +Ciphertext: 474D73001BD4BF9A9B79CFF79198E2F3 +Test: Encrypt +Comment: Set 3, vector 106 +Key: 6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A +Plaintext: 6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A +Ciphertext: 9C487E0BFB6FE07C521C663D03F175CF +Test: Encrypt +Comment: Set 3, vector 107 +Key: 6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B +Plaintext: 6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B +Ciphertext: 39F5672BEFCFCC072F292D47AD481DC7 +Test: Encrypt +Comment: Set 3, vector 108 +Key: 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C +Plaintext: 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C +Ciphertext: D9B86F02C3CB07CEF53834924A01DF14 +Test: Encrypt +Comment: Set 3, vector 109 +Key: 6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D +Plaintext: 6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D +Ciphertext: B42C9F4A33C5425FB20425889ECFFB9D +Test: Encrypt +Comment: Set 3, vector 110 +Key: 6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E +Plaintext: 6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E +Ciphertext: 832D535E3B4C40113C82AE10A7E1B78A +Test: Encrypt +Comment: Set 3, vector 111 +Key: 6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F +Plaintext: 6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F +Ciphertext: E9A8F63AAF1B1FFF05CFEB7E22E519DF +Test: Encrypt +Comment: Set 3, vector 112 +Key: 707070707070707070707070707070707070707070707070 +Plaintext: 70707070707070707070707070707070 +Ciphertext: C61B4EF13F07576701B1018AC9F01863 +Test: Encrypt +Comment: Set 3, vector 113 +Key: 717171717171717171717171717171717171717171717171 +Plaintext: 71717171717171717171717171717171 +Ciphertext: B098DBE07C3528931F14D40AC9F99ACC +Test: Encrypt +Comment: Set 3, vector 114 +Key: 727272727272727272727272727272727272727272727272 +Plaintext: 72727272727272727272727272727272 +Ciphertext: 3FCC0182E96BC01863EB161967D6482A +Test: Encrypt +Comment: Set 3, vector 115 +Key: 737373737373737373737373737373737373737373737373 +Plaintext: 73737373737373737373737373737373 +Ciphertext: D8F20E80F4AC4666066B0E3F1966C8DA +Test: Encrypt +Comment: Set 3, vector 116 +Key: 747474747474747474747474747474747474747474747474 +Plaintext: 74747474747474747474747474747474 +Ciphertext: 4E96D8CC1A34E3C38C37B5339CF26A5D +Test: Encrypt +Comment: Set 3, vector 117 +Key: 757575757575757575757575757575757575757575757575 +Plaintext: 75757575757575757575757575757575 +Ciphertext: 266EDB14B89857636C0F8E8C7D2FACD8 +Test: Encrypt +Comment: Set 3, vector 118 +Key: 767676767676767676767676767676767676767676767676 +Plaintext: 76767676767676767676767676767676 +Ciphertext: 1D060BD61CFA82764CE4DF283FCB2278 +Test: Encrypt +Comment: Set 3, vector 119 +Key: 777777777777777777777777777777777777777777777777 +Plaintext: 77777777777777777777777777777777 +Ciphertext: 4734355A933BFC1F2918CDF1A4E2BAAE +Test: Encrypt +Comment: Set 3, vector 120 +Key: 787878787878787878787878787878787878787878787878 +Plaintext: 78787878787878787878787878787878 +Ciphertext: DADBACBB42FEB35635A8DEBBFA93F5BA +Test: Encrypt +Comment: Set 3, vector 121 +Key: 797979797979797979797979797979797979797979797979 +Plaintext: 79797979797979797979797979797979 +Ciphertext: 8BB5C2E0B44B986EF523870C41721B7D +Test: Encrypt +Comment: Set 3, vector 122 +Key: 7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A +Plaintext: 7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A +Ciphertext: F66844E5DC500F43FF95E05965BAFD63 +Test: Encrypt +Comment: Set 3, vector 123 +Key: 7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B +Plaintext: 7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B +Ciphertext: ECC75A2BE7E27481907621A1796DC821 +Test: Encrypt +Comment: Set 3, vector 124 +Key: 7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C +Plaintext: 7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C +Ciphertext: D195666137F49B67F80EBC8C3ED824BF +Test: Encrypt +Comment: Set 3, vector 125 +Key: 7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D +Plaintext: 7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D +Ciphertext: 2F1ACC482BE5DEFD3EC1AD1F3A064A60 +Test: Encrypt +Comment: Set 3, vector 126 +Key: 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E +Plaintext: 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E +Ciphertext: 5FDDFA05A7F72D294DC386260DC59009 +Test: Encrypt +Comment: Set 3, vector 127 +Key: 7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F +Plaintext: 7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F +Ciphertext: FE94D733BABEB5A5382C2816311E515E +Test: Encrypt +Comment: Set 3, vector 128 +Key: 808080808080808080808080808080808080808080808080 +Plaintext: 80808080808080808080808080808080 +Ciphertext: F602BA7F515B082983B8F7A27F92408F +Test: Encrypt +Comment: Set 3, vector 129 +Key: 818181818181818181818181818181818181818181818181 +Plaintext: 81818181818181818181818181818181 +Ciphertext: 48E95062B889D83CC72767E303329710 +Test: Encrypt +Comment: Set 3, vector 130 +Key: 828282828282828282828282828282828282828282828282 +Plaintext: 82828282828282828282828282828282 +Ciphertext: 0D98319B8ED1E612F063591AAFA95962 +Test: Encrypt +Comment: Set 3, vector 131 +Key: 838383838383838383838383838383838383838383838383 +Plaintext: 83838383838383838383838383838383 +Ciphertext: 6D987B21F8072C09514C711819BDF42D +Test: Encrypt +Comment: Set 3, vector 132 +Key: 848484848484848484848484848484848484848484848484 +Plaintext: 84848484848484848484848484848484 +Ciphertext: 56C6CA23BC6A52C9967D70C6471A0788 +Test: Encrypt +Comment: Set 3, vector 133 +Key: 858585858585858585858585858585858585858585858585 +Plaintext: 85858585858585858585858585858585 +Ciphertext: 03C1004551B9B74D96CC3F9F7D11B04A +Test: Encrypt +Comment: Set 3, vector 134 +Key: 868686868686868686868686868686868686868686868686 +Plaintext: 86868686868686868686868686868686 +Ciphertext: 6356481250E8D52A0D922985BB2BED27 +Test: Encrypt +Comment: Set 3, vector 135 +Key: 878787878787878787878787878787878787878787878787 +Plaintext: 87878787878787878787878787878787 +Ciphertext: BC51A66892A956F44BF75168E935720E +Test: Encrypt +Comment: Set 3, vector 136 +Key: 888888888888888888888888888888888888888888888888 +Plaintext: 88888888888888888888888888888888 +Ciphertext: 73FAAAFB0517BD4D459A250E2CA4F017 +Test: Encrypt +Comment: Set 3, vector 137 +Key: 898989898989898989898989898989898989898989898989 +Plaintext: 89898989898989898989898989898989 +Ciphertext: 160C7D6510CCEB35318629FFFE1E8BA7 +Test: Encrypt +Comment: Set 3, vector 138 +Key: 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A +Plaintext: 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A +Ciphertext: 785ECC6F1A9415EBB05A4990786865A5 +Test: Encrypt +Comment: Set 3, vector 139 +Key: 8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B +Plaintext: 8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B +Ciphertext: 210498B4AC4D909CC7D6DAD6B8851C1A +Test: Encrypt +Comment: Set 3, vector 140 +Key: 8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C +Plaintext: 8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C +Ciphertext: 7094C31A06ED2AA0B3B63C210DEB96E2 +Test: Encrypt +Comment: Set 3, vector 141 +Key: 8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D +Plaintext: 8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D +Ciphertext: F8426DAE3B7C3FF568456EB4D4EB623B +Test: Encrypt +Comment: Set 3, vector 142 +Key: 8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E +Plaintext: 8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E +Ciphertext: 090487421369DED8EAC9812B544A29BE +Test: Encrypt +Comment: Set 3, vector 143 +Key: 8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F +Plaintext: 8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F +Ciphertext: 1AFA1FC5ECA8EAD74F9FE9B67993CB6F +Test: Encrypt +Comment: Set 3, vector 144 +Key: 909090909090909090909090909090909090909090909090 +Plaintext: 90909090909090909090909090909090 +Ciphertext: 38124FCE77189341DE7B225951CDE6E9 +Test: Encrypt +Comment: Set 3, vector 145 +Key: 919191919191919191919191919191919191919191919191 +Plaintext: 91919191919191919191919191919191 +Ciphertext: 059A775350A44BB880A750B32B19E179 +Test: Encrypt +Comment: Set 3, vector 146 +Key: 929292929292929292929292929292929292929292929292 +Plaintext: 92929292929292929292929292929292 +Ciphertext: 7CFA631E8BABF7DEE00DAB0754C385DD +Test: Encrypt +Comment: Set 3, vector 147 +Key: 939393939393939393939393939393939393939393939393 +Plaintext: 93939393939393939393939393939393 +Ciphertext: 0632ED71BA440232DECE4F1B38F94323 +Test: Encrypt +Comment: Set 3, vector 148 +Key: 949494949494949494949494949494949494949494949494 +Plaintext: 94949494949494949494949494949494 +Ciphertext: D049FF03ACF47C866A4209E7588E0CFA +Test: Encrypt +Comment: Set 3, vector 149 +Key: 959595959595959595959595959595959595959595959595 +Plaintext: 95959595959595959595959595959595 +Ciphertext: 910408E331C64A71D50A149DFD50C242 +Test: Encrypt +Comment: Set 3, vector 150 +Key: 969696969696969696969696969696969696969696969696 +Plaintext: 96969696969696969696969696969696 +Ciphertext: 0829C2DD4AF8F06C30978A0199A43C3C +Test: Encrypt +Comment: Set 3, vector 151 +Key: 979797979797979797979797979797979797979797979797 +Plaintext: 97979797979797979797979797979797 +Ciphertext: C70D286C18D2A0EA5D16FEB97F35DE6F +Test: Encrypt +Comment: Set 3, vector 152 +Key: 989898989898989898989898989898989898989898989898 +Plaintext: 98989898989898989898989898989898 +Ciphertext: A220CD3CD177BDD73D44B6D4A7A9ED0E +Test: Encrypt +Comment: Set 3, vector 153 +Key: 999999999999999999999999999999999999999999999999 +Plaintext: 99999999999999999999999999999999 +Ciphertext: 74EC1A68010A0D5FA9688F1552E70EF5 +Test: Encrypt +Comment: Set 3, vector 154 +Key: 9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A +Plaintext: 9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A +Ciphertext: C1C0EE9EEA079CCE8544BA9940963720 +Test: Encrypt +Comment: Set 3, vector 155 +Key: 9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B +Plaintext: 9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B +Ciphertext: 500418F7142C273CCADBDAD8831619D2 +Test: Encrypt +Comment: Set 3, vector 156 +Key: 9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C +Plaintext: 9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C +Ciphertext: 703A0223D3ABA658C531F9BE03F6E842 +Test: Encrypt +Comment: Set 3, vector 157 +Key: 9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D +Plaintext: 9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D +Ciphertext: EBC65558CD43197D87CFF645FDBA1661 +Test: Encrypt +Comment: Set 3, vector 158 +Key: 9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E +Plaintext: 9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E +Ciphertext: 6F6E140E44934DA754F008EB5597BDA3 +Test: Encrypt +Comment: Set 3, vector 159 +Key: 9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F +Plaintext: 9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F +Ciphertext: 3D533A98B85CDD624541956E348ACBD3 +Test: Encrypt +Comment: Set 3, vector 160 +Key: A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0 +Plaintext: A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0 +Ciphertext: 13833D60F1D247019258C457E9F2292A +Test: Encrypt +Comment: Set 3, vector 161 +Key: A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1 +Plaintext: A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1 +Ciphertext: FC13CECE4F5E2467427582595EDB6B87 +Test: Encrypt +Comment: Set 3, vector 162 +Key: A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 +Plaintext: A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 +Ciphertext: 2772A4E636F01514949D47B037825AF9 +Test: Encrypt +Comment: Set 3, vector 163 +Key: A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3 +Plaintext: A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3 +Ciphertext: F13DC1CCF105212AF8BC4F73F0AEF272 +Test: Encrypt +Comment: Set 3, vector 164 +Key: A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4 +Plaintext: A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4 +Ciphertext: A6EB0CABBBA03DB1B2425E6FC559B06A +Test: Encrypt +Comment: Set 3, vector 165 +Key: A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5 +Plaintext: A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5 +Ciphertext: 32222D875D9E73DE72848EA88AC9B259 +Test: Encrypt +Comment: Set 3, vector 166 +Key: A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6 +Plaintext: A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6 +Ciphertext: 7DA6BC64D1E71FFE2D24C1A2FF7405BF +Test: Encrypt +Comment: Set 3, vector 167 +Key: A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7 +Plaintext: A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7 +Ciphertext: AD5129092054880300AFCF09A2921DAF +Test: Encrypt +Comment: Set 3, vector 168 +Key: A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8 +Plaintext: A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8 +Ciphertext: FCF2E0AA207754597C8C00A4615B5B5B +Test: Encrypt +Comment: Set 3, vector 169 +Key: A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9 +Plaintext: A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9 +Ciphertext: 83D1475128C93C79BFE2AC9DA7E5D7BC +Test: Encrypt +Comment: Set 3, vector 170 +Key: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +Plaintext: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +Ciphertext: 9BA09846E13568B746B7D6A43364915F +Test: Encrypt +Comment: Set 3, vector 171 +Key: ABABABABABABABABABABABABABABABABABABABABABABABAB +Plaintext: ABABABABABABABABABABABABABABABAB +Ciphertext: 387BDB77D285F9E59CB88CD830CB31E2 +Test: Encrypt +Comment: Set 3, vector 172 +Key: ACACACACACACACACACACACACACACACACACACACACACACACAC +Plaintext: ACACACACACACACACACACACACACACACAC +Ciphertext: 82BFCC439310DD5DC411CCD4451E789B +Test: Encrypt +Comment: Set 3, vector 173 +Key: ADADADADADADADADADADADADADADADADADADADADADADADAD +Plaintext: ADADADADADADADADADADADADADADADAD +Ciphertext: 34C4240853DA191DF1D63E83401CE0E2 +Test: Encrypt +Comment: Set 3, vector 174 +Key: AEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAE +Plaintext: AEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAE +Ciphertext: B3CE3C38C10A667F5FD67BC8B7037283 +Test: Encrypt +Comment: Set 3, vector 175 +Key: AFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAF +Plaintext: AFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAF +Ciphertext: BEF04E726DC1D5D1D4AB0A025CFDFD7D +Test: Encrypt +Comment: Set 3, vector 176 +Key: B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0 +Plaintext: B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0 +Ciphertext: 725D70D564E78095739EA7980B481056 +Test: Encrypt +Comment: Set 3, vector 177 +Key: B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1 +Plaintext: B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1 +Ciphertext: CAB9293C9E3A82D40E85558F9DA488C1 +Test: Encrypt +Comment: Set 3, vector 178 +Key: B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2 +Plaintext: B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2 +Ciphertext: B433CACA5FF9F5AADB6BAFB7D4BE81FC +Test: Encrypt +Comment: Set 3, vector 179 +Key: B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3 +Plaintext: B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3 +Ciphertext: 3910F153098B638696101E04022A7849 +Test: Encrypt +Comment: Set 3, vector 180 +Key: B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 +Plaintext: B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 +Ciphertext: 1D7FF785CFC6AF98C5C81CDA2ABC9816 +Test: Encrypt +Comment: Set 3, vector 181 +Key: B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5 +Plaintext: B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5 +Ciphertext: 4A30C5521BAC28E5942808CB536376C7 +Test: Encrypt +Comment: Set 3, vector 182 +Key: B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6 +Plaintext: B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6 +Ciphertext: 17B908EF18EB7703DDB667C7A8DBA777 +Test: Encrypt +Comment: Set 3, vector 183 +Key: B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7 +Plaintext: B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7 +Ciphertext: 3222E0228F29C9F27467CB7047838E39 +Test: Encrypt +Comment: Set 3, vector 184 +Key: B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8 +Plaintext: B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8 +Ciphertext: E422497D1FD54DF8F9CEE11548D77303 +Test: Encrypt +Comment: Set 3, vector 185 +Key: B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9 +Plaintext: B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9 +Ciphertext: B26A00606A375B1A64B7F0C333D81A50 +Test: Encrypt +Comment: Set 3, vector 186 +Key: BABABABABABABABABABABABABABABABABABABABABABABABA +Plaintext: BABABABABABABABABABABABABABABABA +Ciphertext: D5032B06E290F6B76327E47E519F8F6D +Test: Encrypt +Comment: Set 3, vector 187 +Key: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB +Plaintext: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB +Ciphertext: 2CED7355B82DF3B88C4417149FFA1783 +Test: Encrypt +Comment: Set 3, vector 188 +Key: BCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC +Plaintext: BCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC +Ciphertext: FC7B4D95C62CA6D33862D56768EA9A1A +Test: Encrypt +Comment: Set 3, vector 189 +Key: BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD +Plaintext: BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD +Ciphertext: 375A9C1E1FCFA6F2369306D966F82156 +Test: Encrypt +Comment: Set 3, vector 190 +Key: BEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBE +Plaintext: BEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBE +Ciphertext: BA4C218D8691D5D9CE15ECCC75C75D8B +Test: Encrypt +Comment: Set 3, vector 191 +Key: BFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBF +Plaintext: BFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBF +Ciphertext: 4D5C53279B76A6F74195C65F09DF85D9 +Test: Encrypt +Comment: Set 3, vector 192 +Key: C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0 +Plaintext: C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0 +Ciphertext: 75CF5E6B3B0BFFF2290A5E58A85CF994 +Test: Encrypt +Comment: Set 3, vector 193 +Key: C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1 +Plaintext: C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1 +Ciphertext: 3482A5C83234E75CB443E09BA17EE3A0 +Test: Encrypt +Comment: Set 3, vector 194 +Key: C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2 +Plaintext: C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2 +Ciphertext: DA592D849C1BFBBEF5C3D0D8DA0F4B9A +Test: Encrypt +Comment: Set 3, vector 195 +Key: C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3 +Plaintext: C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3 +Ciphertext: 6656047376A76ED53FFF8C5DE1B6F886 +Test: Encrypt +Comment: Set 3, vector 196 +Key: C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4 +Plaintext: C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4 +Ciphertext: F86FD06864804515B17B453F8A42A44D +Test: Encrypt +Comment: Set 3, vector 197 +Key: C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5 +Plaintext: C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5 +Ciphertext: E57CD8E81BBF5B42446A7880B32A9A2F +Test: Encrypt +Comment: Set 3, vector 198 +Key: C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 +Plaintext: C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 +Ciphertext: A17219F7DEFF2985BDFADD62A6854947 +Test: Encrypt +Comment: Set 3, vector 199 +Key: C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7 +Plaintext: C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7 +Ciphertext: FF288A92FB408DA875531D163CE0105A +Test: Encrypt +Comment: Set 3, vector 200 +Key: C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8 +Plaintext: C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8 +Ciphertext: 11828CD066FD12620DFA16358CF1A705 +Test: Encrypt +Comment: Set 3, vector 201 +Key: C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9 +Plaintext: C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9 +Ciphertext: 6FA5DCBD14D2520E7F8147EDBEBBEAEE +Test: Encrypt +Comment: Set 3, vector 202 +Key: CACACACACACACACACACACACACACACACACACACACACACACACA +Plaintext: CACACACACACACACACACACACACACACACA +Ciphertext: F365CE3849AFB23AF3B62D7CFF80B19B +Test: Encrypt +Comment: Set 3, vector 203 +Key: CBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCB +Plaintext: CBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCB +Ciphertext: 74BE047CAAE10D095B3BDA14016EA262 +Test: Encrypt +Comment: Set 3, vector 204 +Key: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +Plaintext: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +Ciphertext: DC7A7D66AD1ABF1C7AA28891BE685AB5 +Test: Encrypt +Comment: Set 3, vector 205 +Key: CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD +Plaintext: CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD +Ciphertext: 8BED9C5BAD5C4A4AFB41CDFD7E88BB97 +Test: Encrypt +Comment: Set 3, vector 206 +Key: CECECECECECECECECECECECECECECECECECECECECECECECE +Plaintext: CECECECECECECECECECECECECECECECE +Ciphertext: 915FF93DC6A3984F11AB60BD2AA3DC61 +Test: Encrypt +Comment: Set 3, vector 207 +Key: CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF +Plaintext: CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF +Ciphertext: 43DFEEBBFB3692763752E6EA8931A9B8 +Test: Encrypt +Comment: Set 3, vector 208 +Key: D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0 +Plaintext: D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0 +Ciphertext: 2BB966115263DF2296C5D23E02D9C335 +Test: Encrypt +Comment: Set 3, vector 209 +Key: D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1 +Plaintext: D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1 +Ciphertext: FCCA1E3616236F0D5A1A9D035A35049D +Test: Encrypt +Comment: Set 3, vector 210 +Key: D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2 +Plaintext: D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2 +Ciphertext: 2E7246518C923B2AE23C61C99D7E6CE7 +Test: Encrypt +Comment: Set 3, vector 211 +Key: D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3 +Plaintext: D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3 +Ciphertext: 8D19232494905BAF83F4230395C8E09B +Test: Encrypt +Comment: Set 3, vector 212 +Key: D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4 +Plaintext: D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4 +Ciphertext: 6BC0BBCC76A7F8DF2A03BAB1CDE47FB6 +Test: Encrypt +Comment: Set 3, vector 213 +Key: D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5 +Plaintext: D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5 +Ciphertext: BD3D30B62DC0B0FEED0CC760879DB806 +Test: Encrypt +Comment: Set 3, vector 214 +Key: D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6 +Plaintext: D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6 +Ciphertext: 647388D8E6A9C8D09828041F4E338D47 +Test: Encrypt +Comment: Set 3, vector 215 +Key: D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7 +Plaintext: D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7 +Ciphertext: 4861CFC3FDDC434F2742E45B97FBB270 +Test: Encrypt +Comment: Set 3, vector 216 +Key: D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 +Plaintext: D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 +Ciphertext: 4426BC1C3990A5DE10760D0C10A3BB9A +Test: Encrypt +Comment: Set 3, vector 217 +Key: D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9 +Plaintext: D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9 +Ciphertext: 805211D0BD914F07AB1579EF9E3827EE +Test: Encrypt +Comment: Set 3, vector 218 +Key: DADADADADADADADADADADADADADADADADADADADADADADADA +Plaintext: DADADADADADADADADADADADADADADADA +Ciphertext: 519DB5AA8DA219224EDA77F77B96C135 +Test: Encrypt +Comment: Set 3, vector 219 +Key: DBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDB +Plaintext: DBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDB +Ciphertext: 7A96F769BF260E6D91A070BA7766D3E3 +Test: Encrypt +Comment: Set 3, vector 220 +Key: DCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDC +Plaintext: DCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDC +Ciphertext: 902222F1779476A44CEEDACEDA72B3EC +Test: Encrypt +Comment: Set 3, vector 221 +Key: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD +Plaintext: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD +Ciphertext: 99859E56FE0DAB67CDE755E4790ED51D +Test: Encrypt +Comment: Set 3, vector 222 +Key: DEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDE +Plaintext: DEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDE +Ciphertext: C2F4EE121941873763F302ECE6D8DF9E +Test: Encrypt +Comment: Set 3, vector 223 +Key: DFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDF +Plaintext: DFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDF +Ciphertext: FE1E93DBF071E2280130E169C9E5254A +Test: Encrypt +Comment: Set 3, vector 224 +Key: E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0 +Plaintext: E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0 +Ciphertext: 58F45B5E30D9DE7038EC405B601521AB +Test: Encrypt +Comment: Set 3, vector 225 +Key: E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 +Plaintext: E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 +Ciphertext: 8783BD662F65899EF61E113B7CC6505D +Test: Encrypt +Comment: Set 3, vector 226 +Key: E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2 +Plaintext: E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2 +Ciphertext: A3F6BBB2C3403F433203E0E18DB3E4C0 +Test: Encrypt +Comment: Set 3, vector 227 +Key: E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3 +Plaintext: E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3 +Ciphertext: D3EE663795362A0D2E7A8DB784F95A33 +Test: Encrypt +Comment: Set 3, vector 228 +Key: E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4 +Plaintext: E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4 +Ciphertext: 1B75895E7FCEEEA5ECA62E14F77ECF6A +Test: Encrypt +Comment: Set 3, vector 229 +Key: E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5 +Plaintext: E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5 +Ciphertext: 5040525E4F3B78D2036539C1C463A48B +Test: Encrypt +Comment: Set 3, vector 230 +Key: E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6 +Plaintext: E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6 +Ciphertext: A48E63494241AEACB0EF7B18A431E50D +Test: Encrypt +Comment: Set 3, vector 231 +Key: E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7 +Plaintext: E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7 +Ciphertext: 9DAF4DBBBC81465BC4270129C522ABCB +Test: Encrypt +Comment: Set 3, vector 232 +Key: E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8 +Plaintext: E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8 +Ciphertext: 20B118C870AF1A85C683C60A31ED24E4 +Test: Encrypt +Comment: Set 3, vector 233 +Key: E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9 +Plaintext: E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9 +Ciphertext: 52FF30830000A72FA2CB030539550F06 +Test: Encrypt +Comment: Set 3, vector 234 +Key: EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA +Plaintext: EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA +Ciphertext: 797ED3DB1B9A4BF4122EA0FF667BC36D +Test: Encrypt +Comment: Set 3, vector 235 +Key: EBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEB +Plaintext: EBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEB +Ciphertext: 708CE40FC810F5E84B6EE8FC2E0A46FA +Test: Encrypt +Comment: Set 3, vector 236 +Key: ECECECECECECECECECECECECECECECECECECECECECECECEC +Plaintext: ECECECECECECECECECECECECECECECEC +Ciphertext: 0BA7446B1D3D803BB80CDE94E096E79C +Test: Encrypt +Comment: Set 3, vector 237 +Key: EDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDED +Plaintext: EDEDEDEDEDEDEDEDEDEDEDEDEDEDEDED +Ciphertext: 6B0E95AED4DC9E923EDF3DDD5BAEEA0C +Test: Encrypt +Comment: Set 3, vector 238 +Key: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE +Plaintext: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE +Ciphertext: DE45D435FD6F8A240AD8DCE5A4BD8CC3 +Test: Encrypt +Comment: Set 3, vector 239 +Key: EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF +Plaintext: EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF +Ciphertext: 8823002161D635ADA686D85B087F3022 +Test: Encrypt +Comment: Set 3, vector 240 +Key: F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +Plaintext: F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +Ciphertext: C00F367B98CC819F5F6ADADEA8513DD8 +Test: Encrypt +Comment: Set 3, vector 241 +Key: F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1 +Plaintext: F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1 +Ciphertext: 9C25269FB7FA889FBD9E55AAD4C92DE0 +Test: Encrypt +Comment: Set 3, vector 242 +Key: F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2 +Plaintext: F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2 +Ciphertext: 5DD1D60A62B551FFA18CFF8263C5FCE4 +Test: Encrypt +Comment: Set 3, vector 243 +Key: F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 +Plaintext: F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 +Ciphertext: D183A9113393C1EEC7170331C65D2547 +Test: Encrypt +Comment: Set 3, vector 244 +Key: F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4 +Plaintext: F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4 +Ciphertext: FADF9E4AF6C1D7A6965D5DBA03194F18 +Test: Encrypt +Comment: Set 3, vector 245 +Key: F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5 +Plaintext: F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5 +Ciphertext: F2E9E5BE04D7B47B93D2B81DBCDA8BF3 +Test: Encrypt +Comment: Set 3, vector 246 +Key: F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6 +Plaintext: F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6 +Ciphertext: 7A04D513A59636ECA8A8608F10F21910 +Test: Encrypt +Comment: Set 3, vector 247 +Key: F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7 +Plaintext: F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7 +Ciphertext: 659552FCEF0E90F77050CF3902A22475 +Test: Encrypt +Comment: Set 3, vector 248 +Key: F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8 +Plaintext: F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8 +Ciphertext: F81709C989061D4439BDD47E71DBB457 +Test: Encrypt +Comment: Set 3, vector 249 +Key: F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9 +Plaintext: F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9 +Ciphertext: E05425C950E298F31FC6751375B48B66 +Test: Encrypt +Comment: Set 3, vector 250 +Key: FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA +Plaintext: FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA +Ciphertext: 6E90B365BEBAFA5C49DC4D6AB1593F94 +Test: Encrypt +Comment: Set 3, vector 251 +Key: FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB +Plaintext: FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB +Ciphertext: B2469C08D0F878579E162E8ACC5EF802 +Test: Encrypt +Comment: Set 3, vector 252 +Key: FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC +Plaintext: FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC +Ciphertext: C1DCAB694C7FDBEC88C6FC2597EAC180 +Test: Encrypt +Comment: Set 3, vector 253 +Key: FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD +Plaintext: FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD +Ciphertext: 6651FFBD3C30A496D072493A519D44D9 +Test: Encrypt +Comment: Set 3, vector 254 +Key: FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE +Plaintext: FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE +Ciphertext: A2F5A98929658AF4A9700B9923DAF014 +Test: Encrypt +Comment: Set 3, vector 255 +Key: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +Plaintext: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +Ciphertext: 3F8D5676F51CE23DC3BDB627F8B3883E +Test: Encrypt +Comment: Tests with 256-bit keys +Comment: Set 1, vector 0 +Key: 8000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 2136FABDA091DFB5171B94B8EFBB5D08 +Test: Encrypt +Comment: Set 1, vector 1 +Key: 4000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 6EBC4F33B3EADA5DBF25130F3D02CD34 +Test: Encrypt +Comment: Set 1, vector 2 +Key: 2000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3A7BCDC53A1F02EF20C79CFCE107D38B +Test: Encrypt +Comment: Set 1, vector 3 +Key: 1000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 88A96052B61C5A621EE9A6316A42ED4A +Test: Encrypt +Comment: Set 1, vector 4 +Key: 0800000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: CBD7A2D8354B2DA972A0950BDFFF2CBD +Test: Encrypt +Comment: Set 1, vector 5 +Key: 0400000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 690BEB5FBEA12A4861E826F568E9F8F3 +Test: Encrypt +Comment: Set 1, vector 6 +Key: 0200000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 799A6FA3B78846E424F41370654ABD6F +Test: Encrypt +Comment: Set 1, vector 7 +Key: 0100000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: DD7E24E12F391C5FEDE40136F8DE3731 +Test: Encrypt +Comment: Set 1, vector 8 +Key: 0080000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F7412D526E9244574F9933F602595385 +Test: Encrypt +Comment: Set 1, vector 9 +Key: 0040000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: FD9D0174A83BEC3E7E1C3372CB5E7C9B +Test: Encrypt +Comment: Set 1, vector 10 +Key: 0020000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: FCA62D360A7DFE54DB8D53819A407E71 +Test: Encrypt +Comment: Set 1, vector 11 +Key: 0010000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: AC821C68913DCE3E74A20DB8E902CC4C +Test: Encrypt +Comment: Set 1, vector 12 +Key: 0008000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 80633F6CB8F10863E0A7FDE4C35D50E9 +Test: Encrypt +Comment: Set 1, vector 13 +Key: 0004000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: D417D1D94869EE2364FCE869C0C1114E +Test: Encrypt +Comment: Set 1, vector 14 +Key: 0002000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0FA96DCEA2ACB849490CD5A1488A2FD9 +Test: Encrypt +Comment: Set 1, vector 15 +Key: 0001000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3E99BCB51CAEB9147DCF8643771D1C83 +Test: Encrypt +Comment: Set 1, vector 16 +Key: 0000800000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 25EA413BBC3C2579D3F7CBFD9E378091 +Test: Encrypt +Comment: Set 1, vector 17 +Key: 0000400000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: C0433C1AD2E468FC679988CFBFCA5CD4 +Test: Encrypt +Comment: Set 1, vector 18 +Key: 0000200000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 05108B7D7C2871D9DE1F22232CF6966B +Test: Encrypt +Comment: Set 1, vector 19 +Key: 0000100000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 8ABE085B75333946450F2D1D162E8650 +Test: Encrypt +Comment: Set 1, vector 20 +Key: 0000080000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 487A9C50152B44F5B009D8682EA1FD22 +Test: Encrypt +Comment: Set 1, vector 21 +Key: 0000040000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 739207A812F142B545798BA85170AF25 +Test: Encrypt +Comment: Set 1, vector 22 +Key: 0000020000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E40B90A5840591FEC98A24B23E73892B +Test: Encrypt +Comment: Set 1, vector 23 +Key: 0000010000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0258BFB0DC942F6A9139D3C00EBBEB35 +Test: Encrypt +Comment: Set 1, vector 24 +Key: 0000008000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 650CD6035752320B8252F44AEEBEC9E4 +Test: Encrypt +Comment: Set 1, vector 25 +Key: 0000004000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: FABFFBB7028B53E0BB88E3E4462ACF0D +Test: Encrypt +Comment: Set 1, vector 26 +Key: 0000002000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: C48D3416904896E2F2307EA26FB8CF1C +Test: Encrypt +Comment: Set 1, vector 27 +Key: 0000001000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 2237452352F488F1DA3F1619FC6A7F85 +Test: Encrypt +Comment: Set 1, vector 28 +Key: 0000000800000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: D3E6ECF4A3F70E672AABEE0C2ECA3960 +Test: Encrypt +Comment: Set 1, vector 29 +Key: 0000000400000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7A3EFC8AC6A82E8AEF377D8D96D8E830 +Test: Encrypt +Comment: Set 1, vector 30 +Key: 0000000200000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7278F0441F5AA34C0B7CDB076B453225 +Test: Encrypt +Comment: Set 1, vector 31 +Key: 0000000100000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 382E61EAC044E2151906F936CC9D33AE +Test: Encrypt +Comment: Set 1, vector 32 +Key: 0000000080000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: C51147F4AD33C35647DF7E856C2965D4 +Test: Encrypt +Comment: Set 1, vector 33 +Key: 0000000040000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: DAFE261154ADF63EA3F75B1253A9F77C +Test: Encrypt +Comment: Set 1, vector 34 +Key: 0000000020000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B1A0B0E765C1D0379CA538ED0EFB9649 +Test: Encrypt +Comment: Set 1, vector 35 +Key: 0000000010000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 78F7D01D7795ACA0846CCE835E71FBC2 +Test: Encrypt +Comment: Set 1, vector 36 +Key: 0000000008000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E001A545AC71F53D3AD99C84D7F5B062 +Test: Encrypt +Comment: Set 1, vector 37 +Key: 0000000004000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 58E3907C56BF5ADFDBAE61C172B8F488 +Test: Encrypt +Comment: Set 1, vector 38 +Key: 0000000002000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 16F77C9515B473167BD7ABA7C97B1CCA +Test: Encrypt +Comment: Set 1, vector 39 +Key: 0000000001000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 4BC9F687C7757CDF5A5E94D69E5EA173 +Test: Encrypt +Comment: Set 1, vector 40 +Key: 0000000000800000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 804261A34F26A87694F70C35F338989D +Test: Encrypt +Comment: Set 1, vector 41 +Key: 0000000000400000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E8D8BF002738D7067CD06437C4459365 +Test: Encrypt +Comment: Set 1, vector 42 +Key: 0000000000200000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E131137F7EA2AEAB37F72AF3644FFCCE +Test: Encrypt +Comment: Set 1, vector 43 +Key: 0000000000100000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 542A1FD5CB4BE8485FA83AA14FAAD4A8 +Test: Encrypt +Comment: Set 1, vector 44 +Key: 0000000000080000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: BEC6C8C1A9E5E7982A990B8F9BA0ADE3 +Test: Encrypt +Comment: Set 1, vector 45 +Key: 0000000000040000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: DE55BE1AA823A9F7474C65BD50D55095 +Test: Encrypt +Comment: Set 1, vector 46 +Key: 0000000000020000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: D67CC199AF361A07A0DBD8F6700A4744 +Test: Encrypt +Comment: Set 1, vector 47 +Key: 0000000000010000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: DBAD180017184EF80D398D8D22AAC4A1 +Test: Encrypt +Comment: Set 1, vector 48 +Key: 0000000000008000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 27E68691F10EEFD1B594682DC3EF65A5 +Test: Encrypt +Comment: Set 1, vector 49 +Key: 0000000000004000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 6D4EF0587B948AD62B703D3D7CCEA229 +Test: Encrypt +Comment: Set 1, vector 50 +Key: 0000000000002000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: C0F443758F239E3A3E31E6F93AD4766B +Test: Encrypt +Comment: Set 1, vector 51 +Key: 0000000000001000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: BEB5CB1D8EB3A9EA795A4B43CA1567A9 +Test: Encrypt +Comment: Set 1, vector 52 +Key: 0000000000000800000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: D89A97957F1979C63459A385E21B4A84 +Test: Encrypt +Comment: Set 1, vector 53 +Key: 0000000000000400000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 39A6615147FF571F2FABAD5BE9800A10 +Test: Encrypt +Comment: Set 1, vector 54 +Key: 0000000000000200000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E18B0CB1980124504B46A46A6F4273F3 +Test: Encrypt +Comment: Set 1, vector 55 +Key: 0000000000000100000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 1E13C8034ED53FD4E3F433E1CF4B5CE1 +Test: Encrypt +Comment: Set 1, vector 56 +Key: 0000000000000080000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 71FA53EAADBA0C9BCF86A3071408966D +Test: Encrypt +Comment: Set 1, vector 57 +Key: 0000000000000040000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E50502EC84BB024C7466FE225C7FD8BA +Test: Encrypt +Comment: Set 1, vector 58 +Key: 0000000000000020000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: DEB33581D79C9D4294E315998377BCBF +Test: Encrypt +Comment: Set 1, vector 59 +Key: 0000000000000010000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: A713C2503CE44A04C9108FA160659945 +Test: Encrypt +Comment: Set 1, vector 60 +Key: 0000000000000008000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 520E9E8DB8A67601B02E369916FAB8CC +Test: Encrypt +Comment: Set 1, vector 61 +Key: 0000000000000004000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 8FDC11B74D17D79C6B2DFF2D6A561258 +Test: Encrypt +Comment: Set 1, vector 62 +Key: 0000000000000002000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3EA497AD2FC8F2587EFAA7D49121F26C +Test: Encrypt +Comment: Set 1, vector 63 +Key: 0000000000000001000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3340905F7413C979E5AED11D71B9294E +Test: Encrypt +Comment: Set 1, vector 64 +Key: 0000000000000000800000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 067FAC22E16205FF209B1760ABDE0565 +Test: Encrypt +Comment: Set 1, vector 65 +Key: 0000000000000000400000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: BECA010BAB7BDD7E8A8084DA9853A0F4 +Test: Encrypt +Comment: Set 1, vector 66 +Key: 0000000000000000200000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 146F5A4A7B2880F5AF57333C7F129028 +Test: Encrypt +Comment: Set 1, vector 67 +Key: 0000000000000000100000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F773C1BD724955109A8B4EA3DA1C2197 +Test: Encrypt +Comment: Set 1, vector 68 +Key: 0000000000000000080000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B427EFAC8C656AB6F4DF7F420A177B8E +Test: Encrypt +Comment: Set 1, vector 69 +Key: 0000000000000000040000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B3D1BDB29010DB5FC81B66E2F7189D54 +Test: Encrypt +Comment: Set 1, vector 70 +Key: 0000000000000000020000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 676EEA415693F303ACF5CD84C50816AB +Test: Encrypt +Comment: Set 1, vector 71 +Key: 0000000000000000010000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: BA21C564E52961DEB4B3A3CA9E0B70EF +Test: Encrypt +Comment: Set 1, vector 72 +Key: 0000000000000000008000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: A60FB5DBD17EA92E303492E3F54D0BF2 +Test: Encrypt +Comment: Set 1, vector 73 +Key: 0000000000000000004000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F4F5A0540107D66F32FB289B14EF4299 +Test: Encrypt +Comment: Set 1, vector 74 +Key: 0000000000000000002000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 8D9B4A19F391175CF7DA42FEF313EDD8 +Test: Encrypt +Comment: Set 1, vector 75 +Key: 0000000000000000001000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B0AFAB0183A9FC69DA8BBE9B8FAF653A +Test: Encrypt +Comment: Set 1, vector 76 +Key: 0000000000000000000800000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 68FFD91FD5AD1F1AC176D639694FEA29 +Test: Encrypt +Comment: Set 1, vector 77 +Key: 0000000000000000000400000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 97EC38070014494A2E97EFE354BA2865 +Test: Encrypt +Comment: Set 1, vector 78 +Key: 0000000000000000000200000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E3EC51F889C63AD2C708F22AFC42D18C +Test: Encrypt +Comment: Set 1, vector 79 +Key: 0000000000000000000100000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 8CC5BDB49037DC1D3D8DADFA0B8ECD96 +Test: Encrypt +Comment: Set 1, vector 80 +Key: 0000000000000000000080000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 14F5C3D75BA0397D7436E1479F78435B +Test: Encrypt +Comment: Set 1, vector 81 +Key: 0000000000000000000040000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: FF3B01851C8254967E4DFAA2A0F0C057 +Test: Encrypt +Comment: Set 1, vector 82 +Key: 0000000000000000000020000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B8C8E9AFF66FFEC9D0342FF297A543B1 +Test: Encrypt +Comment: Set 1, vector 83 +Key: 0000000000000000000010000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: A95A113F088FFE17A79050C46377545E +Test: Encrypt +Comment: Set 1, vector 84 +Key: 0000000000000000000008000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: EA4C3AFA65016D057EC1DFDD0411ED06 +Test: Encrypt +Comment: Set 1, vector 85 +Key: 0000000000000000000004000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7D535C84DFAD692D0F89AB73C1F42F60 +Test: Encrypt +Comment: Set 1, vector 86 +Key: 0000000000000000000002000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E857DF0CEBAB1E03CB9AF73CBF9C19D1 +Test: Encrypt +Comment: Set 1, vector 87 +Key: 0000000000000000000001000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7A59BCF6FAC80379EB7E8E2EFAB147D4 +Test: Encrypt +Comment: Set 1, vector 88 +Key: 0000000000000000000000800000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 43EF17F87BAF7536DDE734F885C4CE85 +Test: Encrypt +Comment: Set 1, vector 89 +Key: 0000000000000000000000400000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 2B71CE14089741A1EF1E99DC9E22E739 +Test: Encrypt +Comment: Set 1, vector 90 +Key: 0000000000000000000000200000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 9283885622781998186B7DACBFF68ED2 +Test: Encrypt +Comment: Set 1, vector 91 +Key: 0000000000000000000000100000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 756A184F392D8C821479EFF930338C0A +Test: Encrypt +Comment: Set 1, vector 92 +Key: 0000000000000000000000080000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: CE848D49BB76CA30B607C9539793DA41 +Test: Encrypt +Comment: Set 1, vector 93 +Key: 0000000000000000000000040000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 50F2D5238991EEA9654C8895AFC0AC37 +Test: Encrypt +Comment: Set 1, vector 94 +Key: 0000000000000000000000020000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 561564103E13F4CBB58A9E096DB1958B +Test: Encrypt +Comment: Set 1, vector 95 +Key: 0000000000000000000000010000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: EF2BB05AC6868C15D66D956BD580D467 +Test: Encrypt +Comment: Set 1, vector 96 +Key: 0000000000000000000000008000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: C7B1A5A3A201DF25FD97A47B1FC3569E +Test: Encrypt +Comment: Set 1, vector 97 +Key: 0000000000000000000000004000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0A1873FF47B38095CF6A8BABF3901FF2 +Test: Encrypt +Comment: Set 1, vector 98 +Key: 0000000000000000000000002000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: A96F8F977DC45ABF55518EA10C598E10 +Test: Encrypt +Comment: Set 1, vector 99 +Key: 0000000000000000000000001000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 778C644278689EC0577BDDB2154AE635 +Test: Encrypt +Comment: Set 1, vector 100 +Key: 0000000000000000000000000800000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: DEF97DBCF02648E7BCE6A368F7F34C14 +Test: Encrypt +Comment: Set 1, vector 101 +Key: 0000000000000000000000000400000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 71B85362022D53AF03A17870D8F66614 +Test: Encrypt +Comment: Set 1, vector 102 +Key: 0000000000000000000000000200000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3593FC550A2950C2EF94F6E8F6E90BB3 +Test: Encrypt +Comment: Set 1, vector 103 +Key: 0000000000000000000000000100000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 29E64004DBF1E7833A7CD82EDACD932A +Test: Encrypt +Comment: Set 1, vector 104 +Key: 0000000000000000000000000080000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 715E700DF74A8680F04A48B18AEDB99C +Test: Encrypt +Comment: Set 1, vector 105 +Key: 0000000000000000000000000040000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 72E3288FFB02D1100F84FA605855D812 +Test: Encrypt +Comment: Set 1, vector 106 +Key: 0000000000000000000000000020000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 9021082D3C4CB202936FD76F1392446B +Test: Encrypt +Comment: Set 1, vector 107 +Key: 0000000000000000000000000010000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 1552BD181EE0FB914558053F2662F9AE +Test: Encrypt +Comment: Set 1, vector 108 +Key: 0000000000000000000000000008000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 599D87052322E19141057F0EF3C47508 +Test: Encrypt +Comment: Set 1, vector 109 +Key: 0000000000000000000000000004000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 505AC03CEB2ECA1C9D411B4A1CF2011C +Test: Encrypt +Comment: Set 1, vector 110 +Key: 0000000000000000000000000002000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: DD639574D8FFCD24EA68B2243C5AA7D6 +Test: Encrypt +Comment: Set 1, vector 111 +Key: 0000000000000000000000000001000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 45F5371B714D2652BA4AD083EDB65BEE +Test: Encrypt +Comment: Set 1, vector 112 +Key: 0000000000000000000000000000800000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: DEAB9C368B21FE41E709554340E87C0B +Test: Encrypt +Comment: Set 1, vector 113 +Key: 0000000000000000000000000000400000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3A981045526766BD13943F11CE917AF9 +Test: Encrypt +Comment: Set 1, vector 114 +Key: 0000000000000000000000000000200000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 35CDF30A485CE21F0D005EE0C2BCF315 +Test: Encrypt +Comment: Set 1, vector 115 +Key: 0000000000000000000000000000100000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F561A8C91820252580317385F8336305 +Test: Encrypt +Comment: Set 1, vector 116 +Key: 0000000000000000000000000000080000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0789680D27735220798079572BF4ECF6 +Test: Encrypt +Comment: Set 1, vector 117 +Key: 0000000000000000000000000000040000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B4F16729D7AB16C9AE44FB61291920DE +Test: Encrypt +Comment: Set 1, vector 118 +Key: 0000000000000000000000000000020000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: FB83BF9B1D983CA7FB3718E22D9A2155 +Test: Encrypt +Comment: Set 1, vector 119 +Key: 0000000000000000000000000000010000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: CEC5C5D13E59508D3DA431F1479730F3 +Test: Encrypt +Comment: Set 1, vector 120 +Key: 0000000000000000000000000000008000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 09BEA932E60A4AD34271FF11A2B2AA02 +Test: Encrypt +Comment: Set 1, vector 121 +Key: 0000000000000000000000000000004000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B102F72FD89452C0CD1C6897071F903E +Test: Encrypt +Comment: Set 1, vector 122 +Key: 0000000000000000000000000000002000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: A469F9411F0A3A6E1A8076416C6B55CB +Test: Encrypt +Comment: Set 1, vector 123 +Key: 0000000000000000000000000000001000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 6C3F88FCB538699547A1CF07A529993F +Test: Encrypt +Comment: Set 1, vector 124 +Key: 0000000000000000000000000000000800000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 493E8CC2A63534632A6456ED47BF233C +Test: Encrypt +Comment: Set 1, vector 125 +Key: 0000000000000000000000000000000400000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 1FD81E905F7055C4B04DB1F9718A6861 +Test: Encrypt +Comment: Set 1, vector 126 +Key: 0000000000000000000000000000000200000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B22882E01D7A1BF2D7F0E3BFBFC87156 +Test: Encrypt +Comment: Set 1, vector 127 +Key: 0000000000000000000000000000000100000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 86C9822E849322FB00DF89233D33935D +Test: Encrypt +Comment: Set 1, vector 128 +Key: 0000000000000000000000000000000080000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 12012E8E028D0D3D8DC00847130D424C +Test: Encrypt +Comment: Set 1, vector 129 +Key: 0000000000000000000000000000000040000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 182A96CC3BF10035B9DB292D1399F993 +Test: Encrypt +Comment: Set 1, vector 130 +Key: 0000000000000000000000000000000020000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 91E0E6991989D1FC4CBD754E4E7D0590 +Test: Encrypt +Comment: Set 1, vector 131 +Key: 0000000000000000000000000000000010000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F3EFC4E6F207E370C8CAE39408C4BF1B +Test: Encrypt +Comment: Set 1, vector 132 +Key: 0000000000000000000000000000000008000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: AA767AB2EC6FA2FA183DAF9C0F3BAE5E +Test: Encrypt +Comment: Set 1, vector 133 +Key: 0000000000000000000000000000000004000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: D1FF11F4D1AEEAAE01A115081AF886EF +Test: Encrypt +Comment: Set 1, vector 134 +Key: 0000000000000000000000000000000002000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 5390139711090B56B28338FEA98FCC82 +Test: Encrypt +Comment: Set 1, vector 135 +Key: 0000000000000000000000000000000001000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 13E693CCF6EBF0E6061B92B7ED0B95B6 +Test: Encrypt +Comment: Set 1, vector 136 +Key: 0000000000000000000000000000000000800000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 588FB2F95861D3C427669C68D04ADB25 +Test: Encrypt +Comment: Set 1, vector 137 +Key: 0000000000000000000000000000000000400000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F472ECDF8DEBC416313AAF7C8AAFB43E +Test: Encrypt +Comment: Set 1, vector 138 +Key: 0000000000000000000000000000000000200000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: EAA654BE38E857941A921C70AC7FC7CE +Test: Encrypt +Comment: Set 1, vector 139 +Key: 0000000000000000000000000000000000100000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F2A4E47AE80CDF506B9513C510EA0954 +Test: Encrypt +Comment: Set 1, vector 140 +Key: 0000000000000000000000000000000000080000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F08EC7ED8FBB99F175A990C3E4DECB6B +Test: Encrypt +Comment: Set 1, vector 141 +Key: 0000000000000000000000000000000000040000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 5C767BC584CA3653EDE27CD8B209A0AD +Test: Encrypt +Comment: Set 1, vector 142 +Key: 0000000000000000000000000000000000020000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: AFF9A8BA92A40B2BF42FDB4089B1F9CC +Test: Encrypt +Comment: Set 1, vector 143 +Key: 0000000000000000000000000000000000010000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: BFC1E9198BBE22266712EB1ECB17D748 +Test: Encrypt +Comment: Set 1, vector 144 +Key: 0000000000000000000000000000000000008000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 235184136A29208BD041E60BCB9F7464 +Test: Encrypt +Comment: Set 1, vector 145 +Key: 0000000000000000000000000000000000004000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 83DC48F9177C5C94CBC22E83A2B76829 +Test: Encrypt +Comment: Set 1, vector 146 +Key: 0000000000000000000000000000000000002000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 72CD31ACB7A1A459E4D27C1F26039FA7 +Test: Encrypt +Comment: Set 1, vector 147 +Key: 0000000000000000000000000000000000001000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 139AC4734C3136FD9982FCC7A569B9D3 +Test: Encrypt +Comment: Set 1, vector 148 +Key: 0000000000000000000000000000000000000800000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 12FFA3EF4346F4C57A03A36F9938B251 +Test: Encrypt +Comment: Set 1, vector 149 +Key: 0000000000000000000000000000000000000400000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 43DDB100CE22E5553CF4DCF814BF3CAC +Test: Encrypt +Comment: Set 1, vector 150 +Key: 0000000000000000000000000000000000000200000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: ABDADF4C948BB61C0A917885ADE4C7C5 +Test: Encrypt +Comment: Set 1, vector 151 +Key: 0000000000000000000000000000000000000100000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 197391E089DE173B522DDD8CBEEC3118 +Test: Encrypt +Comment: Set 1, vector 152 +Key: 0000000000000000000000000000000000000080000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 43FBE8BF2728C55C9368D01E40C1CF96 +Test: Encrypt +Comment: Set 1, vector 153 +Key: 0000000000000000000000000000000000000040000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0F5DE5F67EC84F2CB253A0BC48991C71 +Test: Encrypt +Comment: Set 1, vector 154 +Key: 0000000000000000000000000000000000000020000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 52BA4666B972EAE3D2E960D7372D3C48 +Test: Encrypt +Comment: Set 1, vector 155 +Key: 0000000000000000000000000000000000000010000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0735AE765BC079A93B451D873FA93702 +Test: Encrypt +Comment: Set 1, vector 156 +Key: 0000000000000000000000000000000000000008000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 89D988508A4569E2232F72412AE50B65 +Test: Encrypt +Comment: Set 1, vector 157 +Key: 0000000000000000000000000000000000000004000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: BCF0EE2403BC9344030C0FF065B6FD88 +Test: Encrypt +Comment: Set 1, vector 158 +Key: 0000000000000000000000000000000000000002000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 25D76D36F3376D6FD835BA012C7DD2E5 +Test: Encrypt +Comment: Set 1, vector 159 +Key: 0000000000000000000000000000000000000001000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: EF364A31E8551732D4B2098281D4E2C9 +Test: Encrypt +Comment: Set 1, vector 160 +Key: 0000000000000000000000000000000000000000800000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 64B1F927C0A7315EA60BC5F2A0DCCFE2 +Test: Encrypt +Comment: Set 1, vector 161 +Key: 0000000000000000000000000000000000000000400000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: CA99E0EDFA0E121F27659346BCDCC443 +Test: Encrypt +Comment: Set 1, vector 162 +Key: 0000000000000000000000000000000000000000200000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 1816D9D23D1069BC6DEC195F60994C05 +Test: Encrypt +Comment: Set 1, vector 163 +Key: 0000000000000000000000000000000000000000100000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 9819575F6890E093091378AED0612051 +Test: Encrypt +Comment: Set 1, vector 164 +Key: 0000000000000000000000000000000000000000080000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 41903DE72A486B823842FBA2840E265C +Test: Encrypt +Comment: Set 1, vector 165 +Key: 0000000000000000000000000000000000000000040000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 30651D416912A01EDEC4290D34B4A605 +Test: Encrypt +Comment: Set 1, vector 166 +Key: 0000000000000000000000000000000000000000020000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0949AD8AB2E85995686D6D495ABA1028 +Test: Encrypt +Comment: Set 1, vector 167 +Key: 0000000000000000000000000000000000000000010000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3789C2D08E122BE204662FE9A0FDF77A +Test: Encrypt +Comment: Set 1, vector 168 +Key: 0000000000000000000000000000000000000000008000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: A0C66EE031FF045123475E6F5FA64F57 +Test: Encrypt +Comment: Set 1, vector 169 +Key: 0000000000000000000000000000000000000000004000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 1BACCDD314AF39124709013C94CAD1AC +Test: Encrypt +Comment: Set 1, vector 170 +Key: 0000000000000000000000000000000000000000002000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 2FB5DF5527A8E06AED03D683EDF14E9A +Test: Encrypt +Comment: Set 1, vector 171 +Key: 0000000000000000000000000000000000000000001000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: FF2C61AD63CDA6207605C18C888B383D +Test: Encrypt +Comment: Set 1, vector 172 +Key: 0000000000000000000000000000000000000000000800000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 71CE4A5B48671AB9A6561B7109FB8345 +Test: Encrypt +Comment: Set 1, vector 173 +Key: 0000000000000000000000000000000000000000000400000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 37299C12377E9CB8DF5FE730DFFCB5CA +Test: Encrypt +Comment: Set 1, vector 174 +Key: 0000000000000000000000000000000000000000000200000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: C5454350A7CB0EC5CA3932A3948F48BC +Test: Encrypt +Comment: Set 1, vector 175 +Key: 0000000000000000000000000000000000000000000100000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 8AB40D09FFBD0C82E9091FC80D2A63C9 +Test: Encrypt +Comment: Set 1, vector 176 +Key: 0000000000000000000000000000000000000000000080000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 9CB3FE43EAE3DC7AC4F97E609FDE9F10 +Test: Encrypt +Comment: Set 1, vector 177 +Key: 0000000000000000000000000000000000000000000040000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 51369DC689B25C3AC593B578BAEA046E +Test: Encrypt +Comment: Set 1, vector 178 +Key: 0000000000000000000000000000000000000000000020000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 13D9D885A24AE8B859F239890DF438C9 +Test: Encrypt +Comment: Set 1, vector 179 +Key: 0000000000000000000000000000000000000000000010000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: CEACAE376290D5C62D2DAE422CA6E5C0 +Test: Encrypt +Comment: Set 1, vector 180 +Key: 0000000000000000000000000000000000000000000008000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 6AE17D621F97B62F4571AB165CE0A11F +Test: Encrypt +Comment: Set 1, vector 181 +Key: 0000000000000000000000000000000000000000000004000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: C91318F8FD17E9BC656E639A0D648B3A +Test: Encrypt +Comment: Set 1, vector 182 +Key: 0000000000000000000000000000000000000000000002000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: BFF1BC1C935E40FB0C20DED5985F1910 +Test: Encrypt +Comment: Set 1, vector 183 +Key: 0000000000000000000000000000000000000000000001000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 96F0B387F487BBDD5227B595A506F963 +Test: Encrypt +Comment: Set 1, vector 184 +Key: 0000000000000000000000000000000000000000000000800000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 62265B7EFB73A77205ECBBFD166B3EAE +Test: Encrypt +Comment: Set 1, vector 185 +Key: 0000000000000000000000000000000000000000000000400000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 016E8F3087757E8F576B19A58D356FB6 +Test: Encrypt +Comment: Set 1, vector 186 +Key: 0000000000000000000000000000000000000000000000200000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 456FAF632EA07797CEC23DC6553988F9 +Test: Encrypt +Comment: Set 1, vector 187 +Key: 0000000000000000000000000000000000000000000000100000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 147694E2231FA00D6B62D3E51CC8201D +Test: Encrypt +Comment: Set 1, vector 188 +Key: 0000000000000000000000000000000000000000000000080000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 2299D31F3D747838C65FE7C6C0C59214 +Test: Encrypt +Comment: Set 1, vector 189 +Key: 0000000000000000000000000000000000000000000000040000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: C5A669612A23E4F7551D79650071E040 +Test: Encrypt +Comment: Set 1, vector 190 +Key: 0000000000000000000000000000000000000000000000020000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F0A32D722EDFD2BA628C781DACD5FC50 +Test: Encrypt +Comment: Set 1, vector 191 +Key: 0000000000000000000000000000000000000000000000010000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 422C8E2A0DFF095E40654CB2B7176A9B +Test: Encrypt +Comment: Set 1, vector 192 +Key: 0000000000000000000000000000000000000000000000008000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 99DEF168961D4AB9E63157E60F76399C +Test: Encrypt +Comment: Set 1, vector 193 +Key: 0000000000000000000000000000000000000000000000004000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 49C92ACC622A00BCFF7DFDCABF33CB4C +Test: Encrypt +Comment: Set 1, vector 194 +Key: 0000000000000000000000000000000000000000000000002000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 517117A096B2EE66D4BEF2D1EE570CE7 +Test: Encrypt +Comment: Set 1, vector 195 +Key: 0000000000000000000000000000000000000000000000001000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 9DAECC0E82559BC2CDB8A01AB30BA605 +Test: Encrypt +Comment: Set 1, vector 196 +Key: 0000000000000000000000000000000000000000000000000800000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 50B2882928DAB54488413ABA5743535E +Test: Encrypt +Comment: Set 1, vector 197 +Key: 0000000000000000000000000000000000000000000000000400000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E6725F73ED920F473E1442ABEC7DB722 +Test: Encrypt +Comment: Set 1, vector 198 +Key: 0000000000000000000000000000000000000000000000000200000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: CB4F06002C5864E40C80F97157452575 +Test: Encrypt +Comment: Set 1, vector 199 +Key: 0000000000000000000000000000000000000000000000000100000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 8DF72D7C8AE547F2AA3E9AFAAD1D62F0 +Test: Encrypt +Comment: Set 1, vector 200 +Key: 0000000000000000000000000000000000000000000000000080000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0DA429E486F5ED9460B7C54460B0A699 +Test: Encrypt +Comment: Set 1, vector 201 +Key: 0000000000000000000000000000000000000000000000000040000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 24832DB462328D93306C6714E100ADAB +Test: Encrypt +Comment: Set 1, vector 202 +Key: 0000000000000000000000000000000000000000000000000020000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3170D82FEC3D2A58C7D2F28BAC4C7809 +Test: Encrypt +Comment: Set 1, vector 203 +Key: 0000000000000000000000000000000000000000000000000010000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 638A46425AEA9C808AC752EE69F56822 +Test: Encrypt +Comment: Set 1, vector 204 +Key: 0000000000000000000000000000000000000000000000000008000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F98954D90C5E3DB2EEC8A86078D70763 +Test: Encrypt +Comment: Set 1, vector 205 +Key: 0000000000000000000000000000000000000000000000000004000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 8D5868451617FB145B8F7F91712A7AA0 +Test: Encrypt +Comment: Set 1, vector 206 +Key: 0000000000000000000000000000000000000000000000000002000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 2292BA337A4F465E0DFB85DAAC266AE6 +Test: Encrypt +Comment: Set 1, vector 207 +Key: 0000000000000000000000000000000000000000000000000001000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F2560D5063A2F928D699005012A0C839 +Test: Encrypt +Comment: Set 1, vector 208 +Key: 0000000000000000000000000000000000000000000000000000800000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 44968AEABB2852075F83FB942E05099D +Test: Encrypt +Comment: Set 1, vector 209 +Key: 0000000000000000000000000000000000000000000000000000400000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: EB339742AB40B5627A7CB60D4F54DD2E +Test: Encrypt +Comment: Set 1, vector 210 +Key: 0000000000000000000000000000000000000000000000000000200000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 9AAA6FC3BBDE523E9FCD9D5C0255F912 +Test: Encrypt +Comment: Set 1, vector 211 +Key: 0000000000000000000000000000000000000000000000000000100000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E6E25CBAFF57F4C6056706FD13E6A2E3 +Test: Encrypt +Comment: Set 1, vector 212 +Key: 0000000000000000000000000000000000000000000000000000080000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 8A9628166922E8EC6FC28F5E847B9C71 +Test: Encrypt +Comment: Set 1, vector 213 +Key: 0000000000000000000000000000000000000000000000000000040000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 97CF8FF5D1337DA8602F8AB6C0224AF7 +Test: Encrypt +Comment: Set 1, vector 214 +Key: 0000000000000000000000000000000000000000000000000000020000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: DDBBE09A93364599E9233969ADBEBA63 +Test: Encrypt +Comment: Set 1, vector 215 +Key: 0000000000000000000000000000000000000000000000000000010000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: E772954B9DA3DA8A005582C4E9E5B6FA +Test: Encrypt +Comment: Set 1, vector 216 +Key: 0000000000000000000000000000000000000000000000000000008000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 507DFD30F7EEF807F994B298D487FDE6 +Test: Encrypt +Comment: Set 1, vector 217 +Key: 0000000000000000000000000000000000000000000000000000004000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 6FF09F69AED61F091F92503547A19B68 +Test: Encrypt +Comment: Set 1, vector 218 +Key: 0000000000000000000000000000000000000000000000000000002000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 1141E6BB725E09640DD6971F4EF1A886 +Test: Encrypt +Comment: Set 1, vector 219 +Key: 0000000000000000000000000000000000000000000000000000001000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 9C0E8061BA0361B730D24675EF128705 +Test: Encrypt +Comment: Set 1, vector 220 +Key: 0000000000000000000000000000000000000000000000000000000800000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7D0137240D0D3D086198E83BC0CF22D0 +Test: Encrypt +Comment: Set 1, vector 221 +Key: 0000000000000000000000000000000000000000000000000000000400000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: BC4460FF55EBFAA1171B0CE249830281 +Test: Encrypt +Comment: Set 1, vector 222 +Key: 0000000000000000000000000000000000000000000000000000000200000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: CDBE93ADCF1867B952FB82C42DF60CFD +Test: Encrypt +Comment: Set 1, vector 223 +Key: 0000000000000000000000000000000000000000000000000000000100000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 007AA375E4402B8A5657C01259AF3D49 +Test: Encrypt +Comment: Set 1, vector 224 +Key: 0000000000000000000000000000000000000000000000000000000080000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: F5C2B13998E5687C773017C14EB01FE4 +Test: Encrypt +Comment: Set 1, vector 225 +Key: 0000000000000000000000000000000000000000000000000000000040000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0AE71BFDD72FBC4576305E4B0807E17C +Test: Encrypt +Comment: Set 1, vector 226 +Key: 0000000000000000000000000000000000000000000000000000000020000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 35FB1CE6CB7449DF115D3AC6BA656439 +Test: Encrypt +Comment: Set 1, vector 227 +Key: 0000000000000000000000000000000000000000000000000000000010000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 6D64CEC5D9D74BD40FBC0BE69C70B777 +Test: Encrypt +Comment: Set 1, vector 228 +Key: 0000000000000000000000000000000000000000000000000000000008000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7257851ACD3E3E3AE50048973C3A2AE8 +Test: Encrypt +Comment: Set 1, vector 229 +Key: 0000000000000000000000000000000000000000000000000000000004000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 50852661D5BD7960412B29A86F549619 +Test: Encrypt +Comment: Set 1, vector 230 +Key: 0000000000000000000000000000000000000000000000000000000002000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: CDF3561D971D40521CD46BAE98F5867A +Test: Encrypt +Comment: Set 1, vector 231 +Key: 0000000000000000000000000000000000000000000000000000000001000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: FA3C84185B9ABF9887DD501B3B0F52D3 +Test: Encrypt +Comment: Set 1, vector 232 +Key: 0000000000000000000000000000000000000000000000000000000000800000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 40A5B434F81574733D00F25511109E08 +Test: Encrypt +Comment: Set 1, vector 233 +Key: 0000000000000000000000000000000000000000000000000000000000400000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: DA0D248315C527572F1673BDE26A475E +Test: Encrypt +Comment: Set 1, vector 234 +Key: 0000000000000000000000000000000000000000000000000000000000200000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0F8366D8EFB9AB63B0299F278C55CFB4 +Test: Encrypt +Comment: Set 1, vector 235 +Key: 0000000000000000000000000000000000000000000000000000000000100000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 25A089C523CD153EC094862B5923F492 +Test: Encrypt +Comment: Set 1, vector 236 +Key: 0000000000000000000000000000000000000000000000000000000000080000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7268A4628C6A0BE6A8391ABE70986176 +Test: Encrypt +Comment: Set 1, vector 237 +Key: 0000000000000000000000000000000000000000000000000000000000040000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7C11E6478CC688FE707454DF4AB5B666 +Test: Encrypt +Comment: Set 1, vector 238 +Key: 0000000000000000000000000000000000000000000000000000000000020000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 7601B6EBD5CE578973E949C21BFA8CAA +Test: Encrypt +Comment: Set 1, vector 239 +Key: 0000000000000000000000000000000000000000000000000000000000010000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0FCE9CCDF89F2EB139DBEB09B55375D5 +Test: Encrypt +Comment: Set 1, vector 240 +Key: 0000000000000000000000000000000000000000000000000000000000008000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: AAABFDD9E28A3ADCA1212F3D7F53A269 +Test: Encrypt +Comment: Set 1, vector 241 +Key: 0000000000000000000000000000000000000000000000000000000000004000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: FC6B4304423917E41677768BD7A8D402 +Test: Encrypt +Comment: Set 1, vector 242 +Key: 0000000000000000000000000000000000000000000000000000000000002000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 2AA3239D19ADBA9A4190E3653875C589 +Test: Encrypt +Comment: Set 1, vector 243 +Key: 0000000000000000000000000000000000000000000000000000000000001000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 4F4AB0DB2F3D3EA1E5FCBF99651485DC +Test: Encrypt +Comment: Set 1, vector 244 +Key: 0000000000000000000000000000000000000000000000000000000000000800 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B542CEF08D13E300B282CE6A74C51C96 +Test: Encrypt +Comment: Set 1, vector 245 +Key: 0000000000000000000000000000000000000000000000000000000000000400 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 9955E16433B0D58BFC4B35EE9F44734C +Test: Encrypt +Comment: Set 1, vector 246 +Key: 0000000000000000000000000000000000000000000000000000000000000200 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 5027A7DDC6F99A112E45D3090C7C3465 +Test: Encrypt +Comment: Set 1, vector 247 +Key: 0000000000000000000000000000000000000000000000000000000000000100 +Plaintext: 00000000000000000000000000000000 +Ciphertext: CB14EBD24FC63194495FACFFB5C3A07B +Test: Encrypt +Comment: Set 1, vector 248 +Key: 0000000000000000000000000000000000000000000000000000000000000080 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 2BCBE64545A08F59178242452566B997 +Test: Encrypt +Comment: Set 1, vector 249 +Key: 0000000000000000000000000000000000000000000000000000000000000040 +Plaintext: 00000000000000000000000000000000 +Ciphertext: DE428FF12360A0C8FAE73E9D8E6A0657 +Test: Encrypt +Comment: Set 1, vector 250 +Key: 0000000000000000000000000000000000000000000000000000000000000020 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 6425603FCB0F088D87D3AC7078C7014C +Test: Encrypt +Comment: Set 1, vector 251 +Key: 0000000000000000000000000000000000000000000000000000000000000010 +Plaintext: 00000000000000000000000000000000 +Ciphertext: A837813C9436F4C48C45B6C85A4EAF84 +Test: Encrypt +Comment: Set 1, vector 252 +Key: 0000000000000000000000000000000000000000000000000000000000000008 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B95F9010E694BA44B812D6A7A59E027A +Test: Encrypt +Comment: Set 1, vector 253 +Key: 0000000000000000000000000000000000000000000000000000000000000004 +Plaintext: 00000000000000000000000000000000 +Ciphertext: DF2746A2D9ED707DCC686BB64B77C9DD +Test: Encrypt +Comment: Set 1, vector 254 +Key: 0000000000000000000000000000000000000000000000000000000000000002 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 40DD304C3FC8FEF5D7D08FD467E018F6 +Test: Encrypt +Comment: Set 1, vector 255 +Key: 0000000000000000000000000000000000000000000000000000000000000001 +Plaintext: 00000000000000000000000000000000 +Ciphertext: AFCD38B195E0A736304E89B9AE3019D3 +Test: Encrypt +Comment: Set 2, vector 0 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 80000000000000000000000000000000 +Ciphertext: B0C6B88AEA518AB09E847248E91B1B9D +Test: Encrypt +Comment: Set 2, vector 1 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 40000000000000000000000000000000 +Ciphertext: B8D7684E35FA1DB15BDCEE7A48659858 +Test: Encrypt +Comment: Set 2, vector 2 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 20000000000000000000000000000000 +Ciphertext: F0CAD59AF92FBB79F36951E697492750 +Test: Encrypt +Comment: Set 2, vector 3 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 10000000000000000000000000000000 +Ciphertext: 117100F6635389560DC4A2DA24EBA70F +Test: Encrypt +Comment: Set 2, vector 4 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 08000000000000000000000000000000 +Ciphertext: DBDD62355553019ED84C35886421E532 +Test: Encrypt +Comment: Set 2, vector 5 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 04000000000000000000000000000000 +Ciphertext: 9CB8D04FA506F19848F7B9110518BFC8 +Test: Encrypt +Comment: Set 2, vector 6 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 02000000000000000000000000000000 +Ciphertext: E4308E253BC3444D293500701BA82C6A +Test: Encrypt +Comment: Set 2, vector 7 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 01000000000000000000000000000000 +Ciphertext: EA2FAE53F7F30C0170A20E95A068503E +Test: Encrypt +Comment: Set 2, vector 8 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00800000000000000000000000000000 +Ciphertext: 14B14839EA221880B2C64D1FE000B93D +Test: Encrypt +Comment: Set 2, vector 9 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00400000000000000000000000000000 +Ciphertext: A5CFC075B342D5101AACC334E73058BB +Test: Encrypt +Comment: Set 2, vector 10 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00200000000000000000000000000000 +Ciphertext: 477EA56B2EBAD0F8AC5E1936866560FF +Test: Encrypt +Comment: Set 2, vector 11 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00100000000000000000000000000000 +Ciphertext: 107E8598418404196EC59F63E45B7F6D +Test: Encrypt +Comment: Set 2, vector 12 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00080000000000000000000000000000 +Ciphertext: FF6A891E7C1C074A68FEC291928FDD8D +Test: Encrypt +Comment: Set 2, vector 13 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00040000000000000000000000000000 +Ciphertext: F64C250A13F45D377ADB7545B2B157A9 +Test: Encrypt +Comment: Set 2, vector 14 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00020000000000000000000000000000 +Ciphertext: FAD0F252086F11C830C65B63197CBC38 +Test: Encrypt +Comment: Set 2, vector 15 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00010000000000000000000000000000 +Ciphertext: 9DCB89B209441F02AD0D25C6AB826629 +Test: Encrypt +Comment: Set 2, vector 16 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00008000000000000000000000000000 +Ciphertext: E62E4ED4E4F34EDC563710D960E09D4C +Test: Encrypt +Comment: Set 2, vector 17 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00004000000000000000000000000000 +Ciphertext: 98A1B926BA06895C3F2E84CCBACBC356 +Test: Encrypt +Comment: Set 2, vector 18 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00002000000000000000000000000000 +Ciphertext: 29BE0BE4DB7F4D196718AEA38F3B0BFD +Test: Encrypt +Comment: Set 2, vector 19 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00001000000000000000000000000000 +Ciphertext: F670C4EBECBA0B43E71F6D752BFD4854 +Test: Encrypt +Comment: Set 2, vector 20 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000800000000000000000000000000 +Ciphertext: 7D7666B4484CDB7E3605468E093A787C +Test: Encrypt +Comment: Set 2, vector 21 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000400000000000000000000000000 +Ciphertext: 562D06B181C091DA6C43642AE99460C6 +Test: Encrypt +Comment: Set 2, vector 22 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000200000000000000000000000000 +Ciphertext: AB0EFB5975E6186B7D76BC9672453488 +Test: Encrypt +Comment: Set 2, vector 23 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000100000000000000000000000000 +Ciphertext: 10C0756538E7BFF88D19AE2B1F7B859A +Test: Encrypt +Comment: Set 2, vector 24 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000080000000000000000000000000 +Ciphertext: AF7FCD5248F8C72F1695AA05DD1CADE0 +Test: Encrypt +Comment: Set 2, vector 25 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000040000000000000000000000000 +Ciphertext: 9841E555655609A75D7BE20B8A90EF1E +Test: Encrypt +Comment: Set 2, vector 26 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000020000000000000000000000000 +Ciphertext: 27F9546E6A1B7464780000561783569C +Test: Encrypt +Comment: Set 2, vector 27 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000010000000000000000000000000 +Ciphertext: 8671D935D7A8354EECB7288803D42D7A +Test: Encrypt +Comment: Set 2, vector 28 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000008000000000000000000000000 +Ciphertext: 0DA44F508DEBC6F044394624FCEB8EBE +Test: Encrypt +Comment: Set 2, vector 29 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000004000000000000000000000000 +Ciphertext: AB137369BE6D93FBB18006BDB236EC09 +Test: Encrypt +Comment: Set 2, vector 30 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000002000000000000000000000000 +Ciphertext: EB90C4E597A7E1779FFA260886E26F75 +Test: Encrypt +Comment: Set 2, vector 31 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000001000000000000000000000000 +Ciphertext: 618CF3588D5C128EAF252616230E08F7 +Test: Encrypt +Comment: Set 2, vector 32 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000800000000000000000000000 +Ciphertext: 98DC4DB49D197AB9152D12B9DE2D73CA +Test: Encrypt +Comment: Set 2, vector 33 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000400000000000000000000000 +Ciphertext: 5BDDE24B15702A35E1F140C57D206443 +Test: Encrypt +Comment: Set 2, vector 34 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000200000000000000000000000 +Ciphertext: CF755809882BED8BA2F9F1A4ED296A2B +Test: Encrypt +Comment: Set 2, vector 35 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000100000000000000000000000 +Ciphertext: F1A8DBB999538AE89D16F92A7F4D1DF1 +Test: Encrypt +Comment: Set 2, vector 36 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000080000000000000000000000 +Ciphertext: 775222FDDAAECB81CF675C4E0B98179E +Test: Encrypt +Comment: Set 2, vector 37 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000040000000000000000000000 +Ciphertext: 12A648CADCD153C760A965826683119A +Test: Encrypt +Comment: Set 2, vector 38 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000020000000000000000000000 +Ciphertext: 0503FB10AB241E7CF45D8CDEEE474335 +Test: Encrypt +Comment: Set 2, vector 39 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000010000000000000000000000 +Ciphertext: 3D299C0070CBBD831B802690B8E7CA24 +Test: Encrypt +Comment: Set 2, vector 40 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000008000000000000000000000 +Ciphertext: 33105BD4D11D66753DC34D128BEFE3F4 +Test: Encrypt +Comment: Set 2, vector 41 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000004000000000000000000000 +Ciphertext: 5EFCE2B4B987C0F77D27B44836881682 +Test: Encrypt +Comment: Set 2, vector 42 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000002000000000000000000000 +Ciphertext: 7835449454128035D7F0EA99E327577B +Test: Encrypt +Comment: Set 2, vector 43 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000001000000000000000000000 +Ciphertext: 27BEDDA0601BE35122FB1D272D73AB3E +Test: Encrypt +Comment: Set 2, vector 44 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000800000000000000000000 +Ciphertext: 54C3F99FF48E318CC515EDE75800C4B3 +Test: Encrypt +Comment: Set 2, vector 45 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000400000000000000000000 +Ciphertext: C627C329F8E48299F6FDB23B9DBEA0BB +Test: Encrypt +Comment: Set 2, vector 46 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000200000000000000000000 +Ciphertext: 1B6578F9E23BD8C1845A02431C5F9AA3 +Test: Encrypt +Comment: Set 2, vector 47 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000100000000000000000000 +Ciphertext: 6DB2FB8C0B9344D0547C0FF1292020C6 +Test: Encrypt +Comment: Set 2, vector 48 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000080000000000000000000 +Ciphertext: 4FAD9B2C37C131493FBEF53581FA4F83 +Test: Encrypt +Comment: Set 2, vector 49 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000040000000000000000000 +Ciphertext: 47502A01E93D2C87BD5584F6AFD3D99D +Test: Encrypt +Comment: Set 2, vector 50 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000020000000000000000000 +Ciphertext: 056E1C6F651BFE50271B3B7A18E76D84 +Test: Encrypt +Comment: Set 2, vector 51 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000010000000000000000000 +Ciphertext: 5632BAF6627B3D96AD4E06FA6A561F55 +Test: Encrypt +Comment: Set 2, vector 52 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000008000000000000000000 +Ciphertext: E29807CAACDFA2D41A7D9E91FA7FD8EB +Test: Encrypt +Comment: Set 2, vector 53 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000004000000000000000000 +Ciphertext: 81DD44BB5D1822DEE605F9E6FF01D7B3 +Test: Encrypt +Comment: Set 2, vector 54 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000002000000000000000000 +Ciphertext: 5C3649925E47D7FF96482A8FBD9666FD +Test: Encrypt +Comment: Set 2, vector 55 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000001000000000000000000 +Ciphertext: 695415A836E66E737887845EC08A1ADB +Test: Encrypt +Comment: Set 2, vector 56 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000800000000000000000 +Ciphertext: F5416BCE292D9E2CEA5D1CC70BBAEED1 +Test: Encrypt +Comment: Set 2, vector 57 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000400000000000000000 +Ciphertext: 7AEC4F1388FC29C47F7FED74ADDE8485 +Test: Encrypt +Comment: Set 2, vector 58 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000200000000000000000 +Ciphertext: 82A9F1A6CE08BC4876E649D8A8EA7EB6 +Test: Encrypt +Comment: Set 2, vector 59 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000100000000000000000 +Ciphertext: B6296C88ADF1A792908B065EEB04BFC2 +Test: Encrypt +Comment: Set 2, vector 60 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000080000000000000000 +Ciphertext: E766A39AECCA40BDBFBE6FF3FA292913 +Test: Encrypt +Comment: Set 2, vector 61 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000040000000000000000 +Ciphertext: C6D081454EA00D83C23B5A62C84359E1 +Test: Encrypt +Comment: Set 2, vector 62 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000020000000000000000 +Ciphertext: 85D259A79CCA80484504D1603F7A8F53 +Test: Encrypt +Comment: Set 2, vector 63 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000010000000000000000 +Ciphertext: D8291FA1C6DC250078824B2D0A20883F +Test: Encrypt +Comment: Set 2, vector 64 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000008000000000000000 +Ciphertext: 95387CB74C48FFBD1F8D64A6CC45E074 +Test: Encrypt +Comment: Set 2, vector 65 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000004000000000000000 +Ciphertext: A17F975F538F56CDF629B516011DE837 +Test: Encrypt +Comment: Set 2, vector 66 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000002000000000000000 +Ciphertext: B50B615A1654C6E1CB6AB33716C097FE +Test: Encrypt +Comment: Set 2, vector 67 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000001000000000000000 +Ciphertext: 7BBB2CBB874DF6C8B821DA7FB0F9011B +Test: Encrypt +Comment: Set 2, vector 68 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000800000000000000 +Ciphertext: E9EFE074D096A275E47CD2E6206DF6A1 +Test: Encrypt +Comment: Set 2, vector 69 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000400000000000000 +Ciphertext: 88F2F8D5A836406AE8BBB98C65BBDA55 +Test: Encrypt +Comment: Set 2, vector 70 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000200000000000000 +Ciphertext: F64620D8D87585A3EF038B9AD58F5EA0 +Test: Encrypt +Comment: Set 2, vector 71 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000100000000000000 +Ciphertext: 694438EC141C8ED5F2F898B4554A298F +Test: Encrypt +Comment: Set 2, vector 72 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000080000000000000 +Ciphertext: 3E6226EC7726A1EE5F5FA9B18CCE8C44 +Test: Encrypt +Comment: Set 2, vector 73 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000040000000000000 +Ciphertext: 8AB6949E79911647800B9E87362AB97A +Test: Encrypt +Comment: Set 2, vector 74 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000020000000000000 +Ciphertext: 093C5CF24EDAF7F9F1C8A80DE4FF50A9 +Test: Encrypt +Comment: Set 2, vector 75 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000010000000000000 +Ciphertext: 28A36E50061F19E240351ED0E378CBF4 +Test: Encrypt +Comment: Set 2, vector 76 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000008000000000000 +Ciphertext: B93BB36CB88BF26EA79198652AA51D3C +Test: Encrypt +Comment: Set 2, vector 77 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000004000000000000 +Ciphertext: DE4948083D044FAC9BCA6DA8CD67B8A6 +Test: Encrypt +Comment: Set 2, vector 78 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000002000000000000 +Ciphertext: 6E778B5BDA6CA118117E47470D080D3C +Test: Encrypt +Comment: Set 2, vector 79 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000001000000000000 +Ciphertext: 0A9107324DA32B4281D032A3487EF875 +Test: Encrypt +Comment: Set 2, vector 80 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000800000000000 +Ciphertext: 18ED5635312D71ABD123CCE779D4D68A +Test: Encrypt +Comment: Set 2, vector 81 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000400000000000 +Ciphertext: 2E3C63F95C4BC1F944BAB06DEDC9AA8E +Test: Encrypt +Comment: Set 2, vector 82 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000200000000000 +Ciphertext: ACCC869EF07004C8C3C709083BE7BA2F +Test: Encrypt +Comment: Set 2, vector 83 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000100000000000 +Ciphertext: DF60B34FB1A59147CC1FB049C1578206 +Test: Encrypt +Comment: Set 2, vector 84 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000080000000000 +Ciphertext: 4228DC636C08E41021054AA0E1E2227A +Test: Encrypt +Comment: Set 2, vector 85 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000040000000000 +Ciphertext: 7CE27F66EFD735FFD6B3E1738C50495B +Test: Encrypt +Comment: Set 2, vector 86 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000020000000000 +Ciphertext: F8E74B33A9CDE351DA0BBC06D69093D7 +Test: Encrypt +Comment: Set 2, vector 87 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000010000000000 +Ciphertext: AE0D22A5B37B8DC5D81CC641EED334D0 +Test: Encrypt +Comment: Set 2, vector 88 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000008000000000 +Ciphertext: C181C6CA5E163743458B9167A0B6A16A +Test: Encrypt +Comment: Set 2, vector 89 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000004000000000 +Ciphertext: 5171F4F6095E4B276CFBA1F07223FBE6 +Test: Encrypt +Comment: Set 2, vector 90 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000002000000000 +Ciphertext: 2732F4D3A8C9D1D8D493840D6E0B864F +Test: Encrypt +Comment: Set 2, vector 91 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000001000000000 +Ciphertext: 3EF04E0059A061D973532CA5C1DFBE7B +Test: Encrypt +Comment: Set 2, vector 92 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000800000000 +Ciphertext: 6D9A8F23579E4978EBAA87B5ADEB77E5 +Test: Encrypt +Comment: Set 2, vector 93 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000400000000 +Ciphertext: BBD08873CC44BA4253C0C41FEEB7F124 +Test: Encrypt +Comment: Set 2, vector 94 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000200000000 +Ciphertext: 72E4B2437CBD283F3809CE686F6A591E +Test: Encrypt +Comment: Set 2, vector 95 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000100000000 +Ciphertext: 6E5580514B92512B1BF4B1B987B9AA1B +Test: Encrypt +Comment: Set 2, vector 96 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000080000000 +Ciphertext: 5EF5D0C5BCBDCB604D3A083B68CE0FA3 +Test: Encrypt +Comment: Set 2, vector 97 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000040000000 +Ciphertext: 9D991FDD723AD2182777A15CA0E0F665 +Test: Encrypt +Comment: Set 2, vector 98 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000020000000 +Ciphertext: 24440626EFC8F86BEA7DE78085AB8A22 +Test: Encrypt +Comment: Set 2, vector 99 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000010000000 +Ciphertext: 17C3630D62D13C1E826C0FCCBD74A864 +Test: Encrypt +Comment: Set 2, vector 100 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000008000000 +Ciphertext: 4CF5AB86A56AB134A7FE46CCE3F9FCE9 +Test: Encrypt +Comment: Set 2, vector 101 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000004000000 +Ciphertext: 3E6B9C0388F6D9B8F458F30221907607 +Test: Encrypt +Comment: Set 2, vector 102 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000002000000 +Ciphertext: AD9C926B8A5CD98EEE88200617E59958 +Test: Encrypt +Comment: Set 2, vector 103 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000001000000 +Ciphertext: AFF8AED5E075E02AF720CA4BF0028B3B +Test: Encrypt +Comment: Set 2, vector 104 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000800000 +Ciphertext: D90EAFF909202BB209BB3BB8C7F9A954 +Test: Encrypt +Comment: Set 2, vector 105 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000400000 +Ciphertext: 2C709B00E6A22F00F64A7D8EE341853F +Test: Encrypt +Comment: Set 2, vector 106 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000200000 +Ciphertext: CCEC598F0D9F0BF201B2F487136D54A4 +Test: Encrypt +Comment: Set 2, vector 107 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000100000 +Ciphertext: 73B2883A0A166AAE1BF14E60A5195FA3 +Test: Encrypt +Comment: Set 2, vector 108 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000080000 +Ciphertext: E676867BD9AD5EF915143388496779D7 +Test: Encrypt +Comment: Set 2, vector 109 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000040000 +Ciphertext: CDCB73D1BFCFD4BE7F1DAA9B1C6A4055 +Test: Encrypt +Comment: Set 2, vector 110 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000020000 +Ciphertext: 02A3A5C89DAA24CD2C517F7A73286A89 +Test: Encrypt +Comment: Set 2, vector 111 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000010000 +Ciphertext: C0FA2AC9E92EE58C2DD12D6D43AB7035 +Test: Encrypt +Comment: Set 2, vector 112 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000008000 +Ciphertext: EDC2CB1F7291353BDBF2385519E6AE16 +Test: Encrypt +Comment: Set 2, vector 113 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000004000 +Ciphertext: B4B62D16D197A98CD3B978812B9D9884 +Test: Encrypt +Comment: Set 2, vector 114 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000002000 +Ciphertext: 5CDFC95A529A905101CEA26BC1B891ED +Test: Encrypt +Comment: Set 2, vector 115 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000001000 +Ciphertext: CC7150CD3650B98363296C7C4ED368D1 +Test: Encrypt +Comment: Set 2, vector 116 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000800 +Ciphertext: CC57706B0C6526B8E25A5DBD32EACBDB +Test: Encrypt +Comment: Set 2, vector 117 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000400 +Ciphertext: 30D30456AD98B182D64C649648F6AEC9 +Test: Encrypt +Comment: Set 2, vector 118 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000200 +Ciphertext: D7E9DA7F631938EB649A08AF82FBD75F +Test: Encrypt +Comment: Set 2, vector 119 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000100 +Ciphertext: B8DA2AF6600B07895B5D0FFAF4991469 +Test: Encrypt +Comment: Set 2, vector 120 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000080 +Ciphertext: 0F6F64F930BA6C178943322B98114599 +Test: Encrypt +Comment: Set 2, vector 121 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000040 +Ciphertext: 8B1F247802E47C91BEE2AA34ECFD7A01 +Test: Encrypt +Comment: Set 2, vector 122 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000020 +Ciphertext: 7A6985778D3A66E97F23E01F0D0E45E7 +Test: Encrypt +Comment: Set 2, vector 123 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000010 +Ciphertext: BA664AC39855518DFDEE10D1B3111FAE +Test: Encrypt +Comment: Set 2, vector 124 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000008 +Ciphertext: 7C92854D801A1648F65CA81813DDBF83 +Test: Encrypt +Comment: Set 2, vector 125 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000004 +Ciphertext: 6A3F25AAB7E92D9CF378E5D9C040F26B +Test: Encrypt +Comment: Set 2, vector 126 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000002 +Ciphertext: 3D4B2CDE666761BA5DFB305178E667FB +Test: Encrypt +Comment: Set 2, vector 127 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000001 +Ciphertext: 9CDB269B5D293BC5DB9C55B057D9B591 +Test: Encrypt +Comment: Set 3, vector 0 +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 396154111ADEFC500CF6E5C99038BC17 +Test: Encrypt +Comment: Set 3, vector 1 +Key: 0101010101010101010101010101010101010101010101010101010101010101 +Plaintext: 01010101010101010101010101010101 +Ciphertext: 438D0C2E7E86869B56EBA23B66086A01 +Test: Encrypt +Comment: Set 3, vector 2 +Key: 0202020202020202020202020202020202020202020202020202020202020202 +Plaintext: 02020202020202020202020202020202 +Ciphertext: D4F553BFA794F55EF3B7A578629F6DEA +Test: Encrypt +Comment: Set 3, vector 3 +Key: 0303030303030303030303030303030303030303030303030303030303030303 +Plaintext: 03030303030303030303030303030303 +Ciphertext: B1EB06630CF3E25AEF18FA34709232F7 +Test: Encrypt +Comment: Set 3, vector 4 +Key: 0404040404040404040404040404040404040404040404040404040404040404 +Plaintext: 04040404040404040404040404040404 +Ciphertext: 5E858730ABC9823A93CA4CAB67F0B423 +Test: Encrypt +Comment: Set 3, vector 5 +Key: 0505050505050505050505050505050505050505050505050505050505050505 +Plaintext: 05050505050505050505050505050505 +Ciphertext: 9FC988D43FE3712CF6D2DB552FE3C80F +Test: Encrypt +Comment: Set 3, vector 6 +Key: 0606060606060606060606060606060606060606060606060606060606060606 +Plaintext: 06060606060606060606060606060606 +Ciphertext: 6109500D59414C9974D15818A2BA6DD0 +Test: Encrypt +Comment: Set 3, vector 7 +Key: 0707070707070707070707070707070707070707070707070707070707070707 +Plaintext: 07070707070707070707070707070707 +Ciphertext: 5F6BF9AC53A680EACAE7583A8933DA8E +Test: Encrypt +Comment: Set 3, vector 8 +Key: 0808080808080808080808080808080808080808080808080808080808080808 +Plaintext: 08080808080808080808080808080808 +Ciphertext: F9A9C1540AE1B314DBEDF9A49054DC9D +Test: Encrypt +Comment: Set 3, vector 9 +Key: 0909090909090909090909090909090909090909090909090909090909090909 +Plaintext: 09090909090909090909090909090909 +Ciphertext: 6D66755ACDB9D90BEC599A0BC0C7BF48 +Test: Encrypt +Comment: Set 3, vector 10 +Key: 0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A +Plaintext: 0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A +Ciphertext: 5527F328AF93C2D5CCC80AF7A3E8DF3D +Test: Encrypt +Comment: Set 3, vector 11 +Key: 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +Plaintext: 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +Ciphertext: 27AA99F8E6EA08D8E8D5A528EE4774B6 +Test: Encrypt +Comment: Set 3, vector 12 +Key: 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C +Plaintext: 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C +Ciphertext: 46F7D660A22232F5E3664EF355098CE4 +Test: Encrypt +Comment: Set 3, vector 13 +Key: 0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D +Plaintext: 0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D +Ciphertext: BDC0AEC72B53B747AB5C7BD62062826A +Test: Encrypt +Comment: Set 3, vector 14 +Key: 0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E +Plaintext: 0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E +Ciphertext: A0CAB391DC8BFF0281F3E1C70C1CE33B +Test: Encrypt +Comment: Set 3, vector 15 +Key: 0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F +Plaintext: 0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F +Ciphertext: 5CBFB3E894AE1428549CCF777A9F0A73 +Test: Encrypt +Comment: Set 3, vector 16 +Key: 1010101010101010101010101010101010101010101010101010101010101010 +Plaintext: 10101010101010101010101010101010 +Ciphertext: 6693FC130669F194F81E8D175194DDA2 +Test: Encrypt +Comment: Set 3, vector 17 +Key: 1111111111111111111111111111111111111111111111111111111111111111 +Plaintext: 11111111111111111111111111111111 +Ciphertext: A6A72472F8C04329C0E2FB56982A33C7 +Test: Encrypt +Comment: Set 3, vector 18 +Key: 1212121212121212121212121212121212121212121212121212121212121212 +Plaintext: 12121212121212121212121212121212 +Ciphertext: 6321875C5F89CCE16C6FF5E85E759C9A +Test: Encrypt +Comment: Set 3, vector 19 +Key: 1313131313131313131313131313131313131313131313131313131313131313 +Plaintext: 13131313131313131313131313131313 +Ciphertext: 8819C97D05C91A23062E9851F07EF6F7 +Test: Encrypt +Comment: Set 3, vector 20 +Key: 1414141414141414141414141414141414141414141414141414141414141414 +Plaintext: 14141414141414141414141414141414 +Ciphertext: F894FEB12164BB32AC846DD9530604CE +Test: Encrypt +Comment: Set 3, vector 21 +Key: 1515151515151515151515151515151515151515151515151515151515151515 +Plaintext: 15151515151515151515151515151515 +Ciphertext: 61B02392CD3F571B35C862E703DB2053 +Test: Encrypt +Comment: Set 3, vector 22 +Key: 1616161616161616161616161616161616161616161616161616161616161616 +Plaintext: 16161616161616161616161616161616 +Ciphertext: 6269E137F8480D555D1B24F392162DBA +Test: Encrypt +Comment: Set 3, vector 23 +Key: 1717171717171717171717171717171717171717171717171717171717171717 +Plaintext: 17171717171717171717171717171717 +Ciphertext: B6662F56AA3D23DE1DFDE165B2D63FA0 +Test: Encrypt +Comment: Set 3, vector 24 +Key: 1818181818181818181818181818181818181818181818181818181818181818 +Plaintext: 18181818181818181818181818181818 +Ciphertext: C8271ACE969013EE2C9EF1512FFABAE5 +Test: Encrypt +Comment: Set 3, vector 25 +Key: 1919191919191919191919191919191919191919191919191919191919191919 +Plaintext: 19191919191919191919191919191919 +Ciphertext: 6982E764E750CDF3E5F9C4E40A5DFE28 +Test: Encrypt +Comment: Set 3, vector 26 +Key: 1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A +Plaintext: 1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A +Ciphertext: 23172E86AF4A140A78CB1DC776270FFF +Test: Encrypt +Comment: Set 3, vector 27 +Key: 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B +Plaintext: 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B +Ciphertext: BA0BD958FC1DE142EC40326B2C315AA5 +Test: Encrypt +Comment: Set 3, vector 28 +Key: 1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C +Plaintext: 1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C +Ciphertext: 7FB2B8A4B95CBFB74BFD5F7A5641261C +Test: Encrypt +Comment: Set 3, vector 29 +Key: 1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D +Plaintext: 1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D +Ciphertext: 56B261D89F8978041E2602DF97386BF7 +Test: Encrypt +Comment: Set 3, vector 30 +Key: 1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E +Plaintext: 1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E +Ciphertext: A2D74F5148C84C1F990290E17DD3EDFA +Test: Encrypt +Comment: Set 3, vector 31 +Key: 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F +Plaintext: 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F +Ciphertext: 7D8BC76F1D941FC3C7E4C6F17AC03FF4 +Test: Encrypt +Comment: Set 3, vector 32 +Key: 2020202020202020202020202020202020202020202020202020202020202020 +Plaintext: 20202020202020202020202020202020 +Ciphertext: F3E1FDA6B9C8314799F4654C29F1C690 +Test: Encrypt +Comment: Set 3, vector 33 +Key: 2121212121212121212121212121212121212121212121212121212121212121 +Plaintext: 21212121212121212121212121212121 +Ciphertext: 9BB8499B8631F6211D22DE555010E482 +Test: Encrypt +Comment: Set 3, vector 34 +Key: 2222222222222222222222222222222222222222222222222222222222222222 +Plaintext: 22222222222222222222222222222222 +Ciphertext: B098D857086ABC425B437BD63E8A53D2 +Test: Encrypt +Comment: Set 3, vector 35 +Key: 2323232323232323232323232323232323232323232323232323232323232323 +Plaintext: 23232323232323232323232323232323 +Ciphertext: F157E2B1298A205C7EF526F3E3196BF4 +Test: Encrypt +Comment: Set 3, vector 36 +Key: 2424242424242424242424242424242424242424242424242424242424242424 +Plaintext: 24242424242424242424242424242424 +Ciphertext: 91FE4F664ED2FE0097D8B95703694BBE +Test: Encrypt +Comment: Set 3, vector 37 +Key: 2525252525252525252525252525252525252525252525252525252525252525 +Plaintext: 25252525252525252525252525252525 +Ciphertext: 742EF3C2DC4490F7D1BDB3031137B6C1 +Test: Encrypt +Comment: Set 3, vector 38 +Key: 2626262626262626262626262626262626262626262626262626262626262626 +Plaintext: 26262626262626262626262626262626 +Ciphertext: 79302D9C8DBBBDAD7B8D8B9E7A60E42D +Test: Encrypt +Comment: Set 3, vector 39 +Key: 2727272727272727272727272727272727272727272727272727272727272727 +Plaintext: 27272727272727272727272727272727 +Ciphertext: 4F4DA48026B809452E7FFB1C3DAFBD99 +Test: Encrypt +Comment: Set 3, vector 40 +Key: 2828282828282828282828282828282828282828282828282828282828282828 +Plaintext: 28282828282828282828282828282828 +Ciphertext: 6D9DF175ED0DAFE550619CF8362B98E8 +Test: Encrypt +Comment: Set 3, vector 41 +Key: 2929292929292929292929292929292929292929292929292929292929292929 +Plaintext: 29292929292929292929292929292929 +Ciphertext: 5D4A406E3C89612AA89A9D38A80ECFEF +Test: Encrypt +Comment: Set 3, vector 42 +Key: 2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A +Plaintext: 2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A +Ciphertext: 51CE933AD1EB3117A129788D3D0B815A +Test: Encrypt +Comment: Set 3, vector 43 +Key: 2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B +Plaintext: 2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B +Ciphertext: DD39326230AC02767866ADE07AED1DAA +Test: Encrypt +Comment: Set 3, vector 44 +Key: 2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C +Plaintext: 2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C +Ciphertext: DC493BAD40D435273B18026DE5412278 +Test: Encrypt +Comment: Set 3, vector 45 +Key: 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D +Plaintext: 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D +Ciphertext: 8A61E9750E1DAC58C92F5E243CA7465B +Test: Encrypt +Comment: Set 3, vector 46 +Key: 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E +Plaintext: 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E +Ciphertext: 57A7641E6A7B61A86AFD7A23578DFBC5 +Test: Encrypt +Comment: Set 3, vector 47 +Key: 2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F +Plaintext: 2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F +Ciphertext: 019A8F9D38B4B92B077D08B025C15550 +Test: Encrypt +Comment: Set 3, vector 48 +Key: 3030303030303030303030303030303030303030303030303030303030303030 +Plaintext: 30303030303030303030303030303030 +Ciphertext: 9F6EEA9C215C273135C53A3F4208469E +Test: Encrypt +Comment: Set 3, vector 49 +Key: 3131313131313131313131313131313131313131313131313131313131313131 +Plaintext: 31313131313131313131313131313131 +Ciphertext: 7BF3D63D790CAB57EA8354B10FEBDE18 +Test: Encrypt +Comment: Set 3, vector 50 +Key: 3232323232323232323232323232323232323232323232323232323232323232 +Plaintext: 32323232323232323232323232323232 +Ciphertext: AB30751ED4052A1D916E50C4073DFCB5 +Test: Encrypt +Comment: Set 3, vector 51 +Key: 3333333333333333333333333333333333333333333333333333333333333333 +Plaintext: 33333333333333333333333333333333 +Ciphertext: C39180F205BBA8BEE9832BF56FCC75C0 +Test: Encrypt +Comment: Set 3, vector 52 +Key: 3434343434343434343434343434343434343434343434343434343434343434 +Plaintext: 34343434343434343434343434343434 +Ciphertext: 3BEDE5E09CB9CCFC8BE38F8378D49AE9 +Test: Encrypt +Comment: Set 3, vector 53 +Key: 3535353535353535353535353535353535353535353535353535353535353535 +Plaintext: 35353535353535353535353535353535 +Ciphertext: 448AE4ADF7070A8B8C4AB0FE7277E8D7 +Test: Encrypt +Comment: Set 3, vector 54 +Key: 3636363636363636363636363636363636363636363636363636363636363636 +Plaintext: 36363636363636363636363636363636 +Ciphertext: 095A361F2243FC39F4ECD94A5AC0F94A +Test: Encrypt +Comment: Set 3, vector 55 +Key: 3737373737373737373737373737373737373737373737373737373737373737 +Plaintext: 37373737373737373737373737373737 +Ciphertext: AD77D7D2A7F3AF5732CE5A51E83D7025 +Test: Encrypt +Comment: Set 3, vector 56 +Key: 3838383838383838383838383838383838383838383838383838383838383838 +Plaintext: 38383838383838383838383838383838 +Ciphertext: 930DA09C18DF5F6D072AA662CC8F7751 +Test: Encrypt +Comment: Set 3, vector 57 +Key: 3939393939393939393939393939393939393939393939393939393939393939 +Plaintext: 39393939393939393939393939393939 +Ciphertext: F3B3871B66FE8A1FA4AE2150EC8B7060 +Test: Encrypt +Comment: Set 3, vector 58 +Key: 3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A +Plaintext: 3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A +Ciphertext: 62DD93CFA7EFC223A822A6F754B6298D +Test: Encrypt +Comment: Set 3, vector 59 +Key: 3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B +Plaintext: 3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B +Ciphertext: C86A0377B3C45C2B1896829D7B0610F3 +Test: Encrypt +Comment: Set 3, vector 60 +Key: 3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C +Plaintext: 3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C +Ciphertext: 8CCFC961EBAB55C0ECB1B10EDEDD9C61 +Test: Encrypt +Comment: Set 3, vector 61 +Key: 3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D +Plaintext: 3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D +Ciphertext: D828E857BDBD6192300764A2084E0680 +Test: Encrypt +Comment: Set 3, vector 62 +Key: 3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E +Plaintext: 3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E +Ciphertext: 24C0DC84D72EA678201534CE8DC22A45 +Test: Encrypt +Comment: Set 3, vector 63 +Key: 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F +Plaintext: 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F +Ciphertext: D65F340A25D35E5D0B08C63FA44F9898 +Test: Encrypt +Comment: Set 3, vector 64 +Key: 4040404040404040404040404040404040404040404040404040404040404040 +Plaintext: 40404040404040404040404040404040 +Ciphertext: 4A30476F1141FBF303ED63FCD3CB0536 +Test: Encrypt +Comment: Set 3, vector 65 +Key: 4141414141414141414141414141414141414141414141414141414141414141 +Plaintext: 41414141414141414141414141414141 +Ciphertext: 78246080B38B5283960E0253E2FF6A5E +Test: Encrypt +Comment: Set 3, vector 66 +Key: 4242424242424242424242424242424242424242424242424242424242424242 +Plaintext: 42424242424242424242424242424242 +Ciphertext: 475E8388EE3D3EE111DD0E816B244DD2 +Test: Encrypt +Comment: Set 3, vector 67 +Key: 4343434343434343434343434343434343434343434343434343434343434343 +Plaintext: 43434343434343434343434343434343 +Ciphertext: D40D3FECE8B05875F2FCD23526CCD6B2 +Test: Encrypt +Comment: Set 3, vector 68 +Key: 4444444444444444444444444444444444444444444444444444444444444444 +Plaintext: 44444444444444444444444444444444 +Ciphertext: CD9846E1B120482E6B6D71C4F5D704FE +Test: Encrypt +Comment: Set 3, vector 69 +Key: 4545454545454545454545454545454545454545454545454545454545454545 +Plaintext: 45454545454545454545454545454545 +Ciphertext: E707C35474257CE52617B5889ECB974B +Test: Encrypt +Comment: Set 3, vector 70 +Key: 4646464646464646464646464646464646464646464646464646464646464646 +Plaintext: 46464646464646464646464646464646 +Ciphertext: 9A79D57FD89D938F4B4CACA52E8CB544 +Test: Encrypt +Comment: Set 3, vector 71 +Key: 4747474747474747474747474747474747474747474747474747474747474747 +Plaintext: 47474747474747474747474747474747 +Ciphertext: 34F9B98AC130F7E7B123ECBF8910735C +Test: Encrypt +Comment: Set 3, vector 72 +Key: 4848484848484848484848484848484848484848484848484848484848484848 +Plaintext: 48484848484848484848484848484848 +Ciphertext: BF75CC83FE76E8A15981DA738E5A8513 +Test: Encrypt +Comment: Set 3, vector 73 +Key: 4949494949494949494949494949494949494949494949494949494949494949 +Plaintext: 49494949494949494949494949494949 +Ciphertext: 4A452EFBE634441444FB50641CB2EFC1 +Test: Encrypt +Comment: Set 3, vector 74 +Key: 4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A +Plaintext: 4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A +Ciphertext: 3D5ED11F0C81E81BAB97B7148D67BA55 +Test: Encrypt +Comment: Set 3, vector 75 +Key: 4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B +Plaintext: 4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B +Ciphertext: DBBAE78B177C27954DEDBAD5D98E7BEE +Test: Encrypt +Comment: Set 3, vector 76 +Key: 4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C +Plaintext: 4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C +Ciphertext: F52D16EFC5DE991430F6E7D13983DEB8 +Test: Encrypt +Comment: Set 3, vector 77 +Key: 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D +Plaintext: 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D +Ciphertext: B6C98EBC320B3BDD927C2FE57F8180B5 +Test: Encrypt +Comment: Set 3, vector 78 +Key: 4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E +Plaintext: 4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E +Ciphertext: D510C35680C9B958C81599F3665FBEC1 +Test: Encrypt +Comment: Set 3, vector 79 +Key: 4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F +Plaintext: 4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F +Ciphertext: 72DAD08BF510CDFEEC76FEAB908829B4 +Test: Encrypt +Comment: Set 3, vector 80 +Key: 5050505050505050505050505050505050505050505050505050505050505050 +Plaintext: 50505050505050505050505050505050 +Ciphertext: AC7B447EDB38F935469309E766BCB1F6 +Test: Encrypt +Comment: Set 3, vector 81 +Key: 5151515151515151515151515151515151515151515151515151515151515151 +Plaintext: 51515151515151515151515151515151 +Ciphertext: 18B937F666BF580F9CDB60A935427459 +Test: Encrypt +Comment: Set 3, vector 82 +Key: 5252525252525252525252525252525252525252525252525252525252525252 +Plaintext: 52525252525252525252525252525252 +Ciphertext: 6A08B38202685E610CA9584725D6092A +Test: Encrypt +Comment: Set 3, vector 83 +Key: 5353535353535353535353535353535353535353535353535353535353535353 +Plaintext: 53535353535353535353535353535353 +Ciphertext: 1CA09E9C14C2A833A7B7ACB1C9C12AC1 +Test: Encrypt +Comment: Set 3, vector 84 +Key: 5454545454545454545454545454545454545454545454545454545454545454 +Plaintext: 54545454545454545454545454545454 +Ciphertext: 8AB7ED64FE477B7D9A6B5B5056EA1E02 +Test: Encrypt +Comment: Set 3, vector 85 +Key: 5555555555555555555555555555555555555555555555555555555555555555 +Plaintext: 55555555555555555555555555555555 +Ciphertext: D610D6199D4FE03ED09AD568664F709A +Test: Encrypt +Comment: Set 3, vector 86 +Key: 5656565656565656565656565656565656565656565656565656565656565656 +Plaintext: 56565656565656565656565656565656 +Ciphertext: D400C1E6109F04AE50C1C341BA4E3175 +Test: Encrypt +Comment: Set 3, vector 87 +Key: 5757575757575757575757575757575757575757575757575757575757575757 +Plaintext: 57575757575757575757575757575757 +Ciphertext: DF888CBB7DBD8DE3F0BE6C6EDC72060F +Test: Encrypt +Comment: Set 3, vector 88 +Key: 5858585858585858585858585858585858585858585858585858585858585858 +Plaintext: 58585858585858585858585858585858 +Ciphertext: 9C3B100466C63AA93D420EDF54381BF4 +Test: Encrypt +Comment: Set 3, vector 89 +Key: 5959595959595959595959595959595959595959595959595959595959595959 +Plaintext: 59595959595959595959595959595959 +Ciphertext: 0BE794F0233BE9A7DB7C41A1CA4BA7E3 +Test: Encrypt +Comment: Set 3, vector 90 +Key: 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A +Plaintext: 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A +Ciphertext: 2C8D04D6B9DA81D07174729A07F25BB9 +Test: Encrypt +Comment: Set 3, vector 91 +Key: 5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B +Plaintext: 5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B +Ciphertext: FFCEB69835E2E5EF4C867CE28540F91F +Test: Encrypt +Comment: Set 3, vector 92 +Key: 5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C +Plaintext: 5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C +Ciphertext: A7F7F8437918BEFF5DCFCFB366CDFABD +Test: Encrypt +Comment: Set 3, vector 93 +Key: 5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D +Plaintext: 5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D +Ciphertext: 14C9736F407AE78D7D3ED18B875B940D +Test: Encrypt +Comment: Set 3, vector 94 +Key: 5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E +Plaintext: 5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E +Ciphertext: 1668A0C6A5734B98D9D641E0B6FAD80C +Test: Encrypt +Comment: Set 3, vector 95 +Key: 5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F +Plaintext: 5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F +Ciphertext: DA8775267C9722BA743A085F8591F06D +Test: Encrypt +Comment: Set 3, vector 96 +Key: 6060606060606060606060606060606060606060606060606060606060606060 +Plaintext: 60606060606060606060606060606060 +Ciphertext: 5F8172C28603C80206C276E0979EA40E +Test: Encrypt +Comment: Set 3, vector 97 +Key: 6161616161616161616161616161616161616161616161616161616161616161 +Plaintext: 61616161616161616161616161616161 +Ciphertext: E4938D0078D29E0247BF2EA0C1FCB85F +Test: Encrypt +Comment: Set 3, vector 98 +Key: 6262626262626262626262626262626262626262626262626262626262626262 +Plaintext: 62626262626262626262626262626262 +Ciphertext: A48FEE4F9FA4597303C2CF92061304A1 +Test: Encrypt +Comment: Set 3, vector 99 +Key: 6363636363636363636363636363636363636363636363636363636363636363 +Plaintext: 63636363636363636363636363636363 +Ciphertext: 3C8F6CF66C73684DDB09D1AA57CD0950 +Test: Encrypt +Comment: Set 3, vector 100 +Key: 6464646464646464646464646464646464646464646464646464646464646464 +Plaintext: 64646464646464646464646464646464 +Ciphertext: B3D9EE0337253E9C4027FEA938AB399C +Test: Encrypt +Comment: Set 3, vector 101 +Key: 6565656565656565656565656565656565656565656565656565656565656565 +Plaintext: 65656565656565656565656565656565 +Ciphertext: 3BE933A85E5997573077903CEB481AFA +Test: Encrypt +Comment: Set 3, vector 102 +Key: 6666666666666666666666666666666666666666666666666666666666666666 +Plaintext: 66666666666666666666666666666666 +Ciphertext: 06AFED96C6E7130EB3311D81CCE69F9C +Test: Encrypt +Comment: Set 3, vector 103 +Key: 6767676767676767676767676767676767676767676767676767676767676767 +Plaintext: 67676767676767676767676767676767 +Ciphertext: 183C3606139211F90F4849E93DB7DDEE +Test: Encrypt +Comment: Set 3, vector 104 +Key: 6868686868686868686868686868686868686868686868686868686868686868 +Plaintext: 68686868686868686868686868686868 +Ciphertext: 217C34184950DE7B43E46EE4BE88A9BE +Test: Encrypt +Comment: Set 3, vector 105 +Key: 6969696969696969696969696969696969696969696969696969696969696969 +Plaintext: 69696969696969696969696969696969 +Ciphertext: CA447ED204F2A4B2ED6B82E3926967B1 +Test: Encrypt +Comment: Set 3, vector 106 +Key: 6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A +Plaintext: 6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A +Ciphertext: B447F4BEBA7D88A5C62E5F9C316A4523 +Test: Encrypt +Comment: Set 3, vector 107 +Key: 6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B +Plaintext: 6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B +Ciphertext: DEDF599C54D0009795303013CD933B49 +Test: Encrypt +Comment: Set 3, vector 108 +Key: 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C +Plaintext: 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C +Ciphertext: B06280650C77C83AF3D71874AE00D3DA +Test: Encrypt +Comment: Set 3, vector 109 +Key: 6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D +Plaintext: 6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D +Ciphertext: 1BB5B9E9C7DC8AD690F5FC217B7B53C1 +Test: Encrypt +Comment: Set 3, vector 110 +Key: 6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E +Plaintext: 6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E +Ciphertext: FEECFCF0C172C6152F33E4DEE206EBCF +Test: Encrypt +Comment: Set 3, vector 111 +Key: 6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F +Plaintext: 6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F +Ciphertext: FA4C7EA42C425F37588CD273320940C9 +Test: Encrypt +Comment: Set 3, vector 112 +Key: 7070707070707070707070707070707070707070707070707070707070707070 +Plaintext: 70707070707070707070707070707070 +Ciphertext: 563AE5884FC374C4E45B96A6431E51E3 +Test: Encrypt +Comment: Set 3, vector 113 +Key: 7171717171717171717171717171717171717171717171717171717171717171 +Plaintext: 71717171717171717171717171717171 +Ciphertext: 0669E609578A33DBE637C5B86C7F425D +Test: Encrypt +Comment: Set 3, vector 114 +Key: 7272727272727272727272727272727272727272727272727272727272727272 +Plaintext: 72727272727272727272727272727272 +Ciphertext: B2AD99D3941924DDD2A73C4725A08EC3 +Test: Encrypt +Comment: Set 3, vector 115 +Key: 7373737373737373737373737373737373737373737373737373737373737373 +Plaintext: 73737373737373737373737373737373 +Ciphertext: 72C8239B5F4E5319EE05B6E39C9BD336 +Test: Encrypt +Comment: Set 3, vector 116 +Key: 7474747474747474747474747474747474747474747474747474747474747474 +Plaintext: 74747474747474747474747474747474 +Ciphertext: BAD014C4B0A5734AA48E7E80A42E80AF +Test: Encrypt +Comment: Set 3, vector 117 +Key: 7575757575757575757575757575757575757575757575757575757575757575 +Plaintext: 75757575757575757575757575757575 +Ciphertext: BBE294CDB3582B3C1F61ACD43A0E5DB5 +Test: Encrypt +Comment: Set 3, vector 118 +Key: 7676767676767676767676767676767676767676767676767676767676767676 +Plaintext: 76767676767676767676767676767676 +Ciphertext: C231DC35D38F5857BD3449D3E0A1EF1F +Test: Encrypt +Comment: Set 3, vector 119 +Key: 7777777777777777777777777777777777777777777777777777777777777777 +Plaintext: 77777777777777777777777777777777 +Ciphertext: B19E0BACBF3EC295AA6F99B0817B99F3 +Test: Encrypt +Comment: Set 3, vector 120 +Key: 7878787878787878787878787878787878787878787878787878787878787878 +Plaintext: 78787878787878787878787878787878 +Ciphertext: 0E81D1133E74F1A9425237377890584C +Test: Encrypt +Comment: Set 3, vector 121 +Key: 7979797979797979797979797979797979797979797979797979797979797979 +Plaintext: 79797979797979797979797979797979 +Ciphertext: E1149AA17A8B6499E0FA5C45F05D6582 +Test: Encrypt +Comment: Set 3, vector 122 +Key: 7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A +Plaintext: 7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A +Ciphertext: D9208954D8D28335E6F45FFB9D1B92D4 +Test: Encrypt +Comment: Set 3, vector 123 +Key: 7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B +Plaintext: 7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B +Ciphertext: DFABDB0594208A2902703E85C4A657FF +Test: Encrypt +Comment: Set 3, vector 124 +Key: 7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C +Plaintext: 7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C +Ciphertext: E05B6C6E90E852229BF0EFDC4FEB851E +Test: Encrypt +Comment: Set 3, vector 125 +Key: 7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D +Plaintext: 7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D +Ciphertext: 6834CCFDC940452CF40A0866009E58CC +Test: Encrypt +Comment: Set 3, vector 126 +Key: 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E +Plaintext: 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E +Ciphertext: 91449066A1966246636D9085E02002B0 +Test: Encrypt +Comment: Set 3, vector 127 +Key: 7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F +Plaintext: 7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F +Ciphertext: 235C2D836B2025CCCDAE4B26264132E2 +Test: Encrypt +Comment: Set 3, vector 128 +Key: 8080808080808080808080808080808080808080808080808080808080808080 +Plaintext: 80808080808080808080808080808080 +Ciphertext: 0C765AA494E048FC8BB23139F2124CB6 +Test: Encrypt +Comment: Set 3, vector 129 +Key: 8181818181818181818181818181818181818181818181818181818181818181 +Plaintext: 81818181818181818181818181818181 +Ciphertext: ED970D660C84642D0EAFF188F55CC33C +Test: Encrypt +Comment: Set 3, vector 130 +Key: 8282828282828282828282828282828282828282828282828282828282828282 +Plaintext: 82828282828282828282828282828282 +Ciphertext: E124EB4A8BE05CA633238DD69E81E057 +Test: Encrypt +Comment: Set 3, vector 131 +Key: 8383838383838383838383838383838383838383838383838383838383838383 +Plaintext: 83838383838383838383838383838383 +Ciphertext: 4653FBDD6CA7C13CE2DF31B1279B3D5A +Test: Encrypt +Comment: Set 3, vector 132 +Key: 8484848484848484848484848484848484848484848484848484848484848484 +Plaintext: 84848484848484848484848484848484 +Ciphertext: 2D4D87CFB763C3974CEBF6AE1C6269D4 +Test: Encrypt +Comment: Set 3, vector 133 +Key: 8585858585858585858585858585858585858585858585858585858585858585 +Plaintext: 85858585858585858585858585858585 +Ciphertext: F153B13F57F1AE16186EF3B1E98549B8 +Test: Encrypt +Comment: Set 3, vector 134 +Key: 8686868686868686868686868686868686868686868686868686868686868686 +Plaintext: 86868686868686868686868686868686 +Ciphertext: 5451DB2B141B894B4892C7F12BE3F389 +Test: Encrypt +Comment: Set 3, vector 135 +Key: 8787878787878787878787878787878787878787878787878787878787878787 +Plaintext: 87878787878787878787878787878787 +Ciphertext: 61B2185653CFF14EE873DBD3CB663E79 +Test: Encrypt +Comment: Set 3, vector 136 +Key: 8888888888888888888888888888888888888888888888888888888888888888 +Plaintext: 88888888888888888888888888888888 +Ciphertext: C17ACB243808B86349D4176EECF602DF +Test: Encrypt +Comment: Set 3, vector 137 +Key: 8989898989898989898989898989898989898989898989898989898989898989 +Plaintext: 89898989898989898989898989898989 +Ciphertext: 6FCE3ED2207D58A5976FE8B20B247275 +Test: Encrypt +Comment: Set 3, vector 138 +Key: 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A +Plaintext: 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A +Ciphertext: 403F73CC70C7F9A5E96CD77D61140961 +Test: Encrypt +Comment: Set 3, vector 139 +Key: 8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B +Plaintext: 8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B +Ciphertext: DE2B34DECB33550C97D6C074032F3333 +Test: Encrypt +Comment: Set 3, vector 140 +Key: 8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C +Plaintext: 8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C +Ciphertext: FB395AE4F537F8FB7C98BAD54BDB86A0 +Test: Encrypt +Comment: Set 3, vector 141 +Key: 8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D +Plaintext: 8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D +Ciphertext: 258E83BB639D0BEDE648F3AF96CC8E75 +Test: Encrypt +Comment: Set 3, vector 142 +Key: 8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E +Plaintext: 8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E +Ciphertext: A1B5E73720E43FA0871EAAE245B55A0E +Test: Encrypt +Comment: Set 3, vector 143 +Key: 8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F +Plaintext: 8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F +Ciphertext: 774A9ABE1FAB9E3B85A91C0F86758B0E +Test: Encrypt +Comment: Set 3, vector 144 +Key: 9090909090909090909090909090909090909090909090909090909090909090 +Plaintext: 90909090909090909090909090909090 +Ciphertext: 0A6EC1CF2056076933259AE6A337B185 +Test: Encrypt +Comment: Set 3, vector 145 +Key: 9191919191919191919191919191919191919191919191919191919191919191 +Plaintext: 91919191919191919191919191919191 +Ciphertext: C96729F87D62104F941DC21448756F95 +Test: Encrypt +Comment: Set 3, vector 146 +Key: 9292929292929292929292929292929292929292929292929292929292929292 +Plaintext: 92929292929292929292929292929292 +Ciphertext: 1CB85A610C2250A78143A31BB1C19094 +Test: Encrypt +Comment: Set 3, vector 147 +Key: 9393939393939393939393939393939393939393939393939393939393939393 +Plaintext: 93939393939393939393939393939393 +Ciphertext: 16194ABEDEA340C6D57E4C4F50640FBE +Test: Encrypt +Comment: Set 3, vector 148 +Key: 9494949494949494949494949494949494949494949494949494949494949494 +Plaintext: 94949494949494949494949494949494 +Ciphertext: 379A5A54C198FB03178EE841D67F3502 +Test: Encrypt +Comment: Set 3, vector 149 +Key: 9595959595959595959595959595959595959595959595959595959595959595 +Plaintext: 95959595959595959595959595959595 +Ciphertext: A25119AD8A0F6654ECDB2696CF4F8225 +Test: Encrypt +Comment: Set 3, vector 150 +Key: 9696969696969696969696969696969696969696969696969696969696969696 +Plaintext: 96969696969696969696969696969696 +Ciphertext: 264B7FAAD26DEC203D0DE29CE4F0F45B +Test: Encrypt +Comment: Set 3, vector 151 +Key: 9797979797979797979797979797979797979797979797979797979797979797 +Plaintext: 97979797979797979797979797979797 +Ciphertext: 2EBD2A2CD16284D206D81ACF18122E2E +Test: Encrypt +Comment: Set 3, vector 152 +Key: 9898989898989898989898989898989898989898989898989898989898989898 +Plaintext: 98989898989898989898989898989898 +Ciphertext: 25FB2B75B6915C0543412DF9EBD20FC3 +Test: Encrypt +Comment: Set 3, vector 153 +Key: 9999999999999999999999999999999999999999999999999999999999999999 +Plaintext: 99999999999999999999999999999999 +Ciphertext: 21B89B53845A828E0A14F4AE45940284 +Test: Encrypt +Comment: Set 3, vector 154 +Key: 9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A +Plaintext: 9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A +Ciphertext: 4CE809A241E8E59E231F2D00BE0EA285 +Test: Encrypt +Comment: Set 3, vector 155 +Key: 9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B +Plaintext: 9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B +Ciphertext: F914E06D9F7889DC71974DFF104F94D4 +Test: Encrypt +Comment: Set 3, vector 156 +Key: 9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C +Plaintext: 9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C +Ciphertext: AF08BADB48FF961FD5EB663FA3766FC6 +Test: Encrypt +Comment: Set 3, vector 157 +Key: 9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D +Plaintext: 9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D +Ciphertext: 05DDDE95AE659D6BBBD2B4E394399B53 +Test: Encrypt +Comment: Set 3, vector 158 +Key: 9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E +Plaintext: 9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E +Ciphertext: 25E6FE1C89F811D827BDF8D4E977071C +Test: Encrypt +Comment: Set 3, vector 159 +Key: 9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F +Plaintext: 9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F +Ciphertext: 3D00A9143A1829D05F787A904C48C75B +Test: Encrypt +Comment: Set 3, vector 160 +Key: A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0 +Plaintext: A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0 +Ciphertext: 391DF944B0E0BCB84483AF5C4F34D754 +Test: Encrypt +Comment: Set 3, vector 161 +Key: A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1 +Plaintext: A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1 +Ciphertext: BB2D2E556210A7C0EBA3165F63A74967 +Test: Encrypt +Comment: Set 3, vector 162 +Key: A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 +Plaintext: A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 +Ciphertext: A1B0BB24291B259AC4A1CDE9A3B817C9 +Test: Encrypt +Comment: Set 3, vector 163 +Key: A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3 +Plaintext: A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3 +Ciphertext: 6F798763B6ED7F8BB234D2CA78D026DC +Test: Encrypt +Comment: Set 3, vector 164 +Key: A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4 +Plaintext: A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4 +Ciphertext: 038443760056AB3D23BC70ECE6FB4397 +Test: Encrypt +Comment: Set 3, vector 165 +Key: A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5 +Plaintext: A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5 +Ciphertext: C75ECE40A7AE9BB38F604615C873EF02 +Test: Encrypt +Comment: Set 3, vector 166 +Key: A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6 +Plaintext: A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6 +Ciphertext: 2D308C2078842EDBBB35ABCA3F41E467 +Test: Encrypt +Comment: Set 3, vector 167 +Key: A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7 +Plaintext: A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7 +Ciphertext: 393C0E3350B3219DD8FD851C48E28C63 +Test: Encrypt +Comment: Set 3, vector 168 +Key: A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8 +Plaintext: A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8 +Ciphertext: 964BD4A28DB1434570E27FB3AD880398 +Test: Encrypt +Comment: Set 3, vector 169 +Key: A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9 +Plaintext: A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9 +Ciphertext: B668D17C027B550C0C22BDE151EB6EB1 +Test: Encrypt +Comment: Set 3, vector 170 +Key: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +Plaintext: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +Ciphertext: E14186F8205957B243CE522C16453621 +Test: Encrypt +Comment: Set 3, vector 171 +Key: ABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB +Plaintext: ABABABABABABABABABABABABABABABAB +Ciphertext: 0E352BEB6B6BCAFDAE61BBE86F8F1D0E +Test: Encrypt +Comment: Set 3, vector 172 +Key: ACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACAC +Plaintext: ACACACACACACACACACACACACACACACAC +Ciphertext: 4BCF038D9458EAAA3D279CCAC3F5D693 +Test: Encrypt +Comment: Set 3, vector 173 +Key: ADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADAD +Plaintext: ADADADADADADADADADADADADADADADAD +Ciphertext: D5EF17646A481C3B79AAB3C08B4F1611 +Test: Encrypt +Comment: Set 3, vector 174 +Key: AEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAE +Plaintext: AEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAE +Ciphertext: 37642DA589775C2FFA40A7274E9D56E2 +Test: Encrypt +Comment: Set 3, vector 175 +Key: AFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAF +Plaintext: AFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAF +Ciphertext: F829FA6B756F1B1D16B49CB7C8AFFA22 +Test: Encrypt +Comment: Set 3, vector 176 +Key: B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0 +Plaintext: B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0 +Ciphertext: 6FE1450D48D611031E81C70478DB5326 +Test: Encrypt +Comment: Set 3, vector 177 +Key: B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1 +Plaintext: B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1 +Ciphertext: 68C5ECE7F525F69DABF63288533C5C60 +Test: Encrypt +Comment: Set 3, vector 178 +Key: B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2 +Plaintext: B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2 +Ciphertext: 5DF627500627E59A5BAB5D30B6C93219 +Test: Encrypt +Comment: Set 3, vector 179 +Key: B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3 +Plaintext: B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3 +Ciphertext: AD3A4AC8F666C0FCA5D7995783D0986D +Test: Encrypt +Comment: Set 3, vector 180 +Key: B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 +Plaintext: B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 +Ciphertext: A3AEE54D09357B187622109296534F88 +Test: Encrypt +Comment: Set 3, vector 181 +Key: B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5 +Plaintext: B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5 +Ciphertext: 7D1D9A73DB386A717862C4F5089970E1 +Test: Encrypt +Comment: Set 3, vector 182 +Key: B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6 +Plaintext: B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6 +Ciphertext: 916347935FBD0D868A0127D602B91BD5 +Test: Encrypt +Comment: Set 3, vector 183 +Key: B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7 +Plaintext: B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7 +Ciphertext: 4F167893651993D9150ED9E0B780BF82 +Test: Encrypt +Comment: Set 3, vector 184 +Key: B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8 +Plaintext: B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8 +Ciphertext: 488352470ACF9361F22FAC1B3ED67003 +Test: Encrypt +Comment: Set 3, vector 185 +Key: B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9 +Plaintext: B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9 +Ciphertext: 4BBD307FCDE0F89C9A663A0F9C9358C5 +Test: Encrypt +Comment: Set 3, vector 186 +Key: BABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABA +Plaintext: BABABABABABABABABABABABABABABABA +Ciphertext: E402E706D262078113D6626E7071589E +Test: Encrypt +Comment: Set 3, vector 187 +Key: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB +Plaintext: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB +Ciphertext: 422D6FA4519F2E72420685CD4ED2CC8E +Test: Encrypt +Comment: Set 3, vector 188 +Key: BCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC +Plaintext: BCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC +Ciphertext: 6D14CC5F618DF7E0B2210F6C5DD62C92 +Test: Encrypt +Comment: Set 3, vector 189 +Key: BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD +Plaintext: BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD +Ciphertext: 5CC4A5E81F7D7EC528C150437AC2B027 +Test: Encrypt +Comment: Set 3, vector 190 +Key: BEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBE +Plaintext: BEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBE +Ciphertext: B3BE0F996494323504946446EDE489FC +Test: Encrypt +Comment: Set 3, vector 191 +Key: BFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBF +Plaintext: BFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBF +Ciphertext: ABC7DB10FE04BEE94F5887E539C1D235 +Test: Encrypt +Comment: Set 3, vector 192 +Key: C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0 +Plaintext: C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0 +Ciphertext: B18BE6FB1D04E76F21C0678A4333D255 +Test: Encrypt +Comment: Set 3, vector 193 +Key: C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1 +Plaintext: C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1 +Ciphertext: FC5802BAFEDC03088BBA0A5F22402968 +Test: Encrypt +Comment: Set 3, vector 194 +Key: C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2 +Plaintext: C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2 +Ciphertext: 8EA96801643AE7BF649EAC22812214D5 +Test: Encrypt +Comment: Set 3, vector 195 +Key: C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3 +Plaintext: C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3 +Ciphertext: F7683FCDDC2BB0BCFD1350F8E3D76602 +Test: Encrypt +Comment: Set 3, vector 196 +Key: C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4 +Plaintext: C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4 +Ciphertext: 08D0345431AE120CAD6C6D4275E00CA8 +Test: Encrypt +Comment: Set 3, vector 197 +Key: C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5 +Plaintext: C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5 +Ciphertext: 7CD50A623DA79EC84D61CD7FBDBA4153 +Test: Encrypt +Comment: Set 3, vector 198 +Key: C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 +Plaintext: C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 +Ciphertext: 42ACA2B048E5C58D8F004F0E8A2C6DEF +Test: Encrypt +Comment: Set 3, vector 199 +Key: C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7 +Plaintext: C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7 +Ciphertext: E03AD353225F76121D130740C75B839B +Test: Encrypt +Comment: Set 3, vector 200 +Key: C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8 +Plaintext: C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8 +Ciphertext: 26807D0A6D6330A77804B4B1AE84432B +Test: Encrypt +Comment: Set 3, vector 201 +Key: C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9 +Plaintext: C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9 +Ciphertext: 864CE880AE89660474F64B93AF4CE043 +Test: Encrypt +Comment: Set 3, vector 202 +Key: CACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACA +Plaintext: CACACACACACACACACACACACACACACACA +Ciphertext: 82EAD2C033986CAC1F4C3EEEEA1D1892 +Test: Encrypt +Comment: Set 3, vector 203 +Key: CBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCB +Plaintext: CBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCB +Ciphertext: 53F1A5C39DD062DF8D133B3A0FB3DA02 +Test: Encrypt +Comment: Set 3, vector 204 +Key: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +Plaintext: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +Ciphertext: E913208594B288125EEAE0EFEC764D39 +Test: Encrypt +Comment: Set 3, vector 205 +Key: CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD +Plaintext: CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD +Ciphertext: 7DAE4BD638A36A794A73E9B945BEF4D4 +Test: Encrypt +Comment: Set 3, vector 206 +Key: CECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECE +Plaintext: CECECECECECECECECECECECECECECECE +Ciphertext: 04E8155E3E81C261D3A9D4A800182A62 +Test: Encrypt +Comment: Set 3, vector 207 +Key: CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF +Plaintext: CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF +Ciphertext: F466172A8C4C7854F59388474098F441 +Test: Encrypt +Comment: Set 3, vector 208 +Key: D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0 +Plaintext: D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0 +Ciphertext: E95DBB0B366E77D7BC1BF206B95DAEBA +Test: Encrypt +Comment: Set 3, vector 209 +Key: D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1 +Plaintext: D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1 +Ciphertext: 76490E6DD8380855E26BCACF8746978F +Test: Encrypt +Comment: Set 3, vector 210 +Key: D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2 +Plaintext: D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2 +Ciphertext: 3C3B73C8FBDA8CAE5E0D7D0070735DA1 +Test: Encrypt +Comment: Set 3, vector 211 +Key: D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3 +Plaintext: D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3 +Ciphertext: B039EBC9C48828C3913A3BC346CAEAE3 +Test: Encrypt +Comment: Set 3, vector 212 +Key: D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4 +Plaintext: D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4 +Ciphertext: 0AFCC6A58BD3ADB2C0B2A1586C9FA8DE +Test: Encrypt +Comment: Set 3, vector 213 +Key: D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5 +Plaintext: D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5 +Ciphertext: C2187D0E74CE2307BC4DF249EA6E57F1 +Test: Encrypt +Comment: Set 3, vector 214 +Key: D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6 +Plaintext: D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6 +Ciphertext: F3F4AEA2492106A45C12D0029F58ACE1 +Test: Encrypt +Comment: Set 3, vector 215 +Key: D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7 +Plaintext: D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7 +Ciphertext: 3FFADF96B37B67D62D71387C52C41AE9 +Test: Encrypt +Comment: Set 3, vector 216 +Key: D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 +Plaintext: D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 +Ciphertext: 4C1644AD69F7D0D3A1E2B4B0E7F0A592 +Test: Encrypt +Comment: Set 3, vector 217 +Key: D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9 +Plaintext: D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9 +Ciphertext: 68FD6F6592AE5BD9245FA959FE1CA849 +Test: Encrypt +Comment: Set 3, vector 218 +Key: DADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADA +Plaintext: DADADADADADADADADADADADADADADADA +Ciphertext: 7AB97B70C2CCC7D0D1AA7A6D8B7C48CA +Test: Encrypt +Comment: Set 3, vector 219 +Key: DBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDB +Plaintext: DBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDB +Ciphertext: 961BF9E037E303B9B494C2EE063FC4CC +Test: Encrypt +Comment: Set 3, vector 220 +Key: DCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDC +Plaintext: DCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDC +Ciphertext: 0FBF042B227603DB4A1CC8EE62E93DF3 +Test: Encrypt +Comment: Set 3, vector 221 +Key: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD +Plaintext: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD +Ciphertext: 71360ED44C9FAF8F1139D31252A35F49 +Test: Encrypt +Comment: Set 3, vector 222 +Key: DEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDE +Plaintext: DEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDE +Ciphertext: 5E806BD29351AE456549E73B8DDC0026 +Test: Encrypt +Comment: Set 3, vector 223 +Key: DFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDF +Plaintext: DFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDF +Ciphertext: C7908A288B86C1C4FCE5A8A59457EFD3 +Test: Encrypt +Comment: Set 3, vector 224 +Key: E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0 +Plaintext: E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0 +Ciphertext: AAC45B53F6292082B93F949BD77E5776 +Test: Encrypt +Comment: Set 3, vector 225 +Key: E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 +Plaintext: E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 +Ciphertext: 231150ED4D85B4217B3EFC3E71A522C6 +Test: Encrypt +Comment: Set 3, vector 226 +Key: E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2 +Plaintext: E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2 +Ciphertext: 639D9C5EEC8D9569C6DF24630CA8257D +Test: Encrypt +Comment: Set 3, vector 227 +Key: E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3 +Plaintext: E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3 +Ciphertext: 0E7F8C538946D87A01AD49A8CC981B58 +Test: Encrypt +Comment: Set 3, vector 228 +Key: E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4 +Plaintext: E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4 +Ciphertext: 09A293907E499502D78569230D3F1A97 +Test: Encrypt +Comment: Set 3, vector 229 +Key: E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5 +Plaintext: E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5 +Ciphertext: ACF67CC086E386DA064EDBF97F7E889A +Test: Encrypt +Comment: Set 3, vector 230 +Key: E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6 +Plaintext: E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6 +Ciphertext: E7C44DB1A9FCAC410253A7E2674C54F6 +Test: Encrypt +Comment: Set 3, vector 231 +Key: E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7 +Plaintext: E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7 +Ciphertext: B99BA33ECB86DA790FF0CC4F0D41A065 +Test: Encrypt +Comment: Set 3, vector 232 +Key: E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8 +Plaintext: E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8 +Ciphertext: 73405114FDBDB81B1A54C4EFED1BB3FE +Test: Encrypt +Comment: Set 3, vector 233 +Key: E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9 +Plaintext: E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9 +Ciphertext: 80152E139834B3CC01EBF7E6417C5537 +Test: Encrypt +Comment: Set 3, vector 234 +Key: EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA +Plaintext: EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA +Ciphertext: 05CE579D4804FF3C7874571730D81CEC +Test: Encrypt +Comment: Set 3, vector 235 +Key: EBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEB +Plaintext: EBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEB +Ciphertext: F984801E7A806A130325E152DF60012E +Test: Encrypt +Comment: Set 3, vector 236 +Key: ECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECEC +Plaintext: ECECECECECECECECECECECECECECECEC +Ciphertext: 92CBB121474A307505425B4DD1B7F803 +Test: Encrypt +Comment: Set 3, vector 237 +Key: EDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDED +Plaintext: EDEDEDEDEDEDEDEDEDEDEDEDEDEDEDED +Ciphertext: 2DEB2F282D60EFCDB300EADB15C798D8 +Test: Encrypt +Comment: Set 3, vector 238 +Key: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE +Plaintext: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE +Ciphertext: 0F4D7D59B535E29D315D2A5C7BFE4973 +Test: Encrypt +Comment: Set 3, vector 239 +Key: EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF +Plaintext: EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF +Ciphertext: 61E391F7C29B5AD705121CF9559E5C04 +Test: Encrypt +Comment: Set 3, vector 240 +Key: F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +Plaintext: F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +Ciphertext: 65BCBE179D19A5BCF12D141A21E0F7A8 +Test: Encrypt +Comment: Set 3, vector 241 +Key: F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1 +Plaintext: F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1 +Ciphertext: FDB75C659B72AE81E51204CFCB86E631 +Test: Encrypt +Comment: Set 3, vector 242 +Key: F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2 +Plaintext: F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2 +Ciphertext: 5643ED3A3679B9E33E21CD0F95580877 +Test: Encrypt +Comment: Set 3, vector 243 +Key: F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 +Plaintext: F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 +Ciphertext: 618EFEB4C6E4270B81FF7DE786E68420 +Test: Encrypt +Comment: Set 3, vector 244 +Key: F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4 +Plaintext: F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4 +Ciphertext: 75A2A9CC91F006059CA873E5D73C2CCC +Test: Encrypt +Comment: Set 3, vector 245 +Key: F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5 +Plaintext: F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5 +Ciphertext: B55840B5001D1875C29A56EDFDE10E55 +Test: Encrypt +Comment: Set 3, vector 246 +Key: F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6 +Plaintext: F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6 +Ciphertext: 6DD9BDEA7EC0E622DE8B83460BDEA719 +Test: Encrypt +Comment: Set 3, vector 247 +Key: F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7 +Plaintext: F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7 +Ciphertext: D164075BD4CDC95288D896C7CC98285D +Test: Encrypt +Comment: Set 3, vector 248 +Key: F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8 +Plaintext: F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8 +Ciphertext: 8420071C55241802D88FB7AF17EBE43F +Test: Encrypt +Comment: Set 3, vector 249 +Key: F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9 +Plaintext: F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9 +Ciphertext: 03D1D5646E4B2B8A924AB242E485C5D1 +Test: Encrypt +Comment: Set 3, vector 250 +Key: FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA +Plaintext: FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA +Ciphertext: 29106DFB63F4CD6EF5D82CF07C0DBB3A +Test: Encrypt +Comment: Set 3, vector 251 +Key: FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB +Plaintext: FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB +Ciphertext: E9DC1CDD5011E00E0C5699201E1EA002 +Test: Encrypt +Comment: Set 3, vector 252 +Key: FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC +Plaintext: FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC +Ciphertext: 8006C8BD5B210F2FC5B3538F66A6BE0B +Test: Encrypt +Comment: Set 3, vector 253 +Key: FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD +Plaintext: FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD +Ciphertext: 2C6386229480E806D0CD21CDA0EA6B53 +Test: Encrypt +Comment: Set 3, vector 254 +Key: FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE +Plaintext: FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE +Ciphertext: ACDBB0F5A00E3CF63A89D9C09B44A058 +Test: Encrypt +Comment: Set 3, vector 255 +Key: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +Plaintext: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +Ciphertext: 4F05F28CA23EEAE205B67B1C95CD5280 +Test: Encrypt diff --git a/src-cryptopp/TestVectors/ccm.txt b/src-cryptopp/TestVectors/ccm.txt new file mode 100644 index 0000000..f23f084 --- /dev/null +++ b/src-cryptopp/TestVectors/ccm.txt @@ -0,0 +1,240 @@ +AlgorithmType: AuthenticatedSymmetricCipher +Name: AES/CCM +Source: aes-modes-src-07-10-08/Testvals/ccm.1, Basic Tests for CCM (compiled by B. R. Gladman) +Key: 404142434445464748494a4b4c4d4e4f +IV: 10111213141516 +Header: 0001020304050607 +Plaintext: 20212223 +Ciphertext: 7162015b +MAC: 4dac255d +Test: Encrypt +Key: 404142434445464748494a4b4c4d4e4f +IV: 1011121314151617 +Header: 000102030405060708090a0b0c0d0e0f +Plaintext: 202122232425262728292a2b2c2d2e2f +Ciphertext: d2a1f0e051ea5f62081a7792073d593d +MAC: 1fc64fbfaccd +Test: Encrypt +Key: 404142434445464748494a4b4c4d4e4f +IV: 101112131415161718191a1b +Header: 000102030405060708090a0b0c0d0e0f10111213 +Plaintext: 202122232425262728292a2b2c2d2e2f3031323334353637 +Ciphertext: e3b201a9f5b71a7a9b1ceaeccd97e70b6176aad9a4428aa5 +MAC: 484392fbc1b09951 +Test: Encrypt +Key: 404142434445464748494a4b4c4d4e4f +IV: 101112131415161718191a1b1c +Header: r256 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff +Plaintext: 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f +Ciphertext: 69915dad1e84c6376a68c2967e4dab615ae0fd1faec44cc484828529463ccf72 +MAC: b4ac6bec93e8598e7f0dadbcea5b +Test: Encrypt +Key: c97c1f67ce371185514a8a19f2bdd52f +IV: 005030f1844408b5039776e70c +Header: 08400fd2e128a57c5030f1844408abaea5b8fcba0000 +Plaintext: f8ba1a55d02f85ae967bb62fb6cda8eb7e78a050 +Ciphertext: f3d0a2fe9a3dbf2342a643e43246e80c3c04d019 +MAC: 7845ce0b16f97623 +Test: Encrypt +Key: 8f7a053fa577a5597529272097a603d5 +IV: 00eec1762c88de31f3cbba97ea +Header: 08c0ea100c846850eec1762c88deaf2ee9f46a070000 +Plaintext: 83a0634b5ed7627eb9df225e05740342de194117 +Ciphertext: 814b6965d05bf2b2ed38d4beb069fe82714a610b +MAC: 542fbf8da06aa4ae +Test: Encrypt +Key: 40cfb7a62e88013bd6d3affcc191041e +IV: 00b6a88adf36912fdca0f3a5ae +Header: 88c0d9577df763c8b6a88adf3691dc4a8bca94dd00000000 +Plaintext: 2c1bd036831c95496c5f4dbf3d559e72de802a18 +Ciphertext: 89d8580340b626a0b6d4d013bf18f291b89646c8 +MAC: fd1f1f61a9fb4bb3 +Test: Encrypt +Key: 8c89a2ebc96c7602707fcf24b32d3833 +IV: 078ef822734701f670a55a0fe3 +Header: 88c2712a9ddf11db8ef82273470159140dd646a200000700 +Plaintext: 4fad2b1c290fa5ebd872fbc3f3a074898f8b2fbb +Ciphertext: 9d59b15f371448c230f4d739052e13ab3b1a7b10 +MAC: 31fc88004f35ee3d +Test: Encrypt +Key: a574d5143bb25efddeff30122fdfd066 +IV: 0bf351946bc96ba7ffe03c0e37 +Header: 88c245dec69a7480f351946bc96be276fbe6c12700000b00 +Plaintext: 28969b954f263a8018a9ef70a8b051462481922e +Ciphertext: eb4ae4956a801da9624b7e0c18b23e615ec03af6 +MAC: ce0c3be197d305eb +Test: Encrypt +Key: f71eea4e1f58804b9717230ad0614641 +IV: 0dbff943b9f9a66b81eca48989 +Header: 88425af28430fdabbff943b9f9a6ab1d98c7fe7300000d00 +Plaintext: abfda22d3a0bfc9cc1fc079363c2fca143e6eb1d +Ciphertext: 9a709b60a39d40b1dfb612e18b5f114badb6cc86 +MAC: 309a8d5c466bbb71 +Test: Encrypt +Key: 1bdb34980e038124a1db1a892bec366a +IV: 00efec952016915eec4073e723 +Header: 08419b50f4fd56f6efec9520169183570c4ccdee0000 +Plaintext: 98beca86f4b38da20cfdf24724c58eb835665339 +Ciphertext: 12c537ebf3ab584ef1fef9a1f3547a8c13b3225a +MAC: 2d0957ecfabe95b9 +Test: Encrypt +Key: 6eac1bf54bd54edb2321754303024c71 +IV: 0aca3f3aae60c4cefd996eccdd +Header: 88c1552d5f72bb70ca3f3aae60c48ba9b5f82c2f00000a00 +Plaintext: 57cb5c0e5fcd885e9a4239e9b9cad60d64375979 +Ciphertext: 4bf281ef8ec7739f91591b97a87dc14b3fa17462 +MAC: 6dba8ef7f08087dd +Test: Encrypt +Key: 494b501e194675971a48d08c5bc353cb +IV: 0aa4ad6d319985ba82e93437b3 +Header: 88c19afb798b8a4ba4ad6d319985bc429e8f0afa00000a00 +Plaintext: 25a98f9c1bd9c93cf383ab9d98152d76cb4a32c6 +Ciphertext: 561a0d068eac2eadb0c57fe2d0a6cc7398b6ddbf +MAC: cfe438cbea61fa9a +Test: Encrypt +Key: 489e49bc3cfe3fce3895820e872ee1a3 +IV: 0053f869fe279acf1d3e75fea9 +Header: 084340ec29fa759b53f869fe279af0f9f8a65416000052bfd2703d24 +Plaintext: 7f91f2472d7a121c9cdd4b6c9080675a1020aa00 +Ciphertext: 25df5173835e4fba23bc05a253885ebed3ac4871 +MAC: c868a725552c5565 +Test: Encrypt +Key: 02be5c4545672a07e4e314d70f1f9e85 +IV: 0d347ceb9aabffd2d6596e55d4 +Header: 88c3298c0baa9190347ceb9aabffd83d4886e5c20000e29d524ae1960d00 +Plaintext: f9a812e4a28af7f3714d4bf6622e5932f2184509 +Ciphertext: 6315500f924295cd3eafbdc3e151b1df46465b71 +MAC: 681fdee8513c62dc +Test: Encrypt +Key: 77077ed79453e4a18d60438cc6484d6e +IV: 00d8ac5a7ec44450b01e77fd8e +Header: 0843aa288b8435bcd8ac5a7ec444e8b46250538b0000e81402c2ee11 +Plaintext: 431981a2336d02f8cb8448d5428916be95293537 +Ciphertext: cf71b2ccbd590b20800792f359ed1cfd74d800b4 +MAC: fd0f41f426bb8f30 +Test: Encrypt +Source: aes-modes-src-07-10-08/Testvals/ccm.2, Vectors for IEEE P1619.1 CCM Mode +Header: +Key: 0000000000000000000000000000000000000000000000000000000000000000 +IV: 000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: c1944044c8e7aa95d2de9513c7f3dd8c +MAC: 4b0a3e5e51f151eb0ffae7c43d010fdb +Test: Encrypt +Plaintext: +Ciphertext: +Key: 0000000000000000000000000000000000000000000000000000000000000000 +IV: 000000000000000000000000 +Header: 00000000000000000000000000000000 +MAC: 904704e89fb216443cb9d584911fc3c2 +Test: Encrypt +Key: 0000000000000000000000000000000000000000000000000000000000000000 +IV: 000000000000000000000000 +Header: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: c1944044c8e7aa95d2de9513c7f3dd8c +MAC: 87314e9c1fa01abe6a6415943dc38521 +Test: Encrypt +Header: +Key: fb7615b23d80891dd470980bc79584c8b2fb64ce60978f4d17fce45a49e830b7 +IV: dbd1a3636024b7b402da7d6f +Plaintext: a845348ec8c5b5f126f50e76fefd1b1e +Ciphertext: cc881261c6a7fa72b96a1739176b277f +MAC: 3472e1145f2c0cbe146349062cf0e423 +Test: Encrypt +Key: 404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f +IV: 101112131415161718191a1b +Header: 000102030405060708090a0b0c0d0e0f10111213 +Plaintext: 202122232425262728292a2b2c2d2e2f3031323334353637 +Ciphertext: 04f883aeb3bd0730eaf50bb6de4fa2212034e4e41b0e75e5 +MAC: 9bba3f3a107f3239bd63902923f80371 +Test: Encrypt +Key: 404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f +IV: 101112131415161718191a1b +Header: r256 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff +Plaintext: 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f +Ciphertext: 04f883aeb3bd0730eaf50bb6de4fa2212034e4e41b0e75e577f6bf2422c0f6d2 +MAC: 3376d2cf256ef613c56454cbb5265834 +Test: Encrypt +Key: 404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f +IV: 101112131415161718191a1b +Header: 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f +Plaintext: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f 404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f 606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f a0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf e0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff +Ciphertext: 24d8a38e939d2710cad52b96fe6f82010014c4c43b2e55c557d69f0402e0d6f2 06c53d6cbd3f1c3c6de5dcdcad9fb74f25741dea741149fe4278a0cc24741e86 58cc0523b8d7838c60fb1de4b7c3941f5b26dea9322aa29656ec37ac18a9b108 a6f38b7917f5a9c398838b22afbd17252e96694a9e6237964a0eae21c0a6e152 15a0e82022926be97268249599e456e05029c3ebc07d78fc5b4a0862e04e68c2 9514c7bdafc4b52e04833bf30622e4eb42504a44a9dcbc774752de7bb82891ad 1eba9dc3281422a8aba8654268d3d9c81705f4c5a531ef856df5609a159af738 eb753423ed2001b8f20c23725f2bef18c409f7e52132341f27cb8f0e79894dd9 +MAC: ebb1fa9d28ccfe21bdfea7e6d91e0bab +Test: Encrypt +Key: fb7615b23d80891dd470980bc79584c8b2fb64ce6097878d17fce45a49e830b7 +IV: dbd1a3636024b7b402da7d6f +Header: 36 +Plaintext: a9 +Ciphertext: 9d +MAC: 3261b1cf931431e99a32806738ecbd2a +Test: Encrypt +Key: f8d476cfd646ea6c2384cb1c27d6195dfef1a9f37b9c8d21a79c21f8cb90d289 +IV: dbd1a3636024b7b402da7d6f +Header: 7bd859a247961a21823b380e9fe8b65082ba61d3 +Plaintext: 90ae61cf7baebd4cade494c54a29ae70269aec71 +Ciphertext: 6c05313e45dc8ec10bea6c670bd94f31569386a6 +MAC: 8f3829e8e76ee23c04f566189e63c686 +Test: Encrypt +Source: RFC 3610 +Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF +IV: 00 00 00 03 02 01 00 A0 A1 A2 A3 A4 A5 +Header: 00 01 02 03 04 05 06 07 +Plaintext: 08 09 0A 0B 0C 0D 0E 0F\ + 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E +Ciphertext: 58 8C 97 9A 61 C6 63 D2\ + F0 66 D0 C2 C0 F9 89 80 6D 5F 6B 61 DA C3 84 +MAC: 17 E8 D1 2C FD F9 26 E0 +Test: Encrypt +MAC: 17 E8 D1 2C FD F9 26 00 +Test: NotVerify +Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF +IV: 00 00 00 04 03 02 01 A0 A1 A2 A3 A4 A5 +Header: 00 01 02 03 04 05 06 07 +Plaintext: 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F +Ciphertext: 72 C9 1A 36 E1 35 F8 CF 29 1C A8 94 08 5C 87 E3 CC 15 C4 39 C9 E4 3A 3B +MAC: A0 91 D5 6E 10 40 09 16 +Test: Encrypt +Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF +IV: 00 00 00 05 04 03 02 A0 A1 A2 A3 A4 A5 +Header: 00 01 02 03 04 05 06 07 +Plaintext: 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 +Ciphertext: 51 B1 E5 F4 4A 19 7D 1D A4 6B 0F 8E 2D 28 2A E8 71 E8 38 BB 64 DA 85 96 57 +MAC: 4A DA A7 6F BD 9F B0 C5 +Test: Encrypt +Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF +IV: 00 00 00 06 05 04 03 A0 A1 A2 A3 A4 A5 +Header: 00 01 02 03 04 05 06 07 08 09 0A 0B +Plaintext: 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E +Ciphertext: A2 8C 68 65 93 9A 9A 79 FA AA 5C 4C 2A 9D 4A 91 CD AC 8C +MAC: 96 C8 61 B9 C9 E6 1E F1 +Test: Encrypt +Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF +IV: 00 00 00 07 06 05 04 A0 A1 A2 A3 A4 A5 +Header: 00 01 02 03 04 05 06 07 08 09 0A 0B +Plaintext: 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F +Ciphertext: DC F1 FB 7B 5D 9E 23 FB 9D 4E 13 12 53 65 8A D8 6E BD CA 3E +MAC: 51 E8 3F 07 7D 9C 2D 93 +Test: Encrypt +Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF +IV: 00 00 00 08 07 06 05 A0 A1 A2 A3 A4 A5 +Header: 00 01 02 03 04 05 06 07 08 09 0A 0B +Plaintext: 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 +Ciphertext: 6F C1 B0 11 F0 06 56 8B 51 71 A4 2D 95 3D 46 9B 25 70 A4 BD 87 +MAC: 40 5A 04 43 AC 91 CB 94 +Test: Encrypt +Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF +IV: 00 00 00 09 08 07 06 A0 A1 A2 A3 A4 A5 +Header: 00 01 02 03 04 05 06 07 +Plaintext: 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E +Ciphertext: 01 35 D1 B2 C9 5F 41 D5 D1 D4 FE C1 85 D1 66 B8 09 4E 99 9D FE D9 6C +MAC: 04 8C 56 60 2C 97 AC BB 74 90 +Test: Encrypt +Key: C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF +IV: 00 00 00 0A 09 08 07 A0 A1 A2 A3 A4 A5 +Header: 00 01 02 03 04 05 06 07 +Plaintext: 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F +Ciphertext: 7B 75 39 9A C0 83 1D D2 F0 BB D7 58 79 A2 FD 8F 6C AE 6B 6C D9 B7 DB 24 +MAC: C1 7B 44 33 F4 34 96 3F 34 B4 +Test: Encrypt diff --git a/src-cryptopp/TestVectors/cmac.txt b/src-cryptopp/TestVectors/cmac.txt new file mode 100644 index 0000000..4fa6c41 --- /dev/null +++ b/src-cryptopp/TestVectors/cmac.txt @@ -0,0 +1,38 @@ +AlgorithmType: MAC +Name: CMAC(AES) +Source: RFC 4493 +Key: 2b7e1516 28aed2a6 abf71588 09cf4f3c +Message: +MAC: bb1d6929 e9593728 7fa37d12 9b756746 +Test: Verify +Message: 6bc1bee2 2e409f96 e93d7e11 7393172a +MAC: 070a16b4 6b4d4144 f79bdd9d d04a287c +Test: Verify +Message: 6bc1bee2 2e409f96 e93d7e11 7393172a ae2d8a57 1e03ac9c 9eb76fac 45af8e51 30c81c46 a35ce411 +MAC: dfa66747 de9ae630 30ca3261 1497c827 +Test: Verify +Message: 6bc1bee2 2e409f96 e93d7e11 7393172a ae2d8a57 1e03ac9c 9eb76fac 45af8e51 30c81c46 a35ce411 e5fbc119 1a0a52ef f69f2445 df4f9b17 ad2b417b e66c3710 +MAC: 51f0bebf 7e3b9d92 fc497417 79363cfe +Test: Verify +MAC: 51f0bebf 7e3b9d92 fc497417 79363cff +Test: NotVerify + +AlgorithmType: MAC +Name: CMAC(DES-EDE3) +Source: http://csrc.nist.gov/groups/STM/cavp/documents/mac/cmactestvectors.zip +Key: f8fba7b9b3e9d68a 2f70bfd304d32a15 9e13453e0d16928a +Message: +MAC: eb61515b +Test: VerifyTruncated +Key: 344a6732dc5e5431 e98a4f7c323dc1c4 6b0275dc150e68e9 +Message: 25db0710fb165d316e7c32dd25648ed0 +MAC: 862f0e2b +Test: VerifyTruncated +Key: 20ae32c49bab3bf8 f86bb66173fb54d5 3e700868c46bc291 +Message: 582bd9c8c36ec815d0a9 +MAC: 0d62f14f +Test: VerifyTruncated +Key: 62232501b9e9c1b5 54209d7c075d2c31 73a2f289a84c49ce +Message: adaf4bfffab79ffb60b94647faac634929c56e694052881881e60b1149b6 +MAC: a05674f2c905d153 +Test: Verify diff --git a/src-cryptopp/TestVectors/dlies.txt b/src-cryptopp/TestVectors/dlies.txt new file mode 100644 index 0000000..aa71155 --- /dev/null +++ b/src-cryptopp/TestVectors/dlies.txt @@ -0,0 +1,542 @@ +AlgorithmType: AsymmetricCipher +Name: DLIES(NoCofactorMultiplication, KDF2(SHA-1), XOR, HMAC(SHA-1), DHAES) +Source: generated by Wei Dai using Crypto++ 5.1 +Comment: keys are encoded as DSA keys, with OID id-dsa +KeyFormat: DER +Comment: 1024-bit DLIES key +PrivateKey: \ + 308201370201003082011706072a8648ce3804013082010a02818100ba3ed941\ + 10332be99b77a345da72a33146ca960498a6fc2e0e207fdeaadf69c3e5650df7\ + 3255475854900b75af7f6aac021de687a1c166ecb2ab6ec6b9da82ad4fb0f48a\ + 966a2b968406e18ba50947d7ee3bb1f13511cb4dde191f0ade1933d089c5e82a\ + b8d283943d85ef0102e173abf2635aeac2f84cfc9ec6c4e8f3fbc4130281805d\ + 1f6ca0881995f4cdbbd1a2ed395198a3654b024c537e1707103fef556fb4e1f2\ + b286fb992aa3ac2a4805bad7bfb556010ef343d0e0b3765955b7635ced4156a7\ + d87a454b3515cb420370c5d284a3ebf71dd8f89a88e5a6ef0c8f856f0c99e844\ + e2f4155c6941ca1ec2f7808170b9d5f931ad75617c267e4f63627479fde20902\ + 01030417021501fdc788cd93f07dba3af2de42ae5aa3ede219919d +PublicKey: \ + 308201a23082011706072a8648ce3804013082010a02818100ba3ed94110332b\ + e99b77a345da72a33146ca960498a6fc2e0e207fdeaadf69c3e5650df7325547\ + 5854900b75af7f6aac021de687a1c166ecb2ab6ec6b9da82ad4fb0f48a966a2b\ + 968406e18ba50947d7ee3bb1f13511cb4dde191f0ade1933d089c5e82ab8d283\ + 943d85ef0102e173abf2635aeac2f84cfc9ec6c4e8f3fbc4130281805d1f6ca0\ + 881995f4cdbbd1a2ed395198a3654b024c537e1707103fef556fb4e1f2b286fb\ + 992aa3ac2a4805bad7bfb556010ef343d0e0b3765955b7635ced4156a7d87a45\ + 4b3515cb420370c5d284a3ebf71dd8f89a88e5a6ef0c8f856f0c99e844e2f415\ + 5c6941ca1ec2f7808170b9d5f931ad75617c267e4f63627479fde20902010303\ + 81840002818029eaa5b193357c200e0d42f374d4c003c633c77f4778fe40ad0b\ + d035b87ae5da4e74110ec2b15eefe1bd8b9357534c85328382946d314e15b79f\ + 7b854227012dfaac9bd862e73a5630e01327b36319765a3eb1434e108ef6421c\ + 659e3f9223966759611429b3c86ed9937563efbfad8bfedcfa92db3d7d2157fe\ + 2c8a33f08636 +Test: KeyPairValidAndConsistent +Plaintext: 76 +Ciphertext: B11D906CC5A8E71CA8962A8CC0AC4CAFF2DA00DC130C370F42D11FCF5C37DE046EBC07C7D457CA351CE456A043695D14ED055ADAD2B58BE0DF992685EF8B0D21597A43D7B3D9634A077CB70C4590CD73C20FAAACBC5649413EECA0C7B3CBF469E531299398F61496C51FE9FFE48AE9FE6034F104EFC562DE9529C776B86ADD4025AD6B0C3687B012F92C7B9E82F794E4FBE247D644 +Test: DecryptMatch +Plaintext: 89338CE80AFB62E9577A310E40311BB3F77F +Ciphertext: 8A33B0E212DB8155CA796B472F55CD77267C9106229B6055141EA3AAAE42AD27249D90E70F892B0CDC80D29D3D586A5CA6FE67D4BB44C58B03496708F80681125DCEF983B7453B1E4F927438BD2E3E506C1951E9F19BA70F9B687012440CD75C0BB78BDCFAB22AF535D3E2670ABD1F4D44ED95F3360536612B1A7DF35E2A88F66BD6E8C813EB9DC89D93A85C9A0BA13E4862B91171B681E64A0750197C6467B22566BC640E11 +Test: DecryptMatch +Plaintext: 0835455ABD53E6FB11ED9B0C00485D3C6845DB +Ciphertext: A81181517BD270B0D921AF735052898932008DF00D501EDE0D2D564871D61A6A837776E8D7C7F9B0E5F9181C1FC68BC430F30ABB1A64D62B444C0AC5AAE588B4481AEF08B38E466155F10CA04C8202F281186016AE35212A2C7815A22DB2750ABD526D285BDBC598672BFB52E95CE33A0D3E5DCF4CF5F46224CFBB85297F3AB170C8B9478994E32D9A21A452B095D3D902E92C7E444A3307FDD7256FE49341142E5FF7A616475A +Test: DecryptMatch +Plaintext: 1EBED48EC47B6987091C52BC +Ciphertext: 1DF446FF43AAAAAC8E3F7D70C912E2D45AB832BCA3D0FBD17AF864B9EA878C45B9E2902804171A739A0552BB7CE0CD46DC16343714CC9C2E71AE26304885EEEB242665814DD9E33C480ABA214755D5449F16CD8870D1AB3A8E64E45E463AB3F4D3031FA3ECD395B61B372602665FCF218D9C51E8C791FA1E5BCC2916EFBB482E1814632CDF0F1852EE4943D9652DAA4E1F3B22F17F57F51D52A0997BED5B04ED +Test: DecryptMatch +Plaintext: 65D8 +Ciphertext: 4385797FD38AD5DFBB4F613BC87637B0051501E57699A5880E235DB7A6994A04A1613D0C8E07E36AFD08F2E47D018951B22E7625DA647AA1A0791DB3B2FA794610892D9A3D3F173CF95277B4B1EB92579A229510B67E171CB5BBA8B3AA732047BA038816A30124AF1C4C57CA80E93AACCC8EC70BCF7867914E7DE2C403568F9778F8DBEAF08FDB9F48452054C9735DC84F012DF8FE17 +Test: DecryptMatch +Plaintext: F86D8ED91E9934125DA6E9B4E97545C83A +Ciphertext: 13B0AE03AB532D5E31C9384B4E726A9AC73583CFBB0643EC322E3D2D45D9358CAF745B0541C136E8AA2220C42CEC9E1ED174886475538732AA6D6417DA89FA411AEDEADCD9F15D25D27D0AE252F77E888470AE696D5805CE8CCCB40B45D4AA835E97C7BF2CD6A2B4FEC6FCF858606CE4695DCE998C518360068ED028FC882478BF96096D92C166899EB51778BC4B7DA1BA8C4B6CEBA1139F17CEE484EA104A0325420A3D56 +Test: DecryptMatch +Comment: 1025-bit DLIES key +PrivateKey: \ + 308201380201003082011806072a8648ce3804013082010b028181015dd79808\ + 07a15e557e3a39466eb2987828c536a871d4fc7f3723d52f8145a0d10d996295\ + 64aca54fd567c0509ef3c428fac68d916551e77a5ca0ed6d9f12cc96262b1f11\ + 49f398ef9f0f17fc0ed92bb917f890d1e6a4f62b91a7978d0aa1bf53b89805c1\ + 06ebebd0924cb99a4168a38dad65238236d4d166d38a3dfd5359ec5f02818100\ + aeebcc0403d0af2abf1d1ca337594c3c14629b5438ea7e3f9b91ea97c0a2d068\ + 86ccb14ab25652a7eab3e0284f79e2147d6346c8b2a8f3bd2e5076b6cf89664b\ + 13158f88a4f9cc77cf878bfe076c95dc8bfc4868f3527b15c8d3cbc68550dfa9\ + dc4c02e08375f5e849265ccd20b451c6d6b291c11b6a68b369c51efea9acf62f\ + 020102041702150f514282f489098f1df0c7be02ccbb3f23bed00376 +PublicKey: \ + 308201a43082011806072a8648ce3804013082010b028181015dd7980807a15e\ + 557e3a39466eb2987828c536a871d4fc7f3723d52f8145a0d10d99629564aca5\ + 4fd567c0509ef3c428fac68d916551e77a5ca0ed6d9f12cc96262b1f1149f398\ + ef9f0f17fc0ed92bb917f890d1e6a4f62b91a7978d0aa1bf53b89805c106ebeb\ + d0924cb99a4168a38dad65238236d4d166d38a3dfd5359ec5f02818100aeebcc\ + 0403d0af2abf1d1ca337594c3c14629b5438ea7e3f9b91ea97c0a2d06886ccb1\ + 4ab25652a7eab3e0284f79e2147d6346c8b2a8f3bd2e5076b6cf89664b13158f\ + 88a4f9cc77cf878bfe076c95dc8bfc4868f3527b15c8d3cbc68550dfa9dc4c02\ + e08375f5e849265ccd20b451c6d6b291c11b6a68b369c51efea9acf62f020102\ + 038185000281810107143658b98a3725010d3631a3f4f7448cb967ac0118e4ca\ + 8fc8871eb4fb872d55c52d93a4f21eed98b6499db74315956a268f38a288958b\ + f7c4d548662c668669d69375e0cb710ff3a1a9f43e49add1f7ae58b836b6444e\ + 419e40474c27066cb03aae8132e65f3fead0109307ab1c7f0254eb14e9d76639\ + 1a66ca1ba442b425 +Test: KeyPairValidAndConsistent +Plaintext: 256F07E0D37D69BE542BD17FA98CE4CFC3DA849B +Ciphertext: 01269CE30DE12430904CEC9D8B91A6D8860B4F8D37FCE7DBDCE8FA18AC521684F4C1CD5C38BF3B42C259033CD36A53F0376A0CDD801979CF1B76ADD72AFDD27830BD85B373C4D451B84926ABA34012EB98331F0B81CCF8E801ACCDEE88A35DF60EFADABA1F395250A15463203FDCCEDAB7DD6CD1271B38A5E0946F8D189B225E8A307D198AC5E4EB33BCF26A02C0C602AA14592AEA01452E4F8AE46E7A032BABD1BA8ACB0919F2EA18 +Test: DecryptMatch +Plaintext: A992 +Ciphertext: 007822B0BDF45CC5B15102B5E21F7656C8896E98FAD6C2AF6CD55D0DB90B7A6B05E36D260C7A5C070526813290BCA722959B9B9BF00041B4B7F3E3EAFA9B5376A1E02944EDA55B99202601AE6D402D56617B56B28BAC1B405016053CDC78AB4D372B0D58E7380D50F1CD0E31B8CB77FD2F6BA3E7A436A5B35552B9974EA5AB30AC0C4989E34F5FD7D272417FF2094B97119BEB2C73C68B +Test: DecryptMatch +Plaintext: 1D20C118C894EFDC67DAC33E56179C5D262C83 +Ciphertext: 001587AFEC265C244875371B680521FF93F0B1196901A7D580785B62A257B1736C86D1D9E59A31E62F53B92B209B45A7952776C6AC839243B0BBF3A059E6CEE99B120BBD45922B4E813DDE0F5793A42B3AF2DDDAA357136A010519D884589A1F9912110020A8C16E9B91C753EB8842B3224FE9C9A22AE2B82251CFF7799E78885B0B67B27DAAC6A7B58013C31115C2B8C0C0176BC2A7B96A299CC75693B4F2138B2B4053CB5320D5 +Test: DecryptMatch +Plaintext: 83BC82A4F7A4DFC96CD7798BAC52254CD6E9 +Ciphertext: 0085E83465997BFED9CAE63B04B0419578D0BD85B1A65285E5537F4367E5E7E11DD8762BD3335916A13B8CF9D5BC651E762458E9879363B06748BEA0CA86D32CBC4F1B0C0BF67E616B872A64F7356241CD052944F6594A570522EF2BCC53D90E3326D2ECFA036C46256D9B678C93BE5877749AF8FF8FEDB6E1E17B67C7B6C6098D0C71D5B2AB503AFD7739ABCC8DE67DAC056AFE99D8A107230BA88C282FB8FD46E9E9E2C6874A +Test: DecryptMatch +Plaintext: 157597899A950A32 +Ciphertext: 013623199FFDD0D4689A4C50A9FEA3C2250D0C73F209F33BF3EF13E6035976D6F3EAFBA3D83A3862E4B6DFC7581EA43B62F49BC85392B7EAB854F92DA8DD5921A6A4C42777E89004EB7E6D479BD028F758171C324168DC0814369C6BCD8471D9620C4E9BED785A220EF9C0DCF1201311A16C51341E0551043C6EAB45E04A81C9280633F58621D8D3492864FFF6A39EDC48450ABFE0C7AABAEB9A86CFFD +Test: DecryptMatch +Plaintext: CDE651 +Ciphertext: 0040308CCDAB105426597D84A64665200A93208713004DB38594C490F7B85F08ADB67BBE47B7FB7BBDA435A6B6A2CA0B4CBE0FDCBD4FF078FD052213CBCAA4580D1C7962A3505DAA9BEA2957718AB36D061E61B9DEB3D7DD726975C6E7FD79AADBF649F5ABE51AC384E967D3CDAFD9EAA18EEB69774961E439F54844FA22DA1B6892E86471DAE6F7E74CACC944123234826621C7634AE34E +Test: DecryptMatch +Comment: 1026-bit DLIES key +PrivateKey: \ + 308201380201003082011806072a8648ce3804013082010b028181031e7d8589\ + b9fa11e77204b8c1b27ad66b39863978d26912a65de306dcb32a0c7c96bb431d\ + c4a14204a8f01a65b0fe56a4d016716914c21576f10d63dac5f49287636519ac\ + f9be56c9f58eeb90ba3240d4cce26f647bfd86360cf0f6b8ff609ae2ef736558\ + 155a1498adf4e92dc90f34169123a5fcd8ddfc763c81658a4d08383702818101\ + 8f3ec2c4dcfd08f3b9025c60d93d6b359cc31cbc693489532ef1836e5995063e\ + 4b5da18ee250a10254780d32d87f2b52680b38b48a610abb7886b1ed62fa4943\ + b1b28cd67cdf2b64fac775c85d19206a667137b23dfec31b06787b5c7fb04d71\ + 77b9b2ac0aad0a4c56fa7496e4879a0b4891d2fe6c6efe3b1e40b2c526841c1b\ + 020102041702151fa3003b00efad22ecc26c5115e6d036d13d3b2f7e +PublicKey: \ + 308201a33082011806072a8648ce3804013082010b028181031e7d8589b9fa11\ + e77204b8c1b27ad66b39863978d26912a65de306dcb32a0c7c96bb431dc4a142\ + 04a8f01a65b0fe56a4d016716914c21576f10d63dac5f49287636519acf9be56\ + c9f58eeb90ba3240d4cce26f647bfd86360cf0f6b8ff609ae2ef736558155a14\ + 98adf4e92dc90f34169123a5fcd8ddfc763c81658a4d083837028181018f3ec2\ + c4dcfd08f3b9025c60d93d6b359cc31cbc693489532ef1836e5995063e4b5da1\ + 8ee250a10254780d32d87f2b52680b38b48a610abb7886b1ed62fa4943b1b28c\ + d67cdf2b64fac775c85d19206a667137b23dfec31b06787b5c7fb04d7177b9b2\ + ac0aad0a4c56fa7496e4879a0b4891d2fe6c6efe3b1e40b2c526841c1b020102\ + 038184000281802c6360e6e3eba6da6efb5bce8d07a99e42949b68b3c2900583\ + c2eb34498081c7212d8dc95a631d63edeafc625f8faf063e57b41d7b662ba9c1\ + a99b3f2506fdf5e59116a0e93e7e94aab55691abae75eaac9637a713949360a4\ + 5f6908f23ba5503d4760bcd6f7abceb8351a66bb14fae05f03b1494e7ef4154c\ + 99a9cb6a9bfe12 +Test: KeyPairValidAndConsistent +Plaintext: DEC85711F12C0D1D6C26797E91B0F39B37 +Ciphertext: 0215D75DD99B8A59DEA3FBA9B0F8A621EFFBFD831E9543749B04B495147CE9B56D519EE71BDF56D86FD1D9C1AE8BC1D7F29DC469A05221E4A31C726971731CF627E63FAB269FC92DEDDFF3319819373F299D55F4CABE08DADF29A7C60E9B4E2806899371B93A853F828EC4312D94CFDADFDEF2037D9C1FCE21A3E451006AC542E1BC36D3C33AEAC0D1666C26AA886F4C118836EDCA7C5A428E407C4ACD62A885C03202230FA6 +Test: DecryptMatch +Plaintext: 0E665CD2CF75C2E6E24908448F29E9A198EF +Ciphertext: 00A4583FF3A9451C6F8970E53D95EC74F41F709F5156B4FC9C698B1E43C7B5F3230D5417AED2C7447455009CE8381A30BE400EC15BBB1D7BCB9461E593D416421157541479FE1DCEAAE635728C68C58D260337A25D0CF9FA291D84E9E1DF4FF96822CA1F05CDD247AD14E5AFB231A0AF0F2E79FB9A0528CA2FE9431724C0AC9F0A2ABCED9A20EC1203DE2A835D90EA5FB1447EC722456B6F4C75D0645CEC5BECCE35B79FF3071A +Test: DecryptMatch +Plaintext: BE2A +Ciphertext: 02823CB4ABD598FC5D36300306460886BBECFAE6F56E02708A96EFB27EF7E3D8F08442FC819EAB1DC35CC70A074984A149F209EB285C6064DDDBC7781CEF7358F384D592BFC75D346A6D97D8524CB35060A35E3B3145199F4968677FA22BB468DBFF63E3E366D778B3042D5858699D9FE5D6F53D0CB084E107111B572AE9B933B94FF37F2681DC50CDED2714668375DA90787CF0144F1B +Test: DecryptMatch +Plaintext: 20D57B7E074BFFF8F54AF3E69C9B632253B3B5C0 +Ciphertext: 00D18C24BF39CD527455737B4B214BADDE99B070181C1E4729CC7B6EAC82298417FFAE7BDA1F41A7D74D6969BF9CAF3A7F9EC9397DB75F5E53D0282F793D601A28E8B3CA8730CD9D7A0ABA338E2DB3EB5314321EEBA2F16C8072DA6AD9A887AA5AED0EC5EF3DC7E5726626511F8F23B0BA4D83BA358DF0951B07399C7515349E3DE2938D2AA53AB11A4D1C07213E091CD3FB6453AF7DFB6799D45DA44B060F7BF5ACA5A25B3892BBB6 +Test: DecryptMatch +Plaintext: CC47935F7976 +Ciphertext: 02366250DE032B147BCEABCB576ED39F4993251D25010FAEEB41BDDA4301B890063247EEDC041539488E70B977091BF581033EE6EF75C224C8046EE3E7D2330383A30BA07FF33D10F07FF6E1EE20FA4D112CAB1BF457B50DC301DE5C6DBFACE227903379A41DC4D92517A547968D3F147D6435C3DF6A3D0D13635360716CBAC322EBD295593865C3A117050059FBEC83D112C5C3727377EBA7778A +Test: DecryptMatch +Plaintext: 3A370FAFD82869FEC40117 +Ciphertext: 026AE53843D3EFE36D8E52D9FD55DC6F0A0F51584BF81529914DAB6E380A6C9716828A7254307440B6A0CD16BF0D9D713939AE7F6C4D82D5AA70F33C9531E4071B9CB415C7622A23DBF4C81820BE04272874549F081B57D40B27BC1879BF134A2CF5D15203D326F9F97BCAC8606082A50A755CAE6FE2B72060EB1E0B72EF5AFAE8A823B3F0F91877C931CA64A06F3888DD4E2C823B3FCF529407255BE2AAD36A +Test: DecryptMatch +Comment: 1027-bit DLIES key +PrivateKey: \ + 308201380201003082011806072a8648ce3804013082010b028181072c45d24e\ + de76df2a03270413d8ab37645c8d6301ea76bb6cedea97142df7aa422b83043f\ + 8cfd8874dd684f47138433f5832c83c8c811d3c6d477b088006381ffb066402c\ + 951670f1927b1b67883451202f456bdb975d8bb2cde9b43c178ecfe788a0a0ab\ + df2cbfc700fbb97ef71e52221bc054fbd3cf8c04175e4841a45b89cf02818103\ + 9622e9276f3b6f9501938209ec559bb22e46b180f53b5db676f54b8a16fbd521\ + 15c1821fc67ec43a6eb427a389c219fac19641e46408e9e36a3bd8440031c0ff\ + d83320164a8b3878c93d8db3c41a289017a2b5edcbaec5d966f4da1e0bc767f3\ + c4505055ef965fe3807ddcbf7b8f29110de02a7de9e7c6020baf2420d22dc4e7\ + 0201020417021506533f6f0886a8a44137598adb93aeee548c9af303 +PublicKey: \ + 308201a43082011806072a8648ce3804013082010b028181072c45d24ede76df\ + 2a03270413d8ab37645c8d6301ea76bb6cedea97142df7aa422b83043f8cfd88\ + 74dd684f47138433f5832c83c8c811d3c6d477b088006381ffb066402c951670\ + f1927b1b67883451202f456bdb975d8bb2cde9b43c178ecfe788a0a0abdf2cbf\ + c700fbb97ef71e52221bc054fbd3cf8c04175e4841a45b89cf028181039622e9\ + 276f3b6f9501938209ec559bb22e46b180f53b5db676f54b8a16fbd52115c182\ + 1fc67ec43a6eb427a389c219fac19641e46408e9e36a3bd8440031c0ffd83320\ + 164a8b3878c93d8db3c41a289017a2b5edcbaec5d966f4da1e0bc767f3c45050\ + 55ef965fe3807ddcbf7b8f29110de02a7de9e7c6020baf2420d22dc4e7020102\ + 03818500028181056bf5dcced97da0ddd23c1f1294f97431e323f9719fc9bed6\ + 352d08a88ceb13a06b559b8ef7dc04c5a04a761a9631aa1000f32f885fb0de56\ + 505524ae89462079631f438284c8e5225c021d7731087ec0aad11aba9bba95de\ + 03f5c99ac228861a3ee6a7b47617cec687a58255321694b923e63ed247e65ff1\ + 4c279bec5282bc1b +Test: KeyPairValidAndConsistent +Plaintext: D391B4F3B53EB9B035C3AB1E3C6E +Ciphertext: 05D90F9892F6DD3DC3654130CAA312D2287D9E57607C301BE58607BB19FC78D67F2082C907FACA819A0D946AD16B46FE1E7264BE7D25D4EAB4F80D136E89EE7BC53B65CC1692581E3ABFA3C15482A6FEEB607AD1765897E67BCEDAED0E03FDE18E05330A99BEBB8710C77E7735CBB747EB507FE1EC04F239E964B509A4FEE8463478E28BF5338AE016DED9FE6B2DDBD3FDE467C45F0FA619E039FEF085D2F1544EA3CD +Test: DecryptMatch +Plaintext: 28 +Ciphertext: 066BBCB2D9E474A2C6CD514663BDA7AECA1F79136A00C1F9BDBAEDE344872093E67102307C96BF824999D86543121CC3D99B5CC4B511153A42E8A1569D063C27788E105858AF8EEB0766FAD9E0EDEFAEFFC733BE6824644CEE03AEE5FF15860CB3CBF4A46F95988D5E010FB844F944628043C830E575964EC36E2C38326C771085D796F2C22C0969E58665626415463A3CA1F56C357B +Test: DecryptMatch +Plaintext: D2C349F40A24230689EA15736C3AEFB1588A +Ciphertext: 019A66A4ADFED556BBD1E58728A3B7A3631458DCF677BB155DA989827C2240A586783D8C5DB98E266C39FCDF6FB016BBB25D53A6B30F3BC9D1109CB908B54F1932335F3DFC2C80847D94D13C5933953EA1D212107AB42189536171069621403681CAAB2A13EEAEC847193FA6A0234FA8F107E2C1747425584EBB4F4D702E29A3A09580E25B34413208009F9643327A636DF622B7F0267D3169A64646F301C584F64066801383ED +Test: DecryptMatch +Plaintext: 85D75863811C6F574222B577 +Ciphertext: 02C6FFDB38965F3061C736E633B497192862677CB247A37C5FA1FEB4F2C021EA94C65AD9506C73C2E98ADF0F340DAFAD2BF6F6CC906C93655594D093D4B0F6867755013C25ED0AD75DC9A04DD0666E6340BDD6C1E748479F3D64129F76B5BAB37D26319287EC9D65CE9E2243D4CCC7BCEA4065623C4D388A7BD779941EE541DD29E070F7356ED1A1ADAE947D79F8421FA717F933F08CBB8B699B551F1EFF75B8F5 +Test: DecryptMatch +Plaintext: DD07A91D32C26D3258AA4ABBD82E81 +Ciphertext: 05669E0777B003CC2EBE9BF3981160806A8B416A2DEAB4058497C5AF6A5C8F8D1ADF1225CC6FF7D292320E9C98CEDA144862FB4E32EE11AD9CC76A5C85FAE56A2567E6C9D168586F288CF4D525C94FF9F0ED6C3DBD08787768B90F8CD776520EFB920E61FB0E4463BE8D5AAE2683D31F392229A9554E0977BF25BCBBAAC7BB4FCCB009630D0203451A7A2AF847BA60AA0CE8C4D656DBED02353B92025925E1A0A6DF490F +Test: DecryptMatch +Plaintext: 0AA6B9FB846D1230F521F2624127 +Ciphertext: 01A9D56F1547728782D4F80BB0EBC8890BAEFE994900F41D56094F4734ABA2BB371060B2A69C6B7BC8944358519D141FC277E1195B3A78F7068731C3AF3C604A062A0D551397CD804168B7F400F786BC5CC3F912457AEAD56873AEF1A2378F34E953E240C20FFD7DDA229D4C020BDC68684A53C0AB3ACF9B44581353C60CE9854E3451645A604BB7AB3EB44088A07F59CE0FEB6454CC5A83BE5E939B317D4D8537CAFA +Test: DecryptMatch +Comment: 1028-bit DLIES key +PrivateKey: \ + 308201380201003082011806072a8648ce3804013082010b0281810cb31a78b6\ + 6dafe2dd020483aec0cad421e4a3df2a81b827009dd74f5ef0468fc508477190\ + f628033471ee2d56f913d45a94a8ad1582b29785a7ead06c88ce73812e653797\ + 921d3c4a8fba91c1423d6609e85625b2f41494546500237151958b13d1cc0f90\ + 586b0233290d052a18c2aa3ec2bdc32adb4676cbeb30309e330b823702818106\ + 598d3c5b36d7f16e810241d760656a10f251ef9540dc13804eeba7af782347e2\ + 8423b8c87b14019a38f716ab7c89ea2d4a54568ac1594bc2d3f56836446739c0\ + 97329bcbc90e9e2547dd48e0a11eb304f42b12d97a0a4a2a328011b8a8cac589\ + e8e607c82c358119948682950c61551f615ee1956da33b65f598184f1985c11b\ + 020102041702151c0cefd22a713385985cacb5fe84cd40e724ce9587 +PublicKey: \ + 308201a43082011806072a8648ce3804013082010b0281810cb31a78b66dafe2\ + dd020483aec0cad421e4a3df2a81b827009dd74f5ef0468fc508477190f62803\ + 3471ee2d56f913d45a94a8ad1582b29785a7ead06c88ce73812e653797921d3c\ + 4a8fba91c1423d6609e85625b2f41494546500237151958b13d1cc0f90586b02\ + 33290d052a18c2aa3ec2bdc32adb4676cbeb30309e330b823702818106598d3c\ + 5b36d7f16e810241d760656a10f251ef9540dc13804eeba7af782347e28423b8\ + c87b14019a38f716ab7c89ea2d4a54568ac1594bc2d3f56836446739c097329b\ + cbc90e9e2547dd48e0a11eb304f42b12d97a0a4a2a328011b8a8cac589e8e607\ + c82c358119948682950c61551f615ee1956da33b65f598184f1985c11b020102\ + 038185000281810aacd80676c540b97f74d2a94c2f389795c9f696d2a1fa934d\ + 20e93d49d0099d9312552e6e310da5d97cef87c9a5a4c47e7acd195293b09adf\ + db8e0cac95139446aba60fd625d17eaa102c7c26568b34891edb38226f949656\ + 44a9d52ff299cd007ab3dbc15779d4388431a66774ffaae5c6be04526b28c620\ + ac97e8618cb09d46 +Test: KeyPairValidAndConsistent +Plaintext: +Ciphertext: 0194C64DEB9CB401573730A29359456F4E9528347ED80F24E5AEC4441E896E38047EF95AAD9AD7A25AED6CC89FD95CAAEF27F3C814C26FE43F6D65288D87E372A204D1A66C3BCF0346CE89E9D2D7646E90BACB9A85022ACFEF8903C72A663BAED9A346E1A6B2B2FCF70E239EE70A34385F8C76CDD121F6B190085BAB3300E6B811906CE38AC740FE88A3DF8DCA1C6DF73A03236D51 +Test: DecryptMatch +Plaintext: 9498EB7300 +Ciphertext: 0A38C373F6A96D87528D2D55F6391A9E801252A65F622F36A130ABD140E1858024E31F247C3BC8C07D9500CBE7A8A3D6C0670AF0FA14D020DC54B201E657C233F8031DF990AE801077D4D3AD9B861F4C32D36FFB9E8BD5E2651169BC4560CC7FD02159929AA50882F8B4C8508BB98F6BE8A6A7C0E21A2A81AF781447ABEC85C170F3F6256C3B6C5E2D3A01BB5EA8B502D37561C06F1DA536BD59 +Test: DecryptMatch +Plaintext: F07FFAC9794BD8D528F750D50C05 +Ciphertext: 03DAF7F6C2BEBF8D0B380EB71BD8BEE9D649AD7647DF6DE4CBCE00D0363E31F11E0DC0331409863E3C069EE3F975E7F623B55D7F4690C7419C5AD97EB52BBC0212D3FF0A83A031591A31481116B2CD232A9C86A20EA40BD13A53BB73E644A6C7DC1E6C767756E7235538E9D5B155B3173416E99F121E96E02034C6DB9129489A050740F603DEFF96EF1D99E7EB4A32083D0D946670B1AEF30E1E38D3F076D6BCB57255 +Test: DecryptMatch +Plaintext: 85916A46E0965C69C4773C7DF9AF +Ciphertext: 053D29F0878C68FF55FFC8E6E0E03044AE23B79588034F0236A49A5B6D00EFE8C564D2D29ACB61FE49C0E984EFC3A48A96EAF22AF3032D8D0FD3B3BB16A0157C161F2B3D3DF802FDD6B61899212F44493383DDDEA8B2463BACD0C5E1F4F9E4063DE5E52032E7DA8B79E04C5F03144CD710ADA74506CEC2D448BEA0F2B59AB63FCC443BBE920748E122DDD6123BDDAE484DBD02088817D999FDF80D5ED4B308AF4C2DCC +Test: DecryptMatch +Plaintext: EB632C72F563174E680961BCF26EC7 +Ciphertext: 0BBE666C02191F668A2DB000646A14385A8E9199BD887913BA587DA4C683535801853186673AD7C43EFA5B65902559BA5345EFA111E0514D461C1B1EFFAE58708EE6C17F1758EBED31F0B3206B0EC1B4BEB2EF911C589E25CDC3B0020C47119B5F33EA2FB7C332CA6B1FDA2F350A4CB0D6844637F2CCA71EFB036C7400957AE093B21BE90E30A8672847C9BA5266EBBF9D62341F67A4D09FFA196A817DD2F5EE1A9654EC +Test: DecryptMatch +Plaintext: 42B5D2DB89374231 +Ciphertext: 0085B6894D887B59393F9D7365411DF239BE1104FD86CC63A52C990A84FC4660FF9B60CF0641E44A8224C169A9FD1B35EAF78008E34F14B5311CB5D725096D9DE92F35BE6E71E3AC3E3B3D68BDD5351A5AF93F0B3BCDB00B9B126D8DA07E5F42107181F9580CCD0D6F086C94177FD48ECFAE3FCF2F26D64940D749E8A964275290A247AF700210500517BEB2175326F4CD3016AB175B352F9BD3289079 +Test: DecryptMatch +Comment: 1029-bit DLIES key +PrivateKey: \ + 308201380201003082011806072a8648ce3804013082010b0281811b02fc18f7\ + ba0ae7f84ebcaf319294fa2bad52e47e1926267ad38b2f1b2566145bbc190cb5\ + c39a8d6229eb238d3742bbd234b0f28eac92363a31ac96c5b08eaeb1963de59a\ + 3b2d0295c0266a7da4ca92b64f96c497f262e98df7f20ec55814b8441acfb639\ + 7abf9c4e42ab9bd6dda6ae180b12e12ead68672f9d56b98ee40e2b630281810d\ + 817e0c7bdd0573fc275e5798c94a7d15d6a9723f0c93133d69c5978d92b30a2d\ + de0c865ae1cd46b114f591c69ba15de91a58794756491b1d18d64b62d8475758\ + cb1ef2cd1d96814ae013353ed265495b27cb624bf93174c6fbf90762ac0a5c22\ + 0d67db1cbd5fce272155cdeb6ed3570c0589709756b43397ceab5cc7720715b1\ + 020103041702152c7c60166a1bfebb17831e65b8e1f61f3ef9ed9ff7 +PublicKey: \ + 308201a43082011806072a8648ce3804013082010b0281811b02fc18f7ba0ae7\ + f84ebcaf319294fa2bad52e47e1926267ad38b2f1b2566145bbc190cb5c39a8d\ + 6229eb238d3742bbd234b0f28eac92363a31ac96c5b08eaeb1963de59a3b2d02\ + 95c0266a7da4ca92b64f96c497f262e98df7f20ec55814b8441acfb6397abf9c\ + 4e42ab9bd6dda6ae180b12e12ead68672f9d56b98ee40e2b630281810d817e0c\ + 7bdd0573fc275e5798c94a7d15d6a9723f0c93133d69c5978d92b30a2dde0c86\ + 5ae1cd46b114f591c69ba15de91a58794756491b1d18d64b62d8475758cb1ef2\ + cd1d96814ae013353ed265495b27cb624bf93174c6fbf90762ac0a5c220d67db\ + 1cbd5fce272155cdeb6ed3570c0589709756b43397ceab5cc7720715b1020103\ + 038185000281810e6e9c7b74e33a1f4683ddfa35509c39a75b75c10f438efad0\ + 82caad08a7418990983150a9a5ffe3f8e340443dfbabf82fe060da487f94afdd\ + 1e713d491b983fc4fb69d4405a12e356808c5cf6a7bd397c1a5637ba8e168b7e\ + d3f549a9f39f343e8fe3992706e782a1dde5c5e9e6a950f7d980835c1bc1742d\ + c2840cb2e61086d7 +Test: KeyPairValidAndConsistent +Plaintext: 03C57B87 +Ciphertext: 1440C6776914314A1DA161EAA41D52B283E2C0B487C801CEC33DCDB639F579F69D12FD029C994A311913EB6869C7A5659EE8BD9F5D7225BBB2EB77CF6F3D24A5E9866BD2CC50E593EC5CEBA4A96C59FE8B98B5EE2121E5892F2436F98B5C4E4A12077A1A64F1FCEB783D05453A657BB91909637063813CC00754402DE24F4AD6C0D9D4C15B7F4E485AF3538D391CF5993A59F6D1FE6C76E2A7 +Test: DecryptMatch +Plaintext: C5598C0FE0D90B10E7125079E2EDA32E531C2EBF +Ciphertext: 129FC863B70BB82C1C59EE2DA37FF3909F1DAB4B55D9727EE0CA3311BE5797F93446ACA0409CBFA848A90756D2598B6ECA56F6341C6E9F716A62380CB5D47400CF392A5441DA5AD2C1D066F894942837EA7B6237D7BE2E94FFE0A106148C2B7B9AF624242A945BF3B217D89FDBB070FA5940C1C899AD83AF1F865DEADFF0F4E48A7E00BF7AC5625F6E32F8B01394AE90284AFA061AF6DD61ECA1B8FA77CBC172573A9938332D7AEE41 +Test: DecryptMatch +Plaintext: +Ciphertext: 068117F2BCF29C72CDA3F4560A2165B7DB7C29314EFEC8D110425D5AA02F35C0F9A2304A0554C097944EF3A615BD70F5461E6549C319AC1207B100FEF022410C46284CEA9CA103685A18EC944DEA0BAE8E06D2489A3E2D1D9B255F192677664CA6FF44130C28CDE1FD437E85396503DFF305BA2D64E8BF9C75B00CA1595A1AED2C60865C0DF03F408EF95517E70552B2D5A8C190DC +Test: DecryptMatch +Plaintext: 8DDB5FC737283E5B +Ciphertext: 0B3E0CE51E1D3AE240EB34787DB5D49D6786B3BCC29C37EF8B9155F342C4D226CE1D07F7BAE09DFF7E8CD89915E1312F43540A26F03D918BF56B07E6D07A96870362643092F24FBCC6A2DE62F637B5F5F807E430DAF9B7AFE1890143591BBA035538FB419BE4CBADFCED5EB8BE2471B39CFCFBB2BA854C9E0F52E67524ECB80F9FBB3173D2A18C9F4C43F4E20866428A9256AB8AD199BA0BAD55A18896 +Test: DecryptMatch +Plaintext: +Ciphertext: 197D4DC43B0716191F926DC806A1B707ABD6684735144AFE07E0EAEEDD9BB3C89B9D0076859DACE6FFF9E2685592ECB010909910DCA50D2FB1B15EB9B9CFF4F71250D807EDDC2EFB2033BDFD93FD10E117683E3E4E8A5D3308572D4852954BD51251279A79092E3DCB95F1FCEC8310931933F47998DDB61438478CD80864F08D3370C863BE6E7E1CD22E38BC512D9A160478814057 +Test: DecryptMatch +Plaintext: 53AC983CEE599A17261C53 +Ciphertext: 0E31EAACA9E8A86ACEFD1CB817869F48EAB342EAD0DAFE17B848CA9CB72B92567987B929F655B8D601EB1384BE380C8E4BA8B4E274F724F02FC5C00479C308813A3963E2D8AC88ACE92AEB00AB024A4EC5560857310E03009752B86793B356DA344B4AEF01F3ACCD9CBFBE399D0016260C006FCA5443359EA1E012D43921B8D2B8CFD31B94972ECE9C0031420238C76514635E9B40F17D9AF25A1009DB75E4C0 +Test: DecryptMatch +Comment: 1030-bit DLIES key +PrivateKey: \ + 308201380201003082011806072a8648ce3804013082010b02818127b35992d0\ + 8edcc7aaa6ca70365afa8ffacb4a9bef0ea348e27414c2100b81827fbf1abd3f\ + 14150bb5d85ab13b2aca21304365f150511a68c90f4a4eac0bfef0c548e3076b\ + 30a24929c4482f42f2b03ce122b3a251e685a3fe3dbb539932bf8d2b117b1b08\ + dbceb78c84966270657164fe6f20c6d27dca270dd4417f843fdfb23302818113\ + d9acc968476e63d55365381b2d7d47fd65a54df78751a4713a0a610805c0c13f\ + df8d5e9f8a0a85daec2d589d9565109821b2f8a8288d346487a5275605ff7862\ + a47183b598512494e22417a179581e709159d128f342d1ff1edda9cc995fc695\ + 88bd8d846de75bc6424b313832b8b27f379063693ee51386ea20bfc21fefd919\ + 0201030417021513560b35fe90d01a106b1e6ccba4cec953421d48cb +PublicKey: \ + 308201a43082011806072a8648ce3804013082010b02818127b35992d08edcc7\ + aaa6ca70365afa8ffacb4a9bef0ea348e27414c2100b81827fbf1abd3f14150b\ + b5d85ab13b2aca21304365f150511a68c90f4a4eac0bfef0c548e3076b30a249\ + 29c4482f42f2b03ce122b3a251e685a3fe3dbb539932bf8d2b117b1b08dbceb7\ + 8c84966270657164fe6f20c6d27dca270dd4417f843fdfb23302818113d9acc9\ + 68476e63d55365381b2d7d47fd65a54df78751a4713a0a610805c0c13fdf8d5e\ + 9f8a0a85daec2d589d9565109821b2f8a8288d346487a5275605ff7862a47183\ + b598512494e22417a179581e709159d128f342d1ff1edda9cc995fc69588bd8d\ + 846de75bc6424b313832b8b27f379063693ee51386ea20bfc21fefd919020103\ + 0381850002818117f468e3d38f1198556447bc16fb6c6ffe98b31f9042e59602\ + c71286db3e0780601e47372e6eb4a570f2059a7a87ee4471eaf94bcf23e34017\ + 5a377333d39dc64b7eaefcc065bef4a92d0d10acbba71082852c2014d9d3eb2f\ + 8583947c2cbf52865730d2b9511ed8a68367e4d89eca4589b836889cd424485c\ + 9305bc0386b16619 +Test: KeyPairValidAndConsistent +Plaintext: 4424 +Ciphertext: 0C570D0317363DB43DEB295D49A3BC937116F2ECAC9226415952CE634679272B7041A4B806164F12E87A0050AC2D60D393F845965CB3A56FF0CF28D31CFA0285015452C59949E3D96C5C6D1DBE38F6EE98E2C93357E6C036053DF920C7CA5E2EA1617AE44434A347FCE426C55295172ADDE9CAC3AEF2C6D6AB2C8F0FAB1B146FF1A10D5EC2191C99D6418519443EEE2A198BFD159BCC63 +Test: DecryptMatch +Plaintext: 5092C5D9FA398EE31AE27C97 +Ciphertext: 196476CA0E6622569F233780EE0C449C2CAAD3819B348D01B4DE5425EBCDEAEA739C6D9CCACE4DDF06520E83C94D237AFD46A4EFED635112CC78534E2FA6046ED6C06806EA8F4B9F3FC3F87DC55F63B9E14F9ABD82E9CC80A298DB281C9F690391F5B064880CF35C5A0BC7537DE9F65DEB2467FAB5CE8F41529A5B06BFA6B587ED661849BC7388277AE7F7E5EFA3F2526E503ECB106B718275BF32C4F83278CA30 +Test: DecryptMatch +Plaintext: 89BB350DC43CB3 +Ciphertext: 13844D63B45821E8704A9C1F6E9166B5EB7FD98DE5369E5DBB9DECE506EE467294282B5B174EF2F81B6766A3616AC5A974F06D9C47163C69668F4C1C78F8A6716A4EC28A6AE25F615A838B9C747EE857AA2AC92DEDC575AC568A78E8A86EF78D55EDB88707F7B6D558E8A760095BE8BCD066FC57396E67C9D8654245676DAE9FC4BC9D578496CA450B35E179410A5DB443C2026FFF0E5F7E54821E39 +Test: DecryptMatch +Plaintext: +Ciphertext: 040E084ED4A1C135C8867BAFF219A0092855E1E9FC96F38277E16B96986FDEABDC22F3B02CC53B655369DDE3356EA6FE49B77C8EAA49815CD5B1DFDC6E7D0AF6AA985483345BBA8A251F1EC7658DF708C8EED8AB6B953393C03BA2EEDB8B6391D921C9EAD2AA61DBE724B15C9C664EC4EFF83A535E46BF768FD519B043DBF46A36FA03921224281A826F6F43DEA6DF38749D600317 +Test: DecryptMatch +Plaintext: BB296D4FF04AE0171F1F24AE +Ciphertext: 0AA9A85958D9F1BB06E3DB48DACC842534915A7E42715057BD33523EE756F62AD973E37128BB8031358A1DC583F40598B74F079AD667C037D4BE89938233BFE1C167EFE764724F97F2EA42479FB455B1166AAB26A43440867ACE77472CCB13643D5BC9532F68C5368825BF225DF49E2D3BD023447A795AFFE927A796C70E5D6359537A9CE2B4B9323D7FE208540CC32447940ACD91F4718FC7A7CAD45A524B6DA6 +Test: DecryptMatch +Plaintext: 87A2C6B33856C6A096EE +Ciphertext: 12D17080AD0E7FD426E02B6A90736AB4B566F31E937B2D3E642D663D6ABFEB903FC9C4763AE492191E0C15B264CEF321DC8747C590F751A9BA2825D9250F72BA85EEB45B1F1D7B2BA972455DCE7DAE6CBD7B5BFBFB88FCEF52910F9B28D3DCD6BB5D479BBFC73896C3D1C44AB387989DE4D77855F6B8C7A8C12969D51DC6B10BA15C2B19E91A55BD5542853EC6F8F13260E8774C706958B1C9866114FADA1D +Test: DecryptMatch +Comment: 1031-bit DLIES key +PrivateKey: \ + 308201380201003082011806072a8648ce3804013082010b0281814ff13b3664\ + f5c527c36120159d9b9a82054f9ade6866b379e13d03e76cb63b25731132d5f7\ + ec6e95186ed83c793b5d63189dac30c6e6a655605f885fe73d2ae5433c80e660\ + c5d985ad6d12783082861829355c25cd7a7ff84b3033cb7fb530a7baa4000830\ + 2c1eb24b866cf467f570e782bceee66e15585f70b0633965c870530302818127\ + f89d9b327ae293e1b0900acecdcd4102a7cd6f343359bcf09e81f3b65b1d92b9\ + 88996afbf6374a8c376c1e3c9daeb18c4ed6186373532ab02fc42ff39e9572a1\ + 9e40733062ecc2d6b6893c1841430c149aae12e6bd3ffc259819e5bfda9853dd\ + 52000418160f5925c3367a33fab873c15e7773370aac2fb858319cb2e4382981\ + 020103041702150910a291c216ca5f944c5f3eaaa1535c3b8a1f0b15 +PublicKey: \ + 308201a43082011806072a8648ce3804013082010b0281814ff13b3664f5c527\ + c36120159d9b9a82054f9ade6866b379e13d03e76cb63b25731132d5f7ec6e95\ + 186ed83c793b5d63189dac30c6e6a655605f885fe73d2ae5433c80e660c5d985\ + ad6d12783082861829355c25cd7a7ff84b3033cb7fb530a7baa40008302c1eb2\ + 4b866cf467f570e782bceee66e15585f70b0633965c870530302818127f89d9b\ + 327ae293e1b0900acecdcd4102a7cd6f343359bcf09e81f3b65b1d92b988996a\ + fbf6374a8c376c1e3c9daeb18c4ed6186373532ab02fc42ff39e9572a19e4073\ + 3062ecc2d6b6893c1841430c149aae12e6bd3ffc259819e5bfda9853dd520004\ + 18160f5925c3367a33fab873c15e7773370aac2fb858319cb2e4382981020103\ + 038185000281812e9a62ec280cf5ee7d09e5e5675b67a4c325c7565a1129c079\ + 095d0f078e7b8a5b3c947c21c022f01c0b9267a45fdd9f267e63c7f674a02d39\ + 6fc59a960d7991d2e3552d01deb2784f26ec4c9355c0df0497271cb583d157db\ + 90b0634180578ac85005143dda75a33a127df96639e275cee8fe9c02db62d2ed\ + 879f3caae11d6e00 +Test: KeyPairValidAndConsistent +Plaintext: 1FBE21CDBCEBA28625584CB1EA0D9627A919A6CA +Ciphertext: 2CFC251CB2A397880EFD0077D9CEF817A6D69EB6278CD82998C5988DD18D6ED15FC8CAFD1611DE58BB46BA8A87013C7BBD4A8DCFC454F13DB282BBBD4E1594E6AF17AB6219E91D7354EB88515007B58BF0D8FF4BD4C387FF6E02BF81455803E6A936F25245863F1580F00ADFA4BDE052BEC72739B88042CF99480AB6F4489F9C8B9319828A000FDDC4D1A6E49868E3B39DBF7DCDADD9B882B755E330C762FCC023EBBCBD0330D28DB6 +Test: DecryptMatch +Plaintext: DCF33FA5BEDFDD93DA +Ciphertext: 14BA927F10262B134AC43F6787EAEC3546C17EFE3F6D54AD2A245A0EE732B749B7312521372F21716E1DE29AF8FB329C25ADEDE2DADE3A455235DAC6C1F347C2A052893DBA6511C3760384935D68C7808D23CB194E6A19F579782B22C3D8880736BECE89FD75E7E69022E9B2500E5A044105B832C9BFC5F18A807889B401E61A9888276B31FD299D604AEA85091578D41E5B36D66C4510F4B147C5E59615 +Test: DecryptMatch +Plaintext: 217B0E +Ciphertext: 37B50EFF3A3FDA419988CA44CCA3AE95F465A18C89CE2DF025F565DAF0F833E198DAEEB46517FBDE47AA3D5DC5039B873A31D0DEE1EBC63F3E97C0A63CC05A8F877FE70EB7F6198C088FF35C1C369616D3EACB013F295F764146A5AAA2D21CD36B9DA4490CF1B37D379ED7713B955C3B0581650B5C7F4F5B8F45B89B94DC364D3340414B491C29AAF2E197AD6F59B0DD687F2E60F8826169 +Test: DecryptMatch +Plaintext: 36DA002D110CD632A9969DC42409B478A3AD3B +Ciphertext: 37126F749ACDF2B6BF667DE9635CC0BBD61753B30931C847B612936C1AE122D6F0E409B4E9454852540C5FD8DD3DA8BA4026FBE8CC8449CA0071409DB47165907202DC078E5A8F6B0E9C8D3497A2D02F53DC3A47389C1B3778EDDEE980055BC4B7EBAC0B95C0CC4783A4B202CE127FA0D7B65B252492A1847FAA9D1ABE893376917BCD46DB4FFADC06C880AD848683B874F7CDFBF0E4BD87AFC39303C512C44EF58B510702C1129C +Test: DecryptMatch +Plaintext: FAFD +Ciphertext: 0F63F22B7817F2449388E0422C6122200D76BA8D4CEDE63DE950ED26768E6779BA0A238C8C3F2CC5C87C7926F1247A7067E27245423EEEFABCDB606976BA2FD9977320F903733FB57D02620682820B1AEE165604410157C5ECFAB7090EE83638A99E4CA36CA0879D3C14856A3417690A52F14F33CC50FE44503FC47F2D90C096C03F62A85D88891E9568911AF61DF916C3677DCF152FD3 +Test: DecryptMatch +Plaintext: 9E9145E890FEEADC706AE1 +Ciphertext: 0B60A14F132D21E47E2FA20633DE43694EC0394115DB297C1B68D1A7EE7722B6AF5D149A2EF5D0EA05761C0FABCF8C0862AF320E9D273AE743717F78A46F15B640C87F4AD0C25865EA3453B0FB59D997E41A31B6C1669F14639E2F70F7D4324B8729A26C8869D97B432740F7CE28A74EFFC82AD7EF172A02AC678C13235BA2C6EF79143D189838E1F101385BD7098AE3B5B78A80964D5C0A3D7DBA7FD7328BE8 +Test: DecryptMatch +Comment: 1032-bit DLIES key +PrivateKey: \ + 308201390201003082011906072a8648ce3804013082010c02818200b98458f5\ + ada1f23f4ae8a3a519c27fde91efd1f201e386aa6119749aaf6ed389079ae49c\ + c76317f81f14164673e8f0be00edd4db4792d446e7bf84b30200626b442af3f7\ + c9a6ee6fb0f95807e62fa5b2d171a4b326cd60c82b20d63ef00b408ea337f50f\ + a51f07549dc4f9a660842724566b94d6e2a58980d2d20281ce6c327643028181\ + 5cc22c7ad6d0f91fa57451d28ce13fef48f7e8f900f1c355308cba4d57b769c4\ + 83cd724e63b18bfc0f8a0b2339f4785f0076ea6da3c96a2373dfc25981003135\ + a21579fbe4d37737d87cac03f317d2d968b8d2599366b06415906b1f7805a047\ + 519bfa87d28f83aa4ee27cd3304213922b35ca6b7152c4c069690140e736193b\ + 210201030417021534999c0e7b17cc3c110cff71571e8d4708c3122a1a +PublicKey: \ + 308201a53082011906072a8648ce3804013082010c02818200b98458f5ada1f2\ + 3f4ae8a3a519c27fde91efd1f201e386aa6119749aaf6ed389079ae49cc76317\ + f81f14164673e8f0be00edd4db4792d446e7bf84b30200626b442af3f7c9a6ee\ + 6fb0f95807e62fa5b2d171a4b326cd60c82b20d63ef00b408ea337f50fa51f07\ + 549dc4f9a660842724566b94d6e2a58980d2d20281ce6c3276430281815cc22c\ + 7ad6d0f91fa57451d28ce13fef48f7e8f900f1c355308cba4d57b769c483cd72\ + 4e63b18bfc0f8a0b2339f4785f0076ea6da3c96a2373dfc25981003135a21579\ + fbe4d37737d87cac03f317d2d968b8d2599366b06415906b1f7805a047519bfa\ + 87d28f83aa4ee27cd3304213922b35ca6b7152c4c069690140e736193b210201\ + 03038185000281813c42dc88e1e15b9a737bfd64b96a7448983da5242a6cf43e\ + 1cc72e8886db723b681c291f772bfe33de5ba735404581c839341969a691c199\ + 229c2849c1c8c80396837c71d711ce34129d3006aef9d16cac504543c6e570bc\ + 3d730d5cd35d8a375edacf591b2837f9a705d63dd62754365d13c103961161dd\ + 984d89792985ad688f +Test: KeyPairValidAndConsistent +Plaintext: 23 +Ciphertext: 0BE692E3384A784AD01D80A65D22B48449AFC0281B36085B0D8FA03574B4BAD05F754D6FFB8E3F4B4BFE60FC7EA2BC1F11253505C753BEFB1D3BDA0084E6CC1FD82454A601F1C0ADB52B3FFC4895D36542FE0139465B490102C7B6A75C9273B737536DD122CC8C3EA0F32900C82C45B0FEE97D995AC5B4345A8899DD6888D1E814BB5A1141A86E636D31FA05689ABA512DE869D12BB4 +Test: DecryptMatch +Plaintext: 4F571384FD52A9041C8F3094 +Ciphertext: AB7942750662F0FA422F4628B558938545FBF7C749995B4D5B32BBF392292FD1B4EF02E5A2EEF6874BCA9F0D4CBCB92D684CDA821829850BD4CAE110E78E42909CF069B54B4BC7D742E113E57C85BCF54AA5CAE1005516BADA834A857315DD6C3DEF4AEBBBF6CB4AE217107E16E83F884B2933EE618F22C45B78092B2EFF7D5C33DB7D89FED4E134921DFD9DA999FB8AFBFD094D77BD887D2C86AACC401A621905 +Test: DecryptMatch +Plaintext: E421A467654B3B88C93C8E5384FE2B85D4E340 +Ciphertext: 7485B8E5360BC1383FCE1C586E126D5DE89FF1CA7CC8146C37A1E6582A564C4588984915CCE9635EA6ED434C80CAE138FBC1EB15D16B294AC1E59CDE544E4DFBF276D30A7F51461C2B7E7F076222DE6AC534DC47E015BA85062694FD78DC37E9460C10FDAF2C61FC7EE0669E99793A657543B881B50B0D3916E395A959EF55B02DB8E7B4C5B5B653AE2D11CCE639342C8C77C667625116D9E6B6C6AE822CDDF2AA503EC3FAD53D80 +Test: DecryptMatch +Plaintext: 3D6C941B1F03E5C9A4 +Ciphertext: 684AA8D2AD35D2775BC30794A078CFC931096A37D472FE511F72B03B33E87AB1E7B958C3447AF6285AC379379E0D1F1BEC535E4032E186573742A75C1B42BDC52F679DCA13B2B9E67CC73461084DE1777FAAED93C7C1E4A6B19473EDF6A57CD88C076574A356748D501A05AF66A136E908993A0A70538FEB03109C62A41540EB4E166596887B4860E3AB0BF9C1AFD02C67D4BFF28BAECD31D1CEB207A245 +Test: DecryptMatch +Plaintext: +Ciphertext: 111C252A9E64FB777F09AF6AEF9C4210B9644C3A66D5528C631D5348E30B146A6225783DE1FB796DBAB3A901E37818B5AE49BF1F8CC0A6C8909D2DB06D651CB08009A25E13A89653DBBA5959674E37BD72039D4E7BFFB3A2395DF8C36164C3FA71334DBFF2FACA090F1C349BF68443838A0D893B9B498D3B6CC86646F935D5ADED81967A387506688B6478492129534F3A651C9985 +Test: DecryptMatch +Plaintext: DE5F0B92C45A0C1530 +Ciphertext: AE6BAEF52B43EE88AEA7796D667D044887407ED07E7618358243A0108514FE9793EB28EB42B4BA2F28F6687FE7973FB8DBF825541010F1BC1FC7350CBEC0B055C0C71FF2C4D2634582C966C1CFD3449AF8AC956BEC3EE797F7E81E589450EA13C1A8C99116E05E49F4BB87C9B95EFDBEB35B21C36711CEC8A1ECF3E4F194251563F88C056749B835FC19A7CD560FEC785207DD14D43C6104D83BB05F1DA1 +Test: DecryptMatch +Comment: 1536-bit DLIES key +PrivateKey: \ + 308201bb0201003082019706072a8648ce3804013082018a0281c100f9566c8d\ + 687a5ead7c780617d3ed37b4afc46582e9fc0d75ae217fb506f5c2024c2a0e6d\ + 7e042544235b4de63047a33940d772721e895f9d4e92790bef0d3668ec7f6cad\ + e7f9b18049b33efa773c83e97b35ef7ebf18934b48dd4700a48c1f76ffc20684\ + 521bad52834086ccdf1e3d5c9128fef52f6a9444d8e9944d49e5ab411f46b63b\ + 290b7fdc8f48fab24c2059510bb7247e0930d5043802522d67f2b69ac18b82bd\ + 0229e53bf6769fe83c469188d600e6afa6686bd9725afb9ce39bbd9f0281c07c\ + ab3646b43d2f56be3c030be9f69bda57e232c174fe06bad710bfda837ae10126\ + 150736bf0212a211ada6f31823d19ca06bb9390f44afcea7493c85f7869b3476\ + 3fb656f3fcd8c024d99f7d3b9e41f4bd9af7bf5f8c49a5a46ea38052460fbb7f\ + e10342290dd6a941a043666f8f1eae48947f7a97b54a226c74ca26a4f2d5a08f\ + a35b1d9485bfee47a47d5926102ca885db923f04986a821c012916b3f95b4d60\ + c5c15e8114f29dfb3b4ff41e2348c46b007357d33435ecb92d7dce71cddecf02\ + 0102041b02191d78b208d09b23e859be7e79ca76e612d8e5ac75a5ca02c506 +PublicKey: \ + 308202623082019706072a8648ce3804013082018a0281c100f9566c8d687a5e\ + ad7c780617d3ed37b4afc46582e9fc0d75ae217fb506f5c2024c2a0e6d7e0425\ + 44235b4de63047a33940d772721e895f9d4e92790bef0d3668ec7f6cade7f9b1\ + 8049b33efa773c83e97b35ef7ebf18934b48dd4700a48c1f76ffc20684521bad\ + 52834086ccdf1e3d5c9128fef52f6a9444d8e9944d49e5ab411f46b63b290b7f\ + dc8f48fab24c2059510bb7247e0930d5043802522d67f2b69ac18b82bd0229e5\ + 3bf6769fe83c469188d600e6afa6686bd9725afb9ce39bbd9f0281c07cab3646\ + b43d2f56be3c030be9f69bda57e232c174fe06bad710bfda837ae10126150736\ + bf0212a211ada6f31823d19ca06bb9390f44afcea7493c85f7869b34763fb656\ + f3fcd8c024d99f7d3b9e41f4bd9af7bf5f8c49a5a46ea38052460fbb7fe10342\ + 290dd6a941a043666f8f1eae48947f7a97b54a226c74ca26a4f2d5a08fa35b1d\ + 9485bfee47a47d5926102ca885db923f04986a821c012916b3f95b4d60c5c15e\ + 8114f29dfb3b4ff41e2348c46b007357d33435ecb92d7dce71cddecf02010203\ + 81c4000281c07a5b4ddf442b2cd7fd925be84f2ef4c4032d61c5a55c5949b30a\ + 765cd4d5d4566af37ffa7f814f51bdd71c3e5575c6fd0203f14d3ded4e14baa8\ + 2747a6437d35ebc81e2035bfb0e04087fb5fe449163377d47b045b680b394962\ + 20b3138e85f6d24e06f955ec7a1b785ce34c2926cda441bfc86ba2f44a489a41\ + ee1740ab5ec3daf6d2c598e1d143654c05ce61792b47ac92c8d6ba0711419e41\ + 221743b768eeec2601f66d277fba154a62dc996537a0caccfa313cc9fde0194c\ + 05493aab1f07 +Test: KeyPairValidAndConsistent +Plaintext: 9302C420D137C310 +Ciphertext: EEF64A81C754B2EF543A19549AC0FF3F44E4B548284ABAA1E5F1EB704B0D246749D7F1CEF7B20A5226384DBE8FB596101591BE2B53E9909EE3723CB70A385FC2DAF6CE15629EBA21E7F26223B0A2428D8931CBB4F1B281E318A540F38A809C8BAD92D10FDD63305DBBE972E6CB973FC4F2FDF0BB9CC37FC42C7AD76E8DE3FA91E5E79B09796652BFCD62A28A59D9A97759032A0A78E0E1B081DF212A15AA44E35DE9E291EDA499DDB631486C029D56052246C9E37FF24EE9E86465B3B55BC4BAD77B9AC873B6F36EA65892B202E320756540009C81B9C6747BDAF40E +Test: DecryptMatch +Plaintext: 9FD4F26B7317BBD1B235 +Ciphertext: 514DB5C63AD9707197B4F0B2A30CDA18369B963E62F7ABBA1E030E08D3DE4E6C17D4BD7CB8097C2E641FBB0AED6A9FE7FBEAAC1C6B85BB3570D0E86FF6105B9F8C9B562A4EFE4AE3AECA26978C514129006D22C108B1C8A0FA55864EED3D3F81643AAFE36DF1CBC3B4E1B1AD6D5E0612214938A55114589B97286A7EE5B04E39254696DA91453027F07346984423FE2784DEA9375C236E6640504B5BCAC32062836E5BE1695CE73285CD77CE9717FA38E080C28C2959D9E32A589C04ACE5E52970ED49BE34703AD6B9F024DDA176C631EF5EE76833B427E233A5DAEC4328 +Test: DecryptMatch +Plaintext: 337D8BDD32 +Ciphertext: A4EFBF2151DAC683F0C51D60A647151A1EA0C0DAA8CF3497D7116439E6AEEC62A36D06F89AB2F1886FB9F62403E3DA8D6F67F66DA2436EE20FFBADD698DF87EF40470749C0BE0414A7AE4D2755459F8A17F6C7D8920236400313D7846532C391A0A4D99C26C556772E2D3C74E0119C4CEC7EF224488BFEBA017A910E5FD167B4486E436F7481DC5A46F3FF0536193C75A857DC53C5242C11AB911BD21926462C5060BB89F71D99FDEAD3D16B1E21E0D0791B59ED0F49871F744B13F23EF5028C238B895532F90B0ABE9912644EC079604939A0CF519BA9D185 +Test: DecryptMatch +Plaintext: 25549A5AE844ABEAA694E3F6 +Ciphertext: E2B30DD7781DB7EE7B2EE3FEB77F7360A6069396D8BF1DFD85D5429DA5A156677679085D612D0FCCA0979C97E924E77C43D3702940DBB556A5BB6EA33D650E078B1CDF8E5F76DA6591D0AFF4389A3A982A9AC581BFF393B35D36894E407AA56B493C2F7C4CBB75AEC72394AC4F8A99089702F3AEDB2FC7486F5CD01691C3C8F8FF3E951CEC70A4E172B763124BE1D9F96DBBFBA8FA0EBD1A71067A20F68DA6AAAE849880DD7F88901DF051715E240BF0F5B49EEFE35B9B0ED2B69757111080DCE2E2A933CFBE8FB9E6E9A2C2C75E0A4228D06689796AB919EF80405CBF648137 +Test: DecryptMatch +Plaintext: 5E61EB24085019F4A76893517C0A13 +Ciphertext: B13E45F9288FD2C5C0FEE230D1A09DE376ADADB5A4330F33BEC04C6F14C4A1CF3789B976F402F11611AB8345B2EB1069CFEE1E2F482A02A0ED9A3B9D94EB78C7BD7222ECD48A598E34D1F0B6205331CB20E0B2C6C146FB29CC11BAD5CA06BCA3EE39DD536FF330663A817ADECCC284B92F6AE3EB75B00316992BEF8A955EBB4DDE2CEF504E9298AC243C00FDB64B6AE96FD7B2135E6BCEFA7CBFEE135A650AA3D8CD095D1C9156232DCFE1904BC4CCE58B455CEFDDEC1D201B07ED4F999D6281AE21C2008525DB24BEA2D9FDAC1BFEADC3E6E6B1181F1A55A75976C565BC28F177CF02 +Test: DecryptMatch +Plaintext: 87 +Ciphertext: 174E5CFE167D4F6FB9A8FCC0FBEFC12864745900F5A18EA92282C8B6689EF53BBB87B30FC21DB101D93E9FFCED05538EDAB59F9FA07FB176407651DD0C4CD8269B1DBB70F24C8177EC6E16294CF5E87A3070A077B1CE84B612C3E3B1D4FD60D732C4D2CAEF5AC442A358AD0F323E60F58FC8B29894F3EAD3AE0DB8FD08BEBCCD4220CEE6B7C43A5E769D1F890A6B6505EE7FCDC7E399FE5321C2792D7AE094D13EC493CC0911B3EDBA6DAA037E2EA0CD3642784FFF2CB1BE04E5B12AC9D2871F016D8BCCE6DF25C1C04D912CBE707FD4DB0F9E89C4 +Test: DecryptMatch +Comment: 2048-bit DLIES key +PrivateKey: \ + 308202400201003082021906072a8648ce3804013082020c028201010096411b\ + e93e733637e91b1d74f808f4c9c528293e3123ac1d3d2f94c462ff38d0cd2fde\ + c0eb03bc5e54b6df41e9bbe9127a1b3a7f47cfb513340664829ffae26f832b48\ + e2d660d10e4debc1bfb412f331ab7b2f88c0d31fb587ed5c5256e0ebf7da698a\ + fd3cfa0443af91bab8c539376fcbad72bfa6985b6e64250e6b546b07a4575b08\ + 449d383b5650083c637d2452e7d1b9227adfd328ce473bb4374fa31e0ad52e56\ + 7feff6a9c4842d24d069e7babb35313ad63ca5d33d572bb309689a571e9ffe25\ + 38816bd7bde7bb11c10752e6a842751f594f50cf4b8111f387134e30c6c03ba6\ + 40be7cd5b6574c0d0b571a98fcdc292070595dcf6e8d034cc0ef92e8ef028201\ + 004b208df49f399b1bf48d8eba7c047a64e294149f1891d60e9e97ca62317f9c\ + 686697ef607581de2f2a5b6fa0f4ddf4893d0d9d3fa3e7da899a0332414ffd71\ + 37c195a4716b30688726f5e0dfda097998d5bd97c460698fdac3f6ae292b7075\ + fbed34c57e9e7d0221d7c8dd5c629c9bb7e5d6b95fd34c2db732128735aa3583\ + d22bad84224e9c1dab28041e31be922973e8dc913d6fe99467239dda1ba7d18f\ + 056a972b3ff7fb54e24216926834f3dd5d9a989d6b1e52e99eab95d984b44d2b\ + 8f4fff129c40b5ebdef3dd88e083a97354213a8faca7a867a5c088f9c389a718\ + 63601dd3205f3e6adb2ba60685ab8d4c7e6e1490382caee7b74681a66077c974\ + 77020102041e021c614682228a4bea799d01008a4bca099e7cf7711d7914a81c\ + 39d2407f +PublicKey: \ + 308203263082021906072a8648ce3804013082020c028201010096411be93e73\ + 3637e91b1d74f808f4c9c528293e3123ac1d3d2f94c462ff38d0cd2fdec0eb03\ + bc5e54b6df41e9bbe9127a1b3a7f47cfb513340664829ffae26f832b48e2d660\ + d10e4debc1bfb412f331ab7b2f88c0d31fb587ed5c5256e0ebf7da698afd3cfa\ + 0443af91bab8c539376fcbad72bfa6985b6e64250e6b546b07a4575b08449d38\ + 3b5650083c637d2452e7d1b9227adfd328ce473bb4374fa31e0ad52e567feff6\ + a9c4842d24d069e7babb35313ad63ca5d33d572bb309689a571e9ffe2538816b\ + d7bde7bb11c10752e6a842751f594f50cf4b8111f387134e30c6c03ba640be7c\ + d5b6574c0d0b571a98fcdc292070595dcf6e8d034cc0ef92e8ef028201004b20\ + 8df49f399b1bf48d8eba7c047a64e294149f1891d60e9e97ca62317f9c686697\ + ef607581de2f2a5b6fa0f4ddf4893d0d9d3fa3e7da899a0332414ffd7137c195\ + a4716b30688726f5e0dfda097998d5bd97c460698fdac3f6ae292b7075fbed34\ + c57e9e7d0221d7c8dd5c629c9bb7e5d6b95fd34c2db732128735aa3583d22bad\ + 84224e9c1dab28041e31be922973e8dc913d6fe99467239dda1ba7d18f056a97\ + 2b3ff7fb54e24216926834f3dd5d9a989d6b1e52e99eab95d984b44d2b8f4fff\ + 129c40b5ebdef3dd88e083a97354213a8faca7a867a5c088f9c389a71863601d\ + d3205f3e6adb2ba60685ab8d4c7e6e1490382caee7b74681a66077c974770201\ + 020382010500028201001eb30132e415358b7d3f726b93e2eeb083fe7add7abb\ + 6ca352c9e09b365e5768ce032ee52d59f1c65311045c490c42c36ae08cd0264a\ + 26199aeec8c3a8882a363397b4d7e0b6c4abc407f27847be0e8477993069a1a3\ + a3fe68093e09ce55bbedf97c91e741ad2eceb7a0f4be6ff87f68deb03c5280d4\ + 8fdf4900485bf5ca20257b176f58fcee1f0451b3716862488b0642bcd76654ec\ + 4874512538976967a545cdc208a0050f26e541ca70343f653222e6df7aaa07cb\ + cf354a5ab910eb8447382d7f512c440982ab37a402c87d2888eecb35c636ba6c\ + 84a5cce917f234fc7f8d9167167e30f2840407e13751f1944f6aceae3f5a7025\ + 36723c1d88c8c04981e4 +Test: KeyPairValidAndConsistent +Plaintext: 5EE1 +Ciphertext: 73279829369404A1B68D5E86FF334259936133CB04C9186CFF733972054918C3285EE907C2863DEE872252BF03EC9FB088B8DCE6D69D78C6BCD6B3FF87E683C6CF3CA05FA6AF0C068D964BE01030A3AB4E19575811D141A59CFBC9D3558E48CB771D88CB1E0E6C7ABED041077D24005E337AFCFE8531569FE56E2CE97C40693C071409888AE46DAC8BD739AE0E1C392586917FE07A66F7D3AAF0DDC398117B594481D0D5CD19C8708DAED6338EAA552564C31F9548FFC7E5C641FDA95B252EF637C6CF708979948A3E6B4F37A9ADCD60BDD841F3B0945CFF55E2F13468EC71C550CC2AD48E7E1FB444F132AADB1EF2A7C5A22450D0E0CFE9E37D999B4794B5A594A4EB7ED406DB24ED541E575B9F2756545DDD34F6DB +Test: DecryptMatch +Plaintext: 0252EE2E1C603017 +Ciphertext: 0E742D794904D05C0F0B6F60E9655337F8C110F289C6E4A0D6FBA6A2A8EB0FBB566A7F9B9862175C7A00A8205E8C8012366023FD8DDB6EB713DEF86917233DC5D16C2822707230169C183FD3A714806220D7DBA735C4F747A23E4131CE12C5572BD5E659F967A8B7DAD0EB6138D1BB569C6F04EAD79F9A6301609697F73F6FD8CCE934FAC6FC138B4C552E211FB1CC242805C035815F462D0291537DE10632141ED0A7C22439C7270AF0A6244C073CE9E2654FED918C86697988B0B341C5EAD2CD6DE75EAFDB1DFFCC5FE465E8D8C9A34D5B7F0E9DDE62204FD12EE2F99435DD58F3254268F8E6CFFADEA9205DDFCC943004887C405859866A0A40456A6C50B57FCED319AE0EC92B9069F765013436FC9A0253481CBE12B707A2B20D +Test: DecryptMatch +Plaintext: 01AE +Ciphertext: 6AB2E26D99942CEEE4844632355BB3B7713DF000DA11099D4E1BF9EDD1781A9396032E9D96BA0DF21B309A9CABCE9AE3D022C33A931183DEC5A3721EA5CEB39C18935A43E3B0BC153E4469AEB604D031A0084BE5927478AF8EA652D0A4AF455BDC57EDF26E2C6F9A01C91F29984C11D3C60313A53D8AC65D9FA504742868AD3D313506EB4FDD0E9799B111F3041F4C0547BBB06BF7DB20D18B427BCA1BA5099821A5F0997EF08C319B851F0C88B4814CAC7BAA4290B3182738C37B6ABFC2C4770A633F70E6FA4FA53AB286384FFC2AF9B64DECBE12C8EEB97862F76296D13D889E864418056420DCCD0DF9B76FB32FA6BDEE149585F427F133972DB7281D91D6E78B6BC46151901179D186CAAC784D6271023FD6E84B +Test: DecryptMatch +Plaintext: D52A1E0E3253FE281A9471 +Ciphertext: 63F60818E399024073EAF02A7A419229EA4E2FA4126C910AE7D31DE7EB6C9502752F5B7241F2A133E9D71C1A75E23A6F5DBE36C1B661935B0F20123BF434153B1F81BBDE278611C9FAF9F56BE8C78116823AC5B5F355B88A82AD6A73D2B63BECFC7D3B39DB2A6B393E23826235AB76653EDF65DD7A94BD27E221E9D511041340FE83A27F7B26CCF3FA40B2BD786BB9D67D2BCED415F2F76D116E8F3EDC953B8A327D2846F247D91626F643F8DB800F5E1DF0CDAE2369AA8969A938E0BB5A44F0A9C0BBC7D15A34DAF4713531A7B6B59CCCA2282952B16A7E1A1D1CD47D8B2AC6A88BC6A85E692FED89BB3D1F16AC2A922836152059433A29F786F2386A74DD6F555CC8D06C890A4A93E9FE88CEB078333A631E9E3EED0610F0A17F2A4F8DAF +Test: DecryptMatch +Plaintext: 53 +Ciphertext: 7F820C0C9A5709C6026E58446623B5D4B323BACE54724F456684526BD1966A360944227D04824B3C9BAF19A602EBAD25B8047FB6BF9997EBDE6B854140C032481F1479E4B994FC5A2DE8128375099A7A0024AE1CB985D73BB2B806B20E0751EA154BE2A70ECBCA49335BA57694DF1E0EA4566304B8DF4BBFE5AA41D0B767AE1679BDDE70F95E1C0C7E06F4A635F987E2858407BCA2133C3EC5620D58F1AB7FE1426B615959009A4706797FE4060E1C690DA373E48D6BA684F69E981DEE5DB9A58C504DED4D4CA6CD9B776DA03E55DEBA97E541A300465FFC68C5417A10ACED061023ADE00FEED4099180948F26F10D2F9470978469F67AE1092100C16D8FC4104DD1E711CF67D5842DE4102869E96E817F9C9FF520 +Test: DecryptMatch +Plaintext: CEA6026338 +Ciphertext: 13D877F0F00D01125447982639AC82AACF30FA0573001DD809C72D0F811138088C6D6D0569E63AB001CEB0339BFB90F7B71F339CA2F75859920370C622C0C4930B79B99DAC0560C763A1162AB46F58D1409E25301AE6D70DD4FA64984FE894DAD2B6401F8864580132664DDC2A57D1AF8AAE43C2759780C8587475F21275D61765251DA8FE91921703DC8DD279DFF4260D8AFE69257BB43EC609DA30DC33526D66E46365F399AA04F34FA7BA6469CA964AD6F2299233424E7342F1BF493C0BBB31FA1C713543D758219AB0F73B9C24F4699415F96C32E2A700669FCAE7EA6921F96288723ECEDF9677EF35702C8C0B71AC27A57624A7667580A2FBFF72818B2BCBA3589DCB686486FDDB50E29E75EBC8AD3DEDC8B741AF80F7 +Test: DecryptMatch diff --git a/src-cryptopp/TestVectors/dsa.txt b/src-cryptopp/TestVectors/dsa.txt new file mode 100644 index 0000000..8f31ee9 --- /dev/null +++ b/src-cryptopp/TestVectors/dsa.txt @@ -0,0 +1,337 @@ +AlgorithmType: Signature +Name: DSA(1363) +Source: sent by CygnaCom during Crypto++ 5.0 FIPS 140-2 evaluation +KeyFormat: Component +Modulus: 8fbb9edf2fd2834b1a9fe97c25999fbc381ae165d932aa521592c2cdcb4318bfb99a2408f118ea874b73704e2cc557fc89a01ecfb5bc412951e86613b0b2fad2389e81ef42f79705fcdc87a9b9dcb1afb44c37d971aeffc1c859be367457ea19d71f22bcaa29752f15242f59b295125e9e01ab582887fa869e4b0f4a308167a7 +SubgroupOrder: cd6c675f1d22c771e7f59020ca0e94078950df9b +SubgroupGenerator: 7b473ffda9ed6e10f85177ac05f43ec666dc6d42310151053ae83369de9f9b331232cbc83bef31166e19b111e46e57703fc6666ac9a571ff053e18f3c2fbc4c2f32521750a941981a55379a2fe13bc78c6a3787f44dea397af63a7ce432704657feb57295ab9711ac7070ca5b7344bcaaedfd8bbddecd8de9c67e7cffa2fa20d +PublicElement: 64f31bc4d5b42622b41326361fb0d67f9feb364b34be67f6b2e4dc1f928fc70e6fe42cd9cd6ce3dc40113e7b4742d4af6fbe04d962adc5238d4d95b7bb67f0ec6592e966517d0a34137a45dc82ebe282c904750e1aa31b62c919b250d4d8ef922b0b0574cb2ccf1b451d7facd075e77fa532626602b32fee6fb334e1c2911388 +Test: PublicKeyValid +Message: 699c4211bcba049ac8d73c37fc3d02241f70b8ccbd6a1225d813664bcd043660847dfba3dca434cf5600afb60036171ea402bfdc3279ae2f6b7deb5fd0810a96ca7ff7ff1a36021d84a92b6db7d4b03f80b1d5d2306cf3af4be2c448725fedd09399cd5d4fe8853cabc84895fb91e4400c7591e691bafa5cd0398a3c8d18f8c5 +Signature: c0aa11b2571acf6fb78dd85148d97ae04877ea1a05d27ab73783ba4efa3a4b7f110cc44c7ba2c842 +Test: Verify +Message: f5373216e55156d66524e39dd8a345cc519edd8cee2b7cdb755222d42ef8f843000e8b69cffa4b0c154543c3bf871b804a904b5e1ed8a1ad2a29f63bc28b2ce5b5706c5fb2219e40dd682951ad7fed1709397d9ea36fa18894ad0c57391e5af74db54d8f479d4989f6e40de05b63b4a9c7f0ebe535c87485ea36dcbf4b897890 +Signature: 33e28ca5be57567a880c52451ec72f27d25b6e26c38216900ef17f0c307fd7614b399ff5febfd7e6 +Test: Verify +Message: 92fe48a60045104207970b674f800f67cabbba0dbc8d1d120b64a4ddc9b149800003f9efbd6446825ff84fae21d4ed00e61d1f5b4562b872d53b4788ba2247677091889fd75ddd017f52075b3610e275d025ce4c366c608eb2a64a567a5688287ae2cd3066e72db701dc0ce6a7eb46bf210c9f59aa646e5c3ddd86bc210665ba +Signature: 95616a85b6d9ff3c9af7264cbbf8b9cdb71404eec47fa7c91291fb93ddd8b0327df74cfae6698e0d +Test: Verify +Message: 18b8baa09b84cf8ec77a1d34d68b0971fa71016ad5b71838350ce9d114c8aa34d0bf8fd9a747615876845f58b2fb55bba757fb08f176901838b7b7042f87924fcf2a1c50d1c7cce36ab768514b0f277cd86b0a4fa7fe7c653cd729f803751b0d8f8f1cde121d47871caaf0f598deb70c0447e718f0671576ba04f68488ab80c5 +Signature: 23c6fde5fd9a2478d99c3abaa61363d90b2c161e847be181af07276e376ce4f76db56dfc3a1f2425 +Test: Verify +Message: 598660449d62f60b1e0581b0c493803d3ba5cb49a5c5d5917f2a41d6d1b6a8f69a2ea94e7bb8334fa29a0f5ffa32b1f291313fe9491ce32ac3044e8188848db77afd10f17a0ef84b5b56a1b5076d700df021de7ebaeec51827c0eab042ecccfacf6bace5f35add3820b04e6a443e55c632ecbec05032149182d52e1a57e4fef8 +Signature: 2c07790afcaf89768f1d1492345510d937e65bca5621811e1b705651a861be1f88f52090036cc1ce +Test: Verify +Message: e37395964c3c1f7b37c99c2f56070cf9672de2f7cf63bc6778ae6532e81f09baa23cb7e5c2af1c6ad32e7e5bf4aaf7f42cbbf4a20a4bed578182660d02f22799db04b8b2cfa31f41f727ddebd88326ddc6b361d77860e07cedd6e1d87e28c53244a28f14ad6fa099598cb1f73bec114ceded21ad53fa0d6d7482ccaa951a5b1e +Signature: 58697e6dad83ddfe43817e5534535ecd78a985d3928e271212165dec4e76c8025d531ee84ba8caf3 +Test: Verify +Message: 24976d350993351696b33cf2db5440303d5a722cc2d25eeb9ccf1e20f57ec060fa8bf4a22ab9fafbe0bdcb971f5b86fb9ec41e79142e42f4c6b58dd54e71ef4eadd95cce9458b3c5ef2df19ab38896e9e9e35801fb9e079e3fdec0e3c1a7559b5638fdb1dea738edd9bd06f12d144873366f76bc0f5a83621f030d42e857cac0 +Signature: 7488f2ca5fe2bec2c7a83e73407411c9e89bf8cd594d4a03a736423ebd913c2b98a21e445bdf70f6 +Test: NotVerify +Message: 430cde2feba0256295b6366211252174a29c9bd2b8e6db8fe97fb9ce35580a247be8364a37741b077e9f275d3b34b1f2ab3397c2171b1e04d177065972aced3c5201e6a648ef5900a3ab1e4f69f2d59bcf1488a0f84485b8f21e7508ef7ac1eac070269b97ac9726fef3539012f647450557a6c2d4fac685448d3e32235a3e06 +Signature: 7500d2fe4b2943b4da93490d3bac5c344bb18eb550975ead0e461ec33485e11714b4ceab478644b0 +Test: Verify +Message: 81bd412f4f9c8f8b7885d9fec9b013be8246d4284121dc9c2fbfe59a6987af1db141463855cf96ef6031325800b961f2378a6a46c65722bc565ab3c0e993ae15814354790fa8217a9efa9a98c0a6599c39c95638ebf077e0010f5be860bf63df4abc032a559e47e58bd8a9f6e3ee1173e0fb2d378762f4bf87d4764aa483e631 +Signature: 37cb9d9adb92a7e74365f9e4c4857a88a6fabd200d955dc76333b0ea9c1b2f05fee9117c79b10d09 +Test: Verify +Message: 84652beae6fec221ab800bf6303f17a47a84278a1274a2b11f40569bc58ff34ebe28c5a138e4b1c7eed4731989ae1728397db5038f8970c59e84b16353f8a1b411ede5c290de9e50f7de9fab3807f1b6ad238530f09e384900ac0c6591b6a530b30b03e2a8c47ed4fff80744f5219e650cce0eaaed8bf0547b0edf3a39a3f8d9 +Signature: 194a79f399087d977a29a3eab308670b7b133acf4e8b43068639e0e5e37d7ed305e32b85e30a0a22 +Test: Verify +Message: 9cdf6e966c37794c7b3dd6234e76d715099128caff3d03917a4a96a2c703b19386cab41830f5b8ffe9e9fd6b88759450e4714d2f6298e413bca267cc13a5ea6c38ae6fff379b0f8e253b6e562ca95f45d4e6d3b694b6076e99bdeed7d5d9dc7b4bc275c49ae0d5f2c86c015d51cb8eed702790d7ad50c59aa8d203392456dfba +Signature: 7b427233d9e49dbfd8ff2a7814dd99cbd4533d67155696b215d593d5ac3989c8927850601c0d453d +Test: Verify +Message: df577c9f2370b362f86a928e40106d7b0a511d5d8ec619776b82d57e1f195b4bc7f328c619d2490e9fa2b6ed3681ef7cc60fd51343f7cb74e5be0d37a3cb5078f6b89bc0ccd86532ca09f0f7c6bbe5eb85413088b1571e131ef5b6063e5355bfe23d8d6733993f24f036f682ead7871fbd7fe796d0ff4dae90be88c4e8c9a276 +Signature: 39a7efc692685eed0c3cea8838c026b39367c6f446a16258906787af9447329ab99e821eba53cb89 +Test: Verify +Message: 91042eb63d47c10f678bec836f98630e13e707b29c98b28d47b1443cf699e97018d4aecfd500440e7f11134c35c982b1d97b86473500691869fadc89974840f7d2ca319045565573a0fb630bc87576a8bff09460d1027a2500e3ab28b2eeb86d995dd1afe3418c76a4c0f5778094d72c9dc04ab4c8947eede6e3c6cf9d83e80c +Signature: a813d89e3de90f1ce1b77a7d6c629e8f83296aefb8bfe1194f914797d08b53fb59cb9186935dc10e +Test: Verify +Message: e644b9a45009da8248611de174b5613dfb4aafc0a772740c38f1ff480bb23e69ecabb5c2380dbfcf37b1093eb8bf4c3feea04a0d8b270cbd1bfb5a46a2487bd279a62e446649e80afb6b502431f6f97544765f4ad13f24282edb8bdb0ab635bc460d1c421314cdcc4c66eaad16b3e078b6a4e48eb21234e62b688c1d7a56e6be +Signature: 4e4fbbd84fc44f0ecd6c163fa292cd96051ca51764fb5626f8ecbd8470faf6ae5d79c731d9a3497e +Test: NotVerify +Message: d30ac577ac767ce6eee34ccfe09f0278f2faf8d28f657cb424ca7f53712b7f040f7eb63643c784ab02771af64405693a8eca4a21ba22ee1b09c189d96c533a0910583e53283e5693ffc076593d7eaf9e79de5ec9002296e2e4cacc15492cc26beb52b5c4f414ca17fd77b6ee6245ad1ccbec8ec2f89c4c81cc9ca0019deeeda3 +Signature: 4ee3704d4bff39aff0efded0930cf28ff7641f089280f1d0e38a186075e91d73a5b1e7d028340fe5 +Test: Verify +Message: 82bb8073af3e53b8ae158f342c4cae3c039dc830703bf0e893dacf5d280284948596bbd0d3a00cf8915f96464693dc328507df9e27607d43c426095b74102c90c494fc24fbaf5a628ef29146e1ce2c684020182f1e00fb338cc6d4f2fd5ed3b739ce7bc89e05f6cf9fe6b88b769558b72c01ab3accb22291e3d5667a3c8532e3 +Signature: 0b0b366b23090265e75752fdcde1a7d76113653246e0da762e25012cceb13859313e469f4dc31680 +Test: Verify +Message: 12da3a70153655976cba8144f67dc21719410fd136aa69ab4cc11df9eaa955005ba0e5140d3955f643d82a6cfc6e7a222376afc1f8309b4dbe1dbdc4a6bcd2f5fc839f9e9020fec967f12768a3c14130b0c529b3b0d682c129f1fd00eeeceac94b7a0046746269ca30fc1171c2ed30f9182416df371436bde63376e49ab2b635 +Signature: b43f325f82eb07dd2cb3a03a022e8c89216e820da743c216ec6eec5bf445f12b2d326d52e38b90ab +Test: Verify +Message: 45a2799fb193f3adbef66b8035318c5f7eb3610dfc64dbd1a84b87c0f082884ed257db1435c4cce38711b30b9dc8f4e5c7d936a7330ee36984b2e172b37d8ec925c401f80ede802305d93d4ae85e56dbf3e20c7b1c0f4216b17238253465893f773f63e3f4bb07846fa781d6cfcea858382658226e3eeff166e306702e1271c9 +Signature: 238f01011e1b3e7d027af353e06e2138f5a40ffd3d7a78d55c95ea3b94ad82b8ed58c308f7db5ef3 +Test: Verify +Message: 6cff32791fa0d15947fdedf67508fee334d1739512e15ce3ecdb5ac17f56c43e2cf51bbb0bc8b06d34e894164a4dc0ff48f3863a902d3716314916e278667de7bb914ea061279d3c36679b57ee56c6f4f7d84fbe830bcb80d6e71ee2cd15a565b00ca3a13972eebfe4b2da3279d966bad8b7a69a0533701873ed4a36951b94b0 +Signature: c9194d5ca3dbb424faae51f66377836a93bc55ab1d481e5eb9663c7033329d82c13af868f4a24efd +Test: Verify +Message: 37a363f2ebaa01fd1ed7902a4804c8fa46845b63d82b947e59a23073c0e97da2d72db113bbcc8d2095a6336197a744d83a923d5eb610134dc1f80d6f8de1e327fce615de26b88db10dea78599f79615aed9b906fabcaa236e8106a180e94077b1c65462c23863a07003b19e858935ad7d9360d6fae717a8f4480fd443c1a21f7 +Signature: 9ca210249d306006ecffd384f87c4dfcb1d466e005d877c2508475bf0074c4c6fffad6e123bd5dab +Test: Verify +Message: d3b14dfc79ab30cae8e40dcda6bafd6434741e6ab1b9e0d2cd4e8d80f10f176aac3126ef61b662772f31fe4d21bc85b99737e961f5c2c9e28a7d02aac27f7a19901529d8163c687997617e509f576890719ae9aab1c3d3e3524b9434c384036655d56d6ef035db06f7eaa68e78843e22981437fc3eb2950bff2e59d54a154b8a +Signature: 30cffe077d2330f111eaff346634237473feb83cc522a5d20c75db7b4c90c4e21583e1cec8e00f29 +Test: NotVerify +Message: 69d5980a58474652bf27388ea6041f9e0fe688ea95f59fa745682c69bcb1c7ea82e75f19a773eb669cff6e4d549b31219b323c1bb62d16a33c65bfdd344feb77706280b229cc51afdc571dfc6495c35f5953c8e1a83d0b1e73cec7cd2b7bca8beb20f4ec18abf2c437073cb20f4b4def00232255a27ff6b3a17b3b50d88fdcbd +Signature: 18eeda64cc75f18f58d43ce6b95eb3918a521bfb40c1745a38f985d294caf2d86879528678881191 +Test: NotVerify +Message: e0ac66b23eabe745886613c4698c79478f484a43f8dc444e7e7ee215a673c29ba56a56b4b41bcfc1962046ad66132d28a6eaf623858f028c71c3cc4bdd34567d54ddd4f0bf9f97dff31e3def7edd1769b39cdbbaf3f28b283e27a5d7fb548cfc04be365ff66f1717b7164e8148210f83cd1951ffda3db89a0062c5af980a3c8e +Signature: 6db33727b795d286a69ddebadd6e09c527bcb1ee596915b6fc950549beed350fda40a4c1f52c6a34 +Test: Verify +Message: f9cec4d6e1f2c2285dfb17d3ec5d16edec0da9b05ad12d62cbcd8f84ab4ba73eb6cad40ab44ad9a079d7f8221c544d89778a6d50df713f5f25bd1a3acdac1f6a8d0fd92c0a971459ce62fb958dc675bc995dc189a3515088b3e9e33f6b54e59978b60b9359712a2954b55883b54b475c4a9ddeb31c0a19b66f6922ebfcdbb0a1 +Signature: 947428406add226d1dd8db3245d00617b152921404ee5ab8d4e840c87d26073cc4d144a0b51e19a5 +Test: Verify +Message: 966d6fa1ea1ae8d344037a48420d6379278133fbc0c25450974fd9105bf988398f652ad373c511c830d2eb02470dc7c63b3865507d0fc3b0994ce4e4a0dae337d55839d99bd14bbf9eba37be412de0e348653815c77acdee4b5d97d646170062c03e35ec3cb8ac73e8b3f6b40ae5c78aa7014383757a8bc4037c881f2727f772 +Signature: 63137ff0730f28235e87cd5122d22a973035869332ec538d5be6e2c9c0db94f3c012ae4abf3af9fd +Test: Verify +Message: 43a8f0b5992db54d1d65acbf72780493d1af881fe95f9f14f61b834f201ac1df16e5f252eb46b845306efc2b5365655d38b71c63155dbf8193e9a48623f64fd19ecf36a4205fb4ad26594bd2e6a81e3cee19aea80147d4ea2fc700c23395b0e411bf3342f050a09c357f114be21925492e2cb58564f5d666010c0f9e09cedc31 +Signature: 1bf8e80c8183d00907ce80e74989d84815db85dd1654a6d49f74c020a83e8bc931a178ce18056f57 +Test: Verify +Message: c4aaf1632b1438752e9790c89cff4773932d3fab0ef710bcaf41794bcf5c0ccac49e1a3c7143dd2b1484e4e74cf6c4006925fd06f9702a8090276e2ad7e41b74d727a3378835c4ba9533efe5727efac4a14d073f4089b418d7ec8526605a8ed0987c65cc85a3471948dc893b254f41b7d0dd36cefafa057d1cc796b58374bfd7 +Signature: 5fa8964b471c76211e2743c4d993e793dfa7239dc84a19bb3fdad2162a8c98a2434c94213f3a163d +Test: Verify +Message: 739d44364282b7bc61c62188d07e0ef12b907960a740f1764ff8ed7981586c04a47ed0ef2b97fc7dcfa6adc508941762cd79c05f8d2aa15d6e037a06c5f676b7d6d40069cddbe4e0fc81aa18578030ed2d22860929cf0f1389d4d5159d762c2f82378b7a2067a73f62efd159b55a91e8c3248438714773f01704b57fffefc7c3 +Signature: 1b61d79c6b33e3c3394fff6efd641405652033690d7219da8475faaabce3e395bc720d70c60e12f0 +Test: Verify +Message: fc205229f11c877b617739d9ac191773c207ac714c5e2a061a917ad2cde4827ec628b5924eb8e19a06b4357a927d920e8171130580e8dfffc06f2ee5a4449a89af12a87faeed963b2291676cf0d72d984c7997f8e207ba96472924a5a0161f21915542a769b33e978b85e7681f20814bfb964d03ccb25404893674cb1954a87d +Signature: 283d55c038d4270e71ae39db618390f17675478b704764d1fe352550054076f4461eb6da6174dd17 +Test: Verify +Message: c343029ce5d70a70251b50cc5e784126dd65e35080940f450d5cf435d567c9ce8a9dd2cd5d5096c55ba95f2f0952f2b33f6490b642942d24259aef7f62e2ea29b4771bee372ca2d5c30c4428850421c1e0cfb2978323068acb1a3d6b5be34550f9a9d416acc3a637141ef8ce09e845e7787f400d7a99120eb5b4d611f8c051db +Signature: 0cdabb09213e0f09cf01e0329bba5661753950fc92e681173a6eb46c02d00224b50ebca62a248faa +Test: Verify +Message: 5e126ef683f3b61a39065574bece4ad82dbf4d34495f40cb899dd2b163717588ddb683795244ac758252a3adde0a0950126e9984d26a96a7e93b72c780ffbf60ac9d5b553cd8d831c1af2a9edef79426d13cd42942d48e204c45f611cadac252e3804f81d8e612c40dd5423e56cdc3d285e1561b31d400acc875b885d73854d5 +Signature: 01dde9613b9ce3c29b3503c19c13f863f27ab71bc0844476b3860ac891f9ce374aea6c24f517b8ab +Test: Verify +Message: f799a6b5a7bf7c32847fc243cbe0166f5244a377c43682c41b75530e6342174fade751e751885d10692e10858b11926ec626788fdfe925b2cd6d625272a13c899ce41e3c3ccc2f84e533ef6088840d9a6e448bf777e415a291c59ddb7b8d3cdcbca9450bde23ab67f0a6952c3bcf3fc944b6140502bc0a6d60983d00f69dcf1e +Signature: 0fc64023e095044c9d2d003a555e2da7aa5daf413896cd4e7ac774ecbaa0e4ece8e8ccfa053ab62e +Test: Verify +Message: ae0424ff8fb19e8842828a3cd51c93e1123e0c4ce9f9fbbc1b326979295be9ad7c6e6783d62b337ef8924e1b95a3f4aa77546a6af0d409e483ff8b89d422958fcdf0860912c47f45a819b36be047f0538a806ea6580bd83990bf99a6f6c2682cf98316c91df69796a80f50639082a093a5b9b139fb1580739a692b0769b47b3d +Signature: 6fbe751842e02a3fc3726a5d8298d1a7adb799a02d897597f4c459d28e9e25cf447b8cdf50001d21 +Test: Verify +Message: fc5837b228cd6c963b52cabd227cf61b5a1e6ccb4baff71ae4f971da7904bce5d94201efb3fc28912bfc9894b87c307a414f8653784e5fbe76056e3d989f51bf990fca68f0813aa36c00646a0e685fd5278fdce1b2af9a83f41726ed5212d82072180bb396339ce235b5a5dadb187b434335e50fb2aa9f829685108260354721 +Signature: 5bb80b35dad17648220dbe980a660effaddd7c43ad3584318e835c355dd7bf2f5510091389c42914 +Test: Verify +Message: 689eec3b665d72447abe64d4ddd79b7b73cd171bd22fa8689395e0a3d9793997205583d449fe912be240246ababb1859a5fdcdf48ce1d9ebb928ec58615503c073ced04ca0306948abf231ddf33e040b3e0ca7eac8816e218b872fa7d1ad67b9f841ab1c85ab52956d0c61a69f18b78ad5317a739dc6c102a2ea82084038bf7c +Signature: 3cb07367288036891a8861931e5b2104734a6e7e70ffaa32a49032b968805dd0bfc9f1989da22b12 +Test: Verify +Message: bc4828ec0810c7a43cbf028dced7a5890803681f86238a28f296aebeffc7f561a4fa5d6c9a595ab7193ab38eceb39fd220601f6ea5739efddffec8b93b7da7a74ba705014376fde4b375e33a844a57ea3583a43f56a55f9745723c4d287b34e82be7d584fb82e98183094b6be6b4052abd05ae6b92d0034d9d8cc550bdd8d27b +Signature: 67b214ed56ba44ced95d3d9e8c25c99331e3e973a3099e524473ccc8d4256f4ff7de9674a369cb57 +Test: Verify +PublicElement: 19b80e6f0132bd24dc0f26acc6a30445c4deb4fe7394440ce1ea0039d9c8137ec962e54b09d4383989baa288129e551e027477965ba1dbca0b6d586e482325f09a0fb16236d7b4ac3a3bb822a7a329aefeb91936f4b8cae38fd1e369db4f3f97421277533724d27e39248de3618a662c4b757cbbea2e3d805116d3e9d0ab3547 +Test: PublicKeyValid +Message: ceba9387e7ba8d55f8010aa2e8ed7de2c8310df67951e1c49c5fad18baf47dbbb571c2d26f779a79b8a564a07d9184252f097432728b0cda080212effcc3052612c8266e6f2bc88e85e6dafd42cab20679bd1b1d9038a27b6b001e0199237e4cbe37d81441ceaeca363d82728d8f9ebe7dc41d6c2b4f3ee19fcfea07e90c8364 +Signature: 84d8e940de14bfb65b8c0e0999e296a1d3c51f18b8bd79c57d826d9d200a6e38e52490722c6ee201 +Test: Verify +Message: 7b9058ef673b23e5b6a3d97784b898e0d912c990449be876b77b768da6443ba95b5fc1849db70e0482a4a1cf901aaf111b129e8dda38c3e2ccd758204a03c18b6d0500aea30b76a48c11dca21b0a82c9ea54c62bdd5bd71bfb8bacba897c3fbf68590f86b191d55c8ec285095ce2899fffb03983845a9eb9fe6f68749a082ddd +Signature: 7d07f3033c1c841466eeb641ad899ee247757ca067ab38f6f698ad0cce5f26517da7bc51b8e630fa +Test: Verify +Message: 2404a0e4c5ff8fa11c40f9932c8bfd3bac118eee53085c8e658cff857eb56b029ffa907876c65054f258a7fd07e01512bfd850df82a02820a65dbafb3a13d9380f01b9c3093ddd64a49044bcc994cf84d30cf602dd84accc4f2a8fc1a8eb55458ed173bc139c0f494aa028c80ade040a0166da50fdecc00a77aad8d16175b7a2 +Signature: 793e491940787f4e76495575616901c1c77d023342569cb8bc96efcfbc9746b3f51c31e29b221b02 +Test: Verify +Message: 5c311c167d2e3ebc19fbf7ab1c619d8ac1611152527a953d2137eaecc6fdaed79c13f4fa76f224bea7cf162531676a3a4c0a2ab81beba3f9aaa681222b122a8d724a5c77aef60aeb69df73eec3b384eceb157063dee88dce64dd72d4473b4fb2d6ee8de59bd3a61d5843465e48dea37894991aaa130a0b9246f3f659940ed61c +Signature: 7f76e9d084a9afd5c390271261b316cbd1095e710d1b7e4503188c99b8a8d851b130ad240e31f0c3 +Test: NotVerify +Message: 9dc221be2ab612b2ce6c7fc8b739af7fe740e9601f3201d3094a2444a488e076f52c7727ec7665e5949d2f307f0e6ed171e71c7a4cb21f9f3c661494239b5de7470e6d003a5553f80ae385b6aa3fef50a0803ca1f10d64264a93761e6f47a8e2e95e9c82ecc9f5a186361a930e434ab5cc05e10ce5b9e9218bc9e41b6203d81e +Signature: 332a2daa48681410763f13c3b127516c861bf1f187504d8b3bb1bd11ecbf9a9821f18466c10f1859 +Test: Verify +Message: e4354b9c9bd98d62fe629486b6856c96f34d2fa2460200c5c25746f454d32a065f8153049bdbe1b32ff4a8600de6aeeb8f7be7174f1f2f114c06893e3a9997492927596d5bc92a005f96f8417209c36316af59d9f41450e4eff0445b8a8e52ba7d7ed56e927b6060c59ffcc09bc5a313c33ffc80ecba5957e56deee2fc895471 +Signature: 65c2fd8a2635d6942b4b833682b29637eff64d80ac5ba18491bdc26d1c34d70a2c4b680900347d1d +Test: Verify +Message: a090ca3eecf8677a7699f42b16428445a3cbe74981efd6436d66620185469e959b9c8c0dbb464672fa136dff821ed7a2db6874b97bb5810691a9f1f30f22180df6d89abae633943ee56c08ee6fe88eb3bfd139c25df7c899e8e60e3d2647a3b3497cccbd8477a9d7cfdb9d71f657036ee83f0fdc3e6b01f60a559157e36e9781 +Signature: 19b4876e4043fe5f5a58e70b1560b0942ff4fdba842266a6653a6aa1550b91f4ba85a3b676a3659b +Test: Verify +Message: 8e2ecbfb35ae99dd004f2305cb2fe98c81edcccc13372e86b98f4e526d5dde4da43ae6fd4f7cdd8812fd0516c43107832767cf49e95faaaddb0e9f2a70ad0b1b790880ac1f05df022172b3a94f14d13f47ee2e5f70cf01d0341f19ef82ea805a832e51de9b61d7a3a346e89665f280175919a0e59f9e69463d5b757a9a2d7662 +Signature: 6d67367aa1caef2722c125a30e9e08ef7dad05a015893ec3c395c35d81944fe2db2a660e4e60913e +Test: Verify +Message: 6d3ba912c4bc10feb611e15965fe814bb2d5e5de67705a1ca46e8e6a8cb2e3243018f57abb7a698bdfe3f9c08012bd6aa033bc9f8bd9b351433f24b12ec0a3c3fe945c42e1cce9b6eb9153d4c099661686ea3a9b0ad3ff4131280800a2bd1b8ab125f7218fac27b8b092064d7d8a13863c73788a3c56d52344a051113ea1e3b1 +Signature: c56d1aa9f30790bec01fc07e5816fc6f44ab659898a959ecb061b4347e7f2be6f2df97ba33043a00 +Test: Verify +Message: cf2010dec81c60bbe408df2bf20f465d259a5a8d2f7920ce9c566318705c69950423f1281edf713f50ca8eda93cedbdc2378d6929d192081573efd7500520cc6799247edf3323e4849cd902aa013aa273daec49ea6741887fcd4657e987aa511e5450a467e6c3f7088ebdc3451342ad729141aca81e3807843f0944e712bab0c +Signature: a6640671721cb21d86265e30cabbc09ba20cf6081b4a5c7928ab3a53d4e291bf6049e8bf8418f6d6 +Test: Verify +Message: 4b00e4324ff7fbeb0fc48a6c83de82d52da1bcd1eb6669cffbe2bd824fc1d7971383f4b67d96d5bcd4b56e36c480d021e05d58e0788e197f9e93882773c267e1b725f38f919451289b143633316ed687fb131041b930d7064e0de47a10ac9a014f9e39b5232847a87b973c5b63e16d7f957d3aea43847cdd24092975bdb5496f +Signature: ab2f5b0d5237ec1b7e6297700a7c06647a526cb069c8162c513100008fe0dc37d4a8c9639ac94cb0 +Test: Verify +Message: 20f18b1eb4ccf98fa68c10d680f1536bd5c7c3307cb13ede0e3717afa213f74dc8b8f4fbc324ef020ce7335e03744baaf8a824495a9964d63ea00ace13a9467ca4ba9b264fc2337684a4822b81841f004c51dfdcf193333cfd77c4de3a184db0ad10b8f8ce3f7cc407da369470b88647c8d92d43b73864e942d37f388ff7c3c0 +Signature: ae23d943a56fc60ef381a2a5c056d24e472e9e906e4af1bcc91a27800b99b7cbbae8d4fc303ada82 +Test: Verify +Message: c9db3284c5b9a283f38da98655485939d5662045b325ccae3207df72838a1660f22634364f8814fe9f0eeeaa0483e9efea1ce25f74b37bca264268d6d3a3f6dcc986dc063cb347a7f08220db2b97a060dae317b302d8f86e6aec29e287518af0a8f2c32d62b153363ee0d650a2fe9744fdb3567a370e5a5458fdbbce770de953 +Signature: 06bd46f7ec091697c86e82497dc184139a988e3b9adee67ce3d87d739871fb1cdcef9dc6de421615 +Test: Verify +Message: e2e5fc81619b215141e12ea9544184e5ebabcb3834e96dbad2464fb5be7bd22c5dda0aade2be3d59e732a03147e04da33f3c8854c4f23330278e8fb0e76b356bd7de54e071a22c827987cb05d65708e8ac09bd43be2948d304874443881f84bd874852b1c421e6e52f3929bdb77eabcd6c68e29dda66a4bba189e807596fb93b +Signature: c86708f91828158b1c129e48ccc6adfdccf4997e8eb2214c24fd4bf4edd8ac1f3411d77ec65321c2 +Test: Verify +Message: b9a5127b9995a063f3422d3069a4b22ff9b7816e01ceeb3f933733f1fc11b3ca8f694d49b79c159a3ce93c59d555408befc452dabd54071181fd43d8196863b1cc0caa32568fee84335c841c298068b919cbb19e06233412662b7815a916da6408c501af8f2885196ed3dbf17cdf84af0c047632f5f4ca39dcfaa81fc5d370db +Signature: 0461b5dfdcfa1f9be6e7528478e2785903f0b8990f2354209554aeedd246d231567b06c5f81e0842 +Test: Verify +Message: 38da1e2a517a87304f85291a67e7a7ea0e637e797fa1a122707b58ac10845b7d44da2afe232eaf49b011171ad781edf4aab47992dc2358927eda5d5df9ffa75a4da2035389c484278aaa60b1f7630ef97d979e9a48935873c2929892904ee95dc9c7610279533c2256e7bcb9c1a4405100a5a367ba08d81db43bc322cb885adf +Signature: 3e7f697603dd770218ff55f027a8fc980763b6b9bbe84a766e0e55fc7c23e4f734d28f67fd73e14c +Test: Verify +Message: e431f4fc91ec6111098c5de4532c76bdd3ab9a42e92c6c10e7ccc69539a38f31cffdbe8dcedaaf3b78a3a68f592fa1bcb4f663332d94bd38b8811fc7c10f60a69da5cacb303a6af0e0159675bac3bf76e459782d43ebc7896c4dac0fd009f0f224a0306e0f06296a1858454ecee06722394bf4e88129223adda68528bf87d74c +Signature: 2b2111694dd96095c76bd18fbce8f720ddcffe6c8d9c194e880b0abfa44bcaee6b97addc84c519de +Test: NotVerify +Message: 2f3e3407e1c3e585d3f87ecdf8ee45321c8d46ed84410565c7e282c1ece573acc5c2bd688ba53416bb5894433070bfb782b7397b9edae229a653f2780b993a07e887996aa20bbd73be101bc203ad318fd18efbb7c0a3b4057c08cfc3e03535825167c0255d4ef73495f80c60a8fd1352c1ec85b822f6f59201da10baa310dbb2 +Signature: 88ed45212439c0cb86f513026b72002cdae6317544b95fcf4dd1eeaf460edb6f5891080272a3b31c +Test: Verify +Message: b3b7c629f3f5e85b35f7b95d9757a8dd980a2acc68fd9f1b74ee82af328cd5a62ad2ccce45a1b8625a9c3706f6499a066c6597cb1e88309f0afae3a298d4130ca25bb6a5c5994181e73dd00109b59a074e8a95794cfb65f993dd8be27cb2cb863409dea709155933f391dd4466d38058562f7ccd8c8f17a02850d267775fd58c +Signature: b2101fe80d5d71592eae972be0cb7f67e0fc2950bf60fb12b91a1a63d9f4747c1d92d2712cc33300 +Test: Verify +Message: cbf84e9aefa950d9c997dcb571a50e25c09c7ba40e730a1c28e112109621b4090b057b442c3e339a86ea07afc95fde5f4a37f765b99cc34e1fd5039d1b1122405d74d5336360f17273058c25da2b5807633f3c181a9d3483421d6ad294e09550bb5c93bf0ca6423b8affa46e1aa232f603cd8113a90e13958ad080057925c612 +Signature: bb80dfc840147d79654ed993f5266da74985e2225e7f5d61266fb1caa2deb06fa3bebd930122cfe4 +Test: Verify +Message: 3f1ba8edcc9ff1dfe2c25c860202f927af2188fe5bde071b8fef797c5f42f96c0d75001bfc94f37ed912f06a040adaec45b6a3ebac30d901c96974960d67de3f80c34456a5621cdaab73f788d5a9893b2bbaf68162185f7f09efad07f6609df7f0fb0cd59e8284a8b0dd08194c591dcbbb2519f7540fb04ca97bbc06f1a44d4d +Signature: 06c8b4f82b1e5429a07857ad5a1753f1d7cb43b345bd935a1f203ca2e69fcbd2321b295b1ed3c2a2 +Test: Verify +Message: d0b56cf1a2bf4845544090bc5440efaf864b8ba6205a03e5cbffac3af8d50d067f28988a7fe0ab7472b3c7aa8f8b0f5664350432b44c80168f65f0bfb07cd6e11b9f7e70f7d9ff2ca961766b33047f2bcbd0f458bf02e95a8932e8e22ebd69f6dc73953bc3823d8333a21597f8833546f374d1aefa5438c9f1be0b3c2970c05d +Signature: 035b9d105cbcce5d24fc186ff52ca07663ca774e057e6de4f5cba8df8b24cbd361df4878c6ebd3c8 +Test: Verify +Message: 82f8b357919acf5ac548e01bbe97782acc131a157d1b616364ff6dd32c5993d1dea9453a6f343e518e1ef301abc636554b632d368cdc7363f3ec8cb67e768e95e6260eb7354a491989ef9440274005b0c31b63ac0ef54c3081efa52d6939470433a8e745fa9346a94ff39b4e47ba3d31cb7495f11c1c44c2a54190b0055a1416 +Signature: a4e3cd2cbd2151d2033d0a56fa7d388af1e050efbc23bdd5fd17061234244d0a9511b84525e719bc +Test: Verify +Message: 5e5dc7a9fad7608fa377eee0d126a5377bfc0b9c11cd19b3b7f88f25c36c984f78fb9f2a05e3707bb99a933b88dae649c4ed794e143aaff1b911923d02b3764f0da5d244bf375b61064f62854e7b6fcc42371f85c57b3b562f891aaeccf5396c93f518cd23ea579b032f12941b2279186e71b4181aa7f63b91f7df51194718fd +Signature: a96a7dffb16216ec93857df38b10fc73c4792e61055a3d5c2aea3e5193113b7d0bfd81f6c3b0d01c +Test: NotVerify +Message: 9f8215298027d29e4128e75b86e6343bdebfd7f0f60bf417ff57c49a5ce1e14b9154d0be68c5cf6765ede1f56ca818eeb1af228be19217d68ef98202e01cad0b7a7f328eabf3bfebd6ca2999245ab4c968b4a13e52a6f96cd8ef99d0e1c17f8f347d5352a1aa39616e36d6fe04f1a104db476cc0a33e3210b4b022bab7c9ed0f +Signature: 7956b42cf6762bfa1d84425dbde83554a598caeb6e3298db6c225befa59a9840faab00f16b662ca5 +Test: Verify +Message: c196e14d01a2abd6dc046801d766e076cae2539afa2ab5597af92c35c4bbcd8f9378923503069f2dec6fb6c17ba1f7cc1355dd4363417607c881e2e9e5430ffe80b2b326a0258ad7e589d22f270c043a530cd480823f6bd35a23e357aaa804d2411c3d360f58e66c7f29b56314017e5942df2f698f7c0b56eab727964b4222a2 +Signature: caee28fd1cc548ceeb7141e3255c6043751425f2c344e1ddfe08ee2d42ae77391ed03f9baa195aef +Test: Verify +Message: 7d8df5288388272a7473d757c078a6de15994fe827c215d0bf2f6aa50701e1e2141c566cb5445bcd7b78e6b0098d399c9d0f12f5df541530eae276569803ebbc13a7d101997a9d488f4686b7c98b7130185c1c4f157c8fa42ebac032ee8a852891e5c0dec862c513c9950f659aa824129f39c5ee63735ba4a36f9e31a1cd889d +Signature: 75bb8dd4118b861c56c6a56bf00f194b9296bb677ea7ca4f5cda2855253f880473d5aaa8196c39b3 +Test: Verify +Message: fca73579a6d91eabb3401ed9b9145c2bc94a7066a85eba514a62046a95485bca536c2a5678659828970d253c9fce805fda30ab5527a0514a7783677b867b0325dbf979ae0303bc120947f3913a615a9717695ceb9ac1ef1cae1d2f29e9d33e6f8c655bd8bd4c41420307c22e0365a4aa790fbc80795849a0e84993cb36e8c482 +Signature: bb488822df803c1b8b424169ebc82e4638af6d567a7d2adfeaff0861631adc4c602a95a7ea8a0c00 +Test: Verify +Message: 2e5dd807911f65df6c7b71c9727137156df8fe02af3c1e19bb1d51cb35e43d4e07483eb5d5a1784ea46b1d41c6fefc66088c4b661f5bb5165044a710606dd893bb43179de8ba59472cc902617d20744eab2cd621ca4e26f8e2578299da47b24ca247faf8a0e41f815e8eb8617150b785acd1376a868c8878c94c799e7debe530 +Signature: 02bd342623b4f7cadbd88af72c8ccfb29f85042d4d2d6853d6a7769f2ed879fbed85cc6c7440fcd3 +Test: Verify +Message: fd149580b4d7b1e3799006d6c37974de79658e074d2d1cf4585ed124f7204986e569464099642cbde21cbaf5c16d0a01872dccde2f96bf81fef7711c599b37b0e6fa6fd3e71ff5c4d359e4ac36258e37cb5bbe53d7992d48c8ed42f90fc60e793a1d88d156e00510849ffb94da79f7987d49dcfffc0e5d60ef98bd52d07ac6f9 +Signature: 52c97e4fd456b9a2141afde95fc0ebf4ee2a509f274e31f5a6ee2730194eb09532d7c12583b2413f +Test: Verify +Message: d1197e08ba9f4654452e42783e664e3c7ad5cd9de2565149c0aa8d5a49547d576cb9d369da79a5da560856d33e91c2565b0cae7ae59e6ee7da31d891815469b93954b621879c168e5f4a8e84b313fd3d3a5989eb828b493039bc33dab88749e3d12200a9dac0f16afa2dc303b3a557e9b0f53668d1d5381b748477ad07a573ce +Signature: 41b31f1faac06a781ce424ab9ec6cff44f1e015bc7237a3019af5d73774a0b60345b6ed2293b7fa3 +Test: Verify +Message: 78cb9e8764eae88cc7bcfecb525617286955348da2e9c0958124677a7285334108c0ee2475d0b3404940d6806fb5f7c965c06166bbe3a9b7cfe18316c74be80acf4766af95a4c765011ce6b839e8cd90d58a139a60d675f60f42b421c570ae2647fac001bb7d5b5367e8e44da806d2d6324a03ff87db5ea9b9e0af75630dbfed +Signature: 62a367ef341b27a22c1ecb52dcfc34180902479129796872ce1b0cdbb678fcb0df10b1f37da5ac9f +Test: Verify +Message: f0e673b363e13da716f3288bf4b4993d6ff109e72a28529ce9453a2eb69b3d5256249ff7ebfdb3e3ea1d659040550e46c08d7979d03d3165552a0ee8db63ffa0097b19454508e148a35cd6ad14834226cc7d4371f3bc14f391e1a196b3b44be0e361f854c7fa5f0d18299399c635cd1469387e86eb9f947e74e20dee9785ba4a +Signature: bd8054b1502e66908555110fc569ac6ddccdea0285a04c81b9ed46ff160a26eedfeb4a8255147239 +Test: NotVerify +Message: dcbaca556bcbfcc70d2164b348b037467071dc423c11a549aad8d06716ddbee49668724899a84daebf96084efb29f246e7bb6ca967bba2ca82948bca7dde246039c4e8e8cfb593af694f197d6488e164a41f46c8364250b02d81af4cb6f2f9c67da6254d454c4860c3248e58bb277c395d7564bae2fe299263753405f972b7af +Signature: cc52d6498a412d0b801d243e37a0291644135294bb91fd182f3458c59e60725b21436a401d534497 +Test: Verify +Message: 901bc4215934ede2f6835d615c38953a95cd48bc09a249a30edcb412b37f5cd4c9ca75d433d383da706382886614579471a97647acaed5377f511241697fe0c90f42b735865abca8dd1beefcef86930267abe2fd143ef25c6f79e2b86a314a0e7b3ce23ee90271c35661f9b58ec721fc8f8ae2d6d88b768cf70c7e704dce721b +Signature: 69fe1c37cddc2db194719f80d9db24c60618f5e99cda4d645d1be7c3c4ba192c5d8606dc9c2cdc61 +Test: Verify +Message: e524024ea5f5ef7baaf30efbfadbffd9ca00ccd03d91c23a612e8d3c67ab933023239253c4417cb0d5cb934c7370c193d0d23a03e8d75417832da6766c1c605df090eb4a9966c1ea2cf68e45e0e28828e11f0bd305417ae4ce0b5283a0378fcf438243899cfb75ffa88e383cbacc0c6ef5fd7a970c68ea7839e1c8bb7c94d760 +Signature: 41bfc6a00915f9a7e24e0d4a7a1220aa0c0f3127b0286f8333c9b002a4acba9673717ffb09368caa +Test: Verify +PublicElement: 1dd203bc368c505fafbc02d560b4b9f003d93be0f78a11fe60e94c406890ce920be3fab9d9ffe84b80f3fdb9071dc602d7c8165fb62e346847b3918d450b3dcccb4bcff0ab98e3052ae36d1a65caa37c7187bb620c5147870ef676091f5199be871dce4fcda065da9f3568fa70edd637450acaa7e42f128b6a3a0519d86784d4 +Test: PublicKeyValid +Message: 691699d5c945a8508a41c3c83f768406a904e3bcad75c75e76becc40e67857f0435fd8d61f0b5f0b88ee6276718fcd2d60064b0b5ab7d48d0c5377f23b0c69936d174f80d968c95c8ca93f7bde7cef3914f2379e574c202fd5f12c1735af62774136970acfd2fefdf068f20e5cb403e31dc140ad7caac5fd298f84e6aeda5855 +Signature: 9c2687d271c475a3ca252997642f12c2494e6e1612ca7c28dcebefb178a72071de741a27699cbb58 +Test: Verify +Message: ad15c247a6d92417670bb015e2c56b2170d449feaea127d898600517e37d88639f43b0f80ecfd52cbf34e83deff0e860208fa308fb9eaf7463d2a87cdb79ab9c1a221341ed8973544dc5d405c0b530d9f5a72ff69a4b20af81d83b4bf47c151b560a65bbfbdff6a74915ec020fec3ba325746462458072a12ac8351de75dbef7 +Signature: 3edf3214d7492ead518c21641cdeeaf11955cf2c9fd41dd6990a3d93b5b996dc65b4480102910be6 +Test: Verify +Message: fe8aa91c3ff17c55cfeb6ca7d7934f00e1ea15bb63b4fb9d8a94f410486b559ea1eebfb131865289026c0f7e8d058e780e7be2ac0d9dca9929f91942283868ad3cbafa9c9872ef8a3303ade9dc1c8b9b7f11c0afb6ba8b5d9391a444ac07e4e2682730548a6eab50fbe91c60dc909d61cce2853b76c398e25f926e8def8f2136 +Signature: 454f59ad954b584350b19484ee93f3fac35e5a21025acec86b4d2cedb998a838f9c3d801acf7ff52 +Test: Verify +Message: 53bd313ad31f55de5bf21a35c1a6291bca8e6e0b206736489726884da107c1770fd273f10a707fe051af70d0b5521b5fd25d75280f9fb5f2d880aa1a1b0c5e3e0140ec2bee959f09bccb4cc633f7f2c0ccd08fb6a73645f0ca04aeae9c177ccea19f55c277a5eeb212dd66ed34aee5963080758bdf452099e34a4bdf1b405280 +Signature: 7408d817a92cce7b17409ca4a522ee8d2a05bc6ab21cfaa6c48819dde84f86090139f18c389ec906 +Test: Verify +Message: 8d67b965319d7ea31ecc8f7538b0042c8175e4de45b0eb7d869b9e3aaa918d1964cae8d5e05846f63261b131009ef5006f152a824c137f957c6c4a31a6f64d081e444b5c159fcc20004b2c5245f8ea982d862f1906fd9d9f98cd5beaca425e57954bf9b22a6ca8585f00199160b47c2c93410c5ccb69ded3b135ea1d706d573e +Signature: 3c2251163492bf6e777793020a5010959d84a258b28ebc211aeffb54f4f99500f88cf0b2eee180ca +Test: NotVerify +Message: 8fa0b50bd675f973a529cb90f5a7be4302794ed969f31dda80a16e0ef6efe2d1ac177399d350aec5463535a82a7374d6c4b7a3ae9ad7fd28cd3f3fe0b69e6363c0d29eba861297352d5bea7a031cddcd582561a29dcd4c60bc63d678b7d751a683a92d8727132c5c1172e11db8fb6fc2789b80cdaa2e841b03e52ced2ff12632 +Signature: 4d6e667824358fe066bf44377146bf2f5f2d92d2adc0aa673fc3912c3ae67bf8d0c529fb1c25776d +Test: Verify +Message: 17aeab19d1ee54e4aaaa66144a82f1a348dc53f8f1fa9d1b575c44389e580c5883f8315b2d14d83838b1b679009800f12b3a92c179c4638ad07e28f4836a475fe21900e908d0d6a0e0dc44097a339ed18d4c45d24c400f496e22f556789bffb54dca6dbbf95b2794bae667bb508aa4bb86cac22401a779d049ff035715250ad1 +Signature: 570867e6fd129769612e82d31a833ddfbb9a07833815df754b1db1c729e7a85fa4bee867dbcd42ce +Test: Verify +Message: cbdcecd18c9984a189ddd576261b6aebaf3030639731cd79ef7a3faa2af4b9420fa6bb84ff7f701d69624ccb8b73e6496ba1137f157444e81618224339ab687d81c300de67436173556028bd62eff59850f1896dc3611d9cc43c052476d28695174df4383a7f107c43f0a0a4232750af5539c98719900f6ef0fe20a65802cb60 +Signature: bed7f5866b9ec24dc7f0ec818262aa7a2197926c314a353cfdb5d11c7e57685ddc0c1863b7915521 +Test: Verify +Message: e8cac9ce0ef12933d72bb5ec654590ae24739b0b378f75d32293d3acb85902ef4791b9c603032484b0072f45944210c79ca21787cd9dba1feea5dcdf74ef5dabae66e81531eaf9bb86ce2de21390ce5347da9f760abae4ad641eb5f46c9385b6733feef2721cbf8eb27748fbbaa8e40b7d13c80fc55f0c35daf6f82078bd90c9 +Signature: 35dc7ce798a62cf86653c31306ee9dc5a8ffef2a8c086ebe25b001f990e5f511f780ad9d7eeed027 +Test: Verify +Message: 95f01262b79dfb8fc98a0217a661456a8b97042d6dd524499daae53a9a70e096377c44dcee8a528083671634dce0677820eb21640f14a2b4a22b8316e32c98b10f6f2af6e91073aa61a15b34660f722408d22e05d359666567b50e225c8434f655203c46620958279c914bb1fbc65e897ba4a2a96f7c697325a0fff6bb50ae7f +Signature: 9e75e572e76eca4859c954248a01d31921da32e371ecee37eb40aa9c13ca2e65961359e4466e9e72 +Test: Verify +Message: 64414cf10d118df7436add5cbd54ba23e8af55f7f79d44a22b1369ce64ba21fce90cb1c274acee4981062d07d9276ab859debca30814f90b5969a5f3bd1120176ced102775ed0d4604a58cc3f42e0e179540891fbf8d179a1760dde6a1763ef7861d4298288b41e66481d30a2620fd36330b94e333bff649fe2fea1e28a3d493 +Signature: 212c24985e37ee89e71cbe6d6012b89fa181db569227db91fc0b6f557f377e380cc56c271f7cb77f +Test: Verify +Message: 8dcf3f1d21a4d1e15238b6db0e89798e66cc62b60e7d0eee15a550a2e56b47387ddec07aee02cd471418a77a9733c21b22f82ec5e1b4365741a533dfe382b1c3e24cc6314659aecac89eab8ac93c1cfb8d4edc9abcf2de891b95067786844acd32b0091b21c2abc2e65f7be29bbdc1862066230e954c3edd1a0e8044c68a49af +Signature: 7add75db81ef8d210f6dad09da3d11381324430bc473f003495c0288a42fd93957dfa5321bdc3d82 +Test: Verify +Message: 0ee654428677f6fd59e6cdcd1406dae8f753dcbca966a88e1db8ab5abf9bbde6e47528287040f8dac93f865cfd023fca2f9dba5d4725fa07da6b004a57fc955a73595573d773007c096afddd9987309e8c78fdc10dca9de053aca00bcde3c3dc9508f5dc1409a41bf1e04c0a408d429ce85abe9d554f285260f3a4527b46e0a4 +Signature: ccfd740744131a05fbfebb26edf96572d3475d6441c042287c109e0aaa4e9db694d074889cb55dfc +Test: Verify +Message: 1a21fb1ded7d167c9a590c8bfc4abc10ab1aab159476b834d9d91e24ebb8aa84e5ee3ee72c6b87214519fbd2f70f1630a2fad519dec7735857966237e8db8d46f6d6cd6b0f36aa2bc4095337c4e7e03a3a60c6e268a29b2d846f0cf6d33e1cbf04b09fc1cf37f631ce010cd59b2b91c82b2376896b5ea94b193c1278e438ce87 +Signature: a07b8566ada6bbd54b5fc36b4a3b698cbf60c1ee912a5197ba6e98bd4777a884d6bc66022020de8f +Test: Verify +Message: ffc7c4abcca3dae4c21b311e6fb51da2262e53dd491ed515d6cd216d34549a1c40f836ea93c36aec17645380c949258bd0fbd9f2bfb9135727585115615a5a7e9a4ee6541f678a86eb60e72c6e8f14c4a04848af4675cce784732002a42f6c6c25812be108c8132956c74718f6c0c0c5adcff80a7689d93c05d5e62c960aa95e +Signature: 60b09ca0f393d3398635c5075d114429b6cdc8bcc7e66888f49148be9a9f96edc5014b106de6afe6 +Test: Verify +Message: 88fb1d5c4fe552db3d7213c906f74702fc102d41cfe636138ac123fbcbce5fe743319fd36e4eb8bc9355c0c7fe0c69b27de19a7c182f4e5016d0b2b82de57aff08e284e7ffdcb18c1217009826cbeba9843706ff8fe9d66ac64bf073fa7253cad02307f07927f625b1d10994f6cd87bd0b2aac23acab8638934a1485ab0ea11e +Signature: a4e8a3e21168f000ced52e3a35573fb6ba82eaa164813969ad388163d2cb861f472e7cbee985e0e1 +Test: Verify +Message: 4593c65d5e569a3d1369a916c8e6d4f541080dc192e7e51447745056d5b7bc1c404852c00e0d8b406d32f75ca06e4aecaf74a87f4fb7323a0f63d1efc598427c38e963670f15bcb7fa0451151f05a724c747141d49954caf37562916c8c4ba7a866c908a38e7445912d74d781b240055e078e8d457f9492b1646ef03b5b43ccd +Signature: 8c8e17b621fc67bbf36704f2356e7755d960fce3a52357c84b778376dcca9f92c91b9be575daf7b0 +Test: Verify +Message: 6180fb71de61a23cbe0d4383386e0170da515bbd67512b41ef03e0bc2d63fbdf257fc89ffe625fbb1d43da8c84efd80d6974322a1a0ffd4d1158c02753acf7bc0edbc8b2721304dacf0d6100f176f6efb9a0f8c8fd69b385a16cccc9f667b5ea52ed7141f14c8ab10cc1507638db532f012d232fc6384700d7977b39ce6c2f82 +Signature: 4156c005b5e099e4cae1d24a4ef35ae0749e4cdeade8929a74ef00f4f57e18c864ae6a376d8bdb55 +Test: Verify +Message: e52be63c5733b8e9860af61ee50f73e7f679522cd72f31af10ec93469c938e5b35d0b7a1e4f14b18c9039f442831caa9b659908b22ef92e4e617b4a54ffecf32ca7a981872e2d011d72fae3a11538a9306d9cbb7f8bf12de5291a710b3c625ab3b5f621816bea1ca48c4fb78b82f0b9b7e32d92a71560994ec9145ffe1a4e7c0 +Signature: b07e9d17a45cc2ceeb1fde1299ba0d6b3bcbe7dcc50e823d12ae5d86972fc6e21d499d38120d7638 +Test: Verify +Message: 1b223eeb3cebfc1575b37c5eba339ca55ab86c9300a64fcfe94d4f6467f1c06f9714190d5f060f84abb0f3b0e89d4db0c04abad218af03bd480d7fdd9afaab1405ab079e2a82334590d84ac71c0c7f85d4ccf76dd5a3e62992c4ec894f15b22edd7fc0789775a2b29dc33c7d5099697a0ed7db3b2f9b2f6c40084f3e7e590d15 +Signature: 199d5f32d2645a1d46ef1cb3ecb15a34eab59b9a8c3cbf5810966097bb9c280e812c22ac298e156a +Test: Verify +Message: 7296f7fd229c0893a84a5b7ee87a034416e5ae1edf1e7416d6c9df5f20213cf564aa2175ed32403f220e6aca2893e747d5d3f579d8999ed427a7bfd5aa2f55a1258f0be16b5102dcc163e0d790931baa504e87a3b1991ea00b501067089f0b498fbeccf8f4f1e7a55fbfd35d7a7239a55fcf7d55c0178eb2583eebcf936af626 +Signature: 5e2044f956599ab077c91e0f9f9408dfd3c458c61fe6edfab105b1f711919c0b43bbb7557252b193 +Test: Verify +Message: 7279097dcfe09b8615d3275b713dced645da08ef435fe783c5e888676fa3daad07bb933594886f78b6f4ab914530c28d2e9967f48ae5c398ff92f09d5c90b6c9702d850d2b42b355f89cf68d5aad25f4c5742ba5bfaa4c62372e9ca425b3bce164a8d81dcc67deb494a20066e60b6da3c4434b191a06f87c249482950362658e +Signature: c2b345d1c28a149215db60952dac2854103f0260bd4994a0b35394474ab82958d7ceb406f6285f4c +Test: Verify +Message: 7c9b50842db0de693441a2c13323de1369e251c07cd49c41877ff69b672d142642ce53805a0e28cd11b7ca313c491e8facd7e382fa241e9d93ffc8df05dcb67a89b4cac6d01e587f12aedb47558ed958fb5b14898f43f284d15c2f46ff47c1d866050b4c2a1947fa52df2dfc172ce9e86d273ccdd368f070584f82c8eea60bb7 +Signature: 363c61fe40b4c0a4f06908df5c46d8a9c98dee71cd1c56f8d7a16c081712cb1b8c92cfd00464a3e7 +Test: Verify +Message: 0bf43670b5fe01cb48e75a19b519f324451ccbb3d85d8ef15c41311b906aca6efb48ad5027e4cdbd23e951f538f47564ea1da4d133c6d4cbfba32151db0aadc1137db703c975faf58471481ae93f677fb48a2ceffaa5d6579d97ad7c1067dbdb4da98ae01349404c659777e04093804f9b7b9a63a5934e6e3a340df4a7180d96 +Signature: bbefc869907609019f4a85294aa854961e51c4884c235f4cdf85c4c3e0ff34069183ebf0ef50bb9f +Test: Verify +Message: 419ff761987d7257a0bc8817abb4077986972726e6ac93f311cab67ac91747fa7d021871b37f1bf8b082b55e6bbf4709b1a0fa099986cc7d2b44d82b4cd9ea5bec6e43f47490a9da6aafb38767d753e83bada47a5eacf6a59aa11758f665e4e6e7db1121b22a35b5253b19c7767542ce7bb7bcb10c972922b6da0b3aa1334e56 +Signature: 29becc5afb5ea31a71b4169b91f9594d0819de2d409e4c0c3bfe8e2ea53e98dc1ad4a72f3e3081b9 +Test: NotVerify +Message: 31c4c31942471dd6583810807472b62ce7cbbddbac7de47f08d7bb4b6024973f5adcd3f4380a4ea571fd227f9133a22a53829698fc88ba0dfa55746fbe58d6d0d687d43a4fd3c7ba4acb21afdd8f72542df89c8cc90553ee4989d8112713f619dd1e3d82407a7d2c1cfa87a8115f20c1ad84454ecbcca6382bc95dc6532eef31 +Signature: 3c999e56f7ba49e48cb72c76bb7848d4562aa96dbb8c5a3adc19533b00cb2a421fa107b0b956452d +Test: Verify +Message: 64a5d78514c2e26b011e7bca8ae480a2770cb50b03bb6fac29db817c30fb6bb87a68c225898ddb885288bb62c70e43f19f8198646850d15dd08ee5ad30d6d34b595e1395a4593dcb3493f8c98e4825055d454dc87f4249b1537e3067469c869e9cbda24d7cdf602d3f760876fa497fd5498facb15f492d9f4be23c238d05dbaa +Signature: c3a0e8c6df40bb4d672d2438f4f770c141054f1e0b6cd25a0f9d0de138d6c8eb028ae0b23dbd2720 +Test: Verify +Message: c4d9d647a62a699ce00ac9c55b2197a796fd1e8e2120f2d75a50cadf671a9c2c74a8f7db2ec5a549802e81058d1c95f6ee0e78c92ddce79e82f9a3f3cc088ad0d3a2f934bd6661c0ce4327a26402c2c432171036bca8f8da13df464ed36dc31f5a5f942b4a25d55741e07673d8ec556adaae9caec69f5ee387996dca72617e71 +Signature: 1145693d535af4e7b13ed5801c2539db279007dca94800d15c4f2d184c71cf793feab7e46c52121b +Test: Verify +Message: 9981198067ce9d394f53f1233ee06b86075ed7d61142c04f3e54fdcf1ea280f454bf5b76494113c6107a2ae89a76e78e1b356876bc2aeb0582f459257e5b145b368e022d539bdab38d2fae7cd490baa4c1d86b333c74b3b86edd8c25e995cbee1664275ddfd489399eea969746277b00d0c0f8c5e919b09eda88af89b7473ce2 +Signature: 57f2c2fd72f077ef67ceaf46d99753bf796a4712a018b08a786d4c40136256ac0a8618db7dd1eb28 +Test: Verify +Message: bfcbe3e18f4423b9f21b33fadb4763c2e4221126f11b6c79099e6bd9714008000a2fc249edda520144dcacf16c2e3929488e540ee82a03a65c92f723d2dcc6aff61967778bf8eefa46b98a94eb55bc45aaecd9c7bc6fc3d13a8ee4a53de46be03c61cb82a2f8703cae8bc4fa901362b1c2149a6aa440258f5b6a2a76ebae712c +Signature: 5c141ab2f4ee5a513c4ee7e9a5e770f294859b1f6551d44ed78029dbbebe181a73e2726f1b553022 +Test: Verify +Message: 839331e55e6928503c36c0530394dea50f46f78d7bd8fea1ae7894c02a136b4e91b3fbaff91869067196b42fd32e22fbcdf0eaab2b9023af6747ec9f73eddd7bc555ae1fa4e8260ab2844750ba97b8ddbc7773ec3705afc6b68310c09eb20d6f362fa22ef71038d316bad1ae500678c2f594e847386e7c60b6e157194499d4a4 +Signature: 0ad3d7f5ea209ad35ba4a0a17e16483c50f5e4953a692ea71730d7c5c4c13feed38ed90759aa2e86 +Test: Verify +Message: d4fdc830db8cef7540b6b3ab242cfe3bb59004a3f3c61b60a37cda1890fc7108093249ae98f9dcb7ffaad62b79e76dd72fa4fdfbf878e8355523aeadac5f4882c5ecc97583d638d5e309a8aa3a189925ab4a9348e7e601d129c14b6d7005381bff4383dd13bcbba6e4ec6081df583bfe229afee237aa1d0e156eecb05485f9a9 +Signature: 189c08e378bc9feb81891706f80a9fcd1f10725564e3814342937391e39f8830eaed6702b8579e3d +Test: NotVerify +Message: 3fb043ac04c26a1d06fa3f3638e0ab0a218b5a74c36243f4ce1278c606d02b44f1d1027ec6069c17931c6463adb495be5de08e2fc8de583e1f187513085bebd04d579130c4589a607e445f1e33d57110ee17df67f524c4b4fb1f150a896fa955aa3d8afbd6307bb12168c99fa4b957b72c29e45222aca00dba1eefe460827d8c +Signature: 65ab093718776e0b945e5fa24014468ee40422b3688c00beb21593dd4785c90b350e9471a5dff538 +Test: Verify +Message: 155f0682c1d481571fd2d93a6bd70e5e2a6fee3702270f03d7b40d9c2c65057eb8c6521448968747d5ebac49e5a4be9f270f616d49dce8061d4287b4ed6fd7c41c368bd6fef47163f9c3ac8fdce330317f657e209c19a2c1eeba6ace8858e86877072a609cc638c2c3b24fa3086c5d2d6cc7bde8b3b6344b80762c83b4f73082 +Signature: 90e0b86567a2b176a74a817d52009c2bb553eb9ac3694f997c5f70ca3936b6d57f1908868ffc7518 +Test: Verify +Message: 4b03e4a77dd910d51e6c170faa228f3d5c258c96bc44cc986a0d244629292ca62ff8277aab6d353e982bbc62c1e113c815e371812d0916c41ccdb83076a03043a38c651b6511796ba83933c18afdadf6abdc3ef6b6baaab230f6896280d0f50040f97801c37c3456e7cd54a31c2eb3bfb54bcc6c6e0de2583fc270536071d3d3 +Signature: 999adeab789df72dab3c86e115140d0dbb4905adbebe59a1995fbc73fc678a8ca89d7b6cb644569f +Test: Verify +Message: a59d6636f5dc1fbe82ec2df71a90657f5ccbbcf1af6e69157de03b45b42e3c227f53877942c96770d450b1f500fd64683e877e87aece219a56ace7e19d01823b07f9981733a1dea012aa7324697c7fc68a7e0c654fa524cb573b2c1a84f18074b52850eac17cbba7b4932a5e4d24eef1b84b1d62880ba9fff824c2ca63186f26 +Signature: 30f81281e18c995d53f02e6d04eb988bb0b8bd3f1af1a7c8447c704f06d7379dae2ccf95ec13edd9 +Test: NotVerify diff --git a/src-cryptopp/TestVectors/dsa_1363.txt b/src-cryptopp/TestVectors/dsa_1363.txt new file mode 100644 index 0000000..712e5ea --- /dev/null +++ b/src-cryptopp/TestVectors/dsa_1363.txt @@ -0,0 +1,553 @@ +AlgorithmType: Signature +Name: DSA-1363/EMSA1(SHA-1) +Source: generated by Wei Dai using Crypto++ 5.0 +KeyFormat: DER +Comment: 1024-bit DSA key +PrivateKey: \ + 3082014c0201003082012c06072a8648ce3804013082011f02818100bd670f79\ + b0cde98a84fd97e54d5d5c81525a016d222a3986dd7af3f32cde8a9f6564e43a\ + 559a0c9f8bad36cc25330548b347ac158a345631fa90f7b873c36effae2f7823\ + 227a3f580b5dd18304d5932751e743e922eebfbb4289c389d9019c36f96c6b81\ + fffbf20be062182104e3c4b7d02b872d9a21e0fb5f10ded64420951b021509b2\ + 940496d6d9a43bb7ec642c57b302e59b3a515502818100a1c379ba91fe1f9d52\ + 83807b809c698bce4aee6f405f4de8c46becf33c08a63bc5f8088f75b5b6bcfb\ + 0847ccbdee700e4e698652317bbd7a3056404c541136d7332c2b835ef0d1508e\ + f57b437de60675f20f75df0483f242ddeb57efacd180418790f4dec0a8250593\ + ba36f17316580d50db1383ea93a21247650a2e04af904d041702150355dc8843\ + 45c08fb399b23b161831e94dbe61571e +PublicKey: \ + 308201b73082012c06072a8648ce3804013082011f02818100bd670f79b0cde9\ + 8a84fd97e54d5d5c81525a016d222a3986dd7af3f32cde8a9f6564e43a559a0c\ + 9f8bad36cc25330548b347ac158a345631fa90f7b873c36effae2f7823227a3f\ + 580b5dd18304d5932751e743e922eebfbb4289c389d9019c36f96c6b81fffbf2\ + 0be062182104e3c4b7d02b872d9a21e0fb5f10ded64420951b021509b2940496\ + d6d9a43bb7ec642c57b302e59b3a515502818100a1c379ba91fe1f9d5283807b\ + 809c698bce4aee6f405f4de8c46becf33c08a63bc5f8088f75b5b6bcfb0847cc\ + bdee700e4e698652317bbd7a3056404c541136d7332c2b835ef0d1508ef57b43\ + 7de60675f20f75df0483f242ddeb57efacd180418790f4dec0a8250593ba36f1\ + 7316580d50db1383ea93a21247650a2e04af904d03818400028180255cf6b0a3\ + 3f80cab614eafd5f7b2a6d83b3eafe27cd97b77ae70c7b966707d823f0e6aaaa\ + 41dc005aaefd3a0c269e60a665d2642f5d631ff1a3b8701bc06be9c44ab7367f\ + 77fefeec4c5959cd07e50d74a05af60b059ad3fc75249ecf44774b88b46860d9\ + c3fa35d033bcfc7b0b2d48dc180d192d4918cddff4f7ebcdaaa198 +Test: KeyPairValidAndConsistent +Message: 66B92E1E2C44B80F7BFA +Signature: 06418D4F24A8059553951CA062BBD6E0833ED1745608E1158CA4B8F8FE1CD2AF087B5EEE08FCA0D7A63C +Test: Verify +Message: 973266BB0A492248082A +Signature: 02BA236FE800EECABB85698A76B5485865454B3016010755F0E1BF7CE26FB62BE4FD01141F5CA4144811 +Test: Verify +Message: 9A6D079ED0CA9D8B40E8 +Signature: 045BA3DB16E6B910DC89A2D26096625F757D62077D049886B85EBC7500884B4DDD1898BC52746C54F68D +Test: Verify +Message: AA34DCE67BCDAC927DA6 +Signature: 0835C94121313842ABF04D4960E711D1F0904612BC09840989EEAFF2071522B75957DEAC801574BD22EB +Test: Verify +Message: 4EDAC08816AFDBF284DA +Signature: 08E1574E5299C910694D17075136F41EBD558D1B1805CAA3B6E98DCCC3702F286E76BBD29435CA2CEA5C +Test: Verify +Message: D82F2E903230962B8174 +Signature: 0366F1AE94FD2CDEBA4EE879BB8923F0E49CFB921008E6A5C7457E88811D46DC7F297D6A96E909268244 +Test: Verify +Comment: 1025-bit DSA key +PrivateKey: \ + 3082014c0201003082012c06072a8648ce3804013082011f028181017310bf02\ + d70ef2cee45d1cc47ec8ce8cabdd6bf32a560975a42ef057bf9dfd553bc9368d\ + db154a55d855edaa755e69f511a4c69ba78571cc4b14ddbb0f32a4a9c56c2863\ + 05aa21ec4e35de7390747477b3bd574e7b87cbebde2f665703137a1172350ad2\ + f48a0884d076ada9db82f104e6b0ad86693cd4adbd0067639102fcf102150b39\ + 49dadf3196f08bca0606f06443afce2fb1d02f028181015f0f6d1729ef2af723\ + c00e36450a04c7e7681d65b74a6417a53b3eb6036989eff8e0ab11a7ec3ce234\ + 0b7c7a92e1a977aee52555c06c12c4cc28496ddc2598feeb7539ce90d3888e21\ + f61d7f14746cf67d9fed373afd97e2483700e300ed9da25e7200b363a4727ad2\ + 01194b36ea5f816cf83488c3e527d3a5515870d2da63d6041702150696b0f255\ + 468b7ac18e11632f208ca86383a46724 +PublicKey: \ + 308201b73082012c06072a8648ce3804013082011f028181017310bf02d70ef2\ + cee45d1cc47ec8ce8cabdd6bf32a560975a42ef057bf9dfd553bc9368ddb154a\ + 55d855edaa755e69f511a4c69ba78571cc4b14ddbb0f32a4a9c56c286305aa21\ + ec4e35de7390747477b3bd574e7b87cbebde2f665703137a1172350ad2f48a08\ + 84d076ada9db82f104e6b0ad86693cd4adbd0067639102fcf102150b3949dadf\ + 3196f08bca0606f06443afce2fb1d02f028181015f0f6d1729ef2af723c00e36\ + 450a04c7e7681d65b74a6417a53b3eb6036989eff8e0ab11a7ec3ce2340b7c7a\ + 92e1a977aee52555c06c12c4cc28496ddc2598feeb7539ce90d3888e21f61d7f\ + 14746cf67d9fed373afd97e2483700e300ed9da25e7200b363a4727ad201194b\ + 36ea5f816cf83488c3e527d3a5515870d2da63d60381840002818045bf83e62f\ + 50190374b23de5e4a1d0278e9e8e6c8335577d62e80662a380c206e326819c50\ + 82d321dfda1f905fa5a3ead9a2dc769885a27b1fd6a133185dc5a7876a76ab0a\ + 09fe02b7071a924169e4d2d2a67e67ed3628800134183b962c0b313463aa154e\ + 6437d644e025ab234e63d19c129842a61c5e5ea5a06466c858c81c +Test: KeyPairValidAndConsistent +Message: 2F585D0CE4FA1CD93880 +Signature: 0643ABF8D3C2F4BAB02CF79D698948A1A416BEC05D00F33CC3D41CA9117E6CD99E5DCBBD4425DA12E98E +Test: Verify +Message: 4F09A1F217B8393199EE +Signature: 052DE620B5628EECCF7C56410CAC2B72A5AD1B5A67072ABF369453BC28A386ACD5939C9985C09338FD03 +Test: Verify +Message: 03D7110A753B008A76A0 +Signature: 01D44D16B5FDFB8C39AACEA72391A889EECBFFB5E701EB8F46E4FAB96326F73E0CC698E1F66C32FE5C2E +Test: Verify +Message: 129F4781D417671F886D +Signature: 00CE142CE967BA951B9DE26DEFB5B341CB49247C1308515315449B5533ED469B6470C4E3A3751E35E7BB +Test: Verify +Message: 3E1594F559D1248D1112 +Signature: 07B192657E256B60567BF6EB399D8A2DE8FFF7AE8A031A655BEC911A82049155CDB4F2A76A8004AE646D +Test: Verify +Message: D6F0354F1B6B253B6997 +Signature: 07FE18E0C00F6AC3CBCB95874AB66A98E34DF74F37059178C920C5D13CE173B8D2832310B9587940F6D9 +Test: Verify +Comment: 1026-bit DSA key +PrivateKey: \ + 3082014c0201003082012c06072a8648ce3804013082011f0281810250988282\ + 17d00108030801e5f135fc6fd3010be39e49060a96addc8a081198803402c4b4\ + 6e4ce0750fcbab8cf084c7ca8cae09f1b5482d336fa3af47b96791d02d8143e2\ + 74b1325f2213e17f9384c805f479e52a3117cf84869d395f1bc025c918484478\ + d2da1880d32bc519f4e6b2fd2d46958795550ce1765f725626f3fc17021536bb\ + 68cd95dab195f14c4534283e7ea50b00cc31a302818100e2782ad6992f4b7e88\ + 787b4d616744b60e095575a177569c4a069e311e38b7240c43343367e23574c3\ + 0e4d9f05afe1fbe61423bab715915c4ccf28aa0ed2f52b092b86c8ec1f9d4795\ + d6e91c88ba41297625c11a9e1f4f182da13cf51e541038a1266bf32b2dd81ecd\ + 84bb80be8fdf97689942e944b7fbb6981e00cd680ee25f041702152db270c284\ + 328353f979cad99f4133c53acaa6ee71 +PublicKey: \ + 308201b83082012c06072a8648ce3804013082011f028181025098828217d001\ + 08030801e5f135fc6fd3010be39e49060a96addc8a081198803402c4b46e4ce0\ + 750fcbab8cf084c7ca8cae09f1b5482d336fa3af47b96791d02d8143e274b132\ + 5f2213e17f9384c805f479e52a3117cf84869d395f1bc025c918484478d2da18\ + 80d32bc519f4e6b2fd2d46958795550ce1765f725626f3fc17021536bb68cd95\ + dab195f14c4534283e7ea50b00cc31a302818100e2782ad6992f4b7e88787b4d\ + 616744b60e095575a177569c4a069e311e38b7240c43343367e23574c30e4d9f\ + 05afe1fbe61423bab715915c4ccf28aa0ed2f52b092b86c8ec1f9d4795d6e91c\ + 88ba41297625c11a9e1f4f182da13cf51e541038a1266bf32b2dd81ecd84bb80\ + be8fdf97689942e944b7fbb6981e00cd680ee25f038185000281810179b283f6\ + 7868aeded3a0c5633d0e6c18fad77174e2c89c03452593d05e77a9fb029c0ccb\ + 2b6f2328e79c286ee392713f12d9d45578348383b81d11b0e0f7e89965a7785d\ + 5ab64ea25bb73e8acaa8e84cb9897985015757a48c0b1dac3a6a606fe671ea07\ + 3ec434a46f227b8d4b02a46fbba2f6c6216736d669f55778d81004d8 +Test: KeyPairValidAndConsistent +Message: 7E4F2ED4E79062778A2D +Signature: 03DF91D560884BAA90258F0F78A7AB61F9A4A5CF3D363E8DE2EAAB389B9492C2B80C44509BF2372BDEE0 +Test: Verify +Message: A0E35846B5CF1B5BF560 +Signature: 21DF9C60877B6D7F531AAF1C39122779436029685109B2D736A45F51A80099041AA5F118D7D6025AD30E +Test: Verify +Message: 3B138785EFC6F520EAE0 +Signature: 10A38520BAC07202DD1CB5A9C88B15B9579B9A1344025E4C4B9D1BC3AAA8C97AA90121D52E42E59A0A99 +Test: Verify +Message: 0F6BE2AA764B485145D4 +Signature: 0233267173F284737B68D15A500D23F3C86988E3DB28DD55AE3DFEAAA7251D354CB44315D6024CBE3E36 +Test: Verify +Message: 6CD9FBD23EA58826FB04 +Signature: 15A1B0DDA6BDB62D96AC557E3F1F24DCAD0C51EF3523B01EA2A8FD93761D0E4D070BA6352A81F31B776A +Test: Verify +Message: 473A82649565109E9E89 +Signature: 1FE31C3A3EF6F57DE2586A5F2EBD48A5C707092D230E1D217EE0A752EFD9ACA8BF0B9EE9424184B8F8F2 +Test: Verify +Comment: 1027-bit DSA key +PrivateKey: \ + 3082014c0201003082012c06072a8648ce3804013082011f028181055402a8ab\ + e9cda3072ca8601d68032651feb0335856e57f8f8d4ec949098a6459151cefee\ + f91b7aa733668c8cf0e9b96c93c61f3528d4036daa6565646f65d74c4552817d\ + f7e5fb1cc421cfd885e27bb811ad227e81b3fa02f7a00bf01ee6e23fb5572a75\ + f8f29b58bd5f7db435e8a92a923f15d50f34213d29816921bf195b2d0215291d\ + 0ba731a4303070504d8b9615640a5e1345e00f028181051c9d0270b69ceef82a\ + f5aed5f91dc88d585096609d835d03d39cf3ce74f5a3402d4e8e192455493da6\ + 1cc58ee6f54dd941172be3d7642169cbc52273f4b725f1d6c820c3333336c64d\ + 32fb6238121b3ccb7c71b847764946bb0887a44ca9de802cda62efa9dda57375\ + 1084225353f11ed837f3dc25de8374b6fdbfb6e313e46d0417021513b27094d9\ + a5a3a9704cebdbe890da325fa26ad555 +PublicKey: \ + 308201b83082012c06072a8648ce3804013082011f028181055402a8abe9cda3\ + 072ca8601d68032651feb0335856e57f8f8d4ec949098a6459151cefeef91b7a\ + a733668c8cf0e9b96c93c61f3528d4036daa6565646f65d74c4552817df7e5fb\ + 1cc421cfd885e27bb811ad227e81b3fa02f7a00bf01ee6e23fb5572a75f8f29b\ + 58bd5f7db435e8a92a923f15d50f34213d29816921bf195b2d0215291d0ba731\ + a4303070504d8b9615640a5e1345e00f028181051c9d0270b69ceef82af5aed5\ + f91dc88d585096609d835d03d39cf3ce74f5a3402d4e8e192455493da61cc58e\ + e6f54dd941172be3d7642169cbc52273f4b725f1d6c820c3333336c64d32fb62\ + 38121b3ccb7c71b847764946bb0887a44ca9de802cda62efa9dda57375108422\ + 5353f11ed837f3dc25de8374b6fdbfb6e313e46d0381850002818103b06b9909\ + 7cd7145c7d7782b02e247a4741f3c7f39233627f17e13ebff89a18cad6a454c3\ + f32f7ef2910384030da71ae47e1c3fa79c2141dad107f8e715e47fb0bb626baa\ + fc35db769852ebbec2d339c3c3d5f2287cfdd20b3b78ea4607086c42558ae463\ + 7eddd6a74bc1072d0f34d9c0130cbc9e84f537e7ce50df502d17b5c3 +Test: KeyPairValidAndConsistent +Message: AE6DCD9535AEEE3ECC89 +Signature: 1BB090DC4573AA79F34181020C4D5B582BBA67062C23E5DD6913CE91482A05716784BA680F7F4AC1684B +Test: Verify +Message: C83A14EAC016D659F9FE +Signature: 182AC27BC4B77B145BF90E73A2CEEC5325941507F925279DF5B6280664CE82248348C3EDC59DCD428B64 +Test: Verify +Message: 745E02041EB487D16CE6 +Signature: 13C4F9AC03EA094CF7F60B96CAAA29053706E93DEC1024EAA1606E13B2C3062F2D6082846D29E6E60829 +Test: Verify +Message: 62F019655A83501FC4E7 +Signature: 077E19089B0BB32A7B21B0D27218C6E1F14AD432181BB76FF5E7EC35EC01CA47595F4C7ABB8ABD6064A9 +Test: Verify +Message: 351D37A4B5046E885EAA +Signature: 21962B09FF030A41251AD592F8D2AF24144B3AC713245AF18BE28F192FD29326D91F12A76A01477C8788 +Test: Verify +Message: 4073D33915F595F4FF9D +Signature: 1F4CF158E806AFE59139E2A9840BCEF79237800C521E49B7DBDF9830C86E7653FC716B43224EA00C883F +Test: Verify +Comment: 1028-bit DSA key +PrivateKey: \ + 3082014c0201003082012c06072a8648ce3804013082011f0281810abdeff64b\ + 6f28256e4562109bffed29cb5aa95d89cc0ec95da0e773dbff3467c271bbb1e1\ + fbb6af058517fdacdf26b5919674c625eced6317d8631c063f43b3ade2cd633d\ + 554913339071d6ebed5fd665fc5dd7d47b80721a976c3b14fbd253f0f988c354\ + 725289f2897df0a15985c92b2d4da8d087870c251c72d979b8304d5102152368\ + e2b864b250ad45406391e7eeaa3d27cd053c2b02818107c325695dfe315a77ad\ + 7b42f0d18f9d4821b5c153fee7385877602fa54477bb8c0639d2438f34352b97\ + c22d02a7295d2b53d5286a01caa919d6283614690624240af922675ccd4a0534\ + ec336cb79cde31b02b5988cc5a53ca17790d67d803a27bb927b9c59bdc6ac794\ + 175e285cafdece6778ab19a0b444747fee20d5bf929e70041702150771305163\ + 506b2b83bd5279935df1b5fcf180b004 +PublicKey: \ + 308201b83082012c06072a8648ce3804013082011f0281810abdeff64b6f2825\ + 6e4562109bffed29cb5aa95d89cc0ec95da0e773dbff3467c271bbb1e1fbb6af\ + 058517fdacdf26b5919674c625eced6317d8631c063f43b3ade2cd633d554913\ + 339071d6ebed5fd665fc5dd7d47b80721a976c3b14fbd253f0f988c354725289\ + f2897df0a15985c92b2d4da8d087870c251c72d979b8304d5102152368e2b864\ + b250ad45406391e7eeaa3d27cd053c2b02818107c325695dfe315a77ad7b42f0\ + d18f9d4821b5c153fee7385877602fa54477bb8c0639d2438f34352b97c22d02\ + a7295d2b53d5286a01caa919d6283614690624240af922675ccd4a0534ec336c\ + b79cde31b02b5988cc5a53ca17790d67d803a27bb927b9c59bdc6ac794175e28\ + 5cafdece6778ab19a0b444747fee20d5bf929e7003818500028181043e4ae624\ + 4408879264fe6b859b578218705b9a45af22efded27141b7f090cbcbe42dcf48\ + 1df3e41b13920ae02b694eaa6bfd62f2d3c5d677b8c4ce783cbe2789e088b044\ + 89ef535ad4a517351c8835cf128f7ec677a1b1dbe3ae9cc4198ddb6e1cef8e97\ + 8c0725f5063797bc43eb9ae496286cccbad5d4e026e9edb997d2f918 +Test: KeyPairValidAndConsistent +Message: 4867852C83F181CDD010 +Signature: 1D0F4F49AFA0448163604847C9308A824ECE928E05066D47892256DB725FCB31F93F38B9E02C71E100EE +Test: Verify +Message: DA6493C86D6B62C5961C +Signature: 1BB4A8A1B8D81EEE9AB291C49F688F27D2191EA51B15A5DA66A6367D931DAB338E595C80E70CEE4BB644 +Test: Verify +Message: AE2C1136BFE966794A6C +Signature: 02AFAB91234D08FCEC22E57AB5718FBF41A86D2469012F8476BFCF4EA4E03D9F7A6E467ABDD0B5626784 +Test: Verify +Message: B20160E0442E726BE749 +Signature: 140A45F4933F05807A533628962E42A8BEFAF5977917F2A8D8706B8BE83EE6B6CEBCC951553B4E3203B5 +Test: Verify +Message: 3638935C4492F5CA42F2 +Signature: 234F78EF68343E77710E17285E47994AB599F3646315C37B8CC01CF6BE9C803D6B81B232DE9171DA7967 +Test: Verify +Message: DFB674CA6E0FDC0CBE99 +Signature: 1DF9B1B9F78F5FCCCCC5F698EDDBC8EB28C0F4D10002A052284AA4FBA601D3047E3AA97F8CF73731A44B +Test: Verify +Comment: 1029-bit DSA key +PrivateKey: \ + 3082014c0201003082012c06072a8648ce3804013082011f0281811d0f176b67\ + 99b36724c92954c38d0288fa95400c2b14e064f76a6338fccaebca8d978b93bb\ + 76507bc150a50f9fe799fffe12ae2875b13ac1084ffcfde9f62b86185a72f04f\ + f80538d6eac177edc98d61a517b1275bcf4b57aa262e1702d623bc344db7e562\ + 1c949a9b12e9936e88fae9b200a1f8ad5b40ec8220aa301267f38dd702153357\ + 536531dec150be0ef8747f69ea30d987ff7df1028181067dd80dbc6b41f58d08\ + f077a9a3dcbfe12a62065fe6b4691c457f506b56dcab0433b3aad6ef96250163\ + 3d0f3947b491a1317e7e6b632f062c53104d609c9222b056f08a0c83662a7074\ + 4331fd09b2b42fb0768e52da27e92732106fbd41ec737373fd080b56b543d808\ + d49eeb6e1bb0a8619b1edee8fb8295dc042423f684af8a041702152dcdc00a86\ + ecc2a60ebfa6660a83af1d7c3e570b85 +PublicKey: \ + 308201b83082012c06072a8648ce3804013082011f0281811d0f176b6799b367\ + 24c92954c38d0288fa95400c2b14e064f76a6338fccaebca8d978b93bb76507b\ + c150a50f9fe799fffe12ae2875b13ac1084ffcfde9f62b86185a72f04ff80538\ + d6eac177edc98d61a517b1275bcf4b57aa262e1702d623bc344db7e5621c949a\ + 9b12e9936e88fae9b200a1f8ad5b40ec8220aa301267f38dd702153357536531\ + dec150be0ef8747f69ea30d987ff7df1028181067dd80dbc6b41f58d08f077a9\ + a3dcbfe12a62065fe6b4691c457f506b56dcab0433b3aad6ef962501633d0f39\ + 47b491a1317e7e6b632f062c53104d609c9222b056f08a0c83662a70744331fd\ + 09b2b42fb0768e52da27e92732106fbd41ec737373fd080b56b543d808d49eeb\ + 6e1bb0a8619b1edee8fb8295dc042423f684af8a0381850002818113834f0fa1\ + f42abf7dbd264cb7d2eb5798da8972df67f517c62d7ae5070fd588d61db62e49\ + 2f9654833e876ed5737df35069f5ee01a45de881d8f5e68ec52ad9ef32780e8c\ + 453a5f1e38cc17bc5cd061a3c122080f6e1b82d31877e8b08f634f497bd90b06\ + 824eaa0416c64104ce5622c272673d0dedb836ac7d47e0cea0673902 +Test: KeyPairValidAndConsistent +Message: 1E34034C47FE533F8FF5 +Signature: 04E171B845E602A871CD5DACA5738BC4585A452A86108D03D70C3D2D605FAE90DB8D339AADB692EB1ABE +Test: Verify +Message: 53D2CA23AF7DF95634F0 +Signature: 1327D4C32DFB874EA2104A9B30EAF288C7016146D1217C237E0201482E483EBC7F0A713748547F9B6B21 +Test: Verify +Message: 0F056E08AE77B3B30F33 +Signature: 1B4A688745F3D86B0D8A5D97FFA0E31C322EFAAD0A0FCD907B2D49EB8150539E81FF29341EC34440425C +Test: Verify +Message: F08C80E8FD38A3867B76 +Signature: 0972705B5E84A8BA57226C770CCB0ECDEBC816EA162FCB3BA5B3C235105EA75F379EE84187E27A86D21D +Test: Verify +Message: 6D392690B92B3E75020F +Signature: 185968475C67C936CB152F76E80EE22FB82A27ED120C5C0ADB2D750D2C38F0A9671EBFEC2815F675C24C +Test: Verify +Message: 10AE0E091A267641FACF +Signature: 1AC3C2010BFB10CA6889120A23F984FE0D4CF79D1B07578217E5A3C68EDF05006C1F3F1BFB3848E4ECE5 +Test: Verify +Comment: 1030-bit DSA key +PrivateKey: \ + 3082014c0201003082012c06072a8648ce3804013082011f0281812a32d68d31\ + 248024053bf628a94404b9a49d91ade4d7a45b071e93292a7f8c2661d9165f0a\ + b85491d4b0dc67d335fa7d7dd172cb17193390a55eb000aa97e2b8ed3ee64b73\ + aa43ea9b8979132c2d966ab03c42cc14782c96e4284ee1136b8515007ed1b1a5\ + 708b5e8d81304fa651edc715918e2299cfe9016dfec5f454d907f59f021527c7\ + 996c1d3729c4cf1de06529e5619771e27ad9eb0281810d87a4b01385da7f43b6\ + 277933c5f0dc8072dcacd5252e1b29f588114a7ac56e377050aa8174b5dda400\ + f043234e4a746442792734dc80274a00a3676101be94759fc2630b9a85896648\ + 8b12611d03d0b31e7243e124497a754544cee1db10bb0a81cf0b2a68045b76fe\ + 935f641c666fdc788a2b968c6668c669115756b961d9fe04170215091155581e\ + cb7a0a792ba95c772d9382298bfdfa6f +PublicKey: \ + 308201b83082012c06072a8648ce3804013082011f0281812a32d68d31248024\ + 053bf628a94404b9a49d91ade4d7a45b071e93292a7f8c2661d9165f0ab85491\ + d4b0dc67d335fa7d7dd172cb17193390a55eb000aa97e2b8ed3ee64b73aa43ea\ + 9b8979132c2d966ab03c42cc14782c96e4284ee1136b8515007ed1b1a5708b5e\ + 8d81304fa651edc715918e2299cfe9016dfec5f454d907f59f021527c7996c1d\ + 3729c4cf1de06529e5619771e27ad9eb0281810d87a4b01385da7f43b6277933\ + c5f0dc8072dcacd5252e1b29f588114a7ac56e377050aa8174b5dda400f04323\ + 4e4a746442792734dc80274a00a3676101be94759fc2630b9a858966488b1261\ + 1d03d0b31e7243e124497a754544cee1db10bb0a81cf0b2a68045b76fe935f64\ + 1c666fdc788a2b968c6668c669115756b961d9fe038185000281810d7d22c931\ + 422fc46505887559a51490c2e367cdb40242cdbaeb23024693fd5c68f6a3307c\ + a34b224457d5aa610b90eca3b39905481daaba7151318f09f974ad664546d14c\ + 87f797e38139ee1e07adba9c775e07b7f7b3edba87d886920d6b2cef5f084359\ + 566b0a3b8b940a65b9ad93fd7ccd1354cdcee3c43c6bd315180498ad +Test: KeyPairValidAndConsistent +Message: 23EEE1D0EA8950B8F322 +Signature: 1800356929B316D1E4FA886CAE0CAD56E32506522D0B8440BB7695D522F31CD87079BEA4CA9F18ED4288 +Test: Verify +Message: 13FA6F2816FB83190A21 +Signature: 207830C2DE87296BC39CD21630F26228F00CF60BC3150CBC82CFA9006534A6C5E354AA281C434A8C2077 +Test: Verify +Message: D071CCC0C6E4CAE82E5A +Signature: 054C9C0C30C6B73AAB9E54C11D4EFC82BD6E8680932501D78A58EE305930E72ACD3BB2565023455DEAEA +Test: Verify +Message: 22CE83F4803BF3EA2C48 +Signature: 07065A6F5C9A086CB83F2F113895730C1B2FE0DCD90FD6AA887B066D685D3DD6C3C0D95CB8C8A48FBFF1 +Test: Verify +Message: 7A927EC7BB9CA16C1B0A +Signature: 24BF344DC7B25F831428078AC0D929A72A29160B6205A1BD4B1B2C5BD8BEFCB650DE23652701DDD4F4EF +Test: Verify +Message: 9591B069993E10BC0B84 +Signature: 0E6E6BF91BBC9FB91FCD3CE32907F5B6AB5E88928C1E3BC92649EDFDFE672AFB654C765F2758DE4BD78F +Test: Verify +Comment: 1031-bit DSA key +PrivateKey: \ + 3082014c0201003082012c06072a8648ce3804013082011f0281814d58515f7b\ + 41c4fc87e4fcefe5cf6d84b2d74a9d6f498ae9605fcbf1c59217422001a272ef\ + 91dbd09e7af5ee54126dd4fc44bb1ed624d0dd5dafb984d52781140bba40600c\ + bd4752d2c32b43253efee57af6964c339570edb24195502e6d424b84bed65ac9\ + 8c6fc52ec90e40a525f1863a53f2fbe2a0a133342eff4337f26ceb93021526f8\ + 6a81a6bb530c2f9b63e3690e95a0894575f4450281811e24828adb4ebf2becdb\ + dcadf6706631293ad6566803d12479f04a7bb20b6086fe81df164f8bd02c5f41\ + 8c1140d143f11a71170b42d0753c952bfff951b9ca4204868375efaa4afad50b\ + 75787e41c5ab9ce8adcbccecd3716f350bb8aaeca9b6098bd0002d789e1f7db9\ + c19d9045499877b93ecb4e7c64808b742063bbecf60e29041702150e61a054ee\ + 6510734a80f67a54d8c4151c957ef16f +PublicKey: \ + 308201b83082012c06072a8648ce3804013082011f0281814d58515f7b41c4fc\ + 87e4fcefe5cf6d84b2d74a9d6f498ae9605fcbf1c59217422001a272ef91dbd0\ + 9e7af5ee54126dd4fc44bb1ed624d0dd5dafb984d52781140bba40600cbd4752\ + d2c32b43253efee57af6964c339570edb24195502e6d424b84bed65ac98c6fc5\ + 2ec90e40a525f1863a53f2fbe2a0a133342eff4337f26ceb93021526f86a81a6\ + bb530c2f9b63e3690e95a0894575f4450281811e24828adb4ebf2becdbdcadf6\ + 706631293ad6566803d12479f04a7bb20b6086fe81df164f8bd02c5f418c1140\ + d143f11a71170b42d0753c952bfff951b9ca4204868375efaa4afad50b75787e\ + 41c5ab9ce8adcbccecd3716f350bb8aaeca9b6098bd0002d789e1f7db9c19d90\ + 45499877b93ecb4e7c64808b742063bbecf60e290381850002818119b50f1eea\ + 45bfaa22352a38f3c3b86d6f670747ac2fd94359608e25f2bb9f602506bc3572\ + 45deeb4c3c702d435c557da4f4a9fd37330a75547c91681fdbb51f286adb498d\ + 1e489e89b2e6a4eb9ff30222c51fefbeac7435f629f536ac2d6b87664d80e5c9\ + 7398cf489a1d1ca217f7f21ea8e409f938378875cf5f528162e3bc07 +Test: KeyPairValidAndConsistent +Message: B4B3C8FBE82013228A21 +Signature: 0E08FE696A4C70B16A127CAE8C61E5B38B7A1F34402584D1F21F71016054E820E3B1BB866309D93A7DA5 +Test: Verify +Message: 17D2D18302173E2CE992 +Signature: 0203C3869E15F8847B58BD158CB746433AA05F201317C0541908ACD5EA78A02D1FAB79380619199CC5B8 +Test: Verify +Message: 8032AE177D6DF38C7E27 +Signature: 1F436F5BC73A3402221B539F1D7CCBD4C3AE948418216122809E062ACF5D6086546FCBB293B4C7510CBD +Test: Verify +Message: 768640A60A3C62E02428 +Signature: 0A5D52C534A9BF1175247538638077489537025975254955F8A96B0CA2E7985D5D6E3DD54EE298C90100 +Test: Verify +Message: B0999CA45B77ED63639D +Signature: 144DDD0C1BE6D96FC3AFFA240FCD6D2AD0748C848F0C8A25AE8AC2E55A38DE9DBBAFF90CF464547365E2 +Test: Verify +Message: 587EDB968FA82C12C930 +Signature: 01FC4F6F98898F3639E8D93E7C2E6F3945120AD19D15EA13EDC96BED7E73A7D5D161217F1C67F3048BE3 +Test: Verify +Comment: 1032-bit DSA key +PrivateKey: \ + 3082014e0201003082012e06072a8648ce3804013082012102818200d551680a\ + 62ebf98f0ed8930cc5b12de86d0a0c29a0d7e5524c24672a25428833f4c19ac8\ + 83ead22efcc0c6823f2e942c17adb7ab763ff2c7cc2698fa8b6448e514d4628b\ + 197721bdaec780e126ac80ac83f24fef5c154f7690ceba903748be5212e3180e\ + a718ca7a71a49dee939bf9bc5b7845c9648d074587ccd3724493b91f0902152e\ + 802b5369c3f1ddfa789bf8f2ad2e048ced3bf35502818200a9aebee7d29f90b0\ + 81afc4d496a6a78210e918bb57a8a21c5995586c0bf20f7a56bb10a97e05a3a7\ + 23e7db64612b12bb591b1fe7d2e46be8c96a7b2ce7c66076aeded938775ae222\ + 3900adaf52a93f52d62173c82d4b67388c85d4c1127e1edf4643cf09f5375b60\ + c19316c4f8f8fd7daea1d8b44a2d03e97c2741537f63d86b4a041702150f66e0\ + 4c5a75d3eac03d744e5432f23e3aea066a63 +PublicKey: \ + 308201ba3082012e06072a8648ce3804013082012102818200d551680a62ebf9\ + 8f0ed8930cc5b12de86d0a0c29a0d7e5524c24672a25428833f4c19ac883ead2\ + 2efcc0c6823f2e942c17adb7ab763ff2c7cc2698fa8b6448e514d4628b197721\ + bdaec780e126ac80ac83f24fef5c154f7690ceba903748be5212e3180ea718ca\ + 7a71a49dee939bf9bc5b7845c9648d074587ccd3724493b91f0902152e802b53\ + 69c3f1ddfa789bf8f2ad2e048ced3bf35502818200a9aebee7d29f90b081afc4\ + d496a6a78210e918bb57a8a21c5995586c0bf20f7a56bb10a97e05a3a723e7db\ + 64612b12bb591b1fe7d2e46be8c96a7b2ce7c66076aeded938775ae2223900ad\ + af52a93f52d62173c82d4b67388c85d4c1127e1edf4643cf09f5375b60c19316\ + c4f8f8fd7daea1d8b44a2d03e97c2741537f63d86b4a038185000281812640c1\ + 88055329f0b44aaf80f82f7fc7f0e421031834dfbd1fb6d6af6ab3e1c173c901\ + 370a4ce2793c1b88d12f764c58ff064905da9c5001f679c7508972f237bccca5\ + 6524787466a7c9c2d6bb6392963008ed1a3e4cf3b13e66086bce3a4ca04d8cab\ + cf0cadb4c403c7d02a858460d04350e730289cb5adf200b5fdf1198168b5 +Test: KeyPairValidAndConsistent +Message: 909068BEFFA43331FDC7 +Signature: 2CCCFF8A67073E5DF643B61A5AE7A5BC216FE267E713B9005F69797B44ECD33BA5DD87461B5C72C50390 +Test: Verify +Message: AC8AFC7A1D9105539E10 +Signature: 0A2BEB58D806EECDDCBD590EBE4AE5AE7BDA326EA0072ADB9FA6A6FEBF40488C80690A2B1DF141BACF91 +Test: Verify +Message: 310E40311BB3F77F9483 +Signature: 28726153B52FE75F1FAA4C97124EE042065D2C90B50B43F885FC45C42C3ED9BDC4EC2D36A2799A041C67 +Test: Verify +Message: 35455ABD53E6FB11ED9B +Signature: 15B3D6ACA9EAD5AA1501ED201335AF9B46657A4CBF00D19328018D82624D4BD9B22D645429B385DADBCA +Test: Verify +Message: 95FFA73B52F0D06A0C1E +Signature: 2904FA8F78B6DF0D15A08714C8F86B97532A9D13B617EC03F329DA20E42816CCF45DBACB432B1F5011C8 +Test: Verify +Message: 1E9934125DA6E9B4E975 +Signature: 1666A3B9DBE26F2AE3F9BF7CBF47989D87AF82F580147BEC8350E21D4DB0691074F63B85A3A7D8E82A8D +Test: Verify +Comment: 1536-bit DSA key +PrivateKey: \ + 308201d4020100308201b006072a8648ce380401308201a30281c100fada6e4b\ + ecef964a85caf9e129639a5616ac000dbac59bd50b84bc8d464114079c34c5b5\ + 8d7d40027faaf037c6a649c527cb002d3a716bdef62b6c94d7a47a8b65c2ebac\ + 05da09e40cdc417024cccba267a98f4eb69701a276b4f117662b566605c36054\ + e7f015d2e5f81331e5666ec17ebf71907788b40cbcea0f24aaffb029ef5c25c5\ + 5ae998f28a2ddb091d262c32ad324f4e64c7b4b50a19e9d92f6d8024188627cf\ + 5ce68674e7ec7da38fd6cf4ec29a6ce2f17e3188d8ef6b0e50d77d5b0219232c\ + f9bee9d56c8bd8252d1edb59d99c40cf32d07d9e5a48930281c100f028143e3f\ + 9d1317aafb814215ffda9c584da8943e96212c90a082c3d2f335e8a6b64d1c89\ + 0aa2224ebf158bec2b6fe6bad236417acd517a4907331e0be0dd0b801218ac27\ + 0acdd45579290be1b94bc418b8f82c651d82a19d2f0e1cbb0fbc0f054d95150a\ + f96f9a7488010787a799c544883ff76a4e3092f2ca9aa9000cecb88dda343c97\ + 2c8192a83820727b1945c1a270cf913ab932457e8e6e207d06cd0efdf265b762\ + b9fa15c9a14633af17204ba2b755ed1b3b421ac596a2a04e64be43041b02191d\ + 4cedc87d55eea31bd702139b90be08d58692a1f97628a01b +PublicKey: \ + 3082027c308201b006072a8648ce380401308201a30281c100fada6e4becef96\ + 4a85caf9e129639a5616ac000dbac59bd50b84bc8d464114079c34c5b58d7d40\ + 027faaf037c6a649c527cb002d3a716bdef62b6c94d7a47a8b65c2ebac05da09\ + e40cdc417024cccba267a98f4eb69701a276b4f117662b566605c36054e7f015\ + d2e5f81331e5666ec17ebf71907788b40cbcea0f24aaffb029ef5c25c55ae998\ + f28a2ddb091d262c32ad324f4e64c7b4b50a19e9d92f6d8024188627cf5ce686\ + 74e7ec7da38fd6cf4ec29a6ce2f17e3188d8ef6b0e50d77d5b0219232cf9bee9\ + d56c8bd8252d1edb59d99c40cf32d07d9e5a48930281c100f028143e3f9d1317\ + aafb814215ffda9c584da8943e96212c90a082c3d2f335e8a6b64d1c890aa222\ + 4ebf158bec2b6fe6bad236417acd517a4907331e0be0dd0b801218ac270acdd4\ + 5579290be1b94bc418b8f82c651d82a19d2f0e1cbb0fbc0f054d95150af96f9a\ + 7488010787a799c544883ff76a4e3092f2ca9aa9000cecb88dda343c972c8192\ + a83820727b1945c1a270cf913ab932457e8e6e207d06cd0efdf265b762b9fa15\ + c9a14633af17204ba2b755ed1b3b421ac596a2a04e64be430381c5000281c100\ + 819c8cedb9c014aa577e9046b90795accbebe81bef68b1b5c37c68cb357e1a5f\ + f92761bc26cb0953956b6c0aec05acfc9d1a27c50789793b13d9eaf2361760c9\ + 7a7d86e7d922f4809a5d2d01448e938190bbc24c150e03ef8305365ddbf5ca19\ + 6857314e3b3023f8ddc9d209bd7dad1ee763e7003fd1b0c53057d2e9acadd23a\ + a18f83d20143bc41a2dfa4a164c82621fc0f800052ec01bec7c99c66fe20ec57\ + 67e6fbbe8810cd5aa75eff3d8a4cb53e1259ebcfebcc2fcf21ba7f3589cd525a +Test: KeyPairValidAndConsistent +Message: 9F6DC301DF53FE22CAC0 +Signature: 15B22111FEFA4AC1E53F2FEC346559E3613BB94F7BB3E2B7551D8B982FA10C38E7F182834DFC7391155FFA42AB945A29E118 +Test: Verify +Message: 2D7B5B9A27EAB468331E +Signature: 029EEA97097FE926DD09821284BCA3F45750B1F8102380D20100596D914DBF6BEFBE1B7A938E3AA5D656B6FD99E8EEE7C606 +Test: Verify +Message: F552FCBBA04FFCCC5CB6 +Signature: 115DE3CC1553CD5E4D40CCED80146DB1D76C10D992AACBCBCB05375C5FDA9F65B9A19DF7E51E6A36A3F2830AEA433AFD4F8B +Test: Verify +Message: 0D52B894153A4BB74068 +Signature: 0F6B8CC28D82E22B9B87D62CFF5C7B2289BB2F8008C42F105B2322CF95BC6D443A9D89A292F482490D94693A44DDF7AC4BD3 +Test: Verify +Message: 294442E103CC0CBA32A6 +Signature: 0FBD8768A18C2B28CE95775AD734157C34C1C3961C1DBBAFDD0A3E92A312A7925AFC9F7F4760FB0C56B42A2042C6B8B37C0E +Test: Verify +Message: E993D8FE1E6F6C3914ED +Signature: 0559D66BAC906C607BBA769AAFEB93E9AEC55FDD4597E432870CDC8A3DF9778301A0B218C886F6B08A414C51BD2F8214201A +Test: Verify +Comment: 2048-bit DSA key +PrivateKey: \ + 3082025d0201003082023506072a8648ce3804013082022802820101009a0886\ + 5d2bc9e0cf03d2500b2a08402bb9dc953d5fcd73f04be61236efc0998a8f012f\ + 00e52f7a6e91e81b88a4c9f985a2da523cbe7caff08cae44963d2035eda72e1f\ + 31f82c8d64c86e686899d53c0200282f407ceb1507db480f1db223606a57466c\ + f60fe9fc5f7ea7d5fd82ed3ab2cf5e35491dfaef0aa2e10fbfa3cdfeb5ebf65e\ + 4dfc2837e1f6399db06cc2e0420c7b14a4c0d483b742ca58b31fec9f26a64e9b\ + fcaa82334e644f4b954e2a9c7eeae096b8864ecd223ead3bcf9e8c1f68f6678f\ + accdb7f26d8f33d8a5fb0cb156cc7daf4a96ec2b730c0d7f666d699f7345a37d\ + dc1ccdea6d8f439ddb23de04a941b246bc257b0aef544a8e868bc8444f021d03\ + f35f80fcd896f03eda9ff07f2e35295384c4f3b8f8c4821369ab541702820100\ + 75c5d8c8f72302d92be3bf486b8648330ff86954de5e6e83efef624a277574c1\ + 6757684d3874ee303fa08343fe82dae484e5dda6781280b434c4090044cc7ff9\ + b6e962594d3ca069815c0f0b6bfd25215a419420d0ef8a1595c6eb1b44a719b4\ + 0131081f75cc15cb09a5d5a029c8546230c30b4af2d4a9f4374c93a095c83b59\ + 4b1774d635d4aee965f1d094469f7bbf8bdc93216a6b8a6c5753b48962335bf2\ + 092aa583c897878c8a7ce61186b592b05d2aea710b673d5994cedb5f117fdb6b\ + 8ad4d89f443c4eb662b428a34a7522c69794cc0274f3eba837e90da86acbc707\ + 4ee3a0b029d970efa48b3d582b740ae0e585d175a5f63a385f8b6b8878b44e1a\ + 041f021d0212c34d3d17b96a899548ebf43bb886676acebd2f040f5b33a4e88d\ + 2d +PublicKey: \ + 308203423082023506072a8648ce3804013082022802820101009a08865d2bc9\ + e0cf03d2500b2a08402bb9dc953d5fcd73f04be61236efc0998a8f012f00e52f\ + 7a6e91e81b88a4c9f985a2da523cbe7caff08cae44963d2035eda72e1f31f82c\ + 8d64c86e686899d53c0200282f407ceb1507db480f1db223606a57466cf60fe9\ + fc5f7ea7d5fd82ed3ab2cf5e35491dfaef0aa2e10fbfa3cdfeb5ebf65e4dfc28\ + 37e1f6399db06cc2e0420c7b14a4c0d483b742ca58b31fec9f26a64e9bfcaa82\ + 334e644f4b954e2a9c7eeae096b8864ecd223ead3bcf9e8c1f68f6678faccdb7\ + f26d8f33d8a5fb0cb156cc7daf4a96ec2b730c0d7f666d699f7345a37ddc1ccd\ + ea6d8f439ddb23de04a941b246bc257b0aef544a8e868bc8444f021d03f35f80\ + fcd896f03eda9ff07f2e35295384c4f3b8f8c4821369ab54170282010075c5d8\ + c8f72302d92be3bf486b8648330ff86954de5e6e83efef624a277574c1675768\ + 4d3874ee303fa08343fe82dae484e5dda6781280b434c4090044cc7ff9b6e962\ + 594d3ca069815c0f0b6bfd25215a419420d0ef8a1595c6eb1b44a719b4013108\ + 1f75cc15cb09a5d5a029c8546230c30b4af2d4a9f4374c93a095c83b594b1774\ + d635d4aee965f1d094469f7bbf8bdc93216a6b8a6c5753b48962335bf2092aa5\ + 83c897878c8a7ce61186b592b05d2aea710b673d5994cedb5f117fdb6b8ad4d8\ + 9f443c4eb662b428a34a7522c69794cc0274f3eba837e90da86acbc7074ee3a0\ + b029d970efa48b3d582b740ae0e585d175a5f63a385f8b6b8878b44e1a038201\ + 050002820100267f9c3ff3ee3cbc0f9e94dc7e6837e1ff65175e967987b90b9a\ + ea7eef1de6e4c342bebb5dbd0c4e2f6514f2d487857a146dda6cfdbc8b56ed25\ + 4cd65754d84dd21a271cd15fc656274725643728b41ce3f0e6872b6dfb4c289e\ + 03f9b903880ce3d7d745dfbb641c8c42ec0bfb6951ca2611fd877c32248c9725\ + 2bdb42d7bd65ebc50653dff389526c546d1e6ebaf6bd8b3298c01935901b7efb\ + 288b78730d89fba7f46f2a642aee0dbc93aa29c190b201acf89d4f8ba28f3e3f\ + 54a1c5a48294dda908f904afb7db398682c809ce13abd49279221d5b40ad7621\ + 6bad7ca256d718d3552344c481b20da5aac3e637fb7edeaf7960b532ef761376\ + 489f02fa8c10 +Test: KeyPairValidAndConsistent +Message: 5F3914F7AE0F6C76D152 +Signature: 03D30B7EAADDCB384CECDBB7541DFE57187242C836A6C72AF6C2525E1A01DB97DF3F41156089162FAFC87361F2F28E55616A50633637FB13EFE3 +Test: Verify +Message: 769583D4E7EAD14C137A +Signature: 01DC2815FD4918B8D314526066A03AD6593C8CED9E1ED04252B1BBA59D019F1C965028DA88BF4DB35AEDBA2C3C963B7933E5C07C590EF78BDFA1 +Test: Verify +Message: 6441D5239F50C71DE0F5 +Signature: 013F6D395DE56832F72F17F7F7572BB6DD1C48BADCBDEA91F0A634486E034B617DA8F5AB5E6F78C691313F822C599B6400A0A119A5DA330C6830 +Test: Verify +Message: F1C2D4F7C3ECDF2C17B7 +Signature: 006441A8B3517613F950BC1C84504082C0C3EA10CC08DCC1DA22E05480036D78345B17244F0DE41DA8342AF3441489CF9880BAA01BF2745CAB3A +Test: Verify +Message: 752A1F2B8D9A717A882F +Signature: 0127027984402F5B8C7DB1B7666FFA787548E4200D26B9D3B20EA9B4370298A9BDC901F324844613E8B5F34F2BFE40D9E6513D0E207B5105A9B1 +Test: Verify +Message: 666DC6B1E871026EDE56 +Signature: 03E87B55A7E81318B6B7057C901F8E3DC564053C1EA08B1F1FD965453803F21C20CE7FCCF606FB1328EC987666E87AF16ABE6B42DB854BFAA019 +Test: Verify diff --git a/src-cryptopp/TestVectors/eax.txt b/src-cryptopp/TestVectors/eax.txt new file mode 100644 index 0000000..8b77f82 --- /dev/null +++ b/src-cryptopp/TestVectors/eax.txt @@ -0,0 +1,75 @@ +AlgorithmType: AuthenticatedSymmetricCipher +Name: AES/EAX +Source: http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf +Plaintext: +Key: 233952DEE4D5ED5F9B9C6D6FF80FF478 +IV: 62EC67F9C3A4A407FCB2A8C49031A8B3 +Header: 6BFB914FD07EAE6B +Ciphertext: E037830E8389F27B025A2D6527E79D01 +Test: Encrypt +Plaintext: F7FB +Key: 91945D3F4DCBEE0BF45EF52255F095A4 +IV: BECAF043B0A23D843194BA972C66DEBD +Header: FA3BFD4806EB53FA +Ciphertext: 19DD5C4C9331049D0BDAB0277408F67967E5 +Test: Encrypt +Plaintext: 1A47CB4933 +Key: 01F74AD64077F2E704C0F60ADA3DD523 +IV: 70C3DB4F0D26368400A10ED05D2BFF5E +Header: 234A3463C1264AC6 +Ciphertext: D851D5BAE03A59F238A23E39199DC9266626C40F80 +Test: Encrypt +Plaintext: 481C9E39B1 +Key: D07CF6CBB7F313BDDE66B727AFD3C5E8 +IV: 8408DFFF3C1A2B1292DC199E46B7D617 +Header: 33CCE2EABFF5A79D +Ciphertext: 632A9D131AD4C168A4225D8E1FF755939974A7BEDE +Test: Encrypt +Plaintext: 40D0C07DA5E4 +Key: 35B6D0580005BBC12B0587124557D2C2 +IV: FDB6B06676EEDC5C61D74276E1F8E816 +Header: AEB96EAEBE2970E9 +Ciphertext: 071DFE16C675CB0677E536F73AFE6A14B74EE49844DD +Test: Encrypt +Plaintext: 4DE3B35C3FC039245BD1FB7D +Key: BD8E6E11475E60B268784C38C62FEB22 +IV: 6EAC5C93072D8E8513F750935E46DA1B +Header: D4482D1CA78DCE0F +Ciphertext: 835BB4F15D743E350E728414ABB8644FD6CCB86947C5E10590210A4F +Test: Encrypt +Plaintext: 8B0A79306C9CE7ED99DAE4F87F8DD61636 +Key: 7C77D6E813BED5AC98BAA417477A2E7D +IV: 1A8C98DCD73D38393B2BF1569DEEFC19 +Header: 65D2017990D62528 +Ciphertext: 02083E3979DA014812F59F11D52630DA30137327D10649B0AA6E1C181DB617D7F2 +Test: Encrypt +Plaintext: 1BDA122BCE8A8DBAF1877D962B8592DD2D56 +Key: 5FFF20CAFAB119CA2FC73549E20F5B0D +IV: DDE59B97D722156D4D9AFF2BC7559826 +Header: 54B9F04E6A09189A +Ciphertext: 2EC47B2C4954A489AFC7BA4897EDCDAE8CC33B60450599BD02C96382902AEF7F832A +Test: Encrypt +Plaintext: 6CF36720872B8513F6EAB1A8A44438D5EF11 +Key: A4A4782BCFFD3EC5E7EF6D8C34A56123 +IV: B781FCF2F75FA5A8DE97A9CA48E522EC +Header: 899A175897561D7E +Ciphertext: 0DE18FD0FDD91E7AF19F1D8EE8733938B1E8E7F6D2231618102FDB7FE55FF1991700 +Test: Encrypt +Plaintext: CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7 +Key: 8395FCF1E95BEBD697BD010BC766AAC3 +IV: 22E7ADD93CFC6393C57EC0B3C17D6B44 +Header: 126735FCC320D25A +Ciphertext: CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC253B4652B1AF3795B124AB6E +Test: Encrypt +Plaintext: CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7 +Key: 8395FCF1E95BEBD697BD010BC766AAC3 +IV: 22E7ADD93CFC6393C57EC0B3C17D6B44 +Header: 126735FCC320D25A +Ciphertext: CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC253B4652B1AF3795B124AB6E +Test: Encrypt +Plaintext: CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7 +Key: 8395FCF1E95BEBD697BD010BC766AAC3 +IV: 22E7ADD93CFC6393C57EC0B3C17D6B44 +Header: 126735FCC320D25A +Ciphertext: 0B8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC253B4652B1AF3795B124AB6E +Test: NotVerify diff --git a/src-cryptopp/TestVectors/esign.txt b/src-cryptopp/TestVectors/esign.txt new file mode 100644 index 0000000..6370671 --- /dev/null +++ b/src-cryptopp/TestVectors/esign.txt @@ -0,0 +1,93 @@ +AlgorithmType: Signature +Name: ESIGN/EMSA5-MGF1(SHA-1) +Source: Crypto++ 5.0 test vectors, generated by Wei Dai +Comment: 1536-bit key +KeyFormat: DER +PrivateKey: \ + 3082014D0281C100E2A6788AB3CC986AEC06C51690143D3677141645D0628165EE924B9AFB7E6EDD\ + 52D90145B2F6031522C7A6CEC05E358F42B7837DACEA589F868F8DCA1C0F5FD8E5EDB8BBBAFCFF6D\ + 64CFCFBE68F46FBA6EFF45BC9D0CBB4F7F6075F5FFC2049C2F304B51C417764E18D182926E02D411\ + 6CE5C5C010E3D0AA6872A49B0D1FF4B37D54689C31F5821D04E9D4DB34D7536EE7F88B8C481B0EC1\ + F93193A0B70567E6FD76E9FAC4F67BB47DACD356D0C8015261E068DDF8C34C0CAFCF3FA775577FEB\ + 020120024100FAF0F292EE96D4F449024F86C0A104E0633C722586EC00AD33E0234629825D2081BA\ + 337597889CAC55DC6BEBDD8F13FE3AA2133D6371601A37D195DA7BC45EF3024100EBE16F88887A42\ + 5AA08E271467CC2220DC44012AB24ED4FF3512A96E8CB600C8BBCB771459FF0EE63D4B6786952A83\ + A7143A775073F0A1D69B6D0B5817755673 +PublicKey: \ + 3081C70281C100E2A6788AB3CC986AEC06C51690143D3677141645D0628165EE924B9AFB7E6EDD52\ + D90145B2F6031522C7A6CEC05E358F42B7837DACEA589F868F8DCA1C0F5FD8E5EDB8BBBAFCFF6D64\ + CFCFBE68F46FBA6EFF45BC9D0CBB4F7F6075F5FFC2049C2F304B51C417764E18D182926E02D4116C\ + E5C5C010E3D0AA6872A49B0D1FF4B37D54689C31F5821D04E9D4DB34D7536EE7F88B8C481B0EC1F9\ + 3193A0B70567E6FD76E9FAC4F67BB47DACD356D0C8015261E068DDF8C34C0CAFCF3FA775577FEB02\ + 0120 +Test: KeyPairValidAndConsistent +Message: "test" +Signature: \ + A3E32065DEDAE7EC05C1BFCD25797D99CDD5739D9DF3A4AA9AA45AC8233D0D37FEBC763FF184F659\ + 14914F0C341BAE9A5C2E2E38087877CBDC3C7EA034445B0F67D9352A79471A523771DB1267C1B6C6\ + 6673B3402ED6F21A840AB67B0FEB8B88AB33DDE4832190632D512AB16FABA75CFD7799F2E1EF671A\ + 7402370EED0A06ADF41565B8E1D145AE3919B4FF5DF1457BE0FE72ED11928F61414F0200F2766F7C\ + 79A2E552205D975EFE39AE2110FB35F480814113DDE85FCA1E4FF89BB268FB28 +Test: Verify +Message: "test1" +Test: NotVerify + +AlgorithmType: Signature +Name: ESIGN/EMSA5-MGF1(SHA-1) +Source: http://www.nttmcl.com/sec/Esign/esign_emsa5_data_ntt.txt, \ + ESIGN ( IFSSA-ESIGN-EMSA5 ) Test Vector No.1-3 ( 1152 bits ) +KeyFormat: Component +Prime1: ec8b4bdc9a56ae7b60619814ec45d617246063b5aac39c286f7c82ec2824c245001b678217a7cf178979c7270eb510db +Prime2: e7b1c3ae3494d0ac7b6868a53a5fe3ba19471437c54b25699e8c348a003e5e1d4c6d244d4f6a78f260c98fc54795a6a3 +Modulus: c5d0b8fac0cc6acc9d52c61200b541f7b4f8ff9f1bda97e0ebf78a3df768ba70ade59306d6ae65655bff7c6a94518c91e43dc0003b6f8730acc244799bdacb1e5070c6ea3089ea83bd5ef0a533adf3d9d63c0e88ce74545cfb21213fc33813fd913c6a6cf84b5adabc7d74751e9945521ac76a790bba95ad48d9d3fb2fbc4b0ed2ddee7d5ea6aa61633eccdac6381fab +PublicExponent: 0400 +Test: KeyPairValidAndConsistent +Message: 86f28c1cb5e640548309b85dc6e64c1a +Signature: 348dc9a0943b1e2ba7ef501cbe970a023b37ca4019b9a5cb35ffc3bcdb28dcbd4193d7817d418bbaf291d97a1eeb918a03ee65caa7ad26c24f9ef807c8798ade5b70d7328cd36ac0844bf63f511bb63067e8236d084cf8af68e88155ea94b978aab6bd0339c55d976434423fc779d549779e81f528d028c7343e060544410e528814fb0874417d1eedf38d6db4b97dd6 +Test: Verify +Message: 2fd87bfa6c8a965c9e1aaa8e3574202b +Signature: 561ad8bd11270c71f00af0e0cf256d858c757e8b55b9c4d6fb6bf71598ab59352992656348c1ff1ccda14fb7c5c3b53be49727c07422b78ffc380eeb03be7bdf07b279337af8a1eb7c5bdb725b33a82926b6afb7a1fff0750cc2532c6f96e28d7f1e621cf222b42bb850312f1a5fb7d99acd1c6f6d2347a121dd478374d6a40a7b0cd42e430f01b926135fc8d850366a +Test: Verify +Message: 888330ef1dc1588d578badde35c98d1e +Signature: 915d64d7b9b811fe8b58eaff4c2bf9ce2ad886eef95b28093f8c21f4ca950fdb2f6e77f97d0f2f8158445347f5b3ce33e082f3b5204522e15614d1891078d9557796726b5555cbd8d5489638ecf4738257dea70175fe27de54b1f45c0a96c229bd59260bebfb241e8eacb8a1a23b9a9a79b6d1f52cfed8cca2f1968e37d76c435ad1acd44131ef2c5f5e4ea8a33aee4e +Test: Verify + +AlgorithmType: Signature +Name: ESIGN/EMSA5-MGF1(SHA-1) +Source: http://www.nttmcl.com/sec/Esign/esign_emsa5_data_ntt.txt, \ + ESIGN ( IFSSA-ESIGN-EMSA5 ) Test Vector No.4-6 ( 1152 bits ) +KeyFormat: Component +Prime1: d64dac2fb3506111bbac11a04e138d2d6f32df119f2f259065cf5785a46aaf404ad887f0a310b36be4a3a1a33c8a054f +Prime2: d1158628ed1e0695c02a821ab8590f59fc1a3fb1e19ee192ab789e9d963766d78f55cfef9bf58c0c774a32d8a8943955 +Modulus: 92855120174c4a115bf525fa1f2ebf68d8328162149a5a6751b2512584eab7e5582d38d0e5029e01ece85a484030bb884a29121d8924f0195b22842b16436cd36c33bbe843e1cf7a585e89894b14595641d081a3077d667096df251bd93c86ebd94e0d555601794fa66fa2bcea920287c19922bed486a4f631390d1e36cc3635b509cb14c44d50313919a6cbb75eff35 +PublicExponent: 0400 +Test: KeyPairValidAndConsistent +Message: 16a3632339c463e243a4909f8a3810a8 +Signature: 7d8790ee852a4f3ba8bb3fa0f6fc30c29b6bc2bc538195826544138dcb92500122148ac2cf0dc77dd37182c2267a73317ce5b2ae26db79204abe0e10c7212ba8de99fdc5cf498f7ee689588541fb78291afb9b65242f725a4aa32b119957b4314a58b4239a0235b9b1a8a6efbaa3601961d4b0730a6d9e5659f20105931d473daf3d378b39b7f3f01516d72ade9ef68a +Test: Verify +Message: ef8bcad6c164a86b0e0a3c011d556744 +Signature: 6ce6024f64a7f04a0fe29b65cf2ec2ac49d9f90078a77db8bc260d3cfef233165a90b29d5787218b4d05a0e9321f2e802a8ed6d1a4201feb982a5d06bef051d60436d8c61a249432e662e625806526075f02b60d198142b96b67a4ac31d0071a1f971dae5a6a1b6db177591edfe80f7e51c7335441490f05f214b5a1aec94de572e3ec11ef4bebeb42f27037d38a186f +Test: Verify +Message: 29023889c79230c1c479820c5ff2e006 +Signature: 85f0b648ee0f6d30a18666e2da8bcda319ede91ca18e018548e2a1c21b0e0049b91528eba4da3be4551b26c4e59e6aba25312874f2320eaf7c94c541e17fb16fb0d9d9928ea526b0fc0c0fb2d12e425a5917e4039a5366585327bc3456107ff31c889c5e04259457dfe65952dc43cd35f4ca689272769096b9583bbffad4a057673f938fa7192bbca44598cf5600e3eb +Test: Verify + +AlgorithmType: Signature +Name: ESIGN/EMSA5-MGF1(SHA-1) +Source: http://www.nttmcl.com/sec/Esign/esign_emsa5_data_ntt.txt, \ + ESIGN ( IFSSA-ESIGN-EMSA5 ) Test Vector No.7-9 ( 1152 bits ) +KeyFormat: Component +Prime1: fd5708b30e8ee342bacaeb01c0d3baa91a833dacff2878c7df62e04a65afe770acdcefeaf8a72a5809387e5ed97756ef +Prime2: fa335563d5da151e3ab025f3b77d3f1eaf4a0d431012e79b12ca8ec433d347bd9a2b5179f2ed332a19ea2cad694c97dd +Modulus: f5072ba25e7df2c0e0a0abde031dda9534a493396ab895e6132abc90f993535ce55d6395e1fd548371228decc1cfefa9737344243ddb1eccbbc22d68571617afb23638c3f0222a84b0a8c9889ab934aa84cc92e14d972670db6d2105bbd0212c1843ff0ccbae19535ac01cf02ad98aa941fce32fac874cea7f1f83969fbaf025fb562a087efb4652210d45279312da7d +PublicExponent: 0400 +Test: KeyPairValidAndConsistent +Message: abbf5c71245af5d272e627ec845e9ed4 +Signature: b75e2869c052df20d6c008dd911a5bd752d5a23ee42ae47def37f76f6b2d5f04eb8d9b0783c502e0abd30bc567a6672292c3a6736fe8d4034fad857456cd599259d09f42f1d4c64d244fd149f6316f0b763be0de4f9da7f9649a76b984fe2ae99293d406904a9df59d28cc8a58b7ad0029657a47ac0e28d6353287df1ea8feef2fbb65d86425e80487420c1c9c1bda7e +Test: Verify +Message: cf2c943bc4c23175b43ba128c75339d1 +Signature: 64616eb627bf49c2a5a183479a66b7dae12cd1a0982baa0cc12329f594196b9de47909e6b5cf4653bfccdeeb5478fd88c31c197c9adc335a84ec58664ce5fc55c7b2f17b0f32ffac4ff3f3b4ddb3ce125ab7e43efc0be6ae8357895ab5f118a4ec71b57cc1b252373fecd4a1f404ed295f2d97868e3737fdd6fdf124bc2f1e083b57d5c237db775d429d08d5b5ced857 +Test: Verify +Message: 4d011f09f665d5f4a12595900e3827ec +Signature: 1911d3df18bdd9907b69ce6b655086c952c92d826bbef199fb1e0dcb7209a1b28d0a03beabc9e7d8df052febe26f691ff808caaac697c3005d524f3da8c700bf620aa37fd0793b3f22c6a488d733336d040642e0767755391951a754a1111345b912b4c0228ab154eb4baac0383a54023bd7c7ea2ed4bb894444b80d7e5f18407f51c3af858b9fa9198190b4b540fce8 +Test: Verify diff --git a/src-cryptopp/TestVectors/gcm.txt b/src-cryptopp/TestVectors/gcm.txt new file mode 100644 index 0000000..e39ed36 --- /dev/null +++ b/src-cryptopp/TestVectors/gcm.txt @@ -0,0 +1,139 @@ +AlgorithmType: AuthenticatedSymmetricCipher +Name: AES/GCM +Source: aes-modes-src-07-10-08/Testvals/gcm.1, Basic Tests for GCM (compiled by B. R. Gladman) +Key: 00000000000000000000000000000000 +IV: 000000000000000000000000 +MAC: 00000000000000000000000000000000 +Test: NotVerify +Key: 00000000000000000000000000000000 +IV: 000000000000000000000000 +MAC: 58e2fccefa7e3061367f1d57a4e7455a +Test: Encrypt +Key: 00000000000000000000000000000000 +IV: 000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 0388dace60b6a392f328c2b971b2fe78 +MAC: ab6e47d42cec13bdf53a67b21257bddf +Test: Encrypt +Key: feffe9928665731c6d6a8f9467308308 +IV: cafebabefacedbaddecaf888 +Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255 +Ciphertext: 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e 21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985 +MAC: 4d5c2af327cd64a62cf35abd2ba6fab4 +Test: Encrypt +Key: feffe9928665731c6d6a8f9467308308 +IV: cafebabefacedbaddecaf888 +Header: feedfacedeadbeeffeedfacedeadbeefabaddad2 +Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext: 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e 21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091 +MAC: 5bc94fbc3221a5db94fae95ae7121a47 +Test: Encrypt +Key: feffe9928665731c6d6a8f9467308308 +IV: cafebabefacedbad +Header: feedfacedeadbeeffeedfacedeadbeefabaddad2 +Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext: 61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c7423 73806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598 +MAC: 3612d2e79e3b0785561be14aaca2fccb +Test: Encrypt +Key: feffe9928665731c6d6a8f9467308308 +IV: 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728 c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b +Header: feedfacedeadbeeffeedfacedeadbeefabaddad2 +Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext: 8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca7 01e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5 +MAC: 619cc5aefffe0bfa462af43c1699d050 +Test: Encrypt +Header: +Plaintext: +Ciphertext: +Key: 000000000000000000000000000000000000000000000000 +IV: 000000000000000000000000 +MAC: cd33b28ac773f74ba00ed1f312572435 +Test: Encrypt +Key: 000000000000000000000000000000000000000000000000 +IV: 000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 98e7247c07f0fe411c267e4384b0f600 +MAC: 2ff58d80033927ab8ef4d4587514f0fb +Test: Encrypt +Key: feffe9928665731c6d6a8f9467308308feffe9928665731c +IV: cafebabefacedbaddecaf888 +Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255 +Ciphertext: 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c 7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256 +MAC: 9924a7c8587336bfb118024db8674a14 +Test: Encrypt +Key: feffe9928665731c6d6a8f9467308308feffe9928665731c +IV: cafebabefacedbaddecaf888 +Header: feedfacedeadbeeffeedfacedeadbeefabaddad2 +Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext: 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c 7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710 +MAC: 2519498e80f1478f37ba55bd6d27618c +Test: Encrypt +Key: feffe9928665731c6d6a8f9467308308feffe9928665731c +IV: cafebabefacedbad +Header: feedfacedeadbeeffeedfacedeadbeefabaddad2 +Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext: 0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057 fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7 +MAC: 65dcc57fcf623a24094fcca40d3533f8 +Test: Encrypt +Key: feffe9928665731c6d6a8f9467308308feffe9928665731c +IV: 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728 c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b +Header: feedfacedeadbeeffeedfacedeadbeefabaddad2 +Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext: d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e45 81e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b +MAC: dcf566ff291c25bbb8568fc3d376a6d9 +Test: Encrypt +Header: +Plaintext: +Ciphertext: +Key: 0000000000000000000000000000000000000000000000000000000000000000 +IV: 000000000000000000000000 +MAC: 530f8afbc74536b9a963b4f1c4cb738b +Test: Encrypt +Key: 0000000000000000000000000000000000000000000000000000000000000000 +IV: 000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: cea7403d4d606b6e074ec5d3baf39d18 +MAC: d0d1c8a799996bf0265b98b5d48ab919 +Test: Encrypt +Key: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +IV: cafebabefacedbaddecaf888 +Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255 +Ciphertext: 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa 8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad +MAC: b094dac5d93471bdec1a502270e3cc6c +Test: Encrypt +Key: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +IV: cafebabefacedbaddecaf888 +Header: feedfacedeadbeeffeedfacedeadbeefabaddad2 +Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext: 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa 8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662 +MAC: 76fc6ece0f4e1768cddf8853bb2d551b +Test: Encrypt +Key: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +IV: cafebabefacedbad +Header: feedfacedeadbeeffeedfacedeadbeefabaddad2 +Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext: c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0 feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f +MAC: 3a337dbf46a792c45e454913fe2ea8f2 +Test: Encrypt +Key: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +IV: 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728 c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b +Header: feedfacedeadbeeffeedfacedeadbeefabaddad2 +Plaintext: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a72 1c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext: 5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf4 0fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f +MAC: a44a8266ee1c8eb0c8b5d4cf5ae9f19a +Test: Encrypt +Header: +Plaintext: +Ciphertext: +Key: 00000000000000000000000000000000 +IV: 000000000000000000000000 +Plaintext: 000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f 303132333435363738393a3b3c3d3e3f 404142434445464748494a4b4c4d4e4f 505152535455565758595a5b5c5d5e5f 606162636465666768696a6b6c6d6e6f 707172737475767778797a7b7c7d7e7f 808182838485868788898a8b8c8d8e8f 909192939495969798999a9b9c9d9e9f a0a1a2a3a4a5a6a7a8a9aaabacadaeaf b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf d0d1d2d3d4d5d6d7d8d9dadbdcdddedf +Ciphertext: 0389d8cd64b3a595fb21c8b27dbff077 e784b8b85d5e4f34efe493e48896dfff 002333026a56b2fd08a09c87fcbe85cf f97c902a25bb1f4a43478687f5feb6cd ca9f3fc6ecab732627386ee2996a4cde c5e91f48c293c6a87774b950aeb1d7bf 62321a0d76006297b2d06623cf6e4fb1 433494c3326b0ae914120085a195413f 5e3278e4107d7b08dd2107405610e67d 83ed5b5ba0b591e9e46b1029f5f6936f fdb0e788fc09f60d861a0b3e1ab6294a 76ebdf6663421ef7dd6c1bc448dfcdb7 a0c38bae72fa627ed327f2b46fcec25a 77ee5fd7e3354788643c0d7df15075d5 +MAC: 6b385f3012eafda4189da7ad3b6eafbf +Test: Encrypt +Key: 00000000000000000000000000000000 +IV: 000000000000000000000000 +Plaintext: 000102030405060708090a0b0c0d0e0f 101112131415161718191a1b1c1d1e1f 202122232425262728292a2b2c2d2e2f 303132333435363738393a3b3c3d3e3f 404142434445464748494a4b4c4d4e4f 505152535455565758595a5b5c5d5e5f 606162636465666768696a6b6c6d6e6f 707172737475767778797a7b7c7d7e7f 808182838485868788898a8b8c8d8e8f 909192939495969798999a9b9c9d9e9f a0a1a2a3a4a5a6a7a8a9aaabacadaeaf b0b1b2b3b4b5b6b7b8b9babbbcbdbebf c0c1c2c3c4c5c6c7c8c9cacbcccdcecf d0d1d2d3d4d5d6d7d8d9dadbdcdddedf +Ciphertext: 0389d8cd64b3a595fb21c8b27dbff077 e784b8b85d5e4f34efe493e48896dfff 002333026a56b2fd08a09c87fcbe85cf f97c902a25bb1f4a43478687f5feb6cd ca9f3fc6ecab732627386ee2996a4cde c5e91f48c293c6a87774b950aeb1d7bf 62321a0d76006297b2d06623cf6e4fb1 433494c3326b0ae914120085a195413f 5e3278e4107d7b08dd2107405610e67d 83ed5b5ba0b591e9e46b1029f5f6936f fdb0e788fc09f60d861a0b3e1ab6294a 76ebdf6663421ef7dd6c1bc448dfcdb7 a0c38bae72fa627ed327f2b46fcec25a 77ee5fd7e3354788643c0d7df15075d5 +MAC: 6b385f3012eafda4189da7ad3b6eafbf +Test: Encrypt diff --git a/src-cryptopp/TestVectors/hmac.txt b/src-cryptopp/TestVectors/hmac.txt new file mode 100644 index 0000000..52f85fd --- /dev/null +++ b/src-cryptopp/TestVectors/hmac.txt @@ -0,0 +1,125 @@ +AlgorithmType: MAC +Name: HMAC(MD5) +Source: RFC 2202 +Comment: Test Case 1 +Key: 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b +Message: "Hi There" +MAC: 0x9294727a3638bb1c13f48ef8158bfc9d +Test: Verify +Comment: Test Case 2 +Key: "Jefe" +Message: "what do ya want for nothing?" +MAC: 0x750c783e6ab0b503eaa86e310a5db738 +Test: Verify +Comment: Test Case 3 +Key: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +Message: r50 0xdd +MAC: 0x56be34521d144c88dbb8c733f0e8b3f6 +Test: Verify +Comment: Test Case 4 +Key: 0x0102030405060708090a0b0c0d0e0f10111213141516171819 +Message: r50 0xcd +MAC: 0x697eaf0aca3a3aea3a75164746ffaa79 +Test: Verify +Comment: Test Case 5 +Key: 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c +Message: "Test With Truncation" +MAC: 0x56461ef2342edc00f9bab995690efd4c +Test: Verify +MAC: 0x56461ef2342edc00f9bab995 +#TruncatedSize: 12 +Test: VerifyTruncated +Comment: Test Case 6 +Key: r80 0xaa +Message: "Test Using Larger Than Block-Size Key - Hash Key First" +MAC: 0x6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd +Test: Verify +Comment: Test Case 7 +Key: r80 0xaa +Message: "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" +MAC: 0x6f630fad67cda0ee1fb1f562db3aa53e +Test: Verify + +AlgorithmType: MAC +Name: HMAC(SHA-1) +Source: RFC 2202 +Comment: Test Case 1 +Key: 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b +Message: "Hi There" +MAC: 0xb617318655057264e28bc0b6fb378c8ef146be00 +Test: Verify +Comment: Test Case 2 +Key: "Jefe" +Message: "what do ya want for nothing?" +MAC: 0xeffcdf6ae5eb2fa2d27416d5f184df9c259a7c79 +Test: Verify +Comment: Test Case 3 +Key: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +Message: r50 0xdd +MAC: 0x125d7342b9ac11cd91a39af48aa17b4f63f175d3 +Test: Verify +Comment: Test Case 4 +Key: 0x0102030405060708090a0b0c0d0e0f10111213141516171819 +Message: r50 0xcd +MAC: 0x4c9007f4026250c6bc8414f9bf50c86c2d7235da +Test: Verify +Comment: Test Case 5 +Key: 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c +Message: "Test With Truncation" +MAC: 0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04 +Test: Verify +MAC: 0x4c1a03424b55e07fe7f27be1 +#TruncatedSize: 12 +Test: VerifyTruncated +Comment: Test Case 6 +Key: r80 0xaa +Message: "Test Using Larger Than Block-Size Key - Hash Key First" +MAC: 0xaa4ae5e15272d00e95705637ce8a3b55ed402112 +Test: Verify +Comment: Test Case 7 +Key: r80 0xaa +Message: "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" +MAC: 0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91 +Test: Verify + +AlgorithmType: MAC +Name: HMAC(RIPEMD-160) +Source: RFC 2286 +Comment: Test Case 1 +Key: 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b +Message: "Hi There" +MAC: 0x24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668 +Test: Verify +Comment: Test Case 2 +Key: "Jefe" +Message: "what do ya want for nothing?" +MAC: 0xdda6c0213a485a9e24f4742064a7f033b43c4069 +Test: Verify +Comment: Test Case 3 +Key: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +Message: r50 0xdd +MAC: 0xb0b105360de759960ab4f35298e116e295d8e7c1 +Test: Verify +Comment: Test Case 4 +Key: 0x0102030405060708090a0b0c0d0e0f10111213141516171819 +Message: r50 0xcd +MAC: 0xd5ca862f4d21d5e610e18b4cf1beb97a4365ecf4 +Test: Verify +Comment: Test Case 5 +Key: 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c +Message: "Test With Truncation" +MAC: 0x7619693978f91d90539ae786500ff3d8e0518e39 +Test: Verify +MAC: 0x7619693978f91d90539ae786 +#TruncatedSize: 12 +Test: VerifyTruncated +Comment: Test Case 6 +Key: r80 0xaa +Message: "Test Using Larger Than Block-Size Key - Hash Key First" +MAC: 0x6466ca07ac5eac29e1bd523e5ada7605b791fd8b +Test: Verify +Comment: Test Case 7 +Key: r80 0xaa +Message: "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" +MAC: 0x69ea60798d71616cce5fd0871e23754cd75d5a0a +Test: Verify diff --git a/src-cryptopp/TestVectors/mars.txt b/src-cryptopp/TestVectors/mars.txt new file mode 100644 index 0000000..3ed5a10 --- /dev/null +++ b/src-cryptopp/TestVectors/mars.txt @@ -0,0 +1,66 @@ +AlgorithmType: SymmetricCipher +Name: MARS/ECB +Key: 80000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: B3E2AD5608AC1B6733A7CB4FDF8F9952 +Test: Encrypt +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: DCC07B8DFB0738D6E30A22DFCF27E886 +Test: Encrypt +Key: 00000000000000000000000000000000 +Plaintext: DCC07B8DFB0738D6E30A22DFCF27E886 +Ciphertext: 33CAFFBDDC7F1DDA0F9C15FA2F30E2FF +Test: Encrypt +Key: CB14A1776ABBC1CDAFE7243DEF2CEA02 +Plaintext: F94512A9B42D034EC4792204D708A69B +Ciphertext: 225DA2CB64B73F79069F21A5E3CB8522 +Test: Encrypt +Key: 86EDF4DA31824CABEF6A4637C40B0BAB +Plaintext: 4DF955AD5B398D66408D620A2B27E1A9 +Ciphertext: A4B737340AE6D2CAFD930BA97D86129F +Test: Encrypt +Key: 000000000000000000000000000000000000000000000000 +Plaintext: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +Ciphertext: 97778747D60E425C2B4202599DB856FB +Test: Encrypt +Key: D158860838874D9500000000000000000000000000000000 +Plaintext: 93A953A82C10411DD158860838874D95 +Ciphertext: 4FA0E5F64893131712F01408D233E9F7 +Test: Encrypt +Key: 791739A58B04581A93A953A82C10411DD158860838874D95 +Plaintext: 6761C42D3E6142D2A84FBFADB383158F +Ciphertext: F706BC0FD97E28B6F1AF4E17D8755FFF +Test: Encrypt +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 62E45B4CF3477F1DD65063729D9ABA8F +Ciphertext: 0F4B897EA014D21FBC20F1054A42F719 +Test: Encrypt +Key: FBA167983E7AEF22317CE28C02AAE1A3E8E5CC3CEDBEA82A99DBC39AD65E7227 +Plaintext: 1344ABA4D3C44708A8A72116D4F49384 +Ciphertext: 458335D95EA42A9F4DCCD41AECC2390D +Test: Encrypt +Key: 00000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 3FE24DC09173D15F4616A849D396F7E3 +Test: EncryptionMCT +Key: 00000000000000000000000000000000 +Plaintext: 24BD3D2FC6FEE152D1D64545E2230584 +Ciphertext: 00000000000000000000000000000000 +Test: DecryptionMCT +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: 34EC834E2F30741ECB476DA7E9662BBD +Test: EncryptionMCT +Key: 000000000000000000000000000000000000000000000000 +Plaintext: 7F27C3397A8CEEF1BDF859459690FEA8 +Ciphertext: 00000000000000000000000000000000 +Test: DecryptionMCT +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 00000000000000000000000000000000 +Ciphertext: EDE145C10E279501D921C5E3B04420A6 +Test: EncryptionMCT +Key: 0000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 95615ADB0DDF6613A5E84F849AC8C00D +Ciphertext: 00000000000000000000000000000000 +Test: DecryptionMCT diff --git a/src-cryptopp/TestVectors/nr.txt b/src-cryptopp/TestVectors/nr.txt new file mode 100644 index 0000000..f08bb6a --- /dev/null +++ b/src-cryptopp/TestVectors/nr.txt @@ -0,0 +1,615 @@ +AlgorithmType: Signature +Name: NR(1363)/EMSA1(SHA-1) +Source: generated by Wei Dai using Crypto++ 5.0 +Comment: 1024-bit NR key +KeyFormat: Component +SubgroupOrder: \ + 09b2940496d6d9a43bb7ec642c57b302e59b3a5155 +SubgroupGenerator: \ + a1c379ba91fe1f9d5283807b809c698bce4aee6f405f4de8c46becf33c08a63b\ + c5f8088f75b5b6bcfb0847ccbdee700e4e698652317bbd7a3056404c541136d7\ + 332c2b835ef0d1508ef57b437de60675f20f75df0483f242ddeb57efacd18041\ + 8790f4dec0a8250593ba36f17316580d50db1383ea93a21247650a2e04af904d +Modulus: \ + bd670f79b0cde98a84fd97e54d5d5c81525a016d222a3986dd7af3f32cde8a9f\ + 6564e43a559a0c9f8bad36cc25330548b347ac158a345631fa90f7b873c36eff\ + ae2f7823227a3f580b5dd18304d5932751e743e922eebfbb4289c389d9019c36\ + f96c6b81fffbf20be062182104e3c4b7d02b872d9a21e0fb5f10ded64420951b +PrivateExponent: \ + 0355dc884345c08fb399b23b161831e94dbe61571e +PublicElement: \ + 255cf6b0a33f80cab614eafd5f7b2a6d83b3eafe27cd97b77ae70c7b966707d8\ + 23f0e6aaaa41dc005aaefd3a0c269e60a665d2642f5d631ff1a3b8701bc06be9\ + c44ab7367f77fefeec4c5959cd07e50d74a05af60b059ad3fc75249ecf44774b\ + 88b46860d9c3fa35d033bcfc7b0b2d48dc180d192d4918cddff4f7ebcdaaa198 +Test: KeyPairValidAndConsistent +Message: 66B92E1E2C44B80F7BFA +Signature: \ + 06e7586b76d5a8270155cce2d3ff4495237eed29a101eb1341fce0b43d95397b\ + 053d93772b0a9cf3117b +Test: Verify +Message: 973266BB0A492248082A +Signature: \ + 02de44ed2233f0f11dcf567217d2089ec039a211bf000d42e04900a66ce45c58\ + 526a97d7f4cfba29e43d +Test: Verify +Message: 9A6D079ED0CA9D8B40E8 +Signature: \ + 04f59dbb2712926b3bc1d3c428f16203f3443f88db0669adda94dcb54e1fff71\ + fb51bb603e7adff13f84 +Test: Verify +Message: AA34DCE67BCDAC927DA6 +Signature: \ + 08ad21bf9d0cc598a214329d3544685d39487988bb01aced68ad0a4831affbff\ + 3b14df6c0f4ac4d2e967 +Test: Verify +Message: 4EDAC08816AFDBF284DA +Signature: \ + 09a9d5aa9bd1b6b61fe8825128c8e52a6213692b2504c8c6951299b5ca51b03d\ + ea0a5e56f9a7c4cd44f7 +Test: Verify +Message: D82F2E903230962B8174 +Signature: \ + 0441c8d089e690a7fab391de07073326d443a0d9d806a3997ac1641175310890\ + 1e55582a582541330539 +Test: Verify +Comment: 1025-bit NR key +KeyFormat: Component +SubgroupOrder: \ + 0b3949dadf3196f08bca0606f06443afce2fb1d02f +SubgroupGenerator: \ + 015f0f6d1729ef2af723c00e36450a04c7e7681d65b74a6417a53b3eb6036989\ + eff8e0ab11a7ec3ce2340b7c7a92e1a977aee52555c06c12c4cc28496ddc2598\ + feeb7539ce90d3888e21f61d7f14746cf67d9fed373afd97e2483700e300ed9d\ + a25e7200b363a4727ad201194b36ea5f816cf83488c3e527d3a5515870d2da63\ + d6 +Modulus: \ + 017310bf02d70ef2cee45d1cc47ec8ce8cabdd6bf32a560975a42ef057bf9dfd\ + 553bc9368ddb154a55d855edaa755e69f511a4c69ba78571cc4b14ddbb0f32a4\ + a9c56c286305aa21ec4e35de7390747477b3bd574e7b87cbebde2f665703137a\ + 1172350ad2f48a0884d076ada9db82f104e6b0ad86693cd4adbd0067639102fc\ + f1 +PrivateExponent: \ + 0696b0f255468b7ac18e11632f208ca86383a46724 +PublicElement: \ + 45bf83e62f50190374b23de5e4a1d0278e9e8e6c8335577d62e80662a380c206\ + e326819c5082d321dfda1f905fa5a3ead9a2dc769885a27b1fd6a133185dc5a7\ + 876a76ab0a09fe02b7071a924169e4d2d2a67e67ed3628800134183b962c0b31\ + 3463aa154e6437d644e025ab234e63d19c129842a61c5e5ea5a06466c858c81c +Test: KeyPairValidAndConsistent +Message: 2F585D0CE4FA1CD93880 +Signature: \ + 06586d8a703cdc27200d5261853f50effa8ebbdfc905f5becb68b81eca506992\ + 50fb54e46d557c6095dd +Test: Verify +Message: 4F09A1F217B8393199EE +Signature: \ + 0622cd33b1d715829d8fae104759ed449f95becb5e03d36f5578fd6a2951d2e6\ + 26cfce85ba6563990d64 +Test: Verify +Message: 03D7110A753B008A76A0 +Signature: \ + 02925630b4c80e604fc1d8680bfd0e3d878e22b3a30ab8b10da7fc38816a8c5f\ + 1e06927c68f9d3db60d9 +Test: Verify +Message: 129F4781D417671F886D +Signature: \ + 016c2c4ce845b4d412828cbb8a396d080c7eb93bcb01f7010410198c8bac96df\ + 8ab8761cebdb7d87f3a2 +Test: Verify +Message: 3E1594F559D1248D1112 +Signature: \ + 080bab68c62be86ab2c1bfd0edf10387a7cd66b69f054e254218e01f650e4e8c\ + 6bfa10054e367893e59e +Test: Verify +Message: D6F0354F1B6B253B6997 +Signature: \ + 08755c7e8012e8160db75c6160686351e5c577207f01602b4dda2fa56b864374\ + 703c83bb323c7bb34f5f +Test: Verify +Comment: 1026-bit NR key +KeyFormat: Component +SubgroupOrder: \ + 36bb68cd95dab195f14c4534283e7ea50b00cc31a3 +SubgroupGenerator: \ + e2782ad6992f4b7e88787b4d616744b60e095575a177569c4a069e311e38b724\ + 0c43343367e23574c30e4d9f05afe1fbe61423bab715915c4ccf28aa0ed2f52b\ + 092b86c8ec1f9d4795d6e91c88ba41297625c11a9e1f4f182da13cf51e541038\ + a1266bf32b2dd81ecd84bb80be8fdf97689942e944b7fbb6981e00cd680ee25f +Modulus: \ + 025098828217d00108030801e5f135fc6fd3010be39e49060a96addc8a081198\ + 803402c4b46e4ce0750fcbab8cf084c7ca8cae09f1b5482d336fa3af47b96791\ + d02d8143e274b1325f2213e17f9384c805f479e52a3117cf84869d395f1bc025\ + c918484478d2da1880d32bc519f4e6b2fd2d46958795550ce1765f725626f3fc\ + 17 +PrivateExponent: \ + 2db270c284328353f979cad99f4133c53acaa6ee71 +PublicElement: \ + 0179b283f67868aeded3a0c5633d0e6c18fad77174e2c89c03452593d05e77a9\ + fb029c0ccb2b6f2328e79c286ee392713f12d9d45578348383b81d11b0e0f7e8\ + 9965a7785d5ab64ea25bb73e8acaa8e84cb9897985015757a48c0b1dac3a6a60\ + 6fe671ea073ec434a46f227b8d4b02a46fbba2f6c6216736d669f55778d81004\ + d8 +Test: KeyPairValidAndConsistent +Message: 7E4F2ED4E79062778A2D +Signature: \ + 03f523873462ee1513833e2853c3b62e30c5c1cc3224f1a42dc154fa84ecce04\ + 487069530d76e0574a38 +Test: Verify +Message: A0E35846B5CF1B5BF560 +Signature: \ + 2264285d75a55c431a7adb9347bc07d58efbeb1dd9354d01b0b86f2875f8dec0\ + 294d20289d39369c5afa +Test: Verify +Message: 3B138785EFC6F520EAE0 +Signature: \ + 116e45961ca73f3ccf08b35f94877fef88772cf0fa2ab196c85a91104d8fbde6\ + 65b7032b2fb4011a88cc +Test: Verify +Message: 0F6BE2AA764B485145D4 +Signature: \ + 027ad753bde13c7f2fcd7571e5558f8af756cdb9463237fb0e285cb633cc86be\ + 1b410188d701f6ca83c6 +Test: Verify +Message: 6CD9FBD23EA58826FB04 +Signature: \ + 1651decd376899104e3fdbe40ab2d9bfd3c8577f3b092b66e3760678ecb3fc35\ + 23a59107e0bdccb76a73 +Test: Verify +Message: 473A82649565109E9E89 +Signature: \ + 2045ef56d92f89a214d76cca6b591068ac5f0d008c121ec4e5c4c1e8ca9b67cd\ + bb5ecc776a23b6d54ba5 +Test: Verify +Comment: 1027-bit NR key +KeyFormat: Component +SubgroupOrder: \ + 291d0ba731a4303070504d8b9615640a5e1345e00f +SubgroupGenerator: \ + 051c9d0270b69ceef82af5aed5f91dc88d585096609d835d03d39cf3ce74f5a3\ + 402d4e8e192455493da61cc58ee6f54dd941172be3d7642169cbc52273f4b725\ + f1d6c820c3333336c64d32fb6238121b3ccb7c71b847764946bb0887a44ca9de\ + 802cda62efa9dda573751084225353f11ed837f3dc25de8374b6fdbfb6e313e4\ + 6d +Modulus: \ + 055402a8abe9cda3072ca8601d68032651feb0335856e57f8f8d4ec949098a64\ + 59151cefeef91b7aa733668c8cf0e9b96c93c61f3528d4036daa6565646f65d7\ + 4c4552817df7e5fb1cc421cfd885e27bb811ad227e81b3fa02f7a00bf01ee6e2\ + 3fb5572a75f8f29b58bd5f7db435e8a92a923f15d50f34213d29816921bf195b\ + 2d +PrivateExponent: \ + 13b27094d9a5a3a9704cebdbe890da325fa26ad555 +PublicElement: \ + 03b06b99097cd7145c7d7782b02e247a4741f3c7f39233627f17e13ebff89a18\ + cad6a454c3f32f7ef2910384030da71ae47e1c3fa79c2141dad107f8e715e47f\ + b0bb626baafc35db769852ebbec2d339c3c3d5f2287cfdd20b3b78ea4607086c\ + 42558ae4637eddd6a74bc1072d0f34d9c0130cbc9e84f537e7ce50df502d17b5\ + c3 +Test: KeyPairValidAndConsistent +Message: AE6DCD9535AEEE3ECC89 +Signature: \ + 1c6794878aabf07cf9f59b685d4a3a6e51c9135dc101a4a6a62c95a20902e2fa\ + 23db7d15293f595f86ab +Test: Verify +Message: C83A14EAC016D659F9FE +Signature: \ + 18ed4812925dca6a9c30e2e3566433e202be2d305414e1e6583905ad845cbc63\ + 2049804932aac79b858c +Test: Verify +Message: 745E02041EB487D16CE6 +Signature: \ + 13d4ef1de59ef0fe9bc4ecc6d382908642f6f5793e255b819e25ed124f7fa574\ + d91fc2e9b258f0514b15 +Test: Verify +Message: 62F019655A83501FC4E7 +Signature: \ + 07f797768984ecc792f366ece16f5102aec2aac6d31fdaf3972839cac2c99a2b\ + f5b347c887d37943383c +Test: Verify +Message: 351D37A4B5046E885EAA +Signature: \ + 22064cd5179ff1551dbf73c5220e17a9dfa1aa8f7f22f44a6c70f13c6d0a21f8\ + 7e53278251037a6cdc5e +Test: Verify +Message: 4073D33915F595F4FF9D +Signature: \ + 1f902ea2c9521b8c7f11619d35dd22a4667e2eb89a017194bb68ec0a9df762c9\ + 377c1c075b5f09566048 +Test: Verify +Comment: 1028-bit NR key +KeyFormat: Component +SubgroupOrder: \ + 2368e2b864b250ad45406391e7eeaa3d27cd053c2b +SubgroupGenerator: \ + 07c325695dfe315a77ad7b42f0d18f9d4821b5c153fee7385877602fa54477bb\ + 8c0639d2438f34352b97c22d02a7295d2b53d5286a01caa919d6283614690624\ + 240af922675ccd4a0534ec336cb79cde31b02b5988cc5a53ca17790d67d803a2\ + 7bb927b9c59bdc6ac794175e285cafdece6778ab19a0b444747fee20d5bf929e\ + 70 +Modulus: \ + 0abdeff64b6f28256e4562109bffed29cb5aa95d89cc0ec95da0e773dbff3467\ + c271bbb1e1fbb6af058517fdacdf26b5919674c625eced6317d8631c063f43b3\ + ade2cd633d554913339071d6ebed5fd665fc5dd7d47b80721a976c3b14fbd253\ + f0f988c354725289f2897df0a15985c92b2d4da8d087870c251c72d979b8304d\ + 51 +PrivateExponent: \ + 0771305163506b2b83bd5279935df1b5fcf180b004 +PublicElement: \ + 043e4ae6244408879264fe6b859b578218705b9a45af22efded27141b7f090cb\ + cbe42dcf481df3e41b13920ae02b694eaa6bfd62f2d3c5d677b8c4ce783cbe27\ + 89e088b04489ef535ad4a517351c8835cf128f7ec677a1b1dbe3ae9cc4198ddb\ + 6e1cef8e978c0725f5063797bc43eb9ae496286cccbad5d4e026e9edb997d2f9\ + 18 +Test: KeyPairValidAndConsistent +Message: 4867852C83F181CDD010 +Signature: \ + 1db6a5661b20c9289428c3b9ebf65d5a8f757f3a3b1eb15dfaf0c8cefc891954\ + b48279eb45910a141ec3 +Test: Verify +Message: DA6493C86D6B62C5961C +Signature: \ + 1c05300a56319ba4a8ace1206f5f37b5bbefc9d80a171a57b6da3c02aa1f3079\ + 70583c008f073996d932 +Test: Verify +Message: AE2C1136BFE966794A6C +Signature: \ + 02dfd79eb18f3a862b11a5d199a7db1dc53580ade90517a7739cbd8ab1849c44\ + 54ba17a69b8d03ecc4f9 +Test: Verify +Message: B20160E0442E726BE749 +Signature: \ + 14c0cf809174d39f1324b7dd0d6d1fb3be5b5577c10048b12def39772fa60cd5\ + a9d2cca9075f12e5a3c1 +Test: Verify +Message: 3638935C4492F5CA42F2 +Signature: \ + 0081d7216636bc6fb9bc7a637a377ebf4f9048826e0360c8faf03dd28c4ee4a4\ + da82689259f140b3d918 +Test: Verify +Message: DFB674CA6E0FDC0CBE99 +Signature: \ + 1e3e21aa3dcccddb8cf3e360631fc36956263951ff18fec553531252b4dbe753\ + 6ed5fc62897d51500c38 +Test: Verify +Comment: 1029-bit NR key +KeyFormat: Component +SubgroupOrder: \ + 3357536531dec150be0ef8747f69ea30d987ff7df1 +SubgroupGenerator: \ + 067dd80dbc6b41f58d08f077a9a3dcbfe12a62065fe6b4691c457f506b56dcab\ + 0433b3aad6ef962501633d0f3947b491a1317e7e6b632f062c53104d609c9222\ + b056f08a0c83662a70744331fd09b2b42fb0768e52da27e92732106fbd41ec73\ + 7373fd080b56b543d808d49eeb6e1bb0a8619b1edee8fb8295dc042423f684af\ + 8a +Modulus: \ + 1d0f176b6799b36724c92954c38d0288fa95400c2b14e064f76a6338fccaebca\ + 8d978b93bb76507bc150a50f9fe799fffe12ae2875b13ac1084ffcfde9f62b86\ + 185a72f04ff80538d6eac177edc98d61a517b1275bcf4b57aa262e1702d623bc\ + 344db7e5621c949a9b12e9936e88fae9b200a1f8ad5b40ec8220aa301267f38d\ + d7 +PrivateExponent: \ + 2dcdc00a86ecc2a60ebfa6660a83af1d7c3e570b85 +PublicElement: \ + 13834f0fa1f42abf7dbd264cb7d2eb5798da8972df67f517c62d7ae5070fd588\ + d61db62e492f9654833e876ed5737df35069f5ee01a45de881d8f5e68ec52ad9\ + ef32780e8c453a5f1e38cc17bc5cd061a3c122080f6e1b82d31877e8b08f634f\ + 497bd90b06824eaa0416c64104ce5622c272673d0dedb836ac7d47e0cea06739\ + 02 +Test: KeyPairValidAndConsistent +Message: 1E34034C47FE533F8FF5 +Signature: \ + 05c110848feacc9ac762ffa14943f9ce9a111777de0502d9f364ad9b2df4e1a8\ + 17bc15a602579b3a6a25 +Test: Verify +Message: 53D2CA23AF7DF95634F0 +Signature: \ + 14009997efeb3fd246956e44b5b0e48581ac5f414613b41fe5842c85b031ab8a\ + e68f66f8e1f1f9fc1d74 +Test: Verify +Message: 0F056E08AE77B3B30F33 +Signature: \ + 1beedf85b426d36a657f422ab9a9132986eaf415332816d33d70c726c3066158\ + c6481fd00503ffb65518 +Test: Verify +Message: F08C80E8FD38A3867B76 +Signature: \ + 0a23b8d8f920cfb0dec93725e4972080445647c54227fb987dd9f80fab446c75\ + 1c2594276168aa68f318 +Test: Verify +Message: 6D392690B92B3E75020F +Signature: \ + 18668f59c6974dad551a89bec5cacf0bf8617e8f43052eb97d7a1b12411b27b7\ + 4248b3d1f5070823e951 +Test: Verify +Message: 10AE0E091A267641FACF +Signature: \ + 1b3d10f74fdaed3d4d61fedfa3f6ad3a37c0cf6687166a312d5b280724c3545d\ + 225e1fe0639cfb1113d6 +Test: Verify +Comment: 1030-bit NR key +KeyFormat: Component +SubgroupOrder: \ + 27c7996c1d3729c4cf1de06529e5619771e27ad9eb +SubgroupGenerator: \ + 0d87a4b01385da7f43b6277933c5f0dc8072dcacd5252e1b29f588114a7ac56e\ + 377050aa8174b5dda400f043234e4a746442792734dc80274a00a3676101be94\ + 759fc2630b9a858966488b12611d03d0b31e7243e124497a754544cee1db10bb\ + 0a81cf0b2a68045b76fe935f641c666fdc788a2b968c6668c669115756b961d9\ + fe +Modulus: \ + 2a32d68d31248024053bf628a94404b9a49d91ade4d7a45b071e93292a7f8c26\ + 61d9165f0ab85491d4b0dc67d335fa7d7dd172cb17193390a55eb000aa97e2b8\ + ed3ee64b73aa43ea9b8979132c2d966ab03c42cc14782c96e4284ee1136b8515\ + 007ed1b1a5708b5e8d81304fa651edc715918e2299cfe9016dfec5f454d907f5\ + 9f +PrivateExponent: \ + 091155581ecb7a0a792ba95c772d9382298bfdfa6f +PublicElement: \ + 0d7d22c931422fc46505887559a51490c2e367cdb40242cdbaeb23024693fd5c\ + 68f6a3307ca34b224457d5aa610b90eca3b39905481daaba7151318f09f974ad\ + 664546d14c87f797e38139ee1e07adba9c775e07b7f7b3edba87d886920d6b2c\ + ef5f084359566b0a3b8b940a65b9ad93fd7ccd1354cdcee3c43c6bd315180498\ + ad +Test: KeyPairValidAndConsistent +Message: 23EEE1D0EA8950B8F322 +Signature: \ + 18fe1a5f61c4946810e82a1e30fb6c87ce4ad9cebb1ae27eebfa8779fe292b2a\ + 451be3506bb65519dfd0 +Test: Verify +Message: 13FA6F2816FB83190A21 +Signature: \ + 2161a5be85f7ffe806df00f4bd50915e4b0674e7591f1c0902153823f881bc7b\ + 3f093d92bf86b74b5b3e +Test: Verify +Message: D071CCC0C6E4CAE82E5A +Signature: \ + 059158b2cf143f38eb8c51088dd79bf45990e596c8026fa3de5e668368b9d8d7\ + fe9ffdbdecf66aaf02bb +Test: Verify +Message: 22CE83F4803BF3EA2C48 +Signature: \ + 073b56d72a5b706455cfdcbf85b75ee45c40e96dd21a5460542ade665e51a85c\ + 510315a50307c2bbdb2d +Test: Verify +Message: 7A927EC7BB9CA16C1B0A +Signature: \ + 254c7525aad9b4b3807b3900a963fbf42f9ff2144820ea69abe5ba2c80613510\ + e1429ebc726fd0a87a4c +Test: Verify +Message: 9591B069993E10BC0B84 +Signature: \ + 0ed4210e5e4f2f9546ea181c4a61d062a1158810071905b180dbf070b480f436\ + 0b1f66065ecf111741cf +Test: Verify +Comment: 1031-bit NR key +KeyFormat: Component +SubgroupOrder: \ + 26f86a81a6bb530c2f9b63e3690e95a0894575f445 +SubgroupGenerator: \ + 1e24828adb4ebf2becdbdcadf6706631293ad6566803d12479f04a7bb20b6086\ + fe81df164f8bd02c5f418c1140d143f11a71170b42d0753c952bfff951b9ca42\ + 04868375efaa4afad50b75787e41c5ab9ce8adcbccecd3716f350bb8aaeca9b6\ + 098bd0002d789e1f7db9c19d9045499877b93ecb4e7c64808b742063bbecf60e\ + 29 +Modulus: \ + 4d58515f7b41c4fc87e4fcefe5cf6d84b2d74a9d6f498ae9605fcbf1c5921742\ + 2001a272ef91dbd09e7af5ee54126dd4fc44bb1ed624d0dd5dafb984d5278114\ + 0bba40600cbd4752d2c32b43253efee57af6964c339570edb24195502e6d424b\ + 84bed65ac98c6fc52ec90e40a525f1863a53f2fbe2a0a133342eff4337f26ceb\ + 93 +PrivateExponent: \ + 0e61a054ee6510734a80f67a54d8c4151c957ef16f +PublicElement: \ + 19b50f1eea45bfaa22352a38f3c3b86d6f670747ac2fd94359608e25f2bb9f60\ + 2506bc357245deeb4c3c702d435c557da4f4a9fd37330a75547c91681fdbb51f\ + 286adb498d1e489e89b2e6a4eb9ff30222c51fefbeac7435f629f536ac2d6b87\ + 664d80e5c97398cf489a1d1ca217f7f21ea8e409f938378875cf5f528162e3bc\ + 07 +Test: KeyPairValidAndConsistent +Message: B4B3C8FBE82013228A21 +Signature: \ + 0e1003dd216194ded89f7d10b35a266ca7587d8cfb06a1fe3dd43f07dea4a6d6\ + acaa1477f2552c9b3114 +Test: Verify +Message: 17D2D18302173E2CE992 +Signature: \ + 027b40cd9a159257a57efae3a657399a3b6d8b06f707ba3a323abc383a93f919\ + 1246c38c03b028be05df +Test: Verify +Message: 8032AE177D6DF38C7E27 +Signature: \ + 1f5e3d759e3b832f5a6c57b055764ff5b8ad942dd819610ef94cfec296cd1b56\ + 4fd0b18bfa08c3645db3 +Test: Verify +Message: 768640A60A3C62E02428 +Signature: \ + 0abe2dfabc81ab677d2cbd781ef9768325a5d6d15a22f41b32972bd67058e617\ + e28c7e0dfbaae535d655 +Test: Verify +Message: B0999CA45B77ED63639D +Signature: \ + 1525539cd207d5f6f915eb2731b6451e38e11e0a031d7e420e0bb95d6616d8ef\ + 35d20eb43c111f8f9ca1 +Test: Verify +Message: 587EDB968FA82C12C930 +Signature: \ + 024ed20dc19a07e00158aa2fe9cb6353f0112b8fab0e6775667115e1c92e5eb4\ + 29876c12ed48e996f4f7 +Test: Verify +Comment: 1032-bit NR key +KeyFormat: Component +SubgroupOrder: \ + 2e802b5369c3f1ddfa789bf8f2ad2e048ced3bf355 +SubgroupGenerator: \ + a9aebee7d29f90b081afc4d496a6a78210e918bb57a8a21c5995586c0bf20f7a\ + 56bb10a97e05a3a723e7db64612b12bb591b1fe7d2e46be8c96a7b2ce7c66076\ + aeded938775ae2223900adaf52a93f52d62173c82d4b67388c85d4c1127e1edf\ + 4643cf09f5375b60c19316c4f8f8fd7daea1d8b44a2d03e97c2741537f63d86b\ + 4a +Modulus: \ + d551680a62ebf98f0ed8930cc5b12de86d0a0c29a0d7e5524c24672a25428833\ + f4c19ac883ead22efcc0c6823f2e942c17adb7ab763ff2c7cc2698fa8b6448e5\ + 14d4628b197721bdaec780e126ac80ac83f24fef5c154f7690ceba903748be52\ + 12e3180ea718ca7a71a49dee939bf9bc5b7845c9648d074587ccd3724493b91f\ + 09 +PrivateExponent: \ + 0f66e04c5a75d3eac03d744e5432f23e3aea066a63 +PublicElement: \ + 2640c188055329f0b44aaf80f82f7fc7f0e421031834dfbd1fb6d6af6ab3e1c1\ + 73c901370a4ce2793c1b88d12f764c58ff064905da9c5001f679c7508972f237\ + bccca56524787466a7c9c2d6bb6392963008ed1a3e4cf3b13e66086bce3a4ca0\ + 4d8cabcf0cadb4c403c7d02a858460d04350e730289cb5adf200b5fdf1198168\ + b5 +Test: KeyPairValidAndConsistent +Message: 909068BEFFA43331FDC7 +Signature: \ + 2d557d8fae420880640dd9f60a524db48980c80d8b0179dd3c1892f02e87c9f6\ + a04a8aa731be05aaffef +Test: Verify +Message: AC8AFC7A1D9105539E10 +Signature: \ + 0ae7f23328453fdb03c090c09ee69d787ee7dfaccd047445b1026a9a7cacdd1f\ + 91455db7299538817894 +Test: Verify +Message: 310E40311BB3F77F9483 +Signature: \ + 28a8d8de06dc0011b044d19a163d350535d6ca91a023c9687557690ddf102d8c\ + 7558246ced311f2fc444 +Test: Verify +Message: 35455ABD53E6FB11ED9B +Signature: \ + 162156e476cba65e767b4db942bb35cdc6293cf4360f1801a215bb2c726c22af\ + f3a711d3c6473f1eb985 +Test: Verify +Message: 95FFA73B52F0D06A0C1E +Signature: \ + 29bf4f13e6aff528aa1b060c2baed865c442e0472422b4bd485aa5ba2a09ad0d\ + 732637bb3ee520f6bc0b +Test: Verify +Message: 1E9934125DA6E9B4E975 +Signature: \ + 1674975d0a97e799d113ff9cad06b7f70a33f5ca5f1916cee07b525270284fbb\ + 1c0428666987ad7e2116 +Test: Verify +Comment: 1536-bit NR key +KeyFormat: Component +SubgroupOrder: \ + 232cf9bee9d56c8bd8252d1edb59d99c40cf32d07d9e5a4893 +SubgroupGenerator: \ + f028143e3f9d1317aafb814215ffda9c584da8943e96212c90a082c3d2f335e8\ + a6b64d1c890aa2224ebf158bec2b6fe6bad236417acd517a4907331e0be0dd0b\ + 801218ac270acdd45579290be1b94bc418b8f82c651d82a19d2f0e1cbb0fbc0f\ + 054d95150af96f9a7488010787a799c544883ff76a4e3092f2ca9aa9000cecb8\ + 8dda343c972c8192a83820727b1945c1a270cf913ab932457e8e6e207d06cd0e\ + fdf265b762b9fa15c9a14633af17204ba2b755ed1b3b421ac596a2a04e64be43 +Modulus: \ + fada6e4becef964a85caf9e129639a5616ac000dbac59bd50b84bc8d46411407\ + 9c34c5b58d7d40027faaf037c6a649c527cb002d3a716bdef62b6c94d7a47a8b\ + 65c2ebac05da09e40cdc417024cccba267a98f4eb69701a276b4f117662b5666\ + 05c36054e7f015d2e5f81331e5666ec17ebf71907788b40cbcea0f24aaffb029\ + ef5c25c55ae998f28a2ddb091d262c32ad324f4e64c7b4b50a19e9d92f6d8024\ + 188627cf5ce68674e7ec7da38fd6cf4ec29a6ce2f17e3188d8ef6b0e50d77d5b +PrivateExponent: \ + 1d4cedc87d55eea31bd702139b90be08d58692a1f97628a01b +PublicElement: \ + 819c8cedb9c014aa577e9046b90795accbebe81bef68b1b5c37c68cb357e1a5f\ + f92761bc26cb0953956b6c0aec05acfc9d1a27c50789793b13d9eaf2361760c9\ + 7a7d86e7d922f4809a5d2d01448e938190bbc24c150e03ef8305365ddbf5ca19\ + 6857314e3b3023f8ddc9d209bd7dad1ee763e7003fd1b0c53057d2e9acadd23a\ + a18f83d20143bc41a2dfa4a164c82621fc0f800052ec01bec7c99c66fe20ec57\ + 67e6fbbe8810cd5aa75eff3d8a4cb53e1259ebcfebcc2fcf21ba7f3589cd525a +Test: KeyPairValidAndConsistent +Message: 9F6DC301DF53FE22CAC0 +Signature: \ + 15b22111ffa1b733979cd9d8944b1291ce09468ccbd05040de0f83023c8fe083\ + 734ec39a542011643e448b01429c4bae06d1 +Test: Verify +Message: 2D7B5B9A27EAB468331E +Signature: \ + 029eea970a049ffcb4c6117c97d181bec7a27557ceb88d422b2212ca36238380\ + 87cd52d2445f539c9c03705ba4b485f56e19 +Test: Verify +Message: F552FCBBA04FFCCC5CB6 +Signature: \ + 115de3cc15d9a066c00fed43f583f6a9c984d4b8f4c93c3d72094a4b04dda506\ + 7d460c3d1ae33ba66ceaac676256c1e73001 +Test: Verify +Message: 0D52B894153A4BB74068 +Signature: \ + 0f6b8cc28e2068a3fe14d220177793daf3512ba6942e9d16ef1571fa34926c27\ + edd1bfa94723a663425f5c2d01eaddaa972e +Test: Verify +Message: 294442E103CC0CBA32A6 +Signature: \ + 0fbd8768a1b3025c0d0d309cc448320e086318772bb9485a5a0a2afa1eb2afb2\ + d1818aa7b1c55b9dc424e654524278f0ddbc +Test: Verify +Message: E993D8FE1E6F6C3914ED +Signature: \ + 0559d66bad3a51520bbb85827a257ab09dfa33938127c69bf40f08339b2f2251\ + c0e50b63d2a4d05225dea7f58f67de3071e9 +Test: Verify +Comment: 2048-bit NR key +KeyFormat: Component +SubgroupOrder: \ + 03f35f80fcd896f03eda9ff07f2e35295384c4f3b8f8c4821369ab5417 +SubgroupGenerator: \ + 75c5d8c8f72302d92be3bf486b8648330ff86954de5e6e83efef624a277574c1\ + 6757684d3874ee303fa08343fe82dae484e5dda6781280b434c4090044cc7ff9\ + b6e962594d3ca069815c0f0b6bfd25215a419420d0ef8a1595c6eb1b44a719b4\ + 0131081f75cc15cb09a5d5a029c8546230c30b4af2d4a9f4374c93a095c83b59\ + 4b1774d635d4aee965f1d094469f7bbf8bdc93216a6b8a6c5753b48962335bf2\ + 092aa583c897878c8a7ce61186b592b05d2aea710b673d5994cedb5f117fdb6b\ + 8ad4d89f443c4eb662b428a34a7522c69794cc0274f3eba837e90da86acbc707\ + 4ee3a0b029d970efa48b3d582b740ae0e585d175a5f63a385f8b6b8878b44e1a +Modulus: \ + 9a08865d2bc9e0cf03d2500b2a08402bb9dc953d5fcd73f04be61236efc0998a\ + 8f012f00e52f7a6e91e81b88a4c9f985a2da523cbe7caff08cae44963d2035ed\ + a72e1f31f82c8d64c86e686899d53c0200282f407ceb1507db480f1db223606a\ + 57466cf60fe9fc5f7ea7d5fd82ed3ab2cf5e35491dfaef0aa2e10fbfa3cdfeb5\ + ebf65e4dfc2837e1f6399db06cc2e0420c7b14a4c0d483b742ca58b31fec9f26\ + a64e9bfcaa82334e644f4b954e2a9c7eeae096b8864ecd223ead3bcf9e8c1f68\ + f6678faccdb7f26d8f33d8a5fb0cb156cc7daf4a96ec2b730c0d7f666d699f73\ + 45a37ddc1ccdea6d8f439ddb23de04a941b246bc257b0aef544a8e868bc8444f +PrivateExponent: \ + 0212c34d3d17b96a899548ebf43bb886676acebd2f040f5b33a4e88d2d +PublicElement: \ + 267f9c3ff3ee3cbc0f9e94dc7e6837e1ff65175e967987b90b9aea7eef1de6e4\ + c342bebb5dbd0c4e2f6514f2d487857a146dda6cfdbc8b56ed254cd65754d84d\ + d21a271cd15fc656274725643728b41ce3f0e6872b6dfb4c289e03f9b903880c\ + e3d7d745dfbb641c8c42ec0bfb6951ca2611fd877c32248c97252bdb42d7bd65\ + ebc50653dff389526c546d1e6ebaf6bd8b3298c01935901b7efb288b78730d89\ + fba7f46f2a642aee0dbc93aa29c190b201acf89d4f8ba28f3e3f54a1c5a48294\ + dda908f904afb7db398682c809ce13abd49279221d5b40ad76216bad7ca256d7\ + 18d3552344c481b20da5aac3e637fb7edeaf7960b532ef761376489f02fa8c10 +Test: KeyPairValidAndConsistent +Message: 5F3914F7AE0F6C76D152 +Signature: \ + 03d30b7eaaddcb384dce378f806e88d646419bbedbc2c0c5cae32f3c3b02e0e1\ + a3c3ab04b31e2c25db713db539a65c9419a846aea88aaa707cb4 +Test: Verify +Message: 769583D4E7EAD14C137A +Signature: \ + 01dc2815fd4918b8d3bd1743f5ab4546313b1fa8044b4737b2c485eeb0016bcc\ + cc084be064b6a8934a28011167eebbc33513ce609aa206810aa1 +Test: Verify +Message: 6441D5239F50C71DE0F5 +Signature: \ + 013f6d395de56832f82ee813b574002c36e551aaeffbb28ddebb84da7f01ff6f\ + 4c3d0f3519d548e2ec1a0b36f12ac1e4fedc83071bbbbce024a6 +Test: Verify +Message: F1C2D4F7C3ECDF2C17B7 +Signature: \ + 006441a8b3517613f9a8c2e7a89c492e7f49300d901ad01b92167c1fce02453d\ + 52b69dc1fc6532e792ad6366eae7fb14de3ad3f6f3132b0519fc +Test: Verify +Message: 752A1F2B8D9A717A882F +Signature: \ + 0127027984402f5b8cc069decc1bd611f0bb59c6eee86da7d334e3f8b903c5f3\ + 02c65aaf16a837963bf772931235f81e963e4d692699dfd4f7e1 +Test: Verify +Message: 666DC6B1E871026EDE56 +Signature: \ + 03e87b55a7e81318b7599da3fa8f18d46253b6546814fd1ae19318820100c297\ + 4de2624da0d54ca27e7fe3477913a6df35bf925de3f3d9a06849 +Test: Verify diff --git a/src-cryptopp/TestVectors/panama.txt b/src-cryptopp/TestVectors/panama.txt new file mode 100644 index 0000000..bd4d4ee --- /dev/null +++ b/src-cryptopp/TestVectors/panama.txt @@ -0,0 +1,76 @@ +AlgorithmType: MessageDigest +Name: Panama-LE +Source: Panama reference implementation +Message: "" +Digest: aa0cc954d757d7ac7779ca3342334ca471abd47d5952ac91ed837ecd5b16922b +Test: Verify +Message: "The quick brown fox jumps over the lazy dog" +Digest: 5f5ca355b90ac622b0aa7e654ef5f27e9e75111415b48b8afe3add1c6b89cba1 +Test: Verify +Source: generated by Crypto++ 5.2.1 +Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +Digest: af9c66fb6058e2232a5dfba063ee14b0f86f0e334e165812559435464dd9bb60 +Test: Verify + +AlgorithmType: MessageDigest +Name: Panama-BE +Source: Panama reference implementation +Message: "" +Digest: e81aa04523532dd7267e5c5bc3ba0e289837a62ba032350351980e960a84b0af +Test: Verify +Message: "The quick brown fox jumps over the lazy dog" +Digest: 8fa7dadce0110f979a0b795e76b2c25628d8bda88747758149c42e3bc13f85bc +Test: Verify +Source: generated by Crypto++ 5.2.1 +Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +Digest: cb34f0937e8d870d3bd7ff6311765f2c229a6c2154e4db119538db5159437cab +Test: Verify + +AlgorithmType: MAC +Name: Panama-LE +Source: modified from Panama hash test vectors +Key: "" +Message: "" +MAC: aa0cc954d757d7ac7779ca3342334ca471abd47d5952ac91ed837ecd5b16922b +Test: Verify +Message: "The quick brown fox jumps over the lazy dog" +MAC: 5f5ca355b90ac622b0aa7e654ef5f27e9e75111415b48b8afe3add1c6b89cba1 +Test: Verify +Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +MAC: af9c66fb6058e2232a5dfba063ee14b0f86f0e334e165812559435464dd9bb60 +Test: Verify +Key: "The " +Message: "quick brown fox jumps over the lazy dog" +MAC: 5f5ca355b90ac622b0aa7e654ef5f27e9e75111415b48b8afe3add1c6b89cba1 +Test: Verify + +AlgorithmType: MAC +Name: Panama-BE +Source: modified from Panama hash test vectors +Key: "" +Message: "" +MAC: e81aa04523532dd7267e5c5bc3ba0e289837a62ba032350351980e960a84b0af +Test: Verify +Message: "The quick brown fox jumps over the lazy dog" +MAC: 8fa7dadce0110f979a0b795e76b2c25628d8bda88747758149c42e3bc13f85bc +Test: Verify +Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +MAC: cb34f0937e8d870d3bd7ff6311765f2c229a6c2154e4db119538db5159437cab +Test: Verify +Key: "The " +Message: "quick brown fox jumps over the lazy dog" +MAC: 8fa7dadce0110f979a0b795e76b2c25628d8bda88747758149c42e3bc13f85bc +Test: Verify + +AlgorithmType: SymmetricCipher +Source: generated by Crypto++ 5.2.1 +Key: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +IV: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Name: Panama-LE +Plaintext: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Ciphertext: F07F5FF2CCD01A0A7D44ACD6D239C2AF0DA1FF35275BAF5DFA6E09411B79D8B9 +Test: Encrypt +Name: Panama-BE +Plaintext: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f +Ciphertext: E12E2F6BA41AE832D888DA9FA6863BC37C0E996F190A1711330322D37BD98CA4 +Test: Encrypt diff --git a/src-cryptopp/TestVectors/rsa_oaep.txt b/src-cryptopp/TestVectors/rsa_oaep.txt new file mode 100644 index 0000000..4e4cdd3 --- /dev/null +++ b/src-cryptopp/TestVectors/rsa_oaep.txt @@ -0,0 +1,1765 @@ +AlgorithmType: AsymmetricCipher +Name: RSA/OAEP-MGF1(SHA-1) +Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors +KeyFormat: Component +Comment: Example 1: A 1024-bit RSA Key Pair +Modulus: \ +a8 b3 b2 84 af 8e b5 0b 38 70 34 a8 60 f1 46 c4 \ +91 9f 31 87 63 cd 6c 55 98 c8 ae 48 11 a1 e0 ab \ +c4 c7 e0 b0 82 d6 93 a5 e7 fc ed 67 5c f4 66 85 \ +12 77 2c 0c bc 64 a7 42 c6 c6 30 f5 33 c8 cc 72 \ +f6 2a e8 33 c4 0b f2 58 42 e9 84 bb 78 bd bf 97 \ +c0 10 7d 55 bd b6 62 f5 c4 e0 fa b9 84 5c b5 14 \ +8e f7 39 2d d3 aa ff 93 ae 1e 6b 66 7b b3 d4 24 \ +76 16 d4 f5 ba 10 d4 cf d2 26 de 88 d3 9f 16 fb +PublicExponent: 01 00 01 +PrivateExponent: \ +53 33 9c fd b7 9f c8 46 6a 65 5c 73 16 ac a8 5c \ +55 fd 8f 6d d8 98 fd af 11 95 17 ef 4f 52 e8 fd \ +8e 25 8d f9 3f ee 18 0f a0 e4 ab 29 69 3c d8 3b \ +15 2a 55 3d 4a c4 d1 81 2b 8b 9f a5 af 0e 7f 55 \ +fe 73 04 df 41 57 09 26 f3 31 1f 15 c4 d6 5a 73 \ +2c 48 31 16 ee 3d 3d 2d 0a f3 54 9a d9 bf 7c bf \ +b7 8a d8 84 f8 4d 5b eb 04 72 4d c7 36 9b 31 de \ +f3 7d 0c f5 39 e9 cf cd d3 de 65 37 29 ea d5 d1 +Prime1: \ +d3 27 37 e7 26 7f fe 13 41 b2 d5 c0 d1 50 a8 1b \ +58 6f b3 13 2b ed 2f 8d 52 62 86 4a 9c b9 f3 0a \ +f3 8b e4 48 59 8d 41 3a 17 2e fb 80 2c 21 ac f1 \ +c1 1c 52 0c 2f 26 a4 71 dc ad 21 2e ac 7c a3 9d +Prime2: \ +cc 88 53 d1 d5 4d a6 30 fa c0 04 f4 71 f2 81 c7 \ +b8 98 2d 82 24 a4 90 ed be b3 3d 3e 3d 5c c9 3c \ +47 65 70 3d 1d d7 91 64 2f 1f 11 6a 0d d8 52 be \ +24 19 b2 af 72 bf e9 a0 30 e8 60 b0 28 8b 5d 77 +ModPrime1PrivateExponent: \ +0e 12 bf 17 18 e9 ce f5 59 9b a1 c3 88 2f e8 04 \ +6a 90 87 4e ef ce 8f 2c cc 20 e4 f2 74 1f b0 a3 \ +3a 38 48 ae c9 c9 30 5f be cb d2 d7 68 19 96 7d \ +46 71 ac c6 43 1e 40 37 96 8d b3 78 78 e6 95 c1 +ModPrime2PrivateExponent: \ +95 29 7b 0f 95 a2 fa 67 d0 07 07 d6 09 df d4 fc \ +05 c8 9d af c2 ef 6d 6e a5 5b ec 77 1e a3 33 73 \ +4d 92 51 e7 90 82 ec da 86 6e fe f1 3c 45 9e 1a \ +63 13 86 b7 e3 54 c8 99 f5 f1 12 ca 85 d7 15 83 +MultiplicativeInverseOfPrime2ModPrime1: \ +4f 45 6c 50 24 93 bd c0 ed 2a b7 56 a3 a6 ed 4d \ +67 35 2a 69 7d 42 16 e9 32 12 b1 27 a6 3d 54 11 \ +ce 6f a9 8d 5d be fd 73 26 3e 37 28 14 27 43 81 \ +81 66 ed 7d d6 36 87 dd 2a 8c a1 d2 f4 fb d8 e1 +Test: KeyPairValidAndConsistent +Comment: RSAES-OAEP Encryption Example 1.1 +Plaintext: \ +66 28 19 4e 12 07 3d b0 3b a9 4c da 9e f9 53 23 \ +97 d5 0d ba 79 b9 87 00 4a fe fe 34 +Seed: # not used yet\ +18 b7 76 ea 21 06 9d 69 77 6a 33 e9 6b ad 48 e1 \ +dd a0 a5 ef +Ciphertext: \ +35 4f e6 7b 4a 12 6d 5d 35 fe 36 c7 77 79 1a 3f \ +7b a1 3d ef 48 4e 2d 39 08 af f7 22 fa d4 68 fb \ +21 69 6d e9 5d 0b e9 11 c2 d3 17 4f 8a fc c2 01 \ +03 5f 7b 6d 8e 69 40 2d e5 45 16 18 c2 1a 53 5f \ +a9 d7 bf c5 b8 dd 9f c2 43 f8 cf 92 7d b3 13 22 \ +d6 e8 81 ea a9 1a 99 61 70 e6 57 a0 5a 26 64 26 \ +d9 8c 88 00 3f 84 77 c1 22 70 94 a0 d9 fa 1e 8c \ +40 24 30 9c e1 ec cc b5 21 00 35 d4 7a c7 2e 8a +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 1.2 +Plaintext: \ +75 0c 40 47 f5 47 e8 e4 14 11 85 65 23 29 8a c9\ +ba e2 45 ef af 13 97 fb e5 6f 9d d5 +Seed: # not used yet\ +0c c7 42 ce 4a 9b 7f 32 f9 51 bc b2 51 ef d9 25\ +fe 4f e3 5f +Ciphertext: \ +64 0d b1 ac c5 8e 05 68 fe 54 07 e5 f9 b7 01 df\ +f8 c3 c9 1e 71 6c 53 6f c7 fc ec 6c b5 b7 1c 11\ +65 98 8d 4a 27 9e 15 77 d7 30 fc 7a 29 93 2e 3f\ +00 c8 15 15 23 6d 8d 8e 31 01 7a 7a 09 df 43 52\ +d9 04 cd eb 79 aa 58 3a dc c3 1e a6 98 a4 c0 52\ +83 da ba 90 89 be 54 91 f6 7c 1a 4e e4 8d c7 4b\ +bb e6 64 3a ef 84 66 79 b4 cb 39 5a 35 2d 5e d1\ +15 91 2d f6 96 ff e0 70 29 32 94 6d 71 49 2b 44 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 1.3 +Plaintext: \ +d9 4a e0 83 2e 64 45 ce 42 33 1c b0 6d 53 1a 82\ +b1 db 4b aa d3 0f 74 6d c9 16 df 24 d4 e3 c2 45\ +1f ff 59 a6 42 3e b0 e1 d0 2d 4f e6 46 cf 69 9d\ +fd 81 8c 6e 97 b0 51 +Seed: # not used yet\ +25 14 df 46 95 75 5a 67 b2 88 ea f4 90 5c 36 ee\ +c6 6f d2 fd +Ciphertext: \ +42 37 36 ed 03 5f 60 26 af 27 6c 35 c0 b3 74 1b\ +36 5e 5f 76 ca 09 1b 4e 8c 29 e2 f0 be fe e6 03\ +59 5a a8 32 2d 60 2d 2e 62 5e 95 eb 81 b2 f1 c9\ +72 4e 82 2e ca 76 db 86 18 cf 09 c5 34 35 03 a4\ +36 08 35 b5 90 3b c6 37 e3 87 9f b0 5e 0e f3 26\ +85 d5 ae c5 06 7c d7 cc 96 fe 4b 26 70 b6 ea c3\ +06 6b 1f cf 56 86 b6 85 89 aa fb 7d 62 9b 02 d8\ +f8 62 5c a3 83 36 24 d4 80 0f b0 81 b1 cf 94 eb +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 1.4 +Plaintext: \ +52 e6 50 d9 8e 7f 2a 04 8b 4f 86 85 21 53 b9 7e\ +01 dd 31 6f 34 6a 19 f6 7a 85 +Seed: # not used yet\ +c4 43 5a 3e 1a 18 a6 8b 68 20 43 62 90 a3 7c ef\ +b8 5d b3 fb +Ciphertext: \ +45 ea d4 ca 55 1e 66 2c 98 00 f1 ac a8 28 3b 05\ +25 e6 ab ae 30 be 4b 4a ba 76 2f a4 0f d3 d3 8e\ +22 ab ef c6 97 94 f6 eb bb c0 5d db b1 12 16 24\ +7d 2f 41 2f d0 fb a8 7c 6e 3a cd 88 88 13 64 6f\ +d0 e4 8e 78 52 04 f9 c3 f7 3d 6d 82 39 56 27 22\ +dd dd 87 71 fe c4 8b 83 a3 1e e6 f5 92 c4 cf d4\ +bc 88 17 4f 3b 13 a1 12 aa e3 b9 f7 b8 0e 0f c6\ +f7 25 5b a8 80 dc 7d 80 21 e2 2a d6 a8 5f 07 55 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 1.5 +Plaintext: \ +8d a8 9f d9 e5 f9 74 a2 9f ef fb 46 2b 49 18 0f\ +6c f9 e8 02 +Seed: # not used yet\ +b3 18 c4 2d f3 be 0f 83 fe a8 23 f5 a7 b4 7e d5\ +e4 25 a3 b5 +Ciphertext: \ +36 f6 e3 4d 94 a8 d3 4d aa cb a3 3a 21 39 d0 0a\ +d8 5a 93 45 a8 60 51 e7 30 71 62 00 56 b9 20 e2\ +19 00 58 55 a2 13 a0 f2 38 97 cd cd 73 1b 45 25\ +7c 77 7f e9 08 20 2b ef dd 0b 58 38 6b 12 44 ea\ +0c f5 39 a0 5d 5d 10 32 9d a4 4e 13 03 0f d7 60\ +dc d6 44 cf ef 20 94 d1 91 0d 3f 43 3e 1c 7c 6d\ +d1 8b c1 f2 df 7f 64 3d 66 2f b9 dd 37 ea d9 05\ +91 90 f4 fa 66 ca 39 e8 69 c4 eb 44 9c bd c4 39 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 1.6 +Plaintext: \ +26 52 10 50 84 42 71 +Seed: # not used yet\ +e4 ec 09 82 c2 33 6f 3a 67 7f 6a 35 61 74 eb 0c\ +e8 87 ab c2 +Ciphertext: \ +42 ce e2 61 7b 1e ce a4 db 3f 48 29 38 6f bd 61\ +da fb f0 38 e1 80 d8 37 c9 63 66 df 24 c0 97 b4\ +ab 0f ac 6b df 59 0d 82 1c 9f 10 64 2e 68 1a d0\ +5b 8d 78 b3 78 c0 f4 6c e2 fa d6 3f 74 e0 ad 3d\ +f0 6b 07 5d 7e b5 f5 63 6f 8d 40 3b 90 59 ca 76\ +1b 5c 62 bb 52 aa 45 00 2e a7 0b aa ce 08 de d2\ +43 b9 d8 cb d6 2a 68 ad e2 65 83 2b 56 56 4e 43\ +a6 fa 42 ed 19 9a 09 97 69 74 2d f1 53 9e 82 55 +Test: DecryptMatch + +AlgorithmType: AsymmetricCipher +Name: RSA/OAEP-MGF1(SHA-1) +Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors +KeyFormat: Component +Comment: Example 2: A 1025-bit RSA Key Pair +Modulus: \ +01 94 7c 7f ce 90 42 5f 47 27 9e 70 85 1f 25 d5\ +e6 23 16 fe 8a 1d f1 93 71 e3 e6 28 e2 60 54 3e\ +49 01 ef 60 81 f6 8c 0b 81 41 19 0d 2a e8 da ba\ +7d 12 50 ec 6d b6 36 e9 44 ec 37 22 87 7c 7c 1d\ +0a 67 f1 4b 16 94 c5 f0 37 94 51 a4 3e 49 a3 2d\ +de 83 67 0b 73 da 91 a1 c9 9b c2 3b 43 6a 60 05\ +5c 61 0f 0b af 99 c1 a0 79 56 5b 95 a3 f1 52 66\ +32 d1 d4 da 60 f2 0e da 25 e6 53 c4 f0 02 76 6f\ +45 +PublicExponent: \ +01 00 01 +PrivateExponent: \ +08 23 f2 0f ad b5 da 89 08 8a 9d 00 89 3e 21 fa\ +4a 1b 11 fb c9 3c 64 a3 be 0b aa ea 97 fb 3b 93\ +c3 ff 71 37 04 c1 9c 96 3c 1d 10 7a ae 99 05 47\ +39 f7 9e 02 e1 86 de 86 f8 7a 6d de fe a6 d8 cc\ +d1 d3 c8 1a 47 bf a7 25 5b e2 06 01 a4 a4 b2 f0\ +8a 16 7b 5e 27 9d 71 5b 1b 45 5b dd 7e ab 24 59\ +41 d9 76 8b 9a ce fb 3c cd a5 95 2d a3 ce e7 25\ +25 b4 50 16 63 a8 ee 15 c9 e9 92 d9 24 62 fe 39 +Prime1: \ +01 59 db de 04 a3 3e f0 6f b6 08 b8 0b 19 0f 4d\ +3e 22 bc c1 3a c8 e4 a0 81 03 3a bf a4 16 ed b0\ +b3 38 aa 08 b5 73 09 ea 5a 52 40 e7 dc 6e 54 37\ +8c 69 41 4c 31 d9 7d db 1f 40 6d b3 76 9c c4 1a\ +43 +Prime2: \ +01 2b 65 2f 30 40 3b 38 b4 09 95 fd 6f f4 1a 1a\ +cc 8a da 70 37 32 36 b7 20 2d 39 b2 ee 30 cf b4\ +6d b0 95 11 f6 f3 07 cc 61 cc 21 60 6c 18 a7 5b\ +8a 62 f8 22 df 03 1b a0 df 0d af d5 50 6f 56 8b\ +d7 +ModPrime1PrivateExponent: \ +43 6e f5 08 de 73 65 19 c2 da 4c 58 0d 98 c8 2c\ +b7 45 2a 3f b5 ef ad c3 b9 c7 78 9a 1b c6 58 4f\ +79 5a dd bb d3 24 39 c7 46 86 55 2e cb 6c 2c 30\ +7a 4d 3a f7 f5 39 ee c1 57 24 8c 7b 31 f1 a2 55 +ModPrime2PrivateExponent: \ +01 2b 15 a8 9f 3d fb 2b 39 07 3e 73 f0 2b dd 0c\ +1a 7b 37 9d d4 35 f0 5c dd e2 ef f9 e4 62 94 8b\ +7c ec 62 ee 90 50 d5 e0 81 6e 07 85 a8 56 b4 91\ +08 dc b7 5f 36 83 87 4d 1c a6 32 9a 19 01 30 66\ +ff +MultiplicativeInverseOfPrime2ModPrime1: \ +02 70 db 17 d5 91 4b 01 8d 76 11 8b 24 38 9a 73\ +50 ec 83 6b 00 63 a2 17 21 23 6f d8 ed b6 d8 9b\ +51 e7 ee b8 7b 61 1b 71 32 cb 7e a7 35 6c 23 15\ +1c 1e 77 51 50 7c 78 6d 9e e1 79 41 70 a8 c8 e8 +Test: KeyPairValidAndConsistent +Comment: RSAES-OAEP Encryption Example 2.1 +Plaintext: \ +8f f0 0c aa 60 5c 70 28 30 63 4d 9a 6c 3d 42 c6\ +52 b5 8c f1 d9 2f ec 57 0b ee e7 +Seed: # not used yet\ +8c 40 7b 5e c2 89 9e 50 99 c5 3e 8c e7 93 bf 94\ +e7 1b 17 82 +Ciphertext: \ +01 81 af 89 22 b9 fc b4 d7 9d 92 eb e1 98 15 99\ +2f c0 c1 43 9d 8b cd 49 13 98 a0 f4 ad 3a 32 9a\ +5b d9 38 55 60 db 53 26 83 c8 b7 da 04 e4 b1 2a\ +ed 6a ac df 47 1c 34 c9 cd a8 91 ad dc c2 df 34\ +56 65 3a a6 38 2e 9a e5 9b 54 45 52 57 eb 09 9d\ +56 2b be 10 45 3f 2b 6d 13 c5 9c 02 e1 0f 1f 8a\ +bb 5d a0 d0 57 09 32 da cf 2d 09 01 db 72 9d 0f\ +ef cc 05 4e 70 96 8e a5 40 c8 1b 04 bc ae fe 72\ +0e +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 2.2 +Plaintext: \ +2d +Seed: # not used yet\ +b6 00 cf 3c 2e 50 6d 7f 16 77 8c 91 0d 3a 8b 00\ +3e ee 61 d5 +Ciphertext: \ +01 87 59 ff 1d f6 3b 27 92 41 05 62 31 44 16 a8\ +ae af 2a c6 34 b4 6f 94 0a b8 2d 64 db f1 65 ee\ +e3 30 11 da 74 9d 4b ab 6e 2f cd 18 12 9c 9e 49\ +27 7d 84 53 11 2b 42 9a 22 2a 84 71 b0 70 99 39\ +98 e7 58 86 1c 4d 3f 6d 74 9d 91 c4 29 0d 33 2c\ +7a 4a b3 f7 ea 35 ff 3a 07 d4 97 c9 55 ff 0f fc\ +95 00 6b 62 c6 d2 96 81 0d 9b fa b0 24 19 6c 79\ +34 01 2c 2d f9 78 ef 29 9a ba 23 99 40 cb a1 02\ +45 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 2.3 +Plaintext: \ +74 fc 88 c5 1b c9 0f 77 af 9d 5e 9a 4a 70 13 3d\ +4b 4e 0b 34 da 3c 37 c7 ef 8e +Seed: # not used yet\ +a7 37 68 ae ea a9 1f 9d 8c 1e d6 f9 d2 b6 34 67\ +f0 7c ca e3 +Ciphertext: \ +01 88 02 ba b0 4c 60 32 5e 81 c4 96 23 11 f2 be\ +7c 2a dc e9 30 41 a0 07 19 c8 8f 95 75 75 f2 c7\ +9f 1b 7b c8 ce d1 15 c7 06 b3 11 c0 8a 2d 98 6c\ +a3 b6 a9 33 6b 14 7c 29 c6 f2 29 40 9d de c6 51\ +bd 1f dd 5a 0b 7f 61 0c 99 37 fd b4 a3 a7 62 36\ +4b 8b 32 06 b4 ea 48 5f d0 98 d0 8f 63 d4 aa 8b\ +b2 69 7d 02 7b 75 0c 32 d7 f7 4e af 51 80 d2 e9\ +b6 6b 17 cb 2f a5 55 23 bc 28 0d a1 0d 14 be 20\ +53 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 2.4 +Plaintext: \ +a7 eb 2a 50 36 93 1d 27 d4 e8 91 32 6d 99 69 2f\ +fa dd a9 bf 7e fd 3e 34 e6 22 c4 ad c0 85 f7 21\ +df e8 85 07 2c 78 a2 03 b1 51 73 9b e5 40 fa 8c\ +15 3a 10 f0 0a +Seed: # not used yet\ +9a 7b 3b 0e 70 8b d9 6f 81 90 ec ab 4f b9 b2 b3\ +80 5a 81 56 +Ciphertext: \ +00 a4 57 8c bc 17 63 18 a6 38 fb a7 d0 1d f1 57\ +46 af 44 d4 f6 cd 96 d7 e7 c4 95 cb f4 25 b0 9c\ +64 9d 32 bf 88 6d a4 8f ba f9 89 a2 11 71 87 ca\ +fb 1f b5 80 31 76 90 e3 cc d4 46 92 0b 7a f8 2b\ +31 db 58 04 d8 7d 01 51 4a cb fa 91 56 e7 82 f8\ +67 f6 be d9 44 9e 0e 9a 2c 09 bc ec c6 aa 08 76\ +36 96 5e 34 b3 ec 76 6f 2f e2 e4 30 18 a2 fd de\ +b1 40 61 6a 0e 9d 82 e5 33 10 24 ee 06 52 fc 76\ +41 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 2.5 +Plaintext: \ +2e f2 b0 66 f8 54 c3 3f 3b dc bb 59 94 a4 35 e7\ +3d 6c 6c +Seed: # not used yet\ +eb 3c eb bc 4a dc 16 bb 48 e8 8c 8a ec 0e 34 af\ +7f 42 7f d3 +Ciphertext: \ +00 eb c5 f5 fd a7 7c fd ad 3c 83 64 1a 90 25 e7\ +7d 72 d8 a6 fb 33 a8 10 f5 95 0f 8d 74 c7 3e 8d\ +93 1e 86 34 d8 6a b1 24 62 56 ae 07 b6 00 5b 71\ +b7 f2 fb 98 35 12 18 33 1c e6 9b 8f fb dc 9d a0\ +8b bc 9c 70 4f 87 6d eb 9d f9 fc 2e c0 65 ca d8\ +7f 90 90 b0 7a cc 17 aa 7f 99 7b 27 ac a4 88 06\ +e8 97 f7 71 d9 51 41 fe 45 26 d8 a5 30 1b 67 86\ +27 ef ab 70 7f d4 0f be bd 6e 79 2a 25 61 3e 7a\ +ec +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 2.6 +Plaintext: \ +8a 7f b3 44 c8 b6 cb 2c f2 ef 1f 64 3f 9a 32 18\ +f6 e1 9b ba 89 c0 +Seed: # not used yet\ +4c 45 cf 4d 57 c9 8e 3d 6d 20 95 ad c5 1c 48 9e\ +b5 0d ff 84 +Ciphertext: \ +01 08 39 ec 20 c2 7b 90 52 e5 5b ef b9 b7 7e 6f\ +c2 6e 90 75 d7 a5 43 78 c6 46 ab df 51 e4 45 bd\ +57 15 de 81 78 9f 56 f1 80 3d 91 70 76 4a 9e 93\ +cb 78 79 86 94 02 3e e7 39 3c e0 4b c5 d8 f8 c5\ +a5 2c 17 1d 43 83 7e 3a ca 62 f6 09 eb 0a a5 ff\ +b0 96 0e f0 41 98 dd 75 4f 57 f7 fb e6 ab f7 65\ +cf 11 8b 4c a4 43 b2 3b 5a ab 26 6f 95 23 26 ac\ +45 81 10 06 44 32 5f 8b 72 1a cd 5d 04 ff 14 ef\ +3a +Test: DecryptMatch + +AlgorithmType: AsymmetricCipher +Name: RSA/OAEP-MGF1(SHA-1) +Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors +KeyFormat: Component +Comment: Example 3: A 1026-bit RSA Key Pair +Modulus: \ +02 b5 8f ec 03 9a 86 07 00 a4 d7 b6 46 2f 93 e6\ +cd d4 91 16 1d dd 74 f4 e8 10 b4 0e 3c 16 52 00\ +6a 5c 27 7b 27 74 c1 13 05 a4 cb ab 5a 78 ef a5\ +7e 17 a8 6d f7 a3 fa 36 fc 4b 1d 22 49 f2 2e c7\ +c2 dd 6a 46 32 32 ac ce a9 06 d6 6e be 80 b5 70\ +4b 10 72 9d a6 f8 33 23 4a bb 5e fd d4 a2 92 cb\ +fa d3 3b 4d 33 fa 7a 14 b8 c3 97 b5 6e 3a cd 21\ +20 34 28 b7 7c df a3 3a 6d a7 06 b3 d8 b0 fc 43\ +e9 +PublicExponent: \ +01 00 01 +PrivateExponent: \ +15 b4 8a 5b 56 83 a9 46 70 e2 3b 57 18 f8 14 fa\ +0e 13 f8 50 38 f5 07 11 18 2c ba 61 51 05 81 f3\ +d2 2c 7e 23 2e f9 37 e2 2e 55 1d 68 b8 6e 2f 8c\ +b1 aa d8 be 2e 48 8f 5d f7 ef d2 79 e3 f5 68 d4\ +ea f3 6f 80 cf 71 41 ac e6 0f cc 91 13 fb 6c 4a\ +84 1f d5 0b bc 7c 51 2f fc be ff 21 48 7a a8 11\ +eb 3c a8 c6 20 05 34 6a 86 de 86 bf a1 d8 a9 48\ +fd 3f 34 8c 22 ea ad f3 33 c3 ce 6c e1 32 08 fd +Prime1: \ +01 bf 01 d2 16 d7 35 95 cf 02 70 c2 be b7 8d 40\ +a0 d8 44 7d 31 da 91 9a 98 3f 7e ea 78 1b 77 d8\ +5f e3 71 b3 e9 37 3e 7b 69 21 7d 31 50 a0 2d 89\ +58 de 7f ad 9d 55 51 60 95 8b 44 54 12 7e 0e 7e\ +af +Prime2: \ +01 8d 33 99 65 81 66 db 38 29 81 6d 7b 29 54 16\ +75 9e 9c 91 98 7f 5b 2d 8a ec d6 3b 04 b4 8b d7\ +b2 fc f2 29 bb 7f 8a 6d c8 8b a1 3d d2 e3 9a d5\ +5b 6d 1a 06 16 07 08 f9 70 0b e8 0b 8f d3 74 4c\ +e7 +ModPrime1PrivateExponent: \ +06 c0 a2 49 d2 0a 6f 2e e7 5c 88 b4 94 d5 3f 6a\ +ae 99 aa 42 7c 88 c2 8b 16 3a 76 94 45 e5 f3 90\ +cf 40 c2 74 fd 6e a6 32 9a 5c e7 c7 ce 03 a2 15\ +83 96 ee 2a 78 45 78 6e 09 e2 88 5a 97 28 e4 e5 +ModPrime2PrivateExponent: \ +d1 d2 7c 29 fe dd 92 d8 6c 34 8e dd 0c cb fa c1\ +4f 74 6e 05 1c e1 d1 81 1d f3 5d 61 f2 ee 1c 97\ +d4 bf 28 04 80 2f 64 27 18 7b a8 e9 0a 8a f4 42\ +43 b4 07 9b 03 44 5e 60 2e 29 fa 51 93 e6 4f e9 +MultiplicativeInverseOfPrime2ModPrime1: \ +8c b2 f7 56 bd 89 41 b1 d3 b7 70 e5 ad 31 ee 37\ +3b 28 ac da 69 ff 9b 6f 40 fe 57 8b 9f 1a fb 85\ +83 6f 96 27 d3 7a cf f7 3c 27 79 e6 34 bb 26 01\ +1c 2c 8f 7f 33 61 ae 2a 9e a6 5e d6 89 e3 63 9a +Test: KeyPairValidAndConsistent +Comment: RSAES-OAEP Encryption Example 3.1 +Plaintext: \ +08 78 20 b5 69 e8 fa 8d +Seed: # not used yet\ +8c ed 6b 19 62 90 80 57 90 e9 09 07 40 15 e6 a2\ +0b 0c 48 94 +Ciphertext: \ +02 6a 04 85 d9 6a eb d9 6b 43 82 08 50 99 b9 62\ +e6 a2 bd ec 3d 90 c8 db 62 5e 14 37 2d e8 5e 2d\ +5b 7b aa b6 5c 8f af 91 bb 55 04 fb 49 5a fc e5\ +c9 88 b3 f6 a5 2e 20 e1 d6 cb d3 56 6c 5c d1 f2\ +b8 31 8b b5 42 cc 0e a2 5c 4a ab 99 32 af a2 07\ +60 ea dd ec 78 43 96 a0 7e a0 ef 24 d4 e6 f4 d3\ +7e 50 52 a7 a3 1e 14 6a a4 80 a1 11 bb e9 26 40\ +13 07 e0 0f 41 00 33 84 2b 6d 82 fe 5c e4 df ae\ +80 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 3.2 +Plaintext: \ +46 53 ac af 17 19 60 b0 1f 52 a7 be 63 a3 ab 21\ +dc 36 8e c4 3b 50 d8 2e c3 78 1e 04 +Seed: # not used yet\ +b4 29 1d 65 67 55 08 48 cc 15 69 67 c8 09 ba ab\ +6c a5 07 f0 +Ciphertext: \ +02 4d b8 9c 78 02 98 9b e0 78 38 47 86 30 84 94\ +1b f2 09 d7 61 98 7e 38 f9 7c b5 f6 f1 bc 88 da\ +72 a5 0b 73 eb af 11 c8 79 c4 f9 5d f3 7b 85 0b\ +8f 65 d7 62 2e 25 b1 b8 89 e8 0f e8 0b ac a2 06\ +9d 6e 0e 1d 82 99 53 fc 45 90 69 de 98 ea 97 98\ +b4 51 e5 57 e9 9a bf 8f e3 d9 cc f9 09 6e bb f3\ +e5 25 5d 3b 4e 1c 6d 2e ca df 06 7a 35 9e ea 86\ +40 5a cd 47 d5 e1 65 51 7c ca fd 47 d6 db ee 4b\ +f5 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 3.3 +Plaintext: \ +d9 4c d0 e0 8f a4 04 ed 89 +Seed: # not used yet\ +ce 89 28 f6 05 95 58 25 40 08 ba dd 97 94 fa dc\ +d2 fd 1f 65 +Ciphertext: \ +02 39 bc e6 81 03 24 41 52 88 77 d6 d1 c8 bb 28\ +aa 3b c9 7f 1d f5 84 56 36 18 99 57 97 68 38 44\ +ca 86 66 47 32 f4 be d7 a0 aa b0 83 aa ab fb 72\ +38 f5 82 e3 09 58 c2 02 4e 44 e5 70 43 b9 79 50\ +fd 54 3d a9 77 c9 0c dd e5 33 7d 61 84 42 f9 9e\ +60 d7 78 3a b5 9c e6 dd 9d 69 c4 7a d1 e9 62 be\ +c2 2d 05 89 5c ff 8d 3f 64 ed 52 61 d9 2b 26 78\ +51 03 93 48 49 90 ba 3f 7f 06 81 8a e6 ff ce 8a\ +3a +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 3.4 +Plaintext: \ +6c c6 41 b6 b6 1e 6f 96 39 74 da d2 3a 90 13 28\ +4e f1 +Seed: # not used yet\ +6e 29 79 f5 2d 68 14 a5 7d 83 b0 90 05 48 88 f1\ +19 a5 b9 a3 +Ciphertext: \ +02 99 4c 62 af d7 6f 49 8b a1 fd 2c f6 42 85 7f\ +ca 81 f4 37 3c b0 8f 1c ba ee 6f 02 5c 3b 51 2b\ +42 c3 e8 77 91 13 47 66 48 03 9d be 04 93 f9 24\ +62 92 fa c2 89 50 60 0e 7c 0f 32 ed f9 c8 1b 9d\ +ec 45 c3 bd e0 cc 8d 88 47 59 01 69 90 7b 7d c5\ +99 1c eb 29 bb 07 14 d6 13 d9 6d f0 f1 2e c5 d8\ +d3 50 7c 8e e7 ae 78 dd 83 f2 16 fa 61 de 10 03\ +63 ac a4 8a 7e 91 4a e9 f4 2d df be 94 3b 09 d9\ +a0 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 3.5 +Plaintext: \ +df 51 51 83 2b 61 f4 f2 58 91 fb 41 72 f3 28 d2\ +ed df 83 71 ff cf db e9 97 93 92 95 f3 0e ca 69\ +18 01 7c fd a1 15 3b f7 a6 af 87 59 32 23 +Seed: # not used yet\ +2d 76 0b fe 38 c5 9d e3 4c dc 8b 8c 78 a3 8e 66\ +28 4a 2d 27 +Ciphertext: \ +01 62 04 2f f6 96 95 92 a6 16 70 31 81 1a 23 98\ +34 ce 63 8a bf 54 fe c8 b9 94 78 12 2a fe 2e e6\ +7f 8c 5b 18 b0 33 98 05 bf db c5 a4 e6 72 0b 37\ +c5 9c fb a9 42 46 4c 59 7f f5 32 a1 19 82 15 45\ +fd 2e 59 b1 14 e6 1d af 71 82 05 29 f5 02 9c f5\ +24 95 43 27 c3 4e c5 e6 f5 ba 7e fc c4 de 94 3a\ +b8 ad 4e d7 87 b1 45 43 29 f7 0d b7 98 a3 a8 f4\ +d9 2f 82 74 e2 b2 94 8a de 62 7c e8 ee 33 e4 3c\ +60 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 3.6 +Plaintext: \ +3c 3b ad 89 3c 54 4a 6d 52 0a b0 22 31 91 88 c8\ +d5 04 b7 a7 88 b8 50 90 3b 85 97 2e aa 18 55 2e\ +11 34 a7 ad 60 98 82 62 54 ff 7a b6 72 b3 d8 eb\ +31 58 fa c6 d4 cb ae f1 +Seed: # not used yet\ +f1 74 77 9c 5f d3 cf e0 07 ba dc b7 a3 6c 9b 55\ +bf cf bf 0e +Ciphertext: \ +00 11 20 51 e7 5d 06 49 43 bc 44 78 07 5e 43 48\ +2f d5 9c ee 06 79 de 68 93 ee c3 a9 43 da a4 90\ +b9 69 1c 93 df c0 46 4b 66 23 b9 f3 db d3 e7 00\ +83 26 4f 03 4b 37 4f 74 16 4e 1a 00 76 37 25 e5\ +74 74 4b a0 b9 db 83 43 4f 31 df 96 f6 e2 a2 6f\ +6d 8e ba 34 8b d4 68 6c 22 38 ac 07 c3 7a ac 37\ +85 d1 c7 ee a2 f8 19 fd 91 49 17 98 ed 8e 9c ef\ +5e 43 b7 81 b0 e0 27 6e 37 c4 3f f9 49 2d 00 57\ +30 +Test: DecryptMatch + +AlgorithmType: AsymmetricCipher +Name: RSA/OAEP-MGF1(SHA-1) +Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors +KeyFormat: Component +Comment: Example 4: A 1027-bit RSA Key Pair +Modulus: \ +05 12 40 b6 cc 00 04 fa 48 d0 13 46 71 c0 78 c7\ +c8 de c3 b3 e2 f2 5b c2 56 44 67 33 9d b3 88 53\ +d0 6b 85 ee a5 b2 de 35 3b ff 42 ac 2e 46 bc 97\ +fa e6 ac 96 18 da 95 37 a5 c8 f5 53 c1 e3 57 62\ +59 91 d6 10 8d cd 78 85 fb 3a 25 41 3f 53 ef ca\ +d9 48 cb 35 cd 9b 9a e9 c1 c6 76 26 d1 13 d5 7d\ +de 4c 5b ea 76 bb 5b b7 de 96 c0 0d 07 37 2e 96\ +85 a6 d7 5c f9 d2 39 fa 14 8d 70 93 1b 5f 3f b0\ +39 +PublicExponent: \ +01 00 01 +PrivateExponent: \ +04 11 ff ca 3b 7c a5 e9 e9 be 7f e3 8a 85 10 5e\ +35 38 96 db 05 c5 79 6a ec d2 a7 25 16 1e b3 65\ +1c 86 29 a9 b8 62 b9 04 d7 b0 c7 b3 7f 8c b5 a1\ +c2 b5 40 01 01 8a 00 a1 eb 2c af e4 ee 4e 94 92\ +c3 48 bc 2b ed ab 4b 9e bb f0 64 e8 ef f3 22 b9\ +00 9f 8e ec 65 39 05 f4 0d f8 8a 3c dc 49 d4 56\ +7f 75 62 7d 41 ac a6 24 12 9b 46 a0 b7 c6 98 e5\ +e6 5f 2b 7b a1 02 c7 49 a1 01 35 b6 54 0d 04 01 +Prime1: \ +02 74 58 c1 9e c1 63 69 19 e7 36 c9 af 25 d6 09\ +a5 1b 8f 56 1d 19 c6 bf 69 43 dd 1e e1 ab 8a 4a\ +3f 23 21 00 bd 40 b8 8d ec c6 ba 23 55 48 b6 ef\ +79 2a 11 c9 de 82 3d 0a 79 22 c7 09 5b 6e ba 57\ +01 +Prime2: \ +02 10 ee 9b 33 ab 61 71 6e 27 d2 51 bd 46 5f 4b\ +35 a1 a2 32 e2 da 00 90 1c 29 4b f2 23 50 ce 49\ +0d 09 9f 64 2b 53 75 61 2d b6 3b a1 f2 03 86 49\ +2b f0 4d 34 b3 c2 2b ce b9 09 d1 34 41 b5 3b 51\ +39 +ModPrime1PrivateExponent: \ +39 fa 02 8b 82 6e 88 c1 12 1b 75 0a 8b 24 2f a9\ +a3 5c 5b 66 bd fd 1f a6 37 d3 cc 48 a8 4a 4f 45\ +7a 19 4e 77 27 e4 9f 7b cc 6e 5a 5a 41 26 57 fc\ +47 0c 73 22 eb c3 74 16 ef 45 8c 30 7a 8c 09 01 +ModPrime2PrivateExponent: \ +01 5d 99 a8 41 95 94 39 79 fa 9e 1b e2 c3 c1 b6\ +9f 43 2f 46 fd 03 e4 7d 5b ef bb bf d6 b1 d1 37\ +1d 83 ef b3 30 a3 e0 20 94 2b 2f ed 11 5e 5d 02\ +be 24 fd 92 c9 01 9d 1c ec d6 dd 4c f1 e5 4c c8\ +99 +MultiplicativeInverseOfPrime2ModPrime1: \ +01 f0 b7 01 51 70 b3 f5 e4 22 23 ba 30 30 1c 41\ +a6 d8 7c bb 70 e3 0c b7 d3 c6 7d 25 47 3d b1 f6\ +cb f0 3e 3f 91 26 e3 e9 79 68 27 9a 86 5b 2c 2b\ +42 65 24 cf c5 2a 68 3d 31 ed 30 eb 98 4b e4 12\ +ba +Test: KeyPairValidAndConsistent +Comment: RSAES-OAEP Encryption Example 4.1 +Plaintext: \ +4a 86 60 95 34 ee 43 4a 6c bc a3 f7 e9 62 e7 6d\ +45 5e 32 64 c1 9f 60 5f 6e 5f f6 13 7c 65 c5 6d\ +7f b3 44 cd 52 bc 93 37 4f 3d 16 6c 9f 0c 6f 9c\ +50 6b ad 19 33 09 72 d2 +Seed: # not used yet\ +1c ac 19 ce 99 3d ef 55 f9 82 03 f6 85 28 96 c9\ +5c cc a1 f3 +Ciphertext: \ +04 cc e1 96 14 84 5e 09 41 52 a3 fe 18 e5 4e 33\ +30 c4 4e 5e fb c6 4a e1 68 86 cb 18 69 01 4c c5\ +78 1b 1f 8f 9e 04 53 84 d0 11 2a 13 5c a0 d1 2e\ +9c 88 a8 e4 06 34 16 de aa e3 84 4f 60 d6 e9 6f\ +e1 55 14 5f 45 25 b9 a3 44 31 ca 37 66 18 0f 70\ +e1 5a 5e 5d 8e 8b 1a 51 6f f8 70 60 9f 13 f8 96\ +93 5c ed 18 82 79 a5 8e d1 3d 07 11 42 77 d7 5c\ +65 68 60 7e 0a b0 92 fd 80 3a 22 3e 4a 8e e0 b1\ +a8 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 4.2 +Plaintext: \ +b0 ad c4 f3 fe 11 da 59 ce 99 27 73 d9 05 99 43\ +c0 30 46 49 7e e9 d9 f9 a0 6d f1 16 6d b4 6d 98\ +f5 8d 27 ec 07 4c 02 ee e6 cb e2 44 9c 8b 9f c5\ +08 0c 5c 3f 44 33 09 25 12 ec 46 aa 79 37 43 c8 +Seed: # not used yet\ +f5 45 d5 89 75 85 e3 db 71 aa 0c b8 da 76 c5 1d\ +03 2a e9 63 +Ciphertext: \ +00 97 b6 98 c6 16 56 45 b3 03 48 6f bf 5a 2a 44\ +79 c0 ee 85 88 9b 54 1a 6f 0b 85 8d 6b 65 97 b1\ +3b 85 4e b4 f8 39 af 03 39 9a 80 d7 9b da 65 78\ +c8 41 f9 0d 64 57 15 b2 80 d3 71 43 99 2d d1 86\ +c8 0b 94 9b 77 5c ae 97 37 0e 4e c9 74 43 13 6c\ +6d a4 84 e9 70 ff db 13 23 a2 08 47 82 1d 3b 18\ +38 1d e1 3b b4 9a ae a6 65 30 c4 a4 b8 27 1f 3e\ +ae 17 2c d3 66 e0 7e 66 36 f1 01 9d 2a 28 ae d1\ +5e +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 4.3 +Plaintext: \ +bf 6d 42 e7 01 70 7b 1d 02 06 b0 c8 b4 5a 1c 72\ +64 1f f1 28 89 21 9a 82 bd ea 96 5b 5e 79 a9 6b\ +0d 01 63 ed 9d 57 8e c9 ad a2 0f 2f bc f1 ea 3c\ +40 89 d8 34 19 ba 81 b0 c6 0f 36 06 da 99 +Seed: # not used yet\ +ad 99 7f ee f7 30 d6 ea 7b e6 0d 0d c5 2e 72 ea\ +cb fd d2 75 +Ciphertext: \ +03 01 f9 35 e9 c4 7a bc b4 8a cb be 09 89 5d 9f\ +59 71 af 14 83 9d a4 ff 95 41 7e e4 53 d1 fd 77\ +31 90 72 bb 72 97 e1 b5 5d 75 61 cd 9d 1b b2 4c\ +1a 9a 37 c6 19 86 43 08 24 28 04 87 9d 86 eb d0\ +01 dc e5 18 39 75 e1 50 69 89 b7 0e 5a 83 43 41\ +54 d5 cb fd 6a 24 78 7e 60 eb 0c 65 8d 2a c1 93\ +30 2d 11 92 c6 e6 22 d4 a1 2a d4 b5 39 23 bc a2\ +46 df 31 c6 39 5e 37 70 2c 6a 78 ae 08 1f b9 d0\ +65 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 4.4 +Plaintext: \ +fb 2e f1 12 f5 e7 66 eb 94 01 92 97 93 47 94 f7\ +be 2f 6f c1 c5 8e +Seed: # not used yet\ +13 64 54 df 57 30 f7 3c 80 7a 7e 40 d8 c1 a3 12\ +ac 5b 9d d3 +Ciphertext: \ +02 d1 10 ad 30 af b7 27 be b6 91 dd 0c f1 7d 0a\ +f1 a1 e7 fa 0c c0 40 ec 1a 4b a2 6a 42 c5 9d 0a\ +79 6a 2e 22 c8 f3 57 cc c9 8b 65 19 ac eb 68 2e\ +94 5e 62 cb 73 46 14 a5 29 40 7c d4 52 be e3 e4\ +4f ec e8 42 3c c1 9e 55 54 8b 8b 99 4b 84 9c 7e\ +cd e4 93 3e 76 03 7e 1d 0c e4 42 75 b0 87 10 c6\ +8e 43 01 30 b9 29 73 0e d7 7e 09 b0 15 64 2c 55\ +93 f0 4e 4f fb 94 10 79 81 02 a8 e9 6f fd fe 11\ +e4 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 4.5 +Plaintext: \ +28 cc d4 47 bb 9e 85 16 6d ab b9 e5 b7 d1 ad ad\ +c4 b9 d3 9f 20 4e 96 d5 e4 40 ce 9a d9 28 bc 1c\ +22 84 +Seed: # not used yet\ +bc a8 05 7f 82 4b 2e a2 57 f2 86 14 07 ee f6 3d\ +33 20 86 81 +Ciphertext: \ +00 db b8 a7 43 9d 90 ef d9 19 a3 77 c5 4f ae 8f\ +e1 1e c5 8c 3b 85 83 62 e2 3a d1 b8 a4 43 10 79\ +90 66 b9 93 47 aa 52 56 91 d2 ad c5 8d 9b 06 e3\ +4f 28 8c 17 03 90 c5 f0 e1 1c 0a a3 64 59 59 f1\ +8e e7 9e 8f 2b e8 d7 ac 5c 23 d0 61 f1 8d d7 4b\ +8c 5f 2a 58 fc b5 eb 0c 54 f9 9f 01 a8 32 47 56\ +82 92 53 65 83 34 09 48 d7 a8 c9 7c 4a cd 1e 98\ +d1 e2 9d c3 20 e9 7a 26 05 32 a8 aa 7a 75 8a 1e\ +c2 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 4.6 +Plaintext: \ +f2 22 42 75 1e c6 b1 +Seed: # not used yet\ +2e 7e 1e 17 f6 47 b5 dd d0 33 e1 54 72 f9 0f 68\ +12 f3 ac 4e +Ciphertext: \ +00 a5 ff a4 76 8c 8b be ca ee 2d b7 7e 8f 2e ec\ +99 59 59 33 54 55 20 83 5e 5b a7 db 94 93 d3 e1\ +7c dd ef e6 a5 f5 67 62 44 71 90 8d b4 e2 d8 3a\ +0f be e6 06 08 fc 84 04 95 03 b2 23 4a 07 dc 83\ +b2 7b 22 84 7a d8 92 0f f4 2f 67 4e f7 9b 76 28\ +0b 00 23 3d 2b 51 b8 cb 27 03 a9 d4 2b fb c8 25\ +0c 96 ec 32 c0 51 e5 7f 1b 4b a5 28 db 89 c3 7e\ +4c 54 e2 7e 6e 64 ac 69 63 5a e8 87 d9 54 16 19\ +a9 +Test: DecryptMatch + +AlgorithmType: AsymmetricCipher +Name: RSA/OAEP-MGF1(SHA-1) +Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors +KeyFormat: Component +Comment: Example 5: A 1028-bit RSA Key Pair +Modulus: \ +0a ad f3 f9 c1 25 e5 d8 91 f3 1a c4 48 e9 93 de\ +fe 58 0f 80 2b 45 f9 d7 f2 2b a5 02 1e 9c 47 57\ +6b 5a 1e 68 03 1b a9 db 4e 6d ab e4 d9 6a 1d 6f\ +3d 26 72 68 cf f4 08 00 5f 11 8e fc ad b9 98 88\ +d1 c2 34 46 71 66 b2 a2 b8 49 a0 5a 88 9c 06 0a\ +c0 da 0c 5f ae 8b 55 f3 09 ba 62 e7 03 74 2f a0\ +32 6f 2d 10 b0 11 02 14 89 ff 49 77 70 19 0d 89\ +5f d3 9f 52 29 3c 39 ef d7 3a 69 8b da b9 f1 0e\ +d9 +PublicExponent: \ +01 00 01 +PrivateExponent: \ +02 56 eb 4c ba 70 67 f2 d2 be 54 0d cd ff 45 82\ +a3 6b 7d 31 d1 c9 09 9b b2 14 b7 98 48 46 6a 26\ +8f 80 f5 8a 49 ac 04 c0 e3 64 89 34 a0 20 6c 04\ +53 7c 19 b2 36 64 3a 60 82 73 21 44 df 75 fa 21\ +75 88 f7 94 68 2b e8 91 68 27 6d c7 26 c5 c0 cb\ +db 84 d3 1b bf 26 d0 a4 3a f4 95 71 7f 7d 52 8a\ +cf ee 34 15 61 f6 ff 3c ae 05 c5 78 f8 47 0d 96\ +82 f9 c0 d0 72 f9 f6 06 8b 56 d5 88 0f 68 2b e2\ +c5 +Prime1: \ +03 b0 d3 96 2f 6d 17 54 9c bf ca 11 29 43 48 dc\ +f0 e7 e3 9f 8c 2b c6 82 4f 21 64 b6 06 d6 87 86\ +0d ae 1e 63 23 93 cf ed f5 13 22 82 29 06 9e 2f\ +60 e4 ac d7 e6 33 a4 36 06 3f 82 38 5f 48 99 37\ +07 +Prime2: \ +02 e4 c3 2e 2f 51 72 69 b7 07 23 09 f0 0c 0e 31\ +36 5f 7c e2 8b 23 6b 82 91 2d f2 39 ab f3 95 72\ +cf 0e d6 04 b0 29 82 e5 35 64 c5 2d 6a 05 39 7d\ +e5 c0 52 a2 fd dc 14 1e f7 18 98 36 34 6a eb 33\ +1f +ModPrime1PrivateExponent: \ +01 e8 4b 11 9d 25 16 1f a6 7b 00 25 6a 5b d9 b6\ +45 d2 b2 32 ec b0 5b 01 51 80 02 9a 88 62 2a dc\ +3f 09 b3 ae ac de 61 61 ab 7c de 22 c2 ad 26 e7\ +79 7d f5 4e 07 2c bd 3b 26 73 80 0b 3e 43 38 db\ +d5 +ModPrime2PrivateExponent: \ +eb 90 aa 1a 40 13 5b 4c ea 07 19 7c ed c8 81 9b\ +e1 e7 cb ff 25 47 66 21 16 f4 65 a4 a9 f4 87 ab\ +12 f3 ba 4f ef 13 82 22 65 a6 52 97 d9 8b 7b de\ +d9 37 2e 3f fe 81 a3 8b 3e 96 00 fe d0 55 75 4f +MultiplicativeInverseOfPrime2ModPrime1: \ +01 2f 7f 81 38 f9 40 40 62 eb 85 a4 29 24 52 0b\ +38 f5 bb 88 6a 01 96 f4 8b b8 dc ea 60 fd 92 cc\ +02 7f 18 e7 81 58 a3 4a 5c 5d 5f 86 0a 0f 6c 04\ +07 1a 7d 01 31 2c 06 50 62 f1 eb 48 b7 9d 1c 83\ +cb +Test: KeyPairValidAndConsistent +Comment: RSAES-OAEP Encryption Example 5.1 +Plaintext: \ +af 71 a9 01 e3 a6 1d 31 32 f0 fc 1f db 47 4f 9e\ +a6 57 92 57 ff c2 4d 16 41 70 14 5b 3d bd e8 +Seed: # not used yet\ +44 c9 2e 28 3f 77 b9 49 9c 60 3d 96 36 60 c8 7d\ +2f 93 94 61 +Ciphertext: \ +03 60 46 a4 a4 7d 9e d3 ba 9a 89 13 9c 10 50 38\ +eb 74 92 b0 5a 5d 68 bf d5 3a cc ff 45 97 f7 a6\ +86 51 b4 7b 4a 46 27 d9 27 e4 85 ee d7 b4 56 64\ +20 e8 b4 09 87 9e 5d 60 6e ae 25 1d 22 a5 df 79\ +9f 79 20 bf c1 17 b9 92 57 2a 53 b1 26 31 46 bc\ +ea 03 38 5c c5 e8 53 c9 a1 01 c8 c3 e1 bd a3 1a\ +51 98 07 49 6c 6c b5 e5 ef b4 08 82 3a 35 2b 8f\ +a0 66 1f b6 64 ef ad d5 93 de b9 9f ff 5e d0 00\ +e5 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 5.2 +Plaintext: \ +a3 b8 44 a0 82 39 a8 ac 41 60 5a f1 7a 6c fd a4\ +d3 50 13 65 85 90 3a 41 7a 79 26 87 60 51 9a 4b\ +4a c3 30 3e c7 3f 0f 87 cf b3 23 99 +Seed: # not used yet\ +cb 28 f5 86 06 59 fc ee e4 9c 3e ea fc e6 25 a7\ +08 03 bd 32 +Ciphertext: \ +03 d6 eb 65 4e dc e6 15 bc 59 f4 55 26 5e d4 e5\ +a1 82 23 cb b9 be 4e 40 69 b4 73 80 4d 5d e9 6f\ +54 dc aa a6 03 d0 49 c5 d9 4a a1 47 0d fc d2 25\ +40 66 b7 c7 b6 1f f1 f6 f6 77 0e 32 15 c5 13 99\ +fd 4e 34 ec 50 82 bc 48 f0 89 84 0a d0 43 54 ae\ +66 dc 0f 1b d1 8e 46 1a 33 cc 12 58 b4 43 a2 83\ +7a 6d f2 67 59 aa 23 02 33 49 86 f8 73 80 c9 cc\ +9d 53 be 9f 99 60 5d 2c 9a 97 da 7b 09 15 a4 a7\ +ad +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 5.3 +Plaintext: \ +30 8b 0e cb d2 c7 6c b7 7f c6 f7 0c 5e dd 23 3f\ +d2 f2 09 29 d6 29 f0 26 95 3b b6 2a 8f 4a 3a 31\ +4b de 19 5d e8 5b 5f 81 6d a2 aa b0 74 d2 6c b6\ +ac dd f3 23 ae 3b 9c 67 8a c3 cf 12 fb dd e7 +Seed: # not used yet\ +22 85 f4 0d 77 04 82 f9 a9 ef a2 c7 2c b3 ac 55\ +71 6d c0 ca +Ciphertext: \ +07 70 95 21 81 64 9f 9f 9f 07 ff 62 6f f3 a2 2c\ +35 c4 62 44 3d 90 5d 45 6a 9f d0 bf f4 3c ac 2c\ +a7 a9 f5 54 e9 47 8b 9a cc 3a c8 38 b0 20 40 ff\ +d3 e1 84 7d e2 e4 25 39 29 f9 dd 9e e4 04 43 25\ +a9 b0 5c ab b8 08 b2 ee 84 0d 34 e1 5d 10 5a 3f\ +1f 7b 27 69 5a 1a 07 a2 d7 3f e0 8e ca aa 3c 9c\ +9d 4d 5a 89 ff 89 0d 54 72 7d 7a e4 0c 0e c1 a8\ +dd 86 16 5d 8e e2 c6 36 81 41 01 6a 48 b5 5b 69\ +67 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 5.4 +Plaintext: \ +15 c5 b9 ee 11 85 +Seed: # not used yet\ +49 fa 45 d3 a7 8d d1 0d fd 57 73 99 d1 eb 00 af\ +7e ed 55 13 +Ciphertext: \ +08 12 b7 67 68 eb cb 64 2d 04 02 58 e5 f4 44 1a\ +01 85 21 bd 96 68 7e 6c 5e 89 9f cd 6c 17 58 8f\ +f5 9a 82 cc 8a e0 3a 4b 45 b3 12 99 af 17 88 c3\ +29 f7 dc d2 85 f8 cf 4c ed 82 60 6b 97 61 26 71\ +a4 5b ed ca 13 34 42 14 4d 16 17 d1 14 f8 02 85\ +7f 0f 9d 73 97 51 c5 7a 3f 9e e4 00 91 2c 61 e2\ +e6 99 2b e0 31 a4 3d d4 8f a6 ba 14 ee f7 c4 22\ +b5 ed c4 e7 af a0 4f dd 38 f4 02 d1 c8 bb 71 9a\ +bf +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 5.5 +Plaintext: \ +21 02 6e 68 00 c7 fa 72 8f ca ab a0 d1 96 ae 28\ +d7 a2 ac 4f fd 8a bc e7 94 f0 98 5f 60 c8 a6 73\ +72 77 36 5d 3f ea 11 db 89 23 a2 02 9a +Seed: # not used yet\ +f0 28 74 13 23 4c c5 03 47 24 a0 94 c4 58 6b 87\ +af f1 33 fc +Ciphertext: \ +07 b6 0e 14 ec 95 4b fd 29 e6 0d 00 47 e7 89 f5\ +1d 57 18 6c 63 58 99 03 30 67 93 ce d3 f6 82 41\ +c7 43 52 9a ba 6a 63 74 f9 2e 19 e0 16 3e fa 33\ +69 7e 19 6f 76 61 df aa a4 7a ac 6b de 5e 51 de\ +b5 07 c7 2c 58 9a 2c a1 69 3d 96 b1 46 03 81 24\ +9b 2c db 9e ac 44 76 9f 24 89 c5 d3 d2 f9 9f 0e\ +e3 c7 ee 5b f6 4a 5a c7 9c 42 bd 43 3f 14 9b e8\ +cb 59 54 83 61 64 05 95 51 3c 97 af 7b c2 50 97\ +23 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 5.6 +Plaintext: \ +54 1e 37 b6 8b 6c 88 72 b8 4c 02 +Seed: # not used yet\ +d9 fb a4 5c 96 f2 1e 6e 26 d2 9e b2 cd cb 65 85\ +be 9c b3 41 +Ciphertext: \ +08 c3 6d 4d da 33 42 3b 2e d6 83 0d 85 f6 41 1b\ +a1 dc f4 70 a1 fa e0 eb ef ee 7c 08 9f 25 6c ef\ +74 cb 96 ea 69 c3 8f 60 f3 9a be e4 41 29 bc b4\ +c9 2d e7 f7 97 62 3b 20 07 4e 3d 9c 28 99 70 1e\ +d9 07 1e 1e fa 0b dd 84 d4 c3 e5 13 03 02 d8 f0\ +24 0b ab a4 b8 4a 71 cc 03 2f 22 35 a5 ff 0f ae\ +27 7c 3e 8f 91 12 be f4 4c 9a e2 0d 17 5f c9 a4\ +05 8b fc 93 0b a3 1b 02 e2 e4 f4 44 48 37 10 f2\ +4a +Test: DecryptMatch + +AlgorithmType: AsymmetricCipher +Name: RSA/OAEP-MGF1(SHA-1) +Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors +KeyFormat: Component +Comment: Example 6: A 1029-bit RSA Key Pair +Modulus: \ +12 b1 7f 6d ad 2e cd 19 ff 46 dc 13 f7 86 0f 09\ +e0 e0 cf b6 77 b3 8a 52 59 23 05 ce af 02 2c 16\ +6d b9 0d 04 ac 29 e3 3f 7d d1 2d 9f af 66 e0 81\ +6b b6 3e ad 26 7c c7 d4 6c 17 c3 7b e2 14 bc a2\ +a2 2d 72 3a 64 e4 44 07 43 6b 6f c9 65 72 9a ef\ +c2 55 4f 37 6c d5 dc ea 68 29 37 80 a6 2b f3 9d\ +00 29 48 5a 16 0b bb 9e 5d c0 97 2d 21 a5 04 f5\ +2e 5e e0 28 aa 41 63 32 f5 10 b2 e9 cf f5 f7 22\ +af +PublicExponent: \ +01 00 01 +PrivateExponent: \ +02 95 ec a3 56 06 18 36 95 59 ce cd 30 3a a9 cf\ +da fc 1d 9f 06 95 9d f7 5f fe f9 29 aa 89 69 61\ +bc d1 90 dc 69 97 ed a7 f5 96 3e 72 4d 07 b4 dc\ +11 f3 06 5e 5a e9 7d 96 83 51 12 28 0b 90 84 bb\ +14 f2 a2 1e bd 4e 88 9d 41 b9 c4 13 2e c1 95 6f\ +ca b8 bb 2f ed 05 75 88 49 36 52 2c 5f f7 d3 32\ +61 90 48 24 e7 ca de e4 e0 bb 37 2d 24 57 cf 78\ +e2 bd 12 86 22 8f f8 3f 10 73 1c e6 3c 90 cf f3\ +f9 +Prime1: \ +04 a6 ce 8b 73 58 df a6 9b dc f7 42 61 70 05 af\ +b5 38 5f 5f 3a 58 a2 4e f7 4a 22 a8 c0 5c b7 cc\ +38 eb d4 cc 9d 9a 9d 78 9a 62 cd 0f 60 f0 cb 94\ +1d 34 23 c9 69 2e fa 4f e3 ad ff 29 0c 47 49 a3\ +8b +Prime2: \ +04 04 c9 a8 03 37 1f ed b4 c5 be 39 f3 c0 0b 00\ +9e 5e 08 a6 3b e1 e4 00 35 cd ac a5 01 1c c7 01\ +cf 7e eb cb 99 f0 ff e1 7c fd 0a 4b f7 be fd 2d\ +d5 36 ac 94 6d b7 97 fd bc 4a be 8f 29 34 9b 91\ +ed +ModPrime1PrivateExponent: \ +03 96 1c 8f 76 0a a2 bd 51 54 c7 aa fd 77 22 5b\ +3b ac d0 13 9a e7 b5 94 8e a3 31 1f cc d8 6f b9\ +5c 75 af a7 67 28 4b 9b 2d e5 59 57 2f 15 d8 d0\ +44 c7 eb 83 a1 be 5f ad f2 cc 37 7c 0d 84 75 29\ +4b +ModPrime2PrivateExponent: \ +02 21 97 e0 66 74 21 96 aa bc 03 fa 2f ee b4 e7\ +0b 15 cb 78 7d 61 7a cd 31 bb 75 c7 bc 23 4a d7\ +06 f7 c4 8d 21 82 d1 f0 ff 9c 22 8d cf 41 96 7b\ +6c 0b a6 d2 c0 ad 11 0a 1b 85 78 31 ec 24 5e 2c\ +b1 +MultiplicativeInverseOfPrime2ModPrime1: \ +04 01 c4 c0 c5 3d 45 db db 5e 9d 96 d0 fe cf 42\ +75 df 09 74 bc 4a 07 36 b4 a7 4c 32 69 05 3e fb\ +68 6a ce 24 06 e2 2c 9e 05 8d db 4a e5 40 62 7a\ +e2 fd b0 82 61 e8 e7 e4 bc bc 99 4d aa fa 30 5c\ +45 +Test: KeyPairValidAndConsistent +Comment: RSAES-OAEP Encryption Example 6.1 +Plaintext: \ +40 46 ca 8b aa 33 47 ca 27 f4 9e 0d 81 f9 cc 1d\ +71 be 9b a5 17 d4 +Seed: # not used yet\ +dd 0f 6c fe 41 5e 88 e5 a4 69 a5 1f bb a6 df d4\ +0a db 43 84 +Ciphertext: \ +06 30 ee bc d2 85 6c 24 f7 98 80 6e 41 f9 e6 73\ +45 ed a9 ce da 38 6a cc 9f ac ae a1 ee ed 06 ac\ +e5 83 70 97 18 d9 d1 69 fa df 41 4d 5c 76 f9 29\ +96 83 3e f3 05 b7 5b 1e 4b 95 f6 62 a2 0f ae dc\ +3b ae 0c 48 27 a8 bf 8a 88 ed bd 57 ec 20 3a 27\ +a8 41 f0 2e 43 a6 15 ba b1 a8 ca c0 70 1d e3 4d\ +eb de f6 2a 08 80 89 b5 5e c3 6e a7 52 2f d3 ec\ +8d 06 b6 a0 73 e6 df 83 31 53 bc 0a ef d9 3b d1\ +a3 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 6.2 +Plaintext: \ +5c c7 2c 60 23 1d f0 3b 3d 40 f9 b5 79 31 bc 31\ +10 9f 97 25 27 f2 8b 19 e7 48 0c 72 88 cb 3c 92\ +b2 25 12 21 4e 4b e6 c9 14 79 2d da bd f5 7f aa\ +8a a7 +Seed: # not used yet\ +8d 14 bd 94 6a 13 51 14 8f 5c ae 2e d9 a0 c6 53\ +e8 5e bd 85 +Ciphertext: \ +0e bc 37 37 61 73 a4 fd 2f 89 cc 55 c2 ca 62 b2\ +6b 11 d5 1c 3c 7c e4 9e 88 45 f7 4e 76 07 31 7c\ +43 6b c8 d2 3b 96 67 df eb 9d 08 72 34 b4 7b c6\ +83 71 75 ae 5c 05 59 f6 b8 1d 7d 22 41 6d 3e 50\ +f4 ac 53 3d 8f 08 12 f2 db 9e 79 1f e9 c7 75 ac\ +8b 6a d0 f5 35 ad 9c eb 23 a4 a0 20 14 c5 8a b3\ +f8 d3 16 14 99 a2 60 f3 93 48 e7 14 ae 2a 1d 34\ +43 20 8f d8 b7 22 cc fd fb 39 3e 98 01 1f 99 e6\ +3f +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 6.3 +Plaintext: \ +b2 0e 65 13 03 09 2f 4b cc b4 30 70 c0 f8 6d 23\ +04 93 62 ed 96 64 2f c5 63 2c 27 db 4a 52 e3 d8\ +31 f2 ab 06 8b 23 b1 49 87 9c 00 2f 6b f3 fe ee\ +97 59 11 12 56 2c +Seed: # not used yet\ +6c 07 5b c4 55 20 f1 65 c0 bf 5e a4 c5 df 19 1b\ +c9 ef 0e 44 +Ciphertext: \ +0a 98 bf 10 93 61 93 94 43 6c f6 8d 8f 38 e2 f1\ +58 fd e8 ea 54 f3 43 5f 23 9b 8d 06 b8 32 18 44\ +20 24 76 ae ed 96 00 94 92 48 0c e3 a8 d7 05 49\ +8c 4c 8c 68 f0 15 01 dc 81 db 60 8f 60 08 73 50\ +c8 c3 b0 bd 2e 9e f6 a8 14 58 b7 c8 01 b8 9f 2e\ +4f e9 9d 49 00 ba 6a 4b 5e 5a 96 d8 65 dc 67 6c\ +77 55 92 87 94 13 0d 62 80 a8 16 0a 19 0f 2d f3\ +ea 7c f9 aa 02 71 d8 8e 9e 69 05 ec f1 c5 15 2d\ +65 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 6.4 +Plaintext: \ +68 4e 30 38 c5 c0 41 f7 +Seed: # not used yet\ +3b bc 3b d6 63 7d fe 12 84 69 01 02 9b f5 b0 c0\ +71 03 43 9c +Ciphertext: \ +00 8e 7a 67 ca cf b5 c4 e2 4b ec 7d ee 14 91 17\ +f1 95 98 ce 8c 45 80 8f ef 88 c6 08 ff 9c d6 e6\ +95 26 3b 9a 3c 0a d4 b8 ba 4c 95 23 8e 96 a8 42\ +2b 85 35 62 9c 8d 53 82 37 44 79 ad 13 fa 39 97\ +4b 24 2f 9a 75 9e ea f9 c8 3a d5 a8 ca 18 94 0a\ +01 62 ba 75 58 76 df 26 3f 4b d5 0c 65 25 c5 60\ +90 26 7c 1f 0e 09 ce 08 99 a0 cf 35 9e 88 12 0a\ +bd 9b f8 93 44 5b 3c ae 77 d3 60 73 59 ae 9a 52\ +f8 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 6.5 +Plaintext: \ +32 48 8c b2 62 d0 41 d6 e4 dd 35 f9 87 bf 3c a6\ +96 db 1f 06 ac 29 a4 46 93 +Seed: # not used yet\ +b4 6b 41 89 3e 8b ef 32 6f 67 59 38 3a 83 07 1d\ +ae 7f ca bc +Ciphertext: \ +00 00 34 74 41 6c 7b 68 bd f9 61 c3 85 73 79 44\ +d7 f1 f4 0c b3 95 34 3c 69 3c c0 b4 fe 63 b3 1f\ +ed f1 ea ee ac 9c cc 06 78 b3 1d c3 2e 09 77 48\ +95 14 c4 f0 90 85 f6 29 8a 96 53 f0 1a ea 40 45\ +ff 58 2e e8 87 be 26 ae 57 5b 73 ee f7 f3 77 49\ +21 e3 75 a3 d1 9a dd a0 ca 31 aa 18 49 88 7c 1f\ +42 ca c9 67 7f 7a 2f 4e 92 3f 6e 5a 86 8b 38 c0\ +84 ef 18 75 94 dc 9f 7f 04 8f ea 2e 02 95 53 84\ +ab +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 6.6 +Plaintext: \ +50 ba 14 be 84 62 72 02 79 c3 06 ba +Seed: # not used yet\ +0a 24 03 31 2a 41 e3 d5 2f 06 0f bc 13 a6 7d e5\ +cf 76 09 a7 +Ciphertext: \ +0a 02 6d da 5f c8 78 5f 7b d9 bf 75 32 7b 63 e8\ +5e 2c 0f de e5 da db 65 eb dc ac 9a e1 de 95 c9\ +2c 67 2a b4 33 aa 7a 8e 69 ce 6a 6d 88 97 fa c4\ +ac 4a 54 de 84 1a e5 e5 bb ce 76 87 87 9d 79 63\ +4c ea 7a 30 68 40 65 c7 14 d5 24 09 b9 28 25 6b\ +bf 53 ea bc d5 23 1e b7 25 95 04 53 73 99 bd 29\ +16 4b 72 6d 33 a4 6d a7 01 36 0a 41 68 a0 91 cc\ +ab 72 d4 4a 62 fe d2 46 c0 ff ea 5b 13 48 ab 54\ +70 +Test: DecryptMatch + +AlgorithmType: AsymmetricCipher +Name: RSA/OAEP-MGF1(SHA-1) +Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors +KeyFormat: Component +Comment: Example 7: A 1030-bit RSA Key Pair +Modulus: \ +31 11 79 f0 bc fc 9b 9d 3c a3 15 d0 0e f3 0d 7b\ +dd 3a 2c fa e9 91 1b fe dc b9 48 b3 a4 78 2d 07\ +32 b6 ab 44 aa 4b f0 37 41 a6 44 dc 01 be c3 e6\ +9b 01 a0 33 e6 75 d8 ac d7 c4 92 5c 6b 1a ec 31\ +19 05 1d fd 89 76 2d 21 5d 45 47 5f fc b5 9f 90\ +81 48 62 3f 37 17 71 56 f6 ae 86 dd 7a 7c 5f 43\ +dc 1e 1f 90 82 54 05 8a 28 4a 5f 06 c0 02 17 93\ +a8 7f 1a c5 fe ff 7d ca ee 69 c5 e5 1a 37 89 e3\ +73 +PublicExponent: \ +01 00 01 +PrivateExponent: \ +07 0c fc ff 2f eb 82 76 e2 74 32 c4 5d fe e4 8f\ +49 b7 91 7d 65 30 e1 f0 ca 34 60 f3 2e 02 76 17\ +44 87 c5 6e 22 a4 5d 25 00 d7 77 54 95 21 9d 7d\ +16 5a 9c f3 bd 92 c3 2a f9 a9 8d 8d c9 cc 29 68\ +00 ad c9 4a 0a 54 fb 40 f3 42 91 bf 84 ee 8e a1\ +2b 6f 10 93 59 c6 d3 54 2a 50 f9 c7 67 f5 cf ff\ +05 a6 81 c2 e6 56 fb 77 ca aa db 4b e9 46 8d 8a\ +bc d4 df 98 f5 8e 86 d2 05 3f a1 34 9f 74 8e 21\ +b1 +Prime1: \ +07 49 26 2c 11 1c d4 70 ec 25 66 e6 b3 73 2f c0\ +93 29 46 9a a1 90 71 d3 b9 c0 19 06 51 4c 6f 1d\ +26 ba a1 4b ea b0 97 1c 8b 7e 61 1a 4f 79 00 9d\ +6f ea 77 69 28 ca 25 28 5b 0d e3 64 3d 1a 3f 8c\ +71 +Prime2: \ +06 bc 1e 50 e9 6c 02 bf 63 6e 9e ea 8b 89 9b be\ +bf 76 51 de 77 dd 47 4c 3e 9b c2 3b ad 81 82 b6\ +19 04 c7 d9 7d fb eb fb 1e 00 10 88 78 b6 e6 7e\ +41 53 91 d6 79 42 c2 b2 bf 9b 44 35 f8 8b 0c b0\ +23 +ModPrime1PrivateExponent: \ +03 bc 7e a7 f0 aa b1 43 ab c6 ce 8b 97 11 86 36\ +a3 01 72 e4 cf e0 2c 8f a0 dd a3 b7 ba af 90 f8\ +09 29 82 98 55 25 f4 88 bd fc b4 bd 72 6e 22 63\ +9a c6 4a 30 92 ab 7f fc bf 1d 53 34 cf a5 0b 5b\ +f1 +ModPrime2PrivateExponent: \ +02 62 a6 aa 29 c2 a3 c6 7d c5 34 6c 06 38 1a fd\ +98 7a a3 cc 93 cf bf ec f5 4f dd 9f 9d 78 7d 7f\ +59 a5 23 d3 98 97 9d a1 37 a2 f6 38 1f e9 48 01\ +f7 c9 4d a2 15 18 dc 34 cb 40 87 0c 46 97 99 4a\ +d9 +MultiplicativeInverseOfPrime2ModPrime1: \ +64 9d 4c 17 b6 ee 17 21 e7 72 d0 38 9a 55 9c 3d\ +3c df 95 50 d4 57 c4 6b 03 7b 74 64 1b 1d 52 16\ +6a f8 a2 13 c8 39 62 06 cd fb a4 42 2f 18 d6 f6\ +1d bc b5 d2 14 c9 71 bf 48 2a eb 97 6a 73 70 c2 +Test: KeyPairValidAndConsistent +Comment: RSAES-OAEP Encryption Example 7.1 +Plaintext: \ +47 aa e9 09 +Seed: # not used yet\ +43 dd 09 a0 7f f4 ca c7 1c aa 46 32 ee 5e 1c 1d\ +ae e4 cd 8f +Ciphertext: \ +16 88 e4 ce 77 94 bb a6 cb 70 14 16 9e cd 55 9c\ +ed e2 a3 0b 56 a5 2b 68 d9 fe 18 cf 19 73 ef 97\ +b2 a0 31 53 95 1c 75 5f 62 94 aa 49 ad bd b5 58\ +45 ab 68 75 fb 39 86 c9 3e cf 92 79 62 84 0d 28\ +2f 9e 54 ce 8b 69 0f 7c 0c b8 bb d7 34 40 d9 57\ +1d 1b 16 cd 92 60 f9 ea b4 78 3c c4 82 e5 22 3d\ +c6 09 73 87 17 83 ec 27 b0 ae 0f d4 77 32 cb c2\ +86 a1 73 fc 92 b0 0f b4 ba 68 24 64 7c d9 3c 85\ +c1 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 7.2 +Plaintext: \ +1d 9b 2e 22 23 d9 bc 13 bf b9 f1 62 ce 73 5d b4\ +8b a7 c6 8f 68 22 a0 a1 a7 b6 ae 16 58 34 e7 +Seed: # not used yet\ +3a 9c 3c ec 7b 84 f9 bd 3a de cb c6 73 ec 99 d5\ +4b 22 bc 9b +Ciphertext: \ +10 52 ed 39 7b 2e 01 e1 d0 ee 1c 50 bf 24 36 3f\ +95 e5 04 f4 a0 34 34 a0 8f d8 22 57 4e d6 b9 73\ +6e db b5 f3 90 db 10 32 14 79 a8 a1 39 35 0e 2b\ +d4 97 7c 37 78 ef 33 1f 3e 78 ae 11 8b 26 84 51\ +f2 0a 2f 01 d4 71 f5 d5 3c 56 69 37 17 1b 2d bc\ +2d 4b de 45 9a 57 99 f0 37 2d 65 74 23 9b 23 23\ +d2 45 d0 bb 81 c2 86 b6 3c 89 a3 61 01 73 37 e4\ +90 2f 88 a4 67 f4 c7 f2 44 bf d5 ab 46 43 7f f3\ +b6 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 7.3 +Plaintext: \ +d9 76 fc +Seed: # not used yet\ +76 a7 5e 5b 61 57 a5 56 cf 88 84 bb 2e 45 c2 93\ +dd 54 5c f5 +Ciphertext: \ +21 55 cd 84 3f f2 4a 4e e8 ba db 76 94 26 00 28\ +a4 90 81 3b a8 b3 69 a4 cb f1 06 ec 14 8e 52 98\ +70 7f 59 65 be 7d 10 1c 10 49 ea 85 84 c2 4c d6\ +34 55 ad 9c 10 4d 68 62 82 d3 fb 80 3a 4c 11 c1\ +c2 e9 b9 1c 71 78 80 1d 1b 66 40 f0 03 f5 72 8d\ +f0 07 b8 a4 cc c9 2b ce 05 e4 1a 27 27 8d 7c 85\ +01 8c 52 41 43 13 a5 07 77 89 00 1d 4f 01 91 0b\ +72 aa d0 5d 22 0a a1 4a 58 73 3a 74 89 bc 54 55\ +6b +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 7.4 +Plaintext: \ +d4 73 86 23 df 22 3a a4 38 43 df 84 67 53 4c 41\ +d0 13 e0 c8 03 c6 24 e2 63 66 6b 23 9b de 40 a5\ +f2 9a eb 8d e7 9e 3d aa 61 dd 03 70 f4 9b d4 b0\ +13 83 4b 98 21 2a ef 6b 1c 5e e3 73 b3 cb +Seed: # not used yet\ +78 66 31 4a 6a d6 f2 b2 50 a3 59 41 db 28 f5 86\ +4b 58 58 59 +Ciphertext: \ +0a b1 4c 37 3a eb 7d 43 28 d0 aa ad 8c 09 4d 88\ +b9 eb 09 8b 95 f2 10 54 a2 90 82 52 2b e7 c2 7a\ +31 28 78 b6 37 91 7e 3d 81 9e 6c 3c 56 8d b5 d8\ +43 80 2b 06 d5 1d 9e 98 a2 be 0b f4 0c 03 14 23\ +b0 0e df bf f8 32 0e fb 91 71 bd 20 44 65 3a 4c\ +b9 c5 12 2f 6c 65 e8 3c da 2e c3 c1 26 02 7a 9c\ +1a 56 ba 87 4d 0f ea 23 f3 80 b8 2c f2 40 b8 cf\ +54 00 04 75 8c 4c 77 d9 34 15 7a 74 f3 fc 12 bf\ +ac +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 7.5 +Plaintext: \ +bb 47 23 1c a5 ea 1d 3a d4 6c 99 34 5d 9a 8a 61 +Seed: # not used yet\ +b2 16 6e d4 72 d5 8d b1 0c ab 2c 6b 00 0c cc f1\ +0a 7d c5 09 +Ciphertext: \ +02 83 87 a3 18 27 74 34 79 8b 4d 97 f4 60 06 8d\ +f5 29 8f ab a5 04 1b a1 17 61 a1 cb 73 16 b2 41\ +84 11 4e c5 00 25 7e 25 89 ed 3b 60 7a 1e bb e9\ +7a 6c c2 e0 2b f1 b6 81 f4 23 12 a3 3b 7a 77 d8\ +e7 85 5c 4a 6d e0 3e 3c 04 64 3f 78 6b 91 a2 64\ +a0 d6 80 5e 2c ea 91 e6 81 77 eb 7a 64 d9 25 5e\ +4f 27 e7 13 b7 cc ec 00 dc 20 0e bd 21 c2 ea 2b\ +b8 90 fe ae 49 42 df 94 1d c3 f9 78 90 ed 34 74\ +78 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 7.6 +Plaintext: \ +21 84 82 70 95 d3 5c 3f 86 f6 00 e8 e5 97 54 01\ +32 96 +Seed: # not used yet\ +52 67 3b de 2c a1 66 c2 aa 46 13 1a c1 dc 80 8d\ +67 d7 d3 b1 +Ciphertext: \ +14 c6 78 a9 4a d6 05 25 ef 39 e9 59 b2 f3 ba 5c\ +09 7a 94 ff 91 2b 67 db ac e8 05 35 c1 87 ab d4\ +7d 07 54 20 b1 87 21 52 bb a0 8f 7f c3 1f 31 3b\ +bf 92 73 c9 12 fc 4c 01 49 a9 b0 cf b7 98 07 e3\ +46 eb 33 20 69 61 1b ec 0f f9 bc d1 68 f1 f7 c3\ +3e 77 31 3c ea 45 4b 94 e2 54 9e ec f0 02 e2 ac\ +f7 f6 f2 d2 84 5d 4f e0 aa b2 e5 a9 2d df 68 c4\ +80 ae 11 24 79 35 d1 f6 25 74 84 22 16 ae 67 41\ +15 +Test: DecryptMatch + +AlgorithmType: AsymmetricCipher +Name: RSA/OAEP-MGF1(SHA-1) +Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors +KeyFormat: Component +Comment: Example 8: A 1031-bit RSA Key Pair +Modulus: \ +5b df 0e 30 d3 21 dd a5 14 7f 88 24 08 fa 69 19\ +54 80 df 8f 80 d3 f6 e8 bf 58 18 50 4f 36 42 7c\ +a9 b1 f5 54 0b 9c 65 a8 f6 97 4c f8 44 7a 24 4d\ +92 80 20 1b b4 9f cb be 63 78 d1 94 4c d2 27 e2\ +30 f9 6e 3d 10 f8 19 dc ef 27 6c 64 a0 0b 2a 4b\ +67 01 e7 d0 1d e5 fa bd e3 b1 e9 a0 df 82 f4 63\ +13 59 cd 22 66 96 47 fb b1 71 72 46 13 4e d7 b4\ +97 cf ff bd c4 2b 59 c7 3a 96 ed 90 16 62 12 df\ +f7 +PublicExponent: \ +01 00 01 +PrivateExponent: \ +0f 7d 1e 9e 5a aa 25 fd 13 e4 a0 66 3a e1 44 e0\ +d1 5f 5c d1 8b cd b0 9d f2 cc 7e 64 e3 c5 e9 15\ +ad 62 64 53 04 16 1d 09 8c 71 5b b7 ab 8b d0 1d\ +07 ea f3 fe d7 c7 ed 08 af 2a 8a 62 ef 44 ab 16\ +b3 20 e1 4a f7 2a 48 f9 6a fe 26 2a 0a e4 cf 65\ +e6 35 e9 10 79 0c d4 ee 5c ea 76 8a 4b 26 39 f7\ +e6 f6 77 b3 f0 bb 6b e3 2b 75 74 7d 89 09 03 6f\ +02 64 f5 8d 40 1c db a1 31 71 61 57 a7 5e cf 63\ +31 +Prime1: \ +0a 02 ef 84 48 d9 fa d8 bb d0 d0 04 c8 c2 aa 97\ +51 ef 97 21 c1 b0 d0 32 36 a5 4b 0d f9 47 cb ae\ +d5 a2 55 ee 9e 8e 20 d4 91 ea 17 23 fe 09 47 04\ +a9 76 2e 88 af d1 6e bb 59 94 41 2c a9 66 dc 4f\ +9f +Prime2: \ +09 2d 36 2e 7e d3 a0 bf d9 e9 fd 0e 6c 03 01 b6\ +df 29 15 9c f5 0c c8 3b 9b 0c f4 d6 ee a7 1a 61\ +e0 02 b4 6e 0a e9 f2 de 62 d2 5b 5d 74 52 d4 98\ +b8 1c 9a c6 fc 58 59 3d 4c 3f b4 f5 d7 2d fb b0\ +a9 +ModPrime1PrivateExponent: \ +07 c7 14 10 af 10 39 62 db 36 74 04 e3 7a e8 50\ +ba a4 e9 c2 9d d9 21 45 81 52 94 a6 7c 7d 1c 6d\ +ed 26 3a a0 30 a9 b6 33 ae 50 30 3e 14 03 5d 1a\ +f0 14 12 3e ba 68 78 20 30 8d 8e bc 85 b6 95 7d\ +7d +ModPrime2PrivateExponent: \ +ae 2c 75 38 0c 02 c0 16 ad 05 89 1b 33 01 de 88\ +1f 28 ae 11 71 18 2b 6b 2c 83 be a7 c5 15 ec a9\ +ca 29 8c 7b 1c ab 58 17 a5 97 06 8f c8 50 60 de\ +4d a8 a0 16 37 8a ae 43 c7 f9 67 bc c3 79 04 b9 +MultiplicativeInverseOfPrime2ModPrime1: \ +05 98 d1 05 9e 3a da 4f 63 20 75 2c 09 d8 05 ff\ +7d 1f 1a e0 d0 17 ae ee e9 ce fa 0d 7d d7 ff 77\ +5e 44 b5 78 32 2f 64 05 d6 21 1d a1 95 19 66 6a\ +a8 7f dc 4c d8 c8 8f 6b 6e 3d 67 e9 61 dc bb a3\ +d0 +Test: KeyPairValidAndConsistent +Comment: RSAES-OAEP Encryption Example 8.1 +Plaintext: \ +05 0b 75 5e 5e 68 80 f7 b9 e9 d6 92 a7 4c 37 aa\ +e4 49 b3 1b fe a6 de ff 83 74 7a 89 7f 6c 2c 82\ +5b b1 ad bf 85 0a 3c 96 99 4b 5d e5 b3 3c bc 7d\ +4a 17 91 3a 79 67 +Seed: # not used yet\ +77 06 ff ca 1e cf b1 eb ee 2a 55 e5 c6 e2 4c d2\ +79 7a 41 25 +Ciphertext: \ +09 b3 68 3d 8a 2e b0 fb 29 5b 62 ed 1f b9 29 0b\ +71 44 57 b7 82 53 19 f4 64 78 72 af 88 9b 30 40\ +94 72 02 0a d1 29 12 bf 19 b1 1d 48 19 f4 96 14\ +82 4f fd 84 d0 9c 0a 17 e7 d1 73 09 d1 29 19 79\ +04 10 aa 29 95 69 9f 6a 86 db e3 24 2b 5a cc 23\ +af 45 69 10 80 d6 b1 ae 81 0f b3 e3 05 70 87 f0\ +97 00 92 ce 00 be 95 62 ff 40 53 b6 26 2c e0 ca\ +a9 3e 13 72 3d 2e 3a 5b a0 75 d4 5f 0d 61 b5 4b\ +61 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 8.2 +Plaintext: \ +4e b6 8d cd 93 ca 9b 19 df 11 1b d4 36 08 f5 57\ +02 6f e4 aa 1d 5c fa c2 27 a3 eb 5a b9 54 8c 18\ +a0 6d de d2 3f 81 82 59 86 b2 fc d7 11 09 ec ef\ +7e ff 88 87 3f 07 5c 2a a0 c4 69 f6 9c 92 bc +Seed: # not used yet\ +a3 71 7d a1 43 b4 dc ff bc 74 26 65 a8 fa 95 05\ +85 54 83 43 +Ciphertext: \ +2e cf 15 c9 7c 5a 15 b1 47 6a e9 86 b3 71 b5 7a\ +24 28 4f 4a 16 2a 8d 0c 81 82 e7 90 5e 79 22 56\ +f1 81 2b a5 f8 3f 1f 7a 13 0e 42 dc c0 22 32 84\ +4e dc 14 a3 1a 68 ee 97 ae 56 4a 38 3a 34 11 65\ +64 24 c5 f6 2d db 64 60 93 c3 67 be 1f cd a4 26\ +cf 00 a0 6d 8a cb 7e 57 77 6f bb d8 55 ac 3d f5\ +06 fc 16 b1 d7 c3 f2 11 0f 3d 80 68 e9 1e 18 63\ +63 83 1c 84 09 68 0d 8d a9 ec d8 cf 1f a2 0e e3\ +9d +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 8.3 +Plaintext: \ +86 04 ac 56 32 8c 1a b5 ad 91 78 61 +Seed: # not used yet\ +ee 06 20 90 73 cc a0 26 bb 26 4e 51 85 bf 8c 68\ +b7 73 9f 86 +Ciphertext: \ +4b c8 91 30 a5 b2 da bb 7c 2f cf 90 eb 5d 0e af\ +9e 68 1b 71 46 a3 8f 31 73 a3 d9 cf ec 52 ea 9e\ +0a 41 93 2e 64 8a 9d 69 34 4c 50 da 76 3f 51 a0\ +3c 95 76 21 31 e8 05 22 54 dc d2 24 8c ba 40 fd\ +31 66 77 86 ce 05 a2 b7 b5 31 ac 9d ac 9e d5 84\ +a5 9b 67 7c 1a 8a ed 8c 5d 15 d6 8c 05 56 9e 2b\ +e7 80 bf 7d b6 38 fd 2b fd 2a 85 ab 27 68 60 f3\ +77 73 38 fc a9 89 ff d7 43 d1 3e e0 8e 0c a9 89\ +3f +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 8.4 +Plaintext: \ +fd da 5f bf 6e c3 61 a9 d9 a4 ac 68 af 21 6a 06\ +86 f4 38 b1 e0 e5 c3 6b 95 5f 74 e1 07 f3 9c 0d\ +dd cc +Seed: # not used yet\ +99 0a d5 73 dc 48 a9 73 23 5b 6d 82 54 36 18 f2\ +e9 55 10 5d +Ciphertext: \ +2e 45 68 47 d8 fc 36 ff 01 47 d6 99 35 94 b9 39\ +72 27 d5 77 75 2c 79 d0 f9 04 fc b0 39 d4 d8 12\ +fe a6 05 a7 b5 74 dd 82 ca 78 6f 93 75 23 48 43\ +8e e9 f5 b5 45 49 85 d5 f0 e1 69 9e 3e 7a d1 75\ +a3 2e 15 f0 3d eb 04 2a b9 fe 1d d9 db 1b b8 6f\ +8c 08 9c cb 45 e7 ef 0c 5e e7 ca 9b 72 90 ca 6b\ +15 be d4 70 39 78 8a 8a 93 ff 83 e0 e8 d6 24 4c\ +71 00 63 62 de ef 69 b6 f4 16 fb 3c 68 43 83 fb\ +d0 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 8.5 +Plaintext: \ +4a 5f 49 14 be e2 5d e3 c6 93 41 de 07 +Seed: # not used yet\ +ec c6 3b 28 f0 75 6f 22 f5 2a c8 e6 ec 12 51 a6\ +ec 30 47 18 +Ciphertext: \ +1f b9 35 6f d5 c4 b1 79 6d b2 eb f7 d0 d3 93 cc\ +81 0a df 61 45 de fc 2f ce 71 4f 79 d9 38 00 d5\ +e2 ac 21 1e a8 bb ec ca 4b 65 4b 94 c3 b1 8b 30\ +dd 57 6c e3 4d c9 54 36 ef 57 a0 94 15 64 59 23\ +35 9a 5d 7b 41 71 ef 22 c2 46 70 f1 b2 29 d3 60\ +3e 91 f7 66 71 b7 df 97 e7 31 7c 97 73 44 76 d5\ +f3 d1 7d 21 cf 82 b5 ba 9f 83 df 2e 58 8d 36 98\ +4f d1 b5 84 46 8b d2 3b 2e 87 5f 32 f6 89 53 f7\ +b2 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 8.6 +Plaintext: \ +8e 07 d6 6f 7b 88 0a 72 56 3a bc d3 f3 50 92 bc\ +33 40 9f b7 f8 8f 24 72 be +Seed: # not used yet\ +39 25 c7 1b 36 2d 40 a0 a6 de 42 14 55 79 ba 1e\ +7d d4 59 fc +Ciphertext: \ +3a fd 9c 66 00 14 7b 21 79 8d 81 8c 65 5a 0f 4c\ +92 12 db 26 d0 b0 df dc 2a 75 94 cc b3 d2 2f 5b\ +f1 d7 c3 e1 12 cd 73 fc 7d 50 9c 7a 8b af dd 3c\ +27 4d 13 99 00 9f 96 09 ec 4b e6 47 7e 45 3f 07\ +5a a3 3d b3 82 87 0c 1c 34 09 ae f3 92 d7 38 6a\ +e3 a6 96 b9 9a 94 b4 da 05 89 44 7e 95 5d 16 c9\ +8b 17 60 2a 59 bd 73 62 79 fc d8 fb 28 0c 44 62\ +d5 90 bf a9 bf 13 fe d5 70 ea fd e9 73 30 a2 c2\ +10 +Test: DecryptMatch + +AlgorithmType: AsymmetricCipher +Name: RSA/OAEP-MGF1(SHA-1) +Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors +KeyFormat: Component +Comment: Example 9: A 1536-bit RSA Key Pair +Modulus: \ +cf 2c d4 1e 34 ca 3a 72 8e a5 cb 8a ff 64 c3 6d\ +27 bd ef 53 64 e3 36 fd 68 d3 12 3c 5a 19 6a 8c\ +28 70 13 e8 53 d5 15 6d 58 d1 51 95 45 20 fb 4f\ +6d 7b 17 ab b6 81 77 65 90 9c 57 61 19 65 9d 90\ +2b 19 06 ed 8a 2b 10 c1 55 c2 4d 12 45 28 da b9\ +ee ae 37 9b ea c6 6e 4a 41 17 86 dc b8 fd 00 62\ +eb c0 30 de 12 19 a0 4c 2a 8c 1b 7d d3 13 1e 4d\ +6b 6c ae e2 e3 1a 5e d4 1a c1 50 9b 2e f1 ee 2a\ +b1 83 64 be 56 8c a9 41 c2 5e cc 84 ff 9d 64 3b\ +5e c1 aa ae 10 2a 20 d7 3f 47 9b 78 0f d6 da 91\ +07 52 12 d9 ea c0 3a 06 74 d8 99 eb a2 e4 31 f4\ +c4 4b 61 5b 6b a2 23 2b d4 b3 3b ae d7 3d 62 5d +PublicExponent: \ +01 00 01 +PrivateExponent: \ +19 8c 14 1e 23 71 5a 92 bc cf 6a 11 9a 5b c1 13\ +89 46 8d 28 11 f5 48 d7 27 e1 7b 4a b0 eb 98 6d\ +6f 21 1e fb 53 b7 1f 7c cb ea 87 ee 69 c7 5e e6\ +15 00 8c 53 32 de b5 2b f3 90 ab df bf e3 7d 72\ +05 36 81 59 b2 63 8c 1d e3 26 e2 1d 22 25 1f 0f\ +b5 84 8b 3b f1 50 05 d2 a7 43 30 f0 af e9 16 ee\ +62 cc c1 34 4d 1d 83 a7 09 e6 06 76 27 38 40 f7\ +f3 77 42 4a 5e 0a 4d a7 5f 01 b3 1f f7 68 19 cf\ +9c bf dd 21 52 43 c3 91 7c 03 ef 38 19 93 12 e5\ +67 b3 bf 7a ed 3a b4 57 f3 71 ef 8a 14 23 f4 5b\ +68 c6 e2 82 ec 11 1b ba 28 33 b9 87 fd 69 fa d8\ +3b c1 b8 c6 13 c5 e1 ea 16 c1 1e d1 25 ea 7e c1 +Prime1: \ +fc 8d 6c 04 be c4 eb 9a 81 92 ca 79 00 cb e5 36\ +e2 e8 b5 19 de cf 33 b2 45 97 98 c6 90 9d f4 f1\ +76 db 7d 23 19 0f c7 2b 88 65 a7 18 af 89 5f 1b\ +cd 91 45 29 80 27 42 3b 60 5e 70 a4 7c f5 83 90\ +a8 c3 e8 8f c8 c4 8e 8b 32 e3 da 21 0d fb e3 e8\ +81 ea 56 74 b6 a3 48 c2 1e 93 f9 e5 5e a6 5e fd +Prime2: \ +d2 00 d4 5e 78 8a ac ea 60 6a 40 1d 04 60 f8 7d\ +d5 c1 02 7e 12 dc 1a 0d 75 86 e8 93 9d 9c f7 89\ +b4 0f 51 ac 04 42 96 1d e7 d2 1c c2 1e 05 c8 31\ +55 c1 f2 aa 91 93 38 7c fd f9 56 cb 48 d1 53 ba\ +27 04 06 f9 bb ba 53 7d 49 87 d9 e2 f9 94 2d 7a\ +14 cb ff fe a7 4f ec dd a9 28 d2 3e 25 9f 5e e1 +ModPrime1PrivateExponent: \ +db 16 80 2f 79 a2 f0 d4 5f 35 8d 69 fd 33 e4 4b\ +81 fa e8 28 62 2e 93 a5 42 53 e9 97 d0 1b 07 43\ +75 9d a0 e8 12 b4 aa 4e 6c 8b ea b2 32 8d 54 31\ +95 5a 41 8a 67 ff 26 a8 c5 c8 07 a5 da 35 4e 05\ +ef 31 cc 8c f7 58 f4 63 73 29 50 b0 3e 26 57 26\ +fb 94 e3 9d 6a 57 2a 26 24 4a b0 8d b7 57 52 ad +ModPrime2PrivateExponent: \ +a0 a3 17 cf e7 df 14 23 f8 7a 6d ee 84 51 f4 e2\ +b4 a6 7e 54 97 f2 9b 4f 1e 4e 83 0b 9f ad d9 40\ +11 67 02 6f 55 96 e5 a3 9c 97 81 7e 0f 5f 16 e2\ +7e 19 ec 99 02 e0 1d 7e a6 fb 9a a3 c7 60 af ee\ +1e 38 1b 69 de 6a c9 c0 75 85 a0 6a d9 c4 ba 00\ +bf 75 c8 ad 2f a8 98 a4 79 e8 0a e2 94 fe d2 a1 +MultiplicativeInverseOfPrime2ModPrime1: \ +0b 21 f3 35 c3 53 34 2e b4 4c 3a a2 44 45 78 0c\ +2d 65 5b 94 01 74 ca e3 8c 7c 8a 4e 64 93 c0 ba\ +9f d3 03 74 82 67 b0 83 b9 a7 a6 cb 61 e4 2d b3\ +62 b8 c9 89 6d b7 06 4e 02 ad 5a e6 15 87 da 15\ +b4 64 9c 90 59 49 09 fe b3 7d bc b6 54 be b7 26\ +8e c8 01 e5 a8 b4 aa 39 11 be bd 88 54 2f 05 be +Test: KeyPairValidAndConsistent +Comment: RSAES-OAEP Encryption Example 9.1 +Plaintext: \ +f7 35 fd 55 ba 92 59 2c 3b 52 b8 f9 c4 f6 9a aa\ +1c be f8 fe 88 ad d0 95 59 54 12 46 7f 9c f4 ec\ +0b 89 6c 59 ed a1 62 10 e7 54 9c 8a bb 10 cd bc\ +21 a1 2e c9 b6 b5 b8 fd 2f 10 39 9e b6 +Seed: # not used yet\ +8e c9 65 f1 34 a3 ec 99 31 e9 2a 1c a0 dc 81 69\ +d5 ea 70 5c +Ciphertext: \ +26 7b cd 11 8a ca b1 fc 8b a8 1c 85 d7 30 03 cb\ +86 10 fa 55 c1 d9 7d a8 d4 8a 7c 7f 06 89 6a 4d\ +b7 51 aa 28 42 55 b9 d3 6a d6 5f 37 65 3d 82 9f\ +1b 37 f9 7b 80 01 94 25 45 b2 fc 2c 55 a7 37 6c\ +a7 a1 be 4b 17 60 c8 e0 5a 33 e5 aa 25 26 b8 d9\ +8e 31 70 88 e7 83 4c 75 5b 2a 59 b1 26 31 a1 82\ +c0 5d 5d 43 ab 17 79 26 4f 84 56 f5 15 ce 57 df\ +df 51 2d 54 93 da b7 b7 33 8d c4 b7 d7 8d b9 c0\ +91 ac 3b af 53 7a 69 fc 7f 54 9d 97 9f 0e ff 9a\ +94 fd a4 16 9b d4 d1 d1 9a 69 c9 9e 33 c3 b5 54\ +90 d5 01 b3 9b 1e da e1 18 ff 67 93 a1 53 26 15\ +84 d3 a5 f3 9f 6e 68 2e 3d 17 c8 cd 12 61 fa 72 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 9.2 +Plaintext: \ +81 b9 06 60 50 15 a6 3a ab e4 2d df 11 e1 97 89\ +12 f5 40 4c 74 74 b2 6d ce 3e d4 82 bf 96 1e cc\ +81 8b f4 20 c5 46 59 +Seed: # not used yet\ +ec b1 b8 b2 5f a5 0c da b0 8e 56 04 28 67 f4 af\ +58 26 d1 6c +Ciphertext: \ +93 ac 9f 06 71 ec 29 ac bb 44 4e ff c1 a5 74 13\ +51 d6 0f db 0e 39 3f bf 75 4a cf 0d e4 97 61 a1\ +48 41 df 77 72 e9 bc 82 77 39 66 a1 58 4c 4d 72\ +ba ea 00 11 8f 83 f3 5c ca 6e 53 7c bd 4d 81 1f\ +55 83 b2 97 83 d8 a6 d9 4c d3 1b e7 0d 6f 52 6c\ +10 ff 09 c6 fa 7c e0 69 79 5a 3f cd 05 11 fd 5f\ +cb 56 4b cc 80 ea 9c 78 f3 8b 80 01 25 39 d8 a4\ +dd f6 fe 81 e9 cd db 7f 50 db bb bc c7 e5 d8 60\ +97 cc f4 ec 49 18 9f b8 bf 31 8b e6 d5 a0 71 5d\ +51 6b 49 af 19 12 58 cd 32 dc 83 3c e6 eb 46 73\ +c0 3a 19 bb ac e8 8c c5 48 95 f6 36 cc 0c 1e c8\ +90 96 d1 1c e2 35 a2 65 ca 17 64 23 2a 68 9a e8 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 9.3 +Plaintext: \ +fd 32 64 29 df 9b 89 0e 09 b5 4b 18 b8 f3 4f 1e\ +24 +Seed: # not used yet\ +e8 9b b0 32 c6 ce 62 2c bd b5 3b c9 46 60 14 ea\ +77 f7 77 c0 +Ciphertext: \ +81 eb dd 95 05 4b 0c 82 2e f9 ad 76 93 f5 a8 7a\ +df b4 b4 c4 ce 70 df 2d f8 4e d4 9c 04 da 58 ba\ +5f c2 0a 19 e1 a6 e8 b7 a3 90 0b 22 79 6d c4 e8\ +69 ee 6b 42 79 2d 15 a8 ec eb 56 c0 9c 69 91 4e\ +81 3c ea 8f 69 31 e4 b8 ed 6f 42 1a f2 98 d5 95\ +c9 7f 47 89 c7 ca a6 12 c7 ef 36 09 84 c2 1b 93\ +ed c5 40 10 68 b5 af 4c 78 a8 77 1b 98 4d 53 b8\ +ea 8a df 2f 6a 7d 4a 0b a7 6c 75 e1 dd 9f 65 8f\ +20 de d4 a4 60 71 d4 6d 77 91 b5 68 03 d8 fe a7\ +f0 b0 f8 e4 1a e3 f0 93 83 a6 f9 58 5f e7 75 3e\ +aa ff d2 bf 94 56 31 08 be ec c2 07 bb b5 35 f5\ +fc c7 05 f0 dd e9 f7 08 c6 2f 49 a9 c9 03 71 d3 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 9.4 +Plaintext: \ +f1 45 9b 5f 0c 92 f0 1a 0f 72 3a 2e 56 62 48 4d\ +8f 8c 0a 20 fc 29 da d6 ac d4 3b b5 f3 ef fd f4\ +e1 b6 3e 07 fd fe 66 28 d0 d7 4c a1 9b f2 d6 9e\ +4a 0a bf 86 d2 93 92 5a 79 67 72 f8 08 8e +Seed: # not used yet\ +60 6f 3b 99 c0 b9 cc d7 71 ea a2 9e a0 e4 c8 84\ +f3 18 9c cc +Ciphertext: \ +bc c3 5f 94 cd e6 6c b1 13 66 25 d6 25 b9 44 32\ +a3 5b 22 f3 d2 fa 11 a6 13 ff 0f ca 5b d5 7f 87\ +b9 02 cc dc 1c d0 ae bc b0 71 5e e8 69 d1 d1 fe\ +39 5f 67 93 00 3f 5e ca 46 50 59 c8 86 60 d4 46\ +ff 5f 08 18 55 20 22 55 7e 38 c0 8a 67 ea d9 91\ +26 22 54 f1 06 82 97 5e c5 63 97 76 85 37 f4 97\ +7a f6 d5 f6 aa ce b7 fb 25 de c5 93 72 30 23 1f\ +d8 97 8a f4 91 19 a2 9f 29 e4 24 ab 82 72 b4 75\ +62 79 2d 5c 94 f7 74 b8 82 9d 0b 0d 9f 1a 8c 9e\ +dd f3 75 74 d5 fa 24 8e ef a9 c5 27 1f c5 ec 25\ +79 c8 1b dd 61 b4 10 fa 61 fe 36 e4 24 22 1c 11\ +3a dd b2 75 66 4c 80 1d 34 ca 8c 63 51 e4 a8 58 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 9.5 +Plaintext: \ +53 e6 e8 c7 29 d6 f9 c3 19 dd 31 7e 74 b0 db 8e\ +4c cc a2 5f 3c 83 05 74 6e 13 7a c6 3a 63 ef 37\ +39 e7 b5 95 ab b9 6e 8d 55 e5 4f 7b d4 1a b4 33\ +37 8f fb 91 1d +Seed: # not used yet\ +fc bc 42 14 02 e9 ec ab c6 08 2a fa 40 ba 5f 26\ +52 2c 84 0e +Ciphertext: \ +23 2a fb c9 27 fa 08 c2 f6 a2 7b 87 d4 a5 cb 09\ +c0 7d c2 6f ae 73 d7 3a 90 55 88 39 f4 fd 66 d2\ +81 b8 7e c7 34 bc e2 37 ba 16 66 98 ed 82 91 06\ +a7 de 69 42 cd 6c dc e7 8f ed 8d 2e 4d 81 42 8e\ +66 49 0d 03 62 64 ce f9 2a f9 41 d3 e3 50 55 fe\ +39 81 e1 4d 29 cb b9 a4 f6 74 73 06 3b ae c7 9a\ +11 79 f5 a1 7c 9c 18 32 f2 83 8f d7 d5 e5 9b b9\ +65 9d 56 dc e8 a0 19 ed ef 1b b3 ac cc 69 7c c6\ +cc 7a 77 8f 60 a0 64 c7 f6 f5 d5 29 c6 21 02 62\ +e0 03 de 58 3e 81 e3 16 7b 89 97 1f b8 c0 e1 5d\ +44 ff fe f8 9b 53 d8 d6 4d d7 97 d1 59 b5 6d 2b\ +08 ea 53 07 ea 12 c2 41 bd 58 d4 ee 27 8a 1f 2e +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 9.6 +Plaintext: \ +b6 b2 8e a2 19 8d 0c 10 08 bc 64 +Seed: # not used yet\ +23 aa de 0e 1e 08 bb 9b 9a 78 d2 30 2a 52 f9 c2\ +1b 2e 1b a2 +Ciphertext: \ +43 8c c7 dc 08 a6 8d a2 49 e4 25 05 f8 57 3b a6\ +0e 2c 27 73 d5 b2 90 f4 cf 9d ff 71 8e 84 20 81\ +c3 83 e6 70 24 a0 f2 95 94 ea 98 7b 9d 25 e4 b7\ +38 f2 85 97 0d 19 5a bb 3a 8c 80 54 e3 d7 9d 6b\ +9c 9a 83 27 ba 59 6f 12 59 e2 71 26 67 47 66 90\ +7d 8d 58 2f f3 a8 47 61 54 92 9a db 1e 6d 12 35\ +b2 cc b4 ec 8f 66 3b a9 cc 67 0a 92 be bd 85 3c\ +8d bf 69 c6 43 6d 01 6f 61 ad d8 36 e9 47 32 45\ +04 34 20 7f 9f d4 c4 3d ec 2a 12 a9 58 ef a0 1e\ +fe 26 69 89 9b 5e 60 4c 25 5c 55 fb 71 66 de 55\ +89 e3 69 59 7b b0 91 68 c0 6d d5 db 17 7e 06 a1\ +74 0e b2 d5 c8 2f ae ca 6d 92 fc ee 99 31 ba 9f +Test: DecryptMatch + +AlgorithmType: AsymmetricCipher +Name: RSA/OAEP-MGF1(SHA-1) +Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors +KeyFormat: Component +Comment: Example 10: A 2048-bit RSA Key Pair +Modulus: \ +ae 45 ed 56 01 ce c6 b8 cc 05 f8 03 93 5c 67 4d\ +db e0 d7 5c 4c 09 fd 79 51 fc 6b 0c ae c3 13 a8\ +df 39 97 0c 51 8b ff ba 5e d6 8f 3f 0d 7f 22 a4\ +02 9d 41 3f 1a e0 7e 4e be 9e 41 77 ce 23 e7 f5\ +40 4b 56 9e 4e e1 bd cf 3c 1f b0 3e f1 13 80 2d\ +4f 85 5e b9 b5 13 4b 5a 7c 80 85 ad ca e6 fa 2f\ +a1 41 7e c3 76 3b e1 71 b0 c6 2b 76 0e de 23 c1\ +2a d9 2b 98 08 84 c6 41 f5 a8 fa c2 6b da d4 a0\ +33 81 a2 2f e1 b7 54 88 50 94 c8 25 06 d4 01 9a\ +53 5a 28 6a fe b2 71 bb 9b a5 92 de 18 dc f6 00\ +c2 ae ea e5 6e 02 f7 cf 79 fc 14 cf 3b dc 7c d8\ +4f eb bb f9 50 ca 90 30 4b 22 19 a7 aa 06 3a ef\ +a2 c3 c1 98 0e 56 0c d6 4a fe 77 95 85 b6 10 76\ +57 b9 57 85 7e fd e6 01 09 88 ab 7d e4 17 fc 88\ +d8 f3 84 c4 e6 e7 2c 3f 94 3e 0c 31 c0 c4 a5 cc\ +36 f8 79 d8 a3 ac 9d 7d 59 86 0e aa da 6b 83 bb +PublicExponent: \ +01 00 01 +PrivateExponent: \ +05 6b 04 21 6f e5 f3 54 ac 77 25 0a 4b 6b 0c 85\ +25 a8 5c 59 b0 bd 80 c5 64 50 a2 2d 5f 43 8e 59\ +6a 33 3a a8 75 e2 91 dd 43 f4 8c b8 8b 9d 5f c0\ +d4 99 f9 fc d1 c3 97 f9 af c0 70 cd 9e 39 8c 8d\ +19 e6 1d b7 c7 41 0a 6b 26 75 df bf 5d 34 5b 80\ +4d 20 1a dd 50 2d 5c e2 df cb 09 1c e9 99 7b be\ +be 57 30 6f 38 3e 4d 58 81 03 f0 36 f7 e8 5d 19\ +34 d1 52 a3 23 e4 a8 db 45 1d 6f 4a 5b 1b 0f 10\ +2c c1 50 e0 2f ee e2 b8 8d ea 4a d4 c1 ba cc b2\ +4d 84 07 2d 14 e1 d2 4a 67 71 f7 40 8e e3 05 64\ +fb 86 d4 39 3a 34 bc f0 b7 88 50 1d 19 33 03 f1\ +3a 22 84 b0 01 f0 f6 49 ea f7 93 28 d4 ac 5c 43\ +0a b4 41 49 20 a9 46 0e d1 b7 bc 40 ec 65 3e 87\ +6d 09 ab c5 09 ae 45 b5 25 19 01 16 a0 c2 61 01\ +84 82 98 50 9c 1c 3b f3 a4 83 e7 27 40 54 e1 5e\ +97 07 50 36 e9 89 f6 09 32 80 7b 52 57 75 1e 79 +Prime1: \ +ec f5 ae cd 1e 55 15 ff fa cb d7 5a 28 16 c6 eb\ +f4 90 18 cd fb 46 38 e1 85 d6 6a 73 96 b6 f8 09\ +0f 80 18 c7 fd 95 cc 34 b8 57 dc 17 f0 cc 65 16\ +bb 13 46 ab 4d 58 2c ad ad 7b 41 03 35 23 87 b7\ +03 38 d0 84 04 7c 9d 95 39 b6 49 62 04 b3 dd 6e\ +a4 42 49 92 07 be c0 1f 96 42 87 ff 63 36 c3 98\ +46 58 33 68 46 f5 6e 46 86 18 81 c1 02 33 d2 17\ +6b f1 5a 5e 96 dd c7 80 bc 86 8a a7 7d 3c e7 69 +Prime2: \ +bc 46 c4 64 fc 6a c4 ca 78 3b 0e b0 8a 3c 84 1b\ +77 2f 7e 9b 2f 28 ba bd 58 8a e8 85 e1 a0 c6 1e\ +48 58 a0 fb 25 ac 29 99 90 f3 5b e8 51 64 c2 59\ +ba 11 75 cd d7 19 27 07 13 51 84 99 2b 6c 29 b7\ +46 dd 0d 2c ab e1 42 83 5f 7d 14 8c c1 61 52 4b\ +4a 09 94 6d 48 b8 28 47 3f 1c e7 6b 6c b6 88 6c\ +34 5c 03 e0 5f 41 d5 1b 5c 3a 90 a3 f2 40 73 c7\ +d7 4a 4f e2 5d 9c f2 1c 75 96 0f 3f c3 86 31 83 +ModPrime1PrivateExponent: \ +c7 35 64 57 1d 00 fb 15 d0 8a 3d e9 95 7a 50 91\ +5d 71 26 e9 44 2d ac f4 2b c8 2e 86 2e 56 73 ff\ +6a 00 8e d4 d2 e3 74 61 7d f8 9f 17 a1 60 b4 3b\ +7f da 9c b6 b6 b7 42 18 60 98 15 f7 d4 5c a2 63\ +c1 59 aa 32 d2 72 d1 27 fa f4 bc 8c a2 d7 73 78\ +e8 ae b1 9b 0a d7 da 3c b3 de 0a e7 31 49 80 f6\ +2b 6d 4b 0a 87 5d 1d f0 3c 1b ae 39 cc d8 33 ef\ +6c d7 e2 d9 52 8b f0 84 d1 f9 69 e7 94 e9 f6 c1 +ModPrime2PrivateExponent: \ +26 58 b3 7f 6d f9 c1 03 0b e1 db 68 11 7f a9 d8\ +7e 39 ea 2b 69 3b 7e 6d 3a 2f 70 94 74 13 ee c6\ +14 2e 18 fb 8d fc b6 ac 54 5d 7c 86 a0 ad 48 f8\ +45 71 70 f0 ef b2 6b c4 81 26 c5 3e fd 1d 16 92\ +01 98 dc 2a 11 07 dc 28 2d b6 a8 0c d3 06 23 60\ +ba 3f a1 3f 70 e4 31 2f f1 a6 cd 6b 8f c4 cd 9c\ +5c 3d b1 7c 6d 6a 57 21 2f 73 ae 29 f6 19 32 7b\ +ad 59 b1 53 85 85 85 ba 4e 28 b6 0a 62 a4 5e 49 +MultiplicativeInverseOfPrime2ModPrime1: \ +6f 38 52 6b 39 25 08 55 34 ef 3e 41 5a 83 6e de\ +8b 86 15 8a 2c 7c bf ec cb 0b d8 34 30 4f ec 68\ +3b a8 d4 f4 79 c4 33 d4 34 16 e6 32 69 62 3c ea\ +10 07 76 d8 5a ff 40 1d 3f ff 61 0e e6 54 11 ce\ +3b 13 63 d6 3a 97 09 ee de 42 64 7c ea 56 14 93\ +d5 45 70 a8 79 c1 86 82 cd 97 71 0b 96 20 5e c3\ +11 17 d7 3b 5f 36 22 3f ad d6 e8 ba 90 dd 7c 0e\ +e6 1d 44 e1 63 25 1e 20 c7 f6 6e b3 05 11 7c b8 +Test: KeyPairValidAndConsistent +Comment: RSAES-OAEP Encryption Example 10.1 +Plaintext: \ +8b ba 6b f8 2a 6c 0f 86 d5 f1 75 6e 97 95 68 70\ +b0 89 53 b0 6b 4e b2 05 bc 16 94 ee +Seed: # not used yet\ +47 e1 ab 71 19 fe e5 6c 95 ee 5e aa d8 6f 40 d0\ +aa 63 bd 33 +Ciphertext: \ +53 ea 5d c0 8c d2 60 fb 3b 85 85 67 28 7f a9 15\ +52 c3 0b 2f eb fb a2 13 f0 ae 87 70 2d 06 8d 19\ +ba b0 7f e5 74 52 3d fb 42 13 9d 68 c3 c5 af ee\ +e0 bf e4 cb 79 69 cb f3 82 b8 04 d6 e6 13 96 14\ +4e 2d 0e 60 74 1f 89 93 c3 01 4b 58 b9 b1 95 7a\ +8b ab cd 23 af 85 4f 4c 35 6f b1 66 2a a7 2b fc\ +c7 e5 86 55 9d c4 28 0d 16 0c 12 67 85 a7 23 eb\ +ee be ff 71 f1 15 94 44 0a ae f8 7d 10 79 3a 87\ +74 a2 39 d4 a0 4c 87 fe 14 67 b9 da f8 52 08 ec\ +6c 72 55 79 4a 96 cc 29 14 2f 9a 8b d4 18 e3 c1\ +fd 67 34 4b 0c d0 82 9d f3 b2 be c6 02 53 19 62\ +93 c6 b3 4d 3f 75 d3 2f 21 3d d4 5c 62 73 d5 05\ +ad f4 cc ed 10 57 cb 75 8f c2 6a ee fa 44 12 55\ +ed 4e 64 c1 99 ee 07 5e 7f 16 64 61 82 fd b4 64\ +73 9b 68 ab 5d af f0 e6 3e 95 52 01 68 24 f0 54\ +bf 4d 3c 8c 90 a9 7b b6 b6 55 32 84 eb 42 9f cc +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 10.2 +Plaintext: \ +e6 ad 18 1f 05 3b 58 a9 04 f2 45 75 10 37 3e 57 +Seed: # not used yet\ +6d 17 f5 b4 c1 ff ac 35 1d 19 5b f7 b0 9d 09 f0\ +9a 40 79 cf +Ciphertext: \ +a2 b1 a4 30 a9 d6 57 e2 fa 1c 2b b5 ed 43 ff b2\ +5c 05 a3 08 fe 90 93 c0 10 31 79 5f 58 74 40 01\ +10 82 8a e5 8f b9 b5 81 ce 9d dd d3 e5 49 ae 04\ +a0 98 54 59 bd e6 c6 26 59 4e 7b 05 dc 42 78 b2\ +a1 46 5c 13 68 40 88 23 c8 5e 96 dc 66 c3 a3 09\ +83 c6 39 66 4f c4 56 9a 37 fe 21 e5 a1 95 b5 77\ +6e ed 2d f8 d8 d3 61 af 68 6e 75 02 29 bb d6 63\ +f1 61 86 8a 50 61 5e 0c 33 7b ec 0c a3 5f ec 0b\ +b1 9c 36 eb 2e 0b bc c0 58 2f a1 d9 3a ac db 06\ +10 63 f5 9f 2c e1 ee 43 60 5e 5d 89 ec a1 83 d2\ +ac df e9 f8 10 11 02 2a d3 b4 3a 3d d4 17 da c9\ +4b 4e 11 ea 81 b1 92 96 6e 96 6b 18 20 82 e7 19\ +64 60 7b 4f 80 02 f3 62 99 84 4a 11 f2 ae 0f ae\ +ac 2e ae 70 f8 f4 f9 80 88 ac dc d0 ac 55 6e 9f\ +cc c5 11 52 19 08 fa d2 6f 04 c6 42 01 45 03 05\ +77 87 58 b0 53 8b f8 b5 bb 14 4a 82 8e 62 97 95 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 10.3 +Plaintext: \ +51 0a 2c f6 0e 86 6f a2 34 05 53 c9 4e a3 9f bc\ +25 63 11 e8 3e 94 45 4b 41 24 +Seed: # not used yet\ +38 53 87 51 4d ec cc 7c 74 0d d8 cd f9 da ee 49\ +a1 cb fd 54 +Ciphertext: \ +98 86 c3 e6 76 4a 8b 9a 84 e8 41 48 eb d8 c3 b1\ +aa 80 50 38 1a 78 f6 68 71 4c 16 d9 cf d2 a6 ed\ +c5 69 79 c5 35 d9 de e3 b4 4b 85 c1 8b e8 92 89\ +92 37 17 11 47 22 16 d9 5d da 98 d2 ee 83 47 c9\ +b1 4d ff df f8 4a a4 8d 25 ac 06 f7 d7 e6 53 98\ +ac 96 7b 1c e9 09 25 f6 7d ce 04 9b 7f 81 2d b0\ +74 29 97 a7 4d 44 fe 81 db e0 e7 a3 fe af 2e 5c\ +40 af 88 8d 55 0d db be 3b c2 06 57 a2 95 43 f8\ +fc 29 13 b9 bd 1a 61 b2 ab 22 56 ec 40 9b bd 7d\ +c0 d1 77 17 ea 25 c4 3f 42 ed 27 df 87 38 bf 4a\ +fc 67 66 ff 7a ff 08 59 55 5e e2 83 92 0f 4c 8a\ +63 c4 a7 34 0c ba fd dc 33 9e cd b4 b0 51 50 02\ +f9 6c 93 2b 5b 79 16 7a f6 99 c0 ad 3f cc fd f0\ +f4 4e 85 a7 02 62 bf 2e 18 fe 34 b8 50 58 99 75\ +e8 67 ff 96 9d 48 ea bf 21 22 71 54 6c dc 05 a6\ +9e cb 52 6e 52 87 0c 83 6f 30 7b d7 98 78 0e de +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 10.4 +Plaintext: \ +bc dd 19 0d a3 b7 d3 00 df 9a 06 e2 2c aa e2 a7\ +5f 10 c9 1f f6 67 b7 c1 6b de 8b 53 06 4a 26 49\ +a9 40 45 c9 +Seed: # not used yet\ +5c ac a6 a0 f7 64 16 1a 96 84 f8 5d 92 b6 e0 ef\ +37 ca 8b 65 +Ciphertext: \ +63 18 e9 fb 5c 0d 05 e5 30 7e 16 83 43 6e 90 32\ +93 ac 46 42 35 8a aa 22 3d 71 63 01 3a ba 87 e2\ +df da 8e 60 c6 86 0e 29 a1 e9 26 86 16 3e a0 b9\ +17 5f 32 9c a3 b1 31 a1 ed d3 a7 77 59 a8 b9 7b\ +ad 6a 4f 8f 43 96 f2 8c f6 f3 9c a5 81 12 e4 81\ +60 d6 e2 03 da a5 85 6f 3a ca 5f fe d5 77 af 49\ +94 08 e3 df d2 33 e3 e6 04 db e3 4a 9c 4c 90 82\ +de 65 52 7c ac 63 31 d2 9d c8 0e 05 08 a0 fa 71\ +22 e7 f3 29 f6 cc a5 cf a3 4d 4d 1d a4 17 80 54\ +57 e0 08 be c5 49 e4 78 ff 9e 12 a7 63 c4 77 d1\ +5b bb 78 f5 b6 9b d5 78 30 fc 2c 4e d6 86 d7 9b\ +c7 2a 95 d8 5f 88 13 4c 6b 0a fe 56 a8 cc fb c8\ +55 82 8b b3 39 bd 17 90 9c f1 d7 0d e3 33 5a e0\ +70 39 09 3e 60 6d 65 53 65 de 65 50 b8 72 cd 6d\ +e1 d4 40 ee 03 1b 61 94 5f 62 9a d8 a3 53 b0 d4\ +09 39 e9 6a 3c 45 0d 2a 8d 5e ee 9f 67 80 93 c8 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 10.5 +Plaintext: \ +a7 dd 6c 7d c2 4b 46 f9 dd 5f 1e 91 ad a4 c3 b3\ +df 94 7e 87 72 32 a9 +Seed: # not used yet\ +95 bc a9 e3 85 98 94 b3 dd 86 9f a7 ec d5 bb c6\ +40 1b f3 e4 +Ciphertext: \ +75 29 08 72 cc fd 4a 45 05 66 0d 65 1f 56 da 6d\ +aa 09 ca 13 01 d8 90 63 2f 6a 99 2f 3d 56 5c ee\ +46 4a fd ed 40 ed 3b 5b e9 35 67 14 ea 5a a7 65\ +5f 4a 13 66 c2 f1 7c 72 8f 6f 2c 5a 5d 1f 8e 28\ +42 9b c4 e6 f8 f2 cf f8 da 8d c0 e0 a9 80 8e 45\ +fd 09 ea 2f a4 0c b2 b6 ce 6f ff f5 c0 e1 59 d1\ +1b 68 d9 0a 85 f7 b8 4e 10 3b 09 e6 82 66 64 80\ +c6 57 50 5c 09 29 25 94 68 a3 14 78 6d 74 ea b1\ +31 57 3c f2 34 bf 57 db 7d 9e 66 cc 67 48 19 2e\ +00 2d c0 de ea 93 05 85 f0 83 1f dc d9 bc 33 d5\ +1f 79 ed 2f fc 16 bc f4 d5 98 12 fc eb ca a3 f9\ +06 9b 0e 44 56 86 d6 44 c2 5c cf 63 b4 56 ee 5f\ +a6 ff e9 6f 19 cd f7 51 fe d9 ea f3 59 57 75 4d\ +bf 4b fe a5 21 6a a1 84 4d c5 07 cb 2d 08 0e 72\ +2e ba 15 03 08 c2 b5 ff 11 93 62 0f 17 66 ec f4\ +48 1b af b9 43 bd 29 28 77 f2 13 6c a4 94 ab a0 +Test: DecryptMatch +Comment: RSAES-OAEP Encryption Example 10.6 +Plaintext: \ +ea f1 a7 3a 1b 0c 46 09 53 7d e6 9c d9 22 8b bc\ +fb 9a 8c a8 c6 c3 ef af 05 6f e4 a7 f4 63 4e d0\ +0b 7c 39 ec 69 22 d7 b8 ea 2c 04 eb ac +Seed: # not used yet\ +9f 47 dd f4 2e 97 ee a8 56 a9 bd bc 71 4e b3 ac\ +22 f6 eb 32 +Ciphertext: \ +2d 20 7a 73 43 2a 8f b4 c0 30 51 b3 f7 3b 28 a6\ +17 64 09 8d fa 34 c4 7a 20 99 5f 81 15 aa 68 16\ +67 9b 55 7e 82 db ee 58 49 08 c6 e6 97 82 d7 de\ +b3 4d bd 65 af 06 3d 57 fc a7 6a 5f d0 69 49 2f\ +d6 06 8d 99 84 d2 09 35 05 65 a6 2e 5c 77 f2 30\ +38 c1 2c b1 0c 66 34 70 9b 54 7c 46 f6 b4 a7 09\ +bd 85 ca 12 2d 74 46 5e f9 77 62 c2 97 63 e0 6d\ +bc 7a 9e 73 8c 78 bf ca 01 02 dc 5e 79 d6 5b 97\ +3f 28 24 0c aa b2 e1 61 a7 8b 57 d2 62 45 7e d8\ +19 5d 53 e3 c7 ae 9d a0 21 88 3c 6d b7 c2 4a fd\ +d2 32 2e ac 97 2a d3 c3 54 c5 fc ef 1e 14 6c 3a\ +02 90 fb 67 ad f0 07 06 6e 00 42 8d 2c ec 18 ce\ +58 f9 32 86 98 de fe f4 b2 eb 5e c7 69 18 fd e1\ +c1 98 cb b3 8b 7a fc 67 62 6a 9a ef ec 43 22 bf\ +d9 0d 25 63 48 1c 9a 22 1f 78 c8 27 2c 82 d1 b6\ +2a b9 14 e1 c6 9f 6a f6 ef 30 ca 52 60 db 4a 46 +Test: DecryptMatch diff --git a/src-cryptopp/TestVectors/rsa_pkcs1_1_5.txt b/src-cryptopp/TestVectors/rsa_pkcs1_1_5.txt new file mode 100644 index 0000000..2272b7c --- /dev/null +++ b/src-cryptopp/TestVectors/rsa_pkcs1_1_5.txt @@ -0,0 +1,89 @@ +AlgorithmType: Signature +Name: RSA/PKCS1-1.5(MD2) +KeyFormat: DER +Source: http://www.rsasecurity.com/rsalabs/pkcs/index.html, \ + Some Examples of the PKCS Standards +PrivateKey: \ + 30 82 01 50\ + 02 01 00 #version = 0\ + 30 0d #privateKeyAlgorithmIdentifier\ + 06 09 #algorithm = rsaEncryption\ + 2a 86 48 86 f7 0d 01 01 01\ + 05 00 #parameters = NULL\ + 04 82 01 3a #privateKey = RSAPrivateKey encoding\ + 30 82 01 36\ + 02 01 00 #version = 0\ + 02 40 #modulus = n\ + 0a 66 79 1d c6 98 81 68 de 7a b7 74 19 bb 7f b0\ + c0 01 c6 27 10 27 00 75 14 29 42 e1 9a 8d 8c 51\ + d0 53 b3 e3 78 2a 1d e5 dc 5a f4 eb e9 94 68 17\ + 01 14 a1 df e6 7c dc 9a 9a f5 5d 65 56 20 bb ab\ + 02 03 01 00 01 #publicExponent = e\ + 02 40 #privateExponent = d\ + 01 23 c5 b6 1b a3 6e db 1d 36 79 90 41 99 a8 9e\ + a8 0c 09 b9 12 2e 14 00 c0 9a dc f7 78 46 76 d0\ + 1d 23 35 6a 7d 44 d6 bd 8b d5 0e 94 bf c7 23 fa\ + 87 d8 86 2b 75 17 76 91 c1 1d 75 76 92 df 88 81\ + 02 20 #prime1 = p\ + 33 d4 84 45 c8 59 e5 23 40 de 70 4b cd da 06 5f\ + bb 40 58 d7 40 bd 1d 67 d2 9e 9c 14 6c 11 cf 61\ + 02 20 #prime2 = q\ + 33 5e 84 08 86 6b 0f d3 8d c7 00 2d 3f 97 2c 67\ + 38 9a 65 d5 d8 30 65 66 d5 c4 f2 a5 aa 52 62 8b\ + 02 20 #exponent1 = d mod p-1\ + 04 5e c9 00 71 52 53 25 d3 d4 6d b7 96 95 e9 af\ + ac c4 52 39 64 36 0e 02 b1 19 ba a3 66 31 62 41\ + 02 20 #exponent2 = d mod q-1\ + 15 eb 32 73 60 c7 b6 0d 12 e5 e2 d1 6b dc d9 79\ + 81 d1 7f ba 6b 70 db 13 b2 0b 43 6e 24 ea da 59\ + 02 20 #coefficient = q-1 mod p\ + 2c a6 36 6d 72 78 1d fa 24 d3 4a 9a 24 cb c2 ae\ + 92 7a 99 58 af 42 65 63 ff 63 fb 11 65 8a 46 1d +PublicKey: \ + 30 5b #subjectPublicKeyInfo\ + 30 0d #algorithm\ + 06 09 #algorithm = rsaEncryption\ + 2a 86 48 86 f7 0d 01 01 01\ + 05 00 #parameters = NULL\ + 03 4a #subjectPublicKey = RSAPublicKey encoding\ + 00\ + 30 47\ + 02 40 #modulus = n\ + 0a 66 79 1d c6 98 81 68 de 7a b7 74 19 bb 7f b0\ + c0 01 c6 27 10 27 00 75 14 29 42 e1 9a 8d 8c 51\ + d0 53 b3 e3 78 2a 1d e5 dc 5a f4 eb e9 94 68 17\ + 01 14 a1 df e6 7c dc 9a 9a f5 5d 65 56 20 bb ab\ + 02 03 01 00 01 #publicExponent = e +Test: KeyPairValidAndConsistent +Message: # "Everyone gets Friday off."\ + 45 76 65 72 79 6f 6e 65 20 67 65 74 73 20 46 72 69 64 61 79 20 6f 66 66 2e +Signature: \ + 05fa6a812fc7df8bf4f2542509e03e84\ + 6e11b9c620be2009efb440efbcc66921\ + 6994ac04f341b57d05202d428fb2a27b\ + 5c77dfd9b15bfc3d559353503410c1e1 +Test: Verify +Name: RSA/PKCS1-1.5(SHA-1) +Source: generated by Wei Dai using Crypto++ 5.0 +Signature: 0610761F95FFD1B8F29DA34212947EC2AA0E358866A722F03CC3C41487ADC604A48FF54F5C6BEDB9FB7BD59F82D6E55D8F3174BA361B2214B2D74E8825E04E81 +Test: Verify +Message: 00 +Test: NotVerify + +AlgorithmType: Signature +Name: RSA/PKCS1-1.5(SHA-1) +Source: http://islab.oregonstate.edu/emails/pkcs-tng-02/0152 +KeyFormat: Component +Modulus: A885B6F851A8079AB8A281DB0297148511EE0D8C07C0D4AE6D6FED461488E0D41E3FF8F281B06A3240B5007A5C2AB4FB6BE8AF88F119DB998368DDDC9710ABED +PublicExponent: 010001 +PrivateExponent: 2B259D2CA3DF851EE891F6F4678BDDFD9A131C95D3305C63D2723B4A5B9C960F5EC8BB7DCDDBEBD8B6A38767D64AD451E9383E0891E4EE7506100481F2B49323 +Prime1: D7103CD676E39824E2BE50B8E6533FE7CB7484348E283802AD2B8D00C80D19DF +Prime2: C89996DC169CEB3F227958275968804D4BE9FC4012C3219662F1A438C9950BB3 +ModPrime1PrivateExponent: 5D8EA4C8AF83A70634D5920C3DB66D908AC3AF57A597FD75BC9BBB856181C185 +ModPrime2PrivateExponent: C598E54DAEC8ABC1E907769A6C2BD01653ED0C9960E1EDB7E186FDA922883A99 +MultiplicativeInverseOfPrime2ModPrime1: 7C6F27B5B51B78AD80FB36E700990CF307866F2943124CBD93D97C137794C104 +Test: KeyPairValidAndConsistent +Source: generated by Wei Dai using Crypto++ 5.0 +Message: 74657374 # "test" +Signature: A7E00CE4391F914D82158D9B732759808E25A1C6383FE87A5199157650D4296CF612E9FF809E686A0AF328238306E79965F6D0138138829D9A1A22764306F6CE +Test: Verify diff --git a/src-cryptopp/TestVectors/rsa_pss.txt b/src-cryptopp/TestVectors/rsa_pss.txt new file mode 100644 index 0000000..1b5fc9c --- /dev/null +++ b/src-cryptopp/TestVectors/rsa_pss.txt @@ -0,0 +1,2083 @@ +AlgorithmType: Signature +Name: RSA/PSS-MGF1(SHA-1) +Source: http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/, PKCS #1 test vectors +KeyFormat: Component +Comment: Example 1: A 1024-bit RSA Key Pair +Modulus: \ +a5 6e 4a 0e 70 10 17 58 9a 51 87 dc 7e a8 41 d1\ +56 f2 ec 0e 36 ad 52 a4 4d fe b1 e6 1f 7a d9 91\ +d8 c5 10 56 ff ed b1 62 b4 c0 f2 83 a1 2a 88 a3\ +94 df f5 26 ab 72 91 cb b3 07 ce ab fc e0 b1 df\ +d5 cd 95 08 09 6d 5b 2b 8b 6d f5 d6 71 ef 63 77\ +c0 92 1c b2 3c 27 0a 70 e2 59 8e 6f f8 9d 19 f1\ +05 ac c2 d3 f0 cb 35 f2 92 80 e1 38 6b 6f 64 c4\ +ef 22 e1 e1 f2 0d 0c e8 cf fb 22 49 bd 9a 21 37 +PublicExponent: \ +01 00 01 +PrivateExponent: \ +33 a5 04 2a 90 b2 7d 4f 54 51 ca 9b bb d0 b4 47\ +71 a1 01 af 88 43 40 ae f9 88 5f 2a 4b be 92 e8\ +94 a7 24 ac 3c 56 8c 8f 97 85 3a d0 7c 02 66 c8\ +c6 a3 ca 09 29 f1 e8 f1 12 31 88 44 29 fc 4d 9a\ +e5 5f ee 89 6a 10 ce 70 7c 3e d7 e7 34 e4 47 27\ +a3 95 74 50 1a 53 26 83 10 9c 2a ba ca ba 28 3c\ +31 b4 bd 2f 53 c3 ee 37 e3 52 ce e3 4f 9e 50 3b\ +d8 0c 06 22 ad 79 c6 dc ee 88 35 47 c6 a3 b3 25 +Prime1: \ +e7 e8 94 27 20 a8 77 51 72 73 a3 56 05 3e a2 a1\ +bc 0c 94 aa 72 d5 5c 6e 86 29 6b 2d fc 96 79 48\ +c0 a7 2c bc cc a7 ea cb 35 70 6e 09 a1 df 55 a1\ +53 5b d9 b3 cc 34 16 0b 3b 6d cd 3e da 8e 64 43 +Prime2: \ +b6 9d ca 1c f7 d4 d7 ec 81 e7 5b 90 fc ca 87 4a\ +bc de 12 3f d2 70 01 80 aa 90 47 9b 6e 48 de 8d\ +67 ed 24 f9 f1 9d 85 ba 27 58 74 f5 42 cd 20 dc\ +72 3e 69 63 36 4a 1f 94 25 45 2b 26 9a 67 99 fd +ModPrime1PrivateExponent: \ +28 fa 13 93 86 55 be 1f 8a 15 9c ba ca 5a 72 ea\ +19 0c 30 08 9e 19 cd 27 4a 55 6f 36 c4 f6 e1 9f\ +55 4b 34 c0 77 79 04 27 bb dd 8d d3 ed e2 44 83\ +28 f3 85 d8 1b 30 e8 e4 3b 2f ff a0 27 86 19 79 +ModPrime2PrivateExponent: \ +1a 8b 38 f3 98 fa 71 20 49 89 8d 7f b7 9e e0 a7\ +76 68 79 12 99 cd fa 09 ef c0 e5 07 ac b2 1e d7\ +43 01 ef 5b fd 48 be 45 5e ae b6 e1 67 82 55 82\ +75 80 a8 e4 e8 e1 41 51 d1 51 0a 82 a3 f2 e7 29 +MultiplicativeInverseOfPrime2ModPrime1: \ +27 15 6a ba 41 26 d2 4a 81 f3 a5 28 cb fb 27 f5\ +68 86 f8 40 a9 f6 e8 6e 17 a4 4b 94 fe 93 19 58\ +4b 8e 22 fd de 1e 5a 2e 3b d8 aa 5b a8 d8 58 41\ +94 eb 21 90 ac f8 32 b8 47 f1 3a 3d 24 a7 9f 4d +Test: KeyPairValidAndConsistent +Comment: RSASSA-PSS Signature Example 1.1 +Message: \ +cd c8 7d a2 23 d7 86 df 3b 45 e0 bb bc 72 13 26\ +d1 ee 2a f8 06 cc 31 54 75 cc 6f 0d 9c 66 e1 b6\ +23 71 d4 5c e2 39 2e 1a c9 28 44 c3 10 10 2f 15\ +6a 0d 8d 52 c1 f4 c4 0b a3 aa 65 09 57 86 cb 76\ +97 57 a6 56 3b a9 58 fe d0 bc c9 84 e8 b5 17 a3\ +d5 f5 15 b2 3b 8a 41 e7 4a a8 67 69 3f 90 df b0\ +61 a6 e8 6d fa ae e6 44 72 c0 0e 5f 20 94 57 29\ +cb eb e7 7f 06 ce 78 e0 8f 40 98 fb a4 1f 9d 61\ +93 c0 31 7e 8b 60 d4 b6 08 4a cb 42 d2 9e 38 08\ +a3 bc 37 2d 85 e3 31 17 0f cb f7 cc 72 d0 b7 1c\ +29 66 48 b3 a4 d1 0f 41 62 95 d0 80 7a a6 25 ca\ +b2 74 4f d9 ea 8f d2 23 c4 25 37 02 98 28 bd 16\ +be 02 54 6f 13 0f d2 e3 3b 93 6d 26 76 e0 8a ed\ +1b 73 31 8b 75 0a 01 67 d0 +Salt: \ +de e9 59 c7 e0 64 11 36 14 20 ff 80 18 5e d5 7f\ +3e 67 76 af +Signature: \ +90 74 30 8f b5 98 e9 70 1b 22 94 38 8e 52 f9 71\ +fa ac 2b 60 a5 14 5a f1 85 df 52 87 b5 ed 28 87\ +e5 7c e7 fd 44 dc 86 34 e4 07 c8 e0 e4 36 0b c2\ +26 f3 ec 22 7f 9d 9e 54 63 8e 8d 31 f5 05 12 15\ +df 6e bb 9c 2f 95 79 aa 77 59 8a 38 f9 14 b5 b9\ +c1 bd 83 c4 e2 f9 f3 82 a0 d0 aa 35 42 ff ee 65\ +98 4a 60 1b c6 9e b2 8d eb 27 dc a1 2c 82 c2 d4\ +c3 f6 6c d5 00 f1 ff 2b 99 4d 8a 4e 30 cb b3 3c +Test: Verify +Comment: RSASSA-PSS Signature Example 1.2 +Message: \ +85 13 84 cd fe 81 9c 22 ed 6c 4c cb 30 da eb 5c\ +f0 59 bc 8e 11 66 b7 e3 53 0c 4c 23 3e 2b 5f 8f\ +71 a1 cc a5 82 d4 3e cc 72 b1 bc a1 6d fc 70 13\ +22 6b 9e +Salt: \ +ef 28 69 fa 40 c3 46 cb 18 3d ab 3d 7b ff c9 8f\ +d5 6d f4 2d +Signature: \ +3e f7 f4 6e 83 1b f9 2b 32 27 41 42 a5 85 ff ce\ +fb dc a7 b3 2a e9 0d 10 fb 0f 0c 72 99 84 f0 4e\ +f2 9a 9d f0 78 07 75 ce 43 73 9b 97 83 83 90 db\ +0a 55 05 e6 3d e9 27 02 8d 9d 29 b2 19 ca 2c 45\ +17 83 25 58 a5 5d 69 4a 6d 25 b9 da b6 60 03 c4\ +cc cd 90 78 02 19 3b e5 17 0d 26 14 7d 37 b9 35\ +90 24 1b e5 1c 25 05 5f 47 ef 62 75 2c fb e2 14\ +18 fa fe 98 c2 2c 4d 4d 47 72 4f db 56 69 e8 43 +Test: Verify +Comment: RSASSA-PSS Signature Example 1.3 +Message: \ +a4 b1 59 94 17 61 c4 0c 6a 82 f2 b8 0d 1b 94 f5\ +aa 26 54 fd 17 e1 2d 58 88 64 67 9b 54 cd 04 ef\ +8b d0 30 12 be 8d c3 7f 4b 83 af 79 63 fa ff 0d\ +fa 22 54 77 43 7c 48 01 7f f2 be 81 91 cf 39 55\ +fc 07 35 6e ab 3f 32 2f 7f 62 0e 21 d2 54 e5 db\ +43 24 27 9f e0 67 e0 91 0e 2e 81 ca 2c ab 31 c7\ +45 e6 7a 54 05 8e b5 0d 99 3c db 9e d0 b4 d0 29\ +c0 6d 21 a9 4c a6 61 c3 ce 27 fa e1 d6 cb 20 f4\ +56 4d 66 ce 47 67 58 3d 0e 5f 06 02 15 b5 90 17\ +be 85 ea 84 89 39 12 7b d8 c9 c4 d4 7b 51 05 6c\ +03 1c f3 36 f1 7c 99 80 f3 b8 f5 b9 b6 87 8e 8b\ +79 7a a4 3b 88 26 84 33 3e 17 89 3f e9 ca a6 aa\ +29 9f 7e d1 a1 8e e2 c5 48 64 b7 b2 b9 9b 72 61\ +8f b0 25 74 d1 39 ef 50 f0 19 c9 ee f4 16 97 13\ +38 e7 d4 70 +Salt: \ +71 0b 9c 47 47 d8 00 d4 de 87 f1 2a fd ce 6d f1\ +81 07 cc 77 +Signature: \ +66 60 26 fb a7 1b d3 e7 cf 13 15 7c c2 c5 1a 8e\ +4a a6 84 af 97 78 f9 18 49 f3 43 35 d1 41 c0 01\ +54 c4 19 76 21 f9 62 4a 67 5b 5a bc 22 ee 7d 5b\ +aa ff aa e1 c9 ba ca 2c c3 73 b3 f3 3e 78 e6 14\ +3c 39 5a 91 aa 7f ac a6 64 eb 73 3a fd 14 d8 82\ +72 59 d9 9a 75 50 fa ca 50 1e f2 b0 4e 33 c2 3a\ +a5 1f 4b 9e 82 82 ef db 72 8c c0 ab 09 40 5a 91\ +60 7c 63 69 96 1b c8 27 0d 2d 4f 39 fc e6 12 b1 +Test: Verify +Comment: RSASSA-PSS Signature Example 1.4 +Message: \ +bc 65 67 47 fa 9e af b3 f0 +Salt: \ +05 6f 00 98 5d e1 4d 8e f5 ce a9 e8 2f 8c 27 be\ +f7 20 33 5e +Signature: \ +46 09 79 3b 23 e9 d0 93 62 dc 21 bb 47 da 0b 4f\ +3a 76 22 64 9a 47 d4 64 01 9b 9a ea fe 53 35 9c\ +17 8c 91 cd 58 ba 6b cb 78 be 03 46 a7 bc 63 7f\ +4b 87 3d 4b ab 38 ee 66 1f 19 96 34 c5 47 a1 ad\ +84 42 e0 3d a0 15 b1 36 e5 43 f7 ab 07 c0 c1 3e\ +42 25 b8 de 8c ce 25 d4 f6 eb 84 00 f8 1f 7e 18\ +33 b7 ee 6e 33 4d 37 09 64 ca 79 fd b8 72 b4 d7\ +52 23 b5 ee b0 81 01 59 1f b5 32 d1 55 a6 de 87 +Test: Verify +Comment: RSASSA-PSS Signature Example 1.5 +Message: \ +b4 55 81 54 7e 54 27 77 0c 76 8e 8b 82 b7 55 64\ +e0 ea 4e 9c 32 59 4d 6b ff 70 65 44 de 0a 87 76\ +c7 a8 0b 45 76 55 0e ee 1b 2a ca bc 7e 8b 7d 3e\ +f7 bb 5b 03 e4 62 c1 10 47 ea dd 00 62 9a e5 75\ +48 0a c1 47 0f e0 46 f1 3a 2b f5 af 17 92 1d c4\ +b0 aa 8b 02 be e6 33 49 11 65 1d 7f 85 25 d1 0f\ +32 b5 1d 33 be 52 0d 3d df 5a 70 99 55 a3 df e7\ +82 83 b9 e0 ab 54 04 6d 15 0c 17 7f 03 7f dc cc\ +5b e4 ea 5f 68 b5 e5 a3 8c 9d 7e dc cc c4 97 5f\ +45 5a 69 09 b4 +Salt: \ +80 e7 0f f8 6a 08 de 3e c6 09 72 b3 9b 4f bf dc\ +ea 67 ae 8e +Signature: \ +1d 2a ad 22 1c a4 d3 1d df 13 50 92 39 01 93 98\ +e3 d1 4b 32 dc 34 dc 5a f4 ae ae a3 c0 95 af 73\ +47 9c f0 a4 5e 56 29 63 5a 53 a0 18 37 76 15 b1\ +6c b9 b1 3b 3e 09 d6 71 eb 71 e3 87 b8 54 5c 59\ +60 da 5a 64 77 6e 76 8e 82 b2 c9 35 83 bf 10 4c\ +3f db 23 51 2b 7b 4e 89 f6 33 dd 00 63 a5 30 db\ +45 24 b0 1c 3f 38 4c 09 31 0e 31 5a 79 dc d3 d6\ +84 02 2a 7f 31 c8 65 a6 64 e3 16 97 8b 75 9f ad +Test: Verify +Comment: RSASSA-PSS Signature Example 1.6 +Message: \ +10 aa e9 a0 ab 0b 59 5d 08 41 20 7b 70 0d 48 d7\ +5f ae dd e3 b7 75 cd 6b 4c c8 8a e0 6e 46 94 ec\ +74 ba 18 f8 52 0d 4f 5e a6 9c bb e7 cc 2b eb a4\ +3e fd c1 02 15 ac 4e b3 2d c3 02 a1 f5 3d c6 c4\ +35 22 67 e7 93 6c fe bf 7c 8d 67 03 57 84 a3 90\ +9f a8 59 c7 b7 b5 9b 8e 39 c5 c2 34 9f 18 86 b7\ +05 a3 02 67 d4 02 f7 48 6a b4 f5 8c ad 5d 69 ad\ +b1 7a b8 cd 0c e1 ca f5 02 5a f4 ae 24 b1 fb 87\ +94 c6 07 0c c0 9a 51 e2 f9 91 13 11 e3 87 7d 00\ +44 c7 1c 57 a9 93 39 50 08 80 6b 72 3a c3 83 73\ +d3 95 48 18 18 52 8c 1e 70 53 73 92 82 05 35 29\ +51 0e 93 5c d0 fa 77 b8 fa 53 cc 2d 47 4b d4 fb\ +3c c5 c6 72 d6 ff dc 90 a0 0f 98 48 71 2c 4b cf\ +e4 6c 60 57 36 59 b1 1e 64 57 e8 61 f0 f6 04 b6\ +13 8d 14 4f 8c e4 e2 da 73 +Salt: \ +a8 ab 69 dd 80 1f 00 74 c2 a1 fc 60 64 98 36 c6\ +16 d9 96 81 +Signature: \ +2a 34 f6 12 5e 1f 6b 0b f9 71 e8 4f bd 41 c6 32\ +be 8f 2c 2a ce 7d e8 b6 92 6e 31 ff 93 e9 af 98\ +7f bc 06 e5 1e 9b e1 4f 51 98 f9 1f 3f 95 3b d6\ +7d a6 0a 9d f5 97 64 c3 dc 0f e0 8e 1c be f0 b7\ +5f 86 8d 10 ad 3f ba 74 9f ef 59 fb 6d ac 46 a0\ +d6 e5 04 36 93 31 58 6f 58 e4 62 8f 39 aa 27 89\ +82 54 3b c0 ee b5 37 dc 61 95 80 19 b3 94 fb 27\ +3f 21 58 58 a0 a0 1a c4 d6 50 b9 55 c6 7f 4c 58 +Test: Verify +Comment: Example 2: A 1025-bit RSA Key Pair +Modulus: \ +01 d4 0c 1b cf 97 a6 8a e7 cd bd 8a 7b f3 e3 4f\ +a1 9d cc a4 ef 75 a4 74 54 37 5f 94 51 4d 88 fe\ +d0 06 fb 82 9f 84 19 ff 87 d6 31 5d a6 8a 1f f3\ +a0 93 8e 9a bb 34 64 01 1c 30 3a d9 91 99 cf 0c\ +7c 7a 8b 47 7d ce 82 9e 88 44 f6 25 b1 15 e5 e9\ +c4 a5 9c f8 f8 11 3b 68 34 33 6a 2f d2 68 9b 47\ +2c bb 5e 5c ab e6 74 35 0c 59 b6 c1 7e 17 68 74\ +fb 42 f8 fc 3d 17 6a 01 7e dc 61 fd 32 6c 4b 33\ +c9 +PublicExponent: \ +01 00 01 +PrivateExponent: \ +02 7d 14 7e 46 73 05 73 77 fd 1e a2 01 56 57 72\ +17 6a 7d c3 83 58 d3 76 04 56 85 a2 e7 87 c2 3c\ +15 57 6b c1 6b 9f 44 44 02 d6 bf c5 d9 8a 3e 88\ +ea 13 ef 67 c3 53 ec a0 c0 dd ba 92 55 bd 7b 8b\ +b5 0a 64 4a fd fd 1d d5 16 95 b2 52 d2 2e 73 18\ +d1 b6 68 7a 1c 10 ff 75 54 5f 3d b0 fe 60 2d 5f\ +2b 7f 29 4e 36 01 ea b7 b9 d1 ce cd 76 7f 64 69\ +2e 3e 53 6c a2 84 6c b0 c2 dd 48 6a 39 fa 75 b1 +Prime1: \ +01 66 01 e9 26 a0 f8 c9 e2 6e ca b7 69 ea 65 a5\ +e7 c5 2c c9 e0 80 ef 51 94 57 c6 44 da 68 91 c5\ +a1 04 d3 ea 79 55 92 9a 22 e7 c6 8a 7a f9 fc ad\ +77 7c 3c cc 2b 9e 3d 36 50 bc e4 04 39 9b 7e 59\ +d1 +Prime2: \ +01 4e af a1 d4 d0 18 4d a7 e3 1f 87 7d 12 81 dd\ +da 62 56 64 86 9e 83 79 e6 7a d3 b7 5e ae 74 a5\ +80 e9 82 7a bd 6e b7 a0 02 cb 54 11 f5 26 67 97\ +76 8f b8 e9 5a e4 0e 3e 8a 01 f3 5f f8 9e 56 c0\ +79 +ModPrime1PrivateExponent: \ +e2 47 cc e5 04 93 9b 8f 0a 36 09 0d e2 00 93 87\ +55 e2 44 4b 29 53 9a 7d a7 a9 02 f6 05 68 35 c0\ +db 7b 52 55 94 97 cf e2 c6 1a 80 86 d0 21 3c 47\ +2c 78 85 18 00 b1 71 f6 40 1d e2 e9 c2 75 6f 31 +ModPrime2PrivateExponent: \ +b1 2f ba 75 78 55 e5 86 e4 6f 64 c3 8a 70 c6 8b\ +3f 54 8d 93 d7 87 b3 99 99 9d 4c 8f 0b bd 25 81\ +c2 1e 19 ed 00 18 a6 d5 d3 df 86 42 4b 3a bc ad\ +40 19 9d 31 49 5b 61 30 9f 27 c1 bf 55 d4 87 c1 +MultiplicativeInverseOfPrime2ModPrime1: \ +56 4b 1e 1f a0 03 bd a9 1e 89 09 04 25 aa c0 5b\ +91 da 9e e2 50 61 e7 62 8d 5f 51 30 4a 84 99 2f\ +dc 33 76 2b d3 78 a5 9f 03 0a 33 4d 53 2b d0 da\ +e8 f2 98 ea 9e d8 44 63 6a d5 fb 8c bd c0 3c ad +Test: KeyPairValidAndConsistent +Comment: RSASSA-PSS Signature Example 2.1 +Message: \ +da ba 03 20 66 26 3f ae db 65 98 48 11 52 78 a5\ +2c 44 fa a3 a7 6f 37 51 5e d3 36 32 10 72 c4 0a\ +9d 9b 53 bc 05 01 40 78 ad f5 20 87 51 46 aa e7\ +0f f0 60 22 6d cb 7b 1f 1f c2 7e 93 60 +Salt: \ +57 bf 16 0b cb 02 bb 1d c7 28 0c f0 45 85 30 b7\ +d2 83 2f f7 +Signature: \ +01 4c 5b a5 33 83 28 cc c6 e7 a9 0b f1 c0 ab 3f\ +d6 06 ff 47 96 d3 c1 2e 4b 63 9e d9 13 6a 5f ec\ +6c 16 d8 88 4b dd 99 cf dc 52 14 56 b0 74 2b 73\ +68 68 cf 90 de 09 9a db 8d 5f fd 1d ef f3 9b a4\ +00 7a b7 46 ce fd b2 2d 7d f0 e2 25 f5 46 27 dc\ +65 46 61 31 72 1b 90 af 44 53 63 a8 35 8b 9f 60\ +76 42 f7 8f ab 0a b0 f4 3b 71 68 d6 4b ae 70 d8\ +82 78 48 d8 ef 1e 42 1c 57 54 dd f4 2c 25 89 b5\ +b3 +Test: Verify +Comment: RSASSA-PSS Signature Example 2.2 +Message: \ +e4 f8 60 1a 8a 6d a1 be 34 44 7c 09 59 c0 58 57\ +0c 36 68 cf d5 1d d5 f9 cc d6 ad 44 11 fe 82 13\ +48 6d 78 a6 c4 9f 93 ef c2 ca 22 88 ce bc 2b 9b\ +60 bd 04 b1 e2 20 d8 6e 3d 48 48 d7 09 d0 32 d1\ +e8 c6 a0 70 c6 af 9a 49 9f cf 95 35 4b 14 ba 61\ +27 c7 39 de 1b b0 fd 16 43 1e 46 93 8a ec 0c f8\ +ad 9e b7 2e 83 2a 70 35 de 9b 78 07 bd c0 ed 8b\ +68 eb 0f 5a c2 21 6b e4 0c e9 20 c0 db 0e dd d3\ +86 0e d7 88 ef ac ca ca 50 2d 8f 2b d6 d1 a7 c1\ +f4 1f f4 6f 16 81 c8 f1 f8 18 e9 c4 f6 d9 1a 0c\ +78 03 cc c6 3d 76 a6 54 4d 84 3e 08 4e 36 3b 8a\ +cc 55 aa 53 17 33 ed b5 de e5 b5 19 6e 9f 03 e8\ +b7 31 b3 77 64 28 d9 e4 57 fe 3f bc b3 db 72 74\ +44 2d 78 58 90 e9 cb 08 54 b6 44 4d ac e7 91 d7\ +27 3d e1 88 97 19 33 8a 77 fe +Salt: \ +7f 6d d3 59 e6 04 e6 08 70 e8 98 e4 7b 19 bf 2e\ +5a 7b 2a 90 +Signature: \ +01 09 91 65 6c ca 18 2b 7f 29 d2 db c0 07 e7 ae\ +0f ec 15 8e b6 75 9c b9 c4 5c 5f f8 7c 76 35 dd\ +46 d1 50 88 2f 4d e1 e9 ae 65 e7 f7 d9 01 8f 68\ +36 95 4a 47 c0 a8 1a 8a 6b 6f 83 f2 94 4d 60 81\ +b1 aa 7c 75 9b 25 4b 2c 34 b6 91 da 67 cc 02 26\ +e2 0b 2f 18 b4 22 12 76 1d cd 4b 90 8a 62 b3 71\ +b5 91 8c 57 42 af 4b 53 7e 29 69 17 67 4f b9 14\ +19 47 61 62 1c c1 9a 41 f6 fb 95 3f bc bb 64 9d\ +ea +Test: Verify +Comment: RSASSA-PSS Signature Example 2.3 +Message: \ +52 a1 d9 6c 8a c3 9e 41 e4 55 80 98 01 b9 27 a5\ +b4 45 c1 0d 90 2a 0d cd 38 50 d2 2a 66 d2 bb 07\ +03 e6 7d 58 67 11 45 95 aa bf 5a 7a eb 5a 8f 87\ +03 4b bb 30 e1 3c fd 48 17 a9 be 76 23 00 23 60\ +6d 02 86 a3 fa f8 a4 d2 2b 72 8e c5 18 07 9f 9e\ +64 52 6e 3a 0c c7 94 1a a3 38 c4 37 99 7c 68 0c\ +ca c6 7c 66 bf a1 +Salt: \ +fc a8 62 06 8b ce 22 46 72 4b 70 8a 05 19 da 17\ +e6 48 68 8c +Signature: \ +00 7f 00 30 01 8f 53 cd c7 1f 23 d0 36 59 fd e5\ +4d 42 41 f7 58 a7 50 b4 2f 18 5f 87 57 85 20 c3\ +07 42 af d8 43 59 b6 e6 e8 d3 ed 95 9d c6 fe 48\ +6b ed c8 e2 cf 00 1f 63 a7 ab e1 62 56 a1 b8 4d\ +f0 d2 49 fc 05 d3 19 4c e5 f0 91 27 42 db bf 80\ +dd 17 4f 6c 51 f6 ba d7 f1 6c f3 36 4e ba 09 5a\ +06 26 7d c3 79 38 03 ac 75 26 ae be 0a 47 5d 38\ +b8 c2 24 7a b5 1c 48 98 df 70 47 dc 6a df 52 c6\ +c4 +Test: Verify +Comment: RSASSA-PSS Signature Example 2.4 +Message: \ +a7 18 2c 83 ac 18 be 65 70 a1 06 aa 9d 5c 4e 3d\ +bb d4 af ae b0 c6 0c 4a 23 e1 96 9d 79 ff +Salt: \ +80 70 ef 2d e9 45 c0 23 87 68 4b a0 d3 30 96 73\ +22 35 d4 40 +Signature: \ +00 9c d2 f4 ed be 23 e1 23 46 ae 8c 76 dd 9a d3\ +23 0a 62 07 61 41 f1 6c 15 2b a1 85 13 a4 8e f6\ +f0 10 e0 e3 7f d3 df 10 a1 ec 62 9a 0c b5 a3 b5\ +d2 89 30 07 29 8c 30 93 6a 95 90 3b 6b a8 55 55\ +d9 ec 36 73 a0 61 08 fd 62 a2 fd a5 6d 1c e2 e8\ +5c 4d b6 b2 4a 81 ca 3b 49 6c 36 d4 fd 06 eb 7c\ +91 66 d8 e9 48 77 c4 2b ea 62 2b 3b fe 92 51 fd\ +c2 1d 8d 53 71 ba da d7 8a 48 82 14 79 63 35 b4\ +0b +Test: Verify +Comment: RSASSA-PSS Signature Example 2.5 +Message: \ +86 a8 3d 4a 72 ee 93 2a 4f 56 30 af 65 79 a3 86\ +b7 8f e8 89 99 e0 ab d2 d4 90 34 a4 bf c8 54 dd\ +94 f1 09 4e 2e 8c d7 a1 79 d1 95 88 e4 ae fc 1b\ +1b d2 5e 95 e3 dd 46 1f +Salt: \ +17 63 9a 4e 88 d7 22 c4 fc a2 4d 07 9a 8b 29 c3\ +24 33 b0 c9 +Signature: \ +00 ec 43 08 24 93 1e bd 3b aa 43 03 4d ae 98 ba\ +64 6b 8c 36 01 3d 16 71 c3 cf 1c f8 26 0c 37 4b\ +19 f8 e1 cc 8d 96 50 12 40 5e 7e 9b f7 37 86 12\ +df cc 85 fc e1 2c da 11 f9 50 bd 0b a8 87 67 40\ +43 6c 1d 25 95 a6 4a 1b 32 ef cf b7 4a 21 c8 73\ +b3 cc 33 aa f4 e3 dc 39 53 de 67 f0 67 4c 04 53\ +b4 fd 9f 60 44 06 d4 41 b8 16 09 8c b1 06 fe 34\ +72 bc 25 1f 81 5f 59 db 2e 43 78 a3 ad dc 18 1e\ +cf +Test: Verify +Comment: RSASSA-PSS Signature Example 2.6 +Message: \ +04 9f 91 54 d8 71 ac 4a 7c 7a b4 53 25 ba 75 45\ +a1 ed 08 f7 05 25 b2 66 7c f1 +Salt: \ +37 81 0d ef 10 55 ed 92 2b 06 3d f7 98 de 5d 0a\ +ab f8 86 ee +Signature: \ +00 47 5b 16 48 f8 14 a8 dc 0a bd c3 7b 55 27 f5\ +43 b6 66 bb 6e 39 d3 0e 5b 49 d3 b8 76 dc cc 58\ +ea c1 4e 32 a2 d5 5c 26 16 01 44 56 ad 2f 24 6f\ +c8 e3 d5 60 da 3d df 37 9a 1c 0b d2 00 f1 02 21\ +df 07 8c 21 9a 15 1b c8 d4 ec 9d 2f c2 56 44 67\ +81 10 14 ef 15 d8 ea 01 c2 eb bf f8 c2 c8 ef ab\ +38 09 6e 55 fc be 32 85 c7 aa 55 88 51 25 4f af\ +fa 92 c1 c7 2b 78 75 86 63 ef 45 82 84 31 39 d7\ +a6 +Test: Verify +Comment: Example 3: A 1026-bit RSA Key Pair +Modulus: \ +02 f2 46 ef 45 1e d3 ee bb 9a 31 02 00 cc 25 85\ +9c 04 8e 4b e7 98 30 29 91 11 2e b6 8c e6 db 67\ +4e 28 0d a2 1f ed ed 1a e7 48 80 ca 52 2b 18 db\ +24 93 85 01 28 27 c5 15 f0 e4 66 a1 ff a6 91 d9\ +81 70 57 4e 9d 0e ad b0 87 58 6c a4 89 33 da 3c\ +c9 53 d9 5b d0 ed 50 de 10 dd cb 67 36 10 7d 6c\ +83 1c 7f 66 3e 83 3c a4 c0 97 e7 00 ce 0f b9 45\ +f8 8f b8 5f e8 e5 a7 73 17 25 65 b9 14 a4 71 a4\ +43 +PublicExponent: \ +01 00 01 +PrivateExponent: \ +65 14 51 73 3b 56 de 5a c0 a6 89 a4 ae b6 e6 89\ +4a 69 01 4e 07 6c 88 dd 7a 66 7e ab 32 32 bb cc\ +d2 fc 44 ba 2f a9 c3 1d b4 6f 21 ed d1 fd b2 3c\ +5c 12 8a 5d a5 ba b9 1e 7f 95 2b 67 75 9c 7c ff\ +70 54 15 ac 9f a0 90 7c 7c a6 17 8f 66 8f b9 48\ +d8 69 da 4c c3 b7 35 6f 40 08 df d5 44 9d 32 ee\ +02 d9 a4 77 eb 69 fc 29 26 6e 5d 90 70 51 23 75\ +a5 0f bb cc 27 e2 38 ad 98 42 5f 6e bb f8 89 91 +Prime1: \ +01 bd 36 e1 8e ce 4b 0f db 2e 9c 9d 54 8b d1 a7\ +d6 e2 c2 1c 6f dc 35 07 4a 1d 05 b1 c6 c8 b3 d5\ +58 ea 26 39 c9 a9 a4 21 68 01 69 31 72 52 55 8b\ +d1 48 ad 21 5a ac 55 0e 2d cf 12 a8 2d 0e bf e8\ +53 +Prime2: \ +01 b1 b6 56 ad 86 d8 e1 9d 5d c8 62 92 b3 a1 92\ +fd f6 e0 dd 37 87 7b ad 14 82 2f a0 01 90 ca b2\ +65 f9 0d 3f 02 05 7b 6f 54 d6 ec b1 44 91 e5 ad\ +ea ce bc 48 bf 0e bd 2a 2a d2 6d 40 2e 54 f6 16\ +51 +ModPrime1PrivateExponent: \ +1f 27 79 fd 2e 3e 5e 6b ae 05 53 95 18 fb a0 cd\ +0e ad 1a a4 51 3a 7c ba 18 f1 cf 10 e3 f6 81 95\ +69 3d 27 8a 0f 0e e7 2f 89 f9 bc 76 0d 80 e2 f9\ +d0 26 1d 51 65 01 c6 ae 39 f1 4a 47 6c e2 cc f5 +ModPrime2PrivateExponent: \ +01 1a 0d 36 79 4b 04 a8 54 aa b4 b2 46 2d 43 9a\ +50 46 c9 1d 94 0b 2b c6 f7 5b 62 95 6f ef 35 a2\ +a6 e6 3c 53 09 81 7f 30 7b bf f9 d5 9e 7e 33 1b\ +d3 63 f6 d6 68 49 b1 83 46 ad ea 16 9f 0a e9 ae\ +c1 +MultiplicativeInverseOfPrime2ModPrime1: \ +0b 30 f0 ec f5 58 75 2f b3 a6 ce 4b a2 b8 c6 75\ +f6 59 eb a6 c3 76 58 5a 1b 39 71 2d 03 8a e3 d2\ +b4 6f cb 41 8a e1 5d 09 05 da 64 40 e1 51 3a 30\ +b9 b7 d6 66 8f bc 5e 88 e5 ab 7a 17 5e 73 ba 35 +Test: KeyPairValidAndConsistent +Comment: RSASSA-PSS Signature Example 3.1 +Message: \ +59 4b 37 33 3b bb 2c 84 52 4a 87 c1 a0 1f 75 fc\ +ec 0e 32 56 f1 08 e3 8d ca 36 d7 0d 00 57 +Salt: \ +f3 1a d6 c8 cf 89 df 78 ed 77 fe ac bc c2 f8 b0\ +a8 e4 cf aa +Signature: \ +00 88 b1 35 fb 17 94 b6 b9 6c 4a 3e 67 81 97 f8\ +ca c5 2b 64 b2 fe 90 7d 6f 27 de 76 11 24 96 4a\ +99 a0 1a 88 27 40 ec fa ed 6c 01 a4 74 64 bb 05\ +18 23 13 c0 13 38 a8 cd 09 72 14 cd 68 ca 10 3b\ +d5 7d 3b c9 e8 16 21 3e 61 d7 84 f1 82 46 7a bf\ +8a 01 cf 25 3e 99 a1 56 ea a8 e3 e1 f9 0e 3c 6e\ +4e 3a a2 d8 3e d0 34 5b 89 fa fc 9c 26 07 7c 14\ +b6 ac 51 45 4f a2 6e 44 6e 3a 2f 15 3b 2b 16 79\ +7f +Test: Verify +Comment: RSASSA-PSS Signature Example 3.2 +Message: \ +8b 76 95 28 88 4a 0d 1f fd 09 0c f1 02 99 3e 79\ +6d ad cf bd dd 38 e4 4f f6 32 4c a4 51 +Salt: \ +fc f9 f0 e1 f1 99 a3 d1 d0 da 68 1c 5b 86 06 fc\ +64 29 39 f7 +Signature: \ +02 a5 f0 a8 58 a0 86 4a 4f 65 01 7a 7d 69 45 4f\ +3f 97 3a 29 99 83 9b 7b bc 48 bf 78 64 11 69 17\ +95 56 f5 95 fa 41 f6 ff 18 e2 86 c2 78 30 79 bc\ +09 10 ee 9c c3 4f 49 ba 68 11 24 f9 23 df a8 8f\ +42 61 41 a3 68 a5 f5 a9 30 c6 28 c2 c3 c2 00 e1\ +8a 76 44 72 1a 0c be c6 dd 3f 62 79 bd e3 e8 f2\ +be 5e 2d 4e e5 6f 97 e7 ce af 33 05 4b e7 04 2b\ +d9 1a 63 bb 09 f8 97 bd 41 e8 11 97 de e9 9b 11\ +af +Test: Verify +Comment: RSASSA-PSS Signature Example 3.3 +Message: \ +1a bd ba 48 9c 5a da 2f 99 5e d1 6f 19 d5 a9 4d\ +9e 6e c3 4a 8d 84 f8 45 57 d2 6e 5e f9 b0 2b 22\ +88 7e 3f 9a 4b 69 0a d1 14 92 09 c2 0c 61 43 1f\ +0c 01 7c 36 c2 65 7b 35 d7 b0 7d 3f 5a d8 70 85\ +07 a9 c1 b8 31 df 83 5a 56 f8 31 07 18 14 ea 5d\ +3d 8d 8f 6a de 40 cb a3 8b 42 db 7a 2d 3d 7a 29\ +c8 f0 a7 9a 78 38 cf 58 a9 75 7f a2 fe 4c 40 df\ +9b aa 19 3b fc 6f 92 b1 23 ad 57 b0 7a ce 3e 6a\ +c0 68 c9 f1 06 af d9 ee b0 3b 4f 37 c2 5d bf bc\ +fb 30 71 f6 f9 77 17 66 d0 72 f3 bb 07 0a f6 60\ +55 32 97 3a e2 50 51 +Salt: \ +98 6e 7c 43 db b6 71 bd 41 b9 a7 f4 b6 af c8 0e\ +80 5f 24 23 +Signature: \ +02 44 bc d1 c8 c1 69 55 73 6c 80 3b e4 01 27 2e\ +18 cb 99 08 11 b1 4f 72 db 96 41 24 d5 fa 76 06\ +49 cb b5 7a fb 87 55 db b6 2b f5 1f 46 6c f2 3a\ +0a 16 07 57 6e 98 3d 77 8f ce ff a9 2d f7 54 8a\ +ea 8e a4 ec ad 2c 29 dd 9f 95 bc 07 fe 91 ec f8\ +be e2 55 bf e8 76 2f d7 69 0a a9 bf a4 fa 08 49\ +ef 72 8c 2c 42 c4 53 23 64 52 2d f2 ab 7f 9f 8a\ +03 b6 3f 7a 49 91 75 82 86 68 f5 ef 5a 29 e3 80\ +2c +Test: Verify +Comment: RSASSA-PSS Signature Example 3.4 +Message: \ +8f b4 31 f5 ee 79 2b 6c 2a c7 db 53 cc 42 86 55\ +ae b3 2d 03 f4 e8 89 c5 c2 5d e6 83 c4 61 b5 3a\ +cf 89 f9 f8 d3 aa bd f6 b9 f0 c2 a1 de 12 e1 5b\ +49 ed b3 91 9a 65 2f e9 49 1c 25 a7 fc e1 f7 22\ +c2 54 36 08 b6 9d c3 75 ec +Salt: \ +f8 31 2d 9c 8e ea 13 ec 0a 4c 7b 98 12 0c 87 50\ +90 87 c4 78 +Signature: \ +01 96 f1 2a 00 5b 98 12 9c 8d f1 3c 4c b1 6f 8a\ +a8 87 d3 c4 0d 96 df 3a 88 e7 53 2e f3 9c d9 92\ +f2 73 ab c3 70 bc 1b e6 f0 97 cf eb bf 01 18 fd\ +9e f4 b9 27 15 5f 3d f2 2b 90 4d 90 70 2d 1f 7b\ +a7 a5 2b ed 8b 89 42 f4 12 cd 7b d6 76 c9 d1 8e\ +17 03 91 dc d3 45 c0 6a 73 09 64 b3 f3 0b cc e0\ +bb 20 ba 10 6f 9a b0 ee b3 9c f8 a6 60 7f 75 c0\ +34 7f 0a f7 9f 16 af a0 81 d2 c9 2d 1e e6 f8 36\ +b8 +Test: Verify +Comment: RSASSA-PSS Signature Example 3.5 +Message: \ +fe f4 16 1d fa af 9c 52 95 05 1d fc 1f f3 81 0c\ +8c 9e c2 e8 66 f7 07 54 22 c8 ec 42 16 a9 c4 ff\ +49 42 7d 48 3c ae 10 c8 53 4a 41 b2 fd 15 fe e0\ +69 60 ec 6f b3 f7 a7 e9 4a 2f 8a 2e 3e 43 dc 4a\ +40 57 6c 30 97 ac 95 3b 1d e8 6f 0b 4e d3 6d 64\ +4f 23 ae 14 42 55 29 62 24 64 ca 0c bf 0b 17 41\ +34 72 38 15 7f ab 59 e4 de 55 24 09 6d 62 ba ec\ +63 ac 64 +Salt: \ +50 32 7e fe c6 29 2f 98 01 9f c6 7a 2a 66 38 56\ +3e 9b 6e 2d +Signature: \ +02 1e ca 3a b4 89 22 64 ec 22 41 1a 75 2d 92 22\ +10 76 d4 e0 1c 0e 6f 0d de 9a fd 26 ba 5a cf 6d\ +73 9e f9 87 54 5d 16 68 3e 56 74 c9 e7 0f 1d e6\ +49 d7 e6 1d 48 d0 ca eb 4f b4 d8 b2 4f ba 84 a6\ +e3 10 8f ee 7d 07 05 97 32 66 ac 52 4b 4a d2 80\ +f7 ae 17 dc 59 d9 6d 33 51 58 6b 5a 3b db 89 5d\ +1e 1f 78 20 ac 61 35 d8 75 34 80 99 83 82 ba 32\ +b7 34 95 59 60 8c 38 74 52 90 a8 5e f4 e9 f9 bd\ +83 +Test: Verify +Comment: RSASSA-PSS Signature Example 3.6 +Message: \ +ef d2 37 bb 09 8a 44 3a ee b2 bf 6c 3f 8c 81 b8\ +c0 1b 7f cb 3f eb +Salt: \ +b0 de 3f c2 5b 65 f5 af 96 b1 d5 cc 3b 27 d0 c6\ +05 30 87 b3 +Signature: \ +01 2f af ec 86 2f 56 e9 e9 2f 60 ab 0c 77 82 4f\ +42 99 a0 ca 73 4e d2 6e 06 44 d5 d2 22 c7 f0 bd\ +e0 39 64 f8 e7 0a 5c b6 5e d4 4e 44 d5 6a e0 ed\ +f1 ff 86 ca 03 2c c5 dd 44 04 db b7 6a b8 54 58\ +6c 44 ee d8 33 6d 08 d4 57 ce 6c 03 69 3b 45 c0\ +f1 ef ef 93 62 4b 95 b8 ec 16 9c 61 6d 20 e5 53\ +8e bc 0b 67 37 a6 f8 2b 4b c0 57 09 24 fc 6b 35\ +75 9a 33 48 42 62 79 f8 b3 d7 74 4e 2d 22 24 26\ +ce +Test: Verify +Comment: Example 4: A 1027-bit RSA Key Pair +Modulus: \ +05 4a db 78 86 44 7e fe 6f 57 e0 36 8f 06 cf 52\ +b0 a3 37 07 60 d1 61 ce f1 26 b9 1b e7 f8 9c 42\ +1b 62 a6 ec 1d a3 c3 11 d7 5e d5 0e 0a b5 ff f3\ +fd 33 8a cc 3a a8 a4 e7 7e e2 63 69 ac b8 1b a9\ +00 fa 83 f5 30 0c f9 bb 6c 53 ad 1d c8 a1 78 b8\ +15 db 42 35 a9 a9 da 0c 06 de 4e 61 5e a1 27 7c\ +e5 59 e9 c1 08 de 58 c1 4a 81 aa 77 f5 a6 f8 d1\ +33 54 94 49 88 48 c8 b9 59 40 74 0b e7 bf 7c 37\ +05 +PublicExponent: \ +01 00 01 +PrivateExponent: \ +fa 04 1f 8c d9 69 7c ee d3 8e c8 ca a2 75 52 3b\ +4d d7 2b 09 a3 01 d3 54 1d 72 f5 d3 1c 05 cb ce\ +2d 69 83 b3 61 83 af 10 69 0b d4 6c 46 13 1e 35\ +78 94 31 a5 56 77 1d d0 04 9b 57 46 1b f0 60 c1\ +f6 84 72 e8 a6 7c 25 f3 57 e5 b6 b4 73 8f a5 41\ +a7 30 34 6b 4a 07 64 9a 2d fa 80 6a 69 c9 75 b6\ +ab a6 46 78 ac c7 f5 91 3e 89 c6 22 f2 d8 ab b1\ +e3 e3 25 54 e3 9d f9 4b a6 0c 00 2e 38 7d 90 11 +Prime1: \ +02 92 32 33 6d 28 38 94 5d ba 9d d7 72 3f 4e 62\ +4a 05 f7 37 5b 92 7a 87 ab e6 a8 93 a1 65 8f d4\ +9f 47 f6 c7 b0 fa 59 6c 65 fa 68 a2 3f 0a b4 32\ +96 2d 18 d4 34 3b d6 fd 67 1a 5e a8 d1 48 41 39\ +95 +Prime2: \ +02 0e f5 ef e7 c5 39 4a ed 22 72 f7 e8 1a 74 f4\ +c0 2d 14 58 94 cb 1b 3c ab 23 a9 a0 71 0a 2a fc\ +7e 33 29 ac bb 74 3d 01 f6 80 c4 d0 2a fb 4c 8f\ +de 7e 20 93 08 11 bb 2b 99 57 88 b5 e8 72 c2 0b\ +b1 +ModPrime1PrivateExponent: \ +02 6e 7e 28 01 0e cf 24 12 d9 52 3a d7 04 64 7f\ +b4 fe 9b 66 b1 a6 81 58 1b 0e 15 55 3a 89 b1 54\ +28 28 89 8f 27 24 3e ba b4 5f f5 e1 ac b9 d4 df\ +1b 05 1f bc 62 82 4d bc 6f 6c 93 26 1a 78 b9 a7\ +59 +ModPrime2PrivateExponent: \ +01 2d dc c8 6e f6 55 99 8c 39 dd ae 11 71 86 69\ +e5 e4 6c f1 49 5b 07 e1 3b 10 14 cd 69 b3 af 68\ +30 4a d2 a6 b6 43 21 e7 8b f3 bb ca 9b b4 94 e9\ +1d 45 17 17 e2 d9 75 64 c6 54 94 65 d0 20 5c f4\ +21 +MultiplicativeInverseOfPrime2ModPrime1: \ +01 06 00 c4 c2 18 47 45 9f e5 76 70 3e 2e be ca\ +e8 a5 09 4e e6 3f 53 6b f4 ac 68 d3 c1 3e 5e 4f\ +12 ac 5c c1 0a b6 a2 d0 5a 19 92 14 d1 82 47 47\ +d5 51 90 96 36 b7 74 c2 2c ac 0b 83 75 99 ab cc\ +75 +Test: KeyPairValidAndConsistent +Comment: RSASSA-PSS Signature Example 4.1 +Message: \ +9f b0 3b 82 7c 82 17 d9 +Salt: \ +ed 7c 98 c9 5f 30 97 4f be 4f bd dc f0 f2 8d 60\ +21 c0 e9 1d +Signature: \ +03 23 d5 b7 bf 20 ba 45 39 28 9a e4 52 ae 42 97\ +08 0f ef f4 51 84 23 ff 48 11 a8 17 83 7e 7d 82\ +f1 83 6c df ab 54 51 4f f0 88 7b dd ee bf 40 bf\ +99 b0 47 ab c3 ec fa 6a 37 a3 ef 00 f4 a0 c4 a8\ +8a ae 09 04 b7 45 c8 46 c4 10 7e 87 97 72 3e 8a\ +c8 10 d9 e3 d9 5d fa 30 ff 49 66 f4 d7 5d 13 76\ +8d 20 85 7f 2b 14 06 f2 64 cf e7 5e 27 d7 65 2f\ +4b 5e d3 57 5f 28 a7 02 f8 c4 ed 9c f9 b2 d4 49\ +48 +Test: Verify +Comment: RSASSA-PSS Signature Example 4.2 +Message: \ +0c a2 ad 77 79 7e ce 86 de 5b f7 68 75 0d db 5e\ +d6 a3 11 6a d9 9b bd 17 ed f7 f7 82 f0 db 1c d0\ +5b 0f 67 74 68 c5 ea 42 0d c1 16 b1 0e 80 d1 10\ +de 2b 04 61 ea 14 a3 8b e6 86 20 39 2e 7e 89 3c\ +b4 ea 93 93 fb 88 6c 20 ff 79 06 42 30 5b f3 02\ +00 38 92 e5 4d f9 f6 67 50 9d c5 39 20 df 58 3f\ +50 a3 dd 61 ab b6 fa b7 5d 60 03 77 e3 83 e6 ac\ +a6 71 0e ee a2 71 56 e0 67 52 c9 4c e2 5a e9 9f\ +cb f8 59 2d be 2d 7e 27 45 3c b4 4d e0 71 00 eb\ +b1 a2 a1 98 11 a4 78 ad be ab 27 0f 94 e8 fe 36\ +9d 90 b3 ca 61 2f 9f +Salt: \ +22 d7 1d 54 36 3a 42 17 aa 55 11 3f 05 9b 33 84\ +e3 e5 7e 44 +Signature: \ +04 9d 01 85 84 5a 26 4d 28 fe b1 e6 9e da ec 09\ +06 09 e8 e4 6d 93 ab b3 83 71 ce 51 f4 aa 65 a5\ +99 bd aa a8 1d 24 fb a6 6a 08 a1 16 cb 64 4f 3f\ +1e 65 3d 95 c8 9d b8 bb d5 da ac 27 09 c8 98 40\ +00 17 84 10 a7 c6 aa 86 67 dd c3 8c 74 1f 71 0e\ +c8 66 5a a9 05 2b e9 29 d4 e3 b1 67 82 c1 66 21\ +14 c5 41 4b b0 35 34 55 c3 92 fc 28 f3 db 59 05\ +4b 5f 36 5c 49 e1 d1 56 f8 76 ee 10 cb 4f d7 05\ +98 +Test: Verify +Comment: RSASSA-PSS Signature Example 4.3 +Message: \ +28 80 62 af c0 8f cd b7 c5 f8 65 0b 29 83 73 00\ +46 1d d5 67 6c 17 a2 0a 3c 8f b5 14 89 49 e3 f7\ +3d 66 b3 ae 82 c7 24 0e 27 c5 b3 ec 43 28 ee 7d\ +6d df 6a 6a 0c 9b 5b 15 bc da 19 6a 9d 0c 76 b1\ +19 d5 34 d8 5a bd 12 39 62 d5 83 b7 6c e9 d1 80\ +bc e1 ca +Salt: \ +4a f8 70 fb c6 51 60 12 ca 91 6c 70 ba 86 2a c7\ +e8 24 36 17 +Signature: \ +03 fb c4 10 a2 ce d5 95 00 fb 99 f9 e2 af 27 81\ +ad a7 4e 13 14 56 24 60 27 82 e2 99 48 13 ee fc\ +a0 51 9e cd 25 3b 85 5f b6 26 a9 0d 77 1e ae 02\ +8b 0c 47 a1 99 cb d9 f8 e3 26 97 34 af 41 63 59\ +90 90 71 3a 3f a9 10 fa 09 60 65 27 21 43 2b 97\ +10 36 a7 18 1a 2b c0 ca b4 3b 0b 59 8b c6 21 74\ +61 d7 db 30 5f f7 e9 54 c5 b5 bb 23 1c 39 e7 91\ +af 6b cf a7 6b 14 7b 08 13 21 f7 26 41 48 2a 2a\ +ad +Test: Verify +Comment: RSASSA-PSS Signature Example 4.4 +Message: \ +6f 4f 9a b9 50 11 99 ce f5 5c 6c f4 08 fe 7b 36\ +c5 57 c4 9d 42 0a 47 63 d2 46 3c 8a d4 4b 3c fc\ +5b e2 74 2c 0e 7d 9b 0f 66 08 f0 8c 7f 47 b6 93\ +ee +Salt: \ +40 d2 e1 80 fa e1 ea c4 39 c1 90 b5 6c 2c 0e 14\ +dd f9 a2 26 +Signature: \ +04 86 64 4b c6 6b f7 5d 28 33 5a 61 79 b1 08 51\ +f4 3f 09 bd ed 9f ac 1a f3 32 52 bb 99 53 ba 42\ +98 cd 64 66 b2 75 39 a7 0a da a3 f8 9b 3d b3 c7\ +4a b6 35 d1 22 f4 ee 7c e5 57 a6 1e 59 b8 2f fb\ +78 66 30 e5 f9 db 53 c7 7d 9a 0c 12 fa b5 95 8d\ +4c 2c e7 da a8 07 cd 89 ba 2c c7 fc d0 2f f4 70\ +ca 67 b2 29 fc ce 81 4c 85 2c 73 cc 93 be a3 5b\ +e6 84 59 ce 47 8e 9d 46 55 d1 21 c8 47 2f 37 1d\ +4f +Test: Verify +Comment: RSASSA-PSS Signature Example 4.5 +Message: \ +e1 7d 20 38 5d 50 19 55 82 3c 3f 66 62 54 c1 d3\ +dd 36 ad 51 68 b8 f1 8d 28 6f dc f6 7a 7d ad 94\ +09 70 85 fa b7 ed 86 fe 21 42 a2 87 71 71 79 97\ +ef 1a 7a 08 88 4e fc 39 35 6d 76 07 7a af 82 45\ +9a 7f ad 45 84 88 75 f2 81 9b 09 89 37 fe 92 3b\ +cc 9d c4 42 d7 2d 75 4d 81 20 25 09 0c 9b c0 3d\ +b3 08 0c 13 8d d6 3b 35 5d 0b 4b 85 d6 68 8a c1\ +9f 4d e1 50 84 a0 ba 4e 37 3b 93 ef 4a 55 50 96\ +69 19 15 dc 23 c0 0e 95 4c de b2 0a 47 cd 55 d1\ +6c 3d 86 81 d4 6e d7 f2 ed 5e a4 27 95 be 17 ba\ +ed 25 f0 f4 d1 13 b3 63 6a dd d5 85 f1 6a 8b 5a\ +ec 0c 8f a9 c5 f0 3c bf 3b 9b 73 +Salt: \ +24 97 dc 2b 46 15 df ae 5a 66 3d 49 ff d5 6b f7\ +ef c1 13 04 +Signature: \ +02 2a 80 04 53 53 90 4c b3 0c bb 54 2d 7d 49 90\ +42 1a 6e ec 16 a8 02 9a 84 22 ad fd 22 d6 af f8\ +c4 cc 02 94 af 11 0a 0c 06 7e c8 6a 7d 36 41 34\ +45 9b b1 ae 8f f8 36 d5 a8 a2 57 98 40 99 6b 32\ +0b 19 f1 3a 13 fa d3 78 d9 31 a6 56 25 da e2 73\ +9f 0c 53 67 0b 35 d9 d3 cb ac 08 e7 33 e4 ec 2b\ +83 af 4b 91 96 d6 3e 7c 4f f1 dd ea e2 a1 22 79\ +1a 12 5b fe a8 de b0 de 8c cf 1f 4f fa f6 e6 fb\ +0a +Test: Verify +Comment: RSASSA-PSS Signature Example 4.6 +Message: \ +af bc 19 d4 79 24 90 18 fd f4 e0 9f 61 87 26 44\ +04 95 de 11 dd ee e3 88 72 d7 75 fc ea 74 a2 38\ +96 b5 34 3c 9c 38 d4 6a f0 db a2 24 d0 47 58 0c\ +c6 0a 65 e9 39 1c f9 b5 9b 36 a8 60 59 8d 4e 82\ +16 72 2f 99 3b 91 cf ae 87 bc 25 5a f8 9a 6a 19\ +9b ca 4a 39 1e ad bc 3a 24 90 3c 0b d6 67 36 8f\ +6b e7 8e 3f ea bf b4 ff d4 63 12 27 63 74 0f fb\ +be fe ab 9a 25 56 4b c5 d1 c2 4c 93 e4 22 f7 50\ +73 e2 ad 72 bf 45 b1 0d f0 0b 52 a1 47 12 8e 73\ +fe e3 3f a3 f0 57 7d 77 f8 0f bc 2d f1 be d3 13\ +29 0c 12 77 7f 50 +Salt: \ +a3 34 db 6f ae bf 11 08 1a 04 f8 7c 2d 62 1c de\ +c7 93 0b 9b +Signature: \ +00 93 8d cb 6d 58 30 46 06 5f 69 c7 8d a7 a1 f1\ +75 70 66 a7 fa 75 12 5a 9d 29 29 f0 b7 9a 60 b6\ +27 b0 82 f1 1f 5b 19 6f 28 eb 9d aa 6f 21 c0 5e\ +51 40 f6 ae f1 73 7d 20 23 07 5c 05 ec f0 4a 02\ +8c 68 6a 2a b3 e7 d5 a0 66 4f 29 5c e1 29 95 e8\ +90 90 8b 6a d2 1f 08 39 eb 65 b7 03 93 a7 b5 af\ +d9 87 1d e0 ca a0 ce de c5 b8 19 62 67 56 20 9d\ +13 ab 1e 7b b9 54 6a 26 ff 37 e9 a5 1a f9 fd 56\ +2e +Test: Verify +Comment: Example 5: A 1028-bit RSA Key Pair +Modulus: \ +0d 10 f6 61 f2 99 40 f5 ed 39 aa 26 09 66 de b4\ +78 43 67 9d 2b 6f b2 5b 3d e3 70 f3 ac 7c 19 91\ +63 91 fd 25 fb 52 7e bf a6 a4 b4 df 45 a1 75 9d\ +99 6c 4b b4 eb d1 88 28 c4 4f c5 2d 01 91 87 17\ +40 52 5f 47 a4 b0 cc 8d a3 25 ed 8a a6 76 b0 d0\ +f6 26 e0 a7 7f 07 69 21 70 ac ac 80 82 f4 2f aa\ +7d c7 cd 12 3e 73 0e 31 a8 79 85 20 4c ab cb e6\ +67 0d 43 a2 dd 2b 2d de f5 e0 53 92 fc 21 3b c5\ +07 +PublicExponent: \ +01 00 01 +PrivateExponent: \ +03 ce 08 b1 04 ff f3 96 a9 79 bd 3e 4e 46 92 5b\ +63 19 dd b6 3a cb cf d8 19 f1 7d 16 b8 07 7b 3a\ +87 10 1f f3 4b 77 fe 48 b8 b2 05 a9 6e 91 51 ba\ +8e ce a6 4d 0c ce 7b 23 c3 e6 a6 b8 30 58 bc 49\ +da e8 16 ae 73 6d b5 a4 70 8e 2a d4 35 23 2b 56\ +7f 90 96 ce 59 ff 28 06 1e 79 ab 1c 02 d7 17 e6\ +b2 3c ea 6d b8 eb 51 92 fa 7c 1e ab 22 7d ba 74\ +62 1c 45 60 18 96 ee f1 37 92 c8 44 0b eb 15 aa\ +c1 +Prime1: \ +03 f2 f3 31 f4 14 2d 4f 24 b4 3a a1 02 79 a8 96\ +52 d4 e7 53 72 21 a1 a7 b2 a2 5d eb 55 1e 5d e9\ +ac 49 74 11 c2 27 a9 4e 45 f9 1c 2d 1c 13 cc 04\ +6c f4 ce 14 e3 2d 05 87 34 21 0d 44 a8 7e e1 b7\ +3f +Prime2: \ +03 4f 09 0d 73 b5 58 03 03 0c f0 36 1a 5d 80 81\ +bf b7 9f 85 15 23 fe ac 0a 21 24 d0 8d 40 13 ff\ +08 48 77 71 a8 70 d0 47 9d c0 68 6c 62 f7 71 8d\ +fe cf 02 4b 17 c9 26 76 78 05 91 71 33 9c c0 08\ +39 +ModPrime1PrivateExponent: \ +02 aa 66 3a db f5 1a b8 87 a0 18 cb 42 6e 78 bc\ +2f e1 82 dc b2 f7 bc b5 04 41 d1 7f df 0f 06 79\ +8b 50 71 c6 e2 f5 fe b4 d5 4a d8 18 23 11 c1 ef\ +62 d4 c4 9f 18 d1 f5 1f 54 b2 d2 cf fb a4 da 1b\ +e5 +ModPrime2PrivateExponent: \ +02 bb e7 06 07 8b 5c 0b 39 15 12 d4 11 db 1b 19\ +9b 5a 56 64 b8 40 42 ea d3 7f e9 94 ae 72 b9 53\ +2d fb fb 3e 9e 69 81 a0 fb b8 06 51 31 41 b7 c2\ +16 3f e5 6c 39 5e 4b fa ee 57 e3 83 3f 9b 91 8d\ +f9 +MultiplicativeInverseOfPrime2ModPrime1: \ +02 42 b6 cd 00 d3 0a 76 7a ee 9a 89 8e ad 45 3c\ +8e ae a6 3d 50 0b 7d 1e 00 71 3e da e5 1c e3 6b\ +23 b6 64 df 26 e6 3e 26 6e c8 f7 6e 6e 63 ed 1b\ +a4 1e b0 33 b1 20 f7 ea 52 12 ae 21 a9 8f bc 16 +Test: KeyPairValidAndConsistent +Comment: RSASSA-PSS Signature Example 5.1 +Message: \ +30 c7 d5 57 45 8b 43 6d ec fd c1 4d 06 cb 7b 96\ +b0 67 18 c4 8d 7d e5 74 82 a8 68 ae 7f 06 58 70\ +a6 21 65 06 d1 1b 77 93 23 df df 04 6c f5 77 51\ +29 13 4b 4d 56 89 e4 d9 c0 ce 1e 12 d7 d4 b0 6c\ +b5 fc 58 20 de cf a4 1b af 59 bf 25 7b 32 f0 25\ +b7 67 9b 44 5b 94 99 c9 25 55 14 58 85 99 2f 1b\ +76 f8 48 91 ee 4d 3b e0 f5 15 0f d5 90 1e 3a 4c\ +8e d4 3f d3 6b 61 d0 22 e6 5a d5 00 8d bf 33 29\ +3c 22 bf bf d0 73 21 f0 f1 d5 fa 9f df 00 14 c2\ +fc b0 35 8a ad 0e 35 4b 0d 29 +Salt: \ +08 1b 23 3b 43 56 77 50 bd 6e 78 f3 96 a8 8b 9f\ +6a 44 51 51 +Signature: \ +0b a3 73 f7 6e 09 21 b7 0a 8f bf e6 22 f0 bf 77\ +b2 8a 3d b9 8e 36 10 51 c3 d7 cb 92 ad 04 52 91\ +5a 4d e9 c0 17 22 f6 82 3e eb 6a df 7e 0c a8 29\ +0f 5d e3 e5 49 89 0a c2 a3 c5 95 0a b2 17 ba 58\ +59 08 94 95 2d e9 6f 8d f1 11 b2 57 52 15 da 6c\ +16 15 90 c7 45 be 61 24 76 ee 57 8e d3 84 ab 33\ +e3 ec e9 74 81 a2 52 f5 c7 9a 98 b5 53 2a e0 0c\ +dd 62 f2 ec c0 cd 1b ae fe 80 d8 0b 96 21 93 ec\ +1d +Test: Verify +Comment: RSASSA-PSS Signature Example 5.2 +Message: \ +e7 b3 2e 15 56 ea 1b 27 95 04 6a c6 97 39 d2 2a\ +c8 96 6b f1 1c 11 6f 61 4b 16 67 40 e9 6b 90 65\ +3e 57 50 94 5f cf 77 21 86 c0 37 90 a0 7f da 32\ +3e 1a 61 91 6b 06 ee 21 57 db 3d ff 80 d6 7d 5e\ +39 a5 3a e2 68 c8 f0 9e d9 9a 73 20 05 b0 bc 6a\ +04 af 4e 08 d5 7a 00 e7 20 1b 30 60 ef aa db 73\ +11 3b fc 08 7f d8 37 09 3a a2 52 35 b8 c1 49 f5\ +62 15 f0 31 c2 4a d5 bd e7 f2 99 60 df 7d 52 40\ +70 f7 44 9c 6f 78 50 84 be 1a 0f 73 30 47 f3 36\ +f9 15 47 38 67 45 47 db 02 a9 f4 4d fc 6e 60 30\ +10 81 e1 ce 99 84 7f 3b 5b 60 1f f0 6b 4d 57 76\ +a9 74 0b 9a a0 d3 40 58 fd 3b 90 6e 4f 78 59 df\ +b0 7d 71 73 e5 e6 f6 35 0a da c2 1f 27 b2 30 74\ +69 +Salt: \ +bd 0c e1 95 49 d0 70 01 20 cb e5 10 77 db bb b0\ +0a 8d 8b 09 +Signature: \ +08 18 0d e8 25 e4 b8 b0 14 a3 2d a8 ba 76 15 55\ +92 12 04 f2 f9 0d 5f 24 b7 12 90 8f f8 4f 3e 22\ +0a d1 79 97 c0 dd 6e 70 66 30 ba 3e 84 ad d4 d5\ +e7 ab 00 4e 58 07 4b 54 97 09 56 5d 43 ad 9e 97\ +b5 a7 a1 a2 9e 85 b9 f9 0f 4a af cd f5 83 21 de\ +8c 59 74 ef 9a bf 2d 52 6f 33 c0 f2 f8 2e 95 d1\ +58 ea 6b 81 f1 73 6d b8 d1 af 3d 6a c6 a8 3b 32\ +d1 8b ae 0f f1 b2 fe 27 de 4c 76 ed 8c 79 80 a3\ +4e +Test: Verify +Comment: RSASSA-PSS Signature Example 5.3 +Message: \ +8d 83 96 e3 65 07 fe 1e f6 a1 90 17 54 8e 0c 71\ +66 74 c2 fe c2 33 ad b2 f7 75 66 5e c4 1f 2b d0\ +ba 39 6b 06 1a 9d aa 7e 86 6f 7c 23 fd 35 31 95\ +43 00 a3 42 f9 24 53 5e a1 49 8c 48 f6 c8 79 93\ +28 65 fc 02 00 0c 52 87 23 b7 ad 03 35 74 5b 51\ +20 9a 0a fe d9 32 af 8f 08 87 c2 19 00 4d 2a bd\ +89 4e a9 25 59 ee 31 98 af 3a 73 4f e9 b9 63 8c\ +26 3a 72 8a d9 5a 5a e8 ce 3e b1 58 39 f3 aa 78\ +52 bb 39 07 06 e7 76 0e 43 a7 12 91 a2 e3 f8 27\ +23 7d ed a8 51 87 4c 51 76 65 f5 45 f2 72 38 df\ +86 55 7f 37 5d 09 cc d8 bd 15 d8 cc f6 1f 5d 78\ +ca 5c 7f 5c de 78 2e 6b f5 d0 05 70 56 d4 ba d9\ +8b 3d 2f 95 75 e8 24 ab 7a 33 ff 57 b0 ac 10 0a\ +b0 d6 ea d7 aa 0b 50 f6 e4 d3 e5 ec 0b 96 6b +Salt: \ +81 57 79 a9 1b 3a 8b d0 49 bf 2a eb 92 01 42 77\ +22 22 c9 ca +Signature: \ +05 e0 fd bd f6 f7 56 ef 73 31 85 cc fa 8c ed 2e\ +b6 d0 29 d9 d5 6e 35 56 1b 5d b8 e7 02 57 ee 6f\ +d0 19 d2 f0 bb f6 69 fe 9b 98 21 e7 8d f6 d4 1e\ +31 60 8d 58 28 0f 31 8e e3 4f 55 99 41 c8 df 13\ +28 75 74 ba c0 00 b7 e5 8d c4 f4 14 ba 49 fb 12\ +7f 9d 0f 89 36 63 8c 76 e8 53 56 c9 94 f7 97 50\ +f7 fa 3c f4 fd 48 2d f7 5e 3f b9 97 8c d0 61 f7\ +ab b1 75 72 e6 e6 3e 0b de 12 cb dc f1 8c 68 b9\ +79 +Test: Verify +Comment: RSASSA-PSS Signature Example 5.4 +Message: \ +32 8c 65 9e 0a 64 37 43 3c ce b7 3c 14 +Salt: \ +9a ec 4a 74 80 d5 bb c4 29 20 d7 ca 23 5d b6 74\ +98 9c 9a ac +Signature: \ +0b c9 89 85 3b c2 ea 86 87 32 71 ce 18 3a 92 3a\ +b6 5e 8a 53 10 0e 6d f5 d8 7a 24 c4 19 4e b7 97\ +81 3e e2 a1 87 c0 97 dd 87 2d 59 1d a6 0c 56 86\ +05 dd 7e 74 2d 5a f4 e3 3b 11 67 8c cb 63 90 32\ +04 a3 d0 80 b0 90 2c 89 ab a8 86 8f 00 9c 0f 1c\ +0c b8 58 10 bb dd 29 12 1a bb 84 71 ff 2d 39 e4\ +9f d9 2d 56 c6 55 c8 e0 37 ad 18 fa fb dc 92 c9\ +58 63 f7 f6 1e a9 ef a2 8f ea 40 13 69 d1 9d ae\ +a1 +Test: Verify +Comment: RSASSA-PSS Signature Example 5.5 +Message: \ +f3 7b 96 23 79 a4 7d 41 5a 37 6e ec 89 73 15 0b\ +cb 34 ed d5 ab 65 40 41 b6 14 30 56 0c 21 44 58\ +2b a1 33 c8 67 d8 52 d6 b8 e2 33 21 90 13 02 ec\ +b4 5b 09 ec 88 b1 52 71 78 fa 04 32 63 f3 06 7d\ +9f fe 97 30 32 a9 9f 4c b0 8a d2 c7 e0 a2 45 6c\ +dd 57 a7 df 56 fe 60 53 52 7a 5a eb 67 d7 e5 52\ +06 3c 1c a9 7b 1b ef fa 7b 39 e9 97 ca f2 78 78\ +ea 0f 62 cb eb c8 c2 1d f4 c8 89 a2 02 85 1e 94\ +90 88 49 0c 24 9b 6e 9a cf 1d 80 63 f5 be 23 43\ +98 9b f9 5c 4d a0 1a 2b e7 8b 4a b6 b3 78 01 5b\ +c3 79 57 f7 69 48 b5 e5 8e 44 0c 28 45 3d 40 d7\ +cf d5 7e 7d 69 06 00 47 4a b5 e7 59 73 b1 ea 0c\ +5f 1e 45 d1 41 90 af e2 f4 eb 6d 3b df 71 f1 d2\ +f8 bb 15 6a 1c 29 5d 04 aa eb 9d 68 9d ce 79 ed\ +62 bc 44 3e +Salt: \ +e2 0c 1e 98 78 51 2c 39 97 0f 58 37 5e 15 49 a6\ +8b 64 f3 1d +Signature: \ +0a ef a9 43 b6 98 b9 60 9e df 89 8a d2 27 44 ac\ +28 dc 23 94 97 ce a3 69 cb bd 84 f6 5c 95 c0 ad\ +77 6b 59 47 40 16 4b 59 a7 39 c6 ff 7c 2f 07 c7\ +c0 77 a8 6d 95 23 8f e5 1e 1f cf 33 57 4a 4a e0\ +68 4b 42 a3 f6 bf 67 7d 91 82 0c a8 98 74 46 7b\ +2c 23 ad d7 79 69 c8 07 17 43 0d 0e fc 1d 36 95\ +89 2c e8 55 cb 7f 70 11 63 0f 4d f2 6d ef 8d df\ +36 fc 23 90 5f 57 fa 62 43 a4 85 c7 70 d5 68 1f\ +cd +Test: Verify +Comment: RSASSA-PSS Signature Example 5.6 +Message: \ +c6 10 3c 33 0c 1e f7 18 c1 41 e4 7b 8f a8 59 be\ +4d 5b 96 25 9e 7d 14 20 70 ec d4 85 83 9d ba 5a\ +83 69 c1 7c 11 14 03 5e 53 2d 19 5c 74 f4 4a 04\ +76 a2 d3 e8 a4 da 21 00 16 ca ce d0 e3 67 cb 86\ +77 10 a4 b5 aa 2d f2 b8 e5 da f5 fd c6 47 80 7d\ +4d 5e bb 6c 56 b9 76 3c cd ae 4d ea 33 08 eb 0a\ +c2 a8 95 01 cb 20 9d 26 39 fa 5b f8 7c e7 90 74\ +7d 3c b2 d2 95 e8 45 64 f2 f6 37 82 4f 0c 13 02\ +81 29 b0 aa 4a 42 2d 16 22 82 +Salt: \ +23 29 1e 4a 33 07 e8 bb b7 76 62 3a b3 4e 4a 5f\ +4c c8 a8 db +Signature: \ +02 80 2d cc fa 8d fa f5 27 9b f0 b4 a2 9b a1 b1\ +57 61 1f ae aa f4 19 b8 91 9d 15 94 19 00 c1 33\ +9e 7e 92 e6 fa e5 62 c5 3e 6c c8 e8 41 04 b1 10\ +bc e0 3a d1 85 25 e3 c4 9a 0e ad ad 5d 3f 28 f2\ +44 a8 ed 89 ed ba fb b6 86 27 7c fa 8a e9 09 71\ +4d 6b 28 f4 bf 8e 29 3a a0 4c 41 ef e7 c0 a8 12\ +66 d5 c0 61 e2 57 5b e0 32 aa 46 46 74 ff 71 62\ +62 19 bd 74 cc 45 f0 e7 ed 4e 3f f9 6e ee 75 8e\ +8f +Test: Verify +Comment: Example 6: A 1029-bit RSA Key Pair +Modulus: \ +16 4c a3 1c ff 60 9f 3a 0e 71 01 b0 39 f2 e4 fe\ +6d d3 75 19 ab 98 59 8d 17 9e 17 49 96 59 80 71\ +f4 7d 3a 04 55 91 58 d7 be 37 3c f1 aa 53 f0 aa\ +6e f0 90 39 e5 67 8c 2a 4c 63 90 05 14 c8 c4 f8\ +aa ed 5d e1 2a 5f 10 b0 9c 31 1a f8 c0 ff b5 b7\ +a2 97 f2 ef c6 3b 8d 6b 05 10 93 1f 0b 98 e4 8b\ +f5 fc 6e c4 e7 b8 db 1f fa eb 08 c3 8e 02 ad b8\ +f0 3a 48 22 9c 99 e9 69 43 1f 61 cb 8c 4d c6 98\ +d1 +PublicExponent: \ +01 00 01 +PrivateExponent: \ +03 b6 64 ee 3b 75 66 72 3f c6 ea f2 8a bb 43 0a\ +39 80 f1 12 6c 81 de 8a d7 09 ea b3 9a c9 dc d0\ +b1 55 0b 37 29 d8 70 68 e9 52 00 9d f5 44 53 4c\ +1f 50 82 9a 78 f4 59 1e b8 fd 57 14 04 26 a6 bb\ +04 05 b6 a6 f5 1a 57 d9 26 7b 7b bc 65 33 91 a6\ +99 a2 a9 0d ac 8a e2 26 bc c6 0f a8 cd 93 4c 73\ +c7 b0 3b 1f 6b 81 81 58 63 18 38 a8 61 2e 6e 6e\ +a9 2b e2 4f 83 24 fa f5 b1 fd 85 87 22 52 67 ba\ +6f +Prime1: \ +04 f0 54 8c 96 26 ab 1e bf 12 44 93 47 41 d9 9a\ +06 22 0e fa 2a 58 56 aa 0e 75 73 0b 2e c9 6a dc\ +86 be 89 4f a2 80 3b 53 a5 e8 5d 27 6a cb d2 9a\ +b8 23 f8 0a 73 91 bb 54 a5 05 16 72 fb 04 ee b5\ +43 +Prime2: \ +04 83 e0 ae 47 91 55 87 74 3f f3 45 36 2b 55 5d\ +39 62 d9 8b b6 f1 5f 84 8b 4c 92 b1 77 1c a8 ed\ +10 7d 8d 3e e6 5e c4 45 17 dd 0f aa 48 1a 38 7e\ +90 2f 7a 2e 74 7c 26 9e 7e a4 44 80 bc 53 8b 8e\ +5b +ModPrime1PrivateExponent: \ +03 a8 e8 ae a9 92 0c 1a a3 b2 f0 d8 46 e4 b8 50\ +d8 1c a3 06 a5 1c 83 54 4f 94 9f 64 f9 0d cf 3f\ +8e 26 61 f0 7e 56 12 20 a1 80 38 8f be 27 3e 70\ +e2 e5 dc a8 3a 0e 13 48 dd 64 90 c7 31 d6 ec e1\ +ab +ModPrime2PrivateExponent: \ +01 35 bd cd b6 0b f2 19 7c 43 6e d3 4b 32 cd 8b\ +4f c7 77 78 83 2b a7 67 03 55 1f b2 42 b3 01 69\ +95 93 af 77 fd 8f c3 94 a8 52 6a d2 3c c4 1a 03\ +80 6b d8 97 fe 4b 0e a6 46 55 8a ad dc c9 9e 8a\ +25 +MultiplicativeInverseOfPrime2ModPrime1: \ +03 04 c0 3d 9c 73 65 03 a9 84 ab bd 9b a2 23 01\ +40 7c 4a 2a b1 dd 85 76 64 81 b6 0d 45 40 11 52\ +e6 92 be 14 f4 12 1d 9a a3 fd 6e 0b 4d 1d 3a 97\ +35 38 a3 1d 42 ee 6e 1e 5e f6 20 23 1a 2b ba f3\ +5f +Test: KeyPairValidAndConsistent +Comment: RSASSA-PSS Signature Example 6.1 +Message: \ +0a 20 b7 74 ad dc 2f a5 12 45 ed 7c b9 da 60 9e\ +50 ca c6 63 6a 52 54 3f 97 45 8e ed 73 40 f8 d5\ +3f fc 64 91 8f 94 90 78 ee 03 ef 60 d4 2b 5f ec\ +24 60 50 bd 55 05 cd 8c b5 97 ba d3 c4 e7 13 b0\ +ef 30 64 4e 76 ad ab b0 de 01 a1 56 1e fb 25 51\ +58 c7 4f c8 01 e6 e9 19 e5 81 b4 6f 0f 0d dd 08\ +e4 f3 4c 78 10 b5 ed 83 18 f9 1d 7c 8c +Salt: \ +5b 4e a2 ef 62 9c c2 2f 3b 53 8e 01 69 04 b4 7b\ +1e 40 bf d5 +Signature: \ +04 c0 cf ac ec 04 e5 ba db ec e1 59 a5 a1 10 3f\ +69 b3 f3 2b a5 93 cb 4c c4 b1 b7 ab 45 59 16 a9\ +6a 27 cd 26 78 ea 0f 46 ba 37 f7 fc 9c 86 32 5f\ +29 73 3b 38 9f 1d 97 f4 3e 72 01 c0 f3 48 fc 45\ +fe 42 89 23 35 36 2e ee 01 8b 5b 16 1f 2f 93 93\ +03 12 25 c7 13 01 2a 57 6b c8 8e 23 05 24 89 86\ +8d 90 10 cb f0 33 ec c5 68 e8 bc 15 2b dc 59 d5\ +60 e4 12 91 91 5d 28 56 52 08 e2 2a ee c9 ef 85\ +d1 +Test: Verify +Comment: RSASSA-PSS Signature Example 6.2 +Message: \ +2a af f6 63 1f 62 1c e6 15 76 0a 9e bc e9 4b b3\ +33 07 7a d8 64 88 c8 61 d4 b7 6d 29 c1 f4 87 46\ +c6 11 ae 1e 03 ce d4 44 5d 7c fa 1f e5 f6 2e 1b\ +3f 08 45 2b de 3b 6e f8 19 73 ba fb b5 7f 97 bc\ +ee f8 73 98 53 95 b8 26 05 89 aa 88 cb 7d b5 0a\ +b4 69 26 2e 55 1b dc d9 a5 6f 27 5a 0a c4 fe 48\ +47 00 c3 5f 3d bf 2b 46 9e de 86 47 41 b8 6f a5\ +91 72 a3 60 ba 95 a0 2e 13 9b e5 0d df b7 cf 0b\ +42 fa ea bb fb ba a8 6a 44 97 69 9c 4f 2d fd 5b\ +08 40 6a f7 e1 41 44 42 7c 25 3e c0 ef a2 0e af\ +9a 8b e8 cd 49 ce 1f 1b c4 e9 3e 61 9c f2 aa 8e\ +d4 fb 39 bc 85 90 d0 f7 b9 64 88 f7 31 7a c9 ab\ +f7 be e4 e3 a0 e7 15 +Salt: \ +83 14 6a 9e 78 27 22 c2 8b 01 4f 98 b4 26 7b da\ +2a c9 50 4f +Signature: \ +0a 23 14 25 0c f5 2b 6e 4e 90 8d e5 b3 56 46 bc\ +aa 24 36 1d a8 16 0f b0 f9 25 75 90 ab 3a ce 42\ +b0 dc 3e 77 ad 2d b7 c2 03 a2 0b d9 52 fb b5 6b\ +15 67 04 6e cf aa 93 3d 7b 10 00 c3 de 9f f0 5b\ +7d 98 9b a4 6f d4 3b c4 c2 d0 a3 98 6b 7f fa 13\ +47 1d 37 eb 5b 47 d6 47 07 bd 29 0c fd 6a 9f 39\ +3a d0 8e c1 e3 bd 71 bb 57 92 61 50 35 cd af 2d\ +89 29 ae d3 be 09 83 79 37 7e 77 7c e7 9a aa 47\ +73 +Test: Verify +Comment: RSASSA-PSS Signature Example 6.3 +Message: \ +0f 61 95 d0 4a 6e 6f c7 e2 c9 60 0d bf 84 0c 39\ +ea 8d 4d 62 4f d5 35 07 01 6b 0e 26 85 8a 5e 0a\ +ec d7 ad a5 43 ae 5c 0a b3 a6 25 99 cb a0 a5 4e\ +6b f4 46 e2 62 f9 89 97 8f 9d df 5e 9a 41 +Salt: \ +a8 7b 8a ed 07 d7 b8 e2 da f1 4d dc a4 ac 68 c4\ +d0 aa bf f8 +Signature: \ +08 6d f6 b5 00 09 8c 12 0f 24 ff 84 23 f7 27 d9\ +c6 1a 5c 90 07 d3 b6 a3 1c e7 cf 8f 3c be c1 a2\ +6b b2 0e 2b d4 a0 46 79 32 99 e0 3e 37 a2 1b 40\ +19 4f b0 45 f9 0b 18 bf 20 a4 79 92 cc d7 99 cf\ +9c 05 9c 29 9c 05 26 85 49 54 aa de 8a 6a d9 d9\ +7e c9 1a 11 45 38 3f 42 46 8b 23 1f 4d 72 f2 37\ +06 d9 85 3c 3f a4 3c e8 ac e8 bf e7 48 49 87 a1\ +ec 6a 16 c8 da f8 1f 7c 8b f4 27 74 70 7a 9d f4\ +56 +Test: Verify +Comment: RSASSA-PSS Signature Example 6.4 +Message: \ +33 7d 25 fe 98 10 eb ca 0d e4 d4 65 8d 3c eb 8e\ +0f e4 c0 66 ab a3 bc c4 8b 10 5d 3b f7 e0 25 7d\ +44 fe ce a6 59 6f 4d 0c 59 a0 84 02 83 36 78 f7\ +06 20 f9 13 8d fe b7 de d9 05 e4 a6 d5 f0 5c 47\ +3d 55 93 66 52 e2 a5 df 43 c0 cf da 7b ac af 30\ +87 f4 52 4b 06 cf 42 15 7d 01 53 97 39 f7 fd de\ +c9 d5 81 25 df 31 a3 2e ab 06 c1 9b 71 f1 d5 bf +Salt: \ +a3 79 32 f8 a7 49 4a 94 2d 6f 76 74 38 e7 24 d6\ +d0 c0 ef 18 +Signature: \ +0b 5b 11 ad 54 98 63 ff a9 c5 1a 14 a1 10 6c 2a\ +72 cc 8b 64 6e 5c 72 62 50 97 86 10 5a 98 47 76\ +53 4c a9 b5 4c 1c c6 4b f2 d5 a4 4f d7 e8 a6 9d\ +b6 99 d5 ea 52 08 7a 47 48 fd 2a bc 1a fe d1 e5\ +d6 f7 c8 90 25 53 0b da a2 21 3d 7e 03 0f a5 5d\ +f6 f3 4b cf 1c e4 6d 2e df 4e 3a e4 f3 b0 18 91\ +a0 68 c9 e3 a4 4b bc 43 13 3e da d6 ec b9 f3 54\ +00 c4 25 2a 57 62 d6 57 44 b9 9c b9 f4 c5 59 32\ +9f +Test: Verify +Comment: RSASSA-PSS Signature Example 6.5 +Message: \ +84 ec 50 2b 07 2e 82 87 78 9d 8f 92 35 82 9e a3\ +b1 87 af d4 d4 c7 85 61 1b da 5f 9e b3 cb 96 71\ +7e fa 70 07 22 7f 1c 08 cb cb 97 2e 66 72 35 e0\ +fb 7d 43 1a 65 70 32 6d 2e cc e3 5a db 37 3d c7\ +53 b3 be 5f 82 9b 89 17 54 93 19 3f ab 16 ba db\ +41 37 1b 3a ac 0a e6 70 07 6f 24 be f4 20 c1 35\ +ad d7 ce e8 d3 5f bc 94 4d 79 fa fb 9e 30 7a 13\ +b0 f5 56 cb 65 4a 06 f9 73 ed 22 67 23 30 19 7e\ +f5 a7 48 bf 82 6a 5d b2 38 3a 25 36 4b 68 6b 93\ +72 bb 23 39 ae b1 ac 9e 98 89 32 7d 01 6f 16 70\ +77 6d b0 62 01 ad bd ca f8 a5 e3 b7 4e 10 8b 73 +Salt: \ +7b 79 0c 1d 62 f7 b8 4e 94 df 6a f2 89 17 cf 57\ +10 18 11 0e +Signature: \ +02 d7 1f a9 b5 3e 46 54 fe fb 7f 08 38 5c f6 b0\ +ae 3a 81 79 42 eb f6 6c 35 ac 67 f0 b0 69 95 2a\ +3c e9 c7 e1 f1 b0 2e 48 0a 95 00 83 6d e5 d6 4c\ +db 7e cd e0 45 42 f7 a7 99 88 78 7e 24 c2 ba 05\ +f5 fd 48 2c 02 3e d5 c3 0e 04 83 9d c4 4b ed 2a\ +3a 3a 4f ee 01 11 3c 89 1a 47 d3 2e b8 02 5c 28\ +cb 05 0b 5c db 57 6c 70 fe 76 ef 52 34 05 c0 84\ +17 fa f3 50 b0 37 a4 3c 37 93 39 fc b1 8d 3a 35\ +6b +Test: Verify +Comment: RSASSA-PSS Signature Example 6.6 +Message: \ +99 06 d8 9f 97 a9 fd ed d3 cc d8 24 db 68 73 26\ +f3 0f 00 aa 25 a7 fc a2 af cb 3b 0f 86 cd 41 e7\ +3f 0e 8f f7 d2 d8 3f 59 e2 8e d3 1a 5a 0d 55 15\ +23 37 4d e2 2e 4c 7e 8f f5 68 b3 86 ee 3d c4 11\ +63 f1 0b f6 7b b0 06 26 1c 90 82 f9 af 90 bf 1d\ +90 49 a6 b9 fa e7 1c 7f 84 fb e6 e5 5f 02 78 9d\ +e7 74 f2 30 f1 15 02 6a 4b 4e 96 c5 5b 04 a9 5d\ +a3 aa cb b2 ce ce 8f 81 76 4a 1f 1c 99 51 54 11\ +08 7c f7 d3 4a ed ed 09 32 c1 83 +Salt: \ +fb be 05 90 25 b6 9b 89 fb 14 ae 22 89 e7 aa af\ +e6 0c 0f cd +Signature: \ +0a 40 a1 6e 2f e2 b3 8d 1d f9 05 46 16 7c f9 46\ +9c 9e 3c 36 81 a3 44 2b 4b 2c 2f 58 1d eb 38 5c\ +e9 9f c6 18 8b b0 2a 84 1d 56 e7 6d 30 18 91 e2\ +45 60 55 0f cc 2a 26 b5 5f 4c cb 26 d8 37 d3 50\ +a1 54 bc ac a8 39 2d 98 fa 67 95 9e 97 27 b7 8c\ +ad 03 26 9f 56 96 8f c5 6b 68 bd 67 99 26 d8 3c\ +c9 cb 21 55 50 64 5c cd a3 1c 76 0f f3 58 88 94\ +3d 2d 8a 1d 35 1e 81 e5 d0 7b 86 18 2e 75 10 81\ +ef +Test: Verify +Comment: Example 7: A 1030-bit RSA Key Pair +Modulus: \ +37 c9 da 4a 66 c8 c4 08 b8 da 27 d0 c9 d7 9f 8c\ +cb 1e af c1 d2 fe 48 74 6d 94 0b 7c 4e f5 de e1\ +8a d1 26 47 ce fa a0 c4 b3 18 8b 22 1c 51 53 86\ +75 9b 93 f0 20 24 b2 5a b9 24 2f 83 57 d8 f3 fd\ +49 64 0e e5 e6 43 ea f6 c6 4d ee fa 70 89 72 7c\ +8f f0 39 93 33 39 15 c6 ef 21 bf 59 75 b6 e5 0d\ +11 8b 51 00 8e c3 3e 9f 01 a0 a5 45 a1 0a 83 6a\ +43 dd bc a9 d8 b5 c5 d3 54 80 22 d7 06 4e a2 9a\ +b3 +PublicExponent: \ +01 00 01 +PrivateExponent: \ +3b ed 99 90 52 d9 57 bc 06 d6 51 ee f6 e3 a9 80\ +94 b1 62 1b d3 8b 54 49 bd 6c 4a ea 3d e7 e0 84\ +67 9a 44 84 de d2 5b e0 f0 82 6c f3 37 78 25 41\ +4b 14 d4 d6 1d b1 4d e6 26 fb b8 0e 5f 4f ae c9\ +56 f9 a0 a2 d2 4f 99 57 63 80 f0 84 eb 62 e4 6a\ +57 d5 54 27 8b 53 56 26 19 3c e0 20 60 57 5e b6\ +6c 57 98 d3 6f 6c 5d 40 fb 00 d8 09 b4 2a 73 10\ +2c 1c 74 ee 95 bd 71 42 0f ff ef 63 18 b5 2c 29 +Prime1: \ +07 ee fb 42 4b 0e 3a 40 e4 20 8e e5 af b2 80 b2\ +23 17 30 81 14 dd e0 b4 b6 4f 73 01 84 ec 68 da\ +6c e2 86 7a 9f 48 ed 77 26 d5 e2 61 4e d0 4a 54\ +10 73 6c 8c 71 4e e7 02 47 42 98 c6 29 2a f0 75\ +35 +Prime2: \ +07 08 30 db f9 47 ea c0 22 8d e2 63 14 b5 9b 66\ +99 4c c6 0e 83 60 e7 5d 38 76 29 8f 8f 8a 7d 14\ +1d a0 64 e5 ca 02 6a 97 3e 28 f2 54 73 8c ee 66\ +9c 72 1b 03 4c b5 f8 e2 44 da dd 7c d1 e1 59 d5\ +47 +ModPrime1PrivateExponent: \ +05 24 d2 0c 3d 95 cf f7 5a f2 31 34 83 22 7d 87\ +02 71 7a a5 76 de 15 5f 96 05 15 50 1a db 1d 70\ +e1 c0 4d e9 1b 75 b1 61 db f0 39 83 56 12 7e de\ +da 7b bc 19 a3 2d c1 62 1c c9 f5 3c 26 5d 0c e3\ +31 +ModPrime2PrivateExponent: \ +05 f9 84 a1 f2 3c 93 8d 6a 0e 89 72 4b cf 3d d9\ +3f 99 46 92 60 37 fe 7c 6b 13 a2 9e 52 84 85 5f\ +89 08 95 91 d4 40 97 56 27 bf 5c 9e 3a 8b 5c a7\ +9c 77 2a d2 73 e4 0d 32 1a f4 a6 c9 7d fd ed 78\ +d3 +MultiplicativeInverseOfPrime2ModPrime1: \ +dd d9 18 ad ad a2 9d ca b9 81 ff 9a cb a4 25 70\ +23 c0 9a 38 01 cc ce 09 8c e2 68 f8 55 d0 df 57\ +0c d6 e7 b9 b1 4b d9 a5 a9 25 4c bc 31 5b e6 f8\ +ba 1e 25 46 dd d5 69 c5 ea 19 ee d8 35 3b de 5e +Test: KeyPairValidAndConsistent +Comment: RSASSA-PSS Signature Example 7.1 +Message: \ +9e ad 0e 01 94 56 40 67 4e b4 1c ad 43 5e 23 74\ +ea ef a8 ad 71 97 d9 79 13 c4 49 57 d8 d8 3f 40\ +d7 6e e6 0e 39 bf 9c 0f 9e af 30 21 42 1a 07 4d\ +1a de 96 2c 6e 9d 3d c3 bb 17 4f e4 df e6 52 b0\ +91 15 49 5b 8f d2 79 41 74 02 0a 06 02 b5 ca 51\ +84 8c fc 96 ce 5e b5 7f c0 a2 ad c1 dd a3 6a 7c\ +c4 52 64 1a 14 91 1b 37 e4 5b fa 11 da a5 c7 ec\ +db 74 f6 d0 10 0d 1d 3e 39 e7 52 80 0e 20 33 97\ +de 02 33 07 7b 9a 88 85 55 37 fa e9 27 f9 24 38\ +0d 78 0f 98 e1 8d cf f3 9c 5e a7 41 b1 7d 6f dd\ +18 85 bc 9d 58 14 82 d7 71 ce b5 62 d7 8a 8b f8\ +8f 0c 75 b1 13 63 e5 e3 6c d4 79 ce b0 54 5f 9d\ +a8 42 03 e0 e6 e5 08 37 5c c9 e8 44 b8 8b 7a c7\ +a0 a2 01 ea 0f 1b ee 9a 2c 57 79 20 ca 02 c0 1b\ +9d 83 20 e9 74 a5 6f 4e fb 57 63 b9 62 55 ab bf\ +80 37 bf 18 02 cf 01 8f 56 37 94 93 e5 69 a9 +Salt: \ +b7 86 7a 59 95 8c b5 43 28 f8 77 5e 65 46 ec 06\ +d2 7e aa 50 +Signature: \ +18 7f 39 07 23 c8 90 25 91 f0 15 4b ae 6d 4e cb\ +ff e0 67 f0 e8 b7 95 47 6e a4 f4 d5 1c cc 81 05\ +20 bb 3c a9 bc a7 d0 b1 f2 ea 8a 17 d8 73 fa 27\ +57 0a cd 64 2e 38 08 56 1c b9 e9 75 cc fd 80 b2\ +3d c5 77 1c db 33 06 a5 f2 31 59 da cb d3 aa 2d\ +b9 3d 46 d7 66 e0 9e d1 5d 90 0a d8 97 a8 d2 74\ +dc 26 b4 7e 99 4a 27 e9 7e 22 68 a7 66 53 3a e4\ +b5 e4 2a 2f ca f7 55 c1 c4 79 4b 29 4c 60 55 58\ +23 +Test: Verify +Comment: RSASSA-PSS Signature Example 7.2 +Message: \ +8d 80 d2 d0 8d bd 19 c1 54 df 3f 14 67 3a 14 bd\ +03 73 52 31 f2 4e 86 bf 15 3d 0e 69 e7 4c bf f7\ +b1 83 6e 66 4d e8 3f 68 01 24 37 0f c0 f9 6c 9b\ +65 c0 7a 36 6b 64 4c 4a b3 +Salt: \ +0c 09 58 22 66 df 08 63 10 82 1b a7 e1 8d f6 4d\ +fe e6 de 09 +Signature: \ +10 fd 89 76 8a 60 a6 77 88 ab b5 85 6a 78 7c 85\ +61 f3 ed cf 9a 83 e8 98 f7 dc 87 ab 8c ce 79 42\ +9b 43 e5 69 06 94 1a 88 61 94 f1 37 e5 91 fe 7c\ +33 95 55 36 1f bb e1 f2 4f eb 2d 4b cd b8 06 01\ +f3 09 6b c9 13 2d ee a6 0a e1 30 82 f4 4f 9a d4\ +1c d6 28 93 6a 4d 51 17 6e 42 fc 59 cb 76 db 81\ +5c e5 ab 4d b9 9a 10 4a af ea 68 f5 d3 30 32 9e\ +bf 25 8d 4e de 16 06 4b d1 d0 03 93 d5 e1 57 0e\ +b8 +Test: Verify +Comment: RSASSA-PSS Signature Example 7.3 +Message: \ +80 84 05 cd fc 1a 58 b9 bb 03 97 c7 20 72 2a 81\ +ff fb 76 27 8f 33 59 17 ef 9c 47 38 14 b3 e0 16\ +ba 29 73 cd 27 65 f8 f3 f8 2d 6c c3 8a a7 f8 55\ +18 27 fe 8d 1e 38 84 b7 e6 1c 94 68 3b 8f 82 f1\ +84 3b da e2 25 7e ee c9 81 2a d4 c2 cf 28 3c 34\ +e0 b0 ae 0f e3 cb 99 0c f8 8f 2e f9 +Salt: \ +28 03 9d cf e1 06 d3 b8 29 66 11 25 8c 4a 56 65\ +1c 9e 92 dd +Signature: \ +2b 31 fd e9 98 59 b9 77 aa 09 58 6d 8e 27 46 62\ +b2 5a 2a 64 06 40 b4 57 f5 94 05 1c b1 e7 f7 a9\ +11 86 54 55 24 29 26 cf 88 fe 80 df a3 a7 5b a9\ +68 98 44 a1 1e 63 4a 82 b0 75 af bd 69 c1 2a 0d\ +f9 d2 5f 84 ad 49 45 df 3d c8 fe 90 c3 ce fd f2\ +6e 95 f0 53 43 04 b5 bd ba 20 d3 e5 64 0a 2e bf\ +b8 98 aa c3 5a e4 0f 26 fc e5 56 3c 2f 9f 24 f3\ +04 2a f7 6f 3c 70 72 d6 87 bb fb 95 9a 88 46 0a\ +f1 +Test: Verify +Comment: RSASSA-PSS Signature Example 7.4 +Message: \ +f3 37 b9 ba d9 37 de 22 a1 a0 52 df f1 11 34 a8\ +ce 26 97 62 02 98 19 39 b9 1e 07 15 ae 5e 60 96\ +49 da 1a df ce f3 f4 cc a5 9b 23 83 60 e7 d1 e4\ +96 c7 bf 4b 20 4b 5a cf f9 bb d6 16 6a 1d 87 a3\ +6e f2 24 73 73 75 10 39 f8 a8 00 b8 39 98 07 b3\ +a8 5f 44 89 34 97 c0 d0 5f b7 01 7b 82 22 81 52\ +de 6f 25 e6 11 6d cc 75 03 c7 86 c8 75 c2 8f 3a\ +a6 07 e9 4a b0 f1 98 63 ab 1b 50 73 77 0b 0c d5\ +f5 33 ac de 30 c6 fb 95 3c f3 da 68 02 64 e3 0f\ +c1 1b ff 9a 19 bf fa b4 77 9b 62 23 c3 fb 3f e0\ +f7 1a ba de 4e b7 c0 9c 41 e2 4c 22 d2 3f a1 48\ +e6 a1 73 fe b6 39 84 d1 bc 6e e3 a0 2d 91 5b 75\ +2c ea f9 2a 30 15 ec eb 38 ca 58 6c 68 01 b3 7c\ +34 ce fb 2c ff 25 ea 23 c0 86 62 dc ab 26 a7 a9\ +3a 28 5d 05 d3 04 4c +Salt: \ +a7 78 21 eb bb ef 24 62 8e 4e 12 e1 d0 ea 96 de\ +39 8f 7b 0f +Signature: \ +32 c7 ca 38 ff 26 94 9a 15 00 0c 4b a0 4b 2b 13\ +b3 5a 38 10 e5 68 18 4d 7e ca ba a1 66 b7 ff ab\ +dd f2 b6 cf 4b a0 71 24 92 37 90 f2 e5 b1 a5 be\ +04 0a ea 36 fe 13 2e c1 30 e1 f1 05 67 98 2d 17\ +ac 3e 89 b8 d2 6c 30 94 03 4e 76 2d 2e 03 12 64\ +f0 11 70 be ec b3 d1 43 9e 05 84 6f 25 45 83 67\ +a7 d9 c0 20 60 44 46 72 67 1e 64 e8 77 86 45 59\ +ca 19 b2 07 4d 58 8a 28 1b 58 04 d2 37 72 fb be\ +19 +Test: Verify +Comment: RSASSA-PSS Signature Example 7.5 +Message: \ +45 01 3c eb af d9 60 b2 55 47 6a 8e 25 98 b9 aa\ +32 ef be 6d c1 f3 4f 4a 49 8d 8c f5 a2 b4 54 8d\ +08 c5 5d 5f 95 f7 bc c9 61 91 63 05 6f 2d 58 b5\ +2f a0 32 +Salt: \ +9d 5a d8 eb 45 21 34 b6 5d c3 a9 8b 6a 73 b5 f7\ +41 60 9c d6 +Signature: \ +07 eb 65 1d 75 f1 b5 2b c2 63 b2 e1 98 33 6e 99\ +fb eb c4 f3 32 04 9a 92 2a 10 81 56 07 ee 2d 98\ +9d b3 a4 49 5b 7d cc d3 8f 58 a2 11 fb 7e 19 31\ +71 a3 d8 91 13 24 37 eb ca 44 f3 18 b2 80 50 9e\ +52 b5 fa 98 fc ce 82 05 d9 69 7c 8e e4 b7 ff 59\ +d4 c5 9c 79 03 8a 19 70 bd 2a 0d 45 1e cd c5 ef\ +11 d9 97 9c 9d 35 f8 c7 0a 61 63 71 76 07 89 0d\ +58 6a 7c 6d c0 1c 79 f8 6a 8f 28 e8 52 35 f8 c2\ +f1 +Test: Verify +Comment: RSASSA-PSS Signature Example 7.6 +Message: \ +23 58 09 70 86 c8 99 32 3e 75 d9 c9 0d 0c 09 f1\ +2d 9d 54 ed fb df 70 a9 c2 eb 5a 04 d8 f3 6b 9b\ +2b df 2a ab e0 a5 bd a1 96 89 37 f9 d6 eb d3 b6\ +b2 57 ef b3 13 6d 41 31 f9 ac b5 9b 85 e2 60 2c\ +2a 3f cd c8 35 49 4a 1f 4e 5e c1 8b 22 6c 80 23\ +2b 36 a7 5a 45 fd f0 9a 7e a9 e9 8e fb de 14 50\ +d1 19 4b f1 2e 15 a4 c5 f9 eb 5c 0b ce 52 69 e0\ +c3 b2 8c fa b6 55 d8 1a 61 a2 0b 4b e2 f5 44 59\ +bb 25 a0 db 94 c5 22 18 be 10 9a 74 26 de 83 01\ +44 24 78 9a aa 90 e5 05 6e 63 2a 69 81 15 e2 82\ +c1 a5 64 10 f2 6c 20 72 f1 93 48 1a 9d cd 88 05\ +72 00 5e 64 f4 08 2e cf +Salt: \ +3f 2e fc 59 58 80 a7 d4 7f cf 3c ba 04 98 3e a5\ +4c 4b 73 fb +Signature: \ +18 da 3c dc fe 79 bf b7 7f d9 c3 2f 37 7a d3 99\ +14 6f 0a 8e 81 06 20 23 32 71 a6 e3 ed 32 48 90\ +3f 5c dc 92 dc 79 b5 5d 3e 11 61 5a a0 56 a7 95\ +85 37 92 a3 99 8c 34 9c a5 c4 57 e8 ca 7d 29 d7\ +96 aa 24 f8 34 91 70 9b ef cf b1 51 0e a5 13 c9\ +28 29 a3 f0 0b 10 4f 65 56 34 f3 20 75 2e 13 0e\ +c0 cc f6 75 4f f8 93 db 30 29 32 bb 02 5e b6 0e\ +87 82 25 98 fc 61 9e 0e 98 17 37 a9 a4 c4 15 2d\ +33 +Test: Verify +Comment: Example 8: A 1031-bit RSA Key Pair +Modulus: \ +49 53 70 a1 fb 18 54 3c 16 d3 63 1e 31 63 25 5d\ +f6 2b e6 ee e8 90 d5 f2 55 09 e4 f7 78 a8 ea 6f\ +bb bc df 85 df f6 4e 0d 97 20 03 ab 36 81 fb ba\ +6d d4 1f d5 41 82 9b 2e 58 2d e9 f2 a4 a4 e0 a2\ +d0 90 0b ef 47 53 db 3c ee 0e e0 6c 7d fa e8 b1\ +d5 3b 59 53 21 8f 9c ce ea 69 5b 08 66 8e de aa\ +dc ed 94 63 b1 d7 90 d5 eb f2 7e 91 15 b4 6c ad\ +4d 9a 2b 8e fa b0 56 1b 08 10 34 47 39 ad a0 73\ +3f +PublicExponent: \ +01 00 01 +PrivateExponent: \ +6c 66 ff e9 89 80 c3 8f cd ea b5 15 98 98 83 61\ +65 f4 b4 b8 17 c4 f6 a8 d4 86 ee 4e a9 13 0f e9\ +b9 09 2b d1 36 d1 84 f9 5f 50 4a 60 7e ac 56 58\ +46 d2 fd d6 59 7a 89 67 c7 39 6e f9 5a 6e ee bb\ +45 78 a6 43 96 6d ca 4d 8e e3 de 84 2d e6 32 79\ +c6 18 15 9c 1a b5 4a 89 43 7b 6a 61 20 e4 93 0a\ +fb 52 a4 ba 6c ed 8a 49 47 ac 64 b3 0a 34 97 cb\ +e7 01 c2 d6 26 6d 51 72 19 ad 0e c6 d3 47 db e9 +Prime1: \ +08 da d7 f1 13 63 fa a6 23 d5 d6 d5 e8 a3 19 32\ +8d 82 19 0d 71 27 d2 84 6c 43 9b 0a b7 26 19 b0\ +a4 3a 95 32 0e 4e c3 4f c3 a9 ce a8 76 42 23 05\ +bd 76 c5 ba 7b e9 e2 f4 10 c8 06 06 45 a1 d2 9e\ +db +Prime2: \ +08 47 e7 32 37 6f c7 90 0f 89 8e a8 2e b2 b0 fc\ +41 85 65 fd ae 62 f7 d9 ec 4c e2 21 7b 97 99 0d\ +d2 72 db 15 7f 99 f6 3c 0d cb b9 fb ac db d4 c4\ +da db 6d f6 77 56 35 8c a4 17 48 25 b4 8f 49 70\ +6d +ModPrime1PrivateExponent: \ +05 c2 a8 3c 12 4b 36 21 a2 aa 57 ea 2c 3e fe 03\ +5e ff 45 60 f3 3d de bb 7a da b8 1f ce 69 a0 c8\ +c2 ed c1 65 20 dd a8 3d 59 a2 3b e8 67 96 3a c6\ +5f 2c c7 10 bb cf b9 6e e1 03 de b7 71 d1 05 fd\ +85 +ModPrime2PrivateExponent: \ +04 ca e8 aa 0d 9f aa 16 5c 87 b6 82 ec 14 0b 8e\ +d3 b5 0b 24 59 4b 7a 3b 2c 22 0b 36 69 bb 81 9f\ +98 4f 55 31 0a 1a e7 82 36 51 d4 a0 2e 99 44 79\ +72 59 51 39 36 34 34 e5 e3 0a 7e 7d 24 15 51 e1\ +b9 +MultiplicativeInverseOfPrime2ModPrime1: \ +07 d3 e4 7b f6 86 60 0b 11 ac 28 3c e8 8d bb 3f\ +60 51 e8 ef d0 46 80 e4 4c 17 1e f5 31 b8 0b 2b\ +7c 39 fc 76 63 20 e2 cf 15 d8 d9 98 20 e9 6f f3\ +0d c6 96 91 83 9c 4b 40 d7 b0 6e 45 30 7d c9 1f\ +3f +Test: KeyPairValidAndConsistent +Comment: RSASSA-PSS Signature Example 8.1 +Message: \ +81 33 2f 4b e6 29 48 41 5e a1 d8 99 79 2e ea cf\ +6c 6e 1d b1 da 8b e1 3b 5c ea 41 db 2f ed 46 70\ +92 e1 ff 39 89 14 c7 14 25 97 75 f5 95 f8 54 7f\ +73 56 92 a5 75 e6 92 3a f7 8f 22 c6 99 7d db 90\ +fb 6f 72 d7 bb 0d d5 74 4a 31 de cd 3d c3 68 58\ +49 83 6e d3 4a ec 59 63 04 ad 11 84 3c 4f 88 48\ +9f 20 97 35 f5 fb 7f da f7 ce c8 ad dc 58 18 16\ +8f 88 0a cb f4 90 d5 10 05 b7 a8 e8 4e 43 e5 42\ +87 97 75 71 dd 99 ee a4 b1 61 eb 2d f1 f5 10 8f\ +12 a4 14 2a 83 32 2e db 05 a7 54 87 a3 43 5c 9a\ +78 ce 53 ed 93 bc 55 08 57 d7 a9 fb +Salt: \ +1d 65 49 1d 79 c8 64 b3 73 00 9b e6 f6 f2 46 7b\ +ac 4c 78 fa +Signature: \ +02 62 ac 25 4b fa 77 f3 c1 ac a2 2c 51 79 f8 f0\ +40 42 2b 3c 5b af d4 0a 8f 21 cf 0f a5 a6 67 cc\ +d5 99 3d 42 db af b4 09 c5 20 e2 5f ce 2b 1e e1\ +e7 16 57 7f 1e fa 17 f3 da 28 05 2f 40 f0 41 9b\ +23 10 6d 78 45 aa f0 11 25 b6 98 e7 a4 df e9 2d\ +39 67 bb 00 c4 d0 d3 5b a3 55 2a b9 a8 b3 ee f0\ +7c 7f ec db c5 42 4a c4 db 1e 20 cb 37 d0 b2 74\ +47 69 94 0e a9 07 e1 7f bb ca 67 3b 20 52 23 80\ +c5 +Test: Verify +Comment: RSASSA-PSS Signature Example 8.2 +Message: \ +e2 f9 6e af 0e 05 e7 ba 32 6e cc a0 ba 7f d2 f7\ +c0 23 56 f3 ce de 9d 0f aa bf 4f cc 8e 60 a9 73\ +e5 59 5f d9 ea 08 +Salt: \ +43 5c 09 8a a9 90 9e b2 37 7f 12 48 b0 91 b6 89\ +87 ff 18 38 +Signature: \ +27 07 b9 ad 51 15 c5 8c 94 e9 32 e8 ec 0a 28 0f\ +56 33 9e 44 a1 b5 8d 4d dc ff 2f 31 2e 5f 34 dc\ +fe 39 e8 9c 6a 94 dc ee 86 db bd ae 5b 79 ba 4e\ +08 19 a9 e7 bf d9 d9 82 e7 ee 6c 86 ee 68 39 6e\ +8b 3a 14 c9 c8 f3 4b 17 8e b7 41 f9 d3 f1 21 10\ +9b f5 c8 17 2f ad a2 e7 68 f9 ea 14 33 03 2c 00\ +4a 8a a0 7e b9 90 00 0a 48 dc 94 c8 ba c8 aa be\ +2b 09 b1 aa 46 c0 a2 aa 0e 12 f6 3f bb a7 75 ba\ +7e +Test: Verify +Comment: RSASSA-PSS Signature Example 8.3 +Message: \ +e3 5c 6e d9 8f 64 a6 d5 a6 48 fc ab 8a db 16 33\ +1d b3 2e 5d 15 c7 4a 40 ed f9 4c 3d c4 a4 de 79\ +2d 19 08 89 f2 0f 1e 24 ed 12 05 4a 6b 28 79 8f\ +cb 42 d1 c5 48 76 9b 73 4c 96 37 31 42 09 2a ed\ +27 76 03 f4 73 8d f4 dc 14 46 58 6d 0e c6 4d a4\ +fb 60 53 6d b2 ae 17 fc 7e 3c 04 bb fb bb d9 07\ +bf 11 7c 08 63 6f a1 6f 95 f5 1a 62 16 93 4d 3e\ +34 f8 50 30 f1 7b bb c5 ba 69 14 40 58 af f0 81\ +e0 b1 9c f0 3c 17 19 5c 5e 88 8b a5 8f 6f e0 a0\ +2e 5c 3b da 97 19 a7 +Salt: \ +c6 eb be 76 df 0c 4a ea 32 c4 74 17 5b 2f 13 68\ +62 d0 45 29 +Signature: \ +2a d2 05 09 d7 8c f2 6d 1b 6c 40 61 46 08 6e 4b\ +0c 91 a9 1c 2b d1 64 c8 7b 96 6b 8f aa 42 aa 0c\ +a4 46 02 23 23 ba 4b 1a 1b 89 70 6d 7f 4c 3b e5\ +7d 7b 69 70 2d 16 8a b5 95 5e e2 90 35 6b 8c 4a\ +29 ed 46 7d 54 7e c2 3c ba df 28 6c cb 58 63 c6\ +67 9d a4 67 fc 93 24 a1 51 c7 ec 55 aa c6 db 40\ +84 f8 27 26 82 5c fe 1a a4 21 bc 64 04 9f b4 2f\ +23 14 8f 9c 25 b2 dc 30 04 37 c3 8d 42 8a a7 5f\ +96 +Test: Verify +Comment: RSASSA-PSS Signature Example 8.4 +Message: \ +db c5 f7 50 a7 a1 4b e2 b9 3e 83 8d 18 d1 4a 86\ +95 e5 2e 8a dd 9c 0a c7 33 b8 f5 6d 27 47 e5 29\ +a0 cc a5 32 dd 49 b9 02 ae fe d5 14 44 7f 9e 81\ +d1 61 95 c2 85 38 68 cb 9b 30 f7 d0 d4 95 c6 9d\ +01 b5 c5 d5 0b 27 04 5d b3 86 6c 23 24 a4 4a 11\ +0b 17 17 74 6d e4 57 d1 c8 c4 5c 3c d2 a9 29 70\ +c3 d5 96 32 05 5d 4c 98 a4 1d 6e 99 e2 a3 dd d5\ +f7 f9 97 9a b3 cd 18 f3 75 05 d2 51 41 de 2a 1b\ +ff 17 b3 a7 dc e9 41 9e cc 38 5c f1 1d 72 84 0f\ +19 95 3f d0 50 92 51 f6 ca fd e2 89 3d 0e 75 c7\ +81 ba 7a 50 12 ca 40 1a 4f a9 9e 04 b3 c3 24 9f\ +92 6d 5a fe 82 cc 87 da b2 2c 3c 1b 10 5d e4 8e\ +34 ac e9 c9 12 4e 59 59 7a c7 eb f8 +Salt: \ +02 1f dc c6 eb b5 e1 9b 1c b1 6e 9c 67 f2 76 81\ +65 7f e2 0a +Signature: \ +1e 24 e6 e5 86 28 e5 17 50 44 a9 eb 6d 83 7d 48\ +af 12 60 b0 52 0e 87 32 7d e7 89 7e e4 d5 b9 f0\ +df 0b e3 e0 9e d4 de a8 c1 45 4f f3 42 3b b0 8e\ +17 93 24 5a 9d f8 bf 6a b3 96 8c 8e dd c3 b5 32\ +85 71 c7 7f 09 1c c5 78 57 69 12 df eb d1 64 b9\ +de 54 54 fe 0b e1 c1 f6 38 5b 32 83 60 ce 67 ec\ +7a 05 f6 e3 0e b4 5c 17 c4 8a c7 00 41 d2 ca b6\ +7f 0a 2a e7 aa fd cc 8d 24 5e a3 44 2a 63 00 cc\ +c7 +Test: Verify +Comment: RSASSA-PSS Signature Example 8.5 +Message: \ +04 dc 25 1b e7 2e 88 e5 72 34 85 b6 38 3a 63 7e\ +2f ef e0 76 60 c5 19 a5 60 b8 bc 18 bd ed b8 6e\ +ae 23 64 ea 53 ba 9d ca 6e b3 d2 e7 d6 b8 06 af\ +42 b3 e8 7f 29 1b 4a 88 81 d5 bf 57 2c c9 a8 5e\ +19 c8 6a cb 28 f0 98 f9 da 03 83 c5 66 d3 c0 f5\ +8c fd 8f 39 5d cf 60 2e 5c d4 0e 8c 71 83 f7 14\ +99 6e 22 97 ef +Salt: \ +c5 58 d7 16 7c bb 45 08 ad a0 42 97 1e 71 b1 37\ +7e ea 42 69 +Signature: \ +33 34 1b a3 57 6a 13 0a 50 e2 a5 cf 86 79 22 43\ +88 d5 69 3f 5a cc c2 35 ac 95 ad d6 8e 5e b1 ee\ +c3 16 66 d0 ca 7a 1c da 6f 70 a1 aa 76 2c 05 75\ +2a 51 95 0c db 8a f3 c5 37 9f 18 cf e6 b5 bc 55\ +a4 64 82 26 a1 5e 91 2e f1 9a d7 7a de ea 91 1d\ +67 cf ef d6 9b a4 3f a4 11 91 35 ff 64 21 17 ba\ +98 5a 7e 01 00 32 5e 95 19 f1 ca 6a 92 16 bd a0\ +55 b5 78 50 15 29 11 25 e9 0d cd 07 a2 ca 96 73\ +ee +Test: Verify +Comment: RSASSA-PSS Signature Example 8.6 +Message: \ +0e a3 7d f9 a6 fe a4 a8 b6 10 37 3c 24 cf 39 0c\ +20 fa 6e 21 35 c4 00 c8 a3 4f 5c 18 3a 7e 8e a4\ +c9 ae 09 0e d3 17 59 f4 2d c7 77 19 cc a4 00 ec\ +dc c5 17 ac fc 7a c6 90 26 75 b2 ef 30 c5 09 66\ +5f 33 21 48 2f c6 9a 9f b5 70 d1 5e 01 c8 45 d0\ +d8 e5 0d 2a 24 cb f1 cf 0e 71 49 75 a5 db 7b 18\ +d9 e9 e9 cb 91 b5 cb 16 86 90 60 ed 18 b7 b5 62\ +45 50 3f 0c af 90 35 2b 8d e8 1c b5 a1 d9 c6 33\ +60 92 f0 cd +Salt: \ +76 fd 4e 64 fd c9 8e b9 27 a0 40 3e 35 a0 84 e7\ +6b a9 f9 2a +Signature: \ +1e d1 d8 48 fb 1e db 44 12 9b d9 b3 54 79 5a f9\ +7a 06 9a 7a 00 d0 15 10 48 59 3e 0c 72 c3 51 7f\ +f9 ff 2a 41 d0 cb 5a 0a c8 60 d7 36 a1 99 70 4f\ +7c b6 a5 39 86 a8 8b bd 8a bc c0 07 6a 2c e8 47\ +88 00 31 52 5d 44 9d a2 ac 78 35 63 74 c5 36 e3\ +43 fa a7 cb a4 2a 5a aa 65 06 08 77 91 c0 6a 8e\ +98 93 35 ae d1 9b fa b2 d5 e6 7e 27 fb 0c 28 75\ +af 89 6c 21 b6 e8 e7 30 9d 04 e4 f6 72 7e 69 46\ +3e +Test: Verify +Comment: Example 9: A 1536-bit RSA Key Pair +Modulus: \ +e6 bd 69 2a c9 66 45 79 04 03 fd d0 f5 be b8 b9\ +bf 92 ed 10 00 7f c3 65 04 64 19 dd 06 c0 5c 5b\ +5b 2f 48 ec f9 89 e4 ce 26 91 09 97 9c bb 40 b4\ +a0 ad 24 d2 24 83 d1 ee 31 5a d4 cc b1 53 42 68\ +35 26 91 c5 24 f6 dd 8e 6c 29 d2 24 cf 24 69 73\ +ae c8 6c 5b f6 b1 40 1a 85 0d 1b 9a d1 bb 8c bc\ +ec 47 b0 6f 0f 8c 7f 45 d3 fc 8f 31 92 99 c5 43\ +3d db c2 b3 05 3b 47 de d2 ec d4 a4 ca ef d6 14\ +83 3d c8 bb 62 2f 31 7e d0 76 b8 05 7f e8 de 3f\ +84 48 0a d5 e8 3e 4a 61 90 4a 4f 24 8f b3 97 02\ +73 57 e1 d3 0e 46 31 39 81 5c 6f d4 fd 5a c5 b8\ +17 2a 45 23 0e cb 63 18 a0 4f 14 55 d8 4e 5a 8b +PublicExponent: \ +01 00 01 +PrivateExponent: \ +6a 7f d8 4f b8 5f ad 07 3b 34 40 6d b7 4f 8d 61\ +a6 ab c1 21 96 a9 61 dd 79 56 5e 9d a6 e5 18 7b\ +ce 2d 98 02 50 f7 35 95 75 35 92 70 d9 15 90 bb\ +0e 42 7c 71 46 0b 55 d5 14 10 b1 91 bc f3 09 fe\ +a1 31 a9 2c 8e 70 27 38 fa 71 9f 1e 00 41 f5 2e\ +40 e9 1f 22 9f 4d 96 a1 e6 f1 72 e1 55 96 b4 51\ +0a 6d ae c2 61 05 f2 be bc 53 31 6b 87 bd f2 13\ +11 66 60 70 e8 df ee 69 d5 2c 71 a9 76 ca ae 79\ +c7 2b 68 d2 85 80 dc 68 6d 9f 51 29 d2 25 f8 2b\ +3d 61 55 13 a8 82 b3 db 91 41 6b 48 ce 08 88 82\ +13 e3 7e eb 9a f8 00 d8 1c ab 32 8c e4 20 68 99\ +03 c0 0c 7b 5f d3 1b 75 50 3a 6d 41 96 84 d6 29 +Prime1: \ +f8 eb 97 e9 8d f1 26 64 ee fd b7 61 59 6a 69 dd\ +cd 0e 76 da ec e6 ed 4b f5 a1 b5 0a c0 86 f7 92\ +8a 4d 2f 87 26 a7 7e 51 5b 74 da 41 98 8f 22 0b\ +1c c8 7a a1 fc 81 0c e9 9a 82 f2 d1 ce 82 1e dc\ +ed 79 4c 69 41 f4 2c 7a 1a 0b 8c 4d 28 c7 5e c6\ +0b 65 22 79 f6 15 4a 76 2a ed 16 5d 47 de e3 67 +Prime2: \ +ed 4d 71 d0 a6 e2 4b 93 c2 e5 f6 b4 bb e0 5f 5f\ +b0 af a0 42 d2 04 fe 33 78 d3 65 c2 f2 88 b6 a8\ +da d7 ef e4 5d 15 3e ef 40 ca cc 7b 81 ff 93 40\ +02 d1 08 99 4b 94 a5 e4 72 8c d9 c9 63 37 5a e4\ +99 65 bd a5 5c bf 0e fe d8 d6 55 3b 40 27 f2 d8\ +62 08 a6 e6 b4 89 c1 76 12 80 92 d6 29 e4 9d 3d +ModPrime1PrivateExponent: \ +2b b6 8b dd fb 0c 4f 56 c8 55 8b ff af 89 2d 80\ +43 03 78 41 e7 fa 81 cf a6 1a 38 c5 e3 9b 90 1c\ +8e e7 11 22 a5 da 22 27 bd 6c de eb 48 14 52 c1\ +2a d3 d6 1d 5e 4f 77 6a 0a b5 56 59 1b ef e3 e5\ +9e 5a 7f dd b8 34 5e 1f 2f 35 b9 f4 ce e5 7c 32\ +41 4c 08 6a ec 99 3e 93 53 e4 80 d9 ee c6 28 9f +ModPrime2PrivateExponent: \ +4f f8 97 70 9f ad 07 97 46 49 45 78 e7 0f d8 54\ +61 30 ee ab 56 27 c4 9b 08 0f 05 ee 4a d9 f3 e4\ +b7 cb a9 d6 a5 df f1 13 a4 1c 34 09 33 68 33 f1\ +90 81 6d 8a 6b c4 2e 9b ec 56 b7 56 7d 0f 3c 9c\ +69 6d b6 19 b2 45 d9 01 dd 85 6d b7 c8 09 2e 77\ +e9 a1 cc cd 56 ee 4d ba 42 c5 fd b6 1a ec 26 69 +MultiplicativeInverseOfPrime2ModPrime1: \ +77 b9 d1 13 7b 50 40 4a 98 27 29 31 6e fa fc 7d\ +fe 66 d3 4e 5a 18 26 00 d5 f3 0a 0a 85 12 05 1c\ +56 0d 08 1d 4d 0a 18 35 ec 3d 25 a6 0f 4e 4d 6a\ +a9 48 b2 bf 3d bb 5b 12 4c bb c3 48 92 55 a3 a9\ +48 37 2f 69 78 49 67 45 f9 43 e1 db 4f 18 38 2c\ +ea a5 05 df c6 57 57 bb 3f 85 7a 58 dc e5 21 56 +Test: KeyPairValidAndConsistent +Comment: RSASSA-PSS Signature Example 9.1 +Message: \ +a8 8e 26 58 55 e9 d7 ca 36 c6 87 95 f0 b3 1b 59\ +1c d6 58 7c 71 d0 60 a0 b3 f7 f3 ea ef 43 79 59\ +22 02 8b c2 b6 ad 46 7c fc 2d 7f 65 9c 53 85 aa\ +70 ba 36 72 cd de 4c fe 49 70 cc 79 04 60 1b 27\ +88 72 bf 51 32 1c 4a 97 2f 3c 95 57 0f 34 45 d4\ +f5 79 80 e0 f2 0d f5 48 46 e6 a5 2c 66 8f 12 88\ +c0 3f 95 00 6e a3 2f 56 2d 40 d5 2a f9 fe b3 2f\ +0f a0 6d b6 5b 58 8a 23 7b 34 e5 92 d5 5c f9 79\ +f9 03 a6 42 ef 64 d2 ed 54 2a a8 c7 7d c1 dd 76\ +2f 45 a5 93 03 ed 75 e5 41 ca 27 1e 2b 60 ca 70\ +9e 44 fa 06 61 13 1e 8d 5d 41 63 fd 8d 39 85 66\ +ce 26 de 87 30 e7 2f 9c ca 73 76 41 c2 44 15 94\ +20 63 70 28 df 0a 18 07 9d 62 08 ea 8b 47 11 a2\ +c7 50 f5 +Salt: \ +c0 a4 25 31 3d f8 d7 56 4b d2 43 4d 31 15 23 d5\ +25 7e ed 80 +Signature: \ +58 61 07 22 6c 3c e0 13 a7 c8 f0 4d 1a 6a 29 59\ +bb 4b 8e 20 5b a4 3a 27 b5 0f 12 41 11 bc 35 ef\ +58 9b 03 9f 59 32 18 7c b6 96 d7 d9 a3 2c 0c 38\ +30 0a 5c dd a4 83 4b 62 d2 eb 24 0a f3 3f 79 d1\ +3d fb f0 95 bf 59 9e 0d 96 86 94 8c 19 64 74 7b\ +67 e8 9c 9a ba 5c d8 50 16 23 6f 56 6c c5 80 2c\ +b1 3e ad 51 bc 7c a6 be f3 b9 4d cb db b1 d5 70\ +46 97 71 df 0e 00 b1 a8 a0 67 77 47 2d 23 16 27\ +9e da e8 64 74 66 8d 4e 1e ff f9 5f 1d e6 1c 60\ +20 da 32 ae 92 bb f1 65 20 fe f3 cf 4d 88 f6 11\ +21 f2 4b bd 9f e9 1b 59 ca f1 23 5b 2a 93 ff 81\ +fc 40 3a dd f4 eb de a8 49 34 a9 cd af 8e 1a 9e +Test: Verify +Comment: RSASSA-PSS Signature Example 9.2 +Message: \ +c8 c9 c6 af 04 ac da 41 4d 22 7e f2 3e 08 20 c3\ +73 2c 50 0d c8 72 75 e9 5b 0d 09 54 13 99 3c 26\ +58 bc 1d 98 85 81 ba 87 9c 2d 20 1f 14 cb 88 ce\ +d1 53 a0 19 69 a7 bf 0a 7b e7 9c 84 c1 48 6b c1\ +2b 3f a6 c5 98 71 b6 82 7c 8c e2 53 ca 5f ef a8\ +a8 c6 90 bf 32 6e 8e 37 cd b9 6d 90 a8 2e ba b6\ +9f 86 35 0e 18 22 e8 bd 53 6a 2e +Salt: \ +b3 07 c4 3b 48 50 a8 da c2 f1 5f 32 e3 78 39 ef\ +8c 5c 0e 91 +Signature: \ +80 b6 d6 43 25 52 09 f0 a4 56 76 38 97 ac 9e d2\ +59 d4 59 b4 9c 28 87 e5 88 2e cb 44 34 cf d6 6d\ +d7 e1 69 93 75 38 1e 51 cd 7f 55 4f 2c 27 17 04\ +b3 99 d4 2b 4b e2 54 0a 0e ca 61 95 1f 55 26 7f\ +7c 28 78 c1 22 84 2d ad b2 8b 01 bd 5f 8c 02 5f\ +7e 22 84 18 a6 73 c0 3d 6b c0 c7 36 d0 a2 95 46\ +bd 67 f7 86 d9 d6 92 cc ea 77 8d 71 d9 8c 20 63\ +b7 a7 10 92 18 7a 4d 35 af 10 81 11 d8 3e 83 ea\ +e4 6c 46 aa 34 27 7e 06 04 45 89 90 37 88 f1 d5\ +e7 ce e2 5f b4 85 e9 29 49 11 88 14 d6 f2 c3 ee\ +36 14 89 01 6f 32 7f b5 bc 51 7e b5 04 70 bf fa\ +1a fa 5f 4c e9 aa 0c e5 b8 ee 19 bf 55 01 b9 58 +Test: Verify +Comment: RSASSA-PSS Signature Example 9.3 +Message: \ +0a fa d4 2c cd 4f c6 06 54 a5 50 02 d2 28 f5 2a\ +4a 5f e0 3b 8b bb 08 ca 82 da ca 55 8b 44 db e1\ +26 6e 50 c0 e7 45 a3 6d 9d 29 04 e3 40 8a bc d1\ +fd 56 99 94 06 3f 4a 75 cc 72 f2 fe e2 a0 cd 89\ +3a 43 af 1c 5b 8b 48 7d f0 a7 16 10 02 4e 4f 6d\ +df 9f 28 ad 08 13 c1 aa b9 1b cb 3c 90 64 d5 ff\ +74 2d ef fe a6 57 09 41 39 36 9e 5e a6 f4 a9 63\ +19 a5 cc 82 24 14 5b 54 50 62 75 8f ef d1 fe 34\ +09 ae 16 92 59 c6 cd fd 6b 5f 29 58 e3 14 fa ec\ +be 69 d2 ca ce 58 ee 55 17 9a b9 b3 e6 d1 ec c1\ +4a 55 7c 5f eb e9 88 59 52 64 fc 5d a1 c5 71 46\ +2e ca 79 8a 18 a1 a4 94 0c da b4 a3 e9 20 09 cc\ +d4 2e 1e 94 7b 13 14 e3 22 38 a2 de ce 7d 23 a8\ +9b 5b 30 c7 51 fd 0a 4a 43 0d 2c 54 85 94 +Salt: \ +9a 2b 00 7e 80 97 8b bb 19 2c 35 4e b7 da 9a ed\ +fc 74 db f5 +Signature: \ +48 44 08 f3 89 8c d5 f5 34 83 f8 08 19 ef bf 27\ +08 c3 4d 27 a8 b2 a6 fa e8 b3 22 f9 24 02 37 f9\ +81 81 7a ca 18 46 f1 08 4d aa 6d 7c 07 95 f6 e5\ +bf 1a f5 9c 38 e1 85 84 37 ce 1f 7e c4 19 b9 8c\ +87 36 ad f6 dd 9a 00 b1 80 6d 2b d3 ad 0a 73 77\ +5e 05 f5 2d fe f3 a5 9a b4 b0 81 43 f0 df 05 cd\ +1a d9 d0 4b ec ec a6 da a4 a2 12 98 03 e2 00 cb\ +c7 77 87 ca f4 c1 d0 66 3a 6c 59 87 b6 05 95 20\ +19 78 2c af 2e c1 42 6d 68 fb 94 ed 1d 4b e8 16\ +a7 ed 08 1b 77 e6 ab 33 0b 3f fc 07 38 20 fe cd\ +e3 72 7f cb e2 95 ee 61 a0 50 a3 43 65 86 37 c3\ +fd 65 9c fb 63 73 6d e3 2d 9f 90 d3 c2 f6 3e ca +Test: Verify +Comment: RSASSA-PSS Signature Example 9.4 +Message: \ +1d fd 43 b4 6c 93 db 82 62 9b da e2 bd 0a 12 b8\ +82 ea 04 c3 b4 65 f5 cf 93 02 3f 01 05 96 26 db\ +be 99 f2 6b b1 be 94 9d dd d1 6d c7 f3 de bb 19\ +a1 94 62 7f 0b 22 44 34 df 7d 87 00 e9 e9 8b 06\ +e3 60 c1 2f db e3 d1 9f 51 c9 68 4e b9 08 9e cb\ +b0 a2 f0 45 03 99 d3 f5 9e ac 72 94 08 5d 04 4f\ +53 93 c6 ce 73 74 23 d8 b8 6c 41 53 70 d3 89 e3\ +0b 9f 0a 3c 02 d2 5d 00 82 e8 ad 6f 3f 1e f2 4a\ +45 c3 cf 82 b3 83 36 70 63 a4 d4 61 3e 42 64 f0\ +1b 2d ac 2e 5a a4 20 43 f8 fb 5f 69 fa 87 1d 14\ +fb 27 3e 76 7a 53 1c 40 f0 2f 34 3b c2 fb 45 a0\ +c7 e0 f6 be 25 61 92 3a 77 21 1d 66 a6 e2 db b4\ +3c 36 63 50 be ae 22 da 3a c2 c1 f5 07 70 96 fc\ +b5 c4 bf 25 5f 75 74 35 1a e0 b1 e1 f0 36 32 81\ +7c 08 56 d4 a8 ba 97 af bd c8 b8 58 55 40 2b c5\ +69 26 fc ec 20 9f 9e a8 +Salt: \ +70 f3 82 bd df 4d 5d 2d d8 8b 3b c7 b7 30 8b e6\ +32 b8 40 45 +Signature: \ +84 eb eb 48 1b e5 98 45 b4 64 68 ba fb 47 1c 01\ +12 e0 2b 23 5d 84 b5 d9 11 cb d1 92 6e e5 07 4a\ +e0 42 44 95 cb 20 e8 23 08 b8 eb b6 5f 41 9a 03\ +fb 40 e7 2b 78 98 1d 88 aa d1 43 05 36 85 17 2c\ +97 b2 9c 8b 7b f0 ae 73 b5 b2 26 3c 40 3d a0 ed\ +2f 80 ff 74 50 af 78 28 eb 8b 86 f0 02 8b d2 a8\ +b1 76 a4 d2 28 cc ce a1 83 94 f2 38 b0 9f f7 58\ +cc 00 bc 04 30 11 52 35 57 42 f2 82 b5 4e 66 3a\ +91 9e 70 9d 8d a2 4a de 55 00 a7 b9 aa 50 22 6e\ +0c a5 29 23 e6 c2 d8 60 ec 50 ff 48 0f a5 74 77\ +e8 2b 05 65 f4 37 9f 79 c7 72 d5 c2 da 80 af 9f\ +bf 32 5e ce 6f c2 0b 00 96 16 14 be e8 9a 18 3e +Test: Verify +Comment: RSASSA-PSS Signature Example 9.5 +Message: \ +1b dc 6e 7c 98 fb 8c f5 4e 9b 09 7b 66 a8 31 e9\ +cf e5 2d 9d 48 88 44 8e e4 b0 97 80 93 ba 1d 7d\ +73 ae 78 b3 a6 2b a4 ad 95 cd 28 9c cb 9e 00 52\ +26 bb 3d 17 8b cc aa 82 1f b0 44 a4 e2 1e e9 76\ +96 c1 4d 06 78 c9 4c 2d ae 93 b0 ad 73 92 22 18\ +55 3d aa 7e 44 eb e5 77 25 a7 a4 5c c7 2b 9b 21\ +38 a6 b1 7c 8d b4 11 ce 82 79 ee 12 41 af f0 a8\ +be c6 f7 7f 87 ed b0 c6 9c b2 72 36 e3 43 5a 80\ +0b 19 2e 4f 11 e5 19 e3 fe 30 fc 30 ea cc ca 4f\ +bb 41 76 90 29 bf 70 8e 81 7a 9e 68 38 05 be 67\ +fa 10 09 84 68 3b 74 83 8e 3b cf fa 79 36 6e ed\ +1d 48 1c 76 72 91 18 83 8f 31 ba 8a 04 8a 93 c1\ +be 44 24 59 8e 8d f6 32 8b 7a 77 88 0a 3f 9c 7e\ +2e 8d fc a8 eb 5a 26 fb 86 bd c5 56 d4 2b be 01\ +d9 fa 6e d8 06 46 49 1c 93 41 +Salt: \ +d6 89 25 7a 86 ef fa 68 21 2c 5e 0c 61 9e ca 29\ +5f b9 1b 67 +Signature: \ +82 10 2d f8 cb 91 e7 17 99 19 a0 4d 26 d3 35 d6\ +4f bc 2f 87 2c 44 83 39 43 24 1d e8 45 48 10 27\ +4c df 3d b5 f4 2d 42 3d b1 52 af 71 35 f7 01 42\ +0e 39 b4 94 a6 7c bf d1 9f 91 19 da 23 3a 23 da\ +5c 64 39 b5 ba 0d 2b c3 73 ee e3 50 70 01 37 8d\ +4a 40 73 85 6b 7f e2 ab a0 b5 ee 93 b2 7f 4a fe\ +c7 d4 d1 20 92 1c 83 f6 06 76 5b 02 c1 9e 4d 6a\ +1a 3b 95 fa 4c 42 29 51 be 4f 52 13 10 77 ef 17\ +17 97 29 cd df bd b5 69 50 db ac ee fe 78 cb 16\ +64 0a 09 9e a5 6d 24 38 9e ef 10 f8 fe cb 31 ba\ +3e a3 b2 27 c0 a8 66 98 bb 89 e3 e9 36 39 05 bf\ +22 77 7b 2a 3a a5 21 b6 5b 4c ef 76 d8 3b de 4c +Test: Verify +Comment: RSASSA-PSS Signature Example 9.6 +Message: \ +88 c7 a9 f1 36 04 01 d9 0e 53 b1 01 b6 1c 53 25\ +c3 c7 5d b1 b4 11 fb eb 8e 83 0b 75 e9 6b 56 67\ +0a d2 45 40 4e 16 79 35 44 ee 35 4b c6 13 a9 0c\ +c9 84 87 15 a7 3d b5 89 3e 7f 6d 27 98 15 c0 c1\ +de 83 ef 8e 29 56 e3 a5 6e d2 6a 88 8d 7a 9c dc\ +d0 42 f4 b1 6b 7f a5 1e f1 a0 57 36 62 d1 6a 30\ +2d 0e c5 b2 85 d2 e0 3a d9 65 29 c8 7b 3d 37 4d\ +b3 72 d9 5b 24 43 d0 61 b6 b1 a3 50 ba 87 80 7e\ +d0 83 af d1 eb 05 c3 f5 2f 4e ba 5e d2 22 77 14\ +fd b5 0b 9d 9d 9d d6 81 4f 62 f6 27 2f cd 5c db\ +ce 7a 9e f7 97 +Salt: \ +c2 5f 13 bf 67 d0 81 67 1a 04 81 a1 f1 82 0d 61\ +3b ba 22 76 +Signature: \ +a7 fd b0 d2 59 16 5c a2 c8 8d 00 bb f1 02 8a 86\ +7d 33 76 99 d0 61 19 3b 17 a9 64 8e 14 cc bb aa\ +de ac aa cd ec 81 5e 75 71 29 4e bb 8a 11 7a f2\ +05 fa 07 8b 47 b0 71 2c 19 9e 3a d0 51 35 c5 04\ +c2 4b 81 70 51 15 74 08 02 48 79 92 ff d5 11 d4\ +af c6 b8 54 49 1e b3 f0 dd 52 31 39 54 2f f1 5c\ +31 01 ee 85 54 35 17 c6 a3 c7 94 17 c6 7e 2d d9\ +aa 74 1e 9a 29 b0 6d cb 59 3c 23 36 b3 67 0a e3\ +af ba c7 c3 e7 6e 21 54 73 e8 66 e3 38 ca 24 4d\ +e0 0b 62 62 4d 6b 94 26 82 2c ea e9 f8 cc 46 08\ +95 f4 12 50 07 3f d4 5c 5a 1e 7b 42 5c 20 4a 42\ +3a 69 91 59 f6 90 3e 71 0b 37 a7 bb 2b c8 04 9f +Test: Verify +Comment: Example 10: A 2048-bit RSA Key Pair +Modulus: \ +a5 dd 86 7a c4 cb 02 f9 0b 94 57 d4 8c 14 a7 70\ +ef 99 1c 56 c3 9c 0e c6 5f d1 1a fa 89 37 ce a5\ +7b 9b e7 ac 73 b4 5c 00 17 61 5b 82 d6 22 e3 18\ +75 3b 60 27 c0 fd 15 7b e1 2f 80 90 fe e2 a7 ad\ +cd 0e ef 75 9f 88 ba 49 97 c7 a4 2d 58 c9 aa 12\ +cb 99 ae 00 1f e5 21 c1 3b b5 43 14 45 a8 d5 ae\ +4f 5e 4c 7e 94 8a c2 27 d3 60 40 71 f2 0e 57 7e\ +90 5f be b1 5d fa f0 6d 1d e5 ae 62 53 d6 3a 6a\ +21 20 b3 1a 5d a5 da bc 95 50 60 0e 20 f2 7d 37\ +39 e2 62 79 25 fe a3 cc 50 9f 21 df f0 4e 6e ea\ +45 49 c5 40 d6 80 9f f9 30 7e ed e9 1f ff 58 73\ +3d 83 85 a2 37 d6 d3 70 5a 33 e3 91 90 09 92 07\ +0d f7 ad f1 35 7c f7 e3 70 0c e3 66 7d e8 3f 17\ +b8 df 17 78 db 38 1d ce 09 cb 4a d0 58 a5 11 00\ +1a 73 81 98 ee 27 cf 55 a1 3b 75 45 39 90 65 82\ +ec 8b 17 4b d5 8d 5d 1f 3d 76 7c 61 37 21 ae 05 +PublicExponent: \ +01 00 01 +PrivateExponent: \ +2d 2f f5 67 b3 fe 74 e0 61 91 b7 fd ed 6d e1 12\ +29 0c 67 06 92 43 0d 59 69 18 40 47 da 23 4c 96\ +93 de ed 16 73 ed 42 95 39 c9 69 d3 72 c0 4d 6b\ +47 e0 f5 b8 ce e0 84 3e 5c 22 83 5d bd 3b 05 a0\ +99 79 84 ae 60 58 b1 1b c4 90 7c bf 67 ed 84 fa\ +9a e2 52 df b0 d0 cd 49 e6 18 e3 5d fd fe 59 bc\ +a3 dd d6 6c 33 ce bb c7 7a d4 41 aa 69 5e 13 e3\ +24 b5 18 f0 1c 60 f5 a8 5c 99 4a d1 79 f2 a6 b5\ +fb e9 34 02 b1 17 67 be 01 bf 07 34 44 d6 ba 1d\ +d2 bc a5 bd 07 4d 4a 5f ae 35 31 ad 13 03 d8 4b\ +30 d8 97 31 8c bb ba 04 e0 3c 2e 66 de 6d 91 f8\ +2f 96 ea 1d 4b b5 4a 5a ae 10 2d 59 46 57 f5 c9\ +78 95 53 51 2b 29 6d ea 29 d8 02 31 96 35 7e 3e\ +3a 6e 95 8f 39 e3 c2 34 40 38 ea 60 4b 31 ed c6\ +f0 f7 ff 6e 71 81 a5 7c 92 82 6a 26 8f 86 76 8e\ +96 f8 78 56 2f c7 1d 85 d6 9e 44 86 12 f7 04 8f +Prime1: \ +cf d5 02 83 fe ee b9 7f 6f 08 d7 3c bc 7b 38 36\ +f8 2b bc d4 99 47 9f 5e 6f 76 fd fc b8 b3 8c 4f\ +71 dc 9e 88 bd 6a 6f 76 37 1a fd 65 d2 af 18 62\ +b3 2a fb 34 a9 5f 71 b8 b1 32 04 3f fe be 3a 95\ +2b af 75 92 44 81 48 c0 3f 9c 69 b1 d6 8e 4c e5\ +cf 32 c8 6b af 46 fe d3 01 ca 1a b4 03 06 9b 32\ +f4 56 b9 1f 71 89 8a b0 81 cd 8c 42 52 ef 52 71\ +91 5c 97 94 b8 f2 95 85 1d a7 51 0f 99 cb 73 eb +Prime2: \ +cc 4e 90 d2 a1 b3 a0 65 d3 b2 d1 f5 a8 fc e3 1b\ +54 44 75 66 4e ab 56 1d 29 71 b9 9f b7 be f8 44\ +e8 ec 1f 36 0b 8c 2a c8 35 96 92 97 1e a6 a3 8f\ +72 3f cc 21 1f 5d bc b1 77 a0 fd ac 51 64 a1 d4\ +ff 7f bb 4e 82 99 86 35 3c b9 83 65 9a 14 8c dd\ +42 0c 7d 31 ba 38 22 ea 90 a3 2b e4 6c 03 0e 8c\ +17 e1 fa 0a d3 78 59 e0 6b 0a a6 fa 3b 21 6d 9c\ +be 6c 0e 22 33 97 69 c0 a6 15 91 3e 5d a7 19 cf +ModPrime1PrivateExponent: \ +1c 2d 1f c3 2f 6b c4 00 4f d8 5d fd e0 fb bf 9a\ +4c 38 f9 c7 c4 e4 1d ea 1a a8 82 34 a2 01 cd 92\ +f3 b7 da 52 65 83 a9 8a d8 5b b3 60 fb 98 3b 71\ +1e 23 44 9d 56 1d 17 78 d7 a5 15 48 6b cb f4 7b\ +46 c9 e9 e1 a3 a1 f7 70 00 ef be b0 9a 8a fe 47\ +e5 b8 57 cd a9 9c b1 6d 7f ff 9b 71 2e 3b d6 0c\ +a9 6d 9c 79 73 d6 16 d4 69 34 a9 c0 50 28 1c 00\ +43 99 ce ff 1d b7 dd a7 87 66 a8 a9 b9 cb 08 73 +ModPrime2PrivateExponent: \ +cb 3b 3c 04 ca a5 8c 60 be 7d 9b 2d eb b3 e3 96\ +43 f4 f5 73 97 be 08 23 6a 1e 9e af aa 70 65 36\ +e7 1c 3a cf e0 1c c6 51 f2 3c 9e 05 85 8f ee 13\ +bb 6a 8a fc 47 df 4e dc 9a 4b a3 0b ce cb 73 d0\ +15 78 52 32 7e e7 89 01 5c 2e 8d ee 7b 9f 05 a0\ +f3 1a c9 4e b6 17 31 64 74 0c 5c 95 14 7c d5 f3\ +b5 ae 2c b4 a8 37 87 f0 1d 8a b3 1f 27 c2 d0 ee\ +a2 dd 8a 11 ab 90 6a ba 20 7c 43 c6 ee 12 53 31 +MultiplicativeInverseOfPrime2ModPrime1: \ +12 f6 b2 cf 13 74 a7 36 fa d0 56 16 05 0f 96 ab\ +4b 61 d1 17 7c 7f 9d 52 5a 29 f3 d1 80 e7 76 67\ +e9 9d 99 ab f0 52 5d 07 58 66 0f 37 52 65 5b 0f\ +25 b8 df 84 31 d9 a8 ff 77 c1 6c 12 a0 a5 12 2a\ +9f 0b f7 cf d5 a2 66 a3 5c 15 9f 99 12 08 b9 03\ +16 ff 44 4f 3e 0b 6b d0 e9 3b 8a 7a 24 48 e9 57\ +e3 dd a6 cf cf 22 66 b1 06 01 3a c4 68 08 d3 b3\ +88 7b 3b 00 34 4b aa c9 53 0b 4c e7 08 fc 32 b6 +Test: KeyPairValidAndConsistent +Comment: RSASSA-PSS Signature Example 10.1 +Message: \ +88 31 77 e5 12 6b 9b e2 d9 a9 68 03 27 d5 37 0c\ +6f 26 86 1f 58 20 c4 3d a6 7a 3a d6 09 +Salt: \ +04 e2 15 ee 6f f9 34 b9 da 70 d7 73 0c 87 34 ab\ +fc ec de 89 +Signature: \ +82 c2 b1 60 09 3b 8a a3 c0 f7 52 2b 19 f8 73 54\ +06 6c 77 84 7a bf 2a 9f ce 54 2d 0e 84 e9 20 c5\ +af b4 9f fd fd ac e1 65 60 ee 94 a1 36 96 01 14\ +8e ba d7 a0 e1 51 cf 16 33 17 91 a5 72 7d 05 f2\ +1e 74 e7 eb 81 14 40 20 69 35 d7 44 76 5a 15 e7\ +9f 01 5c b6 6c 53 2c 87 a6 a0 59 61 c8 bf ad 74\ +1a 9a 66 57 02 28 94 39 3e 72 23 73 97 96 c0 2a\ +77 45 5d 0f 55 5b 0e c0 1d df 25 9b 62 07 fd 0f\ +d5 76 14 ce f1 a5 57 3b aa ff 4e c0 00 69 95 16\ +59 b8 5f 24 30 0a 25 16 0c a8 52 2d c6 e6 72 7e\ +57 d0 19 d7 e6 36 29 b8 fe 5e 89 e2 5c c1 5b eb\ +3a 64 75 77 55 92 99 28 0b 9b 28 f7 9b 04 09 00\ +0b e2 5b bd 96 40 8b a3 b4 3c c4 86 18 4d d1 c8\ +e6 25 53 fa 1a f4 04 0f 60 66 3d e7 f5 e4 9c 04\ +38 8e 25 7f 1c e8 9c 95 da b4 8a 31 5d 9b 66 b1\ +b7 62 82 33 87 6f f2 38 52 30 d0 70 d0 7e 16 66 +Comment: RSASSA-PSS Signature Example 10.2 +Message: \ +dd 67 0a 01 46 58 68 ad c9 3f 26 13 19 57 a5 0c\ +52 fb 77 7c db aa 30 89 2c 9e 12 36 11 64 ec 13\ +97 9d 43 04 81 18 e4 44 5d b8 7b ee 58 dd 98 7b\ +34 25 d0 20 71 d8 db ae 80 70 8b 03 9d bb 64 db\ +d1 de 56 57 d9 fe d0 c1 18 a5 41 43 74 2e 0f f3\ +c8 7f 74 e4 58 57 64 7a f3 f7 9e b0 a1 4c 9d 75\ +ea 9a 1a 04 b7 cf 47 8a 89 7a 70 8f d9 88 f4 8e\ +80 1e db 0b 70 39 df 8c 23 bb 3c 56 f4 e8 21 ac +Salt: \ +8b 2b dd 4b 40 fa f5 45 c7 78 dd f9 bc 1a 49 cb\ +57 f9 b7 1b +Signature: \ +14 ae 35 d9 dd 06 ba 92 f7 f3 b8 97 97 8a ed 7c\ +d4 bf 5f f0 b5 85 a4 0b d4 6c e1 b4 2c d2 70 30\ +53 bb 90 44 d6 4e 81 3d 8f 96 db 2d d7 00 7d 10\ +11 8f 6f 8f 84 96 09 7a d7 5e 1f f6 92 34 1b 28\ +92 ad 55 a6 33 a1 c5 5e 7f 0a 0a d5 9a 0e 20 3a\ +5b 82 78 ae c5 4d d8 62 2e 28 31 d8 71 74 f8 ca\ +ff 43 ee 6c 46 44 53 45 d8 4a 59 65 9b fb 92 ec\ +d4 c8 18 66 86 95 f3 47 06 f6 68 28 a8 99 59 63\ +7f 2b f3 e3 25 1c 24 bd ba 4d 4b 76 49 da 00 22\ +21 8b 11 9c 84 e7 9a 65 27 ec 5b 8a 5f 86 1c 15\ +99 52 e2 3e c0 5e 1e 71 73 46 fa ef e8 b1 68 68\ +25 bd 2b 26 2f b2 53 10 66 c0 de 09 ac de 2e 42\ +31 69 07 28 b5 d8 5e 11 5a 2f 6b 92 b7 9c 25 ab\ +c9 bd 93 99 ff 8b cf 82 5a 52 ea 1f 56 ea 76 dd\ +26 f4 3b aa fa 18 bf a9 2a 50 4c bd 35 69 9e 26\ +d1 dc c5 a2 88 73 85 f3 c6 32 32 f0 6f 32 44 c3 +Comment: RSASSA-PSS Signature Example 10.3 +Message: \ +48 b2 b6 a5 7a 63 c8 4c ea 85 9d 65 c6 68 28 4b\ +08 d9 6b dc aa be 25 2d b0 e4 a9 6c b1 ba c6 01\ +93 41 db 6f be fb 8d 10 6b 0e 90 ed a6 bc c6 c6\ +26 2f 37 e7 ea 9c 7e 5d 22 6b d7 df 85 ec 5e 71\ +ef ff 2f 54 c5 db 57 7f f7 29 ff 91 b8 42 49 1d\ +e2 74 1d 0c 63 16 07 df 58 6b 90 5b 23 b9 1a f1\ +3d a1 23 04 bf 83 ec a8 a7 3e 87 1f f9 db +Salt: \ +4e 96 fc 1b 39 8f 92 b4 46 71 01 0c 0d c3 ef d6\ +e2 0c 2d 73 +Signature: \ +6e 3e 4d 7b 6b 15 d2 fb 46 01 3b 89 00 aa 5b bb\ +39 39 cf 2c 09 57 17 98 70 42 02 6e e6 2c 74 c5\ +4c ff d5 d7 d5 7e fb bf 95 0a 0f 5c 57 4f a0 9d\ +3f c1 c9 f5 13 b0 5b 4f f5 0d d8 df 7e df a2 01\ +02 85 4c 35 e5 92 18 01 19 a7 0c e5 b0 85 18 2a\ +a0 2d 9e a2 aa 90 d1 df 03 f2 da ae 88 5b a2 f5\ +d0 5a fd ac 97 47 6f 06 b9 3b 5b c9 4a 1a 80 aa\ +91 16 c4 d6 15 f3 33 b0 98 89 2b 25 ff ac e2 66\ +f5 db 5a 5a 3b cc 10 a8 24 ed 55 aa d3 5b 72 78\ +34 fb 8c 07 da 28 fc f4 16 a5 d9 b2 22 4f 1f 8b\ +44 2b 36 f9 1e 45 6f de a2 d7 cf e3 36 72 68 de\ +03 07 a4 c7 4e 92 41 59 ed 33 39 3d 5e 06 55 53\ +1c 77 32 7b 89 82 1b de df 88 01 61 c7 8c d4 19\ +6b 54 19 f7 ac c3 f1 3e 5e bf 16 1b 6e 7c 67 24\ +71 6c a3 3b 85 c2 e2 56 40 19 2a c2 85 96 51 d5\ +0b de 7e b9 76 e5 1c ec 82 8b 98 b6 56 3b 86 bb +Comment: RSASSA-PSS Signature Example 10.4 +Message: \ +0b 87 77 c7 f8 39 ba f0 a6 4b bb db c5 ce 79 75\ +5c 57 a2 05 b8 45 c1 74 e2 d2 e9 05 46 a0 89 c4\ +e6 ec 8a df fa 23 a7 ea 97 ba e6 b6 5d 78 2b 82\ +db 5d 2b 5a 56 d2 2a 29 a0 5e 7c 44 33 e2 b8 2a\ +62 1a bb a9 0a dd 05 ce 39 3f c4 8a 84 05 42 45\ +1a +Salt: \ +c7 cd 69 8d 84 b6 51 28 d8 83 5e 3a 8b 1e b0 e0\ +1c b5 41 ec +Signature: \ +34 04 7f f9 6c 4d c0 dc 90 b2 d4 ff 59 a1 a3 61\ +a4 75 4b 25 5d 2e e0 af 7d 8b f8 7c 9b c9 e7 dd\ +ee de 33 93 4c 63 ca 1c 0e 3d 26 2c b1 45 ef 93\ +2a 1f 2c 0a 99 7a a6 a3 4f 8e ae e7 47 7d 82 cc\ +f0 90 95 a6 b8 ac ad 38 d4 ee c9 fb 7e ab 7a d0\ +2d a1 d1 1d 8e 54 c1 82 5e 55 bf 58 c2 a2 32 34\ +b9 02 be 12 4f 9e 90 38 a8 f6 8f a4 5d ab 72 f6\ +6e 09 45 bf 1d 8b ac c9 04 4c 6f 07 09 8c 9f ce\ +c5 8a 3a ab 10 0c 80 51 78 15 5f 03 0a 12 4c 45\ +0e 5a cb da 47 d0 e4 f1 0b 80 a2 3f 80 3e 77 4d\ +02 3b 00 15 c2 0b 9f 9b be 7c 91 29 63 38 d5 ec\ +b4 71 ca fb 03 20 07 b6 7a 60 be 5f 69 50 4a 9f\ +01 ab b3 cb 46 7b 26 0e 2b ce 86 0b e8 d9 5b f9\ +2c 0c 8e 14 96 ed 1e 52 85 93 a4 ab b6 df 46 2d\ +de 8a 09 68 df fe 46 83 11 68 57 a2 32 f5 eb f6\ +c8 5b e2 38 74 5a d0 f3 8f 76 7a 5f db f4 86 fb +Comment: RSASSA-PSS Signature Example 10.5 +Message: \ +f1 03 6e 00 8e 71 e9 64 da dc 92 19 ed 30 e1 7f\ +06 b4 b6 8a 95 5c 16 b3 12 b1 ed df 02 8b 74 97\ +6b ed 6b 3f 6a 63 d4 e7 78 59 24 3c 9c cc dc 98\ +01 65 23 ab b0 24 83 b3 55 91 c3 3a ad 81 21 3b\ +b7 c7 bb 1a 47 0a ab c1 0d 44 25 6c 4d 45 59 d9\ +16 +Salt: \ +ef a8 bf f9 62 12 b2 f4 a3 f3 71 a1 0d 57 41 52\ +65 5f 5d fb +Signature: \ +7e 09 35 ea 18 f4 d6 c1 d1 7c e8 2e b2 b3 83 6c\ +55 b3 84 58 9c e1 9d fe 74 33 63 ac 99 48 d1 f3\ +46 b7 bf dd fe 92 ef d7 8a db 21 fa ef c8 9a de\ +42 b1 0f 37 40 03 fe 12 2e 67 42 9a 1c b8 cb d1\ +f8 d9 01 45 64 c4 4d 12 01 16 f4 99 0f 1a 6e 38\ +77 4c 19 4b d1 b8 21 32 86 b0 77 b0 49 9d 2e 7b\ +3f 43 4a b1 22 89 c5 56 68 4d ee d7 81 31 93 4b\ +b3 dd 65 37 23 6f 7c 6f 3d cb 09 d4 76 be 07 72\ +1e 37 e1 ce ed 9b 2f 7b 40 68 87 bd 53 15 73 05\ +e1 c8 b4 f8 4d 73 3b c1 e1 86 fe 06 cc 59 b6 ed\ +b8 f4 bd 7f fe fd f4 f7 ba 9c fb 9d 57 06 89 b5\ +a1 a4 10 9a 74 6a 69 08 93 db 37 99 25 5a 0c b9\ +21 5d 2d 1c d4 90 59 0e 95 2e 8c 87 86 aa 00 11\ +26 52 52 47 0c 04 1d fb c3 ee c7 c3 cb f7 1c 24\ +86 9d 11 5c 0c b4 a9 56 f5 6d 53 0b 80 ab 58 9a\ +cf ef c6 90 75 1d df 36 e8 d3 83 f8 3c ed d2 cc +Comment: RSASSA-PSS Signature Example 10.6 +Message: \ +25 f1 08 95 a8 77 16 c1 37 45 0b b9 51 9d fa a1\ +f2 07 fa a9 42 ea 88 ab f7 1e 9c 17 98 00 85 b5\ +55 ae ba b7 62 64 ae 2a 3a b9 3c 2d 12 98 11 91\ +dd ac 6f b5 94 9e b3 6a ee 3c 5d a9 40 f0 07 52\ +c9 16 d9 46 08 fa 7d 97 ba 6a 29 15 b6 88 f2 03\ +23 d4 e9 d9 68 01 d8 9a 72 ab 58 92 dc 21 17 c0\ +74 34 fc f9 72 e0 58 cf 8c 41 ca 4b 4f f5 54 f7\ +d5 06 8a d3 15 5f ce d0 f3 12 5b c0 4f 91 93 37\ +8a 8f 5c 4c 3b 8c b4 dd 6d 1c c6 9d 30 ec ca 6e\ +aa 51 e3 6a 05 73 0e 9e 34 2e 85 5b af 09 9d ef\ +b8 af d7 +Salt: \ +ad 8b 15 23 70 36 46 22 4b 66 0b 55 08 85 91 7c\ +a2 d1 df 28 +Signature: \ +6d 3b 5b 87 f6 7e a6 57 af 21 f7 54 41 97 7d 21\ +80 f9 1b 2c 5f 69 2d e8 29 55 69 6a 68 67 30 d9\ +b9 77 8d 97 07 58 cc b2 60 71 c2 20 9f fb d6 12\ +5b e2 e9 6e a8 1b 67 cb 9b 93 08 23 9f da 17 f7\ +b2 b6 4e cd a0 96 b6 b9 35 64 0a 5a 1c b4 2a 91\ +55 b1 c9 ef 7a 63 3a 02 c5 9f 0d 6e e5 9b 85 2c\ +43 b3 50 29 e7 3c 94 0f f0 41 0e 8f 11 4e ed 46\ +bb d0 fa e1 65 e4 2b e2 52 8a 40 1c 3b 28 fd 81\ +8e f3 23 2d ca 9f 4d 2a 0f 51 66 ec 59 c4 23 96\ +d6 c1 1d bc 12 15 a5 6f a1 71 69 db 95 75 34 3e\ +f3 4f 9d e3 2a 49 cd c3 17 49 22 f2 29 c2 3e 18\ +e4 5d f9 35 31 19 ec 43 19 ce dc e7 a1 7c 64 08\ +8c 1f 6f 52 be 29 63 41 00 b3 91 9d 38 f3 d1 ed\ +94 e6 89 1e 66 a7 3b 8f b8 49 f5 87 4d f5 94 59\ +e2 98 c7 bb ce 2e ee 78 2a 19 5a a6 6f e2 d0 73\ +2b 25 e5 95 f5 7d 3e 06 1b 1f c3 e4 06 3b f9 8f +Test: Verify diff --git a/src-cryptopp/TestVectors/rw.txt b/src-cryptopp/TestVectors/rw.txt new file mode 100644 index 0000000..2d932d0 --- /dev/null +++ b/src-cryptopp/TestVectors/rw.txt @@ -0,0 +1,166 @@ +AlgorithmType: Signature +Name: RW/EMSA2(SHA-1) +Source: generated by Wei Dai using Crypto++ 5.1 +Comment: 1024-bit RW key +KeyFormat: Component +Modulus: \ + e5eb47bc1f82db3001faaeabc5bbe71b7d307b431889ac10255262281ec5f5af\ + 8a790bd7bbec5efffa442cf2c3fd5ca4778763b9d15aeac0b9b71bdb13da8272\ + 7f4967ac685975f8ff05a763c864d100b7cc1142102aa2dd343ea1a0ab530255\ + 195c3a6400ecab7b27eff9b01ef6d37381fa6fb5401347f195354396772e8285 +Prime1: \ + ef86dd7af3f32cde8a9f6564e43a559a0c9f8bad36cc25330548b347ac158a34\ + 5631fa90f7b873c36effae2f7823227a3f580b5dd18304d5932751e743e9281b +Prime2: \ + f5bb4289c389d9019c36f96c6b81fffbf20be0620c6343e2b800aefb1b55a330\ + 8cc1402da7a2a558579a2a5146b30cb08e3f20b501081248f2f1de36cdfce9df +MultiplicativeInverseOfPrime2ModPrime1: \ + 88813a3d50b7c301948ee1985db19c9fd33a47c78c977024745e10483d9cc4f0\ + f573597ce564a91421d1d7457bc45a971f7d8b31403298da77799b57cf9a76de +PublicExponent: 02 +Test: KeyPairValidAndConsistent +Message: 2CA039854B55688740E3 +Signature: 1AF029CBEC9C692CE5096E73E4E9A52EC9A28D207A5511CCEC7681E5E3D867A4AE2E22DE4909D89196A272F1B50DE6FA3248BCA334D46E0D57171A790B6F4697E7BA7047DB79DECD47BD21995243DEBBF25915DDBC93C45875C14DE953792257C5C6825C905AFF40109C8CC7E793123D47AC1B5B6304A436CFA9BEEC8E0054E7 +Test: Verify +Message: 2A51DF4AF88613D91A37 +Signature: 6FF18F4471E1A8F850C910A181A9F28E69AACD8E8126969605E000A853197541AF9047E5D17315BF062B9CD8DF91196F0343285D9E31D5C72560C156782B6D0E5AF8F06D7DCDD8CABEC01B2438C168C40C21F6A8794648361BD2AEE13573A49ECA07A7EED97C0B9C5B1E508869E4CFD5FE1771924B1CF5A4BFF7D4379E5CD59F +Test: Verify +Message: 1CF8DDD95D780A89D7CF +Signature: 539C266B0313E0E256ED98EEF13E6AE64CED90C160A4999B3D47CBDA5285DAB0E0678C0E079CE9B8EB23E10EDFACFC19A80EEBB8F38ED5B5D6C8A988AB8CEC40A5A5BA102F75586167EAB6D5BF0CE8FF30C656895800F6F1B37D69FBBAF9055F7505DBEB537C0F986A1B5F0270DC12A640FFCB626F9763FDCFEFA1208C104003 +Test: Verify +Message: 2119A954F1AC0F3DCDB2 +Signature: 60C3CCF4F086B15B7F850B445F384333F7AE5A4B5EDE2820C7233239E1B86D6E4B4FCA4F50B087CE1DF17DA5D62672A17F2CF87A2875BBD9B138CAF6863821D6A4D553E9EB64C9254A8F9A6B960E57E39069D65E3F561AA1FA91643D42FEEFB9270D34AB0861DEA1E234EA587F580503D46A1989D413DAC2FFE0FC4CA663CE68 +Test: Verify +Message: F6959926E6D9D37D8BC0 +Signature: 249E1066542618CE0D236A7174708F801E7AB257931E9967A65C483ED66FB58598F99B6664AF0EAE221E2A6B271D7D17875ED02BF7FE35AA0786023858521CB79FEE0D134D9DDA609B0270FC9804BB6BF74AD90AE11EB339353533DC0D5A69E6B8758212B86024ED563767EA5D9B59655E0B8CC21244F720BA4ED663BF668E3A +Test: Verify +Message: 7A4C634DE6F16315BD5F +Signature: 308A5D65224201BED626CC83FB901EC84874EE03B2E7AB4E752EDBDE024C754E3CC9841CA062100A8843DE9183354B4E0596E8C68F1605828287884F0F9BA6968FC7A9F0CA09418A8485B90465E5D3F96CE4995A5FC7A6E5ABD9CC06BB8A2C3C8109F72EAE67FB4C108852C881CA645B3C5586F27F12FF3028ADE56E32AD9434 +Test: Verify +Comment: 1032-bit RW key +KeyFormat: Component +Modulus: \ + b660eb18786256c993ebc6dcb5892eac342f6d91229b73dc5d04f1afb9bb0dd4\ + eb0b48895f514b4c9afeaf86e91226f2299126d37528ce374e89cc312c06f47c\ + 81112bf5ca60ffc33b98318e04a17627269f1af461b6cb40f3be03b0113fb2d8\ + 404e154c7191306b36fd3efa73c784ad9189115d0bb1bd82b850d000e7cc8d20\ + 35 +Prime1: \ + 0bc31c063f43b3ade2cd633d554913339071d6ebed5fd665fc5dd7d47b80721a\ + 976c3b14fbd253f0f988c354725289f2897d7fb62c5c74af7d597a1e22aafba1\ + d3 +Prime2: \ + 0f816bf0add559afda38b008e4087f6a38b575c56fff453056eaaab3381c9552\ + 0969546f954d458d48e44850938b1db471cf4b40afc47e067fb5bce67ba98be8\ + d7 +MultiplicativeInverseOfPrime2ModPrime1: \ + 0b684eeec75b3e24e2d9947341b3f462258628af6f0b881396c887fe26a3408c\ + 40b13370710c82dd4a021a87bbaab5c0fc96cb1d015a783a764a8ab7b002903d\ + 21 +PublicExponent: 02 +Test: KeyPairValidAndConsistent +Message: EF0F1D56F4E5D587C212 +Signature: 3E544FEBB6623F5D392003B729FE2BFC20E2CB3ECAC22734DFCA55150254E616A41C5E54CE3B50FBC2FE2363EE9AF9B15C70615497B0A458F8AB6D850992EEEB56D65F87EA1BD6E2B4B7E40A0F5E1635C7DDB17110C61039CF712D3524C9C2C1F35D9163BE5C70276F46634514BE16EC09602782E88FE74EAEB2F50CBB0E3B5C4A +Test: Verify +Message: 2C9EA313EACF2C5DA43A +Signature: 1FEFF88814BB53E447E1E955AC8F1AF597C15C3866033E337AFBAB8627306F2EC1276621FF2176C89323CE32EA20F6AEC2CC271F1ED749408B2A3E43A23A44D6A3F38DCDDCAB696B239110AA7ECF12C6681B0E97E6FFF1B72F4F6D796BF82B9450AB8B3D28CA9D220BDF84ACCEA1DA5EDA0B470C3A82BBDD77B4C2723297608BD4 +Test: Verify +Message: EC5CC4228C3C70EE8F35 +Signature: 228BAA85062F10DCC9D99A23D340BC4B9E463D8AB86A6781A6D2143564303E2DC78772BF68449BE1E2711A68D5A15CF04A23573FB3870454308F583BBB5F2467069EF1395431E70F91BD56D846DC8DB2E88AB3D26A9770660B87A76D6C3575DE512BAFA8A0B901AD15B7D8E8BE2F176A182D16A9609F19A4298416245873175805 +Test: Verify +Message: D81F0C6F2D3D60EE19FE +Signature: 17EAA0C18178CD45A2B9100997F682E5F02BE09FBE4D8F345033951345CE98C8B3F13F2CA2A950CE7BDCBF83DBB700890E1F0B863D04C3ADB298F546A8F09F4DA4EF0DC6E7317207CB3CF691114E55D9EAA11C53BE55F7C214F62E6B0460DFA60C55B16EB55B29C9DBB908266C1BDBB03AD651EFB91905B142D852DCA0C4E3BBEE +Test: Verify +Message: FEF5EE07C74118DA30B9 +Signature: 2637E16E2599B6EC2F4728C73D3B29F483C2B881F1E1969C426027605EF080E9B17D258D5E1EBC6472A2501E04CF19C144537FCB38A1DA00D948EBD39FA11322D9230B62E2C12AEDB366BD85A2089588A8D52E941FD986D89828A342B83438A960B6FD87E9AD025AD75A692AA9DFEA873A9467B42D84879E85C5D11EFAB347FBED +Test: Verify +Message: 0B9554FFE4F6ADAB2C76 +Signature: 095952F24D9FBEF3A93A932865F4BDBB522CF24EBE153CE4BBB24CF301A1C7B51FE47B94F8F8B211CBC5A926FF6BAF9A6BBF7E15975D2DCCB95EF01AB7E641687870B0D01FC18B6B16FE17D3FC82931FBBCD4FD18C7F9588CEE8491876D72F98F2E7EEA90C12907210D6859053ADC7178B87BF8B4826954D6986FE761E71E1B7EA +Test: Verify +Comment: 1536-bit RW key +KeyFormat: Component +Modulus: \ + 9f8f8ab78ad635c71c9ef0fce9d4a958a9013ed69fcd67c385722668d4357c32\ + 3732c78179eaa17984531ba570aa0721a1e228957b1008010f1a2d6c42e09847\ + 9ffeaff9bbfeb3c8e101f968fc7ac74cfba210f76a6da160e65934d216368763\ + 8f59e414dc6f0448c0b4052c90f7dc565d32acae5da04e3e157dca184aba8362\ + bb28a2da6915d51d65f54fbeee69104a5a1b2304b87230c504b126dcf1c377cf\ + 1777b93be6903b50a44f054ae233b7cc24f950ded467cb8ffbdb17e7b6937605 +Prime1: \ + d0505c510a3b38a139d6d139818b04251d6ca46c2e717cfafbeebcd5fff8ae62\ + de4698e3241784f05e8c86f0f996db77259ebaac6983f092853639f619b75701\ + e562408cc1f5c543cada21fc26af36905b10a0df5b111efd754666bb3db4be63 +Prime2: \ + c41623ccb51e2474eb3dc5c2ef42cfd320a285ef7aefc1d1edcd5f566549cb79\ + 7285f01c89b9f749ca506b717c2a45b708fec2e7d611c5eee6af0a6d61219c7d\ + cab18961e98eea3b7797c61a75aed21d411de4fcf4a009a8238a832dd6e41277 +MultiplicativeInverseOfPrime2ModPrime1: \ + bc1ceeed917217387ead12254cfc183f82c79709499f510ce093d6d28bc1bf2b\ + fabc3d86d64a1c807605bd57f9ec533745d6e359270885c3eb7a36a02dff7137\ + 9bd453bf3fdc282afa2295d5e393f1c2c74edcbd2374c7740e8135ef0b8af258 +PublicExponent: 02 +Test: KeyPairValidAndConsistent +Message: 400AEF79EDBCEA796D71 +Signature: 15EB5A68CBCB0D6313BB2D14436237A716AC3159B059FBC29931933DB802D6925C01BDC6D90DD0DA25980F1C8199AB9CD3FD105A63D13B5C0101A0430455334492038FBE029BF4EE61F8A2F88D2A6D5424DE7C0CC314B5EA4F867B35224D574463BDE78B71904033C1455484865EB80AE1C2A7D1C229CD0A4D49C0F06A26E264AD42ACAA131F8C0C5EA4DC9EB5BD349D1EE12B3F91F4B9F2DABC3BCF0E216D4A34A3541169955BE45289CECE16DA6BC5352FF31D66538F64308D6FBB9C7DDE72 +Test: Verify +Message: 63F64BFAD5B830682F44 +Signature: 1003E58A73B018FF9F0F66D3BE9A8DD9D83097A0EB216AEEAA75B63C150AAE9E8BE2A5DE426D18FBC56865F4C9CA51A9BB6E99B70C59B7995246A1F4327C9E4A69517131DA66DDE98AE5D8355527D1C5E4D83CC7ED7B3B1F404F6FDF731DA615974F0777CD22C1E6FAA3569D1141900734C7F3262FE7B9ED291A934DE81A06EBF258F7159DE842737A32DAEC79EFE211C2739D3F5859CB9A633D2A16D78C347790241925C3E776F04B5D5F1900A7B48645DF16DC6F9E8C990AEFEE22FA1DA496 +Test: Verify +Message: B6AAE87E8D469A16A335 +Signature: 368EE32DDF9D5526E50B1645473DB79CE4B0EF3801F3DF050E8B6B10DFAA600A505FD1C91CAE1CD8CB8FA7BC2F81EDFEE7E74DCF7BDA9ED4FF87C39650E8A473672FD012A6A57C5DC44FFBBDA4A5DECD099A32791CEDC6170C8B367080792713041350D2483B27924822DD886A36EE575A3CD6C097162F758F5628D3EA301050AC848F0ACAEDAB8AD34D436E418AA53618AFAFC3168B7CFA641B1A88C86007FD1EDD8FE1D1A94FCE59B548DA3D8FE313A0A97719E19C857560763EFF1682CC14 +Test: Verify +Message: DB0F126516E3EDFF3D7C +Signature: 42076C3F6976EF4BBEAFEF0B4F7A8198CACE6F73436C59DF212474C94D00B0501C359CAB8950EB8937E8458964C817926A3181EED64EAB3A5274A9B3114406F62A62C51F4EDBEEF3BD948C21578996236D6D477B2701DD5A4818B08F5D4740CD23064798C3406133D0758D51717DB4575117DE887733D1E7170AA0845A81535444A962F2003A46361E8A8A1914DA6732C37334320F155E90E18D9E2A921034BEC81395AF69D61E22FEF90BC4F9127914B536BD2477552166C11F139519129864 +Test: Verify +Message: A58B1E5E98C44A8680BD +Signature: 100B8692C7A09EFB585A63B5D636EABFE9DDFE50D5235B11BDFD818D1810893B327ACC3B78942900C8F7498BDC1D2FB44330ADD3FEBC709046D8028F38AA7DCC768558E7D6469EDA306C0FCAE001C7B01544C80043864761355888C13960DD53BBD7854F2FBB7D9DE021BAD69769418712B6335A8C63143329363C65CB4170AA0C040559136EA9C19A6793024AF77BCF3EE793CAEDF07FD8A8E2C9C29B5F225F399BBA177D070314E319359394DB999D866A48D591EE8C662BA6394E396300FE +Test: Verify +Message: 7AF0498714B0D93AB959 +Signature: 35A959E3717468552590C26FA92009C3866955A1D14405AD33D3FA745D7591521A323BA031070B1FB60A1B6FE0C7198FC14EA41CE62EB6EB060FD073E816C9C85BB6251BF5235567E12951778A61D87F117137C347DE56337FBF9A3360D49330A98248233719FF862F83F772AC887F035820579F406D221191F4535ABA37401FF6E28216EC06AB8832D9AB3EAE4E1D3D780A1FA46883A79B657A7027597BCE4F21744CFC3704A449A204D3790F668E2EB710D5CF031BAA58359D35DDF92455D7 +Test: Verify +Comment: 2048-bit RW key +KeyFormat: Component +Modulus: \ + b6dee7375bf4385043b3cc2ac5cacbc14ad11a17574738dd2bd84d2d1e6c74e1\ + 6066c2a5c35bc3b87839858afb5ee5e8abfab408f38772866f6f833f39fab248\ + 3a2c34ed55ad7098f9f63d4ec70b7950f02daaaab10781a0008f993c4027e381\ + 6bfd45c52f59452a7b28873513dce415a84fc8bc06601567f91ec41647da2304\ + 5b6e01e24516724acc02947ad5aa2dba4d952bc4f49d18ada0b0f7cc5d488814\ + b921c0bc2b33d8828d80130df7d79b0992cec40d3bc7217d4a4dff3699345e44\ + dac968575194845aa7b60dcf3c712d9b0a384824c3579b40dba265457d50f69f\ + 02a140884d89b7fdee9f0a787e76a37c58c92cf2d3818c72097d41b3faa7aa95 +Prime1: \ + fa880a456f9c205a26e02c3357536531dec150be0ef8747f69ea30d987ff7dd8\ + 9e9a1075ebd39f04fa495bd26d8408a8de69113a9fbb52f20713d1d046a76b47\ + 8cf77c46454a7afda2ef418f63faf67c947d898bca109f3275999e8f2e60e2c0\ + eec133ff69e71a2d396632670b52d8ea03f7589d8144ab580b1d3e60efa1280b +Prime2: \ + badcc718dd2d761c4893c4831d56ada30fc5c7c148d473bedf7615b7e821b92f\ + 319676ce278349f1309fb3d264c1a22bde71b221354c7a4d31117b3ec3c9d480\ + 2e0a26bd8ec05d28b6502c65f35c687af7f8396b963ed029a2c5ae38dd7c5c96\ + 2a953c113c0f590957ab19a6e2afda6db84f22c0c31ae243debd2920fbe9fbdf +MultiplicativeInverseOfPrime2ModPrime1: \ + 48a56f93e044a8211861da6bde9ab61265c63e168e507b56cd6e6e5f4de57c2f\ + 5c0b626462d6c06790cf561fa12a350dc0c08767f2717914183fac90db36495a\ + 91c0e9c0fbcfef19c85075b3b744fc378a9f2045cd7fd144ecd39bd1a59f1483\ + 10f6982efb3ffe502b279c4c0cb2a7f9ef64ca8f38690c486afb5f659cf7f838 +PublicExponent: 02 +Test: KeyPairValidAndConsistent +Message: 00AA5515CDAE5CD0F0DC +Signature: 30EECA6B48D796552F5A6A3C11F28D730FA077422CAAB34FDEB879AE0F71DF21330E2F3BE5BF3A8CA372EBCD3DFA7C81B3398C31B0972D0B857926CB39732351AACEB8276D52B9D82F9C245FA0F1CF49E785A2BC00FF27FBCF777F84D05BEF17FCC0505820B029AC8F0CE17D2469372CE47E1428BB941004FE170EF87163E07298EFFCC1BFA7E7CB1F572C340CAA075A5962A15B69CE937BC7EFB492F501FC88CBF0119C351C8498782091EF6EFB19120195E5FF51DF86F90E90FAEB225AA2EE43AB4E8358101C0348C7E3859B9DEBA19464C74B74AC48A0B73FC8D2E7F8033E86208F0792B6E5B6DE36C99DEF604949811D1671EF6B0A4781B4E7A0A72AD855 +Test: Verify +Message: B8E2FB9EAE22FB2C0021 +Signature: 416D33F8C213CF81F805F54FC1D4E7C6A588A0965F1C9CAEEA1D41452E20935AAF2D30F957584B56621035430212A428E27A2F687CA9DBB596C19864AE692EF7BBA730F3D70CC2DDE15AB71E1E350C0C316EFA1A831ACD1441598B112482487DF72F58ED318182C7CD0906FE39C5655BF1313F29A15D60A6178CBF600C7FBFF8994840ED649C3C4026A463B3EA39C692B7D112B128BE49E1E32D4A7FF8D4513283D8DCD9CCB8FB7300BE0BDD4C44DAA2F7049B3AD83437093E623442AC69B48911CDA21E95E0775041F67F6E6AE01DCE646AEC20908E7C1B693600FE41ABA85AC0C778641E46C419083E41773C749DB3E1BD8FD764E271860D2D7F8E11BD6AB3 +Test: Verify +Message: 8C8C306A629373BAE647 +Signature: 0E9A00045FFD399D9DA9D0D7E543CF9FFD098BC23E72DD7763A64F22C7F0479CE866E31438B8F7DE31A18F35AF419BED6C67BE1540614D3310DD24F019E14FCC3AF73743F4C143D4B79CDF35C752A300F0A8251CCFF4AAF18785C533A7DF1A20AFE6770DEBD1B8BA2C83B2E345A04F833CD173E998FF9840C2F8A370FFDCFF5FD95CBD71B25FC9972192470FD145975344F64C2F6D68CB3513F48F9FC070021BEE8F6A4282D098C44DF655CE415E89B97994AE3ABE85986C7EE0AC348EF2A4F52D102EA80836E77E81AD3678803E53C83CF2F30D2D4950FB6B038CCB3F2690A9381EB34D6C09E88C090AB05E28047DC490EB8A1282FEB38E82FB0B18309284C4 +Test: Verify +Message: 15E7B7B7ED0F176B6799 +Signature: 39FF4B5FA50AE498F3C91A655E6865840D1FC401EE02DBC8460A59DEB8816E6680F712B7BAF8D4DC11A3B54BF906BE698306F0449BB43F3F223B944D930A1A3C718E8A9E2EEDEC5A07AB817C26A80CC2A2EE2846A597EAB8A999D38DB98490166F2574524038BBDF24B4E4622C843210C6B94987638C6976562EA9727385B152614C18349BD54AD95DE33D5354954B505E5259CCDA47E3CECEF3154F6E5481E536BAB568146A0BFCB66573714A7BA7ABE0385115720687F33D9C6EF6BB60272F1272CF349990E3A2FBCCE180B730792101089B164AE5A001F5263F7493AF148D6E0953E311AD12E4202D35F96DD30885663B5101F9B05675FCD2FCC4FCC4DDFF +Test: Verify +Message: B36724C92954C38D0288 +Signature: 3C8CD3614555568BBECA99174B7B203D0BC6FABE9E6FFE0C41EB4D9A2C601D2393CA1E01B7D7E99337758AC914C9F151311E5AE6708DAF1D8C825DA471652C6E13A8FE5802D7AE097BFC899A4EC8CA235B5982B9058C53AAD52823ACF692290EB8823C126635AB0BBF101C2B3149AB16183FA2DBB049DDB99C5E83723E4D4693CA3A08588AA868C677D42ABDAA6586EF192391D276C5E5AF0763ACCA6293F06250C51FDC2AD369CD44EB5F654E98761C881DDEC08E795FFB229B20522349B0714059E18B7B23A48875EAB12ED3F0A011D3A985DD7384B0046F39FA6C1A331F3D4C5125100BA58666935C68A7A10849D9C74850BAB82AE15EC950A283F3E7DAD8 +Test: Verify +Message: FA95400C2B14E064F76A +Signature: 3F67F9DBEB88E6AD057BEDC3D97030555A908867EC578A6CA572137CB61C21036AADE6DDC5592EC7CCB6B263E51B4C886A51904C858040E493D64B9ACE5BAA50C4A66D04ACCDFE0039D8541C4363DEFFCF93BDF5F5CC1FB64855D956B5EFD42D4C9B96B9CBAA97A32F02AAB307674E53404E6836DB5C96B59572ADBFD1113B87608ACE6D0898CB02E35575CC28D38A9FF8C1C4AD36BAA991DEFAB533F0A6C9C2F0F0815F1D659ED576E5DB18494A54B6817D9E34A134F3B9A0F1E8C77FC204B6EE087C0445A7036C935117E338D092F6E1FF4DF7605525C409456A5195233A176B29B2FD8FB2808D0412FCA0541B2BB6800BD8BB9DC9DC25230166071E8D961E +Test: Verify diff --git a/src-cryptopp/TestVectors/salsa.txt b/src-cryptopp/TestVectors/salsa.txt new file mode 100644 index 0000000..b00ff96 --- /dev/null +++ b/src-cryptopp/TestVectors/salsa.txt @@ -0,0 +1,463 @@ +AlgorithmType: SymmetricCipher +Name: Salsa20 +Source: http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors?rev=161&view=markup +Comment: Set 1, vector# 0 +Key: 80000000000000000000000000000000 +IV: 0000000000000000 +Plaintext: r16 00000000 +Seek: 0 +Ciphertext: 4DFA5E481DA23EA09A31022050859936DA52FCEE218005164F267CB65F5CFD7F2B4F97E0FF16924A52DF269515110A07F9E460BC65EF95DA58F740B7D1DBB0AA +Test: Encrypt +Seek: 448 +Ciphertext: B375703739DACED4DD4059FD71C3C47FC2F9939670FAD4A46066ADCC6A5645783308B90FFB72BE04A6B147CBE38CC0C3B9267C296A92A7C69873F9F263BE9703 +Test: Encrypt +Seek: 192 +Plaintext: r32 00000000 +Ciphertext: DA9C1581F429E0A00F7D67E23B730676783B262E8EB43A25F55FB90B3E753AEF8C6713EC66C51881111593CCB3E8CB8F8DE124080501EEEB389C4BCB6977CF95\ +7D5789631EB4554400E1E025935DFA7B3E9039D61BDC58A8697D36815BF1985CEFDF7AE112E5BB81E37ECF0616CE7147FC08A93A367E08631F23C03B00A8DA2F +Test: Encrypt +Comment: Set 3, vector#243 +Key: F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112 +IV: 0000000000000000 +Plaintext: r16 00000000 +Seek: 0 +Ciphertext: B4C0AFA503BE7FC29A62058166D56F8F5D27DC246F75B9AD8760C8C39DFD87492D3B76D5D9637F009EADA14458A52DFB09815337E72672681DDDC24633750D83 +Test: Encrypt +Seek: 448 +Ciphertext: 5A5FB5C8F0AFEA471F0318A4A2792F7AA5C67B6D6E0F0DDB79961C34E3A564BA2EECE78D9AFF45E510FEAB1030B102D39DFCECB77F5798F7D2793C0AB09C7A04 +Test: Encrypt +Seek: 192 +Plaintext: r32 00000000 +Ciphertext: DBBA0683DF48C335A9802EEF0252256354C9F763C3FDE19131A6BB7B85040624B1D6CD4BF66D16F7482236C8602A6D58505EEDCCA0B77AED574AB583115124B9\ +F0C5F98BAE05E019764EF6B65E0694A904CB9EC9C10C297B1AB1A6052365BB78E55D3C6CB9F06184BA7D425A92E7E987757FC5D9AFD7082418DD64125CA6F2B6 +Test: Encrypt +Comment: Set 6, vector# 3 +Seek: 0 +Key: 0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C +IV: 288FF65DC42B92F9 +Plaintext: r131072 00 +CiphertextXorDigest: E00EBCCD70D69152725F9987982178A2E2E139C7BCBE04CA8A0E99E318D9AB76F988C8549F75ADD790BA4F81C176DA653C1A043F11A958E169B6D2319F4EEC1A +Test: EncryptXorDigest +AlgorithmType: SymmetricCipher +Name: Salsa20 +Source: http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/reduced/12-rounds/verified.test-vectors?rev=210&view=auto +Comment: Set 1, vector# 0 +Rounds: 12 +Key: 80000000000000000000000000000000 +IV: 0000000000000000 +Plaintext: r64 00 +Seek: 0 +Ciphertext: FC207DBFC76C5E1774961E7A5AAD09069B2225AC1CE0FE7A0CE77003E7E5BDF8B31AF821000813E6C56B8C1771D6EE7039B2FBD0A68E8AD70A3944B677937897 +Test: Encrypt +Seek: 192 +Ciphertext: 4B62A4881FA1AF9560586510D5527ED48A51ECAFA4DECEEBBDDC10E9918D44AB26B10C0A31ED242F146C72940C6E9C3753F641DA84E9F68B4F9E76B6C48CA5AC +Test: Encrypt +Source: http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/reduced/8-rounds/verified.test-vectors?rev=210&view=auto +Comment: Set 1, vector# 0 +Rounds: 8 +Key: 80000000000000000000000000000000 +IV: 0000000000000000 +Plaintext: r64 00 +Seek: 0 +Ciphertext: A9C9F888AB552A2D1BBFF9F36BEBEB337A8B4B107C75B63BAE26CB9A235BBA9D784F38BEFC3ADF4CD3E266687EA7B9F09BA650AE81EAC6063AE31FF12218DDC5 +Test: Encrypt +Seek: 192 +Ciphertext: BB5B6BB2CC8B8A0222DCCC1753ED4AEB23377ACCBD5D4C0B69A8A03BB115EF71871BC10559080ACA7C68F0DEF32A80DDBAF497259BB76A3853A7183B51CC4B9F +Test: Encrypt + +AlgorithmType: SymmetricCipher +Name: XSalsa20 +Source: created by Wei Dai using naclcrypto-20090308 +Key: 1b27556473e985d462cd51197a9a46c76009549eac6474f206c4ee0844f68389 +IV: 69696ee955b62b73cd62bda875fc73d68219e0036b7a0b37 +Plaintext: r139 00 +Ciphertext: \ +eea6a7251c1e72916d11c2cb214d3c252539121d8e234e652d651fa4c8cff880\ +309e645a74e9e0a60d8243acd9177ab51a1beb8d5a2f5d700c093c5e55855796\ +25337bd3ab619d615760d8c5b224a85b1d0efe0eb8a7ee163abb0376529fcc09\ +bab506c618e13ce777d82c3ae9d1a6f972d4160287cbfe60bf2130fc0a6ff604\ +9d0a5c8a82f429231f0080 +Key: a6a7251c1e72916d11c2cb214d3c252539121d8e234e652d651fa4c8cff88030 +IV: 9e645a74e9e0a60d8243acd9177ab51a1beb8d5a2f5d700c +Plaintext: 093c5e5585579625337bd3ab619d615760d8c5b224a85b1d0efe0eb8a7ee163abb0376529fcc09bab506c618e13ce777d82c3ae9d1a6f972d4160287cbfe60bf2130fc0a6ff6049d0a5c8a82f429231f008082e845d7e189d37f9ed2b464e6b919e6523a8c1210bd52a02a4c3fe406d3085f5068d1909eeeca6369abc981a42e87fe665583f0ab85ae71f6f84f528e6b397af86f6917d9754b7320dbdc2fea81496f2732f532ac78c4e9c6cfb18f8e9bdf74622eb126141416776971a84f94d156beaf67aecbf2ad412e76e66e8fad7633f5b6d7f3d64b5c6c69ce29003c6024465ae3b89be78e915d88b4b5621d +Ciphertext: b2af688e7d8fc4b508c05cc39dd583d6714322c64d7f3e63147aede2d9534934b04ff6f337b031815cd094bdbc6d7a92077dce709412286822ef0737ee47f6b7ffa22f9d53f11dd2b0a3bb9fc01d9a88f9d53c26e9365c2c3c063bc4840bfc812e4b80463e69d179530b25c158f543191cff993106511aa036043bbc75866ab7e34afc57e2cce4934a5faae6eabe4f221770183dd060467827c27a354159a081275a291f69d946d6fe28ed0b9ce08206cf484925a51b9498dbde178ddd3ae91a8581b91682d860f840782f6eea49dbb9bd721501d2c67122dea3b7283848c5f13e0c0de876bd227a856e4de593a3 +Test: Encrypt +IV: b2af688e7d8fc4b508c05cc39dd583d6714322c64d7f3e63 +Ciphertext: 418078fe843f5984dd3c7975d1ff51af4dceda640999aaa3c28618ae286ca15051cb4d55f9da22a213ef14a2b905b52c99a557854c7f2a6d6ed6f69c1c6649f3fb67b8628468029b3367920c2e1148aa1f3b9c695cb1426f09ce84045842946e0454e41ab1edb32cae4b95669de4e2ccaf00ba86ffeae6a9c5fce4153baddb0d8998a600537a9649939cb7d7a9c4e8cbca0fab77963abd516699879de0b1971dc7328668111ff5b77c253b9e6346d1a2ce6e390cd736156ad7f44b339cfb141f00e7a766c06e130b0c31d88980d2ad8814a2d641599162ab8af25d93067f06a49637eaf6523806b8fa07d56628bb +Test: Resync +Key: 9e1da239d155f52ad37f75c7368a536668b051952923ad44f57e75ab588e475a +IV: af06f17859dffa799891c4288f6635b5c5a45eee9017fd72 +Plaintext: feac9d54fc8c115ae247d9a7e919dd76cfcbc72d32cae4944860817cbdfb8c04e6b1df76a16517cd33ccf1acda9206389e9e318f5966c093cfb3ec2d9ee2de856437ed581f552f26ac2907609df8c613b9e33d44bfc21ff79153e9ef81a9d66cc317857f752cc175fd8891fefebb7d041e6517c3162d197e2112837d3bc4104312ad35b75ea686e7c70d4ec04746b52ff09c421451459fb59f +Ciphertext: 2c261a2f4e61a62e1b27689916bf03453fcbc97bb2af6f329391ef063b5a219bf984d07d70f602d85f6db61474e9d9f5a2deecb4fcd90184d16f3b5b5e168ee03ea8c93f3933a22bc3d1a5ae8c2d8b02757c87c073409052a2a8a41e7f487e041f9a49a0997b540e18621cad3a24f0a56d9b19227929057ab3ba950f6274b121f193e32e06e5388781a1cb57317c0ba6305e910961d01002f0 +Test: Encrypt +IV: 2c261a2f4e61a62e1b27689916bf03453fcbc97bb2af6f32 +Ciphertext: 7030af4a9db8a6b95f55f962efefcc60d8ceb0d5d920e808cebd8cf6f31542d227a67c9db8888cfcb9410ae357f8a3da06a608a93b7fd5513978c6b8b837f6ecaafd3366495cdd3ab719d9d4c2ac74d6ea2eb117f30369ea62727fa6dc7982f668fa3bf44c9da8e70ff8c18b07d63aa01afe1311bdafc457d06c69aaea0dfbb1fc89d1574ad1e7be8b459d4cf36bdd88db0363219652089c50 +Test: Resync +Key: d5c7f6797b7e7e9c1d7fd2610b2abf2bc5a7885fb3ff78092fb3abe8986d35e2 +IV: 744e17312b27969d826444640e9c4a378ae334f185369c95 +Plaintext: 7758298c628eb3a4b6963c5445ef66971222be5d1a4ad839715d1188071739b77cc6e05d5410f963a64167629757 +Ciphertext: 27b8cfe81416a76301fd1eec6a4d99675069b2da2776c360db1bdfea7c0aa613913e10f7a60fec04d11e65f2d64e +Test: Encrypt +IV: 27b8cfe81416a76301fd1eec6a4d99675069b2da2776c360 +Ciphertext: ed158a1dd07f4316d403af3e6977afaac8205d678b38fa5928c61e366ff27003143d5d20482a2ea76a50756225a4 +Test: Resync +Key: 737d7811ce96472efed12258b78122f11deaec8759ccbd71eac6bbefa627785c +IV: 6fb2ee3dda6dbd12f1274f126701ec75c35c86607adb3edd +Plaintext: 501325fb2645264864df11faa17bbd58312b77cad3d94ac8fb8542f0eb653ad73d7fce932bb874cb89ac39fc47f8267cf0f0c209f204b2d8578a3bdf461cb6a271a468bebaccd9685014ccbc9a73618c6a5e778a21cc8416c60ad24ddc417a130d53eda6dfbfe47d09170a7be1a708b7b5f3ad464310be36d9a2a95dc39e83d38667e842eb6411e8a23712297b165f690c2d7ca1b1346e3c1fccf5cafd4f8be0 +Ciphertext: 6724c372d2e9074da5e27a6c54b2d703dc1d4c9b1f8d90f00c122e692ace7700eadca942544507f1375b6581d5a8fb39981c1c0e6e1ff2140b082e9ec016fce141d5199647d43b0b68bfd0fea5e00f468962c7384dd6129aea6a3fdfe75abb210ed5607cef8fa0e152833d5ac37d52e557b91098a322e76a45bbbcf4899e790618aa3f4c2e5e0fc3de93269a577d77a5502e8ea02f717b1dd2df1ec69d8b61ca +Test: Encrypt +IV: 6724c372d2e9074da5e27a6c54b2d703dc1d4c9b1f8d90f0 +Ciphertext: cfb653dd50a04a8580847d5bb98dc15e27c60f5a70da635718ba6d589f47935ed476fc960ffaf3b8750a59171b1434429a977ba878aea7ace8dd083a9238585112591165d0948a86e89e6118d572aa85667cceffd78a60baa5a152dc5e29bdd93f7389edde1541eec2f3aac38ea2bfc812f73de7e2e7b1322468f823a2c7c16e30fe9283894ac057da5c45a67f4988b4edafeb51c1b4a51a849d188b15838552 +Test: Resync +Key: 760158da09f89bbab2c99e6997f9523a95fcef10239bcca2573b7105f6898d34 +IV: 43636b2cc346fc8b7c85a19bf507bdc3dafe953b88c69dba +Plaintext: d30a6d42dff49f0ed039a306bae9dec8d9e88366cc19e8c3642fd58fa0794ebf8029d949730339b0823a51f0f49f0d2c71f1051c1e0e2c86941f172789cdb1b0107413e70f982ff9761877bb526ef1c3eb1106a948d60ef21bd35d32cfd64f89b79ed63ecc5cca56246af736766f285d8e6b0da9cb1cd21020223ffacc5a32 +Ciphertext: c815b6b79b64f9369aec8dce8c753df8a50f2bc97c70ce2f014db33a65ac5816bac9e30ac08bdded308c65cb87e28e2e71b677dc25c5a6499c1553555daf1f55270a56959dffa0c66f24e0af00951ec4bb59ccc3a6c5f52e0981647e53e439313a52c40fa7004c855b6e6eb25b212a138e843a9ba46edb2a039ee82a263abe +Test: Encrypt +IV: c815b6b79b64f9369aec8dce8c753df8a50f2bc97c70ce2f +Ciphertext: ab7204ab4f995c2d87376c3586f0261250907ab2c25e2d232f10f51f0f3a3f11ff704ba188a508301fb9d5f7e4d55070631ecd2e3be5d79d4fa67f4f4acb3879afc2dc18c09446489b79dd3043f74027e9a24a54d8babe757c9a3470a95cb7b7b093331e32534b337d697046f7349bcfa89036b3cf50ecfc6f1e61300a49b6 +Test: Resync +Key: 27ba7e81e7edd4e71be53c07ce8e633138f287e155c7fa9e84c4ad804b7fa1b9 +IV: ea05f4ebcd2fb6b000da0612861ba54ff5c176fb601391aa +Plaintext: e09ff5d2cb050d69b2d42494bde5825238c756d6991d99d7a20d1ef0b83c371c89872690b2fc11d5369f4fc4971b6d3d6c078aef9b0f05c0e61ab89c025168054defeb03fef633858700c58b1262ce011300012673e893e44901dc18eee3105699c44c805897bdaf776af1833162a21a +Ciphertext: a23e7ef93c5d0667c96d9e404dcbe6be62026fa98f7a3ff9ba5d458643a16a1cef7272dc6097a9b52f35983557c77a11b314b4f7d5dc2cca15ee47616f861873cbfed1d32372171a61e38e447f3cf362b3abbb2ed4170d89dcb28187b7bfd206a3e026f084a7e0ed63d319de6bc9afc0 +Test: Encrypt +IV: a23e7ef93c5d0667c96d9e404dcbe6be62026fa98f7a3ff9 +Ciphertext: 5c77efcb16097df824bd58cd3498e07af1c761740b5539929115e2caf3bc10eed2a16254a4306f4e20827247900276ce887362990c070c0f79e15987473b7ad240e7a9f8e6e3f020fb337438cc3c8b81c4cdbfbdd7b543b13a48a4959744f3efcb99a939c0599ce32f816d12c2b47a2f +Test: Resync +Key: 6799d76e5ffb5b4920bc2768bafd3f8c16554e65efcf9a16f4683a7a06927c11 +IV: 61ab951921e54ff06d9b77f313a4e49df7a057d5fd627989 +Plaintext: 472766 +Ciphertext: 8fd7df +Test: Encrypt +IV: 8fd7dfcb16097df824bd58cd3498e07af1c761740b553992 +Ciphertext: 85e098 +Test: Resync +Key: f68238c08365bb293d26980a606488d09c2f109edafa0bbae9937b5cc219a49c +IV: 5190b51e9b708624820b5abdf4e40fad1fb950ad1adc2d26 +Plaintext: 47ec6b1f73c4b7ff5274a0bfd7f45f864812c85a12fbcb3c2cf8a3e90cf66ccf2eacb521e748363c77f52eb426ae57a0c6c78f75af71284569e79d1a92f949a9d69c4efc0b69902f1e36d7562765543e2d3942d9f6ff5948d8a312cff72c1afd9ea3088aff7640bfd265f7a9946e606abc77bcedae6bddc75a0dba0bd917d73e3bd1268f727e0096345da1ed25cf553ea7a98fea6b6f285732de37431561ee1b3064887fbcbd71935e02 +Ciphertext: 36160e88d3500529ba4edba17bc24d8cfaca9a0680b3b1fc97cf03f3675b7ac301c883a68c071bc54acdd3b63af4a2d72f985e51f9d60a4c7fd481af10b2fc75e252fdee7ea6b6453190617dcc6e2fe1cd56585fc2f0b0e97c5c3f8ad7eb4f31bc4890c03882aac24cc53acc1982296526690a220271c2f6e326750d3fbda5d5b63512c831f67830f59ac49aae330b3e0e02c9ea0091d19841f1b0e13d69c9fbfe8a12d6f30bb734d9d2 +Test: Encrypt +IV: 36160e88d3500529ba4edba17bc24d8cfaca9a0680b3b1fc +Ciphertext: f003b213737415a81894a3d3d8fe4e4434d4df2b253d60c44609bdc0414cedf8bae297ecdb1d0b92393dd6dd7027b555388ac8a66308082fc6327ad94ad96223003de15c48a06e9cd99b5561e7fc5949c6ba8cf11d6ba1374ec32062caef541e7252d168781aab4c637793433b3998c5a5013fd35c336600a02765ddbf52b97ae80dbfbbe55e43c6bd5f746a1c2df4c80611c76a90308c47b2807876249d6d3c507a1a96c2bbb8242ccd +Test: Resync +Key: 45b2bd0de4ed9293ec3e26c4840faaf64b7d619d51e9d7a2c7e36c83d584c3df +IV: 546c8c5d6be8f90952cab3f36d7c1957baaa7a59abe3d7e5 +Plaintext: 5007c8cd5b3c40e17d7fe423a87ae0ced86bec1c39dc07a25772f3e96dabd56cd3fd7319f6c9654925f2d87087a700e1b130da796895d1c9b9acd62b266144067d373ed51e787498b03c52faad16bb3826fa511b0ed2a19a8663f5ba2d6ea7c38e7212e9697d91486c49d8a000b9a1935d6a7ff7ef23e720a45855481440463b4ac8c4f6e7062adc1f1e1e25d3d65a31812f58a71160 +Ciphertext: 8eacfba568898b10c0957a7d44100685e8763a71a69a8d16bc7b3f88085bb9a2f09642e4d09a9f0ad09d0aad66b22610c8bd02ff6679bb92c2c026a216bf425c6be35fb8dae7ff0c72b0efd6a18037c70eed0ca90062a49a3c97fdc90a8f9c2ea536bfdc41918a7582c9927fae47efaa3dc87967b7887dee1bf071734c7665901d9105dae2fdf66b4918e51d8f4a48c60d19fbfbbcba +Test: Encrypt +IV: 8eacfba568898b10c0957a7d44100685e8763a71a69a8d16 +Ciphertext: f17808cf21dba4762ced5fcc264f615a4619d8d5ee3278dbdacf14a799f8ee5f8a38a7fd9d262b336e51a8790c90fb8f0b63a49edae81f9a200ad73d9ed5ce6257524b506d7a219013e3e44a1f2a264b7f7f121e5d4765d0bdfe4a36fc51e48ee21e9dcbc3dc2541405bbdb90490fd786b942a07786094fc990be21e5b746d522cad26269a76c85134ee654f33485807fc28cf87ac37 +Test: Resync +Key: fe559c9a282beb40814d016d6bfcb2c0c0d8bf077b1110b8703a3ce39d70e0e1 +IV: b076200cc7011259805e18b304092754002723ebec5d6200 +Plaintext: 6db65b9ec8b114a944137c821fd606be75478d928366d5284096cdef782fcff7e8f59cb8ffcda979757902c5ffa6bc477ceaa4cb5d5ea76f94d91e833f823a6bc78f1055dfa6a97bea8965c1cde67a668e001257334a585727d9e0f7c1a06e88d3d25a4e6d9096c968bf138e116a3ebeffd4bb4808adb1fd698164ba0a35c709a47f16f1f4435a2345a9194a00b95abd51851d505809a6077da9baca5831afff31578c487ee68f2767974a98a7e803aac788da98319c4ea8eaa3d394855651f484cef543f537e35158ee29 +Ciphertext: 4dce9c8f97a028051b0727f34e1b9ef21f06f0760f36e71713204027902090ba2bb6b13436ee778d9f50530efbd7a32b0d41443f58ccaee781c7b716d3a96fdec0e3764ed7959f34c3941278591ea033b5cbadc0f1916032e9bebbd1a8395b83fb63b1454bd775bd20b3a2a96f951246ac14daf68166ba62f6cbff8bd121ac9498ff8852fd2be975df52b5daef3829d18eda42e715022dcbf930d0a789ee6a146c2c7088c35773c63c06b4af4559856ac199ced86863e4294707825337c5857970eb7fddeb263781309011 +Test: Encrypt +IV: 4dce9c8f97a028051b0727f34e1b9ef21f06f0760f36e717 +Ciphertext: 534f5151319c299d7356be2275ed2137fab66742797370b511e5150dcf7bc75c06d5249e8e8bd7c16e563cc7d99368a7a7f47f811a2ae2b632c73e9f49641bf9954d4df19c2778221d780f799806757738b327e6aeebab6bb22137f8b994c1e08baff75bb2774576bce2deb599817fc7a69860c538efffe91439f4714e4629b00a25b5b1a6be8aa7da2be33bad953481926e0067a70d4ff1a7bd0111e605ef6a2d66fa7af43d746c24a5d464dd6f75773aa9b65bbdfad9b82fe80f182b144cea9211d0b2472de873008509 +Test: Resync +Key: 0ae10012d7e56614b03dcc89b14bae9242ffe630f3d7e35ce8bbb97bbc2c92c3 +IV: f96b025d6cf46a8a12ac2af1e2aef1fb83590adadaa5c5ea +Plaintext: ea0f354e96f12bc72bbaa3d12b4a8ed879b042f0689878f46b651cc4116d6f78409b11430b3aaa30b2076891e8e1fa528f2fd169ed93dc9f84e24409eec2101daf4d057be2492d11de640cbd7b355ad29fb70400fffd7cd6d425abeeb732a0eaa4330af4c656252c4173deab653eb85c58462d7ab0f35fd12b613d29d473d330310dc323d3c66348bbdbb68a326324657cae7b77a9e34358f2cec50c85609e73056856796e3be8d62b6e2fe9f953 +Ciphertext: e8abd48924b54e5b80866be7d4ebe5cf4274cafff08b39cb2d40a8f0b472398aedc776e0793812fbf1f60078635d2ed86b15efcdba60411ee23b07233592a44ec31b1013ce8964236675f8f183aef885e864f2a72edf4215b5338fa2b54653dfa1a8c55ce5d95cc605b9b311527f2e3463ffbec78a9d1d65dabad2f338769c9f43f133a791a11c7eca9af0b771a4ac32963dc8f631a2c11217ac6e1b9430c1aae1ceebe22703f429998a8fb8c641 +Test: Encrypt +IV: e8abd48924b54e5b80866be7d4ebe5cf4274cafff08b39cb +Ciphertext: e8c59b616dd10474930c432422d23d8df8dee1c626def1278eb6c9828435c0c8a98aea9d350752a78cf0cf1de7973436605f22b0d40b9059d777c55c8fd02cd9dbab6888161ed28979c64b700d7ea48038edf36af21078713f844f5f23a4f271aad3562ed2cd773de622fff2f0b5785672760a7064e5415c76ffec522eb1225868345e89a9fcbb4f12c1176b01550fe7a74f750dc43d6fa4718c33ba99b0084c7a1a8e245c8566056296aabe13af +Test: Resync +Key: 082c539bc5b20f97d767cd3f229eda80b2adc4fe49c86329b5cd6250a9877450 +IV: 845543502e8b64912d8f2c8d9fffb3c69365686587c08d0c +Plaintext: a96bb7e910281a6dfad7c8a9c370674f0ceec1ad8d4f0de32f9ae4a23ed329e3d6bc708f876640a229153ac0e7281a8188dd77695138f01cda5f41d5215fd5c6bdd46d982cb73b1efe2997970a9fdbdb1e768d7e5db712068d8ba1af6067b5753495e23e6e1963af012f9c7ce450bf2de619d3d59542fb55f3 +Ciphertext: 835da74fc6de08cbda277a7966a07c8dcd627e7b17adde6d930b6581e3124b8baad096f693991fedb1572930601fc7709541839b8e3ffd5f033d2060d999c6c6e3048276613e648000acb5212cc632a916afce290e20ebdf612d08a6aa4c79a74b070d3f872a861f8dc6bb07614db515d363349d3a8e3336a3 +Test: Encrypt +IV: 835da74fc6de08cbda277a7966a07c8dcd627e7b17adde6d +Ciphertext: a91f3039c37f753857510f121cbbab8f942b41a4d04815729361268c84abed9fd3dd2c0a84ea5dc3cab46245f720d8f0fd81ce4c7837aae561186f66ae70db9e5c2238f1b417b0ab001eada16d1f9bcc2ed74d335fe8da60bebd8b1c4ae4c51d8c46eec7d1fd575a5824bced85b02bfcb1e11d5686471b2791 +Test: Resync +Key: 3d02bff3375d403027356b94f514203737ee9a85d2052db3e4e5a217c259d18a +IV: 74216c95031895f48c1dba651555ebfa3ca326a755237025 +Plaintext: 0d4b0f54fd09ae39baa5fa4baccf2e6682e61b257e01f42b8f +Ciphertext: 16c4006c28365190411eb1593814cf15e74c22238f210afc3d +Test: Encrypt +IV: 16c4006c28365190411eb1593814cf15e74c22238f210afc +Ciphertext: c86458ffa23d50437f3385ea7d3fbae5cdc1df7a14658b8316 +Test: Resync +Key: ad1a5c47688874e6663a0f3fa16fa7efb7ecadc175c468e5432914bdb480ffc6 +IV: e489eed440f1aae1fac8fb7a9825635454f8f8f1f52e2fcc +Plaintext: aa6c1e53580f03a9abb73bfdadedfecada4c6b0ebe020ef10db745e54ba861caf65f0e40dfc520203bb54d29e0a8f78f16b3f1aa525d6bfa33c54726e59988cfbec78056 +Ciphertext: 02fe84ce81e178e7aabdd3ba925a766c3c24756eefae33942af75e8b464556b5997e616f3f2dfc7fce91848afd79912d9fb55201b5813a5a074d2c0d4292c1fd441807c5 +Test: Encrypt +IV: 02fe84ce81e178e7aabdd3ba925a766c3c24756eefae3394 +Ciphertext: 5526b8ff95272e95ad298c30f9f165353ecf0f68aa2943476ec53c386cf07c465b677be13d01279779965dda94d23fe9452dc4934e344c2ee0f6f5e32efc2b3f79630492 +Test: Resync +Key: 053a02bedd6368c1fb8afc7a1b199f7f7ea2220c9a4b642a6850091c9d20ab9c +IV: c713eea5c26dad75ad3f52451e003a9cb0d649f917c89dde +Plaintext: 8f0a8a164760426567e388840276de3f95cb5e3fadc6ed3f3e4fe8bc169d9388804dcb94b6587dbb66cb0bd5f87b8e98b52af37ba290629b858e0e2aa7378047a26602 +Ciphertext: 516710e59843e6fbd4f25d0d8ca0ec0d47d39d125e9dad987e0518d49107014cb0ae405e30c2eb3794750bca142ce95e290cf95abe15e822823e2e7d3ab21bc8fbd445 +Test: Encrypt +IV: 516710e59843e6fbd4f25d0d8ca0ec0d47d39d125e9dad98 +Ciphertext: aadb7c36647ded09fca7587edfa9bbe81911925fa8996330c8e7b77601075e5f94404db9f82c67e2cd39d1649062d4c30cf23bc28f9ddd6d5b9ec586a7de7f8ef45560 +Test: Resync +Key: 5b14ab0fbed4c58952548a6cb1e0000cf4481421f41288ea0aa84add9f7deb96 +IV: 54bf52b911231b952ba1a6af8e45b1c5a29d97e2abad7c83 +Plaintext: 37fb44a675978b560ff9a4a87011d6f3ad2d37a2c3815b45a3c0e6d1b1d8b1784cd468927c2ee39e1dccd4765e1c3d676a335be1ccd6900a45f5d41a317648315d8a8c24adc64eb285f6aeba05b9029586353d303f17a807658b9ff790474e1737bd5fdc604aeff8dfcaf1427dcc3aacbb0256badcd183ed75a2dc52452f87d3c1ed2aa583472b0ab91cda20614e9b6fdbda3b49b098c95823cc72d8e5b717f2314b0324e9ce +Ciphertext: ae6deb5d6ce43d4b09d0e6b1c0e9f46157bcd8ab50eaa3197ff9fa2bf7af649eb52c68544fd3adfe6b1eb316f1f23538d470c30dbfec7e57b60cbcd096c782e7736b669199c8253e70214cf2a098fda8eac5da79a9496a3aae754d03b17c6d70d1027f42bf7f95ce3d1d9c338854e158fcc803e4d6262fb639521e47116ef78a7a437ca9427ba645cd646832feab822a208278e45e93e118d780b988d65397eddfd7a819526e +Test: Encrypt +IV: ae6deb5d6ce43d4b09d0e6b1c0e9f46157bcd8ab50eaa319 +Ciphertext: 89e9c51abd31d6156b96c4e82ef0dfe5c376bd6324750fdbc46e5ae63897323c816fb5bb8e6bf4335853e512cc334dbbfecccfe4e5c8fe8289963ee7127f3ac56bc26b7bd4f0d1e0afb06bde930e7587eedf07995d5052bbff5453147c1555a7c8534111295bb5ab9e89645cc330ae3e0d9294c9e7d6d841579e93aefeaed879f8e8299459a3c07e3c9dee497360510668c5246970ad39077e8d8935b0d885f11d2f06dee0d7 +Test: Resync +Key: d74636e3413a88d85f322ca80fb0bd650bd0bf0134e2329160b69609cd58a4b0 +IV: efb606aa1d9d9f0f465eaa7f8165f1ac09f5cb46fecf2a57 +Plaintext: f85471b75f6ec81abac2799ec09e98e280b2ffd64ca285e5a0109cfb31ffab2d617b2c2952a2a8a788fc0da2af7f530758f74f1ab56391ab5ff2adbcc5be2d6c7f49fbe8118104c6ff9a23c6dfe52f57954e6a69dcee5db06f514f4a0a572a9a8525d961dae72269b987189d465df6107119c7fa790853e063cba0fab7800ca932e258880fd74c33c784675bedad0e7c09e9cc4d63dd5e9713d5d4a0196e6b562226ac31b4f57c04f90a181973737ddc7e80f364112a9fbb435ebdbcabf7d490ce52 +Ciphertext: b2b795fe6c1d4c83c1327e015a67d4465fd8e32813575cbab263e20ef05864d2dc17e0e4eb81436adfe9f638dcc1c8d78f6b0306baf938e5d2ab0b3e05e735cc6fff2d6e02e3d60484bea7c7a8e13e23197fea7b04d47d48f4a4e5944174539492800d3ef51e2ee5e4c8a0bdf050c2dd3dd74fce5e7e5c37364f7547a11480a3063b9a0a157b15b10a5a954de2731ced055aa2e2767f0891d4329c426f3808ee867bed0dc75b5922b7cfb895700fda016105a4c7b7f0bb90f029f6bbcb04ac36ac16 +Test: Encrypt +IV: b2b795fe6c1d4c83c1327e015a67d4465fd8e32813575cba +Ciphertext: 0a8a907dc7f30f6f68eec465ead25768383956a304aa32e4ccea6e3756cbb19f2751e3b68339ade1499004a88170e44620529d3c568cb1e014c16548830dfbce1b47a2dcdd28e59bb0daf5908c5ff51817bd119fe33bda07d63e93a3522685eb101d912b02d093780d10884959ae4a49e2fb7fca51b81394f09314879a41f6dc2f4a7dc34e88da4747a5a1fc15dcb207d13222f08f91f079eafbded0d6036325f607ff29ff2fc7635e8c3767d61a3b7814227d6a2798d623bfdf674604e4e9e03529 +Test: Resync +Key: ea060c72f6e0080fd4a9a2131c9d684902415cab34fce4e52d62273e3c385f37 +IV: 5826043957a27509423fdd82f34935928a4b23a84ede72c8 +Plaintext: 20ae58dbf5c20225c35518711a86a19a61d5ba47ab17e8c5fa9658333d40ed31bffb79cde927c36baf61ed8df37acac330f64471bd91d90bfafa72dc8cdb6ed95ec6610cd6e8f2859255216a3eb4b573410d5644a40e4f0fa785d556304489c0023a1991eb0d01b5 +Ciphertext: 6025c4d5bcc769cc3e67b88340b4101690eb283654c761f8a0af360926313129f16d1c9358ecbaf66acd85787c7c1f52a953bc05e91d43bf3d94d341bffc5913435fb3a8e6264ccd1c355472929a140fe30a22689b055082c70395e0b070a3f0967ab36848cdf3d9 +Test: Encrypt +IV: 6025c4d5bcc769cc3e67b88340b4101690eb283654c761f8 +Ciphertext: a420fde6c359342819ed9c07853c594c0098fd2a3c8da24713dbd12261b528e43af7dd52ddf1a1b553d08c20b0ab399c38a067fb115368c990d9e839735c8427aa885eacb5c2900d1d04afdd3d35793f11c78dd826c5d09351f39823a13976eaa5a49b0bdb054043 +Test: Resync +Key: 115aaaa3a3827fb05175412dc6478747d7c128ce2637b6afdfe3213f7b0b6991 +IV: f8cbe32bdb4c8eac3a571f186ef683b9eb902302ff7ac746 +Plaintext: b09472fbdaa3e4bdb7b04c8819fb3257f764154d09cea22e9a67b40f7e601a97c469811773d2733eb4ab0da6249f237d4c063012fd06714a726b24a512daa7e287d39818980a6720abc45f10aab7d71da318244507b5a9d0aeae76ec5efd3b5ce167c38196744d13b07a14805ee49dc4421e0c59d559e8518a9911682ce1d2b307ccba48dd98c003103421ae6253c6a2476dda5d11cb3d5e7d6dc2c02499d5731095ee89f77c7d4ef27231fd6e9e854d1ed84b0b47bc4794e68e055e1d83d75ab527a53ebefa4d363f952562ac1aa47635296d55e2d5d1b8e214c95445bd586c7f82b31839ff78a60f0063 +Ciphertext: 50c5e2584d473a696c797ff1668137e331bcd9a1ecd5c146422a9140de87c10996d407c5eb8335b5bdb7a9b1613ccc198d5157c6f89d409e1ce7958605d68d442e1b10179c13e12ec33f98d676ae4be95ac7a82786402b1491918a6526e9676037d04fa7aebfd9afd39f6d10dc663877ebbb67aa82c6089529218db9622bd0af7e722e72265e25524d827da8eea6d7e0daf94c516ba24ecca2d820959c0dc939252158903d97139f6fcd81752deb3e9108fc62178bf54797c428e0887d1849fb5004c3b76f0d466afffd47f5066d6dfcbe4782319738e90fa19de6b99861bfc9e8112df4573bb38b1b9e35 +Test: Encrypt +IV: 50c5e2584d473a696c797ff1668137e331bcd9a1ecd5c146 +Ciphertext: 280303c6467f6badc300961c549c33f249c6d2df0596a459383b4c995b296854dea2072d04e46cd47c3380c4be6f6456e8759a5ab2025bd20ae6d116b0bba77b4f03aaa118c73e50f48755a89474c4380e8bbecffc4d6c84514711094ef67c2ed8b81a07c2afa41a19709e69d0bea22067eb3ce3618d80066f9c9f333eea1a624cc4d4dbfb0134004d1d6d295751c7a134cfd29cc85045734e2a4400c261cca16bca4c7e4622837eeed6ddc64c0999347248081aedd3f4d911ad5c92aa491b05510adcb0bcd7c0711a964f176775f11d8b00d9e4264afbb4d6b6a81760d964ca495485895ebba1dd1d2bf9 +Test: Resync +Key: da4147528d2e7862009aa772051e60e309721eeef4b4bcd7f98ae8d0561960b3 +IV: b625057bd07c1385fc08bdc14d735e5832dce5aa0045d9e4 +Plaintext: 6db3a848beb8a6e9670ed91427364c9b042d000a14eb2ac4c6097625e20b2e8eb367c156f927262d2251974d5953f17d00b4ed6b4d93513a19ee6b4f1a159bec8ff94151a7bdd6074d12d343fd852fa69a26302a11caf57417e950723c5a5e795de4cb6523fede7af6b6cb68f41931a1eebea6079e8018fe4116e7b03df7 +Ciphertext: 399c5bf3b894e3dcb5881fdcd927d8cf4ececa5140b2425df5cb2cb993b6901f736e94fb847de41b7c32ae990510402ce5e99a34b5acbb3b5aefbe55be4707025ffcfd6605b6ebeffca3c1ed3c42cba900eb5f14c195e5c574eae67e7355b780403e44ebc91f81fb04f95759f78999fe619d5b8f9fb2185c0e14cadfa8dd +Test: Encrypt +IV: 399c5bf3b894e3dcb5881fdcd927d8cf4ececa5140b2425d +Ciphertext: ebb1d4ebb394e185fddd72fad5efa8434465a9ce758fbdae25cdc6b1278b2e137f5afa706c5a8e95684fcf6645c6c2f67f698621c7d6c7f1899be12e2f6c9e480315c12f02405b8bcf45f4a715eeb72f12e0fef15740734747764e698ee88d05ab30028c9ee237a48b50c8fc453b7d370daad88e57a572a9cb8091526861 +Test: Resync +Key: d61f8e75dc9295dc029292764f3ed08dfb6fd725cae4b0e47aceecaefcf654d8 +IV: a6046a92ad15e9f9d8027ff39bfbf534d46fec35bc9cd94f +Plaintext: c11f014781804645ca22ca213a5558a038090341f3f70aa1df0bf135fb8d0184d77783b519c9c2b2b0b748880a85bab986de7a37a4a11bcbb5c0c87676d7808fd41abbfd0d7a11a7c545405a4ae42f60baa22ccee6de0272e79610c7b885b70ba9bf027657abae393cc8f56735faab9f6fbe36e7a4d99ce15cdac24223880bfb5865ac7acf01ea833098fb148406e6 +Ciphertext: f3b2a1188c33e96124f383b8b75dcacbf782f728eaf436db05551ae2be1a77f09c9ea009d8651329d0a812580d1e11d0f64c44e245bf30dd9c8033b72d0e5049131063c5fc2a3f219e6c1bd993c8961cc174eebb655574dd45b73d0d804f5190f92e385dfd7c2a4ff430ed6dabd41db040aca8ece7f11de796478026f48337f763cf69aef12609384f0ae72ee38c8c +Test: Encrypt +IV: f3b2a1188c33e96124f383b8b75dcacbf782f728eaf436db +Ciphertext: a9b213db6c8e161687e1b63f32a806f15aa8b3ee60cd37d7d437f90b446c3361d37893b702dfe774e5e5ce486399cd408fbf6ca1005768bf7825130c061e43f6077080438514f1a8ecdc6ff7cc264122b1a55c849c76328e833667326f23670590b77f2bfb9a666bcc4c44c16efd6c506c37ec62de8e5365ee894670ac4264b807a8455d8df05ba45af51ff1fee343 +Test: Resync +Key: 0f2850f98634181f49e53bf49d2f822fbf75e5f77c6cd7487541c514a4101ce7 +IV: d6defb4e74c327d89123bdc1d1c6d2fce6b745079bc2c9ef +Plaintext: a064bd9bdab0ee26530c2d26be556cd67295180bca445dfc87954bc51b28a21b606a229cf5a41fa104c51c3f32003a65064ff73e66691e4d2b1a22d236232be18677d54aba7ad49edcc9284897a7f88945513460166e5dfd7650959c05328abc0a7e95c352dbc227ca17 +Ciphertext: 51de41664070aec657612a57641c0c83ae14f5b3b25b25d916e0cdfae1c1bd21f7b47d9ab02b6841e115394cad58a568c1d7c2559a1d3fcd9cb4b25529d26e475ae313e6487538d16376a6b24e5cf27d2dbf4c83bd18996594f60549f34a8683b04d05198893a816adbb +Test: Encrypt +IV: 51de41664070aec657612a57641c0c83ae14f5b3b25b25d9 +Ciphertext: b5f57b5f00d2bf5f48828a4e793997e6d12b0f14953f5b1634cba91867776f75d2d2d247799a46080372046518416c60a07a65b2aa1318238597c320360a279e7633045bc43cf41bf9d366eafc7613b090a41fd8db3f684afc03d96c82a40b46e2994438febf268020c4 +Test: Resync +Key: 5cf680e8a11eb005d03fdc3d4ec0e129e6aceb47262dee6c452a5b8b0ef1b450 +IV: 6a6920ddba39b5a2640976ca10c97bf308a8cdd70ea98260 +Plaintext: 1f322b31f5f577a596b0fbe567864c7ce2973b41f924205defe08e2866b7fb5c1814d664d33957614e91668bb15d9848ffb93dc08c1f74c5f5e1f88148d1a1a7ad47395b75834de4988adfbf7e58a38157544c2be5b913152c1d00 +Ciphertext: 64d6c9ca4db201d95afc0dce28f6e47d51c2856ccbbc8f4c2e2bd2d834aca165dedd117b0be9a7dcd21eb22b508f4ecd0236075b064a0ced23e324b18b2bf2cda1c4416f78c740e51ce687cd37842be368fc4e6ba7cb312d89ea7a +Test: Encrypt +IV: 64d6c9ca4db201d95afc0dce28f6e47d51c2856ccbbc8f4c +Ciphertext: 9f4090fc504efc0f6bb5f76ac9881e1379da9f700737d86e9636714debc5c4eb3276fcff90bf71c32a71e06c199b3431475ab77410e83a7eba158723efb383a5437731a136758aaf7d39f0def719b0dd46798d9d53a30cd1b91eb3 +Test: Resync +Key: 9d27327495159927d0dd93e258908590343a57f6583e0d8aca07070ce41fd37a +IV: a01d1d7d1d43de5fcd60277f84dd8b93d08d480a77961f71 +Plaintext: e2ce8d1f9ee9329c3599e1880b9e6cb75d52e86f48ca89b829d4d7ca16d3e1b496b8b46097501793cdf6764ffd44b44013c7aadbf0ccfa4eab012529373a9022480f58877332b81f3c703ca80a77f429d944d5a877d89c6f64214c9ea6d3a098d9057d519354cfbb71a4bcddaee65de22e4d782ef0065952b891c9494d8a509e86d08ca31594015d3c31931d417cd048e59945d42ab74983434d14ef4e078f30ec2fe9ceb7e247d557b1d2593ab35896082c1c218dd73a868bc5cae74862b898395681234b20fa1ae9cab6a49b94bcc38a3a4a91cefc7745d094d9d8cab730cda4079705e4afd0f5e401 +Ciphertext: 94e0d546dbdcedd76e26629484ffd9b67b9c15f61b07df7ef0efce41270bdc9039ffad321c5b2d2847f6f4d5d105676fde08b8c47df248850dee1272d51feb42d503e58d67b61fff0a20abd999a5ad5942676aca3f31ce08614106fb692ae230c2a74339eb38c074bb59cf5ab42fcc428a0d629c12fbc3d845e84ed76c3f774e92c1109be12f00aa8ebd2a137a914e655081e6e60176cc98e849165d9d93235c605c8562f51bb407aeb8f330692d6245297817eebd32fa2ee96520b560e37019e9aadaea40f25ac4c5446fe93c5b39fc90152f088a5a936ba4efb10db7f246143f2cd151b1f1155e05a8 +Test: Encrypt +IV: 94e0d546dbdcedd76e26629484ffd9b67b9c15f61b07df7e +Ciphertext: 33203e910f56c5e1a63f3a801fdd772dfd1c3b0f3e012772bf0796337d95f4562c349f65557e76dc0aadb982d1aa3a3a865db36418bd1efcae36095fdb3ad68e1df72622d45d5336224caeb237adf9c19b02e23a1b9d4b32a5b6f39595a93d495a74cceeb4254e0b75f54277b80b153f62c8b5bdccae8d3ce24d8ee258f6d4ec6d631f6d1c8e8daa049d33076bea38acc5fda4a8822a16a693c936b340eb7951cd1ab0f7f58206252b0ebe46c77214dc86db136f8e170fc402f31e1c7ef9bc409b19260e4164c145aca28846ead4dc91783bcb1bd914a23d7bdf83745cb74c7ba66eca45457c53f42280 +Test: Resync +Key: b1a6c9bc9870d808a81612d0f4b335cbfd8b305150a6140627df06d9f8b24c0e +IV: 7313e9e505147d4a4c2023259ba01197169bac01af0d5bb0 +Plaintext: 479d7baf87a385c781f0dee6e51ee4f94eb2ee3e93bdbb3f402b0252496225d4118511ff893f4ddebcd31149920e259006cc7353ec5a95da4bc61ee6863282edc341afe9541d44958c2855b6714625ed2fde62db387e114fe837bbecee398351d187e0c93e0a0618f9d923504dd662c11e43af794e7ac7c99816c180ccfe1779bd2dd476ed68eb1736f421922fdc6696 +Ciphertext: 30a86c8b6a55670856e6d1b31d59602e05819022f12df1c67294fa138d65d5fd9f5e9192ad09604e08005537832d07ad5f4743bdbf137b7e18b8811066c7e411291fffc6e6ab55744789a225f15086173495279a4c628ffe4b1f8bb4d886bf74ada7d783b143edda1675ca9493ac1da04ae62584ce41c8a2c4f9fae79d94363bcf79c343e51ce5694c639bdbd8405781 +Test: Encrypt +IV: 30a86c8b6a55670856e6d1b31d59602e05819022f12df1c6 +Ciphertext: 33c313c0da87030169b7da6963644cdd257891b14fc1e4387d35faadc39279cca215e7079ec4272bc259e6499b0cb6dd52c6dff5965c7ddc9e951ac5c0056b4065a6f8eb5cc8e5373633a4aa3aa1736a67be11ef63c3418b1fe57730d6cce0f40e5bf02e61f6aae1404a813fd2a2a870960833be71dc73bff4a98718d64cb146a2ca5d41fcba85a56fa3d0413d0a807b +Test: Resync +Key: 4f9f97fd4ba7db6365f5fec9fde4e752c8bbde48a7ea986b878302e4cc8af9d5 +IV: 05788b5db4e3711eca900a2bfe6f78de44e98a70362504d7 +Plaintext: eb50b1e352f3fae6921fa7884c99365411928a2ffa33e3106768a773246c31cb0bca5cc166819b3b05819017f06c8b8932607db6d66d58d6a2f7356e4666ff7bec3a2223c12777fa54d9ed1dc139d9512c52e1e53762badc7e6f8da576afd940fb4a29d89e76fcdc93e515d69a6ca9efe5d053b7600b458b6719852ec4ad3c59d0b0a69971ac6ae53118c186f2d1a57e350ac3c8ad7d4e087c8f32816462f0506122fc01caa8c93aeebf0edf0c8e1cb726bfc861 +Ciphertext: c63f829e84c1c9709c49780a445bbf0dd441acc5304e0433ce0cd70af3fe98d36bd9e6fab17e6e8b50fda157e3ce9d2a928e8c234dd1700999047db4a28ea40a9657172a471f962d872a1d3342c12965aa1f1484e760979181ec8fde5472f509f76748fb4557b9b73fd517f70b20795caa1cd19e4dd5ac65e8f4cdb65a4ad60e0dd64407dc5232a5a893ace71acb35700fe059bb641497a2db63caf083942b7fe530092e90014bc5b6f889710ba3fc50d086fc32 +Test: Encrypt +IV: c63f829e84c1c9709c49780a445bbf0dd441acc5304e0433 +Ciphertext: 625aa1ac285ed59cb4b17da0ddb32a772eaf95181d0587fa92be22d1f5b65e403de9c0caa3301aa569ef9396c4cd06cffb602d5b5e6d2238712e74de51b0620733e1ba802038de3735b2a08951cbf17759f90cb0c4c4eb6a1acf147b54b7ac7372bafa4377fe7510d06a9c4ed6f972a669e270610a7084b61d4b52d2931803b805440b3d5e333ccdb0f3e7c0d013f068b2b402680a83210d71051da3529299343813150fb0f26ec053a8dac9993568e9b0c703ed +Test: Resync +Key: eee68b65fafe9a5bf2f9f92512a716e5af3740efea15e596f4ea0b5aef23550a +IV: 4d312f84330a107250b68c0b1df417ef713615b704d99b71 +Plaintext: 95ccd08ed2ab0fb87f55786f1f10d33c7713bef4435c3699b13982235ed040c9d9cb1b1f335cac0faf8654812f6874408bf20b129558a2c342c07c7f42a30700b374d18b91d881fc0f153f4ec1a55633a92d637212a11d122a9a1eb085439ea1226ea7124e8bd1c644a1996fa6369dedcacd5c766d7dc9a8c8682c5729ccf4d59433ba8e1569fe826089995414afd576ffb9686a30725fb9e5d7 +Ciphertext: 6c832a8147658a1741af29b0f558fa3773c81429f91a5cef270f7154988f97d4b28549604909f726a8a6e89d625089ea387b2725861963480424d9835d7e2fea93a5bd3bf86c7827fb22e7a68efea1a05c45f9606d4ab7add687d9418ba60517cecb3503287fbc5b2c9f0f9b5faa991337b394dfac7514dc38ffe019a1e7c74e5ad23f4e3bddb74ffc8a81f521d0b6044f98238f7c2a38ab14c0 +Test: Encrypt +IV: 6c832a8147658a1741af29b0f558fa3773c81429f91a5cef +Ciphertext: 7e1ef21dad49405e2fc86c50bf045eb14c65e58acb64e210af9ad8ebb5679021721312b96514d8681fa9d52c01c83f7d871401ec345a334648e0fc2ca294ced407ff98f1d1bc4afd83bb325072a5367d9a014092bc99699713bf84587fe2ee998bf8df35aacf61a96be157bddfd52e5b5a1d4a2e3bb109502e608f286aa8f0d5f67b4072ad9b60971ee8cf9fe966015260e61802f19f4bc8a29c +Test: Resync +Key: 188fbb5bea95b5101e056b93d8890c68e1328966089ebf424defa1bcb96e88ff +IV: b51304a0194bbb2490fced46fd0f39c3e87ea5196ca67ce3 +Plaintext: cd78c7c8f308addbd9acb6352d1b5b8a6ddee8a6f51401556e612d4c18960d152e6973381f45b19693e8ab6643424f01e9ab27de29f4ea16465d95674f7c939b +Ciphertext: 81a468948c618db0de96ad5cdd8b577c8253df097128cea4ffc7044f3eefa1b486b9159545fe135ea8a862fefa015f663febbd9b9527cba516551949013e9601 +Test: Encrypt +IV: 81a468948c618db0de96ad5cdd8b577c8253df097128cea4 +Ciphertext: 0510193beecfda67addf420e9c52130dbc8883cbe27d3e013207dc0ef3ff4e0b92e9ea2a2b644ffbab55c942acd63ddb7f1cff8d51d27b0a7d2853584dcc0bd5 +Test: Resync +Key: 2fb88c256a737eacf97ce4e1d13f1e20e8b2426f19076d7901bf6696f38a81b4 +IV: 12a82872b47b2c5b73cbb38904a08d283701eba289c057b0 +Plaintext: 3caae8a0c99f38cb7b2e45ea91dd5dc1331f0efff9f69a5dab0164693e986ba0da48a84321f618cc7e4b4e4d66acd8a71b69e23dbfbc6bca0c4ae279f3583b08705100adb7a4aecc0d72955a7305f4e7e2765b0a1bebea9d7e044e360d44b402f01357dc9a3e83fb46b48a683c1ad450a255bf45fe801db33414d985fd3a337c857d370ddd05c3313ae2eee0c8cb1d12a2fb650ea6e4851f2ca27badaf36dede18a9f8a62a502f6c2ff94d591cc27438e7215ce6e6abf76c22190b7201763cbc8d3a2be1f366f69eca6e5386883f56bd1c +Ciphertext: d446cbadf5afb1f21d7748a5973e8650d1dbdceaf5b837cdecf972bd091734a71ee1692fca675f4972d1e8db716873a03f9a5516f409982316cdc9f66ca0a8018dd055af0086397a86cf7574253d53fabd3aeefdc54dc2eae48b5b61a31dfb8db6531d2185034b81f745a3b88fa11453df073343de8bbd35a45f9cdff45b52e5352081f1f1a003a58200a4aefe27c87e930b77b8dc5b0882dc848437892e1902d126813e31ee27526d947bad5e8f9cf16a302da1a8f3883e3c9b257091e708ad58f4e716bb49e660cbf1f6fa709d64857f +Test: Encrypt +IV: d446cbadf5afb1f21d7748a5973e8650d1dbdceaf5b837cd +Ciphertext: 4125c6831bd2d39c1b1a2e12c505ca077fede7c553d486ae9a87ca3232d27974fb35c9a18a6315e5feafbffa943e52e9c46aa0eff6bce2f2dbf703c641ac570a92551f8a6e9aee14e8bc433b36e06bbefb0a292279f688e5d06dcdf317eded20f9dab8fab19298b146e1555b772d9f9c95e920356282ae691436a8505051190bd840b234fde486726dabec5e0755f4335b8ff4e30c30bd4f473a6af3fa3e7542f2b720784da760753938a682e86cf7ee18c5b5f7f515ff0380134d375e434934508f7cdd7602ffe2039a376d443c048103 +Test: Resync +Key: 7066fe1125429407b653fd090262bed2a3f7f3be2fa8f160f3344f327b1e53da +IV: beec3787c335739fa5d7ad15b85b7e3e7c9438367434872a +Plaintext: 9dad7f5ca1 +Ciphertext: 014a1f27cc +Test: Encrypt +IV: 014a1f27ccd2d39c1b1a2e12c505ca077fede7c553d486ae +Ciphertext: 20539f2d9f +Test: Resync +Key: 3154d3f5bb56b00b34a255425057e99ed9effd1cb0168d16157fd769ddc665ba +IV: f7f9f18f9648f6dc06ac643ea77f1493a9fea3390a98bb0c +Plaintext: 80a488703cf316be904ac8394437ea02ae2c027b7880ebec58416429ea060db543839d781d82a0fa209077e4b1 +Ciphertext: a07abc8ef3641cf33179296ca401bb291a9547d3e6d1b0886ac31d26d2f3281a6a568cc042593132a3cc1082be +Test: Encrypt +IV: a07abc8ef3641cf33179296ca401bb291a9547d3e6d1b088 +Ciphertext: 27ff7646fa8c6b98b1a732841e1596caba7b87eb40508ef0f8ef390aa5e36c0296ba84b686701d5e3d34b16508 +Test: Resync +Key: 81426f03ae1578d8ec1407827db18640d9d90d2bb773971f4ef14f859bc19e06 +IV: 479961f75954ed4f8024108cdb149ca3fd53e6a239a01e86 +Plaintext: 9cd08cf58e13e94e02c9a40269875392251353223f5329412e2a5e34328ea18c414d4c730b4e1c0bc140953f4ecf4ffc8aec963e59305d4d +Ciphertext: db3ea5b5fdc9671ec56b3f1cecbb2a552b0ea4ce9be508863f3dfb3238d4fb91b896727357fe454a08114200ea7226787fd2ab154d53eac8 +Test: Encrypt +IV: db3ea5b5fdc9671ec56b3f1cecbb2a552b0ea4ce9be50886 +Ciphertext: a887b52b3e97e6c899e1d68e57f283633ec9392438d17fb645702ae3b0ae0aad3a7c6eff0baff9f5357328307f628f470891884c264973fd +Test: Resync +Key: b3c260036b79cd3345e04cbee474dfea3a7c773db2ccb29d4c36a1b8c8b252e7 +IV: 1277840fe82046c024e6f4f53b4ff761c7c9bd1fea6c855a +Plaintext: 6a6dac1bc93b9b5c0dde0d1e6a534914dc2a6d51e6f8af3e9d42b88bedc2173782a2314b33f795cc2e4536829871d77186168f5461d18130581664586256 +Ciphertext: ff5e71022c6522998a2d10843fda170796a70d186e5fca2afcf529c6d075c5212c793fb322c1675d0bd3cc6b18f2715678812e81a8727a2d6ac1158eacf6 +Test: Encrypt +IV: ff5e71022c6522998a2d10843fda170796a70d186e5fca2a +Ciphertext: 7e8b5b4d250c13e38b5dcaa5532295e649ab3669fa594cf30eb81a54b25b3fed4f35be97afe4a2a37b7404acb41ad31d737fa9f272e1c57b3754830b4823 +Test: Resync +Key: 14fabd52e0fff9dae88d54815d82a56c4d4a660db5f214288cec1982e56fae81 +IV: 55b8328a312dff104c7f0720af0b7624f9281731b9f5f4b6 +Plaintext: 71bfc290baeeb0380732aa4312982c0dd0cc06cf2ee53adb0ae61c64228b80c073e7687ad3d3f888151b4066f415b62cf851d2987a3c816255ac40b62f453f350da8c4e1ec6dd0985e721b45a063381e997f629a7fbcd44fead19adc289f58f104fd37ec93a35305ba6fa44844d22e80a853e6db1d466ba2ad09ee2d30b3f47dd01b4d7b5d498cffd934cd3e005dc91e9e951951d5b937b319de0a7ba23c7918b1d74d3551b6500d39e6d626fa9cac8ec4e744713a93d5edc8413e2fba1d3b9b0f70509e38a66a2a2d70c510b57e15ac0c4b2aa7c5d6eb088fcdf6cbfef2c6dad19d7f17437cd261636c6d +Ciphertext: 7fc8bc27994031b3c35632590a15607ccaf1be15c542eea5b71ea1f7fa3abee79cb1281a00adb05e6fee4e65e8cba616a5789629d8fc617fae9bde9d92f6c8779374b1cd32a8e9277d0cb052c7658b3ab24ee1e55e5dd88a76266e9fb5661f576000968a9af71a3edb59ef3974e76aceb41c3de2fcb204a0022f302316eb01a0a8d74378599a7f72987e9abbd6f1a8af152ee89455840584010da73b01bbd7b01093a8c38049dc7a5ee0ee80daa98de46803ed75d0a97083ca328e7642a07e1c037346a280a856a64bba53b050272b7ba9742ef62aa89e34500f0efd7bce800bcac91981556a878d102ceb +Test: Encrypt +IV: 7fc8bc27994031b3c35632590a15607ccaf1be15c542eea5 +Ciphertext: bfd5908a43916afa5e2709b2e43ac62f406a4e677b855d70b216ae92cd444fa47f5568558c3cedece54e8b436e904e927175b455d96672a8cbdb4316b9e48a704216e30e9955ae7107f9f7770768bfd3ce71416bd337710bdf4e8789c8537a37f7c995c616a437ee406ca20c8f333a7c2f84ef87dac8c32f5b9678e344645bd356dbff32089fd195d982d3bb94b06b5b232580b492cb754659df62c9b5186b26bc2485409ff95bdc0c1c4c80bfaae878abebd373b159507b5894c5a9f8402447559b5aa7c3b491b97adf202847d0f74605a2502b193b6440a6b1765d538e38a2206630dfda4123fbbe4da6 +Test: Resync +Key: 75fe951556aae3d6ee93670241b7adac6907fd9285dbdf165834fa0cbf741b00 +IV: fff3e1ebb2e48520be552d2f0b617291c42a946f38804243 +Plaintext: 2b56b7dfaf5969d84a88aaa10dd12682f15d8a9a942deb6eba04a9a7ff38f2d0a947b414cbf7f1fca82d74b4ef98880368ba58ab7da98e8d6a6c46cc47cf0536961920e46095627b73737ea19e393c2f19d1f252ddd74b8fe050d95d21004b8997678eb565db0e369cb8bd326942e634a20845c61265da8a21448357f3eb +Ciphertext: 4b3bbef56b4400b130f8df0ab25bb28ece9160c430417060e48e691e6cc4ba119b0c34f5e76d4f1b7963785b4c6a9fb0b42c9f4eed92f8d0989710456c7f8d228fb26359f6e2549439ff5610dacaeb1df4f43a39cb3802ab1c87ce73f731ab1127ea9c2e82fb372be407a8c2b1af40398b33582e842ef0862f120a96c75b +Test: Encrypt +IV: 4b3bbef56b4400b130f8df0ab25bb28ece9160c430417060 +Ciphertext: 76c77925fc94b86624decfd2014fa505a6343054ae55c5be6d12c43018944b5d1c2aa08b9c11ae00d0c8779e70f220ffa59847969e54228d89b4351471fcdb9f0f76f18fcb896983d09dc5e8d9ee666f5abcb4d9e7bebbba824092c65646c3bee46d07609057e44b36dedfc02ce576506aa1274d550afc57d973fbd60294 +Test: Resync +Key: ea7bcb7f8712f9aa149a311d906dbcba443319f68a441a68a263c7bd0fe10fbc +IV: 620e57a9ce4b3d438c968e603f3c1518ab70be5b7bbecc62 +Plaintext: e40ef8606c72444fd3feeb1873f7ccdd3900760af66c269ad1ee6bf1e4546b1a556d4a90f6397527b270021c226dad5353a142c22963bb818548c3ed504965b2e6eb9744a15ca3c00fef2835d34592b90cc4bef8be904987dfc35e92f835ba15f054ceb760ad903d56c65854fd21f6a03ce9f8f16c04ef7ad9507b5cfa4b373eb544f2bc61bc16e371db087fb7bb749463c16f75 +Ciphertext: a31ae696ac9d66241bf9c826a381c4610de7f6416b153d7f8cc17484f1eeb63b2bc25d7c9b8a486e3e8eed6d34b4604ab5dbca373a80c29d50f416bb4ffb8485bfc6f7b61328f7c708360cf93370b7224b7cba075becafeb5cb62938b396dcc789900d8cb8315ceb460a753f20baabb4c6f61526a012e305c28bcb59fed20565ad1afce39f98b354b67a33daa8425479a07c0dd0 +Test: Encrypt +IV: a31ae696ac9d66241bf9c826a381c4610de7f6416b153d7f +Ciphertext: be217c97aca7ee0c1be18f1d93ccdd0f26d751bbbc36ca29f12bbf4afe83bbf7a749d325aad3b6af4913dbb83b09ade5ec79d88b755f7b2ba63df6ec458627c83e28e4742bd49396f19463bd597902de42ac46ba675d2f0c9db8d39dcc56a5e9233264be90cfed284302b965ab0f0748dcadcd02354c1f81d640a359b8ee5aa58a1908de1356031432b6f12e22ae9ee9f847f0a0 +Test: Resync +Key: 017f97c643425ef0ce5c0a6a0c6dd67aa6181e6aed360adcb103bba88773e1b1 +IV: 8189c8cd17a945196321cb6147cf483d785eacbea352fe3e +Plaintext: 145a3d3ac4c5b57d68d26a1ddabc71289929b6dbf317acbb3d83313c9e4861fa9d9679de974e4f7eea83129cb8f4221df16cdf545e000e087735cb37cb321d097b7b2f4874b74af6a6da9c429b1e62d418066bdff5ea0ed7c3 +Ciphertext: 90551d5f8ebaa8c1aeb52d893ddec3e9cb95f77b8bd5f6d0b3f8a3fae5fd8d9c1e42a96360e8e7e6cc9b7711ee1d61b4d67e6c2d682215c59a72778756dcc3fa93068889219579b2a1ddd85b0e69880913cd2e9be47b93ea70 +Test: Encrypt +IV: 90551d5f8ebaa8c1aeb52d893ddec3e9cb95f77b8bd5f6d0 +Ciphertext: ef58a8589c2996e1fd990d7ec412353edcef7dff079ae0ffbf430f3a479818352647fd8640a518575a3210fa45f7df5bd63532273d54c442ff02918aa79176c137cfea1a6ae167464183ae716a0f6057be891537059ac3322b +Test: Resync +Key: e9a7e6aba47b1d9c1df629c6920ded6894b85d3e7fd211bbcc7a9335e5cbf7bb +IV: af86ca3a196464931fd579bff601c9fe7fcc7a10d7778d22 +Plaintext: ee681bb5ecd15201f433a8f89871109aff85ed5a4a16a7ffe032fff60f1acca78cee6532f7740be05438da05933c8d29fc880533d589f6029291cd0a965113e042b27734968784f871f9e9e6c2a7342bc01fba3ef666aa0e018957169f2213f492acd0d2ab82dec47d8afe7a6bedee72d0c5c7ac0d86d0af5238da822ad4e6346cf2ac76faa64d34051a91659009976d140534a4f2a80f2758a912eed692b62bda4a46649fe58563707478746c77d658f481ebf90c2cd5ff3276fa8dc36739084640e319282d74479084a15838b9822056e900f2050d0f48ed52a3a3ffbdfe3a1831 +Ciphertext: b049fa161f19691f3bfa783327d2663eb8b7f188b301b17336f68630d8e001349f659428fd29359c15e95aa3f5a9f46a92d214e0085ab661b511831d00fb6f496e171b8c139def92be2ad8f6d94c2fde48f9d77ea338b920b2d8d6ad380ce761faf170bbc05128e65149b29d32aeec45e2882362dd2d0e3c7cf9634b9f52c578cb2e1d51b5aad6447f4d1860b1a1f1b7e45bcc002a5f4f03dd7116216414b0be23876b35ffb58f466a4087c992340437e89b12151a7d8f1af04aed585f5feee36f60c1b0e19251c7587e8590e7b6bae774f3ba5f3be2d726c8da4da3824debffedc3 +Test: Encrypt +IV: b049fa161f19691f3bfa783327d2663eb8b7f188b301b173 +Ciphertext: 7cc5bceb953ed1acf44c3a448a15f07c4e4db33f863bbc2368acfe699cd18f0580e3ff8545b946c15dd0f5c15e355fc4a10e340035e91c60b757cb69bbee8d2a22b20066b15929bf3506f2b271326509552b6430f4b82cf9b38ae83124f9b448dbbe049d7b3a98bf25678a72965f9656df149bc068e4cbea8573befef8c70b32d1dae7dc9b74601db95866dc7b5a3b307ac6ab9d09f3c55b6aaeb34c8b0e77c724666a4cea694ee90129568a46bb0f8380d8bac4f6151e84d357f32488ef8d62a08cb02255de04612bec676db471ea2199b9e86fb8ad89b259c0d1ac487cd95a5430 +Test: Resync +Key: af768581d5e401b02de76e6986de0bedbfb7130b9014727194c1d3f02c747fd0 +IV: c4568db83cf9eed0c05629951afa4fe5b72c055d89421efa +Plaintext: b34095f5b7660a03edb3e2277dcd3241270c9a7b890cd682214ff979b725148b1d836346ad84bd776ad748f6fb063c15fb763ca5005e9af95840f2677c1904090a19d83dcbf1011a48c23b620eda573b4a61bb8b86fbb7260090ff6f788a9dc27b5c95c3a3ebff1dc6f72446a23740179bf4dcb0169624d1ce2bf17c79dfaa35c7e12e313488919adf7e56f2d61cad070c164797b9d2dbaf5b954b56fd43e15b61f2cddde618bff31ad545ff163f2482024388ec470329835a8deb0f230760 +Ciphertext: 5b132bc08ec5bb09b5c92587a661c25ec54b8f65a581ab5f788c97c959e39cfb93032c6f63a489deac9eacb0b1a40b14ed152077fdc7b8b6dd5f94501d319d1f5cdfac56dbbedf8a5430843ca36507a363d5694e277ad8c0dcd0c0bd729bbe4b64823acff976f39973ae2d3eaa415f32db86a207f3220054306d99558e27ced2a683699a65d13eb67abb38230137de63c5c758a2149a773d403442cb826d70064c57aa4a778cb3e00a36cc4ebba6ec83dc178a7e4a3fb07c22b77a9c00e889 +Test: Encrypt +IV: 5b132bc08ec5bb09b5c92587a661c25ec54b8f65a581ab5f +Ciphertext: 907a2c78d9e0064b600c1d20985b6268b48cb8e7af87f615f8c298316b186ef64470b1c3c05f46096697d84ac390a3d2e37cb2306b718e7c48fb624bb1c5b3855951444f83e0433e26bbe2e05d8ad375633447a9f1c0856e35c6996c4fe4a477f503a47818ccd364b099b8d640ff2540f892e6a8e915a90b96b3ec13ec18e81a5c5e9f6054e6c90b49892e22ad1f0911a33740fe0719845f5428b0911b220ccec09a73cd8a790afe1ad4b76480c5e7718755fd2c29ea2f5f3cd7608ecb7bbb +Test: Resync +Key: 215f4b041d68a316d29cbea833a9d4170c32c5ea0aa34e90b4381e642f74231b +IV: 0b9e85d8e3d62b0c5b45ef1ead0b180348c0c82b2325beb2 +Plaintext: 68a7cfb070a3ffbb5a1456ff96703d56f84fbf74d92573368def92bde3b49dc9cf8ea87dd8a51d4c12cd9b4e1d20d5939a20b86bdb9fe5c76a10bef983c871c559741ac89155eb6d1a226c2a371c03f3bdf2b4bc +Ciphertext: 68d6236f9df3727c9a457609c0b59e393864855160b1e2074257f72d8b122c99fda40d6092cc96c8134823ab93545a6f8b43e8efca9502b5db2ecb86af5798b45639dc41b34df49782388cad7d1826d9d165b79f +Test: Encrypt +IV: 68d6236f9df3727c9a457609c0b59e393864855160b1e207 +Ciphertext: ab148bbc10bdb9a086c2c94c641225bdd8bca6f04d11a7cc5ba7eb728f1fd84522d3861a648ccae4e03f34162058f560028680d986c4a71e5369a312af02d135684b348b2cf42df1ab7ca841d474b3b51b8b52bf +Test: Resync +Key: 2ecbb5a282ee515b3226952d11d0579607f653a708d18920d18dc5106f76074f +IV: 53f67a3bada58382426b7d2142c327c7a9fa75a8634463c7 +Plaintext: 0878ed1298af132502bb5144066d26042e4a2990 +Ciphertext: f8ef2dc3ffca9dfa4d006bd9d3c00d7517fe0971 +Test: Encrypt +IV: f8ef2dc3ffca9dfa4d006bd9d3c00d7517fe09714d11a7cc +Ciphertext: 488bfbb9058907da6218b81138c26f306b3e214c +Test: Resync +Key: 473ee670e4b93e070c69e4c9f9d1a1808aca67c02dc9b8250034b9a19f0a306f +IV: c7bc3457a0d5b3384ff35ac10c8b09a114b09ad8e3d1ef6b +Plaintext: 09ba3c2aa122ee53878bf46711922fc946d67085ff68c3c5f07da6749194737b715bdfd4d052366fc6761c5aad4931808033b620f7e47d3c6bb65e355d66f4f577ee42a1881a853acfa6e710673b72ba15cc169333aef8fc63635ae5a7af8154d19409f57121d6580d10796585236812bdee04346084c9a831aea5d4be2ea248a90b9d71fb00823c2fdb522ff00e7482bd9d178766ad26807d963002104d3e42d2 +Ciphertext: 12fa7fe0fa0791d6a1ccb22f025563a9f61b1dbaf825bb59ae7523b531da1d720b816f42c12adeebe8171309aa65a5357d46e719e260af1ed2eb2096ab59a00f08671acf0e3a4ca67843641a5d9be4e2c00f8da7d37349f2560dabd133dab9dfe2ff6f3c087099ebcd2c4420b6485a8e810392310a8dfb61eb850ae70680882e98d8c97c1c922e6358c0ff3a6cb6df77f0ff86f4b2697c698c0440305d3ff03c1e +Test: Encrypt +IV: 12fa7fe0fa0791d6a1ccb22f025563a9f61b1dbaf825bb59 +Ciphertext: b069c6b32e99129d65d0e17dc92106edb3949710ea7f84638137073b706d790f4c57db477f4f40161c029f1663ca17fa6ffbe8f6d1e10d94718cc7cb75549307c2e3da305bd33263d7f80d8da26ddeeecb95a241f0d0dd636ca54f7129ee35bd49c707c52aff4a6fb5f520575d693949b8a1ece03cf093663c86b8cf97c89b87fc76cf76d9dce6791c499208fcf7a2b7e868f625a940b5721bee984bf3ba0925cd +Test: Resync +Key: 95d049394412ccaaa002264f391f2448837b9a9eaeeec49ae73f21c3bfb83016 +IV: deb9499a1b4043f0c116133700eae22ea61f45ffad305c03 +Plaintext: fba6e561dbb8d9d3dca1b6073d29103b758c463c5ad756920f66dcfe88fe0e4fc21b6aa382b6b96ef5785d51bf4c6b2375f7ca4494e711a34fef708ec09dd10311d312f7aaef6828f112ffa786263f1f9507ecd5fc3a80bc3fa75c17d272ef1c7cac66097a46df791d0d61a22a68dc4217f7ce54abbf7d4fd3fcedfb4d92c4a87657e15aa3417b62 +Ciphertext: a081927e375175dc84df664d824c351c9417614523e0c30d9fc5b6ab5aadcbd9d3a2fc28cfd7c11a807dfbcfdc7d28a54a5c44e52f6e9806a1c08a5fb06f322d22a91f5aa5097b9cb12ac29d5bdbbf8312fcde98b79c6cae3a26c9828874f9c8e2b072b6c1c70f15a1b6464c722fe183fb1367e03bb3991d8de30396aafe160b4669462ace11bf46 +Test: Encrypt +IV: a081927e375175dc84df664d824c351c9417614523e0c30d +Ciphertext: 2629e5e9e550bcb2d80ad3134a2ceaa80ebc96a68d4cb9b0bfc1e78b8b9b06b6ee34e242a174f65f2c74688b740aa9d52f14e900436c020c10b860f7cc8063dffa9b5baf2202a8ca05a3b52bea40bf7dc3c9444989f33e2ff0cc841742df284ea75c6dcfc9a2eee78dd9ce6b29255979b4abd333ed1ed92d19661850d42ca425a30d3aaf95a201d3 +Test: Resync +Key: 9a1831352b9bd922b41cde1ad94b40b3c2f622ffdd633d03f5638d2ca01b892a +IV: 4539205c887f099743e9ebd3aa4ef88ca7eb0a957a1cf8a2 +Plaintext: b4a37464a37b3691c7fe66a81572f535d780925b3b28dbc85b574edc2b6753278994fbcdac780c6f09e153fcd8a2ffb6e873c440dabcbd081e7bb35098c29dc97248dae7781dbc3b00d7c097c75a2f3cc88bf6dd1989 +Ciphertext: abc902e1dc5c4e5d858597347ebf523cfa233ffa1c38b7d8e8df8cb5dc75f08e74cc7077352efccdd18e39820bf03a39ae1aa56b3f07d92b148b26d6214d710167004b338c1f9868b6932b3d999e60f84ec839dc09cd +Test: Encrypt +IV: abc902e1dc5c4e5d858597347ebf523cfa233ffa1c38b7d8 +Ciphertext: 7b2d46034c39cf770b075dbf8eaaa19492e51e451d1ba97a0f4a71c466dea5dfa1d506ff3c7cb90fe276dfd73a6c0ce88e0df56ec0429872dbcae451dd19d2f3e58ac420e83c97909dce9673e7785cf3a11df9a0b062 +Test: Resync +Key: beed63202b4bb586cadbbb8b6893bc6ca2c07217a3b9275b499245aaace55383 +IV: d22603bfe4fe47187d969fce3aefe24beafb9337ef886980 +Plaintext: 375fe2819168ed3a1bfa7f46e037af06f202f1927b78606a46a35f41e23806817a4151872a5738ba76fc6bc736208124d2da5aaa952276125eb5ee95ab9668a7e773a2c429acf296979436ab21bf8bd77f31ab3023bd7fdbe28b93fe92ddabf0bdb1d990d628bf43942d728cddd330c8b79ab6a270877b789a714095074823637880bb380ad826c3a5ec6fd46c0e2b5887dbcfb101fd84 +Ciphertext: a9b65651c6b7b3a6322c21538d9732f2f31beabe4e94c288aff4cc0bd18dea04f15215343a07e16eda6eb535a04f0fa6100bbafd8fb7e89ed087e662cd5537ed321351d19b56a6dc4a8cf50078f7bc9bb9d2982a0ffc8d24e1814935a9ca38edc6b04105a8ac488437946af107e1bf0838db8ec4066646692fc61b9d94d09a83d63913838c1e88ef6845de6b32e261ae972a6b70e72d6e +Test: Encrypt +IV: a9b65651c6b7b3a6322c21538d9732f2f31beabe4e94c288 +Ciphertext: 685c9adf5239c2f521ac91e3a335267b34ce2aad1760f8771c51ac8c48ae1b93938ae2fa2f988b7c87a43c8cd4a97b5e65c2d11aa878c69349308922bf63dff3a5579d549d22c0028a336aac48bdba88cd9654e37746d2728ddf653c7eed0b0404df6f5a4342d0d7e1df8841da0a249313e105e2863d63fbed1ee621ef5e57f48753dbe3d2fc08d15b5244bdf0369c1741fe92fe3b677e +Test: Resync +Key: 8d4b9a4e7e3107c54a75a7c74b93ddf9c44adeffb07a503a05d6a5f287244808 +IV: 7abba4d58cf460f394f80bc9a080a355961c4a2511f50947 +Plaintext: ed3eccc8be0e5ae6d90eed3b15357050171716c7ae56bc9ef7224db5740257361b83aec0d8c7dc7a9e1df44e0f3fd1b8275bb6c5d6fb8d172df4918f39bab0323a5fa7c4a98aef3a482394882daf5403767f639c0d651f01b9b294d511876c4c3c471f7b684900c54cbbc1143d8aa690d7ab98a41fd9236c31692b7d2406beab5202e1b617ee43a6b9c8324404c4862e5fc0301ba8ac7d7b65df1eb36bf038c85e51a03f1b38a6fa74b0163657eebe640343b83a94ef09308ea3f98cc30ad9 +Ciphertext: 5cf10e20d44ba83ba4b201c7176846976b1a10a98d37f006a9b1ba01b4c81db6e97514d0dad76855d95483f3765b26ecb5f8403f8bd65a79cdc220bbc39a35538dfc757431c20b22cc825633a9af1be926f1072b38d2e89dcc903f2d257592ca97520c869abd4f2ec41b10adf0a2f7c56296975869dbc3a2e1465d32b7781991747ad3d141fb0c343419b76c5ce4facfc257f666c1dd020bdc8f189aea79d5c77e63f42da60510ba86ec2b1c934b90d77793b5951faf1c94b5e3ce38d869b0 +Test: Encrypt +IV: 5cf10e20d44ba83ba4b201c7176846976b1a10a98d37f006 +Ciphertext: e23e817a9c4c2740922734bbe3cc5fad938020ed34c0fe401d4da9cee010d4d1056b71d28856ea327d495c643d819d2d4ba6d97820909a7ac222b892aac4ab130610fbe29311f28432303af69d3dbd3a696fb35582aef9b7040a7e85f6c48d31a3d0c3f1cddb5251bc01a5ce0ace8c95882228ddf7c57aaf1890d70b899631a09af5f4130b436a69ab8623e0260cadebad595ba3d27da5df9e62544876d4daa3fe7af8ba8bdbb7246af0289903d69928c43a1c720b948e2d5a0e8b0d062fca +Test: Resync +Key: 39efc9016ceab203c0e172a335d7dc2916ff577f168904648dce170abf5d21ba +IV: e4e0a36fd930f726ff81007cc919ba0da8aacb5abab72394 +Plaintext: c1229356fb463b251270dae5bfe6772135af17b0624454edee3490ae95616c8b4efaab8a6b6f2a83b083d4ef19a86950c6b570d9000e94255087ecaeb56fead57eb8c51ef71fc802f9fd9d14f462fb5568d4206815e7f3473442b5f9ccc730fbf86a45a008f2b784d14791dcda532578e3ba17a0a3733bd518e15d2a65eb6c79a2130d988db4ee07f1f557a9a08aaa77f28744cf928829c940f70ec541a07b2646f4860fbda22f95cd20018deb68159aec40a889e534dd071a076b46d29a3445c8cebdf2ae0ea6ca7ecdfd203e5941581db5a84e66828f2c3e1b +Ciphertext: c885db1a0c9211392f2cf3cd655170409d53fa559acc66faf0f75766b4501ce80b739f51b985ab10ebcaae7adc2b58c1315ded28b77a2c1c1e3bb65b7d9866827a8b4a39f316222bf0522f3c4cd1ab367c6135cd1b104fcaf4cc746e12d3c72a5cf781d487e1a297d83822c6b68c1b5a9a9505a9b64963d64b2d50ef487057aec172cd070533c400fe0d83f79f4affb1be18fd9429d5dda1ed35c71d674fe98788e3b488bb3b5a781fb6689f8732aa8e4674a5df2643b03a332fdc3d5e10bee7014753a745b4e7bd2b579b8885955d8141fca840204da3eeceef +Test: Encrypt +IV: c885db1a0c9211392f2cf3cd655170409d53fa559acc66fa +Ciphertext: a65f1a87049667811331f8305128b6c06fc3becedae1661dcbac3a627d27cf80429687178b1ff1577cc99bee4b311c480dc3053a74fa523660e9af670d852a032e69b65bb2af61af8a2db4d3aad0a4b27ee74bc2203ac502d188975463f050e3369259d676881b1b318a1cd26094923d2c6fb15c0b522952c176c3cbc01252a4d64f875aea09a9295957be06209ae896410f5665422df60dc4038dc9ad1a45f16350bb433054b9a14061b5eed9cde905ea59f15bd1f58811dd4df49531138431e9d57a8a9adbd4d4fa472077ccf40a2a61affb82242db08f3d27 +Test: Resync +Key: 3070f0db09c523507d36404dac79038a393e9f0e3cf5f870b16d2a06da68dcd3 +IV: 4afe87bf79eb938d786ba54c26fd6d7e62261eeae8b62202 +Plaintext: f4ea120b47d15466ade07df0f2ff508759d9cb1035ceeab43920e9094fa50b868673b07173557d4b994b1e9d35078c1c7369df6b6adb2ec0e6bfd280fea8ac31db44beb0c2a4ddc6198957bd0592e3e587d304863b893ff8eee0efc70ced5d712651c3e9dd1a0de0480fd8cccbae4c50dccbacb83dcdc3e2cef7dbc645f0af468163fb0e015ef48ad74694dfbce2db8430a6e91645fd16adbb72e21a0fbaedf5ecff829cea9cbc22f82902748aa52da5ce903d9f2bde77efef5fa3970c720e89f25dd05157247bf0de2d2129c3f856238d4fad +Ciphertext: 46f396f0d2d54189968bf56b5b2f35588c3ad851e00fac6507598f3ea0193a586c00b18677811cc305b0261d9aebbb9c0485a5800c940aa4f09c4fbdede12553824c429c7954e0b8dad889203d292517b98a64e8d7a37c1364eb0934751323d9b9f8498f50d729e977fb742880222f22ac5d7bfebe6905a4c344d82027398a70c334635792deb0f20b83861b05e731f5627aee17df20413c79957556e66a970085e9ad40a73d9a964381584976c6f111619a916fbb5f5d305df862d5a56bac9ff9b436f31c85f34ff890b5ad3299eda2b8642d +Test: Encrypt +IV: 46f396f0d2d54189968bf56b5b2f35588c3ad851e00fac65 +Ciphertext: 358a8f5e5c6fe93c3d6d7d2f90f5973ba2c0cf7c4579c92a52d1ce6203ddd90188d3e36ff7cbe94e7adb4ec7596e89edcf3a94dba1fe64eeb24e8bec5fed2ef6faa4f0d16faf5853e8f69ee0ca0e048658507bd155bfa13d487c3b994f3a1b8871996eedc2d899d9d79ecd8ff968000b863337dc04d9ad8d05696659f8a1cae880e471621ea13ec42d163eecfdf9cd07bf0b10d6f4634ff16d26c700c88831efc82ac0abd0269b93e302422cfc2dc4088e28bc22ed6c06c9b51774bf3aa4088a6a18fa3d3608f9927837efc3382b25a7ab873c +Test: Resync diff --git a/src-cryptopp/TestVectors/seal.txt b/src-cryptopp/TestVectors/seal.txt new file mode 100644 index 0000000..a1ca35f --- /dev/null +++ b/src-cryptopp/TestVectors/seal.txt @@ -0,0 +1,137 @@ +AlgorithmType: SymmetricCipher +Name: SEAL-3.0-BE +Source: generated by Crypto++ 5.2 +Comment: verified against partial ciphertext from 1997 SEAL paper by Rogaway and Coppersmith +Key: 67452301efcdab8998badcfe10325476c3d2e1f0 +IV: 013577af +Plaintext: r1024 00000000 +Ciphertext: \ +37a005959b84c49ca4be1e050673530f5fb097fdf6a13fbd6c2cdecd81fdee7c\ +2abdc3e764209aff00a12283ef675085c1634b53289059e6a7ab5ed9480c01eb\ +4c64569a8dce2a23feed0ef58f6f5ac3f74145127dbcaec4bcb6b1a459bdc287\ +58ba0523f721c3e154433dc7353f02ef487b07ad309ef5e44e6cc19026f5fd57\ +07cc32ec12b9c01fe0c58beb2fe73ea79e24093f05911663a76b21beab18cede\ +17275c54d18fcd3e4cf32279347b22f8751119fb56d92f55d511e4ecc1334085\ +e74934455a2daec3f1821c54b4cb809053b8d837de4186600afedf8bd72dd56e\ +223745c19f76edba01e9b5346666d01f677fbd68fa5010fd7db8b06829a90da0\ +e81b84756a70946a6c05e16d225a2e11af586bb1c5b1d21f5349f8e5e3ee41f4\ +232d554954d1bc86064754b86c1dc92d7a9de30086d8eb4a7c86db9c380f13b9\ +52e11c5b89f1be0a6b52c6e7a053da7359c5fd7f50c70232d86aff08c5ff1746\ +d3bd074d79ad6fc657e0cbbe5d02c4fce55d3c31fef4642ed738f751430f2f1c\ +f6e453ef6edeb9540cec52c697d4864201e141e06c3ddf5aaa64a1a984247e96\ +d2cf1e7fb2bc239919369f4a0bf9d111d0d8be64afae86214d5f62e64f25e8f1\ +3e12680ec170ad6234cbbda938df53cc17a12afea1eb4005122a65cb42bedb76\ +edf029db910fc81b81f3dd28341fed4064ce37648548e5852d4aebb7923016f9\ +afcb07ae7bc11800e217a0062f0b53ffa8d471aa78ca6a13b7f5647189106773\ +0a311d6fe4ff57f05f9a58aa742696b6cbb3ec539da0c2aadd6a60d2a33c26d5\ +8a343448ed912aafb98568c6ae1cb1efaeafd81a6e3e7c450f8e2be4c6cc18f9\ +5e8a1c6c59190a2798e912a614c1e7d0f7e74b1baf8e5682f5442f998b24fa86\ +d1e5f673002e2c92db8ebf7abb1c9d267a9763f4bd54f7bbf07c4466dac0bf3f\ +faf5666a43a52f0812e76df5f9d4da8ed1bc6d4ab29b34718facb4bebc11e907\ +fe9b0e3937de7769fc5b0cc52b3e50d57e02b9b4022949aaf3698bc58f696073\ +ec972a425caee9700864d3d166130ee09d51320b9d51bc9b4aa575c789786242\ +0698d9e1f6426fd141a32c9f55c24e5149e274983035ac1c44833b0179aed63e\ +a2b2b61afa54700155e55c7c343412584f7b0fe73d63c5ad88718dde3000ac1d\ +b4050ae2610032e6b389eec48952a1a2ed0016e525ccd9616706caba89ed07d5\ +4f15ecfaabbc91b7c82c5904bc0f83d44888997faa11fe8fa7333cb8c5b16e31\ +52233c80fbc9f71d9ee8fefa50d67a7e45b93d3469ba4078bb1ed5859e7a8e62\ +b26bacf538507fa6bd43e18d67d7aaf27baaa68d233ca392ce33e257d5ddf3fa\ +ef6a951430d686f65ee9afaf6aee0677b41098922b41fba202ef05a27d614612\ +5daebeb147d617c8df42dba0b91dfbf8ab5805ee9877e495881035fbb7342c24\ +e24f3b85c88671184152ab0d395a9a81afab3bf93bea49cb23ee6bd1c9fb84e6\ +4ecd462f60119ceeae7f1d2150bd36fe7ef2782b0fd12b55df119a517103d489\ +0a739b715d3d33e2ae9fe659df4bc0136c0b243538eaa8f9b813043d66ae15c8\ +261c94c0072afc802668b3151ad1c0ab0f034eb3e8f2fce0c9fbc8f68404fb93\ +a1cd11f4eb9a5eeb9117462ea602ae41fbfe0074323e56e15deb04d41f3510cd\ +1df417f759f4c2bee72bab88833e7d3d9837801f16901ee12581588fa7037f74\ +073b2166405d79098098fb196cc4b1733e45796fa7fc977cbd23853e5943b2ad\ +e154856565a455189198f6ba50b9cc6fda0c309a413ccc746bc8261fd6b060f0\ +5cfcc82894125b3f1e0b0c47257fd838cf295aa13102724163a9fc2598fe8572\ +d0bf844518dccc1ee16eb8e4c9935b78fb969b7c3104091079079a7688f1e833\ +0335f63eabfdd3224a506bae4ea3022a8a4959f4fa410ad7111488a39e3c1cd7\ +a28ce83255de2c4477fe62f660af3b7ba049240aa5212e4e9fffd8b66fd51b17\ +0bdf6c7e7214361a7efdceae86878f49716c0859ce2e24979bae82d98025720e\ +06d7904c9646f1b1058b1a7c93ee4fd728c4f19051adf2ca30f4d54cf65be23a\ +7198e5be5765c018bbc1d2344fa8d1aa908cb8f789ea793c6c60d9a7ba9eebcf\ +7aee50a54810cbe3b632144956a157c220e33a232c169cc9ae64d6aa3560a185\ +fc2d94f15b389eebad8d07662c2be6d6349ece8ef88aea27d430ec9512ff1bc0\ +c5560862fa4a833af750d968e9fb545e3879571ec021735761da937e294820c6\ +585ae00e8023f48a4e1f392217df763a09e540ca615188345512179f8889902f\ +38c626ea3a333fc367818b058dbb8d6aa474ff3438b2de2b32822fdb93f77618\ +83b89223e0e616c885fa3414905d098d82a5359f629ed11589974393cfaf4695\ +da7ee36346d088a6ea6ef21ad6245da8de9956fcefc930c4e2759b596e3f98d9\ +2483b2bd82b74269caae2014f796ffcfe5db58759f0cd4e527b16f989d9cbab7\ +f20282ee2e666cc19ad64aa7a36193ff248002c762280a98f3ad2bf07b32f26b\ +eff5a5586d967d844aba69f7297bb1e28075273f39aa6e7c6c7308728da8ad30\ +31a2d20ebe99940732f93d0440b6e3b481774b69eb76179496350983031c2611\ +a27d885d91ac37debc02512edd06e1d10061325c5e04269c0c14942d10f03f83\ +06ef173d645478d79c74990a82df4b13f2754f273227f96988c25bedaf392534\ +69d73d642305f8058ce4713f65a36b822cd98da3fd805c4408d18dde4ee8e794\ +72e38f8683edbbfdce8d085e005407666eefba25d8c3368c6cb656a699b30736\ +31b8024eb6859019feb76bdb5a0d7f17c92a37fe6bcd14630c1a62bdde1e41b5\ +e9ab7306183a16c31554821ad44229ebce2e552f9a09fd1607dec8c92a1e893a\ +b80c331cdc7860093503cedfd44b3403b3501415916303baef0c68d12efa7c54\ +a11af3a7df5d23df98cfba907dafad0a8989c710d4602fc75f663fb16039d94e\ +f860f358bbf05ac9c34865141030513c4cda32e9b777d9fd9e4ebdc1ad0b24f6\ +799f815e29b8e2259f94b0215b94b349938556736d3ed578cdcea9024d71f174\ +376f05b3c203cc56476dd92d07ecf7e283cc181225a2b690eeaf3cffd35bbda9\ +c4ed0456661e2e39f6be537d2446f65cae13a6dea668b04f8f223601629cd3d1\ +1b75180dfea19435bae5e0622c5005371d4198b8dc1e0c40adbbe08d3651d345\ +4d68507f7f0b56d4bf2a328bb68854064699d0a38d7468ef64ddb4139644fabb\ +d21ad79b5f28a5612e445dc5673b2038e3f7dcf17a12ab32da214fb28500ea79\ +00491554da45661a03e2a878d1006d4fba8e22a7e5dded9b02fb8b5e6d166aad\ +43f8ef3eec4a7050a0304d46cc0be3ec97f0bdd137eea7c001bd8519101ff3af\ +76d1d7710c22c5b0a69c10df3493283254f5afa2ce4b3959d3be512e6ddb78da\ +30cc0a338d675c8fc3fcbbd313b696c660a85fa13ec9fa13ac8e8dbce8335575\ +608d5962ecb516b9ac186206e1ffb971924e9301e6fc220d0769ea1cd954e2fd\ +dc591ea026e369509d427ad062b81ca5e8873432a0d7a031b7f26702840fbb5e\ +5e9e6c8794dbec841822ca92aea2a22709182a3cda136b7b3569d85be6213817\ +06b2852b7de3e20907739958726334ad0c2c3b7327d0060b3f6cd319bf6666e0\ +9de3ee588abb948a6df37d5ac2b18c82d63ca0a0dcc6f1c1e2ae609999f60738\ +714df767fbf14b12b7a002ce0dad86f8adf777ff7ccc9b08180faa0d96b44023\ +3ca5398525eaaa9afba9e0ea4f2cfbf5a3e868f99ddc1a86ee36baf2ab56f9b0\ +b1ff1ff591033e579847267b9557217e0991d2c90e61f7e58321d9bdaba96c9c\ +63e9d3924f0a8c7ac6d4fc94d74d7bc1a96aafad76fca0fa4017d76f00f5cb5e\ +96058fafb57caf07cbcf665fea359cfa2cd4084796e3ea2ccf30bbe6e8f7efea\ +60190fcf2700d1d27b80ff53d8071aeee1ed8708617c92d821f83c9a7ea90c72\ +f19a58e9179cbed5f4f86a80c28e0fbc3fac50d5eea3117df747ab076044f1ef\ +61c7bb95ab31ca2f4f6e61d19e906230694158df40a72fb748dd79d0fd0617b7\ +24b23c6d0569d170731ee07dfd637820f10fbe860a179f2a24775b1f27a2e528\ +a5808d13cc3f995d2cf0c4a832915e19bd6293bfae8eeabcf85de223c4dea84f\ +0d095815cd34ab885d6c50816bf8fd07d4e58aa8c8fbf34344fc3279c1efa142\ +68471ff263f121bc501439c9fe1ae45c946b348a00535ae451d17f3edcecea67\ +5a7dde387813246bb8312147163f813159413fd550e00204c441b0eaf4d12c79\ +520a3d3bd75b00e20a5284457fc3999ac7ce1f1202e5bd651047c74eac7ff92d\ +7f214d6583304f6dda309a01230198b1e656c9707f2f27663c1855771af7f449\ +0e3f3f8da53f0492654a3c40d15620e2fd2a68658ecaa8fb5601775a393878a3\ +110d75e6b968db8eb81c2ecba5852b2eaf7f9b8967b60f92ee4af138a5e777b7\ +aad802e39d7237a17b4a79d9a467a4be1be5121de907400ee5586f0f94bed1db\ +35dcd7995ec93b49b0f6dc7a1e3e4cc0ad1945e60dbe0d24948eb94ddbc45e20\ +fe0bea593df4e6d38647fb623df65f6fbd1e36f318decf77824abd6bdf95eb8f\ +a5f29b650f36b77a305bf9c15b034a7ce1f482ccba079171a6476863a70bf49f\ +cc488177e461837c64d5f5419ae0a344010df2d6edb170b1461ef27024199b15\ +44144dc327eb225f1ee99ab4f07bf2f934042f2df86252c4058212b2e5cf35dd\ +14df206c1dba5445d41f211911e1053813a09e7fea3d5de5cac92acfe36b3ef6\ +8d4767c52a31c8ccba0eaa85874892d813ae601db1ffd5cd42ec1e98534056e2\ +753b5fa30f993016b787de9620a1242986370e005ff4495315c2b1aedb59a32e\ +47be953ea41f15fbe7a115d10328f67e59c538948ceef3f4a338a030ad198b2f\ +c89f067b336f28085a4ca061a38ae6190de48981de1c942ea83a9143b1faf94c\ +2f462a9de5d14b915bfc52e916d16f11cf59a28a3d933fedb48ac06b7cdd29a0\ +720ed851863bafe7a149f403881afe46b940ca37c29b7e49a730b28404179449\ +73274553b70fb11da65acc1c5420677288c624e67542f230da340d1e9b8dc5a1\ +90b69bf5e67e77929250a802f07cdf0716db567209774367aae32e0c1e90928f\ +61c43eaa372f1e9ec70aa0dd506734d23825213edaf184a24a1bb128811db664\ +783cb27cac1edd074d79d1259f84da9e0e5c75923a4dbfaa8a6283dd2279ba69\ +bcd1d78970d7a54a0d31c44071cbf05527010e2ff808cadefd74d906a8ad8c32\ +a01845d3ad78bc6ed96a688dfff171d80d931409d94c83da2bc54ad9790e9a6b\ +a5093384850090a961572f6fdb929a1a6baa98c015e95b0a6da10de04b8471c1\ +aeac19b6c887c1c81dad641d55ab1a29250d14dc41a042f83eb8a6bddcb662a9\ +3e00cf6adaed95cb52b36692f43a8e9b85ba7723d70e5ada851a16fe102ee1c6\ +d3bf8be1634ade9fa6b44626c734788b3aed0c287ab7e80ae5fc1451ddb037c0\ +f729309209226022f13e6f8aa592445db33bb1f29101e0df15db15df0bab6411\ +5bc12f0bbf430551473dbd274db2eea9905eab75f290ecbd903b675f1ad9ac2f\ +2196d00139e7671ac8b95a8cc8e244511d481863b509e5bb7573b6ce49cf0fc9\ +53de75523ca31a64012d11bb7f60f1f67b199a4f2013f6ea3808e2639eb5f263\ +1c19568bcf36071235de8ae7b2d5815e2e0a2e81098a6b4d6179e29ed0a92bdf\ +585a2905f0496ba58eb3d740efa54b664d1a6134fed9fede636504aa691e08e4 +Test: Encrypt diff --git a/src-cryptopp/TestVectors/seed.txt b/src-cryptopp/TestVectors/seed.txt new file mode 100644 index 0000000..a08a102 --- /dev/null +++ b/src-cryptopp/TestVectors/seed.txt @@ -0,0 +1,19 @@ +AlgorithmType: SymmetricCipher +Name: SEED/ECB +Source: RFC 4269 +Key: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +Plaintext: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F +Ciphertext: 5E BA C6 E0 05 4E 16 68 19 AF F1 CC 6D 34 6C DB +Test: Encrypt +Key: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F +Plaintext: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +Ciphertext: C1 1F 22 F2 01 40 50 50 84 48 35 97 E4 37 0F 43 +Test: Encrypt +Key: 47 06 48 08 51 E6 1B E8 5D 74 BF B3 FD 95 61 85 +Plaintext: 83 A2 F8 A2 88 64 1F B9 A4 E9 A5 CC 2F 13 1C 7D +Ciphertext: EE 54 D1 3E BC AE 70 6D 22 6B C3 14 2C D4 0D 4A +Test: Encrypt +Key: 28 DB C3 BC 49 FF D8 7D CF A5 09 B1 1D 42 2B E7 +Plaintext: B4 1E 6B E2 EB A8 4A 14 8E 2E ED 84 59 3C 5E C7 +Ciphertext: 9B 9B 7B FC D1 81 3C B9 5D 0B 36 18 F4 0F 51 22 +Test: Encrypt diff --git a/src-cryptopp/TestVectors/sha.txt b/src-cryptopp/TestVectors/sha.txt new file mode 100644 index 0000000..7980daa --- /dev/null +++ b/src-cryptopp/TestVectors/sha.txt @@ -0,0 +1,59 @@ +AlgorithmType: MessageDigest +Name: SHA-1 +Message: "abc" +Digest: A9993E364706816ABA3E25717850C26C9CD0D89D +Test: Verify +Message: "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +Digest: 84983E441C3BD26EBAAE4AA1F95129E5E54670F1 +Test: Verify +Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +Digest: 34AA973CD4C4DAA4F61EEB2BDBAD27316534016F +Test: Verify + +AlgorithmType: MessageDigest +Name: SHA-224 +Message: "abc" +Digest: 23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7 +Test: Verify +Message: "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +Digest: 75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525 +Test: Verify +Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +Digest: 20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67 +Test: Verify + +AlgorithmType: MessageDigest +Name: SHA-256 +Message: "abc" +Digest: ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad +Test: Verify +Message: "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +Digest: 248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1 +Test: Verify +Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +Digest: cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0 +Test: Verify + +AlgorithmType: MessageDigest +Name: SHA-384 +Message: "abc" +Digest: cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7 +Test: Verify +Message: "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" +Digest: 09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039 +Test: Verify +Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +Digest: 9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985 +Test: Verify + +AlgorithmType: MessageDigest +Name: SHA-512 +Message: "abc" +Digest: ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f +Test: Verify +Message: "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" +Digest: 8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909 +Test: Verify +Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +Digest: e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b +Test: Verify diff --git a/src-cryptopp/TestVectors/shacal2.txt b/src-cryptopp/TestVectors/shacal2.txt new file mode 100644 index 0000000..19a3d86 --- /dev/null +++ b/src-cryptopp/TestVectors/shacal2.txt @@ -0,0 +1,5123 @@ +AlgorithmType: SymmetricCipher +Name: SHACAL-2/ECB +Source: NESSIE submission +Comment: Set 1, vector 0 +Key: 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 361AB6322FA9E7A7BB23818D839E01BDDAFDF47305426EDD297AEDB9F6202BAE +Test: Encrypt +Comment: Set 1, vector 1 +Key: 40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: F3BAF53E5301E08813F8BE6F651BB19E9722151FF15063BA42A6FEF7CF3BF3D7 +Test: Encrypt +Comment: Set 1, vector 2 +Key: 20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E485005217441B60EE5B48EE8AF924B268B6B952D7F593E6102AC83D7DA72838 +Test: Encrypt +Comment: Set 1, vector 3 +Key: 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: AE70E355CB7E26FF12421F46CDAD5CB98367FE0E86CC234EDF97481765CD1AD9 +Test: Encrypt +Comment: Set 1, vector 4 +Key: 08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 00CECD0B01311F881018E7A20BCE169766C089D91FF161346C4E1BD122EA199F +Test: Encrypt +Comment: Set 1, vector 5 +Key: 04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 47A879CB6785AD37119C450CD50E9A36FE318FA8E7B6C6E0FA963430122F33CD +Test: Encrypt +Comment: Set 1, vector 6 +Key: 02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: CF3D53B9F9F7CA2C66738A4C09CEA9212C056F525BDC26F263FBA1B482EDF503 +Test: Encrypt +Comment: Set 1, vector 7 +Key: 01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A274D404E83E82817389A2CB7B528C792A0E80DE879A5A67DE633B0B7DD57B7B +Test: Encrypt +Comment: Set 1, vector 8 +Key: 00800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 09B3AB9332301D4E3C239D192A4221AFD43F6829A705D396FA96BDE1E716BC38 +Test: Encrypt +Comment: Set 1, vector 9 +Key: 00400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: D3B9AB867A6868C4400D200979055C8F9E3A6BFB40D1F9E376B9EC89223D7050 +Test: Encrypt +Comment: Set 1, vector 10 +Key: 00200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 4F27041481DCF574586CD6D5B72F2E806B0DBC351FEEA624112897A8A64CDBA9 +Test: Encrypt +Comment: Set 1, vector 11 +Key: 00100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 77CEC8EA64BB7FAE966D030FE4CF318C318DBEBAEB896F31FAA3C9CBA0AE125D +Test: Encrypt +Comment: Set 1, vector 12 +Key: 00080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E6F96E0217B8BDC6BBF30CB91C05325F493EB076E505FC6469AAA2BBB3A8A60B +Test: Encrypt +Comment: Set 1, vector 13 +Key: 00040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: ED949C1CFC555EC7192464AE86EC0334AD1198C2DBA36DB38CDF7160C950D474 +Test: Encrypt +Comment: Set 1, vector 14 +Key: 00020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 41EB01CC3875F31A6C8D7008C958BBB164813C59435B01879199979FC4762B26 +Test: Encrypt +Comment: Set 1, vector 15 +Key: 00010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: CCE7C4F96A665DDD23F39A78A3C7898E5F945FE908F1707DBED08BA6BCA3A58E +Test: Encrypt +Comment: Set 1, vector 16 +Key: 00008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 5FDBD5741AB5BC53E8C75F4497E37D5BE92B89D2424A11BBF189449AE005E2E8 +Test: Encrypt +Comment: Set 1, vector 17 +Key: 00004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E6C00B21A5B89F4FE9251E53E7AFE30D6C8721678BF842575EEE185E85632778 +Test: Encrypt +Comment: Set 1, vector 18 +Key: 00002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: FC19871F6E933014D92721D77BDF4E0EF528A325D5DC979536D6C46457CA066F +Test: Encrypt +Comment: Set 1, vector 19 +Key: 00001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A195202A93364212B989EB2C667EE05881657AD95FB6B3EE62DD21EB73347E56 +Test: Encrypt +Comment: Set 1, vector 20 +Key: 00000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A25B4FB9B4F8418514A1A04078DFBDF73B83B936A887AD6B1B672F1C2AF128CF +Test: Encrypt +Comment: Set 1, vector 21 +Key: 00000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: ACB2AB0F22068D36C160D668ED300DCF32C66FB8447594878DE1B1A83B414E13 +Test: Encrypt +Comment: Set 1, vector 22 +Key: 00000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A5AD217E39C9B40A921B4E52B1B47649C72631E7A99FE4897A92CD1A65BF8BFF +Test: Encrypt +Comment: Set 1, vector 23 +Key: 00000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 1185C198ABA5AD97F5DF7850284CD5E34BBE5E0EEC3CE4ACC4FC0A3CE3FA3BEE +Test: Encrypt +Comment: Set 1, vector 24 +Key: 00000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7AC85AA2C5A9A219B8E437C65913738628EE442F56BD57292C8A1B36026B6664 +Test: Encrypt +Comment: Set 1, vector 25 +Key: 00000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 6140F926FA90F091603D23A4876A3A5598890CB1F2FDE64E43C50630BE4101D2 +Test: Encrypt +Comment: Set 1, vector 26 +Key: 00000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 365135682290CB40D83228B3F26FD63266EED9C72DAC991510FEFA9B56466E8F +Test: Encrypt +Comment: Set 1, vector 27 +Key: 00000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 928EED2E262D9E398ADA06151ADFB35F34018114E97414C75E390C8EDA8D2440 +Test: Encrypt +Comment: Set 1, vector 28 +Key: 00000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E362280E66204F47E8FB782D18522AA3E1D527C15EBA88E76DB5AF44E156BB45 +Test: Encrypt +Comment: Set 1, vector 29 +Key: 00000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 807E3938AF9C9F0233FDA70B0E26028B390101F238ECFBD53EAE8E2D86552DBF +Test: Encrypt +Comment: Set 1, vector 30 +Key: 00000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E7D3FA388C4E07ADD32E188BD09264A2BD19F0F7EC5712AC05C47B49C7FD6651 +Test: Encrypt +Comment: Set 1, vector 31 +Key: 00000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 891CFD4A18F35239FD4463DE95FE9CAF4569AC82766E457315C123FB5FE6A397 +Test: Encrypt +Comment: Set 1, vector 32 +Key: 00000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 5C8E12B2572ED949494B324383806FD61B7CF0479DEB5D62028E83B7091BB039 +Test: Encrypt +Comment: Set 1, vector 33 +Key: 00000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 6F071D68C107B19B9949A6B7AF2C79EDC40FBA9BD07674AB3B1DB8CDE0A9637D +Test: Encrypt +Comment: Set 1, vector 34 +Key: 00000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: FD720D4ECFB7B68BA48C52E2F69FE268773D73B41723AA51127895B14C516F34 +Test: Encrypt +Comment: Set 1, vector 35 +Key: 00000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 0D3D7DEB1F8742BB22C4A3FB88C7C07CDCC8165ECF624C95FD8838D90D465B0D +Test: Encrypt +Comment: Set 1, vector 36 +Key: 00000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 06A524998D1FEA6AF6E4015B9A16B7A447F50AE0A8902E6E3308D3B47E98C4F1 +Test: Encrypt +Comment: Set 1, vector 37 +Key: 00000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 9FBDF43AB1294164BC968E113673BB11195AE39267BF2537F0E429E3C10B5D2F +Test: Encrypt +Comment: Set 1, vector 38 +Key: 00000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 81C4C7F2144555C888D876787EE62BC03EBB57093DB3DDE806918707684C8C52 +Test: Encrypt +Comment: Set 1, vector 39 +Key: 00000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: F62E7B237C98C5727D4F267AE17932AAC4DAEF0CAF4C02176B4CBB902ED164D1 +Test: Encrypt +Comment: Set 1, vector 40 +Key: 00000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 99CAD86B7E78D9B2ED9DA56F27C9AECB49CBFFC287930CEBC1BF06EA94541E9B +Test: Encrypt +Comment: Set 1, vector 41 +Key: 00000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: ED1F4429D5C36B2C16D598A2CE52D9C84E9DE7CD0B4899E47ADCB999CAEDB0CA +Test: Encrypt +Comment: Set 1, vector 42 +Key: 00000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3FEF41084D9CFF6111C40F9656C46D3892323465630B0C1D082255222847D9D0 +Test: Encrypt +Comment: Set 1, vector 43 +Key: 00000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: AB7D2B41135ED54EC7AB11C67D20BC35F0C8652D209D675AAB3A33FA264C9380 +Test: Encrypt +Comment: Set 1, vector 44 +Key: 00000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 1208F63F213F1A55127900FFBFEB0569B693376D9310C9A9E36EA1DE22CB5A59 +Test: Encrypt +Comment: Set 1, vector 45 +Key: 00000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 10C38678BC2465923063E41B4339D96F3DC5A64CA77A9C9C132D75BC4EC517F1 +Test: Encrypt +Comment: Set 1, vector 46 +Key: 00000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 5342519F1181700EDC380133226AE072971AC1AC6DF72440FD817C9ACB862E68 +Test: Encrypt +Comment: Set 1, vector 47 +Key: 00000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 09D02729C71C6E5E852272B853E87C1BAB5E522875E5D8063501ECE10315B4D6 +Test: Encrypt +Comment: Set 1, vector 48 +Key: 00000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 33D7D4F58BDD14244621A960A076573892ABDDBEF36109289A3E8A4EC536E95F +Test: Encrypt +Comment: Set 1, vector 49 +Key: 00000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 81A4590D64E2140414B913AC73BECEC19CAC798C313196007E39EF4F75C7DDB5 +Test: Encrypt +Comment: Set 1, vector 50 +Key: 00000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 942ED16EC4A9D72D74ABFB7E79CDE840997DD2AD83C9DDFAD02528A9A7E0AAC3 +Test: Encrypt +Comment: Set 1, vector 51 +Key: 00000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 8376BF03EAE71EF035E18903AC0CC2CCC93610C48050DB096BE758743234CD63 +Test: Encrypt +Comment: Set 1, vector 52 +Key: 00000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: B5613234B5F9D1201A9A581D59BD744B8E59728E5E330B74CBF03B9E81C950E0 +Test: Encrypt +Comment: Set 1, vector 53 +Key: 00000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 4750E864B881A2764EC508D0DD4AF06B7B1B123FDCCCA141A74DEAF28070B408 +Test: Encrypt +Comment: Set 1, vector 54 +Key: 00000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: B3F29EE6BDF09A16C4EA8C1539CD033B17706436FC40DEBD95DA70BF05BF1856 +Test: Encrypt +Comment: Set 1, vector 55 +Key: 00000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3A91B7730E3FE044B75E75B9BB09BC1550AD5AC9F495AFFB524FAD90A51112D5 +Test: Encrypt +Comment: Set 1, vector 56 +Key: 00000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: D262DF12E3D8DA99A9F7F011D607905DCBE9AB03C317E81E4BCD076F3C55EBB2 +Test: Encrypt +Comment: Set 1, vector 57 +Key: 00000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 827BD4A79FD82594F645A02F9546906ADCBFF47E2F2D0D0DAF89A200389A5E00 +Test: Encrypt +Comment: Set 1, vector 58 +Key: 00000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E83B866B294780E36058CBCB62BC3C509604F9EB9A44F1CFAFD50F248359A106 +Test: Encrypt +Comment: Set 1, vector 59 +Key: 00000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 8695B4BC5DC6528183B94D5257DC668DCAA0E5A855B76555B65FCCF941A8CCAC +Test: Encrypt +Comment: Set 1, vector 60 +Key: 00000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3B5D549F736D15CFD0F39A42CB1ACBEA370ADAA9EBC7C012AF2E30463DF98E03 +Test: Encrypt +Comment: Set 1, vector 61 +Key: 00000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 1C29F7919784BDF30E566B75DBA4C911FC48C1CD7F845406B86DA540B71C572E +Test: Encrypt +Comment: Set 1, vector 62 +Key: 00000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: D530E5B30338589A6AE67E0C1E2C57AF02CCEFF84705BC4AAD0D93375E7F2DAB +Test: Encrypt +Comment: Set 1, vector 63 +Key: 00000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: AE92CD3DA2022DC9C91E381DA62D8FFA646FD02A1A5A3249AEAD35B729C48329 +Test: Encrypt +Comment: Set 1, vector 64 +Key: 00000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 111318C5C6DAE45DF4FAFF404AE2140300DBBF9361E926900F3ED7F731385A52 +Test: Encrypt +Comment: Set 1, vector 65 +Key: 00000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: AA0DAA9A0025B5B3243367C7FC22F56F65A52B3CEEA060825C1FD2813953BEF8 +Test: Encrypt +Comment: Set 1, vector 66 +Key: 00000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 11EA951B966D0B3DF0D6AA00059281E6944CBB9921F84209265938CCE91F4910 +Test: Encrypt +Comment: Set 1, vector 67 +Key: 00000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: DFDE0D41A657B700DADED5F9CB341481A0183AC1BB51291E8719F77251B478F6 +Test: Encrypt +Comment: Set 1, vector 68 +Key: 00000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A8A42F8E3C2BD71D415EF9FBDBB9DA86B32CFC24EBDADC656B7BFF17FC8BE365 +Test: Encrypt +Comment: Set 1, vector 69 +Key: 00000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 1755CB48D8057669C488DF3A2296651F3FB64AA173DC6FCBD2C1113A084679C1 +Test: Encrypt +Comment: Set 1, vector 70 +Key: 00000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: CEFD04E10B318145993C0AF4B4A64F623BCE0E04CE04E6D3DDE14EC6DFC0CDEE +Test: Encrypt +Comment: Set 1, vector 71 +Key: 00000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: D9C83924493AE365C6369317A4393F904D530C1D30B2FD1A2E4126D0A532A743 +Test: Encrypt +Comment: Set 1, vector 72 +Key: 00000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 9B8FC0A924382EBD28AA3F6871B17E1BA9C94418FC3533B446C2DE8C188EABB6 +Test: Encrypt +Comment: Set 1, vector 73 +Key: 00000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: F91346BFBC0E05A4076B8CD5640E9DD278D4A7755A6D870565AC2A7E60A7F5AE +Test: Encrypt +Comment: Set 1, vector 74 +Key: 00000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 58D205808D4A580FF8111B9EF06BEE613D51E3B2E026B296F5E9F8520C7319FE +Test: Encrypt +Comment: Set 1, vector 75 +Key: 00000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 15D0C54FC35621B206A4A50EC3DADCEDFE4CCA17C9C5396A18901099A3389086 +Test: Encrypt +Comment: Set 1, vector 76 +Key: 00000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 48DE43EC8F644BCCFF61A52D93BEDEEBA38C71C196203A4A5AD9145416EFF31E +Test: Encrypt +Comment: Set 1, vector 77 +Key: 00000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 253057DA247A8D7A1B4A23E87B67D49669ADE1FE5EF32E08058F2DA6E82D1C25 +Test: Encrypt +Comment: Set 1, vector 78 +Key: 00000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 6494B08A0B0CE628E34EC6D7EFBC436687D242131974789ECF20911C0CF16839 +Test: Encrypt +Comment: Set 1, vector 79 +Key: 00000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 5088AC91D68173FE292A64D04D9A8083535649D44D7F00F23F389810F5F2528E +Test: Encrypt +Comment: Set 1, vector 80 +Key: 00000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: FFF5D0D5296B0C3553DD43C429F51AF844EB6100E373A6A7A16B79A73392AC58 +Test: Encrypt +Comment: Set 1, vector 81 +Key: 00000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 4A805BF70CBBAC2FACF405789FE96C4EF097D36F6982B843246C353E77539863 +Test: Encrypt +Comment: Set 1, vector 82 +Key: 00000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 5F5F6828D3D2FDF24B4AC2F1F4080F40E9564CD8F9BAFC34E5567F96E2F057BA +Test: Encrypt +Comment: Set 1, vector 83 +Key: 00000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 5BFAD855773EF036BAE365C18B6C5784E8BD4673514B0499E7ACFA38F7832927 +Test: Encrypt +Comment: Set 1, vector 84 +Key: 00000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: B38604950FA73165F940D4DB527D09CD0B233276CD3808B5CADCCB9FA859AEEB +Test: Encrypt +Comment: Set 1, vector 85 +Key: 00000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: B96570996489A74726A70C02CD55FB9D4C3ADE0B69FAE7C37899E3D560A5132F +Test: Encrypt +Comment: Set 1, vector 86 +Key: 00000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 0B8612F83912A9EF1082E9D08C772738908BCCD20DE47D64ACA1500633163479 +Test: Encrypt +Comment: Set 1, vector 87 +Key: 00000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: CCC75B4A84D08B14495AA8349B0AF79480FF6D0695561710AA16739A54504E58 +Test: Encrypt +Comment: Set 1, vector 88 +Key: 00000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: BC3F95A0CB0DCAEDB78E3D6E855267E34F3168C436774E28035D144406E803DA +Test: Encrypt +Comment: Set 1, vector 89 +Key: 00000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: BD0A34B0509EFA39D9D091577FC4296F563AF5F3AF9E030FCC3661C0BD82738E +Test: Encrypt +Comment: Set 1, vector 90 +Key: 00000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: EC82DA0C15A50EB98E97532C509DBAC9C392DB79ADDC139F9ADC6091708CD726 +Test: Encrypt +Comment: Set 1, vector 91 +Key: 00000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7F164D165F7585E8306E38D44211325D0C6C177C523F13F69DB39DFEDF5BFD3F +Test: Encrypt +Comment: Set 1, vector 92 +Key: 00000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 73F36AF678E74D413BE851E77F5E55DE1DD92D5237DBAE75E3AB6364D1F181DF +Test: Encrypt +Comment: Set 1, vector 93 +Key: 00000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: BE25140C4E7804B22390822501718BE09E7F494594EBD2BCB35A36AC2F0CA095 +Test: Encrypt +Comment: Set 1, vector 94 +Key: 00000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 33171A271100D5CC5CF651ABF60977CD15B718863213DC243CAFA6CA86041094 +Test: Encrypt +Comment: Set 1, vector 95 +Key: 00000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 323FF7A80198298E438C833032CE609D4E6C5C107C9069E8B216080DE5C0880D +Test: Encrypt +Comment: Set 1, vector 96 +Key: 00000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: D8FB3E266B96E48524159A3BE04CC85B3DB70F2FE649A01259E4FCCBCD3E7BAF +Test: Encrypt +Comment: Set 1, vector 97 +Key: 00000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 88B2171E37F3E861B6A69397BCC46044EABBC424E3359D11C96A62CB33F6C56C +Test: Encrypt +Comment: Set 1, vector 98 +Key: 00000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 96168ED95200986AFF506D3C2F043DFE03356345C52AD205BDC91423C6079824 +Test: Encrypt +Comment: Set 1, vector 99 +Key: 00000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 4FDE2AD110847B5F4F2BD20CE5047913B12A682D119D9A8C8395B9958771FC22 +Test: Encrypt +Comment: Set 1, vector 100 +Key: 00000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: F703282E54592A5617E10618027BB67F639E43A90767150D8B7F5E83054B3CBD +Test: Encrypt +Comment: Set 1, vector 101 +Key: 00000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 6673138D1A64DD26CDD2F62CAB0BAB2318DE17507BAA307A189EC4997F9C3F89 +Test: Encrypt +Comment: Set 1, vector 102 +Key: 00000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 328B2F4069F398422D78E359F19938B8BFBC9E073C2162A0829265CFD48B89CA +Test: Encrypt +Comment: Set 1, vector 103 +Key: 00000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 02B14A28344C4164DDF0EDB594D581AE847FC0090EE6B933B8B8B91EAE90F5B3 +Test: Encrypt +Comment: Set 1, vector 104 +Key: 00000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 506221E93DBCBA6787757CCBBB0D5CDE9D06CFE3A23A8942A13C5B3849B2D2B9 +Test: Encrypt +Comment: Set 1, vector 105 +Key: 00000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 53A01AD91AE1C7F0DCBE19CF701A895E03FD866F77ABC7B174B327A0576D7719 +Test: Encrypt +Comment: Set 1, vector 106 +Key: 00000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: B27AB67ACB784CB231A76D05B2539F0146F5C2F330987DE2C91AEAF8511DB9D1 +Test: Encrypt +Comment: Set 1, vector 107 +Key: 00000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 682263AAD3FF0B227983D20CB8A8B572427A2EE1B85A7FBB0961C722A7DE70CE +Test: Encrypt +Comment: Set 1, vector 108 +Key: 00000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E8AA0C754FBFB2BAF1025C8C13101552FA32E4031843E3DC56D2D819476CBFA6 +Test: Encrypt +Comment: Set 1, vector 109 +Key: 00000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7952391AEB6094458B28B543B9A5AC1DDB0CB18AEB431BE7CC7A4D45CCBEBEB0 +Test: Encrypt +Comment: Set 1, vector 110 +Key: 00000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 138599B1B9406E932D6229A4FFD959EE02E626022342FF233269A00DA1F58384 +Test: Encrypt +Comment: Set 1, vector 111 +Key: 00000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 87FA25FEBEFB539BFA46F9FAF8D62DB8E3C126D7409813A3B2FFC760FF19D390 +Test: Encrypt +Comment: Set 1, vector 112 +Key: 00000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 943B778E6053E3CBC59E9423A6D8AE678D369D5E27AB56D668DAD944D0A238F4 +Test: Encrypt +Comment: Set 1, vector 113 +Key: 00000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 00D31AA7620BEE29169C62966C53058F05709CD7C6A6584AFA80D7B2B7D9414C +Test: Encrypt +Comment: Set 1, vector 114 +Key: 00000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 9A6DD9EAE3286D48A7548C0A8A4CE8FFFB61B362C95C897DCD1CB1D8BBF76DEB +Test: Encrypt +Comment: Set 1, vector 115 +Key: 00000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 8231E89C8C74641DA6CD862B98B5DE749D6751B44361B763DF888F3D2312FAD5 +Test: Encrypt +Comment: Set 1, vector 116 +Key: 00000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: AEE13BA9322E1089262CEB199FD96E8A3C1E29142C6542961CA0B70782A4FD65 +Test: Encrypt +Comment: Set 1, vector 117 +Key: 00000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 89EEFABFFF030B563CAA5965CFF0372E0518BA1BF9A6E07D279C20AF3D52B9E5 +Test: Encrypt +Comment: Set 1, vector 118 +Key: 00000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 9EB46332AE8F271D9613A5FD1D6E1B06ED7A553C874A44A6F3A0615D46AA079D +Test: Encrypt +Comment: Set 1, vector 119 +Key: 00000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: FDB79EB3D755AC9338093917F84742BB1D62197D9730AEFCBAA9B3A4CEEC0B5E +Test: Encrypt +Comment: Set 1, vector 120 +Key: 00000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 64D439442C3FB4B580E0C7BC212F5589B395F6D100AA8165E4599A34F288D31D +Test: Encrypt +Comment: Set 1, vector 121 +Key: 00000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 09F8A382936078076F496A14B7BFD77CF4E549171FBDD8106AD0C2F87FD9C151 +Test: Encrypt +Comment: Set 1, vector 122 +Key: 00000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: AEB59849B6291FC1B8917642088608C4B9EE364C8C1FAE502F1ECD5BFACBC96A +Test: Encrypt +Comment: Set 1, vector 123 +Key: 00000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 006136B68224BF8BF47C0298FE7E2A4B72964A6C9F36EB709C452F0319B6A104 +Test: Encrypt +Comment: Set 1, vector 124 +Key: 00000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 55912F44A9A3493CF0A4DEF2F77978ECE0868ABF30BBAB15A96AFE15575AA90A +Test: Encrypt +Comment: Set 1, vector 125 +Key: 00000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 81BA612B664481588AB16246226CC1B59A08A7FE0FD64B0111C67C4BF344D2C7 +Test: Encrypt +Comment: Set 1, vector 126 +Key: 00000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 6B7930B1609C35095BE581F8F73709A65781DC1D49381411F6474CEBE6D16182 +Test: Encrypt +Comment: Set 1, vector 127 +Key: 00000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7308AEC23D25A231B26448AFE78D5047804C5011B9B5F95C16DF2670551F0001 +Test: Encrypt +Comment: Set 1, vector 128 +Key: 00000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: FBE855BD6540594E2D90566E7A30F57516EE170817B66C2468615D5D3D5DF03B +Test: Encrypt +Comment: Set 1, vector 129 +Key: 00000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: B072D598869D6EFCC8856A2B4686EF05A37DDB3F26DFEDA2F9C406B7250801F5 +Test: Encrypt +Comment: Set 1, vector 130 +Key: 00000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 0CF58B2665B889C06836E699DC2B4C615106541987229D686D43614D3BFC290B +Test: Encrypt +Comment: Set 1, vector 131 +Key: 00000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: F591E78CE6A8A375CBF821D222A49C862A461DC52C74065BA6349598CC7CB6EC +Test: Encrypt +Comment: Set 1, vector 132 +Key: 00000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A32B883113DE96B7AFD4ABE8E1703C8D724397542527E27F0CA32C89332980D9 +Test: Encrypt +Comment: Set 1, vector 133 +Key: 00000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 9B2C992F4CA0E70E0DDB03400AD24C4F20AD5F32940537B33F375C7979968537 +Test: Encrypt +Comment: Set 1, vector 134 +Key: 00000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 0DDEEEBC428F117B094FD27B614F6BDFEC0D71D61F8F93F9A09E0443F2FEB659 +Test: Encrypt +Comment: Set 1, vector 135 +Key: 00000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: D58740E259B1C9A5DADD2FA5FFB768ACECD0DA6FE40D7D59F3CF6FCD4838FEDA +Test: Encrypt +Comment: Set 1, vector 136 +Key: 00000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E6F318C17501C28164BE9CA692E92D4CF4835E2778B126E9841CA0F132CCAA61 +Test: Encrypt +Comment: Set 1, vector 137 +Key: 00000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3776A0BB5880EB65386F20D11BCF308C2DA3B010F7E2DAF3FB8B55B523E7CBC3 +Test: Encrypt +Comment: Set 1, vector 138 +Key: 00000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3926539CFD76BB79E50A571D75AA51B94864A79CA5DCAF6CE451FC068E487625 +Test: Encrypt +Comment: Set 1, vector 139 +Key: 00000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A8D9B6254BCD0BC32CA3ECF7A7A80882DDC178F47D8E91F760883D589D94F45C +Test: Encrypt +Comment: Set 1, vector 140 +Key: 00000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A2C3810606AD6AAAA571C8A783A686E9F713D0A1238C3E621347622C569C7BB6 +Test: Encrypt +Comment: Set 1, vector 141 +Key: 00000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 902FF7C8DA5B1D171603F48C02E72B611C40E4B15F06BF4A7DB914AAA7E63036 +Test: Encrypt +Comment: Set 1, vector 142 +Key: 00000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 55AAAB17A700544B1384EA512146F65A2F871C30F8EF7AB84DD96E004E924403 +Test: Encrypt +Comment: Set 1, vector 143 +Key: 00000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E9F049D8DD032202BC5E16F061B0449AEFD91845A4786A045E35739826E283AE +Test: Encrypt +Comment: Set 1, vector 144 +Key: 00000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 6347929B2B5B6634C2674CC4AD3B04B321F7404101E79259A35053E552369548 +Test: Encrypt +Comment: Set 1, vector 145 +Key: 00000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3C8D318014177555818122F69A95BED7A175464310A9B53DD4AF3C5887970D39 +Test: Encrypt +Comment: Set 1, vector 146 +Key: 00000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A3CE794DEA39A03EB4337395E3713ACA02E15148CC9302083E9F2FD55A921BF5 +Test: Encrypt +Comment: Set 1, vector 147 +Key: 00000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 2EE444D85842D41D9AEFBB7ECE34EEB71720AFB04498F9B4CFB87C10AC842D3A +Test: Encrypt +Comment: Set 1, vector 148 +Key: 00000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 0050EF8A2E0EAC79CD1BCC82F52F04410DA08263A320DA47B500DD72FBAA3487 +Test: Encrypt +Comment: Set 1, vector 149 +Key: 00000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 51721D61A2032DB004C8B83F7509B045A5190892FBC5AEB9BAA4B27D7969C791 +Test: Encrypt +Comment: Set 1, vector 150 +Key: 00000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 016D3D0A0C9B1EA97A12AB7BFA23BD4A973D5F10C06581A6DA92668BF3B4026E +Test: Encrypt +Comment: Set 1, vector 151 +Key: 00000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 687DAF7B782EB92EE2F8812ABA81A1F8EC353797544602A8EF2D2D6C1AC7EB48 +Test: Encrypt +Comment: Set 1, vector 152 +Key: 00000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 538008D0A4465A705313E0A03DE02BDFF7D9F0F0226F630DAFEA5434D9ADD7EE +Test: Encrypt +Comment: Set 1, vector 153 +Key: 00000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 2F65E608EF3E4C202C347ADDB9733132350A7AC9E544C5D7D76F9527DB3640AE +Test: Encrypt +Comment: Set 1, vector 154 +Key: 00000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 1EF33EF878790A6E16E18377C474700E6AF64C0C56F5FE8E7A1A83D990BB7B9B +Test: Encrypt +Comment: Set 1, vector 155 +Key: 00000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3369751D8735C5B82164E9FDFAA8B224AA4BD3FC2CD3DC48C60A1C290AE189BD +Test: Encrypt +Comment: Set 1, vector 156 +Key: 00000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 428F02228A58756A94871F5DCB37F54AD21345ABEDECB6D12630E51ADF4D6128 +Test: Encrypt +Comment: Set 1, vector 157 +Key: 00000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 521221AE0F51055948753BAC7A30394DA0F3DCB485364AB512E62D9CDC24FE48 +Test: Encrypt +Comment: Set 1, vector 158 +Key: 00000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7E44783F40C4A3EBB40E5D4E22A9BECAD3008D8B1AE64929B666664D8D8680D9 +Test: Encrypt +Comment: Set 1, vector 159 +Key: 00000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 48F54AE18072D2E58922EB0B14E4C32CD72807BF436A01164B0B5027ADCE6121 +Test: Encrypt +Comment: Set 1, vector 160 +Key: 00000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 671E9014ABC8FBBA21A307FAFF3FC7C89231ACA932F58C2D79DA323F80B3F87B +Test: Encrypt +Comment: Set 1, vector 161 +Key: 00000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 4473A8EF3585DDC8AB5858DB58FD87FA42E724D2374D7888FCFA66D82B30145A +Test: Encrypt +Comment: Set 1, vector 162 +Key: 00000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A4AD8D6A847FF420E96E1E592852FC7B362F1E0DBBE417B0CFC80C1200C5BB97 +Test: Encrypt +Comment: Set 1, vector 163 +Key: 00000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: B10D378FB56687BDDE7462A91FD0C42C773097765AC4C332B5007D1D47670EE0 +Test: Encrypt +Comment: Set 1, vector 164 +Key: 00000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 788D00A54C0A6FB10067E08B8F2C60B4DBA05B58D3C8CEEABE49C2FD2FD7D6C2 +Test: Encrypt +Comment: Set 1, vector 165 +Key: 00000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: CC54D8465F9529077237703DF4DC136FCD7A9D2FF3B89FF0D226EA3B234B6113 +Test: Encrypt +Comment: Set 1, vector 166 +Key: 00000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A0DAF3D3568FA9134C9C1B6EC5137B72715271DEC644F1268FDFA88A89989371 +Test: Encrypt +Comment: Set 1, vector 167 +Key: 00000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 0BBCCB3D83D7B6D3AA96AD5687C4895CD990146E293733A649B4D7EC48E9A93C +Test: Encrypt +Comment: Set 1, vector 168 +Key: 00000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: DDF8388BA3EA8FDC869D54D38D6BFE47FB7C5B6D81B3D80AE8B7DE00F4581EC1 +Test: Encrypt +Comment: Set 1, vector 169 +Key: 00000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: FF4F175CADFA435B31D5766FE6FE73B88B33BF5A87D79A2B47FCEB6BFE6E39AF +Test: Encrypt +Comment: Set 1, vector 170 +Key: 00000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 9B28804310814CF3C9782CB23FAB7FE19D5BDA5E9553F23E7876A6426316365C +Test: Encrypt +Comment: Set 1, vector 171 +Key: 00000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 94831F56AC794746628AF8A0684ABFE6A1113EB5B95939A8223D5C0C08BF52FD +Test: Encrypt +Comment: Set 1, vector 172 +Key: 00000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 689C2CAC1FC6999B8BA48B767A995871D80AB561FADF20D8613274CFFD00BF32 +Test: Encrypt +Comment: Set 1, vector 173 +Key: 00000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 4CC4412727B69CE43E6B85D89F03DAC6982CF867FB98801DA1F0E8720123699E +Test: Encrypt +Comment: Set 1, vector 174 +Key: 00000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 8160A24A68E81E4A839E1C16086983BE98652856CC621B3F7612A8B1324FA33E +Test: Encrypt +Comment: Set 1, vector 175 +Key: 00000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 024B19F8BE7203D9E5589AB96B86BD68A488D7994813D0231C835637B9E59A64 +Test: Encrypt +Comment: Set 1, vector 176 +Key: 00000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 954714BFD736CB391604E77367C2875EF291C02EED35B6DD6A20D58FBADAFB84 +Test: Encrypt +Comment: Set 1, vector 177 +Key: 00000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 6E95756FEA083B4AB4E624B5CFB00E31CAEA9C03CE4A1F51104BF6E7A86495F3 +Test: Encrypt +Comment: Set 1, vector 178 +Key: 00000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 93176B234B0A25F30649FD3172F75F181CD47C75D795FCFD5A537F18B101B24D +Test: Encrypt +Comment: Set 1, vector 179 +Key: 00000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 51637CD02F79DA935C5A317C1F8AC79E47E255E4A83F3F04DBA2998DF5118D39 +Test: Encrypt +Comment: Set 1, vector 180 +Key: 00000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 15C15F38B0CDEC62A426CF4AED25096DCCF1B2C7CF49A223F4D3ED7E06CAD2D7 +Test: Encrypt +Comment: Set 1, vector 181 +Key: 00000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 14520B3D7B8734A8D4E07CAB93744560D60FE7C9122C97F2ADB97D811074D225 +Test: Encrypt +Comment: Set 1, vector 182 +Key: 00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: F16ED0E9813C694563BF3557D73085C8761642B6B003291B31C681D3A9421E73 +Test: Encrypt +Comment: Set 1, vector 183 +Key: 00000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: BD3B03B8DF1994DDD3BE4509BB2B4AED0F7D0F7638102C58B15ED9DC9FAD5261 +Test: Encrypt +Comment: Set 1, vector 184 +Key: 00000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 45813D3ABF443D14B8519A10BA667F16C2EC757B309B978E26FFE56EE0BA00B1 +Test: Encrypt +Comment: Set 1, vector 185 +Key: 00000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A13D32CA09C34BBA16813BE8F4D56AF772B67327C7CDE0756B3D5CECEF2BCD2D +Test: Encrypt +Comment: Set 1, vector 186 +Key: 00000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: EC7D07D6F3AD0351131F15816F8044CBB1592324F62903B9DD6180D88E09EF07 +Test: Encrypt +Comment: Set 1, vector 187 +Key: 00000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 873F46936C8CC3A23CCA3EA3288CA070CC41F128296FCE6E7AAD2B7381BBAEBB +Test: Encrypt +Comment: Set 1, vector 188 +Key: 00000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 0AF0BB23EFCF86B273A27D84435F53F9984183E4C0D2F69945E79BAC8674C3A5 +Test: Encrypt +Comment: Set 1, vector 189 +Key: 00000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7B9A8CD1942564414FE5C1237B680970A306CCB0CF73F1123D2E823D084F3126 +Test: Encrypt +Comment: Set 1, vector 190 +Key: 00000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: C21A4ABA37069F7173A704B16C2DB945301BD4B08D3202BCBCA4AF8E5BA8A963 +Test: Encrypt +Comment: Set 1, vector 191 +Key: 00000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 5B2F725ECF531E569AC6B69408259547B9B054CAAA20B6727FE7654FAE4386D2 +Test: Encrypt +Comment: Set 1, vector 192 +Key: 00000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 58E6E58AD73C9DA9A19CBCBCB6E89B44951781A027D5C5CBEAABD95D55BE1CDF +Test: Encrypt +Comment: Set 1, vector 193 +Key: 00000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 8F076E12AB23D9CABFD006D16E1D554AB367CE88B3FDD44717824387DC9D4B43 +Test: Encrypt +Comment: Set 1, vector 194 +Key: 00000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: C5A351191F18886099542CE6B3025D6F0F4EF8A9A1C804803166BC2699D4B3C2 +Test: Encrypt +Comment: Set 1, vector 195 +Key: 00000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 39BF10576DBE0BA332EF36C38CD96F4F0043B8A0C6CCCCD3521F169821CC4C0E +Test: Encrypt +Comment: Set 1, vector 196 +Key: 00000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 12EC53C9420154F7D5334D4BF94BE3B4CCB044FDF56B4A92E245F016BBE9C057 +Test: Encrypt +Comment: Set 1, vector 197 +Key: 00000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 569D436AFFBB65451ECFDDDC7BABD5608BC183E9437F30B5058C505158BCE7EE +Test: Encrypt +Comment: Set 1, vector 198 +Key: 00000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 4E53AA49C4A8E0A00FA51E3DBE4D6BD6ABC1505C2E3FDADAC282BBDF5987E075 +Test: Encrypt +Comment: Set 1, vector 199 +Key: 00000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E0BF45509232C9F66517F057FB01C2E0E08906842B59DA4980413F629388C088 +Test: Encrypt +Comment: Set 1, vector 200 +Key: 00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: CC5A42F9BBCD1A5BE0D8EAC69A184E1693AE5F1C9FDAA05B8CB5330D5D63A2C0 +Test: Encrypt +Comment: Set 1, vector 201 +Key: 00000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 4247A5AA925AEAF29EA9FCC3C942DC47FB1A13213B302FE0C6F33243C631D2A0 +Test: Encrypt +Comment: Set 1, vector 202 +Key: 00000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: DAC043890BB61728CFC30E3A860BFF9474DE05CA104C242BAF498344470319B5 +Test: Encrypt +Comment: Set 1, vector 203 +Key: 00000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 214703F986092730BDF01020A825628FD06CD22C9F385CE14BBB2738A38A1E94 +Test: Encrypt +Comment: Set 1, vector 204 +Key: 00000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: AD3EED667396E27E4EF749BE1BC2D222380AA5C070B7246EB3A8249D9003BE1E +Test: Encrypt +Comment: Set 1, vector 205 +Key: 00000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 57B33C626E776BAAB8D655DD93125D49BFE92177BB63AA9902A44E4CC6F90666 +Test: Encrypt +Comment: Set 1, vector 206 +Key: 00000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3ABEB777D6240D198677B50B14545714D71D2F46885513688406B201F689C3BD +Test: Encrypt +Comment: Set 1, vector 207 +Key: 00000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 0B9E5A4358BCD0CA1AF306274CA676B515499878D2ACA0AD7865139D36910018 +Test: Encrypt +Comment: Set 1, vector 208 +Key: 00000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 9EAB0FE92E1B83FAE87EF6369BD0EED91D10DCFC5810FA0188D06929CF927422 +Test: Encrypt +Comment: Set 1, vector 209 +Key: 00000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: BC205D90F13A69AA6C45979861B1E5737A69C61F726D252F773E528276B9F1B7 +Test: Encrypt +Comment: Set 1, vector 210 +Key: 00000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: CEB885427DF7C988804E7C2401BD703CBB8F3D3D50AFD6CE9F56D32F802F8219 +Test: Encrypt +Comment: Set 1, vector 211 +Key: 00000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: C61CE53D0A5E771E6AC98830D496079A34ECE8967D737D0EBE393E7549679BA3 +Test: Encrypt +Comment: Set 1, vector 212 +Key: 00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 842F934F9C3E9690F3AABC753B6C27F7F3EF7B199ABFDA287686F35E2884A2F5 +Test: Encrypt +Comment: Set 1, vector 213 +Key: 00000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: EE357FEC92355A11FDCE30B089E4F5918A90025832DB3562C762A8421F3B6625 +Test: Encrypt +Comment: Set 1, vector 214 +Key: 00000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: C9CC50B7CB29557DCDC64C995B24D2E0E8AD8FBB4906A8DF06D67A69B1AAB8A6 +Test: Encrypt +Comment: Set 1, vector 215 +Key: 00000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: D6DE0F6B51BCBDA8D44D7EEA5F91C85B78F42B6612A35662CE3AB3043E87701D +Test: Encrypt +Comment: Set 1, vector 216 +Key: 00000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E3F3E3A5317DCBE044E1A97CAD714449DF0F8E9C319F5C12C19917B2F47F1FD7 +Test: Encrypt +Comment: Set 1, vector 217 +Key: 00000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3A1A26993055B3B30BA84236212646D2622680117D2813316223EDFFA1BBB22B +Test: Encrypt +Comment: Set 1, vector 218 +Key: 00000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 192EE13F6909D98437E8F424DE7DC873D82330DE64B379F3F8985658B00033DA +Test: Encrypt +Comment: Set 1, vector 219 +Key: 00000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: DEB92C0159D40548317AEAF996819352F43CB1E487885A0851234A43E4C5CB2F +Test: Encrypt +Comment: Set 1, vector 220 +Key: 00000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: C671DF68881157258EF58E7C7E712351FC9D743A2C4ECAAC9D3ABE98F9701B3C +Test: Encrypt +Comment: Set 1, vector 221 +Key: 00000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7A8BA935035DFE8F1DE34EA373FB60E147E6D5572686212BF95B6E0C115D15B8 +Test: Encrypt +Comment: Set 1, vector 222 +Key: 00000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: AA95483043360A3CCD5E98C8D5088F9F7154DA3E36F517C459F03B94EA8B5DCF +Test: Encrypt +Comment: Set 1, vector 223 +Key: 00000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: F716EF1B45585282C50AD6EB1EAD2D19AFBF57235E5D56A015882C55EECC2044 +Test: Encrypt +Comment: Set 1, vector 224 +Key: 00000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: CECA215484E90CE7AF49BED4B5F84543D05CE120973EE8510E0A410FA391BE3F +Test: Encrypt +Comment: Set 1, vector 225 +Key: 00000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 5AF45DB110A67D0CC49D1A1BB5765ACDDD6482BD88664A4A511BEB8DCDDC08B3 +Test: Encrypt +Comment: Set 1, vector 226 +Key: 00000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E0AFCA91B3CCF0A0C4E332C4F75BC17E5956B0F3A438F0B0ACA0E9B08DA9A1C0 +Test: Encrypt +Comment: Set 1, vector 227 +Key: 00000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: C559C00EB5C49F2321975A264F855C291DB8FF942FC4617193236318D55DA27A +Test: Encrypt +Comment: Set 1, vector 228 +Key: 00000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 88BCDD04989FE085F888A57176463662C57DC70DD3888F427B68BD5A36C3297A +Test: Encrypt +Comment: Set 1, vector 229 +Key: 00000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3C6302F9C2C8997C41FA0F0187B9E19D14FC2196A001D39F56BF5200E76D4F66 +Test: Encrypt +Comment: Set 1, vector 230 +Key: 00000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 641DA3FF9CC2C5AD625FD131D91E1AE5AD3088DF404384BD885917FD1AFDB9AB +Test: Encrypt +Comment: Set 1, vector 231 +Key: 00000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 1A05DEF28E631857C796D665FA66F8A4743F9A340904EC1C084AB022E63E3A0A +Test: Encrypt +Comment: Set 1, vector 232 +Key: 00000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 04DF8F3469AFEA2F63ECA1FA64FC18F1E42B42F7666BDCBFE6CC1C68614D85A7 +Test: Encrypt +Comment: Set 1, vector 233 +Key: 00000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 21AA974CF45CF84383024A8E7D3427BCD9A0A4F4B2AA83FA44911615B2D9A27E +Test: Encrypt +Comment: Set 1, vector 234 +Key: 00000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 74533E9973B565E0B7F9DB65A63B70BC5840EE4E1B6D927033CC1F733BD78AD1 +Test: Encrypt +Comment: Set 1, vector 235 +Key: 00000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E818E22E590974A00FBF40C1A1DD100F5C2E3A76C594D129DDE0C9119CC1A836 +Test: Encrypt +Comment: Set 1, vector 236 +Key: 00000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 00BEF3BB9263863455A8736A114E7DF13C903D6D9FE065FED48E6634EE9B9156 +Test: Encrypt +Comment: Set 1, vector 237 +Key: 00000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A0D418EAA61D8B6234D8B07D4652F61EDA48B00764E124DE5D7545973E4BFB0D +Test: Encrypt +Comment: Set 1, vector 238 +Key: 00000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 21472EDC58EB9D2EDE5D8A24DE18784500420820C388408E2D09C8935D3208CA +Test: Encrypt +Comment: Set 1, vector 239 +Key: 00000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 278849105940CFDF61AB8DF9A37427A24BD452C244988E7CE85B8FF94A913F71 +Test: Encrypt +Comment: Set 1, vector 240 +Key: 00000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7B35DC73EBA6408C2486D59ADA0A17B89ADC10E405E029E51B8FA7096704DF23 +Test: Encrypt +Comment: Set 1, vector 241 +Key: 00000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: D81FC2305382B4110925F4EEEE6C93C3356B30F4E083B47C0FFB429DC8A317A5 +Test: Encrypt +Comment: Set 1, vector 242 +Key: 00000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: B1CC26F822DAA8B4EF2DC5C08792C21A985D285697C9BC49E038331996F2DE35 +Test: Encrypt +Comment: Set 1, vector 243 +Key: 00000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 565635B8CF39652AD3F94F9658FBF2310A08DC25975102D9E0A658574E5437C6 +Test: Encrypt +Comment: Set 1, vector 244 +Key: 00000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3A9E77725182484E375528415C99C9BB2795A0841FD9F7E7D2DDE20A6CD71C04 +Test: Encrypt +Comment: Set 1, vector 245 +Key: 00000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: BD3F45893A96EF8C218B3C22079E64BF847F3C41D87F1AC68E62B32E5A59D350 +Test: Encrypt +Comment: Set 1, vector 246 +Key: 00000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 44BBB67723B8FC5778D18FFA60F1A7DF16F2A4583BA07E3B2A9A4286765AF743 +Test: Encrypt +Comment: Set 1, vector 247 +Key: 00000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 06198963CE32DC41A3869CB3893E1602D21EA64DD206C2DEA9FA79F756260BF8 +Test: Encrypt +Comment: Set 1, vector 248 +Key: 00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 82EA3EC56648E3152D541EA5EA76F9C1D12A373D5183CFFDBC49C0FCE25AC9BA +Test: Encrypt +Comment: Set 1, vector 249 +Key: 00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 2D6F44E5104C9A6B28DA5731FE95AD5ED73051B4D405FCB77D2845A3306CD9EA +Test: Encrypt +Comment: Set 1, vector 250 +Key: 00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 360DF8BA5BA3F245E4751C6B1D81CCCC7160D6DE8CB12B496DEF04A78B0D3DD6 +Test: Encrypt +Comment: Set 1, vector 251 +Key: 00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: BE0B2DE97E0528C5A135A81F2DA7431C8BF01A456411CB826F1205A9E57A44D2 +Test: Encrypt +Comment: Set 1, vector 252 +Key: 00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 4CC729EFC23033F244182FBAE629ABF4386CDB279C6394C7CC914724604D8736 +Test: Encrypt +Comment: Set 1, vector 253 +Key: 00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: BA44E9372A4EDC847FE6601F0DDBCF40864B2BB5C4EFF9B3038F7EAD6672907B +Test: Encrypt +Comment: Set 1, vector 254 +Key: 00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: DF3109ACA9E8546F5140E6705EDD69EB5512F0C5B3567D6EE132700820839B77 +Test: Encrypt +Comment: Set 1, vector 255 +Key: 00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: D909866F49103120A46CD4F2A98B2A2169E3E9AE7BB5AD36CEBD675F62B73018 +Test: Encrypt +Comment: Set 1, vector 256 +Key: 00000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 63081A9DE55FA28CFF0089A3D4A52568BFC0D3A172B1750180A91BA12EC3E38A +Test: Encrypt +Comment: Set 1, vector 257 +Key: 00000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7FBD9ADE476739C69CF906B611639D554ECF25BA26AC87A11EF30856DE890D28 +Test: Encrypt +Comment: Set 1, vector 258 +Key: 00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 495FB031327D3AE9CCA3F449E73571539EF9FD88589B5C3142F5A4461CAFF9F1 +Test: Encrypt +Comment: Set 1, vector 259 +Key: 00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 1E958BF17F89DD463B49BDE9B05D01DC2557DC4CE072C24D0527E45BA1C8026C +Test: Encrypt +Comment: Set 1, vector 260 +Key: 00000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 92093F21E7CFDCD81765E71ED960121F84C6FE1CDA50B00592ED0DB9A8808FFA +Test: Encrypt +Comment: Set 1, vector 261 +Key: 00000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 122E0C5E19B0636ADE10F1A14FF4CA69EC426B4F311C109F6B137BEE274B1912 +Test: Encrypt +Comment: Set 1, vector 262 +Key: 00000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 2CE82AD1BF9BDA86355188CF5605CEAB73E98BC617CDC3D5C8598F11BA96F6A5 +Test: Encrypt +Comment: Set 1, vector 263 +Key: 00000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: B14A656DB71E54DF9D443E899417FF4F79E033106AA34D8669EEF0E9918FF4C7 +Test: Encrypt +Comment: Set 1, vector 264 +Key: 00000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 47ECD5C02C3D702FC36817981781B1A4593E240773121F763EB788D46E990C5C +Test: Encrypt +Comment: Set 1, vector 265 +Key: 00000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 91B74FC5E6FC8C6C30F33CE83BC0055190373FC589C0516F248227531C6B853F +Test: Encrypt +Comment: Set 1, vector 266 +Key: 00000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: AC8F0393E6D8881EFF753E7CE47EC441106AFE1315E712BB439F2F2DD4318670 +Test: Encrypt +Comment: Set 1, vector 267 +Key: 00000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 5765316B484E3091FB5135ECD4A5356293BD87512688EF14C719B61857767E1C +Test: Encrypt +Comment: Set 1, vector 268 +Key: 00000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: FAD76A9798E8DD194095DACF92F83779DEDA70C413033DADEE55B4C94B98B426 +Test: Encrypt +Comment: Set 1, vector 269 +Key: 00000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 87F337C9D5763F38C679C5EB9A67F72B4581487ABC5ADCD5BABF4C71B5EB6F7C +Test: Encrypt +Comment: Set 1, vector 270 +Key: 00000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 526B4C3E3FE096F47D32A403A7D20EE269A42F68939B2FA8254A1812D9EC6069 +Test: Encrypt +Comment: Set 1, vector 271 +Key: 00000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 342C0D2D0A5048DC98F2E8CDBB84CC610E30BEBC12F7572CB416CBFCFA24039D +Test: Encrypt +Comment: Set 1, vector 272 +Key: 00000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 47D03635744E2D917F799F77A7E09E6F064CE224A4A1D507090DBE200DBD022A +Test: Encrypt +Comment: Set 1, vector 273 +Key: 00000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 0DCE2CCCD9628DD4F6552A020B9447D35DEEFCFE5D8CDD8223AB3BA9090D8141 +Test: Encrypt +Comment: Set 1, vector 274 +Key: 00000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: AC5622C3DDECDB0A46F796596ED595926B2783E6A884D18517F7344CCAB3A2C0 +Test: Encrypt +Comment: Set 1, vector 275 +Key: 00000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 80E59C358DC6F0B5749FEAF45A9BE7F884842839EE6B47024083F52A8636C2A6 +Test: Encrypt +Comment: Set 1, vector 276 +Key: 00000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 8E57504AD8F6DA6D8633D413362E961A6D69B18FA1B501DB846080A5A9C9C700 +Test: Encrypt +Comment: Set 1, vector 277 +Key: 00000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 4956C679E9B58DDE2185BB018A7D6C61C918FA0AA9D6102E7DEF1183DB768FB1 +Test: Encrypt +Comment: Set 1, vector 278 +Key: 00000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 2C25F9CD0DB2444EE43D0AD2C3AF0303D1487528F45AFD346617D164F80635B9 +Test: Encrypt +Comment: Set 1, vector 279 +Key: 00000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 5292E96CB2110AD3FD231C5B2BCD1A8986333787664D1A551B9B750B2AA39A11 +Test: Encrypt +Comment: Set 1, vector 280 +Key: 00000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: D189129077C79106AEACA4E3463FD0650AC493ED981DC252531C072F18E1E292 +Test: Encrypt +Comment: Set 1, vector 281 +Key: 00000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: F9490DB8BAE36E28E73419D1D57869D760D772DC8752D1DE948262755B4ED503 +Test: Encrypt +Comment: Set 1, vector 282 +Key: 00000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 994EB2D9BE7C9FD547426F295F15DE3BC8F4A2B3955C7028ED890B1DE0FBE21C +Test: Encrypt +Comment: Set 1, vector 283 +Key: 00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 464BFD1EB42B595AEF9700C7C4C184A2132B5F1E85625592E48A233FA7840EC3 +Test: Encrypt +Comment: Set 1, vector 284 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A097C32D58D5A932AC9DBEE942DCCE547222E37E97DC3B29A63AAF118D5B01CF +Test: Encrypt +Comment: Set 1, vector 285 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: D3D13CC4379D2817B8CF8E06312FC727A3BA3C58F96E478E4EC5BC7BAEDDCDE4 +Test: Encrypt +Comment: Set 1, vector 286 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 577C709C26BD52547BD7C0D3F9CDEBEC0F266178905C4C067B75A01D799EF910 +Test: Encrypt +Comment: Set 1, vector 287 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 08FCEF6A263916C53AEBB6CCD2623E7BA3C38C871C5A8B64106308B74A7AE1B6 +Test: Encrypt +Comment: Set 1, vector 288 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A22F794F4913B2B1CD930FA26EC219081F297DE4EC808771C9B375782F891D67 +Test: Encrypt +Comment: Set 1, vector 289 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 52F2C9714DAD06FCF5FD8962131D33952A6D68C2A90B8C08C3AB86B09A2C77C5 +Test: Encrypt +Comment: Set 1, vector 290 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 60BDED5533E692A9F073AAED43A5D5A81378E73A953514ACD5B0997B61848E3E +Test: Encrypt +Comment: Set 1, vector 291 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 38921BE2443A8101FBB44BCB4C5B87AB5026AA34C78B7FCDE07E102E142B6162 +Test: Encrypt +Comment: Set 1, vector 292 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: D49C075CC20268EE889A10E27F2D4EAA99A1764F765621FE97687ECB6067E5AA +Test: Encrypt +Comment: Set 1, vector 293 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 50FC6782B3285D35117C0FA81039A7F264FC4EB492F3B86A233D45F2834F153A +Test: Encrypt +Comment: Set 1, vector 294 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 1CC0B39D670A88D424F5D40B2F9256AF3736689BD82F0EB315AC9056F7EC63A0 +Test: Encrypt +Comment: Set 1, vector 295 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: CF66C3CD4B08CB0E4D25186BF84BE3AAAB1C435F07D12593AD001F70894030FE +Test: Encrypt +Comment: Set 1, vector 296 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 352572656D0EB6E0CE604C1A913ED733D465A480504B61B0F9BBA77122FD20D3 +Test: Encrypt +Comment: Set 1, vector 297 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 096E9F34E6E277EDB994954C3705F6904452001D3A3E799A1D0230D430E207D7 +Test: Encrypt +Comment: Set 1, vector 298 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 277BC612F90A6D0735B86168C021098F134D1627D0FEF38607038415D1BADF84 +Test: Encrypt +Comment: Set 1, vector 299 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 2376E2CE884AEC093E22A3C119D573609225FD5DC9B3EB7602C340D1AB51BDF2 +Test: Encrypt +Comment: Set 1, vector 300 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3EE2E39ADB49F92D09D55ACC817B5B2F22FB202951AEFB6DE8998D2932145669 +Test: Encrypt +Comment: Set 1, vector 301 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E508313113570BBB5A1E63F46AB52B57ED0676A061936F093961D34409F1B962 +Test: Encrypt +Comment: Set 1, vector 302 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 198A9A0A5B04AE936CB19E02A5B2A254A2DD5A4D71F6C676C0A826CD261CE8C0 +Test: Encrypt +Comment: Set 1, vector 303 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: EFEB9C3D34865B89275EFB9DCE1929697FC9E68ED9E9E32E2CF267DE57388E77 +Test: Encrypt +Comment: Set 1, vector 304 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 61016E27DF83D9DE642AE01D7D56C4BFE881C8BDEDD15C503BDC28D3F7107754 +Test: Encrypt +Comment: Set 1, vector 305 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 2FB5FDEC05BD94EF5A7F0DEA7A368F7C2B26ABC5789FEAE7B7B6A5E6C364041C +Test: Encrypt +Comment: Set 1, vector 306 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: F765AE08A03CF705D4BE6A6AF8A34CDE7A14F599B2CB7E2FCF2770F0CFD4F7AC +Test: Encrypt +Comment: Set 1, vector 307 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: D38105C4DE4742F16E6AE7C1C3C85A515DA8BC758456E4B5D64C0539B76D473B +Test: Encrypt +Comment: Set 1, vector 308 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: BFE3A705729C82DDE1297DF492A8F8ABAFBF2F436830B3716FC206D6931BBFEF +Test: Encrypt +Comment: Set 1, vector 309 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: B81E7CB312AC5FF0A1795FCD4AD8B3D84FE6C8B796584DE794B7E230823E6AF0 +Test: Encrypt +Comment: Set 1, vector 310 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 605C8D477420CF7D8218CB8A6B3624700BADE8D1384B04995F3C942DE38ABA6D +Test: Encrypt +Comment: Set 1, vector 311 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 87A3F6DC69A7675F27CD00D7A84251366CCCA92775D680EBEBB48B92A5781D7E +Test: Encrypt +Comment: Set 1, vector 312 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 71625BD75BF6A89C643553D382B325EDACCFB4BF5F1617DED0C44BAB96A9F72D +Test: Encrypt +Comment: Set 1, vector 313 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: ADF64E64C1A8D854C421F5AA8CCBE789F3643B0D769A2CDC68D7C3AC85FDB634 +Test: Encrypt +Comment: Set 1, vector 314 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3C1AB3A3A85B1EEAA057557DBB59FC28479B38BEE67F4CDA0CD49880DC15ED0F +Test: Encrypt +Comment: Set 1, vector 315 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 026071B93A8B85F000539539626BBF664273EA701B63D487208962F8CC14F1DA +Test: Encrypt +Comment: Set 1, vector 316 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 61EC580BC31488BD8993C9B9D6B430BEBAE04F9807F199808CF05B0B4F083F9A +Test: Encrypt +Comment: Set 1, vector 317 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: DF9093A33937B0B3ACAEAC1840C8E1358CC90FB0B6C0834D4CE4F442830127B7 +Test: Encrypt +Comment: Set 1, vector 318 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 5683A2E768F9E105E9ABF7B71DE48833367D19E961D9D95577D2C4E48716EE9E +Test: Encrypt +Comment: Set 1, vector 319 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 1D33978B4B75C10ACB850BBD98BB2CCB31F7D6F561E34AABAEB929C2F7762219 +Test: Encrypt +Comment: Set 1, vector 320 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 6197C557619E4B791888DFD695B4BF55B7F72258968E26B9B74A6A3814267DD2 +Test: Encrypt +Comment: Set 1, vector 321 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 9AD5C65433732C4ABF08BAE9015692F509775FC0450677CB1E76A060974B8807 +Test: Encrypt +Comment: Set 1, vector 322 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 44AA2FB88757EA695083CE00105D5B77C2DCE04EE1315D99040A1495E97EEB42 +Test: Encrypt +Comment: Set 1, vector 323 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 9C637BA9B011A62B15BE522D6C514092358222CDB01A2A35B895B1E57DF1303B +Test: Encrypt +Comment: Set 1, vector 324 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 21774A71C07FC295C4BF477A512445B2AC9AFD6619DCF0124CBD735BC823F945 +Test: Encrypt +Comment: Set 1, vector 325 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3D74A1E781FEE340DD9D912F6A681F85C0EF78BAE81D3E50A5DB8A311057DCB3 +Test: Encrypt +Comment: Set 1, vector 326 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 5B851E24E32EEB5BFAB09D26E86BBE4DA23C43C8E88635413516825D1F56DC43 +Test: Encrypt +Comment: Set 1, vector 327 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E79FAFD3076C0F879222F86A0671104F350B115A6AC107F5C66BB673CB047948 +Test: Encrypt +Comment: Set 1, vector 328 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 5E8EBDFCEF4F70640695CF76FE7912F5E77F55095F0A3EC15CE692AED2C7312E +Test: Encrypt +Comment: Set 1, vector 329 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 99EC9D6724631EBC582C22B1B002C8F63B386EF1A96A9E4D162F698F3EC13944 +Test: Encrypt +Comment: Set 1, vector 330 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 9DCF4937F7E089B09AF8F441538E2577E315212AA56EB20209F040BE602509C3 +Test: Encrypt +Comment: Set 1, vector 331 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 063CE595D4EEC463726FDB74E5254B5AFB965D2729D02F1890E70E33C4C7AE49 +Test: Encrypt +Comment: Set 1, vector 332 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 18F5B3F2F2B54FF37C354F3181228FBAA7D337791671988801C19333165EAD35 +Test: Encrypt +Comment: Set 1, vector 333 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 912671C8099032B1C0AE139D8F029B153B22B999DC30170DAAE3904CBDEFF083 +Test: Encrypt +Comment: Set 1, vector 334 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: CAE46BA93F81E1AD26A8FACE45566E162B8F4CAE831B4B80F93D2A809D3C557D +Test: Encrypt +Comment: Set 1, vector 335 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 31708CCF07D82433A61053273FBC5543BAA1A73B836624FF092361E55631531D +Test: Encrypt +Comment: Set 1, vector 336 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: B5F46BFA7B367DCE7998428525483F775D8F5F1A8DB9F7E3EB848F887283028A +Test: Encrypt +Comment: Set 1, vector 337 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 1D1B9489F66B8FDC1902C02CE15E94727352C2F6A302C12A6F9672BC44014F6F +Test: Encrypt +Comment: Set 1, vector 338 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 8EDD86FA2225D954B3F9F57A0433ED692E99F7ED55EF0A8D112468AEA58717A2 +Test: Encrypt +Comment: Set 1, vector 339 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 6F1414CBA350BB5DF73F7B23FCC0859BC2F081374BD4FBA7571DEC9343BD939A +Test: Encrypt +Comment: Set 1, vector 340 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 84535A21BFDE843B9E70AEEC9E5EB915FCEFF57449B7872142AA0669EFF250BF +Test: Encrypt +Comment: Set 1, vector 341 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: C4CC653F5CFA6C13C4693967D4CD1398B8808982F0C1D6D9B4CC9A6FCAF41E8B +Test: Encrypt +Comment: Set 1, vector 342 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 0949688EEF8CFBB88589CAB3EF58912A2C413E413EF122BB7F4C0E17BF723E71 +Test: Encrypt +Comment: Set 1, vector 343 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: AFF2976C45A69940BB88C71381DAEDD767BAF454331FCC5666624EB052CE05CD +Test: Encrypt +Comment: Set 1, vector 344 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A7D73428AA840EFCBFF0C856409C9B19CBDC19BE376EBC75DFC008A6BC9EAB37 +Test: Encrypt +Comment: Set 1, vector 345 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3C59AA18035D96933FB938DE0331DBE42DA57B539A77D660DBFA12B62611760A +Test: Encrypt +Comment: Set 1, vector 346 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 1F982024A86CEBEF27F0D19765907131C5EA1385761E92C7432D55A118AF2FD0 +Test: Encrypt +Comment: Set 1, vector 347 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 5D5CE5B2BCEC679BEE0B894E4E0FD2E5ABD345D8F8061A02BD4B1873C3A9B612 +Test: Encrypt +Comment: Set 1, vector 348 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 54C62940FC9BD4D96A0D19CE92F6880B5F45A422DF0400E868020ED5B42BC287 +Test: Encrypt +Comment: Set 1, vector 349 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 6A7B7E894CB7FE3A0153B5CC6E78351A07AEC726CCAF93A2C426C83760974035 +Test: Encrypt +Comment: Set 1, vector 350 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: D2DAC7485B1818A7A2976F164C80AB5FE47B7CBDA4048000D09DAC65857A8387 +Test: Encrypt +Comment: Set 1, vector 351 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7C545CC73456F1C1B06C5B5A05A9659F5D30A4D78E9D85C29A38735BEF098E0E +Test: Encrypt +Comment: Set 1, vector 352 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7E3FA28ABB96C7CFAC0DFAFA5BF2E469D75ECF690FA876F3307D851D3CF0AAC4 +Test: Encrypt +Comment: Set 1, vector 353 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 46FFBA6995D7D6A2B58AB5F995AE3A305CB0385242428FD092FE777556AB05B5 +Test: Encrypt +Comment: Set 1, vector 354 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 052E5126AEDA420CC39EEF255B816BD475DBD36635B090D04C43410F40236BE2 +Test: Encrypt +Comment: Set 1, vector 355 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 80BBBFF3EB0CE3976503A85240226D7FE177B4F30C753F081D7E1F3F8F0FC176 +Test: Encrypt +Comment: Set 1, vector 356 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 4A748837D0A7950876ABC89127A6D6FE5B646C7FE9DF8005CBBC3832DFE488EF +Test: Encrypt +Comment: Set 1, vector 357 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 84F35DFA249674C24E6DFB3947E3F3475817DF9548B301D4741B79EF9D26629A +Test: Encrypt +Comment: Set 1, vector 358 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: BEC48DE878DD3533F3614B3A0A4BDF5FB34DBA96AE94508FC0D3927032CC6E61 +Test: Encrypt +Comment: Set 1, vector 359 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 80DDDED6AF53DB0459359FE311F32C5DFE85F281C45365BEA7A2D6BA8A2D5EA9 +Test: Encrypt +Comment: Set 1, vector 360 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 43BA1E833A673FB760B13DA40C509EBB7170CA05E7BD2728A7FDA0EB8E3020B8 +Test: Encrypt +Comment: Set 1, vector 361 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 917FDDD2206E751DBAD9BD2EAA3E1FDD7C6CFC7782367B563DE6E116D0E4A3B9 +Test: Encrypt +Comment: Set 1, vector 362 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3AD03FD2841A7C8E8BA49100FCA794DAAF29995A9CDCC6D4F868914C890C3BFC +Test: Encrypt +Comment: Set 1, vector 363 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 79A9305A48A10F739B06EBD24DAACBF5289ED6A83415021DB1CAAB542E417DDB +Test: Encrypt +Comment: Set 1, vector 364 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 195DA96825A0F6B94A71E2EDD934FB184F375EEF66411567815A4A6E966CAC0C +Test: Encrypt +Comment: Set 1, vector 365 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 513239A738978DE007138E83F5CD13A0A9BE374CF61B09021767CAE284D5510E +Test: Encrypt +Comment: Set 1, vector 366 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 6BC70608C85D884873CDE727CF2B8A4E9563DA58242C907A3E87C2608AC0F1F7 +Test: Encrypt +Comment: Set 1, vector 367 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: F47D47E5D0013BF10141C7BF92642E4CCCF8020347B59F1FAB145849EEF0A2E1 +Test: Encrypt +Comment: Set 1, vector 368 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 879D4097A300F6575BC2021F218E9AE9FED113AF9B4FC9179C621244A9E2A090 +Test: Encrypt +Comment: Set 1, vector 369 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 91EF2BE82D9080A366AC7C4344E457E5F46DA5BD54DD50C97D2910D1478BFA21 +Test: Encrypt +Comment: Set 1, vector 370 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 0EED2315EF9B9278CCAD8EE2E33493F5A4FDAE31EC1DA863C017E8AEB77C2867 +Test: Encrypt +Comment: Set 1, vector 371 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: FE80FF0F839BE1F911A21C97B36D439ED66F9965293890D98D8A3A98F2CFAE1D +Test: Encrypt +Comment: Set 1, vector 372 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 4E241C22B26385E268F868E37873C36B173625048DAAE4ADE3C2E09D856A8AE9 +Test: Encrypt +Comment: Set 1, vector 373 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 71DA83DEC321D3160433BD8E2C2345921A6505444C9B1949B4D6CE400F1FBDBB +Test: Encrypt +Comment: Set 1, vector 374 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 21FF7AA748E96269211F129671E4F7A25BC55D92A144B7BEEB75F445FDCCDDB3 +Test: Encrypt +Comment: Set 1, vector 375 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 070290F0A10324414DCFD323822ABD2256ADDA0913FEDC70EA53F3F88EEB7AB2 +Test: Encrypt +Comment: Set 1, vector 376 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A112192AEDC7824247A9239BE92E45928416D086FEA09D4370DDFE862493AF4E +Test: Encrypt +Comment: Set 1, vector 377 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: B0CD1E1BF87C1C63C455C8A285DF739A85706A587CDF0726C4615590DD25BDDE +Test: Encrypt +Comment: Set 1, vector 378 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: F5EBFED2EF7706C5DEF09E94641FDA500100F500E431C601C879CC65CE260DF6 +Test: Encrypt +Comment: Set 1, vector 379 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 02CA5B7EAA7F906B706DD5B13A6C121927EAE22FB51C7259A781A916C5906E7D +Test: Encrypt +Comment: Set 1, vector 380 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 10569B20052606FEEB9956C2882702477F1D48F82B09C0BE1C97C3150F5F7D1F +Test: Encrypt +Comment: Set 1, vector 381 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 95C649C5B1ADCE59BE93F701C01D815D7A32D151179FC1B6610B3A2A98EE1295 +Test: Encrypt +Comment: Set 1, vector 382 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7E1DD644C151A0C1055E0AEB7A9DBE80BE09CCDE6C69797D00E7B391A6311D1D +Test: Encrypt +Comment: Set 1, vector 383 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 6A82511AEBE5A82B6392CCA180B10F77FF0C14A7CF8CED894E1C8EDF9BAB29DA +Test: Encrypt +Comment: Set 1, vector 384 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: AD05B4B2F644469BCCD1BE1D028B1FB26F270088E56D8B73364F958730B0C9D7 +Test: Encrypt +Comment: Set 1, vector 385 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 8B4110E53906CBD07EC61AC8DC8C97C475085AE6AE6418C45CAD7495B2C2F4A9 +Test: Encrypt +Comment: Set 1, vector 386 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: FC44F97B9B3791B98D941B460C585BC7A485024F2B15370605FA64BEB36F10F6 +Test: Encrypt +Comment: Set 1, vector 387 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 95E1B79F255E9E477D756B0123F22397C723D63F3D6AC710A1647E5D6229AC25 +Test: Encrypt +Comment: Set 1, vector 388 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 523D59EEA567CAE613403BE8C8769E9E375F290D7FA2DFF64C9B41120E96F0C0 +Test: Encrypt +Comment: Set 1, vector 389 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: DCD843BF9123A86C9938CB833C815217E37325B4ECF9A43E8E878ED2CDB257E3 +Test: Encrypt +Comment: Set 1, vector 390 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 4D737BB7B6B2EA155FA64CAA9124588594AD9D3239B03A0B5F1A1670EF37C309 +Test: Encrypt +Comment: Set 1, vector 391 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: D884858B07B3ADC2AB0067E24CEF443AF6D3CB691C7D3EDDFAF672763DF6991F +Test: Encrypt +Comment: Set 1, vector 392 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 24923E668BA92F02D0545738A1F3A81AD3EACC6F3E65A3C6879FEB3D55C3BEF5 +Test: Encrypt +Comment: Set 1, vector 393 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 98006EC6FFEE6DC3FE9D53FC632D1D82E8DC5BCB0BE0BBF1782701F858934432 +Test: Encrypt +Comment: Set 1, vector 394 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 1C7CD45E2FDF746F2F6B7FCE3510DD14CAC7420FDA6BC9C6D3287E894D2B9EF5 +Test: Encrypt +Comment: Set 1, vector 395 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: DF1B2CD5A9A7ADC85A257882E53150F9B3BAD4B5EFEEE8B4B212F8FB08F11194 +Test: Encrypt +Comment: Set 1, vector 396 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 5DF3202330B96E2C8D45284BC1D8CC34C076B18600495EC43F847D09B9AB08C2 +Test: Encrypt +Comment: Set 1, vector 397 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: CEE878EA6317D3B4E2CC695FCCC5EE04B7415B735F2D11B9A8891293D5D5E818 +Test: Encrypt +Comment: Set 1, vector 398 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3753BC3550155B6880CF1AAE6365FA5EA4F277B4E01FD26133A5C69F5620AC9F +Test: Encrypt +Comment: Set 1, vector 399 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 8FF623E4246D8B7D14904BFB478256CA55EBD9E383B672A91D512AFD606BA629 +Test: Encrypt +Comment: Set 1, vector 400 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: C823B856B5E462FAD71A1D9C8F02CE1FE48650BD53BD620D021ADB1C53C21B84 +Test: Encrypt +Comment: Set 1, vector 401 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 22D0CD94534D8DCC359095D77008069E57851298103A13ACB50BF6FA778CB9A3 +Test: Encrypt +Comment: Set 1, vector 402 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 413F7657C9E46D928AE307FE794D1B10FEEB433D7F829C66118E155227F811BD +Test: Encrypt +Comment: Set 1, vector 403 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 12A9E9ABCC1916594307C982852A6750FFD5D9DCFDA261EC54C2D465BBB0FB64 +Test: Encrypt +Comment: Set 1, vector 404 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: EEB4897AEABADA871D368A00748CB437801933D78A14687EDDB3D526BBC2BFF7 +Test: Encrypt +Comment: Set 1, vector 405 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 2444A95492348F7AB5C8EFE89839C6491833EF227637640F8199262DA70E5406 +Test: Encrypt +Comment: Set 1, vector 406 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: CD0F1C806CE40D9901A04A23B52BBCFF51D20E964BA2ADCFE9AEE7CC8FE4A3B5 +Test: Encrypt +Comment: Set 1, vector 407 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 30E58CD115B75139A5D2ECC5253F6467FDEF4DFA307D11132570F90E657BC254 +Test: Encrypt +Comment: Set 1, vector 408 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 563FF22D971BDFACD7A90EDE80F076126CB16A759FDE6DB83E0DEE71CA48F33F +Test: Encrypt +Comment: Set 1, vector 409 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: D235A2277B7D3A772C3D092D2E3D92248865EFED8C2577D3D087C5BE84891667 +Test: Encrypt +Comment: Set 1, vector 410 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3CD74A025D1C2044875FE1D97351608E0203CE65F2EB283633505AFDC3C6393B +Test: Encrypt +Comment: Set 1, vector 411 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: FDAAE4CA8FD698D4330AD8217D40C8368AE9A825BE3359CB881FA74315ADA4DD +Test: Encrypt +Comment: Set 1, vector 412 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A9BBBED3051D1EB40AA806CF6505EBB4A0D3BAE671AFA03BD2586B01ECC6B9AD +Test: Encrypt +Comment: Set 1, vector 413 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 468AC86525069F4A9F1F7036BB2FC3D042296707B9FE8328C9514DA52FCBBCC2 +Test: Encrypt +Comment: Set 1, vector 414 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 96498A45E45E26AA2A1DD58E7374BCDA71420627B332F94FE98E045251B432C0 +Test: Encrypt +Comment: Set 1, vector 415 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 36FB6B4DAE5EDE9971BC2F5A353A3D5954961D9C8F7D38063A9F8556881F1E1B +Test: Encrypt +Comment: Set 1, vector 416 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 4206BEA972707980637FCD2B990F2B8EAE3243C9178487047B1A9BE2C7F6225C +Test: Encrypt +Comment: Set 1, vector 417 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: BF2763F46F4EF8CF40E42B6E4F161785D3478BDD1EA0BFAB30763B98BBC64720 +Test: Encrypt +Comment: Set 1, vector 418 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E7B97A297B534B1842528055982B7C382CFFDD161D69725789BF0CC35339D0A8 +Test: Encrypt +Comment: Set 1, vector 419 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: F8E68E206729EDF06C9379DC6F87891FFB6D5DD75A040D4F0E17BDF28308E6E0 +Test: Encrypt +Comment: Set 1, vector 420 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: DA69958998715C7517B9864E3A81F5960A48E9071FEB047084683D95A8532751 +Test: Encrypt +Comment: Set 1, vector 421 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 99456A498166535817F3DD3B47696CC74777ADE25DFA5CB5A3DF1A47DBCF0F17 +Test: Encrypt +Comment: Set 1, vector 422 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: D2D061B7FEDCA0663FE8F738042D1CE7D0EFB3BCED73977087FAB06192A361C1 +Test: Encrypt +Comment: Set 1, vector 423 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: ABF4E053FD99A777A5C95F057A1D8D3BC433D212220FE2BD5074C7E7B4AAA636 +Test: Encrypt +Comment: Set 1, vector 424 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 335F971AF070B59191F61547DC555F2AD86B263B23AAD53A80D6DA0C8A73C6BB +Test: Encrypt +Comment: Set 1, vector 425 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: C2EE398458AD869FCFB5DBAD16CB66F2CDEBE8D9D2C0FC4B258553D7D648E281 +Test: Encrypt +Comment: Set 1, vector 426 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 659BDB67C3BB43D43CF53EF14411F9B5B2B3C8C9B961087622BF1F0412596D81 +Test: Encrypt +Comment: Set 1, vector 427 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 21E2DA7422F753B1B625D95BFE5FD1C52CB5DFEDF0F2662EF17416E44F671525 +Test: Encrypt +Comment: Set 1, vector 428 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: C14725058665DCF8D701BB4A3DD5490DDA85E2754D9B233C008B5FC3559837B0 +Test: Encrypt +Comment: Set 1, vector 429 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: BF0D7F94DF1C7CA59CAF588BEDB316CB4E31A578B76C1E5213EB663C0E850F97 +Test: Encrypt +Comment: Set 1, vector 430 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: C81ABCB56C58DB2D5A329C6777091857DA4A5CBCB9D05AD6B0D4A2D4E915A7F4 +Test: Encrypt +Comment: Set 1, vector 431 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: F9D7611F502D0CED242909E032173BAF5A43DAF7009F53E25E109D7F4FEF9981 +Test: Encrypt +Comment: Set 1, vector 432 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 4EC0E7F808A10BFD4676E5CCA67E1D48806F346B702B2827810487EE56907C71 +Test: Encrypt +Comment: Set 1, vector 433 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 34C183C96FE5D9D2B4ED564EE9726551B27E1AF24848B5D711503E88BECBE458 +Test: Encrypt +Comment: Set 1, vector 434 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3E5EA6B326751B501C91C4A575B0ED6AEA9D60A14908187ACB3FC145B5468131 +Test: Encrypt +Comment: Set 1, vector 435 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: DA3904568BC8844CB594F44FE13F5D663B55EE6995D2232A999D591F2FCE7812 +Test: Encrypt +Comment: Set 1, vector 436 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 9293ED1C3C5B1A91B54A43BC63603F2EAD345EF9A7D3E69BD955EF1B8D36FD13 +Test: Encrypt +Comment: Set 1, vector 437 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 65C5CE0CC96FA6085A23EF00299B6D8518673DC9B8BF764DB595A8A7F8E940C7 +Test: Encrypt +Comment: Set 1, vector 438 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: EF95E25669CF4079F8BA728F41BD115F2913D8CFE0116C86032CD133E4787011 +Test: Encrypt +Comment: Set 1, vector 439 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7860315B44671B93718FEAB94BBCEE6B1006354914A90C3BF2DA1B6FA62F48AB +Test: Encrypt +Comment: Set 1, vector 440 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 2AA9968D7011FB1F33B97DAD01C2708A6826C030AFCCA35B222B2E47C89F14E1 +Test: Encrypt +Comment: Set 1, vector 441 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: CA9DD4F0771447B9AD0664DDA2921192568C2012246CCF5E95CD6CF3FBC44DCA +Test: Encrypt +Comment: Set 1, vector 442 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 38D51B18372FD7E7A617D7BCBCC658CB16014B05ECA242AF52B40AEDF6952DE4 +Test: Encrypt +Comment: Set 1, vector 443 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 640D035CFD65FE70D089866A53F21D00F86FDB1CEE2880F9FA7D382D424978A1 +Test: Encrypt +Comment: Set 1, vector 444 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: B41B62EC90FA9CC037F1BC74AEED25226917DD3B2B2E5C11EC6AE7601CF3F0E2 +Test: Encrypt +Comment: Set 1, vector 445 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A4340A36C7E640C83D2401AAE6F9F103BC9B568EF5B7F67663E64B820974B235 +Test: Encrypt +Comment: Set 1, vector 446 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: CAEF6FE59B0C05DDFE4F233412A185038077B7138EE9BA5FF4815C63C2BE84D2 +Test: Encrypt +Comment: Set 1, vector 447 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: F5D76FAAF12F566711DAAAC0E1F71260354FBA7BC0DBC34D7A2B6FE8E19DC672 +Test: Encrypt +Comment: Set 1, vector 448 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: DB1B22D80BD5BEA8D3F5F445E296FF3506C98C6FAE617D6C8DD943BC535AF864 +Test: Encrypt +Comment: Set 1, vector 449 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: DA02BA2C706095D3EB008EFFEB5E501FFF78B59EC34CBCAF0D7CE82268CCAFBA +Test: Encrypt +Comment: Set 1, vector 450 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: F878759262E5C2BA6CBC2091406D4045F876767C475582965B185DC9437ADD1E +Test: Encrypt +Comment: Set 1, vector 451 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: CA268715277F1CABC2062D4EDFD667759829782F793715199EE172917DA35C5D +Test: Encrypt +Comment: Set 1, vector 452 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 01BACD8388BF42064C8E927B3629C0DA82A0FEC4883EC068DC48483C43512BC5 +Test: Encrypt +Comment: Set 1, vector 453 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3D782388FD4ECBFEBBD49F2FBCF80A687E4CC0B8FEF51F097DEB679F49CB8B06 +Test: Encrypt +Comment: Set 1, vector 454 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 392E11AF1FD4A97ED260B680930C95DF26679260EAE0C025C405CDCDBC8E810D +Test: Encrypt +Comment: Set 1, vector 455 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 10E6AA6CAA90220E6D8963837D9EC3D46F8E9679379345282573753F2093E0F2 +Test: Encrypt +Comment: Set 1, vector 456 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E3EF5E9644294206A5707EF83C54E5EF5F4DB9841383C3EB767DEA722E9B7D0E +Test: Encrypt +Comment: Set 1, vector 457 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 0EDD01B5FE46475139F14371B548B58C5E33830D6EA6864BFBAB36D25345F8F3 +Test: Encrypt +Comment: Set 1, vector 458 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7DB72BFBC00A04E38DD4B9F2EA5C0114D19B2956EB959BEAD3E29DFB9BFC9A2A +Test: Encrypt +Comment: Set 1, vector 459 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7DB561AF481CC8B010BFD18A0216E2554888BBDD4E90B00476809B48601C9306 +Test: Encrypt +Comment: Set 1, vector 460 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 4EAB74E6D12574BCDEF95BC0CAD67C7E04B24472431607EBAD5F915F1116C9CB +Test: Encrypt +Comment: Set 1, vector 461 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 5A48DE560FA1ABF0F85BFF9A0A1928020A6C51AD3FE7C1392C2A875401DE62F0 +Test: Encrypt +Comment: Set 1, vector 462 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 074956F37AF065DBEDB2D68C602A4B65B7D614F8A0B284539E234B307CFDC495 +Test: Encrypt +Comment: Set 1, vector 463 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 9BB4837A582A5CB30579DABEEC41ACCB3786AA9BE52DDC88065BE0FFD33917EC +Test: Encrypt +Comment: Set 1, vector 464 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E1E690D74FC254D1D2A8238096285CC100013E8A8BB55FE92F6DF69DB217773E +Test: Encrypt +Comment: Set 1, vector 465 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: DFE35C2BC6ADFEBE4D9E8F84160AD6315CA43F0F022DDC629106E008F29C81AE +Test: Encrypt +Comment: Set 1, vector 466 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 8106B2FE206F9F8738BEC324B531E6943F00B20EC35DEADCB508197EEEBA5473 +Test: Encrypt +Comment: Set 1, vector 467 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E46E36293B659E73FAA1722AF29651621598FF2E92694C99F7BB0C792B93BAB2 +Test: Encrypt +Comment: Set 1, vector 468 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: F3CAB9F84AF81A06F9F350C345B44E053C8F1EE36D62159B4993950BB76D0948 +Test: Encrypt +Comment: Set 1, vector 469 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E3381C1644BBBB29290D30F15C96956BF4AEFE443FBDA0DB3EF2CEE7081D1DB3 +Test: Encrypt +Comment: Set 1, vector 470 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A4DD97D2710285907527C4FAE5676774D937FEC609F8489A16384568FAAA699F +Test: Encrypt +Comment: Set 1, vector 471 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 43C608E43584C631E620672EB0A92707C396ACC12CBCE0810A28F7EA3491E0A3 +Test: Encrypt +Comment: Set 1, vector 472 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A1DC3C2AE54BB2FA291913562F05E021AF361E422D39C89D8CFDBE4B672B63ED +Test: Encrypt +Comment: Set 1, vector 473 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 890CB43DA15A1D69A10EA9322B8C14D61AD537462439A735472CEF9428C8A2D9 +Test: Encrypt +Comment: Set 1, vector 474 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 9119548582EB7EA7F4AA1B224A6825B786F316EAA7AAA18B61B56D64AA4CBA29 +Test: Encrypt +Comment: Set 1, vector 475 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 574DD7CA20662ECBC730FA7CE314094E427FB8250E0F636894B650DA35A7F0CE +Test: Encrypt +Comment: Set 1, vector 476 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 3575DEA861D0F97DA32438DB834020996820BE85EAE5ED15A7983A31C7669C70 +Test: Encrypt +Comment: Set 1, vector 477 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 27EA06CBD196073357F1F790191D14796FE2BEFBE18B8C48D7566528B3DDA4C6 +Test: Encrypt +Comment: Set 1, vector 478 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 11B190730F6EDE90C8B3FEE01E722ADDD21BEB4324A358F86F524E4B7F7AF975 +Test: Encrypt +Comment: Set 1, vector 479 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 07E3CDB5130D8FF7A2A31335AD478FEF10805E266C00646CFBBEE81F2B3C1711 +Test: Encrypt +Comment: Set 1, vector 480 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A0ED0FFEEBCBF4066EE550E63065B08569B92BCC938002A5469ABD1C397233A0 +Test: Encrypt +Comment: Set 1, vector 481 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 2C9CDE299A4C507EC03C617EACE2358E76BC1AD338FE5A66A9105F18788A8836 +Test: Encrypt +Comment: Set 1, vector 482 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 5163F9C4ECECD047E83BDF1D6EE233487646A96FE43B4B08C41324FD8ECB271B +Test: Encrypt +Comment: Set 1, vector 483 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: AA2AE4BF506AB3D7607A29C3EF90B4C7933EE58ED3AB3720817FE3C611A850AC +Test: Encrypt +Comment: Set 1, vector 484 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: B04B4C802D91D9ADE76EBAFCDBA0A96A8A83DAEB7069370D6E901A42291EB8C6 +Test: Encrypt +Comment: Set 1, vector 485 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 91A99BC40CF38388B4AA77798D720653492CCED5230382ED587A305A2A1A6BCF +Test: Encrypt +Comment: Set 1, vector 486 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 91FB386F3B9AF82F93836005CBD9ED6727B9BBF1F669EAE6D06DA6D04D1AC082 +Test: Encrypt +Comment: Set 1, vector 487 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 01F8956120BF068AE7241BB96FF086C2D67547B549A8743FC0569978F201678E +Test: Encrypt +Comment: Set 1, vector 488 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A8C562A616F918A669A29C0724B76E3D04B125E0AB5A09E8CE60F54E4816EC90 +Test: Encrypt +Comment: Set 1, vector 489 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: B41D3BC188419DC929D611197D17FB4D29B78CD7FBC03B904219DD8A2FEE210C +Test: Encrypt +Comment: Set 1, vector 490 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: B119861B67AFE45C0134E2336CAC90BAFD1EB94C557EBA6DFDCBE69367B37981 +Test: Encrypt +Comment: Set 1, vector 491 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A2317FD4C041AF4D87C46FC684FBEE8DB65E4D43E5EA74237988A7EB67404656 +Test: Encrypt +Comment: Set 1, vector 492 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 641794C292A1A590F909D01F175E012671AEBF1E432295AED662E74C1EEA5DD4 +Test: Encrypt +Comment: Set 1, vector 493 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7984AC47362281DF446BE46AEC5D9A94B842F6F5BCCB01FD564318A49F94042C +Test: Encrypt +Comment: Set 1, vector 494 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 74F84174C9E2EBBEE396727DBB1C9CFAE2809D802F7E7CF8F7515FA3A629ED98 +Test: Encrypt +Comment: Set 1, vector 495 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7A9E862E27444A492C91CA2EE5E93369FEB74BB881AAC74F895D97E61500FA99 +Test: Encrypt +Comment: Set 1, vector 496 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 638E347CEC7121A668AF985E56F7F3934D852FCF53283B767BAC213337AAE99A +Test: Encrypt +Comment: Set 1, vector 497 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 45DC398895DA1B415708B4BC8B7EF133849E0E8E99945AE4D9C894FDF6D2815D +Test: Encrypt +Comment: Set 1, vector 498 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 1ACF1203B698FE2E3375E251EBBC05D387FECABDE6A9194DF5195F3FBF1E3502 +Test: Encrypt +Comment: Set 1, vector 499 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: F6A064BDC6EE0777B09CC1A0154F28AD282D4D6E48F9DE11CA083B8A9F454891 +Test: Encrypt +Comment: Set 1, vector 500 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: FE68FB721E181EA8A62CDD3CA0278C6EB1344DF07E73676D3F0DC501D99721C3 +Test: Encrypt +Comment: Set 1, vector 501 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 72923AD92EF01BDB90B9639DD411E4540CE0F531A0AE401547FBA03CB850B63A +Test: Encrypt +Comment: Set 1, vector 502 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 0B1D0F485A4DE59658FE61F1F0010D9EF5A2BA97624CC3687D94EE4335777138 +Test: Encrypt +Comment: Set 1, vector 503 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7423264FBF5EA94BA461BD80B2518B1CAF3757CF5BAB4511144637F5DC917168 +Test: Encrypt +Comment: Set 1, vector 504 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 589FADA29BEA438C12CA96241AA492FCFED48C1C1C05C16C88CD7A8B46E16A0D +Test: Encrypt +Comment: Set 1, vector 505 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 319B5D23945A98C9480E6460CBCB86A8B36038A28500A36182B228060713F58B +Test: Encrypt +Comment: Set 1, vector 506 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: B81B723D3E18A074078B7D041E55B9B130953ECF70BF773273A28E11238651A5 +Test: Encrypt +Comment: Set 1, vector 507 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E660AC40BC4700D4CE85AA43A2A39A24D0F255E64A9251D7442AEFB6EDFD43A8 +Test: Encrypt +Comment: Set 1, vector 508 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: C27914CB70EA29C06B321E4F61730CE6679A342733738BE72C97EED40802EC17 +Test: Encrypt +Comment: Set 1, vector 509 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 764B78FA0EC12E017D9F7C69FF53FA8FA00E7185888F36DBC3CA9A10A6122FBA +Test: Encrypt +Comment: Set 1, vector 510 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E2F9F554823B38D2099DD27E0AD6AD69BE137626840B41B7CF081D7881C47CC7 +Test: Encrypt +Comment: Set 1, vector 511 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 403E453BBAF997A75C4517B588431C75BCF01208B378A4F4FBB138217A9CA4A2 +Test: Encrypt +Comment: Set 2, vector 0 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 8000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 2CAE7C0460EE2FC3200923A1B6C2ABEEA746C8B44F6C3FB941BD3AF02A3E6E3E +Test: Encrypt +Comment: Set 2, vector 1 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 4000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 45FAAFBEE792EA704EE3D08CFA9D9F5CF93FEB3443E0049DE5898A48F5A3D92B +Test: Encrypt +Comment: Set 2, vector 2 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 2000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 720F072E7796310AC1BDDD3714581EB95896723DA3E61E0892B43F65A4153965 +Test: Encrypt +Comment: Set 2, vector 3 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 1000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 5E6671D1F792673D63940E69D78A3471B3C150707DA72E6C25CBD2C4DA2B9778 +Test: Encrypt +Comment: Set 2, vector 4 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0800000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 2E96F027C2B62ED2D2EE692A992ACAB827D16FDA71DD98109A645E4094923D3B +Test: Encrypt +Comment: Set 2, vector 5 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0400000000000000000000000000000000000000000000000000000000000000 +Ciphertext: A38D7F334B21394B28A29FC9CBC68AD9F2AE85E7434D1C2F57AAA4C1A49DB759 +Test: Encrypt +Comment: Set 2, vector 6 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0200000000000000000000000000000000000000000000000000000000000000 +Ciphertext: F67B5037CE9193023095D43DE312523F99E6CBCDF43EC00A947284496E311DD6 +Test: Encrypt +Comment: Set 2, vector 7 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0100000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7DC030A91C39EC8558AC10044AF79D4CCA92BBC8093B3A2456E26350E35EEBDA +Test: Encrypt +Comment: Set 2, vector 8 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0080000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 99260425AA126953E04A3D959F9153404521EC64C3B35E61EEBA67AAD2C1295A +Test: Encrypt +Comment: Set 2, vector 9 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0040000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 65C380354899581B2B40EDDF40A0695FB608DCDD11C6B0C2CA6BB427DB1D2A9D +Test: Encrypt +Comment: Set 2, vector 10 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0020000000000000000000000000000000000000000000000000000000000000 +Ciphertext: BBD1C4488D41FB1B096E835AD29FC3DC5B97496BA638625D78B99C5ABBDFA13A +Test: Encrypt +Comment: Set 2, vector 11 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0010000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7AFDEE496D690233ED0717E2D92DE3A102FDF902E51E69FFCE244B84A69CA826 +Test: Encrypt +Comment: Set 2, vector 12 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0008000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 06D8C3E7AAC698D143013B364BD7ABC4E4EB6BA82BBAB2A4A0B486E70E24592C +Test: Encrypt +Comment: Set 2, vector 13 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0004000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 727A8BF64932039C3409ED31CFC0171651BA69D551E8073A4BD1D35F31F52336 +Test: Encrypt +Comment: Set 2, vector 14 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0002000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 9EE7CA05C4161860014BEA89FB2DED90B4F0B362AD67789C6045C9C71310A8AA +Test: Encrypt +Comment: Set 2, vector 15 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0001000000000000000000000000000000000000000000000000000000000000 +Ciphertext: E924224559E43960EC44165CAD471CFED381B279B3EA4AF96BDB071BE987DA0D +Test: Encrypt +Comment: Set 2, vector 16 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000800000000000000000000000000000000000000000000000000000000000 +Ciphertext: FF189222046B5F4FB491CDC9A98130D772629F3EF44A06894268C507C25061AF +Test: Encrypt +Comment: Set 2, vector 17 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000400000000000000000000000000000000000000000000000000000000000 +Ciphertext: 6B053BA7765F2A62595A1E83444B52FCF16C8BBBEB21B437E6FC8C5F03B3673F +Test: Encrypt +Comment: Set 2, vector 18 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000200000000000000000000000000000000000000000000000000000000000 +Ciphertext: 0FB836DC6BCDA1C2955CC7A6F25E72C5FFFDE1075D820217157051FB5BD3D3EF +Test: Encrypt +Comment: Set 2, vector 19 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000100000000000000000000000000000000000000000000000000000000000 +Ciphertext: 200EBC8B8217D9A6895253F9366543027E5F493DBA1A5AD4FC7AB66FB806308E +Test: Encrypt +Comment: Set 2, vector 20 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000080000000000000000000000000000000000000000000000000000000000 +Ciphertext: 45B33F2465C674941B7E26C5986E42F6814A71323B420E401DCC8DA200FC3C08 +Test: Encrypt +Comment: Set 2, vector 21 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000040000000000000000000000000000000000000000000000000000000000 +Ciphertext: D2BF0A074053A01A227DC439311BF8BD696203995285A3A2CD3674A0CC6A65B2 +Test: Encrypt +Comment: Set 2, vector 22 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000020000000000000000000000000000000000000000000000000000000000 +Ciphertext: 5FFFAB58BA2CB27AE92E10F36F99A8EFEDF9DE2446A9C2E82E48F22FB1ED8C5D +Test: Encrypt +Comment: Set 2, vector 23 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000010000000000000000000000000000000000000000000000000000000000 +Ciphertext: 835A1BD7A3688BA0F7C572417A06FCCBCE0A69C7FCDF10C8BCF4469AE80DF11E +Test: Encrypt +Comment: Set 2, vector 24 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000008000000000000000000000000000000000000000000000000000000000 +Ciphertext: 559D1BECB3DBBE40A7E31C66D97D292821B934818172553FC1CE68AD8E6A741F +Test: Encrypt +Comment: Set 2, vector 25 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000004000000000000000000000000000000000000000000000000000000000 +Ciphertext: D962BE9A9C4F8DDA6F0EC42DB8B48FA14A1E91E639BD85FF26A2543D9FDFA9A9 +Test: Encrypt +Comment: Set 2, vector 26 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000002000000000000000000000000000000000000000000000000000000000 +Ciphertext: 588B2319C62ED25ECEAB7C327B212F5FCD5D89DE8A85AA3713BF332CF5F715DF +Test: Encrypt +Comment: Set 2, vector 27 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000001000000000000000000000000000000000000000000000000000000000 +Ciphertext: 67EDE571C64AFF87D7AE5294E64F1709F920A10D278E1629FC8B2BE7EF5ABE0D +Test: Encrypt +Comment: Set 2, vector 28 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000800000000000000000000000000000000000000000000000000000000 +Ciphertext: 60D9E58A6828847F9644DC165EB508B5A2BC67219B969B605B3CFAE109C9CE47 +Test: Encrypt +Comment: Set 2, vector 29 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000400000000000000000000000000000000000000000000000000000000 +Ciphertext: 5A0C538CB78F13404BF8D8AF5C43A17F04AD0D35DAD45F88E26B9D1C204B5AFB +Test: Encrypt +Comment: Set 2, vector 30 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000200000000000000000000000000000000000000000000000000000000 +Ciphertext: 724EE8B7D7BCAC2587C42D92FFCDF7EDFF91F06AD43ED353F332E1FAC3B70F5F +Test: Encrypt +Comment: Set 2, vector 31 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000100000000000000000000000000000000000000000000000000000000 +Ciphertext: D50F11DACBF340C1315419D1983028DCED83F8350FE50DA4F9554DFA641E99E1 +Test: Encrypt +Comment: Set 2, vector 32 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000080000000000000000000000000000000000000000000000000000000 +Ciphertext: 9460ACD1B739015ED197B2659353AAC465339FAD9D1AFB845A337630332C1C55 +Test: Encrypt +Comment: Set 2, vector 33 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000040000000000000000000000000000000000000000000000000000000 +Ciphertext: 7D7A56F8A89463C4CE519B96854200C6E05703651CE3ACD5549B59D0B9788B93 +Test: Encrypt +Comment: Set 2, vector 34 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000020000000000000000000000000000000000000000000000000000000 +Ciphertext: D07E4F830ADF1DE4886C614CDB6B3D988884293AE65A63B3E9886A8727C022B2 +Test: Encrypt +Comment: Set 2, vector 35 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000010000000000000000000000000000000000000000000000000000000 +Ciphertext: 56CCEC1812B3B83086208DBF0C98119DC1CAE316E91B09F4F6F36BDCF73F8873 +Test: Encrypt +Comment: Set 2, vector 36 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000008000000000000000000000000000000000000000000000000000000 +Ciphertext: E8C3012B0EEB2D18DEA4C06BAC2906DF858BFB8A4D86D6841C02A9E45B2D0455 +Test: Encrypt +Comment: Set 2, vector 37 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000004000000000000000000000000000000000000000000000000000000 +Ciphertext: E10FB90CB2F5F830763FCEFA386A8E70052AB8994A55DC95FEDF8B71E11D2636 +Test: Encrypt +Comment: Set 2, vector 38 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000002000000000000000000000000000000000000000000000000000000 +Ciphertext: 848DFB81A0D4D13A40F9119AB77A3B6D2B96E76396B39984739FDF31ADBC376F +Test: Encrypt +Comment: Set 2, vector 39 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000001000000000000000000000000000000000000000000000000000000 +Ciphertext: 61068A490E20E07686D8A77B81718A3214508E3FE3DA6A6BBAA8ABD67B98623F +Test: Encrypt +Comment: Set 2, vector 40 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000800000000000000000000000000000000000000000000000000000 +Ciphertext: 9197E2A5212260324CA6E6FA0BBA56B4E5D9934C8B9E42D9F43E901C0994082C +Test: Encrypt +Comment: Set 2, vector 41 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000400000000000000000000000000000000000000000000000000000 +Ciphertext: E9DC3C1445CBFF1B863CF3FB6B338B4EC29F2C083E65A4BBCC2F1FAC22CCA8DD +Test: Encrypt +Comment: Set 2, vector 42 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000200000000000000000000000000000000000000000000000000000 +Ciphertext: 80039358C99E64A255D5E4E334C830FFEC8E0CBF2EB6030DE7DCE1A938821938 +Test: Encrypt +Comment: Set 2, vector 43 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000100000000000000000000000000000000000000000000000000000 +Ciphertext: E508D93429BBE95EE38672A2F653841701F391C68235391367F16415C2C84ADC +Test: Encrypt +Comment: Set 2, vector 44 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000080000000000000000000000000000000000000000000000000000 +Ciphertext: 710463874DF68B8930CC5CD6A00ABA2BCE27352997F2582EF472ED5F5AFE75A8 +Test: Encrypt +Comment: Set 2, vector 45 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000040000000000000000000000000000000000000000000000000000 +Ciphertext: E90AD04D26F4FF6D25D193CD2C34A2E1C6A1E570CCC705B873CACC94E61F79A7 +Test: Encrypt +Comment: Set 2, vector 46 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000020000000000000000000000000000000000000000000000000000 +Ciphertext: 8E19B69D55C9A2B2CCEACB50EC8007F39C81A0F261A8568D1298967C132BB790 +Test: Encrypt +Comment: Set 2, vector 47 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000010000000000000000000000000000000000000000000000000000 +Ciphertext: 4051E2FA9032676DC6E11CE947C64C9A0C0FC262AA41F40FA0C4093D1E4FA924 +Test: Encrypt +Comment: Set 2, vector 48 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000008000000000000000000000000000000000000000000000000000 +Ciphertext: 5DA6F415CCDF1A2D3335A0BEBB879D88CB9C871744111004C0E5AA6D27EB0311 +Test: Encrypt +Comment: Set 2, vector 49 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000004000000000000000000000000000000000000000000000000000 +Ciphertext: 684C24EC1DD06F6B565890190BE1F8BC7F4537CF5F9CF038ECB6D1D86164503A +Test: Encrypt +Comment: Set 2, vector 50 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000002000000000000000000000000000000000000000000000000000 +Ciphertext: 6D259C132726524987D4FD96C1ECD943D6B87BB98C61C4FFE41E282EC82F246A +Test: Encrypt +Comment: Set 2, vector 51 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000001000000000000000000000000000000000000000000000000000 +Ciphertext: 14707F80CC43E4E6321362B0ACFF84FE57E9D477B56637D01CAA09B232D726C5 +Test: Encrypt +Comment: Set 2, vector 52 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000800000000000000000000000000000000000000000000000000 +Ciphertext: FE98609B71F9CD65CD377C98BC4117EC8708E58D15361F9CAC02C64F0452B80D +Test: Encrypt +Comment: Set 2, vector 53 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000400000000000000000000000000000000000000000000000000 +Ciphertext: 1B78E77F935EBA86B28C9B37818245E2865AF84A73C9DAA735E42E6009AA07F3 +Test: Encrypt +Comment: Set 2, vector 54 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000200000000000000000000000000000000000000000000000000 +Ciphertext: F354ADD75ED9E121B1BFAD9483C6825AEF57BAA2DF08B519640E022E196B313F +Test: Encrypt +Comment: Set 2, vector 55 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000100000000000000000000000000000000000000000000000000 +Ciphertext: 7E0D7DCC0642CD5BF0C39460C4C183E5F321BCAB5EEA0AC7021E1AECE423E2A9 +Test: Encrypt +Comment: Set 2, vector 56 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000080000000000000000000000000000000000000000000000000 +Ciphertext: D1CCBD3EEA6ACF918569BEC2C900723B4359CA19C58E32ED65FDCBAA30A41C98 +Test: Encrypt +Comment: Set 2, vector 57 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000040000000000000000000000000000000000000000000000000 +Ciphertext: 361246D37645483C6D13C6500326694A0D577604CDF7CD36586B6C7F96FBE077 +Test: Encrypt +Comment: Set 2, vector 58 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000020000000000000000000000000000000000000000000000000 +Ciphertext: 0BC890CF369C233EDB99A51CEC75BFF60FB36BFB3EC15F253054F8865CB16DFF +Test: Encrypt +Comment: Set 2, vector 59 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000010000000000000000000000000000000000000000000000000 +Ciphertext: B5ED5183A00C882F8D213AFCE35C14E940407B7C2A8C9A5A19F289AED42DFAD7 +Test: Encrypt +Comment: Set 2, vector 60 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000008000000000000000000000000000000000000000000000000 +Ciphertext: 22B4EA3A5718D6CEE4EA78725F5BAC735C539C343D7B45121EDDA22CA39D9413 +Test: Encrypt +Comment: Set 2, vector 61 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000004000000000000000000000000000000000000000000000000 +Ciphertext: 94ECEC21BC3426C7214F266B6442F85B6AE765BD6206A951B2AA14505D19FBCA +Test: Encrypt +Comment: Set 2, vector 62 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000002000000000000000000000000000000000000000000000000 +Ciphertext: EF77932A5749126D65BD88330C18D91EDBB7FB53D7B3B675EE148EFC893559B9 +Test: Encrypt +Comment: Set 2, vector 63 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000001000000000000000000000000000000000000000000000000 +Ciphertext: BB9E132DC5DE8035433FBEAC46395E861BDA17A4892FFE6BD1B10D6B4D6AE0F3 +Test: Encrypt +Comment: Set 2, vector 64 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000800000000000000000000000000000000000000000000000 +Ciphertext: 7B536CF871F7FF406AD640683F405F0E14D72E77CDD2AB091D9A8E169155CE24 +Test: Encrypt +Comment: Set 2, vector 65 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000400000000000000000000000000000000000000000000000 +Ciphertext: 2417835AB4BD0A1D3439310480224C52796F3DB3536419F51A09551DFD4A6799 +Test: Encrypt +Comment: Set 2, vector 66 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000200000000000000000000000000000000000000000000000 +Ciphertext: 8E49C9819DFF2DEFCD8DF3E9EA910F79A9A932F43E4B763D6988CC0924C20544 +Test: Encrypt +Comment: Set 2, vector 67 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000100000000000000000000000000000000000000000000000 +Ciphertext: 1D364FDEFCB51560E4408CF25FC05E7698235D271E725590533CE24E3F3EC1EE +Test: Encrypt +Comment: Set 2, vector 68 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000080000000000000000000000000000000000000000000000 +Ciphertext: F1C0422AC64E4D566E799ADA6CE33B59C31051C55ED2212841460CE330F2763E +Test: Encrypt +Comment: Set 2, vector 69 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000040000000000000000000000000000000000000000000000 +Ciphertext: FA90883588183011F2748ADBC5217BA38CF6787FFD8BFCBEA06ADE193B1313C5 +Test: Encrypt +Comment: Set 2, vector 70 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000020000000000000000000000000000000000000000000000 +Ciphertext: 84EE69F947AEAAA0F1F2DA8C1508733D31F62FEBCF7085C68DEA5A602A566EBF +Test: Encrypt +Comment: Set 2, vector 71 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000010000000000000000000000000000000000000000000000 +Ciphertext: 260C06AB73B581E29C34FEE05363F532D4C693B5E8025291FC99C48F9CFCEFF8 +Test: Encrypt +Comment: Set 2, vector 72 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000008000000000000000000000000000000000000000000000 +Ciphertext: 98184C744C6A24B329A7827CE0F5B30AE709493A22F9064D1C3F7FED046D1C2A +Test: Encrypt +Comment: Set 2, vector 73 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000004000000000000000000000000000000000000000000000 +Ciphertext: 3CCDF1C3103B356E7A460410D91F1F00F749EB96F3E89F91248FB5E0949806EF +Test: Encrypt +Comment: Set 2, vector 74 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000002000000000000000000000000000000000000000000000 +Ciphertext: 49AB6245E93A6CF84BF66A7451D134535362CB8A8CE2E47012BF8B4EF02894D4 +Test: Encrypt +Comment: Set 2, vector 75 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000001000000000000000000000000000000000000000000000 +Ciphertext: 7A92C7BB97CB99AD15EA9DA3A629031901840D23EA4227C699944882E2E8F3CC +Test: Encrypt +Comment: Set 2, vector 76 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000800000000000000000000000000000000000000000000 +Ciphertext: 00FC7EBE56FCB696D9606FBBEEA6955871B7A03CDCAAE25DFC47D06145371AD3 +Test: Encrypt +Comment: Set 2, vector 77 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000400000000000000000000000000000000000000000000 +Ciphertext: FFF7327A979B527486052C1B99DECCFCC5E680D39613DE4107E8A04980DDFD70 +Test: Encrypt +Comment: Set 2, vector 78 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000200000000000000000000000000000000000000000000 +Ciphertext: 1E950B49D7D446867ED48272D220BCCC35B104A76A107880FB37D8AE55E69F58 +Test: Encrypt +Comment: Set 2, vector 79 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000100000000000000000000000000000000000000000000 +Ciphertext: 3B97EDED4E70497DAE02FD51E10AB26888096D2D182A7BC7EE55B6F3243E0144 +Test: Encrypt +Comment: Set 2, vector 80 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000080000000000000000000000000000000000000000000 +Ciphertext: 94414A0116665FFD8D1589B050A1663DBA15463206DA4E6A735B58FA7B4AA7ED +Test: Encrypt +Comment: Set 2, vector 81 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000040000000000000000000000000000000000000000000 +Ciphertext: D586FFCBBF32561B9659306068DD31C2A1FBC8DDF99CF0BDAB3DCC0664B403C7 +Test: Encrypt +Comment: Set 2, vector 82 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000020000000000000000000000000000000000000000000 +Ciphertext: 061E17DB1EAF9884C940B8C72E884C8D9D46819FDDF6724239168DDBEE170B9B +Test: Encrypt +Comment: Set 2, vector 83 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000010000000000000000000000000000000000000000000 +Ciphertext: D70F322E45E1D64B3D91249E9DE766DB7EF9084120C13D0215F31A6DE2E791C6 +Test: Encrypt +Comment: Set 2, vector 84 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000008000000000000000000000000000000000000000000 +Ciphertext: 5018967FCA5E67F24DCCE2190D24CD3E24A0B709B70DC38F1A4B4FE39CDCD2E5 +Test: Encrypt +Comment: Set 2, vector 85 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000004000000000000000000000000000000000000000000 +Ciphertext: 9108A0540D8D02658268185F06DFF6F2248681D0D9F9F4C6658942FC27C68246 +Test: Encrypt +Comment: Set 2, vector 86 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000002000000000000000000000000000000000000000000 +Ciphertext: 6595E74A5943DFE1A3FC19ADEBF190CDEC4C2EA0B7CCC6364E0AF7222CCEAA46 +Test: Encrypt +Comment: Set 2, vector 87 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000001000000000000000000000000000000000000000000 +Ciphertext: 5F156FB20AFD4BC0E4E4B2BA7700A38FFCAF9229E3CBA8C99915B692A76ACDEA +Test: Encrypt +Comment: Set 2, vector 88 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000800000000000000000000000000000000000000000 +Ciphertext: F0584D66033584791BED0EB67D2A73AA918E0F88F08683DC1F67DB7DD3375326 +Test: Encrypt +Comment: Set 2, vector 89 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000400000000000000000000000000000000000000000 +Ciphertext: 5EB0956E3DA8ECFC571D5BD1C4EF430FBB10117C6684B8530B6552B812780EBF +Test: Encrypt +Comment: Set 2, vector 90 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000200000000000000000000000000000000000000000 +Ciphertext: E8C8CB56ED63B5BA16DD833CC9C7AC77E425C284FFD547E8F9FE10410CA02FF3 +Test: Encrypt +Comment: Set 2, vector 91 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000100000000000000000000000000000000000000000 +Ciphertext: 68704A278A231ED468C1F0CFF43A4FC61253EACBE2BDCE1ED86D89F43263016D +Test: Encrypt +Comment: Set 2, vector 92 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000080000000000000000000000000000000000000000 +Ciphertext: CA16F899842EE79CBAC4D7CD67172C7DD537E6EA21D48C15B0B34B29BF87E79B +Test: Encrypt +Comment: Set 2, vector 93 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000040000000000000000000000000000000000000000 +Ciphertext: 9E6E7B31FF5D4D5C7D1C264273A27DA542BFCC6116B7DFDEF6332690B7304BDD +Test: Encrypt +Comment: Set 2, vector 94 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000020000000000000000000000000000000000000000 +Ciphertext: FE466983DED41AFB1908DF12A5532054C6DB320F0ECBDCE7610BBE2A07AA7F68 +Test: Encrypt +Comment: Set 2, vector 95 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000010000000000000000000000000000000000000000 +Ciphertext: D2D93C1B66FD710F8B72564A44ACA93995938FEE7C38DE482C9586E3413EB40C +Test: Encrypt +Comment: Set 2, vector 96 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000008000000000000000000000000000000000000000 +Ciphertext: 6623F853780833A60B60E6467CFA3D3D000228F2C8334F8B00CFE119133D41C7 +Test: Encrypt +Comment: Set 2, vector 97 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000004000000000000000000000000000000000000000 +Ciphertext: 1CED4727527E1C3107A89E77645241D240F3F113AC2BF8319E5D8EFF68997595 +Test: Encrypt +Comment: Set 2, vector 98 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000002000000000000000000000000000000000000000 +Ciphertext: FA450B3D8A7C03B643DF6EC70867D0502AE20235335AF5932A7016D71A6059A4 +Test: Encrypt +Comment: Set 2, vector 99 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000001000000000000000000000000000000000000000 +Ciphertext: A6F76AB74CE44538579369F5367B826C4EA72EB6EE08A0CFE1272EB435FDFEFC +Test: Encrypt +Comment: Set 2, vector 100 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000800000000000000000000000000000000000000 +Ciphertext: 8108B48A62A0E0CD58B066C10613E2B589CFB0BCEF4EB58BBF8C88E84A2CD258 +Test: Encrypt +Comment: Set 2, vector 101 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000400000000000000000000000000000000000000 +Ciphertext: F335D10835B018414786D30923663B77B2E0CA65423B96BFA885B9797138CF4F +Test: Encrypt +Comment: Set 2, vector 102 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000200000000000000000000000000000000000000 +Ciphertext: 87D8E75FEDA12025B9517BBF8421E837872E8978E48DA51BB8B8574C04731091 +Test: Encrypt +Comment: Set 2, vector 103 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000100000000000000000000000000000000000000 +Ciphertext: B8A50E6EDFF9711C6064812423F5DC5D77970BE65B545C042A02BACB30A4CD6F +Test: Encrypt +Comment: Set 2, vector 104 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000080000000000000000000000000000000000000 +Ciphertext: EB98815E5A9337DF35F98D7CF27183EC8423D5F9D145326638B864E0F994DD7D +Test: Encrypt +Comment: Set 2, vector 105 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000040000000000000000000000000000000000000 +Ciphertext: 3E5DDB36ABD739986483DE7A9EEF2468461A02B55CAA24100394442F0946F337 +Test: Encrypt +Comment: Set 2, vector 106 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000020000000000000000000000000000000000000 +Ciphertext: 809F726C3BB19BD09D4412B64777085D968ED4E612286008C4BAC69F671E7E31 +Test: Encrypt +Comment: Set 2, vector 107 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000010000000000000000000000000000000000000 +Ciphertext: 28F2EE8D382DF1AB0CF82B93C7A09B87180E8D19C35657302EFE1B1C4CA11ED4 +Test: Encrypt +Comment: Set 2, vector 108 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000008000000000000000000000000000000000000 +Ciphertext: 76E6887FC464215C9576BB233F5A3A7D98CA73F9B2D06E3BB81BC34AF02C8CE9 +Test: Encrypt +Comment: Set 2, vector 109 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000004000000000000000000000000000000000000 +Ciphertext: E8CEF712D7AF841C4FE7800CB04C27E25BDB41BECFA894588F73776CAAE2A0FA +Test: Encrypt +Comment: Set 2, vector 110 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000002000000000000000000000000000000000000 +Ciphertext: 868D3A678A216D01A765046E2991A21F9626493063AFE771E3369E5DA2BA7E9B +Test: Encrypt +Comment: Set 2, vector 111 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000001000000000000000000000000000000000000 +Ciphertext: D6465061FA1B143E1F6A3FCC1601D2D9FAEEF995C457E9EE301A27E8139D1AFE +Test: Encrypt +Comment: Set 2, vector 112 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000800000000000000000000000000000000000 +Ciphertext: B42BB57D2F25612AAB33EF3213D6D210D9831502A1C4D51C4E72148CBB9893D1 +Test: Encrypt +Comment: Set 2, vector 113 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000400000000000000000000000000000000000 +Ciphertext: CE0EC3C44BFAABE6E18B3506E01199B0F2E0BCA4EA6C29D367EDDD0E83A1C65F +Test: Encrypt +Comment: Set 2, vector 114 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000200000000000000000000000000000000000 +Ciphertext: 627101F50E134D6F33EF70AF0E32A3AF7C3237E3A5D99319719F175DD0392383 +Test: Encrypt +Comment: Set 2, vector 115 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000100000000000000000000000000000000000 +Ciphertext: CBCC83BE624059BD8B950BCF486AFBC342CF3575EBA6950FB39C03DB4822EDD9 +Test: Encrypt +Comment: Set 2, vector 116 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000080000000000000000000000000000000000 +Ciphertext: 5EAD7961798903C315DD89BE57105FEA164CA06A4ECDBB5CB10B76711C3E49A0 +Test: Encrypt +Comment: Set 2, vector 117 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000040000000000000000000000000000000000 +Ciphertext: 69169E6E11EAC935E12E6E30EFCEDD7236EAED9C5E1E3B215CD7167AB88B199D +Test: Encrypt +Comment: Set 2, vector 118 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000020000000000000000000000000000000000 +Ciphertext: 5B08F07728399920CA30DC57CE94CAE85A44530033B2AE6BB7F8E29D7934C437 +Test: Encrypt +Comment: Set 2, vector 119 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000010000000000000000000000000000000000 +Ciphertext: 8FAD35B4FBC3BBAB2F4BF00D8A1651BE3FD77085AC5E6C7F6E2EDF5048F86068 +Test: Encrypt +Comment: Set 2, vector 120 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000008000000000000000000000000000000000 +Ciphertext: 71B22D911D9E754A76EC052CD7DC503CDE9A16E9043A04CFA244D8EB19FC21AA +Test: Encrypt +Comment: Set 2, vector 121 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000004000000000000000000000000000000000 +Ciphertext: 062A10B7F5E3E8D7F3FC2C14E10EC9CA947A8FDC0EBC01E3A127BAFE689D6577 +Test: Encrypt +Comment: Set 2, vector 122 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000002000000000000000000000000000000000 +Ciphertext: 0FC375F0F68567F1827C7218132B434E84DA6377DB50AB330E8D9BD2754BD1B8 +Test: Encrypt +Comment: Set 2, vector 123 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000001000000000000000000000000000000000 +Ciphertext: 0E4C1117D462EEBCF5FCD7AC9807AF40C403910421CD19A4634B1C86113EB387 +Test: Encrypt +Comment: Set 2, vector 124 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000800000000000000000000000000000000 +Ciphertext: A9DB2CD2A23780D8BC5A2567961BCA24A41531157D4A229046B47DE48CAE0FDD +Test: Encrypt +Comment: Set 2, vector 125 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000400000000000000000000000000000000 +Ciphertext: 7195678F00F98B00706E7C497E5FA2BC648EDA00B4B7DFAC6234C8232DF8E071 +Test: Encrypt +Comment: Set 2, vector 126 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000200000000000000000000000000000000 +Ciphertext: E5C1970C7C0B8E7E1BF871219486359C2E5037BE6E8E637BDB9F11051FB36A16 +Test: Encrypt +Comment: Set 2, vector 127 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000100000000000000000000000000000000 +Ciphertext: 2426496DC3B09404B609157E2273D526C3E6909B82F65527B42ABDD6348CF602 +Test: Encrypt +Comment: Set 2, vector 128 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000080000000000000000000000000000000 +Ciphertext: F9870238947E1575AF11D14D12E593163B98BA12E79F05563CBFFBCFB23FDC38 +Test: Encrypt +Comment: Set 2, vector 129 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000040000000000000000000000000000000 +Ciphertext: 2B1E410ACE9E8875F965A29D90773B68CAC452AE98CEB5922B7BAD936ACC421B +Test: Encrypt +Comment: Set 2, vector 130 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000020000000000000000000000000000000 +Ciphertext: 180285A7AD7DD8FFD619970804F0FDB9706D5F5C467F815D0B1A455DED9D9300 +Test: Encrypt +Comment: Set 2, vector 131 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000010000000000000000000000000000000 +Ciphertext: BAEB5C1C68D72F1AE4735F6B75CDF9265E4F6F55DA934C4F118A3728AA2BC0D5 +Test: Encrypt +Comment: Set 2, vector 132 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000008000000000000000000000000000000 +Ciphertext: 9DEBFCC984F55E97C0064335C8A4B7489B7BDD75560EA51982114FCE4D481032 +Test: Encrypt +Comment: Set 2, vector 133 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000004000000000000000000000000000000 +Ciphertext: DF3B0B54DF4D1814A6F46B8F8B37E27AE8B9EC54B97BF9C523F1EC713EDDFFEE +Test: Encrypt +Comment: Set 2, vector 134 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000002000000000000000000000000000000 +Ciphertext: 37AA04C74A1E8ED165BC1B4C97265A32B5579D9B2A7B7C883A98B616D5C24FAE +Test: Encrypt +Comment: Set 2, vector 135 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000001000000000000000000000000000000 +Ciphertext: 83815356746186AE4CC327AB3A8CE04EF66ABD32D44D7089F1D7E301BFE006D6 +Test: Encrypt +Comment: Set 2, vector 136 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000800000000000000000000000000000 +Ciphertext: 2C6C7878E099F55653CA784A0BE4C9EC6201AFDCF99CDDC1ED862D4FE88CFDC8 +Test: Encrypt +Comment: Set 2, vector 137 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000400000000000000000000000000000 +Ciphertext: 424804513D38537C024955F2CCB29BECFD801FC06CD8EC5DE353872F0B50616F +Test: Encrypt +Comment: Set 2, vector 138 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000200000000000000000000000000000 +Ciphertext: 48C31A55ED4716825D43FF671C01A86CDD792AABF78703ADC58F5FD65B3C0DE1 +Test: Encrypt +Comment: Set 2, vector 139 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000100000000000000000000000000000 +Ciphertext: BF99E4263F2C512CDE33A91E04FACA55052444E40FF79F09716FC06D24FDDE1D +Test: Encrypt +Comment: Set 2, vector 140 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000080000000000000000000000000000 +Ciphertext: 1A40488BA16A5D0AE6381018F15ABF95C78FB05867E3D7E213CAD7BA3DC9EA3B +Test: Encrypt +Comment: Set 2, vector 141 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000040000000000000000000000000000 +Ciphertext: BEAD8979A1A485959C3E9C8BF9CCF7CF850EB205296E1E8FF8BCAFBB011FF21D +Test: Encrypt +Comment: Set 2, vector 142 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000020000000000000000000000000000 +Ciphertext: A8EDCC85F5A941B4434BD4DAD5E39EEAD102DA25BBB2C3D143572AC7425ED819 +Test: Encrypt +Comment: Set 2, vector 143 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000010000000000000000000000000000 +Ciphertext: 631126B3A837AA4C999EFE6A687BBA58751464A6395670213C8445CC8409C33F +Test: Encrypt +Comment: Set 2, vector 144 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000008000000000000000000000000000 +Ciphertext: CA4A5FD3A3D2DA973E16C0A849E374C5A293351A66415B45107BD228CB842B19 +Test: Encrypt +Comment: Set 2, vector 145 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000004000000000000000000000000000 +Ciphertext: A61FDF733DDEC4C3AE51BE778BDD6E34BED64449ABCA7A718EAA513A2A5A9014 +Test: Encrypt +Comment: Set 2, vector 146 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000002000000000000000000000000000 +Ciphertext: 2C632530E7FCD550B5F9D14E21409AFD07C7E1FBF04B3B3FEC8C61AC8A1591ED +Test: Encrypt +Comment: Set 2, vector 147 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000001000000000000000000000000000 +Ciphertext: B2D97A1D343D3D5E1A7E444BA6E57D2E5ED42E02F719ECA22BA47E796AB37B18 +Test: Encrypt +Comment: Set 2, vector 148 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000800000000000000000000000000 +Ciphertext: AC515AAC675C2C3E46A8F77578189149327413CF40B48E16BF83D3500C2B1355 +Test: Encrypt +Comment: Set 2, vector 149 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000400000000000000000000000000 +Ciphertext: C8ADC6079B92459A8E975FFFE2352A90629CF9E8D53630536D9EBC7DAC4C467E +Test: Encrypt +Comment: Set 2, vector 150 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000200000000000000000000000000 +Ciphertext: 97B2C40964B25AE5CBD092E36B37A3BB4520570A9920034C584C66600D3857D9 +Test: Encrypt +Comment: Set 2, vector 151 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000100000000000000000000000000 +Ciphertext: 99A017D3829CEFE10DDD33D33F53EA470A2A74A35ED3BED8B7E9D6EF3B790153 +Test: Encrypt +Comment: Set 2, vector 152 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000080000000000000000000000000 +Ciphertext: 6141854199F9E01CFE4A35DF918B805985ACC8F8A7456FFBF91D27D4E85E4C49 +Test: Encrypt +Comment: Set 2, vector 153 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000040000000000000000000000000 +Ciphertext: 28BC7571E7C921B31BC2D7BF55853C2CC5B815B39471907DAE152F685791378B +Test: Encrypt +Comment: Set 2, vector 154 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000020000000000000000000000000 +Ciphertext: AD751D4D9D635900C22B6166328ECD85FB4A1610D055793BF04A83CB6F5F02DB +Test: Encrypt +Comment: Set 2, vector 155 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000010000000000000000000000000 +Ciphertext: 8670009356A0A3BD402CF218664826C05BE1651C6E606C011967F8F9C3835017 +Test: Encrypt +Comment: Set 2, vector 156 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000008000000000000000000000000 +Ciphertext: 6CE35F565BC4F38D73116267C49D345B7B19D57D5C90136CAF512F76AF47FAAD +Test: Encrypt +Comment: Set 2, vector 157 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000004000000000000000000000000 +Ciphertext: FD0DF28AFE47414F99219AD120F33DCA6F8756B2264349911041B0AEC9D77A43 +Test: Encrypt +Comment: Set 2, vector 158 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000002000000000000000000000000 +Ciphertext: 49CE284D7A18A0608E5E3768286E919DE97DD81B369AB0A012AD7BDC491DED1A +Test: Encrypt +Comment: Set 2, vector 159 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000001000000000000000000000000 +Ciphertext: 12B27FEC757A809C68F670698E5CB40E762855022FC12DE2332DB9814FC6E5E2 +Test: Encrypt +Comment: Set 2, vector 160 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000800000000000000000000000 +Ciphertext: 53074884476D09C729F35C3906046C2DCBA7F12BF59CDD3CE73ABF91847C6369 +Test: Encrypt +Comment: Set 2, vector 161 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000400000000000000000000000 +Ciphertext: D29E3C55DD3D867D7263D2C961FDB6A97B8D827AB73A20479ACB06DF992AEC24 +Test: Encrypt +Comment: Set 2, vector 162 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000200000000000000000000000 +Ciphertext: 4BE421463C6F2CC8118A50684EB5FC98323EA27F03D4B98EC05727BA0FFA40E8 +Test: Encrypt +Comment: Set 2, vector 163 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000100000000000000000000000 +Ciphertext: A96EC7F07298F9D86A811D0110D60E65C80F3E913B575831A5E8533932196B24 +Test: Encrypt +Comment: Set 2, vector 164 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000080000000000000000000000 +Ciphertext: F12B579997BA4203D8A0FF36181E4C1B50C703FE32CF18D9BF84355BC404D135 +Test: Encrypt +Comment: Set 2, vector 165 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000040000000000000000000000 +Ciphertext: 35EBB3FE5FACC9B9D321E82A73C344CA05D0E73372579349A1F365DEA0105292 +Test: Encrypt +Comment: Set 2, vector 166 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000020000000000000000000000 +Ciphertext: 0F1F0518D57ADC91D810B5899EB7EE7900D05AD8AD2960FE07893F30859B636F +Test: Encrypt +Comment: Set 2, vector 167 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000010000000000000000000000 +Ciphertext: A6CAF97EF17BEFDCF3412D7F45F72C1F1726198ED3B5CD905DF9078DCD70F882 +Test: Encrypt +Comment: Set 2, vector 168 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000008000000000000000000000 +Ciphertext: E287019353E8C71C62178B3AF7A3ECA210D79F803F43C09B6C08F295367A30CA +Test: Encrypt +Comment: Set 2, vector 169 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000004000000000000000000000 +Ciphertext: CF7A7ECEA347875A7B9191BF9FFDC3FB53512052FA42370E39BF5D906EE82D4E +Test: Encrypt +Comment: Set 2, vector 170 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000002000000000000000000000 +Ciphertext: 7E362B5B5ED5CAB9A518320E498FDB915BFD72BB5C588495AC49FC2D5CEC2134 +Test: Encrypt +Comment: Set 2, vector 171 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000001000000000000000000000 +Ciphertext: 69254195C6A9A4D334F8F0558A6C9635EB8A397E5AB672E81DC194AFA5C3A8B7 +Test: Encrypt +Comment: Set 2, vector 172 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000800000000000000000000 +Ciphertext: 3934A6BA3DE9885771111CBA59D50EC684F8F612AAAE3E511C0A211D972723C4 +Test: Encrypt +Comment: Set 2, vector 173 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000400000000000000000000 +Ciphertext: BCEE40ADD3CFDE924F58786640A56A68FE83615EDD82873DF6908057AF39F74A +Test: Encrypt +Comment: Set 2, vector 174 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000200000000000000000000 +Ciphertext: 70F4E0381A989C486A45FAE5B108373E950843EE48DC2A43E7AA625BF3AC9838 +Test: Encrypt +Comment: Set 2, vector 175 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000100000000000000000000 +Ciphertext: FAED24C44DE7F447CD1169F4D8D734E55154B73F79B31AD1CD310C7F5529433A +Test: Encrypt +Comment: Set 2, vector 176 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000080000000000000000000 +Ciphertext: 887BA60DED98C75DADDC1CD0824E7E6C76D947617A919A3B870B489CD1B7F6B2 +Test: Encrypt +Comment: Set 2, vector 177 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000040000000000000000000 +Ciphertext: 33D833FFDB7BEB6BBAB4DDACA6784B88C4B76A49641AA01BC980AB31084F4351 +Test: Encrypt +Comment: Set 2, vector 178 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000020000000000000000000 +Ciphertext: 8CDEF08AB44C2CB2AB5EC94437E501A96999B30C045A79DE99E220595B95DA2F +Test: Encrypt +Comment: Set 2, vector 179 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000010000000000000000000 +Ciphertext: 029247C8EC0610E7F5B49FA4191E99CDECBC1E44DF123270901A57DE8ED64850 +Test: Encrypt +Comment: Set 2, vector 180 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000008000000000000000000 +Ciphertext: 08487E1E53C677CA34640459BDBF7C53247DD54624B9C2156A59F24A818A258E +Test: Encrypt +Comment: Set 2, vector 181 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000004000000000000000000 +Ciphertext: 2C7C0444738DB202D9236CF00E1B75F579E18CAD4341093675F66732746F8060 +Test: Encrypt +Comment: Set 2, vector 182 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000002000000000000000000 +Ciphertext: F493AF90C19A9EA6460AE35418D4857236D678B570352665092854CFF9FB684E +Test: Encrypt +Comment: Set 2, vector 183 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000001000000000000000000 +Ciphertext: 4575CF8865954F9FDCC9C2F7A41BFD52B1C770E2C7609151E41D9B1D0489500C +Test: Encrypt +Comment: Set 2, vector 184 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000800000000000000000 +Ciphertext: BA0606FA831D4EF759CF457F88B0EEDFDF13BD3ABF72547456052C877B9E3A3B +Test: Encrypt +Comment: Set 2, vector 185 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000400000000000000000 +Ciphertext: 10E979D310CAD332AA3DC860EF69B2BBD96E817BFB93393AD4D8B141C0A301E4 +Test: Encrypt +Comment: Set 2, vector 186 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000200000000000000000 +Ciphertext: B46DE2A7729FAF7CEE978353D4392EA23FE1BB36732D101377C603125125FE62 +Test: Encrypt +Comment: Set 2, vector 187 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000100000000000000000 +Ciphertext: F03E1B911C1EDD769CAD59A744FAD47CB5E19502C1E7F4F0B3197101F3B673C1 +Test: Encrypt +Comment: Set 2, vector 188 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000080000000000000000 +Ciphertext: A9128F8B0C1809095597110471DD7F10040AE71626E8C694BA529B4C9E1353A2 +Test: Encrypt +Comment: Set 2, vector 189 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000040000000000000000 +Ciphertext: B9EDCD81B2CFB461C1FC554ED71CCC958AF4B2B726C011173F4058C40211C496 +Test: Encrypt +Comment: Set 2, vector 190 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000020000000000000000 +Ciphertext: 400F0635E34B796116E3752A0EDA47C3ABC19641DDD60427B4CE3AA8700CEA8E +Test: Encrypt +Comment: Set 2, vector 191 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000010000000000000000 +Ciphertext: 0E526F1012B80F22F946FD51D776187DEFD554B1F5806102E7DD9277FE06B826 +Test: Encrypt +Comment: Set 2, vector 192 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000008000000000000000 +Ciphertext: 1FC0DA71F72D08CDD0F59120C4A88E793869A2C598BAB97C92D6C63C0FAEADA9 +Test: Encrypt +Comment: Set 2, vector 193 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000004000000000000000 +Ciphertext: C493FDECD4D49D5FC6D8590C70BEAAD97EB7694244201CA4CF1732E03D7A4251 +Test: Encrypt +Comment: Set 2, vector 194 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000002000000000000000 +Ciphertext: C532BFE04C6CA7E8B4ABFF9E8BD9C676CBC9AA78FEF4A2DC5CC907742B3ED64F +Test: Encrypt +Comment: Set 2, vector 195 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000001000000000000000 +Ciphertext: 5C8F3ECB07F0264162A9C01A6BB2BC5CF3C7B9ED315803BF86A72406C2655242 +Test: Encrypt +Comment: Set 2, vector 196 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000800000000000000 +Ciphertext: 8C13C039C13DF9C8D821D33E85AFE93EEAFCFC2A2F06D85B3BDE2743FC37AD3F +Test: Encrypt +Comment: Set 2, vector 197 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000400000000000000 +Ciphertext: 3D990835001730714D0880420F57041E37A7FAF1FCA991AA38C409C80F2DC61F +Test: Encrypt +Comment: Set 2, vector 198 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000200000000000000 +Ciphertext: EC44357D4F18EBE148B47AB546D6A5F3E08F8F6C9E2B8B6B99FF303814BF43BA +Test: Encrypt +Comment: Set 2, vector 199 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000100000000000000 +Ciphertext: 00C3B30C81FBC65B9E12C8D6429104FDF40D322D47A59E637FC8CE749725BDCC +Test: Encrypt +Comment: Set 2, vector 200 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000080000000000000 +Ciphertext: 6136C065D96E7F18AB296F86AF04BB264A6DA61DEA7C5413C9131B7EBE551B88 +Test: Encrypt +Comment: Set 2, vector 201 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000040000000000000 +Ciphertext: 2A363A08CAD79DF6A3F2DF5D842B14935C5D09C9D6C78C4989ADCB018A735A5D +Test: Encrypt +Comment: Set 2, vector 202 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000020000000000000 +Ciphertext: B25955B31CC449A42502D1AB61D699DE558BA2C7825BA06B17B239851E575880 +Test: Encrypt +Comment: Set 2, vector 203 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000010000000000000 +Ciphertext: CBE2FD81D74436E167D6A5CF8F7DC07338885146351483E4474CD213D853A6FE +Test: Encrypt +Comment: Set 2, vector 204 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000008000000000000 +Ciphertext: 66DE9DCBF2B85FF944EDD40B3D81F5F8699DB1982C045667FDE9A499A7777DD6 +Test: Encrypt +Comment: Set 2, vector 205 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000004000000000000 +Ciphertext: D940E3F69C42E847312E473E362FD609BE7780D99DAC30F8F095D58EFDC58D59 +Test: Encrypt +Comment: Set 2, vector 206 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000002000000000000 +Ciphertext: 60FBA04239A8C312E10C7773673E94678CB1E13B069759AF304C56CCA6F490DD +Test: Encrypt +Comment: Set 2, vector 207 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000001000000000000 +Ciphertext: D67E081F763F322BA82FA01E184C355A65DE8028E47BF0DB5FCAEDA8C2593F02 +Test: Encrypt +Comment: Set 2, vector 208 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000800000000000 +Ciphertext: 434868F9A6086D0F9218E02CB9534E9EEE88B90C6174A4306B0D0843A35CFDFD +Test: Encrypt +Comment: Set 2, vector 209 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000400000000000 +Ciphertext: B6CCB5899745E29FEE7870B22C2F989D84C98C4510DEA892666E187CDEF77E1A +Test: Encrypt +Comment: Set 2, vector 210 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000200000000000 +Ciphertext: E798F9255A21E0ECDC4BA638F0BF03BAA0AD7810844837582193D7FB3E11B5DF +Test: Encrypt +Comment: Set 2, vector 211 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000100000000000 +Ciphertext: 9BAE51C5C4DF9E55570EF0FE5F2C6AC0CF9FD953E65CD07ED12378BD5A0F2911 +Test: Encrypt +Comment: Set 2, vector 212 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000080000000000 +Ciphertext: 95ECC45EEDD4537D6A7D54D60A64CBFB6728982441C7EE10B7A84A80B51EE171 +Test: Encrypt +Comment: Set 2, vector 213 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000040000000000 +Ciphertext: D8D77750B38E522216DA0A1A9DB7C56788E504708A2048B66946FB83C1981FCB +Test: Encrypt +Comment: Set 2, vector 214 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000020000000000 +Ciphertext: 0CAA8435D051798DB289708EC6CC4C98F0018AB7F068FA0E40443A1F227002CD +Test: Encrypt +Comment: Set 2, vector 215 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000010000000000 +Ciphertext: 5410408C0306460E6033543669A26A63F7C7BBDFEF4273C9BAD8AC472EDAFB67 +Test: Encrypt +Comment: Set 2, vector 216 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000008000000000 +Ciphertext: DD3A0F7B61D056015B54A329882E942ECA3C5C3F64ACFE71E3255A8F53E1AD73 +Test: Encrypt +Comment: Set 2, vector 217 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000004000000000 +Ciphertext: 80A70BE4CC4C61C0F7F501E8068C75CEA78DC11A224D0C47C09D20361C99CF00 +Test: Encrypt +Comment: Set 2, vector 218 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000002000000000 +Ciphertext: BEF3417464A46BBD2B7E9FB967F4FBF406C2B5B9C8B076B770C199C003786A40 +Test: Encrypt +Comment: Set 2, vector 219 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000001000000000 +Ciphertext: C1756ADF6EEF9837B43C4B032B17A79C3A583EE37981CC495CA95893F34218A6 +Test: Encrypt +Comment: Set 2, vector 220 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000800000000 +Ciphertext: 90273FCA31968871BE3D5C76AFCB47D9ECC31A48B87988FD359E93AFF6815F4D +Test: Encrypt +Comment: Set 2, vector 221 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000400000000 +Ciphertext: D0A5F666F7A819EF8BA114C1872158179731F6989997E13AFD73DB252E5CD2A2 +Test: Encrypt +Comment: Set 2, vector 222 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000200000000 +Ciphertext: D4E3DA34C47E5A86A723ED5B9F615B283E4CD54E9F2ED9EAA98A7AB8DE41B14C +Test: Encrypt +Comment: Set 2, vector 223 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000100000000 +Ciphertext: 547227D086EBB538F5836B8E1E65601209AEB6DFD1C450C014C559D879D71862 +Test: Encrypt +Comment: Set 2, vector 224 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000080000000 +Ciphertext: 9E52F033EFE0762ED108095BDF6CD8A89F8E1028F0D3D9B39B601C1084F95F74 +Test: Encrypt +Comment: Set 2, vector 225 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000040000000 +Ciphertext: A049C5B9BD63EBEB23B34EA2F27813D29EDC044E2486D709AC7D2C731557066B +Test: Encrypt +Comment: Set 2, vector 226 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000020000000 +Ciphertext: 1A9CDD2A99C5ED7FB2A6A1870230B0BD6890567E0E4439E248548DF25CB6126E +Test: Encrypt +Comment: Set 2, vector 227 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000010000000 +Ciphertext: 41F2CDA0EFE97BCE8689CF33201B4E57E0600BBB1F274DF3D589915F8EA5C372 +Test: Encrypt +Comment: Set 2, vector 228 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000008000000 +Ciphertext: 1F4712D7AB6D127ABDA90DA977CFC60B44F84859AE4B705851CF687E01E1E250 +Test: Encrypt +Comment: Set 2, vector 229 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000004000000 +Ciphertext: DC93D915CBBC140EDB08B34406F71B4CD38274E92DE8FAF355D274AE7929BC28 +Test: Encrypt +Comment: Set 2, vector 230 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000002000000 +Ciphertext: D2D9A648EDAF9339D7EE52419CC33C42E4CA91AA670D14B78952F41F889122E5 +Test: Encrypt +Comment: Set 2, vector 231 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000001000000 +Ciphertext: F34BA77405D00CAFC3E6786CDB26263C10CDC4D6AFAEDF4C26566A51DB82F5F9 +Test: Encrypt +Comment: Set 2, vector 232 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000800000 +Ciphertext: 21A7EAD6D95FC7AB788206CEA15A25CC4AEB69BAA96C78D5E2851DDBA25523F0 +Test: Encrypt +Comment: Set 2, vector 233 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000400000 +Ciphertext: 822BC3900195E6F224805E77B2460A65FA1A11CFD473F1DFA65351CBB4EFDFEB +Test: Encrypt +Comment: Set 2, vector 234 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000200000 +Ciphertext: 648A71BE1E77866181F980B37690D5C8A37DF29BB2EBC3A41665CD0CCC2E8EF8 +Test: Encrypt +Comment: Set 2, vector 235 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000100000 +Ciphertext: 808E32C933955FF7C8D6F1A4C6754CB3B7311612CFF846D02C81B712C78EB63E +Test: Encrypt +Comment: Set 2, vector 236 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000080000 +Ciphertext: E074251CC7C5BFFCE2CA45933206B2EE8864156A4626C03EA030B71F8BD454BE +Test: Encrypt +Comment: Set 2, vector 237 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000040000 +Ciphertext: 72EBE213A06F63603B49A750808F348FF7C9E4EC72884FDA7C58968EC5A25EED +Test: Encrypt +Comment: Set 2, vector 238 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000020000 +Ciphertext: 20618612C2AF418DE3E185AF7973D508DC31DE1E9D9FB4FDF9E95FD592F567EF +Test: Encrypt +Comment: Set 2, vector 239 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000010000 +Ciphertext: F94C66D4884A657BF0A6A6EA31A90A07F193F55465575FF1BF8DE68F3441BF4E +Test: Encrypt +Comment: Set 2, vector 240 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000008000 +Ciphertext: 9636DCAB40FB991FC330D8EFD671FF83BAA0C9E33D7A146D5E7ADC53592B605F +Test: Encrypt +Comment: Set 2, vector 241 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000004000 +Ciphertext: FC21689B5F46A011ECFE1E314E03ED7105BAC620193714B2290087C17FB763B6 +Test: Encrypt +Comment: Set 2, vector 242 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000002000 +Ciphertext: ABD2583E0FCC95122FDC700AF9B1FDA50D91E752E19BE9D2EE4F5E22033D53C6 +Test: Encrypt +Comment: Set 2, vector 243 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000001000 +Ciphertext: 3501CD56EE5EA39AB32F38371E5C2CF6EEEB9DA82D210A8D88AE8F29917AE9F4 +Test: Encrypt +Comment: Set 2, vector 244 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000800 +Ciphertext: 7559A2AA6CBFA8A181565EDDDE323DB80CE740545FFEE13B4851980AD2451E24 +Test: Encrypt +Comment: Set 2, vector 245 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000400 +Ciphertext: CEF6DBFD1FBCCBB587BD748D6CC992F8EF671A829E2D6AD73D1DC1C1B2A9E8DD +Test: Encrypt +Comment: Set 2, vector 246 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000200 +Ciphertext: 46FBBCD26A1F879746BDF4FF7804A5C105F621837ABCF94F17123B700A58A08A +Test: Encrypt +Comment: Set 2, vector 247 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000100 +Ciphertext: 0B10D2DA0E0FB6F067D641FF7F8C9C8FF4E2D689450787B7136ADF38DC1F2948 +Test: Encrypt +Comment: Set 2, vector 248 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000080 +Ciphertext: 4492E09E73459BF74417FC0D7190DA719A891C9CAE14801944FFB24912E377A8 +Test: Encrypt +Comment: Set 2, vector 249 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000040 +Ciphertext: 76D72C3D3AF6F2FF6AFBC0C1A553E6F8171D81D6BB1CB3C3A6C43ED826A88FAA +Test: Encrypt +Comment: Set 2, vector 250 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000020 +Ciphertext: D912041134584B69AC01938EC88913DBCFF7CDBE93CDF7443BD465F1B2E3F7F5 +Test: Encrypt +Comment: Set 2, vector 251 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000010 +Ciphertext: F0883EB64A5345CC9A0055D4E882D199EFFC334C05B53BC4132AC1A51BA39A9F +Test: Encrypt +Comment: Set 2, vector 252 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000008 +Ciphertext: 276246B0D93A4E6FF05832F51D2BF60641B63594EB90A1E08A7D98C6DDAE1461 +Test: Encrypt +Comment: Set 2, vector 253 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000004 +Ciphertext: 6AA2B04BF65F4213583CED5347537123DC3BE0703209170D1D34B0B8A66C1C58 +Test: Encrypt +Comment: Set 2, vector 254 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000002 +Ciphertext: DC438414927E453DBFD91DC60C635EE4273A9921A134DB513AB2BBDBAE64A9AD +Test: Encrypt +Comment: Set 2, vector 255 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000001 +Ciphertext: 45D43E9288738C5AD1A683D8DE59CEDD22D666A2B7078EB1301B532A272D570B +Test: Encrypt +Comment: Set 3, vector 0 +Key: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Plaintext: 0000000000000000000000000000000000000000000000000000000000000000 +Ciphertext: 7CA51614425C3BA8CE54DD2FC2020AE7B6E574D198136D0FAE7E26CCBF0BE7A6 +Test: Encrypt +Comment: Set 3, vector 1 +Key: 01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101 +Plaintext: 0101010101010101010101010101010101010101010101010101010101010101 +Ciphertext: C4B7C6A9738C77EE28F7E685C8358E0AF88FB6D23955EE6DF49FE3F5DA16F826 +Test: Encrypt +Comment: Set 3, vector 2 +Key: 02020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202 +Plaintext: 0202020202020202020202020202020202020202020202020202020202020202 +Ciphertext: CD108DD9EC1000B79C75AA3DCC88F913E6F52773853035A5C44F3245B134CBFF +Test: Encrypt +Comment: Set 3, vector 3 +Key: 03030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303 +Plaintext: 0303030303030303030303030303030303030303030303030303030303030303 +Ciphertext: E8F9DE8F066B675AE90C919FC4981603485BBB92382D8C844CAF707973D5276D +Test: Encrypt +Comment: Set 3, vector 4 +Key: 04040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404 +Plaintext: 0404040404040404040404040404040404040404040404040404040404040404 +Ciphertext: 6AA777340200C1B65AB25193A8BB267C233DAC7E1B3C523D406FC5B567B7B586 +Test: Encrypt +Comment: Set 3, vector 5 +Key: 05050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505 +Plaintext: 0505050505050505050505050505050505050505050505050505050505050505 +Ciphertext: 6B14A9C454143376DBDC3C93FB8096B09C01456B0B55412FD9692CD7CB587069 +Test: Encrypt +Comment: Set 3, vector 6 +Key: 06060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606 +Plaintext: 0606060606060606060606060606060606060606060606060606060606060606 +Ciphertext: 3FED53DEF4FBC1D012B36562132AB40049818DA4E62E86716DE5EF70790B0D6A +Test: Encrypt +Comment: Set 3, vector 7 +Key: 07070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707 +Plaintext: 0707070707070707070707070707070707070707070707070707070707070707 +Ciphertext: 7A428F7A6841BC8F0E99335C5021C413D2639321DC8D9F280A2F0EF4B420A212 +Test: Encrypt +Comment: Set 3, vector 8 +Key: 08080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808 +Plaintext: 0808080808080808080808080808080808080808080808080808080808080808 +Ciphertext: A23BE32D37FA4054EC45D6A9CC643AF9124EDAA4AD9ABC7FAAB449D39D11B128 +Test: Encrypt +Comment: Set 3, vector 9 +Key: 09090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909 +Plaintext: 0909090909090909090909090909090909090909090909090909090909090909 +Ciphertext: 972195D6756F7D3A4D13BF49BFBCE7D164460355150C297A41CCC6AA9F31C5D6 +Test: Encrypt +Comment: Set 3, vector 10 +Key: 0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A +Plaintext: 0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A +Ciphertext: 2AA722C58EBDB7701225BA9C3B1F7C946D57DEDC74FEDDB637EB14E27A0F0CC9 +Test: Encrypt +Comment: Set 3, vector 11 +Key: 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +Plaintext: 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +Ciphertext: 1C9A0420B9F6EF013FB3ADB4F20C862B61702BA479276E3187322B33D4B128C2 +Test: Encrypt +Comment: Set 3, vector 12 +Key: 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C +Plaintext: 0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C +Ciphertext: 666CC3862BAACADA4D35A9079D52438FB3B4416C9938397E61D48066B6476068 +Test: Encrypt +Comment: Set 3, vector 13 +Key: 0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D +Plaintext: 0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D +Ciphertext: DB94504EF884901FAA5778199329A2DCC9AA50A4453172CE8ADE11BFE54234E9 +Test: Encrypt +Comment: Set 3, vector 14 +Key: 0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E +Plaintext: 0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E +Ciphertext: DF0B4204DB7E0924BD2931C131E6DFEB013A5844F717DF7A2DEF86FBC2125DA6 +Test: Encrypt +Comment: Set 3, vector 15 +Key: 0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F +Plaintext: 0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F +Ciphertext: D7C2D4257254E7A05657047B43B65AB778C9E6ACDE53F14000FDFC346CEE4BA6 +Test: Encrypt +Comment: Set 3, vector 16 +Key: 10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010 +Plaintext: 1010101010101010101010101010101010101010101010101010101010101010 +Ciphertext: F64819DFBEBE0A6DB650E7072CE28EA606586418B317785FF0AD44212A84C82C +Test: Encrypt +Comment: Set 3, vector 17 +Key: 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 +Plaintext: 1111111111111111111111111111111111111111111111111111111111111111 +Ciphertext: 155B7E6FFCC0AA874E22494545374E97C08A3D1B1045A0F35FFC54B2842D02A4 +Test: Encrypt +Comment: Set 3, vector 18 +Key: 12121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212 +Plaintext: 1212121212121212121212121212121212121212121212121212121212121212 +Ciphertext: FEE12FD9E87DCB4FE5C5249E3EAEDA0514F6A4826C1A5ABC87E22B95D4A84851 +Test: Encrypt +Comment: Set 3, vector 19 +Key: 13131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313 +Plaintext: 1313131313131313131313131313131313131313131313131313131313131313 +Ciphertext: 1DA785C2A2CEFED459474EE5401F5B795F6ED468DBB924CFFCF65EF465DE9534 +Test: Encrypt +Comment: Set 3, vector 20 +Key: 14141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414 +Plaintext: 1414141414141414141414141414141414141414141414141414141414141414 +Ciphertext: 4434A4D83273B06B64AF4ED1D70EEAD50DBFC44C5931A7B7B98FF9F514B229E9 +Test: Encrypt +Comment: Set 3, vector 21 +Key: 15151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515 +Plaintext: 1515151515151515151515151515151515151515151515151515151515151515 +Ciphertext: 1AB982A6C64C2C42D05F9FB8ED9BE0EEB5B48CEE8EAB0250D98D43157E999EDC +Test: Encrypt +Comment: Set 3, vector 22 +Key: 16161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616 +Plaintext: 1616161616161616161616161616161616161616161616161616161616161616 +Ciphertext: 83291A3265ACAB71E5CCCF0281A433579F39AE6C2FB7CB7528D7F820158177FF +Test: Encrypt +Comment: Set 3, vector 23 +Key: 17171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717 +Plaintext: 1717171717171717171717171717171717171717171717171717171717171717 +Ciphertext: 90F1FF9F69854321CFC6D0A4541CCDF73C1A1DC737D96FB76F0DDD0BB0097BBA +Test: Encrypt +Comment: Set 3, vector 24 +Key: 18181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818 +Plaintext: 1818181818181818181818181818181818181818181818181818181818181818 +Ciphertext: ABF9813765AFBEA9BF26026716294D5C5B309243339ECC9F21CEADE6E7083266 +Test: Encrypt +Comment: Set 3, vector 25 +Key: 19191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919 +Plaintext: 1919191919191919191919191919191919191919191919191919191919191919 +Ciphertext: 7B5C8222D85392E82E703ADFB0FF02DBD2297791B84E26A3A1ED12309247D064 +Test: Encrypt +Comment: Set 3, vector 26 +Key: 1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A +Plaintext: 1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A +Ciphertext: 227355246FCC9106FA5572475E8C466F1140CD75A8A84DFCD2B0908392914FD7 +Test: Encrypt +Comment: Set 3, vector 27 +Key: 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B +Plaintext: 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B +Ciphertext: E5E5A887FA888691FF93014C2E368DC10775A447A5EF4B632A089DA82D245BE3 +Test: Encrypt +Comment: Set 3, vector 28 +Key: 1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C +Plaintext: 1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C +Ciphertext: BA417FC94107761C0969EF6EA7DDC74E5F85CAB61E2271CEB6D9C98B139F4576 +Test: Encrypt +Comment: Set 3, vector 29 +Key: 1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D +Plaintext: 1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D +Ciphertext: F3B85912DF6950B9AE28CE08E456D494E0C949A36FA102540C51827AEC9168AB +Test: Encrypt +Comment: Set 3, vector 30 +Key: 1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E +Plaintext: 1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E +Ciphertext: 1AC0ED993D24366380522B05F97B6FC64B199241A1D556B992632AEE400F0494 +Test: Encrypt +Comment: Set 3, vector 31 +Key: 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F +Plaintext: 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F +Ciphertext: 3550CD591130231B0F01F6860B699715B98B9497B4035C7323000D67C5F0B1B7 +Test: Encrypt +Comment: Set 3, vector 32 +Key: 20202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020 +Plaintext: 2020202020202020202020202020202020202020202020202020202020202020 +Ciphertext: E267D6113C27170A3EE6DF496E801A6131BBD3444365D7C03791E25610F1A0E4 +Test: Encrypt +Comment: Set 3, vector 33 +Key: 21212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121 +Plaintext: 2121212121212121212121212121212121212121212121212121212121212121 +Ciphertext: 3D71B778381E70BCC1A7B8411208225FC922857E862FC17312E3782CEA289B15 +Test: Encrypt +Comment: Set 3, vector 34 +Key: 22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222 +Plaintext: 2222222222222222222222222222222222222222222222222222222222222222 +Ciphertext: 16B41DE00DBF29B96CC59E246DE3188B786E097394E9EEE2250169AE00306FD8 +Test: Encrypt +Comment: Set 3, vector 35 +Key: 23232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323 +Plaintext: 2323232323232323232323232323232323232323232323232323232323232323 +Ciphertext: 99DDE88C9F26D270B3C507A25FE49955A0FEA6C8FEBAD133842DA1CE730EEB7F +Test: Encrypt +Comment: Set 3, vector 36 +Key: 24242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424 +Plaintext: 2424242424242424242424242424242424242424242424242424242424242424 +Ciphertext: 9766D3F9E73987EE10A20605C8338C0759A7024CF2DF549DE5084EC4902C550A +Test: Encrypt +Comment: Set 3, vector 37 +Key: 25252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525 +Plaintext: 2525252525252525252525252525252525252525252525252525252525252525 +Ciphertext: 0FFD89849C8EC5A46B8F43C799ED305AF602C73E810FC729A8C9BB0F5C55CD54 +Test: Encrypt +Comment: Set 3, vector 38 +Key: 26262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626 +Plaintext: 2626262626262626262626262626262626262626262626262626262626262626 +Ciphertext: 91956E101CE4546623A5BE49811F167476CB568972CEBF7A59EB27DA524A0C6B +Test: Encrypt +Comment: Set 3, vector 39 +Key: 27272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727 +Plaintext: 2727272727272727272727272727272727272727272727272727272727272727 +Ciphertext: 7DEC5ECE0D590EE3E099C07F2DD6A6A9C71632D277803FD007275B93369ABED0 +Test: Encrypt +Comment: Set 3, vector 40 +Key: 28282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828 +Plaintext: 2828282828282828282828282828282828282828282828282828282828282828 +Ciphertext: 039C192AFC54EFDE1ED3610B0E9F95AA08D7CDC6AE71A66B5C508E4D14C038CF +Test: Encrypt +Comment: Set 3, vector 41 +Key: 29292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929 +Plaintext: 2929292929292929292929292929292929292929292929292929292929292929 +Ciphertext: D558F8F4562BD8FE816FABF621556C8416C6FD00209028DF978F8915CC093E16 +Test: Encrypt +Comment: Set 3, vector 42 +Key: 2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A +Plaintext: 2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A +Ciphertext: 1AE21791ED4B610DD693012518759D6E9C1BBF206482EEA43470F02B493CFFB8 +Test: Encrypt +Comment: Set 3, vector 43 +Key: 2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B +Plaintext: 2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B +Ciphertext: 34F2112E8FBD1B373BA8400B05321F658FDFE0DC87C1304C36766DE71840A4DF +Test: Encrypt +Comment: Set 3, vector 44 +Key: 2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C +Plaintext: 2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C +Ciphertext: DBF9B56BBF2E50DF321CA687F8BE0E6222E7DF52B4A142174058CC119D9EC0DA +Test: Encrypt +Comment: Set 3, vector 45 +Key: 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D +Plaintext: 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D +Ciphertext: 8B2757374F778FE0B30D11AD7116CE37E2AB858A4E1C50D1115B6E328F3635F5 +Test: Encrypt +Comment: Set 3, vector 46 +Key: 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E +Plaintext: 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E +Ciphertext: 06588A873366FAA47323C9A098A759718DFB0E310C91A4E38B42CC56A0757811 +Test: Encrypt +Comment: Set 3, vector 47 +Key: 2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F +Plaintext: 2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F +Ciphertext: 7B861B18E3F322D8000BDDCBCE3B50405AA923375568F16AE84411E91DB879C3 +Test: Encrypt +Comment: Set 3, vector 48 +Key: 30303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030 +Plaintext: 3030303030303030303030303030303030303030303030303030303030303030 +Ciphertext: 170F74A4D692C302551EE17CD544D65185112D2A5E812D203B36FC39BF1DA9C7 +Test: Encrypt +Comment: Set 3, vector 49 +Key: 31313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131 +Plaintext: 3131313131313131313131313131313131313131313131313131313131313131 +Ciphertext: 0178F59DDAB05A4DFAF66FD406170E08227096EF9712CB481A26EBD82F470D7A +Test: Encrypt +Comment: Set 3, vector 50 +Key: 32323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232 +Plaintext: 3232323232323232323232323232323232323232323232323232323232323232 +Ciphertext: 8BAC479F3A92DF71F973AA457E19D75FB0F1A0FE68FF440A86154721BCC345D4 +Test: Encrypt +Comment: Set 3, vector 51 +Key: 33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333 +Plaintext: 3333333333333333333333333333333333333333333333333333333333333333 +Ciphertext: EB50A10C7A0ED9960CDE0C3EDB899A6B67324B1EE23DE4BB13F60D187C3CBA35 +Test: Encrypt +Comment: Set 3, vector 52 +Key: 34343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434 +Plaintext: 3434343434343434343434343434343434343434343434343434343434343434 +Ciphertext: 00AA782AC61FD06DC781E3C5662C65BD1043EC28D056C98F07074DA7C11C1E1F +Test: Encrypt +Comment: Set 3, vector 53 +Key: 35353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535 +Plaintext: 3535353535353535353535353535353535353535353535353535353535353535 +Ciphertext: 23B9F2F26CFC51ECC6DD1AFE614C2DAE8348DA033F9B67AEAA87B71F5377D95D +Test: Encrypt +Comment: Set 3, vector 54 +Key: 36363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636 +Plaintext: 3636363636363636363636363636363636363636363636363636363636363636 +Ciphertext: 9655D4B1CBEF855401274C3339C16DB9B5A9651F60579CFE8554B6EE25DCCA0E +Test: Encrypt +Comment: Set 3, vector 55 +Key: 37373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737 +Plaintext: 3737373737373737373737373737373737373737373737373737373737373737 +Ciphertext: E072ED2DAD79B07C48B50ED31E02FD9705562525D49DBF45DACCFDF35D5A6965 +Test: Encrypt +Comment: Set 3, vector 56 +Key: 38383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838 +Plaintext: 3838383838383838383838383838383838383838383838383838383838383838 +Ciphertext: 287638BAE945B88A95029155BC47D033B5C5C4C191F079C234C6E97683FFABA0 +Test: Encrypt +Comment: Set 3, vector 57 +Key: 39393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939 +Plaintext: 3939393939393939393939393939393939393939393939393939393939393939 +Ciphertext: 500CD3B02BF6FA8C66D1ADE0CE43B325A759CD3426096084A261F054D798F885 +Test: Encrypt +Comment: Set 3, vector 58 +Key: 3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A +Plaintext: 3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A +Ciphertext: 17614BAB583F2DCF809A2AEE973A4875251B571525521B3A8C47303450B6301F +Test: Encrypt +Comment: Set 3, vector 59 +Key: 3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B +Plaintext: 3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B +Ciphertext: 978C8DFD9AC74FF670CC8B31EDC8EC15DDBC2854375ED9BA07BB0F7B96C70BB3 +Test: Encrypt +Comment: Set 3, vector 60 +Key: 3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C +Plaintext: 3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C +Ciphertext: 994CA36F6230C7DB63CAD61342FAB3F155C361DAD458FC457AD09ACCAB2EB43F +Test: Encrypt +Comment: Set 3, vector 61 +Key: 3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D +Plaintext: 3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D +Ciphertext: AC06659932208AC1DD5F07448A7407232F1410CDAC92F7C5305C4043C559345F +Test: Encrypt +Comment: Set 3, vector 62 +Key: 3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E +Plaintext: 3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E +Ciphertext: B55616F0743A29655FEC468CD30C8C65F7925327665670BA9E41A2E09C05C63B +Test: Encrypt +Comment: Set 3, vector 63 +Key: 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F +Plaintext: 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F +Ciphertext: 78F4852712C3547547A114E73F52C6128EDD3F29E0B2C938D6F9F69AF2303FD2 +Test: Encrypt +Comment: Set 3, vector 64 +Key: 40404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040 +Plaintext: 4040404040404040404040404040404040404040404040404040404040404040 +Ciphertext: C97909916EE86FFDCE8A92903046109B53F788A53039434DF1A394DAD6F697A2 +Test: Encrypt +Comment: Set 3, vector 65 +Key: 41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141 +Plaintext: 4141414141414141414141414141414141414141414141414141414141414141 +Ciphertext: C3FD3C59D37D44AF9EE6B87AC0939A4A4B2FBAAC23E80E72B1CAC352FE30A8E2 +Test: Encrypt +Comment: Set 3, vector 66 +Key: 42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 +Plaintext: 4242424242424242424242424242424242424242424242424242424242424242 +Ciphertext: 94C70F7654479BC9DA9854129F57F3E69C31B63900A404F577AF1C83CD96E5D6 +Test: Encrypt +Comment: Set 3, vector 67 +Key: 43434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343 +Plaintext: 4343434343434343434343434343434343434343434343434343434343434343 +Ciphertext: 71DD024E9CE700B373A275AA870A68B5DAD9E47D38BC18F34073319041A1CADF +Test: Encrypt +Comment: Set 3, vector 68 +Key: 44444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444 +Plaintext: 4444444444444444444444444444444444444444444444444444444444444444 +Ciphertext: 274D101B2BD0E7CAFC9E5559DC68567DC8975056B84573C4294D78513B7406D8 +Test: Encrypt +Comment: Set 3, vector 69 +Key: 45454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545 +Plaintext: 4545454545454545454545454545454545454545454545454545454545454545 +Ciphertext: 8DCE5B5C376E42F11A322D8CBCEB8C0AE1EC24F3C65D72B326708FEAF13E3B51 +Test: Encrypt +Comment: Set 3, vector 70 +Key: 46464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646 +Plaintext: 4646464646464646464646464646464646464646464646464646464646464646 +Ciphertext: D62D3BA9BBD23F4424EB929AE7A4CD83A70FA7EFD2E6CCFED23E1176AFDB69CD +Test: Encrypt +Comment: Set 3, vector 71 +Key: 47474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747 +Plaintext: 4747474747474747474747474747474747474747474747474747474747474747 +Ciphertext: FE7670925FEA3AAE1F039590EA230C094C3E434BF1350B12D4EA26E48A6EF7F0 +Test: Encrypt +Comment: Set 3, vector 72 +Key: 48484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848 +Plaintext: 4848484848484848484848484848484848484848484848484848484848484848 +Ciphertext: 3A57E728BFA31AA36C8E4ED38A34B465BA233AD066225F31651C93B870AAFE6D +Test: Encrypt +Comment: Set 3, vector 73 +Key: 49494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949 +Plaintext: 4949494949494949494949494949494949494949494949494949494949494949 +Ciphertext: 3B56014035A28EA6F2F2B09429FED7FC0F5B76D5458F1EB4F3AAA7E7F6610C65 +Test: Encrypt +Comment: Set 3, vector 74 +Key: 4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A +Plaintext: 4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A +Ciphertext: 2D28A28ECABAC61B540CD933BE43AF16F11429EDE8E7B62121CD853054363730 +Test: Encrypt +Comment: Set 3, vector 75 +Key: 4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B +Plaintext: 4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B +Ciphertext: D8A892E3C24C6A2EB8446B3737A0E3AA1478811B819FFD3440B5307185906518 +Test: Encrypt +Comment: Set 3, vector 76 +Key: 4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C +Plaintext: 4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C +Ciphertext: 798AD5E43127299B61247059F508268CDBA78B46D4FD28C200AE1052C52294E7 +Test: Encrypt +Comment: Set 3, vector 77 +Key: 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D +Plaintext: 4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D +Ciphertext: 63F43065BA1F262D950219D71B9CD5FA78D6798BCAA981FE3391FF8EA735E4C7 +Test: Encrypt +Comment: Set 3, vector 78 +Key: 4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E +Plaintext: 4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E +Ciphertext: E8E461EB5FD98011A37765ECA336B080D58B35C636AD6F423893EE768913255C +Test: Encrypt +Comment: Set 3, vector 79 +Key: 4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F +Plaintext: 4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F +Ciphertext: 7348E30FFC0C4F5569B6490622A34FB015C364944553582355887BC472279E8D +Test: Encrypt +Comment: Set 3, vector 80 +Key: 50505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050 +Plaintext: 5050505050505050505050505050505050505050505050505050505050505050 +Ciphertext: BE28CB05EEEEDA8FD8971E9970ECBCA25856F66E95AC8B987C69F04BE3276CD7 +Test: Encrypt +Comment: Set 3, vector 81 +Key: 51515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151 +Plaintext: 5151515151515151515151515151515151515151515151515151515151515151 +Ciphertext: 5D336C5E34D4EB95CFAB87C542C72A748AA45E7F77D841A738017927C7908804 +Test: Encrypt +Comment: Set 3, vector 82 +Key: 52525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252 +Plaintext: 5252525252525252525252525252525252525252525252525252525252525252 +Ciphertext: 2942A594A7964F41460EB6037DDE2C28FFBFFB3C21F7EFF43F06632DA980ED8B +Test: Encrypt +Comment: Set 3, vector 83 +Key: 53535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353535353 +Plaintext: 5353535353535353535353535353535353535353535353535353535353535353 +Ciphertext: 1C0F7A4E3147BC7F8150D8144ED31D0054FF15414E5DBF289BFEC160D22684AC +Test: Encrypt +Comment: Set 3, vector 84 +Key: 54545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454 +Plaintext: 5454545454545454545454545454545454545454545454545454545454545454 +Ciphertext: 7931C7B9D78CB50610B1BEF596268B94446FCDA44C3EE7CEE53121AC519C4001 +Test: Encrypt +Comment: Set 3, vector 85 +Key: 55555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555 +Plaintext: 5555555555555555555555555555555555555555555555555555555555555555 +Ciphertext: F4E331C357C603EE5ED5547D75B54631A68D7CD74C5075198D0FC38E5661F556 +Test: Encrypt +Comment: Set 3, vector 86 +Key: 56565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656 +Plaintext: 5656565656565656565656565656565656565656565656565656565656565656 +Ciphertext: 378C2887958E31971E8F59C882730E48407E4DA9C26D4C76B672CD53202AB1B8 +Test: Encrypt +Comment: Set 3, vector 87 +Key: 57575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757 +Plaintext: 5757575757575757575757575757575757575757575757575757575757575757 +Ciphertext: DBE68FE249F4A8D36E1CB49DBE20ED58649CCC502F85895875C1FE82269219DA +Test: Encrypt +Comment: Set 3, vector 88 +Key: 58585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858 +Plaintext: 5858585858585858585858585858585858585858585858585858585858585858 +Ciphertext: 103BD780F3B382C4B28E6E1CB41CBEE22CC1BB64E4A0147D658EDA96A6E7FEAB +Test: Encrypt +Comment: Set 3, vector 89 +Key: 59595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959 +Plaintext: 5959595959595959595959595959595959595959595959595959595959595959 +Ciphertext: 382EF838282E0F4BA729083542BB8CB48AB874FF568DFDA56AFC4ED266DD3243 +Test: Encrypt +Comment: Set 3, vector 90 +Key: 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A +Plaintext: 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A +Ciphertext: 088665DE8F9DC9298DEF4164C12526597F56859AAC2C96A95645A06014BA689A +Test: Encrypt +Comment: Set 3, vector 91 +Key: 5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B +Plaintext: 5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B +Ciphertext: EC988946646A1B2DCC7EDEC4FCAB11BF29055A226F4C75D28F9DFB8D2EB5C9B6 +Test: Encrypt +Comment: Set 3, vector 92 +Key: 5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C +Plaintext: 5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C +Ciphertext: B77221CE7F68292BD4E3A55E8EC7BD1FC68B1B6B02F1008586248833C1089F5C +Test: Encrypt +Comment: Set 3, vector 93 +Key: 5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D +Plaintext: 5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D +Ciphertext: B3E4AA5DE6D25A6237FDD97540191D669C64E54A7D3C544E949489355AFC82B5 +Test: Encrypt +Comment: Set 3, vector 94 +Key: 5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E +Plaintext: 5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E +Ciphertext: AAA6FA046AC4270B22A742C4C29445EB38511E5048414886EBF39523B7EAF76A +Test: Encrypt +Comment: Set 3, vector 95 +Key: 5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F +Plaintext: 5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F +Ciphertext: 4D23440171778573BE7B515C68FA99D0426A32111CA493337E7C55280A90F697 +Test: Encrypt +Comment: Set 3, vector 96 +Key: 60606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060 +Plaintext: 6060606060606060606060606060606060606060606060606060606060606060 +Ciphertext: 8EE711FB281CBAA99917C85F0623B68E2EDAFEFCC3B1B841883D71BA6683568A +Test: Encrypt +Comment: Set 3, vector 97 +Key: 61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 +Plaintext: 6161616161616161616161616161616161616161616161616161616161616161 +Ciphertext: EC29DAE53DB4475F8900311F425FE60CB834A82F2A6A2DB4810F95F4D6991B84 +Test: Encrypt +Comment: Set 3, vector 98 +Key: 62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262 +Plaintext: 6262626262626262626262626262626262626262626262626262626262626262 +Ciphertext: 91E58DDE741553572B5D6F3DAD25953906424FF217497226746A25C0CE1C7D0F +Test: Encrypt +Comment: Set 3, vector 99 +Key: 63636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363 +Plaintext: 6363636363636363636363636363636363636363636363636363636363636363 +Ciphertext: B6EC4D9421AB011D4EEDBC32B289E45AC44CAEB1DC5FAEA752DFFA0137325067 +Test: Encrypt +Comment: Set 3, vector 100 +Key: 64646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464 +Plaintext: 6464646464646464646464646464646464646464646464646464646464646464 +Ciphertext: D9CB13EA06CADF09AC446F9B09553FFE3BF4F1152997B171C03E609D4BD60ADB +Test: Encrypt +Comment: Set 3, vector 101 +Key: 65656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565 +Plaintext: 6565656565656565656565656565656565656565656565656565656565656565 +Ciphertext: 2D07CA161326ED154D9E3FF650963557EC369A91ABB0D49FC1F32AEF39A3B12E +Test: Encrypt +Comment: Set 3, vector 102 +Key: 66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666 +Plaintext: 6666666666666666666666666666666666666666666666666666666666666666 +Ciphertext: 28E8B606EE621D2C5B865B8208C7BD40C3596931CE3FF8FA5AD7EB8EE4480E95 +Test: Encrypt +Comment: Set 3, vector 103 +Key: 67676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767 +Plaintext: 6767676767676767676767676767676767676767676767676767676767676767 +Ciphertext: 9B9B3A23DA29539DA1E9BAA20449750EC192CE14A5063E1A2FFAF5039A665754 +Test: Encrypt +Comment: Set 3, vector 104 +Key: 68686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868 +Plaintext: 6868686868686868686868686868686868686868686868686868686868686868 +Ciphertext: D770E305A9C2D257759D8AE9E70C408D1CB090F976BBAFF3A56730A78BA8BF4F +Test: Encrypt +Comment: Set 3, vector 105 +Key: 69696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969 +Plaintext: 6969696969696969696969696969696969696969696969696969696969696969 +Ciphertext: 453988B10DFD852D1AFD11E96C50024571CCB0F19E7C3C4981F8B8BDCD11F720 +Test: Encrypt +Comment: Set 3, vector 106 +Key: 6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A +Plaintext: 6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A +Ciphertext: 17DFD98CB5C24610DD631C4E2749A679D68F854F21AABE8BF67605A256452AD8 +Test: Encrypt +Comment: Set 3, vector 107 +Key: 6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B +Plaintext: 6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B +Ciphertext: DA260145EC80E19C18685540AC71FA460DD4427168E37BC6E0F967D90C306FBB +Test: Encrypt +Comment: Set 3, vector 108 +Key: 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C +Plaintext: 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C +Ciphertext: 2AC246E2E384ECCC4BC69CE82EDB51C05DD864642F1E9A572DA6043DD1D56DF0 +Test: Encrypt +Comment: Set 3, vector 109 +Key: 6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D +Plaintext: 6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D +Ciphertext: D1A06B820071CC4122F0B0797A294F31922E26703CDEF15A6D8F511CDBD8BD3F +Test: Encrypt +Comment: Set 3, vector 110 +Key: 6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E +Plaintext: 6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E +Ciphertext: C8D23274A1FF6AEBDF0BA70FBA7A895277B1CC8040F8FB2814195E3A7E85BD01 +Test: Encrypt +Comment: Set 3, vector 111 +Key: 6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F +Plaintext: 6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F +Ciphertext: E0133DC7960953BABC7BFBA52E88DCF86EBD979D6D63EB19466EEADEDEDEEBB3 +Test: Encrypt +Comment: Set 3, vector 112 +Key: 70707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070707070 +Plaintext: 7070707070707070707070707070707070707070707070707070707070707070 +Ciphertext: A1A9527766EE54D566D97E7A0763A5AECE86F2816411AC2066439D6BDF02FEA7 +Test: Encrypt +Comment: Set 3, vector 113 +Key: 71717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171 +Plaintext: 7171717171717171717171717171717171717171717171717171717171717171 +Ciphertext: E1833EF5C2BA2EF192642164F0F2C02A7334EF5AEA37E9DD56D17AE6CB031004 +Test: Encrypt +Comment: Set 3, vector 114 +Key: 72727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272 +Plaintext: 7272727272727272727272727272727272727272727272727272727272727272 +Ciphertext: DD2CC0EECAA7E5364376FA73E12C64A0C42FB9FC7E94EFF0B22A051D6EDFE905 +Test: Encrypt +Comment: Set 3, vector 115 +Key: 73737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373 +Plaintext: 7373737373737373737373737373737373737373737373737373737373737373 +Ciphertext: 9A72F15B911E6A50A32EEEDF83B62B628E37ED403085180571DEBEA2F37CF49F +Test: Encrypt +Comment: Set 3, vector 116 +Key: 74747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474 +Plaintext: 7474747474747474747474747474747474747474747474747474747474747474 +Ciphertext: CD83CE7861EE8259A9C29BC3870EA1BF629ECD31F2E18F0BC12221F239207457 +Test: Encrypt +Comment: Set 3, vector 117 +Key: 75757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575 +Plaintext: 7575757575757575757575757575757575757575757575757575757575757575 +Ciphertext: 7B4218C5AEA4EEFE17E2AB110D8B63A947F21D5210162F6283EDDF00900CEE27 +Test: Encrypt +Comment: Set 3, vector 118 +Key: 76767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676 +Plaintext: 7676767676767676767676767676767676767676767676767676767676767676 +Ciphertext: 935DE2010B112937A233E7CB1023FB9D3C46D7C688A478A94F86AD3919FD2728 +Test: Encrypt +Comment: Set 3, vector 119 +Key: 77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777 +Plaintext: 7777777777777777777777777777777777777777777777777777777777777777 +Ciphertext: 416A91A68A520732E672ACB5A36599D9A99901F013CC460D9C2FB16AAB45996E +Test: Encrypt +Comment: Set 3, vector 120 +Key: 78787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878 +Plaintext: 7878787878787878787878787878787878787878787878787878787878787878 +Ciphertext: FD066F9C65CD3D61B43F5DA44F7B94C85541DC5E09D52B044DA963699C39FDA0 +Test: Encrypt +Comment: Set 3, vector 121 +Key: 79797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979 +Plaintext: 7979797979797979797979797979797979797979797979797979797979797979 +Ciphertext: 63937A7953E453B6E48539FACBD1BC489E03D209DB188837C5A09BA458FFFB92 +Test: Encrypt +Comment: Set 3, vector 122 +Key: 7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A +Plaintext: 7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A +Ciphertext: 68F9EA0F87112633611052A45BBF32B7069079EDB16A928CD2AA16BE464178E3 +Test: Encrypt +Comment: Set 3, vector 123 +Key: 7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B +Plaintext: 7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B +Ciphertext: 874D5ED6C8052C3B4AB830626A195F508DDA15388BA75B3D957B26BC134C9B30 +Test: Encrypt +Comment: Set 3, vector 124 +Key: 7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C +Plaintext: 7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C +Ciphertext: EC3EA8DC433E39B85E4C4D68AC6A854A1B943D99EB2E9A018EA27DC1874CA867 +Test: Encrypt +Comment: Set 3, vector 125 +Key: 7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D +Plaintext: 7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D +Ciphertext: 9CE2298362F1F234A73BECA011EC31B4BC7E143D87B4F118CDADE6AB8D1ED783 +Test: Encrypt +Comment: Set 3, vector 126 +Key: 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E +Plaintext: 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E +Ciphertext: 27973D9B510ED9C612CC770FC1AE25EE21B1A9616CB64617EDA477939BE98D04 +Test: Encrypt +Comment: Set 3, vector 127 +Key: 7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F +Plaintext: 7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F +Ciphertext: 82A0EB8C058E727EBD6032F0F77EE693342C97BD44E9538032652B1CA10403DE +Test: Encrypt +Comment: Set 3, vector 128 +Key: 80808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080 +Plaintext: 8080808080808080808080808080808080808080808080808080808080808080 +Ciphertext: C3C1CD5F3060B3EC4E6ABC0818B68449E1750FB482368C8F3305270E16F98735 +Test: Encrypt +Comment: Set 3, vector 129 +Key: 81818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181818181 +Plaintext: 8181818181818181818181818181818181818181818181818181818181818181 +Ciphertext: 26381852C68B646D80E53C958855293BDC6FAAA85C5F9CAAACABE7B8077E4F7A +Test: Encrypt +Comment: Set 3, vector 130 +Key: 82828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282 +Plaintext: 8282828282828282828282828282828282828282828282828282828282828282 +Ciphertext: E2EA924898ED40FBD8C633706AD7D698392DF1EF33A10FDFCBE51B58C3AE0668 +Test: Encrypt +Comment: Set 3, vector 131 +Key: 83838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383838383 +Plaintext: 8383838383838383838383838383838383838383838383838383838383838383 +Ciphertext: 15CBDDA36707819D0C7694AAD46B2345BDEFC9D4F26F03A4BF860CE46F7BB53A +Test: Encrypt +Comment: Set 3, vector 132 +Key: 84848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484 +Plaintext: 8484848484848484848484848484848484848484848484848484848484848484 +Ciphertext: F96318A42737AB884FAA82BBB7025063E9A25C5957F52A7342E0C03A1A64273C +Test: Encrypt +Comment: Set 3, vector 133 +Key: 85858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585858585 +Plaintext: 8585858585858585858585858585858585858585858585858585858585858585 +Ciphertext: 7813FEB148D103075C80ACDFC95E2437A560D9B2E6C910E3A59805338E498907 +Test: Encrypt +Comment: Set 3, vector 134 +Key: 86868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686868686 +Plaintext: 8686868686868686868686868686868686868686868686868686868686868686 +Ciphertext: C7E9D5FE3BA11096AB77E715DFF0D2EB67E9136F0393CD004A7E994B3F994FA4 +Test: Encrypt +Comment: Set 3, vector 135 +Key: 87878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787 +Plaintext: 8787878787878787878787878787878787878787878787878787878787878787 +Ciphertext: F7D2DD8DF86A0E985CF6E83AA5922A548C83856D88C2C9D49EA962C9E6497949 +Test: Encrypt +Comment: Set 3, vector 136 +Key: 88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888 +Plaintext: 8888888888888888888888888888888888888888888888888888888888888888 +Ciphertext: C64887C6573E3D7F286C0353188FC93F05321C0C949ACDCB0237725576BCF77B +Test: Encrypt +Comment: Set 3, vector 137 +Key: 89898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989 +Plaintext: 8989898989898989898989898989898989898989898989898989898989898989 +Ciphertext: 77FB97C9C953BE6BD58044FB1E095BB5E3F4B3A51DAFE6F2F7ADED0FB707921F +Test: Encrypt +Comment: Set 3, vector 138 +Key: 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A +Plaintext: 8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A +Ciphertext: 22DE5F20955357BA1BF70E4D6DA436CCDE28C228031E4A413882C918EF8082D1 +Test: Encrypt +Comment: Set 3, vector 139 +Key: 8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B +Plaintext: 8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B +Ciphertext: 146FF5907A3C58593C3FD3EB7498C4426CCE04DD0DA9138954BB97AAC821D87F +Test: Encrypt +Comment: Set 3, vector 140 +Key: 8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C +Plaintext: 8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C +Ciphertext: 474ADC5855C87504A7C859409E25154D94B05A925F1D9989AE653B5511710BD7 +Test: Encrypt +Comment: Set 3, vector 141 +Key: 8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D +Plaintext: 8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D +Ciphertext: 959B1090C1FF59998C100814E95E40EF94C6F2B7ED0425C78391192CFFFFA465 +Test: Encrypt +Comment: Set 3, vector 142 +Key: 8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E +Plaintext: 8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E +Ciphertext: 9DA473108FFCECB228F8809860CDA316F4E1FAC5ADC39BB0373F01DCEBCBF271 +Test: Encrypt +Comment: Set 3, vector 143 +Key: 8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F +Plaintext: 8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F +Ciphertext: 905FD0302F9F3C4296E15F94EDD72A8F9F4E9E4068F068099CAAE7247235847E +Test: Encrypt +Comment: Set 3, vector 144 +Key: 90909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090 +Plaintext: 9090909090909090909090909090909090909090909090909090909090909090 +Ciphertext: B63B82FB4B4961E4800FD13CAF145BEBF3625822AF7F5D3ACF2A4506471C636D +Test: Encrypt +Comment: Set 3, vector 145 +Key: 91919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191919191 +Plaintext: 9191919191919191919191919191919191919191919191919191919191919191 +Ciphertext: 63AA9822C7A5A6777D03F901E3BAF91FD566553C88835EF06DB9A983212288BF +Test: Encrypt +Comment: Set 3, vector 146 +Key: 92929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292929292 +Plaintext: 9292929292929292929292929292929292929292929292929292929292929292 +Ciphertext: 5417F10E4028BDE0F741114632E2090A1E6C83ACB1D03EA98D18D003838B4F0A +Test: Encrypt +Comment: Set 3, vector 147 +Key: 93939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393939393 +Plaintext: 9393939393939393939393939393939393939393939393939393939393939393 +Ciphertext: FD2C478FB17EE8520149E8A242BB07E0B32929536B191AC6DBCE05891C5E4BFC +Test: Encrypt +Comment: Set 3, vector 148 +Key: 94949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494 +Plaintext: 9494949494949494949494949494949494949494949494949494949494949494 +Ciphertext: 6A36A092BC0F029B60D40440F141EF0DC21A241547359FB618E9243C39AE3D7C +Test: Encrypt +Comment: Set 3, vector 149 +Key: 95959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595959595 +Plaintext: 9595959595959595959595959595959595959595959595959595959595959595 +Ciphertext: 605BC400A0FEE12092D369142E4D20C3A4F3D7623254BF9E242766946FC47ED1 +Test: Encrypt +Comment: Set 3, vector 150 +Key: 96969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696 +Plaintext: 9696969696969696969696969696969696969696969696969696969696969696 +Ciphertext: 6A5FA33652F946D7C93A56D15B5D3807401C667A9757495341F78526D58659D2 +Test: Encrypt +Comment: Set 3, vector 151 +Key: 97979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797 +Plaintext: 9797979797979797979797979797979797979797979797979797979797979797 +Ciphertext: 5C6AC175B74B9F7F7D6371A90B1F35E1276628DF6A82B0ECE38590C88B7B8DCA +Test: Encrypt +Comment: Set 3, vector 152 +Key: 98989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898989898 +Plaintext: 9898989898989898989898989898989898989898989898989898989898989898 +Ciphertext: 67BB4E7818FBE6CFAB113C1B2EC797E3164432BFF708450312422D5AEC70A8A8 +Test: Encrypt +Comment: Set 3, vector 153 +Key: 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 +Plaintext: 9999999999999999999999999999999999999999999999999999999999999999 +Ciphertext: BFDA13CA82E73FBF62B6F1BB7181916CE7FD7DC7608EB958A8246346DFBB04E9 +Test: Encrypt +Comment: Set 3, vector 154 +Key: 9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A +Plaintext: 9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A +Ciphertext: C30F3EF137BF7718F76C7E4D2366A48E7C3CE53735BBF8B56CD51609A23AC06C +Test: Encrypt +Comment: Set 3, vector 155 +Key: 9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B +Plaintext: 9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B +Ciphertext: D73795A681B4FBE858703C15D60299682F64C800E691D223C4BE51012DA4D3DA +Test: Encrypt +Comment: Set 3, vector 156 +Key: 9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C +Plaintext: 9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C +Ciphertext: 885A096C820E01E48E1A5F75DB0A007C2A96B66FCAB38AE80CF92DD8B6A35F6F +Test: Encrypt +Comment: Set 3, vector 157 +Key: 9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D +Plaintext: 9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D +Ciphertext: 8FBDD4939C31026305C575F1FDCED3DBAE320C56CF064E9F19B44A43898BFD5C +Test: Encrypt +Comment: Set 3, vector 158 +Key: 9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E +Plaintext: 9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E +Ciphertext: 2D9EC00B081BC1512EC11A0B8B898639415AEEA3270C4B49E4B47C601AB85875 +Test: Encrypt +Comment: Set 3, vector 159 +Key: 9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F +Plaintext: 9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F +Ciphertext: 59565FB9888519C77E9C4E86D72AD86205AB55488D5ED0B9A388FB2D301C4400 +Test: Encrypt +Comment: Set 3, vector 160 +Key: A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0 +Plaintext: A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0 +Ciphertext: 32D6CAA3D5E0A5D3CCD0FD8F2105CFF662FC4052FE348C2DFD0BC3EEFF3AB700 +Test: Encrypt +Comment: Set 3, vector 161 +Key: A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1 +Plaintext: A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1 +Ciphertext: 7C3276EA6BB6FDDDEC8B901C45978B7D4D34AACE9F2D02F7D7F5826A89809DE9 +Test: Encrypt +Comment: Set 3, vector 162 +Key: A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 +Plaintext: A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2 +Ciphertext: C5ABC33559D828DD1464264F94D46A8519B4CE47EAA0EC9BF0504C876AC85451 +Test: Encrypt +Comment: Set 3, vector 163 +Key: A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3 +Plaintext: A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3A3 +Ciphertext: E63050ADB9F2789F91A192E089883D7346DD42DE4C654E1D4B72C77D6C09FDB0 +Test: Encrypt +Comment: Set 3, vector 164 +Key: A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4 +Plaintext: A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4 +Ciphertext: E7C58AF118E1DFD2A279DE640EDEF02FB4F3C78D778D145ECC6B2C4CCD065229 +Test: Encrypt +Comment: Set 3, vector 165 +Key: A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5 +Plaintext: A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5 +Ciphertext: 278D8C11ACFDB851131432B3E19C409F940F93E0F6CB49D076C62E70B9C27095 +Test: Encrypt +Comment: Set 3, vector 166 +Key: A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6 +Plaintext: A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6A6 +Ciphertext: D4839B5679FCA83189BB8C3681E83BAC871A02F297578855034E915F4EF04C12 +Test: Encrypt +Comment: Set 3, vector 167 +Key: A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7 +Plaintext: A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7A7 +Ciphertext: 91AFF6474168F1D113E3DC66E620CF2F7283CE84F5FDDECC7E79CC005859C1BA +Test: Encrypt +Comment: Set 3, vector 168 +Key: A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8 +Plaintext: A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8A8 +Ciphertext: 1374026DD442B1C1E0BA34570240F6A9E99781C8307A1544A9D3C91857C7E6E1 +Test: Encrypt +Comment: Set 3, vector 169 +Key: A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9 +Plaintext: A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9A9 +Ciphertext: C95E8163D47755E25E8A4BA1FDFF46E016F080F13A794FD21251CE238F28C52E +Test: Encrypt +Comment: Set 3, vector 170 +Key: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +Plaintext: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +Ciphertext: 5DA751854BEEDB19D767A09E2BD9C12D15E51A4409A1F70574496D0A0DA767F9 +Test: Encrypt +Comment: Set 3, vector 171 +Key: ABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB +Plaintext: ABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABAB +Ciphertext: C1A0ADDB98DA358D8F40CDB8FA427770D6BD5705D81A804A9BA27FFAE8790BD1 +Test: Encrypt +Comment: Set 3, vector 172 +Key: ACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACAC +Plaintext: ACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACAC +Ciphertext: 604830D513CB29E0E89A36EAB97FFDFC0855AE212F9DDAB62ABE7572CBCEBFC5 +Test: Encrypt +Comment: Set 3, vector 173 +Key: ADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADAD +Plaintext: ADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADAD +Ciphertext: 0DB5075E0B9727D439ED88030D31B532B61556D206220CAE70A7B42EE4C5F72E +Test: Encrypt +Comment: Set 3, vector 174 +Key: AEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAE +Plaintext: AEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAE +Ciphertext: A5167DC20ED3B1894B10C6AA754FDCF9FC1418439D9CA80C40974E9CB7630A12 +Test: Encrypt +Comment: Set 3, vector 175 +Key: AFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAF +Plaintext: AFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAF +Ciphertext: 1A90CCEA061A2FB58E4D1F363B6CEEC26BFB55F4F140A18991C8EF50E8DFB306 +Test: Encrypt +Comment: Set 3, vector 176 +Key: B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0 +Plaintext: B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0 +Ciphertext: 5CED17D75543C21AA1E020D4B084DB86A77BC445C7E77DA54DC6D786A0976A09 +Test: Encrypt +Comment: Set 3, vector 177 +Key: B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1 +Plaintext: B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1 +Ciphertext: BB28F1F9496ED578276F99F3A2D4657566DC2CDDDCF00AE44555DA614C64E54E +Test: Encrypt +Comment: Set 3, vector 178 +Key: B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2 +Plaintext: B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2 +Ciphertext: 30C28BF86BEAEBB25F4A667FB2B9C183B85B456527EB49B44AA4EA825A44E026 +Test: Encrypt +Comment: Set 3, vector 179 +Key: B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3 +Plaintext: B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3B3 +Ciphertext: C2B0DEB4BC6C28869675FB75D2C2081396601B1FA823185D2D9EDE0730BBEAEA +Test: Encrypt +Comment: Set 3, vector 180 +Key: B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 +Plaintext: B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4 +Ciphertext: B3EDC667C3FD03CE50D05877C8A78C330F809DF5F8F7FB11968A3664C77CA78B +Test: Encrypt +Comment: Set 3, vector 181 +Key: B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5 +Plaintext: B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5B5 +Ciphertext: BC2FCF90C52B883CAC3F0A673FA093EEB48952F4DE50A9288464B84A920A1316 +Test: Encrypt +Comment: Set 3, vector 182 +Key: B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6 +Plaintext: B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6B6 +Ciphertext: 30BCF4063A59823CE94B14B6B65F1B4DBEED8FB30832765B5186F4B834DBEA89 +Test: Encrypt +Comment: Set 3, vector 183 +Key: B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7 +Plaintext: B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7B7 +Ciphertext: 51B4C7E8F697FACC24294A2CEB404C4BEC0CA41C76A6B50A824800EA4464C796 +Test: Encrypt +Comment: Set 3, vector 184 +Key: B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8 +Plaintext: B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8B8 +Ciphertext: 2CCFF61604C0881CCC6A69B885878D6D07CEA7DAB31719D89DC4ECB0063DF5D2 +Test: Encrypt +Comment: Set 3, vector 185 +Key: B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9 +Plaintext: B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9B9 +Ciphertext: 87998D9F16DC018B5DBD42A2E0C26D3774C2A41986E2D0A1504CE37B6EE71688 +Test: Encrypt +Comment: Set 3, vector 186 +Key: BABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABA +Plaintext: BABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABABA +Ciphertext: D774451BB82A62A4C7708D0194F6C129C483CEFD182BAADF5A35EB77892F317A +Test: Encrypt +Comment: Set 3, vector 187 +Key: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB +Plaintext: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB +Ciphertext: B88CE3DF52572A1A1C8253E05D789BBF204E2CFC7A00389429F4C6B428EF8CD6 +Test: Encrypt +Comment: Set 3, vector 188 +Key: BCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC +Plaintext: BCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBC +Ciphertext: B854E538E6674A1831F635AA6650A0A4D0730A9A4B12511509EFD49E34D57D62 +Test: Encrypt +Comment: Set 3, vector 189 +Key: BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD +Plaintext: BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD +Ciphertext: A69EF2348FEEF1EA09A2B29A6D977092ECD522A62EE906FA47624C92A872EB17 +Test: Encrypt +Comment: Set 3, vector 190 +Key: BEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBE +Plaintext: BEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBE +Ciphertext: A1AE0CBC3B5200F1D8AE165EE42D45F6CE8C4FF448F8127B6D9AB4936FC76CA8 +Test: Encrypt +Comment: Set 3, vector 191 +Key: BFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBF +Plaintext: BFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBF +Ciphertext: 91948E36B83E21FF8A5EEDAA48E50E3A292A3B68D20657FA7E11F50BC7A12205 +Test: Encrypt +Comment: Set 3, vector 192 +Key: C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0 +Plaintext: C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0 +Ciphertext: 56CD17219224C3103E3E3E5CABAB6C1E78DEA9AD27613E8D62901FFA31500BFF +Test: Encrypt +Comment: Set 3, vector 193 +Key: C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1 +Plaintext: C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1 +Ciphertext: 2E8FE5CAB2448B194387B160E9141E7D1B879BA1580B3D393B55436608EA2735 +Test: Encrypt +Comment: Set 3, vector 194 +Key: C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2 +Plaintext: C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2C2 +Ciphertext: 5DD74E1155DD90840C702145DF6912754FB74B47625EA4C5382326681DB3390E +Test: Encrypt +Comment: Set 3, vector 195 +Key: C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3 +Plaintext: C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3 +Ciphertext: 3A9F5962554037DCB1FA2AD04BFC0BF79699941500D5F9841320C6D8601310A2 +Test: Encrypt +Comment: Set 3, vector 196 +Key: C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4 +Plaintext: C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4C4 +Ciphertext: BB0F5B68087BBA51DBB700BA1860CC3D0A587E54D57F4014DE4E48E58E529F87 +Test: Encrypt +Comment: Set 3, vector 197 +Key: C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5 +Plaintext: C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5C5 +Ciphertext: 8384025D801AB8EC4D4416F5B7E862B6D9AC9E4AEE334C35FD0296B1402E4975 +Test: Encrypt +Comment: Set 3, vector 198 +Key: C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 +Plaintext: C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6 +Ciphertext: BE3057511C5D0E51315D89671BB4E57E7B590EC3ECE8A14D728248ED8F5107BB +Test: Encrypt +Comment: Set 3, vector 199 +Key: C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7 +Plaintext: C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7C7 +Ciphertext: 18882618837D15B0B6BD77E1F37470EC58155A2788BDD9D91AEBD16B29A92A1B +Test: Encrypt +Comment: Set 3, vector 200 +Key: C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8 +Plaintext: C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8C8 +Ciphertext: 8FAFDDC7E04C1AF3BBE8428222DCA59D2EF8C9E0213430492ECAB7B414987FEF +Test: Encrypt +Comment: Set 3, vector 201 +Key: C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9 +Plaintext: C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9C9 +Ciphertext: 4D687992D4F9F515FE451AC967CBF75F906D637C3C261758E263A0DA0DEF69C2 +Test: Encrypt +Comment: Set 3, vector 202 +Key: CACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACA +Plaintext: CACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACACA +Ciphertext: 9DDC94BFF87FDBAFDB0AB9DC17D3649231300E5E6270600856722324DC9CA39A +Test: Encrypt +Comment: Set 3, vector 203 +Key: CBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCB +Plaintext: CBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCB +Ciphertext: 86E9CCD90D7B902D23D82C085B1F886402DBD2D19C5A81A32F318C98C6E2A98A +Test: Encrypt +Comment: Set 3, vector 204 +Key: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +Plaintext: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +Ciphertext: 164FCD7D1FFE12FF1FDEE6384145EF546A5CD98C22817A5205FF2C2E18339779 +Test: Encrypt +Comment: Set 3, vector 205 +Key: CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD +Plaintext: CDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCD +Ciphertext: 4579935A483BAC6B4CCD8C25BCC9E6DEAF46EA8B53F8B5E37CC436EAB85A1330 +Test: Encrypt +Comment: Set 3, vector 206 +Key: CECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECE +Plaintext: CECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECE +Ciphertext: E5F810DF5B215F559E76EF925F2B795915A7B03A6F7019FAC8E9127A7CE93F09 +Test: Encrypt +Comment: Set 3, vector 207 +Key: CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF +Plaintext: CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF +Ciphertext: 2EA0892E2B2F29A63526B37DECD18E31DC970A60E60A4D8414A5BD0D2D5491EF +Test: Encrypt +Comment: Set 3, vector 208 +Key: D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0 +Plaintext: D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0 +Ciphertext: 900F155E80A716199EB062827CDDDC4DA857550BA1C265A46D47BE4024706F40 +Test: Encrypt +Comment: Set 3, vector 209 +Key: D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1 +Plaintext: D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1 +Ciphertext: 5B495546838A97D8DF4B9CA95EF8350210A3ECAB81469678EBDE1E5846C1F42D +Test: Encrypt +Comment: Set 3, vector 210 +Key: D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2 +Plaintext: D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2 +Ciphertext: 60E7E367347BC3F4091CE34CCA288C8AFC6375ED8F4394D904FD8489280D50F1 +Test: Encrypt +Comment: Set 3, vector 211 +Key: D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3 +Plaintext: D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3D3 +Ciphertext: F215EED91D35B7BA649F05C3D1E2B254CB1215588AB78DF54F3CA221AB4A3F1B +Test: Encrypt +Comment: Set 3, vector 212 +Key: D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4 +Plaintext: D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4D4 +Ciphertext: 6441A445D808842C6185B81ACBC5AF86386C54C79026BFC21C1DB5111362AA15 +Test: Encrypt +Comment: Set 3, vector 213 +Key: D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5 +Plaintext: D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5 +Ciphertext: 4EE459EDAC1FE0CB08E80C8C13FCE8C44CBFECF7A7F9F14C15B5A92BB7F34E71 +Test: Encrypt +Comment: Set 3, vector 214 +Key: D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6 +Plaintext: D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6D6 +Ciphertext: 78826499B0F2F402E6DA3CACA36EA35492B7BD2A4D84575D0432E16368E78808 +Test: Encrypt +Comment: Set 3, vector 215 +Key: D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7 +Plaintext: D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7D7 +Ciphertext: BDFBCAE2761BEF6A411156AE01A63F9321EE969C56043F2A44C5D3D4BB017BC0 +Test: Encrypt +Comment: Set 3, vector 216 +Key: D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 +Plaintext: D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8 +Ciphertext: 926F2CD84035F9070C3506E6D7245FEA9A845F2D355785BB17E1D3C34FA81228 +Test: Encrypt +Comment: Set 3, vector 217 +Key: D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9 +Plaintext: D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9D9 +Ciphertext: 6C5F6B1C746967142D55FA3769A9417D5A44875D364DB4412B4F9EB254D9BB89 +Test: Encrypt +Comment: Set 3, vector 218 +Key: DADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADA +Plaintext: DADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADA +Ciphertext: 8329A1E54D9F45DB4E8CE6F1B481C3EE00D5511B52B3CDADCBD562A9F1B35770 +Test: Encrypt +Comment: Set 3, vector 219 +Key: DBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDB +Plaintext: DBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBDB +Ciphertext: 7A7FEEDEF1950F1A60529743163406CAF167097358377E0650CF0BB35CD783F6 +Test: Encrypt +Comment: Set 3, vector 220 +Key: DCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDC +Plaintext: DCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDCDC +Ciphertext: C52CFB15D2F53156701AE4951AA46BCFC872252447BB14E1CE19CAC074926984 +Test: Encrypt +Comment: Set 3, vector 221 +Key: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD +Plaintext: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD +Ciphertext: 79DFF8DC12ABCEC71E7FAE55ABC8C374135ECE2D52834BC77B860252B756D54A +Test: Encrypt +Comment: Set 3, vector 222 +Key: DEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDE +Plaintext: DEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDE +Ciphertext: 62963B66E680BD5602EC86DB7267E15CB1FF6EA698B54EBA661D125400C7F2DD +Test: Encrypt +Comment: Set 3, vector 223 +Key: DFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDF +Plaintext: DFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDF +Ciphertext: 0C2E76743ACC9CC0525D6E2C519D12C369CFA9E27F13068F98D2F32FAD7220CB +Test: Encrypt +Comment: Set 3, vector 224 +Key: E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0 +Plaintext: E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0 +Ciphertext: B464640E72C30DF092A5BB00F34568A7C04B8620265EDA53F19F3A06164AF980 +Test: Encrypt +Comment: Set 3, vector 225 +Key: E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 +Plaintext: E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1 +Ciphertext: 3725215E79F1FE3DC64B4316449FF98EB52D03330BFC848CD83A407475AADA3A +Test: Encrypt +Comment: Set 3, vector 226 +Key: E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2 +Plaintext: E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2 +Ciphertext: BA273F544C5076D523CC75F90E315A39E465D2B25434E6577FE629F27061BBA4 +Test: Encrypt +Comment: Set 3, vector 227 +Key: E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3 +Plaintext: E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3E3 +Ciphertext: 472161A0F42E64BD0FE6D448996C370E2C3A56BDE16B378EAA31740551121B4E +Test: Encrypt +Comment: Set 3, vector 228 +Key: E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4 +Plaintext: E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4E4 +Ciphertext: EA089A10A597504D057E1F03064C9465C1A707C9472A7C0DBAD6978F5BB83A46 +Test: Encrypt +Comment: Set 3, vector 229 +Key: E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5 +Plaintext: E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5E5 +Ciphertext: E91B3433426F88FA31A05E17906E55EA1D803ADFE080C51FBD98290CBF427BEF +Test: Encrypt +Comment: Set 3, vector 230 +Key: E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6 +Plaintext: E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6E6 +Ciphertext: 747C4999D0256384349A5FB132DE1AAD4D7FC48507FEC206B80ED429AF7FDBDB +Test: Encrypt +Comment: Set 3, vector 231 +Key: E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7 +Plaintext: E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7 +Ciphertext: 3F8058A1A9B7B0A9C31B4670EEAA6988BF2D41E9B3417EF899EF12CBBC9C77DE +Test: Encrypt +Comment: Set 3, vector 232 +Key: E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8 +Plaintext: E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8E8 +Ciphertext: 9DA431EC0DADDEC4A76B3830B20AA03D346AD09691FB98FC0E9A8987F7B70EDF +Test: Encrypt +Comment: Set 3, vector 233 +Key: E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9 +Plaintext: E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9E9 +Ciphertext: 63BF528E184A43EF807DC9169BDB9CD7B63EE144478A4735EC2EE3A5A7EE460A +Test: Encrypt +Comment: Set 3, vector 234 +Key: EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA +Plaintext: EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA +Ciphertext: 73DC5F8AFA9493AD7767D15A36E7741044EFC225136B4972DC5294E80071A64D +Test: Encrypt +Comment: Set 3, vector 235 +Key: EBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEB +Plaintext: EBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEBEB +Ciphertext: 7EEE75D690458A604D20CD21ED64B228F0C3563DB8FB925341FC02845B6E06BA +Test: Encrypt +Comment: Set 3, vector 236 +Key: ECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECEC +Plaintext: ECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECECEC +Ciphertext: AA4D9E1A0157AC347DC7A1997718944427BD579DC18B94F181390E8C36A1305C +Test: Encrypt +Comment: Set 3, vector 237 +Key: EDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDED +Plaintext: EDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDED +Ciphertext: 1695BC5C3D63F4B0E0BC3225F00BB0B8E8D29F3DC09584353E11510002E2BE53 +Test: Encrypt +Comment: Set 3, vector 238 +Key: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE +Plaintext: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE +Ciphertext: C68C7A2FBDA419A515AE816480490BFB2A72A4B6534A19A8D8C6C85FAA949567 +Test: Encrypt +Comment: Set 3, vector 239 +Key: EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF +Plaintext: EFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEF +Ciphertext: 5F45E7F72A64C66269F83714A88A0701561C3E7AF33BB48887D4439F5DE4A82D +Test: Encrypt +Comment: Set 3, vector 240 +Key: F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +Plaintext: F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0 +Ciphertext: AD49A5C8EB06256147F02301FB47710E915B5A8FC3219C0D56A19382977119FC +Test: Encrypt +Comment: Set 3, vector 241 +Key: F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1 +Plaintext: F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1 +Ciphertext: 2387AF70EE04E7F25277E81081B044EA24090D503CE8F64997BB610C762D8F6F +Test: Encrypt +Comment: Set 3, vector 242 +Key: F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2 +Plaintext: F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2F2 +Ciphertext: B5D496DD36BA0B47832C170A53760CE5E47B1FF5C28848F5F7A1827E94BC73CB +Test: Encrypt +Comment: Set 3, vector 243 +Key: F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 +Plaintext: F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3 +Ciphertext: 77978F2EAB7E8B6B32C9293B83F51419785A0CD276276CB417ACA806A456A6AE +Test: Encrypt +Comment: Set 3, vector 244 +Key: F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4 +Plaintext: F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4F4 +Ciphertext: E3CBD41F80B27C9A684D7C7C27BBCA9FD59E5E81E93B7BC5BFDF66722EF68EEE +Test: Encrypt +Comment: Set 3, vector 245 +Key: F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5 +Plaintext: F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5F5 +Ciphertext: 4482F0C362CB423104CAA26E1415B0B7519E1189624D313E65D324C6DC95F516 +Test: Encrypt +Comment: Set 3, vector 246 +Key: F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6 +Plaintext: F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6F6 +Ciphertext: CD72EE9A6919348595286348C7E488DB3648458688F72BAD994B26FE6999E676 +Test: Encrypt +Comment: Set 3, vector 247 +Key: F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7 +Plaintext: F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7F7 +Ciphertext: 03EF38F91710AE8BCC8B9193F6A55A7C90C66300D20EDCF5B4946F3B38BEF6C5 +Test: Encrypt +Comment: Set 3, vector 248 +Key: F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8 +Plaintext: F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8F8 +Ciphertext: B67638D30578AB2319FE275D0B833B50D7ABF01E8760F566D0D441D8EAFDF8AA +Test: Encrypt +Comment: Set 3, vector 249 +Key: F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9 +Plaintext: F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9F9 +Ciphertext: 98B05FF6042436505C7163415E187E09F10C3B1A86FA4B458CE1EF31022F5D16 +Test: Encrypt +Comment: Set 3, vector 250 +Key: FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA +Plaintext: FAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFAFA +Ciphertext: B670A350A2CF0478412307EF00F97F8B30175CDB7593FF4686BD614B41444342 +Test: Encrypt +Comment: Set 3, vector 251 +Key: FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB +Plaintext: FBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFBFB +Ciphertext: D7FD492E6302265C24FAB910AA1335C29D53406147E853F7604F4AF1A9407E83 +Test: Encrypt +Comment: Set 3, vector 252 +Key: FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC +Plaintext: FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC +Ciphertext: 28926789363A4306E2C75FD1D8FDF0FE6B62FDB2AFAEDDA6F47A565C2781968B +Test: Encrypt +Comment: Set 3, vector 253 +Key: FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD +Plaintext: FDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFDFD +Ciphertext: 813C816CD4B18F20BD06E2E93CFAA717EBB6554B556CC33D67530608A9BF100F +Test: Encrypt +Comment: Set 3, vector 254 +Key: FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE +Plaintext: FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE +Ciphertext: 5DC15C83E7C4F5AAF8D8482ED1E443271B28B59288783DBCDDEC3544E3368A6E +Test: Encrypt +Comment: Set 3, vector 255 +Key: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +Plaintext: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +Ciphertext: 0598127BAF11706F77402000D730C54A0B84C868A98C6CA4D7F3C0FA06A78B7A +Test: Encrypt diff --git a/src-cryptopp/TestVectors/sosemanuk.txt b/src-cryptopp/TestVectors/sosemanuk.txt new file mode 100644 index 0000000..435d89b --- /dev/null +++ b/src-cryptopp/TestVectors/sosemanuk.txt @@ -0,0 +1,25 @@ +AlgorithmType: SymmetricCipher +Source: Sosemanuk reference implementation, compiled with -DSOSEMANUK_VECTOR +Key: A7C083FEB7 +IV: 00112233445566778899AABBCCDDEEFF +Name: Sosemanuk +Plaintext: r160 00 +Ciphertext: \ + FE 81 D2 16 2C 9A 10 0D 04 89 5C 45 4A 77 51 5B\ + BE 6A 43 1A 93 5C B9 0E 22 21 EB B7 EF 50 23 28\ + 94 35 39 49 2E FF 63 10 C8 71 05 4C 28 89 CC 72\ + 8F 82 E8 6B 1A FF F4 33 4B 61 27 A1 3A 15 5C 75\ + 15 16 30 BD 48 2E B6 73 FF 5D B4 77 FA 6C 53 EB\ + E1 A4 EC 38 C2 3C 54 00 C3 15 45 5D 93 A2 AC ED\ + 95 98 60 47 27 FA 34 0D 5F 2A 8B D7 57 B7 78 33\ + F7 4B D2 BC 04 93 13 C8 06 16 B4 A0 62 68 AE 35\ + 0D B9 2E EC 4F A5 6C 17 13 74 A6 7A 80 C0 06 D0\ + EA D0 48 CE 7B 64 0F 17 D3 D5 A6 2D 1F 25 1C 21 +Test: Encrypt +Source: http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/sosemanuk/unverified.test-vectors?rev=189&view=auto +Comment: Set 6, vector# 3 +Key: 0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C +IV: 288FF65DC42B92F960C72E95FC63CA31 +Plaintext: r131072 00 +CiphertextXorDigest: CC09FB7405DD54BBF09407B1D2033FBBAC53F388DD387A46F2B8FCFF692A7838353523A621A55D08DA0CA5348AE96D8B0D6A028F309982EF6628054D01B9A368 +Test: EncryptXorDigest diff --git a/src-cryptopp/TestVectors/tea.txt b/src-cryptopp/TestVectors/tea.txt new file mode 100644 index 0000000..dc46d3f --- /dev/null +++ b/src-cryptopp/TestVectors/tea.txt @@ -0,0 +1,711 @@ +AlgorithmType: SymmetricCipher +Name: TEA/ECB +Source: http://www.cix.co.uk/~klockstone/teavect.htm +Comment: test 1 +Plaintext: 00000000 00000000 +Key: 00000000 00000000 00000000 00000000 +Ciphertext: 41ea3a0a 94baa940 +Test: Encrypt +Comment: test 2 +Plaintext: 94baa940 00000000 +Key: 00000000 00000000 00000000 41ea3a0a +Ciphertext: 4e8e7829 7d8236d8 +Test: Encrypt +Comment: test 3 +Plaintext: 7d8236d8 00000000 +Key: 00000000 00000000 41ea3a0a 4e8e7829 +Ciphertext: c88ba95e e7edac02 +Test: Encrypt +Comment: test 4 +Plaintext: e7edac02 00000000 +Key: 00000000 41ea3a0a 4e8e7829 c88ba95e +Ciphertext: b84e28af b6b62088 +Test: Encrypt +Comment: test 5 +Plaintext: b6b62088 00000000 +Key: 41ea3a0a 4e8e7829 c88ba95e b84e28af +Ciphertext: a0a47295 8fadf3b3 +Test: Encrypt +Comment: test 6 +Plaintext: 8fadf3b3 41ea3a0a +Key: 4e8e7829 c88ba95e b84e28af a0a47295 +Ciphertext: ed650698 cf9f2b79 +Test: Encrypt +Comment: test 7 +Plaintext: cf9f2b79 4e8e7829 +Key: c88ba95e b84e28af a0a47295 ed650698 +Ciphertext: 1024eea0 6220ae1c +Test: Encrypt +Comment: test 8 +Plaintext: 6220ae1c c88ba95e +Key: b84e28af a0a47295 ed650698 1024eea0 +Ciphertext: 5ddf75d9 7a4ce68f +Test: Encrypt +Comment: test 9 +Plaintext: 7a4ce68f b84e28af +Key: a0a47295 ed650698 1024eea0 5ddf75d9 +Ciphertext: f1be9d1e 8dd4a984 +Test: Encrypt +Comment: test 10 +Plaintext: 8dd4a984 a0a47295 +Key: ed650698 1024eea0 5ddf75d9 f1be9d1e +Ciphertext: d32c758c 092dabad +Test: Encrypt +Comment: test 11 +Plaintext: 092dabad ed650698 +Key: 1024eea0 5ddf75d9 f1be9d1e d32c758c +Ciphertext: bdb43728 f7183fc0 +Test: Encrypt +Comment: test 12 +Plaintext: f7183fc0 1024eea0 +Key: 5ddf75d9 f1be9d1e d32c758c bdb43728 +Ciphertext: a9c3801a d9dcfb4e +Test: Encrypt +Comment: test 13 +Plaintext: d9dcfb4e 5ddf75d9 +Key: f1be9d1e d32c758c bdb43728 a9c3801a +Ciphertext: 32a1e654 a9df917c +Test: Encrypt +Comment: test 14 +Plaintext: a9df917c f1be9d1e +Key: d32c758c bdb43728 a9c3801a 32a1e654 +Ciphertext: 08b63bb9 b20bd3e8 +Test: Encrypt +Comment: test 15 +Plaintext: b20bd3e8 d32c758c +Key: bdb43728 a9c3801a 32a1e654 08b63bb9 +Ciphertext: 21410574 cc4264c6 +Test: Encrypt +Comment: test 16 +Plaintext: cc4264c6 bdb43728 +Key: a9c3801a 32a1e654 08b63bb9 21410574 +Ciphertext: 4ec5d2e2 5ada1d89 +Test: Encrypt +Comment: test 17 +Plaintext: 5ada1d89 a9c3801a +Key: 32a1e654 08b63bb9 21410574 4ec5d2e2 +Ciphertext: dd46249e 28aa0b4b +Test: Encrypt +Comment: test 18 +Plaintext: 28aa0b4b 32a1e654 +Key: 08b63bb9 21410574 4ec5d2e2 dd46249e +Ciphertext: 2486dcba a713df03 +Test: Encrypt +Comment: test 19 +Plaintext: a713df03 08b63bb9 +Key: 21410574 4ec5d2e2 dd46249e 2486dcba +Ciphertext: b7c7af9d 1acb6cab +Test: Encrypt +Comment: test 20 +Plaintext: 1acb6cab 21410574 +Key: 4ec5d2e2 dd46249e 2486dcba b7c7af9d +Ciphertext: 8cc0400a 9aa49fbb +Test: Encrypt +Comment: test 21 +Plaintext: 9aa49fbb 4ec5d2e2 +Key: dd46249e 2486dcba b7c7af9d 8cc0400a +Ciphertext: 9c241876 6cbc8c66 +Test: Encrypt +Comment: test 22 +Plaintext: 6cbc8c66 dd46249e +Key: 2486dcba b7c7af9d 8cc0400a 9c241876 +Ciphertext: b59c5d45 a90066f9 +Test: Encrypt +Comment: test 23 +Plaintext: a90066f9 2486dcba +Key: b7c7af9d 8cc0400a 9c241876 b59c5d45 +Ciphertext: b765a1b3 64b37eb0 +Test: Encrypt +Comment: test 24 +Plaintext: 64b37eb0 b7c7af9d +Key: 8cc0400a 9c241876 b59c5d45 b765a1b3 +Ciphertext: 7b172fac f5ab4933 +Test: Encrypt +Comment: test 25 +Plaintext: f5ab4933 8cc0400a +Key: 9c241876 b59c5d45 b765a1b3 7b172fac +Ciphertext: fe48f4fb ada404b1 +Test: Encrypt +Comment: test 26 +Plaintext: ada404b1 9c241876 +Key: b59c5d45 b765a1b3 7b172fac fe48f4fb +Ciphertext: c5294093 c1d53e3d +Test: Encrypt +Comment: test 27 +Plaintext: c1d53e3d b59c5d45 +Key: b765a1b3 7b172fac fe48f4fb c5294093 +Ciphertext: 759ca8e2 77a96649 +Test: Encrypt +Comment: test 28 +Plaintext: 77a96649 b765a1b3 +Key: 7b172fac fe48f4fb c5294093 759ca8e2 +Ciphertext: 69c53e0f 3e979807 +Test: Encrypt +Comment: test 29 +Plaintext: 3e979807 7b172fac +Key: fe48f4fb c5294093 759ca8e2 69c53e0f +Ciphertext: 60388ada a21fa8e8 +Test: Encrypt +Comment: test 30 +Plaintext: a21fa8e8 fe48f4fb +Key: c5294093 759ca8e2 69c53e0f 60388ada +Ciphertext: df70a1f5 ac4aa407 +Test: Encrypt +Comment: test 31 +Plaintext: ac4aa407 c5294093 +Key: 759ca8e2 69c53e0f 60388ada df70a1f5 +Ciphertext: d9cb4e09 92636233 +Test: Encrypt +Comment: test 32 +Plaintext: 92636233 759ca8e2 +Key: 69c53e0f 60388ada df70a1f5 d9cb4e09 +Ciphertext: 7d2c6c57 7a6adb4d +Test: Encrypt +Comment: test 33 +Plaintext: 7a6adb4d 69c53e0f +Key: 60388ada df70a1f5 d9cb4e09 7d2c6c57 +Ciphertext: 44b71215 cf25368a +Test: Encrypt +Comment: test 34 +Plaintext: cf25368a 60388ada +Key: df70a1f5 d9cb4e09 7d2c6c57 44b71215 +Ciphertext: c10105a1 ef781a18 +Test: Encrypt +Comment: test 35 +Plaintext: ef781a18 df70a1f5 +Key: d9cb4e09 7d2c6c57 44b71215 c10105a1 +Ciphertext: bfdb29fa 9ece39b6 +Test: Encrypt +Comment: test 36 +Plaintext: 9ece39b6 d9cb4e09 +Key: 7d2c6c57 44b71215 c10105a1 bfdb29fa +Ciphertext: 9b0b256d dc04574c +Test: Encrypt +Comment: test 37 +Plaintext: dc04574c 7d2c6c57 +Key: 44b71215 c10105a1 bfdb29fa 9b0b256d +Ciphertext: f8295142 8c022711 +Test: Encrypt +Comment: test 38 +Plaintext: 8c022711 44b71215 +Key: c10105a1 bfdb29fa 9b0b256d f8295142 +Ciphertext: 61341d1c 3a85f2f0 +Test: Encrypt +Comment: test 39 +Plaintext: 3a85f2f0 c10105a1 +Key: bfdb29fa 9b0b256d f8295142 61341d1c +Ciphertext: f6a0d30c ad230209 +Test: Encrypt +Comment: test 40 +Plaintext: ad230209 bfdb29fa +Key: 9b0b256d f8295142 61341d1c f6a0d30c +Ciphertext: 3de21a3f aa0cf5c9 +Test: Encrypt +Comment: test 41 +Plaintext: aa0cf5c9 9b0b256d +Key: f8295142 61341d1c f6a0d30c 3de21a3f +Ciphertext: a7e307c6 bd52d939 +Test: Encrypt +Comment: test 42 +Plaintext: bd52d939 f8295142 +Key: 61341d1c f6a0d30c 3de21a3f a7e307c6 +Ciphertext: 017bc3a7 66fd8c77 +Test: Encrypt +Comment: test 43 +Plaintext: 66fd8c77 61341d1c +Key: f6a0d30c 3de21a3f a7e307c6 017bc3a7 +Ciphertext: d8f8fc86 d01b5761 +Test: Encrypt +Comment: test 44 +Plaintext: d01b5761 f6a0d30c +Key: 3de21a3f a7e307c6 017bc3a7 d8f8fc86 +Ciphertext: e186c41a 5e6e5a4d +Test: Encrypt +Comment: test 45 +Plaintext: 5e6e5a4d 3de21a3f +Key: a7e307c6 017bc3a7 d8f8fc86 e186c41a +Ciphertext: 4368d224 dbb4e677 +Test: Encrypt +Comment: test 46 +Plaintext: dbb4e677 a7e307c6 +Key: 017bc3a7 d8f8fc86 e186c41a 4368d224 +Ciphertext: 9bd0321e 84096523 +Test: Encrypt +Comment: test 47 +Plaintext: 84096523 017bc3a7 +Key: d8f8fc86 e186c41a 4368d224 9bd0321e +Ciphertext: b7c56d5b 97c65866 +Test: Encrypt +Comment: test 48 +Plaintext: 97c65866 d8f8fc86 +Key: e186c41a 4368d224 9bd0321e b7c56d5b +Ciphertext: 63a1bfac 5a5d7ca2 +Test: Encrypt +Comment: test 49 +Plaintext: 5a5d7ca2 e186c41a +Key: 4368d224 9bd0321e b7c56d5b 63a1bfac +Ciphertext: 91f56dff 7281794f +Test: Encrypt +Comment: test 50 +Plaintext: 7281794f 4368d224 +Key: 9bd0321e b7c56d5b 63a1bfac 91f56dff +Ciphertext: e4c63780 019aedf7 +Test: Encrypt +Comment: test 51 +Plaintext: 019aedf7 9bd0321e +Key: b7c56d5b 63a1bfac 91f56dff e4c63780 +Ciphertext: a9fb56e7 35f4aeca +Test: Encrypt +Comment: test 52 +Plaintext: 35f4aeca b7c56d5b +Key: 63a1bfac 91f56dff e4c63780 a9fb56e7 +Ciphertext: a6537187 f0f1ba93 +Test: Encrypt +Comment: test 53 +Plaintext: f0f1ba93 63a1bfac +Key: 91f56dff e4c63780 a9fb56e7 a6537187 +Ciphertext: cc960eda e44c6b8f +Test: Encrypt +Comment: test 54 +Plaintext: e44c6b8f 91f56dff +Key: e4c63780 a9fb56e7 a6537187 cc960eda +Ciphertext: e12f106d 4f1152d0 +Test: Encrypt +Comment: test 55 +Plaintext: 4f1152d0 e4c63780 +Key: a9fb56e7 a6537187 cc960eda e12f106d +Ciphertext: 556ad853 f79992fd +Test: Encrypt +Comment: test 56 +Plaintext: f79992fd a9fb56e7 +Key: a6537187 cc960eda e12f106d 556ad853 +Ciphertext: 78e8e265 128df6ad +Test: Encrypt +Comment: test 57 +Plaintext: 128df6ad a6537187 +Key: cc960eda e12f106d 556ad853 78e8e265 +Ciphertext: f23892aa 288cb926 +Test: Encrypt +Comment: test 58 +Plaintext: 288cb926 cc960eda +Key: e12f106d 556ad853 78e8e265 f23892aa +Ciphertext: 1d115839 6a117fca +Test: Encrypt +Comment: test 59 +Plaintext: 6a117fca e12f106d +Key: 556ad853 78e8e265 f23892aa 1d115839 +Ciphertext: cf899635 5b087e34 +Test: Encrypt +Comment: test 60 +Plaintext: 5b087e34 556ad853 +Key: 78e8e265 f23892aa 1d115839 cf899635 +Ciphertext: 5c60bff2 e68d88c2 +Test: Encrypt +Comment: test 61 +Plaintext: e68d88c2 78e8e265 +Key: f23892aa 1d115839 cf899635 5c60bff2 +Ciphertext: 7072d01c bffeb50a +Test: Encrypt +Comment: test 62 +Plaintext: bffeb50a f23892aa +Key: 1d115839 cf899635 5c60bff2 7072d01c +Ciphertext: 4513c5eb 9c99ae9e +Test: Encrypt +Comment: test 63 +Plaintext: 9c99ae9e 1d115839 +Key: cf899635 5c60bff2 7072d01c 4513c5eb +Ciphertext: 8f3a38ab 80d9c4ad +Test: Encrypt +Comment: test 64 +Plaintext: 80d9c4ad cf899635 +Key: 5c60bff2 7072d01c 4513c5eb 8f3a38ab +Ciphertext: 2bb0f1b3 c023ed11 +Test: Encrypt + +AlgorithmType: SymmetricCipher +Name: XTEA/ECB +Source: http://www.cix.co.uk/~klockstone/teavect.htm +Comment: test 1 +Plaintext: 00000000 00000000 +Key: 00000000 00000000 00000000 00000000 +Rounds: 1 +Ciphertext: 00000000 9e3779b9 +Test: Encrypt +Comment: test 2 +Plaintext: 9e3779b9 00000000 +Key: 00000000 00000000 00000000 00000000 +Rounds: 2 +Ciphertext: ec01a1de aaa0256d +Test: Encrypt +Comment: test 3 +Plaintext: aaa0256d 00000000 +Key: 00000000 00000000 00000000 ec01a1de +Rounds: 3 +Ciphertext: 114f6d74 a39e590c +Test: Encrypt +Comment: test 4 +Plaintext: a39e590c 00000000 +Key: 00000000 00000000 ec01a1de 114f6d74 +Rounds: 4 +Ciphertext: bc3a7de2 4e238eb9 +Test: Encrypt +Comment: test 5 +Plaintext: 4e238eb9 00000000 +Key: 00000000 ec01a1de 114f6d74 bc3a7de2 +Rounds: 5 +Ciphertext: 845846cf 2f36d07f +Test: Encrypt +Comment: test 6 +Plaintext: 2f36d07f 00000000 +Key: ec01a1de 114f6d74 bc3a7de2 845846cf +Rounds: 6 +Ciphertext: 2794a127 4f3e4b6a +Test: Encrypt +Comment: test 7 +Plaintext: 4f3e4b6a ec01a1de +Key: 114f6d74 bc3a7de2 845846cf 2794a127 +Rounds: 7 +Ciphertext: 6b8ea8b8 d99e66c3 +Test: Encrypt +Comment: test 8 +Plaintext: d99e66c3 114f6d74 +Key: bc3a7de2 845846cf 2794a127 6b8ea8b8 +Rounds: 8 +Ciphertext: 31c5fa6c 241756d6 +Test: Encrypt +Comment: test 9 +Plaintext: 241756d6 bc3a7de2 +Key: 845846cf 2794a127 6b8ea8b8 31c5fa6c +Rounds: 9 +Ciphertext: 4a581696 1fd58a6b +Test: Encrypt +Comment: test 10 +Plaintext: 1fd58a6b 845846cf +Key: 2794a127 6b8ea8b8 31c5fa6c 4a581696 +Rounds: 10 +Ciphertext: dfcd0451 df8822cd +Test: Encrypt +Comment: test 11 +Plaintext: df8822cd 2794a127 +Key: 6b8ea8b8 31c5fa6c 4a581696 dfcd0451 +Rounds: 11 +Ciphertext: 3ad1ff17 f465776c +Test: Encrypt +Comment: test 12 +Plaintext: f465776c 6b8ea8b8 +Key: 31c5fa6c 4a581696 dfcd0451 3ad1ff17 +Rounds: 12 +Ciphertext: 6a1d78c8 4d30bdb9 +Test: Encrypt +Comment: test 13 +Plaintext: 4d30bdb9 31c5fa6c +Key: 4a581696 dfcd0451 3ad1ff17 6a1d78c8 +Rounds: 13 +Ciphertext: 08c86d67 f6ef939b +Test: Encrypt +Comment: test 14 +Plaintext: f6ef939b 4a581696 +Key: dfcd0451 3ad1ff17 6a1d78c8 08c86d67 +Rounds: 14 +Ciphertext: 2a65bfbe f733428c +Test: Encrypt +Comment: test 15 +Plaintext: f733428c dfcd0451 +Key: 3ad1ff17 6a1d78c8 08c86d67 2a65bfbe +Rounds: 15 +Ciphertext: b4bd6e46 40672bcc +Test: Encrypt +Comment: test 16 +Plaintext: 40672bcc 3ad1ff17 +Key: 6a1d78c8 08c86d67 2a65bfbe b4bd6e46 +Rounds: 16 +Ciphertext: 1d8e6992 9a478905 +Test: Encrypt +Comment: test 17 +Plaintext: 9a478905 6a1d78c8 +Key: 08c86d67 2a65bfbe b4bd6e46 1d8e6992 +Rounds: 17 +Ciphertext: f8994ada 80dee76a +Test: Encrypt +Comment: test 18 +Plaintext: 80dee76a 08c86d67 +Key: 2a65bfbe b4bd6e46 1d8e6992 f8994ada +Rounds: 18 +Ciphertext: 0997e6ed cdfef370 +Test: Encrypt +Comment: test 19 +Plaintext: cdfef370 2a65bfbe +Key: b4bd6e46 1d8e6992 f8994ada 0997e6ed +Rounds: 19 +Ciphertext: ece50553 10b76c66 +Test: Encrypt +Comment: test 20 +Plaintext: 10b76c66 b4bd6e46 +Key: 1d8e6992 f8994ada 0997e6ed ece50553 +Rounds: 20 +Ciphertext: a6d39c7b dce1a473 +Test: Encrypt +Comment: test 21 +Plaintext: dce1a473 1d8e6992 +Key: f8994ada 0997e6ed ece50553 a6d39c7b +Rounds: 21 +Ciphertext: 21d06fb7 fbb98544 +Test: Encrypt +Comment: test 22 +Plaintext: fbb98544 f8994ada +Key: 0997e6ed ece50553 a6d39c7b 21d06fb7 +Rounds: 22 +Ciphertext: 72cdd36c e1115fb6 +Test: Encrypt +Comment: test 23 +Plaintext: e1115fb6 0997e6ed +Key: ece50553 a6d39c7b 21d06fb7 72cdd36c +Rounds: 23 +Ciphertext: 25bc6eb3 e4c28ab7 +Test: Encrypt +Comment: test 24 +Plaintext: e4c28ab7 ece50553 +Key: a6d39c7b 21d06fb7 72cdd36c 25bc6eb3 +Rounds: 24 +Ciphertext: 4932a288 78020b9e +Test: Encrypt +Comment: test 25 +Plaintext: 78020b9e a6d39c7b +Key: 21d06fb7 72cdd36c 25bc6eb3 4932a288 +Rounds: 25 +Ciphertext: 25285da1 b66c4459 +Test: Encrypt +Comment: test 26 +Plaintext: b66c4459 21d06fb7 +Key: 72cdd36c 25bc6eb3 4932a288 25285da1 +Rounds: 26 +Ciphertext: 39b0155c f227ab20 +Test: Encrypt +Comment: test 27 +Plaintext: f227ab20 72cdd36c +Key: 25bc6eb3 4932a288 25285da1 39b0155c +Rounds: 27 +Ciphertext: 547571aa f38f1e39 +Test: Encrypt +Comment: test 28 +Plaintext: f38f1e39 25bc6eb3 +Key: 4932a288 25285da1 39b0155c 547571aa +Rounds: 28 +Ciphertext: 27f917b1 e5796aee +Test: Encrypt +Comment: test 29 +Plaintext: e5796aee 4932a288 +Key: 25285da1 39b0155c 547571aa 27f917b1 +Rounds: 29 +Ciphertext: c1da8993 670f9fd2 +Test: Encrypt +Comment: test 30 +Plaintext: 670f9fd2 25285da1 +Key: 39b0155c 547571aa 27f917b1 c1da8993 +Rounds: 30 +Ciphertext: 60e2acaa d0a60db4 +Test: Encrypt +Comment: test 31 +Plaintext: d0a60db4 39b0155c +Key: 547571aa 27f917b1 c1da8993 60e2acaa +Rounds: 31 +Ciphertext: a6eb923d af20a390 +Test: Encrypt +Comment: test 32 +Plaintext: af20a390 547571aa +Key: 27f917b1 c1da8993 60e2acaa a6eb923d +Rounds: 32 +Ciphertext: d26428af 0a202283 +Test: Encrypt +Comment: test 33 +Plaintext: 0a202283 27f917b1 +Key: c1da8993 60e2acaa a6eb923d d26428af +Rounds: 33 +Ciphertext: 1c03ceb9 96e9f2d3 +Test: Encrypt +Comment: test 34 +Plaintext: 96e9f2d3 c1da8993 +Key: 60e2acaa a6eb923d d26428af 1c03ceb9 +Rounds: 34 +Ciphertext: e260b3c1 bbd7dff0 +Test: Encrypt +Comment: test 35 +Plaintext: bbd7dff0 60e2acaa +Key: a6eb923d d26428af 1c03ceb9 e260b3c1 +Rounds: 35 +Ciphertext: d33073f9 12841b97 +Test: Encrypt +Comment: test 36 +Plaintext: 12841b97 a6eb923d +Key: d26428af 1c03ceb9 e260b3c1 d33073f9 +Rounds: 36 +Ciphertext: 17b7ea05 1d723f18 +Test: Encrypt +Comment: test 37 +Plaintext: 1d723f18 d26428af +Key: 1c03ceb9 e260b3c1 d33073f9 17b7ea05 +Rounds: 37 +Ciphertext: 9f571045 31e849b9 +Test: Encrypt +Comment: test 38 +Plaintext: 31e849b9 1c03ceb9 +Key: e260b3c1 d33073f9 17b7ea05 9f571045 +Rounds: 38 +Ciphertext: 288351d2 bd0a0054 +Test: Encrypt +Comment: test 39 +Plaintext: bd0a0054 e260b3c1 +Key: d33073f9 17b7ea05 9f571045 288351d2 +Rounds: 39 +Ciphertext: 9236883a 2bd13143 +Test: Encrypt +Comment: test 40 +Plaintext: 2bd13143 d33073f9 +Key: 17b7ea05 9f571045 288351d2 9236883a +Rounds: 40 +Ciphertext: e91dcf23 7c3fd716 +Test: Encrypt +Comment: test 41 +Plaintext: 7c3fd716 17b7ea05 +Key: 9f571045 288351d2 9236883a e91dcf23 +Rounds: 41 +Ciphertext: 5c8ff51e c3abe43d +Test: Encrypt +Comment: test 42 +Plaintext: c3abe43d 9f571045 +Key: 288351d2 9236883a e91dcf23 5c8ff51e +Rounds: 42 +Ciphertext: 446e9f7c ecb0eb4d +Test: Encrypt +Comment: test 43 +Plaintext: ecb0eb4d 288351d2 +Key: 9236883a e91dcf23 5c8ff51e 446e9f7c +Rounds: 43 +Ciphertext: 86455f77 ffc74050 +Test: Encrypt +Comment: test 44 +Plaintext: ffc74050 9236883a +Key: e91dcf23 5c8ff51e 446e9f7c 86455f77 +Rounds: 44 +Ciphertext: ae85d873 e21ef8d3 +Test: Encrypt +Comment: test 45 +Plaintext: e21ef8d3 e91dcf23 +Key: 5c8ff51e 446e9f7c 86455f77 ae85d873 +Rounds: 45 +Ciphertext: cf411a68 18dce768 +Test: Encrypt +Comment: test 46 +Plaintext: 18dce768 5c8ff51e +Key: 446e9f7c 86455f77 ae85d873 cf411a68 +Rounds: 46 +Ciphertext: 4ef68794 07d2b1b3 +Test: Encrypt +Comment: test 47 +Plaintext: 07d2b1b3 446e9f7c +Key: 86455f77 ae85d873 cf411a68 4ef68794 +Rounds: 47 +Ciphertext: d75a1925 07476976 +Test: Encrypt +Comment: test 48 +Plaintext: 07476976 86455f77 +Key: ae85d873 cf411a68 4ef68794 d75a1925 +Rounds: 48 +Ciphertext: 909d29cb 16b37e1b +Test: Encrypt +Comment: test 49 +Plaintext: 16b37e1b ae85d873 +Key: cf411a68 4ef68794 d75a1925 909d29cb +Rounds: 49 +Ciphertext: e05578cd bd40cd0c +Test: Encrypt +Comment: test 50 +Plaintext: bd40cd0c cf411a68 +Key: 4ef68794 d75a1925 909d29cb e05578cd +Rounds: 50 +Ciphertext: 988b50e5 adf1b74c +Test: Encrypt +Comment: test 51 +Plaintext: adf1b74c 4ef68794 +Key: d75a1925 909d29cb e05578cd 988b50e5 +Rounds: 51 +Ciphertext: 90699d3d d2333c19 +Test: Encrypt +Comment: test 52 +Plaintext: d2333c19 d75a1925 +Key: 909d29cb e05578cd 988b50e5 90699d3d +Rounds: 52 +Ciphertext: a119eb2e 3488c65b +Test: Encrypt +Comment: test 53 +Plaintext: 3488c65b 909d29cb +Key: e05578cd 988b50e5 90699d3d a119eb2e +Rounds: 53 +Ciphertext: e4c43e62 e9c4894b +Test: Encrypt +Comment: test 54 +Plaintext: e9c4894b e05578cd +Key: 988b50e5 90699d3d a119eb2e e4c43e62 +Rounds: 54 +Ciphertext: e1aec3f2 1976c384 +Test: Encrypt +Comment: test 55 +Plaintext: 1976c384 988b50e5 +Key: 90699d3d a119eb2e e4c43e62 e1aec3f2 +Rounds: 55 +Ciphertext: 1b7b0e2b 0b392b46 +Test: Encrypt +Comment: test 56 +Plaintext: 0b392b46 90699d3d +Key: a119eb2e e4c43e62 e1aec3f2 1b7b0e2b +Rounds: 56 +Ciphertext: 1a6ffc0c 600f2ee0 +Test: Encrypt +Comment: test 57 +Plaintext: 600f2ee0 a119eb2e +Key: e4c43e62 e1aec3f2 1b7b0e2b 1a6ffc0c +Rounds: 57 +Ciphertext: 82ccc9d3 94ba3d77 +Test: Encrypt +Comment: test 58 +Plaintext: 94ba3d77 e4c43e62 +Key: e1aec3f2 1b7b0e2b 1a6ffc0c 82ccc9d3 +Rounds: 58 +Ciphertext: 38b5ebd1 c56af77e +Test: Encrypt +Comment: test 59 +Plaintext: c56af77e e1aec3f2 +Key: 1b7b0e2b 1a6ffc0c 82ccc9d3 38b5ebd1 +Rounds: 59 +Ciphertext: f5571f9d fe136a04 +Test: Encrypt +Comment: test 60 +Plaintext: fe136a04 1b7b0e2b +Key: 1a6ffc0c 82ccc9d3 38b5ebd1 f5571f9d +Rounds: 60 +Ciphertext: 62ee209f 08550367 +Test: Encrypt +Comment: test 61 +Plaintext: 08550367 1a6ffc0c +Key: 82ccc9d3 38b5ebd1 f5571f9d 62ee209f +Rounds: 61 +Ciphertext: 069b7afc b0fcde91 +Test: Encrypt +Comment: test 62 +Plaintext: b0fcde91 82ccc9d3 +Key: 38b5ebd1 f5571f9d 62ee209f 069b7afc +Rounds: 62 +Ciphertext: 376a8936 11b9c087 +Test: Encrypt +Comment: test 63 +Plaintext: 11b9c087 38b5ebd1 +Key: f5571f9d 62ee209f 069b7afc 376a8936 +Rounds: 63 +Ciphertext: cdc9e923 2e6c1fe7 +Test: Encrypt +Comment: test 64 +Plaintext: 2e6c1fe7 f5571f9d +Key: 62ee209f 069b7afc 376a8936 cdc9e923 +Rounds: 64 +Ciphertext: 7a01cbc9 b03d6068 +Test: Encrypt diff --git a/src-cryptopp/TestVectors/ttmac.txt b/src-cryptopp/TestVectors/ttmac.txt new file mode 100644 index 0000000..ec2e683 --- /dev/null +++ b/src-cryptopp/TestVectors/ttmac.txt @@ -0,0 +1,40 @@ +AlgorithmType: MAC +Name: Two-Track-MAC +Source: NESSIE submission +Comment: Key for all test cases +Key: 00112233445566778899aabbccddeeff01234567 +Comment: Test Case 1 +Message: "" +MAC: 2dec8ed4a0fd712ed9fbf2ab466ec2df21215e4a +Test: Verify +Comment: Test Case 2 +Message: "a" +MAC: 5893e3e6e306704dd77ad6e6ed432cde321a7756 +Test: Verify +Comment: Test Case 3 +Message: "abc" +MAC: 70bfd1029797a5c16da5b557a1f0b2779b78497e +Test: Verify +Comment: Test Case 4 +Message: "message digest" +MAC: 8289f4f19ffe4f2af737de4bd71c829d93a972fa +Test: Verify +Comment: Test Case 5 +Message: "abcdefghijklmnopqrstuvwxyz" +MAC: 2186ca09c5533198b7371f245273504ca92bae60 +Test: Verify +Comment: Test Case 6 +Message: "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +MAC: 8a7bf77aef62a2578497a27c0d6518a429e7c14d +Test: Verify +Comment: Test Case 7 +Message: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" +MAC: 54bac392a886806d169556fcbb6789b54fb364fb +Test: Verify +Comment: Test Case 8 +Message: r8 "1234567890" +MAC: 0ced2c9f8f0d9d03981ab5c8184bac43dd54c484 +Test: Verify +Comment: Test Case 9 +Message: r15625 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +MAC: 27b3aedb5df8b629f0142194daa3846e1895f3d2 diff --git a/src-cryptopp/TestVectors/vmac.txt b/src-cryptopp/TestVectors/vmac.txt new file mode 100644 index 0000000..1d983cd --- /dev/null +++ b/src-cryptopp/TestVectors/vmac.txt @@ -0,0 +1,77 @@ +AlgorithmType: MAC +Name: VMAC(AES)-64 +Source: http://www.fastcrypto.org/vmac/draft-krovetz-vmac-01.txt +Key: "abcdefghijklmnop" +IV: "bcdefghi" +Message: "" +MAC: 2576BE1C56D8B81B +Test: Verify +Message: "abc" +MAC: 2D376CF5B1813CE5 +Test: Verify +Message: r16 "abc" +MAC: E8421F61D573D298 +Test: Verify +Message: r100 "abc" +MAC: 4492DF6C5CAC1BBE +Test: Verify +Message: r1000000 "abc" +MAC: 09BA597DD7601113 +Test: Verify +Message: r42 "abc" "ab" +MAC: D638B73921F184DE +Test: Verify +Message: r170 "abc" "ab" +MAC: 9DA310281E6FD0A0 +Test: Verify +Message: r65 "a" +MAC: 90 ea 57 cb 51 bc 92 a3 +Test: Verify +Message: r129 "a" +MAC: 86 34 83 87 d1 3d 82 33 +Test: Verify +Message: r65 "abc" +MAC: E86A86EC77A8BF61 +Test: Verify +Message: "abc" +MAC: 2D376CF5B1813CE0 +Test: NotVerify + +AlgorithmType: MAC +Name: VMAC(AES)-128 +Source: http://www.fastcrypto.org/vmac/draft-krovetz-vmac-01.txt +Key: "abcdefghijklmnop" +IV: "bcdefghi" +Message: "" +MAC: 472766C70F74ED23481D6D7DE4E80DAC +Test: Verify +Message: "abc" +MAC: 4EE815A06A1D71EDD36FC75D51188A42 +Test: Verify +Message: r16 "abc" +MAC: 09F2C80C8E1007A0C12FAE19FE4504AE +Test: Verify +Message: r100 "abc" +MAC: 66438817154850C61D8A412164803BCB +Test: Verify +Message: r1000000 "abc" +MAC: 2B6B02288FFC461B75485DE893C629DC +Test: Verify +Message: r42 "abc" "ab" +MAC: F7E95FE3DA8DB9E6BB973E65D0B4CEA5 +Test: Verify +Message: r170 "abc" "ab" +MAC: BF53B8D2D70C05A85880C2E21CAF1299 +Test: Verify +Message: r65 "a" +MAC: b2 9b 00 76 0a 58 c7 ab 92 d6 60 24 d6 9c 1b 92 +Test: Verify +Message: r129 "a" +MAC: a7 e5 2c 32 89 d9 b7 3b 53 57 6f 05 95 85 ee 79 +Test: Verify +Message: r65 "abc" +MAC: 0A1B2F973044F469F405917E45010334 +Test: Verify +Message: "abc" +MAC: 4EE815A06A1D71EDD36FC75D51188A40 +Test: NotVerify diff --git a/src-cryptopp/TestVectors/whrlpool.txt b/src-cryptopp/TestVectors/whrlpool.txt new file mode 100644 index 0000000..9a4df8b --- /dev/null +++ b/src-cryptopp/TestVectors/whrlpool.txt @@ -0,0 +1,39 @@ +AlgorithmType: MessageDigest +Name: Whirlpool +Source: ISO test vectors in http://planeta.terra.com.br/informatica/paulobarreto/whirlpool.zip +Message: "" +Digest: 19FA61D75522A466 9B44E39C1D2E1726 C530232130D407F8 9AFEE0964997F7A7\ + 3E83BE698B288FEB CF88E3E03C4F0757 EA8964E59B63D937 08B138CC42A66EB3 +Test: Verify +Message: "a" +Digest: 8ACA2602792AEC6F 11A67206531FB7D7 F0DFF59413145E69 73C45001D0087B42\ + D11BC645413AEFF6 3A42391A39145A59 1A92200D560195E5 3B478584FDAE231A +Test: Verify +Message: "abc" +Digest: 4E2448A4C6F486BB 16B6562C73B4020B F3043E3A731BCE72 1AE1B303D97E6D4C\ + 7181EEBDB6C57E27 7D0E34957114CBD6 C797FC9D95D8B582 D225292076D4EEF5 +Test: Verify +Message: "message digest" +Digest: 378C84A4126E2DC6 E56DCC7458377AAC 838D00032230F53C E1F5700C0FFB4D3B\ + 8421557659EF55C1 06B4B52AC5A4AAA6 92ED920052838F33 62E86DBD37A8903E +Test: Verify +Message: "abcdefghijklmnopqrstuvwxyz" +Digest: F1D754662636FFE9 2C82EBB9212A484A 8D38631EAD4238F5 442EE13B8054E41B\ + 08BF2A9251C30B6A 0B8AAE86177AB4A6 F68F673E7207865D 5D9819A3DBA4EB3B +Test: Verify +Message: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" +Digest: DC37E008CF9EE69B F11F00ED9ABA2690 1DD7C28CDEC066CC 6AF42E40F82F3A1E\ + 08EBA26629129D8F B7CB57211B9281A6 5517CC879D7B9621 42C65F5A7AF01467 +Test: Verify +Message: r8 "1234567890" +Digest: 466EF18BABB0154D 25B9D38A6414F5C0 8784372BCCB204D6 549C4AFADB601429\ + 4D5BD8DF2A6C44E5 38CD047B2681A51A 2C60481E88C5A20B 2C2A80CF3A9A083B +Test: Verify +Message: "abcdbcdecdefdefgefghfghighijhijk" +Digest: 2A987EA40F917061 F5D6F0A0E4644F48 8A7A5A52DEEE6562 07C562F988E95C69\ + 16BDC8031BC5BE1B 7B947639FE050B56 939BAAA0ADFF9AE6 745B7B181C3BE3FD +Test: Verify +Message: r1000000 "a" +Digest: 0C99005BEB57EFF5 0A7CF005560DDF5D 29057FD86B20BFD6 2DECA0F1CCEA4AF5\ + 1FC15490EDDC47AF 32BB2B66C34FF9AD 8C6008AD677F7712 6953B226E4ED8B01 +Test: Verify diff --git a/src-cryptopp/adhoc.cpp.proto b/src-cryptopp/adhoc.cpp.proto new file mode 100644 index 0000000..df09f11 --- /dev/null +++ b/src-cryptopp/adhoc.cpp.proto @@ -0,0 +1,17 @@ +#include "filters.h" +#include "files.h" +#include "base64.h" +#include "hex.h" +#include + +USING_NAMESPACE(CryptoPP) +USING_NAMESPACE(std) + +extern int (*AdhocTest)(int argc, char *argv[]); + +int MyAdhocTest(int argc, char *argv[]) +{ + return 0; +} + +static int s_i = (AdhocTest = &MyAdhocTest, 0); diff --git a/src-cryptopp/aes.h b/src-cryptopp/aes.h new file mode 100644 index 0000000..0087542 --- /dev/null +++ b/src-cryptopp/aes.h @@ -0,0 +1,16 @@ +#ifndef CRYPTOPP_AES_H +#define CRYPTOPP_AES_H + +#include "rijndael.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! AES winner, announced on 10/2/2000 +DOCUMENTED_TYPEDEF(Rijndael, AES); + +typedef RijndaelEncryption AESEncryption; +typedef RijndaelDecryption AESDecryption; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/algebra.cpp b/src-cryptopp/algebra.cpp new file mode 100644 index 0000000..b8818e6 --- /dev/null +++ b/src-cryptopp/algebra.cpp @@ -0,0 +1,340 @@ +// algebra.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_ALGEBRA_CPP // SunCC workaround: compiler could cause this file to be included twice +#define CRYPTOPP_ALGEBRA_CPP + +#include "algebra.h" +#include "integer.h" + +#include + +NAMESPACE_BEGIN(CryptoPP) + +template const T& AbstractGroup::Double(const Element &a) const +{ + return Add(a, a); +} + +template const T& AbstractGroup::Subtract(const Element &a, const Element &b) const +{ + // make copy of a in case Inverse() overwrites it + Element a1(a); + return Add(a1, Inverse(b)); +} + +template T& AbstractGroup::Accumulate(Element &a, const Element &b) const +{ + return a = Add(a, b); +} + +template T& AbstractGroup::Reduce(Element &a, const Element &b) const +{ + return a = Subtract(a, b); +} + +template const T& AbstractRing::Square(const Element &a) const +{ + return Multiply(a, a); +} + +template const T& AbstractRing::Divide(const Element &a, const Element &b) const +{ + // make copy of a in case MultiplicativeInverse() overwrites it + Element a1(a); + return Multiply(a1, MultiplicativeInverse(b)); +} + +template const T& AbstractEuclideanDomain::Mod(const Element &a, const Element &b) const +{ + Element q; + DivisionAlgorithm(result, q, a, b); + return result; +} + +template const T& AbstractEuclideanDomain::Gcd(const Element &a, const Element &b) const +{ + Element g[3]={b, a}; + unsigned int i0=0, i1=1, i2=2; + + while (!this->Equal(g[i1], this->Identity())) + { + g[i2] = Mod(g[i0], g[i1]); + unsigned int t = i0; i0 = i1; i1 = i2; i2 = t; + } + + return result = g[i0]; +} + +template const typename QuotientRing::Element& QuotientRing::MultiplicativeInverse(const Element &a) const +{ + Element g[3]={m_modulus, a}; + Element v[3]={m_domain.Identity(), m_domain.MultiplicativeIdentity()}; + Element y; + unsigned int i0=0, i1=1, i2=2; + + while (!Equal(g[i1], Identity())) + { + // y = g[i0] / g[i1]; + // g[i2] = g[i0] % g[i1]; + m_domain.DivisionAlgorithm(g[i2], y, g[i0], g[i1]); + // v[i2] = v[i0] - (v[i1] * y); + v[i2] = m_domain.Subtract(v[i0], m_domain.Multiply(v[i1], y)); + unsigned int t = i0; i0 = i1; i1 = i2; i2 = t; + } + + return m_domain.IsUnit(g[i0]) ? m_domain.Divide(v[i0], g[i0]) : m_domain.Identity(); +} + +template T AbstractGroup::ScalarMultiply(const Element &base, const Integer &exponent) const +{ + Element result; + SimultaneousMultiply(&result, base, &exponent, 1); + return result; +} + +template T AbstractGroup::CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const +{ + const unsigned expLen = STDMAX(e1.BitCount(), e2.BitCount()); + if (expLen==0) + return Identity(); + + const unsigned w = (expLen <= 46 ? 1 : (expLen <= 260 ? 2 : 3)); + const unsigned tableSize = 1< powerTable(tableSize << w); + + powerTable[1] = x; + powerTable[tableSize] = y; + if (w==1) + powerTable[3] = Add(x,y); + else + { + powerTable[2] = Double(x); + powerTable[2*tableSize] = Double(y); + + unsigned i, j; + + for (i=3; i=0; i--) + { + power1 = 2*power1 + e1.GetBit(i); + power2 = 2*power2 + e2.GetBit(i); + + if (i==0 || 2*power1 >= tableSize || 2*power2 >= tableSize) + { + unsigned squaresBefore = prevPosition-i; + unsigned squaresAfter = 0; + prevPosition = i; + while ((power1 || power2) && power1%2 == 0 && power2%2==0) + { + power1 /= 2; + power2 /= 2; + squaresBefore--; + squaresAfter++; + } + if (firstTime) + { + result = powerTable[(power2< Element GeneralCascadeMultiplication(const AbstractGroup &group, Iterator begin, Iterator end) +{ + if (end-begin == 1) + return group.ScalarMultiply(begin->base, begin->exponent); + else if (end-begin == 2) + return group.CascadeScalarMultiply(begin->base, begin->exponent, (begin+1)->base, (begin+1)->exponent); + else + { + Integer q, t; + Iterator last = end; + --last; + + std::make_heap(begin, end); + std::pop_heap(begin, end); + + while (!!begin->exponent) + { + // last->exponent is largest exponent, begin->exponent is next largest + t = last->exponent; + Integer::Divide(last->exponent, q, t, begin->exponent); + + if (q == Integer::One()) + group.Accumulate(begin->base, last->base); // avoid overhead of ScalarMultiply() + else + group.Accumulate(begin->base, group.ScalarMultiply(last->base, q)); + + std::push_heap(begin, end); + std::pop_heap(begin, end); + } + + return group.ScalarMultiply(last->base, last->exponent); + } +} + +struct WindowSlider +{ + WindowSlider(const Integer &expIn, bool fastNegate, unsigned int windowSizeIn=0) + : exp(expIn), windowModulus(Integer::One()), windowSize(windowSizeIn), windowBegin(0), fastNegate(fastNegate), firstTime(true), finished(false) + { + if (windowSize == 0) + { + unsigned int expLen = exp.BitCount(); + windowSize = expLen <= 17 ? 1 : (expLen <= 24 ? 2 : (expLen <= 70 ? 3 : (expLen <= 197 ? 4 : (expLen <= 539 ? 5 : (expLen <= 1434 ? 6 : 7))))); + } + windowModulus <<= windowSize; + } + + void FindNextWindow() + { + unsigned int expLen = exp.WordCount() * WORD_BITS; + unsigned int skipCount = firstTime ? 0 : windowSize; + firstTime = false; + while (!exp.GetBit(skipCount)) + { + if (skipCount >= expLen) + { + finished = true; + return; + } + skipCount++; + } + + exp >>= skipCount; + windowBegin += skipCount; + expWindow = word32(exp % (word(1) << windowSize)); + + if (fastNegate && exp.GetBit(windowSize)) + { + negateNext = true; + expWindow = (word32(1) << windowSize) - expWindow; + exp += windowModulus; + } + else + negateNext = false; + } + + Integer exp, windowModulus; + unsigned int windowSize, windowBegin; + word32 expWindow; + bool fastNegate, negateNext, firstTime, finished; +}; + +template +void AbstractGroup::SimultaneousMultiply(T *results, const T &base, const Integer *expBegin, unsigned int expCount) const +{ + std::vector > buckets(expCount); + std::vector exponents; + exponents.reserve(expCount); + unsigned int i; + + for (i=0; iNotNegative()); + exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 0)); + exponents[i].FindNextWindow(); + buckets[i].resize(1<<(exponents[i].windowSize-1), Identity()); + } + + unsigned int expBitPosition = 0; + Element g = base; + bool notDone = true; + + while (notDone) + { + notDone = false; + for (i=0; i 1) + { + for (int j = (int)buckets[i].size()-2; j >= 1; j--) + { + Accumulate(buckets[i][j], buckets[i][j+1]); + Accumulate(r, buckets[i][j]); + } + Accumulate(buckets[i][0], buckets[i][1]); + r = Add(Double(r), buckets[i][0]); + } + } +} + +template T AbstractRing::Exponentiate(const Element &base, const Integer &exponent) const +{ + Element result; + SimultaneousExponentiate(&result, base, &exponent, 1); + return result; +} + +template T AbstractRing::CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const +{ + return MultiplicativeGroup().AbstractGroup::CascadeScalarMultiply(x, e1, y, e2); +} + +template Element GeneralCascadeExponentiation(const AbstractRing &ring, Iterator begin, Iterator end) +{ + return GeneralCascadeMultiplication(ring.MultiplicativeGroup(), begin, end); +} + +template +void AbstractRing::SimultaneousExponentiate(T *results, const T &base, const Integer *exponents, unsigned int expCount) const +{ + MultiplicativeGroup().AbstractGroup::SimultaneousMultiply(results, base, exponents, expCount); +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/algebra.h b/src-cryptopp/algebra.h new file mode 100644 index 0000000..13038bd --- /dev/null +++ b/src-cryptopp/algebra.h @@ -0,0 +1,285 @@ +#ifndef CRYPTOPP_ALGEBRA_H +#define CRYPTOPP_ALGEBRA_H + +#include "config.h" + +NAMESPACE_BEGIN(CryptoPP) + +class Integer; + +// "const Element&" returned by member functions are references +// to internal data members. Since each object may have only +// one such data member for holding results, the following code +// will produce incorrect results: +// abcd = group.Add(group.Add(a,b), group.Add(c,d)); +// But this should be fine: +// abcd = group.Add(a, group.Add(b, group.Add(c,d)); + +//! Abstract Group +template class CRYPTOPP_NO_VTABLE AbstractGroup +{ +public: + typedef T Element; + + virtual ~AbstractGroup() {} + + virtual bool Equal(const Element &a, const Element &b) const =0; + virtual const Element& Identity() const =0; + virtual const Element& Add(const Element &a, const Element &b) const =0; + virtual const Element& Inverse(const Element &a) const =0; + virtual bool InversionIsFast() const {return false;} + + virtual const Element& Double(const Element &a) const; + virtual const Element& Subtract(const Element &a, const Element &b) const; + virtual Element& Accumulate(Element &a, const Element &b) const; + virtual Element& Reduce(Element &a, const Element &b) const; + + virtual Element ScalarMultiply(const Element &a, const Integer &e) const; + virtual Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const; + + virtual void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const; +}; + +//! Abstract Ring +template class CRYPTOPP_NO_VTABLE AbstractRing : public AbstractGroup +{ +public: + typedef T Element; + + AbstractRing() {m_mg.m_pRing = this;} + AbstractRing(const AbstractRing &source) {m_mg.m_pRing = this;} + AbstractRing& operator=(const AbstractRing &source) {return *this;} + + virtual bool IsUnit(const Element &a) const =0; + virtual const Element& MultiplicativeIdentity() const =0; + virtual const Element& Multiply(const Element &a, const Element &b) const =0; + virtual const Element& MultiplicativeInverse(const Element &a) const =0; + + virtual const Element& Square(const Element &a) const; + virtual const Element& Divide(const Element &a, const Element &b) const; + + virtual Element Exponentiate(const Element &a, const Integer &e) const; + virtual Element CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const; + + virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const; + + virtual const AbstractGroup& MultiplicativeGroup() const + {return m_mg;} + +private: + class MultiplicativeGroupT : public AbstractGroup + { + public: + const AbstractRing& GetRing() const + {return *m_pRing;} + + bool Equal(const Element &a, const Element &b) const + {return GetRing().Equal(a, b);} + + const Element& Identity() const + {return GetRing().MultiplicativeIdentity();} + + const Element& Add(const Element &a, const Element &b) const + {return GetRing().Multiply(a, b);} + + Element& Accumulate(Element &a, const Element &b) const + {return a = GetRing().Multiply(a, b);} + + const Element& Inverse(const Element &a) const + {return GetRing().MultiplicativeInverse(a);} + + const Element& Subtract(const Element &a, const Element &b) const + {return GetRing().Divide(a, b);} + + Element& Reduce(Element &a, const Element &b) const + {return a = GetRing().Divide(a, b);} + + const Element& Double(const Element &a) const + {return GetRing().Square(a);} + + Element ScalarMultiply(const Element &a, const Integer &e) const + {return GetRing().Exponentiate(a, e);} + + Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const + {return GetRing().CascadeExponentiate(x, e1, y, e2);} + + void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const + {GetRing().SimultaneousExponentiate(results, base, exponents, exponentsCount);} + + const AbstractRing *m_pRing; + }; + + MultiplicativeGroupT m_mg; +}; + +// ******************************************************** + +//! Base and Exponent +template +struct BaseAndExponent +{ +public: + BaseAndExponent() {} + BaseAndExponent(const T &base, const E &exponent) : base(base), exponent(exponent) {} + bool operator<(const BaseAndExponent &rhs) const {return exponent < rhs.exponent;} + T base; + E exponent; +}; + +// VC60 workaround: incomplete member template support +template + Element GeneralCascadeMultiplication(const AbstractGroup &group, Iterator begin, Iterator end); +template + Element GeneralCascadeExponentiation(const AbstractRing &ring, Iterator begin, Iterator end); + +// ******************************************************** + +//! Abstract Euclidean Domain +template class CRYPTOPP_NO_VTABLE AbstractEuclideanDomain : public AbstractRing +{ +public: + typedef T Element; + + virtual void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const =0; + + virtual const Element& Mod(const Element &a, const Element &b) const =0; + virtual const Element& Gcd(const Element &a, const Element &b) const; + +protected: + mutable Element result; +}; + +// ******************************************************** + +//! EuclideanDomainOf +template class EuclideanDomainOf : public AbstractEuclideanDomain +{ +public: + typedef T Element; + + EuclideanDomainOf() {} + + bool Equal(const Element &a, const Element &b) const + {return a==b;} + + const Element& Identity() const + {return Element::Zero();} + + const Element& Add(const Element &a, const Element &b) const + {return result = a+b;} + + Element& Accumulate(Element &a, const Element &b) const + {return a+=b;} + + const Element& Inverse(const Element &a) const + {return result = -a;} + + const Element& Subtract(const Element &a, const Element &b) const + {return result = a-b;} + + Element& Reduce(Element &a, const Element &b) const + {return a-=b;} + + const Element& Double(const Element &a) const + {return result = a.Doubled();} + + const Element& MultiplicativeIdentity() const + {return Element::One();} + + const Element& Multiply(const Element &a, const Element &b) const + {return result = a*b;} + + const Element& Square(const Element &a) const + {return result = a.Squared();} + + bool IsUnit(const Element &a) const + {return a.IsUnit();} + + const Element& MultiplicativeInverse(const Element &a) const + {return result = a.MultiplicativeInverse();} + + const Element& Divide(const Element &a, const Element &b) const + {return result = a/b;} + + const Element& Mod(const Element &a, const Element &b) const + {return result = a%b;} + + void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const + {Element::Divide(r, q, a, d);} + + bool operator==(const EuclideanDomainOf &rhs) const + {return true;} + +private: + mutable Element result; +}; + +//! Quotient Ring +template class QuotientRing : public AbstractRing +{ +public: + typedef T EuclideanDomain; + typedef typename T::Element Element; + + QuotientRing(const EuclideanDomain &domain, const Element &modulus) + : m_domain(domain), m_modulus(modulus) {} + + const EuclideanDomain & GetDomain() const + {return m_domain;} + + const Element& GetModulus() const + {return m_modulus;} + + bool Equal(const Element &a, const Element &b) const + {return m_domain.Equal(m_domain.Mod(m_domain.Subtract(a, b), m_modulus), m_domain.Identity());} + + const Element& Identity() const + {return m_domain.Identity();} + + const Element& Add(const Element &a, const Element &b) const + {return m_domain.Add(a, b);} + + Element& Accumulate(Element &a, const Element &b) const + {return m_domain.Accumulate(a, b);} + + const Element& Inverse(const Element &a) const + {return m_domain.Inverse(a);} + + const Element& Subtract(const Element &a, const Element &b) const + {return m_domain.Subtract(a, b);} + + Element& Reduce(Element &a, const Element &b) const + {return m_domain.Reduce(a, b);} + + const Element& Double(const Element &a) const + {return m_domain.Double(a);} + + bool IsUnit(const Element &a) const + {return m_domain.IsUnit(m_domain.Gcd(a, m_modulus));} + + const Element& MultiplicativeIdentity() const + {return m_domain.MultiplicativeIdentity();} + + const Element& Multiply(const Element &a, const Element &b) const + {return m_domain.Mod(m_domain.Multiply(a, b), m_modulus);} + + const Element& Square(const Element &a) const + {return m_domain.Mod(m_domain.Square(a), m_modulus);} + + const Element& MultiplicativeInverse(const Element &a) const; + + bool operator==(const QuotientRing &rhs) const + {return m_domain == rhs.m_domain && m_modulus == rhs.m_modulus;} + +protected: + EuclideanDomain m_domain; + Element m_modulus; +}; + +NAMESPACE_END + +#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES +#include "algebra.cpp" +#endif + +#endif diff --git a/src-cryptopp/algparam.cpp b/src-cryptopp/algparam.cpp new file mode 100644 index 0000000..a70d5dd --- /dev/null +++ b/src-cryptopp/algparam.cpp @@ -0,0 +1,75 @@ +// algparam.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "algparam.h" + +NAMESPACE_BEGIN(CryptoPP) + +PAssignIntToInteger g_pAssignIntToInteger = NULL; + +bool CombinedNameValuePairs::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + if (strcmp(name, "ValueNames") == 0) + return m_pairs1.GetVoidValue(name, valueType, pValue) && m_pairs2.GetVoidValue(name, valueType, pValue); + else + return m_pairs1.GetVoidValue(name, valueType, pValue) || m_pairs2.GetVoidValue(name, valueType, pValue); +} + +void AlgorithmParametersBase::operator=(const AlgorithmParametersBase& rhs) +{ + assert(false); +} + +bool AlgorithmParametersBase::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + if (strcmp(name, "ValueNames") == 0) + { + NameValuePairs::ThrowIfTypeMismatch(name, typeid(std::string), valueType); + if (m_next.get()) + m_next->GetVoidValue(name, valueType, pValue); + (*reinterpret_cast(pValue) += m_name) += ";"; + return true; + } + else if (strcmp(name, m_name) == 0) + { + AssignValue(name, valueType, pValue); + m_used = true; + return true; + } + else if (m_next.get()) + return m_next->GetVoidValue(name, valueType, pValue); + else + return false; +} + +AlgorithmParameters::AlgorithmParameters() + : m_defaultThrowIfNotUsed(true) +{ +} + +AlgorithmParameters::AlgorithmParameters(const AlgorithmParameters &x) + : m_defaultThrowIfNotUsed(x.m_defaultThrowIfNotUsed) +{ + m_next.reset(const_cast(x).m_next.release()); +} + +AlgorithmParameters & AlgorithmParameters::operator=(const AlgorithmParameters &x) +{ + m_next.reset(const_cast(x).m_next.release()); + return *this; +} + +bool AlgorithmParameters::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + if (m_next.get()) + return m_next->GetVoidValue(name, valueType, pValue); + else + return false; +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/algparam.h b/src-cryptopp/algparam.h new file mode 100644 index 0000000..ea5129c --- /dev/null +++ b/src-cryptopp/algparam.h @@ -0,0 +1,398 @@ +#ifndef CRYPTOPP_ALGPARAM_H +#define CRYPTOPP_ALGPARAM_H + +#include "cryptlib.h" +#include "smartptr.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! used to pass byte array input as part of a NameValuePairs object +/*! the deepCopy option is used when the NameValuePairs object can't + keep a copy of the data available */ +class ConstByteArrayParameter +{ +public: + ConstByteArrayParameter(const char *data = NULL, bool deepCopy = false) + { + Assign((const byte *)data, data ? strlen(data) : 0, deepCopy); + } + ConstByteArrayParameter(const byte *data, size_t size, bool deepCopy = false) + { + Assign(data, size, deepCopy); + } + template ConstByteArrayParameter(const T &string, bool deepCopy = false) + { + CRYPTOPP_COMPILE_ASSERT(sizeof(CPP_TYPENAME T::value_type) == 1); + Assign((const byte *)string.data(), string.size(), deepCopy); + } + + void Assign(const byte *data, size_t size, bool deepCopy) + { + if (deepCopy) + m_block.Assign(data, size); + else + { + m_data = data; + m_size = size; + } + m_deepCopy = deepCopy; + } + + const byte *begin() const {return m_deepCopy ? m_block.begin() : m_data;} + const byte *end() const {return m_deepCopy ? m_block.end() : m_data + m_size;} + size_t size() const {return m_deepCopy ? m_block.size() : m_size;} + +private: + bool m_deepCopy; + const byte *m_data; + size_t m_size; + SecByteBlock m_block; +}; + +class ByteArrayParameter +{ +public: + ByteArrayParameter(byte *data = NULL, unsigned int size = 0) + : m_data(data), m_size(size) {} + ByteArrayParameter(SecByteBlock &block) + : m_data(block.begin()), m_size(block.size()) {} + + byte *begin() const {return m_data;} + byte *end() const {return m_data + m_size;} + size_t size() const {return m_size;} + +private: + byte *m_data; + size_t m_size; +}; + +class CRYPTOPP_DLL CombinedNameValuePairs : public NameValuePairs +{ +public: + CombinedNameValuePairs(const NameValuePairs &pairs1, const NameValuePairs &pairs2) + : m_pairs1(pairs1), m_pairs2(pairs2) {} + + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + +private: + const NameValuePairs &m_pairs1, &m_pairs2; +}; + +template +class GetValueHelperClass +{ +public: + GetValueHelperClass(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst) + : m_pObject(pObject), m_name(name), m_valueType(&valueType), m_pValue(pValue), m_found(false), m_getValueNames(false) + { + if (strcmp(m_name, "ValueNames") == 0) + { + m_found = m_getValueNames = true; + NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(std::string), *m_valueType); + if (searchFirst) + searchFirst->GetVoidValue(m_name, valueType, pValue); + if (typeid(T) != typeid(BASE)) + pObject->BASE::GetVoidValue(m_name, valueType, pValue); + ((*reinterpret_cast(m_pValue) += "ThisPointer:") += typeid(T).name()) += ';'; + } + + if (!m_found && strncmp(m_name, "ThisPointer:", 12) == 0 && strcmp(m_name+12, typeid(T).name()) == 0) + { + NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T *), *m_valueType); + *reinterpret_cast(pValue) = pObject; + m_found = true; + return; + } + + if (!m_found && searchFirst) + m_found = searchFirst->GetVoidValue(m_name, valueType, pValue); + + if (!m_found && typeid(T) != typeid(BASE)) + m_found = pObject->BASE::GetVoidValue(m_name, valueType, pValue); + } + + operator bool() const {return m_found;} + + template + GetValueHelperClass & operator()(const char *name, const R & (T::*pm)() const) + { + if (m_getValueNames) + (*reinterpret_cast(m_pValue) += name) += ";"; + if (!m_found && strcmp(name, m_name) == 0) + { + NameValuePairs::ThrowIfTypeMismatch(name, typeid(R), *m_valueType); + *reinterpret_cast(m_pValue) = (m_pObject->*pm)(); + m_found = true; + } + return *this; + } + + GetValueHelperClass &Assignable() + { +#ifndef __INTEL_COMPILER // ICL 9.1 workaround: Intel compiler copies the vTable pointer for some reason + if (m_getValueNames) + ((*reinterpret_cast(m_pValue) += "ThisObject:") += typeid(T).name()) += ';'; + if (!m_found && strncmp(m_name, "ThisObject:", 11) == 0 && strcmp(m_name+11, typeid(T).name()) == 0) + { + NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T), *m_valueType); + *reinterpret_cast(m_pValue) = *m_pObject; + m_found = true; + } +#endif + return *this; + } + +private: + const T *m_pObject; + const char *m_name; + const std::type_info *m_valueType; + void *m_pValue; + bool m_found, m_getValueNames; +}; + +template +GetValueHelperClass GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL, BASE *dummy=NULL) +{ + return GetValueHelperClass(pObject, name, valueType, pValue, searchFirst); +} + +template +GetValueHelperClass GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL) +{ + return GetValueHelperClass(pObject, name, valueType, pValue, searchFirst); +} + +// ******************************************************** + +template +R Hack_DefaultValueFromConstReferenceType(const R &) +{ + return R(); +} + +template +bool Hack_GetValueIntoConstReference(const NameValuePairs &source, const char *name, const R &value) +{ + return source.GetValue(name, const_cast(value)); +} + +template +class AssignFromHelperClass +{ +public: + AssignFromHelperClass(T *pObject, const NameValuePairs &source) + : m_pObject(pObject), m_source(source), m_done(false) + { + if (source.GetThisObject(*pObject)) + m_done = true; + else if (typeid(BASE) != typeid(T)) + pObject->BASE::AssignFrom(source); + } + + template + AssignFromHelperClass & operator()(const char *name, void (T::*pm)(R)) // VC60 workaround: "const R &" here causes compiler error + { + if (!m_done) + { + R value = Hack_DefaultValueFromConstReferenceType(reinterpret_cast(*(int *)NULL)); + if (!Hack_GetValueIntoConstReference(m_source, name, value)) + throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name + "'"); + (m_pObject->*pm)(value); + } + return *this; + } + + template + AssignFromHelperClass & operator()(const char *name1, const char *name2, void (T::*pm)(R, S)) // VC60 workaround: "const R &" here causes compiler error + { + if (!m_done) + { + R value1 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast(*(int *)NULL)); + if (!Hack_GetValueIntoConstReference(m_source, name1, value1)) + throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name1 + "'"); + S value2 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast(*(int *)NULL)); + if (!Hack_GetValueIntoConstReference(m_source, name2, value2)) + throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name2 + "'"); + (m_pObject->*pm)(value1, value2); + } + return *this; + } + +private: + T *m_pObject; + const NameValuePairs &m_source; + bool m_done; +}; + +template +AssignFromHelperClass AssignFromHelper(T *pObject, const NameValuePairs &source, BASE *dummy=NULL) +{ + return AssignFromHelperClass(pObject, source); +} + +template +AssignFromHelperClass AssignFromHelper(T *pObject, const NameValuePairs &source) +{ + return AssignFromHelperClass(pObject, source); +} + +// ******************************************************** + +// to allow the linker to discard Integer code if not needed. +typedef bool (CRYPTOPP_API * PAssignIntToInteger)(const std::type_info &valueType, void *pInteger, const void *pInt); +CRYPTOPP_DLL extern PAssignIntToInteger g_pAssignIntToInteger; + +CRYPTOPP_DLL const std::type_info & CRYPTOPP_API IntegerTypeId(); + +class CRYPTOPP_DLL AlgorithmParametersBase +{ +public: + class ParameterNotUsed : public Exception + { + public: + ParameterNotUsed(const char *name) : Exception(OTHER_ERROR, std::string("AlgorithmParametersBase: parameter \"") + name + "\" not used") {} + }; + + // this is actually a move, not a copy + AlgorithmParametersBase(const AlgorithmParametersBase &x) + : m_name(x.m_name), m_throwIfNotUsed(x.m_throwIfNotUsed), m_used(x.m_used) + { + m_next.reset(const_cast(x).m_next.release()); + x.m_used = true; + } + + AlgorithmParametersBase(const char *name, bool throwIfNotUsed) + : m_name(name), m_throwIfNotUsed(throwIfNotUsed), m_used(false) {} + + virtual ~AlgorithmParametersBase() + { +#ifdef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE + if (!std::uncaught_exception()) +#else + try +#endif + { + if (m_throwIfNotUsed && !m_used) + throw ParameterNotUsed(m_name); + } +#ifndef CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE + catch(...) + { + } +#endif + } + + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + +protected: + friend class AlgorithmParameters; + void operator=(const AlgorithmParametersBase& rhs); // assignment not allowed, declare this for VC60 + + virtual void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const =0; + virtual void MoveInto(void *p) const =0; // not really const + + const char *m_name; + bool m_throwIfNotUsed; + mutable bool m_used; + member_ptr m_next; +}; + +template +class AlgorithmParametersTemplate : public AlgorithmParametersBase +{ +public: + AlgorithmParametersTemplate(const char *name, const T &value, bool throwIfNotUsed) + : AlgorithmParametersBase(name, throwIfNotUsed), m_value(value) + { + } + + void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const + { + // special case for retrieving an Integer parameter when an int was passed in + if (!(g_pAssignIntToInteger != NULL && typeid(T) == typeid(int) && g_pAssignIntToInteger(valueType, pValue, &m_value))) + { + NameValuePairs::ThrowIfTypeMismatch(name, typeid(T), valueType); + *reinterpret_cast(pValue) = m_value; + } + } + + void MoveInto(void *buffer) const + { + AlgorithmParametersTemplate* p = new(buffer) AlgorithmParametersTemplate(*this); + } + +protected: + T m_value; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate; +CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate; +CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate; + +class CRYPTOPP_DLL AlgorithmParameters : public NameValuePairs +{ +public: + AlgorithmParameters(); + +#ifdef __BORLANDC__ + template + AlgorithmParameters(const char *name, const T &value, bool throwIfNotUsed=true) + : m_next(new AlgorithmParametersTemplate(name, value, throwIfNotUsed)) + , m_defaultThrowIfNotUsed(throwIfNotUsed) + { + } +#endif + + AlgorithmParameters(const AlgorithmParameters &x); + + AlgorithmParameters & operator=(const AlgorithmParameters &x); + + template + AlgorithmParameters & operator()(const char *name, const T &value, bool throwIfNotUsed) + { + member_ptr p(new AlgorithmParametersTemplate(name, value, throwIfNotUsed)); + p->m_next.reset(m_next.release()); + m_next.reset(p.release()); + m_defaultThrowIfNotUsed = throwIfNotUsed; + return *this; + } + + template + AlgorithmParameters & operator()(const char *name, const T &value) + { + return operator()(name, value, m_defaultThrowIfNotUsed); + } + + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + +protected: + member_ptr m_next; + bool m_defaultThrowIfNotUsed; +}; + +//! Create an object that implements NameValuePairs for passing parameters +/*! \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed + \note throwIfNotUsed is ignored if using a compiler that does not support std::uncaught_exception(), + such as MSVC 7.0 and earlier. + \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by + repeatedly using operator() on the object returned by MakeParameters, for example: + AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3); +*/ +#ifdef __BORLANDC__ +typedef AlgorithmParameters MakeParameters; +#else +template +AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed = true) +{ + return AlgorithmParameters()(name, value, throwIfNotUsed); +} +#endif + +#define CRYPTOPP_GET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Get##name) +#define CRYPTOPP_SET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Set##name) +#define CRYPTOPP_SET_FUNCTION_ENTRY2(name1, name2) (Name::name1(), Name::name2(), &ThisClass::Set##name1##And##name2) + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/argnames.h b/src-cryptopp/argnames.h new file mode 100644 index 0000000..23add3c --- /dev/null +++ b/src-cryptopp/argnames.h @@ -0,0 +1,79 @@ +#ifndef CRYPTOPP_ARGNAMES_H +#define CRYPTOPP_ARGNAMES_H + +#include "cryptlib.h" + +NAMESPACE_BEGIN(CryptoPP) + +DOCUMENTED_NAMESPACE_BEGIN(Name) + +#define CRYPTOPP_DEFINE_NAME_STRING(name) inline const char *name() {return #name;} + +CRYPTOPP_DEFINE_NAME_STRING(ValueNames) //!< string, a list of value names with a semicolon (';') after each name +CRYPTOPP_DEFINE_NAME_STRING(Version) //!< int +CRYPTOPP_DEFINE_NAME_STRING(Seed) //!< ConstByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(Key) //!< ConstByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(IV) //!< ConstByteArrayParameter, also accepts const byte * for backwards compatibility +CRYPTOPP_DEFINE_NAME_STRING(StolenIV) //!< byte * +CRYPTOPP_DEFINE_NAME_STRING(Rounds) //!< int +CRYPTOPP_DEFINE_NAME_STRING(FeedbackSize) //!< int +CRYPTOPP_DEFINE_NAME_STRING(WordSize) //!< int, in bytes +CRYPTOPP_DEFINE_NAME_STRING(BlockSize) //!< int, in bytes +CRYPTOPP_DEFINE_NAME_STRING(EffectiveKeyLength) //!< int, in bits +CRYPTOPP_DEFINE_NAME_STRING(KeySize) //!< int, in bits +CRYPTOPP_DEFINE_NAME_STRING(ModulusSize) //!< int, in bits +CRYPTOPP_DEFINE_NAME_STRING(SubgroupOrderSize) //!< int, in bits +CRYPTOPP_DEFINE_NAME_STRING(PrivateExponentSize)//!< int, in bits +CRYPTOPP_DEFINE_NAME_STRING(Modulus) //!< Integer +CRYPTOPP_DEFINE_NAME_STRING(PublicExponent) //!< Integer +CRYPTOPP_DEFINE_NAME_STRING(PrivateExponent) //!< Integer +CRYPTOPP_DEFINE_NAME_STRING(PublicElement) //!< Integer +CRYPTOPP_DEFINE_NAME_STRING(SubgroupOrder) //!< Integer +CRYPTOPP_DEFINE_NAME_STRING(Cofactor) //!< Integer +CRYPTOPP_DEFINE_NAME_STRING(SubgroupGenerator) //!< Integer, ECP::Point, or EC2N::Point +CRYPTOPP_DEFINE_NAME_STRING(Curve) //!< ECP or EC2N +CRYPTOPP_DEFINE_NAME_STRING(GroupOID) //!< OID +CRYPTOPP_DEFINE_NAME_STRING(PointerToPrimeSelector) //!< const PrimeSelector * +CRYPTOPP_DEFINE_NAME_STRING(Prime1) //!< Integer +CRYPTOPP_DEFINE_NAME_STRING(Prime2) //!< Integer +CRYPTOPP_DEFINE_NAME_STRING(ModPrime1PrivateExponent) //!< Integer +CRYPTOPP_DEFINE_NAME_STRING(ModPrime2PrivateExponent) //!< Integer +CRYPTOPP_DEFINE_NAME_STRING(MultiplicativeInverseOfPrime2ModPrime1) //!< Integer +CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime1) //!< Integer +CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime2) //!< Integer +CRYPTOPP_DEFINE_NAME_STRING(PutMessage) //!< bool +CRYPTOPP_DEFINE_NAME_STRING(TruncatedDigestSize) //!< int +CRYPTOPP_DEFINE_NAME_STRING(BlockPaddingScheme) //!< StreamTransformationFilter::BlockPaddingScheme +CRYPTOPP_DEFINE_NAME_STRING(HashVerificationFilterFlags) //!< word32 +CRYPTOPP_DEFINE_NAME_STRING(AuthenticatedDecryptionFilterFlags) //!< word32 +CRYPTOPP_DEFINE_NAME_STRING(SignatureVerificationFilterFlags) //!< word32 +CRYPTOPP_DEFINE_NAME_STRING(InputBuffer) //!< ConstByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(OutputBuffer) //!< ByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(InputFileName) //!< const char * +CRYPTOPP_DEFINE_NAME_STRING(InputStreamPointer) //!< std::istream * +CRYPTOPP_DEFINE_NAME_STRING(InputBinaryMode) //!< bool +CRYPTOPP_DEFINE_NAME_STRING(OutputFileName) //!< const char * +CRYPTOPP_DEFINE_NAME_STRING(OutputStreamPointer) //!< std::ostream * +CRYPTOPP_DEFINE_NAME_STRING(OutputBinaryMode) //!< bool +CRYPTOPP_DEFINE_NAME_STRING(EncodingParameters) //!< ConstByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(KeyDerivationParameters) //!< ConstByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(Separator) //< ConstByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(Terminator) //< ConstByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(Uppercase) //< bool +CRYPTOPP_DEFINE_NAME_STRING(GroupSize) //< int +CRYPTOPP_DEFINE_NAME_STRING(Pad) //< bool +CRYPTOPP_DEFINE_NAME_STRING(PaddingByte) //< byte +CRYPTOPP_DEFINE_NAME_STRING(Log2Base) //< int +CRYPTOPP_DEFINE_NAME_STRING(EncodingLookupArray) //< const byte * +CRYPTOPP_DEFINE_NAME_STRING(DecodingLookupArray) //< const byte * +CRYPTOPP_DEFINE_NAME_STRING(InsertLineBreaks) //< bool +CRYPTOPP_DEFINE_NAME_STRING(MaxLineLength) //< int +CRYPTOPP_DEFINE_NAME_STRING(DigestSize) //!< int, in bytes +CRYPTOPP_DEFINE_NAME_STRING(L1KeyLength) //!< int, in bytes +CRYPTOPP_DEFINE_NAME_STRING(TableSize) //!< int, in bytes + +DOCUMENTED_NAMESPACE_END + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/asn.cpp b/src-cryptopp/asn.cpp new file mode 100644 index 0000000..3ebbaf7 --- /dev/null +++ b/src-cryptopp/asn.cpp @@ -0,0 +1,595 @@ +// asn.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "asn.h" + +#include +#include + +NAMESPACE_BEGIN(CryptoPP) +USING_NAMESPACE(std) + +/// DER Length +size_t DERLengthEncode(BufferedTransformation &bt, lword length) +{ + size_t i=0; + if (length <= 0x7f) + { + bt.Put(byte(length)); + i++; + } + else + { + bt.Put(byte(BytePrecision(length) | 0x80)); + i++; + for (int j=BytePrecision(length); j; --j) + { + bt.Put(byte(length >> (j-1)*8)); + i++; + } + } + return i; +} + +bool BERLengthDecode(BufferedTransformation &bt, lword &length, bool &definiteLength) +{ + byte b; + + if (!bt.Get(b)) + return false; + + if (!(b & 0x80)) + { + definiteLength = true; + length = b; + } + else + { + unsigned int lengthBytes = b & 0x7f; + + if (lengthBytes == 0) + { + definiteLength = false; + return true; + } + + definiteLength = true; + length = 0; + while (lengthBytes--) + { + if (length >> (8*(sizeof(length)-1))) + BERDecodeError(); // length about to overflow + + if (!bt.Get(b)) + return false; + + length = (length << 8) | b; + } + } + return true; +} + +bool BERLengthDecode(BufferedTransformation &bt, size_t &length) +{ + lword lw; + bool definiteLength; + if (!BERLengthDecode(bt, lw, definiteLength)) + BERDecodeError(); + if (!SafeConvert(lw, length)) + BERDecodeError(); + return definiteLength; +} + +void DEREncodeNull(BufferedTransformation &out) +{ + out.Put(TAG_NULL); + out.Put(0); +} + +void BERDecodeNull(BufferedTransformation &in) +{ + byte b; + if (!in.Get(b) || b != TAG_NULL) + BERDecodeError(); + size_t length; + if (!BERLengthDecode(in, length) || length != 0) + BERDecodeError(); +} + +/// ASN Strings +size_t DEREncodeOctetString(BufferedTransformation &bt, const byte *str, size_t strLen) +{ + bt.Put(OCTET_STRING); + size_t lengthBytes = DERLengthEncode(bt, strLen); + bt.Put(str, strLen); + return 1+lengthBytes+strLen; +} + +size_t DEREncodeOctetString(BufferedTransformation &bt, const SecByteBlock &str) +{ + return DEREncodeOctetString(bt, str.begin(), str.size()); +} + +size_t BERDecodeOctetString(BufferedTransformation &bt, SecByteBlock &str) +{ + byte b; + if (!bt.Get(b) || b != OCTET_STRING) + BERDecodeError(); + + size_t bc; + if (!BERLengthDecode(bt, bc)) + BERDecodeError(); + + str.resize(bc); + if (bc != bt.Get(str, bc)) + BERDecodeError(); + return bc; +} + +size_t BERDecodeOctetString(BufferedTransformation &bt, BufferedTransformation &str) +{ + byte b; + if (!bt.Get(b) || b != OCTET_STRING) + BERDecodeError(); + + size_t bc; + if (!BERLengthDecode(bt, bc)) + BERDecodeError(); + + bt.TransferTo(str, bc); + return bc; +} + +size_t DEREncodeTextString(BufferedTransformation &bt, const std::string &str, byte asnTag) +{ + bt.Put(asnTag); + size_t lengthBytes = DERLengthEncode(bt, str.size()); + bt.Put((const byte *)str.data(), str.size()); + return 1+lengthBytes+str.size(); +} + +size_t BERDecodeTextString(BufferedTransformation &bt, std::string &str, byte asnTag) +{ + byte b; + if (!bt.Get(b) || b != asnTag) + BERDecodeError(); + + size_t bc; + if (!BERLengthDecode(bt, bc)) + BERDecodeError(); + + SecByteBlock temp(bc); + if (bc != bt.Get(temp, bc)) + BERDecodeError(); + str.assign((char *)temp.begin(), bc); + return bc; +} + +/// ASN BitString +size_t DEREncodeBitString(BufferedTransformation &bt, const byte *str, size_t strLen, unsigned int unusedBits) +{ + bt.Put(BIT_STRING); + size_t lengthBytes = DERLengthEncode(bt, strLen+1); + bt.Put((byte)unusedBits); + bt.Put(str, strLen); + return 2+lengthBytes+strLen; +} + +size_t BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits) +{ + byte b; + if (!bt.Get(b) || b != BIT_STRING) + BERDecodeError(); + + size_t bc; + if (!BERLengthDecode(bt, bc)) + BERDecodeError(); + + byte unused; + if (!bt.Get(unused)) + BERDecodeError(); + unusedBits = unused; + str.resize(bc-1); + if ((bc-1) != bt.Get(str, bc-1)) + BERDecodeError(); + return bc-1; +} + +void DERReencode(BufferedTransformation &source, BufferedTransformation &dest) +{ + byte tag; + source.Peek(tag); + BERGeneralDecoder decoder(source, tag); + DERGeneralEncoder encoder(dest, tag); + if (decoder.IsDefiniteLength()) + decoder.TransferTo(encoder, decoder.RemainingLength()); + else + { + while (!decoder.EndReached()) + DERReencode(decoder, encoder); + } + decoder.MessageEnd(); + encoder.MessageEnd(); +} + +void OID::EncodeValue(BufferedTransformation &bt, word32 v) +{ + for (unsigned int i=RoundUpToMultipleOf(STDMAX(7U,BitPrecision(v)), 7U)-7; i != 0; i-=7) + bt.Put((byte)(0x80 | ((v >> i) & 0x7f))); + bt.Put((byte)(v & 0x7f)); +} + +size_t OID::DecodeValue(BufferedTransformation &bt, word32 &v) +{ + byte b; + size_t i=0; + v = 0; + while (true) + { + if (!bt.Get(b)) + BERDecodeError(); + i++; + v <<= 7; + v += b & 0x7f; + if (!(b & 0x80)) + return i; + } +} + +void OID::DEREncode(BufferedTransformation &bt) const +{ + assert(m_values.size() >= 2); + ByteQueue temp; + temp.Put(byte(m_values[0] * 40 + m_values[1])); + for (size_t i=2; i 0) + { + word32 v; + size_t valueLen = DecodeValue(bt, v); + if (valueLen > length) + BERDecodeError(); + m_values.push_back(v); + length -= valueLen; + } +} + +void OID::BERDecodeAndCheck(BufferedTransformation &bt) const +{ + OID oid(bt); + if (*this != oid) + BERDecodeError(); +} + +inline BufferedTransformation & EncodedObjectFilter::CurrentTarget() +{ + if (m_flags & PUT_OBJECTS) + return *AttachedTransformation(); + else + return TheBitBucket(); +} + +void EncodedObjectFilter::Put(const byte *inString, size_t length) +{ + if (m_nCurrentObject == m_nObjects) + { + AttachedTransformation()->Put(inString, length); + return; + } + + LazyPutter lazyPutter(m_queue, inString, length); + + while (m_queue.AnyRetrievable()) + { + switch (m_state) + { + case IDENTIFIER: + if (!m_queue.Get(m_id)) + return; + m_queue.TransferTo(CurrentTarget(), 1); + m_state = LENGTH; // fall through + case LENGTH: + { + byte b; + if (m_level > 0 && m_id == 0 && m_queue.Peek(b) && b == 0) + { + m_queue.TransferTo(CurrentTarget(), 1); + m_level--; + m_state = IDENTIFIER; + break; + } + ByteQueue::Walker walker(m_queue); + bool definiteLength; + if (!BERLengthDecode(walker, m_lengthRemaining, definiteLength)) + return; + m_queue.TransferTo(CurrentTarget(), walker.GetCurrentPosition()); + if (!((m_id & CONSTRUCTED) || definiteLength)) + BERDecodeError(); + if (!definiteLength) + { + if (!(m_id & CONSTRUCTED)) + BERDecodeError(); + m_level++; + m_state = IDENTIFIER; + break; + } + m_state = BODY; // fall through + } + case BODY: + m_lengthRemaining -= m_queue.TransferTo(CurrentTarget(), m_lengthRemaining); + + if (m_lengthRemaining == 0) + m_state = IDENTIFIER; + } + + if (m_state == IDENTIFIER && m_level == 0) + { + // just finished processing a level 0 object + ++m_nCurrentObject; + + if (m_flags & PUT_MESSANGE_END_AFTER_EACH_OBJECT) + AttachedTransformation()->MessageEnd(); + + if (m_nCurrentObject == m_nObjects) + { + if (m_flags & PUT_MESSANGE_END_AFTER_ALL_OBJECTS) + AttachedTransformation()->MessageEnd(); + + if (m_flags & PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS) + AttachedTransformation()->MessageSeriesEnd(); + + m_queue.TransferAllTo(*AttachedTransformation()); + return; + } + } + } +} + +BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag) + : m_inQueue(inQueue), m_finished(false) +{ + Init(asnTag); +} + +BERGeneralDecoder::BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag) + : m_inQueue(inQueue), m_finished(false) +{ + Init(asnTag); +} + +void BERGeneralDecoder::Init(byte asnTag) +{ + byte b; + if (!m_inQueue.Get(b) || b != asnTag) + BERDecodeError(); + + if (!BERLengthDecode(m_inQueue, m_length, m_definiteLength)) + BERDecodeError(); + + if (!m_definiteLength && !(asnTag & CONSTRUCTED)) + BERDecodeError(); // cannot be primitive and have indefinite length +} + +BERGeneralDecoder::~BERGeneralDecoder() +{ + try // avoid throwing in constructor + { + if (!m_finished) + MessageEnd(); + } + catch (...) + { + } +} + +bool BERGeneralDecoder::EndReached() const +{ + if (m_definiteLength) + return m_length == 0; + else + { // check end-of-content octets + word16 i; + return (m_inQueue.PeekWord16(i)==2 && i==0); + } +} + +byte BERGeneralDecoder::PeekByte() const +{ + byte b; + if (!Peek(b)) + BERDecodeError(); + return b; +} + +void BERGeneralDecoder::CheckByte(byte check) +{ + byte b; + if (!Get(b) || b != check) + BERDecodeError(); +} + +void BERGeneralDecoder::MessageEnd() +{ + m_finished = true; + if (m_definiteLength) + { + if (m_length != 0) + BERDecodeError(); + } + else + { // remove end-of-content octets + word16 i; + if (m_inQueue.GetWord16(i) != 2 || i != 0) + BERDecodeError(); + } +} + +size_t BERGeneralDecoder::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) +{ + if (m_definiteLength && transferBytes > m_length) + transferBytes = m_length; + size_t blockedBytes = m_inQueue.TransferTo2(target, transferBytes, channel, blocking); + ReduceLength(transferBytes); + return blockedBytes; +} + +size_t BERGeneralDecoder::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const +{ + if (m_definiteLength) + end = STDMIN(m_length, end); + return m_inQueue.CopyRangeTo2(target, begin, end, channel, blocking); +} + +lword BERGeneralDecoder::ReduceLength(lword delta) +{ + if (m_definiteLength) + { + if (m_length < delta) + BERDecodeError(); + m_length -= delta; + } + return delta; +} + +DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag) + : m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag) +{ +} + +DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag) + : m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag) +{ +} + +DERGeneralEncoder::~DERGeneralEncoder() +{ + try // avoid throwing in constructor + { + if (!m_finished) + MessageEnd(); + } + catch (...) + { + } +} + +void DERGeneralEncoder::MessageEnd() +{ + m_finished = true; + lword length = CurrentSize(); + m_outQueue.Put(m_asnTag); + DERLengthEncode(m_outQueue, length); + TransferTo(m_outQueue); +} + +// ************************************************************* + +void X509PublicKey::BERDecode(BufferedTransformation &bt) +{ + BERSequenceDecoder subjectPublicKeyInfo(bt); + BERSequenceDecoder algorithm(subjectPublicKeyInfo); + GetAlgorithmID().BERDecodeAndCheck(algorithm); + bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm); + algorithm.MessageEnd(); + + BERGeneralDecoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING); + subjectPublicKey.CheckByte(0); // unused bits + BERDecodePublicKey(subjectPublicKey, parametersPresent, (size_t)subjectPublicKey.RemainingLength()); + subjectPublicKey.MessageEnd(); + subjectPublicKeyInfo.MessageEnd(); +} + +void X509PublicKey::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder subjectPublicKeyInfo(bt); + + DERSequenceEncoder algorithm(subjectPublicKeyInfo); + GetAlgorithmID().DEREncode(algorithm); + DEREncodeAlgorithmParameters(algorithm); + algorithm.MessageEnd(); + + DERGeneralEncoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING); + subjectPublicKey.Put(0); // unused bits + DEREncodePublicKey(subjectPublicKey); + subjectPublicKey.MessageEnd(); + + subjectPublicKeyInfo.MessageEnd(); +} + +void PKCS8PrivateKey::BERDecode(BufferedTransformation &bt) +{ + BERSequenceDecoder privateKeyInfo(bt); + word32 version; + BERDecodeUnsigned(privateKeyInfo, version, INTEGER, 0, 0); // check version + + BERSequenceDecoder algorithm(privateKeyInfo); + GetAlgorithmID().BERDecodeAndCheck(algorithm); + bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm); + algorithm.MessageEnd(); + + BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING); + BERDecodePrivateKey(octetString, parametersPresent, (size_t)privateKeyInfo.RemainingLength()); + octetString.MessageEnd(); + + if (!privateKeyInfo.EndReached()) + BERDecodeOptionalAttributes(privateKeyInfo); + privateKeyInfo.MessageEnd(); +} + +void PKCS8PrivateKey::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder privateKeyInfo(bt); + DEREncodeUnsigned(privateKeyInfo, 0); // version + + DERSequenceEncoder algorithm(privateKeyInfo); + GetAlgorithmID().DEREncode(algorithm); + DEREncodeAlgorithmParameters(algorithm); + algorithm.MessageEnd(); + + DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING); + DEREncodePrivateKey(octetString); + octetString.MessageEnd(); + + DEREncodeOptionalAttributes(privateKeyInfo); + privateKeyInfo.MessageEnd(); +} + +void PKCS8PrivateKey::BERDecodeOptionalAttributes(BufferedTransformation &bt) +{ + DERReencode(bt, m_optionalAttributes); +} + +void PKCS8PrivateKey::DEREncodeOptionalAttributes(BufferedTransformation &bt) const +{ + m_optionalAttributes.CopyTo(bt); +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/asn.h b/src-cryptopp/asn.h new file mode 100644 index 0000000..c35126b --- /dev/null +++ b/src-cryptopp/asn.h @@ -0,0 +1,369 @@ +#ifndef CRYPTOPP_ASN_H +#define CRYPTOPP_ASN_H + +#include "filters.h" +#include "queue.h" +#include + +NAMESPACE_BEGIN(CryptoPP) + +// these tags and flags are not complete +enum ASNTag +{ + BOOLEAN = 0x01, + INTEGER = 0x02, + BIT_STRING = 0x03, + OCTET_STRING = 0x04, + TAG_NULL = 0x05, + OBJECT_IDENTIFIER = 0x06, + OBJECT_DESCRIPTOR = 0x07, + EXTERNAL = 0x08, + REAL = 0x09, + ENUMERATED = 0x0a, + UTF8_STRING = 0x0c, + SEQUENCE = 0x10, + SET = 0x11, + NUMERIC_STRING = 0x12, + PRINTABLE_STRING = 0x13, + T61_STRING = 0x14, + VIDEOTEXT_STRING = 0x15, + IA5_STRING = 0x16, + UTC_TIME = 0x17, + GENERALIZED_TIME = 0x18, + GRAPHIC_STRING = 0x19, + VISIBLE_STRING = 0x1a, + GENERAL_STRING = 0x1b +}; + +enum ASNIdFlag +{ + UNIVERSAL = 0x00, +// DATA = 0x01, +// HEADER = 0x02, + CONSTRUCTED = 0x20, + APPLICATION = 0x40, + CONTEXT_SPECIFIC = 0x80, + PRIVATE = 0xc0 +}; + +inline void BERDecodeError() {throw BERDecodeErr();} + +class CRYPTOPP_DLL UnknownOID : public BERDecodeErr +{ +public: + UnknownOID() : BERDecodeErr("BER decode error: unknown object identifier") {} + UnknownOID(const char *err) : BERDecodeErr(err) {} +}; + +// unsigned int DERLengthEncode(unsigned int length, byte *output=0); +CRYPTOPP_DLL size_t CRYPTOPP_API DERLengthEncode(BufferedTransformation &out, lword length); +// returns false if indefinite length +CRYPTOPP_DLL bool CRYPTOPP_API BERLengthDecode(BufferedTransformation &in, size_t &length); + +CRYPTOPP_DLL void CRYPTOPP_API DEREncodeNull(BufferedTransformation &out); +CRYPTOPP_DLL void CRYPTOPP_API BERDecodeNull(BufferedTransformation &in); + +CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &out, const byte *str, size_t strLen); +CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeOctetString(BufferedTransformation &out, const SecByteBlock &str); +CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &in, SecByteBlock &str); +CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeOctetString(BufferedTransformation &in, BufferedTransformation &str); + +// for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING +CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeTextString(BufferedTransformation &out, const std::string &str, byte asnTag); +CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeTextString(BufferedTransformation &in, std::string &str, byte asnTag); + +CRYPTOPP_DLL size_t CRYPTOPP_API DEREncodeBitString(BufferedTransformation &out, const byte *str, size_t strLen, unsigned int unusedBits=0); +CRYPTOPP_DLL size_t CRYPTOPP_API BERDecodeBitString(BufferedTransformation &in, SecByteBlock &str, unsigned int &unusedBits); + +// BER decode from source and DER reencode into dest +CRYPTOPP_DLL void CRYPTOPP_API DERReencode(BufferedTransformation &source, BufferedTransformation &dest); + +//! Object Identifier +class CRYPTOPP_DLL OID +{ +public: + OID() {} + OID(word32 v) : m_values(1, v) {} + OID(BufferedTransformation &bt) {BERDecode(bt);} + + inline OID & operator+=(word32 rhs) {m_values.push_back(rhs); return *this;} + + void DEREncode(BufferedTransformation &bt) const; + void BERDecode(BufferedTransformation &bt); + + // throw BERDecodeErr() if decoded value doesn't equal this OID + void BERDecodeAndCheck(BufferedTransformation &bt) const; + + std::vector m_values; + +private: + static void EncodeValue(BufferedTransformation &bt, word32 v); + static size_t DecodeValue(BufferedTransformation &bt, word32 &v); +}; + +class EncodedObjectFilter : public Filter +{ +public: + enum Flag {PUT_OBJECTS=1, PUT_MESSANGE_END_AFTER_EACH_OBJECT=2, PUT_MESSANGE_END_AFTER_ALL_OBJECTS=4, PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS=8}; + EncodedObjectFilter(BufferedTransformation *attachment = NULL, unsigned int nObjects = 1, word32 flags = 0); + + void Put(const byte *inString, size_t length); + + unsigned int GetNumberOfCompletedObjects() const {return m_nCurrentObject;} + unsigned long GetPositionOfObject(unsigned int i) const {return m_positions[i];} + +private: + BufferedTransformation & CurrentTarget(); + + word32 m_flags; + unsigned int m_nObjects, m_nCurrentObject, m_level; + std::vector m_positions; + ByteQueue m_queue; + enum State {IDENTIFIER, LENGTH, BODY, TAIL, ALL_DONE} m_state; + byte m_id; + lword m_lengthRemaining; +}; + +//! BER General Decoder +class CRYPTOPP_DLL BERGeneralDecoder : public Store +{ +public: + explicit BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag); + explicit BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag); + ~BERGeneralDecoder(); + + bool IsDefiniteLength() const {return m_definiteLength;} + lword RemainingLength() const {assert(m_definiteLength); return m_length;} + bool EndReached() const; + byte PeekByte() const; + void CheckByte(byte b); + + size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); + size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const; + + // call this to denote end of sequence + void MessageEnd(); + +protected: + BufferedTransformation &m_inQueue; + bool m_finished, m_definiteLength; + lword m_length; + +private: + void Init(byte asnTag); + void StoreInitialize(const NameValuePairs ¶meters) {assert(false);} + lword ReduceLength(lword delta); +}; + +//! DER General Encoder +class CRYPTOPP_DLL DERGeneralEncoder : public ByteQueue +{ +public: + explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED); + explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED); + ~DERGeneralEncoder(); + + // call this to denote end of sequence + void MessageEnd(); + +private: + BufferedTransformation &m_outQueue; + bool m_finished; + + byte m_asnTag; +}; + +//! BER Sequence Decoder +class CRYPTOPP_DLL BERSequenceDecoder : public BERGeneralDecoder +{ +public: + explicit BERSequenceDecoder(BufferedTransformation &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED) + : BERGeneralDecoder(inQueue, asnTag) {} + explicit BERSequenceDecoder(BERSequenceDecoder &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED) + : BERGeneralDecoder(inQueue, asnTag) {} +}; + +//! DER Sequence Encoder +class CRYPTOPP_DLL DERSequenceEncoder : public DERGeneralEncoder +{ +public: + explicit DERSequenceEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED) + : DERGeneralEncoder(outQueue, asnTag) {} + explicit DERSequenceEncoder(DERSequenceEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED) + : DERGeneralEncoder(outQueue, asnTag) {} +}; + +//! BER Set Decoder +class CRYPTOPP_DLL BERSetDecoder : public BERGeneralDecoder +{ +public: + explicit BERSetDecoder(BufferedTransformation &inQueue, byte asnTag = SET | CONSTRUCTED) + : BERGeneralDecoder(inQueue, asnTag) {} + explicit BERSetDecoder(BERSetDecoder &inQueue, byte asnTag = SET | CONSTRUCTED) + : BERGeneralDecoder(inQueue, asnTag) {} +}; + +//! DER Set Encoder +class CRYPTOPP_DLL DERSetEncoder : public DERGeneralEncoder +{ +public: + explicit DERSetEncoder(BufferedTransformation &outQueue, byte asnTag = SET | CONSTRUCTED) + : DERGeneralEncoder(outQueue, asnTag) {} + explicit DERSetEncoder(DERSetEncoder &outQueue, byte asnTag = SET | CONSTRUCTED) + : DERGeneralEncoder(outQueue, asnTag) {} +}; + +template +class ASNOptional : public member_ptr +{ +public: + void BERDecode(BERSequenceDecoder &seqDecoder, byte tag, byte mask = ~CONSTRUCTED) + { + byte b; + if (seqDecoder.Peek(b) && (b & mask) == tag) + reset(new T(seqDecoder)); + } + void DEREncode(BufferedTransformation &out) + { + if (this->get() != NULL) + this->get()->DEREncode(out); + } +}; + +//! _ +template +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1CryptoMaterial : public ASN1Object, public BASE +{ +public: + void Save(BufferedTransformation &bt) const + {BEREncode(bt);} + void Load(BufferedTransformation &bt) + {BERDecode(bt);} +}; + +//! encodes/decodes subjectPublicKeyInfo +class CRYPTOPP_DLL X509PublicKey : public ASN1CryptoMaterial +{ +public: + void BERDecode(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const; + + virtual OID GetAlgorithmID() const =0; + virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt) + {BERDecodeNull(bt); return false;} + virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const + {DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1 + + //! decode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header + virtual void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0; + //! encode subjectPublicKey part of subjectPublicKeyInfo, without the BIT STRING header + virtual void DEREncodePublicKey(BufferedTransformation &bt) const =0; +}; + +//! encodes/decodes privateKeyInfo +class CRYPTOPP_DLL PKCS8PrivateKey : public ASN1CryptoMaterial +{ +public: + void BERDecode(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const; + + virtual OID GetAlgorithmID() const =0; + virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt) + {BERDecodeNull(bt); return false;} + virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const + {DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1 + + //! decode privateKey part of privateKeyInfo, without the OCTET STRING header + virtual void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size) =0; + //! encode privateKey part of privateKeyInfo, without the OCTET STRING header + virtual void DEREncodePrivateKey(BufferedTransformation &bt) const =0; + + //! decode optional attributes including context-specific tag + /*! /note default implementation stores attributes to be output in DEREncodeOptionalAttributes */ + virtual void BERDecodeOptionalAttributes(BufferedTransformation &bt); + //! encode optional attributes including context-specific tag + virtual void DEREncodeOptionalAttributes(BufferedTransformation &bt) const; + +protected: + ByteQueue m_optionalAttributes; +}; + +// ******************************************************** + +//! DER Encode Unsigned +/*! for INTEGER, BOOLEAN, and ENUM */ +template +size_t DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag = INTEGER) +{ + byte buf[sizeof(w)+1]; + unsigned int bc; + if (asnTag == BOOLEAN) + { + buf[sizeof(w)] = w ? 0xff : 0; + bc = 1; + } + else + { + buf[0] = 0; + for (unsigned int i=0; i> (sizeof(w)-1-i)*8); + bc = sizeof(w); + while (bc > 1 && buf[sizeof(w)+1-bc] == 0) + --bc; + if (buf[sizeof(w)+1-bc] & 0x80) + ++bc; + } + out.Put(asnTag); + size_t lengthBytes = DERLengthEncode(out, bc); + out.Put(buf+sizeof(w)+1-bc, bc); + return 1+lengthBytes+bc; +} + +//! BER Decode Unsigned +// VC60 workaround: std::numeric_limits::max conflicts with MFC max macro +// CW41 workaround: std::numeric_limits::max causes a template error +template +void BERDecodeUnsigned(BufferedTransformation &in, T &w, byte asnTag = INTEGER, + T minValue = 0, T maxValue = 0xffffffff) +{ + byte b; + if (!in.Get(b) || b != asnTag) + BERDecodeError(); + + size_t bc; + BERLengthDecode(in, bc); + + SecByteBlock buf(bc); + + if (bc != in.Get(buf, bc)) + BERDecodeError(); + + const byte *ptr = buf; + while (bc > sizeof(w) && *ptr == 0) + { + bc--; + ptr++; + } + if (bc > sizeof(w)) + BERDecodeError(); + + w = 0; + for (unsigned int i=0; i maxValue) + BERDecodeError(); +} + +inline bool operator==(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) + {return lhs.m_values == rhs.m_values;} +inline bool operator!=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) + {return lhs.m_values != rhs.m_values;} +inline bool operator<(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs) + {return std::lexicographical_compare(lhs.m_values.begin(), lhs.m_values.end(), rhs.m_values.begin(), rhs.m_values.end());} +inline ::CryptoPP::OID operator+(const ::CryptoPP::OID &lhs, unsigned long rhs) + {return ::CryptoPP::OID(lhs)+=rhs;} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/authenc.h b/src-cryptopp/authenc.h new file mode 100644 index 0000000..f726716 --- /dev/null +++ b/src-cryptopp/authenc.h @@ -0,0 +1,49 @@ +#ifndef CRYPTOPP_AUTHENC_H +#define CRYPTOPP_AUTHENC_H + +#include "cryptlib.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! . +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedSymmetricCipherBase : public AuthenticatedSymmetricCipher +{ +public: + AuthenticatedSymmetricCipherBase() : m_state(State_Start) {} + + bool IsRandomAccess() const {return false;} + bool IsSelfInverting() const {return true;} + void UncheckedSetKey(const byte *,unsigned int,const CryptoPP::NameValuePairs &) {assert(false);} + + void SetKey(const byte *userKey, size_t keylength, const NameValuePairs ¶ms); + void Restart() {if (m_state > State_KeySet) m_state = State_KeySet;} + void Resynchronize(const byte *iv, int length=-1); + void Update(const byte *input, size_t length); + void ProcessData(byte *outString, const byte *inString, size_t length); + void TruncatedFinal(byte *mac, size_t macSize); + +protected: + void AuthenticateData(const byte *data, size_t len); + const SymmetricCipher & GetSymmetricCipher() const {return const_cast(this)->AccessSymmetricCipher();}; + + virtual SymmetricCipher & AccessSymmetricCipher() =0; + virtual bool AuthenticationIsOnPlaintext() const =0; + virtual unsigned int AuthenticationBlockSize() const =0; + virtual void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms) =0; + virtual void Resync(const byte *iv, size_t len) =0; + virtual size_t AuthenticateBlocks(const byte *data, size_t len) =0; + virtual void AuthenticateLastHeaderBlock() =0; + virtual void AuthenticateLastConfidentialBlock() {} + virtual void AuthenticateLastFooterBlock(byte *mac, size_t macSize) =0; + + enum State {State_Start, State_KeySet, State_IVSet, State_AuthUntransformed, State_AuthTransformed, State_AuthFooter}; + State m_state; + unsigned int m_bufferedDataLength; + lword m_totalHeaderLength, m_totalMessageLength, m_totalFooterLength; + AlignedSecByteBlock m_buffer; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/basecode.cpp b/src-cryptopp/basecode.cpp new file mode 100644 index 0000000..0c98b22 --- /dev/null +++ b/src-cryptopp/basecode.cpp @@ -0,0 +1,238 @@ +// basecode.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "basecode.h" +#include "fltrimpl.h" +#include + +NAMESPACE_BEGIN(CryptoPP) + +void BaseN_Encoder::IsolatedInitialize(const NameValuePairs ¶meters) +{ + parameters.GetRequiredParameter("BaseN_Encoder", Name::EncodingLookupArray(), m_alphabet); + + parameters.GetRequiredIntParameter("BaseN_Encoder", Name::Log2Base(), m_bitsPerChar); + if (m_bitsPerChar <= 0 || m_bitsPerChar >= 8) + throw InvalidArgument("BaseN_Encoder: Log2Base must be between 1 and 7 inclusive"); + + byte padding; + bool pad; + if (parameters.GetValue(Name::PaddingByte(), padding)) + pad = parameters.GetValueWithDefault(Name::Pad(), true); + else + pad = false; + m_padding = pad ? padding : -1; + + m_bytePos = m_bitPos = 0; + + int i = 8; + while (i%m_bitsPerChar != 0) + i += 8; + m_outputBlockSize = i/m_bitsPerChar; + + m_outBuf.New(m_outputBlockSize); +} + +size_t BaseN_Encoder::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) +{ + FILTER_BEGIN; + while (m_inputPosition < length) + { + if (m_bytePos == 0) + memset(m_outBuf, 0, m_outputBlockSize); + + { + unsigned int b = begin[m_inputPosition++], bitsLeftInSource = 8; + while (true) + { + assert(m_bitPos < m_bitsPerChar); + unsigned int bitsLeftInTarget = m_bitsPerChar-m_bitPos; + m_outBuf[m_bytePos] |= b >> (8-bitsLeftInTarget); + if (bitsLeftInSource >= bitsLeftInTarget) + { + m_bitPos = 0; + ++m_bytePos; + bitsLeftInSource -= bitsLeftInTarget; + if (bitsLeftInSource == 0) + break; + b <<= bitsLeftInTarget; + b &= 0xff; + } + else + { + m_bitPos += bitsLeftInSource; + break; + } + } + } + + assert(m_bytePos <= m_outputBlockSize); + if (m_bytePos == m_outputBlockSize) + { + int i; + for (i=0; i 0) + ++m_bytePos; + + int i; + for (i=0; i 0) + { + memset(m_outBuf+m_bytePos, m_padding, m_outputBlockSize-m_bytePos); + m_bytePos = m_outputBlockSize; + } + FILTER_OUTPUT(2, m_outBuf, m_bytePos, messageEnd); + m_bytePos = m_bitPos = 0; + } + FILTER_END_NO_MESSAGE_END; +} + +void BaseN_Decoder::IsolatedInitialize(const NameValuePairs ¶meters) +{ + parameters.GetRequiredParameter("BaseN_Decoder", Name::DecodingLookupArray(), m_lookup); + + parameters.GetRequiredIntParameter("BaseN_Decoder", Name::Log2Base(), m_bitsPerChar); + if (m_bitsPerChar <= 0 || m_bitsPerChar >= 8) + throw InvalidArgument("BaseN_Decoder: Log2Base must be between 1 and 7 inclusive"); + + m_bytePos = m_bitPos = 0; + + int i = m_bitsPerChar; + while (i%8 != 0) + i += m_bitsPerChar; + m_outputBlockSize = i/8; + + m_outBuf.New(m_outputBlockSize); +} + +size_t BaseN_Decoder::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) +{ + FILTER_BEGIN; + while (m_inputPosition < length) + { + unsigned int value; + value = m_lookup[begin[m_inputPosition++]]; + if (value >= 256) + continue; + + if (m_bytePos == 0 && m_bitPos == 0) + memset(m_outBuf, 0, m_outputBlockSize); + + { + int newBitPos = m_bitPos + m_bitsPerChar; + if (newBitPos <= 8) + m_outBuf[m_bytePos] |= value << (8-newBitPos); + else + { + m_outBuf[m_bytePos] |= value >> (newBitPos-8); + m_outBuf[m_bytePos+1] |= value << (16-newBitPos); + } + + m_bitPos = newBitPos; + while (m_bitPos >= 8) + { + m_bitPos -= 8; + ++m_bytePos; + } + } + + if (m_bytePos == m_outputBlockSize) + { + FILTER_OUTPUT(1, m_outBuf, m_outputBlockSize, 0); + m_bytePos = m_bitPos = 0; + } + } + if (messageEnd) + { + FILTER_OUTPUT(2, m_outBuf, m_bytePos, messageEnd); + m_bytePos = m_bitPos = 0; + } + FILTER_END_NO_MESSAGE_END; +} + +void BaseN_Decoder::InitializeDecodingLookupArray(int *lookup, const byte *alphabet, unsigned int base, bool caseInsensitive) +{ + std::fill(lookup, lookup+256, -1); + + for (unsigned int i=0; i +{ +public: + BaseN_Encoder(BufferedTransformation *attachment=NULL) + {Detach(attachment);} + + BaseN_Encoder(const byte *alphabet, int log2base, BufferedTransformation *attachment=NULL, int padding=-1) + { + Detach(attachment); + IsolatedInitialize(MakeParameters(Name::EncodingLookupArray(), alphabet) + (Name::Log2Base(), log2base) + (Name::Pad(), padding != -1) + (Name::PaddingByte(), byte(padding))); + } + + void IsolatedInitialize(const NameValuePairs ¶meters); + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); + +private: + const byte *m_alphabet; + int m_padding, m_bitsPerChar, m_outputBlockSize; + int m_bytePos, m_bitPos; + SecByteBlock m_outBuf; +}; + +//! base n decoder, where n is a power of 2 +class CRYPTOPP_DLL BaseN_Decoder : public Unflushable +{ +public: + BaseN_Decoder(BufferedTransformation *attachment=NULL) + {Detach(attachment);} + + BaseN_Decoder(const int *lookup, int log2base, BufferedTransformation *attachment=NULL) + { + Detach(attachment); + IsolatedInitialize(MakeParameters(Name::DecodingLookupArray(), lookup)(Name::Log2Base(), log2base)); + } + + void IsolatedInitialize(const NameValuePairs ¶meters); + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); + + static void CRYPTOPP_API InitializeDecodingLookupArray(int *lookup, const byte *alphabet, unsigned int base, bool caseInsensitive); + +private: + const int *m_lookup; + int m_padding, m_bitsPerChar, m_outputBlockSize; + int m_bytePos, m_bitPos; + SecByteBlock m_outBuf; +}; + +//! filter that breaks input stream into groups of fixed size +class CRYPTOPP_DLL Grouper : public Bufferless +{ +public: + Grouper(BufferedTransformation *attachment=NULL) + {Detach(attachment);} + + Grouper(int groupSize, const std::string &separator, const std::string &terminator, BufferedTransformation *attachment=NULL) + { + Detach(attachment); + IsolatedInitialize(MakeParameters(Name::GroupSize(), groupSize) + (Name::Separator(), ConstByteArrayParameter(separator)) + (Name::Terminator(), ConstByteArrayParameter(terminator))); + } + + void IsolatedInitialize(const NameValuePairs ¶meters); + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); + +private: + SecByteBlock m_separator, m_terminator; + size_t m_groupSize, m_counter; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/cbcmac.h b/src-cryptopp/cbcmac.h new file mode 100644 index 0000000..4675dcb --- /dev/null +++ b/src-cryptopp/cbcmac.h @@ -0,0 +1,50 @@ +#ifndef CRYPTOPP_CBCMAC_H +#define CRYPTOPP_CBCMAC_H + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! _ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_MAC_Base : public MessageAuthenticationCode +{ +public: + CBC_MAC_Base() {} + + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); + void Update(const byte *input, size_t length); + void TruncatedFinal(byte *mac, size_t size); + unsigned int DigestSize() const {return const_cast(this)->AccessCipher().BlockSize();} + +protected: + virtual BlockCipher & AccessCipher() =0; + +private: + void ProcessBuf(); + SecByteBlock m_reg; + unsigned int m_counter; +}; + +//! CBC-MAC +/*! Compatible with FIPS 113. T should be a class derived from BlockCipherDocumentation. + Secure only for fixed length messages. For variable length messages use CMAC or DMAC. +*/ +template +class CBC_MAC : public MessageAuthenticationCodeImpl >, public SameKeyLengthAs +{ +public: + CBC_MAC() {} + CBC_MAC(const byte *key, size_t length=SameKeyLengthAs::DEFAULT_KEYLENGTH) + {this->SetKey(key, length);} + + static std::string StaticAlgorithmName() {return std::string("CBC-MAC(") + T::StaticAlgorithmName() + ")";} + +private: + BlockCipher & AccessCipher() {return m_cipher;} + typename T::Encryption m_cipher; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/ccm.h b/src-cryptopp/ccm.h new file mode 100644 index 0000000..2f3c56b --- /dev/null +++ b/src-cryptopp/ccm.h @@ -0,0 +1,101 @@ +#ifndef CRYPTOPP_CCM_H +#define CRYPTOPP_CCM_H + +#include "authenc.h" +#include "modes.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! . +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CCM_Base : public AuthenticatedSymmetricCipherBase +{ +public: + CCM_Base() + : m_digestSize(0), m_L(0) {} + + // AuthenticatedSymmetricCipher + std::string AlgorithmName() const + {return GetBlockCipher().AlgorithmName() + std::string("/CCM");} + size_t MinKeyLength() const + {return GetBlockCipher().MinKeyLength();} + size_t MaxKeyLength() const + {return GetBlockCipher().MaxKeyLength();} + size_t DefaultKeyLength() const + {return GetBlockCipher().DefaultKeyLength();} + size_t GetValidKeyLength(size_t n) const + {return GetBlockCipher().GetValidKeyLength(n);} + bool IsValidKeyLength(size_t n) const + {return GetBlockCipher().IsValidKeyLength(n);} + unsigned int OptimalDataAlignment() const + {return GetBlockCipher().OptimalDataAlignment();} + IV_Requirement IVRequirement() const + {return UNIQUE_IV;} + unsigned int IVSize() const + {return 8;} + unsigned int MinIVLength() const + {return 7;} + unsigned int MaxIVLength() const + {return 13;} + unsigned int DigestSize() const + {return m_digestSize;} + lword MaxHeaderLength() const + {return W64LIT(0)-1;} + lword MaxMessageLength() const + {return m_L<8 ? (W64LIT(1)<<(8*m_L))-1 : W64LIT(0)-1;} + bool NeedsPrespecifiedDataLengths() const + {return true;} + void UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength); + +protected: + // AuthenticatedSymmetricCipherBase + bool AuthenticationIsOnPlaintext() const + {return true;} + unsigned int AuthenticationBlockSize() const + {return GetBlockCipher().BlockSize();} + void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms); + void Resync(const byte *iv, size_t len); + size_t AuthenticateBlocks(const byte *data, size_t len); + void AuthenticateLastHeaderBlock(); + void AuthenticateLastConfidentialBlock(); + void AuthenticateLastFooterBlock(byte *mac, size_t macSize); + SymmetricCipher & AccessSymmetricCipher() {return m_ctr;} + + virtual BlockCipher & AccessBlockCipher() =0; + virtual int DefaultDigestSize() const =0; + + const BlockCipher & GetBlockCipher() const {return const_cast(this)->AccessBlockCipher();}; + byte *CBC_Buffer() {return m_buffer+REQUIRED_BLOCKSIZE;} + + enum {REQUIRED_BLOCKSIZE = 16}; + int m_digestSize, m_L; + word64 m_messageLength, m_aadLength; + CTR_Mode_ExternalCipher::Encryption m_ctr; +}; + +//! . +template +class CCM_Final : public CCM_Base +{ +public: + static std::string StaticAlgorithmName() + {return T_BlockCipher::StaticAlgorithmName() + std::string("/CCM");} + bool IsForwardTransformation() const + {return T_IsEncryption;} + +private: + BlockCipher & AccessBlockCipher() {return m_cipher;} + int DefaultDigestSize() const {return T_DefaultDigestSize;} + typename T_BlockCipher::Encryption m_cipher; +}; + +/// CCM +template +struct CCM : public AuthenticatedSymmetricCipherDocumentation +{ + typedef CCM_Final Encryption; + typedef CCM_Final Decryption; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/channels.h b/src-cryptopp/channels.h new file mode 100644 index 0000000..8374156 --- /dev/null +++ b/src-cryptopp/channels.h @@ -0,0 +1,123 @@ +#ifndef CRYPTOPP_CHANNELS_H +#define CRYPTOPP_CHANNELS_H + +#include "simple.h" +#include "smartptr.h" +#include +#include + +NAMESPACE_BEGIN(CryptoPP) + +#if 0 +//! Route input on default channel to different and/or multiple channels based on message sequence number +class MessageSwitch : public Sink +{ +public: + void AddDefaultRoute(BufferedTransformation &destination, const std::string &channel); + void AddRoute(unsigned int begin, unsigned int end, BufferedTransformation &destination, const std::string &channel); + + void Put(byte inByte); + void Put(const byte *inString, unsigned int length); + + void Flush(bool completeFlush, int propagation=-1); + void MessageEnd(int propagation=-1); + void PutMessageEnd(const byte *inString, unsigned int length, int propagation=-1); + void MessageSeriesEnd(int propagation=-1); + +private: + typedef std::pair Route; + struct RangeRoute + { + RangeRoute(unsigned int begin, unsigned int end, const Route &route) + : begin(begin), end(end), route(route) {} + bool operator<(const RangeRoute &rhs) const {return begin < rhs.begin;} + unsigned int begin, end; + Route route; + }; + + typedef std::list RouteList; + typedef std::list DefaultRouteList; + + RouteList m_routes; + DefaultRouteList m_defaultRoutes; + unsigned int m_nCurrentMessage; +}; +#endif + +class ChannelSwitchTypedefs +{ +public: + typedef std::pair Route; + typedef std::multimap RouteMap; + + typedef std::pair > DefaultRoute; + typedef std::list DefaultRouteList; + + // SunCC workaround: can't use const_iterator here + typedef RouteMap::iterator MapIterator; + typedef DefaultRouteList::iterator ListIterator; +}; + +class ChannelSwitch; + +class ChannelRouteIterator : public ChannelSwitchTypedefs +{ +public: + ChannelSwitch& m_cs; + std::string m_channel; + bool m_useDefault; + MapIterator m_itMapCurrent, m_itMapEnd; + ListIterator m_itListCurrent, m_itListEnd; + + ChannelRouteIterator(ChannelSwitch &cs) : m_cs(cs) {} + void Reset(const std::string &channel); + bool End() const; + void Next(); + BufferedTransformation & Destination(); + const std::string & Channel(); +}; + +//! Route input to different and/or multiple channels based on channel ID +class CRYPTOPP_DLL ChannelSwitch : public Multichannel, public ChannelSwitchTypedefs +{ +public: + ChannelSwitch() : m_it(*this), m_blocked(false) {} + ChannelSwitch(BufferedTransformation &destination) : m_it(*this), m_blocked(false) + { + AddDefaultRoute(destination); + } + ChannelSwitch(BufferedTransformation &destination, const std::string &outChannel) : m_it(*this), m_blocked(false) + { + AddDefaultRoute(destination, outChannel); + } + + void IsolatedInitialize(const NameValuePairs ¶meters=g_nullNameValuePairs); + + size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking); + size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking); + + bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true); + bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true); + + byte * ChannelCreatePutSpace(const std::string &channel, size_t &size); + + void AddDefaultRoute(BufferedTransformation &destination); + void RemoveDefaultRoute(BufferedTransformation &destination); + void AddDefaultRoute(BufferedTransformation &destination, const std::string &outChannel); + void RemoveDefaultRoute(BufferedTransformation &destination, const std::string &outChannel); + void AddRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel); + void RemoveRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel); + +private: + RouteMap m_routeMap; + DefaultRouteList m_defaultRoutes; + + ChannelRouteIterator m_it; + bool m_blocked; + + friend class ChannelRouteIterator; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/cmac.h b/src-cryptopp/cmac.h new file mode 100644 index 0000000..ab3ecf8 --- /dev/null +++ b/src-cryptopp/cmac.h @@ -0,0 +1,52 @@ +#ifndef CRYPTOPP_CMAC_H +#define CRYPTOPP_CMAC_H + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! _ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CMAC_Base : public MessageAuthenticationCode +{ +public: + CMAC_Base() {} + + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); + void Update(const byte *input, size_t length); + void TruncatedFinal(byte *mac, size_t size); + unsigned int DigestSize() const {return GetCipher().BlockSize();} + unsigned int OptimalBlockSize() const {return GetCipher().BlockSize();} + unsigned int OptimalDataAlignment() const {return GetCipher().OptimalDataAlignment();} + +protected: + friend class EAX_Base; + + const BlockCipher & GetCipher() const {return const_cast(this)->AccessCipher();} + virtual BlockCipher & AccessCipher() =0; + + void ProcessBuf(); + SecByteBlock m_reg; + unsigned int m_counter; +}; + +/// CMAC +/*! Template parameter T should be a class derived from BlockCipherDocumentation, for example AES, with a block size of 8, 16, or 32 */ +template +class CMAC : public MessageAuthenticationCodeImpl >, public SameKeyLengthAs +{ +public: + CMAC() {} + CMAC(const byte *key, size_t length=SameKeyLengthAs::DEFAULT_KEYLENGTH) + {this->SetKey(key, length);} + + static std::string StaticAlgorithmName() {return std::string("CMAC(") + T::StaticAlgorithmName() + ")";} + +private: + BlockCipher & AccessCipher() {return m_cipher;} + typename T::Encryption m_cipher; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/config.h b/src-cryptopp/config.h new file mode 100644 index 0000000..a31ccbc --- /dev/null +++ b/src-cryptopp/config.h @@ -0,0 +1,459 @@ +#ifndef CRYPTOPP_CONFIG_H +#define CRYPTOPP_CONFIG_H + +extern const char*cryptopp_extra_version; + +// ***************** Important Settings ******************** + +// define this if running on a big-endian CPU +#if !defined(IS_LITTLE_ENDIAN) && (defined(__BIG_ENDIAN__) || defined(__sparc) || defined(__sparc__) || defined(__hppa__) || defined(__mips__) || (defined(__MWERKS__) && !defined(__INTEL__))) +# define IS_BIG_ENDIAN +#endif + +// define this if running on a little-endian CPU +// big endian will be assumed if IS_LITTLE_ENDIAN is not defined +#ifndef IS_BIG_ENDIAN +# define IS_LITTLE_ENDIAN +#endif + +// define this if you want to disable all OS-dependent features, +// such as sockets and OS-provided random number generators +// #define NO_OS_DEPENDENCE + +// Define this to use features provided by Microsoft's CryptoAPI. +// Currently the only feature used is random number generation. +// This macro will be ignored if NO_OS_DEPENDENCE is defined. +#define USE_MS_CRYPTOAPI + +// Define this to 1 to enforce the requirement in FIPS 186-2 Change Notice 1 that only 1024 bit moduli be used +#ifndef DSA_1024_BIT_MODULUS_ONLY +# define DSA_1024_BIT_MODULUS_ONLY 1 +#endif + +// ***************** Less Important Settings *************** + +// define this to retain (as much as possible) old deprecated function and class names +// #define CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY + +#define GZIP_OS_CODE 0 + +// Try this if your CPU has 256K internal cache or a slow multiply instruction +// and you want a (possibly) faster IDEA implementation using log tables +// #define IDEA_LARGECACHE + +// Define this if, for the linear congruential RNG, you want to use +// the original constants as specified in S.K. Park and K.W. Miller's +// CACM paper. +// #define LCRNG_ORIGINAL_NUMBERS + +// choose which style of sockets to wrap (mostly useful for cygwin which has both) +#define PREFER_BERKELEY_STYLE_SOCKETS +// #define PREFER_WINDOWS_STYLE_SOCKETS + +// set the name of Rijndael cipher, was "Rijndael" before version 5.3 +#define CRYPTOPP_RIJNDAEL_NAME "AES" + +// ***************** Important Settings Again ******************** +// But the defaults should be ok. + +// namespace support is now required +#ifdef NO_NAMESPACE +# error namespace support is now required +#endif + +// Define this to workaround a Microsoft CryptoAPI bug where +// each call to CryptAcquireContext causes a 100 KB memory leak. +// Defining this will cause Crypto++ to make only one call to CryptAcquireContext. +#define WORKAROUND_MS_BUG_Q258000 + +#ifdef CRYPTOPP_DOXYGEN_PROCESSING +// Avoid putting "CryptoPP::" in front of everything in Doxygen output +# define CryptoPP +# define NAMESPACE_BEGIN(x) +# define NAMESPACE_END +// Get Doxygen to generate better documentation for these typedefs +# define DOCUMENTED_TYPEDEF(x, y) class y : public x {}; +#else +# define NAMESPACE_BEGIN(x) namespace x { +# define NAMESPACE_END } +# define DOCUMENTED_TYPEDEF(x, y) typedef x y; +#endif +#define ANONYMOUS_NAMESPACE_BEGIN namespace { +#define USING_NAMESPACE(x) using namespace x; +#define DOCUMENTED_NAMESPACE_BEGIN(x) namespace x { +#define DOCUMENTED_NAMESPACE_END } + +// What is the type of the third parameter to bind? +// For Unix, the new standard is ::socklen_t (typically unsigned int), and the old standard is int. +// Unfortunately there is no way to tell whether or not socklen_t is defined. +// To work around this, TYPE_OF_SOCKLEN_T is a macro so that you can change it from the makefile. +#ifndef TYPE_OF_SOCKLEN_T +# if defined(_WIN32) || defined(__CYGWIN__) +# define TYPE_OF_SOCKLEN_T int +# else +# define TYPE_OF_SOCKLEN_T ::socklen_t +# endif +#endif + +#if defined(__CYGWIN__) && defined(PREFER_WINDOWS_STYLE_SOCKETS) +# define __USE_W32_SOCKETS +#endif + +typedef unsigned char byte; // put in global namespace to avoid ambiguity with other byte typedefs + +NAMESPACE_BEGIN(CryptoPP) + +typedef unsigned short word16; +typedef unsigned int word32; + +#if defined(_MSC_VER) || defined(__BORLANDC__) + typedef unsigned __int64 word64; + #define W64LIT(x) x##ui64 +#else + typedef unsigned long long word64; + #define W64LIT(x) x##ULL +#endif + +// define large word type, used for file offsets and such +typedef word64 lword; +const lword LWORD_MAX = W64LIT(0xffffffffffffffff); + +#ifdef __GNUC__ + #define CRYPTOPP_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#endif + +// define hword, word, and dword. these are used for multiprecision integer arithmetic +// Intel compiler won't have _umul128 until version 10.0. See http://softwarecommunity.intel.com/isn/Community/en-US/forums/thread/30231625.aspx +#if (defined(_MSC_VER) && (!defined(__INTEL_COMPILER) || __INTEL_COMPILER >= 1000) && (defined(_M_X64) || defined(_M_IA64))) || (defined(__DECCXX) && defined(__alpha__)) || (defined(__INTEL_COMPILER) && defined(__x86_64__)) || (defined(__SUNPRO_CC) && defined(__x86_64__)) + typedef word32 hword; + typedef word64 word; +#else + #define CRYPTOPP_NATIVE_DWORD_AVAILABLE + #if defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || defined(__x86_64__) || defined(__mips64) || defined(__sparc64__) + #if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !(CRYPTOPP_GCC_VERSION == 40001 && defined(__APPLE__)) && CRYPTOPP_GCC_VERSION >= 30400 + // GCC 4.0.1 on MacOS X is missing __umodti3 and __udivti3 + // mode(TI) division broken on amd64 with GCC earlier than GCC 3.4 + typedef word32 hword; + typedef word64 word; + typedef __uint128_t dword; + typedef __uint128_t word128; + #define CRYPTOPP_WORD128_AVAILABLE + #else + // if we're here, it means we're on a 64-bit CPU but we don't have a way to obtain 128-bit multiplication results + typedef word16 hword; + typedef word32 word; + typedef word64 dword; + #endif + #else + // being here means the native register size is probably 32 bits or less + #define CRYPTOPP_BOOL_SLOW_WORD64 1 + typedef word16 hword; + typedef word32 word; + typedef word64 dword; + #endif +#endif +#ifndef CRYPTOPP_BOOL_SLOW_WORD64 + #define CRYPTOPP_BOOL_SLOW_WORD64 0 +#endif + +const unsigned int WORD_SIZE = sizeof(word); +const unsigned int WORD_BITS = WORD_SIZE * 8; + +NAMESPACE_END + +#ifndef CRYPTOPP_L1_CACHE_LINE_SIZE + // This should be a lower bound on the L1 cache line size. It's used for defense against timing attacks. + #if defined(_M_X64) || defined(__x86_64__) + #define CRYPTOPP_L1_CACHE_LINE_SIZE 64 + #else + // L1 cache line size is 32 on Pentium III and earlier + #define CRYPTOPP_L1_CACHE_LINE_SIZE 32 + #endif +#endif + +#if defined(_MSC_VER) + #if _MSC_VER == 1200 + #include + #endif + #if _MSC_VER > 1200 || defined(_mm_free) + #define CRYPTOPP_MSVC6PP_OR_LATER // VC 6 processor pack or later + #else + #define CRYPTOPP_MSVC6_NO_PP // VC 6 without processor pack + #endif +#endif + +#ifndef CRYPTOPP_ALIGN_DATA + #if defined(CRYPTOPP_MSVC6PP_OR_LATER) + #define CRYPTOPP_ALIGN_DATA(x) __declspec(align(x)) + #elif defined(__GNUC__) + #define CRYPTOPP_ALIGN_DATA(x) __attribute__((aligned(x))) + #else + #define CRYPTOPP_ALIGN_DATA(x) + #endif +#endif + +#ifndef CRYPTOPP_SECTION_ALIGN16 + #if defined(__GNUC__) && !defined(__APPLE__) + // the alignment attribute doesn't seem to work without this section attribute when -fdata-sections is turned on + #define CRYPTOPP_SECTION_ALIGN16 __attribute__((section ("CryptoPP_Align16"))) + #else + #define CRYPTOPP_SECTION_ALIGN16 + #endif +#endif + +#if defined(_MSC_VER) || defined(__fastcall) + #define CRYPTOPP_FASTCALL __fastcall +#else + #define CRYPTOPP_FASTCALL +#endif + +// VC60 workaround: it doesn't allow typename in some places +#if defined(_MSC_VER) && (_MSC_VER < 1300) +#define CPP_TYPENAME +#else +#define CPP_TYPENAME typename +#endif + +// VC60 workaround: can't cast unsigned __int64 to float or double +#if defined(_MSC_VER) && !defined(CRYPTOPP_MSVC6PP_OR_LATER) +#define CRYPTOPP_VC6_INT64 (__int64) +#else +#define CRYPTOPP_VC6_INT64 +#endif + +#ifdef _MSC_VER +#define CRYPTOPP_NO_VTABLE __declspec(novtable) +#else +#define CRYPTOPP_NO_VTABLE +#endif + +#ifdef _MSC_VER + // 4231: nonstandard extension used : 'extern' before template explicit instantiation + // 4250: dominance + // 4251: member needs to have dll-interface + // 4275: base needs to have dll-interface + // 4660: explicitly instantiating a class that's already implicitly instantiated + // 4661: no suitable definition provided for explicit template instantiation request + // 4786: identifer was truncated in debug information + // 4355: 'this' : used in base member initializer list + // 4910: '__declspec(dllexport)' and 'extern' are incompatible on an explicit instantiation +# pragma warning(disable: 4231 4250 4251 4275 4660 4661 4786 4355 4910) +#endif + +#ifdef __BORLANDC__ +// 8037: non-const function called for const object. needed to work around BCB2006 bug +# pragma warn -8037 +#endif + +#if (defined(_MSC_VER) && _MSC_VER <= 1300) || defined(__MWERKS__) || defined(_STLPORT_VERSION) +#define CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION +#endif + +#ifndef CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION +#define CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE +#endif + +#ifdef CRYPTOPP_DISABLE_X86ASM // for backwards compatibility: this macro had both meanings +#define CRYPTOPP_DISABLE_ASM +#define CRYPTOPP_DISABLE_SSE2 +#endif + +#if !defined(CRYPTOPP_DISABLE_ASM) && ((defined(_MSC_VER) && defined(_M_IX86)) || (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))) + #define CRYPTOPP_X86_ASM_AVAILABLE + + #if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(CRYPTOPP_MSVC6PP_OR_LATER) || CRYPTOPP_GCC_VERSION >= 30300) + #define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 1 + #else + #define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 0 + #endif + + // SSSE3 was actually introduced in GNU as 2.17, which was released 6/23/2006, but we can't tell what version of binutils is installed. + // GCC 4.1.2 was released on 2/13/2007, so we'll use that as a proxy for the binutils version. + #if !defined(CRYPTOPP_DISABLE_SSSE3) && (_MSC_VER >= 1400 || CRYPTOPP_GCC_VERSION >= 40102) + #define CRYPTOPP_BOOL_SSSE3_ASM_AVAILABLE 1 + #else + #define CRYPTOPP_BOOL_SSSE3_ASM_AVAILABLE 0 + #endif +#endif + +#if !defined(CRYPTOPP_DISABLE_ASM) && defined(_MSC_VER) && defined(_M_X64) + #define CRYPTOPP_X64_MASM_AVAILABLE +#endif + +#if !defined(CRYPTOPP_DISABLE_ASM) && defined(__GNUC__) && defined(__x86_64__) + #define CRYPTOPP_X64_ASM_AVAILABLE +#endif + +#if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(CRYPTOPP_MSVC6PP_OR_LATER) || defined(__SSE2__)) + #define CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 1 +#else + #define CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 0 +#endif + +#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE) + #define CRYPTOPP_BOOL_ALIGN16_ENABLED 1 +#else + #define CRYPTOPP_BOOL_ALIGN16_ENABLED 0 +#endif + +// how to allocate 16-byte aligned memory (for SSE2) +#if defined(CRYPTOPP_MSVC6PP_OR_LATER) + #define CRYPTOPP_MM_MALLOC_AVAILABLE +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) + #define CRYPTOPP_MALLOC_ALIGNMENT_IS_16 +#elif defined(__linux__) || defined(__sun__) || defined(__CYGWIN__) + #define CRYPTOPP_MEMALIGN_AVAILABLE +#else + #define CRYPTOPP_NO_ALIGNED_ALLOC +#endif + +// how to disable inlining +#if defined(_MSC_VER) && _MSC_VER >= 1300 +# define CRYPTOPP_NOINLINE_DOTDOTDOT +# define CRYPTOPP_NOINLINE __declspec(noinline) +#elif defined(__GNUC__) +# define CRYPTOPP_NOINLINE_DOTDOTDOT +# define CRYPTOPP_NOINLINE __attribute__((noinline)) +#else +# define CRYPTOPP_NOINLINE_DOTDOTDOT ... +# define CRYPTOPP_NOINLINE +#endif + +// how to declare class constants +#if (defined(_MSC_VER) && _MSC_VER <= 1300) || defined(__INTEL_COMPILER) +# define CRYPTOPP_CONSTANT(x) enum {x}; +#else +# define CRYPTOPP_CONSTANT(x) static const int x; +#endif + +#if defined(_M_X64) || defined(__x86_64__) + #define CRYPTOPP_BOOL_X64 1 +#else + #define CRYPTOPP_BOOL_X64 0 +#endif + +// see http://predef.sourceforge.net/prearch.html +#if defined(_M_IX86) || defined(__i386__) || defined(__i386) || defined(_X86_) || defined(__I86__) || defined(__INTEL__) + #define CRYPTOPP_BOOL_X86 1 +#else + #define CRYPTOPP_BOOL_X86 0 +#endif + +#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86 || defined(__powerpc__) + #define CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS +#endif + +#define CRYPTOPP_VERSION 560 + +#include "extraversion.h" + +// ***************** determine availability of OS features ******************** + +#ifndef NO_OS_DEPENDENCE + +#if defined(_WIN32) || defined(__CYGWIN__) +#define CRYPTOPP_WIN32_AVAILABLE +#endif + +#if defined(__unix__) || defined(__MACH__) || defined(__NetBSD__) || defined(__sun) +#define CRYPTOPP_UNIX_AVAILABLE +#endif + +#if defined(CRYPTOPP_WIN32_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE) +# define HIGHRES_TIMER_AVAILABLE +#endif + +#ifdef CRYPTOPP_UNIX_AVAILABLE +# define HAS_BERKELEY_STYLE_SOCKETS +#endif + +#ifdef CRYPTOPP_WIN32_AVAILABLE +# define HAS_WINDOWS_STYLE_SOCKETS +#endif + +#if defined(HIGHRES_TIMER_AVAILABLE) && (defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(HAS_WINDOWS_STYLE_SOCKETS)) +# define SOCKETS_AVAILABLE +#endif + +#if defined(HAS_WINDOWS_STYLE_SOCKETS) && (!defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(PREFER_WINDOWS_STYLE_SOCKETS)) +# define USE_WINDOWS_STYLE_SOCKETS +#else +# define USE_BERKELEY_STYLE_SOCKETS +#endif + +#if defined(HIGHRES_TIMER_AVAILABLE) && defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(USE_BERKELEY_STYLE_SOCKETS) +# define WINDOWS_PIPES_AVAILABLE +#endif + +#if defined(CRYPTOPP_WIN32_AVAILABLE) && defined(USE_MS_CRYPTOAPI) +# define NONBLOCKING_RNG_AVAILABLE +# define OS_RNG_AVAILABLE +#endif + +#if defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING) +# define NONBLOCKING_RNG_AVAILABLE +# define BLOCKING_RNG_AVAILABLE +# define OS_RNG_AVAILABLE +# define HAS_PTHREADS +# define THREADS_AVAILABLE +#endif + +#ifdef CRYPTOPP_WIN32_AVAILABLE +# define HAS_WINTHREADS +# define THREADS_AVAILABLE +#endif + +#endif // NO_OS_DEPENDENCE + +// ***************** DLL related ******************** + +#ifdef CRYPTOPP_WIN32_AVAILABLE + +#ifdef CRYPTOPP_EXPORTS +#define CRYPTOPP_IS_DLL +#define CRYPTOPP_DLL __declspec(dllexport) +#elif defined(CRYPTOPP_IMPORTS) +#define CRYPTOPP_IS_DLL +#define CRYPTOPP_DLL __declspec(dllimport) +#else +#define CRYPTOPP_DLL +#endif + +#define CRYPTOPP_API __cdecl + +#else // CRYPTOPP_WIN32_AVAILABLE + +#define CRYPTOPP_DLL +#define CRYPTOPP_API + +#endif // CRYPTOPP_WIN32_AVAILABLE + +#if defined(__MWERKS__) +#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern class CRYPTOPP_DLL +#elif defined(__BORLANDC__) || defined(__SUNPRO_CC) +#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL +#else +#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern template class CRYPTOPP_DLL +#endif + +#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_IMPORTS) +#define CRYPTOPP_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL +#else +#define CRYPTOPP_DLL_TEMPLATE_CLASS CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS +#endif + +#if defined(__MWERKS__) +#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern class +#elif defined(__BORLANDC__) || defined(__SUNPRO_CC) +#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS template class +#else +#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern template class +#endif + +#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_EXPORTS) +#define CRYPTOPP_STATIC_TEMPLATE_CLASS template class +#else +#define CRYPTOPP_STATIC_TEMPLATE_CLASS CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS +#endif + +#endif diff --git a/src-cryptopp/cpu.cpp b/src-cryptopp/cpu.cpp new file mode 100644 index 0000000..3e46804 --- /dev/null +++ b/src-cryptopp/cpu.cpp @@ -0,0 +1,199 @@ +// cpu.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "cpu.h" +#include "misc.h" +#include + +#ifdef __GNUC__ +#include +#include +#endif + +#ifdef CRYPTOPP_MSVC6PP_OR_LATER +#include +#endif + +NAMESPACE_BEGIN(CryptoPP) + +#ifdef CRYPTOPP_X86_ASM_AVAILABLE + +#ifndef _MSC_VER +typedef void (*SigHandler)(int); + +static jmp_buf s_jmpNoCPUID; +static void SigIllHandlerCPUID(int) +{ + longjmp(s_jmpNoCPUID, 1); +} +#endif + +bool CpuId(word32 input, word32 *output) +{ +#ifdef _MSC_VER + __try + { + __asm + { + mov eax, input + cpuid + mov edi, output + mov [edi], eax + mov [edi+4], ebx + mov [edi+8], ecx + mov [edi+12], edx + } + } + __except (1) + { + return false; + } + return true; +#else + SigHandler oldHandler = signal(SIGILL, SigIllHandlerCPUID); + if (oldHandler == SIG_ERR) + return false; + + bool result = true; + if (setjmp(s_jmpNoCPUID)) + result = false; + else + { + __asm__ + ( + // save ebx in case -fPIC is being used +#if CRYPTOPP_BOOL_X86 + "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx" +#else + "pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx" +#endif + : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3]) + : "a" (input) + ); + } + + signal(SIGILL, oldHandler); + return result; +#endif +} + +#ifndef _MSC_VER +static jmp_buf s_jmpNoSSE2; +static void SigIllHandlerSSE2(int) +{ + longjmp(s_jmpNoSSE2, 1); +} +#endif + +#elif _MSC_VER >= 1400 && CRYPTOPP_BOOL_X64 + +bool CpuId(word32 input, word32 *output) +{ + __cpuid((int *)output, input); + return true; +} + +#endif + +#ifdef CRYPTOPP_CPUID_AVAILABLE + +static bool TrySSE2() +{ +#if CRYPTOPP_BOOL_X64 + return true; +#elif defined(_MSC_VER) + __try + { +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE + AS2(por xmm0, xmm0) // executing SSE2 instruction +#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE + __mm128i x = _mm_setzero_si128(); + return _mm_cvtsi128_si32(x) == 0; +#endif + } + __except (1) + { + return false; + } + return true; +#elif defined(__GNUC__) + SigHandler oldHandler = signal(SIGILL, SigIllHandlerSSE2); + if (oldHandler == SIG_ERR) + return false; + + bool result = true; + if (setjmp(s_jmpNoSSE2)) + result = false; + else + { +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE + __asm __volatile ("por %xmm0, %xmm0"); +#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE + __mm128i x = _mm_setzero_si128(); + result = _mm_cvtsi128_si32(x) == 0; +#endif + } + + signal(SIGILL, oldHandler); + return result; +#else + return false; +#endif +} + +bool g_x86DetectionDone = false; +bool g_hasISSE = false, g_hasSSE2 = false, g_hasSSSE3 = false, g_hasMMX = false, g_isP4 = false; +word32 g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE; + +void DetectX86Features() +{ + word32 cpuid[4], cpuid1[4]; + if (!CpuId(0, cpuid)) + return; + if (!CpuId(1, cpuid1)) + return; + + g_hasMMX = (cpuid1[3] & (1 << 23)) != 0; + if ((cpuid1[3] & (1 << 26)) != 0) + g_hasSSE2 = TrySSE2(); + g_hasSSSE3 = g_hasSSE2 && (cpuid1[2] & (1<<9)); + + if ((cpuid1[3] & (1 << 25)) != 0) + g_hasISSE = true; + else + { + word32 cpuid2[4]; + CpuId(0x080000000, cpuid2); + if (cpuid2[0] >= 0x080000001) + { + CpuId(0x080000001, cpuid2); + g_hasISSE = (cpuid2[3] & (1 << 22)) != 0; + } + } + + std::swap(cpuid[2], cpuid[3]); + if (memcmp(cpuid+1, "GenuineIntel", 12) == 0) + { + g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf; + g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1); + } + else if (memcmp(cpuid+1, "AuthenticAMD", 12) == 0) + { + CpuId(0x80000005, cpuid); + g_cacheLineSize = GETBYTE(cpuid[2], 0); + } + + if (!g_cacheLineSize) + g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE; + + g_x86DetectionDone = true; +} + +#endif + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/cpu.h b/src-cryptopp/cpu.h new file mode 100644 index 0000000..7f01dad --- /dev/null +++ b/src-cryptopp/cpu.h @@ -0,0 +1,263 @@ +#ifndef CRYPTOPP_CPU_H +#define CRYPTOPP_CPU_H + +#ifdef CRYPTOPP_GENERATE_X64_MASM + +#define CRYPTOPP_X86_ASM_AVAILABLE +#define CRYPTOPP_BOOL_X64 1 +#define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 1 +#define NAMESPACE_END + +#else + +#include "config.h" + +#ifdef CRYPTOPP_MSVC6PP_OR_LATER + #include +#endif + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || (_MSC_VER >= 1400 && CRYPTOPP_BOOL_X64) + +#define CRYPTOPP_CPUID_AVAILABLE + +// these should not be used directly +extern CRYPTOPP_DLL bool g_x86DetectionDone; +extern CRYPTOPP_DLL bool g_hasSSE2; +extern CRYPTOPP_DLL bool g_hasISSE; +extern CRYPTOPP_DLL bool g_hasMMX; +extern CRYPTOPP_DLL bool g_hasSSSE3; +extern CRYPTOPP_DLL bool g_isP4; +extern CRYPTOPP_DLL word32 g_cacheLineSize; +CRYPTOPP_DLL void CRYPTOPP_API DetectX86Features(); + +CRYPTOPP_DLL bool CRYPTOPP_API CpuId(word32 input, word32 *output); + +#if CRYPTOPP_BOOL_X64 +inline bool HasSSE2() {return true;} +inline bool HasISSE() {return true;} +inline bool HasMMX() {return true;} +#else + +inline bool HasSSE2() +{ + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasSSE2; +} + +inline bool HasISSE() +{ + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasISSE; +} + +inline bool HasMMX() +{ + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasMMX; +} + +#endif + +inline bool HasSSSE3() +{ + if (!g_x86DetectionDone) + DetectX86Features(); + return g_hasSSSE3; +} + +inline bool IsP4() +{ + if (!g_x86DetectionDone) + DetectX86Features(); + return g_isP4; +} + +inline int GetCacheLineSize() +{ + if (!g_x86DetectionDone) + DetectX86Features(); + return g_cacheLineSize; +} + +#else + +inline int GetCacheLineSize() +{ + return CRYPTOPP_L1_CACHE_LINE_SIZE; +} + +inline bool HasSSSE3() {return false;} +inline bool IsP4() {return false;} + +// assume MMX and SSE2 if intrinsics are enabled +#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_X64 +inline bool HasSSE2() {return true;} +inline bool HasISSE() {return true;} +inline bool HasMMX() {return true;} +#else +inline bool HasSSE2() {return false;} +inline bool HasISSE() {return false;} +inline bool HasMMX() {return false;} +#endif + +#endif // #ifdef CRYPTOPP_X86_ASM_AVAILABLE || _MSC_VER >= 1400 + +#endif + +#ifdef CRYPTOPP_GENERATE_X64_MASM + #define AS1(x) x*newline* + #define AS2(x, y) x, y*newline* + #define AS3(x, y, z) x, y, z*newline* + #define ASS(x, y, a, b, c, d) x, y, a*64+b*16+c*4+d*newline* + #define ASL(x) label##x:*newline* + #define ASJ(x, y, z) x label##y*newline* + #define ASC(x, y) x label##y*newline* + #define AS_HEX(y) 0##y##h +#elif defined(__GNUC__) + // define these in two steps to allow arguments to be expanded + #define GNU_AS1(x) #x ";" + #define GNU_AS2(x, y) #x ", " #y ";" + #define GNU_AS3(x, y, z) #x ", " #y ", " #z ";" + #define GNU_ASL(x) "\n" #x ":" + #define GNU_ASJ(x, y, z) #x " " #y #z ";" + #define AS1(x) GNU_AS1(x) + #define AS2(x, y) GNU_AS2(x, y) + #define AS3(x, y, z) GNU_AS3(x, y, z) + #define ASS(x, y, a, b, c, d) #x ", " #y ", " #a "*64+" #b "*16+" #c "*4+" #d ";" + #define ASL(x) GNU_ASL(x) + #define ASJ(x, y, z) GNU_ASJ(x, y, z) + #define ASC(x, y) #x " " #y ";" + #define CRYPTOPP_NAKED + #define AS_HEX(y) 0x##y +#else + #define AS1(x) __asm {x} + #define AS2(x, y) __asm {x, y} + #define AS3(x, y, z) __asm {x, y, z} + #define ASS(x, y, a, b, c, d) __asm {x, y, _MM_SHUFFLE(a, b, c, d)} + #define ASL(x) __asm {label##x:} + #define ASJ(x, y, z) __asm {x label##y} + #define ASC(x, y) __asm {x label##y} + #define CRYPTOPP_NAKED __declspec(naked) + #define AS_HEX(y) 0x##y +#endif + +#define IF0(y) +#define IF1(y) y + +#ifdef CRYPTOPP_GENERATE_X64_MASM +#define ASM_MOD(x, y) ((x) MOD (y)) +#define XMMWORD_PTR XMMWORD PTR +#else +// GNU assembler doesn't seem to have mod operator +#define ASM_MOD(x, y) ((x)-((x)/(y))*(y)) +// GAS 2.15 doesn't support XMMWORD PTR. it seems necessary only for MASM +#define XMMWORD_PTR +#endif + +#if CRYPTOPP_BOOL_X86 + #define AS_REG_1 ecx + #define AS_REG_2 edx + #define AS_REG_3 esi + #define AS_REG_4 edi + #define AS_REG_5 eax + #define AS_REG_6 ebx + #define AS_REG_7 ebp + #define AS_REG_1d ecx + #define AS_REG_2d edx + #define AS_REG_3d esi + #define AS_REG_4d edi + #define AS_REG_5d eax + #define AS_REG_6d ebx + #define AS_REG_7d ebp + #define WORD_SZ 4 + #define WORD_REG(x) e##x + #define WORD_PTR DWORD PTR + #define AS_PUSH_IF86(x) AS1(push e##x) + #define AS_POP_IF86(x) AS1(pop e##x) + #define AS_JCXZ jecxz +#elif CRYPTOPP_BOOL_X64 + #ifdef CRYPTOPP_GENERATE_X64_MASM + #define AS_REG_1 rcx + #define AS_REG_2 rdx + #define AS_REG_3 r8 + #define AS_REG_4 r9 + #define AS_REG_5 rax + #define AS_REG_6 r10 + #define AS_REG_7 r11 + #define AS_REG_1d ecx + #define AS_REG_2d edx + #define AS_REG_3d r8d + #define AS_REG_4d r9d + #define AS_REG_5d eax + #define AS_REG_6d r10d + #define AS_REG_7d r11d + #else + #define AS_REG_1 rdi + #define AS_REG_2 rsi + #define AS_REG_3 rdx + #define AS_REG_4 rcx + #define AS_REG_5 r8 + #define AS_REG_6 r9 + #define AS_REG_7 r10 + #define AS_REG_1d edi + #define AS_REG_2d esi + #define AS_REG_3d edx + #define AS_REG_4d ecx + #define AS_REG_5d r8d + #define AS_REG_6d r9d + #define AS_REG_7d r10d + #endif + #define WORD_SZ 8 + #define WORD_REG(x) r##x + #define WORD_PTR QWORD PTR + #define AS_PUSH_IF86(x) + #define AS_POP_IF86(x) + #define AS_JCXZ jrcxz +#endif + +// helper macro for stream cipher output +#define AS_XMM_OUTPUT4(labelPrefix, inputPtr, outputPtr, x0, x1, x2, x3, t, p0, p1, p2, p3, increment)\ + AS2( test inputPtr, inputPtr)\ + ASC( jz, labelPrefix##3)\ + AS2( test inputPtr, 15)\ + ASC( jnz, labelPrefix##7)\ + AS2( pxor xmm##x0, [inputPtr+p0*16])\ + AS2( pxor xmm##x1, [inputPtr+p1*16])\ + AS2( pxor xmm##x2, [inputPtr+p2*16])\ + AS2( pxor xmm##x3, [inputPtr+p3*16])\ + AS2( add inputPtr, increment*16)\ + ASC( jmp, labelPrefix##3)\ + ASL(labelPrefix##7)\ + AS2( movdqu xmm##t, [inputPtr+p0*16])\ + AS2( pxor xmm##x0, xmm##t)\ + AS2( movdqu xmm##t, [inputPtr+p1*16])\ + AS2( pxor xmm##x1, xmm##t)\ + AS2( movdqu xmm##t, [inputPtr+p2*16])\ + AS2( pxor xmm##x2, xmm##t)\ + AS2( movdqu xmm##t, [inputPtr+p3*16])\ + AS2( pxor xmm##x3, xmm##t)\ + AS2( add inputPtr, increment*16)\ + ASL(labelPrefix##3)\ + AS2( test outputPtr, 15)\ + ASC( jnz, labelPrefix##8)\ + AS2( movdqa [outputPtr+p0*16], xmm##x0)\ + AS2( movdqa [outputPtr+p1*16], xmm##x1)\ + AS2( movdqa [outputPtr+p2*16], xmm##x2)\ + AS2( movdqa [outputPtr+p3*16], xmm##x3)\ + ASC( jmp, labelPrefix##9)\ + ASL(labelPrefix##8)\ + AS2( movdqu [outputPtr+p0*16], xmm##x0)\ + AS2( movdqu [outputPtr+p1*16], xmm##x1)\ + AS2( movdqu [outputPtr+p2*16], xmm##x2)\ + AS2( movdqu [outputPtr+p3*16], xmm##x3)\ + ASL(labelPrefix##9)\ + AS2( add outputPtr, increment*16) + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/cryptdll.dsp b/src-cryptopp/cryptdll.dsp new file mode 100644 index 0000000..aad342e --- /dev/null +++ b/src-cryptopp/cryptdll.dsp @@ -0,0 +1,594 @@ +# Microsoft Developer Studio Project File - Name="cryptdll" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=cryptdll - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "cryptdll.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "cryptdll.mak" CFG="cryptdll - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "cryptdll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "cryptdll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "cryptdll - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "cryptdll___Win32_Release" +# PROP BASE Intermediate_Dir "cryptdll___Win32_Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "DLL_Release" +# PROP Intermediate_Dir "DLL_Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CRYPTDLL_EXPORTS" /YX /FD /c +# ADD CPP /nologo /G5 /MT /W3 /GR /GX /Zi /O1 /Ob2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CRYPTOPP_EXPORTS" /D CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2=1 /D "USE_PRECOMPILED_HEADERS" /Yu"pch.h" /FD /Zm200 /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 advapi32.lib /nologo /base:"0x42900000" /dll /map /debug /machine:I386 /out:"DLL_Release/cryptopp.dll" /opt:ref +# SUBTRACT LINK32 /pdb:none +# Begin Custom Build +OutDir=.\DLL_Release +TargetPath=.\DLL_Release\cryptopp.dll +InputPath=.\DLL_Release\cryptopp.dll +SOURCE="$(InputPath)" + +"$(OutDir)\cryptopp.mac.done" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + CTRelease\cryptest mac_dll $(TargetPath) + echo mac done > $(OutDir)\cryptopp.mac.done + +# End Custom Build + +!ELSEIF "$(CFG)" == "cryptdll - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "cryptdll___Win32_Debug" +# PROP BASE Intermediate_Dir "cryptdll___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "DLL_Debug" +# PROP Intermediate_Dir "DLL_Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CRYPTDLL_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /G5 /MTd /W3 /Gm /GR /GX /Zi /Oi /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CRYPTOPP_EXPORTS" /D CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2=1 /D "USE_PRECOMPILED_HEADERS" /Yu"pch.h" /FD /GZ /Zm200 /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 advapi32.lib /nologo /base:"0x42900000" /dll /incremental:no /debug /machine:I386 /out:"DLL_Debug/cryptopp.dll" /opt:ref +# SUBTRACT LINK32 /pdb:none +# Begin Custom Build +OutDir=.\DLL_Debug +TargetPath=.\DLL_Debug\cryptopp.dll +InputPath=.\DLL_Debug\cryptopp.dll +SOURCE="$(InputPath)" + +"$(OutDir)\cryptopp.mac.done" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + CTDebug\cryptest mac_dll $(TargetPath) + echo mac done > $(OutDir)\cryptopp.mac.done + +# End Custom Build + +!ENDIF + +# Begin Target + +# Name "cryptdll - Win32 Release" +# Name "cryptdll - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\algebra.cpp +# End Source File +# Begin Source File + +SOURCE=.\algparam.cpp +# End Source File +# Begin Source File + +SOURCE=.\asn.cpp +# End Source File +# Begin Source File + +SOURCE=.\authenc.cpp +# End Source File +# Begin Source File + +SOURCE=.\basecode.cpp +# End Source File +# Begin Source File + +SOURCE=.\cbcmac.cpp +# End Source File +# Begin Source File + +SOURCE=.\ccm.cpp +# End Source File +# Begin Source File + +SOURCE=.\channels.cpp +# End Source File +# Begin Source File + +SOURCE=.\cmac.cpp +# End Source File +# Begin Source File + +SOURCE=.\cpu.cpp +# End Source File +# Begin Source File + +SOURCE=.\cryptlib.cpp +# End Source File +# Begin Source File + +SOURCE=.\des.cpp +# End Source File +# Begin Source File + +SOURCE=.\dessp.cpp +# End Source File +# Begin Source File + +SOURCE=.\dh.cpp +# End Source File +# Begin Source File + +SOURCE=.\dll.cpp +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=.\dsa.cpp +# End Source File +# Begin Source File + +SOURCE=.\ec2n.cpp +# End Source File +# Begin Source File + +SOURCE=.\eccrypto.cpp +# End Source File +# Begin Source File + +SOURCE=.\ecp.cpp +# End Source File +# Begin Source File + +SOURCE=.\emsa2.cpp +# End Source File +# Begin Source File + +SOURCE=.\eprecomp.cpp +# End Source File +# Begin Source File + +SOURCE=.\files.cpp +# End Source File +# Begin Source File + +SOURCE=.\filters.cpp +# End Source File +# Begin Source File + +SOURCE=.\fips140.cpp +# End Source File +# Begin Source File + +SOURCE=.\fipstest.cpp +# End Source File +# Begin Source File + +SOURCE=.\gcm.cpp +# End Source File +# Begin Source File + +SOURCE=.\gf2n.cpp +# End Source File +# Begin Source File + +SOURCE=.\gfpcrypt.cpp +# End Source File +# Begin Source File + +SOURCE=.\hex.cpp +# End Source File +# Begin Source File + +SOURCE=.\hmac.cpp +# End Source File +# Begin Source File + +SOURCE=.\hrtimer.cpp +# End Source File +# Begin Source File + +SOURCE=.\integer.cpp +# End Source File +# Begin Source File + +SOURCE=.\iterhash.cpp +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=.\misc.cpp +# End Source File +# Begin Source File + +SOURCE=.\modes.cpp +# End Source File +# Begin Source File + +SOURCE=.\mqueue.cpp +# End Source File +# Begin Source File + +SOURCE=.\nbtheory.cpp +# End Source File +# Begin Source File + +SOURCE=.\oaep.cpp +# End Source File +# Begin Source File + +SOURCE=.\osrng.cpp +# End Source File +# Begin Source File + +SOURCE=.\pch.cpp +# ADD CPP /Yc"pch.h" +# End Source File +# Begin Source File + +SOURCE=.\pkcspad.cpp +# End Source File +# Begin Source File + +SOURCE=.\pssr.cpp +# End Source File +# Begin Source File + +SOURCE=.\pubkey.cpp +# End Source File +# Begin Source File + +SOURCE=.\queue.cpp +# End Source File +# Begin Source File + +SOURCE=.\randpool.cpp +# End Source File +# Begin Source File + +SOURCE=.\rdtables.cpp +# End Source File +# Begin Source File + +SOURCE=.\rijndael.cpp +# End Source File +# Begin Source File + +SOURCE=.\rng.cpp +# End Source File +# Begin Source File + +SOURCE=.\rsa.cpp +# End Source File +# Begin Source File + +SOURCE=.\rw.cpp +# End Source File +# Begin Source File + +SOURCE=.\sha.cpp +# End Source File +# Begin Source File + +SOURCE=.\simple.cpp +# End Source File +# Begin Source File + +SOURCE=.\skipjack.cpp +# End Source File +# Begin Source File + +SOURCE=.\strciphr.cpp +# End Source File +# Begin Source File + +SOURCE=.\trdlocal.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter ".h" +# Begin Source File + +SOURCE=.\aes.h +# End Source File +# Begin Source File + +SOURCE=.\algebra.h +# End Source File +# Begin Source File + +SOURCE=.\algparam.h +# End Source File +# Begin Source File + +SOURCE=.\argnames.h +# End Source File +# Begin Source File + +SOURCE=.\asn.h +# End Source File +# Begin Source File + +SOURCE=.\authenc.h +# End Source File +# Begin Source File + +SOURCE=.\basecode.h +# End Source File +# Begin Source File + +SOURCE=.\cbcmac.h +# End Source File +# Begin Source File + +SOURCE=.\ccm.h +# End Source File +# Begin Source File + +SOURCE=.\channels.h +# End Source File +# Begin Source File + +SOURCE=.\cmac.h +# End Source File +# Begin Source File + +SOURCE=.\config.h +# End Source File +# Begin Source File + +SOURCE=.\cryptlib.h +# End Source File +# Begin Source File + +SOURCE=.\des.h +# End Source File +# Begin Source File + +SOURCE=.\dh.h +# End Source File +# Begin Source File + +SOURCE=.\dll.h +# End Source File +# Begin Source File + +SOURCE=.\dsa.h +# End Source File +# Begin Source File + +SOURCE=.\ec2n.h +# End Source File +# Begin Source File + +SOURCE=.\eccrypto.h +# End Source File +# Begin Source File + +SOURCE=.\ecp.h +# End Source File +# Begin Source File + +SOURCE=.\eprecomp.h +# End Source File +# Begin Source File + +SOURCE=.\files.h +# End Source File +# Begin Source File + +SOURCE=.\filters.h +# End Source File +# Begin Source File + +SOURCE=.\fips140.h +# End Source File +# Begin Source File + +SOURCE=.\fltrimpl.h +# End Source File +# Begin Source File + +SOURCE=.\gcm.h +# End Source File +# Begin Source File + +SOURCE=.\gf2n.h +# End Source File +# Begin Source File + +SOURCE=.\gfpcrypt.h +# End Source File +# Begin Source File + +SOURCE=.\hex.h +# End Source File +# Begin Source File + +SOURCE=.\hmac.h +# End Source File +# Begin Source File + +SOURCE=.\integer.h +# End Source File +# Begin Source File + +SOURCE=.\iterhash.h +# End Source File +# Begin Source File + +SOURCE=.\mdc.h +# End Source File +# Begin Source File + +SOURCE=.\misc.h +# End Source File +# Begin Source File + +SOURCE=.\modarith.h +# End Source File +# Begin Source File + +SOURCE=.\modes.h +# End Source File +# Begin Source File + +SOURCE=.\modexppc.h +# End Source File +# Begin Source File + +SOURCE=.\mqueue.h +# End Source File +# Begin Source File + +SOURCE=.\mqv.h +# End Source File +# Begin Source File + +SOURCE=.\nbtheory.h +# End Source File +# Begin Source File + +SOURCE=.\oaep.h +# End Source File +# Begin Source File + +SOURCE=.\oids.h +# End Source File +# Begin Source File + +SOURCE=.\osrng.h +# End Source File +# Begin Source File + +SOURCE=.\pch.h +# End Source File +# Begin Source File + +SOURCE=.\pkcspad.h +# End Source File +# Begin Source File + +SOURCE=.\pubkey.h +# End Source File +# Begin Source File + +SOURCE=.\queue.h +# End Source File +# Begin Source File + +SOURCE=.\randpool.h +# End Source File +# Begin Source File + +SOURCE=.\rijndael.h +# End Source File +# Begin Source File + +SOURCE=.\rng.h +# End Source File +# Begin Source File + +SOURCE=.\rsa.h +# End Source File +# Begin Source File + +SOURCE=.\secblock.h +# End Source File +# Begin Source File + +SOURCE=.\seckey.h +# End Source File +# Begin Source File + +SOURCE=.\sha.h +# End Source File +# Begin Source File + +SOURCE=.\simple.h +# End Source File +# Begin Source File + +SOURCE=.\skipjack.h +# End Source File +# Begin Source File + +SOURCE=.\smartptr.h +# End Source File +# Begin Source File + +SOURCE=.\stdcpp.h +# End Source File +# Begin Source File + +SOURCE=.\strciphr.h +# End Source File +# Begin Source File + +SOURCE=.\trdlocal.h +# End Source File +# Begin Source File + +SOURCE=.\words.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\cryptopp.rc +# End Source File +# End Target +# End Project diff --git a/src-cryptopp/cryptdll.vcproj b/src-cryptopp/cryptdll.vcproj new file mode 100644 index 0000000..5e7d799 --- /dev/null +++ b/src-cryptopp/cryptdll.vcproj @@ -0,0 +1,2694 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src-cryptopp/cryptest.dsp b/src-cryptopp/cryptest.dsp new file mode 100644 index 0000000..a981642 --- /dev/null +++ b/src-cryptopp/cryptest.dsp @@ -0,0 +1,207 @@ +# Microsoft Developer Studio Project File - Name="cryptest" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=cryptest - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "cryptest.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "cryptest.mak" CFG="cryptest - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "cryptest - Win32 DLL-Import Release" (based on "Win32 (x86) Console Application") +!MESSAGE "cryptest - Win32 DLL-Import Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "cryptest - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "cryptest - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "cryptest - Win32 DLL-Import Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "cryptest___Win32_FIPS_140_Release" +# PROP BASE Intermediate_Dir "cryptest___Win32_FIPS_140_Release" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "CT_DLL_Import_Release" +# PROP Intermediate_Dir "CT_DLL_Import_Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /G5 /Gz /MT /W3 /GX /Zi /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /Zm200 /c +# ADD CPP /nologo /G5 /Gz /MT /W3 /GR /GX /Zi /O1 /Ob2 /D "NDEBUG" /D "CRYPTOPP_IMPORTS" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /Zm400 /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /OPT:NOWIN98 +# ADD LINK32 Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /out:"DLL_Release/cryptest.exe" /libpath:"DLL_Release" /OPT:NOWIN98 /OPT:REF /OPT:ICF +# SUBTRACT LINK32 /pdb:none /incremental:yes +# Begin Special Build Tool +SOURCE="$(InputPath)" +PreLink_Cmds=echo This configuration requires cryptopp.dll. echo You can build it yourself using the cryptdll project, or echo obtain a pre-built, FIPS 140-2 validated DLL. If you build it yourself echo the resulting DLL will not be considered FIPS validated echo unless it undergoes FIPS validation. +# End Special Build Tool + +!ELSEIF "$(CFG)" == "cryptest - Win32 DLL-Import Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "cryptest___Win32_FIPS_140_Debug" +# PROP BASE Intermediate_Dir "cryptest___Win32_FIPS_140_Debug" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "CT_DLL_Import_Debug" +# PROP Intermediate_Dir "CT_DLL_Import_Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /Zm200 /c +# ADD CPP /nologo /G5 /Gz /MTd /W3 /GR /GX /Zi /Oi /D "_DEBUG" /D "CRYPTOPP_IMPORTS" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /Zm400 /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /OPT:NOWIN98 +# ADD LINK32 Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /out:"DLL_Debug/cryptest.exe" /pdbtype:sept /libpath:"DLL_Debug" /OPT:NOWIN98 +# Begin Special Build Tool +SOURCE="$(InputPath)" +PreLink_Cmds=echo This configuration requires cryptopp.dll. echo You can build it yourself using the cryptdll project, or echo obtain a pre-built, FIPS 140-2 validated DLL. If you build it yourself echo the resulting DLL will not be considered FIPS validated echo unless it undergoes FIPS validation. +# End Special Build Tool + +!ELSEIF "$(CFG)" == "cryptest - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "cryptes0" +# PROP BASE Intermediate_Dir "cryptes0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "CTRelease" +# PROP Intermediate_Dir "CTRelease" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GR /GX /Zi /O1 /Ob2 /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "WIN32" /YX /FD /Zm400 /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 advapi32.lib Ws2_32.lib /nologo /subsystem:console /map /debug /machine:I386 /OPT:NOWIN98 /OPT:REF /OPT:ICF +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "cryptest - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "cryptes1" +# PROP BASE Intermediate_Dir "cryptes1" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "CTDebug" +# PROP Intermediate_Dir "CTDebug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /GR /GX /Zi /Oi /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "WIN32" /YX /FD /Zm400 /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 advapi32.lib Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /OPT:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "cryptest - Win32 DLL-Import Release" +# Name "cryptest - Win32 DLL-Import Debug" +# Name "cryptest - Win32 Release" +# Name "cryptest - Win32 Debug" +# Begin Group "Source Code" + +# PROP Default_Filter ".cpp;.h" +# Begin Source File + +SOURCE=.\adhoc.cpp +# End Source File +# Begin Source File + +SOURCE=.\bench.cpp +# End Source File +# Begin Source File + +SOURCE=.\bench.h +# End Source File +# Begin Source File + +SOURCE=.\bench2.cpp +# End Source File +# Begin Source File + +SOURCE=.\datatest.cpp +# End Source File +# Begin Source File + +SOURCE=.\dlltest.cpp +# End Source File +# Begin Source File + +SOURCE=.\fipsalgt.cpp +# End Source File +# Begin Source File + +SOURCE=.\regtest.cpp +# End Source File +# Begin Source File + +SOURCE=.\test.cpp +# End Source File +# Begin Source File + +SOURCE=.\validat1.cpp +# End Source File +# Begin Source File + +SOURCE=.\validat2.cpp +# End Source File +# Begin Source File + +SOURCE=.\validat3.cpp +# End Source File +# Begin Source File + +SOURCE=.\validate.h +# End Source File +# End Group +# End Target +# End Project diff --git a/src-cryptopp/cryptest.dsw b/src-cryptopp/cryptest.dsw new file mode 100644 index 0000000..a2f1411 --- /dev/null +++ b/src-cryptopp/cryptest.dsw @@ -0,0 +1,74 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "cryptdll"=.\cryptdll.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name cryptest + End Project Dependency +}}} + +############################################################################### + +Project: "cryptest"=.\cryptest.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name cryptlib + End Project Dependency +}}} + +############################################################################### + +Project: "cryptlib"=.\cryptlib.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "dlltest"=.\dlltest.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name cryptdll + End Project Dependency +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/src-cryptopp/cryptest.sln b/src-cryptopp/cryptest.sln new file mode 100644 index 0000000..dea1776 --- /dev/null +++ b/src-cryptopp/cryptest.sln @@ -0,0 +1,100 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cryptdll", "cryptdll.vcproj", "{EBD86293-69A9-456B-B814-916E12AA9BBF}" + ProjectSection(ProjectDependencies) = postProject + {9EAFA456-89B4-4879-AD4F-C2C341184CF5} = {9EAFA456-89B4-4879-AD4F-C2C341184CF5} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cryptest", "cryptest.vcproj", "{9EAFA456-89B4-4879-AD4F-C2C341184CF5}" + ProjectSection(ProjectDependencies) = postProject + {3423EC9A-52E4-4A4D-9753-EDEBC38785EF} = {3423EC9A-52E4-4A4D-9753-EDEBC38785EF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cryptlib", "cryptlib.vcproj", "{3423EC9A-52E4-4A4D-9753-EDEBC38785EF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dlltest", "dlltest.vcproj", "{A7483CE8-2784-46CE-8CB8-8C0C1D27E232}" + ProjectSection(ProjectDependencies) = postProject + {EBD86293-69A9-456B-B814-916E12AA9BBF} = {EBD86293-69A9-456B-B814-916E12AA9BBF} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + DLL-Import Debug|Win32 = DLL-Import Debug|Win32 + DLL-Import Debug|x64 = DLL-Import Debug|x64 + DLL-Import Release|Win32 = DLL-Import Release|Win32 + DLL-Import Release|x64 = DLL-Import Release|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EBD86293-69A9-456B-B814-916E12AA9BBF}.Debug|Win32.ActiveCfg = Debug|Win32 + {EBD86293-69A9-456B-B814-916E12AA9BBF}.Debug|Win32.Build.0 = Debug|Win32 + {EBD86293-69A9-456B-B814-916E12AA9BBF}.Debug|x64.ActiveCfg = Debug|x64 + {EBD86293-69A9-456B-B814-916E12AA9BBF}.Debug|x64.Build.0 = Debug|x64 + {EBD86293-69A9-456B-B814-916E12AA9BBF}.DLL-Import Debug|Win32.ActiveCfg = Debug|Win32 + {EBD86293-69A9-456B-B814-916E12AA9BBF}.DLL-Import Debug|Win32.Build.0 = Debug|Win32 + {EBD86293-69A9-456B-B814-916E12AA9BBF}.DLL-Import Debug|x64.ActiveCfg = Debug|x64 + {EBD86293-69A9-456B-B814-916E12AA9BBF}.DLL-Import Debug|x64.Build.0 = Debug|x64 + {EBD86293-69A9-456B-B814-916E12AA9BBF}.DLL-Import Release|Win32.ActiveCfg = Release|Win32 + {EBD86293-69A9-456B-B814-916E12AA9BBF}.DLL-Import Release|Win32.Build.0 = Release|Win32 + {EBD86293-69A9-456B-B814-916E12AA9BBF}.DLL-Import Release|x64.ActiveCfg = Release|x64 + {EBD86293-69A9-456B-B814-916E12AA9BBF}.DLL-Import Release|x64.Build.0 = Release|x64 + {EBD86293-69A9-456B-B814-916E12AA9BBF}.Release|Win32.ActiveCfg = Release|Win32 + {EBD86293-69A9-456B-B814-916E12AA9BBF}.Release|Win32.Build.0 = Release|Win32 + {EBD86293-69A9-456B-B814-916E12AA9BBF}.Release|x64.ActiveCfg = Release|x64 + {EBD86293-69A9-456B-B814-916E12AA9BBF}.Release|x64.Build.0 = Release|x64 + {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.Debug|Win32.ActiveCfg = Debug|Win32 + {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.Debug|Win32.Build.0 = Debug|Win32 + {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.Debug|x64.ActiveCfg = Debug|x64 + {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.Debug|x64.Build.0 = Debug|x64 + {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.DLL-Import Debug|Win32.ActiveCfg = DLL-Import Debug|Win32 + {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.DLL-Import Debug|Win32.Build.0 = DLL-Import Debug|Win32 + {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.DLL-Import Debug|x64.ActiveCfg = DLL-Import Debug|x64 + {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.DLL-Import Debug|x64.Build.0 = DLL-Import Debug|x64 + {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.DLL-Import Release|Win32.ActiveCfg = DLL-Import Release|Win32 + {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.DLL-Import Release|Win32.Build.0 = DLL-Import Release|Win32 + {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.DLL-Import Release|x64.ActiveCfg = DLL-Import Release|x64 + {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.DLL-Import Release|x64.Build.0 = DLL-Import Release|x64 + {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.Release|Win32.ActiveCfg = Release|Win32 + {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.Release|Win32.Build.0 = Release|Win32 + {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.Release|x64.ActiveCfg = Release|x64 + {9EAFA456-89B4-4879-AD4F-C2C341184CF5}.Release|x64.Build.0 = Release|x64 + {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.Debug|Win32.ActiveCfg = Debug|Win32 + {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.Debug|Win32.Build.0 = Debug|Win32 + {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.Debug|x64.ActiveCfg = Debug|x64 + {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.Debug|x64.Build.0 = Debug|x64 + {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.DLL-Import Debug|Win32.ActiveCfg = DLL-Import Debug|Win32 + {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.DLL-Import Debug|Win32.Build.0 = DLL-Import Debug|Win32 + {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.DLL-Import Debug|x64.ActiveCfg = DLL-Import Debug|x64 + {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.DLL-Import Debug|x64.Build.0 = DLL-Import Debug|x64 + {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.DLL-Import Release|Win32.ActiveCfg = DLL-Import Release|Win32 + {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.DLL-Import Release|Win32.Build.0 = DLL-Import Release|Win32 + {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.DLL-Import Release|x64.ActiveCfg = DLL-Import Release|x64 + {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.DLL-Import Release|x64.Build.0 = DLL-Import Release|x64 + {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.Release|Win32.ActiveCfg = Release|Win32 + {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.Release|Win32.Build.0 = Release|Win32 + {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.Release|x64.ActiveCfg = Release|x64 + {3423EC9A-52E4-4A4D-9753-EDEBC38785EF}.Release|x64.Build.0 = Release|x64 + {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.Debug|Win32.ActiveCfg = Debug|Win32 + {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.Debug|Win32.Build.0 = Debug|Win32 + {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.Debug|x64.ActiveCfg = Debug|x64 + {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.Debug|x64.Build.0 = Debug|x64 + {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.DLL-Import Debug|Win32.ActiveCfg = Debug|Win32 + {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.DLL-Import Debug|Win32.Build.0 = Debug|Win32 + {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.DLL-Import Debug|x64.ActiveCfg = Debug|x64 + {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.DLL-Import Debug|x64.Build.0 = Debug|x64 + {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.DLL-Import Release|Win32.ActiveCfg = Release|Win32 + {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.DLL-Import Release|Win32.Build.0 = Release|Win32 + {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.DLL-Import Release|x64.ActiveCfg = Release|x64 + {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.DLL-Import Release|x64.Build.0 = Release|x64 + {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.Release|Win32.ActiveCfg = Release|Win32 + {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.Release|Win32.Build.0 = Release|Win32 + {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.Release|x64.ActiveCfg = Release|x64 + {A7483CE8-2784-46CE-8CB8-8C0C1D27E232}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src-cryptopp/cryptest.vcproj b/src-cryptopp/cryptest.vcproj new file mode 100644 index 0000000..1d39fca --- /dev/null +++ b/src-cryptopp/cryptest.vcproj @@ -0,0 +1,1850 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src-cryptopp/cryptest_bds.bdsgroup b/src-cryptopp/cryptest_bds.bdsgroup new file mode 100644 index 0000000..bbb081a --- /dev/null +++ b/src-cryptopp/cryptest_bds.bdsgroup @@ -0,0 +1,22 @@ + + + + + + + + + + + cryptest_bds.bdsproj + cryptlib_bds.bdsproj + cryptest_bds.exe cryptlib_bds.lib + + + + + + + + diff --git a/src-cryptopp/cryptest_bds.bdsproj b/src-cryptopp/cryptest_bds.bdsproj new file mode 100644 index 0000000..9086d30 --- /dev/null +++ b/src-cryptopp/cryptest_bds.bdsproj @@ -0,0 +1,267 @@ + + + + + + + + + + + + cryptest_bds.bpf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + False + False + 1 + 0 + 0 + 0 + False + False + False + False + False + 1033 + 1252 + + + + + 1.0.0.0 + + + + + + 1.0.0.0 + + + + + + + v + + True + . + D:\cvs\c5\Debug_Build\cryptest_bds.exe + + + + + False + + False + + True + False + + + Delphi 1.0 Compatibility Components + Borland C++Builder Internet Explorer 5 Components Package + + + + + + + + + + + diff --git a/src-cryptopp/cryptest_bds.bpf b/src-cryptopp/cryptest_bds.bpf new file mode 100644 index 0000000..c30200b --- /dev/null +++ b/src-cryptopp/cryptest_bds.bpf @@ -0,0 +1,5 @@ +This file is used by the project manager only and should be treated like the project file + +To add a file to this project use the Project menu 'Add to Project' + +main \ No newline at end of file diff --git a/src-cryptopp/cryptlib.cpp b/src-cryptopp/cryptlib.cpp new file mode 100644 index 0000000..41daf6b --- /dev/null +++ b/src-cryptopp/cryptlib.cpp @@ -0,0 +1,835 @@ +// cryptlib.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "cryptlib.h" +#include "misc.h" +#include "filters.h" +#include "algparam.h" +#include "fips140.h" +#include "argnames.h" +#include "fltrimpl.h" +#include "trdlocal.h" +#include "osrng.h" + +#include + +#include "config.h" + +#include "extraversion.h" +const char *cryptopp_extra_version = CRYPTOPP_EXTRA_VERSION; + +NAMESPACE_BEGIN(CryptoPP) + +const char *const cryptopp_extra_version = CRYPTOPP_EXTRA_VERSION; + +CRYPTOPP_COMPILE_ASSERT(sizeof(byte) == 1); +CRYPTOPP_COMPILE_ASSERT(sizeof(word16) == 2); +CRYPTOPP_COMPILE_ASSERT(sizeof(word32) == 4); +CRYPTOPP_COMPILE_ASSERT(sizeof(word64) == 8); +#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE +CRYPTOPP_COMPILE_ASSERT(sizeof(dword) == 2*sizeof(word)); +#endif + +const std::string DEFAULT_CHANNEL; +const std::string AAD_CHANNEL = "AAD"; +const std::string &BufferedTransformation::NULL_CHANNEL = DEFAULT_CHANNEL; + +class NullNameValuePairs : public NameValuePairs +{ +public: + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const {return false;} +}; + +simple_ptr s_pNullNameValuePairs(new NullNameValuePairs); +const NameValuePairs &g_nullNameValuePairs = *s_pNullNameValuePairs.m_p; + +BufferedTransformation & TheBitBucket() +{ + static BitBucket bitBucket; + return bitBucket; +} + +Algorithm::Algorithm(bool checkSelfTestStatus) +{ + if (checkSelfTestStatus && FIPS_140_2_ComplianceEnabled()) + { + if (GetPowerUpSelfTestStatus() == POWER_UP_SELF_TEST_NOT_DONE && !PowerUpSelfTestInProgressOnThisThread()) + throw SelfTestFailure("Cryptographic algorithms are disabled before the power-up self tests are performed."); + + if (GetPowerUpSelfTestStatus() == POWER_UP_SELF_TEST_FAILED) + throw SelfTestFailure("Cryptographic algorithms are disabled after a power-up self test failed."); + } +} + +void SimpleKeyingInterface::SetKey(const byte *key, size_t length, const NameValuePairs ¶ms) +{ + this->ThrowIfInvalidKeyLength(length); + this->UncheckedSetKey(key, (unsigned int)length, params); +} + +void SimpleKeyingInterface::SetKeyWithRounds(const byte *key, size_t length, int rounds) +{ + SetKey(key, length, MakeParameters(Name::Rounds(), rounds)); +} + +void SimpleKeyingInterface::SetKeyWithIV(const byte *key, size_t length, const byte *iv, size_t ivLength) +{ + SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, ivLength))); +} + +void SimpleKeyingInterface::ThrowIfInvalidKeyLength(size_t length) +{ + if (!IsValidKeyLength(length)) + throw InvalidKeyLength(GetAlgorithm().AlgorithmName(), length); +} + +void SimpleKeyingInterface::ThrowIfResynchronizable() +{ + if (IsResynchronizable()) + throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": this object requires an IV"); +} + +void SimpleKeyingInterface::ThrowIfInvalidIV(const byte *iv) +{ + if (!iv && !(IVRequirement() == INTERNALLY_GENERATED_IV || IVRequirement() == UNIQUE_IV || !IsResynchronizable())) + throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": this object cannot use a null IV"); +} + +size_t SimpleKeyingInterface::ThrowIfInvalidIVLength(int size) +{ + if (size < 0) + return IVSize(); + else if ((size_t)size < MinIVLength()) + throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": IV length " + IntToString(size) + " is less than the minimum of " + IntToString(MinIVLength())); + else if ((size_t)size > MaxIVLength()) + throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": IV length " + IntToString(size) + " exceeds the maximum of " + IntToString(MaxIVLength())); + else + return size; +} + +const byte * SimpleKeyingInterface::GetIVAndThrowIfInvalid(const NameValuePairs ¶ms, size_t &size) +{ + ConstByteArrayParameter ivWithLength; + const byte *iv; + bool found = false; + + try {found = params.GetValue(Name::IV(), ivWithLength);} + catch (const NameValuePairs::ValueTypeMismatch &) {} + + if (found) + { + iv = ivWithLength.begin(); + ThrowIfInvalidIV(iv); + size = ThrowIfInvalidIVLength((int)ivWithLength.size()); + return iv; + } + else if (params.GetValue(Name::IV(), iv)) + { + ThrowIfInvalidIV(iv); + size = IVSize(); + return iv; + } + else + { + ThrowIfResynchronizable(); + size = 0; + return NULL; + } +} + +void SimpleKeyingInterface::GetNextIV(RandomNumberGenerator &rng, byte *IV) +{ + rng.GenerateBlock(IV, IVSize()); +} + +size_t BlockTransformation::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const +{ + size_t blockSize = BlockSize(); + size_t inIncrement = (flags & (BT_InBlockIsCounter|BT_DontIncrementInOutPointers)) ? 0 : blockSize; + size_t xorIncrement = xorBlocks ? blockSize : 0; + size_t outIncrement = (flags & BT_DontIncrementInOutPointers) ? 0 : blockSize; + + if (flags & BT_ReverseDirection) + { + assert(length % blockSize == 0); + inBlocks += length - blockSize; + xorBlocks += length - blockSize; + outBlocks += length - blockSize; + inIncrement = 0-inIncrement; + xorIncrement = 0-xorIncrement; + outIncrement = 0-outIncrement; + } + + while (length >= blockSize) + { + if (flags & BT_XorInput) + { + xorbuf(outBlocks, xorBlocks, inBlocks, blockSize); + ProcessBlock(outBlocks); + } + else + ProcessAndXorBlock(inBlocks, xorBlocks, outBlocks); + if (flags & BT_InBlockIsCounter) + const_cast(inBlocks)[blockSize-1]++; + inBlocks += inIncrement; + outBlocks += outIncrement; + xorBlocks += xorIncrement; + length -= blockSize; + } + + return length; +} + +unsigned int BlockTransformation::OptimalDataAlignment() const +{ + return GetAlignmentOf(); +} + +unsigned int StreamTransformation::OptimalDataAlignment() const +{ + return GetAlignmentOf(); +} + +unsigned int HashTransformation::OptimalDataAlignment() const +{ + return GetAlignmentOf(); +} + +void StreamTransformation::ProcessLastBlock(byte *outString, const byte *inString, size_t length) +{ + assert(MinLastBlockSize() == 0); // this function should be overriden otherwise + + if (length == MandatoryBlockSize()) + ProcessData(outString, inString, length); + else if (length != 0) + throw NotImplemented(AlgorithmName() + ": this object does't support a special last block"); +} + +void AuthenticatedSymmetricCipher::SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength) +{ + if (headerLength > MaxHeaderLength()) + throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": header length " + IntToString(headerLength) + " exceeds the maximum of " + IntToString(MaxHeaderLength())); + + if (messageLength > MaxMessageLength()) + throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": message length " + IntToString(messageLength) + " exceeds the maximum of " + IntToString(MaxMessageLength())); + + if (footerLength > MaxFooterLength()) + throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": footer length " + IntToString(footerLength) + " exceeds the maximum of " + IntToString(MaxFooterLength())); + + UncheckedSpecifyDataLengths(headerLength, messageLength, footerLength); +} + +void AuthenticatedSymmetricCipher::EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *message, size_t messageLength) +{ + Resynchronize(iv, ivLength); + SpecifyDataLengths(headerLength, messageLength); + Update(header, headerLength); + ProcessString(ciphertext, message, messageLength); + TruncatedFinal(mac, macSize); +} + +bool AuthenticatedSymmetricCipher::DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *ciphertext, size_t ciphertextLength) +{ + Resynchronize(iv, ivLength); + SpecifyDataLengths(headerLength, ciphertextLength); + Update(header, headerLength); + ProcessString(message, ciphertext, ciphertextLength); + return TruncatedVerify(mac, macLength); +} + +unsigned int RandomNumberGenerator::GenerateBit() +{ + return GenerateByte() & 1; +} + +byte RandomNumberGenerator::GenerateByte() +{ + byte b; + GenerateBlock(&b, 1); + return b; +} + +word32 RandomNumberGenerator::GenerateWord32(word32 min, word32 max) +{ + word32 range = max-min; + const int maxBits = BitPrecision(range); + + word32 value; + + do + { + GenerateBlock((byte *)&value, sizeof(value)); + value = Crop(value, maxBits); + } while (value > range); + + return value+min; +} + +void RandomNumberGenerator::GenerateBlock(byte *output, size_t size) +{ + ArraySink s(output, size); + GenerateIntoBufferedTransformation(s, DEFAULT_CHANNEL, size); +} + +void RandomNumberGenerator::DiscardBytes(size_t n) +{ + GenerateIntoBufferedTransformation(TheBitBucket(), DEFAULT_CHANNEL, n); +} + +void RandomNumberGenerator::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length) +{ + FixedSizeSecBlock buffer; + while (length) + { + size_t len = UnsignedMin(buffer.size(), length); + GenerateBlock(buffer, len); + target.ChannelPut(channel, buffer, len); + length -= len; + } +} + +//! see NullRNG() +class ClassNullRNG : public RandomNumberGenerator +{ +public: + std::string AlgorithmName() const {return "NullRNG";} + void GenerateBlock(byte *output, size_t size) {throw NotImplemented("NullRNG: NullRNG should only be passed to functions that don't need to generate random bytes");} +}; + +RandomNumberGenerator & NullRNG() +{ + static ClassNullRNG s_nullRNG; + return s_nullRNG; +} + +bool HashTransformation::TruncatedVerify(const byte *digestIn, size_t digestLength) +{ + ThrowIfInvalidTruncatedSize(digestLength); + SecByteBlock digest(digestLength); + TruncatedFinal(digest, digestLength); + return VerifyBufsEqual(digest, digestIn, digestLength); +} + +void HashTransformation::ThrowIfInvalidTruncatedSize(size_t size) const +{ + if (size > DigestSize()) + throw InvalidArgument("HashTransformation: can't truncate a " + IntToString(DigestSize()) + " byte digest to " + IntToString(size) + " bytes"); +} + +unsigned int BufferedTransformation::GetMaxWaitObjectCount() const +{ + const BufferedTransformation *t = AttachedTransformation(); + return t ? t->GetMaxWaitObjectCount() : 0; +} + +void BufferedTransformation::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack) +{ + BufferedTransformation *t = AttachedTransformation(); + if (t) + t->GetWaitObjects(container, callStack); // reduce clutter by not adding to stack here +} + +void BufferedTransformation::Initialize(const NameValuePairs ¶meters, int propagation) +{ + assert(!AttachedTransformation()); + IsolatedInitialize(parameters); +} + +bool BufferedTransformation::Flush(bool hardFlush, int propagation, bool blocking) +{ + assert(!AttachedTransformation()); + return IsolatedFlush(hardFlush, blocking); +} + +bool BufferedTransformation::MessageSeriesEnd(int propagation, bool blocking) +{ + assert(!AttachedTransformation()); + return IsolatedMessageSeriesEnd(blocking); +} + +byte * BufferedTransformation::ChannelCreatePutSpace(const std::string &channel, size_t &size) +{ + if (channel.empty()) + return CreatePutSpace(size); + else + throw NoChannelSupport(AlgorithmName()); +} + +size_t BufferedTransformation::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) +{ + if (channel.empty()) + return Put2(begin, length, messageEnd, blocking); + else + throw NoChannelSupport(AlgorithmName()); +} + +size_t BufferedTransformation::ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking) +{ + if (channel.empty()) + return PutModifiable2(begin, length, messageEnd, blocking); + else + return ChannelPut2(channel, begin, length, messageEnd, blocking); +} + +bool BufferedTransformation::ChannelFlush(const std::string &channel, bool completeFlush, int propagation, bool blocking) +{ + if (channel.empty()) + return Flush(completeFlush, propagation, blocking); + else + throw NoChannelSupport(AlgorithmName()); +} + +bool BufferedTransformation::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking) +{ + if (channel.empty()) + return MessageSeriesEnd(propagation, blocking); + else + throw NoChannelSupport(AlgorithmName()); +} + +lword BufferedTransformation::MaxRetrievable() const +{ + if (AttachedTransformation()) + return AttachedTransformation()->MaxRetrievable(); + else + return CopyTo(TheBitBucket()); +} + +bool BufferedTransformation::AnyRetrievable() const +{ + if (AttachedTransformation()) + return AttachedTransformation()->AnyRetrievable(); + else + { + byte b; + return Peek(b) != 0; + } +} + +size_t BufferedTransformation::Get(byte &outByte) +{ + if (AttachedTransformation()) + return AttachedTransformation()->Get(outByte); + else + return Get(&outByte, 1); +} + +size_t BufferedTransformation::Get(byte *outString, size_t getMax) +{ + if (AttachedTransformation()) + return AttachedTransformation()->Get(outString, getMax); + else + { + ArraySink arraySink(outString, getMax); + return (size_t)TransferTo(arraySink, getMax); + } +} + +size_t BufferedTransformation::Peek(byte &outByte) const +{ + if (AttachedTransformation()) + return AttachedTransformation()->Peek(outByte); + else + return Peek(&outByte, 1); +} + +size_t BufferedTransformation::Peek(byte *outString, size_t peekMax) const +{ + if (AttachedTransformation()) + return AttachedTransformation()->Peek(outString, peekMax); + else + { + ArraySink arraySink(outString, peekMax); + return (size_t)CopyTo(arraySink, peekMax); + } +} + +lword BufferedTransformation::Skip(lword skipMax) +{ + if (AttachedTransformation()) + return AttachedTransformation()->Skip(skipMax); + else + return TransferTo(TheBitBucket(), skipMax); +} + +lword BufferedTransformation::TotalBytesRetrievable() const +{ + if (AttachedTransformation()) + return AttachedTransformation()->TotalBytesRetrievable(); + else + return MaxRetrievable(); +} + +unsigned int BufferedTransformation::NumberOfMessages() const +{ + if (AttachedTransformation()) + return AttachedTransformation()->NumberOfMessages(); + else + return CopyMessagesTo(TheBitBucket()); +} + +bool BufferedTransformation::AnyMessages() const +{ + if (AttachedTransformation()) + return AttachedTransformation()->AnyMessages(); + else + return NumberOfMessages() != 0; +} + +bool BufferedTransformation::GetNextMessage() +{ + if (AttachedTransformation()) + return AttachedTransformation()->GetNextMessage(); + else + { + assert(!AnyMessages()); + return false; + } +} + +unsigned int BufferedTransformation::SkipMessages(unsigned int count) +{ + if (AttachedTransformation()) + return AttachedTransformation()->SkipMessages(count); + else + return TransferMessagesTo(TheBitBucket(), count); +} + +size_t BufferedTransformation::TransferMessagesTo2(BufferedTransformation &target, unsigned int &messageCount, const std::string &channel, bool blocking) +{ + if (AttachedTransformation()) + return AttachedTransformation()->TransferMessagesTo2(target, messageCount, channel, blocking); + else + { + unsigned int maxMessages = messageCount; + for (messageCount=0; messageCount < maxMessages && AnyMessages(); messageCount++) + { + size_t blockedBytes; + lword transferredBytes; + + while (AnyRetrievable()) + { + transferredBytes = LWORD_MAX; + blockedBytes = TransferTo2(target, transferredBytes, channel, blocking); + if (blockedBytes > 0) + return blockedBytes; + } + + if (target.ChannelMessageEnd(channel, GetAutoSignalPropagation(), blocking)) + return 1; + + bool result = GetNextMessage(); + assert(result); + } + return 0; + } +} + +unsigned int BufferedTransformation::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const +{ + if (AttachedTransformation()) + return AttachedTransformation()->CopyMessagesTo(target, count, channel); + else + return 0; +} + +void BufferedTransformation::SkipAll() +{ + if (AttachedTransformation()) + AttachedTransformation()->SkipAll(); + else + { + while (SkipMessages()) {} + while (Skip()) {} + } +} + +size_t BufferedTransformation::TransferAllTo2(BufferedTransformation &target, const std::string &channel, bool blocking) +{ + if (AttachedTransformation()) + return AttachedTransformation()->TransferAllTo2(target, channel, blocking); + else + { + assert(!NumberOfMessageSeries()); + + unsigned int messageCount; + do + { + messageCount = UINT_MAX; + size_t blockedBytes = TransferMessagesTo2(target, messageCount, channel, blocking); + if (blockedBytes) + return blockedBytes; + } + while (messageCount != 0); + + lword byteCount; + do + { + byteCount = ULONG_MAX; + size_t blockedBytes = TransferTo2(target, byteCount, channel, blocking); + if (blockedBytes) + return blockedBytes; + } + while (byteCount != 0); + + return 0; + } +} + +void BufferedTransformation::CopyAllTo(BufferedTransformation &target, const std::string &channel) const +{ + if (AttachedTransformation()) + AttachedTransformation()->CopyAllTo(target, channel); + else + { + assert(!NumberOfMessageSeries()); + while (CopyMessagesTo(target, UINT_MAX, channel)) {} + } +} + +void BufferedTransformation::SetRetrievalChannel(const std::string &channel) +{ + if (AttachedTransformation()) + AttachedTransformation()->SetRetrievalChannel(channel); +} + +size_t BufferedTransformation::ChannelPutWord16(const std::string &channel, word16 value, ByteOrder order, bool blocking) +{ + PutWord(false, order, m_buf, value); + return ChannelPut(channel, m_buf, 2, blocking); +} + +size_t BufferedTransformation::ChannelPutWord32(const std::string &channel, word32 value, ByteOrder order, bool blocking) +{ + PutWord(false, order, m_buf, value); + return ChannelPut(channel, m_buf, 4, blocking); +} + +size_t BufferedTransformation::PutWord16(word16 value, ByteOrder order, bool blocking) +{ + return ChannelPutWord16(DEFAULT_CHANNEL, value, order, blocking); +} + +size_t BufferedTransformation::PutWord32(word32 value, ByteOrder order, bool blocking) +{ + return ChannelPutWord32(DEFAULT_CHANNEL, value, order, blocking); +} + +size_t BufferedTransformation::PeekWord16(word16 &value, ByteOrder order) const +{ + byte buf[2] = {0, 0}; + size_t len = Peek(buf, 2); + + if (order) + value = (buf[0] << 8) | buf[1]; + else + value = (buf[1] << 8) | buf[0]; + + return len; +} + +size_t BufferedTransformation::PeekWord32(word32 &value, ByteOrder order) const +{ + byte buf[4] = {0, 0, 0, 0}; + size_t len = Peek(buf, 4); + + if (order) + value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf [3]; + else + value = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf [0]; + + return len; +} + +size_t BufferedTransformation::GetWord16(word16 &value, ByteOrder order) +{ + return (size_t)Skip(PeekWord16(value, order)); +} + +size_t BufferedTransformation::GetWord32(word32 &value, ByteOrder order) +{ + return (size_t)Skip(PeekWord32(value, order)); +} + +void BufferedTransformation::Attach(BufferedTransformation *newOut) +{ + if (AttachedTransformation() && AttachedTransformation()->Attachable()) + AttachedTransformation()->Attach(newOut); + else + Detach(newOut); +} + +void GeneratableCryptoMaterial::GenerateRandomWithKeySize(RandomNumberGenerator &rng, unsigned int keySize) +{ + GenerateRandom(rng, MakeParameters("KeySize", (int)keySize)); +} + +class PK_DefaultEncryptionFilter : public Unflushable +{ +public: + PK_DefaultEncryptionFilter(RandomNumberGenerator &rng, const PK_Encryptor &encryptor, BufferedTransformation *attachment, const NameValuePairs ¶meters) + : m_rng(rng), m_encryptor(encryptor), m_parameters(parameters) + { + Detach(attachment); + } + + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) + { + FILTER_BEGIN; + m_plaintextQueue.Put(inString, length); + + if (messageEnd) + { + { + size_t plaintextLength; + if (!SafeConvert(m_plaintextQueue.CurrentSize(), plaintextLength)) + throw InvalidArgument("PK_DefaultEncryptionFilter: plaintext too long"); + size_t ciphertextLength = m_encryptor.CiphertextLength(plaintextLength); + + SecByteBlock plaintext(plaintextLength); + m_plaintextQueue.Get(plaintext, plaintextLength); + m_ciphertext.resize(ciphertextLength); + m_encryptor.Encrypt(m_rng, plaintext, plaintextLength, m_ciphertext, m_parameters); + } + + FILTER_OUTPUT(1, m_ciphertext, m_ciphertext.size(), messageEnd); + } + FILTER_END_NO_MESSAGE_END; + } + + RandomNumberGenerator &m_rng; + const PK_Encryptor &m_encryptor; + const NameValuePairs &m_parameters; + ByteQueue m_plaintextQueue; + SecByteBlock m_ciphertext; +}; + +BufferedTransformation * PK_Encryptor::CreateEncryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment, const NameValuePairs ¶meters) const +{ + return new PK_DefaultEncryptionFilter(rng, *this, attachment, parameters); +} + +class PK_DefaultDecryptionFilter : public Unflushable +{ +public: + PK_DefaultDecryptionFilter(RandomNumberGenerator &rng, const PK_Decryptor &decryptor, BufferedTransformation *attachment, const NameValuePairs ¶meters) + : m_rng(rng), m_decryptor(decryptor), m_parameters(parameters) + { + Detach(attachment); + } + + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) + { + FILTER_BEGIN; + m_ciphertextQueue.Put(inString, length); + + if (messageEnd) + { + { + size_t ciphertextLength; + if (!SafeConvert(m_ciphertextQueue.CurrentSize(), ciphertextLength)) + throw InvalidArgument("PK_DefaultDecryptionFilter: ciphertext too long"); + size_t maxPlaintextLength = m_decryptor.MaxPlaintextLength(ciphertextLength); + + SecByteBlock ciphertext(ciphertextLength); + m_ciphertextQueue.Get(ciphertext, ciphertextLength); + m_plaintext.resize(maxPlaintextLength); + m_result = m_decryptor.Decrypt(m_rng, ciphertext, ciphertextLength, m_plaintext, m_parameters); + if (!m_result.isValidCoding) + throw InvalidCiphertext(m_decryptor.AlgorithmName() + ": invalid ciphertext"); + } + + FILTER_OUTPUT(1, m_plaintext, m_result.messageLength, messageEnd); + } + FILTER_END_NO_MESSAGE_END; + } + + RandomNumberGenerator &m_rng; + const PK_Decryptor &m_decryptor; + const NameValuePairs &m_parameters; + ByteQueue m_ciphertextQueue; + SecByteBlock m_plaintext; + DecodingResult m_result; +}; + +BufferedTransformation * PK_Decryptor::CreateDecryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment, const NameValuePairs ¶meters) const +{ + return new PK_DefaultDecryptionFilter(rng, *this, attachment, parameters); +} + +size_t PK_Signer::Sign(RandomNumberGenerator &rng, PK_MessageAccumulator *messageAccumulator, byte *signature) const +{ + std::auto_ptr m(messageAccumulator); + return SignAndRestart(rng, *m, signature, false); +} + +size_t PK_Signer::SignMessage(RandomNumberGenerator &rng, const byte *message, size_t messageLen, byte *signature) const +{ + std::auto_ptr m(NewSignatureAccumulator(rng)); + m->Update(message, messageLen); + return SignAndRestart(rng, *m, signature, false); +} + +size_t PK_Signer::SignMessageWithRecovery(RandomNumberGenerator &rng, const byte *recoverableMessage, size_t recoverableMessageLength, + const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, byte *signature) const +{ + std::auto_ptr m(NewSignatureAccumulator(rng)); + InputRecoverableMessage(*m, recoverableMessage, recoverableMessageLength); + m->Update(nonrecoverableMessage, nonrecoverableMessageLength); + return SignAndRestart(rng, *m, signature, false); +} + +bool PK_Verifier::Verify(PK_MessageAccumulator *messageAccumulator) const +{ + std::auto_ptr m(messageAccumulator); + return VerifyAndRestart(*m); +} + +bool PK_Verifier::VerifyMessage(const byte *message, size_t messageLen, const byte *signature, size_t signatureLength) const +{ + std::auto_ptr m(NewVerificationAccumulator()); + InputSignature(*m, signature, signatureLength); + m->Update(message, messageLen); + return VerifyAndRestart(*m); +} + +DecodingResult PK_Verifier::Recover(byte *recoveredMessage, PK_MessageAccumulator *messageAccumulator) const +{ + std::auto_ptr m(messageAccumulator); + return RecoverAndRestart(recoveredMessage, *m); +} + +DecodingResult PK_Verifier::RecoverMessage(byte *recoveredMessage, + const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, + const byte *signature, size_t signatureLength) const +{ + std::auto_ptr m(NewVerificationAccumulator()); + InputSignature(*m, signature, signatureLength); + m->Update(nonrecoverableMessage, nonrecoverableMessageLength); + return RecoverAndRestart(recoveredMessage, *m); +} + +void SimpleKeyAgreementDomain::GenerateKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const +{ + GeneratePrivateKey(rng, privateKey); + GeneratePublicKey(rng, privateKey, publicKey); +} + +void AuthenticatedKeyAgreementDomain::GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const +{ + GenerateStaticPrivateKey(rng, privateKey); + GenerateStaticPublicKey(rng, privateKey, publicKey); +} + +void AuthenticatedKeyAgreementDomain::GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const +{ + GenerateEphemeralPrivateKey(rng, privateKey); + GenerateEphemeralPublicKey(rng, privateKey, publicKey); +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/cryptlib.dsp b/src-cryptopp/cryptlib.dsp new file mode 100644 index 0000000..8bbb6ea --- /dev/null +++ b/src-cryptopp/cryptlib.dsp @@ -0,0 +1,1204 @@ +# Microsoft Developer Studio Project File - Name="cryptlib" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=cryptlib - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "cryptlib.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "cryptlib.mak" CFG="cryptlib - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "cryptlib - Win32 DLL-Import Release" (based on "Win32 (x86) Static Library") +!MESSAGE "cryptlib - Win32 DLL-Import Debug" (based on "Win32 (x86) Static Library") +!MESSAGE "cryptlib - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "cryptlib - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "cryptlib - Win32 DLL-Import Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "cryptlib___Win32_FIPS_140_Release" +# PROP BASE Intermediate_Dir "cryptlib___Win32_FIPS_140_Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "DLL_Import_Release" +# PROP Intermediate_Dir "DLL_Import_Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /G5 /Gz /MT /W3 /GX /Zi /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /Yu"pch.h" /FD /c +# ADD CPP /nologo /G5 /Gz /MT /W3 /GR /GX /Zi /O2 /Ob2 /D "NDEBUG" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /D "WIN32" /D "CRYPTOPP_IMPORTS" /Yu"pch.h" /FD /Zm400 /c +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "cryptlib - Win32 DLL-Import Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "cryptlib___Win32_FIPS_140_Debug" +# PROP BASE Intermediate_Dir "cryptlib___Win32_FIPS_140_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "DLL_Import_Debug" +# PROP Intermediate_Dir "DLL_Import_Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /Yu"pch.h" /FD /c +# ADD CPP /nologo /G5 /Gz /MTd /W3 /GR /GX /Zi /Oi /D "_DEBUG" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /D "WIN32" /D "CRYPTOPP_IMPORTS" /Yu"pch.h" /FD /Zm400 /c +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "cryptlib - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "cryptlib" +# PROP BASE Intermediate_Dir "cryptlib" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GR /GX /Zi /O2 /Ob2 /D "NDEBUG" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /D "WIN32" /Yu"pch.h" /FD /Zm400 /c +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "cryptlib - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "cryptli0" +# PROP BASE Intermediate_Dir "cryptli0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /GR /GX /Zi /Oi /D "_DEBUG" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /D "WIN32" /Yu"pch.h" /FD /Zm400 /c +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "cryptlib - Win32 DLL-Import Release" +# Name "cryptlib - Win32 DLL-Import Debug" +# Name "cryptlib - Win32 Release" +# Name "cryptlib - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter ".cpp" +# Begin Source File + +SOURCE=.\3way.cpp +# End Source File +# Begin Source File + +SOURCE=.\adhoc.cpp.proto + +!IF "$(CFG)" == "cryptlib - Win32 DLL-Import Release" + +# Begin Custom Build +InputPath=.\adhoc.cpp.proto + +"adhoc.cpp.copied" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + if not exist adhoc.cpp copy "$(InputPath)" adhoc.cpp + echo: >> adhoc.cpp.copied + +# End Custom Build + +!ELSEIF "$(CFG)" == "cryptlib - Win32 DLL-Import Debug" + +# Begin Custom Build +InputPath=.\adhoc.cpp.proto + +"adhoc.cpp.copied" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + if not exist adhoc.cpp copy "$(InputPath)" adhoc.cpp + echo: >> adhoc.cpp.copied + +# End Custom Build + +!ELSEIF "$(CFG)" == "cryptlib - Win32 Release" + +# Begin Custom Build +InputPath=.\adhoc.cpp.proto + +"adhoc.cpp.copied" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + if not exist adhoc.cpp copy "$(InputPath)" adhoc.cpp + echo: >> adhoc.cpp.copied + +# End Custom Build + +!ELSEIF "$(CFG)" == "cryptlib - Win32 Debug" + +# Begin Custom Build +InputPath=.\adhoc.cpp.proto + +"adhoc.cpp.copied" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + if not exist adhoc.cpp copy "$(InputPath)" adhoc.cpp + echo: >> adhoc.cpp.copied + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\adler32.cpp +# End Source File +# Begin Source File + +SOURCE=.\algebra.cpp +# End Source File +# Begin Source File + +SOURCE=.\algparam.cpp +# End Source File +# Begin Source File + +SOURCE=.\arc4.cpp +# End Source File +# Begin Source File + +SOURCE=.\asn.cpp +# End Source File +# Begin Source File + +SOURCE=.\authenc.cpp +# End Source File +# Begin Source File + +SOURCE=.\base32.cpp +# End Source File +# Begin Source File + +SOURCE=.\base64.cpp +# End Source File +# Begin Source File + +SOURCE=.\basecode.cpp +# End Source File +# Begin Source File + +SOURCE=.\bfinit.cpp +# End Source File +# Begin Source File + +SOURCE=.\blowfish.cpp +# End Source File +# Begin Source File + +SOURCE=.\blumshub.cpp +# End Source File +# Begin Source File + +SOURCE=.\camellia.cpp +# End Source File +# Begin Source File + +SOURCE=.\cast.cpp +# End Source File +# Begin Source File + +SOURCE=.\casts.cpp +# End Source File +# Begin Source File + +SOURCE=.\cbcmac.cpp +# End Source File +# Begin Source File + +SOURCE=.\ccm.cpp +# End Source File +# Begin Source File + +SOURCE=.\channels.cpp +# End Source File +# Begin Source File + +SOURCE=.\cmac.cpp +# End Source File +# Begin Source File + +SOURCE=.\cpu.cpp +# End Source File +# Begin Source File + +SOURCE=.\crc.cpp +# End Source File +# Begin Source File + +SOURCE=.\cryptlib.cpp +# End Source File +# Begin Source File + +SOURCE=.\default.cpp +# End Source File +# Begin Source File + +SOURCE=.\des.cpp +# End Source File +# Begin Source File + +SOURCE=.\dessp.cpp +# End Source File +# Begin Source File + +SOURCE=.\dh.cpp +# End Source File +# Begin Source File + +SOURCE=.\dh2.cpp +# End Source File +# Begin Source File + +SOURCE=.\dll.cpp +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=.\dsa.cpp +# End Source File +# Begin Source File + +SOURCE=.\eax.cpp +# End Source File +# Begin Source File + +SOURCE=.\ec2n.cpp +# End Source File +# Begin Source File + +SOURCE=.\eccrypto.cpp +# End Source File +# Begin Source File + +SOURCE=.\ecp.cpp +# End Source File +# Begin Source File + +SOURCE=.\elgamal.cpp +# End Source File +# Begin Source File + +SOURCE=.\emsa2.cpp +# End Source File +# Begin Source File + +SOURCE=.\eprecomp.cpp +# End Source File +# Begin Source File + +SOURCE=.\esign.cpp +# End Source File +# Begin Source File + +SOURCE=.\files.cpp +# End Source File +# Begin Source File + +SOURCE=.\filters.cpp +# End Source File +# Begin Source File + +SOURCE=.\fips140.cpp +# End Source File +# Begin Source File + +SOURCE=.\fipstest.cpp +# End Source File +# Begin Source File + +SOURCE=.\gcm.cpp +# End Source File +# Begin Source File + +SOURCE=.\gf256.cpp +# End Source File +# Begin Source File + +SOURCE=.\gf2_32.cpp +# End Source File +# Begin Source File + +SOURCE=.\gf2n.cpp +# End Source File +# Begin Source File + +SOURCE=.\gfpcrypt.cpp +# End Source File +# Begin Source File + +SOURCE=.\gost.cpp +# End Source File +# Begin Source File + +SOURCE=.\gzip.cpp +# End Source File +# Begin Source File + +SOURCE=.\hex.cpp +# End Source File +# Begin Source File + +SOURCE=.\hmac.cpp +# End Source File +# Begin Source File + +SOURCE=.\hrtimer.cpp +# End Source File +# Begin Source File + +SOURCE=.\ida.cpp +# End Source File +# Begin Source File + +SOURCE=.\idea.cpp +# End Source File +# Begin Source File + +SOURCE=.\integer.cpp +# End Source File +# Begin Source File + +SOURCE=.\iterhash.cpp +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=.\luc.cpp +# End Source File +# Begin Source File + +SOURCE=.\mars.cpp +# End Source File +# Begin Source File + +SOURCE=.\marss.cpp +# End Source File +# Begin Source File + +SOURCE=.\md2.cpp +# End Source File +# Begin Source File + +SOURCE=.\md4.cpp +# End Source File +# Begin Source File + +SOURCE=.\md5.cpp +# End Source File +# Begin Source File + +SOURCE=.\misc.cpp +# End Source File +# Begin Source File + +SOURCE=.\modes.cpp +# End Source File +# Begin Source File + +SOURCE=.\mqueue.cpp +# End Source File +# Begin Source File + +SOURCE=.\mqv.cpp +# End Source File +# Begin Source File + +SOURCE=.\nbtheory.cpp +# End Source File +# Begin Source File + +SOURCE=.\network.cpp +# End Source File +# Begin Source File + +SOURCE=.\oaep.cpp +# End Source File +# Begin Source File + +SOURCE=.\osrng.cpp +# End Source File +# Begin Source File + +SOURCE=.\panama.cpp +# End Source File +# Begin Source File + +SOURCE=.\pch.cpp +# ADD CPP /Yc"pch.h" +# End Source File +# Begin Source File + +SOURCE=.\pkcspad.cpp +# End Source File +# Begin Source File + +SOURCE=.\polynomi.cpp +# End Source File +# Begin Source File + +SOURCE=.\pssr.cpp +# End Source File +# Begin Source File + +SOURCE=.\pubkey.cpp +# End Source File +# Begin Source File + +SOURCE=.\queue.cpp +# End Source File +# Begin Source File + +SOURCE=.\rabin.cpp +# End Source File +# Begin Source File + +SOURCE=.\randpool.cpp +# End Source File +# Begin Source File + +SOURCE=.\rc2.cpp +# End Source File +# Begin Source File + +SOURCE=.\rc5.cpp +# End Source File +# Begin Source File + +SOURCE=.\rc6.cpp +# End Source File +# Begin Source File + +SOURCE=.\rdtables.cpp +# End Source File +# Begin Source File + +SOURCE=.\rijndael.cpp +# End Source File +# Begin Source File + +SOURCE=.\ripemd.cpp +# End Source File +# Begin Source File + +SOURCE=.\rng.cpp +# End Source File +# Begin Source File + +SOURCE=.\rsa.cpp +# End Source File +# Begin Source File + +SOURCE=.\rw.cpp +# End Source File +# Begin Source File + +SOURCE=.\safer.cpp +# End Source File +# Begin Source File + +SOURCE=.\salsa.cpp +# End Source File +# Begin Source File + +SOURCE=.\seal.cpp +# End Source File +# Begin Source File + +SOURCE=.\seed.cpp +# End Source File +# Begin Source File + +SOURCE=.\serpent.cpp +# End Source File +# Begin Source File + +SOURCE=.\sha.cpp +# End Source File +# Begin Source File + +SOURCE=.\shacal2.cpp +# End Source File +# Begin Source File + +SOURCE=.\shark.cpp +# End Source File +# Begin Source File + +SOURCE=.\sharkbox.cpp +# End Source File +# Begin Source File + +SOURCE=.\simple.cpp +# End Source File +# Begin Source File + +SOURCE=.\skipjack.cpp +# End Source File +# Begin Source File + +SOURCE=.\socketft.cpp +# End Source File +# Begin Source File + +SOURCE=.\sosemanuk.cpp +# End Source File +# Begin Source File + +SOURCE=.\square.cpp +# End Source File +# Begin Source File + +SOURCE=.\squaretb.cpp +# End Source File +# Begin Source File + +SOURCE=.\strciphr.cpp +# End Source File +# Begin Source File + +SOURCE=.\tea.cpp +# End Source File +# Begin Source File + +SOURCE=.\tftables.cpp +# End Source File +# Begin Source File + +SOURCE=.\tiger.cpp +# End Source File +# Begin Source File + +SOURCE=.\tigertab.cpp +# End Source File +# Begin Source File + +SOURCE=.\trdlocal.cpp +# End Source File +# Begin Source File + +SOURCE=.\ttmac.cpp +# End Source File +# Begin Source File + +SOURCE=.\twofish.cpp +# End Source File +# Begin Source File + +SOURCE=.\vmac.cpp +# End Source File +# Begin Source File + +SOURCE=.\wait.cpp +# End Source File +# Begin Source File + +SOURCE=.\wake.cpp +# End Source File +# Begin Source File + +SOURCE=.\whrlpool.cpp +# End Source File +# Begin Source File + +SOURCE=.\winpipes.cpp +# End Source File +# Begin Source File + +SOURCE=.\xtr.cpp +# End Source File +# Begin Source File + +SOURCE=.\xtrcrypt.cpp +# End Source File +# Begin Source File + +SOURCE=.\zdeflate.cpp +# End Source File +# Begin Source File + +SOURCE=.\zinflate.cpp +# End Source File +# Begin Source File + +SOURCE=.\zlib.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter ".;.h" +# Begin Source File + +SOURCE=.\3way.h +# End Source File +# Begin Source File + +SOURCE=.\adler32.h +# End Source File +# Begin Source File + +SOURCE=.\aes.h +# End Source File +# Begin Source File + +SOURCE=.\algebra.h +# End Source File +# Begin Source File + +SOURCE=.\algparam.h +# End Source File +# Begin Source File + +SOURCE=.\arc4.h +# End Source File +# Begin Source File + +SOURCE=.\argnames.h +# End Source File +# Begin Source File + +SOURCE=.\asn.h +# End Source File +# Begin Source File + +SOURCE=.\authenc.h +# End Source File +# Begin Source File + +SOURCE=.\base32.h +# End Source File +# Begin Source File + +SOURCE=.\base64.h +# End Source File +# Begin Source File + +SOURCE=.\basecode.h +# End Source File +# Begin Source File + +SOURCE=.\blowfish.h +# End Source File +# Begin Source File + +SOURCE=.\blumshub.h +# End Source File +# Begin Source File + +SOURCE=.\camellia.h +# End Source File +# Begin Source File + +SOURCE=.\cast.h +# End Source File +# Begin Source File + +SOURCE=.\cbcmac.h +# End Source File +# Begin Source File + +SOURCE=.\ccm.h +# End Source File +# Begin Source File + +SOURCE=.\channels.h +# End Source File +# Begin Source File + +SOURCE=.\cmac.h +# End Source File +# Begin Source File + +SOURCE=.\config.h +# End Source File +# Begin Source File + +SOURCE=.\crc.h +# End Source File +# Begin Source File + +SOURCE=.\cryptlib.h +# End Source File +# Begin Source File + +SOURCE=.\default.h +# End Source File +# Begin Source File + +SOURCE=.\des.h +# End Source File +# Begin Source File + +SOURCE=.\dh.h +# End Source File +# Begin Source File + +SOURCE=.\dh2.h +# End Source File +# Begin Source File + +SOURCE=.\dmac.h +# End Source File +# Begin Source File + +SOURCE=.\dsa.h +# End Source File +# Begin Source File + +SOURCE=.\dword.h +# End Source File +# Begin Source File + +SOURCE=.\eax.h +# End Source File +# Begin Source File + +SOURCE=.\ec2n.h +# End Source File +# Begin Source File + +SOURCE=.\eccrypto.h +# End Source File +# Begin Source File + +SOURCE=.\ecp.h +# End Source File +# Begin Source File + +SOURCE=.\elgamal.h +# End Source File +# Begin Source File + +SOURCE=.\emsa2.h +# End Source File +# Begin Source File + +SOURCE=.\eprecomp.h +# End Source File +# Begin Source File + +SOURCE=.\esign.h +# End Source File +# Begin Source File + +SOURCE=.\factory.h +# End Source File +# Begin Source File + +SOURCE=.\files.h +# End Source File +# Begin Source File + +SOURCE=.\filters.h +# End Source File +# Begin Source File + +SOURCE=.\fips140.h +# End Source File +# Begin Source File + +SOURCE=.\fltrimpl.h +# End Source File +# Begin Source File + +SOURCE=.\gcm.h +# End Source File +# Begin Source File + +SOURCE=.\gf256.h +# End Source File +# Begin Source File + +SOURCE=.\gf2_32.h +# End Source File +# Begin Source File + +SOURCE=.\gf2n.h +# End Source File +# Begin Source File + +SOURCE=.\gfpcrypt.h +# End Source File +# Begin Source File + +SOURCE=.\gost.h +# End Source File +# Begin Source File + +SOURCE=.\gzip.h +# End Source File +# Begin Source File + +SOURCE=.\hex.h +# End Source File +# Begin Source File + +SOURCE=.\hmac.h +# End Source File +# Begin Source File + +SOURCE=.\hrtimer.h +# End Source File +# Begin Source File + +SOURCE=.\ida.h +# End Source File +# Begin Source File + +SOURCE=.\idea.h +# End Source File +# Begin Source File + +SOURCE=.\integer.h +# End Source File +# Begin Source File + +SOURCE=.\iterhash.h +# End Source File +# Begin Source File + +SOURCE=.\lubyrack.h +# End Source File +# Begin Source File + +SOURCE=.\luc.h +# End Source File +# Begin Source File + +SOURCE=.\mars.h +# End Source File +# Begin Source File + +SOURCE=.\md2.h +# End Source File +# Begin Source File + +SOURCE=.\md4.h +# End Source File +# Begin Source File + +SOURCE=.\md5.h +# End Source File +# Begin Source File + +SOURCE=.\mdc.h +# End Source File +# Begin Source File + +SOURCE=.\misc.h +# End Source File +# Begin Source File + +SOURCE=.\modarith.h +# End Source File +# Begin Source File + +SOURCE=.\modes.h +# End Source File +# Begin Source File + +SOURCE=.\modexppc.h +# End Source File +# Begin Source File + +SOURCE=.\mqueue.h +# End Source File +# Begin Source File + +SOURCE=.\mqv.h +# End Source File +# Begin Source File + +SOURCE=.\nbtheory.h +# End Source File +# Begin Source File + +SOURCE=.\network.h +# End Source File +# Begin Source File + +SOURCE=.\nr.h +# End Source File +# Begin Source File + +SOURCE=.\oaep.h +# End Source File +# Begin Source File + +SOURCE=.\oids.h +# End Source File +# Begin Source File + +SOURCE=.\osrng.h +# End Source File +# Begin Source File + +SOURCE=.\panama.h +# End Source File +# Begin Source File + +SOURCE=.\pch.h +# End Source File +# Begin Source File + +SOURCE=.\pkcspad.h +# End Source File +# Begin Source File + +SOURCE=.\polynomi.h +# End Source File +# Begin Source File + +SOURCE=.\pssr.h +# End Source File +# Begin Source File + +SOURCE=.\pubkey.h +# End Source File +# Begin Source File + +SOURCE=.\pwdbased.h +# End Source File +# Begin Source File + +SOURCE=.\queue.h +# End Source File +# Begin Source File + +SOURCE=.\rabin.h +# End Source File +# Begin Source File + +SOURCE=.\randpool.h +# End Source File +# Begin Source File + +SOURCE=.\rc2.h +# End Source File +# Begin Source File + +SOURCE=.\rc5.h +# End Source File +# Begin Source File + +SOURCE=.\rc6.h +# End Source File +# Begin Source File + +SOURCE=.\rijndael.h +# End Source File +# Begin Source File + +SOURCE=.\ripemd.h +# End Source File +# Begin Source File + +SOURCE=.\rng.h +# End Source File +# Begin Source File + +SOURCE=.\rsa.h +# End Source File +# Begin Source File + +SOURCE=.\rw.h +# End Source File +# Begin Source File + +SOURCE=.\safer.h +# End Source File +# Begin Source File + +SOURCE=.\salsa.h +# End Source File +# Begin Source File + +SOURCE=.\seal.h +# End Source File +# Begin Source File + +SOURCE=.\secblock.h +# End Source File +# Begin Source File + +SOURCE=.\seckey.h +# End Source File +# Begin Source File + +SOURCE=.\seed.h +# End Source File +# Begin Source File + +SOURCE=.\serpent.h +# End Source File +# Begin Source File + +SOURCE=.\sha.h +# End Source File +# Begin Source File + +SOURCE=.\shacal2.h +# End Source File +# Begin Source File + +SOURCE=.\shark.h +# End Source File +# Begin Source File + +SOURCE=.\simple.h +# End Source File +# Begin Source File + +SOURCE=.\skipjack.h +# End Source File +# Begin Source File + +SOURCE=.\smartptr.h +# End Source File +# Begin Source File + +SOURCE=.\socketft.h +# End Source File +# Begin Source File + +SOURCE=.\square.h +# End Source File +# Begin Source File + +SOURCE=.\strciphr.h +# End Source File +# Begin Source File + +SOURCE=.\tea.h +# End Source File +# Begin Source File + +SOURCE=.\tiger.h +# End Source File +# Begin Source File + +SOURCE=.\trdlocal.h +# End Source File +# Begin Source File + +SOURCE=.\trunhash.h +# End Source File +# Begin Source File + +SOURCE=.\ttmac.h +# End Source File +# Begin Source File + +SOURCE=.\twofish.h +# End Source File +# Begin Source File + +SOURCE=.\wait.h +# End Source File +# Begin Source File + +SOURCE=.\wake.h +# End Source File +# Begin Source File + +SOURCE=.\whrlpool.h +# End Source File +# Begin Source File + +SOURCE=.\winpipes.h +# End Source File +# Begin Source File + +SOURCE=.\words.h +# End Source File +# Begin Source File + +SOURCE=.\xtr.h +# End Source File +# Begin Source File + +SOURCE=.\xtrcrypt.h +# End Source File +# Begin Source File + +SOURCE=.\zdeflate.h +# End Source File +# Begin Source File + +SOURCE=.\zinflate.h +# End Source File +# Begin Source File + +SOURCE=.\zlib.h +# End Source File +# End Group +# Begin Group "Miscellaneous" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\Doxyfile +# End Source File +# Begin Source File + +SOURCE=.\GNUmakefile +# End Source File +# Begin Source File + +SOURCE=.\license.txt +# End Source File +# Begin Source File + +SOURCE=.\readme.txt +# End Source File +# End Group +# End Target +# End Project diff --git a/src-cryptopp/cryptlib.h b/src-cryptopp/cryptlib.h new file mode 100644 index 0000000..b5faa58 --- /dev/null +++ b/src-cryptopp/cryptlib.h @@ -0,0 +1,1661 @@ +// cryptlib.h - written and placed in the public domain by Wei Dai +/*! \file + This file contains the declarations for the abstract base + classes that provide a uniform interface to this library. +*/ + +/*! \mainpage Crypto++ Library 5.6.0 API Reference +
+
Abstract Base Classes
+ cryptlib.h +
Authenticated Encryption
+ AuthenticatedSymmetricCipherDocumentation +
Symmetric Ciphers
+ SymmetricCipherDocumentation +
Hash Functions
+ SHA1, SHA224, SHA256, SHA384, SHA512, Tiger, Whirlpool, RIPEMD160, RIPEMD320, RIPEMD128, RIPEMD256, Weak1::MD2, Weak1::MD4, Weak1::MD5 +
Non-Cryptographic Checksums
+ CRC32, Adler32 +
Message Authentication Codes
+ VMAC, HMAC, CBC_MAC, CMAC, DMAC, TTMAC, GCM (GMAC) +
Random Number Generators
+ NullRNG(), LC_RNG, RandomPool, BlockingRng, NonblockingRng, AutoSeededRandomPool, AutoSeededX917RNG, DefaultAutoSeededRNG +
Password-based Cryptography
+ PasswordBasedKeyDerivationFunction +
Public Key Cryptosystems
+ DLIES, ECIES, LUCES, RSAES, RabinES, LUC_IES +
Public Key Signature Schemes
+ DSA, GDSA, ECDSA, NR, ECNR, LUCSS, RSASS, RSASS_ISO, RabinSS, RWSS, ESIGN +
Key Agreement
+ #DH, DH2, #MQV, ECDH, ECMQV, XTR_DH +
Algebraic Structures
+ Integer, PolynomialMod2, PolynomialOver, RingOfPolynomialsOver, + ModularArithmetic, MontgomeryRepresentation, GFP2_ONB, + GF2NP, GF256, GF2_32, EC2N, ECP +
Secret Sharing and Information Dispersal
+ SecretSharing, SecretRecovery, InformationDispersal, InformationRecovery +
Compression
+ Deflator, Inflator, Gzip, Gunzip, ZlibCompressor, ZlibDecompressor +
Input Source Classes
+ StringSource, ArraySource, FileSource, SocketSource, WindowsPipeSource, RandomNumberSource +
Output Sink Classes
+ StringSinkTemplate, ArraySink, FileSink, SocketSink, WindowsPipeSink, RandomNumberSink +
Filter Wrappers
+ StreamTransformationFilter, HashFilter, HashVerificationFilter, SignerFilter, SignatureVerificationFilter +
Binary to Text Encoders and Decoders
+ HexEncoder, HexDecoder, Base64Encoder, Base64Decoder, Base32Encoder, Base32Decoder +
Wrappers for OS features
+ Timer, Socket, WindowsHandle, ThreadLocalStorage, ThreadUserTimer +
FIPS 140 related
+ fips140.h +
+ +In the FIPS 140-2 validated DLL version of Crypto++, only the following implementation class are available. +
+
Block Ciphers
+ AES, DES_EDE2, DES_EDE3, SKIPJACK +
Cipher Modes (replace template parameter BC with one of the block ciphers above)
+ ECB_Mode\, CTR_Mode\, CBC_Mode\, CFB_FIPS_Mode\, OFB_Mode\ +
Hash Functions
+ SHA1, SHA224, SHA256, SHA384, SHA512 +
Public Key Signature Schemes (replace template parameter H with one of the hash functions above)
+ RSASS\, RSASS\, RSASS_ISO\, RWSS\, DSA, ECDSA\, ECDSA\ +
Message Authentication Codes (replace template parameter H with one of the hash functions above)
+ HMAC\, CBC_MAC\, CBC_MAC\ +
Random Number Generators
+ DefaultAutoSeededRNG (AutoSeededX917RNG\) +
Key Agreement
+ #DH +
Public Key Cryptosystems
+ RSAES\ \> +
+ +

This reference manual is a work in progress. Some classes are still lacking detailed descriptions. +

Click here to download a zip archive containing this manual. +

Thanks to Ryan Phillips for providing the Doxygen configuration file +and getting me started with this manual. +*/ + +#ifndef CRYPTOPP_CRYPTLIB_H +#define CRYPTOPP_CRYPTLIB_H + +#include "config.h" +#include "stdcpp.h" + +NAMESPACE_BEGIN(CryptoPP) + +// forward declarations +class Integer; +class RandomNumberGenerator; +class BufferedTransformation; + +//! used to specify a direction for a cipher to operate in (encrypt or decrypt) +enum CipherDir {ENCRYPTION, DECRYPTION}; + +//! used to represent infinite time +const unsigned long INFINITE_TIME = ULONG_MAX; + +// VC60 workaround: using enums as template parameters causes problems +template +struct EnumToType +{ + static ENUM_TYPE ToEnum() {return (ENUM_TYPE)VALUE;} +}; + +enum ByteOrder {LITTLE_ENDIAN_ORDER = 0, BIG_ENDIAN_ORDER = 1}; +typedef EnumToType LittleEndian; +typedef EnumToType BigEndian; + +//! base class for all exceptions thrown by Crypto++ +class CRYPTOPP_DLL Exception : public std::exception +{ +public: + //! error types + enum ErrorType { + //! a method is not implemented + NOT_IMPLEMENTED, + //! invalid function argument + INVALID_ARGUMENT, + //! BufferedTransformation received a Flush(true) signal but can't flush buffers + CANNOT_FLUSH, + //! data integerity check (such as CRC or MAC) failed + DATA_INTEGRITY_CHECK_FAILED, + //! received input data that doesn't conform to expected format + INVALID_DATA_FORMAT, + //! error reading from input device or writing to output device + IO_ERROR, + //! some error not belong to any of the above categories + OTHER_ERROR + }; + + explicit Exception(ErrorType errorType, const std::string &s) : m_errorType(errorType), m_what(s) {} + virtual ~Exception() throw() {} + const char *what() const throw() {return (m_what.c_str());} + const std::string &GetWhat() const {return m_what;} + void SetWhat(const std::string &s) {m_what = s;} + ErrorType GetErrorType() const {return m_errorType;} + void SetErrorType(ErrorType errorType) {m_errorType = errorType;} + +private: + ErrorType m_errorType; + std::string m_what; +}; + +//! exception thrown when an invalid argument is detected +class CRYPTOPP_DLL InvalidArgument : public Exception +{ +public: + explicit InvalidArgument(const std::string &s) : Exception(INVALID_ARGUMENT, s) {} +}; + +//! exception thrown when input data is received that doesn't conform to expected format +class CRYPTOPP_DLL InvalidDataFormat : public Exception +{ +public: + explicit InvalidDataFormat(const std::string &s) : Exception(INVALID_DATA_FORMAT, s) {} +}; + +//! exception thrown by decryption filters when trying to decrypt an invalid ciphertext +class CRYPTOPP_DLL InvalidCiphertext : public InvalidDataFormat +{ +public: + explicit InvalidCiphertext(const std::string &s) : InvalidDataFormat(s) {} +}; + +//! exception thrown by a class if a non-implemented method is called +class CRYPTOPP_DLL NotImplemented : public Exception +{ +public: + explicit NotImplemented(const std::string &s) : Exception(NOT_IMPLEMENTED, s) {} +}; + +//! exception thrown by a class when Flush(true) is called but it can't completely flush its buffers +class CRYPTOPP_DLL CannotFlush : public Exception +{ +public: + explicit CannotFlush(const std::string &s) : Exception(CANNOT_FLUSH, s) {} +}; + +//! error reported by the operating system +class CRYPTOPP_DLL OS_Error : public Exception +{ +public: + OS_Error(ErrorType errorType, const std::string &s, const std::string& operation, int errorCode) + : Exception(errorType, s), m_operation(operation), m_errorCode(errorCode) {} + ~OS_Error() throw() {} + + // the operating system API that reported the error + const std::string & GetOperation() const {return m_operation;} + // the error code return by the operating system + int GetErrorCode() const {return m_errorCode;} + +protected: + std::string m_operation; + int m_errorCode; +}; + +//! used to return decoding results +struct CRYPTOPP_DLL DecodingResult +{ + explicit DecodingResult() : isValidCoding(false), messageLength(0) {} + explicit DecodingResult(size_t len) : isValidCoding(true), messageLength(len) {} + + bool operator==(const DecodingResult &rhs) const {return isValidCoding == rhs.isValidCoding && messageLength == rhs.messageLength;} + bool operator!=(const DecodingResult &rhs) const {return !operator==(rhs);} + + bool isValidCoding; + size_t messageLength; + +#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY + operator size_t() const {return isValidCoding ? messageLength : 0;} +#endif +}; + +//! interface for retrieving values given their names +/*! \note This class is used to safely pass a variable number of arbitrarily typed arguments to functions + and to read values from keys and crypto parameters. + \note To obtain an object that implements NameValuePairs for the purpose of parameter + passing, use the MakeParameters() function. + \note To get a value from NameValuePairs, you need to know the name and the type of the value. + Call GetValueNames() on a NameValuePairs object to obtain a list of value names that it supports. + Then look at the Name namespace documentation to see what the type of each value is, or + alternatively, call GetIntValue() with the value name, and if the type is not int, a + ValueTypeMismatch exception will be thrown and you can get the actual type from the exception object. +*/ +class CRYPTOPP_NO_VTABLE NameValuePairs +{ +public: + virtual ~NameValuePairs() {} + + //! exception thrown when trying to retrieve a value using a different type than expected + class CRYPTOPP_DLL ValueTypeMismatch : public InvalidArgument + { + public: + ValueTypeMismatch(const std::string &name, const std::type_info &stored, const std::type_info &retrieving) + : InvalidArgument("NameValuePairs: type mismatch for '" + name + "', stored '" + stored.name() + "', trying to retrieve '" + retrieving.name() + "'") + , m_stored(stored), m_retrieving(retrieving) {} + + const std::type_info & GetStoredTypeInfo() const {return m_stored;} + const std::type_info & GetRetrievingTypeInfo() const {return m_retrieving;} + + private: + const std::type_info &m_stored; + const std::type_info &m_retrieving; + }; + + //! get a copy of this object or a subobject of it + template + bool GetThisObject(T &object) const + { + return GetValue((std::string("ThisObject:")+typeid(T).name()).c_str(), object); + } + + //! get a pointer to this object, as a pointer to T + template + bool GetThisPointer(T *&p) const + { + return GetValue((std::string("ThisPointer:")+typeid(T).name()).c_str(), p); + } + + //! get a named value, returns true if the name exists + template + bool GetValue(const char *name, T &value) const + { + return GetVoidValue(name, typeid(T), &value); + } + + //! get a named value, returns the default if the name doesn't exist + template + T GetValueWithDefault(const char *name, T defaultValue) const + { + GetValue(name, defaultValue); + return defaultValue; + } + + //! get a list of value names that can be retrieved + CRYPTOPP_DLL std::string GetValueNames() const + {std::string result; GetValue("ValueNames", result); return result;} + + //! get a named value with type int + /*! used to ensure we don't accidentally try to get an unsigned int + or some other type when we mean int (which is the most common case) */ + CRYPTOPP_DLL bool GetIntValue(const char *name, int &value) const + {return GetValue(name, value);} + + //! get a named value with type int, with default + CRYPTOPP_DLL int GetIntValueWithDefault(const char *name, int defaultValue) const + {return GetValueWithDefault(name, defaultValue);} + + //! used by derived classes to check for type mismatch + CRYPTOPP_DLL static void CRYPTOPP_API ThrowIfTypeMismatch(const char *name, const std::type_info &stored, const std::type_info &retrieving) + {if (stored != retrieving) throw ValueTypeMismatch(name, stored, retrieving);} + + template + void GetRequiredParameter(const char *className, const char *name, T &value) const + { + if (!GetValue(name, value)) + throw InvalidArgument(std::string(className) + ": missing required parameter '" + name + "'"); + } + + CRYPTOPP_DLL void GetRequiredIntParameter(const char *className, const char *name, int &value) const + { + if (!GetIntValue(name, value)) + throw InvalidArgument(std::string(className) + ": missing required parameter '" + name + "'"); + } + + //! to be implemented by derived classes, users should use one of the above functions instead + CRYPTOPP_DLL virtual bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const =0; +}; + +//! namespace containing value name definitions +/*! value names, types and semantics: + + ThisObject:ClassName (ClassName, copy of this object or a subobject) + ThisPointer:ClassName (const ClassName *, pointer to this object or a subobject) +*/ +DOCUMENTED_NAMESPACE_BEGIN(Name) +// more names defined in argnames.h +DOCUMENTED_NAMESPACE_END + +//! empty set of name-value pairs +extern CRYPTOPP_DLL const NameValuePairs &g_nullNameValuePairs; + +// ******************************************************** + +//! interface for cloning objects, this is not implemented by most classes yet +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Clonable +{ +public: + virtual ~Clonable() {} + //! this is not implemented by most classes yet + virtual Clonable* Clone() const {throw NotImplemented("Clone() is not implemented yet.");} // TODO: make this =0 +}; + +//! interface for all crypto algorithms + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Algorithm : public Clonable +{ +public: + /*! When FIPS 140-2 compliance is enabled and checkSelfTestStatus == true, + this constructor throws SelfTestFailure if the self test hasn't been run or fails. */ + Algorithm(bool checkSelfTestStatus = true); + //! returns name of this algorithm, not universally implemented yet + virtual std::string AlgorithmName() const {return "unknown";} +}; + +//! keying interface for crypto algorithms that take byte strings as keys +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SimpleKeyingInterface +{ +public: + virtual ~SimpleKeyingInterface() {} + + //! returns smallest valid key length in bytes */ + virtual size_t MinKeyLength() const =0; + //! returns largest valid key length in bytes */ + virtual size_t MaxKeyLength() const =0; + //! returns default (recommended) key length in bytes */ + virtual size_t DefaultKeyLength() const =0; + + //! returns the smallest valid key length in bytes that is >= min(n, GetMaxKeyLength()) + virtual size_t GetValidKeyLength(size_t n) const =0; + + //! returns whether n is a valid key length + virtual bool IsValidKeyLength(size_t n) const + {return n == GetValidKeyLength(n);} + + //! set or reset the key of this object + /*! \param params is used to specify Rounds, BlockSize, etc. */ + virtual void SetKey(const byte *key, size_t length, const NameValuePairs ¶ms = g_nullNameValuePairs); + + //! calls SetKey() with an NameValuePairs object that just specifies "Rounds" + void SetKeyWithRounds(const byte *key, size_t length, int rounds); + + //! calls SetKey() with an NameValuePairs object that just specifies "IV" + void SetKeyWithIV(const byte *key, size_t length, const byte *iv, size_t ivLength); + + //! calls SetKey() with an NameValuePairs object that just specifies "IV" + void SetKeyWithIV(const byte *key, size_t length, const byte *iv) + {SetKeyWithIV(key, length, iv, IVSize());} + + enum IV_Requirement {UNIQUE_IV = 0, RANDOM_IV, UNPREDICTABLE_RANDOM_IV, INTERNALLY_GENERATED_IV, NOT_RESYNCHRONIZABLE}; + //! returns the minimal requirement for secure IVs + virtual IV_Requirement IVRequirement() const =0; + + //! returns whether this object can be resynchronized (i.e. supports initialization vectors) + /*! If this function returns true, and no IV is passed to SetKey() and CanUseStructuredIVs()==true, an IV of all 0's will be assumed. */ + bool IsResynchronizable() const {return IVRequirement() < NOT_RESYNCHRONIZABLE;} + //! returns whether this object can use random IVs (in addition to ones returned by GetNextIV) + bool CanUseRandomIVs() const {return IVRequirement() <= UNPREDICTABLE_RANDOM_IV;} + //! returns whether this object can use random but possibly predictable IVs (in addition to ones returned by GetNextIV) + bool CanUsePredictableIVs() const {return IVRequirement() <= RANDOM_IV;} + //! returns whether this object can use structured IVs, for example a counter (in addition to ones returned by GetNextIV) + bool CanUseStructuredIVs() const {return IVRequirement() <= UNIQUE_IV;} + + virtual unsigned int IVSize() const {throw NotImplemented(GetAlgorithm().AlgorithmName() + ": this object doesn't support resynchronization");} + //! returns default length of IVs accepted by this object + unsigned int DefaultIVLength() const {return IVSize();} + //! returns minimal length of IVs accepted by this object + virtual unsigned int MinIVLength() const {return IVSize();} + //! returns maximal length of IVs accepted by this object + virtual unsigned int MaxIVLength() const {return IVSize();} + //! resynchronize with an IV. ivLength=-1 means use IVSize() + virtual void Resynchronize(const byte *iv, int ivLength=-1) {throw NotImplemented(GetAlgorithm().AlgorithmName() + ": this object doesn't support resynchronization");} + //! get a secure IV for the next message + /*! This method should be called after you finish encrypting one message and are ready to start the next one. + After calling it, you must call SetKey() or Resynchronize() before using this object again. + This method is not implemented on decryption objects. */ + virtual void GetNextIV(RandomNumberGenerator &rng, byte *IV); + +protected: + virtual const Algorithm & GetAlgorithm() const =0; + virtual void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) =0; + + void ThrowIfInvalidKeyLength(size_t length); + void ThrowIfResynchronizable(); // to be called when no IV is passed + void ThrowIfInvalidIV(const byte *iv); // check for NULL IV if it can't be used + size_t ThrowIfInvalidIVLength(int size); + const byte * GetIVAndThrowIfInvalid(const NameValuePairs ¶ms, size_t &size); + inline void AssertValidKeyLength(size_t length) const + {assert(IsValidKeyLength(length));} +}; + +//! interface for the data processing part of block ciphers + +/*! Classes derived from BlockTransformation are block ciphers + in ECB mode (for example the DES::Encryption class), which are stateless. + These classes should not be used directly, but only in combination with + a mode class (see CipherModeDocumentation in modes.h). +*/ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockTransformation : public Algorithm +{ +public: + //! encrypt or decrypt inBlock, xor with xorBlock, and write to outBlock + virtual void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const =0; + + //! encrypt or decrypt one block + /*! \pre size of inBlock and outBlock == BlockSize() */ + void ProcessBlock(const byte *inBlock, byte *outBlock) const + {ProcessAndXorBlock(inBlock, NULL, outBlock);} + + //! encrypt or decrypt one block in place + void ProcessBlock(byte *inoutBlock) const + {ProcessAndXorBlock(inoutBlock, NULL, inoutBlock);} + + //! block size of the cipher in bytes + virtual unsigned int BlockSize() const =0; + + //! returns how inputs and outputs should be aligned for optimal performance + virtual unsigned int OptimalDataAlignment() const; + + //! returns true if this is a permutation (i.e. there is an inverse transformation) + virtual bool IsPermutation() const {return true;} + + //! returns true if this is an encryption object + virtual bool IsForwardTransformation() const =0; + + //! return number of blocks that can be processed in parallel, for bit-slicing implementations + virtual unsigned int OptimalNumberOfParallelBlocks() const {return 1;} + + enum {BT_InBlockIsCounter=1, BT_DontIncrementInOutPointers=2, BT_XorInput=4, BT_ReverseDirection=8} FlagsForAdvancedProcessBlocks; + + //! encrypt and xor blocks according to flags (see FlagsForAdvancedProcessBlocks) + /*! /note If BT_InBlockIsCounter is set, last byte of inBlocks may be modified. */ + virtual size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const; + + inline CipherDir GetCipherDirection() const {return IsForwardTransformation() ? ENCRYPTION : DECRYPTION;} +}; + +//! interface for the data processing part of stream ciphers + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE StreamTransformation : public Algorithm +{ +public: + //! return a reference to this object, + /*! This function is useful for passing a temporary StreamTransformation object to a + function that takes a non-const reference. */ + StreamTransformation& Ref() {return *this;} + + //! returns block size, if input must be processed in blocks, otherwise 1 + virtual unsigned int MandatoryBlockSize() const {return 1;} + + //! returns the input block size that is most efficient for this cipher + /*! \note optimal input length is n * OptimalBlockSize() - GetOptimalBlockSizeUsed() for any n > 0 */ + virtual unsigned int OptimalBlockSize() const {return MandatoryBlockSize();} + //! returns how much of the current block is used up + virtual unsigned int GetOptimalBlockSizeUsed() const {return 0;} + + //! returns how input should be aligned for optimal performance + virtual unsigned int OptimalDataAlignment() const; + + //! encrypt or decrypt an array of bytes of specified length + /*! \note either inString == outString, or they don't overlap */ + virtual void ProcessData(byte *outString, const byte *inString, size_t length) =0; + + //! for ciphers where the last block of data is special, encrypt or decrypt the last block of data + /*! For now the only use of this function is for CBC-CTS mode. */ + virtual void ProcessLastBlock(byte *outString, const byte *inString, size_t length); + //! returns the minimum size of the last block, 0 indicating the last block is not special + virtual unsigned int MinLastBlockSize() const {return 0;} + + //! same as ProcessData(inoutString, inoutString, length) + inline void ProcessString(byte *inoutString, size_t length) + {ProcessData(inoutString, inoutString, length);} + //! same as ProcessData(outString, inString, length) + inline void ProcessString(byte *outString, const byte *inString, size_t length) + {ProcessData(outString, inString, length);} + //! implemented as {ProcessData(&input, &input, 1); return input;} + inline byte ProcessByte(byte input) + {ProcessData(&input, &input, 1); return input;} + + //! returns whether this cipher supports random access + virtual bool IsRandomAccess() const =0; + //! for random access ciphers, seek to an absolute position + virtual void Seek(lword n) + { + assert(!IsRandomAccess()); + throw NotImplemented("StreamTransformation: this object doesn't support random access"); + } + + //! returns whether this transformation is self-inverting (e.g. xor with a keystream) + virtual bool IsSelfInverting() const =0; + //! returns whether this is an encryption object + virtual bool IsForwardTransformation() const =0; +}; + +//! interface for hash functions and data processing part of MACs + +/*! HashTransformation objects are stateful. They are created in an initial state, + change state as Update() is called, and return to the initial + state when Final() is called. This interface allows a large message to + be hashed in pieces by calling Update() on each piece followed by + calling Final(). +*/ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE HashTransformation : public Algorithm +{ +public: + //! return a reference to this object, + /*! This function is useful for passing a temporary HashTransformation object to a + function that takes a non-const reference. */ + HashTransformation& Ref() {return *this;} + + //! process more input + virtual void Update(const byte *input, size_t length) =0; + + //! request space to write input into + virtual byte * CreateUpdateSpace(size_t &size) {size=0; return NULL;} + + //! compute hash for current message, then restart for a new message + /*! \pre size of digest == DigestSize(). */ + virtual void Final(byte *digest) + {TruncatedFinal(digest, DigestSize());} + + //! discard the current state, and restart with a new message + virtual void Restart() + {TruncatedFinal(NULL, 0);} + + //! size of the hash/digest/MAC returned by Final() + virtual unsigned int DigestSize() const =0; + + //! same as DigestSize() + unsigned int TagSize() const {return DigestSize();} + + + //! block size of underlying compression function, or 0 if not block based + virtual unsigned int BlockSize() const {return 0;} + + //! input to Update() should have length a multiple of this for optimal speed + virtual unsigned int OptimalBlockSize() const {return 1;} + + //! returns how input should be aligned for optimal performance + virtual unsigned int OptimalDataAlignment() const; + + //! use this if your input is in one piece and you don't want to call Update() and Final() separately + virtual void CalculateDigest(byte *digest, const byte *input, size_t length) + {Update(input, length); Final(digest);} + + //! verify that digest is a valid digest for the current message, then reinitialize the object + /*! Default implementation is to call Final() and do a bitwise comparison + between its output and digest. */ + virtual bool Verify(const byte *digest) + {return TruncatedVerify(digest, DigestSize());} + + //! use this if your input is in one piece and you don't want to call Update() and Verify() separately + virtual bool VerifyDigest(const byte *digest, const byte *input, size_t length) + {Update(input, length); return Verify(digest);} + + //! truncated version of Final() + virtual void TruncatedFinal(byte *digest, size_t digestSize) =0; + + //! truncated version of CalculateDigest() + virtual void CalculateTruncatedDigest(byte *digest, size_t digestSize, const byte *input, size_t length) + {Update(input, length); TruncatedFinal(digest, digestSize);} + + //! truncated version of Verify() + virtual bool TruncatedVerify(const byte *digest, size_t digestLength); + + //! truncated version of VerifyDigest() + virtual bool VerifyTruncatedDigest(const byte *digest, size_t digestLength, const byte *input, size_t length) + {Update(input, length); return TruncatedVerify(digest, digestLength);} + +protected: + void ThrowIfInvalidTruncatedSize(size_t size) const; +}; + +typedef HashTransformation HashFunction; + +//! interface for one direction (encryption or decryption) of a block cipher +/*! \note These objects usually should not be used directly. See BlockTransformation for more details. */ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockCipher : public SimpleKeyingInterface, public BlockTransformation +{ +protected: + const Algorithm & GetAlgorithm() const {return *this;} +}; + +//! interface for one direction (encryption or decryption) of a stream cipher or cipher mode +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SymmetricCipher : public SimpleKeyingInterface, public StreamTransformation +{ +protected: + const Algorithm & GetAlgorithm() const {return *this;} +}; + +//! interface for message authentication codes +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE MessageAuthenticationCode : public SimpleKeyingInterface, public HashTransformation +{ +protected: + const Algorithm & GetAlgorithm() const {return *this;} +}; + +//! interface for for one direction (encryption or decryption) of a stream cipher or block cipher mode with authentication +/*! The StreamTransformation part of this interface is used to encrypt/decrypt the data, and the MessageAuthenticationCode part of this + interface is used to input additional authenticated data (AAD, which is MAC'ed but not encrypted), and to generate/verify the MAC. */ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedSymmetricCipher : public MessageAuthenticationCode, public StreamTransformation +{ +public: + //! this indicates that a member function was called in the wrong state, for example trying to encrypt a message before having set the key or IV + class BadState : public Exception + { + public: + explicit BadState(const std::string &name, const char *message) : Exception(OTHER_ERROR, name + ": " + message) {} + explicit BadState(const std::string &name, const char *function, const char *state) : Exception(OTHER_ERROR, name + ": " + function + " was called before " + state) {} + }; + + //! the maximum length of AAD that can be input before the encrypted data + virtual lword MaxHeaderLength() const =0; + //! the maximum length of encrypted data + virtual lword MaxMessageLength() const =0; + //! the maximum length of AAD that can be input after the encrypted data + virtual lword MaxFooterLength() const {return 0;} + //! if this function returns true, SpecifyDataLengths() must be called before attempting to input data + /*! This is the case for some schemes, such as CCM. */ + virtual bool NeedsPrespecifiedDataLengths() const {return false;} + //! this function only needs to be called if NeedsPrespecifiedDataLengths() returns true + void SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength=0); + //! encrypt and generate MAC in one call. will truncate MAC if macSize < TagSize() + virtual void EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *message, size_t messageLength); + //! decrypt and verify MAC in one call, returning true iff MAC is valid. will assume MAC is truncated if macLength < TagSize() + virtual bool DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *ciphertext, size_t ciphertextLength); + + // redeclare this to avoid compiler ambiguity errors + virtual std::string AlgorithmName() const =0; + +protected: + const Algorithm & GetAlgorithm() const {return *static_cast(this);} + virtual void UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength) {} +}; + +#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY +typedef SymmetricCipher StreamCipher; +#endif + +//! interface for random number generators +/*! All return values are uniformly distributed over the range specified. +*/ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomNumberGenerator : public Algorithm +{ +public: + //! update RNG state with additional unpredictable values + virtual void IncorporateEntropy(const byte *input, size_t length) {throw NotImplemented("RandomNumberGenerator: IncorporateEntropy not implemented");} + + //! returns true if IncorporateEntropy is implemented + virtual bool CanIncorporateEntropy() const {return false;} + + //! generate new random byte and return it + virtual byte GenerateByte(); + + //! generate new random bit and return it + /*! Default implementation is to call GenerateByte() and return its lowest bit. */ + virtual unsigned int GenerateBit(); + + //! generate a random 32 bit word in the range min to max, inclusive + virtual word32 GenerateWord32(word32 a=0, word32 b=0xffffffffL); + + //! generate random array of bytes + virtual void GenerateBlock(byte *output, size_t size); + + //! generate and discard n bytes + virtual void DiscardBytes(size_t n); + + //! generate random bytes as input to a BufferedTransformation + virtual void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length); + + //! randomly shuffle the specified array, resulting permutation is uniformly distributed + template void Shuffle(IT begin, IT end) + { + for (; begin != end; ++begin) + std::iter_swap(begin, begin + GenerateWord32(0, end-begin-1)); + } + +#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY + byte GetByte() {return GenerateByte();} + unsigned int GetBit() {return GenerateBit();} + word32 GetLong(word32 a=0, word32 b=0xffffffffL) {return GenerateWord32(a, b);} + word16 GetShort(word16 a=0, word16 b=0xffff) {return (word16)GenerateWord32(a, b);} + void GetBlock(byte *output, size_t size) {GenerateBlock(output, size);} +#endif +}; + +//! returns a reference that can be passed to functions that ask for a RNG but doesn't actually use it +CRYPTOPP_DLL RandomNumberGenerator & CRYPTOPP_API NullRNG(); + +class WaitObjectContainer; +class CallStack; + +//! interface for objects that you can wait for + +class CRYPTOPP_NO_VTABLE Waitable +{ +public: + virtual ~Waitable() {} + + //! maximum number of wait objects that this object can return + virtual unsigned int GetMaxWaitObjectCount() const =0; + //! put wait objects into container + /*! \param callStack is used for tracing no wait loops, example: + something.GetWaitObjects(c, CallStack("my func after X", 0)); + - or in an outer GetWaitObjects() method that itself takes a callStack parameter: + innerThing.GetWaitObjects(c, CallStack("MyClass::GetWaitObjects at X", &callStack)); */ + virtual void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack) =0; + //! wait on this object + /*! same as creating an empty container, calling GetWaitObjects(), and calling Wait() on the container */ + bool Wait(unsigned long milliseconds, CallStack const& callStack); +}; + +//! the default channel for BufferedTransformation, equal to the empty string +extern CRYPTOPP_DLL const std::string DEFAULT_CHANNEL; + +//! channel for additional authenticated data, equal to "AAD" +extern CRYPTOPP_DLL const std::string AAD_CHANNEL; + +//! interface for buffered transformations + +/*! BufferedTransformation is a generalization of BlockTransformation, + StreamTransformation, and HashTransformation. + + A buffered transformation is an object that takes a stream of bytes + as input (this may be done in stages), does some computation on them, and + then places the result into an internal buffer for later retrieval. Any + partial result already in the output buffer is not modified by further + input. + + If a method takes a "blocking" parameter, and you + pass "false" for it, the method will return before all input has been processed if + the input cannot be processed without waiting (for network buffers to become available, for example). + In this case the method will return true + or a non-zero integer value. When this happens you must continue to call the method with the same + parameters until it returns false or zero, before calling any other method on it or + attached BufferedTransformation. The integer return value in this case is approximately + the number of bytes left to be processed, and can be used to implement a progress bar. + + For functions that take a "propagation" parameter, propagation != 0 means pass on the signal to attached + BufferedTransformation objects, with propagation decremented at each step until it reaches 0. + -1 means unlimited propagation. + + \nosubgrouping +*/ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BufferedTransformation : public Algorithm, public Waitable +{ +public: + // placed up here for CW8 + static const std::string &NULL_CHANNEL; // same as DEFAULT_CHANNEL, for backwards compatibility + + BufferedTransformation() : Algorithm(false) {} + + //! return a reference to this object + /*! This function is useful for passing a temporary BufferedTransformation object to a + function that takes a non-const reference. */ + BufferedTransformation& Ref() {return *this;} + + //! \name INPUT + //@{ + //! input a byte for processing + size_t Put(byte inByte, bool blocking=true) + {return Put(&inByte, 1, blocking);} + //! input multiple bytes + size_t Put(const byte *inString, size_t length, bool blocking=true) + {return Put2(inString, length, 0, blocking);} + + //! input a 16-bit word + size_t PutWord16(word16 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true); + //! input a 32-bit word + size_t PutWord32(word32 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true); + + //! request space which can be written into by the caller, and then used as input to Put() + /*! \param size is requested size (as a hint) for input, and size of the returned space for output */ + /*! \note The purpose of this method is to help avoid doing extra memory allocations. */ + virtual byte * CreatePutSpace(size_t &size) {size=0; return NULL;} + + virtual bool CanModifyInput() const {return false;} + + //! input multiple bytes that may be modified by callee + size_t PutModifiable(byte *inString, size_t length, bool blocking=true) + {return PutModifiable2(inString, length, 0, blocking);} + + bool MessageEnd(int propagation=-1, bool blocking=true) + {return !!Put2(NULL, 0, propagation < 0 ? -1 : propagation+1, blocking);} + size_t PutMessageEnd(const byte *inString, size_t length, int propagation=-1, bool blocking=true) + {return Put2(inString, length, propagation < 0 ? -1 : propagation+1, blocking);} + + //! input multiple bytes for blocking or non-blocking processing + /*! \param messageEnd means how many filters to signal MessageEnd to, including this one */ + virtual size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) =0; + //! input multiple bytes that may be modified by callee for blocking or non-blocking processing + /*! \param messageEnd means how many filters to signal MessageEnd to, including this one */ + virtual size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking) + {return Put2(inString, length, messageEnd, blocking);} + + //! thrown by objects that have not implemented nonblocking input processing + struct BlockingInputOnly : public NotImplemented + {BlockingInputOnly(const std::string &s) : NotImplemented(s + ": Nonblocking input is not implemented by this object.") {}}; + //@} + + //! \name WAITING + //@{ + unsigned int GetMaxWaitObjectCount() const; + void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack); + //@} + + //! \name SIGNALS + //@{ + virtual void IsolatedInitialize(const NameValuePairs ¶meters) {throw NotImplemented("BufferedTransformation: this object can't be reinitialized");} + virtual bool IsolatedFlush(bool hardFlush, bool blocking) =0; + virtual bool IsolatedMessageSeriesEnd(bool blocking) {return false;} + + //! initialize or reinitialize this object + virtual void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1); + //! flush buffered input and/or output + /*! \param hardFlush is used to indicate whether all data should be flushed + \note Hard flushes must be used with care. It means try to process and output everything, even if + there may not be enough data to complete the action. For example, hard flushing a HexDecoder would + cause an error if you do it after inputing an odd number of hex encoded characters. + For some types of filters, for example ZlibDecompressor, hard flushes can only + be done at "synchronization points". These synchronization points are positions in the data + stream that are created by hard flushes on the corresponding reverse filters, in this + example ZlibCompressor. This is useful when zlib compressed data is moved across a + network in packets and compression state is preserved across packets, as in the ssh2 protocol. + */ + virtual bool Flush(bool hardFlush, int propagation=-1, bool blocking=true); + //! mark end of a series of messages + /*! There should be a MessageEnd immediately before MessageSeriesEnd. */ + virtual bool MessageSeriesEnd(int propagation=-1, bool blocking=true); + + //! set propagation of automatically generated and transferred signals + /*! propagation == 0 means do not automaticly generate signals */ + virtual void SetAutoSignalPropagation(int propagation) {} + + //! + virtual int GetAutoSignalPropagation() const {return 0;} +public: + +#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY + void Close() {MessageEnd();} +#endif + //@} + + //! \name RETRIEVAL OF ONE MESSAGE + //@{ + //! returns number of bytes that is currently ready for retrieval + /*! All retrieval functions return the actual number of bytes + retrieved, which is the lesser of the request number and + MaxRetrievable(). */ + virtual lword MaxRetrievable() const; + + //! returns whether any bytes are currently ready for retrieval + virtual bool AnyRetrievable() const; + + //! try to retrieve a single byte + virtual size_t Get(byte &outByte); + //! try to retrieve multiple bytes + virtual size_t Get(byte *outString, size_t getMax); + + //! peek at the next byte without removing it from the output buffer + virtual size_t Peek(byte &outByte) const; + //! peek at multiple bytes without removing them from the output buffer + virtual size_t Peek(byte *outString, size_t peekMax) const; + + //! try to retrieve a 16-bit word + size_t GetWord16(word16 &value, ByteOrder order=BIG_ENDIAN_ORDER); + //! try to retrieve a 32-bit word + size_t GetWord32(word32 &value, ByteOrder order=BIG_ENDIAN_ORDER); + + //! try to peek at a 16-bit word + size_t PeekWord16(word16 &value, ByteOrder order=BIG_ENDIAN_ORDER) const; + //! try to peek at a 32-bit word + size_t PeekWord32(word32 &value, ByteOrder order=BIG_ENDIAN_ORDER) const; + + //! move transferMax bytes of the buffered output to target as input + lword TransferTo(BufferedTransformation &target, lword transferMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL) + {TransferTo2(target, transferMax, channel); return transferMax;} + + //! discard skipMax bytes from the output buffer + virtual lword Skip(lword skipMax=LWORD_MAX); + + //! copy copyMax bytes of the buffered output to target as input + lword CopyTo(BufferedTransformation &target, lword copyMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL) const + {return CopyRangeTo(target, 0, copyMax, channel);} + + //! copy copyMax bytes of the buffered output, starting at position (relative to current position), to target as input + lword CopyRangeTo(BufferedTransformation &target, lword position, lword copyMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL) const + {lword i = position; CopyRangeTo2(target, i, i+copyMax, channel); return i-position;} + +#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY + unsigned long MaxRetrieveable() const {return MaxRetrievable();} +#endif + //@} + + //! \name RETRIEVAL OF MULTIPLE MESSAGES + //@{ + //! + virtual lword TotalBytesRetrievable() const; + //! number of times MessageEnd() has been received minus messages retrieved or skipped + virtual unsigned int NumberOfMessages() const; + //! returns true if NumberOfMessages() > 0 + virtual bool AnyMessages() const; + //! start retrieving the next message + /*! + Returns false if no more messages exist or this message + is not completely retrieved. + */ + virtual bool GetNextMessage(); + //! skip count number of messages + virtual unsigned int SkipMessages(unsigned int count=UINT_MAX); + //! + unsigned int TransferMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL) + {TransferMessagesTo2(target, count, channel); return count;} + //! + unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL) const; + + //! + virtual void SkipAll(); + //! + void TransferAllTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL) + {TransferAllTo2(target, channel);} + //! + void CopyAllTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL) const; + + virtual bool GetNextMessageSeries() {return false;} + virtual unsigned int NumberOfMessagesInThisSeries() const {return NumberOfMessages();} + virtual unsigned int NumberOfMessageSeries() const {return 0;} + //@} + + //! \name NON-BLOCKING TRANSFER OF OUTPUT + //@{ + //! upon return, byteCount contains number of bytes that have finished being transfered, and returns the number of bytes left in the current transfer block + virtual size_t TransferTo2(BufferedTransformation &target, lword &byteCount, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) =0; + //! upon return, begin contains the start position of data yet to be finished copying, and returns the number of bytes left in the current transfer block + virtual size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const =0; + //! upon return, messageCount contains number of messages that have finished being transfered, and returns the number of bytes left in the current transfer block + size_t TransferMessagesTo2(BufferedTransformation &target, unsigned int &messageCount, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); + //! returns the number of bytes left in the current transfer block + size_t TransferAllTo2(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); + //@} + + //! \name CHANNELS + //@{ + struct NoChannelSupport : public NotImplemented + {NoChannelSupport(const std::string &name) : NotImplemented(name + ": this object doesn't support multiple channels") {}}; + struct InvalidChannelName : public InvalidArgument + {InvalidChannelName(const std::string &name, const std::string &channel) : InvalidArgument(name + ": unexpected channel name \"" + channel + "\"") {}}; + + size_t ChannelPut(const std::string &channel, byte inByte, bool blocking=true) + {return ChannelPut(channel, &inByte, 1, blocking);} + size_t ChannelPut(const std::string &channel, const byte *inString, size_t length, bool blocking=true) + {return ChannelPut2(channel, inString, length, 0, blocking);} + + size_t ChannelPutModifiable(const std::string &channel, byte *inString, size_t length, bool blocking=true) + {return ChannelPutModifiable2(channel, inString, length, 0, blocking);} + + size_t ChannelPutWord16(const std::string &channel, word16 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true); + size_t ChannelPutWord32(const std::string &channel, word32 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true); + + bool ChannelMessageEnd(const std::string &channel, int propagation=-1, bool blocking=true) + {return !!ChannelPut2(channel, NULL, 0, propagation < 0 ? -1 : propagation+1, blocking);} + size_t ChannelPutMessageEnd(const std::string &channel, const byte *inString, size_t length, int propagation=-1, bool blocking=true) + {return ChannelPut2(channel, inString, length, propagation < 0 ? -1 : propagation+1, blocking);} + + virtual byte * ChannelCreatePutSpace(const std::string &channel, size_t &size); + + virtual size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking); + virtual size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking); + + virtual bool ChannelFlush(const std::string &channel, bool hardFlush, int propagation=-1, bool blocking=true); + virtual bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true); + + virtual void SetRetrievalChannel(const std::string &channel); + //@} + + //! \name ATTACHMENT + /*! Some BufferedTransformation objects (e.g. Filter objects) + allow other BufferedTransformation objects to be attached. When + this is done, the first object instead of buffering its output, + sents that output to the attached object as input. The entire + attachment chain is deleted when the anchor object is destructed. + */ + //@{ + //! returns whether this object allows attachment + virtual bool Attachable() {return false;} + //! returns the object immediately attached to this object or NULL for no attachment + virtual BufferedTransformation *AttachedTransformation() {assert(!Attachable()); return 0;} + //! + virtual const BufferedTransformation *AttachedTransformation() const + {return const_cast(this)->AttachedTransformation();} + //! delete the current attachment chain and replace it with newAttachment + virtual void Detach(BufferedTransformation *newAttachment = 0) + {assert(!Attachable()); throw NotImplemented("BufferedTransformation: this object is not attachable");} + //! add newAttachment to the end of attachment chain + virtual void Attach(BufferedTransformation *newAttachment); + //@} + +protected: + static int DecrementPropagation(int propagation) + {return propagation != 0 ? propagation - 1 : 0;} + +private: + byte m_buf[4]; // for ChannelPutWord16 and ChannelPutWord32, to ensure buffer isn't deallocated before non-blocking operation completes +}; + +//! returns a reference to a BufferedTransformation object that discards all input +BufferedTransformation & TheBitBucket(); + +//! interface for crypto material, such as public and private keys, and crypto parameters + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CryptoMaterial : public NameValuePairs +{ +public: + //! exception thrown when invalid crypto material is detected + class CRYPTOPP_DLL InvalidMaterial : public InvalidDataFormat + { + public: + explicit InvalidMaterial(const std::string &s) : InvalidDataFormat(s) {} + }; + + //! assign values from source to this object + /*! \note This function can be used to create a public key from a private key. */ + virtual void AssignFrom(const NameValuePairs &source) =0; + + //! check this object for errors + /*! \param level denotes the level of thoroughness: + 0 - using this object won't cause a crash or exception (rng is ignored) + 1 - this object will probably function (encrypt, sign, etc.) correctly (but may not check for weak keys and such) + 2 - make sure this object will function correctly, and do reasonable security checks + 3 - do checks that may take a long time + \return true if the tests pass */ + virtual bool Validate(RandomNumberGenerator &rng, unsigned int level) const =0; + + //! throws InvalidMaterial if this object fails Validate() test + virtual void ThrowIfInvalid(RandomNumberGenerator &rng, unsigned int level) const + {if (!Validate(rng, level)) throw InvalidMaterial("CryptoMaterial: this object contains invalid values");} + +// virtual std::vector GetSupportedFormats(bool includeSaveOnly=false, bool includeLoadOnly=false); + + //! save key into a BufferedTransformation + virtual void Save(BufferedTransformation &bt) const + {throw NotImplemented("CryptoMaterial: this object does not support saving");} + + //! load key from a BufferedTransformation + /*! \throws KeyingErr if decode fails + \note Generally does not check that the key is valid. + Call ValidateKey() or ThrowIfInvalidKey() to check that. */ + virtual void Load(BufferedTransformation &bt) + {throw NotImplemented("CryptoMaterial: this object does not support loading");} + + //! \return whether this object supports precomputation + virtual bool SupportsPrecomputation() const {return false;} + //! do precomputation + /*! The exact semantics of Precompute() is varies, but + typically it means calculate a table of n objects + that can be used later to speed up computation. */ + virtual void Precompute(unsigned int n) + {assert(!SupportsPrecomputation()); throw NotImplemented("CryptoMaterial: this object does not support precomputation");} + //! retrieve previously saved precomputation + virtual void LoadPrecomputation(BufferedTransformation &storedPrecomputation) + {assert(!SupportsPrecomputation()); throw NotImplemented("CryptoMaterial: this object does not support precomputation");} + //! save precomputation for later use + virtual void SavePrecomputation(BufferedTransformation &storedPrecomputation) const + {assert(!SupportsPrecomputation()); throw NotImplemented("CryptoMaterial: this object does not support precomputation");} + + // for internal library use + void DoQuickSanityCheck() const {ThrowIfInvalid(NullRNG(), 0);} + +#if (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590) + // Sun Studio 11/CC 5.8 workaround: it generates incorrect code when casting to an empty virtual base class + char m_sunCCworkaround; +#endif +}; + +//! interface for generatable crypto material, such as private keys and crypto parameters + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE GeneratableCryptoMaterial : virtual public CryptoMaterial +{ +public: + //! generate a random key or crypto parameters + /*! \throws KeyingErr if algorithm parameters are invalid, or if a key can't be generated + (e.g., if this is a public key object) */ + virtual void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms = g_nullNameValuePairs) + {throw NotImplemented("GeneratableCryptoMaterial: this object does not support key/parameter generation");} + + //! calls the above function with a NameValuePairs object that just specifies "KeySize" + void GenerateRandomWithKeySize(RandomNumberGenerator &rng, unsigned int keySize); +}; + +//! interface for public keys + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PublicKey : virtual public CryptoMaterial +{ +}; + +//! interface for private keys + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PrivateKey : public GeneratableCryptoMaterial +{ +}; + +//! interface for crypto prameters + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CryptoParameters : public GeneratableCryptoMaterial +{ +}; + +//! interface for asymmetric algorithms + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AsymmetricAlgorithm : public Algorithm +{ +public: + //! returns a reference to the crypto material used by this object + virtual CryptoMaterial & AccessMaterial() =0; + //! returns a const reference to the crypto material used by this object + virtual const CryptoMaterial & GetMaterial() const =0; + + //! for backwards compatibility, calls AccessMaterial().Load(bt) + void BERDecode(BufferedTransformation &bt) + {AccessMaterial().Load(bt);} + //! for backwards compatibility, calls GetMaterial().Save(bt) + void DEREncode(BufferedTransformation &bt) const + {GetMaterial().Save(bt);} +}; + +//! interface for asymmetric algorithms using public keys + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PublicKeyAlgorithm : public AsymmetricAlgorithm +{ +public: + // VC60 workaround: no co-variant return type + CryptoMaterial & AccessMaterial() {return AccessPublicKey();} + const CryptoMaterial & GetMaterial() const {return GetPublicKey();} + + virtual PublicKey & AccessPublicKey() =0; + virtual const PublicKey & GetPublicKey() const {return const_cast(this)->AccessPublicKey();} +}; + +//! interface for asymmetric algorithms using private keys + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PrivateKeyAlgorithm : public AsymmetricAlgorithm +{ +public: + CryptoMaterial & AccessMaterial() {return AccessPrivateKey();} + const CryptoMaterial & GetMaterial() const {return GetPrivateKey();} + + virtual PrivateKey & AccessPrivateKey() =0; + virtual const PrivateKey & GetPrivateKey() const {return const_cast(this)->AccessPrivateKey();} +}; + +//! interface for key agreement algorithms + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE KeyAgreementAlgorithm : public AsymmetricAlgorithm +{ +public: + CryptoMaterial & AccessMaterial() {return AccessCryptoParameters();} + const CryptoMaterial & GetMaterial() const {return GetCryptoParameters();} + + virtual CryptoParameters & AccessCryptoParameters() =0; + virtual const CryptoParameters & GetCryptoParameters() const {return const_cast(this)->AccessCryptoParameters();} +}; + +//! interface for public-key encryptors and decryptors + +/*! This class provides an interface common to encryptors and decryptors + for querying their plaintext and ciphertext lengths. +*/ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_CryptoSystem +{ +public: + virtual ~PK_CryptoSystem() {} + + //! maximum length of plaintext for a given ciphertext length + /*! \note This function returns 0 if ciphertextLength is not valid (too long or too short). */ + virtual size_t MaxPlaintextLength(size_t ciphertextLength) const =0; + + //! calculate length of ciphertext given length of plaintext + /*! \note This function returns 0 if plaintextLength is not valid (too long). */ + virtual size_t CiphertextLength(size_t plaintextLength) const =0; + + //! this object supports the use of the parameter with the given name + /*! some possible parameter names: EncodingParameters, KeyDerivationParameters */ + virtual bool ParameterSupported(const char *name) const =0; + + //! return fixed ciphertext length, if one exists, otherwise return 0 + /*! \note "Fixed" here means length of ciphertext does not depend on length of plaintext. + It usually does depend on the key length. */ + virtual size_t FixedCiphertextLength() const {return 0;} + + //! return maximum plaintext length given the fixed ciphertext length, if one exists, otherwise return 0 + virtual size_t FixedMaxPlaintextLength() const {return 0;} + +#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY + size_t MaxPlainTextLength(size_t cipherTextLength) const {return MaxPlaintextLength(cipherTextLength);} + size_t CipherTextLength(size_t plainTextLength) const {return CiphertextLength(plainTextLength);} +#endif +}; + +//! interface for public-key encryptors +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Encryptor : public PK_CryptoSystem, public PublicKeyAlgorithm +{ +public: + //! exception thrown when trying to encrypt plaintext of invalid length + class CRYPTOPP_DLL InvalidPlaintextLength : public Exception + { + public: + InvalidPlaintextLength() : Exception(OTHER_ERROR, "PK_Encryptor: invalid plaintext length") {} + }; + + //! encrypt a byte string + /*! \pre CiphertextLength(plaintextLength) != 0 (i.e., plaintext isn't too long) + \pre size of ciphertext == CiphertextLength(plaintextLength) + */ + virtual void Encrypt(RandomNumberGenerator &rng, + const byte *plaintext, size_t plaintextLength, + byte *ciphertext, const NameValuePairs ¶meters = g_nullNameValuePairs) const =0; + + //! create a new encryption filter + /*! \note The caller is responsible for deleting the returned pointer. + \note Encoding parameters should be passed in the "EP" channel. + */ + virtual BufferedTransformation * CreateEncryptionFilter(RandomNumberGenerator &rng, + BufferedTransformation *attachment=NULL, const NameValuePairs ¶meters = g_nullNameValuePairs) const; +}; + +//! interface for public-key decryptors + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Decryptor : public PK_CryptoSystem, public PrivateKeyAlgorithm +{ +public: + //! decrypt a byte string, and return the length of plaintext + /*! \pre size of plaintext == MaxPlaintextLength(ciphertextLength) bytes. + \return the actual length of the plaintext, indication that decryption failed. + */ + virtual DecodingResult Decrypt(RandomNumberGenerator &rng, + const byte *ciphertext, size_t ciphertextLength, + byte *plaintext, const NameValuePairs ¶meters = g_nullNameValuePairs) const =0; + + //! create a new decryption filter + /*! \note caller is responsible for deleting the returned pointer + */ + virtual BufferedTransformation * CreateDecryptionFilter(RandomNumberGenerator &rng, + BufferedTransformation *attachment=NULL, const NameValuePairs ¶meters = g_nullNameValuePairs) const; + + //! decrypt a fixed size ciphertext + DecodingResult FixedLengthDecrypt(RandomNumberGenerator &rng, const byte *ciphertext, byte *plaintext, const NameValuePairs ¶meters = g_nullNameValuePairs) const + {return Decrypt(rng, ciphertext, FixedCiphertextLength(), plaintext, parameters);} +}; + +#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY +typedef PK_CryptoSystem PK_FixedLengthCryptoSystem; +typedef PK_Encryptor PK_FixedLengthEncryptor; +typedef PK_Decryptor PK_FixedLengthDecryptor; +#endif + +//! interface for public-key signers and verifiers + +/*! This class provides an interface common to signers and verifiers + for querying scheme properties. +*/ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_SignatureScheme +{ +public: + //! invalid key exception, may be thrown by any function in this class if the private or public key has a length that can't be used + class CRYPTOPP_DLL InvalidKeyLength : public Exception + { + public: + InvalidKeyLength(const std::string &message) : Exception(OTHER_ERROR, message) {} + }; + + //! key too short exception, may be thrown by any function in this class if the private or public key is too short to sign or verify anything + class CRYPTOPP_DLL KeyTooShort : public InvalidKeyLength + { + public: + KeyTooShort() : InvalidKeyLength("PK_Signer: key too short for this signature scheme") {} + }; + + virtual ~PK_SignatureScheme() {} + + //! signature length if it only depends on the key, otherwise 0 + virtual size_t SignatureLength() const =0; + + //! maximum signature length produced for a given length of recoverable message part + virtual size_t MaxSignatureLength(size_t recoverablePartLength = 0) const {return SignatureLength();} + + //! length of longest message that can be recovered, or 0 if this signature scheme does not support message recovery + virtual size_t MaxRecoverableLength() const =0; + + //! length of longest message that can be recovered from a signature of given length, or 0 if this signature scheme does not support message recovery + virtual size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const =0; + + //! requires a random number generator to sign + /*! if this returns false, NullRNG() can be passed to functions that take RandomNumberGenerator & */ + virtual bool IsProbabilistic() const =0; + + //! whether or not a non-recoverable message part can be signed + virtual bool AllowNonrecoverablePart() const =0; + + //! if this function returns true, during verification you must input the signature before the message, otherwise you can input it at anytime */ + virtual bool SignatureUpfront() const {return false;} + + //! whether you must input the recoverable part before the non-recoverable part during signing + virtual bool RecoverablePartFirst() const =0; +}; + +//! interface for accumulating messages to be signed or verified +/*! Only Update() should be called + on this class. No other functions inherited from HashTransformation should be called. +*/ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_MessageAccumulator : public HashTransformation +{ +public: + //! should not be called on PK_MessageAccumulator + unsigned int DigestSize() const + {throw NotImplemented("PK_MessageAccumulator: DigestSize() should not be called");} + //! should not be called on PK_MessageAccumulator + void TruncatedFinal(byte *digest, size_t digestSize) + {throw NotImplemented("PK_MessageAccumulator: TruncatedFinal() should not be called");} +}; + +//! interface for public-key signers + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Signer : public PK_SignatureScheme, public PrivateKeyAlgorithm +{ +public: + //! create a new HashTransformation to accumulate the message to be signed + virtual PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const =0; + + virtual void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const =0; + + //! sign and delete messageAccumulator (even in case of exception thrown) + /*! \pre size of signature == MaxSignatureLength() + \return actual signature length + */ + virtual size_t Sign(RandomNumberGenerator &rng, PK_MessageAccumulator *messageAccumulator, byte *signature) const; + + //! sign and restart messageAccumulator + /*! \pre size of signature == MaxSignatureLength() + \return actual signature length + */ + virtual size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart=true) const =0; + + //! sign a message + /*! \pre size of signature == MaxSignatureLength() + \return actual signature length + */ + virtual size_t SignMessage(RandomNumberGenerator &rng, const byte *message, size_t messageLen, byte *signature) const; + + //! sign a recoverable message + /*! \pre size of signature == MaxSignatureLength(recoverableMessageLength) + \return actual signature length + */ + virtual size_t SignMessageWithRecovery(RandomNumberGenerator &rng, const byte *recoverableMessage, size_t recoverableMessageLength, + const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, byte *signature) const; +}; + +//! interface for public-key signature verifiers +/*! The Recover* functions throw NotImplemented if the signature scheme does not support + message recovery. + The Verify* functions throw InvalidDataFormat if the scheme does support message + recovery and the signature contains a non-empty recoverable message part. The + Recovery* functions should be used in that case. +*/ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Verifier : public PK_SignatureScheme, public PublicKeyAlgorithm +{ +public: + //! create a new HashTransformation to accumulate the message to be verified + virtual PK_MessageAccumulator * NewVerificationAccumulator() const =0; + + //! input signature into a message accumulator + virtual void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const =0; + + //! check whether messageAccumulator contains a valid signature and message, and delete messageAccumulator (even in case of exception thrown) + virtual bool Verify(PK_MessageAccumulator *messageAccumulator) const; + + //! check whether messageAccumulator contains a valid signature and message, and restart messageAccumulator + virtual bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const =0; + + //! check whether input signature is a valid signature for input message + virtual bool VerifyMessage(const byte *message, size_t messageLen, + const byte *signature, size_t signatureLength) const; + + //! recover a message from its signature + /*! \pre size of recoveredMessage == MaxRecoverableLengthFromSignatureLength(signatureLength) + */ + virtual DecodingResult Recover(byte *recoveredMessage, PK_MessageAccumulator *messageAccumulator) const; + + //! recover a message from its signature + /*! \pre size of recoveredMessage == MaxRecoverableLengthFromSignatureLength(signatureLength) + */ + virtual DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const =0; + + //! recover a message from its signature + /*! \pre size of recoveredMessage == MaxRecoverableLengthFromSignatureLength(signatureLength) + */ + virtual DecodingResult RecoverMessage(byte *recoveredMessage, + const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, + const byte *signature, size_t signatureLength) const; +}; + +//! interface for domains of simple key agreement protocols + +/*! A key agreement domain is a set of parameters that must be shared + by two parties in a key agreement protocol, along with the algorithms + for generating key pairs and deriving agreed values. +*/ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SimpleKeyAgreementDomain : public KeyAgreementAlgorithm +{ +public: + //! return length of agreed value produced + virtual unsigned int AgreedValueLength() const =0; + //! return length of private keys in this domain + virtual unsigned int PrivateKeyLength() const =0; + //! return length of public keys in this domain + virtual unsigned int PublicKeyLength() const =0; + //! generate private key + /*! \pre size of privateKey == PrivateKeyLength() */ + virtual void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const =0; + //! generate public key + /*! \pre size of publicKey == PublicKeyLength() */ + virtual void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const =0; + //! generate private/public key pair + /*! \note equivalent to calling GeneratePrivateKey() and then GeneratePublicKey() */ + virtual void GenerateKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const; + //! derive agreed value from your private key and couterparty's public key, return false in case of failure + /*! \note If you have previously validated the public key, use validateOtherPublicKey=false to save time. + \pre size of agreedValue == AgreedValueLength() + \pre length of privateKey == PrivateKeyLength() + \pre length of otherPublicKey == PublicKeyLength() + */ + virtual bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const =0; + +#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY + bool ValidateDomainParameters(RandomNumberGenerator &rng) const + {return GetCryptoParameters().Validate(rng, 2);} +#endif +}; + +//! interface for domains of authenticated key agreement protocols + +/*! In an authenticated key agreement protocol, each party has two + key pairs. The long-lived key pair is called the static key pair, + and the short-lived key pair is called the ephemeral key pair. +*/ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedKeyAgreementDomain : public KeyAgreementAlgorithm +{ +public: + //! return length of agreed value produced + virtual unsigned int AgreedValueLength() const =0; + + //! return length of static private keys in this domain + virtual unsigned int StaticPrivateKeyLength() const =0; + //! return length of static public keys in this domain + virtual unsigned int StaticPublicKeyLength() const =0; + //! generate static private key + /*! \pre size of privateKey == PrivateStaticKeyLength() */ + virtual void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const =0; + //! generate static public key + /*! \pre size of publicKey == PublicStaticKeyLength() */ + virtual void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const =0; + //! generate private/public key pair + /*! \note equivalent to calling GenerateStaticPrivateKey() and then GenerateStaticPublicKey() */ + virtual void GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const; + + //! return length of ephemeral private keys in this domain + virtual unsigned int EphemeralPrivateKeyLength() const =0; + //! return length of ephemeral public keys in this domain + virtual unsigned int EphemeralPublicKeyLength() const =0; + //! generate ephemeral private key + /*! \pre size of privateKey == PrivateEphemeralKeyLength() */ + virtual void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const =0; + //! generate ephemeral public key + /*! \pre size of publicKey == PublicEphemeralKeyLength() */ + virtual void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const =0; + //! generate private/public key pair + /*! \note equivalent to calling GenerateEphemeralPrivateKey() and then GenerateEphemeralPublicKey() */ + virtual void GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const; + + //! derive agreed value from your private keys and couterparty's public keys, return false in case of failure + /*! \note The ephemeral public key will always be validated. + If you have previously validated the static public key, use validateStaticOtherPublicKey=false to save time. + \pre size of agreedValue == AgreedValueLength() + \pre length of staticPrivateKey == StaticPrivateKeyLength() + \pre length of ephemeralPrivateKey == EphemeralPrivateKeyLength() + \pre length of staticOtherPublicKey == StaticPublicKeyLength() + \pre length of ephemeralOtherPublicKey == EphemeralPublicKeyLength() + */ + virtual bool Agree(byte *agreedValue, + const byte *staticPrivateKey, const byte *ephemeralPrivateKey, + const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey, + bool validateStaticOtherPublicKey=true) const =0; + +#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY + bool ValidateDomainParameters(RandomNumberGenerator &rng) const + {return GetCryptoParameters().Validate(rng, 2);} +#endif +}; + +// interface for password authenticated key agreement protocols, not implemented yet +#if 0 +//! interface for protocol sessions +/*! The methods should be called in the following order: + + InitializeSession(rng, parameters); // or call initialize method in derived class + while (true) + { + if (OutgoingMessageAvailable()) + { + length = GetOutgoingMessageLength(); + GetOutgoingMessage(message); + ; // send outgoing message + } + + if (LastMessageProcessed()) + break; + + ; // receive incoming message + ProcessIncomingMessage(message); + } + ; // call methods in derived class to obtain result of protocol session +*/ +class ProtocolSession +{ +public: + //! exception thrown when an invalid protocol message is processed + class ProtocolError : public Exception + { + public: + ProtocolError(ErrorType errorType, const std::string &s) : Exception(errorType, s) {} + }; + + //! exception thrown when a function is called unexpectedly + /*! for example calling ProcessIncomingMessage() when ProcessedLastMessage() == true */ + class UnexpectedMethodCall : public Exception + { + public: + UnexpectedMethodCall(const std::string &s) : Exception(OTHER_ERROR, s) {} + }; + + ProtocolSession() : m_rng(NULL), m_throwOnProtocolError(true), m_validState(false) {} + virtual ~ProtocolSession() {} + + virtual void InitializeSession(RandomNumberGenerator &rng, const NameValuePairs ¶meters) =0; + + bool GetThrowOnProtocolError() const {return m_throwOnProtocolError;} + void SetThrowOnProtocolError(bool throwOnProtocolError) {m_throwOnProtocolError = throwOnProtocolError;} + + bool HasValidState() const {return m_validState;} + + virtual bool OutgoingMessageAvailable() const =0; + virtual unsigned int GetOutgoingMessageLength() const =0; + virtual void GetOutgoingMessage(byte *message) =0; + + virtual bool LastMessageProcessed() const =0; + virtual void ProcessIncomingMessage(const byte *message, unsigned int messageLength) =0; + +protected: + void HandleProtocolError(Exception::ErrorType errorType, const std::string &s) const; + void CheckAndHandleInvalidState() const; + void SetValidState(bool valid) {m_validState = valid;} + + RandomNumberGenerator *m_rng; + +private: + bool m_throwOnProtocolError, m_validState; +}; + +class KeyAgreementSession : public ProtocolSession +{ +public: + virtual unsigned int GetAgreedValueLength() const =0; + virtual void GetAgreedValue(byte *agreedValue) const =0; +}; + +class PasswordAuthenticatedKeyAgreementSession : public KeyAgreementSession +{ +public: + void InitializePasswordAuthenticatedKeyAgreementSession(RandomNumberGenerator &rng, + const byte *myId, unsigned int myIdLength, + const byte *counterPartyId, unsigned int counterPartyIdLength, + const byte *passwordOrVerifier, unsigned int passwordOrVerifierLength); +}; + +class PasswordAuthenticatedKeyAgreementDomain : public KeyAgreementAlgorithm +{ +public: + //! return whether the domain parameters stored in this object are valid + virtual bool ValidateDomainParameters(RandomNumberGenerator &rng) const + {return GetCryptoParameters().Validate(rng, 2);} + + virtual unsigned int GetPasswordVerifierLength(const byte *password, unsigned int passwordLength) const =0; + virtual void GeneratePasswordVerifier(RandomNumberGenerator &rng, const byte *userId, unsigned int userIdLength, const byte *password, unsigned int passwordLength, byte *verifier) const =0; + + enum RoleFlags {CLIENT=1, SERVER=2, INITIATOR=4, RESPONDER=8}; + + virtual bool IsValidRole(unsigned int role) =0; + virtual PasswordAuthenticatedKeyAgreementSession * CreateProtocolSession(unsigned int role) const =0; +}; +#endif + +//! BER Decode Exception Class, may be thrown during an ASN1 BER decode operation +class CRYPTOPP_DLL BERDecodeErr : public InvalidArgument +{ +public: + BERDecodeErr() : InvalidArgument("BER decode error") {} + BERDecodeErr(const std::string &s) : InvalidArgument(s) {} +}; + +//! interface for encoding and decoding ASN1 objects +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1Object +{ +public: + virtual ~ASN1Object() {} + //! decode this object from a BufferedTransformation, using BER (Basic Encoding Rules) + virtual void BERDecode(BufferedTransformation &bt) =0; + //! encode this object into a BufferedTransformation, using DER (Distinguished Encoding Rules) + virtual void DEREncode(BufferedTransformation &bt) const =0; + //! encode this object into a BufferedTransformation, using BER + /*! this may be useful if DEREncode() would be too inefficient */ + virtual void BEREncode(BufferedTransformation &bt) const {DEREncode(bt);} +}; + +#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY +typedef PK_SignatureScheme PK_SignatureSystem; +typedef SimpleKeyAgreementDomain PK_SimpleKeyAgreementDomain; +typedef AuthenticatedKeyAgreementDomain PK_AuthenticatedKeyAgreementDomain; +#endif + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/cryptlib.vcproj b/src-cryptopp/cryptlib.vcproj new file mode 100644 index 0000000..210401e --- /dev/null +++ b/src-cryptopp/cryptlib.vcproj @@ -0,0 +1,9580 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src-cryptopp/cryptlib_bds.bdsproj b/src-cryptopp/cryptlib_bds.bdsproj new file mode 100644 index 0000000..9b9c7b2 --- /dev/null +++ b/src-cryptopp/cryptlib_bds.bdsproj @@ -0,0 +1,377 @@ + + + + + + + + + + + + cryptlib_bds.cpp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + False + False + 1 + 0 + 0 + 0 + False + False + False + False + False + 1033 + 1252 + + + + + 1.0.0.0 + + + + + + 1.0.0.0 + + + + + + + + + False + + + + + + + False + + False + + True + False + + + + + + + + + + + diff --git a/src-cryptopp/cryptopp.rc b/src-cryptopp/cryptopp.rc new file mode 100644 index 0000000..c33dc98 --- /dev/null +++ b/src-cryptopp/cryptopp.rc @@ -0,0 +1,104 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 5,6,0,0 + PRODUCTVERSION 5,6,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "free crypto library, more information available at www.cryptopp.com" + VALUE "CompanyName", "Wei Dai" + VALUE "FileDescription", "Crypto++® Library DLL" + VALUE "FileVersion", "5, 6, 0, 0" + VALUE "InternalName", "cryptopp" + VALUE "LegalCopyright", "Copyright © 1995-2009 by Wei Dai" + VALUE "LegalTrademarks", "Crypto++®" + VALUE "OriginalFilename", "cryptopp.dll" + VALUE "ProductName", "Crypto++® Library" + VALUE "ProductVersion", "5, 6, 0, 0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src-cryptopp/des.cpp b/src-cryptopp/des.cpp new file mode 100644 index 0000000..a6e0c51 --- /dev/null +++ b/src-cryptopp/des.cpp @@ -0,0 +1,449 @@ +// des.cpp - modified by Wei Dai from Phil Karn's des.c +// The original code and all modifications are in the public domain. + +/* + * This is a major rewrite of my old public domain DES code written + * circa 1987, which in turn borrowed heavily from Jim Gillogly's 1977 + * public domain code. I pretty much kept my key scheduling code, but + * the actual encrypt/decrypt routines are taken from from Richard + * Outerbridge's DES code as printed in Schneier's "Applied Cryptography." + * + * This code is in the public domain. I would appreciate bug reports and + * enhancements. + * + * Phil Karn KA9Q, karn@unix.ka9q.ampr.org, August 1994. + */ + +#include "pch.h" +#include "misc.h" +#include "des.h" + +NAMESPACE_BEGIN(CryptoPP) + +typedef BlockGetAndPut Block; + +// Richard Outerbridge's initial permutation algorithm +/* +inline void IPERM(word32 &left, word32 &right) +{ + word32 work; + + work = ((left >> 4) ^ right) & 0x0f0f0f0f; + right ^= work; + left ^= work << 4; + work = ((left >> 16) ^ right) & 0xffff; + right ^= work; + left ^= work << 16; + work = ((right >> 2) ^ left) & 0x33333333; + left ^= work; + right ^= (work << 2); + work = ((right >> 8) ^ left) & 0xff00ff; + left ^= work; + right ^= (work << 8); + right = rotl(right, 1); + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = rotl(left, 1); +} +inline void FPERM(word32 &left, word32 &right) +{ + word32 work; + + right = rotr(right, 1); + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = rotr(left, 1); + work = ((left >> 8) ^ right) & 0xff00ff; + right ^= work; + left ^= work << 8; + work = ((left >> 2) ^ right) & 0x33333333; + right ^= work; + left ^= work << 2; + work = ((right >> 16) ^ left) & 0xffff; + left ^= work; + right ^= work << 16; + work = ((right >> 4) ^ left) & 0x0f0f0f0f; + left ^= work; + right ^= work << 4; +} +*/ + +// Wei Dai's modification to Richard Outerbridge's initial permutation +// algorithm, this one is faster if you have access to rotate instructions +// (like in MSVC) +static inline void IPERM(word32 &left, word32 &right) +{ + word32 work; + + right = rotlFixed(right, 4U); + work = (left ^ right) & 0xf0f0f0f0; + left ^= work; + right = rotrFixed(right^work, 20U); + work = (left ^ right) & 0xffff0000; + left ^= work; + right = rotrFixed(right^work, 18U); + work = (left ^ right) & 0x33333333; + left ^= work; + right = rotrFixed(right^work, 6U); + work = (left ^ right) & 0x00ff00ff; + left ^= work; + right = rotlFixed(right^work, 9U); + work = (left ^ right) & 0xaaaaaaaa; + left = rotlFixed(left^work, 1U); + right ^= work; +} + +static inline void FPERM(word32 &left, word32 &right) +{ + word32 work; + + right = rotrFixed(right, 1U); + work = (left ^ right) & 0xaaaaaaaa; + right ^= work; + left = rotrFixed(left^work, 9U); + work = (left ^ right) & 0x00ff00ff; + right ^= work; + left = rotlFixed(left^work, 6U); + work = (left ^ right) & 0x33333333; + right ^= work; + left = rotlFixed(left^work, 18U); + work = (left ^ right) & 0xffff0000; + right ^= work; + left = rotlFixed(left^work, 20U); + work = (left ^ right) & 0xf0f0f0f0; + right ^= work; + left = rotrFixed(left^work, 4U); +} + +void DES::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) +{ + AssertValidKeyLength(length); + + RawSetKey(GetCipherDirection(), userKey); +} + +#ifndef CRYPTOPP_IMPORTS + +/* Tables defined in the Data Encryption Standard documents + * Three of these tables, the initial permutation, the final + * permutation and the expansion operator, are regular enough that + * for speed, we hard-code them. They're here for reference only. + * Also, the S and P boxes are used by a separate program, gensp.c, + * to build the combined SP box, Spbox[]. They're also here just + * for reference. + */ +#ifdef notdef +/* initial permutation IP */ +static byte ip[] = { + 58, 50, 42, 34, 26, 18, 10, 2, + 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, + 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, + 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, + 63, 55, 47, 39, 31, 23, 15, 7 +}; + +/* final permutation IP^-1 */ +static byte fp[] = { + 40, 8, 48, 16, 56, 24, 64, 32, + 39, 7, 47, 15, 55, 23, 63, 31, + 38, 6, 46, 14, 54, 22, 62, 30, + 37, 5, 45, 13, 53, 21, 61, 29, + 36, 4, 44, 12, 52, 20, 60, 28, + 35, 3, 43, 11, 51, 19, 59, 27, + 34, 2, 42, 10, 50, 18, 58, 26, + 33, 1, 41, 9, 49, 17, 57, 25 +}; +/* expansion operation matrix */ +static byte ei[] = { + 32, 1, 2, 3, 4, 5, + 4, 5, 6, 7, 8, 9, + 8, 9, 10, 11, 12, 13, + 12, 13, 14, 15, 16, 17, + 16, 17, 18, 19, 20, 21, + 20, 21, 22, 23, 24, 25, + 24, 25, 26, 27, 28, 29, + 28, 29, 30, 31, 32, 1 +}; +/* The (in)famous S-boxes */ +static byte sbox[8][64] = { + /* S1 */ + 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, + 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, + 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, + 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13, + + /* S2 */ + 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, + 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, + 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, + 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9, + + /* S3 */ + 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, + 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, + 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12, + + /* S4 */ + 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, + 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, + 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, + 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14, + + /* S5 */ + 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, + 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, + 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, + 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3, + + /* S6 */ + 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, + 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, + 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, + 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13, + + /* S7 */ + 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, + 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, + 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, + 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12, + + /* S8 */ + 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, + 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, + 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, + 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 +}; + +/* 32-bit permutation function P used on the output of the S-boxes */ +static byte p32i[] = { + 16, 7, 20, 21, + 29, 12, 28, 17, + 1, 15, 23, 26, + 5, 18, 31, 10, + 2, 8, 24, 14, + 32, 27, 3, 9, + 19, 13, 30, 6, + 22, 11, 4, 25 +}; +#endif + +/* permuted choice table (key) */ +static const byte pc1[] = { + 57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4 +}; + +/* number left rotations of pc1 */ +static const byte totrot[] = { + 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 +}; + +/* permuted choice key (table) */ +static const byte pc2[] = { + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 +}; + +/* End of DES-defined tables */ + +/* bit 0 is left-most in byte */ +static const int bytebit[] = { + 0200,0100,040,020,010,04,02,01 +}; + +/* Set key (initialize key schedule array) */ +void RawDES::RawSetKey(CipherDir dir, const byte *key) +{ + SecByteBlock buffer(56+56+8); + byte *const pc1m=buffer; /* place to modify pc1 into */ + byte *const pcr=pc1m+56; /* place to rotate pc1 into */ + byte *const ks=pcr+56; + register int i,j,l; + int m; + + for (j=0; j<56; j++) { /* convert pc1 to bits of key */ + l=pc1[j]-1; /* integer bit location */ + m = l & 07; /* find bit */ + pc1m[j]=(key[l>>3] & /* find which key byte l is in */ + bytebit[m]) /* and which bit of that byte */ + ? 1 : 0; /* and store 1-bit result */ + } + for (i=0; i<16; i++) { /* key chunk for each iteration */ + memset(ks,0,8); /* Clear key schedule */ + for (j=0; j<56; j++) /* rotate pc1 the right amount */ + pcr[j] = pc1m[(l=j+totrot[i])<(j<28? 28 : 56) ? l: l-28]; + /* rotate left and right halves independently */ + for (j=0; j<48; j++){ /* select bits individually */ + /* check bit that goes to ks[j] */ + if (pcr[pc2[j]-1]){ + /* mask it in if it's there */ + l= j % 6; + ks[j/6] |= bytebit[l] >> 2; + } + } + /* Now convert to odd/even interleaved form for use in F */ + k[2*i] = ((word32)ks[0] << 24) + | ((word32)ks[2] << 16) + | ((word32)ks[4] << 8) + | ((word32)ks[6]); + k[2*i+1] = ((word32)ks[1] << 24) + | ((word32)ks[3] << 16) + | ((word32)ks[5] << 8) + | ((word32)ks[7]); + } + + if (dir==DECRYPTION) // reverse key schedule order + for (i=0; i<16; i+=2) + { + std::swap(k[i], k[32-2-i]); + std::swap(k[i+1], k[32-1-i]); + } +} + +void RawDES::RawProcessBlock(word32 &l_, word32 &r_) const +{ + word32 l = l_, r = r_; + const word32 *kptr=k; + + for (unsigned i=0; i<8; i++) + { + word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0]; + l ^= Spbox[6][(work) & 0x3f] + ^ Spbox[4][(work >> 8) & 0x3f] + ^ Spbox[2][(work >> 16) & 0x3f] + ^ Spbox[0][(work >> 24) & 0x3f]; + work = r ^ kptr[4*i+1]; + l ^= Spbox[7][(work) & 0x3f] + ^ Spbox[5][(work >> 8) & 0x3f] + ^ Spbox[3][(work >> 16) & 0x3f] + ^ Spbox[1][(work >> 24) & 0x3f]; + + work = rotrFixed(l, 4U) ^ kptr[4*i+2]; + r ^= Spbox[6][(work) & 0x3f] + ^ Spbox[4][(work >> 8) & 0x3f] + ^ Spbox[2][(work >> 16) & 0x3f] + ^ Spbox[0][(work >> 24) & 0x3f]; + work = l ^ kptr[4*i+3]; + r ^= Spbox[7][(work) & 0x3f] + ^ Spbox[5][(work >> 8) & 0x3f] + ^ Spbox[3][(work >> 16) & 0x3f] + ^ Spbox[1][(work >> 24) & 0x3f]; + } + + l_ = l; r_ = r; +} + +void DES_EDE2::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) +{ + AssertValidKeyLength(length); + + m_des1.RawSetKey(GetCipherDirection(), userKey); + m_des2.RawSetKey(ReverseCipherDir(GetCipherDirection()), userKey+8); +} + +void DES_EDE2::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 l,r; + Block::Get(inBlock)(l)(r); + IPERM(l,r); + m_des1.RawProcessBlock(l, r); + m_des2.RawProcessBlock(r, l); + m_des1.RawProcessBlock(l, r); + FPERM(l,r); + Block::Put(xorBlock, outBlock)(r)(l); +} + +void DES_EDE3::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) +{ + AssertValidKeyLength(length); + + m_des1.RawSetKey(GetCipherDirection(), userKey + (IsForwardTransformation() ? 0 : 16)); + m_des2.RawSetKey(ReverseCipherDir(GetCipherDirection()), userKey + 8); + m_des3.RawSetKey(GetCipherDirection(), userKey + (IsForwardTransformation() ? 16 : 0)); +} + +void DES_EDE3::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 l,r; + Block::Get(inBlock)(l)(r); + IPERM(l,r); + m_des1.RawProcessBlock(l, r); + m_des2.RawProcessBlock(r, l); + m_des3.RawProcessBlock(l, r); + FPERM(l,r); + Block::Put(xorBlock, outBlock)(r)(l); +} + +#endif // #ifndef CRYPTOPP_IMPORTS + +static inline bool CheckParity(byte b) +{ + unsigned int a = b ^ (b >> 4); + return ((a ^ (a>>1) ^ (a>>2) ^ (a>>3)) & 1) == 1; +} + +bool DES::CheckKeyParityBits(const byte *key) +{ + for (unsigned int i=0; i<8; i++) + if (!CheckParity(key[i])) + return false; + return true; +} + +void DES::CorrectKeyParityBits(byte *key) +{ + for (unsigned int i=0; i<8; i++) + if (!CheckParity(key[i])) + key[i] ^= 1; +} + +// Encrypt or decrypt a block of data in ECB mode +void DES::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 l,r; + Block::Get(inBlock)(l)(r); + IPERM(l,r); + RawProcessBlock(l, r); + FPERM(l,r); + Block::Put(xorBlock, outBlock)(r)(l); +} + +void DES_XEX3::Base::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &) +{ + AssertValidKeyLength(length); + + if (!m_des.get()) + m_des.reset(new DES::Encryption); + + memcpy(m_x1, key + (IsForwardTransformation() ? 0 : 16), BLOCKSIZE); + m_des->RawSetKey(GetCipherDirection(), key + 8); + memcpy(m_x3, key + (IsForwardTransformation() ? 16 : 0), BLOCKSIZE); +} + +void DES_XEX3::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + xorbuf(outBlock, inBlock, m_x1, BLOCKSIZE); + m_des->ProcessAndXorBlock(outBlock, xorBlock, outBlock); + xorbuf(outBlock, m_x3, BLOCKSIZE); +} + +NAMESPACE_END diff --git a/src-cryptopp/des.h b/src-cryptopp/des.h new file mode 100644 index 0000000..62f6288 --- /dev/null +++ b/src-cryptopp/des.h @@ -0,0 +1,144 @@ +#ifndef CRYPTOPP_DES_H +#define CRYPTOPP_DES_H + +/** \file +*/ + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +class CRYPTOPP_DLL RawDES +{ +public: + void RawSetKey(CipherDir direction, const byte *userKey); + void RawProcessBlock(word32 &l, word32 &r) const; + +protected: + static const word32 Spbox[8][64]; + + FixedSizeSecBlock k; +}; + +//! _ +struct DES_Info : public FixedBlockSize<8>, public FixedKeyLength<8> +{ + // disable DES in DLL version by not exporting this function + static const char * StaticAlgorithmName() {return "DES";} +}; + +/// DES +/*! The DES implementation in Crypto++ ignores the parity bits + (the least significant bits of each byte) in the key. However + you can use CheckKeyParityBits() and CorrectKeyParityBits() to + check or correct the parity bits if you wish. */ +class DES : public DES_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl, public RawDES + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + +public: + //! check DES key parity bits + static bool CheckKeyParityBits(const byte *key); + //! correct DES key parity bits + static void CorrectKeyParityBits(byte *key); + + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +//! _ +struct DES_EDE2_Info : public FixedBlockSize<8>, public FixedKeyLength<16> +{ + CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return "DES-EDE2";} +}; + +/// DES-EDE2 +class DES_EDE2 : public DES_EDE2_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + protected: + RawDES m_des1, m_des2; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +//! _ +struct DES_EDE3_Info : public FixedBlockSize<8>, public FixedKeyLength<24> +{ + CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return "DES-EDE3";} +}; + +/// DES-EDE3 +class DES_EDE3 : public DES_EDE3_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + protected: + RawDES m_des1, m_des2, m_des3; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +//! _ +struct DES_XEX3_Info : public FixedBlockSize<8>, public FixedKeyLength<24> +{ + static const char *StaticAlgorithmName() {return "DES-XEX3";} +}; + +/// DES-XEX3, AKA DESX +class DES_XEX3 : public DES_XEX3_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + protected: + FixedSizeSecBlock m_x1, m_x3; + // VS2005 workaround: calling modules compiled with /clr gets unresolved external symbol DES::Base::ProcessAndXorBlock + // if we use DES::Encryption here directly without value_ptr. + value_ptr m_des; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef DES::Encryption DESEncryption; +typedef DES::Decryption DESDecryption; + +typedef DES_EDE2::Encryption DES_EDE2_Encryption; +typedef DES_EDE2::Decryption DES_EDE2_Decryption; + +typedef DES_EDE3::Encryption DES_EDE3_Encryption; +typedef DES_EDE3::Decryption DES_EDE3_Decryption; + +typedef DES_XEX3::Encryption DES_XEX3_Encryption; +typedef DES_XEX3::Decryption DES_XEX3_Decryption; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/dessp.cpp b/src-cryptopp/dessp.cpp new file mode 100644 index 0000000..49ed1d2 --- /dev/null +++ b/src-cryptopp/dessp.cpp @@ -0,0 +1,95 @@ +// This file is mostly generated by Phil Karn's gensp.c + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "des.h" + +NAMESPACE_BEGIN(CryptoPP) + +// VC60 workaround: gives a C4786 warning without this function +// when runtime lib is set to multithread debug DLL +// even though warning 4786 is disabled! +void DES_VC60Workaround() +{ +} + +const word32 RawDES::Spbox[8][64] = { +{ +0x01010400,0x00000000,0x00010000,0x01010404, 0x01010004,0x00010404,0x00000004,0x00010000, +0x00000400,0x01010400,0x01010404,0x00000400, 0x01000404,0x01010004,0x01000000,0x00000004, +0x00000404,0x01000400,0x01000400,0x00010400, 0x00010400,0x01010000,0x01010000,0x01000404, +0x00010004,0x01000004,0x01000004,0x00010004, 0x00000000,0x00000404,0x00010404,0x01000000, +0x00010000,0x01010404,0x00000004,0x01010000, 0x01010400,0x01000000,0x01000000,0x00000400, +0x01010004,0x00010000,0x00010400,0x01000004, 0x00000400,0x00000004,0x01000404,0x00010404, +0x01010404,0x00010004,0x01010000,0x01000404, 0x01000004,0x00000404,0x00010404,0x01010400, +0x00000404,0x01000400,0x01000400,0x00000000, 0x00010004,0x00010400,0x00000000,0x01010004}, +{ +0x80108020,0x80008000,0x00008000,0x00108020, 0x00100000,0x00000020,0x80100020,0x80008020, +0x80000020,0x80108020,0x80108000,0x80000000, 0x80008000,0x00100000,0x00000020,0x80100020, +0x00108000,0x00100020,0x80008020,0x00000000, 0x80000000,0x00008000,0x00108020,0x80100000, +0x00100020,0x80000020,0x00000000,0x00108000, 0x00008020,0x80108000,0x80100000,0x00008020, +0x00000000,0x00108020,0x80100020,0x00100000, 0x80008020,0x80100000,0x80108000,0x00008000, +0x80100000,0x80008000,0x00000020,0x80108020, 0x00108020,0x00000020,0x00008000,0x80000000, +0x00008020,0x80108000,0x00100000,0x80000020, 0x00100020,0x80008020,0x80000020,0x00100020, +0x00108000,0x00000000,0x80008000,0x00008020, 0x80000000,0x80100020,0x80108020,0x00108000}, +{ +0x00000208,0x08020200,0x00000000,0x08020008, 0x08000200,0x00000000,0x00020208,0x08000200, +0x00020008,0x08000008,0x08000008,0x00020000, 0x08020208,0x00020008,0x08020000,0x00000208, +0x08000000,0x00000008,0x08020200,0x00000200, 0x00020200,0x08020000,0x08020008,0x00020208, +0x08000208,0x00020200,0x00020000,0x08000208, 0x00000008,0x08020208,0x00000200,0x08000000, +0x08020200,0x08000000,0x00020008,0x00000208, 0x00020000,0x08020200,0x08000200,0x00000000, +0x00000200,0x00020008,0x08020208,0x08000200, 0x08000008,0x00000200,0x00000000,0x08020008, +0x08000208,0x00020000,0x08000000,0x08020208, 0x00000008,0x00020208,0x00020200,0x08000008, +0x08020000,0x08000208,0x00000208,0x08020000, 0x00020208,0x00000008,0x08020008,0x00020200}, +{ +0x00802001,0x00002081,0x00002081,0x00000080, 0x00802080,0x00800081,0x00800001,0x00002001, +0x00000000,0x00802000,0x00802000,0x00802081, 0x00000081,0x00000000,0x00800080,0x00800001, +0x00000001,0x00002000,0x00800000,0x00802001, 0x00000080,0x00800000,0x00002001,0x00002080, +0x00800081,0x00000001,0x00002080,0x00800080, 0x00002000,0x00802080,0x00802081,0x00000081, +0x00800080,0x00800001,0x00802000,0x00802081, 0x00000081,0x00000000,0x00000000,0x00802000, +0x00002080,0x00800080,0x00800081,0x00000001, 0x00802001,0x00002081,0x00002081,0x00000080, +0x00802081,0x00000081,0x00000001,0x00002000, 0x00800001,0x00002001,0x00802080,0x00800081, +0x00002001,0x00002080,0x00800000,0x00802001, 0x00000080,0x00800000,0x00002000,0x00802080}, +{ +0x00000100,0x02080100,0x02080000,0x42000100, 0x00080000,0x00000100,0x40000000,0x02080000, +0x40080100,0x00080000,0x02000100,0x40080100, 0x42000100,0x42080000,0x00080100,0x40000000, +0x02000000,0x40080000,0x40080000,0x00000000, 0x40000100,0x42080100,0x42080100,0x02000100, +0x42080000,0x40000100,0x00000000,0x42000000, 0x02080100,0x02000000,0x42000000,0x00080100, +0x00080000,0x42000100,0x00000100,0x02000000, 0x40000000,0x02080000,0x42000100,0x40080100, +0x02000100,0x40000000,0x42080000,0x02080100, 0x40080100,0x00000100,0x02000000,0x42080000, +0x42080100,0x00080100,0x42000000,0x42080100, 0x02080000,0x00000000,0x40080000,0x42000000, +0x00080100,0x02000100,0x40000100,0x00080000, 0x00000000,0x40080000,0x02080100,0x40000100}, +{ +0x20000010,0x20400000,0x00004000,0x20404010, 0x20400000,0x00000010,0x20404010,0x00400000, +0x20004000,0x00404010,0x00400000,0x20000010, 0x00400010,0x20004000,0x20000000,0x00004010, +0x00000000,0x00400010,0x20004010,0x00004000, 0x00404000,0x20004010,0x00000010,0x20400010, +0x20400010,0x00000000,0x00404010,0x20404000, 0x00004010,0x00404000,0x20404000,0x20000000, +0x20004000,0x00000010,0x20400010,0x00404000, 0x20404010,0x00400000,0x00004010,0x20000010, +0x00400000,0x20004000,0x20000000,0x00004010, 0x20000010,0x20404010,0x00404000,0x20400000, +0x00404010,0x20404000,0x00000000,0x20400010, 0x00000010,0x00004000,0x20400000,0x00404010, +0x00004000,0x00400010,0x20004010,0x00000000, 0x20404000,0x20000000,0x00400010,0x20004010}, +{ +0x00200000,0x04200002,0x04000802,0x00000000, 0x00000800,0x04000802,0x00200802,0x04200800, +0x04200802,0x00200000,0x00000000,0x04000002, 0x00000002,0x04000000,0x04200002,0x00000802, +0x04000800,0x00200802,0x00200002,0x04000800, 0x04000002,0x04200000,0x04200800,0x00200002, +0x04200000,0x00000800,0x00000802,0x04200802, 0x00200800,0x00000002,0x04000000,0x00200800, +0x04000000,0x00200800,0x00200000,0x04000802, 0x04000802,0x04200002,0x04200002,0x00000002, +0x00200002,0x04000000,0x04000800,0x00200000, 0x04200800,0x00000802,0x00200802,0x04200800, +0x00000802,0x04000002,0x04200802,0x04200000, 0x00200800,0x00000000,0x00000002,0x04200802, +0x00000000,0x00200802,0x04200000,0x00000800, 0x04000002,0x04000800,0x00000800,0x00200002}, +{ +0x10001040,0x00001000,0x00040000,0x10041040, 0x10000000,0x10001040,0x00000040,0x10000000, +0x00040040,0x10040000,0x10041040,0x00041000, 0x10041000,0x00041040,0x00001000,0x00000040, +0x10040000,0x10000040,0x10001000,0x00001040, 0x00041000,0x00040040,0x10040040,0x10041000, +0x00001040,0x00000000,0x00000000,0x10040040, 0x10000040,0x10001000,0x00041040,0x00040000, +0x00041040,0x00040000,0x10041000,0x00001000, 0x00000040,0x10040040,0x00001000,0x00041040, +0x10001000,0x00000040,0x10000040,0x10040000, 0x10040040,0x10000000,0x00040000,0x10001040, +0x00000000,0x10041040,0x00040040,0x10000040, 0x10040000,0x10001000,0x10001040,0x00000000, +0x10041040,0x00041000,0x00041000,0x00001040, 0x00001040,0x00040040,0x10000000,0x10041000} +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/dh.h b/src-cryptopp/dh.h new file mode 100644 index 0000000..10e8d14 --- /dev/null +++ b/src-cryptopp/dh.h @@ -0,0 +1,99 @@ +#ifndef CRYPTOPP_DH_H +#define CRYPTOPP_DH_H + +/** \file +*/ + +#include "gfpcrypt.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! , +template +class DH_Domain : public DL_SimpleKeyAgreementDomainBase +{ + typedef DL_SimpleKeyAgreementDomainBase Base; + +public: + typedef GROUP_PARAMETERS GroupParameters; + typedef typename GroupParameters::Element Element; + typedef DL_KeyAgreementAlgorithm_DH DH_Algorithm; + typedef DH_Domain Domain; + + DH_Domain() {} + + DH_Domain(const GroupParameters ¶ms) + : m_groupParameters(params) {} + + DH_Domain(BufferedTransformation &bt) + {m_groupParameters.BERDecode(bt);} + + template + DH_Domain(RandomNumberGenerator &v1, const T2 &v2) + {m_groupParameters.Initialize(v1, v2);} + + template + DH_Domain(RandomNumberGenerator &v1, const T2 &v2, const T3 &v3) + {m_groupParameters.Initialize(v1, v2, v3);} + + template + DH_Domain(RandomNumberGenerator &v1, const T2 &v2, const T3 &v3, const T4 &v4) + {m_groupParameters.Initialize(v1, v2, v3, v4);} + + template + DH_Domain(const T1 &v1, const T2 &v2) + {m_groupParameters.Initialize(v1, v2);} + + template + DH_Domain(const T1 &v1, const T2 &v2, const T3 &v3) + {m_groupParameters.Initialize(v1, v2, v3);} + + template + DH_Domain(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) + {m_groupParameters.Initialize(v1, v2, v3, v4);} + + const GroupParameters & GetGroupParameters() const {return m_groupParameters;} + GroupParameters & AccessGroupParameters() {return m_groupParameters;} + + void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const + { + Base::GeneratePublicKey(rng, privateKey, publicKey); + + if (FIPS_140_2_ComplianceEnabled()) + { + SecByteBlock privateKey2(this->PrivateKeyLength()); + this->GeneratePrivateKey(rng, privateKey2); + + SecByteBlock publicKey2(this->PublicKeyLength()); + Base::GeneratePublicKey(rng, privateKey2, publicKey2); + + SecByteBlock agreedValue(this->AgreedValueLength()), agreedValue2(this->AgreedValueLength()); + bool agreed1 = this->Agree(agreedValue, privateKey, publicKey2); + bool agreed2 = this->Agree(agreedValue2, privateKey2, publicKey); + + if (!agreed1 || !agreed2 || agreedValue != agreedValue2) + throw SelfTestFailure(this->AlgorithmName() + ": pairwise consistency test failed"); + } + } + + static std::string CRYPTOPP_API StaticAlgorithmName() + {return GroupParameters::StaticAlgorithmNamePrefix() + DH_Algorithm::StaticAlgorithmName();} + std::string AlgorithmName() const {return StaticAlgorithmName();} + +private: + const DL_KeyAgreementAlgorithm & GetKeyAgreementAlgorithm() const + {return Singleton().Ref();} + DL_GroupParameters & AccessAbstractGroupParameters() + {return m_groupParameters;} + + GroupParameters m_groupParameters; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS DH_Domain; + +//! Diffie-Hellman in GF(p) with key validation +typedef DH_Domain DH; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/dll.cpp b/src-cryptopp/dll.cpp new file mode 100644 index 0000000..2b4ef7a --- /dev/null +++ b/src-cryptopp/dll.cpp @@ -0,0 +1,146 @@ +// dll.cpp - written and placed in the public domain by Wei Dai + +#define CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES +#define CRYPTOPP_DEFAULT_NO_DLL + +#include "dll.h" +#pragma warning(default: 4660) + +#if defined(CRYPTOPP_EXPORTS) && defined(CRYPTOPP_WIN32_AVAILABLE) +#include +#endif + +#ifndef CRYPTOPP_IMPORTS + +NAMESPACE_BEGIN(CryptoPP) + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14}; +template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x2d,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x04,0x05,0x00,0x04,0x1c}; +template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20}; +template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30}; +template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40}; +template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte EMSA2HashId::id = 0x33; +template<> const byte EMSA2HashId::id = 0x38; +template<> const byte EMSA2HashId::id = 0x34; +template<> const byte EMSA2HashId::id = 0x36; +template<> const byte EMSA2HashId::id = 0x35; + +NAMESPACE_END + +#endif + +#ifdef CRYPTOPP_EXPORTS + +USING_NAMESPACE(CryptoPP) + +#if !(defined(_MSC_VER) && (_MSC_VER < 1300)) +using std::set_new_handler; +#endif + +static PNew s_pNew = NULL; +static PDelete s_pDelete = NULL; + +static void * New (size_t size) +{ + void *p; + while (!(p = malloc(size))) + CallNewHandler(); + + return p; +} + +static void SetNewAndDeleteFunctionPointers() +{ + void *p = NULL; + HMODULE hModule = NULL; + MEMORY_BASIC_INFORMATION mbi; + + while (true) + { + VirtualQuery(p, &mbi, sizeof(mbi)); + + if (p >= (char *)mbi.BaseAddress + mbi.RegionSize) + break; + + p = (char *)mbi.BaseAddress + mbi.RegionSize; + + if (!mbi.AllocationBase || mbi.AllocationBase == hModule) + continue; + + hModule = HMODULE(mbi.AllocationBase); + + PGetNewAndDelete pGetNewAndDelete = (PGetNewAndDelete)GetProcAddress(hModule, "GetNewAndDeleteForCryptoPP"); + if (pGetNewAndDelete) + { + pGetNewAndDelete(s_pNew, s_pDelete); + return; + } + + PSetNewAndDelete pSetNewAndDelete = (PSetNewAndDelete)GetProcAddress(hModule, "SetNewAndDeleteFromCryptoPP"); + if (pSetNewAndDelete) + { + s_pNew = &New; + s_pDelete = &free; + pSetNewAndDelete(s_pNew, s_pDelete, &set_new_handler); + return; + } + } + + // try getting these directly using mangled names of new and delete operators + + hModule = GetModuleHandle("msvcrtd"); + if (!hModule) + hModule = GetModuleHandle("msvcrt"); + if (hModule) + { + // 32-bit versions + s_pNew = (PNew)GetProcAddress(hModule, "??2@YAPAXI@Z"); + s_pDelete = (PDelete)GetProcAddress(hModule, "??3@YAXPAX@Z"); + if (s_pNew && s_pDelete) + return; + + // 64-bit versions + s_pNew = (PNew)GetProcAddress(hModule, "??2@YAPEAX_K@Z"); + s_pDelete = (PDelete)GetProcAddress(hModule, "??3@YAXPEAX@Z"); + if (s_pNew && s_pDelete) + return; + } + + OutputDebugString("Crypto++ was not able to obtain new and delete function pointers.\n"); + throw 0; +} + +void * operator new (size_t size) +{ + if (!s_pNew) + SetNewAndDeleteFunctionPointers(); + + return s_pNew(size); +} + +void operator delete (void * p) +{ + s_pDelete(p); +} + +void * operator new [] (size_t size) +{ + return operator new (size); +} + +void operator delete [] (void * p) +{ + operator delete (p); +} + +#endif // #ifdef CRYPTOPP_EXPORTS diff --git a/src-cryptopp/dll.h b/src-cryptopp/dll.h new file mode 100644 index 0000000..5e42d46 --- /dev/null +++ b/src-cryptopp/dll.h @@ -0,0 +1,71 @@ +#ifndef CRYPTOPP_DLL_H +#define CRYPTOPP_DLL_H + +#if !defined(CRYPTOPP_IMPORTS) && !defined(CRYPTOPP_EXPORTS) && !defined(CRYPTOPP_DEFAULT_NO_DLL) +#ifdef CRYPTOPP_CONFIG_H +#error To use the DLL version of Crypto++, this file must be included before any other Crypto++ header files. +#endif +#define CRYPTOPP_IMPORTS +#endif + +#include "aes.h" +#include "cbcmac.h" +#include "ccm.h" +#include "cmac.h" +#include "channels.h" +#include "des.h" +#include "dh.h" +#include "dsa.h" +#include "ec2n.h" +#include "eccrypto.h" +#include "ecp.h" +#include "files.h" +#include "fips140.h" +#include "gcm.h" +#include "hex.h" +#include "hmac.h" +#include "modes.h" +#include "mqueue.h" +#include "nbtheory.h" +#include "osrng.h" +#include "pkcspad.h" +#include "pssr.h" +#include "randpool.h" +#include "rsa.h" +#include "rw.h" +#include "sha.h" +#include "skipjack.h" +#include "trdlocal.h" + +#ifdef CRYPTOPP_IMPORTS + +#ifdef _DLL +// cause CRT DLL to be initialized before Crypto++ so that we can use malloc and free during DllMain() +#ifdef NDEBUG +#pragma comment(lib, "msvcrt") +#else +#pragma comment(lib, "msvcrtd") +#endif +#endif + +#pragma comment(lib, "cryptopp") + +#endif // #ifdef CRYPTOPP_IMPORTS + +#include // for new_handler + +NAMESPACE_BEGIN(CryptoPP) + +#if !(defined(_MSC_VER) && (_MSC_VER < 1300)) +using std::new_handler; +#endif + +typedef void * (CRYPTOPP_API * PNew)(size_t); +typedef void (CRYPTOPP_API * PDelete)(void *); +typedef void (CRYPTOPP_API * PGetNewAndDelete)(PNew &, PDelete &); +typedef new_handler (CRYPTOPP_API * PSetNewHandler)(new_handler); +typedef void (CRYPTOPP_API * PSetNewAndDelete)(PNew, PDelete, PSetNewHandler); + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/dlltest.dsp b/src-cryptopp/dlltest.dsp new file mode 100644 index 0000000..b980b7f --- /dev/null +++ b/src-cryptopp/dlltest.dsp @@ -0,0 +1,90 @@ +# Microsoft Developer Studio Project File - Name="dlltest" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=dlltest - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "dlltest.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "dlltest.mak" CFG="dlltest - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "dlltest - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "dlltest - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "dlltest - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "dlltest___Win32_Release" +# PROP BASE Intermediate_Dir "dlltest___Win32_Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "dlltest___Win32_Release" +# PROP Intermediate_Dir "dlltest___Win32_Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /Gz /MT /W3 /GR /GX /Zi /O1 /Ob2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "CRYPTOPP_DLL_ONLY" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 /nologo /subsystem:console /map /debug /machine:I386 /out:"DLL_Release/dlltest.exe" /libpath:"DLL_Release" + +!ELSEIF "$(CFG)" == "dlltest - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "dlltest___Win32_Debug" +# PROP BASE Intermediate_Dir "dlltest___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "dlltest___Win32_Debug" +# PROP Intermediate_Dir "dlltest___Win32_Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /Gz /MTd /W3 /Gm /GR /GX /Zi /Oi /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "CRYPTOPP_DLL_ONLY" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /out:"DLL_Debug/dlltest.exe" /pdbtype:sept /libpath:"DLL_Debug" + +!ENDIF + +# Begin Target + +# Name "dlltest - Win32 Release" +# Name "dlltest - Win32 Debug" +# Begin Source File + +SOURCE=.\dlltest.cpp +# End Source File +# End Target +# End Project diff --git a/src-cryptopp/dlltest.vcproj b/src-cryptopp/dlltest.vcproj new file mode 100644 index 0000000..0bf11ff --- /dev/null +++ b/src-cryptopp/dlltest.vcproj @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src-cryptopp/dsa.cpp b/src-cryptopp/dsa.cpp new file mode 100644 index 0000000..ac9e1f8 --- /dev/null +++ b/src-cryptopp/dsa.cpp @@ -0,0 +1,119 @@ +// dsa.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "dsa.h" +#include "nbtheory.h" + +NAMESPACE_BEGIN(CryptoPP) + +size_t DSAConvertSignatureFormat(byte *buffer, size_t bufferSize, DSASignatureFormat toFormat, const byte *signature, size_t signatureLen, DSASignatureFormat fromFormat) +{ + Integer r, s; + StringStore store(signature, signatureLen); + ArraySink sink(buffer, bufferSize); + + switch (fromFormat) + { + case DSA_P1363: + r.Decode(store, signatureLen/2); + s.Decode(store, signatureLen/2); + break; + case DSA_DER: + { + BERSequenceDecoder seq(store); + r.BERDecode(seq); + s.BERDecode(seq); + seq.MessageEnd(); + break; + } + case DSA_OPENPGP: + r.OpenPGPDecode(store); + s.OpenPGPDecode(store); + break; + } + + switch (toFormat) + { + case DSA_P1363: + r.Encode(sink, bufferSize/2); + s.Encode(sink, bufferSize/2); + break; + case DSA_DER: + { + DERSequenceEncoder seq(sink); + r.DEREncode(seq); + s.DEREncode(seq); + seq.MessageEnd(); + break; + } + case DSA_OPENPGP: + r.OpenPGPEncode(sink); + s.OpenPGPEncode(sink); + break; + } + + return (size_t)sink.TotalPutLength(); +} + +bool DSA::GeneratePrimes(const byte *seedIn, unsigned int g, int &counter, + Integer &p, unsigned int L, Integer &q, bool useInputCounterValue) +{ + assert(g%8 == 0); + + SHA sha; + SecByteBlock seed(seedIn, g/8); + SecByteBlock U(SHA::DIGESTSIZE); + SecByteBlock temp(SHA::DIGESTSIZE); + SecByteBlock W(((L-1)/160+1) * SHA::DIGESTSIZE); + const int n = (L-1) / 160; + const int b = (L-1) % 160; + Integer X; + + sha.CalculateDigest(U, seed, g/8); + + for (int i=g/8-1, carry=true; i>=0 && carry; i--) + carry=!++seed[i]; + + sha.CalculateDigest(temp, seed, g/8); + xorbuf(U, temp, SHA::DIGESTSIZE); + + U[0] |= 0x80; + U[SHA::DIGESTSIZE-1] |= 1; + q.Decode(U, SHA::DIGESTSIZE); + + if (!IsPrime(q)) + return false; + + int counterEnd = useInputCounterValue ? counter+1 : 4096; + + for (int c = 0; c < counterEnd; c++) + { + for (int k=0; k<=n; k++) + { + for (int i=g/8-1, carry=true; i>=0 && carry; i--) + carry=!++seed[i]; + if (!useInputCounterValue || c == counter) + sha.CalculateDigest(W+(n-k)*SHA::DIGESTSIZE, seed, g/8); + } + if (!useInputCounterValue || c == counter) + { + W[SHA::DIGESTSIZE - 1 - b/8] |= 0x80; + X.Decode(W + SHA::DIGESTSIZE - 1 - b/8, L/8); + p = X-((X % (2*q))-1); + + if (p.GetBit(L-1) && IsPrime(p)) + { + counter = c; + return true; + } + } + } + return false; +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/dsa.h b/src-cryptopp/dsa.h new file mode 100644 index 0000000..6ae0387 --- /dev/null +++ b/src-cryptopp/dsa.h @@ -0,0 +1,35 @@ +#ifndef CRYPTOPP_DSA_H +#define CRYPTOPP_DSA_H + +/** \file +*/ + +#include "gfpcrypt.h" + +NAMESPACE_BEGIN(CryptoPP) + +/*! The DSA signature format used by Crypto++ is as defined by IEEE P1363. + Java uses the DER format, and OpenPGP uses the OpenPGP format. */ +enum DSASignatureFormat {DSA_P1363, DSA_DER, DSA_OPENPGP}; +/** This function converts between these formats, and returns length of signature in the target format. + If toFormat == DSA_P1363, bufferSize must equal publicKey.SignatureLength() */ +size_t DSAConvertSignatureFormat(byte *buffer, size_t bufferSize, DSASignatureFormat toFormat, + const byte *signature, size_t signatureLen, DSASignatureFormat fromFormat); + +#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY + +typedef DSA::Signer DSAPrivateKey; +typedef DSA::Verifier DSAPublicKey; + +const int MIN_DSA_PRIME_LENGTH = DSA::MIN_PRIME_LENGTH; +const int MAX_DSA_PRIME_LENGTH = DSA::MAX_PRIME_LENGTH; +const int DSA_PRIME_LENGTH_MULTIPLE = DSA::PRIME_LENGTH_MULTIPLE; + +inline bool GenerateDSAPrimes(const byte *seed, size_t seedLength, int &counter, Integer &p, unsigned int primeLength, Integer &q) + {return DSA::GeneratePrimes(seed, seedLength, counter, p, primeLength, q);} + +#endif + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/ec2n.cpp b/src-cryptopp/ec2n.cpp new file mode 100644 index 0000000..dbab31a --- /dev/null +++ b/src-cryptopp/ec2n.cpp @@ -0,0 +1,288 @@ +// ec2n.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "ec2n.h" +#include "asn.h" + +#include "algebra.cpp" +#include "eprecomp.cpp" + +NAMESPACE_BEGIN(CryptoPP) + +EC2N::EC2N(BufferedTransformation &bt) + : m_field(BERDecodeGF2NP(bt)) +{ + BERSequenceDecoder seq(bt); + m_field->BERDecodeElement(seq, m_a); + m_field->BERDecodeElement(seq, m_b); + // skip optional seed + if (!seq.EndReached()) + BERDecodeOctetString(seq, TheBitBucket()); + seq.MessageEnd(); +} + +void EC2N::DEREncode(BufferedTransformation &bt) const +{ + m_field->DEREncode(bt); + DERSequenceEncoder seq(bt); + m_field->DEREncodeElement(seq, m_a); + m_field->DEREncodeElement(seq, m_b); + seq.MessageEnd(); +} + +bool EC2N::DecodePoint(EC2N::Point &P, const byte *encodedPoint, size_t encodedPointLen) const +{ + StringStore store(encodedPoint, encodedPointLen); + return DecodePoint(P, store, encodedPointLen); +} + +bool EC2N::DecodePoint(EC2N::Point &P, BufferedTransformation &bt, size_t encodedPointLen) const +{ + byte type; + if (encodedPointLen < 1 || !bt.Get(type)) + return false; + + switch (type) + { + case 0: + P.identity = true; + return true; + case 2: + case 3: + { + if (encodedPointLen != EncodedPointSize(true)) + return false; + + P.identity = false; + P.x.Decode(bt, m_field->MaxElementByteLength()); + + if (P.x.IsZero()) + { + P.y = m_field->SquareRoot(m_b); + return true; + } + + FieldElement z = m_field->Square(P.x); + assert(P.x == m_field->SquareRoot(z)); + P.y = m_field->Divide(m_field->Add(m_field->Multiply(z, m_field->Add(P.x, m_a)), m_b), z); + assert(P.x == m_field->Subtract(m_field->Divide(m_field->Subtract(m_field->Multiply(P.y, z), m_b), z), m_a)); + z = m_field->SolveQuadraticEquation(P.y); + assert(m_field->Add(m_field->Square(z), z) == P.y); + z.SetCoefficient(0, type & 1); + + P.y = m_field->Multiply(z, P.x); + return true; + } + case 4: + { + if (encodedPointLen != EncodedPointSize(false)) + return false; + + unsigned int len = m_field->MaxElementByteLength(); + P.identity = false; + P.x.Decode(bt, len); + P.y.Decode(bt, len); + return true; + } + default: + return false; + } +} + +void EC2N::EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const +{ + if (P.identity) + NullStore().TransferTo(bt, EncodedPointSize(compressed)); + else if (compressed) + { + bt.Put(2 + (!P.x ? 0 : m_field->Divide(P.y, P.x).GetBit(0))); + P.x.Encode(bt, m_field->MaxElementByteLength()); + } + else + { + unsigned int len = m_field->MaxElementByteLength(); + bt.Put(4); // uncompressed + P.x.Encode(bt, len); + P.y.Encode(bt, len); + } +} + +void EC2N::EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const +{ + ArraySink sink(encodedPoint, EncodedPointSize(compressed)); + EncodePoint(sink, P, compressed); + assert(sink.TotalPutLength() == EncodedPointSize(compressed)); +} + +EC2N::Point EC2N::BERDecodePoint(BufferedTransformation &bt) const +{ + SecByteBlock str; + BERDecodeOctetString(bt, str); + Point P; + if (!DecodePoint(P, str, str.size())) + BERDecodeError(); + return P; +} + +void EC2N::DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const +{ + SecByteBlock str(EncodedPointSize(compressed)); + EncodePoint(str, P, compressed); + DEREncodeOctetString(bt, str); +} + +bool EC2N::ValidateParameters(RandomNumberGenerator &rng, unsigned int level) const +{ + bool pass = !!m_b; + pass = pass && m_a.CoefficientCount() <= m_field->MaxElementBitLength(); + pass = pass && m_b.CoefficientCount() <= m_field->MaxElementBitLength(); + + if (level >= 1) + pass = pass && m_field->GetModulus().IsIrreducible(); + + return pass; +} + +bool EC2N::VerifyPoint(const Point &P) const +{ + const FieldElement &x = P.x, &y = P.y; + return P.identity || + (x.CoefficientCount() <= m_field->MaxElementBitLength() + && y.CoefficientCount() <= m_field->MaxElementBitLength() + && !(((x+m_a)*x*x+m_b-(x+y)*y)%m_field->GetModulus())); +} + +bool EC2N::Equal(const Point &P, const Point &Q) const +{ + if (P.identity && Q.identity) + return true; + + if (P.identity && !Q.identity) + return false; + + if (!P.identity && Q.identity) + return false; + + return (m_field->Equal(P.x,Q.x) && m_field->Equal(P.y,Q.y)); +} + +const EC2N::Point& EC2N::Identity() const +{ + return Singleton().Ref(); +} + +const EC2N::Point& EC2N::Inverse(const Point &P) const +{ + if (P.identity) + return P; + else + { + m_R.identity = false; + m_R.y = m_field->Add(P.x, P.y); + m_R.x = P.x; + return m_R; + } +} + +const EC2N::Point& EC2N::Add(const Point &P, const Point &Q) const +{ + if (P.identity) return Q; + if (Q.identity) return P; + if (Equal(P, Q)) return Double(P); + if (m_field->Equal(P.x, Q.x) && m_field->Equal(P.y, m_field->Add(Q.x, Q.y))) return Identity(); + + FieldElement t = m_field->Add(P.y, Q.y); + t = m_field->Divide(t, m_field->Add(P.x, Q.x)); + FieldElement x = m_field->Square(t); + m_field->Accumulate(x, t); + m_field->Accumulate(x, Q.x); + m_field->Accumulate(x, m_a); + m_R.y = m_field->Add(P.y, m_field->Multiply(t, x)); + m_field->Accumulate(x, P.x); + m_field->Accumulate(m_R.y, x); + + m_R.x.swap(x); + m_R.identity = false; + return m_R; +} + +const EC2N::Point& EC2N::Double(const Point &P) const +{ + if (P.identity) return P; + if (!m_field->IsUnit(P.x)) return Identity(); + + FieldElement t = m_field->Divide(P.y, P.x); + m_field->Accumulate(t, P.x); + m_R.y = m_field->Square(P.x); + m_R.x = m_field->Square(t); + m_field->Accumulate(m_R.x, t); + m_field->Accumulate(m_R.x, m_a); + m_field->Accumulate(m_R.y, m_field->Multiply(t, m_R.x)); + m_field->Accumulate(m_R.y, m_R.x); + + m_R.identity = false; + return m_R; +} + +// ******************************************************** + +/* +EcPrecomputation& EcPrecomputation::operator=(const EcPrecomputation &rhs) +{ + m_ec = rhs.m_ec; + m_ep = rhs.m_ep; + m_ep.m_group = m_ec.get(); + return *this; +} + +void EcPrecomputation::SetCurveAndBase(const EC2N &ec, const EC2N::Point &base) +{ + m_ec.reset(new EC2N(ec)); + m_ep.SetGroupAndBase(*m_ec, base); +} + +void EcPrecomputation::Precompute(unsigned int maxExpBits, unsigned int storage) +{ + m_ep.Precompute(maxExpBits, storage); +} + +void EcPrecomputation::Load(BufferedTransformation &bt) +{ + BERSequenceDecoder seq(bt); + word32 version; + BERDecodeUnsigned(seq, version, INTEGER, 1, 1); + m_ep.m_exponentBase.BERDecode(seq); + m_ep.m_windowSize = m_ep.m_exponentBase.BitCount() - 1; + m_ep.m_bases.clear(); + while (!seq.EndReached()) + m_ep.m_bases.push_back(m_ec->BERDecodePoint(seq)); + seq.MessageEnd(); +} + +void EcPrecomputation::Save(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + DEREncodeUnsigned(seq, 1); // version + m_ep.m_exponentBase.DEREncode(seq); + for (unsigned i=0; iDEREncodePoint(seq, m_ep.m_bases[i]); + seq.MessageEnd(); +} + +EC2N::Point EcPrecomputation::Exponentiate(const Integer &exponent) const +{ + return m_ep.Exponentiate(exponent); +} + +EC2N::Point EcPrecomputation::CascadeExponentiate(const Integer &exponent, const DL_FixedBasePrecomputation &pc2, const Integer &exponent2) const +{ + return m_ep.CascadeExponentiate(exponent, static_cast &>(pc2).m_ep, exponent2); +} +*/ + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/ec2n.h b/src-cryptopp/ec2n.h new file mode 100644 index 0000000..ae4007c --- /dev/null +++ b/src-cryptopp/ec2n.h @@ -0,0 +1,113 @@ +#ifndef CRYPTOPP_EC2N_H +#define CRYPTOPP_EC2N_H + +#include "gf2n.h" +#include "eprecomp.h" +#include "smartptr.h" +#include "pubkey.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! Elliptic Curve Point +struct CRYPTOPP_DLL EC2NPoint +{ + EC2NPoint() : identity(true) {} + EC2NPoint(const PolynomialMod2 &x, const PolynomialMod2 &y) + : identity(false), x(x), y(y) {} + + bool operator==(const EC2NPoint &t) const + {return (identity && t.identity) || (!identity && !t.identity && x==t.x && y==t.y);} + bool operator< (const EC2NPoint &t) const + {return identity ? !t.identity : (!t.identity && (x; + +//! Elliptic Curve over GF(2^n) +class CRYPTOPP_DLL EC2N : public AbstractGroup +{ +public: + typedef GF2NP Field; + typedef Field::Element FieldElement; + typedef EC2NPoint Point; + + EC2N() {} + EC2N(const Field &field, const Field::Element &a, const Field::Element &b) + : m_field(field), m_a(a), m_b(b) {} + // construct from BER encoded parameters + // this constructor will decode and extract the the fields fieldID and curve of the sequence ECParameters + EC2N(BufferedTransformation &bt); + + // encode the fields fieldID and curve of the sequence ECParameters + void DEREncode(BufferedTransformation &bt) const; + + bool Equal(const Point &P, const Point &Q) const; + const Point& Identity() const; + const Point& Inverse(const Point &P) const; + bool InversionIsFast() const {return true;} + const Point& Add(const Point &P, const Point &Q) const; + const Point& Double(const Point &P) const; + + Point Multiply(const Integer &k, const Point &P) const + {return ScalarMultiply(P, k);} + Point CascadeMultiply(const Integer &k1, const Point &P, const Integer &k2, const Point &Q) const + {return CascadeScalarMultiply(P, k1, Q, k2);} + + bool ValidateParameters(RandomNumberGenerator &rng, unsigned int level=3) const; + bool VerifyPoint(const Point &P) const; + + unsigned int EncodedPointSize(bool compressed = false) const + {return 1 + (compressed?1:2)*m_field->MaxElementByteLength();} + // returns false if point is compressed and not valid (doesn't check if uncompressed) + bool DecodePoint(Point &P, BufferedTransformation &bt, size_t len) const; + bool DecodePoint(Point &P, const byte *encodedPoint, size_t len) const; + void EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const; + void EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const; + + Point BERDecodePoint(BufferedTransformation &bt) const; + void DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const; + + Integer FieldSize() const {return Integer::Power2(m_field->MaxElementBitLength());} + const Field & GetField() const {return *m_field;} + const FieldElement & GetA() const {return m_a;} + const FieldElement & GetB() const {return m_b;} + + bool operator==(const EC2N &rhs) const + {return GetField() == rhs.GetField() && m_a == rhs.m_a && m_b == rhs.m_b;} + +private: + clonable_ptr m_field; + FieldElement m_a, m_b; + mutable Point m_R; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS DL_FixedBasePrecomputationImpl; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupPrecomputation; + +template class EcPrecomputation; + +//! EC2N precomputation +template<> class EcPrecomputation : public DL_GroupPrecomputation +{ +public: + typedef EC2N EllipticCurve; + + // DL_GroupPrecomputation + const AbstractGroup & GetGroup() const {return m_ec;} + Element BERDecodeElement(BufferedTransformation &bt) const {return m_ec.BERDecodePoint(bt);} + void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {m_ec.DEREncodePoint(bt, v, false);} + + // non-inherited + void SetCurve(const EC2N &ec) {m_ec = ec;} + const EC2N & GetCurve() const {return m_ec;} + +private: + EC2N m_ec; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/eccrypto.cpp b/src-cryptopp/eccrypto.cpp new file mode 100644 index 0000000..922104c --- /dev/null +++ b/src-cryptopp/eccrypto.cpp @@ -0,0 +1,694 @@ +// eccrypto.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "eccrypto.h" +#include "nbtheory.h" +#include "oids.h" +#include "hex.h" +#include "argnames.h" +#include "ec2n.h" + +NAMESPACE_BEGIN(CryptoPP) + +#if 0 +static void ECDSA_TestInstantiations() +{ + ECDSA::Signer t1; + ECDSA::Verifier t2(t1); + ECNR::Signer t3; + ECNR::Verifier t4(t3); + ECIES::Encryptor t5; + ECIES::Decryptor t6; + ECDH::Domain t7; + ECMQV::Domain t8; +} +#endif + +// VC60 workaround: complains when these functions are put into an anonymous namespace +static Integer ConvertToInteger(const PolynomialMod2 &x) +{ + unsigned int l = x.ByteCount(); + SecByteBlock temp(l); + x.Encode(temp, l); + return Integer(temp, l); +} + +static inline Integer ConvertToInteger(const Integer &x) +{ + return x; +} + +static bool CheckMOVCondition(const Integer &q, const Integer &r) +{ + // see "Updated standards for validating elliptic curves", http://eprint.iacr.org/2007/343 + Integer t = 1; + unsigned int n = q.IsEven() ? 1 : q.BitCount(), m = r.BitCount(); + + for (unsigned int i=n; DiscreteLogWorkFactor(i) struct EcRecommendedParameters; + +template<> struct EcRecommendedParameters +{ + EcRecommendedParameters(const OID &oid, unsigned int t2, unsigned int t3, unsigned int t4, const char *a, const char *b, const char *g, const char *n, unsigned int h) + : oid(oid), t0(0), t1(0), t2(t2), t3(t3), t4(t4), a(a), b(b), g(g), n(n), h(h) {} + EcRecommendedParameters(const OID &oid, unsigned int t0, unsigned int t1, unsigned int t2, unsigned int t3, unsigned int t4, const char *a, const char *b, const char *g, const char *n, unsigned int h) + : oid(oid), t0(t0), t1(t1), t2(t2), t3(t3), t4(t4), a(a), b(b), g(g), n(n), h(h) {} + EC2N *NewEC() const + { + StringSource ssA(a, true, new HexDecoder); + StringSource ssB(b, true, new HexDecoder); + if (t0 == 0) + return new EC2N(GF2NT(t2, t3, t4), EC2N::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), EC2N::FieldElement(ssB, (size_t)ssB.MaxRetrievable())); + else + return new EC2N(GF2NPP(t0, t1, t2, t3, t4), EC2N::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), EC2N::FieldElement(ssB, (size_t)ssB.MaxRetrievable())); + }; + + OID oid; + unsigned int t0, t1, t2, t3, t4; + const char *a, *b, *g, *n; + unsigned int h; +}; + +template<> struct EcRecommendedParameters +{ + EcRecommendedParameters(const OID &oid, const char *p, const char *a, const char *b, const char *g, const char *n, unsigned int h) + : oid(oid), p(p), a(a), b(b), g(g), n(n), h(h) {} + ECP *NewEC() const + { + StringSource ssP(p, true, new HexDecoder); + StringSource ssA(a, true, new HexDecoder); + StringSource ssB(b, true, new HexDecoder); + return new ECP(Integer(ssP, (size_t)ssP.MaxRetrievable()), ECP::FieldElement(ssA, (size_t)ssA.MaxRetrievable()), ECP::FieldElement(ssB, (size_t)ssB.MaxRetrievable())); + }; + + OID oid; + const char *p; + const char *a, *b, *g, *n; + unsigned int h; +}; + +struct OIDLessThan +{ + template + inline bool operator()(const EcRecommendedParameters& a, const OID& b) {return a.oid < b;} + template + inline bool operator()(const OID& a, const EcRecommendedParameters& b) {return a < b.oid;} + template + inline bool operator()(const EcRecommendedParameters& a, const EcRecommendedParameters& b) {return a.oid < b.oid;} +}; + +static void GetRecommendedParameters(const EcRecommendedParameters *&begin, const EcRecommendedParameters *&end) +{ + // this array must be sorted by OID + static const EcRecommendedParameters rec[] = { + EcRecommendedParameters(ASN1::sect163k1(), + 163, 7, 6, 3, 0, + "000000000000000000000000000000000000000001", + "000000000000000000000000000000000000000001", + "0402FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE80289070FB05D38FF58321F2E800536D538CCDAA3D9", + "04000000000000000000020108A2E0CC0D99F8A5EF", + 2), + EcRecommendedParameters(ASN1::sect163r1(), + 163, 7, 6, 3, 0, + "07B6882CAAEFA84F9554FF8428BD88E246D2782AE2", + "0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9", + "040369979697AB43897789566789567F787A7876A65400435EDB42EFAFB2989D51FEFCE3C80988F41FF883", + "03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B", + 2), + EcRecommendedParameters(ASN1::sect239k1(), + 239, 158, 0, + "000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000001", + "0429A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA", + "2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5", + 4), + EcRecommendedParameters(ASN1::sect113r1(), + 113, 9, 0, + "003088250CA6E7C7FE649CE85820F7", + "00E8BEE4D3E2260744188BE0E9C723", + "04009D73616F35F4AB1407D73562C10F00A52830277958EE84D1315ED31886", + "0100000000000000D9CCEC8A39E56F", + 2), + EcRecommendedParameters(ASN1::sect113r2(), + 113, 9, 0, + "00689918DBEC7E5A0DD6DFC0AA55C7", + "0095E9A9EC9B297BD4BF36E059184F", + "0401A57A6A7B26CA5EF52FCDB816479700B3ADC94ED1FE674C06E695BABA1D", + "010000000000000108789B2496AF93", + 2), + EcRecommendedParameters(ASN1::sect163r2(), + 163, 7, 6, 3, 0, + "000000000000000000000000000000000000000001", + "020A601907B8C953CA1481EB10512F78744A3205FD", + "0403F0EBA16286A2D57EA0991168D4994637E8343E3600D51FBC6C71A0094FA2CDD545B11C5C0C797324F1", + "040000000000000000000292FE77E70C12A4234C33", + 2), + EcRecommendedParameters(ASN1::sect283k1(), + 283, 12, 7, 5, 0, + "000000000000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000000000000000001", + "040503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC245849283601CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259", + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61", + 4), + EcRecommendedParameters(ASN1::sect283r1(), + 283, 12, 7, 5, 0, + "000000000000000000000000000000000000000000000000000000000000000000000001", + "027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5", + "0405F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B1205303676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4", + "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307", + 2), + EcRecommendedParameters(ASN1::sect131r1(), + 131, 8, 3, 2, 0, + "07A11B09A76B562144418FF3FF8C2570B8", + "0217C05610884B63B9C6C7291678F9D341", + "040081BAF91FDF9833C40F9C181343638399078C6E7EA38C001F73C8134B1B4EF9E150", + "0400000000000000023123953A9464B54D", + 2), + EcRecommendedParameters(ASN1::sect131r2(), + 131, 8, 3, 2, 0, + "03E5A88919D7CAFCBF415F07C2176573B2", + "04B8266A46C55657AC734CE38F018F2192", + "040356DCD8F2F95031AD652D23951BB366A80648F06D867940A5366D9E265DE9EB240F", + "0400000000000000016954A233049BA98F", + 2), + EcRecommendedParameters(ASN1::sect193r1(), + 193, 15, 0, + "0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01", + "00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814", + "0401F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E10025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05", + "01000000000000000000000000C7F34A778F443ACC920EBA49", + 2), + EcRecommendedParameters(ASN1::sect193r2(), + 193, 15, 0, + "0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B", + "00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE", + "0400D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C", + "010000000000000000000000015AAB561B005413CCD4EE99D5", + 2), + EcRecommendedParameters(ASN1::sect233k1(), + 233, 74, 0, + "000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000001", + "04017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD612601DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3", + "8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF", + 4), + EcRecommendedParameters(ASN1::sect233r1(), + 233, 74, 0, + "000000000000000000000000000000000000000000000000000000000001", + "0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD", + "0400FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052", + "01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", + 2), + EcRecommendedParameters(ASN1::sect409k1(), + 409, 87, 0, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "040060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE902374601E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B", + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF", + 4), + EcRecommendedParameters(ASN1::sect409r1(), + 409, 87, 0, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F", + "04015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A70061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706", + "010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173", + 2), + EcRecommendedParameters(ASN1::sect571k1(), + 571, 10, 5, 2, 0, + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "04026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C89720349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3", + "020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001", + 4), + EcRecommendedParameters(ASN1::sect571r1(), + 571, 10, 5, 2, 0, + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A", + "040303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B", + "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47", + 2), + }; + begin = rec; + end = rec + sizeof(rec)/sizeof(rec[0]); +} + +static void GetRecommendedParameters(const EcRecommendedParameters *&begin, const EcRecommendedParameters *&end) +{ + // this array must be sorted by OID + static const EcRecommendedParameters rec[] = { + EcRecommendedParameters(ASN1::secp192r1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", + "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", + "04188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF101207192B95FFC8DA78631011ED6B24CDD573F977A11E794811", + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", + 1), + EcRecommendedParameters(ASN1::secp256r1(), + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", + "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", + "046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", + 1), + EcRecommendedParameters(ASN1::brainpoolP160r1(), + "E95E4A5F737059DC60DFC7AD95B3D8139515620F", + "340E7BE2A280EB74E2BE61BADA745D97E8F7C300", + "1E589A8595423412134FAA2DBDEC95C8D8675E58", + "04BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC31667CB477A1A8EC338F94741669C976316DA6321", + "E95E4A5F737059DC60DF5991D45029409E60FC09", + 1), + EcRecommendedParameters(ASN1::brainpoolP192r1(), + "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", + "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", + "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", + "04C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD614B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F", + "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", + 1), + EcRecommendedParameters(ASN1::brainpoolP224r1(), + "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", + "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", + "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", + "040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD", + "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", + 1), + EcRecommendedParameters(ASN1::brainpoolP256r1(), + "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", + "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", + "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", + "048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", + "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", + 1), + EcRecommendedParameters(ASN1::brainpoolP320r1(), + "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", + "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", + "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", + "0443BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E2061114FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1", + "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", + 1), + EcRecommendedParameters(ASN1::brainpoolP384r1(), + "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", + "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", + "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", + "041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", + "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", + 1), + EcRecommendedParameters(ASN1::brainpoolP512r1(), + "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", + "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", + "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", + "0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", + "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", + 1), + EcRecommendedParameters(ASN1::secp112r1(), + "DB7C2ABF62E35E668076BEAD208B", + "DB7C2ABF62E35E668076BEAD2088", + "659EF8BA043916EEDE8911702B22", + "0409487239995A5EE76B55F9C2F098A89CE5AF8724C0A23E0E0FF77500", + "DB7C2ABF62E35E7628DFAC6561C5", + 1), + EcRecommendedParameters(ASN1::secp112r2(), + "DB7C2ABF62E35E668076BEAD208B", + "6127C24C05F38A0AAAF65C0EF02C", + "51DEF1815DB5ED74FCC34C85D709", + "044BA30AB5E892B4E1649DD0928643ADCD46F5882E3747DEF36E956E97", + "36DF0AAFD8B8D7597CA10520D04B", + 4), + EcRecommendedParameters(ASN1::secp160r1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", + "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", + "044A96B5688EF573284664698968C38BB913CBFC8223A628553168947D59DCC912042351377AC5FB32", + "0100000000000000000001F4C8F927AED3CA752257", + 1), + EcRecommendedParameters(ASN1::secp160k1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", + "0000000000000000000000000000000000000000", + "0000000000000000000000000000000000000007", + "043B4C382CE37AA192A4019E763036F4F5DD4D7EBB938CF935318FDCED6BC28286531733C3F03C4FEE", + "0100000000000000000001B8FA16DFAB9ACA16B6B3", + 1), + EcRecommendedParameters(ASN1::secp256k1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000007", + "0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", + 1), + EcRecommendedParameters(ASN1::secp128r1(), + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", + "E87579C11079F43DD824993C2CEE5ED3", + "04161FF7528B899B2D0C28607CA52C5B86CF5AC8395BAFEB13C02DA292DDED7A83", + "FFFFFFFE0000000075A30D1B9038A115", + 1), + EcRecommendedParameters(ASN1::secp128r2(), + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", + "D6031998D1B3BBFEBF59CC9BBFF9AEE1", + "5EEEFCA380D02919DC2C6558BB6D8A5D", + "047B6AA5D85E572983E6FB32A7CDEBC14027B6916A894D3AEE7106FE805FC34B44", + "3FFFFFFF7FFFFFFFBE0024720613B5A3", + 4), + EcRecommendedParameters(ASN1::secp160r2(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70", + "B4E134D3FB59EB8BAB57274904664D5AF50388BA", + "0452DCB034293A117E1F4FF11B30F7199D3144CE6DFEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E", + "0100000000000000000000351EE786A818F3A1A16B", + 1), + EcRecommendedParameters(ASN1::secp192k1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", + "000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000003", + "04DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", + "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", + 1), + EcRecommendedParameters(ASN1::secp224k1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", + "00000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000005", + "04A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", + "010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", + 1), + EcRecommendedParameters(ASN1::secp224r1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", + "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", + "04B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", + 1), + EcRecommendedParameters(ASN1::secp384r1(), + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", + "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", + "04AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB73617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", + 1), + EcRecommendedParameters(ASN1::secp521r1(), + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", + "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", + "0400C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", + 1), + }; + begin = rec; + end = rec + sizeof(rec)/sizeof(rec[0]); +} + +template OID DL_GroupParameters_EC::GetNextRecommendedParametersOID(const OID &oid) +{ + const EcRecommendedParameters *begin, *end; + GetRecommendedParameters(begin, end); + const EcRecommendedParameters *it = std::upper_bound(begin, end, oid, OIDLessThan()); + return (it == end ? OID() : it->oid); +} + +template void DL_GroupParameters_EC::Initialize(const OID &oid) +{ + const EcRecommendedParameters *begin, *end; + GetRecommendedParameters(begin, end); + const EcRecommendedParameters *it = std::lower_bound(begin, end, oid, OIDLessThan()); + if (it == end || it->oid != oid) + throw UnknownOID(); + + const EcRecommendedParameters ¶m = *it; + m_oid = oid; + std::auto_ptr ec(param.NewEC()); + this->m_groupPrecomputation.SetCurve(*ec); + + StringSource ssG(param.g, true, new HexDecoder); + Element G; + bool result = GetCurve().DecodePoint(G, ssG, (size_t)ssG.MaxRetrievable()); + this->SetSubgroupGenerator(G); + assert(result); + + StringSource ssN(param.n, true, new HexDecoder); + m_n.Decode(ssN, (size_t)ssN.MaxRetrievable()); + m_k = param.h; +} + +template +bool DL_GroupParameters_EC::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + if (strcmp(name, Name::GroupOID()) == 0) + { + if (m_oid.m_values.empty()) + return false; + + this->ThrowIfTypeMismatch(name, typeid(OID), valueType); + *reinterpret_cast(pValue) = m_oid; + return true; + } + else + return GetValueHelper >(this, name, valueType, pValue).Assignable() + CRYPTOPP_GET_FUNCTION_ENTRY(Curve); +} + +template +void DL_GroupParameters_EC::AssignFrom(const NameValuePairs &source) +{ + OID oid; + if (source.GetValue(Name::GroupOID(), oid)) + Initialize(oid); + else + { + EllipticCurve ec; + Point G; + Integer n; + + source.GetRequiredParameter("DL_GroupParameters_EC", Name::Curve(), ec); + source.GetRequiredParameter("DL_GroupParameters_EC", Name::SubgroupGenerator(), G); + source.GetRequiredParameter("DL_GroupParameters_EC", Name::SubgroupOrder(), n); + Integer k = source.GetValueWithDefault(Name::Cofactor(), Integer::Zero()); + + Initialize(ec, G, n, k); + } +} + +template +void DL_GroupParameters_EC::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg) +{ + try + { + AssignFrom(alg); + } + catch (InvalidArgument &) + { + throw NotImplemented("DL_GroupParameters_EC: curve generation is not implemented yet"); + } +} + +template +void DL_GroupParameters_EC::BERDecode(BufferedTransformation &bt) +{ + byte b; + if (!bt.Peek(b)) + BERDecodeError(); + if (b == OBJECT_IDENTIFIER) + Initialize(OID(bt)); + else + { + BERSequenceDecoder seq(bt); + word32 version; + BERDecodeUnsigned(seq, version, INTEGER, 1, 1); // check version + EllipticCurve ec(seq); + Point G = ec.BERDecodePoint(seq); + Integer n(seq); + Integer k; + bool cofactorPresent = !seq.EndReached(); + if (cofactorPresent) + k.BERDecode(seq); + else + k = Integer::Zero(); + seq.MessageEnd(); + + Initialize(ec, G, n, k); + } +} + +template +void DL_GroupParameters_EC::DEREncode(BufferedTransformation &bt) const +{ + if (m_encodeAsOID && !m_oid.m_values.empty()) + m_oid.DEREncode(bt); + else + { + DERSequenceEncoder seq(bt); + DEREncodeUnsigned(seq, 1); // version + GetCurve().DEREncode(seq); + GetCurve().DEREncodePoint(seq, this->GetSubgroupGenerator(), m_compress); + m_n.DEREncode(seq); + if (m_k.NotZero()) + m_k.DEREncode(seq); + seq.MessageEnd(); + } +} + +template +Integer DL_GroupParameters_EC::GetCofactor() const +{ + if (!m_k) + { + Integer q = GetCurve().FieldSize(); + Integer qSqrt = q.SquareRoot(); + m_k = (q+2*qSqrt+1)/m_n; + } + + return m_k; +} + +template +Integer DL_GroupParameters_EC::ConvertElementToInteger(const Element &element) const +{ + return ConvertToInteger(element.x); +}; + +template +bool DL_GroupParameters_EC::ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const +{ + bool pass = GetCurve().ValidateParameters(rng, level); + + Integer q = GetCurve().FieldSize(); + pass = pass && m_n!=q; + + if (level >= 2) + { + Integer qSqrt = q.SquareRoot(); + pass = pass && m_n>4*qSqrt; + pass = pass && VerifyPrime(rng, m_n, level-2); + pass = pass && (m_k.IsZero() || m_k == (q+2*qSqrt+1)/m_n); + pass = pass && CheckMOVCondition(q, m_n); + } + + return pass; +} + +template +bool DL_GroupParameters_EC::ValidateElement(unsigned int level, const Element &g, const DL_FixedBasePrecomputation *gpc) const +{ + bool pass = !IsIdentity(g) && GetCurve().VerifyPoint(g); + if (level >= 1) + { + if (gpc) + pass = pass && gpc->Exponentiate(this->GetGroupPrecomputation(), Integer::One()) == g; + } + if (level >= 2 && pass) + { + const Integer &q = GetSubgroupOrder(); + Element gq = gpc ? gpc->Exponentiate(this->GetGroupPrecomputation(), q) : this->ExponentiateElement(g, q); + pass = pass && IsIdentity(gq); + } + return pass; +} + +template +void DL_GroupParameters_EC::SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const +{ + GetCurve().SimultaneousMultiply(results, base, exponents, exponentsCount); +} + +template +CPP_TYPENAME DL_GroupParameters_EC::Element DL_GroupParameters_EC::MultiplyElements(const Element &a, const Element &b) const +{ + return GetCurve().Add(a, b); +} + +template +CPP_TYPENAME DL_GroupParameters_EC::Element DL_GroupParameters_EC::CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const +{ + return GetCurve().CascadeMultiply(exponent1, element1, exponent2, element2); +} + +template +OID DL_GroupParameters_EC::GetAlgorithmID() const +{ + return ASN1::id_ecPublicKey(); +} + +// ****************************************************************** + +template +void DL_PublicKey_EC::BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size) +{ + typename EC::Point P; + if (!this->GetGroupParameters().GetCurve().DecodePoint(P, bt, size)) + BERDecodeError(); + this->SetPublicElement(P); +} + +template +void DL_PublicKey_EC::DEREncodePublicKey(BufferedTransformation &bt) const +{ + this->GetGroupParameters().GetCurve().EncodePoint(bt, this->GetPublicElement(), this->GetGroupParameters().GetPointCompression()); +} + +// ****************************************************************** + +template +void DL_PrivateKey_EC::BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size) +{ + BERSequenceDecoder seq(bt); + word32 version; + BERDecodeUnsigned(seq, version, INTEGER, 1, 1); // check version + + BERGeneralDecoder dec(seq, OCTET_STRING); + if (!dec.IsDefiniteLength()) + BERDecodeError(); + Integer x; + x.Decode(dec, (size_t)dec.RemainingLength()); + dec.MessageEnd(); + if (!parametersPresent && seq.PeekByte() != (CONTEXT_SPECIFIC | CONSTRUCTED | 0)) + BERDecodeError(); + if (!seq.EndReached() && seq.PeekByte() == (CONTEXT_SPECIFIC | CONSTRUCTED | 0)) + { + BERGeneralDecoder parameters(seq, CONTEXT_SPECIFIC | CONSTRUCTED | 0); + this->AccessGroupParameters().BERDecode(parameters); + parameters.MessageEnd(); + } + if (!seq.EndReached()) + { + // skip over the public element + SecByteBlock subjectPublicKey; + unsigned int unusedBits; + BERGeneralDecoder publicKey(seq, CONTEXT_SPECIFIC | CONSTRUCTED | 1); + BERDecodeBitString(publicKey, subjectPublicKey, unusedBits); + publicKey.MessageEnd(); + Element Q; + if (!(unusedBits == 0 && this->GetGroupParameters().GetCurve().DecodePoint(Q, subjectPublicKey, subjectPublicKey.size()))) + BERDecodeError(); + } + seq.MessageEnd(); + + this->SetPrivateExponent(x); +} + +template +void DL_PrivateKey_EC::DEREncodePrivateKey(BufferedTransformation &bt) const +{ + DERSequenceEncoder privateKey(bt); + DEREncodeUnsigned(privateKey, 1); // version + // SEC 1 ver 1.0 says privateKey (m_d) has the same length as order of the curve + // this will be changed to order of base point in a future version + this->GetPrivateExponent().DEREncodeAsOctetString(privateKey, this->GetGroupParameters().GetSubgroupOrder().ByteCount()); + privateKey.MessageEnd(); +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/eccrypto.h b/src-cryptopp/eccrypto.h new file mode 100644 index 0000000..7ac8d90 --- /dev/null +++ b/src-cryptopp/eccrypto.h @@ -0,0 +1,280 @@ +#ifndef CRYPTOPP_ECCRYPTO_H +#define CRYPTOPP_ECCRYPTO_H + +/*! \file +*/ + +#include "pubkey.h" +#include "integer.h" +#include "asn.h" +#include "hmac.h" +#include "sha.h" +#include "gfpcrypt.h" +#include "dh.h" +#include "mqv.h" +#include "ecp.h" +#include "ec2n.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! Elliptic Curve Parameters +/*! This class corresponds to the ASN.1 sequence of the same name + in ANSI X9.62 (also SEC 1). +*/ +template +class DL_GroupParameters_EC : public DL_GroupParametersImpl > +{ + typedef DL_GroupParameters_EC ThisClass; + +public: + typedef EC EllipticCurve; + typedef typename EllipticCurve::Point Point; + typedef Point Element; + typedef IncompatibleCofactorMultiplication DefaultCofactorOption; + + DL_GroupParameters_EC() : m_compress(false), m_encodeAsOID(false) {} + DL_GroupParameters_EC(const OID &oid) + : m_compress(false), m_encodeAsOID(false) {Initialize(oid);} + DL_GroupParameters_EC(const EllipticCurve &ec, const Point &G, const Integer &n, const Integer &k = Integer::Zero()) + : m_compress(false), m_encodeAsOID(false) {Initialize(ec, G, n, k);} + DL_GroupParameters_EC(BufferedTransformation &bt) + : m_compress(false), m_encodeAsOID(false) {BERDecode(bt);} + + void Initialize(const EllipticCurve &ec, const Point &G, const Integer &n, const Integer &k = Integer::Zero()) + { + this->m_groupPrecomputation.SetCurve(ec); + this->SetSubgroupGenerator(G); + m_n = n; + m_k = k; + } + void Initialize(const OID &oid); + + // NameValuePairs + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + + // GeneratibleCryptoMaterial interface + //! this implementation doesn't actually generate a curve, it just initializes the parameters with existing values + /*! parameters: (Curve, SubgroupGenerator, SubgroupOrder, Cofactor (optional)), or (GroupOID) */ + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg); + + // DL_GroupParameters + const DL_FixedBasePrecomputation & GetBasePrecomputation() const {return this->m_gpc;} + DL_FixedBasePrecomputation & AccessBasePrecomputation() {return this->m_gpc;} + const Integer & GetSubgroupOrder() const {return m_n;} + Integer GetCofactor() const; + bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const; + bool ValidateElement(unsigned int level, const Element &element, const DL_FixedBasePrecomputation *precomp) const; + bool FastSubgroupCheckAvailable() const {return false;} + void EncodeElement(bool reversible, const Element &element, byte *encoded) const + { + if (reversible) + GetCurve().EncodePoint(encoded, element, m_compress); + else + element.x.Encode(encoded, GetEncodedElementSize(false)); + } + unsigned int GetEncodedElementSize(bool reversible) const + { + if (reversible) + return GetCurve().EncodedPointSize(m_compress); + else + return GetCurve().GetField().MaxElementByteLength(); + } + Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const + { + Point result; + if (!GetCurve().DecodePoint(result, encoded, GetEncodedElementSize(true))) + throw DL_BadElement(); + if (checkForGroupMembership && !ValidateElement(1, result, NULL)) + throw DL_BadElement(); + return result; + } + Integer ConvertElementToInteger(const Element &element) const; + Integer GetMaxExponent() const {return GetSubgroupOrder()-1;} + bool IsIdentity(const Element &element) const {return element.identity;} + void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const; + static std::string CRYPTOPP_API StaticAlgorithmNamePrefix() {return "EC";} + + // ASN1Key + OID GetAlgorithmID() const; + + // used by MQV + Element MultiplyElements(const Element &a, const Element &b) const; + Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const; + + // non-inherited + + // enumerate OIDs for recommended parameters, use OID() to get first one + static OID CRYPTOPP_API GetNextRecommendedParametersOID(const OID &oid); + + void BERDecode(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const; + + void SetPointCompression(bool compress) {m_compress = compress;} + bool GetPointCompression() const {return m_compress;} + + void SetEncodeAsOID(bool encodeAsOID) {m_encodeAsOID = encodeAsOID;} + bool GetEncodeAsOID() const {return m_encodeAsOID;} + + const EllipticCurve& GetCurve() const {return this->m_groupPrecomputation.GetCurve();} + + bool operator==(const ThisClass &rhs) const + {return this->m_groupPrecomputation.GetCurve() == rhs.m_groupPrecomputation.GetCurve() && this->m_gpc.GetBase(this->m_groupPrecomputation) == rhs.m_gpc.GetBase(rhs.m_groupPrecomputation);} + +#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY + const Point& GetBasePoint() const {return GetSubgroupGenerator();} + const Integer& GetBasePointOrder() const {return GetSubgroupOrder();} + void LoadRecommendedParameters(const OID &oid) {Initialize(oid);} +#endif + +protected: + unsigned int FieldElementLength() const {return GetCurve().GetField().MaxElementByteLength();} + unsigned int ExponentLength() const {return m_n.ByteCount();} + + OID m_oid; // set if parameters loaded from a recommended curve + Integer m_n; // order of base point + bool m_compress, m_encodeAsOID; + mutable Integer m_k; // cofactor +}; + +//! EC public key +template +class DL_PublicKey_EC : public DL_PublicKeyImpl > +{ +public: + typedef typename EC::Point Element; + + void Initialize(const DL_GroupParameters_EC ¶ms, const Element &Q) + {this->AccessGroupParameters() = params; this->SetPublicElement(Q);} + void Initialize(const EC &ec, const Element &G, const Integer &n, const Element &Q) + {this->AccessGroupParameters().Initialize(ec, G, n); this->SetPublicElement(Q);} + + // X509PublicKey + void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size); + void DEREncodePublicKey(BufferedTransformation &bt) const; +}; + +//! EC private key +template +class DL_PrivateKey_EC : public DL_PrivateKeyImpl > +{ +public: + typedef typename EC::Point Element; + + void Initialize(const DL_GroupParameters_EC ¶ms, const Integer &x) + {this->AccessGroupParameters() = params; this->SetPrivateExponent(x);} + void Initialize(const EC &ec, const Element &G, const Integer &n, const Integer &x) + {this->AccessGroupParameters().Initialize(ec, G, n); this->SetPrivateExponent(x);} + void Initialize(RandomNumberGenerator &rng, const DL_GroupParameters_EC ¶ms) + {this->GenerateRandom(rng, params);} + void Initialize(RandomNumberGenerator &rng, const EC &ec, const Element &G, const Integer &n) + {this->GenerateRandom(rng, DL_GroupParameters_EC(ec, G, n));} + + // PKCS8PrivateKey + void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size); + void DEREncodePrivateKey(BufferedTransformation &bt) const; +}; + +//! Elliptic Curve Diffie-Hellman, AKA ECDH +template ::DefaultCofactorOption> +struct ECDH +{ + typedef DH_Domain, COFACTOR_OPTION> Domain; +}; + +/// Elliptic Curve Menezes-Qu-Vanstone, AKA ECMQV +template ::DefaultCofactorOption> +struct ECMQV +{ + typedef MQV_Domain, COFACTOR_OPTION> Domain; +}; + +//! EC keys +template +struct DL_Keys_EC +{ + typedef DL_PublicKey_EC PublicKey; + typedef DL_PrivateKey_EC PrivateKey; +}; + +template +struct ECDSA; + +//! ECDSA keys +template +struct DL_Keys_ECDSA +{ + typedef DL_PublicKey_EC PublicKey; + typedef DL_PrivateKey_WithSignaturePairwiseConsistencyTest, ECDSA > PrivateKey; +}; + +//! ECDSA algorithm +template +class DL_Algorithm_ECDSA : public DL_Algorithm_GDSA +{ +public: + static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECDSA";} +}; + +//! ECNR algorithm +template +class DL_Algorithm_ECNR : public DL_Algorithm_NR +{ +public: + static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECNR";} +}; + +//! ECDSA +template +struct ECDSA : public DL_SS, DL_Algorithm_ECDSA, DL_SignatureMessageEncodingMethod_DSA, H> +{ +}; + +//! ECNR +template +struct ECNR : public DL_SS, DL_Algorithm_ECNR, DL_SignatureMessageEncodingMethod_NR, H> +{ +}; + +//! Elliptic Curve Integrated Encryption Scheme, AKA ECIES +/*! Default to (NoCofactorMultiplication and DHAES_MODE = false) for compatibilty with SEC1 and Crypto++ 4.2. + The combination of (IncompatibleCofactorMultiplication and DHAES_MODE = true) is recommended for best + efficiency and security. */ +template +struct ECIES + : public DL_ES< + DL_Keys_EC, + DL_KeyAgreementAlgorithm_DH, + DL_KeyDerivationAlgorithm_P1363 >, + DL_EncryptionAlgorithm_Xor, DHAES_MODE>, + ECIES > +{ + static std::string CRYPTOPP_API StaticAlgorithmName() {return "ECIES";} // TODO: fix this after name is standardized +}; + +NAMESPACE_END + +#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES +#include "eccrypto.cpp" +#endif + +NAMESPACE_BEGIN(CryptoPP) + +CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_EC; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl >; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKeyImpl >; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_EC; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl >; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKeyImpl >; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_EC; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest, ECDSA >; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest, ECDSA >; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/ecp.cpp b/src-cryptopp/ecp.cpp new file mode 100644 index 0000000..55a7cc1 --- /dev/null +++ b/src-cryptopp/ecp.cpp @@ -0,0 +1,473 @@ +// ecp.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "ecp.h" +#include "asn.h" +#include "nbtheory.h" + +#include "algebra.cpp" + +NAMESPACE_BEGIN(CryptoPP) + +ANONYMOUS_NAMESPACE_BEGIN +static inline ECP::Point ToMontgomery(const ModularArithmetic &mr, const ECP::Point &P) +{ + return P.identity ? P : ECP::Point(mr.ConvertIn(P.x), mr.ConvertIn(P.y)); +} + +static inline ECP::Point FromMontgomery(const ModularArithmetic &mr, const ECP::Point &P) +{ + return P.identity ? P : ECP::Point(mr.ConvertOut(P.x), mr.ConvertOut(P.y)); +} +NAMESPACE_END + +ECP::ECP(const ECP &ecp, bool convertToMontgomeryRepresentation) +{ + if (convertToMontgomeryRepresentation && !ecp.GetField().IsMontgomeryRepresentation()) + { + m_fieldPtr.reset(new MontgomeryRepresentation(ecp.GetField().GetModulus())); + m_a = GetField().ConvertIn(ecp.m_a); + m_b = GetField().ConvertIn(ecp.m_b); + } + else + operator=(ecp); +} + +ECP::ECP(BufferedTransformation &bt) + : m_fieldPtr(new Field(bt)) +{ + BERSequenceDecoder seq(bt); + GetField().BERDecodeElement(seq, m_a); + GetField().BERDecodeElement(seq, m_b); + // skip optional seed + if (!seq.EndReached()) + { + SecByteBlock seed; + unsigned int unused; + BERDecodeBitString(seq, seed, unused); + } + seq.MessageEnd(); +} + +void ECP::DEREncode(BufferedTransformation &bt) const +{ + GetField().DEREncode(bt); + DERSequenceEncoder seq(bt); + GetField().DEREncodeElement(seq, m_a); + GetField().DEREncodeElement(seq, m_b); + seq.MessageEnd(); +} + +bool ECP::DecodePoint(ECP::Point &P, const byte *encodedPoint, size_t encodedPointLen) const +{ + StringStore store(encodedPoint, encodedPointLen); + return DecodePoint(P, store, encodedPointLen); +} + +bool ECP::DecodePoint(ECP::Point &P, BufferedTransformation &bt, size_t encodedPointLen) const +{ + byte type; + if (encodedPointLen < 1 || !bt.Get(type)) + return false; + + switch (type) + { + case 0: + P.identity = true; + return true; + case 2: + case 3: + { + if (encodedPointLen != EncodedPointSize(true)) + return false; + + Integer p = FieldSize(); + + P.identity = false; + P.x.Decode(bt, GetField().MaxElementByteLength()); + P.y = ((P.x*P.x+m_a)*P.x+m_b) % p; + + if (Jacobi(P.y, p) !=1) + return false; + + P.y = ModularSquareRoot(P.y, p); + + if ((type & 1) != P.y.GetBit(0)) + P.y = p-P.y; + + return true; + } + case 4: + { + if (encodedPointLen != EncodedPointSize(false)) + return false; + + unsigned int len = GetField().MaxElementByteLength(); + P.identity = false; + P.x.Decode(bt, len); + P.y.Decode(bt, len); + return true; + } + default: + return false; + } +} + +void ECP::EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const +{ + if (P.identity) + NullStore().TransferTo(bt, EncodedPointSize(compressed)); + else if (compressed) + { + bt.Put(2 + P.y.GetBit(0)); + P.x.Encode(bt, GetField().MaxElementByteLength()); + } + else + { + unsigned int len = GetField().MaxElementByteLength(); + bt.Put(4); // uncompressed + P.x.Encode(bt, len); + P.y.Encode(bt, len); + } +} + +void ECP::EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const +{ + ArraySink sink(encodedPoint, EncodedPointSize(compressed)); + EncodePoint(sink, P, compressed); + assert(sink.TotalPutLength() == EncodedPointSize(compressed)); +} + +ECP::Point ECP::BERDecodePoint(BufferedTransformation &bt) const +{ + SecByteBlock str; + BERDecodeOctetString(bt, str); + Point P; + if (!DecodePoint(P, str, str.size())) + BERDecodeError(); + return P; +} + +void ECP::DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const +{ + SecByteBlock str(EncodedPointSize(compressed)); + EncodePoint(str, P, compressed); + DEREncodeOctetString(bt, str); +} + +bool ECP::ValidateParameters(RandomNumberGenerator &rng, unsigned int level) const +{ + Integer p = FieldSize(); + + bool pass = p.IsOdd(); + pass = pass && !m_a.IsNegative() && m_a

= 1) + pass = pass && ((4*m_a*m_a*m_a+27*m_b*m_b)%p).IsPositive(); + + if (level >= 2) + pass = pass && VerifyPrime(rng, p); + + return pass; +} + +bool ECP::VerifyPoint(const Point &P) const +{ + const FieldElement &x = P.x, &y = P.y; + Integer p = FieldSize(); + return P.identity || + (!x.IsNegative() && x

().Ref(); +} + +const ECP::Point& ECP::Inverse(const Point &P) const +{ + if (P.identity) + return P; + else + { + m_R.identity = false; + m_R.x = P.x; + m_R.y = GetField().Inverse(P.y); + return m_R; + } +} + +const ECP::Point& ECP::Add(const Point &P, const Point &Q) const +{ + if (P.identity) return Q; + if (Q.identity) return P; + if (GetField().Equal(P.x, Q.x)) + return GetField().Equal(P.y, Q.y) ? Double(P) : Identity(); + + FieldElement t = GetField().Subtract(Q.y, P.y); + t = GetField().Divide(t, GetField().Subtract(Q.x, P.x)); + FieldElement x = GetField().Subtract(GetField().Subtract(GetField().Square(t), P.x), Q.x); + m_R.y = GetField().Subtract(GetField().Multiply(t, GetField().Subtract(P.x, x)), P.y); + + m_R.x.swap(x); + m_R.identity = false; + return m_R; +} + +const ECP::Point& ECP::Double(const Point &P) const +{ + if (P.identity || P.y==GetField().Identity()) return Identity(); + + FieldElement t = GetField().Square(P.x); + t = GetField().Add(GetField().Add(GetField().Double(t), t), m_a); + t = GetField().Divide(t, GetField().Double(P.y)); + FieldElement x = GetField().Subtract(GetField().Subtract(GetField().Square(t), P.x), P.x); + m_R.y = GetField().Subtract(GetField().Multiply(t, GetField().Subtract(P.x, x)), P.y); + + m_R.x.swap(x); + m_R.identity = false; + return m_R; +} + +template void ParallelInvert(const AbstractRing &ring, Iterator begin, Iterator end) +{ + size_t n = end-begin; + if (n == 1) + *begin = ring.MultiplicativeInverse(*begin); + else if (n > 1) + { + std::vector vec((n+1)/2); + unsigned int i; + Iterator it; + + for (i=0, it=begin; i::iterator it) : it(it) {} + Integer& operator*() {return it->z;} + int operator-(ZIterator it2) {return int(it-it2.it);} + ZIterator operator+(int i) {return ZIterator(it+i);} + ZIterator& operator+=(int i) {it+=i; return *this;} + std::vector::iterator it; +}; + +ECP::Point ECP::ScalarMultiply(const Point &P, const Integer &k) const +{ + Element result; + if (k.BitCount() <= 5) + AbstractGroup::SimultaneousMultiply(&result, P, &k, 1); + else + ECP::SimultaneousMultiply(&result, P, &k, 1); + return result; +} + +void ECP::SimultaneousMultiply(ECP::Point *results, const ECP::Point &P, const Integer *expBegin, unsigned int expCount) const +{ + if (!GetField().IsMontgomeryRepresentation()) + { + ECP ecpmr(*this, true); + const ModularArithmetic &mr = ecpmr.GetField(); + ecpmr.SimultaneousMultiply(results, ToMontgomery(mr, P), expBegin, expCount); + for (unsigned int i=0; i bases; + std::vector exponents; + exponents.reserve(expCount); + std::vector > baseIndices(expCount); + std::vector > negateBase(expCount); + std::vector > exponentWindows(expCount); + unsigned int i; + + for (i=0; iNotNegative()); + exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 5)); + exponents[i].FindNextWindow(); + } + + unsigned int expBitPosition = 0; + bool notDone = true; + + while (notDone) + { + notDone = false; + bool baseAdded = false; + for (i=0; i > finalCascade; + for (i=0; i::CascadeScalarMultiply(P, k1, Q, k2); +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/ecp.h b/src-cryptopp/ecp.h new file mode 100644 index 0000000..d946be6 --- /dev/null +++ b/src-cryptopp/ecp.h @@ -0,0 +1,126 @@ +#ifndef CRYPTOPP_ECP_H +#define CRYPTOPP_ECP_H + +#include "modarith.h" +#include "eprecomp.h" +#include "smartptr.h" +#include "pubkey.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! Elliptical Curve Point +struct CRYPTOPP_DLL ECPPoint +{ + ECPPoint() : identity(true) {} + ECPPoint(const Integer &x, const Integer &y) + : identity(false), x(x), y(y) {} + + bool operator==(const ECPPoint &t) const + {return (identity && t.identity) || (!identity && !t.identity && x==t.x && y==t.y);} + bool operator< (const ECPPoint &t) const + {return identity ? !t.identity : (!t.identity && (x; + +//! Elliptic Curve over GF(p), where p is prime +class CRYPTOPP_DLL ECP : public AbstractGroup +{ +public: + typedef ModularArithmetic Field; + typedef Integer FieldElement; + typedef ECPPoint Point; + + ECP() {} + ECP(const ECP &ecp, bool convertToMontgomeryRepresentation = false); + ECP(const Integer &modulus, const FieldElement &a, const FieldElement &b) + : m_fieldPtr(new Field(modulus)), m_a(a.IsNegative() ? modulus+a : a), m_b(b) {} + // construct from BER encoded parameters + // this constructor will decode and extract the the fields fieldID and curve of the sequence ECParameters + ECP(BufferedTransformation &bt); + + // encode the fields fieldID and curve of the sequence ECParameters + void DEREncode(BufferedTransformation &bt) const; + + bool Equal(const Point &P, const Point &Q) const; + const Point& Identity() const; + const Point& Inverse(const Point &P) const; + bool InversionIsFast() const {return true;} + const Point& Add(const Point &P, const Point &Q) const; + const Point& Double(const Point &P) const; + Point ScalarMultiply(const Point &P, const Integer &k) const; + Point CascadeScalarMultiply(const Point &P, const Integer &k1, const Point &Q, const Integer &k2) const; + void SimultaneousMultiply(Point *results, const Point &base, const Integer *exponents, unsigned int exponentsCount) const; + + Point Multiply(const Integer &k, const Point &P) const + {return ScalarMultiply(P, k);} + Point CascadeMultiply(const Integer &k1, const Point &P, const Integer &k2, const Point &Q) const + {return CascadeScalarMultiply(P, k1, Q, k2);} + + bool ValidateParameters(RandomNumberGenerator &rng, unsigned int level=3) const; + bool VerifyPoint(const Point &P) const; + + unsigned int EncodedPointSize(bool compressed = false) const + {return 1 + (compressed?1:2)*GetField().MaxElementByteLength();} + // returns false if point is compressed and not valid (doesn't check if uncompressed) + bool DecodePoint(Point &P, BufferedTransformation &bt, size_t len) const; + bool DecodePoint(Point &P, const byte *encodedPoint, size_t len) const; + void EncodePoint(byte *encodedPoint, const Point &P, bool compressed) const; + void EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const; + + Point BERDecodePoint(BufferedTransformation &bt) const; + void DEREncodePoint(BufferedTransformation &bt, const Point &P, bool compressed) const; + + Integer FieldSize() const {return GetField().GetModulus();} + const Field & GetField() const {return *m_fieldPtr;} + const FieldElement & GetA() const {return m_a;} + const FieldElement & GetB() const {return m_b;} + + bool operator==(const ECP &rhs) const + {return GetField() == rhs.GetField() && m_a == rhs.m_a && m_b == rhs.m_b;} + +private: + clonable_ptr m_fieldPtr; + FieldElement m_a, m_b; + mutable Point m_R; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS DL_FixedBasePrecomputationImpl; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupPrecomputation; + +template class EcPrecomputation; + +//! ECP precomputation +template<> class EcPrecomputation : public DL_GroupPrecomputation +{ +public: + typedef ECP EllipticCurve; + + // DL_GroupPrecomputation + bool NeedConversions() const {return true;} + Element ConvertIn(const Element &P) const + {return P.identity ? P : ECP::Point(m_ec->GetField().ConvertIn(P.x), m_ec->GetField().ConvertIn(P.y));}; + Element ConvertOut(const Element &P) const + {return P.identity ? P : ECP::Point(m_ec->GetField().ConvertOut(P.x), m_ec->GetField().ConvertOut(P.y));} + const AbstractGroup & GetGroup() const {return *m_ec;} + Element BERDecodeElement(BufferedTransformation &bt) const {return m_ec->BERDecodePoint(bt);} + void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {m_ec->DEREncodePoint(bt, v, false);} + + // non-inherited + void SetCurve(const ECP &ec) + { + m_ec.reset(new ECP(ec, true)); + m_ecOriginal = ec; + } + const ECP & GetCurve() const {return *m_ecOriginal;} + +private: + value_ptr m_ec, m_ecOriginal; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/emsa2.h b/src-cryptopp/emsa2.h new file mode 100644 index 0000000..49109e6 --- /dev/null +++ b/src-cryptopp/emsa2.h @@ -0,0 +1,86 @@ +#ifndef CRYPTOPP_EMSA2_H +#define CRYPTOPP_EMSA2_H + +/** \file + This file contains various padding schemes for public key algorithms. +*/ + +#include "cryptlib.h" +#include "pubkey.h" + +#ifdef CRYPTOPP_IS_DLL +#include "sha.h" +#endif + +NAMESPACE_BEGIN(CryptoPP) + +template class EMSA2HashId +{ +public: + static const byte id; +}; + +template +class EMSA2HashIdLookup : public BASE +{ +public: + struct HashIdentifierLookup + { + template struct HashIdentifierLookup2 + { + static HashIdentifier Lookup() + { + return HashIdentifier(&EMSA2HashId::id, 1); + } + }; + }; +}; + +// EMSA2HashId can be instantiated with the following classes. +class SHA1; +class RIPEMD160; +class RIPEMD128; +class SHA256; +class SHA384; +class SHA512; +class Whirlpool; +class SHA224; +// end of list + +#ifdef CRYPTOPP_IS_DLL +CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId; +CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId; +CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId; +CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId; +CRYPTOPP_DLL_TEMPLATE_CLASS EMSA2HashId; +#endif + +//! _ +class CRYPTOPP_DLL EMSA2Pad : public EMSA2HashIdLookup +{ +public: + static const char * CRYPTOPP_API StaticAlgorithmName() {return "EMSA2";} + + size_t MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const + {return 8*digestLength + 31;} + + void ComputeMessageRepresentative(RandomNumberGenerator &rng, + const byte *recoverableMessage, size_t recoverableMessageLength, + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const; +}; + +//! EMSA2, for use with RWSS and RSA_ISO +/*! Only the following hash functions are supported by this signature standard: + \dontinclude emsa2.h + \skip EMSA2HashId can be instantiated + \until end of list +*/ +struct P1363_EMSA2 : public SignatureStandard +{ + typedef EMSA2Pad SignatureMessageEncodingMethod; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/eprecomp.cpp b/src-cryptopp/eprecomp.cpp new file mode 100644 index 0000000..a061cf6 --- /dev/null +++ b/src-cryptopp/eprecomp.cpp @@ -0,0 +1,112 @@ +// eprecomp.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "eprecomp.h" +#include "asn.h" + +NAMESPACE_BEGIN(CryptoPP) + +template void DL_FixedBasePrecomputationImpl::SetBase(const DL_GroupPrecomputation &group, const Element &i_base) +{ + m_base = group.NeedConversions() ? group.ConvertIn(i_base) : i_base; + + if (m_bases.empty() || !(m_base == m_bases[0])) + { + m_bases.resize(1); + m_bases[0] = m_base; + } + + if (group.NeedConversions()) + m_base = i_base; +} + +template void DL_FixedBasePrecomputationImpl::Precompute(const DL_GroupPrecomputation &group, unsigned int maxExpBits, unsigned int storage) +{ + assert(m_bases.size() > 0); + assert(storage <= maxExpBits); + + if (storage > 1) + { + m_windowSize = (maxExpBits+storage-1)/storage; + m_exponentBase = Integer::Power2(m_windowSize); + } + + m_bases.resize(storage); + for (unsigned i=1; i void DL_FixedBasePrecomputationImpl::Load(const DL_GroupPrecomputation &group, BufferedTransformation &bt) +{ + BERSequenceDecoder seq(bt); + word32 version; + BERDecodeUnsigned(seq, version, INTEGER, 1, 1); + m_exponentBase.BERDecode(seq); + m_windowSize = m_exponentBase.BitCount() - 1; + m_bases.clear(); + while (!seq.EndReached()) + m_bases.push_back(group.BERDecodeElement(seq)); + if (!m_bases.empty() && group.NeedConversions()) + m_base = group.ConvertOut(m_bases[0]); + seq.MessageEnd(); +} + +template void DL_FixedBasePrecomputationImpl::Save(const DL_GroupPrecomputation &group, BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + DEREncodeUnsigned(seq, 1); // version + m_exponentBase.DEREncode(seq); + for (unsigned i=0; i void DL_FixedBasePrecomputationImpl::PrepareCascade(const DL_GroupPrecomputation &i_group, std::vector > &eb, const Integer &exponent) const +{ + const AbstractGroup &group = i_group.GetGroup(); + + Integer r, q, e = exponent; + bool fastNegate = group.InversionIsFast() && m_windowSize > 1; + unsigned int i; + + for (i=0; i+1(group.Inverse(m_bases[i]), m_exponentBase - r)); + } + else + eb.push_back(BaseAndExponent(m_bases[i], r)); + } + eb.push_back(BaseAndExponent(m_bases[i], e)); +} + +template T DL_FixedBasePrecomputationImpl::Exponentiate(const DL_GroupPrecomputation &group, const Integer &exponent) const +{ + std::vector > eb; // array of segments of the exponent and precalculated bases + eb.reserve(m_bases.size()); + PrepareCascade(group, eb, exponent); + return group.ConvertOut(GeneralCascadeMultiplication(group.GetGroup(), eb.begin(), eb.end())); +} + +template T + DL_FixedBasePrecomputationImpl::CascadeExponentiate(const DL_GroupPrecomputation &group, const Integer &exponent, + const DL_FixedBasePrecomputation &i_pc2, const Integer &exponent2) const +{ + std::vector > eb; // array of segments of the exponent and precalculated bases + const DL_FixedBasePrecomputationImpl &pc2 = static_cast &>(i_pc2); + eb.reserve(m_bases.size() + pc2.m_bases.size()); + PrepareCascade(group, eb, exponent); + pc2.PrepareCascade(group, eb, exponent2); + return group.ConvertOut(GeneralCascadeMultiplication(group.GetGroup(), eb.begin(), eb.end())); +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/eprecomp.h b/src-cryptopp/eprecomp.h new file mode 100644 index 0000000..1f32567 --- /dev/null +++ b/src-cryptopp/eprecomp.h @@ -0,0 +1,75 @@ +#ifndef CRYPTOPP_EPRECOMP_H +#define CRYPTOPP_EPRECOMP_H + +#include "integer.h" +#include "algebra.h" +#include + +NAMESPACE_BEGIN(CryptoPP) + +template +class DL_GroupPrecomputation +{ +public: + typedef T Element; + + virtual bool NeedConversions() const {return false;} + virtual Element ConvertIn(const Element &v) const {return v;} + virtual Element ConvertOut(const Element &v) const {return v;} + virtual const AbstractGroup & GetGroup() const =0; + virtual Element BERDecodeElement(BufferedTransformation &bt) const =0; + virtual void DEREncodeElement(BufferedTransformation &bt, const Element &P) const =0; +}; + +template +class DL_FixedBasePrecomputation +{ +public: + typedef T Element; + + virtual bool IsInitialized() const =0; + virtual void SetBase(const DL_GroupPrecomputation &group, const Element &base) =0; + virtual const Element & GetBase(const DL_GroupPrecomputation &group) const =0; + virtual void Precompute(const DL_GroupPrecomputation &group, unsigned int maxExpBits, unsigned int storage) =0; + virtual void Load(const DL_GroupPrecomputation &group, BufferedTransformation &storedPrecomputation) =0; + virtual void Save(const DL_GroupPrecomputation &group, BufferedTransformation &storedPrecomputation) const =0; + virtual Element Exponentiate(const DL_GroupPrecomputation &group, const Integer &exponent) const =0; + virtual Element CascadeExponentiate(const DL_GroupPrecomputation &group, const Integer &exponent, const DL_FixedBasePrecomputation &pc2, const Integer &exponent2) const =0; +}; + +template +class DL_FixedBasePrecomputationImpl : public DL_FixedBasePrecomputation +{ +public: + typedef T Element; + + DL_FixedBasePrecomputationImpl() : m_windowSize(0) {} + + // DL_FixedBasePrecomputation + bool IsInitialized() const + {return !m_bases.empty();} + void SetBase(const DL_GroupPrecomputation &group, const Element &base); + const Element & GetBase(const DL_GroupPrecomputation &group) const + {return group.NeedConversions() ? m_base : m_bases[0];} + void Precompute(const DL_GroupPrecomputation &group, unsigned int maxExpBits, unsigned int storage); + void Load(const DL_GroupPrecomputation &group, BufferedTransformation &storedPrecomputation); + void Save(const DL_GroupPrecomputation &group, BufferedTransformation &storedPrecomputation) const; + Element Exponentiate(const DL_GroupPrecomputation &group, const Integer &exponent) const; + Element CascadeExponentiate(const DL_GroupPrecomputation &group, const Integer &exponent, const DL_FixedBasePrecomputation &pc2, const Integer &exponent2) const; + +private: + void PrepareCascade(const DL_GroupPrecomputation &group, std::vector > &eb, const Integer &exponent) const; + + Element m_base; + unsigned int m_windowSize; + Integer m_exponentBase; // what base to represent the exponent in + std::vector m_bases; // precalculated bases +}; + +NAMESPACE_END + +#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES +#include "eprecomp.cpp" +#endif + +#endif diff --git a/src-cryptopp/extraversion.h b/src-cryptopp/extraversion.h new file mode 100644 index 0000000..4d31a23 --- /dev/null +++ b/src-cryptopp/extraversion.h @@ -0,0 +1,8 @@ + +/* This _version.py is generated from git metadata by the pycryptopp + * setup.py. The main version number is taken from the most recent release + * tag. If some patches have been added since the last release, this will + * have a -NN "build number" suffix, or else a -rNN "revision number" suffix. + */ + +#define CRYPTOPP_EXTRA_VERSION "pycryptopp-0.6.0.1206569328141510525648634803928199668821045408958" diff --git a/src-cryptopp/files.h b/src-cryptopp/files.h new file mode 100644 index 0000000..2c4e2b8 --- /dev/null +++ b/src-cryptopp/files.h @@ -0,0 +1,97 @@ +#ifndef CRYPTOPP_FILES_H +#define CRYPTOPP_FILES_H + +#include "cryptlib.h" +#include "filters.h" +#include "argnames.h" + +#include +#include + +NAMESPACE_BEGIN(CryptoPP) + +//! file-based implementation of Store interface +class CRYPTOPP_DLL FileStore : public Store, private FilterPutSpaceHelper, public NotCopyable +{ +public: + class Err : public Exception + { + public: + Err(const std::string &s) : Exception(IO_ERROR, s) {} + }; + class OpenErr : public Err {public: OpenErr(const std::string &filename) : Err("FileStore: error opening file for reading: " + filename) {}}; + class ReadErr : public Err {public: ReadErr() : Err("FileStore: error reading file") {}}; + + FileStore() : m_stream(NULL) {} + FileStore(std::istream &in) + {StoreInitialize(MakeParameters(Name::InputStreamPointer(), &in));} + FileStore(const char *filename) + {StoreInitialize(MakeParameters(Name::InputFileName(), filename));} + + std::istream* GetStream() {return m_stream;} + + lword MaxRetrievable() const; + size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); + size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const; + lword Skip(lword skipMax=ULONG_MAX); + +private: + void StoreInitialize(const NameValuePairs ¶meters); + + member_ptr m_file; + std::istream *m_stream; + byte *m_space; + size_t m_len; + bool m_waiting; +}; + +//! file-based implementation of Source interface +class CRYPTOPP_DLL FileSource : public SourceTemplate +{ +public: + typedef FileStore::Err Err; + typedef FileStore::OpenErr OpenErr; + typedef FileStore::ReadErr ReadErr; + + FileSource(BufferedTransformation *attachment = NULL) + : SourceTemplate(attachment) {} + FileSource(std::istream &in, bool pumpAll, BufferedTransformation *attachment = NULL) + : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputStreamPointer(), &in));} + FileSource(const char *filename, bool pumpAll, BufferedTransformation *attachment = NULL, bool binary=true) + : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputFileName(), filename)(Name::InputBinaryMode(), binary));} + + std::istream* GetStream() {return m_store.GetStream();} +}; + +//! file-based implementation of Sink interface +class CRYPTOPP_DLL FileSink : public Sink, public NotCopyable +{ +public: + class Err : public Exception + { + public: + Err(const std::string &s) : Exception(IO_ERROR, s) {} + }; + class OpenErr : public Err {public: OpenErr(const std::string &filename) : Err("FileSink: error opening file for writing: " + filename) {}}; + class WriteErr : public Err {public: WriteErr() : Err("FileSink: error writing file") {}}; + + FileSink() : m_stream(NULL) {} + FileSink(std::ostream &out) + {IsolatedInitialize(MakeParameters(Name::OutputStreamPointer(), &out));} + FileSink(const char *filename, bool binary=true) + {IsolatedInitialize(MakeParameters(Name::OutputFileName(), filename)("OutputBinaryMode", binary));} + + std::ostream* GetStream() {return m_stream;} + + void IsolatedInitialize(const NameValuePairs ¶meters); + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking); + bool IsolatedFlush(bool hardFlush, bool blocking); + +private: + member_ptr m_file; + std::ostream *m_stream; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/filters.cpp b/src-cryptopp/filters.cpp new file mode 100644 index 0000000..083dfd3 --- /dev/null +++ b/src-cryptopp/filters.cpp @@ -0,0 +1,1120 @@ +// filters.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "filters.h" +#include "mqueue.h" +#include "fltrimpl.h" +#include "argnames.h" +#include +#include + +NAMESPACE_BEGIN(CryptoPP) + +Filter::Filter(BufferedTransformation *attachment) + : m_attachment(attachment), m_continueAt(0) +{ +} + +BufferedTransformation * Filter::NewDefaultAttachment() const +{ + return new MessageQueue; +} + +BufferedTransformation * Filter::AttachedTransformation() +{ + if (m_attachment.get() == NULL) + m_attachment.reset(NewDefaultAttachment()); + return m_attachment.get(); +} + +const BufferedTransformation *Filter::AttachedTransformation() const +{ + if (m_attachment.get() == NULL) + const_cast(this)->m_attachment.reset(NewDefaultAttachment()); + return m_attachment.get(); +} + +void Filter::Detach(BufferedTransformation *newOut) +{ + m_attachment.reset(newOut); +} + +void Filter::Insert(Filter *filter) +{ + filter->m_attachment.reset(m_attachment.release()); + m_attachment.reset(filter); +} + +size_t Filter::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const +{ + return AttachedTransformation()->CopyRangeTo2(target, begin, end, channel, blocking); +} + +size_t Filter::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) +{ + return AttachedTransformation()->TransferTo2(target, transferBytes, channel, blocking); +} + +void Filter::Initialize(const NameValuePairs ¶meters, int propagation) +{ + m_continueAt = 0; + IsolatedInitialize(parameters); + PropagateInitialize(parameters, propagation); +} + +bool Filter::Flush(bool hardFlush, int propagation, bool blocking) +{ + switch (m_continueAt) + { + case 0: + if (IsolatedFlush(hardFlush, blocking)) + return true; + case 1: + if (OutputFlush(1, hardFlush, propagation, blocking)) + return true; + } + return false; +} + +bool Filter::MessageSeriesEnd(int propagation, bool blocking) +{ + switch (m_continueAt) + { + case 0: + if (IsolatedMessageSeriesEnd(blocking)) + return true; + case 1: + if (ShouldPropagateMessageSeriesEnd() && OutputMessageSeriesEnd(1, propagation, blocking)) + return true; + } + return false; +} + +void Filter::PropagateInitialize(const NameValuePairs ¶meters, int propagation) +{ + if (propagation) + AttachedTransformation()->Initialize(parameters, propagation-1); +} + +size_t Filter::OutputModifiable(int outputSite, byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel) +{ + if (messageEnd) + messageEnd--; + size_t result = AttachedTransformation()->ChannelPutModifiable2(channel, inString, length, messageEnd, blocking); + m_continueAt = result ? outputSite : 0; + return result; +} + +size_t Filter::Output(int outputSite, const byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel) +{ + if (messageEnd) + messageEnd--; + size_t result = AttachedTransformation()->ChannelPut2(channel, inString, length, messageEnd, blocking); + m_continueAt = result ? outputSite : 0; + return result; +} + +bool Filter::OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel) +{ + if (propagation && AttachedTransformation()->ChannelFlush(channel, hardFlush, propagation-1, blocking)) + { + m_continueAt = outputSite; + return true; + } + m_continueAt = 0; + return false; +} + +bool Filter::OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel) +{ + if (propagation && AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation-1, blocking)) + { + m_continueAt = outputSite; + return true; + } + m_continueAt = 0; + return false; +} + +// ************************************************************* + +void MeterFilter::ResetMeter() +{ + m_currentMessageBytes = m_totalBytes = m_currentSeriesMessages = m_totalMessages = m_totalMessageSeries = 0; + m_rangesToSkip.clear(); +} + +void MeterFilter::AddRangeToSkip(unsigned int message, lword position, lword size, bool sortNow) +{ + MessageRange r = {message, position, size}; + m_rangesToSkip.push_back(r); + if (sortNow) + std::sort(m_rangesToSkip.begin(), m_rangesToSkip.end()); +} + +size_t MeterFilter::PutMaybeModifiable(byte *begin, size_t length, int messageEnd, bool blocking, bool modifiable) +{ + if (!m_transparent) + return 0; + + size_t t; + FILTER_BEGIN; + + m_begin = begin; + m_length = length; + + while (m_length > 0 || messageEnd) + { + if (m_length > 0 && !m_rangesToSkip.empty() && m_rangesToSkip.front().message == m_totalMessages && m_currentMessageBytes + m_length > m_rangesToSkip.front().position) + { + FILTER_OUTPUT_MAYBE_MODIFIABLE(1, m_begin, t = (size_t)SaturatingSubtract(m_rangesToSkip.front().position, m_currentMessageBytes), false, modifiable); + + assert(t < m_length); + m_begin += t; + m_length -= t; + m_currentMessageBytes += t; + m_totalBytes += t; + + if (m_currentMessageBytes + m_length < m_rangesToSkip.front().position + m_rangesToSkip.front().size) + t = m_length; + else + { + t = (size_t)SaturatingSubtract(m_rangesToSkip.front().position + m_rangesToSkip.front().size, m_currentMessageBytes); + assert(t <= m_length); + m_rangesToSkip.pop_front(); + } + + m_begin += t; + m_length -= t; + m_currentMessageBytes += t; + m_totalBytes += t; + } + else + { + FILTER_OUTPUT_MAYBE_MODIFIABLE(2, m_begin, m_length, messageEnd, modifiable); + + m_currentMessageBytes += m_length; + m_totalBytes += m_length; + m_length = 0; + + if (messageEnd) + { + m_currentMessageBytes = 0; + m_currentSeriesMessages++; + m_totalMessages++; + messageEnd = false; + } + } + } + + FILTER_END_NO_MESSAGE_END; +} + +size_t MeterFilter::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) +{ + return PutMaybeModifiable(const_cast(begin), length, messageEnd, blocking, false); +} + +size_t MeterFilter::PutModifiable2(byte *begin, size_t length, int messageEnd, bool blocking) +{ + return PutMaybeModifiable(begin, length, messageEnd, blocking, true); +} + +bool MeterFilter::IsolatedMessageSeriesEnd(bool blocking) +{ + m_currentMessageBytes = 0; + m_currentSeriesMessages = 0; + m_totalMessageSeries++; + return false; +} + +// ************************************************************* + +void FilterWithBufferedInput::BlockQueue::ResetQueue(size_t blockSize, size_t maxBlocks) +{ + m_buffer.New(blockSize * maxBlocks); + m_blockSize = blockSize; + m_maxBlocks = maxBlocks; + m_size = 0; + m_begin = m_buffer; +} + +byte *FilterWithBufferedInput::BlockQueue::GetBlock() +{ + if (m_size >= m_blockSize) + { + byte *ptr = m_begin; + if ((m_begin+=m_blockSize) == m_buffer.end()) + m_begin = m_buffer; + m_size -= m_blockSize; + return ptr; + } + else + return NULL; +} + +byte *FilterWithBufferedInput::BlockQueue::GetContigousBlocks(size_t &numberOfBytes) +{ + numberOfBytes = STDMIN(numberOfBytes, STDMIN(size_t(m_buffer.end()-m_begin), m_size)); + byte *ptr = m_begin; + m_begin += numberOfBytes; + m_size -= numberOfBytes; + if (m_size == 0 || m_begin == m_buffer.end()) + m_begin = m_buffer; + return ptr; +} + +size_t FilterWithBufferedInput::BlockQueue::GetAll(byte *outString) +{ + size_t size = m_size; + size_t numberOfBytes = m_maxBlocks*m_blockSize; + const byte *ptr = GetContigousBlocks(numberOfBytes); + memcpy(outString, ptr, numberOfBytes); + memcpy(outString+numberOfBytes, m_begin, m_size); + m_size = 0; + return size; +} + +void FilterWithBufferedInput::BlockQueue::Put(const byte *inString, size_t length) +{ + assert(m_size + length <= m_buffer.size()); + byte *end = (m_size < size_t(m_buffer.end()-m_begin)) ? m_begin + m_size : m_begin + m_size - m_buffer.size(); + size_t len = STDMIN(length, size_t(m_buffer.end()-end)); + memcpy(end, inString, len); + if (len < length) + memcpy(m_buffer, inString+len, length-len); + m_size += length; +} + +FilterWithBufferedInput::FilterWithBufferedInput(BufferedTransformation *attachment) + : Filter(attachment) +{ +} + +FilterWithBufferedInput::FilterWithBufferedInput(size_t firstSize, size_t blockSize, size_t lastSize, BufferedTransformation *attachment) + : Filter(attachment), m_firstSize(firstSize), m_blockSize(blockSize), m_lastSize(lastSize) + , m_firstInputDone(false) +{ + if (m_firstSize < 0 || m_blockSize < 1 || m_lastSize < 0) + throw InvalidArgument("FilterWithBufferedInput: invalid buffer size"); + + m_queue.ResetQueue(1, m_firstSize); +} + +void FilterWithBufferedInput::IsolatedInitialize(const NameValuePairs ¶meters) +{ + InitializeDerivedAndReturnNewSizes(parameters, m_firstSize, m_blockSize, m_lastSize); + if (m_firstSize < 0 || m_blockSize < 1 || m_lastSize < 0) + throw InvalidArgument("FilterWithBufferedInput: invalid buffer size"); + m_queue.ResetQueue(1, m_firstSize); + m_firstInputDone = false; +} + +bool FilterWithBufferedInput::IsolatedFlush(bool hardFlush, bool blocking) +{ + if (!blocking) + throw BlockingInputOnly("FilterWithBufferedInput"); + + if (hardFlush) + ForceNextPut(); + FlushDerived(); + + return false; +} + +size_t FilterWithBufferedInput::PutMaybeModifiable(byte *inString, size_t length, int messageEnd, bool blocking, bool modifiable) +{ + if (!blocking) + throw BlockingInputOnly("FilterWithBufferedInput"); + + if (length != 0) + { + size_t newLength = m_queue.CurrentSize() + length; + + if (!m_firstInputDone && newLength >= m_firstSize) + { + size_t len = m_firstSize - m_queue.CurrentSize(); + m_queue.Put(inString, len); + FirstPut(m_queue.GetContigousBlocks(m_firstSize)); + assert(m_queue.CurrentSize() == 0); + m_queue.ResetQueue(m_blockSize, (2*m_blockSize+m_lastSize-2)/m_blockSize); + + inString += len; + newLength -= m_firstSize; + m_firstInputDone = true; + } + + if (m_firstInputDone) + { + if (m_blockSize == 1) + { + while (newLength > m_lastSize && m_queue.CurrentSize() > 0) + { + size_t len = newLength - m_lastSize; + byte *ptr = m_queue.GetContigousBlocks(len); + NextPutModifiable(ptr, len); + newLength -= len; + } + + if (newLength > m_lastSize) + { + size_t len = newLength - m_lastSize; + NextPutMaybeModifiable(inString, len, modifiable); + inString += len; + newLength -= len; + } + } + else + { + while (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() >= m_blockSize) + { + NextPutModifiable(m_queue.GetBlock(), m_blockSize); + newLength -= m_blockSize; + } + + if (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() > 0) + { + assert(m_queue.CurrentSize() < m_blockSize); + size_t len = m_blockSize - m_queue.CurrentSize(); + m_queue.Put(inString, len); + inString += len; + NextPutModifiable(m_queue.GetBlock(), m_blockSize); + newLength -= m_blockSize; + } + + if (newLength >= m_blockSize + m_lastSize) + { + size_t len = RoundDownToMultipleOf(newLength - m_lastSize, m_blockSize); + NextPutMaybeModifiable(inString, len, modifiable); + inString += len; + newLength -= len; + } + } + } + + m_queue.Put(inString, newLength - m_queue.CurrentSize()); + } + + if (messageEnd) + { + if (!m_firstInputDone && m_firstSize==0) + FirstPut(NULL); + + SecByteBlock temp(m_queue.CurrentSize()); + m_queue.GetAll(temp); + LastPut(temp, temp.size()); + + m_firstInputDone = false; + m_queue.ResetQueue(1, m_firstSize); + + Output(1, NULL, 0, messageEnd, blocking); + } + return 0; +} + +void FilterWithBufferedInput::ForceNextPut() +{ + if (!m_firstInputDone) + return; + + if (m_blockSize > 1) + { + while (m_queue.CurrentSize() >= m_blockSize) + NextPutModifiable(m_queue.GetBlock(), m_blockSize); + } + else + { + size_t len; + while ((len = m_queue.CurrentSize()) > 0) + NextPutModifiable(m_queue.GetContigousBlocks(len), len); + } +} + +void FilterWithBufferedInput::NextPutMultiple(const byte *inString, size_t length) +{ + assert(m_blockSize > 1); // m_blockSize = 1 should always override this function + while (length > 0) + { + assert(length >= m_blockSize); + NextPutSingle(inString); + inString += m_blockSize; + length -= m_blockSize; + } +} + +// ************************************************************* + +void Redirector::Initialize(const NameValuePairs ¶meters, int propagation) +{ + m_target = parameters.GetValueWithDefault("RedirectionTargetPointer", (BufferedTransformation*)NULL); + m_behavior = parameters.GetIntValueWithDefault("RedirectionBehavior", PASS_EVERYTHING); + + if (m_target && GetPassSignals()) + m_target->Initialize(parameters, propagation); +} + +// ************************************************************* + +ProxyFilter::ProxyFilter(BufferedTransformation *filter, size_t firstSize, size_t lastSize, BufferedTransformation *attachment) + : FilterWithBufferedInput(firstSize, 1, lastSize, attachment), m_filter(filter) +{ + if (m_filter.get()) + m_filter->Attach(new OutputProxy(*this, false)); +} + +bool ProxyFilter::IsolatedFlush(bool hardFlush, bool blocking) +{ + return m_filter.get() ? m_filter->Flush(hardFlush, -1, blocking) : false; +} + +void ProxyFilter::SetFilter(Filter *filter) +{ + m_filter.reset(filter); + if (filter) + { + OutputProxy *proxy; + std::auto_ptr temp(proxy = new OutputProxy(*this, false)); + m_filter->TransferAllTo(*proxy); + m_filter->Attach(temp.release()); + } +} + +void ProxyFilter::NextPutMultiple(const byte *s, size_t len) +{ + if (m_filter.get()) + m_filter->Put(s, len); +} + +void ProxyFilter::NextPutModifiable(byte *s, size_t len) +{ + if (m_filter.get()) + m_filter->PutModifiable(s, len); +} + +// ************************************************************* + +void RandomNumberSink::IsolatedInitialize(const NameValuePairs ¶meters) +{ + parameters.GetRequiredParameter("RandomNumberSink", "RandomNumberGeneratorPointer", m_rng); +} + +size_t RandomNumberSink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) +{ + m_rng->IncorporateEntropy(begin, length); + return 0; +} + +size_t ArraySink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) +{ + if (m_buf+m_total != begin) + memcpy(m_buf+m_total, begin, STDMIN(length, SaturatingSubtract(m_size, m_total))); + m_total += length; + return 0; +} + +byte * ArraySink::CreatePutSpace(size_t &size) +{ + size = SaturatingSubtract(m_size, m_total); + return m_buf + m_total; +} + +void ArraySink::IsolatedInitialize(const NameValuePairs ¶meters) +{ + ByteArrayParameter array; + if (!parameters.GetValue(Name::OutputBuffer(), array)) + throw InvalidArgument("ArraySink: missing OutputBuffer argument"); + m_buf = array.begin(); + m_size = array.size(); + m_total = 0; +} + +size_t ArrayXorSink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) +{ + xorbuf(m_buf+m_total, begin, STDMIN(length, SaturatingSubtract(m_size, m_total))); + m_total += length; + return 0; +} + +// ************************************************************* + +StreamTransformationFilter::StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment, BlockPaddingScheme padding, bool allowAuthenticatedSymmetricCipher) + : FilterWithBufferedInput(attachment) + , m_cipher(c) +{ + assert(c.MinLastBlockSize() == 0 || c.MinLastBlockSize() > c.MandatoryBlockSize()); + + if (!allowAuthenticatedSymmetricCipher && dynamic_cast(&c) != 0) + throw InvalidArgument("StreamTransformationFilter: please use AuthenticatedEncryptionFilter and AuthenticatedDecryptionFilter for AuthenticatedSymmetricCipher"); + + IsolatedInitialize(MakeParameters(Name::BlockPaddingScheme(), padding)); +} + +size_t StreamTransformationFilter::LastBlockSize(StreamTransformation &c, BlockPaddingScheme padding) +{ + if (c.MinLastBlockSize() > 0) + return c.MinLastBlockSize(); + else if (c.MandatoryBlockSize() > 1 && !c.IsForwardTransformation() && padding != NO_PADDING && padding != ZEROS_PADDING) + return c.MandatoryBlockSize(); + else + return 0; +} + +void StreamTransformationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize) +{ + BlockPaddingScheme padding = parameters.GetValueWithDefault(Name::BlockPaddingScheme(), DEFAULT_PADDING); + bool isBlockCipher = (m_cipher.MandatoryBlockSize() > 1 && m_cipher.MinLastBlockSize() == 0); + + if (padding == DEFAULT_PADDING) + m_padding = isBlockCipher ? PKCS_PADDING : NO_PADDING; + else + m_padding = padding; + + if (!isBlockCipher && (m_padding == PKCS_PADDING || m_padding == ONE_AND_ZEROS_PADDING)) + throw InvalidArgument("StreamTransformationFilter: PKCS_PADDING and ONE_AND_ZEROS_PADDING cannot be used with " + m_cipher.AlgorithmName()); + + firstSize = 0; + blockSize = m_cipher.MandatoryBlockSize(); + lastSize = LastBlockSize(m_cipher, m_padding); +} + +void StreamTransformationFilter::FirstPut(const byte *inString) +{ + m_optimalBufferSize = m_cipher.OptimalBlockSize(); + m_optimalBufferSize = (unsigned int)STDMAX(m_optimalBufferSize, RoundDownToMultipleOf(4096U, m_optimalBufferSize)); +} + +void StreamTransformationFilter::NextPutMultiple(const byte *inString, size_t length) +{ + if (!length) + return; + + size_t s = m_cipher.MandatoryBlockSize(); + + do + { + size_t len = m_optimalBufferSize; + byte *space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, s, length, len); + if (len < length) + { + if (len == m_optimalBufferSize) + len -= m_cipher.GetOptimalBlockSizeUsed(); + len = RoundDownToMultipleOf(len, s); + } + else + len = length; + m_cipher.ProcessString(space, inString, len); + AttachedTransformation()->PutModifiable(space, len); + inString += len; + length -= len; + } + while (length > 0); +} + +void StreamTransformationFilter::NextPutModifiable(byte *inString, size_t length) +{ + m_cipher.ProcessString(inString, length); + AttachedTransformation()->PutModifiable(inString, length); +} + +void StreamTransformationFilter::LastPut(const byte *inString, size_t length) +{ + byte *space = NULL; + + switch (m_padding) + { + case NO_PADDING: + case ZEROS_PADDING: + if (length > 0) + { + size_t minLastBlockSize = m_cipher.MinLastBlockSize(); + bool isForwardTransformation = m_cipher.IsForwardTransformation(); + + if (isForwardTransformation && m_padding == ZEROS_PADDING && (minLastBlockSize == 0 || length < minLastBlockSize)) + { + // do padding + size_t blockSize = STDMAX(minLastBlockSize, (size_t)m_cipher.MandatoryBlockSize()); + space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, blockSize); + memcpy(space, inString, length); + memset(space + length, 0, blockSize - length); + m_cipher.ProcessLastBlock(space, space, blockSize); + AttachedTransformation()->Put(space, blockSize); + } + else + { + if (minLastBlockSize == 0) + { + if (isForwardTransformation) + throw InvalidDataFormat("StreamTransformationFilter: plaintext length is not a multiple of block size and NO_PADDING is specified"); + else + throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size"); + } + + space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, length, m_optimalBufferSize); + m_cipher.ProcessLastBlock(space, inString, length); + AttachedTransformation()->Put(space, length); + } + } + break; + + case PKCS_PADDING: + case ONE_AND_ZEROS_PADDING: + unsigned int s; + s = m_cipher.MandatoryBlockSize(); + assert(s > 1); + space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, s, m_optimalBufferSize); + if (m_cipher.IsForwardTransformation()) + { + assert(length < s); + memcpy(space, inString, length); + if (m_padding == PKCS_PADDING) + { + assert(s < 256); + byte pad = byte(s-length); + memset(space+length, pad, s-length); + } + else + { + space[length] = 0x80; + memset(space+length+1, 0, s-length-1); + } + m_cipher.ProcessData(space, space, s); + AttachedTransformation()->Put(space, s); + } + else + { + if (length != s) + throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size"); + m_cipher.ProcessData(space, inString, s); + if (m_padding == PKCS_PADDING) + { + byte pad = space[s-1]; + if (pad < 1 || pad > s || std::find_if(space+s-pad, space+s, std::bind2nd(std::not_equal_to(), pad)) != space+s) + throw InvalidCiphertext("StreamTransformationFilter: invalid PKCS #7 block padding found"); + length = s-pad; + } + else + { + while (length > 1 && space[length-1] == 0) + --length; + if (space[--length] != 0x80) + throw InvalidCiphertext("StreamTransformationFilter: invalid ones-and-zeros padding found"); + } + AttachedTransformation()->Put(space, length); + } + break; + + default: + assert(false); + } +} + +// ************************************************************* + +HashFilter::HashFilter(HashTransformation &hm, BufferedTransformation *attachment, bool putMessage, int truncatedDigestSize, const std::string &messagePutChannel, const std::string &hashPutChannel) + : m_hashModule(hm), m_putMessage(putMessage), m_messagePutChannel(messagePutChannel), m_hashPutChannel(hashPutChannel) +{ + m_digestSize = truncatedDigestSize < 0 ? m_hashModule.DigestSize() : truncatedDigestSize; + Detach(attachment); +} + +void HashFilter::IsolatedInitialize(const NameValuePairs ¶meters) +{ + m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false); + int s = parameters.GetIntValueWithDefault(Name::TruncatedDigestSize(), -1); + m_digestSize = s < 0 ? m_hashModule.DigestSize() : s; +} + +size_t HashFilter::Put2(const byte *inString, size_t length, int messageEnd, bool blocking) +{ + FILTER_BEGIN; + if (m_putMessage) + FILTER_OUTPUT3(1, 0, inString, length, 0, m_messagePutChannel); + m_hashModule.Update(inString, length); + if (messageEnd) + { + { + size_t size; + m_space = HelpCreatePutSpace(*AttachedTransformation(), m_hashPutChannel, m_digestSize, m_digestSize, size = m_digestSize); + m_hashModule.TruncatedFinal(m_space, m_digestSize); + } + FILTER_OUTPUT3(2, 0, m_space, m_digestSize, messageEnd, m_hashPutChannel); + } + FILTER_END_NO_MESSAGE_END; +} + +// ************************************************************* + +HashVerificationFilter::HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment, word32 flags, int truncatedDigestSize) + : FilterWithBufferedInput(attachment) + , m_hashModule(hm) +{ + IsolatedInitialize(MakeParameters(Name::HashVerificationFilterFlags(), flags)(Name::TruncatedDigestSize(), truncatedDigestSize)); +} + +void HashVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize) +{ + m_flags = parameters.GetValueWithDefault(Name::HashVerificationFilterFlags(), (word32)DEFAULT_FLAGS); + int s = parameters.GetIntValueWithDefault(Name::TruncatedDigestSize(), -1); + m_digestSize = s < 0 ? m_hashModule.DigestSize() : s; + m_verified = false; + firstSize = m_flags & HASH_AT_BEGIN ? m_digestSize : 0; + blockSize = 1; + lastSize = m_flags & HASH_AT_BEGIN ? 0 : m_digestSize; +} + +void HashVerificationFilter::FirstPut(const byte *inString) +{ + if (m_flags & HASH_AT_BEGIN) + { + m_expectedHash.New(m_digestSize); + memcpy(m_expectedHash, inString, m_expectedHash.size()); + if (m_flags & PUT_HASH) + AttachedTransformation()->Put(inString, m_expectedHash.size()); + } +} + +void HashVerificationFilter::NextPutMultiple(const byte *inString, size_t length) +{ + m_hashModule.Update(inString, length); + if (m_flags & PUT_MESSAGE) + AttachedTransformation()->Put(inString, length); +} + +void HashVerificationFilter::LastPut(const byte *inString, size_t length) +{ + if (m_flags & HASH_AT_BEGIN) + { + assert(length == 0); + m_verified = m_hashModule.TruncatedVerify(m_expectedHash, m_digestSize); + } + else + { + m_verified = (length==m_digestSize && m_hashModule.TruncatedVerify(inString, length)); + if (m_flags & PUT_HASH) + AttachedTransformation()->Put(inString, length); + } + + if (m_flags & PUT_RESULT) + AttachedTransformation()->Put(m_verified); + + if ((m_flags & THROW_EXCEPTION) && !m_verified) + throw HashVerificationFailed(); +} + +// ************************************************************* + +AuthenticatedEncryptionFilter::AuthenticatedEncryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment, + bool putAAD, int truncatedDigestSize, const std::string &macChannel, BlockPaddingScheme padding) + : StreamTransformationFilter(c, attachment, padding, true) + , m_hf(c, new OutputProxy(*this, false), putAAD, truncatedDigestSize, AAD_CHANNEL, macChannel) +{ + assert(c.IsForwardTransformation()); +} + +void AuthenticatedEncryptionFilter::IsolatedInitialize(const NameValuePairs ¶meters) +{ + m_hf.IsolatedInitialize(parameters); + StreamTransformationFilter::IsolatedInitialize(parameters); +} + +byte * AuthenticatedEncryptionFilter::ChannelCreatePutSpace(const std::string &channel, size_t &size) +{ + if (channel.empty()) + return StreamTransformationFilter::CreatePutSpace(size); + + if (channel == AAD_CHANNEL) + return m_hf.CreatePutSpace(size); + + throw InvalidChannelName("AuthenticatedEncryptionFilter", channel); +} + +size_t AuthenticatedEncryptionFilter::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) +{ + if (channel.empty()) + return StreamTransformationFilter::Put2(begin, length, messageEnd, blocking); + + if (channel == AAD_CHANNEL) + return m_hf.Put2(begin, length, 0, blocking); + + throw InvalidChannelName("AuthenticatedEncryptionFilter", channel); +} + +void AuthenticatedEncryptionFilter::LastPut(const byte *inString, size_t length) +{ + StreamTransformationFilter::LastPut(inString, length); + m_hf.MessageEnd(); +} + +// ************************************************************* + +AuthenticatedDecryptionFilter::AuthenticatedDecryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment, word32 flags, int truncatedDigestSize, BlockPaddingScheme padding) + : FilterWithBufferedInput(attachment) + , m_hashVerifier(c, new OutputProxy(*this, false)) + , m_streamFilter(c, new OutputProxy(*this, false), padding, true) +{ + assert(!c.IsForwardTransformation() || c.IsSelfInverting()); + IsolatedInitialize(MakeParameters(Name::BlockPaddingScheme(), padding)(Name::AuthenticatedDecryptionFilterFlags(), flags)(Name::TruncatedDigestSize(), truncatedDigestSize)); +} + +void AuthenticatedDecryptionFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize) +{ + word32 flags = parameters.GetValueWithDefault(Name::AuthenticatedDecryptionFilterFlags(), (word32)DEFAULT_FLAGS); + + m_hashVerifier.Initialize(CombinedNameValuePairs(parameters, MakeParameters(Name::HashVerificationFilterFlags(), flags))); + m_streamFilter.Initialize(parameters); + + firstSize = m_hashVerifier.m_firstSize; + blockSize = 1; + lastSize = m_hashVerifier.m_lastSize; +} + +byte * AuthenticatedDecryptionFilter::ChannelCreatePutSpace(const std::string &channel, size_t &size) +{ + if (channel.empty()) + return m_streamFilter.CreatePutSpace(size); + + if (channel == AAD_CHANNEL) + return m_hashVerifier.CreatePutSpace(size); + + throw InvalidChannelName("AuthenticatedDecryptionFilter", channel); +} + +size_t AuthenticatedDecryptionFilter::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) +{ + if (channel.empty()) + { + if (m_lastSize > 0) + m_hashVerifier.ForceNextPut(); + return FilterWithBufferedInput::Put2(begin, length, messageEnd, blocking); + } + + if (channel == AAD_CHANNEL) + return m_hashVerifier.Put2(begin, length, 0, blocking); + + throw InvalidChannelName("AuthenticatedDecryptionFilter", channel); +} + +void AuthenticatedDecryptionFilter::FirstPut(const byte *inString) +{ + m_hashVerifier.Put(inString, m_firstSize); +} + +void AuthenticatedDecryptionFilter::NextPutMultiple(const byte *inString, size_t length) +{ + m_streamFilter.Put(inString, length); +} + +void AuthenticatedDecryptionFilter::LastPut(const byte *inString, size_t length) +{ + m_streamFilter.MessageEnd(); + m_hashVerifier.PutMessageEnd(inString, length); +} + +// ************************************************************* + +void SignerFilter::IsolatedInitialize(const NameValuePairs ¶meters) +{ + m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false); + m_messageAccumulator.reset(m_signer.NewSignatureAccumulator(m_rng)); +} + +size_t SignerFilter::Put2(const byte *inString, size_t length, int messageEnd, bool blocking) +{ + FILTER_BEGIN; + m_messageAccumulator->Update(inString, length); + if (m_putMessage) + FILTER_OUTPUT(1, inString, length, 0); + if (messageEnd) + { + m_buf.New(m_signer.SignatureLength()); + m_signer.Sign(m_rng, m_messageAccumulator.release(), m_buf); + FILTER_OUTPUT(2, m_buf, m_buf.size(), messageEnd); + m_messageAccumulator.reset(m_signer.NewSignatureAccumulator(m_rng)); + } + FILTER_END_NO_MESSAGE_END; +} + +SignatureVerificationFilter::SignatureVerificationFilter(const PK_Verifier &verifier, BufferedTransformation *attachment, word32 flags) + : FilterWithBufferedInput(attachment) + , m_verifier(verifier) +{ + IsolatedInitialize(MakeParameters(Name::SignatureVerificationFilterFlags(), flags)); +} + +void SignatureVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize) +{ + m_flags = parameters.GetValueWithDefault(Name::SignatureVerificationFilterFlags(), (word32)DEFAULT_FLAGS); + m_messageAccumulator.reset(m_verifier.NewVerificationAccumulator()); + size_t size = m_verifier.SignatureLength(); + assert(size != 0); // TODO: handle recoverable signature scheme + m_verified = false; + firstSize = m_flags & SIGNATURE_AT_BEGIN ? size : 0; + blockSize = 1; + lastSize = m_flags & SIGNATURE_AT_BEGIN ? 0 : size; +} + +void SignatureVerificationFilter::FirstPut(const byte *inString) +{ + if (m_flags & SIGNATURE_AT_BEGIN) + { + if (m_verifier.SignatureUpfront()) + m_verifier.InputSignature(*m_messageAccumulator, inString, m_verifier.SignatureLength()); + else + { + m_signature.New(m_verifier.SignatureLength()); + memcpy(m_signature, inString, m_signature.size()); + } + + if (m_flags & PUT_SIGNATURE) + AttachedTransformation()->Put(inString, m_signature.size()); + } + else + { + assert(!m_verifier.SignatureUpfront()); + } +} + +void SignatureVerificationFilter::NextPutMultiple(const byte *inString, size_t length) +{ + m_messageAccumulator->Update(inString, length); + if (m_flags & PUT_MESSAGE) + AttachedTransformation()->Put(inString, length); +} + +void SignatureVerificationFilter::LastPut(const byte *inString, size_t length) +{ + if (m_flags & SIGNATURE_AT_BEGIN) + { + assert(length == 0); + m_verifier.InputSignature(*m_messageAccumulator, m_signature, m_signature.size()); + m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator); + } + else + { + m_verifier.InputSignature(*m_messageAccumulator, inString, length); + m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator); + if (m_flags & PUT_SIGNATURE) + AttachedTransformation()->Put(inString, length); + } + + if (m_flags & PUT_RESULT) + AttachedTransformation()->Put(m_verified); + + if ((m_flags & THROW_EXCEPTION) && !m_verified) + throw SignatureVerificationFailed(); +} + +// ************************************************************* + +size_t Source::PumpAll2(bool blocking) +{ + unsigned int messageCount = UINT_MAX; + do { + RETURN_IF_NONZERO(PumpMessages2(messageCount, blocking)); + } while(messageCount == UINT_MAX); + + return 0; +} + +bool Store::GetNextMessage() +{ + if (!m_messageEnd && !AnyRetrievable()) + { + m_messageEnd=true; + return true; + } + else + return false; +} + +unsigned int Store::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const +{ + if (m_messageEnd || count == 0) + return 0; + else + { + CopyTo(target, ULONG_MAX, channel); + if (GetAutoSignalPropagation()) + target.ChannelMessageEnd(channel, GetAutoSignalPropagation()-1); + return 1; + } +} + +void StringStore::StoreInitialize(const NameValuePairs ¶meters) +{ + ConstByteArrayParameter array; + if (!parameters.GetValue(Name::InputBuffer(), array)) + throw InvalidArgument("StringStore: missing InputBuffer argument"); + m_store = array.begin(); + m_length = array.size(); + m_count = 0; +} + +size_t StringStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) +{ + lword position = 0; + size_t blockedBytes = CopyRangeTo2(target, position, transferBytes, channel, blocking); + m_count += (size_t)position; + transferBytes = position; + return blockedBytes; +} + +size_t StringStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const +{ + size_t i = UnsignedMin(m_length, m_count+begin); + size_t len = UnsignedMin(m_length-i, end-begin); + size_t blockedBytes = target.ChannelPut2(channel, m_store+i, len, 0, blocking); + if (!blockedBytes) + begin += len; + return blockedBytes; +} + +void RandomNumberStore::StoreInitialize(const NameValuePairs ¶meters) +{ + parameters.GetRequiredParameter("RandomNumberStore", "RandomNumberGeneratorPointer", m_rng); + int length; + parameters.GetRequiredIntParameter("RandomNumberStore", "RandomNumberStoreSize", length); + m_length = length; +} + +size_t RandomNumberStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) +{ + if (!blocking) + throw NotImplemented("RandomNumberStore: nonblocking transfer is not implemented by this object"); + + transferBytes = UnsignedMin(transferBytes, m_length - m_count); + m_rng->GenerateIntoBufferedTransformation(target, channel, transferBytes); + m_count += transferBytes; + + return 0; +} + +size_t NullStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const +{ + static const byte nullBytes[128] = {0}; + while (begin < end) + { + size_t len = (size_t)STDMIN(end-begin, lword(128)); + size_t blockedBytes = target.ChannelPut2(channel, nullBytes, len, 0, blocking); + if (blockedBytes) + return blockedBytes; + begin += len; + } + return 0; +} + +size_t NullStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) +{ + lword begin = 0; + size_t blockedBytes = NullStore::CopyRangeTo2(target, begin, transferBytes, channel, blocking); + transferBytes = begin; + m_size -= begin; + return blockedBytes; +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/filters.h b/src-cryptopp/filters.h new file mode 100644 index 0000000..b2194ca --- /dev/null +++ b/src-cryptopp/filters.h @@ -0,0 +1,808 @@ +#ifndef CRYPTOPP_FILTERS_H +#define CRYPTOPP_FILTERS_H + +#include "simple.h" +#include "secblock.h" +#include "misc.h" +#include "smartptr.h" +#include "queue.h" +#include "algparam.h" +#include + +NAMESPACE_BEGIN(CryptoPP) + +/// provides an implementation of BufferedTransformation's attachment interface +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Filter : public BufferedTransformation, public NotCopyable +{ +public: + Filter(BufferedTransformation *attachment = NULL); + + bool Attachable() {return true;} + BufferedTransformation *AttachedTransformation(); + const BufferedTransformation *AttachedTransformation() const; + void Detach(BufferedTransformation *newAttachment = NULL); + + size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); + size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const; + + void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1); + bool Flush(bool hardFlush, int propagation=-1, bool blocking=true); + bool MessageSeriesEnd(int propagation=-1, bool blocking=true); + +protected: + virtual BufferedTransformation * NewDefaultAttachment() const; + void Insert(Filter *nextFilter); // insert filter after this one + + virtual bool ShouldPropagateMessageEnd() const {return true;} + virtual bool ShouldPropagateMessageSeriesEnd() const {return true;} + + void PropagateInitialize(const NameValuePairs ¶meters, int propagation); + + size_t Output(int outputSite, const byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel=DEFAULT_CHANNEL); + size_t OutputModifiable(int outputSite, byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel=DEFAULT_CHANNEL); + bool OutputMessageEnd(int outputSite, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL); + bool OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL); + bool OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL); + +private: + member_ptr m_attachment; + +protected: + size_t m_inputPosition; + int m_continueAt; +}; + +struct CRYPTOPP_DLL FilterPutSpaceHelper +{ + // desiredSize is how much to ask target, bufferSize is how much to allocate in m_tempSpace + byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize, size_t desiredSize, size_t &bufferSize) + { + assert(desiredSize >= minSize && bufferSize >= minSize); + if (m_tempSpace.size() < minSize) + { + byte *result = target.ChannelCreatePutSpace(channel, desiredSize); + if (desiredSize >= minSize) + { + bufferSize = desiredSize; + return result; + } + m_tempSpace.New(bufferSize); + } + + bufferSize = m_tempSpace.size(); + return m_tempSpace.begin(); + } + byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize) + {return HelpCreatePutSpace(target, channel, minSize, minSize, minSize);} + byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize, size_t bufferSize) + {return HelpCreatePutSpace(target, channel, minSize, minSize, bufferSize);} + SecByteBlock m_tempSpace; +}; + +//! measure how many byte and messages pass through, also serves as valve +class CRYPTOPP_DLL MeterFilter : public Bufferless +{ +public: + MeterFilter(BufferedTransformation *attachment=NULL, bool transparent=true) + : m_transparent(transparent) {Detach(attachment); ResetMeter();} + + void SetTransparent(bool transparent) {m_transparent = transparent;} + void AddRangeToSkip(unsigned int message, lword position, lword size, bool sortNow = true); + void ResetMeter(); + void IsolatedInitialize(const NameValuePairs ¶meters) {ResetMeter();} + + lword GetCurrentMessageBytes() const {return m_currentMessageBytes;} + lword GetTotalBytes() {return m_totalBytes;} + unsigned int GetCurrentSeriesMessages() {return m_currentSeriesMessages;} + unsigned int GetTotalMessages() {return m_totalMessages;} + unsigned int GetTotalMessageSeries() {return m_totalMessageSeries;} + + byte * CreatePutSpace(size_t &size) + {return AttachedTransformation()->CreatePutSpace(size);} + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); + size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking); + bool IsolatedMessageSeriesEnd(bool blocking); + +private: + size_t PutMaybeModifiable(byte *inString, size_t length, int messageEnd, bool blocking, bool modifiable); + bool ShouldPropagateMessageEnd() const {return m_transparent;} + bool ShouldPropagateMessageSeriesEnd() const {return m_transparent;} + + struct MessageRange + { + inline bool operator<(const MessageRange &b) const // BCB2006 workaround: this has to be a member function + {return message < b.message || (message == b.message && position < b.position);} + unsigned int message; lword position; lword size; + }; + + bool m_transparent; + lword m_currentMessageBytes, m_totalBytes; + unsigned int m_currentSeriesMessages, m_totalMessages, m_totalMessageSeries; + std::deque m_rangesToSkip; + byte *m_begin; + size_t m_length; +}; + +//! _ +class CRYPTOPP_DLL TransparentFilter : public MeterFilter +{ +public: + TransparentFilter(BufferedTransformation *attachment=NULL) : MeterFilter(attachment, true) {} +}; + +//! _ +class CRYPTOPP_DLL OpaqueFilter : public MeterFilter +{ +public: + OpaqueFilter(BufferedTransformation *attachment=NULL) : MeterFilter(attachment, false) {} +}; + +/*! FilterWithBufferedInput divides up the input stream into + a first block, a number of middle blocks, and a last block. + First and last blocks are optional, and middle blocks may + be a stream instead (i.e. blockSize == 1). +*/ +class CRYPTOPP_DLL FilterWithBufferedInput : public Filter +{ +public: + FilterWithBufferedInput(BufferedTransformation *attachment); + //! firstSize and lastSize may be 0, blockSize must be at least 1 + FilterWithBufferedInput(size_t firstSize, size_t blockSize, size_t lastSize, BufferedTransformation *attachment); + + void IsolatedInitialize(const NameValuePairs ¶meters); + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) + { + return PutMaybeModifiable(const_cast(inString), length, messageEnd, blocking, false); + } + size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking) + { + return PutMaybeModifiable(inString, length, messageEnd, blocking, true); + } + /*! calls ForceNextPut() if hardFlush is true */ + bool IsolatedFlush(bool hardFlush, bool blocking); + + /*! The input buffer may contain more than blockSize bytes if lastSize != 0. + ForceNextPut() forces a call to NextPut() if this is the case. + */ + void ForceNextPut(); + +protected: + bool DidFirstPut() {return m_firstInputDone;} + + virtual void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize) + {InitializeDerived(parameters);} + virtual void InitializeDerived(const NameValuePairs ¶meters) {} + // FirstPut() is called if (firstSize != 0 and totalLength >= firstSize) + // or (firstSize == 0 and (totalLength > 0 or a MessageEnd() is received)) + virtual void FirstPut(const byte *inString) =0; + // NextPut() is called if totalLength >= firstSize+blockSize+lastSize + virtual void NextPutSingle(const byte *inString) {assert(false);} + // Same as NextPut() except length can be a multiple of blockSize + // Either NextPut() or NextPutMultiple() must be overriden + virtual void NextPutMultiple(const byte *inString, size_t length); + // Same as NextPutMultiple(), but inString can be modified + virtual void NextPutModifiable(byte *inString, size_t length) + {NextPutMultiple(inString, length);} + // LastPut() is always called + // if totalLength < firstSize then length == totalLength + // else if totalLength <= firstSize+lastSize then length == totalLength-firstSize + // else lastSize <= length < lastSize+blockSize + virtual void LastPut(const byte *inString, size_t length) =0; + virtual void FlushDerived() {} + +protected: + size_t PutMaybeModifiable(byte *begin, size_t length, int messageEnd, bool blocking, bool modifiable); + void NextPutMaybeModifiable(byte *inString, size_t length, bool modifiable) + { + if (modifiable) NextPutModifiable(inString, length); + else NextPutMultiple(inString, length); + } + + // This function should no longer be used, put this here to cause a compiler error + // if someone tries to override NextPut(). + virtual int NextPut(const byte *inString, size_t length) {assert(false); return 0;} + + class BlockQueue + { + public: + void ResetQueue(size_t blockSize, size_t maxBlocks); + byte *GetBlock(); + byte *GetContigousBlocks(size_t &numberOfBytes); + size_t GetAll(byte *outString); + void Put(const byte *inString, size_t length); + size_t CurrentSize() const {return m_size;} + size_t MaxSize() const {return m_buffer.size();} + + private: + SecByteBlock m_buffer; + size_t m_blockSize, m_maxBlocks, m_size; + byte *m_begin; + }; + + size_t m_firstSize, m_blockSize, m_lastSize; + bool m_firstInputDone; + BlockQueue m_queue; +}; + +//! _ +class CRYPTOPP_DLL FilterWithInputQueue : public Filter +{ +public: + FilterWithInputQueue(BufferedTransformation *attachment=NULL) : Filter(attachment) {} + + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) + { + if (!blocking) + throw BlockingInputOnly("FilterWithInputQueue"); + + m_inQueue.Put(inString, length); + if (messageEnd) + { + IsolatedMessageEnd(blocking); + Output(0, NULL, 0, messageEnd, blocking); + } + return 0; + } + +protected: + virtual bool IsolatedMessageEnd(bool blocking) =0; + void IsolatedInitialize(const NameValuePairs ¶meters) {m_inQueue.Clear();} + + ByteQueue m_inQueue; +}; + +struct BlockPaddingSchemeDef +{ + enum BlockPaddingScheme {NO_PADDING, ZEROS_PADDING, PKCS_PADDING, ONE_AND_ZEROS_PADDING, DEFAULT_PADDING}; +}; + +//! Filter Wrapper for StreamTransformation, optionally handling padding/unpadding when needed +class CRYPTOPP_DLL StreamTransformationFilter : public FilterWithBufferedInput, public BlockPaddingSchemeDef, private FilterPutSpaceHelper +{ +public: + /*! DEFAULT_PADDING means PKCS_PADDING if c.MandatoryBlockSize() > 1 && c.MinLastBlockSize() == 0 (e.g. ECB or CBC mode), + otherwise NO_PADDING (OFB, CFB, CTR, CBC-CTS modes). + See http://www.weidai.com/scan-mirror/csp.html for details of the padding schemes. */ + StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment = NULL, BlockPaddingScheme padding = DEFAULT_PADDING, bool allowAuthenticatedSymmetricCipher = false); + + std::string AlgorithmName() const {return m_cipher.AlgorithmName();} + +protected: + void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize); + void FirstPut(const byte *inString); + void NextPutMultiple(const byte *inString, size_t length); + void NextPutModifiable(byte *inString, size_t length); + void LastPut(const byte *inString, size_t length); + + static size_t LastBlockSize(StreamTransformation &c, BlockPaddingScheme padding); + + StreamTransformation &m_cipher; + BlockPaddingScheme m_padding; + unsigned int m_optimalBufferSize; +}; + +#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY +typedef StreamTransformationFilter StreamCipherFilter; +#endif + +//! Filter Wrapper for HashTransformation +class CRYPTOPP_DLL HashFilter : public Bufferless, private FilterPutSpaceHelper +{ +public: + HashFilter(HashTransformation &hm, BufferedTransformation *attachment = NULL, bool putMessage=false, int truncatedDigestSize=-1, const std::string &messagePutChannel=DEFAULT_CHANNEL, const std::string &hashPutChannel=DEFAULT_CHANNEL); + + std::string AlgorithmName() const {return m_hashModule.AlgorithmName();} + void IsolatedInitialize(const NameValuePairs ¶meters); + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); + byte * CreatePutSpace(size_t &size) {return m_hashModule.CreateUpdateSpace(size);} + +private: + HashTransformation &m_hashModule; + bool m_putMessage; + unsigned int m_digestSize; + byte *m_space; + std::string m_messagePutChannel, m_hashPutChannel; +}; + +//! Filter Wrapper for HashTransformation +class CRYPTOPP_DLL HashVerificationFilter : public FilterWithBufferedInput +{ +public: + class HashVerificationFailed : public Exception + { + public: + HashVerificationFailed() + : Exception(DATA_INTEGRITY_CHECK_FAILED, "HashVerificationFilter: message hash or MAC not valid") {} + }; + + enum Flags {HASH_AT_END=0, HASH_AT_BEGIN=1, PUT_MESSAGE=2, PUT_HASH=4, PUT_RESULT=8, THROW_EXCEPTION=16, DEFAULT_FLAGS = HASH_AT_BEGIN | PUT_RESULT}; + HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS, int truncatedDigestSize=-1); + + std::string AlgorithmName() const {return m_hashModule.AlgorithmName();} + bool GetLastResult() const {return m_verified;} + +protected: + void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize); + void FirstPut(const byte *inString); + void NextPutMultiple(const byte *inString, size_t length); + void LastPut(const byte *inString, size_t length); + +private: + friend class AuthenticatedDecryptionFilter; + + HashTransformation &m_hashModule; + word32 m_flags; + unsigned int m_digestSize; + bool m_verified; + SecByteBlock m_expectedHash; +}; + +typedef HashVerificationFilter HashVerifier; // for backwards compatibility + +//! Filter wrapper for encrypting with AuthenticatedSymmetricCipher, optionally handling padding/unpadding when needed +/*! Additional authenticated data should be given in channel "AAD". If putAAD is true, AAD will be Put() to the attached BufferedTransformation in channel "AAD". */ +class CRYPTOPP_DLL AuthenticatedEncryptionFilter : public StreamTransformationFilter +{ +public: + /*! See StreamTransformationFilter for documentation on BlockPaddingScheme */ + AuthenticatedEncryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment = NULL, bool putAAD=false, int truncatedDigestSize=-1, const std::string &macChannel=DEFAULT_CHANNEL, BlockPaddingScheme padding = DEFAULT_PADDING); + + void IsolatedInitialize(const NameValuePairs ¶meters); + byte * ChannelCreatePutSpace(const std::string &channel, size_t &size); + size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking); + void LastPut(const byte *inString, size_t length); + +protected: + HashFilter m_hf; +}; + +//! Filter wrapper for decrypting with AuthenticatedSymmetricCipher, optionally handling padding/unpadding when needed +/*! Additional authenticated data should be given in channel "AAD". */ +class CRYPTOPP_DLL AuthenticatedDecryptionFilter : public FilterWithBufferedInput, public BlockPaddingSchemeDef +{ +public: + enum Flags {MAC_AT_END=0, MAC_AT_BEGIN=1, THROW_EXCEPTION=16, DEFAULT_FLAGS = THROW_EXCEPTION}; + + /*! See StreamTransformationFilter for documentation on BlockPaddingScheme */ + AuthenticatedDecryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS, int truncatedDigestSize=-1, BlockPaddingScheme padding = DEFAULT_PADDING); + + std::string AlgorithmName() const {return m_hashVerifier.AlgorithmName();} + byte * ChannelCreatePutSpace(const std::string &channel, size_t &size); + size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking); + bool GetLastResult() const {return m_hashVerifier.GetLastResult();} + +protected: + void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize); + void FirstPut(const byte *inString); + void NextPutMultiple(const byte *inString, size_t length); + void LastPut(const byte *inString, size_t length); + + HashVerificationFilter m_hashVerifier; + StreamTransformationFilter m_streamFilter; +}; + +//! Filter Wrapper for PK_Signer +class CRYPTOPP_DLL SignerFilter : public Unflushable +{ +public: + SignerFilter(RandomNumberGenerator &rng, const PK_Signer &signer, BufferedTransformation *attachment = NULL, bool putMessage=false) + : m_rng(rng), m_signer(signer), m_messageAccumulator(signer.NewSignatureAccumulator(rng)), m_putMessage(putMessage) {Detach(attachment);} + + std::string AlgorithmName() const {return m_signer.AlgorithmName();} + + void IsolatedInitialize(const NameValuePairs ¶meters); + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); + +private: + RandomNumberGenerator &m_rng; + const PK_Signer &m_signer; + member_ptr m_messageAccumulator; + bool m_putMessage; + SecByteBlock m_buf; +}; + +//! Filter Wrapper for PK_Verifier +class CRYPTOPP_DLL SignatureVerificationFilter : public FilterWithBufferedInput +{ +public: + class SignatureVerificationFailed : public Exception + { + public: + SignatureVerificationFailed() + : Exception(DATA_INTEGRITY_CHECK_FAILED, "VerifierFilter: digital signature not valid") {} + }; + + enum Flags {SIGNATURE_AT_END=0, SIGNATURE_AT_BEGIN=1, PUT_MESSAGE=2, PUT_SIGNATURE=4, PUT_RESULT=8, THROW_EXCEPTION=16, DEFAULT_FLAGS = SIGNATURE_AT_BEGIN | PUT_RESULT}; + SignatureVerificationFilter(const PK_Verifier &verifier, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS); + + std::string AlgorithmName() const {return m_verifier.AlgorithmName();} + + bool GetLastResult() const {return m_verified;} + +protected: + void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize); + void FirstPut(const byte *inString); + void NextPutMultiple(const byte *inString, size_t length); + void LastPut(const byte *inString, size_t length); + +private: + const PK_Verifier &m_verifier; + member_ptr m_messageAccumulator; + word32 m_flags; + SecByteBlock m_signature; + bool m_verified; +}; + +typedef SignatureVerificationFilter VerifierFilter; // for backwards compatibility + +//! Redirect input to another BufferedTransformation without owning it +class CRYPTOPP_DLL Redirector : public CustomSignalPropagation +{ +public: + enum Behavior + { + DATA_ONLY = 0x00, + PASS_SIGNALS = 0x01, + PASS_WAIT_OBJECTS = 0x02, + PASS_EVERYTHING = PASS_SIGNALS | PASS_WAIT_OBJECTS + }; + + Redirector() : m_target(NULL), m_behavior(PASS_EVERYTHING) {} + Redirector(BufferedTransformation &target, Behavior behavior=PASS_EVERYTHING) + : m_target(&target), m_behavior(behavior) {} + + void Redirect(BufferedTransformation &target) {m_target = ⌖} + void StopRedirection() {m_target = NULL;} + + Behavior GetBehavior() {return (Behavior) m_behavior;} + void SetBehavior(Behavior behavior) {m_behavior=behavior;} + bool GetPassSignals() const {return (m_behavior & PASS_SIGNALS) != 0;} + void SetPassSignals(bool pass) { if (pass) m_behavior |= PASS_SIGNALS; else m_behavior &= ~(word32) PASS_SIGNALS; } + bool GetPassWaitObjects() const {return (m_behavior & PASS_WAIT_OBJECTS) != 0;} + void SetPassWaitObjects(bool pass) { if (pass) m_behavior |= PASS_WAIT_OBJECTS; else m_behavior &= ~(word32) PASS_WAIT_OBJECTS; } + + bool CanModifyInput() const + {return m_target ? m_target->CanModifyInput() : false;} + + void Initialize(const NameValuePairs ¶meters, int propagation); + byte * CreatePutSpace(size_t &size) + {return m_target ? m_target->CreatePutSpace(size) : (byte *)(size=0, NULL);} + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking) + {return m_target ? m_target->Put2(begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;} + bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) + {return m_target && GetPassSignals() ? m_target->Flush(hardFlush, propagation, blocking) : false;} + bool MessageSeriesEnd(int propagation=-1, bool blocking=true) + {return m_target && GetPassSignals() ? m_target->MessageSeriesEnd(propagation, blocking) : false;} + + byte * ChannelCreatePutSpace(const std::string &channel, size_t &size) + {return m_target ? m_target->ChannelCreatePutSpace(channel, size) : (byte *)(size=0, NULL);} + size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) + {return m_target ? m_target->ChannelPut2(channel, begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;} + size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking) + {return m_target ? m_target->ChannelPutModifiable2(channel, begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;} + bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true) + {return m_target && GetPassSignals() ? m_target->ChannelFlush(channel, completeFlush, propagation, blocking) : false;} + bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true) + {return m_target && GetPassSignals() ? m_target->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;} + + unsigned int GetMaxWaitObjectCount() const + { return m_target && GetPassWaitObjects() ? m_target->GetMaxWaitObjectCount() : 0; } + void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack) + { if (m_target && GetPassWaitObjects()) m_target->GetWaitObjects(container, callStack); } + +private: + BufferedTransformation *m_target; + word32 m_behavior; +}; + +// Used By ProxyFilter +class CRYPTOPP_DLL OutputProxy : public CustomSignalPropagation +{ +public: + OutputProxy(BufferedTransformation &owner, bool passSignal) : m_owner(owner), m_passSignal(passSignal) {} + + bool GetPassSignal() const {return m_passSignal;} + void SetPassSignal(bool passSignal) {m_passSignal = passSignal;} + + byte * CreatePutSpace(size_t &size) + {return m_owner.AttachedTransformation()->CreatePutSpace(size);} + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking) + {return m_owner.AttachedTransformation()->Put2(begin, length, m_passSignal ? messageEnd : 0, blocking);} + size_t PutModifiable2(byte *begin, size_t length, int messageEnd, bool blocking) + {return m_owner.AttachedTransformation()->PutModifiable2(begin, length, m_passSignal ? messageEnd : 0, blocking);} + void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1) + {if (m_passSignal) m_owner.AttachedTransformation()->Initialize(parameters, propagation);} + bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) + {return m_passSignal ? m_owner.AttachedTransformation()->Flush(hardFlush, propagation, blocking) : false;} + bool MessageSeriesEnd(int propagation=-1, bool blocking=true) + {return m_passSignal ? m_owner.AttachedTransformation()->MessageSeriesEnd(propagation, blocking) : false;} + + byte * ChannelCreatePutSpace(const std::string &channel, size_t &size) + {return m_owner.AttachedTransformation()->ChannelCreatePutSpace(channel, size);} + size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) + {return m_owner.AttachedTransformation()->ChannelPut2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking);} + size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking) + {return m_owner.AttachedTransformation()->ChannelPutModifiable2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking);} + bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true) + {return m_passSignal ? m_owner.AttachedTransformation()->ChannelFlush(channel, completeFlush, propagation, blocking) : false;} + bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true) + {return m_passSignal ? m_owner.AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;} + +private: + BufferedTransformation &m_owner; + bool m_passSignal; +}; + +//! Base class for Filter classes that are proxies for a chain of other filters. +class CRYPTOPP_DLL ProxyFilter : public FilterWithBufferedInput +{ +public: + ProxyFilter(BufferedTransformation *filter, size_t firstSize, size_t lastSize, BufferedTransformation *attachment); + + bool IsolatedFlush(bool hardFlush, bool blocking); + + void SetFilter(Filter *filter); + void NextPutMultiple(const byte *s, size_t len); + void NextPutModifiable(byte *inString, size_t length); + +protected: + member_ptr m_filter; +}; + +//! simple proxy filter that doesn't modify the underlying filter's input or output +class CRYPTOPP_DLL SimpleProxyFilter : public ProxyFilter +{ +public: + SimpleProxyFilter(BufferedTransformation *filter, BufferedTransformation *attachment) + : ProxyFilter(filter, 0, 0, attachment) {} + + void FirstPut(const byte *) {} + void LastPut(const byte *, size_t) {m_filter->MessageEnd();} +}; + +//! proxy for the filter created by PK_Encryptor::CreateEncryptionFilter +/*! This class is here just to provide symmetry with VerifierFilter. */ +class CRYPTOPP_DLL PK_EncryptorFilter : public SimpleProxyFilter +{ +public: + PK_EncryptorFilter(RandomNumberGenerator &rng, const PK_Encryptor &encryptor, BufferedTransformation *attachment = NULL) + : SimpleProxyFilter(encryptor.CreateEncryptionFilter(rng), attachment) {} +}; + +//! proxy for the filter created by PK_Decryptor::CreateDecryptionFilter +/*! This class is here just to provide symmetry with SignerFilter. */ +class CRYPTOPP_DLL PK_DecryptorFilter : public SimpleProxyFilter +{ +public: + PK_DecryptorFilter(RandomNumberGenerator &rng, const PK_Decryptor &decryptor, BufferedTransformation *attachment = NULL) + : SimpleProxyFilter(decryptor.CreateDecryptionFilter(rng), attachment) {} +}; + +//! Append input to a string object +template +class StringSinkTemplate : public Bufferless +{ +public: + // VC60 workaround: no T::char_type + typedef typename T::traits_type::char_type char_type; + + StringSinkTemplate(T &output) + : m_output(&output) {assert(sizeof(output[0])==1);} + + void IsolatedInitialize(const NameValuePairs ¶meters) + {if (!parameters.GetValue("OutputStringPointer", m_output)) throw InvalidArgument("StringSink: OutputStringPointer not specified");} + + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking) + { + if (length > 0) + { + typename T::size_type size = m_output->size(); + if (length < size && size + length > m_output->capacity()) + m_output->reserve(2*size); + m_output->append((const char_type *)begin, (const char_type *)begin+length); + } + return 0; + } + +private: + T *m_output; +}; + +//! Append input to an std::string +CRYPTOPP_DLL_TEMPLATE_CLASS StringSinkTemplate; +typedef StringSinkTemplate StringSink; + +//! incorporates input into RNG as additional entropy +class RandomNumberSink : public Bufferless +{ +public: + RandomNumberSink() + : m_rng(NULL) {} + + RandomNumberSink(RandomNumberGenerator &rng) + : m_rng(&rng) {} + + void IsolatedInitialize(const NameValuePairs ¶meters); + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); + +private: + RandomNumberGenerator *m_rng; +}; + +//! Copy input to a memory buffer +class CRYPTOPP_DLL ArraySink : public Bufferless +{ +public: + ArraySink(const NameValuePairs ¶meters = g_nullNameValuePairs) {IsolatedInitialize(parameters);} + ArraySink(byte *buf, size_t size) : m_buf(buf), m_size(size), m_total(0) {} + + size_t AvailableSize() {return SaturatingSubtract(m_size, m_total);} + lword TotalPutLength() {return m_total;} + + void IsolatedInitialize(const NameValuePairs ¶meters); + byte * CreatePutSpace(size_t &size); + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); + +protected: + byte *m_buf; + size_t m_size; + lword m_total; +}; + +//! Xor input to a memory buffer +class CRYPTOPP_DLL ArrayXorSink : public ArraySink +{ +public: + ArrayXorSink(byte *buf, size_t size) + : ArraySink(buf, size) {} + + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking); + byte * CreatePutSpace(size_t &size) {return BufferedTransformation::CreatePutSpace(size);} +}; + +//! string-based implementation of Store interface +class StringStore : public Store +{ +public: + StringStore(const char *string = NULL) + {StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string)));} + StringStore(const byte *string, size_t length) + {StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));} + template StringStore(const T &string) + {StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string)));} + + CRYPTOPP_DLL size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); + CRYPTOPP_DLL size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const; + +private: + CRYPTOPP_DLL void StoreInitialize(const NameValuePairs ¶meters); + + const byte *m_store; + size_t m_length, m_count; +}; + +//! RNG-based implementation of Source interface +class CRYPTOPP_DLL RandomNumberStore : public Store +{ +public: + RandomNumberStore() + : m_rng(NULL), m_length(0), m_count(0) {} + + RandomNumberStore(RandomNumberGenerator &rng, lword length) + : m_rng(&rng), m_length(length), m_count(0) {} + + bool AnyRetrievable() const {return MaxRetrievable() != 0;} + lword MaxRetrievable() const {return m_length-m_count;} + + size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); + size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const + { + throw NotImplemented("RandomNumberStore: CopyRangeTo2() is not supported by this store"); + } + +private: + void StoreInitialize(const NameValuePairs ¶meters); + + RandomNumberGenerator *m_rng; + lword m_length, m_count; +}; + +//! empty store +class CRYPTOPP_DLL NullStore : public Store +{ +public: + NullStore(lword size = ULONG_MAX) : m_size(size) {} + void StoreInitialize(const NameValuePairs ¶meters) {} + lword MaxRetrievable() const {return m_size;} + size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); + size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const; + +private: + lword m_size; +}; + +//! A Filter that pumps data into its attachment as input +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Source : public InputRejecting +{ +public: + Source(BufferedTransformation *attachment = NULL) + {Source::Detach(attachment);} + + lword Pump(lword pumpMax=size_t(0)-1) + {Pump2(pumpMax); return pumpMax;} + unsigned int PumpMessages(unsigned int count=UINT_MAX) + {PumpMessages2(count); return count;} + void PumpAll() + {PumpAll2();} + virtual size_t Pump2(lword &byteCount, bool blocking=true) =0; + virtual size_t PumpMessages2(unsigned int &messageCount, bool blocking=true) =0; + virtual size_t PumpAll2(bool blocking=true); + virtual bool SourceExhausted() const =0; + +protected: + void SourceInitialize(bool pumpAll, const NameValuePairs ¶meters) + { + IsolatedInitialize(parameters); + if (pumpAll) + PumpAll(); + } +}; + +//! Turn a Store into a Source +template +class SourceTemplate : public Source +{ +public: + SourceTemplate(BufferedTransformation *attachment) + : Source(attachment) {} + void IsolatedInitialize(const NameValuePairs ¶meters) + {m_store.IsolatedInitialize(parameters);} + size_t Pump2(lword &byteCount, bool blocking=true) + {return m_store.TransferTo2(*AttachedTransformation(), byteCount, DEFAULT_CHANNEL, blocking);} + size_t PumpMessages2(unsigned int &messageCount, bool blocking=true) + {return m_store.TransferMessagesTo2(*AttachedTransformation(), messageCount, DEFAULT_CHANNEL, blocking);} + size_t PumpAll2(bool blocking=true) + {return m_store.TransferAllTo2(*AttachedTransformation(), DEFAULT_CHANNEL, blocking);} + bool SourceExhausted() const + {return !m_store.AnyRetrievable() && !m_store.AnyMessages();} + void SetAutoSignalPropagation(int propagation) + {m_store.SetAutoSignalPropagation(propagation);} + int GetAutoSignalPropagation() const + {return m_store.GetAutoSignalPropagation();} + +protected: + T m_store; +}; + +//! string-based implementation of Source interface +class CRYPTOPP_DLL StringSource : public SourceTemplate +{ +public: + StringSource(BufferedTransformation *attachment = NULL) + : SourceTemplate(attachment) {} + //! zero terminated string as source + StringSource(const char *string, bool pumpAll, BufferedTransformation *attachment = NULL) + : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));} + //! binary byte array as source + StringSource(const byte *string, size_t length, bool pumpAll, BufferedTransformation *attachment = NULL) + : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));} + //! std::string as source + StringSource(const std::string &string, bool pumpAll, BufferedTransformation *attachment = NULL) + : SourceTemplate(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));} +}; + +//! use the third constructor for an array source +typedef StringSource ArraySource; + +//! RNG-based implementation of Source interface +class CRYPTOPP_DLL RandomNumberSource : public SourceTemplate +{ +public: + RandomNumberSource(RandomNumberGenerator &rng, int length, bool pumpAll, BufferedTransformation *attachment = NULL) + : SourceTemplate(attachment) + {SourceInitialize(pumpAll, MakeParameters("RandomNumberGeneratorPointer", &rng)("RandomNumberStoreSize", length));} +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/fips140.cpp b/src-cryptopp/fips140.cpp new file mode 100644 index 0000000..1fcf590 --- /dev/null +++ b/src-cryptopp/fips140.cpp @@ -0,0 +1,84 @@ +// fips140.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "fips140.h" +#include "trdlocal.h" // needs to be included last for cygwin + +NAMESPACE_BEGIN(CryptoPP) + +// Define this to 1 to turn on FIPS 140-2 compliance features, including additional tests during +// startup, random number generation, and key generation. These tests may affect performance. +#ifndef CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 +#define CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 0 +#endif + +#if (CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 && !defined(THREADS_AVAILABLE)) +#error FIPS 140-2 compliance requires the availability of thread local storage. +#endif + +#if (CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 && !defined(OS_RNG_AVAILABLE)) +#error FIPS 140-2 compliance requires the availability of OS provided RNG. +#endif + +PowerUpSelfTestStatus g_powerUpSelfTestStatus = POWER_UP_SELF_TEST_NOT_DONE; + +bool FIPS_140_2_ComplianceEnabled() +{ + return CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2; +} + +void SimulatePowerUpSelfTestFailure() +{ + g_powerUpSelfTestStatus = POWER_UP_SELF_TEST_FAILED; +} + +PowerUpSelfTestStatus CRYPTOPP_API GetPowerUpSelfTestStatus() +{ + return g_powerUpSelfTestStatus; +} + +#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 +ThreadLocalStorage & AccessPowerUpSelfTestInProgress() +{ + static ThreadLocalStorage selfTestInProgress; + return selfTestInProgress; +} +#endif + +bool PowerUpSelfTestInProgressOnThisThread() +{ +#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 + return AccessPowerUpSelfTestInProgress().GetValue() != NULL; +#else + assert(false); // should not be called + return false; +#endif +} + +void SetPowerUpSelfTestInProgressOnThisThread(bool inProgress) +{ +#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 + AccessPowerUpSelfTestInProgress().SetValue((void *)inProgress); +#endif +} + +void EncryptionPairwiseConsistencyTest_FIPS_140_Only(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor) +{ +#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 + EncryptionPairwiseConsistencyTest(encryptor, decryptor); +#endif +} + +void SignaturePairwiseConsistencyTest_FIPS_140_Only(const PK_Signer &signer, const PK_Verifier &verifier) +{ +#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 + SignaturePairwiseConsistencyTest(signer, verifier); +#endif +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/fips140.h b/src-cryptopp/fips140.h new file mode 100644 index 0000000..a3e5386 --- /dev/null +++ b/src-cryptopp/fips140.h @@ -0,0 +1,59 @@ +#ifndef CRYPTOPP_FIPS140_H +#define CRYPTOPP_FIPS140_H + +/*! \file + FIPS 140 related functions and classes. +*/ + +#include "cryptlib.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! exception thrown when a crypto algorithm is used after a self test fails +class CRYPTOPP_DLL SelfTestFailure : public Exception +{ +public: + explicit SelfTestFailure(const std::string &s) : Exception(OTHER_ERROR, s) {} +}; + +//! returns whether FIPS 140-2 compliance features were enabled at compile time +CRYPTOPP_DLL bool CRYPTOPP_API FIPS_140_2_ComplianceEnabled(); + +//! enum values representing status of the power-up self test +enum PowerUpSelfTestStatus {POWER_UP_SELF_TEST_NOT_DONE, POWER_UP_SELF_TEST_FAILED, POWER_UP_SELF_TEST_PASSED}; + +//! perform the power-up self test, and set the self test status +CRYPTOPP_DLL void CRYPTOPP_API DoPowerUpSelfTest(const char *moduleFilename, const byte *expectedModuleMac); + +//! perform the power-up self test using the filename of this DLL and the embedded module MAC +CRYPTOPP_DLL void CRYPTOPP_API DoDllPowerUpSelfTest(); + +//! set the power-up self test status to POWER_UP_SELF_TEST_FAILED +CRYPTOPP_DLL void CRYPTOPP_API SimulatePowerUpSelfTestFailure(); + +//! return the current power-up self test status +CRYPTOPP_DLL PowerUpSelfTestStatus CRYPTOPP_API GetPowerUpSelfTestStatus(); + +typedef PowerUpSelfTestStatus (CRYPTOPP_API * PGetPowerUpSelfTestStatus)(); + +CRYPTOPP_DLL MessageAuthenticationCode * CRYPTOPP_API NewIntegrityCheckingMAC(); + +CRYPTOPP_DLL bool CRYPTOPP_API IntegrityCheckModule(const char *moduleFilename, const byte *expectedModuleMac, SecByteBlock *pActualMac = NULL, unsigned long *pMacFileLocation = NULL); + +// this is used by Algorithm constructor to allow Algorithm objects to be constructed for the self test +bool PowerUpSelfTestInProgressOnThisThread(); + +void SetPowerUpSelfTestInProgressOnThisThread(bool inProgress); + +void SignaturePairwiseConsistencyTest(const PK_Signer &signer, const PK_Verifier &verifier); +void EncryptionPairwiseConsistencyTest(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor); + +void SignaturePairwiseConsistencyTest_FIPS_140_Only(const PK_Signer &signer, const PK_Verifier &verifier); +void EncryptionPairwiseConsistencyTest_FIPS_140_Only(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor); + +#define CRYPTOPP_DUMMY_DLL_MAC "MAC_51f34b8db820ae8" + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/fltrimpl.h b/src-cryptopp/fltrimpl.h new file mode 100644 index 0000000..4087d7d --- /dev/null +++ b/src-cryptopp/fltrimpl.h @@ -0,0 +1,67 @@ +#ifndef CRYPTOPP_FLTRIMPL_H +#define CRYPTOPP_FLTRIMPL_H + +#define FILTER_BEGIN \ + switch (m_continueAt) \ + { \ + case 0: \ + m_inputPosition = 0; + +#define FILTER_END_NO_MESSAGE_END_NO_RETURN \ + break; \ + default: \ + assert(false); \ + } + +#define FILTER_END_NO_MESSAGE_END \ + FILTER_END_NO_MESSAGE_END_NO_RETURN \ + return 0; + +/* +#define FILTER_END \ + case -1: \ + if (messageEnd && Output(-1, NULL, 0, messageEnd, blocking)) \ + return 1; \ + FILTER_END_NO_MESSAGE_END +*/ + +#define FILTER_OUTPUT3(site, statement, output, length, messageEnd, channel) \ + {\ + case site: \ + statement; \ + if (Output(site, output, length, messageEnd, blocking, channel)) \ + return STDMAX(size_t(1), length-m_inputPosition);\ + } + +#define FILTER_OUTPUT2(site, statement, output, length, messageEnd) \ + FILTER_OUTPUT3(site, statement, output, length, messageEnd, DEFAULT_CHANNEL) + +#define FILTER_OUTPUT(site, output, length, messageEnd) \ + FILTER_OUTPUT2(site, 0, output, length, messageEnd) + +#define FILTER_OUTPUT_BYTE(site, output) \ + FILTER_OUTPUT(site, &(const byte &)(byte)output, 1, 0) + +#define FILTER_OUTPUT2_MODIFIABLE(site, statement, output, length, messageEnd) \ + {\ + case site: \ + statement; \ + if (OutputModifiable(site, output, length, messageEnd, blocking)) \ + return STDMAX(size_t(1), length-m_inputPosition);\ + } + +#define FILTER_OUTPUT_MODIFIABLE(site, output, length, messageEnd) \ + FILTER_OUTPUT2_MODIFIABLE(site, 0, output, length, messageEnd) + +#define FILTER_OUTPUT2_MAYBE_MODIFIABLE(site, statement, output, length, messageEnd, modifiable) \ + {\ + case site: \ + statement; \ + if (modifiable ? OutputModifiable(site, output, length, messageEnd, blocking) : Output(site, output, length, messageEnd, blocking)) \ + return STDMAX(size_t(1), length-m_inputPosition);\ + } + +#define FILTER_OUTPUT_MAYBE_MODIFIABLE(site, output, length, messageEnd, modifiable) \ + FILTER_OUTPUT2_MAYBE_MODIFIABLE(site, 0, output, length, messageEnd, modifiable) + +#endif diff --git a/src-cryptopp/gcm.h b/src-cryptopp/gcm.h new file mode 100644 index 0000000..851ae80 --- /dev/null +++ b/src-cryptopp/gcm.h @@ -0,0 +1,105 @@ +#ifndef CRYPTOPP_GCM_H +#define CRYPTOPP_GCM_H + +#include "authenc.h" +#include "modes.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! . +enum GCM_TablesOption {GCM_2K_Tables, GCM_64K_Tables}; + +//! . +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE GCM_Base : public AuthenticatedSymmetricCipherBase +{ +public: + // AuthenticatedSymmetricCipher + std::string AlgorithmName() const + {return GetBlockCipher().AlgorithmName() + std::string("/GCM");} + size_t MinKeyLength() const + {return GetBlockCipher().MinKeyLength();} + size_t MaxKeyLength() const + {return GetBlockCipher().MaxKeyLength();} + size_t DefaultKeyLength() const + {return GetBlockCipher().DefaultKeyLength();} + size_t GetValidKeyLength(size_t n) const + {return GetBlockCipher().GetValidKeyLength(n);} + bool IsValidKeyLength(size_t n) const + {return GetBlockCipher().IsValidKeyLength(n);} + unsigned int OptimalDataAlignment() const; + IV_Requirement IVRequirement() const + {return UNIQUE_IV;} + unsigned int IVSize() const + {return 12;} + unsigned int MinIVLength() const + {return 1;} + unsigned int MaxIVLength() const + {return UINT_MAX;} // (W64LIT(1)<<61)-1 in the standard + unsigned int DigestSize() const + {return 16;} + lword MaxHeaderLength() const + {return (W64LIT(1)<<61)-1;} + lword MaxMessageLength() const + {return ((W64LIT(1)<<39)-256)/8;} + +protected: + // AuthenticatedSymmetricCipherBase + bool AuthenticationIsOnPlaintext() const + {return false;} + unsigned int AuthenticationBlockSize() const + {return HASH_BLOCKSIZE;} + void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs ¶ms); + void Resync(const byte *iv, size_t len); + size_t AuthenticateBlocks(const byte *data, size_t len); + void AuthenticateLastHeaderBlock(); + void AuthenticateLastConfidentialBlock(); + void AuthenticateLastFooterBlock(byte *mac, size_t macSize); + SymmetricCipher & AccessSymmetricCipher() {return m_ctr;} + + virtual BlockCipher & AccessBlockCipher() =0; + virtual GCM_TablesOption GetTablesOption() const =0; + + const BlockCipher & GetBlockCipher() const {return const_cast(this)->AccessBlockCipher();}; + byte *HashBuffer() {return m_buffer+REQUIRED_BLOCKSIZE;} + byte *HashKey() {return m_buffer+2*REQUIRED_BLOCKSIZE;} + byte *MulTable() {return m_buffer+3*REQUIRED_BLOCKSIZE;} + + class GCTR : public CTR_Mode_ExternalCipher::Encryption + { + protected: + void IncrementCounterBy256(); + }; + + GCTR m_ctr; + static word16 s_reductionTable[256]; + static bool s_reductionTableInitialized; + enum {REQUIRED_BLOCKSIZE = 16, HASH_BLOCKSIZE = 16}; +}; + +//! . +template +class GCM_Final : public GCM_Base +{ +public: + static std::string StaticAlgorithmName() + {return T_BlockCipher::StaticAlgorithmName() + std::string("/GCM");} + bool IsForwardTransformation() const + {return T_IsEncryption;} + +private: + GCM_TablesOption GetTablesOption() const {return T_TablesOption;} + BlockCipher & AccessBlockCipher() {return m_cipher;} + typename T_BlockCipher::Encryption m_cipher; +}; + +//! GCM +template +struct GCM : public AuthenticatedSymmetricCipherDocumentation +{ + typedef GCM_Final Encryption; + typedef GCM_Final Decryption; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/gf2n.cpp b/src-cryptopp/gf2n.cpp new file mode 100644 index 0000000..0fac46a --- /dev/null +++ b/src-cryptopp/gf2n.cpp @@ -0,0 +1,879 @@ +// gf2n.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "gf2n.h" +#include "algebra.h" +#include "words.h" +#include "randpool.h" +#include "asn.h" +#include "oids.h" + +#include + +NAMESPACE_BEGIN(CryptoPP) + +PolynomialMod2::PolynomialMod2() +{ +} + +PolynomialMod2::PolynomialMod2(word value, size_t bitLength) + : reg(BitsToWords(bitLength)) +{ + assert(value==0 || reg.size()>0); + + if (reg.size() > 0) + { + reg[0] = value; + SetWords(reg+1, 0, reg.size()-1); + } +} + +PolynomialMod2::PolynomialMod2(const PolynomialMod2& t) + : reg(t.reg.size()) +{ + CopyWords(reg, t.reg, reg.size()); +} + +void PolynomialMod2::Randomize(RandomNumberGenerator &rng, size_t nbits) +{ + const size_t nbytes = nbits/8 + 1; + SecByteBlock buf(nbytes); + rng.GenerateBlock(buf, nbytes); + buf[0] = (byte)Crop(buf[0], nbits % 8); + Decode(buf, nbytes); +} + +PolynomialMod2 PolynomialMod2::AllOnes(size_t bitLength) +{ + PolynomialMod2 result((word)0, bitLength); + SetWords(result.reg, ~(word)0, result.reg.size()); + if (bitLength%WORD_BITS) + result.reg[result.reg.size()-1] = (word)Crop(result.reg[result.reg.size()-1], bitLength%WORD_BITS); + return result; +} + +void PolynomialMod2::SetBit(size_t n, int value) +{ + if (value) + { + reg.CleanGrow(n/WORD_BITS + 1); + reg[n/WORD_BITS] |= (word(1) << (n%WORD_BITS)); + } + else + { + if (n/WORD_BITS < reg.size()) + reg[n/WORD_BITS] &= ~(word(1) << (n%WORD_BITS)); + } +} + +byte PolynomialMod2::GetByte(size_t n) const +{ + if (n/WORD_SIZE >= reg.size()) + return 0; + else + return byte(reg[n/WORD_SIZE] >> ((n%WORD_SIZE)*8)); +} + +void PolynomialMod2::SetByte(size_t n, byte value) +{ + reg.CleanGrow(BytesToWords(n+1)); + reg[n/WORD_SIZE] &= ~(word(0xff) << 8*(n%WORD_SIZE)); + reg[n/WORD_SIZE] |= (word(value) << 8*(n%WORD_SIZE)); +} + +PolynomialMod2 PolynomialMod2::Monomial(size_t i) +{ + PolynomialMod2 r((word)0, i+1); + r.SetBit(i); + return r; +} + +PolynomialMod2 PolynomialMod2::Trinomial(size_t t0, size_t t1, size_t t2) +{ + PolynomialMod2 r((word)0, t0+1); + r.SetBit(t0); + r.SetBit(t1); + r.SetBit(t2); + return r; +} + +PolynomialMod2 PolynomialMod2::Pentanomial(size_t t0, size_t t1, size_t t2, size_t t3, size_t t4) +{ + PolynomialMod2 r((word)0, t0+1); + r.SetBit(t0); + r.SetBit(t1); + r.SetBit(t2); + r.SetBit(t3); + r.SetBit(t4); + return r; +} + +template +struct NewPolynomialMod2 +{ + PolynomialMod2 * operator()() const + { + return new PolynomialMod2(i); + } +}; + +const PolynomialMod2 &PolynomialMod2::Zero() +{ + return Singleton().Ref(); +} + +const PolynomialMod2 &PolynomialMod2::One() +{ + return Singleton >().Ref(); +} + +void PolynomialMod2::Decode(const byte *input, size_t inputLen) +{ + StringStore store(input, inputLen); + Decode(store, inputLen); +} + +void PolynomialMod2::Encode(byte *output, size_t outputLen) const +{ + ArraySink sink(output, outputLen); + Encode(sink, outputLen); +} + +void PolynomialMod2::Decode(BufferedTransformation &bt, size_t inputLen) +{ + reg.CleanNew(BytesToWords(inputLen)); + + for (size_t i=inputLen; i > 0; i--) + { + byte b; + bt.Get(b); + reg[(i-1)/WORD_SIZE] |= word(b) << ((i-1)%WORD_SIZE)*8; + } +} + +void PolynomialMod2::Encode(BufferedTransformation &bt, size_t outputLen) const +{ + for (size_t i=outputLen; i > 0; i--) + bt.Put(GetByte(i-1)); +} + +void PolynomialMod2::DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const +{ + DERGeneralEncoder enc(bt, OCTET_STRING); + Encode(enc, length); + enc.MessageEnd(); +} + +void PolynomialMod2::BERDecodeAsOctetString(BufferedTransformation &bt, size_t length) +{ + BERGeneralDecoder dec(bt, OCTET_STRING); + if (!dec.IsDefiniteLength() || dec.RemainingLength() != length) + BERDecodeError(); + Decode(dec, length); + dec.MessageEnd(); +} + +unsigned int PolynomialMod2::WordCount() const +{ + return (unsigned int)CountWords(reg, reg.size()); +} + +unsigned int PolynomialMod2::ByteCount() const +{ + unsigned wordCount = WordCount(); + if (wordCount) + return (wordCount-1)*WORD_SIZE + BytePrecision(reg[wordCount-1]); + else + return 0; +} + +unsigned int PolynomialMod2::BitCount() const +{ + unsigned wordCount = WordCount(); + if (wordCount) + return (wordCount-1)*WORD_BITS + BitPrecision(reg[wordCount-1]); + else + return 0; +} + +unsigned int PolynomialMod2::Parity() const +{ + unsigned i; + word temp=0; + for (i=0; i= reg.size()) + { + PolynomialMod2 result((word)0, b.reg.size()*WORD_BITS); + XorWords(result.reg, reg, b.reg, reg.size()); + CopyWords(result.reg+reg.size(), b.reg+reg.size(), b.reg.size()-reg.size()); + return result; + } + else + { + PolynomialMod2 result((word)0, reg.size()*WORD_BITS); + XorWords(result.reg, reg, b.reg, b.reg.size()); + CopyWords(result.reg+b.reg.size(), reg+b.reg.size(), reg.size()-b.reg.size()); + return result; + } +} + +PolynomialMod2 PolynomialMod2::And(const PolynomialMod2 &b) const +{ + PolynomialMod2 result((word)0, WORD_BITS*STDMIN(reg.size(), b.reg.size())); + AndWords(result.reg, reg, b.reg, result.reg.size()); + return result; +} + +PolynomialMod2 PolynomialMod2::Times(const PolynomialMod2 &b) const +{ + PolynomialMod2 result((word)0, BitCount() + b.BitCount()); + + for (int i=b.Degree(); i>=0; i--) + { + result <<= 1; + if (b[i]) + XorWords(result.reg, reg, reg.size()); + } + return result; +} + +PolynomialMod2 PolynomialMod2::Squared() const +{ + static const word map[16] = {0, 1, 4, 5, 16, 17, 20, 21, 64, 65, 68, 69, 80, 81, 84, 85}; + + PolynomialMod2 result((word)0, 2*reg.size()*WORD_BITS); + + for (unsigned i=0; i> (j/2)) % 16] << j; + + for (j=0; j> (j/2 + WORD_BITS/2)) % 16] << j; + } + + return result; +} + +void PolynomialMod2::Divide(PolynomialMod2 &remainder, PolynomialMod2 "ient, + const PolynomialMod2 ÷nd, const PolynomialMod2 &divisor) +{ + if (!divisor) + throw PolynomialMod2::DivideByZero(); + + int degree = divisor.Degree(); + remainder.reg.CleanNew(BitsToWords(degree+1)); + if (dividend.BitCount() >= divisor.BitCount()) + quotient.reg.CleanNew(BitsToWords(dividend.BitCount() - divisor.BitCount() + 1)); + else + quotient.reg.CleanNew(0); + + for (int i=dividend.Degree(); i>=0; i--) + { + remainder <<= 1; + remainder.reg[0] |= dividend[i]; + if (remainder[degree]) + { + remainder -= divisor; + quotient.SetBit(i); + } + } +} + +PolynomialMod2 PolynomialMod2::DividedBy(const PolynomialMod2 &b) const +{ + PolynomialMod2 remainder, quotient; + PolynomialMod2::Divide(remainder, quotient, *this, b); + return quotient; +} + +PolynomialMod2 PolynomialMod2::Modulo(const PolynomialMod2 &b) const +{ + PolynomialMod2 remainder, quotient; + PolynomialMod2::Divide(remainder, quotient, *this, b); + return remainder; +} + +PolynomialMod2& PolynomialMod2::operator<<=(unsigned int n) +{ + if (!reg.size()) + return *this; + + int i; + word u; + word carry=0; + word *r=reg; + + if (n==1) // special case code for most frequent case + { + i = (int)reg.size(); + while (i--) + { + u = *r; + *r = (u << 1) | carry; + carry = u >> (WORD_BITS-1); + r++; + } + + if (carry) + { + reg.Grow(reg.size()+1); + reg[reg.size()-1] = carry; + } + + return *this; + } + + int shiftWords = n / WORD_BITS; + int shiftBits = n % WORD_BITS; + + if (shiftBits) + { + i = (int)reg.size(); + while (i--) + { + u = *r; + *r = (u << shiftBits) | carry; + carry = u >> (WORD_BITS-shiftBits); + r++; + } + } + + if (carry) + { + reg.Grow(reg.size()+shiftWords+1); + reg[reg.size()-1] = carry; + } + else + reg.Grow(reg.size()+shiftWords); + + if (shiftWords) + { + for (i = (int)reg.size()-1; i>=shiftWords; i--) + reg[i] = reg[i-shiftWords]; + for (; i>=0; i--) + reg[i] = 0; + } + + return *this; +} + +PolynomialMod2& PolynomialMod2::operator>>=(unsigned int n) +{ + if (!reg.size()) + return *this; + + int shiftWords = n / WORD_BITS; + int shiftBits = n % WORD_BITS; + + size_t i; + word u; + word carry=0; + word *r=reg+reg.size()-1; + + if (shiftBits) + { + i = reg.size(); + while (i--) + { + u = *r; + *r = (u >> shiftBits) | carry; + carry = u << (WORD_BITS-shiftBits); + r--; + } + } + + if (shiftWords) + { + for (i=0; i>(unsigned int n) const +{ + PolynomialMod2 result(*this); + return result>>=n; +} + +bool PolynomialMod2::operator!() const +{ + for (unsigned i=0; i s(a.BitCount()/bits+1); + unsigned i; + const char vec[]="0123456789ABCDEF"; + + for (i=0; i*bits < a.BitCount(); i++) + { + int digit=0; + for (int j=0; j().Gcd(a, b); +} + +PolynomialMod2 PolynomialMod2::InverseMod(const PolynomialMod2 &modulus) const +{ + typedef EuclideanDomainOf Domain; + return QuotientRing(Domain(), modulus).MultiplicativeInverse(*this); +} + +bool PolynomialMod2::IsIrreducible() const +{ + signed int d = Degree(); + if (d <= 0) + return false; + + PolynomialMod2 t(2), u(t); + for (int i=1; i<=d/2; i++) + { + u = u.Squared()%(*this); + if (!Gcd(u+t, *this).IsUnit()) + return false; + } + return true; +} + +// ******************************************************** + +GF2NP::GF2NP(const PolynomialMod2 &modulus) + : QuotientRing >(EuclideanDomainOf(), modulus), m(modulus.Degree()) +{ +} + +GF2NP::Element GF2NP::SquareRoot(const Element &a) const +{ + Element r = a; + for (unsigned int i=1; i t1 && t1 > t2 && t2==0); +} + +const GF2NT::Element& GF2NT::MultiplicativeInverse(const Element &a) const +{ + if (t0-t1 < WORD_BITS) + return GF2NP::MultiplicativeInverse(a); + + SecWordBlock T(m_modulus.reg.size() * 4); + word *b = T; + word *c = T+m_modulus.reg.size(); + word *f = T+2*m_modulus.reg.size(); + word *g = T+3*m_modulus.reg.size(); + size_t bcLen=1, fgLen=m_modulus.reg.size(); + unsigned int k=0; + + SetWords(T, 0, 3*m_modulus.reg.size()); + b[0]=1; + assert(a.reg.size() <= m_modulus.reg.size()); + CopyWords(f, a.reg, a.reg.size()); + CopyWords(g, m_modulus.reg, m_modulus.reg.size()); + + while (1) + { + word t=f[0]; + while (!t) + { + ShiftWordsRightByWords(f, fgLen, 1); + if (c[bcLen-1]) + bcLen++; + assert(bcLen <= m_modulus.reg.size()); + ShiftWordsLeftByWords(c, bcLen, 1); + k+=WORD_BITS; + t=f[0]; + } + + unsigned int i=0; + while (t%2 == 0) + { + t>>=1; + i++; + } + k+=i; + + if (t==1 && CountWords(f, fgLen)==1) + break; + + if (i==1) + { + ShiftWordsRightByBits(f, fgLen, 1); + t=ShiftWordsLeftByBits(c, bcLen, 1); + } + else + { + ShiftWordsRightByBits(f, fgLen, i); + t=ShiftWordsLeftByBits(c, bcLen, i); + } + if (t) + { + c[bcLen] = t; + bcLen++; + assert(bcLen <= m_modulus.reg.size()); + } + + if (f[fgLen-1]==0 && g[fgLen-1]==0) + fgLen--; + + if (f[fgLen-1] < g[fgLen-1]) + { + std::swap(f, g); + std::swap(b, c); + } + + XorWords(f, g, fgLen); + XorWords(b, c, bcLen); + } + + while (k >= WORD_BITS) + { + word temp = b[0]; + // right shift b + for (unsigned i=0; i+1> j) & 1) << (t1 + j); + else + b[t1/WORD_BITS-1] ^= temp << t1%WORD_BITS; + + if (t1 % WORD_BITS) + b[t1/WORD_BITS] ^= temp >> (WORD_BITS - t1%WORD_BITS); + + if (t0%WORD_BITS) + { + b[t0/WORD_BITS-1] ^= temp << t0%WORD_BITS; + b[t0/WORD_BITS] ^= temp >> (WORD_BITS - t0%WORD_BITS); + } + else + b[t0/WORD_BITS-1] ^= temp; + + k -= WORD_BITS; + } + + if (k) + { + word temp = b[0] << (WORD_BITS - k); + ShiftWordsRightByBits(b, BitsToWords(m), k); + + if (t1 < WORD_BITS) + for (unsigned int j=0; j> j) & 1) << (t1 + j); + else + b[t1/WORD_BITS-1] ^= temp << t1%WORD_BITS; + + if (t1 % WORD_BITS) + b[t1/WORD_BITS] ^= temp >> (WORD_BITS - t1%WORD_BITS); + + if (t0%WORD_BITS) + { + b[t0/WORD_BITS-1] ^= temp << t0%WORD_BITS; + b[t0/WORD_BITS] ^= temp >> (WORD_BITS - t0%WORD_BITS); + } + else + b[t0/WORD_BITS-1] ^= temp; + } + + CopyWords(result.reg.begin(), b, result.reg.size()); + return result; +} + +const GF2NT::Element& GF2NT::Multiply(const Element &a, const Element &b) const +{ + size_t aSize = STDMIN(a.reg.size(), result.reg.size()); + Element r((word)0, m); + + for (int i=m-1; i>=0; i--) + { + if (r[m-1]) + { + ShiftWordsLeftByBits(r.reg.begin(), r.reg.size(), 1); + XorWords(r.reg.begin(), m_modulus.reg, r.reg.size()); + } + else + ShiftWordsLeftByBits(r.reg.begin(), r.reg.size(), 1); + + if (b[i]) + XorWords(r.reg.begin(), a.reg, aSize); + } + + if (m%WORD_BITS) + r.reg.begin()[r.reg.size()-1] = (word)Crop(r.reg[r.reg.size()-1], m%WORD_BITS); + + CopyWords(result.reg.begin(), r.reg.begin(), result.reg.size()); + return result; +} + +const GF2NT::Element& GF2NT::Reduced(const Element &a) const +{ + if (t0-t1 < WORD_BITS) + return m_domain.Mod(a, m_modulus); + + SecWordBlock b(a.reg); + + size_t i; + for (i=b.size()-1; i>=BitsToWords(t0); i--) + { + word temp = b[i]; + + if (t0%WORD_BITS) + { + b[i-t0/WORD_BITS] ^= temp >> t0%WORD_BITS; + b[i-t0/WORD_BITS-1] ^= temp << (WORD_BITS - t0%WORD_BITS); + } + else + b[i-t0/WORD_BITS] ^= temp; + + if ((t0-t1)%WORD_BITS) + { + b[i-(t0-t1)/WORD_BITS] ^= temp >> (t0-t1)%WORD_BITS; + b[i-(t0-t1)/WORD_BITS-1] ^= temp << (WORD_BITS - (t0-t1)%WORD_BITS); + } + else + b[i-(t0-t1)/WORD_BITS] ^= temp; + } + + if (i==BitsToWords(t0)-1 && t0%WORD_BITS) + { + word mask = ((word)1<<(t0%WORD_BITS))-1; + word temp = b[i] & ~mask; + b[i] &= mask; + + b[i-t0/WORD_BITS] ^= temp >> t0%WORD_BITS; + + if ((t0-t1)%WORD_BITS) + { + b[i-(t0-t1)/WORD_BITS] ^= temp >> (t0-t1)%WORD_BITS; + if ((t0-t1)%WORD_BITS > t0%WORD_BITS) + b[i-(t0-t1)/WORD_BITS-1] ^= temp << (WORD_BITS - (t0-t1)%WORD_BITS); + else + assert(temp << (WORD_BITS - (t0-t1)%WORD_BITS) == 0); + } + else + b[i-(t0-t1)/WORD_BITS] ^= temp; + } + + SetWords(result.reg.begin(), 0, result.reg.size()); + CopyWords(result.reg.begin(), b, STDMIN(b.size(), result.reg.size())); + return result; +} + +void GF2NP::DEREncodeElement(BufferedTransformation &out, const Element &a) const +{ + a.DEREncodeAsOctetString(out, MaxElementByteLength()); +} + +void GF2NP::BERDecodeElement(BufferedTransformation &in, Element &a) const +{ + a.BERDecodeAsOctetString(in, MaxElementByteLength()); +} + +void GF2NT::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + ASN1::characteristic_two_field().DEREncode(seq); + DERSequenceEncoder parameters(seq); + DEREncodeUnsigned(parameters, m); + ASN1::tpBasis().DEREncode(parameters); + DEREncodeUnsigned(parameters, t1); + parameters.MessageEnd(); + seq.MessageEnd(); +} + +void GF2NPP::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + ASN1::characteristic_two_field().DEREncode(seq); + DERSequenceEncoder parameters(seq); + DEREncodeUnsigned(parameters, m); + ASN1::ppBasis().DEREncode(parameters); + DERSequenceEncoder pentanomial(parameters); + DEREncodeUnsigned(pentanomial, t3); + DEREncodeUnsigned(pentanomial, t2); + DEREncodeUnsigned(pentanomial, t1); + pentanomial.MessageEnd(); + parameters.MessageEnd(); + seq.MessageEnd(); +} + +GF2NP * BERDecodeGF2NP(BufferedTransformation &bt) +{ + // VC60 workaround: auto_ptr lacks reset() + member_ptr result; + + BERSequenceDecoder seq(bt); + if (OID(seq) != ASN1::characteristic_two_field()) + BERDecodeError(); + BERSequenceDecoder parameters(seq); + unsigned int m; + BERDecodeUnsigned(parameters, m); + OID oid(parameters); + if (oid == ASN1::tpBasis()) + { + unsigned int t1; + BERDecodeUnsigned(parameters, t1); + result.reset(new GF2NT(m, t1, 0)); + } + else if (oid == ASN1::ppBasis()) + { + unsigned int t1, t2, t3; + BERSequenceDecoder pentanomial(parameters); + BERDecodeUnsigned(pentanomial, t3); + BERDecodeUnsigned(pentanomial, t2); + BERDecodeUnsigned(pentanomial, t1); + pentanomial.MessageEnd(); + result.reset(new GF2NPP(m, t3, t2, t1, 0)); + } + else + { + BERDecodeError(); + return NULL; + } + parameters.MessageEnd(); + seq.MessageEnd(); + + return result.release(); +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/gf2n.h b/src-cryptopp/gf2n.h new file mode 100644 index 0000000..67ade64 --- /dev/null +++ b/src-cryptopp/gf2n.h @@ -0,0 +1,369 @@ +#ifndef CRYPTOPP_GF2N_H +#define CRYPTOPP_GF2N_H + +/*! \file */ + +#include "cryptlib.h" +#include "secblock.h" +#include "misc.h" +#include "algebra.h" + +#include + +NAMESPACE_BEGIN(CryptoPP) + +//! Polynomial with Coefficients in GF(2) +/*! \nosubgrouping */ +class CRYPTOPP_DLL PolynomialMod2 +{ +public: + //! \name ENUMS, EXCEPTIONS, and TYPEDEFS + //@{ + //! divide by zero exception + class DivideByZero : public Exception + { + public: + DivideByZero() : Exception(OTHER_ERROR, "PolynomialMod2: division by zero") {} + }; + + typedef unsigned int RandomizationParameter; + //@} + + //! \name CREATORS + //@{ + //! creates the zero polynomial + PolynomialMod2(); + //! copy constructor + PolynomialMod2(const PolynomialMod2& t); + + //! convert from word + /*! value should be encoded with the least significant bit as coefficient to x^0 + and most significant bit as coefficient to x^(WORD_BITS-1) + bitLength denotes how much memory to allocate initially + */ + PolynomialMod2(word value, size_t bitLength=WORD_BITS); + + //! convert from big-endian byte array + PolynomialMod2(const byte *encodedPoly, size_t byteCount) + {Decode(encodedPoly, byteCount);} + + //! convert from big-endian form stored in a BufferedTransformation + PolynomialMod2(BufferedTransformation &encodedPoly, size_t byteCount) + {Decode(encodedPoly, byteCount);} + + //! create a random polynomial uniformly distributed over all polynomials with degree less than bitcount + PolynomialMod2(RandomNumberGenerator &rng, size_t bitcount) + {Randomize(rng, bitcount);} + + //! return x^i + static PolynomialMod2 CRYPTOPP_API Monomial(size_t i); + //! return x^t0 + x^t1 + x^t2 + static PolynomialMod2 CRYPTOPP_API Trinomial(size_t t0, size_t t1, size_t t2); + //! return x^t0 + x^t1 + x^t2 + x^t3 + x^t4 + static PolynomialMod2 CRYPTOPP_API Pentanomial(size_t t0, size_t t1, size_t t2, size_t t3, size_t t4); + //! return x^(n-1) + ... + x + 1 + static PolynomialMod2 CRYPTOPP_API AllOnes(size_t n); + + //! + static const PolynomialMod2 & CRYPTOPP_API Zero(); + //! + static const PolynomialMod2 & CRYPTOPP_API One(); + //@} + + //! \name ENCODE/DECODE + //@{ + //! minimum number of bytes to encode this polynomial + /*! MinEncodedSize of 0 is 1 */ + unsigned int MinEncodedSize() const {return STDMAX(1U, ByteCount());} + + //! encode in big-endian format + /*! if outputLen < MinEncodedSize, the most significant bytes will be dropped + if outputLen > MinEncodedSize, the most significant bytes will be padded + */ + void Encode(byte *output, size_t outputLen) const; + //! + void Encode(BufferedTransformation &bt, size_t outputLen) const; + + //! + void Decode(const byte *input, size_t inputLen); + //! + //* Precondition: bt.MaxRetrievable() >= inputLen + void Decode(BufferedTransformation &bt, size_t inputLen); + + //! encode value as big-endian octet string + void DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const; + //! decode value as big-endian octet string + void BERDecodeAsOctetString(BufferedTransformation &bt, size_t length); + //@} + + //! \name ACCESSORS + //@{ + //! number of significant bits = Degree() + 1 + unsigned int BitCount() const; + //! number of significant bytes = ceiling(BitCount()/8) + unsigned int ByteCount() const; + //! number of significant words = ceiling(ByteCount()/sizeof(word)) + unsigned int WordCount() const; + + //! return the n-th bit, n=0 being the least significant bit + bool GetBit(size_t n) const {return GetCoefficient(n)!=0;} + //! return the n-th byte + byte GetByte(size_t n) const; + + //! the zero polynomial will return a degree of -1 + signed int Degree() const {return BitCount()-1;} + //! degree + 1 + unsigned int CoefficientCount() const {return BitCount();} + //! return coefficient for x^i + int GetCoefficient(size_t i) const + {return (i/WORD_BITS < reg.size()) ? int(reg[i/WORD_BITS] >> (i % WORD_BITS)) & 1 : 0;} + //! return coefficient for x^i + int operator[](unsigned int i) const {return GetCoefficient(i);} + + //! + bool IsZero() const {return !*this;} + //! + bool Equals(const PolynomialMod2 &rhs) const; + //@} + + //! \name MANIPULATORS + //@{ + //! + PolynomialMod2& operator=(const PolynomialMod2& t); + //! + PolynomialMod2& operator&=(const PolynomialMod2& t); + //! + PolynomialMod2& operator^=(const PolynomialMod2& t); + //! + PolynomialMod2& operator+=(const PolynomialMod2& t) {return *this ^= t;} + //! + PolynomialMod2& operator-=(const PolynomialMod2& t) {return *this ^= t;} + //! + PolynomialMod2& operator*=(const PolynomialMod2& t); + //! + PolynomialMod2& operator/=(const PolynomialMod2& t); + //! + PolynomialMod2& operator%=(const PolynomialMod2& t); + //! + PolynomialMod2& operator<<=(unsigned int); + //! + PolynomialMod2& operator>>=(unsigned int); + + //! + void Randomize(RandomNumberGenerator &rng, size_t bitcount); + + //! + void SetBit(size_t i, int value = 1); + //! set the n-th byte to value + void SetByte(size_t n, byte value); + + //! + void SetCoefficient(size_t i, int value) {SetBit(i, value);} + + //! + void swap(PolynomialMod2 &a) {reg.swap(a.reg);} + //@} + + //! \name UNARY OPERATORS + //@{ + //! + bool operator!() const; + //! + PolynomialMod2 operator+() const {return *this;} + //! + PolynomialMod2 operator-() const {return *this;} + //@} + + //! \name BINARY OPERATORS + //@{ + //! + PolynomialMod2 And(const PolynomialMod2 &b) const; + //! + PolynomialMod2 Xor(const PolynomialMod2 &b) const; + //! + PolynomialMod2 Plus(const PolynomialMod2 &b) const {return Xor(b);} + //! + PolynomialMod2 Minus(const PolynomialMod2 &b) const {return Xor(b);} + //! + PolynomialMod2 Times(const PolynomialMod2 &b) const; + //! + PolynomialMod2 DividedBy(const PolynomialMod2 &b) const; + //! + PolynomialMod2 Modulo(const PolynomialMod2 &b) const; + + //! + PolynomialMod2 operator>>(unsigned int n) const; + //! + PolynomialMod2 operator<<(unsigned int n) const; + //@} + + //! \name OTHER ARITHMETIC FUNCTIONS + //@{ + //! sum modulo 2 of all coefficients + unsigned int Parity() const; + + //! check for irreducibility + bool IsIrreducible() const; + + //! is always zero since we're working modulo 2 + PolynomialMod2 Doubled() const {return Zero();} + //! + PolynomialMod2 Squared() const; + + //! only 1 is a unit + bool IsUnit() const {return Equals(One());} + //! return inverse if *this is a unit, otherwise return 0 + PolynomialMod2 MultiplicativeInverse() const {return IsUnit() ? One() : Zero();} + + //! greatest common divisor + static PolynomialMod2 CRYPTOPP_API Gcd(const PolynomialMod2 &a, const PolynomialMod2 &n); + //! calculate multiplicative inverse of *this mod n + PolynomialMod2 InverseMod(const PolynomialMod2 &) const; + + //! calculate r and q such that (a == d*q + r) && (deg(r) < deg(d)) + static void CRYPTOPP_API Divide(PolynomialMod2 &r, PolynomialMod2 &q, const PolynomialMod2 &a, const PolynomialMod2 &d); + //@} + + //! \name INPUT/OUTPUT + //@{ + //! + friend std::ostream& operator<<(std::ostream& out, const PolynomialMod2 &a); + //@} + +private: + friend class GF2NT; + + SecWordBlock reg; +}; + +//! +inline bool operator==(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) +{return a.Equals(b);} +//! +inline bool operator!=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) +{return !(a==b);} +//! compares degree +inline bool operator> (const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) +{return a.Degree() > b.Degree();} +//! compares degree +inline bool operator>=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) +{return a.Degree() >= b.Degree();} +//! compares degree +inline bool operator< (const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) +{return a.Degree() < b.Degree();} +//! compares degree +inline bool operator<=(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) +{return a.Degree() <= b.Degree();} +//! +inline CryptoPP::PolynomialMod2 operator&(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.And(b);} +//! +inline CryptoPP::PolynomialMod2 operator^(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Xor(b);} +//! +inline CryptoPP::PolynomialMod2 operator+(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Plus(b);} +//! +inline CryptoPP::PolynomialMod2 operator-(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Minus(b);} +//! +inline CryptoPP::PolynomialMod2 operator*(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Times(b);} +//! +inline CryptoPP::PolynomialMod2 operator/(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.DividedBy(b);} +//! +inline CryptoPP::PolynomialMod2 operator%(const CryptoPP::PolynomialMod2 &a, const CryptoPP::PolynomialMod2 &b) {return a.Modulo(b);} + +// CodeWarrior 8 workaround: put these template instantiations after overloaded operator declarations, +// but before the use of QuotientRing > for VC .NET 2003 +CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup; +CRYPTOPP_DLL_TEMPLATE_CLASS AbstractRing; +CRYPTOPP_DLL_TEMPLATE_CLASS AbstractEuclideanDomain; +CRYPTOPP_DLL_TEMPLATE_CLASS EuclideanDomainOf; +CRYPTOPP_DLL_TEMPLATE_CLASS QuotientRing >; + +//! GF(2^n) with Polynomial Basis +class CRYPTOPP_DLL GF2NP : public QuotientRing > +{ +public: + GF2NP(const PolynomialMod2 &modulus); + + virtual GF2NP * Clone() const {return new GF2NP(*this);} + virtual void DEREncode(BufferedTransformation &bt) const + {assert(false);} // no ASN.1 syntax yet for general polynomial basis + + void DEREncodeElement(BufferedTransformation &out, const Element &a) const; + void BERDecodeElement(BufferedTransformation &in, Element &a) const; + + bool Equal(const Element &a, const Element &b) const + {assert(a.Degree() < m_modulus.Degree() && b.Degree() < m_modulus.Degree()); return a.Equals(b);} + + bool IsUnit(const Element &a) const + {assert(a.Degree() < m_modulus.Degree()); return !!a;} + + unsigned int MaxElementBitLength() const + {return m;} + + unsigned int MaxElementByteLength() const + {return (unsigned int)BitsToBytes(MaxElementBitLength());} + + Element SquareRoot(const Element &a) const; + + Element HalfTrace(const Element &a) const; + + // returns z such that z^2 + z == a + Element SolveQuadraticEquation(const Element &a) const; + +protected: + unsigned int m; +}; + +//! GF(2^n) with Trinomial Basis +class CRYPTOPP_DLL GF2NT : public GF2NP +{ +public: + // polynomial modulus = x^t0 + x^t1 + x^t2, t0 > t1 > t2 + GF2NT(unsigned int t0, unsigned int t1, unsigned int t2); + + GF2NP * Clone() const {return new GF2NT(*this);} + void DEREncode(BufferedTransformation &bt) const; + + const Element& Multiply(const Element &a, const Element &b) const; + + const Element& Square(const Element &a) const + {return Reduced(a.Squared());} + + const Element& MultiplicativeInverse(const Element &a) const; + +private: + const Element& Reduced(const Element &a) const; + + unsigned int t0, t1; + mutable PolynomialMod2 result; +}; + +//! GF(2^n) with Pentanomial Basis +class CRYPTOPP_DLL GF2NPP : public GF2NP +{ +public: + // polynomial modulus = x^t0 + x^t1 + x^t2 + x^t3 + x^t4, t0 > t1 > t2 > t3 > t4 + GF2NPP(unsigned int t0, unsigned int t1, unsigned int t2, unsigned int t3, unsigned int t4) + : GF2NP(PolynomialMod2::Pentanomial(t0, t1, t2, t3, t4)), t0(t0), t1(t1), t2(t2), t3(t3) {} + + GF2NP * Clone() const {return new GF2NPP(*this);} + void DEREncode(BufferedTransformation &bt) const; + +private: + unsigned int t0, t1, t2, t3; +}; + +// construct new GF2NP from the ASN.1 sequence Characteristic-two +CRYPTOPP_DLL GF2NP * CRYPTOPP_API BERDecodeGF2NP(BufferedTransformation &bt); + +NAMESPACE_END + +#ifndef __BORLANDC__ +NAMESPACE_BEGIN(std) +template<> inline void swap(CryptoPP::PolynomialMod2 &a, CryptoPP::PolynomialMod2 &b) +{ + a.swap(b); +} +NAMESPACE_END +#endif + +#endif diff --git a/src-cryptopp/gfpcrypt.cpp b/src-cryptopp/gfpcrypt.cpp new file mode 100644 index 0000000..6d9ffce --- /dev/null +++ b/src-cryptopp/gfpcrypt.cpp @@ -0,0 +1,275 @@ +// dsa.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "gfpcrypt.h" +#include "asn.h" +#include "oids.h" +#include "nbtheory.h" + +NAMESPACE_BEGIN(CryptoPP) + +void TestInstantiations_gfpcrypt() +{ + GDSA::Signer test; + GDSA::Verifier test1; + DSA::Signer test5(NullRNG(), 100); + DSA::Signer test2(test5); + NR::Signer test3; + NR::Verifier test4; + DLIES<>::Encryptor test6; + DLIES<>::Decryptor test7; +} + +void DL_GroupParameters_DSA::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg) +{ + Integer p, q, g; + + if (alg.GetValue("Modulus", p) && alg.GetValue("SubgroupGenerator", g)) + { + q = alg.GetValueWithDefault("SubgroupOrder", ComputeGroupOrder(p)/2); + } + else + { + int modulusSize = 1024; + alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize); + + if (!DSA::IsValidPrimeLength(modulusSize)) + throw InvalidArgument("DSA: not a valid prime length"); + + SecByteBlock seed(SHA::DIGESTSIZE); + Integer h; + int c; + + do + { + rng.GenerateBlock(seed, SHA::DIGESTSIZE); + } while (!DSA::GeneratePrimes(seed, SHA::DIGESTSIZE*8, c, p, modulusSize, q)); + + do + { + h.Randomize(rng, 2, p-2); + g = a_exp_b_mod_c(h, (p-1)/q, p); + } while (g <= 1); + } + + Initialize(p, q, g); +} + +bool DL_GroupParameters_DSA::ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const +{ + bool pass = DL_GroupParameters_GFP::ValidateGroup(rng, level); + pass = pass && DSA::IsValidPrimeLength(GetModulus().BitCount()); + pass = pass && GetSubgroupOrder().BitCount() == 160; + return pass; +} + +void DL_SignatureMessageEncodingMethod_DSA::ComputeMessageRepresentative(RandomNumberGenerator &rng, + const byte *recoverableMessage, size_t recoverableMessageLength, + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const +{ + assert(recoverableMessageLength == 0); + assert(hashIdentifier.second == 0); + const size_t representativeByteLength = BitsToBytes(representativeBitLength); + const size_t digestSize = hash.DigestSize(); + const size_t paddingLength = SaturatingSubtract(representativeByteLength, digestSize); + + memset(representative, 0, paddingLength); + hash.TruncatedFinal(representative+paddingLength, STDMIN(representativeByteLength, digestSize)); + + if (digestSize*8 > representativeBitLength) + { + Integer h(representative, representativeByteLength); + h >>= representativeByteLength*8 - representativeBitLength; + h.Encode(representative, representativeByteLength); + } +} + +void DL_SignatureMessageEncodingMethod_NR::ComputeMessageRepresentative(RandomNumberGenerator &rng, + const byte *recoverableMessage, size_t recoverableMessageLength, + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const +{ + assert(recoverableMessageLength == 0); + assert(hashIdentifier.second == 0); + const size_t representativeByteLength = BitsToBytes(representativeBitLength); + const size_t digestSize = hash.DigestSize(); + const size_t paddingLength = SaturatingSubtract(representativeByteLength, digestSize); + + memset(representative, 0, paddingLength); + hash.TruncatedFinal(representative+paddingLength, STDMIN(representativeByteLength, digestSize)); + + if (digestSize*8 >= representativeBitLength) + { + Integer h(representative, representativeByteLength); + h >>= representativeByteLength*8 - representativeBitLength + 1; + h.Encode(representative, representativeByteLength); + } +} + +bool DL_GroupParameters_IntegerBased::ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const +{ + const Integer &p = GetModulus(), &q = GetSubgroupOrder(); + + bool pass = true; + pass = pass && p > Integer::One() && p.IsOdd(); + pass = pass && q > Integer::One() && q.IsOdd(); + + if (level >= 1) + pass = pass && GetCofactor() > Integer::One() && GetGroupOrder() % q == Integer::Zero(); + if (level >= 2) + pass = pass && VerifyPrime(rng, q, level-2) && VerifyPrime(rng, p, level-2); + + return pass; +} + +bool DL_GroupParameters_IntegerBased::ValidateElement(unsigned int level, const Integer &g, const DL_FixedBasePrecomputation *gpc) const +{ + const Integer &p = GetModulus(), &q = GetSubgroupOrder(); + + bool pass = true; + pass = pass && GetFieldType() == 1 ? g.IsPositive() : g.NotNegative(); + pass = pass && g < p && !IsIdentity(g); + + if (level >= 1) + { + if (gpc) + pass = pass && gpc->Exponentiate(GetGroupPrecomputation(), Integer::One()) == g; + } + if (level >= 2) + { + if (GetFieldType() == 2) + pass = pass && Jacobi(g*g-4, p)==-1; + + // verifying that Lucas((p+1)/2, w, p)==2 is omitted because it's too costly + // and at most 1 bit is leaked if it's false + bool fullValidate = (GetFieldType() == 2 && level >= 3) || !FastSubgroupCheckAvailable(); + + if (fullValidate && pass) + { + Integer gp = gpc ? gpc->Exponentiate(GetGroupPrecomputation(), q) : ExponentiateElement(g, q); + pass = pass && IsIdentity(gp); + } + else if (GetFieldType() == 1) + pass = pass && Jacobi(g, p) == 1; + } + + return pass; +} + +void DL_GroupParameters_IntegerBased::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg) +{ + Integer p, q, g; + + if (alg.GetValue("Modulus", p) && alg.GetValue("SubgroupGenerator", g)) + { + q = alg.GetValueWithDefault("SubgroupOrder", ComputeGroupOrder(p)/2); + } + else + { + int modulusSize, subgroupOrderSize; + + if (!alg.GetIntValue("ModulusSize", modulusSize)) + modulusSize = alg.GetIntValueWithDefault("KeySize", 2048); + + if (!alg.GetIntValue("SubgroupOrderSize", subgroupOrderSize)) + subgroupOrderSize = GetDefaultSubgroupOrderSize(modulusSize); + + PrimeAndGenerator pg; + pg.Generate(GetFieldType() == 1 ? 1 : -1, rng, modulusSize, subgroupOrderSize); + p = pg.Prime(); + q = pg.SubPrime(); + g = pg.Generator(); + } + + Initialize(p, q, g); +} + +Integer DL_GroupParameters_IntegerBased::DecodeElement(const byte *encoded, bool checkForGroupMembership) const +{ + Integer g(encoded, GetModulus().ByteCount()); + if (!ValidateElement(1, g, NULL)) + throw DL_BadElement(); + return g; +} + +void DL_GroupParameters_IntegerBased::BERDecode(BufferedTransformation &bt) +{ + BERSequenceDecoder parameters(bt); + Integer p(parameters); + Integer q(parameters); + Integer g; + if (parameters.EndReached()) + { + g = q; + q = ComputeGroupOrder(p) / 2; + } + else + g.BERDecode(parameters); + parameters.MessageEnd(); + + SetModulusAndSubgroupGenerator(p, g); + SetSubgroupOrder(q); +} + +void DL_GroupParameters_IntegerBased::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder parameters(bt); + GetModulus().DEREncode(parameters); + m_q.DEREncode(parameters); + GetSubgroupGenerator().DEREncode(parameters); + parameters.MessageEnd(); +} + +bool DL_GroupParameters_IntegerBased::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + return GetValueHelper >(this, name, valueType, pValue) + CRYPTOPP_GET_FUNCTION_ENTRY(Modulus); +} + +void DL_GroupParameters_IntegerBased::AssignFrom(const NameValuePairs &source) +{ + AssignFromHelper(this, source) + CRYPTOPP_SET_FUNCTION_ENTRY2(Modulus, SubgroupGenerator) + CRYPTOPP_SET_FUNCTION_ENTRY(SubgroupOrder) + ; +} + +OID DL_GroupParameters_IntegerBased::GetAlgorithmID() const +{ + return ASN1::id_dsa(); +} + +void DL_GroupParameters_GFP::SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const +{ + ModularArithmetic ma(GetModulus()); + ma.SimultaneousExponentiate(results, base, exponents, exponentsCount); +} + +DL_GroupParameters_GFP::Element DL_GroupParameters_GFP::MultiplyElements(const Element &a, const Element &b) const +{ + return a_times_b_mod_c(a, b, GetModulus()); +} + +DL_GroupParameters_GFP::Element DL_GroupParameters_GFP::CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const +{ + ModularArithmetic ma(GetModulus()); + return ma.CascadeExponentiate(element1, exponent1, element2, exponent2); +} + +Integer DL_GroupParameters_IntegerBased::GetMaxExponent() const +{ + return STDMIN(GetSubgroupOrder()-1, Integer::Power2(2*DiscreteLogWorkFactor(GetFieldType()*GetModulus().BitCount()))); +} + +unsigned int DL_GroupParameters_IntegerBased::GetDefaultSubgroupOrderSize(unsigned int modulusSize) const +{ + return 2*DiscreteLogWorkFactor(GetFieldType()*modulusSize); +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/gfpcrypt.h b/src-cryptopp/gfpcrypt.h new file mode 100644 index 0000000..5e9c635 --- /dev/null +++ b/src-cryptopp/gfpcrypt.h @@ -0,0 +1,536 @@ +#ifndef CRYPTOPP_GFPCRYPT_H +#define CRYPTOPP_GFPCRYPT_H + +/** \file + Implementation of schemes based on DL over GF(p) +*/ + +#include "pubkey.h" +#include "modexppc.h" +#include "sha.h" +#include "algparam.h" +#include "asn.h" +#include "smartptr.h" +#include "hmac.h" + +#include + +NAMESPACE_BEGIN(CryptoPP) + +CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters; + +//! _ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBased : public ASN1CryptoMaterial > +{ + typedef DL_GroupParameters_IntegerBased ThisClass; + +public: + void Initialize(const DL_GroupParameters_IntegerBased ¶ms) + {Initialize(params.GetModulus(), params.GetSubgroupOrder(), params.GetSubgroupGenerator());} + void Initialize(RandomNumberGenerator &rng, unsigned int pbits) + {GenerateRandom(rng, MakeParameters("ModulusSize", (int)pbits));} + void Initialize(const Integer &p, const Integer &g) + {SetModulusAndSubgroupGenerator(p, g); SetSubgroupOrder(ComputeGroupOrder(p)/2);} + void Initialize(const Integer &p, const Integer &q, const Integer &g) + {SetModulusAndSubgroupGenerator(p, g); SetSubgroupOrder(q);} + + // ASN1Object interface + void BERDecode(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const; + + // GeneratibleCryptoMaterial interface + /*! parameters: (ModulusSize, SubgroupOrderSize (optional)) */ + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg); + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + + // DL_GroupParameters + const Integer & GetSubgroupOrder() const {return m_q;} + Integer GetGroupOrder() const {return GetFieldType() == 1 ? GetModulus()-Integer::One() : GetModulus()+Integer::One();} + bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const; + bool ValidateElement(unsigned int level, const Integer &element, const DL_FixedBasePrecomputation *precomp) const; + bool FastSubgroupCheckAvailable() const {return GetCofactor() == 2;} + void EncodeElement(bool reversible, const Element &element, byte *encoded) const + {element.Encode(encoded, GetModulus().ByteCount());} + unsigned int GetEncodedElementSize(bool reversible) const {return GetModulus().ByteCount();} + Integer DecodeElement(const byte *encoded, bool checkForGroupMembership) const; + Integer ConvertElementToInteger(const Element &element) const + {return element;} + Integer GetMaxExponent() const; + static std::string CRYPTOPP_API StaticAlgorithmNamePrefix() {return "";} + + OID GetAlgorithmID() const; + + virtual const Integer & GetModulus() const =0; + virtual void SetModulusAndSubgroupGenerator(const Integer &p, const Integer &g) =0; + + void SetSubgroupOrder(const Integer &q) + {m_q = q; ParametersChanged();} + +protected: + Integer ComputeGroupOrder(const Integer &modulus) const + {return modulus-(GetFieldType() == 1 ? 1 : -1);} + + // GF(p) = 1, GF(p^2) = 2 + virtual int GetFieldType() const =0; + virtual unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const; + +private: + Integer m_q; +}; + +//! _ +template > +class CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBasedImpl : public DL_GroupParametersImpl +{ + typedef DL_GroupParameters_IntegerBasedImpl ThisClass; + +public: + typedef typename GROUP_PRECOMP::Element Element; + + // GeneratibleCryptoMaterial interface + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const + {return GetValueHelper(this, name, valueType, pValue).Assignable();} + + void AssignFrom(const NameValuePairs &source) + {AssignFromHelper(this, source);} + + // DL_GroupParameters + const DL_FixedBasePrecomputation & GetBasePrecomputation() const {return this->m_gpc;} + DL_FixedBasePrecomputation & AccessBasePrecomputation() {return this->m_gpc;} + + // IntegerGroupParameters + const Integer & GetModulus() const {return this->m_groupPrecomputation.GetModulus();} + const Integer & GetGenerator() const {return this->m_gpc.GetBase(this->GetGroupPrecomputation());} + + void SetModulusAndSubgroupGenerator(const Integer &p, const Integer &g) // these have to be set together + {this->m_groupPrecomputation.SetModulus(p); this->m_gpc.SetBase(this->GetGroupPrecomputation(), g); this->ParametersChanged();} + + // non-inherited + bool operator==(const DL_GroupParameters_IntegerBasedImpl &rhs) const + {return GetModulus() == rhs.GetModulus() && GetGenerator() == rhs.GetGenerator() && this->GetSubgroupOrder() == rhs.GetSubgroupOrder();} + bool operator!=(const DL_GroupParameters_IntegerBasedImpl &rhs) const + {return !operator==(rhs);} +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_IntegerBasedImpl; + +//! GF(p) group parameters +class CRYPTOPP_DLL DL_GroupParameters_GFP : public DL_GroupParameters_IntegerBasedImpl +{ +public: + // DL_GroupParameters + bool IsIdentity(const Integer &element) const {return element == Integer::One();} + void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const; + + // NameValuePairs interface + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const + { + return GetValueHelper(this, name, valueType, pValue).Assignable(); + } + + // used by MQV + Element MultiplyElements(const Element &a, const Element &b) const; + Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const; + +protected: + int GetFieldType() const {return 1;} +}; + +//! GF(p) group parameters that default to same primes +class CRYPTOPP_DLL DL_GroupParameters_GFP_DefaultSafePrime : public DL_GroupParameters_GFP +{ +public: + typedef NoCofactorMultiplication DefaultCofactorOption; + +protected: + unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const {return modulusSize-1;} +}; + +//! GDSA algorithm +template +class DL_Algorithm_GDSA : public DL_ElgamalLikeSignatureAlgorithm +{ +public: + static const char * CRYPTOPP_API StaticAlgorithmName() {return "DSA-1363";} + + void Sign(const DL_GroupParameters ¶ms, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const + { + const Integer &q = params.GetSubgroupOrder(); + r %= q; + Integer kInv = k.InverseMod(q); + s = (kInv * (x*r + e)) % q; + assert(!!r && !!s); + } + + bool Verify(const DL_GroupParameters ¶ms, const DL_PublicKey &publicKey, const Integer &e, const Integer &r, const Integer &s) const + { + const Integer &q = params.GetSubgroupOrder(); + if (r>=q || r<1 || s>=q || s<1) + return false; + + Integer w = s.InverseMod(q); + Integer u1 = (e * w) % q; + Integer u2 = (r * w) % q; + // verify r == (g^u1 * y^u2 mod p) mod q + return r == params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(u1, u2)) % q; + } +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA; + +//! NR algorithm +template +class DL_Algorithm_NR : public DL_ElgamalLikeSignatureAlgorithm +{ +public: + static const char * CRYPTOPP_API StaticAlgorithmName() {return "NR";} + + void Sign(const DL_GroupParameters ¶ms, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const + { + const Integer &q = params.GetSubgroupOrder(); + r = (r + e) % q; + s = (k - x*r) % q; + assert(!!r); + } + + bool Verify(const DL_GroupParameters ¶ms, const DL_PublicKey &publicKey, const Integer &e, const Integer &r, const Integer &s) const + { + const Integer &q = params.GetSubgroupOrder(); + if (r>=q || r<1 || s>=q) + return false; + + // check r == (m_g^s * m_y^r + m) mod m_q + return r == (params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(s, r)) + e) % q; + } +}; + +/*! DSA public key format is defined in 7.3.3 of RFC 2459. The + private key format is defined in 12.9 of PKCS #11 v2.10. */ +template +class DL_PublicKey_GFP : public DL_PublicKeyImpl +{ +public: + void Initialize(const DL_GroupParameters_IntegerBased ¶ms, const Integer &y) + {this->AccessGroupParameters().Initialize(params); this->SetPublicElement(y);} + void Initialize(const Integer &p, const Integer &g, const Integer &y) + {this->AccessGroupParameters().Initialize(p, g); this->SetPublicElement(y);} + void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &y) + {this->AccessGroupParameters().Initialize(p, q, g); this->SetPublicElement(y);} + + // X509PublicKey + void BERDecodePublicKey(BufferedTransformation &bt, bool, size_t) + {this->SetPublicElement(Integer(bt));} + void DEREncodePublicKey(BufferedTransformation &bt) const + {this->GetPublicElement().DEREncode(bt);} +}; + +//! DL private key (in GF(p) groups) +template +class DL_PrivateKey_GFP : public DL_PrivateKeyImpl +{ +public: + void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits) + {this->GenerateRandomWithKeySize(rng, modulusBits);} + void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &g) + {this->GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupGenerator", g));} + void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &q, const Integer &g) + {this->GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupOrder", q)("SubgroupGenerator", g));} + void Initialize(const DL_GroupParameters_IntegerBased ¶ms, const Integer &x) + {this->AccessGroupParameters().Initialize(params); this->SetPrivateExponent(x);} + void Initialize(const Integer &p, const Integer &g, const Integer &x) + {this->AccessGroupParameters().Initialize(p, g); this->SetPrivateExponent(x);} + void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &x) + {this->AccessGroupParameters().Initialize(p, q, g); this->SetPrivateExponent(x);} +}; + +//! DL signing/verification keys (in GF(p) groups) +struct DL_SignatureKeys_GFP +{ + typedef DL_GroupParameters_GFP GroupParameters; + typedef DL_PublicKey_GFP PublicKey; + typedef DL_PrivateKey_GFP PrivateKey; +}; + +//! DL encryption/decryption keys (in GF(p) groups) +struct DL_CryptoKeys_GFP +{ + typedef DL_GroupParameters_GFP_DefaultSafePrime GroupParameters; + typedef DL_PublicKey_GFP PublicKey; + typedef DL_PrivateKey_GFP PrivateKey; +}; + +//! provided for backwards compatibility, this class uses the old non-standard Crypto++ key format +template +class DL_PublicKey_GFP_OldFormat : public BASE +{ +public: + void BERDecode(BufferedTransformation &bt) + { + BERSequenceDecoder seq(bt); + Integer v1(seq); + Integer v2(seq); + Integer v3(seq); + + if (seq.EndReached()) + { + this->AccessGroupParameters().Initialize(v1, v1/2, v2); + this->SetPublicElement(v3); + } + else + { + Integer v4(seq); + this->AccessGroupParameters().Initialize(v1, v2, v3); + this->SetPublicElement(v4); + } + + seq.MessageEnd(); + } + + void DEREncode(BufferedTransformation &bt) const + { + DERSequenceEncoder seq(bt); + this->GetGroupParameters().GetModulus().DEREncode(seq); + if (this->GetGroupParameters().GetCofactor() != 2) + this->GetGroupParameters().GetSubgroupOrder().DEREncode(seq); + this->GetGroupParameters().GetGenerator().DEREncode(seq); + this->GetPublicElement().DEREncode(seq); + seq.MessageEnd(); + } +}; + +//! provided for backwards compatibility, this class uses the old non-standard Crypto++ key format +template +class DL_PrivateKey_GFP_OldFormat : public BASE +{ +public: + void BERDecode(BufferedTransformation &bt) + { + BERSequenceDecoder seq(bt); + Integer v1(seq); + Integer v2(seq); + Integer v3(seq); + Integer v4(seq); + + if (seq.EndReached()) + { + this->AccessGroupParameters().Initialize(v1, v1/2, v2); + this->SetPrivateExponent(v4 % (v1/2)); // some old keys may have x >= q + } + else + { + Integer v5(seq); + this->AccessGroupParameters().Initialize(v1, v2, v3); + this->SetPrivateExponent(v5); + } + + seq.MessageEnd(); + } + + void DEREncode(BufferedTransformation &bt) const + { + DERSequenceEncoder seq(bt); + this->GetGroupParameters().GetModulus().DEREncode(seq); + if (this->GetGroupParameters().GetCofactor() != 2) + this->GetGroupParameters().GetSubgroupOrder().DEREncode(seq); + this->GetGroupParameters().GetGenerator().DEREncode(seq); + this->GetGroupParameters().ExponentiateBase(this->GetPrivateExponent()).DEREncode(seq); + this->GetPrivateExponent().DEREncode(seq); + seq.MessageEnd(); + } +}; + +//! DSA-1363 +template +struct GDSA : public DL_SS< + DL_SignatureKeys_GFP, + DL_Algorithm_GDSA, + DL_SignatureMessageEncodingMethod_DSA, + H> +{ +}; + +//! NR +template +struct NR : public DL_SS< + DL_SignatureKeys_GFP, + DL_Algorithm_NR, + DL_SignatureMessageEncodingMethod_NR, + H> +{ +}; + +//! DSA group parameters, these are GF(p) group parameters that are allowed by the DSA standard +class CRYPTOPP_DLL DL_GroupParameters_DSA : public DL_GroupParameters_GFP +{ +public: + /*! also checks that the lengths of p and q are allowed by the DSA standard */ + bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const; + /*! parameters: (ModulusSize), or (Modulus, SubgroupOrder, SubgroupGenerator) */ + /*! ModulusSize must be between DSA::MIN_PRIME_LENGTH and DSA::MAX_PRIME_LENGTH, and divisible by DSA::PRIME_LENGTH_MULTIPLE */ + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg); +}; + +struct DSA; + +//! DSA keys +struct DL_Keys_DSA +{ + typedef DL_PublicKey_GFP PublicKey; + typedef DL_PrivateKey_WithSignaturePairwiseConsistencyTest, DSA> PrivateKey; +}; + +//! DSA +struct CRYPTOPP_DLL DSA : public DL_SS< + DL_Keys_DSA, + DL_Algorithm_GDSA, + DL_SignatureMessageEncodingMethod_DSA, + SHA, + DSA> +{ + static const char * CRYPTOPP_API StaticAlgorithmName() {return "DSA";} + + //! Generate DSA primes according to NIST standard + /*! Both seedLength and primeLength are in bits, but seedLength should + be a multiple of 8. + If useInputCounterValue == true, the counter parameter is taken as input, otherwise it's used for output + */ + static bool CRYPTOPP_API GeneratePrimes(const byte *seed, unsigned int seedLength, int &counter, + Integer &p, unsigned int primeLength, Integer &q, bool useInputCounterValue = false); + + static bool CRYPTOPP_API IsValidPrimeLength(unsigned int pbits) + {return pbits >= MIN_PRIME_LENGTH && pbits <= MAX_PRIME_LENGTH && pbits % PRIME_LENGTH_MULTIPLE == 0;} + + //! FIPS 186-2 Change Notice 1 changed the minimum modulus length to 1024 + enum { +#if (DSA_1024_BIT_MODULUS_ONLY) + MIN_PRIME_LENGTH = 1024, +#else + MIN_PRIME_LENGTH = 512, +#endif + MAX_PRIME_LENGTH = 1024, PRIME_LENGTH_MULTIPLE = 64}; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_GFP; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_GFP; +CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest, DSA>; + +//! the XOR encryption method, for use with DL-based cryptosystems +template +class DL_EncryptionAlgorithm_Xor : public DL_SymmetricEncryptionAlgorithm +{ +public: + bool ParameterSupported(const char *name) const {return strcmp(name, Name::EncodingParameters()) == 0;} + size_t GetSymmetricKeyLength(size_t plaintextLength) const + {return plaintextLength + MAC::DEFAULT_KEYLENGTH;} + size_t GetSymmetricCiphertextLength(size_t plaintextLength) const + {return plaintextLength + MAC::DIGESTSIZE;} + size_t GetMaxSymmetricPlaintextLength(size_t ciphertextLength) const + {return (unsigned int)SaturatingSubtract(ciphertextLength, (unsigned int)MAC::DIGESTSIZE);} + void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters) const + { + const byte *cipherKey, *macKey; + if (DHAES_MODE) + { + macKey = key; + cipherKey = key + MAC::DEFAULT_KEYLENGTH; + } + else + { + cipherKey = key; + macKey = key + plaintextLength; + } + + ConstByteArrayParameter encodingParameters; + parameters.GetValue(Name::EncodingParameters(), encodingParameters); + + xorbuf(ciphertext, plaintext, cipherKey, plaintextLength); + MAC mac(macKey); + mac.Update(ciphertext, plaintextLength); + mac.Update(encodingParameters.begin(), encodingParameters.size()); + if (DHAES_MODE) + { + byte L[8] = {0,0,0,0}; + PutWord(false, BIG_ENDIAN_ORDER, L+4, word32(encodingParameters.size())); + mac.Update(L, 8); + } + mac.Final(ciphertext + plaintextLength); + } + DecodingResult SymmetricDecrypt(const byte *key, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters) const + { + size_t plaintextLength = GetMaxSymmetricPlaintextLength(ciphertextLength); + const byte *cipherKey, *macKey; + if (DHAES_MODE) + { + macKey = key; + cipherKey = key + MAC::DEFAULT_KEYLENGTH; + } + else + { + cipherKey = key; + macKey = key + plaintextLength; + } + + ConstByteArrayParameter encodingParameters; + parameters.GetValue(Name::EncodingParameters(), encodingParameters); + + MAC mac(macKey); + mac.Update(ciphertext, plaintextLength); + mac.Update(encodingParameters.begin(), encodingParameters.size()); + if (DHAES_MODE) + { + byte L[8] = {0,0,0,0}; + PutWord(false, BIG_ENDIAN_ORDER, L+4, word32(encodingParameters.size())); + mac.Update(L, 8); + } + if (!mac.Verify(ciphertext + plaintextLength)) + return DecodingResult(); + + xorbuf(plaintext, ciphertext, cipherKey, plaintextLength); + return DecodingResult(plaintextLength); + } +}; + +//! _ +template +class DL_KeyDerivationAlgorithm_P1363 : public DL_KeyDerivationAlgorithm +{ +public: + bool ParameterSupported(const char *name) const {return strcmp(name, Name::KeyDerivationParameters()) == 0;} + void Derive(const DL_GroupParameters ¶ms, byte *derivedKey, size_t derivedLength, const T &agreedElement, const T &ephemeralPublicKey, const NameValuePairs ¶meters) const + { + SecByteBlock agreedSecret; + if (DHAES_MODE) + { + agreedSecret.New(params.GetEncodedElementSize(true) + params.GetEncodedElementSize(false)); + params.EncodeElement(true, ephemeralPublicKey, agreedSecret); + params.EncodeElement(false, agreedElement, agreedSecret + params.GetEncodedElementSize(true)); + } + else + { + agreedSecret.New(params.GetEncodedElementSize(false)); + params.EncodeElement(false, agreedElement, agreedSecret); + } + + ConstByteArrayParameter derivationParameters; + parameters.GetValue(Name::KeyDerivationParameters(), derivationParameters); + KDF::DeriveKey(derivedKey, derivedLength, agreedSecret, agreedSecret.size(), derivationParameters.begin(), derivationParameters.size()); + } +}; + +//! Discrete Log Integrated Encryption Scheme, AKA DLIES +template +struct DLIES + : public DL_ES< + DL_CryptoKeys_GFP, + DL_KeyAgreementAlgorithm_DH, + DL_KeyDerivationAlgorithm_P1363 >, + DL_EncryptionAlgorithm_Xor, DHAES_MODE>, + DLIES<> > +{ + static std::string CRYPTOPP_API StaticAlgorithmName() {return "DLIES";} // TODO: fix this after name is standardized +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/hex.cpp b/src-cryptopp/hex.cpp new file mode 100644 index 0000000..b6484a5 --- /dev/null +++ b/src-cryptopp/hex.cpp @@ -0,0 +1,44 @@ +// hex.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "hex.h" + +NAMESPACE_BEGIN(CryptoPP) + +static const byte s_vecUpper[] = "0123456789ABCDEF"; +static const byte s_vecLower[] = "0123456789abcdef"; + +void HexEncoder::IsolatedInitialize(const NameValuePairs ¶meters) +{ + bool uppercase = parameters.GetValueWithDefault(Name::Uppercase(), true); + m_filter->Initialize(CombinedNameValuePairs( + parameters, + MakeParameters(Name::EncodingLookupArray(), uppercase ? &s_vecUpper[0] : &s_vecLower[0], false)(Name::Log2Base(), 4, true))); +} + +void HexDecoder::IsolatedInitialize(const NameValuePairs ¶meters) +{ + BaseN_Decoder::IsolatedInitialize(CombinedNameValuePairs( + parameters, + MakeParameters(Name::DecodingLookupArray(), GetDefaultDecodingLookupArray(), false)(Name::Log2Base(), 4, true))); +} + +const int *HexDecoder::GetDefaultDecodingLookupArray() +{ + static bool s_initialized = false; + static int s_array[256]; + + if (!s_initialized) + { + InitializeDecodingLookupArray(s_array, s_vecUpper, 16, true); + s_initialized = true; + } + return s_array; +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/hex.h b/src-cryptopp/hex.h new file mode 100644 index 0000000..006914c --- /dev/null +++ b/src-cryptopp/hex.h @@ -0,0 +1,36 @@ +#ifndef CRYPTOPP_HEX_H +#define CRYPTOPP_HEX_H + +#include "basecode.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! Converts given data to base 16 +class CRYPTOPP_DLL HexEncoder : public SimpleProxyFilter +{ +public: + HexEncoder(BufferedTransformation *attachment = NULL, bool uppercase = true, int outputGroupSize = 0, const std::string &separator = ":", const std::string &terminator = "") + : SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment) + { + IsolatedInitialize(MakeParameters(Name::Uppercase(), uppercase)(Name::GroupSize(), outputGroupSize)(Name::Separator(), ConstByteArrayParameter(separator))(Name::Terminator(), ConstByteArrayParameter(terminator))); + } + + void IsolatedInitialize(const NameValuePairs ¶meters); +}; + +//! Decode base 16 data back to bytes +class CRYPTOPP_DLL HexDecoder : public BaseN_Decoder +{ +public: + HexDecoder(BufferedTransformation *attachment = NULL) + : BaseN_Decoder(GetDefaultDecodingLookupArray(), 4, attachment) {} + + void IsolatedInitialize(const NameValuePairs ¶meters); + +private: + static const int * CRYPTOPP_API GetDefaultDecodingLookupArray(); +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/hmac.cpp b/src-cryptopp/hmac.cpp new file mode 100644 index 0000000..d4a649c --- /dev/null +++ b/src-cryptopp/hmac.cpp @@ -0,0 +1,86 @@ +// hmac.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "hmac.h" + +NAMESPACE_BEGIN(CryptoPP) + +void HMAC_Base::UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs &) +{ + AssertValidKeyLength(keylength); + + Restart(); + + HashTransformation &hash = AccessHash(); + unsigned int blockSize = hash.BlockSize(); + + if (!blockSize) + throw InvalidArgument("HMAC: can only be used with a block-based hash function"); + + m_buf.resize(2*AccessHash().BlockSize() + AccessHash().DigestSize()); + + if (keylength <= blockSize) + memcpy(AccessIpad(), userKey, keylength); + else + { + AccessHash().CalculateDigest(AccessIpad(), userKey, keylength); + keylength = hash.DigestSize(); + } + + assert(keylength <= blockSize); + memset(AccessIpad()+keylength, 0, blockSize-keylength); + + for (unsigned int i=0; i, public MessageAuthenticationCode +{ +public: + HMAC_Base() : m_innerHashKeyed(false) {} + void UncheckedSetKey(const byte *userKey, unsigned int keylength, const NameValuePairs ¶ms); + + void Restart(); + void Update(const byte *input, size_t length); + void TruncatedFinal(byte *mac, size_t size); + unsigned int OptimalBlockSize() const {return const_cast(this)->AccessHash().OptimalBlockSize();} + unsigned int DigestSize() const {return const_cast(this)->AccessHash().DigestSize();} + +protected: + virtual HashTransformation & AccessHash() =0; + byte * AccessIpad() {return m_buf;} + byte * AccessOpad() {return m_buf + AccessHash().BlockSize();} + byte * AccessInnerHash() {return m_buf + 2*AccessHash().BlockSize();} + +private: + void KeyInnerHash(); + + SecByteBlock m_buf; + bool m_innerHashKeyed; +}; + +//! HMAC +/*! HMAC(K, text) = H(K XOR opad, H(K XOR ipad, text)) */ +template +class HMAC : public MessageAuthenticationCodeImpl > +{ +public: + CRYPTOPP_CONSTANT(DIGESTSIZE=T::DIGESTSIZE) + CRYPTOPP_CONSTANT(BLOCKSIZE=T::BLOCKSIZE) + + HMAC() {} + HMAC(const byte *key, size_t length=HMAC_Base::DEFAULT_KEYLENGTH) + {this->SetKey(key, length);} + + static std::string StaticAlgorithmName() {return std::string("HMAC(") + T::StaticAlgorithmName() + ")";} + std::string AlgorithmName() const {return std::string("HMAC(") + m_hash.AlgorithmName() + ")";} + +private: + HashTransformation & AccessHash() {return m_hash;} + + T m_hash; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/integer.cpp b/src-cryptopp/integer.cpp new file mode 100644 index 0000000..9adb745 --- /dev/null +++ b/src-cryptopp/integer.cpp @@ -0,0 +1,4245 @@ +// integer.cpp - written and placed in the public domain by Wei Dai +// contains public domain code contributed by Alister Lee and Leonard Janke + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "integer.h" +#include "modarith.h" +#include "nbtheory.h" +#include "asn.h" +#include "oids.h" +#include "words.h" +#include "algparam.h" +#include "pubkey.h" // for P1363_KDF2 +#include "sha.h" +#include "cpu.h" + +#include + +#if _MSC_VER >= 1400 + #include +#endif + +#ifdef __DECCXX + #include +#endif + +#ifdef CRYPTOPP_MSVC6_NO_PP + #pragma message("You do not seem to have the Visual C++ Processor Pack installed, so use of SSE2 instructions will be disabled.") +#endif + +#define CRYPTOPP_INTEGER_SSE2 (CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86) + +NAMESPACE_BEGIN(CryptoPP) + +bool AssignIntToInteger(const std::type_info &valueType, void *pInteger, const void *pInt) +{ + if (valueType != typeid(Integer)) + return false; + *reinterpret_cast(pInteger) = *reinterpret_cast(pInt); + return true; +} + +inline static int Compare(const word *A, const word *B, size_t N) +{ + while (N--) + if (A[N] > B[N]) + return 1; + else if (A[N] < B[N]) + return -1; + + return 0; +} + +inline static int Increment(word *A, size_t N, word B=1) +{ + assert(N); + word t = A[0]; + A[0] = t+B; + if (A[0] >= t) + return 0; + for (unsigned i=1; i>(WORD_BITS-1)); d##0 = 2*d##0 + (c>>(WORD_BITS-1)); c *= 2; + #endif + #ifndef Acc2WordsBy2 + #define Acc2WordsBy2(a, b) a##0 += b##0; a##1 += a##0 < b##0; a##1 += b##1; + #endif + #define AddWithCarry(u, a, b) {word t = a+b; u##0 = t + u##1; u##1 = (ta) + (u##0>t);} + #define GetCarry(u) u##1 + #define GetBorrow(u) u##1 +#else + #define Declare2Words(x) dword x; + #if _MSC_VER >= 1400 && !defined(__INTEL_COMPILER) + #define MultiplyWords(p, a, b) p = __emulu(a, b); + #else + #define MultiplyWords(p, a, b) p = (dword)a*b; + #endif + #define AssignWord(a, b) a = b; + #define Add2WordsBy1(a, b, c) a = b + c; + #define Acc2WordsBy2(a, b) a += b; + #define LowWord(a) word(a) + #define HighWord(a) word(a>>WORD_BITS) + #define Double3Words(c, d) d = 2*d + (c>>(WORD_BITS-1)); c *= 2; + #define AddWithCarry(u, a, b) u = dword(a) + b + GetCarry(u); + #define SubtractWithBorrow(u, a, b) u = dword(a) - b - GetBorrow(u); + #define GetCarry(u) HighWord(u) + #define GetBorrow(u) word(u>>(WORD_BITS*2-1)) +#endif +#ifndef MulAcc + #define MulAcc(c, d, a, b) MultiplyWords(p, a, b); Acc2WordsBy1(p, c); c = LowWord(p); Acc2WordsBy1(d, HighWord(p)); +#endif +#ifndef Acc2WordsBy1 + #define Acc2WordsBy1(a, b) Add2WordsBy1(a, a, b) +#endif +#ifndef Acc3WordsBy2 + #define Acc3WordsBy2(c, d, e) Acc2WordsBy1(e, c); c = LowWord(e); Add2WordsBy1(e, d, HighWord(e)); +#endif + +class DWord +{ +public: + DWord() {} + +#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + explicit DWord(word low) + { + m_whole = low; + } +#else + explicit DWord(word low) + { + m_halfs.low = low; + m_halfs.high = 0; + } +#endif + + DWord(word low, word high) + { + m_halfs.low = low; + m_halfs.high = high; + } + + static DWord Multiply(word a, word b) + { + DWord r; + #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + r.m_whole = (dword)a * b; + #elif defined(MultiplyWordsLoHi) + MultiplyWordsLoHi(r.m_halfs.low, r.m_halfs.high, a, b); + #endif + return r; + } + + static DWord MultiplyAndAdd(word a, word b, word c) + { + DWord r = Multiply(a, b); + return r += c; + } + + DWord & operator+=(word a) + { + #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + m_whole = m_whole + a; + #else + m_halfs.low += a; + m_halfs.high += (m_halfs.low < a); + #endif + return *this; + } + + DWord operator+(word a) + { + DWord r; + #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + r.m_whole = m_whole + a; + #else + r.m_halfs.low = m_halfs.low + a; + r.m_halfs.high = m_halfs.high + (r.m_halfs.low < a); + #endif + return r; + } + + DWord operator-(DWord a) + { + DWord r; + #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + r.m_whole = m_whole - a.m_whole; + #else + r.m_halfs.low = m_halfs.low - a.m_halfs.low; + r.m_halfs.high = m_halfs.high - a.m_halfs.high - (r.m_halfs.low > m_halfs.low); + #endif + return r; + } + + DWord operator-(word a) + { + DWord r; + #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + r.m_whole = m_whole - a; + #else + r.m_halfs.low = m_halfs.low - a; + r.m_halfs.high = m_halfs.high - (r.m_halfs.low > m_halfs.low); + #endif + return r; + } + + // returns quotient, which must fit in a word + word operator/(word divisor); + + word operator%(word a); + + bool operator!() const + { + #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + return !m_whole; + #else + return !m_halfs.high && !m_halfs.low; + #endif + } + + word GetLowHalf() const {return m_halfs.low;} + word GetHighHalf() const {return m_halfs.high;} + word GetHighHalfAsBorrow() const {return 0-m_halfs.high;} + +private: + union + { + #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + dword m_whole; + #endif + struct + { + #ifdef IS_LITTLE_ENDIAN + word low; + word high; + #else + word high; + word low; + #endif + } m_halfs; + }; +}; + +class Word +{ +public: + Word() {} + + Word(word value) + { + m_whole = value; + } + + Word(hword low, hword high) + { + m_whole = low | (word(high) << (WORD_BITS/2)); + } + + static Word Multiply(hword a, hword b) + { + Word r; + r.m_whole = (word)a * b; + return r; + } + + Word operator-(Word a) + { + Word r; + r.m_whole = m_whole - a.m_whole; + return r; + } + + Word operator-(hword a) + { + Word r; + r.m_whole = m_whole - a; + return r; + } + + // returns quotient, which must fit in a word + hword operator/(hword divisor) + { + return hword(m_whole / divisor); + } + + bool operator!() const + { + return !m_whole; + } + + word GetWhole() const {return m_whole;} + hword GetLowHalf() const {return hword(m_whole);} + hword GetHighHalf() const {return hword(m_whole>>(WORD_BITS/2));} + hword GetHighHalfAsBorrow() const {return 0-hword(m_whole>>(WORD_BITS/2));} + +private: + word m_whole; +}; + +// do a 3 word by 2 word divide, returns quotient and leaves remainder in A +template +S DivideThreeWordsByTwo(S *A, S B0, S B1, D *dummy=NULL) +{ + // assert {A[2],A[1]} < {B1,B0}, so quotient can fit in a S + assert(A[2] < B1 || (A[2]==B1 && A[1] < B0)); + + // estimate the quotient: do a 2 S by 1 S divide + S Q; + if (S(B1+1) == 0) + Q = A[2]; + else + Q = D(A[1], A[2]) / S(B1+1); + + // now subtract Q*B from A + D p = D::Multiply(B0, Q); + D u = (D) A[0] - p.GetLowHalf(); + A[0] = u.GetLowHalf(); + u = (D) A[1] - p.GetHighHalf() - u.GetHighHalfAsBorrow() - D::Multiply(B1, Q); + A[1] = u.GetLowHalf(); + A[2] += u.GetHighHalf(); + + // Q <= actual quotient, so fix it + while (A[2] || A[1] > B1 || (A[1]==B1 && A[0]>=B0)) + { + u = (D) A[0] - B0; + A[0] = u.GetLowHalf(); + u = (D) A[1] - B1 - u.GetHighHalfAsBorrow(); + A[1] = u.GetLowHalf(); + A[2] += u.GetHighHalf(); + Q++; + assert(Q); // shouldn't overflow + } + + return Q; +} + +// do a 4 word by 2 word divide, returns 2 word quotient in Q0 and Q1 +template +inline D DivideFourWordsByTwo(S *T, const D &Al, const D &Ah, const D &B) +{ + if (!B) // if divisor is 0, we assume divisor==2**(2*WORD_BITS) + return D(Ah.GetLowHalf(), Ah.GetHighHalf()); + else + { + S Q[2]; + T[0] = Al.GetLowHalf(); + T[1] = Al.GetHighHalf(); + T[2] = Ah.GetLowHalf(); + T[3] = Ah.GetHighHalf(); + Q[1] = DivideThreeWordsByTwo(T+1, B.GetLowHalf(), B.GetHighHalf()); + Q[0] = DivideThreeWordsByTwo(T, B.GetLowHalf(), B.GetHighHalf()); + return D(Q[0], Q[1]); + } +} + +// returns quotient, which must fit in a word +inline word DWord::operator/(word a) +{ + #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + return word(m_whole / a); + #else + hword r[4]; + return DivideFourWordsByTwo(r, m_halfs.low, m_halfs.high, a).GetWhole(); + #endif +} + +inline word DWord::operator%(word a) +{ + #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE + return word(m_whole % a); + #else + if (a < (word(1) << (WORD_BITS/2))) + { + hword h = hword(a); + word r = m_halfs.high % h; + r = ((m_halfs.low >> (WORD_BITS/2)) + (r << (WORD_BITS/2))) % h; + return hword((hword(m_halfs.low) + (r << (WORD_BITS/2))) % h); + } + else + { + hword r[4]; + DivideFourWordsByTwo(r, m_halfs.low, m_halfs.high, a); + return Word(r[0], r[1]).GetWhole(); + } + #endif +} + +// ******************************************************** + +// use some tricks to share assembly code between MSVC and GCC +#if defined(__GNUC__) + #define AddPrologue \ + int result; \ + __asm__ __volatile__ \ + ( \ + ".intel_syntax noprefix;" + #define AddEpilogue \ + ".att_syntax prefix;" \ + : "=a" (result)\ + : "d" (C), "a" (A), "D" (B), "c" (N) \ + : "%esi", "memory", "cc" \ + );\ + return result; + #define MulPrologue \ + __asm__ __volatile__ \ + ( \ + ".intel_syntax noprefix;" \ + AS1( push ebx) \ + AS2( mov ebx, edx) + #define MulEpilogue \ + AS1( pop ebx) \ + ".att_syntax prefix;" \ + : \ + : "d" (s_maskLow16), "c" (C), "a" (A), "D" (B) \ + : "%esi", "memory", "cc" \ + ); + #define SquPrologue MulPrologue + #define SquEpilogue \ + AS1( pop ebx) \ + ".att_syntax prefix;" \ + : \ + : "d" (s_maskLow16), "c" (C), "a" (A) \ + : "%esi", "%edi", "memory", "cc" \ + ); + #define TopPrologue MulPrologue + #define TopEpilogue \ + AS1( pop ebx) \ + ".att_syntax prefix;" \ + : \ + : "d" (s_maskLow16), "c" (C), "a" (A), "D" (B), "S" (L) \ + : "memory", "cc" \ + ); +#else + #define AddPrologue \ + __asm push edi \ + __asm push esi \ + __asm mov eax, [esp+12] \ + __asm mov edi, [esp+16] + #define AddEpilogue \ + __asm pop esi \ + __asm pop edi \ + __asm ret 8 +#if _MSC_VER < 1300 + #define SaveEBX __asm push ebx + #define RestoreEBX __asm pop ebx +#else + #define SaveEBX + #define RestoreEBX +#endif + #define SquPrologue \ + AS2( mov eax, A) \ + AS2( mov ecx, C) \ + SaveEBX \ + AS2( lea ebx, s_maskLow16) + #define MulPrologue \ + AS2( mov eax, A) \ + AS2( mov edi, B) \ + AS2( mov ecx, C) \ + SaveEBX \ + AS2( lea ebx, s_maskLow16) + #define TopPrologue \ + AS2( mov eax, A) \ + AS2( mov edi, B) \ + AS2( mov ecx, C) \ + AS2( mov esi, L) \ + SaveEBX \ + AS2( lea ebx, s_maskLow16) + #define SquEpilogue RestoreEBX + #define MulEpilogue RestoreEBX + #define TopEpilogue RestoreEBX +#endif + +#ifdef CRYPTOPP_X64_MASM_AVAILABLE +extern "C" { +int Baseline_Add(size_t N, word *C, const word *A, const word *B); +int Baseline_Sub(size_t N, word *C, const word *A, const word *B); +} +#elif defined(CRYPTOPP_X64_ASM_AVAILABLE) && defined(__GNUC__) && defined(CRYPTOPP_WORD128_AVAILABLE) +int Baseline_Add(size_t N, word *C, const word *A, const word *B) +{ + word result; + __asm__ __volatile__ + ( + ".intel_syntax;" + AS1( neg %1) + ASJ( jz, 1, f) + AS2( mov %0,[%3+8*%1]) + AS2( add %0,[%4+8*%1]) + AS2( mov [%2+8*%1],%0) + ASL(0) + AS2( mov %0,[%3+8*%1+8]) + AS2( adc %0,[%4+8*%1+8]) + AS2( mov [%2+8*%1+8],%0) + AS2( lea %1,[%1+2]) + ASJ( jrcxz, 1, f) + AS2( mov %0,[%3+8*%1]) + AS2( adc %0,[%4+8*%1]) + AS2( mov [%2+8*%1],%0) + ASJ( jmp, 0, b) + ASL(1) + AS2( mov %0, 0) + AS2( adc %0, %0) + ".att_syntax;" + : "=&r" (result), "+c" (N) + : "r" (C+N), "r" (A+N), "r" (B+N) + : "memory", "cc" + ); + return (int)result; +} + +int Baseline_Sub(size_t N, word *C, const word *A, const word *B) +{ + word result; + __asm__ __volatile__ + ( + ".intel_syntax;" + AS1( neg %1) + ASJ( jz, 1, f) + AS2( mov %0,[%3+8*%1]) + AS2( sub %0,[%4+8*%1]) + AS2( mov [%2+8*%1],%0) + ASL(0) + AS2( mov %0,[%3+8*%1+8]) + AS2( sbb %0,[%4+8*%1+8]) + AS2( mov [%2+8*%1+8],%0) + AS2( lea %1,[%1+2]) + ASJ( jrcxz, 1, f) + AS2( mov %0,[%3+8*%1]) + AS2( sbb %0,[%4+8*%1]) + AS2( mov [%2+8*%1],%0) + ASJ( jmp, 0, b) + ASL(1) + AS2( mov %0, 0) + AS2( adc %0, %0) + ".att_syntax;" + : "=&r" (result), "+c" (N) + : "r" (C+N), "r" (A+N), "r" (B+N) + : "memory", "cc" + ); + return (int)result; +} +#elif defined(CRYPTOPP_X86_ASM_AVAILABLE) && CRYPTOPP_BOOL_X86 +CRYPTOPP_NAKED int CRYPTOPP_FASTCALL Baseline_Add(size_t N, word *C, const word *A, const word *B) +{ + AddPrologue + + // now: eax = A, edi = B, edx = C, ecx = N + AS2( lea eax, [eax+4*ecx]) + AS2( lea edi, [edi+4*ecx]) + AS2( lea edx, [edx+4*ecx]) + + AS1( neg ecx) // ecx is negative index + AS2( test ecx, 2) // this clears carry flag + ASJ( jz, 0, f) + AS2( sub ecx, 2) + ASJ( jmp, 1, f) + + ASL(0) + ASJ( jecxz, 2, f) // loop until ecx overflows and becomes zero + AS2( mov esi,[eax+4*ecx]) + AS2( adc esi,[edi+4*ecx]) + AS2( mov [edx+4*ecx],esi) + AS2( mov esi,[eax+4*ecx+4]) + AS2( adc esi,[edi+4*ecx+4]) + AS2( mov [edx+4*ecx+4],esi) + ASL(1) + AS2( mov esi,[eax+4*ecx+8]) + AS2( adc esi,[edi+4*ecx+8]) + AS2( mov [edx+4*ecx+8],esi) + AS2( mov esi,[eax+4*ecx+12]) + AS2( adc esi,[edi+4*ecx+12]) + AS2( mov [edx+4*ecx+12],esi) + + AS2( lea ecx,[ecx+4]) // advance index, avoid inc which causes slowdown on Intel Core 2 + ASJ( jmp, 0, b) + + ASL(2) + AS2( mov eax, 0) + AS1( setc al) // store carry into eax (return result register) + + AddEpilogue +} + +CRYPTOPP_NAKED int CRYPTOPP_FASTCALL Baseline_Sub(size_t N, word *C, const word *A, const word *B) +{ + AddPrologue + + // now: eax = A, edi = B, edx = C, ecx = N + AS2( lea eax, [eax+4*ecx]) + AS2( lea edi, [edi+4*ecx]) + AS2( lea edx, [edx+4*ecx]) + + AS1( neg ecx) // ecx is negative index + AS2( test ecx, 2) // this clears carry flag + ASJ( jz, 0, f) + AS2( sub ecx, 2) + ASJ( jmp, 1, f) + + ASL(0) + ASJ( jecxz, 2, f) // loop until ecx overflows and becomes zero + AS2( mov esi,[eax+4*ecx]) + AS2( sbb esi,[edi+4*ecx]) + AS2( mov [edx+4*ecx],esi) + AS2( mov esi,[eax+4*ecx+4]) + AS2( sbb esi,[edi+4*ecx+4]) + AS2( mov [edx+4*ecx+4],esi) + ASL(1) + AS2( mov esi,[eax+4*ecx+8]) + AS2( sbb esi,[edi+4*ecx+8]) + AS2( mov [edx+4*ecx+8],esi) + AS2( mov esi,[eax+4*ecx+12]) + AS2( sbb esi,[edi+4*ecx+12]) + AS2( mov [edx+4*ecx+12],esi) + + AS2( lea ecx,[ecx+4]) // advance index, avoid inc which causes slowdown on Intel Core 2 + ASJ( jmp, 0, b) + + ASL(2) + AS2( mov eax, 0) + AS1( setc al) // store carry into eax (return result register) + + AddEpilogue +} + +#if CRYPTOPP_INTEGER_SSE2 +CRYPTOPP_NAKED int CRYPTOPP_FASTCALL SSE2_Add(size_t N, word *C, const word *A, const word *B) +{ + AddPrologue + + // now: eax = A, edi = B, edx = C, ecx = N + AS2( lea eax, [eax+4*ecx]) + AS2( lea edi, [edi+4*ecx]) + AS2( lea edx, [edx+4*ecx]) + + AS1( neg ecx) // ecx is negative index + AS2( pxor mm2, mm2) + ASJ( jz, 2, f) + AS2( test ecx, 2) // this clears carry flag + ASJ( jz, 0, f) + AS2( sub ecx, 2) + ASJ( jmp, 1, f) + + ASL(0) + AS2( movd mm0, DWORD PTR [eax+4*ecx]) + AS2( movd mm1, DWORD PTR [edi+4*ecx]) + AS2( paddq mm0, mm1) + AS2( paddq mm2, mm0) + AS2( movd DWORD PTR [edx+4*ecx], mm2) + AS2( psrlq mm2, 32) + + AS2( movd mm0, DWORD PTR [eax+4*ecx+4]) + AS2( movd mm1, DWORD PTR [edi+4*ecx+4]) + AS2( paddq mm0, mm1) + AS2( paddq mm2, mm0) + AS2( movd DWORD PTR [edx+4*ecx+4], mm2) + AS2( psrlq mm2, 32) + + ASL(1) + AS2( movd mm0, DWORD PTR [eax+4*ecx+8]) + AS2( movd mm1, DWORD PTR [edi+4*ecx+8]) + AS2( paddq mm0, mm1) + AS2( paddq mm2, mm0) + AS2( movd DWORD PTR [edx+4*ecx+8], mm2) + AS2( psrlq mm2, 32) + + AS2( movd mm0, DWORD PTR [eax+4*ecx+12]) + AS2( movd mm1, DWORD PTR [edi+4*ecx+12]) + AS2( paddq mm0, mm1) + AS2( paddq mm2, mm0) + AS2( movd DWORD PTR [edx+4*ecx+12], mm2) + AS2( psrlq mm2, 32) + + AS2( add ecx, 4) + ASJ( jnz, 0, b) + + ASL(2) + AS2( movd eax, mm2) + AS1( emms) + + AddEpilogue +} +CRYPTOPP_NAKED int CRYPTOPP_FASTCALL SSE2_Sub(size_t N, word *C, const word *A, const word *B) +{ + AddPrologue + + // now: eax = A, edi = B, edx = C, ecx = N + AS2( lea eax, [eax+4*ecx]) + AS2( lea edi, [edi+4*ecx]) + AS2( lea edx, [edx+4*ecx]) + + AS1( neg ecx) // ecx is negative index + AS2( pxor mm2, mm2) + ASJ( jz, 2, f) + AS2( test ecx, 2) // this clears carry flag + ASJ( jz, 0, f) + AS2( sub ecx, 2) + ASJ( jmp, 1, f) + + ASL(0) + AS2( movd mm0, DWORD PTR [eax+4*ecx]) + AS2( movd mm1, DWORD PTR [edi+4*ecx]) + AS2( psubq mm0, mm1) + AS2( psubq mm0, mm2) + AS2( movd DWORD PTR [edx+4*ecx], mm0) + AS2( psrlq mm0, 63) + + AS2( movd mm2, DWORD PTR [eax+4*ecx+4]) + AS2( movd mm1, DWORD PTR [edi+4*ecx+4]) + AS2( psubq mm2, mm1) + AS2( psubq mm2, mm0) + AS2( movd DWORD PTR [edx+4*ecx+4], mm2) + AS2( psrlq mm2, 63) + + ASL(1) + AS2( movd mm0, DWORD PTR [eax+4*ecx+8]) + AS2( movd mm1, DWORD PTR [edi+4*ecx+8]) + AS2( psubq mm0, mm1) + AS2( psubq mm0, mm2) + AS2( movd DWORD PTR [edx+4*ecx+8], mm0) + AS2( psrlq mm0, 63) + + AS2( movd mm2, DWORD PTR [eax+4*ecx+12]) + AS2( movd mm1, DWORD PTR [edi+4*ecx+12]) + AS2( psubq mm2, mm1) + AS2( psubq mm2, mm0) + AS2( movd DWORD PTR [edx+4*ecx+12], mm2) + AS2( psrlq mm2, 63) + + AS2( add ecx, 4) + ASJ( jnz, 0, b) + + ASL(2) + AS2( movd eax, mm2) + AS1( emms) + + AddEpilogue +} +#endif // #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE +#else +int CRYPTOPP_FASTCALL Baseline_Add(size_t N, word *C, const word *A, const word *B) +{ + assert (N%2 == 0); + + Declare2Words(u); + AssignWord(u, 0); + for (size_t i=0; i=2 && N%2==0); + + if (N <= s_recursionLimit) + s_pMul[N/4](R, A, B); + else + { + const size_t N2 = N/2; + + size_t AN2 = Compare(A0, A1, N2) > 0 ? 0 : N2; + Subtract(R0, A + AN2, A + (N2 ^ AN2), N2); + + size_t BN2 = Compare(B0, B1, N2) > 0 ? 0 : N2; + Subtract(R1, B + BN2, B + (N2 ^ BN2), N2); + + RecursiveMultiply(R2, T2, A1, B1, N2); + RecursiveMultiply(T0, T2, R0, R1, N2); + RecursiveMultiply(R0, T2, A0, B0, N2); + + // now T[01] holds (A1-A0)*(B0-B1), R[01] holds A0*B0, R[23] holds A1*B1 + + int c2 = Add(R2, R2, R1, N2); + int c3 = c2; + c2 += Add(R1, R2, R0, N2); + c3 += Add(R2, R2, R3, N2); + + if (AN2 == BN2) + c3 -= Subtract(R1, R1, T0, N); + else + c3 += Add(R1, R1, T0, N); + + c3 += Increment(R2, N2, c2); + assert (c3 >= 0 && c3 <= 2); + Increment(R3, N2, c3); + } +} + +// R[2*N] - result = A*A +// T[2*N] - temporary work space +// A[N] --- number to be squared + +void RecursiveSquare(word *R, word *T, const word *A, size_t N) +{ + assert(N && N%2==0); + + if (N <= s_recursionLimit) + s_pSqu[N/4](R, A); + else + { + const size_t N2 = N/2; + + RecursiveSquare(R0, T2, A0, N2); + RecursiveSquare(R2, T2, A1, N2); + RecursiveMultiply(T0, T2, A0, A1, N2); + + int carry = Add(R1, R1, T0, N); + carry += Add(R1, R1, T0, N); + Increment(R3, N2, carry); + } +} + +// R[N] - bottom half of A*B +// T[3*N/2] - temporary work space +// A[N] - multiplier +// B[N] - multiplicant + +void RecursiveMultiplyBottom(word *R, word *T, const word *A, const word *B, size_t N) +{ + assert(N>=2 && N%2==0); + + if (N <= s_recursionLimit) + s_pBot[N/4](R, A, B); + else + { + const size_t N2 = N/2; + + RecursiveMultiply(R, T, A0, B0, N2); + RecursiveMultiplyBottom(T0, T1, A1, B0, N2); + Add(R1, R1, T0, N2); + RecursiveMultiplyBottom(T0, T1, A0, B1, N2); + Add(R1, R1, T0, N2); + } +} + +// R[N] --- upper half of A*B +// T[2*N] - temporary work space +// L[N] --- lower half of A*B +// A[N] --- multiplier +// B[N] --- multiplicant + +void MultiplyTop(word *R, word *T, const word *L, const word *A, const word *B, size_t N) +{ + assert(N>=2 && N%2==0); + + if (N <= s_recursionLimit) + s_pTop[N/4](R, A, B, L[N-1]); + else + { + const size_t N2 = N/2; + + size_t AN2 = Compare(A0, A1, N2) > 0 ? 0 : N2; + Subtract(R0, A + AN2, A + (N2 ^ AN2), N2); + + size_t BN2 = Compare(B0, B1, N2) > 0 ? 0 : N2; + Subtract(R1, B + BN2, B + (N2 ^ BN2), N2); + + RecursiveMultiply(T0, T2, R0, R1, N2); + RecursiveMultiply(R0, T2, A1, B1, N2); + + // now T[01] holds (A1-A0)*(B0-B1) = A1*B0+A0*B1-A1*B1-A0*B0, R[01] holds A1*B1 + + int t, c3; + int c2 = Subtract(T2, L+N2, L, N2); + + if (AN2 == BN2) + { + c2 -= Add(T2, T2, T0, N2); + t = (Compare(T2, R0, N2) == -1); + c3 = t - Subtract(T2, T2, T1, N2); + } + else + { + c2 += Subtract(T2, T2, T0, N2); + t = (Compare(T2, R0, N2) == -1); + c3 = t + Add(T2, T2, T1, N2); + } + + c2 += t; + if (c2 >= 0) + c3 += Increment(T2, N2, c2); + else + c3 -= Decrement(T2, N2, -c2); + c3 += Add(R0, T2, R1, N2); + + assert (c3 >= 0 && c3 <= 2); + Increment(R1, N2, c3); + } +} + +inline void Multiply(word *R, word *T, const word *A, const word *B, size_t N) +{ + RecursiveMultiply(R, T, A, B, N); +} + +inline void Square(word *R, word *T, const word *A, size_t N) +{ + RecursiveSquare(R, T, A, N); +} + +inline void MultiplyBottom(word *R, word *T, const word *A, const word *B, size_t N) +{ + RecursiveMultiplyBottom(R, T, A, B, N); +} + +// R[NA+NB] - result = A*B +// T[NA+NB] - temporary work space +// A[NA] ---- multiplier +// B[NB] ---- multiplicant + +void AsymmetricMultiply(word *R, word *T, const word *A, size_t NA, const word *B, size_t NB) +{ + if (NA == NB) + { + if (A == B) + Square(R, T, A, NA); + else + Multiply(R, T, A, B, NA); + + return; + } + + if (NA > NB) + { + std::swap(A, B); + std::swap(NA, NB); + } + + assert(NB % NA == 0); + + if (NA==2 && !A[1]) + { + switch (A[0]) + { + case 0: + SetWords(R, 0, NB+2); + return; + case 1: + CopyWords(R, B, NB); + R[NB] = R[NB+1] = 0; + return; + default: + R[NB] = LinearMultiply(R, B, A[0], NB); + R[NB+1] = 0; + return; + } + } + + size_t i; + if ((NB/NA)%2 == 0) + { + Multiply(R, T, A, B, NA); + CopyWords(T+2*NA, R+NA, NA); + + for (i=2*NA; i=4); + +#define M0 M +#define M1 (M+N2) +#define V0 V +#define V1 (V+N2) + +#define X0 X +#define X1 (X+N2) +#define X2 (X+N) +#define X3 (X+N+N2) + + const size_t N2 = N/2; + Multiply(T0, T2, V0, X3, N2); + int c2 = Add(T0, T0, X0, N); + MultiplyBottom(T3, T2, T0, U, N2); + MultiplyTop(T2, R, T0, T3, M0, N2); + c2 -= Subtract(T2, T1, T2, N2); + Multiply(T0, R, T3, M1, N2); + c2 -= Subtract(T0, T2, T0, N2); + int c3 = -(int)Subtract(T1, X2, T1, N2); + Multiply(R0, T2, V1, X3, N2); + c3 += Add(R, R, T, N); + + if (c2>0) + c3 += Increment(R1, N2); + else if (c2<0) + c3 -= Decrement(R1, N2, -c2); + + assert(c3>=-1 && c3<=1); + if (c3>0) + Subtract(R, R, M, N); + else if (c3<0) + Add(R, R, M, N); + +#undef M0 +#undef M1 +#undef V0 +#undef V1 + +#undef X0 +#undef X1 +#undef X2 +#undef X3 +} + +#undef A0 +#undef A1 +#undef B0 +#undef B1 + +#undef T0 +#undef T1 +#undef T2 +#undef T3 + +#undef R0 +#undef R1 +#undef R2 +#undef R3 + +/* +// do a 3 word by 2 word divide, returns quotient and leaves remainder in A +static word SubatomicDivide(word *A, word B0, word B1) +{ + // assert {A[2],A[1]} < {B1,B0}, so quotient can fit in a word + assert(A[2] < B1 || (A[2]==B1 && A[1] < B0)); + + // estimate the quotient: do a 2 word by 1 word divide + word Q; + if (B1+1 == 0) + Q = A[2]; + else + Q = DWord(A[1], A[2]).DividedBy(B1+1); + + // now subtract Q*B from A + DWord p = DWord::Multiply(B0, Q); + DWord u = (DWord) A[0] - p.GetLowHalf(); + A[0] = u.GetLowHalf(); + u = (DWord) A[1] - p.GetHighHalf() - u.GetHighHalfAsBorrow() - DWord::Multiply(B1, Q); + A[1] = u.GetLowHalf(); + A[2] += u.GetHighHalf(); + + // Q <= actual quotient, so fix it + while (A[2] || A[1] > B1 || (A[1]==B1 && A[0]>=B0)) + { + u = (DWord) A[0] - B0; + A[0] = u.GetLowHalf(); + u = (DWord) A[1] - B1 - u.GetHighHalfAsBorrow(); + A[1] = u.GetLowHalf(); + A[2] += u.GetHighHalf(); + Q++; + assert(Q); // shouldn't overflow + } + + return Q; +} + +// do a 4 word by 2 word divide, returns 2 word quotient in Q0 and Q1 +static inline void AtomicDivide(word *Q, const word *A, const word *B) +{ + if (!B[0] && !B[1]) // if divisor is 0, we assume divisor==2**(2*WORD_BITS) + { + Q[0] = A[2]; + Q[1] = A[3]; + } + else + { + word T[4]; + T[0] = A[0]; T[1] = A[1]; T[2] = A[2]; T[3] = A[3]; + Q[1] = SubatomicDivide(T+1, B[0], B[1]); + Q[0] = SubatomicDivide(T, B[0], B[1]); + +#ifndef NDEBUG + // multiply quotient and divisor and add remainder, make sure it equals dividend + assert(!T[2] && !T[3] && (T[1] < B[1] || (T[1]==B[1] && T[0](T, DWord(A[0], A[1]), DWord(A[2], A[3]), DWord(B[0], B[1])); + Q[0] = q.GetLowHalf(); + Q[1] = q.GetHighHalf(); + +#ifndef NDEBUG + if (B[0] || B[1]) + { + // multiply quotient and divisor and add remainder, make sure it equals dividend + assert(!T[2] && !T[3] && (T[1] < B[1] || (T[1]==B[1] && T[0]= 0) + { + R[N] -= Subtract(R, R, B, N); + Q[1] += (++Q[0]==0); + assert(Q[0] || Q[1]); // no overflow + } +} + +// R[NB] -------- remainder = A%B +// Q[NA-NB+2] --- quotient = A/B +// T[NA+3*(NB+2)] - temp work space +// A[NA] -------- dividend +// B[NB] -------- divisor + +void Divide(word *R, word *Q, word *T, const word *A, size_t NA, const word *B, size_t NB) +{ + assert(NA && NB && NA%2==0 && NB%2==0); + assert(B[NB-1] || B[NB-2]); + assert(NB <= NA); + + // set up temporary work space + word *const TA=T; + word *const TB=T+NA+2; + word *const TP=T+NA+2+NB; + + // copy B into TB and normalize it so that TB has highest bit set to 1 + unsigned shiftWords = (B[NB-1]==0); + TB[0] = TB[NB-1] = 0; + CopyWords(TB+shiftWords, B, NB-shiftWords); + unsigned shiftBits = WORD_BITS - BitPrecision(TB[NB-1]); + assert(shiftBits < WORD_BITS); + ShiftWordsLeftByBits(TB, NB, shiftBits); + + // copy A into TA and normalize it + TA[0] = TA[NA] = TA[NA+1] = 0; + CopyWords(TA+shiftWords, A, NA); + ShiftWordsLeftByBits(TA, NA+2, shiftBits); + + if (TA[NA+1]==0 && TA[NA] <= 1) + { + Q[NA-NB+1] = Q[NA-NB] = 0; + while (TA[NA] || Compare(TA+NA-NB, TB, NB) >= 0) + { + TA[NA] -= Subtract(TA+NA-NB, TA+NA-NB, TB, NB); + ++Q[NA-NB]; + } + } + else + { + NA+=2; + assert(Compare(TA+NA-NB, TB, NB) < 0); + } + + word BT[2]; + BT[0] = TB[NB-2] + 1; + BT[1] = TB[NB-1] + (BT[0]==0); + + // start reducing TA mod TB, 2 words at a time + for (size_t i=NA-2; i>=NB; i-=2) + { + AtomicDivide(Q+i-NB, TA+i-2, BT); + CorrectQuotientEstimate(TA+i-NB, TP, Q+i-NB, TB, NB); + } + + // copy TA into R, and denormalize it + CopyWords(R, TA+shiftWords, NB); + ShiftWordsRightByBits(R, NB, shiftBits); +} + +static inline size_t EvenWordCount(const word *X, size_t N) +{ + while (N && X[N-2]==0 && X[N-1]==0) + N-=2; + return N; +} + +// return k +// R[N] --- result = A^(-1) * 2^k mod M +// T[4*N] - temporary work space +// A[NA] -- number to take inverse of +// M[N] --- modulus + +unsigned int AlmostInverse(word *R, word *T, const word *A, size_t NA, const word *M, size_t N) +{ + assert(NA<=N && N && N%2==0); + + word *b = T; + word *c = T+N; + word *f = T+2*N; + word *g = T+3*N; + size_t bcLen=2, fgLen=EvenWordCount(M, N); + unsigned int k=0, s=0; + + SetWords(T, 0, 3*N); + b[0]=1; + CopyWords(f, A, NA); + CopyWords(g, M, N); + + while (1) + { + word t=f[0]; + while (!t) + { + if (EvenWordCount(f, fgLen)==0) + { + SetWords(R, 0, N); + return 0; + } + + ShiftWordsRightByWords(f, fgLen, 1); + if (c[bcLen-1]) bcLen+=2; + assert(bcLen <= N); + ShiftWordsLeftByWords(c, bcLen, 1); + k+=WORD_BITS; + t=f[0]; + } + + unsigned int i=0; + while (t%2 == 0) + { + t>>=1; + i++; + } + k+=i; + + if (t==1 && f[1]==0 && EvenWordCount(f, fgLen)==2) + { + if (s%2==0) + CopyWords(R, b, N); + else + Subtract(R, M, b, N); + return k; + } + + ShiftWordsRightByBits(f, fgLen, i); + t=ShiftWordsLeftByBits(c, bcLen, i); + if (t) + { + c[bcLen] = t; + bcLen+=2; + assert(bcLen <= N); + } + + if (f[fgLen-2]==0 && g[fgLen-2]==0 && f[fgLen-1]==0 && g[fgLen-1]==0) + fgLen-=2; + + if (Compare(f, g, fgLen)==-1) + { + std::swap(f, g); + std::swap(b, c); + s++; + } + + Subtract(f, f, g, fgLen); + + if (Add(b, b, c, bcLen)) + { + b[bcLen] = 1; + bcLen+=2; + assert(bcLen <= N); + } + } +} + +// R[N] - result = A/(2^k) mod M +// A[N] - input +// M[N] - modulus + +void DivideByPower2Mod(word *R, const word *A, size_t k, const word *M, size_t N) +{ + CopyWords(R, A, N); + + while (k--) + { + if (R[0]%2==0) + ShiftWordsRightByBits(R, N, 1); + else + { + word carry = Add(R, R, M, N); + ShiftWordsRightByBits(R, N, 1); + R[N-1] += carry<<(WORD_BITS-1); + } + } +} + +// R[N] - result = A*(2^k) mod M +// A[N] - input +// M[N] - modulus + +void MultiplyByPower2Mod(word *R, const word *A, size_t k, const word *M, size_t N) +{ + CopyWords(R, A, N); + + while (k--) + if (ShiftWordsLeftByBits(R, N, 1) || Compare(R, M, N)>=0) + Subtract(R, R, M, N); +} + +// ****************************************************************** + +InitializeInteger::InitializeInteger() +{ + if (!g_pAssignIntToInteger) + { + SetFunctionPointers(); + g_pAssignIntToInteger = AssignIntToInteger; + } +} + +static const unsigned int RoundupSizeTable[] = {2, 2, 2, 4, 4, 8, 8, 8, 8}; + +static inline size_t RoundupSize(size_t n) +{ + if (n<=8) + return RoundupSizeTable[n]; + else if (n<=16) + return 16; + else if (n<=32) + return 32; + else if (n<=64) + return 64; + else return size_t(1) << BitPrecision(n-1); +} + +Integer::Integer() + : reg(2), sign(POSITIVE) +{ + reg[0] = reg[1] = 0; +} + +Integer::Integer(const Integer& t) + : reg(RoundupSize(t.WordCount())), sign(t.sign) +{ + CopyWords(reg, t.reg, reg.size()); +} + +Integer::Integer(Sign s, lword value) + : reg(2), sign(s) +{ + reg[0] = word(value); + reg[1] = word(SafeRightShift(value)); +} + +Integer::Integer(signed long value) + : reg(2) +{ + if (value >= 0) + sign = POSITIVE; + else + { + sign = NEGATIVE; + value = -value; + } + reg[0] = word(value); + reg[1] = word(SafeRightShift((unsigned long)value)); +} + +Integer::Integer(Sign s, word high, word low) + : reg(2), sign(s) +{ + reg[0] = low; + reg[1] = high; +} + +bool Integer::IsConvertableToLong() const +{ + if (ByteCount() > sizeof(long)) + return false; + + unsigned long value = (unsigned long)reg[0]; + value += SafeLeftShift((unsigned long)reg[1]); + + if (sign==POSITIVE) + return (signed long)value >= 0; + else + return -(signed long)value < 0; +} + +signed long Integer::ConvertToLong() const +{ + assert(IsConvertableToLong()); + + unsigned long value = (unsigned long)reg[0]; + value += SafeLeftShift((unsigned long)reg[1]); + return sign==POSITIVE ? value : -(signed long)value; +} + +Integer::Integer(BufferedTransformation &encodedInteger, size_t byteCount, Signedness s) +{ + Decode(encodedInteger, byteCount, s); +} + +Integer::Integer(const byte *encodedInteger, size_t byteCount, Signedness s) +{ + Decode(encodedInteger, byteCount, s); +} + +Integer::Integer(BufferedTransformation &bt) +{ + BERDecode(bt); +} + +Integer::Integer(RandomNumberGenerator &rng, size_t bitcount) +{ + Randomize(rng, bitcount); +} + +Integer::Integer(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType, const Integer &equiv, const Integer &mod) +{ + if (!Randomize(rng, min, max, rnType, equiv, mod)) + throw Integer::RandomNumberNotFound(); +} + +Integer Integer::Power2(size_t e) +{ + Integer r((word)0, BitsToWords(e+1)); + r.SetBit(e); + return r; +} + +template +struct NewInteger +{ + Integer * operator()() const + { + return new Integer(i); + } +}; + +const Integer &Integer::Zero() +{ + return Singleton().Ref(); +} + +const Integer &Integer::One() +{ + return Singleton >().Ref(); +} + +const Integer &Integer::Two() +{ + return Singleton >().Ref(); +} + +bool Integer::operator!() const +{ + return IsNegative() ? false : (reg[0]==0 && WordCount()==0); +} + +Integer& Integer::operator=(const Integer& t) +{ + if (this != &t) + { + if (reg.size() != t.reg.size() || t.reg[t.reg.size()/2] == 0) + reg.New(RoundupSize(t.WordCount())); + CopyWords(reg, t.reg, reg.size()); + sign = t.sign; + } + return *this; +} + +bool Integer::GetBit(size_t n) const +{ + if (n/WORD_BITS >= reg.size()) + return 0; + else + return bool((reg[n/WORD_BITS] >> (n % WORD_BITS)) & 1); +} + +void Integer::SetBit(size_t n, bool value) +{ + if (value) + { + reg.CleanGrow(RoundupSize(BitsToWords(n+1))); + reg[n/WORD_BITS] |= (word(1) << (n%WORD_BITS)); + } + else + { + if (n/WORD_BITS < reg.size()) + reg[n/WORD_BITS] &= ~(word(1) << (n%WORD_BITS)); + } +} + +byte Integer::GetByte(size_t n) const +{ + if (n/WORD_SIZE >= reg.size()) + return 0; + else + return byte(reg[n/WORD_SIZE] >> ((n%WORD_SIZE)*8)); +} + +void Integer::SetByte(size_t n, byte value) +{ + reg.CleanGrow(RoundupSize(BytesToWords(n+1))); + reg[n/WORD_SIZE] &= ~(word(0xff) << 8*(n%WORD_SIZE)); + reg[n/WORD_SIZE] |= (word(value) << 8*(n%WORD_SIZE)); +} + +lword Integer::GetBits(size_t i, size_t n) const +{ + lword v = 0; + assert(n <= sizeof(v)*8); + for (unsigned int j=0; j +static Integer StringToInteger(const T *str) +{ + int radix; + // GCC workaround + // std::char_traits::length() not defined in GCC 3.2 and STLport 4.5.3 + unsigned int length; + for (length = 0; str[length] != 0; length++) {} + + Integer v; + + if (length == 0) + return v; + + switch (str[length-1]) + { + case 'h': + case 'H': + radix=16; + break; + case 'o': + case 'O': + radix=8; + break; + case 'b': + case 'B': + radix=2; + break; + default: + radix=10; + } + + if (length > 2 && str[0] == '0' && str[1] == 'x') + radix = 16; + + for (unsigned i=0; i= '0' && str[i] <= '9') + digit = str[i] - '0'; + else if (str[i] >= 'A' && str[i] <= 'F') + digit = str[i] - 'A' + 10; + else if (str[i] >= 'a' && str[i] <= 'f') + digit = str[i] - 'a' + 10; + else + digit = radix; + + if (digit < radix) + { + v *= radix; + v += digit; + } + } + + if (str[0] == '-') + v.Negate(); + + return v; +} + +Integer::Integer(const char *str) + : reg(2), sign(POSITIVE) +{ + *this = StringToInteger(str); +} + +Integer::Integer(const wchar_t *str) + : reg(2), sign(POSITIVE) +{ + *this = StringToInteger(str); +} + +unsigned int Integer::WordCount() const +{ + return (unsigned int)CountWords(reg, reg.size()); +} + +unsigned int Integer::ByteCount() const +{ + unsigned wordCount = WordCount(); + if (wordCount) + return (wordCount-1)*WORD_SIZE + BytePrecision(reg[wordCount-1]); + else + return 0; +} + +unsigned int Integer::BitCount() const +{ + unsigned wordCount = WordCount(); + if (wordCount) + return (wordCount-1)*WORD_BITS + BitPrecision(reg[wordCount-1]); + else + return 0; +} + +void Integer::Decode(const byte *input, size_t inputLen, Signedness s) +{ + StringStore store(input, inputLen); + Decode(store, inputLen, s); +} + +void Integer::Decode(BufferedTransformation &bt, size_t inputLen, Signedness s) +{ + assert(bt.MaxRetrievable() >= inputLen); + + byte b; + bt.Peek(b); + sign = ((s==SIGNED) && (b & 0x80)) ? NEGATIVE : POSITIVE; + + while (inputLen>0 && (sign==POSITIVE ? b==0 : b==0xff)) + { + bt.Skip(1); + inputLen--; + bt.Peek(b); + } + + reg.CleanNew(RoundupSize(BytesToWords(inputLen))); + + for (size_t i=inputLen; i > 0; i--) + { + bt.Get(b); + reg[(i-1)/WORD_SIZE] |= word(b) << ((i-1)%WORD_SIZE)*8; + } + + if (sign == NEGATIVE) + { + for (size_t i=inputLen; i 0; i--) + bt.Put(GetByte(i-1)); + } + else + { + // take two's complement of *this + Integer temp = Integer::Power2(8*STDMAX((size_t)ByteCount(), outputLen)) + *this; + temp.Encode(bt, outputLen, UNSIGNED); + } +} + +void Integer::DEREncode(BufferedTransformation &bt) const +{ + DERGeneralEncoder enc(bt, INTEGER); + Encode(enc, MinEncodedSize(SIGNED), SIGNED); + enc.MessageEnd(); +} + +void Integer::BERDecode(const byte *input, size_t len) +{ + StringStore store(input, len); + BERDecode(store); +} + +void Integer::BERDecode(BufferedTransformation &bt) +{ + BERGeneralDecoder dec(bt, INTEGER); + if (!dec.IsDefiniteLength() || dec.MaxRetrievable() < dec.RemainingLength()) + BERDecodeError(); + Decode(dec, (size_t)dec.RemainingLength(), SIGNED); + dec.MessageEnd(); +} + +void Integer::DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const +{ + DERGeneralEncoder enc(bt, OCTET_STRING); + Encode(enc, length); + enc.MessageEnd(); +} + +void Integer::BERDecodeAsOctetString(BufferedTransformation &bt, size_t length) +{ + BERGeneralDecoder dec(bt, OCTET_STRING); + if (!dec.IsDefiniteLength() || dec.RemainingLength() != length) + BERDecodeError(); + Decode(dec, length); + dec.MessageEnd(); +} + +size_t Integer::OpenPGPEncode(byte *output, size_t len) const +{ + ArraySink sink(output, len); + return OpenPGPEncode(sink); +} + +size_t Integer::OpenPGPEncode(BufferedTransformation &bt) const +{ + word16 bitCount = BitCount(); + bt.PutWord16(bitCount); + size_t byteCount = BitsToBytes(bitCount); + Encode(bt, byteCount); + return 2 + byteCount; +} + +void Integer::OpenPGPDecode(const byte *input, size_t len) +{ + StringStore store(input, len); + OpenPGPDecode(store); +} + +void Integer::OpenPGPDecode(BufferedTransformation &bt) +{ + word16 bitCount; + if (bt.GetWord16(bitCount) != 2 || bt.MaxRetrievable() < BitsToBytes(bitCount)) + throw OpenPGPDecodeErr(); + Decode(bt, BitsToBytes(bitCount)); +} + +void Integer::Randomize(RandomNumberGenerator &rng, size_t nbits) +{ + const size_t nbytes = nbits/8 + 1; + SecByteBlock buf(nbytes); + rng.GenerateBlock(buf, nbytes); + if (nbytes) + buf[0] = (byte)Crop(buf[0], nbits % 8); + Decode(buf, nbytes, UNSIGNED); +} + +void Integer::Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max) +{ + if (min > max) + throw InvalidArgument("Integer: Min must be no greater than Max"); + + Integer range = max - min; + const unsigned int nbits = range.BitCount(); + + do + { + Randomize(rng, nbits); + } + while (*this > range); + + *this += min; +} + +bool Integer::Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType, const Integer &equiv, const Integer &mod) +{ + return GenerateRandomNoThrow(rng, MakeParameters("Min", min)("Max", max)("RandomNumberType", rnType)("EquivalentTo", equiv)("Mod", mod)); +} + +class KDF2_RNG : public RandomNumberGenerator +{ +public: + KDF2_RNG(const byte *seed, size_t seedSize) + : m_counter(0), m_counterAndSeed(seedSize + 4) + { + memcpy(m_counterAndSeed + 4, seed, seedSize); + } + + void GenerateBlock(byte *output, size_t size) + { + PutWord(false, BIG_ENDIAN_ORDER, m_counterAndSeed, m_counter); + ++m_counter; + P1363_KDF2::DeriveKey(output, size, m_counterAndSeed, m_counterAndSeed.size(), NULL, 0); + } + +private: + word32 m_counter; + SecByteBlock m_counterAndSeed; +}; + +bool Integer::GenerateRandomNoThrow(RandomNumberGenerator &i_rng, const NameValuePairs ¶ms) +{ + Integer min = params.GetValueWithDefault("Min", Integer::Zero()); + Integer max; + if (!params.GetValue("Max", max)) + { + int bitLength; + if (params.GetIntValue("BitLength", bitLength)) + max = Integer::Power2(bitLength); + else + throw InvalidArgument("Integer: missing Max argument"); + } + if (min > max) + throw InvalidArgument("Integer: Min must be no greater than Max"); + + Integer equiv = params.GetValueWithDefault("EquivalentTo", Integer::Zero()); + Integer mod = params.GetValueWithDefault("Mod", Integer::One()); + + if (equiv.IsNegative() || equiv >= mod) + throw InvalidArgument("Integer: invalid EquivalentTo and/or Mod argument"); + + Integer::RandomNumberType rnType = params.GetValueWithDefault("RandomNumberType", Integer::ANY); + + member_ptr kdf2Rng; + ConstByteArrayParameter seed; + if (params.GetValue(Name::Seed(), seed)) + { + ByteQueue bq; + DERSequenceEncoder seq(bq); + min.DEREncode(seq); + max.DEREncode(seq); + equiv.DEREncode(seq); + mod.DEREncode(seq); + DEREncodeUnsigned(seq, rnType); + DEREncodeOctetString(seq, seed.begin(), seed.size()); + seq.MessageEnd(); + + SecByteBlock finalSeed((size_t)bq.MaxRetrievable()); + bq.Get(finalSeed, finalSeed.size()); + kdf2Rng.reset(new KDF2_RNG(finalSeed.begin(), finalSeed.size())); + } + RandomNumberGenerator &rng = kdf2Rng.get() ? (RandomNumberGenerator &)*kdf2Rng : i_rng; + + switch (rnType) + { + case ANY: + if (mod == One()) + Randomize(rng, min, max); + else + { + Integer min1 = min + (equiv-min)%mod; + if (max < min1) + return false; + Randomize(rng, Zero(), (max - min1) / mod); + *this *= mod; + *this += min1; + } + return true; + + case PRIME: + { + const PrimeSelector *pSelector = params.GetValueWithDefault(Name::PointerToPrimeSelector(), (const PrimeSelector *)NULL); + + int i; + i = 0; + while (1) + { + if (++i==16) + { + // check if there are any suitable primes in [min, max] + Integer first = min; + if (FirstPrime(first, max, equiv, mod, pSelector)) + { + // if there is only one suitable prime, we're done + *this = first; + if (!FirstPrime(first, max, equiv, mod, pSelector)) + return true; + } + else + return false; + } + + Randomize(rng, min, max); + if (FirstPrime(*this, STDMIN(*this+mod*PrimeSearchInterval(max), max), equiv, mod, pSelector)) + return true; + } + } + + default: + throw InvalidArgument("Integer: invalid RandomNumberType argument"); + } +} + +std::istream& operator>>(std::istream& in, Integer &a) +{ + char c; + unsigned int length = 0; + SecBlock str(length + 16); + + std::ws(in); + + do + { + in.read(&c, 1); + str[length++] = c; + if (length >= str.size()) + str.Grow(length + 16); + } + while (in && (c=='-' || c=='x' || (c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F') || c=='h' || c=='H' || c=='o' || c=='O' || c==',' || c=='.')); + + if (in.gcount()) + in.putback(c); + str[length-1] = '\0'; + a = Integer(str); + + return in; +} + +std::ostream& operator<<(std::ostream& out, const Integer &a) +{ + // Get relevant conversion specifications from ostream. + long f = out.flags() & std::ios::basefield; // Get base digits. + int base, block; + char suffix; + switch(f) + { + case std::ios::oct : + base = 8; + block = 8; + suffix = 'o'; + break; + case std::ios::hex : + base = 16; + block = 4; + suffix = 'h'; + break; + default : + base = 10; + block = 3; + suffix = '.'; + } + + Integer temp1=a, temp2; + + if (a.IsNegative()) + { + out << '-'; + temp1.Negate(); + } + + if (!a) + out << '0'; + + static const char upper[]="0123456789ABCDEF"; + static const char lower[]="0123456789abcdef"; + + const char* vec = (out.flags() & std::ios::uppercase) ? upper : lower; + unsigned i=0; + SecBlock s(a.BitCount() / (BitPrecision(base)-1) + 1); + + while (!!temp1) + { + word digit; + Integer::Divide(digit, temp2, temp1, base); + s[i++]=vec[digit]; + temp1.swap(temp2); + } + + while (i--) + { + out << s[i]; +// if (i && !(i%block)) +// out << ","; + } + return out << suffix; +} + +Integer& Integer::operator++() +{ + if (NotNegative()) + { + if (Increment(reg, reg.size())) + { + reg.CleanGrow(2*reg.size()); + reg[reg.size()/2]=1; + } + } + else + { + word borrow = Decrement(reg, reg.size()); + assert(!borrow); + if (WordCount()==0) + *this = Zero(); + } + return *this; +} + +Integer& Integer::operator--() +{ + if (IsNegative()) + { + if (Increment(reg, reg.size())) + { + reg.CleanGrow(2*reg.size()); + reg[reg.size()/2]=1; + } + } + else + { + if (Decrement(reg, reg.size())) + *this = -One(); + } + return *this; +} + +void PositiveAdd(Integer &sum, const Integer &a, const Integer& b) +{ + int carry; + if (a.reg.size() == b.reg.size()) + carry = Add(sum.reg, a.reg, b.reg, a.reg.size()); + else if (a.reg.size() > b.reg.size()) + { + carry = Add(sum.reg, a.reg, b.reg, b.reg.size()); + CopyWords(sum.reg+b.reg.size(), a.reg+b.reg.size(), a.reg.size()-b.reg.size()); + carry = Increment(sum.reg+b.reg.size(), a.reg.size()-b.reg.size(), carry); + } + else + { + carry = Add(sum.reg, a.reg, b.reg, a.reg.size()); + CopyWords(sum.reg+a.reg.size(), b.reg+a.reg.size(), b.reg.size()-a.reg.size()); + carry = Increment(sum.reg+a.reg.size(), b.reg.size()-a.reg.size(), carry); + } + + if (carry) + { + sum.reg.CleanGrow(2*sum.reg.size()); + sum.reg[sum.reg.size()/2] = 1; + } + sum.sign = Integer::POSITIVE; +} + +void PositiveSubtract(Integer &diff, const Integer &a, const Integer& b) +{ + unsigned aSize = a.WordCount(); + aSize += aSize%2; + unsigned bSize = b.WordCount(); + bSize += bSize%2; + + if (aSize == bSize) + { + if (Compare(a.reg, b.reg, aSize) >= 0) + { + Subtract(diff.reg, a.reg, b.reg, aSize); + diff.sign = Integer::POSITIVE; + } + else + { + Subtract(diff.reg, b.reg, a.reg, aSize); + diff.sign = Integer::NEGATIVE; + } + } + else if (aSize > bSize) + { + word borrow = Subtract(diff.reg, a.reg, b.reg, bSize); + CopyWords(diff.reg+bSize, a.reg+bSize, aSize-bSize); + borrow = Decrement(diff.reg+bSize, aSize-bSize, borrow); + assert(!borrow); + diff.sign = Integer::POSITIVE; + } + else + { + word borrow = Subtract(diff.reg, b.reg, a.reg, aSize); + CopyWords(diff.reg+aSize, b.reg+aSize, bSize-aSize); + borrow = Decrement(diff.reg+aSize, bSize-aSize, borrow); + assert(!borrow); + diff.sign = Integer::NEGATIVE; + } +} + +// MSVC .NET 2003 workaround +template inline const T& STDMAX2(const T& a, const T& b) +{ + return a < b ? b : a; +} + +Integer Integer::Plus(const Integer& b) const +{ + Integer sum((word)0, STDMAX2(reg.size(), b.reg.size())); + if (NotNegative()) + { + if (b.NotNegative()) + PositiveAdd(sum, *this, b); + else + PositiveSubtract(sum, *this, b); + } + else + { + if (b.NotNegative()) + PositiveSubtract(sum, b, *this); + else + { + PositiveAdd(sum, *this, b); + sum.sign = Integer::NEGATIVE; + } + } + return sum; +} + +Integer& Integer::operator+=(const Integer& t) +{ + reg.CleanGrow(t.reg.size()); + if (NotNegative()) + { + if (t.NotNegative()) + PositiveAdd(*this, *this, t); + else + PositiveSubtract(*this, *this, t); + } + else + { + if (t.NotNegative()) + PositiveSubtract(*this, t, *this); + else + { + PositiveAdd(*this, *this, t); + sign = Integer::NEGATIVE; + } + } + return *this; +} + +Integer Integer::Minus(const Integer& b) const +{ + Integer diff((word)0, STDMAX2(reg.size(), b.reg.size())); + if (NotNegative()) + { + if (b.NotNegative()) + PositiveSubtract(diff, *this, b); + else + PositiveAdd(diff, *this, b); + } + else + { + if (b.NotNegative()) + { + PositiveAdd(diff, *this, b); + diff.sign = Integer::NEGATIVE; + } + else + PositiveSubtract(diff, b, *this); + } + return diff; +} + +Integer& Integer::operator-=(const Integer& t) +{ + reg.CleanGrow(t.reg.size()); + if (NotNegative()) + { + if (t.NotNegative()) + PositiveSubtract(*this, *this, t); + else + PositiveAdd(*this, *this, t); + } + else + { + if (t.NotNegative()) + { + PositiveAdd(*this, *this, t); + sign = Integer::NEGATIVE; + } + else + PositiveSubtract(*this, t, *this); + } + return *this; +} + +Integer& Integer::operator<<=(size_t n) +{ + const size_t wordCount = WordCount(); + const size_t shiftWords = n / WORD_BITS; + const unsigned int shiftBits = (unsigned int)(n % WORD_BITS); + + reg.CleanGrow(RoundupSize(wordCount+BitsToWords(n))); + ShiftWordsLeftByWords(reg, wordCount + shiftWords, shiftWords); + ShiftWordsLeftByBits(reg+shiftWords, wordCount+BitsToWords(shiftBits), shiftBits); + return *this; +} + +Integer& Integer::operator>>=(size_t n) +{ + const size_t wordCount = WordCount(); + const size_t shiftWords = n / WORD_BITS; + const unsigned int shiftBits = (unsigned int)(n % WORD_BITS); + + ShiftWordsRightByWords(reg, wordCount, shiftWords); + if (wordCount > shiftWords) + ShiftWordsRightByBits(reg, wordCount-shiftWords, shiftBits); + if (IsNegative() && WordCount()==0) // avoid -0 + *this = Zero(); + return *this; +} + +void PositiveMultiply(Integer &product, const Integer &a, const Integer &b) +{ + size_t aSize = RoundupSize(a.WordCount()); + size_t bSize = RoundupSize(b.WordCount()); + + product.reg.CleanNew(RoundupSize(aSize+bSize)); + product.sign = Integer::POSITIVE; + + IntegerSecBlock workspace(aSize + bSize); + AsymmetricMultiply(product.reg, workspace, a.reg, aSize, b.reg, bSize); +} + +void Multiply(Integer &product, const Integer &a, const Integer &b) +{ + PositiveMultiply(product, a, b); + + if (a.NotNegative() != b.NotNegative()) + product.Negate(); +} + +Integer Integer::Times(const Integer &b) const +{ + Integer product; + Multiply(product, *this, b); + return product; +} + +/* +void PositiveDivide(Integer &remainder, Integer "ient, + const Integer ÷nd, const Integer &divisor) +{ + remainder.reg.CleanNew(divisor.reg.size()); + remainder.sign = Integer::POSITIVE; + quotient.reg.New(0); + quotient.sign = Integer::POSITIVE; + unsigned i=dividend.BitCount(); + while (i--) + { + word overflow = ShiftWordsLeftByBits(remainder.reg, remainder.reg.size(), 1); + remainder.reg[0] |= dividend[i]; + if (overflow || remainder >= divisor) + { + Subtract(remainder.reg, remainder.reg, divisor.reg, remainder.reg.size()); + quotient.SetBit(i); + } + } +} +*/ + +void PositiveDivide(Integer &remainder, Integer "ient, + const Integer &a, const Integer &b) +{ + unsigned aSize = a.WordCount(); + unsigned bSize = b.WordCount(); + + if (!bSize) + throw Integer::DivideByZero(); + + if (aSize < bSize) + { + remainder = a; + remainder.sign = Integer::POSITIVE; + quotient = Integer::Zero(); + return; + } + + aSize += aSize%2; // round up to next even number + bSize += bSize%2; + + remainder.reg.CleanNew(RoundupSize(bSize)); + remainder.sign = Integer::POSITIVE; + quotient.reg.CleanNew(RoundupSize(aSize-bSize+2)); + quotient.sign = Integer::POSITIVE; + + IntegerSecBlock T(aSize+3*(bSize+2)); + Divide(remainder.reg, quotient.reg, T, a.reg, aSize, b.reg, bSize); +} + +void Integer::Divide(Integer &remainder, Integer "ient, const Integer ÷nd, const Integer &divisor) +{ + PositiveDivide(remainder, quotient, dividend, divisor); + + if (dividend.IsNegative()) + { + quotient.Negate(); + if (remainder.NotZero()) + { + --quotient; + remainder = divisor.AbsoluteValue() - remainder; + } + } + + if (divisor.IsNegative()) + quotient.Negate(); +} + +void Integer::DivideByPowerOf2(Integer &r, Integer &q, const Integer &a, unsigned int n) +{ + q = a; + q >>= n; + + const size_t wordCount = BitsToWords(n); + if (wordCount <= a.WordCount()) + { + r.reg.resize(RoundupSize(wordCount)); + CopyWords(r.reg, a.reg, wordCount); + SetWords(r.reg+wordCount, 0, r.reg.size()-wordCount); + if (n % WORD_BITS != 0) + r.reg[wordCount-1] %= (word(1) << (n % WORD_BITS)); + } + else + { + r.reg.resize(RoundupSize(a.WordCount())); + CopyWords(r.reg, a.reg, r.reg.size()); + } + r.sign = POSITIVE; + + if (a.IsNegative() && r.NotZero()) + { + --q; + r = Power2(n) - r; + } +} + +Integer Integer::DividedBy(const Integer &b) const +{ + Integer remainder, quotient; + Integer::Divide(remainder, quotient, *this, b); + return quotient; +} + +Integer Integer::Modulo(const Integer &b) const +{ + Integer remainder, quotient; + Integer::Divide(remainder, quotient, *this, b); + return remainder; +} + +void Integer::Divide(word &remainder, Integer "ient, const Integer ÷nd, word divisor) +{ + if (!divisor) + throw Integer::DivideByZero(); + + assert(divisor); + + if ((divisor & (divisor-1)) == 0) // divisor is a power of 2 + { + quotient = dividend >> (BitPrecision(divisor)-1); + remainder = dividend.reg[0] & (divisor-1); + return; + } + + unsigned int i = dividend.WordCount(); + quotient.reg.CleanNew(RoundupSize(i)); + remainder = 0; + while (i--) + { + quotient.reg[i] = DWord(dividend.reg[i], remainder) / divisor; + remainder = DWord(dividend.reg[i], remainder) % divisor; + } + + if (dividend.NotNegative()) + quotient.sign = POSITIVE; + else + { + quotient.sign = NEGATIVE; + if (remainder) + { + --quotient; + remainder = divisor - remainder; + } + } +} + +Integer Integer::DividedBy(word b) const +{ + word remainder; + Integer quotient; + Integer::Divide(remainder, quotient, *this, b); + return quotient; +} + +word Integer::Modulo(word divisor) const +{ + if (!divisor) + throw Integer::DivideByZero(); + + assert(divisor); + + word remainder; + + if ((divisor & (divisor-1)) == 0) // divisor is a power of 2 + remainder = reg[0] & (divisor-1); + else + { + unsigned int i = WordCount(); + + if (divisor <= 5) + { + DWord sum(0, 0); + while (i--) + sum += reg[i]; + remainder = sum % divisor; + } + else + { + remainder = 0; + while (i--) + remainder = DWord(reg[i], remainder) % divisor; + } + } + + if (IsNegative() && remainder) + remainder = divisor - remainder; + + return remainder; +} + +void Integer::Negate() +{ + if (!!(*this)) // don't flip sign if *this==0 + sign = Sign(1-sign); +} + +int Integer::PositiveCompare(const Integer& t) const +{ + unsigned size = WordCount(), tSize = t.WordCount(); + + if (size == tSize) + return CryptoPP::Compare(reg, t.reg, size); + else + return size > tSize ? 1 : -1; +} + +int Integer::Compare(const Integer& t) const +{ + if (NotNegative()) + { + if (t.NotNegative()) + return PositiveCompare(t); + else + return 1; + } + else + { + if (t.NotNegative()) + return -1; + else + return -PositiveCompare(t); + } +} + +Integer Integer::SquareRoot() const +{ + if (!IsPositive()) + return Zero(); + + // overestimate square root + Integer x, y = Power2((BitCount()+1)/2); + assert(y*y >= *this); + + do + { + x = y; + y = (x + *this/x) >> 1; + } while (y().Gcd(a, b); +} + +Integer Integer::InverseMod(const Integer &m) const +{ + assert(m.NotNegative()); + + if (IsNegative()) + return Modulo(m).InverseMod(m); + + if (m.IsEven()) + { + if (!m || IsEven()) + return Zero(); // no inverse + if (*this == One()) + return One(); + + Integer u = m.Modulo(*this).InverseMod(*this); + return !u ? Zero() : (m*(*this-u)+1)/(*this); + } + + SecBlock T(m.reg.size() * 4); + Integer r((word)0, m.reg.size()); + unsigned k = AlmostInverse(r.reg, T, reg, reg.size(), m.reg, m.reg.size()); + DivideByPower2Mod(r.reg, r.reg, k, m.reg, m.reg.size()); + return r; +} + +word Integer::InverseMod(word mod) const +{ + word g0 = mod, g1 = *this % mod; + word v0 = 0, v1 = 1; + word y; + + while (g1) + { + if (g1 == 1) + return v1; + y = g0 / g1; + g0 = g0 % g1; + v0 += y * v1; + + if (!g0) + break; + if (g0 == 1) + return mod-v0; + y = g1 / g0; + g1 = g1 % g0; + v1 += y * v0; + } + return 0; +} + +// ******************************************************** + +ModularArithmetic::ModularArithmetic(BufferedTransformation &bt) +{ + BERSequenceDecoder seq(bt); + OID oid(seq); + if (oid != ASN1::prime_field()) + BERDecodeError(); + m_modulus.BERDecode(seq); + seq.MessageEnd(); + m_result.reg.resize(m_modulus.reg.size()); +} + +void ModularArithmetic::DEREncode(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + ASN1::prime_field().DEREncode(seq); + m_modulus.DEREncode(seq); + seq.MessageEnd(); +} + +void ModularArithmetic::DEREncodeElement(BufferedTransformation &out, const Element &a) const +{ + a.DEREncodeAsOctetString(out, MaxElementByteLength()); +} + +void ModularArithmetic::BERDecodeElement(BufferedTransformation &in, Element &a) const +{ + a.BERDecodeAsOctetString(in, MaxElementByteLength()); +} + +const Integer& ModularArithmetic::Half(const Integer &a) const +{ + if (a.reg.size()==m_modulus.reg.size()) + { + CryptoPP::DivideByPower2Mod(m_result.reg.begin(), a.reg, 1, m_modulus.reg, a.reg.size()); + return m_result; + } + else + return m_result1 = (a.IsEven() ? (a >> 1) : ((a+m_modulus) >> 1)); +} + +const Integer& ModularArithmetic::Add(const Integer &a, const Integer &b) const +{ + if (a.reg.size()==m_modulus.reg.size() && b.reg.size()==m_modulus.reg.size()) + { + if (CryptoPP::Add(m_result.reg.begin(), a.reg, b.reg, a.reg.size()) + || Compare(m_result.reg, m_modulus.reg, a.reg.size()) >= 0) + { + CryptoPP::Subtract(m_result.reg.begin(), m_result.reg, m_modulus.reg, a.reg.size()); + } + return m_result; + } + else + { + m_result1 = a+b; + if (m_result1 >= m_modulus) + m_result1 -= m_modulus; + return m_result1; + } +} + +Integer& ModularArithmetic::Accumulate(Integer &a, const Integer &b) const +{ + if (a.reg.size()==m_modulus.reg.size() && b.reg.size()==m_modulus.reg.size()) + { + if (CryptoPP::Add(a.reg, a.reg, b.reg, a.reg.size()) + || Compare(a.reg, m_modulus.reg, a.reg.size()) >= 0) + { + CryptoPP::Subtract(a.reg, a.reg, m_modulus.reg, a.reg.size()); + } + } + else + { + a+=b; + if (a>=m_modulus) + a-=m_modulus; + } + + return a; +} + +const Integer& ModularArithmetic::Subtract(const Integer &a, const Integer &b) const +{ + if (a.reg.size()==m_modulus.reg.size() && b.reg.size()==m_modulus.reg.size()) + { + if (CryptoPP::Subtract(m_result.reg.begin(), a.reg, b.reg, a.reg.size())) + CryptoPP::Add(m_result.reg.begin(), m_result.reg, m_modulus.reg, a.reg.size()); + return m_result; + } + else + { + m_result1 = a-b; + if (m_result1.IsNegative()) + m_result1 += m_modulus; + return m_result1; + } +} + +Integer& ModularArithmetic::Reduce(Integer &a, const Integer &b) const +{ + if (a.reg.size()==m_modulus.reg.size() && b.reg.size()==m_modulus.reg.size()) + { + if (CryptoPP::Subtract(a.reg, a.reg, b.reg, a.reg.size())) + CryptoPP::Add(a.reg, a.reg, m_modulus.reg, a.reg.size()); + } + else + { + a-=b; + if (a.IsNegative()) + a+=m_modulus; + } + + return a; +} + +const Integer& ModularArithmetic::Inverse(const Integer &a) const +{ + if (!a) + return a; + + CopyWords(m_result.reg.begin(), m_modulus.reg, m_modulus.reg.size()); + if (CryptoPP::Subtract(m_result.reg.begin(), m_result.reg, a.reg, a.reg.size())) + Decrement(m_result.reg.begin()+a.reg.size(), m_modulus.reg.size()-a.reg.size()); + + return m_result; +} + +Integer ModularArithmetic::CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const +{ + if (m_modulus.IsOdd()) + { + MontgomeryRepresentation dr(m_modulus); + return dr.ConvertOut(dr.CascadeExponentiate(dr.ConvertIn(x), e1, dr.ConvertIn(y), e2)); + } + else + return AbstractRing::CascadeExponentiate(x, e1, y, e2); +} + +void ModularArithmetic::SimultaneousExponentiate(Integer *results, const Integer &base, const Integer *exponents, unsigned int exponentsCount) const +{ + if (m_modulus.IsOdd()) + { + MontgomeryRepresentation dr(m_modulus); + dr.SimultaneousExponentiate(results, dr.ConvertIn(base), exponents, exponentsCount); + for (unsigned int i=0; i::SimultaneousExponentiate(results, base, exponents, exponentsCount); +} + +MontgomeryRepresentation::MontgomeryRepresentation(const Integer &m) // modulus must be odd + : ModularArithmetic(m), + m_u((word)0, m_modulus.reg.size()), + m_workspace(5*m_modulus.reg.size()) +{ + if (!m_modulus.IsOdd()) + throw InvalidArgument("MontgomeryRepresentation: Montgomery representation requires an odd modulus"); + + RecursiveInverseModPower2(m_u.reg, m_workspace, m_modulus.reg, m_modulus.reg.size()); +} + +const Integer& MontgomeryRepresentation::Multiply(const Integer &a, const Integer &b) const +{ + word *const T = m_workspace.begin(); + word *const R = m_result.reg.begin(); + const size_t N = m_modulus.reg.size(); + assert(a.reg.size()<=N && b.reg.size()<=N); + + AsymmetricMultiply(T, T+2*N, a.reg, a.reg.size(), b.reg, b.reg.size()); + SetWords(T+a.reg.size()+b.reg.size(), 0, 2*N-a.reg.size()-b.reg.size()); + MontgomeryReduce(R, T+2*N, T, m_modulus.reg, m_u.reg, N); + return m_result; +} + +const Integer& MontgomeryRepresentation::Square(const Integer &a) const +{ + word *const T = m_workspace.begin(); + word *const R = m_result.reg.begin(); + const size_t N = m_modulus.reg.size(); + assert(a.reg.size()<=N); + + CryptoPP::Square(T, T+2*N, a.reg, a.reg.size()); + SetWords(T+2*a.reg.size(), 0, 2*N-2*a.reg.size()); + MontgomeryReduce(R, T+2*N, T, m_modulus.reg, m_u.reg, N); + return m_result; +} + +Integer MontgomeryRepresentation::ConvertOut(const Integer &a) const +{ + word *const T = m_workspace.begin(); + word *const R = m_result.reg.begin(); + const size_t N = m_modulus.reg.size(); + assert(a.reg.size()<=N); + + CopyWords(T, a.reg, a.reg.size()); + SetWords(T+a.reg.size(), 0, 2*N-a.reg.size()); + MontgomeryReduce(R, T+2*N, T, m_modulus.reg, m_u.reg, N); + return m_result; +} + +const Integer& MontgomeryRepresentation::MultiplicativeInverse(const Integer &a) const +{ +// return (EuclideanMultiplicativeInverse(a, modulus)<<(2*WORD_BITS*modulus.reg.size()))%modulus; + word *const T = m_workspace.begin(); + word *const R = m_result.reg.begin(); + const size_t N = m_modulus.reg.size(); + assert(a.reg.size()<=N); + + CopyWords(T, a.reg, a.reg.size()); + SetWords(T+a.reg.size(), 0, 2*N-a.reg.size()); + MontgomeryReduce(R, T+2*N, T, m_modulus.reg, m_u.reg, N); + unsigned k = AlmostInverse(R, T, R, N, m_modulus.reg, N); + +// cout << "k=" << k << " N*32=" << 32*N << endl; + + if (k>N*WORD_BITS) + DivideByPower2Mod(R, R, k-N*WORD_BITS, m_modulus.reg, N); + else + MultiplyByPower2Mod(R, R, N*WORD_BITS-k, m_modulus.reg, N); + + return m_result; +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/integer.h b/src-cryptopp/integer.h new file mode 100644 index 0000000..6d844fa --- /dev/null +++ b/src-cryptopp/integer.h @@ -0,0 +1,420 @@ +#ifndef CRYPTOPP_INTEGER_H +#define CRYPTOPP_INTEGER_H + +/** \file */ + +#include "cryptlib.h" +#include "secblock.h" + +#include +#include + +NAMESPACE_BEGIN(CryptoPP) + +struct InitializeInteger // used to initialize static variables +{ + InitializeInteger(); +}; + +typedef SecBlock > IntegerSecBlock; + +//! multiple precision integer and basic arithmetics +/*! This class can represent positive and negative integers + with absolute value less than (256**sizeof(word)) ** (256**sizeof(int)). + \nosubgrouping +*/ +class CRYPTOPP_DLL Integer : private InitializeInteger, public ASN1Object +{ +public: + //! \name ENUMS, EXCEPTIONS, and TYPEDEFS + //@{ + //! division by zero exception + class DivideByZero : public Exception + { + public: + DivideByZero() : Exception(OTHER_ERROR, "Integer: division by zero") {} + }; + + //! + class RandomNumberNotFound : public Exception + { + public: + RandomNumberNotFound() : Exception(OTHER_ERROR, "Integer: no integer satisfies the given parameters") {} + }; + + //! + enum Sign {POSITIVE=0, NEGATIVE=1}; + + //! + enum Signedness { + //! + UNSIGNED, + //! + SIGNED}; + + //! + enum RandomNumberType { + //! + ANY, + //! + PRIME}; + //@} + + //! \name CREATORS + //@{ + //! creates the zero integer + Integer(); + + //! copy constructor + Integer(const Integer& t); + + //! convert from signed long + Integer(signed long value); + + //! convert from lword + Integer(Sign s, lword value); + + //! convert from two words + Integer(Sign s, word highWord, word lowWord); + + //! convert from string + /*! str can be in base 2, 8, 10, or 16. Base is determined by a + case insensitive suffix of 'h', 'o', or 'b'. No suffix means base 10. + */ + explicit Integer(const char *str); + explicit Integer(const wchar_t *str); + + //! convert from big-endian byte array + Integer(const byte *encodedInteger, size_t byteCount, Signedness s=UNSIGNED); + + //! convert from big-endian form stored in a BufferedTransformation + Integer(BufferedTransformation &bt, size_t byteCount, Signedness s=UNSIGNED); + + //! convert from BER encoded byte array stored in a BufferedTransformation object + explicit Integer(BufferedTransformation &bt); + + //! create a random integer + /*! The random integer created is uniformly distributed over [0, 2**bitcount). */ + Integer(RandomNumberGenerator &rng, size_t bitcount); + + //! avoid calling constructors for these frequently used integers + static const Integer & CRYPTOPP_API Zero(); + //! avoid calling constructors for these frequently used integers + static const Integer & CRYPTOPP_API One(); + //! avoid calling constructors for these frequently used integers + static const Integer & CRYPTOPP_API Two(); + + //! create a random integer of special type + /*! Ideally, the random integer created should be uniformly distributed + over {x | min <= x <= max and x is of rnType and x % mod == equiv}. + However the actual distribution may not be uniform because sequential + search is used to find an appropriate number from a random starting + point. + May return (with very small probability) a pseudoprime when a prime + is requested and max > lastSmallPrime*lastSmallPrime (lastSmallPrime + is declared in nbtheory.h). + \throw RandomNumberNotFound if the set is empty. + */ + Integer(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType=ANY, const Integer &equiv=Zero(), const Integer &mod=One()); + + //! return the integer 2**e + static Integer CRYPTOPP_API Power2(size_t e); + //@} + + //! \name ENCODE/DECODE + //@{ + //! minimum number of bytes to encode this integer + /*! MinEncodedSize of 0 is 1 */ + size_t MinEncodedSize(Signedness=UNSIGNED) const; + //! encode in big-endian format + /*! unsigned means encode absolute value, signed means encode two's complement if negative. + if outputLen < MinEncodedSize, the most significant bytes will be dropped + if outputLen > MinEncodedSize, the most significant bytes will be padded + */ + void Encode(byte *output, size_t outputLen, Signedness=UNSIGNED) const; + //! + void Encode(BufferedTransformation &bt, size_t outputLen, Signedness=UNSIGNED) const; + + //! encode using Distinguished Encoding Rules, put result into a BufferedTransformation object + void DEREncode(BufferedTransformation &bt) const; + + //! encode absolute value as big-endian octet string + void DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const; + + //! encode absolute value in OpenPGP format, return length of output + size_t OpenPGPEncode(byte *output, size_t bufferSize) const; + //! encode absolute value in OpenPGP format, put result into a BufferedTransformation object + size_t OpenPGPEncode(BufferedTransformation &bt) const; + + //! + void Decode(const byte *input, size_t inputLen, Signedness=UNSIGNED); + //! + //* Precondition: bt.MaxRetrievable() >= inputLen + void Decode(BufferedTransformation &bt, size_t inputLen, Signedness=UNSIGNED); + + //! + void BERDecode(const byte *input, size_t inputLen); + //! + void BERDecode(BufferedTransformation &bt); + + //! decode nonnegative value as big-endian octet string + void BERDecodeAsOctetString(BufferedTransformation &bt, size_t length); + + class OpenPGPDecodeErr : public Exception + { + public: + OpenPGPDecodeErr() : Exception(INVALID_DATA_FORMAT, "OpenPGP decode error") {} + }; + + //! + void OpenPGPDecode(const byte *input, size_t inputLen); + //! + void OpenPGPDecode(BufferedTransformation &bt); + //@} + + //! \name ACCESSORS + //@{ + //! return true if *this can be represented as a signed long + bool IsConvertableToLong() const; + //! return equivalent signed long if possible, otherwise undefined + signed long ConvertToLong() const; + + //! number of significant bits = floor(log2(abs(*this))) + 1 + unsigned int BitCount() const; + //! number of significant bytes = ceiling(BitCount()/8) + unsigned int ByteCount() const; + //! number of significant words = ceiling(ByteCount()/sizeof(word)) + unsigned int WordCount() const; + + //! return the i-th bit, i=0 being the least significant bit + bool GetBit(size_t i) const; + //! return the i-th byte + byte GetByte(size_t i) const; + //! return n lowest bits of *this >> i + lword GetBits(size_t i, size_t n) const; + + //! + bool IsZero() const {return !*this;} + //! + bool NotZero() const {return !IsZero();} + //! + bool IsNegative() const {return sign == NEGATIVE;} + //! + bool NotNegative() const {return !IsNegative();} + //! + bool IsPositive() const {return NotNegative() && NotZero();} + //! + bool NotPositive() const {return !IsPositive();} + //! + bool IsEven() const {return GetBit(0) == 0;} + //! + bool IsOdd() const {return GetBit(0) == 1;} + //@} + + //! \name MANIPULATORS + //@{ + //! + Integer& operator=(const Integer& t); + + //! + Integer& operator+=(const Integer& t); + //! + Integer& operator-=(const Integer& t); + //! + Integer& operator*=(const Integer& t) {return *this = Times(t);} + //! + Integer& operator/=(const Integer& t) {return *this = DividedBy(t);} + //! + Integer& operator%=(const Integer& t) {return *this = Modulo(t);} + //! + Integer& operator/=(word t) {return *this = DividedBy(t);} + //! + Integer& operator%=(word t) {return *this = Integer(POSITIVE, 0, Modulo(t));} + + //! + Integer& operator<<=(size_t); + //! + Integer& operator>>=(size_t); + + //! + void Randomize(RandomNumberGenerator &rng, size_t bitcount); + //! + void Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max); + //! set this Integer to a random element of {x | min <= x <= max and x is of rnType and x % mod == equiv} + /*! returns false if the set is empty */ + bool Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType, const Integer &equiv=Zero(), const Integer &mod=One()); + + bool GenerateRandomNoThrow(RandomNumberGenerator &rng, const NameValuePairs ¶ms = g_nullNameValuePairs); + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms = g_nullNameValuePairs) + { + if (!GenerateRandomNoThrow(rng, params)) + throw RandomNumberNotFound(); + } + + //! set the n-th bit to value + void SetBit(size_t n, bool value=1); + //! set the n-th byte to value + void SetByte(size_t n, byte value); + + //! + void Negate(); + //! + void SetPositive() {sign = POSITIVE;} + //! + void SetNegative() {if (!!(*this)) sign = NEGATIVE;} + + //! + void swap(Integer &a); + //@} + + //! \name UNARY OPERATORS + //@{ + //! + bool operator!() const; + //! + Integer operator+() const {return *this;} + //! + Integer operator-() const; + //! + Integer& operator++(); + //! + Integer& operator--(); + //! + Integer operator++(int) {Integer temp = *this; ++*this; return temp;} + //! + Integer operator--(int) {Integer temp = *this; --*this; return temp;} + //@} + + //! \name BINARY OPERATORS + //@{ + //! signed comparison + /*! \retval -1 if *this < a + \retval 0 if *this = a + \retval 1 if *this > a + */ + int Compare(const Integer& a) const; + + //! + Integer Plus(const Integer &b) const; + //! + Integer Minus(const Integer &b) const; + //! + Integer Times(const Integer &b) const; + //! + Integer DividedBy(const Integer &b) const; + //! + Integer Modulo(const Integer &b) const; + //! + Integer DividedBy(word b) const; + //! + word Modulo(word b) const; + + //! + Integer operator>>(size_t n) const {return Integer(*this)>>=n;} + //! + Integer operator<<(size_t n) const {return Integer(*this)<<=n;} + //@} + + //! \name OTHER ARITHMETIC FUNCTIONS + //@{ + //! + Integer AbsoluteValue() const; + //! + Integer Doubled() const {return Plus(*this);} + //! + Integer Squared() const {return Times(*this);} + //! extract square root, if negative return 0, else return floor of square root + Integer SquareRoot() const; + //! return whether this integer is a perfect square + bool IsSquare() const; + + //! is 1 or -1 + bool IsUnit() const; + //! return inverse if 1 or -1, otherwise return 0 + Integer MultiplicativeInverse() const; + + //! modular multiplication + CRYPTOPP_DLL friend Integer CRYPTOPP_API a_times_b_mod_c(const Integer &x, const Integer& y, const Integer& m); + //! modular exponentiation + CRYPTOPP_DLL friend Integer CRYPTOPP_API a_exp_b_mod_c(const Integer &x, const Integer& e, const Integer& m); + + //! calculate r and q such that (a == d*q + r) && (0 <= r < abs(d)) + static void CRYPTOPP_API Divide(Integer &r, Integer &q, const Integer &a, const Integer &d); + //! use a faster division algorithm when divisor is short + static void CRYPTOPP_API Divide(word &r, Integer &q, const Integer &a, word d); + + //! returns same result as Divide(r, q, a, Power2(n)), but faster + static void CRYPTOPP_API DivideByPowerOf2(Integer &r, Integer &q, const Integer &a, unsigned int n); + + //! greatest common divisor + static Integer CRYPTOPP_API Gcd(const Integer &a, const Integer &n); + //! calculate multiplicative inverse of *this mod n + Integer InverseMod(const Integer &n) const; + //! + word InverseMod(word n) const; + //@} + + //! \name INPUT/OUTPUT + //@{ + //! + friend CRYPTOPP_DLL std::istream& CRYPTOPP_API operator>>(std::istream& in, Integer &a); + //! + friend CRYPTOPP_DLL std::ostream& CRYPTOPP_API operator<<(std::ostream& out, const Integer &a); + //@} + +private: + friend class ModularArithmetic; + friend class MontgomeryRepresentation; + friend class HalfMontgomeryRepresentation; + + Integer(word value, size_t length); + + int PositiveCompare(const Integer &t) const; + friend void PositiveAdd(Integer &sum, const Integer &a, const Integer &b); + friend void PositiveSubtract(Integer &diff, const Integer &a, const Integer &b); + friend void PositiveMultiply(Integer &product, const Integer &a, const Integer &b); + friend void PositiveDivide(Integer &remainder, Integer "ient, const Integer ÷nd, const Integer &divisor); + + IntegerSecBlock reg; + Sign sign; +}; + +//! +inline bool operator==(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)==0;} +//! +inline bool operator!=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)!=0;} +//! +inline bool operator> (const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)> 0;} +//! +inline bool operator>=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)>=0;} +//! +inline bool operator< (const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)< 0;} +//! +inline bool operator<=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)<=0;} +//! +inline CryptoPP::Integer operator+(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Plus(b);} +//! +inline CryptoPP::Integer operator-(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Minus(b);} +//! +inline CryptoPP::Integer operator*(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Times(b);} +//! +inline CryptoPP::Integer operator/(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.DividedBy(b);} +//! +inline CryptoPP::Integer operator%(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Modulo(b);} +//! +inline CryptoPP::Integer operator/(const CryptoPP::Integer &a, CryptoPP::word b) {return a.DividedBy(b);} +//! +inline CryptoPP::word operator%(const CryptoPP::Integer &a, CryptoPP::word b) {return a.Modulo(b);} + +NAMESPACE_END + +#ifndef __BORLANDC__ +NAMESPACE_BEGIN(std) +inline void swap(CryptoPP::Integer &a, CryptoPP::Integer &b) +{ + a.swap(b); +} +NAMESPACE_END +#endif + +#endif diff --git a/src-cryptopp/iterhash.cpp b/src-cryptopp/iterhash.cpp new file mode 100644 index 0000000..478950c --- /dev/null +++ b/src-cryptopp/iterhash.cpp @@ -0,0 +1,159 @@ +// iterhash.cpp - written and placed in the public domain by Wei Dai + +#ifndef __GNUC__ +#define CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES +#endif + +#include "iterhash.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +template void IteratedHashBase::Update(const byte *input, size_t len) +{ + HashWordType oldCountLo = m_countLo, oldCountHi = m_countHi; + if ((m_countLo = oldCountLo + HashWordType(len)) < oldCountLo) + m_countHi++; // carry from low to high + m_countHi += (HashWordType)SafeRightShift<8*sizeof(HashWordType)>(len); + if (m_countHi < oldCountHi || SafeRightShift<2*8*sizeof(HashWordType)>(len) != 0) + throw HashInputTooLong(this->AlgorithmName()); + + unsigned int blockSize = this->BlockSize(); + unsigned int num = ModPowerOf2(oldCountLo, blockSize); + T* dataBuf = this->DataBuf(); + byte* data = (byte *)dataBuf; + + if (num != 0) // process left over data + { + if (num+len >= blockSize) + { + memcpy(data+num, input, blockSize-num); + HashBlock(dataBuf); + input += (blockSize-num); + len -= (blockSize-num); + num = 0; + // drop through and do the rest + } + else + { + memcpy(data+num, input, len); + return; + } + } + + // now process the input data in blocks of blockSize bytes and save the leftovers to m_data + if (len >= blockSize) + { + if (input == data) + { + assert(len == blockSize); + HashBlock(dataBuf); + return; + } + else if (IsAligned(input)) + { + size_t leftOver = HashMultipleBlocks((T *)input, len); + input += (len - leftOver); + len = leftOver; + } + else + do + { // copy input first if it's not aligned correctly + memcpy(data, input, blockSize); + HashBlock(dataBuf); + input+=blockSize; + len-=blockSize; + } while (len >= blockSize); + } + + memcpy(data, input, len); +} + +template byte * IteratedHashBase::CreateUpdateSpace(size_t &size) +{ + unsigned int blockSize = this->BlockSize(); + unsigned int num = ModPowerOf2(m_countLo, blockSize); + size = blockSize - num; + return (byte *)DataBuf() + num; +} + +template size_t IteratedHashBase::HashMultipleBlocks(const T *input, size_t length) +{ + unsigned int blockSize = this->BlockSize(); + bool noReverse = NativeByteOrderIs(this->GetByteOrder()); + T* dataBuf = this->DataBuf(); + do + { + if (noReverse) + this->HashEndianCorrectedBlock(input); + else + { + ByteReverse(dataBuf, input, this->BlockSize()); + this->HashEndianCorrectedBlock(dataBuf); + } + + input += blockSize/sizeof(T); + length -= blockSize; + } + while (length >= blockSize); + return length; +} + +template void IteratedHashBase::PadLastBlock(unsigned int lastBlockSize, byte padFirst) +{ + unsigned int blockSize = this->BlockSize(); + unsigned int num = ModPowerOf2(m_countLo, blockSize); + T* dataBuf = this->DataBuf(); + byte* data = (byte *)dataBuf; + data[num++] = padFirst; + if (num <= lastBlockSize) + memset(data+num, 0, lastBlockSize-num); + else + { + memset(data+num, 0, blockSize-num); + HashBlock(dataBuf); + memset(data, 0, lastBlockSize); + } +} + +template void IteratedHashBase::Restart() +{ + m_countLo = m_countHi = 0; + Init(); +} + +template void IteratedHashBase::TruncatedFinal(byte *digest, size_t size) +{ + this->ThrowIfInvalidTruncatedSize(size); + + T* dataBuf = this->DataBuf(); + T* stateBuf = this->StateBuf(); + unsigned int blockSize = this->BlockSize(); + ByteOrder order = this->GetByteOrder(); + + PadLastBlock(blockSize - 2*sizeof(HashWordType)); + dataBuf[blockSize/sizeof(T)-2+order] = ConditionalByteReverse(order, this->GetBitCountLo()); + dataBuf[blockSize/sizeof(T)-1-order] = ConditionalByteReverse(order, this->GetBitCountHi()); + + HashBlock(dataBuf); + + if (IsAligned(digest) && size%sizeof(HashWordType)==0) + ConditionalByteReverse(order, (HashWordType *)digest, stateBuf, size); + else + { + ConditionalByteReverse(order, stateBuf, stateBuf, this->DigestSize()); + memcpy(digest, stateBuf, size); + } + + this->Restart(); // reinit for next use +} + +#ifdef __GNUC__ + template class IteratedHashBase; + template class IteratedHashBase; + + template class IteratedHashBase; + template class IteratedHashBase; +#endif + +NAMESPACE_END diff --git a/src-cryptopp/iterhash.h b/src-cryptopp/iterhash.h new file mode 100644 index 0000000..cce9e82 --- /dev/null +++ b/src-cryptopp/iterhash.h @@ -0,0 +1,106 @@ +#ifndef CRYPTOPP_ITERHASH_H +#define CRYPTOPP_ITERHASH_H + +#include "cryptlib.h" +#include "secblock.h" +#include "misc.h" +#include "simple.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! exception thrown when trying to hash more data than is allowed by a hash function +class CRYPTOPP_DLL HashInputTooLong : public InvalidDataFormat +{ +public: + explicit HashInputTooLong(const std::string &alg) + : InvalidDataFormat("IteratedHashBase: input data exceeds maximum allowed by hash function " + alg) {} +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE IteratedHashBase : public BASE +{ +public: + typedef T HashWordType; + + IteratedHashBase() : m_countLo(0), m_countHi(0) {} + unsigned int OptimalBlockSize() const {return this->BlockSize();} + unsigned int OptimalDataAlignment() const {return GetAlignmentOf();} + void Update(const byte *input, size_t length); + byte * CreateUpdateSpace(size_t &size); + void Restart(); + void TruncatedFinal(byte *digest, size_t size); + +protected: + inline T GetBitCountHi() const {return (m_countLo >> (8*sizeof(T)-3)) + (m_countHi << 3);} + inline T GetBitCountLo() const {return m_countLo << 3;} + + void PadLastBlock(unsigned int lastBlockSize, byte padFirst=0x80); + virtual void Init() =0; + + virtual ByteOrder GetByteOrder() const =0; + virtual void HashEndianCorrectedBlock(const HashWordType *data) =0; + virtual size_t HashMultipleBlocks(const T *input, size_t length); + void HashBlock(const HashWordType *input) {HashMultipleBlocks(input, this->BlockSize());} + + virtual T* DataBuf() =0; + virtual T* StateBuf() =0; + +private: + T m_countLo, m_countHi; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE IteratedHash : public IteratedHashBase +{ +public: + typedef T_Endianness ByteOrderClass; + typedef T_HashWordType HashWordType; + + CRYPTOPP_CONSTANT(BLOCKSIZE = T_BlockSize) + // BCB2006 workaround: can't use BLOCKSIZE here + CRYPTOPP_COMPILE_ASSERT((T_BlockSize & (T_BlockSize - 1)) == 0); // blockSize is a power of 2 + unsigned int BlockSize() const {return T_BlockSize;} + + ByteOrder GetByteOrder() const {return T_Endianness::ToEnum();} + + inline static void CorrectEndianess(HashWordType *out, const HashWordType *in, size_t byteCount) + { + ConditionalByteReverse(T_Endianness::ToEnum(), out, in, byteCount); + } + +protected: + T_HashWordType* DataBuf() {return this->m_data;} + FixedSizeSecBlock m_data; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE IteratedHashWithStaticTransform + : public ClonableImpl, T_Transform> > +{ +public: + CRYPTOPP_CONSTANT(DIGESTSIZE = T_DigestSize ? T_DigestSize : T_StateSize) + unsigned int DigestSize() const {return DIGESTSIZE;}; + +protected: + IteratedHashWithStaticTransform() {this->Init();} + void HashEndianCorrectedBlock(const T_HashWordType *data) {T_Transform::Transform(this->m_state, data);} + void Init() {T_Transform::InitState(this->m_state);} + + T_HashWordType* StateBuf() {return this->m_state;} + FixedSizeAlignedSecBlock m_state; +}; + +#ifndef __GNUC__ + CRYPTOPP_DLL_TEMPLATE_CLASS IteratedHashBase; + CRYPTOPP_STATIC_TEMPLATE_CLASS IteratedHashBase; + + CRYPTOPP_DLL_TEMPLATE_CLASS IteratedHashBase; + CRYPTOPP_STATIC_TEMPLATE_CLASS IteratedHashBase; +#endif + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/misc.cpp b/src-cryptopp/misc.cpp new file mode 100644 index 0000000..7e4fa89 --- /dev/null +++ b/src-cryptopp/misc.cpp @@ -0,0 +1,130 @@ +// misc.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "misc.h" +#include "words.h" +#include + +NAMESPACE_BEGIN(CryptoPP) + +void xorbuf(byte *buf, const byte *mask, size_t count) +{ + size_t i; + + if (IsAligned(buf) && IsAligned(mask)) + { + if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned(buf) && IsAligned(mask)) + { + for (i=0; i(output) && IsAligned(input) && IsAligned(mask)) + { + if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned(output) && IsAligned(input) && IsAligned(mask)) + { + for (i=0; i(buf) && IsAligned(mask)) + { + word32 acc32 = 0; + if (!CRYPTOPP_BOOL_SLOW_WORD64 && IsAligned(buf) && IsAligned(mask)) + { + word64 acc64 = 0; + for (i=0; i>32); + } + + for (i=0; i>8) | byte(acc32>>16) | byte(acc32>>24); + } + + for (i=0; i // for memcpy and memmove + +#ifdef _MSC_VER + #if _MSC_VER >= 1400 + // VC2005 workaround: disable declarations that conflict with winnt.h + #define _interlockedbittestandset CRYPTOPP_DISABLED_INTRINSIC_1 + #define _interlockedbittestandreset CRYPTOPP_DISABLED_INTRINSIC_2 + #define _interlockedbittestandset64 CRYPTOPP_DISABLED_INTRINSIC_3 + #define _interlockedbittestandreset64 CRYPTOPP_DISABLED_INTRINSIC_4 + #include + #undef _interlockedbittestandset + #undef _interlockedbittestandreset + #undef _interlockedbittestandset64 + #undef _interlockedbittestandreset64 + #define CRYPTOPP_FAST_ROTATE(x) 1 + #elif _MSC_VER >= 1300 + #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32 | (x) == 64) + #else + #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32) + #endif +#elif (defined(__MWERKS__) && TARGET_CPU_PPC) || \ + (defined(__GNUC__) && (defined(_ARCH_PWR2) || defined(_ARCH_PWR) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(_ARCH_COM))) + #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32) +#elif defined(__GNUC__) && (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86) // depend on GCC's peephole optimization to generate rotate instructions + #define CRYPTOPP_FAST_ROTATE(x) 1 +#else + #define CRYPTOPP_FAST_ROTATE(x) 0 +#endif + +#ifdef __BORLANDC__ +#include +#endif + +#if defined(__GNUC__) && defined(__linux__) +#define CRYPTOPP_BYTESWAP_AVAILABLE +#include +#endif + +NAMESPACE_BEGIN(CryptoPP) + +// ************** compile-time assertion *************** + +template +struct CompileAssert +{ + static char dummy[2*b-1]; +}; + +#define CRYPTOPP_COMPILE_ASSERT(assertion) CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, __LINE__) +#if defined(CRYPTOPP_EXPORTS) || defined(CRYPTOPP_IMPORTS) +#define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance) +#else +#define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance) static CompileAssert<(assertion)> CRYPTOPP_ASSERT_JOIN(cryptopp_assert_, instance) +#endif +#define CRYPTOPP_ASSERT_JOIN(X, Y) CRYPTOPP_DO_ASSERT_JOIN(X, Y) +#define CRYPTOPP_DO_ASSERT_JOIN(X, Y) X##Y + +// ************** misc classes *************** + +class CRYPTOPP_DLL Empty +{ +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE TwoBases : public BASE1, public BASE2 +{ +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE ThreeBases : public BASE1, public BASE2, public BASE3 +{ +}; + +template +class ObjectHolder +{ +protected: + T m_object; +}; + +class NotCopyable +{ +public: + NotCopyable() {} +private: + NotCopyable(const NotCopyable &); + void operator=(const NotCopyable &); +}; + +template +struct NewObject +{ + T* operator()() const {return new T;} +}; + +/*! This function safely initializes a static object in a multithreaded environment without using locks (for portability). + Note that if two threads call Ref() at the same time, they may get back different references, and one object + may end up being memory leaked. This is by design. +*/ +template , int instance=0> +class Singleton +{ +public: + Singleton(F objectFactory = F()) : m_objectFactory(objectFactory) {} + + // prevent this function from being inlined + CRYPTOPP_NOINLINE const T & Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const; + +private: + F m_objectFactory; +}; + +template +const T & Singleton::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const +{ + static volatile simple_ptr s_pObject; + T *p = s_pObject.m_p; + + if (p) + return *p; + + T *newObject = m_objectFactory(); + p = s_pObject.m_p; + + if (p) + { + delete newObject; + return *p; + } + + s_pObject.m_p = newObject; + return *newObject; +} + +// ************** misc functions *************** + +#if (!__STDC_WANT_SECURE_LIB__) +inline void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t count) +{ + if (count > sizeInBytes) + throw InvalidArgument("memcpy_s: buffer overflow"); + memcpy(dest, src, count); +} + +inline void memmove_s(void *dest, size_t sizeInBytes, const void *src, size_t count) +{ + if (count > sizeInBytes) + throw InvalidArgument("memmove_s: buffer overflow"); + memmove(dest, src, count); +} +#endif + +inline void * memset_z(void *ptr, int value, size_t num) +{ +// avoid extranous warning on GCC 4.3.2 Ubuntu 8.10 +#if CRYPTOPP_GCC_VERSION >= 30001 + if (__builtin_constant_p(num) && num==0) + return ptr; +#endif + return memset(ptr, value, num); +} + +// can't use std::min or std::max in MSVC60 or Cygwin 1.1.0 +template inline const T& STDMIN(const T& a, const T& b) +{ + return b < a ? b : a; +} + +template inline const T1 UnsignedMin(const T1& a, const T2& b) +{ + CRYPTOPP_COMPILE_ASSERT((sizeof(T1)<=sizeof(T2) && T2(-1)>0) || (sizeof(T1)>sizeof(T2) && T1(-1)>0)); + assert(a==0 || a>0); // GCC workaround: get rid of the warning "comparison is always true due to limited range of data type" + assert(b>=0); + + if (sizeof(T1)<=sizeof(T2)) + return b < (T2)a ? (T1)b : a; + else + return (T1)b < a ? (T1)b : a; +} + +template inline const T& STDMAX(const T& a, const T& b) +{ + return a < b ? b : a; +} + +#define RETURN_IF_NONZERO(x) size_t returnedValue = x; if (returnedValue) return returnedValue + +// this version of the macro is fastest on Pentium 3 and Pentium 4 with MSVC 6 SP5 w/ Processor Pack +#define GETBYTE(x, y) (unsigned int)byte((x)>>(8*(y))) +// these may be faster on other CPUs/compilers +// #define GETBYTE(x, y) (unsigned int)(((x)>>(8*(y)))&255) +// #define GETBYTE(x, y) (((byte *)&(x))[y]) + +#define CRYPTOPP_GET_BYTE_AS_BYTE(x, y) byte((x)>>(8*(y))) + +template +unsigned int Parity(T value) +{ + for (unsigned int i=8*sizeof(value)/2; i>0; i/=2) + value ^= value >> i; + return (unsigned int)value&1; +} + +template +unsigned int BytePrecision(const T &value) +{ + if (!value) + return 0; + + unsigned int l=0, h=8*sizeof(value); + + while (h-l > 8) + { + unsigned int t = (l+h)/2; + if (value >> t) + l = t; + else + h = t; + } + + return h/8; +} + +template +unsigned int BitPrecision(const T &value) +{ + if (!value) + return 0; + + unsigned int l=0, h=8*sizeof(value); + + while (h-l > 1) + { + unsigned int t = (l+h)/2; + if (value >> t) + l = t; + else + h = t; + } + + return h; +} + +template +inline T Crop(T value, size_t size) +{ + if (size < 8*sizeof(value)) + return T(value & ((T(1) << size) - 1)); + else + return value; +} + +template +inline bool SafeConvert(T1 from, T2 &to) +{ + to = (T2)from; + if (from != to || (from > 0) != (to > 0)) + return false; + return true; +} + +inline size_t BitsToBytes(size_t bitCount) +{ + return ((bitCount+7)/(8)); +} + +inline size_t BytesToWords(size_t byteCount) +{ + return ((byteCount+WORD_SIZE-1)/WORD_SIZE); +} + +inline size_t BitsToWords(size_t bitCount) +{ + return ((bitCount+WORD_BITS-1)/(WORD_BITS)); +} + +inline size_t BitsToDwords(size_t bitCount) +{ + return ((bitCount+2*WORD_BITS-1)/(2*WORD_BITS)); +} + +CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *buf, const byte *mask, size_t count); +CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *output, const byte *input, const byte *mask, size_t count); + +CRYPTOPP_DLL bool CRYPTOPP_API VerifyBufsEqual(const byte *buf1, const byte *buf2, size_t count); + +template +inline bool IsPowerOf2(const T &n) +{ + return n > 0 && (n & (n-1)) == 0; +} + +template +inline T2 ModPowerOf2(const T1 &a, const T2 &b) +{ + assert(IsPowerOf2(b)); + return T2(a) & (b-1); +} + +template +inline T1 RoundDownToMultipleOf(const T1 &n, const T2 &m) +{ + if (IsPowerOf2(m)) + return n - ModPowerOf2(n, m); + else + return n - n%m; +} + +template +inline T1 RoundUpToMultipleOf(const T1 &n, const T2 &m) +{ + if (n+m-1 < n) + throw InvalidArgument("RoundUpToMultipleOf: integer overflow"); + return RoundDownToMultipleOf(n+m-1, m); +} + +template +inline unsigned int GetAlignmentOf(T *dummy=NULL) // VC60 workaround +{ +#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS + if (sizeof(T) < 16) + return 1; +#endif + +#if (_MSC_VER >= 1300) + return __alignof(T); +#elif defined(__GNUC__) + return __alignof__(T); +#elif CRYPTOPP_BOOL_SLOW_WORD64 + return UnsignedMin(4U, sizeof(T)); +#else + return sizeof(T); +#endif +} + +inline bool IsAlignedOn(const void *p, unsigned int alignment) +{ + return alignment==1 || (IsPowerOf2(alignment) ? ModPowerOf2((size_t)p, alignment) == 0 : (size_t)p % alignment == 0); +} + +template +inline bool IsAligned(const void *p, T *dummy=NULL) // VC60 workaround +{ + return IsAlignedOn(p, GetAlignmentOf()); +} + +#ifdef IS_LITTLE_ENDIAN + typedef LittleEndian NativeByteOrder; +#else + typedef BigEndian NativeByteOrder; +#endif + +inline ByteOrder GetNativeByteOrder() +{ + return NativeByteOrder::ToEnum(); +} + +inline bool NativeByteOrderIs(ByteOrder order) +{ + return order == GetNativeByteOrder(); +} + +template +std::string IntToString(T a, unsigned int base = 10) +{ + if (a == 0) + return "0"; + bool negate = false; + if (a < 0) + { + negate = true; + a = 0-a; // VC .NET does not like -a + } + std::string result; + while (a > 0) + { + T digit = a % base; + result = char((digit < 10 ? '0' : ('a' - 10)) + digit) + result; + a /= base; + } + if (negate) + result = "-" + result; + return result; +} + +template +inline T1 SaturatingSubtract(const T1 &a, const T2 &b) +{ + return T1((a > b) ? (a - b) : 0); +} + +template +inline CipherDir GetCipherDir(const T &obj) +{ + return obj.IsForwardTransformation() ? ENCRYPTION : DECRYPTION; +} + +CRYPTOPP_DLL void CRYPTOPP_API CallNewHandler(); + +inline void IncrementCounterByOne(byte *inout, unsigned int s) +{ + for (int i=s-1, carry=1; i>=0 && carry; i--) + carry = !++inout[i]; +} + +inline void IncrementCounterByOne(byte *output, const byte *input, unsigned int s) +{ + int i, carry; + for (i=s-1, carry=1; i>=0 && carry; i--) + carry = ((output[i] = input[i]+1) == 0); + memcpy_s(output, s, input, i+1); +} + +// ************** rotate functions *************** + +template inline T rotlFixed(T x, unsigned int y) +{ + assert(y < sizeof(T)*8); + return T((x<>(sizeof(T)*8-y))); +} + +template inline T rotrFixed(T x, unsigned int y) +{ + assert(y < sizeof(T)*8); + return T((x>>y) | (x<<(sizeof(T)*8-y))); +} + +template inline T rotlVariable(T x, unsigned int y) +{ + assert(y < sizeof(T)*8); + return T((x<>(sizeof(T)*8-y))); +} + +template inline T rotrVariable(T x, unsigned int y) +{ + assert(y < sizeof(T)*8); + return T((x>>y) | (x<<(sizeof(T)*8-y))); +} + +template inline T rotlMod(T x, unsigned int y) +{ + y %= sizeof(T)*8; + return T((x<>(sizeof(T)*8-y))); +} + +template inline T rotrMod(T x, unsigned int y) +{ + y %= sizeof(T)*8; + return T((x>>y) | (x<<(sizeof(T)*8-y))); +} + +#ifdef _MSC_VER + +template<> inline word32 rotlFixed(word32 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return y ? _lrotl(x, y) : x; +} + +template<> inline word32 rotrFixed(word32 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return y ? _lrotr(x, y) : x; +} + +template<> inline word32 rotlVariable(word32 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return _lrotl(x, y); +} + +template<> inline word32 rotrVariable(word32 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return _lrotr(x, y); +} + +template<> inline word32 rotlMod(word32 x, unsigned int y) +{ + return _lrotl(x, y); +} + +template<> inline word32 rotrMod(word32 x, unsigned int y) +{ + return _lrotr(x, y); +} + +#endif // #ifdef _MSC_VER + +#if _MSC_VER >= 1300 && !defined(__INTEL_COMPILER) +// Intel C++ Compiler 10.0 calls a function instead of using the rotate instruction when using these instructions + +template<> inline word64 rotlFixed(word64 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return y ? _rotl64(x, y) : x; +} + +template<> inline word64 rotrFixed(word64 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return y ? _rotr64(x, y) : x; +} + +template<> inline word64 rotlVariable(word64 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return _rotl64(x, y); +} + +template<> inline word64 rotrVariable(word64 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return _rotr64(x, y); +} + +template<> inline word64 rotlMod(word64 x, unsigned int y) +{ + return _rotl64(x, y); +} + +template<> inline word64 rotrMod(word64 x, unsigned int y) +{ + return _rotr64(x, y); +} + +#endif // #if _MSC_VER >= 1310 + +#if _MSC_VER >= 1400 && !defined(__INTEL_COMPILER) +// Intel C++ Compiler 10.0 gives undefined externals with these + +template<> inline word16 rotlFixed(word16 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return y ? _rotl16(x, y) : x; +} + +template<> inline word16 rotrFixed(word16 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return y ? _rotr16(x, y) : x; +} + +template<> inline word16 rotlVariable(word16 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return _rotl16(x, y); +} + +template<> inline word16 rotrVariable(word16 x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return _rotr16(x, y); +} + +template<> inline word16 rotlMod(word16 x, unsigned int y) +{ + return _rotl16(x, y); +} + +template<> inline word16 rotrMod(word16 x, unsigned int y) +{ + return _rotr16(x, y); +} + +template<> inline byte rotlFixed(byte x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return y ? _rotl8(x, y) : x; +} + +template<> inline byte rotrFixed(byte x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return y ? _rotr8(x, y) : x; +} + +template<> inline byte rotlVariable(byte x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return _rotl8(x, y); +} + +template<> inline byte rotrVariable(byte x, unsigned int y) +{ + assert(y < 8*sizeof(x)); + return _rotr8(x, y); +} + +template<> inline byte rotlMod(byte x, unsigned int y) +{ + return _rotl8(x, y); +} + +template<> inline byte rotrMod(byte x, unsigned int y) +{ + return _rotr8(x, y); +} + +#endif // #if _MSC_VER >= 1400 + +#if (defined(__MWERKS__) && TARGET_CPU_PPC) + +template<> inline word32 rotlFixed(word32 x, unsigned int y) +{ + assert(y < 32); + return y ? __rlwinm(x,y,0,31) : x; +} + +template<> inline word32 rotrFixed(word32 x, unsigned int y) +{ + assert(y < 32); + return y ? __rlwinm(x,32-y,0,31) : x; +} + +template<> inline word32 rotlVariable(word32 x, unsigned int y) +{ + assert(y < 32); + return (__rlwnm(x,y,0,31)); +} + +template<> inline word32 rotrVariable(word32 x, unsigned int y) +{ + assert(y < 32); + return (__rlwnm(x,32-y,0,31)); +} + +template<> inline word32 rotlMod(word32 x, unsigned int y) +{ + return (__rlwnm(x,y,0,31)); +} + +template<> inline word32 rotrMod(word32 x, unsigned int y) +{ + return (__rlwnm(x,32-y,0,31)); +} + +#endif // #if (defined(__MWERKS__) && TARGET_CPU_PPC) + +// ************** endian reversal *************** + +template +inline unsigned int GetByte(ByteOrder order, T value, unsigned int index) +{ + if (order == LITTLE_ENDIAN_ORDER) + return GETBYTE(value, index); + else + return GETBYTE(value, sizeof(T)-index-1); +} + +inline byte ByteReverse(byte value) +{ + return value; +} + +inline word16 ByteReverse(word16 value) +{ +#ifdef CRYPTOPP_BYTESWAP_AVAILABLE + return bswap_16(value); +#elif defined(_MSC_VER) && _MSC_VER >= 1300 + return _byteswap_ushort(value); +#else + return rotlFixed(value, 8U); +#endif +} + +inline word32 ByteReverse(word32 value) +{ +#if defined(__GNUC__) && defined(CRYPTOPP_X86_ASM_AVAILABLE) + __asm__ ("bswap %0" : "=r" (value) : "0" (value)); + return value; +#elif defined(CRYPTOPP_BYTESWAP_AVAILABLE) + return bswap_32(value); +#elif defined(__MWERKS__) && TARGET_CPU_PPC + return (word32)__lwbrx(&value,0); +#elif _MSC_VER >= 1400 || (_MSC_VER >= 1300 && !defined(_DLL)) + return _byteswap_ulong(value); +#elif CRYPTOPP_FAST_ROTATE(32) + // 5 instructions with rotate instruction, 9 without + return (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff); +#else + // 6 instructions with rotate instruction, 8 without + value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8); + return rotlFixed(value, 16U); +#endif +} + +inline word64 ByteReverse(word64 value) +{ +#if defined(__GNUC__) && defined(CRYPTOPP_X86_ASM_AVAILABLE) && defined(__x86_64__) + __asm__ ("bswap %0" : "=r" (value) : "0" (value)); + return value; +#elif defined(CRYPTOPP_BYTESWAP_AVAILABLE) + return bswap_64(value); +#elif defined(_MSC_VER) && _MSC_VER >= 1300 + return _byteswap_uint64(value); +#elif CRYPTOPP_BOOL_SLOW_WORD64 + return (word64(ByteReverse(word32(value))) << 32) | ByteReverse(word32(value>>32)); +#else + value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | ((value & W64LIT(0x00FF00FF00FF00FF)) << 8); + value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) | ((value & W64LIT(0x0000FFFF0000FFFF)) << 16); + return rotlFixed(value, 32U); +#endif +} + +inline byte BitReverse(byte value) +{ + value = ((value & 0xAA) >> 1) | ((value & 0x55) << 1); + value = ((value & 0xCC) >> 2) | ((value & 0x33) << 2); + return rotlFixed(value, 4U); +} + +inline word16 BitReverse(word16 value) +{ + value = ((value & 0xAAAA) >> 1) | ((value & 0x5555) << 1); + value = ((value & 0xCCCC) >> 2) | ((value & 0x3333) << 2); + value = ((value & 0xF0F0) >> 4) | ((value & 0x0F0F) << 4); + return ByteReverse(value); +} + +inline word32 BitReverse(word32 value) +{ + value = ((value & 0xAAAAAAAA) >> 1) | ((value & 0x55555555) << 1); + value = ((value & 0xCCCCCCCC) >> 2) | ((value & 0x33333333) << 2); + value = ((value & 0xF0F0F0F0) >> 4) | ((value & 0x0F0F0F0F) << 4); + return ByteReverse(value); +} + +inline word64 BitReverse(word64 value) +{ +#if CRYPTOPP_BOOL_SLOW_WORD64 + return (word64(BitReverse(word32(value))) << 32) | BitReverse(word32(value>>32)); +#else + value = ((value & W64LIT(0xAAAAAAAAAAAAAAAA)) >> 1) | ((value & W64LIT(0x5555555555555555)) << 1); + value = ((value & W64LIT(0xCCCCCCCCCCCCCCCC)) >> 2) | ((value & W64LIT(0x3333333333333333)) << 2); + value = ((value & W64LIT(0xF0F0F0F0F0F0F0F0)) >> 4) | ((value & W64LIT(0x0F0F0F0F0F0F0F0F)) << 4); + return ByteReverse(value); +#endif +} + +template +inline T BitReverse(T value) +{ + if (sizeof(T) == 1) + return (T)BitReverse((byte)value); + else if (sizeof(T) == 2) + return (T)BitReverse((word16)value); + else if (sizeof(T) == 4) + return (T)BitReverse((word32)value); + else + { + assert(sizeof(T) == 8); + return (T)BitReverse((word64)value); + } +} + +template +inline T ConditionalByteReverse(ByteOrder order, T value) +{ + return NativeByteOrderIs(order) ? value : ByteReverse(value); +} + +template +void ByteReverse(T *out, const T *in, size_t byteCount) +{ + assert(byteCount % sizeof(T) == 0); + size_t count = byteCount/sizeof(T); + for (size_t i=0; i +inline void ConditionalByteReverse(ByteOrder order, T *out, const T *in, size_t byteCount) +{ + if (!NativeByteOrderIs(order)) + ByteReverse(out, in, byteCount); + else if (in != out) + memcpy_s(out, byteCount, in, byteCount); +} + +template +inline void GetUserKey(ByteOrder order, T *out, size_t outlen, const byte *in, size_t inlen) +{ + const size_t U = sizeof(T); + assert(inlen <= outlen*U); + memcpy_s(out, outlen*U, in, inlen); + memset_z((byte *)out+inlen, 0, outlen*U-inlen); + ConditionalByteReverse(order, out, out, RoundUpToMultipleOf(inlen, U)); +} + +#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS +inline byte UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const byte *) +{ + return block[0]; +} + +inline word16 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word16 *) +{ + return (order == BIG_ENDIAN_ORDER) + ? block[1] | (block[0] << 8) + : block[0] | (block[1] << 8); +} + +inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word32 *) +{ + return (order == BIG_ENDIAN_ORDER) + ? word32(block[3]) | (word32(block[2]) << 8) | (word32(block[1]) << 16) | (word32(block[0]) << 24) + : word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16) | (word32(block[3]) << 24); +} + +inline word64 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word64 *) +{ + return (order == BIG_ENDIAN_ORDER) + ? + (word64(block[7]) | + (word64(block[6]) << 8) | + (word64(block[5]) << 16) | + (word64(block[4]) << 24) | + (word64(block[3]) << 32) | + (word64(block[2]) << 40) | + (word64(block[1]) << 48) | + (word64(block[0]) << 56)) + : + (word64(block[0]) | + (word64(block[1]) << 8) | + (word64(block[2]) << 16) | + (word64(block[3]) << 24) | + (word64(block[4]) << 32) | + (word64(block[5]) << 40) | + (word64(block[6]) << 48) | + (word64(block[7]) << 56)); +} + +inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, byte value, const byte *xorBlock) +{ + block[0] = xorBlock ? (value ^ xorBlock[0]) : value; +} + +inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word16 value, const byte *xorBlock) +{ + if (order == BIG_ENDIAN_ORDER) + { + if (xorBlock) + { + block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + } + else + { + block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + } + } + else + { + if (xorBlock) + { + block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + } + else + { + block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + } + } +} + +inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word32 value, const byte *xorBlock) +{ + if (order == BIG_ENDIAN_ORDER) + { + if (xorBlock) + { + block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); + block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); + block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + } + else + { + block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); + block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); + block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + } + } + else + { + if (xorBlock) + { + block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); + block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); + } + else + { + block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); + block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); + } + } +} + +inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word64 value, const byte *xorBlock) +{ + if (order == BIG_ENDIAN_ORDER) + { + if (xorBlock) + { + block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 7); + block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 6); + block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 5); + block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 4); + block[4] = xorBlock[4] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); + block[5] = xorBlock[5] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); + block[6] = xorBlock[6] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[7] = xorBlock[7] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + } + else + { + block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 7); + block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 6); + block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 5); + block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 4); + block[4] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); + block[5] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); + block[6] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[7] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + } + } + else + { + if (xorBlock) + { + block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); + block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); + block[4] = xorBlock[4] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 4); + block[5] = xorBlock[5] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 5); + block[6] = xorBlock[6] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 6); + block[7] = xorBlock[7] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 7); + } + else + { + block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0); + block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1); + block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2); + block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3); + block[4] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 4); + block[5] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 5); + block[6] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 6); + block[7] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 7); + } + } +} +#endif // #ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS + +template +inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block) +{ +#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS + if (!assumeAligned) + return UnalignedGetWordNonTemplate(order, block, (T*)NULL); + assert(IsAligned(block)); +#endif + return ConditionalByteReverse(order, *reinterpret_cast(block)); +} + +template +inline void GetWord(bool assumeAligned, ByteOrder order, T &result, const byte *block) +{ + result = GetWord(assumeAligned, order, block); +} + +template +inline void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock = NULL) +{ +#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS + if (!assumeAligned) + return UnalignedPutWordNonTemplate(order, block, value, xorBlock); + assert(IsAligned(block)); + assert(IsAligned(xorBlock)); +#endif + *reinterpret_cast(block) = ConditionalByteReverse(order, value) ^ (xorBlock ? *reinterpret_cast(xorBlock) : 0); +} + +template +class GetBlock +{ +public: + GetBlock(const void *block) + : m_block((const byte *)block) {} + + template + inline GetBlock & operator()(U &x) + { + CRYPTOPP_COMPILE_ASSERT(sizeof(U) >= sizeof(T)); + x = GetWord(A, B::ToEnum(), m_block); + m_block += sizeof(T); + return *this; + } + +private: + const byte *m_block; +}; + +template +class PutBlock +{ +public: + PutBlock(const void *xorBlock, void *block) + : m_xorBlock((const byte *)xorBlock), m_block((byte *)block) {} + + template + inline PutBlock & operator()(U x) + { + PutWord(A, B::ToEnum(), m_block, (T)x, m_xorBlock); + m_block += sizeof(T); + if (m_xorBlock) + m_xorBlock += sizeof(T); + return *this; + } + +private: + const byte *m_xorBlock; + byte *m_block; +}; + +template +struct BlockGetAndPut +{ + // function needed because of C++ grammatical ambiguity between expression-statements and declarations + static inline GetBlock Get(const void *block) {return GetBlock(block);} + typedef PutBlock Put; +}; + +template +std::string WordToString(T value, ByteOrder order = BIG_ENDIAN_ORDER) +{ + if (!NativeByteOrderIs(order)) + value = ByteReverse(value); + + return std::string((char *)&value, sizeof(value)); +} + +template +T StringToWord(const std::string &str, ByteOrder order = BIG_ENDIAN_ORDER) +{ + T value = 0; + memcpy_s(&value, sizeof(value), str.data(), UnsignedMin(str.size(), sizeof(value))); + return NativeByteOrderIs(order) ? value : ByteReverse(value); +} + +// ************** help remove warning on g++ *************** + +template struct SafeShifter; + +template<> struct SafeShifter +{ + template + static inline T RightShift(T value, unsigned int bits) + { + return 0; + } + + template + static inline T LeftShift(T value, unsigned int bits) + { + return 0; + } +}; + +template<> struct SafeShifter +{ + template + static inline T RightShift(T value, unsigned int bits) + { + return value >> bits; + } + + template + static inline T LeftShift(T value, unsigned int bits) + { + return value << bits; + } +}; + +template +inline T SafeRightShift(T value) +{ + return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits); +} + +template +inline T SafeLeftShift(T value) +{ + return SafeShifter<(bits>=(8*sizeof(T)))>::LeftShift(value, bits); +} + +// ************** use one buffer for multiple data members *************** + +#define CRYPTOPP_BLOCK_1(n, t, s) t* m_##n() {return (t *)(m_aggregate+0);} size_t SS1() {return sizeof(t)*(s);} size_t m_##n##Size() {return (s);} +#define CRYPTOPP_BLOCK_2(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS1());} size_t SS2() {return SS1()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} +#define CRYPTOPP_BLOCK_3(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS2());} size_t SS3() {return SS2()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} +#define CRYPTOPP_BLOCK_4(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS3());} size_t SS4() {return SS3()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} +#define CRYPTOPP_BLOCK_5(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS4());} size_t SS5() {return SS4()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} +#define CRYPTOPP_BLOCK_6(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS5());} size_t SS6() {return SS5()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} +#define CRYPTOPP_BLOCK_7(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS6());} size_t SS7() {return SS6()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} +#define CRYPTOPP_BLOCK_8(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS7());} size_t SS8() {return SS7()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);} +#define CRYPTOPP_BLOCKS_END(i) size_t SST() {return SS##i();} void AllocateBlocks() {m_aggregate.New(SST());} AlignedSecByteBlock m_aggregate; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/modarith.h b/src-cryptopp/modarith.h new file mode 100644 index 0000000..c0368e3 --- /dev/null +++ b/src-cryptopp/modarith.h @@ -0,0 +1,158 @@ +#ifndef CRYPTOPP_MODARITH_H +#define CRYPTOPP_MODARITH_H + +// implementations are in integer.cpp + +#include "cryptlib.h" +#include "misc.h" +#include "integer.h" +#include "algebra.h" + +NAMESPACE_BEGIN(CryptoPP) + +CRYPTOPP_DLL_TEMPLATE_CLASS AbstractGroup; +CRYPTOPP_DLL_TEMPLATE_CLASS AbstractRing; +CRYPTOPP_DLL_TEMPLATE_CLASS AbstractEuclideanDomain; + +//! ring of congruence classes modulo n +/*! \note this implementation represents each congruence class as the smallest non-negative integer in that class */ +class CRYPTOPP_DLL ModularArithmetic : public AbstractRing +{ +public: + + typedef int RandomizationParameter; + typedef Integer Element; + + ModularArithmetic(const Integer &modulus = Integer::One()) + : m_modulus(modulus), m_result((word)0, modulus.reg.size()) {} + + ModularArithmetic(const ModularArithmetic &ma) + : m_modulus(ma.m_modulus), m_result((word)0, m_modulus.reg.size()) {} + + ModularArithmetic(BufferedTransformation &bt); // construct from BER encoded parameters + + virtual ModularArithmetic * Clone() const {return new ModularArithmetic(*this);} + + void DEREncode(BufferedTransformation &bt) const; + + void DEREncodeElement(BufferedTransformation &out, const Element &a) const; + void BERDecodeElement(BufferedTransformation &in, Element &a) const; + + const Integer& GetModulus() const {return m_modulus;} + void SetModulus(const Integer &newModulus) {m_modulus = newModulus; m_result.reg.resize(m_modulus.reg.size());} + + virtual bool IsMontgomeryRepresentation() const {return false;} + + virtual Integer ConvertIn(const Integer &a) const + {return a%m_modulus;} + + virtual Integer ConvertOut(const Integer &a) const + {return a;} + + const Integer& Half(const Integer &a) const; + + bool Equal(const Integer &a, const Integer &b) const + {return a==b;} + + const Integer& Identity() const + {return Integer::Zero();} + + const Integer& Add(const Integer &a, const Integer &b) const; + + Integer& Accumulate(Integer &a, const Integer &b) const; + + const Integer& Inverse(const Integer &a) const; + + const Integer& Subtract(const Integer &a, const Integer &b) const; + + Integer& Reduce(Integer &a, const Integer &b) const; + + const Integer& Double(const Integer &a) const + {return Add(a, a);} + + const Integer& MultiplicativeIdentity() const + {return Integer::One();} + + const Integer& Multiply(const Integer &a, const Integer &b) const + {return m_result1 = a*b%m_modulus;} + + const Integer& Square(const Integer &a) const + {return m_result1 = a.Squared()%m_modulus;} + + bool IsUnit(const Integer &a) const + {return Integer::Gcd(a, m_modulus).IsUnit();} + + const Integer& MultiplicativeInverse(const Integer &a) const + {return m_result1 = a.InverseMod(m_modulus);} + + const Integer& Divide(const Integer &a, const Integer &b) const + {return Multiply(a, MultiplicativeInverse(b));} + + Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const; + + void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const; + + unsigned int MaxElementBitLength() const + {return (m_modulus-1).BitCount();} + + unsigned int MaxElementByteLength() const + {return (m_modulus-1).ByteCount();} + + Element RandomElement( RandomNumberGenerator &rng , const RandomizationParameter &ignore_for_now = 0 ) const + // left RandomizationParameter arg as ref in case RandomizationParameter becomes a more complicated struct + { + return Element( rng , Integer( (long) 0) , m_modulus - Integer( (long) 1 ) ) ; + } + + bool operator==(const ModularArithmetic &rhs) const + {return m_modulus == rhs.m_modulus;} + + static const RandomizationParameter DefaultRandomizationParameter ; + +protected: + Integer m_modulus; + mutable Integer m_result, m_result1; + +}; + +// const ModularArithmetic::RandomizationParameter ModularArithmetic::DefaultRandomizationParameter = 0 ; + +//! do modular arithmetics in Montgomery representation for increased speed +/*! \note the Montgomery representation represents each congruence class [a] as a*r%n, where r is a convenient power of 2 */ +class CRYPTOPP_DLL MontgomeryRepresentation : public ModularArithmetic +{ +public: + MontgomeryRepresentation(const Integer &modulus); // modulus must be odd + + virtual ModularArithmetic * Clone() const {return new MontgomeryRepresentation(*this);} + + bool IsMontgomeryRepresentation() const {return true;} + + Integer ConvertIn(const Integer &a) const + {return (a<<(WORD_BITS*m_modulus.reg.size()))%m_modulus;} + + Integer ConvertOut(const Integer &a) const; + + const Integer& MultiplicativeIdentity() const + {return m_result1 = Integer::Power2(WORD_BITS*m_modulus.reg.size())%m_modulus;} + + const Integer& Multiply(const Integer &a, const Integer &b) const; + + const Integer& Square(const Integer &a) const; + + const Integer& MultiplicativeInverse(const Integer &a) const; + + Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const + {return AbstractRing::CascadeExponentiate(x, e1, y, e2);} + + void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const + {AbstractRing::SimultaneousExponentiate(results, base, exponents, exponentsCount);} + +private: + Integer m_u; + mutable IntegerSecBlock m_workspace; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/modes.cpp b/src-cryptopp/modes.cpp new file mode 100644 index 0000000..81bf4de --- /dev/null +++ b/src-cryptopp/modes.cpp @@ -0,0 +1,243 @@ +// modes.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "modes.h" + +#ifndef NDEBUG +#include "des.h" +#endif + +NAMESPACE_BEGIN(CryptoPP) + +#ifndef NDEBUG +void Modes_TestInstantiations() +{ + CFB_Mode::Encryption m0; + CFB_Mode::Decryption m1; + OFB_Mode::Encryption m2; + CTR_Mode::Encryption m3; + ECB_Mode::Encryption m4; + CBC_Mode::Encryption m5; +} +#endif + +void CFB_ModePolicy::Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount) +{ + assert(m_cipher->IsForwardTransformation()); // CFB mode needs the "encrypt" direction of the underlying block cipher, even to decrypt + assert(m_feedbackSize == BlockSize()); + + unsigned int s = BlockSize(); + if (dir == ENCRYPTION) + { + m_cipher->ProcessAndXorBlock(m_register, input, output); + m_cipher->AdvancedProcessBlocks(output, input+s, output+s, (iterationCount-1)*s, 0); + memcpy(m_register, output+(iterationCount-1)*s, s); + } + else + { + memcpy(m_temp, input+(iterationCount-1)*s, s); // make copy first in case of in-place decryption + m_cipher->AdvancedProcessBlocks(input, input+s, output+s, (iterationCount-1)*s, BlockTransformation::BT_ReverseDirection); + m_cipher->ProcessAndXorBlock(m_register, input, output); + memcpy(m_register, m_temp, s); + } +} + +void CFB_ModePolicy::TransformRegister() +{ + assert(m_cipher->IsForwardTransformation()); // CFB mode needs the "encrypt" direction of the underlying block cipher, even to decrypt + m_cipher->ProcessBlock(m_register, m_temp); + unsigned int updateSize = BlockSize()-m_feedbackSize; + memmove_s(m_register, m_register.size(), m_register+m_feedbackSize, updateSize); + memcpy_s(m_register+updateSize, m_register.size()-updateSize, m_temp, m_feedbackSize); +} + +void CFB_ModePolicy::CipherResynchronize(const byte *iv, size_t length) +{ + memcpy_s(m_register, m_register.size(), iv, BlockSize()); + TransformRegister(); +} + +void CFB_ModePolicy::SetFeedbackSize(unsigned int feedbackSize) +{ + if (feedbackSize > BlockSize()) + throw InvalidArgument("CFB_Mode: invalid feedback size"); + m_feedbackSize = feedbackSize ? feedbackSize : BlockSize(); +} + +void CFB_ModePolicy::ResizeBuffers() +{ + CipherModeBase::ResizeBuffers(); + m_temp.New(BlockSize()); +} + +void OFB_ModePolicy::WriteKeystream(byte *keystreamBuffer, size_t iterationCount) +{ + assert(m_cipher->IsForwardTransformation()); // OFB mode needs the "encrypt" direction of the underlying block cipher, even to decrypt + unsigned int s = BlockSize(); + m_cipher->ProcessBlock(m_register, keystreamBuffer); + if (iterationCount > 1) + m_cipher->AdvancedProcessBlocks(keystreamBuffer, NULL, keystreamBuffer+s, s*(iterationCount-1), 0); + memcpy(m_register, keystreamBuffer+s*(iterationCount-1), s); +} + +void OFB_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) +{ + CopyOrZero(m_register, iv, length); +} + +void CTR_ModePolicy::SeekToIteration(lword iterationCount) +{ + int carry=0; + for (int i=BlockSize()-1; i>=0; i--) + { + unsigned int sum = m_register[i] + byte(iterationCount) + carry; + m_counterArray[i] = (byte) sum; + carry = sum >> 8; + iterationCount >>= 8; + } +} + +void CTR_ModePolicy::IncrementCounterBy256() +{ + IncrementCounterByOne(m_counterArray, BlockSize()-1); +} + +void CTR_ModePolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) +{ + assert(m_cipher->IsForwardTransformation()); // CTR mode needs the "encrypt" direction of the underlying block cipher, even to decrypt + unsigned int s = BlockSize(); + unsigned int inputIncrement = input ? s : 0; + + while (iterationCount) + { + byte lsb = m_counterArray[s-1]; + size_t blocks = UnsignedMin(iterationCount, 256U-lsb); + m_cipher->AdvancedProcessBlocks(m_counterArray, input, output, blocks*s, BlockTransformation::BT_InBlockIsCounter); + if ((m_counterArray[s-1] = lsb + (byte)blocks) == 0) + IncrementCounterBy256(); + + output += blocks*s; + input += blocks*inputIncrement; + iterationCount -= blocks; + } +} + +void CTR_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) +{ + assert(length == BlockSize()); + CopyOrZero(m_register, iv, length); + m_counterArray = m_register; +} + +void BlockOrientedCipherModeBase::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) +{ + m_cipher->SetKey(key, length, params); + ResizeBuffers(); + if (IsResynchronizable()) + { + size_t ivLength; + const byte *iv = GetIVAndThrowIfInvalid(params, ivLength); + Resynchronize(iv, (int)ivLength); + } +} + +void ECB_OneWay::ProcessData(byte *outString, const byte *inString, size_t length) +{ + assert(length%BlockSize()==0); + m_cipher->AdvancedProcessBlocks(inString, NULL, outString, length, 0); +} + +void CBC_Encryption::ProcessData(byte *outString, const byte *inString, size_t length) +{ + if (!length) + return; + assert(length%BlockSize()==0); + + unsigned int blockSize = BlockSize(); + m_cipher->AdvancedProcessBlocks(inString, m_register, outString, blockSize, BlockTransformation::BT_XorInput); + if (length > blockSize) + m_cipher->AdvancedProcessBlocks(inString+blockSize, outString, outString+blockSize, length-blockSize, BlockTransformation::BT_XorInput); + memcpy(m_register, outString + length - blockSize, blockSize); +} + +void CBC_CTS_Encryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length) +{ + if (length <= BlockSize()) + { + if (!m_stolenIV) + throw InvalidArgument("CBC_Encryption: message is too short for ciphertext stealing"); + + // steal from IV + memcpy(outString, m_register, length); + outString = m_stolenIV; + } + else + { + // steal from next to last block + xorbuf(m_register, inString, BlockSize()); + m_cipher->ProcessBlock(m_register); + inString += BlockSize(); + length -= BlockSize(); + memcpy(outString+BlockSize(), m_register, length); + } + + // output last full ciphertext block + xorbuf(m_register, inString, length); + m_cipher->ProcessBlock(m_register); + memcpy(outString, m_register, BlockSize()); +} + +void CBC_Decryption::ProcessData(byte *outString, const byte *inString, size_t length) +{ + if (!length) + return; + assert(length%BlockSize()==0); + + unsigned int blockSize = BlockSize(); + memcpy(m_temp, inString+length-blockSize, blockSize); // save copy now in case of in-place decryption + if (length > blockSize) + m_cipher->AdvancedProcessBlocks(inString+blockSize, inString, outString+blockSize, length-blockSize, BlockTransformation::BT_ReverseDirection); + m_cipher->ProcessAndXorBlock(inString, m_register, outString); + m_register.swap(m_temp); +} + +void CBC_CTS_Decryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length) +{ + const byte *pn, *pn1; + bool stealIV = length <= BlockSize(); + + if (stealIV) + { + pn = inString; + pn1 = m_register; + } + else + { + pn = inString + BlockSize(); + pn1 = inString; + length -= BlockSize(); + } + + // decrypt last partial plaintext block + memcpy(m_temp, pn1, BlockSize()); + m_cipher->ProcessBlock(m_temp); + xorbuf(m_temp, pn, length); + + if (stealIV) + memcpy(outString, m_temp, length); + else + { + memcpy(outString+BlockSize(), m_temp, length); + // decrypt next to last plaintext block + memcpy(m_temp, pn, length); + m_cipher->ProcessBlock(m_temp); + xorbuf(outString, m_temp, m_register, BlockSize()); + } +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/modes.h b/src-cryptopp/modes.h new file mode 100644 index 0000000..ff88d31 --- /dev/null +++ b/src-cryptopp/modes.h @@ -0,0 +1,421 @@ +#ifndef CRYPTOPP_MODES_H +#define CRYPTOPP_MODES_H + +/*! \file +*/ + +#include "cryptlib.h" +#include "secblock.h" +#include "misc.h" +#include "strciphr.h" +#include "argnames.h" +#include "algparam.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! Cipher modes documentation. See NIST SP 800-38A for definitions of these modes. See AuthenticatedSymmetricCipherDocumentation for authenticated encryption modes. + +/*! Each class derived from this one defines two types, Encryption and Decryption, + both of which implement the SymmetricCipher interface. + For each mode there are two classes, one of which is a template class, + and the other one has a name that ends in "_ExternalCipher". + The "external cipher" mode objects hold a reference to the underlying block cipher, + instead of holding an instance of it. The reference must be passed in to the constructor. + For the "cipher holder" classes, the CIPHER template parameter should be a class + derived from BlockCipherDocumentation, for example DES or AES. +*/ +struct CipherModeDocumentation : public SymmetricCipherDocumentation +{ +}; + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CipherModeBase : public SymmetricCipher +{ +public: + size_t MinKeyLength() const {return m_cipher->MinKeyLength();} + size_t MaxKeyLength() const {return m_cipher->MaxKeyLength();} + size_t DefaultKeyLength() const {return m_cipher->DefaultKeyLength();} + size_t GetValidKeyLength(size_t n) const {return m_cipher->GetValidKeyLength(n);} + bool IsValidKeyLength(size_t n) const {return m_cipher->IsValidKeyLength(n);} + + unsigned int OptimalDataAlignment() const {return m_cipher->OptimalDataAlignment();} + + unsigned int IVSize() const {return BlockSize();} + virtual IV_Requirement IVRequirement() const =0; + + void SetCipher(BlockCipher &cipher) + { + this->ThrowIfResynchronizable(); + this->m_cipher = &cipher; + this->ResizeBuffers(); + } + + void SetCipherWithIV(BlockCipher &cipher, const byte *iv, int feedbackSize = 0) + { + this->ThrowIfInvalidIV(iv); + this->m_cipher = &cipher; + this->ResizeBuffers(); + this->SetFeedbackSize(feedbackSize); + if (this->IsResynchronizable()) + this->Resynchronize(iv); + } + +protected: + CipherModeBase() : m_cipher(NULL) {} + inline unsigned int BlockSize() const {assert(m_register.size() > 0); return (unsigned int)m_register.size();} + virtual void SetFeedbackSize(unsigned int feedbackSize) + { + if (!(feedbackSize == 0 || feedbackSize == BlockSize())) + throw InvalidArgument("CipherModeBase: feedback size cannot be specified for this cipher mode"); + } + virtual void ResizeBuffers() + { + m_register.New(m_cipher->BlockSize()); + } + + BlockCipher *m_cipher; + AlignedSecByteBlock m_register; +}; + +template +class CRYPTOPP_NO_VTABLE ModePolicyCommonTemplate : public CipherModeBase, public POLICY_INTERFACE +{ + unsigned int GetAlignment() const {return m_cipher->OptimalDataAlignment();} + void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length); +}; + +template +void ModePolicyCommonTemplate::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) +{ + m_cipher->SetKey(key, length, params); + ResizeBuffers(); + int feedbackSize = params.GetIntValueWithDefault(Name::FeedbackSize(), 0); + SetFeedbackSize(feedbackSize); +} + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_ModePolicy : public ModePolicyCommonTemplate +{ +public: + IV_Requirement IVRequirement() const {return RANDOM_IV;} + static const char * CRYPTOPP_API StaticAlgorithmName() {return "CFB";} + +protected: + unsigned int GetBytesPerIteration() const {return m_feedbackSize;} + byte * GetRegisterBegin() {return m_register + BlockSize() - m_feedbackSize;} + bool CanIterate() const {return m_feedbackSize == BlockSize();} + void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount); + void TransformRegister(); + void CipherResynchronize(const byte *iv, size_t length); + void SetFeedbackSize(unsigned int feedbackSize); + void ResizeBuffers(); + + SecByteBlock m_temp; + unsigned int m_feedbackSize; +}; + +inline void CopyOrZero(void *dest, const void *src, size_t s) +{ + if (src) + memcpy_s(dest, s, src, s); + else + memset(dest, 0, s); +} + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE OFB_ModePolicy : public ModePolicyCommonTemplate +{ +public: + bool CipherIsRandomAccess() const {return false;} + IV_Requirement IVRequirement() const {return UNIQUE_IV;} + static const char * CRYPTOPP_API StaticAlgorithmName() {return "OFB";} + +private: + unsigned int GetBytesPerIteration() const {return BlockSize();} + unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();} + void WriteKeystream(byte *keystreamBuffer, size_t iterationCount); + void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length); +}; + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CTR_ModePolicy : public ModePolicyCommonTemplate +{ +public: + bool CipherIsRandomAccess() const {return true;} + IV_Requirement IVRequirement() const {return RANDOM_IV;} + static const char * CRYPTOPP_API StaticAlgorithmName() {return "CTR";} + +protected: + virtual void IncrementCounterBy256(); + + unsigned int GetAlignment() const {return m_cipher->OptimalDataAlignment();} + unsigned int GetBytesPerIteration() const {return BlockSize();} + unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();} + void WriteKeystream(byte *buffer, size_t iterationCount) + {OperateKeystream(WRITE_KEYSTREAM, buffer, NULL, iterationCount);} + bool CanOperateKeystream() const {return true;} + void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount); + void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length); + void SeekToIteration(lword iterationCount); + + AlignedSecByteBlock m_counterArray; +}; + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockOrientedCipherModeBase : public CipherModeBase +{ +public: + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); + unsigned int MandatoryBlockSize() const {return BlockSize();} + bool IsRandomAccess() const {return false;} + bool IsSelfInverting() const {return false;} + bool IsForwardTransformation() const {return m_cipher->IsForwardTransformation();} + void Resynchronize(const byte *iv, int length=-1) {memcpy_s(m_register, m_register.size(), iv, ThrowIfInvalidIVLength(length));} + +protected: + bool RequireAlignedInput() const {return true;} + void ResizeBuffers() + { + CipherModeBase::ResizeBuffers(); + m_buffer.New(BlockSize()); + } + + SecByteBlock m_buffer; +}; + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ECB_OneWay : public BlockOrientedCipherModeBase +{ +public: + void SetKey(const byte *key, size_t length, const NameValuePairs ¶ms = g_nullNameValuePairs) + {m_cipher->SetKey(key, length, params); BlockOrientedCipherModeBase::ResizeBuffers();} + IV_Requirement IVRequirement() const {return NOT_RESYNCHRONIZABLE;} + unsigned int OptimalBlockSize() const {return BlockSize() * m_cipher->OptimalNumberOfParallelBlocks();} + void ProcessData(byte *outString, const byte *inString, size_t length); + static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECB";} +}; + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_ModeBase : public BlockOrientedCipherModeBase +{ +public: + IV_Requirement IVRequirement() const {return UNPREDICTABLE_RANDOM_IV;} + bool RequireAlignedInput() const {return false;} + unsigned int MinLastBlockSize() const {return 0;} + static const char * CRYPTOPP_API StaticAlgorithmName() {return "CBC";} +}; + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Encryption : public CBC_ModeBase +{ +public: + void ProcessData(byte *outString, const byte *inString, size_t length); +}; + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Encryption : public CBC_Encryption +{ +public: + void SetStolenIV(byte *iv) {m_stolenIV = iv;} + unsigned int MinLastBlockSize() const {return BlockSize()+1;} + void ProcessLastBlock(byte *outString, const byte *inString, size_t length); + static const char * CRYPTOPP_API StaticAlgorithmName() {return "CBC/CTS";} + +protected: + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) + { + CBC_Encryption::UncheckedSetKey(key, length, params); + m_stolenIV = params.GetValueWithDefault(Name::StolenIV(), (byte *)NULL); + } + + byte *m_stolenIV; +}; + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Decryption : public CBC_ModeBase +{ +public: + void ProcessData(byte *outString, const byte *inString, size_t length); + +protected: + void ResizeBuffers() + { + BlockOrientedCipherModeBase::ResizeBuffers(); + m_temp.New(BlockSize()); + } + AlignedSecByteBlock m_temp; +}; + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Decryption : public CBC_Decryption +{ +public: + unsigned int MinLastBlockSize() const {return BlockSize()+1;} + void ProcessLastBlock(byte *outString, const byte *inString, size_t length); +}; + +//! _ +template +class CipherModeFinalTemplate_CipherHolder : protected ObjectHolder, public AlgorithmImpl > +{ +public: + CipherModeFinalTemplate_CipherHolder() + { + this->m_cipher = &this->m_object; + this->ResizeBuffers(); + } + CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length) + { + this->m_cipher = &this->m_object; + this->SetKey(key, length); + } + CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length, const byte *iv) + { + this->m_cipher = &this->m_object; + this->SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, this->m_cipher->BlockSize()))); + } + CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length, const byte *iv, int feedbackSize) + { + this->m_cipher = &this->m_object; + this->SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, this->m_cipher->BlockSize()))(Name::FeedbackSize(), feedbackSize)); + } + + static std::string CRYPTOPP_API StaticAlgorithmName() + {return CIPHER::StaticAlgorithmName() + "/" + BASE::StaticAlgorithmName();} +}; + +//! _ +template +class CipherModeFinalTemplate_ExternalCipher : public BASE +{ +public: + CipherModeFinalTemplate_ExternalCipher() {} + CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher) + {this->SetCipher(cipher);} + CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher, const byte *iv, int feedbackSize = 0) + {this->SetCipherWithIV(cipher, iv, feedbackSize);} + + std::string AlgorithmName() const + {return (this->m_cipher ? this->m_cipher->AlgorithmName() + "/" : std::string("")) + BASE::StaticAlgorithmName();} +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate >; +CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate >; +CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate >; + +//! CFB mode +template +struct CFB_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder > > > Encryption; + typedef CipherModeFinalTemplate_CipherHolder > > > Decryption; +}; + +//! CFB mode, external cipher +struct CFB_Mode_ExternalCipher : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_ExternalCipher > > > Encryption; + typedef CipherModeFinalTemplate_ExternalCipher > > > Decryption; +}; + +//! CFB mode FIPS variant, requiring full block plaintext according to FIPS 800-38A +template +struct CFB_FIPS_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder > > > > Encryption; + typedef CipherModeFinalTemplate_CipherHolder > > > > Decryption; +}; + +//! CFB mode FIPS variant, requiring full block plaintext according to FIPS 800-38A, external cipher +struct CFB_FIPS_Mode_ExternalCipher : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_ExternalCipher > > > > Encryption; + typedef CipherModeFinalTemplate_ExternalCipher > > > > Decryption; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate >; + +//! OFB mode +template +struct OFB_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder > > > Encryption; + typedef Encryption Decryption; +}; + +//! OFB mode, external cipher +struct OFB_Mode_ExternalCipher : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_ExternalCipher > > > Encryption; + typedef Encryption Decryption; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate >; + +//! CTR mode +template +struct CTR_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder > > > Encryption; + typedef Encryption Decryption; +}; + +//! CTR mode, external cipher +struct CTR_Mode_ExternalCipher : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_ExternalCipher > > > Encryption; + typedef Encryption Decryption; +}; + +//! ECB mode +template +struct ECB_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder Encryption; + typedef CipherModeFinalTemplate_CipherHolder Decryption; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher; + +//! ECB mode, external cipher +struct ECB_Mode_ExternalCipher : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_ExternalCipher Encryption; + typedef Encryption Decryption; +}; + +//! CBC mode +template +struct CBC_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder Encryption; + typedef CipherModeFinalTemplate_CipherHolder Decryption; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher; +CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher; + +//! CBC mode, external cipher +struct CBC_Mode_ExternalCipher : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_ExternalCipher Encryption; + typedef CipherModeFinalTemplate_ExternalCipher Decryption; +}; + +//! CBC mode with ciphertext stealing +template +struct CBC_CTS_Mode : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_CipherHolder Encryption; + typedef CipherModeFinalTemplate_CipherHolder Decryption; +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher; +CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher; + +//! CBC mode with ciphertext stealing, external cipher +struct CBC_CTS_Mode_ExternalCipher : public CipherModeDocumentation +{ + typedef CipherModeFinalTemplate_ExternalCipher Encryption; + typedef CipherModeFinalTemplate_ExternalCipher Decryption; +}; + +#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY +typedef CFB_Mode_ExternalCipher::Encryption CFBEncryption; +typedef CFB_Mode_ExternalCipher::Decryption CFBDecryption; +typedef OFB_Mode_ExternalCipher::Encryption OFB; +typedef CTR_Mode_ExternalCipher::Encryption CounterMode; +#endif + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/modexppc.h b/src-cryptopp/modexppc.h new file mode 100644 index 0000000..fbe7012 --- /dev/null +++ b/src-cryptopp/modexppc.h @@ -0,0 +1,34 @@ +#ifndef CRYPTOPP_MODEXPPC_H +#define CRYPTOPP_MODEXPPC_H + +#include "modarith.h" +#include "eprecomp.h" +#include "smartptr.h" +#include "pubkey.h" + +NAMESPACE_BEGIN(CryptoPP) + +CRYPTOPP_DLL_TEMPLATE_CLASS DL_FixedBasePrecomputationImpl; + +class ModExpPrecomputation : public DL_GroupPrecomputation +{ +public: + // DL_GroupPrecomputation + bool NeedConversions() const {return true;} + Element ConvertIn(const Element &v) const {return m_mr->ConvertIn(v);} + virtual Element ConvertOut(const Element &v) const {return m_mr->ConvertOut(v);} + const AbstractGroup & GetGroup() const {return m_mr->MultiplicativeGroup();} + Element BERDecodeElement(BufferedTransformation &bt) const {return Integer(bt);} + void DEREncodeElement(BufferedTransformation &bt, const Element &v) const {v.DEREncode(bt);} + + // non-inherited + void SetModulus(const Integer &v) {m_mr.reset(new MontgomeryRepresentation(v));} + const Integer & GetModulus() const {return m_mr->GetModulus();} + +private: + value_ptr m_mr; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/mqueue.cpp b/src-cryptopp/mqueue.cpp new file mode 100644 index 0000000..1d645d8 --- /dev/null +++ b/src-cryptopp/mqueue.cpp @@ -0,0 +1,174 @@ +// mqueue.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "mqueue.h" + +NAMESPACE_BEGIN(CryptoPP) + +MessageQueue::MessageQueue(unsigned int nodeSize) + : m_queue(nodeSize), m_lengths(1, 0U), m_messageCounts(1, 0U) +{ +} + +size_t MessageQueue::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const +{ + if (begin >= MaxRetrievable()) + return 0; + + return m_queue.CopyRangeTo2(target, begin, STDMIN(MaxRetrievable(), end), channel, blocking); +} + +size_t MessageQueue::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) +{ + transferBytes = STDMIN(MaxRetrievable(), transferBytes); + size_t blockedBytes = m_queue.TransferTo2(target, transferBytes, channel, blocking); + m_lengths.front() -= transferBytes; + return blockedBytes; +} + +bool MessageQueue::GetNextMessage() +{ + if (NumberOfMessages() > 0 && !AnyRetrievable()) + { + m_lengths.pop_front(); + if (m_messageCounts[0] == 0 && m_messageCounts.size() > 1) + m_messageCounts.pop_front(); + return true; + } + else + return false; +} + +unsigned int MessageQueue::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const +{ + ByteQueue::Walker walker(m_queue); + std::deque::const_iterator it = m_lengths.begin(); + unsigned int i; + for (i=0; i 0 && q2.AnyRetrievable()) + { + size_t len = length; + const byte *data = q2.Spy(len); + len = STDMIN(len, length); + if (memcmp(inString, data, len) != 0) + goto mismatch; + inString += len; + length -= len; + q2.Skip(len); + } + + q1.Put(inString, length); + + if (messageEnd) + { + if (q2.AnyRetrievable()) + goto mismatch; + else if (q2.AnyMessages()) + q2.GetNextMessage(); + else if (q2.NumberOfMessageSeries() > 0) + goto mismatch; + else + q1.MessageEnd(); + } + + return 0; + +mismatch: + return HandleMismatchDetected(blocking); + } +} + +bool EqualityComparisonFilter::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking) +{ + unsigned int i = MapChannel(channel); + + if (i == 2) + { + OutputMessageSeriesEnd(4, propagation, blocking, channel); + return false; + } + else if (m_mismatchDetected) + return false; + else + { + MessageQueue &q1 = m_q[i], &q2 = m_q[1-i]; + + if (q2.AnyRetrievable() || q2.AnyMessages()) + goto mismatch; + else if (q2.NumberOfMessageSeries() > 0) + return Output(2, (const byte *)"\1", 1, 0, blocking) != 0; + else + q1.MessageSeriesEnd(); + + return false; + +mismatch: + return HandleMismatchDetected(blocking); + } +} + +bool EqualityComparisonFilter::HandleMismatchDetected(bool blocking) +{ + m_mismatchDetected = true; + if (m_throwIfNotEqual) + throw MismatchDetected(); + return Output(1, (const byte *)"\0", 1, 0, blocking) != 0; +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/mqueue.h b/src-cryptopp/mqueue.h new file mode 100644 index 0000000..efa57a7 --- /dev/null +++ b/src-cryptopp/mqueue.h @@ -0,0 +1,100 @@ +#ifndef CRYPTOPP_MQUEUE_H +#define CRYPTOPP_MQUEUE_H + +#include "queue.h" +#include "filters.h" +#include + +NAMESPACE_BEGIN(CryptoPP) + +//! Message Queue +class CRYPTOPP_DLL MessageQueue : public AutoSignaling +{ +public: + MessageQueue(unsigned int nodeSize=256); + + void IsolatedInitialize(const NameValuePairs ¶meters) + {m_queue.IsolatedInitialize(parameters); m_lengths.assign(1, 0U); m_messageCounts.assign(1, 0U);} + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking) + { + m_queue.Put(begin, length); + m_lengths.back() += length; + if (messageEnd) + { + m_lengths.push_back(0); + m_messageCounts.back()++; + } + return 0; + } + bool IsolatedFlush(bool hardFlush, bool blocking) {return false;} + bool IsolatedMessageSeriesEnd(bool blocking) + {m_messageCounts.push_back(0); return false;} + + lword MaxRetrievable() const + {return m_lengths.front();} + bool AnyRetrievable() const + {return m_lengths.front() > 0;} + + size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); + size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const; + + lword TotalBytesRetrievable() const + {return m_queue.MaxRetrievable();} + unsigned int NumberOfMessages() const + {return (unsigned int)m_lengths.size()-1;} + bool GetNextMessage(); + + unsigned int NumberOfMessagesInThisSeries() const + {return m_messageCounts[0];} + unsigned int NumberOfMessageSeries() const + {return (unsigned int)m_messageCounts.size()-1;} + + unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL) const; + + const byte * Spy(size_t &contiguousSize) const; + + void swap(MessageQueue &rhs); + +private: + ByteQueue m_queue; + std::deque m_lengths; + std::deque m_messageCounts; +}; + + +//! A filter that checks messages on two channels for equality +class CRYPTOPP_DLL EqualityComparisonFilter : public Unflushable > +{ +public: + struct MismatchDetected : public Exception {MismatchDetected() : Exception(DATA_INTEGRITY_CHECK_FAILED, "EqualityComparisonFilter: did not receive the same data on two channels") {}}; + + /*! if throwIfNotEqual is false, this filter will output a '\\0' byte when it detects a mismatch, '\\1' otherwise */ + EqualityComparisonFilter(BufferedTransformation *attachment=NULL, bool throwIfNotEqual=true, const std::string &firstChannel="0", const std::string &secondChannel="1") + : m_throwIfNotEqual(throwIfNotEqual), m_mismatchDetected(false) + , m_firstChannel(firstChannel), m_secondChannel(secondChannel) + {Detach(attachment);} + + size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking); + bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true); + +private: + unsigned int MapChannel(const std::string &channel) const; + bool HandleMismatchDetected(bool blocking); + + bool m_throwIfNotEqual, m_mismatchDetected; + std::string m_firstChannel, m_secondChannel; + MessageQueue m_q[2]; +}; + +NAMESPACE_END + +#ifndef __BORLANDC__ +NAMESPACE_BEGIN(std) +template<> inline void swap(CryptoPP::MessageQueue &a, CryptoPP::MessageQueue &b) +{ + a.swap(b); +} +NAMESPACE_END +#endif + +#endif diff --git a/src-cryptopp/mqv.h b/src-cryptopp/mqv.h new file mode 100644 index 0000000..2683817 --- /dev/null +++ b/src-cryptopp/mqv.h @@ -0,0 +1,141 @@ +#ifndef CRYPTOPP_MQV_H +#define CRYPTOPP_MQV_H + +/** \file +*/ + +#include "gfpcrypt.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! _ +template +class MQV_Domain : public AuthenticatedKeyAgreementDomain +{ +public: + typedef GROUP_PARAMETERS GroupParameters; + typedef typename GroupParameters::Element Element; + typedef MQV_Domain Domain; + + MQV_Domain() {} + + MQV_Domain(const GroupParameters ¶ms) + : m_groupParameters(params) {} + + MQV_Domain(BufferedTransformation &bt) + {m_groupParameters.BERDecode(bt);} + + template + MQV_Domain(T1 v1, T2 v2) + {m_groupParameters.Initialize(v1, v2);} + + template + MQV_Domain(T1 v1, T2 v2, T3 v3) + {m_groupParameters.Initialize(v1, v2, v3);} + + template + MQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4) + {m_groupParameters.Initialize(v1, v2, v3, v4);} + + const GroupParameters & GetGroupParameters() const {return m_groupParameters;} + GroupParameters & AccessGroupParameters() {return m_groupParameters;} + + CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();} + + unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);} + unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();} + unsigned int StaticPublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);} + + void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const + { + Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent()); + x.Encode(privateKey, StaticPrivateKeyLength()); + } + + void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const + { + const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); + Integer x(privateKey, StaticPrivateKeyLength()); + Element y = params.ExponentiateBase(x); + params.EncodeElement(true, y, publicKey); + } + + unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();} + unsigned int EphemeralPublicKeyLength() const {return StaticPublicKeyLength();} + + void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const + { + const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); + Integer x(rng, Integer::One(), params.GetMaxExponent()); + x.Encode(privateKey, StaticPrivateKeyLength()); + Element y = params.ExponentiateBase(x); + params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength()); + } + + void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const + { + memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength()); + } + + bool Agree(byte *agreedValue, + const byte *staticPrivateKey, const byte *ephemeralPrivateKey, + const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey, + bool validateStaticOtherPublicKey=true) const + { + try + { + const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); + Element WW = params.DecodeElement(staticOtherPublicKey, validateStaticOtherPublicKey); + Element VV = params.DecodeElement(ephemeralOtherPublicKey, true); + + Integer s(staticPrivateKey, StaticPrivateKeyLength()); + Integer u(ephemeralPrivateKey, StaticPrivateKeyLength()); + Element V = params.DecodeElement(ephemeralPrivateKey+StaticPrivateKeyLength(), false); + + const Integer &r = params.GetSubgroupOrder(); + Integer h2 = Integer::Power2((r.BitCount()+1)/2); + Integer e = ((h2+params.ConvertElementToInteger(V)%h2)*s+u) % r; + Integer tt = h2 + params.ConvertElementToInteger(VV) % h2; + + if (COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION) + { + Element P = params.ExponentiateElement(WW, tt); + P = m_groupParameters.MultiplyElements(P, VV); + Element R[2]; + const Integer e2[2] = {r, e}; + params.SimultaneousExponentiate(R, P, e2, 2); + if (!params.IsIdentity(R[0]) || params.IsIdentity(R[1])) + return false; + params.EncodeElement(false, R[1], agreedValue); + } + else + { + const Integer &k = params.GetCofactor(); + if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION) + e = ModularArithmetic(r).Divide(e, k); + Element P = m_groupParameters.CascadeExponentiate(VV, k*e, WW, k*(e*tt%r)); + if (params.IsIdentity(P)) + return false; + params.EncodeElement(false, P, agreedValue); + } + } + catch (DL_BadElement &) + { + return false; + } + return true; + } + +private: + DL_GroupParameters & AccessAbstractGroupParameters() {return m_groupParameters;} + const DL_GroupParameters & GetAbstractGroupParameters() const {return m_groupParameters;} + + GroupParameters m_groupParameters; +}; + +//! Menezes-Qu-Vanstone in GF(p) with key validation, AKA MQV +typedef MQV_Domain MQV; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/nbtheory.cpp b/src-cryptopp/nbtheory.cpp new file mode 100644 index 0000000..3fdea4e --- /dev/null +++ b/src-cryptopp/nbtheory.cpp @@ -0,0 +1,1123 @@ +// nbtheory.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "nbtheory.h" +#include "modarith.h" +#include "algparam.h" + +#include +#include + +#ifdef _OPENMP +// needed in MSVC 2005 to generate correct manifest +#include +#endif + +NAMESPACE_BEGIN(CryptoPP) + +const word s_lastSmallPrime = 32719; + +struct NewPrimeTable +{ + std::vector * operator()() const + { + const unsigned int maxPrimeTableSize = 3511; + + std::auto_ptr > pPrimeTable(new std::vector); + std::vector &primeTable = *pPrimeTable; + primeTable.reserve(maxPrimeTableSize); + + primeTable.push_back(2); + unsigned int testEntriesEnd = 1; + + for (unsigned int p=3; p<=s_lastSmallPrime; p+=2) + { + unsigned int j; + for (j=1; j &primeTable = Singleton, NewPrimeTable>().Ref(); + size = (unsigned int)primeTable.size(); + return &primeTable[0]; +} + +bool IsSmallPrime(const Integer &p) +{ + unsigned int primeTableSize; + const word16 * primeTable = GetPrimeTable(primeTableSize); + + if (p.IsPositive() && p <= primeTable[primeTableSize-1]) + return std::binary_search(primeTable, primeTable+primeTableSize, (word16)p.ConvertToLong()); + else + return false; +} + +bool TrialDivision(const Integer &p, unsigned bound) +{ + unsigned int primeTableSize; + const word16 * primeTable = GetPrimeTable(primeTableSize); + + assert(primeTable[primeTableSize-1] >= bound); + + unsigned int i; + for (i = 0; primeTable[i]3 && b>1 && b3 && b>1 && b>a; + + Integer z = a_exp_b_mod_c(b, m, n); + if (z==1 || z==nminus1) + return true; + for (unsigned j=1; j3); + + Integer b; + for (unsigned int i=0; i2); + + Integer b=3; + unsigned int i=0; + int j; + + while ((j=Jacobi(b.Squared()-4, n)) == 1) + { + if (++i==64 && n.IsSquare()) // avoid infinite loop if n is a square + return false; + ++b; ++b; + } + + if (j==0) + return false; + else + return Lucas(n+1, b, n)==2; +} + +bool IsStrongLucasProbablePrime(const Integer &n) +{ + if (n <= 1) + return false; + + if (n.IsEven()) + return n==2; + + assert(n>2); + + Integer b=3; + unsigned int i=0; + int j; + + while ((j=Jacobi(b.Squared()-4, n)) == 1) + { + if (++i==64 && n.IsSquare()) // avoid infinite loop if n is a square + return false; + ++b; ++b; + } + + if (j==0) + return false; + + Integer n1 = n+1; + unsigned int a; + + // calculate a = largest power of 2 that divides n1 + for (a=0; ; a++) + if (n1.GetBit(a)) + break; + Integer m = n1>>a; + + Integer z = Lucas(m, b, n); + if (z==2 || z==n-2) + return true; + for (i=1; i().Ref()) + return SmallDivisorsTest(p); + else + return SmallDivisorsTest(p) && IsStrongProbablePrime(p, 3) && IsStrongLucasProbablePrime(p); +} + +bool VerifyPrime(RandomNumberGenerator &rng, const Integer &p, unsigned int level) +{ + bool pass = IsPrime(p) && RabinMillerTest(rng, p, 1); + if (level >= 1) + pass = pass && RabinMillerTest(rng, p, 10); + return pass; +} + +unsigned int PrimeSearchInterval(const Integer &max) +{ + return max.BitCount(); +} + +static inline bool FastProbablePrimeTest(const Integer &n) +{ + return IsStrongProbablePrime(n,2); +} + +AlgorithmParameters MakeParametersForTwoPrimesOfEqualSize(unsigned int productBitLength) +{ + if (productBitLength < 16) + throw InvalidArgument("invalid bit length"); + + Integer minP, maxP; + + if (productBitLength%2==0) + { + minP = Integer(182) << (productBitLength/2-8); + maxP = Integer::Power2(productBitLength/2)-1; + } + else + { + minP = Integer::Power2((productBitLength-1)/2); + maxP = Integer(181) << ((productBitLength+1)/2-8); + } + + return MakeParameters("RandomNumberType", Integer::PRIME)("Min", minP)("Max", maxP); +} + +class PrimeSieve +{ +public: + // delta == 1 or -1 means double sieve with p = 2*q + delta + PrimeSieve(const Integer &first, const Integer &last, const Integer &step, signed int delta=0); + bool NextCandidate(Integer &c); + + void DoSieve(); + static void SieveSingle(std::vector &sieve, word16 p, const Integer &first, const Integer &step, word16 stepInv); + + Integer m_first, m_last, m_step; + signed int m_delta; + word m_next; + std::vector m_sieve; +}; + +PrimeSieve::PrimeSieve(const Integer &first, const Integer &last, const Integer &step, signed int delta) + : m_first(first), m_last(last), m_step(step), m_delta(delta), m_next(0) +{ + DoSieve(); +} + +bool PrimeSieve::NextCandidate(Integer &c) +{ + bool safe = SafeConvert(std::find(m_sieve.begin()+m_next, m_sieve.end(), false) - m_sieve.begin(), m_next); + assert(safe); + if (m_next == m_sieve.size()) + { + m_first += long(m_sieve.size())*m_step; + if (m_first > m_last) + return false; + else + { + m_next = 0; + DoSieve(); + return NextCandidate(c); + } + } + else + { + c = m_first + long(m_next)*m_step; + ++m_next; + return true; + } +} + +void PrimeSieve::SieveSingle(std::vector &sieve, word16 p, const Integer &first, const Integer &step, word16 stepInv) +{ + if (stepInv) + { + size_t sieveSize = sieve.size(); + size_t j = (word32(p-(first%p))*stepInv) % p; + // if the first multiple of p is p, skip it + if (first.WordCount() <= 1 && first + step*long(j) == p) + j += p; + for (; j < sieveSize; j += p) + sieve[j] = true; + } +} + +void PrimeSieve::DoSieve() +{ + unsigned int primeTableSize; + const word16 * primeTable = GetPrimeTable(primeTableSize); + + const unsigned int maxSieveSize = 32768; + unsigned int sieveSize = STDMIN(Integer(maxSieveSize), (m_last-m_first)/m_step+1).ConvertToLong(); + + m_sieve.clear(); + m_sieve.resize(sieveSize, false); + + if (m_delta == 0) + { + for (unsigned int i = 0; i < primeTableSize; ++i) + SieveSingle(m_sieve, primeTable[i], m_first, m_step, (word16)m_step.InverseMod(primeTable[i])); + } + else + { + assert(m_step%2==0); + Integer qFirst = (m_first-m_delta) >> 1; + Integer halfStep = m_step >> 1; + for (unsigned int i = 0; i < primeTableSize; ++i) + { + word16 p = primeTable[i]; + word16 stepInv = (word16)m_step.InverseMod(p); + SieveSingle(m_sieve, p, m_first, m_step, stepInv); + + word16 halfStepInv = 2*stepInv < p ? 2*stepInv : 2*stepInv-p; + SieveSingle(m_sieve, p, qFirst, halfStep, halfStepInv); + } + } +} + +bool FirstPrime(Integer &p, const Integer &max, const Integer &equiv, const Integer &mod, const PrimeSelector *pSelector) +{ + assert(!equiv.IsNegative() && equiv < mod); + + Integer gcd = GCD(equiv, mod); + if (gcd != Integer::One()) + { + // the only possible prime p such that p%mod==equiv where GCD(mod,equiv)!=1 is GCD(mod,equiv) + if (p <= gcd && gcd <= max && IsPrime(gcd) && (!pSelector || pSelector->IsAcceptable(gcd))) + { + p = gcd; + return true; + } + else + return false; + } + + unsigned int primeTableSize; + const word16 * primeTable = GetPrimeTable(primeTableSize); + + if (p <= primeTable[primeTableSize-1]) + { + const word16 *pItr; + + --p; + if (p.IsPositive()) + pItr = std::upper_bound(primeTable, primeTable+primeTableSize, (word)p.ConvertToLong()); + else + pItr = primeTable; + + while (pItr < primeTable+primeTableSize && !(*pItr%mod == equiv && (!pSelector || pSelector->IsAcceptable(*pItr)))) + ++pItr; + + if (pItr < primeTable+primeTableSize) + { + p = *pItr; + return p <= max; + } + + p = primeTable[primeTableSize-1]+1; + } + + assert(p > primeTable[primeTableSize-1]); + + if (mod.IsOdd()) + return FirstPrime(p, max, CRT(equiv, mod, 1, 2, 1), mod<<1, pSelector); + + p += (equiv-p)%mod; + + if (p>max) + return false; + + PrimeSieve sieve(p, max, mod); + + while (sieve.NextCandidate(p)) + { + if ((!pSelector || pSelector->IsAcceptable(p)) && FastProbablePrimeTest(p) && IsPrime(p)) + return true; + } + + return false; +} + +// the following two functions are based on code and comments provided by Preda Mihailescu +static bool ProvePrime(const Integer &p, const Integer &q) +{ + assert(p < q*q*q); + assert(p % q == 1); + +// this is the Quisquater test. Numbers p having passed the Lucas - Lehmer test +// for q and verifying p < q^3 can only be built up of two factors, both = 1 mod q, +// or be prime. The next two lines build the discriminant of a quadratic equation +// which holds iff p is built up of two factors (excercise ... ) + + Integer r = (p-1)/q; + if (((r%q).Squared()-4*(r/q)).IsSquare()) + return false; + + unsigned int primeTableSize; + const word16 * primeTable = GetPrimeTable(primeTableSize); + + assert(primeTableSize >= 50); + for (int i=0; i<50; i++) + { + Integer b = a_exp_b_mod_c(primeTable[i], r, p); + if (b != 1) + return a_exp_b_mod_c(b, q, p) == 1; + } + return false; +} + +Integer MihailescuProvablePrime(RandomNumberGenerator &rng, unsigned int pbits) +{ + Integer p; + Integer minP = Integer::Power2(pbits-1); + Integer maxP = Integer::Power2(pbits) - 1; + + if (maxP <= Integer(s_lastSmallPrime).Squared()) + { + // Randomize() will generate a prime provable by trial division + p.Randomize(rng, minP, maxP, Integer::PRIME); + return p; + } + + unsigned int qbits = (pbits+2)/3 + 1 + rng.GenerateWord32(0, pbits/36); + Integer q = MihailescuProvablePrime(rng, qbits); + Integer q2 = q<<1; + + while (true) + { + // this initializes the sieve to search in the arithmetic + // progression p = p_0 + \lambda * q2 = p_0 + 2 * \lambda * q, + // with q the recursively generated prime above. We will be able + // to use Lucas tets for proving primality. A trick of Quisquater + // allows taking q > cubic_root(p) rather then square_root: this + // decreases the recursion. + + p.Randomize(rng, minP, maxP, Integer::ANY, 1, q2); + PrimeSieve sieve(p, STDMIN(p+PrimeSearchInterval(maxP)*q2, maxP), q2); + + while (sieve.NextCandidate(p)) + { + if (FastProbablePrimeTest(p) && ProvePrime(p, q)) + return p; + } + } + + // not reached + return p; +} + +Integer MaurerProvablePrime(RandomNumberGenerator &rng, unsigned int bits) +{ + const unsigned smallPrimeBound = 29, c_opt=10; + Integer p; + + unsigned int primeTableSize; + const word16 * primeTable = GetPrimeTable(primeTableSize); + + if (bits < smallPrimeBound) + { + do + p.Randomize(rng, Integer::Power2(bits-1), Integer::Power2(bits)-1, Integer::ANY, 1, 2); + while (TrialDivision(p, 1 << ((bits+1)/2))); + } + else + { + const unsigned margin = bits > 50 ? 20 : (bits-10)/2; + double relativeSize; + do + relativeSize = pow(2.0, double(rng.GenerateWord32())/0xffffffff - 1); + while (bits * relativeSize >= bits - margin); + + Integer a,b; + Integer q = MaurerProvablePrime(rng, unsigned(bits*relativeSize)); + Integer I = Integer::Power2(bits-2)/q; + Integer I2 = I << 1; + unsigned int trialDivisorBound = (unsigned int)STDMIN((unsigned long)primeTable[primeTableSize-1], (unsigned long)bits*bits/c_opt); + bool success = false; + while (!success) + { + p.Randomize(rng, I, I2, Integer::ANY); + p *= q; p <<= 1; ++p; + if (!TrialDivision(p, trialDivisorBound)) + { + a.Randomize(rng, 2, p-1, Integer::ANY); + b = a_exp_b_mod_c(a, (p-1)/q, p); + success = (GCD(b-1, p) == 1) && (a_exp_b_mod_c(b, q, p) == 1); + } + } + } + return p; +} + +Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q, const Integer &u) +{ + // isn't operator overloading great? + return p * (u * (xq-xp) % q) + xp; +/* + Integer t1 = xq-xp; + cout << hex << t1 << endl; + Integer t2 = u * t1; + cout << hex << t2 << endl; + Integer t3 = t2 % q; + cout << hex << t3 << endl; + Integer t4 = p * t3; + cout << hex << t4 << endl; + Integer t5 = t4 + xp; + cout << hex << t5 << endl; + return t5; +*/ +} + +Integer ModularSquareRoot(const Integer &a, const Integer &p) +{ + if (p%4 == 3) + return a_exp_b_mod_c(a, (p+1)/4, p); + + Integer q=p-1; + unsigned int r=0; + while (q.IsEven()) + { + r++; + q >>= 1; + } + + Integer n=2; + while (Jacobi(n, p) != -1) + ++n; + + Integer y = a_exp_b_mod_c(n, q, p); + Integer x = a_exp_b_mod_c(a, (q-1)/2, p); + Integer b = (x.Squared()%p)*a%p; + x = a*x%p; + Integer tempb, t; + + while (b != 1) + { + unsigned m=0; + tempb = b; + do + { + m++; + b = b.Squared()%p; + if (m==r) + return Integer::Zero(); + } + while (b != 1); + + t = y; + for (unsigned i=0; i>= 1; + b >>= 1; + k++; + } + + while (a[0]==0) + a >>= 1; + + while (b[0]==0) + b >>= 1; + + while (1) + { + switch (a.Compare(b)) + { + case -1: + b -= a; + while (b[0]==0) + b >>= 1; + break; + + case 0: + return (a <<= k); + + case 1: + a -= b; + while (a[0]==0) + a >>= 1; + break; + + default: + assert(false); + } + } +} + +Integer EuclideanMultiplicativeInverse(const Integer &a, const Integer &b) +{ + assert(b.Positive()); + + if (a.Negative()) + return EuclideanMultiplicativeInverse(a%b, b); + + if (b[0]==0) + { + if (!b || a[0]==0) + return Integer::Zero(); // no inverse + if (a==1) + return 1; + Integer u = EuclideanMultiplicativeInverse(b, a); + if (!u) + return Integer::Zero(); // no inverse + else + return (b*(a-u)+1)/a; + } + + Integer u=1, d=a, v1=b, v3=b, t1, t3, b2=(b+1)>>1; + + if (a[0]) + { + t1 = Integer::Zero(); + t3 = -b; + } + else + { + t1 = b2; + t3 = a>>1; + } + + while (!!t3) + { + while (t3[0]==0) + { + t3 >>= 1; + if (t1[0]==0) + t1 >>= 1; + else + { + t1 >>= 1; + t1 += b2; + } + } + if (t3.Positive()) + { + u = t1; + d = t3; + } + else + { + v1 = b-t1; + v3 = -t3; + } + t1 = u-v1; + t3 = d-v3; + if (t1.Negative()) + t1 += b; + } + if (d==1) + return u; + else + return Integer::Zero(); // no inverse +} +*/ + +int Jacobi(const Integer &aIn, const Integer &bIn) +{ + assert(bIn.IsOdd()); + + Integer b = bIn, a = aIn%bIn; + int result = 1; + + while (!!a) + { + unsigned i=0; + while (a.GetBit(i)==0) + i++; + a>>=i; + + if (i%2==1 && (b%8==3 || b%8==5)) + result = -result; + + if (a%4==3 && b%4==3) + result = -result; + + std::swap(a, b); + a %= b; + } + + return (b==1) ? result : 0; +} + +Integer Lucas(const Integer &e, const Integer &pIn, const Integer &n) +{ + unsigned i = e.BitCount(); + if (i==0) + return Integer::Two(); + + MontgomeryRepresentation m(n); + Integer p=m.ConvertIn(pIn%n), two=m.ConvertIn(Integer::Two()); + Integer v=p, v1=m.Subtract(m.Square(p), two); + + i--; + while (i--) + { + if (e.GetBit(i)) + { + // v = (v*v1 - p) % m; + v = m.Subtract(m.Multiply(v,v1), p); + // v1 = (v1*v1 - 2) % m; + v1 = m.Subtract(m.Square(v1), two); + } + else + { + // v1 = (v*v1 - p) % m; + v1 = m.Subtract(m.Multiply(v,v1), p); + // v = (v*v - 2) % m; + v = m.Subtract(m.Square(v), two); + } + } + return m.ConvertOut(v); +} + +// This is Peter Montgomery's unpublished Lucas sequence evalutation algorithm. +// The total number of multiplies and squares used is less than the binary +// algorithm (see above). Unfortunately I can't get it to run as fast as +// the binary algorithm because of the extra overhead. +/* +Integer Lucas(const Integer &n, const Integer &P, const Integer &modulus) +{ + if (!n) + return 2; + +#define f(A, B, C) m.Subtract(m.Multiply(A, B), C) +#define X2(A) m.Subtract(m.Square(A), two) +#define X3(A) m.Multiply(A, m.Subtract(m.Square(A), three)) + + MontgomeryRepresentation m(modulus); + Integer two=m.ConvertIn(2), three=m.ConvertIn(3); + Integer A=m.ConvertIn(P), B, C, p, d=n, e, r, t, T, U; + + while (d!=1) + { + p = d; + unsigned int b = WORD_BITS * p.WordCount(); + Integer alpha = (Integer(5)<<(2*b-2)).SquareRoot() - Integer::Power2(b-1); + r = (p*alpha)>>b; + e = d-r; + B = A; + C = two; + d = r; + + while (d!=e) + { + if (d>2)) + if ((dm3+em3==0 || dm3+em3==3) && (t = e, t >>= 2, t += e, d <= t)) + { + // #1 +// t = (d+d-e)/3; +// t = d; t += d; t -= e; t /= 3; +// e = (e+e-d)/3; +// e += e; e -= d; e /= 3; +// d = t; + +// t = (d+e)/3 + t = d; t += e; t /= 3; + e -= t; + d -= t; + + T = f(A, B, C); + U = f(T, A, B); + B = f(T, B, A); + A = U; + continue; + } + +// if (dm6 == em6 && d <= e + (e>>2)) + if (dm3 == em3 && dm2 == em2 && (t = e, t >>= 2, t += e, d <= t)) + { + // #2 +// d = (d-e)>>1; + d -= e; d >>= 1; + B = f(A, B, C); + A = X2(A); + continue; + } + +// if (d <= (e<<2)) + if (d <= (t = e, t <<= 2)) + { + // #3 + d -= e; + C = f(A, B, C); + swap(B, C); + continue; + } + + if (dm2 == em2) + { + // #4 +// d = (d-e)>>1; + d -= e; d >>= 1; + B = f(A, B, C); + A = X2(A); + continue; + } + + if (dm2 == 0) + { + // #5 + d >>= 1; + C = f(A, C, B); + A = X2(A); + continue; + } + + if (dm3 == 0) + { + // #6 +// d = d/3 - e; + d /= 3; d -= e; + T = X2(A); + C = f(T, f(A, B, C), C); + swap(B, C); + A = f(T, A, A); + continue; + } + + if (dm3+em3==0 || dm3+em3==3) + { + // #7 +// d = (d-e-e)/3; + d -= e; d -= e; d /= 3; + T = f(A, B, C); + B = f(T, A, B); + A = X3(A); + continue; + } + + if (dm3 == em3) + { + // #8 +// d = (d-e)/3; + d -= e; d /= 3; + T = f(A, B, C); + C = f(A, C, B); + B = T; + A = X3(A); + continue; + } + + assert(em2 == 0); + // #9 + e >>= 1; + C = f(C, B, A); + B = X2(B); + } + + A = f(A, B, C); + } + +#undef f +#undef X2 +#undef X3 + + return m.ConvertOut(A); +} +*/ + +Integer InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q, const Integer &u) +{ + Integer d = (m*m-4); + Integer p2, q2; + #pragma omp parallel + #pragma omp sections + { + #pragma omp section + { + p2 = p-Jacobi(d,p); + p2 = Lucas(EuclideanMultiplicativeInverse(e,p2), m, p); + } + #pragma omp section + { + q2 = q-Jacobi(d,q); + q2 = Lucas(EuclideanMultiplicativeInverse(e,q2), m, q); + } + } + return CRT(p2, p, q2, q, u); +} + +unsigned int FactoringWorkFactor(unsigned int n) +{ + // extrapolated from the table in Odlyzko's "The Future of Integer Factorization" + // updated to reflect the factoring of RSA-130 + if (n<5) return 0; + else return (unsigned int)(2.4 * pow((double)n, 1.0/3.0) * pow(log(double(n)), 2.0/3.0) - 5); +} + +unsigned int DiscreteLogWorkFactor(unsigned int n) +{ + // assuming discrete log takes about the same time as factoring + if (n<5) return 0; + else return (unsigned int)(2.4 * pow((double)n, 1.0/3.0) * pow(log(double(n)), 2.0/3.0) - 5); +} + +// ******************************************************** + +void PrimeAndGenerator::Generate(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned int qbits) +{ + // no prime exists for delta = -1, qbits = 4, and pbits = 5 + assert(qbits > 4); + assert(pbits > qbits); + + if (qbits+1 == pbits) + { + Integer minP = Integer::Power2(pbits-1); + Integer maxP = Integer::Power2(pbits) - 1; + bool success = false; + + while (!success) + { + p.Randomize(rng, minP, maxP, Integer::ANY, 6+5*delta, 12); + PrimeSieve sieve(p, STDMIN(p+PrimeSearchInterval(maxP)*12, maxP), 12, delta); + + while (sieve.NextCandidate(p)) + { + assert(IsSmallPrime(p) || SmallDivisorsTest(p)); + q = (p-delta) >> 1; + assert(IsSmallPrime(q) || SmallDivisorsTest(q)); + if (FastProbablePrimeTest(q) && FastProbablePrimeTest(p) && IsPrime(q) && IsPrime(p)) + { + success = true; + break; + } + } + } + + if (delta == 1) + { + // find g such that g is a quadratic residue mod p, then g has order q + // g=4 always works, but this way we get the smallest quadratic residue (other than 1) + for (g=2; Jacobi(g, p) != 1; ++g) {} + // contributed by Walt Tuvell: g should be the following according to the Law of Quadratic Reciprocity + assert((p%8==1 || p%8==7) ? g==2 : (p%12==1 || p%12==11) ? g==3 : g==4); + } + else + { + assert(delta == -1); + // find g such that g*g-4 is a quadratic non-residue, + // and such that g has order q + for (g=3; ; ++g) + if (Jacobi(g*g-4, p)==-1 && Lucas(q, g, p)==2) + break; + } + } + else + { + Integer minQ = Integer::Power2(qbits-1); + Integer maxQ = Integer::Power2(qbits) - 1; + Integer minP = Integer::Power2(pbits-1); + Integer maxP = Integer::Power2(pbits) - 1; + + do + { + q.Randomize(rng, minQ, maxQ, Integer::PRIME); + } while (!p.Randomize(rng, minP, maxP, Integer::PRIME, delta%q, q)); + + // find a random g of order q + if (delta==1) + { + do + { + Integer h(rng, 2, p-2, Integer::ANY); + g = a_exp_b_mod_c(h, (p-1)/q, p); + } while (g <= 1); + assert(a_exp_b_mod_c(g, q, p)==1); + } + else + { + assert(delta==-1); + do + { + Integer h(rng, 3, p-1, Integer::ANY); + if (Jacobi(h*h-4, p)==1) + continue; + g = Lucas((p+1)/q, h, p); + } while (g <= 2); + assert(Lucas(q, g, p) == 2); + } + } +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/nbtheory.h b/src-cryptopp/nbtheory.h new file mode 100644 index 0000000..6364792 --- /dev/null +++ b/src-cryptopp/nbtheory.h @@ -0,0 +1,131 @@ +// nbtheory.h - written and placed in the public domain by Wei Dai + +#ifndef CRYPTOPP_NBTHEORY_H +#define CRYPTOPP_NBTHEORY_H + +#include "integer.h" +#include "algparam.h" + +NAMESPACE_BEGIN(CryptoPP) + +// obtain pointer to small prime table and get its size +CRYPTOPP_DLL const word16 * CRYPTOPP_API GetPrimeTable(unsigned int &size); + +// ************ primality testing **************** + +// generate a provable prime +CRYPTOPP_DLL Integer CRYPTOPP_API MaurerProvablePrime(RandomNumberGenerator &rng, unsigned int bits); +CRYPTOPP_DLL Integer CRYPTOPP_API MihailescuProvablePrime(RandomNumberGenerator &rng, unsigned int bits); + +CRYPTOPP_DLL bool CRYPTOPP_API IsSmallPrime(const Integer &p); + +// returns true if p is divisible by some prime less than bound +// bound not be greater than the largest entry in the prime table +CRYPTOPP_DLL bool CRYPTOPP_API TrialDivision(const Integer &p, unsigned bound); + +// returns true if p is NOT divisible by small primes +CRYPTOPP_DLL bool CRYPTOPP_API SmallDivisorsTest(const Integer &p); + +// These is no reason to use these two, use the ones below instead +CRYPTOPP_DLL bool CRYPTOPP_API IsFermatProbablePrime(const Integer &n, const Integer &b); +CRYPTOPP_DLL bool CRYPTOPP_API IsLucasProbablePrime(const Integer &n); + +CRYPTOPP_DLL bool CRYPTOPP_API IsStrongProbablePrime(const Integer &n, const Integer &b); +CRYPTOPP_DLL bool CRYPTOPP_API IsStrongLucasProbablePrime(const Integer &n); + +// Rabin-Miller primality test, i.e. repeating the strong probable prime test +// for several rounds with random bases +CRYPTOPP_DLL bool CRYPTOPP_API RabinMillerTest(RandomNumberGenerator &rng, const Integer &w, unsigned int rounds); + +// primality test, used to generate primes +CRYPTOPP_DLL bool CRYPTOPP_API IsPrime(const Integer &p); + +// more reliable than IsPrime(), used to verify primes generated by others +CRYPTOPP_DLL bool CRYPTOPP_API VerifyPrime(RandomNumberGenerator &rng, const Integer &p, unsigned int level = 1); + +class CRYPTOPP_DLL PrimeSelector +{ +public: + const PrimeSelector *GetSelectorPointer() const {return this;} + virtual bool IsAcceptable(const Integer &candidate) const =0; +}; + +// use a fast sieve to find the first probable prime in {x | p<=x<=max and x%mod==equiv} +// returns true iff successful, value of p is undefined if no such prime exists +CRYPTOPP_DLL bool CRYPTOPP_API FirstPrime(Integer &p, const Integer &max, const Integer &equiv, const Integer &mod, const PrimeSelector *pSelector); + +CRYPTOPP_DLL unsigned int CRYPTOPP_API PrimeSearchInterval(const Integer &max); + +CRYPTOPP_DLL AlgorithmParameters CRYPTOPP_API MakeParametersForTwoPrimesOfEqualSize(unsigned int productBitLength); + +// ********** other number theoretic functions ************ + +inline Integer GCD(const Integer &a, const Integer &b) + {return Integer::Gcd(a,b);} +inline bool RelativelyPrime(const Integer &a, const Integer &b) + {return Integer::Gcd(a,b) == Integer::One();} +inline Integer LCM(const Integer &a, const Integer &b) + {return a/Integer::Gcd(a,b)*b;} +inline Integer EuclideanMultiplicativeInverse(const Integer &a, const Integer &b) + {return a.InverseMod(b);} + +// use Chinese Remainder Theorem to calculate x given x mod p and x mod q, and u = inverse of p mod q +CRYPTOPP_DLL Integer CRYPTOPP_API CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q, const Integer &u); + +// if b is prime, then Jacobi(a, b) returns 0 if a%b==0, 1 if a is quadratic residue mod b, -1 otherwise +// check a number theory book for what Jacobi symbol means when b is not prime +CRYPTOPP_DLL int CRYPTOPP_API Jacobi(const Integer &a, const Integer &b); + +// calculates the Lucas function V_e(p, 1) mod n +CRYPTOPP_DLL Integer CRYPTOPP_API Lucas(const Integer &e, const Integer &p, const Integer &n); +// calculates x such that m==Lucas(e, x, p*q), p q primes, u=inverse of p mod q +CRYPTOPP_DLL Integer CRYPTOPP_API InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q, const Integer &u); + +inline Integer ModularExponentiation(const Integer &a, const Integer &e, const Integer &m) + {return a_exp_b_mod_c(a, e, m);} +// returns x such that x*x%p == a, p prime +CRYPTOPP_DLL Integer CRYPTOPP_API ModularSquareRoot(const Integer &a, const Integer &p); +// returns x such that a==ModularExponentiation(x, e, p*q), p q primes, +// and e relatively prime to (p-1)*(q-1) +// dp=d%(p-1), dq=d%(q-1), (d is inverse of e mod (p-1)*(q-1)) +// and u=inverse of p mod q +CRYPTOPP_DLL Integer CRYPTOPP_API ModularRoot(const Integer &a, const Integer &dp, const Integer &dq, const Integer &p, const Integer &q, const Integer &u); + +// find r1 and r2 such that ax^2 + bx + c == 0 (mod p) for x in {r1, r2}, p prime +// returns true if solutions exist +CRYPTOPP_DLL bool CRYPTOPP_API SolveModularQuadraticEquation(Integer &r1, Integer &r2, const Integer &a, const Integer &b, const Integer &c, const Integer &p); + +// returns log base 2 of estimated number of operations to calculate discrete log or factor a number +CRYPTOPP_DLL unsigned int CRYPTOPP_API DiscreteLogWorkFactor(unsigned int bitlength); +CRYPTOPP_DLL unsigned int CRYPTOPP_API FactoringWorkFactor(unsigned int bitlength); + +// ******************************************************** + +//! generator of prime numbers of special forms +class CRYPTOPP_DLL PrimeAndGenerator +{ +public: + PrimeAndGenerator() {} + // generate a random prime p of the form 2*q+delta, where delta is 1 or -1 and q is also prime + // Precondition: pbits > 5 + // warning: this is slow, because primes of this form are harder to find + PrimeAndGenerator(signed int delta, RandomNumberGenerator &rng, unsigned int pbits) + {Generate(delta, rng, pbits, pbits-1);} + // generate a random prime p of the form 2*r*q+delta, where q is also prime + // Precondition: qbits > 4 && pbits > qbits + PrimeAndGenerator(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned qbits) + {Generate(delta, rng, pbits, qbits);} + + void Generate(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned qbits); + + const Integer& Prime() const {return p;} + const Integer& SubPrime() const {return q;} + const Integer& Generator() const {return g;} + +private: + Integer p, q, g; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/oaep.cpp b/src-cryptopp/oaep.cpp new file mode 100644 index 0000000..1d474be --- /dev/null +++ b/src-cryptopp/oaep.cpp @@ -0,0 +1,97 @@ +// oaep.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "oaep.h" +#include + +NAMESPACE_BEGIN(CryptoPP) + +// ******************************************************** + +size_t OAEP_Base::MaxUnpaddedLength(size_t paddedLength) const +{ + return SaturatingSubtract(paddedLength/8, 1+2*DigestSize()); +} + +void OAEP_Base::Pad(RandomNumberGenerator &rng, const byte *input, size_t inputLength, byte *oaepBlock, size_t oaepBlockLen, const NameValuePairs ¶meters) const +{ + assert (inputLength <= MaxUnpaddedLength(oaepBlockLen)); + + // convert from bit length to byte length + if (oaepBlockLen % 8 != 0) + { + oaepBlock[0] = 0; + oaepBlock++; + } + oaepBlockLen /= 8; + + std::auto_ptr pHash(NewHash()); + const size_t hLen = pHash->DigestSize(); + const size_t seedLen = hLen, dbLen = oaepBlockLen-seedLen; + byte *const maskedSeed = oaepBlock; + byte *const maskedDB = oaepBlock+seedLen; + + ConstByteArrayParameter encodingParameters; + parameters.GetValue(Name::EncodingParameters(), encodingParameters); + + // DB = pHash || 00 ... || 01 || M + pHash->CalculateDigest(maskedDB, encodingParameters.begin(), encodingParameters.size()); + memset(maskedDB+hLen, 0, dbLen-hLen-inputLength-1); + maskedDB[dbLen-inputLength-1] = 0x01; + memcpy(maskedDB+dbLen-inputLength, input, inputLength); + + rng.GenerateBlock(maskedSeed, seedLen); + std::auto_ptr pMGF(NewMGF()); + pMGF->GenerateAndMask(*pHash, maskedDB, dbLen, maskedSeed, seedLen); + pMGF->GenerateAndMask(*pHash, maskedSeed, seedLen, maskedDB, dbLen); +} + +DecodingResult OAEP_Base::Unpad(const byte *oaepBlock, size_t oaepBlockLen, byte *output, const NameValuePairs ¶meters) const +{ + bool invalid = false; + + // convert from bit length to byte length + if (oaepBlockLen % 8 != 0) + { + invalid = (oaepBlock[0] != 0) || invalid; + oaepBlock++; + } + oaepBlockLen /= 8; + + std::auto_ptr pHash(NewHash()); + const size_t hLen = pHash->DigestSize(); + const size_t seedLen = hLen, dbLen = oaepBlockLen-seedLen; + + invalid = (oaepBlockLen < 2*hLen+1) || invalid; + + SecByteBlock t(oaepBlock, oaepBlockLen); + byte *const maskedSeed = t; + byte *const maskedDB = t+seedLen; + + std::auto_ptr pMGF(NewMGF()); + pMGF->GenerateAndMask(*pHash, maskedSeed, seedLen, maskedDB, dbLen); + pMGF->GenerateAndMask(*pHash, maskedDB, dbLen, maskedSeed, seedLen); + + ConstByteArrayParameter encodingParameters; + parameters.GetValue(Name::EncodingParameters(), encodingParameters); + + // DB = pHash' || 00 ... || 01 || M + byte *M = std::find(maskedDB+hLen, maskedDB+dbLen, 0x01); + invalid = (M == maskedDB+dbLen) || invalid; + invalid = (std::find_if(maskedDB+hLen, M, std::bind2nd(std::not_equal_to(), 0)) != M) || invalid; + invalid = !pHash->VerifyDigest(maskedDB, encodingParameters.begin(), encodingParameters.size()) || invalid; + + if (invalid) + return DecodingResult(); + + M++; + memcpy(output, M, maskedDB+dbLen-M); + return DecodingResult(maskedDB+dbLen-M); +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/oaep.h b/src-cryptopp/oaep.h new file mode 100644 index 0000000..4bf6b0d --- /dev/null +++ b/src-cryptopp/oaep.h @@ -0,0 +1,42 @@ +#ifndef CRYPTOPP_OAEP_H +#define CRYPTOPP_OAEP_H + +#include "pubkey.h" +#include "sha.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! _ +class CRYPTOPP_DLL OAEP_Base : public PK_EncryptionMessageEncodingMethod +{ +public: + bool ParameterSupported(const char *name) const {return strcmp(name, Name::EncodingParameters()) == 0;} + size_t MaxUnpaddedLength(size_t paddedLength) const; + void Pad(RandomNumberGenerator &rng, const byte *raw, size_t inputLength, byte *padded, size_t paddedLength, const NameValuePairs ¶meters) const; + DecodingResult Unpad(const byte *padded, size_t paddedLength, byte *raw, const NameValuePairs ¶meters) const; + +protected: + virtual unsigned int DigestSize() const =0; + virtual HashTransformation * NewHash() const =0; + virtual MaskGeneratingFunction * NewMGF() const =0; +}; + +//! EME-OAEP, for use with classes derived from TF_ES +template +class OAEP : public OAEP_Base, public EncryptionStandard +{ +public: + static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string("OAEP-") + MGF::StaticAlgorithmName() + "(" + H::StaticAlgorithmName() + ")";} + typedef OAEP EncryptionMessageEncodingMethod; + +protected: + unsigned int DigestSize() const {return H::DIGESTSIZE;} + HashTransformation * NewHash() const {return new H;} + MaskGeneratingFunction * NewMGF() const {return new MGF;} +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS OAEP; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/oids.h b/src-cryptopp/oids.h new file mode 100644 index 0000000..9911ec2 --- /dev/null +++ b/src-cryptopp/oids.h @@ -0,0 +1,123 @@ +#ifndef CRYPTOPP_OIDS_H +#define CRYPTOPP_OIDS_H + +// crypto-related ASN.1 object identifiers + +#include "asn.h" + +NAMESPACE_BEGIN(CryptoPP) + +NAMESPACE_BEGIN(ASN1) + +#define DEFINE_OID(value, name) inline OID name() {return value;} + +DEFINE_OID(1, iso) + DEFINE_OID(iso()+2, member_body) + DEFINE_OID(member_body()+840, iso_us) + DEFINE_OID(iso_us()+10040, ansi_x9_57) + DEFINE_OID(ansi_x9_57()+4+1, id_dsa) + DEFINE_OID(iso_us()+10045, ansi_x9_62) + DEFINE_OID(ansi_x9_62()+1, id_fieldType) + DEFINE_OID(id_fieldType()+1, prime_field) + DEFINE_OID(id_fieldType()+2, characteristic_two_field) + DEFINE_OID(characteristic_two_field()+3, id_characteristic_two_basis) + DEFINE_OID(id_characteristic_two_basis()+1, gnBasis) + DEFINE_OID(id_characteristic_two_basis()+2, tpBasis) + DEFINE_OID(id_characteristic_two_basis()+3, ppBasis) + DEFINE_OID(ansi_x9_62()+2, id_publicKeyType) + DEFINE_OID(id_publicKeyType()+1, id_ecPublicKey) + DEFINE_OID(ansi_x9_62()+3, ansi_x9_62_curves) + DEFINE_OID(ansi_x9_62_curves()+1, ansi_x9_62_curves_prime) + DEFINE_OID(ansi_x9_62_curves_prime()+1, secp192r1) + DEFINE_OID(ansi_x9_62_curves_prime()+7, secp256r1) + DEFINE_OID(iso_us()+113549, rsadsi) + DEFINE_OID(rsadsi()+1, pkcs) + DEFINE_OID(pkcs()+1, pkcs_1) + DEFINE_OID(pkcs_1()+1, rsaEncryption); + DEFINE_OID(rsadsi()+2, rsadsi_digestAlgorithm) + DEFINE_OID(rsadsi_digestAlgorithm()+2, id_md2) + DEFINE_OID(rsadsi_digestAlgorithm()+5, id_md5) + DEFINE_OID(iso()+3, identified_organization); + DEFINE_OID(identified_organization()+14, oiw); + DEFINE_OID(oiw()+14, oiw_secsig); + DEFINE_OID(oiw_secsig()+2, oiw_secsig_algorithms); + DEFINE_OID(oiw_secsig_algorithms()+26, id_sha1); + + DEFINE_OID(identified_organization()+36, teletrust); + DEFINE_OID(teletrust()+3, teletrust_algorithm) + DEFINE_OID(teletrust_algorithm()+2+1, id_ripemd160) + DEFINE_OID(teletrust_algorithm()+3+2+8+1, teletrust_ellipticCurve) + DEFINE_OID(teletrust_ellipticCurve()+1+1, brainpoolP160r1) + DEFINE_OID(teletrust_ellipticCurve()+1+3, brainpoolP192r1) + DEFINE_OID(teletrust_ellipticCurve()+1+5, brainpoolP224r1) + DEFINE_OID(teletrust_ellipticCurve()+1+7, brainpoolP256r1) + DEFINE_OID(teletrust_ellipticCurve()+1+9, brainpoolP320r1) + DEFINE_OID(teletrust_ellipticCurve()+1+11, brainpoolP384r1) + DEFINE_OID(teletrust_ellipticCurve()+1+13, brainpoolP512r1) + + DEFINE_OID(identified_organization()+132, certicom); + DEFINE_OID(certicom()+0, certicom_ellipticCurve); + // these are sorted by curve type and then by OID + // first curves based on GF(p) + DEFINE_OID(certicom_ellipticCurve()+6, secp112r1); + DEFINE_OID(certicom_ellipticCurve()+7, secp112r2); + DEFINE_OID(certicom_ellipticCurve()+8, secp160r1); + DEFINE_OID(certicom_ellipticCurve()+9, secp160k1); + DEFINE_OID(certicom_ellipticCurve()+10, secp256k1); + DEFINE_OID(certicom_ellipticCurve()+28, secp128r1); + DEFINE_OID(certicom_ellipticCurve()+29, secp128r2); + DEFINE_OID(certicom_ellipticCurve()+30, secp160r2); + DEFINE_OID(certicom_ellipticCurve()+31, secp192k1); + DEFINE_OID(certicom_ellipticCurve()+32, secp224k1); + DEFINE_OID(certicom_ellipticCurve()+33, secp224r1); + DEFINE_OID(certicom_ellipticCurve()+34, secp384r1); + DEFINE_OID(certicom_ellipticCurve()+35, secp521r1); + // then curves based on GF(2^n) + DEFINE_OID(certicom_ellipticCurve()+1, sect163k1); + DEFINE_OID(certicom_ellipticCurve()+2, sect163r1); + DEFINE_OID(certicom_ellipticCurve()+3, sect239k1); + DEFINE_OID(certicom_ellipticCurve()+4, sect113r1); + DEFINE_OID(certicom_ellipticCurve()+5, sect113r2); + DEFINE_OID(certicom_ellipticCurve()+15, sect163r2); + DEFINE_OID(certicom_ellipticCurve()+16, sect283k1); + DEFINE_OID(certicom_ellipticCurve()+17, sect283r1); + DEFINE_OID(certicom_ellipticCurve()+22, sect131r1); + DEFINE_OID(certicom_ellipticCurve()+23, sect131r2); + DEFINE_OID(certicom_ellipticCurve()+24, sect193r1); + DEFINE_OID(certicom_ellipticCurve()+25, sect193r2); + DEFINE_OID(certicom_ellipticCurve()+26, sect233k1); + DEFINE_OID(certicom_ellipticCurve()+27, sect233r1); + DEFINE_OID(certicom_ellipticCurve()+36, sect409k1); + DEFINE_OID(certicom_ellipticCurve()+37, sect409r1); + DEFINE_OID(certicom_ellipticCurve()+38, sect571k1); + DEFINE_OID(certicom_ellipticCurve()+39, sect571r1); +DEFINE_OID(2, joint_iso_ccitt) + DEFINE_OID(joint_iso_ccitt()+16, country) + DEFINE_OID(country()+840, joint_iso_ccitt_us) + DEFINE_OID(joint_iso_ccitt_us()+1, us_organization) + DEFINE_OID(us_organization()+101, us_gov) + DEFINE_OID(us_gov()+3, csor) + DEFINE_OID(csor()+4, nistalgorithms) + DEFINE_OID(nistalgorithms()+1, aes) + DEFINE_OID(aes()+1, id_aes128_ECB) + DEFINE_OID(aes()+2, id_aes128_cbc) + DEFINE_OID(aes()+3, id_aes128_ofb) + DEFINE_OID(aes()+4, id_aes128_cfb) + DEFINE_OID(aes()+21, id_aes192_ECB) + DEFINE_OID(aes()+22, id_aes192_cbc) + DEFINE_OID(aes()+23, id_aes192_ofb) + DEFINE_OID(aes()+24, id_aes192_cfb) + DEFINE_OID(aes()+41, id_aes256_ECB) + DEFINE_OID(aes()+42, id_aes256_cbc) + DEFINE_OID(aes()+43, id_aes256_ofb) + DEFINE_OID(aes()+44, id_aes256_cfb) + DEFINE_OID(nistalgorithms()+2, nist_hashalgs) + DEFINE_OID(nist_hashalgs()+1, id_sha256) + DEFINE_OID(nist_hashalgs()+2, id_sha384) + DEFINE_OID(nist_hashalgs()+3, id_sha512) + +NAMESPACE_END + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/osrng.cpp b/src-cryptopp/osrng.cpp new file mode 100644 index 0000000..fa6dd36 --- /dev/null +++ b/src-cryptopp/osrng.cpp @@ -0,0 +1,171 @@ +// osrng.cpp - written and placed in the public domain by Wei Dai + +// Thanks to Leonard Janke for the suggestion for AutoSeededRandomPool. + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "osrng.h" + +#ifdef OS_RNG_AVAILABLE + +#include "rng.h" + +#ifdef CRYPTOPP_WIN32_AVAILABLE +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0400 +#endif +#include +#include +#endif + +#ifdef CRYPTOPP_UNIX_AVAILABLE +#include +#include +#include +#endif + +NAMESPACE_BEGIN(CryptoPP) + +#if defined(NONBLOCKING_RNG_AVAILABLE) || defined(BLOCKING_RNG_AVAILABLE) +OS_RNG_Err::OS_RNG_Err(const std::string &operation) + : Exception(OTHER_ERROR, "OS_Rng: " + operation + " operation failed with error " + +#ifdef CRYPTOPP_WIN32_AVAILABLE + "0x" + IntToString(GetLastError(), 16) +#else + IntToString(errno) +#endif + ) +{ +} +#endif + +#ifdef NONBLOCKING_RNG_AVAILABLE + +#ifdef CRYPTOPP_WIN32_AVAILABLE + +MicrosoftCryptoProvider::MicrosoftCryptoProvider() +{ + if(!CryptAcquireContext(&m_hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) + throw OS_RNG_Err("CryptAcquireContext"); +} + +MicrosoftCryptoProvider::~MicrosoftCryptoProvider() +{ + CryptReleaseContext(m_hProvider, 0); +} + +#endif + +NonblockingRng::NonblockingRng() +{ +#ifndef CRYPTOPP_WIN32_AVAILABLE + m_fd = open("/dev/urandom",O_RDONLY); + if (m_fd == -1) + throw OS_RNG_Err("open /dev/urandom"); +#endif +} + +NonblockingRng::~NonblockingRng() +{ +#ifndef CRYPTOPP_WIN32_AVAILABLE + close(m_fd); +#endif +} + +void NonblockingRng::GenerateBlock(byte *output, size_t size) +{ +#ifdef CRYPTOPP_WIN32_AVAILABLE +# ifdef WORKAROUND_MS_BUG_Q258000 + const MicrosoftCryptoProvider &m_Provider = Singleton().Ref(); +# endif + if (!CryptGenRandom(m_Provider.GetProviderHandle(), (DWORD)size, output)) + throw OS_RNG_Err("CryptGenRandom"); +#else + if (read(m_fd, output, size) != size) + throw OS_RNG_Err("read /dev/urandom"); +#endif +} + +#endif + +// ************************************************************* + +#ifdef BLOCKING_RNG_AVAILABLE + +#ifndef CRYPTOPP_BLOCKING_RNG_FILENAME +#ifdef __OpenBSD__ +#define CRYPTOPP_BLOCKING_RNG_FILENAME "/dev/srandom" +#else +#define CRYPTOPP_BLOCKING_RNG_FILENAME "/dev/random" +#endif +#endif + +BlockingRng::BlockingRng() +{ + m_fd = open(CRYPTOPP_BLOCKING_RNG_FILENAME,O_RDONLY); + if (m_fd == -1) + throw OS_RNG_Err("open " CRYPTOPP_BLOCKING_RNG_FILENAME); +} + +BlockingRng::~BlockingRng() +{ + close(m_fd); +} + +void BlockingRng::GenerateBlock(byte *output, size_t size) +{ + while (size) + { + // on some systems /dev/random will block until all bytes + // are available, on others it will returns immediately + ssize_t len = read(m_fd, output, size); + if (len < 0) + throw OS_RNG_Err("read " CRYPTOPP_BLOCKING_RNG_FILENAME); + size -= len; + output += len; + if (size) + sleep(1); + } +} + +#endif + +// ************************************************************* + +void OS_GenerateRandomBlock(bool blocking, byte *output, size_t size) +{ +#ifdef NONBLOCKING_RNG_AVAILABLE + if (blocking) +#endif + { +#ifdef BLOCKING_RNG_AVAILABLE + BlockingRng rng; + rng.GenerateBlock(output, size); +#endif + } + +#ifdef BLOCKING_RNG_AVAILABLE + if (!blocking) +#endif + { +#ifdef NONBLOCKING_RNG_AVAILABLE + NonblockingRng rng; + rng.GenerateBlock(output, size); +#endif + } +} + +void AutoSeededRandomPool::Reseed(bool blocking, unsigned int seedSize) +{ + SecByteBlock seed(seedSize); + OS_GenerateRandomBlock(blocking, seed, seedSize); + IncorporateEntropy(seed, seedSize); +} + +NAMESPACE_END + +#endif + +#endif diff --git a/src-cryptopp/osrng.h b/src-cryptopp/osrng.h new file mode 100644 index 0000000..eb4e6e2 --- /dev/null +++ b/src-cryptopp/osrng.h @@ -0,0 +1,153 @@ +#ifndef CRYPTOPP_OSRNG_H +#define CRYPTOPP_OSRNG_H + +#include "config.h" + +#ifdef OS_RNG_AVAILABLE + +#include "randpool.h" +#include "rng.h" +#include "aes.h" +#include "sha.h" +#include "fips140.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! Exception class for Operating-System Random Number Generator. +class CRYPTOPP_DLL OS_RNG_Err : public Exception +{ +public: + OS_RNG_Err(const std::string &operation); +}; + +#ifdef NONBLOCKING_RNG_AVAILABLE + +#ifdef CRYPTOPP_WIN32_AVAILABLE +class CRYPTOPP_DLL MicrosoftCryptoProvider +{ +public: + MicrosoftCryptoProvider(); + ~MicrosoftCryptoProvider(); +#if defined(_WIN64) + typedef unsigned __int64 ProviderHandle; // type HCRYPTPROV, avoid #include +#else + typedef unsigned long ProviderHandle; +#endif + ProviderHandle GetProviderHandle() const {return m_hProvider;} +private: + ProviderHandle m_hProvider; +}; + +#pragma comment(lib, "advapi32.lib") +#endif + +//! encapsulate CryptoAPI's CryptGenRandom or /dev/urandom +class CRYPTOPP_DLL NonblockingRng : public RandomNumberGenerator +{ +public: + NonblockingRng(); + ~NonblockingRng(); + void GenerateBlock(byte *output, size_t size); + +protected: +#ifdef CRYPTOPP_WIN32_AVAILABLE +# ifndef WORKAROUND_MS_BUG_Q258000 + MicrosoftCryptoProvider m_Provider; +# endif +#else + int m_fd; +#endif +}; + +#endif + +#ifdef BLOCKING_RNG_AVAILABLE + +//! encapsulate /dev/random, or /dev/srandom on OpenBSD +class CRYPTOPP_DLL BlockingRng : public RandomNumberGenerator +{ +public: + BlockingRng(); + ~BlockingRng(); + void GenerateBlock(byte *output, size_t size); + +protected: + int m_fd; +}; + +#endif + +CRYPTOPP_DLL void CRYPTOPP_API OS_GenerateRandomBlock(bool blocking, byte *output, size_t size); + +//! Automaticly Seeded Randomness Pool +/*! This class seeds itself using an operating system provided RNG. */ +class CRYPTOPP_DLL AutoSeededRandomPool : public RandomPool +{ +public: + //! use blocking to choose seeding with BlockingRng or NonblockingRng. the parameter is ignored if only one of these is available + explicit AutoSeededRandomPool(bool blocking = false, unsigned int seedSize = 32) + {Reseed(blocking, seedSize);} + void Reseed(bool blocking = false, unsigned int seedSize = 32); +}; + +//! RNG from ANSI X9.17 Appendix C, seeded using an OS provided RNG +template +class AutoSeededX917RNG : public RandomNumberGenerator, public NotCopyable +{ +public: + //! use blocking to choose seeding with BlockingRng or NonblockingRng. the parameter is ignored if only one of these is available + explicit AutoSeededX917RNG(bool blocking = false) + {Reseed(blocking);} + void Reseed(bool blocking = false, const byte *additionalEntropy = NULL, size_t length = 0); + // exposed for testing + void Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector); + + bool CanIncorporateEntropy() const {return true;} + void IncorporateEntropy(const byte *input, size_t length) {Reseed(false, input, length);} + void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length) {m_rng->GenerateIntoBufferedTransformation(target, channel, length);} + +private: + member_ptr m_rng; +}; + +template +void AutoSeededX917RNG::Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector) +{ + m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, keylength), seed, timeVector)); +} + +template +void AutoSeededX917RNG::Reseed(bool blocking, const byte *input, size_t length) +{ + SecByteBlock seed(BLOCK_CIPHER::BLOCKSIZE + BLOCK_CIPHER::DEFAULT_KEYLENGTH); + const byte *key; + do + { + OS_GenerateRandomBlock(blocking, seed, seed.size()); + if (length > 0) + { + SHA256 hash; + hash.Update(seed, seed.size()); + hash.Update(input, length); + hash.TruncatedFinal(seed, UnsignedMin(hash.DigestSize(), seed.size())); + } + key = seed + BLOCK_CIPHER::BLOCKSIZE; + } // check that seed and key don't have same value + while (memcmp(key, seed, STDMIN((unsigned int)BLOCK_CIPHER::BLOCKSIZE, (unsigned int)BLOCK_CIPHER::DEFAULT_KEYLENGTH)) == 0); + + Reseed(key, BLOCK_CIPHER::DEFAULT_KEYLENGTH, seed, NULL); +} + +CRYPTOPP_DLL_TEMPLATE_CLASS AutoSeededX917RNG; + +#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 +typedef AutoSeededX917RNG DefaultAutoSeededRNG; +#else +typedef AutoSeededRandomPool DefaultAutoSeededRNG; +#endif + +NAMESPACE_END + +#endif + +#endif diff --git a/src-cryptopp/pch.h b/src-cryptopp/pch.h new file mode 100644 index 0000000..418c390 --- /dev/null +++ b/src-cryptopp/pch.h @@ -0,0 +1,21 @@ +#ifndef CRYPTOPP_PCH_H +#define CRYPTOPP_PCH_H + +#ifdef CRYPTOPP_GENERATE_X64_MASM + + #include "cpu.h" + +#else + + #include "config.h" + + #ifdef USE_PRECOMPILED_HEADERS + #include "simple.h" + #include "secblock.h" + #include "misc.h" + #include "smartptr.h" + #endif + +#endif + +#endif diff --git a/src-cryptopp/pkcspad.cpp b/src-cryptopp/pkcspad.cpp new file mode 100644 index 0000000..e1f1d1e --- /dev/null +++ b/src-cryptopp/pkcspad.cpp @@ -0,0 +1,124 @@ +// pkcspad.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_PKCSPAD_CPP // SunCC workaround: compiler could cause this file to be included twice +#define CRYPTOPP_PKCSPAD_CPP + +#include "pkcspad.h" +#include + +NAMESPACE_BEGIN(CryptoPP) + +// more in dll.cpp +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x02,0x05,0x00,0x04,0x10}; +template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x04,0x10}; +template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x24,0x03,0x02,0x01,0x05,0x00,0x04,0x14}; +template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); + +template<> const byte PKCS_DigestDecoration::decoration[] = {0x30,0x29,0x30,0x0D,0x06,0x09,0x2B,0x06,0x01,0x04,0x01,0xDA,0x47,0x0C,0x02,0x05,0x00,0x04,0x18}; +template<> const unsigned int PKCS_DigestDecoration::length = sizeof(PKCS_DigestDecoration::decoration); + +size_t PKCS_EncryptionPaddingScheme::MaxUnpaddedLength(size_t paddedLength) const +{ + return SaturatingSubtract(paddedLength/8, 10U); +} + +void PKCS_EncryptionPaddingScheme::Pad(RandomNumberGenerator &rng, const byte *input, size_t inputLen, byte *pkcsBlock, size_t pkcsBlockLen, const NameValuePairs ¶meters) const +{ + assert (inputLen <= MaxUnpaddedLength(pkcsBlockLen)); // this should be checked by caller + + // convert from bit length to byte length + if (pkcsBlockLen % 8 != 0) + { + pkcsBlock[0] = 0; + pkcsBlock++; + } + pkcsBlockLen /= 8; + + pkcsBlock[0] = 2; // block type 2 + + // pad with non-zero random bytes + for (unsigned i = 1; i < pkcsBlockLen-inputLen-1; i++) + pkcsBlock[i] = (byte)rng.GenerateWord32(1, 0xff); + + pkcsBlock[pkcsBlockLen-inputLen-1] = 0; // separator + memcpy(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen); +} + +DecodingResult PKCS_EncryptionPaddingScheme::Unpad(const byte *pkcsBlock, size_t pkcsBlockLen, byte *output, const NameValuePairs ¶meters) const +{ + bool invalid = false; + size_t maxOutputLen = MaxUnpaddedLength(pkcsBlockLen); + + // convert from bit length to byte length + if (pkcsBlockLen % 8 != 0) + { + invalid = (pkcsBlock[0] != 0) || invalid; + pkcsBlock++; + } + pkcsBlockLen /= 8; + + // Require block type 2. + invalid = (pkcsBlock[0] != 2) || invalid; + + // skip past the padding until we find the separator + size_t i=1; + while (i maxOutputLen) || invalid; + + if (invalid) + return DecodingResult(); + + memcpy (output, pkcsBlock+i, outputLen); + return DecodingResult(outputLen); +} + +// ******************************************************** + +#ifndef CRYPTOPP_IMPORTS + +void PKCS1v15_SignatureMessageEncodingMethod::ComputeMessageRepresentative(RandomNumberGenerator &rng, + const byte *recoverableMessage, size_t recoverableMessageLength, + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const +{ + assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize())); + + size_t pkcsBlockLen = representativeBitLength; + // convert from bit length to byte length + if (pkcsBlockLen % 8 != 0) + { + representative[0] = 0; + representative++; + } + pkcsBlockLen /= 8; + + representative[0] = 1; // block type 1 + + unsigned int digestSize = hash.DigestSize(); + byte *pPadding = representative + 1; + byte *pDigest = representative + pkcsBlockLen - digestSize; + byte *pHashId = pDigest - hashIdentifier.second; + byte *pSeparator = pHashId - 1; + + // pad with 0xff + memset(pPadding, 0xff, pSeparator-pPadding); + *pSeparator = 0; + memcpy(pHashId, hashIdentifier.first, hashIdentifier.second); + hash.Final(pDigest); +} + +#endif + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/pkcspad.h b/src-cryptopp/pkcspad.h new file mode 100644 index 0000000..6371c76 --- /dev/null +++ b/src-cryptopp/pkcspad.h @@ -0,0 +1,94 @@ +#ifndef CRYPTOPP_PKCSPAD_H +#define CRYPTOPP_PKCSPAD_H + +#include "cryptlib.h" +#include "pubkey.h" + +#ifdef CRYPTOPP_IS_DLL +#include "sha.h" +#endif + +NAMESPACE_BEGIN(CryptoPP) + +//! EME-PKCS1-v1_5 +class PKCS_EncryptionPaddingScheme : public PK_EncryptionMessageEncodingMethod +{ +public: + static const char * StaticAlgorithmName() {return "EME-PKCS1-v1_5";} + + size_t MaxUnpaddedLength(size_t paddedLength) const; + void Pad(RandomNumberGenerator &rng, const byte *raw, size_t inputLength, byte *padded, size_t paddedLength, const NameValuePairs ¶meters) const; + DecodingResult Unpad(const byte *padded, size_t paddedLength, byte *raw, const NameValuePairs ¶meters) const; +}; + +template class PKCS_DigestDecoration +{ +public: + static const byte decoration[]; + static const unsigned int length; +}; + +// PKCS_DigestDecoration can be instantiated with the following +// classes as specified in PKCS#1 v2.0 and P1363a +class SHA1; +class RIPEMD160; +class Tiger; +class SHA224; +class SHA256; +class SHA384; +class SHA512; +namespace Weak1 { +class MD2; +class MD5; +} +// end of list + +#ifdef CRYPTOPP_IS_DLL +CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; +CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; +CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; +CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; +CRYPTOPP_DLL_TEMPLATE_CLASS PKCS_DigestDecoration; +#endif + +//! EMSA-PKCS1-v1_5 +class CRYPTOPP_DLL PKCS1v15_SignatureMessageEncodingMethod : public PK_DeterministicSignatureMessageEncodingMethod +{ +public: + static const char * CRYPTOPP_API StaticAlgorithmName() {return "EMSA-PKCS1-v1_5";} + + size_t MinRepresentativeBitLength(size_t hashIdentifierSize, size_t digestSize) const + {return 8 * (digestSize + hashIdentifierSize + 10);} + + void ComputeMessageRepresentative(RandomNumberGenerator &rng, + const byte *recoverableMessage, size_t recoverableMessageLength, + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const; + + struct HashIdentifierLookup + { + template struct HashIdentifierLookup2 + { + static HashIdentifier Lookup() + { + return HashIdentifier(PKCS_DigestDecoration::decoration, PKCS_DigestDecoration::length); + } + }; + }; +}; + +//! PKCS #1 version 1.5, for use with RSAES and RSASS +/*! Only the following hash functions are supported by this signature standard: + \dontinclude pkcspad.h + \skip can be instantiated + \until end of list +*/ +struct PKCS1v15 : public SignatureStandard, public EncryptionStandard +{ + typedef PKCS_EncryptionPaddingScheme EncryptionMessageEncodingMethod; + typedef PKCS1v15_SignatureMessageEncodingMethod SignatureMessageEncodingMethod; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/pssr.cpp b/src-cryptopp/pssr.cpp new file mode 100644 index 0000000..ccbe4ee --- /dev/null +++ b/src-cryptopp/pssr.cpp @@ -0,0 +1,145 @@ +// pssr.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "pssr.h" +#include + +NAMESPACE_BEGIN(CryptoPP) + +// more in dll.cpp +template<> const byte EMSA2HashId::id = 0x31; +template<> const byte EMSA2HashId::id = 0x32; +template<> const byte EMSA2HashId::id = 0x37; + +#ifndef CRYPTOPP_IMPORTS + +size_t PSSR_MEM_Base::MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const +{ + size_t saltLen = SaltLen(digestLength); + size_t minPadLen = MinPadLen(digestLength); + return 9 + 8*(minPadLen + saltLen + digestLength + hashIdentifierLength); +} + +size_t PSSR_MEM_Base::MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const +{ + if (AllowRecovery()) + return SaturatingSubtract(representativeBitLength, MinRepresentativeBitLength(hashIdentifierLength, digestLength)) / 8; + return 0; +} + +bool PSSR_MEM_Base::IsProbabilistic() const +{ + return SaltLen(1) > 0; +} + +bool PSSR_MEM_Base::AllowNonrecoverablePart() const +{ + return true; +} + +bool PSSR_MEM_Base::RecoverablePartFirst() const +{ + return false; +} + +void PSSR_MEM_Base::ComputeMessageRepresentative(RandomNumberGenerator &rng, + const byte *recoverableMessage, size_t recoverableMessageLength, + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const +{ + assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize())); + + const size_t u = hashIdentifier.second + 1; + const size_t representativeByteLength = BitsToBytes(representativeBitLength); + const size_t digestSize = hash.DigestSize(); + const size_t saltSize = SaltLen(digestSize); + byte *const h = representative + representativeByteLength - u - digestSize; + + SecByteBlock digest(digestSize), salt(saltSize); + hash.Final(digest); + rng.GenerateBlock(salt, saltSize); + + // compute H = hash of M' + byte c[8]; + PutWord(false, BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength)); + PutWord(false, BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3)); + hash.Update(c, 8); + hash.Update(recoverableMessage, recoverableMessageLength); + hash.Update(digest, digestSize); + hash.Update(salt, saltSize); + hash.Final(h); + + // compute representative + GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize, false); + byte *xorStart = representative + representativeByteLength - u - digestSize - salt.size() - recoverableMessageLength - 1; + xorStart[0] ^= 1; + xorbuf(xorStart + 1, recoverableMessage, recoverableMessageLength); + xorbuf(xorStart + 1 + recoverableMessageLength, salt, salt.size()); + memcpy(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second); + representative[representativeByteLength - 1] = hashIdentifier.second ? 0xcc : 0xbc; + if (representativeBitLength % 8 != 0) + representative[0] = (byte)Crop(representative[0], representativeBitLength % 8); +} + +DecodingResult PSSR_MEM_Base::RecoverMessageFromRepresentative( + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength, + byte *recoverableMessage) const +{ + assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize())); + + const size_t u = hashIdentifier.second + 1; + const size_t representativeByteLength = BitsToBytes(representativeBitLength); + const size_t digestSize = hash.DigestSize(); + const size_t saltSize = SaltLen(digestSize); + const byte *const h = representative + representativeByteLength - u - digestSize; + + SecByteBlock digest(digestSize); + hash.Final(digest); + + DecodingResult result(0); + bool &valid = result.isValidCoding; + size_t &recoverableMessageLength = result.messageLength; + + valid = (representative[representativeByteLength - 1] == (hashIdentifier.second ? 0xcc : 0xbc)) && valid; + valid = VerifyBufsEqual(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second) && valid; + + GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize); + if (representativeBitLength % 8 != 0) + representative[0] = (byte)Crop(representative[0], representativeBitLength % 8); + + // extract salt and recoverableMessage from DB = 00 ... || 01 || M || salt + byte *salt = representative + representativeByteLength - u - digestSize - saltSize; + byte *M = std::find_if(representative, salt-1, std::bind2nd(std::not_equal_to(), 0)); + recoverableMessageLength = salt-M-1; + if (*M == 0x01 + && (size_t)(M - representative - (representativeBitLength % 8 != 0)) >= MinPadLen(digestSize) + && recoverableMessageLength <= MaxRecoverableLength(representativeBitLength, hashIdentifier.second, digestSize)) + { + memcpy(recoverableMessage, M+1, recoverableMessageLength); + } + else + { + recoverableMessageLength = 0; + valid = false; + } + + // verify H = hash of M' + byte c[8]; + PutWord(false, BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength)); + PutWord(false, BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3)); + hash.Update(c, 8); + hash.Update(recoverableMessage, recoverableMessageLength); + hash.Update(digest, digestSize); + hash.Update(salt, saltSize); + valid = hash.Verify(h) && valid; + + if (!AllowRecovery() && valid && recoverableMessageLength != 0) + {throw NotImplemented("PSSR_MEM: message recovery disabled");} + + return result; +} + +#endif + +NAMESPACE_END diff --git a/src-cryptopp/pssr.h b/src-cryptopp/pssr.h new file mode 100644 index 0000000..6ec6936 --- /dev/null +++ b/src-cryptopp/pssr.h @@ -0,0 +1,66 @@ +#ifndef CRYPTOPP_PSSR_H +#define CRYPTOPP_PSSR_H + +#include "pubkey.h" +#include "emsa2.h" + +#ifdef CRYPTOPP_IS_DLL +#include "sha.h" +#endif + +NAMESPACE_BEGIN(CryptoPP) + +class CRYPTOPP_DLL PSSR_MEM_Base : public PK_RecoverableSignatureMessageEncodingMethod +{ + virtual bool AllowRecovery() const =0; + virtual size_t SaltLen(size_t hashLen) const =0; + virtual size_t MinPadLen(size_t hashLen) const =0; + virtual const MaskGeneratingFunction & GetMGF() const =0; + +public: + size_t MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const; + size_t MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const; + bool IsProbabilistic() const; + bool AllowNonrecoverablePart() const; + bool RecoverablePartFirst() const; + void ComputeMessageRepresentative(RandomNumberGenerator &rng, + const byte *recoverableMessage, size_t recoverableMessageLength, + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const; + DecodingResult RecoverMessageFromRepresentative( + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength, + byte *recoverableMessage) const; +}; + +template class PSSR_MEM_BaseWithHashId; +template<> class PSSR_MEM_BaseWithHashId : public EMSA2HashIdLookup {}; +template<> class PSSR_MEM_BaseWithHashId : public PSSR_MEM_Base {}; + +template +class PSSR_MEM : public PSSR_MEM_BaseWithHashId +{ + virtual bool AllowRecovery() const {return ALLOW_RECOVERY;} + virtual size_t SaltLen(size_t hashLen) const {return SALT_LEN < 0 ? hashLen : SALT_LEN;} + virtual size_t MinPadLen(size_t hashLen) const {return MIN_PAD_LEN < 0 ? hashLen : MIN_PAD_LEN;} + virtual const MaskGeneratingFunction & GetMGF() const {static MGF mgf; return mgf;} + +public: + static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(ALLOW_RECOVERY ? "PSSR-" : "PSS-") + MGF::StaticAlgorithmName();} +}; + +//! PSSR-MGF1 +struct PSSR : public SignatureStandard +{ + typedef PSSR_MEM SignatureMessageEncodingMethod; +}; + +//! PSS-MGF1 +struct PSS : public SignatureStandard +{ + typedef PSSR_MEM SignatureMessageEncodingMethod; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/pubkey.cpp b/src-cryptopp/pubkey.cpp new file mode 100644 index 0000000..7336e8b --- /dev/null +++ b/src-cryptopp/pubkey.cpp @@ -0,0 +1,162 @@ +// pubkey.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "pubkey.h" + +NAMESPACE_BEGIN(CryptoPP) + +void P1363_MGF1KDF2_Common(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, const byte *derivationParams, size_t derivationParamsLength, bool mask, unsigned int counterStart) +{ + ArraySink *sink; + HashFilter filter(hash, sink = mask ? new ArrayXorSink(output, outputLength) : new ArraySink(output, outputLength)); + word32 counter = counterStart; + while (sink->AvailableSize() > 0) + { + filter.Put(input, inputLength); + filter.PutWord32(counter++); + filter.Put(derivationParams, derivationParamsLength); + filter.MessageEnd(); + } +} + +bool PK_DeterministicSignatureMessageEncodingMethod::VerifyMessageRepresentative( + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const +{ + SecByteBlock computedRepresentative(BitsToBytes(representativeBitLength)); + ComputeMessageRepresentative(NullRNG(), NULL, 0, hash, hashIdentifier, messageEmpty, computedRepresentative, representativeBitLength); + return VerifyBufsEqual(representative, computedRepresentative, computedRepresentative.size()); +} + +bool PK_RecoverableSignatureMessageEncodingMethod::VerifyMessageRepresentative( + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const +{ + SecByteBlock recoveredMessage(MaxRecoverableLength(representativeBitLength, hashIdentifier.second, hash.DigestSize())); + DecodingResult result = RecoverMessageFromRepresentative( + hash, hashIdentifier, messageEmpty, representative, representativeBitLength, recoveredMessage); + return result.isValidCoding && result.messageLength == 0; +} + +void TF_SignerBase::InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const +{ + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + HashIdentifier id = GetHashIdentifier(); + const MessageEncodingInterface &encoding = GetMessageEncodingInterface(); + + if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize())) + throw PK_SignatureScheme::KeyTooShort(); + + size_t maxRecoverableLength = encoding.MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, ma.AccessHash().DigestSize()); + + if (maxRecoverableLength == 0) + {throw NotImplemented("TF_SignerBase: this algorithm does not support messsage recovery or the key is too short");} + if (recoverableMessageLength > maxRecoverableLength) + throw InvalidArgument("TF_SignerBase: the recoverable message part is too long for the given key and algorithm"); + + ma.m_recoverableMessage.Assign(recoverableMessage, recoverableMessageLength); + encoding.ProcessRecoverableMessage( + ma.AccessHash(), + recoverableMessage, recoverableMessageLength, + NULL, 0, ma.m_semisignature); +} + +size_t TF_SignerBase::SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const +{ + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + HashIdentifier id = GetHashIdentifier(); + const MessageEncodingInterface &encoding = GetMessageEncodingInterface(); + + if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize())) + throw PK_SignatureScheme::KeyTooShort(); + + SecByteBlock representative(MessageRepresentativeLength()); + encoding.ComputeMessageRepresentative(rng, + ma.m_recoverableMessage, ma.m_recoverableMessage.size(), + ma.AccessHash(), id, ma.m_empty, + representative, MessageRepresentativeBitLength()); + ma.m_empty = true; + + Integer r(representative, representative.size()); + size_t signatureLength = SignatureLength(); + GetTrapdoorFunctionInterface().CalculateRandomizedInverse(rng, r).Encode(signature, signatureLength); + return signatureLength; +} + +void TF_VerifierBase::InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const +{ + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + HashIdentifier id = GetHashIdentifier(); + const MessageEncodingInterface &encoding = GetMessageEncodingInterface(); + + if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize())) + throw PK_SignatureScheme::KeyTooShort(); + + ma.m_representative.New(MessageRepresentativeLength()); + Integer x = GetTrapdoorFunctionInterface().ApplyFunction(Integer(signature, signatureLength)); + if (x.BitCount() > MessageRepresentativeBitLength()) + x = Integer::Zero(); // don't return false here to prevent timing attack + x.Encode(ma.m_representative, ma.m_representative.size()); +} + +bool TF_VerifierBase::VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const +{ + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + HashIdentifier id = GetHashIdentifier(); + const MessageEncodingInterface &encoding = GetMessageEncodingInterface(); + + if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize())) + throw PK_SignatureScheme::KeyTooShort(); + + bool result = encoding.VerifyMessageRepresentative( + ma.AccessHash(), id, ma.m_empty, ma.m_representative, MessageRepresentativeBitLength()); + ma.m_empty = true; + return result; +} + +DecodingResult TF_VerifierBase::RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const +{ + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + HashIdentifier id = GetHashIdentifier(); + const MessageEncodingInterface &encoding = GetMessageEncodingInterface(); + + if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize())) + throw PK_SignatureScheme::KeyTooShort(); + + DecodingResult result = encoding.RecoverMessageFromRepresentative( + ma.AccessHash(), id, ma.m_empty, ma.m_representative, MessageRepresentativeBitLength(), recoveredMessage); + ma.m_empty = true; + return result; +} + +DecodingResult TF_DecryptorBase::Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters) const +{ + SecByteBlock paddedBlock(PaddedBlockByteLength()); + Integer x = GetTrapdoorFunctionInterface().CalculateInverse(rng, Integer(ciphertext, FixedCiphertextLength())); + if (x.ByteCount() > paddedBlock.size()) + x = Integer::Zero(); // don't return false here to prevent timing attack + x.Encode(paddedBlock, paddedBlock.size()); + return GetMessageEncodingInterface().Unpad(paddedBlock, PaddedBlockBitLength(), plaintext, parameters); +} + +void TF_EncryptorBase::Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters) const +{ + if (plaintextLength > FixedMaxPlaintextLength()) + { + if (FixedMaxPlaintextLength() < 1) + throw InvalidArgument(AlgorithmName() + ": this key is too short to encrypt any messages"); + else + throw InvalidArgument(AlgorithmName() + ": message length of " + IntToString(plaintextLength) + " exceeds the maximum of " + IntToString(FixedMaxPlaintextLength()) + " for this public key"); + } + + SecByteBlock paddedBlock(PaddedBlockByteLength()); + GetMessageEncodingInterface().Pad(rng, plaintext, plaintextLength, paddedBlock, PaddedBlockBitLength(), parameters); + GetTrapdoorFunctionInterface().ApplyRandomizedFunction(rng, Integer(paddedBlock, paddedBlock.size())).Encode(ciphertext, FixedCiphertextLength()); +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/pubkey.h b/src-cryptopp/pubkey.h new file mode 100644 index 0000000..bdf0035 --- /dev/null +++ b/src-cryptopp/pubkey.h @@ -0,0 +1,1678 @@ +// pubkey.h - written and placed in the public domain by Wei Dai + +#ifndef CRYPTOPP_PUBKEY_H +#define CRYPTOPP_PUBKEY_H + +/** \file + + This file contains helper classes/functions for implementing public key algorithms. + + The class hierachies in this .h file tend to look like this: +

+                  x1
+                 / \
+                y1  z1
+                 |  |
+            x2  x2
+                 |  |
+                y2  z2
+                 |  |
+            x3  x3
+                 |  |
+                y3  z3
+
+ - x1, y1, z1 are abstract interface classes defined in cryptlib.h + - x2, y2, z2 are implementations of the interfaces using "abstract policies", which + are pure virtual functions that should return interfaces to interchangeable algorithms. + These classes have "Base" suffixes. + - x3, y3, z3 hold actual algorithms and implement those virtual functions. + These classes have "Impl" suffixes. + + The "TF_" prefix means an implementation using trapdoor functions on integers. + The "DL_" prefix means an implementation using group operations (in groups where discrete log is hard). +*/ + +#include "modarith.h" +#include "filters.h" +#include "eprecomp.h" +#include "fips140.h" +#include "argnames.h" +#include + +// VC60 workaround: this macro is defined in shlobj.h and conflicts with a template parameter used in this file +#undef INTERFACE + +NAMESPACE_BEGIN(CryptoPP) + +//! _ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionBounds +{ +public: + virtual ~TrapdoorFunctionBounds() {} + + virtual Integer PreimageBound() const =0; + virtual Integer ImageBound() const =0; + virtual Integer MaxPreimage() const {return --PreimageBound();} + virtual Integer MaxImage() const {return --ImageBound();} +}; + +//! _ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunction : public TrapdoorFunctionBounds +{ +public: + virtual Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const =0; + virtual bool IsRandomized() const {return true;} +}; + +//! _ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunction : public RandomizedTrapdoorFunction +{ +public: + Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const + {return ApplyFunction(x);} + bool IsRandomized() const {return false;} + + virtual Integer ApplyFunction(const Integer &x) const =0; +}; + +//! _ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomizedTrapdoorFunctionInverse +{ +public: + virtual ~RandomizedTrapdoorFunctionInverse() {} + + virtual Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const =0; + virtual bool IsRandomized() const {return true;} +}; + +//! _ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TrapdoorFunctionInverse : public RandomizedTrapdoorFunctionInverse +{ +public: + virtual ~TrapdoorFunctionInverse() {} + + Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const + {return CalculateInverse(rng, x);} + bool IsRandomized() const {return false;} + + virtual Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const =0; +}; + +// ******************************************************** + +//! message encoding method for public key encryption +class CRYPTOPP_NO_VTABLE PK_EncryptionMessageEncodingMethod +{ +public: + virtual ~PK_EncryptionMessageEncodingMethod() {} + + virtual bool ParameterSupported(const char *name) const {return false;} + + //! max size of unpadded message in bytes, given max size of padded message in bits (1 less than size of modulus) + virtual size_t MaxUnpaddedLength(size_t paddedLength) const =0; + + virtual void Pad(RandomNumberGenerator &rng, const byte *raw, size_t inputLength, byte *padded, size_t paddedBitLength, const NameValuePairs ¶meters) const =0; + + virtual DecodingResult Unpad(const byte *padded, size_t paddedBitLength, byte *raw, const NameValuePairs ¶meters) const =0; +}; + +// ******************************************************** + +//! _ +template +class CRYPTOPP_NO_VTABLE TF_Base +{ +protected: + virtual const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const =0; + + typedef TFI TrapdoorFunctionInterface; + virtual const TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const =0; + + typedef MEI MessageEncodingInterface; + virtual const MessageEncodingInterface & GetMessageEncodingInterface() const =0; +}; + +// ******************************************************** + +//! _ +template +class CRYPTOPP_NO_VTABLE PK_FixedLengthCryptoSystemImpl : public BASE +{ +public: + size_t MaxPlaintextLength(size_t ciphertextLength) const + {return ciphertextLength == FixedCiphertextLength() ? FixedMaxPlaintextLength() : 0;} + size_t CiphertextLength(size_t plaintextLength) const + {return plaintextLength <= FixedMaxPlaintextLength() ? FixedCiphertextLength() : 0;} + + virtual size_t FixedMaxPlaintextLength() const =0; + virtual size_t FixedCiphertextLength() const =0; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE TF_CryptoSystemBase : public PK_FixedLengthCryptoSystemImpl, protected BASE +{ +public: + bool ParameterSupported(const char *name) const {return this->GetMessageEncodingInterface().ParameterSupported(name);} + size_t FixedMaxPlaintextLength() const {return this->GetMessageEncodingInterface().MaxUnpaddedLength(PaddedBlockBitLength());} + size_t FixedCiphertextLength() const {return this->GetTrapdoorFunctionBounds().MaxImage().ByteCount();} + +protected: + size_t PaddedBlockByteLength() const {return BitsToBytes(PaddedBlockBitLength());} + size_t PaddedBlockBitLength() const {return this->GetTrapdoorFunctionBounds().PreimageBound().BitCount()-1;} +}; + +//! _ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_DecryptorBase : public TF_CryptoSystemBase > +{ +public: + DecodingResult Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters = g_nullNameValuePairs) const; +}; + +//! _ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_EncryptorBase : public TF_CryptoSystemBase > +{ +public: + void Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters = g_nullNameValuePairs) const; +}; + +// ******************************************************** + +typedef std::pair HashIdentifier; + +//! interface for message encoding method for public key signature schemes +class CRYPTOPP_NO_VTABLE PK_SignatureMessageEncodingMethod +{ +public: + virtual ~PK_SignatureMessageEncodingMethod() {} + + virtual size_t MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const + {return 0;} + virtual size_t MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const + {return 0;} + + bool IsProbabilistic() const + {return true;} + bool AllowNonrecoverablePart() const + {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} + virtual bool RecoverablePartFirst() const + {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} + + // for verification, DL + virtual void ProcessSemisignature(HashTransformation &hash, const byte *semisignature, size_t semisignatureLength) const {} + + // for signature + virtual void ProcessRecoverableMessage(HashTransformation &hash, + const byte *recoverableMessage, size_t recoverableMessageLength, + const byte *presignature, size_t presignatureLength, + SecByteBlock &semisignature) const + { + if (RecoverablePartFirst()) + assert(!"ProcessRecoverableMessage() not implemented"); + } + + virtual void ComputeMessageRepresentative(RandomNumberGenerator &rng, + const byte *recoverableMessage, size_t recoverableMessageLength, + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const =0; + + virtual bool VerifyMessageRepresentative( + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const =0; + + virtual DecodingResult RecoverMessageFromRepresentative( // for TF + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength, + byte *recoveredMessage) const + {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} + + virtual DecodingResult RecoverMessageFromSemisignature( // for DL + HashTransformation &hash, HashIdentifier hashIdentifier, + const byte *presignature, size_t presignatureLength, + const byte *semisignature, size_t semisignatureLength, + byte *recoveredMessage) const + {throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");} + + // VC60 workaround + struct HashIdentifierLookup + { + template struct HashIdentifierLookup2 + { + static HashIdentifier CRYPTOPP_API Lookup() + { + return HashIdentifier(NULL, 0); + } + }; + }; +}; + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_DeterministicSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod +{ +public: + bool VerifyMessageRepresentative( + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const; +}; + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_RecoverableSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod +{ +public: + bool VerifyMessageRepresentative( + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const; +}; + +class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_DSA : public PK_DeterministicSignatureMessageEncodingMethod +{ +public: + void ComputeMessageRepresentative(RandomNumberGenerator &rng, + const byte *recoverableMessage, size_t recoverableMessageLength, + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const; +}; + +class CRYPTOPP_DLL DL_SignatureMessageEncodingMethod_NR : public PK_DeterministicSignatureMessageEncodingMethod +{ +public: + void ComputeMessageRepresentative(RandomNumberGenerator &rng, + const byte *recoverableMessage, size_t recoverableMessageLength, + HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty, + byte *representative, size_t representativeBitLength) const; +}; + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_MessageAccumulatorBase : public PK_MessageAccumulator +{ +public: + PK_MessageAccumulatorBase() : m_empty(true) {} + + virtual HashTransformation & AccessHash() =0; + + void Update(const byte *input, size_t length) + { + AccessHash().Update(input, length); + m_empty = m_empty && length == 0; + } + + SecByteBlock m_recoverableMessage, m_representative, m_presignature, m_semisignature; + Integer m_k, m_s; + bool m_empty; +}; + +template +class PK_MessageAccumulatorImpl : public PK_MessageAccumulatorBase, protected ObjectHolder +{ +public: + HashTransformation & AccessHash() {return this->m_object;} +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE TF_SignatureSchemeBase : public INTERFACE, protected BASE +{ +public: + size_t SignatureLength() const + {return this->GetTrapdoorFunctionBounds().MaxPreimage().ByteCount();} + size_t MaxRecoverableLength() const + {return this->GetMessageEncodingInterface().MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, GetDigestSize());} + size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const + {return this->MaxRecoverableLength();} + + bool IsProbabilistic() const + {return this->GetTrapdoorFunctionInterface().IsRandomized() || this->GetMessageEncodingInterface().IsProbabilistic();} + bool AllowNonrecoverablePart() const + {return this->GetMessageEncodingInterface().AllowNonrecoverablePart();} + bool RecoverablePartFirst() const + {return this->GetMessageEncodingInterface().RecoverablePartFirst();} + +protected: + size_t MessageRepresentativeLength() const {return BitsToBytes(MessageRepresentativeBitLength());} + size_t MessageRepresentativeBitLength() const {return this->GetTrapdoorFunctionBounds().ImageBound().BitCount()-1;} + virtual HashIdentifier GetHashIdentifier() const =0; + virtual size_t GetDigestSize() const =0; +}; + +//! _ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_SignerBase : public TF_SignatureSchemeBase > +{ +public: + void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const; + size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart=true) const; +}; + +//! _ +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TF_VerifierBase : public TF_SignatureSchemeBase > +{ +public: + void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const; + bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const; + DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &recoveryAccumulator) const; +}; + +// ******************************************************** + +//! _ +template +struct TF_CryptoSchemeOptions +{ + typedef T1 AlgorithmInfo; + typedef T2 Keys; + typedef typename Keys::PrivateKey PrivateKey; + typedef typename Keys::PublicKey PublicKey; + typedef T3 MessageEncodingMethod; +}; + +//! _ +template +struct TF_SignatureSchemeOptions : public TF_CryptoSchemeOptions +{ + typedef T4 HashFunction; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE TF_ObjectImplBase : public AlgorithmImpl +{ +public: + typedef SCHEME_OPTIONS SchemeOptions; + typedef KEY_CLASS KeyClass; + + PublicKey & AccessPublicKey() {return AccessKey();} + const PublicKey & GetPublicKey() const {return GetKey();} + + PrivateKey & AccessPrivateKey() {return AccessKey();} + const PrivateKey & GetPrivateKey() const {return GetKey();} + + virtual const KeyClass & GetKey() const =0; + virtual KeyClass & AccessKey() =0; + + const KeyClass & GetTrapdoorFunction() const {return GetKey();} + + PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const + { + return new PK_MessageAccumulatorImpl; + } + PK_MessageAccumulator * NewVerificationAccumulator() const + { + return new PK_MessageAccumulatorImpl; + } + +protected: + const typename BASE::MessageEncodingInterface & GetMessageEncodingInterface() const + {return Singleton().Ref();} + const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const + {return GetKey();} + const typename BASE::TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const + {return GetKey();} + + // for signature scheme + HashIdentifier GetHashIdentifier() const + { + typedef CPP_TYPENAME SchemeOptions::MessageEncodingMethod::HashIdentifierLookup::template HashIdentifierLookup2 L; + return L::Lookup(); + } + size_t GetDigestSize() const + { + typedef CPP_TYPENAME SchemeOptions::HashFunction H; + return H::DIGESTSIZE; + } +}; + +//! _ +template +class TF_ObjectImplExtRef : public TF_ObjectImplBase +{ +public: + TF_ObjectImplExtRef(const KEY *pKey = NULL) : m_pKey(pKey) {} + void SetKeyPtr(const KEY *pKey) {m_pKey = pKey;} + + const KEY & GetKey() const {return *m_pKey;} + KEY & AccessKey() {throw NotImplemented("TF_ObjectImplExtRef: cannot modify refererenced key");} + +private: + const KEY * m_pKey; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE TF_ObjectImpl : public TF_ObjectImplBase +{ +public: + typedef KEY_CLASS KeyClass; + + const KeyClass & GetKey() const {return m_trapdoorFunction;} + KeyClass & AccessKey() {return m_trapdoorFunction;} + +private: + KeyClass m_trapdoorFunction; +}; + +//! _ +template +class TF_DecryptorImpl : public TF_ObjectImpl +{ +}; + +//! _ +template +class TF_EncryptorImpl : public TF_ObjectImpl +{ +}; + +//! _ +template +class TF_SignerImpl : public TF_ObjectImpl +{ +}; + +//! _ +template +class TF_VerifierImpl : public TF_ObjectImpl +{ +}; + +// ******************************************************** + +//! _ +class CRYPTOPP_NO_VTABLE MaskGeneratingFunction +{ +public: + virtual ~MaskGeneratingFunction() {} + virtual void GenerateAndMask(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, bool mask = true) const =0; +}; + +CRYPTOPP_DLL void CRYPTOPP_API P1363_MGF1KDF2_Common(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, const byte *derivationParams, size_t derivationParamsLength, bool mask, unsigned int counterStart); + +//! _ +class P1363_MGF1 : public MaskGeneratingFunction +{ +public: + static const char * CRYPTOPP_API StaticAlgorithmName() {return "MGF1";} + void GenerateAndMask(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, bool mask = true) const + { + P1363_MGF1KDF2_Common(hash, output, outputLength, input, inputLength, NULL, 0, mask, 0); + } +}; + +// ******************************************************** + +//! _ +template +class P1363_KDF2 +{ +public: + static void CRYPTOPP_API DeriveKey(byte *output, size_t outputLength, const byte *input, size_t inputLength, const byte *derivationParams, size_t derivationParamsLength) + { + H h; + P1363_MGF1KDF2_Common(h, output, outputLength, input, inputLength, derivationParams, derivationParamsLength, false, 1); + } +}; + +// ******************************************************** + +//! to be thrown by DecodeElement and AgreeWithStaticPrivateKey +class DL_BadElement : public InvalidDataFormat +{ +public: + DL_BadElement() : InvalidDataFormat("CryptoPP: invalid group element") {} +}; + +//! interface for DL group parameters +template +class CRYPTOPP_NO_VTABLE DL_GroupParameters : public CryptoParameters +{ + typedef DL_GroupParameters ThisClass; + +public: + typedef T Element; + + DL_GroupParameters() : m_validationLevel(0) {} + + // CryptoMaterial + bool Validate(RandomNumberGenerator &rng, unsigned int level) const + { + if (!GetBasePrecomputation().IsInitialized()) + return false; + + if (m_validationLevel > level) + return true; + + bool pass = ValidateGroup(rng, level); + pass = pass && ValidateElement(level, GetSubgroupGenerator(), &GetBasePrecomputation()); + + m_validationLevel = pass ? level+1 : 0; + + return pass; + } + + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const + { + return GetValueHelper(this, name, valueType, pValue) + CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupOrder) + CRYPTOPP_GET_FUNCTION_ENTRY(SubgroupGenerator) + ; + } + + bool SupportsPrecomputation() const {return true;} + + void Precompute(unsigned int precomputationStorage=16) + { + AccessBasePrecomputation().Precompute(GetGroupPrecomputation(), GetSubgroupOrder().BitCount(), precomputationStorage); + } + + void LoadPrecomputation(BufferedTransformation &storedPrecomputation) + { + AccessBasePrecomputation().Load(GetGroupPrecomputation(), storedPrecomputation); + m_validationLevel = 0; + } + + void SavePrecomputation(BufferedTransformation &storedPrecomputation) const + { + GetBasePrecomputation().Save(GetGroupPrecomputation(), storedPrecomputation); + } + + // non-inherited + virtual const Element & GetSubgroupGenerator() const {return GetBasePrecomputation().GetBase(GetGroupPrecomputation());} + virtual void SetSubgroupGenerator(const Element &base) {AccessBasePrecomputation().SetBase(GetGroupPrecomputation(), base);} + virtual Element ExponentiateBase(const Integer &exponent) const + { + return GetBasePrecomputation().Exponentiate(GetGroupPrecomputation(), exponent); + } + virtual Element ExponentiateElement(const Element &base, const Integer &exponent) const + { + Element result; + SimultaneousExponentiate(&result, base, &exponent, 1); + return result; + } + + virtual const DL_GroupPrecomputation & GetGroupPrecomputation() const =0; + virtual const DL_FixedBasePrecomputation & GetBasePrecomputation() const =0; + virtual DL_FixedBasePrecomputation & AccessBasePrecomputation() =0; + virtual const Integer & GetSubgroupOrder() const =0; // order of subgroup generated by base element + virtual Integer GetMaxExponent() const =0; + virtual Integer GetGroupOrder() const {return GetSubgroupOrder()*GetCofactor();} // one of these two needs to be overriden + virtual Integer GetCofactor() const {return GetGroupOrder()/GetSubgroupOrder();} + virtual unsigned int GetEncodedElementSize(bool reversible) const =0; + virtual void EncodeElement(bool reversible, const Element &element, byte *encoded) const =0; + virtual Element DecodeElement(const byte *encoded, bool checkForGroupMembership) const =0; + virtual Integer ConvertElementToInteger(const Element &element) const =0; + virtual bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const =0; + virtual bool ValidateElement(unsigned int level, const Element &element, const DL_FixedBasePrecomputation *precomp) const =0; + virtual bool FastSubgroupCheckAvailable() const =0; + virtual bool IsIdentity(const Element &element) const =0; + virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const =0; + +protected: + void ParametersChanged() {m_validationLevel = 0;} + +private: + mutable unsigned int m_validationLevel; +}; + +//! _ +template , class BASE = DL_GroupParameters > +class DL_GroupParametersImpl : public BASE +{ +public: + typedef GROUP_PRECOMP GroupPrecomputation; + typedef typename GROUP_PRECOMP::Element Element; + typedef BASE_PRECOMP BasePrecomputation; + + const DL_GroupPrecomputation & GetGroupPrecomputation() const {return m_groupPrecomputation;} + const DL_FixedBasePrecomputation & GetBasePrecomputation() const {return m_gpc;} + DL_FixedBasePrecomputation & AccessBasePrecomputation() {return m_gpc;} + +protected: + GROUP_PRECOMP m_groupPrecomputation; + BASE_PRECOMP m_gpc; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE DL_Key +{ +public: + virtual const DL_GroupParameters & GetAbstractGroupParameters() const =0; + virtual DL_GroupParameters & AccessAbstractGroupParameters() =0; +}; + +//! interface for DL public keys +template +class CRYPTOPP_NO_VTABLE DL_PublicKey : public DL_Key +{ + typedef DL_PublicKey ThisClass; + +public: + typedef T Element; + + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const + { + return GetValueHelper(this, name, valueType, pValue, &this->GetAbstractGroupParameters()) + CRYPTOPP_GET_FUNCTION_ENTRY(PublicElement); + } + + void AssignFrom(const NameValuePairs &source); + + // non-inherited + virtual const Element & GetPublicElement() const {return GetPublicPrecomputation().GetBase(this->GetAbstractGroupParameters().GetGroupPrecomputation());} + virtual void SetPublicElement(const Element &y) {AccessPublicPrecomputation().SetBase(this->GetAbstractGroupParameters().GetGroupPrecomputation(), y);} + virtual Element ExponentiatePublicElement(const Integer &exponent) const + { + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + return GetPublicPrecomputation().Exponentiate(params.GetGroupPrecomputation(), exponent); + } + virtual Element CascadeExponentiateBaseAndPublicElement(const Integer &baseExp, const Integer &publicExp) const + { + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + return params.GetBasePrecomputation().CascadeExponentiate(params.GetGroupPrecomputation(), baseExp, GetPublicPrecomputation(), publicExp); + } + + virtual const DL_FixedBasePrecomputation & GetPublicPrecomputation() const =0; + virtual DL_FixedBasePrecomputation & AccessPublicPrecomputation() =0; +}; + +//! interface for DL private keys +template +class CRYPTOPP_NO_VTABLE DL_PrivateKey : public DL_Key +{ + typedef DL_PrivateKey ThisClass; + +public: + typedef T Element; + + void MakePublicKey(DL_PublicKey &pub) const + { + pub.AccessAbstractGroupParameters().AssignFrom(this->GetAbstractGroupParameters()); + pub.SetPublicElement(this->GetAbstractGroupParameters().ExponentiateBase(GetPrivateExponent())); + } + + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const + { + return GetValueHelper(this, name, valueType, pValue, &this->GetAbstractGroupParameters()) + CRYPTOPP_GET_FUNCTION_ENTRY(PrivateExponent); + } + + void AssignFrom(const NameValuePairs &source) + { + this->AccessAbstractGroupParameters().AssignFrom(source); + AssignFromHelper(this, source) + CRYPTOPP_SET_FUNCTION_ENTRY(PrivateExponent); + } + + virtual const Integer & GetPrivateExponent() const =0; + virtual void SetPrivateExponent(const Integer &x) =0; +}; + +template +void DL_PublicKey::AssignFrom(const NameValuePairs &source) +{ + DL_PrivateKey *pPrivateKey = NULL; + if (source.GetThisPointer(pPrivateKey)) + pPrivateKey->MakePublicKey(*this); + else + { + this->AccessAbstractGroupParameters().AssignFrom(source); + AssignFromHelper(this, source) + CRYPTOPP_SET_FUNCTION_ENTRY(PublicElement); + } +} + +class OID; + +//! _ +template +class DL_KeyImpl : public PK +{ +public: + typedef GP GroupParameters; + + O GetAlgorithmID() const {return GetGroupParameters().GetAlgorithmID();} +// void BERDecode(BufferedTransformation &bt) +// {PK::BERDecode(bt);} +// void DEREncode(BufferedTransformation &bt) const +// {PK::DEREncode(bt);} + bool BERDecodeAlgorithmParameters(BufferedTransformation &bt) + {AccessGroupParameters().BERDecode(bt); return true;} + bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const + {GetGroupParameters().DEREncode(bt); return true;} + + const GP & GetGroupParameters() const {return m_groupParameters;} + GP & AccessGroupParameters() {return m_groupParameters;} + +private: + GP m_groupParameters; +}; + +class X509PublicKey; +class PKCS8PrivateKey; + +//! _ +template +class DL_PrivateKeyImpl : public DL_PrivateKey, public DL_KeyImpl +{ +public: + typedef typename GP::Element Element; + + // GeneratableCryptoMaterial + bool Validate(RandomNumberGenerator &rng, unsigned int level) const + { + bool pass = GetAbstractGroupParameters().Validate(rng, level); + + const Integer &q = GetAbstractGroupParameters().GetSubgroupOrder(); + const Integer &x = GetPrivateExponent(); + + pass = pass && x.IsPositive() && x < q; + if (level >= 1) + pass = pass && Integer::Gcd(x, q) == Integer::One(); + return pass; + } + + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const + { + return GetValueHelper >(this, name, valueType, pValue).Assignable(); + } + + void AssignFrom(const NameValuePairs &source) + { + AssignFromHelper >(this, source); + } + + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms) + { + if (!params.GetThisObject(this->AccessGroupParameters())) + this->AccessGroupParameters().GenerateRandom(rng, params); +// std::pair seed; + Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent()); +// Integer::ANY, Integer::Zero(), Integer::One(), +// params.GetValue("DeterministicKeyGenerationSeed", seed) ? &seed : NULL); + SetPrivateExponent(x); + } + + bool SupportsPrecomputation() const {return true;} + + void Precompute(unsigned int precomputationStorage=16) + {AccessAbstractGroupParameters().Precompute(precomputationStorage);} + + void LoadPrecomputation(BufferedTransformation &storedPrecomputation) + {AccessAbstractGroupParameters().LoadPrecomputation(storedPrecomputation);} + + void SavePrecomputation(BufferedTransformation &storedPrecomputation) const + {GetAbstractGroupParameters().SavePrecomputation(storedPrecomputation);} + + // DL_Key + const DL_GroupParameters & GetAbstractGroupParameters() const {return this->GetGroupParameters();} + DL_GroupParameters & AccessAbstractGroupParameters() {return this->AccessGroupParameters();} + + // DL_PrivateKey + const Integer & GetPrivateExponent() const {return m_x;} + void SetPrivateExponent(const Integer &x) {m_x = x;} + + // PKCS8PrivateKey + void BERDecodePrivateKey(BufferedTransformation &bt, bool, size_t) + {m_x.BERDecode(bt);} + void DEREncodePrivateKey(BufferedTransformation &bt) const + {m_x.DEREncode(bt);} + +private: + Integer m_x; +}; + +//! _ +template +class DL_PrivateKey_WithSignaturePairwiseConsistencyTest : public BASE +{ +public: + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms) + { + BASE::GenerateRandom(rng, params); + + if (FIPS_140_2_ComplianceEnabled()) + { + typename SIGNATURE_SCHEME::Signer signer(*this); + typename SIGNATURE_SCHEME::Verifier verifier(signer); + SignaturePairwiseConsistencyTest_FIPS_140_Only(signer, verifier); + } + } +}; + +//! _ +template +class DL_PublicKeyImpl : public DL_PublicKey, public DL_KeyImpl +{ +public: + typedef typename GP::Element Element; + + // CryptoMaterial + bool Validate(RandomNumberGenerator &rng, unsigned int level) const + { + bool pass = GetAbstractGroupParameters().Validate(rng, level); + pass = pass && GetAbstractGroupParameters().ValidateElement(level, this->GetPublicElement(), &GetPublicPrecomputation()); + return pass; + } + + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const + { + return GetValueHelper >(this, name, valueType, pValue).Assignable(); + } + + void AssignFrom(const NameValuePairs &source) + { + AssignFromHelper >(this, source); + } + + bool SupportsPrecomputation() const {return true;} + + void Precompute(unsigned int precomputationStorage=16) + { + AccessAbstractGroupParameters().Precompute(precomputationStorage); + AccessPublicPrecomputation().Precompute(GetAbstractGroupParameters().GetGroupPrecomputation(), GetAbstractGroupParameters().GetSubgroupOrder().BitCount(), precomputationStorage); + } + + void LoadPrecomputation(BufferedTransformation &storedPrecomputation) + { + AccessAbstractGroupParameters().LoadPrecomputation(storedPrecomputation); + AccessPublicPrecomputation().Load(GetAbstractGroupParameters().GetGroupPrecomputation(), storedPrecomputation); + } + + void SavePrecomputation(BufferedTransformation &storedPrecomputation) const + { + GetAbstractGroupParameters().SavePrecomputation(storedPrecomputation); + GetPublicPrecomputation().Save(GetAbstractGroupParameters().GetGroupPrecomputation(), storedPrecomputation); + } + + // DL_Key + const DL_GroupParameters & GetAbstractGroupParameters() const {return this->GetGroupParameters();} + DL_GroupParameters & AccessAbstractGroupParameters() {return this->AccessGroupParameters();} + + // DL_PublicKey + const DL_FixedBasePrecomputation & GetPublicPrecomputation() const {return m_ypc;} + DL_FixedBasePrecomputation & AccessPublicPrecomputation() {return m_ypc;} + + // non-inherited + bool operator==(const DL_PublicKeyImpl &rhs) const + {return this->GetGroupParameters() == rhs.GetGroupParameters() && this->GetPublicElement() == rhs.GetPublicElement();} + +private: + typename GP::BasePrecomputation m_ypc; +}; + +//! interface for Elgamal-like signature algorithms +template +class CRYPTOPP_NO_VTABLE DL_ElgamalLikeSignatureAlgorithm +{ +public: + virtual void Sign(const DL_GroupParameters ¶ms, const Integer &privateKey, const Integer &k, const Integer &e, Integer &r, Integer &s) const =0; + virtual bool Verify(const DL_GroupParameters ¶ms, const DL_PublicKey &publicKey, const Integer &e, const Integer &r, const Integer &s) const =0; + virtual Integer RecoverPresignature(const DL_GroupParameters ¶ms, const DL_PublicKey &publicKey, const Integer &r, const Integer &s) const + {throw NotImplemented("DL_ElgamalLikeSignatureAlgorithm: this signature scheme does not support message recovery");} + virtual size_t RLen(const DL_GroupParameters ¶ms) const + {return params.GetSubgroupOrder().ByteCount();} + virtual size_t SLen(const DL_GroupParameters ¶ms) const + {return params.GetSubgroupOrder().ByteCount();} +}; + +//! interface for DL key agreement algorithms +template +class CRYPTOPP_NO_VTABLE DL_KeyAgreementAlgorithm +{ +public: + typedef T Element; + + virtual Element AgreeWithEphemeralPrivateKey(const DL_GroupParameters ¶ms, const DL_FixedBasePrecomputation &publicPrecomputation, const Integer &privateExponent) const =0; + virtual Element AgreeWithStaticPrivateKey(const DL_GroupParameters ¶ms, const Element &publicElement, bool validateOtherPublicKey, const Integer &privateExponent) const =0; +}; + +//! interface for key derivation algorithms used in DL cryptosystems +template +class CRYPTOPP_NO_VTABLE DL_KeyDerivationAlgorithm +{ +public: + virtual bool ParameterSupported(const char *name) const {return false;} + virtual void Derive(const DL_GroupParameters &groupParams, byte *derivedKey, size_t derivedLength, const T &agreedElement, const T &ephemeralPublicKey, const NameValuePairs &derivationParams) const =0; +}; + +//! interface for symmetric encryption algorithms used in DL cryptosystems +class CRYPTOPP_NO_VTABLE DL_SymmetricEncryptionAlgorithm +{ +public: + virtual bool ParameterSupported(const char *name) const {return false;} + virtual size_t GetSymmetricKeyLength(size_t plaintextLength) const =0; + virtual size_t GetSymmetricCiphertextLength(size_t plaintextLength) const =0; + virtual size_t GetMaxSymmetricPlaintextLength(size_t ciphertextLength) const =0; + virtual void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters) const =0; + virtual DecodingResult SymmetricDecrypt(const byte *key, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters) const =0; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE DL_Base +{ +protected: + typedef KI KeyInterface; + typedef typename KI::Element Element; + + const DL_GroupParameters & GetAbstractGroupParameters() const {return GetKeyInterface().GetAbstractGroupParameters();} + DL_GroupParameters & AccessAbstractGroupParameters() {return AccessKeyInterface().AccessAbstractGroupParameters();} + + virtual KeyInterface & AccessKeyInterface() =0; + virtual const KeyInterface & GetKeyInterface() const =0; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE DL_SignatureSchemeBase : public INTERFACE, public DL_Base +{ +public: + size_t SignatureLength() const + { + return GetSignatureAlgorithm().RLen(this->GetAbstractGroupParameters()) + + GetSignatureAlgorithm().SLen(this->GetAbstractGroupParameters()); + } + size_t MaxRecoverableLength() const + {return GetMessageEncodingInterface().MaxRecoverableLength(0, GetHashIdentifier().second, GetDigestSize());} + size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const + {assert(false); return 0;} // TODO + + bool IsProbabilistic() const + {return true;} + bool AllowNonrecoverablePart() const + {return GetMessageEncodingInterface().AllowNonrecoverablePart();} + bool RecoverablePartFirst() const + {return GetMessageEncodingInterface().RecoverablePartFirst();} + +protected: + size_t MessageRepresentativeLength() const {return BitsToBytes(MessageRepresentativeBitLength());} + size_t MessageRepresentativeBitLength() const {return this->GetAbstractGroupParameters().GetSubgroupOrder().BitCount();} + + virtual const DL_ElgamalLikeSignatureAlgorithm & GetSignatureAlgorithm() const =0; + virtual const PK_SignatureMessageEncodingMethod & GetMessageEncodingInterface() const =0; + virtual HashIdentifier GetHashIdentifier() const =0; + virtual size_t GetDigestSize() const =0; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE DL_SignerBase : public DL_SignatureSchemeBase > +{ +public: + // for validation testing + void RawSign(const Integer &k, const Integer &e, Integer &r, Integer &s) const + { + const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + const DL_PrivateKey &key = this->GetKeyInterface(); + + r = params.ConvertElementToInteger(params.ExponentiateBase(k)); + alg.Sign(params, key.GetPrivateExponent(), k, e, r, s); + } + + void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const + { + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + ma.m_recoverableMessage.Assign(recoverableMessage, recoverableMessageLength); + this->GetMessageEncodingInterface().ProcessRecoverableMessage(ma.AccessHash(), + recoverableMessage, recoverableMessageLength, + ma.m_presignature, ma.m_presignature.size(), + ma.m_semisignature); + } + + size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const + { + this->GetMaterial().DoQuickSanityCheck(); + + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + const DL_PrivateKey &key = this->GetKeyInterface(); + + SecByteBlock representative(this->MessageRepresentativeLength()); + this->GetMessageEncodingInterface().ComputeMessageRepresentative( + rng, + ma.m_recoverableMessage, ma.m_recoverableMessage.size(), + ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty, + representative, this->MessageRepresentativeBitLength()); + ma.m_empty = true; + Integer e(representative, representative.size()); + + // hash message digest into random number k to prevent reusing the same k on a different messages + // after virtual machine rollback + if (rng.CanIncorporateEntropy()) + rng.IncorporateEntropy(representative, representative.size()); + Integer k(rng, 1, params.GetSubgroupOrder()-1); + Integer r, s; + r = params.ConvertElementToInteger(params.ExponentiateBase(k)); + alg.Sign(params, key.GetPrivateExponent(), k, e, r, s); + + /* + Integer r, s; + if (this->MaxRecoverableLength() > 0) + r.Decode(ma.m_semisignature, ma.m_semisignature.size()); + else + r.Decode(ma.m_presignature, ma.m_presignature.size()); + alg.Sign(params, key.GetPrivateExponent(), ma.m_k, e, r, s); + */ + + size_t rLen = alg.RLen(params); + r.Encode(signature, rLen); + s.Encode(signature+rLen, alg.SLen(params)); + + if (restart) + RestartMessageAccumulator(rng, ma); + + return this->SignatureLength(); + } + +protected: + void RestartMessageAccumulator(RandomNumberGenerator &rng, PK_MessageAccumulatorBase &ma) const + { + // k needs to be generated before hashing for signature schemes with recovery + // but to defend against VM rollbacks we need to generate k after hashing. + // so this code is commented out, since no DL-based signature scheme with recovery + // has been implemented in Crypto++ anyway + /* + const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + ma.m_k.Randomize(rng, 1, params.GetSubgroupOrder()-1); + ma.m_presignature.New(params.GetEncodedElementSize(false)); + params.ConvertElementToInteger(params.ExponentiateBase(ma.m_k)).Encode(ma.m_presignature, ma.m_presignature.size()); + */ + } +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE DL_VerifierBase : public DL_SignatureSchemeBase > +{ +public: + void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const + { + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + + size_t rLen = alg.RLen(params); + ma.m_semisignature.Assign(signature, rLen); + ma.m_s.Decode(signature+rLen, alg.SLen(params)); + + this->GetMessageEncodingInterface().ProcessSemisignature(ma.AccessHash(), ma.m_semisignature, ma.m_semisignature.size()); + } + + bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const + { + this->GetMaterial().DoQuickSanityCheck(); + + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + const DL_PublicKey &key = this->GetKeyInterface(); + + SecByteBlock representative(this->MessageRepresentativeLength()); + this->GetMessageEncodingInterface().ComputeMessageRepresentative(NullRNG(), ma.m_recoverableMessage, ma.m_recoverableMessage.size(), + ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty, + representative, this->MessageRepresentativeBitLength()); + ma.m_empty = true; + Integer e(representative, representative.size()); + + Integer r(ma.m_semisignature, ma.m_semisignature.size()); + return alg.Verify(params, key, e, r, ma.m_s); + } + + DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const + { + this->GetMaterial().DoQuickSanityCheck(); + + PK_MessageAccumulatorBase &ma = static_cast(messageAccumulator); + const DL_ElgamalLikeSignatureAlgorithm &alg = this->GetSignatureAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + const DL_PublicKey &key = this->GetKeyInterface(); + + SecByteBlock representative(this->MessageRepresentativeLength()); + this->GetMessageEncodingInterface().ComputeMessageRepresentative( + NullRNG(), + ma.m_recoverableMessage, ma.m_recoverableMessage.size(), + ma.AccessHash(), this->GetHashIdentifier(), ma.m_empty, + representative, this->MessageRepresentativeBitLength()); + ma.m_empty = true; + Integer e(representative, representative.size()); + + ma.m_presignature.New(params.GetEncodedElementSize(false)); + Integer r(ma.m_semisignature, ma.m_semisignature.size()); + alg.RecoverPresignature(params, key, r, ma.m_s).Encode(ma.m_presignature, ma.m_presignature.size()); + + return this->GetMessageEncodingInterface().RecoverMessageFromSemisignature( + ma.AccessHash(), this->GetHashIdentifier(), + ma.m_presignature, ma.m_presignature.size(), + ma.m_semisignature, ma.m_semisignature.size(), + recoveredMessage); + } +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE DL_CryptoSystemBase : public PK, public DL_Base +{ +public: + typedef typename DL_Base::Element Element; + + size_t MaxPlaintextLength(size_t ciphertextLength) const + { + unsigned int minLen = this->GetAbstractGroupParameters().GetEncodedElementSize(true); + return ciphertextLength < minLen ? 0 : GetSymmetricEncryptionAlgorithm().GetMaxSymmetricPlaintextLength(ciphertextLength - minLen); + } + + size_t CiphertextLength(size_t plaintextLength) const + { + size_t len = GetSymmetricEncryptionAlgorithm().GetSymmetricCiphertextLength(plaintextLength); + return len == 0 ? 0 : this->GetAbstractGroupParameters().GetEncodedElementSize(true) + len; + } + + bool ParameterSupported(const char *name) const + {return GetKeyDerivationAlgorithm().ParameterSupported(name) || GetSymmetricEncryptionAlgorithm().ParameterSupported(name);} + +protected: + virtual const DL_KeyAgreementAlgorithm & GetKeyAgreementAlgorithm() const =0; + virtual const DL_KeyDerivationAlgorithm & GetKeyDerivationAlgorithm() const =0; + virtual const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const =0; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE DL_DecryptorBase : public DL_CryptoSystemBase > +{ +public: + typedef T Element; + + DecodingResult Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs ¶meters = g_nullNameValuePairs) const + { + try + { + const DL_KeyAgreementAlgorithm &agreeAlg = this->GetKeyAgreementAlgorithm(); + const DL_KeyDerivationAlgorithm &derivAlg = this->GetKeyDerivationAlgorithm(); + const DL_SymmetricEncryptionAlgorithm &encAlg = this->GetSymmetricEncryptionAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + const DL_PrivateKey &key = this->GetKeyInterface(); + + Element q = params.DecodeElement(ciphertext, true); + size_t elementSize = params.GetEncodedElementSize(true); + ciphertext += elementSize; + ciphertextLength -= elementSize; + + Element z = agreeAlg.AgreeWithStaticPrivateKey(params, q, true, key.GetPrivateExponent()); + + SecByteBlock derivedKey(encAlg.GetSymmetricKeyLength(encAlg.GetMaxSymmetricPlaintextLength(ciphertextLength))); + derivAlg.Derive(params, derivedKey, derivedKey.size(), z, q, parameters); + + return encAlg.SymmetricDecrypt(derivedKey, ciphertext, ciphertextLength, plaintext, parameters); + } + catch (DL_BadElement &) + { + return DecodingResult(); + } + } +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE DL_EncryptorBase : public DL_CryptoSystemBase > +{ +public: + typedef T Element; + + void Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs ¶meters = g_nullNameValuePairs) const + { + const DL_KeyAgreementAlgorithm &agreeAlg = this->GetKeyAgreementAlgorithm(); + const DL_KeyDerivationAlgorithm &derivAlg = this->GetKeyDerivationAlgorithm(); + const DL_SymmetricEncryptionAlgorithm &encAlg = this->GetSymmetricEncryptionAlgorithm(); + const DL_GroupParameters ¶ms = this->GetAbstractGroupParameters(); + const DL_PublicKey &key = this->GetKeyInterface(); + + Integer x(rng, Integer::One(), params.GetMaxExponent()); + Element q = params.ExponentiateBase(x); + params.EncodeElement(true, q, ciphertext); + unsigned int elementSize = params.GetEncodedElementSize(true); + ciphertext += elementSize; + + Element z = agreeAlg.AgreeWithEphemeralPrivateKey(params, key.GetPublicPrecomputation(), x); + + SecByteBlock derivedKey(encAlg.GetSymmetricKeyLength(plaintextLength)); + derivAlg.Derive(params, derivedKey, derivedKey.size(), z, q, parameters); + + encAlg.SymmetricEncrypt(rng, derivedKey, plaintext, plaintextLength, ciphertext, parameters); + } +}; + +//! _ +template +struct DL_SchemeOptionsBase +{ + typedef T1 AlgorithmInfo; + typedef T2 GroupParameters; + typedef typename GroupParameters::Element Element; +}; + +//! _ +template +struct DL_KeyedSchemeOptions : public DL_SchemeOptionsBase +{ + typedef T2 Keys; + typedef typename Keys::PrivateKey PrivateKey; + typedef typename Keys::PublicKey PublicKey; +}; + +//! _ +template +struct DL_SignatureSchemeOptions : public DL_KeyedSchemeOptions +{ + typedef T3 SignatureAlgorithm; + typedef T4 MessageEncodingMethod; + typedef T5 HashFunction; +}; + +//! _ +template +struct DL_CryptoSchemeOptions : public DL_KeyedSchemeOptions +{ + typedef T3 KeyAgreementAlgorithm; + typedef T4 KeyDerivationAlgorithm; + typedef T5 SymmetricEncryptionAlgorithm; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE DL_ObjectImplBase : public AlgorithmImpl +{ +public: + typedef SCHEME_OPTIONS SchemeOptions; + typedef typename KEY::Element Element; + + PrivateKey & AccessPrivateKey() {return m_key;} + PublicKey & AccessPublicKey() {return m_key;} + + // KeyAccessor + const KEY & GetKey() const {return m_key;} + KEY & AccessKey() {return m_key;} + +protected: + typename BASE::KeyInterface & AccessKeyInterface() {return m_key;} + const typename BASE::KeyInterface & GetKeyInterface() const {return m_key;} + + // for signature scheme + HashIdentifier GetHashIdentifier() const + { + typedef typename SchemeOptions::MessageEncodingMethod::HashIdentifierLookup HashLookup; + return HashLookup::template HashIdentifierLookup2::Lookup(); + } + size_t GetDigestSize() const + { + typedef CPP_TYPENAME SchemeOptions::HashFunction H; + return H::DIGESTSIZE; + } + +private: + KEY m_key; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE DL_ObjectImpl : public DL_ObjectImplBase +{ +public: + typedef typename KEY::Element Element; + +protected: + const DL_ElgamalLikeSignatureAlgorithm & GetSignatureAlgorithm() const + {return Singleton().Ref();} + const DL_KeyAgreementAlgorithm & GetKeyAgreementAlgorithm() const + {return Singleton().Ref();} + const DL_KeyDerivationAlgorithm & GetKeyDerivationAlgorithm() const + {return Singleton().Ref();} + const DL_SymmetricEncryptionAlgorithm & GetSymmetricEncryptionAlgorithm() const + {return Singleton().Ref();} + HashIdentifier GetHashIdentifier() const + {return HashIdentifier();} + const PK_SignatureMessageEncodingMethod & GetMessageEncodingInterface() const + {return Singleton().Ref();} +}; + +//! _ +template +class DL_SignerImpl : public DL_ObjectImpl, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey> +{ +public: + PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const + { + std::auto_ptr p(new PK_MessageAccumulatorImpl); + this->RestartMessageAccumulator(rng, *p); + return p.release(); + } +}; + +//! _ +template +class DL_VerifierImpl : public DL_ObjectImpl, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey> +{ +public: + PK_MessageAccumulator * NewVerificationAccumulator() const + { + return new PK_MessageAccumulatorImpl; + } +}; + +//! _ +template +class DL_EncryptorImpl : public DL_ObjectImpl, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey> +{ +}; + +//! _ +template +class DL_DecryptorImpl : public DL_ObjectImpl, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey> +{ +}; + +// ******************************************************** + +//! _ +template +class CRYPTOPP_NO_VTABLE DL_SimpleKeyAgreementDomainBase : public SimpleKeyAgreementDomain +{ +public: + typedef T Element; + + CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();} + unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);} + unsigned int PrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();} + unsigned int PublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);} + + void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const + { + Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent()); + x.Encode(privateKey, PrivateKeyLength()); + } + + void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const + { + const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); + Integer x(privateKey, PrivateKeyLength()); + Element y = params.ExponentiateBase(x); + params.EncodeElement(true, y, publicKey); + } + + bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const + { + try + { + const DL_GroupParameters ¶ms = GetAbstractGroupParameters(); + Integer x(privateKey, PrivateKeyLength()); + Element w = params.DecodeElement(otherPublicKey, validateOtherPublicKey); + + Element z = GetKeyAgreementAlgorithm().AgreeWithStaticPrivateKey( + GetAbstractGroupParameters(), w, validateOtherPublicKey, x); + params.EncodeElement(false, z, agreedValue); + } + catch (DL_BadElement &) + { + return false; + } + return true; + } + + const Element &GetGenerator() const {return GetAbstractGroupParameters().GetSubgroupGenerator();} + +protected: + virtual const DL_KeyAgreementAlgorithm & GetKeyAgreementAlgorithm() const =0; + virtual DL_GroupParameters & AccessAbstractGroupParameters() =0; + const DL_GroupParameters & GetAbstractGroupParameters() const {return const_cast *>(this)->AccessAbstractGroupParameters();} +}; + +enum CofactorMultiplicationOption {NO_COFACTOR_MULTIPLICTION, COMPATIBLE_COFACTOR_MULTIPLICTION, INCOMPATIBLE_COFACTOR_MULTIPLICTION}; +typedef EnumToType NoCofactorMultiplication; +typedef EnumToType CompatibleCofactorMultiplication; +typedef EnumToType IncompatibleCofactorMultiplication; + +//! DH key agreement algorithm +template +class DL_KeyAgreementAlgorithm_DH : public DL_KeyAgreementAlgorithm +{ +public: + typedef ELEMENT Element; + + static const char * CRYPTOPP_API StaticAlgorithmName() + {return COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION ? "DHC" : "DH";} + + Element AgreeWithEphemeralPrivateKey(const DL_GroupParameters ¶ms, const DL_FixedBasePrecomputation &publicPrecomputation, const Integer &privateExponent) const + { + return publicPrecomputation.Exponentiate(params.GetGroupPrecomputation(), + COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION ? privateExponent*params.GetCofactor() : privateExponent); + } + + Element AgreeWithStaticPrivateKey(const DL_GroupParameters ¶ms, const Element &publicElement, bool validateOtherPublicKey, const Integer &privateExponent) const + { + if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION) + { + const Integer &k = params.GetCofactor(); + return params.ExponentiateElement(publicElement, + ModularArithmetic(params.GetSubgroupOrder()).Divide(privateExponent, k)*k); + } + else if (COFACTOR_OPTION::ToEnum() == INCOMPATIBLE_COFACTOR_MULTIPLICTION) + return params.ExponentiateElement(publicElement, privateExponent*params.GetCofactor()); + else + { + assert(COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION); + + if (!validateOtherPublicKey) + return params.ExponentiateElement(publicElement, privateExponent); + + if (params.FastSubgroupCheckAvailable()) + { + if (!params.ValidateElement(2, publicElement, NULL)) + throw DL_BadElement(); + return params.ExponentiateElement(publicElement, privateExponent); + } + else + { + const Integer e[2] = {params.GetSubgroupOrder(), privateExponent}; + Element r[2]; + params.SimultaneousExponentiate(r, publicElement, e, 2); + if (!params.IsIdentity(r[0])) + throw DL_BadElement(); + return r[1]; + } + } + } +}; + +// ******************************************************** + +//! A template implementing constructors for public key algorithm classes +template +class CRYPTOPP_NO_VTABLE PK_FinalTemplate : public BASE +{ +public: + PK_FinalTemplate() {} + + PK_FinalTemplate(const CryptoMaterial &key) + {this->AccessKey().AssignFrom(key);} + + PK_FinalTemplate(BufferedTransformation &bt) + {this->AccessKey().BERDecode(bt);} + + PK_FinalTemplate(const AsymmetricAlgorithm &algorithm) + {this->AccessKey().AssignFrom(algorithm.GetMaterial());} + + PK_FinalTemplate(const Integer &v1) + {this->AccessKey().Initialize(v1);} + +#if (defined(_MSC_VER) && _MSC_VER < 1300) + + template + PK_FinalTemplate(T1 &v1, T2 &v2) + {this->AccessKey().Initialize(v1, v2);} + + template + PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3) + {this->AccessKey().Initialize(v1, v2, v3);} + + template + PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4) + {this->AccessKey().Initialize(v1, v2, v3, v4);} + + template + PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5);} + + template + PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);} + + template + PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6, T7 &v7) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);} + + template + PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6, T7 &v7, T8 &v8) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);} + +#else + + template + PK_FinalTemplate(const T1 &v1, const T2 &v2) + {this->AccessKey().Initialize(v1, v2);} + + template + PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3) + {this->AccessKey().Initialize(v1, v2, v3);} + + template + PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) + {this->AccessKey().Initialize(v1, v2, v3, v4);} + + template + PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5);} + + template + PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);} + + template + PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);} + + template + PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);} + + template + PK_FinalTemplate(T1 &v1, const T2 &v2) + {this->AccessKey().Initialize(v1, v2);} + + template + PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3) + {this->AccessKey().Initialize(v1, v2, v3);} + + template + PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) + {this->AccessKey().Initialize(v1, v2, v3, v4);} + + template + PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5);} + + template + PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);} + + template + PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);} + + template + PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8) + {this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);} + +#endif +}; + +//! Base class for public key encryption standard classes. These classes are used to select from variants of algorithms. Note that not all standards apply to all algorithms. +struct EncryptionStandard {}; + +//! Base class for public key signature standard classes. These classes are used to select from variants of algorithms. Note that not all standards apply to all algorithms. +struct SignatureStandard {}; + +template +class TF_ES; + +//! Trapdoor Function Based Encryption Scheme +template > +class TF_ES : public KEYS +{ + typedef typename STANDARD::EncryptionMessageEncodingMethod MessageEncodingMethod; + +public: + //! see EncryptionStandard for a list of standards + typedef STANDARD Standard; + typedef TF_CryptoSchemeOptions SchemeOptions; + + static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(KEYS::StaticAlgorithmName()) + "/" + MessageEncodingMethod::StaticAlgorithmName();} + + //! implements PK_Decryptor interface + typedef PK_FinalTemplate > Decryptor; + //! implements PK_Encryptor interface + typedef PK_FinalTemplate > Encryptor; +}; + +template // VC60 workaround: doesn't work if KEYS is first parameter +class TF_SS; + +//! Trapdoor Function Based Signature Scheme +template > // VC60 workaround: doesn't work if KEYS is first parameter +class TF_SS : public KEYS +{ +public: + //! see SignatureStandard for a list of standards + typedef STANDARD Standard; + typedef typename Standard::SignatureMessageEncodingMethod MessageEncodingMethod; + typedef TF_SignatureSchemeOptions SchemeOptions; + + static std::string CRYPTOPP_API StaticAlgorithmName() {return std::string(KEYS::StaticAlgorithmName()) + "/" + MessageEncodingMethod::StaticAlgorithmName() + "(" + H::StaticAlgorithmName() + ")";} + + //! implements PK_Signer interface + typedef PK_FinalTemplate > Signer; + //! implements PK_Verifier interface + typedef PK_FinalTemplate > Verifier; +}; + +template +class DL_SS; + +//! Discrete Log Based Signature Scheme +template > +class DL_SS : public KEYS +{ + typedef DL_SignatureSchemeOptions SchemeOptions; + +public: + static std::string StaticAlgorithmName() {return SA::StaticAlgorithmName() + std::string("/EMSA1(") + H::StaticAlgorithmName() + ")";} + + //! implements PK_Signer interface + typedef PK_FinalTemplate > Signer; + //! implements PK_Verifier interface + typedef PK_FinalTemplate > Verifier; +}; + +//! Discrete Log Based Encryption Scheme +template +class DL_ES : public KEYS +{ + typedef DL_CryptoSchemeOptions SchemeOptions; + +public: + //! implements PK_Decryptor interface + typedef PK_FinalTemplate > Decryptor; + //! implements PK_Encryptor interface + typedef PK_FinalTemplate > Encryptor; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/queue.cpp b/src-cryptopp/queue.cpp new file mode 100644 index 0000000..ae05a78 --- /dev/null +++ b/src-cryptopp/queue.cpp @@ -0,0 +1,564 @@ +// queue.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "queue.h" +#include "filters.h" + +NAMESPACE_BEGIN(CryptoPP) + +static const unsigned int s_maxAutoNodeSize = 16*1024; + +// this class for use by ByteQueue only +class ByteQueueNode +{ +public: + ByteQueueNode(size_t maxSize) + : buf(maxSize) + { + m_head = m_tail = 0; + next = 0; + } + + inline size_t MaxSize() const {return buf.size();} + + inline size_t CurrentSize() const + { + return m_tail-m_head; + } + + inline bool UsedUp() const + { + return (m_head==MaxSize()); + } + + inline void Clear() + { + m_head = m_tail = 0; + } + + inline size_t Put(const byte *begin, size_t length) + { + size_t l = STDMIN(length, MaxSize()-m_tail); + if (buf+m_tail != begin) + memcpy(buf+m_tail, begin, l); + m_tail += l; + return l; + } + + inline size_t Peek(byte &outByte) const + { + if (m_tail==m_head) + return 0; + + outByte=buf[m_head]; + return 1; + } + + inline size_t Peek(byte *target, size_t copyMax) const + { + size_t len = STDMIN(copyMax, m_tail-m_head); + memcpy(target, buf+m_head, len); + return len; + } + + inline size_t CopyTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL) const + { + size_t len = m_tail-m_head; + target.ChannelPut(channel, buf+m_head, len); + return len; + } + + inline size_t CopyTo(BufferedTransformation &target, size_t copyMax, const std::string &channel=DEFAULT_CHANNEL) const + { + size_t len = STDMIN(copyMax, m_tail-m_head); + target.ChannelPut(channel, buf+m_head, len); + return len; + } + + inline size_t Get(byte &outByte) + { + size_t len = Peek(outByte); + m_head += len; + return len; + } + + inline size_t Get(byte *outString, size_t getMax) + { + size_t len = Peek(outString, getMax); + m_head += len; + return len; + } + + inline size_t TransferTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL) + { + size_t len = m_tail-m_head; + target.ChannelPutModifiable(channel, buf+m_head, len); + m_head = m_tail; + return len; + } + + inline size_t TransferTo(BufferedTransformation &target, lword transferMax, const std::string &channel=DEFAULT_CHANNEL) + { + size_t len = UnsignedMin(m_tail-m_head, transferMax); + target.ChannelPutModifiable(channel, buf+m_head, len); + m_head += len; + return len; + } + + inline size_t Skip(size_t skipMax) + { + size_t len = STDMIN(skipMax, m_tail-m_head); + m_head += len; + return len; + } + + inline byte operator[](size_t i) const + { + return buf[m_head+i]; + } + + ByteQueueNode *next; + + SecByteBlock buf; + size_t m_head, m_tail; +}; + +// ******************************************************** + +ByteQueue::ByteQueue(size_t nodeSize) + : m_lazyLength(0) +{ + SetNodeSize(nodeSize); + m_head = m_tail = new ByteQueueNode(m_nodeSize); +} + +void ByteQueue::SetNodeSize(size_t nodeSize) +{ + m_autoNodeSize = !nodeSize; + m_nodeSize = m_autoNodeSize ? 256 : nodeSize; +} + +ByteQueue::ByteQueue(const ByteQueue ©) +{ + CopyFrom(copy); +} + +void ByteQueue::CopyFrom(const ByteQueue ©) +{ + m_lazyLength = 0; + m_autoNodeSize = copy.m_autoNodeSize; + m_nodeSize = copy.m_nodeSize; + m_head = m_tail = new ByteQueueNode(*copy.m_head); + + for (ByteQueueNode *current=copy.m_head->next; current; current=current->next) + { + m_tail->next = new ByteQueueNode(*current); + m_tail = m_tail->next; + } + + m_tail->next = NULL; + + Put(copy.m_lazyString, copy.m_lazyLength); +} + +ByteQueue::~ByteQueue() +{ + Destroy(); +} + +void ByteQueue::Destroy() +{ + for (ByteQueueNode *next, *current=m_head; current; current=next) + { + next=current->next; + delete current; + } +} + +void ByteQueue::IsolatedInitialize(const NameValuePairs ¶meters) +{ + m_nodeSize = parameters.GetIntValueWithDefault("NodeSize", 256); + Clear(); +} + +lword ByteQueue::CurrentSize() const +{ + lword size=0; + + for (ByteQueueNode *current=m_head; current; current=current->next) + size += current->CurrentSize(); + + return size + m_lazyLength; +} + +bool ByteQueue::IsEmpty() const +{ + return m_head==m_tail && m_head->CurrentSize()==0 && m_lazyLength==0; +} + +void ByteQueue::Clear() +{ + for (ByteQueueNode *next, *current=m_head->next; current; current=next) + { + next=current->next; + delete current; + } + + m_tail = m_head; + m_head->Clear(); + m_head->next = NULL; + m_lazyLength = 0; +} + +size_t ByteQueue::Put2(const byte *inString, size_t length, int messageEnd, bool blocking) +{ + if (m_lazyLength > 0) + FinalizeLazyPut(); + + size_t len; + while ((len=m_tail->Put(inString, length)) < length) + { + inString += len; + length -= len; + if (m_autoNodeSize && m_nodeSize < s_maxAutoNodeSize) + do + { + m_nodeSize *= 2; + } + while (m_nodeSize < length && m_nodeSize < s_maxAutoNodeSize); + m_tail->next = new ByteQueueNode(STDMAX(m_nodeSize, length)); + m_tail = m_tail->next; + } + + return 0; +} + +void ByteQueue::CleanupUsedNodes() +{ + while (m_head != m_tail && m_head->UsedUp()) + { + ByteQueueNode *temp=m_head; + m_head=m_head->next; + delete temp; + } + + if (m_head->CurrentSize() == 0) + m_head->Clear(); +} + +void ByteQueue::LazyPut(const byte *inString, size_t size) +{ + if (m_lazyLength > 0) + FinalizeLazyPut(); + + if (inString == m_tail->buf+m_tail->m_tail) + Put(inString, size); + else + { + m_lazyString = const_cast(inString); + m_lazyLength = size; + m_lazyStringModifiable = false; + } +} + +void ByteQueue::LazyPutModifiable(byte *inString, size_t size) +{ + if (m_lazyLength > 0) + FinalizeLazyPut(); + m_lazyString = inString; + m_lazyLength = size; + m_lazyStringModifiable = true; +} + +void ByteQueue::UndoLazyPut(size_t size) +{ + if (m_lazyLength < size) + throw InvalidArgument("ByteQueue: size specified for UndoLazyPut is too large"); + + m_lazyLength -= size; +} + +void ByteQueue::FinalizeLazyPut() +{ + size_t len = m_lazyLength; + m_lazyLength = 0; + if (len) + Put(m_lazyString, len); +} + +size_t ByteQueue::Get(byte &outByte) +{ + if (m_head->Get(outByte)) + { + if (m_head->UsedUp()) + CleanupUsedNodes(); + return 1; + } + else if (m_lazyLength > 0) + { + outByte = *m_lazyString++; + m_lazyLength--; + return 1; + } + else + return 0; +} + +size_t ByteQueue::Get(byte *outString, size_t getMax) +{ + ArraySink sink(outString, getMax); + return (size_t)TransferTo(sink, getMax); +} + +size_t ByteQueue::Peek(byte &outByte) const +{ + if (m_head->Peek(outByte)) + return 1; + else if (m_lazyLength > 0) + { + outByte = *m_lazyString; + return 1; + } + else + return 0; +} + +size_t ByteQueue::Peek(byte *outString, size_t peekMax) const +{ + ArraySink sink(outString, peekMax); + return (size_t)CopyTo(sink, peekMax); +} + +size_t ByteQueue::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) +{ + if (blocking) + { + lword bytesLeft = transferBytes; + for (ByteQueueNode *current=m_head; bytesLeft && current; current=current->next) + bytesLeft -= current->TransferTo(target, bytesLeft, channel); + CleanupUsedNodes(); + + size_t len = (size_t)STDMIN(bytesLeft, (lword)m_lazyLength); + if (len) + { + if (m_lazyStringModifiable) + target.ChannelPutModifiable(channel, m_lazyString, len); + else + target.ChannelPut(channel, m_lazyString, len); + m_lazyString += len; + m_lazyLength -= len; + bytesLeft -= len; + } + transferBytes -= bytesLeft; + return 0; + } + else + { + Walker walker(*this); + size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking); + Skip(transferBytes); + return blockedBytes; + } +} + +size_t ByteQueue::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const +{ + Walker walker(*this); + walker.Skip(begin); + lword transferBytes = end-begin; + size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking); + begin += transferBytes; + return blockedBytes; +} + +void ByteQueue::Unget(byte inByte) +{ + Unget(&inByte, 1); +} + +void ByteQueue::Unget(const byte *inString, size_t length) +{ + size_t len = STDMIN(length, m_head->m_head); + length -= len; + m_head->m_head -= len; + memcpy(m_head->buf + m_head->m_head, inString + length, len); + + if (length > 0) + { + ByteQueueNode *newHead = new ByteQueueNode(length); + newHead->next = m_head; + m_head = newHead; + m_head->Put(inString, length); + } +} + +const byte * ByteQueue::Spy(size_t &contiguousSize) const +{ + contiguousSize = m_head->m_tail - m_head->m_head; + if (contiguousSize == 0 && m_lazyLength > 0) + { + contiguousSize = m_lazyLength; + return m_lazyString; + } + else + return m_head->buf + m_head->m_head; +} + +byte * ByteQueue::CreatePutSpace(size_t &size) +{ + if (m_lazyLength > 0) + FinalizeLazyPut(); + + if (m_tail->m_tail == m_tail->MaxSize()) + { + m_tail->next = new ByteQueueNode(STDMAX(m_nodeSize, size)); + m_tail = m_tail->next; + } + + size = m_tail->MaxSize() - m_tail->m_tail; + return m_tail->buf + m_tail->m_tail; +} + +ByteQueue & ByteQueue::operator=(const ByteQueue &rhs) +{ + Destroy(); + CopyFrom(rhs); + return *this; +} + +bool ByteQueue::operator==(const ByteQueue &rhs) const +{ + const lword currentSize = CurrentSize(); + + if (currentSize != rhs.CurrentSize()) + return false; + + Walker walker1(*this), walker2(rhs); + byte b1, b2; + + while (walker1.Get(b1) && walker2.Get(b2)) + if (b1 != b2) + return false; + + return true; +} + +byte ByteQueue::operator[](lword i) const +{ + for (ByteQueueNode *current=m_head; current; current=current->next) + { + if (i < current->CurrentSize()) + return (*current)[(size_t)i]; + + i -= current->CurrentSize(); + } + + assert(i < m_lazyLength); + return m_lazyString[i]; +} + +void ByteQueue::swap(ByteQueue &rhs) +{ + std::swap(m_autoNodeSize, rhs.m_autoNodeSize); + std::swap(m_nodeSize, rhs.m_nodeSize); + std::swap(m_head, rhs.m_head); + std::swap(m_tail, rhs.m_tail); + std::swap(m_lazyString, rhs.m_lazyString); + std::swap(m_lazyLength, rhs.m_lazyLength); + std::swap(m_lazyStringModifiable, rhs.m_lazyStringModifiable); +} + +// ******************************************************** + +void ByteQueue::Walker::IsolatedInitialize(const NameValuePairs ¶meters) +{ + m_node = m_queue.m_head; + m_position = 0; + m_offset = 0; + m_lazyString = m_queue.m_lazyString; + m_lazyLength = m_queue.m_lazyLength; +} + +size_t ByteQueue::Walker::Get(byte &outByte) +{ + ArraySink sink(&outByte, 1); + return (size_t)TransferTo(sink, 1); +} + +size_t ByteQueue::Walker::Get(byte *outString, size_t getMax) +{ + ArraySink sink(outString, getMax); + return (size_t)TransferTo(sink, getMax); +} + +size_t ByteQueue::Walker::Peek(byte &outByte) const +{ + ArraySink sink(&outByte, 1); + return (size_t)CopyTo(sink, 1); +} + +size_t ByteQueue::Walker::Peek(byte *outString, size_t peekMax) const +{ + ArraySink sink(outString, peekMax); + return (size_t)CopyTo(sink, peekMax); +} + +size_t ByteQueue::Walker::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) +{ + lword bytesLeft = transferBytes; + size_t blockedBytes = 0; + + while (m_node) + { + size_t len = (size_t)STDMIN(bytesLeft, (lword)m_node->CurrentSize()-m_offset); + blockedBytes = target.ChannelPut2(channel, m_node->buf+m_node->m_head+m_offset, len, 0, blocking); + + if (blockedBytes) + goto done; + + m_position += len; + bytesLeft -= len; + + if (!bytesLeft) + { + m_offset += len; + goto done; + } + + m_node = m_node->next; + m_offset = 0; + } + + if (bytesLeft && m_lazyLength) + { + size_t len = (size_t)STDMIN(bytesLeft, (lword)m_lazyLength); + blockedBytes = target.ChannelPut2(channel, m_lazyString, len, 0, blocking); + if (blockedBytes) + goto done; + + m_lazyString += len; + m_lazyLength -= len; + bytesLeft -= len; + } + +done: + transferBytes -= bytesLeft; + return blockedBytes; +} + +size_t ByteQueue::Walker::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const +{ + Walker walker(*this); + walker.Skip(begin); + lword transferBytes = end-begin; + size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking); + begin += transferBytes; + return blockedBytes; +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/queue.h b/src-cryptopp/queue.h new file mode 100644 index 0000000..75f7807 --- /dev/null +++ b/src-cryptopp/queue.h @@ -0,0 +1,143 @@ +// specification file for an unlimited queue for storing bytes + +#ifndef CRYPTOPP_QUEUE_H +#define CRYPTOPP_QUEUE_H + +#include "simple.h" +//#include + +NAMESPACE_BEGIN(CryptoPP) + +/** The queue is implemented as a linked list of byte arrays, but you don't need to + know about that. So just ignore this next line. :) */ +class ByteQueueNode; + +//! Byte Queue +class CRYPTOPP_DLL ByteQueue : public Bufferless +{ +public: + ByteQueue(size_t nodeSize=0); + ByteQueue(const ByteQueue ©); + ~ByteQueue(); + + lword MaxRetrievable() const + {return CurrentSize();} + bool AnyRetrievable() const + {return !IsEmpty();} + + void IsolatedInitialize(const NameValuePairs ¶meters); + byte * CreatePutSpace(size_t &size); + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking); + + size_t Get(byte &outByte); + size_t Get(byte *outString, size_t getMax); + + size_t Peek(byte &outByte) const; + size_t Peek(byte *outString, size_t peekMax) const; + + size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); + size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const; + + // these member functions are not inherited + void SetNodeSize(size_t nodeSize); + + lword CurrentSize() const; + bool IsEmpty() const; + + void Clear(); + + void Unget(byte inByte); + void Unget(const byte *inString, size_t length); + + const byte * Spy(size_t &contiguousSize) const; + + void LazyPut(const byte *inString, size_t size); + void LazyPutModifiable(byte *inString, size_t size); + void UndoLazyPut(size_t size); + void FinalizeLazyPut(); + + ByteQueue & operator=(const ByteQueue &rhs); + bool operator==(const ByteQueue &rhs) const; + byte operator[](lword i) const; + void swap(ByteQueue &rhs); + + class Walker : public InputRejecting + { + public: + Walker(const ByteQueue &queue) + : m_queue(queue) {Initialize();} + + lword GetCurrentPosition() {return m_position;} + + lword MaxRetrievable() const + {return m_queue.CurrentSize() - m_position;} + + void IsolatedInitialize(const NameValuePairs ¶meters); + + size_t Get(byte &outByte); + size_t Get(byte *outString, size_t getMax); + + size_t Peek(byte &outByte) const; + size_t Peek(byte *outString, size_t peekMax) const; + + size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true); + size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const; + + private: + const ByteQueue &m_queue; + const ByteQueueNode *m_node; + lword m_position; + size_t m_offset; + const byte *m_lazyString; + size_t m_lazyLength; + }; + + friend class Walker; + +private: + void CleanupUsedNodes(); + void CopyFrom(const ByteQueue ©); + void Destroy(); + + bool m_autoNodeSize; + size_t m_nodeSize; + ByteQueueNode *m_head, *m_tail; + byte *m_lazyString; + size_t m_lazyLength; + bool m_lazyStringModifiable; +}; + +//! use this to make sure LazyPut is finalized in event of exception +class CRYPTOPP_DLL LazyPutter +{ +public: + LazyPutter(ByteQueue &bq, const byte *inString, size_t size) + : m_bq(bq) {bq.LazyPut(inString, size);} + ~LazyPutter() + {try {m_bq.FinalizeLazyPut();} catch(...) {}} +protected: + LazyPutter(ByteQueue &bq) : m_bq(bq) {} +private: + ByteQueue &m_bq; +}; + +//! like LazyPutter, but does a LazyPutModifiable instead +class LazyPutterModifiable : public LazyPutter +{ +public: + LazyPutterModifiable(ByteQueue &bq, byte *inString, size_t size) + : LazyPutter(bq) {bq.LazyPutModifiable(inString, size);} +}; + +NAMESPACE_END + +#ifndef __BORLANDC__ +NAMESPACE_BEGIN(std) +template<> inline void swap(CryptoPP::ByteQueue &a, CryptoPP::ByteQueue &b) +{ + a.swap(b); +} +NAMESPACE_END +#endif + +#endif diff --git a/src-cryptopp/randpool.cpp b/src-cryptopp/randpool.cpp new file mode 100644 index 0000000..4e935fe --- /dev/null +++ b/src-cryptopp/randpool.cpp @@ -0,0 +1,52 @@ +// randpool.cpp - written and placed in the public domain by Wei Dai +// RandomPool used to follow the design of randpool in PGP 2.6.x, +// but as of version 5.5 it has been redesigned to reduce the risk +// of reusing random numbers after state rollback (which may occur +// when running in a virtual machine like VMware). + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "randpool.h" +#include "aes.h" +#include "sha.h" + +NAMESPACE_BEGIN(CryptoPP) + +RandomPool::RandomPool() + : m_pCipher(new AES::Encryption), m_keySet(false) +{ + memset(m_key, 0, m_key.SizeInBytes()); + memset(m_seed, 0, m_seed.SizeInBytes()); +} + +void RandomPool::IncorporateEntropy(const byte *input, size_t length) +{ + SHA256 hash; + hash.Update(m_key, 32); + hash.Update(input, length); + hash.Final(m_key); + m_keySet = false; +} + +void RandomPool::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size) +{ + if (size > 0) + { + if (!m_keySet) + m_pCipher->SetKey(m_key, 32); + + do + { + m_pCipher->ProcessBlock(m_seed); + size_t len = UnsignedMin(16, size); + target.ChannelPut(channel, m_seed, len); + size -= len; + } while (size > 0); + } +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/randpool.h b/src-cryptopp/randpool.h new file mode 100644 index 0000000..c25bc9b --- /dev/null +++ b/src-cryptopp/randpool.h @@ -0,0 +1,33 @@ +#ifndef CRYPTOPP_RANDPOOL_H +#define CRYPTOPP_RANDPOOL_H + +#include "cryptlib.h" +#include "filters.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! Randomness Pool +/*! This class can be used to generate cryptographic quality + pseudorandom bytes after seeding the pool with IncorporateEntropy() */ +class CRYPTOPP_DLL RandomPool : public RandomNumberGenerator, public NotCopyable +{ +public: + RandomPool(); + + bool CanIncorporateEntropy() const {return true;} + void IncorporateEntropy(const byte *input, size_t length); + void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size); + + // for backwards compatibility. use RandomNumberSource, RandomNumberStore, and RandomNumberSink for other BufferTransformation functionality + void Put(const byte *input, size_t length) {IncorporateEntropy(input, length);} + +private: + FixedSizeSecBlock m_key; + FixedSizeSecBlock m_seed; + member_ptr m_pCipher; + bool m_keySet; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/rdtables.cpp b/src-cryptopp/rdtables.cpp new file mode 100644 index 0000000..4937932 --- /dev/null +++ b/src-cryptopp/rdtables.cpp @@ -0,0 +1,172 @@ +// Rijndael tables + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "rijndael.h" + +// VC60 workaround: gives a C4786 warning without this function +// when runtime lib is set to multithread debug DLL +// even though warning 4786 is disabled! +void Rijndael_VC60Workaround() +{ +} + +NAMESPACE_BEGIN(CryptoPP) + +/* +Te0[x] = S [x].[02, 01, 01, 03]; +Te1[x] = S [x].[03, 02, 01, 01]; +Te2[x] = S [x].[01, 03, 02, 01]; +Te3[x] = S [x].[01, 01, 03, 02]; + +Td0[x] = Si[x].[0e, 09, 0d, 0b]; +Td1[x] = Si[x].[0b, 0e, 09, 0d]; +Td2[x] = Si[x].[0d, 0b, 0e, 09]; +Td3[x] = Si[x].[09, 0d, 0b, 0e]; +*/ + +const byte Rijndael::Base::Se[256] = { + 0x63, 0x7c, 0x77, 0x7b, + 0xf2, 0x6b, 0x6f, 0xc5, + 0x30, 0x01, 0x67, 0x2b, + 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, + 0xfa, 0x59, 0x47, 0xf0, + 0xad, 0xd4, 0xa2, 0xaf, + 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, + 0x36, 0x3f, 0xf7, 0xcc, + 0x34, 0xa5, 0xe5, 0xf1, + 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, + 0x18, 0x96, 0x05, 0x9a, + 0x07, 0x12, 0x80, 0xe2, + 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, + 0x1b, 0x6e, 0x5a, 0xa0, + 0x52, 0x3b, 0xd6, 0xb3, + 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, + 0x20, 0xfc, 0xb1, 0x5b, + 0x6a, 0xcb, 0xbe, 0x39, + 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, + 0x43, 0x4d, 0x33, 0x85, + 0x45, 0xf9, 0x02, 0x7f, + 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, + 0x92, 0x9d, 0x38, 0xf5, + 0xbc, 0xb6, 0xda, 0x21, + 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, + 0x5f, 0x97, 0x44, 0x17, + 0xc4, 0xa7, 0x7e, 0x3d, + 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, + 0x22, 0x2a, 0x90, 0x88, + 0x46, 0xee, 0xb8, 0x14, + 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, + 0x49, 0x06, 0x24, 0x5c, + 0xc2, 0xd3, 0xac, 0x62, + 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, + 0x8d, 0xd5, 0x4e, 0xa9, + 0x6c, 0x56, 0xf4, 0xea, + 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, + 0x1c, 0xa6, 0xb4, 0xc6, + 0xe8, 0xdd, 0x74, 0x1f, + 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, + 0x48, 0x03, 0xf6, 0x0e, + 0x61, 0x35, 0x57, 0xb9, + 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, + 0x69, 0xd9, 0x8e, 0x94, + 0x9b, 0x1e, 0x87, 0xe9, + 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, + 0xbf, 0xe6, 0x42, 0x68, + 0x41, 0x99, 0x2d, 0x0f, + 0xb0, 0x54, 0xbb, 0x16, +}; + +const byte Rijndael::Base::Sd[256] = { + 0x52, 0x09, 0x6a, 0xd5, + 0x30, 0x36, 0xa5, 0x38, + 0xbf, 0x40, 0xa3, 0x9e, + 0x81, 0xf3, 0xd7, 0xfb, + 0x7c, 0xe3, 0x39, 0x82, + 0x9b, 0x2f, 0xff, 0x87, + 0x34, 0x8e, 0x43, 0x44, + 0xc4, 0xde, 0xe9, 0xcb, + 0x54, 0x7b, 0x94, 0x32, + 0xa6, 0xc2, 0x23, 0x3d, + 0xee, 0x4c, 0x95, 0x0b, + 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, + 0x28, 0xd9, 0x24, 0xb2, + 0x76, 0x5b, 0xa2, 0x49, + 0x6d, 0x8b, 0xd1, 0x25, + 0x72, 0xf8, 0xf6, 0x64, + 0x86, 0x68, 0x98, 0x16, + 0xd4, 0xa4, 0x5c, 0xcc, + 0x5d, 0x65, 0xb6, 0x92, + 0x6c, 0x70, 0x48, 0x50, + 0xfd, 0xed, 0xb9, 0xda, + 0x5e, 0x15, 0x46, 0x57, + 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, + 0x8c, 0xbc, 0xd3, 0x0a, + 0xf7, 0xe4, 0x58, 0x05, + 0xb8, 0xb3, 0x45, 0x06, + 0xd0, 0x2c, 0x1e, 0x8f, + 0xca, 0x3f, 0x0f, 0x02, + 0xc1, 0xaf, 0xbd, 0x03, + 0x01, 0x13, 0x8a, 0x6b, + 0x3a, 0x91, 0x11, 0x41, + 0x4f, 0x67, 0xdc, 0xea, + 0x97, 0xf2, 0xcf, 0xce, + 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, + 0xe7, 0xad, 0x35, 0x85, + 0xe2, 0xf9, 0x37, 0xe8, + 0x1c, 0x75, 0xdf, 0x6e, + 0x47, 0xf1, 0x1a, 0x71, + 0x1d, 0x29, 0xc5, 0x89, + 0x6f, 0xb7, 0x62, 0x0e, + 0xaa, 0x18, 0xbe, 0x1b, + 0xfc, 0x56, 0x3e, 0x4b, + 0xc6, 0xd2, 0x79, 0x20, + 0x9a, 0xdb, 0xc0, 0xfe, + 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, + 0x88, 0x07, 0xc7, 0x31, + 0xb1, 0x12, 0x10, 0x59, + 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, + 0x19, 0xb5, 0x4a, 0x0d, + 0x2d, 0xe5, 0x7a, 0x9f, + 0x93, 0xc9, 0x9c, 0xef, + 0xa0, 0xe0, 0x3b, 0x4d, + 0xae, 0x2a, 0xf5, 0xb0, + 0xc8, 0xeb, 0xbb, 0x3c, + 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, + 0xba, 0x77, 0xd6, 0x26, + 0xe1, 0x69, 0x14, 0x63, + 0x55, 0x21, 0x0c, 0x7d, +}; + +const word32 Rijndael::Base::rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/rijndael.cpp b/src-cryptopp/rijndael.cpp new file mode 100644 index 0000000..ba9bcc8 --- /dev/null +++ b/src-cryptopp/rijndael.cpp @@ -0,0 +1,981 @@ +// rijndael.cpp - modified by Chris Morgan +// and Wei Dai from Paulo Baretto's Rijndael implementation +// The original code and all modifications are in the public domain. + +// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM rijndael.cpp" to generate MASM code + +/* +Feb 2009: The x86/x64 assembly code was rewritten in by Wei Dai to do counter mode +caching, which was invented by Hongjun Wu and popularized by Daniel J. Bernstein +and Peter Schwabe in their paper "New AES software speed records". The round +function was also modified to include a trick similar to one in Brian Gladman's +x86 assembly code, doing an 8-bit register move to minimize the number of +register spills. Also switched to compressed tables and copying round keys to +the stack. + +The C++ implementation now uses compressed tables if +CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS is defined. +*/ + +/* +July 2006: Defense against timing attacks was added in by Wei Dai. + +The code now uses smaller tables in the first and last rounds, +and preloads them into L1 cache before usage (by loading at least +one element in each cache line). + +We try to delay subsequent accesses to each table (used in the first +and last rounds) until all of the table has been preloaded. Hopefully +the compiler isn't smart enough to optimize that code away. + +After preloading the table, we also try not to access any memory location +other than the table and the stack, in order to prevent table entries from +being unloaded from L1 cache, until that round is finished. +(Some popular CPUs have 2-way associative caches.) +*/ + +// This is the original introductory comment: + +/** + * version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * author Vincent Rijmen + * author Antoon Bosselaers + * author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS +#ifndef CRYPTOPP_GENERATE_X64_MASM + +#include "rijndael.h" +#include "misc.h" +#include "cpu.h" + +NAMESPACE_BEGIN(CryptoPP) + +#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE) +namespace rdtable {CRYPTOPP_ALIGN_DATA(16) word64 Te[256+2];} +using namespace rdtable; +#else +static word64 Te[256]; +#endif +static word64 Td[256]; +#else +static word32 Te[256*4], Td[256*4]; +#endif +static volatile bool s_TeFilled = false, s_TdFilled = false; + +// ************************* Portable Code ************************************ + +#define QUARTER_ROUND(L, T, t, a, b, c, d) \ + a ^= L(T, 3, byte(t)); t >>= 8;\ + b ^= L(T, 2, byte(t)); t >>= 8;\ + c ^= L(T, 1, byte(t)); t >>= 8;\ + d ^= L(T, 0, t); + +#define QUARTER_ROUND_LE(t, a, b, c, d) \ + tempBlock[a] = ((byte *)(Te+byte(t)))[1]; t >>= 8;\ + tempBlock[b] = ((byte *)(Te+byte(t)))[1]; t >>= 8;\ + tempBlock[c] = ((byte *)(Te+byte(t)))[1]; t >>= 8;\ + tempBlock[d] = ((byte *)(Te+t))[1]; + +#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS + #define QUARTER_ROUND_LD(t, a, b, c, d) \ + tempBlock[a] = ((byte *)(Td+byte(t)))[GetNativeByteOrder()*7]; t >>= 8;\ + tempBlock[b] = ((byte *)(Td+byte(t)))[GetNativeByteOrder()*7]; t >>= 8;\ + tempBlock[c] = ((byte *)(Td+byte(t)))[GetNativeByteOrder()*7]; t >>= 8;\ + tempBlock[d] = ((byte *)(Td+t))[GetNativeByteOrder()*7]; +#else + #define QUARTER_ROUND_LD(t, a, b, c, d) \ + tempBlock[a] = Sd[byte(t)]; t >>= 8;\ + tempBlock[b] = Sd[byte(t)]; t >>= 8;\ + tempBlock[c] = Sd[byte(t)]; t >>= 8;\ + tempBlock[d] = Sd[t]; +#endif + +#define QUARTER_ROUND_E(t, a, b, c, d) QUARTER_ROUND(TL_M, Te, t, a, b, c, d) +#define QUARTER_ROUND_D(t, a, b, c, d) QUARTER_ROUND(TL_M, Td, t, a, b, c, d) + +#ifdef IS_LITTLE_ENDIAN + #define QUARTER_ROUND_FE(t, a, b, c, d) QUARTER_ROUND(TL_F, Te, t, d, c, b, a) + #define QUARTER_ROUND_FD(t, a, b, c, d) QUARTER_ROUND(TL_F, Td, t, d, c, b, a) + #ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS + #define TL_F(T, i, x) (*(word32 *)((byte *)T + x*8 + (6-i)%4+1)) + #define TL_M(T, i, x) (*(word32 *)((byte *)T + x*8 + (i+3)%4+1)) + #else + #define TL_F(T, i, x) rotrFixed(T[x], (3-i)*8) + #define TL_M(T, i, x) T[i*256 + x] + #endif +#else + #define QUARTER_ROUND_FE(t, a, b, c, d) QUARTER_ROUND(TL_F, Te, t, a, b, c, d) + #define QUARTER_ROUND_FD(t, a, b, c, d) QUARTER_ROUND(TL_F, Td, t, a, b, c, d) + #ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS + #define TL_F(T, i, x) (*(word32 *)((byte *)T + x*8 + (4-i)%4)) + #define TL_M TL_F + #else + #define TL_F(T, i, x) rotrFixed(T[x], i*8) + #define TL_M(T, i, x) T[i*256 + x] + #endif +#endif + + +#define f2(x) ((x<<1)^(((x>>7)&1)*0x11b)) +#define f4(x) ((x<<2)^(((x>>6)&1)*0x11b)^(((x>>6)&2)*0x11b)) +#define f8(x) ((x<<3)^(((x>>5)&1)*0x11b)^(((x>>5)&2)*0x11b)^(((x>>5)&4)*0x11b)) + +#define f3(x) (f2(x) ^ x) +#define f9(x) (f8(x) ^ x) +#define fb(x) (f8(x) ^ f2(x) ^ x) +#define fd(x) (f8(x) ^ f4(x) ^ x) +#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) + +void Rijndael::Base::FillEncTable() +{ + for (int i=0; i<256; i++) + { + byte x = Se[i]; +#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS + word32 y = word32(x)<<8 | word32(x)<<16 | word32(f2(x))<<24; + Te[i] = word64(y | f3(x))<<32 | y; +#else + word32 y = f3(x) | word32(x)<<8 | word32(x)<<16 | word32(f2(x))<<24; + for (int j=0; j<4; j++) + { + Te[i+j*256] = y; + y = rotrFixed(y, 8); + } +#endif + } +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE) + Te[256] = Te[257] = 0; +#endif + s_TeFilled = true; +} + +void Rijndael::Base::FillDecTable() +{ + for (int i=0; i<256; i++) + { + byte x = Sd[i]; +#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS + word32 y = word32(fd(x))<<8 | word32(f9(x))<<16 | word32(fe(x))<<24; + Td[i] = word64(y | fb(x))<<32 | y | x; +#else + word32 y = fb(x) | word32(fd(x))<<8 | word32(f9(x))<<16 | word32(fe(x))<<24;; + for (int j=0; j<4; j++) + { + Td[i+j*256] = y; + y = rotrFixed(y, 8); + } +#endif + } + s_TdFilled = true; +} + +void Rijndael::Base::UncheckedSetKey(const byte *userKey, unsigned int keylen, const NameValuePairs &) +{ + AssertValidKeyLength(keylen); + + m_rounds = keylen/4 + 6; + m_key.New(4*(m_rounds+1)); + + word32 temp, *rk = m_key; + const word32 *rc = rcon; + + GetUserKey(BIG_ENDIAN_ORDER, rk, keylen/4, userKey, keylen); + + while (true) + { + temp = rk[keylen/4-1]; + rk[keylen/4] = rk[0] ^ + (word32(Se[GETBYTE(temp, 2)]) << 24) ^ + (word32(Se[GETBYTE(temp, 1)]) << 16) ^ + (word32(Se[GETBYTE(temp, 0)]) << 8) ^ + Se[GETBYTE(temp, 3)] ^ + *(rc++); + rk[keylen/4+1] = rk[1] ^ rk[keylen/4]; + rk[keylen/4+2] = rk[2] ^ rk[keylen/4+1]; + rk[keylen/4+3] = rk[3] ^ rk[keylen/4+2]; + + if (rk + keylen/4 + 4 == m_key.end()) + break; + + if (keylen == 24) + { + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + } + else if (keylen == 32) + { + temp = rk[11]; + rk[12] = rk[ 4] ^ + (word32(Se[GETBYTE(temp, 3)]) << 24) ^ + (word32(Se[GETBYTE(temp, 2)]) << 16) ^ + (word32(Se[GETBYTE(temp, 1)]) << 8) ^ + Se[GETBYTE(temp, 0)]; + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + } + rk += keylen/4; + } + + if (IsForwardTransformation()) + { + if (!s_TeFilled) + FillEncTable(); + } + else + { + if (!s_TdFilled) + FillDecTable(); + + unsigned int i, j; + rk = m_key; + + /* invert the order of the round keys: */ + for (i = 0, j = 4*m_rounds; i < j; i += 4, j -= 4) { + temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; + temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; + temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; + temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; + } + +#define InverseMixColumn(x) x = TL_M(Td, 0, Se[GETBYTE(x, 3)]) ^ TL_M(Td, 1, Se[GETBYTE(x, 2)]) ^ TL_M(Td, 2, Se[GETBYTE(x, 1)]) ^ TL_M(Td, 3, Se[GETBYTE(x, 0)]) + + /* apply the inverse MixColumn transform to all round keys but the first and the last: */ + for (i = 1; i < m_rounds; i++) { + rk += 4; + InverseMixColumn(rk[0]); + InverseMixColumn(rk[1]); + InverseMixColumn(rk[2]); + InverseMixColumn(rk[3]); + } + } + + ConditionalByteReverse(BIG_ENDIAN_ORDER, m_key.begin(), m_key.begin(), 16); + ConditionalByteReverse(BIG_ENDIAN_ORDER, m_key + m_rounds*4, m_key + m_rounds*4, 16); +} + +void Rijndael::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE) + if (HasSSE2()) + { + Rijndael::Enc::AdvancedProcessBlocks(inBlock, xorBlock, outBlock, 16, 0); + return; + } +#endif + + typedef BlockGetAndPut Block; + + word32 s0, s1, s2, s3, t0, t1, t2, t3; + Block::Get(inBlock)(s0)(s1)(s2)(s3); + + const word32 *rk = m_key; + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + t0 = rk[4]; + t1 = rk[5]; + t2 = rk[6]; + t3 = rk[7]; + rk += 8; + + // timing attack countermeasure. see comments at top for more details + const int cacheLineSize = GetCacheLineSize(); + unsigned int i; + word32 u = 0; +#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS + for (i=0; i<2048; i+=cacheLineSize) +#else + for (i=0; i<1024; i+=cacheLineSize) +#endif + u &= *(const word32 *)(((const byte *)Te)+i); + u &= Te[255]; + s0 |= u; s1 |= u; s2 |= u; s3 |= u; + + QUARTER_ROUND_FE(s3, t0, t1, t2, t3) + QUARTER_ROUND_FE(s2, t3, t0, t1, t2) + QUARTER_ROUND_FE(s1, t2, t3, t0, t1) + QUARTER_ROUND_FE(s0, t1, t2, t3, t0) + + // Nr - 2 full rounds: + unsigned int r = m_rounds/2 - 1; + do + { + s0 = rk[0]; s1 = rk[1]; s2 = rk[2]; s3 = rk[3]; + + QUARTER_ROUND_E(t3, s0, s1, s2, s3) + QUARTER_ROUND_E(t2, s3, s0, s1, s2) + QUARTER_ROUND_E(t1, s2, s3, s0, s1) + QUARTER_ROUND_E(t0, s1, s2, s3, s0) + + t0 = rk[4]; t1 = rk[5]; t2 = rk[6]; t3 = rk[7]; + + QUARTER_ROUND_E(s3, t0, t1, t2, t3) + QUARTER_ROUND_E(s2, t3, t0, t1, t2) + QUARTER_ROUND_E(s1, t2, t3, t0, t1) + QUARTER_ROUND_E(s0, t1, t2, t3, t0) + + rk += 8; + } while (--r); + + word32 tbw[4]; + byte *const tempBlock = (byte *)tbw; + + QUARTER_ROUND_LE(t2, 15, 2, 5, 8) + QUARTER_ROUND_LE(t1, 11, 14, 1, 4) + QUARTER_ROUND_LE(t0, 7, 10, 13, 0) + QUARTER_ROUND_LE(t3, 3, 6, 9, 12) + + Block::Put(xorBlock, outBlock)(tbw[0]^rk[0])(tbw[1]^rk[1])(tbw[2]^rk[2])(tbw[3]^rk[3]); +} + +void Rijndael::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + typedef BlockGetAndPut Block; + + word32 s0, s1, s2, s3, t0, t1, t2, t3; + Block::Get(inBlock)(s0)(s1)(s2)(s3); + + const word32 *rk = m_key; + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + t0 = rk[4]; + t1 = rk[5]; + t2 = rk[6]; + t3 = rk[7]; + rk += 8; + + // timing attack countermeasure. see comments at top for more details + const int cacheLineSize = GetCacheLineSize(); + unsigned int i; + word32 u = 0; +#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS + for (i=0; i<2048; i+=cacheLineSize) +#else + for (i=0; i<1024; i+=cacheLineSize) +#endif + u &= *(const word32 *)(((const byte *)Td)+i); + u &= Td[255]; + s0 |= u; s1 |= u; s2 |= u; s3 |= u; + + QUARTER_ROUND_FD(s3, t2, t1, t0, t3) + QUARTER_ROUND_FD(s2, t1, t0, t3, t2) + QUARTER_ROUND_FD(s1, t0, t3, t2, t1) + QUARTER_ROUND_FD(s0, t3, t2, t1, t0) + + // Nr - 2 full rounds: + unsigned int r = m_rounds/2 - 1; + do + { + s0 = rk[0]; s1 = rk[1]; s2 = rk[2]; s3 = rk[3]; + + QUARTER_ROUND_D(t3, s2, s1, s0, s3) + QUARTER_ROUND_D(t2, s1, s0, s3, s2) + QUARTER_ROUND_D(t1, s0, s3, s2, s1) + QUARTER_ROUND_D(t0, s3, s2, s1, s0) + + t0 = rk[4]; t1 = rk[5]; t2 = rk[6]; t3 = rk[7]; + + QUARTER_ROUND_D(s3, t2, t1, t0, t3) + QUARTER_ROUND_D(s2, t1, t0, t3, t2) + QUARTER_ROUND_D(s1, t0, t3, t2, t1) + QUARTER_ROUND_D(s0, t3, t2, t1, t0) + + rk += 8; + } while (--r); + +#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS + // timing attack countermeasure. see comments at top for more details + // If CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS is defined, + // QUARTER_ROUND_LD will use Td, which is already preloaded. + u = 0; + for (i=0; i<256; i+=cacheLineSize) + u &= *(const word32 *)(Sd+i); + u &= *(const word32 *)(Sd+252); + t0 |= u; t1 |= u; t2 |= u; t3 |= u; +#endif + + word32 tbw[4]; + byte *const tempBlock = (byte *)tbw; + + QUARTER_ROUND_LD(t2, 7, 2, 13, 8) + QUARTER_ROUND_LD(t1, 3, 14, 9, 4) + QUARTER_ROUND_LD(t0, 15, 10, 5, 0) + QUARTER_ROUND_LD(t3, 11, 6, 1, 12) + + Block::Put(xorBlock, outBlock)(tbw[0]^rk[0])(tbw[1]^rk[1])(tbw[2]^rk[2])(tbw[3]^rk[3]); +} + +// ************************* Assembly Code ************************************ + +#pragma warning(disable: 4731) // frame pointer register 'ebp' modified by inline assembly code + +#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM + +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE + +CRYPTOPP_NAKED void CRYPTOPP_FASTCALL Rijndael_Enc_AdvancedProcessBlocks(void *locals, const word32 *k) +{ +#if CRYPTOPP_BOOL_X86 + +#define L_REG esp +#define L_INDEX(i) (L_REG+768+i) +#define L_INXORBLOCKS L_INBLOCKS+4 +#define L_OUTXORBLOCKS L_INBLOCKS+8 +#define L_OUTBLOCKS L_INBLOCKS+12 +#define L_INCREMENTS L_INDEX(16*15) +#define L_SP L_INDEX(16*16) +#define L_LENGTH L_INDEX(16*16+4) +#define L_KEYS_BEGIN L_INDEX(16*16+8) + +#define MOVD movd +#define MM(i) mm##i + +#define MXOR(a,b,c) \ + AS2( movzx esi, b)\ + AS2( movd mm7, DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\ + AS2( pxor MM(a), mm7)\ + +#define MMOV(a,b,c) \ + AS2( movzx esi, b)\ + AS2( movd MM(a), DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\ + +#else + +#define L_REG r8 +#define L_INDEX(i) (L_REG+i) +#define L_INXORBLOCKS L_INBLOCKS+8 +#define L_OUTXORBLOCKS L_INBLOCKS+16 +#define L_OUTBLOCKS L_INBLOCKS+24 +#define L_INCREMENTS L_INDEX(16*16) +#define L_LENGTH L_INDEX(16*18+8) +#define L_KEYS_BEGIN L_INDEX(16*19) + +#define MOVD mov +#define MM_0 r9d +#define MM_1 r12d +#ifdef __GNUC__ +#define MM_2 r11d +#else +#define MM_2 r10d +#endif +#define MM(i) MM_##i + +#define MXOR(a,b,c) \ + AS2( movzx esi, b)\ + AS2( xor MM(a), DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\ + +#define MMOV(a,b,c) \ + AS2( movzx esi, b)\ + AS2( mov MM(a), DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\ + +#endif + +#define L_SUBKEYS L_INDEX(0) +#define L_SAVED_X L_SUBKEYS +#define L_KEY12 L_INDEX(16*12) +#define L_LASTROUND L_INDEX(16*13) +#define L_INBLOCKS L_INDEX(16*14) +#define MAP0TO4(i) (ASM_MOD(i+3,4)+1) + +#define XOR(a,b,c) \ + AS2( movzx esi, b)\ + AS2( xor a, DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\ + +#define MOV(a,b,c) \ + AS2( movzx esi, b)\ + AS2( mov a, DWORD PTR [AS_REG_7+8*WORD_REG(si)+MAP0TO4(c)])\ + +#ifdef CRYPTOPP_GENERATE_X64_MASM + ALIGN 8 + Rijndael_Enc_AdvancedProcessBlocks PROC FRAME + rex_push_reg rsi + push_reg rdi + push_reg rbx + push_reg r12 + .endprolog + mov L_REG, rcx + mov AS_REG_7, ?Te@rdtable@CryptoPP@@3PA_KA + mov edi, DWORD PTR [?g_cacheLineSize@CryptoPP@@3IA] +#elif defined(__GNUC__) + __asm__ __volatile__ + ( + ".intel_syntax noprefix;" + #if CRYPTOPP_BOOL_X64 + AS2( mov L_REG, rcx) + #endif + AS_PUSH_IF86(bx) + AS_PUSH_IF86(bp) + AS2( mov AS_REG_7, WORD_REG(si)) +#else + AS_PUSH_IF86(si) + AS_PUSH_IF86(di) + AS_PUSH_IF86(bx) + AS_PUSH_IF86(bp) + AS2( lea AS_REG_7, [Te]) + AS2( mov edi, [g_cacheLineSize]) +#endif + +#if CRYPTOPP_BOOL_X86 + AS2( mov [ecx+16*12+16*4], esp) // save esp to L_SP + AS2( lea esp, [ecx-768]) +#endif + + // copy subkeys to stack + AS2( mov WORD_REG(si), [L_KEYS_BEGIN]) + AS2( mov WORD_REG(ax), 16) + AS2( and WORD_REG(ax), WORD_REG(si)) + AS2( movdqa xmm3, XMMWORD_PTR [WORD_REG(dx)+16+WORD_REG(ax)]) // subkey 1 (non-counter) or 2 (counter) + AS2( movdqa [L_KEY12], xmm3) + AS2( lea WORD_REG(ax), [WORD_REG(dx)+WORD_REG(ax)+2*16]) + AS2( sub WORD_REG(ax), WORD_REG(si)) + ASL(0) + AS2( movdqa xmm0, [WORD_REG(ax)+WORD_REG(si)]) + AS2( movdqa XMMWORD_PTR [L_SUBKEYS+WORD_REG(si)], xmm0) + AS2( add WORD_REG(si), 16) + AS2( cmp WORD_REG(si), 16*12) + ASJ( jl, 0, b) + + // read subkeys 0, 1 and last + AS2( movdqa xmm4, [WORD_REG(ax)+WORD_REG(si)]) // last subkey + AS2( movdqa xmm1, [WORD_REG(dx)]) // subkey 0 + AS2( MOVD MM(1), [WORD_REG(dx)+4*4]) // 0,1,2,3 + AS2( mov ebx, [WORD_REG(dx)+5*4]) // 4,5,6,7 + AS2( mov ecx, [WORD_REG(dx)+6*4]) // 8,9,10,11 + AS2( mov edx, [WORD_REG(dx)+7*4]) // 12,13,14,15 + + // load table into cache + AS2( xor WORD_REG(ax), WORD_REG(ax)) + ASL(9) + AS2( mov esi, [AS_REG_7+WORD_REG(ax)]) + AS2( add WORD_REG(ax), WORD_REG(di)) + AS2( mov esi, [AS_REG_7+WORD_REG(ax)]) + AS2( add WORD_REG(ax), WORD_REG(di)) + AS2( mov esi, [AS_REG_7+WORD_REG(ax)]) + AS2( add WORD_REG(ax), WORD_REG(di)) + AS2( mov esi, [AS_REG_7+WORD_REG(ax)]) + AS2( add WORD_REG(ax), WORD_REG(di)) + AS2( cmp WORD_REG(ax), 2048) + ASJ( jl, 9, b) + AS1( lfence) + + AS2( test DWORD PTR [L_LENGTH], 1) + ASJ( jz, 8, f) + + // counter mode one-time setup + AS2( mov WORD_REG(si), [L_INBLOCKS]) + AS2( movdqu xmm2, [WORD_REG(si)]) // counter + AS2( pxor xmm2, xmm1) + AS2( psrldq xmm1, 14) + AS2( movd eax, xmm1) + AS2( mov al, BYTE PTR [WORD_REG(si)+15]) + AS2( MOVD MM(2), eax) +#if CRYPTOPP_BOOL_X86 + AS2( mov eax, 1) + AS2( movd mm3, eax) +#endif + + // partial first round, in: xmm2(15,14,13,12;11,10,9,8;7,6,5,4;3,2,1,0), out: mm1, ebx, ecx, edx + AS2( movd eax, xmm2) + AS2( psrldq xmm2, 4) + AS2( movd edi, xmm2) + AS2( psrldq xmm2, 4) + MXOR( 1, al, 0) // 0 + XOR( edx, ah, 1) // 1 + AS2( shr eax, 16) + XOR( ecx, al, 2) // 2 + XOR( ebx, ah, 3) // 3 + AS2( mov eax, edi) + AS2( movd edi, xmm2) + AS2( psrldq xmm2, 4) + XOR( ebx, al, 0) // 4 + MXOR( 1, ah, 1) // 5 + AS2( shr eax, 16) + XOR( edx, al, 2) // 6 + XOR( ecx, ah, 3) // 7 + AS2( mov eax, edi) + AS2( movd edi, xmm2) + XOR( ecx, al, 0) // 8 + XOR( ebx, ah, 1) // 9 + AS2( shr eax, 16) + MXOR( 1, al, 2) // 10 + XOR( edx, ah, 3) // 11 + AS2( mov eax, edi) + XOR( edx, al, 0) // 12 + XOR( ecx, ah, 1) // 13 + AS2( shr eax, 16) + XOR( ebx, al, 2) // 14 + AS2( psrldq xmm2, 3) + + // partial second round, in: ebx(4,5,6,7), ecx(8,9,10,11), edx(12,13,14,15), out: eax, ebx, edi, mm0 + AS2( mov eax, [L_KEY12+0*4]) + AS2( mov edi, [L_KEY12+2*4]) + AS2( MOVD MM(0), [L_KEY12+3*4]) + MXOR( 0, cl, 3) /* 11 */ + XOR( edi, bl, 3) /* 7 */ + MXOR( 0, bh, 2) /* 6 */ + AS2( shr ebx, 16) /* 4,5 */ + XOR( eax, bl, 1) /* 5 */ + MOV( ebx, bh, 0) /* 4 */ + AS2( xor ebx, [L_KEY12+1*4]) + XOR( eax, ch, 2) /* 10 */ + AS2( shr ecx, 16) /* 8,9 */ + XOR( eax, dl, 3) /* 15 */ + XOR( ebx, dh, 2) /* 14 */ + AS2( shr edx, 16) /* 12,13 */ + XOR( edi, ch, 0) /* 8 */ + XOR( ebx, cl, 1) /* 9 */ + XOR( edi, dl, 1) /* 13 */ + MXOR( 0, dh, 0) /* 12 */ + + AS2( movd ecx, xmm2) + AS2( MOVD edx, MM(1)) + AS2( MOVD [L_SAVED_X+3*4], MM(0)) + AS2( mov [L_SAVED_X+0*4], eax) + AS2( mov [L_SAVED_X+1*4], ebx) + AS2( mov [L_SAVED_X+2*4], edi) + ASJ( jmp, 5, f) + + ASL(3) + // non-counter mode per-block setup + AS2( MOVD MM(1), [L_KEY12+0*4]) // 0,1,2,3 + AS2( mov ebx, [L_KEY12+1*4]) // 4,5,6,7 + AS2( mov ecx, [L_KEY12+2*4]) // 8,9,10,11 + AS2( mov edx, [L_KEY12+3*4]) // 12,13,14,15 + ASL(8) + AS2( mov WORD_REG(ax), [L_INBLOCKS]) + AS2( movdqu xmm2, [WORD_REG(ax)]) + AS2( mov WORD_REG(si), [L_INXORBLOCKS]) + AS2( movdqu xmm5, [WORD_REG(si)]) + AS2( pxor xmm2, xmm1) + AS2( pxor xmm2, xmm5) + + // first round, in: xmm2(15,14,13,12;11,10,9,8;7,6,5,4;3,2,1,0), out: eax, ebx, ecx, edx + AS2( movd eax, xmm2) + AS2( psrldq xmm2, 4) + AS2( movd edi, xmm2) + AS2( psrldq xmm2, 4) + MXOR( 1, al, 0) // 0 + XOR( edx, ah, 1) // 1 + AS2( shr eax, 16) + XOR( ecx, al, 2) // 2 + XOR( ebx, ah, 3) // 3 + AS2( mov eax, edi) + AS2( movd edi, xmm2) + AS2( psrldq xmm2, 4) + XOR( ebx, al, 0) // 4 + MXOR( 1, ah, 1) // 5 + AS2( shr eax, 16) + XOR( edx, al, 2) // 6 + XOR( ecx, ah, 3) // 7 + AS2( mov eax, edi) + AS2( movd edi, xmm2) + XOR( ecx, al, 0) // 8 + XOR( ebx, ah, 1) // 9 + AS2( shr eax, 16) + MXOR( 1, al, 2) // 10 + XOR( edx, ah, 3) // 11 + AS2( mov eax, edi) + XOR( edx, al, 0) // 12 + XOR( ecx, ah, 1) // 13 + AS2( shr eax, 16) + XOR( ebx, al, 2) // 14 + MXOR( 1, ah, 3) // 15 + AS2( MOVD eax, MM(1)) + + AS2( add L_REG, [L_KEYS_BEGIN]) + AS2( add L_REG, 4*16) + ASJ( jmp, 2, f) + + ASL(1) + // counter-mode per-block setup + AS2( MOVD ecx, MM(2)) + AS2( MOVD edx, MM(1)) + AS2( mov eax, [L_SAVED_X+0*4]) + AS2( mov ebx, [L_SAVED_X+1*4]) + AS2( xor cl, ch) + AS2( and WORD_REG(cx), 255) + ASL(5) +#if CRYPTOPP_BOOL_X86 + AS2( paddb MM(2), mm3) +#else + AS2( add MM(2), 1) +#endif + // remaining part of second round, in: edx(previous round),esi(keyed counter byte) eax,ebx,[L_SAVED_X+2*4],[L_SAVED_X+3*4], out: eax,ebx,ecx,edx + AS2( xor edx, DWORD PTR [AS_REG_7+WORD_REG(cx)*8+3]) + XOR( ebx, dl, 3) + MOV( ecx, dh, 2) + AS2( shr edx, 16) + AS2( xor ecx, [L_SAVED_X+2*4]) + XOR( eax, dh, 0) + MOV( edx, dl, 1) + AS2( xor edx, [L_SAVED_X+3*4]) + + AS2( add L_REG, [L_KEYS_BEGIN]) + AS2( add L_REG, 3*16) + ASJ( jmp, 4, f) + +// in: eax(0,1,2,3), ebx(4,5,6,7), ecx(8,9,10,11), edx(12,13,14,15) +// out: eax, ebx, edi, mm0 +#define ROUND() \ + MXOR( 0, cl, 3) /* 11 */\ + AS2( mov cl, al) /* 8,9,10,3 */\ + XOR( edi, ah, 2) /* 2 */\ + AS2( shr eax, 16) /* 0,1 */\ + XOR( edi, bl, 3) /* 7 */\ + MXOR( 0, bh, 2) /* 6 */\ + AS2( shr ebx, 16) /* 4,5 */\ + MXOR( 0, al, 1) /* 1 */\ + MOV( eax, ah, 0) /* 0 */\ + XOR( eax, bl, 1) /* 5 */\ + MOV( ebx, bh, 0) /* 4 */\ + XOR( eax, ch, 2) /* 10 */\ + XOR( ebx, cl, 3) /* 3 */\ + AS2( shr ecx, 16) /* 8,9 */\ + XOR( eax, dl, 3) /* 15 */\ + XOR( ebx, dh, 2) /* 14 */\ + AS2( shr edx, 16) /* 12,13 */\ + XOR( edi, ch, 0) /* 8 */\ + XOR( ebx, cl, 1) /* 9 */\ + XOR( edi, dl, 1) /* 13 */\ + MXOR( 0, dh, 0) /* 12 */\ + + ASL(2) // 2-round loop + AS2( MOVD MM(0), [L_SUBKEYS-4*16+3*4]) + AS2( mov edi, [L_SUBKEYS-4*16+2*4]) + ROUND() + AS2( mov ecx, edi) + AS2( xor eax, [L_SUBKEYS-4*16+0*4]) + AS2( xor ebx, [L_SUBKEYS-4*16+1*4]) + AS2( MOVD edx, MM(0)) + + ASL(4) + AS2( MOVD MM(0), [L_SUBKEYS-4*16+7*4]) + AS2( mov edi, [L_SUBKEYS-4*16+6*4]) + ROUND() + AS2( mov ecx, edi) + AS2( xor eax, [L_SUBKEYS-4*16+4*4]) + AS2( xor ebx, [L_SUBKEYS-4*16+5*4]) + AS2( MOVD edx, MM(0)) + + AS2( add L_REG, 32) + AS2( test L_REG, 255) + ASJ( jnz, 2, b) + AS2( sub L_REG, 16*16) + +#define LAST(a, b, c) \ + AS2( movzx esi, a )\ + AS2( movzx edi, BYTE PTR [AS_REG_7+WORD_REG(si)*8+1] )\ + AS2( movzx esi, b )\ + AS2( xor edi, DWORD PTR [AS_REG_7+WORD_REG(si)*8+0] )\ + AS2( mov WORD PTR [L_LASTROUND+c], di )\ + + // last round + LAST(ch, dl, 2) + LAST(dh, al, 6) + AS2( shr edx, 16) + LAST(ah, bl, 10) + AS2( shr eax, 16) + LAST(bh, cl, 14) + AS2( shr ebx, 16) + LAST(dh, al, 12) + AS2( shr ecx, 16) + LAST(ah, bl, 0) + LAST(bh, cl, 4) + LAST(ch, dl, 8) + + AS2( mov WORD_REG(ax), [L_OUTXORBLOCKS]) + AS2( mov WORD_REG(bx), [L_OUTBLOCKS]) + + AS2( mov WORD_REG(cx), [L_LENGTH]) + AS2( sub WORD_REG(cx), 16) + + AS2( movdqu xmm2, [WORD_REG(ax)]) + AS2( pxor xmm2, xmm4) + +#if CRYPTOPP_BOOL_X86 + AS2( movdqa xmm0, [L_INCREMENTS]) + AS2( paddd xmm0, [L_INBLOCKS]) + AS2( movdqa [L_INBLOCKS], xmm0) +#else + AS2( movdqa xmm0, [L_INCREMENTS+16]) + AS2( paddq xmm0, [L_INBLOCKS+16]) + AS2( movdqa [L_INBLOCKS+16], xmm0) +#endif + + AS2( pxor xmm2, [L_LASTROUND]) + AS2( movdqu [WORD_REG(bx)], xmm2) + + ASJ( jle, 7, f) + AS2( mov [L_LENGTH], WORD_REG(cx)) + AS2( test WORD_REG(cx), 1) + ASJ( jnz, 1, b) +#if CRYPTOPP_BOOL_X64 + AS2( movdqa xmm0, [L_INCREMENTS]) + AS2( paddq xmm0, [L_INBLOCKS]) + AS2( movdqa [L_INBLOCKS], xmm0) +#endif + ASJ( jmp, 3, b) + + ASL(7) + // erase keys on stack + AS2( xorps xmm0, xmm0) + AS2( lea WORD_REG(ax), [L_SUBKEYS+7*16]) + AS2( movaps [WORD_REG(ax)-7*16], xmm0) + AS2( movaps [WORD_REG(ax)-6*16], xmm0) + AS2( movaps [WORD_REG(ax)-5*16], xmm0) + AS2( movaps [WORD_REG(ax)-4*16], xmm0) + AS2( movaps [WORD_REG(ax)-3*16], xmm0) + AS2( movaps [WORD_REG(ax)-2*16], xmm0) + AS2( movaps [WORD_REG(ax)-1*16], xmm0) + AS2( movaps [WORD_REG(ax)+0*16], xmm0) + AS2( movaps [WORD_REG(ax)+1*16], xmm0) + AS2( movaps [WORD_REG(ax)+2*16], xmm0) + AS2( movaps [WORD_REG(ax)+3*16], xmm0) + AS2( movaps [WORD_REG(ax)+4*16], xmm0) + AS2( movaps [WORD_REG(ax)+5*16], xmm0) + AS2( movaps [WORD_REG(ax)+6*16], xmm0) +#if CRYPTOPP_BOOL_X86 + AS2( mov esp, [L_SP]) + AS1( emms) +#endif + AS_POP_IF86(bp) + AS_POP_IF86(bx) +#if defined(_MSC_VER) && CRYPTOPP_BOOL_X86 + AS_POP_IF86(di) + AS_POP_IF86(si) + AS1(ret) +#endif +#ifdef CRYPTOPP_GENERATE_X64_MASM + pop r12 + pop rbx + pop rdi + pop rsi + ret + Rijndael_Enc_AdvancedProcessBlocks ENDP +#endif +#ifdef __GNUC__ + ".att_syntax prefix;" + : + : "c" (locals), "d" (k), "S" (Te), "D" (g_cacheLineSize) + : "memory", "cc", "%eax" + #if CRYPTOPP_BOOL_X64 + , "%rbx", "%r8", "%r9", "%r10", "%r11", "%r12" + #endif + ); +#endif +} + +#endif + +#ifndef CRYPTOPP_GENERATE_X64_MASM + +#ifdef CRYPTOPP_X64_MASM_AVAILABLE +extern "C" { +void Rijndael_Enc_AdvancedProcessBlocks(void *locals, const word32 *k); +} +#endif + +#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86 + +static inline bool AliasedWithTable(const byte *begin, const byte *end) +{ + size_t s0 = size_t(begin)%4096, s1 = size_t(end)%4096; + size_t t0 = size_t(Te)%4096, t1 = (size_t(Te)+sizeof(Te))%4096; + if (t1 > t0) + return (s0 >= t0 && s0 < t1) || (s1 > t0 && s1 <= t1); + else + return (s0 < t1 || s1 <= t1) || (s0 >= t0 || s1 > t0); +} + +size_t Rijndael::Enc::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const +{ +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE) + if (length < BLOCKSIZE) + return length; + + if (HasSSE2()) + { + struct Locals + { + word32 subkeys[4*12], workspace[8]; + const byte *inBlocks, *inXorBlocks, *outXorBlocks; + byte *outBlocks; + size_t inIncrement, inXorIncrement, outXorIncrement, outIncrement; + size_t regSpill, lengthAndCounterFlag, keysBegin; + }; + + size_t increment = BLOCKSIZE; + const byte* zeros = (byte *)(Te+256); + byte *space; + + do { + space = (byte *)alloca(255+sizeof(Locals)); + space += (256-(size_t)space%256)%256; + } + while (AliasedWithTable(space, space+sizeof(Locals))); + + if (flags & BT_ReverseDirection) + { + assert(length % BLOCKSIZE == 0); + inBlocks += length - BLOCKSIZE; + xorBlocks += length - BLOCKSIZE; + outBlocks += length - BLOCKSIZE; + increment = 0-increment; + } + + Locals &locals = *(Locals *)space; + + locals.inBlocks = inBlocks; + locals.inXorBlocks = (flags & BT_XorInput) && xorBlocks ? xorBlocks : zeros; + locals.outXorBlocks = (flags & BT_XorInput) || !xorBlocks ? zeros : xorBlocks; + locals.outBlocks = outBlocks; + + locals.inIncrement = (flags & BT_DontIncrementInOutPointers) ? 0 : increment; + locals.inXorIncrement = (flags & BT_XorInput) && xorBlocks ? increment : 0; + locals.outXorIncrement = (flags & BT_XorInput) || !xorBlocks ? 0 : increment; + locals.outIncrement = (flags & BT_DontIncrementInOutPointers) ? 0 : increment; + + locals.lengthAndCounterFlag = length - (length%16) - bool(flags & BT_InBlockIsCounter); + int keysToCopy = m_rounds - (flags & BT_InBlockIsCounter ? 3 : 2); + locals.keysBegin = (12-keysToCopy)*16; + + Rijndael_Enc_AdvancedProcessBlocks(&locals, m_key); + return length%16; + } + else +#endif + return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags); +} + +#endif + +NAMESPACE_END + +#endif +#endif diff --git a/src-cryptopp/rijndael.h b/src-cryptopp/rijndael.h new file mode 100644 index 0000000..d602186 --- /dev/null +++ b/src-cryptopp/rijndael.h @@ -0,0 +1,65 @@ +#ifndef CRYPTOPP_RIJNDAEL_H +#define CRYPTOPP_RIJNDAEL_H + +/** \file +*/ + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! _ +struct Rijndael_Info : public FixedBlockSize<16>, public VariableKeyLength<16, 16, 32, 8> +{ + CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return CRYPTOPP_RIJNDAEL_NAME;} +}; + +/// Rijndael +class CRYPTOPP_DLL Rijndael : public Rijndael_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + + protected: + static void FillEncTable(); + static void FillDecTable(); + + // VS2005 workaround: have to put these on seperate lines, or error C2487 is triggered in DLL build + static const byte Se[256]; + static const byte Sd[256]; + + static const word32 rcon[]; + + unsigned int m_rounds; + FixedSizeAlignedSecBlock m_key; + }; + + class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; +#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86 + size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const; +#endif + }; + + class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef Rijndael::Encryption RijndaelEncryption; +typedef Rijndael::Decryption RijndaelDecryption; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/rng.cpp b/src-cryptopp/rng.cpp new file mode 100644 index 0000000..6ddbc50 --- /dev/null +++ b/src-cryptopp/rng.cpp @@ -0,0 +1,142 @@ +// rng.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#include "rng.h" +#include "fips140.h" + +#include + +NAMESPACE_BEGIN(CryptoPP) + +// linear congruential generator +// originally by William S. England + +// do not use for cryptographic purposes + +/* +** Original_numbers are the original published m and q in the +** ACM article above. John Burton has furnished numbers for +** a reportedly better generator. The new numbers are now +** used in this program by default. +*/ + +#ifndef LCRNG_ORIGINAL_NUMBERS +const word32 LC_RNG::m=2147483647L; +const word32 LC_RNG::q=44488L; + +const word16 LC_RNG::a=(unsigned int)48271L; +const word16 LC_RNG::r=3399; +#else +const word32 LC_RNG::m=2147483647L; +const word32 LC_RNG::q=127773L; + +const word16 LC_RNG::a=16807; +const word16 LC_RNG::r=2836; +#endif + +void LC_RNG::GenerateBlock(byte *output, size_t size) +{ + while (size--) + { + word32 hi = seed/q; + word32 lo = seed%q; + + long test = a*lo - r*hi; + + if (test > 0) + seed = test; + else + seed = test+ m; + + *output++ = (GETBYTE(seed, 0) ^ GETBYTE(seed, 1) ^ GETBYTE(seed, 2) ^ GETBYTE(seed, 3)); + } +} + +// ******************************************************** + +#ifndef CRYPTOPP_IMPORTS + +X917RNG::X917RNG(BlockTransformation *c, const byte *seed, const byte *deterministicTimeVector) + : cipher(c), + S(cipher->BlockSize()), + dtbuf(S), + randseed(seed, S), + m_lastBlock(S), + m_deterministicTimeVector(deterministicTimeVector, deterministicTimeVector ? S : 0) +{ + assert (deterministicTimeVector); + + // for FIPS 140-2 + GenerateBlock(m_lastBlock, S); +} + +void X917RNG::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size) +{ + while (size > 0) + { + // calculate new enciphered timestamp + if (m_deterministicTimeVector.size()) + { + cipher->ProcessBlock(m_deterministicTimeVector, dtbuf); + IncrementCounterByOne(m_deterministicTimeVector, S); + } + else + { + assert(false); + } + + // combine enciphered timestamp with seed + xorbuf(randseed, dtbuf, S); + + // generate a new block of random bytes + cipher->ProcessBlock(randseed); + if (memcmp(m_lastBlock, randseed, S) == 0) + throw SelfTestFailure("X917RNG: Continuous random number generator test failed."); + + // output random bytes + size_t len = UnsignedMin(S, size); + target.ChannelPut(channel, randseed, len); + size -= len; + + // compute new seed vector + memcpy(m_lastBlock, randseed, S); + xorbuf(randseed, dtbuf, S); + cipher->ProcessBlock(randseed); + } +} + +#endif + +MaurerRandomnessTest::MaurerRandomnessTest() + : sum(0.0), n(0) +{ + for (unsigned i=0; i= Q) + sum += log(double(n - tab[inByte])); + tab[inByte] = n; + n++; + } + return 0; +} + +double MaurerRandomnessTest::GetTestValue() const +{ + if (BytesNeeded() > 0) + throw Exception(Exception::OTHER_ERROR, "MaurerRandomnessTest: " + IntToString(BytesNeeded()) + " more bytes of input needed"); + + double fTu = (sum/(n-Q))/log(2.0); // this is the test value defined by Maurer + + double value = fTu * 0.1392; // arbitrarily normalize it to + return value > 1.0 ? 1.0 : value; // a number between 0 and 1 +} + +NAMESPACE_END diff --git a/src-cryptopp/rng.h b/src-cryptopp/rng.h new file mode 100644 index 0000000..2439dee --- /dev/null +++ b/src-cryptopp/rng.h @@ -0,0 +1,77 @@ +// rng.h - misc RNG related classes, see also osrng.h, randpool.h + +#ifndef CRYPTOPP_RNG_H +#define CRYPTOPP_RNG_H + +#include "cryptlib.h" +#include "filters.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! linear congruential generator +/*! originally by William S. England, do not use for cryptographic purposes */ +class LC_RNG : public RandomNumberGenerator +{ +public: + LC_RNG(word32 init_seed) + : seed(init_seed) {} + + void GenerateBlock(byte *output, size_t size); + + word32 GetSeed() {return seed;} + +private: + word32 seed; + + static const word32 m; + static const word32 q; + static const word16 a; + static const word16 r; +}; + +//! RNG derived from ANSI X9.17 Appendix C + +class CRYPTOPP_DLL X917RNG : public RandomNumberGenerator, public NotCopyable +{ +public: + // cipher will be deleted by destructor, deterministicTimeVector = 0 means obtain time vector from system + X917RNG(BlockTransformation *cipher, const byte *seed, const byte *deterministicTimeVector = 0); + + void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword size); + +private: + member_ptr cipher; + unsigned int S; // blocksize of cipher + SecByteBlock dtbuf; // buffer for enciphered timestamp + SecByteBlock randseed, m_lastBlock, m_deterministicTimeVector; +}; + +/** This class implements Maurer's Universal Statistical Test for Random Bit Generators + it is intended for measuring the randomness of *PHYSICAL* RNGs. + For more details see his paper in Journal of Cryptology, 1992. */ + +class MaurerRandomnessTest : public Bufferless +{ +public: + MaurerRandomnessTest(); + + size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking); + + // BytesNeeded() returns how many more bytes of input is needed by the test + // GetTestValue() should not be called before BytesNeeded()==0 + unsigned int BytesNeeded() const {return n >= (Q+K) ? 0 : Q+K-n;} + + // returns a number between 0.0 and 1.0, describing the quality of the + // random numbers entered + double GetTestValue() const; + +private: + enum {L=8, V=256, Q=2000, K=2000}; + double sum; + unsigned int n; + unsigned int tab[V]; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/rsa.cpp b/src-cryptopp/rsa.cpp new file mode 100644 index 0000000..59449c4 --- /dev/null +++ b/src-cryptopp/rsa.cpp @@ -0,0 +1,304 @@ +// rsa.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "rsa.h" +#include "asn.h" +#include "oids.h" +#include "modarith.h" +#include "nbtheory.h" +#include "sha.h" +#include "algparam.h" +#include "fips140.h" + +#if !defined(NDEBUG) && !defined(CRYPTOPP_IS_DLL) +#include "pssr.h" +NAMESPACE_BEGIN(CryptoPP) +void RSA_TestInstantiations() +{ + RSASS::Verifier x1(1, 1); + RSASS::Signer x2(NullRNG(), 1); + RSASS::Verifier x3(x2); + RSASS::Verifier x4(x2.GetKey()); + RSASS::Verifier x5(x3); +#ifndef __MWERKS__ + RSASS::Signer x6 = x2; + x3 = x2; + x6 = x2; +#endif + RSAES::Encryptor x7(x2); +#ifndef __GNUC__ + RSAES::Encryptor x8(x3); +#endif + RSAES >::Encryptor x9(x2); + + x4 = x2.GetKey(); +} +NAMESPACE_END +#endif + +#ifndef CRYPTOPP_IMPORTS + +NAMESPACE_BEGIN(CryptoPP) + +OID RSAFunction::GetAlgorithmID() const +{ + return ASN1::rsaEncryption(); +} + +void RSAFunction::BERDecodePublicKey(BufferedTransformation &bt, bool, size_t) +{ + BERSequenceDecoder seq(bt); + m_n.BERDecode(seq); + m_e.BERDecode(seq); + seq.MessageEnd(); +} + +void RSAFunction::DEREncodePublicKey(BufferedTransformation &bt) const +{ + DERSequenceEncoder seq(bt); + m_n.DEREncode(seq); + m_e.DEREncode(seq); + seq.MessageEnd(); +} + +Integer RSAFunction::ApplyFunction(const Integer &x) const +{ + DoQuickSanityCheck(); + return a_exp_b_mod_c(x, m_e, m_n); +} + +bool RSAFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const +{ + bool pass = true; + pass = pass && m_n > Integer::One() && m_n.IsOdd(); + pass = pass && m_e > Integer::One() && m_e.IsOdd() && m_e < m_n; + return pass; +} + +bool RSAFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + return GetValueHelper(this, name, valueType, pValue).Assignable() + CRYPTOPP_GET_FUNCTION_ENTRY(Modulus) + CRYPTOPP_GET_FUNCTION_ENTRY(PublicExponent) + ; +} + +void RSAFunction::AssignFrom(const NameValuePairs &source) +{ + AssignFromHelper(this, source) + CRYPTOPP_SET_FUNCTION_ENTRY(Modulus) + CRYPTOPP_SET_FUNCTION_ENTRY(PublicExponent) + ; +} + +// ***************************************************************************** + +class RSAPrimeSelector : public PrimeSelector +{ +public: + RSAPrimeSelector(const Integer &e) : m_e(e) {} + bool IsAcceptable(const Integer &candidate) const {return RelativelyPrime(m_e, candidate-Integer::One());} + Integer m_e; +}; + +void InvertibleRSAFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg) +{ + int modulusSize = 2048; + alg.GetIntValue(Name::ModulusSize(), modulusSize) || alg.GetIntValue(Name::KeySize(), modulusSize); + + if (modulusSize < 16) + throw InvalidArgument("InvertibleRSAFunction: specified modulus size is too small"); + + m_e = alg.GetValueWithDefault(Name::PublicExponent(), Integer(17)); + + if (m_e < 3 || m_e.IsEven()) + throw InvalidArgument("InvertibleRSAFunction: invalid public exponent"); + + RSAPrimeSelector selector(m_e); + AlgorithmParameters primeParam = MakeParametersForTwoPrimesOfEqualSize(modulusSize) + (Name::PointerToPrimeSelector(), selector.GetSelectorPointer()); + m_p.GenerateRandom(rng, primeParam); + m_q.GenerateRandom(rng, primeParam); + + m_d = m_e.InverseMod(LCM(m_p-1, m_q-1)); + assert(m_d.IsPositive()); + + m_dp = m_d % (m_p-1); + m_dq = m_d % (m_q-1); + m_n = m_p * m_q; + m_u = m_q.InverseMod(m_p); + + if (FIPS_140_2_ComplianceEnabled()) + { + RSASS::Signer signer(*this); + RSASS::Verifier verifier(signer); + SignaturePairwiseConsistencyTest_FIPS_140_Only(signer, verifier); + + RSAES >::Decryptor decryptor(*this); + RSAES >::Encryptor encryptor(decryptor); + EncryptionPairwiseConsistencyTest_FIPS_140_Only(encryptor, decryptor); + } +} + +void InvertibleRSAFunction::Initialize(RandomNumberGenerator &rng, unsigned int keybits, const Integer &e) +{ + GenerateRandom(rng, MakeParameters(Name::ModulusSize(), (int)keybits)(Name::PublicExponent(), e+e.IsEven())); +} + +void InvertibleRSAFunction::Initialize(const Integer &n, const Integer &e, const Integer &d) +{ + if (n.IsEven() || e.IsEven() | d.IsEven()) + throw InvalidArgument("InvertibleRSAFunction: input is not a valid RSA private key"); + + m_n = n; + m_e = e; + m_d = d; + + Integer r = --(d*e); + unsigned int s = 0; + while (r.IsEven()) + { + r >>= 1; + s++; + } + + ModularArithmetic modn(n); + for (Integer i = 2; ; ++i) + { + Integer a = modn.Exponentiate(i, r); + if (a == 1) + continue; + Integer b; + unsigned int j = 0; + while (a != n-1) + { + b = modn.Square(a); + if (b == 1) + { + m_p = GCD(a-1, n); + m_q = n/m_p; + m_dp = m_d % (m_p-1); + m_dq = m_d % (m_q-1); + m_u = m_q.InverseMod(m_p); + return; + } + if (++j == s) + throw InvalidArgument("InvertibleRSAFunction: input is not a valid RSA private key"); + a = b; + } + } +} + +void InvertibleRSAFunction::BERDecodePrivateKey(BufferedTransformation &bt, bool, size_t) +{ + BERSequenceDecoder privateKey(bt); + word32 version; + BERDecodeUnsigned(privateKey, version, INTEGER, 0, 0); // check version + m_n.BERDecode(privateKey); + m_e.BERDecode(privateKey); + m_d.BERDecode(privateKey); + m_p.BERDecode(privateKey); + m_q.BERDecode(privateKey); + m_dp.BERDecode(privateKey); + m_dq.BERDecode(privateKey); + m_u.BERDecode(privateKey); + privateKey.MessageEnd(); +} + +void InvertibleRSAFunction::DEREncodePrivateKey(BufferedTransformation &bt) const +{ + DERSequenceEncoder privateKey(bt); + DEREncodeUnsigned(privateKey, 0); // version + m_n.DEREncode(privateKey); + m_e.DEREncode(privateKey); + m_d.DEREncode(privateKey); + m_p.DEREncode(privateKey); + m_q.DEREncode(privateKey); + m_dp.DEREncode(privateKey); + m_dq.DEREncode(privateKey); + m_u.DEREncode(privateKey); + privateKey.MessageEnd(); +} + +Integer InvertibleRSAFunction::CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const +{ + DoQuickSanityCheck(); + ModularArithmetic modn(m_n); + Integer r, rInv; + do { // do this in a loop for people using small numbers for testing + r.Randomize(rng, Integer::One(), m_n - Integer::One()); + rInv = modn.MultiplicativeInverse(r); + } while (rInv.IsZero()); + Integer re = modn.Exponentiate(r, m_e); + re = modn.Multiply(re, x); // blind + // here we follow the notation of PKCS #1 and let u=q inverse mod p + // but in ModRoot, u=p inverse mod q, so we reverse the order of p and q + Integer y = ModularRoot(re, m_dq, m_dp, m_q, m_p, m_u); + y = modn.Multiply(y, rInv); // unblind + if (modn.Exponentiate(y, m_e) != x) // check + throw Exception(Exception::OTHER_ERROR, "InvertibleRSAFunction: computational error during private key operation"); + return y; +} + +bool InvertibleRSAFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const +{ + bool pass = RSAFunction::Validate(rng, level); + pass = pass && m_p > Integer::One() && m_p.IsOdd() && m_p < m_n; + pass = pass && m_q > Integer::One() && m_q.IsOdd() && m_q < m_n; + pass = pass && m_d > Integer::One() && m_d.IsOdd() && m_d < m_n; + pass = pass && m_dp > Integer::One() && m_dp.IsOdd() && m_dp < m_p; + pass = pass && m_dq > Integer::One() && m_dq.IsOdd() && m_dq < m_q; + pass = pass && m_u.IsPositive() && m_u < m_p; + if (level >= 1) + { + pass = pass && m_p * m_q == m_n; + pass = pass && m_e*m_d % LCM(m_p-1, m_q-1) == 1; + pass = pass && m_dp == m_d%(m_p-1) && m_dq == m_d%(m_q-1); + pass = pass && m_u * m_q % m_p == 1; + } + if (level >= 2) + pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2); + return pass; +} + +bool InvertibleRSAFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const +{ + return GetValueHelper(this, name, valueType, pValue).Assignable() + CRYPTOPP_GET_FUNCTION_ENTRY(Prime1) + CRYPTOPP_GET_FUNCTION_ENTRY(Prime2) + CRYPTOPP_GET_FUNCTION_ENTRY(PrivateExponent) + CRYPTOPP_GET_FUNCTION_ENTRY(ModPrime1PrivateExponent) + CRYPTOPP_GET_FUNCTION_ENTRY(ModPrime2PrivateExponent) + CRYPTOPP_GET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1) + ; +} + +void InvertibleRSAFunction::AssignFrom(const NameValuePairs &source) +{ + AssignFromHelper(this, source) + CRYPTOPP_SET_FUNCTION_ENTRY(Prime1) + CRYPTOPP_SET_FUNCTION_ENTRY(Prime2) + CRYPTOPP_SET_FUNCTION_ENTRY(PrivateExponent) + CRYPTOPP_SET_FUNCTION_ENTRY(ModPrime1PrivateExponent) + CRYPTOPP_SET_FUNCTION_ENTRY(ModPrime2PrivateExponent) + CRYPTOPP_SET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1) + ; +} + +// ***************************************************************************** + +Integer RSAFunction_ISO::ApplyFunction(const Integer &x) const +{ + Integer t = RSAFunction::ApplyFunction(x); + return t % 16 == 12 ? t : m_n - t; +} + +Integer InvertibleRSAFunction_ISO::CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const +{ + Integer t = InvertibleRSAFunction::CalculateInverse(rng, x); + return STDMIN(t, m_n-t); +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/rsa.h b/src-cryptopp/rsa.h new file mode 100644 index 0000000..6a8b185 --- /dev/null +++ b/src-cryptopp/rsa.h @@ -0,0 +1,174 @@ +#ifndef CRYPTOPP_RSA_H +#define CRYPTOPP_RSA_H + +/** \file + This file contains classes that implement the RSA + ciphers and signature schemes as defined in PKCS #1 v2.0. +*/ + +#include "pubkey.h" +#include "asn.h" +#include "pkcspad.h" +#include "oaep.h" +#include "emsa2.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! _ +class CRYPTOPP_DLL RSAFunction : public TrapdoorFunction, public X509PublicKey +{ + typedef RSAFunction ThisClass; + +public: + void Initialize(const Integer &n, const Integer &e) + {m_n = n; m_e = e;} + + // X509PublicKey + OID GetAlgorithmID() const; + void BERDecodePublicKey(BufferedTransformation &bt, bool parametersPresent, size_t size); + void DEREncodePublicKey(BufferedTransformation &bt) const; + + // CryptoMaterial + bool Validate(RandomNumberGenerator &rng, unsigned int level) const; + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + + // TrapdoorFunction + Integer ApplyFunction(const Integer &x) const; + Integer PreimageBound() const {return m_n;} + Integer ImageBound() const {return m_n;} + + // non-derived + const Integer & GetModulus() const {return m_n;} + const Integer & GetPublicExponent() const {return m_e;} + + void SetModulus(const Integer &n) {m_n = n;} + void SetPublicExponent(const Integer &e) {m_e = e;} + +protected: + Integer m_n, m_e; +}; + +//! _ +class CRYPTOPP_DLL InvertibleRSAFunction : public RSAFunction, public TrapdoorFunctionInverse, public PKCS8PrivateKey +{ + typedef InvertibleRSAFunction ThisClass; + +public: + void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits, const Integer &e = 17); + void Initialize(const Integer &n, const Integer &e, const Integer &d, const Integer &p, const Integer &q, const Integer &dp, const Integer &dq, const Integer &u) + {m_n = n; m_e = e; m_d = d; m_p = p; m_q = q; m_dp = dp; m_dq = dq; m_u = u;} + //! factor n given private exponent + void Initialize(const Integer &n, const Integer &e, const Integer &d); + + // PKCS8PrivateKey + void BERDecode(BufferedTransformation &bt) + {PKCS8PrivateKey::BERDecode(bt);} + void DEREncode(BufferedTransformation &bt) const + {PKCS8PrivateKey::DEREncode(bt);} + void Load(BufferedTransformation &bt) + {PKCS8PrivateKey::BERDecode(bt);} + void Save(BufferedTransformation &bt) const + {PKCS8PrivateKey::DEREncode(bt);} + OID GetAlgorithmID() const {return RSAFunction::GetAlgorithmID();} + void BERDecodePrivateKey(BufferedTransformation &bt, bool parametersPresent, size_t size); + void DEREncodePrivateKey(BufferedTransformation &bt) const; + + // TrapdoorFunctionInverse + Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const; + + // GeneratableCryptoMaterial + bool Validate(RandomNumberGenerator &rng, unsigned int level) const; + /*! parameters: (ModulusSize, PublicExponent (default 17)) */ + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg); + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + + // non-derived interface + const Integer& GetPrime1() const {return m_p;} + const Integer& GetPrime2() const {return m_q;} + const Integer& GetPrivateExponent() const {return m_d;} + const Integer& GetModPrime1PrivateExponent() const {return m_dp;} + const Integer& GetModPrime2PrivateExponent() const {return m_dq;} + const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const {return m_u;} + + void SetPrime1(const Integer &p) {m_p = p;} + void SetPrime2(const Integer &q) {m_q = q;} + void SetPrivateExponent(const Integer &d) {m_d = d;} + void SetModPrime1PrivateExponent(const Integer &dp) {m_dp = dp;} + void SetModPrime2PrivateExponent(const Integer &dq) {m_dq = dq;} + void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer &u) {m_u = u;} + +protected: + Integer m_d, m_p, m_q, m_dp, m_dq, m_u; +}; + +class CRYPTOPP_DLL RSAFunction_ISO : public RSAFunction +{ +public: + Integer ApplyFunction(const Integer &x) const; + Integer PreimageBound() const {return ++(m_n>>1);} +}; + +class CRYPTOPP_DLL InvertibleRSAFunction_ISO : public InvertibleRSAFunction +{ +public: + Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const; + Integer PreimageBound() const {return ++(m_n>>1);} +}; + +//! RSA +struct CRYPTOPP_DLL RSA +{ + static const char * CRYPTOPP_API StaticAlgorithmName() {return "RSA";} + typedef RSAFunction PublicKey; + typedef InvertibleRSAFunction PrivateKey; +}; + +//! RSA cryptosystem +template +struct RSAES : public TF_ES +{ +}; + +//! RSA signature scheme with appendix +/*! See documentation of PKCS1v15 for a list of hash functions that can be used with it. */ +template +struct RSASS : public TF_SS +{ +}; + +struct CRYPTOPP_DLL RSA_ISO +{ + static const char * CRYPTOPP_API StaticAlgorithmName() {return "RSA-ISO";} + typedef RSAFunction_ISO PublicKey; + typedef InvertibleRSAFunction_ISO PrivateKey; +}; + +template +struct RSASS_ISO : public TF_SS +{ +}; + +// The two RSA encryption schemes defined in PKCS #1 v2.0 +typedef RSAES::Decryptor RSAES_PKCS1v15_Decryptor; +typedef RSAES::Encryptor RSAES_PKCS1v15_Encryptor; + +typedef RSAES >::Decryptor RSAES_OAEP_SHA_Decryptor; +typedef RSAES >::Encryptor RSAES_OAEP_SHA_Encryptor; + +// The three RSA signature schemes defined in PKCS #1 v2.0 +typedef RSASS::Signer RSASSA_PKCS1v15_SHA_Signer; +typedef RSASS::Verifier RSASSA_PKCS1v15_SHA_Verifier; + +namespace Weak { +typedef RSASS::Signer RSASSA_PKCS1v15_MD2_Signer; +typedef RSASS::Verifier RSASSA_PKCS1v15_MD2_Verifier; + +typedef RSASS::Signer RSASSA_PKCS1v15_MD5_Signer; +typedef RSASS::Verifier RSASSA_PKCS1v15_MD5_Verifier; +} + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/rw.h b/src-cryptopp/rw.h new file mode 100644 index 0000000..ec8b850 --- /dev/null +++ b/src-cryptopp/rw.h @@ -0,0 +1,92 @@ +#ifndef CRYPTOPP_RW_H +#define CRYPTOPP_RW_H + +/** \file + This file contains classes that implement the + Rabin-Williams signature schemes as defined in IEEE P1363. +*/ + +#include "pubkey.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! _ +class CRYPTOPP_DLL RWFunction : public TrapdoorFunction, public PublicKey +{ + typedef RWFunction ThisClass; + +public: + void Initialize(const Integer &n) + {m_n = n;} + + void BERDecode(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const; + + Integer ApplyFunction(const Integer &x) const; + Integer PreimageBound() const {return ++(m_n>>1);} + Integer ImageBound() const {return m_n;} + + bool Validate(RandomNumberGenerator &rng, unsigned int level) const; + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + + const Integer& GetModulus() const {return m_n;} + void SetModulus(const Integer &n) {m_n = n;} + +protected: + Integer m_n; +}; + +//! _ +class CRYPTOPP_DLL InvertibleRWFunction : public RWFunction, public TrapdoorFunctionInverse, public PrivateKey +{ + typedef InvertibleRWFunction ThisClass; + +public: + void Initialize(const Integer &n, const Integer &p, const Integer &q, const Integer &u) + {m_n = n; m_p = p; m_q = q; m_u = u;} + // generate a random private key + void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits) + {GenerateRandomWithKeySize(rng, modulusBits);} + + void BERDecode(BufferedTransformation &bt); + void DEREncode(BufferedTransformation &bt) const; + + Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const; + + // GeneratibleCryptoMaterial + bool Validate(RandomNumberGenerator &rng, unsigned int level) const; + bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const; + void AssignFrom(const NameValuePairs &source); + /*! parameters: (ModulusSize) */ + void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg); + + const Integer& GetPrime1() const {return m_p;} + const Integer& GetPrime2() const {return m_q;} + const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const {return m_u;} + + void SetPrime1(const Integer &p) {m_p = p;} + void SetPrime2(const Integer &q) {m_q = q;} + void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer &u) {m_u = u;} + +protected: + Integer m_p, m_q, m_u; +}; + +//! RW +struct RW +{ + static std::string StaticAlgorithmName() {return "RW";} + typedef RWFunction PublicKey; + typedef InvertibleRWFunction PrivateKey; +}; + +//! RWSS +template +struct RWSS : public TF_SS +{ +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/salsa.cpp b/src-cryptopp/salsa.cpp new file mode 100644 index 0000000..bd216ee --- /dev/null +++ b/src-cryptopp/salsa.cpp @@ -0,0 +1,598 @@ +// salsa.cpp - written and placed in the public domain by Wei Dai + +// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM salsa.cpp" to generate MASM code + +#include "pch.h" + +#ifndef CRYPTOPP_GENERATE_X64_MASM + +#include "salsa.h" +#include "misc.h" +#include "argnames.h" +#include "cpu.h" + +NAMESPACE_BEGIN(CryptoPP) + +void Salsa20_TestInstantiations() +{ + Salsa20::Encryption x; +} + +void Salsa20_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) +{ + m_rounds = params.GetIntValueWithDefault(Name::Rounds(), 20); + + if (!(m_rounds == 8 || m_rounds == 12 || m_rounds == 20)) + throw InvalidRounds(Salsa20::StaticAlgorithmName(), m_rounds); + + // m_state is reordered for SSE2 + GetBlock get1(key); + get1(m_state[13])(m_state[10])(m_state[7])(m_state[4]); + GetBlock get2(key + length - 16); + get2(m_state[15])(m_state[12])(m_state[9])(m_state[6]); + + // "expand 16-byte k" or "expand 32-byte k" + m_state[0] = 0x61707865; + m_state[1] = (length == 16) ? 0x3120646e : 0x3320646e; + m_state[2] = (length == 16) ? 0x79622d36 : 0x79622d32; + m_state[3] = 0x6b206574; +} + +void Salsa20_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length) +{ + assert(length==8); + GetBlock get(IV); + get(m_state[14])(m_state[11]); + m_state[8] = m_state[5] = 0; +} + +void Salsa20_Policy::SeekToIteration(lword iterationCount) +{ + m_state[8] = (word32)iterationCount; + m_state[5] = (word32)SafeRightShift<32>(iterationCount); +} + +#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64 +unsigned int Salsa20_Policy::GetAlignment() const +{ +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE + if (HasSSE2()) + return 16; + else +#endif + return GetAlignmentOf(); +} + +unsigned int Salsa20_Policy::GetOptimalBlockSize() const +{ +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE + if (HasSSE2()) + return 4*BYTES_PER_ITERATION; + else +#endif + return BYTES_PER_ITERATION; +} +#endif + +#ifdef CRYPTOPP_X64_MASM_AVAILABLE +extern "C" { +void Salsa20_OperateKeystream(byte *output, const byte *input, size_t iterationCount, int rounds, void *state); +} +#endif + +#pragma warning(disable: 4731) // frame pointer register 'ebp' modified by inline assembly code + +void Salsa20_Policy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) +{ +#endif // #ifdef CRYPTOPP_GENERATE_X64_MASM + +#ifdef CRYPTOPP_X64_MASM_AVAILABLE + Salsa20_OperateKeystream(output, input, iterationCount, m_rounds, m_state.data()); + return; +#endif + +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE +#ifdef CRYPTOPP_GENERATE_X64_MASM + ALIGN 8 + Salsa20_OperateKeystream PROC FRAME + mov r10, [rsp + 5*8] ; state + alloc_stack(10*16 + 32*16 + 8) + save_xmm128 xmm6, 0200h + save_xmm128 xmm7, 0210h + save_xmm128 xmm8, 0220h + save_xmm128 xmm9, 0230h + save_xmm128 xmm10, 0240h + save_xmm128 xmm11, 0250h + save_xmm128 xmm12, 0260h + save_xmm128 xmm13, 0270h + save_xmm128 xmm14, 0280h + save_xmm128 xmm15, 0290h + .endprolog + + #define REG_output rcx + #define REG_input rdx + #define REG_iterationCount r8 + #define REG_state r10 + #define REG_rounds e9d + #define REG_roundsLeft eax + #define REG_temp32 r11d + #define REG_temp r11 + #define SSE2_WORKSPACE rsp +#else + if (HasSSE2()) + { + #if CRYPTOPP_BOOL_X64 + #define REG_output %4 + #define REG_input %1 + #define REG_iterationCount %2 + #define REG_state %3 + #define REG_rounds %0 + #define REG_roundsLeft eax + #define REG_temp32 edx + #define REG_temp rdx + #define SSE2_WORKSPACE %5 + + FixedSizeAlignedSecBlock workspace; + #else + #define REG_output edi + #define REG_input eax + #define REG_iterationCount ecx + #define REG_state esi + #define REG_rounds edx + #define REG_roundsLeft ebx + #define REG_temp32 ebp + #define REG_temp ebp + #define SSE2_WORKSPACE esp + WORD_SZ + #endif + + #ifdef __GNUC__ + __asm__ __volatile__ + ( + ".intel_syntax noprefix;" + AS_PUSH_IF86( bx) + #else + void *s = m_state.data(); + word32 r = m_rounds; + + AS2( mov REG_iterationCount, iterationCount) + AS2( mov REG_input, input) + AS2( mov REG_output, output) + AS2( mov REG_state, s) + AS2( mov REG_rounds, r) + #endif +#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM + + AS_PUSH_IF86( bp) + AS2( cmp REG_iterationCount, 4) + ASJ( jl, 5, f) + +#if CRYPTOPP_BOOL_X86 + AS2( mov ebx, esp) + AS2( and esp, -16) + AS2( sub esp, 32*16) + AS1( push ebx) +#endif + +#define SSE2_EXPAND_S(i, j) \ + ASS( pshufd xmm4, xmm##i, j, j, j, j) \ + AS2( movdqa [SSE2_WORKSPACE + (i*4+j)*16 + 256], xmm4) + + AS2( movdqa xmm0, [REG_state + 0*16]) + AS2( movdqa xmm1, [REG_state + 1*16]) + AS2( movdqa xmm2, [REG_state + 2*16]) + AS2( movdqa xmm3, [REG_state + 3*16]) + SSE2_EXPAND_S(0, 0) + SSE2_EXPAND_S(0, 1) + SSE2_EXPAND_S(0, 2) + SSE2_EXPAND_S(0, 3) + SSE2_EXPAND_S(1, 0) + SSE2_EXPAND_S(1, 2) + SSE2_EXPAND_S(1, 3) + SSE2_EXPAND_S(2, 1) + SSE2_EXPAND_S(2, 2) + SSE2_EXPAND_S(2, 3) + SSE2_EXPAND_S(3, 0) + SSE2_EXPAND_S(3, 1) + SSE2_EXPAND_S(3, 2) + SSE2_EXPAND_S(3, 3) + +#define SSE2_EXPAND_S85(i) \ + AS2( mov dword ptr [SSE2_WORKSPACE + 8*16 + i*4 + 256], REG_roundsLeft) \ + AS2( mov dword ptr [SSE2_WORKSPACE + 5*16 + i*4 + 256], REG_temp32) \ + AS2( add REG_roundsLeft, 1) \ + AS2( adc REG_temp32, 0) + + ASL(1) + AS2( mov REG_roundsLeft, dword ptr [REG_state + 8*4]) + AS2( mov REG_temp32, dword ptr [REG_state + 5*4]) + SSE2_EXPAND_S85(0) + SSE2_EXPAND_S85(1) + SSE2_EXPAND_S85(2) + SSE2_EXPAND_S85(3) + AS2( mov dword ptr [REG_state + 8*4], REG_roundsLeft) + AS2( mov dword ptr [REG_state + 5*4], REG_temp32) + +#define SSE2_QUARTER_ROUND(a, b, d, i) \ + AS2( movdqa xmm4, xmm##d) \ + AS2( paddd xmm4, xmm##a) \ + AS2( movdqa xmm5, xmm4) \ + AS2( pslld xmm4, i) \ + AS2( psrld xmm5, 32-i) \ + AS2( pxor xmm##b, xmm4) \ + AS2( pxor xmm##b, xmm5) + +#define L01(A,B,C,D,a,b,c,d,i) AS2( movdqa xmm##A, [SSE2_WORKSPACE + d*16 + i*256]) /* y3 */ +#define L02(A,B,C,D,a,b,c,d,i) AS2( movdqa xmm##C, [SSE2_WORKSPACE + a*16 + i*256]) /* y0 */ +#define L03(A,B,C,D,a,b,c,d,i) AS2( paddd xmm##A, xmm##C) /* y0+y3 */ +#define L04(A,B,C,D,a,b,c,d,i) AS2( movdqa xmm##B, xmm##A) +#define L05(A,B,C,D,a,b,c,d,i) AS2( pslld xmm##A, 7) +#define L06(A,B,C,D,a,b,c,d,i) AS2( psrld xmm##B, 32-7) +#define L07(A,B,C,D,a,b,c,d,i) AS2( pxor xmm##A, [SSE2_WORKSPACE + b*16 + i*256]) +#define L08(A,B,C,D,a,b,c,d,i) AS2( pxor xmm##A, xmm##B) /* z1 */ +#define L09(A,B,C,D,a,b,c,d,i) AS2( movdqa [SSE2_WORKSPACE + b*16], xmm##A) +#define L10(A,B,C,D,a,b,c,d,i) AS2( movdqa xmm##B, xmm##A) +#define L11(A,B,C,D,a,b,c,d,i) AS2( paddd xmm##A, xmm##C) /* z1+y0 */ +#define L12(A,B,C,D,a,b,c,d,i) AS2( movdqa xmm##D, xmm##A) +#define L13(A,B,C,D,a,b,c,d,i) AS2( pslld xmm##A, 9) +#define L14(A,B,C,D,a,b,c,d,i) AS2( psrld xmm##D, 32-9) +#define L15(A,B,C,D,a,b,c,d,i) AS2( pxor xmm##A, [SSE2_WORKSPACE + c*16 + i*256]) +#define L16(A,B,C,D,a,b,c,d,i) AS2( pxor xmm##A, xmm##D) /* z2 */ +#define L17(A,B,C,D,a,b,c,d,i) AS2( movdqa [SSE2_WORKSPACE + c*16], xmm##A) +#define L18(A,B,C,D,a,b,c,d,i) AS2( movdqa xmm##D, xmm##A) +#define L19(A,B,C,D,a,b,c,d,i) AS2( paddd xmm##A, xmm##B) /* z2+z1 */ +#define L20(A,B,C,D,a,b,c,d,i) AS2( movdqa xmm##B, xmm##A) +#define L21(A,B,C,D,a,b,c,d,i) AS2( pslld xmm##A, 13) +#define L22(A,B,C,D,a,b,c,d,i) AS2( psrld xmm##B, 32-13) +#define L23(A,B,C,D,a,b,c,d,i) AS2( pxor xmm##A, [SSE2_WORKSPACE + d*16 + i*256]) +#define L24(A,B,C,D,a,b,c,d,i) AS2( pxor xmm##A, xmm##B) /* z3 */ +#define L25(A,B,C,D,a,b,c,d,i) AS2( movdqa [SSE2_WORKSPACE + d*16], xmm##A) +#define L26(A,B,C,D,a,b,c,d,i) AS2( paddd xmm##A, xmm##D) /* z3+z2 */ +#define L27(A,B,C,D,a,b,c,d,i) AS2( movdqa xmm##D, xmm##A) +#define L28(A,B,C,D,a,b,c,d,i) AS2( pslld xmm##A, 18) +#define L29(A,B,C,D,a,b,c,d,i) AS2( psrld xmm##D, 32-18) +#define L30(A,B,C,D,a,b,c,d,i) AS2( pxor xmm##A, xmm##C) /* xor y0 */ +#define L31(A,B,C,D,a,b,c,d,i) AS2( pxor xmm##A, xmm##D) /* z0 */ +#define L32(A,B,C,D,a,b,c,d,i) AS2( movdqa [SSE2_WORKSPACE + a*16], xmm##A) + +#define SSE2_QUARTER_ROUND_X8(i, a, b, c, d, e, f, g, h) \ + L01(0,1,2,3, a,b,c,d, i) L01(4,5,6,7, e,f,g,h, i) \ + L02(0,1,2,3, a,b,c,d, i) L02(4,5,6,7, e,f,g,h, i) \ + L03(0,1,2,3, a,b,c,d, i) L03(4,5,6,7, e,f,g,h, i) \ + L04(0,1,2,3, a,b,c,d, i) L04(4,5,6,7, e,f,g,h, i) \ + L05(0,1,2,3, a,b,c,d, i) L05(4,5,6,7, e,f,g,h, i) \ + L06(0,1,2,3, a,b,c,d, i) L06(4,5,6,7, e,f,g,h, i) \ + L07(0,1,2,3, a,b,c,d, i) L07(4,5,6,7, e,f,g,h, i) \ + L08(0,1,2,3, a,b,c,d, i) L08(4,5,6,7, e,f,g,h, i) \ + L09(0,1,2,3, a,b,c,d, i) L09(4,5,6,7, e,f,g,h, i) \ + L10(0,1,2,3, a,b,c,d, i) L10(4,5,6,7, e,f,g,h, i) \ + L11(0,1,2,3, a,b,c,d, i) L11(4,5,6,7, e,f,g,h, i) \ + L12(0,1,2,3, a,b,c,d, i) L12(4,5,6,7, e,f,g,h, i) \ + L13(0,1,2,3, a,b,c,d, i) L13(4,5,6,7, e,f,g,h, i) \ + L14(0,1,2,3, a,b,c,d, i) L14(4,5,6,7, e,f,g,h, i) \ + L15(0,1,2,3, a,b,c,d, i) L15(4,5,6,7, e,f,g,h, i) \ + L16(0,1,2,3, a,b,c,d, i) L16(4,5,6,7, e,f,g,h, i) \ + L17(0,1,2,3, a,b,c,d, i) L17(4,5,6,7, e,f,g,h, i) \ + L18(0,1,2,3, a,b,c,d, i) L18(4,5,6,7, e,f,g,h, i) \ + L19(0,1,2,3, a,b,c,d, i) L19(4,5,6,7, e,f,g,h, i) \ + L20(0,1,2,3, a,b,c,d, i) L20(4,5,6,7, e,f,g,h, i) \ + L21(0,1,2,3, a,b,c,d, i) L21(4,5,6,7, e,f,g,h, i) \ + L22(0,1,2,3, a,b,c,d, i) L22(4,5,6,7, e,f,g,h, i) \ + L23(0,1,2,3, a,b,c,d, i) L23(4,5,6,7, e,f,g,h, i) \ + L24(0,1,2,3, a,b,c,d, i) L24(4,5,6,7, e,f,g,h, i) \ + L25(0,1,2,3, a,b,c,d, i) L25(4,5,6,7, e,f,g,h, i) \ + L26(0,1,2,3, a,b,c,d, i) L26(4,5,6,7, e,f,g,h, i) \ + L27(0,1,2,3, a,b,c,d, i) L27(4,5,6,7, e,f,g,h, i) \ + L28(0,1,2,3, a,b,c,d, i) L28(4,5,6,7, e,f,g,h, i) \ + L29(0,1,2,3, a,b,c,d, i) L29(4,5,6,7, e,f,g,h, i) \ + L30(0,1,2,3, a,b,c,d, i) L30(4,5,6,7, e,f,g,h, i) \ + L31(0,1,2,3, a,b,c,d, i) L31(4,5,6,7, e,f,g,h, i) \ + L32(0,1,2,3, a,b,c,d, i) L32(4,5,6,7, e,f,g,h, i) + +#define SSE2_QUARTER_ROUND_X16(i, a, b, c, d, e, f, g, h, A, B, C, D, E, F, G, H) \ + L01(0,1,2,3, a,b,c,d, i) L01(4,5,6,7, e,f,g,h, i) L01(8,9,10,11, A,B,C,D, i) L01(12,13,14,15, E,F,G,H, i) \ + L02(0,1,2,3, a,b,c,d, i) L02(4,5,6,7, e,f,g,h, i) L02(8,9,10,11, A,B,C,D, i) L02(12,13,14,15, E,F,G,H, i) \ + L03(0,1,2,3, a,b,c,d, i) L03(4,5,6,7, e,f,g,h, i) L03(8,9,10,11, A,B,C,D, i) L03(12,13,14,15, E,F,G,H, i) \ + L04(0,1,2,3, a,b,c,d, i) L04(4,5,6,7, e,f,g,h, i) L04(8,9,10,11, A,B,C,D, i) L04(12,13,14,15, E,F,G,H, i) \ + L05(0,1,2,3, a,b,c,d, i) L05(4,5,6,7, e,f,g,h, i) L05(8,9,10,11, A,B,C,D, i) L05(12,13,14,15, E,F,G,H, i) \ + L06(0,1,2,3, a,b,c,d, i) L06(4,5,6,7, e,f,g,h, i) L06(8,9,10,11, A,B,C,D, i) L06(12,13,14,15, E,F,G,H, i) \ + L07(0,1,2,3, a,b,c,d, i) L07(4,5,6,7, e,f,g,h, i) L07(8,9,10,11, A,B,C,D, i) L07(12,13,14,15, E,F,G,H, i) \ + L08(0,1,2,3, a,b,c,d, i) L08(4,5,6,7, e,f,g,h, i) L08(8,9,10,11, A,B,C,D, i) L08(12,13,14,15, E,F,G,H, i) \ + L09(0,1,2,3, a,b,c,d, i) L09(4,5,6,7, e,f,g,h, i) L09(8,9,10,11, A,B,C,D, i) L09(12,13,14,15, E,F,G,H, i) \ + L10(0,1,2,3, a,b,c,d, i) L10(4,5,6,7, e,f,g,h, i) L10(8,9,10,11, A,B,C,D, i) L10(12,13,14,15, E,F,G,H, i) \ + L11(0,1,2,3, a,b,c,d, i) L11(4,5,6,7, e,f,g,h, i) L11(8,9,10,11, A,B,C,D, i) L11(12,13,14,15, E,F,G,H, i) \ + L12(0,1,2,3, a,b,c,d, i) L12(4,5,6,7, e,f,g,h, i) L12(8,9,10,11, A,B,C,D, i) L12(12,13,14,15, E,F,G,H, i) \ + L13(0,1,2,3, a,b,c,d, i) L13(4,5,6,7, e,f,g,h, i) L13(8,9,10,11, A,B,C,D, i) L13(12,13,14,15, E,F,G,H, i) \ + L14(0,1,2,3, a,b,c,d, i) L14(4,5,6,7, e,f,g,h, i) L14(8,9,10,11, A,B,C,D, i) L14(12,13,14,15, E,F,G,H, i) \ + L15(0,1,2,3, a,b,c,d, i) L15(4,5,6,7, e,f,g,h, i) L15(8,9,10,11, A,B,C,D, i) L15(12,13,14,15, E,F,G,H, i) \ + L16(0,1,2,3, a,b,c,d, i) L16(4,5,6,7, e,f,g,h, i) L16(8,9,10,11, A,B,C,D, i) L16(12,13,14,15, E,F,G,H, i) \ + L17(0,1,2,3, a,b,c,d, i) L17(4,5,6,7, e,f,g,h, i) L17(8,9,10,11, A,B,C,D, i) L17(12,13,14,15, E,F,G,H, i) \ + L18(0,1,2,3, a,b,c,d, i) L18(4,5,6,7, e,f,g,h, i) L18(8,9,10,11, A,B,C,D, i) L18(12,13,14,15, E,F,G,H, i) \ + L19(0,1,2,3, a,b,c,d, i) L19(4,5,6,7, e,f,g,h, i) L19(8,9,10,11, A,B,C,D, i) L19(12,13,14,15, E,F,G,H, i) \ + L20(0,1,2,3, a,b,c,d, i) L20(4,5,6,7, e,f,g,h, i) L20(8,9,10,11, A,B,C,D, i) L20(12,13,14,15, E,F,G,H, i) \ + L21(0,1,2,3, a,b,c,d, i) L21(4,5,6,7, e,f,g,h, i) L21(8,9,10,11, A,B,C,D, i) L21(12,13,14,15, E,F,G,H, i) \ + L22(0,1,2,3, a,b,c,d, i) L22(4,5,6,7, e,f,g,h, i) L22(8,9,10,11, A,B,C,D, i) L22(12,13,14,15, E,F,G,H, i) \ + L23(0,1,2,3, a,b,c,d, i) L23(4,5,6,7, e,f,g,h, i) L23(8,9,10,11, A,B,C,D, i) L23(12,13,14,15, E,F,G,H, i) \ + L24(0,1,2,3, a,b,c,d, i) L24(4,5,6,7, e,f,g,h, i) L24(8,9,10,11, A,B,C,D, i) L24(12,13,14,15, E,F,G,H, i) \ + L25(0,1,2,3, a,b,c,d, i) L25(4,5,6,7, e,f,g,h, i) L25(8,9,10,11, A,B,C,D, i) L25(12,13,14,15, E,F,G,H, i) \ + L26(0,1,2,3, a,b,c,d, i) L26(4,5,6,7, e,f,g,h, i) L26(8,9,10,11, A,B,C,D, i) L26(12,13,14,15, E,F,G,H, i) \ + L27(0,1,2,3, a,b,c,d, i) L27(4,5,6,7, e,f,g,h, i) L27(8,9,10,11, A,B,C,D, i) L27(12,13,14,15, E,F,G,H, i) \ + L28(0,1,2,3, a,b,c,d, i) L28(4,5,6,7, e,f,g,h, i) L28(8,9,10,11, A,B,C,D, i) L28(12,13,14,15, E,F,G,H, i) \ + L29(0,1,2,3, a,b,c,d, i) L29(4,5,6,7, e,f,g,h, i) L29(8,9,10,11, A,B,C,D, i) L29(12,13,14,15, E,F,G,H, i) \ + L30(0,1,2,3, a,b,c,d, i) L30(4,5,6,7, e,f,g,h, i) L30(8,9,10,11, A,B,C,D, i) L30(12,13,14,15, E,F,G,H, i) \ + L31(0,1,2,3, a,b,c,d, i) L31(4,5,6,7, e,f,g,h, i) L31(8,9,10,11, A,B,C,D, i) L31(12,13,14,15, E,F,G,H, i) \ + L32(0,1,2,3, a,b,c,d, i) L32(4,5,6,7, e,f,g,h, i) L32(8,9,10,11, A,B,C,D, i) L32(12,13,14,15, E,F,G,H, i) + +#if CRYPTOPP_BOOL_X64 + SSE2_QUARTER_ROUND_X16(1, 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15) +#else + SSE2_QUARTER_ROUND_X8(1, 2, 6, 10, 14, 3, 7, 11, 15) + SSE2_QUARTER_ROUND_X8(1, 0, 4, 8, 12, 1, 5, 9, 13) +#endif + AS2( mov REG_roundsLeft, REG_rounds) + ASJ( jmp, 2, f) + + ASL(SSE2_Salsa_Output) + AS2( movdqa xmm0, xmm4) + AS2( punpckldq xmm4, xmm5) + AS2( movdqa xmm1, xmm6) + AS2( punpckldq xmm6, xmm7) + AS2( movdqa xmm2, xmm4) + AS2( punpcklqdq xmm4, xmm6) // e + AS2( punpckhqdq xmm2, xmm6) // f + AS2( punpckhdq xmm0, xmm5) + AS2( punpckhdq xmm1, xmm7) + AS2( movdqa xmm6, xmm0) + AS2( punpcklqdq xmm0, xmm1) // g + AS2( punpckhqdq xmm6, xmm1) // h + AS_XMM_OUTPUT4(SSE2_Salsa_Output_A, REG_input, REG_output, 4, 2, 0, 6, 1, 0, 4, 8, 12, 1) + AS1( ret) + + ASL(6) +#if CRYPTOPP_BOOL_X64 + SSE2_QUARTER_ROUND_X16(0, 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15) + ASL(2) + SSE2_QUARTER_ROUND_X16(0, 0, 13, 10, 7, 1, 14, 11, 4, 2, 15, 8, 5, 3, 12, 9, 6) +#else + SSE2_QUARTER_ROUND_X8(0, 2, 6, 10, 14, 3, 7, 11, 15) + SSE2_QUARTER_ROUND_X8(0, 0, 4, 8, 12, 1, 5, 9, 13) + ASL(2) + SSE2_QUARTER_ROUND_X8(0, 2, 15, 8, 5, 3, 12, 9, 6) + SSE2_QUARTER_ROUND_X8(0, 0, 13, 10, 7, 1, 14, 11, 4) +#endif + AS2( sub REG_roundsLeft, 2) + ASJ( jnz, 6, b) + +#define SSE2_OUTPUT_4(a, b, c, d) \ + AS2( movdqa xmm4, [SSE2_WORKSPACE + a*16 + 256])\ + AS2( paddd xmm4, [SSE2_WORKSPACE + a*16])\ + AS2( movdqa xmm5, [SSE2_WORKSPACE + b*16 + 256])\ + AS2( paddd xmm5, [SSE2_WORKSPACE + b*16])\ + AS2( movdqa xmm6, [SSE2_WORKSPACE + c*16 + 256])\ + AS2( paddd xmm6, [SSE2_WORKSPACE + c*16])\ + AS2( movdqa xmm7, [SSE2_WORKSPACE + d*16 + 256])\ + AS2( paddd xmm7, [SSE2_WORKSPACE + d*16])\ + ASC( call, SSE2_Salsa_Output) + + SSE2_OUTPUT_4(0, 13, 10, 7) + SSE2_OUTPUT_4(4, 1, 14, 11) + SSE2_OUTPUT_4(8, 5, 2, 15) + SSE2_OUTPUT_4(12, 9, 6, 3) + AS2( test REG_input, REG_input) + ASJ( jz, 9, f) + AS2( add REG_input, 12*16) + ASL(9) + AS2( add REG_output, 12*16) + AS2( sub REG_iterationCount, 4) + AS2( cmp REG_iterationCount, 4) + ASJ( jge, 1, b) + AS_POP_IF86( sp) + + ASL(5) + AS2( sub REG_iterationCount, 1) + ASJ( jl, 4, f) + AS2( movdqa xmm0, [REG_state + 0*16]) + AS2( movdqa xmm1, [REG_state + 1*16]) + AS2( movdqa xmm2, [REG_state + 2*16]) + AS2( movdqa xmm3, [REG_state + 3*16]) + AS2( mov REG_roundsLeft, REG_rounds) + + ASL(0) + SSE2_QUARTER_ROUND(0, 1, 3, 7) + SSE2_QUARTER_ROUND(1, 2, 0, 9) + SSE2_QUARTER_ROUND(2, 3, 1, 13) + SSE2_QUARTER_ROUND(3, 0, 2, 18) + ASS( pshufd xmm1, xmm1, 2, 1, 0, 3) + ASS( pshufd xmm2, xmm2, 1, 0, 3, 2) + ASS( pshufd xmm3, xmm3, 0, 3, 2, 1) + SSE2_QUARTER_ROUND(0, 3, 1, 7) + SSE2_QUARTER_ROUND(3, 2, 0, 9) + SSE2_QUARTER_ROUND(2, 1, 3, 13) + SSE2_QUARTER_ROUND(1, 0, 2, 18) + ASS( pshufd xmm1, xmm1, 0, 3, 2, 1) + ASS( pshufd xmm2, xmm2, 1, 0, 3, 2) + ASS( pshufd xmm3, xmm3, 2, 1, 0, 3) + AS2( sub REG_roundsLeft, 2) + ASJ( jnz, 0, b) + + AS2( paddd xmm0, [REG_state + 0*16]) + AS2( paddd xmm1, [REG_state + 1*16]) + AS2( paddd xmm2, [REG_state + 2*16]) + AS2( paddd xmm3, [REG_state + 3*16]) + + AS2( add dword ptr [REG_state + 8*4], 1) + AS2( adc dword ptr [REG_state + 5*4], 0) + + AS2( pcmpeqb xmm6, xmm6) // all ones + AS2( psrlq xmm6, 32) // lo32 mask + ASS( pshufd xmm7, xmm6, 0, 1, 2, 3) // hi32 mask + AS2( movdqa xmm4, xmm0) + AS2( movdqa xmm5, xmm3) + AS2( pand xmm0, xmm7) + AS2( pand xmm4, xmm6) + AS2( pand xmm3, xmm6) + AS2( pand xmm5, xmm7) + AS2( por xmm4, xmm5) // 0,13,2,15 + AS2( movdqa xmm5, xmm1) + AS2( pand xmm1, xmm7) + AS2( pand xmm5, xmm6) + AS2( por xmm0, xmm5) // 4,1,6,3 + AS2( pand xmm6, xmm2) + AS2( pand xmm2, xmm7) + AS2( por xmm1, xmm6) // 8,5,10,7 + AS2( por xmm2, xmm3) // 12,9,14,11 + + AS2( movdqa xmm5, xmm4) + AS2( movdqa xmm6, xmm0) + AS3( shufpd xmm4, xmm1, 2) // 0,13,10,7 + AS3( shufpd xmm0, xmm2, 2) // 4,1,14,11 + AS3( shufpd xmm1, xmm5, 2) // 8,5,2,15 + AS3( shufpd xmm2, xmm6, 2) // 12,9,6,3 + + // output keystream + AS_XMM_OUTPUT4(SSE2_Salsa_Output_B, REG_input, REG_output, 4, 0, 1, 2, 3, 0, 1, 2, 3, 4) + ASJ( jmp, 5, b) + ASL(4) + + AS_POP_IF86( bp) +#ifdef __GNUC__ + AS_POP_IF86( bx) + ".att_syntax prefix;" + : + #if CRYPTOPP_BOOL_X64 + : "r" (m_rounds), "r" (input), "r" (iterationCount), "r" (m_state.data()), "r" (output), "r" (workspace.m_ptr) + : "%eax", "%edx", "memory", "cc", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15" + #else + : "d" (m_rounds), "a" (input), "c" (iterationCount), "S" (m_state.data()), "D" (output) + : "memory", "cc" + #endif + ); +#endif +#ifdef CRYPTOPP_GENERATE_X64_MASM + movdqa xmm6, [rsp + 0200h] + movdqa xmm7, [rsp + 0210h] + movdqa xmm8, [rsp + 0220h] + movdqa xmm9, [rsp + 0230h] + movdqa xmm10, [rsp + 0240h] + movdqa xmm11, [rsp + 0250h] + movdqa xmm12, [rsp + 0260h] + movdqa xmm13, [rsp + 0270h] + movdqa xmm14, [rsp + 0280h] + movdqa xmm15, [rsp + 0290h] + add rsp, 10*16 + 32*16 + 8 + ret +Salsa20_OperateKeystream ENDP +#else + } + else +#endif +#endif +#ifndef CRYPTOPP_GENERATE_X64_MASM + { + word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; + + while (iterationCount--) + { + x0 = m_state[0]; x1 = m_state[1]; x2 = m_state[2]; x3 = m_state[3]; + x4 = m_state[4]; x5 = m_state[5]; x6 = m_state[6]; x7 = m_state[7]; + x8 = m_state[8]; x9 = m_state[9]; x10 = m_state[10]; x11 = m_state[11]; + x12 = m_state[12]; x13 = m_state[13]; x14 = m_state[14]; x15 = m_state[15]; + + for (int i=m_rounds; i>0; i-=2) + { + #define QUARTER_ROUND(a, b, c, d) \ + b = b ^ rotlFixed(a + d, 7); \ + c = c ^ rotlFixed(b + a, 9); \ + d = d ^ rotlFixed(c + b, 13); \ + a = a ^ rotlFixed(d + c, 18); + + QUARTER_ROUND(x0, x4, x8, x12) + QUARTER_ROUND(x1, x5, x9, x13) + QUARTER_ROUND(x2, x6, x10, x14) + QUARTER_ROUND(x3, x7, x11, x15) + + QUARTER_ROUND(x0, x13, x10, x7) + QUARTER_ROUND(x1, x14, x11, x4) + QUARTER_ROUND(x2, x15, x8, x5) + QUARTER_ROUND(x3, x12, x9, x6) + } + + #define SALSA_OUTPUT(x) {\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 0, x0 + m_state[0]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 1, x13 + m_state[13]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 2, x10 + m_state[10]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 3, x7 + m_state[7]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 4, x4 + m_state[4]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 5, x1 + m_state[1]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 6, x14 + m_state[14]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 7, x11 + m_state[11]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 8, x8 + m_state[8]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 9, x5 + m_state[5]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 10, x2 + m_state[2]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 11, x15 + m_state[15]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 12, x12 + m_state[12]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 13, x9 + m_state[9]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 14, x6 + m_state[6]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 15, x3 + m_state[3]);} + +#ifndef CRYPTOPP_DOXYGEN_PROCESSING + CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(SALSA_OUTPUT, BYTES_PER_ITERATION); +#endif + + if (++m_state[8] == 0) + ++m_state[5]; + } + } +} // see comment above if an internal compiler error occurs here + +void XSalsa20_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) +{ + m_rounds = params.GetIntValueWithDefault(Name::Rounds(), 20); + + if (!(m_rounds == 8 || m_rounds == 12 || m_rounds == 20)) + throw InvalidRounds(XSalsa20::StaticAlgorithmName(), m_rounds); + + GetUserKey(LITTLE_ENDIAN_ORDER, m_key.begin(), m_key.size(), key, length); + if (length == 16) + memcpy(m_key.begin()+4, m_key.begin(), 16); + + // "expand 32-byte k" + m_state[0] = 0x61707865; + m_state[1] = 0x3320646e; + m_state[2] = 0x79622d32; + m_state[3] = 0x6b206574; +} + +void XSalsa20_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length) +{ + assert(length==24); + + word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; + + GetBlock get(IV); + get(x14)(x11)(x8)(x5)(m_state[14])(m_state[11]); + + x13 = m_key[0]; x10 = m_key[1]; x7 = m_key[2]; x4 = m_key[3]; + x15 = m_key[4]; x12 = m_key[5]; x9 = m_key[6]; x6 = m_key[7]; + x0 = m_state[0]; x1 = m_state[1]; x2 = m_state[2]; x3 = m_state[3]; + + for (int i=m_rounds; i>0; i-=2) + { + QUARTER_ROUND(x0, x4, x8, x12) + QUARTER_ROUND(x1, x5, x9, x13) + QUARTER_ROUND(x2, x6, x10, x14) + QUARTER_ROUND(x3, x7, x11, x15) + + QUARTER_ROUND(x0, x13, x10, x7) + QUARTER_ROUND(x1, x14, x11, x4) + QUARTER_ROUND(x2, x15, x8, x5) + QUARTER_ROUND(x3, x12, x9, x6) + } + + m_state[13] = x0; m_state[10] = x1; m_state[7] = x2; m_state[4] = x3; + m_state[15] = x14; m_state[12] = x11; m_state[9] = x8; m_state[6] = x5; + m_state[8] = m_state[5] = 0; +} + +NAMESPACE_END + +#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM diff --git a/src-cryptopp/salsa.h b/src-cryptopp/salsa.h new file mode 100644 index 0000000..49af885 --- /dev/null +++ b/src-cryptopp/salsa.h @@ -0,0 +1,65 @@ +// salsa.h - written and placed in the public domain by Wei Dai + +#ifndef CRYPTOPP_SALSA_H +#define CRYPTOPP_SALSA_H + +#include "strciphr.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! _ +struct Salsa20_Info : public VariableKeyLength<32, 16, 32, 16, SimpleKeyingInterface::UNIQUE_IV, 8> +{ + static const char *StaticAlgorithmName() {return "Salsa20";} +}; + +class CRYPTOPP_NO_VTABLE Salsa20_Policy : public AdditiveCipherConcretePolicy +{ +protected: + void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length); + void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount); + void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length); + bool CipherIsRandomAccess() const {return true;} + void SeekToIteration(lword iterationCount); +#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64 + unsigned int GetAlignment() const; + unsigned int GetOptimalBlockSize() const; +#endif + + FixedSizeAlignedSecBlock m_state; + int m_rounds; +}; + +/// Salsa20, variable rounds: 8, 12 or 20 (default 20) +struct Salsa20 : public Salsa20_Info, public SymmetricCipherDocumentation +{ + typedef SymmetricCipherFinal >, Salsa20_Info> Encryption; + typedef Encryption Decryption; +}; + +//! _ +struct XSalsa20_Info : public FixedKeyLength<32, SimpleKeyingInterface::UNIQUE_IV, 24> +{ + static const char *StaticAlgorithmName() {return "XSalsa20";} +}; + +class CRYPTOPP_NO_VTABLE XSalsa20_Policy : public Salsa20_Policy +{ +public: + void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length); + void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length); + +protected: + FixedSizeSecBlock m_key; +}; + +/// XSalsa20, variable rounds: 8, 12 or 20 (default 20) +struct XSalsa20 : public XSalsa20_Info, public SymmetricCipherDocumentation +{ + typedef SymmetricCipherFinal >, XSalsa20_Info> Encryption; + typedef Encryption Decryption; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/secblock.h b/src-cryptopp/secblock.h new file mode 100644 index 0000000..6300e27 --- /dev/null +++ b/src-cryptopp/secblock.h @@ -0,0 +1,501 @@ +// secblock.h - written and placed in the public domain by Wei Dai + +#ifndef CRYPTOPP_SECBLOCK_H +#define CRYPTOPP_SECBLOCK_H + +#include "config.h" +#include "misc.h" +#include + +#if defined(CRYPTOPP_MEMALIGN_AVAILABLE) || defined(CRYPTOPP_MM_MALLOC_AVAILABLE) || defined(QNX) + #include +#endif + +NAMESPACE_BEGIN(CryptoPP) + +// ************** secure memory allocation *************** + +template +class AllocatorBase +{ +public: + typedef T value_type; + typedef size_t size_type; +#ifdef CRYPTOPP_MSVCRT6 + typedef ptrdiff_t difference_type; +#else + typedef std::ptrdiff_t difference_type; +#endif + typedef T * pointer; + typedef const T * const_pointer; + typedef T & reference; + typedef const T & const_reference; + + pointer address(reference r) const {return (&r);} + const_pointer address(const_reference r) const {return (&r); } + void construct(pointer p, const T& val) {new (p) T(val);} + void destroy(pointer p) {p->~T();} + size_type max_size() const {return ~size_type(0)/sizeof(T);} // switch to std::numeric_limits::max later + +protected: + static void CheckSize(size_t n) + { + if (n > ~size_t(0) / sizeof(T)) + throw InvalidArgument("AllocatorBase: requested size would cause integer overflow"); + } +}; + +#define CRYPTOPP_INHERIT_ALLOCATOR_TYPES \ +typedef typename AllocatorBase::value_type value_type;\ +typedef typename AllocatorBase::size_type size_type;\ +typedef typename AllocatorBase::difference_type difference_type;\ +typedef typename AllocatorBase::pointer pointer;\ +typedef typename AllocatorBase::const_pointer const_pointer;\ +typedef typename AllocatorBase::reference reference;\ +typedef typename AllocatorBase::const_reference const_reference; + +#if defined(_MSC_VER) && (_MSC_VER < 1300) +// this pragma causes an internal compiler error if placed immediately before std::swap(a, b) +#pragma warning(push) +#pragma warning(disable: 4700) // VC60 workaround: don't know how to get rid of this warning +#endif + +template +typename A::pointer StandardReallocate(A& a, T *p, typename A::size_type oldSize, typename A::size_type newSize, bool preserve) +{ + if (oldSize == newSize) + return p; + + if (preserve) + { + typename A::pointer newPointer = a.allocate(newSize, NULL); + memcpy_s(newPointer, sizeof(T)*newSize, p, sizeof(T)*STDMIN(oldSize, newSize)); + a.deallocate(p, oldSize); + return newPointer; + } + else + { + a.deallocate(p, oldSize); + return a.allocate(newSize, NULL); + } +} + +#if defined(_MSC_VER) && (_MSC_VER < 1300) +#pragma warning(pop) +#endif + +template +class AllocatorWithCleanup : public AllocatorBase +{ +public: + CRYPTOPP_INHERIT_ALLOCATOR_TYPES + + pointer allocate(size_type n, const void * = NULL) + { + this->CheckSize(n); + if (n == 0) + return NULL; + + if (CRYPTOPP_BOOL_ALIGN16_ENABLED && T_Align16 && n*sizeof(T) >= 16) + { + byte *p; + #ifdef CRYPTOPP_MM_MALLOC_AVAILABLE + while (!(p = (byte *)_mm_malloc(sizeof(T)*n, 16))) + #elif defined(CRYPTOPP_MEMALIGN_AVAILABLE) + while (!(p = (byte *)memalign(16, sizeof(T)*n))) + #elif defined(CRYPTOPP_MALLOC_ALIGNMENT_IS_16) + while (!(p = (byte *)malloc(sizeof(T)*n))) + #else + while (!(p = (byte *)malloc(sizeof(T)*n + 16))) + #endif + CallNewHandler(); + + #ifdef CRYPTOPP_NO_ALIGNED_ALLOC + size_t adjustment = 16-((size_t)p%16); + p += adjustment; + p[-1] = (byte)adjustment; + #endif + + assert(IsAlignedOn(p, 16)); + return (pointer)p; + } + + pointer p; + while (!(p = (pointer)malloc(sizeof(T)*n))) + CallNewHandler(); + return p; + } + + void deallocate(void *p, size_type n) + { + memset_z(p, 0, n*sizeof(T)); + + if (CRYPTOPP_BOOL_ALIGN16_ENABLED && T_Align16 && n*sizeof(T) >= 16) + { + #ifdef CRYPTOPP_MM_MALLOC_AVAILABLE + _mm_free(p); + #elif defined(CRYPTOPP_NO_ALIGNED_ALLOC) + p = (byte *)p - ((byte *)p)[-1]; + free(p); + #else + free(p); + #endif + return; + } + + free(p); + } + + pointer reallocate(T *p, size_type oldSize, size_type newSize, bool preserve) + { + return StandardReallocate(*this, p, oldSize, newSize, preserve); + } + + // VS.NET STL enforces the policy of "All STL-compliant allocators have to provide a + // template class member called rebind". + template struct rebind { typedef AllocatorWithCleanup other; }; +#if _MSC_VER >= 1500 + AllocatorWithCleanup() {} + template AllocatorWithCleanup(const AllocatorWithCleanup &) {} +#endif +}; + +CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; +CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; +CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; +CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; +#if CRYPTOPP_BOOL_X86 +CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup; // for Integer +#endif + +template +class NullAllocator : public AllocatorBase +{ +public: + CRYPTOPP_INHERIT_ALLOCATOR_TYPES + + pointer allocate(size_type n, const void * = NULL) + { + assert(false); + return NULL; + } + + void deallocate(void *p, size_type n) + { + assert(false); + } + + size_type max_size() const {return 0;} +}; + +// This allocator can't be used with standard collections because +// they require that all objects of the same allocator type are equivalent. +// So this is for use with SecBlock only. +template , bool T_Align16 = false> +class FixedSizeAllocatorWithCleanup : public AllocatorBase +{ +public: + CRYPTOPP_INHERIT_ALLOCATOR_TYPES + + FixedSizeAllocatorWithCleanup() : m_allocated(false) {} + + pointer allocate(size_type n) + { + assert(IsAlignedOn(m_array, 8)); + + if (n <= S && !m_allocated) + { + m_allocated = true; + return GetAlignedArray(); + } + else + return m_fallbackAllocator.allocate(n); + } + + pointer allocate(size_type n, const void *hint) + { + if (n <= S && !m_allocated) + { + m_allocated = true; + return GetAlignedArray(); + } + else + return m_fallbackAllocator.allocate(n, hint); + } + + void deallocate(void *p, size_type n) + { + if (p == GetAlignedArray()) + { + assert(n <= S); + assert(m_allocated); + m_allocated = false; + memset(p, 0, n*sizeof(T)); + } + else + m_fallbackAllocator.deallocate(p, n); + } + + pointer reallocate(pointer p, size_type oldSize, size_type newSize, bool preserve) + { + if (p == GetAlignedArray() && newSize <= S) + { + assert(oldSize <= S); + if (oldSize > newSize) + memset(p + newSize, 0, (oldSize-newSize)*sizeof(T)); + return p; + } + + pointer newPointer = allocate(newSize, NULL); + if (preserve) + memcpy(newPointer, p, sizeof(T)*STDMIN(oldSize, newSize)); + deallocate(p, oldSize); + return newPointer; + } + + size_type max_size() const {return STDMAX(m_fallbackAllocator.max_size(), S);} + +private: +#ifdef __BORLANDC__ + T* GetAlignedArray() {return m_array;} + T m_array[S]; +#else + T* GetAlignedArray() {return (CRYPTOPP_BOOL_ALIGN16_ENABLED && T_Align16) ? (T*)(((byte *)m_array) + (0-(size_t)m_array)%16) : m_array;} + CRYPTOPP_ALIGN_DATA(8) T m_array[(CRYPTOPP_BOOL_ALIGN16_ENABLED && T_Align16) ? S+8/sizeof(T) : S]; +#endif + A m_fallbackAllocator; + bool m_allocated; +}; + +//! a block of memory allocated using A +template > +class SecBlock +{ +public: + typedef typename A::value_type value_type; + typedef typename A::pointer iterator; + typedef typename A::const_pointer const_iterator; + typedef typename A::size_type size_type; + + explicit SecBlock(size_type size=0) + : m_size(size) {m_ptr = m_alloc.allocate(size, NULL);} + SecBlock(const SecBlock &t) + : m_size(t.m_size) {m_ptr = m_alloc.allocate(m_size, NULL); memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, m_size*sizeof(T));} + SecBlock(const T *t, size_type len) + : m_size(len) + { + m_ptr = m_alloc.allocate(len, NULL); + if (t == NULL) + memset_z(m_ptr, 0, len*sizeof(T)); + else + memcpy(m_ptr, t, len*sizeof(T)); + } + + ~SecBlock() + {m_alloc.deallocate(m_ptr, m_size);} + +#ifdef __BORLANDC__ + operator T *() const + {return (T*)m_ptr;} +#else + operator const void *() const + {return m_ptr;} + operator void *() + {return m_ptr;} + + operator const T *() const + {return m_ptr;} + operator T *() + {return m_ptr;} +#endif + +// T *operator +(size_type offset) +// {return m_ptr+offset;} + +// const T *operator +(size_type offset) const +// {return m_ptr+offset;} + +// T& operator[](size_type index) +// {assert(index >= 0 && index < m_size); return m_ptr[index];} + +// const T& operator[](size_type index) const +// {assert(index >= 0 && index < m_size); return m_ptr[index];} + + iterator begin() + {return m_ptr;} + const_iterator begin() const + {return m_ptr;} + iterator end() + {return m_ptr+m_size;} + const_iterator end() const + {return m_ptr+m_size;} + + typename A::pointer data() {return m_ptr;} + typename A::const_pointer data() const {return m_ptr;} + + size_type size() const {return m_size;} + bool empty() const {return m_size == 0;} + + byte * BytePtr() {return (byte *)m_ptr;} + const byte * BytePtr() const {return (const byte *)m_ptr;} + size_type SizeInBytes() const {return m_size*sizeof(T);} + + //! set contents and size + void Assign(const T *t, size_type len) + { + New(len); + memcpy_s(m_ptr, m_size*sizeof(T), t, len*sizeof(T)); + } + + //! copy contents and size from another SecBlock + void Assign(const SecBlock &t) + { + if (this != &t) + { + New(t.m_size); + memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, m_size*sizeof(T)); + } + } + + SecBlock& operator=(const SecBlock &t) + { + Assign(t); + return *this; + } + + // append to this object + SecBlock& operator+=(const SecBlock &t) + { + size_type oldSize = m_size; + Grow(m_size+t.m_size); + memcpy_s(m_ptr+oldSize, m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T)); + return *this; + } + + // append operator + SecBlock operator+(const SecBlock &t) + { + SecBlock result(m_size+t.m_size); + memcpy_s(result.m_ptr, result.m_size*sizeof(T), m_ptr, m_size*sizeof(T)); + memcpy_s(result.m_ptr+m_size, t.m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T)); + return result; + } + + bool operator==(const SecBlock &t) const + { + return m_size == t.m_size && VerifyBufsEqual(m_ptr, t.m_ptr, m_size*sizeof(T)); + } + + bool operator!=(const SecBlock &t) const + { + return !operator==(t); + } + + //! change size, without preserving contents + void New(size_type newSize) + { + m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false); + m_size = newSize; + } + + //! change size and set contents to 0 + void CleanNew(size_type newSize) + { + New(newSize); + memset_z(m_ptr, 0, m_size*sizeof(T)); + } + + //! change size only if newSize > current size. contents are preserved + void Grow(size_type newSize) + { + if (newSize > m_size) + { + m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true); + m_size = newSize; + } + } + + //! change size only if newSize > current size. contents are preserved and additional area is set to 0 + void CleanGrow(size_type newSize) + { + if (newSize > m_size) + { + m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true); + memset(m_ptr+m_size, 0, (newSize-m_size)*sizeof(T)); + m_size = newSize; + } + } + + //! change size and preserve contents + void resize(size_type newSize) + { + m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true); + m_size = newSize; + } + + //! swap contents and size with another SecBlock + void swap(SecBlock &b) + { + std::swap(m_alloc, b.m_alloc); + std::swap(m_size, b.m_size); + std::swap(m_ptr, b.m_ptr); + } + +//private: + A m_alloc; + size_type m_size; + T *m_ptr; +}; + +typedef SecBlock SecByteBlock; +typedef SecBlock > AlignedSecByteBlock; +typedef SecBlock SecWordBlock; + +//! a SecBlock with fixed size, allocated statically +template > +class FixedSizeSecBlock : public SecBlock +{ +public: + explicit FixedSizeSecBlock() : SecBlock(S) {} +}; + +template +class FixedSizeAlignedSecBlock : public FixedSizeSecBlock, T_Align16> > +{ +}; + +//! a SecBlock that preallocates size S statically, and uses the heap when this size is exceeded +template > > +class SecBlockWithHint : public SecBlock +{ +public: + explicit SecBlockWithHint(size_t size) : SecBlock(size) {} +}; + +template +inline bool operator==(const CryptoPP::AllocatorWithCleanup&, const CryptoPP::AllocatorWithCleanup&) {return (true);} +template +inline bool operator!=(const CryptoPP::AllocatorWithCleanup&, const CryptoPP::AllocatorWithCleanup&) {return (false);} + +NAMESPACE_END + +NAMESPACE_BEGIN(std) +template +inline void swap(CryptoPP::SecBlock &a, CryptoPP::SecBlock &b) +{ + a.swap(b); +} + +#if defined(_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE) || (defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES)) +// working for STLport 5.1.3 and MSVC 6 SP5 +template +inline CryptoPP::AllocatorWithCleanup<_Tp2>& +__stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*) +{ + return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a); +} +#endif + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/seckey.h b/src-cryptopp/seckey.h new file mode 100644 index 0000000..35046a6 --- /dev/null +++ b/src-cryptopp/seckey.h @@ -0,0 +1,221 @@ +// seckey.h - written and placed in the public domain by Wei Dai + +// This file contains helper classes/functions for implementing secret key algorithms. + +#ifndef CRYPTOPP_SECKEY_H +#define CRYPTOPP_SECKEY_H + +#include "cryptlib.h" +#include "misc.h" +#include "simple.h" + +NAMESPACE_BEGIN(CryptoPP) + +inline CipherDir ReverseCipherDir(CipherDir dir) +{ + return (dir == ENCRYPTION) ? DECRYPTION : ENCRYPTION; +} + +//! to be inherited by block ciphers with fixed block size +template +class FixedBlockSize +{ +public: + CRYPTOPP_CONSTANT(BLOCKSIZE = N) +}; + +// ************** rounds *************** + +//! to be inherited by ciphers with fixed number of rounds +template +class FixedRounds +{ +public: + CRYPTOPP_CONSTANT(ROUNDS = R) +}; + +//! to be inherited by ciphers with variable number of rounds +template // use INT_MAX here because enums are treated as signed ints +class VariableRounds +{ +public: + CRYPTOPP_CONSTANT(DEFAULT_ROUNDS = D) + CRYPTOPP_CONSTANT(MIN_ROUNDS = N) + CRYPTOPP_CONSTANT(MAX_ROUNDS = M) + static unsigned int StaticGetDefaultRounds(size_t keylength) {return DEFAULT_ROUNDS;} + +protected: + inline void ThrowIfInvalidRounds(int rounds, const Algorithm *alg) + { + if (rounds < MIN_ROUNDS || rounds > MAX_ROUNDS) + throw InvalidRounds(alg->AlgorithmName(), rounds); + } + + inline unsigned int GetRoundsAndThrowIfInvalid(const NameValuePairs ¶m, const Algorithm *alg) + { + int rounds = param.GetIntValueWithDefault("Rounds", DEFAULT_ROUNDS); + ThrowIfInvalidRounds(rounds, alg); + return (unsigned int)rounds; + } +}; + +// ************** key length *************** + +//! to be inherited by keyed algorithms with fixed key length +template +class FixedKeyLength +{ +public: + CRYPTOPP_CONSTANT(KEYLENGTH=N) + CRYPTOPP_CONSTANT(MIN_KEYLENGTH=N) + CRYPTOPP_CONSTANT(MAX_KEYLENGTH=N) + CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH=N) + CRYPTOPP_CONSTANT(IV_REQUIREMENT = IV_REQ) + CRYPTOPP_CONSTANT(IV_LENGTH = IV_L) + static size_t CRYPTOPP_API StaticGetValidKeyLength(size_t) {return KEYLENGTH;} +}; + +/// support query of variable key length, template parameters are default, min, max, multiple (default multiple 1) +template +class VariableKeyLength +{ + // make these private to avoid Doxygen documenting them in all derived classes + CRYPTOPP_COMPILE_ASSERT(Q > 0); + CRYPTOPP_COMPILE_ASSERT(N % Q == 0); + CRYPTOPP_COMPILE_ASSERT(M % Q == 0); + CRYPTOPP_COMPILE_ASSERT(N < M); + CRYPTOPP_COMPILE_ASSERT(D >= N); + CRYPTOPP_COMPILE_ASSERT(M >= D); + +public: + CRYPTOPP_CONSTANT(MIN_KEYLENGTH=N) + CRYPTOPP_CONSTANT(MAX_KEYLENGTH=M) + CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH=D) + CRYPTOPP_CONSTANT(KEYLENGTH_MULTIPLE=Q) + CRYPTOPP_CONSTANT(IV_REQUIREMENT=IV_REQ) + CRYPTOPP_CONSTANT(IV_LENGTH=IV_L) + + static size_t CRYPTOPP_API StaticGetValidKeyLength(size_t n) + { + if (n < (size_t)MIN_KEYLENGTH) + return MIN_KEYLENGTH; + else if (n > (size_t)MAX_KEYLENGTH) + return (size_t)MAX_KEYLENGTH; + else + { + n += KEYLENGTH_MULTIPLE-1; + return n - n%KEYLENGTH_MULTIPLE; + } + } +}; + +/// support query of key length that's the same as another class +template +class SameKeyLengthAs +{ +public: + CRYPTOPP_CONSTANT(MIN_KEYLENGTH=T::MIN_KEYLENGTH) + CRYPTOPP_CONSTANT(MAX_KEYLENGTH=T::MAX_KEYLENGTH) + CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH=T::DEFAULT_KEYLENGTH) + CRYPTOPP_CONSTANT(IV_REQUIREMENT=IV_REQ) + CRYPTOPP_CONSTANT(IV_LENGTH=IV_L) + + static size_t CRYPTOPP_API StaticGetValidKeyLength(size_t keylength) + {return T::StaticGetValidKeyLength(keylength);} +}; + +// ************** implementation helper for SimpleKeyed *************** + +//! _ +template +class CRYPTOPP_NO_VTABLE SimpleKeyingInterfaceImpl : public BASE +{ +public: + size_t MinKeyLength() const {return INFO::MIN_KEYLENGTH;} + size_t MaxKeyLength() const {return (size_t)INFO::MAX_KEYLENGTH;} + size_t DefaultKeyLength() const {return INFO::DEFAULT_KEYLENGTH;} + size_t GetValidKeyLength(size_t n) const {return INFO::StaticGetValidKeyLength(n);} + SimpleKeyingInterface::IV_Requirement IVRequirement() const {return (SimpleKeyingInterface::IV_Requirement)INFO::IV_REQUIREMENT;} + unsigned int IVSize() const {return INFO::IV_LENGTH;} +}; + +template +class CRYPTOPP_NO_VTABLE BlockCipherImpl : public AlgorithmImpl > > +{ +public: + unsigned int BlockSize() const {return this->BLOCKSIZE;} +}; + +//! _ +template +class BlockCipherFinal : public ClonableImpl, BASE> +{ +public: + BlockCipherFinal() {} + BlockCipherFinal(const byte *key) + {this->SetKey(key, this->DEFAULT_KEYLENGTH);} + BlockCipherFinal(const byte *key, size_t length) + {this->SetKey(key, length);} + BlockCipherFinal(const byte *key, size_t length, unsigned int rounds) + {this->SetKeyWithRounds(key, length, rounds);} + + bool IsForwardTransformation() const {return DIR == ENCRYPTION;} +}; + +//! _ +template +class MessageAuthenticationCodeImpl : public AlgorithmImpl, INFO> +{ +}; + +//! _ +template +class MessageAuthenticationCodeFinal : public ClonableImpl, MessageAuthenticationCodeImpl > +{ +public: + MessageAuthenticationCodeFinal() {} + MessageAuthenticationCodeFinal(const byte *key) + {this->SetKey(key, this->DEFAULT_KEYLENGTH);} + MessageAuthenticationCodeFinal(const byte *key, size_t length) + {this->SetKey(key, length);} +}; + +// ************** documentation *************** + +//! These objects usually should not be used directly. See CipherModeDocumentation instead. +/*! Each class derived from this one defines two types, Encryption and Decryption, + both of which implement the BlockCipher interface. */ +struct BlockCipherDocumentation +{ + //! implements the BlockCipher interface + typedef BlockCipher Encryption; + //! implements the BlockCipher interface + typedef BlockCipher Decryption; +}; + +/*! \brief Each class derived from this one defines two types, Encryption and Decryption, + both of which implement the SymmetricCipher interface. Two types of classes derive + from this class: stream ciphers and block cipher modes. Stream ciphers can be used + alone, cipher mode classes need to be used with a block cipher. See CipherModeDocumentation + for more for information about using cipher modes and block ciphers. */ +struct SymmetricCipherDocumentation +{ + //! implements the SymmetricCipher interface + typedef SymmetricCipher Encryption; + //! implements the SymmetricCipher interface + typedef SymmetricCipher Decryption; +}; + +/*! \brief Each class derived from this one defines two types, Encryption and Decryption, + both of which implement the AuthenticatedSymmetricCipher interface. */ +struct AuthenticatedSymmetricCipherDocumentation +{ + //! implements the AuthenticatedSymmetricCipher interface + typedef AuthenticatedSymmetricCipher Encryption; + //! implements the AuthenticatedSymmetricCipher interface + typedef AuthenticatedSymmetricCipher Decryption; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/serpent.cpp b/src-cryptopp/serpent.cpp new file mode 100644 index 0000000..40fab23 --- /dev/null +++ b/src-cryptopp/serpent.cpp @@ -0,0 +1,123 @@ +// serpent.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "serpent.h" +#include "misc.h" + +#include "serpentp.h" + +NAMESPACE_BEGIN(CryptoPP) + +void Serpent_KeySchedule(word32 *k, unsigned int rounds, const byte *userKey, size_t keylen) +{ + FixedSizeSecBlock k0; + GetUserKey(LITTLE_ENDIAN_ORDER, k0.begin(), 8, userKey, keylen); + if (keylen < 32) + k0[keylen/4] |= word32(1) << ((keylen%4)*8); + + word32 t = k0[7]; + unsigned int i; + for (i = 0; i < 8; ++i) + k[i] = k0[i] = t = rotlFixed(k0[i] ^ k0[(i+3)%8] ^ k0[(i+5)%8] ^ t ^ 0x9e3779b9 ^ i, 11); + for (i = 8; i < 4*(rounds+1); ++i) + k[i] = t = rotlFixed(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11); + k -= 20; + + word32 a,b,c,d,e; + for (i=0; i Block; + +void Serpent::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 a, b, c, d, e; + + Block::Get(inBlock)(a)(b)(c)(d); + + const word32 *k = m_key; + unsigned int i=1; + + do + { + beforeS0(KX); beforeS0(S0); afterS0(LT); + afterS0(KX); afterS0(S1); afterS1(LT); + afterS1(KX); afterS1(S2); afterS2(LT); + afterS2(KX); afterS2(S3); afterS3(LT); + afterS3(KX); afterS3(S4); afterS4(LT); + afterS4(KX); afterS4(S5); afterS5(LT); + afterS5(KX); afterS5(S6); afterS6(LT); + afterS6(KX); afterS6(S7); + + if (i == 4) + break; + + ++i; + c = b; + b = e; + e = d; + d = a; + a = e; + k += 32; + beforeS0(LT); + } + while (true); + + afterS7(KX); + + Block::Put(xorBlock, outBlock)(d)(e)(b)(a); +} + +void Serpent::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 a, b, c, d, e; + + Block::Get(inBlock)(a)(b)(c)(d); + + const word32 *k = m_key + 96; + unsigned int i=4; + + beforeI7(KX); + goto start; + + do + { + c = b; + b = d; + d = e; + k -= 32; + beforeI7(ILT); +start: + beforeI7(I7); afterI7(KX); + afterI7(ILT); afterI7(I6); afterI6(KX); + afterI6(ILT); afterI6(I5); afterI5(KX); + afterI5(ILT); afterI5(I4); afterI4(KX); + afterI4(ILT); afterI4(I3); afterI3(KX); + afterI3(ILT); afterI3(I2); afterI2(KX); + afterI2(ILT); afterI2(I1); afterI1(KX); + afterI1(ILT); afterI1(I0); afterI0(KX); + } + while (--i != 0); + + Block::Put(xorBlock, outBlock)(a)(d)(b)(e); +} + +NAMESPACE_END diff --git a/src-cryptopp/serpent.h b/src-cryptopp/serpent.h new file mode 100644 index 0000000..f7ee8d6 --- /dev/null +++ b/src-cryptopp/serpent.h @@ -0,0 +1,52 @@ +#ifndef CRYPTOPP_SERPENT_H +#define CRYPTOPP_SERPENT_H + +/** \file +*/ + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! _ +struct Serpent_Info : public FixedBlockSize<16>, public VariableKeyLength<16, 0, 32>, public FixedRounds<32> +{ + static const char *StaticAlgorithmName() {return "Serpent";} +}; + +/// Serpent +class Serpent : public Serpent_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + + protected: + FixedSizeSecBlock m_key; + }; + + class CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + class CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef Serpent::Encryption SerpentEncryption; +typedef Serpent::Decryption SerpentDecryption; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/serpentp.h b/src-cryptopp/serpentp.h new file mode 100644 index 0000000..7869a3f --- /dev/null +++ b/src-cryptopp/serpentp.h @@ -0,0 +1,434 @@ +// private header for Serpent and Sosemanuk + +NAMESPACE_BEGIN(CryptoPP) + +// linear transformation +#define LT(i,a,b,c,d,e) {\ + a = rotlFixed(a, 13); \ + c = rotlFixed(c, 3); \ + d = rotlFixed(d ^ c ^ (a << 3), 7); \ + b = rotlFixed(b ^ a ^ c, 1); \ + a = rotlFixed(a ^ b ^ d, 5); \ + c = rotlFixed(c ^ d ^ (b << 7), 22);} + +// inverse linear transformation +#define ILT(i,a,b,c,d,e) {\ + c = rotrFixed(c, 22); \ + a = rotrFixed(a, 5); \ + c ^= d ^ (b << 7); \ + a ^= b ^ d; \ + b = rotrFixed(b, 1); \ + d = rotrFixed(d, 7) ^ c ^ (a << 3); \ + b ^= a ^ c; \ + c = rotrFixed(c, 3); \ + a = rotrFixed(a, 13);} + +// order of output from S-box functions +#define beforeS0(f) f(0,a,b,c,d,e) +#define afterS0(f) f(1,b,e,c,a,d) +#define afterS1(f) f(2,c,b,a,e,d) +#define afterS2(f) f(3,a,e,b,d,c) +#define afterS3(f) f(4,e,b,d,c,a) +#define afterS4(f) f(5,b,a,e,c,d) +#define afterS5(f) f(6,a,c,b,e,d) +#define afterS6(f) f(7,a,c,d,b,e) +#define afterS7(f) f(8,d,e,b,a,c) + +// order of output from inverse S-box functions +#define beforeI7(f) f(8,a,b,c,d,e) +#define afterI7(f) f(7,d,a,b,e,c) +#define afterI6(f) f(6,a,b,c,e,d) +#define afterI5(f) f(5,b,d,e,c,a) +#define afterI4(f) f(4,b,c,e,a,d) +#define afterI3(f) f(3,a,b,e,c,d) +#define afterI2(f) f(2,b,d,e,c,a) +#define afterI1(f) f(1,a,b,c,e,d) +#define afterI0(f) f(0,a,d,b,e,c) + +// The instruction sequences for the S-box functions +// come from Dag Arne Osvik's paper "Speeding up Serpent". + +#define S0(i, r0, r1, r2, r3, r4) \ + { \ + r3 ^= r0; \ + r4 = r1; \ + r1 &= r3; \ + r4 ^= r2; \ + r1 ^= r0; \ + r0 |= r3; \ + r0 ^= r4; \ + r4 ^= r3; \ + r3 ^= r2; \ + r2 |= r1; \ + r2 ^= r4; \ + r4 = ~r4; \ + r4 |= r1; \ + r1 ^= r3; \ + r1 ^= r4; \ + r3 |= r0; \ + r1 ^= r3; \ + r4 ^= r3; \ + } + +#define I0(i, r0, r1, r2, r3, r4) \ + { \ + r2 = ~r2; \ + r4 = r1; \ + r1 |= r0; \ + r4 = ~r4; \ + r1 ^= r2; \ + r2 |= r4; \ + r1 ^= r3; \ + r0 ^= r4; \ + r2 ^= r0; \ + r0 &= r3; \ + r4 ^= r0; \ + r0 |= r1; \ + r0 ^= r2; \ + r3 ^= r4; \ + r2 ^= r1; \ + r3 ^= r0; \ + r3 ^= r1; \ + r2 &= r3; \ + r4 ^= r2; \ + } + +#define S1(i, r0, r1, r2, r3, r4) \ + { \ + r0 = ~r0; \ + r2 = ~r2; \ + r4 = r0; \ + r0 &= r1; \ + r2 ^= r0; \ + r0 |= r3; \ + r3 ^= r2; \ + r1 ^= r0; \ + r0 ^= r4; \ + r4 |= r1; \ + r1 ^= r3; \ + r2 |= r0; \ + r2 &= r4; \ + r0 ^= r1; \ + r1 &= r2; \ + r1 ^= r0; \ + r0 &= r2; \ + r0 ^= r4; \ + } + +#define I1(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r1; \ + r1 ^= r3; \ + r3 &= r1; \ + r4 ^= r2; \ + r3 ^= r0; \ + r0 |= r1; \ + r2 ^= r3; \ + r0 ^= r4; \ + r0 |= r2; \ + r1 ^= r3; \ + r0 ^= r1; \ + r1 |= r3; \ + r1 ^= r0; \ + r4 = ~r4; \ + r4 ^= r1; \ + r1 |= r0; \ + r1 ^= r0; \ + r1 |= r4; \ + r3 ^= r1; \ + } + +#define S2(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r0; \ + r0 &= r2; \ + r0 ^= r3; \ + r2 ^= r1; \ + r2 ^= r0; \ + r3 |= r4; \ + r3 ^= r1; \ + r4 ^= r2; \ + r1 = r3; \ + r3 |= r4; \ + r3 ^= r0; \ + r0 &= r1; \ + r4 ^= r0; \ + r1 ^= r3; \ + r1 ^= r4; \ + r4 = ~r4; \ + } + +#define I2(i, r0, r1, r2, r3, r4) \ + { \ + r2 ^= r3; \ + r3 ^= r0; \ + r4 = r3; \ + r3 &= r2; \ + r3 ^= r1; \ + r1 |= r2; \ + r1 ^= r4; \ + r4 &= r3; \ + r2 ^= r3; \ + r4 &= r0; \ + r4 ^= r2; \ + r2 &= r1; \ + r2 |= r0; \ + r3 = ~r3; \ + r2 ^= r3; \ + r0 ^= r3; \ + r0 &= r1; \ + r3 ^= r4; \ + r3 ^= r0; \ + } + +#define S3(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r0; \ + r0 |= r3; \ + r3 ^= r1; \ + r1 &= r4; \ + r4 ^= r2; \ + r2 ^= r3; \ + r3 &= r0; \ + r4 |= r1; \ + r3 ^= r4; \ + r0 ^= r1; \ + r4 &= r0; \ + r1 ^= r3; \ + r4 ^= r2; \ + r1 |= r0; \ + r1 ^= r2; \ + r0 ^= r3; \ + r2 = r1; \ + r1 |= r3; \ + r1 ^= r0; \ + } + +#define I3(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r2; \ + r2 ^= r1; \ + r1 &= r2; \ + r1 ^= r0; \ + r0 &= r4; \ + r4 ^= r3; \ + r3 |= r1; \ + r3 ^= r2; \ + r0 ^= r4; \ + r2 ^= r0; \ + r0 |= r3; \ + r0 ^= r1; \ + r4 ^= r2; \ + r2 &= r3; \ + r1 |= r3; \ + r1 ^= r2; \ + r4 ^= r0; \ + r2 ^= r4; \ + } + +#define S4(i, r0, r1, r2, r3, r4) \ + { \ + r1 ^= r3; \ + r3 = ~r3; \ + r2 ^= r3; \ + r3 ^= r0; \ + r4 = r1; \ + r1 &= r3; \ + r1 ^= r2; \ + r4 ^= r3; \ + r0 ^= r4; \ + r2 &= r4; \ + r2 ^= r0; \ + r0 &= r1; \ + r3 ^= r0; \ + r4 |= r1; \ + r4 ^= r0; \ + r0 |= r3; \ + r0 ^= r2; \ + r2 &= r3; \ + r0 = ~r0; \ + r4 ^= r2; \ + } + +#define I4(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r2; \ + r2 &= r3; \ + r2 ^= r1; \ + r1 |= r3; \ + r1 &= r0; \ + r4 ^= r2; \ + r4 ^= r1; \ + r1 &= r2; \ + r0 = ~r0; \ + r3 ^= r4; \ + r1 ^= r3; \ + r3 &= r0; \ + r3 ^= r2; \ + r0 ^= r1; \ + r2 &= r0; \ + r3 ^= r0; \ + r2 ^= r4; \ + r2 |= r3; \ + r3 ^= r0; \ + r2 ^= r1; \ + } + +#define S5(i, r0, r1, r2, r3, r4) \ + { \ + r0 ^= r1; \ + r1 ^= r3; \ + r3 = ~r3; \ + r4 = r1; \ + r1 &= r0; \ + r2 ^= r3; \ + r1 ^= r2; \ + r2 |= r4; \ + r4 ^= r3; \ + r3 &= r1; \ + r3 ^= r0; \ + r4 ^= r1; \ + r4 ^= r2; \ + r2 ^= r0; \ + r0 &= r3; \ + r2 = ~r2; \ + r0 ^= r4; \ + r4 |= r3; \ + r2 ^= r4; \ + } + +#define I5(i, r0, r1, r2, r3, r4) \ + { \ + r1 = ~r1; \ + r4 = r3; \ + r2 ^= r1; \ + r3 |= r0; \ + r3 ^= r2; \ + r2 |= r1; \ + r2 &= r0; \ + r4 ^= r3; \ + r2 ^= r4; \ + r4 |= r0; \ + r4 ^= r1; \ + r1 &= r2; \ + r1 ^= r3; \ + r4 ^= r2; \ + r3 &= r4; \ + r4 ^= r1; \ + r3 ^= r0; \ + r3 ^= r4; \ + r4 = ~r4; \ + } + +#define S6(i, r0, r1, r2, r3, r4) \ + { \ + r2 = ~r2; \ + r4 = r3; \ + r3 &= r0; \ + r0 ^= r4; \ + r3 ^= r2; \ + r2 |= r4; \ + r1 ^= r3; \ + r2 ^= r0; \ + r0 |= r1; \ + r2 ^= r1; \ + r4 ^= r0; \ + r0 |= r3; \ + r0 ^= r2; \ + r4 ^= r3; \ + r4 ^= r0; \ + r3 = ~r3; \ + r2 &= r4; \ + r2 ^= r3; \ + } + +#define I6(i, r0, r1, r2, r3, r4) \ + { \ + r0 ^= r2; \ + r4 = r2; \ + r2 &= r0; \ + r4 ^= r3; \ + r2 = ~r2; \ + r3 ^= r1; \ + r2 ^= r3; \ + r4 |= r0; \ + r0 ^= r2; \ + r3 ^= r4; \ + r4 ^= r1; \ + r1 &= r3; \ + r1 ^= r0; \ + r0 ^= r3; \ + r0 |= r2; \ + r3 ^= r1; \ + r4 ^= r0; \ + } + +#define S7(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r2; \ + r2 &= r1; \ + r2 ^= r3; \ + r3 &= r1; \ + r4 ^= r2; \ + r2 ^= r1; \ + r1 ^= r0; \ + r0 |= r4; \ + r0 ^= r2; \ + r3 ^= r1; \ + r2 ^= r3; \ + r3 &= r0; \ + r3 ^= r4; \ + r4 ^= r2; \ + r2 &= r0; \ + r4 = ~r4; \ + r2 ^= r4; \ + r4 &= r0; \ + r1 ^= r3; \ + r4 ^= r1; \ + } + +#define I7(i, r0, r1, r2, r3, r4) \ + { \ + r4 = r2; \ + r2 ^= r0; \ + r0 &= r3; \ + r2 = ~r2; \ + r4 |= r3; \ + r3 ^= r1; \ + r1 |= r0; \ + r0 ^= r2; \ + r2 &= r4; \ + r1 ^= r2; \ + r2 ^= r0; \ + r0 |= r2; \ + r3 &= r4; \ + r0 ^= r3; \ + r4 ^= r1; \ + r3 ^= r4; \ + r4 |= r0; \ + r3 ^= r2; \ + r4 ^= r2; \ + } + +// key xor +#define KX(r, a, b, c, d, e) {\ + a ^= k[4 * r + 0]; \ + b ^= k[4 * r + 1]; \ + c ^= k[4 * r + 2]; \ + d ^= k[4 * r + 3];} + +#define LK(r, a, b, c, d, e) {\ + a = k[(8-r)*4 + 0]; \ + b = k[(8-r)*4 + 1]; \ + c = k[(8-r)*4 + 2]; \ + d = k[(8-r)*4 + 3];} + +#define SK(r, a, b, c, d, e) {\ + k[(8-r)*4 + 4] = a; \ + k[(8-r)*4 + 5] = b; \ + k[(8-r)*4 + 6] = c; \ + k[(8-r)*4 + 7] = d;} + +void Serpent_KeySchedule(word32 *k, unsigned int rounds, const byte *userKey, size_t keylen); + +NAMESPACE_END diff --git a/src-cryptopp/sha.cpp b/src-cryptopp/sha.cpp new file mode 100644 index 0000000..df947ad --- /dev/null +++ b/src-cryptopp/sha.cpp @@ -0,0 +1,900 @@ +// sha.cpp - modified by Wei Dai from Steve Reid's public domain sha1.c + +// Steve Reid implemented SHA-1. Wei Dai implemented SHA-2. +// Both are in the public domain. + +// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM sha.cpp" to generate MASM code + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS +#ifndef CRYPTOPP_GENERATE_X64_MASM + +#include "sha.h" +#include "misc.h" +#include "cpu.h" + +NAMESPACE_BEGIN(CryptoPP) + +// start of Steve Reid's code + +#define blk0(i) (W[i] = data[i]) +#define blk1(i) (W[i&15] = rotlFixed(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1)) + +void SHA1::InitState(HashWordType *state) +{ + state[0] = 0x67452301L; + state[1] = 0xEFCDAB89L; + state[2] = 0x98BADCFEL; + state[3] = 0x10325476L; + state[4] = 0xC3D2E1F0L; +} + +#define f1(x,y,z) (z^(x&(y^z))) +#define f2(x,y,z) (x^y^z) +#define f3(x,y,z) ((x&y)|(z&(x|y))) +#define f4(x,y,z) (x^y^z) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=f1(w,x,y)+blk0(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30); +#define R1(v,w,x,y,z,i) z+=f1(w,x,y)+blk1(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30); +#define R2(v,w,x,y,z,i) z+=f2(w,x,y)+blk1(i)+0x6ED9EBA1+rotlFixed(v,5);w=rotlFixed(w,30); +#define R3(v,w,x,y,z,i) z+=f3(w,x,y)+blk1(i)+0x8F1BBCDC+rotlFixed(v,5);w=rotlFixed(w,30); +#define R4(v,w,x,y,z,i) z+=f4(w,x,y)+blk1(i)+0xCA62C1D6+rotlFixed(v,5);w=rotlFixed(w,30); + +void SHA1::Transform(word32 *state, const word32 *data) +{ + word32 W[16]; + /* Copy context->state[] to working vars */ + word32 a = state[0]; + word32 b = state[1]; + word32 c = state[2]; + word32 d = state[3]; + word32 e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; +} + +// end of Steve Reid's code + +// ************************************************************* + +void SHA224::InitState(HashWordType *state) +{ + static const word32 s[8] = {0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4}; + memcpy(state, s, sizeof(s)); +} + +void SHA256::InitState(HashWordType *state) +{ + static const word32 s[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; + memcpy(state, s, sizeof(s)); +} + +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE +CRYPTOPP_ALIGN_DATA(16) extern const word32 SHA256_K[64] CRYPTOPP_SECTION_ALIGN16 = { +#else +extern const word32 SHA256_K[64] = { +#endif + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM + +#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_GENERATE_X64_MASM) + +#pragma warning(disable: 4731) // frame pointer register 'ebp' modified by inline assembly code + +static void CRYPTOPP_FASTCALL X86_SHA256_HashBlocks(word32 *state, const word32 *data, size_t len +#if defined(_MSC_VER) && (_MSC_VER == 1200) + , ... // VC60 workaround: prevent VC 6 from inlining this function +#endif + ) +{ +#if defined(_MSC_VER) && (_MSC_VER == 1200) + AS2(mov ecx, [state]) + AS2(mov edx, [data]) +#endif + + #define LOCALS_SIZE 8*4 + 16*4 + 4*WORD_SZ + #define H(i) [BASE+ASM_MOD(1024+7-(i),8)*4] + #define G(i) H(i+1) + #define F(i) H(i+2) + #define E(i) H(i+3) + #define D(i) H(i+4) + #define C(i) H(i+5) + #define B(i) H(i+6) + #define A(i) H(i+7) + #define Wt(i) BASE+8*4+ASM_MOD(1024+15-(i),16)*4 + #define Wt_2(i) Wt((i)-2) + #define Wt_15(i) Wt((i)-15) + #define Wt_7(i) Wt((i)-7) + #define K_END [BASE+8*4+16*4+0*WORD_SZ] + #define STATE_SAVE [BASE+8*4+16*4+1*WORD_SZ] + #define DATA_SAVE [BASE+8*4+16*4+2*WORD_SZ] + #define DATA_END [BASE+8*4+16*4+3*WORD_SZ] + #define Kt(i) WORD_REG(si)+(i)*4 +#if CRYPTOPP_BOOL_X86 + #define BASE esp+4 +#elif defined(__GNUC__) + #define BASE r8 +#else + #define BASE rsp +#endif + +#define RA0(i, edx, edi) \ + AS2( add edx, [Kt(i)] )\ + AS2( add edx, [Wt(i)] )\ + AS2( add edx, H(i) )\ + +#define RA1(i, edx, edi) + +#define RB0(i, edx, edi) + +#define RB1(i, edx, edi) \ + AS2( mov AS_REG_7d, [Wt_2(i)] )\ + AS2( mov edi, [Wt_15(i)])\ + AS2( mov ebx, AS_REG_7d )\ + AS2( shr AS_REG_7d, 10 )\ + AS2( ror ebx, 17 )\ + AS2( xor AS_REG_7d, ebx )\ + AS2( ror ebx, 2 )\ + AS2( xor ebx, AS_REG_7d )/* s1(W_t-2) */\ + AS2( add ebx, [Wt_7(i)])\ + AS2( mov AS_REG_7d, edi )\ + AS2( shr AS_REG_7d, 3 )\ + AS2( ror edi, 7 )\ + AS2( add ebx, [Wt(i)])/* s1(W_t-2) + W_t-7 + W_t-16 */\ + AS2( xor AS_REG_7d, edi )\ + AS2( add edx, [Kt(i)])\ + AS2( ror edi, 11 )\ + AS2( add edx, H(i) )\ + AS2( xor AS_REG_7d, edi )/* s0(W_t-15) */\ + AS2( add AS_REG_7d, ebx )/* W_t = s1(W_t-2) + W_t-7 + s0(W_t-15) W_t-16*/\ + AS2( mov [Wt(i)], AS_REG_7d)\ + AS2( add edx, AS_REG_7d )\ + +#define ROUND(i, r, eax, ecx, edi, edx)\ + /* in: edi = E */\ + /* unused: eax, ecx, temp: ebx, AS_REG_7d, out: edx = T1 */\ + AS2( mov edx, F(i) )\ + AS2( xor edx, G(i) )\ + AS2( and edx, edi )\ + AS2( xor edx, G(i) )/* Ch(E,F,G) = (G^(E&(F^G))) */\ + AS2( mov AS_REG_7d, edi )\ + AS2( ror edi, 6 )\ + AS2( ror AS_REG_7d, 25 )\ + RA##r(i, edx, edi )/* H + Wt + Kt + Ch(E,F,G) */\ + AS2( xor AS_REG_7d, edi )\ + AS2( ror edi, 5 )\ + AS2( xor AS_REG_7d, edi )/* S1(E) */\ + AS2( add edx, AS_REG_7d )/* T1 = S1(E) + Ch(E,F,G) + H + Wt + Kt */\ + RB##r(i, edx, edi )/* H + Wt + Kt + Ch(E,F,G) */\ + /* in: ecx = A, eax = B^C, edx = T1 */\ + /* unused: edx, temp: ebx, AS_REG_7d, out: eax = A, ecx = B^C, edx = E */\ + AS2( mov ebx, ecx )\ + AS2( xor ecx, B(i) )/* A^B */\ + AS2( and eax, ecx )\ + AS2( xor eax, B(i) )/* Maj(A,B,C) = B^((A^B)&(B^C) */\ + AS2( mov AS_REG_7d, ebx )\ + AS2( ror ebx, 2 )\ + AS2( add eax, edx )/* T1 + Maj(A,B,C) */\ + AS2( add edx, D(i) )\ + AS2( mov D(i), edx )\ + AS2( ror AS_REG_7d, 22 )\ + AS2( xor AS_REG_7d, ebx )\ + AS2( ror ebx, 11 )\ + AS2( xor AS_REG_7d, ebx )\ + AS2( add eax, AS_REG_7d )/* T1 + S0(A) + Maj(A,B,C) */\ + AS2( mov H(i), eax )\ + +#define SWAP_COPY(i) \ + AS2( mov WORD_REG(bx), [WORD_REG(dx)+i*WORD_SZ])\ + AS1( bswap WORD_REG(bx))\ + AS2( mov [Wt(i*(1+CRYPTOPP_BOOL_X64)+CRYPTOPP_BOOL_X64)], WORD_REG(bx)) + +#if defined(__GNUC__) + #if CRYPTOPP_BOOL_X64 + FixedSizeAlignedSecBlock workspace; + #endif + __asm__ __volatile__ + ( + #if CRYPTOPP_BOOL_X64 + "lea %4, %%r8;" + #endif + ".intel_syntax noprefix;" +#elif defined(CRYPTOPP_GENERATE_X64_MASM) + ALIGN 8 + X86_SHA256_HashBlocks PROC FRAME + rex_push_reg rsi + push_reg rdi + push_reg rbx + push_reg rbp + alloc_stack(LOCALS_SIZE+8) + .endprolog + mov rdi, r8 + lea rsi, [?SHA256_K@CryptoPP@@3QBIB + 48*4] +#endif + +#if CRYPTOPP_BOOL_X86 + #ifndef __GNUC__ + AS2( mov edi, [len]) + AS2( lea WORD_REG(si), [SHA256_K+48*4]) + #endif + #if !defined(_MSC_VER) || (_MSC_VER < 1400) + AS_PUSH_IF86(bx) + #endif + + AS_PUSH_IF86(bp) + AS2( mov ebx, esp) + AS2( and esp, -16) + AS2( sub WORD_REG(sp), LOCALS_SIZE) + AS_PUSH_IF86(bx) +#endif + AS2( mov STATE_SAVE, WORD_REG(cx)) + AS2( mov DATA_SAVE, WORD_REG(dx)) + AS2( lea WORD_REG(ax), [WORD_REG(di) + WORD_REG(dx)]) + AS2( mov DATA_END, WORD_REG(ax)) + AS2( mov K_END, WORD_REG(si)) + +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE +#if CRYPTOPP_BOOL_X86 + AS2( test edi, 1) + ASJ( jnz, 2, f) + AS1( dec DWORD PTR K_END) +#endif + AS2( movdqa xmm0, XMMWORD_PTR [WORD_REG(cx)+0*16]) + AS2( movdqa xmm1, XMMWORD_PTR [WORD_REG(cx)+1*16]) +#endif + +#if CRYPTOPP_BOOL_X86 +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE + ASJ( jmp, 0, f) +#endif + ASL(2) // non-SSE2 + AS2( mov esi, ecx) + AS2( lea edi, A(0)) + AS2( mov ecx, 8) + AS1( rep movsd) + AS2( mov esi, K_END) + ASJ( jmp, 3, f) +#endif + +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE + ASL(0) + AS2( movdqa E(0), xmm1) + AS2( movdqa A(0), xmm0) +#endif +#if CRYPTOPP_BOOL_X86 + ASL(3) +#endif + AS2( sub WORD_REG(si), 48*4) + SWAP_COPY(0) SWAP_COPY(1) SWAP_COPY(2) SWAP_COPY(3) + SWAP_COPY(4) SWAP_COPY(5) SWAP_COPY(6) SWAP_COPY(7) +#if CRYPTOPP_BOOL_X86 + SWAP_COPY(8) SWAP_COPY(9) SWAP_COPY(10) SWAP_COPY(11) + SWAP_COPY(12) SWAP_COPY(13) SWAP_COPY(14) SWAP_COPY(15) +#endif + AS2( mov edi, E(0)) // E + AS2( mov eax, B(0)) // B + AS2( xor eax, C(0)) // B^C + AS2( mov ecx, A(0)) // A + + ROUND(0, 0, eax, ecx, edi, edx) + ROUND(1, 0, ecx, eax, edx, edi) + ROUND(2, 0, eax, ecx, edi, edx) + ROUND(3, 0, ecx, eax, edx, edi) + ROUND(4, 0, eax, ecx, edi, edx) + ROUND(5, 0, ecx, eax, edx, edi) + ROUND(6, 0, eax, ecx, edi, edx) + ROUND(7, 0, ecx, eax, edx, edi) + ROUND(8, 0, eax, ecx, edi, edx) + ROUND(9, 0, ecx, eax, edx, edi) + ROUND(10, 0, eax, ecx, edi, edx) + ROUND(11, 0, ecx, eax, edx, edi) + ROUND(12, 0, eax, ecx, edi, edx) + ROUND(13, 0, ecx, eax, edx, edi) + ROUND(14, 0, eax, ecx, edi, edx) + ROUND(15, 0, ecx, eax, edx, edi) + + ASL(1) + AS2(add WORD_REG(si), 4*16) + ROUND(0, 1, eax, ecx, edi, edx) + ROUND(1, 1, ecx, eax, edx, edi) + ROUND(2, 1, eax, ecx, edi, edx) + ROUND(3, 1, ecx, eax, edx, edi) + ROUND(4, 1, eax, ecx, edi, edx) + ROUND(5, 1, ecx, eax, edx, edi) + ROUND(6, 1, eax, ecx, edi, edx) + ROUND(7, 1, ecx, eax, edx, edi) + ROUND(8, 1, eax, ecx, edi, edx) + ROUND(9, 1, ecx, eax, edx, edi) + ROUND(10, 1, eax, ecx, edi, edx) + ROUND(11, 1, ecx, eax, edx, edi) + ROUND(12, 1, eax, ecx, edi, edx) + ROUND(13, 1, ecx, eax, edx, edi) + ROUND(14, 1, eax, ecx, edi, edx) + ROUND(15, 1, ecx, eax, edx, edi) + AS2( cmp WORD_REG(si), K_END) + ASJ( jb, 1, b) + + AS2( mov WORD_REG(dx), DATA_SAVE) + AS2( add WORD_REG(dx), 64) + AS2( mov AS_REG_7, STATE_SAVE) + AS2( mov DATA_SAVE, WORD_REG(dx)) + +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE +#if CRYPTOPP_BOOL_X86 + AS2( test DWORD PTR K_END, 1) + ASJ( jz, 4, f) +#endif + AS2( movdqa xmm1, XMMWORD_PTR [AS_REG_7+1*16]) + AS2( movdqa xmm0, XMMWORD_PTR [AS_REG_7+0*16]) + AS2( paddd xmm1, E(0)) + AS2( paddd xmm0, A(0)) + AS2( movdqa [AS_REG_7+1*16], xmm1) + AS2( movdqa [AS_REG_7+0*16], xmm0) + AS2( cmp WORD_REG(dx), DATA_END) + ASJ( jb, 0, b) +#endif + +#if CRYPTOPP_BOOL_X86 +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE + ASJ( jmp, 5, f) + ASL(4) // non-SSE2 +#endif + AS2( add [AS_REG_7+0*4], ecx) // A + AS2( add [AS_REG_7+4*4], edi) // E + AS2( mov eax, B(0)) + AS2( mov ebx, C(0)) + AS2( mov ecx, D(0)) + AS2( add [AS_REG_7+1*4], eax) + AS2( add [AS_REG_7+2*4], ebx) + AS2( add [AS_REG_7+3*4], ecx) + AS2( mov eax, F(0)) + AS2( mov ebx, G(0)) + AS2( mov ecx, H(0)) + AS2( add [AS_REG_7+5*4], eax) + AS2( add [AS_REG_7+6*4], ebx) + AS2( add [AS_REG_7+7*4], ecx) + AS2( mov ecx, AS_REG_7d) + AS2( cmp WORD_REG(dx), DATA_END) + ASJ( jb, 2, b) +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE + ASL(5) +#endif +#endif + + AS_POP_IF86(sp) + AS_POP_IF86(bp) + #if !defined(_MSC_VER) || (_MSC_VER < 1400) + AS_POP_IF86(bx) + #endif + +#ifdef CRYPTOPP_GENERATE_X64_MASM + add rsp, LOCALS_SIZE+8 + pop rbp + pop rbx + pop rdi + pop rsi + ret + X86_SHA256_HashBlocks ENDP +#endif + +#ifdef __GNUC__ + ".att_syntax prefix;" + : + : "c" (state), "d" (data), "S" (SHA256_K+48), "D" (len) + #if CRYPTOPP_BOOL_X64 + , "m" (workspace[0]) + #endif + : "memory", "cc", "%eax" + #if CRYPTOPP_BOOL_X64 + , "%rbx", "%r8", "%r10" + #endif + ); +#endif +} + +#endif // #if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_GENERATE_X64_MASM) + +#ifndef CRYPTOPP_GENERATE_X64_MASM + +#ifdef CRYPTOPP_X64_MASM_AVAILABLE +extern "C" { +void CRYPTOPP_FASTCALL X86_SHA256_HashBlocks(word32 *state, const word32 *data, size_t len); +} +#endif + +#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE) + +size_t SHA256::HashMultipleBlocks(const word32 *input, size_t length) +{ + X86_SHA256_HashBlocks(m_state, input, (length&(size_t(0)-BLOCKSIZE)) - !HasSSE2()); + return length % BLOCKSIZE; +} + +size_t SHA224::HashMultipleBlocks(const word32 *input, size_t length) +{ + X86_SHA256_HashBlocks(m_state, input, (length&(size_t(0)-BLOCKSIZE)) - !HasSSE2()); + return length % BLOCKSIZE; +} + +#endif + +#define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15])) + +#define Ch(x,y,z) (z^(x&(y^z))) +#define Maj(x,y,z) (y^((x^y)&(y^z))) + +#define a(i) T[(0-i)&7] +#define b(i) T[(1-i)&7] +#define c(i) T[(2-i)&7] +#define d(i) T[(3-i)&7] +#define e(i) T[(4-i)&7] +#define f(i) T[(5-i)&7] +#define g(i) T[(6-i)&7] +#define h(i) T[(7-i)&7] + +#define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA256_K[i+j]+(j?blk2(i):blk0(i));\ + d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)) + +// for SHA256 +#define S0(x) (rotrFixed(x,2)^rotrFixed(x,13)^rotrFixed(x,22)) +#define S1(x) (rotrFixed(x,6)^rotrFixed(x,11)^rotrFixed(x,25)) +#define s0(x) (rotrFixed(x,7)^rotrFixed(x,18)^(x>>3)) +#define s1(x) (rotrFixed(x,17)^rotrFixed(x,19)^(x>>10)) + +void SHA256::Transform(word32 *state, const word32 *data) +{ + word32 W[16]; +#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE) + // this byte reverse is a waste of time, but this function is only called by MDC + ByteReverse(W, data, BLOCKSIZE); + X86_SHA256_HashBlocks(state, W, BLOCKSIZE - !HasSSE2()); +#else + word32 T[8]; + /* Copy context->state[] to working vars */ + memcpy(T, state, sizeof(T)); + /* 64 operations, partially loop unrolled */ + for (unsigned int j=0; j<64; j+=16) + { + R( 0); R( 1); R( 2); R( 3); + R( 4); R( 5); R( 6); R( 7); + R( 8); R( 9); R(10); R(11); + R(12); R(13); R(14); R(15); + } + /* Add the working vars back into context.state[] */ + state[0] += a(0); + state[1] += b(0); + state[2] += c(0); + state[3] += d(0); + state[4] += e(0); + state[5] += f(0); + state[6] += g(0); + state[7] += h(0); +#endif +} + +/* +// smaller but slower +void SHA256::Transform(word32 *state, const word32 *data) +{ + word32 T[20]; + word32 W[32]; + unsigned int i = 0, j = 0; + word32 *t = T+8; + + memcpy(t, state, 8*4); + word32 e = t[4], a = t[0]; + + do + { + word32 w = data[j]; + W[j] = w; + w += SHA256_K[j]; + w += t[7]; + w += S1(e); + w += Ch(e, t[5], t[6]); + e = t[3] + w; + t[3] = t[3+8] = e; + w += S0(t[0]); + a = w + Maj(a, t[1], t[2]); + t[-1] = t[7] = a; + --t; + ++j; + if (j%8 == 0) + t += 8; + } while (j<16); + + do + { + i = j&0xf; + word32 w = s1(W[i+16-2]) + s0(W[i+16-15]) + W[i] + W[i+16-7]; + W[i+16] = W[i] = w; + w += SHA256_K[j]; + w += t[7]; + w += S1(e); + w += Ch(e, t[5], t[6]); + e = t[3] + w; + t[3] = t[3+8] = e; + w += S0(t[0]); + a = w + Maj(a, t[1], t[2]); + t[-1] = t[7] = a; + + w = s1(W[(i+1)+16-2]) + s0(W[(i+1)+16-15]) + W[(i+1)] + W[(i+1)+16-7]; + W[(i+1)+16] = W[(i+1)] = w; + w += SHA256_K[j+1]; + w += (t-1)[7]; + w += S1(e); + w += Ch(e, (t-1)[5], (t-1)[6]); + e = (t-1)[3] + w; + (t-1)[3] = (t-1)[3+8] = e; + w += S0((t-1)[0]); + a = w + Maj(a, (t-1)[1], (t-1)[2]); + (t-1)[-1] = (t-1)[7] = a; + + t-=2; + j+=2; + if (j%8 == 0) + t += 8; + } while (j<64); + + state[0] += a; + state[1] += t[1]; + state[2] += t[2]; + state[3] += t[3]; + state[4] += e; + state[5] += t[5]; + state[6] += t[6]; + state[7] += t[7]; +} +*/ + +#undef S0 +#undef S1 +#undef s0 +#undef s1 +#undef R + +// ************************************************************* + +void SHA384::InitState(HashWordType *state) +{ + static const word64 s[8] = { + W64LIT(0xcbbb9d5dc1059ed8), W64LIT(0x629a292a367cd507), + W64LIT(0x9159015a3070dd17), W64LIT(0x152fecd8f70e5939), + W64LIT(0x67332667ffc00b31), W64LIT(0x8eb44a8768581511), + W64LIT(0xdb0c2e0d64f98fa7), W64LIT(0x47b5481dbefa4fa4)}; + memcpy(state, s, sizeof(s)); +} + +void SHA512::InitState(HashWordType *state) +{ + static const word64 s[8] = { + W64LIT(0x6a09e667f3bcc908), W64LIT(0xbb67ae8584caa73b), + W64LIT(0x3c6ef372fe94f82b), W64LIT(0xa54ff53a5f1d36f1), + W64LIT(0x510e527fade682d1), W64LIT(0x9b05688c2b3e6c1f), + W64LIT(0x1f83d9abfb41bd6b), W64LIT(0x5be0cd19137e2179)}; + memcpy(state, s, sizeof(s)); +} + +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86 +CRYPTOPP_ALIGN_DATA(16) static const word64 SHA512_K[80] CRYPTOPP_SECTION_ALIGN16 = { +#else +static const word64 SHA512_K[80] = { +#endif + W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd), + W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc), + W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019), + W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118), + W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe), + W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2), + W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1), + W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694), + W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3), + W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65), + W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483), + W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5), + W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210), + W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4), + W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725), + W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70), + W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926), + W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df), + W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8), + W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b), + W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001), + W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30), + W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910), + W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8), + W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53), + W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8), + W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb), + W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3), + W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60), + W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec), + W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9), + W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b), + W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207), + W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178), + W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6), + W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b), + W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493), + W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c), + W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a), + W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817) +}; + +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86 +// put assembly version in separate function, otherwise MSVC 2005 SP1 doesn't generate correct code for the non-assembly version +CRYPTOPP_NAKED static void CRYPTOPP_FASTCALL SHA512_SSE2_Transform(word64 *state, const word64 *data) +{ +#ifdef __GNUC__ + __asm__ __volatile__ + ( + ".intel_syntax noprefix;" + AS1( push ebx) + AS2( mov ebx, eax) +#else + AS1( push ebx) + AS1( push esi) + AS1( push edi) + AS2( lea ebx, SHA512_K) +#endif + + AS2( mov eax, esp) + AS2( and esp, 0xfffffff0) + AS2( sub esp, 27*16) // 17*16 for expanded data, 20*8 for state + AS1( push eax) + AS2( xor eax, eax) + AS2( lea edi, [esp+4+8*8]) // start at middle of state buffer. will decrement pointer each round to avoid copying + AS2( lea esi, [esp+4+20*8+8]) // 16-byte alignment, then add 8 + + AS2( movdqa xmm0, [ecx+0*16]) + AS2( movdq2q mm4, xmm0) + AS2( movdqa [edi+0*16], xmm0) + AS2( movdqa xmm0, [ecx+1*16]) + AS2( movdqa [edi+1*16], xmm0) + AS2( movdqa xmm0, [ecx+2*16]) + AS2( movdq2q mm5, xmm0) + AS2( movdqa [edi+2*16], xmm0) + AS2( movdqa xmm0, [ecx+3*16]) + AS2( movdqa [edi+3*16], xmm0) + ASJ( jmp, 0, f) + +#define SSE2_S0_S1(r, a, b, c) \ + AS2( movq mm6, r)\ + AS2( psrlq r, a)\ + AS2( movq mm7, r)\ + AS2( psllq mm6, 64-c)\ + AS2( pxor mm7, mm6)\ + AS2( psrlq r, b-a)\ + AS2( pxor mm7, r)\ + AS2( psllq mm6, c-b)\ + AS2( pxor mm7, mm6)\ + AS2( psrlq r, c-b)\ + AS2( pxor r, mm7)\ + AS2( psllq mm6, b-a)\ + AS2( pxor r, mm6) + +#define SSE2_s0(r, a, b, c) \ + AS2( movdqa xmm6, r)\ + AS2( psrlq r, a)\ + AS2( movdqa xmm7, r)\ + AS2( psllq xmm6, 64-c)\ + AS2( pxor xmm7, xmm6)\ + AS2( psrlq r, b-a)\ + AS2( pxor xmm7, r)\ + AS2( psrlq r, c-b)\ + AS2( pxor r, xmm7)\ + AS2( psllq xmm6, c-a)\ + AS2( pxor r, xmm6) + +#define SSE2_s1(r, a, b, c) \ + AS2( movdqa xmm6, r)\ + AS2( psrlq r, a)\ + AS2( movdqa xmm7, r)\ + AS2( psllq xmm6, 64-c)\ + AS2( pxor xmm7, xmm6)\ + AS2( psrlq r, b-a)\ + AS2( pxor xmm7, r)\ + AS2( psllq xmm6, c-b)\ + AS2( pxor xmm7, xmm6)\ + AS2( psrlq r, c-b)\ + AS2( pxor r, xmm7) + + ASL(SHA512_Round) + // k + w is in mm0, a is in mm4, e is in mm5 + AS2( paddq mm0, [edi+7*8]) // h + AS2( movq mm2, [edi+5*8]) // f + AS2( movq mm3, [edi+6*8]) // g + AS2( pxor mm2, mm3) + AS2( pand mm2, mm5) + SSE2_S0_S1(mm5,14,18,41) + AS2( pxor mm2, mm3) + AS2( paddq mm0, mm2) // h += Ch(e,f,g) + AS2( paddq mm5, mm0) // h += S1(e) + AS2( movq mm2, [edi+1*8]) // b + AS2( movq mm1, mm2) + AS2( por mm2, mm4) + AS2( pand mm2, [edi+2*8]) // c + AS2( pand mm1, mm4) + AS2( por mm1, mm2) + AS2( paddq mm1, mm5) // temp = h + Maj(a,b,c) + AS2( paddq mm5, [edi+3*8]) // e = d + h + AS2( movq [edi+3*8], mm5) + AS2( movq [edi+11*8], mm5) + SSE2_S0_S1(mm4,28,34,39) // S0(a) + AS2( paddq mm4, mm1) // a = temp + S0(a) + AS2( movq [edi-8], mm4) + AS2( movq [edi+7*8], mm4) + AS1( ret) + + // first 16 rounds + ASL(0) + AS2( movq mm0, [edx+eax*8]) + AS2( movq [esi+eax*8], mm0) + AS2( movq [esi+eax*8+16*8], mm0) + AS2( paddq mm0, [ebx+eax*8]) + ASC( call, SHA512_Round) + AS1( inc eax) + AS2( sub edi, 8) + AS2( test eax, 7) + ASJ( jnz, 0, b) + AS2( add edi, 8*8) + AS2( cmp eax, 16) + ASJ( jne, 0, b) + + // rest of the rounds + AS2( movdqu xmm0, [esi+(16-2)*8]) + ASL(1) + // data expansion, W[i-2] already in xmm0 + AS2( movdqu xmm3, [esi]) + AS2( paddq xmm3, [esi+(16-7)*8]) + AS2( movdqa xmm2, [esi+(16-15)*8]) + SSE2_s1(xmm0, 6, 19, 61) + AS2( paddq xmm0, xmm3) + SSE2_s0(xmm2, 1, 7, 8) + AS2( paddq xmm0, xmm2) + AS2( movdq2q mm0, xmm0) + AS2( movhlps xmm1, xmm0) + AS2( paddq mm0, [ebx+eax*8]) + AS2( movlps [esi], xmm0) + AS2( movlps [esi+8], xmm1) + AS2( movlps [esi+8*16], xmm0) + AS2( movlps [esi+8*17], xmm1) + // 2 rounds + ASC( call, SHA512_Round) + AS2( sub edi, 8) + AS2( movdq2q mm0, xmm1) + AS2( paddq mm0, [ebx+eax*8+8]) + ASC( call, SHA512_Round) + // update indices and loop + AS2( add esi, 16) + AS2( add eax, 2) + AS2( sub edi, 8) + AS2( test eax, 7) + ASJ( jnz, 1, b) + // do housekeeping every 8 rounds + AS2( mov esi, 0xf) + AS2( and esi, eax) + AS2( lea esi, [esp+4+20*8+8+esi*8]) + AS2( add edi, 8*8) + AS2( cmp eax, 80) + ASJ( jne, 1, b) + +#define SSE2_CombineState(i) \ + AS2( movdqa xmm0, [edi+i*16])\ + AS2( paddq xmm0, [ecx+i*16])\ + AS2( movdqa [ecx+i*16], xmm0) + + SSE2_CombineState(0) + SSE2_CombineState(1) + SSE2_CombineState(2) + SSE2_CombineState(3) + + AS1( pop esp) + AS1( emms) + +#if defined(__GNUC__) + AS1( pop ebx) + ".att_syntax prefix;" + : + : "a" (SHA512_K), "c" (state), "d" (data) + : "%esi", "%edi", "memory", "cc" + ); +#else + AS1( pop edi) + AS1( pop esi) + AS1( pop ebx) + AS1( ret) +#endif +} +#endif // #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE + +void SHA512::Transform(word64 *state, const word64 *data) +{ +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86 + if (HasSSE2()) + { + SHA512_SSE2_Transform(state, data); + return; + } +#endif + +#define S0(x) (rotrFixed(x,28)^rotrFixed(x,34)^rotrFixed(x,39)) +#define S1(x) (rotrFixed(x,14)^rotrFixed(x,18)^rotrFixed(x,41)) +#define s0(x) (rotrFixed(x,1)^rotrFixed(x,8)^(x>>7)) +#define s1(x) (rotrFixed(x,19)^rotrFixed(x,61)^(x>>6)) + +#define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA512_K[i+j]+(j?blk2(i):blk0(i));\ + d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)) + + word64 W[16]; + word64 T[8]; + /* Copy context->state[] to working vars */ + memcpy(T, state, sizeof(T)); + /* 80 operations, partially loop unrolled */ + for (unsigned int j=0; j<80; j+=16) + { + R( 0); R( 1); R( 2); R( 3); + R( 4); R( 5); R( 6); R( 7); + R( 8); R( 9); R(10); R(11); + R(12); R(13); R(14); R(15); + } + /* Add the working vars back into context.state[] */ + state[0] += a(0); + state[1] += b(0); + state[2] += c(0); + state[3] += d(0); + state[4] += e(0); + state[5] += f(0); + state[6] += g(0); + state[7] += h(0); +} + +NAMESPACE_END + +#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM +#endif // #ifndef CRYPTOPP_IMPORTS diff --git a/src-cryptopp/sha.h b/src-cryptopp/sha.h new file mode 100644 index 0000000..679081e --- /dev/null +++ b/src-cryptopp/sha.h @@ -0,0 +1,63 @@ +#ifndef CRYPTOPP_SHA_H +#define CRYPTOPP_SHA_H + +#include "iterhash.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// SHA-1 +class CRYPTOPP_DLL SHA1 : public IteratedHashWithStaticTransform +{ +public: + static void CRYPTOPP_API InitState(HashWordType *state); + static void CRYPTOPP_API Transform(word32 *digest, const word32 *data); + static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-1";} +}; + +typedef SHA1 SHA; // for backwards compatibility + +//! implements the SHA-256 standard +class CRYPTOPP_DLL SHA256 : public IteratedHashWithStaticTransform +{ +public: +#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE) + size_t HashMultipleBlocks(const word32 *input, size_t length); +#endif + static void CRYPTOPP_API InitState(HashWordType *state); + static void CRYPTOPP_API Transform(word32 *digest, const word32 *data); + static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-256";} +}; + +//! implements the SHA-224 standard +class CRYPTOPP_DLL SHA224 : public IteratedHashWithStaticTransform +{ +public: +#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE) + size_t HashMultipleBlocks(const word32 *input, size_t length); +#endif + static void CRYPTOPP_API InitState(HashWordType *state); + static void CRYPTOPP_API Transform(word32 *digest, const word32 *data) {SHA256::Transform(digest, data);} + static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-224";} +}; + +//! implements the SHA-512 standard +class CRYPTOPP_DLL SHA512 : public IteratedHashWithStaticTransform +{ +public: + static void CRYPTOPP_API InitState(HashWordType *state); + static void CRYPTOPP_API Transform(word64 *digest, const word64 *data); + static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-512";} +}; + +//! implements the SHA-384 standard +class CRYPTOPP_DLL SHA384 : public IteratedHashWithStaticTransform +{ +public: + static void CRYPTOPP_API InitState(HashWordType *state); + static void CRYPTOPP_API Transform(word64 *digest, const word64 *data) {SHA512::Transform(digest, data);} + static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-384";} +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/simple.h b/src-cryptopp/simple.h new file mode 100644 index 0000000..35fd65a --- /dev/null +++ b/src-cryptopp/simple.h @@ -0,0 +1,209 @@ +// simple.h - written and placed in the public domain by Wei Dai +/*! \file + Simple non-interface classes derived from classes in cryptlib.h. +*/ + +#ifndef CRYPTOPP_SIMPLE_H +#define CRYPTOPP_SIMPLE_H + +#include "cryptlib.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! _ +template +class CRYPTOPP_NO_VTABLE ClonableImpl : public BASE +{ +public: + Clonable * Clone() const {return new DERIVED(*static_cast(this));} +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE AlgorithmImpl : public BASE +{ +public: + static std::string CRYPTOPP_API StaticAlgorithmName() {return ALGORITHM_INFO::StaticAlgorithmName();} + std::string AlgorithmName() const {return ALGORITHM_INFO::StaticAlgorithmName();} +}; + +//! _ +class CRYPTOPP_DLL InvalidKeyLength : public InvalidArgument +{ +public: + explicit InvalidKeyLength(const std::string &algorithm, size_t length) : InvalidArgument(algorithm + ": " + IntToString(length) + " is not a valid key length") {} +}; + +//! _ +class CRYPTOPP_DLL InvalidRounds : public InvalidArgument +{ +public: + explicit InvalidRounds(const std::string &algorithm, unsigned int rounds) : InvalidArgument(algorithm + ": " + IntToString(rounds) + " is not a valid number of rounds") {} +}; + +// ***************************** + +//! _ +template +class CRYPTOPP_NO_VTABLE Bufferless : public T +{ +public: + bool IsolatedFlush(bool hardFlush, bool blocking) {return false;} +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE Unflushable : public T +{ +public: + bool Flush(bool completeFlush, int propagation=-1, bool blocking=true) + {return ChannelFlush(DEFAULT_CHANNEL, completeFlush, propagation, blocking);} + bool IsolatedFlush(bool hardFlush, bool blocking) + {assert(false); return false;} + bool ChannelFlush(const std::string &channel, bool hardFlush, int propagation=-1, bool blocking=true) + { + if (hardFlush && !InputBufferIsEmpty()) + throw CannotFlush("Unflushable: this object has buffered input that cannot be flushed"); + else + { + BufferedTransformation *attached = this->AttachedTransformation(); + return attached && propagation ? attached->ChannelFlush(channel, hardFlush, propagation-1, blocking) : false; + } + } + +protected: + virtual bool InputBufferIsEmpty() const {return false;} +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE InputRejecting : public T +{ +public: + struct InputRejected : public NotImplemented + {InputRejected() : NotImplemented("BufferedTransformation: this object doesn't allow input") {}}; + + // shouldn't be calling these functions on this class + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking) + {throw InputRejected();} + bool IsolatedFlush(bool, bool) {return false;} + bool IsolatedMessageSeriesEnd(bool) {throw InputRejected();} + + size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) + {throw InputRejected();} + bool ChannelMessageSeriesEnd(const std::string &, int, bool) {throw InputRejected();} +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE CustomFlushPropagation : public T +{ +public: + virtual bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) =0; + +private: + bool IsolatedFlush(bool hardFlush, bool blocking) {assert(false); return false;} +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE CustomSignalPropagation : public CustomFlushPropagation +{ +public: + virtual void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1) =0; + +private: + void IsolatedInitialize(const NameValuePairs ¶meters) {assert(false);} +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE Multichannel : public CustomFlushPropagation +{ +public: + bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) + {return this->ChannelFlush(DEFAULT_CHANNEL, hardFlush, propagation, blocking);} + bool MessageSeriesEnd(int propagation=-1, bool blocking=true) + {return this->ChannelMessageSeriesEnd(DEFAULT_CHANNEL, propagation, blocking);} + byte * CreatePutSpace(size_t &size) + {return this->ChannelCreatePutSpace(DEFAULT_CHANNEL, size);} + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking) + {return this->ChannelPut2(DEFAULT_CHANNEL, begin, length, messageEnd, blocking);} + size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking) + {return this->ChannelPutModifiable2(DEFAULT_CHANNEL, inString, length, messageEnd, blocking);} + +// void ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1) +// {PropagateMessageSeriesEnd(propagation, channel);} + byte * ChannelCreatePutSpace(const std::string &channel, size_t &size) + {size = 0; return NULL;} + bool ChannelPutModifiable(const std::string &channel, byte *inString, size_t length) + {this->ChannelPut(channel, inString, length); return false;} + + virtual size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking) =0; + size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking) + {return ChannelPut2(channel, begin, length, messageEnd, blocking);} + + virtual bool ChannelFlush(const std::string &channel, bool hardFlush, int propagation=-1, bool blocking=true) =0; +}; + +//! _ +template +class CRYPTOPP_NO_VTABLE AutoSignaling : public T +{ +public: + AutoSignaling(int propagation=-1) : m_autoSignalPropagation(propagation) {} + + void SetAutoSignalPropagation(int propagation) + {m_autoSignalPropagation = propagation;} + int GetAutoSignalPropagation() const + {return m_autoSignalPropagation;} + +private: + int m_autoSignalPropagation; +}; + +//! A BufferedTransformation that only contains pre-existing data as "output" +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Store : public AutoSignaling > +{ +public: + Store() : m_messageEnd(false) {} + + void IsolatedInitialize(const NameValuePairs ¶meters) + { + m_messageEnd = false; + StoreInitialize(parameters); + } + + unsigned int NumberOfMessages() const {return m_messageEnd ? 0 : 1;} + bool GetNextMessage(); + unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL) const; + +protected: + virtual void StoreInitialize(const NameValuePairs ¶meters) =0; + + bool m_messageEnd; +}; + +//! A BufferedTransformation that doesn't produce any retrievable output +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Sink : public BufferedTransformation +{ +public: + size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) + {transferBytes = 0; return 0;} + size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const + {return 0;} +}; + +class CRYPTOPP_DLL BitBucket : public Bufferless +{ +public: + std::string AlgorithmName() const {return "BitBucket";} + void IsolatedInitialize(const NameValuePairs ¶meters) {} + size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking) + {return 0;} +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/skipjack.h b/src-cryptopp/skipjack.h new file mode 100644 index 0000000..2cf10d2 --- /dev/null +++ b/src-cryptopp/skipjack.h @@ -0,0 +1,61 @@ +#ifndef CRYPTOPP_SKIPJACK_H +#define CRYPTOPP_SKIPJACK_H + +/** \file +*/ + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! _ +struct SKIPJACK_Info : public FixedBlockSize<8>, public FixedKeyLength<10> +{ + CRYPTOPP_DLL static const char * CRYPTOPP_API StaticAlgorithmName() {return "SKIPJACK";} +}; + +/// SKIPJACK +class SKIPJACK : public SKIPJACK_Info, public BlockCipherDocumentation +{ + class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Base : public BlockCipherImpl + { + public: + void UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs ¶ms); + unsigned int OptimalDataAlignment() const {return GetAlignmentOf();} + + protected: + static const byte fTable[256]; + + FixedSizeSecBlock tab; + }; + + class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + private: + static const byte Se[256]; + static const word32 Te[4][256]; + }; + + class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + private: + static const byte Sd[256]; + static const word32 Td[4][256]; + }; + +public: + typedef BlockCipherFinal Encryption; + typedef BlockCipherFinal Decryption; +}; + +typedef SKIPJACK::Encryption SKIPJACKEncryption; +typedef SKIPJACK::Decryption SKIPJACKDecryption; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/smartptr.h b/src-cryptopp/smartptr.h new file mode 100644 index 0000000..a0a727e --- /dev/null +++ b/src-cryptopp/smartptr.h @@ -0,0 +1,223 @@ +#ifndef CRYPTOPP_SMARTPTR_H +#define CRYPTOPP_SMARTPTR_H + +#include "config.h" +#include + +NAMESPACE_BEGIN(CryptoPP) + +template class simple_ptr +{ +public: + simple_ptr(T *p = NULL) : m_p(p) {} + ~simple_ptr() {delete m_p; m_p = NULL;} // set m_p to NULL so double destruction (which might occur in Singleton) will be harmless + T *m_p; +}; + +template class member_ptr +{ +public: + explicit member_ptr(T *p = NULL) : m_p(p) {} + + ~member_ptr(); + + const T& operator*() const { return *m_p; } + T& operator*() { return *m_p; } + + const T* operator->() const { return m_p; } + T* operator->() { return m_p; } + + const T* get() const { return m_p; } + T* get() { return m_p; } + + T* release() + { + T *old_p = m_p; + m_p = 0; + return old_p; + } + + void reset(T *p = 0); + +protected: + member_ptr(const member_ptr& rhs); // copy not allowed + void operator=(const member_ptr& rhs); // assignment not allowed + + T *m_p; +}; + +template member_ptr::~member_ptr() {delete m_p;} +template void member_ptr::reset(T *p) {delete m_p; m_p = p;} + +// ******************************************************** + +template class value_ptr : public member_ptr +{ +public: + value_ptr(const T &obj) : member_ptr(new T(obj)) {} + value_ptr(T *p = NULL) : member_ptr(p) {} + value_ptr(const value_ptr& rhs) + : member_ptr(rhs.m_p ? new T(*rhs.m_p) : NULL) {} + + value_ptr& operator=(const value_ptr& rhs); + bool operator==(const value_ptr& rhs) + { + return (!this->m_p && !rhs.m_p) || (this->m_p && rhs.m_p && *this->m_p == *rhs.m_p); + } +}; + +template value_ptr& value_ptr::operator=(const value_ptr& rhs) +{ + T *old_p = this->m_p; + this->m_p = rhs.m_p ? new T(*rhs.m_p) : NULL; + delete old_p; + return *this; +} + +// ******************************************************** + +template class clonable_ptr : public member_ptr +{ +public: + clonable_ptr(const T &obj) : member_ptr(obj.Clone()) {} + clonable_ptr(T *p = NULL) : member_ptr(p) {} + clonable_ptr(const clonable_ptr& rhs) + : member_ptr(rhs.m_p ? rhs.m_p->Clone() : NULL) {} + + clonable_ptr& operator=(const clonable_ptr& rhs); +}; + +template clonable_ptr& clonable_ptr::operator=(const clonable_ptr& rhs) +{ + T *old_p = this->m_p; + this->m_p = rhs.m_p ? rhs.m_p->Clone() : NULL; + delete old_p; + return *this; +} + +// ******************************************************** + +template class counted_ptr +{ +public: + explicit counted_ptr(T *p = 0); + counted_ptr(const T &r) : m_p(0) {attach(r);} + counted_ptr(const counted_ptr& rhs); + + ~counted_ptr(); + + const T& operator*() const { return *m_p; } + T& operator*() { return *m_p; } + + const T* operator->() const { return m_p; } + T* operator->() { return get(); } + + const T* get() const { return m_p; } + T* get(); + + void attach(const T &p); + + counted_ptr & operator=(const counted_ptr& rhs); + +private: + T *m_p; +}; + +template counted_ptr::counted_ptr(T *p) + : m_p(p) +{ + if (m_p) + m_p->m_referenceCount = 1; +} + +template counted_ptr::counted_ptr(const counted_ptr& rhs) + : m_p(rhs.m_p) +{ + if (m_p) + m_p->m_referenceCount++; +} + +template counted_ptr::~counted_ptr() +{ + if (m_p && --m_p->m_referenceCount == 0) + delete m_p; +} + +template void counted_ptr::attach(const T &r) +{ + if (m_p && --m_p->m_referenceCount == 0) + delete m_p; + if (r.m_referenceCount == 0) + { + m_p = r.clone(); + m_p->m_referenceCount = 1; + } + else + { + m_p = const_cast(&r); + m_p->m_referenceCount++; + } +} + +template T* counted_ptr::get() +{ + if (m_p && m_p->m_referenceCount > 1) + { + T *temp = m_p->clone(); + m_p->m_referenceCount--; + m_p = temp; + m_p->m_referenceCount = 1; + } + return m_p; +} + +template counted_ptr & counted_ptr::operator=(const counted_ptr& rhs) +{ + if (m_p != rhs.m_p) + { + if (m_p && --m_p->m_referenceCount == 0) + delete m_p; + m_p = rhs.m_p; + if (m_p) + m_p->m_referenceCount++; + } + return *this; +} + +// ******************************************************** + +template class vector_member_ptrs +{ +public: + vector_member_ptrs(size_t size=0) + : m_size(size), m_ptr(new member_ptr[size]) {} + ~vector_member_ptrs() + {delete [] this->m_ptr;} + + member_ptr& operator[](size_t index) + {assert(indexm_size); return this->m_ptr[index];} + const member_ptr& operator[](size_t index) const + {assert(indexm_size); return this->m_ptr[index];} + + size_t size() const {return this->m_size;} + void resize(size_t newSize) + { + member_ptr *newPtr = new member_ptr[newSize]; + for (size_t i=0; im_size && im_ptr[i].release()); + delete [] this->m_ptr; + this->m_size = newSize; + this->m_ptr = newPtr; + } + +private: + vector_member_ptrs(const vector_member_ptrs &c); // copy not allowed + void operator=(const vector_member_ptrs &x); // assignment not allowed + + size_t m_size; + member_ptr *m_ptr; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/sosemanuk.cpp b/src-cryptopp/sosemanuk.cpp new file mode 100644 index 0000000..0863675 --- /dev/null +++ b/src-cryptopp/sosemanuk.cpp @@ -0,0 +1,711 @@ +// sosemanuk.cpp - written and placed in the public domain by Wei Dai + +// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM sosemanuk.cpp" to generate MASM code + +#include "pch.h" + +#ifndef CRYPTOPP_GENERATE_X64_MASM + +#include "sosemanuk.h" +#include "misc.h" +#include "cpu.h" + +#include "serpentp.h" + +NAMESPACE_BEGIN(CryptoPP) + +void SosemanukPolicy::CipherSetKey(const NameValuePairs ¶ms, const byte *userKey, size_t keylen) +{ + Serpent_KeySchedule(m_key, 24, userKey, keylen); +} + +void SosemanukPolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) +{ + assert(length==16); + + word32 a, b, c, d, e; + + typedef BlockGetAndPut Block; + Block::Get(iv)(a)(b)(c)(d); + + const word32 *k = m_key; + unsigned int i=1; + + do + { + beforeS0(KX); beforeS0(S0); afterS0(LT); + afterS0(KX); afterS0(S1); afterS1(LT); + if (i == 3) // after 18th round + { + m_state[4] = b; + m_state[5] = e; + m_state[10] = c; + m_state[11] = a; + } + afterS1(KX); afterS1(S2); afterS2(LT); + afterS2(KX); afterS2(S3); afterS3(LT); + if (i == 2) // after 12th round + { + m_state[6] = c; + m_state[7] = d; + m_state[8] = b; + m_state[9] = e; + } + afterS3(KX); afterS3(S4); afterS4(LT); + afterS4(KX); afterS4(S5); afterS5(LT); + afterS5(KX); afterS5(S6); afterS6(LT); + afterS6(KX); afterS6(S7); afterS7(LT); + + if (i == 3) + break; + + ++i; + c = b; + b = e; + e = d; + d = a; + a = e; + k += 32; + } + while (true); + + afterS7(KX); + + m_state[0] = a; + m_state[1] = b; + m_state[2] = e; + m_state[3] = d; + +#define XMUX(c, x, y) (x ^ (y & (0 - (c & 1)))) + m_state[11] += XMUX(m_state[10], m_state[1], m_state[8]); + m_state[10] = rotlFixed(m_state[10] * 0x54655307, 7); +} + +extern "C" { +word32 s_sosemanukMulTables[512] = { +#if CRYPTOPP_BOOL_X86 | CRYPTOPP_BOOL_X64 + 0x00000000, 0xE19FCF12, 0x6B973724, 0x8A08F836, + 0xD6876E48, 0x3718A15A, 0xBD10596C, 0x5C8F967E, + 0x05A7DC90, 0xE4381382, 0x6E30EBB4, 0x8FAF24A6, + 0xD320B2D8, 0x32BF7DCA, 0xB8B785FC, 0x59284AEE, + 0x0AE71189, 0xEB78DE9B, 0x617026AD, 0x80EFE9BF, + 0xDC607FC1, 0x3DFFB0D3, 0xB7F748E5, 0x566887F7, + 0x0F40CD19, 0xEEDF020B, 0x64D7FA3D, 0x8548352F, + 0xD9C7A351, 0x38586C43, 0xB2509475, 0x53CF5B67, + 0x146722BB, 0xF5F8EDA9, 0x7FF0159F, 0x9E6FDA8D, + 0xC2E04CF3, 0x237F83E1, 0xA9777BD7, 0x48E8B4C5, + 0x11C0FE2B, 0xF05F3139, 0x7A57C90F, 0x9BC8061D, + 0xC7479063, 0x26D85F71, 0xACD0A747, 0x4D4F6855, + 0x1E803332, 0xFF1FFC20, 0x75170416, 0x9488CB04, + 0xC8075D7A, 0x29989268, 0xA3906A5E, 0x420FA54C, + 0x1B27EFA2, 0xFAB820B0, 0x70B0D886, 0x912F1794, + 0xCDA081EA, 0x2C3F4EF8, 0xA637B6CE, 0x47A879DC, + 0x28CE44DF, 0xC9518BCD, 0x435973FB, 0xA2C6BCE9, + 0xFE492A97, 0x1FD6E585, 0x95DE1DB3, 0x7441D2A1, + 0x2D69984F, 0xCCF6575D, 0x46FEAF6B, 0xA7616079, + 0xFBEEF607, 0x1A713915, 0x9079C123, 0x71E60E31, + 0x22295556, 0xC3B69A44, 0x49BE6272, 0xA821AD60, + 0xF4AE3B1E, 0x1531F40C, 0x9F390C3A, 0x7EA6C328, + 0x278E89C6, 0xC61146D4, 0x4C19BEE2, 0xAD8671F0, + 0xF109E78E, 0x1096289C, 0x9A9ED0AA, 0x7B011FB8, + 0x3CA96664, 0xDD36A976, 0x573E5140, 0xB6A19E52, + 0xEA2E082C, 0x0BB1C73E, 0x81B93F08, 0x6026F01A, + 0x390EBAF4, 0xD89175E6, 0x52998DD0, 0xB30642C2, + 0xEF89D4BC, 0x0E161BAE, 0x841EE398, 0x65812C8A, + 0x364E77ED, 0xD7D1B8FF, 0x5DD940C9, 0xBC468FDB, + 0xE0C919A5, 0x0156D6B7, 0x8B5E2E81, 0x6AC1E193, + 0x33E9AB7D, 0xD276646F, 0x587E9C59, 0xB9E1534B, + 0xE56EC535, 0x04F10A27, 0x8EF9F211, 0x6F663D03, + 0x50358817, 0xB1AA4705, 0x3BA2BF33, 0xDA3D7021, + 0x86B2E65F, 0x672D294D, 0xED25D17B, 0x0CBA1E69, + 0x55925487, 0xB40D9B95, 0x3E0563A3, 0xDF9AACB1, + 0x83153ACF, 0x628AF5DD, 0xE8820DEB, 0x091DC2F9, + 0x5AD2999E, 0xBB4D568C, 0x3145AEBA, 0xD0DA61A8, + 0x8C55F7D6, 0x6DCA38C4, 0xE7C2C0F2, 0x065D0FE0, + 0x5F75450E, 0xBEEA8A1C, 0x34E2722A, 0xD57DBD38, + 0x89F22B46, 0x686DE454, 0xE2651C62, 0x03FAD370, + 0x4452AAAC, 0xA5CD65BE, 0x2FC59D88, 0xCE5A529A, + 0x92D5C4E4, 0x734A0BF6, 0xF942F3C0, 0x18DD3CD2, + 0x41F5763C, 0xA06AB92E, 0x2A624118, 0xCBFD8E0A, + 0x97721874, 0x76EDD766, 0xFCE52F50, 0x1D7AE042, + 0x4EB5BB25, 0xAF2A7437, 0x25228C01, 0xC4BD4313, + 0x9832D56D, 0x79AD1A7F, 0xF3A5E249, 0x123A2D5B, + 0x4B1267B5, 0xAA8DA8A7, 0x20855091, 0xC11A9F83, + 0x9D9509FD, 0x7C0AC6EF, 0xF6023ED9, 0x179DF1CB, + 0x78FBCCC8, 0x996403DA, 0x136CFBEC, 0xF2F334FE, + 0xAE7CA280, 0x4FE36D92, 0xC5EB95A4, 0x24745AB6, + 0x7D5C1058, 0x9CC3DF4A, 0x16CB277C, 0xF754E86E, + 0xABDB7E10, 0x4A44B102, 0xC04C4934, 0x21D38626, + 0x721CDD41, 0x93831253, 0x198BEA65, 0xF8142577, + 0xA49BB309, 0x45047C1B, 0xCF0C842D, 0x2E934B3F, + 0x77BB01D1, 0x9624CEC3, 0x1C2C36F5, 0xFDB3F9E7, + 0xA13C6F99, 0x40A3A08B, 0xCAAB58BD, 0x2B3497AF, + 0x6C9CEE73, 0x8D032161, 0x070BD957, 0xE6941645, + 0xBA1B803B, 0x5B844F29, 0xD18CB71F, 0x3013780D, + 0x693B32E3, 0x88A4FDF1, 0x02AC05C7, 0xE333CAD5, + 0xBFBC5CAB, 0x5E2393B9, 0xD42B6B8F, 0x35B4A49D, + 0x667BFFFA, 0x87E430E8, 0x0DECC8DE, 0xEC7307CC, + 0xB0FC91B2, 0x51635EA0, 0xDB6BA696, 0x3AF46984, + 0x63DC236A, 0x8243EC78, 0x084B144E, 0xE9D4DB5C, + 0xB55B4D22, 0x54C48230, 0xDECC7A06, 0x3F53B514, +#else + 0x00000000, 0xE19FCF13, 0x6B973726, 0x8A08F835, + 0xD6876E4C, 0x3718A15F, 0xBD10596A, 0x5C8F9679, + 0x05A7DC98, 0xE438138B, 0x6E30EBBE, 0x8FAF24AD, + 0xD320B2D4, 0x32BF7DC7, 0xB8B785F2, 0x59284AE1, + 0x0AE71199, 0xEB78DE8A, 0x617026BF, 0x80EFE9AC, + 0xDC607FD5, 0x3DFFB0C6, 0xB7F748F3, 0x566887E0, + 0x0F40CD01, 0xEEDF0212, 0x64D7FA27, 0x85483534, + 0xD9C7A34D, 0x38586C5E, 0xB250946B, 0x53CF5B78, + 0x1467229B, 0xF5F8ED88, 0x7FF015BD, 0x9E6FDAAE, + 0xC2E04CD7, 0x237F83C4, 0xA9777BF1, 0x48E8B4E2, + 0x11C0FE03, 0xF05F3110, 0x7A57C925, 0x9BC80636, + 0xC747904F, 0x26D85F5C, 0xACD0A769, 0x4D4F687A, + 0x1E803302, 0xFF1FFC11, 0x75170424, 0x9488CB37, + 0xC8075D4E, 0x2998925D, 0xA3906A68, 0x420FA57B, + 0x1B27EF9A, 0xFAB82089, 0x70B0D8BC, 0x912F17AF, + 0xCDA081D6, 0x2C3F4EC5, 0xA637B6F0, 0x47A879E3, + 0x28CE449F, 0xC9518B8C, 0x435973B9, 0xA2C6BCAA, + 0xFE492AD3, 0x1FD6E5C0, 0x95DE1DF5, 0x7441D2E6, + 0x2D699807, 0xCCF65714, 0x46FEAF21, 0xA7616032, + 0xFBEEF64B, 0x1A713958, 0x9079C16D, 0x71E60E7E, + 0x22295506, 0xC3B69A15, 0x49BE6220, 0xA821AD33, + 0xF4AE3B4A, 0x1531F459, 0x9F390C6C, 0x7EA6C37F, + 0x278E899E, 0xC611468D, 0x4C19BEB8, 0xAD8671AB, + 0xF109E7D2, 0x109628C1, 0x9A9ED0F4, 0x7B011FE7, + 0x3CA96604, 0xDD36A917, 0x573E5122, 0xB6A19E31, + 0xEA2E0848, 0x0BB1C75B, 0x81B93F6E, 0x6026F07D, + 0x390EBA9C, 0xD891758F, 0x52998DBA, 0xB30642A9, + 0xEF89D4D0, 0x0E161BC3, 0x841EE3F6, 0x65812CE5, + 0x364E779D, 0xD7D1B88E, 0x5DD940BB, 0xBC468FA8, + 0xE0C919D1, 0x0156D6C2, 0x8B5E2EF7, 0x6AC1E1E4, + 0x33E9AB05, 0xD2766416, 0x587E9C23, 0xB9E15330, + 0xE56EC549, 0x04F10A5A, 0x8EF9F26F, 0x6F663D7C, + 0x50358897, 0xB1AA4784, 0x3BA2BFB1, 0xDA3D70A2, + 0x86B2E6DB, 0x672D29C8, 0xED25D1FD, 0x0CBA1EEE, + 0x5592540F, 0xB40D9B1C, 0x3E056329, 0xDF9AAC3A, + 0x83153A43, 0x628AF550, 0xE8820D65, 0x091DC276, + 0x5AD2990E, 0xBB4D561D, 0x3145AE28, 0xD0DA613B, + 0x8C55F742, 0x6DCA3851, 0xE7C2C064, 0x065D0F77, + 0x5F754596, 0xBEEA8A85, 0x34E272B0, 0xD57DBDA3, + 0x89F22BDA, 0x686DE4C9, 0xE2651CFC, 0x03FAD3EF, + 0x4452AA0C, 0xA5CD651F, 0x2FC59D2A, 0xCE5A5239, + 0x92D5C440, 0x734A0B53, 0xF942F366, 0x18DD3C75, + 0x41F57694, 0xA06AB987, 0x2A6241B2, 0xCBFD8EA1, + 0x977218D8, 0x76EDD7CB, 0xFCE52FFE, 0x1D7AE0ED, + 0x4EB5BB95, 0xAF2A7486, 0x25228CB3, 0xC4BD43A0, + 0x9832D5D9, 0x79AD1ACA, 0xF3A5E2FF, 0x123A2DEC, + 0x4B12670D, 0xAA8DA81E, 0x2085502B, 0xC11A9F38, + 0x9D950941, 0x7C0AC652, 0xF6023E67, 0x179DF174, + 0x78FBCC08, 0x9964031B, 0x136CFB2E, 0xF2F3343D, + 0xAE7CA244, 0x4FE36D57, 0xC5EB9562, 0x24745A71, + 0x7D5C1090, 0x9CC3DF83, 0x16CB27B6, 0xF754E8A5, + 0xABDB7EDC, 0x4A44B1CF, 0xC04C49FA, 0x21D386E9, + 0x721CDD91, 0x93831282, 0x198BEAB7, 0xF81425A4, + 0xA49BB3DD, 0x45047CCE, 0xCF0C84FB, 0x2E934BE8, + 0x77BB0109, 0x9624CE1A, 0x1C2C362F, 0xFDB3F93C, + 0xA13C6F45, 0x40A3A056, 0xCAAB5863, 0x2B349770, + 0x6C9CEE93, 0x8D032180, 0x070BD9B5, 0xE69416A6, + 0xBA1B80DF, 0x5B844FCC, 0xD18CB7F9, 0x301378EA, + 0x693B320B, 0x88A4FD18, 0x02AC052D, 0xE333CA3E, + 0xBFBC5C47, 0x5E239354, 0xD42B6B61, 0x35B4A472, + 0x667BFF0A, 0x87E43019, 0x0DECC82C, 0xEC73073F, + 0xB0FC9146, 0x51635E55, 0xDB6BA660, 0x3AF46973, + 0x63DC2392, 0x8243EC81, 0x084B14B4, 0xE9D4DBA7, + 0xB55B4DDE, 0x54C482CD, 0xDECC7AF8, 0x3F53B5EB, +#endif + 0x00000000, 0x180F40CD, 0x301E8033, 0x2811C0FE, + 0x603CA966, 0x7833E9AB, 0x50222955, 0x482D6998, + 0xC078FBCC, 0xD877BB01, 0xF0667BFF, 0xE8693B32, + 0xA04452AA, 0xB84B1267, 0x905AD299, 0x88559254, + 0x29F05F31, 0x31FF1FFC, 0x19EEDF02, 0x01E19FCF, + 0x49CCF657, 0x51C3B69A, 0x79D27664, 0x61DD36A9, + 0xE988A4FD, 0xF187E430, 0xD99624CE, 0xC1996403, + 0x89B40D9B, 0x91BB4D56, 0xB9AA8DA8, 0xA1A5CD65, + 0x5249BE62, 0x4A46FEAF, 0x62573E51, 0x7A587E9C, + 0x32751704, 0x2A7A57C9, 0x026B9737, 0x1A64D7FA, + 0x923145AE, 0x8A3E0563, 0xA22FC59D, 0xBA208550, + 0xF20DECC8, 0xEA02AC05, 0xC2136CFB, 0xDA1C2C36, + 0x7BB9E153, 0x63B6A19E, 0x4BA76160, 0x53A821AD, + 0x1B854835, 0x038A08F8, 0x2B9BC806, 0x339488CB, + 0xBBC11A9F, 0xA3CE5A52, 0x8BDF9AAC, 0x93D0DA61, + 0xDBFDB3F9, 0xC3F2F334, 0xEBE333CA, 0xF3EC7307, + 0xA492D5C4, 0xBC9D9509, 0x948C55F7, 0x8C83153A, + 0xC4AE7CA2, 0xDCA13C6F, 0xF4B0FC91, 0xECBFBC5C, + 0x64EA2E08, 0x7CE56EC5, 0x54F4AE3B, 0x4CFBEEF6, + 0x04D6876E, 0x1CD9C7A3, 0x34C8075D, 0x2CC74790, + 0x8D628AF5, 0x956DCA38, 0xBD7C0AC6, 0xA5734A0B, + 0xED5E2393, 0xF551635E, 0xDD40A3A0, 0xC54FE36D, + 0x4D1A7139, 0x551531F4, 0x7D04F10A, 0x650BB1C7, + 0x2D26D85F, 0x35299892, 0x1D38586C, 0x053718A1, + 0xF6DB6BA6, 0xEED42B6B, 0xC6C5EB95, 0xDECAAB58, + 0x96E7C2C0, 0x8EE8820D, 0xA6F942F3, 0xBEF6023E, + 0x36A3906A, 0x2EACD0A7, 0x06BD1059, 0x1EB25094, + 0x569F390C, 0x4E9079C1, 0x6681B93F, 0x7E8EF9F2, + 0xDF2B3497, 0xC724745A, 0xEF35B4A4, 0xF73AF469, + 0xBF179DF1, 0xA718DD3C, 0x8F091DC2, 0x97065D0F, + 0x1F53CF5B, 0x075C8F96, 0x2F4D4F68, 0x37420FA5, + 0x7F6F663D, 0x676026F0, 0x4F71E60E, 0x577EA6C3, + 0xE18D0321, 0xF98243EC, 0xD1938312, 0xC99CC3DF, + 0x81B1AA47, 0x99BEEA8A, 0xB1AF2A74, 0xA9A06AB9, + 0x21F5F8ED, 0x39FAB820, 0x11EB78DE, 0x09E43813, + 0x41C9518B, 0x59C61146, 0x71D7D1B8, 0x69D89175, + 0xC87D5C10, 0xD0721CDD, 0xF863DC23, 0xE06C9CEE, + 0xA841F576, 0xB04EB5BB, 0x985F7545, 0x80503588, + 0x0805A7DC, 0x100AE711, 0x381B27EF, 0x20146722, + 0x68390EBA, 0x70364E77, 0x58278E89, 0x4028CE44, + 0xB3C4BD43, 0xABCBFD8E, 0x83DA3D70, 0x9BD57DBD, + 0xD3F81425, 0xCBF754E8, 0xE3E69416, 0xFBE9D4DB, + 0x73BC468F, 0x6BB30642, 0x43A2C6BC, 0x5BAD8671, + 0x1380EFE9, 0x0B8FAF24, 0x239E6FDA, 0x3B912F17, + 0x9A34E272, 0x823BA2BF, 0xAA2A6241, 0xB225228C, + 0xFA084B14, 0xE2070BD9, 0xCA16CB27, 0xD2198BEA, + 0x5A4C19BE, 0x42435973, 0x6A52998D, 0x725DD940, + 0x3A70B0D8, 0x227FF015, 0x0A6E30EB, 0x12617026, + 0x451FD6E5, 0x5D109628, 0x750156D6, 0x6D0E161B, + 0x25237F83, 0x3D2C3F4E, 0x153DFFB0, 0x0D32BF7D, + 0x85672D29, 0x9D686DE4, 0xB579AD1A, 0xAD76EDD7, + 0xE55B844F, 0xFD54C482, 0xD545047C, 0xCD4A44B1, + 0x6CEF89D4, 0x74E0C919, 0x5CF109E7, 0x44FE492A, + 0x0CD320B2, 0x14DC607F, 0x3CCDA081, 0x24C2E04C, + 0xAC977218, 0xB49832D5, 0x9C89F22B, 0x8486B2E6, + 0xCCABDB7E, 0xD4A49BB3, 0xFCB55B4D, 0xE4BA1B80, + 0x17566887, 0x0F59284A, 0x2748E8B4, 0x3F47A879, + 0x776AC1E1, 0x6F65812C, 0x477441D2, 0x5F7B011F, + 0xD72E934B, 0xCF21D386, 0xE7301378, 0xFF3F53B5, + 0xB7123A2D, 0xAF1D7AE0, 0x870CBA1E, 0x9F03FAD3, + 0x3EA637B6, 0x26A9777B, 0x0EB8B785, 0x16B7F748, + 0x5E9A9ED0, 0x4695DE1D, 0x6E841EE3, 0x768B5E2E, + 0xFEDECC7A, 0xE6D18CB7, 0xCEC04C49, 0xD6CF0C84, + 0x9EE2651C, 0x86ED25D1, 0xAEFCE52F, 0xB6F3A5E2 +}; +} + +#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64 +unsigned int SosemanukPolicy::GetAlignment() const +{ +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE +#ifdef __INTEL_COMPILER + if (HasSSE2() && !IsP4()) // Intel compiler produces faster code for this algorithm on the P4 +#else + if (HasSSE2()) +#endif + return 16; + else +#endif + return GetAlignmentOf(); +} + +unsigned int SosemanukPolicy::GetOptimalBlockSize() const +{ +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE +#ifdef __INTEL_COMPILER + if (HasSSE2() && !IsP4()) // Intel compiler produces faster code for this algorithm on the P4 +#else + if (HasSSE2()) +#endif + return 4*BYTES_PER_ITERATION; + else +#endif + return BYTES_PER_ITERATION; +} +#endif + +#ifdef CRYPTOPP_X64_MASM_AVAILABLE +extern "C" { +void Sosemanuk_OperateKeystream(size_t iterationCount, const byte *input, byte *output, word32 *state); +} +#endif + +#pragma warning(disable: 4731) // frame pointer register 'ebp' modified by inline assembly code + +void SosemanukPolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) +{ +#endif // #ifdef CRYPTOPP_GENERATE_X64_MASM + +#ifdef CRYPTOPP_X64_MASM_AVAILABLE + Sosemanuk_OperateKeystream(iterationCount, input, output, m_state.data()); + return; +#endif + +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE +#ifdef CRYPTOPP_GENERATE_X64_MASM + ALIGN 8 + Sosemanuk_OperateKeystream PROC FRAME + rex_push_reg rsi + push_reg rdi + alloc_stack(80*4*2+12*4+8*WORD_SZ + 2*16+8) + save_xmm128 xmm6, 02f0h + save_xmm128 xmm7, 0300h + .endprolog + mov rdi, r8 + mov rax, r9 +#else +#ifdef __INTEL_COMPILER + if (HasSSE2() && !IsP4()) // Intel compiler produces faster code for this algorithm on the P4 +#else + if (HasSSE2()) +#endif + { +#ifdef __GNUC__ + #if CRYPTOPP_BOOL_X64 + FixedSizeAlignedSecBlock workspace; + #endif + __asm__ __volatile__ + ( + ".intel_syntax noprefix;" + AS_PUSH_IF86( bx) +#else + word32 *state = m_state; + AS2( mov WORD_REG(ax), state) + AS2( mov WORD_REG(di), output) + AS2( mov WORD_REG(dx), input) + AS2( mov WORD_REG(cx), iterationCount) +#endif +#endif // #ifdef CRYPTOPP_GENERATE_X64_MASM + +#if defined(__GNUC__) && CRYPTOPP_BOOL_X64 + #define SSE2_workspace %5 +#else + #define SSE2_workspace WORD_REG(sp) +#endif + +#define SSE2_output WORD_PTR [SSE2_workspace+1*WORD_SZ] +#define SSE2_input WORD_PTR [SSE2_workspace+2*WORD_SZ] +#define SSE2_wordsLeft WORD_PTR [SSE2_workspace+3*WORD_SZ] +#define SSE2_diEnd WORD_PTR [SSE2_workspace+4*WORD_SZ] +#define SSE2_pMulTables WORD_PTR [SSE2_workspace+5*WORD_SZ] +#define SSE2_state WORD_PTR [SSE2_workspace+6*WORD_SZ] +#define SSE2_wordsLeft2 WORD_PTR [SSE2_workspace+7*WORD_SZ] +#define SSE2_stateCopy SSE2_workspace + 8*WORD_SZ +#define SSE2_uvStart SSE2_stateCopy + 12*4 + +#if CRYPTOPP_BOOL_X86 + AS_PUSH_IF86( bp) + AS2( mov AS_REG_6, esp) + AS2( and esp, -16) + AS2( sub esp, 80*4*2+12*4+8*WORD_SZ) // 80 v's, 80 u's, 12 state, 8 locals + AS2( mov [esp], AS_REG_6) +#endif + AS2( mov SSE2_output, WORD_REG(di)) + AS2( mov SSE2_input, WORD_REG(dx)) + AS2( mov SSE2_state, WORD_REG(ax)) +#ifndef _MSC_VER + AS2( mov SSE2_pMulTables, WORD_REG(si)) +#endif + AS2( lea WORD_REG(cx), [4*WORD_REG(cx)+WORD_REG(cx)]) + AS2( lea WORD_REG(si), [4*WORD_REG(cx)]) + AS2( mov SSE2_wordsLeft, WORD_REG(si)) + AS2( movdqa xmm0, [WORD_REG(ax)+0*16]) // copy state to stack to save a register + AS2( movdqa [SSE2_stateCopy+0*16], xmm0) + AS2( movdqa xmm0, [WORD_REG(ax)+1*16]) + AS2( movdqa [SSE2_stateCopy+1*16], xmm0) + AS2( movq xmm0, QWORD PTR [WORD_REG(ax)+2*16]) + AS2( movq QWORD PTR [SSE2_stateCopy+2*16], xmm0) + AS2( psrlq xmm0, 32) + AS2( movd AS_REG_6d, xmm0) // s(9) + AS2( mov ecx, [WORD_REG(ax)+10*4]) + AS2( mov edx, [WORD_REG(ax)+11*4]) + AS2( pcmpeqb xmm7, xmm7) // all ones + +#define s(i) SSE2_stateCopy + ASM_MOD(i,10)*4 +#define u(j) WORD_REG(di) + (ASM_MOD(j,4)*20 + (j/4)) * 4 +#define v(j) WORD_REG(di) + (ASM_MOD(j,4)*20 + (j/4)) * 4 + 80*4 + +#define R10 ecx +#define R11 edx +#define R20 edx +#define R21 ecx +// workaround bug in GAS 2.15 +#define R20r WORD_REG(dx) +#define R21r WORD_REG(cx) + +#define SSE2_STEP(i, j) \ + AS2( mov eax, [s(i+0)])\ + AS2( mov [v(i)], eax)\ + AS2( rol eax, 8)\ + AS2( lea AS_REG_7, [AS_REG_6 + R2##j##r])\ + AS2( xor AS_REG_7d, R1##j)\ + AS2( mov [u(i)], AS_REG_7d)\ + AS2( mov AS_REG_7d, 1)\ + AS2( and AS_REG_7d, R2##j)\ + AS1( neg AS_REG_7d)\ + AS2( and AS_REG_7d, AS_REG_6d)\ + AS2( xor AS_REG_6d, eax)\ + AS2( movzx eax, al)\ + AS2( xor AS_REG_6d, [WORD_REG(si)+WORD_REG(ax)*4])\ + AS2( mov eax, [s(i+3)])\ + AS2( xor AS_REG_7d, [s(i+2)])\ + AS2( add R1##j, AS_REG_7d)\ + AS2( movzx AS_REG_7d, al)\ + AS2( shr eax, 8)\ + AS2( xor AS_REG_6d, [WORD_REG(si)+1024+AS_REG_7*4])\ + AS2( xor AS_REG_6d, eax)\ + AS2( imul R2##j, AS_HEX(54655307))\ + AS2( rol R2##j, 7)\ + AS2( mov [s(i+0)], AS_REG_6d)\ + + ASL(2) // outer loop, each iteration of this processes 80 words + AS2( lea WORD_REG(di), [SSE2_uvStart]) // start of v and u + AS2( mov WORD_REG(ax), 80) + AS2( cmp WORD_REG(si), 80) + AS2( cmovg WORD_REG(si), WORD_REG(ax)) + AS2( mov SSE2_wordsLeft2, WORD_REG(si)) + AS2( lea WORD_REG(si), [WORD_REG(di)+WORD_REG(si)]) // use to end first inner loop + AS2( mov SSE2_diEnd, WORD_REG(si)) +#ifdef _MSC_VER + AS2( lea WORD_REG(si), s_sosemanukMulTables) +#else + AS2( mov WORD_REG(si), SSE2_pMulTables) +#endif + + ASL(0) // first inner loop, 20 words each, 4 iterations + SSE2_STEP(0, 0) + SSE2_STEP(1, 1) + SSE2_STEP(2, 0) + SSE2_STEP(3, 1) + SSE2_STEP(4, 0) + SSE2_STEP(5, 1) + SSE2_STEP(6, 0) + SSE2_STEP(7, 1) + SSE2_STEP(8, 0) + SSE2_STEP(9, 1) + SSE2_STEP(10, 0) + SSE2_STEP(11, 1) + SSE2_STEP(12, 0) + SSE2_STEP(13, 1) + SSE2_STEP(14, 0) + SSE2_STEP(15, 1) + SSE2_STEP(16, 0) + SSE2_STEP(17, 1) + SSE2_STEP(18, 0) + SSE2_STEP(19, 1) + // loop + AS2( add WORD_REG(di), 5*4) + AS2( cmp WORD_REG(di), SSE2_diEnd) + ASJ( jne, 0, b) + + AS2( mov WORD_REG(ax), SSE2_input) + AS2( mov AS_REG_7, SSE2_output) + AS2( lea WORD_REG(di), [SSE2_uvStart]) // start of v and u + AS2( mov WORD_REG(si), SSE2_wordsLeft2) + + ASL(1) // second inner loop, 16 words each, 5 iterations + AS2( movdqa xmm0, [WORD_REG(di)+0*20*4]) + AS2( movdqa xmm2, [WORD_REG(di)+2*20*4]) + AS2( movdqa xmm3, [WORD_REG(di)+3*20*4]) + AS2( movdqa xmm1, [WORD_REG(di)+1*20*4]) + // S2 + AS2( movdqa xmm4, xmm0) + AS2( pand xmm0, xmm2) + AS2( pxor xmm0, xmm3) + AS2( pxor xmm2, xmm1) + AS2( pxor xmm2, xmm0) + AS2( por xmm3, xmm4) + AS2( pxor xmm3, xmm1) + AS2( pxor xmm4, xmm2) + AS2( movdqa xmm1, xmm3) + AS2( por xmm3, xmm4) + AS2( pxor xmm3, xmm0) + AS2( pand xmm0, xmm1) + AS2( pxor xmm4, xmm0) + AS2( pxor xmm1, xmm3) + AS2( pxor xmm1, xmm4) + AS2( pxor xmm4, xmm7) + // xor with v + AS2( pxor xmm2, [WORD_REG(di)+80*4]) + AS2( pxor xmm3, [WORD_REG(di)+80*5]) + AS2( pxor xmm1, [WORD_REG(di)+80*6]) + AS2( pxor xmm4, [WORD_REG(di)+80*7]) + // exit loop early if less than 16 words left to output + // this is necessary because block size is 20 words, and we output 16 words in each iteration of this loop + AS2( cmp WORD_REG(si), 16) + ASJ( jl, 4, f) + // unpack + AS2( movdqa xmm6, xmm2) + AS2( punpckldq xmm2, xmm3) + AS2( movdqa xmm5, xmm1) + AS2( punpckldq xmm1, xmm4) + AS2( movdqa xmm0, xmm2) + AS2( punpcklqdq xmm2, xmm1) + AS2( punpckhqdq xmm0, xmm1) + AS2( punpckhdq xmm6, xmm3) + AS2( punpckhdq xmm5, xmm4) + AS2( movdqa xmm3, xmm6) + AS2( punpcklqdq xmm6, xmm5) + AS2( punpckhqdq xmm3, xmm5) + // output keystream + AS_XMM_OUTPUT4(SSE2_Sosemanuk_Output, WORD_REG(ax), AS_REG_7, 2,0,6,3, 1, 0,1,2,3, 4) + + // loop + AS2( add WORD_REG(di), 4*4) + AS2( sub WORD_REG(si), 16) + ASJ( jnz, 1, b) + + // outer loop + AS2( mov WORD_REG(si), SSE2_wordsLeft) + AS2( sub WORD_REG(si), 80) + ASJ( jz, 6, f) + AS2( mov SSE2_wordsLeft, WORD_REG(si)) + AS2( mov SSE2_input, WORD_REG(ax)) + AS2( mov SSE2_output, AS_REG_7) + ASJ( jmp, 2, b) + + ASL(4) // final output of less than 16 words + AS2( test WORD_REG(ax), WORD_REG(ax)) + ASJ( jz, 5, f) + AS2( movd xmm0, dword ptr [WORD_REG(ax)+0*4]) + AS2( pxor xmm2, xmm0) + AS2( movd xmm0, dword ptr [WORD_REG(ax)+1*4]) + AS2( pxor xmm3, xmm0) + AS2( movd xmm0, dword ptr [WORD_REG(ax)+2*4]) + AS2( pxor xmm1, xmm0) + AS2( movd xmm0, dword ptr [WORD_REG(ax)+3*4]) + AS2( pxor xmm4, xmm0) + AS2( add WORD_REG(ax), 16) + ASL(5) + AS2( movd dword ptr [AS_REG_7+0*4], xmm2) + AS2( movd dword ptr [AS_REG_7+1*4], xmm3) + AS2( movd dword ptr [AS_REG_7+2*4], xmm1) + AS2( movd dword ptr [AS_REG_7+3*4], xmm4) + AS2( sub WORD_REG(si), 4) + ASJ( jz, 6, f) + AS2( add AS_REG_7, 16) + AS2( psrldq xmm2, 4) + AS2( psrldq xmm3, 4) + AS2( psrldq xmm1, 4) + AS2( psrldq xmm4, 4) + ASJ( jmp, 4, b) + + ASL(6) // save state + AS2( mov AS_REG_6, SSE2_state) + AS2( movdqa xmm0, [SSE2_stateCopy+0*16]) + AS2( movdqa [AS_REG_6+0*16], xmm0) + AS2( movdqa xmm0, [SSE2_stateCopy+1*16]) + AS2( movdqa [AS_REG_6+1*16], xmm0) + AS2( movq xmm0, QWORD PTR [SSE2_stateCopy+2*16]) + AS2( movq QWORD PTR [AS_REG_6+2*16], xmm0) + AS2( mov [AS_REG_6+10*4], ecx) + AS2( mov [AS_REG_6+11*4], edx) + + AS_POP_IF86( sp) + AS_POP_IF86( bp) + +#ifdef __GNUC__ + AS_POP_IF86( bx) + ".att_syntax prefix;" + : + : "a" (m_state.m_ptr), "c" (iterationCount), "S" (s_sosemanukMulTables), "D" (output), "d" (input) + #if CRYPTOPP_BOOL_X64 + , "r" (workspace.m_ptr) + : "memory", "cc", "%r9", "%r10", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7" + #else + : "memory", "cc" + #endif + ); +#endif +#ifdef CRYPTOPP_GENERATE_X64_MASM + movdqa xmm6, [rsp + 02f0h] + movdqa xmm7, [rsp + 0300h] + add rsp, 80*4*2+12*4+8*WORD_SZ + 2*16+8 + pop rdi + pop rsi + ret + Sosemanuk_OperateKeystream ENDP +#else + } + else +#endif +#endif +#ifndef CRYPTOPP_GENERATE_X64_MASM + { +#if CRYPTOPP_BOOL_X86 | CRYPTOPP_BOOL_X64 +#define MUL_A(x) (x = rotlFixed(x, 8), x ^ s_sosemanukMulTables[byte(x)]) +#else +#define MUL_A(x) (((x) << 8) ^ s_sosemanukMulTables[(x) >> 24]) +#endif + +#define DIV_A(x) (((x) >> 8) ^ s_sosemanukMulTables[256 + byte(x)]) + +#define r1(i) ((i%2) ? reg2 : reg1) +#define r2(i) ((i%2) ? reg1 : reg2) + +#define STEP(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, v, u) \ + u = (s##x9 + r2(x0)) ^ r1(x0);\ + v = s##x0;\ + s##x0 = MUL_A(s##x0) ^ DIV_A(s##x3) ^ s##x9;\ + r1(x0) += XMUX(r2(x0), s##x2, s##x9);\ + r2(x0) = rotlFixed(r2(x0) * 0x54655307, 7);\ + +#define SOSEMANUK_OUTPUT(x) \ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 0, u2 ^ v0);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 1, u3 ^ v1);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 2, u1 ^ v2);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 3, u4 ^ v3); + +#define OUTPUT4 \ + S2(0, u0, u1, u2, u3, u4);\ + CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(SOSEMANUK_OUTPUT, 4*4); + + word32 s0 = m_state[0]; + word32 s1 = m_state[1]; + word32 s2 = m_state[2]; + word32 s3 = m_state[3]; + word32 s4 = m_state[4]; + word32 s5 = m_state[5]; + word32 s6 = m_state[6]; + word32 s7 = m_state[7]; + word32 s8 = m_state[8]; + word32 s9 = m_state[9]; + word32 reg1 = m_state[10]; + word32 reg2 = m_state[11]; + word32 u0, u1, u2, u3, u4, v0, v1, v2, v3; + + do + { + STEP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, v0, u0) + STEP(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, v1, u1) + STEP(2, 3, 4, 5, 6, 7, 8, 9, 0, 1, v2, u2) + STEP(3, 4, 5, 6, 7, 8, 9, 0, 1, 2, v3, u3) + OUTPUT4 + STEP(4, 5, 6, 7, 8, 9, 0, 1, 2, 3, v0, u0) + STEP(5, 6, 7, 8, 9, 0, 1, 2, 3, 4, v1, u1) + STEP(6, 7, 8, 9, 0, 1, 2, 3, 4, 5, v2, u2) + STEP(7, 8, 9, 0, 1, 2, 3, 4, 5, 6, v3, u3) + OUTPUT4 + STEP(8, 9, 0, 1, 2, 3, 4, 5, 6, 7, v0, u0) + STEP(9, 0, 1, 2, 3, 4, 5, 6, 7, 8, v1, u1) + STEP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, v2, u2) + STEP(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, v3, u3) + OUTPUT4 + STEP(2, 3, 4, 5, 6, 7, 8, 9, 0, 1, v0, u0) + STEP(3, 4, 5, 6, 7, 8, 9, 0, 1, 2, v1, u1) + STEP(4, 5, 6, 7, 8, 9, 0, 1, 2, 3, v2, u2) + STEP(5, 6, 7, 8, 9, 0, 1, 2, 3, 4, v3, u3) + OUTPUT4 + STEP(6, 7, 8, 9, 0, 1, 2, 3, 4, 5, v0, u0) + STEP(7, 8, 9, 0, 1, 2, 3, 4, 5, 6, v1, u1) + STEP(8, 9, 0, 1, 2, 3, 4, 5, 6, 7, v2, u2) + STEP(9, 0, 1, 2, 3, 4, 5, 6, 7, 8, v3, u3) + OUTPUT4 + } + while (--iterationCount); + + m_state[0] = s0; + m_state[1] = s1; + m_state[2] = s2; + m_state[3] = s3; + m_state[4] = s4; + m_state[5] = s5; + m_state[6] = s6; + m_state[7] = s7; + m_state[8] = s8; + m_state[9] = s9; + m_state[10] = reg1; + m_state[11] = reg2; + } +} + +NAMESPACE_END + +#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM diff --git a/src-cryptopp/sosemanuk.h b/src-cryptopp/sosemanuk.h new file mode 100644 index 0000000..ff1d820 --- /dev/null +++ b/src-cryptopp/sosemanuk.h @@ -0,0 +1,40 @@ +#ifndef CRYPTOPP_SOSEMANUK_H +#define CRYPTOPP_SOSEMANUK_H + +#include "strciphr.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! algorithm info +struct SosemanukInfo : public VariableKeyLength<16, 1, 32, 1, SimpleKeyingInterface::UNIQUE_IV, 16> +{ + static const char * StaticAlgorithmName() {return "Sosemanuk";} +}; + +//! _ +class SosemanukPolicy : public AdditiveCipherConcretePolicy, public SosemanukInfo +{ +protected: + void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length); + void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount); + void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length); + bool CipherIsRandomAccess() const {return false;} +#if CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64 + unsigned int GetAlignment() const; + unsigned int GetOptimalBlockSize() const; +#endif + + FixedSizeSecBlock m_key; + FixedSizeAlignedSecBlock m_state; +}; + +//! Sosemanuk +struct Sosemanuk : public SosemanukInfo, public SymmetricCipherDocumentation +{ + typedef SymmetricCipherFinal >, SosemanukInfo> Encryption; + typedef Encryption Decryption; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/stdcpp.h b/src-cryptopp/stdcpp.h new file mode 100644 index 0000000..234bf54 --- /dev/null +++ b/src-cryptopp/stdcpp.h @@ -0,0 +1,31 @@ +#ifndef CRYPTOPP_STDCPP_H +#define CRYPTOPP_STDCPP_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// for alloca +#ifdef __sun +#include +#elif defined(__MINGW32__) +#include +#endif + +#ifdef _MSC_VER +#pragma warning(disable: 4231) // re-disable this +#ifdef _CRTAPI1 +#define CRYPTOPP_MSVCRT6 +#endif +#endif + +#endif diff --git a/src-cryptopp/strciphr.cpp b/src-cryptopp/strciphr.cpp new file mode 100644 index 0000000..53e0073 --- /dev/null +++ b/src-cryptopp/strciphr.cpp @@ -0,0 +1,252 @@ +// strciphr.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" + +#ifndef CRYPTOPP_IMPORTS + +#include "strciphr.h" + +NAMESPACE_BEGIN(CryptoPP) + +template +void AdditiveCipherTemplate::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) +{ + PolicyInterface &policy = this->AccessPolicy(); + policy.CipherSetKey(params, key, length); + m_leftOver = 0; + unsigned int bufferByteSize = policy.CanOperateKeystream() ? GetBufferByteSize(policy) : RoundUpToMultipleOf(1024U, GetBufferByteSize(policy)); + m_buffer.New(bufferByteSize); + + if (this->IsResynchronizable()) + { + size_t ivLength; + const byte *iv = this->GetIVAndThrowIfInvalid(params, ivLength); + policy.CipherResynchronize(m_buffer, iv, ivLength); + } +} + +template +void AdditiveCipherTemplate::GenerateBlock(byte *outString, size_t length) +{ + if (m_leftOver > 0) + { + size_t len = STDMIN(m_leftOver, length); + memcpy(outString, KeystreamBufferEnd()-m_leftOver, len); + length -= len; + m_leftOver -= len; + outString += len; + + if (!length) + return; + } + assert(m_leftOver == 0); + + PolicyInterface &policy = this->AccessPolicy(); + unsigned int bytesPerIteration = policy.GetBytesPerIteration(); + + if (length >= bytesPerIteration) + { + size_t iterations = length / bytesPerIteration; + policy.WriteKeystream(outString, iterations); + outString += iterations * bytesPerIteration; + length -= iterations * bytesPerIteration; + } + + if (length > 0) + { + size_t bufferByteSize = RoundUpToMultipleOf(length, bytesPerIteration); + size_t bufferIterations = bufferByteSize / bytesPerIteration; + + policy.WriteKeystream(KeystreamBufferEnd()-bufferByteSize, bufferIterations); + memcpy(outString, KeystreamBufferEnd()-bufferByteSize, length); + m_leftOver = bufferByteSize - length; + } +} + +template +void AdditiveCipherTemplate::ProcessData(byte *outString, const byte *inString, size_t length) +{ + if (m_leftOver > 0) + { + size_t len = STDMIN(m_leftOver, length); + xorbuf(outString, inString, KeystreamBufferEnd()-m_leftOver, len); + length -= len; + m_leftOver -= len; + inString += len; + outString += len; + + if (!length) + return; + } + assert(m_leftOver == 0); + + PolicyInterface &policy = this->AccessPolicy(); + unsigned int bytesPerIteration = policy.GetBytesPerIteration(); + + if (policy.CanOperateKeystream() && length >= bytesPerIteration) + { + size_t iterations = length / bytesPerIteration; + unsigned int alignment = policy.GetAlignment(); + KeystreamOperation operation = KeystreamOperation((IsAlignedOn(inString, alignment) * 2) | (int)IsAlignedOn(outString, alignment)); + + policy.OperateKeystream(operation, outString, inString, iterations); + + inString += iterations * bytesPerIteration; + outString += iterations * bytesPerIteration; + length -= iterations * bytesPerIteration; + + if (!length) + return; + } + + size_t bufferByteSize = m_buffer.size(); + size_t bufferIterations = bufferByteSize / bytesPerIteration; + + while (length >= bufferByteSize) + { + policy.WriteKeystream(m_buffer, bufferIterations); + xorbuf(outString, inString, KeystreamBufferBegin(), bufferByteSize); + length -= bufferByteSize; + inString += bufferByteSize; + outString += bufferByteSize; + } + + if (length > 0) + { + bufferByteSize = RoundUpToMultipleOf(length, bytesPerIteration); + bufferIterations = bufferByteSize / bytesPerIteration; + + policy.WriteKeystream(KeystreamBufferEnd()-bufferByteSize, bufferIterations); + xorbuf(outString, inString, KeystreamBufferEnd()-bufferByteSize, length); + m_leftOver = bufferByteSize - length; + } +} + +template +void AdditiveCipherTemplate::Resynchronize(const byte *iv, int length) +{ + PolicyInterface &policy = this->AccessPolicy(); + m_leftOver = 0; + m_buffer.New(GetBufferByteSize(policy)); + policy.CipherResynchronize(m_buffer, iv, this->ThrowIfInvalidIVLength(length)); +} + +template +void AdditiveCipherTemplate::Seek(lword position) +{ + PolicyInterface &policy = this->AccessPolicy(); + unsigned int bytesPerIteration = policy.GetBytesPerIteration(); + + policy.SeekToIteration(position / bytesPerIteration); + position %= bytesPerIteration; + + if (position > 0) + { + policy.WriteKeystream(KeystreamBufferEnd()-bytesPerIteration, 1); + m_leftOver = bytesPerIteration - (unsigned int)position; + } + else + m_leftOver = 0; +} + +template +void CFB_CipherTemplate::UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) +{ + PolicyInterface &policy = this->AccessPolicy(); + policy.CipherSetKey(params, key, length); + + if (this->IsResynchronizable()) + { + size_t ivLength; + const byte *iv = this->GetIVAndThrowIfInvalid(params, ivLength); + policy.CipherResynchronize(iv, ivLength); + } + + m_leftOver = policy.GetBytesPerIteration(); +} + +template +void CFB_CipherTemplate::Resynchronize(const byte *iv, int length) +{ + PolicyInterface &policy = this->AccessPolicy(); + policy.CipherResynchronize(iv, this->ThrowIfInvalidIVLength(length)); + m_leftOver = policy.GetBytesPerIteration(); +} + +template +void CFB_CipherTemplate::ProcessData(byte *outString, const byte *inString, size_t length) +{ + assert(length % this->MandatoryBlockSize() == 0); + + PolicyInterface &policy = this->AccessPolicy(); + unsigned int bytesPerIteration = policy.GetBytesPerIteration(); + unsigned int alignment = policy.GetAlignment(); + byte *reg = policy.GetRegisterBegin(); + + if (m_leftOver) + { + size_t len = STDMIN(m_leftOver, length); + CombineMessageAndShiftRegister(outString, reg + bytesPerIteration - m_leftOver, inString, len); + m_leftOver -= len; + length -= len; + inString += len; + outString += len; + } + + if (!length) + return; + + assert(m_leftOver == 0); + + if (policy.CanIterate() && length >= bytesPerIteration && IsAlignedOn(outString, alignment)) + { + if (IsAlignedOn(inString, alignment)) + policy.Iterate(outString, inString, GetCipherDir(*this), length / bytesPerIteration); + else + { + memcpy(outString, inString, length); + policy.Iterate(outString, outString, GetCipherDir(*this), length / bytesPerIteration); + } + inString += length - length % bytesPerIteration; + outString += length - length % bytesPerIteration; + length %= bytesPerIteration; + } + + while (length >= bytesPerIteration) + { + policy.TransformRegister(); + CombineMessageAndShiftRegister(outString, reg, inString, bytesPerIteration); + length -= bytesPerIteration; + inString += bytesPerIteration; + outString += bytesPerIteration; + } + + if (length > 0) + { + policy.TransformRegister(); + CombineMessageAndShiftRegister(outString, reg, inString, length); + m_leftOver = bytesPerIteration - length; + } +} + +template +void CFB_EncryptionTemplate::CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) +{ + xorbuf(reg, message, length); + memcpy(output, reg, length); +} + +template +void CFB_DecryptionTemplate::CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) +{ + for (unsigned int i=0; i, AdditiveCipherTemplate\<\> \> \> Encryption; + + AdditiveCipherTemplate and CFB_CipherTemplate are designed so that they don't need + to take a policy class as a template parameter (although this is allowed), so that + their code is not duplicated for each new cipher. Instead they each + get a reference to an abstract policy interface by calling AccessPolicy() on itself, so + AccessPolicy() must be overriden to return the actual policy reference. This is done + by the ConceretePolicyHolder class. Finally, SymmetricCipherFinal implements the constructors and + other functions that must be implemented by the most derived class. +*/ + +#ifndef CRYPTOPP_STRCIPHR_H +#define CRYPTOPP_STRCIPHR_H + +#include "seckey.h" +#include "secblock.h" +#include "argnames.h" + +NAMESPACE_BEGIN(CryptoPP) + +template +class CRYPTOPP_NO_VTABLE AbstractPolicyHolder : public BASE +{ +public: + typedef POLICY_INTERFACE PolicyInterface; + virtual ~AbstractPolicyHolder() {} + +protected: + virtual const POLICY_INTERFACE & GetPolicy() const =0; + virtual POLICY_INTERFACE & AccessPolicy() =0; +}; + +template +class ConcretePolicyHolder : public BASE, protected POLICY +{ +protected: + const POLICY_INTERFACE & GetPolicy() const {return *this;} + POLICY_INTERFACE & AccessPolicy() {return *this;} +}; + +enum KeystreamOperationFlags {OUTPUT_ALIGNED=1, INPUT_ALIGNED=2, INPUT_NULL = 4}; +enum KeystreamOperation { + WRITE_KEYSTREAM = INPUT_NULL, + WRITE_KEYSTREAM_ALIGNED = INPUT_NULL | OUTPUT_ALIGNED, + XOR_KEYSTREAM = 0, + XOR_KEYSTREAM_INPUT_ALIGNED = INPUT_ALIGNED, + XOR_KEYSTREAM_OUTPUT_ALIGNED= OUTPUT_ALIGNED, + XOR_KEYSTREAM_BOTH_ALIGNED = OUTPUT_ALIGNED | INPUT_ALIGNED}; + +struct CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AdditiveCipherAbstractPolicy +{ + virtual ~AdditiveCipherAbstractPolicy() {} + virtual unsigned int GetAlignment() const {return 1;} + virtual unsigned int GetBytesPerIteration() const =0; + virtual unsigned int GetOptimalBlockSize() const {return GetBytesPerIteration();} + virtual unsigned int GetIterationsToBuffer() const =0; + virtual void WriteKeystream(byte *keystream, size_t iterationCount) + {OperateKeystream(KeystreamOperation(INPUT_NULL | (KeystreamOperationFlags)IsAlignedOn(keystream, GetAlignment())), keystream, NULL, iterationCount);} + virtual bool CanOperateKeystream() const {return false;} + virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) {assert(false);} + virtual void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) =0; + virtual void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");} + virtual bool CipherIsRandomAccess() const =0; + virtual void SeekToIteration(lword iterationCount) {assert(!CipherIsRandomAccess()); throw NotImplemented("StreamTransformation: this object doesn't support random access");} +}; + +template +struct CRYPTOPP_NO_VTABLE AdditiveCipherConcretePolicy : public BASE +{ + typedef WT WordType; + CRYPTOPP_CONSTANT(BYTES_PER_ITERATION = sizeof(WordType) * W) + +#if !(CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64) + unsigned int GetAlignment() const {return GetAlignmentOf();} +#endif + unsigned int GetBytesPerIteration() const {return BYTES_PER_ITERATION;} + unsigned int GetIterationsToBuffer() const {return X;} + bool CanOperateKeystream() const {return true;} + virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) =0; +}; + +// use these to implement OperateKeystream +#define CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, b, i, a) \ + PutWord(bool(x & OUTPUT_ALIGNED), b, output+i*sizeof(WordType), (x & INPUT_NULL) ? a : a ^ GetWord(bool(x & INPUT_ALIGNED), b, input+i*sizeof(WordType))); +#define CRYPTOPP_KEYSTREAM_OUTPUT_XMM(x, i, a) {\ + __m128i t = (x & INPUT_NULL) ? a : _mm_xor_si128(a, (x & INPUT_ALIGNED) ? _mm_load_si128((__m128i *)input+i) : _mm_loadu_si128((__m128i *)input+i));\ + if (x & OUTPUT_ALIGNED) _mm_store_si128((__m128i *)output+i, t);\ + else _mm_storeu_si128((__m128i *)output+i, t);} +#define CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(x, y) \ + switch (operation) \ + { \ + case WRITE_KEYSTREAM: \ + x(WRITE_KEYSTREAM) \ + break; \ + case XOR_KEYSTREAM: \ + x(XOR_KEYSTREAM) \ + input += y; \ + break; \ + case XOR_KEYSTREAM_INPUT_ALIGNED: \ + x(XOR_KEYSTREAM_INPUT_ALIGNED) \ + input += y; \ + break; \ + case XOR_KEYSTREAM_OUTPUT_ALIGNED: \ + x(XOR_KEYSTREAM_OUTPUT_ALIGNED) \ + input += y; \ + break; \ + case WRITE_KEYSTREAM_ALIGNED: \ + x(WRITE_KEYSTREAM_ALIGNED) \ + break; \ + case XOR_KEYSTREAM_BOTH_ALIGNED: \ + x(XOR_KEYSTREAM_BOTH_ALIGNED) \ + input += y; \ + break; \ + } \ + output += y; + +template > +class CRYPTOPP_NO_VTABLE AdditiveCipherTemplate : public BASE, public RandomNumberGenerator +{ +public: + void GenerateBlock(byte *output, size_t size); + void ProcessData(byte *outString, const byte *inString, size_t length); + void Resynchronize(const byte *iv, int length=-1); + unsigned int OptimalBlockSize() const {return this->GetPolicy().GetOptimalBlockSize();} + unsigned int GetOptimalNextBlockSize() const {return (unsigned int)this->m_leftOver;} + unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();} + bool IsSelfInverting() const {return true;} + bool IsForwardTransformation() const {return true;} + bool IsRandomAccess() const {return this->GetPolicy().CipherIsRandomAccess();} + void Seek(lword position); + + typedef typename BASE::PolicyInterface PolicyInterface; + +protected: + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); + + unsigned int GetBufferByteSize(const PolicyInterface &policy) const {return policy.GetBytesPerIteration() * policy.GetIterationsToBuffer();} + + inline byte * KeystreamBufferBegin() {return this->m_buffer.data();} + inline byte * KeystreamBufferEnd() {return (this->m_buffer.data() + this->m_buffer.size());} + + SecByteBlock m_buffer; + size_t m_leftOver; +}; + +class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_CipherAbstractPolicy +{ +public: + virtual ~CFB_CipherAbstractPolicy() {} + virtual unsigned int GetAlignment() const =0; + virtual unsigned int GetBytesPerIteration() const =0; + virtual byte * GetRegisterBegin() =0; + virtual void TransformRegister() =0; + virtual bool CanIterate() const {return false;} + virtual void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount) {assert(false); throw 0;} + virtual void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) =0; + virtual void CipherResynchronize(const byte *iv, size_t length) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");} +}; + +template +struct CRYPTOPP_NO_VTABLE CFB_CipherConcretePolicy : public BASE +{ + typedef WT WordType; + + unsigned int GetAlignment() const {return sizeof(WordType);} + unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;} + bool CanIterate() const {return true;} + void TransformRegister() {this->Iterate(NULL, NULL, ENCRYPTION, 1);} + + template + struct RegisterOutput + { + RegisterOutput(byte *output, const byte *input, CipherDir dir) + : m_output(output), m_input(input), m_dir(dir) {} + + inline RegisterOutput& operator()(WordType ®isterWord) + { + assert(IsAligned(m_output)); + assert(IsAligned(m_input)); + + if (!NativeByteOrderIs(B::ToEnum())) + registerWord = ByteReverse(registerWord); + + if (m_dir == ENCRYPTION) + { + if (m_input == NULL) + assert(m_output == NULL); + else + { + WordType ct = *(const WordType *)m_input ^ registerWord; + registerWord = ct; + *(WordType*)m_output = ct; + m_input += sizeof(WordType); + m_output += sizeof(WordType); + } + } + else + { + WordType ct = *(const WordType *)m_input; + *(WordType*)m_output = registerWord ^ ct; + registerWord = ct; + m_input += sizeof(WordType); + m_output += sizeof(WordType); + } + + // registerWord is left unreversed so it can be xor-ed with further input + + return *this; + } + + byte *m_output; + const byte *m_input; + CipherDir m_dir; + }; +}; + +template +class CRYPTOPP_NO_VTABLE CFB_CipherTemplate : public BASE +{ +public: + void ProcessData(byte *outString, const byte *inString, size_t length); + void Resynchronize(const byte *iv, int length=-1); + unsigned int OptimalBlockSize() const {return this->GetPolicy().GetBytesPerIteration();} + unsigned int GetOptimalNextBlockSize() const {return (unsigned int)m_leftOver;} + unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();} + bool IsRandomAccess() const {return false;} + bool IsSelfInverting() const {return false;} + + typedef typename BASE::PolicyInterface PolicyInterface; + +protected: + virtual void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) =0; + + void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); + + size_t m_leftOver; +}; + +template > +class CRYPTOPP_NO_VTABLE CFB_EncryptionTemplate : public CFB_CipherTemplate +{ + bool IsForwardTransformation() const {return true;} + void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length); +}; + +template > +class CRYPTOPP_NO_VTABLE CFB_DecryptionTemplate : public CFB_CipherTemplate +{ + bool IsForwardTransformation() const {return false;} + void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length); +}; + +template +class CFB_RequireFullDataBlocks : public BASE +{ +public: + unsigned int MandatoryBlockSize() const {return this->OptimalBlockSize();} +}; + +//! _ +template +class SymmetricCipherFinal : public AlgorithmImpl, INFO> +{ +public: + SymmetricCipherFinal() {} + SymmetricCipherFinal(const byte *key) + {this->SetKey(key, this->DEFAULT_KEYLENGTH);} + SymmetricCipherFinal(const byte *key, size_t length) + {this->SetKey(key, length);} + SymmetricCipherFinal(const byte *key, size_t length, const byte *iv) + {this->SetKeyWithIV(key, length, iv);} + + Clonable * Clone() const {return static_cast(new SymmetricCipherFinal(*this));} +}; + +NAMESPACE_END + +#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES +#include "strciphr.cpp" +#endif + +NAMESPACE_BEGIN(CryptoPP) +CRYPTOPP_DLL_TEMPLATE_CLASS AbstractPolicyHolder; +CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate >; +CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate >; +CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate >; +CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate >; +NAMESPACE_END + +#endif diff --git a/src-cryptopp/tiger.cpp b/src-cryptopp/tiger.cpp new file mode 100644 index 0000000..c6c05ca --- /dev/null +++ b/src-cryptopp/tiger.cpp @@ -0,0 +1,265 @@ +// tiger.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "tiger.h" +#include "misc.h" +#include "cpu.h" + +NAMESPACE_BEGIN(CryptoPP) + +void Tiger::InitState(HashWordType *state) +{ + state[0] = W64LIT(0x0123456789ABCDEF); + state[1] = W64LIT(0xFEDCBA9876543210); + state[2] = W64LIT(0xF096A5B4C3B2E187); +} + +void Tiger::TruncatedFinal(byte *hash, size_t size) +{ + ThrowIfInvalidTruncatedSize(size); + + PadLastBlock(56, 0x01); + CorrectEndianess(m_data, m_data, 56); + + m_data[7] = GetBitCountLo(); + + Transform(m_state, m_data); + CorrectEndianess(m_state, m_state, DigestSize()); + memcpy(hash, m_state, size); + + Restart(); // reinit for next use +} + +void Tiger::Transform (word64 *digest, const word64 *X) +{ +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86 + if (HasSSE2()) + { +#ifdef __GNUC__ + __asm__ __volatile__ + ( + ".intel_syntax noprefix;" + AS1( push ebx) +#else + #if _MSC_VER < 1300 + const word64 *t = table; + AS2( mov edx, t) + #else + AS2( lea edx, [table]) + #endif + AS2( mov eax, digest) + AS2( mov esi, X) +#endif + AS2( movq mm0, [eax]) + AS2( movq mm1, [eax+1*8]) + AS2( movq mm5, mm1) + AS2( movq mm2, [eax+2*8]) + AS2( movq mm7, [edx+4*2048+0*8]) + AS2( movq mm6, [edx+4*2048+1*8]) + AS2( mov ecx, esp) + AS2( and esp, 0xfffffff0) + AS2( sub esp, 8*8) + AS1( push ecx) + +#define SSE2_round(a,b,c,x,mul) \ + AS2( pxor c, [x])\ + AS2( movd ecx, c)\ + AS2( movzx edi, cl)\ + AS2( movq mm3, [edx+0*2048+edi*8])\ + AS2( movzx edi, ch)\ + AS2( movq mm4, [edx+3*2048+edi*8])\ + AS2( shr ecx, 16)\ + AS2( movzx edi, cl)\ + AS2( pxor mm3, [edx+1*2048+edi*8])\ + AS2( movzx edi, ch)\ + AS2( pxor mm4, [edx+2*2048+edi*8])\ + AS3( pextrw ecx, c, 2)\ + AS2( movzx edi, cl)\ + AS2( pxor mm3, [edx+2*2048+edi*8])\ + AS2( movzx edi, ch)\ + AS2( pxor mm4, [edx+1*2048+edi*8])\ + AS3( pextrw ecx, c, 3)\ + AS2( movzx edi, cl)\ + AS2( pxor mm3, [edx+3*2048+edi*8])\ + AS2( psubq a, mm3)\ + AS2( movzx edi, ch)\ + AS2( pxor mm4, [edx+0*2048+edi*8])\ + AS2( paddq b, mm4)\ + SSE2_mul_##mul(b) + +#define SSE2_mul_5(b) \ + AS2( movq mm3, b)\ + AS2( psllq b, 2)\ + AS2( paddq b, mm3) + +#define SSE2_mul_7(b) \ + AS2( movq mm3, b)\ + AS2( psllq b, 3)\ + AS2( psubq b, mm3) + +#define SSE2_mul_9(b) \ + AS2( movq mm3, b)\ + AS2( psllq b, 3)\ + AS2( paddq b, mm3) + +#define label2_5 1 +#define label2_7 2 +#define label2_9 3 + +#define SSE2_pass(A,B,C,mul,X) \ + AS2( xor ebx, ebx)\ + ASL(mul)\ + SSE2_round(A,B,C,X+0*8+ebx,mul)\ + SSE2_round(B,C,A,X+1*8+ebx,mul)\ + AS2( cmp ebx, 6*8)\ + ASJ( je, label2_##mul, f)\ + SSE2_round(C,A,B,X+2*8+ebx,mul)\ + AS2( add ebx, 3*8)\ + ASJ( jmp, mul, b)\ + ASL(label2_##mul) + +#define SSE2_key_schedule(Y,X) \ + AS2( movq mm3, [X+7*8])\ + AS2( pxor mm3, mm6)\ + AS2( movq mm4, [X+0*8])\ + AS2( psubq mm4, mm3)\ + AS2( movq [Y+0*8], mm4)\ + AS2( pxor mm4, [X+1*8])\ + AS2( movq mm3, mm4)\ + AS2( movq [Y+1*8], mm4)\ + AS2( paddq mm4, [X+2*8])\ + AS2( pxor mm3, mm7)\ + AS2( psllq mm3, 19)\ + AS2( movq [Y+2*8], mm4)\ + AS2( pxor mm3, mm4)\ + AS2( movq mm4, [X+3*8])\ + AS2( psubq mm4, mm3)\ + AS2( movq [Y+3*8], mm4)\ + AS2( pxor mm4, [X+4*8])\ + AS2( movq mm3, mm4)\ + AS2( movq [Y+4*8], mm4)\ + AS2( paddq mm4, [X+5*8])\ + AS2( pxor mm3, mm7)\ + AS2( psrlq mm3, 23)\ + AS2( movq [Y+5*8], mm4)\ + AS2( pxor mm3, mm4)\ + AS2( movq mm4, [X+6*8])\ + AS2( psubq mm4, mm3)\ + AS2( movq [Y+6*8], mm4)\ + AS2( pxor mm4, [X+7*8])\ + AS2( movq mm3, mm4)\ + AS2( movq [Y+7*8], mm4)\ + AS2( paddq mm4, [Y+0*8])\ + AS2( pxor mm3, mm7)\ + AS2( psllq mm3, 19)\ + AS2( movq [Y+0*8], mm4)\ + AS2( pxor mm3, mm4)\ + AS2( movq mm4, [Y+1*8])\ + AS2( psubq mm4, mm3)\ + AS2( movq [Y+1*8], mm4)\ + AS2( pxor mm4, [Y+2*8])\ + AS2( movq mm3, mm4)\ + AS2( movq [Y+2*8], mm4)\ + AS2( paddq mm4, [Y+3*8])\ + AS2( pxor mm3, mm7)\ + AS2( psrlq mm3, 23)\ + AS2( movq [Y+3*8], mm4)\ + AS2( pxor mm3, mm4)\ + AS2( movq mm4, [Y+4*8])\ + AS2( psubq mm4, mm3)\ + AS2( movq [Y+4*8], mm4)\ + AS2( pxor mm4, [Y+5*8])\ + AS2( movq [Y+5*8], mm4)\ + AS2( paddq mm4, [Y+6*8])\ + AS2( movq [Y+6*8], mm4)\ + AS2( pxor mm4, [edx+4*2048+2*8])\ + AS2( movq mm3, [Y+7*8])\ + AS2( psubq mm3, mm4)\ + AS2( movq [Y+7*8], mm3) + + SSE2_pass(mm0, mm1, mm2, 5, esi) + SSE2_key_schedule(esp+4, esi) + SSE2_pass(mm2, mm0, mm1, 7, esp+4) + SSE2_key_schedule(esp+4, esp+4) + SSE2_pass(mm1, mm2, mm0, 9, esp+4) + + AS2( pxor mm0, [eax+0*8]) + AS2( movq [eax+0*8], mm0) + AS2( psubq mm1, mm5) + AS2( movq [eax+1*8], mm1) + AS2( paddq mm2, [eax+2*8]) + AS2( movq [eax+2*8], mm2) + + AS1( pop esp) + AS1( emms) +#ifdef __GNUC__ + AS1( pop ebx) + ".att_syntax prefix;" + : + : "a" (digest), "S" (X), "d" (table) + : "%ecx", "%edi", "memory", "cc" + ); +#endif + } + else +#endif + { + word64 a = digest[0]; + word64 b = digest[1]; + word64 c = digest[2]; + word64 Y[8]; + +#define t1 (table) +#define t2 (table+256) +#define t3 (table+256*2) +#define t4 (table+256*3) + +#define round(a,b,c,x,mul) \ + c ^= x; \ + a -= t1[GETBYTE(c,0)] ^ t2[GETBYTE(c,2)] ^ t3[GETBYTE(c,4)] ^ t4[GETBYTE(c,6)]; \ + b += t4[GETBYTE(c,1)] ^ t3[GETBYTE(c,3)] ^ t2[GETBYTE(c,5)] ^ t1[GETBYTE(c,7)]; \ + b *= mul + +#define pass(a,b,c,mul,X) {\ + int i=0;\ + while (true)\ + {\ + round(a,b,c,X[i+0],mul); \ + round(b,c,a,X[i+1],mul); \ + if (i==6)\ + break;\ + round(c,a,b,X[i+2],mul); \ + i+=3;\ + }} + +#define key_schedule(Y,X) \ + Y[0] = X[0] - (X[7]^W64LIT(0xA5A5A5A5A5A5A5A5)); \ + Y[1] = X[1] ^ Y[0]; \ + Y[2] = X[2] + Y[1]; \ + Y[3] = X[3] - (Y[2] ^ ((~Y[1])<<19)); \ + Y[4] = X[4] ^ Y[3]; \ + Y[5] = X[5] + Y[4]; \ + Y[6] = X[6] - (Y[5] ^ ((~Y[4])>>23)); \ + Y[7] = X[7] ^ Y[6]; \ + Y[0] += Y[7]; \ + Y[1] -= Y[0] ^ ((~Y[7])<<19); \ + Y[2] ^= Y[1]; \ + Y[3] += Y[2]; \ + Y[4] -= Y[3] ^ ((~Y[2])>>23); \ + Y[5] ^= Y[4]; \ + Y[6] += Y[5]; \ + Y[7] -= Y[6] ^ W64LIT(0x0123456789ABCDEF) + + pass(a,b,c,5,X); + key_schedule(Y,X); + pass(c,a,b,7,Y); + key_schedule(Y,Y); + pass(b,c,a,9,Y); + + digest[0] = a ^ digest[0]; + digest[1] = b - digest[1]; + digest[2] = c + digest[2]; + } +} + +NAMESPACE_END diff --git a/src-cryptopp/tiger.h b/src-cryptopp/tiger.h new file mode 100644 index 0000000..5f6e941 --- /dev/null +++ b/src-cryptopp/tiger.h @@ -0,0 +1,24 @@ +#ifndef CRYPTOPP_TIGER_H +#define CRYPTOPP_TIGER_H + +#include "config.h" +#include "iterhash.h" + +NAMESPACE_BEGIN(CryptoPP) + +/// Tiger +class Tiger : public IteratedHashWithStaticTransform +{ +public: + static void InitState(HashWordType *state); + static void Transform(word64 *digest, const word64 *data); + void TruncatedFinal(byte *hash, size_t size); + static const char * StaticAlgorithmName() {return "Tiger";} + +protected: + static const word64 table[4*256+3]; +}; + +NAMESPACE_END + +#endif diff --git a/src-cryptopp/tigertab.cpp b/src-cryptopp/tigertab.cpp new file mode 100644 index 0000000..5c1595b --- /dev/null +++ b/src-cryptopp/tigertab.cpp @@ -0,0 +1,525 @@ +#include "pch.h" +#include "tiger.h" + +NAMESPACE_BEGIN(CryptoPP) + +const word64 Tiger::table[4*256+3] = +{ + W64LIT(0x02AAB17CF7E90C5E) /* 0 */, W64LIT(0xAC424B03E243A8EC) /* 1 */, + W64LIT(0x72CD5BE30DD5FCD3) /* 2 */, W64LIT(0x6D019B93F6F97F3A) /* 3 */, + W64LIT(0xCD9978FFD21F9193) /* 4 */, W64LIT(0x7573A1C9708029E2) /* 5 */, + W64LIT(0xB164326B922A83C3) /* 6 */, W64LIT(0x46883EEE04915870) /* 7 */, + W64LIT(0xEAACE3057103ECE6) /* 8 */, W64LIT(0xC54169B808A3535C) /* 9 */, + W64LIT(0x4CE754918DDEC47C) /* 10 */, W64LIT(0x0AA2F4DFDC0DF40C) /* 11 */, + W64LIT(0x10B76F18A74DBEFA) /* 12 */, W64LIT(0xC6CCB6235AD1AB6A) /* 13 */, + W64LIT(0x13726121572FE2FF) /* 14 */, W64LIT(0x1A488C6F199D921E) /* 15 */, + W64LIT(0x4BC9F9F4DA0007CA) /* 16 */, W64LIT(0x26F5E6F6E85241C7) /* 17 */, + W64LIT(0x859079DBEA5947B6) /* 18 */, W64LIT(0x4F1885C5C99E8C92) /* 19 */, + W64LIT(0xD78E761EA96F864B) /* 20 */, W64LIT(0x8E36428C52B5C17D) /* 21 */, + W64LIT(0x69CF6827373063C1) /* 22 */, W64LIT(0xB607C93D9BB4C56E) /* 23 */, + W64LIT(0x7D820E760E76B5EA) /* 24 */, W64LIT(0x645C9CC6F07FDC42) /* 25 */, + W64LIT(0xBF38A078243342E0) /* 26 */, W64LIT(0x5F6B343C9D2E7D04) /* 27 */, + W64LIT(0xF2C28AEB600B0EC6) /* 28 */, W64LIT(0x6C0ED85F7254BCAC) /* 29 */, + W64LIT(0x71592281A4DB4FE5) /* 30 */, W64LIT(0x1967FA69CE0FED9F) /* 31 */, + W64LIT(0xFD5293F8B96545DB) /* 32 */, W64LIT(0xC879E9D7F2A7600B) /* 33 */, + W64LIT(0x860248920193194E) /* 34 */, W64LIT(0xA4F9533B2D9CC0B3) /* 35 */, + W64LIT(0x9053836C15957613) /* 36 */, W64LIT(0xDB6DCF8AFC357BF1) /* 37 */, + W64LIT(0x18BEEA7A7A370F57) /* 38 */, W64LIT(0x037117CA50B99066) /* 39 */, + W64LIT(0x6AB30A9774424A35) /* 40 */, W64LIT(0xF4E92F02E325249B) /* 41 */, + W64LIT(0x7739DB07061CCAE1) /* 42 */, W64LIT(0xD8F3B49CECA42A05) /* 43 */, + W64LIT(0xBD56BE3F51382F73) /* 44 */, W64LIT(0x45FAED5843B0BB28) /* 45 */, + W64LIT(0x1C813D5C11BF1F83) /* 46 */, W64LIT(0x8AF0E4B6D75FA169) /* 47 */, + W64LIT(0x33EE18A487AD9999) /* 48 */, W64LIT(0x3C26E8EAB1C94410) /* 49 */, + W64LIT(0xB510102BC0A822F9) /* 50 */, W64LIT(0x141EEF310CE6123B) /* 51 */, + W64LIT(0xFC65B90059DDB154) /* 52 */, W64LIT(0xE0158640C5E0E607) /* 53 */, + W64LIT(0x884E079826C3A3CF) /* 54 */, W64LIT(0x930D0D9523C535FD) /* 55 */, + W64LIT(0x35638D754E9A2B00) /* 56 */, W64LIT(0x4085FCCF40469DD5) /* 57 */, + W64LIT(0xC4B17AD28BE23A4C) /* 58 */, W64LIT(0xCAB2F0FC6A3E6A2E) /* 59 */, + W64LIT(0x2860971A6B943FCD) /* 60 */, W64LIT(0x3DDE6EE212E30446) /* 61 */, + W64LIT(0x6222F32AE01765AE) /* 62 */, W64LIT(0x5D550BB5478308FE) /* 63 */, + W64LIT(0xA9EFA98DA0EDA22A) /* 64 */, W64LIT(0xC351A71686C40DA7) /* 65 */, + W64LIT(0x1105586D9C867C84) /* 66 */, W64LIT(0xDCFFEE85FDA22853) /* 67 */, + W64LIT(0xCCFBD0262C5EEF76) /* 68 */, W64LIT(0xBAF294CB8990D201) /* 69 */, + W64LIT(0xE69464F52AFAD975) /* 70 */, W64LIT(0x94B013AFDF133E14) /* 71 */, + W64LIT(0x06A7D1A32823C958) /* 72 */, W64LIT(0x6F95FE5130F61119) /* 73 */, + W64LIT(0xD92AB34E462C06C0) /* 74 */, W64LIT(0xED7BDE33887C71D2) /* 75 */, + W64LIT(0x79746D6E6518393E) /* 76 */, W64LIT(0x5BA419385D713329) /* 77 */, + W64LIT(0x7C1BA6B948A97564) /* 78 */, W64LIT(0x31987C197BFDAC67) /* 79 */, + W64LIT(0xDE6C23C44B053D02) /* 80 */, W64LIT(0x581C49FED002D64D) /* 81 */, + W64LIT(0xDD474D6338261571) /* 82 */, W64LIT(0xAA4546C3E473D062) /* 83 */, + W64LIT(0x928FCE349455F860) /* 84 */, W64LIT(0x48161BBACAAB94D9) /* 85 */, + W64LIT(0x63912430770E6F68) /* 86 */, W64LIT(0x6EC8A5E602C6641C) /* 87 */, + W64LIT(0x87282515337DDD2B) /* 88 */, W64LIT(0x2CDA6B42034B701B) /* 89 */, + W64LIT(0xB03D37C181CB096D) /* 90 */, W64LIT(0xE108438266C71C6F) /* 91 */, + W64LIT(0x2B3180C7EB51B255) /* 92 */, W64LIT(0xDF92B82F96C08BBC) /* 93 */, + W64LIT(0x5C68C8C0A632F3BA) /* 94 */, W64LIT(0x5504CC861C3D0556) /* 95 */, + W64LIT(0xABBFA4E55FB26B8F) /* 96 */, W64LIT(0x41848B0AB3BACEB4) /* 97 */, + W64LIT(0xB334A273AA445D32) /* 98 */, W64LIT(0xBCA696F0A85AD881) /* 99 */, + W64LIT(0x24F6EC65B528D56C) /* 100 */, W64LIT(0x0CE1512E90F4524A) /* 101 */, + W64LIT(0x4E9DD79D5506D35A) /* 102 */, W64LIT(0x258905FAC6CE9779) /* 103 */, + W64LIT(0x2019295B3E109B33) /* 104 */, W64LIT(0xF8A9478B73A054CC) /* 105 */, + W64LIT(0x2924F2F934417EB0) /* 106 */, W64LIT(0x3993357D536D1BC4) /* 107 */, + W64LIT(0x38A81AC21DB6FF8B) /* 108 */, W64LIT(0x47C4FBF17D6016BF) /* 109 */, + W64LIT(0x1E0FAADD7667E3F5) /* 110 */, W64LIT(0x7ABCFF62938BEB96) /* 111 */, + W64LIT(0xA78DAD948FC179C9) /* 112 */, W64LIT(0x8F1F98B72911E50D) /* 113 */, + W64LIT(0x61E48EAE27121A91) /* 114 */, W64LIT(0x4D62F7AD31859808) /* 115 */, + W64LIT(0xECEBA345EF5CEAEB) /* 116 */, W64LIT(0xF5CEB25EBC9684CE) /* 117 */, + W64LIT(0xF633E20CB7F76221) /* 118 */, W64LIT(0xA32CDF06AB8293E4) /* 119 */, + W64LIT(0x985A202CA5EE2CA4) /* 120 */, W64LIT(0xCF0B8447CC8A8FB1) /* 121 */, + W64LIT(0x9F765244979859A3) /* 122 */, W64LIT(0xA8D516B1A1240017) /* 123 */, + W64LIT(0x0BD7BA3EBB5DC726) /* 124 */, W64LIT(0xE54BCA55B86ADB39) /* 125 */, + W64LIT(0x1D7A3AFD6C478063) /* 126 */, W64LIT(0x519EC608E7669EDD) /* 127 */, + W64LIT(0x0E5715A2D149AA23) /* 128 */, W64LIT(0x177D4571848FF194) /* 129 */, + W64LIT(0xEEB55F3241014C22) /* 130 */, W64LIT(0x0F5E5CA13A6E2EC2) /* 131 */, + W64LIT(0x8029927B75F5C361) /* 132 */, W64LIT(0xAD139FABC3D6E436) /* 133 */, + W64LIT(0x0D5DF1A94CCF402F) /* 134 */, W64LIT(0x3E8BD948BEA5DFC8) /* 135 */, + W64LIT(0xA5A0D357BD3FF77E) /* 136 */, W64LIT(0xA2D12E251F74F645) /* 137 */, + W64LIT(0x66FD9E525E81A082) /* 138 */, W64LIT(0x2E0C90CE7F687A49) /* 139 */, + W64LIT(0xC2E8BCBEBA973BC5) /* 140 */, W64LIT(0x000001BCE509745F) /* 141 */, + W64LIT(0x423777BBE6DAB3D6) /* 142 */, W64LIT(0xD1661C7EAEF06EB5) /* 143 */, + W64LIT(0xA1781F354DAACFD8) /* 144 */, W64LIT(0x2D11284A2B16AFFC) /* 145 */, + W64LIT(0xF1FC4F67FA891D1F) /* 146 */, W64LIT(0x73ECC25DCB920ADA) /* 147 */, + W64LIT(0xAE610C22C2A12651) /* 148 */, W64LIT(0x96E0A810D356B78A) /* 149 */, + W64LIT(0x5A9A381F2FE7870F) /* 150 */, W64LIT(0xD5AD62EDE94E5530) /* 151 */, + W64LIT(0xD225E5E8368D1427) /* 152 */, W64LIT(0x65977B70C7AF4631) /* 153 */, + W64LIT(0x99F889B2DE39D74F) /* 154 */, W64LIT(0x233F30BF54E1D143) /* 155 */, + W64LIT(0x9A9675D3D9A63C97) /* 156 */, W64LIT(0x5470554FF334F9A8) /* 157 */, + W64LIT(0x166ACB744A4F5688) /* 158 */, W64LIT(0x70C74CAAB2E4AEAD) /* 159 */, + W64LIT(0xF0D091646F294D12) /* 160 */, W64LIT(0x57B82A89684031D1) /* 161 */, + W64LIT(0xEFD95A5A61BE0B6B) /* 162 */, W64LIT(0x2FBD12E969F2F29A) /* 163 */, + W64LIT(0x9BD37013FEFF9FE8) /* 164 */, W64LIT(0x3F9B0404D6085A06) /* 165 */, + W64LIT(0x4940C1F3166CFE15) /* 166 */, W64LIT(0x09542C4DCDF3DEFB) /* 167 */, + W64LIT(0xB4C5218385CD5CE3) /* 168 */, W64LIT(0xC935B7DC4462A641) /* 169 */, + W64LIT(0x3417F8A68ED3B63F) /* 170 */, W64LIT(0xB80959295B215B40) /* 171 */, + W64LIT(0xF99CDAEF3B8C8572) /* 172 */, W64LIT(0x018C0614F8FCB95D) /* 173 */, + W64LIT(0x1B14ACCD1A3ACDF3) /* 174 */, W64LIT(0x84D471F200BB732D) /* 175 */, + W64LIT(0xC1A3110E95E8DA16) /* 176 */, W64LIT(0x430A7220BF1A82B8) /* 177 */, + W64LIT(0xB77E090D39DF210E) /* 178 */, W64LIT(0x5EF4BD9F3CD05E9D) /* 179 */, + W64LIT(0x9D4FF6DA7E57A444) /* 180 */, W64LIT(0xDA1D60E183D4A5F8) /* 181 */, + W64LIT(0xB287C38417998E47) /* 182 */, W64LIT(0xFE3EDC121BB31886) /* 183 */, + W64LIT(0xC7FE3CCC980CCBEF) /* 184 */, W64LIT(0xE46FB590189BFD03) /* 185 */, + W64LIT(0x3732FD469A4C57DC) /* 186 */, W64LIT(0x7EF700A07CF1AD65) /* 187 */, + W64LIT(0x59C64468A31D8859) /* 188 */, W64LIT(0x762FB0B4D45B61F6) /* 189 */, + W64LIT(0x155BAED099047718) /* 190 */, W64LIT(0x68755E4C3D50BAA6) /* 191 */, + W64LIT(0xE9214E7F22D8B4DF) /* 192 */, W64LIT(0x2ADDBF532EAC95F4) /* 193 */, + W64LIT(0x32AE3909B4BD0109) /* 194 */, W64LIT(0x834DF537B08E3450) /* 195 */, + W64LIT(0xFA209DA84220728D) /* 196 */, W64LIT(0x9E691D9B9EFE23F7) /* 197 */, + W64LIT(0x0446D288C4AE8D7F) /* 198 */, W64LIT(0x7B4CC524E169785B) /* 199 */, + W64LIT(0x21D87F0135CA1385) /* 200 */, W64LIT(0xCEBB400F137B8AA5) /* 201 */, + W64LIT(0x272E2B66580796BE) /* 202 */, W64LIT(0x3612264125C2B0DE) /* 203 */, + W64LIT(0x057702BDAD1EFBB2) /* 204 */, W64LIT(0xD4BABB8EACF84BE9) /* 205 */, + W64LIT(0x91583139641BC67B) /* 206 */, W64LIT(0x8BDC2DE08036E024) /* 207 */, + W64LIT(0x603C8156F49F68ED) /* 208 */, W64LIT(0xF7D236F7DBEF5111) /* 209 */, + W64LIT(0x9727C4598AD21E80) /* 210 */, W64LIT(0xA08A0896670A5FD7) /* 211 */, + W64LIT(0xCB4A8F4309EBA9CB) /* 212 */, W64LIT(0x81AF564B0F7036A1) /* 213 */, + W64LIT(0xC0B99AA778199ABD) /* 214 */, W64LIT(0x959F1EC83FC8E952) /* 215 */, + W64LIT(0x8C505077794A81B9) /* 216 */, W64LIT(0x3ACAAF8F056338F0) /* 217 */, + W64LIT(0x07B43F50627A6778) /* 218 */, W64LIT(0x4A44AB49F5ECCC77) /* 219 */, + W64LIT(0x3BC3D6E4B679EE98) /* 220 */, W64LIT(0x9CC0D4D1CF14108C) /* 221 */, + W64LIT(0x4406C00B206BC8A0) /* 222 */, W64LIT(0x82A18854C8D72D89) /* 223 */, + W64LIT(0x67E366B35C3C432C) /* 224 */, W64LIT(0xB923DD61102B37F2) /* 225 */, + W64LIT(0x56AB2779D884271D) /* 226 */, W64LIT(0xBE83E1B0FF1525AF) /* 227 */, + W64LIT(0xFB7C65D4217E49A9) /* 228 */, W64LIT(0x6BDBE0E76D48E7D4) /* 229 */, + W64LIT(0x08DF828745D9179E) /* 230 */, W64LIT(0x22EA6A9ADD53BD34) /* 231 */, + W64LIT(0xE36E141C5622200A) /* 232 */, W64LIT(0x7F805D1B8CB750EE) /* 233 */, + W64LIT(0xAFE5C7A59F58E837) /* 234 */, W64LIT(0xE27F996A4FB1C23C) /* 235 */, + W64LIT(0xD3867DFB0775F0D0) /* 236 */, W64LIT(0xD0E673DE6E88891A) /* 237 */, + W64LIT(0x123AEB9EAFB86C25) /* 238 */, W64LIT(0x30F1D5D5C145B895) /* 239 */, + W64LIT(0xBB434A2DEE7269E7) /* 240 */, W64LIT(0x78CB67ECF931FA38) /* 241 */, + W64LIT(0xF33B0372323BBF9C) /* 242 */, W64LIT(0x52D66336FB279C74) /* 243 */, + W64LIT(0x505F33AC0AFB4EAA) /* 244 */, W64LIT(0xE8A5CD99A2CCE187) /* 245 */, + W64LIT(0x534974801E2D30BB) /* 246 */, W64LIT(0x8D2D5711D5876D90) /* 247 */, + W64LIT(0x1F1A412891BC038E) /* 248 */, W64LIT(0xD6E2E71D82E56648) /* 249 */, + W64LIT(0x74036C3A497732B7) /* 250 */, W64LIT(0x89B67ED96361F5AB) /* 251 */, + W64LIT(0xFFED95D8F1EA02A2) /* 252 */, W64LIT(0xE72B3BD61464D43D) /* 253 */, + W64LIT(0xA6300F170BDC4820) /* 254 */, W64LIT(0xEBC18760ED78A77A) /* 255 */, + W64LIT(0xE6A6BE5A05A12138) /* 256 */, W64LIT(0xB5A122A5B4F87C98) /* 257 */, + W64LIT(0x563C6089140B6990) /* 258 */, W64LIT(0x4C46CB2E391F5DD5) /* 259 */, + W64LIT(0xD932ADDBC9B79434) /* 260 */, W64LIT(0x08EA70E42015AFF5) /* 261 */, + W64LIT(0xD765A6673E478CF1) /* 262 */, W64LIT(0xC4FB757EAB278D99) /* 263 */, + W64LIT(0xDF11C6862D6E0692) /* 264 */, W64LIT(0xDDEB84F10D7F3B16) /* 265 */, + W64LIT(0x6F2EF604A665EA04) /* 266 */, W64LIT(0x4A8E0F0FF0E0DFB3) /* 267 */, + W64LIT(0xA5EDEEF83DBCBA51) /* 268 */, W64LIT(0xFC4F0A2A0EA4371E) /* 269 */, + W64LIT(0xE83E1DA85CB38429) /* 270 */, W64LIT(0xDC8FF882BA1B1CE2) /* 271 */, + W64LIT(0xCD45505E8353E80D) /* 272 */, W64LIT(0x18D19A00D4DB0717) /* 273 */, + W64LIT(0x34A0CFEDA5F38101) /* 274 */, W64LIT(0x0BE77E518887CAF2) /* 275 */, + W64LIT(0x1E341438B3C45136) /* 276 */, W64LIT(0xE05797F49089CCF9) /* 277 */, + W64LIT(0xFFD23F9DF2591D14) /* 278 */, W64LIT(0x543DDA228595C5CD) /* 279 */, + W64LIT(0x661F81FD99052A33) /* 280 */, W64LIT(0x8736E641DB0F7B76) /* 281 */, + W64LIT(0x15227725418E5307) /* 282 */, W64LIT(0xE25F7F46162EB2FA) /* 283 */, + W64LIT(0x48A8B2126C13D9FE) /* 284 */, W64LIT(0xAFDC541792E76EEA) /* 285 */, + W64LIT(0x03D912BFC6D1898F) /* 286 */, W64LIT(0x31B1AAFA1B83F51B) /* 287 */, + W64LIT(0xF1AC2796E42AB7D9) /* 288 */, W64LIT(0x40A3A7D7FCD2EBAC) /* 289 */, + W64LIT(0x1056136D0AFBBCC5) /* 290 */, W64LIT(0x7889E1DD9A6D0C85) /* 291 */, + W64LIT(0xD33525782A7974AA) /* 292 */, W64LIT(0xA7E25D09078AC09B) /* 293 */, + W64LIT(0xBD4138B3EAC6EDD0) /* 294 */, W64LIT(0x920ABFBE71EB9E70) /* 295 */, + W64LIT(0xA2A5D0F54FC2625C) /* 296 */, W64LIT(0xC054E36B0B1290A3) /* 297 */, + W64LIT(0xF6DD59FF62FE932B) /* 298 */, W64LIT(0x3537354511A8AC7D) /* 299 */, + W64LIT(0xCA845E9172FADCD4) /* 300 */, W64LIT(0x84F82B60329D20DC) /* 301 */, + W64LIT(0x79C62CE1CD672F18) /* 302 */, W64LIT(0x8B09A2ADD124642C) /* 303 */, + W64LIT(0xD0C1E96A19D9E726) /* 304 */, W64LIT(0x5A786A9B4BA9500C) /* 305 */, + W64LIT(0x0E020336634C43F3) /* 306 */, W64LIT(0xC17B474AEB66D822) /* 307 */, + W64LIT(0x6A731AE3EC9BAAC2) /* 308 */, W64LIT(0x8226667AE0840258) /* 309 */, + W64LIT(0x67D4567691CAECA5) /* 310 */, W64LIT(0x1D94155C4875ADB5) /* 311 */, + W64LIT(0x6D00FD985B813FDF) /* 312 */, W64LIT(0x51286EFCB774CD06) /* 313 */, + W64LIT(0x5E8834471FA744AF) /* 314 */, W64LIT(0xF72CA0AEE761AE2E) /* 315 */, + W64LIT(0xBE40E4CDAEE8E09A) /* 316 */, W64LIT(0xE9970BBB5118F665) /* 317 */, + W64LIT(0x726E4BEB33DF1964) /* 318 */, W64LIT(0x703B000729199762) /* 319 */, + W64LIT(0x4631D816F5EF30A7) /* 320 */, W64LIT(0xB880B5B51504A6BE) /* 321 */, + W64LIT(0x641793C37ED84B6C) /* 322 */, W64LIT(0x7B21ED77F6E97D96) /* 323 */, + W64LIT(0x776306312EF96B73) /* 324 */, W64LIT(0xAE528948E86FF3F4) /* 325 */, + W64LIT(0x53DBD7F286A3F8F8) /* 326 */, W64LIT(0x16CADCE74CFC1063) /* 327 */, + W64LIT(0x005C19BDFA52C6DD) /* 328 */, W64LIT(0x68868F5D64D46AD3) /* 329 */, + W64LIT(0x3A9D512CCF1E186A) /* 330 */, W64LIT(0x367E62C2385660AE) /* 331 */, + W64LIT(0xE359E7EA77DCB1D7) /* 332 */, W64LIT(0x526C0773749ABE6E) /* 333 */, + W64LIT(0x735AE5F9D09F734B) /* 334 */, W64LIT(0x493FC7CC8A558BA8) /* 335 */, + W64LIT(0xB0B9C1533041AB45) /* 336 */, W64LIT(0x321958BA470A59BD) /* 337 */, + W64LIT(0x852DB00B5F46C393) /* 338 */, W64LIT(0x91209B2BD336B0E5) /* 339 */, + W64LIT(0x6E604F7D659EF19F) /* 340 */, W64LIT(0xB99A8AE2782CCB24) /* 341 */, + W64LIT(0xCCF52AB6C814C4C7) /* 342 */, W64LIT(0x4727D9AFBE11727B) /* 343 */, + W64LIT(0x7E950D0C0121B34D) /* 344 */, W64LIT(0x756F435670AD471F) /* 345 */, + W64LIT(0xF5ADD442615A6849) /* 346 */, W64LIT(0x4E87E09980B9957A) /* 347 */, + W64LIT(0x2ACFA1DF50AEE355) /* 348 */, W64LIT(0xD898263AFD2FD556) /* 349 */, + W64LIT(0xC8F4924DD80C8FD6) /* 350 */, W64LIT(0xCF99CA3D754A173A) /* 351 */, + W64LIT(0xFE477BACAF91BF3C) /* 352 */, W64LIT(0xED5371F6D690C12D) /* 353 */, + W64LIT(0x831A5C285E687094) /* 354 */, W64LIT(0xC5D3C90A3708A0A4) /* 355 */, + W64LIT(0x0F7F903717D06580) /* 356 */, W64LIT(0x19F9BB13B8FDF27F) /* 357 */, + W64LIT(0xB1BD6F1B4D502843) /* 358 */, W64LIT(0x1C761BA38FFF4012) /* 359 */, + W64LIT(0x0D1530C4E2E21F3B) /* 360 */, W64LIT(0x8943CE69A7372C8A) /* 361 */, + W64LIT(0xE5184E11FEB5CE66) /* 362 */, W64LIT(0x618BDB80BD736621) /* 363 */, + W64LIT(0x7D29BAD68B574D0B) /* 364 */, W64LIT(0x81BB613E25E6FE5B) /* 365 */, + W64LIT(0x071C9C10BC07913F) /* 366 */, W64LIT(0xC7BEEB7909AC2D97) /* 367 */, + W64LIT(0xC3E58D353BC5D757) /* 368 */, W64LIT(0xEB017892F38F61E8) /* 369 */, + W64LIT(0xD4EFFB9C9B1CC21A) /* 370 */, W64LIT(0x99727D26F494F7AB) /* 371 */, + W64LIT(0xA3E063A2956B3E03) /* 372 */, W64LIT(0x9D4A8B9A4AA09C30) /* 373 */, + W64LIT(0x3F6AB7D500090FB4) /* 374 */, W64LIT(0x9CC0F2A057268AC0) /* 375 */, + W64LIT(0x3DEE9D2DEDBF42D1) /* 376 */, W64LIT(0x330F49C87960A972) /* 377 */, + W64LIT(0xC6B2720287421B41) /* 378 */, W64LIT(0x0AC59EC07C00369C) /* 379 */, + W64LIT(0xEF4EAC49CB353425) /* 380 */, W64LIT(0xF450244EEF0129D8) /* 381 */, + W64LIT(0x8ACC46E5CAF4DEB6) /* 382 */, W64LIT(0x2FFEAB63989263F7) /* 383 */, + W64LIT(0x8F7CB9FE5D7A4578) /* 384 */, W64LIT(0x5BD8F7644E634635) /* 385 */, + W64LIT(0x427A7315BF2DC900) /* 386 */, W64LIT(0x17D0C4AA2125261C) /* 387 */, + W64LIT(0x3992486C93518E50) /* 388 */, W64LIT(0xB4CBFEE0A2D7D4C3) /* 389 */, + W64LIT(0x7C75D6202C5DDD8D) /* 390 */, W64LIT(0xDBC295D8E35B6C61) /* 391 */, + W64LIT(0x60B369D302032B19) /* 392 */, W64LIT(0xCE42685FDCE44132) /* 393 */, + W64LIT(0x06F3DDB9DDF65610) /* 394 */, W64LIT(0x8EA4D21DB5E148F0) /* 395 */, + W64LIT(0x20B0FCE62FCD496F) /* 396 */, W64LIT(0x2C1B912358B0EE31) /* 397 */, + W64LIT(0xB28317B818F5A308) /* 398 */, W64LIT(0xA89C1E189CA6D2CF) /* 399 */, + W64LIT(0x0C6B18576AAADBC8) /* 400 */, W64LIT(0xB65DEAA91299FAE3) /* 401 */, + W64LIT(0xFB2B794B7F1027E7) /* 402 */, W64LIT(0x04E4317F443B5BEB) /* 403 */, + W64LIT(0x4B852D325939D0A6) /* 404 */, W64LIT(0xD5AE6BEEFB207FFC) /* 405 */, + W64LIT(0x309682B281C7D374) /* 406 */, W64LIT(0xBAE309A194C3B475) /* 407 */, + W64LIT(0x8CC3F97B13B49F05) /* 408 */, W64LIT(0x98A9422FF8293967) /* 409 */, + W64LIT(0x244B16B01076FF7C) /* 410 */, W64LIT(0xF8BF571C663D67EE) /* 411 */, + W64LIT(0x1F0D6758EEE30DA1) /* 412 */, W64LIT(0xC9B611D97ADEB9B7) /* 413 */, + W64LIT(0xB7AFD5887B6C57A2) /* 414 */, W64LIT(0x6290AE846B984FE1) /* 415 */, + W64LIT(0x94DF4CDEACC1A5FD) /* 416 */, W64LIT(0x058A5BD1C5483AFF) /* 417 */, + W64LIT(0x63166CC142BA3C37) /* 418 */, W64LIT(0x8DB8526EB2F76F40) /* 419 */, + W64LIT(0xE10880036F0D6D4E) /* 420 */, W64LIT(0x9E0523C9971D311D) /* 421 */, + W64LIT(0x45EC2824CC7CD691) /* 422 */, W64LIT(0x575B8359E62382C9) /* 423 */, + W64LIT(0xFA9E400DC4889995) /* 424 */, W64LIT(0xD1823ECB45721568) /* 425 */, + W64LIT(0xDAFD983B8206082F) /* 426 */, W64LIT(0xAA7D29082386A8CB) /* 427 */, + W64LIT(0x269FCD4403B87588) /* 428 */, W64LIT(0x1B91F5F728BDD1E0) /* 429 */, + W64LIT(0xE4669F39040201F6) /* 430 */, W64LIT(0x7A1D7C218CF04ADE) /* 431 */, + W64LIT(0x65623C29D79CE5CE) /* 432 */, W64LIT(0x2368449096C00BB1) /* 433 */, + W64LIT(0xAB9BF1879DA503BA) /* 434 */, W64LIT(0xBC23ECB1A458058E) /* 435 */, + W64LIT(0x9A58DF01BB401ECC) /* 436 */, W64LIT(0xA070E868A85F143D) /* 437 */, + W64LIT(0x4FF188307DF2239E) /* 438 */, W64LIT(0x14D565B41A641183) /* 439 */, + W64LIT(0xEE13337452701602) /* 440 */, W64LIT(0x950E3DCF3F285E09) /* 441 */, + W64LIT(0x59930254B9C80953) /* 442 */, W64LIT(0x3BF299408930DA6D) /* 443 */, + W64LIT(0xA955943F53691387) /* 444 */, W64LIT(0xA15EDECAA9CB8784) /* 445 */, + W64LIT(0x29142127352BE9A0) /* 446 */, W64LIT(0x76F0371FFF4E7AFB) /* 447 */, + W64LIT(0x0239F450274F2228) /* 448 */, W64LIT(0xBB073AF01D5E868B) /* 449 */, + W64LIT(0xBFC80571C10E96C1) /* 450 */, W64LIT(0xD267088568222E23) /* 451 */, + W64LIT(0x9671A3D48E80B5B0) /* 452 */, W64LIT(0x55B5D38AE193BB81) /* 453 */, + W64LIT(0x693AE2D0A18B04B8) /* 454 */, W64LIT(0x5C48B4ECADD5335F) /* 455 */, + W64LIT(0xFD743B194916A1CA) /* 456 */, W64LIT(0x2577018134BE98C4) /* 457 */, + W64LIT(0xE77987E83C54A4AD) /* 458 */, W64LIT(0x28E11014DA33E1B9) /* 459 */, + W64LIT(0x270CC59E226AA213) /* 460 */, W64LIT(0x71495F756D1A5F60) /* 461 */, + W64LIT(0x9BE853FB60AFEF77) /* 462 */, W64LIT(0xADC786A7F7443DBF) /* 463 */, + W64LIT(0x0904456173B29A82) /* 464 */, W64LIT(0x58BC7A66C232BD5E) /* 465 */, + W64LIT(0xF306558C673AC8B2) /* 466 */, W64LIT(0x41F639C6B6C9772A) /* 467 */, + W64LIT(0x216DEFE99FDA35DA) /* 468 */, W64LIT(0x11640CC71C7BE615) /* 469 */, + W64LIT(0x93C43694565C5527) /* 470 */, W64LIT(0xEA038E6246777839) /* 471 */, + W64LIT(0xF9ABF3CE5A3E2469) /* 472 */, W64LIT(0x741E768D0FD312D2) /* 473 */, + W64LIT(0x0144B883CED652C6) /* 474 */, W64LIT(0xC20B5A5BA33F8552) /* 475 */, + W64LIT(0x1AE69633C3435A9D) /* 476 */, W64LIT(0x97A28CA4088CFDEC) /* 477 */, + W64LIT(0x8824A43C1E96F420) /* 478 */, W64LIT(0x37612FA66EEEA746) /* 479 */, + W64LIT(0x6B4CB165F9CF0E5A) /* 480 */, W64LIT(0x43AA1C06A0ABFB4A) /* 481 */, + W64LIT(0x7F4DC26FF162796B) /* 482 */, W64LIT(0x6CBACC8E54ED9B0F) /* 483 */, + W64LIT(0xA6B7FFEFD2BB253E) /* 484 */, W64LIT(0x2E25BC95B0A29D4F) /* 485 */, + W64LIT(0x86D6A58BDEF1388C) /* 486 */, W64LIT(0xDED74AC576B6F054) /* 487 */, + W64LIT(0x8030BDBC2B45805D) /* 488 */, W64LIT(0x3C81AF70E94D9289) /* 489 */, + W64LIT(0x3EFF6DDA9E3100DB) /* 490 */, W64LIT(0xB38DC39FDFCC8847) /* 491 */, + W64LIT(0x123885528D17B87E) /* 492 */, W64LIT(0xF2DA0ED240B1B642) /* 493 */, + W64LIT(0x44CEFADCD54BF9A9) /* 494 */, W64LIT(0x1312200E433C7EE6) /* 495 */, + W64LIT(0x9FFCC84F3A78C748) /* 496 */, W64LIT(0xF0CD1F72248576BB) /* 497 */, + W64LIT(0xEC6974053638CFE4) /* 498 */, W64LIT(0x2BA7B67C0CEC4E4C) /* 499 */, + W64LIT(0xAC2F4DF3E5CE32ED) /* 500 */, W64LIT(0xCB33D14326EA4C11) /* 501 */, + W64LIT(0xA4E9044CC77E58BC) /* 502 */, W64LIT(0x5F513293D934FCEF) /* 503 */, + W64LIT(0x5DC9645506E55444) /* 504 */, W64LIT(0x50DE418F317DE40A) /* 505 */, + W64LIT(0x388CB31A69DDE259) /* 506 */, W64LIT(0x2DB4A83455820A86) /* 507 */, + W64LIT(0x9010A91E84711AE9) /* 508 */, W64LIT(0x4DF7F0B7B1498371) /* 509 */, + W64LIT(0xD62A2EABC0977179) /* 510 */, W64LIT(0x22FAC097AA8D5C0E) /* 511 */, + W64LIT(0xF49FCC2FF1DAF39B) /* 512 */, W64LIT(0x487FD5C66FF29281) /* 513 */, + W64LIT(0xE8A30667FCDCA83F) /* 514 */, W64LIT(0x2C9B4BE3D2FCCE63) /* 515 */, + W64LIT(0xDA3FF74B93FBBBC2) /* 516 */, W64LIT(0x2FA165D2FE70BA66) /* 517 */, + W64LIT(0xA103E279970E93D4) /* 518 */, W64LIT(0xBECDEC77B0E45E71) /* 519 */, + W64LIT(0xCFB41E723985E497) /* 520 */, W64LIT(0xB70AAA025EF75017) /* 521 */, + W64LIT(0xD42309F03840B8E0) /* 522 */, W64LIT(0x8EFC1AD035898579) /* 523 */, + W64LIT(0x96C6920BE2B2ABC5) /* 524 */, W64LIT(0x66AF4163375A9172) /* 525 */, + W64LIT(0x2174ABDCCA7127FB) /* 526 */, W64LIT(0xB33CCEA64A72FF41) /* 527 */, + W64LIT(0xF04A4933083066A5) /* 528 */, W64LIT(0x8D970ACDD7289AF5) /* 529 */, + W64LIT(0x8F96E8E031C8C25E) /* 530 */, W64LIT(0xF3FEC02276875D47) /* 531 */, + W64LIT(0xEC7BF310056190DD) /* 532 */, W64LIT(0xF5ADB0AEBB0F1491) /* 533 */, + W64LIT(0x9B50F8850FD58892) /* 534 */, W64LIT(0x4975488358B74DE8) /* 535 */, + W64LIT(0xA3354FF691531C61) /* 536 */, W64LIT(0x0702BBE481D2C6EE) /* 537 */, + W64LIT(0x89FB24057DEDED98) /* 538 */, W64LIT(0xAC3075138596E902) /* 539 */, + W64LIT(0x1D2D3580172772ED) /* 540 */, W64LIT(0xEB738FC28E6BC30D) /* 541 */, + W64LIT(0x5854EF8F63044326) /* 542 */, W64LIT(0x9E5C52325ADD3BBE) /* 543 */, + W64LIT(0x90AA53CF325C4623) /* 544 */, W64LIT(0xC1D24D51349DD067) /* 545 */, + W64LIT(0x2051CFEEA69EA624) /* 546 */, W64LIT(0x13220F0A862E7E4F) /* 547 */, + W64LIT(0xCE39399404E04864) /* 548 */, W64LIT(0xD9C42CA47086FCB7) /* 549 */, + W64LIT(0x685AD2238A03E7CC) /* 550 */, W64LIT(0x066484B2AB2FF1DB) /* 551 */, + W64LIT(0xFE9D5D70EFBF79EC) /* 552 */, W64LIT(0x5B13B9DD9C481854) /* 553 */, + W64LIT(0x15F0D475ED1509AD) /* 554 */, W64LIT(0x0BEBCD060EC79851) /* 555 */, + W64LIT(0xD58C6791183AB7F8) /* 556 */, W64LIT(0xD1187C5052F3EEE4) /* 557 */, + W64LIT(0xC95D1192E54E82FF) /* 558 */, W64LIT(0x86EEA14CB9AC6CA2) /* 559 */, + W64LIT(0x3485BEB153677D5D) /* 560 */, W64LIT(0xDD191D781F8C492A) /* 561 */, + W64LIT(0xF60866BAA784EBF9) /* 562 */, W64LIT(0x518F643BA2D08C74) /* 563 */, + W64LIT(0x8852E956E1087C22) /* 564 */, W64LIT(0xA768CB8DC410AE8D) /* 565 */, + W64LIT(0x38047726BFEC8E1A) /* 566 */, W64LIT(0xA67738B4CD3B45AA) /* 567 */, + W64LIT(0xAD16691CEC0DDE19) /* 568 */, W64LIT(0xC6D4319380462E07) /* 569 */, + W64LIT(0xC5A5876D0BA61938) /* 570 */, W64LIT(0x16B9FA1FA58FD840) /* 571 */, + W64LIT(0x188AB1173CA74F18) /* 572 */, W64LIT(0xABDA2F98C99C021F) /* 573 */, + W64LIT(0x3E0580AB134AE816) /* 574 */, W64LIT(0x5F3B05B773645ABB) /* 575 */, + W64LIT(0x2501A2BE5575F2F6) /* 576 */, W64LIT(0x1B2F74004E7E8BA9) /* 577 */, + W64LIT(0x1CD7580371E8D953) /* 578 */, W64LIT(0x7F6ED89562764E30) /* 579 */, + W64LIT(0xB15926FF596F003D) /* 580 */, W64LIT(0x9F65293DA8C5D6B9) /* 581 */, + W64LIT(0x6ECEF04DD690F84C) /* 582 */, W64LIT(0x4782275FFF33AF88) /* 583 */, + W64LIT(0xE41433083F820801) /* 584 */, W64LIT(0xFD0DFE409A1AF9B5) /* 585 */, + W64LIT(0x4325A3342CDB396B) /* 586 */, W64LIT(0x8AE77E62B301B252) /* 587 */, + W64LIT(0xC36F9E9F6655615A) /* 588 */, W64LIT(0x85455A2D92D32C09) /* 589 */, + W64LIT(0xF2C7DEA949477485) /* 590 */, W64LIT(0x63CFB4C133A39EBA) /* 591 */, + W64LIT(0x83B040CC6EBC5462) /* 592 */, W64LIT(0x3B9454C8FDB326B0) /* 593 */, + W64LIT(0x56F56A9E87FFD78C) /* 594 */, W64LIT(0x2DC2940D99F42BC6) /* 595 */, + W64LIT(0x98F7DF096B096E2D) /* 596 */, W64LIT(0x19A6E01E3AD852BF) /* 597 */, + W64LIT(0x42A99CCBDBD4B40B) /* 598 */, W64LIT(0xA59998AF45E9C559) /* 599 */, + W64LIT(0x366295E807D93186) /* 600 */, W64LIT(0x6B48181BFAA1F773) /* 601 */, + W64LIT(0x1FEC57E2157A0A1D) /* 602 */, W64LIT(0x4667446AF6201AD5) /* 603 */, + W64LIT(0xE615EBCACFB0F075) /* 604 */, W64LIT(0xB8F31F4F68290778) /* 605 */, + W64LIT(0x22713ED6CE22D11E) /* 606 */, W64LIT(0x3057C1A72EC3C93B) /* 607 */, + W64LIT(0xCB46ACC37C3F1F2F) /* 608 */, W64LIT(0xDBB893FD02AAF50E) /* 609 */, + W64LIT(0x331FD92E600B9FCF) /* 610 */, W64LIT(0xA498F96148EA3AD6) /* 611 */, + W64LIT(0xA8D8426E8B6A83EA) /* 612 */, W64LIT(0xA089B274B7735CDC) /* 613 */, + W64LIT(0x87F6B3731E524A11) /* 614 */, W64LIT(0x118808E5CBC96749) /* 615 */, + W64LIT(0x9906E4C7B19BD394) /* 616 */, W64LIT(0xAFED7F7E9B24A20C) /* 617 */, + W64LIT(0x6509EADEEB3644A7) /* 618 */, W64LIT(0x6C1EF1D3E8EF0EDE) /* 619 */, + W64LIT(0xB9C97D43E9798FB4) /* 620 */, W64LIT(0xA2F2D784740C28A3) /* 621 */, + W64LIT(0x7B8496476197566F) /* 622 */, W64LIT(0x7A5BE3E6B65F069D) /* 623 */, + W64LIT(0xF96330ED78BE6F10) /* 624 */, W64LIT(0xEEE60DE77A076A15) /* 625 */, + W64LIT(0x2B4BEE4AA08B9BD0) /* 626 */, W64LIT(0x6A56A63EC7B8894E) /* 627 */, + W64LIT(0x02121359BA34FEF4) /* 628 */, W64LIT(0x4CBF99F8283703FC) /* 629 */, + W64LIT(0x398071350CAF30C8) /* 630 */, W64LIT(0xD0A77A89F017687A) /* 631 */, + W64LIT(0xF1C1A9EB9E423569) /* 632 */, W64LIT(0x8C7976282DEE8199) /* 633 */, + W64LIT(0x5D1737A5DD1F7ABD) /* 634 */, W64LIT(0x4F53433C09A9FA80) /* 635 */, + W64LIT(0xFA8B0C53DF7CA1D9) /* 636 */, W64LIT(0x3FD9DCBC886CCB77) /* 637 */, + W64LIT(0xC040917CA91B4720) /* 638 */, W64LIT(0x7DD00142F9D1DCDF) /* 639 */, + W64LIT(0x8476FC1D4F387B58) /* 640 */, W64LIT(0x23F8E7C5F3316503) /* 641 */, + W64LIT(0x032A2244E7E37339) /* 642 */, W64LIT(0x5C87A5D750F5A74B) /* 643 */, + W64LIT(0x082B4CC43698992E) /* 644 */, W64LIT(0xDF917BECB858F63C) /* 645 */, + W64LIT(0x3270B8FC5BF86DDA) /* 646 */, W64LIT(0x10AE72BB29B5DD76) /* 647 */, + W64LIT(0x576AC94E7700362B) /* 648 */, W64LIT(0x1AD112DAC61EFB8F) /* 649 */, + W64LIT(0x691BC30EC5FAA427) /* 650 */, W64LIT(0xFF246311CC327143) /* 651 */, + W64LIT(0x3142368E30E53206) /* 652 */, W64LIT(0x71380E31E02CA396) /* 653 */, + W64LIT(0x958D5C960AAD76F1) /* 654 */, W64LIT(0xF8D6F430C16DA536) /* 655 */, + W64LIT(0xC8FFD13F1BE7E1D2) /* 656 */, W64LIT(0x7578AE66004DDBE1) /* 657 */, + W64LIT(0x05833F01067BE646) /* 658 */, W64LIT(0xBB34B5AD3BFE586D) /* 659 */, + W64LIT(0x095F34C9A12B97F0) /* 660 */, W64LIT(0x247AB64525D60CA8) /* 661 */, + W64LIT(0xDCDBC6F3017477D1) /* 662 */, W64LIT(0x4A2E14D4DECAD24D) /* 663 */, + W64LIT(0xBDB5E6D9BE0A1EEB) /* 664 */, W64LIT(0x2A7E70F7794301AB) /* 665 */, + W64LIT(0xDEF42D8A270540FD) /* 666 */, W64LIT(0x01078EC0A34C22C1) /* 667 */, + W64LIT(0xE5DE511AF4C16387) /* 668 */, W64LIT(0x7EBB3A52BD9A330A) /* 669 */, + W64LIT(0x77697857AA7D6435) /* 670 */, W64LIT(0x004E831603AE4C32) /* 671 */, + W64LIT(0xE7A21020AD78E312) /* 672 */, W64LIT(0x9D41A70C6AB420F2) /* 673 */, + W64LIT(0x28E06C18EA1141E6) /* 674 */, W64LIT(0xD2B28CBD984F6B28) /* 675 */, + W64LIT(0x26B75F6C446E9D83) /* 676 */, W64LIT(0xBA47568C4D418D7F) /* 677 */, + W64LIT(0xD80BADBFE6183D8E) /* 678 */, W64LIT(0x0E206D7F5F166044) /* 679 */, + W64LIT(0xE258A43911CBCA3E) /* 680 */, W64LIT(0x723A1746B21DC0BC) /* 681 */, + W64LIT(0xC7CAA854F5D7CDD3) /* 682 */, W64LIT(0x7CAC32883D261D9C) /* 683 */, + W64LIT(0x7690C26423BA942C) /* 684 */, W64LIT(0x17E55524478042B8) /* 685 */, + W64LIT(0xE0BE477656A2389F) /* 686 */, W64LIT(0x4D289B5E67AB2DA0) /* 687 */, + W64LIT(0x44862B9C8FBBFD31) /* 688 */, W64LIT(0xB47CC8049D141365) /* 689 */, + W64LIT(0x822C1B362B91C793) /* 690 */, W64LIT(0x4EB14655FB13DFD8) /* 691 */, + W64LIT(0x1ECBBA0714E2A97B) /* 692 */, W64LIT(0x6143459D5CDE5F14) /* 693 */, + W64LIT(0x53A8FBF1D5F0AC89) /* 694 */, W64LIT(0x97EA04D81C5E5B00) /* 695 */, + W64LIT(0x622181A8D4FDB3F3) /* 696 */, W64LIT(0xE9BCD341572A1208) /* 697 */, + W64LIT(0x1411258643CCE58A) /* 698 */, W64LIT(0x9144C5FEA4C6E0A4) /* 699 */, + W64LIT(0x0D33D06565CF620F) /* 700 */, W64LIT(0x54A48D489F219CA1) /* 701 */, + W64LIT(0xC43E5EAC6D63C821) /* 702 */, W64LIT(0xA9728B3A72770DAF) /* 703 */, + W64LIT(0xD7934E7B20DF87EF) /* 704 */, W64LIT(0xE35503B61A3E86E5) /* 705 */, + W64LIT(0xCAE321FBC819D504) /* 706 */, W64LIT(0x129A50B3AC60BFA6) /* 707 */, + W64LIT(0xCD5E68EA7E9FB6C3) /* 708 */, W64LIT(0xB01C90199483B1C7) /* 709 */, + W64LIT(0x3DE93CD5C295376C) /* 710 */, W64LIT(0xAED52EDF2AB9AD13) /* 711 */, + W64LIT(0x2E60F512C0A07884) /* 712 */, W64LIT(0xBC3D86A3E36210C9) /* 713 */, + W64LIT(0x35269D9B163951CE) /* 714 */, W64LIT(0x0C7D6E2AD0CDB5FA) /* 715 */, + W64LIT(0x59E86297D87F5733) /* 716 */, W64LIT(0x298EF221898DB0E7) /* 717 */, + W64LIT(0x55000029D1A5AA7E) /* 718 */, W64LIT(0x8BC08AE1B5061B45) /* 719 */, + W64LIT(0xC2C31C2B6C92703A) /* 720 */, W64LIT(0x94CC596BAF25EF42) /* 721 */, + W64LIT(0x0A1D73DB22540456) /* 722 */, W64LIT(0x04B6A0F9D9C4179A) /* 723 */, + W64LIT(0xEFFDAFA2AE3D3C60) /* 724 */, W64LIT(0xF7C8075BB49496C4) /* 725 */, + W64LIT(0x9CC5C7141D1CD4E3) /* 726 */, W64LIT(0x78BD1638218E5534) /* 727 */, + W64LIT(0xB2F11568F850246A) /* 728 */, W64LIT(0xEDFABCFA9502BC29) /* 729 */, + W64LIT(0x796CE5F2DA23051B) /* 730 */, W64LIT(0xAAE128B0DC93537C) /* 731 */, + W64LIT(0x3A493DA0EE4B29AE) /* 732 */, W64LIT(0xB5DF6B2C416895D7) /* 733 */, + W64LIT(0xFCABBD25122D7F37) /* 734 */, W64LIT(0x70810B58105DC4B1) /* 735 */, + W64LIT(0xE10FDD37F7882A90) /* 736 */, W64LIT(0x524DCAB5518A3F5C) /* 737 */, + W64LIT(0x3C9E85878451255B) /* 738 */, W64LIT(0x4029828119BD34E2) /* 739 */, + W64LIT(0x74A05B6F5D3CECCB) /* 740 */, W64LIT(0xB610021542E13ECA) /* 741 */, + W64LIT(0x0FF979D12F59E2AC) /* 742 */, W64LIT(0x6037DA27E4F9CC50) /* 743 */, + W64LIT(0x5E92975A0DF1847D) /* 744 */, W64LIT(0xD66DE190D3E623FE) /* 745 */, + W64LIT(0x5032D6B87B568048) /* 746 */, W64LIT(0x9A36B7CE8235216E) /* 747 */, + W64LIT(0x80272A7A24F64B4A) /* 748 */, W64LIT(0x93EFED8B8C6916F7) /* 749 */, + W64LIT(0x37DDBFF44CCE1555) /* 750 */, W64LIT(0x4B95DB5D4B99BD25) /* 751 */, + W64LIT(0x92D3FDA169812FC0) /* 752 */, W64LIT(0xFB1A4A9A90660BB6) /* 753 */, + W64LIT(0x730C196946A4B9B2) /* 754 */, W64LIT(0x81E289AA7F49DA68) /* 755 */, + W64LIT(0x64669A0F83B1A05F) /* 756 */, W64LIT(0x27B3FF7D9644F48B) /* 757 */, + W64LIT(0xCC6B615C8DB675B3) /* 758 */, W64LIT(0x674F20B9BCEBBE95) /* 759 */, + W64LIT(0x6F31238275655982) /* 760 */, W64LIT(0x5AE488713E45CF05) /* 761 */, + W64LIT(0xBF619F9954C21157) /* 762 */, W64LIT(0xEABAC46040A8EAE9) /* 763 */, + W64LIT(0x454C6FE9F2C0C1CD) /* 764 */, W64LIT(0x419CF6496412691C) /* 765 */, + W64LIT(0xD3DC3BEF265B0F70) /* 766 */, W64LIT(0x6D0E60F5C3578A9E) /* 767 */, + W64LIT(0x5B0E608526323C55) /* 768 */, W64LIT(0x1A46C1A9FA1B59F5) /* 769 */, + W64LIT(0xA9E245A17C4C8FFA) /* 770 */, W64LIT(0x65CA5159DB2955D7) /* 771 */, + W64LIT(0x05DB0A76CE35AFC2) /* 772 */, W64LIT(0x81EAC77EA9113D45) /* 773 */, + W64LIT(0x528EF88AB6AC0A0D) /* 774 */, W64LIT(0xA09EA253597BE3FF) /* 775 */, + W64LIT(0x430DDFB3AC48CD56) /* 776 */, W64LIT(0xC4B3A67AF45CE46F) /* 777 */, + W64LIT(0x4ECECFD8FBE2D05E) /* 778 */, W64LIT(0x3EF56F10B39935F0) /* 779 */, + W64LIT(0x0B22D6829CD619C6) /* 780 */, W64LIT(0x17FD460A74DF2069) /* 781 */, + W64LIT(0x6CF8CC8E8510ED40) /* 782 */, W64LIT(0xD6C824BF3A6ECAA7) /* 783 */, + W64LIT(0x61243D581A817049) /* 784 */, W64LIT(0x048BACB6BBC163A2) /* 785 */, + W64LIT(0xD9A38AC27D44CC32) /* 786 */, W64LIT(0x7FDDFF5BAAF410AB) /* 787 */, + W64LIT(0xAD6D495AA804824B) /* 788 */, W64LIT(0xE1A6A74F2D8C9F94) /* 789 */, + W64LIT(0xD4F7851235DEE8E3) /* 790 */, W64LIT(0xFD4B7F886540D893) /* 791 */, + W64LIT(0x247C20042AA4BFDA) /* 792 */, W64LIT(0x096EA1C517D1327C) /* 793 */, + W64LIT(0xD56966B4361A6685) /* 794 */, W64LIT(0x277DA5C31221057D) /* 795 */, + W64LIT(0x94D59893A43ACFF7) /* 796 */, W64LIT(0x64F0C51CCDC02281) /* 797 */, + W64LIT(0x3D33BCC4FF6189DB) /* 798 */, W64LIT(0xE005CB184CE66AF1) /* 799 */, + W64LIT(0xFF5CCD1D1DB99BEA) /* 800 */, W64LIT(0xB0B854A7FE42980F) /* 801 */, + W64LIT(0x7BD46A6A718D4B9F) /* 802 */, W64LIT(0xD10FA8CC22A5FD8C) /* 803 */, + W64LIT(0xD31484952BE4BD31) /* 804 */, W64LIT(0xC7FA975FCB243847) /* 805 */, + W64LIT(0x4886ED1E5846C407) /* 806 */, W64LIT(0x28CDDB791EB70B04) /* 807 */, + W64LIT(0xC2B00BE2F573417F) /* 808 */, W64LIT(0x5C9590452180F877) /* 809 */, + W64LIT(0x7A6BDDFFF370EB00) /* 810 */, W64LIT(0xCE509E38D6D9D6A4) /* 811 */, + W64LIT(0xEBEB0F00647FA702) /* 812 */, W64LIT(0x1DCC06CF76606F06) /* 813 */, + W64LIT(0xE4D9F28BA286FF0A) /* 814 */, W64LIT(0xD85A305DC918C262) /* 815 */, + W64LIT(0x475B1D8732225F54) /* 816 */, W64LIT(0x2D4FB51668CCB5FE) /* 817 */, + W64LIT(0xA679B9D9D72BBA20) /* 818 */, W64LIT(0x53841C0D912D43A5) /* 819 */, + W64LIT(0x3B7EAA48BF12A4E8) /* 820 */, W64LIT(0x781E0E47F22F1DDF) /* 821 */, + W64LIT(0xEFF20CE60AB50973) /* 822 */, W64LIT(0x20D261D19DFFB742) /* 823 */, + W64LIT(0x16A12B03062A2E39) /* 824 */, W64LIT(0x1960EB2239650495) /* 825 */, + W64LIT(0x251C16FED50EB8B8) /* 826 */, W64LIT(0x9AC0C330F826016E) /* 827 */, + W64LIT(0xED152665953E7671) /* 828 */, W64LIT(0x02D63194A6369570) /* 829 */, + W64LIT(0x5074F08394B1C987) /* 830 */, W64LIT(0x70BA598C90B25CE1) /* 831 */, + W64LIT(0x794A15810B9742F6) /* 832 */, W64LIT(0x0D5925E9FCAF8C6C) /* 833 */, + W64LIT(0x3067716CD868744E) /* 834 */, W64LIT(0x910AB077E8D7731B) /* 835 */, + W64LIT(0x6A61BBDB5AC42F61) /* 836 */, W64LIT(0x93513EFBF0851567) /* 837 */, + W64LIT(0xF494724B9E83E9D5) /* 838 */, W64LIT(0xE887E1985C09648D) /* 839 */, + W64LIT(0x34B1D3C675370CFD) /* 840 */, W64LIT(0xDC35E433BC0D255D) /* 841 */, + W64LIT(0xD0AAB84234131BE0) /* 842 */, W64LIT(0x08042A50B48B7EAF) /* 843 */, + W64LIT(0x9997C4EE44A3AB35) /* 844 */, W64LIT(0x829A7B49201799D0) /* 845 */, + W64LIT(0x263B8307B7C54441) /* 846 */, W64LIT(0x752F95F4FD6A6CA6) /* 847 */, + W64LIT(0x927217402C08C6E5) /* 848 */, W64LIT(0x2A8AB754A795D9EE) /* 849 */, + W64LIT(0xA442F7552F72943D) /* 850 */, W64LIT(0x2C31334E19781208) /* 851 */, + W64LIT(0x4FA98D7CEAEE6291) /* 852 */, W64LIT(0x55C3862F665DB309) /* 853 */, + W64LIT(0xBD0610175D53B1F3) /* 854 */, W64LIT(0x46FE6CB840413F27) /* 855 */, + W64LIT(0x3FE03792DF0CFA59) /* 856 */, W64LIT(0xCFE700372EB85E8F) /* 857 */, + W64LIT(0xA7BE29E7ADBCE118) /* 858 */, W64LIT(0xE544EE5CDE8431DD) /* 859 */, + W64LIT(0x8A781B1B41F1873E) /* 860 */, W64LIT(0xA5C94C78A0D2F0E7) /* 861 */, + W64LIT(0x39412E2877B60728) /* 862 */, W64LIT(0xA1265EF3AFC9A62C) /* 863 */, + W64LIT(0xBCC2770C6A2506C5) /* 864 */, W64LIT(0x3AB66DD5DCE1CE12) /* 865 */, + W64LIT(0xE65499D04A675B37) /* 866 */, W64LIT(0x7D8F523481BFD216) /* 867 */, + W64LIT(0x0F6F64FCEC15F389) /* 868 */, W64LIT(0x74EFBE618B5B13C8) /* 869 */, + W64LIT(0xACDC82B714273E1D) /* 870 */, W64LIT(0xDD40BFE003199D17) /* 871 */, + W64LIT(0x37E99257E7E061F8) /* 872 */, W64LIT(0xFA52626904775AAA) /* 873 */, + W64LIT(0x8BBBF63A463D56F9) /* 874 */, W64LIT(0xF0013F1543A26E64) /* 875 */, + W64LIT(0xA8307E9F879EC898) /* 876 */, W64LIT(0xCC4C27A4150177CC) /* 877 */, + W64LIT(0x1B432F2CCA1D3348) /* 878 */, W64LIT(0xDE1D1F8F9F6FA013) /* 879 */, + W64LIT(0x606602A047A7DDD6) /* 880 */, W64LIT(0xD237AB64CC1CB2C7) /* 881 */, + W64LIT(0x9B938E7225FCD1D3) /* 882 */, W64LIT(0xEC4E03708E0FF476) /* 883 */, + W64LIT(0xFEB2FBDA3D03C12D) /* 884 */, W64LIT(0xAE0BCED2EE43889A) /* 885 */, + W64LIT(0x22CB8923EBFB4F43) /* 886 */, W64LIT(0x69360D013CF7396D) /* 887 */, + W64LIT(0x855E3602D2D4E022) /* 888 */, W64LIT(0x073805BAD01F784C) /* 889 */, + W64LIT(0x33E17A133852F546) /* 890 */, W64LIT(0xDF4874058AC7B638) /* 891 */, + W64LIT(0xBA92B29C678AA14A) /* 892 */, W64LIT(0x0CE89FC76CFAADCD) /* 893 */, + W64LIT(0x5F9D4E0908339E34) /* 894 */, W64LIT(0xF1AFE9291F5923B9) /* 895 */, + W64LIT(0x6E3480F60F4A265F) /* 896 */, W64LIT(0xEEBF3A2AB29B841C) /* 897 */, + W64LIT(0xE21938A88F91B4AD) /* 898 */, W64LIT(0x57DFEFF845C6D3C3) /* 899 */, + W64LIT(0x2F006B0BF62CAAF2) /* 900 */, W64LIT(0x62F479EF6F75EE78) /* 901 */, + W64LIT(0x11A55AD41C8916A9) /* 902 */, W64LIT(0xF229D29084FED453) /* 903 */, + W64LIT(0x42F1C27B16B000E6) /* 904 */, W64LIT(0x2B1F76749823C074) /* 905 */, + W64LIT(0x4B76ECA3C2745360) /* 906 */, W64LIT(0x8C98F463B91691BD) /* 907 */, + W64LIT(0x14BCC93CF1ADE66A) /* 908 */, W64LIT(0x8885213E6D458397) /* 909 */, + W64LIT(0x8E177DF0274D4711) /* 910 */, W64LIT(0xB49B73B5503F2951) /* 911 */, + W64LIT(0x10168168C3F96B6B) /* 912 */, W64LIT(0x0E3D963B63CAB0AE) /* 913 */, + W64LIT(0x8DFC4B5655A1DB14) /* 914 */, W64LIT(0xF789F1356E14DE5C) /* 915 */, + W64LIT(0x683E68AF4E51DAC1) /* 916 */, W64LIT(0xC9A84F9D8D4B0FD9) /* 917 */, + W64LIT(0x3691E03F52A0F9D1) /* 918 */, W64LIT(0x5ED86E46E1878E80) /* 919 */, + W64LIT(0x3C711A0E99D07150) /* 920 */, W64LIT(0x5A0865B20C4E9310) /* 921 */, + W64LIT(0x56FBFC1FE4F0682E) /* 922 */, W64LIT(0xEA8D5DE3105EDF9B) /* 923 */, + W64LIT(0x71ABFDB12379187A) /* 924 */, W64LIT(0x2EB99DE1BEE77B9C) /* 925 */, + W64LIT(0x21ECC0EA33CF4523) /* 926 */, W64LIT(0x59A4D7521805C7A1) /* 927 */, + W64LIT(0x3896F5EB56AE7C72) /* 928 */, W64LIT(0xAA638F3DB18F75DC) /* 929 */, + W64LIT(0x9F39358DABE9808E) /* 930 */, W64LIT(0xB7DEFA91C00B72AC) /* 931 */, + W64LIT(0x6B5541FD62492D92) /* 932 */, W64LIT(0x6DC6DEE8F92E4D5B) /* 933 */, + W64LIT(0x353F57ABC4BEEA7E) /* 934 */, W64LIT(0x735769D6DA5690CE) /* 935 */, + W64LIT(0x0A234AA642391484) /* 936 */, W64LIT(0xF6F9508028F80D9D) /* 937 */, + W64LIT(0xB8E319A27AB3F215) /* 938 */, W64LIT(0x31AD9C1151341A4D) /* 939 */, + W64LIT(0x773C22A57BEF5805) /* 940 */, W64LIT(0x45C7561A07968633) /* 941 */, + W64LIT(0xF913DA9E249DBE36) /* 942 */, W64LIT(0xDA652D9B78A64C68) /* 943 */, + W64LIT(0x4C27A97F3BC334EF) /* 944 */, W64LIT(0x76621220E66B17F4) /* 945 */, + W64LIT(0x967743899ACD7D0B) /* 946 */, W64LIT(0xF3EE5BCAE0ED6782) /* 947 */, + W64LIT(0x409F753600C879FC) /* 948 */, W64LIT(0x06D09A39B5926DB6) /* 949 */, + W64LIT(0x6F83AEB0317AC588) /* 950 */, W64LIT(0x01E6CA4A86381F21) /* 951 */, + W64LIT(0x66FF3462D19F3025) /* 952 */, W64LIT(0x72207C24DDFD3BFB) /* 953 */, + W64LIT(0x4AF6B6D3E2ECE2EB) /* 954 */, W64LIT(0x9C994DBEC7EA08DE) /* 955 */, + W64LIT(0x49ACE597B09A8BC4) /* 956 */, W64LIT(0xB38C4766CF0797BA) /* 957 */, + W64LIT(0x131B9373C57C2A75) /* 958 */, W64LIT(0xB1822CCE61931E58) /* 959 */, + W64LIT(0x9D7555B909BA1C0C) /* 960 */, W64LIT(0x127FAFDD937D11D2) /* 961 */, + W64LIT(0x29DA3BADC66D92E4) /* 962 */, W64LIT(0xA2C1D57154C2ECBC) /* 963 */, + W64LIT(0x58C5134D82F6FE24) /* 964 */, W64LIT(0x1C3AE3515B62274F) /* 965 */, + W64LIT(0xE907C82E01CB8126) /* 966 */, W64LIT(0xF8ED091913E37FCB) /* 967 */, + W64LIT(0x3249D8F9C80046C9) /* 968 */, W64LIT(0x80CF9BEDE388FB63) /* 969 */, + W64LIT(0x1881539A116CF19E) /* 970 */, W64LIT(0x5103F3F76BD52457) /* 971 */, + W64LIT(0x15B7E6F5AE47F7A8) /* 972 */, W64LIT(0xDBD7C6DED47E9CCF) /* 973 */, + W64LIT(0x44E55C410228BB1A) /* 974 */, W64LIT(0xB647D4255EDB4E99) /* 975 */, + W64LIT(0x5D11882BB8AAFC30) /* 976 */, W64LIT(0xF5098BBB29D3212A) /* 977 */, + W64LIT(0x8FB5EA14E90296B3) /* 978 */, W64LIT(0x677B942157DD025A) /* 979 */, + W64LIT(0xFB58E7C0A390ACB5) /* 980 */, W64LIT(0x89D3674C83BD4A01) /* 981 */, + W64LIT(0x9E2DA4DF4BF3B93B) /* 982 */, W64LIT(0xFCC41E328CAB4829) /* 983 */, + W64LIT(0x03F38C96BA582C52) /* 984 */, W64LIT(0xCAD1BDBD7FD85DB2) /* 985 */, + W64LIT(0xBBB442C16082AE83) /* 986 */, W64LIT(0xB95FE86BA5DA9AB0) /* 987 */, + W64LIT(0xB22E04673771A93F) /* 988 */, W64LIT(0x845358C9493152D8) /* 989 */, + W64LIT(0xBE2A488697B4541E) /* 990 */, W64LIT(0x95A2DC2DD38E6966) /* 991 */, + W64LIT(0xC02C11AC923C852B) /* 992 */, W64LIT(0x2388B1990DF2A87B) /* 993 */, + W64LIT(0x7C8008FA1B4F37BE) /* 994 */, W64LIT(0x1F70D0C84D54E503) /* 995 */, + W64LIT(0x5490ADEC7ECE57D4) /* 996 */, W64LIT(0x002B3C27D9063A3A) /* 997 */, + W64LIT(0x7EAEA3848030A2BF) /* 998 */, W64LIT(0xC602326DED2003C0) /* 999 */, + W64LIT(0x83A7287D69A94086) /* 1000 */, W64LIT(0xC57A5FCB30F57A8A) /* 1001 */, + W64LIT(0xB56844E479EBE779) /* 1002 */, W64LIT(0xA373B40F05DCBCE9) /* 1003 */, + W64LIT(0xD71A786E88570EE2) /* 1004 */, W64LIT(0x879CBACDBDE8F6A0) /* 1005 */, + W64LIT(0x976AD1BCC164A32F) /* 1006 */, W64LIT(0xAB21E25E9666D78B) /* 1007 */, + W64LIT(0x901063AAE5E5C33C) /* 1008 */, W64LIT(0x9818B34448698D90) /* 1009 */, + W64LIT(0xE36487AE3E1E8ABB) /* 1010 */, W64LIT(0xAFBDF931893BDCB4) /* 1011 */, + W64LIT(0x6345A0DC5FBBD519) /* 1012 */, W64LIT(0x8628FE269B9465CA) /* 1013 */, + W64LIT(0x1E5D01603F9C51EC) /* 1014 */, W64LIT(0x4DE44006A15049B7) /* 1015 */, + W64LIT(0xBF6C70E5F776CBB1) /* 1016 */, W64LIT(0x411218F2EF552BED) /* 1017 */, + W64LIT(0xCB0C0708705A36A3) /* 1018 */, W64LIT(0xE74D14754F986044) /* 1019 */, + W64LIT(0xCD56D9430EA8280E) /* 1020 */, W64LIT(0xC12591D7535F5065) /* 1021 */, + W64LIT(0xC83223F1720AEF96) /* 1022 */, W64LIT(0xC3A0396F7363A51F) /* 1023 */, + W64LIT(0xffffffffffffffff), + W64LIT(0xA5A5A5A5A5A5A5A5), + W64LIT(0x0123456789ABCDEF), +}; + +NAMESPACE_END diff --git a/src-cryptopp/trdlocal.h b/src-cryptopp/trdlocal.h new file mode 100644 index 0000000..92d244a --- /dev/null +++ b/src-cryptopp/trdlocal.h @@ -0,0 +1,44 @@ +#ifndef CRYPTOPP_TRDLOCAL_H +#define CRYPTOPP_TRDLOCAL_H + +#include "config.h" + +#ifdef THREADS_AVAILABLE + +#include "misc.h" + +#ifdef HAS_WINTHREADS +typedef unsigned long ThreadLocalIndexType; +#else +#include +typedef pthread_key_t ThreadLocalIndexType; +#endif + +NAMESPACE_BEGIN(CryptoPP) + +//! thread local storage +class CRYPTOPP_DLL ThreadLocalStorage : public NotCopyable +{ +public: + //! exception thrown by ThreadLocalStorage class + class Err : public OS_Error + { + public: + Err(const std::string& operation, int error); + }; + + ThreadLocalStorage(); + ~ThreadLocalStorage(); + + void SetValue(void *value); + void *GetValue() const; + +private: + ThreadLocalIndexType m_index; +}; + +NAMESPACE_END + +#endif // #ifdef THREADS_AVAILABLE + +#endif diff --git a/src-cryptopp/words.h b/src-cryptopp/words.h new file mode 100644 index 0000000..d5fda71 --- /dev/null +++ b/src-cryptopp/words.h @@ -0,0 +1,103 @@ +#ifndef CRYPTOPP_WORDS_H +#define CRYPTOPP_WORDS_H + +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +inline size_t CountWords(const word *X, size_t N) +{ + while (N && X[N-1]==0) + N--; + return N; +} + +inline void SetWords(word *r, word a, size_t n) +{ + for (size_t i=0; i> (WORD_BITS-shiftBits); + } + return carry; +} + +inline word ShiftWordsRightByBits(word *r, size_t n, unsigned int shiftBits) +{ + assert (shiftBits0; i--) + { + u = r[i-1]; + r[i-1] = (u >> shiftBits) | carry; + carry = u << (WORD_BITS-shiftBits); + } + return carry; +} + +inline void ShiftWordsLeftByWords(word *r, size_t n, size_t shiftWords) +{ + shiftWords = STDMIN(shiftWords, n); + if (shiftWords) + { + for (size_t i=n-1; i>=shiftWords; i--) + r[i] = r[i-shiftWords]; + SetWords(r, 0, shiftWords); + } +} + +inline void ShiftWordsRightByWords(word *r, size_t n, size_t shiftWords) +{ + shiftWords = STDMIN(shiftWords, n); + if (shiftWords) + { + for (size_t i=0; i+shiftWords + +static PyObject * +ed25519_publickey(PyObject *self, PyObject *args) +{ + unsigned char verfkey[PUBLICKEYBYTES]; + unsigned char signkey[SECRETKEYBYTES]; + unsigned char *seed; + Py_ssize_t seed_len; + if (!PyArg_ParseTuple(args, "s#", &seed, &seed_len)) + return NULL; + crypto_sign_publickey(verfkey, signkey, seed); + return Py_BuildValue("(s#s#)", + verfkey, PUBLICKEYBYTES, + signkey, SECRETKEYBYTES); +} + +PyDoc_STRVAR(ed25519_sign_doc, +"sign(message, signing_key)\n\ +\n\ +Return the concatenation of three parts: the 32-byte R signature value,\n\ +the original message, and the 32-byte S signature value."); + +static PyObject * +ed25519_sign(PyObject *self, PyObject *args) +{ + const unsigned char *msg; Py_ssize_t msg_len; + const unsigned char *signkey; Py_ssize_t signkey_len; + unsigned char *sig_and_msg; unsigned long long sig_and_msg_len1; + Py_ssize_t sig_and_msg_len2; + PyObject *ret; + + // NOTE: using s# copies the message. It'd be nicer to use it in-place. + // Consider s* and using a Py_buffer. Don't forget PyBuffer_Release. + // Py_buffer is available in py2.6 and later. + //// on the other hand, the funky NaCl API means we're already doing 3 + //// copies anyway, so a 4th isn't a big deal. + if (!PyArg_ParseTuple(args, "s#s#:signature", + &msg, &msg_len, + &signkey, &signkey_len)) + return NULL; + if (signkey_len != SECRETKEYBYTES) { // 64 + PyErr_SetString(PyExc_TypeError, + "Private signing keys are 64 byte strings"); + return NULL; + } + sig_and_msg = PyMem_Malloc(msg_len + SIGNATUREBYTES); + if (!sig_and_msg) + return PyErr_NoMemory(); + crypto_sign(sig_and_msg, &sig_and_msg_len1, msg, msg_len, signkey); + sig_and_msg_len2 = sig_and_msg_len1; + ret = Py_BuildValue("s#", sig_and_msg, sig_and_msg_len2); + PyMem_Free(sig_and_msg); + return ret; +} + +PyDoc_STRVAR(ed25519_open_doc, +"open(message+signature, verifying_key)\n\ +\n\ +Check the signature for validity. Returns the message if valid, raises\n\ +ed25519.error if not."); + +static PyObject * +ed25519_open(PyObject *self, PyObject *args) +{ + const unsigned char *sig_and_msg; Py_ssize_t sig_and_msg_len; + const unsigned char *verfkey; Py_ssize_t verfkey_len; + unsigned char *msg; unsigned long long msg_len1; + Py_ssize_t msg_len2; + PyObject *ret; + int result; + if (!PyArg_ParseTuple(args, "s#s#:checkvalid", + &sig_and_msg, &sig_and_msg_len, + &verfkey, &verfkey_len )) + return NULL; + if (sig_and_msg_len < SIGNATUREBYTES) { // 64 + PyErr_SetString(PyExc_TypeError, + "signature-and-message must be at least 64 bytes long"); + return NULL; + } + if (verfkey_len != PUBLICKEYBYTES) { // 32 + PyErr_SetString(PyExc_TypeError, + "Public verifying keys are 32 byte strings"); + return NULL; + } + + // crypto_sign_open() uses the output buffer as a scratchpad, and thus + // requires an extra 64 bytes beyond the expected message. So allocate + // sig_and_msg_len, not sig_and_msg_len-SIGNATUREBYTES + msg = PyMem_Malloc(sig_and_msg_len); + if (!msg) + return PyErr_NoMemory(); + result = crypto_sign_open(msg, &msg_len1, sig_and_msg, sig_and_msg_len, + verfkey); + // be faithful to the NaCl interface and return the message, even though + // it's a waste. + if (result == 0) { + // good signature + msg_len2 = msg_len1; + ret = Py_BuildValue("s#", msg, msg_len2); + PyMem_Free(msg); + return ret; + } + // bad signature. We do throw an exception when the signature is bad, so + // it can't be silently ignored + PyMem_Free(msg); + PyErr_SetString(BadSignatureError, "Bad Signature"); + return NULL; +} + + +/* List of functions defined in the module */ + +static PyMethodDef ed25519_methods[] = { + {"publickey", ed25519_publickey, METH_VARARGS, ed25519_publickey_doc}, + {"sign", ed25519_sign, METH_VARARGS, ed25519_sign_doc}, + {"open", ed25519_open, METH_VARARGS, ed25519_open_doc}, + {NULL, NULL} /* sentinel */ +}; + +PyDoc_STRVAR(module_doc, +"Low-level Ed25519 signature/verification functions."); + +/* Initialization function for the module (*must* be called init_ed25519) */ + +PyMODINIT_FUNC +init_ed25519(void) +{ + PyObject *m; + + /* Create the module and add the functions */ + m = Py_InitModule3("_ed25519", ed25519_methods, module_doc); + if (m == NULL) + return; + + /* Add some symbolic constants to the module */ + if (BadSignatureError == NULL) { + BadSignatureError = PyErr_NewException("ed25519.BadSignatureError", + NULL, NULL); + if (BadSignatureError == NULL) + return; + } + if (SECRETKEYBYTESObject == NULL) { + SECRETKEYBYTESObject = PyInt_FromLong(SECRETKEYBYTES); + if (SECRETKEYBYTESObject == NULL) + return; + } + if (PUBLICKEYBYTESObject == NULL) { + PUBLICKEYBYTESObject = PyInt_FromLong(PUBLICKEYBYTES); + if (PUBLICKEYBYTESObject == NULL) + return; + } + if (SIGNATUREBYTESObject == NULL) { + SIGNATUREBYTESObject = PyInt_FromLong(SIGNATUREBYTES); + if (SIGNATUREBYTESObject == NULL) + return; + } + Py_INCREF(BadSignatureError); + PyModule_AddObject(m, "BadSignatureError", BadSignatureError); + PyModule_AddObject(m, "SECRETKEYBYTES", SECRETKEYBYTESObject); + PyModule_AddObject(m, "PUBLICKEYBYTES", PUBLICKEYBYTESObject); + PyModule_AddObject(m, "SIGNATUREKEYBYTES", SIGNATUREBYTESObject); +} diff --git a/src-ed25519/supercop-ref/Makefile b/src-ed25519/supercop-ref/Makefile new file mode 100644 index 0000000..69b0d3b --- /dev/null +++ b/src-ed25519/supercop-ref/Makefile @@ -0,0 +1,10 @@ + +CC=gcc +CFLAGS=-O2 -Wall + +OBJS= fe25519.o ge25519.o sc25519.o sha512-blocks.o sha512-hash.o ed25519.o randombytes.o verify.o +test: test.o $(OBJS) + gcc -o $@ $^ + +clean: + rm -f *.o test diff --git a/src-ed25519/supercop-ref/api.h b/src-ed25519/supercop-ref/api.h new file mode 100644 index 0000000..1d0c988 --- /dev/null +++ b/src-ed25519/supercop-ref/api.h @@ -0,0 +1,4 @@ +#define CRYPTO_SECRETKEYBYTES 64 +#define CRYPTO_PUBLICKEYBYTES 32 +#define CRYPTO_BYTES 64 + diff --git a/src-ed25519/supercop-ref/crypto_int32.h b/src-ed25519/supercop-ref/crypto_int32.h new file mode 100644 index 0000000..cae135e --- /dev/null +++ b/src-ed25519/supercop-ref/crypto_int32.h @@ -0,0 +1,6 @@ +#ifndef crypto_int32_h +#define crypto_int32_h + +typedef int crypto_int32; + +#endif diff --git a/src-ed25519/supercop-ref/crypto_sign.h b/src-ed25519/supercop-ref/crypto_sign.h new file mode 100644 index 0000000..afed208 --- /dev/null +++ b/src-ed25519/supercop-ref/crypto_sign.h @@ -0,0 +1,13 @@ +#ifndef crypto_sign_edwards25519sha512batch_H +#define crypto_sign_edwards25519sha512batch_H + +#define SECRETKEYBYTES 64 +#define PUBLICKEYBYTES 32 +#define SIGNATUREBYTES 64 + +extern int crypto_sign(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *); +extern int crypto_sign_open(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *); +extern int crypto_sign_keypair(unsigned char *,unsigned char *); +extern int crypto_sign_publickey(unsigned char *pk, unsigned char *sk, unsigned char *seed); + +#endif diff --git a/src-ed25519/supercop-ref/crypto_uint32.h b/src-ed25519/supercop-ref/crypto_uint32.h new file mode 100644 index 0000000..21020d7 --- /dev/null +++ b/src-ed25519/supercop-ref/crypto_uint32.h @@ -0,0 +1,6 @@ +#ifndef crypto_uint32_h +#define crypto_uint32_h + +typedef unsigned int crypto_uint32; + +#endif diff --git a/src-ed25519/supercop-ref/crypto_verify_32.h b/src-ed25519/supercop-ref/crypto_verify_32.h new file mode 100644 index 0000000..ad265c7 --- /dev/null +++ b/src-ed25519/supercop-ref/crypto_verify_32.h @@ -0,0 +1,7 @@ +#ifndef crypto_verify_32_H +#define crypto_verify_32_H + +#define crypto_verify_32_ref_BYTES 32 +extern int crypto_verify_32(const unsigned char *,const unsigned char *); + +#endif diff --git a/src-ed25519/supercop-ref/ed25519.c b/src-ed25519/supercop-ref/ed25519.c new file mode 100644 index 0000000..925b894 --- /dev/null +++ b/src-ed25519/supercop-ref/ed25519.c @@ -0,0 +1,136 @@ +#include "crypto_sign.h" + +#include "crypto_verify_32.h" +#include "sha512.h" + +#include "ge25519.h" + +static void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen) +{ + unsigned long long i; + + for (i = 0;i < 32;++i) playground[i] = sm[i]; + for (i = 32;i < 64;++i) playground[i] = pk[i-32]; + for (i = 64;i < smlen;++i) playground[i] = sm[i]; + + crypto_hash_sha512(hram,playground,smlen); +} + + +int crypto_sign_publickey( + unsigned char *pk, // write 32 bytes into this + unsigned char *sk, // write 64 bytes into this (seed+pubkey) + unsigned char *seed // 32 bytes + ) +{ + sc25519 scsk; + ge25519 gepk; + int i; + + crypto_hash_sha512(sk, seed, 32); + sk[0] &= 248; + sk[31] &= 127; + sk[31] |= 64; + + sc25519_from32bytes(&scsk,sk); + + ge25519_scalarmult_base(&gepk, &scsk); + ge25519_pack(pk, &gepk); + for(i=0;i<32;i++) + sk[32 + i] = pk[i]; + for(i=0;i<32;i++) + sk[i] = seed[i]; + return 0; +} + +int crypto_sign( + unsigned char *sm,unsigned long long *smlen, + const unsigned char *m,unsigned long long mlen, + const unsigned char *sk + ) +{ + sc25519 sck, scs, scsk; + ge25519 ger; + unsigned char r[32]; + unsigned char s[32]; + unsigned char extsk[64]; + unsigned long long i; + unsigned char hmg[crypto_hash_sha512_BYTES]; + unsigned char hram[crypto_hash_sha512_BYTES]; + + crypto_hash_sha512(extsk, sk, 32); + extsk[0] &= 248; + extsk[31] &= 127; + extsk[31] |= 64; + + *smlen = mlen+64; + for(i=0;i>= 31; /* 1: yes; 0: no */ + return x; +} + +static crypto_uint32 ge(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ +{ + unsigned int x = a; + x -= (unsigned int) b; /* 0..65535: yes; 4294901761..4294967295: no */ + x >>= 31; /* 0: yes; 1: no */ + x ^= 1; /* 1: yes; 0: no */ + return x; +} + +static crypto_uint32 times19(crypto_uint32 a) +{ + return (a << 4) + (a << 1) + a; +} + +static crypto_uint32 times38(crypto_uint32 a) +{ + return (a << 5) + (a << 2) + (a << 1); +} + +static void reduce_add_sub(fe25519 *r) +{ + crypto_uint32 t; + int i,rep; + + for(rep=0;rep<4;rep++) + { + t = r->v[31] >> 7; + r->v[31] &= 127; + t = times19(t); + r->v[0] += t; + for(i=0;i<31;i++) + { + t = r->v[i] >> 8; + r->v[i+1] += t; + r->v[i] &= 255; + } + } +} + +static void reduce_mul(fe25519 *r) +{ + crypto_uint32 t; + int i,rep; + + for(rep=0;rep<2;rep++) + { + t = r->v[31] >> 7; + r->v[31] &= 127; + t = times19(t); + r->v[0] += t; + for(i=0;i<31;i++) + { + t = r->v[i] >> 8; + r->v[i+1] += t; + r->v[i] &= 255; + } + } +} + +/* reduction modulo 2^255-19 */ +void fe25519_freeze(fe25519 *r) +{ + int i; + crypto_uint32 m = equal(r->v[31],127); + for(i=30;i>0;i--) + m &= equal(r->v[i],255); + m &= ge(r->v[0],237); + + m = -m; + + r->v[31] -= m&127; + for(i=30;i>0;i--) + r->v[i] -= m&255; + r->v[0] -= m&237; +} + +void fe25519_unpack(fe25519 *r, const unsigned char x[32]) +{ + int i; + for(i=0;i<32;i++) r->v[i] = x[i]; + r->v[31] &= 127; +} + +/* Assumes input x being reduced below 2^255 */ +void fe25519_pack(unsigned char r[32], const fe25519 *x) +{ + int i; + fe25519 y = *x; + fe25519_freeze(&y); + for(i=0;i<32;i++) + r[i] = y.v[i]; +} + +int fe25519_iszero(const fe25519 *x) +{ + int i, r; + fe25519 t = *x; + fe25519_freeze(&t); + r = equal(t.v[0],0); + for(i=1;i<32;i++) + r &= equal(t.v[i],0); + return r; +} + +int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y) +{ + int i; + fe25519 t1 = *x; + fe25519 t2 = *y; + fe25519_freeze(&t1); + fe25519_freeze(&t2); + for(i=0;i<32;i++) + if(t1.v[i] != t2.v[i]) return 0; + return 1; +} + +void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b) +{ + int i; + crypto_uint32 mask = b; + mask = -mask; + for(i=0;i<32;i++) r->v[i] ^= mask & (x->v[i] ^ r->v[i]); +} + +unsigned char fe25519_getparity(const fe25519 *x) +{ + fe25519 t = *x; + fe25519_freeze(&t); + return t.v[0] & 1; +} + +void fe25519_setone(fe25519 *r) +{ + int i; + r->v[0] = 1; + for(i=1;i<32;i++) r->v[i]=0; +} + +void fe25519_setzero(fe25519 *r) +{ + int i; + for(i=0;i<32;i++) r->v[i]=0; +} + +void fe25519_neg(fe25519 *r, const fe25519 *x) +{ + fe25519 t; + int i; + for(i=0;i<32;i++) t.v[i]=x->v[i]; + fe25519_setzero(r); + fe25519_sub(r, r, &t); +} + +void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y) +{ + int i; + for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i]; + reduce_add_sub(r); +} + +void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y) +{ + int i; + crypto_uint32 t[32]; + t[0] = x->v[0] + 0x1da; + t[31] = x->v[31] + 0xfe; + for(i=1;i<31;i++) t[i] = x->v[i] + 0x1fe; + for(i=0;i<32;i++) r->v[i] = t[i] - y->v[i]; + reduce_add_sub(r); +} + +void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y) +{ + int i,j; + crypto_uint32 t[63]; + for(i=0;i<63;i++)t[i] = 0; + + for(i=0;i<32;i++) + for(j=0;j<32;j++) + t[i+j] += x->v[i] * y->v[j]; + + for(i=32;i<63;i++) + r->v[i-32] = t[i-32] + times38(t[i]); + r->v[31] = t[31]; /* result now in r[0]...r[31] */ + + reduce_mul(r); +} + +void fe25519_square(fe25519 *r, const fe25519 *x) +{ + fe25519_mul(r, x, x); +} + +void fe25519_invert(fe25519 *r, const fe25519 *x) +{ + fe25519 z2; + fe25519 z9; + fe25519 z11; + fe25519 z2_5_0; + fe25519 z2_10_0; + fe25519 z2_20_0; + fe25519 z2_50_0; + fe25519 z2_100_0; + fe25519 t0; + fe25519 t1; + int i; + + /* 2 */ fe25519_square(&z2,x); + /* 4 */ fe25519_square(&t1,&z2); + /* 8 */ fe25519_square(&t0,&t1); + /* 9 */ fe25519_mul(&z9,&t0,x); + /* 11 */ fe25519_mul(&z11,&z9,&z2); + /* 22 */ fe25519_square(&t0,&z11); + /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t0,&z9); + + /* 2^6 - 2^1 */ fe25519_square(&t0,&z2_5_0); + /* 2^7 - 2^2 */ fe25519_square(&t1,&t0); + /* 2^8 - 2^3 */ fe25519_square(&t0,&t1); + /* 2^9 - 2^4 */ fe25519_square(&t1,&t0); + /* 2^10 - 2^5 */ fe25519_square(&t0,&t1); + /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t0,&z2_5_0); + + /* 2^11 - 2^1 */ fe25519_square(&t0,&z2_10_0); + /* 2^12 - 2^2 */ fe25519_square(&t1,&t0); + /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); } + /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t1,&z2_10_0); + + /* 2^21 - 2^1 */ fe25519_square(&t0,&z2_20_0); + /* 2^22 - 2^2 */ fe25519_square(&t1,&t0); + /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); } + /* 2^40 - 2^0 */ fe25519_mul(&t0,&t1,&z2_20_0); + + /* 2^41 - 2^1 */ fe25519_square(&t1,&t0); + /* 2^42 - 2^2 */ fe25519_square(&t0,&t1); + /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); } + /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t0,&z2_10_0); + + /* 2^51 - 2^1 */ fe25519_square(&t0,&z2_50_0); + /* 2^52 - 2^2 */ fe25519_square(&t1,&t0); + /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); } + /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t1,&z2_50_0); + + /* 2^101 - 2^1 */ fe25519_square(&t1,&z2_100_0); + /* 2^102 - 2^2 */ fe25519_square(&t0,&t1); + /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); } + /* 2^200 - 2^0 */ fe25519_mul(&t1,&t0,&z2_100_0); + + /* 2^201 - 2^1 */ fe25519_square(&t0,&t1); + /* 2^202 - 2^2 */ fe25519_square(&t1,&t0); + /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); } + /* 2^250 - 2^0 */ fe25519_mul(&t0,&t1,&z2_50_0); + + /* 2^251 - 2^1 */ fe25519_square(&t1,&t0); + /* 2^252 - 2^2 */ fe25519_square(&t0,&t1); + /* 2^253 - 2^3 */ fe25519_square(&t1,&t0); + /* 2^254 - 2^4 */ fe25519_square(&t0,&t1); + /* 2^255 - 2^5 */ fe25519_square(&t1,&t0); + /* 2^255 - 21 */ fe25519_mul(r,&t1,&z11); +} + +void fe25519_pow2523(fe25519 *r, const fe25519 *x) +{ + fe25519 z2; + fe25519 z9; + fe25519 z11; + fe25519 z2_5_0; + fe25519 z2_10_0; + fe25519 z2_20_0; + fe25519 z2_50_0; + fe25519 z2_100_0; + fe25519 t; + int i; + + /* 2 */ fe25519_square(&z2,x); + /* 4 */ fe25519_square(&t,&z2); + /* 8 */ fe25519_square(&t,&t); + /* 9 */ fe25519_mul(&z9,&t,x); + /* 11 */ fe25519_mul(&z11,&z9,&z2); + /* 22 */ fe25519_square(&t,&z11); + /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t,&z9); + + /* 2^6 - 2^1 */ fe25519_square(&t,&z2_5_0); + /* 2^10 - 2^5 */ for (i = 1;i < 5;i++) { fe25519_square(&t,&t); } + /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t,&z2_5_0); + + /* 2^11 - 2^1 */ fe25519_square(&t,&z2_10_0); + /* 2^20 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); } + /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t,&z2_10_0); + + /* 2^21 - 2^1 */ fe25519_square(&t,&z2_20_0); + /* 2^40 - 2^20 */ for (i = 1;i < 20;i++) { fe25519_square(&t,&t); } + /* 2^40 - 2^0 */ fe25519_mul(&t,&t,&z2_20_0); + + /* 2^41 - 2^1 */ fe25519_square(&t,&t); + /* 2^50 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); } + /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t,&z2_10_0); + + /* 2^51 - 2^1 */ fe25519_square(&t,&z2_50_0); + /* 2^100 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); } + /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t,&z2_50_0); + + /* 2^101 - 2^1 */ fe25519_square(&t,&z2_100_0); + /* 2^200 - 2^100 */ for (i = 1;i < 100;i++) { fe25519_square(&t,&t); } + /* 2^200 - 2^0 */ fe25519_mul(&t,&t,&z2_100_0); + + /* 2^201 - 2^1 */ fe25519_square(&t,&t); + /* 2^250 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); } + /* 2^250 - 2^0 */ fe25519_mul(&t,&t,&z2_50_0); + + /* 2^251 - 2^1 */ fe25519_square(&t,&t); + /* 2^252 - 2^2 */ fe25519_square(&t,&t); + /* 2^252 - 3 */ fe25519_mul(r,&t,x); +} diff --git a/src-ed25519/supercop-ref/fe25519.h b/src-ed25519/supercop-ref/fe25519.h new file mode 100644 index 0000000..ef338e8 --- /dev/null +++ b/src-ed25519/supercop-ref/fe25519.h @@ -0,0 +1,63 @@ +#ifndef FE25519_H +#define FE25519_H + +#include "crypto_int32.h" +#include "crypto_uint32.h" + +#define fe25519 crypto_sign_ed25519_ref_fe25519 +#define fe25519_freeze crypto_sign_ed25519_ref_fe25519_freeze +#define fe25519_unpack crypto_sign_ed25519_ref_fe25519_unpack +#define fe25519_pack crypto_sign_ed25519_ref_fe25519_pack +#define fe25519_iszero crypto_sign_ed25519_ref_fe25519_iszero +#define fe25519_iseq_vartime crypto_sign_ed25519_ref_fe25519_iseq_vartime +#define fe25519_cmov crypto_sign_ed25519_ref_fe25519_cmov +#define fe25519_setone crypto_sign_ed25519_ref_fe25519_setone +#define fe25519_setzero crypto_sign_ed25519_ref_fe25519_setzero +#define fe25519_neg crypto_sign_ed25519_ref_fe25519_neg +#define fe25519_getparity crypto_sign_ed25519_ref_fe25519_getparity +#define fe25519_add crypto_sign_ed25519_ref_fe25519_add +#define fe25519_sub crypto_sign_ed25519_ref_fe25519_sub +#define fe25519_mul crypto_sign_ed25519_ref_fe25519_mul +#define fe25519_square crypto_sign_ed25519_ref_fe25519_square +#define fe25519_invert crypto_sign_ed25519_ref_fe25519_invert +#define fe25519_pow2523 crypto_sign_ed25519_ref_fe25519_pow2523 + +typedef struct +{ + crypto_uint32 v[32]; +} +fe25519; + +void fe25519_freeze(fe25519 *r); + +void fe25519_unpack(fe25519 *r, const unsigned char x[32]); + +void fe25519_pack(unsigned char r[32], const fe25519 *x); + +int fe25519_iszero(const fe25519 *x); + +int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y); + +void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b); + +void fe25519_setone(fe25519 *r); + +void fe25519_setzero(fe25519 *r); + +void fe25519_neg(fe25519 *r, const fe25519 *x); + +unsigned char fe25519_getparity(const fe25519 *x); + +void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y); + +void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y); + +void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y); + +void fe25519_square(fe25519 *r, const fe25519 *x); + +void fe25519_invert(fe25519 *r, const fe25519 *x); + +void fe25519_pow2523(fe25519 *r, const fe25519 *x); + +#endif diff --git a/src-ed25519/supercop-ref/ge25519.c b/src-ed25519/supercop-ref/ge25519.c new file mode 100644 index 0000000..0ea7f15 --- /dev/null +++ b/src-ed25519/supercop-ref/ge25519.c @@ -0,0 +1,311 @@ +#include "fe25519.h" +#include "sc25519.h" +#include "ge25519.h" + +/* + * Arithmetic on the twisted Edwards curve -x^2 + y^2 = 1 + dx^2y^2 + * with d = -(121665/121666) = 37095705934669439343138083508754565189542113879843219016388785533085940283555 + * Base point: (15112221349535400772501151409588531511454012693041857206046113283949847762202,46316835694926478169428394003475163141307993866256225615783033603165251855960); + */ + +/* d */ +static const fe25519 ge25519_ecd = {{0xA3, 0x78, 0x59, 0x13, 0xCA, 0x4D, 0xEB, 0x75, 0xAB, 0xD8, 0x41, 0x41, 0x4D, 0x0A, 0x70, 0x00, + 0x98, 0xE8, 0x79, 0x77, 0x79, 0x40, 0xC7, 0x8C, 0x73, 0xFE, 0x6F, 0x2B, 0xEE, 0x6C, 0x03, 0x52}}; +/* 2*d */ +static const fe25519 ge25519_ec2d = {{0x59, 0xF1, 0xB2, 0x26, 0x94, 0x9B, 0xD6, 0xEB, 0x56, 0xB1, 0x83, 0x82, 0x9A, 0x14, 0xE0, 0x00, + 0x30, 0xD1, 0xF3, 0xEE, 0xF2, 0x80, 0x8E, 0x19, 0xE7, 0xFC, 0xDF, 0x56, 0xDC, 0xD9, 0x06, 0x24}}; +/* sqrt(-1) */ +static const fe25519 ge25519_sqrtm1 = {{0xB0, 0xA0, 0x0E, 0x4A, 0x27, 0x1B, 0xEE, 0xC4, 0x78, 0xE4, 0x2F, 0xAD, 0x06, 0x18, 0x43, 0x2F, + 0xA7, 0xD7, 0xFB, 0x3D, 0x99, 0x00, 0x4D, 0x2B, 0x0B, 0xDF, 0xC1, 0x4F, 0x80, 0x24, 0x83, 0x2B}}; + +#define ge25519_p3 ge25519 + +typedef struct +{ + fe25519 x; + fe25519 z; + fe25519 y; + fe25519 t; +} ge25519_p1p1; + +typedef struct +{ + fe25519 x; + fe25519 y; + fe25519 z; +} ge25519_p2; + +typedef struct +{ + fe25519 x; + fe25519 y; +} ge25519_aff; + + +/* Packed coordinates of the base point */ +const ge25519 ge25519_base = {{{0x1A, 0xD5, 0x25, 0x8F, 0x60, 0x2D, 0x56, 0xC9, 0xB2, 0xA7, 0x25, 0x95, 0x60, 0xC7, 0x2C, 0x69, + 0x5C, 0xDC, 0xD6, 0xFD, 0x31, 0xE2, 0xA4, 0xC0, 0xFE, 0x53, 0x6E, 0xCD, 0xD3, 0x36, 0x69, 0x21}}, + {{0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0xA3, 0xDD, 0xB7, 0xA5, 0xB3, 0x8A, 0xDE, 0x6D, 0xF5, 0x52, 0x51, 0x77, 0x80, 0x9F, 0xF0, 0x20, + 0x7D, 0xE3, 0xAB, 0x64, 0x8E, 0x4E, 0xEA, 0x66, 0x65, 0x76, 0x8B, 0xD7, 0x0F, 0x5F, 0x87, 0x67}}}; + +/* Multiples of the base point in affine representation */ +static const ge25519_aff ge25519_base_multiples_affine[425] = { +#include "ge25519_base.data" +}; + +static void p1p1_to_p2(ge25519_p2 *r, const ge25519_p1p1 *p) +{ + fe25519_mul(&r->x, &p->x, &p->t); + fe25519_mul(&r->y, &p->y, &p->z); + fe25519_mul(&r->z, &p->z, &p->t); +} + +static void p1p1_to_p3(ge25519_p3 *r, const ge25519_p1p1 *p) +{ + p1p1_to_p2((ge25519_p2 *)r, p); + fe25519_mul(&r->t, &p->x, &p->y); +} + +static void ge25519_mixadd2(ge25519_p3 *r, const ge25519_aff *q) +{ + fe25519 a,b,t1,t2,c,d,e,f,g,h,qt; + fe25519_mul(&qt, &q->x, &q->y); + fe25519_sub(&a, &r->y, &r->x); /* A = (Y1-X1)*(Y2-X2) */ + fe25519_add(&b, &r->y, &r->x); /* B = (Y1+X1)*(Y2+X2) */ + fe25519_sub(&t1, &q->y, &q->x); + fe25519_add(&t2, &q->y, &q->x); + fe25519_mul(&a, &a, &t1); + fe25519_mul(&b, &b, &t2); + fe25519_sub(&e, &b, &a); /* E = B-A */ + fe25519_add(&h, &b, &a); /* H = B+A */ + fe25519_mul(&c, &r->t, &qt); /* C = T1*k*T2 */ + fe25519_mul(&c, &c, &ge25519_ec2d); + fe25519_add(&d, &r->z, &r->z); /* D = Z1*2 */ + fe25519_sub(&f, &d, &c); /* F = D-C */ + fe25519_add(&g, &d, &c); /* G = D+C */ + fe25519_mul(&r->x, &e, &f); + fe25519_mul(&r->y, &h, &g); + fe25519_mul(&r->z, &g, &f); + fe25519_mul(&r->t, &e, &h); +} + +static void add_p1p1(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_p3 *q) +{ + fe25519 a, b, c, d, t; + + fe25519_sub(&a, &p->y, &p->x); /* A = (Y1-X1)*(Y2-X2) */ + fe25519_sub(&t, &q->y, &q->x); + fe25519_mul(&a, &a, &t); + fe25519_add(&b, &p->x, &p->y); /* B = (Y1+X1)*(Y2+X2) */ + fe25519_add(&t, &q->x, &q->y); + fe25519_mul(&b, &b, &t); + fe25519_mul(&c, &p->t, &q->t); /* C = T1*k*T2 */ + fe25519_mul(&c, &c, &ge25519_ec2d); + fe25519_mul(&d, &p->z, &q->z); /* D = Z1*2*Z2 */ + fe25519_add(&d, &d, &d); + fe25519_sub(&r->x, &b, &a); /* E = B-A */ + fe25519_sub(&r->t, &d, &c); /* F = D-C */ + fe25519_add(&r->z, &d, &c); /* G = D+C */ + fe25519_add(&r->y, &b, &a); /* H = B+A */ +} + +/* See http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd */ +static void dbl_p1p1(ge25519_p1p1 *r, const ge25519_p2 *p) +{ + fe25519 a,b,c,d; + fe25519_square(&a, &p->x); + fe25519_square(&b, &p->y); + fe25519_square(&c, &p->z); + fe25519_add(&c, &c, &c); + fe25519_neg(&d, &a); + + fe25519_add(&r->x, &p->x, &p->y); + fe25519_square(&r->x, &r->x); + fe25519_sub(&r->x, &r->x, &a); + fe25519_sub(&r->x, &r->x, &b); + fe25519_add(&r->z, &d, &b); + fe25519_sub(&r->t, &r->z, &c); + fe25519_sub(&r->y, &d, &b); +} + +/* Constant-time version of: if(b) r = p */ +static void cmov_aff(ge25519_aff *r, const ge25519_aff *p, unsigned char b) +{ + fe25519_cmov(&r->x, &p->x, b); + fe25519_cmov(&r->y, &p->y, b); +} + +static unsigned char equal(signed char b,signed char c) +{ + unsigned char ub = b; + unsigned char uc = c; + unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */ + crypto_uint32 y = x; /* 0: yes; 1..255: no */ + y -= 1; /* 4294967295: yes; 0..254: no */ + y >>= 31; /* 1: yes; 0: no */ + return y; +} + +static unsigned char negative(signed char b) +{ + unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ + x >>= 63; /* 1: yes; 0: no */ + return x; +} + +static void choose_t(ge25519_aff *t, unsigned long long pos, signed char b) +{ + /* constant time */ + fe25519 v; + *t = ge25519_base_multiples_affine[5*pos+0]; + cmov_aff(t, &ge25519_base_multiples_affine[5*pos+1],equal(b,1) | equal(b,-1)); + cmov_aff(t, &ge25519_base_multiples_affine[5*pos+2],equal(b,2) | equal(b,-2)); + cmov_aff(t, &ge25519_base_multiples_affine[5*pos+3],equal(b,3) | equal(b,-3)); + cmov_aff(t, &ge25519_base_multiples_affine[5*pos+4],equal(b,-4)); + fe25519_neg(&v, &t->x); + fe25519_cmov(&t->x, &v, negative(b)); +} + +static void setneutral(ge25519 *r) +{ + fe25519_setzero(&r->x); + fe25519_setone(&r->y); + fe25519_setone(&r->z); + fe25519_setzero(&r->t); +} + +/* ******************************************************************** + * EXPORTED FUNCTIONS + ******************************************************************** */ + +/* return 0 on success, -1 otherwise */ +int ge25519_unpackneg_vartime(ge25519_p3 *r, const unsigned char p[32]) +{ + unsigned char par; + fe25519 t, chk, num, den, den2, den4, den6; + fe25519_setone(&r->z); + par = p[31] >> 7; + fe25519_unpack(&r->y, p); + fe25519_square(&num, &r->y); /* x = y^2 */ + fe25519_mul(&den, &num, &ge25519_ecd); /* den = dy^2 */ + fe25519_sub(&num, &num, &r->z); /* x = y^2-1 */ + fe25519_add(&den, &r->z, &den); /* den = dy^2+1 */ + + /* Computation of sqrt(num/den) */ + /* 1.: computation of num^((p-5)/8)*den^((7p-35)/8) = (num*den^7)^((p-5)/8) */ + fe25519_square(&den2, &den); + fe25519_square(&den4, &den2); + fe25519_mul(&den6, &den4, &den2); + fe25519_mul(&t, &den6, &num); + fe25519_mul(&t, &t, &den); + + fe25519_pow2523(&t, &t); + /* 2. computation of r->x = t * num * den^3 */ + fe25519_mul(&t, &t, &num); + fe25519_mul(&t, &t, &den); + fe25519_mul(&t, &t, &den); + fe25519_mul(&r->x, &t, &den); + + /* 3. Check whether sqrt computation gave correct result, multiply by sqrt(-1) if not: */ + fe25519_square(&chk, &r->x); + fe25519_mul(&chk, &chk, &den); + if (!fe25519_iseq_vartime(&chk, &num)) + fe25519_mul(&r->x, &r->x, &ge25519_sqrtm1); + + /* 4. Now we have one of the two square roots, except if input was not a square */ + fe25519_square(&chk, &r->x); + fe25519_mul(&chk, &chk, &den); + if (!fe25519_iseq_vartime(&chk, &num)) + return -1; + + /* 5. Choose the desired square root according to parity: */ + if(fe25519_getparity(&r->x) != (1-par)) + fe25519_neg(&r->x, &r->x); + + fe25519_mul(&r->t, &r->x, &r->y); + return 0; +} + +void ge25519_pack(unsigned char r[32], const ge25519_p3 *p) +{ + fe25519 tx, ty, zi; + fe25519_invert(&zi, &p->z); + fe25519_mul(&tx, &p->x, &zi); + fe25519_mul(&ty, &p->y, &zi); + fe25519_pack(r, &ty); + r[31] ^= fe25519_getparity(&tx) << 7; +} + +int ge25519_isneutral_vartime(const ge25519_p3 *p) +{ + int ret = 1; + if(!fe25519_iszero(&p->x)) ret = 0; + if(!fe25519_iseq_vartime(&p->y, &p->z)) ret = 0; + return ret; +} + +/* computes [s1]p1 + [s2]p2 */ +void ge25519_double_scalarmult_vartime(ge25519_p3 *r, const ge25519_p3 *p1, const sc25519 *s1, const ge25519_p3 *p2, const sc25519 *s2) +{ + ge25519_p1p1 tp1p1; + ge25519_p3 pre[16]; + unsigned char b[127]; + int i; + + /* precomputation s2 s1 */ + setneutral(pre); /* 00 00 */ + pre[1] = *p1; /* 00 01 */ + dbl_p1p1(&tp1p1,(ge25519_p2 *)p1); p1p1_to_p3( &pre[2], &tp1p1); /* 00 10 */ + add_p1p1(&tp1p1,&pre[1], &pre[2]); p1p1_to_p3( &pre[3], &tp1p1); /* 00 11 */ + pre[4] = *p2; /* 01 00 */ + add_p1p1(&tp1p1,&pre[1], &pre[4]); p1p1_to_p3( &pre[5], &tp1p1); /* 01 01 */ + add_p1p1(&tp1p1,&pre[2], &pre[4]); p1p1_to_p3( &pre[6], &tp1p1); /* 01 10 */ + add_p1p1(&tp1p1,&pre[3], &pre[4]); p1p1_to_p3( &pre[7], &tp1p1); /* 01 11 */ + dbl_p1p1(&tp1p1,(ge25519_p2 *)p2); p1p1_to_p3( &pre[8], &tp1p1); /* 10 00 */ + add_p1p1(&tp1p1,&pre[1], &pre[8]); p1p1_to_p3( &pre[9], &tp1p1); /* 10 01 */ + dbl_p1p1(&tp1p1,(ge25519_p2 *)&pre[5]); p1p1_to_p3(&pre[10], &tp1p1); /* 10 10 */ + add_p1p1(&tp1p1,&pre[3], &pre[8]); p1p1_to_p3(&pre[11], &tp1p1); /* 10 11 */ + add_p1p1(&tp1p1,&pre[4], &pre[8]); p1p1_to_p3(&pre[12], &tp1p1); /* 11 00 */ + add_p1p1(&tp1p1,&pre[1],&pre[12]); p1p1_to_p3(&pre[13], &tp1p1); /* 11 01 */ + add_p1p1(&tp1p1,&pre[2],&pre[12]); p1p1_to_p3(&pre[14], &tp1p1); /* 11 10 */ + add_p1p1(&tp1p1,&pre[3],&pre[12]); p1p1_to_p3(&pre[15], &tp1p1); /* 11 11 */ + + sc25519_2interleave2(b,s1,s2); + + /* scalar multiplication */ + *r = pre[b[126]]; + for(i=125;i>=0;i--) + { + dbl_p1p1(&tp1p1, (ge25519_p2 *)r); + p1p1_to_p2((ge25519_p2 *) r, &tp1p1); + dbl_p1p1(&tp1p1, (ge25519_p2 *)r); + if(b[i]!=0) + { + p1p1_to_p3(r, &tp1p1); + add_p1p1(&tp1p1, r, &pre[b[i]]); + } + if(i != 0) p1p1_to_p2((ge25519_p2 *)r, &tp1p1); + else p1p1_to_p3(r, &tp1p1); + } +} + +void ge25519_scalarmult_base(ge25519_p3 *r, const sc25519 *s) +{ + signed char b[85]; + int i; + ge25519_aff t; + sc25519_window3(b,s); + + choose_t((ge25519_aff *)r, 0, b[0]); + fe25519_setone(&r->z); + fe25519_mul(&r->t, &r->x, &r->y); + for(i=1;i<85;i++) + { + choose_t(&t, (unsigned long long) i, b[i]); + ge25519_mixadd2(r, &t); + } +} diff --git a/src-ed25519/supercop-ref/ge25519.h b/src-ed25519/supercop-ref/ge25519.h new file mode 100644 index 0000000..18519d2 --- /dev/null +++ b/src-ed25519/supercop-ref/ge25519.h @@ -0,0 +1,35 @@ +#ifndef GE25519_H +#define GE25519_H + +#include "fe25519.h" +#include "sc25519.h" + +#define ge25519 crypto_sign_ed25519_ref_ge25519 +#define ge25519_base crypto_sign_ed25519_ref_ge25519_base +#define ge25519_unpackneg_vartime crypto_sign_ed25519_ref_unpackneg_vartime +#define ge25519_pack crypto_sign_ed25519_ref_pack +#define ge25519_isneutral_vartime crypto_sign_ed25519_ref_isneutral_vartime +#define ge25519_double_scalarmult_vartime crypto_sign_ed25519_ref_double_scalarmult_vartime +#define ge25519_scalarmult_base crypto_sign_ed25519_ref_scalarmult_base + +typedef struct +{ + fe25519 x; + fe25519 y; + fe25519 z; + fe25519 t; +} ge25519; + +extern const ge25519 ge25519_base; + +int ge25519_unpackneg_vartime(ge25519 *r, const unsigned char p[32]); + +void ge25519_pack(unsigned char r[32], const ge25519 *p); + +int ge25519_isneutral_vartime(const ge25519 *p); + +void ge25519_double_scalarmult_vartime(ge25519 *r, const ge25519 *p1, const sc25519 *s1, const ge25519 *p2, const sc25519 *s2); + +void ge25519_scalarmult_base(ge25519 *r, const sc25519 *s); + +#endif diff --git a/src-ed25519/supercop-ref/ge25519_base.data b/src-ed25519/supercop-ref/ge25519_base.data new file mode 100644 index 0000000..d2ef2c1 --- /dev/null +++ b/src-ed25519/supercop-ref/ge25519_base.data @@ -0,0 +1,850 @@ +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21}} , + {{0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}}}, +{{{0x0e, 0xce, 0x43, 0x28, 0x4e, 0xa1, 0xc5, 0x83, 0x5f, 0xa4, 0xd7, 0x15, 0x45, 0x8e, 0x0d, 0x08, 0xac, 0xe7, 0x33, 0x18, 0x7d, 0x3b, 0x04, 0x3d, 0x6c, 0x04, 0x5a, 0x9f, 0x4c, 0x38, 0xab, 0x36}} , + {{0xc9, 0xa3, 0xf8, 0x6a, 0xae, 0x46, 0x5f, 0x0e, 0x56, 0x51, 0x38, 0x64, 0x51, 0x0f, 0x39, 0x97, 0x56, 0x1f, 0xa2, 0xc9, 0xe8, 0x5e, 0xa2, 0x1d, 0xc2, 0x29, 0x23, 0x09, 0xf3, 0xcd, 0x60, 0x22}}}, +{{{0x5c, 0xe2, 0xf8, 0xd3, 0x5f, 0x48, 0x62, 0xac, 0x86, 0x48, 0x62, 0x81, 0x19, 0x98, 0x43, 0x63, 0x3a, 0xc8, 0xda, 0x3e, 0x74, 0xae, 0xf4, 0x1f, 0x49, 0x8f, 0x92, 0x22, 0x4a, 0x9c, 0xae, 0x67}} , + {{0xd4, 0xb4, 0xf5, 0x78, 0x48, 0x68, 0xc3, 0x02, 0x04, 0x03, 0x24, 0x67, 0x17, 0xec, 0x16, 0x9f, 0xf7, 0x9e, 0x26, 0x60, 0x8e, 0xa1, 0x26, 0xa1, 0xab, 0x69, 0xee, 0x77, 0xd1, 0xb1, 0x67, 0x12}}}, +{{{0x70, 0xf8, 0xc9, 0xc4, 0x57, 0xa6, 0x3a, 0x49, 0x47, 0x15, 0xce, 0x93, 0xc1, 0x9e, 0x73, 0x1a, 0xf9, 0x20, 0x35, 0x7a, 0xb8, 0xd4, 0x25, 0x83, 0x46, 0xf1, 0xcf, 0x56, 0xdb, 0xa8, 0x3d, 0x20}} , + {{0x2f, 0x11, 0x32, 0xca, 0x61, 0xab, 0x38, 0xdf, 0xf0, 0x0f, 0x2f, 0xea, 0x32, 0x28, 0xf2, 0x4c, 0x6c, 0x71, 0xd5, 0x80, 0x85, 0xb8, 0x0e, 0x47, 0xe1, 0x95, 0x15, 0xcb, 0x27, 0xe8, 0xd0, 0x47}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xc8, 0x84, 0xa5, 0x08, 0xbc, 0xfd, 0x87, 0x3b, 0x99, 0x8b, 0x69, 0x80, 0x7b, 0xc6, 0x3a, 0xeb, 0x93, 0xcf, 0x4e, 0xf8, 0x5c, 0x2d, 0x86, 0x42, 0xb6, 0x71, 0xd7, 0x97, 0x5f, 0xe1, 0x42, 0x67}} , + {{0xb4, 0xb9, 0x37, 0xfc, 0xa9, 0x5b, 0x2f, 0x1e, 0x93, 0xe4, 0x1e, 0x62, 0xfc, 0x3c, 0x78, 0x81, 0x8f, 0xf3, 0x8a, 0x66, 0x09, 0x6f, 0xad, 0x6e, 0x79, 0x73, 0xe5, 0xc9, 0x00, 0x06, 0xd3, 0x21}}}, +{{{0xf8, 0xf9, 0x28, 0x6c, 0x6d, 0x59, 0xb2, 0x59, 0x74, 0x23, 0xbf, 0xe7, 0x33, 0x8d, 0x57, 0x09, 0x91, 0x9c, 0x24, 0x08, 0x15, 0x2b, 0xe2, 0xb8, 0xee, 0x3a, 0xe5, 0x27, 0x06, 0x86, 0xa4, 0x23}} , + {{0xeb, 0x27, 0x67, 0xc1, 0x37, 0xab, 0x7a, 0xd8, 0x27, 0x9c, 0x07, 0x8e, 0xff, 0x11, 0x6a, 0xb0, 0x78, 0x6e, 0xad, 0x3a, 0x2e, 0x0f, 0x98, 0x9f, 0x72, 0xc3, 0x7f, 0x82, 0xf2, 0x96, 0x96, 0x70}}}, +{{{0x81, 0x6b, 0x88, 0xe8, 0x1e, 0xc7, 0x77, 0x96, 0x0e, 0xa1, 0xa9, 0x52, 0xe0, 0xd8, 0x0e, 0x61, 0x9e, 0x79, 0x2d, 0x95, 0x9c, 0x8d, 0x96, 0xe0, 0x06, 0x40, 0x5d, 0x87, 0x28, 0x5f, 0x98, 0x70}} , + {{0xf1, 0x79, 0x7b, 0xed, 0x4f, 0x44, 0xb2, 0xe7, 0x08, 0x0d, 0xc2, 0x08, 0x12, 0xd2, 0x9f, 0xdf, 0xcd, 0x93, 0x20, 0x8a, 0xcf, 0x33, 0xca, 0x6d, 0x89, 0xb9, 0x77, 0xc8, 0x93, 0x1b, 0x4e, 0x60}}}, +{{{0x26, 0x4f, 0x7e, 0x97, 0xf6, 0x40, 0xdd, 0x4f, 0xfc, 0x52, 0x78, 0xf9, 0x90, 0x31, 0x03, 0xe6, 0x7d, 0x56, 0x39, 0x0b, 0x1d, 0x56, 0x82, 0x85, 0xf9, 0x1a, 0x42, 0x17, 0x69, 0x6c, 0xcf, 0x39}} , + {{0x69, 0xd2, 0x06, 0x3a, 0x4f, 0x39, 0x2d, 0xf9, 0x38, 0x40, 0x8c, 0x4c, 0xe7, 0x05, 0x12, 0xb4, 0x78, 0x8b, 0xf8, 0xc0, 0xec, 0x93, 0xde, 0x7a, 0x6b, 0xce, 0x2c, 0xe1, 0x0e, 0xa9, 0x34, 0x44}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x0b, 0xa4, 0x3c, 0xb0, 0x0f, 0x7a, 0x51, 0xf1, 0x78, 0xd6, 0xd9, 0x6a, 0xfd, 0x46, 0xe8, 0xb8, 0xa8, 0x79, 0x1d, 0x87, 0xf9, 0x90, 0xf2, 0x9c, 0x13, 0x29, 0xf8, 0x0b, 0x20, 0x64, 0xfa, 0x05}} , + {{0x26, 0x09, 0xda, 0x17, 0xaf, 0x95, 0xd6, 0xfb, 0x6a, 0x19, 0x0d, 0x6e, 0x5e, 0x12, 0xf1, 0x99, 0x4c, 0xaa, 0xa8, 0x6f, 0x79, 0x86, 0xf4, 0x72, 0x28, 0x00, 0x26, 0xf9, 0xea, 0x9e, 0x19, 0x3d}}}, +{{{0x87, 0xdd, 0xcf, 0xf0, 0x5b, 0x49, 0xa2, 0x5d, 0x40, 0x7a, 0x23, 0x26, 0xa4, 0x7a, 0x83, 0x8a, 0xb7, 0x8b, 0xd2, 0x1a, 0xbf, 0xea, 0x02, 0x24, 0x08, 0x5f, 0x7b, 0xa9, 0xb1, 0xbe, 0x9d, 0x37}} , + {{0xfc, 0x86, 0x4b, 0x08, 0xee, 0xe7, 0xa0, 0xfd, 0x21, 0x45, 0x09, 0x34, 0xc1, 0x61, 0x32, 0x23, 0xfc, 0x9b, 0x55, 0x48, 0x53, 0x99, 0xf7, 0x63, 0xd0, 0x99, 0xce, 0x01, 0xe0, 0x9f, 0xeb, 0x28}}}, +{{{0x47, 0xfc, 0xab, 0x5a, 0x17, 0xf0, 0x85, 0x56, 0x3a, 0x30, 0x86, 0x20, 0x28, 0x4b, 0x8e, 0x44, 0x74, 0x3a, 0x6e, 0x02, 0xf1, 0x32, 0x8f, 0x9f, 0x3f, 0x08, 0x35, 0xe9, 0xca, 0x16, 0x5f, 0x6e}} , + {{0x1c, 0x59, 0x1c, 0x65, 0x5d, 0x34, 0xa4, 0x09, 0xcd, 0x13, 0x9c, 0x70, 0x7d, 0xb1, 0x2a, 0xc5, 0x88, 0xaf, 0x0b, 0x60, 0xc7, 0x9f, 0x34, 0x8d, 0xd6, 0xb7, 0x7f, 0xea, 0x78, 0x65, 0x8d, 0x77}}}, +{{{0x56, 0xa5, 0xc2, 0x0c, 0xdd, 0xbc, 0xb8, 0x20, 0x6d, 0x57, 0x61, 0xb5, 0xfb, 0x78, 0xb5, 0xd4, 0x49, 0x54, 0x90, 0x26, 0xc1, 0xcb, 0xe9, 0xe6, 0xbf, 0xec, 0x1d, 0x4e, 0xed, 0x07, 0x7e, 0x5e}} , + {{0xc7, 0xf6, 0x6c, 0x56, 0x31, 0x20, 0x14, 0x0e, 0xa8, 0xd9, 0x27, 0xc1, 0x9a, 0x3d, 0x1b, 0x7d, 0x0e, 0x26, 0xd3, 0x81, 0xaa, 0xeb, 0xf5, 0x6b, 0x79, 0x02, 0xf1, 0x51, 0x5c, 0x75, 0x55, 0x0f}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x0a, 0x34, 0xcd, 0x82, 0x3c, 0x33, 0x09, 0x54, 0xd2, 0x61, 0x39, 0x30, 0x9b, 0xfd, 0xef, 0x21, 0x26, 0xd4, 0x70, 0xfa, 0xee, 0xf9, 0x31, 0x33, 0x73, 0x84, 0xd0, 0xb3, 0x81, 0xbf, 0xec, 0x2e}} , + {{0xe8, 0x93, 0x8b, 0x00, 0x64, 0xf7, 0x9c, 0xb8, 0x74, 0xe0, 0xe6, 0x49, 0x48, 0x4d, 0x4d, 0x48, 0xb6, 0x19, 0xa1, 0x40, 0xb7, 0xd9, 0x32, 0x41, 0x7c, 0x82, 0x37, 0xa1, 0x2d, 0xdc, 0xd2, 0x54}}}, +{{{0x68, 0x2b, 0x4a, 0x5b, 0xd5, 0xc7, 0x51, 0x91, 0x1d, 0xe1, 0x2a, 0x4b, 0xc4, 0x47, 0xf1, 0xbc, 0x7a, 0xb3, 0xcb, 0xc8, 0xb6, 0x7c, 0xac, 0x90, 0x05, 0xfd, 0xf3, 0xf9, 0x52, 0x3a, 0x11, 0x6b}} , + {{0x3d, 0xc1, 0x27, 0xf3, 0x59, 0x43, 0x95, 0x90, 0xc5, 0x96, 0x79, 0xf5, 0xf4, 0x95, 0x65, 0x29, 0x06, 0x9c, 0x51, 0x05, 0x18, 0xda, 0xb8, 0x2e, 0x79, 0x7e, 0x69, 0x59, 0x71, 0x01, 0xeb, 0x1a}}}, +{{{0x15, 0x06, 0x49, 0xb6, 0x8a, 0x3c, 0xea, 0x2f, 0x34, 0x20, 0x14, 0xc3, 0xaa, 0xd6, 0xaf, 0x2c, 0x3e, 0xbd, 0x65, 0x20, 0xe2, 0x4d, 0x4b, 0x3b, 0xeb, 0x9f, 0x4a, 0xc3, 0xad, 0xa4, 0x3b, 0x60}} , + {{0xbc, 0x58, 0xe6, 0xc0, 0x95, 0x2a, 0x2a, 0x81, 0x9a, 0x7a, 0xf3, 0xd2, 0x06, 0xbe, 0x48, 0xbc, 0x0c, 0xc5, 0x46, 0xe0, 0x6a, 0xd4, 0xac, 0x0f, 0xd9, 0xcc, 0x82, 0x34, 0x2c, 0xaf, 0xdb, 0x1f}}}, +{{{0xf7, 0x17, 0x13, 0xbd, 0xfb, 0xbc, 0xd2, 0xec, 0x45, 0xb3, 0x15, 0x31, 0xe9, 0xaf, 0x82, 0x84, 0x3d, 0x28, 0xc6, 0xfc, 0x11, 0xf5, 0x41, 0xb5, 0x8b, 0xd3, 0x12, 0x76, 0x52, 0xe7, 0x1a, 0x3c}} , + {{0x4e, 0x36, 0x11, 0x07, 0xa2, 0x15, 0x20, 0x51, 0xc4, 0x2a, 0xc3, 0x62, 0x8b, 0x5e, 0x7f, 0xa6, 0x0f, 0xf9, 0x45, 0x85, 0x6c, 0x11, 0x86, 0xb7, 0x7e, 0xe5, 0xd7, 0xf9, 0xc3, 0x91, 0x1c, 0x05}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xea, 0xd6, 0xde, 0x29, 0x3a, 0x00, 0xb9, 0x02, 0x59, 0xcb, 0x26, 0xc4, 0xba, 0x99, 0xb1, 0x97, 0x2f, 0x8e, 0x00, 0x92, 0x26, 0x4f, 0x52, 0xeb, 0x47, 0x1b, 0x89, 0x8b, 0x24, 0xc0, 0x13, 0x7d}} , + {{0xd5, 0x20, 0x5b, 0x80, 0xa6, 0x80, 0x20, 0x95, 0xc3, 0xe9, 0x9f, 0x8e, 0x87, 0x9e, 0x1e, 0x9e, 0x7a, 0xc7, 0xcc, 0x75, 0x6c, 0xa5, 0xf1, 0x91, 0x1a, 0xa8, 0x01, 0x2c, 0xab, 0x76, 0xa9, 0x59}}}, +{{{0xde, 0xc9, 0xb1, 0x31, 0x10, 0x16, 0xaa, 0x35, 0x14, 0x6a, 0xd4, 0xb5, 0x34, 0x82, 0x71, 0xd2, 0x4a, 0x5d, 0x9a, 0x1f, 0x53, 0x26, 0x3c, 0xe5, 0x8e, 0x8d, 0x33, 0x7f, 0xff, 0xa9, 0xd5, 0x17}} , + {{0x89, 0xaf, 0xf6, 0xa4, 0x64, 0xd5, 0x10, 0xe0, 0x1d, 0xad, 0xef, 0x44, 0xbd, 0xda, 0x83, 0xac, 0x7a, 0xa8, 0xf0, 0x1c, 0x07, 0xf9, 0xc3, 0x43, 0x6c, 0x3f, 0xb7, 0xd3, 0x87, 0x22, 0x02, 0x73}}}, +{{{0x64, 0x1d, 0x49, 0x13, 0x2f, 0x71, 0xec, 0x69, 0x87, 0xd0, 0x42, 0xee, 0x13, 0xec, 0xe3, 0xed, 0x56, 0x7b, 0xbf, 0xbd, 0x8c, 0x2f, 0x7d, 0x7b, 0x9d, 0x28, 0xec, 0x8e, 0x76, 0x2f, 0x6f, 0x08}} , + {{0x22, 0xf5, 0x5f, 0x4d, 0x15, 0xef, 0xfc, 0x4e, 0x57, 0x03, 0x36, 0x89, 0xf0, 0xeb, 0x5b, 0x91, 0xd6, 0xe2, 0xca, 0x01, 0xa5, 0xee, 0x52, 0xec, 0xa0, 0x3c, 0x8f, 0x33, 0x90, 0x5a, 0x94, 0x72}}}, +{{{0x8a, 0x4b, 0xe7, 0x38, 0xbc, 0xda, 0xc2, 0xb0, 0x85, 0xe1, 0x4a, 0xfe, 0x2d, 0x44, 0x84, 0xcb, 0x20, 0x6b, 0x2d, 0xbf, 0x11, 0x9c, 0xd7, 0xbe, 0xd3, 0x3e, 0x5f, 0xbf, 0x68, 0xbc, 0xa8, 0x07}} , + {{0x01, 0x89, 0x28, 0x22, 0x6a, 0x78, 0xaa, 0x29, 0x03, 0xc8, 0x74, 0x95, 0x03, 0x3e, 0xdc, 0xbd, 0x07, 0x13, 0xa8, 0xa2, 0x20, 0x2d, 0xb3, 0x18, 0x70, 0x42, 0xfd, 0x7a, 0xc4, 0xd7, 0x49, 0x72}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x02, 0xff, 0x32, 0x2b, 0x5c, 0x93, 0x54, 0x32, 0xe8, 0x57, 0x54, 0x1a, 0x8b, 0x33, 0x60, 0x65, 0xd3, 0x67, 0xa4, 0xc1, 0x26, 0xc4, 0xa4, 0x34, 0x1f, 0x9b, 0xa7, 0xa9, 0xf4, 0xd9, 0x4f, 0x5b}} , + {{0x46, 0x8d, 0xb0, 0x33, 0x54, 0x26, 0x5b, 0x68, 0xdf, 0xbb, 0xc5, 0xec, 0xc2, 0xf9, 0x3c, 0x5a, 0x37, 0xc1, 0x8e, 0x27, 0x47, 0xaa, 0x49, 0x5a, 0xf8, 0xfb, 0x68, 0x04, 0x23, 0xd1, 0xeb, 0x40}}}, +{{{0x65, 0xa5, 0x11, 0x84, 0x8a, 0x67, 0x9d, 0x9e, 0xd1, 0x44, 0x68, 0x7a, 0x34, 0xe1, 0x9f, 0xa3, 0x54, 0xcd, 0x07, 0xca, 0x79, 0x1f, 0x54, 0x2f, 0x13, 0x70, 0x4e, 0xee, 0xa2, 0xfa, 0xe7, 0x5d}} , + {{0x36, 0xec, 0x54, 0xf8, 0xce, 0xe4, 0x85, 0xdf, 0xf6, 0x6f, 0x1d, 0x90, 0x08, 0xbc, 0xe8, 0xc0, 0x92, 0x2d, 0x43, 0x6b, 0x92, 0xa9, 0x8e, 0xab, 0x0a, 0x2e, 0x1c, 0x1e, 0x64, 0x23, 0x9f, 0x2c}}}, +{{{0xa7, 0xd6, 0x2e, 0xd5, 0xcc, 0xd4, 0xcb, 0x5a, 0x3b, 0xa7, 0xf9, 0x46, 0x03, 0x1d, 0xad, 0x2b, 0x34, 0x31, 0x90, 0x00, 0x46, 0x08, 0x82, 0x14, 0xc4, 0xe0, 0x9c, 0xf0, 0xe3, 0x55, 0x43, 0x31}} , + {{0x60, 0xd6, 0xdd, 0x78, 0xe6, 0xd4, 0x22, 0x42, 0x1f, 0x00, 0xf9, 0xb1, 0x6a, 0x63, 0xe2, 0x92, 0x59, 0xd1, 0x1a, 0xb7, 0x00, 0x54, 0x29, 0xc9, 0xc1, 0xf6, 0x6f, 0x7a, 0xc5, 0x3c, 0x5f, 0x65}}}, +{{{0x27, 0x4f, 0xd0, 0x72, 0xb1, 0x11, 0x14, 0x27, 0x15, 0x94, 0x48, 0x81, 0x7e, 0x74, 0xd8, 0x32, 0xd5, 0xd1, 0x11, 0x28, 0x60, 0x63, 0x36, 0x32, 0x37, 0xb5, 0x13, 0x1c, 0xa0, 0x37, 0xe3, 0x74}} , + {{0xf1, 0x25, 0x4e, 0x11, 0x96, 0x67, 0xe6, 0x1c, 0xc2, 0xb2, 0x53, 0xe2, 0xda, 0x85, 0xee, 0xb2, 0x9f, 0x59, 0xf3, 0xba, 0xbd, 0xfa, 0xcf, 0x6e, 0xf9, 0xda, 0xa4, 0xb3, 0x02, 0x8f, 0x64, 0x08}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x34, 0x94, 0xf2, 0x64, 0x54, 0x47, 0x37, 0x07, 0x40, 0x8a, 0x20, 0xba, 0x4a, 0x55, 0xd7, 0x3f, 0x47, 0xba, 0x25, 0x23, 0x14, 0xb0, 0x2c, 0xe8, 0x55, 0xa8, 0xa6, 0xef, 0x51, 0xbd, 0x6f, 0x6a}} , + {{0x71, 0xd6, 0x16, 0x76, 0xb2, 0x06, 0xea, 0x79, 0xf5, 0xc4, 0xc3, 0x52, 0x7e, 0x61, 0xd1, 0xe1, 0xad, 0x70, 0x78, 0x1d, 0x16, 0x11, 0xf8, 0x7c, 0x2b, 0xfc, 0x55, 0x9f, 0x52, 0xf8, 0xf5, 0x16}}}, +{{{0x34, 0x96, 0x9a, 0xf6, 0xc5, 0xe0, 0x14, 0x03, 0x24, 0x0e, 0x4c, 0xad, 0x9e, 0x9a, 0x70, 0x23, 0x96, 0xb2, 0xf1, 0x2e, 0x9d, 0xc3, 0x32, 0x9b, 0x54, 0xa5, 0x73, 0xde, 0x88, 0xb1, 0x3e, 0x24}} , + {{0xf6, 0xe2, 0x4c, 0x1f, 0x5b, 0xb2, 0xaf, 0x82, 0xa5, 0xcf, 0x81, 0x10, 0x04, 0xef, 0xdb, 0xa2, 0xcc, 0x24, 0xb2, 0x7e, 0x0b, 0x7a, 0xeb, 0x01, 0xd8, 0x52, 0xf4, 0x51, 0x89, 0x29, 0x79, 0x37}}}, +{{{0x74, 0xde, 0x12, 0xf3, 0x68, 0xb7, 0x66, 0xc3, 0xee, 0x68, 0xdc, 0x81, 0xb5, 0x55, 0x99, 0xab, 0xd9, 0x28, 0x63, 0x6d, 0x8b, 0x40, 0x69, 0x75, 0x6c, 0xcd, 0x5c, 0x2a, 0x7e, 0x32, 0x7b, 0x29}} , + {{0x02, 0xcc, 0x22, 0x74, 0x4d, 0x19, 0x07, 0xc0, 0xda, 0xb5, 0x76, 0x51, 0x2a, 0xaa, 0xa6, 0x0a, 0x5f, 0x26, 0xd4, 0xbc, 0xaf, 0x48, 0x88, 0x7f, 0x02, 0xbc, 0xf2, 0xe1, 0xcf, 0xe9, 0xdd, 0x15}}}, +{{{0xed, 0xb5, 0x9a, 0x8c, 0x9a, 0xdd, 0x27, 0xf4, 0x7f, 0x47, 0xd9, 0x52, 0xa7, 0xcd, 0x65, 0xa5, 0x31, 0x22, 0xed, 0xa6, 0x63, 0x5b, 0x80, 0x4a, 0xad, 0x4d, 0xed, 0xbf, 0xee, 0x49, 0xb3, 0x06}} , + {{0xf8, 0x64, 0x8b, 0x60, 0x90, 0xe9, 0xde, 0x44, 0x77, 0xb9, 0x07, 0x36, 0x32, 0xc2, 0x50, 0xf5, 0x65, 0xdf, 0x48, 0x4c, 0x37, 0xaa, 0x68, 0xab, 0x9a, 0x1f, 0x3e, 0xff, 0x89, 0x92, 0xa0, 0x07}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x7d, 0x4f, 0x9c, 0x19, 0xc0, 0x4a, 0x31, 0xec, 0xf9, 0xaa, 0xeb, 0xb2, 0x16, 0x9c, 0xa3, 0x66, 0x5f, 0xd1, 0xd4, 0xed, 0xb8, 0x92, 0x1c, 0xab, 0xda, 0xea, 0xd9, 0x57, 0xdf, 0x4c, 0x2a, 0x48}} , + {{0x4b, 0xb0, 0x4e, 0x6e, 0x11, 0x3b, 0x51, 0xbd, 0x6a, 0xfd, 0xe4, 0x25, 0xa5, 0x5f, 0x11, 0x3f, 0x98, 0x92, 0x51, 0x14, 0xc6, 0x5f, 0x3c, 0x0b, 0xa8, 0xf7, 0xc2, 0x81, 0x43, 0xde, 0x91, 0x73}}}, +{{{0x3c, 0x8f, 0x9f, 0x33, 0x2a, 0x1f, 0x43, 0x33, 0x8f, 0x68, 0xff, 0x1f, 0x3d, 0x73, 0x6b, 0xbf, 0x68, 0xcc, 0x7d, 0x13, 0x6c, 0x24, 0x4b, 0xcc, 0x4d, 0x24, 0x0d, 0xfe, 0xde, 0x86, 0xad, 0x3b}} , + {{0x79, 0x51, 0x81, 0x01, 0xdc, 0x73, 0x53, 0xe0, 0x6e, 0x9b, 0xea, 0x68, 0x3f, 0x5c, 0x14, 0x84, 0x53, 0x8d, 0x4b, 0xc0, 0x9f, 0x9f, 0x89, 0x2b, 0x8c, 0xba, 0x86, 0xfa, 0xf2, 0xcd, 0xe3, 0x2d}}}, +{{{0x06, 0xf9, 0x29, 0x5a, 0xdb, 0x3d, 0x84, 0x52, 0xab, 0xcc, 0x6b, 0x60, 0x9d, 0xb7, 0x4a, 0x0e, 0x36, 0x63, 0x91, 0xad, 0xa0, 0x95, 0xb0, 0x97, 0x89, 0x4e, 0xcf, 0x7d, 0x3c, 0xe5, 0x7c, 0x28}} , + {{0x2e, 0x69, 0x98, 0xfd, 0xc6, 0xbd, 0xcc, 0xca, 0xdf, 0x9a, 0x44, 0x7e, 0x9d, 0xca, 0x89, 0x6d, 0xbf, 0x27, 0xc2, 0xf8, 0xcd, 0x46, 0x00, 0x2b, 0xb5, 0x58, 0x4e, 0xb7, 0x89, 0x09, 0xe9, 0x2d}}}, +{{{0x54, 0xbe, 0x75, 0xcb, 0x05, 0xb0, 0x54, 0xb7, 0xe7, 0x26, 0x86, 0x4a, 0xfc, 0x19, 0xcf, 0x27, 0x46, 0xd4, 0x22, 0x96, 0x5a, 0x11, 0xe8, 0xd5, 0x1b, 0xed, 0x71, 0xc5, 0x5d, 0xc8, 0xaf, 0x45}} , + {{0x40, 0x7b, 0x77, 0x57, 0x49, 0x9e, 0x80, 0x39, 0x23, 0xee, 0x81, 0x0b, 0x22, 0xcf, 0xdb, 0x7a, 0x2f, 0x14, 0xb8, 0x57, 0x8f, 0xa1, 0x39, 0x1e, 0x77, 0xfc, 0x0b, 0xa6, 0xbf, 0x8a, 0x0c, 0x6c}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x77, 0x3a, 0xd4, 0xd8, 0x27, 0xcf, 0xe8, 0xa1, 0x72, 0x9d, 0xca, 0xdd, 0x0d, 0x96, 0xda, 0x79, 0xed, 0x56, 0x42, 0x15, 0x60, 0xc7, 0x1c, 0x6b, 0x26, 0x30, 0xf6, 0x6a, 0x95, 0x67, 0xf3, 0x0a}} , + {{0xc5, 0x08, 0xa4, 0x2b, 0x2f, 0xbd, 0x31, 0x81, 0x2a, 0xa6, 0xb6, 0xe4, 0x00, 0x91, 0xda, 0x3d, 0xb2, 0xb0, 0x96, 0xce, 0x8a, 0xd2, 0x8d, 0x70, 0xb3, 0xd3, 0x34, 0x01, 0x90, 0x8d, 0x10, 0x21}}}, +{{{0x33, 0x0d, 0xe7, 0xba, 0x4f, 0x07, 0xdf, 0x8d, 0xea, 0x7d, 0xa0, 0xc5, 0xd6, 0xb1, 0xb0, 0xe5, 0x57, 0x1b, 0x5b, 0xf5, 0x45, 0x13, 0x14, 0x64, 0x5a, 0xeb, 0x5c, 0xfc, 0x54, 0x01, 0x76, 0x2b}} , + {{0x02, 0x0c, 0xc2, 0xaf, 0x96, 0x36, 0xfe, 0x4a, 0xe2, 0x54, 0x20, 0x6a, 0xeb, 0xb2, 0x9f, 0x62, 0xd7, 0xce, 0xa2, 0x3f, 0x20, 0x11, 0x34, 0x37, 0xe0, 0x42, 0xed, 0x6f, 0xf9, 0x1a, 0xc8, 0x7d}}}, +{{{0xd8, 0xb9, 0x11, 0xe8, 0x36, 0x3f, 0x42, 0xc1, 0xca, 0xdc, 0xd3, 0xf1, 0xc8, 0x23, 0x3d, 0x4f, 0x51, 0x7b, 0x9d, 0x8d, 0xd8, 0xe4, 0xa0, 0xaa, 0xf3, 0x04, 0xd6, 0x11, 0x93, 0xc8, 0x35, 0x45}} , + {{0x61, 0x36, 0xd6, 0x08, 0x90, 0xbf, 0xa7, 0x7a, 0x97, 0x6c, 0x0f, 0x84, 0xd5, 0x33, 0x2d, 0x37, 0xc9, 0x6a, 0x80, 0x90, 0x3d, 0x0a, 0xa2, 0xaa, 0xe1, 0xb8, 0x84, 0xba, 0x61, 0x36, 0xdd, 0x69}}}, +{{{0x6b, 0xdb, 0x5b, 0x9c, 0xc6, 0x92, 0xbc, 0x23, 0xaf, 0xc5, 0xb8, 0x75, 0xf8, 0x42, 0xfa, 0xd6, 0xb6, 0x84, 0x94, 0x63, 0x98, 0x93, 0x48, 0x78, 0x38, 0xcd, 0xbb, 0x18, 0x34, 0xc3, 0xdb, 0x67}} , + {{0x96, 0xf3, 0x3a, 0x09, 0x56, 0xb0, 0x6f, 0x7c, 0x51, 0x1e, 0x1b, 0x39, 0x48, 0xea, 0xc9, 0x0c, 0x25, 0xa2, 0x7a, 0xca, 0xe7, 0x92, 0xfc, 0x59, 0x30, 0xa3, 0x89, 0x85, 0xdf, 0x6f, 0x43, 0x38}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x79, 0x84, 0x44, 0x19, 0xbd, 0xe9, 0x54, 0xc4, 0xc0, 0x6e, 0x2a, 0xa8, 0xa8, 0x9b, 0x43, 0xd5, 0x71, 0x22, 0x5f, 0xdc, 0x01, 0xfa, 0xdf, 0xb3, 0xb8, 0x47, 0x4b, 0x0a, 0xa5, 0x44, 0xea, 0x29}} , + {{0x05, 0x90, 0x50, 0xaf, 0x63, 0x5f, 0x9d, 0x9e, 0xe1, 0x9d, 0x38, 0x97, 0x1f, 0x6c, 0xac, 0x30, 0x46, 0xb2, 0x6a, 0x19, 0xd1, 0x4b, 0xdb, 0xbb, 0x8c, 0xda, 0x2e, 0xab, 0xc8, 0x5a, 0x77, 0x6c}}}, +{{{0x2b, 0xbe, 0xaf, 0xa1, 0x6d, 0x2f, 0x0b, 0xb1, 0x8f, 0xe3, 0xe0, 0x38, 0xcd, 0x0b, 0x41, 0x1b, 0x4a, 0x15, 0x07, 0xf3, 0x6f, 0xdc, 0xb8, 0xe9, 0xde, 0xb2, 0xa3, 0x40, 0x01, 0xa6, 0x45, 0x1e}} , + {{0x76, 0x0a, 0xda, 0x8d, 0x2c, 0x07, 0x3f, 0x89, 0x7d, 0x04, 0xad, 0x43, 0x50, 0x6e, 0xd2, 0x47, 0xcb, 0x8a, 0xe6, 0x85, 0x1a, 0x24, 0xf3, 0xd2, 0x60, 0xfd, 0xdf, 0x73, 0xa4, 0x0d, 0x73, 0x0e}}}, +{{{0xfd, 0x67, 0x6b, 0x71, 0x9b, 0x81, 0x53, 0x39, 0x39, 0xf4, 0xb8, 0xd5, 0xc3, 0x30, 0x9b, 0x3b, 0x7c, 0xa3, 0xf0, 0xd0, 0x84, 0x21, 0xd6, 0xbf, 0xb7, 0x4c, 0x87, 0x13, 0x45, 0x2d, 0xa7, 0x55}} , + {{0x5d, 0x04, 0xb3, 0x40, 0x28, 0x95, 0x2d, 0x30, 0x83, 0xec, 0x5e, 0xe4, 0xff, 0x75, 0xfe, 0x79, 0x26, 0x9d, 0x1d, 0x36, 0xcd, 0x0a, 0x15, 0xd2, 0x24, 0x14, 0x77, 0x71, 0xd7, 0x8a, 0x1b, 0x04}}}, +{{{0x5d, 0x93, 0xc9, 0xbe, 0xaa, 0x90, 0xcd, 0x9b, 0xfb, 0x73, 0x7e, 0xb0, 0x64, 0x98, 0x57, 0x44, 0x42, 0x41, 0xb1, 0xaf, 0xea, 0xc1, 0xc3, 0x22, 0xff, 0x60, 0x46, 0xcb, 0x61, 0x81, 0x70, 0x61}} , + {{0x0d, 0x82, 0xb9, 0xfe, 0x21, 0xcd, 0xc4, 0xf5, 0x98, 0x0c, 0x4e, 0x72, 0xee, 0x87, 0x49, 0xf8, 0xa1, 0x95, 0xdf, 0x8f, 0x2d, 0xbd, 0x21, 0x06, 0x7c, 0x15, 0xe8, 0x12, 0x6d, 0x93, 0xd6, 0x38}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x91, 0xf7, 0x51, 0xd9, 0xef, 0x7d, 0x42, 0x01, 0x13, 0xe9, 0xb8, 0x7f, 0xa6, 0x49, 0x17, 0x64, 0x21, 0x80, 0x83, 0x2c, 0x63, 0x4c, 0x60, 0x09, 0x59, 0x91, 0x92, 0x77, 0x39, 0x51, 0xf4, 0x48}} , + {{0x60, 0xd5, 0x22, 0x83, 0x08, 0x2f, 0xff, 0x99, 0x3e, 0x69, 0x6d, 0x88, 0xda, 0xe7, 0x5b, 0x52, 0x26, 0x31, 0x2a, 0xe5, 0x89, 0xde, 0x68, 0x90, 0xb6, 0x22, 0x5a, 0xbd, 0xd3, 0x85, 0x53, 0x31}}}, +{{{0xd8, 0xce, 0xdc, 0xf9, 0x3c, 0x4b, 0xa2, 0x1d, 0x2c, 0x2f, 0x36, 0xbe, 0x7a, 0xfc, 0xcd, 0xbc, 0xdc, 0xf9, 0x30, 0xbd, 0xff, 0x05, 0xc7, 0xe4, 0x8e, 0x17, 0x62, 0xf8, 0x4d, 0xa0, 0x56, 0x79}} , + {{0x82, 0xe7, 0xf6, 0xba, 0x53, 0x84, 0x0a, 0xa3, 0x34, 0xff, 0x3c, 0xa3, 0x6a, 0xa1, 0x37, 0xea, 0xdd, 0xb6, 0x95, 0xb3, 0x78, 0x19, 0x76, 0x1e, 0x55, 0x2f, 0x77, 0x2e, 0x7f, 0xc1, 0xea, 0x5e}}}, +{{{0x83, 0xe1, 0x6e, 0xa9, 0x07, 0x33, 0x3e, 0x83, 0xff, 0xcb, 0x1c, 0x9f, 0xb1, 0xa3, 0xb4, 0xc9, 0xe1, 0x07, 0x97, 0xff, 0xf8, 0x23, 0x8f, 0xce, 0x40, 0xfd, 0x2e, 0x5e, 0xdb, 0x16, 0x43, 0x2d}} , + {{0xba, 0x38, 0x02, 0xf7, 0x81, 0x43, 0x83, 0xa3, 0x20, 0x4f, 0x01, 0x3b, 0x8a, 0x04, 0x38, 0x31, 0xc6, 0x0f, 0xc8, 0xdf, 0xd7, 0xfa, 0x2f, 0x88, 0x3f, 0xfc, 0x0c, 0x76, 0xc4, 0xa6, 0x45, 0x72}}}, +{{{0xbb, 0x0c, 0xbc, 0x6a, 0xa4, 0x97, 0x17, 0x93, 0x2d, 0x6f, 0xde, 0x72, 0x10, 0x1c, 0x08, 0x2c, 0x0f, 0x80, 0x32, 0x68, 0x27, 0xd4, 0xab, 0xdd, 0xc5, 0x58, 0x61, 0x13, 0x6d, 0x11, 0x1e, 0x4d}} , + {{0x1a, 0xb9, 0xc9, 0x10, 0xfb, 0x1e, 0x4e, 0xf4, 0x84, 0x4b, 0x8a, 0x5e, 0x7b, 0x4b, 0xe8, 0x43, 0x8c, 0x8f, 0x00, 0xb5, 0x54, 0x13, 0xc5, 0x5c, 0xb6, 0x35, 0x4e, 0x9d, 0xe4, 0x5b, 0x41, 0x6d}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x15, 0x7d, 0x12, 0x48, 0x82, 0x14, 0x42, 0xcd, 0x32, 0xd4, 0x4b, 0xc1, 0x72, 0x61, 0x2a, 0x8c, 0xec, 0xe2, 0xf8, 0x24, 0x45, 0x94, 0xe3, 0xbe, 0xdd, 0x67, 0xa8, 0x77, 0x5a, 0xae, 0x5b, 0x4b}} , + {{0xcb, 0x77, 0x9a, 0x20, 0xde, 0xb8, 0x23, 0xd9, 0xa0, 0x0f, 0x8c, 0x7b, 0xa5, 0xcb, 0xae, 0xb6, 0xec, 0x42, 0x67, 0x0e, 0x58, 0xa4, 0x75, 0x98, 0x21, 0x71, 0x84, 0xb3, 0xe0, 0x76, 0x94, 0x73}}}, +{{{0xdf, 0xfc, 0x69, 0x28, 0x23, 0x3f, 0x5b, 0xf8, 0x3b, 0x24, 0x37, 0xf3, 0x1d, 0xd5, 0x22, 0x6b, 0xd0, 0x98, 0xa8, 0x6c, 0xcf, 0xff, 0x06, 0xe1, 0x13, 0xdf, 0xb9, 0xc1, 0x0c, 0xa9, 0xbf, 0x33}} , + {{0xd9, 0x81, 0xda, 0xb2, 0x4f, 0x82, 0x9d, 0x43, 0x81, 0x09, 0xf1, 0xd2, 0x01, 0xef, 0xac, 0xf4, 0x2d, 0x7d, 0x01, 0x09, 0xf1, 0xff, 0xa5, 0x9f, 0xe5, 0xca, 0x27, 0x63, 0xdb, 0x20, 0xb1, 0x53}}}, +{{{0x67, 0x02, 0xe8, 0xad, 0xa9, 0x34, 0xd4, 0xf0, 0x15, 0x81, 0xaa, 0xc7, 0x4d, 0x87, 0x94, 0xea, 0x75, 0xe7, 0x4c, 0x94, 0x04, 0x0e, 0x69, 0x87, 0xe7, 0x51, 0x91, 0x10, 0x03, 0xc7, 0xbe, 0x56}} , + {{0x32, 0xfb, 0x86, 0xec, 0x33, 0x6b, 0x2e, 0x51, 0x2b, 0xc8, 0xfa, 0x6c, 0x70, 0x47, 0x7e, 0xce, 0x05, 0x0c, 0x71, 0xf3, 0xb4, 0x56, 0xa6, 0xdc, 0xcc, 0x78, 0x07, 0x75, 0xd0, 0xdd, 0xb2, 0x6a}}}, +{{{0xc6, 0xef, 0xb9, 0xc0, 0x2b, 0x22, 0x08, 0x1e, 0x71, 0x70, 0xb3, 0x35, 0x9c, 0x7a, 0x01, 0x92, 0x44, 0x9a, 0xf6, 0xb0, 0x58, 0x95, 0xc1, 0x9b, 0x02, 0xed, 0x2d, 0x7c, 0x34, 0x29, 0x49, 0x44}} , + {{0x45, 0x62, 0x1d, 0x2e, 0xff, 0x2a, 0x1c, 0x21, 0xa4, 0x25, 0x7b, 0x0d, 0x8c, 0x15, 0x39, 0xfc, 0x8f, 0x7c, 0xa5, 0x7d, 0x1e, 0x25, 0xa3, 0x45, 0xd6, 0xab, 0xbd, 0xcb, 0xc5, 0x5e, 0x78, 0x77}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xd0, 0xd3, 0x42, 0xed, 0x1d, 0x00, 0x3c, 0x15, 0x2c, 0x9c, 0x77, 0x81, 0xd2, 0x73, 0xd1, 0x06, 0xd5, 0xc4, 0x7f, 0x94, 0xbb, 0x92, 0x2d, 0x2c, 0x4b, 0x45, 0x4b, 0xe9, 0x2a, 0x89, 0x6b, 0x2b}} , + {{0xd2, 0x0c, 0x88, 0xc5, 0x48, 0x4d, 0xea, 0x0d, 0x4a, 0xc9, 0x52, 0x6a, 0x61, 0x79, 0xe9, 0x76, 0xf3, 0x85, 0x52, 0x5c, 0x1b, 0x2c, 0xe1, 0xd6, 0xc4, 0x0f, 0x18, 0x0e, 0x4e, 0xf6, 0x1c, 0x7f}}}, +{{{0xb4, 0x04, 0x2e, 0x42, 0xcb, 0x1f, 0x2b, 0x11, 0x51, 0x7b, 0x08, 0xac, 0xaa, 0x3e, 0x9e, 0x52, 0x60, 0xb7, 0xc2, 0x61, 0x57, 0x8c, 0x84, 0xd5, 0x18, 0xa6, 0x19, 0xfc, 0xb7, 0x75, 0x91, 0x1b}} , + {{0xe8, 0x68, 0xca, 0x44, 0xc8, 0x38, 0x38, 0xcc, 0x53, 0x0a, 0x32, 0x35, 0xcc, 0x52, 0xcb, 0x0e, 0xf7, 0xc5, 0xe7, 0xec, 0x3d, 0x85, 0xcc, 0x58, 0xe2, 0x17, 0x47, 0xff, 0x9f, 0xa5, 0x30, 0x17}}}, +{{{0xe3, 0xae, 0xc8, 0xc1, 0x71, 0x75, 0x31, 0x00, 0x37, 0x41, 0x5c, 0x0e, 0x39, 0xda, 0x73, 0xa0, 0xc7, 0x97, 0x36, 0x6c, 0x5b, 0xf2, 0xee, 0x64, 0x0a, 0x3d, 0x89, 0x1e, 0x1d, 0x49, 0x8c, 0x37}} , + {{0x4c, 0xe6, 0xb0, 0xc1, 0xa5, 0x2a, 0x82, 0x09, 0x08, 0xad, 0x79, 0x9c, 0x56, 0xf6, 0xf9, 0xc1, 0xd7, 0x7c, 0x39, 0x7f, 0x93, 0xca, 0x11, 0x55, 0xbf, 0x07, 0x1b, 0x82, 0x29, 0x69, 0x95, 0x5c}}}, +{{{0x87, 0xee, 0xa6, 0x56, 0x9e, 0xc2, 0x9a, 0x56, 0x24, 0x42, 0x85, 0x4d, 0x98, 0x31, 0x1e, 0x60, 0x4d, 0x87, 0x85, 0x04, 0xae, 0x46, 0x12, 0xf9, 0x8e, 0x7f, 0xe4, 0x7f, 0xf6, 0x1c, 0x37, 0x01}} , + {{0x73, 0x4c, 0xb6, 0xc5, 0xc4, 0xe9, 0x6c, 0x85, 0x48, 0x4a, 0x5a, 0xac, 0xd9, 0x1f, 0x43, 0xf8, 0x62, 0x5b, 0xee, 0x98, 0x2a, 0x33, 0x8e, 0x79, 0xce, 0x61, 0x06, 0x35, 0xd8, 0xd7, 0xca, 0x71}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x72, 0xd3, 0xae, 0xa6, 0xca, 0x8f, 0xcd, 0xcc, 0x78, 0x8e, 0x19, 0x4d, 0xa7, 0xd2, 0x27, 0xe9, 0xa4, 0x3c, 0x16, 0x5b, 0x84, 0x80, 0xf9, 0xd0, 0xcc, 0x6a, 0x1e, 0xca, 0x1e, 0x67, 0xbd, 0x63}} , + {{0x7b, 0x6e, 0x2a, 0xd2, 0x87, 0x48, 0xff, 0xa1, 0xca, 0xe9, 0x15, 0x85, 0xdc, 0xdb, 0x2c, 0x39, 0x12, 0x91, 0xa9, 0x20, 0xaa, 0x4f, 0x29, 0xf4, 0x15, 0x7a, 0xd2, 0xf5, 0x32, 0xcc, 0x60, 0x04}}}, +{{{0xe5, 0x10, 0x47, 0x3b, 0xfa, 0x90, 0xfc, 0x30, 0xb5, 0xea, 0x6f, 0x56, 0x8f, 0xfb, 0x0e, 0xa7, 0x3b, 0xc8, 0xb2, 0xff, 0x02, 0x7a, 0x33, 0x94, 0x93, 0x2a, 0x03, 0xe0, 0x96, 0x3a, 0x6c, 0x0f}} , + {{0x5a, 0x63, 0x67, 0xe1, 0x9b, 0x47, 0x78, 0x9f, 0x38, 0x79, 0xac, 0x97, 0x66, 0x1d, 0x5e, 0x51, 0xee, 0x24, 0x42, 0xe8, 0x58, 0x4b, 0x8a, 0x03, 0x75, 0x86, 0x37, 0x86, 0xe2, 0x97, 0x4e, 0x3d}}}, +{{{0x3f, 0x75, 0x8e, 0xb4, 0xff, 0xd8, 0xdd, 0xd6, 0x37, 0x57, 0x9d, 0x6d, 0x3b, 0xbd, 0xd5, 0x60, 0x88, 0x65, 0x9a, 0xb9, 0x4a, 0x68, 0x84, 0xa2, 0x67, 0xdd, 0x17, 0x25, 0x97, 0x04, 0x8b, 0x5e}} , + {{0xbb, 0x40, 0x5e, 0xbc, 0x16, 0x92, 0x05, 0xc4, 0xc0, 0x4e, 0x72, 0x90, 0x0e, 0xab, 0xcf, 0x8a, 0xed, 0xef, 0xb9, 0x2d, 0x3b, 0xf8, 0x43, 0x5b, 0xba, 0x2d, 0xeb, 0x2f, 0x52, 0xd2, 0xd1, 0x5a}}}, +{{{0x40, 0xb4, 0xab, 0xe6, 0xad, 0x9f, 0x46, 0x69, 0x4a, 0xb3, 0x8e, 0xaa, 0xea, 0x9c, 0x8a, 0x20, 0x16, 0x5d, 0x8c, 0x13, 0xbd, 0xf6, 0x1d, 0xc5, 0x24, 0xbd, 0x90, 0x2a, 0x1c, 0xc7, 0x13, 0x3b}} , + {{0x54, 0xdc, 0x16, 0x0d, 0x18, 0xbe, 0x35, 0x64, 0x61, 0x52, 0x02, 0x80, 0xaf, 0x05, 0xf7, 0xa6, 0x42, 0xd3, 0x8f, 0x2e, 0x79, 0x26, 0xa8, 0xbb, 0xb2, 0x17, 0x48, 0xb2, 0x7a, 0x0a, 0x89, 0x14}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x20, 0xa8, 0x88, 0xe3, 0x91, 0xc0, 0x6e, 0xbb, 0x8a, 0x27, 0x82, 0x51, 0x83, 0xb2, 0x28, 0xa9, 0x83, 0xeb, 0xa6, 0xa9, 0x4d, 0x17, 0x59, 0x22, 0x54, 0x00, 0x50, 0x45, 0xcb, 0x48, 0x4b, 0x18}} , + {{0x33, 0x7c, 0xe7, 0x26, 0xba, 0x4d, 0x32, 0xfe, 0x53, 0xf4, 0xfa, 0x83, 0xe3, 0xa5, 0x79, 0x66, 0x73, 0xef, 0x80, 0x23, 0x68, 0xc2, 0x60, 0xdd, 0xa9, 0x33, 0xdc, 0x03, 0x7a, 0xe0, 0xe0, 0x3e}}}, +{{{0x34, 0x5c, 0x13, 0xfb, 0xc0, 0xe3, 0x78, 0x2b, 0x54, 0x58, 0x22, 0x9b, 0x76, 0x81, 0x7f, 0x93, 0x9c, 0x25, 0x3c, 0xd2, 0xe9, 0x96, 0x21, 0x26, 0x08, 0xf5, 0xed, 0x95, 0x11, 0xae, 0x04, 0x5a}} , + {{0xb9, 0xe8, 0xc5, 0x12, 0x97, 0x1f, 0x83, 0xfe, 0x3e, 0x94, 0x99, 0xd4, 0x2d, 0xf9, 0x52, 0x59, 0x5c, 0x82, 0xa6, 0xf0, 0x75, 0x7e, 0xe8, 0xec, 0xcc, 0xac, 0x18, 0x21, 0x09, 0x67, 0x66, 0x67}}}, +{{{0xb3, 0x40, 0x29, 0xd1, 0xcb, 0x1b, 0x08, 0x9e, 0x9c, 0xb7, 0x53, 0xb9, 0x3b, 0x71, 0x08, 0x95, 0x12, 0x1a, 0x58, 0xaf, 0x7e, 0x82, 0x52, 0x43, 0x4f, 0x11, 0x39, 0xf4, 0x93, 0x1a, 0x26, 0x05}} , + {{0x6e, 0x44, 0xa3, 0xf9, 0x64, 0xaf, 0xe7, 0x6d, 0x7d, 0xdf, 0x1e, 0xac, 0x04, 0xea, 0x3b, 0x5f, 0x9b, 0xe8, 0x24, 0x9d, 0x0e, 0xe5, 0x2e, 0x3e, 0xdf, 0xa9, 0xf7, 0xd4, 0x50, 0x71, 0xf0, 0x78}}}, +{{{0x3e, 0xa8, 0x38, 0xc2, 0x57, 0x56, 0x42, 0x9a, 0xb1, 0xe2, 0xf8, 0x45, 0xaa, 0x11, 0x48, 0x5f, 0x17, 0xc4, 0x54, 0x27, 0xdc, 0x5d, 0xaa, 0xdd, 0x41, 0xbc, 0xdf, 0x81, 0xb9, 0x53, 0xee, 0x52}} , + {{0xc3, 0xf1, 0xa7, 0x6d, 0xb3, 0x5f, 0x92, 0x6f, 0xcc, 0x91, 0xb8, 0x95, 0x05, 0xdf, 0x3c, 0x64, 0x57, 0x39, 0x61, 0x51, 0xad, 0x8c, 0x38, 0x7b, 0xc8, 0xde, 0x00, 0x34, 0xbe, 0xa1, 0xb0, 0x7e}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x25, 0x24, 0x1d, 0x8a, 0x67, 0x20, 0xee, 0x42, 0xeb, 0x38, 0xed, 0x0b, 0x8b, 0xcd, 0x46, 0x9d, 0x5e, 0x6b, 0x1e, 0x24, 0x9d, 0x12, 0x05, 0x1a, 0xcc, 0x05, 0x4e, 0x92, 0x38, 0xe1, 0x1f, 0x50}} , + {{0x4e, 0xee, 0x1c, 0x91, 0xe6, 0x11, 0xbd, 0x8e, 0x55, 0x1a, 0x18, 0x75, 0x66, 0xaf, 0x4d, 0x7b, 0x0f, 0xae, 0x6d, 0x85, 0xca, 0x82, 0x58, 0x21, 0x9c, 0x18, 0xe0, 0xed, 0xec, 0x22, 0x80, 0x2f}}}, +{{{0x68, 0x3b, 0x0a, 0x39, 0x1d, 0x6a, 0x15, 0x57, 0xfc, 0xf0, 0x63, 0x54, 0xdb, 0x39, 0xdb, 0xe8, 0x5c, 0x64, 0xff, 0xa0, 0x09, 0x4f, 0x3b, 0xb7, 0x32, 0x60, 0x99, 0x94, 0xfd, 0x94, 0x82, 0x2d}} , + {{0x24, 0xf6, 0x5a, 0x44, 0xf1, 0x55, 0x2c, 0xdb, 0xea, 0x7c, 0x84, 0x7c, 0x01, 0xac, 0xe3, 0xfd, 0xc9, 0x27, 0xc1, 0x5a, 0xb9, 0xde, 0x4f, 0x5a, 0x90, 0xdd, 0xc6, 0x67, 0xaa, 0x6f, 0x8a, 0x3a}}}, +{{{0x78, 0x52, 0x87, 0xc9, 0x97, 0x63, 0xb1, 0xdd, 0x54, 0x5f, 0xc1, 0xf8, 0xf1, 0x06, 0xa6, 0xa8, 0xa3, 0x88, 0x82, 0xd4, 0xcb, 0xa6, 0x19, 0xdd, 0xd1, 0x11, 0x87, 0x08, 0x17, 0x4c, 0x37, 0x2a}} , + {{0xa1, 0x0c, 0xf3, 0x08, 0x43, 0xd9, 0x24, 0x1e, 0x83, 0xa7, 0xdf, 0x91, 0xca, 0xbd, 0x69, 0x47, 0x8d, 0x1b, 0xe2, 0xb9, 0x4e, 0xb5, 0xe1, 0x76, 0xb3, 0x1c, 0x93, 0x03, 0xce, 0x5f, 0xb3, 0x5a}}}, +{{{0x1d, 0xda, 0xe4, 0x61, 0x03, 0x50, 0xa9, 0x8b, 0x68, 0x18, 0xef, 0xb2, 0x1c, 0x84, 0x3b, 0xa2, 0x44, 0x95, 0xa3, 0x04, 0x3b, 0xd6, 0x99, 0x00, 0xaf, 0x76, 0x42, 0x67, 0x02, 0x7d, 0x85, 0x56}} , + {{0xce, 0x72, 0x0e, 0x29, 0x84, 0xb2, 0x7d, 0xd2, 0x45, 0xbe, 0x57, 0x06, 0xed, 0x7f, 0xcf, 0xed, 0xcd, 0xef, 0x19, 0xd6, 0xbc, 0x15, 0x79, 0x64, 0xd2, 0x18, 0xe3, 0x20, 0x67, 0x3a, 0x54, 0x0b}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x52, 0xfd, 0x04, 0xc5, 0xfb, 0x99, 0xe7, 0xe8, 0xfb, 0x8c, 0xe1, 0x42, 0x03, 0xef, 0x9d, 0xd9, 0x9e, 0x4d, 0xf7, 0x80, 0xcf, 0x2e, 0xcc, 0x9b, 0x45, 0xc9, 0x7b, 0x7a, 0xbc, 0x37, 0xa8, 0x52}} , + {{0x96, 0x11, 0x41, 0x8a, 0x47, 0x91, 0xfe, 0xb6, 0xda, 0x7a, 0x54, 0x63, 0xd1, 0x14, 0x35, 0x05, 0x86, 0x8c, 0xa9, 0x36, 0x3f, 0xf2, 0x85, 0x54, 0x4e, 0x92, 0xd8, 0x85, 0x01, 0x46, 0xd6, 0x50}}}, +{{{0x53, 0xcd, 0xf3, 0x86, 0x40, 0xe6, 0x39, 0x42, 0x95, 0xd6, 0xcb, 0x45, 0x1a, 0x20, 0xc8, 0x45, 0x4b, 0x32, 0x69, 0x04, 0xb1, 0xaf, 0x20, 0x46, 0xc7, 0x6b, 0x23, 0x5b, 0x69, 0xee, 0x30, 0x3f}} , + {{0x70, 0x83, 0x47, 0xc0, 0xdb, 0x55, 0x08, 0xa8, 0x7b, 0x18, 0x6d, 0xf5, 0x04, 0x5a, 0x20, 0x0c, 0x4a, 0x8c, 0x60, 0xae, 0xae, 0x0f, 0x64, 0x55, 0x55, 0x2e, 0xd5, 0x1d, 0x53, 0x31, 0x42, 0x41}}}, +{{{0xca, 0xfc, 0x88, 0x6b, 0x96, 0x78, 0x0a, 0x8b, 0x83, 0xdc, 0xbc, 0xaf, 0x40, 0xb6, 0x8d, 0x7f, 0xef, 0xb4, 0xd1, 0x3f, 0xcc, 0xa2, 0x74, 0xc9, 0xc2, 0x92, 0x55, 0x00, 0xab, 0xdb, 0xbf, 0x4f}} , + {{0x93, 0x1c, 0x06, 0x2d, 0x66, 0x65, 0x02, 0xa4, 0x97, 0x18, 0xfd, 0x00, 0xe7, 0xab, 0x03, 0xec, 0xce, 0xc1, 0xbf, 0x37, 0xf8, 0x13, 0x53, 0xa5, 0xe5, 0x0c, 0x3a, 0xa8, 0x55, 0xb9, 0xff, 0x68}}}, +{{{0xe4, 0xe6, 0x6d, 0x30, 0x7d, 0x30, 0x35, 0xc2, 0x78, 0x87, 0xf9, 0xfc, 0x6b, 0x5a, 0xc3, 0xb7, 0x65, 0xd8, 0x2e, 0xc7, 0xa5, 0x0c, 0xc6, 0xdc, 0x12, 0xaa, 0xd6, 0x4f, 0xc5, 0x38, 0xbc, 0x0e}} , + {{0xe2, 0x3c, 0x76, 0x86, 0x38, 0xf2, 0x7b, 0x2c, 0x16, 0x78, 0x8d, 0xf5, 0xa4, 0x15, 0xda, 0xdb, 0x26, 0x85, 0xa0, 0x56, 0xdd, 0x1d, 0xe3, 0xb3, 0xfd, 0x40, 0xef, 0xf2, 0xd9, 0xa1, 0xb3, 0x04}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xdb, 0x49, 0x0e, 0xe6, 0x58, 0x10, 0x7a, 0x52, 0xda, 0xb5, 0x7d, 0x37, 0x6a, 0x3e, 0xa1, 0x78, 0xce, 0xc7, 0x1c, 0x24, 0x23, 0xdb, 0x7d, 0xfb, 0x8c, 0x8d, 0xdc, 0x30, 0x67, 0x69, 0x75, 0x3b}} , + {{0xa9, 0xea, 0x6d, 0x16, 0x16, 0x60, 0xf4, 0x60, 0x87, 0x19, 0x44, 0x8c, 0x4a, 0x8b, 0x3e, 0xfb, 0x16, 0x00, 0x00, 0x54, 0xa6, 0x9e, 0x9f, 0xef, 0xcf, 0xd9, 0xd2, 0x4c, 0x74, 0x31, 0xd0, 0x34}}}, +{{{0xa4, 0xeb, 0x04, 0xa4, 0x8c, 0x8f, 0x71, 0x27, 0x95, 0x85, 0x5d, 0x55, 0x4b, 0xb1, 0x26, 0x26, 0xc8, 0xae, 0x6a, 0x7d, 0xa2, 0x21, 0xca, 0xce, 0x38, 0xab, 0x0f, 0xd0, 0xd5, 0x2b, 0x6b, 0x00}} , + {{0xe5, 0x67, 0x0c, 0xf1, 0x3a, 0x9a, 0xea, 0x09, 0x39, 0xef, 0xd1, 0x30, 0xbc, 0x33, 0xba, 0xb1, 0x6a, 0xc5, 0x27, 0x08, 0x7f, 0x54, 0x80, 0x3d, 0xab, 0xf6, 0x15, 0x7a, 0xc2, 0x40, 0x73, 0x72}}}, +{{{0x84, 0x56, 0x82, 0xb6, 0x12, 0x70, 0x7f, 0xf7, 0xf0, 0xbd, 0x5b, 0xa9, 0xd5, 0xc5, 0x5f, 0x59, 0xbf, 0x7f, 0xb3, 0x55, 0x22, 0x02, 0xc9, 0x44, 0x55, 0x87, 0x8f, 0x96, 0x98, 0x64, 0x6d, 0x15}} , + {{0xb0, 0x8b, 0xaa, 0x1e, 0xec, 0xc7, 0xa5, 0x8f, 0x1f, 0x92, 0x04, 0xc6, 0x05, 0xf6, 0xdf, 0xa1, 0xcc, 0x1f, 0x81, 0xf5, 0x0e, 0x9c, 0x57, 0xdc, 0xe3, 0xbb, 0x06, 0x87, 0x1e, 0xfe, 0x23, 0x6c}}}, +{{{0xd8, 0x2b, 0x5b, 0x16, 0xea, 0x20, 0xf1, 0xd3, 0x68, 0x8f, 0xae, 0x5b, 0xd0, 0xa9, 0x1a, 0x19, 0xa8, 0x36, 0xfb, 0x2b, 0x57, 0x88, 0x7d, 0x90, 0xd5, 0xa6, 0xf3, 0xdc, 0x38, 0x89, 0x4e, 0x1f}} , + {{0xcc, 0x19, 0xda, 0x9b, 0x3b, 0x43, 0x48, 0x21, 0x2e, 0x23, 0x4d, 0x3d, 0xae, 0xf8, 0x8c, 0xfc, 0xdd, 0xa6, 0x74, 0x37, 0x65, 0xca, 0xee, 0x1a, 0x19, 0x8e, 0x9f, 0x64, 0x6f, 0x0c, 0x8b, 0x5a}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x25, 0xb9, 0xc2, 0xf0, 0x72, 0xb8, 0x15, 0x16, 0xcc, 0x8d, 0x3c, 0x6f, 0x25, 0xed, 0xf4, 0x46, 0x2e, 0x0c, 0x60, 0x0f, 0xe2, 0x84, 0x34, 0x55, 0x89, 0x59, 0x34, 0x1b, 0xf5, 0x8d, 0xfe, 0x08}} , + {{0xf8, 0xab, 0x93, 0xbc, 0x44, 0xba, 0x1b, 0x75, 0x4b, 0x49, 0x6f, 0xd0, 0x54, 0x2e, 0x63, 0xba, 0xb5, 0xea, 0xed, 0x32, 0x14, 0xc9, 0x94, 0xd8, 0xc5, 0xce, 0xf4, 0x10, 0x68, 0xe0, 0x38, 0x27}}}, +{{{0x74, 0x1c, 0x14, 0x9b, 0xd4, 0x64, 0x61, 0x71, 0x5a, 0xb6, 0x21, 0x33, 0x4f, 0xf7, 0x8e, 0xba, 0xa5, 0x48, 0x9a, 0xc7, 0xfa, 0x9a, 0xf0, 0xb4, 0x62, 0xad, 0xf2, 0x5e, 0xcc, 0x03, 0x24, 0x1a}} , + {{0xf5, 0x76, 0xfd, 0xe4, 0xaf, 0xb9, 0x03, 0x59, 0xce, 0x63, 0xd2, 0x3b, 0x1f, 0xcd, 0x21, 0x0c, 0xad, 0x44, 0xa5, 0x97, 0xac, 0x80, 0x11, 0x02, 0x9b, 0x0c, 0xe5, 0x8b, 0xcd, 0xfb, 0x79, 0x77}}}, +{{{0x15, 0xbe, 0x9a, 0x0d, 0xba, 0x38, 0x72, 0x20, 0x8a, 0xf5, 0xbe, 0x59, 0x93, 0x79, 0xb7, 0xf6, 0x6a, 0x0c, 0x38, 0x27, 0x1a, 0x60, 0xf4, 0x86, 0x3b, 0xab, 0x5a, 0x00, 0xa0, 0xce, 0x21, 0x7d}} , + {{0x6c, 0xba, 0x14, 0xc5, 0xea, 0x12, 0x9e, 0x2e, 0x82, 0x63, 0xce, 0x9b, 0x4a, 0xe7, 0x1d, 0xec, 0xf1, 0x2e, 0x51, 0x1c, 0xf4, 0xd0, 0x69, 0x15, 0x42, 0x9d, 0xa3, 0x3f, 0x0e, 0xbf, 0xe9, 0x5c}}}, +{{{0xe4, 0x0d, 0xf4, 0xbd, 0xee, 0x31, 0x10, 0xed, 0xcb, 0x12, 0x86, 0xad, 0xd4, 0x2f, 0x90, 0x37, 0x32, 0xc3, 0x0b, 0x73, 0xec, 0x97, 0x85, 0xa4, 0x01, 0x1c, 0x76, 0x35, 0xfe, 0x75, 0xdd, 0x71}} , + {{0x11, 0xa4, 0x88, 0x9f, 0x3e, 0x53, 0x69, 0x3b, 0x1b, 0xe0, 0xf7, 0xba, 0x9b, 0xad, 0x4e, 0x81, 0x5f, 0xb5, 0x5c, 0xae, 0xbe, 0x67, 0x86, 0x37, 0x34, 0x8e, 0x07, 0x32, 0x45, 0x4a, 0x67, 0x39}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x90, 0x70, 0x58, 0x20, 0x03, 0x1e, 0x67, 0xb2, 0xc8, 0x9b, 0x58, 0xc5, 0xb1, 0xeb, 0x2d, 0x4a, 0xde, 0x82, 0x8c, 0xf2, 0xd2, 0x14, 0xb8, 0x70, 0x61, 0x4e, 0x73, 0xd6, 0x0b, 0x6b, 0x0d, 0x30}} , + {{0x81, 0xfc, 0x55, 0x5c, 0xbf, 0xa7, 0xc4, 0xbd, 0xe2, 0xf0, 0x4b, 0x8f, 0xe9, 0x7d, 0x99, 0xfa, 0xd3, 0xab, 0xbc, 0xc7, 0x83, 0x2b, 0x04, 0x7f, 0x0c, 0x19, 0x43, 0x03, 0x3d, 0x07, 0xca, 0x40}}}, +{{{0xf9, 0xc8, 0xbe, 0x8c, 0x16, 0x81, 0x39, 0x96, 0xf6, 0x17, 0x58, 0xc8, 0x30, 0x58, 0xfb, 0xc2, 0x03, 0x45, 0xd2, 0x52, 0x76, 0xe0, 0x6a, 0x26, 0x28, 0x5c, 0x88, 0x59, 0x6a, 0x5a, 0x54, 0x42}} , + {{0x07, 0xb5, 0x2e, 0x2c, 0x67, 0x15, 0x9b, 0xfb, 0x83, 0x69, 0x1e, 0x0f, 0xda, 0xd6, 0x29, 0xb1, 0x60, 0xe0, 0xb2, 0xba, 0x69, 0xa2, 0x9e, 0xbd, 0xbd, 0xe0, 0x1c, 0xbd, 0xcd, 0x06, 0x64, 0x70}}}, +{{{0x41, 0xfa, 0x8c, 0xe1, 0x89, 0x8f, 0x27, 0xc8, 0x25, 0x8f, 0x6f, 0x5f, 0x55, 0xf8, 0xde, 0x95, 0x6d, 0x2f, 0x75, 0x16, 0x2b, 0x4e, 0x44, 0xfd, 0x86, 0x6e, 0xe9, 0x70, 0x39, 0x76, 0x97, 0x7e}} , + {{0x17, 0x62, 0x6b, 0x14, 0xa1, 0x7c, 0xd0, 0x79, 0x6e, 0xd8, 0x8a, 0xa5, 0x6d, 0x8c, 0x93, 0xd2, 0x3f, 0xec, 0x44, 0x8d, 0x6e, 0x91, 0x01, 0x8c, 0x8f, 0xee, 0x01, 0x8f, 0xc0, 0xb4, 0x85, 0x0e}}}, +{{{0x02, 0x3a, 0x70, 0x41, 0xe4, 0x11, 0x57, 0x23, 0xac, 0xe6, 0xfc, 0x54, 0x7e, 0xcd, 0xd7, 0x22, 0xcb, 0x76, 0x9f, 0x20, 0xce, 0xa0, 0x73, 0x76, 0x51, 0x3b, 0xa4, 0xf8, 0xe3, 0x62, 0x12, 0x6c}} , + {{0x7f, 0x00, 0x9c, 0x26, 0x0d, 0x6f, 0x48, 0x7f, 0x3a, 0x01, 0xed, 0xc5, 0x96, 0xb0, 0x1f, 0x4f, 0xa8, 0x02, 0x62, 0x27, 0x8a, 0x50, 0x8d, 0x9a, 0x8b, 0x52, 0x0f, 0x1e, 0xcf, 0x41, 0x38, 0x19}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xf5, 0x6c, 0xd4, 0x2f, 0x0f, 0x69, 0x0f, 0x87, 0x3f, 0x61, 0x65, 0x1e, 0x35, 0x34, 0x85, 0xba, 0x02, 0x30, 0xac, 0x25, 0x3d, 0xe2, 0x62, 0xf1, 0xcc, 0xe9, 0x1b, 0xc2, 0xef, 0x6a, 0x42, 0x57}} , + {{0x34, 0x1f, 0x2e, 0xac, 0xd1, 0xc7, 0x04, 0x52, 0x32, 0x66, 0xb2, 0x33, 0x73, 0x21, 0x34, 0x54, 0xf7, 0x71, 0xed, 0x06, 0xb0, 0xff, 0xa6, 0x59, 0x6f, 0x8a, 0x4e, 0xfb, 0x02, 0xb0, 0x45, 0x6b}}}, +{{{0xf5, 0x48, 0x0b, 0x03, 0xc5, 0x22, 0x7d, 0x80, 0x08, 0x53, 0xfe, 0x32, 0xb1, 0xa1, 0x8a, 0x74, 0x6f, 0xbd, 0x3f, 0x85, 0xf4, 0xcf, 0xf5, 0x60, 0xaf, 0x41, 0x7e, 0x3e, 0x46, 0xa3, 0x5a, 0x20}} , + {{0xaa, 0x35, 0x87, 0x44, 0x63, 0x66, 0x97, 0xf8, 0x6e, 0x55, 0x0c, 0x04, 0x3e, 0x35, 0x50, 0xbf, 0x93, 0x69, 0xd2, 0x8b, 0x05, 0x55, 0x99, 0xbe, 0xe2, 0x53, 0x61, 0xec, 0xe8, 0x08, 0x0b, 0x32}}}, +{{{0xb3, 0x10, 0x45, 0x02, 0x69, 0x59, 0x2e, 0x97, 0xd9, 0x64, 0xf8, 0xdb, 0x25, 0x80, 0xdc, 0xc4, 0xd5, 0x62, 0x3c, 0xed, 0x65, 0x91, 0xad, 0xd1, 0x57, 0x81, 0x94, 0xaa, 0xa1, 0x29, 0xfc, 0x68}} , + {{0xdd, 0xb5, 0x7d, 0xab, 0x5a, 0x21, 0x41, 0x53, 0xbb, 0x17, 0x79, 0x0d, 0xd1, 0xa8, 0x0c, 0x0c, 0x20, 0x88, 0x09, 0xe9, 0x84, 0xe8, 0x25, 0x11, 0x67, 0x7a, 0x8b, 0x1a, 0xe4, 0x5d, 0xe1, 0x5d}}}, +{{{0x37, 0xea, 0xfe, 0x65, 0x3b, 0x25, 0xe8, 0xe1, 0xc2, 0xc5, 0x02, 0xa4, 0xbe, 0x98, 0x0a, 0x2b, 0x61, 0xc1, 0x9b, 0xe2, 0xd5, 0x92, 0xe6, 0x9e, 0x7d, 0x1f, 0xca, 0x43, 0x88, 0x8b, 0x2c, 0x59}} , + {{0xe0, 0xb5, 0x00, 0x1d, 0x2a, 0x6f, 0xaf, 0x79, 0x86, 0x2f, 0xa6, 0x5a, 0x93, 0xd1, 0xfe, 0xae, 0x3a, 0xee, 0xdb, 0x7c, 0x61, 0xbe, 0x7c, 0x01, 0xf9, 0xfe, 0x52, 0xdc, 0xd8, 0x52, 0xa3, 0x42}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x22, 0xaf, 0x13, 0x37, 0xbd, 0x37, 0x71, 0xac, 0x04, 0x46, 0x63, 0xac, 0xa4, 0x77, 0xed, 0x25, 0x38, 0xe0, 0x15, 0xa8, 0x64, 0x00, 0x0d, 0xce, 0x51, 0x01, 0xa9, 0xbc, 0x0f, 0x03, 0x1c, 0x04}} , + {{0x89, 0xf9, 0x80, 0x07, 0xcf, 0x3f, 0xb3, 0xe9, 0xe7, 0x45, 0x44, 0x3d, 0x2a, 0x7c, 0xe9, 0xe4, 0x16, 0x5c, 0x5e, 0x65, 0x1c, 0xc7, 0x7d, 0xc6, 0x7a, 0xfb, 0x43, 0xee, 0x25, 0x76, 0x46, 0x72}}}, +{{{0x02, 0xa2, 0xed, 0xf4, 0x8f, 0x6b, 0x0b, 0x3e, 0xeb, 0x35, 0x1a, 0xd5, 0x7e, 0xdb, 0x78, 0x00, 0x96, 0x8a, 0xa0, 0xb4, 0xcf, 0x60, 0x4b, 0xd4, 0xd5, 0xf9, 0x2d, 0xbf, 0x88, 0xbd, 0x22, 0x62}} , + {{0x13, 0x53, 0xe4, 0x82, 0x57, 0xfa, 0x1e, 0x8f, 0x06, 0x2b, 0x90, 0xba, 0x08, 0xb6, 0x10, 0x54, 0x4f, 0x7c, 0x1b, 0x26, 0xed, 0xda, 0x6b, 0xdd, 0x25, 0xd0, 0x4e, 0xea, 0x42, 0xbb, 0x25, 0x03}}}, +{{{0x51, 0x16, 0x50, 0x7c, 0xd5, 0x5d, 0xf6, 0x99, 0xe8, 0x77, 0x72, 0x4e, 0xfa, 0x62, 0xcb, 0x76, 0x75, 0x0c, 0xe2, 0x71, 0x98, 0x92, 0xd5, 0xfa, 0x45, 0xdf, 0x5c, 0x6f, 0x1e, 0x9e, 0x28, 0x69}} , + {{0x0d, 0xac, 0x66, 0x6d, 0xc3, 0x8b, 0xba, 0x16, 0xb5, 0xe2, 0xa0, 0x0d, 0x0c, 0xbd, 0xa4, 0x8e, 0x18, 0x6c, 0xf2, 0xdc, 0xf9, 0xdc, 0x4a, 0x86, 0x25, 0x95, 0x14, 0xcb, 0xd8, 0x1a, 0x04, 0x0f}}}, +{{{0x97, 0xa5, 0xdb, 0x8b, 0x2d, 0xaa, 0x42, 0x11, 0x09, 0xf2, 0x93, 0xbb, 0xd9, 0x06, 0x84, 0x4e, 0x11, 0xa8, 0xa0, 0x25, 0x2b, 0xa6, 0x5f, 0xae, 0xc4, 0xb4, 0x4c, 0xc8, 0xab, 0xc7, 0x3b, 0x02}} , + {{0xee, 0xc9, 0x29, 0x0f, 0xdf, 0x11, 0x85, 0xed, 0xce, 0x0d, 0x62, 0x2c, 0x8f, 0x4b, 0xf9, 0x04, 0xe9, 0x06, 0x72, 0x1d, 0x37, 0x20, 0x50, 0xc9, 0x14, 0xeb, 0xec, 0x39, 0xa7, 0x97, 0x2b, 0x4d}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x69, 0xd1, 0x39, 0xbd, 0xfb, 0x33, 0xbe, 0xc4, 0xf0, 0x5c, 0xef, 0xf0, 0x56, 0x68, 0xfc, 0x97, 0x47, 0xc8, 0x72, 0xb6, 0x53, 0xa4, 0x0a, 0x98, 0xa5, 0xb4, 0x37, 0x71, 0xcf, 0x66, 0x50, 0x6d}} , + {{0x17, 0xa4, 0x19, 0x52, 0x11, 0x47, 0xb3, 0x5c, 0x5b, 0xa9, 0x2e, 0x22, 0xb4, 0x00, 0x52, 0xf9, 0x57, 0x18, 0xb8, 0xbe, 0x5a, 0xe3, 0xab, 0x83, 0xc8, 0x87, 0x0a, 0x2a, 0xd8, 0x8c, 0xbb, 0x54}}}, +{{{0xa9, 0x62, 0x93, 0x85, 0xbe, 0xe8, 0x73, 0x4a, 0x0e, 0xb0, 0xb5, 0x2d, 0x94, 0x50, 0xaa, 0xd3, 0xb2, 0xea, 0x9d, 0x62, 0x76, 0x3b, 0x07, 0x34, 0x4e, 0x2d, 0x70, 0xc8, 0x9a, 0x15, 0x66, 0x6b}} , + {{0xc5, 0x96, 0xca, 0xc8, 0x22, 0x1a, 0xee, 0x5f, 0xe7, 0x31, 0x60, 0x22, 0x83, 0x08, 0x63, 0xce, 0xb9, 0x32, 0x44, 0x58, 0x5d, 0x3a, 0x9b, 0xe4, 0x04, 0xd5, 0xef, 0x38, 0xef, 0x4b, 0xdd, 0x19}}}, +{{{0x4d, 0xc2, 0x17, 0x75, 0xa1, 0x68, 0xcd, 0xc3, 0xc6, 0x03, 0x44, 0xe3, 0x78, 0x09, 0x91, 0x47, 0x3f, 0x0f, 0xe4, 0x92, 0x58, 0xfa, 0x7d, 0x1f, 0x20, 0x94, 0x58, 0x5e, 0xbc, 0x19, 0x02, 0x6f}} , + {{0x20, 0xd6, 0xd8, 0x91, 0x54, 0xa7, 0xf3, 0x20, 0x4b, 0x34, 0x06, 0xfa, 0x30, 0xc8, 0x6f, 0x14, 0x10, 0x65, 0x74, 0x13, 0x4e, 0xf0, 0x69, 0x26, 0xce, 0xcf, 0x90, 0xf4, 0xd0, 0xc5, 0xc8, 0x64}}}, +{{{0x26, 0xa2, 0x50, 0x02, 0x24, 0x72, 0xf1, 0xf0, 0x4e, 0x2d, 0x93, 0xd5, 0x08, 0xe7, 0xae, 0x38, 0xf7, 0x18, 0xa5, 0x32, 0x34, 0xc2, 0xf0, 0xa6, 0xec, 0xb9, 0x61, 0x7b, 0x64, 0x99, 0xac, 0x71}} , + {{0x25, 0xcf, 0x74, 0x55, 0x1b, 0xaa, 0xa9, 0x38, 0x41, 0x40, 0xd5, 0x95, 0x95, 0xab, 0x1c, 0x5e, 0xbc, 0x41, 0x7e, 0x14, 0x30, 0xbe, 0x13, 0x89, 0xf4, 0xe5, 0xeb, 0x28, 0xc0, 0xc2, 0x96, 0x3a}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x2b, 0x77, 0x45, 0xec, 0x67, 0x76, 0x32, 0x4c, 0xb9, 0xdf, 0x25, 0x32, 0x6b, 0xcb, 0xe7, 0x14, 0x61, 0x43, 0xee, 0xba, 0x9b, 0x71, 0xef, 0xd2, 0x48, 0x65, 0xbb, 0x1b, 0x8a, 0x13, 0x1b, 0x22}} , + {{0x84, 0xad, 0x0c, 0x18, 0x38, 0x5a, 0xba, 0xd0, 0x98, 0x59, 0xbf, 0x37, 0xb0, 0x4f, 0x97, 0x60, 0x20, 0xb3, 0x9b, 0x97, 0xf6, 0x08, 0x6c, 0xa4, 0xff, 0xfb, 0xb7, 0xfa, 0x95, 0xb2, 0x51, 0x79}}}, +{{{0x28, 0x5c, 0x3f, 0xdb, 0x6b, 0x18, 0x3b, 0x5c, 0xd1, 0x04, 0x28, 0xde, 0x85, 0x52, 0x31, 0xb5, 0xbb, 0xf6, 0xa9, 0xed, 0xbe, 0x28, 0x4f, 0xb3, 0x7e, 0x05, 0x6a, 0xdb, 0x95, 0x0d, 0x1b, 0x1c}} , + {{0xd5, 0xc5, 0xc3, 0x9a, 0x0a, 0xd0, 0x31, 0x3e, 0x07, 0x36, 0x8e, 0xc0, 0x8a, 0x62, 0xb1, 0xca, 0xd6, 0x0e, 0x1e, 0x9d, 0xef, 0xab, 0x98, 0x4d, 0xbb, 0x6c, 0x05, 0xe0, 0xe4, 0x5d, 0xbd, 0x57}}}, +{{{0xcc, 0x21, 0x27, 0xce, 0xfd, 0xa9, 0x94, 0x8e, 0xe1, 0xab, 0x49, 0xe0, 0x46, 0x26, 0xa1, 0xa8, 0x8c, 0xa1, 0x99, 0x1d, 0xb4, 0x27, 0x6d, 0x2d, 0xc8, 0x39, 0x30, 0x5e, 0x37, 0x52, 0xc4, 0x6e}} , + {{0xa9, 0x85, 0xf4, 0xe7, 0xb0, 0x15, 0x33, 0x84, 0x1b, 0x14, 0x1a, 0x02, 0xd9, 0x3b, 0xad, 0x0f, 0x43, 0x6c, 0xea, 0x3e, 0x0f, 0x7e, 0xda, 0xdd, 0x6b, 0x4c, 0x7f, 0x6e, 0xd4, 0x6b, 0xbf, 0x0f}}}, +{{{0x47, 0x9f, 0x7c, 0x56, 0x7c, 0x43, 0x91, 0x1c, 0xbb, 0x4e, 0x72, 0x3e, 0x64, 0xab, 0xa0, 0xa0, 0xdf, 0xb4, 0xd8, 0x87, 0x3a, 0xbd, 0xa8, 0x48, 0xc9, 0xb8, 0xef, 0x2e, 0xad, 0x6f, 0x84, 0x4f}} , + {{0x2d, 0x2d, 0xf0, 0x1b, 0x7e, 0x2a, 0x6c, 0xf8, 0xa9, 0x6a, 0xe1, 0xf0, 0x99, 0xa1, 0x67, 0x9a, 0xd4, 0x13, 0xca, 0xca, 0xba, 0x27, 0x92, 0xaa, 0xa1, 0x5d, 0x50, 0xde, 0xcc, 0x40, 0x26, 0x0a}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x9f, 0x3e, 0xf2, 0xb2, 0x90, 0xce, 0xdb, 0x64, 0x3e, 0x03, 0xdd, 0x37, 0x36, 0x54, 0x70, 0x76, 0x24, 0xb5, 0x69, 0x03, 0xfc, 0xa0, 0x2b, 0x74, 0xb2, 0x05, 0x0e, 0xcc, 0xd8, 0x1f, 0x6a, 0x1f}} , + {{0x19, 0x5e, 0x60, 0x69, 0x58, 0x86, 0xa0, 0x31, 0xbd, 0x32, 0xe9, 0x2c, 0x5c, 0xd2, 0x85, 0xba, 0x40, 0x64, 0xa8, 0x74, 0xf8, 0x0e, 0x1c, 0xb3, 0xa9, 0x69, 0xe8, 0x1e, 0x40, 0x64, 0x99, 0x77}}}, +{{{0x6c, 0x32, 0x4f, 0xfd, 0xbb, 0x5c, 0xbb, 0x8d, 0x64, 0x66, 0x4a, 0x71, 0x1f, 0x79, 0xa3, 0xad, 0x8d, 0xf9, 0xd4, 0xec, 0xcf, 0x67, 0x70, 0xfa, 0x05, 0x4a, 0x0f, 0x6e, 0xaf, 0x87, 0x0a, 0x6f}} , + {{0xc6, 0x36, 0x6e, 0x6c, 0x8c, 0x24, 0x09, 0x60, 0xbe, 0x26, 0xd2, 0x4c, 0x5e, 0x17, 0xca, 0x5f, 0x1d, 0xcc, 0x87, 0xe8, 0x42, 0x6a, 0xcb, 0xcb, 0x7d, 0x92, 0x05, 0x35, 0x81, 0x13, 0x60, 0x6b}}}, +{{{0xf4, 0x15, 0xcd, 0x0f, 0x0a, 0xaf, 0x4e, 0x6b, 0x51, 0xfd, 0x14, 0xc4, 0x2e, 0x13, 0x86, 0x74, 0x44, 0xcb, 0x66, 0x6b, 0xb6, 0x9d, 0x74, 0x56, 0x32, 0xac, 0x8d, 0x8e, 0x8c, 0x8c, 0x8c, 0x39}} , + {{0xca, 0x59, 0x74, 0x1a, 0x11, 0xef, 0x6d, 0xf7, 0x39, 0x5c, 0x3b, 0x1f, 0xfa, 0xe3, 0x40, 0x41, 0x23, 0x9e, 0xf6, 0xd1, 0x21, 0xa2, 0xbf, 0xad, 0x65, 0x42, 0x6b, 0x59, 0x8a, 0xe8, 0xc5, 0x7f}}}, +{{{0x64, 0x05, 0x7a, 0x84, 0x4a, 0x13, 0xc3, 0xf6, 0xb0, 0x6e, 0x9a, 0x6b, 0x53, 0x6b, 0x32, 0xda, 0xd9, 0x74, 0x75, 0xc4, 0xba, 0x64, 0x3d, 0x3b, 0x08, 0xdd, 0x10, 0x46, 0xef, 0xc7, 0x90, 0x1f}} , + {{0x7b, 0x2f, 0x3a, 0xce, 0xc8, 0xa1, 0x79, 0x3c, 0x30, 0x12, 0x44, 0x28, 0xf6, 0xbc, 0xff, 0xfd, 0xf4, 0xc0, 0x97, 0xb0, 0xcc, 0xc3, 0x13, 0x7a, 0xb9, 0x9a, 0x16, 0xe4, 0xcb, 0x4c, 0x34, 0x63}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x07, 0x4e, 0xd3, 0x2d, 0x09, 0x33, 0x0e, 0xd2, 0x0d, 0xbe, 0x3e, 0xe7, 0xe4, 0xaa, 0xb7, 0x00, 0x8b, 0xe8, 0xad, 0xaa, 0x7a, 0x8d, 0x34, 0x28, 0xa9, 0x81, 0x94, 0xc5, 0xe7, 0x42, 0xac, 0x47}} , + {{0x24, 0x89, 0x7a, 0x8f, 0xb5, 0x9b, 0xf0, 0xc2, 0x03, 0x64, 0xd0, 0x1e, 0xf5, 0xa4, 0xb2, 0xf3, 0x74, 0xe9, 0x1a, 0x16, 0xfd, 0xcb, 0x15, 0xea, 0xeb, 0x10, 0x6c, 0x35, 0xd1, 0xc1, 0xa6, 0x28}}}, +{{{0xcc, 0xd5, 0x39, 0xfc, 0xa5, 0xa4, 0xad, 0x32, 0x15, 0xce, 0x19, 0xe8, 0x34, 0x2b, 0x1c, 0x60, 0x91, 0xfc, 0x05, 0xa9, 0xb3, 0xdc, 0x80, 0x29, 0xc4, 0x20, 0x79, 0x06, 0x39, 0xc0, 0xe2, 0x22}} , + {{0xbb, 0xa8, 0xe1, 0x89, 0x70, 0x57, 0x18, 0x54, 0x3c, 0xf6, 0x0d, 0x82, 0x12, 0x05, 0x87, 0x96, 0x06, 0x39, 0xe3, 0xf8, 0xb3, 0x95, 0xe5, 0xd7, 0x26, 0xbf, 0x09, 0x5a, 0x94, 0xf9, 0x1c, 0x63}}}, +{{{0x2b, 0x8c, 0x2d, 0x9a, 0x8b, 0x84, 0xf2, 0x56, 0xfb, 0xad, 0x2e, 0x7f, 0xb7, 0xfc, 0x30, 0xe1, 0x35, 0x89, 0xba, 0x4d, 0xa8, 0x6d, 0xce, 0x8c, 0x8b, 0x30, 0xe0, 0xda, 0x29, 0x18, 0x11, 0x17}} , + {{0x19, 0xa6, 0x5a, 0x65, 0x93, 0xc3, 0xb5, 0x31, 0x22, 0x4f, 0xf3, 0xf6, 0x0f, 0xeb, 0x28, 0xc3, 0x7c, 0xeb, 0xce, 0x86, 0xec, 0x67, 0x76, 0x6e, 0x35, 0x45, 0x7b, 0xd8, 0x6b, 0x92, 0x01, 0x65}}}, +{{{0x3d, 0xd5, 0x9a, 0x64, 0x73, 0x36, 0xb1, 0xd6, 0x86, 0x98, 0x42, 0x3f, 0x8a, 0xf1, 0xc7, 0xf5, 0x42, 0xa8, 0x9c, 0x52, 0xa8, 0xdc, 0xf9, 0x24, 0x3f, 0x4a, 0xa1, 0xa4, 0x5b, 0xe8, 0x62, 0x1a}} , + {{0xc5, 0xbd, 0xc8, 0x14, 0xd5, 0x0d, 0xeb, 0xe1, 0xa5, 0xe6, 0x83, 0x11, 0x09, 0x00, 0x1d, 0x55, 0x83, 0x51, 0x7e, 0x75, 0x00, 0x81, 0xb9, 0xcb, 0xd8, 0xc5, 0xe5, 0xa1, 0xd9, 0x17, 0x6d, 0x1f}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xea, 0xf9, 0xe4, 0xe9, 0xe1, 0x52, 0x3f, 0x51, 0x19, 0x0d, 0xdd, 0xd9, 0x9d, 0x93, 0x31, 0x87, 0x23, 0x09, 0xd5, 0x83, 0xeb, 0x92, 0x09, 0x76, 0x6e, 0xe3, 0xf8, 0xc0, 0xa2, 0x66, 0xb5, 0x36}} , + {{0x3a, 0xbb, 0x39, 0xed, 0x32, 0x02, 0xe7, 0x43, 0x7a, 0x38, 0x14, 0x84, 0xe3, 0x44, 0xd2, 0x5e, 0x94, 0xdd, 0x78, 0x89, 0x55, 0x4c, 0x73, 0x9e, 0xe1, 0xe4, 0x3e, 0x43, 0xd0, 0x4a, 0xde, 0x1b}}}, +{{{0xb2, 0xe7, 0x8f, 0xe3, 0xa3, 0xc5, 0xcb, 0x72, 0xee, 0x79, 0x41, 0xf8, 0xdf, 0xee, 0x65, 0xc5, 0x45, 0x77, 0x27, 0x3c, 0xbd, 0x58, 0xd3, 0x75, 0xe2, 0x04, 0x4b, 0xbb, 0x65, 0xf3, 0xc8, 0x0f}} , + {{0x24, 0x7b, 0x93, 0x34, 0xb5, 0xe2, 0x74, 0x48, 0xcd, 0xa0, 0x0b, 0x92, 0x97, 0x66, 0x39, 0xf4, 0xb0, 0xe2, 0x5d, 0x39, 0x6a, 0x5b, 0x45, 0x17, 0x78, 0x1e, 0xdb, 0x91, 0x81, 0x1c, 0xf9, 0x16}}}, +{{{0x16, 0xdf, 0xd1, 0x5a, 0xd5, 0xe9, 0x4e, 0x58, 0x95, 0x93, 0x5f, 0x51, 0x09, 0xc3, 0x2a, 0xc9, 0xd4, 0x55, 0x48, 0x79, 0xa4, 0xa3, 0xb2, 0xc3, 0x62, 0xaa, 0x8c, 0xe8, 0xad, 0x47, 0x39, 0x1b}} , + {{0x46, 0xda, 0x9e, 0x51, 0x3a, 0xe6, 0xd1, 0xa6, 0xbb, 0x4d, 0x7b, 0x08, 0xbe, 0x8c, 0xd5, 0xf3, 0x3f, 0xfd, 0xf7, 0x44, 0x80, 0x2d, 0x53, 0x4b, 0xd0, 0x87, 0x68, 0xc1, 0xb5, 0xd8, 0xf7, 0x07}}}, +{{{0xf4, 0x10, 0x46, 0xbe, 0xb7, 0xd2, 0xd1, 0xce, 0x5e, 0x76, 0xa2, 0xd7, 0x03, 0xdc, 0xe4, 0x81, 0x5a, 0xf6, 0x3c, 0xde, 0xae, 0x7a, 0x9d, 0x21, 0x34, 0xa5, 0xf6, 0xa9, 0x73, 0xe2, 0x8d, 0x60}} , + {{0xfa, 0x44, 0x71, 0xf6, 0x41, 0xd8, 0xc6, 0x58, 0x13, 0x37, 0xeb, 0x84, 0x0f, 0x96, 0xc7, 0xdc, 0xc8, 0xa9, 0x7a, 0x83, 0xb2, 0x2f, 0x31, 0xb1, 0x1a, 0xd8, 0x98, 0x3f, 0x11, 0xd0, 0x31, 0x3b}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x81, 0xd5, 0x34, 0x16, 0x01, 0xa3, 0x93, 0xea, 0x52, 0x94, 0xec, 0x93, 0xb7, 0x81, 0x11, 0x2d, 0x58, 0xf9, 0xb5, 0x0a, 0xaa, 0x4f, 0xf6, 0x2e, 0x3f, 0x36, 0xbf, 0x33, 0x5a, 0xe7, 0xd1, 0x08}} , + {{0x1a, 0xcf, 0x42, 0xae, 0xcc, 0xb5, 0x77, 0x39, 0xc4, 0x5b, 0x5b, 0xd0, 0x26, 0x59, 0x27, 0xd0, 0x55, 0x71, 0x12, 0x9d, 0x88, 0x3d, 0x9c, 0xea, 0x41, 0x6a, 0xf0, 0x50, 0x93, 0x93, 0xdd, 0x47}}}, +{{{0x6f, 0xc9, 0x51, 0x6d, 0x1c, 0xaa, 0xf5, 0xa5, 0x90, 0x3f, 0x14, 0xe2, 0x6e, 0x8e, 0x64, 0xfd, 0xac, 0xe0, 0x4e, 0x22, 0xe5, 0xc1, 0xbc, 0x29, 0x0a, 0x6a, 0x9e, 0xa1, 0x60, 0xcb, 0x2f, 0x0b}} , + {{0xdc, 0x39, 0x32, 0xf3, 0xa1, 0x44, 0xe9, 0xc5, 0xc3, 0x78, 0xfb, 0x95, 0x47, 0x34, 0x35, 0x34, 0xe8, 0x25, 0xde, 0x93, 0xc6, 0xb4, 0x76, 0x6d, 0x86, 0x13, 0xc6, 0xe9, 0x68, 0xb5, 0x01, 0x63}}}, +{{{0x1f, 0x9a, 0x52, 0x64, 0x97, 0xd9, 0x1c, 0x08, 0x51, 0x6f, 0x26, 0x9d, 0xaa, 0x93, 0x33, 0x43, 0xfa, 0x77, 0xe9, 0x62, 0x9b, 0x5d, 0x18, 0x75, 0xeb, 0x78, 0xf7, 0x87, 0x8f, 0x41, 0xb4, 0x4d}} , + {{0x13, 0xa8, 0x82, 0x3e, 0xe9, 0x13, 0xad, 0xeb, 0x01, 0xca, 0xcf, 0xda, 0xcd, 0xf7, 0x6c, 0xc7, 0x7a, 0xdc, 0x1e, 0x6e, 0xc8, 0x4e, 0x55, 0x62, 0x80, 0xea, 0x78, 0x0c, 0x86, 0xb9, 0x40, 0x51}}}, +{{{0x27, 0xae, 0xd3, 0x0d, 0x4c, 0x8f, 0x34, 0xea, 0x7d, 0x3c, 0xe5, 0x8a, 0xcf, 0x5b, 0x92, 0xd8, 0x30, 0x16, 0xb4, 0xa3, 0x75, 0xff, 0xeb, 0x27, 0xc8, 0x5c, 0x6c, 0xc2, 0xee, 0x6c, 0x21, 0x0b}} , + {{0xc3, 0xba, 0x12, 0x53, 0x2a, 0xaa, 0x77, 0xad, 0x19, 0x78, 0x55, 0x8a, 0x2e, 0x60, 0x87, 0xc2, 0x6e, 0x91, 0x38, 0x91, 0x3f, 0x7a, 0xc5, 0x24, 0x8f, 0x51, 0xc5, 0xde, 0xb0, 0x53, 0x30, 0x56}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x02, 0xfe, 0x54, 0x12, 0x18, 0xca, 0x7d, 0xa5, 0x68, 0x43, 0xa3, 0x6d, 0x14, 0x2a, 0x6a, 0xa5, 0x8e, 0x32, 0xe7, 0x63, 0x4f, 0xe3, 0xc6, 0x44, 0x3e, 0xab, 0x63, 0xca, 0x17, 0x86, 0x74, 0x3f}} , + {{0x1e, 0x64, 0xc1, 0x7d, 0x52, 0xdc, 0x13, 0x5a, 0xa1, 0x9c, 0x4e, 0xee, 0x99, 0x28, 0xbb, 0x4c, 0xee, 0xac, 0xa9, 0x1b, 0x89, 0xa2, 0x38, 0x39, 0x7b, 0xc4, 0x0f, 0x42, 0xe6, 0x89, 0xed, 0x0f}}}, +{{{0xf3, 0x3c, 0x8c, 0x80, 0x83, 0x10, 0x8a, 0x37, 0x50, 0x9c, 0xb4, 0xdf, 0x3f, 0x8c, 0xf7, 0x23, 0x07, 0xd6, 0xff, 0xa0, 0x82, 0x6c, 0x75, 0x3b, 0xe4, 0xb5, 0xbb, 0xe4, 0xe6, 0x50, 0xf0, 0x08}} , + {{0x62, 0xee, 0x75, 0x48, 0x92, 0x33, 0xf2, 0xf4, 0xad, 0x15, 0x7a, 0xa1, 0x01, 0x46, 0xa9, 0x32, 0x06, 0x88, 0xb6, 0x36, 0x47, 0x35, 0xb9, 0xb4, 0x42, 0x85, 0x76, 0xf0, 0x48, 0x00, 0x90, 0x38}}}, +{{{0x51, 0x15, 0x9d, 0xc3, 0x95, 0xd1, 0x39, 0xbb, 0x64, 0x9d, 0x15, 0x81, 0xc1, 0x68, 0xd0, 0xb6, 0xa4, 0x2c, 0x7d, 0x5e, 0x02, 0x39, 0x00, 0xe0, 0x3b, 0xa4, 0xcc, 0xca, 0x1d, 0x81, 0x24, 0x10}} , + {{0xe7, 0x29, 0xf9, 0x37, 0xd9, 0x46, 0x5a, 0xcd, 0x70, 0xfe, 0x4d, 0x5b, 0xbf, 0xa5, 0xcf, 0x91, 0xf4, 0xef, 0xee, 0x8a, 0x29, 0xd0, 0xe7, 0xc4, 0x25, 0x92, 0x8a, 0xff, 0x36, 0xfc, 0xe4, 0x49}}}, +{{{0xbd, 0x00, 0xb9, 0x04, 0x7d, 0x35, 0xfc, 0xeb, 0xd0, 0x0b, 0x05, 0x32, 0x52, 0x7a, 0x89, 0x24, 0x75, 0x50, 0xe1, 0x63, 0x02, 0x82, 0x8e, 0xe7, 0x85, 0x0c, 0xf2, 0x56, 0x44, 0x37, 0x83, 0x25}} , + {{0x8f, 0xa1, 0xce, 0xcb, 0x60, 0xda, 0x12, 0x02, 0x1e, 0x29, 0x39, 0x2a, 0x03, 0xb7, 0xeb, 0x77, 0x40, 0xea, 0xc9, 0x2b, 0x2c, 0xd5, 0x7d, 0x7e, 0x2c, 0xc7, 0x5a, 0xfd, 0xff, 0xc4, 0xd1, 0x62}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x1d, 0x88, 0x98, 0x5b, 0x4e, 0xfc, 0x41, 0x24, 0x05, 0xe6, 0x50, 0x2b, 0xae, 0x96, 0x51, 0xd9, 0x6b, 0x72, 0xb2, 0x33, 0x42, 0x98, 0x68, 0xbb, 0x10, 0x5a, 0x7a, 0x8c, 0x9d, 0x07, 0xb4, 0x05}} , + {{0x2f, 0x61, 0x9f, 0xd7, 0xa8, 0x3f, 0x83, 0x8c, 0x10, 0x69, 0x90, 0xe6, 0xcf, 0xd2, 0x63, 0xa3, 0xe4, 0x54, 0x7e, 0xe5, 0x69, 0x13, 0x1c, 0x90, 0x57, 0xaa, 0xe9, 0x53, 0x22, 0x43, 0x29, 0x23}}}, +{{{0xe5, 0x1c, 0xf8, 0x0a, 0xfd, 0x2d, 0x7e, 0xf5, 0xf5, 0x70, 0x7d, 0x41, 0x6b, 0x11, 0xfe, 0xbe, 0x99, 0xd1, 0x55, 0x29, 0x31, 0xbf, 0xc0, 0x97, 0x6c, 0xd5, 0x35, 0xcc, 0x5e, 0x8b, 0xd9, 0x69}} , + {{0x8e, 0x4e, 0x9f, 0x25, 0xf8, 0x81, 0x54, 0x2d, 0x0e, 0xd5, 0x54, 0x81, 0x9b, 0xa6, 0x92, 0xce, 0x4b, 0xe9, 0x8f, 0x24, 0x3b, 0xca, 0xe0, 0x44, 0xab, 0x36, 0xfe, 0xfb, 0x87, 0xd4, 0x26, 0x3e}}}, +{{{0x0f, 0x93, 0x9c, 0x11, 0xe7, 0xdb, 0xf1, 0xf0, 0x85, 0x43, 0x28, 0x15, 0x37, 0xdd, 0xde, 0x27, 0xdf, 0xad, 0x3e, 0x49, 0x4f, 0xe0, 0x5b, 0xf6, 0x80, 0x59, 0x15, 0x3c, 0x85, 0xb7, 0x3e, 0x12}} , + {{0xf5, 0xff, 0xcc, 0xf0, 0xb4, 0x12, 0x03, 0x5f, 0xc9, 0x84, 0xcb, 0x1d, 0x17, 0xe0, 0xbc, 0xcc, 0x03, 0x62, 0xa9, 0x8b, 0x94, 0xa6, 0xaa, 0x18, 0xcb, 0x27, 0x8d, 0x49, 0xa6, 0x17, 0x15, 0x07}}}, +{{{0xd9, 0xb6, 0xd4, 0x9d, 0xd4, 0x6a, 0xaf, 0x70, 0x07, 0x2c, 0x10, 0x9e, 0xbd, 0x11, 0xad, 0xe4, 0x26, 0x33, 0x70, 0x92, 0x78, 0x1c, 0x74, 0x9f, 0x75, 0x60, 0x56, 0xf4, 0x39, 0xa8, 0xa8, 0x62}} , + {{0x3b, 0xbf, 0x55, 0x35, 0x61, 0x8b, 0x44, 0x97, 0xe8, 0x3a, 0x55, 0xc1, 0xc8, 0x3b, 0xfd, 0x95, 0x29, 0x11, 0x60, 0x96, 0x1e, 0xcb, 0x11, 0x9d, 0xc2, 0x03, 0x8a, 0x1b, 0xc6, 0xd6, 0x45, 0x3d}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x7e, 0x0e, 0x50, 0xb2, 0xcc, 0x0d, 0x6b, 0xa6, 0x71, 0x5b, 0x42, 0xed, 0xbd, 0xaf, 0xac, 0xf0, 0xfc, 0x12, 0xa2, 0x3f, 0x4e, 0xda, 0xe8, 0x11, 0xf3, 0x23, 0xe1, 0x04, 0x62, 0x03, 0x1c, 0x4e}} , + {{0xc8, 0xb1, 0x1b, 0x6f, 0x73, 0x61, 0x3d, 0x27, 0x0d, 0x7d, 0x7a, 0x25, 0x5f, 0x73, 0x0e, 0x2f, 0x93, 0xf6, 0x24, 0xd8, 0x4f, 0x90, 0xac, 0xa2, 0x62, 0x0a, 0xf0, 0x61, 0xd9, 0x08, 0x59, 0x6a}}}, +{{{0x6f, 0x2d, 0x55, 0xf8, 0x2f, 0x8e, 0xf0, 0x18, 0x3b, 0xea, 0xdd, 0x26, 0x72, 0xd1, 0xf5, 0xfe, 0xe5, 0xb8, 0xe6, 0xd3, 0x10, 0x48, 0x46, 0x49, 0x3a, 0x9f, 0x5e, 0x45, 0x6b, 0x90, 0xe8, 0x7f}} , + {{0xd3, 0x76, 0x69, 0x33, 0x7b, 0xb9, 0x40, 0x70, 0xee, 0xa6, 0x29, 0x6b, 0xdd, 0xd0, 0x5d, 0x8d, 0xc1, 0x3e, 0x4a, 0xea, 0x37, 0xb1, 0x03, 0x02, 0x03, 0x35, 0xf1, 0x28, 0x9d, 0xff, 0x00, 0x13}}}, +{{{0x7a, 0xdb, 0x12, 0xd2, 0x8a, 0x82, 0x03, 0x1b, 0x1e, 0xaf, 0xf9, 0x4b, 0x9c, 0xbe, 0xae, 0x7c, 0xe4, 0x94, 0x2a, 0x23, 0xb3, 0x62, 0x86, 0xe7, 0xfd, 0x23, 0xaa, 0x99, 0xbd, 0x2b, 0x11, 0x6c}} , + {{0x8d, 0xa6, 0xd5, 0xac, 0x9d, 0xcc, 0x68, 0x75, 0x7f, 0xc3, 0x4d, 0x4b, 0xdd, 0x6c, 0xbb, 0x11, 0x5a, 0x60, 0xe5, 0xbd, 0x7d, 0x27, 0x8b, 0xda, 0xb4, 0x95, 0xf6, 0x03, 0x27, 0xa4, 0x92, 0x3f}}}, +{{{0x22, 0xd6, 0xb5, 0x17, 0x84, 0xbf, 0x12, 0xcc, 0x23, 0x14, 0x4a, 0xdf, 0x14, 0x31, 0xbc, 0xa1, 0xac, 0x6e, 0xab, 0xfa, 0x57, 0x11, 0x53, 0xb3, 0x27, 0xe6, 0xf9, 0x47, 0x33, 0x44, 0x34, 0x1e}} , + {{0x79, 0xfc, 0xa6, 0xb4, 0x0b, 0x35, 0x20, 0xc9, 0x4d, 0x22, 0x84, 0xc4, 0xa9, 0x20, 0xec, 0x89, 0x94, 0xba, 0x66, 0x56, 0x48, 0xb9, 0x87, 0x7f, 0xca, 0x1e, 0x06, 0xed, 0xa5, 0x55, 0x59, 0x29}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x56, 0xe1, 0xf5, 0xf1, 0xd5, 0xab, 0xa8, 0x2b, 0xae, 0x89, 0xf3, 0xcf, 0x56, 0x9f, 0xf2, 0x4b, 0x31, 0xbc, 0x18, 0xa9, 0x06, 0x5b, 0xbe, 0xb4, 0x61, 0xf8, 0xb2, 0x06, 0x9c, 0x81, 0xab, 0x4c}} , + {{0x1f, 0x68, 0x76, 0x01, 0x16, 0x38, 0x2b, 0x0f, 0x77, 0x97, 0x92, 0x67, 0x4e, 0x86, 0x6a, 0x8b, 0xe5, 0xe8, 0x0c, 0xf7, 0x36, 0x39, 0xb5, 0x33, 0xe6, 0xcf, 0x5e, 0xbd, 0x18, 0xfb, 0x10, 0x1f}}}, +{{{0x83, 0xf0, 0x0d, 0x63, 0xef, 0x53, 0x6b, 0xb5, 0x6b, 0xf9, 0x83, 0xcf, 0xde, 0x04, 0x22, 0x9b, 0x2c, 0x0a, 0xe0, 0xa5, 0xd8, 0xc7, 0x9c, 0xa5, 0xa3, 0xf6, 0x6f, 0xcf, 0x90, 0x6b, 0x68, 0x7c}} , + {{0x33, 0x15, 0xd7, 0x7f, 0x1a, 0xd5, 0x21, 0x58, 0xc4, 0x18, 0xa5, 0xf0, 0xcc, 0x73, 0xa8, 0xfd, 0xfa, 0x18, 0xd1, 0x03, 0x91, 0x8d, 0x52, 0xd2, 0xa3, 0xa4, 0xd3, 0xb1, 0xea, 0x1d, 0x0f, 0x00}}}, +{{{0xcc, 0x48, 0x83, 0x90, 0xe5, 0xfd, 0x3f, 0x84, 0xaa, 0xf9, 0x8b, 0x82, 0x59, 0x24, 0x34, 0x68, 0x4f, 0x1c, 0x23, 0xd9, 0xcc, 0x71, 0xe1, 0x7f, 0x8c, 0xaf, 0xf1, 0xee, 0x00, 0xb6, 0xa0, 0x77}} , + {{0xf5, 0x1a, 0x61, 0xf7, 0x37, 0x9d, 0x00, 0xf4, 0xf2, 0x69, 0x6f, 0x4b, 0x01, 0x85, 0x19, 0x45, 0x4d, 0x7f, 0x02, 0x7c, 0x6a, 0x05, 0x47, 0x6c, 0x1f, 0x81, 0x20, 0xd4, 0xe8, 0x50, 0x27, 0x72}}}, +{{{0x2c, 0x3a, 0xe5, 0xad, 0xf4, 0xdd, 0x2d, 0xf7, 0x5c, 0x44, 0xb5, 0x5b, 0x21, 0xa3, 0x89, 0x5f, 0x96, 0x45, 0xca, 0x4d, 0xa4, 0x21, 0x99, 0x70, 0xda, 0xc4, 0xc4, 0xa0, 0xe5, 0xf4, 0xec, 0x0a}} , + {{0x07, 0x68, 0x21, 0x65, 0xe9, 0x08, 0xa0, 0x0b, 0x6a, 0x4a, 0xba, 0xb5, 0x80, 0xaf, 0xd0, 0x1b, 0xc5, 0xf5, 0x4b, 0x73, 0x50, 0x60, 0x2d, 0x71, 0x69, 0x61, 0x0e, 0xc0, 0x20, 0x40, 0x30, 0x19}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xd0, 0x75, 0x57, 0x3b, 0xeb, 0x5c, 0x14, 0x56, 0x50, 0xc9, 0x4f, 0xb8, 0xb8, 0x1e, 0xa3, 0xf4, 0xab, 0xf5, 0xa9, 0x20, 0x15, 0x94, 0x82, 0xda, 0x96, 0x1c, 0x9b, 0x59, 0x8c, 0xff, 0xf4, 0x51}} , + {{0xc1, 0x3a, 0x86, 0xd7, 0xb0, 0x06, 0x84, 0x7f, 0x1b, 0xbd, 0xd4, 0x07, 0x78, 0x80, 0x2e, 0xb1, 0xb4, 0xee, 0x52, 0x38, 0xee, 0x9a, 0xf9, 0xf6, 0xf3, 0x41, 0x6e, 0xd4, 0x88, 0x95, 0xac, 0x35}}}, +{{{0x41, 0x97, 0xbf, 0x71, 0x6a, 0x9b, 0x72, 0xec, 0xf3, 0xf8, 0x6b, 0xe6, 0x0e, 0x6c, 0x69, 0xa5, 0x2f, 0x68, 0x52, 0xd8, 0x61, 0x81, 0xc0, 0x63, 0x3f, 0xa6, 0x3c, 0x13, 0x90, 0xe6, 0x8d, 0x56}} , + {{0xe8, 0x39, 0x30, 0x77, 0x23, 0xb1, 0xfd, 0x1b, 0x3d, 0x3e, 0x74, 0x4d, 0x7f, 0xae, 0x5b, 0x3a, 0xb4, 0x65, 0x0e, 0x3a, 0x43, 0xdc, 0xdc, 0x41, 0x47, 0xe6, 0xe8, 0x92, 0x09, 0x22, 0x48, 0x4c}}}, +{{{0x85, 0x57, 0x9f, 0xb5, 0xc8, 0x06, 0xb2, 0x9f, 0x47, 0x3f, 0xf0, 0xfa, 0xe6, 0xa9, 0xb1, 0x9b, 0x6f, 0x96, 0x7d, 0xf9, 0xa4, 0x65, 0x09, 0x75, 0x32, 0xa6, 0x6c, 0x7f, 0x47, 0x4b, 0x2f, 0x4f}} , + {{0x34, 0xe9, 0x59, 0x93, 0x9d, 0x26, 0x80, 0x54, 0xf2, 0xcc, 0x3c, 0xc2, 0x25, 0x85, 0xe3, 0x6a, 0xc1, 0x62, 0x04, 0xa7, 0x08, 0x32, 0x6d, 0xa1, 0x39, 0x84, 0x8a, 0x3b, 0x87, 0x5f, 0x11, 0x13}}}, +{{{0xda, 0x03, 0x34, 0x66, 0xc4, 0x0c, 0x73, 0x6e, 0xbc, 0x24, 0xb5, 0xf9, 0x70, 0x81, 0x52, 0xe9, 0xf4, 0x7c, 0x23, 0xdd, 0x9f, 0xb8, 0x46, 0xef, 0x1d, 0x22, 0x55, 0x7d, 0x71, 0xc4, 0x42, 0x33}} , + {{0xc5, 0x37, 0x69, 0x5b, 0xa8, 0xc6, 0x9d, 0xa4, 0xfc, 0x61, 0x6e, 0x68, 0x46, 0xea, 0xd7, 0x1c, 0x67, 0xd2, 0x7d, 0xfa, 0xf1, 0xcc, 0x54, 0x8d, 0x36, 0x35, 0xc9, 0x00, 0xdf, 0x6c, 0x67, 0x50}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x9a, 0x4d, 0x42, 0x29, 0x5d, 0xa4, 0x6b, 0x6f, 0xa8, 0x8a, 0x4d, 0x91, 0x7b, 0xd2, 0xdf, 0x36, 0xef, 0x01, 0x22, 0xc5, 0xcc, 0x8d, 0xeb, 0x58, 0x3d, 0xb3, 0x50, 0xfc, 0x8b, 0x97, 0x96, 0x33}} , + {{0x93, 0x33, 0x07, 0xc8, 0x4a, 0xca, 0xd0, 0xb1, 0xab, 0xbd, 0xdd, 0xa7, 0x7c, 0xac, 0x3e, 0x45, 0xcb, 0xcc, 0x07, 0x91, 0xbf, 0x35, 0x9d, 0xcb, 0x7d, 0x12, 0x3c, 0x11, 0x59, 0x13, 0xcf, 0x5c}}}, +{{{0x45, 0xb8, 0x41, 0xd7, 0xab, 0x07, 0x15, 0x00, 0x8e, 0xce, 0xdf, 0xb2, 0x43, 0x5c, 0x01, 0xdc, 0xf4, 0x01, 0x51, 0x95, 0x10, 0x5a, 0xf6, 0x24, 0x24, 0xa0, 0x19, 0x3a, 0x09, 0x2a, 0xaa, 0x3f}} , + {{0xdc, 0x8e, 0xeb, 0xc6, 0xbf, 0xdd, 0x11, 0x7b, 0xe7, 0x47, 0xe6, 0xce, 0xe7, 0xb6, 0xc5, 0xe8, 0x8a, 0xdc, 0x4b, 0x57, 0x15, 0x3b, 0x66, 0xca, 0x89, 0xa3, 0xfd, 0xac, 0x0d, 0xe1, 0x1d, 0x7a}}}, +{{{0x89, 0xef, 0xbf, 0x03, 0x75, 0xd0, 0x29, 0x50, 0xcb, 0x7d, 0xd6, 0xbe, 0xad, 0x5f, 0x7b, 0x00, 0x32, 0xaa, 0x98, 0xed, 0x3f, 0x8f, 0x92, 0xcb, 0x81, 0x56, 0x01, 0x63, 0x64, 0xa3, 0x38, 0x39}} , + {{0x8b, 0xa4, 0xd6, 0x50, 0xb4, 0xaa, 0x5d, 0x64, 0x64, 0x76, 0x2e, 0xa1, 0xa6, 0xb3, 0xb8, 0x7c, 0x7a, 0x56, 0xf5, 0x5c, 0x4e, 0x84, 0x5c, 0xfb, 0xdd, 0xca, 0x48, 0x8b, 0x48, 0xb9, 0xba, 0x34}}}, +{{{0xc5, 0xe3, 0xe8, 0xae, 0x17, 0x27, 0xe3, 0x64, 0x60, 0x71, 0x47, 0x29, 0x02, 0x0f, 0x92, 0x5d, 0x10, 0x93, 0xc8, 0x0e, 0xa1, 0xed, 0xba, 0xa9, 0x96, 0x1c, 0xc5, 0x76, 0x30, 0xcd, 0xf9, 0x30}} , + {{0x95, 0xb0, 0xbd, 0x8c, 0xbc, 0xa7, 0x4f, 0x7e, 0xfd, 0x4e, 0x3a, 0xbf, 0x5f, 0x04, 0x79, 0x80, 0x2b, 0x5a, 0x9f, 0x4f, 0x68, 0x21, 0x19, 0x71, 0xc6, 0x20, 0x01, 0x42, 0xaa, 0xdf, 0xae, 0x2c}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x90, 0x6e, 0x7e, 0x4b, 0x71, 0x93, 0xc0, 0x72, 0xed, 0xeb, 0x71, 0x24, 0x97, 0x26, 0x9c, 0xfe, 0xcb, 0x3e, 0x59, 0x19, 0xa8, 0x0f, 0x75, 0x7d, 0xbe, 0x18, 0xe6, 0x96, 0x1e, 0x95, 0x70, 0x60}} , + {{0x89, 0x66, 0x3e, 0x1d, 0x4c, 0x5f, 0xfe, 0xc0, 0x04, 0x43, 0xd6, 0x44, 0x19, 0xb5, 0xad, 0xc7, 0x22, 0xdc, 0x71, 0x28, 0x64, 0xde, 0x41, 0x38, 0x27, 0x8f, 0x2c, 0x6b, 0x08, 0xb8, 0xb8, 0x7b}}}, +{{{0x3d, 0x70, 0x27, 0x9d, 0xd9, 0xaf, 0xb1, 0x27, 0xaf, 0xe3, 0x5d, 0x1e, 0x3a, 0x30, 0x54, 0x61, 0x60, 0xe8, 0xc3, 0x26, 0x3a, 0xbc, 0x7e, 0xf5, 0x81, 0xdd, 0x64, 0x01, 0x04, 0xeb, 0xc0, 0x1e}} , + {{0xda, 0x2c, 0xa4, 0xd1, 0xa1, 0xc3, 0x5c, 0x6e, 0x32, 0x07, 0x1f, 0xb8, 0x0e, 0x19, 0x9e, 0x99, 0x29, 0x33, 0x9a, 0xae, 0x7a, 0xed, 0x68, 0x42, 0x69, 0x7c, 0x07, 0xb3, 0x38, 0x2c, 0xf6, 0x3d}}}, +{{{0x64, 0xaa, 0xb5, 0x88, 0x79, 0x65, 0x38, 0x8c, 0x94, 0xd6, 0x62, 0x37, 0x7d, 0x64, 0xcd, 0x3a, 0xeb, 0xff, 0xe8, 0x81, 0x09, 0xc7, 0x6a, 0x50, 0x09, 0x0d, 0x28, 0x03, 0x0d, 0x9a, 0x93, 0x0a}} , + {{0x42, 0xa3, 0xf1, 0xc5, 0xb4, 0x0f, 0xd8, 0xc8, 0x8d, 0x15, 0x31, 0xbd, 0xf8, 0x07, 0x8b, 0xcd, 0x08, 0x8a, 0xfb, 0x18, 0x07, 0xfe, 0x8e, 0x52, 0x86, 0xef, 0xbe, 0xec, 0x49, 0x52, 0x99, 0x08}}}, +{{{0x0f, 0xa9, 0xd5, 0x01, 0xaa, 0x48, 0x4f, 0x28, 0x66, 0x32, 0x1a, 0xba, 0x7c, 0xea, 0x11, 0x80, 0x17, 0x18, 0x9b, 0x56, 0x88, 0x25, 0x06, 0x69, 0x12, 0x2c, 0xea, 0x56, 0x69, 0x41, 0x24, 0x19}} , + {{0xde, 0x21, 0xf0, 0xda, 0x8a, 0xfb, 0xb1, 0xb8, 0xcd, 0xc8, 0x6a, 0x82, 0x19, 0x73, 0xdb, 0xc7, 0xcf, 0x88, 0xeb, 0x96, 0xee, 0x6f, 0xfb, 0x06, 0xd2, 0xcd, 0x7d, 0x7b, 0x12, 0x28, 0x8e, 0x0c}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x93, 0x44, 0x97, 0xce, 0x28, 0xff, 0x3a, 0x40, 0xc4, 0xf5, 0xf6, 0x9b, 0xf4, 0x6b, 0x07, 0x84, 0xfb, 0x98, 0xd8, 0xec, 0x8c, 0x03, 0x57, 0xec, 0x49, 0xed, 0x63, 0xb6, 0xaa, 0xff, 0x98, 0x28}} , + {{0x3d, 0x16, 0x35, 0xf3, 0x46, 0xbc, 0xb3, 0xf4, 0xc6, 0xb6, 0x4f, 0xfa, 0xf4, 0xa0, 0x13, 0xe6, 0x57, 0x45, 0x93, 0xb9, 0xbc, 0xd6, 0x59, 0xe7, 0x77, 0x94, 0x6c, 0xab, 0x96, 0x3b, 0x4f, 0x09}}}, +{{{0x5a, 0xf7, 0x6b, 0x01, 0x12, 0x4f, 0x51, 0xc1, 0x70, 0x84, 0x94, 0x47, 0xb2, 0x01, 0x6c, 0x71, 0xd7, 0xcc, 0x17, 0x66, 0x0f, 0x59, 0x5d, 0x5d, 0x10, 0x01, 0x57, 0x11, 0xf5, 0xdd, 0xe2, 0x34}} , + {{0x26, 0xd9, 0x1f, 0x5c, 0x58, 0xac, 0x8b, 0x03, 0xd2, 0xc3, 0x85, 0x0f, 0x3a, 0xc3, 0x7f, 0x6d, 0x8e, 0x86, 0xcd, 0x52, 0x74, 0x8f, 0x55, 0x77, 0x17, 0xb7, 0x8e, 0xb7, 0x88, 0xea, 0xda, 0x1b}}}, +{{{0xb6, 0xea, 0x0e, 0x40, 0x93, 0x20, 0x79, 0x35, 0x6a, 0x61, 0x84, 0x5a, 0x07, 0x6d, 0xf9, 0x77, 0x6f, 0xed, 0x69, 0x1c, 0x0d, 0x25, 0x76, 0xcc, 0xf0, 0xdb, 0xbb, 0xc5, 0xad, 0xe2, 0x26, 0x57}} , + {{0xcf, 0xe8, 0x0e, 0x6b, 0x96, 0x7d, 0xed, 0x27, 0xd1, 0x3c, 0xa9, 0xd9, 0x50, 0xa9, 0x98, 0x84, 0x5e, 0x86, 0xef, 0xd6, 0xf0, 0xf8, 0x0e, 0x89, 0x05, 0x2f, 0xd9, 0x5f, 0x15, 0x5f, 0x73, 0x79}}}, +{{{0xc8, 0x5c, 0x16, 0xfe, 0xed, 0x9f, 0x26, 0x56, 0xf6, 0x4b, 0x9f, 0xa7, 0x0a, 0x85, 0xfe, 0xa5, 0x8c, 0x87, 0xdd, 0x98, 0xce, 0x4e, 0xc3, 0x58, 0x55, 0xb2, 0x7b, 0x3d, 0xd8, 0x6b, 0xb5, 0x4c}} , + {{0x65, 0x38, 0xa0, 0x15, 0xfa, 0xa7, 0xb4, 0x8f, 0xeb, 0xc4, 0x86, 0x9b, 0x30, 0xa5, 0x5e, 0x4d, 0xea, 0x8a, 0x9a, 0x9f, 0x1a, 0xd8, 0x5b, 0x53, 0x14, 0x19, 0x25, 0x63, 0xb4, 0x6f, 0x1f, 0x5d}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xac, 0x8f, 0xbc, 0x1e, 0x7d, 0x8b, 0x5a, 0x0b, 0x8d, 0xaf, 0x76, 0x2e, 0x71, 0xe3, 0x3b, 0x6f, 0x53, 0x2f, 0x3e, 0x90, 0x95, 0xd4, 0x35, 0x14, 0x4f, 0x8c, 0x3c, 0xce, 0x57, 0x1c, 0x76, 0x49}} , + {{0xa8, 0x50, 0xe1, 0x61, 0x6b, 0x57, 0x35, 0xeb, 0x44, 0x0b, 0x0c, 0x6e, 0xf9, 0x25, 0x80, 0x74, 0xf2, 0x8f, 0x6f, 0x7a, 0x3e, 0x7f, 0x2d, 0xf3, 0x4e, 0x09, 0x65, 0x10, 0x5e, 0x03, 0x25, 0x32}}}, +{{{0xa9, 0x60, 0xdc, 0x0f, 0x64, 0xe5, 0x1d, 0xe2, 0x8d, 0x4f, 0x79, 0x2f, 0x0e, 0x24, 0x02, 0x00, 0x05, 0x77, 0x43, 0x25, 0x3d, 0x6a, 0xc7, 0xb7, 0xbf, 0x04, 0x08, 0x65, 0xf4, 0x39, 0x4b, 0x65}} , + {{0x96, 0x19, 0x12, 0x6b, 0x6a, 0xb7, 0xe3, 0xdc, 0x45, 0x9b, 0xdb, 0xb4, 0xa8, 0xae, 0xdc, 0xa8, 0x14, 0x44, 0x65, 0x62, 0xce, 0x34, 0x9a, 0x84, 0x18, 0x12, 0x01, 0xf1, 0xe2, 0x7b, 0xce, 0x50}}}, +{{{0x41, 0x21, 0x30, 0x53, 0x1b, 0x47, 0x01, 0xb7, 0x18, 0xd8, 0x82, 0x57, 0xbd, 0xa3, 0x60, 0xf0, 0x32, 0xf6, 0x5b, 0xf0, 0x30, 0x88, 0x91, 0x59, 0xfd, 0x90, 0xa2, 0xb9, 0x55, 0x93, 0x21, 0x34}} , + {{0x97, 0x67, 0x9e, 0xeb, 0x6a, 0xf9, 0x6e, 0xd6, 0x73, 0xe8, 0x6b, 0x29, 0xec, 0x63, 0x82, 0x00, 0xa8, 0x99, 0x1c, 0x1d, 0x30, 0xc8, 0x90, 0x52, 0x90, 0xb6, 0x6a, 0x80, 0x4e, 0xff, 0x4b, 0x51}}}, +{{{0x0f, 0x7d, 0x63, 0x8c, 0x6e, 0x5c, 0xde, 0x30, 0xdf, 0x65, 0xfa, 0x2e, 0xb0, 0xa3, 0x25, 0x05, 0x54, 0xbd, 0x25, 0xba, 0x06, 0xae, 0xdf, 0x8b, 0xd9, 0x1b, 0xea, 0x38, 0xb3, 0x05, 0x16, 0x09}} , + {{0xc7, 0x8c, 0xbf, 0x64, 0x28, 0xad, 0xf8, 0xa5, 0x5a, 0x6f, 0xc9, 0xba, 0xd5, 0x7f, 0xd5, 0xd6, 0xbd, 0x66, 0x2f, 0x3d, 0xaa, 0x54, 0xf6, 0xba, 0x32, 0x22, 0x9a, 0x1e, 0x52, 0x05, 0xf4, 0x1d}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xaa, 0x1f, 0xbb, 0xeb, 0xfe, 0xe4, 0x87, 0xfc, 0xb1, 0x2c, 0xb7, 0x88, 0xf4, 0xc6, 0xb9, 0xf5, 0x24, 0x46, 0xf2, 0xa5, 0x9f, 0x8f, 0x8a, 0x93, 0x70, 0x69, 0xd4, 0x56, 0xec, 0xfd, 0x06, 0x46}} , + {{0x4e, 0x66, 0xcf, 0x4e, 0x34, 0xce, 0x0c, 0xd9, 0xa6, 0x50, 0xd6, 0x5e, 0x95, 0xaf, 0xe9, 0x58, 0xfa, 0xee, 0x9b, 0xb8, 0xa5, 0x0f, 0x35, 0xe0, 0x43, 0x82, 0x6d, 0x65, 0xe6, 0xd9, 0x00, 0x0f}}}, +{{{0x7b, 0x75, 0x3a, 0xfc, 0x64, 0xd3, 0x29, 0x7e, 0xdd, 0x49, 0x9a, 0x59, 0x53, 0xbf, 0xb4, 0xa7, 0x52, 0xb3, 0x05, 0xab, 0xc3, 0xaf, 0x16, 0x1a, 0x85, 0x42, 0x32, 0xa2, 0x86, 0xfa, 0x39, 0x43}} , + {{0x0e, 0x4b, 0xa3, 0x63, 0x8a, 0xfe, 0xa5, 0x58, 0xf1, 0x13, 0xbd, 0x9d, 0xaa, 0x7f, 0x76, 0x40, 0x70, 0x81, 0x10, 0x75, 0x99, 0xbb, 0xbe, 0x0b, 0x16, 0xe9, 0xba, 0x62, 0x34, 0xcc, 0x07, 0x6d}}}, +{{{0xc3, 0xf1, 0xc6, 0x93, 0x65, 0xee, 0x0b, 0xbc, 0xea, 0x14, 0xf0, 0xc1, 0xf8, 0x84, 0x89, 0xc2, 0xc9, 0xd7, 0xea, 0x34, 0xca, 0xa7, 0xc4, 0x99, 0xd5, 0x50, 0x69, 0xcb, 0xd6, 0x21, 0x63, 0x7c}} , + {{0x99, 0xeb, 0x7c, 0x31, 0x73, 0x64, 0x67, 0x7f, 0x0c, 0x66, 0xaa, 0x8c, 0x69, 0x91, 0xe2, 0x26, 0xd3, 0x23, 0xe2, 0x76, 0x5d, 0x32, 0x52, 0xdf, 0x5d, 0xc5, 0x8f, 0xb7, 0x7c, 0x84, 0xb3, 0x70}}}, +{{{0xeb, 0x01, 0xc7, 0x36, 0x97, 0x4e, 0xb6, 0xab, 0x5f, 0x0d, 0x2c, 0xba, 0x67, 0x64, 0x55, 0xde, 0xbc, 0xff, 0xa6, 0xec, 0x04, 0xd3, 0x8d, 0x39, 0x56, 0x5e, 0xee, 0xf8, 0xe4, 0x2e, 0x33, 0x62}} , + {{0x65, 0xef, 0xb8, 0x9f, 0xc8, 0x4b, 0xa7, 0xfd, 0x21, 0x49, 0x9b, 0x92, 0x35, 0x82, 0xd6, 0x0a, 0x9b, 0xf2, 0x79, 0xf1, 0x47, 0x2f, 0x6a, 0x7e, 0x9f, 0xcf, 0x18, 0x02, 0x3c, 0xfb, 0x1b, 0x3e}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x2f, 0x8b, 0xc8, 0x40, 0x51, 0xd1, 0xac, 0x1a, 0x0b, 0xe4, 0xa9, 0xa2, 0x42, 0x21, 0x19, 0x2f, 0x7b, 0x97, 0xbf, 0xf7, 0x57, 0x6d, 0x3f, 0x3d, 0x4f, 0x0f, 0xe2, 0xb2, 0x81, 0x00, 0x9e, 0x7b}} , + {{0x8c, 0x85, 0x2b, 0xc4, 0xfc, 0xf1, 0xab, 0xe8, 0x79, 0x22, 0xc4, 0x84, 0x17, 0x3a, 0xfa, 0x86, 0xa6, 0x7d, 0xf9, 0xf3, 0x6f, 0x03, 0x57, 0x20, 0x4d, 0x79, 0xf9, 0x6e, 0x71, 0x54, 0x38, 0x09}}}, +{{{0x40, 0x29, 0x74, 0xa8, 0x2f, 0x5e, 0xf9, 0x79, 0xa4, 0xf3, 0x3e, 0xb9, 0xfd, 0x33, 0x31, 0xac, 0x9a, 0x69, 0x88, 0x1e, 0x77, 0x21, 0x2d, 0xf3, 0x91, 0x52, 0x26, 0x15, 0xb2, 0xa6, 0xcf, 0x7e}} , + {{0xc6, 0x20, 0x47, 0x6c, 0xa4, 0x7d, 0xcb, 0x63, 0xea, 0x5b, 0x03, 0xdf, 0x3e, 0x88, 0x81, 0x6d, 0xce, 0x07, 0x42, 0x18, 0x60, 0x7e, 0x7b, 0x55, 0xfe, 0x6a, 0xf3, 0xda, 0x5c, 0x8b, 0x95, 0x10}}}, +{{{0x62, 0xe4, 0x0d, 0x03, 0xb4, 0xd7, 0xcd, 0xfa, 0xbd, 0x46, 0xdf, 0x93, 0x71, 0x10, 0x2c, 0xa8, 0x3b, 0xb6, 0x09, 0x05, 0x70, 0x84, 0x43, 0x29, 0xa8, 0x59, 0xf5, 0x8e, 0x10, 0xe4, 0xd7, 0x20}} , + {{0x57, 0x82, 0x1c, 0xab, 0xbf, 0x62, 0x70, 0xe8, 0xc4, 0xcf, 0xf0, 0x28, 0x6e, 0x16, 0x3c, 0x08, 0x78, 0x89, 0x85, 0x46, 0x0f, 0xf6, 0x7f, 0xcf, 0xcb, 0x7e, 0xb8, 0x25, 0xe9, 0x5a, 0xfa, 0x03}}}, +{{{0xfb, 0x95, 0x92, 0x63, 0x50, 0xfc, 0x62, 0xf0, 0xa4, 0x5e, 0x8c, 0x18, 0xc2, 0x17, 0x24, 0xb7, 0x78, 0xc2, 0xa9, 0xe7, 0x6a, 0x32, 0xd6, 0x29, 0x85, 0xaf, 0xcb, 0x8d, 0x91, 0x13, 0xda, 0x6b}} , + {{0x36, 0x0a, 0xc2, 0xb6, 0x4b, 0xa5, 0x5d, 0x07, 0x17, 0x41, 0x31, 0x5f, 0x62, 0x46, 0xf8, 0x92, 0xf9, 0x66, 0x48, 0x73, 0xa6, 0x97, 0x0d, 0x7d, 0x88, 0xee, 0x62, 0xb1, 0x03, 0xa8, 0x3f, 0x2c}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x4a, 0xb1, 0x70, 0x8a, 0xa9, 0xe8, 0x63, 0x79, 0x00, 0xe2, 0x25, 0x16, 0xca, 0x4b, 0x0f, 0xa4, 0x66, 0xad, 0x19, 0x9f, 0x88, 0x67, 0x0c, 0x8b, 0xc2, 0x4a, 0x5b, 0x2b, 0x6d, 0x95, 0xaf, 0x19}} , + {{0x8b, 0x9d, 0xb6, 0xcc, 0x60, 0xb4, 0x72, 0x4f, 0x17, 0x69, 0x5a, 0x4a, 0x68, 0x34, 0xab, 0xa1, 0x45, 0x32, 0x3c, 0x83, 0x87, 0x72, 0x30, 0x54, 0x77, 0x68, 0xae, 0xfb, 0xb5, 0x8b, 0x22, 0x5e}}}, +{{{0xf1, 0xb9, 0x87, 0x35, 0xc5, 0xbb, 0xb9, 0xcf, 0xf5, 0xd6, 0xcd, 0xd5, 0x0c, 0x7c, 0x0e, 0xe6, 0x90, 0x34, 0xfb, 0x51, 0x42, 0x1e, 0x6d, 0xac, 0x9a, 0x46, 0xc4, 0x97, 0x29, 0x32, 0xbf, 0x45}} , + {{0x66, 0x9e, 0xc6, 0x24, 0xc0, 0xed, 0xa5, 0x5d, 0x88, 0xd4, 0xf0, 0x73, 0x97, 0x7b, 0xea, 0x7f, 0x42, 0xff, 0x21, 0xa0, 0x9b, 0x2f, 0x9a, 0xfd, 0x53, 0x57, 0x07, 0x84, 0x48, 0x88, 0x9d, 0x52}}}, +{{{0xc6, 0x96, 0x48, 0x34, 0x2a, 0x06, 0xaf, 0x94, 0x3d, 0xf4, 0x1a, 0xcf, 0xf2, 0xc0, 0x21, 0xc2, 0x42, 0x5e, 0xc8, 0x2f, 0x35, 0xa2, 0x3e, 0x29, 0xfa, 0x0c, 0x84, 0xe5, 0x89, 0x72, 0x7c, 0x06}} , + {{0x32, 0x65, 0x03, 0xe5, 0x89, 0xa6, 0x6e, 0xb3, 0x5b, 0x8e, 0xca, 0xeb, 0xfe, 0x22, 0x56, 0x8b, 0x5d, 0x14, 0x4b, 0x4d, 0xf9, 0xbe, 0xb5, 0xf5, 0xe6, 0x5c, 0x7b, 0x8b, 0xf4, 0x13, 0x11, 0x34}}}, +{{{0x07, 0xc6, 0x22, 0x15, 0xe2, 0x9c, 0x60, 0xa2, 0x19, 0xd9, 0x27, 0xae, 0x37, 0x4e, 0xa6, 0xc9, 0x80, 0xa6, 0x91, 0x8f, 0x12, 0x49, 0xe5, 0x00, 0x18, 0x47, 0xd1, 0xd7, 0x28, 0x22, 0x63, 0x39}} , + {{0xe8, 0xe2, 0x00, 0x7e, 0xf2, 0x9e, 0x1e, 0x99, 0x39, 0x95, 0x04, 0xbd, 0x1e, 0x67, 0x7b, 0xb2, 0x26, 0xac, 0xe6, 0xaa, 0xe2, 0x46, 0xd5, 0xe4, 0xe8, 0x86, 0xbd, 0xab, 0x7c, 0x55, 0x59, 0x6f}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x24, 0x64, 0x6e, 0x9b, 0x35, 0x71, 0x78, 0xce, 0x33, 0x03, 0x21, 0x33, 0x36, 0xf1, 0x73, 0x9b, 0xb9, 0x15, 0x8b, 0x2c, 0x69, 0xcf, 0x4d, 0xed, 0x4f, 0x4d, 0x57, 0x14, 0x13, 0x82, 0xa4, 0x4d}} , + {{0x65, 0x6e, 0x0a, 0xa4, 0x59, 0x07, 0x17, 0xf2, 0x6b, 0x4a, 0x1f, 0x6e, 0xf6, 0xb5, 0xbc, 0x62, 0xe4, 0xb6, 0xda, 0xa2, 0x93, 0xbc, 0x29, 0x05, 0xd2, 0xd2, 0x73, 0x46, 0x03, 0x16, 0x40, 0x31}}}, +{{{0x4c, 0x73, 0x6d, 0x15, 0xbd, 0xa1, 0x4d, 0x5c, 0x13, 0x0b, 0x24, 0x06, 0x98, 0x78, 0x1c, 0x5b, 0xeb, 0x1f, 0x18, 0x54, 0x43, 0xd9, 0x55, 0x66, 0xda, 0x29, 0x21, 0xe8, 0xb8, 0x3c, 0x42, 0x22}} , + {{0xb4, 0xcd, 0x08, 0x6f, 0x15, 0x23, 0x1a, 0x0b, 0x22, 0xed, 0xd1, 0xf1, 0xa7, 0xc7, 0x73, 0x45, 0xf3, 0x9e, 0xce, 0x76, 0xb7, 0xf6, 0x39, 0xb6, 0x8e, 0x79, 0xbe, 0xe9, 0x9b, 0xcf, 0x7d, 0x62}}}, +{{{0x92, 0x5b, 0xfc, 0x72, 0xfd, 0xba, 0xf1, 0xfd, 0xa6, 0x7c, 0x95, 0xe3, 0x61, 0x3f, 0xe9, 0x03, 0xd4, 0x2b, 0xd4, 0x20, 0xd9, 0xdb, 0x4d, 0x32, 0x3e, 0xf5, 0x11, 0x64, 0xe3, 0xb4, 0xbe, 0x32}} , + {{0x86, 0x17, 0x90, 0xe7, 0xc9, 0x1f, 0x10, 0xa5, 0x6a, 0x2d, 0x39, 0xd0, 0x3b, 0xc4, 0xa6, 0xe9, 0x59, 0x13, 0xda, 0x1a, 0xe6, 0xa0, 0xb9, 0x3c, 0x50, 0xb8, 0x40, 0x7c, 0x15, 0x36, 0x5a, 0x42}}}, +{{{0xb4, 0x0b, 0x32, 0xab, 0xdc, 0x04, 0x51, 0x55, 0x21, 0x1e, 0x0b, 0x75, 0x99, 0x89, 0x73, 0x35, 0x3a, 0x91, 0x2b, 0xfe, 0xe7, 0x49, 0xea, 0x76, 0xc1, 0xf9, 0x46, 0xb9, 0x53, 0x02, 0x23, 0x04}} , + {{0xfc, 0x5a, 0x1e, 0x1d, 0x74, 0x58, 0x95, 0xa6, 0x8f, 0x7b, 0x97, 0x3e, 0x17, 0x3b, 0x79, 0x2d, 0xa6, 0x57, 0xef, 0x45, 0x02, 0x0b, 0x4d, 0x6e, 0x9e, 0x93, 0x8d, 0x2f, 0xd9, 0x9d, 0xdb, 0x04}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xc0, 0xd7, 0x56, 0x97, 0x58, 0x91, 0xde, 0x09, 0x4f, 0x9f, 0xbe, 0x63, 0xb0, 0x83, 0x86, 0x43, 0x5d, 0xbc, 0xe0, 0xf3, 0xc0, 0x75, 0xbf, 0x8b, 0x8e, 0xaa, 0xf7, 0x8b, 0x64, 0x6e, 0xb0, 0x63}} , + {{0x16, 0xae, 0x8b, 0xe0, 0x9b, 0x24, 0x68, 0x5c, 0x44, 0xc2, 0xd0, 0x08, 0xb7, 0x7b, 0x62, 0xfd, 0x7f, 0xd8, 0xd4, 0xb7, 0x50, 0xfd, 0x2c, 0x1b, 0xbf, 0x41, 0x95, 0xd9, 0x8e, 0xd8, 0x17, 0x1b}}}, +{{{0x86, 0x55, 0x37, 0x8e, 0xc3, 0x38, 0x48, 0x14, 0xb5, 0x97, 0xd2, 0xa7, 0x54, 0x45, 0xf1, 0x35, 0x44, 0x38, 0x9e, 0xf1, 0x1b, 0xb6, 0x34, 0x00, 0x3c, 0x96, 0xee, 0x29, 0x00, 0xea, 0x2c, 0x0b}} , + {{0xea, 0xda, 0x99, 0x9e, 0x19, 0x83, 0x66, 0x6d, 0xe9, 0x76, 0x87, 0x50, 0xd1, 0xfd, 0x3c, 0x60, 0x87, 0xc6, 0x41, 0xd9, 0x8e, 0xdb, 0x5e, 0xde, 0xaa, 0x9a, 0xd3, 0x28, 0xda, 0x95, 0xea, 0x47}}}, +{{{0xd0, 0x80, 0xba, 0x19, 0xae, 0x1d, 0xa9, 0x79, 0xf6, 0x3f, 0xac, 0x5d, 0x6f, 0x96, 0x1f, 0x2a, 0xce, 0x29, 0xb2, 0xff, 0x37, 0xf1, 0x94, 0x8f, 0x0c, 0xb5, 0x28, 0xba, 0x9a, 0x21, 0xf6, 0x66}} , + {{0x02, 0xfb, 0x54, 0xb8, 0x05, 0xf3, 0x81, 0x52, 0x69, 0x34, 0x46, 0x9d, 0x86, 0x76, 0x8f, 0xd7, 0xf8, 0x6a, 0x66, 0xff, 0xe6, 0xa7, 0x90, 0xf7, 0x5e, 0xcd, 0x6a, 0x9b, 0x55, 0xfc, 0x9d, 0x48}}}, +{{{0xbd, 0xaa, 0x13, 0xe6, 0xcd, 0x45, 0x4a, 0xa4, 0x59, 0x0a, 0x64, 0xb1, 0x98, 0xd6, 0x34, 0x13, 0x04, 0xe6, 0x97, 0x94, 0x06, 0xcb, 0xd4, 0x4e, 0xbb, 0x96, 0xcd, 0xd1, 0x57, 0xd1, 0xe3, 0x06}} , + {{0x7a, 0x6c, 0x45, 0x27, 0xc4, 0x93, 0x7f, 0x7d, 0x7c, 0x62, 0x50, 0x38, 0x3a, 0x6b, 0xb5, 0x88, 0xc6, 0xd9, 0xf1, 0x78, 0x19, 0xb9, 0x39, 0x93, 0x3d, 0xc9, 0xe0, 0x9c, 0x3c, 0xce, 0xf5, 0x72}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x24, 0xea, 0x23, 0x7d, 0x56, 0x2c, 0xe2, 0x59, 0x0e, 0x85, 0x60, 0x04, 0x88, 0x5a, 0x74, 0x1e, 0x4b, 0xef, 0x13, 0xda, 0x4c, 0xff, 0x83, 0x45, 0x85, 0x3f, 0x08, 0x95, 0x2c, 0x20, 0x13, 0x1f}} , + {{0x48, 0x5f, 0x27, 0x90, 0x5c, 0x02, 0x42, 0xad, 0x78, 0x47, 0x5c, 0xb5, 0x7e, 0x08, 0x85, 0x00, 0xfa, 0x7f, 0xfd, 0xfd, 0xe7, 0x09, 0x11, 0xf2, 0x7e, 0x1b, 0x38, 0x6c, 0x35, 0x6d, 0x33, 0x66}}}, +{{{0x93, 0x03, 0x36, 0x81, 0xac, 0xe4, 0x20, 0x09, 0x35, 0x4c, 0x45, 0xb2, 0x1e, 0x4c, 0x14, 0x21, 0xe6, 0xe9, 0x8a, 0x7b, 0x8d, 0xfe, 0x1e, 0xc6, 0x3e, 0xc1, 0x35, 0xfa, 0xe7, 0x70, 0x4e, 0x1d}} , + {{0x61, 0x2e, 0xc2, 0xdd, 0x95, 0x57, 0xd1, 0xab, 0x80, 0xe8, 0x63, 0x17, 0xb5, 0x48, 0xe4, 0x8a, 0x11, 0x9e, 0x72, 0xbe, 0x85, 0x8d, 0x51, 0x0a, 0xf2, 0x9f, 0xe0, 0x1c, 0xa9, 0x07, 0x28, 0x7b}}}, +{{{0xbb, 0x71, 0x14, 0x5e, 0x26, 0x8c, 0x3d, 0xc8, 0xe9, 0x7c, 0xd3, 0xd6, 0xd1, 0x2f, 0x07, 0x6d, 0xe6, 0xdf, 0xfb, 0x79, 0xd6, 0x99, 0x59, 0x96, 0x48, 0x40, 0x0f, 0x3a, 0x7b, 0xb2, 0xa0, 0x72}} , + {{0x4e, 0x3b, 0x69, 0xc8, 0x43, 0x75, 0x51, 0x6c, 0x79, 0x56, 0xe4, 0xcb, 0xf7, 0xa6, 0x51, 0xc2, 0x2c, 0x42, 0x0b, 0xd4, 0x82, 0x20, 0x1c, 0x01, 0x08, 0x66, 0xd7, 0xbf, 0x04, 0x56, 0xfc, 0x02}}}, +{{{0x24, 0xe8, 0xb7, 0x60, 0xae, 0x47, 0x80, 0xfc, 0xe5, 0x23, 0xe7, 0xc2, 0xc9, 0x85, 0xe6, 0x98, 0xa0, 0x29, 0x4e, 0xe1, 0x84, 0x39, 0x2d, 0x95, 0x2c, 0xf3, 0x45, 0x3c, 0xff, 0xaf, 0x27, 0x4c}} , + {{0x6b, 0xa6, 0xf5, 0x4b, 0x11, 0xbd, 0xba, 0x5b, 0x9e, 0xc4, 0xa4, 0x51, 0x1e, 0xbe, 0xd0, 0x90, 0x3a, 0x9c, 0xc2, 0x26, 0xb6, 0x1e, 0xf1, 0x95, 0x7d, 0xc8, 0x6d, 0x52, 0xe6, 0x99, 0x2c, 0x5f}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x85, 0xe0, 0x24, 0x32, 0xb4, 0xd1, 0xef, 0xfc, 0x69, 0xa2, 0xbf, 0x8f, 0x72, 0x2c, 0x95, 0xf6, 0xe4, 0x6e, 0x7d, 0x90, 0xf7, 0x57, 0x81, 0xa0, 0xf7, 0xda, 0xef, 0x33, 0x07, 0xe3, 0x6b, 0x78}} , + {{0x36, 0x27, 0x3e, 0xc6, 0x12, 0x07, 0xab, 0x4e, 0xbe, 0x69, 0x9d, 0xb3, 0xbe, 0x08, 0x7c, 0x2a, 0x47, 0x08, 0xfd, 0xd4, 0xcd, 0x0e, 0x27, 0x34, 0x5b, 0x98, 0x34, 0x2f, 0x77, 0x5f, 0x3a, 0x65}}}, +{{{0x13, 0xaa, 0x2e, 0x4c, 0xf0, 0x22, 0xb8, 0x6c, 0xb3, 0x19, 0x4d, 0xeb, 0x6b, 0xd0, 0xa4, 0xc6, 0x9c, 0xdd, 0xc8, 0x5b, 0x81, 0x57, 0x89, 0xdf, 0x33, 0xa9, 0x68, 0x49, 0x80, 0xe4, 0xfe, 0x21}} , + {{0x00, 0x17, 0x90, 0x30, 0xe9, 0xd3, 0x60, 0x30, 0x31, 0xc2, 0x72, 0x89, 0x7a, 0x36, 0xa5, 0xbd, 0x39, 0x83, 0x85, 0x50, 0xa1, 0x5d, 0x6c, 0x41, 0x1d, 0xb5, 0x2c, 0x07, 0x40, 0x77, 0x0b, 0x50}}}, +{{{0x64, 0x34, 0xec, 0xc0, 0x9e, 0x44, 0x41, 0xaf, 0xa0, 0x36, 0x05, 0x6d, 0xea, 0x30, 0x25, 0x46, 0x35, 0x24, 0x9d, 0x86, 0xbd, 0x95, 0xf1, 0x6a, 0x46, 0xd7, 0x94, 0x54, 0xf9, 0x3b, 0xbd, 0x5d}} , + {{0x77, 0x5b, 0xe2, 0x37, 0xc7, 0xe1, 0x7c, 0x13, 0x8c, 0x9f, 0x7b, 0x7b, 0x2a, 0xce, 0x42, 0xa3, 0xb9, 0x2a, 0x99, 0xa8, 0xc0, 0xd8, 0x3c, 0x86, 0xb0, 0xfb, 0xe9, 0x76, 0x77, 0xf7, 0xf5, 0x56}}}, +{{{0xdf, 0xb3, 0x46, 0x11, 0x6e, 0x13, 0xb7, 0x28, 0x4e, 0x56, 0xdd, 0xf1, 0xac, 0xad, 0x58, 0xc3, 0xf8, 0x88, 0x94, 0x5e, 0x06, 0x98, 0xa1, 0xe4, 0x6a, 0xfb, 0x0a, 0x49, 0x5d, 0x8a, 0xfe, 0x77}} , + {{0x46, 0x02, 0xf5, 0xa5, 0xaf, 0xc5, 0x75, 0x6d, 0xba, 0x45, 0x35, 0x0a, 0xfe, 0xc9, 0xac, 0x22, 0x91, 0x8d, 0x21, 0x95, 0x33, 0x03, 0xc0, 0x8a, 0x16, 0xf3, 0x39, 0xe0, 0x01, 0x0f, 0x53, 0x3c}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x34, 0x75, 0x37, 0x1f, 0x34, 0x4e, 0xa9, 0x1d, 0x68, 0x67, 0xf8, 0x49, 0x98, 0x96, 0xfc, 0x4c, 0x65, 0x97, 0xf7, 0x02, 0x4a, 0x52, 0x6c, 0x01, 0xbd, 0x48, 0xbb, 0x1b, 0xed, 0xa4, 0xe2, 0x53}} , + {{0x59, 0xd5, 0x9b, 0x5a, 0xa2, 0x90, 0xd3, 0xb8, 0x37, 0x4c, 0x55, 0x82, 0x28, 0x08, 0x0f, 0x7f, 0xaa, 0x81, 0x65, 0xe0, 0x0c, 0x52, 0xc9, 0xa3, 0x32, 0x27, 0x64, 0xda, 0xfd, 0x34, 0x23, 0x5a}}}, +{{{0xb5, 0xb0, 0x0c, 0x4d, 0xb3, 0x7b, 0x23, 0xc8, 0x1f, 0x8a, 0x39, 0x66, 0xe6, 0xba, 0x4c, 0x10, 0x37, 0xca, 0x9c, 0x7c, 0x05, 0x9e, 0xff, 0xc0, 0xf8, 0x8e, 0xb1, 0x8f, 0x6f, 0x67, 0x18, 0x26}} , + {{0x4b, 0x41, 0x13, 0x54, 0x23, 0x1a, 0xa4, 0x4e, 0xa9, 0x8b, 0x1e, 0x4b, 0xfc, 0x15, 0x24, 0xbb, 0x7e, 0xcb, 0xb6, 0x1e, 0x1b, 0xf5, 0xf2, 0xc8, 0x56, 0xec, 0x32, 0xa2, 0x60, 0x5b, 0xa0, 0x2a}}}, +{{{0xa4, 0x29, 0x47, 0x86, 0x2e, 0x92, 0x4f, 0x11, 0x4f, 0xf3, 0xb2, 0x5c, 0xd5, 0x3e, 0xa6, 0xb9, 0xc8, 0xe2, 0x33, 0x11, 0x1f, 0x01, 0x8f, 0xb0, 0x9b, 0xc7, 0xa5, 0xff, 0x83, 0x0f, 0x1e, 0x28}} , + {{0x1d, 0x29, 0x7a, 0xa1, 0xec, 0x8e, 0xb5, 0xad, 0xea, 0x02, 0x68, 0x60, 0x74, 0x29, 0x1c, 0xa5, 0xcf, 0xc8, 0x3b, 0x7d, 0x8b, 0x2b, 0x7c, 0xad, 0xa4, 0x40, 0x17, 0x51, 0x59, 0x7c, 0x2e, 0x5d}}}, +{{{0x0a, 0x6c, 0x4f, 0xbc, 0x3e, 0x32, 0xe7, 0x4a, 0x1a, 0x13, 0xc1, 0x49, 0x38, 0xbf, 0xf7, 0xc2, 0xd3, 0x8f, 0x6b, 0xad, 0x52, 0xf7, 0xcf, 0xbc, 0x27, 0xcb, 0x40, 0x67, 0x76, 0xcd, 0x6d, 0x56}} , + {{0xe5, 0xb0, 0x27, 0xad, 0xbe, 0x9b, 0xf2, 0xb5, 0x63, 0xde, 0x3a, 0x23, 0x95, 0xb7, 0x0a, 0x7e, 0xf3, 0x9e, 0x45, 0x6f, 0x19, 0x39, 0x75, 0x8f, 0x39, 0x3d, 0x0f, 0xc0, 0x9f, 0xf1, 0xe9, 0x51}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x88, 0xaa, 0x14, 0x24, 0x86, 0x94, 0x11, 0x12, 0x3e, 0x1a, 0xb5, 0xcc, 0xbb, 0xe0, 0x9c, 0xd5, 0x9c, 0x6d, 0xba, 0x58, 0x72, 0x8d, 0xfb, 0x22, 0x7b, 0x9f, 0x7c, 0x94, 0x30, 0xb3, 0x51, 0x21}} , + {{0xf6, 0x74, 0x3d, 0xf2, 0xaf, 0xd0, 0x1e, 0x03, 0x7c, 0x23, 0x6b, 0xc9, 0xfc, 0x25, 0x70, 0x90, 0xdc, 0x9a, 0xa4, 0xfb, 0x49, 0xfc, 0x3d, 0x0a, 0x35, 0x38, 0x6f, 0xe4, 0x7e, 0x50, 0x01, 0x2a}}}, +{{{0xd6, 0xe3, 0x96, 0x61, 0x3a, 0xfd, 0xef, 0x9b, 0x1f, 0x90, 0xa4, 0x24, 0x14, 0x5b, 0xc8, 0xde, 0x50, 0xb1, 0x1d, 0xaf, 0xe8, 0x55, 0x8a, 0x87, 0x0d, 0xfe, 0xaa, 0x3b, 0x82, 0x2c, 0x8d, 0x7b}} , + {{0x85, 0x0c, 0xaf, 0xf8, 0x83, 0x44, 0x49, 0xd9, 0x45, 0xcf, 0xf7, 0x48, 0xd9, 0x53, 0xb4, 0xf1, 0x65, 0xa0, 0xe1, 0xc3, 0xb3, 0x15, 0xed, 0x89, 0x9b, 0x4f, 0x62, 0xb3, 0x57, 0xa5, 0x45, 0x1c}}}, +{{{0x8f, 0x12, 0xea, 0xaf, 0xd1, 0x1f, 0x79, 0x10, 0x0b, 0xf6, 0xa3, 0x7b, 0xea, 0xac, 0x8b, 0x57, 0x32, 0x62, 0xe7, 0x06, 0x12, 0x51, 0xa0, 0x3b, 0x43, 0x5e, 0xa4, 0x20, 0x78, 0x31, 0xce, 0x0d}} , + {{0x84, 0x7c, 0xc2, 0xa6, 0x91, 0x23, 0xce, 0xbd, 0xdc, 0xf9, 0xce, 0xd5, 0x75, 0x30, 0x22, 0xe6, 0xf9, 0x43, 0x62, 0x0d, 0xf7, 0x75, 0x9d, 0x7f, 0x8c, 0xff, 0x7d, 0xe4, 0x72, 0xac, 0x9f, 0x1c}}}, +{{{0x88, 0xc1, 0x99, 0xd0, 0x3c, 0x1c, 0x5d, 0xb4, 0xef, 0x13, 0x0f, 0x90, 0xb9, 0x36, 0x2f, 0x95, 0x95, 0xc6, 0xdc, 0xde, 0x0a, 0x51, 0xe2, 0x8d, 0xf3, 0xbc, 0x51, 0xec, 0xdf, 0xb1, 0xa2, 0x5f}} , + {{0x2e, 0x68, 0xa1, 0x23, 0x7d, 0x9b, 0x40, 0x69, 0x85, 0x7b, 0x42, 0xbf, 0x90, 0x4b, 0xd6, 0x40, 0x2f, 0xd7, 0x52, 0x52, 0xb2, 0x21, 0xde, 0x64, 0xbd, 0x88, 0xc3, 0x6d, 0xa5, 0xfa, 0x81, 0x3f}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xfb, 0xfd, 0x47, 0x7b, 0x8a, 0x66, 0x9e, 0x79, 0x2e, 0x64, 0x82, 0xef, 0xf7, 0x21, 0xec, 0xf6, 0xd8, 0x86, 0x09, 0x31, 0x7c, 0xdd, 0x03, 0x6a, 0x58, 0xa0, 0x77, 0xb7, 0x9b, 0x8c, 0x87, 0x1f}} , + {{0x55, 0x47, 0xe4, 0xa8, 0x3d, 0x55, 0x21, 0x34, 0xab, 0x1d, 0xae, 0xe0, 0xf4, 0xea, 0xdb, 0xc5, 0xb9, 0x58, 0xbf, 0xc4, 0x2a, 0x89, 0x31, 0x1a, 0xf4, 0x2d, 0xe1, 0xca, 0x37, 0x99, 0x47, 0x59}}}, +{{{0xc7, 0xca, 0x63, 0xc1, 0x49, 0xa9, 0x35, 0x45, 0x55, 0x7e, 0xda, 0x64, 0x32, 0x07, 0x50, 0xf7, 0x32, 0xac, 0xde, 0x75, 0x58, 0x9b, 0x11, 0xb2, 0x3a, 0x1f, 0xf5, 0xf7, 0x79, 0x04, 0xe6, 0x08}} , + {{0x46, 0xfa, 0x22, 0x4b, 0xfa, 0xe1, 0xfe, 0x96, 0xfc, 0x67, 0xba, 0x67, 0x97, 0xc4, 0xe7, 0x1b, 0x86, 0x90, 0x5f, 0xee, 0xf4, 0x5b, 0x11, 0xb2, 0xcd, 0xad, 0xee, 0xc2, 0x48, 0x6c, 0x2b, 0x1b}}}, +{{{0xe3, 0x39, 0x62, 0xb4, 0x4f, 0x31, 0x04, 0xc9, 0xda, 0xd5, 0x73, 0x51, 0x57, 0xc5, 0xb8, 0xf3, 0xa3, 0x43, 0x70, 0xe4, 0x61, 0x81, 0x84, 0xe2, 0xbb, 0xbf, 0x4f, 0x9e, 0xa4, 0x5e, 0x74, 0x06}} , + {{0x29, 0xac, 0xff, 0x27, 0xe0, 0x59, 0xbe, 0x39, 0x9c, 0x0d, 0x83, 0xd7, 0x10, 0x0b, 0x15, 0xb7, 0xe1, 0xc2, 0x2c, 0x30, 0x73, 0x80, 0x3a, 0x7d, 0x5d, 0xab, 0x58, 0x6b, 0xc1, 0xf0, 0xf4, 0x22}}}, +{{{0xfe, 0x7f, 0xfb, 0x35, 0x7d, 0xc6, 0x01, 0x23, 0x28, 0xc4, 0x02, 0xac, 0x1f, 0x42, 0xb4, 0x9d, 0xfc, 0x00, 0x94, 0xa5, 0xee, 0xca, 0xda, 0x97, 0x09, 0x41, 0x77, 0x87, 0x5d, 0x7b, 0x87, 0x78}} , + {{0xf5, 0xfb, 0x90, 0x2d, 0x81, 0x19, 0x9e, 0x2f, 0x6d, 0x85, 0x88, 0x8c, 0x40, 0x5c, 0x77, 0x41, 0x4d, 0x01, 0x19, 0x76, 0x60, 0xe8, 0x4c, 0x48, 0xe4, 0x33, 0x83, 0x32, 0x6c, 0xb4, 0x41, 0x03}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xff, 0x10, 0xc2, 0x09, 0x4f, 0x6e, 0xf4, 0xd2, 0xdf, 0x7e, 0xca, 0x7b, 0x1c, 0x1d, 0xba, 0xa3, 0xb6, 0xda, 0x67, 0x33, 0xd4, 0x87, 0x36, 0x4b, 0x11, 0x20, 0x05, 0xa6, 0x29, 0xc1, 0x87, 0x17}} , + {{0xf6, 0x96, 0xca, 0x2f, 0xda, 0x38, 0xa7, 0x1b, 0xfc, 0xca, 0x7d, 0xfe, 0x08, 0x89, 0xe2, 0x47, 0x2b, 0x6a, 0x5d, 0x4b, 0xfa, 0xa1, 0xb4, 0xde, 0xb6, 0xc2, 0x31, 0x51, 0xf5, 0xe0, 0xa4, 0x0b}}}, +{{{0x5c, 0xe5, 0xc6, 0x04, 0x8e, 0x2b, 0x57, 0xbe, 0x38, 0x85, 0x23, 0xcb, 0xb7, 0xbe, 0x4f, 0xa9, 0xd3, 0x6e, 0x12, 0xaa, 0xd5, 0xb2, 0x2e, 0x93, 0x29, 0x9a, 0x4a, 0x88, 0x18, 0x43, 0xf5, 0x01}} , + {{0x50, 0xfc, 0xdb, 0xa2, 0x59, 0x21, 0x8d, 0xbd, 0x7e, 0x33, 0xae, 0x2f, 0x87, 0x1a, 0xd0, 0x97, 0xc7, 0x0d, 0x4d, 0x63, 0x01, 0xef, 0x05, 0x84, 0xec, 0x40, 0xdd, 0xa8, 0x0a, 0x4f, 0x70, 0x0b}}}, +{{{0x41, 0x69, 0x01, 0x67, 0x5c, 0xd3, 0x8a, 0xc5, 0xcf, 0x3f, 0xd1, 0x57, 0xd1, 0x67, 0x3e, 0x01, 0x39, 0xb5, 0xcb, 0x81, 0x56, 0x96, 0x26, 0xb6, 0xc2, 0xe7, 0x5c, 0xfb, 0x63, 0x97, 0x58, 0x06}} , + {{0x0c, 0x0e, 0xf3, 0xba, 0xf0, 0xe5, 0xba, 0xb2, 0x57, 0x77, 0xc6, 0x20, 0x9b, 0x89, 0x24, 0xbe, 0xf2, 0x9c, 0x8a, 0xba, 0x69, 0xc1, 0xf1, 0xb0, 0x4f, 0x2a, 0x05, 0x9a, 0xee, 0x10, 0x7e, 0x36}}}, +{{{0x3f, 0x26, 0xe9, 0x40, 0xe9, 0x03, 0xad, 0x06, 0x69, 0x91, 0xe0, 0xd1, 0x89, 0x60, 0x84, 0x79, 0xde, 0x27, 0x6d, 0xe6, 0x76, 0xbd, 0xea, 0xe6, 0xae, 0x48, 0xc3, 0x67, 0xc0, 0x57, 0xcd, 0x2f}} , + {{0x7f, 0xc1, 0xdc, 0xb9, 0xc7, 0xbc, 0x86, 0x3d, 0x55, 0x4b, 0x28, 0x7a, 0xfb, 0x4d, 0xc7, 0xf8, 0xbc, 0x67, 0x2a, 0x60, 0x4d, 0x8f, 0x07, 0x0b, 0x1a, 0x17, 0xbf, 0xfa, 0xac, 0xa7, 0x3d, 0x1a}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x91, 0x3f, 0xed, 0x5e, 0x18, 0x78, 0x3f, 0x23, 0x2c, 0x0d, 0x8c, 0x44, 0x00, 0xe8, 0xfb, 0xe9, 0x8e, 0xd6, 0xd1, 0x36, 0x58, 0x57, 0x9e, 0xae, 0x4b, 0x5c, 0x0b, 0x07, 0xbc, 0x6b, 0x55, 0x2b}} , + {{0x6f, 0x4d, 0x17, 0xd7, 0xe1, 0x84, 0xd9, 0x78, 0xb1, 0x90, 0xfd, 0x2e, 0xb3, 0xb5, 0x19, 0x3f, 0x1b, 0xfa, 0xc0, 0x68, 0xb3, 0xdd, 0x00, 0x2e, 0x89, 0xbd, 0x7e, 0x80, 0x32, 0x13, 0xa0, 0x7b}}}, +{{{0x1a, 0x6f, 0x40, 0xaf, 0x44, 0x44, 0xb0, 0x43, 0x8f, 0x0d, 0xd0, 0x1e, 0xc4, 0x0b, 0x19, 0x5d, 0x8e, 0xfe, 0xc1, 0xf3, 0xc5, 0x5c, 0x91, 0xf8, 0x04, 0x4e, 0xbe, 0x90, 0xb4, 0x47, 0x5c, 0x3f}} , + {{0xb0, 0x3b, 0x2c, 0xf3, 0xfe, 0x32, 0x71, 0x07, 0x3f, 0xaa, 0xba, 0x45, 0x60, 0xa8, 0x8d, 0xea, 0x54, 0xcb, 0x39, 0x10, 0xb4, 0xf2, 0x8b, 0xd2, 0x14, 0x82, 0x42, 0x07, 0x8e, 0xe9, 0x7c, 0x53}}}, +{{{0xb0, 0xae, 0xc1, 0x8d, 0xc9, 0x8f, 0xb9, 0x7a, 0x77, 0xef, 0xba, 0x79, 0xa0, 0x3c, 0xa8, 0xf5, 0x6a, 0xe2, 0x3f, 0x5d, 0x00, 0xe3, 0x4b, 0x45, 0x24, 0x7b, 0x43, 0x78, 0x55, 0x1d, 0x2b, 0x1e}} , + {{0x01, 0xb8, 0xd6, 0x16, 0x67, 0xa0, 0x15, 0xb9, 0xe1, 0x58, 0xa4, 0xa7, 0x31, 0x37, 0x77, 0x2f, 0x8b, 0x12, 0x9f, 0xf4, 0x3f, 0xc7, 0x36, 0x66, 0xd2, 0xa8, 0x56, 0xf7, 0x7f, 0x74, 0xc6, 0x41}}}, +{{{0x5d, 0xf8, 0xb4, 0xa8, 0x30, 0xdd, 0xcc, 0x38, 0xa5, 0xd3, 0xca, 0xd8, 0xd1, 0xf8, 0xb2, 0x31, 0x91, 0xd4, 0x72, 0x05, 0x57, 0x4a, 0x3b, 0x82, 0x4a, 0xc6, 0x68, 0x20, 0xe2, 0x18, 0x41, 0x61}} , + {{0x19, 0xd4, 0x8d, 0x47, 0x29, 0x12, 0x65, 0xb0, 0x11, 0x78, 0x47, 0xb5, 0xcb, 0xa3, 0xa5, 0xfa, 0x05, 0x85, 0x54, 0xa9, 0x33, 0x97, 0x8d, 0x2b, 0xc2, 0xfe, 0x99, 0x35, 0x28, 0xe5, 0xeb, 0x63}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xb1, 0x3f, 0x3f, 0xef, 0xd8, 0xf4, 0xfc, 0xb3, 0xa0, 0x60, 0x50, 0x06, 0x2b, 0x29, 0x52, 0x70, 0x15, 0x0b, 0x24, 0x24, 0xf8, 0x5f, 0x79, 0x18, 0xcc, 0xff, 0x89, 0x99, 0x84, 0xa1, 0xae, 0x13}} , + {{0x44, 0x1f, 0xb8, 0xc2, 0x01, 0xc1, 0x30, 0x19, 0x55, 0x05, 0x60, 0x10, 0xa4, 0x6c, 0x2d, 0x67, 0x70, 0xe5, 0x25, 0x1b, 0xf2, 0xbf, 0xdd, 0xfb, 0x70, 0x2b, 0xa1, 0x8c, 0x9c, 0x94, 0x84, 0x08}}}, +{{{0xe7, 0xc4, 0x43, 0x4d, 0xc9, 0x2b, 0x69, 0x5d, 0x1d, 0x3c, 0xaf, 0xbb, 0x43, 0x38, 0x4e, 0x98, 0x3d, 0xed, 0x0d, 0x21, 0x03, 0xfd, 0xf0, 0x99, 0x47, 0x04, 0xb0, 0x98, 0x69, 0x55, 0x72, 0x0f}} , + {{0x5e, 0xdf, 0x15, 0x53, 0x3b, 0x86, 0x80, 0xb0, 0xf1, 0x70, 0x68, 0x8f, 0x66, 0x7c, 0x0e, 0x49, 0x1a, 0xd8, 0x6b, 0xfe, 0x4e, 0xef, 0xca, 0x47, 0xd4, 0x03, 0xc1, 0x37, 0x50, 0x9c, 0xc1, 0x16}}}, +{{{0xcd, 0x24, 0xc6, 0x3e, 0x0c, 0x82, 0x9b, 0x91, 0x2b, 0x61, 0x4a, 0xb2, 0x0f, 0x88, 0x55, 0x5f, 0x5a, 0x57, 0xff, 0xe5, 0x74, 0x0b, 0x13, 0x43, 0x00, 0xd8, 0x6b, 0xcf, 0xd2, 0x15, 0x03, 0x2c}} , + {{0xdc, 0xff, 0x15, 0x61, 0x2f, 0x4a, 0x2f, 0x62, 0xf2, 0x04, 0x2f, 0xb5, 0x0c, 0xb7, 0x1e, 0x3f, 0x74, 0x1a, 0x0f, 0xd7, 0xea, 0xcd, 0xd9, 0x7d, 0xf6, 0x12, 0x0e, 0x2f, 0xdb, 0x5a, 0x3b, 0x16}}}, +{{{0x1b, 0x37, 0x47, 0xe3, 0xf5, 0x9e, 0xea, 0x2c, 0x2a, 0xe7, 0x82, 0x36, 0xf4, 0x1f, 0x81, 0x47, 0x92, 0x4b, 0x69, 0x0e, 0x11, 0x8c, 0x5d, 0x53, 0x5b, 0x81, 0x27, 0x08, 0xbc, 0xa0, 0xae, 0x25}} , + {{0x69, 0x32, 0xa1, 0x05, 0x11, 0x42, 0x00, 0xd2, 0x59, 0xac, 0x4d, 0x62, 0x8b, 0x13, 0xe2, 0x50, 0x5d, 0xa0, 0x9d, 0x9b, 0xfd, 0xbb, 0x12, 0x41, 0x75, 0x41, 0x9e, 0xcc, 0xdc, 0xc7, 0xdc, 0x5d}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xd9, 0xe3, 0x38, 0x06, 0x46, 0x70, 0x82, 0x5e, 0x28, 0x49, 0x79, 0xff, 0x25, 0xd2, 0x4e, 0x29, 0x8d, 0x06, 0xb0, 0x23, 0xae, 0x9b, 0x66, 0xe4, 0x7d, 0xc0, 0x70, 0x91, 0xa3, 0xfc, 0xec, 0x4e}} , + {{0x62, 0x12, 0x37, 0x6a, 0x30, 0xf6, 0x1e, 0xfb, 0x14, 0x5c, 0x0d, 0x0e, 0xb7, 0x81, 0x6a, 0xe7, 0x08, 0x05, 0xac, 0xaa, 0x38, 0x46, 0xe2, 0x73, 0xea, 0x4b, 0x07, 0x81, 0x43, 0x7c, 0x9e, 0x5e}}}, +{{{0xfc, 0xf9, 0x21, 0x4f, 0x2e, 0x76, 0x9b, 0x1f, 0x28, 0x60, 0x77, 0x43, 0x32, 0x9d, 0xbe, 0x17, 0x30, 0x2a, 0xc6, 0x18, 0x92, 0x66, 0x62, 0x30, 0x98, 0x40, 0x11, 0xa6, 0x7f, 0x18, 0x84, 0x28}} , + {{0x3f, 0xab, 0xd3, 0xf4, 0x8a, 0x76, 0xa1, 0x3c, 0xca, 0x2d, 0x49, 0xc3, 0xea, 0x08, 0x0b, 0x85, 0x17, 0x2a, 0xc3, 0x6c, 0x08, 0xfd, 0x57, 0x9f, 0x3d, 0x5f, 0xdf, 0x67, 0x68, 0x42, 0x00, 0x32}}}, +{{{0x51, 0x60, 0x1b, 0x06, 0x4f, 0x8a, 0x21, 0xba, 0x38, 0xa8, 0xba, 0xd6, 0x40, 0xf6, 0xe9, 0x9b, 0x76, 0x4d, 0x56, 0x21, 0x5b, 0x0a, 0x9b, 0x2e, 0x4f, 0x3d, 0x81, 0x32, 0x08, 0x9f, 0x97, 0x5b}} , + {{0xe5, 0x44, 0xec, 0x06, 0x9d, 0x90, 0x79, 0x9f, 0xd3, 0xe0, 0x79, 0xaf, 0x8f, 0x10, 0xfd, 0xdd, 0x04, 0xae, 0x27, 0x97, 0x46, 0x33, 0x79, 0xea, 0xb8, 0x4e, 0xca, 0x5a, 0x59, 0x57, 0xe1, 0x0e}}}, +{{{0x1a, 0xda, 0xf3, 0xa5, 0x41, 0x43, 0x28, 0xfc, 0x7e, 0xe7, 0x71, 0xea, 0xc6, 0x3b, 0x59, 0xcc, 0x2e, 0xd3, 0x40, 0xec, 0xb3, 0x13, 0x6f, 0x44, 0xcd, 0x13, 0xb2, 0x37, 0xf2, 0x6e, 0xd9, 0x1c}} , + {{0xe3, 0xdb, 0x60, 0xcd, 0x5c, 0x4a, 0x18, 0x0f, 0xef, 0x73, 0x36, 0x71, 0x8c, 0xf6, 0x11, 0xb4, 0xd8, 0xce, 0x17, 0x5e, 0x4f, 0x26, 0x77, 0x97, 0x5f, 0xcb, 0xef, 0x91, 0xeb, 0x6a, 0x62, 0x7a}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x18, 0x4a, 0xa2, 0x97, 0x08, 0x81, 0x2d, 0x83, 0xc4, 0xcc, 0xf0, 0x83, 0x7e, 0xec, 0x0d, 0x95, 0x4c, 0x5b, 0xfb, 0xfa, 0x98, 0x80, 0x4a, 0x66, 0x56, 0x0c, 0x51, 0xb3, 0xf2, 0x04, 0x5d, 0x27}} , + {{0x3b, 0xb9, 0xb8, 0x06, 0x5a, 0x2e, 0xfe, 0xc3, 0x82, 0x37, 0x9c, 0xa3, 0x11, 0x1f, 0x9c, 0xa6, 0xda, 0x63, 0x48, 0x9b, 0xad, 0xde, 0x2d, 0xa6, 0xbc, 0x6e, 0x32, 0xda, 0x27, 0x65, 0xdd, 0x57}}}, +{{{0x84, 0x4f, 0x37, 0x31, 0x7d, 0x2e, 0xbc, 0xad, 0x87, 0x07, 0x2a, 0x6b, 0x37, 0xfc, 0x5f, 0xeb, 0x4e, 0x75, 0x35, 0xa6, 0xde, 0xab, 0x0a, 0x19, 0x3a, 0xb7, 0xb1, 0xef, 0x92, 0x6a, 0x3b, 0x3c}} , + {{0x3b, 0xb2, 0x94, 0x6d, 0x39, 0x60, 0xac, 0xee, 0xe7, 0x81, 0x1a, 0x3b, 0x76, 0x87, 0x5c, 0x05, 0x94, 0x2a, 0x45, 0xb9, 0x80, 0xe9, 0x22, 0xb1, 0x07, 0xcb, 0x40, 0x9e, 0x70, 0x49, 0x6d, 0x12}}}, +{{{0xfd, 0x18, 0x78, 0x84, 0xa8, 0x4c, 0x7d, 0x6e, 0x59, 0xa6, 0xe5, 0x74, 0xf1, 0x19, 0xa6, 0x84, 0x2e, 0x51, 0xc1, 0x29, 0x13, 0xf2, 0x14, 0x6b, 0x5d, 0x53, 0x51, 0xf7, 0xef, 0xbf, 0x01, 0x22}} , + {{0xa4, 0x4b, 0x62, 0x4c, 0xe6, 0xfd, 0x72, 0x07, 0xf2, 0x81, 0xfc, 0xf2, 0xbd, 0x12, 0x7c, 0x68, 0x76, 0x2a, 0xba, 0xf5, 0x65, 0xb1, 0x1f, 0x17, 0x0a, 0x38, 0xb0, 0xbf, 0xc0, 0xf8, 0xf4, 0x2a}}}, +{{{0x55, 0x60, 0x55, 0x5b, 0xe4, 0x1d, 0x71, 0x4c, 0x9d, 0x5b, 0x9f, 0x70, 0xa6, 0x85, 0x9a, 0x2c, 0xa0, 0xe2, 0x32, 0x48, 0xce, 0x9e, 0x2a, 0xa5, 0x07, 0x3b, 0xc7, 0x6c, 0x86, 0x77, 0xde, 0x3c}} , + {{0xf7, 0x18, 0x7a, 0x96, 0x7e, 0x43, 0x57, 0xa9, 0x55, 0xfc, 0x4e, 0xb6, 0x72, 0x00, 0xf2, 0xe4, 0xd7, 0x52, 0xd3, 0xd3, 0xb6, 0x85, 0xf6, 0x71, 0xc7, 0x44, 0x3f, 0x7f, 0xd7, 0xb3, 0xf2, 0x79}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x46, 0xca, 0xa7, 0x55, 0x7b, 0x79, 0xf3, 0xca, 0x5a, 0x65, 0xf6, 0xed, 0x50, 0x14, 0x7b, 0xe4, 0xc4, 0x2a, 0x65, 0x9e, 0xe2, 0xf9, 0xca, 0xa7, 0x22, 0x26, 0x53, 0xcb, 0x21, 0x5b, 0xa7, 0x31}} , + {{0x90, 0xd7, 0xc5, 0x26, 0x08, 0xbd, 0xb0, 0x53, 0x63, 0x58, 0xc3, 0x31, 0x5e, 0x75, 0x46, 0x15, 0x91, 0xa6, 0xf8, 0x2f, 0x1a, 0x08, 0x65, 0x88, 0x2f, 0x98, 0x04, 0xf1, 0x7c, 0x6e, 0x00, 0x77}}}, +{{{0x81, 0x21, 0x61, 0x09, 0xf6, 0x4e, 0xf1, 0x92, 0xee, 0x63, 0x61, 0x73, 0x87, 0xc7, 0x54, 0x0e, 0x42, 0x4b, 0xc9, 0x47, 0xd1, 0xb8, 0x7e, 0x91, 0x75, 0x37, 0x99, 0x28, 0xb8, 0xdd, 0x7f, 0x50}} , + {{0x89, 0x8f, 0xc0, 0xbe, 0x5d, 0xd6, 0x9f, 0xa0, 0xf0, 0x9d, 0x81, 0xce, 0x3a, 0x7b, 0x98, 0x58, 0xbb, 0xd7, 0x78, 0xc8, 0x3f, 0x13, 0xf1, 0x74, 0x19, 0xdf, 0xf8, 0x98, 0x89, 0x5d, 0xfa, 0x5f}}}, +{{{0x9e, 0x35, 0x85, 0x94, 0x47, 0x1f, 0x90, 0x15, 0x26, 0xd0, 0x84, 0xed, 0x8a, 0x80, 0xf7, 0x63, 0x42, 0x86, 0x27, 0xd7, 0xf4, 0x75, 0x58, 0xdc, 0x9c, 0xc0, 0x22, 0x7e, 0x20, 0x35, 0xfd, 0x1f}} , + {{0x68, 0x0e, 0x6f, 0x97, 0xba, 0x70, 0xbb, 0xa3, 0x0e, 0xe5, 0x0b, 0x12, 0xf4, 0xa2, 0xdc, 0x47, 0xf8, 0xe6, 0xd0, 0x23, 0x6c, 0x33, 0xa8, 0x99, 0x46, 0x6e, 0x0f, 0x44, 0xba, 0x76, 0x48, 0x0f}}}, +{{{0xa3, 0x2a, 0x61, 0x37, 0xe2, 0x59, 0x12, 0x0e, 0x27, 0xba, 0x64, 0x43, 0xae, 0xc0, 0x42, 0x69, 0x79, 0xa4, 0x1e, 0x29, 0x8b, 0x15, 0xeb, 0xf8, 0xaf, 0xd4, 0xa2, 0x68, 0x33, 0xb5, 0x7a, 0x24}} , + {{0x2c, 0x19, 0x33, 0xdd, 0x1b, 0xab, 0xec, 0x01, 0xb0, 0x23, 0xf8, 0x42, 0x2b, 0x06, 0x88, 0xea, 0x3d, 0x2d, 0x00, 0x2a, 0x78, 0x45, 0x4d, 0x38, 0xed, 0x2e, 0x2e, 0x44, 0x49, 0xed, 0xcb, 0x33}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xa0, 0x68, 0xe8, 0x41, 0x8f, 0x91, 0xf8, 0x11, 0x13, 0x90, 0x2e, 0xa7, 0xab, 0x30, 0xef, 0xad, 0xa0, 0x61, 0x00, 0x88, 0xef, 0xdb, 0xce, 0x5b, 0x5c, 0xbb, 0x62, 0xc8, 0x56, 0xf9, 0x00, 0x73}} , + {{0x3f, 0x60, 0xc1, 0x82, 0x2d, 0xa3, 0x28, 0x58, 0x24, 0x9e, 0x9f, 0xe3, 0x70, 0xcc, 0x09, 0x4e, 0x1a, 0x3f, 0x11, 0x11, 0x15, 0x07, 0x3c, 0xa4, 0x41, 0xe0, 0x65, 0xa3, 0x0a, 0x41, 0x6d, 0x11}}}, +{{{0x31, 0x40, 0x01, 0x52, 0x56, 0x94, 0x5b, 0x28, 0x8a, 0xaa, 0x52, 0xee, 0xd8, 0x0a, 0x05, 0x8d, 0xcd, 0xb5, 0xaa, 0x2e, 0x38, 0xaa, 0xb7, 0x87, 0xf7, 0x2b, 0xfb, 0x04, 0xcb, 0x84, 0x3d, 0x54}} , + {{0x20, 0xef, 0x59, 0xde, 0xa4, 0x2b, 0x93, 0x6e, 0x2e, 0xec, 0x42, 0x9a, 0xd4, 0x2d, 0xf4, 0x46, 0x58, 0x27, 0x2b, 0x18, 0x8f, 0x83, 0x3d, 0x69, 0x9e, 0xd4, 0x3e, 0xb6, 0xc5, 0xfd, 0x58, 0x03}}}, +{{{0x33, 0x89, 0xc9, 0x63, 0x62, 0x1c, 0x17, 0xb4, 0x60, 0xc4, 0x26, 0x68, 0x09, 0xc3, 0x2e, 0x37, 0x0f, 0x7b, 0xb4, 0x9c, 0xb6, 0xf9, 0xfb, 0xd4, 0x51, 0x78, 0xc8, 0x63, 0xea, 0x77, 0x47, 0x07}} , + {{0x32, 0xb4, 0x18, 0x47, 0x79, 0xcb, 0xd4, 0x5a, 0x07, 0x14, 0x0f, 0xa0, 0xd5, 0xac, 0xd0, 0x41, 0x40, 0xab, 0x61, 0x23, 0xe5, 0x2a, 0x2a, 0x6f, 0xf7, 0xa8, 0xd4, 0x76, 0xef, 0xe7, 0x45, 0x6c}}}, +{{{0xa1, 0x5e, 0x60, 0x4f, 0xfb, 0xe1, 0x70, 0x6a, 0x1f, 0x55, 0x4f, 0x09, 0xb4, 0x95, 0x33, 0x36, 0xc6, 0x81, 0x01, 0x18, 0x06, 0x25, 0x27, 0xa4, 0xb4, 0x24, 0xa4, 0x86, 0x03, 0x4c, 0xac, 0x02}} , + {{0x77, 0x38, 0xde, 0xd7, 0x60, 0x48, 0x07, 0xf0, 0x74, 0xa8, 0xff, 0x54, 0xe5, 0x30, 0x43, 0xff, 0x77, 0xfb, 0x21, 0x07, 0xff, 0xb2, 0x07, 0x6b, 0xe4, 0xe5, 0x30, 0xfc, 0x19, 0x6c, 0xa3, 0x01}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x13, 0xc5, 0x2c, 0xac, 0xd3, 0x83, 0x82, 0x7c, 0x29, 0xf7, 0x05, 0xa5, 0x00, 0xb6, 0x1f, 0x86, 0x55, 0xf4, 0xd6, 0x2f, 0x0c, 0x99, 0xd0, 0x65, 0x9b, 0x6b, 0x46, 0x0d, 0x43, 0xf8, 0x16, 0x28}} , + {{0x1e, 0x7f, 0xb4, 0x74, 0x7e, 0xb1, 0x89, 0x4f, 0x18, 0x5a, 0xab, 0x64, 0x06, 0xdf, 0x45, 0x87, 0xe0, 0x6a, 0xc6, 0xf0, 0x0e, 0xc9, 0x24, 0x35, 0x38, 0xea, 0x30, 0x54, 0xb4, 0xc4, 0x52, 0x54}}}, +{{{0xe9, 0x9f, 0xdc, 0x3f, 0xc1, 0x89, 0x44, 0x74, 0x27, 0xe4, 0xc1, 0x90, 0xff, 0x4a, 0xa7, 0x3c, 0xee, 0xcd, 0xf4, 0x1d, 0x25, 0x94, 0x7f, 0x63, 0x16, 0x48, 0xbc, 0x64, 0xfe, 0x95, 0xc4, 0x0c}} , + {{0x8b, 0x19, 0x75, 0x6e, 0x03, 0x06, 0x5e, 0x6a, 0x6f, 0x1a, 0x8c, 0xe3, 0xd3, 0x28, 0xf2, 0xe0, 0xb9, 0x7a, 0x43, 0x69, 0xe6, 0xd3, 0xc0, 0xfe, 0x7e, 0x97, 0xab, 0x6c, 0x7b, 0x8e, 0x13, 0x42}}}, +{{{0xd4, 0xca, 0x70, 0x3d, 0xab, 0xfb, 0x5f, 0x5e, 0x00, 0x0c, 0xcc, 0x77, 0x22, 0xf8, 0x78, 0x55, 0xae, 0x62, 0x35, 0xfb, 0x9a, 0xc6, 0x03, 0xe4, 0x0c, 0xee, 0xab, 0xc7, 0xc0, 0x89, 0x87, 0x54}} , + {{0x32, 0xad, 0xae, 0x85, 0x58, 0x43, 0xb8, 0xb1, 0xe6, 0x3e, 0x00, 0x9c, 0x78, 0x88, 0x56, 0xdb, 0x9c, 0xfc, 0x79, 0xf6, 0xf9, 0x41, 0x5f, 0xb7, 0xbc, 0x11, 0xf9, 0x20, 0x36, 0x1c, 0x53, 0x2b}}}, +{{{0x5a, 0x20, 0x5b, 0xa1, 0xa5, 0x44, 0x91, 0x24, 0x02, 0x63, 0x12, 0x64, 0xb8, 0x55, 0xf6, 0xde, 0x2c, 0xdb, 0x47, 0xb8, 0xc6, 0x0a, 0xc3, 0x00, 0x78, 0x93, 0xd8, 0xf5, 0xf5, 0x18, 0x28, 0x0a}} , + {{0xd6, 0x1b, 0x9a, 0x6c, 0xe5, 0x46, 0xea, 0x70, 0x96, 0x8d, 0x4e, 0x2a, 0x52, 0x21, 0x26, 0x4b, 0xb1, 0xbb, 0x0f, 0x7c, 0xa9, 0x9b, 0x04, 0xbb, 0x51, 0x08, 0xf1, 0x9a, 0xa4, 0x76, 0x7c, 0x18}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xfa, 0x94, 0xf7, 0x40, 0xd0, 0xd7, 0xeb, 0xa9, 0x82, 0x36, 0xd5, 0x15, 0xb9, 0x33, 0x7a, 0xbf, 0x8a, 0xf2, 0x63, 0xaa, 0x37, 0xf5, 0x59, 0xac, 0xbd, 0xbb, 0x32, 0x36, 0xbe, 0x73, 0x99, 0x38}} , + {{0x2c, 0xb3, 0xda, 0x7a, 0xd8, 0x3d, 0x99, 0xca, 0xd2, 0xf4, 0xda, 0x99, 0x8e, 0x4f, 0x98, 0xb7, 0xf4, 0xae, 0x3e, 0x9f, 0x8e, 0x35, 0x60, 0xa4, 0x33, 0x75, 0xa4, 0x04, 0x93, 0xb1, 0x6b, 0x4d}}}, +{{{0x97, 0x9d, 0xa8, 0xcd, 0x97, 0x7b, 0x9d, 0xb9, 0xe7, 0xa5, 0xef, 0xfd, 0xa8, 0x42, 0x6b, 0xc3, 0x62, 0x64, 0x7d, 0xa5, 0x1b, 0xc9, 0x9e, 0xd2, 0x45, 0xb9, 0xee, 0x03, 0xb0, 0xbf, 0xc0, 0x68}} , + {{0xed, 0xb7, 0x84, 0x2c, 0xf6, 0xd3, 0xa1, 0x6b, 0x24, 0x6d, 0x87, 0x56, 0x97, 0x59, 0x79, 0x62, 0x9f, 0xac, 0xed, 0xf3, 0xc9, 0x89, 0x21, 0x2e, 0x04, 0xb3, 0xcc, 0x2f, 0xbe, 0xd6, 0x0a, 0x4b}}}, +{{{0x39, 0x61, 0x05, 0xed, 0x25, 0x89, 0x8b, 0x5d, 0x1b, 0xcb, 0x0c, 0x55, 0xf4, 0x6a, 0x00, 0x8a, 0x46, 0xe8, 0x1e, 0xc6, 0x83, 0xc8, 0x5a, 0x76, 0xdb, 0xcc, 0x19, 0x7a, 0xcc, 0x67, 0x46, 0x0b}} , + {{0x53, 0xcf, 0xc2, 0xa1, 0xad, 0x6a, 0xf3, 0xcd, 0x8f, 0xc9, 0xde, 0x1c, 0xf8, 0x6c, 0x8f, 0xf8, 0x76, 0x42, 0xe7, 0xfe, 0xb2, 0x72, 0x21, 0x0a, 0x66, 0x74, 0x8f, 0xb7, 0xeb, 0xe4, 0x6f, 0x01}}}, +{{{0x22, 0x8c, 0x6b, 0xbe, 0xfc, 0x4d, 0x70, 0x62, 0x6e, 0x52, 0x77, 0x99, 0x88, 0x7e, 0x7b, 0x57, 0x7a, 0x0d, 0xfe, 0xdc, 0x72, 0x92, 0xf1, 0x68, 0x1d, 0x97, 0xd7, 0x7c, 0x8d, 0x53, 0x10, 0x37}} , + {{0x53, 0x88, 0x77, 0x02, 0xca, 0x27, 0xa8, 0xe5, 0x45, 0xe2, 0xa8, 0x48, 0x2a, 0xab, 0x18, 0xca, 0xea, 0x2d, 0x2a, 0x54, 0x17, 0x37, 0x32, 0x09, 0xdc, 0xe0, 0x4a, 0xb7, 0x7d, 0x82, 0x10, 0x7d}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x8a, 0x64, 0x1e, 0x14, 0x0a, 0x57, 0xd4, 0xda, 0x5c, 0x96, 0x9b, 0x01, 0x4c, 0x67, 0xbf, 0x8b, 0x30, 0xfe, 0x08, 0xdb, 0x0d, 0xd5, 0xa8, 0xd7, 0x09, 0x11, 0x85, 0xa2, 0xd3, 0x45, 0xfb, 0x7e}} , + {{0xda, 0x8c, 0xc2, 0xd0, 0xac, 0x18, 0xe8, 0x52, 0x36, 0xd4, 0x21, 0xa3, 0xdd, 0x57, 0x22, 0x79, 0xb7, 0xf8, 0x71, 0x9d, 0xc6, 0x91, 0x70, 0x86, 0x56, 0xbf, 0xa1, 0x11, 0x8b, 0x19, 0xe1, 0x0f}}}, +{{{0x18, 0x32, 0x98, 0x2c, 0x8f, 0x91, 0xae, 0x12, 0xf0, 0x8c, 0xea, 0xf3, 0x3c, 0xb9, 0x5d, 0xe4, 0x69, 0xed, 0xb2, 0x47, 0x18, 0xbd, 0xce, 0x16, 0x52, 0x5c, 0x23, 0xe2, 0xa5, 0x25, 0x52, 0x5d}} , + {{0xb9, 0xb1, 0xe7, 0x5d, 0x4e, 0xbc, 0xee, 0xbb, 0x40, 0x81, 0x77, 0x82, 0x19, 0xab, 0xb5, 0xc6, 0xee, 0xab, 0x5b, 0x6b, 0x63, 0x92, 0x8a, 0x34, 0x8d, 0xcd, 0xee, 0x4f, 0x49, 0xe5, 0xc9, 0x7e}}}, +{{{0x21, 0xac, 0x8b, 0x22, 0xcd, 0xc3, 0x9a, 0xe9, 0x5e, 0x78, 0xbd, 0xde, 0xba, 0xad, 0xab, 0xbf, 0x75, 0x41, 0x09, 0xc5, 0x58, 0xa4, 0x7d, 0x92, 0xb0, 0x7f, 0xf2, 0xa1, 0xd1, 0xc0, 0xb3, 0x6d}} , + {{0x62, 0x4f, 0xd0, 0x75, 0x77, 0xba, 0x76, 0x77, 0xd7, 0xb8, 0xd8, 0x92, 0x6f, 0x98, 0x34, 0x3d, 0xd6, 0x4e, 0x1c, 0x0f, 0xf0, 0x8f, 0x2e, 0xf1, 0xb3, 0xbd, 0xb1, 0xb9, 0xec, 0x99, 0xb4, 0x07}}}, +{{{0x60, 0x57, 0x2e, 0x9a, 0x72, 0x1d, 0x6b, 0x6e, 0x58, 0x33, 0x24, 0x8c, 0x48, 0x39, 0x46, 0x8e, 0x89, 0x6a, 0x88, 0x51, 0x23, 0x62, 0xb5, 0x32, 0x09, 0x36, 0xe3, 0x57, 0xf5, 0x98, 0xde, 0x6f}} , + {{0x8b, 0x2c, 0x00, 0x48, 0x4a, 0xf9, 0x5b, 0x87, 0x69, 0x52, 0xe5, 0x5b, 0xd1, 0xb1, 0xe5, 0x25, 0x25, 0xe0, 0x9c, 0xc2, 0x13, 0x44, 0xe8, 0xb9, 0x0a, 0x70, 0xad, 0xbd, 0x0f, 0x51, 0x94, 0x69}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xa2, 0xdc, 0xab, 0xa9, 0x25, 0x2d, 0xac, 0x5f, 0x03, 0x33, 0x08, 0xe7, 0x7e, 0xfe, 0x95, 0x36, 0x3c, 0x5b, 0x3a, 0xd3, 0x05, 0x82, 0x1c, 0x95, 0x2d, 0xd8, 0x77, 0x7e, 0x02, 0xd9, 0x5b, 0x70}} , + {{0xc2, 0xfe, 0x1b, 0x0c, 0x67, 0xcd, 0xd6, 0xe0, 0x51, 0x8e, 0x2c, 0xe0, 0x79, 0x88, 0xf0, 0xcf, 0x41, 0x4a, 0xad, 0x23, 0xd4, 0x46, 0xca, 0x94, 0xa1, 0xc3, 0xeb, 0x28, 0x06, 0xfa, 0x17, 0x14}}}, +{{{0x7b, 0xaa, 0x70, 0x0a, 0x4b, 0xfb, 0xf5, 0xbf, 0x80, 0xc5, 0xcf, 0x08, 0x7a, 0xdd, 0xa1, 0xf4, 0x9d, 0x54, 0x50, 0x53, 0x23, 0x77, 0x23, 0xf5, 0x34, 0xa5, 0x22, 0xd1, 0x0d, 0x96, 0x2e, 0x47}} , + {{0xcc, 0xb7, 0x32, 0x89, 0x57, 0xd0, 0x98, 0x75, 0xe4, 0x37, 0x99, 0xa9, 0xe8, 0xba, 0xed, 0xba, 0xeb, 0xc7, 0x4f, 0x15, 0x76, 0x07, 0x0c, 0x4c, 0xef, 0x9f, 0x52, 0xfc, 0x04, 0x5d, 0x58, 0x10}}}, +{{{0xce, 0x82, 0xf0, 0x8f, 0x79, 0x02, 0xa8, 0xd1, 0xda, 0x14, 0x09, 0x48, 0xee, 0x8a, 0x40, 0x98, 0x76, 0x60, 0x54, 0x5a, 0xde, 0x03, 0x24, 0xf5, 0xe6, 0x2f, 0xe1, 0x03, 0xbf, 0x68, 0x82, 0x7f}} , + {{0x64, 0xe9, 0x28, 0xc7, 0xa4, 0xcf, 0x2a, 0xf9, 0x90, 0x64, 0x72, 0x2c, 0x8b, 0xeb, 0xec, 0xa0, 0xf2, 0x7d, 0x35, 0xb5, 0x90, 0x4d, 0x7f, 0x5b, 0x4a, 0x49, 0xe4, 0xb8, 0x3b, 0xc8, 0xa1, 0x2f}}}, +{{{0x8b, 0xc5, 0xcc, 0x3d, 0x69, 0xa6, 0xa1, 0x18, 0x44, 0xbc, 0x4d, 0x77, 0x37, 0xc7, 0x86, 0xec, 0x0c, 0xc9, 0xd6, 0x44, 0xa9, 0x23, 0x27, 0xb9, 0x03, 0x34, 0xa7, 0x0a, 0xd5, 0xc7, 0x34, 0x37}} , + {{0xf9, 0x7e, 0x3e, 0x66, 0xee, 0xf9, 0x99, 0x28, 0xff, 0xad, 0x11, 0xd8, 0xe2, 0x66, 0xc5, 0xcd, 0x0f, 0x0d, 0x0b, 0x6a, 0xfc, 0x7c, 0x24, 0xa8, 0x4f, 0xa8, 0x5e, 0x80, 0x45, 0x8b, 0x6c, 0x41}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xef, 0x1e, 0xec, 0xf7, 0x8d, 0x77, 0xf2, 0xea, 0xdb, 0x60, 0x03, 0x21, 0xc0, 0xff, 0x5e, 0x67, 0xc3, 0x71, 0x0b, 0x21, 0xb4, 0x41, 0xa0, 0x68, 0x38, 0xc6, 0x01, 0xa3, 0xd3, 0x51, 0x3c, 0x3c}} , + {{0x92, 0xf8, 0xd6, 0x4b, 0xef, 0x42, 0x13, 0xb2, 0x4a, 0xc4, 0x2e, 0x72, 0x3f, 0xc9, 0x11, 0xbd, 0x74, 0x02, 0x0e, 0xf5, 0x13, 0x9d, 0x83, 0x1a, 0x1b, 0xd5, 0x54, 0xde, 0xc4, 0x1e, 0x16, 0x6c}}}, +{{{0x27, 0x52, 0xe4, 0x63, 0xaa, 0x94, 0xe6, 0xc3, 0x28, 0x9c, 0xc6, 0x56, 0xac, 0xfa, 0xb6, 0xbd, 0xe2, 0xcc, 0x76, 0xc6, 0x27, 0x27, 0xa2, 0x8e, 0x78, 0x2b, 0x84, 0x72, 0x10, 0xbd, 0x4e, 0x2a}} , + {{0xea, 0xa7, 0x23, 0xef, 0x04, 0x61, 0x80, 0x50, 0xc9, 0x6e, 0xa5, 0x96, 0xd1, 0xd1, 0xc8, 0xc3, 0x18, 0xd7, 0x2d, 0xfd, 0x26, 0xbd, 0xcb, 0x7b, 0x92, 0x51, 0x0e, 0x4a, 0x65, 0x57, 0xb8, 0x49}}}, +{{{0xab, 0x55, 0x36, 0xc3, 0xec, 0x63, 0x55, 0x11, 0x55, 0xf6, 0xa5, 0xc7, 0x01, 0x5f, 0xfe, 0x79, 0xd8, 0x0a, 0xf7, 0x03, 0xd8, 0x98, 0x99, 0xf5, 0xd0, 0x00, 0x54, 0x6b, 0x66, 0x28, 0xf5, 0x25}} , + {{0x7a, 0x8d, 0xa1, 0x5d, 0x70, 0x5d, 0x51, 0x27, 0xee, 0x30, 0x65, 0x56, 0x95, 0x46, 0xde, 0xbd, 0x03, 0x75, 0xb4, 0x57, 0x59, 0x89, 0xeb, 0x02, 0x9e, 0xcc, 0x89, 0x19, 0xa7, 0xcb, 0x17, 0x67}}}, +{{{0x6a, 0xeb, 0xfc, 0x9a, 0x9a, 0x10, 0xce, 0xdb, 0x3a, 0x1c, 0x3c, 0x6a, 0x9d, 0xea, 0x46, 0xbc, 0x45, 0x49, 0xac, 0xe3, 0x41, 0x12, 0x7c, 0xf0, 0xf7, 0x4f, 0xf9, 0xf7, 0xff, 0x2c, 0x89, 0x04}} , + {{0x30, 0x31, 0x54, 0x1a, 0x46, 0xca, 0xe6, 0xc6, 0xcb, 0xe2, 0xc3, 0xc1, 0x8b, 0x75, 0x81, 0xbe, 0xee, 0xf8, 0xa3, 0x11, 0x1c, 0x25, 0xa3, 0xa7, 0x35, 0x51, 0x55, 0xe2, 0x25, 0xaa, 0xe2, 0x3a}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xb4, 0x48, 0x10, 0x9f, 0x8a, 0x09, 0x76, 0xfa, 0xf0, 0x7a, 0xb0, 0x70, 0xf7, 0x83, 0x80, 0x52, 0x84, 0x2b, 0x26, 0xa2, 0xc4, 0x5d, 0x4f, 0xba, 0xb1, 0xc8, 0x40, 0x0d, 0x78, 0x97, 0xc4, 0x60}} , + {{0xd4, 0xb1, 0x6c, 0x08, 0xc7, 0x40, 0x38, 0x73, 0x5f, 0x0b, 0xf3, 0x76, 0x5d, 0xb2, 0xa5, 0x2f, 0x57, 0x57, 0x07, 0xed, 0x08, 0xa2, 0x6c, 0x4f, 0x08, 0x02, 0xb5, 0x0e, 0xee, 0x44, 0xfa, 0x22}}}, +{{{0x0f, 0x00, 0x3f, 0xa6, 0x04, 0x19, 0x56, 0x65, 0x31, 0x7f, 0x8b, 0xeb, 0x0d, 0xe1, 0x47, 0x89, 0x97, 0x16, 0x53, 0xfa, 0x81, 0xa7, 0xaa, 0xb2, 0xbf, 0x67, 0xeb, 0x72, 0x60, 0x81, 0x0d, 0x48}} , + {{0x7e, 0x13, 0x33, 0xcd, 0xa8, 0x84, 0x56, 0x1e, 0x67, 0xaf, 0x6b, 0x43, 0xac, 0x17, 0xaf, 0x16, 0xc0, 0x52, 0x99, 0x49, 0x5b, 0x87, 0x73, 0x7e, 0xb5, 0x43, 0xda, 0x6b, 0x1d, 0x0f, 0x2d, 0x55}}}, +{{{0xe9, 0x58, 0x1f, 0xff, 0x84, 0x3f, 0x93, 0x1c, 0xcb, 0xe1, 0x30, 0x69, 0xa5, 0x75, 0x19, 0x7e, 0x14, 0x5f, 0xf8, 0xfc, 0x09, 0xdd, 0xa8, 0x78, 0x9d, 0xca, 0x59, 0x8b, 0xd1, 0x30, 0x01, 0x13}} , + {{0xff, 0x76, 0x03, 0xc5, 0x4b, 0x89, 0x99, 0x70, 0x00, 0x59, 0x70, 0x9c, 0xd5, 0xd9, 0x11, 0x89, 0x5a, 0x46, 0xfe, 0xef, 0xdc, 0xd9, 0x55, 0x2b, 0x45, 0xa7, 0xb0, 0x2d, 0xfb, 0x24, 0xc2, 0x29}}}, +{{{0x38, 0x06, 0xf8, 0x0b, 0xac, 0x82, 0xc4, 0x97, 0x2b, 0x90, 0xe0, 0xf7, 0xa8, 0xab, 0x6c, 0x08, 0x80, 0x66, 0x90, 0x46, 0xf7, 0x26, 0x2d, 0xf8, 0xf1, 0xc4, 0x6b, 0x4a, 0x82, 0x98, 0x8e, 0x37}} , + {{0x8e, 0xb4, 0xee, 0xb8, 0xd4, 0x3f, 0xb2, 0x1b, 0xe0, 0x0a, 0x3d, 0x75, 0x34, 0x28, 0xa2, 0x8e, 0xc4, 0x92, 0x7b, 0xfe, 0x60, 0x6e, 0x6d, 0xb8, 0x31, 0x1d, 0x62, 0x0d, 0x78, 0x14, 0x42, 0x11}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x5e, 0xa8, 0xd8, 0x04, 0x9b, 0x73, 0xc9, 0xc9, 0xdc, 0x0d, 0x73, 0xbf, 0x0a, 0x0a, 0x73, 0xff, 0x18, 0x1f, 0x9c, 0x51, 0xaa, 0xc6, 0xf1, 0x83, 0x25, 0xfd, 0xab, 0xa3, 0x11, 0xd3, 0x01, 0x24}} , + {{0x4d, 0xe3, 0x7e, 0x38, 0x62, 0x5e, 0x64, 0xbb, 0x2b, 0x53, 0xb5, 0x03, 0x68, 0xc4, 0xf2, 0x2b, 0x5a, 0x03, 0x32, 0x99, 0x4a, 0x41, 0x9a, 0xe1, 0x1a, 0xae, 0x8c, 0x48, 0xf3, 0x24, 0x32, 0x65}}}, +{{{0xe8, 0xdd, 0xad, 0x3a, 0x8c, 0xea, 0xf4, 0xb3, 0xb2, 0xe5, 0x73, 0xf2, 0xed, 0x8b, 0xbf, 0xed, 0xb1, 0x0c, 0x0c, 0xfb, 0x2b, 0xf1, 0x01, 0x48, 0xe8, 0x26, 0x03, 0x8e, 0x27, 0x4d, 0x96, 0x72}} , + {{0xc8, 0x09, 0x3b, 0x60, 0xc9, 0x26, 0x4d, 0x7c, 0xf2, 0x9c, 0xd4, 0xa1, 0x3b, 0x26, 0xc2, 0x04, 0x33, 0x44, 0x76, 0x3c, 0x02, 0xbb, 0x11, 0x42, 0x0c, 0x22, 0xb7, 0xc6, 0xe1, 0xac, 0xb4, 0x0e}}}, +{{{0x6f, 0x85, 0xe7, 0xef, 0xde, 0x67, 0x30, 0xfc, 0xbf, 0x5a, 0xe0, 0x7b, 0x7a, 0x2a, 0x54, 0x6b, 0x5d, 0x62, 0x85, 0xa1, 0xf8, 0x16, 0x88, 0xec, 0x61, 0xb9, 0x96, 0xb5, 0xef, 0x2d, 0x43, 0x4d}} , + {{0x7c, 0x31, 0x33, 0xcc, 0xe4, 0xcf, 0x6c, 0xff, 0x80, 0x47, 0x77, 0xd1, 0xd8, 0xe9, 0x69, 0x97, 0x98, 0x7f, 0x20, 0x57, 0x1d, 0x1d, 0x4f, 0x08, 0x27, 0xc8, 0x35, 0x57, 0x40, 0xc6, 0x21, 0x0c}}}, +{{{0xd2, 0x8e, 0x9b, 0xfa, 0x42, 0x8e, 0xdf, 0x8f, 0xc7, 0x86, 0xf9, 0xa4, 0xca, 0x70, 0x00, 0x9d, 0x21, 0xbf, 0xec, 0x57, 0x62, 0x30, 0x58, 0x8c, 0x0d, 0x35, 0xdb, 0x5d, 0x8b, 0x6a, 0xa0, 0x5a}} , + {{0xc1, 0x58, 0x7c, 0x0d, 0x20, 0xdd, 0x11, 0x26, 0x5f, 0x89, 0x3b, 0x97, 0x58, 0xf8, 0x8b, 0xe3, 0xdf, 0x32, 0xe2, 0xfc, 0xd8, 0x67, 0xf2, 0xa5, 0x37, 0x1e, 0x6d, 0xec, 0x7c, 0x27, 0x20, 0x79}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xd0, 0xe9, 0xc0, 0xfa, 0x95, 0x45, 0x23, 0x96, 0xf1, 0x2c, 0x79, 0x25, 0x14, 0xce, 0x40, 0x14, 0x44, 0x2c, 0x36, 0x50, 0xd9, 0x63, 0x56, 0xb7, 0x56, 0x3b, 0x9e, 0xa7, 0xef, 0x89, 0xbb, 0x0e}} , + {{0xce, 0x7f, 0xdc, 0x0a, 0xcc, 0x82, 0x1c, 0x0a, 0x78, 0x71, 0xe8, 0x74, 0x8d, 0x01, 0x30, 0x0f, 0xa7, 0x11, 0x4c, 0xdf, 0x38, 0xd7, 0xa7, 0x0d, 0xf8, 0x48, 0x52, 0x00, 0x80, 0x7b, 0x5f, 0x0e}}}, +{{{0x25, 0x83, 0xe6, 0x94, 0x7b, 0x81, 0xb2, 0x91, 0xae, 0x0e, 0x05, 0xc9, 0xa3, 0x68, 0x2d, 0xd9, 0x88, 0x25, 0x19, 0x2a, 0x61, 0x61, 0x21, 0x97, 0x15, 0xa1, 0x35, 0xa5, 0x46, 0xc8, 0xa2, 0x0e}} , + {{0x1b, 0x03, 0x0d, 0x8b, 0x5a, 0x1b, 0x97, 0x4b, 0xf2, 0x16, 0x31, 0x3d, 0x1f, 0x33, 0xa0, 0x50, 0x3a, 0x18, 0xbe, 0x13, 0xa1, 0x76, 0xc1, 0xba, 0x1b, 0xf1, 0x05, 0x7b, 0x33, 0xa8, 0x82, 0x3b}}}, +{{{0xba, 0x36, 0x7b, 0x6d, 0xa9, 0xea, 0x14, 0x12, 0xc5, 0xfa, 0x91, 0x00, 0xba, 0x9b, 0x99, 0xcc, 0x56, 0x02, 0xe9, 0xa0, 0x26, 0x40, 0x66, 0x8c, 0xc4, 0xf8, 0x85, 0x33, 0x68, 0xe7, 0x03, 0x20}} , + {{0x50, 0x5b, 0xff, 0xa9, 0xb2, 0xf1, 0xf1, 0x78, 0xcf, 0x14, 0xa4, 0xa9, 0xfc, 0x09, 0x46, 0x94, 0x54, 0x65, 0x0d, 0x9c, 0x5f, 0x72, 0x21, 0xe2, 0x97, 0xa5, 0x2d, 0x81, 0xce, 0x4a, 0x5f, 0x79}}}, +{{{0x3d, 0x5f, 0x5c, 0xd2, 0xbc, 0x7d, 0x77, 0x0e, 0x2a, 0x6d, 0x22, 0x45, 0x84, 0x06, 0xc4, 0xdd, 0xc6, 0xa6, 0xc6, 0xd7, 0x49, 0xad, 0x6d, 0x87, 0x91, 0x0e, 0x3a, 0x67, 0x1d, 0x2c, 0x1d, 0x56}} , + {{0xfe, 0x7a, 0x74, 0xcf, 0xd4, 0xd2, 0xe5, 0x19, 0xde, 0xd0, 0xdb, 0x70, 0x23, 0x69, 0xe6, 0x6d, 0xec, 0xec, 0xcc, 0x09, 0x33, 0x6a, 0x77, 0xdc, 0x6b, 0x22, 0x76, 0x5d, 0x92, 0x09, 0xac, 0x2d}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x23, 0x15, 0x17, 0xeb, 0xd3, 0xdb, 0x12, 0x5e, 0x01, 0xf0, 0x91, 0xab, 0x2c, 0x41, 0xce, 0xac, 0xed, 0x1b, 0x4b, 0x2d, 0xbc, 0xdb, 0x17, 0x66, 0x89, 0x46, 0xad, 0x4b, 0x1e, 0x6f, 0x0b, 0x14}} , + {{0x11, 0xce, 0xbf, 0xb6, 0x77, 0x2d, 0x48, 0x22, 0x18, 0x4f, 0xa3, 0x5d, 0x4a, 0xb0, 0x70, 0x12, 0x3e, 0x54, 0xd7, 0xd8, 0x0e, 0x2b, 0x27, 0xdc, 0x53, 0xff, 0xca, 0x8c, 0x59, 0xb3, 0x4e, 0x44}}}, +{{{0x07, 0x76, 0x61, 0x0f, 0x66, 0xb2, 0x21, 0x39, 0x7e, 0xc0, 0xec, 0x45, 0x28, 0x82, 0xa1, 0x29, 0x32, 0x44, 0x35, 0x13, 0x5e, 0x61, 0x5e, 0x54, 0xcb, 0x7c, 0xef, 0xf6, 0x41, 0xcf, 0x9f, 0x0a}} , + {{0xdd, 0xf9, 0xda, 0x84, 0xc3, 0xe6, 0x8a, 0x9f, 0x24, 0xd2, 0x96, 0x5d, 0x39, 0x6f, 0x58, 0x8c, 0xc1, 0x56, 0x93, 0xab, 0xb5, 0x79, 0x3b, 0xd2, 0xa8, 0x73, 0x16, 0xed, 0xfa, 0xb4, 0x2f, 0x73}}}, +{{{0x8b, 0xb1, 0x95, 0xe5, 0x92, 0x50, 0x35, 0x11, 0x76, 0xac, 0xf4, 0x4d, 0x24, 0xc3, 0x32, 0xe6, 0xeb, 0xfe, 0x2c, 0x87, 0xc4, 0xf1, 0x56, 0xc4, 0x75, 0x24, 0x7a, 0x56, 0x85, 0x5a, 0x3a, 0x13}} , + {{0x0d, 0x16, 0xac, 0x3c, 0x4a, 0x58, 0x86, 0x3a, 0x46, 0x7f, 0x6c, 0xa3, 0x52, 0x6e, 0x37, 0xe4, 0x96, 0x9c, 0xe9, 0x5c, 0x66, 0x41, 0x67, 0xe4, 0xfb, 0x79, 0x0c, 0x05, 0xf6, 0x64, 0xd5, 0x7c}}}, +{{{0x28, 0xc1, 0xe1, 0x54, 0x73, 0xf2, 0xbf, 0x76, 0x74, 0x19, 0x19, 0x1b, 0xe4, 0xb9, 0xa8, 0x46, 0x65, 0x73, 0xf3, 0x77, 0x9b, 0x29, 0x74, 0x5b, 0xc6, 0x89, 0x6c, 0x2c, 0x7c, 0xf8, 0xb3, 0x0f}} , + {{0xf7, 0xd5, 0xe9, 0x74, 0x5d, 0xb8, 0x25, 0x16, 0xb5, 0x30, 0xbc, 0x84, 0xc5, 0xf0, 0xad, 0xca, 0x12, 0x28, 0xbc, 0x9d, 0xd4, 0xfa, 0x82, 0xe6, 0xe3, 0xbf, 0xa2, 0x15, 0x2c, 0xd4, 0x34, 0x10}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x61, 0xb1, 0x46, 0xba, 0x0e, 0x31, 0xa5, 0x67, 0x6c, 0x7f, 0xd6, 0xd9, 0x27, 0x85, 0x0f, 0x79, 0x14, 0xc8, 0x6c, 0x2f, 0x5f, 0x5b, 0x9c, 0x35, 0x3d, 0x38, 0x86, 0x77, 0x65, 0x55, 0x6a, 0x7b}} , + {{0xd3, 0xb0, 0x3a, 0x66, 0x60, 0x1b, 0x43, 0xf1, 0x26, 0x58, 0x99, 0x09, 0x8f, 0x2d, 0xa3, 0x14, 0x71, 0x85, 0xdb, 0xed, 0xf6, 0x26, 0xd5, 0x61, 0x9a, 0x73, 0xac, 0x0e, 0xea, 0xac, 0xb7, 0x0c}}}, +{{{0x5e, 0xf4, 0xe5, 0x17, 0x0e, 0x10, 0x9f, 0xe7, 0x43, 0x5f, 0x67, 0x5c, 0xac, 0x4b, 0xe5, 0x14, 0x41, 0xd2, 0xbf, 0x48, 0xf5, 0x14, 0xb0, 0x71, 0xc6, 0x61, 0xc1, 0xb2, 0x70, 0x58, 0xd2, 0x5a}} , + {{0x2d, 0xba, 0x16, 0x07, 0x92, 0x94, 0xdc, 0xbd, 0x50, 0x2b, 0xc9, 0x7f, 0x42, 0x00, 0xba, 0x61, 0xed, 0xf8, 0x43, 0xed, 0xf5, 0xf9, 0x40, 0x60, 0xb2, 0xb0, 0x82, 0xcb, 0xed, 0x75, 0xc7, 0x65}}}, +{{{0x80, 0xba, 0x0d, 0x09, 0x40, 0xa7, 0x39, 0xa6, 0x67, 0x34, 0x7e, 0x66, 0xbe, 0x56, 0xfb, 0x53, 0x78, 0xc4, 0x46, 0xe8, 0xed, 0x68, 0x6c, 0x7f, 0xce, 0xe8, 0x9f, 0xce, 0xa2, 0x64, 0x58, 0x53}} , + {{0xe8, 0xc1, 0xa9, 0xc2, 0x7b, 0x59, 0x21, 0x33, 0xe2, 0x43, 0x73, 0x2b, 0xac, 0x2d, 0xc1, 0x89, 0x3b, 0x15, 0xe2, 0xd5, 0xc0, 0x97, 0x8a, 0xfd, 0x6f, 0x36, 0x33, 0xb7, 0xb9, 0xc3, 0x88, 0x09}}}, +{{{0xd0, 0xb6, 0x56, 0x30, 0x5c, 0xae, 0xb3, 0x75, 0x44, 0xa4, 0x83, 0x51, 0x6e, 0x01, 0x65, 0xef, 0x45, 0x76, 0xe6, 0xf5, 0xa2, 0x0d, 0xd4, 0x16, 0x3b, 0x58, 0x2f, 0xf2, 0x2f, 0x36, 0x18, 0x3f}} , + {{0xfd, 0x2f, 0xe0, 0x9b, 0x1e, 0x8c, 0xc5, 0x18, 0xa9, 0xca, 0xd4, 0x2b, 0x35, 0xb6, 0x95, 0x0a, 0x9f, 0x7e, 0xfb, 0xc4, 0xef, 0x88, 0x7b, 0x23, 0x43, 0xec, 0x2f, 0x0d, 0x0f, 0x7a, 0xfc, 0x5c}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x8d, 0xd2, 0xda, 0xc7, 0x44, 0xd6, 0x7a, 0xdb, 0x26, 0x7d, 0x1d, 0xb8, 0xe1, 0xde, 0x9d, 0x7a, 0x7d, 0x17, 0x7e, 0x1c, 0x37, 0x04, 0x8d, 0x2d, 0x7c, 0x5e, 0x18, 0x38, 0x1e, 0xaf, 0xc7, 0x1b}} , + {{0x33, 0x48, 0x31, 0x00, 0x59, 0xf6, 0xf2, 0xca, 0x0f, 0x27, 0x1b, 0x63, 0x12, 0x7e, 0x02, 0x1d, 0x49, 0xc0, 0x5d, 0x79, 0x87, 0xef, 0x5e, 0x7a, 0x2f, 0x1f, 0x66, 0x55, 0xd8, 0x09, 0xd9, 0x61}}}, +{{{0x54, 0x83, 0x02, 0x18, 0x82, 0x93, 0x99, 0x07, 0xd0, 0xa7, 0xda, 0xd8, 0x75, 0x89, 0xfa, 0xf2, 0xd9, 0xa3, 0xb8, 0x6b, 0x5a, 0x35, 0x28, 0xd2, 0x6b, 0x59, 0xc2, 0xf8, 0x45, 0xe2, 0xbc, 0x06}} , + {{0x65, 0xc0, 0xa3, 0x88, 0x51, 0x95, 0xfc, 0x96, 0x94, 0x78, 0xe8, 0x0d, 0x8b, 0x41, 0xc9, 0xc2, 0x58, 0x48, 0x75, 0x10, 0x2f, 0xcd, 0x2a, 0xc9, 0xa0, 0x6d, 0x0f, 0xdd, 0x9c, 0x98, 0x26, 0x3d}}}, +{{{0x2f, 0x66, 0x29, 0x1b, 0x04, 0x89, 0xbd, 0x7e, 0xee, 0x6e, 0xdd, 0xb7, 0x0e, 0xef, 0xb0, 0x0c, 0xb4, 0xfc, 0x7f, 0xc2, 0xc9, 0x3a, 0x3c, 0x64, 0xef, 0x45, 0x44, 0xaf, 0x8a, 0x90, 0x65, 0x76}} , + {{0xa1, 0x4c, 0x70, 0x4b, 0x0e, 0xa0, 0x83, 0x70, 0x13, 0xa4, 0xaf, 0xb8, 0x38, 0x19, 0x22, 0x65, 0x09, 0xb4, 0x02, 0x4f, 0x06, 0xf8, 0x17, 0xce, 0x46, 0x45, 0xda, 0x50, 0x7c, 0x8a, 0xd1, 0x4e}}}, +{{{0xf7, 0xd4, 0x16, 0x6c, 0x4e, 0x95, 0x9d, 0x5d, 0x0f, 0x91, 0x2b, 0x52, 0xfe, 0x5c, 0x34, 0xe5, 0x30, 0xe6, 0xa4, 0x3b, 0xf3, 0xf3, 0x34, 0x08, 0xa9, 0x4a, 0xa0, 0xb5, 0x6e, 0xb3, 0x09, 0x0a}} , + {{0x26, 0xd9, 0x5e, 0xa3, 0x0f, 0xeb, 0xa2, 0xf3, 0x20, 0x3b, 0x37, 0xd4, 0xe4, 0x9e, 0xce, 0x06, 0x3d, 0x53, 0xed, 0xae, 0x2b, 0xeb, 0xb6, 0x24, 0x0a, 0x11, 0xa3, 0x0f, 0xd6, 0x7f, 0xa4, 0x3a}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xdb, 0x9f, 0x2c, 0xfc, 0xd6, 0xb2, 0x1e, 0x2e, 0x52, 0x7a, 0x06, 0x87, 0x2d, 0x86, 0x72, 0x2b, 0x6d, 0x90, 0x77, 0x46, 0x43, 0xb5, 0x7a, 0xf8, 0x60, 0x7d, 0x91, 0x60, 0x5b, 0x9d, 0x9e, 0x07}} , + {{0x97, 0x87, 0xc7, 0x04, 0x1c, 0x38, 0x01, 0x39, 0x58, 0xc7, 0x85, 0xa3, 0xfc, 0x64, 0x00, 0x64, 0x25, 0xa2, 0xbf, 0x50, 0x94, 0xca, 0x26, 0x31, 0x45, 0x0a, 0x24, 0xd2, 0x51, 0x29, 0x51, 0x16}}}, +{{{0x4d, 0x4a, 0xd7, 0x98, 0x71, 0x57, 0xac, 0x7d, 0x8b, 0x37, 0xbd, 0x63, 0xff, 0x87, 0xb1, 0x49, 0x95, 0x20, 0x7c, 0xcf, 0x7c, 0x59, 0xc4, 0x91, 0x9c, 0xef, 0xd0, 0xdb, 0x60, 0x09, 0x9d, 0x46}} , + {{0xcb, 0x78, 0x94, 0x90, 0xe4, 0x45, 0xb3, 0xf6, 0xd9, 0xf6, 0x57, 0x74, 0xd5, 0xf8, 0x83, 0x4f, 0x39, 0xc9, 0xbd, 0x88, 0xc2, 0x57, 0x21, 0x1f, 0x24, 0x32, 0x68, 0xf8, 0xc7, 0x21, 0x5f, 0x0b}}}, +{{{0x2a, 0x36, 0x68, 0xfc, 0x5f, 0xb6, 0x4f, 0xa5, 0xe3, 0x9d, 0x24, 0x2f, 0xc0, 0x93, 0x61, 0xcf, 0xf8, 0x0a, 0xed, 0xe1, 0xdb, 0x27, 0xec, 0x0e, 0x14, 0x32, 0x5f, 0x8e, 0xa1, 0x62, 0x41, 0x16}} , + {{0x95, 0x21, 0x01, 0xce, 0x95, 0x5b, 0x0e, 0x57, 0xc7, 0xb9, 0x62, 0xb5, 0x28, 0xca, 0x11, 0xec, 0xb4, 0x46, 0x06, 0x73, 0x26, 0xff, 0xfb, 0x66, 0x7d, 0xee, 0x5f, 0xb2, 0x56, 0xfd, 0x2a, 0x08}}}, +{{{0x92, 0x67, 0x77, 0x56, 0xa1, 0xff, 0xc4, 0xc5, 0x95, 0xf0, 0xe3, 0x3a, 0x0a, 0xca, 0x94, 0x4d, 0x9e, 0x7e, 0x3d, 0xb9, 0x6e, 0xb6, 0xb0, 0xce, 0xa4, 0x30, 0x89, 0x99, 0xe9, 0xad, 0x11, 0x59}} , + {{0xf6, 0x48, 0x95, 0xa1, 0x6f, 0x5f, 0xb7, 0xa5, 0xbb, 0x30, 0x00, 0x1c, 0xd2, 0x8a, 0xd6, 0x25, 0x26, 0x1b, 0xb2, 0x0d, 0x37, 0x6a, 0x05, 0xf4, 0x9d, 0x3e, 0x17, 0x2a, 0x43, 0xd2, 0x3a, 0x06}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x32, 0x99, 0x93, 0xd1, 0x9a, 0x72, 0xf3, 0xa9, 0x16, 0xbd, 0xb4, 0x4c, 0xdd, 0xf9, 0xd4, 0xb2, 0x64, 0x9a, 0xd3, 0x05, 0xe4, 0xa3, 0x73, 0x1c, 0xcb, 0x7e, 0x57, 0x67, 0xff, 0x04, 0xb3, 0x10}} , + {{0xb9, 0x4b, 0xa4, 0xad, 0xd0, 0x6d, 0x61, 0x23, 0xb4, 0xaf, 0x34, 0xa9, 0xaa, 0x65, 0xec, 0xd9, 0x69, 0xe3, 0x85, 0xcd, 0xcc, 0xe7, 0xb0, 0x9b, 0x41, 0xc1, 0x1c, 0xf9, 0xa0, 0xfa, 0xb7, 0x13}}}, +{{{0x04, 0xfd, 0x88, 0x3c, 0x0c, 0xd0, 0x09, 0x52, 0x51, 0x4f, 0x06, 0x19, 0xcc, 0xc3, 0xbb, 0xde, 0x80, 0xc5, 0x33, 0xbc, 0xf9, 0xf3, 0x17, 0x36, 0xdd, 0xc6, 0xde, 0xe8, 0x9b, 0x5d, 0x79, 0x1b}} , + {{0x65, 0x0a, 0xbe, 0x51, 0x57, 0xad, 0x50, 0x79, 0x08, 0x71, 0x9b, 0x07, 0x95, 0x8f, 0xfb, 0xae, 0x4b, 0x38, 0xba, 0xcf, 0x53, 0x2a, 0x86, 0x1e, 0xc0, 0x50, 0x5c, 0x67, 0x1b, 0xf6, 0x87, 0x6c}}}, +{{{0x4f, 0x00, 0xb2, 0x66, 0x55, 0xed, 0x4a, 0xed, 0x8d, 0xe1, 0x66, 0x18, 0xb2, 0x14, 0x74, 0x8d, 0xfd, 0x1a, 0x36, 0x0f, 0x26, 0x5c, 0x8b, 0x89, 0xf3, 0xab, 0xf2, 0xf3, 0x24, 0x67, 0xfd, 0x70}} , + {{0xfd, 0x4e, 0x2a, 0xc1, 0x3a, 0xca, 0x8f, 0x00, 0xd8, 0xec, 0x74, 0x67, 0xef, 0x61, 0xe0, 0x28, 0xd0, 0x96, 0xf4, 0x48, 0xde, 0x81, 0xe3, 0xef, 0xdc, 0xaa, 0x7d, 0xf3, 0xb6, 0x55, 0xa6, 0x65}}}, +{{{0xeb, 0xcb, 0xc5, 0x70, 0x91, 0x31, 0x10, 0x93, 0x0d, 0xc8, 0xd0, 0xef, 0x62, 0xe8, 0x6f, 0x82, 0xe3, 0x69, 0x3d, 0x91, 0x7f, 0x31, 0xe1, 0x26, 0x35, 0x3c, 0x4a, 0x2f, 0xab, 0xc4, 0x9a, 0x5e}} , + {{0xab, 0x1b, 0xb5, 0xe5, 0x2b, 0xc3, 0x0e, 0x29, 0xb0, 0xd0, 0x73, 0xe6, 0x4f, 0x64, 0xf2, 0xbc, 0xe4, 0xe4, 0xe1, 0x9a, 0x52, 0x33, 0x2f, 0xbd, 0xcc, 0x03, 0xee, 0x8a, 0xfa, 0x00, 0x5f, 0x50}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xf6, 0xdb, 0x0d, 0x22, 0x3d, 0xb5, 0x14, 0x75, 0x31, 0xf0, 0x81, 0xe2, 0xb9, 0x37, 0xa2, 0xa9, 0x84, 0x11, 0x9a, 0x07, 0xb5, 0x53, 0x89, 0x78, 0xa9, 0x30, 0x27, 0xa1, 0xf1, 0x4e, 0x5c, 0x2e}} , + {{0x8b, 0x00, 0x54, 0xfb, 0x4d, 0xdc, 0xcb, 0x17, 0x35, 0x40, 0xff, 0xb7, 0x8c, 0xfe, 0x4a, 0xe4, 0x4e, 0x99, 0x4e, 0xa8, 0x74, 0x54, 0x5d, 0x5c, 0x96, 0xa3, 0x12, 0x55, 0x36, 0x31, 0x17, 0x5c}}}, +{{{0xce, 0x24, 0xef, 0x7b, 0x86, 0xf2, 0x0f, 0x77, 0xe8, 0x5c, 0x7d, 0x87, 0x38, 0x2d, 0xef, 0xaf, 0xf2, 0x8c, 0x72, 0x2e, 0xeb, 0xb6, 0x55, 0x4b, 0x6e, 0xf1, 0x4e, 0x8a, 0x0e, 0x9a, 0x6c, 0x4c}} , + {{0x25, 0xea, 0x86, 0xc2, 0xd1, 0x4f, 0xb7, 0x3e, 0xa8, 0x5c, 0x8d, 0x66, 0x81, 0x25, 0xed, 0xc5, 0x4c, 0x05, 0xb9, 0xd8, 0xd6, 0x70, 0xbe, 0x73, 0x82, 0xe8, 0xa1, 0xe5, 0x1e, 0x71, 0xd5, 0x26}}}, +{{{0x4e, 0x6d, 0xc3, 0xa7, 0x4f, 0x22, 0x45, 0x26, 0xa2, 0x7e, 0x16, 0xf7, 0xf7, 0x63, 0xdc, 0x86, 0x01, 0x2a, 0x71, 0x38, 0x5c, 0x33, 0xc3, 0xce, 0x30, 0xff, 0xf9, 0x2c, 0x91, 0x71, 0x8a, 0x72}} , + {{0x8c, 0x44, 0x09, 0x28, 0xd5, 0x23, 0xc9, 0x8f, 0xf3, 0x84, 0x45, 0xc6, 0x9a, 0x5e, 0xff, 0xd2, 0xc7, 0x57, 0x93, 0xa3, 0xc1, 0x69, 0xdd, 0x62, 0x0f, 0xda, 0x5c, 0x30, 0x59, 0x5d, 0xe9, 0x4c}}}, +{{{0x92, 0x7e, 0x50, 0x27, 0x72, 0xd7, 0x0c, 0xd6, 0x69, 0x96, 0x81, 0x35, 0x84, 0x94, 0x35, 0x8b, 0x6c, 0xaa, 0x62, 0x86, 0x6e, 0x1c, 0x15, 0xf3, 0x6c, 0xb3, 0xff, 0x65, 0x1b, 0xa2, 0x9b, 0x59}} , + {{0xe2, 0xa9, 0x65, 0x88, 0xc4, 0x50, 0xfa, 0xbb, 0x3b, 0x6e, 0x5f, 0x44, 0x01, 0xca, 0x97, 0xd4, 0xdd, 0xf6, 0xcd, 0x3f, 0x3f, 0xe5, 0x97, 0x67, 0x2b, 0x8c, 0x66, 0x0f, 0x35, 0x9b, 0xf5, 0x07}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xf1, 0x59, 0x27, 0xd8, 0xdb, 0x5a, 0x11, 0x5e, 0x82, 0xf3, 0x38, 0xff, 0x1c, 0xed, 0xfe, 0x3f, 0x64, 0x54, 0x3f, 0x7f, 0xd1, 0x81, 0xed, 0xef, 0x65, 0xc5, 0xcb, 0xfd, 0xe1, 0x80, 0xcd, 0x11}} , + {{0xe0, 0xdb, 0x22, 0x28, 0xe6, 0xff, 0x61, 0x9d, 0x41, 0x14, 0x2d, 0x3b, 0x26, 0x22, 0xdf, 0xf1, 0x34, 0x81, 0xe9, 0x45, 0xee, 0x0f, 0x98, 0x8b, 0xa6, 0x3f, 0xef, 0xf7, 0x43, 0x19, 0xf1, 0x43}}}, +{{{0xee, 0xf3, 0x00, 0xa1, 0x50, 0xde, 0xc0, 0xb6, 0x01, 0xe3, 0x8c, 0x3c, 0x4d, 0x31, 0xd2, 0xb0, 0x58, 0xcd, 0xed, 0x10, 0x4a, 0x7a, 0xef, 0x80, 0xa9, 0x19, 0x32, 0xf3, 0xd8, 0x33, 0x8c, 0x06}} , + {{0xcb, 0x7d, 0x4f, 0xff, 0x30, 0xd8, 0x12, 0x3b, 0x39, 0x1c, 0x06, 0xf9, 0x4c, 0x34, 0x35, 0x71, 0xb5, 0x16, 0x94, 0x67, 0xdf, 0xee, 0x11, 0xde, 0xa4, 0x1d, 0x88, 0x93, 0x35, 0xa9, 0x32, 0x10}}}, +{{{0xe9, 0xc3, 0xbc, 0x7b, 0x5c, 0xfc, 0xb2, 0xf9, 0xc9, 0x2f, 0xe5, 0xba, 0x3a, 0x0b, 0xab, 0x64, 0x38, 0x6f, 0x5b, 0x4b, 0x93, 0xda, 0x64, 0xec, 0x4d, 0x3d, 0xa0, 0xf5, 0xbb, 0xba, 0x47, 0x48}} , + {{0x60, 0xbc, 0x45, 0x1f, 0x23, 0xa2, 0x3b, 0x70, 0x76, 0xe6, 0x97, 0x99, 0x4f, 0x77, 0x54, 0x67, 0x30, 0x9a, 0xe7, 0x66, 0xd6, 0xcd, 0x2e, 0x51, 0x24, 0x2c, 0x42, 0x4a, 0x11, 0xfe, 0x6f, 0x7e}}}, +{{{0x87, 0xc0, 0xb1, 0xf0, 0xa3, 0x6f, 0x0c, 0x93, 0xa9, 0x0a, 0x72, 0xef, 0x5c, 0xbe, 0x65, 0x35, 0xa7, 0x6a, 0x4e, 0x2c, 0xbf, 0x21, 0x23, 0xe8, 0x2f, 0x97, 0xc7, 0x3e, 0xc8, 0x17, 0xac, 0x1e}} , + {{0x7b, 0xef, 0x21, 0xe5, 0x40, 0xcc, 0x1e, 0xdc, 0xd6, 0xbd, 0x97, 0x7a, 0x7c, 0x75, 0x86, 0x7a, 0x25, 0x5a, 0x6e, 0x7c, 0xe5, 0x51, 0x3c, 0x1b, 0x5b, 0x82, 0x9a, 0x07, 0x60, 0xa1, 0x19, 0x04}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x96, 0x88, 0xa6, 0xab, 0x8f, 0xe3, 0x3a, 0x49, 0xf8, 0xfe, 0x34, 0xe7, 0x6a, 0xb2, 0xfe, 0x40, 0x26, 0x74, 0x57, 0x4c, 0xf6, 0xd4, 0x99, 0xce, 0x5d, 0x7b, 0x2f, 0x67, 0xd6, 0x5a, 0xe4, 0x4e}} , + {{0x5c, 0x82, 0xb3, 0xbd, 0x55, 0x25, 0xf6, 0x6a, 0x93, 0xa4, 0x02, 0xc6, 0x7d, 0x5c, 0xb1, 0x2b, 0x5b, 0xff, 0xfb, 0x56, 0xf8, 0x01, 0x41, 0x90, 0xc6, 0xb6, 0xac, 0x4f, 0xfe, 0xa7, 0x41, 0x70}}}, +{{{0xdb, 0xfa, 0x9b, 0x2c, 0xd4, 0x23, 0x67, 0x2c, 0x8a, 0x63, 0x6c, 0x07, 0x26, 0x48, 0x4f, 0xc2, 0x03, 0xd2, 0x53, 0x20, 0x28, 0xed, 0x65, 0x71, 0x47, 0xa9, 0x16, 0x16, 0x12, 0xbc, 0x28, 0x33}} , + {{0x39, 0xc0, 0xfa, 0xfa, 0xcd, 0x33, 0x43, 0xc7, 0x97, 0x76, 0x9b, 0x93, 0x91, 0x72, 0xeb, 0xc5, 0x18, 0x67, 0x4c, 0x11, 0xf0, 0xf4, 0xe5, 0x73, 0xb2, 0x5c, 0x1b, 0xc2, 0x26, 0x3f, 0xbf, 0x2b}}}, +{{{0x86, 0xe6, 0x8c, 0x1d, 0xdf, 0xca, 0xfc, 0xd5, 0xf8, 0x3a, 0xc3, 0x44, 0x72, 0xe6, 0x78, 0x9d, 0x2b, 0x97, 0xf8, 0x28, 0x45, 0xb4, 0x20, 0xc9, 0x2a, 0x8c, 0x67, 0xaa, 0x11, 0xc5, 0x5b, 0x2f}} , + {{0x17, 0x0f, 0x86, 0x52, 0xd7, 0x9d, 0xc3, 0x44, 0x51, 0x76, 0x32, 0x65, 0xb4, 0x37, 0x81, 0x99, 0x46, 0x37, 0x62, 0xed, 0xcf, 0x64, 0x9d, 0x72, 0x40, 0x7a, 0x4c, 0x0b, 0x76, 0x2a, 0xfb, 0x56}}}, +{{{0x33, 0xa7, 0x90, 0x7c, 0xc3, 0x6f, 0x17, 0xa5, 0xa0, 0x67, 0x72, 0x17, 0xea, 0x7e, 0x63, 0x14, 0x83, 0xde, 0xc1, 0x71, 0x2d, 0x41, 0x32, 0x7a, 0xf3, 0xd1, 0x2b, 0xd8, 0x2a, 0xa6, 0x46, 0x36}} , + {{0xac, 0xcc, 0x6b, 0x7c, 0xf9, 0xb8, 0x8b, 0x08, 0x5c, 0xd0, 0x7d, 0x8f, 0x73, 0xea, 0x20, 0xda, 0x86, 0xca, 0x00, 0xc7, 0xad, 0x73, 0x4d, 0xe9, 0xe8, 0xa9, 0xda, 0x1f, 0x03, 0x06, 0xdd, 0x24}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x9c, 0xb2, 0x61, 0x0a, 0x98, 0x2a, 0xa5, 0xd7, 0xee, 0xa9, 0xac, 0x65, 0xcb, 0x0a, 0x1e, 0xe2, 0xbe, 0xdc, 0x85, 0x59, 0x0f, 0x9c, 0xa6, 0x57, 0x34, 0xa5, 0x87, 0xeb, 0x7b, 0x1e, 0x0c, 0x3c}} , + {{0x2f, 0xbd, 0x84, 0x63, 0x0d, 0xb5, 0xa0, 0xf0, 0x4b, 0x9e, 0x93, 0xc6, 0x34, 0x9a, 0x34, 0xff, 0x73, 0x19, 0x2f, 0x6e, 0x54, 0x45, 0x2c, 0x92, 0x31, 0x76, 0x34, 0xf1, 0xb2, 0x26, 0xe8, 0x74}}}, +{{{0x0a, 0x67, 0x90, 0x6d, 0x0c, 0x4c, 0xcc, 0xc0, 0xe6, 0xbd, 0xa7, 0x5e, 0x55, 0x8c, 0xcd, 0x58, 0x9b, 0x11, 0xa2, 0xbb, 0x4b, 0xb1, 0x43, 0x04, 0x3c, 0x55, 0xed, 0x23, 0xfe, 0xcd, 0xb1, 0x53}} , + {{0x05, 0xfb, 0x75, 0xf5, 0x01, 0xaf, 0x38, 0x72, 0x58, 0xfc, 0x04, 0x29, 0x34, 0x7a, 0x67, 0xa2, 0x08, 0x50, 0x6e, 0xd0, 0x2b, 0x73, 0xd5, 0xb8, 0xe4, 0x30, 0x96, 0xad, 0x45, 0xdf, 0xa6, 0x5c}}}, +{{{0x0d, 0x88, 0x1a, 0x90, 0x7e, 0xdc, 0xd8, 0xfe, 0xc1, 0x2f, 0x5d, 0x67, 0xee, 0x67, 0x2f, 0xed, 0x6f, 0x55, 0x43, 0x5f, 0x87, 0x14, 0x35, 0x42, 0xd3, 0x75, 0xae, 0xd5, 0xd3, 0x85, 0x1a, 0x76}} , + {{0x87, 0xc8, 0xa0, 0x6e, 0xe1, 0xb0, 0xad, 0x6a, 0x4a, 0x34, 0x71, 0xed, 0x7c, 0xd6, 0x44, 0x03, 0x65, 0x4a, 0x5c, 0x5c, 0x04, 0xf5, 0x24, 0x3f, 0xb0, 0x16, 0x5e, 0x8c, 0xb2, 0xd2, 0xc5, 0x20}}}, +{{{0x98, 0x83, 0xc2, 0x37, 0xa0, 0x41, 0xa8, 0x48, 0x5c, 0x5f, 0xbf, 0xc8, 0xfa, 0x24, 0xe0, 0x59, 0x2c, 0xbd, 0xf6, 0x81, 0x7e, 0x88, 0xe6, 0xca, 0x04, 0xd8, 0x5d, 0x60, 0xbb, 0x74, 0xa7, 0x0b}} , + {{0x21, 0x13, 0x91, 0xbf, 0x77, 0x7a, 0x33, 0xbc, 0xe9, 0x07, 0x39, 0x0a, 0xdd, 0x7d, 0x06, 0x10, 0x9a, 0xee, 0x47, 0x73, 0x1b, 0x15, 0x5a, 0xfb, 0xcd, 0x4d, 0xd0, 0xd2, 0x3a, 0x01, 0xba, 0x54}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x48, 0xd5, 0x39, 0x4a, 0x0b, 0x20, 0x6a, 0x43, 0xa0, 0x07, 0x82, 0x5e, 0x49, 0x7c, 0xc9, 0x47, 0xf1, 0x7c, 0x37, 0xb9, 0x23, 0xef, 0x6b, 0x46, 0x45, 0x8c, 0x45, 0x76, 0xdf, 0x14, 0x6b, 0x6e}} , + {{0x42, 0xc9, 0xca, 0x29, 0x4c, 0x76, 0x37, 0xda, 0x8a, 0x2d, 0x7c, 0x3a, 0x58, 0xf2, 0x03, 0xb4, 0xb5, 0xb9, 0x1a, 0x13, 0x2d, 0xde, 0x5f, 0x6b, 0x9d, 0xba, 0x52, 0xc9, 0x5d, 0xb3, 0xf3, 0x30}}}, +{{{0x4c, 0x6f, 0xfe, 0x6b, 0x0c, 0x62, 0xd7, 0x48, 0x71, 0xef, 0xb1, 0x85, 0x79, 0xc0, 0xed, 0x24, 0xb1, 0x08, 0x93, 0x76, 0x8e, 0xf7, 0x38, 0x8e, 0xeb, 0xfe, 0x80, 0x40, 0xaf, 0x90, 0x64, 0x49}} , + {{0x4a, 0x88, 0xda, 0xc1, 0x98, 0x44, 0x3c, 0x53, 0x4e, 0xdb, 0x4b, 0xb9, 0x12, 0x5f, 0xcd, 0x08, 0x04, 0xef, 0x75, 0xe7, 0xb1, 0x3a, 0xe5, 0x07, 0xfa, 0xca, 0x65, 0x7b, 0x72, 0x10, 0x64, 0x7f}}}, +{{{0x3d, 0x81, 0xf0, 0xeb, 0x16, 0xfd, 0x58, 0x33, 0x8d, 0x7c, 0x1a, 0xfb, 0x20, 0x2c, 0x8a, 0xee, 0x90, 0xbb, 0x33, 0x6d, 0x45, 0xe9, 0x8e, 0x99, 0x85, 0xe1, 0x08, 0x1f, 0xc5, 0xf1, 0xb5, 0x46}} , + {{0xe4, 0xe7, 0x43, 0x4b, 0xa0, 0x3f, 0x2b, 0x06, 0xba, 0x17, 0xae, 0x3d, 0xe6, 0xce, 0xbd, 0xb8, 0xed, 0x74, 0x11, 0x35, 0xec, 0x96, 0xfe, 0x31, 0xe3, 0x0e, 0x7a, 0x4e, 0xc9, 0x1d, 0xcb, 0x20}}}, +{{{0xe0, 0x67, 0xe9, 0x7b, 0xdb, 0x96, 0x5c, 0xb0, 0x32, 0xd0, 0x59, 0x31, 0x90, 0xdc, 0x92, 0x97, 0xac, 0x09, 0x38, 0x31, 0x0f, 0x7e, 0xd6, 0x5d, 0xd0, 0x06, 0xb6, 0x1f, 0xea, 0xf0, 0x5b, 0x07}} , + {{0x81, 0x9f, 0xc7, 0xde, 0x6b, 0x41, 0x22, 0x35, 0x14, 0x67, 0x77, 0x3e, 0x90, 0x81, 0xb0, 0xd9, 0x85, 0x4c, 0xca, 0x9b, 0x3f, 0x04, 0x59, 0xd6, 0xaa, 0x17, 0xc3, 0x88, 0x34, 0x37, 0xba, 0x43}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x4c, 0xb6, 0x69, 0xc8, 0x81, 0x95, 0x94, 0x33, 0x92, 0x34, 0xe9, 0x3c, 0x84, 0x0d, 0x3d, 0x5a, 0x37, 0x9c, 0x22, 0xa0, 0xaa, 0x65, 0xce, 0xb4, 0xc2, 0x2d, 0x66, 0x67, 0x02, 0xff, 0x74, 0x10}} , + {{0x22, 0xb0, 0xd5, 0xe6, 0xc7, 0xef, 0xb1, 0xa7, 0x13, 0xda, 0x60, 0xb4, 0x80, 0xc1, 0x42, 0x7d, 0x10, 0x70, 0x97, 0x04, 0x4d, 0xda, 0x23, 0x89, 0xc2, 0x0e, 0x68, 0xcb, 0xde, 0xe0, 0x9b, 0x29}}}, +{{{0x33, 0xfe, 0x42, 0x2a, 0x36, 0x2b, 0x2e, 0x36, 0x64, 0x5c, 0x8b, 0xcc, 0x81, 0x6a, 0x15, 0x08, 0xa1, 0x27, 0xe8, 0x57, 0xe5, 0x78, 0x8e, 0xf2, 0x58, 0x19, 0x12, 0x42, 0xae, 0xc4, 0x63, 0x3e}} , + {{0x78, 0x96, 0x9c, 0xa7, 0xca, 0x80, 0xae, 0x02, 0x85, 0xb1, 0x7c, 0x04, 0x5c, 0xc1, 0x5b, 0x26, 0xc1, 0xba, 0xed, 0xa5, 0x59, 0x70, 0x85, 0x8c, 0x8c, 0xe8, 0x87, 0xac, 0x6a, 0x28, 0x99, 0x35}}}, +{{{0x9f, 0x04, 0x08, 0x28, 0xbe, 0x87, 0xda, 0x80, 0x28, 0x38, 0xde, 0x9f, 0xcd, 0xe4, 0xe3, 0x62, 0xfb, 0x2e, 0x46, 0x8d, 0x01, 0xb3, 0x06, 0x51, 0xd4, 0x19, 0x3b, 0x11, 0xfa, 0xe2, 0xad, 0x1e}} , + {{0xa0, 0x20, 0x99, 0x69, 0x0a, 0xae, 0xa3, 0x70, 0x4e, 0x64, 0x80, 0xb7, 0x85, 0x9c, 0x87, 0x54, 0x43, 0x43, 0x55, 0x80, 0x6d, 0x8d, 0x7c, 0xa9, 0x64, 0xca, 0x6c, 0x2e, 0x21, 0xd8, 0xc8, 0x6c}}}, +{{{0x91, 0x4a, 0x07, 0xad, 0x08, 0x75, 0xc1, 0x4f, 0xa4, 0xb2, 0xc3, 0x6f, 0x46, 0x3e, 0xb1, 0xce, 0x52, 0xab, 0x67, 0x09, 0x54, 0x48, 0x6b, 0x6c, 0xd7, 0x1d, 0x71, 0x76, 0xcb, 0xff, 0xdd, 0x31}} , + {{0x36, 0x88, 0xfa, 0xfd, 0xf0, 0x36, 0x6f, 0x07, 0x74, 0x88, 0x50, 0xd0, 0x95, 0x38, 0x4a, 0x48, 0x2e, 0x07, 0x64, 0x97, 0x11, 0x76, 0x01, 0x1a, 0x27, 0x4d, 0x8e, 0x25, 0x9a, 0x9b, 0x1c, 0x22}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xbe, 0x57, 0xbd, 0x0e, 0x0f, 0xac, 0x5e, 0x76, 0xa3, 0x71, 0xad, 0x2b, 0x10, 0x45, 0x02, 0xec, 0x59, 0xd5, 0x5d, 0xa9, 0x44, 0xcc, 0x25, 0x4c, 0xb3, 0x3c, 0x5b, 0x69, 0x07, 0x55, 0x26, 0x6b}} , + {{0x30, 0x6b, 0xd4, 0xa7, 0x51, 0x29, 0xe3, 0xf9, 0x7a, 0x75, 0x2a, 0x82, 0x2f, 0xd6, 0x1d, 0x99, 0x2b, 0x80, 0xd5, 0x67, 0x1e, 0x15, 0x9d, 0xca, 0xfd, 0xeb, 0xac, 0x97, 0x35, 0x09, 0x7f, 0x3f}}}, +{{{0x35, 0x0d, 0x34, 0x0a, 0xb8, 0x67, 0x56, 0x29, 0x20, 0xf3, 0x19, 0x5f, 0xe2, 0x83, 0x42, 0x73, 0x53, 0xa8, 0xc5, 0x02, 0x19, 0x33, 0xb4, 0x64, 0xbd, 0xc3, 0x87, 0x8c, 0xd7, 0x76, 0xed, 0x25}} , + {{0x47, 0x39, 0x37, 0x76, 0x0d, 0x1d, 0x0c, 0xf5, 0x5a, 0x6d, 0x43, 0x88, 0x99, 0x15, 0xb4, 0x52, 0x0f, 0x2a, 0xb3, 0xb0, 0x3f, 0xa6, 0xb3, 0x26, 0xb3, 0xc7, 0x45, 0xf5, 0x92, 0x5f, 0x9b, 0x17}}}, +{{{0x9d, 0x23, 0xbd, 0x15, 0xfe, 0x52, 0x52, 0x15, 0x26, 0x79, 0x86, 0xba, 0x06, 0x56, 0x66, 0xbb, 0x8c, 0x2e, 0x10, 0x11, 0xd5, 0x4a, 0x18, 0x52, 0xda, 0x84, 0x44, 0xf0, 0x3e, 0xe9, 0x8c, 0x35}} , + {{0xad, 0xa0, 0x41, 0xec, 0xc8, 0x4d, 0xb9, 0xd2, 0x6e, 0x96, 0x4e, 0x5b, 0xc5, 0xc2, 0xa0, 0x1b, 0xcf, 0x0c, 0xbf, 0x17, 0x66, 0x57, 0xc1, 0x17, 0x90, 0x45, 0x71, 0xc2, 0xe1, 0x24, 0xeb, 0x27}}}, +{{{0x2c, 0xb9, 0x42, 0xa4, 0xaf, 0x3b, 0x42, 0x0e, 0xc2, 0x0f, 0xf2, 0xea, 0x83, 0xaf, 0x9a, 0x13, 0x17, 0xb0, 0xbd, 0x89, 0x17, 0xe3, 0x72, 0xcb, 0x0e, 0x76, 0x7e, 0x41, 0x63, 0x04, 0x88, 0x71}} , + {{0x75, 0x78, 0x38, 0x86, 0x57, 0xdd, 0x9f, 0xee, 0x54, 0x70, 0x65, 0xbf, 0xf1, 0x2c, 0xe0, 0x39, 0x0d, 0xe3, 0x89, 0xfd, 0x8e, 0x93, 0x4f, 0x43, 0xdc, 0xd5, 0x5b, 0xde, 0xf9, 0x98, 0xe5, 0x7b}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xe7, 0x3b, 0x65, 0x11, 0xdf, 0xb2, 0xf2, 0x63, 0x94, 0x12, 0x6f, 0x5c, 0x9e, 0x77, 0xc1, 0xb6, 0xd8, 0xab, 0x58, 0x7a, 0x1d, 0x95, 0x73, 0xdd, 0xe7, 0xe3, 0x6f, 0xf2, 0x03, 0x1d, 0xdb, 0x76}} , + {{0xae, 0x06, 0x4e, 0x2c, 0x52, 0x1b, 0xbc, 0x5a, 0x5a, 0xa5, 0xbe, 0x27, 0xbd, 0xeb, 0xe1, 0x14, 0x17, 0x68, 0x26, 0x07, 0x03, 0xd1, 0x18, 0x0b, 0xdf, 0xf1, 0x06, 0x5c, 0xa6, 0x1b, 0xb9, 0x24}}}, +{{{0xc5, 0x66, 0x80, 0x13, 0x0e, 0x48, 0x8c, 0x87, 0x31, 0x84, 0xb4, 0x60, 0xed, 0xc5, 0xec, 0xb6, 0xc5, 0x05, 0x33, 0x5f, 0x2f, 0x7d, 0x40, 0xb6, 0x32, 0x1d, 0x38, 0x74, 0x1b, 0xf1, 0x09, 0x3d}} , + {{0xd4, 0x69, 0x82, 0xbc, 0x8d, 0xf8, 0x34, 0x36, 0x75, 0x55, 0x18, 0x55, 0x58, 0x3c, 0x79, 0xaf, 0x26, 0x80, 0xab, 0x9b, 0x95, 0x00, 0xf1, 0xcb, 0xda, 0xc1, 0x9f, 0xf6, 0x2f, 0xa2, 0xf4, 0x45}}}, +{{{0x17, 0xbe, 0xeb, 0x85, 0xed, 0x9e, 0xcd, 0x56, 0xf5, 0x17, 0x45, 0x42, 0xb4, 0x1f, 0x44, 0x4c, 0x05, 0x74, 0x15, 0x47, 0x00, 0xc6, 0x6a, 0x3d, 0x24, 0x09, 0x0d, 0x58, 0xb1, 0x42, 0xd7, 0x04}} , + {{0x8d, 0xbd, 0xa3, 0xc4, 0x06, 0x9b, 0x1f, 0x90, 0x58, 0x60, 0x74, 0xb2, 0x00, 0x3b, 0x3c, 0xd2, 0xda, 0x82, 0xbb, 0x10, 0x90, 0x69, 0x92, 0xa9, 0xb4, 0x30, 0x81, 0xe3, 0x7c, 0xa8, 0x89, 0x45}}}, +{{{0x3f, 0xdc, 0x05, 0xcb, 0x41, 0x3c, 0xc8, 0x23, 0x04, 0x2c, 0x38, 0x99, 0xe3, 0x68, 0x55, 0xf9, 0xd3, 0x32, 0xc7, 0xbf, 0xfa, 0xd4, 0x1b, 0x5d, 0xde, 0xdc, 0x10, 0x42, 0xc0, 0x42, 0xd9, 0x75}} , + {{0x2d, 0xab, 0x35, 0x4e, 0x87, 0xc4, 0x65, 0x97, 0x67, 0x24, 0xa4, 0x47, 0xad, 0x3f, 0x8e, 0xf3, 0xcb, 0x31, 0x17, 0x77, 0xc5, 0xe2, 0xd7, 0x8f, 0x3c, 0xc1, 0xcd, 0x56, 0x48, 0xc1, 0x6c, 0x69}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x14, 0xae, 0x5f, 0x88, 0x7b, 0xa5, 0x90, 0xdf, 0x10, 0xb2, 0x8b, 0x5e, 0x24, 0x17, 0xc3, 0xa3, 0xd4, 0x0f, 0x92, 0x61, 0x1a, 0x19, 0x5a, 0xad, 0x76, 0xbd, 0xd8, 0x1c, 0xdd, 0xe0, 0x12, 0x6d}} , + {{0x8e, 0xbd, 0x70, 0x8f, 0x02, 0xa3, 0x24, 0x4d, 0x5a, 0x67, 0xc4, 0xda, 0xf7, 0x20, 0x0f, 0x81, 0x5b, 0x7a, 0x05, 0x24, 0x67, 0x83, 0x0b, 0x2a, 0x80, 0xe7, 0xfd, 0x74, 0x4b, 0x9e, 0x5c, 0x0d}}}, +{{{0x94, 0xd5, 0x5f, 0x1f, 0xa2, 0xfb, 0xeb, 0xe1, 0x07, 0x34, 0xf8, 0x20, 0xad, 0x81, 0x30, 0x06, 0x2d, 0xa1, 0x81, 0x95, 0x36, 0xcf, 0x11, 0x0b, 0xaf, 0xc1, 0x2b, 0x9a, 0x6c, 0x55, 0xc1, 0x16}} , + {{0x36, 0x4f, 0xf1, 0x5e, 0x74, 0x35, 0x13, 0x28, 0xd7, 0x11, 0xcf, 0xb8, 0xde, 0x93, 0xb3, 0x05, 0xb8, 0xb5, 0x73, 0xe9, 0xeb, 0xad, 0x19, 0x1e, 0x89, 0x0f, 0x8b, 0x15, 0xd5, 0x8c, 0xe3, 0x23}}}, +{{{0x33, 0x79, 0xe7, 0x18, 0xe6, 0x0f, 0x57, 0x93, 0x15, 0xa0, 0xa7, 0xaa, 0xc4, 0xbf, 0x4f, 0x30, 0x74, 0x95, 0x5e, 0x69, 0x4a, 0x5b, 0x45, 0xe4, 0x00, 0xeb, 0x23, 0x74, 0x4c, 0xdf, 0x6b, 0x45}} , + {{0x97, 0x29, 0x6c, 0xc4, 0x42, 0x0b, 0xdd, 0xc0, 0x29, 0x5c, 0x9b, 0x34, 0x97, 0xd0, 0xc7, 0x79, 0x80, 0x63, 0x74, 0xe4, 0x8e, 0x37, 0xb0, 0x2b, 0x7c, 0xe8, 0x68, 0x6c, 0xc3, 0x82, 0x97, 0x57}}}, +{{{0x22, 0xbe, 0x83, 0xb6, 0x4b, 0x80, 0x6b, 0x43, 0x24, 0x5e, 0xef, 0x99, 0x9b, 0xa8, 0xfc, 0x25, 0x8d, 0x3b, 0x03, 0x94, 0x2b, 0x3e, 0xe7, 0x95, 0x76, 0x9b, 0xcc, 0x15, 0xdb, 0x32, 0xe6, 0x66}} , + {{0x84, 0xf0, 0x4a, 0x13, 0xa6, 0xd6, 0xfa, 0x93, 0x46, 0x07, 0xf6, 0x7e, 0x5c, 0x6d, 0x5e, 0xf6, 0xa6, 0xe7, 0x48, 0xf0, 0x06, 0xea, 0xff, 0x90, 0xc1, 0xcc, 0x4c, 0x19, 0x9c, 0x3c, 0x4e, 0x53}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x2a, 0x50, 0xe3, 0x07, 0x15, 0x59, 0xf2, 0x8b, 0x81, 0xf2, 0xf3, 0xd3, 0x6c, 0x99, 0x8c, 0x70, 0x67, 0xec, 0xcc, 0xee, 0x9e, 0x59, 0x45, 0x59, 0x7d, 0x47, 0x75, 0x69, 0xf5, 0x24, 0x93, 0x5d}} , + {{0x6a, 0x4f, 0x1b, 0xbe, 0x6b, 0x30, 0xcf, 0x75, 0x46, 0xe3, 0x7b, 0x9d, 0xfc, 0xcd, 0xd8, 0x5c, 0x1f, 0xb4, 0xc8, 0xe2, 0x24, 0xec, 0x1a, 0x28, 0x05, 0x32, 0x57, 0xfd, 0x3c, 0x5a, 0x98, 0x10}}}, +{{{0xa3, 0xdb, 0xf7, 0x30, 0xd8, 0xc2, 0x9a, 0xe1, 0xd3, 0xce, 0x22, 0xe5, 0x80, 0x1e, 0xd9, 0xe4, 0x1f, 0xab, 0xc0, 0x71, 0x1a, 0x86, 0x0e, 0x27, 0x99, 0x5b, 0xfa, 0x76, 0x99, 0xb0, 0x08, 0x3c}} , + {{0x2a, 0x93, 0xd2, 0x85, 0x1b, 0x6a, 0x5d, 0xa6, 0xee, 0xd1, 0xd1, 0x33, 0xbd, 0x6a, 0x36, 0x73, 0x37, 0x3a, 0x44, 0xb4, 0xec, 0xa9, 0x7a, 0xde, 0x83, 0x40, 0xd7, 0xdf, 0x28, 0xba, 0xa2, 0x30}}}, +{{{0xd3, 0xb5, 0x6d, 0x05, 0x3f, 0x9f, 0xf3, 0x15, 0x8d, 0x7c, 0xca, 0xc9, 0xfc, 0x8a, 0x7c, 0x94, 0xb0, 0x63, 0x36, 0x9b, 0x78, 0xd1, 0x91, 0x1f, 0x93, 0xd8, 0x57, 0x43, 0xde, 0x76, 0xa3, 0x43}} , + {{0x9b, 0x35, 0xe2, 0xa9, 0x3d, 0x32, 0x1e, 0xbb, 0x16, 0x28, 0x70, 0xe9, 0x45, 0x2f, 0x8f, 0x70, 0x7f, 0x08, 0x7e, 0x53, 0xc4, 0x7a, 0xbf, 0xf7, 0xe1, 0xa4, 0x6a, 0xd8, 0xac, 0x64, 0x1b, 0x11}}}, +{{{0xb2, 0xeb, 0x47, 0x46, 0x18, 0x3e, 0x1f, 0x99, 0x0c, 0xcc, 0xf1, 0x2c, 0xe0, 0xe7, 0x8f, 0xe0, 0x01, 0x7e, 0x65, 0xb8, 0x0c, 0xd0, 0xfb, 0xc8, 0xb9, 0x90, 0x98, 0x33, 0x61, 0x3b, 0xd8, 0x27}} , + {{0xa0, 0xbe, 0x72, 0x3a, 0x50, 0x4b, 0x74, 0xab, 0x01, 0xc8, 0x93, 0xc5, 0xe4, 0xc7, 0x08, 0x6c, 0xb4, 0xca, 0xee, 0xeb, 0x8e, 0xd7, 0x4e, 0x26, 0xc6, 0x1d, 0xe2, 0x71, 0xaf, 0x89, 0xa0, 0x2a}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x98, 0x0b, 0xe4, 0xde, 0xdb, 0xa8, 0xfa, 0x82, 0x74, 0x06, 0x52, 0x6d, 0x08, 0x52, 0x8a, 0xff, 0x62, 0xc5, 0x6a, 0x44, 0x0f, 0x51, 0x8c, 0x1f, 0x6e, 0xb6, 0xc6, 0x2c, 0x81, 0xd3, 0x76, 0x46}} , + {{0xf4, 0x29, 0x74, 0x2e, 0x80, 0xa7, 0x1a, 0x8f, 0xf6, 0xbd, 0xd6, 0x8e, 0xbf, 0xc1, 0x95, 0x2a, 0xeb, 0xa0, 0x7f, 0x45, 0xa0, 0x50, 0x14, 0x05, 0xb1, 0x57, 0x4c, 0x74, 0xb7, 0xe2, 0x89, 0x7d}}}, +{{{0x07, 0xee, 0xa7, 0xad, 0xb7, 0x09, 0x0b, 0x49, 0x4e, 0xbf, 0xca, 0xe5, 0x21, 0xe6, 0xe6, 0xaf, 0xd5, 0x67, 0xf3, 0xce, 0x7e, 0x7c, 0x93, 0x7b, 0x5a, 0x10, 0x12, 0x0e, 0x6c, 0x06, 0x11, 0x75}} , + {{0xd5, 0xfc, 0x86, 0xa3, 0x3b, 0xa3, 0x3e, 0x0a, 0xfb, 0x0b, 0xf7, 0x36, 0xb1, 0x5b, 0xda, 0x70, 0xb7, 0x00, 0xa7, 0xda, 0x88, 0x8f, 0x84, 0xa8, 0xbc, 0x1c, 0x39, 0xb8, 0x65, 0xf3, 0x4d, 0x60}}}, +{{{0x96, 0x9d, 0x31, 0xf4, 0xa2, 0xbe, 0x81, 0xb9, 0xa5, 0x59, 0x9e, 0xba, 0x07, 0xbe, 0x74, 0x58, 0xd8, 0xeb, 0xc5, 0x9f, 0x3d, 0xd1, 0xf4, 0xae, 0xce, 0x53, 0xdf, 0x4f, 0xc7, 0x2a, 0x89, 0x4d}} , + {{0x29, 0xd8, 0xf2, 0xaa, 0xe9, 0x0e, 0xf7, 0x2e, 0x5f, 0x9d, 0x8a, 0x5b, 0x09, 0xed, 0xc9, 0x24, 0x22, 0xf4, 0x0f, 0x25, 0x8f, 0x1c, 0x84, 0x6e, 0x34, 0x14, 0x6c, 0xea, 0xb3, 0x86, 0x5d, 0x04}}}, +{{{0x07, 0x98, 0x61, 0xe8, 0x6a, 0xd2, 0x81, 0x49, 0x25, 0xd5, 0x5b, 0x18, 0xc7, 0x35, 0x52, 0x51, 0xa4, 0x46, 0xad, 0x18, 0x0d, 0xc9, 0x5f, 0x18, 0x91, 0x3b, 0xb4, 0xc0, 0x60, 0x59, 0x8d, 0x66}} , + {{0x03, 0x1b, 0x79, 0x53, 0x6e, 0x24, 0xae, 0x57, 0xd9, 0x58, 0x09, 0x85, 0x48, 0xa2, 0xd3, 0xb5, 0xe2, 0x4d, 0x11, 0x82, 0xe6, 0x86, 0x3c, 0xe9, 0xb1, 0x00, 0x19, 0xc2, 0x57, 0xf7, 0x66, 0x7a}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x0f, 0xe3, 0x89, 0x03, 0xd7, 0x22, 0x95, 0x9f, 0xca, 0xb4, 0x8d, 0x9e, 0x6d, 0x97, 0xff, 0x8d, 0x21, 0x59, 0x07, 0xef, 0x03, 0x2d, 0x5e, 0xf8, 0x44, 0x46, 0xe7, 0x85, 0x80, 0xc5, 0x89, 0x50}} , + {{0x8b, 0xd8, 0x53, 0x86, 0x24, 0x86, 0x29, 0x52, 0x01, 0xfa, 0x20, 0xc3, 0x4e, 0x95, 0xcb, 0xad, 0x7b, 0x34, 0x94, 0x30, 0xb7, 0x7a, 0xfa, 0x96, 0x41, 0x60, 0x2b, 0xcb, 0x59, 0xb9, 0xca, 0x50}}}, +{{{0xc2, 0x5b, 0x9b, 0x78, 0x23, 0x1b, 0x3a, 0x88, 0x94, 0x5f, 0x0a, 0x9b, 0x98, 0x2b, 0x6e, 0x53, 0x11, 0xf6, 0xff, 0xc6, 0x7d, 0x42, 0xcc, 0x02, 0x80, 0x40, 0x0d, 0x1e, 0xfb, 0xaf, 0x61, 0x07}} , + {{0xb0, 0xe6, 0x2f, 0x81, 0x70, 0xa1, 0x2e, 0x39, 0x04, 0x7c, 0xc4, 0x2c, 0x87, 0x45, 0x4a, 0x5b, 0x69, 0x97, 0xac, 0x6d, 0x2c, 0x10, 0x42, 0x7c, 0x3b, 0x15, 0x70, 0x60, 0x0e, 0x11, 0x6d, 0x3a}}}, +{{{0x9b, 0x18, 0x80, 0x5e, 0xdb, 0x05, 0xbd, 0xc6, 0xb7, 0x3c, 0xc2, 0x40, 0x4d, 0x5d, 0xce, 0x97, 0x8a, 0x34, 0x15, 0xab, 0x28, 0x5d, 0x10, 0xf0, 0x37, 0x0c, 0xcc, 0x16, 0xfa, 0x1f, 0x33, 0x0d}} , + {{0x19, 0xf9, 0x35, 0xaa, 0x59, 0x1a, 0x0c, 0x5c, 0x06, 0xfc, 0x6a, 0x0b, 0x97, 0x53, 0x36, 0xfc, 0x2a, 0xa5, 0x5a, 0x9b, 0x30, 0xef, 0x23, 0xaf, 0x39, 0x5d, 0x9a, 0x6b, 0x75, 0x57, 0x48, 0x0b}}}, +{{{0x26, 0xdc, 0x76, 0x3b, 0xfc, 0xf9, 0x9c, 0x3f, 0x89, 0x0b, 0x62, 0x53, 0xaf, 0x83, 0x01, 0x2e, 0xbc, 0x6a, 0xc6, 0x03, 0x0d, 0x75, 0x2a, 0x0d, 0xe6, 0x94, 0x54, 0xcf, 0xb3, 0xe5, 0x96, 0x25}} , + {{0xfe, 0x82, 0xb1, 0x74, 0x31, 0x8a, 0xa7, 0x6f, 0x56, 0xbd, 0x8d, 0xf4, 0xe0, 0x94, 0x51, 0x59, 0xde, 0x2c, 0x5a, 0xf4, 0x84, 0x6b, 0x4a, 0x88, 0x93, 0xc0, 0x0c, 0x9a, 0xac, 0xa7, 0xa0, 0x68}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x25, 0x0d, 0xd6, 0xc7, 0x23, 0x47, 0x10, 0xad, 0xc7, 0x08, 0x5c, 0x87, 0x87, 0x93, 0x98, 0x18, 0xb8, 0xd3, 0x9c, 0xac, 0x5a, 0x3d, 0xc5, 0x75, 0xf8, 0x49, 0x32, 0x14, 0xcc, 0x51, 0x96, 0x24}} , + {{0x65, 0x9c, 0x5d, 0xf0, 0x37, 0x04, 0xf0, 0x34, 0x69, 0x2a, 0xf0, 0xa5, 0x64, 0xca, 0xde, 0x2b, 0x5b, 0x15, 0x10, 0xd2, 0xab, 0x06, 0xdd, 0xc4, 0xb0, 0xb6, 0x5b, 0xc1, 0x17, 0xdf, 0x8f, 0x02}}}, +{{{0xbd, 0x59, 0x3d, 0xbf, 0x5c, 0x31, 0x44, 0x2c, 0x32, 0x94, 0x04, 0x60, 0x84, 0x0f, 0xad, 0x00, 0xb6, 0x8f, 0xc9, 0x1d, 0xcc, 0x5c, 0xa2, 0x49, 0x0e, 0x50, 0x91, 0x08, 0x9a, 0x43, 0x55, 0x05}} , + {{0x5d, 0x93, 0x55, 0xdf, 0x9b, 0x12, 0x19, 0xec, 0x93, 0x85, 0x42, 0x9e, 0x66, 0x0f, 0x9d, 0xaf, 0x99, 0xaf, 0x26, 0x89, 0xbc, 0x61, 0xfd, 0xff, 0xce, 0x4b, 0xf4, 0x33, 0x95, 0xc9, 0x35, 0x58}}}, +{{{0x12, 0x55, 0xf9, 0xda, 0xcb, 0x44, 0xa7, 0xdc, 0x57, 0xe2, 0xf9, 0x9a, 0xe6, 0x07, 0x23, 0x60, 0x54, 0xa7, 0x39, 0xa5, 0x9b, 0x84, 0x56, 0x6e, 0xaa, 0x8b, 0x8f, 0xb0, 0x2c, 0x87, 0xaf, 0x67}} , + {{0x00, 0xa9, 0x4c, 0xb2, 0x12, 0xf8, 0x32, 0xa8, 0x7a, 0x00, 0x4b, 0x49, 0x32, 0xba, 0x1f, 0x5d, 0x44, 0x8e, 0x44, 0x7a, 0xdc, 0x11, 0xfb, 0x39, 0x08, 0x57, 0x87, 0xa5, 0x12, 0x42, 0x93, 0x0e}}}, +{{{0x17, 0xb4, 0xae, 0x72, 0x59, 0xd0, 0xaa, 0xa8, 0x16, 0x8b, 0x63, 0x11, 0xb3, 0x43, 0x04, 0xda, 0x0c, 0xa8, 0xb7, 0x68, 0xdd, 0x4e, 0x54, 0xe7, 0xaf, 0x5d, 0x5d, 0x05, 0x76, 0x36, 0xec, 0x0d}} , + {{0x6d, 0x7c, 0x82, 0x32, 0x38, 0x55, 0x57, 0x74, 0x5b, 0x7d, 0xc3, 0xc4, 0xfb, 0x06, 0x29, 0xf0, 0x13, 0x55, 0x54, 0xc6, 0xa7, 0xdc, 0x4c, 0x9f, 0x98, 0x49, 0x20, 0xa8, 0xc3, 0x8d, 0xfa, 0x48}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x87, 0x47, 0x9d, 0xe9, 0x25, 0xd5, 0xe3, 0x47, 0x78, 0xdf, 0x85, 0xa7, 0x85, 0x5e, 0x7a, 0x4c, 0x5f, 0x79, 0x1a, 0xf3, 0xa2, 0xb2, 0x28, 0xa0, 0x9c, 0xdd, 0x30, 0x40, 0xd4, 0x38, 0xbd, 0x28}} , + {{0xfc, 0xbb, 0xd5, 0x78, 0x6d, 0x1d, 0xd4, 0x99, 0xb4, 0xaa, 0x44, 0x44, 0x7a, 0x1b, 0xd8, 0xfe, 0xb4, 0x99, 0xb9, 0xcc, 0xe7, 0xc4, 0xd3, 0x3a, 0x73, 0x83, 0x41, 0x5c, 0x40, 0xd7, 0x2d, 0x55}}}, +{{{0x26, 0xe1, 0x7b, 0x5f, 0xe5, 0xdc, 0x3f, 0x7d, 0xa1, 0xa7, 0x26, 0x44, 0x22, 0x23, 0xc0, 0x8f, 0x7d, 0xf1, 0xb5, 0x11, 0x47, 0x7b, 0x19, 0xd4, 0x75, 0x6f, 0x1e, 0xa5, 0x27, 0xfe, 0xc8, 0x0e}} , + {{0xd3, 0x11, 0x3d, 0xab, 0xef, 0x2c, 0xed, 0xb1, 0x3d, 0x7c, 0x32, 0x81, 0x6b, 0xfe, 0xf8, 0x1c, 0x3c, 0x7b, 0xc0, 0x61, 0xdf, 0xb8, 0x75, 0x76, 0x7f, 0xaa, 0xd8, 0x93, 0xaf, 0x3d, 0xe8, 0x3d}}}, +{{{0xfd, 0x5b, 0x4e, 0x8d, 0xb6, 0x7e, 0x82, 0x9b, 0xef, 0xce, 0x04, 0x69, 0x51, 0x52, 0xff, 0xef, 0xa0, 0x52, 0xb5, 0x79, 0x17, 0x5e, 0x2f, 0xde, 0xd6, 0x3c, 0x2d, 0xa0, 0x43, 0xb4, 0x0b, 0x19}} , + {{0xc0, 0x61, 0x48, 0x48, 0x17, 0xf4, 0x9e, 0x18, 0x51, 0x2d, 0xea, 0x2f, 0xf2, 0xf2, 0xe0, 0xa3, 0x14, 0xb7, 0x8b, 0x3a, 0x30, 0xf5, 0x81, 0xc1, 0x5d, 0x71, 0x39, 0x62, 0x55, 0x1f, 0x60, 0x5a}}}, +{{{0xe5, 0x89, 0x8a, 0x76, 0x6c, 0xdb, 0x4d, 0x0a, 0x5b, 0x72, 0x9d, 0x59, 0x6e, 0x63, 0x63, 0x18, 0x7c, 0xe3, 0xfa, 0xe2, 0xdb, 0xa1, 0x8d, 0xf4, 0xa5, 0xd7, 0x16, 0xb2, 0xd0, 0xb3, 0x3f, 0x39}} , + {{0xce, 0x60, 0x09, 0x6c, 0xf5, 0x76, 0x17, 0x24, 0x80, 0x3a, 0x96, 0xc7, 0x94, 0x2e, 0xf7, 0x6b, 0xef, 0xb5, 0x05, 0x96, 0xef, 0xd3, 0x7b, 0x51, 0xda, 0x05, 0x44, 0x67, 0xbc, 0x07, 0x21, 0x4e}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xe9, 0x73, 0x6f, 0x21, 0xb9, 0xde, 0x22, 0x7d, 0xeb, 0x97, 0x31, 0x10, 0xa3, 0xea, 0xe1, 0xc6, 0x37, 0xeb, 0x8f, 0x43, 0x58, 0xde, 0x41, 0x64, 0x0e, 0x3e, 0x07, 0x99, 0x3d, 0xf1, 0xdf, 0x1e}} , + {{0xf8, 0xad, 0x43, 0xc2, 0x17, 0x06, 0xe2, 0xe4, 0xa9, 0x86, 0xcd, 0x18, 0xd7, 0x78, 0xc8, 0x74, 0x66, 0xd2, 0x09, 0x18, 0xa5, 0xf1, 0xca, 0xa6, 0x62, 0x92, 0xc1, 0xcb, 0x00, 0xeb, 0x42, 0x2e}}}, +{{{0x7b, 0x34, 0x24, 0x4c, 0xcf, 0x38, 0xe5, 0x6c, 0x0a, 0x01, 0x2c, 0x22, 0x0b, 0x24, 0x38, 0xad, 0x24, 0x7e, 0x19, 0xf0, 0x6c, 0xf9, 0x31, 0xf4, 0x35, 0x11, 0xf6, 0x46, 0x33, 0x3a, 0x23, 0x59}} , + {{0x20, 0x0b, 0xa1, 0x08, 0x19, 0xad, 0x39, 0x54, 0xea, 0x3e, 0x23, 0x09, 0xb6, 0xe2, 0xd2, 0xbc, 0x4d, 0xfc, 0x9c, 0xf0, 0x13, 0x16, 0x22, 0x3f, 0xb9, 0xd2, 0x11, 0x86, 0x90, 0x55, 0xce, 0x3c}}}, +{{{0xc4, 0x0b, 0x4b, 0x62, 0x99, 0x37, 0x84, 0x3f, 0x74, 0xa2, 0xf9, 0xce, 0xe2, 0x0b, 0x0f, 0x2a, 0x3d, 0xa3, 0xe3, 0xdb, 0x5a, 0x9d, 0x93, 0xcc, 0xa5, 0xef, 0x82, 0x91, 0x1d, 0xe6, 0x6c, 0x68}} , + {{0xa3, 0x64, 0x17, 0x9b, 0x8b, 0xc8, 0x3a, 0x61, 0xe6, 0x9d, 0xc6, 0xed, 0x7b, 0x03, 0x52, 0x26, 0x9d, 0x3a, 0xb3, 0x13, 0xcc, 0x8a, 0xfd, 0x2c, 0x1a, 0x1d, 0xed, 0x13, 0xd0, 0x55, 0x57, 0x0e}}}, +{{{0x1a, 0xea, 0xbf, 0xfd, 0x4a, 0x3c, 0x8e, 0xec, 0x29, 0x7e, 0x77, 0x77, 0x12, 0x99, 0xd7, 0x84, 0xf9, 0x55, 0x7f, 0xf1, 0x8b, 0xb4, 0xd2, 0x95, 0xa3, 0x8d, 0xf0, 0x8a, 0xa7, 0xeb, 0x82, 0x4b}} , + {{0x2c, 0x28, 0xf4, 0x3a, 0xf6, 0xde, 0x0a, 0xe0, 0x41, 0x44, 0x23, 0xf8, 0x3f, 0x03, 0x64, 0x9f, 0xc3, 0x55, 0x4c, 0xc6, 0xc1, 0x94, 0x1c, 0x24, 0x5d, 0x5f, 0x92, 0x45, 0x96, 0x57, 0x37, 0x14}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xc1, 0xcd, 0x90, 0x66, 0xb9, 0x76, 0xa0, 0x5b, 0xa5, 0x85, 0x75, 0x23, 0xf9, 0x89, 0xa5, 0x82, 0xb2, 0x6f, 0xb1, 0xeb, 0xc4, 0x69, 0x6f, 0x18, 0x5a, 0xed, 0x94, 0x3d, 0x9d, 0xd9, 0x2c, 0x1a}} , + {{0x35, 0xb0, 0xe6, 0x73, 0x06, 0xb7, 0x37, 0xe0, 0xf8, 0xb0, 0x22, 0xe8, 0xd2, 0xed, 0x0b, 0xef, 0xe6, 0xc6, 0x5a, 0x99, 0x9e, 0x1a, 0x9f, 0x04, 0x97, 0xe4, 0x4d, 0x0b, 0xbe, 0xba, 0x44, 0x40}}}, +{{{0xc1, 0x56, 0x96, 0x91, 0x5f, 0x1f, 0xbb, 0x54, 0x6f, 0x88, 0x89, 0x0a, 0xb2, 0xd6, 0x41, 0x42, 0x6a, 0x82, 0xee, 0x14, 0xaa, 0x76, 0x30, 0x65, 0x0f, 0x67, 0x39, 0xa6, 0x51, 0x7c, 0x49, 0x24}} , + {{0x35, 0xa3, 0x78, 0xd1, 0x11, 0x0f, 0x75, 0xd3, 0x70, 0x46, 0xdb, 0x20, 0x51, 0xcb, 0x92, 0x80, 0x54, 0x10, 0x74, 0x36, 0x86, 0xa9, 0xd7, 0xa3, 0x08, 0x78, 0xf1, 0x01, 0x29, 0xf8, 0x80, 0x3b}}}, +{{{0xdb, 0xa7, 0x9d, 0x9d, 0xbf, 0xa0, 0xcc, 0xed, 0x53, 0xa2, 0xa2, 0x19, 0x39, 0x48, 0x83, 0x19, 0x37, 0x58, 0xd1, 0x04, 0x28, 0x40, 0xf7, 0x8a, 0xc2, 0x08, 0xb7, 0xa5, 0x42, 0xcf, 0x53, 0x4c}} , + {{0xa7, 0xbb, 0xf6, 0x8e, 0xad, 0xdd, 0xf7, 0x90, 0xdd, 0x5f, 0x93, 0x89, 0xae, 0x04, 0x37, 0xe6, 0x9a, 0xb7, 0xe8, 0xc0, 0xdf, 0x16, 0x2a, 0xbf, 0xc4, 0x3a, 0x3c, 0x41, 0xd5, 0x89, 0x72, 0x5a}}}, +{{{0x1f, 0x96, 0xff, 0x34, 0x2c, 0x13, 0x21, 0xcb, 0x0a, 0x89, 0x85, 0xbe, 0xb3, 0x70, 0x9e, 0x1e, 0xde, 0x97, 0xaf, 0x96, 0x30, 0xf7, 0x48, 0x89, 0x40, 0x8d, 0x07, 0xf1, 0x25, 0xf0, 0x30, 0x58}} , + {{0x1e, 0xd4, 0x93, 0x57, 0xe2, 0x17, 0xe7, 0x9d, 0xab, 0x3c, 0x55, 0x03, 0x82, 0x2f, 0x2b, 0xdb, 0x56, 0x1e, 0x30, 0x2e, 0x24, 0x47, 0x6e, 0xe6, 0xff, 0x33, 0x24, 0x2c, 0x75, 0x51, 0xd4, 0x67}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0x2b, 0x06, 0xd9, 0xa1, 0x5d, 0xe1, 0xf4, 0xd1, 0x1e, 0x3c, 0x9a, 0xc6, 0x29, 0x2b, 0x13, 0x13, 0x78, 0xc0, 0xd8, 0x16, 0x17, 0x2d, 0x9e, 0xa9, 0xc9, 0x79, 0x57, 0xab, 0x24, 0x91, 0x92, 0x19}} , + {{0x69, 0xfb, 0xa1, 0x9c, 0xa6, 0x75, 0x49, 0x7d, 0x60, 0x73, 0x40, 0x42, 0xc4, 0x13, 0x0a, 0x95, 0x79, 0x1e, 0x04, 0x83, 0x94, 0x99, 0x9b, 0x1e, 0x0c, 0xe8, 0x1f, 0x54, 0xef, 0xcb, 0xc0, 0x52}}}, +{{{0x14, 0x89, 0x73, 0xa1, 0x37, 0x87, 0x6a, 0x7a, 0xcf, 0x1d, 0xd9, 0x2e, 0x1a, 0x67, 0xed, 0x74, 0xc0, 0xf0, 0x9c, 0x33, 0xdd, 0xdf, 0x08, 0xbf, 0x7b, 0xd1, 0x66, 0xda, 0xe6, 0xc9, 0x49, 0x08}} , + {{0xe9, 0xdd, 0x5e, 0x55, 0xb0, 0x0a, 0xde, 0x21, 0x4c, 0x5a, 0x2e, 0xd4, 0x80, 0x3a, 0x57, 0x92, 0x7a, 0xf1, 0xc4, 0x2c, 0x40, 0xaf, 0x2f, 0xc9, 0x92, 0x03, 0xe5, 0x5a, 0xbc, 0xdc, 0xf4, 0x09}}}, +{{{0xf3, 0xe1, 0x2b, 0x7c, 0x05, 0x86, 0x80, 0x93, 0x4a, 0xad, 0xb4, 0x8f, 0x7e, 0x99, 0x0c, 0xfd, 0xcd, 0xef, 0xd1, 0xff, 0x2c, 0x69, 0x34, 0x13, 0x41, 0x64, 0xcf, 0x3b, 0xd0, 0x90, 0x09, 0x1e}} , + {{0x9d, 0x45, 0xd6, 0x80, 0xe6, 0x45, 0xaa, 0xf4, 0x15, 0xaa, 0x5c, 0x34, 0x87, 0x99, 0xa2, 0x8c, 0x26, 0x84, 0x62, 0x7d, 0xb6, 0x29, 0xc0, 0x52, 0xea, 0xf5, 0x81, 0x18, 0x0f, 0x35, 0xa9, 0x0e}}}, +{{{0xe7, 0x20, 0x72, 0x7c, 0x6d, 0x94, 0x5f, 0x52, 0x44, 0x54, 0xe3, 0xf1, 0xb2, 0xb0, 0x36, 0x46, 0x0f, 0xae, 0x92, 0xe8, 0x70, 0x9d, 0x6e, 0x79, 0xb1, 0xad, 0x37, 0xa9, 0x5f, 0xc0, 0xde, 0x03}} , + {{0x15, 0x55, 0x37, 0xc6, 0x1c, 0x27, 0x1c, 0x6d, 0x14, 0x4f, 0xca, 0xa4, 0xc4, 0x88, 0x25, 0x46, 0x39, 0xfc, 0x5a, 0xe5, 0xfe, 0x29, 0x11, 0x69, 0xf5, 0x72, 0x84, 0x4d, 0x78, 0x9f, 0x94, 0x15}}}, +{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, +{{{0xec, 0xd3, 0xff, 0x57, 0x0b, 0xb0, 0xb2, 0xdc, 0xf8, 0x4f, 0xe2, 0x12, 0xd5, 0x36, 0xbe, 0x6b, 0x09, 0x43, 0x6d, 0xa3, 0x4d, 0x90, 0x2d, 0xb8, 0x74, 0xe8, 0x71, 0x45, 0x19, 0x8b, 0x0c, 0x6a}} , + {{0xb8, 0x42, 0x1c, 0x03, 0xad, 0x2c, 0x03, 0x8e, 0xac, 0xd7, 0x98, 0x29, 0x13, 0xc6, 0x02, 0x29, 0xb5, 0xd4, 0xe7, 0xcf, 0xcc, 0x8b, 0x83, 0xec, 0x35, 0xc7, 0x9c, 0x74, 0xb7, 0xad, 0x85, 0x5f}}}, +{{{0x78, 0x84, 0xe1, 0x56, 0x45, 0x69, 0x68, 0x5a, 0x4f, 0xb8, 0xb1, 0x29, 0xff, 0x33, 0x03, 0x31, 0xb7, 0xcb, 0x96, 0x25, 0xe6, 0xe6, 0x41, 0x98, 0x1a, 0xbb, 0x03, 0x56, 0xf2, 0xb2, 0x91, 0x34}} , + {{0x2c, 0x6c, 0xf7, 0x66, 0xa4, 0x62, 0x6b, 0x39, 0xb3, 0xba, 0x65, 0xd3, 0x1c, 0xf8, 0x11, 0xaa, 0xbe, 0xdc, 0x80, 0x59, 0x87, 0xf5, 0x7b, 0xe5, 0xe3, 0xb3, 0x3e, 0x39, 0xda, 0xbe, 0x88, 0x09}}}, +{{{0x8b, 0xf1, 0xa0, 0xf5, 0xdc, 0x29, 0xb4, 0xe2, 0x07, 0xc6, 0x7a, 0x00, 0xd0, 0x89, 0x17, 0x51, 0xd4, 0xbb, 0xd4, 0x22, 0xea, 0x7e, 0x7d, 0x7c, 0x24, 0xea, 0xf2, 0xe8, 0x22, 0x12, 0x95, 0x06}} , + {{0xda, 0x7c, 0xa4, 0x0c, 0xf4, 0xba, 0x6e, 0xe1, 0x89, 0xb5, 0x59, 0xca, 0xf1, 0xc0, 0x29, 0x36, 0x09, 0x44, 0xe2, 0x7f, 0xd1, 0x63, 0x15, 0x99, 0xea, 0x25, 0xcf, 0x0c, 0x9d, 0xc0, 0x44, 0x6f}}}, +{{{0x1d, 0x86, 0x4e, 0xcf, 0xf7, 0x37, 0x10, 0x25, 0x8f, 0x12, 0xfb, 0x19, 0xfb, 0xe0, 0xed, 0x10, 0xc8, 0xe2, 0xf5, 0x75, 0xb1, 0x33, 0xc0, 0x96, 0x0d, 0xfb, 0x15, 0x6c, 0x0d, 0x07, 0x5f, 0x05}} , + {{0x69, 0x3e, 0x47, 0x97, 0x2c, 0xaf, 0x52, 0x7c, 0x78, 0x83, 0xad, 0x1b, 0x39, 0x82, 0x2f, 0x02, 0x6f, 0x47, 0xdb, 0x2a, 0xb0, 0xe1, 0x91, 0x99, 0x55, 0xb8, 0x99, 0x3a, 0xa0, 0x44, 0x11, 0x51}}} diff --git a/src-ed25519/supercop-ref/sc25519.c b/src-ed25519/supercop-ref/sc25519.c new file mode 100644 index 0000000..4c30430 --- /dev/null +++ b/src-ed25519/supercop-ref/sc25519.c @@ -0,0 +1,298 @@ +#include "sc25519.h" + +/*Arithmetic modulo the group order m = 2^252 + 27742317777372353535851937790883648493 = 7237005577332262213973186563042994240857116359379907606001950938285454250989 */ + +static const crypto_uint32 m[32] = {0xED, 0xD3, 0xF5, 0x5C, 0x1A, 0x63, 0x12, 0x58, 0xD6, 0x9C, 0xF7, 0xA2, 0xDE, 0xF9, 0xDE, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}; + +static const crypto_uint32 mu[33] = {0x1B, 0x13, 0x2C, 0x0A, 0xA3, 0xE5, 0x9C, 0xED, 0xA7, 0x29, 0x63, 0x08, 0x5D, 0x21, 0x06, 0x21, + 0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F}; + +static crypto_uint32 lt(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */ +{ + unsigned int x = a; + x -= (unsigned int) b; /* 0..65535: no; 4294901761..4294967295: yes */ + x >>= 31; /* 0: no; 1: yes */ + return x; +} + +/* Reduce coefficients of r before calling reduce_add_sub */ +static void reduce_add_sub(sc25519 *r) +{ + crypto_uint32 pb = 0; + crypto_uint32 b; + crypto_uint32 mask; + int i; + unsigned char t[32]; + + for(i=0;i<32;i++) + { + pb += m[i]; + b = lt(r->v[i],pb); + t[i] = r->v[i]-pb+(b<<8); + pb = b; + } + mask = b - 1; + for(i=0;i<32;i++) + r->v[i] ^= mask & (r->v[i] ^ t[i]); +} + +/* Reduce coefficients of x before calling barrett_reduce */ +static void barrett_reduce(sc25519 *r, const crypto_uint32 x[64]) +{ + /* See HAC, Alg. 14.42 */ + int i,j; + crypto_uint32 q2[66]; + crypto_uint32 *q3 = q2 + 33; + crypto_uint32 r1[33]; + crypto_uint32 r2[33]; + crypto_uint32 carry; + crypto_uint32 pb = 0; + crypto_uint32 b; + + for (i = 0;i < 66;++i) q2[i] = 0; + for (i = 0;i < 33;++i) r2[i] = 0; + + for(i=0;i<33;i++) + for(j=0;j<33;j++) + if(i+j >= 31) q2[i+j] += mu[i]*x[j+31]; + carry = q2[31] >> 8; + q2[32] += carry; + carry = q2[32] >> 8; + q2[33] += carry; + + for(i=0;i<33;i++)r1[i] = x[i]; + for(i=0;i<32;i++) + for(j=0;j<33;j++) + if(i+j < 33) r2[i+j] += m[i]*q3[j]; + + for(i=0;i<32;i++) + { + carry = r2[i] >> 8; + r2[i+1] += carry; + r2[i] &= 0xff; + } + + for(i=0;i<32;i++) + { + pb += r2[i]; + b = lt(r1[i],pb); + r->v[i] = r1[i]-pb+(b<<8); + pb = b; + } + + /* XXX: Can it really happen that r<0?, See HAC, Alg 14.42, Step 3 + * If so: Handle it here! + */ + + reduce_add_sub(r); + reduce_add_sub(r); +} + +void sc25519_from32bytes(sc25519 *r, const unsigned char x[32]) +{ + int i; + crypto_uint32 t[64]; + for(i=0;i<32;i++) t[i] = x[i]; + for(i=32;i<64;++i) t[i] = 0; + barrett_reduce(r, t); +} + +void shortsc25519_from16bytes(shortsc25519 *r, const unsigned char x[16]) +{ + int i; + for(i=0;i<16;i++) r->v[i] = x[i]; +} + +void sc25519_from64bytes(sc25519 *r, const unsigned char x[64]) +{ + int i; + crypto_uint32 t[64]; + for(i=0;i<64;i++) t[i] = x[i]; + barrett_reduce(r, t); +} + +void sc25519_from_shortsc(sc25519 *r, const shortsc25519 *x) +{ + int i; + for(i=0;i<16;i++) + r->v[i] = x->v[i]; + for(i=0;i<16;i++) + r->v[16+i] = 0; +} + +void sc25519_to32bytes(unsigned char r[32], const sc25519 *x) +{ + int i; + for(i=0;i<32;i++) r[i] = x->v[i]; +} + +int sc25519_iszero_vartime(const sc25519 *x) +{ + int i; + for(i=0;i<32;i++) + if(x->v[i] != 0) return 0; + return 1; +} + +int sc25519_isshort_vartime(const sc25519 *x) +{ + int i; + for(i=31;i>15;i--) + if(x->v[i] != 0) return 0; + return 1; +} + +int sc25519_lt_vartime(const sc25519 *x, const sc25519 *y) +{ + int i; + for(i=31;i>=0;i--) + { + if(x->v[i] < y->v[i]) return 1; + if(x->v[i] > y->v[i]) return 0; + } + return 0; +} + +void sc25519_add(sc25519 *r, const sc25519 *x, const sc25519 *y) +{ + int i, carry; + for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i]; + for(i=0;i<31;i++) + { + carry = r->v[i] >> 8; + r->v[i+1] += carry; + r->v[i] &= 0xff; + } + reduce_add_sub(r); +} + +void sc25519_sub_nored(sc25519 *r, const sc25519 *x, const sc25519 *y) +{ + crypto_uint32 b = 0; + crypto_uint32 t; + int i; + for(i=0;i<32;i++) + { + t = x->v[i] - y->v[i] - b; + r->v[i] = t & 255; + b = (t >> 8) & 1; + } +} + +void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y) +{ + int i,j,carry; + crypto_uint32 t[64]; + for(i=0;i<64;i++)t[i] = 0; + + for(i=0;i<32;i++) + for(j=0;j<32;j++) + t[i+j] += x->v[i] * y->v[j]; + + /* Reduce coefficients */ + for(i=0;i<63;i++) + { + carry = t[i] >> 8; + t[i+1] += carry; + t[i] &= 0xff; + } + + barrett_reduce(r, t); +} + +void sc25519_mul_shortsc(sc25519 *r, const sc25519 *x, const shortsc25519 *y) +{ + sc25519 t; + sc25519_from_shortsc(&t, y); + sc25519_mul(r, x, &t); +} + +void sc25519_window3(signed char r[85], const sc25519 *s) +{ + char carry; + int i; + for(i=0;i<10;i++) + { + r[8*i+0] = s->v[3*i+0] & 7; + r[8*i+1] = (s->v[3*i+0] >> 3) & 7; + r[8*i+2] = (s->v[3*i+0] >> 6) & 7; + r[8*i+2] ^= (s->v[3*i+1] << 2) & 7; + r[8*i+3] = (s->v[3*i+1] >> 1) & 7; + r[8*i+4] = (s->v[3*i+1] >> 4) & 7; + r[8*i+5] = (s->v[3*i+1] >> 7) & 7; + r[8*i+5] ^= (s->v[3*i+2] << 1) & 7; + r[8*i+6] = (s->v[3*i+2] >> 2) & 7; + r[8*i+7] = (s->v[3*i+2] >> 5) & 7; + } + r[8*i+0] = s->v[3*i+0] & 7; + r[8*i+1] = (s->v[3*i+0] >> 3) & 7; + r[8*i+2] = (s->v[3*i+0] >> 6) & 7; + r[8*i+2] ^= (s->v[3*i+1] << 2) & 7; + r[8*i+3] = (s->v[3*i+1] >> 1) & 7; + r[8*i+4] = (s->v[3*i+1] >> 4) & 7; + + /* Making it signed */ + carry = 0; + for(i=0;i<84;i++) + { + r[i] += carry; + r[i+1] += r[i] >> 3; + r[i] &= 7; + carry = r[i] >> 2; + r[i] -= carry<<3; + } + r[84] += carry; +} + +void sc25519_window5(signed char r[51], const sc25519 *s) +{ + char carry; + int i; + for(i=0;i<6;i++) + { + r[8*i+0] = s->v[5*i+0] & 31; + r[8*i+1] = (s->v[5*i+0] >> 5) & 31; + r[8*i+1] ^= (s->v[5*i+1] << 3) & 31; + r[8*i+2] = (s->v[5*i+1] >> 2) & 31; + r[8*i+3] = (s->v[5*i+1] >> 7) & 31; + r[8*i+3] ^= (s->v[5*i+2] << 1) & 31; + r[8*i+4] = (s->v[5*i+2] >> 4) & 31; + r[8*i+4] ^= (s->v[5*i+3] << 4) & 31; + r[8*i+5] = (s->v[5*i+3] >> 1) & 31; + r[8*i+6] = (s->v[5*i+3] >> 6) & 31; + r[8*i+6] ^= (s->v[5*i+4] << 2) & 31; + r[8*i+7] = (s->v[5*i+4] >> 3) & 31; + } + r[8*i+0] = s->v[5*i+0] & 31; + r[8*i+1] = (s->v[5*i+0] >> 5) & 31; + r[8*i+1] ^= (s->v[5*i+1] << 3) & 31; + r[8*i+2] = (s->v[5*i+1] >> 2) & 31; + + /* Making it signed */ + carry = 0; + for(i=0;i<50;i++) + { + r[i] += carry; + r[i+1] += r[i] >> 5; + r[i] &= 31; + carry = r[i] >> 4; + r[i] -= carry<<5; + } + r[50] += carry; +} + +void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2) +{ + int i; + for(i=0;i<31;i++) + { + r[4*i] = ( s1->v[i] & 3) ^ (( s2->v[i] & 3) << 2); + r[4*i+1] = ((s1->v[i] >> 2) & 3) ^ (((s2->v[i] >> 2) & 3) << 2); + r[4*i+2] = ((s1->v[i] >> 4) & 3) ^ (((s2->v[i] >> 4) & 3) << 2); + r[4*i+3] = ((s1->v[i] >> 6) & 3) ^ (((s2->v[i] >> 6) & 3) << 2); + } + r[124] = ( s1->v[31] & 3) ^ (( s2->v[31] & 3) << 2); + r[125] = ((s1->v[31] >> 2) & 3) ^ (((s2->v[31] >> 2) & 3) << 2); + r[126] = ((s1->v[31] >> 4) & 3) ^ (((s2->v[31] >> 4) & 3) << 2); +} diff --git a/src-ed25519/supercop-ref/sc25519.h b/src-ed25519/supercop-ref/sc25519.h new file mode 100644 index 0000000..23c94a4 --- /dev/null +++ b/src-ed25519/supercop-ref/sc25519.h @@ -0,0 +1,73 @@ +#ifndef SC25519_H +#define SC25519_H + +#include "crypto_int32.h" +#include "crypto_uint32.h" + +#define sc25519 crypto_sign_ed25519_ref_sc25519 +#define shortsc25519 crypto_sign_ed25519_ref_shortsc25519 +#define sc25519_from32bytes crypto_sign_ed25519_ref_sc25519_from32bytes +#define shortsc25519_from16bytes crypto_sign_ed25519_ref_shortsc25519_from16bytes +#define sc25519_from64bytes crypto_sign_ed25519_ref_sc25519_from64bytes +#define sc25519_from_shortsc crypto_sign_ed25519_ref_sc25519_from_shortsc +#define sc25519_to32bytes crypto_sign_ed25519_ref_sc25519_to32bytes +#define sc25519_iszero_vartime crypto_sign_ed25519_ref_sc25519_iszero_vartime +#define sc25519_isshort_vartime crypto_sign_ed25519_ref_sc25519_isshort_vartime +#define sc25519_lt_vartime crypto_sign_ed25519_ref_sc25519_lt_vartime +#define sc25519_add crypto_sign_ed25519_ref_sc25519_add +#define sc25519_sub_nored crypto_sign_ed25519_ref_sc25519_sub_nored +#define sc25519_mul crypto_sign_ed25519_ref_sc25519_mul +#define sc25519_mul_shortsc crypto_sign_ed25519_ref_sc25519_mul_shortsc +#define sc25519_window3 crypto_sign_ed25519_ref_sc25519_window3 +#define sc25519_window5 crypto_sign_ed25519_ref_sc25519_window5 +#define sc25519_2interleave2 crypto_sign_ed25519_ref_sc25519_2interleave2 + +typedef struct +{ + crypto_uint32 v[32]; +} +sc25519; + +typedef struct +{ + crypto_uint32 v[16]; +} +shortsc25519; + +void sc25519_from32bytes(sc25519 *r, const unsigned char x[32]); + +void shortsc25519_from16bytes(shortsc25519 *r, const unsigned char x[16]); + +void sc25519_from64bytes(sc25519 *r, const unsigned char x[64]); + +void sc25519_from_shortsc(sc25519 *r, const shortsc25519 *x); + +void sc25519_to32bytes(unsigned char r[32], const sc25519 *x); + +int sc25519_iszero_vartime(const sc25519 *x); + +int sc25519_isshort_vartime(const sc25519 *x); + +int sc25519_lt_vartime(const sc25519 *x, const sc25519 *y); + +void sc25519_add(sc25519 *r, const sc25519 *x, const sc25519 *y); + +void sc25519_sub_nored(sc25519 *r, const sc25519 *x, const sc25519 *y); + +void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y); + +void sc25519_mul_shortsc(sc25519 *r, const sc25519 *x, const shortsc25519 *y); + +/* Convert s into a representation of the form \sum_{i=0}^{84}r[i]2^3 + * with r[i] in {-4,...,3} + */ +void sc25519_window3(signed char r[85], const sc25519 *s); + +/* Convert s into a representation of the form \sum_{i=0}^{50}r[i]2^5 + * with r[i] in {-16,...,15} + */ +void sc25519_window5(signed char r[51], const sc25519 *s); + +void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2); + +#endif diff --git a/src-ed25519/supercop-ref/sha512-blocks.c b/src-ed25519/supercop-ref/sha512-blocks.c new file mode 100644 index 0000000..c8dbf0d --- /dev/null +++ b/src-ed25519/supercop-ref/sha512-blocks.c @@ -0,0 +1,239 @@ +//#include "crypto_hashblocks.h" + +typedef unsigned long long uint64; + +static uint64 load_bigendian(const unsigned char *x) +{ + return + (uint64) (x[7]) \ + | (((uint64) (x[6])) << 8) \ + | (((uint64) (x[5])) << 16) \ + | (((uint64) (x[4])) << 24) \ + | (((uint64) (x[3])) << 32) \ + | (((uint64) (x[2])) << 40) \ + | (((uint64) (x[1])) << 48) \ + | (((uint64) (x[0])) << 56) + ; +} + +static void store_bigendian(unsigned char *x,uint64 u) +{ + x[7] = u; u >>= 8; + x[6] = u; u >>= 8; + x[5] = u; u >>= 8; + x[4] = u; u >>= 8; + x[3] = u; u >>= 8; + x[2] = u; u >>= 8; + x[1] = u; u >>= 8; + x[0] = u; +} + +#define SHR(x,c) ((x) >> (c)) +#define ROTR(x,c) (((x) >> (c)) | ((x) << (64 - (c)))) + +#define Ch(x,y,z) ((x & y) ^ (~x & z)) +#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z)) +#define Sigma0(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) +#define Sigma1(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) +#define sigma0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x,7)) +#define sigma1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x,6)) + +#define M(w0,w14,w9,w1) w0 = sigma1(w14) + w9 + sigma0(w1) + w0; + +#define EXPAND \ + M(w0 ,w14,w9 ,w1 ) \ + M(w1 ,w15,w10,w2 ) \ + M(w2 ,w0 ,w11,w3 ) \ + M(w3 ,w1 ,w12,w4 ) \ + M(w4 ,w2 ,w13,w5 ) \ + M(w5 ,w3 ,w14,w6 ) \ + M(w6 ,w4 ,w15,w7 ) \ + M(w7 ,w5 ,w0 ,w8 ) \ + M(w8 ,w6 ,w1 ,w9 ) \ + M(w9 ,w7 ,w2 ,w10) \ + M(w10,w8 ,w3 ,w11) \ + M(w11,w9 ,w4 ,w12) \ + M(w12,w10,w5 ,w13) \ + M(w13,w11,w6 ,w14) \ + M(w14,w12,w7 ,w15) \ + M(w15,w13,w8 ,w0 ) + +#define F(w,k) \ + T1 = h + Sigma1(e) + Ch(e,f,g) + k + w; \ + T2 = Sigma0(a) + Maj(a,b,c); \ + h = g; \ + g = f; \ + f = e; \ + e = d + T1; \ + d = c; \ + c = b; \ + b = a; \ + a = T1 + T2; + +int crypto_hashblocks(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen) +{ + uint64 state[8]; + uint64 a; + uint64 b; + uint64 c; + uint64 d; + uint64 e; + uint64 f; + uint64 g; + uint64 h; + uint64 T1; + uint64 T2; + + a = load_bigendian(statebytes + 0); state[0] = a; + b = load_bigendian(statebytes + 8); state[1] = b; + c = load_bigendian(statebytes + 16); state[2] = c; + d = load_bigendian(statebytes + 24); state[3] = d; + e = load_bigendian(statebytes + 32); state[4] = e; + f = load_bigendian(statebytes + 40); state[5] = f; + g = load_bigendian(statebytes + 48); state[6] = g; + h = load_bigendian(statebytes + 56); state[7] = h; + + while (inlen >= 128) { + uint64 w0 = load_bigendian(in + 0); + uint64 w1 = load_bigendian(in + 8); + uint64 w2 = load_bigendian(in + 16); + uint64 w3 = load_bigendian(in + 24); + uint64 w4 = load_bigendian(in + 32); + uint64 w5 = load_bigendian(in + 40); + uint64 w6 = load_bigendian(in + 48); + uint64 w7 = load_bigendian(in + 56); + uint64 w8 = load_bigendian(in + 64); + uint64 w9 = load_bigendian(in + 72); + uint64 w10 = load_bigendian(in + 80); + uint64 w11 = load_bigendian(in + 88); + uint64 w12 = load_bigendian(in + 96); + uint64 w13 = load_bigendian(in + 104); + uint64 w14 = load_bigendian(in + 112); + uint64 w15 = load_bigendian(in + 120); + + F(w0 ,0x428a2f98d728ae22ULL) + F(w1 ,0x7137449123ef65cdULL) + F(w2 ,0xb5c0fbcfec4d3b2fULL) + F(w3 ,0xe9b5dba58189dbbcULL) + F(w4 ,0x3956c25bf348b538ULL) + F(w5 ,0x59f111f1b605d019ULL) + F(w6 ,0x923f82a4af194f9bULL) + F(w7 ,0xab1c5ed5da6d8118ULL) + F(w8 ,0xd807aa98a3030242ULL) + F(w9 ,0x12835b0145706fbeULL) + F(w10,0x243185be4ee4b28cULL) + F(w11,0x550c7dc3d5ffb4e2ULL) + F(w12,0x72be5d74f27b896fULL) + F(w13,0x80deb1fe3b1696b1ULL) + F(w14,0x9bdc06a725c71235ULL) + F(w15,0xc19bf174cf692694ULL) + + EXPAND + + F(w0 ,0xe49b69c19ef14ad2ULL) + F(w1 ,0xefbe4786384f25e3ULL) + F(w2 ,0x0fc19dc68b8cd5b5ULL) + F(w3 ,0x240ca1cc77ac9c65ULL) + F(w4 ,0x2de92c6f592b0275ULL) + F(w5 ,0x4a7484aa6ea6e483ULL) + F(w6 ,0x5cb0a9dcbd41fbd4ULL) + F(w7 ,0x76f988da831153b5ULL) + F(w8 ,0x983e5152ee66dfabULL) + F(w9 ,0xa831c66d2db43210ULL) + F(w10,0xb00327c898fb213fULL) + F(w11,0xbf597fc7beef0ee4ULL) + F(w12,0xc6e00bf33da88fc2ULL) + F(w13,0xd5a79147930aa725ULL) + F(w14,0x06ca6351e003826fULL) + F(w15,0x142929670a0e6e70ULL) + + EXPAND + + F(w0 ,0x27b70a8546d22ffcULL) + F(w1 ,0x2e1b21385c26c926ULL) + F(w2 ,0x4d2c6dfc5ac42aedULL) + F(w3 ,0x53380d139d95b3dfULL) + F(w4 ,0x650a73548baf63deULL) + F(w5 ,0x766a0abb3c77b2a8ULL) + F(w6 ,0x81c2c92e47edaee6ULL) + F(w7 ,0x92722c851482353bULL) + F(w8 ,0xa2bfe8a14cf10364ULL) + F(w9 ,0xa81a664bbc423001ULL) + F(w10,0xc24b8b70d0f89791ULL) + F(w11,0xc76c51a30654be30ULL) + F(w12,0xd192e819d6ef5218ULL) + F(w13,0xd69906245565a910ULL) + F(w14,0xf40e35855771202aULL) + F(w15,0x106aa07032bbd1b8ULL) + + EXPAND + + F(w0 ,0x19a4c116b8d2d0c8ULL) + F(w1 ,0x1e376c085141ab53ULL) + F(w2 ,0x2748774cdf8eeb99ULL) + F(w3 ,0x34b0bcb5e19b48a8ULL) + F(w4 ,0x391c0cb3c5c95a63ULL) + F(w5 ,0x4ed8aa4ae3418acbULL) + F(w6 ,0x5b9cca4f7763e373ULL) + F(w7 ,0x682e6ff3d6b2b8a3ULL) + F(w8 ,0x748f82ee5defb2fcULL) + F(w9 ,0x78a5636f43172f60ULL) + F(w10,0x84c87814a1f0ab72ULL) + F(w11,0x8cc702081a6439ecULL) + F(w12,0x90befffa23631e28ULL) + F(w13,0xa4506cebde82bde9ULL) + F(w14,0xbef9a3f7b2c67915ULL) + F(w15,0xc67178f2e372532bULL) + + EXPAND + + F(w0 ,0xca273eceea26619cULL) + F(w1 ,0xd186b8c721c0c207ULL) + F(w2 ,0xeada7dd6cde0eb1eULL) + F(w3 ,0xf57d4f7fee6ed178ULL) + F(w4 ,0x06f067aa72176fbaULL) + F(w5 ,0x0a637dc5a2c898a6ULL) + F(w6 ,0x113f9804bef90daeULL) + F(w7 ,0x1b710b35131c471bULL) + F(w8 ,0x28db77f523047d84ULL) + F(w9 ,0x32caab7b40c72493ULL) + F(w10,0x3c9ebe0a15c9bebcULL) + F(w11,0x431d67c49c100d4cULL) + F(w12,0x4cc5d4becb3e42b6ULL) + F(w13,0x597f299cfc657e2aULL) + F(w14,0x5fcb6fab3ad6faecULL) + F(w15,0x6c44198c4a475817ULL) + + a += state[0]; + b += state[1]; + c += state[2]; + d += state[3]; + e += state[4]; + f += state[5]; + g += state[6]; + h += state[7]; + + state[0] = a; + state[1] = b; + state[2] = c; + state[3] = d; + state[4] = e; + state[5] = f; + state[6] = g; + state[7] = h; + + in += 128; + inlen -= 128; + } + + store_bigendian(statebytes + 0,state[0]); + store_bigendian(statebytes + 8,state[1]); + store_bigendian(statebytes + 16,state[2]); + store_bigendian(statebytes + 24,state[3]); + store_bigendian(statebytes + 32,state[4]); + store_bigendian(statebytes + 40,state[5]); + store_bigendian(statebytes + 48,state[6]); + store_bigendian(statebytes + 56,state[7]); + + return inlen; +} diff --git a/src-ed25519/supercop-ref/sha512-hash.c b/src-ed25519/supercop-ref/sha512-hash.c new file mode 100644 index 0000000..f2f2925 --- /dev/null +++ b/src-ed25519/supercop-ref/sha512-hash.c @@ -0,0 +1,72 @@ +/* +20080913 +D. J. Bernstein +Public domain. +*/ + +#include "sha512.h" + +extern int crypto_hashblocks(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen); + +#define blocks crypto_hashblocks + +static const unsigned char iv[64] = { + 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08, + 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b, + 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b, + 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1, + 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1, + 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f, + 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b, + 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79 +} ; + +typedef unsigned long long uint64; + +int crypto_hash_sha512(unsigned char *out,const unsigned char *in,unsigned long long inlen) +{ + unsigned char h[64]; + unsigned char padded[256]; + int i; + unsigned long long bytes = inlen; + + for (i = 0;i < 64;++i) h[i] = iv[i]; + + blocks(h,in,inlen); + in += inlen; + inlen &= 127; + in -= inlen; + + for (i = 0;i < inlen;++i) padded[i] = in[i]; + padded[inlen] = 0x80; + + if (inlen < 112) { + for (i = inlen + 1;i < 119;++i) padded[i] = 0; + padded[119] = bytes >> 61; + padded[120] = bytes >> 53; + padded[121] = bytes >> 45; + padded[122] = bytes >> 37; + padded[123] = bytes >> 29; + padded[124] = bytes >> 21; + padded[125] = bytes >> 13; + padded[126] = bytes >> 5; + padded[127] = bytes << 3; + blocks(h,padded,128); + } else { + for (i = inlen + 1;i < 247;++i) padded[i] = 0; + padded[247] = bytes >> 61; + padded[248] = bytes >> 53; + padded[249] = bytes >> 45; + padded[250] = bytes >> 37; + padded[251] = bytes >> 29; + padded[252] = bytes >> 21; + padded[253] = bytes >> 13; + padded[254] = bytes >> 5; + padded[255] = bytes << 3; + blocks(h,padded,256); + } + + for (i = 0;i < 64;++i) out[i] = h[i]; + + return 0; +} diff --git a/src-ed25519/supercop-ref/sha512.h b/src-ed25519/supercop-ref/sha512.h new file mode 100644 index 0000000..37376b1 --- /dev/null +++ b/src-ed25519/supercop-ref/sha512.h @@ -0,0 +1,4 @@ +extern int crypto_hashblocks(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen); +extern int crypto_hash_sha512(unsigned char *out,const unsigned char *in,unsigned long long inlen); + +#define crypto_hash_sha512_BYTES 64 diff --git a/src-ed25519/supercop-ref/test.c b/src-ed25519/supercop-ref/test.c new file mode 100644 index 0000000..35620f2 --- /dev/null +++ b/src-ed25519/supercop-ref/test.c @@ -0,0 +1,39 @@ + +#include +#include +#include +#include "crypto_sign.h" + +char *msg = "Hello World"; + +int main(int argc, char *argv[]) { + unsigned char sk[SECRETKEYBYTES], vk[PUBLICKEYBYTES]; + unsigned char *sigmsg, *newmsg; + unsigned long long sigmsglen, newmsglen; + int ret; + crypto_sign_keypair(vk, sk); + printf("got keypair\n"); + sigmsg = malloc(strlen(msg)+1+BYTES); + if (!sigmsg) + return 1; + crypto_sign(sigmsg, &sigmsglen, (unsigned char *)msg, strlen(msg)+1, sk); + printf("got signature\n"); + if (sigmsglen != strlen(msg)+1+BYTES) + return 2; + newmsg = malloc(sigmsglen); + if (!newmsg) + return 3; + ret = crypto_sign_open(newmsg, &newmsglen, sigmsg, sigmsglen, vk); + printf("verified signature\n"); + if (ret == 0) + printf("good!\n"); + else + printf("bad\n"); + sigmsg[0] ^= 0x01; + ret = crypto_sign_open(newmsg, &newmsglen, sigmsg, sigmsglen, vk); + if (ret == 0) + printf("bad: failed to detect simple corruption\n"); + else + printf("good: detected simple corruption\n"); + return 0; +} diff --git a/src-ed25519/supercop-ref/verify.c b/src-ed25519/supercop-ref/verify.c new file mode 100644 index 0000000..a04186b --- /dev/null +++ b/src-ed25519/supercop-ref/verify.c @@ -0,0 +1,40 @@ +#include "crypto_verify_32.h" + +int crypto_verify_32(const unsigned char *x,const unsigned char *y) +{ + unsigned int differentbits = 0; +#define F(i) differentbits |= x[i] ^ y[i]; + F(0) + F(1) + F(2) + F(3) + F(4) + F(5) + F(6) + F(7) + F(8) + F(9) + F(10) + F(11) + F(12) + F(13) + F(14) + F(15) + F(16) + F(17) + F(18) + F(19) + F(20) + F(21) + F(22) + F(23) + F(24) + F(25) + F(26) + F(27) + F(28) + F(29) + F(30) + F(31) + return (1 & ((differentbits - 1) >> 8)) - 1; +} diff --git a/src/pycryptopp/__init__.py b/src/pycryptopp/__init__.py new file mode 100644 index 0000000..6248289 --- /dev/null +++ b/src/pycryptopp/__init__.py @@ -0,0 +1,31 @@ +""" +pycryptopp - Python wrappers for Crypto++ +""" + +# we import our glue .so here, and then other modules use the copy in +# sys.modules. + +import _pycryptopp +__doc__ = _pycryptopp.__doc__ + +__version__ = "unknown" +try: + import _version +except ImportError: + # We're running in a tree that hasn't run "python ./setup.py + # update_version", and didn't come with a _version.py, so we don't know + # what our version is. This should not happen very often. + pass +else: + __version__ = _version.__version__ + +def _import_my_names(thismodule, prefix): + for name in dir(_pycryptopp): + if name.startswith(prefix): + myname = name[len(prefix):] + thismodule[myname] = getattr(_pycryptopp, name) + +import publickey, hash, cipher + +quiet_pyflakes=[__version__, publickey, hash, cipher, _pycryptopp, __doc__, _import_my_names] +del quiet_pyflakes diff --git a/src/pycryptopp/_pycryptoppmodule.cpp b/src/pycryptopp/_pycryptoppmodule.cpp new file mode 100644 index 0000000..1c99817 --- /dev/null +++ b/src/pycryptopp/_pycryptoppmodule.cpp @@ -0,0 +1,72 @@ +#include + +#include "publickey/ecdsamodule.hpp" +#include "publickey/rsamodule.hpp" +#include "hash/sha256module.hpp" +#include "cipher/aesmodule.hpp" +#include "cipher/xsalsa20module.hpp" + +/* from Crypto++ */ +#ifdef DISABLE_EMBEDDED_CRYPTOPP +#include +#else +#include +#endif + +PyDoc_STRVAR(_pycryptopp__doc__, +"_pycryptopp -- Python wrappers for a few algorithms from Crypto++\n\ +\n\ +from pycryptopp import publickey\n\ +from pycryptopp.publickey import ecdsa\n\ +from pycryptopp.publickey import rsa\n\ +from pycryptopp import cipher\n\ +from pycryptopp.cipher import aes\n\ +from pycryptopp.cipher import xsalsa20\n\ +from pycryptopp import hash\n\ +from pycryptopp.hash import sha256"); + +static PyMethodDef _pycryptopp_functions[] = { + {"rsa_generate", reinterpret_cast(rsa_generate), METH_KEYWORDS, const_cast(rsa_generate__doc__)}, + {"rsa_create_verifying_key_from_string", reinterpret_cast(rsa_create_verifying_key_from_string), METH_KEYWORDS, const_cast(rsa_create_verifying_key_from_string__doc__)}, + {"rsa_create_signing_key_from_string", reinterpret_cast(rsa_create_signing_key_from_string), METH_KEYWORDS, const_cast(rsa_create_signing_key_from_string__doc__)}, + {NULL, NULL, 0, NULL} /* sentinel */ +}; + +#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ +#define PyMODINIT_FUNC void +#endif +PyMODINIT_FUNC +init_pycryptopp(void) { + PyObject *module; + + module = Py_InitModule3("_pycryptopp", _pycryptopp_functions, _pycryptopp__doc__); + if (!module) + return; + + PyObject* version; + + /* a tuple of (Crypto++ version, extra-version) */ + #ifndef DISABLE_EMBEDDED_CRYPTOPP + /* In the version of Crypto++ which is included in pycryptopp, there is a + symbol named `cryptopp_extra_version' which is declared (external + variable) in config.h and defined in cryptlib.cpp. Of course it is + possible that the header file we've #include'd is from the + embedded-in-pycryptopp version of Crypto++ but the dynamically linked + library that we load is from an older version which doesn't have this + symbol. In that case, the load will fail before we get this far. */ + version = Py_BuildValue("is", CRYPTOPP_VERSION, cryptopp_extra_version); + #else + version = Py_BuildValue("iO", CRYPTOPP_VERSION, Py_None); + #endif + + int succ = PyModule_AddObject(module, "cryptopp_version", version); + if (succ != 0) + return; + + + init_ecdsa(module); + init_rsa(module); + init_sha256(module); + init_aes(module); + init_xsalsa20(module); +} diff --git a/src/pycryptopp/_version.py b/src/pycryptopp/_version.py new file mode 100644 index 0000000..c5c437f --- /dev/null +++ b/src/pycryptopp/_version.py @@ -0,0 +1,8 @@ + +# This is the version of this tree, as created by pycryptopp's setup.py from the +# git information: the main version number is taken from the most recent +# release tag. If some patches have been added since the last release, this +# will have a -NN "build number" suffix, followed by -gXXX "revid" suffix. + +__pkgname__ = "pycryptopp" +__version__ = "0.6.0.1206569328141510525648634803928199668821045408958" diff --git a/src/pycryptopp/cipher/__init__.py b/src/pycryptopp/cipher/__init__.py new file mode 100644 index 0000000..0ebfadf --- /dev/null +++ b/src/pycryptopp/cipher/__init__.py @@ -0,0 +1,4 @@ +import aes +import xsalsa20 + +quiet_pyflakes=[aes, xsalsa20] diff --git a/src/pycryptopp/cipher/aes.py b/src/pycryptopp/cipher/aes.py new file mode 100644 index 0000000..7280063 --- /dev/null +++ b/src/pycryptopp/cipher/aes.py @@ -0,0 +1,68 @@ + +from pycryptopp import _import_my_names + +# These initializations to None are just to pacify pyflakes, which +# doesn't understand that we have to do some funky import trickery +# below in _import_my_names() in order to get sensible namespaces. +AES=None +Error=None + +_import_my_names(globals(), "aes_") + +del _import_my_names + +def start_up_self_test(): + """ + This is a quick test intended to detect major errors such as the library being + miscompiled and segfaulting or returning incorrect answers. We've had problems + of that kind many times, thus justifying running this self-test on import. + This idea was suggested to me by the second edition of "Practical + Cryptography" by Ferguson, Schneier, and Kohno. + These tests were copied from pycryptopp/test/test_aes.py on 2009-10-30. + """ + enc0 = "dc95c078a2408989ad48a21492842087530f8afbc74536b9a963b4f1c4cb738b" + from binascii import a2b_hex, b2a_hex + + cryptor = AES(key="\x00"*32) + ct = cryptor.process("\x00"*32) + if enc0 != b2a_hex(ct): + raise Error("pycryptopp failed startup self-test. Please run pycryptopp unit tests.") + + cryptor = AES(key="\x00"*32) + ct1 = cryptor.process("\x00"*15) + ct2 = cryptor.process("\x00"*17) + if enc0 != b2a_hex(ct1+ct2): + raise Error("pycryptopp failed startup self-test. Please run pycryptopp unit tests.") + + enc0 = "66e94bd4ef8a2c3b884cfa59ca342b2e" + cryptor = AES(key="\x00"*16) + ct = cryptor.process("\x00"*16) + if enc0 != b2a_hex(ct): + raise Error("pycryptopp failed startup self-test. Please run pycryptopp unit tests.") + + cryptor = AES(key="\x00"*16) + ct1 = cryptor.process("\x00"*8) + ct2 = cryptor.process("\x00"*8) + if enc0 != b2a_hex(ct1+ct2): + raise Error("pycryptopp failed startup self-test. Please run pycryptopp unit tests.") + + def _test_from_Niels_AES(keysize, result): + def fake_ecb_using_ctr(k, p): + return AES(key=k, iv=p).process('\x00'*16) + + E = fake_ecb_using_ctr + b = 16 + k = keysize + S = '\x00' * (k+b) + for i in range(1000): + K = S[-k:] + P = S[-k-b:-k] + S += E(K, E(K, P)) + + if S[-b:] != a2b_hex(result): + raise Error("pycryptopp failed startup self-test. Please run pycryptopp unit tests.") + + _test_from_Niels_AES(16, 'bd883f01035e58f42f9d812f2dacbcd8') + _test_from_Niels_AES(32, 'c84b0f3a2c76dd9871900b07f09bdd3e') + +start_up_self_test() diff --git a/src/pycryptopp/cipher/aesmodule.cpp b/src/pycryptopp/cipher/aesmodule.cpp new file mode 100644 index 0000000..0599911 --- /dev/null +++ b/src/pycryptopp/cipher/aesmodule.cpp @@ -0,0 +1,191 @@ +/** + * aesmodule.cpp -- Python wrappers around Crypto++'s AES-CTR + */ + +#define PY_SSIZE_T_CLEAN +#include +#if (PY_VERSION_HEX < 0x02050000) +typedef int Py_ssize_t; +#endif + +#include "aesmodule.hpp" + + +/* from Crypto++ */ +#ifdef DISABLE_EMBEDDED_CRYPTOPP +#include +#include +#else +#include +#include +#endif + +static const char*const aes___doc__ = "_aes counter mode cipher\n\ +You are advised to run aes.start_up_self_test() after importing this module."; + +static PyObject *aes_error; + +typedef struct { + PyObject_HEAD + + /* internal */ + CryptoPP::CTR_Mode::Encryption * e; +} AES; + +PyDoc_STRVAR(AES__doc__, +"An AES cipher object.\n\ +\n\ +This object encrypts/decrypts in CTR mode, using a counter that is initialized\n\ +to zero when you instantiate the object. Successive calls to .process() will\n\ +use the current counter value and increment it.\n\ +\n\ +Note that you must never encrypt different data with the same key, or you\n\ +will leak information about your data. Therefore the only safe way to use\n\ +this class is to use a different AES key every time you are going to encrypt\n\ +different data. A good way to generate a different AES key is using AES, like\n\ +this:\n\ +\n\ + onetimekey = AES(key=masterkey).process(nonce)\n\ +\n\ +Where 'masterkey' is a secret key used only for generating onetimekeys this\ +way, and 'nonce' is a value that is guaranteed to never repeat.\ +\n\ +@param key: the symmetric encryption key; a string of exactly 16 bytes\ +"); + +static PyObject * +AES_process(AES* self, PyObject* msgobj) { + if (!PyString_CheckExact(msgobj)) { + PyStringObject* typerepr = reinterpret_cast(PyObject_Repr(reinterpret_cast(msgobj->ob_type))); + if (typerepr) { + PyErr_Format(aes_error, "Precondition violation: you are required to pass a Python string object (not a unicode, a subclass of string, or anything else), but you passed %s.", PyString_AS_STRING(reinterpret_cast(typerepr))); + Py_DECREF(typerepr); + } else + PyErr_Format(aes_error, "Precondition violation: you are required to pass a Python string object (not a unicode, a subclass of string, or anything else)."); + return NULL; + } + + const char *msg; + Py_ssize_t msgsize; + if (PyString_AsStringAndSize(msgobj, const_cast(&msg), &msgsize)) + return NULL; + assert (msgsize >= 0); + + PyStringObject* result = reinterpret_cast(PyString_FromStringAndSize(NULL, msgsize)); + if (!result) + return NULL; + + self->e->ProcessData(reinterpret_cast(PyString_AS_STRING(result)), reinterpret_cast(msg), msgsize); + return reinterpret_cast(result); +} + +PyDoc_STRVAR(AES_process__doc__, +"Encrypt or decrypt the next bytes, returning the result."); + +static PyMethodDef AES_methods[] = { + {"process", reinterpret_cast(AES_process), METH_O, AES_process__doc__}, + {NULL}, +}; + +static PyObject * +AES_new(PyTypeObject* type, PyObject *args, PyObject *kwdict) { + AES* self = reinterpret_cast(type->tp_alloc(type, 0)); + if (!self) + return NULL; + self->e = NULL; + return reinterpret_cast(self); +} + +static void +AES_dealloc(PyObject* self) { + if (reinterpret_cast(self)->e) + delete reinterpret_cast(self)->e; + self->ob_type->tp_free(self); +} + +static int +AES_init(PyObject* self, PyObject *args, PyObject *kwdict) { + static const char *kwlist[] = { "key", "iv", NULL }; + const char *key = NULL; + Py_ssize_t keysize = 0; + const char *iv = NULL; + const char defaultiv[CryptoPP::AES::BLOCKSIZE] = {0}; + Py_ssize_t ivsize = 0; + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#|t#:AES.__init__", const_cast(kwlist), &key, &keysize, &iv, &ivsize)) + return -1; + assert (keysize >= 0); + assert (ivsize >= 0); + + if (!iv) + iv = defaultiv; + else if (ivsize != 16) { + PyErr_Format(aes_error, "Precondition violation: if an IV is passed, it must be exactly 16 bytes, not %d", ivsize); + return -1; + } + try { + reinterpret_cast(self)->e = new CryptoPP::CTR_Mode::Encryption(reinterpret_cast(key), keysize, reinterpret_cast(iv)); + } catch (CryptoPP::InvalidKeyLength le) { + PyErr_Format(aes_error, "Precondition violation: you are required to pass a valid key size. Crypto++ gave this exception: %s", le.what()); + return -1; + } + if (!reinterpret_cast(self)->e) { + PyErr_NoMemory(); + return -1; + } + return 0; +} + +static PyTypeObject AES_type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "_aes.AES", /*tp_name*/ + sizeof(AES), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + AES_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + AES__doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + AES_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + AES_init, /* tp_init */ + 0, /* tp_alloc */ + AES_new, /* tp_new */ +}; + +void +init_aes(PyObject*const module) { + if (PyType_Ready(&AES_type) < 0) + return; + Py_INCREF(&AES_type); + PyModule_AddObject(module, "aes_AES", (PyObject *)&AES_type); + + aes_error = PyErr_NewException(const_cast("_aes.Error"), NULL, NULL); + PyModule_AddObject(module, "aes_Error", aes_error); + + PyModule_AddStringConstant(module, "aes___doc__", const_cast(aes___doc__)); +} diff --git a/src/pycryptopp/cipher/aesmodule.hpp b/src/pycryptopp/cipher/aesmodule.hpp new file mode 100644 index 0000000..d10f44f --- /dev/null +++ b/src/pycryptopp/cipher/aesmodule.hpp @@ -0,0 +1,7 @@ +#ifndef __INCL_AESMODULE_HPP +#define __INCL_AESMODULE_HPP + +extern void +init_aes(PyObject* module); + +#endif /* #ifndef __INCL_AESMODULE_HPP */ diff --git a/src/pycryptopp/cipher/xsalsa20.py b/src/pycryptopp/cipher/xsalsa20.py new file mode 100644 index 0000000..86ddcd3 --- /dev/null +++ b/src/pycryptopp/cipher/xsalsa20.py @@ -0,0 +1,31 @@ +from pycryptopp import _import_my_names + +_import_my_names(globals(), "xsalsa20_") + +del _import_my_names + +def selftest(): + # pyflakes doesn't know that XSalsa20 is made available above + XSalsa20 = globals()["XSalsa20"] + from binascii import unhexlify + key = unhexlify("ad5eadf7163b0d36e44c126037a03419" + "fcda2b3a1bb4ab064b6070e61b0fa5ca") + iv = unhexlify("6a059adb8c7d4acb1c537767d541506f" "c5ef0ace9a2a65bd") + encrypted = unhexlify("23a8ed0475150e988c545b11e3660de7" + "8bf88e6628c4c99ba36330c05cb919e7" + "901295db479c9a8a0401d5e040b8919b" + "7d64b2f728c59703c3") + p = XSalsa20(key, iv) + decrypted = p.process(encrypted) + expected = "crypto libraries should always test themselves at powerup" + assert decrypted == expected + + p = XSalsa20(key, iv) + decrypted = "" + offset = 0 + for chunksize in [13,11,1,2,3,20,999]: + decrypted += p.process(encrypted[offset:offset+chunksize]) + offset += chunksize + assert decrypted == expected + +selftest() diff --git a/src/pycryptopp/cipher/xsalsa20module.cpp b/src/pycryptopp/cipher/xsalsa20module.cpp new file mode 100644 index 0000000..ab29787 --- /dev/null +++ b/src/pycryptopp/cipher/xsalsa20module.cpp @@ -0,0 +1,176 @@ +/** + * xsalsa20module.cpp -- Python wrappers around Crypto++'s salsa + */ + +#define PY_SSIZE_T_CLEAN +#include +#if (PY_VERSION_HEX < 0x02050000) +typedef int Py_ssize_t; +#endif + +#include "xsalsa20module.hpp" + +#ifdef DISABLE_EMBEDDED_CRYPTOPP +#include +#else +#include +#endif + +static const char* const xsalsa20__doc__ = "_xsalsa20 cipher"; + +static PyObject *xsalsa20_error; + +typedef struct { + PyObject_HEAD + + /* internal */ +// CryptoPP::CTR_Mode::Encryption *e; + CryptoPP::XSalsa20::Encryption *e; +} XSalsa20; + +PyDoc_STRVAR(XSalsa20__doc__, +"An XSalsa20 cipher object.\n\ +\n\ +This object encrypts/decrypts in CTR mode, using a counter that is initialized\n\ +to zero when you instantiate the object. Successive calls to .process() will \n\ +use the current counter and increment it.\n\ +\n\ +"); + +static PyObject *XSalsa20_process(XSalsa20* self, PyObject* msgobj) { + if(!PyString_CheckExact(msgobj)) { + PyStringObject* typerepr = reinterpret_cast(PyObject_Repr(reinterpret_cast(msgobj->ob_type))); + if (typerepr) { + PyErr_Format(xsalsa20_error, "Precondition violation: you are required to pass a Python string object (not a unicode, a subclass of string, or anything else), but you passed %s.", PyString_AS_STRING(reinterpret_cast(typerepr))); + Py_DECREF(typerepr); + } else + PyErr_Format(xsalsa20_error, "Precondition violation: you are required to pass a Python string object (not a unicode, a subclass of string, or anything else)."); + return NULL; + } + + const char* msg; + Py_ssize_t msgsize; + if (PyString_AsStringAndSize(msgobj, const_cast(&msg), &msgsize)) + return NULL; + assert (msgsize >= 0); + + PyStringObject* result = reinterpret_cast(PyString_FromStringAndSize(NULL, msgsize)); + if (!result) + return NULL; + + self->e->ProcessString(reinterpret_cast(PyString_AS_STRING(result)), reinterpret_cast(msg), msgsize); + return reinterpret_cast(result); +} + +PyDoc_STRVAR(XSalsa20_process__doc__, +"Encrypt or decrypt the next bytes, returning the result."); + +static PyMethodDef XSalsa20_methods[] = { + {"process", reinterpret_cast(XSalsa20_process), METH_O, XSalsa20_process__doc__}, + {NULL}, +}; + +static PyObject* XSalsa20_new(PyTypeObject* type, PyObject *args, PyObject *kwdict) { + XSalsa20* self = reinterpret_cast(type->tp_alloc(type, 0)); + if (!self) + return NULL; + self->e = NULL; + return reinterpret_cast(self); +} + +static void XSalsa20_dealloc(PyObject* self) { + if (reinterpret_cast(self)->e) + delete reinterpret_cast(self)->e; + self->ob_type->tp_free(self); +} + +static int XSalsa20_init(PyObject* self, PyObject *args, PyObject *kwdict) { + static const char *kwlist[] = { "key", "iv", NULL}; + const char *key = NULL; + Py_ssize_t keysize = 0; + const char *iv = NULL; + const char defaultiv[24] = {0}; + Py_ssize_t ivsize = 0; + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#|t#:XSalsa20.__init__", const_cast(kwlist), &key, &keysize, &iv, &ivsize)) + return -1; + assert (keysize >= 0); + assert (ivsize >= 0); + + if (!iv) + iv = defaultiv; + else if (ivsize != 24) { + PyErr_Format(xsalsa20_error, "Precondition violation: if an IV is passed, it must be exactly 24 bytes, not %d", ivsize); + return -1; + } + + try { + reinterpret_cast(self)->e = new CryptoPP::XSalsa20::Encryption(reinterpret_cast(key), keysize, reinterpret_cast(iv)); + } + catch (CryptoPP::InvalidKeyLength le) + { + PyErr_Format(xsalsa20_error, "Precondition violation: you are required to pass a valid key size. Crypto++ gave this exception: %s", le.what()); + return -1; + } + if (!reinterpret_cast(self)->e) + { + PyErr_NoMemory(); + return -1; + } + return 0; +} + + +static PyTypeObject XSalsa20_type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "_xsalsa.XSalsa20", /*tp_name*/ + sizeof(XSalsa20), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + XSalsa20_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + XSalsa20__doc__, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + XSalsa20_methods, /*tp_methods*/ + 0, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + XSalsa20_init, /*tp_init*/ + 0, /*tp_alloc*/ + XSalsa20_new, /*tp_new*/ +}; + +void init_xsalsa20(PyObject*const module) +{ + if (PyType_Ready(&XSalsa20_type) < 0) + return; + Py_INCREF(&XSalsa20_type); + PyModule_AddObject(module, "xsalsa20_XSalsa20", (PyObject *)&XSalsa20_type); + + xsalsa20_error = PyErr_NewException(const_cast("_xsalsa20.Error"), NULL, NULL); + PyModule_AddObject(module, "xsalsa20_Error", xsalsa20_error); + + PyModule_AddStringConstant(module, "xsalsa20__doc__", const_cast(xsalsa20__doc__)); +} diff --git a/src/pycryptopp/cipher/xsalsa20module.hpp b/src/pycryptopp/cipher/xsalsa20module.hpp new file mode 100644 index 0000000..24e1e2d --- /dev/null +++ b/src/pycryptopp/cipher/xsalsa20module.hpp @@ -0,0 +1,6 @@ +#ifndef __INCL_XSALSA20MODULE_HPP +#define __INCL_XSALSA20MODULE_HPP + +extern void init_xsalsa20(PyObject* module); + +#endif; /*#ifndef __INCL_XSALSA20MODULE_HPP*/ diff --git a/src/pycryptopp/hash/__init__.py b/src/pycryptopp/hash/__init__.py new file mode 100644 index 0000000..5399f81 --- /dev/null +++ b/src/pycryptopp/hash/__init__.py @@ -0,0 +1,3 @@ +import sha256 + +quiet_pyflakes=[sha256] diff --git a/src/pycryptopp/hash/sha256.py b/src/pycryptopp/hash/sha256.py new file mode 100644 index 0000000..cf52a31 --- /dev/null +++ b/src/pycryptopp/hash/sha256.py @@ -0,0 +1,43 @@ +from pycryptopp import _import_my_names + +# These initializations to None are just to pacify pyflakes, which +# doesn't understand that we have to do some funky import trickery +# below in _import_my_names() in order to get sensible namespaces. +SHA256=None +Error=None + +_import_my_names(globals(), "sha256_") + +del _import_my_names + +def start_up_self_test(): + """ + This is a quick test intended to detect major errors such as the library being + miscompiled and segfaulting or returning incorrect answers. We've had problems + of that kind many times, thus justifying running this self-test on import. + This idea was suggested to me by the second edition of "Practical + Cryptography" by Ferguson, Schneier, and Kohno. + This test was copied from pycryptopp/test/test_sha256.py on 2010-09-04. + + This test takes up to 1.5 milliseconds on a VirtualBox instance on + my Macbook Pro (fast 64-bit Intel dual-core). + + Test that updating a hasher with various sized inputs yields + the expected answer. This is somewhat redundant with + test_chunksize(), but that's okay. This one exercises some + slightly different situations (such as finalizing a hash after + different length inputs.) This one is recursive so that there + is a single fixed result that we expect. + """ + hx = SHA256() + s = ''.join([ chr(c) for c in range(65) ]) + for i in range(0, 65): + hy = SHA256(s[:i]).digest() + hx.update(hy) + for i in range(0, 65): + hx.update(chr(0xFE)) + hx.update(s[:64]) + if hx.hexdigest().lower() != '5191c7841dd4e16aa454d40af924585dffc67157ffdbfd0236acddd07901629d': + raise Error("pycryptopp failed startup self-test. Please run pycryptopp unit tests.") + +start_up_self_test() diff --git a/src/pycryptopp/hash/sha256module.cpp b/src/pycryptopp/hash/sha256module.cpp new file mode 100644 index 0000000..bf9d8e3 --- /dev/null +++ b/src/pycryptopp/hash/sha256module.cpp @@ -0,0 +1,189 @@ +/** + * sha256module.cpp -- Python wrappers around Crypto++'s SHA-256 + */ + +#define PY_SSIZE_T_CLEAN +#include +#if (PY_VERSION_HEX < 0x02050000) +typedef int Py_ssize_t; +#endif + +#include + +/* from Crypto++ */ +#ifdef DISABLE_EMBEDDED_CRYPTOPP +#include +#include +#include +#else +#include +#include +#include +#endif + +static const char*const sha256___doc__ = "_sha256 hash function"; + +static PyObject *sha256_error; + +typedef struct { + PyObject_HEAD + + /* internal */ + CryptoPP::SHA256* h; + PyStringObject* digest; +} SHA256; + +PyDoc_STRVAR(SHA256__doc__, +"a SHA256 hash object\n\ +Its constructor takes an optional string, which has the same effect as\n\ +calling .update() with that string."); + +static PyObject * +SHA256_update(SHA256* self, PyObject* msgobj) { + if (self->digest) + return PyErr_Format(sha256_error, "Precondition violation: once .digest() has been called you are required to never call .update() again."); + + const char *msg; + Py_ssize_t msgsize; + if (PyString_AsStringAndSize(msgobj, const_cast(&msg), &msgsize)) + return NULL; + self->h->Update(reinterpret_cast(msg), msgsize); + Py_RETURN_NONE; +} + +PyDoc_STRVAR(SHA256_update__doc__, +"Update the hash object with the string msg. Repeated calls are equivalent to\n\ +a single call with the concatenation of all the messages."); + +static PyObject * +SHA256_digest(SHA256* self, PyObject* dummy) { + if (!self->digest) { + assert (self->h); + self->digest = reinterpret_cast(PyString_FromStringAndSize(NULL, self->h->DigestSize())); + if (!self->digest) + return NULL; + self->h->Final(reinterpret_cast(PyString_AS_STRING(self->digest))); + } + + Py_INCREF(self->digest); + return reinterpret_cast(self->digest); +} + +PyDoc_STRVAR(SHA256_digest__doc__, +"Return the binary digest of the messages that were passed to the update()\n\ +method (including the initial message if any)."); + +static PyObject * +SHA256_hexdigest(SHA256* self, PyObject* dummy) { + PyObject* digest = SHA256_digest(self, NULL); + if (!digest) + return NULL; + Py_ssize_t dsize = PyString_GET_SIZE(digest); + PyStringObject* hexdigest = reinterpret_cast(PyString_FromStringAndSize(NULL, dsize*2)); + CryptoPP::ArraySink* as = new CryptoPP::ArraySink(reinterpret_cast(PyString_AS_STRING(hexdigest)), dsize*2); + CryptoPP::HexEncoder enc; + enc.Attach(as); + enc.Put(reinterpret_cast(PyString_AS_STRING(digest)), static_cast(dsize)); + Py_DECREF(digest); digest = NULL; + + return reinterpret_cast(hexdigest); +} + +PyDoc_STRVAR(SHA256_hexdigest__doc__, +"Return the hex-encoded digest of the messages that were passed to the update()\n\ +method (including the initial message if any)."); + +static PyMethodDef SHA256_methods[] = { + {"update", reinterpret_cast(SHA256_update), METH_O, SHA256_update__doc__}, + {"digest", reinterpret_cast(SHA256_digest), METH_NOARGS, SHA256_digest__doc__}, + {"hexdigest", reinterpret_cast(SHA256_hexdigest), METH_NOARGS, SHA256_hexdigest__doc__}, + {NULL}, +}; + +static PyObject * +SHA256_new(PyTypeObject* type, PyObject *args, PyObject *kwdict) { + SHA256* self = reinterpret_cast(type->tp_alloc(type, 0)); + if (!self) + return NULL; + self->h = new CryptoPP::SHA256(); + if (!self->h) + return PyErr_NoMemory(); + self->digest = NULL; + return reinterpret_cast(self); +} + +static void +SHA256_dealloc(SHA256* self) { + Py_XDECREF(self->digest); + delete self->h; + self->ob_type->tp_free((PyObject*)self); +} + +static int +SHA256_init(PyObject* self, PyObject *args, PyObject *kwdict) { + static const char *kwlist[] = { "msg", NULL }; + const char *msg = NULL; + Py_ssize_t msgsize = 0; + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|t#", const_cast(kwlist), &msg, &msgsize)) + return -1; + + if (msg) + reinterpret_cast(self)->h->Update(reinterpret_cast(msg), msgsize); + return 0; +} + +static PyTypeObject SHA256_type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "_sha256.SHA256", /*tp_name*/ + sizeof(SHA256), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + reinterpret_cast(SHA256_dealloc), /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + SHA256__doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + SHA256_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + //reinterpret_cast(SHA256_init), /* tp_init */ + SHA256_init, /* tp_init */ + 0, /* tp_alloc */ + SHA256_new, /* tp_new */ +}; + +void +init_sha256(PyObject* module) { + if (PyType_Ready(&SHA256_type) < 0) + return; + Py_INCREF(&SHA256_type); + PyModule_AddObject(module, "sha256_SHA256", (PyObject *)&SHA256_type); + + sha256_error = PyErr_NewException(const_cast("_sha256.Error"), NULL, NULL); + PyModule_AddObject(module, "sha256_Error", sha256_error); + + PyModule_AddStringConstant(module, "sha256___doc__", const_cast(sha256___doc__)); +} diff --git a/src/pycryptopp/hash/sha256module.hpp b/src/pycryptopp/hash/sha256module.hpp new file mode 100644 index 0000000..2dac9b5 --- /dev/null +++ b/src/pycryptopp/hash/sha256module.hpp @@ -0,0 +1,7 @@ +#ifndef __INCL_SHA256MODULE_HPP +#define __INCL_SHA256MODULE_HPP + +extern void +init_sha256(PyObject* module); + +#endif /* #ifndef __INCL_SHA256MODULE_HPP */ diff --git a/src/pycryptopp/publickey/__init__.py b/src/pycryptopp/publickey/__init__.py new file mode 100644 index 0000000..be9d7ad --- /dev/null +++ b/src/pycryptopp/publickey/__init__.py @@ -0,0 +1,3 @@ +import ecdsa, rsa, ed25519 + +quiet_pyflakes=[ecdsa, rsa, ed25519] diff --git a/src/pycryptopp/publickey/ecdsa.py b/src/pycryptopp/publickey/ecdsa.py new file mode 100644 index 0000000..c25ba33 --- /dev/null +++ b/src/pycryptopp/publickey/ecdsa.py @@ -0,0 +1,5 @@ +from pycryptopp import _import_my_names + +_import_my_names(globals(), "ecdsa_") + +del _import_my_names diff --git a/src/pycryptopp/publickey/ecdsamodule.cpp b/src/pycryptopp/publickey/ecdsamodule.cpp new file mode 100644 index 0000000..1ec7eec --- /dev/null +++ b/src/pycryptopp/publickey/ecdsamodule.cpp @@ -0,0 +1,523 @@ +/** +* Things to do: +* Make it work and pass tests. +* compressed pub keys -- check out Wei Dai's example code on mailinglist as linked to from pycryptopp trac by Brian +* Make new KDF (standard, Crypto++-compatible). +* in C++ +* in Python +* use Crypto++ Randomize()'s +* provide RNG class which is P1363-SHA-256 + +* Profit! +* Migrate pair-programming to Bespin. +* Put a Tahoe backend under Bespin. +*/ + +/** + * ecdsamodule.cpp -- Python wrappers around Crypto++'s + * ECDSA(1363)/EMSA1(SHA-256) -- ECDSA. + * + * The keys (192-bit) use the curve ASN1::secp192r1() and SHA-256 as the + * hash function. The Key Derivation Protocol is P1363_KDF2 + * http://www.users.zetnet.co.uk/hopwood/crypto/scan/prf.html#KDF2 + * to generate private (signing) keys from unguessable seeds -- see + * source code for details and doc string for usage. + */ + +#define PY_SSIZE_T_CLEAN +#include +#if (PY_VERSION_HEX < 0x02050000) +typedef int Py_ssize_t; +#endif + +#include + +#include "ecdsamodule.hpp" + +/* from Crypto++ */ +#ifdef DISABLE_EMBEDDED_CRYPTOPP +#include +#include +#include +#include +#include +#include +#include +// only needed for debugging -- the _dump() function +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +// only needed for debugging -- the _dump() function +#include +#include +#include +#endif + +static const int KEY_SIZE_BITS=192; + +USING_NAMESPACE(CryptoPP) + +static const char*const ecdsa___doc__ = "ecdsa -- ECDSA(1363)/EMSA1(Tiger) signatures\n\ +\n\ +To create a new ECDSA signing key (deterministically from a 12-byte seed), construct an instance of the class, passing the seed as argument, i.e. SigningKey(seed).\n\ +\n\ +To get a verifying key from a signing key, call get_verifying_key() on the signing key instance.\n\ +\n\ +To deserialize an ECDSA verifying key from a string, call VerifyingKey(serialized_verifying_key)."; + +static PyObject *ecdsa_error; + +typedef struct { + PyObject_HEAD + + /* internal */ + ECDSA::Verifier *k; +} VerifyingKey; + +PyDoc_STRVAR(VerifyingKey__doc__, +"an ECDSA verifying key"); + +static int +VerifyingKey___init__(PyObject* self, PyObject* args, PyObject* kwdict) { + static const char *kwlist[] = { "serializedverifyingkey", NULL }; + const char *serializedverifyingkey; + Py_ssize_t serializedverifyingkeysize = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#:VerifyingKey__init__", const_cast(kwlist), &serializedverifyingkey, &serializedverifyingkeysize)) + return NULL; + assert (serializedverifyingkeysize >= 0); + + if (serializedverifyingkeysize != 25) { + PyErr_Format(ecdsa_error, "Precondition violation: size in bits is required to be %d (for %d-bit key), but it was %Zd", 25, KEY_SIZE_BITS, serializedverifyingkeysize); + return -1; + } + + VerifyingKey *mself = reinterpret_cast(self); + + StringSource ss(reinterpret_cast(serializedverifyingkey), serializedverifyingkeysize, true); + + ECP::Element element; + DL_GroupParameters_EC params(ASN1::secp192r1()); + params.SetPointCompression(true); + try { + element = params.DecodeElement(reinterpret_cast(serializedverifyingkey), true); + mself->k = new ECDSA::Verifier(params, element); + if (!mself->k) { + PyErr_NoMemory(); + return -1; + } + } catch (InvalidDataFormat le) { + PyErr_Format(ecdsa_error, "Serialized verifying key was corrupted. Crypto++ gave this exception: %s", le.what()); + return -1; + } + + return 0; +} + +static void +VerifyingKey_dealloc(VerifyingKey* self) { + if (self->k) + delete self->k; + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject * +VerifyingKey_verify(VerifyingKey *self, PyObject *args, PyObject *kwdict) { + static const char *kwlist[] = { "msg", "signature", NULL }; + const char *msg; + Py_ssize_t msgsize; + const char *signature; + Py_ssize_t signaturesize = 0; + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#t#:verify", const_cast(kwlist), &msg, &msgsize, &signature, &signaturesize)) + return NULL; + assert (msgsize >= 0); + assert (signaturesize >= 0); + + if (self->k->VerifyMessage(reinterpret_cast(msg), msgsize, reinterpret_cast(signature), signaturesize)) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + +PyDoc_STRVAR(VerifyingKey_verify__doc__, +"Return whether the signature is a valid signature on the msg."); + +static PyObject * +VerifyingKey_serialize(VerifyingKey *self, PyObject *dummy) { + ECDSA::Verifier *pubkey; + pubkey = new ECDSA::Verifier(*(self->k)); + const DL_GroupParameters_EC& params = pubkey->GetKey().GetGroupParameters(); + + Py_ssize_t len = params.GetEncodedElementSize(true); + PyObject* result = PyString_FromStringAndSize(NULL, len); + if (!result) + return NULL; + + params.EncodeElement(true, pubkey->GetKey().GetPublicElement(), + reinterpret_cast(PyString_AS_STRING(result))); + + return result; +} + +PyDoc_STRVAR(VerifyingKey_serialize__doc__, +"Return a string containing the key material. The string can be passed to \n\ +the constructor of VerifyingKey to instantiate a new copy of this key."); + +static PyMethodDef VerifyingKey_methods[] = { + {"verify", reinterpret_cast(VerifyingKey_verify), METH_KEYWORDS, VerifyingKey_verify__doc__}, + {"serialize", reinterpret_cast(VerifyingKey_serialize), METH_NOARGS, VerifyingKey_serialize__doc__}, + {NULL}, +}; + +static PyTypeObject VerifyingKey_type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "ecdsa.VerifyingKey", /*tp_name*/ + sizeof(VerifyingKey), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)VerifyingKey_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + VerifyingKey__doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + VerifyingKey_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + VerifyingKey___init__, /* tp_init */ +}; + +typedef struct { + PyObject_HEAD + + /* internal */ + ECDSA::Signer *k; +} SigningKey; + +static void +SigningKey_dealloc(SigningKey* self) { + if (self->k) + delete self->k; + self->ob_type->tp_free((PyObject*)self); +} + +static const char* TAG_AND_SALT = "102:pycryptopp v0.5.3 key derivation algorithm using Tiger hash to generate ECDSA 192-bit secret exponents," \ + "16:H1yGNvUONoc0FD1d,"; +static const size_t TAG_AND_SALT_len = 127; + +/** copied from Crypto++'s integer.cpp */ +/** The following is in Crypto++'s integer.cpp and we use them: +* void Integer::Randomize(RandomNumberGenerator &rng, size_t nbits) +* { +* const size_t nbytes = nbits/8 + 1; +* SecByteBlock buf(nbytes); +* rng.GenerateBlock(buf, nbytes); +* if (nbytes) +* buf[0] = (byte)Crop(buf[0], nbits % 8); +* Decode(buf, nbytes, UNSIGNED); +* } +* void Integer::Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max) +* { +* if (min > max) +* throw InvalidArgument("Integer: Min must be no greater than Max"); +* +* Integer range = max - min; +* const unsigned int nbits = range.BitCount(); +* +* do +* { +* Randomize(rng, nbits); +* } +* while (*this > range); +* +* *this += min; +* } +* +*/ + +static int +SigningKey___init__(PyObject* self, PyObject* args, PyObject* kwdict) { + static const char *kwlist[] = { "seed", NULL }; + const char* seed; + Py_ssize_t seedlen; + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#:SigningKey___init__", const_cast(kwlist), &seed, &seedlen)) { + return -1; + } + + if (seedlen != 12) { + PyErr_Format(ecdsa_error, "Precondition violation: seed is required to be of length 12, but it was %zd", seedlen); + return -1; + } + + OID curve; + Integer grouporderm1; + byte privexpbytes[24] = {0}; + Integer privexponentm1; + privexponentm1.Decode(privexpbytes, sizeof(privexpbytes)); assert (privexponentm1 == 0); // just checking.. + + DL_GroupParameters_EC params(ASN1::secp192r1()); + params.SetPointCompression(true); + grouporderm1 = params.GetGroupOrder() - 1; + Tiger t; + + t.Update(reinterpret_cast(TAG_AND_SALT), TAG_AND_SALT_len); + t.Update(reinterpret_cast(seed), seedlen); + t.TruncatedFinal(privexpbytes, Tiger::DIGESTSIZE); + privexponentm1.Decode(privexpbytes, sizeof(privexpbytes)); + + while (privexponentm1 >= grouporderm1) { + Tiger t2; + t2.Update(reinterpret_cast(TAG_AND_SALT), TAG_AND_SALT_len); + std::cerr << "WHEE " << sizeof(privexpbytes) << "\n";std::cerr.flush(); + t2.Update(privexpbytes, sizeof(privexpbytes)); + t2.TruncatedFinal(privexpbytes, Tiger::DIGESTSIZE); + privexponentm1.Decode(privexpbytes, sizeof(privexpbytes)); + } + + SigningKey* mself = reinterpret_cast(self); + + mself->k = new ECDSA::Signer(params, privexponentm1+1); + + if (!mself->k) { + PyErr_NoMemory(); + return -1; + } + + return 0; +} + +PyDoc_STRVAR(SigningKey__init____doc__, +"Create a signing key (192 bits) deterministically from the given seed.\n\ +\n\ +This implies that if someone can guess the seed then they can learn the signing key. A good way to get an unguessable seed is os.urandom(12).\n\ +\n\ +@param seed seed\n\ +\n\ +@precondition len(seed) >= ceil(sizeinbits/16.0)"); + +static PyObject * +SigningKey__dump(SigningKey *self, PyObject *dummy) { + const DL_GroupParameters_EC& gp = self->k->GetKey().GetGroupParameters(); + std::cout << "whee " << gp.GetEncodedElementSize(true) << "\a"; + std::cout << "booo " << gp.GetEncodedElementSize(false) << "\n"; + + ECPPoint p = gp.GetSubgroupGenerator(); + std::cout << "generator " << p.x << ", " << p.y << "\n"; + + std::cout << "GroupOrder: "; + std::cout << gp.GetGroupOrder(); + std::cout << "\n"; + + std::string s; + StringSink* ss = new StringSink(s); + HexEncoder he(ss); + std::cout << "AlgorithmID: "; + gp.GetAlgorithmID().DEREncode(he); + std::cout << s << "\n"; + + const ECP& ec = gp.GetCurve(); + Integer fieldsize = ec.FieldSize(); + std::cout << "field size " << fieldsize.BitCount() << " " << fieldsize.ByteCount() << " " << ec.FieldSize() << "\n"; + std::cout << "Curve: "; + std::cout << "curve field max element bit length: " << ec.GetField().MaxElementBitLength() << "\n"; + std::cout << "curve field modulus: " << ec.GetField().GetModulus() << "\n"; + std::cout << "curve A: " << ec.GetA() << ", curve B: " << ec.GetB(); + + const ECP::Field& f = ec.GetField(); + std::cout << "curve field modulus: " << f.GetModulus() << "\n"; + std::cout << "curve field identity: " << f.Identity() << "\n"; + + std::string cfs; + StringSink* cfss = new StringSink(cfs); + HexEncoder cfhe(cfss); + f.DEREncode(cfhe); + std::cout << "curve field derencoding: " << cfs << "\n"; + + const CryptoMaterial& cm = self->k->GetMaterial(); + Integer i; + cm.GetValue("SubgroupOrder", i); + std::cout << "\n"; + std::cout << "SubgroupOrder: "; + std::cout << i; + std::cout << "\n"; + ECP::Element e; + cm.GetValue("SubgroupGenerator", e); + std::cout << "SubgroupGenerator: "; + std::cout << e.x << ", " << e.y; + std::cout << "\n"; + + std::cout << "private key: "; + + const PrivateKey& privkey = self->k->GetPrivateKey(); + + std::cout << privkey.GetValueNames() << "\n"; + + Integer privi; + privkey.GetValue("PrivateExponent", privi); + std::cout << privi << "\n"; + std::cout << "numbits: " << privi.BitCount() << "\n"; + std::cout << "numbytes: " << privi.ByteCount() << "\n"; + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(SigningKey__dump__doc__, +"Print to stdout some descriptions of the math pieces."); + +static PyObject * +SigningKey_sign(SigningKey *self, PyObject *msgobj) { + const char *msg; + Py_ssize_t msgsize; + PyString_AsStringAndSize(msgobj, const_cast(&msg), reinterpret_cast(&msgsize)); + assert (msgsize >= 0); + + Py_ssize_t sigsize; + sigsize = self->k->SignatureLength(); + + PyStringObject* result = reinterpret_cast(PyString_FromStringAndSize(NULL, sigsize)); + if (!result) + return NULL; + assert (sigsize >= 0); + + AutoSeededRandomPool randpool(false); //XXX + + Py_ssize_t siglengthwritten; + try { + siglengthwritten = self->k->SignMessage( + randpool, + reinterpret_cast(msg), + msgsize, + reinterpret_cast(PyString_AS_STRING(result))); + } catch (InvalidDataFormat le) { + Py_DECREF(result); + return PyErr_Format(ecdsa_error, "Signing key was corrupted. Crypto++ gave this exception: %s", le.what()); + } + + if (siglengthwritten < sigsize) + fprintf(stderr, "%s: %d: %s: %s", __FILE__, __LINE__, "SigningKey_sign", "INTERNAL ERROR: signature was shorter than expected."); + else if (siglengthwritten > sigsize) { + fprintf(stderr, "%s: %d: %s: %s", __FILE__, __LINE__, "SigningKey_sign", "INTERNAL ERROR: signature was longer than expected, so memory was invalidly overwritten."); + abort(); + } + assert (siglengthwritten >= 0); + + return reinterpret_cast(result); +} + +PyDoc_STRVAR(SigningKey_sign__doc__, + "Return a signature on the argument."); //XXX If randseed is not None then it is required to be an "); // XXX randseed! + +static PyObject * +SigningKey_get_verifying_key(SigningKey *self, PyObject *dummy) { + VerifyingKey *verifier = PyObject_New(VerifyingKey, &VerifyingKey_type); + if (!verifier) + return NULL; + + verifier->k = new ECDSA::Verifier(*(self->k)); + if (!verifier->k) + return PyErr_NoMemory(); + verifier->k->AccessKey().AccessGroupParameters().SetPointCompression(true); + + return reinterpret_cast(verifier); +} + +PyDoc_STRVAR(SigningKey_get_verifying_key__doc__, +"Return the corresponding verifying key."); + +static PyMethodDef SigningKey_methods[] = { + {"sign", reinterpret_cast(SigningKey_sign), METH_O, SigningKey_sign__doc__}, + {"_dump", reinterpret_cast(SigningKey__dump), METH_NOARGS, SigningKey__dump__doc__}, + {"get_verifying_key", reinterpret_cast(SigningKey_get_verifying_key), METH_NOARGS, SigningKey_get_verifying_key__doc__}, + {NULL}, +}; + +static PyTypeObject SigningKey_type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "ecdsa.SigningKey", /*tp_name*/ + sizeof(SigningKey), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)SigningKey_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + SigningKey__init____doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + SigningKey_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + SigningKey___init__, /* tp_init */ +}; + +void +init_ecdsa(PyObject*const module) { + VerifyingKey_type.tp_new = PyType_GenericNew; + if (PyType_Ready(&VerifyingKey_type) < 0) + return; + Py_INCREF(&VerifyingKey_type); + PyModule_AddObject(module, "ecdsa_VerifyingKey", (PyObject *)&VerifyingKey_type); + + SigningKey_type.tp_new = PyType_GenericNew; + if (PyType_Ready(&SigningKey_type) < 0) + return; + Py_INCREF(&SigningKey_type); + PyModule_AddObject(module, "ecdsa_SigningKey", (PyObject *)&SigningKey_type); + + ecdsa_error = PyErr_NewException(const_cast("_ecdsa.Error"), NULL, NULL); + PyModule_AddObject(module, "ecdsa_Error", ecdsa_error); + + PyModule_AddStringConstant(module, "ecdsa___doc__", const_cast(ecdsa___doc__)); +} diff --git a/src/pycryptopp/publickey/ecdsamodule.hpp b/src/pycryptopp/publickey/ecdsamodule.hpp new file mode 100644 index 0000000..ad3c4fc --- /dev/null +++ b/src/pycryptopp/publickey/ecdsamodule.hpp @@ -0,0 +1,7 @@ +#ifndef __INCL_ECDSAMODULE_HPP +#define __INCL_ECDSAMODULE_HPP + +void +init_ecdsa(PyObject* module); + +#endif /* #ifndef __INCL_ECDSAMODULE_HPP */ diff --git a/src/pycryptopp/publickey/ed25519/__init__.py b/src/pycryptopp/publickey/ed25519/__init__.py new file mode 100644 index 0000000..f399769 --- /dev/null +++ b/src/pycryptopp/publickey/ed25519/__init__.py @@ -0,0 +1,7 @@ +from keys import (BadSignatureError, SigningKey, VerifyingKey) + +(BadSignatureError, SigningKey, VerifyingKey) # hush pyflakes + +from _version import get_versions +__version__ = get_versions()['version'] +del get_versions diff --git a/src/pycryptopp/publickey/ed25519/_version.py b/src/pycryptopp/publickey/ed25519/_version.py new file mode 100644 index 0000000..e1d12a1 --- /dev/null +++ b/src/pycryptopp/publickey/ed25519/_version.py @@ -0,0 +1,11 @@ + +# This file was generated by 'versioneer.py' (0.7) from +# revision-control system data, or from the parent directory name of an +# unpacked source archive. Distribution tarballs contain a pre-generated copy +# of this file. + +version_version = '1.0' +version_full = '519b740ca2c67f0ba4c2758ed1c17f11df561ee7' +def get_versions(default={}, verbose=False): + return {'version': version_version, 'full': version_full} + diff --git a/src/pycryptopp/publickey/ed25519/keys.py b/src/pycryptopp/publickey/ed25519/keys.py new file mode 100644 index 0000000..5d7eafb --- /dev/null +++ b/src/pycryptopp/publickey/ed25519/keys.py @@ -0,0 +1,70 @@ +import _ed25519 +BadSignatureError = _ed25519.BadSignatureError + +class SigningKey(object): + # this is how all keys are created + def __init__(self, sk_bytes): + if not isinstance(sk_bytes, type("")): + raise TypeError("must be bytes, not %s" % type(sk_bytes)) + if len(sk_bytes) != 32: + raise ValueError("must be exactly 32 bytes") + vk_bytes, sk_and_vk = _ed25519.publickey(sk_bytes) + assert sk_and_vk[:32] == sk_bytes + assert vk_bytes == sk_and_vk[32:] + self.vk_bytes = vk_bytes + self.sk_and_vk = sk_and_vk + + def __eq__(self, them): + if not isinstance(them, object): return False + return (them.__class__ == self.__class__ + and them.sk_and_vk == self.sk_and_vk) + + def get_verifying_key_bytes(self): + return self.vk_bytes + + def sign(self, msg): + sig_and_msg = _ed25519.sign(msg, self.sk_and_vk) + # the response is R+S+msg + sig_R = sig_and_msg[0:32] + sig_S = sig_and_msg[32:64] + msg_out = sig_and_msg[64:] + sig_out = sig_R + sig_S + assert msg_out == msg + return sig_out + +class VerifyingKey(object): + def __init__(self, vk_bytes): + if not isinstance(vk_bytes, type("")): + raise TypeError("must be bytes, not %s" % type(vk_bytes)) + if len(vk_bytes) != 32: + raise ValueError("must be exactly 32 bytes") + self.vk_bytes = vk_bytes + + def __eq__(self, them): + if not isinstance(them, object): return False + return (them.__class__ == self.__class__ + and them.vk_bytes == self.vk_bytes) + + def verify(self, sig, msg): + assert isinstance(sig, type("")) # string, really bytes + assert len(sig) == 64 + sig_R = sig[:32] + sig_S = sig[32:] + sig_and_msg = sig_R + sig_S + msg + # this might raise BadSignatureError + msg2 = _ed25519.open(sig_and_msg, self.vk_bytes) + assert msg2 == msg + +def selftest(): + from binascii import unhexlify + message = "crypto libraries should always test themselves at powerup" + sk_bytes = unhexlify("548b1f9f938519ad3d527d8c47a1e6ec1439fbec61710b245363865c6f234899") + sk = SigningKey(sk_bytes) + vk_bytes = unhexlify("787162d9ad1ad571237681560c1ad653fb7df9e09e637e6a8072e4520fd288ca") + vk = VerifyingKey(vk_bytes) + assert sk.get_verifying_key_bytes() == vk_bytes + sig = sk.sign(message) + assert sig == "13f42bc2d485e76c7cfaad25e1a840ede25b44a73befb0a528d836d7b434cf87e260c09d980388fab4cb564885857ea4dc3fb04107ca74960cc5a4d415fbf50d".decode('hex'), sig + vk.verify(sig, message) + +selftest() diff --git a/src/pycryptopp/publickey/rsa.py b/src/pycryptopp/publickey/rsa.py new file mode 100644 index 0000000..bb498a5 --- /dev/null +++ b/src/pycryptopp/publickey/rsa.py @@ -0,0 +1,5 @@ +from pycryptopp import _import_my_names + +_import_my_names(globals(), "rsa_") + +del _import_my_names diff --git a/src/pycryptopp/publickey/rsamodule.cpp b/src/pycryptopp/publickey/rsamodule.cpp new file mode 100644 index 0000000..f423017 --- /dev/null +++ b/src/pycryptopp/publickey/rsamodule.cpp @@ -0,0 +1,393 @@ +/** + * rsamodule.cpp -- Python wrappers around Crypto++'s RSA-PSS-SHA256 + * more precisely: + * PSS-MGF1 + * with RSA as the public key algorithm and SHA-256 as the hash function + */ + +#define PY_SSIZE_T_CLEAN +#include +#if (PY_VERSION_HEX < 0x02050000) +typedef int Py_ssize_t; +#endif + +#include "rsamodule.hpp" + +/* from Crypto++ */ +#ifdef DISABLE_EMBEDDED_CRYPTOPP +#include +#include +#include +#include +#else +#include +#include +#include +#include +#endif + +USING_NAMESPACE(CryptoPP) + +static const char*const rsa___doc__ = "_rsa -- RSA-PSS-SHA256 signatures\n\ +\n\ +To create a new RSA signing key from the operating system's random number generator, call generate().\n\ +To deserialize an RSA signing key from a string, call create_signing_key_from_string().\n\ +\n\ +To get an RSA verifying key from an RSA signing key, call get_verifying_key() on the signing key.\n\ +To deserialize an RSA verifying key from a string, call create_verifying_key_from_string()."; + +static PyObject *rsa_error; + +typedef struct { + PyObject_HEAD + + /* internal */ + RSASS::Verifier *k; +} VerifyingKey; + +PyDoc_STRVAR(VerifyingKey__doc__, +"an RSA verifying key"); + +static void +VerifyingKey_dealloc(VerifyingKey* self) { + if (self->k) + delete self->k; + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject * +VerifyingKey_verify(VerifyingKey *self, PyObject *args, PyObject *kwdict) { + static const char *kwlist[] = { "msg", "signature", NULL }; + const char *msg; + Py_ssize_t msgsize; + const char *signature; + Py_ssize_t signaturesize = 0; + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#t#:verify", const_cast(kwlist), &msg, &msgsize, &signature, &signaturesize)) + return NULL; + assert (msgsize >= 0); + assert (signaturesize >= 0); + + Py_ssize_t sigsize = self->k->SignatureLength(); + if (sigsize != signaturesize) + return PyErr_Format(rsa_error, "Precondition violation: signatures are required to be of size %zu, but it was %zu", sigsize, signaturesize); + assert (sigsize >= 0); + + assert (signaturesize == sigsize); + + if (self->k->VerifyMessage(reinterpret_cast(msg), msgsize, reinterpret_cast(signature), signaturesize)) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + +PyDoc_STRVAR(VerifyingKey_verify__doc__, +"Return whether the signature is a valid signature on the msg."); + +static PyObject * +VerifyingKey_serialize(VerifyingKey *self, PyObject *dummy) { + std::string outstr; + StringSink ss(outstr); + self->k->DEREncode(ss); + PyStringObject* result = reinterpret_cast(PyString_FromStringAndSize(outstr.c_str(), outstr.size())); + if (!result) + return NULL; + + return reinterpret_cast(result); +} + +PyDoc_STRVAR(VerifyingKey_serialize__doc__, +"Return a string containing the key material. The string can be passed to \n\ +create_verifying_key_from_string() to instantiate a new copy of this key."); + +static PyMethodDef VerifyingKey_methods[] = { + {"verify", reinterpret_cast(VerifyingKey_verify), METH_KEYWORDS, VerifyingKey_verify__doc__}, + {"serialize", reinterpret_cast(VerifyingKey_serialize), METH_NOARGS, VerifyingKey_serialize__doc__}, + {NULL}, +}; + +static PyTypeObject VerifyingKey_type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "_rsa.VerifyingKey", /*tp_name*/ + sizeof(VerifyingKey), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + reinterpret_cast(VerifyingKey_dealloc), /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + VerifyingKey__doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + VerifyingKey_methods, /* tp_methods */ +}; + +/** This function is only for internal use by rsamodule.cpp. */ +static VerifyingKey* +VerifyingKey_construct() { + VerifyingKey *self = reinterpret_cast(VerifyingKey_type.tp_alloc(&VerifyingKey_type, 0)); + if (!self) + return NULL; + self->k = NULL; + return self; +} + +PyDoc_STRVAR(SigningKey__doc__, +"an RSA signing key"); + +typedef struct { + PyObject_HEAD + + /* internal */ + RSASS::Signer *k; +} SigningKey; + +static void +SigningKey_dealloc(SigningKey* self) { + if (self->k) + delete self->k; + self->ob_type->tp_free((PyObject*)self); +} + +static PyObject * +SigningKey_sign(SigningKey *self, PyObject *msgobj) { + const char *msg; + Py_ssize_t msgsize; + PyString_AsStringAndSize(msgobj, const_cast(&msg), reinterpret_cast(&msgsize)); + assert (msgsize >= 0); + + Py_ssize_t sigsize = self->k->SignatureLength(); + PyStringObject* result = reinterpret_cast(PyString_FromStringAndSize(NULL, sigsize)); + if (!result) + return NULL; + assert (sigsize >= 0); + + AutoSeededRandomPool randpool(false); + Py_ssize_t siglengthwritten = self->k->SignMessage( + randpool, + reinterpret_cast(msg), + msgsize, + reinterpret_cast(PyString_AS_STRING(result))); + if (siglengthwritten < sigsize) + fprintf(stderr, "%s: %d: %s: %s", __FILE__, __LINE__, "SigningKey_sign", "INTERNAL ERROR: signature was shorter than expected."); + else if (siglengthwritten > sigsize) { + fprintf(stderr, "%s: %d: %s: %s", __FILE__, __LINE__, "SigningKey_sign", "INTERNAL ERROR: signature was longer than expected, so invalid memory was overwritten."); + abort(); + } + assert (siglengthwritten >= 0); + + return reinterpret_cast(result); +} + +PyDoc_STRVAR(SigningKey_sign__doc__, +"Return a signature on the argument."); + +static PyObject * +SigningKey_get_verifying_key(SigningKey *self, PyObject *dummy) { + VerifyingKey *verifier = reinterpret_cast(VerifyingKey_construct()); + if (!verifier) + return NULL; + + verifier->k = new RSASS::Verifier(*(self->k)); + if (!verifier->k) + return PyErr_NoMemory(); + return reinterpret_cast(verifier); +} + +PyDoc_STRVAR(SigningKey_get_verifying_key__doc__, +"Return the corresponding verifying key."); + +static PyObject * +SigningKey_serialize(SigningKey *self, PyObject *dummy) { + std::string outstr; + StringSink ss(outstr); + self->k->DEREncode(ss); + PyStringObject* result = reinterpret_cast(PyString_FromStringAndSize(outstr.c_str(), outstr.size())); + if (!result) + return NULL; + + return reinterpret_cast(result); +} + +PyDoc_STRVAR(SigningKey_serialize__doc__, +"Return a string containing the key material. The string can be passed to \n\ +create_signing_key_from_string() to instantiate a new copy of this key."); + +static PyMethodDef SigningKey_methods[] = { + {"sign", reinterpret_cast(SigningKey_sign), METH_O, SigningKey_sign__doc__}, + {"get_verifying_key", reinterpret_cast(SigningKey_get_verifying_key), METH_NOARGS, SigningKey_get_verifying_key__doc__}, + {"serialize", reinterpret_cast(SigningKey_serialize), METH_NOARGS, SigningKey_serialize__doc__}, + {NULL}, +}; + +static PyTypeObject SigningKey_type = { + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "_rsa.SigningKey", /*tp_name*/ + sizeof(SigningKey), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)SigningKey_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + SigningKey__doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + SigningKey_methods /* tp_methods */ +}; + +/** This function is only for internal use by rsamodule.cpp. */ +static SigningKey* +SigningKey_construct() { + SigningKey *self = reinterpret_cast(SigningKey_type.tp_alloc(&SigningKey_type, 0)); + if (!self) + return NULL; + self->k = NULL; + return self; +} + +// static const int MIN_KEY_SIZE_BITS=3675; /* according to Lenstra 2001 "Unbelievable security: Matching AES security using public key systems", you should use RSA keys of length 3675 bits if you want it to be as hard to factor your RSA key as to brute-force your AES-128 key in the year 2030. */ +static const int MIN_KEY_SIZE_BITS=522; /* minimum that can do PSS-SHA256 -- totally insecure and allowed only for faster unit tests */ + +PyObject * +rsa_generate(PyObject *dummy, PyObject *args, PyObject *kwdict) { + static const char *kwlist[] = { + "sizeinbits", + NULL + }; + int sizeinbits; + + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "i:generate", const_cast(kwlist), &sizeinbits)) + return NULL; + + if (sizeinbits < MIN_KEY_SIZE_BITS) + return PyErr_Format(rsa_error, "Precondition violation: size in bits is required to be >= %d, but it was %d", MIN_KEY_SIZE_BITS, sizeinbits); + + AutoSeededRandomPool osrng(false); + SigningKey *signer = SigningKey_construct(); + if (!signer) + return NULL; + signer->k = new RSASS::Signer(osrng, sizeinbits); + if (!signer->k) + return PyErr_NoMemory(); + return reinterpret_cast(signer); +} + +const char*const rsa_generate__doc__ = "Create a signing key using the operating system's random number generator.\n\ +\n\ +@param sizeinbits size of the key in bits\n\ +\n\ +@precondition sizeinbits >= 522"; + +PyObject * +rsa_create_verifying_key_from_string(PyObject *dummy, PyObject *args, PyObject *kwdict) { + static const char *kwlist[] = { + "serializedverifyingkey", + NULL + }; + const char *serializedverifyingkey; + Py_ssize_t serializedverifyingkeysize = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#:create_verifying_key_from_string", const_cast(kwlist), &serializedverifyingkey, &serializedverifyingkeysize)) + return NULL; + assert (serializedverifyingkeysize >= 0); + + VerifyingKey *verifier = reinterpret_cast(VerifyingKey_construct()); + if (!verifier) + return NULL; + StringSource ss(reinterpret_cast(serializedverifyingkey), serializedverifyingkeysize, true); + + try { + verifier->k = new RSASS::Verifier(ss); + } catch (CryptoPP::BERDecodeErr le) { + return PyErr_Format(rsa_error, "Serialized verifying key was corrupted. Crypto++ gave this exception: %s", le.what()); + } + + if (!verifier->k) + return PyErr_NoMemory(); + return reinterpret_cast(verifier); +} + +const char*const rsa_create_verifying_key_from_string__doc__ = "Create a verifying key from its serialized state."; + +PyObject * +rsa_create_signing_key_from_string(PyObject *dummy, PyObject *args, PyObject *kwdict) { + static const char *kwlist[] = { + "serializedsigningkey", + NULL + }; + const char *serializedsigningkey; + Py_ssize_t serializedsigningkeysize = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#:create_signing_key_from_string", const_cast(kwlist), &serializedsigningkey, &serializedsigningkeysize)) + return NULL; + assert (serializedsigningkeysize >= 0); + + SigningKey *signer = SigningKey_construct(); + if (!signer) + return NULL; + StringSource ss(reinterpret_cast(serializedsigningkey), serializedsigningkeysize, true); + + try { + signer->k = new RSASS::Signer(ss); + } catch (CryptoPP::BERDecodeErr le) { + return PyErr_Format(rsa_error, "Serialized signing key was corrupted. Crypto++ gave this exception: %s", le.what()); + } + + if (!signer->k) + return PyErr_NoMemory(); + return reinterpret_cast(signer); +} + +const char*const rsa_create_signing_key_from_string__doc__ = "Create a signing key from its serialized state."; + +void +init_rsa(PyObject*const module) { + VerifyingKey_type.tp_new = PyType_GenericNew; + if (PyType_Ready(&VerifyingKey_type) < 0) + return; + Py_INCREF(&VerifyingKey_type); + PyModule_AddObject(module, "rsa_VerifyingKey", (PyObject *)&VerifyingKey_type); + + SigningKey_type.tp_new = PyType_GenericNew; + if (PyType_Ready(&SigningKey_type) < 0) + return; + Py_INCREF(&SigningKey_type); + PyModule_AddObject(module, "rsa_SigningKey", (PyObject *)&SigningKey_type); + + rsa_error = PyErr_NewException(const_cast("_rsa.Error"), NULL, NULL); + PyModule_AddObject(module, "rsa_Error", rsa_error); + + PyModule_AddStringConstant(module, "rsa___doc__", const_cast(rsa___doc__)); +} diff --git a/src/pycryptopp/publickey/rsamodule.hpp b/src/pycryptopp/publickey/rsamodule.hpp new file mode 100644 index 0000000..30849a2 --- /dev/null +++ b/src/pycryptopp/publickey/rsamodule.hpp @@ -0,0 +1,21 @@ +#ifndef __INCL_RSAMODULE_HPP +#define __INCL_RSAMODULE_HPP + +void +init_rsa(PyObject* module); + +extern PyMethodDef rsa_functions[]; + +extern PyObject * +rsa_generate(PyObject *dummy, PyObject *args, PyObject *kwdict); +extern const char*const rsa_generate__doc__; + +extern PyObject * +rsa_create_verifying_key_from_string(PyObject *dummy, PyObject *args, PyObject *kwdict); +extern const char*const rsa_create_verifying_key_from_string__doc__; + +extern PyObject * +rsa_create_signing_key_from_string(PyObject *dummy, PyObject *args, PyObject *kwdict); +extern const char*const rsa_create_signing_key_from_string__doc__; + +#endif /* #ifndef __INCL_RSAMODULE_HPP */ diff --git a/src/pycryptopp/test/__init__.py b/src/pycryptopp/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/pycryptopp/test/test_aes.py b/src/pycryptopp/test/test_aes.py new file mode 100644 index 0000000..16c3e20 --- /dev/null +++ b/src/pycryptopp/test/test_aes.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python + +import random, re + +import unittest + +from binascii import a2b_hex, b2a_hex + +global VERBOSE +VERBOSE=False + +from pycryptopp.cipher import aes + +from pkg_resources import resource_string, resource_listdir + +from base64 import b32encode +def ab(x): # debuggery + if len(x) >= 3: + return "%s:%s" % (len(x), b32encode(x[-3:]),) + elif len(x) == 2: + return "%s:%s" % (len(x), b32encode(x[-2:]),) + elif len(x) == 1: + return "%s:%s" % (len(x), b32encode(x[-1:]),) + elif len(x) == 0: + return "%s:%s" % (len(x), "--empty--",) + +def randstr(n): + return ''.join(map(chr, map(random.randrange, [0]*n, [256]*n))) + +class AES256(unittest.TestCase): + enc0 = "dc95c078a2408989ad48a21492842087530f8afbc74536b9a963b4f1c4cb738b" + + def test_encrypt_zeroes(self): + cryptor = aes.AES(key="\x00"*32) + ct = cryptor.process("\x00"*32) + self.failUnlessEqual(self.enc0, b2a_hex(ct)) + + def test_init_type_check(self): + self.failUnlessRaises(TypeError, aes.AES, None) + self.failUnlessRaises(aes.Error, aes.AES, "a"*1) # too short + self.failUnlessRaises(aes.Error, aes.AES, "a"*17) # not one of the valid key sizes for AES (16, 24, 32) + + def test_encrypt_zeroes_in_two_parts(self): + cryptor = aes.AES(key="\x00"*32) + ct1 = cryptor.process("\x00"*15) + ct2 = cryptor.process("\x00"*17) + self.failUnlessEqual(self.enc0, b2a_hex(ct1+ct2)) + +class AES128(unittest.TestCase): + enc0 = "66e94bd4ef8a2c3b884cfa59ca342b2e" + + def test_encrypt_zeroes(self): + cryptor = aes.AES(key="\x00"*16) + ct = cryptor.process("\x00"*16) + self.failUnlessEqual(self.enc0, b2a_hex(ct)) + + def test_init_type_check(self): + self.failUnlessRaises(TypeError, aes.AES, None) + self.failUnlessRaises(aes.Error, aes.AES, "a") # too short + + def test_encrypt_zeroes_in_two_parts(self): + cryptor = aes.AES(key="\x00"*16) + ct1 = cryptor.process("\x00"*8) + ct2 = cryptor.process("\x00"*8) + self.failUnlessEqual(self.enc0, b2a_hex(ct1+ct2)) + +def fake_ecb_using_ctr(k, p): + return aes.AES(key=k, iv=p).process('\x00'*16) + +NIST_KAT_VECTS_RE=re.compile("\nCOUNT = ([0-9]+)\nKEY = ([0-9a-f]+)\nPLAINTEXT = ([0-9a-f]+)\nCIPHERTEXT = ([0-9a-f]+)") + +class AES_from_NIST_KAT(unittest.TestCase): + def test_NIST_KAT(self): + for vectname in resource_listdir('pycryptopp', 'testvectors/KAT_AES'): + self._test_KAT_file(resource_string('pycryptopp', '/'.join(['testvectors/KAT_AES', vectname]))) + + def _test_KAT_file(self, vects_str): + for mo in NIST_KAT_VECTS_RE.finditer(vects_str): + key = a2b_hex(mo.group(2)) + plaintext = a2b_hex(mo.group(3)) + ciphertext = a2b_hex(mo.group(4)) + + computedciphertext = fake_ecb_using_ctr(key, plaintext) + self.failUnlessEqual(computedciphertext, ciphertext, "computedciphertext: %s, ciphertext: %s, key: %s, plaintext: %s" % (b2a_hex(computedciphertext), b2a_hex(ciphertext), b2a_hex(key), b2a_hex(plaintext))) + +class AES_from_Niels_Ferguson(unittest.TestCase): + # http://blogs.msdn.com/si_team/archive/2006/05/19/aes-test-vectors.aspx + def _test_from_Niels_AES(self, keysize, result): + E = fake_ecb_using_ctr + b = 16 + k = keysize + S = '\x00' * (k+b) + for i in range(1000): + K = S[-k:] + P = S[-k-b:-k] + S += E(K, E(K, P)) + + self.failUnlessEqual(S[-b:], a2b_hex(result)) + + def test_from_Niels_AES128(self): + return self._test_from_Niels_AES(16, 'bd883f01035e58f42f9d812f2dacbcd8') + + def test_from_Niels_AES256(self): + return self._test_from_Niels_AES(32, 'c84b0f3a2c76dd9871900b07f09bdd3e') + +class PartialIV(unittest.TestCase): + def test_partial(self): + k = "k"*16 + for iv_len in range(0, 16)+range(17,70): # all are wrong, 16 is right + self.failUnlessRaises(aes.Error, + aes.AES, k, iv="i"*iv_len) + +if __name__ == "__main__": + unittest.main() diff --git a/src/pycryptopp/test/test_ecdsa.py b/src/pycryptopp/test/test_ecdsa.py new file mode 100644 index 0000000..d70a000 --- /dev/null +++ b/src/pycryptopp/test/test_ecdsa.py @@ -0,0 +1,263 @@ +#!/usr/bin/env python + +import random +import base64 + +import os +SEED = os.environ.get('REPEATABLE_RANDOMNESS_SEED', None) + +if SEED is None: + # Generate a seed which is fairly short (to ease cut-and-paste, writing it + # down, etc.). Note that Python's random module's seed() function is going + # to take the hash() of this seed, which is a 32-bit value (currently) so + # there is no point in making this seed larger than 32 bits. Make it 30 + # bits, which conveniently fits into six base-32 chars. Include a separator + # because chunking facilitates memory (including working and short-term + # memory) in humans. + chars = "ybndrfg8ejkmcpqxot1uwisza345h769" # Zooko's choice, rationale in "DESIGN" doc in z-base-32 project + SEED = ''.join([random.choice(chars) for x in range(3)] + ['-'] + [random.choice(chars) for x in range(3)]) + +import logging +logging.info("REPEATABLE_RANDOMNESS_SEED: %s\n" % SEED) +logging.info("In order to reproduce this run of the code, set the environment variable \"REPEATABLE_RANDOMNESS_SEED\" to %s before executing.\n" % SEED) +random.seed(SEED) + +def seed_which_refuses(a): + logging.warn("I refuse to reseed to %s -- I already seeded with %s.\n" % (a, SEED,)) + return +random.seed = seed_which_refuses + +from random import randrange + +import unittest + +from pycryptopp.publickey import ecdsa + +def randstr(n, rr=randrange): + return ''.join([chr(rr(0, 256)) for x in xrange(n)]) + +from base64 import b32encode +def ab(x): # debuggery + if len(x) >= 3: + return "%s:%s" % (len(x), b32encode(x[-3:]),) + elif len(x) == 2: + return "%s:%s" % (len(x), b32encode(x[-2:]),) + elif len(x) == 1: + return "%s:%s" % (len(x), b32encode(x[-1:]),) + elif len(x) == 0: + return "%s:%s" % (len(x), "--empty--",) + +def div_ceil(n, d): + """ + The smallest integer k such that k*d >= n. + """ + return (n/d) + (n%d != 0) + +KEYBITS=192 + +# The number of bytes required for a seed to have the same security level as a +# key in this elliptic curve: 2 bits of public key per bit of security. +SEEDBITS=div_ceil(192, 2) +SEEDBYTES=div_ceil(SEEDBITS, 8) + +# The number of bytes required to encode a public key in this elliptic curve. +PUBKEYBYTES=div_ceil(KEYBITS, 8)+1 # 1 byte for the sign of the y component + +# The number of bytes requires to encode a signature in this elliptic curve. +SIGBITS=KEYBITS*2 +SIGBYTES=div_ceil(SIGBITS, 8) + +class Signer(unittest.TestCase): + def test_construct(self): + seed = randstr(SEEDBYTES) + ecdsa.SigningKey(seed) + + def test_sign(self): + seed = randstr(SEEDBYTES) + signer = ecdsa.SigningKey(seed) + sig = signer.sign("message") + self.failUnlessEqual(len(sig), SIGBYTES) + + def test_sign_and_verify(self): + seed = randstr(SEEDBYTES) + signer = ecdsa.SigningKey(seed) + sig = signer.sign("message") + v = signer.get_verifying_key() + self.failUnless(v.verify("message", sig)) + + def test_sign_and_verify_emptymsg(self): + seed = randstr(SEEDBYTES) + signer = ecdsa.SigningKey(seed) + sig = signer.sign("") + v = signer.get_verifying_key() + self.failUnless(v.verify("", sig)) + + def test_construct_from_same_seed_is_reproducible(self): + seed = randstr(SEEDBYTES) + signer1 = ecdsa.SigningKey(seed) + signer2 = ecdsa.SigningKey(seed) + self.failUnlessEqual(signer1.get_verifying_key().serialize(), signer2.get_verifying_key().serialize()) + + # ... and using different seeds constructs a different private key. + seed3 = randstr(SEEDBYTES) + assert seed3 != seed, "Internal error in Python random module's PRNG (or in pycryptopp's hacks to it to facilitate testing) -- got two identical strings from randstr(%s)" % SEEDBYTES + signer3 = ecdsa.SigningKey(seed3) + self.failIfEqual(signer1.get_verifying_key().serialize(), signer3.get_verifying_key().serialize()) + + # Also try the all-zeroes string just because bugs sometimes are + # data-dependent on zero or cause bogus zeroes. + seed4 = '\x00'*SEEDBYTES + assert seed4 != seed, "Internal error in Python random module's PRNG (or in pycryptopp's hacks to it to facilitate testing) -- got the all-zeroes string from randstr(%s)" % SEEDBYTES + signer4 = ecdsa.SigningKey(seed4) + self.failIfEqual(signer4.get_verifying_key().serialize(), signer1.get_verifying_key().serialize()) + + signer5 = ecdsa.SigningKey(seed4) + self.failUnlessEqual(signer5.get_verifying_key().serialize(), signer4.get_verifying_key().serialize()) + + def test_construct_short_seed(self): + try: + ecdsa.SigningKey("\x00\x00\x00") + except ecdsa.Error, le: + self.failUnless("seed is required to be of length " in str(le), le) + else: + self.fail("Should have raised error from seed being too short.") + + def test_construct_bad_arg_type(self): + try: + ecdsa.SigningKey(1) + except TypeError, le: + self.failUnless("must be string" in str(le), le) + else: + self.fail("Should have raised error from seed being of the wrong type.") + +class Verifier(unittest.TestCase): + def test_from_signer_and_serialize_and_deserialize(self): + seed = randstr(SEEDBYTES) + signer = ecdsa.SigningKey(seed) + + verifier = signer.get_verifying_key() + s1 = verifier.serialize() + self.failUnlessEqual(len(s1), PUBKEYBYTES) + ecdsa.VerifyingKey(s1) + s2 = verifier.serialize() + self.failUnlessEqual(s1, s2) + +def flip_one_bit(s): + assert s + i = randrange(0, len(s)) + result = s[:i] + chr(ord(s[i])^(0x01<= 3: + return "%s:%s" % (len(x), b32encode(x[-3:]),) + elif len(x) == 2: + return "%s:%s" % (len(x), b32encode(x[-2:]),) + elif len(x) == 1: + return "%s:%s" % (len(x), b32encode(x[-1:]),) + elif len(x) == 0: + return "%s:%s" % (len(x), "--empty--",) + +def randstr(n): + return ''.join(map(chr, map(random.randrange, [0]*n, [256]*n))) + +KEYSIZE=522 # 522 bits is far too few for actual security -- it is used only for faster unit tests + +class Signer(unittest.TestCase): + def test_generate_bad_size(self): + try: + rsa.generate(KEYSIZE-1) + except rsa.Error, le: + self.failUnless("size in bits is required to be >=" in str(le), le) + else: + self.fail("Should have raised error from size being too small.") + try: + rsa.generate(sizeinbits=KEYSIZE-1) + except rsa.Error, le: + self.failUnless("size in bits is required to be >=" in str(le), le) + else: + self.fail("Should have raised error from size being too small.") + + def test_generate(self): + rsa.generate(KEYSIZE) + # Hooray! It didn't raise an exception! We win! + rsa.generate(sizeinbits=KEYSIZE) + # Hooray! It didn't raise an exception! We win! + + def test_sign(self): + signer = rsa.generate(KEYSIZE) + result = signer.sign("abc") + self.failUnlessEqual(len(result), ((KEYSIZE+7)/8)) + # TODO: test against RSAInc. test vectors. + + def test_create_from_string_invalid(self): + try: + rsa.create_signing_key_from_string("invalid string") + except rsa.Error, le: + self.failUnless("decode error" in str(le), le) + else: + self.fail("Should have raised error from invalid string") + + try: + rsa.create_verifying_key_from_string("invalid string") + except rsa.Error, le: + self.failUnless("decode error" in str(le), le) + else: + self.fail("Should have raised error from invalid string") + +class SignAndVerify(unittest.TestCase): + def _help_test_sign_and_check(self, signer, verifier, msg): + sig = signer.sign(msg) + self.failUnlessEqual(len(sig), ((KEYSIZE+7)/8)) + self.failUnless(verifier.verify(msg, sig)) + + def test_sign_and_check_a(self): + signer = rsa.generate(KEYSIZE) + verifier = signer.get_verifying_key() + return self._help_test_sign_and_check(signer, verifier, "a") + + def _help_test_sign_and_check_random(self, signer, verifier): + for i in range(3): + l = random.randrange(0, 2**10) + msg = randstr(l) + self._help_test_sign_and_check(signer, verifier, msg) + + def test_sign_and_check_random(self): + signer = rsa.generate(KEYSIZE) + verifier = signer.get_verifying_key() + return self._help_test_sign_and_check_random(signer, verifier) + + def _help_test_sign_and_failcheck(self, signer, verifier, msg): + sig = signer.sign("a") + sig = sig[:-1] + chr(ord(sig[-1])^0x01) + self.failUnless(not verifier.verify(msg, sig)) + + def test_sign_and_failcheck_a(self): + signer = rsa.generate(KEYSIZE) + verifier = signer.get_verifying_key() + return self._help_test_sign_and_failcheck(signer, verifier, "a") + + def _help_test_sign_and_failcheck_random(self, signer, verifier): + for i in range(3): + l = random.randrange(0, 2**10) + msg = randstr(l) + self._help_test_sign_and_failcheck(signer, verifier, msg) + + def test_sign_and_failcheck_random(self): + signer = rsa.generate(KEYSIZE) + verifier = signer.get_verifying_key() + return self._help_test_sign_and_failcheck_random(signer, verifier) + + def test_serialize_and_deserialize_verifying_key_and_test(self): + signer = rsa.generate(KEYSIZE) + verifier = signer.get_verifying_key() + serstr = verifier.serialize() + verifier = None + newverifier = rsa.create_verifying_key_from_string(serstr) + self._help_test_sign_and_check(signer, newverifier, "a") + self._help_test_sign_and_check_random(signer, newverifier) + self._help_test_sign_and_failcheck(signer, newverifier, "a") + self._help_test_sign_and_failcheck_random(signer, newverifier) + + def test_serialize_and_deserialize_signing_key_and_test(self): + signer = rsa.generate(KEYSIZE) + verifier = signer.get_verifying_key() + serstr = signer.serialize() + signer = None + newsigner = rsa.create_signing_key_from_string(serstr) + self._help_test_sign_and_check(newsigner, verifier, "a") + self._help_test_sign_and_check_random(newsigner, verifier) + self._help_test_sign_and_failcheck(newsigner, verifier, "a") + self._help_test_sign_and_failcheck_random(newsigner, verifier) + + +if __name__ == "__main__": + unittest.main() diff --git a/src/pycryptopp/test/test_sha256.py b/src/pycryptopp/test/test_sha256.py new file mode 100644 index 0000000..5e982dc --- /dev/null +++ b/src/pycryptopp/test/test_sha256.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python + +import random, re + +import unittest + +from binascii import b2a_hex, a2b_hex + +global VERBOSE +VERBOSE=False + +from pycryptopp.hash import sha256 + +from pkg_resources import resource_string + +def resource_string_lines(pkgname, resname): + return split_on_newlines(resource_string(pkgname, resname)) + +from base64 import b32encode +def ab(x): # debuggery + if len(x) >= 3: + return "%s:%s" % (len(x), b32encode(x[-3:]),) + elif len(x) == 2: + return "%s:%s" % (len(x), b32encode(x[-2:]),) + elif len(x) == 1: + return "%s:%s" % (len(x), b32encode(x[-1:]),) + elif len(x) == 0: + return "%s:%s" % (len(x), "--empty--",) + +def randstr(n): + return ''.join(map(chr, map(random.randrange, [0]*n, [256]*n))) + +h0 = a2b_hex("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") +h_bd = a2b_hex("68325720aabd7c82f30f554b313d0570c95accbb7dc4b5aae11204c08ffe732b") +h_5fd4 = a2b_hex("7c4fbf484498d21b487b9d61de8914b2eadaf2698712936d47c3ada2558f6788") + +class SHA256(unittest.TestCase): + def test_digest(self): + empty_digest = sha256.SHA256().digest() + self.failUnless(isinstance(empty_digest, str)) + self.failUnlessEqual(len(empty_digest), 32) + self.failUnlessEqual(empty_digest, h0) + + def test_hexdigest(self): + empty_hexdigest = sha256.SHA256().hexdigest() + self.failUnlessEqual(a2b_hex(empty_hexdigest), h0) + test_hexdigest.todo = "Not yet implemented: SHA256.hexdigest()." + + def test_onebyte_1(self): + d = sha256.SHA256("\xbd").digest() + self.failUnlessEqual(d, h_bd) + + def test_onebyte_2(self): + s = sha256.SHA256() + s.update("\xbd") + d = s.digest() + self.failUnlessEqual(d, h_bd) + + def test_update(self): + s = sha256.SHA256("\x5f") + s.update("\xd4") + d = s.digest() + self.failUnlessEqual(d, h_5fd4) + + def test_constructor_type_check(self): + self.failUnlessRaises(TypeError, sha256.SHA256, None) + + def test_update_type_check(self): + h = sha256.SHA256() + self.failUnlessRaises(TypeError, h.update, None) + + def test_digest_twice(self): + h = sha256.SHA256() + d1 = h.digest() + self.failUnless(isinstance(d1, str)) + d2 = h.digest() + self.failUnlessEqual(d1, d2) + + def test_digest_then_update_fail(self): + h = sha256.SHA256() + h.digest() + try: + h.update("oops") + except sha256.Error, le: + self.failUnless("digest() has been called" in str(le), le) + + def test_chunksize(self): + # hashes can be computed on arbitrarily-sized chunks + problems = False + for length in range(2, 140): + s = "a"*length + expected = sha256.SHA256(s).hexdigest() + for a in range(0, length): + h = sha256.SHA256() + h.update(s[:a]) + h.update(s[a:]) + got = h.hexdigest() + if got != expected: + problems = True + print len(s[:a]), len(s[a:]), len(s), got, expected + self.failIf(problems) + + def test_recursive_different_chunksizes(self): + """ + Test that updating a hasher with various sized inputs yields + the expected answer. This is somewhat redundant with + test_chunksize(), but that's okay. This one exercises some + slightly different situations (such as finalizing a hash after + different length inputs.) This one is recursive so that there + is a single fixed result that we expect. + """ + hx = sha256.SHA256() + s = ''.join([ chr(c) for c in range(65) ]) + for i in range(0, 65): + hy = sha256.SHA256(s[:i]).digest() + hx.update(hy) + for i in range(0, 65): + hx.update(chr(0xFE)) + hx.update(s[:64]) + self.failUnlessEqual(hx.hexdigest().lower(), '5191c7841dd4e16aa454d40af924585dffc67157ffdbfd0236acddd07901629d') + + +VECTS_RE=re.compile("\nLen = ([0-9]+)\nMsg = ([0-9a-f]+)\nMD = ([0-9a-f]+)") + +# split_on_newlines() copied from pyutil.strutil +def split_on_newlines(s): + """ + Splits s on all of the three newline sequences: "\r\n", "\r", or "\n". + """ + res = [] + for x in s.split('\r\n'): + for y in x.split('\r'): + res.extend(y.split('\n')) + return res + +class SHSVectors(unittest.TestCase): + """ + All of the SHA-256 test vectors from the NIST SHS, in the files distributed + by NIST. (NIST distributes them in a .zip, but we expect them to be + unpacked and in a subdirectory named 'testvectors'). + """ + def test_short(self): + return self._test_vect(resource_string('pycryptopp', 'testvectors/SHA256ShortMsg.txt')) + + def test_long(self): + return self._test_vect(resource_string('pycryptopp', 'testvectors/SHA256LongMsg.txt')) + + def _test_vect(self, vects_str): + for mo in VECTS_RE.finditer(vects_str): + msglenbits = int(mo.group(1)) + assert msglenbits % 8 == 0 + msglen = msglenbits / 8 + msg = a2b_hex(mo.group(2))[:msglen] # The slice is necessary because NIST seems to think that "00" is a reasonable representation for the zero-length string. + assert len(msg) == msglen, (len(msg), msglen) + md = a2b_hex(mo.group(3)) + + computed_md = sha256.SHA256(msg).digest() + self.failUnlessEqual(computed_md, md) + + def test_monte(self): + inlines = resource_string_lines('pycryptopp', 'testvectors/SHA256Monte.txt') + for line in inlines: + line = line.strip() + if line[:7] == 'Seed = ': + seed = a2b_hex(line[7:]) + break + + j = 0 + for line in inlines: + line = line.strip() + if line[:8] == 'COUNT = ': + assert int(line[8:]) == j + elif line[:5] == 'MD = ': + mds = [] + mds.append(seed);mds.append(seed);mds.append(seed); + for i in range(1000): + m = mds[-3]+mds[-2]+mds[-1] + mds.append(sha256.SHA256(m).digest()) + seed = mds[-1] + self.failUnlessEqual(line[5:], b2a_hex(seed)) + j += 1 diff --git a/src/pycryptopp/test/test_xsalsa20.py b/src/pycryptopp/test/test_xsalsa20.py new file mode 100644 index 0000000..f3ee02a --- /dev/null +++ b/src/pycryptopp/test/test_xsalsa20.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python + +import random, re +import unittest + +from binascii import a2b_hex, b2a_hex +from pkg_resources import resource_string + +from pycryptopp.cipher import xsalsa20 +TEST_XSALSA_RE=re.compile("\nCOUNT=([0-9]+)\nKEY=([0-9a-f]+)\nIV=([0-9a-f]+)\nPLAINTEXT=([0-9a-f]+)\nCIPHERTEXT=([0-9a-f]+)") + +class XSalsa20Test(unittest.TestCase): + + enc0="eea6a7251c1e72916d11c2cb214d3c252539121d8e234e652d651fa4c8cff880309e645a74e9e0a60d8243acd9177ab51a1beb8d5a2f5d700c093c5e5585579625337bd3ab619d615760d8c5b224a85b1d0efe0eb8a7ee163abb0376529fcc09bab506c618e13ce777d82c3ae9d1a6f972d4160287cbfe60bf2130fc0a6ff6049d0a5c8a82f429231f0080" + + def test_zero_XSalsa20(self): + key="1b27556473e985d462cd51197a9a46c76009549eac6474f206c4ee0844f68389" + iv="69696ee955b62b73cd62bda875fc73d68219e0036b7a0b37" + computedcipher=xsalsa20.XSalsa20(a2b_hex(key),a2b_hex(iv)).process('\x00'*139) + self.failUnlessEqual(a2b_hex(self.enc0), computedcipher, "enc0: %s, computedciper: %s" % (self.enc0, b2a_hex(computedcipher))) + + cryptor=xsalsa20.XSalsa20(a2b_hex(key),a2b_hex(iv)) + + computedcipher1=cryptor.process('\x00'*69) + computedcipher2=cryptor.process('\x00'*69) + computedcipher3=cryptor.process('\x00') + computedcipher12=b2a_hex(computedcipher1)+b2a_hex(computedcipher2)+b2a_hex(computedcipher3) + self.failUnlessEqual(self.enc0, computedcipher12) + + + def test_XSalsa(self): + # The test vector is from Crypto++'s TestVectors/salsa.txt, comment + # there is: Source: created by Wei Dai using naclcrypto-20090308 . + # naclcrypto being DJB's crypto library and of course DJB designed + # XSalsa20 + s = resource_string("pycryptopp", "testvectors/xsalsa20.txt") + return self._test_XSalsa(s) + + def _test_XSalsa(self, vects_str): + for mo in TEST_XSALSA_RE.finditer(vects_str): + #count = int(mo.group(1)) + key = a2b_hex(mo.group(2)) + iv = a2b_hex(mo.group(3)) + #plaintext = a2b_hex(mo.group(4)) + #ciphertext= a2b_hex(mo.group(5)) + plaintext = mo.group(4) + ciphertext = mo.group(5) + computedcipher=xsalsa20.XSalsa20(key,iv).process(a2b_hex(plaintext)) + #print "ciphertext", b2a_hex(computedcipher), '\n' + #print "computedtext", ciphertext, '\n' + #print count, ": \n" + self.failUnlessEqual(computedcipher,a2b_hex(ciphertext),"computedcipher: %s, ciphertext: %s" % (b2a_hex(computedcipher), ciphertext)) + + #the random decomposing + plaintext1 = "" + plaintext2 = "" + length = len(plaintext) + rccipher = "" + cryptor = xsalsa20.XSalsa20(key,iv) + if length > 2: + point = random.randint(0,length-3) + if (point%2) !=0: + point -= 1 + plaintext1 += plaintext[:point+2] + plaintext2 += plaintext[point+2:] + rccipher += b2a_hex(cryptor.process(a2b_hex(plaintext1))) + rccipher += b2a_hex(cryptor.process(a2b_hex(plaintext2))) + self.failUnlessEqual(rccipher, ciphertext, "random computed cipher: %s, ciphertext: %s" % (rccipher, ciphertext)) + + #every byte encrypted + cryptor = xsalsa20.XSalsa20(key,iv) + eccipher="" + l = 0 + while l<=(length-2): + eccipher += b2a_hex(cryptor.process(a2b_hex(plaintext[l:l+2]))) + l += 2 + self.failUnlessEqual(eccipher, ciphertext, "every byte computed cipher: %s, ciphertext: %s" % (eccipher, ciphertext)) + + + def test_types_and_lengths(self): + # the key= argument must be a bytestring exactly 32 bytes long + self.failUnlessRaises(TypeError, xsalsa20.XSalsa20, None) + for i in range(70): + key = "a"*i + if i != 32: + self.failUnlessRaises(xsalsa20.Error, xsalsa20.XSalsa20, key) + else: + self.failUnless(xsalsa20.XSalsa20(key)) + + # likewise, iv= (if provided) must be exactly 24 bytes long. Passing + # None is not treated the same as not passing the argument at all. + key = "a"*32 + self.failUnlessRaises(TypeError, xsalsa20.XSalsa20, key, None) + for i in range(70): + iv = "i"*i + if i != 24: + self.failUnlessRaises(xsalsa20.Error, xsalsa20.XSalsa20, key, iv) + else: + self.failUnless(xsalsa20.XSalsa20(key, iv)) + + def test_recursive(self): + # Try to use the same technique as: + # http://blogs.msdn.com/si_team/archive/2006/05/19/aes-test-vectors.aspx + # It's not exactly the same, though, because XSalsa20 is a stream + # cipher, whereas the Ferguson code is exercising a block cipher. But + # we try to do something similar. + + # the XSalsa20 internal function uses a 32-byte block. We want to + # exercise it twice for each key, to guard against + # clobbering-after-key-setup errors. Just doing enc(enc(p)) could let + # XOR errors slip through. So to be safe, use B=64. + B=64 + N=24 + K=32 + s = "\x00"*(B+N+K) + def enc(key, nonce, plaintext): + p = xsalsa20.XSalsa20(key=key, iv=nonce) + return p.process(plaintext) + for i in range(1000): + plaintext = s[-K-N-B:-K-N] + nonce = s[-K-N:-K] + key = s[-K:] + ciphertext = enc(key, nonce, plaintext) + s += ciphertext + s = s[-K-N-B:] + output = b2a_hex(s[-B:]) + # I've compared this output against pynacl -warner + self.failUnlessEqual(output, + "77f8e2792dd4f2d44edf469c3a7ad5f7" + "5cb373fe0c3d9c8ee570dc91e00f1caa" + "25f725c202f3781869a40b8a2c856b55" + "8178b6af9576a15799c445c30aeced66") + + +if __name__ == "__main__": + unittest.main() diff --git a/src/pycryptopp/testvectors/KAT_AES/ECBGFSbox128e.txt b/src/pycryptopp/testvectors/KAT_AES/ECBGFSbox128e.txt new file mode 100644 index 0000000..346f347 --- /dev/null +++ b/src/pycryptopp/testvectors/KAT_AES/ECBGFSbox128e.txt @@ -0,0 +1,36 @@ +[ENCRYPT] + +COUNT = 0 +KEY = 00000000000000000000000000000000 +PLAINTEXT = f34481ec3cc627bacd5dc3fb08f273e6 +CIPHERTEXT = 0336763e966d92595a567cc9ce537f5e + +COUNT = 1 +KEY = 00000000000000000000000000000000 +PLAINTEXT = 9798c4640bad75c7c3227db910174e72 +CIPHERTEXT = a9a1631bf4996954ebc093957b234589 + +COUNT = 2 +KEY = 00000000000000000000000000000000 +PLAINTEXT = 96ab5c2ff612d9dfaae8c31f30c42168 +CIPHERTEXT = ff4f8391a6a40ca5b25d23bedd44a597 + +COUNT = 3 +KEY = 00000000000000000000000000000000 +PLAINTEXT = 6a118a874519e64e9963798a503f1d35 +CIPHERTEXT = dc43be40be0e53712f7e2bf5ca707209 + +COUNT = 4 +KEY = 00000000000000000000000000000000 +PLAINTEXT = cb9fceec81286ca3e989bd979b0cb284 +CIPHERTEXT = 92beedab1895a94faa69b632e5cc47ce + +COUNT = 5 +KEY = 00000000000000000000000000000000 +PLAINTEXT = b26aeb1874e47ca8358ff22378f09144 +CIPHERTEXT = 459264f4798f6a78bacb89c15ed3d601 + +COUNT = 6 +KEY = 00000000000000000000000000000000 +PLAINTEXT = 58c8e00b2631686d54eab84b91f0aca1 +CIPHERTEXT = 08a4e2efec8a8e3312ca7460b9040bbf diff --git a/src/pycryptopp/testvectors/KAT_AES/ECBGFSbox256e.txt b/src/pycryptopp/testvectors/KAT_AES/ECBGFSbox256e.txt new file mode 100644 index 0000000..66bd7f8 --- /dev/null +++ b/src/pycryptopp/testvectors/KAT_AES/ECBGFSbox256e.txt @@ -0,0 +1,26 @@ +[ENCRYPT] + +COUNT = 0 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 014730f80ac625fe84f026c60bfd547d +CIPHERTEXT = 5c9d844ed46f9885085e5d6a4f94c7d7 + +COUNT = 1 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 0b24af36193ce4665f2825d7b4749c98 +CIPHERTEXT = a9ff75bd7cf6613d3731c77c3b6d0c04 + +COUNT = 2 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 761c1fe41a18acf20d241650611d90f1 +CIPHERTEXT = 623a52fcea5d443e48d9181ab32c7421 + +COUNT = 3 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 8a560769d605868ad80d819bdba03771 +CIPHERTEXT = 38f2c7ae10612415d27ca190d27da8b4 + +COUNT = 4 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 91fbef2d15a97816060bee1feaa49afe +CIPHERTEXT = 1bc704f1bce135ceb810341b216d7abe diff --git a/src/pycryptopp/testvectors/KAT_AES/ECBKeySbox128e.txt b/src/pycryptopp/testvectors/KAT_AES/ECBKeySbox128e.txt new file mode 100644 index 0000000..09efbbe --- /dev/null +++ b/src/pycryptopp/testvectors/KAT_AES/ECBKeySbox128e.txt @@ -0,0 +1,106 @@ +[ENCRYPT] + +COUNT = 0 +KEY = 10a58869d74be5a374cf867cfb473859 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6d251e6944b051e04eaa6fb4dbf78465 + +COUNT = 1 +KEY = caea65cdbb75e9169ecd22ebe6e54675 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6e29201190152df4ee058139def610bb + +COUNT = 2 +KEY = a2e2fa9baf7d20822ca9f0542f764a41 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c3b44b95d9d2f25670eee9a0de099fa3 + +COUNT = 3 +KEY = b6364ac4e1de1e285eaf144a2415f7a0 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 5d9b05578fc944b3cf1ccf0e746cd581 + +COUNT = 4 +KEY = 64cf9c7abc50b888af65f49d521944b2 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f7efc89d5dba578104016ce5ad659c05 + +COUNT = 5 +KEY = 47d6742eefcc0465dc96355e851b64d9 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 0306194f666d183624aa230a8b264ae7 + +COUNT = 6 +KEY = 3eb39790678c56bee34bbcdeccf6cdb5 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 858075d536d79ccee571f7d7204b1f67 + +COUNT = 7 +KEY = 64110a924f0743d500ccadae72c13427 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 35870c6a57e9e92314bcb8087cde72ce + +COUNT = 8 +KEY = 18d8126516f8a12ab1a36d9f04d68e51 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6c68e9be5ec41e22c825b7c7affb4363 + +COUNT = 9 +KEY = f530357968578480b398a3c251cd1093 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f5df39990fc688f1b07224cc03e86cea + +COUNT = 10 +KEY = da84367f325d42d601b4326964802e8e +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = bba071bcb470f8f6586e5d3add18bc66 + +COUNT = 11 +KEY = e37b1c6aa2846f6fdb413f238b089f23 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 43c9f7e62f5d288bb27aa40ef8fe1ea8 + +COUNT = 12 +KEY = 6c002b682483e0cabcc731c253be5674 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3580d19cff44f1014a7c966a69059de5 + +COUNT = 13 +KEY = 143ae8ed6555aba96110ab58893a8ae1 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 806da864dd29d48deafbe764f8202aef + +COUNT = 14 +KEY = b69418a85332240dc82492353956ae0c +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a303d940ded8f0baff6f75414cac5243 + +COUNT = 15 +KEY = 71b5c08a1993e1362e4d0ce9b22b78d5 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c2dabd117f8a3ecabfbb11d12194d9d0 + +COUNT = 16 +KEY = e234cdca2606b81f29408d5f6da21206 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = fff60a4740086b3b9c56195b98d91a7b + +COUNT = 17 +KEY = 13237c49074a3da078dc1d828bb78c6f +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8146a08e2357f0caa30ca8c94d1a0544 + +COUNT = 18 +KEY = 3071a2a48fe6cbd04f1a129098e308f8 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4b98e06d356deb07ebb824e5713f7be3 + +COUNT = 19 +KEY = 90f42ec0f68385f2ffc5dfc03a654dce +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 7a20a53d460fc9ce0423a7a0764c6cf2 + +COUNT = 20 +KEY = febd9a24d8b65c1c787d50a4ed3619a9 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f4a70d8af877f9b02b4c40df57d45b17 diff --git a/src/pycryptopp/testvectors/KAT_AES/ECBKeySbox256e.txt b/src/pycryptopp/testvectors/KAT_AES/ECBKeySbox256e.txt new file mode 100644 index 0000000..a633884 --- /dev/null +++ b/src/pycryptopp/testvectors/KAT_AES/ECBKeySbox256e.txt @@ -0,0 +1,81 @@ +[ENCRYPT] + +COUNT = 0 +KEY = c47b0294dbbbee0fec4757f22ffeee3587ca4730c3d33b691df38bab076bc558 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 46f2fb342d6f0ab477476fc501242c5f + +COUNT = 1 +KEY = 28d46cffa158533194214a91e712fc2b45b518076675affd910edeca5f41ac64 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4bf3b0a69aeb6657794f2901b1440ad4 + +COUNT = 2 +KEY = c1cc358b449909a19436cfbb3f852ef8bcb5ed12ac7058325f56e6099aab1a1c +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 352065272169abf9856843927d0674fd + +COUNT = 3 +KEY = 984ca75f4ee8d706f46c2d98c0bf4a45f5b00d791c2dfeb191b5ed8e420fd627 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4307456a9e67813b452e15fa8fffe398 + +COUNT = 4 +KEY = b43d08a447ac8609baadae4ff12918b9f68fc1653f1269222f123981ded7a92f +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4663446607354989477a5c6f0f007ef4 + +COUNT = 5 +KEY = 1d85a181b54cde51f0e098095b2962fdc93b51fe9b88602b3f54130bf76a5bd9 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 531c2c38344578b84d50b3c917bbb6e1 + +COUNT = 6 +KEY = dc0eba1f2232a7879ded34ed8428eeb8769b056bbaf8ad77cb65c3541430b4cf +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = fc6aec906323480005c58e7e1ab004ad + +COUNT = 7 +KEY = f8be9ba615c5a952cabbca24f68f8593039624d524c816acda2c9183bd917cb9 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a3944b95ca0b52043584ef02151926a8 + +COUNT = 8 +KEY = 797f8b3d176dac5b7e34a2d539c4ef367a16f8635f6264737591c5c07bf57a3e +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a74289fe73a4c123ca189ea1e1b49ad5 + +COUNT = 9 +KEY = 6838d40caf927749c13f0329d331f448e202c73ef52c5f73a37ca635d4c47707 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = b91d4ea4488644b56cf0812fa7fcf5fc + +COUNT = 10 +KEY = ccd1bc3c659cd3c59bc437484e3c5c724441da8d6e90ce556cd57d0752663bbc +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 304f81ab61a80c2e743b94d5002a126b + +COUNT = 11 +KEY = 13428b5e4c005e0636dd338405d173ab135dec2a25c22c5df0722d69dcc43887 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 649a71545378c783e368c9ade7114f6c + +COUNT = 12 +KEY = 07eb03a08d291d1b07408bf3512ab40c91097ac77461aad4bb859647f74f00ee +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 47cb030da2ab051dfc6c4bf6910d12bb + +COUNT = 13 +KEY = 90143ae20cd78c5d8ebdd6cb9dc1762427a96c78c639bccc41a61424564eafe1 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 798c7c005dee432b2c8ea5dfa381ecc3 + +COUNT = 14 +KEY = b7a5794d52737475d53d5a377200849be0260a67a2b22ced8bbef12882270d07 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 637c31dc2591a07636f646b72daabbe7 + +COUNT = 15 +KEY = fca02f3d5011cfc5c1e23165d413a049d4526a991827424d896fe3435e0bf68e +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 179a49c712154bbffbe6e7a84a18e220 diff --git a/src/pycryptopp/testvectors/KAT_AES/ECBVarKey128e.txt b/src/pycryptopp/testvectors/KAT_AES/ECBVarKey128e.txt new file mode 100644 index 0000000..27d6dd8 --- /dev/null +++ b/src/pycryptopp/testvectors/KAT_AES/ECBVarKey128e.txt @@ -0,0 +1,641 @@ +[ENCRYPT] + +COUNT = 0 +KEY = 80000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 0edd33d3c621e546455bd8ba1418bec8 + +COUNT = 1 +KEY = c0000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4bc3f883450c113c64ca42e1112a9e87 + +COUNT = 2 +KEY = e0000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 72a1da770f5d7ac4c9ef94d822affd97 + +COUNT = 3 +KEY = f0000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 970014d634e2b7650777e8e84d03ccd8 + +COUNT = 4 +KEY = f8000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f17e79aed0db7e279e955b5f493875a7 + +COUNT = 5 +KEY = fc000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 9ed5a75136a940d0963da379db4af26a + +COUNT = 6 +KEY = fe000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c4295f83465c7755e8fa364bac6a7ea5 + +COUNT = 7 +KEY = ff000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = b1d758256b28fd850ad4944208cf1155 + +COUNT = 8 +KEY = ff800000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 42ffb34c743de4d88ca38011c990890b + +COUNT = 9 +KEY = ffc00000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 9958f0ecea8b2172c0c1995f9182c0f3 + +COUNT = 10 +KEY = ffe00000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 956d7798fac20f82a8823f984d06f7f5 + +COUNT = 11 +KEY = fff00000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a01bf44f2d16be928ca44aaf7b9b106b + +COUNT = 12 +KEY = fff80000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = b5f1a33e50d40d103764c76bd4c6b6f8 + +COUNT = 13 +KEY = fffc0000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2637050c9fc0d4817e2d69de878aee8d + +COUNT = 14 +KEY = fffe0000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 113ecbe4a453269a0dd26069467fb5b5 + +COUNT = 15 +KEY = ffff0000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 97d0754fe68f11b9e375d070a608c884 + +COUNT = 16 +KEY = ffff8000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c6a0b3e998d05068a5399778405200b4 + +COUNT = 17 +KEY = ffffc000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = df556a33438db87bc41b1752c55e5e49 + +COUNT = 18 +KEY = ffffe000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 90fb128d3a1af6e548521bb962bf1f05 + +COUNT = 19 +KEY = fffff000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 26298e9c1db517c215fadfb7d2a8d691 + +COUNT = 20 +KEY = fffff800000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a6cb761d61f8292d0df393a279ad0380 + +COUNT = 21 +KEY = fffffc00000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 12acd89b13cd5f8726e34d44fd486108 + +COUNT = 22 +KEY = fffffe00000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 95b1703fc57ba09fe0c3580febdd7ed4 + +COUNT = 23 +KEY = ffffff00000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = de11722d893e9f9121c381becc1da59a + +COUNT = 24 +KEY = ffffff80000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6d114ccb27bf391012e8974c546d9bf2 + +COUNT = 25 +KEY = ffffffc0000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 5ce37e17eb4646ecfac29b9cc38d9340 + +COUNT = 26 +KEY = ffffffe0000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 18c1b6e2157122056d0243d8a165cddb + +COUNT = 27 +KEY = fffffff0000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 99693e6a59d1366c74d823562d7e1431 + +COUNT = 28 +KEY = fffffff8000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6c7c64dc84a8bba758ed17eb025a57e3 + +COUNT = 29 +KEY = fffffffc000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = e17bc79f30eaab2fac2cbbe3458d687a + +COUNT = 30 +KEY = fffffffe000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 1114bc2028009b923f0b01915ce5e7c4 + +COUNT = 31 +KEY = ffffffff000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 9c28524a16a1e1c1452971caa8d13476 + +COUNT = 32 +KEY = ffffffff800000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ed62e16363638360fdd6ad62112794f0 + +COUNT = 33 +KEY = ffffffffc00000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 5a8688f0b2a2c16224c161658ffd4044 + +COUNT = 34 +KEY = ffffffffe00000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 23f710842b9bb9c32f26648c786807ca + +COUNT = 35 +KEY = fffffffff00000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 44a98bf11e163f632c47ec6a49683a89 + +COUNT = 36 +KEY = fffffffff80000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 0f18aff94274696d9b61848bd50ac5e5 + +COUNT = 37 +KEY = fffffffffc0000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 82408571c3e2424540207f833b6dda69 + +COUNT = 38 +KEY = fffffffffe0000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 303ff996947f0c7d1f43c8f3027b9b75 + +COUNT = 39 +KEY = ffffffffff0000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 7df4daf4ad29a3615a9b6ece5c99518a + +COUNT = 40 +KEY = ffffffffff8000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c72954a48d0774db0b4971c526260415 + +COUNT = 41 +KEY = ffffffffffc000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 1df9b76112dc6531e07d2cfda04411f0 + +COUNT = 42 +KEY = ffffffffffe000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8e4d8e699119e1fc87545a647fb1d34f + +COUNT = 43 +KEY = fffffffffff000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = e6c4807ae11f36f091c57d9fb68548d1 + +COUNT = 44 +KEY = fffffffffff800000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8ebf73aad49c82007f77a5c1ccec6ab4 + +COUNT = 45 +KEY = fffffffffffc00000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4fb288cc2040049001d2c7585ad123fc + +COUNT = 46 +KEY = fffffffffffe00000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 04497110efb9dceb13e2b13fb4465564 + +COUNT = 47 +KEY = ffffffffffff00000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 75550e6cb5a88e49634c9ab69eda0430 + +COUNT = 48 +KEY = ffffffffffff80000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = b6768473ce9843ea66a81405dd50b345 + +COUNT = 49 +KEY = ffffffffffffc0000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = cb2f430383f9084e03a653571e065de6 + +COUNT = 50 +KEY = ffffffffffffe0000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ff4e66c07bae3e79fb7d210847a3b0ba + +COUNT = 51 +KEY = fffffffffffff0000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 7b90785125505fad59b13c186dd66ce3 + +COUNT = 52 +KEY = fffffffffffff8000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8b527a6aebdaec9eaef8eda2cb7783e5 + +COUNT = 53 +KEY = fffffffffffffc000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 43fdaf53ebbc9880c228617d6a9b548b + +COUNT = 54 +KEY = fffffffffffffe000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 53786104b9744b98f052c46f1c850d0b + +COUNT = 55 +KEY = ffffffffffffff000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = b5ab3013dd1e61df06cbaf34ca2aee78 + +COUNT = 56 +KEY = ffffffffffffff800000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 7470469be9723030fdcc73a8cd4fbb10 + +COUNT = 57 +KEY = ffffffffffffffc00000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a35a63f5343ebe9ef8167bcb48ad122e + +COUNT = 58 +KEY = ffffffffffffffe00000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = fd8687f0757a210e9fdf181204c30863 + +COUNT = 59 +KEY = fffffffffffffff00000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 7a181e84bd5457d26a88fbae96018fb0 + +COUNT = 60 +KEY = fffffffffffffff80000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 653317b9362b6f9b9e1a580e68d494b5 + +COUNT = 61 +KEY = fffffffffffffffc0000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 995c9dc0b689f03c45867b5faa5c18d1 + +COUNT = 62 +KEY = fffffffffffffffe0000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 77a4d96d56dda398b9aabecfc75729fd + +COUNT = 63 +KEY = ffffffffffffffff0000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 84be19e053635f09f2665e7bae85b42d + +COUNT = 64 +KEY = ffffffffffffffff8000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 32cd652842926aea4aa6137bb2be2b5e + +COUNT = 65 +KEY = ffffffffffffffffc000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 493d4a4f38ebb337d10aa84e9171a554 + +COUNT = 66 +KEY = ffffffffffffffffe000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d9bff7ff454b0ec5a4a2a69566e2cb84 + +COUNT = 67 +KEY = fffffffffffffffff000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3535d565ace3f31eb249ba2cc6765d7a + +COUNT = 68 +KEY = fffffffffffffffff800000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f60e91fc3269eecf3231c6e9945697c6 + +COUNT = 69 +KEY = fffffffffffffffffc00000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ab69cfadf51f8e604d9cc37182f6635a + +COUNT = 70 +KEY = fffffffffffffffffe00000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 7866373f24a0b6ed56e0d96fcdafb877 + +COUNT = 71 +KEY = ffffffffffffffffff00000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 1ea448c2aac954f5d812e9d78494446a + +COUNT = 72 +KEY = ffffffffffffffffff80000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = acc5599dd8ac02239a0fef4a36dd1668 + +COUNT = 73 +KEY = ffffffffffffffffffc0000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d8764468bb103828cf7e1473ce895073 + +COUNT = 74 +KEY = ffffffffffffffffffe0000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 1b0d02893683b9f180458e4aa6b73982 + +COUNT = 75 +KEY = fffffffffffffffffff0000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 96d9b017d302df410a937dcdb8bb6e43 + +COUNT = 76 +KEY = fffffffffffffffffff8000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ef1623cc44313cff440b1594a7e21cc6 + +COUNT = 77 +KEY = fffffffffffffffffffc000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 284ca2fa35807b8b0ae4d19e11d7dbd7 + +COUNT = 78 +KEY = fffffffffffffffffffe000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f2e976875755f9401d54f36e2a23a594 + +COUNT = 79 +KEY = ffffffffffffffffffff000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ec198a18e10e532403b7e20887c8dd80 + +COUNT = 80 +KEY = ffffffffffffffffffff800000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 545d50ebd919e4a6949d96ad47e46a80 + +COUNT = 81 +KEY = ffffffffffffffffffffc00000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = dbdfb527060e0a71009c7bb0c68f1d44 + +COUNT = 82 +KEY = ffffffffffffffffffffe00000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 9cfa1322ea33da2173a024f2ff0d896d + +COUNT = 83 +KEY = fffffffffffffffffffff00000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8785b1a75b0f3bd958dcd0e29318c521 + +COUNT = 84 +KEY = fffffffffffffffffffff80000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 38f67b9e98e4a97b6df030a9fcdd0104 + +COUNT = 85 +KEY = fffffffffffffffffffffc0000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 192afffb2c880e82b05926d0fc6c448b + +COUNT = 86 +KEY = fffffffffffffffffffffe0000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6a7980ce7b105cf530952d74daaf798c + +COUNT = 87 +KEY = ffffffffffffffffffffff0000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ea3695e1351b9d6858bd958cf513ef6c + +COUNT = 88 +KEY = ffffffffffffffffffffff8000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6da0490ba0ba0343b935681d2cce5ba1 + +COUNT = 89 +KEY = ffffffffffffffffffffffc000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f0ea23af08534011c60009ab29ada2f1 + +COUNT = 90 +KEY = ffffffffffffffffffffffe000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ff13806cf19cc38721554d7c0fcdcd4b + +COUNT = 91 +KEY = fffffffffffffffffffffff000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6838af1f4f69bae9d85dd188dcdf0688 + +COUNT = 92 +KEY = fffffffffffffffffffffff800000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 36cf44c92d550bfb1ed28ef583ddf5d7 + +COUNT = 93 +KEY = fffffffffffffffffffffffc00000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d06e3195b5376f109d5c4ec6c5d62ced + +COUNT = 94 +KEY = fffffffffffffffffffffffe00000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c440de014d3d610707279b13242a5c36 + +COUNT = 95 +KEY = ffffffffffffffffffffffff00000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f0c5c6ffa5e0bd3a94c88f6b6f7c16b9 + +COUNT = 96 +KEY = ffffffffffffffffffffffff80000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3e40c3901cd7effc22bffc35dee0b4d9 + +COUNT = 97 +KEY = ffffffffffffffffffffffffc0000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = b63305c72bedfab97382c406d0c49bc6 + +COUNT = 98 +KEY = ffffffffffffffffffffffffe0000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 36bbaab22a6bd4925a99a2b408d2dbae + +COUNT = 99 +KEY = fffffffffffffffffffffffff0000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 307c5b8fcd0533ab98bc51e27a6ce461 + +COUNT = 100 +KEY = fffffffffffffffffffffffff8000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 829c04ff4c07513c0b3ef05c03e337b5 + +COUNT = 101 +KEY = fffffffffffffffffffffffffc000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f17af0e895dda5eb98efc68066e84c54 + +COUNT = 102 +KEY = fffffffffffffffffffffffffe000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 277167f3812afff1ffacb4a934379fc3 + +COUNT = 103 +KEY = ffffffffffffffffffffffffff000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2cb1dc3a9c72972e425ae2ef3eb597cd + +COUNT = 104 +KEY = ffffffffffffffffffffffffff800000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 36aeaa3a213e968d4b5b679d3a2c97fe + +COUNT = 105 +KEY = ffffffffffffffffffffffffffc00000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 9241daca4fdd034a82372db50e1a0f3f + +COUNT = 106 +KEY = ffffffffffffffffffffffffffe00000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c14574d9cd00cf2b5a7f77e53cd57885 + +COUNT = 107 +KEY = fffffffffffffffffffffffffff00000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 793de39236570aba83ab9b737cb521c9 + +COUNT = 108 +KEY = fffffffffffffffffffffffffff80000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 16591c0f27d60e29b85a96c33861a7ef + +COUNT = 109 +KEY = fffffffffffffffffffffffffffc0000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 44fb5c4d4f5cb79be5c174a3b1c97348 + +COUNT = 110 +KEY = fffffffffffffffffffffffffffe0000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 674d2b61633d162be59dde04222f4740 + +COUNT = 111 +KEY = ffffffffffffffffffffffffffff0000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = b4750ff263a65e1f9e924ccfd98f3e37 + +COUNT = 112 +KEY = ffffffffffffffffffffffffffff8000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 62d0662d6eaeddedebae7f7ea3a4f6b6 + +COUNT = 113 +KEY = ffffffffffffffffffffffffffffc000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 70c46bb30692be657f7eaa93ebad9897 + +COUNT = 114 +KEY = ffffffffffffffffffffffffffffe000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 323994cfb9da285a5d9642e1759b224a + +COUNT = 115 +KEY = fffffffffffffffffffffffffffff000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 1dbf57877b7b17385c85d0b54851e371 + +COUNT = 116 +KEY = fffffffffffffffffffffffffffff800 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = dfa5c097cdc1532ac071d57b1d28d1bd + +COUNT = 117 +KEY = fffffffffffffffffffffffffffffc00 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3a0c53fa37311fc10bd2a9981f513174 + +COUNT = 118 +KEY = fffffffffffffffffffffffffffffe00 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ba4f970c0a25c41814bdae2e506be3b4 + +COUNT = 119 +KEY = ffffffffffffffffffffffffffffff00 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2dce3acb727cd13ccd76d425ea56e4f6 + +COUNT = 120 +KEY = ffffffffffffffffffffffffffffff80 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 5160474d504b9b3eefb68d35f245f4b3 + +COUNT = 121 +KEY = ffffffffffffffffffffffffffffffc0 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 41a8a947766635dec37553d9a6c0cbb7 + +COUNT = 122 +KEY = ffffffffffffffffffffffffffffffe0 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 25d6cfe6881f2bf497dd14cd4ddf445b + +COUNT = 123 +KEY = fffffffffffffffffffffffffffffff0 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 41c78c135ed9e98c096640647265da1e + +COUNT = 124 +KEY = fffffffffffffffffffffffffffffff8 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 5a4d404d8917e353e92a21072c3b2305 + +COUNT = 125 +KEY = fffffffffffffffffffffffffffffffc +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 02bc96846b3fdc71643f384cd3cc3eaf + +COUNT = 126 +KEY = fffffffffffffffffffffffffffffffe +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 9ba4a9143f4e5d4048521c4f8877d88e + +COUNT = 127 +KEY = ffffffffffffffffffffffffffffffff +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a1f6258c877d5fcd8964484538bfc92c diff --git a/src/pycryptopp/testvectors/KAT_AES/ECBVarKey256e.txt b/src/pycryptopp/testvectors/KAT_AES/ECBVarKey256e.txt new file mode 100644 index 0000000..3b7a986 --- /dev/null +++ b/src/pycryptopp/testvectors/KAT_AES/ECBVarKey256e.txt @@ -0,0 +1,1281 @@ +[ENCRYPT] + +COUNT = 0 +KEY = 8000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = e35a6dcb19b201a01ebcfa8aa22b5759 + +COUNT = 1 +KEY = c000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = b29169cdcf2d83e838125a12ee6aa400 + +COUNT = 2 +KEY = e000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d8f3a72fc3cdf74dfaf6c3e6b97b2fa6 + +COUNT = 3 +KEY = f000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 1c777679d50037c79491a94da76a9a35 + +COUNT = 4 +KEY = f800000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 9cf4893ecafa0a0247a898e040691559 + +COUNT = 5 +KEY = fc00000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8fbb413703735326310a269bd3aa94b2 + +COUNT = 6 +KEY = fe00000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 60e32246bed2b0e859e55c1cc6b26502 + +COUNT = 7 +KEY = ff00000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ec52a212f80a09df6317021bc2a9819e + +COUNT = 8 +KEY = ff80000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f23e5b600eb70dbccf6c0b1d9a68182c + +COUNT = 9 +KEY = ffc0000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a3f599d63a82a968c33fe26590745970 + +COUNT = 10 +KEY = ffe0000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d1ccb9b1337002cbac42c520b5d67722 + +COUNT = 11 +KEY = fff0000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = cc111f6c37cf40a1159d00fb59fb0488 + +COUNT = 12 +KEY = fff8000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = dc43b51ab609052372989a26e9cdd714 + +COUNT = 13 +KEY = fffc000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4dcede8da9e2578f39703d4433dc6459 + +COUNT = 14 +KEY = fffe000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 1a4c1c263bbccfafc11782894685e3a8 + +COUNT = 15 +KEY = ffff000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 937ad84880db50613423d6d527a2823d + +COUNT = 16 +KEY = ffff800000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 610b71dfc688e150d8152c5b35ebc14d + +COUNT = 17 +KEY = ffffc00000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 27ef2495dabf323885aab39c80f18d8b + +COUNT = 18 +KEY = ffffe00000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 633cafea395bc03adae3a1e2068e4b4e + +COUNT = 19 +KEY = fffff00000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6e1b482b53761cf631819b749a6f3724 + +COUNT = 20 +KEY = fffff80000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 976e6f851ab52c771998dbb2d71c75a9 + +COUNT = 21 +KEY = fffffc0000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 85f2ba84f8c307cf525e124c3e22e6cc + +COUNT = 22 +KEY = fffffe0000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6bcca98bf6a835fa64955f72de4115fe + +COUNT = 23 +KEY = ffffff0000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2c75e2d36eebd65411f14fd0eb1d2a06 + +COUNT = 24 +KEY = ffffff8000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = bd49295006250ffca5100b6007a0eade + +COUNT = 25 +KEY = ffffffc000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a190527d0ef7c70f459cd3940df316ec + +COUNT = 26 +KEY = ffffffe000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = bbd1097a62433f79449fa97d4ee80dbf + +COUNT = 27 +KEY = fffffff000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 07058e408f5b99b0e0f061a1761b5b3b + +COUNT = 28 +KEY = fffffff800000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 5fd1f13fa0f31e37fabde328f894eac2 + +COUNT = 29 +KEY = fffffffc00000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = fc4af7c948df26e2ef3e01c1ee5b8f6f + +COUNT = 30 +KEY = fffffffe00000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 829fd7208fb92d44a074a677ee9861ac + +COUNT = 31 +KEY = ffffffff00000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ad9fc613a703251b54c64a0e76431711 + +COUNT = 32 +KEY = ffffffff80000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 33ac9eccc4cc75e2711618f80b1548e8 + +COUNT = 33 +KEY = ffffffffc0000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2025c74b8ad8f4cda17ee2049c4c902d + +COUNT = 34 +KEY = ffffffffe0000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f85ca05fe528f1ce9b790166e8d551e7 + +COUNT = 35 +KEY = fffffffff0000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6f6238d8966048d4967154e0dad5a6c9 + +COUNT = 36 +KEY = fffffffff8000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f2b21b4e7640a9b3346de8b82fb41e49 + +COUNT = 37 +KEY = fffffffffc000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f836f251ad1d11d49dc344628b1884e1 + +COUNT = 38 +KEY = fffffffffe000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 077e9470ae7abea5a9769d49182628c3 + +COUNT = 39 +KEY = ffffffffff000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = e0dcc2d27fc9865633f85223cf0d611f + +COUNT = 40 +KEY = ffffffffff800000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = be66cfea2fecd6bf0ec7b4352c99bcaa + +COUNT = 41 +KEY = ffffffffffc00000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = df31144f87a2ef523facdcf21a427804 + +COUNT = 42 +KEY = ffffffffffe00000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = b5bb0f5629fb6aae5e1839a3c3625d63 + +COUNT = 43 +KEY = fffffffffff00000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3c9db3335306fe1ec612bdbfae6b6028 + +COUNT = 44 +KEY = fffffffffff80000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3dd5c34634a79d3cfcc8339760e6f5f4 + +COUNT = 45 +KEY = fffffffffffc0000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 82bda118a3ed7af314fa2ccc5c07b761 + +COUNT = 46 +KEY = fffffffffffe0000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2937a64f7d4f46fe6fea3b349ec78e38 + +COUNT = 47 +KEY = ffffffffffff0000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 225f068c28476605735ad671bb8f39f3 + +COUNT = 48 +KEY = ffffffffffff8000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ae682c5ecd71898e08942ac9aa89875c + +COUNT = 49 +KEY = ffffffffffffc000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 5e031cb9d676c3022d7f26227e85c38f + +COUNT = 50 +KEY = ffffffffffffe000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a78463fb064db5d52bb64bfef64f2dda + +COUNT = 51 +KEY = fffffffffffff000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8aa9b75e784593876c53a00eae5af52b + +COUNT = 52 +KEY = fffffffffffff800000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3f84566df23da48af692722fe980573a + +COUNT = 53 +KEY = fffffffffffffc00000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 31690b5ed41c7eb42a1e83270a7ff0e6 + +COUNT = 54 +KEY = fffffffffffffe00000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 77dd7702646d55f08365e477d3590eda + +COUNT = 55 +KEY = ffffffffffffff00000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4c022ac62b3cb78d739cc67b3e20bb7e + +COUNT = 56 +KEY = ffffffffffffff80000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 092fa137ce18b5dfe7906f550bb13370 + +COUNT = 57 +KEY = ffffffffffffffc0000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3e0cdadf2e68353c0027672c97144dd3 + +COUNT = 58 +KEY = ffffffffffffffe0000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d8c4b200b383fc1f2b2ea677618a1d27 + +COUNT = 59 +KEY = fffffffffffffff0000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 11825f99b0e9bb3477c1c0713b015aac + +COUNT = 60 +KEY = fffffffffffffff8000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f8b9fffb5c187f7ddc7ab10f4fb77576 + +COUNT = 61 +KEY = fffffffffffffffc000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ffb4e87a32b37d6f2c8328d3b5377802 + +COUNT = 62 +KEY = fffffffffffffffe000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d276c13a5d220f4da9224e74896391ce + +COUNT = 63 +KEY = ffffffffffffffff000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 94efe7a0e2e031e2536da01df799c927 + +COUNT = 64 +KEY = ffffffffffffffff800000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8f8fd822680a85974e53a5a8eb9d38de + +COUNT = 65 +KEY = ffffffffffffffffc00000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = e0f0a91b2e45f8cc37b7805a3042588d + +COUNT = 66 +KEY = ffffffffffffffffe00000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 597a6252255e46d6364dbeeda31e279c + +COUNT = 67 +KEY = fffffffffffffffff00000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f51a0f694442b8f05571797fec7ee8bf + +COUNT = 68 +KEY = fffffffffffffffff80000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 9ff071b165b5198a93dddeebc54d09b5 + +COUNT = 69 +KEY = fffffffffffffffffc0000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c20a19fd5758b0c4bc1a5df89cf73877 + +COUNT = 70 +KEY = fffffffffffffffffe0000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 97120166307119ca2280e9315668e96f + +COUNT = 71 +KEY = ffffffffffffffffff0000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4b3b9f1e099c2a09dc091e90e4f18f0a + +COUNT = 72 +KEY = ffffffffffffffffff8000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = eb040b891d4b37f6851f7ec219cd3f6d + +COUNT = 73 +KEY = ffffffffffffffffffc000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 9f0fdec08b7fd79aa39535bea42db92a + +COUNT = 74 +KEY = ffffffffffffffffffe000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2e70f168fc74bf911df240bcd2cef236 + +COUNT = 75 +KEY = fffffffffffffffffff000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 462ccd7f5fd1108dbc152f3cacad328b + +COUNT = 76 +KEY = fffffffffffffffffff800000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a4af534a7d0b643a01868785d86dfb95 + +COUNT = 77 +KEY = fffffffffffffffffffc00000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ab980296197e1a5022326c31da4bf6f3 + +COUNT = 78 +KEY = fffffffffffffffffffe00000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f97d57b3333b6281b07d486db2d4e20c + +COUNT = 79 +KEY = ffffffffffffffffffff00000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f33fa36720231afe4c759ade6bd62eb6 + +COUNT = 80 +KEY = ffffffffffffffffffff80000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = fdcfac0c02ca538343c68117e0a15938 + +COUNT = 81 +KEY = ffffffffffffffffffffc0000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ad4916f5ee5772be764fc027b8a6e539 + +COUNT = 82 +KEY = ffffffffffffffffffffe0000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2e16873e1678610d7e14c02d002ea845 + +COUNT = 83 +KEY = fffffffffffffffffffff0000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4e6e627c1acc51340053a8236d579576 + +COUNT = 84 +KEY = fffffffffffffffffffff8000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ab0c8410aeeead92feec1eb430d652cb + +COUNT = 85 +KEY = fffffffffffffffffffffc000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = e86f7e23e835e114977f60e1a592202e + +COUNT = 86 +KEY = fffffffffffffffffffffe000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = e68ad5055a367041fade09d9a70a794b + +COUNT = 87 +KEY = ffffffffffffffffffffff000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 0791823a3c666bb6162825e78606a7fe + +COUNT = 88 +KEY = ffffffffffffffffffffff800000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = dcca366a9bf47b7b868b77e25c18a364 + +COUNT = 89 +KEY = ffffffffffffffffffffffc00000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 684c9efc237e4a442965f84bce20247a + +COUNT = 90 +KEY = ffffffffffffffffffffffe00000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a858411ffbe63fdb9c8aa1bfaed67b52 + +COUNT = 91 +KEY = fffffffffffffffffffffff00000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 04bc3da2179c3015498b0e03910db5b8 + +COUNT = 92 +KEY = fffffffffffffffffffffff80000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 40071eeab3f935dbc25d00841460260f + +COUNT = 93 +KEY = fffffffffffffffffffffffc0000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 0ebd7c30ed2016e08ba806ddb008bcc8 + +COUNT = 94 +KEY = fffffffffffffffffffffffe0000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 15c6becf0f4cec7129cbd22d1a79b1b8 + +COUNT = 95 +KEY = ffffffffffffffffffffffff0000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 0aeede5b91f721700e9e62edbf60b781 + +COUNT = 96 +KEY = ffffffffffffffffffffffff8000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 266581af0dcfbed1585e0a242c64b8df + +COUNT = 97 +KEY = ffffffffffffffffffffffffc000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6693dc911662ae473216ba22189a511a + +COUNT = 98 +KEY = ffffffffffffffffffffffffe000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 7606fa36d86473e6fb3a1bb0e2c0adf5 + +COUNT = 99 +KEY = fffffffffffffffffffffffff000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 112078e9e11fbb78e26ffb8899e96b9a + +COUNT = 100 +KEY = fffffffffffffffffffffffff800000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 40b264e921e9e4a82694589ef3798262 + +COUNT = 101 +KEY = fffffffffffffffffffffffffc00000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8d4595cb4fa7026715f55bd68e2882f9 + +COUNT = 102 +KEY = fffffffffffffffffffffffffe00000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = b588a302bdbc09197df1edae68926ed9 + +COUNT = 103 +KEY = ffffffffffffffffffffffffff00000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 33f7502390b8a4a221cfecd0666624ba + +COUNT = 104 +KEY = ffffffffffffffffffffffffff80000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3d20253adbce3be2373767c4d822c566 + +COUNT = 105 +KEY = ffffffffffffffffffffffffffc0000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a42734a3929bf84cf0116c9856a3c18c + +COUNT = 106 +KEY = ffffffffffffffffffffffffffe0000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = e3abc4939457422bb957da3c56938c6d + +COUNT = 107 +KEY = fffffffffffffffffffffffffff0000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 972bdd2e7c525130fadc8f76fc6f4b3f + +COUNT = 108 +KEY = fffffffffffffffffffffffffff8000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 84a83d7b94c699cbcb8a7d9b61f64093 + +COUNT = 109 +KEY = fffffffffffffffffffffffffffc000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ce61d63514aded03d43e6ebfc3a9001f + +COUNT = 110 +KEY = fffffffffffffffffffffffffffe000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6c839dd58eeae6b8a36af48ed63d2dc9 + +COUNT = 111 +KEY = ffffffffffffffffffffffffffff000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = cd5ece55b8da3bf622c4100df5de46f9 + +COUNT = 112 +KEY = ffffffffffffffffffffffffffff800000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3b6f46f40e0ac5fc0a9c1105f800f48d + +COUNT = 113 +KEY = ffffffffffffffffffffffffffffc00000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ba26d47da3aeb028de4fb5b3a854a24b + +COUNT = 114 +KEY = ffffffffffffffffffffffffffffe00000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 87f53bf620d3677268445212904389d5 + +COUNT = 115 +KEY = fffffffffffffffffffffffffffff00000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 10617d28b5e0f4605492b182a5d7f9f6 + +COUNT = 116 +KEY = fffffffffffffffffffffffffffff80000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 9aaec4fabbf6fae2a71feff02e372b39 + +COUNT = 117 +KEY = fffffffffffffffffffffffffffffc0000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3a90c62d88b5c42809abf782488ed130 + +COUNT = 118 +KEY = fffffffffffffffffffffffffffffe0000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f1f1c5a40899e15772857ccb65c7a09a + +COUNT = 119 +KEY = ffffffffffffffffffffffffffffff0000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 190843d29b25a3897c692ce1dd81ee52 + +COUNT = 120 +KEY = ffffffffffffffffffffffffffffff8000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a866bc65b6941d86e8420a7ffb0964db + +COUNT = 121 +KEY = ffffffffffffffffffffffffffffffc000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8193c6ff85225ced4255e92f6e078a14 + +COUNT = 122 +KEY = ffffffffffffffffffffffffffffffe000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 9661cb2424d7d4a380d547f9e7ec1cb9 + +COUNT = 123 +KEY = fffffffffffffffffffffffffffffff000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 86f93d9ec08453a071e2e2877877a9c8 + +COUNT = 124 +KEY = fffffffffffffffffffffffffffffff800000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 27eefa80ce6a4a9d598e3fec365434d2 + +COUNT = 125 +KEY = fffffffffffffffffffffffffffffffc00000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d62068444578e3ab39ce7ec95dd045dc + +COUNT = 126 +KEY = fffffffffffffffffffffffffffffffe00000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = b5f71d4dd9a71fe5d8bc8ba7e6ea3048 + +COUNT = 127 +KEY = ffffffffffffffffffffffffffffffff00000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6825a347ac479d4f9d95c5cb8d3fd7e9 + +COUNT = 128 +KEY = ffffffffffffffffffffffffffffffff80000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = e3714e94a5778955cc0346358e94783a + +COUNT = 129 +KEY = ffffffffffffffffffffffffffffffffc0000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d836b44bb29e0c7d89fa4b2d4b677d2a + +COUNT = 130 +KEY = ffffffffffffffffffffffffffffffffe0000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 5d454b75021d76d4b84f873a8f877b92 + +COUNT = 131 +KEY = fffffffffffffffffffffffffffffffff0000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c3498f7eced2095314fc28115885b33f + +COUNT = 132 +KEY = fffffffffffffffffffffffffffffffff8000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6e668856539ad8e405bd123fe6c88530 + +COUNT = 133 +KEY = fffffffffffffffffffffffffffffffffc000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8680db7f3a87b8605543cfdbe6754076 + +COUNT = 134 +KEY = fffffffffffffffffffffffffffffffffe000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6c5d03b13069c3658b3179be91b0800c + +COUNT = 135 +KEY = ffffffffffffffffffffffffffffffffff000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ef1b384ac4d93eda00c92add0995ea5f + +COUNT = 136 +KEY = ffffffffffffffffffffffffffffffffff800000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = bf8115805471741bd5ad20a03944790f + +COUNT = 137 +KEY = ffffffffffffffffffffffffffffffffffc00000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c64c24b6894b038b3c0d09b1df068b0b + +COUNT = 138 +KEY = ffffffffffffffffffffffffffffffffffe00000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3967a10cffe27d0178545fbf6a40544b + +COUNT = 139 +KEY = fffffffffffffffffffffffffffffffffff00000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 7c85e9c95de1a9ec5a5363a8a053472d + +COUNT = 140 +KEY = fffffffffffffffffffffffffffffffffff80000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a9eec03c8abec7ba68315c2c8c2316e0 + +COUNT = 141 +KEY = fffffffffffffffffffffffffffffffffffc0000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = cac8e414c2f388227ae14986fc983524 + +COUNT = 142 +KEY = fffffffffffffffffffffffffffffffffffe0000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 5d942b7f4622ce056c3ce3ce5f1dd9d6 + +COUNT = 143 +KEY = ffffffffffffffffffffffffffffffffffff0000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d240d648ce21a3020282c3f1b528a0b6 + +COUNT = 144 +KEY = ffffffffffffffffffffffffffffffffffff8000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 45d089c36d5c5a4efc689e3b0de10dd5 + +COUNT = 145 +KEY = ffffffffffffffffffffffffffffffffffffc000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = b4da5df4becb5462e03a0ed00d295629 + +COUNT = 146 +KEY = ffffffffffffffffffffffffffffffffffffe000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = dcf4e129136c1a4b7a0f38935cc34b2b + +COUNT = 147 +KEY = fffffffffffffffffffffffffffffffffffff000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d9a4c7618b0ce48a3d5aee1a1c0114c4 + +COUNT = 148 +KEY = fffffffffffffffffffffffffffffffffffff800000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ca352df025c65c7b0bf306fbee0f36ba + +COUNT = 149 +KEY = fffffffffffffffffffffffffffffffffffffc00000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 238aca23fd3409f38af63378ed2f5473 + +COUNT = 150 +KEY = fffffffffffffffffffffffffffffffffffffe00000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 59836a0e06a79691b36667d5380d8188 + +COUNT = 151 +KEY = ffffffffffffffffffffffffffffffffffffff00000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 33905080f7acf1cdae0a91fc3e85aee4 + +COUNT = 152 +KEY = ffffffffffffffffffffffffffffffffffffff80000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 72c9e4646dbc3d6320fc6689d93e8833 + +COUNT = 153 +KEY = ffffffffffffffffffffffffffffffffffffffc0000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ba77413dea5925b7f5417ea47ff19f59 + +COUNT = 154 +KEY = ffffffffffffffffffffffffffffffffffffffe0000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6cae8129f843d86dc786a0fb1a184970 + +COUNT = 155 +KEY = fffffffffffffffffffffffffffffffffffffff0000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = fcfefb534100796eebbd990206754e19 + +COUNT = 156 +KEY = fffffffffffffffffffffffffffffffffffffff8000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8c791d5fdddf470da04f3e6dc4a5b5b5 + +COUNT = 157 +KEY = fffffffffffffffffffffffffffffffffffffffc000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c93bbdc07a4611ae4bb266ea5034a387 + +COUNT = 158 +KEY = fffffffffffffffffffffffffffffffffffffffe000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c102e38e489aa74762f3efc5bb23205a + +COUNT = 159 +KEY = ffffffffffffffffffffffffffffffffffffffff000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 93201481665cbafc1fcc220bc545fb3d + +COUNT = 160 +KEY = ffffffffffffffffffffffffffffffffffffffff800000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4960757ec6ce68cf195e454cfd0f32ca + +COUNT = 161 +KEY = ffffffffffffffffffffffffffffffffffffffffc00000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = feec7ce6a6cbd07c043416737f1bbb33 + +COUNT = 162 +KEY = ffffffffffffffffffffffffffffffffffffffffe00000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 11c5413904487a805d70a8edd9c35527 + +COUNT = 163 +KEY = fffffffffffffffffffffffffffffffffffffffff00000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 347846b2b2e36f1f0324c86f7f1b98e2 + +COUNT = 164 +KEY = fffffffffffffffffffffffffffffffffffffffff80000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 332eee1a0cbd19ca2d69b426894044f0 + +COUNT = 165 +KEY = fffffffffffffffffffffffffffffffffffffffffc0000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 866b5b3977ba6efa5128efbda9ff03cd + +COUNT = 166 +KEY = fffffffffffffffffffffffffffffffffffffffffe0000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = cc1445ee94c0f08cdee5c344ecd1e233 + +COUNT = 167 +KEY = ffffffffffffffffffffffffffffffffffffffffff0000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = be288319029363c2622feba4b05dfdfe + +COUNT = 168 +KEY = ffffffffffffffffffffffffffffffffffffffffff8000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = cfd1875523f3cd21c395651e6ee15e56 + +COUNT = 169 +KEY = ffffffffffffffffffffffffffffffffffffffffffc000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = cb5a408657837c53bf16f9d8465dce19 + +COUNT = 170 +KEY = ffffffffffffffffffffffffffffffffffffffffffe000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ca0bf42cb107f55ccff2fc09ee08ca15 + +COUNT = 171 +KEY = fffffffffffffffffffffffffffffffffffffffffff000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = fdd9bbb4a7dc2e4a23536a5880a2db67 + +COUNT = 172 +KEY = fffffffffffffffffffffffffffffffffffffffffff800000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ede447b362c484993dec9442a3b46aef + +COUNT = 173 +KEY = fffffffffffffffffffffffffffffffffffffffffffc00000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 10dffb05904bff7c4781df780ad26837 + +COUNT = 174 +KEY = fffffffffffffffffffffffffffffffffffffffffffe00000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c33bc13e8de88ac25232aa7496398783 + +COUNT = 175 +KEY = ffffffffffffffffffffffffffffffffffffffffffff00000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ca359c70803a3b2a3d542e8781dea975 + +COUNT = 176 +KEY = ffffffffffffffffffffffffffffffffffffffffffff80000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = bcc65b526f88d05b89ce8a52021fdb06 + +COUNT = 177 +KEY = ffffffffffffffffffffffffffffffffffffffffffffc0000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = db91a38855c8c4643851fbfb358b0109 + +COUNT = 178 +KEY = ffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ca6e8893a114ae8e27d5ab03a5499610 + +COUNT = 179 +KEY = fffffffffffffffffffffffffffffffffffffffffffff0000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6629d2b8df97da728cdd8b1e7f945077 + +COUNT = 180 +KEY = fffffffffffffffffffffffffffffffffffffffffffff8000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4570a5a18cfc0dd582f1d88d5c9a1720 + +COUNT = 181 +KEY = fffffffffffffffffffffffffffffffffffffffffffffc000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 72bc65aa8e89562e3f274d45af1cd10b + +COUNT = 182 +KEY = fffffffffffffffffffffffffffffffffffffffffffffe000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 98551da1a6503276ae1c77625f9ea615 + +COUNT = 183 +KEY = ffffffffffffffffffffffffffffffffffffffffffffff000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 0ddfe51ced7e3f4ae927daa3fe452cee + +COUNT = 184 +KEY = ffffffffffffffffffffffffffffffffffffffffffffff800000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = db826251e4ce384b80218b0e1da1dd4c + +COUNT = 185 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffc00000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2cacf728b88abbad7011ed0e64a1680c + +COUNT = 186 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffe00000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 330d8ee7c5677e099ac74c9994ee4cfb + +COUNT = 187 +KEY = fffffffffffffffffffffffffffffffffffffffffffffff00000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = edf61ae362e882ddc0167474a7a77f3a + +COUNT = 188 +KEY = fffffffffffffffffffffffffffffffffffffffffffffff80000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6168b00ba7859e0970ecfd757efecf7c + +COUNT = 189 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffc0000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d1415447866230d28bb1ea18a4cdfd02 + +COUNT = 190 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 516183392f7a8763afec68a060264141 + +COUNT = 191 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 77565c8d73cfd4130b4aa14d8911710f + +COUNT = 192 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 37232a4ed21ccc27c19c9610078cabac + +COUNT = 193 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffc000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 804f32ea71828c7d329077e712231666 + +COUNT = 194 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d64424f23cb97215e9c2c6f28d29eab7 + +COUNT = 195 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 023e82b533f68c75c238cebdb2ee89a2 + +COUNT = 196 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffff800000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 193a3d24157a51f1ee0893f6777417e7 + +COUNT = 197 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffc00000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 84ecacfcd400084d078612b1945f2ef5 + +COUNT = 198 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffe00000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 1dcd8bb173259eb33a5242b0de31a455 + +COUNT = 199 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 35e9eddbc375e792c19992c19165012b + +COUNT = 200 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8a772231c01dfdd7c98e4cfddcc0807a + +COUNT = 201 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffc0000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6eda7ff6b8319180ff0d6e65629d01c3 + +COUNT = 202 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c267ef0e2d01a993944dd397101413cb + +COUNT = 203 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = e9f80e9d845bcc0f62926af72eabca39 + +COUNT = 204 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffff8000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6702990727aa0878637b45dcd3a3b074 + +COUNT = 205 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffc000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2e2e647d5360e09230a5d738ca33471e + +COUNT = 206 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 1f56413c7add6f43d1d56e4f02190330 + +COUNT = 207 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 69cd0606e15af729d6bca143016d9842 + +COUNT = 208 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffff800000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a085d7c1a500873a20099c4caa3c3f5b + +COUNT = 209 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4fc0d230f8891415b87b83f95f2e09d1 + +COUNT = 210 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4327d08c523d8eba697a4336507d1f42 + +COUNT = 211 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 7a15aab82701efa5ae36ab1d6b76290f + +COUNT = 212 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 5bf0051893a18bb30e139a58fed0fa54 + +COUNT = 213 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffc0000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 97e8adf65638fd9cdf3bc22c17fe4dbd + +COUNT = 214 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 1ee6ee326583a0586491c96418d1a35d + +COUNT = 215 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 26b549c2ec756f82ecc48008e529956b + +COUNT = 216 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 70377b6da669b072129e057cc28e9ca5 + +COUNT = 217 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffc000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 9c94b8b0cb8bcc919072262b3fa05ad9 + +COUNT = 218 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2fbb83dfd0d7abcb05cd28cad2dfb523 + +COUNT = 219 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 96877803de77744bb970d0a91f4debae + +COUNT = 220 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffff800000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 7379f3370cf6e5ce12ae5969c8eea312 + +COUNT = 221 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 02dc99fa3d4f98ce80985e7233889313 + +COUNT = 222 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 1e38e759075ba5cab6457da51844295a + +COUNT = 223 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 70bed8dbf615868a1f9d9b05d3e7a267 + +COUNT = 224 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 234b148b8cb1d8c32b287e896903d150 + +COUNT = 225 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 294b033df4da853f4be3e243f7e513f4 + +COUNT = 226 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3f58c950f0367160adec45f2441e7411 + +COUNT = 227 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 37f655536a704e5ace182d742a820cf4 + +COUNT = 228 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ea7bd6bb63418731aeac790fe42d61e8 + +COUNT = 229 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffc000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = e74a4c999b4c064e48bb1e413f51e5ea + +COUNT = 230 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ba9ebefdb4ccf30f296cecb3bc1943e8 + +COUNT = 231 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3194367a4898c502c13bb7478640a72d + +COUNT = 232 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = da797713263d6f33a5478a65ef60d412 + +COUNT = 233 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d1ac39bb1ef86b9c1344f214679aa376 + +COUNT = 234 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2fdea9e650532be5bc0e7325337fd363 + +COUNT = 235 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d3a204dbd9c2af158b6ca67a5156ce4a + +COUNT = 236 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3a0a0e75a8da36735aee6684d965a778 + +COUNT = 237 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 52fc3e620492ea99641ea168da5b6d52 + +COUNT = 238 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d2e0c7f15b4772467d2cfc873000b2ca + +COUNT = 239 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 563531135e0c4d70a38f8bdb190ba04e + +COUNT = 240 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a8a39a0f5663f4c0fe5f2d3cafff421a + +COUNT = 241 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d94b5e90db354c1e42f61fabe167b2c0 + +COUNT = 242 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 50e6d3c9b6698a7cd276f96b1473f35a + +COUNT = 243 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 9338f08e0ebee96905d8f2e825208f43 + +COUNT = 244 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8b378c86672aa54a3a266ba19d2580ca + +COUNT = 245 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = cca7c3086f5f9511b31233da7cab9160 + +COUNT = 246 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 5b40ff4ec9be536ba23035fa4f06064c + +COUNT = 247 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 60eb5af8416b257149372194e8b88749 + +COUNT = 248 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2f005a8aed8a361c92e440c15520cbd1 + +COUNT = 249 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 7b03627611678a997717578807a800e2 + +COUNT = 250 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = cf78618f74f6f3696e0a4779b90b5a77 + +COUNT = 251 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 03720371a04962eaea0a852e69972858 + +COUNT = 252 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 1f8a8133aa8ccf70e2bd3285831ca6b7 + +COUNT = 253 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 27936bd27fb1468fc8b48bc483321725 + +COUNT = 254 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = b07d4f3e2cd2ef2eb545980754dfea0f + +COUNT = 255 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4bf85f1b5d54adbc307b0a048389adcb diff --git a/src/pycryptopp/testvectors/KAT_AES/ECBVarTxt128e.txt b/src/pycryptopp/testvectors/KAT_AES/ECBVarTxt128e.txt new file mode 100644 index 0000000..52dc52c --- /dev/null +++ b/src/pycryptopp/testvectors/KAT_AES/ECBVarTxt128e.txt @@ -0,0 +1,641 @@ +[ENCRYPT] + +COUNT = 0 +KEY = 00000000000000000000000000000000 +PLAINTEXT = 80000000000000000000000000000000 +CIPHERTEXT = 3ad78e726c1ec02b7ebfe92b23d9ec34 + +COUNT = 1 +KEY = 00000000000000000000000000000000 +PLAINTEXT = c0000000000000000000000000000000 +CIPHERTEXT = aae5939c8efdf2f04e60b9fe7117b2c2 + +COUNT = 2 +KEY = 00000000000000000000000000000000 +PLAINTEXT = e0000000000000000000000000000000 +CIPHERTEXT = f031d4d74f5dcbf39daaf8ca3af6e527 + +COUNT = 3 +KEY = 00000000000000000000000000000000 +PLAINTEXT = f0000000000000000000000000000000 +CIPHERTEXT = 96d9fd5cc4f07441727df0f33e401a36 + +COUNT = 4 +KEY = 00000000000000000000000000000000 +PLAINTEXT = f8000000000000000000000000000000 +CIPHERTEXT = 30ccdb044646d7e1f3ccea3dca08b8c0 + +COUNT = 5 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fc000000000000000000000000000000 +CIPHERTEXT = 16ae4ce5042a67ee8e177b7c587ecc82 + +COUNT = 6 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fe000000000000000000000000000000 +CIPHERTEXT = b6da0bb11a23855d9c5cb1b4c6412e0a + +COUNT = 7 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ff000000000000000000000000000000 +CIPHERTEXT = db4f1aa530967d6732ce4715eb0ee24b + +COUNT = 8 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ff800000000000000000000000000000 +CIPHERTEXT = a81738252621dd180a34f3455b4baa2f + +COUNT = 9 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffc00000000000000000000000000000 +CIPHERTEXT = 77e2b508db7fd89234caf7939ee5621a + +COUNT = 10 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffe00000000000000000000000000000 +CIPHERTEXT = b8499c251f8442ee13f0933b688fcd19 + +COUNT = 11 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fff00000000000000000000000000000 +CIPHERTEXT = 965135f8a81f25c9d630b17502f68e53 + +COUNT = 12 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fff80000000000000000000000000000 +CIPHERTEXT = 8b87145a01ad1c6cede995ea3670454f + +COUNT = 13 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffc0000000000000000000000000000 +CIPHERTEXT = 8eae3b10a0c8ca6d1d3b0fa61e56b0b2 + +COUNT = 14 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffe0000000000000000000000000000 +CIPHERTEXT = 64b4d629810fda6bafdf08f3b0d8d2c5 + +COUNT = 15 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffff0000000000000000000000000000 +CIPHERTEXT = d7e5dbd3324595f8fdc7d7c571da6c2a + +COUNT = 16 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffff8000000000000000000000000000 +CIPHERTEXT = f3f72375264e167fca9de2c1527d9606 + +COUNT = 17 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffc000000000000000000000000000 +CIPHERTEXT = 8ee79dd4f401ff9b7ea945d86666c13b + +COUNT = 18 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffe000000000000000000000000000 +CIPHERTEXT = dd35cea2799940b40db3f819cb94c08b + +COUNT = 19 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffff000000000000000000000000000 +CIPHERTEXT = 6941cb6b3e08c2b7afa581ebdd607b87 + +COUNT = 20 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffff800000000000000000000000000 +CIPHERTEXT = 2c20f439f6bb097b29b8bd6d99aad799 + +COUNT = 21 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffc00000000000000000000000000 +CIPHERTEXT = 625d01f058e565f77ae86378bd2c49b3 + +COUNT = 22 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffe00000000000000000000000000 +CIPHERTEXT = c0b5fd98190ef45fbb4301438d095950 + +COUNT = 23 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffff00000000000000000000000000 +CIPHERTEXT = 13001ff5d99806efd25da34f56be854b + +COUNT = 24 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffff80000000000000000000000000 +CIPHERTEXT = 3b594c60f5c8277a5113677f94208d82 + +COUNT = 25 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffc0000000000000000000000000 +CIPHERTEXT = e9c0fc1818e4aa46bd2e39d638f89e05 + +COUNT = 26 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffe0000000000000000000000000 +CIPHERTEXT = f8023ee9c3fdc45a019b4e985c7e1a54 + +COUNT = 27 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffff0000000000000000000000000 +CIPHERTEXT = 35f40182ab4662f3023baec1ee796b57 + +COUNT = 28 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffff8000000000000000000000000 +CIPHERTEXT = 3aebbad7303649b4194a6945c6cc3694 + +COUNT = 29 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffc000000000000000000000000 +CIPHERTEXT = a2124bea53ec2834279bed7f7eb0f938 + +COUNT = 30 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffe000000000000000000000000 +CIPHERTEXT = b9fb4399fa4facc7309e14ec98360b0a + +COUNT = 31 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffff000000000000000000000000 +CIPHERTEXT = c26277437420c5d634f715aea81a9132 + +COUNT = 32 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffff800000000000000000000000 +CIPHERTEXT = 171a0e1b2dd424f0e089af2c4c10f32f + +COUNT = 33 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffc00000000000000000000000 +CIPHERTEXT = 7cadbe402d1b208fe735edce00aee7ce + +COUNT = 34 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffe00000000000000000000000 +CIPHERTEXT = 43b02ff929a1485af6f5c6d6558baa0f + +COUNT = 35 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffff00000000000000000000000 +CIPHERTEXT = 092faacc9bf43508bf8fa8613ca75dea + +COUNT = 36 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffff80000000000000000000000 +CIPHERTEXT = cb2bf8280f3f9742c7ed513fe802629c + +COUNT = 37 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffc0000000000000000000000 +CIPHERTEXT = 215a41ee442fa992a6e323986ded3f68 + +COUNT = 38 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffe0000000000000000000000 +CIPHERTEXT = f21e99cf4f0f77cea836e11a2fe75fb1 + +COUNT = 39 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffff0000000000000000000000 +CIPHERTEXT = 95e3a0ca9079e646331df8b4e70d2cd6 + +COUNT = 40 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffff8000000000000000000000 +CIPHERTEXT = 4afe7f120ce7613f74fc12a01a828073 + +COUNT = 41 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffc000000000000000000000 +CIPHERTEXT = 827f000e75e2c8b9d479beed913fe678 + +COUNT = 42 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffe000000000000000000000 +CIPHERTEXT = 35830c8e7aaefe2d30310ef381cbf691 + +COUNT = 43 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffff000000000000000000000 +CIPHERTEXT = 191aa0f2c8570144f38657ea4085ebe5 + +COUNT = 44 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffff800000000000000000000 +CIPHERTEXT = 85062c2c909f15d9269b6c18ce99c4f0 + +COUNT = 45 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffc00000000000000000000 +CIPHERTEXT = 678034dc9e41b5a560ed239eeab1bc78 + +COUNT = 46 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffe00000000000000000000 +CIPHERTEXT = c2f93a4ce5ab6d5d56f1b93cf19911c1 + +COUNT = 47 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffff00000000000000000000 +CIPHERTEXT = 1c3112bcb0c1dcc749d799743691bf82 + +COUNT = 48 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffff80000000000000000000 +CIPHERTEXT = 00c55bd75c7f9c881989d3ec1911c0d4 + +COUNT = 49 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffc0000000000000000000 +CIPHERTEXT = ea2e6b5ef182b7dff3629abd6a12045f + +COUNT = 50 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffe0000000000000000000 +CIPHERTEXT = 22322327e01780b17397f24087f8cc6f + +COUNT = 51 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffff0000000000000000000 +CIPHERTEXT = c9cacb5cd11692c373b2411768149ee7 + +COUNT = 52 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffff8000000000000000000 +CIPHERTEXT = a18e3dbbca577860dab6b80da3139256 + +COUNT = 53 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffc000000000000000000 +CIPHERTEXT = 79b61c37bf328ecca8d743265a3d425c + +COUNT = 54 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffe000000000000000000 +CIPHERTEXT = d2d99c6bcc1f06fda8e27e8ae3f1ccc7 + +COUNT = 55 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffff000000000000000000 +CIPHERTEXT = 1bfd4b91c701fd6b61b7f997829d663b + +COUNT = 56 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffff800000000000000000 +CIPHERTEXT = 11005d52f25f16bdc9545a876a63490a + +COUNT = 57 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffc00000000000000000 +CIPHERTEXT = 3a4d354f02bb5a5e47d39666867f246a + +COUNT = 58 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffe00000000000000000 +CIPHERTEXT = d451b8d6e1e1a0ebb155fbbf6e7b7dc3 + +COUNT = 59 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffff00000000000000000 +CIPHERTEXT = 6898d4f42fa7ba6a10ac05e87b9f2080 + +COUNT = 60 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffff80000000000000000 +CIPHERTEXT = b611295e739ca7d9b50f8e4c0e754a3f + +COUNT = 61 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffc0000000000000000 +CIPHERTEXT = 7d33fc7d8abe3ca1936759f8f5deaf20 + +COUNT = 62 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffe0000000000000000 +CIPHERTEXT = 3b5e0f566dc96c298f0c12637539b25c + +COUNT = 63 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffff0000000000000000 +CIPHERTEXT = f807c3e7985fe0f5a50e2cdb25c5109e + +COUNT = 64 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffff8000000000000000 +CIPHERTEXT = 41f992a856fb278b389a62f5d274d7e9 + +COUNT = 65 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffc000000000000000 +CIPHERTEXT = 10d3ed7a6fe15ab4d91acbc7d0767ab1 + +COUNT = 66 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffe000000000000000 +CIPHERTEXT = 21feecd45b2e675973ac33bf0c5424fc + +COUNT = 67 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffff000000000000000 +CIPHERTEXT = 1480cb3955ba62d09eea668f7c708817 + +COUNT = 68 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffff800000000000000 +CIPHERTEXT = 66404033d6b72b609354d5496e7eb511 + +COUNT = 69 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffc00000000000000 +CIPHERTEXT = 1c317a220a7d700da2b1e075b00266e1 + +COUNT = 70 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffe00000000000000 +CIPHERTEXT = ab3b89542233f1271bf8fd0c0f403545 + +COUNT = 71 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffff00000000000000 +CIPHERTEXT = d93eae966fac46dca927d6b114fa3f9e + +COUNT = 72 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffff80000000000000 +CIPHERTEXT = 1bdec521316503d9d5ee65df3ea94ddf + +COUNT = 73 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffc0000000000000 +CIPHERTEXT = eef456431dea8b4acf83bdae3717f75f + +COUNT = 74 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffe0000000000000 +CIPHERTEXT = 06f2519a2fafaa596bfef5cfa15c21b9 + +COUNT = 75 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffff0000000000000 +CIPHERTEXT = 251a7eac7e2fe809e4aa8d0d7012531a + +COUNT = 76 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffff8000000000000 +CIPHERTEXT = 3bffc16e4c49b268a20f8d96a60b4058 + +COUNT = 77 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffc000000000000 +CIPHERTEXT = e886f9281999c5bb3b3e8862e2f7c988 + +COUNT = 78 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffe000000000000 +CIPHERTEXT = 563bf90d61beef39f48dd625fcef1361 + +COUNT = 79 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffff000000000000 +CIPHERTEXT = 4d37c850644563c69fd0acd9a049325b + +COUNT = 80 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffff800000000000 +CIPHERTEXT = b87c921b91829ef3b13ca541ee1130a6 + +COUNT = 81 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffc00000000000 +CIPHERTEXT = 2e65eb6b6ea383e109accce8326b0393 + +COUNT = 82 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffe00000000000 +CIPHERTEXT = 9ca547f7439edc3e255c0f4d49aa8990 + +COUNT = 83 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffff00000000000 +CIPHERTEXT = a5e652614c9300f37816b1f9fd0c87f9 + +COUNT = 84 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffff80000000000 +CIPHERTEXT = 14954f0b4697776f44494fe458d814ed + +COUNT = 85 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffc0000000000 +CIPHERTEXT = 7c8d9ab6c2761723fe42f8bb506cbcf7 + +COUNT = 86 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffe0000000000 +CIPHERTEXT = db7e1932679fdd99742aab04aa0d5a80 + +COUNT = 87 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffff0000000000 +CIPHERTEXT = 4c6a1c83e568cd10f27c2d73ded19c28 + +COUNT = 88 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffff8000000000 +CIPHERTEXT = 90ecbe6177e674c98de412413f7ac915 + +COUNT = 89 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffc000000000 +CIPHERTEXT = 90684a2ac55fe1ec2b8ebd5622520b73 + +COUNT = 90 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffe000000000 +CIPHERTEXT = 7472f9a7988607ca79707795991035e6 + +COUNT = 91 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffff000000000 +CIPHERTEXT = 56aff089878bf3352f8df172a3ae47d8 + +COUNT = 92 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffff800000000 +CIPHERTEXT = 65c0526cbe40161b8019a2a3171abd23 + +COUNT = 93 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffc00000000 +CIPHERTEXT = 377be0be33b4e3e310b4aabda173f84f + +COUNT = 94 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffe00000000 +CIPHERTEXT = 9402e9aa6f69de6504da8d20c4fcaa2f + +COUNT = 95 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffff00000000 +CIPHERTEXT = 123c1f4af313ad8c2ce648b2e71fb6e1 + +COUNT = 96 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffff80000000 +CIPHERTEXT = 1ffc626d30203dcdb0019fb80f726cf4 + +COUNT = 97 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffc0000000 +CIPHERTEXT = 76da1fbe3a50728c50fd2e621b5ad885 + +COUNT = 98 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffe0000000 +CIPHERTEXT = 082eb8be35f442fb52668e16a591d1d6 + +COUNT = 99 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffff0000000 +CIPHERTEXT = e656f9ecf5fe27ec3e4a73d00c282fb3 + +COUNT = 100 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffff8000000 +CIPHERTEXT = 2ca8209d63274cd9a29bb74bcd77683a + +COUNT = 101 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffc000000 +CIPHERTEXT = 79bf5dce14bb7dd73a8e3611de7ce026 + +COUNT = 102 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffe000000 +CIPHERTEXT = 3c849939a5d29399f344c4a0eca8a576 + +COUNT = 103 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffff000000 +CIPHERTEXT = ed3c0a94d59bece98835da7aa4f07ca2 + +COUNT = 104 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffff800000 +CIPHERTEXT = 63919ed4ce10196438b6ad09d99cd795 + +COUNT = 105 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffc00000 +CIPHERTEXT = 7678f3a833f19fea95f3c6029e2bc610 + +COUNT = 106 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffe00000 +CIPHERTEXT = 3aa426831067d36b92be7c5f81c13c56 + +COUNT = 107 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffff00000 +CIPHERTEXT = 9272e2d2cdd11050998c845077a30ea0 + +COUNT = 108 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffff80000 +CIPHERTEXT = 088c4b53f5ec0ff814c19adae7f6246c + +COUNT = 109 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffc0000 +CIPHERTEXT = 4010a5e401fdf0a0354ddbcc0d012b17 + +COUNT = 110 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffe0000 +CIPHERTEXT = a87a385736c0a6189bd6589bd8445a93 + +COUNT = 111 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffff0000 +CIPHERTEXT = 545f2b83d9616dccf60fa9830e9cd287 + +COUNT = 112 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffff8000 +CIPHERTEXT = 4b706f7f92406352394037a6d4f4688d + +COUNT = 113 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffc000 +CIPHERTEXT = b7972b3941c44b90afa7b264bfba7387 + +COUNT = 114 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffe000 +CIPHERTEXT = 6f45732cf10881546f0fd23896d2bb60 + +COUNT = 115 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffff000 +CIPHERTEXT = 2e3579ca15af27f64b3c955a5bfc30ba + +COUNT = 116 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffff800 +CIPHERTEXT = 34a2c5a91ae2aec99b7d1b5fa6780447 + +COUNT = 117 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffffc00 +CIPHERTEXT = a4d6616bd04f87335b0e53351227a9ee + +COUNT = 118 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffffe00 +CIPHERTEXT = 7f692b03945867d16179a8cefc83ea3f + +COUNT = 119 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffff00 +CIPHERTEXT = 3bd141ee84a0e6414a26e7a4f281f8a2 + +COUNT = 120 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffff80 +CIPHERTEXT = d1788f572d98b2b16ec5d5f3922b99bc + +COUNT = 121 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffffc0 +CIPHERTEXT = 0833ff6f61d98a57b288e8c3586b85a6 + +COUNT = 122 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffffe0 +CIPHERTEXT = 8568261797de176bf0b43becc6285afb + +COUNT = 123 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffffff0 +CIPHERTEXT = f9b0fda0c4a898f5b9e6f661c4ce4d07 + +COUNT = 124 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffffff8 +CIPHERTEXT = 8ade895913685c67c5269f8aae42983e + +COUNT = 125 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffffffc +CIPHERTEXT = 39bde67d5c8ed8a8b1c37eb8fa9f5ac0 + +COUNT = 126 +KEY = 00000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffffffe +CIPHERTEXT = 5c005e72c1418c44f569f2ea33ba54f3 + +COUNT = 127 +KEY = 00000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffffff +CIPHERTEXT = 3f5b8cc9ea855a0afa7347d23e8d664e diff --git a/src/pycryptopp/testvectors/KAT_AES/ECBVarTxt256e.txt b/src/pycryptopp/testvectors/KAT_AES/ECBVarTxt256e.txt new file mode 100644 index 0000000..2f804e4 --- /dev/null +++ b/src/pycryptopp/testvectors/KAT_AES/ECBVarTxt256e.txt @@ -0,0 +1,641 @@ +[ENCRYPT] + +COUNT = 0 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 80000000000000000000000000000000 +CIPHERTEXT = ddc6bf790c15760d8d9aeb6f9a75fd4e + +COUNT = 1 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = c0000000000000000000000000000000 +CIPHERTEXT = 0a6bdc6d4c1e6280301fd8e97ddbe601 + +COUNT = 2 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = e0000000000000000000000000000000 +CIPHERTEXT = 9b80eefb7ebe2d2b16247aa0efc72f5d + +COUNT = 3 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = f0000000000000000000000000000000 +CIPHERTEXT = 7f2c5ece07a98d8bee13c51177395ff7 + +COUNT = 4 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = f8000000000000000000000000000000 +CIPHERTEXT = 7818d800dcf6f4be1e0e94f403d1e4c2 + +COUNT = 5 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fc000000000000000000000000000000 +CIPHERTEXT = e74cd1c92f0919c35a0324123d6177d3 + +COUNT = 6 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fe000000000000000000000000000000 +CIPHERTEXT = 8092a4dcf2da7e77e93bdd371dfed82e + +COUNT = 7 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ff000000000000000000000000000000 +CIPHERTEXT = 49af6b372135acef10132e548f217b17 + +COUNT = 8 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ff800000000000000000000000000000 +CIPHERTEXT = 8bcd40f94ebb63b9f7909676e667f1e7 + +COUNT = 9 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffc00000000000000000000000000000 +CIPHERTEXT = fe1cffb83f45dcfb38b29be438dbd3ab + +COUNT = 10 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffe00000000000000000000000000000 +CIPHERTEXT = 0dc58a8d886623705aec15cb1e70dc0e + +COUNT = 11 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fff00000000000000000000000000000 +CIPHERTEXT = c218faa16056bd0774c3e8d79c35a5e4 + +COUNT = 12 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fff80000000000000000000000000000 +CIPHERTEXT = 047bba83f7aa841731504e012208fc9e + +COUNT = 13 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffc0000000000000000000000000000 +CIPHERTEXT = dc8f0e4915fd81ba70a331310882f6da + +COUNT = 14 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffe0000000000000000000000000000 +CIPHERTEXT = 1569859ea6b7206c30bf4fd0cbfac33c + +COUNT = 15 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffff0000000000000000000000000000 +CIPHERTEXT = 300ade92f88f48fa2df730ec16ef44cd + +COUNT = 16 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffff8000000000000000000000000000 +CIPHERTEXT = 1fe6cc3c05965dc08eb0590c95ac71d0 + +COUNT = 17 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffc000000000000000000000000000 +CIPHERTEXT = 59e858eaaa97fec38111275b6cf5abc0 + +COUNT = 18 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffe000000000000000000000000000 +CIPHERTEXT = 2239455e7afe3b0616100288cc5a723b + +COUNT = 19 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffff000000000000000000000000000 +CIPHERTEXT = 3ee500c5c8d63479717163e55c5c4522 + +COUNT = 20 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffff800000000000000000000000000 +CIPHERTEXT = d5e38bf15f16d90e3e214041d774daa8 + +COUNT = 21 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffc00000000000000000000000000 +CIPHERTEXT = b1f4066e6f4f187dfe5f2ad1b17819d0 + +COUNT = 22 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffe00000000000000000000000000 +CIPHERTEXT = 6ef4cc4de49b11065d7af2909854794a + +COUNT = 23 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffff00000000000000000000000000 +CIPHERTEXT = ac86bc606b6640c309e782f232bf367f + +COUNT = 24 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffff80000000000000000000000000 +CIPHERTEXT = 36aff0ef7bf3280772cf4cac80a0d2b2 + +COUNT = 25 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffc0000000000000000000000000 +CIPHERTEXT = 1f8eedea0f62a1406d58cfc3ecea72cf + +COUNT = 26 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffe0000000000000000000000000 +CIPHERTEXT = abf4154a3375a1d3e6b1d454438f95a6 + +COUNT = 27 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffff0000000000000000000000000 +CIPHERTEXT = 96f96e9d607f6615fc192061ee648b07 + +COUNT = 28 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffff8000000000000000000000000 +CIPHERTEXT = cf37cdaaa0d2d536c71857634c792064 + +COUNT = 29 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffc000000000000000000000000 +CIPHERTEXT = fbd6640c80245c2b805373f130703127 + +COUNT = 30 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffe000000000000000000000000 +CIPHERTEXT = 8d6a8afe55a6e481badae0d146f436db + +COUNT = 31 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffff000000000000000000000000 +CIPHERTEXT = 6a4981f2915e3e68af6c22385dd06756 + +COUNT = 32 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffff800000000000000000000000 +CIPHERTEXT = 42a1136e5f8d8d21d3101998642d573b + +COUNT = 33 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffc00000000000000000000000 +CIPHERTEXT = 9b471596dc69ae1586cee6158b0b0181 + +COUNT = 34 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffe00000000000000000000000 +CIPHERTEXT = 753665c4af1eff33aa8b628bf8741cfd + +COUNT = 35 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffff00000000000000000000000 +CIPHERTEXT = 9a682acf40be01f5b2a4193c9a82404d + +COUNT = 36 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffff80000000000000000000000 +CIPHERTEXT = 54fafe26e4287f17d1935f87eb9ade01 + +COUNT = 37 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffc0000000000000000000000 +CIPHERTEXT = 49d541b2e74cfe73e6a8e8225f7bd449 + +COUNT = 38 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffe0000000000000000000000 +CIPHERTEXT = 11a45530f624ff6f76a1b3826626ff7b + +COUNT = 39 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffff0000000000000000000000 +CIPHERTEXT = f96b0c4a8bc6c86130289f60b43b8fba + +COUNT = 40 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffff8000000000000000000000 +CIPHERTEXT = 48c7d0e80834ebdc35b6735f76b46c8b + +COUNT = 41 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffc000000000000000000000 +CIPHERTEXT = 2463531ab54d66955e73edc4cb8eaa45 + +COUNT = 42 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffe000000000000000000000 +CIPHERTEXT = ac9bd8e2530469134b9d5b065d4f565b + +COUNT = 43 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffff000000000000000000000 +CIPHERTEXT = 3f5f9106d0e52f973d4890e6f37e8a00 + +COUNT = 44 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffff800000000000000000000 +CIPHERTEXT = 20ebc86f1304d272e2e207e59db639f0 + +COUNT = 45 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffc00000000000000000000 +CIPHERTEXT = e67ae6426bf9526c972cff072b52252c + +COUNT = 46 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffe00000000000000000000 +CIPHERTEXT = 1a518dddaf9efa0d002cc58d107edfc8 + +COUNT = 47 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffff00000000000000000000 +CIPHERTEXT = ead731af4d3a2fe3b34bed047942a49f + +COUNT = 48 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffff80000000000000000000 +CIPHERTEXT = b1d4efe40242f83e93b6c8d7efb5eae9 + +COUNT = 49 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffc0000000000000000000 +CIPHERTEXT = cd2b1fec11fd906c5c7630099443610a + +COUNT = 50 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffe0000000000000000000 +CIPHERTEXT = a1853fe47fe29289d153161d06387d21 + +COUNT = 51 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffff0000000000000000000 +CIPHERTEXT = 4632154179a555c17ea604d0889fab14 + +COUNT = 52 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffff8000000000000000000 +CIPHERTEXT = dd27cac6401a022e8f38f9f93e774417 + +COUNT = 53 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffc000000000000000000 +CIPHERTEXT = c090313eb98674f35f3123385fb95d4d + +COUNT = 54 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffe000000000000000000 +CIPHERTEXT = cc3526262b92f02edce548f716b9f45c + +COUNT = 55 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffff000000000000000000 +CIPHERTEXT = c0838d1a2b16a7c7f0dfcc433c399c33 + +COUNT = 56 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffff800000000000000000 +CIPHERTEXT = 0d9ac756eb297695eed4d382eb126d26 + +COUNT = 57 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffc00000000000000000 +CIPHERTEXT = 56ede9dda3f6f141bff1757fa689c3e1 + +COUNT = 58 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffe00000000000000000 +CIPHERTEXT = 768f520efe0f23e61d3ec8ad9ce91774 + +COUNT = 59 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffff00000000000000000 +CIPHERTEXT = b1144ddfa75755213390e7c596660490 + +COUNT = 60 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffff80000000000000000 +CIPHERTEXT = 1d7c0c4040b355b9d107a99325e3b050 + +COUNT = 61 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffc0000000000000000 +CIPHERTEXT = d8e2bb1ae8ee3dcf5bf7d6c38da82a1a + +COUNT = 62 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffe0000000000000000 +CIPHERTEXT = faf82d178af25a9886a47e7f789b98d7 + +COUNT = 63 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffff0000000000000000 +CIPHERTEXT = 9b58dbfd77fe5aca9cfc190cd1b82d19 + +COUNT = 64 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffff8000000000000000 +CIPHERTEXT = 77f392089042e478ac16c0c86a0b5db5 + +COUNT = 65 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffc000000000000000 +CIPHERTEXT = 19f08e3420ee69b477ca1420281c4782 + +COUNT = 66 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffe000000000000000 +CIPHERTEXT = a1b19beee4e117139f74b3c53fdcb875 + +COUNT = 67 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffff000000000000000 +CIPHERTEXT = a37a5869b218a9f3a0868d19aea0ad6a + +COUNT = 68 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffff800000000000000 +CIPHERTEXT = bc3594e865bcd0261b13202731f33580 + +COUNT = 69 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffc00000000000000 +CIPHERTEXT = 811441ce1d309eee7185e8c752c07557 + +COUNT = 70 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffe00000000000000 +CIPHERTEXT = 959971ce4134190563518e700b9874d1 + +COUNT = 71 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffff00000000000000 +CIPHERTEXT = 76b5614a042707c98e2132e2e805fe63 + +COUNT = 72 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffff80000000000000 +CIPHERTEXT = 7d9fa6a57530d0f036fec31c230b0cc6 + +COUNT = 73 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffc0000000000000 +CIPHERTEXT = 964153a83bf6989a4ba80daa91c3e081 + +COUNT = 74 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffe0000000000000 +CIPHERTEXT = a013014d4ce8054cf2591d06f6f2f176 + +COUNT = 75 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffff0000000000000 +CIPHERTEXT = d1c5f6399bf382502e385eee1474a869 + +COUNT = 76 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffff8000000000000 +CIPHERTEXT = 0007e20b8298ec354f0f5fe7470f36bd + +COUNT = 77 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffc000000000000 +CIPHERTEXT = b95ba05b332da61ef63a2b31fcad9879 + +COUNT = 78 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffe000000000000 +CIPHERTEXT = 4620a49bd967491561669ab25dce45f4 + +COUNT = 79 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffff000000000000 +CIPHERTEXT = 12e71214ae8e04f0bb63d7425c6f14d5 + +COUNT = 80 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffff800000000000 +CIPHERTEXT = 4cc42fc1407b008fe350907c092e80ac + +COUNT = 81 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffc00000000000 +CIPHERTEXT = 08b244ce7cbc8ee97fbba808cb146fda + +COUNT = 82 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffe00000000000 +CIPHERTEXT = 39b333e8694f21546ad1edd9d87ed95b + +COUNT = 83 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffff00000000000 +CIPHERTEXT = 3b271f8ab2e6e4a20ba8090f43ba78f3 + +COUNT = 84 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffff80000000000 +CIPHERTEXT = 9ad983f3bf651cd0393f0a73cccdea50 + +COUNT = 85 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffc0000000000 +CIPHERTEXT = 8f476cbff75c1f725ce18e4bbcd19b32 + +COUNT = 86 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffe0000000000 +CIPHERTEXT = 905b6267f1d6ab5320835a133f096f2a + +COUNT = 87 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffff0000000000 +CIPHERTEXT = 145b60d6d0193c23f4221848a892d61a + +COUNT = 88 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffff8000000000 +CIPHERTEXT = 55cfb3fb6d75cad0445bbc8dafa25b0f + +COUNT = 89 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffc000000000 +CIPHERTEXT = 7b8e7098e357ef71237d46d8b075b0f5 + +COUNT = 90 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffe000000000 +CIPHERTEXT = 2bf27229901eb40f2df9d8398d1505ae + +COUNT = 91 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffff000000000 +CIPHERTEXT = 83a63402a77f9ad5c1e931a931ecd706 + +COUNT = 92 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffff800000000 +CIPHERTEXT = 6f8ba6521152d31f2bada1843e26b973 + +COUNT = 93 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffc00000000 +CIPHERTEXT = e5c3b8e30fd2d8e6239b17b44bd23bbd + +COUNT = 94 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffe00000000 +CIPHERTEXT = 1ac1f7102c59933e8b2ddc3f14e94baa + +COUNT = 95 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffff00000000 +CIPHERTEXT = 21d9ba49f276b45f11af8fc71a088e3d + +COUNT = 96 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffff80000000 +CIPHERTEXT = 649f1cddc3792b4638635a392bc9bade + +COUNT = 97 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffc0000000 +CIPHERTEXT = e2775e4b59c1bc2e31a2078c11b5a08c + +COUNT = 98 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffe0000000 +CIPHERTEXT = 2be1fae5048a25582a679ca10905eb80 + +COUNT = 99 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffff0000000 +CIPHERTEXT = da86f292c6f41ea34fb2068df75ecc29 + +COUNT = 100 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffff8000000 +CIPHERTEXT = 220df19f85d69b1b562fa69a3c5beca5 + +COUNT = 101 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffc000000 +CIPHERTEXT = 1f11d5d0355e0b556ccdb6c7f5083b4d + +COUNT = 102 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffe000000 +CIPHERTEXT = 62526b78be79cb384633c91f83b4151b + +COUNT = 103 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffff000000 +CIPHERTEXT = 90ddbcb950843592dd47bbef00fdc876 + +COUNT = 104 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffff800000 +CIPHERTEXT = 2fd0e41c5b8402277354a7391d2618e2 + +COUNT = 105 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffc00000 +CIPHERTEXT = 3cdf13e72dee4c581bafec70b85f9660 + +COUNT = 106 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffe00000 +CIPHERTEXT = afa2ffc137577092e2b654fa199d2c43 + +COUNT = 107 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffff00000 +CIPHERTEXT = 8d683ee63e60d208e343ce48dbc44cac + +COUNT = 108 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffff80000 +CIPHERTEXT = 705a4ef8ba2133729c20185c3d3a4763 + +COUNT = 109 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffc0000 +CIPHERTEXT = 0861a861c3db4e94194211b77ed761b9 + +COUNT = 110 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffe0000 +CIPHERTEXT = 4b00c27e8b26da7eab9d3a88dec8b031 + +COUNT = 111 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffff0000 +CIPHERTEXT = 5f397bf03084820cc8810d52e5b666e9 + +COUNT = 112 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffff8000 +CIPHERTEXT = 63fafabb72c07bfbd3ddc9b1203104b8 + +COUNT = 113 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffc000 +CIPHERTEXT = 683e2140585b18452dd4ffbb93c95df9 + +COUNT = 114 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffe000 +CIPHERTEXT = 286894e48e537f8763b56707d7d155c8 + +COUNT = 115 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffff000 +CIPHERTEXT = a423deabc173dcf7e2c4c53e77d37cd1 + +COUNT = 116 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffff800 +CIPHERTEXT = eb8168313e1cfdfdb5e986d5429cf172 + +COUNT = 117 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffffc00 +CIPHERTEXT = 27127daafc9accd2fb334ec3eba52323 + +COUNT = 118 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffffe00 +CIPHERTEXT = ee0715b96f72e3f7a22a5064fc592f4c + +COUNT = 119 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffff00 +CIPHERTEXT = 29ee526770f2a11dcfa989d1ce88830f + +COUNT = 120 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffff80 +CIPHERTEXT = 0493370e054b09871130fe49af730a5a + +COUNT = 121 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffffc0 +CIPHERTEXT = 9b7b940f6c509f9e44a4ee140448ee46 + +COUNT = 122 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffffe0 +CIPHERTEXT = 2915be4a1ecfdcbe3e023811a12bb6c7 + +COUNT = 123 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffffff0 +CIPHERTEXT = 7240e524bc51d8c4d440b1be55d1062c + +COUNT = 124 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffffff8 +CIPHERTEXT = da63039d38cb4612b2dc36ba26684b93 + +COUNT = 125 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffffffc +CIPHERTEXT = 0f59cb5a4b522e2ac56c1a64f558ad9a + +COUNT = 126 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffffffe +CIPHERTEXT = 7bfe9d876c6d63c1d035da8fe21c409d + +COUNT = 127 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffffff +CIPHERTEXT = acdace8078a32b1a182bfa4987ca1347 diff --git a/src/pycryptopp/testvectors/SHA256LongMsg.txt b/src/pycryptopp/testvectors/SHA256LongMsg.txt new file mode 100644 index 0000000..47943d9 --- /dev/null +++ b/src/pycryptopp/testvectors/SHA256LongMsg.txt @@ -0,0 +1,263 @@ +# CAVS 5.0 +# "SHA-256 LongMsg" information for "s" +# SHA-256 tests are configured for BYTE oriented implementations +# Generated on Wed Feb 08 14:59:33 2006 + +[L = 32] + +Len = 1304 +Msg = ebaccc34d6d6d3d21ed0ad2ba7c07c21d253c4814f4ad89d32369237497f47a1adabfa2398ddd09d769cc46d3fd69c9303251c13c750799b8f151166bc2658609871168b30a4d0a162f183fb360f99b172811503681a11f813c16a446272ba6fd48586344533b9280856519c357059c344ef1718dbaf86fae5c10799e46b5316886fb4e68090757890539617e403c511a4f78a19c818c2ea2e9d4e2de9190c9dddb806 +MD = c907180443dee3cbccb4c31328e625158527a593b878de1b8e4ba37f1d69fb66 + +Len = 2096 +Msg = f6ce8221bf64273c91c4cb41ebba1bfcfa12c043c701317eb0c0cb66157a230c53689b1df63b33652abaa29373aca63c9ef89822f80b43b5bd7af6dad3e8d8ecb82b7c00baaab56e6609ac8d42092fbdbfa94cab69921fd061b1e83b0d2660910e5d4e52727a555d2bfb10b7c0986188436e0566835d6cd682afc8102afa65033b4738998873ba3c63d6f7995623e1a4148febdcae36d3d00ababfe2922d8c4b2931635f635d8d12f5e388bc6a705a191854259453e3fcc5e01bf538ac877f70be62f62b6b0075e8c96aeca7664972f03905dc16d82d8ebdec1a919ae2cfe67ae4241a8608241bc5c7b34ae2b074d1305de937eba7dc32c116febc909bcf687282bdf7f7a290 +MD = efd35c0d49e6a22c2b54599abb0dfa419435a5b749ef1c7123d59a2fb5db8f75 + +Len = 2888 +Msg = 1c5b8bdf2aa1a8feb0acf02f3fda16ebbc8bccaf053386aad7ae80b9f0d40296704ee34d85a84cef47a6be89e1dc5657f27950363364cb58598acb3b3d7684dc3a22d628d60c14b3a58d09ac6b663d11819c741f7a87780d052518f915b47123407f6c5965f888b29207da7f25a2527f319e3f5223c41530a5286edbc2b650d24b0eaec87a923154d6bc38ea56b61d0ac924bab775442b2bff3ad6c98ba5a9532376a35d5d02960238562bd548ca261a13d9eb37ba2f4165dc0457abb7a9050d9060530155713f22827abb284107f618d562dcb838ade046032df9698fe9ea685a74c79aac07b51e7ad2f1cb8a94146ad86a952339e48f363e5ec4ec5b8ee3cc48590611a8eb7f5ce906d4a76b9a087ae4971c6103ffd69d533fc11a63bf75a124b8184f9246254696be6ca22b415bafc1917b59de243de30b77f7dceea52a4fb438063bb23f30424ba1c2a514b094703601baf2147c4d702eaf6f1b4567893ec182d7bc4fff27bace +MD = 9d2bc3b2987a7274e05e74e3cc566440296832a28643884b49bfcd6ede1057ff + +Len = 3680 +Msg = 2ddf06cb013f9267b1e5c0bb535d7d54572ad06d170a0e58ae7c4d1f0e801a6a4d9e6fa34029df594bc514e277277b45c51c3e57c3cd73235c41938ff4232d3db5c6dbb0236676b0f7b186ef2a85fcec50fc241827a6d5387015eb0afd9ff62b0c5f3438d37dbd335caffe29930068129ed169f96c1d9c5d91013dd6517bdffcfa72618478f61eac23ca64dadb1f287f57a3f742baba305b670b713c173f4f7729054adc395affe1f307a048296ba2fb247ab53b3806f9f99b3e6f847874ae653e23d7873e30ca9c75709abba66b3f4ead5f8b2b0f886001d59f1ff69ba1638ee4d1f0cfb000e6a3510c3b7d7aa7673f9959615c66c8cb39bc3869daa94ed8bac1197dfab753bbbe2ee369d5cca7839890711f14664fa36bf9103677c90374b17d0266517aafb1b7b4fe0d0ac4f4f91f3caeae9c37a4515d342f6c1624499f3ac194931c229f30558c6410658c15339d4218f43c00503bd8149ef5ffe1a7c11f35d8eca3d6a8a05f5e1d582e499297d94db7da3bead9cba34164b77a29a6422680d55a2dbf54699ed132cfad26f48f9d039448e31cc9688864899ccf24cc8b184a94c304042af3da8eaa5c2949c182af0cb6277abea7794d25168b45f9a402bc3d1b116ecfb2a7da3d8de6ec +MD = f14720e0e460e1b0c4be8e44b25bf4bfae05267749c1ef4f33e0ac35176712f4 + +Len = 4472 +Msg = 5ba171c9571cf2b394b38724eedca061e72955ad021cefbe6c3eaa72e16bb9bfce708be8b3d84df7cc02b067f077ec21b97b05aae5e24c9afc252a5033b519e4918ff35d50116f24860ce8b9051a61a57f32c7b0ee797553325bfe70fcdb2641ec27318ff67061240af8ba82f46d08d581752327e38a72d35608ae3c0484e8be2660cee56d9c2adda0efab2a8617e899066da2778dbc4900b053c21a13596844896151c97c3ed2399019451983c109da5841cb08b4b804c48865c374f002adb95b5342a2edfe621f219d0fb8b312747ebd1a26422026ab06256639b16426bf07e55d2ad78683e1769ca4916dddb3306f7e203c8e98ac44aed07daa39376da7146fa88fd210765728495554a1cb4b4593e27a9452e5f5d9a3d1d2a07431816cca415cfcfa527ecc1c70d9dfbd4383bcd43351b7f7cfa771cf708ea2ca1907160fa2a0f6b71644493a5957ba270e039c19b7cc2be61e6b1519f5d939a3b9aaaecddc9c07712270d56a4cf86e49f472ed49b8147a869ae8cc69a7daeb67d7103beb3579b6903fa9799490e4828abc78b84e7c502b3e0bc79ea7cfba437e3ce1c551f65f8b7c35973ca06e427e5130be040f4ca9c77838af93bbb5a0c650b0c655e766750f9ecce326762e3aeb0816ecd9746f47d59bea49b48ea1b5fe45fb66f195cfe4c95ccc353fff18f6501637aa3f652f51dd0fe93d0806db2172c6e46ba44377d3421ffc349021739b35e35b9e3fcad2f0683bfd32970caa0baa39347a73d9a76b0050258920c5895422d74973e0 +MD = 81197ebe77012c262a00d99888e261dd28fe6ff91aa1f7cb4e487f3561aad9f0 + +Len = 5264 +Msg = 19172bbbd984215e9c6e0508dc3c34f2f5a710477cc1f640d335708dfad0abf8a8402b459b1cbd5c2c25adaa26cc3ac4d8f4474d69f8531b6cf0ab95b430de5f6a12723a5cf6d525988696c83a3fd513822df9232af5a165f619dcfd8c789c6986146861c6185202091a292cbf9def291bda8d8f66c0c66798396a8e29afcc5c25cf75847f8c1a3ba767cc9d5eee6f4cca836d5ac55fac697bd7bd1034dd56816ec902692f5a171899f7e8e2bf3b3dc5b7b1004cf1dc39b2c67b3d4b540a21208a8c75d97f882fe10852e6c4898b41dc0bebae2c8f3e578ca2ad5207323f1781a0a0389c16204cdd1bfe2c0b65e763d8eebadfc44a8eed3d37f6640b76841febd98bb17a9e295555fb85247ffa568b0387a5fbdac7d3e20eacdddb20c7df21a85dd74a3bbcac3291cf6f35e7f1e0a1a3ff346a37b11520472aeb1f0ecd5a06fe530b6aa61ab0cbd9c042c60df18d8d017def95a3ae5d8e30d8a6989d31fcb436e3b07885603d0875f68841b7a36637652a5fe2e566b21411df98ae949bcd1497374dde9e365bd1ac98c80daeae7287162e0bbac7831c9a316649cabdb2d60e6b746a03b942130ec8cf8b92babcba665eb07b860faaa308d9964052de1f1e8bf8c5904fa02f6ca70fc25838a27244ba83d838ac86855046519705b0c08aad718850452a1aa36f84ca9ab767307a1a6dcecfc996f4bc2a3de190204a2b998caa613d14fcee46238d407e30872a7c446587bdb6aa21f739d3d1a91a8ae7f7c21ccbb5822de5c290abbb974c00591fc88cf6ca8852d4dd86f1680c79d7bb4a57b110e01925c7bcbec4810c923a850cb0c8631cc6f5d7161880efdec898703b544f77e5604d5cdfb6c1db068b9e76eb040315def8faf04bf866ae4a8c37ce71c0e047ecdf0b6bd07f8b11adbd92f363ca245536a7 +MD = 8dfdfb63612074044698085316cb4ee2032127c72425269eca374173aa60df95 + +Len = 6056 +Msg = b37f522011a07e325b88bae54cd1c64ac6aaa89e21d8a06ec3fb5efef01373ece44206111fd4c8a8017c2ab296e0cd99b358391342f3d349dabc0939933bd058183e507cfdd9ddfa53ab2a0b7a63b97537839667066445a4b27af9e322da077676f9992b53b7a7707a9c23baa06174277ab226621732e0c772c096c748f9ff8e27fd4ae4c8760d519ed77e85afe2e5f6a36d51cb1a658af9431348acab9ea2e852d2c970041ff6e7e6e5a13550eff42cda3d7f6cba062d834dfd7759f3d4d7cc20fe8097b0ba4c787b4df6922a8e891049a8180b9d1cb0adb7058b97c9a08681b90bd520744df64d8597e363e6ca8ce9153884716baffbbfaab4ec2ed50c9750448132d5f7e2dcae2b4cd2722ba8e50069752c66cdc8f6014d9002e6be1ff381e9e6fe7ce280e6e295f32a85a2327d9d6be676b16a6d89bbc92336872ce1805cd2c4a1dedc30fc33ec145365f26f3a074313cb1ceca99c3445f5eed8c95b272824a283c38ef906e75837b5dac46705881a84946df88117b5ea8c93a23a94d12f0a090cf39fe3ec4700e5b8abc023c76618c2376d39ffe286df728ead2a9464b7aa80a435b8f6969b0da5c4a28daa66ea64541ee4542ae5ef4d2f45c13f64ca092c8fb352813bec2ba6004185d404cc5c27c2af9af40a09385c4922a6210be96db9bea113a1b9d73ef47d971d3c3adf0488955456bfa834a8334a8c237991ab2a7996d63dc1783d1e1fa42e326e538929b05474e25d0b4f88fbbaeb02effff68a939eba9b888108114efd6e8c1157b015c6877604773b4320db1fa6092a5cb4d32f5eb5f49fdb1e60a911c0f2ce4f3e0ef3b6c485b541f6b8fc032701d3b0cc4e775f300fad8e695359678a2d4d421a5d5f6ac52cbe24529886edd5b191042643912891b55ba3cf318687350635382c4a312ae1c33bec3e08a06618e30d5faafaa54242ae51213a4457fa2a422f395c1c927f8010d3a2a14f72f5585defc940badc33a9c2361091d2f547d0ace24e921da9f00add2f4d65b62522fde8de4ad0cd5d8530b9b379bc2488f68e0bf77eb6939f05e7f0f6 +MD = 54e0c23db7b3fd43e6c7b947d2585480475c2080815744ea40268fd0886e7954 + +Len = 6848 +Msg = a10c4b7bd10fc6bd35a7f0ab6951614de7ef81397a6e9d5af5a63bf02481abd80360df0e2eba7d70990631c481dc48fda2577bbaabbd0810ef6208895dc9fc6cb20da93fed7f268b039133dfd5f3cc175ffbfede324afa7224ad68a84641fd2f16db5018f6a6e996dd0e9b034ddd152485a4b3aef75d9a09fc4e0353c731d7a897917da13177ef1a8e461439d1e44aac7c1a4131e23e105ce00f8295c8e0b1609ef9d7e1873a609f7e014488494e9335ab255270dc3485f336b68d733197b4dd91d907e0de3664ab1507d3f89d6419497c8d8b71cb882157670ccbf7ea9e08a9dafab4a620b421c8bb1f6a91b56e046f5619963e99830b0fdcd9e528db3dd44cdf24873c33fcc27dd813b15c79b47c30a1931bdf2c6a6ca3fce5820eedbc404c0a1e27a901566d52d4a94f60d27da812c6c1c15a6e886b9c2ef74bb206627633c2b23ef5700a4bd017aaeda5a613b09f2b6b31b945243181dcd9e81b0f789b886ea671296a5f837e09dd3234dfbcbd5f395b13049b85e5da6d510051f146dad478c36a4bd69e3de5130cc71463c1f7d958580e4157f4b03049283b5d9214599e47d1d1669b10a38b9bfd534d1c6a8595f129ca7a61b9ba09d8264346dc2a406e43984d7fa3fadafa0b797fe8f0fe8f1b6a97f0b6a11c2af08112bd14b6cfb8ccd4df87a0d5a70dbac948f3ecc9c73ff42d6a28feff65286aafb554d0074de941627027d0195e62513f3256618e0bbba7a06a195963dbde01c7d8ae81b9eafa545511d41857660149d3ff505027132bbc2d5e6ccfb5c7723c3241732fb3ef138e158b367e7708132aef768bc07b27b8bb3b10c868dd710ca358b94ce2dda45e760aa6f60d628cc07afa61acb9748e8a2d3146d62dc321d5bfa107e1a31f5000949d29bccafe3a2fc35c865e43f992c89a79c93e254f1ff41776f5d979613c247034de2fbf3459898c7cad4767f3799a887a61a7586ab292343d49dc6d8bb1f093398bf8f3ed33f55ec4a00f2c488c29819cd5b9cffa24d79c60cc948685f58c8412f9bf6e0f0e9cc09b265f9be1139d0c47ef1d91e8bbead94546a6cc375021cb29f02b398333a63a6906dfbaa6561eb2e3757ba61dc0f473567fbd478a0cd7f1e438e45b32ea3a54970936937f9cd2f9d8307a17807a1cf0f93e7f006470d57dad9893dc037b80978bf70c2e552fe46c8fe8c3ebf8338bda +MD = b057d3eebc727da07a2dfbdbd6b4d6617dd7195771daf7de563c2919c8632cfd + +Len = 7640 +Msg = 8390cf0be07661cc7669aac54ce09a37733a629d45f5d983ef201f9b2d13800e555d9b1097fec3b783d7a50dcb5e2b644b96a1e9463f177cf34906bf388f366db5c2deee04a30e283f764a97c3b377a034fefc22c259214faa99babaff160ab0aaa7e2ccb0ce09c6b32fe08cbc474694375aba703fadbfa31cf685b30a11c57f3cf4edd321e57d3ae6ebb1133c8260e75b9224fa47a2bb205249add2e2e62f817491482ae152322be0900355cdcc8d42a98f82e961a0dc6f537b7b410eff105f59673bfb787bf042aa071f7af68d944d27371c64160fe9382772372516c230c1f45c0d6b6cca7f274b394da9402d3eafdf733994ec58ab22d71829a98399574d4b5908a447a5a681cb0dd50a31145311d92c22a16de1ead66a5499f2dceb4cae694772ce90762ef8336afec653aa9b1a1c4820b221136dfce80dce2ba920d88a530c9410d0a4e0358a3a11052e58dd73b0b179ef8f56fe3b5a2d117a73a0c38a1392b6938e9782e0d86456ee4884e3c39d4d75813f13633bc79baa07c0d2d555afbf207f52b7dca126d015aa2b9873b3eb065e90b9b065a5373fe1fb1b20d594327d19fba56cb81e7b6696605ffa56eba3c27a438697cc21b201fd7e09f18deea1b3ea2f0d1edc02df0e20396a145412cd6b13c32d2e605641c948b714aec30c0649dc44143511f35ab0fd5dd64c34d06fe86f3836dfe9edeb7f08cfc3bd40956826356242191f99f53473f32b0cc0cf9321d6c92a112e8db90b86ee9e87cc32d0343db01e32ce9eb782cb24efbbbeb440fe929e8f2bf8dfb1550a3a2e742e8b455a3e5730e9e6a7a9824d17acc0f72a7f67eae0f0970f8bde46dcdefaed3047cf807e7f00a42e5fd11d40f5e98533d7574425b7d2bc3b3845c443008b58980e768e464e17cc6f6b3939eee52f713963d07d8c4abf02448ef0b889c9671e2f8a436ddeeffcca7176e9bf9d1005ecd377f2fa67c23ed1f137e60bf46018a8bd613d038e883704fc26e798969df35ec7bbc6a4fe46d8910bd82fa3cded265d0a3b6d399e4251e4d8233daa21b5812fded6536198ff13aa5a1cd46a5b9a17a4ddc1d9f85544d1d1cc16f3df858038c8e071a11a7e157a85a6a8dc47e88d75e7009a8b26fdb73f33a2a70f1e0c259f8f9533b9b8f9af9288b7274f21baeec78d396f8bacdcc22471207d9b4efccd3fedc5c5a2214ff5e51c553f35e21ae696fe51e8df733a8e06f50f419e599e9f9e4b37ce643fc810faaa47989771509d69a110ac916261427026369a21263ac4460fb4f708f8ae28599856db7cb6a43ac8e03d64a9609807e76c5f312b9d1863bfa304e8953647648b4f4ab0ed995e +MD = 4109cdbec3240ad74cc6c37f39300f70fede16e21efc77f7865998714aad0b5e + +Len = 8432 +Msg = 491b02a46a098a5c96c4d541d1961c7e2b9a15bb37690de6bff63733b6b744616e0633400cc66b703849076b197171c5801632b363a808cb8e16390a95ee281b0dc526d6fbd98a088df5047208952e14024b64abd161d67843c0db43901089a08c218271218a10acfd90755e88497cf0190154a969dc9e7548bdc5e58e678e7655e2f016652125e4f0e1013880d483e32dffaab81360894b03d59ef879396027ced017cfafe5f039ceb15107d77f6a74a60e0dddb737bf81decf0f8538cf263b61b2a0a3e71f9a32ffc80cd377925a2cecf625223da7679f3f75bf92b37109387552329bf6174a58ebeedba447557a91677f9b8e8df9aa2d908d572ad26731a8717676bdc2152931fbeb66832f0ff32d807017299075afb438e07e527df8c512bfe7131334615f4795865477170aec889d9340fc2c629fbc9f36dd149c6dedffc66db2a53442132223884e89e78c8e2828aebf0e4a0aa1cb2d571b77170ed3f6eecffb79ab026e480bbafbc087de0097878a3b68d3b3de6b4a0ae183d6239c7f9fd795997fe79743b7e10424e0486b5d24ef5d10ada67d235e18d741c1f47322414b290d9a3ab69b8dc810bdd811f70065a5cd10c22ba77bd14aa4b8c1c97e683cf45edbe242f5d6f736c8945883cb0ab4733270f88984fc0b66f1f1bce9e5d8f99add0d41497a7e5bf2d3b049e4100378223536390a3b2d753465f29b9dd1fbde054eab9e956d1a23c5db19917ded71187a7d6c6cf4f597757ea9c5472d6a5754fc57bbe06ff733b67785d81a968bdefe43b3197990d9c0740a6472a7e1d776c449a347f11f40507cd07bf4ca7712d191457e4647261032dba13fffa20041e094b2d856b8ed6ff9dd9865758b67a9d3394887fac0fec175100be27622d4cf1b2e009ff11d21acb74196ea6444b0786b5e13753dcb5f150f7d10f4de0ea3aab1f8fb9f1f080221101093b3c8dd98a821686ff1175093348a88781e404db6f92a5c6a81e861d9f38eb25768a93d68617dc024a39138e0456e9b0a07a3c955e50cc016ec5410ee4db990aab00f4e67ca08ccfa32b2698f70411d8f570f69c896e18ec8896cfe89551810543303f7df0c49f5b94783cce7df8d76d0b88d155633302d46003711f233339b1c9a8c20164ec8a328890a4932b7d90d92d023b548e4820558f8bd327010929acb8db3b155b90e3f10a151c9b623ae4ca047dc32e6d35e7ec819074a4d14be7329b37f93e475a22f39366032bd49939ac1c6bd7278254c005d0c1c3fcf663e90feb5f8ac0ba90cdd6bf13d6e8d51105fbcf5d05e4605d4f3de7905fb3f2f9a57123a26e5127ed5af6e7af2636e64ad045a7b1cde98997fbf1407c864e5965b322deb1227401b840f097887fbaaaaf3ef6301a9dbb509d4ccc75f6f6408c408881670c358dfa8a1640693021c884a69899f2e803be67e5c83be2901e2f1e029c096704161354fb5162b746db04f6c983ad5aba8e873 +MD = f2aae44efd3e8c207b27ea2c85e99b9d3f66610b4749488782580fe2bf58c2f4 + +Len = 9224 +Msg = 5eed6c988deff49afc8ab1f95a3a8030096d663fdd3876fb2049f5a8d91dbdc94d73df37c7008c7195643633535df24a6c3a21a6dd934fb13c385bdff967d886e542b4f1f07f17b037628e313ee86995794662bc12917fa2e6bf39efd1ceddc92b4333ed92d65efeea6c031ca345adb93a7770a8039bcd7725c6d6ffe6bb9239295ea354346c2604b76adb1c0adb865fb7b69593381702d802357b38c294c17fe67c4e4d5fa93a69a5445f58fc12bc2ff7ec17a53a6fe66c83f470c2ecc230436a837a019af561d6bde2d7f9005216d002ff3f05900941dcb3ebfdc4ecaea82cbe5d70976db862f3062c8b269f035debe0d955dcc24fdbcf97036a664bbff0e2e9f07838605a0667880bc208608d59279a60a15159a77cee3922fed2905cd20ef326d90cfc4315db4b65c6c7cb59d22d367e6a8ddc7bebe1a031022d43ef1458e5e5dd3ac8dc57f65824dd8a68cd90a4bf1afab8d332f14fd419bea2ecdf7f67c617caeb4d8b9361b62e5079c0525a353a1b97f9c63456e1dec07a561494dbe49ea3e94611b993c36d6d67be5a51fa88b16b8a783ee9e23ec5107e744276f076757182749ecf1dc586c7697ebe3036442bf11b5ec3b95c0e91f01122ffed85c65469dd9c7c33fa0f0826a0e47559d711b19591d3db0c8efb4a477d88d261647b427341e7314ff248fb7152150632a5994a3f36fe104a3eabf9ff08d0433a533e4877f87d478acc186790c83cf9256781fed75008e9db35c6a6fffb1fdae01bb76d5d4885464b5229556a4a7fd798e774d5452818ee273bf5572f9ea020bb848db90d7a27b4fc4a20cce91f0627f5eb18d8710657a89718e0167738789c335569346fd58d1b047da8d5f491fa71a33c150e4431ed9e91932eeabf13d2d7b158f2e76ca3dc02cbb3677773e6833e0aa21480a4f301587e7587dcef75d4579b53d1d9ea2a3ff2b9b305ba4f67c81492e4bd347a92bb5fc78695f2efa7a6a65b0fad12d2b4dc7236472ba66e5cf27ea3ccb734af57443ad28efd36a7f1714c57542f9b0d87db0aaa358144b90d2801a520ab88298ac47109556ab0009a5dcff9e9ff7b82eb65427d46ae9b18c1932700a94036d273628dd3a28267e0ec91b9a898c4ba182aa2a317425bb374c25b771c2f1f48915a4715973fed63312d3691cb272661b98bb9b4e0f12f95b356a779627aefc54d869b91bff254acd9a673e0cc5fcf774c55d2fd411bd348bfc69fb6385159b6f040858ab2845f4bc29f712d12086404b8d11707a087eed47e5a6db5077d052261d02d87d8bdb547d25f570005ea9011e747ae5966fe2942da5936fe38c79a11887ebc109964ffa8f3304ee10dccf9a4c0febf7cfc482c99ba0d251a31f4c18c4d925aad5d43e4760c587e59927847c82b4073f6c82d9ee105bc5f905ccf219998532ee78c200dba04200eeffcb423821053f15134752723a5af0fe8201f6343510a61458ec4217cc5d0272cb34935dc57806214a7e77066812e5babe4ab2e8f60ff1a50cbf7c9c236b0f0971fff24dde90feec8894c21b281806b60123c2b87ad7a828eac80ad963f0892b8a99d988dac48bcf4416ce20f8def688f119a013221c3c189972974ffc81f3417b7ed3bf5 +MD = 8ea50b0ea8a41452b2a95125bfd10baf240db4b1764e11aa3693e07fa014c5ed + +Len = 10016 +Msg = 6726764e237d11dd9020a5eb4799a4f268d35cd7d47fcb6f9cb7b442b9e1f28ffdd70d9049450bfe015288d8bd82096141da8e68b04666cbfc39473ea1939e4993c72490743db2570bf55645f26ea6688ec6547a44220363ea5059fe7cab5620113fe4d70d2eafef975336bb4e24231237ddd797fadb4a3d4f45120bb3f2c11d5f8774ec7ae0a9cf8eb251c1396e276425683f463938e263116099ecac30884765e7fd57251b49fdd65bcfdf1b125a683eaeb4106a0274dd1ae91729d12d52a70ca7a7a174a737835996d79d5cd965256bf95d7bf301a7b15028b34b89b0c8433a0e9951d14b1a69fdaa9184648bf0a3958f62113dfd24e99d6596d93b839225d865fcefa3d09ab5ace1261b9bf0a2eba2b9ec5ab0be928de8e7e75b516c5755cff4f70352ff60714d81beea6acf24047cbf23ddb40b9aa319f7cf5a3234bfd90503b316469e14a4c8d3807a37f21df609e92e22b2aee43517dd765d46a374bb64da58afe6755e57051f95526b1f36ca337f35b1106d174acce103ecf5801b03d3c10d579c4ee491ebad25fb6f1f1787e0c862133811dbeb1f4b9f8fa7955fb739fffa95d0ef515a64c457fbaaba6735fa0ddbcf9062da1ff86271cfc4a8e5e180dd48f1e8214bba58ad53dc83b7cfdd6896c86d8227b9ee3f6fa233b48258888fa31ff34dac7abaadb1422564e0f68512ab5275752a2360dcba5944dfeb5eb54e99a624675888614c164c5fb4fb8538e094a170d131be7eb88bbf88aeaa9f6fa506060b9eed1ab81d249811dad123fbba98dce6fd05324fb92afc898789c5be7c3466315b32dbc508254fc3402a79d888012b5d636e28dbc8de37cfd34e75aabb69ef1c04f07092f65f98fe4dce2ed63215b75f6a33482bcef198e0fbc2593c4aeec95603ef8427cd1b9c486984ebfda01da8737a1e3946b1a9484665ad197b110b1b67bef7bd8a77a1822cfc155856bb602622fbf5a4345b4f6f897bd75d70f9070dd59fd0c3c5da39732f6e4a1ce8692858f2558130feb22a342fa407cc21e82cc92a0c413fe0e02b97db28e9e0bc93bb666df18a86aba084c0c247070e98c7c074ed6f14d9e170be15b790ba4bd82262791b35d84d430ca33bcace9dccdd7f0c39a72f0f38d2713c164b0f870646fc65b9838a322ecfddd0cccda092aef6f6583edfb4fb05bacdebc1200e16b80e0b0c4d2d5961d156fd539b5525ad5bed16ecab1d669fe7a26b143fbdf3300a36359f5da1082edde05374d1e9c5b87ccac60fa9eaadc5879133feb7aa279da4c864651368015efb76c77b9612e879b893ed0a60ccf1338c8f0df3527013252dcb7fa79509aabcd21e41af1156f6bab8527525f74d9ab29fa5e13938961e904e486ead0b0c6d0f0be2a95a6b405741230e45a896f5100a68d9971990a4afa5ae4619bf9efab11e4dcae7c2cb5573d6a2d045db674bbb038e3517db8223302df6cd68257559ddb241dde42f5a1fb343dd9f5d068fd70465bac149c7389a08f1cde64326bab45b938e2386eb40257d4f7b837570392151f793841625d7919fb6dc97920c92909289dda4b63da4ef3ac1258475628bb20b82c286643c8a905d47caea3d1d2777ea5cd6695d6cae06536282ab4524ad119bceeecf1d557720aa6b40e72ca2a1f0cbd3207961c188f12efa3bffcefec8c667a3c06827b8c6c8eee9e69547e228849db864dcac8457383551f788f638045ad9c9e0586cada011918a63fc7727e2b9c8d1499b24fd4664cf2e5f4fa6198854 +MD = 83e3d216d72dfa9cc5d076f6e6606ab276fee722df341ef3050c10a80358fa72 + +Len = 10808 +Msg = e254dae65dd3d1e9def3c3550b571ef84f494d9821f424cf8ad37e1ae169242cda33f188bfdb344efcae5655e150bd7ba4aeef39a535fb7bf64215ae1bd9801a0e99b17287efb1a9798bc308e010477eba10de375337cf6fc6c6a989c1432a5b886f60cd3d790ea25e7151958fff83a89a5560b9b4626756024983d25b11eb98509e47c069e014e0b24a492576863ba24b67bee74e1f8dd6b0b2ecb272aa8b796c0dae74948c8b0c7dfdf3df1e0b3513d52c40eaacd40797dae92a518d76d2a5e6a3dc1045e53bcdc87297ec0ef83aa4418e2dea53eb9e4287d585d634dd88c5c64a1bbd0553ebcc9a917d73ceb312fd9674cf0ecdca1a7fc0604769ef47748012e9b1a35b3e65b1fb42ed9de7a685c5dcc56c7fa0db43f58c71b634471c5f7fd467e7e9cf0e6f23f36d2e92e0375ba41b6b4d655784e14df3f11c5cc3c4116a13ae05b8e92bd2ca8bfa897941d05b445c4dbae7772fbb2ffdc6bf0ceca852e8d8a5533732fd564fcad1467a93d84f4aa653fa2d8a439a41b3d9e86a482eeaa12a34198f31edc25ab9daadbf5db7fd61026557601828462e1c12de9e61bfa03e11439ee76e61e0925efe056d27d42d2f776b17a8a745879c4059ebd1bfc43d6795ba2b6872c276a0c32398af7a99a95c0d4d832cc10425342897552be8a38ac3bf810839c4794d2bf032acabdc6d3891ccf3e315edcce79ddbb265d366c64cfb96817d84edec2ddceb148a89d8b8a176bd467f8ab406967f619463f2c1934eb622a0d26e7385dd5bbeaf7a72f3e3adb2e72c9eb49c18fa84c32397af7f74579d6cc74e21e0ab274f71edc38eb75424ee538e8abb2f6bdb52084948332ad02e587bdf3ac5bbc5d1610ab5af04ab74ced1075589c6f567019138edc0a5490e9c8e58cede818d3da43893ee84fd57ab72040d67e4fd757434ea5cf7452e659869e7097e827edd7a687d13828ba04462da2e6daee38937fb3b047b4e20f605d55d0d98d56ee433e4e5d793580c16f9ffccf82d11cd92c362df899ddc9924b12d3fa50cbde9da17e3e2ef1a584f86feec11095777ec3fa213e81eca88f7e1f208d95a6e1d3d8812df296cb06a9b19dc8f710bf2ca86b95b741e6d0b3a84544ecef1d1c5dcb017ab4080f75d763af61a52b3a307f1e42876ef481e67da86a64fe750b519e48baf6b6eb0382a647247409ca17b9dd44eb37beb30d9e75146fe7dbcbeac731c1677d9d281d61e1c8c31d7d4013bbc5b0b82f3d09c4592850c855fb3035eda6c98987dd2ba7a4287cfde66649c8b6c6e65be6605550a705f20627d35e67556bc5b3adfd725cb9c8b857675b33a11b6f5a28f5af423d189c7c9be5fab3096eff4a583884a88723711f4208c29a378a1d80b1c5904cd42e6a650c18e7ba96baefdbf9eff91ac1618026605342e9e6636ffe88eea9d1d048ee2fd92910f199c9abdf1b1cc1659604944214df42af4847c52810c9627d9c08965185af0cd48d1bb1d82e5783f56f7d1c16e1f55856d797bba1dbfe30aca1de015e940341ffeb11a05bc618a766d85b85f94a3dea7d1ed3b1d06cf5bafb8c49adcb86de46c02e4be5ee54e8a2264af0608dd0317f9e88ac5658263867c6b5cbfa1cc09881b1d13b00e46d300aa041fc4a38f6488e17af52078daa3ebdaaa8e584c6e3ba89617e6f6ff27197578157dfa18f3f1bac84ed9544056b812323e026bc4e62bcd44b8049a17d04771f35f70ae4f51cf34172ddc6aa33dca83eaf05f03f37c027e8dc716a34088867a83a9a1ea2ff1297e34dfa6698bd900c76c864d25c078e844d90ec31a6198fe1a90bdb8b5a21a2521892ce059df7083651ec876db132104a69053b4066248d6d882615c189015eba47cdc3242874b7be56a807f2cd4c07f2c1a5f906f2ae0373cc25e +MD = 5f3a2c2f3feab3dcc0757db4b07a3ae06fd928b7be833696fb2aebd31db18372 + +Len = 11600 +Msg = cefd0d77197e9cca59549d833dbf5b8d92a533a3b937a61259d2acc051234a6df18f663969d2db6681e6c9608b262efa96b3bbfbe517e0d9a0282ac4c82fcee6704a86ea2b0f9bbbc172438e26e92e22acce5c467704319d31ddcb9e003b93deb5f61292477e074f7fc2b615f450828c3abdbe8d5747c1e476b93855e08fc1dd275bb539a46744ad249cc8fedfa253c0aa498ad86d28b739d68419f14f737f692e4015e82c127d5a19c92150ce29c847623a682da1ee3b21b905157b372ef50c326fdaa7c6c6d8dfc5116a13a82b0aa8cc58ff96dbe377268705d5fa7f094c4d9baead7c5acd7dc58f3b4b4f57f1406b4e6af81a034d90cfa94c01760f4cacb4d2c63671d16d9594e1116b0dc2c39319523afac10175b1a485a240f7cf3f3cca3d7f1c8d11ef48d222597355d1e82b393f8eae94bda3002e84cf3a86a729251645a007d8039bbd09b9dc0a2d6caa2f537d2fbc9a1f1fa5f40e9a982a7f548e2152f3a15b8fb81dc01062d99f7b4fc8f074e5cbdc1030c97f8ccc02ec3f06a071cd3e8f1d9e908f808eb388b2e6201d978c778360761f9455642d1fd2cf8883901c4a7c2616693cd09b96be6e956557d02daf8e303b352d00008598e717225e06a9df0e7fe18c4c389fd423dc71669d23bf53915445b7bd08c69c1430ff1b5959dbc4ed2fe541e64002356003606a1819aa2c37d27ef06bf3203a3cb770bd9e1319c3c23e0ccf32712d811dec4bbbef39560225b4cc27604b7526b883504e52bbcda235b53c8059528680019d1b9f4b0b2b9d060219a3c3972d292f9c8917a0da5e2aed9b5f9a836c76fab520b65f541892c480c24cadbd60b00b4a0b0160aef7342393f85c66d74566b6e17d064331e7f1413bfe4d8d762d6594b0d7a271a49ab755ced51b2c7e67bc7d2cbaf2920b01b1dae0bd048b1586b68b09085291ab4c4f8847398434a05ae2173ee1619609ec3b58170859efc3f30abaffa7fb09eb936483a62c7fc563a43e4cc0f93d955432f68287e63400a7fdcae738ba84228bfa5e0f92b6f428f2cf3ae45a0b6dd8135a4922d95f7d07ea2b5cdb5c4cd521b306a5f4b3e0cba673633ca6b31ed9a76fed9efeb57b1c4cb306295e1462d6518d41a1fab2b1ec850fe6ae5b743a694a90725ce0c143f9172b15993808066ff93e32bae837323f0dede2f7cb446705089d71ea8ea8befcb079e01530df3f8860f1615988e969ad8836de7fbeccae952abf73b2d010f40e5ec7ef030f411609cfcc57e4a071601c3c1163aefcb41601f81dff1b70a2ee156b3acbcc9dd891da8ef79bc5f9761f7572a7f8ec4ca3a831bae09d8d3405b3fa1dfcfbd9a249bbe3e59bb5625ba1aca1721f25a178416b0db82fd570e6e14ba6bd350791e63f990d1ce02e258e9a118784a272354637677e3a33302d4ce0bf00920c785b3060353e7aed8d755908560ef05868107f2da46a8713352a2fa816efe6aad4a14a54965f48eb5ab985948120fd688e9aebca2bbbe8f86dd056e1585dff37a6cafac4c459cf011e5bdae59ca4f5fb6c3c51b70357a50a5e878b348e3126da733e0958c81254585fc220a4ae811e388b5c7a9c3428067092b89448bf53a3bbc5643fb7a9742217a8561f78c0a1c14872642f1fc714525391c93ac7f3aabe0323a6638a6f6680677e7f9f0ad9eb2552a9ba36ebc305d3dae12445563220bfda166b3f7822cfb5706ba567010147947fb9c857a630e2cf2e0c2f7d9f859ced67251c992acb990a59f6304006409d54f729f45cf916938f769a54aa4af30792d3d81f3a4772abc74ba888f2c19fd5aee181a80b8b7eff5bdb11fa93ff8547f445b7ddea781ded346d071545d925d8ea654a4b2e056f107b85fb88016542455be64bbe7065d64798e89d4001f7db8c50ad0b458b0ef2ad369bdf68bc2432e911de1b2b96b5a4a13de3f26fedc2c7da28de4cfdeb4f0ebed54646018ce55d1c5d54af8a221190e369878c0bd2e3f3aab92396dd156fcb2ca0adb7bb3950ccc486709044dd20a0f565fcf57d780167e54ca26f4cd3 +MD = 2328026cc8289db308359222e9ab8f13ccbff7f53fa1f9f579a52cfb5c46b267 + +Len = 12392 +Msg = 1d4243dd682c6036925438fd8db2748a64f597a5cec730eb03515474ce024bb2e48c8a9c7430e10cff3cf6666ad2f27b52ea7aad9f9ae1535c969c5fc6f3f63ea23005ffd476dcb82e1f0225867623930bbd06fcd975bf74cad926c38fac875400349b4eb187b700c605448208266f99387621dca3dd3215f624daea54b568bda6a236d032e9dcad70f7a4c5186a3e57801bb593255ca200877ea01b3b97ff413b81bdce8026b187d3fb0a35e0cbf8938cb6a96a887977fb26f0609d6cd9b6a768da1790c2c6a055981c5e1b85d00516034ee5a9f4bd19cf7b8002b91003f4b9d4b42e5e214f10e1665f88bf3202cea88eec519890aef1442d386eb74f9d203d2717e980c54b69f1e6ce70690de7b910d597d57f85d66521e5208cdf5030a4fc0b0c303dd541124ebf70ff613e092f187f5759a5fabdde304a3f45783c43e7be2699ebdf7aba75c09a4d1beeeef099863534c55318e9c537059d7fcc3a5f514a20c902acdb3df90e1f6ead5a45225d239e3701d107e480ffbd422321730b4a6aa2a15eed21520602f5da9eeb6a29e5b76367f567ee3679501b371ac00fcf3ae4542be5e973810462c599d4ea868d970a2bcd8a5df56516f1c7834af135338981dd6e80eafa535bf736b4399fc0d4dde39f6fa6fa46fbc1ac682e9dfc0dc09f09e6721836dd4f7489f132b45141881e0c665732870680e147a641fa28c0fde5441640931645feb5e09d1b2c493030c14b298d174c607add8b2bc348be7673c1fa16dfdbd25ae687c3e3788bd0b655306990173b917a731f409cbc710656a89cf28d57d6b2439153fb6b50b82cfb7ed22e42ff889e7cf20e2ea4345c488926dff524b16efe29877f51dcab9ba526330f61e84de5ba8f80121ce934f1cc3775f0cb83f48afd334e758adf911c8560fd4fcc2907392fdba493d413c318d9861b393c512811f88a709b711b0b2312d062fa35ae376e4387e6f91ccbeab9b9a1a220103655ed3755755bcd392098969fec78651fe46b3fbbceadbdb9b0bcb2ae920f0edc840502bde31c65e0d96357f42332242317186ba1e5157f841d090dd6716dffe8bd41a1ea444502b93c6c9ef88e8e3962d75d0e5eb29a29d439891240c9a2ab0506895b031f406c6b549cb2d2b5f56e852c22711dbda485530d2208152116dad969c57a31fd746b9f26d9ddab20d089341e4fdd048f9c59a7a0bd397c0231540ceddd449b6549c7fdbc0c65ab58855316b6cc983bafe86e78fa43eb9ef35be0479ab9026adf27472c1d1e93f9e47e94d4fb81eaeba5f28c6f249a67a27cfc48327942fbc5f376b5d551f5afbe4c211415f6571d3cfa217a3325acf5b1257c5274915e79d52a9ed79f617b012119d89a82ad34785535dc026d055fdcf37743c7b5ebf6c2c10b0775335496d04bd20af0c32a02425fde8deac5cd9d668ff9b96e9f8df31fb21f1a593832306664ff1edc7f75a7c4817e9bfbe2844dd9ae344611d8813bd8d0ec3d4a5703300993287e275e940d46e49c6efd6d32577e77ae537608cfb83542fcd90f38d07e0200d691990a911a0fafc06eb80ddfa29d13f14666d87d507e31d7577182a00299d490bff92873b8690b7203f46b94187ea98589a9ef95edfac4031d38de7ca41537df70116343ce9a203b95782f59a06862f08207f71e76f2240a952cf36b4cc0504a0ca7600843eb15a28c0d003422a566bc9b489521d3ae787426146a75e2e04859fb84caca01a41330507b862f877bdc703b3373a5ec76e9c737baeaa24ebe4694a6704792ef0d416b498a6a51b533ec95c99239b2a9929f8d32e41cfb78a2738473327f67f56ec8dddf0154a29514c0b2af2b8f50f249c14d7e5ba78748d3f7b0cb941c51fb0ecf0e7baaeb2b0f687d4f54c61b88afe5789083e7354fa79bf9a0175cc358e9367f85834bd8f30c754ef5202d8861c8acebdda94f6b597b40a1ddbd531e85a72e00ca61adc3027285592a7b277ce425e743bc585df3afae0b18ee2741d5df1e3e79657b9852612bdec679cd7b9f18aedda7b5f8d775592644865bbbee906e34ae12df3bd430171dc8be677ef29b054cd84051f186985dcd3313ade321f63bd2c5f5be0828032c328d697ef65415b3e51e3517ab3205c58920e56b06a4af4de1cc478d495d74a95074ee459e69b82b62f8af908fa36499445227 +MD = 09622f3ab1fadfe0b034fd22adeae053ebeab7720537dc8f6eb586d17b1a0bb7 + +Len = 13184 +Msg = 04364d756936036f67ba3abfd5919843af141ccd0b50b26b4f6705eca233959fa02d095e528dc6cb5db3c0da79c69090259bc80a9ad883c0fd59400bd8d2f0e5cbb64df07f586ebbdc5198407c2158b15f19ce74e0784c6ce7d4207a61bbad43ed9bc134d8df22c44c5b6af9c4ea152ec355d913c67736f5779f4d402336f5426ea20c3146690b70159add0e3b69f290bb198ff0341f68e514847065088bf068b794d6f0af4050469fd69a86c8e5155dae2b981213b60ac3254931f2f701c5402e38c977fdaa1bce53d6496952a8a62004549d814985461814b737eed7e19d4f3c588bd016f09191976491c0c3f8ce5e245c4646c0d4426b48962b6192739f1f49bac403e45adc16d4461a92021eb4a1780b3a685eeb264429aeb4530ffff437be271d164d2f24e573458de7f7628270672922ef0d111b2b1fc67bcd36cdc31f01673d133bb99087da2992c78a0b5d54597da5e4b48f49a992a827d6ef2535607c42ce01953e498373bad03ba3636fd4b6d06c4e3badd745ea1a6177224e7281968075e943077761a5c0f04a2ab0e078e7ea1e3589b3ed888fe5d1b7b791a10ab6e8dcd22c5c40aad70299fd073bd8c8529364a188e9b5f9ead11e9e9636ea834644abc43a84cfe57349745b224c7e4d6093e69b1f97542061a5f134a8857675ad5a8ac854c94a9ae05d296c632afa8e79b14b2a3604f5855d2bf182d3c56d6853f21fe46271da5286065f38b31f751306b63c57b679beb14729c78f0040f7e2a0d615224dc5a693cd0cbec8f87117656d6b6029853ed72b85681a63183c3a6dfccd128afb0dd7e81d36f0231c69070b189560a88c9b697b81b0930701026190cf9ebe23559194d6de4d9a51054f6e8d6dffe3dcb3d89c2aa1c8da82a5da92d48112c3f5439806e7781a675b9d6b7374d67092cee33c97bf4f7a96dcea0bf5bf7af1c608ae6c54a25362fc48ca043f47baaf1585021083c2f28c6f1ebadfb4db220372657c53a78fd7f004207664f98e81851309f99c87bbf1c70f4ffc9cf4b0e20f6c13979627376d8b25eb88d1cad292ba3463b128cc33b6f31b77988be0c420df5f1ae57dfb217bfa07b2e894da995716219a11fc7ab2a8d83e9e75f49da24539f183504f4cd56b06537d7ef5506e376182b60060b8be2f3d1ecd7d1f56cfbae6ca55bf5641dca377b152323b54d69a62fec0689baee1b3ec630c975331d4e6ae939819d803bd8d15c83becb0105be8e23ebf30f685a29cabb661abda563a3058f454481eb9008fa7413f949aa9848aa9eabb40b965895343bfd6a2faee8902ae949233708c2e13f7c36612424ad9e67fa9bc802c751f3e7c257262fc2147c3761c5ac215a4ce80cbf7b94ef019e3652c23cbd896deebc61d903dd42816feda7933b2dd5728683eec853f30ec3e296f7701ef3041c77653f0aa40e0c5f635b17f82a46c7c4185b5221401a17de2346d29eb31707359464ebb18826f1de875af50b13757cd16ac4d344c0587ec2d8ac50a88978075bce51d47850b677615453cb367738692d0656eecd755cc8246b5e1e2812c488f17db2a5c97e4b219a52dc0714c61e213963880105af95684563d27797df5b00892aedcc1f614364ebfb5a3520908519791aeeb6980f70f3d84a8019725fca12a57e89a404ba3dd5c8b664e1e4671bc68e84e17bfee59ddf4f980d6032148013b8b10ce9f3e9a8d8d32c7279daaa20cccc4a06cda4f27aaf0dc4c0e8618e1ba8459afdfa776003027dc619797dea5270c4d2d538149675d7a569511e8b3d0b24de74c35209cddad73b0ba07d38a82f770aa7c327e8423deda8fe246f1991cd3de5d6f38d2573aecb9d75cdd1a553f633f04167297a9621558aebb176872cd037ee4a15085501ed54179cf8334e7e652c382817c95602dea3cdca8eb17e8ec2c76a468e5002f915052bc995fe9e97eae424d47b73f508b45cd40322bc4a17f350fc44f5f0c9b9b4535cb44db0103105e058cef8a5f22840e5403e03d384591068e6cdb26713c459c33cc585d43dca34a5468025fbb7e202d194c3b8a3b7d27873ec696a2f7bb963d92e85b4f781d3f5a7709079d1d0a688a6444ca7a95f14ba066f7073b65c097109a46d718686dec76b59686ab4b71630d7d1215760d4804394d2ab65a85f24efe950f5320db75b386573808f30d59199fabe0a4e46c2a5b3a3c852c651dfac5edc96a58cf99dd9b72a51614dc2d6b932638d3002d7a41568b7b30f0c6f67f04c67f806d8d694cad22e75932ce714ed88b6a15b0baff32001452548ae3d82a1172ff781ac2156af07e6528ea31a3aaf0b78ace3c +MD = 4228ed1c7ef246538e4be2584b7c60308565a25d35d128963fe8d340d40e125f + +Len = 13976 +Msg = 738d923a0b694b60e246cecff04c6d1cc6d9e1b270d347c79f3c688f08063daf0729b3f488f4ab4527a045d6962b5e9f3f64570d2b4218f7237955d3154f102ab9ac60497371703a7c0bcaf23d48d6ccfb699d36b978d3aa5adc15e1072a6f43d03e21a1968ba32628afe68bac4add8b41113c97e21e80ca8d8a2f1fa53e61e296067f64b7e84bf374b32009acda7bc45883bb966edc253e05ae2bf7b934eeef512d01fa9f307088a84001d505a0b95f89e8a29d2459ccee076e92d009b31e524ada30cc160c1acd0c7d10557f439e441c687a13cd3e7cc2def2eb115f64faf3c9369240e42452aae793d5f2e16c335c592aca6031323ea2d163be2481ef89ba1569b1bfd01f1f0783a9d814f5c27f8d87571aeb18de197627e9947037fbd490789a15b2a3a58acc26e8a22481ee8ac0f016f31e4ae9152629abf35d4b30e15b38f2447f25609ae11978ba884e975cdeda90db608efc3a9a1fd266538338ba059e98c8901ef5572ea480a8aa2466fecd8eed5c1aaebf91bb518572baa9b86774f2b4294b560fc99c0e28f5f1cb0377775454feb270d9216f06eda1fa835bee927c70ed1a9554f911a19a28c40a15cfc273ed48919df3f29f87327a7bdac6594583f29e64a26cee76a3fbc98daa440e9835e1c21ffdb40d341d7b85a675a4b0775162c3904600b0b45d7660b3743a3de0e058f4c457c579140ef04be11e9bf90f2ce9e50849b848b11730769e2d9c6482bd7967e974cd3e29a2bb53959b533ef55daf8b33733bbd57195492b5a0158965146da2f41d7565592301252bb57686112cdb3d798b32178daa083d62944bb6732d5c2d4f1865f58ed7ed4a0934a9da4be09584425b445f3a1374fe0dd0e6f2934f6d91602d44f6af08a44999e096418bc307e6f6a91a9c489dc25d1c1d8f46adc4c8559126bb71a4fc51aa4281e5c3b91b56edfd3e5bd69e8d17e2f843eeb8aad2960149ca716c55fb1af66bde3e68bd31ad21c0e2b015242e9e16090aaa5370c2ff1eefe00ff2aa4f27b47ec047397f4d3209a55cc162c2c77c80b73a6b1ce8dc2a33ed313c088b3fa16ce2efab3de7b70d2d157635c4609fdca96b9adb1dfa6740c8aa85a1b8e012b0a7ff33107cdeb6671579f6b544e6ffe4178bf3a05d8fad68658ea3e50991117beb3d541fff4a93684a37a5e8e93c2fbc54810d62e48df4cb930155b10486842bc304197fcd15973753b94b77bb4b778de8b3b0cabbde8590d96b61adafa7b3e7b4bc4bd8ee2507fdb865b009c2f91f7f598ba47fe968a8e0c034908014dde5d848cdb2d46b642ee102a59b47072f6eb9316fb02a7615a4e3cfc4aad33b0e6326069f16194bb8530cb8e0d6d891d6ad64f7c99e736bcbc3c08e84774d2a2376f8769a3f4f960bbda5627d276668d425a734003401cf744ba085dabf97eb0564762127f51f5544b5d588e6579695131bab6f7c3b7daaf785aa3d2f4958869a75ca8eacff318f4b83c4b3822e121f79da9730a57a8e043cb9073decde3901ccf3194593262c4c086f996ab973820ef0a99400e3bbdde62b2fde0d7746e26682248ecf4232b89463c17d36f3f08d6b5fcfca659ec41257ac2e58363a49fabda4524eb323eb7e7044c0979e986bdc3dad9560e93e5ed460a7ff9d3f9bae2a0c19c384799c1826e793b5102a10ad178cc4437f142b51cb0804ebd4b0043f195dcbbf56aa1783580238e80f62c47ee5608b214e6dcd65a057ab382612dcc26fb7a190eccdfbf2bbc81ba1bdcf1aa5eec2ea76f67c8d62fb55842ebaeb8b00d623837d6f6ab02ef741242841f87becdbb9c98c9ec9d10f830b7817b9c679c1f4a759cd070a9effb5753cc4c4655019544e10a96fdd0235e1806d394a280ecd714e0bc9db342d2c9d6d49bf6e9ffff50088a716913f899cbdbc4cde969bb2ebf61d82b91470c57f5630345f662df248886f771b2b77cc0cbdc8fe4cc4a6cde52b1ea4e5d946cebe89c6e6edd5978fda930b66ff650e354d8cab6acbfdd2c781b7585a94533fb0b2dd3846b0e2664072ca655d0c688b2b26d06d77a569a5088843d38d0faae2d323fb8d3bf2b6216cdad58445885c76156132170f202fa9f8c17698239f05b79fd98acdaff978507ad85b7004bc69585dc459b019867866fff6f9ae068a8c477d9b3300890f517cd435043284f0b5b76a18ee407c1d6b6386ed731d1c186919d3329e2fb17a692ce1b87ad1ab6c6b1ea42498d0222e3128f36f8dee4f93c1b60a6772620e82e7e8092b62556377b11273b20066f200f13db044ef288541bfa48b00579f8a71f438b45467c7935aaf1d3f88cd0dd4ddd42b233440d3a86c886dbdc5f7f00c8db7a54afd2f2e235e8fc6706fa8cab00b0279b60728f89f5a47980780f75c7d2059b633ec6292fac876956e2f39a76ed3a2afd084519d525322aed3f702ebc37001f4d8eaa9fb02e38e13a29027abf77ddc55 +MD = 070a01b15b49be7fbc5707b3a3350555fab1abd7ba57bfc71b3b6e8c8b9556f6 + +Len = 14768 +Msg = a0e1e1c6ddfa6af33d5cf86e9f01ef1a250b345880fe93d86e2d5eaf807257a92122d0e0d440118dbdf1fa1f6330ea8ab4c3dfe24a6ede28ec66956458083ff33fcbc823927431fdfc893762b0072f5a645735a89d7f85a22e96293ffb7ad57203c50fb69efc92ea020af5600ced88313eb07fd3049952ed3ba36369f32ee2cb74f6edc28042fcfdd85e7d40024abbb748b4048a04240bb11b778b0ac88e2da99b47ac6fc1ac37de856b172b178791958c4c0ef627887998d7f8e949000180b27ea093e4e8a40a34111b0a49d50ad2731261e33ef42d64487610c44f25eea18e27eae94a7d913fa88554a0c1c33c46f8e0d9cc8cf37c946900a66644bebf59e69e0bf7c808db9ce1e8001fbc6985b4cd009e1105addbd0a47ea1154f54db7062e9ed058712e9ea884206d061504ee69a7a96fad3a9b3e1a1f7eb1a986eaaaea912765aaf2225f0449c4efbd9fffda20654abcf1e6f6d9007736bbd489494db6421904067c1f678befdc0e84bfefcb1b998c4d70d886fa37efa0945874f01be3a1c22fdd776c4489d6d44dee0d6b1db5c4ec85bc97b23e2b095adfc7c255920d40d14da28c9f82a8af4c227c00e86e7977ca1a37ad0f017424b3f2850a004c9d9fb4e1f8242f8e32d9b2209122ee19f112c36f746103d08df25a7122a486a81f2efb7140c6a2d3e2d694ccdffbf2cc973656f9f58c2747e2d29cd0233a4f410c7f03901efc8ff02336728baae48ce2e643034e2d66efc41d4619a3f933c083dff06bb2d52e5d7f6e69b9f1a47512f968d946d0ae99d3d197dd5f413719810d1433926e15e471be4ef0f9733f462b7c99599025db8d59fced08cc5c4f54172953a9260653b783592f5cbf94fdb04ce8e2647db246ca18a27748ef39b49be984e8d18520110008bc8a1d5aeb424bedcaee5a7e1a62c8666ee12e367e09297e8c7e3d4e4fd056587509b379daaf81949f27cc0fa2d210e9be951940adbfb55ccc7e5ccffa044318ff18af9ad7b7f9c7d1f939a0fff72c091e1daa7c3d4a97fab153b0a8933f2eb0d721621c86de0cfe100d13e09654824b09d54277912c79dec7a8c966cfe3a1c689ce8b9d5ca443adb5cdfb3cea7cbc361e7681916de7b37f9be80768e49424b0837a8c8bbd8d266d4fa6401480d22240a85be878180edd639a9c0b4d95c3200550bfe5764e0b3da35a309315ddf76d01540fd78a24047011402f458337e33c4b7df906db7290e1e641f764af764ee4de8e0cdf56165ae41f293c46886f96d1d967c09129cfd0cbbcb365254fde5b325ed2dd805a6394c1d3b22d6eeb91307965aab0f4efba2d538d0b0465857aaecdf8aefc3b05902491d5778d5f1b41529b46b324a2abc61901ddd54f95cedfbc20429ed39fe6209cdc9af5d677a5f47fd0131d964adc88265f359eb146ba7205d1b31f0e0f8a996ffaaa9993490a2f0a804156a02e0054d7d40ac3d3e8a6d60e4ac0ac060a517f10747aef3e53b655955457dabcfc95c0a008f3d1220c3270580401b25620e92610e282734228390cb2a4dd2667072b50016657632611dbd55585ecee78e39032f3cd67a2492710b8c4fa37d6190e3f978e54cbe65aaa11799958e8acd8b3053a4b8d8118bde0cbee4edcfe465d5230eba98cb7d72a3551d185e58b8a002fb6806abb65231ae5d911d2c5a7139e739de0e556b1c22f343b81cdc45be289aa02c9d3cf9a7dea86a6d7e33cb8ba76f3050bc44b2013d4373ceeb36dc052dfc2986b394287759773d384e2baa9975150d4b0b8f2a958b3aeb48ce95a5f577cf9d5d8edacb296bc1dedcd63b80056c80dab9455b5b40d381b50f0d2129f6cdbc059b77376b27dc2f533f5e8cd33654599f81b0d3cc6bdfbfd90af001ef71f96b6827b6d38fd87468a64b2d462e94f547628b941c057c759d5d20bf5e80ccc183cee993d5bfa4fa15dfe68d90168716f32dbf3b618edd5ec34b3bc15f6271eead40c9566583f338dd04fac492157781040705ecc8f0f462d8aa423f2d1fc64890c4af46ad642df4691f6e1b75b2ccfc23f945ee79b22b4885831c81ef3f3596d56583acd2e9baf760372ada6176ee50f809678a9d5ce9da71ddb3cfce4825a223282dd0ff9b03096b5516497de746452a4153085c7695de44c0ee71f2c4fe32231795fa5a006ef132801ab0f28f3aa262a9f1b0dd89991da835b5ae823a270f7c39a4720ba264795cc01e56e7f6333147482ac9491c5c5f4342f0d0a7330a01d796407f3b094e67921d0a8485a29ab88226e49dc7b8466bbdf2871d88360ecfdc37526b12bb92847ba0c682f41dd500ba4b087280e4bf0bbf4a63de4ecb9b433223c37cb7429a98c0503a985bef4ed198c07f919c282f05f1546a5a207a1923826279fb5326cc6b08364f0ee29e6bf2c48c2f42420cfe22fa1785db27ccf03873fd5e300ded92c4fc58eb2bb3b4962de5b702cd9a19942a839b9da78a48894aaefb59620e21536d43c0f738f3b93648a34adf79cdd65ae533e9980772774a21da6451da7d49762c86765c7dcd33b20ca84cad8f03ccb61bb308604307df9c84a04130e183ee65ca6d80004267ac744199c5565763811193aa00dba3700ae8 +MD = 9e4c602ce1eca142f4334587312e5af9b08bfd18c333c5e31f5484992312aad0 + +Len = 15560 +Msg = 7c7c49a8a31b68934e15cac10a53018d95246ce9e9355bf575be75d0aef957adc6d87e2abbf767de94d0f431e82e12719fe49922fcbe7495dcb801bc386eba3cf1d416c4cd27aa9dbc239483617719b4cd768d468e0f73bde8ffe6dd624538bd85d6d81de09379f94f78705f7d165e7da84310fea410a39723fbecdc3366175908488ddefc231c1ad436526b45f329f5b7b3eaf248a94b481414da61b4b99f370491fdae29bfda27d3c40052c0f6c243822fe2c981c2b2fb43b37a13eb271a800019f036704ffc49d58c42baf6087091911dc12b584321d6393e929be296ce5b85482e1ed8bbcaa761f5e24cf00f7d046de64fc2d314e0017d1feba0a1ef04f11a867e0d6aeb8c6aff67a6afb5f42fc69df35433fd1d37a597bc4dcb2e1b0469473baaab2dc78ab9374a588b4da0cfffa9ab9829db476eea107f80c4930116ec94cf78a129380cbd9207be8ac1faa4d61a75e24a7778ccf76fcf4b32d88882a28aaab1976624599d9704a15218e9f87476bbfc3ed8999af53c1377be039a8fb2b0341d34ed75ba82cfaac88b5a57110148e4acae0693210b00b5cc0f1e1e87458ed68321c5117794c061fdde902b38a41558bb420a4ca662411c12ce30fbb082adf6ac06f6e2d8faf49206f2c14db585677ef1a1ebae74218ab011a2421b539294fe618989ce24ddf3a3ac71f5a4d0cdc5c01574b1a0d27160d991345b65b79ccb54685585bfa56443feb700341ad1a4b885f1626409077a4dff592b83c126c9db628910f29ca1b86e09ef498796ff31c7364b140dd35c63d88a3230c217e6414b8e8e63d84d6100fc2e1cf4f501a49d7a39ec31b4e519558ae2e4eb214f402ba3423df540b92d6573d405a98741060f59f79c625f278677e96f3703a7527caf6ce5606f31ca4d0f5d62730f443f6db0edd8224f1881eaf27f9af3215d06e2f72ddfbd78b467082541422ece34e323a8bd45489fe6db8fedd4c9dfec4954ba286e971db9d078a7d0a8dbfe8f5f166f1e51a4d4fbd21dbb916e65c40d75244b6db87747d98de672371995abfacebe983a325e8f0ae22fb706d7d76a2be95fdeec91e60581f397b1831cd8fcb688c4e726e7dc417520f9cb73978699efacebbbcd844c1d590b74acdb390cba6c9511a407f885b2e394643e0034d91900c5b22a3916125808dc65ab68f999adc3fe8c1708eec0a9fd45565ad7383ab1083f9b7358d19e7e376e53f551e3e89d64ca1c874e50f7f06b3bb8651d2b102bac1f8ddd513c59578dca24d3bf805f52f601ab3e04a6914dd47e73a8fd93c24d966f72b14ddfabaab3f7c28dda56679322ac20825079f689e0176d6b9dfabae06e3731387343fd4150fd136bc9ef692a90d1629c5a4f8d6c380d90f625e75fabdb7db2b7ecefb5e20de501b4b5d3cbdde77b5bd44bb3c0bd8468c390bee31978864bdd79df6b3d5692b673b2c588f775cfaff2714b2af6466b30ed829075500d17a89ac57540fb65867850ab229853baf2770fbd813e98cd966ef815c2256c33359dd1e2d5f559d6923482e8f38b4973f5da9afe16760c1bad2acb8e7c7bd5b288306a192912bd735df1f0b161e73f6a83e17c7d325abbf8576a4e38e800f452b96b4db29620910290b7824e94369f6542929b82fb730d2b3c38695a2b3b2fdb705662f546a63c4cd28e2006b3ffd02ddaf7e0549c486b7e059b043b70b4ef1454f89229612c2619cc7fb222e7cb3a8af418333d3b623bb75a9c0724ddf49dc60e59c3980e3ab731259120ea5721454338fb7d830147e69fe2415a5d9a829fb94681de887659575b86cd52a62c8959224daaa46f1581d5fe4694e62ed0e65fb5a379cc42c1106e619739319e8d8bdeeddc2d92499f986f9c2e9d91dfa7a94382cd48730e16e86409ffe0a31aa3b03c6d8c8a2d59c9121b40406344b74652b5e76df6bd339d68a11c67c79161957fdb6a06cb5fe6b97943b427eee8ffd6691cae2b8c91fb80188d6176f8e4bc8c8124acf1f80f3a97544ebe894663007e77e09dae11d6ace48091a2d57a8273b03c7dfaf617259b8c2ca4270f749fff6703687d9f8d768ff32913a52b5555ce283a4f1dbd328852c088adb6607f8247b8951e15a50858ecd59a7d33219144141d0303deed5022a75af0d035256ff61f9ab5692f698b640bb25b35145f37368fb61dff032e7adae182ec786a054ce2ce35ecb191921d8233b1f5a5108c4f15851c12ad542ab7984a62050a1fa91f2d9db0c15f04c9c79aaefaef33ef50dfc83f766a749b860f44281fc2ef1ab8f0c1d434bdd950b69094c2b6d1497855f13705edabbb9eed8ac7c4e4ac8f24dbc585bbe866883d008058b80d244e74408c4a1fa95fec2605310766d7495204baa86199f547d493509fcfd8266eaaacbcb9e9d4d10d6efb760bed562024a184fca03db882e526194df6df692a3ac4e56f7ffc6d8e3ea9e5e92061dbe8c2e26a49b5015eb8cae498a08c71b5400d06ea01e66b32077905ac06794c3e57ad7f7f4bf096d4bf7d78d9f0696e029171d7821bf61e6b6546ea17741d94c8946cde8ba758e262be8648a1e696bc9945ed9f7465b8fd60cf2dc0f0dc1423bec887695608f6ce4fdd6ebebb2a1a45c2830ac7898633f1596eb7effde567df6b1a8686a714d042e546bb40ee63fdefc4734eb589276fe09d696bdf07381db216b3f29f4773f1276a1ef838013948a4e93e43d23cef75b475e9d2f8d57c3e8306ba531bffce5e632790aa +MD = fff5357ab834e99ef46b094d6faf459f779137b419a102da8161d5531cdc7f6e + +Len = 16352 +Msg = b02f6bfd27f4e096b586b89f25d049e79db6f0268940a73bd5fbdab75f9c779face7456edacf765ad5df7fd8ced82762e99cde78364a51e5e3ab3b43b0cd7ec1a2ed7224fc9a7d0c6b18e4798103e08d6434f594c8e97f411a1f8e3afe43f3d8fc0a9b27769e1c35defa8e8926979cf17748da8125625ad8e3217aa53347ff6a2106688031207c5c964d2610a4dd8214889e384737000931a477a78b3621ca0179a98036146bc409fbd95317e51dbb800100b5efe40ab4d4c6eabef4ef197b246cbb8c5106c61dc47565bea4d09f6ebd4834f97f16c7854ab24267e946773b5c620333daf178af166cbb0ec24daac451c702ad02b480a21acf4749702382312fc34a1ed8bccaa18648a1ec764487e5c6e434797da67e33cc84c10d946e838627f758f4534f041c9d71e000ca9d7ff8a4099004fad40661e93b775a5a0fc261cc66f55e54926e47e14f40f1c540d826719de0f780266353f85b32d9ccee87eba579e904e16d4f4bdc4a88686f16da96b708eaf91884db33814cba32f1f41a4b3a96fb8d05c8f14f16cb820cd105cf71fdb177b3c9d6b8260c75d70cd107c2aa1327f5a2c58b9a7c1638f486f2f6fddecc024ecd9b0440562240510f7510c930b9929dea2b9e93fa64fba77ddbd2ad06ab6239ee96f6bceb4a14efe4e4f87504b341bc0e3ee924f0887a639a927f28102239febec394730d0d597a3326a50f4f899a19b5065494860a1fef8521e7b325b9f066e729c7afe2f278bba34401de38c4077e888cc82de6735115e58ff0996df9ed390ed075b69581d777dd45f32ce8ebeeb12ed72b35354b779b62e584200f69993fdec187d24c42df798931623f8786b97b50ef67f59e18fb4aa52a8a9234925c3ffc03e6482fbef8884e1138613c1dcfa496dd62b5476444ea5666ea3503fa9f03139e7863687c8b6bd4ec5cd72f3998f4a7a806bd58b6ba431da28c52a52bc851c99b276a1c04feebc4cab6ec89617c332c583954fa97c51ca0e5583041ad41f2c601daa476dfbbd0c6b32ee7721ee328ccf6e5c3548ecd3f8a373619000670aeb3d8795a9b9428e281b0ac0f11f7359c3089f15390233a7281a00e530ac0bf4c3829ebd5b6abafe89ec818ae8f74da5700194549d3de747e2d29c82786629596fcfb1a5aedadb7acc4045a0a131d3b21e3afc9f04848e32b38d94cdd9c755952a856ed346821a7f49c6a5a6bc67bbec28151658f14e8f04047b982bd76807549e3424ca9508fe989ce05011bd015cc01830a016d6246018705cf520f390b504356c81f03cd7fe43301da35615873cea791df85d358eb80c61725a51a109f5208a9ef4e88067a00b9ddf3df84861e2a7c52dad9091e5ed3c628c3612721c3e35f83c0c2812407a5e50c57e8cd839d4a486f02e557dd27644fdeaf707e94ff6b118c4161354eaf3b7d330e3684777894d38f5f9205bdcf9929e1f3b86792db52e76d7c14eeadf92a4afd21b3f18a3872e55bfac65ae5dddc1bda97232a43e000a6ce79c4f2696ddb140f97455be2644b457bda6a9f7ed994ee71a1980ece95de19563f578ba993b4a31478d60caa8486bc9607671daf4c286a4d1bfe5c5b825207aed6b7fe95f41ebeb2cc4d4a08218d12548aa319a1bd0257170c3f5d1430c5377e46ca965717822f919c925e24c2c70f5f6a08de7bb4897d767d42561f26a0726d977a9a148446bc5aef8d9027ef9c7a5caf7db366b925a41375ef92a4ec498023d2ad51f7c4d42eb5ce26273930741df662e9df8a553e9395fc2e58cc0b2a2949ff4d04255e924c4940456d810eb7bed38a36ab0e0f3c13a51ae7efbe0aa935872441fcc9daeae0bf4dd2a82810cd269b2f4b5f1b7088ecebd802a0a371306b844b717e09c143b0befdb52155bf1f1df7591043d8ff88e60e3d67b3a3c92694e97bc5d50d9a0486ef59d62031a1136b8f116d9e6e44a5c8b752ff70e599f3785dbd2548feed9728fa681dece44012d70a5e4aba04c7475c8d1eb01e9269fedf8918791e0443635e863373cf9524852a10498fddc311d76839a96307d1c2b1911494a9a04622d0f23bc0be0f6dd3d22c4bd92450d3a9bbb562fb0171cb2a7355a7399d16ed1546aac319e8f593d763a56016f15b5b175d0bb11d70a5a82badf5ea103ec820a12d50c346d7c92fb89e5dfa08df4583e42432ce169aeb8f4dc537842072fd0850edaae64d75d36bfced1cbfb8d458759777f160ee658aa81724e41e7122fecda9ee81d138a85a6d2db7a9572db9da56b8c0110fadbbcc1c1132c45f0c37149634999c2f0f5aa85dd263cd6b6f771451cf665b855c83f713c3579ef0f897858b7a54c5a6d8720364745b50a387f44e8b65d1946703a554b4b6fc3b783d2c99d60288c2de9dd8b4aa9a06faa67c1ad02f01688760a8082b28718764a0e4dc9a9c549e5c8165740356cccc921d56d0e1632c95fb165596c4977c62df10f491ce08f9fc5b34392e37909315e2af1efdca4f6dc0b7311136662860f3746f75327f3f780c87a120ee9a827549b005db8bd41d4c4f845ae5d05b03a4a4ed6670a7f36c5935a870229c7251fcd0c5c6956144f251ab2a39d74de951d0dc119cebd872b525de854947200828b013e99b546765f9053c7175f293593a6d02a7baf1ad46426371e7d29862a42d1878e32c21857e57ef6a21b63b8bf3e502807867870eb63c9b5596b61c4a8e88bc687d2003a3d637989e01a6bc1dfe7b17bd4c4cb7e309cb56f25a9bdbc10d62244c7d2003a9b6bf863edaeb7c32c4233421ea10881488161ab0fb2adead6ae3d98aacd3287f661743b4742d83b08b06e2141c5c03897b4672f7400a2cf8ee32628cd2e27a0e2e6857669715da819c4ba8fea8d82e2a2a82e32ff2e3cd +MD = 40c943edd4867c0e53b5d6deffb13e48907d85a64c5dc10270272f3bd4f4abae + +Len = 17144 +Msg = 42110a204d2c48f945f42022fb8982dc74664c963594b6c1bd1dede054c4fede03f3f6a5e4f547ec9c656e5025e7d3a7d116f1918bbdb64f60492dd93f7e5a2afd6a66df9c97fc00cd85f21eb3572c9eeacdbd54c8725054e317c704d37f2176395ca1f5007a2cdee23bf4b22e435368c974f908731d4a754c6e028a97301b69bdb3f0109507a22ee26ebb341e1211ae76f4eed415256d5ca538279313f70fac93559b58e5a42597d60890cd092c2e18f733e1e135f281b1f65c7e46d03dc7e7c32ceaf477ba7cc1c5f0bba479f9724d561b1d565bec4e1b45c24fcc556b09c1531e240dd3b27055b70e84e3f5e1a5f69b93e95c107b9b439c52e24d2ae79ee24d1593ca82f2c9fbb54a32af064c8ebacc828c1bda0732d102f47ef0d81b4ef3b8f87d540be44f5ac58c0f3332a2f642f3d24fba44f8d96c80906ddde66de09c9daf2bd2f6efc91bf2bc6194044ba536176a7a62d3b659bc1c0ef53ddc471e840321e56dcc7a01e541c271fd01af633d4132553a11a97a6ae0565f384310ce54f238f34d13efbd61bc868794b336f8ff7812276b8539031ed450f3f5a230b9b373db9c9956b5c6376af1eb81a1492b25c4f23a1cb7cfbe7fffe5f89d810fa74a8cf2297a1a34e40e53e9e4ed534ec5572dbad47630d1713669fbb857681560c14766e217e9d4de8e8057bb0052af8f3cbc523ea177a9e5eb1a7b794ce0aaabbfac1d0f994afd7e60f824b9e125d24e7d78a2c0c414bde2451b4e84a3703651ecc200f827c6178a2cc33623b95421cdc16a93a107907730ec735a2185a1211bf191f7e5eae48acb99ea7744af6802d3b1980b2b93723e96892a89971afad3ce7621eb1d092cbe095074ce63ece8df27f50cf3a4904279ddc449c2308903b435227bc2e9ad261c0cf96922c7975c1f9234ce3455268992cd44d6ec32fb442d179ea66691fe5b0a9b3bd25db9d94c2adc16e4b4867bcdf02eb2dcf1e69746a43b91aabd5d2352f180beb66681da4168cd45585d7fba99fbc8b560b8948690826aa490b19445933a812b1d2567c1c3412c6632168709721b63f66c2984efaa306c7f5f29808ba74b672a0f82b3b7581dc32478c6e790e2b8c61c072cfdfb1d1409c91f0c671e158ef9629565ace38a6458243457e879703abad03aa949d27098092bd84492256569017cb6b69b6ee07eb4116db0d0e9a50907ba0c88ae9b2b23334c93b849c92046451f7b5dc87fe2d39f912cb9e70a078d758185b1757fd71c50d55850d432cd8c8ff4ea427b3f19cbe14c785a7704202fcbcead0de5a5fbed286d2df47a87f4a3a5a30e4efcd50ccf41ec597bc6ff7855d3488d8248351ffd83bd1c8c84f11df34fd3ec67926a44458816d7041d22956953982cf9e459cbb4296c2c003a97d1e4572c8e76872647977e74fbddc49501d11465925b0337887ae2236538e4a297de8458fb6421309f2bebaeccef038144f7de58c88eebf7ddb7758ad01dca39f8499dfc3b17a9b1d36b976c5220220ee4417919d57ce4c253d3ab48749534857b8d6bc3577966d06cbe4a55965968636b19ac4fc10b38c071364c065a8969ada812b6525671a2b6f18bcb119f831fa961e640a295252d18bf49206b88e2b2da0740455440e6a38aea3ce34976848d074c0ffebc58b10df3c572ee20088657342180e26f1dc2b375e0385aa52146faa6b6feab4212971e780c1a80cce25fa0e27d38534bf6ec189f5ae7f8ccaaafb0ad261a12dfcbbfa9d01baa9c181c54d40da3d26191d24c1a2fe0b1846718a9f64525cbfa398c11f5227a880bacc04c3ddc1cb4d4e9baca034efafec81d741b13963a792af85c754c97b21e942fd53121786f4874fab54e192331368a97c5ec50c7ed8c6bc544d3f4574ad3014a64eac90824f4096dcbc0a6d70cc1937c1306f501c66c85484b133689ca0e19a4745f7db5c4225ae90408f0911407ab7567504a6b4e824028791d5a55ba39a3e60d7885a7d6393017690e407acf71992ac8b2962e0c34640dd6d9a8e4a3bb68b7371d2805e2a1539f01bbddbac76527423e14237188ebb8a16b2f685e0dfc30c0fb36aff770c18b28d5f51178844c1b66d15e375d4b1005893f08e1eb7e64c2a860ab62a70903a05aeba522dc8c8f3e3d8a781b1adc0913705a4a5cb1805be8186f64893a34ce59df4db4590f69945870704b17cfc340aafcc5df21db9a4968b82f496cdb7a8b7f5c0308fe39a3c531a68bbd72a4891b92d587ad788f55960b2fa84353b062a0da7c138b5981c0899088e4b776c2b50492a4a89ea9f537aa9926e23885e1747632e48723b1104a473fbd82226951cf6274113199fb37caedda44e6124b9738754f3f66ba500ec96904ee6ee49478609dfec32985b87a96c89632bbb7edfa3705f933b9377ca2c356a8c3aee73f60ef1df963984c26e922a194976911b331f88ff76887827ef4c276f3e34c11b23104492c9887d58da9f6e19d1cf906e46503791288d8839e2d4d31acf74f4c3412278b610bfc0837e59af179697280cabde12d1238b5222375edef9da6c07f0e2be14a5e6402cd6bc39737f025dc66ab621911bf22244757f328188c99a69289a5b9efec4a9e0c706b731dc9f83fa0d07b338fe0ee30da80d089144278096ceba838e0d365daad8f06b90ace8ca4158131b80e3f44dec3e733954b87eaf2f77c5be486db5ebd9810bcee66c58612af06ac2ff6a2ca38ead445d6262297671a86e74849ccdd4fb63bb49c9877919255a61320aed22b45378e2ed30bdd2873bd4f74e9926d8999ed57174a0aac532befaa8e13a0970d0d935f1514637e451bc8202951c7870ba226ae0c81232c74e5665a479133b81999e48d222297ce956924412e0752e20a734a86bcc84bbe9dc8a0fe6321cffff6f014617f840d95c164b7faac9399462f123f284fa7ea2c76dd86de0d4cdc324c1a092351c22f9b70146a93cb7e067b2289efdceca6683ca62b00426b99c21ac520ad1bc36564a74b822653b24eff488ae040eabb4e2eb7 +MD = 29cf92662574e34f87f056f66104497cd0a0966cc2164db8b525cc514364951d + +Len = 17936 +Msg = 68948be01fdab2bed3182ef08b45e162d4ce5cf264a1a225fc842e1893ac38bab08b353918e99dbaa936f04d861ffb20745f58f384d834cbf3e254eb4ee35a00d920459c32d238e5327d7c8f147dc707d9e1bff1ea7dbad5003bc81541b2f323acfac5f0b6be0ba83592d99c7e87ce80cafd99d6dfb9bcaaec389080b4428a8beec2bc1fecd49f697c200f5e0c6797f1115bef89a9b4c3b27e80b612eebaa7a06a1f33101c3d7b91cdcd27bb0542abc374a2c8f29095565580bc42b53943d3c9e7ba31ab8e202789f141289db343905fbc7b2df9de85fefbb8933a50db0594712c3abed88aa62cb8b0251aeb5c8fd02bb18d2586d9ab420cf0aea8cb1d2775fd0248e27f57f71185d121068d4951f3911a81b881cb30aaf0eeb4930e47d2fbd6318ca6883e3a5e5a1edcf36ac2af7ff8c0feeed2fa3bbe0f7b4e0400a12db06481ad11db87989c9e5dffe96c0ed1fec86cadd061aff507d25e24028b73611b0fba542c617a3852b85731f07a77e0f768e435651631850c9f61dd95960495c440a328fe005e430812d41b117c4304f342f040b6daca1455df4a21c50a9df2345d05d28fa17de046139c65535bbb6479bd5a73c993c0ca6bfbe29a9bcd86a0f2d0a8f9e72d1d38952376b6bffd27291141e978a82b5cced559f1ee1ec807c686ff54460f8a87727caa2bb65b4bcf7a433664f75b88e6491b633fc557e3688c7954d1600ea203b78410840e312dfa8098059497e894a662c68093c84c07f01b5235e6f1ec5bd82f33be4666498cf263971441015935e3425d17b69e071ae89b990c5d9eb19f5001141a3c65a94efd4ac9cc32ddb655e710689271f090059834d740fc116655b156ac8d2db45b5d645db49531d205dbf8f570588a66edb1480c92398cf2136544558580e0fb679f6fc6e2d8048850af5f19fcd1c9a72805404e555fd4e8beb6512726591ee1d3fe65aadbfb74a89eb964a39465f85c49e8c720a51a9e9c713220f31782af0ea9619034256849daf8e14ebcc07cdd2c564427aa0cd2b0b633c0f8e2e1615b2bf1af36894a854bc5650f678b097e42c05900a61511efd3dd0d48231c0b60eae0b1d2a0d4d2bc4212ed2bf539f6d3edbf59048d893dd9cfb905b3e7c81de523d4f3b1163b4374f568981d41ed10e3a6d25f38242d16f86cf326e78d0e9f5acfb0be34dfe627142d706fcd93d0dd1737a17284b22a26b5723375cd5c171a26b61b1b4345fe0506b2d27923330ae7d567d39ad081a8f576a820fc4d9e0b16b1a0be10c68eab66b14c35be0868c2b686fd11df04d7ce09a4d763c250991219635540a8a50314d17dc34147627b20d093c2024a08fdc4eca8c7a4cfbc9752ada49c4be8c8ec62ced2de9f1b1bb44dbf627e4fe2c43bb326e8408a2c7bdef659dc3f84da1891bce51866f742195b710b5df89fb020d8c33dce0abde073b624a6730495857b394b9fb724f0c546b8b33aebfa9bba051e1bbbc1ece6f38e69041ad1b426f1da2e378317dd33ab88133cd6734aeb0a5953e42828b0ad6eb23ec03f5e17de271eb6a71aa15c68fcc9b334675fb136a806c0450a6d1cb958c97c7d9d83f4662e2d1ac3eabb6836c1f0e1c27316f7249af2ad67ebf7f9b3b9ba6c66baa614650ef1a2b57dcec84501e5e50e8400e45eea076171522e0e42996d56a020314084d05195a25b43453ec49007412185408ca02b268cc87a250f01ca8256578a3e6b7b343db50a80a7c912d98f83d30dd256c24842e0d44304c1f8b937aee51bd6c11784e01314efb68df4a8c4fb200063625a45fe94fef174018722bed0544ad22fad28c7e701f7393371e5efd293c6bb5b6f0aa2d1ceec3d77b5ed5fe52c81f95c43083a5757fffa629278582fb1c7a2e70a7f76becd9d27ca8a026215f32712f1e40c808ba071bfc35e49473b046ce0ae328cc284826afaa30e490f8733a3e695951ce3ac63b451fedd40041e131b3c59ef19cd4a75bc7da94aabae64735f3df16020a9e2293078ba1746d6ff663d8090490ee0392ffc7985450e86d33cc2deac4c001b54794dfb9f15410706863b72fa495343793790b7de075ce0fd1534936f61a4812bdb73a456de1bdd5dfa7bdb40f6d03e3115e2fc5d997b040a861d22e2a8f4238ed70a39877abaa1294a67820a596e1989525813aa02553a2117e654ac28d948a6f67a83daf2089a95ff6631ff78131baa755cc36c4ad0ca6a51f5f176ea393a9bbf2b4af54deb12c6a0dfaec75da88dbc0655d34b7ad6fb0ebbb3c1e7f4fe3f94bb865683934d4fe7b53cc20b1016b7e68eab0cf1994e1735de888ba8500ea0b970f16e2acc159a1ec6e435739743e15194c53603af1f640640dd19600653a53368d55c92012b3b935c3fcfa6fc195325a00d192cc5332baa6b1831b81cb3952a2b9be6643a777a70feb5584d477f54893aea7c12e171b349e7a39c589c18bac53fa9d5487de09fda35ae970f7e5c2ea5ebc4285d0ec146093ae422e78d695a2d2e69f0e5d451f1fb88925595ab9a27a23a04e6b6510b2a15ee458a0ef88ebe8a804101e446afb9fb7fc95a86d52088a8b0107cc5b437a8938b2c9e74e46e2e03bb9bceecdbe34002a2bb6e8b05d699ded351b2313e2e08ac970324c259f3f1c069de21a69cd5cb377ad1594c42a4a16d2e2f52a2f7d692879c31e59f600451ea1172c0ba906da5c28e71e2709472ea7d461322c2e8188e4d211ea9b4ff8994a93cbf73cfc09415cc6604d3a00328ba35a563ec3618dd4325af3238a8406b0324712d048d3230627d8bf3f28398ae5abdd28976a98f0bfa38cdd559242b90e6843824399ef02ad5fc84a508c25aec123e55eb89c1568bfbad036fd6d0c7e185f0190cdca7026bb672d981dc0452cb29e0b7f3ec2674468eadd96875531c4627919d4db3536eda4d0613f138f28631e9ca7f076981f123fb60d828ff5632a8168f4b4f87473e5ee1e1b95be233000798253591c67ad60989ed87173b8012ed9811ac7a1f2e7ae1bb2a5329a370c8367f1861f8ccb82ae2817d6e9ef37ac3fff63f463745ae284a240a6ac24351e4a5e6cc8ca443e4f5952b371623edeb4dc47842a4ecbf6f528162a9858e8a7d5e3b14683dfdf3a5400acf440610f27cb92665424b03561aff6dbd2e2cf5409d3ee25315fd6ba3a4 +MD = aca454a02aba8dff7251f3dc3372f4a4953e81593325e69a1aa1d53df5ded02f + +Len = 18728 +Msg = 42b849668cd7341092ff4d5652481c2d415d6fbd35d25a5a83b87cb7646f84569ebcf443601b25026d578bc67c573be4df3baa8664a8b8a4795fed3093150291d07fa353dbac731d109751e3e0fdda5c776c2eb79d9df78ada03a80bdea403821f28defec42f2647c2e8241545e0ff7f511783b6a95920f3f0cb36ae0ec59011d5df2eace54f476acc728ec472a8b534b5652fed50853bc901e01e83eb1faf2639ce19c504b2dd6d765c165830fe0163ea7ebcc259c94ef3566ae8f03c5b6ba9921a29b1ea00f03808cf4539478aedf43989b29f8ecc635937901d5fcb20c98229eee6d95fe289b3caf2a1cf7ff380d0eaae97ebb53781e3eb7a44375e17d39a4670d7a32affaec604eeb483a0e1c2dd4517f50e97b1b179bc51e5e0bee790d730c8847815016a59fdea06bb71febc0491e95370fce3fa03f03d88c2b3390822311f75c1e68dc254fe0f1de0bbef752e184f3a79ac746469d065b64504b544648f9d33e4664ec09f4f84835b465ff541206f31916e0df793a4f2f6d17b024b839369454b5de96b223872c092daf44527f271c0200b56bc69b40bd1cedec9256985ac335c9309cbc601015aef3f566cc6d67e6f8e4cf6bad447d9cea4f6b1dbfcad8d8681cf54e971f158dbd93c2e720813bec743f696f9baa78475bb8b6374265235c521db72cc0c51a0cbb89b2460d3f3584fa7d4dd82051a334e7b6586f8cdbecb78a37d0c7c806900b0f322df3d11bc748f22ad745c9be90ee24d4bc370db377827717eca02b381a114f49a0811a9b73c101d48028f665c3eb89706c2e33706645bf2a553658fe1ab7e22ca46e5832cd659fe6e30244cbaeb58c25f2a59c973b69b8ebc50adfbd14577e57c42c087636af32fe7a622374d3c4b371ba4da79c59770ad8968e3de989786a576a4aa9da32164167b0b910e5b5a185d05d76f2f462e61b7d6440e227fca33ca8113abad3622361df2087ab92d6d479be46c1fd33ca4f614698b36aece0606bc6537cc9f6296f0ab1344e41f0b9c615b7f0af34df020b72d0ae6636acd7288e4eab9145b70a51b27a768d72a3c0fed049f5af185aacb2d6883fd9e3ec33740a8d8418cc9a8763efb761b5bc10aef73fe0c032364b2ccdf2e9b77ee12fa7cb671f6763ad25132e18e480679ccbb647bb08eae91d04f4c55e819fd5cceb86a73a80d01285cb4008d48e5d0383498958e84ed0342b2ca7318fcc636ef5a4629feb3e5895e501a09c8911522a1dfe9ab33e1f0a93ef36b68afd46acbaf9eece0dffc46b7e297c9751dd19fa4bab6f6cdf32f61498d797a54a2d6cd63a483f1b89fe9f833be170a6b11704cfd8da1062455d7068a382e3f5e7a6cb6a7d7ef9fd8c5e4c2a4faba24132ed6e4d6228963d8e13fa71545f902afbefdee3e4fcb3c68d9546eb39c676196fb6c2fd67f5453101fd00e91bfc10a6ef6f03ed21400119264a1c207ae06071c0098f4a6aeec1ff498f202a7ab70a0c4abaf6c082f75667ced328749377e5fccc6c3fdedb7370fadd30e4aff13ed0cd963a1408aa711834efc71842040b9b1cfd4561054a01f6a63588aaf40fe2096d4a92e840084beaf3119c58335d09e454db2b7f683738b7a3db0d0f91375f186de02befe11cf63334dcd964a2fef15626de9507721386285646246f01f7f48231ef8b977668fe757c99f4da3b7a506515700885ad6f58ed400f6565b0d240db6bd1288b8a7cc3463cd18505475fb595b347fc6694cb4f6af38f56704846c2887e2d991867b8e319f83be082510f8f6c62cef746a287c825d34e6e0b12d6081deb6d33dac8adec653111cdde031a5c6da66d7f92615561a281d512b2bb0070103618af4f07dc3dbc69fb7384b7f08afe10bbfbd65b948a6561bbeaf3ab46a8e3d0a861f1cfc46584156197f30a32c9a21422f28eebc5d0e3055b6d4a5e18f11d6d94d24f6ae6e250c5dc91c55441670e334b0a28bc79a3afef4c00236e0807314f7696d473c432b6fdd4f75820bd0176f08c99302820913081f65a1b359459a408c6260d64dcd50b2fe34f4819f61790de703631c94b17f95ff2c19e5f3e470a1bfbe676d8a157d1ce7ffff19aad17d05f9e57aa1a69a67efbc9dd3945767dc81b907e9d29b229bf6c1380011d1280a9e65f740595fcdb45c7d4035882dd5c526a2c44ece27fc9088b3675e32be6f0a2254c11e0c68514c256a9ea8881c3715d9a17efd29d6ac461ae615814419ae64d7edcc7a81682e1992ac3e955ecc94b3e2debc60ab5239a3f482c9d10f89eb0006599fbd81086d02ea6ba862d0e6f487898206de1c40ab915eae0cb65ab730c6f6bfc250d4f015ee77ce6579a712607916b5e4df434b0bf79f926598ef4b849ef148be9942c72ec77ffefc40aaf7de71d09edfcbe91960bc00575cdf94ecf0703d1c1a029335c1744b23f521a33e795701667e0bd652b2cac92579f312427a2423625ef28ee4d4dd2364d982588e3613ef344a05d29f09084223453c30f62da2eb4313d1fc7972ea4ee92fcd93901f8de231ca22a5a86e5eb27a4723b8b00ed2dde6c006a59fa08316db7f691aec3bae248586ca1614e8b46351070e7017279c4174edfb51fc6890c16252beb549925cfc570666ef8b80f29bd10e6622d47fe95e142217c838d1f998a52e342e4f2d80b1cfd35cf6b73d01a322e394948f1e9f7defe8c2d1fce3a6e3cd9e334ca713038c177416f43d27c7c36b0ffe8fef0da8e62cc66436f0a77fea012723d6f94ccbd55471fab0c8462d42d5180eda9c53eae1f44565bdbb246df46a536c95ece1c2d4b15372f4fea31b6a87882b3f3ff84fb66feb2e2f0563564b2fa9765129d9cfd054a0e58687457a81a9e6bc848005beacc4432553786a24357ab1aad1583cd91365e3bb2f0c3430d065bb2b7206811e0c1cd2b3f3ba43bdfb70f46edf2013cae30da15bb73579279fe18edfd17a74591e9e2240d573f60be53bf92b412965898973642fe6a91b453645e7406983e6562a73ba35c24c89f43a03484ac01c3afe4dc1b39e84112274dcba4eb601cae0fd78c222f882ec066244ef6a3124a19a11761c17105814979bda684ca963f6693650b4e3f3ddfd743c4928e64a355f8eaa4eae17ed2b5b81a27876688155b08ae9f971848d9b24dc6a92d644fcbbff1db11b9f3b9ec58de870fe0c2ba6a0a04afebc208d2d830b45d3671f0dae7d28500e26170b89ee53d4efb4541c810c6db15de1e9863d5f5ab7610f2ec8ca44832ea9b73d10176e554e06e273c37860c0c7efb0f5f824f5b93bfbd429fdb7d8b8bf6a1539d1b00c +MD = 05e57bccda00a36aeb23c6958e1dcf7a162454e8b72860029ce32869da48baf5 + +Len = 19520 +Msg = b67a27e6468229d4decf44bbbeb1598a67b4934fff75eda9f8b5f580edaccff3cc9f7c923ab55dce3307f2adf1f6e8c310c1535def5738ff59694e1165c405d59adec89c57ae7f3a72c159b7208bc84715fbcd7cec5275bbc834a4ed3cff1176685d926b65159affe427ff3f11170100be898915bd0eaec58d3e7d7c3a07fac07e4462672c91b307ce5e6eaf8d439cd452930f8e2b34ea05f0ae64252681c89a23bcc0f873cbd4397b912e6d5cb7a0ad1b43e851fe6c326339acde53c91884eba1ed3586046b047d32e6c5e3461a15725fbf9bc4fe5d8dc7af62756bec72359d3efe4879a5184cbb3a85bd771314040b672fb051f2b003199bf6b0d65537e397431782391f7ab2dbdc979e938a4f745f7bbcaf5fa40c9c41459017fccd1096c1f8626a2e3a3a41c66044ee9e75706d58e28e2155da1a6127f55933451ba55703a40488c1bd00fe620eb337009a22f7dde6cc8e9d5d8259b3f3788b1a099d2d45902864587273f3982d0d0020c10b1bd7cd9e7c9ef5eb8cce8616a8e15da0216f05f4875d1f3c27510779d268b4d3e02ce02d75c069fd035ef85b1004e0583a69499078368d03a273e220343f3a234fc567a1006b8361c54c8f6e4de95a6a801ba425bf4d846f6de7072aae0d1aa36e8aaa22a60709bfda819478e7fa9381fb6e60dbe508cc288f96bebec83b1dfa4763f0d6edfcc4be4be44ea0649d5243b448c4d971d12cd710674f040b2f0bd0e23983e860b37c071f5c070f4e3c6158b2931748eb0f6d24f9410125fe52accf45f2a97e8492f9425ed305ec2c3e8669fd35a24fdb2957b6510e1d492a0cc79d7a78abc1e302021611309260870b8a1e9e18ad17ca89b23620b5eb9715c626e289b1d1d8046c612b3f5bf493e60b341e9c227fc84096464b6e1eb33849e68f47788762eb6f36dc2af03b73acd1a64e12ff3d6289c3b8db9e4431bd544ed6cb7351e1a824adca3cbb2cba59d4d0449ea1d0509c82dd5738d6a9d65012aafca2101ca6e9a9458e4885fcbfec326c4dee74164276dc15db269ca6f5b69ae7c2dbc3dfc06ea2bfecca31673376ef2c290432d9fd38bff3ad6d98427635158c8f4036a4167f38a44b886676fc3d329940a88421682a520033d571854116ab22ca9711729063927a124ccd30038a2439faa412f76b94bec3d626d0773ea18330dda9fb521664daccabdc0e9d30a4ec97c0bf8362eebd2ac5fe275c21561dc63e2f3e9d4a90c8351f7d00d0c56cd5b438f8c0806bd9eebf8c14a1be8a6fd49bd5281e9f65e6d8cdfdf082bbb19d63a1a60c70b019146fa5a27e5c9dba720c2b7c3010a8a801dccaed6c297868ac97dd686297bc748888038fa620a2ba480e9dbbafdd601dc71c547859bcaff282b9900664fd4b841b8101d9f2b57591d7221a1a0d4d71cb21df91241f0407580511e10878690652b6a1c90acce2bd47098fca22b22880baf76fac7c26c929a11fe6f9f708a494e5423180a99b7022e5c59fd45a073638f33212cb05d7d2bdd5b782005b7b779f45a579513fc7284e72f298614a723f3e7db811174998e96afdb52b1dba39a7cc7bc9c16253b8cfe6f67ac3987b5c0a3d6073b4b7cfd2d4d81f002a789eaaffc58e9451db6dd530957a4468a2742e60dba54a42d31fee5cb04682c73a8e36463286f070e5168812010438cfa6bd4e09c053240595c252499a7722498b134543ba6cc468a8d4393cd29f3e3fcddf26cd9572eb43233f68633dbcc8fa92b43fbf0647f87f4b324e77b1503e023f611c74020b8645a51e9772421c5c2078f98c82be1f73fef6b5308b4621205e23cb9ac5ae24dd5344e8463d50a0c704646a945489fc1f2dd3e747403819cc9ca1a6078942c8d8b42724df8d104eefee7f90bffd0fe7e353074ffb5e2f402b03e379cb8865fc5fb2785ac92a2a30bd25f1f27644f9e7a7b9bd75b5acd59f23dd0ecc4e8ac0ca5a935c126cdc454e19f3e1181ff3ef0553a81be2dbf3cf3d9d704d28f757fb39b1a0fdd5306b09aeec9e778b24d09848d066491dd7fbc8238206c61330b6bd514c21832a7d9e205a1c6fddd2eba49db8043b70ae0f8c6657b8e5a1176171ae1b135e169abb3e2f5a93ae3875de36a55dd871b81eed6e51e3295507bcf04e779eef9edcac5213e1b437a3b3fd63505940344f48f4d76832cebba020894616c0e3c62b00e8aae5db72f29673f1e4b86168011c49b83744b121580d1306cb9030f0824ba8d62b7cc89cabcea3d9c83764dd2521e2f374c875e3e7e309bbe78670cf0947fdff3ea04e384a94693e77950ba88aa63c2cf6bd271c506b293103be2888456726ea49181550b630eda6599afdd016f27eeb25ea6ed57bed9cef8502ff211cf24b1fb6adc6ebd9ea589cd60ee25db34fd1b86919f31550b0897dd7189da478329627eb2709129a09d2a556b8645848035d1c2a105ee4b7fe19645fc8ab18406d2d89524e85cce1d7824b416129c8bd57499ed098564a981d732b87dcd1865cec38cd51e9e321969a9115ffd1d9b5fa93bec7c3798350db56c15ab61ab6f5b3f7e07c52c2ca19a29b278bf8d01d27e6ffe31d6b7b8efd68f1287a534c036d2fd54c1dbc9fe3bdeb226a3694269d276be3e12a31661f5a2736d212c8385ff7b7d0a638f749d6145a77859d3c9a00bc7086df767b01dd6d006de7aa7ca77399342e13556b884a26d7e19e4956f6eeefde310687b2157140dcdd8ecad760e75d8c38bdfd8023e8fc4ba9dec04c0011c79b2c7ee73f6a82dba1cff0fb412d624ba836ccb79ee4579d9c186c8c84810e4c90bf6e1e88c8b944398b35c422d48c6a7070680c2d913f11b474713468409086a532feb2f7f7be858a5984aee21e0ec2cc2db78395f34a61790514415e073d7ec3cc582df3be38a67e810540e9d3905ba5b7e4a43ed21e94d5157e3ad09cbd3bd0d6a117e3e7d0adfc4ae202a0bbb93ee15415f790f663b2afead6a725c8b9c5b59804f631382da4ebfe407c6d9d32726a4d7305f426c2c4eecd4511c553d9255b5aa754447af89235e34a37b943a2ff26ea2555d02ce2d17c06f3ff1805c462a964b2b88474d880c14125baed73b2eeff72536f8dce6de140dd07f986a6238486fd4eab59f076757762fc8d6ff60a46dc2f27dc94d508fd229aa98777fd9d94dc6fa3b42bb479793f8df539a994510fa467c7234c085d2b0a84033253d3db989200d85b628a8a94010938450114305141635bcc1c311475e0e43a8182f0849b90f91528663851cfa51fee39e1404e159a6b0c606e16d5e38c0279fd6c1c41a2bea284a4a086753113173f9eb0de546297c60166a981477cf726e62c791fbab704424a56763e9fc3343952fad6b7e94120be6466343812480798a99812c096e14a2292c65126768ceecc50d8bb93b6b91d995ae87903df4fa59febc99dc87e29788b827d9a08a3942a +MD = d64f8f18ceb845e9097e41e4ca3fe0d0e491de285aac85e18c11b5fdf2c5a60e + +Len = 20312 +Msg = 27d608665d73b02b1b55f7d6d4337f13db25d6c9c970f9921ea0166e2bd896b82f675b59c09b463b6cdafd01a1eeebf5caa18841bb8ada634f263cdb4f2b5e2696188df0731134864feaa38a908210eabd52db12e245176136ca45dafb28621da6132595407c82f20cad72da6a94f6dbfb5f59a5064ab6761ab5bbd5f57aac83a57dabafed853669ea4af159f6cfa6b1cdf18a60ef40c289450f253306c74442dc81a7a643d35ad232e9a96ffed827527b30f5ac64d04081fdff0c5cf6b830409344a2e10a0ff5142db42085485a81a84d4322f22ea23a488badf7b88df47a6712f124ca0ae0101920d1e0019efbbd9a8a539998155db7c537426eaf93242a9da0aeb3c80aefb2c85668714dc663e20f7c87e308e1aac0e048e6f9a9cfef46cc86a3d943d4e3e30916a259cf883bf8f1690887a85a305c8108c0210e0afed8db0dfa1da32e65abc4a7a622f1ae2b08279afd0de248989390bdf96d460cf8e7b27ad80751e11d13e1529d531afeda1899578ffe1d72896df5b0b866b99d867c39186720b3b5b222495faf75b142f1332fe8e6e0c0a1acf398292692cf85509e582ecfef3271cde1e216030f2040175ed194293e359da92c626f6b7bf18bfd55f70338fd37df155695bec2a9cec1f5a367a4819de32e272139ccaea9857935a9fee0c9d028c5338b4ba113cc238c3309d9601587321cced8078617a3f515a2a3550daaf26eecce88ea051ffe876b78980f100e838a2e475bb2e6d0f1a728ea4ae4d204eb721c8f535b330eca62246c59f1fc931a532d3ab22334fe1b0579b5a79477ff419b1c1df6877307b51c80b853686ccdd2f5e24ee343b8cca975d2acc04b43c27e50b62279550d32491d47048f5aa7e336d8122cf8f9ba602461f9769ff27f7629fbb043e2ac48b80dce41f713b1f6fecb65887cf82c81e21430b7bc4c727442cb03d32a3b766dc18995353ae953a1461b020be5ecc6567bff4ad426cdb1674febd0e77f8c9ac47446dbed75192af0e2ad18620fdbae81526f17185b2c99a3c411cab4e9db0095facb092f4fa91c2afb091056a3cdcc4a91ebff4b0471116fcac65901113290287ba085c470a31399b8b850af49cb08f85dfc6a34c8a200128990e5989f9832c41e4eb974810ef68342414235a8db4ad5e128c09c50c950d528fad63f3a16ceb30b5c0b062af3ad31c02c4daf69087a2742fa694b44ede800d08994bf8ab24c3b6b52e54412591feb5b02d8e733578037abf7cd094b17b0dba8c787e0387694a566b9aef4e24836f93b494da3afd2444d42a9549e0d4e90add93b1769ec6a8e392318cedf41c9d9a2878c13ac8580afb12f9767d1339a70c08a6dad244d95233ecbf7adcdd8e2f02f685092ca5c69a7aa9b496c6b6503385ae4e6afd704ff39fe85deb3864f9d64e8051f32c4dc961581ae48cd354a92d0c40f2d874bb9b0b9bf7a5648d14d021b1587805b64ae0ee27f8f1bf0f48b4e204632ca9b4813b18ccad1e6d4777a18fefe15fc75707ad9f4e9674a3f73cf40112775465596ba099867b317bf417fe7f5ebd81ae8b1e700350a5d5e2079bf6e89b101281cfc57c0c7dd487071f40477e923f7621cef9e8a8c299adefdcd03e2712afef8574392df0076b779525bb0d1c0ef9b5c7af2477fe08d45523d3842a4b2db943f7033126c2a7829bacb3d2cfc6497ec91688189e81b7f8742488224ba320ce983ce9480722f2cc5bc42611f00bb6311884f660ccc244788378673532edb05284fd92e83f6f6dab406209032e6af9a33c998677933e32d6fb95fd27408940d7728f9c9c40267ca1d20ce920db5278679dda94d78254079654e3b69324e446dfe98962cea9d6a432993b22f57750a6d0c4becdfb0ab2372918082fe320ad56ee72618209ed0e78f00e6362fb92e4298139bc7e7cacc74611cd69c5a1f432e56575be76d88a2c6f4c9a1c159dae9b64fb756a42b6d911b8e2dd8f1459f02376d78bd6bdb4f1befbbad4dba7663ae4eda2003ea7542000041ed0fe9875a4ed8fd72d60d319c434b2bd3718b4efb83f280752a018bf1240cc28302ede7fa2ff94c6d2e33391623c08e63959ba94b728a8adf53513521022558183a632e24ad82a3904b47b966c2372a8741524ffa82fe408507423d7aa4344dd43db52482d15b4a03b7af7a3328994965fe1808b1bb36ea90cd3c6aa61122e7de954991bca26d89effad544265ecc312553559b18261bd0272ea7834a51d56f5fc9893d7a289ea87c9a1fdfe76bba2af0c971d1d6ca933a73b1eb51116d372c7e62dcf0636cd7eed121f7121d57497eeee7d47294b0876f9bde709ca06c2f6864e7a9711f7501a51717c4a6702b63734635e746f9dee0b8c83d9e2ba256a46938e05a89574c02137502ed648aeeef53213b1014ae5e845d2257dec8bd33807923d65600b3f7c480146cdc1110a8d564a682b8a65a385da6d0b39639990caade4d50059eda802d361bdcf878ad61fdeffe9148c2a67252dafbd93047dfe80ae0ddd6cf2a75ee277cb3dba96007224f3b50f026313a164a43ca5212ba37d088c9fcf01c6e2b4a999904f05790c6f2b392c528bcbabd2b2f2766a5a65a48cb0cdfd1275430a59b6ad635a36ad193da113a85c07127d8bae8cff65a52efbbe17e6c8502df398ae9847b6f7c4aeb16e1517cb740ac3f32ca5d83a3fa8040371ac6b63f0a2551833dced0d90460a6f60f5ba08330d7c97463768b950c9716657fcc0628c58f3f389e301c9cc212cadb6c17ee1219598e458d1b2ef318ff39ed1779a368bd83cd501492a9df3ec91e6f016dae8c839a564e5134b5e5a61f7176ebb3d7267a6ac174a7dcbdcb01ee6b57d5462719f402e836b6a968953f6186a80163e88a82ade44b60f6a18892e7793ef088a2dff6f90ea6c5628f286a2c3f2d63721fbd5fb2fe7e46c99d3d791e10ca5b1d670910e78e46854772c9b0e965aa19c6c4e799e3d7b4613bf8123ff9f8a31debbebdcb3431bdfe41599e98fec0ca29491f2fb6a73696ba35fc306be2f8723edcef23ad48bfb438368bcfaad418329de177be4065e5cb58a0efbf8540dadfc7d74165408b00d23c1051856ed3358d7c7816bcbf87aafc44621ae6167b6491bfc3fea80c66bcc011b5f3e86d63df81cff54250b9744ed18465c5cea5fb5f312e8a6c17983fba25bf0fb91f2eedddb69d4044a2b89499f1228f389fba2792661d13d3d76c7fc3aa4f04ea5339d7f8d6ee4164db434f520525caba80dd69c7d992467d13108f9ff7c87ed0ab178bf886cbe0e923e30d43b496fd94999728c432980bb1f10dd516b33264b1504f6fa5703a051da11e3632a77c100f136fcd5218344ab699e9bbef86959ed66969edc63c4698467e7f32e886dfea7116eebe393370ebd5342fa8f41afa13871fee6c2592f481ade18b692df8c87502c99a64412c53d656ea6404eb1468ad0c9a655488184ea89af3cc44c8a53d980c55fe2732abe5f481e212369d1fe853ac01560cb8795bf554dcc9298336493bd5e29f70d3572f2b9d45c0a8d2e181edb07c49fe7d5b235125c30a812453f146a69707a5edd93864f43af7 +MD = 31348f741d49adb56427575dd984fd8fae7d9d6c3e8089f4c54f2a07102191dc + +Len = 21104 +Msg = 262c1abe379063c5c4447a28e3534dee0da13fc2d1d17af6c96582c9ce2710e568c81d2c88c83db47a952e1015f7b1d235ab984d6b4f21a0f27e82f0e53bc5f4b093d6b7c57edb999007c397acac22cd57083c3923af5fc2ef5a77791644dc1ee6d36ee6547be47bede06145103a48e85bfe520e63bbde66a84188edc809fc6cf2d10d419e8701637b682fa1a969cd2a29d6035292394393057dddd26253cee4bcd5d9510b69da5821e95633e001569ca9d8768f17f23952ee559fb34eeafa912d27fd9d04eb1662c7a9fe831bc98e44c44bd44c5cae66aa4b10f615f39627782b0e9faeefd35d8955f14d1ac38a1a2c60794412c83472a304f70982b91ffda39fd4e80a35ea59d6b4096e7f410ca55c66a8ef68c34e064501520181084c261972bfff3b3ff8b050ca39873afb17d5dabf21fcd6b5c2ca992b69059b48e647e28a180cc974c50a0080c9c1d45b7352b0512c94e4065965a668833e56e1b50b07d126393a3b1810ecbf0043d4c8e7c5e60610df1b1fdb8074a1e9d43d3c81178f2e33ac18febb691e6d2836c2aa3dd682c51704026610c20cbfe4eed5bf12168288858dea2474be9e7387c127683b2c8e75872c2244c0d475a8bab4a8d330aee8c9650539150cb772ba650d896caa701100a97e0122b25db746b34f3de1a287cad81b3c8c384bfba4290c41731d5149144dc5232966af06db7f19e71c4f314a2f9def596bf7f8333ca7c3866ae3fa609e442342227a7f77e83d32a3ce86a59f200029845eb9dd06401ed104f8266b5cb7cd0a0472c4ea57e66748acdaefc62da4e910e7eee7c01dba757fe2a44e6de767d0c491a3aeb84edee5a12ac8f15b9dc340eda7a2e76a1fb1941549f6c3c8a6b73597103d9eb006d79f854421f32e9685ed08ef0322a3b52e63db6077ee4443aee4cca9c6fe9b24d97c3e226b5f05c1f3d8a9e59800328738c91850ae35a96655c6aa86c8354153ec6713ed319ca9c614ea18b1e9eae13cd7b116402401beb6b2c17bcccaab6a3919454bcdf812e24cf1099c7c7e46767d13001b595fbb4cdcd0be85a655c8de7e67ff2fe94a2977fb901e7f6ee07dbaf1f59f70c2e9c91b7fb4a6123af0f464cbdf7d076aae49327dfb1207ae96f8754184765da44a95f348685f68b02397c6c887a71b77addad9773acb7d65281e6f14c96d292708859cdff3d3cf317619ca1c6965b239ce443594533329ba1f566f13ca6d1e72ad03ddeb5de891e572e2396f8da015d899ef0e79503152d6010a3fe6915c82aec1768015ae88f5f39e5ada6bf93e8d7b96442cd138ac41e059a1a53426249e02ca464b04ef9a428382ea77b6b729604a4ea95642148e3f01ac836aa58fabba9752da07602806c1bfa7f8d6f8cf47d66e48875674ebbe9261841756e2d6db1e95e09c7cd35fb4bacd94eec0da4782390f0c47f211c524822768c73093039a1123fdf371039e8c74d5d132fd0329c1cf54234ff3beaba8597ce1fbc2601cd2dc692f47af98ec753900e72e551d7dece26614092025a3325d877619d2ef2b6ac8900101ff3b525a4f755d4890cd49eab86d67db43eeb8aad871af8a29eb374a1bc0f8872794d620ff5dbbea75bd97a59990a52f22c1eff8106114b68ffa495a1d209e42ef4a83b091e08a7bce956e04cff7556c874452044e802e05cbc4688218d97a9a21065ef24d25516361fcd7efa1cbfffa3822e8b6d9f584e0a7f29caa521214f8836f71ce7b559809f79bd84e56342b41fd01b9f7fbe99eade92cedba14f4f5c2df2ec32d6297e8d7571a7c09375962a9a08aceadfa8405d55a19649aa6a7a462fbea5cf54b14c7344b20c8098c632b9ae7642ec21fed40c1c26208325052a93e9f4c45107ef4c0889955c6349d790f7c9c37e11cb24dd7d8e9afe26a5a1e8dc095fb8564435e583c0a637d73b1c495b785adf0a5fbcb538196a7f82b0b32d74ea4a024dbe27a19b666eff5af116c45b36b6c624341903b2693f2545badb70f5293e32b5ca2718a5f75a437ce0698a7d8151c3fe0cec4172ea639fee486d4be332b6ba1cecd6b339ffe274abad670448f4d669063e88d70019824fcacdfb26b5934e18e1ba98f9ddfcb233659c91da33ed9f25cb4d816cc07305a589dff789e2c76ecfa2a7f064f85a23e049529c74c4f8267abbbe685b6a838841a9e304fdf14b835eee396f8d1fb4c20bb543c95c828106d85605903b34c76494896b85fb779c464712e388caca7917263804cb09e334baef38b7bb74d5bb452ec6fe0cfadc360208cf3abea67f338dc05009f4056d6fbcffc2492ca0b3db8460d10f0c84a5a5511461a383b8a460b05a7bc7d6c797be77ba913e763755a4aceb461307114a66ae0a78b27a79e07d096549c305c8e89d8580140c2ab141a3492e84ae7f395106935b72fc0552aa050361188ff391d68960e0c936aca6fe63d39b1b35f7555fe18b77fec4b6eb678538ee868312bae7fe946d2f529e70f242c6c1784de20dbd9410f06ab0f19caf7a146e0240f59ca3899a85c4c452a7a3ecad223a5ad1baf0aaae55455557fef85010501a4e1ecf8fa6ddbb18207bc3a9adf14dcfe148f59f71ce072d065c7ac8a3c7354d1ef0bc12e2e88d97db7c5d7a233d94b785aa4610a5ea86706871a8a6e1a39e09180dfac3aa456dd279d6cd7bc8dca76f9c98150aa3ae63bdd03a0109963ffaecddd90418797eec46601dac452b68e676aa74fae3e7642f73f2080c674df6cc46e4f45087dcff796242a3725cb77ce26b43d350130db63a21327e3346556292c5a1c268a84131a5b4861aa838f9632b9bdd35cd3e731f2444160f0e3d58fdeee7b8c5c4e052dff1cbaee5b6506db612a6fb1ecabcb4096e6b013d05a2d533210b7e90fdc66e34de16219735398100481b11e0c1244cff88e4a88aa21d36acd9cf87966bd11feacb0282a1ad5adfbc2c46a64e48fbaa8bf47f607a7c1319c589925868a786c46c693f4687774ad6644fd84c99daa959194169cd7efc1adb17b102656a395e1824091ae1cb3b700173233e6965feb3d531f052541a9a9b170dd08e331d89dd77cc5b23e8ef5270ed6336f781251db1bb6071b778dfe02a4a2278943615117b6fafbff8c06664a3f6defb822879c019581f5607b031552ee0f009c312d378be5c58a7f80cc2eabfca20f16cc3b67e5147e90dd19ea1724f77f114792dcb281cea51b3b032774cfab3f3b915e77db10017381993a8c2bfd26ba02944fb7e982d8615639fb616040b60a1a32c0832009c2296f9cc42f7a67e5877a8b500605156bc3e28352c01c8583cc5500dba75d58c16803efa11c2be99cb021337d112dc3ef916821ee8dcd267c4c9303952bbb8664f7e599b79b670cb1fba094be1f8a13cc948f19b90f9eab07547d44d756611a15a0bca2f0f356568d319fb6fc79448d6b9400759990b59d8eaabbca8a72779c3b293013326e1f51981ac5a21d6882b93259623d78563a847817f49e94c527953d5bebf36752eb853a7dbb5f0b326c208aaa5e773daa56e62d63d0c6df98978c85fe924a76e8e179dc2329f5ac1f2b49dc509c2dd0d4304d1556f94c5132ef097adad02147782ab5e4d5b56dea79e7bc8e14c366191cf24098b81437d4dd589484b64a7fc24aedc1bc590aceac86c7020abc7b2bffcac1481e50cc904fdffab60b5cab6ccfa55326ca77ce20d990f4a2b6106e836d25c8ec0fe7c65ea981fcf67792 +MD = bbfe5ce52c9d8a4715c2e22b99a78a5548f6b3912593391e5869e5658f876949 + +Len = 21896 +Msg = 5c6a4129d88584e6514ae5f1e7a8a84f15803b85e4060f135e6ba73e46b9ef1206fecea8e9acfea58a401c038d22fb148ccc3ec3542f261e5252a811483dc37444151049d3889b3e726cf17a45a27a950c4109e852f0b208e794dc8d912c9618fff82f94fee100bbf0158ddc79f2cddc7b25c57c45135cd907786a39894d12041df05211d37fd823eb8417b490d89bf1c3c19905955ecb9a99457a9d996add428843a149b829c97f4d02b887f21d8cdaca5dae0da99aa7538544364227499fda263945c316a97bd6fdd598df068949a17a412c1beb8f9a0ab3bdc4af9db301d2e11c660756c59830e345de4336e37a4eb9b43ab8c2044ac90bf74c6c6170aa34a0322b9ede46c596e79cb33ceaf5c7e771ff006a96c25f97743cf702dd4844084bc5bd0f18f3ac0ef1203e518885d676896ba7bcd092827dd9d2ecf877037454c91b44e26a96f5a3e91ba80a795c5202e93e5733d63a5b811f0254d69968e422047ce7a03ef5485ab7d318ef2542e19479c03759118291ae2f145725aa413c79e332ced0fbda4b3d4391b789f4fe2b33213b70b5e934cd09f1501c6c125423624e8422fa090ba953759cac5f4f5ad9e7c9f529cfc716b69c4dfecc33386a42e32db90ba6d05008a4363e20f99c1c93b859378b3011f2f56e2c658e03864a4107681ab05db87311396cbd3be0440d00afb949be5f318e318774ce8b6263bec7d3e8ef3aa6293a6b190162249bb0f5c9d3d173e9e48db213f00f81ebdb378c7c519380d00a8b6fbe4cdb7504b2479c962d89fd35488f2842b0e3c6d5f36b7d0a8852149b1046d8b4dbe43e02ae70c90ec3ca2ec9129db767cfdae57134655916800ef4c340c23ef3cd020447169546d99f7a50ceca21262a56db25e8258ee84b42ad696f226768232a1f11fb721dd9a0c983a96bf9823e324ccdd0624e4ef14ed519b9c73f9e20edfb22ab444b704b0b47cb82c92628c728b99a2c06380e3eca41382cf41ecd2cf947f31b4d27f663c1233c220fd97b89b3a52982fd6a3495658ff40c1e475e55ee167aa93c9117eb6b65bdd3669ae34b7c1962196f6c2abfc7c6339f6c43b76374709f9c3a0e3ba9b01335dbf6f2c8d72b1c2d3b83c7568499eedf2f0799421e355e4a3e6e28ca6739378e83e66892f367b7722e610222ab8310df0217d1654ed6e763d501662cebadd8af135f85a968d8f1193b32a5f5fe2c321b60c3748aba0214d2aa1a50c9fdb5ff80d388cf75fd27d20aaa1e3936433d5f7b933309182b5fec7f05e26f0967f9b3e90a8ad05f7cfc622ec34c454f435d9ce7e2901877699577522d814a55f020fcd2028c10cdabfeaa6bcee551a7c635f3479402290e3c4dbd346c1e6a135fd3e22301b7162854d6b1aa1210e5a6946d6b83f2b0c5476c2fc70b08e155ad7db96ec450326ad93d2c7fd4d8f68ab474ac0c8344c37389c0e29cc14af39589127ba79d372694462fa71dcf68bec7392f9adf30d262bc3d010f443c7a7cb211e6c09697fdbb1cd9f1ef92850a91259d8de0eb70e3b627c9f75dc866e0a332abc0314198ec188bf94dade6dc06972b485626392cc0e73c966a752f25c4919fc16975b2894a66690d098922bea3f761a35213cf4db21c830c22fe81636d6e80baaa35f15360cc3c7fee2a4d122ada4f144950b7b9ff7d8593e6a1c60724615efe491904dc76738eb6c4396fc0e3677e040285f95aef33c994800607f93192c0f50ec8f50ed483e61a535d91af16c775dc46599b16cc66d775b6d44c21dc2a2e07c3ebccd0c123cd13623fb9c90b21bc02dd74a7d7dc3d38a051b39b676d51309c2e298f09877bca09bb86f2f50a9edce08f7f248469e1737b194dfeb32b2e4f1c192b48a36cb4656424db411b5a665cdc24221b05b97a1070d5477ced5fea12ef4a99fe85b9f6268c66e6b02444a0c46063049342142f98e64f4c1dfd51ac027d891aba97b56896ea494e46f610759dd315ce9422c42892454d02eacb499da52ea05683c1aa333ce494bc0b7a060c6d9d02272790108e86f49811ea3f8fe5866b55f661ebde7ea0e311d708986d8ebf26f2b852713f89fc5df82226426aab2a9a72a25cfd9a724b50864844398f2218d5ad291fae9a407de734dda4ba24171b25bd017ddf2637c491bcb6c743b2f10214fa21962f69dc90fa16e96e910353e072ffbccb7acaf493107bca9aa01f22044ba348bedcf484befe64ef8cad508401ebff7a4eb4ced241338a2cc4361edea7e06e479f9d82618e5be79604f852d506f687e40f7679f85564b3834deff64d713c24c6415b5c9b887a6787e058536c78fd5da215a9158e570abc773eb1f196ecc78d6cadfccb5934c1ac6928b79971df674a5b6933e8bed08c6eb29e6655e2a0e970e2ea6a15c31b997de5e2fc6d0dc19c16b711fe3bae475491d975f56b58140b96d0008b8202c46ba3a3180f1767a804896017f0558644c9ed97cc467b21d093c8dcf8495c3eb79de74ad1d8dfa91b076bfb82f3806f4f534991aa41cd645cebccb1d98be99e7d990f82163e0df8a30d83335bee0291f15a6f7217cea84a41796af5ab38734b9dc5e3f5ee2ce87fc77e9aada9c82413b14625e01bd556fb06a76c51763a406d9f8b2d496187b9630fc27814746b2e1d18803483bf3e1d9e33dc986c4378982b0c52b3267738c8cf0341e50ec5be68d9ad6e64050af1465b507fb8ef19dac5ad6b813e3539275de92c63a943a3a9196df8797c0b05d6185be6fa928101480e1c4482961dae3cc0d911918b5d16148b0181094640b6d6ddc67cb4efcb02aabaa020bc8387de6038c83a31550126e704bed187884927d7dbc49b15967424e812608597cd1bd2790fde30adcdd9dc0acdcb6f590bd160c25c7bca8551256feb5e85fe7b3b8091708b427a6bbc8d3f662e51e3e9977e6780a616916ce686ec99e63610d0975f232ef51da0d5e9c557e16e78b69ef4f846f801bb78321e3ea2dbf19c45fea75f919a95962b511e282d64d7676fdfe9e80511b793083fc1f69a9ac8de246d3429e29bb2d6a249215ec8d8af4796163ff6aab50fc5c8fc9755dabcb426358605641e1b95048d24bb1031233f3fb3aabec93fcb507941cf67046c2afb9901afe4b94e018749754ab4e66e2fcf784f032e0acb3ac3d9f921fbaa57cde5610f5197d07935cecde023d48789e2a71af189576057ecb00a7a5b19f0a48cbca6e7d5e750a79eb2b75917e39c89260e4c22a40174eac85f374ce38a7e5a4ec68f12a19ce2e0267d2f658ea8cc77e24e3669bcf3ee8cb61786f52316fb81fd4d45171f7e2d2db4755f8ef0ecc05afead014e39f675459e211fff818410228097f07eb654da9531e46d5ba5771f3a6174d55983d2b11e68c52bf2679e6444bfecb6d0cde890218310815415119220f5ead913024f4b1efd4bd2543c2aa0efa296c294ce00f8d89342c402a882c112a15936031e34eb4e43fb3baf68f16b2b11dc3a522065b9c249c15decc791531b4d0713b2404b38b4231d8f8a53bb6e01f40547932bdf7ce78dd7759bd808f140e13d99a6ce5adb5a85f8f56e65505078335a10dd5736e95048ca349545ad428b4643f069322a7b4852d596e20677ba99b623bebb0c31a70460e3c1647449ef0362613f83d283c18570fc9a6e9efa546b65a878b2b2995f0bbf6a458fcfa39fb01edfae7a182d5519c9b5289a959fc5f62930674cb136b86e4ba7e79fbc85fb9b630467d86befde0c444868ef532fb642e804b21071d05b34eee1d01ba5b5aacb171a8f2432920566c8fc83f44071ce588c6d83865b2fef658f62278bf1fc5548236751e7d7df71303f1ba132c42fb63ffbb1ff37d51a1d0a167015780822a41b70 +MD = ae61d634df38ba68aedda7a4effaba658acf82c0d1b7203f643b852701a95820 + +Len = 22688 +Msg = 6969dc58d6367ab563e89af7f95605d34af6ab8d5951430e3cb432372029ae758fa52395ee83d5da4a31c84d542add55a9243d87578afabf9d2cf470f336fa384a5e32b89562bba288b29013a069b02463827cbce94960a89b0fb5ed3b22e65c25fdd268d4bb7235a7d2bcf1e5fdc767007a2fd11676bbeebdc63d5500d7ba09a5e8cb4db27643ba2ff8128e2ccd6a4706732071e7f954bc8cb754514b3cbe665488e510377c7659a68e5c937cc1e0ecffd5154262ba73388f4bc28923393a9cb945e8596bb3533c96fb60a7dec1737d7207d7ec91a2608a4eea4ea490b675d25c889bcf5704228886a7e77359b56922e8732e187c9762db51fdc24b9a9bb831c6b7c71b02572a68fffab89ff5850b05e880e16e2a82c25321eae4254ad04be17e3c34e57495b402885c9dd2ba1aa14bfa96ba95a34cc919451b7ddba73e76090c7daad4b6a4087ea9355cb4b15a731fa61d7f36efdbbc5645f65414b9cb81d2f9e4f190cf6e6e05eaedbeeee12ec8a7757df9f81719e631aae533798960b363ccd7d0c2c7da2ebfd4ec8b28537eea0bee1ff08422ed8ed3fa4fe0b11ee655e50dc01112a7cf8fd3ee9a8b090d331f749a692c81183efb63c09c24658143af7f45067a277637da69c060853a1933b00affc4749801f6760a8133c73db861095afb11d4aa3cf958abd3a443637f68e5f4a7999171e6fc47f0c77e91e0cd26ab9db749e64201fd4ebfaecf8b2b45b9055b1a4e4cb3ce38b63c19e44af7c77cdc7101167a98ce2b07cdda4a263a750d5a66de4d6b06c2920b1700cdb929af4ae6fe62e05653aa6bcafedd7cdc39164e2a3e7dfcb614c9f28da803a1a71f8c780f6b610f431c9ea5de7941cc74d03163be0a7fc5f782eb408518aac9dc8166eda0e1870b099bb1c18c678da4b8a6cd345ef36a0ff4fb30643b8e7dab20f64693e0875a3c7077eba71cf04a6b6e64f2a95121c8417625a146f73305b03b2633511986640b4059543fd63bff885fb1a8aae1bb20c545a845cf012ec940f4ba350f91052dde40e8f572017134655336f81f54e9fb02292d25e5a0a851c4145a54b5922d3b1e39cdd526e7b97269129be9f0f3d5e060ea5c47711ec926a264ad992c62251834f4affc44ce3c3ffc6387840506a457474fdcb55cc1b8cf44a95c0b5a49164c86363773b5ff2226860fa2d046d581e81f2256778cd29ed410ae0eb22891285d7eca0d415fc292ac6fdf95d59ca7921c50297193eb98a2be703a6c977e8082d58377d86e2c5fb45b2098089bedc6ff7a422dd613605ded14cb141ec145604d3cfc044003031db1baff05a22b2378f18b5ef52cfed267a65e8905cb386377b018533aef07cb45b15175ed0c8c240690d50a4b1c5d2b00f62511d51b05c20ed4f3efe18a826e1fdba9eb17eec6dab803e2aff54e37526e05efcd4cb82f486ce15438c1bc7dd3f35849c74ceee22bd5733ab6bc69942ff9fa47243147bedfdbfec496a12afee20950b97254b7e701a707638568167daaebfeb27e4e73bb6ea153ca714a7f1083a8ea8255f7efdd4374e8e786c1fcf8ab8a38ba4369e12ddd0709ee318561b89e1a4e2bd7fd3fccd9853d4e208ec4101a20d1e6dc4b3c1c145548b83e1879001ba5a53c5f2d4ebdaa222f1eba9915cadff3f0beafbc2a91fad337b101cb6eefe292173e5750c5b7a092e6e1bea89830e24bbecb2584539279c9ff60e068e88ddc29cbb8262e4bc3a21f891e9384f4490c726394a76a612a787ec74d44b591e3efb1ea32348f89e8990f405ea1f5d21d43af06a29b37f95ee03bb801967c0ef804749b34e93b262e6bab352850c3dab57049cf7b6ab3c5389748fa033c830ad504b80747adf9cb9d013b8d0408b5b3187c89e7a97da66dbf86edb4dba0932b80d5c655f2e893203e4307737a3194064e4db776b43bd899fb95720f122873190361e6aebe02cfcc1819560d1333287a60cd1ba3220b11f0f5ad1e322f3eed7d668e5f3a32637678336c7283567639b855e2fc977d57181ab4b43a45ba49c7ffaf467b20d67350cb9822a1fecc638f673576a47a4c86b6c040940e723cb1ca46e8708089329b246e4e252ca6fb60f130097059731800b38aa233e2df3cddbefb18f4b79ccf41bc085d5b5ba26dd629bbd8b864aa682cd71fe17bfeb442376bc548ba688234cfde42ceae751baa2efdafaa360d48c474e9280552a91ad626984d7fa9db62e9ab53c4a805c43838ce36b587d29b75b43fb34c17a22d3981120f3bc5ab5765773fe235f3478e22a1209c7478745858c1f6fb341e52d038ca63963622a726b365f1553eb85e1c006d8af69584048a1a72ff8a87224adb3f3a82f6e69f868e733b2b7386fe31b6fb22760ebfb46a7ae250c328ee2c72967857d5f7f4432ed8ce825403b6cda8a33b4a4baa9b0f8e70d9e2aa9c1142b24809acc5600817884bebc1d3ce752dab2de76c7193d09d58b327b01db0976ff23a1abebbfbc9217c31f380129c6c27229a271150910766b18df342822a29b81ab5d4171d8ee06bf3d00d47783442c2f53325c0506be8737f44652142d36e2712ff5e3e54e2f4fdd372629f6d60a0070d400601d9eb1acbac21a7d4c6730fc3c260e1bbc9bfaedd065d190f59e62efc5009f55c53d746761e6cdee375d2b39412228517e3ecb61572d95b20a58f93aba7d5185a26f8137dbf6d35d7b6b703a3eb8c71d90933b3ad01305058b723781cfaee9782ba162ae7756cd236f3eca6f733e5ce89a55a4eab9aa81f42f86a8456329a9b5d77f932bc2ab0dd8b93374598d476c3af1e2a2e19248bf163d02c606135224c71c668d404c5827f5bfe61888fb48779d4dc6bfbfe891fed45a830b345edced1490d2cb8c82e2adf309b3216e3bd5f187f47e55f63b0ad3c6fe63f260a41e5536ab50d85104df02791d471989cd548c739c75f004f817c0569f42161b918b1f95e27d3e4e20a1b7c0710e8b5c3e688ae89c4a386cae4d671bc389e0b5a5c78ecacca467c484df50819b85d165fd768f6f7a6779addc101a8ef1c7dccf3f48353dc052ef649fec4f34f329963789030c70bd5a4e48e0046d18a06884e8ec81a57764252f9ed05d16531e7644317f928484eb9f20be789ed141560853632c0842003e87b2e3d4a6485483f855e42fa98a247ba28b8f0443e9a19913d2fe8c40bd50b5f713c40b5c57b1ba3c65d047bc7fc7f411092b01a818b1e0178dfb7bcf59e140efccdff2f3b703279ede86264fe7f7cb470422ff1fd0faa18feeea7908ba4a85fe486809e0f8c162ac3a6669d8553c87d116f75b3fb4c473e9605c028150f4eb9f011cdec8af64e1f1040170ea49feb02bbc28b46c36d7cdb0acc0b6cdb078f84ea16eefff1d762bf9c5d7da0a38b6bad35e278949d98d15720ea8f4524b3f129983ce9c18f56db712ea6a139c941d2e549794483d1f6cf1aa10854993a3bfe0ec22cc818ab9c409f90c38ac25fe6a711bd2cf8fda6aefd8c54cd635263c83e9c328e93ee8cd019b0885b4024ada5739b5aa59ae965e8e41603e2c356e882383baf09502a7b1bef0cdf16cc45fba4bdeae88c352e57ce0a1e74ee7c8f11907454004509b4c0a5481b5d9e350f910b0d662f88ceb6c185f90e709a97e3251a7a4deeebc574a395af44c9988369b603eb77f6426f68ee38394cbf8e1b3c6e4ad39041a38d526c13a9f2ecafbf3ab4b4e08507621f2c250d50422971108132460683c11468366249c08a8f89f06cd14573f8288fe7eaad2cc85676eb7f9aba369b9035e75e08ce5d7b7578ce1ee656de2d382271cd8acfbe29f26da66f6e4e431a1e67c377b0f877621b702751908ba995adbdb1dcf5d3ebf97dd847e8e735950c941d51bc1628c0fee43e3c9252b7cb33c0c0f7191101dac25f7d79f2ecb953f95c20393422a65fd639acb4e814236f8fd7f5ea8ec7a0b40bff24e2966620a567dd3822e7bdb97d738080375cbe18bb325c22334200faa05dc7972adb3bb3b4e07f2cb4 +MD = 83cc6bc59acd9a8c5ab212c8857c81fecfc89eedaa584165abc0d9020c1f6187 + +Len = 23480 +Msg = 79a8f244af767d0585ef5fb6a82042ecaf4f2632478ba8448d88837ebbaa57930760a982c8b32bc6db1f3ecd45a1b6ac1911dd119db2ba79a80893a34ee9b044bfd762fc6d8d44896dd8c13b20a8d6a7126719a02289fb63e4654a124343fa646bb6249ae62c4fb504c3efe6815e2b4662f9e3c72039f26a0847b0b3e2dfbb5bd1a4f8447ab7d4b26887d0b7afeb3cefd06e426edde927f7de58ce6e72e67e90ba4ae4e272565ce761cd6c96f476910b266e3f7da2c223702c3dab2c3d7fc86ded4ff35c16336ebeb73dcc6c9627b3032aa3e1dcb7ec6d3fbba14fd389d32359345d2a9aae73929e317ef71fde27293da5b23074648e8dca532ac34d9f0a16bc55199385824150ef9939f599149e7b235e46342bf1d10c7bbb800e80c74b2aff192d3503dac3311ab515cfc080b4321c1f05f6eaa5dc71b9bd4c385649bee588484118fdfd21bc854ebb8c7e6a8fd58fae977d9acad844eb1f364ab66c8cd2c0aafc455c34847a992bd234ba195aece6d4a5d121a6ec0e7baae54b8779dd760f0607c306c714f1be1603d05cd63b008859d7fb69814155d0260243b3b8d85bde26099ae5fef8ab5dd5f6664be95a98dd05d40258a5fea4525b343b2171a60893d0abd3e0205930dc315201719ae03c4da045eed8594c8069112439b9ec6e0598cd9575de775e06a5f2c0a6b531f57440f1d1c8d0e453737d0f7a48637059db53e56e88c94930b71ee0e75ffff5c0c91ec12197278f3a04f61edd6d07478f112edfdf1588dff6cbb1c27033372f6ac24fd8dc63c7a22abc3c06f5b28db7372f8f858f220381d9c8c562022b46271ae83bfeab3497654a21b78f6b1edd097abde09d27ba22770138c186464d1225f9c14bfb36137f1fc3bdd080e7b9e0857f4488f04ee2cd0895a20ff7e3a384712fd7e5962407671abc18eda3108c7c726f4cef46ada4ec7dbd8f167d82358452e3b273981e19379c5eb878be8f9e9a1a715b7d67eb07671ea3863edfcb09fb123ed85bcacb50d7eed027d79a0bf823c3aefb9a1ab11326336c0fefe76529cff767d307f1d4b430583bed74ff2da0fdb64db3ae28a7d1110443b2915bf99dea4a862bddd8e04d2821c790b5b59da0123b770b215a744811d94ef88c042e6b3252c56647469824a8939b9a048302004899548c5b76c1810cf9b56849aaad9d91594a0eab02a34099f4e093c83205c6891a0bbdc5443582ebada18b2e151e3beea53daa73d5aba9e18dbd01688a4dfcbc04c527c58e7955973d3ae7a40c274b307fc7c3068755686aa65b6e4e5383a9c9a0a950c41a3402f7f1a706145973d7412f10e0cce04b841a87e261e1554ed69736e0c22bb10f8ff2101170e4c2a8e608fd3f892da83505db7779638958578a100e9105601bb20672e49fab7e106f816d317c4791a6baf494c048fbae2345cd1b6fe59fcd20c46e5eb37a41480b6faf5812f1a060a383582da878b1b87fc1a7a0a3041ad888eed09dc6c9baac7a5178b1e9c31e026738398d78310d1034732188f015feeb1ad7331965b59c1026bce460fe1d49e0ba809f9e779a981c0a0242b99f40d16d9f279fb9d86671ded859fc4e9925a86064039347efdcd945c917131cf7af1dc6e0881d656603c07d56d0c7610203c3eb2c6a1c70261e58f338599a994287695da2a0b30558b4125568c84d8280e022eadb5d430165899e8f2071e119c6f33e9cb0176c82f6a3eeced8e9979a5de44ec339830fe3f445327f4906f082cd1923ead1964dc288f5dc506ddcac8fdf36cee00e8588fc1b799c2d7bc1cdbe9d21a0afccc560ae56d56443ee49954b4fff2aa7220ab635224e65ff7e4a82b37e343d546a4bac2ea8690f0f24d758b4f566eb823dbba27750eb145f1948174bba7a833f73d1392bc5d9641cd72fffb4189498d8264053a8ef7831b41663926c981af9d9affe108bf64eecd3cef9913201b0b910a640d1b1451f45663b44fd005f3c288ae57b383883f02d9ad3dc1715f9e3d6948564257b9b06d7dd51935fee580a96bbdfefb918b4e6b1daac809847465578cb8b5356ed38556f801ff7c11ecba9cdd263039c15d05900fc228e1caf302d261d7fb56cee663595b96f192a78ff4455393a5fe8162170a066fdaeac35019469f22b3470686bced2f007a1a2e43e01b4562caaa502ed541b8205874ec1ffb1c8b2557669429047ad8bb036324ace087493008cdbc37d2cf9b702c20c3b74adcbc5c6235f641dc8aff33280e092f8821c5780af93401921c06cbb06ee8ba6affa9446e45ab65a7b5e905529b6a40497350972b8d561095bfa0bf9fcfb9adee0de859d61631f8e8645cae1d6bc683a6e46139f52a70e94012efb844c3b4e6367fe019241818a0311e90a9d31f9c7e230d7dccf23132f033be5a4249db6907f6de271ee2cbddcff45d4b652e275a7430471ccc9d320ac9e33a66ea1977549781a133b79cc1efecb498d38c89138f2a6139b4b570bd66dad0ef9c1c2e37f5f979518c9fbc6acd8af469cf6c7e54b8e5385ddc13f733e5b78f766055029dcbc240779813cc56f52f2648a5a1786b5659281bf964ab25f5c471476a2141095466797bfcd036f7055decaddca7f1d7e5dab2fca3240714259618db000d341b1e7a76e71141a6cb6c7b9a120b0c952af60e5b885fee957ed3b0f8b9d87586438862eb317bd47654992cc10d873bbcc4e558a4478600d0d6ae89936c3a06a20330a428f3a325302329c5f408f7b1e346623e0fa2cc1733ac14a47b5acb1d01da95d2c2a61da06ea78cfba59cc30b931fcb43003288ae487f8486031e0245304a26634ab141d27c62311248218fa566c1aefc187f421289b19c92ed1e55fbb7d260da13bdb63803d3c4ce7e3fa41bb8cc7bcddad19f007202bb7f7be45ccd02f3e3abd013f14d7f8c96749a5fa6db13a0c03ca9d1e5d49bb37f9041f88d159c3f1d5ce26c798f59ed54a93f0a0e6001ef0acd1808bd2b51644779d1d34d820e048c61dd1fc58a2d865dd0ceb751470df7ba03a7ee9b614d95a190ae0d348eb2f49f5f22b64baa54e8308febf0060c926b5c54dbebf712eac81c7928fec898358fe4b955c8927c8a736b3af93c930d29aa7045269956bcb35c2697e520803b0026fae4d8bf308d18c87c6689059ed54e4584690a6f40bb31f24e71653ae1e39d5a30763e028c389a47c2971de370018abd071509e62bbad10b029a2b76642e87ba23f1f84b2c2b89820c412a4ebcfe398186eda7869e383b06d176aa9b9d78399743cc99f196b260f787f930bfec480533726765d91e9fba9639ab64f2d45d3da22e8a958e3289ab28e433b3af746b58335806c756136dea09a98cdd14cf4a0e3b22a07d89a60de2969f654595ebc4cd01b6303e76132f3401bfaf8589e4cb25f2fe92a47c57ab81b11822492bc900be4f0b984dc1945042eeda97f0caab6d0f49e0f5bccede0f1308fcdf40b9829bb64bc69377b12d8d715188caa14f898c44a0983e28f99f95111eac10bec7aef24fb875b64edd351369ba58ac098105b540a772d07b9512d9f662a45b35eea4a0d4f5a775359e41ae7689b8d0bc27b6849dcf1f512729ee4a5d65840328971a23f083ca54ce8ce99b225027cd1b8c0266a677ec34ae10686290a7a9cd194965f83cf36cd96c21838617ae23e5ba267fc8154267ff82f137bf4aa9b40d8a7e2e99f4c4fd77a0e4a5eba0e44bdf1a9f854544af11164834d2cce5dc0148fecdca95b268fab40f5ed72878a2fe0dbf5fc95adf2e861d6063bff7ecbf3003d880c058105fe31309e88de8e95ac8f60adfb2652f4125896e0655dce9d3bec2ca6fa66d793a5529131a30998d8c2b2c9f97b710bf778dceb3853af847ba1c0a26c2f3527758bf4add8c65b6cfb79325e0206dda2a320d61f368e5b690c2b64e80232d83756b800cab97a3cd4a5d9f567f023d2dda2142f78049dcb45f9e3c046918bb9cfdc355f31fc4614967eebe42ceb5bb886995ccd3fc70865e0e9d1bd0341c33eb9af09f72acab34b7b2fb6e7f51a34f86333fe9abbaa58930185fc41693961d1bc783cb2fc4b48494b6042e709a538f83d16047d36d214bc72756c35bea2edd99fdfd777f1a68d77ceb898cab1b5ef21dbea755df66ac447f96029824ba3ef +MD = 08f73cb073693da1efa1a308a377daf15208e2102bde446fa2d599257d8e46ba + +Len = 24272 +Msg = 0b3c5e8b34d68a5439ec20523f1914397ad7d2594d0881cdb3cf84f6dda447281da838a2023513c4c5ba637ce3c646020c6270c53ca472a528813c62dbe3e154a1fb9b5d24d90f1dd53ad2648da12bed74a91b4923999a190539248003e474d860df90a4e1e905c6321374f385d24d637c53dbcd490e8192149e43399cd0871b22fa1d5f838e7e29a4ee510f128234cdea09b839f72cad791b59a173f0cea385aef44d7650ef01adf27372a17ed966918772bb75751ba834e311461745074f7ece7625d2913516bae649de920ffe6d191b37eb690b02fa2d346f3b0ee4a3136e4828af598d8745b846199dc80e1ad1cb6eff51fe010929cad51b873e15c977bde5b1f2f48e0e170fdb8ab82dc35418114773f31a9e5abf7590bc329120a104d36dbaf68cdaf113286d4536a875d5cc52703adba62b1a44952bfa45ee4c544119a8eac407ba59c269c4f11f206dc474f5affd118bf0743e916f7fc73ce20ab7f55eea634f766eaa3ba7377c7ff44a9964cd649baf358e37d324f0c0652aeaecd05661db4a56575507dfbf54ac508fc206921683fc4290b6c212f838506c1d6a1359f835e2a23d4b333530af8fc9ba7743c5bcd1595ea344c6003d38e5f0cbb9242f5778fea14712296e339510a9f4418330fd8badd3ef6847b867c70cfd1a5f6da025ac859c9e344f556f0f173664a62e9982bbe2e79baaad001feeaddd35e654740ad961db69390fb18d248cba3330acc9f368dfe3cf9261a10db4b0d642d64372b00879a6d1a7d04934dd577b88676688f79b8c0fb5a9c963d821fd316ab5a163bc41b545fe08f9e60d4060c28cd2c29d365bd1b272764e0d283d7d36d40dd60fd98afdff17e3f450bf5890d666f929d259b0961531815869a711162ca9654a3eaded391e45c1284ff32acd013f6404ed08a2c3811853503dfba4b15d104665b8e07151e8af29fdab51c000893f9cb9b7ea3a403c4f739c52ccfe370f32378f441b1e2da67ea3db2b802112b78d28b2f8a87ff58eff69a670c3288e8b36c030ac06fdb69fd9b72a992955e9d352905578e97acbc150bed55e8729a0194569b0b64815d21de9ee52bbf3656f25b55d0cfe5631a81c69f990e6c109530087bb772b896f6a66d5cfbb5987588af4df163e5497ae76e673a241ce19d1918a233dedd2731167c3c6e3ce3d8c36248af843524053f91b6895424fdf368841fd42787a75ac05af7ce4b0f12eab07242d276cb28b321881eaf86022e1c1364ba20bf287dadc532cd956c08df38cd47226941ac5fdde158eb3c384229c61e396c1a7357acaac01c422459b0b55d6a4f6bd68d4f35dfcf72c0d1f36b7d8bf980ca23dc9bd0dc319619ed8c7d11c32809839cb23a47537c7423e34ff495c835d948cf634b66bcba2ea9638ce4910476f40e4e48e400b348cb78f296640f1543816c9fa00cfac69a547528c38daf8be79d604dc9d2fe89e4e754827f4045fda337b9f70b46f974729601afd8beb9e3ea642e2dad8dad41b1663b1552ffd6ebe55a95780d9fdf60d361d36b351e6c870ff6cc607c8a79653eb6912dca193e5a8a6893854f6e38f63d466edd511323ffb8b3cf78bf4fff8f0d56fb2e3d22f8e3f2f038c1193882aef0c23898c5437cb89539bbf8de44bc097dc5dda9349372f2cf70099e23954915ce53c50ffa15d33bf5d6f643521f1b7f2091bd2148e1591170666a9ed6eaf8b5068998b57800c4147b3a22fac325ba5a96392e28d292f7ca6651f025abd01df739c2281bb79acbbc95d1a681a9fef5264f2a85226a3efb8841b11ec52abb2566f89c07c5415a56aec61c157a7f11785cabf46690982bc0c573026b1fdc22ab8e93759c249db5f1659c97d4479af3a0883d155705b51fd41c8ad44988289d2cd8cafd69cc3544387b89d3876bb61bfa13831bbaf47951c1f7e9955e80988105cfdf82052ea06b784b0e3d9369390101991e5626ef2d8806e22fc40eabc484d2fe71a1d2ce57b24d7e9a548cc29c3943735f730f587a191f65bdfede6c150f20cf01eb772dd3bf3460cea6d80a682b3c5cd6e0f8b2c79b77fd2494423402865bcc00bd56bf9cc8a9ac1bb30993255d5890053e67a09e75ad02e422deb6259100700e95f6062b8539aaf1f7961f4c5624d77ad9c084873e2b218d290844e6a5ab458c03c993f87b4107f1e301e1559c2d7d9841b7e0ea5b7ed380255372de3aa8d6f99565eb9bf17c2d8c03d19bc9a5eefcfe14a248606414935d9644c274d6a58ee7b94f7f8eae37a630e889a120e9c5f01cb1141d51de98eb85fa50b632f01de7c6fdeab238f80fec80ff9e93f3fe5ee164a581e26721583689d01bc0a11d7e7c27c1cc463375616aecb794d6ab5a263b76607049f8e2ef1ee9a5ea6437b543b68aa3688df69cd8cbd4bee10bcf639878b28073968f89da0f15fa61237f6e0a115011540c0ad4d279e9642785c8c14223b973e05aa38c9581af2bf480e09e3e2718a9f332d8b3eaef9b45bce72ff99fc6ebb95b28dd719e1115d9390ef3dc5c6254cbdab4f8c08ea75ae235928d532dccd9df487385cf7027da808320219ee15d94f58ee4d3713a3bb8b8063a498468bff4444cbd44fca8506d908757125c697349c56455015c7a073535c320ecf3cd2adb86bc78839f93055fa7aa361e9b614df3aa1f880ac8dab440f9e0f8f037e777f0253c37da1eecc12124502fcee245382311f4f0487cb8ad6c62e424fbb73421c29e206da0f1020e52a53db6abb791dc48aba92052bea06d280f413757f83fd2d3502dac80bc7f674498b75d3d81e3a4d4c5808aa2253e7e045d7ca29d7166e592f9a856f1e7b146a77d51a5ece7972c67fe3fa1cf36df5a71ec2ae954c945f491e9250f6cf94436dbc19103324f48dd72c42b082269ff8d0129a08de656696a50ad28386a77a4b25213fa07b62f652275a5d72054353b7022a48202fabf2db14fc4166462d96f43cad30125e11e68a5f111c88cdd3f0fbe66db43eaea5a1f83efac9415fe94e065769d2ae03b82efd26596739015ede8c24e3c6aa83dbdbb3cc0f515bf8630b48215b0ebc93df3573253b26cfca6a8432639467abd7d509d66640c2fd3a2436833f8dcd83350e63b404be41904f814cb54b897d8bd21c9127b397026f4db3357f5c07f54c12ce20876aeba0c5b92a9ddc85c9f1909b37dd6f5c1bfaf9589872041ecf6f5f51a6d4b6ffc82cb52feedf70b95cac035bae537508d492e3835c53da2def24041c1fe7076c60cbaada537b3a8e4b952c390a5d0360cbb374f88642c8326ffb8398bfc24359b866eae1e3d7ffad9d93525ed162df0c0743f5dc9ea698d555db23ef11cb326ddae6be6d265c8abe5a90bef18ecad2b3902bae5a2ce710bdabae2d499a6b9b51cd316ea6a372a2688a73b91bc6fca4fd6f54e797b96df993795be9cde40a47ad993142b3e2820e533624890403621d94aba5e8becc9f1afec5ca9fa47611ff2847cc82bd6bf29728668a76d3cc63051d4c05f8f5eee73da799e397f5d8e6896addec75ebc72c058f208fcab1aa6723435b5e6164a6ac2835fc8e18e993f3ad1c667864667d96202f6e1acbc524d640abdf9769357c57a451f7b36ca82e9f35e6e7589755159aafb15714c338c2192400e098598df84e79a3903ad9593151e76f6a7456e1179f7cbce463f8310c9697e867497997a3fa6fd2d10ba82524738d60f6b4e9320c0d4df91bf0b3d98bb6610b7a92107804c34e87c20e2133906ced609400976f7c4beb1006a33b57c6e14913245b685ba412dd696a2c8bacfda4d0184b40aac1edc31ea8ad64dad4458019a56a8cc766094de521d14b30b7f183fd2f235c684fe9dcad69161cd67891f9976c560d76c1bdde2e56ff54567df6713e4e243c1a42f7fe62fd4bb1786a31b68c0defc6bd95482b80b1fd30462593d6591d57c807c1a0910309540d08d3ad1dbf333d9fe30a309ea3dad2c548d8511a1743c3e979f56afd59383716ceda8e98fa8449813247ff9d5e7886fda3beb6a540697085b605dfab2c2ffeb611a85b8e03a81a52f0753c927b3322bfa1fe4cdf9c366785071a87014499b1d41b649c67a348b8fc66bb70e4c0b5acf288c19b31f253afd2b45ce968681c56583237da8aa20c2c65dc4222fbf6a32f80a12e2a010c67505205f28d496260f7299f499b61c89b7d779931da3fe5a8b050346e81b8b01b53ef4205fb0af80e9b31aac16a53dd9eb318e7b12118546a394a89a828bfa717bf90b2bcbc15f3ce4b579ac8ccc8a8bcd7320cea7dee0c91 +MD = d9f3869427a8ee975ad34192b53ae37559350ba9bd01299af917503f710e591a + +Len = 25064 +Msg = 2ff9fc3a5e47bc3ccdd7b3a6ecaaed1b5c2a3ff4a60d93402c7c800960751eda336e187dd13b02098b31ed1d148c3966f10eab672be9bf7947df401077a8154112945e814271c0b0fdaffc5636c2c72c54c8d6dee36c380f890ae89d3c14a327b3b4f7cd1ab29d370a9908d9b8153e756da0e7e1365da30adc44a13916806e95fe150aeac2c641a89c36382f044d474924dd06f88c86ab7327d7936b6db51e92db01c05ea075550a9acfb5df803289b161c95dac4dadf6515209e5bbaa7c5c2732be41b31e878166ebaca771968badb40caa1184e19b2cac4423c0b1339bd05beb95b470a3c36cc37915356dad225a5b0dc94d09b018f68ce76c4bd671da2136eece411e96f2bf292b52875c2cbd39ad4c6e37c123ecfcfa222eafb1cc03f7c023b1124461dc21a1e9aac6c67d25f1b2b1e1f736a0dee5fdddaf13cbaddcfc0273864c6a6b493b319b671a3107222b722569b6f090b7599e0039a0aa7a2fd603c4941a191c01b5e429cfaa27327c8ff68e4f9c765c3f02e474127dd89dc22dcb0024a2d7dccb36bf7c2b9f2f66fac445d6dcd04f6a3e85d71f82d4dd7c5daa630d7e0c2f137166cc7ac220d20b657367e3557b06247c8d7fead3ca3f81caf4d2d5ea81a629b9ee120cde5696898543659f05c420f1c0c0e5bd4b898812d0b4203eb029c6866c76991bc569064922dd46f033d42738d4c6108134393f9936925632172b169352a56a8dc080a7b104e812c026d2a3637e48081cd401ed7dc5357b9868af1eb632248c4c17c3032af20dd1f627e71ad987eed678740a192645469757ecdf6758d59a073e125ba11db6f48c7a7e3b1602b75f817c5b7c4bfc7e6cb359e8e178e204b0e44df97009f016444b3473f51e46d544110fd37e0c673750d585a7ddd9ba850e2a601329c40ddba6140c4e3ebb0dab448f1b2238e2cf3a9a08c370fc134a205be15ea9af59dacdc1f1ea563d73bfff08028791d3589c4df151fb8a65adf99f401131032a50c1b33ee9b6d41bd1c49a37723b6877f33639fdba153e422f2ec864c3c069c1322856c4045810ff5a84447ae71eef4b3d05c5674afad4b822536570fff3239c85797ffc4bb852129868c4796a1a6e78bd72bbd7099094f10dcf3c0bcbb278e4d41bf48dc5bee27b12d6e4db02162c25fbe3e1f400c0c515780a16de31e5b2c1a4767e217b53076350376a49b8fb727b80c101673673b14beb6cba903874175a7ff2e45d735d0bf2dbf41f6a93af88a2d375e1d7b38f9ebcef5df2cae847f0d8ecf7f0ebb7c5344f3a73cbe79b1bb6c17c654aed80fdd5900b4584344a47846274ed68734f74cba3f51e3667d827440104fb0351a4a69eeec88c3975655a1d219d3c159c41511715955c279353bc7989f29ed6aa277140fead9ad9364269013df24cbf0f974362cea194681313c09e82ceb589a1124505ea42d72c1ee75d79ddf8862d745934f2f6a130bf8e201dfb1321aae5dd6c0c33d70facf9d65e1ccd29395029728d0b11b41d97f5ac83b9d86571e4b2073dad13ef9d7f0a05af90454a3c1379b13db005309e31d216437e7d9f49cbb8c68e10ed5a73b92554e09f29688938e6da700a1693ab661d74685231ea2ec7bec3661d094019c3136bfb33c0aaa92538952f038e05cd9ea06dfb1f3e6eaa408ea5cdbcaec818039cf107335339234437898182b3ad8b4121aa02ccea52449eee15cbd5261af7e3878f0d872a3d7ffcab5f6e70cfb46db769d388417ebf8549a7bb6950b75f3eca9eec14178ddd46b45bbefeb32841fb68408f926641dcf3aa813eae15aabf7620a7b124cbc441ffd6104f3a34067dbebd6d862a237dd218274347a30c4761264c6b85458b169232c992ba29dbb3903d1cba61576078c87c29b77d4e1ed56ed6b8b211803fcdf867f5a9a6d39176a100eeedc822057ce7a519a389b9319e0d0ecb44fcdccf2f9a27c21dbb413c96d8909ccf6291facf561d5dd012ec2ee86757ede8ef622385a1f998b5a27ac55c5e748c28d8af27b93e6c5f06c1edfefca4388668921923163466df3a038615105b3428c0d1817484c718850c3ec68722eb3afe8a8c09b82c7cf5ff75856e13faf659d75ef611ca7618ab39ac307fb3a164e3be17863ac80da12e602bd139a661586a00ccef660fd95aade2ac3f1e69c338be2cd627b53c02ca996a278fefb88fa9ef0dd063882df3b4a4e7d514ad91ce8f50b1911881fd531fbf8630669930ca10716533fb800a0d4f1ab2ef5733120b9023b60e00a6f248c9271a0dfe3ef55bb57770bc5e55906e5396aac2b0b9d6c264bea116882d0229f059908700e6f18ac1899635340fa560e7a13715c546c43b32a9db71581d173dbbde4e6614990b9e5c2f3f6427b7332933c2c1b241e2c4bd236dcde7177e18cd533dbe72e1602be1adf2d313dd5321126081b05fca95be915f91de406d58ec21e0fe467210423999dd59ba08feee576396666de508689a000d9d754304b47d8189aa503048481e0f13ed5c0c338dbd64fcfa5e0ca56240505619fcba8199b23576c843723279c08b783422e6243a3b5dbbc4ec9b468c99c9618eda6b8f107384d0e0870176dd085434b8726078fcb995fa4c7f5c95ec8bb55784771ed420a8b8bf7a84a5bb7cdeb46e01b540d7dc1f55e21b80153a8dff5a5f813b9df8d139176a1fa225a95f2bf14f95544febe055e59bb8558fdd74de02a20f8eafa42b0feafa56494be98dd554fefeb5555912438d4cab689225ab0ef347b5d81b8037107896a8e1dd230ec625a3c4421acc7ad2951e7d20e6ba39797577fc81aa33fc250b679cd2a4feebe4ac686d6265ea1fe84438b5e452452605d25a6af124668237e995ba8468232b193173837cff5b096ee3c2db1e9f6e7a9c5017899051c0d22c5b478a5ff13ad64cfbec8efab1c8404dbae6783595dc3e2539d7e1c7f8eaf3eea9a595cc06eaf56553fc144341d9cd6b11ca1391fc387a88d3c1f8fce38bed631bd8623171db8e4b81cb9fbf7735b7b23096349a9c2934ad67fe5898d84cc975f90879f7f8b6ace8cd80b6d61d8506095e7363b83d58767c3cb58904a0d58e0b8a5c6387642354237e43e2f0f970c257e5892953a66c47dd9c0f11a703cd440c17fda7477cc990e4de3ea975d59ff4860bff0dd3a00eb0b8cd347ae8c8dcf462e813cda10a516713339696cd77b9a47d19fd98a0f3e6b7f5184b4c31b9aba5f445c55efcd462e299c6762e60a767d82456ad5022679b677cc57c0de99ce25faa763be1c0a4a5075cdf04fb972f519a630c35bfc1c3d6c5351cf147773a292a6cc29ede5440c2e045c66884d8d61ef12281bd6de6d13edb0865cf81455b260f227316dd227060753cc2cb518c6377e649ff6ee1f7577cb0dee74144bac68415b4cfca6791fe27cc2a1c55eb1c9f037fc0cc6fa35e1e374c9deb6d173e45e9450a1fe30309b0c1eff51d2dd9ee526bc66f30e93b81ee18b82fb97b82399efea50daa883af250d3e6870a7ca36c4356c33f750432ca8fc7fb7a99940d139a6a40a3bae293b5a408b7c62e69d2fd3c6d7d16e1e70ea0c8eb1d68d3e0413501d51bb5951996b875056c9cd01ded080358fcdebebb5a6a622c27e0ae86a5059be9402c8454cb648a750df037bf7cf762be487d52a79b92263420c973aec2ec304bb6eecfbbbb21adfea0a9ac7807311e476adde6d45b7fd9a8100d6b821e5387a685e5be77ed58a4482fb17770171e029c69e4c16a21994633ff93db2743a069a0b6f799b0e96f38fcc1efe0ce3326d5654d7c2d907648347bf6430ec8b93d9ee14f0ea78d38d031c25f4b2fbbe4b15e491e8c706ee1f46a28fc054b8b0690ee125b11313761e1574110adab5eb12766f1e5fbd32dea05b1e31ac1d998b40321dbdfe87fd6ec0c7222dcfd9de022f0b505aab39ef519e3d154575f01184bfcfee3e57bd99162b8490ccb234d68bf74132c739b19edf7f69222bbc70b3351e54ed374b287904a4ca5a8e608031f111c480e4a9b8c3e0ba7bcf54ee23f105025d9529575d0fc2c324e9e3492072c9f4e1b54369b3e0fdd5c16771996e4d8cf2467094facfefd90d10c95bdaaa0b8f17356a640837889f67e694e23cc44b2574ac0a0aa3f57baff91a7368a3918eb90f4bfab6e3b82d4dd767d22746da5c76fffabbeae16245c01dae628a225b5ec03371f0ccaaca4171aab1a9c155f503f9fabf20b6419ac0a1c1492130e58c0e4d2a63d715cbc267b368408630d8c8d416fb65b31d33139eddaa773a1d4b880fa86a8e3802b544f27b86b0e2064daa4f56888afd50344112dc2fc5178fe2f3f57a6a4d7e43f5d684328c7f67b2333dc841189b5a2fd3b7df15c79f44093a44322ba04e243a0bdb9f90fff861b517e7e16f222373dc8ffc561318724a29cfed6844b2fcc46575e8a6ff47d +MD = ef1d670ceaacabcd5296230756429cdad36d12d5a04abe8f342065a550c97d8f + +Len = 25856 +Msg = 97691986f3fca44e9c434b25f3e99dae223e326caf81e327525f3a9104b7282959a0f6600fad7efae7709bb8b33cde34b12f830c1770a342efb6abe3250a0ce7dfcd34590cfcbeb840b3e59cbff03f9cd89aa87074c27b53ee2809ab250143ecd0f7baba1272ca4e4f16111a3d8d26b03e8688e0edfdd520f6bd3d322c243500d52770cb48950b84bba0087a5699fd368cfb0da3aaab1873b07e2fbd61fc4beb96643ed3d7f0e9242c59b004319e2bf769021e03d453ac12c472c797ec10eb74bab60c1ce708cdf44c4af200f72318bb7ea1a346937ef9c5d9a2ee07f6e87e65ea25c2ec9f671dbec07ab7b5cfb12c4a72e285b50eb3675697148a54a70d6d84cdba488c2794434833f1e56ce2cfcf6beecdaa986e7a5e8ba8d284c726061f9a0c7c8644a817a55b4bb8656d570569e89a69fb37da5b462eb1e4c5a89c5bfb6e4e74655b4a79adbeb0d6200057db62871dbe60d97bdf87055d50343f30956bca3ca8cb1b3441c13b0b53fd6d0ada221120d4c2c8798d89d95120b8d30b3bd5747d22a1ca8ff74b980438e3fb9789114d4ab4074afbeeb471385c3bad54d5a335baead0b18223b29e428cbcf327709805446519a829887197b80aa41634ec3cd59b063f18364e5e156e576f9de1181dffb5efde2a2ce626117934db54d307081cc780d546d2ffb7c52fa2e441ee080a04465b40172c8d3da824e1c7af58ae6fd2e7607c857fbf25752e74032775c8c5dc9fb026b950071c24611a5271eb69d9bea2ac1b1b651510ef13d5b4979fe1b84f67f67756c1da2d4dd7e663e0b6c1aea9a16e9951ab89e0f985cddfd894da492546351d37a791d6eb2f4de346de3d565b8cade06f7aa3fd5c2c656c337b3be225e676ffa429b181c51157b8e98e663a9c0a72d7bdf9eccfe0b1a443f07c8dea19ecc005e46fc495a4230dcb12ecc2c034c3c4668351ebbf4cbc934c57c157c9c7031c1741a2527a501076040820db51ea60ab7508a928336af43870af6f21e6f7d1911d01eae197917e9a4b1553395687892fec952a2c9400029d9542b174ab73fe27ff6d6efb562f1682897fad6235d4e559b372fb7e4bd78dcaa456add67f0233e6a5cd57271ef17f35a48f55e058961d30b3e746a7beb73ec586348bd2ca6b18d7f869ccee58a061bb868d743b2598d8bcd23c302d5767bd98212474edf5775401de88f6d66a04661d15c131f906a1bf06f9b8e39a7db1b14b5f6d90b166ee906d4074fd69bde534623b72b5a462787a1511a48775975bc3e4275906a5869873210773082fb90b7392dfea27c3a0e6b0f2004843470f2e9a6d602eff51bd3ca62719ce3fafc63eccb6e96fb0df2ab309a3b0ec40974cf2dfedf435a23e74a4d08760cdcb714d45e6d5404a787f67a72f3207d8a6edb66f396dcab618f311969a47c3b7d4fdb4e96bf7cec3a62bbf89c7a6ef539cd1b56c51f4caf988f8fedbab7129d681dc65f200247a21636c9a237c084fa74accb1b3ce8adc451bd6a13bad0c7c70fb95c6284f652caed6c8603bf35f0e1ad965120a5937e8e4f814647d4521a3ce6ab0415200c1ccb028c9799ad7b316f57125403a9a04d61c493aae6b1db78638f5b53d3abb41437080f74e08ce0d4e803993a40b38f88e3633d1e6cbddd60df5c42d22a627ec773607d9454d80749e025a37a444dc1cf979e06076662d86204f00a0575fecca514ae4f7c73097f0eec5fc99a9af2d76fd2f786fc504b3d0a78cd194462db3e3b9f340d93d7ab889260f45421c12d411839e22863b6d1abb8af55e9356d72440987a43080df38d482f2960b9633678f27410072e40680850b1d2d024ef27e6e8d427140ba163be34ef5b7386e8e3c223b6cb4fee3cbe2696046b4ed079e3a2e35742dc6a5f92f3554feca73211e059ab3318214f97371b956c07011d5cd4ff3a0713c2aeb148d3b43726234448f7e792d13ea5d8b99b8f55cff0119501c2a6f4cee2ef5efe4c0658904f1044f4ee11e07a8705110bb22cdf176ca5c0ce753e1993f68b02ad67354a40b095ba7c8e819e15396682f344973a2ac4e5252cb470b23e98bd22286108903191db2f4a9fdfd48a9df3b4da187b6ef240fa4c8448e4c5b610ad47d6022634493a092bc5e9d288c1fbd12e29f77e8455270cbd3cfa415de5a684f81f11383d72f24834553303c4a19b2b7846a948833dc34201be902f7fb2a26abe6b58e5b49302c0d462471a8f14c4271b9bf68273915ac59f70d25835054b8620229dd6a094b2989254ebbef202bfed9e8ea6d45c3935bd1fbc8a6186c6ea01a6aca9b2095c4af9f694e897f351d5a6898980e5471c9c510a097ef57bddc702d8724422f8d5120a8988064e9dea4b7a65f34d5e3b24d6a9e6be77ba1a332ab23fda35ce73e652f4d2990c8bf5b56c90b834d5e641382dee3e453d586dae5b39624d465d857751de5a2fc4f5059a7f110db4e0266040e748970598787c37a1bec9343d78337158f1a7b3f435d482cb24e9da36c6a0254dde7b6650c24db74669fdf5e3c687baaf54438b65f36a5399f2d6109e6d09cda7d971d02cddeb14906385fa00f0883b9e30b621dfd6d0f731a35bbee2c3a4213d6002abf6725b38c8d4e9a95c9d3edc6dad86dc2a860d54db5e014ac8727809569cb45f7428a60935e4b26cbe76b28663f23d230dac2954df4b4e1d191f8d6e3cb512546fa8d57121b967aaf022eb1fc928626051f02dde8493cc9f9c74ec3635d2a1f3ae99f057d27e90cab84af190e7767efabef920d9145e03381b199c4b8a1beba2fba4fda29159b636df96cdc2050518591c700a2fd5d37a515cb6a59383b977ca1c71063ca67260552dad869c6bfdb8e533fcf3c7101bb95029f210f867d4cdd4daa7120c59f2168f693824056185e706cb46e4890c5d489f4875e46180937626fdee2afaf201604c5ddeb0e72ec52b24abf5e45d13c2b0a481e829b5141ff92a4df055eeb8c6c7f4cf4831291be60fa79cb2fc2b6b7278c99ef3e8de6ca0de4792529bd0f46ad2ef881eafb3701018f7662533db5d942875653d28c3d03daee493bf0488ef140aa65007336d756ad07cd1f591553151480fa06ff14c871ef06b19dd99ffeeedf57feeabc33f711dbe9ea5cb1e812fd0610115304b61db6c2c43ec54611b3c1d1de32cb36a11ae506ac6a94ee3489f3afab28d293fea124fead4d4cd64c520cb0a3bd0c72dcb722c5d5aa627e790c8b69c8acf02d4cf75eeb38699f0abe6e12042eda38e165506d91ec464fd3243f36dcef1a56213f84c720ec102643d64c8434f636db12c97b27e356aab79cd476886184fd5f1024edf0284edd8d223291d5cb903f6d77779bd442bb64343bf866f2a020c2858acb775c79c72e3e1631b2895063705a900e47152870ef30210e650811590663f161c58e9deb8eb3a07243014c06664cfcebe14d1d1dc845ec95152b2d844574d4a66ce8fd228b884162b7f016ef7d9f0e9f1efe89287bf01f1aebee6d48ec22b4f7b20e10128116899175b8599542db45a634ac05077699090e5dc448fd771812d459608f221c08e97d20dc8c8e428c528fe6d8096144db6afddf4f593882af6ecab772c2d7c8b9d1843dcf1830f91c85ba89f51e9c6321954804e206807b63295940d743b9f3b3e25521228533d3268fc4b295bd3f5df618ab532ee94beddde30ea9e09a3f49818c4e7f697bed6d14b12ce53c5db091d375664e787a11366a2c3947313ede169d400eacf634e423719a51965b88a6ab443c275b61217701b25587ad4b9a2d07819de43e6b78bea2c7bbe14a75b66806c2cd5d1e7b77c3cc210f684082349288b9068db83b9fc34771863a761d7f9b40d9a975ec2a05adf240aa69a597a6a516be0a598ed912989e29a9fbada53cb6c5e3711058ef238c109bc6fa40de68db3e0b29d636e689a5233a677355bf8621128a84aaf95d89f4a39cd598a6d8e3bb6b1ae59254c66d8f533e7f5002ced480c33984a421d7816e27be66c34c19bfbc2a87be0c4d0b26adcaa022003955b05c347ad1aa86ffa25f198afb18a5134563f8bc23a2a4275d86d60a20027de6a1fa02c8fc1c7d38754df59cf2f756482d395232a703dead6ab121c6d9e524e41200aa9e7478990472c1483efeedb44adfa2c385c89e70ffe6a32a80b016d2e099069885db5d4f06134f8e1b6f7a637dc536c92ff8d0efb149d34ca253161c6e9f5248f98129239fdf4f33acd51bc863767bef8bc859cf441cc824b6337145e0ad9a5874166aab445f56e55db040779e7bd88333b787843ad8083f26c1a703e94c35337ffba04a95fbecffb89196d5714dd330c236e8a307f409f89e9e25caeae3c96697b15886073d880f47f97d86ae55028481d6fba02e0953ed68198bff580cbd6e35d7f1e20aac9e70864862ff8839dceb2d084f003f706c8a3dd43835c33f87b6e4c00ae332b1b6effe1ef5a4a164c8c11e5b41479ed1ba5b6a4eb8f2bef4bedd2f0a120df1f557ca09dd940a8c5e6cc2c03080eade95c3ed77f98cbaadb4d95d7f2695c6dae0078b4414ccb59b8f2f5ccd386c6e71452f9d0 +MD = e4969dc07650252ffe1d6cf6c84d16c0233ee3adb98a7577266b4448ac57f4a0 + +Len = 26648 +Msg = 2cf74ed39d611a8e49076d0cab863bfe052e6845fe118daa905afad021e1f766f0fc50a1b39710ea7f878cd4e71ba35068f44524051732992e410474e67b702825edc94a7bf7c545f77e844f4784ce9c20fc9dd1e1dcdbbb73736c4173fd6f979375c1b53daac3087a955e6713ea4448f6ed7834da87107826993a1e0f907d1b013a41ca41d89299d074210392748bbeaf70de353a415a38115a74f2045c211c39e45071cea7b862c1c2d50a0d4b2d64162cd8bc47313f63fa5f24a79888e302011cf7922e42bfc915278266cc96b2a4f2ca6db14b804961aa505124143c4b36228a3d15a7cf2f38934d31fe177ea0e50af1a6fc8c55009be9d40451c0a2e21e64d52ae282778e1604d9eaba362b818e274a898553d9eb777e934416e3df2f238ea5c6e2076166cb3076b38270c4dc09117c2135e733925e3336195bc61ebaad6aa41afb7db63ebfdfca963e0f723abd903073f2928c7db9ce658b08b2850c25be782d162e9d9f5ad97d9ad6595c22126c0e89a59a0c35ee18c7a305ed3cacf153c9071c603f1004e538c73297ab1c706cbd6a3748da4167d905683abf6c227bf140b1f35cc31925cda3263b1086b03f5ae61e8ee41f298ad9c6e390723df72a5f8432856a5242255765bed70e1667e7fc30ae94b60276c1dfb31aed4dd6b265673e92b8d114146c4c2698efd782c8d01a44212f05acaf73b574173b9760db96cf16da76db3016627390ba6cb4f35c637ec97f491b455c0721b0e2609902fb2460b311a6cecfd16f96492e34ed91a906ef68d0c93ef405e7ec0f81469be59977e2be3f30f318cbfc7bf9fc31ca83392234c91d97b7e1337ade3bfed3e4303df71dde6cfb92348e6feb492a4993f2942016936d9bce356d28bed960f1be0c6f0cd9bca1f1f34aa232aee0c2668f0540665d6fc9bdca183c595694b0876fa1b81edd00e6f95d838dab8c68cb6f07e5c75ed10438e5f5b127756c11f57c40169f95f25141fb1a07d9444d864e4c43b9b16f39fbc2fb9529b6e4c9fb37ba7994add9e057bce070fd0d64b8e452e58baa84005ffb6fe7f3a7710f35f87f28624268526fbb5e8ea88db272972adf2227e0ca7b09ad48915754e15c77b0d4ae43495a6866252fee09e14fd8b000fdeb5e820a4700b854e108588d3459cd3e3463d00b848f3c38e8dd1e6cfdcb0cb5287ab9cdcc0cc69cc050dafd00a1f4c5a20b00020cb0a980656a6f9249b2f90ec1c1ac9a72f47c26147502ba2618cf72e08301c76a92140f4bfafa47242c6d119e7c84f9a18284fcc7c0f94b1086064cd713fae204fd23ee84d3e716f60010c5a7f26872c17c8626bf79e73824b3415b6d0313dc44b98124f63d5f8427f78c32c56d818e3aab29aae6e8f40acc6627a88b9a763b918dd4b98b828a1b1fd98660de33f6d474d71692225546486f69603a1a21488a5242c5b629e98f62476ea958db8df0cdd8c8f5e65d07087a7482951a00e0b44ef1a0fb22bab996e1057d9a21a5c397ffcc456dac7e476029457a6e4e271fdf11d56f1f05253bc921c2d004c3221d12f4b91826ee6d5d76dc491892e07526f45a6677d86852b74ea9e72d8d473ce38a340807c9b31291731be826aad7d43c19b20c80cf5229744d01da5dddb4da5c26451fdbfe04552a7f6e8a6a5d3c2bab76a02f51abcb92bcefb205289d12e4d10fb1685b6ce81e72c15e97ae541661b935ac37b315db75d55b43cf557569418a6c004951bc6755af627277b8366d60af7b5e8c6eb58bba08ba3c9fae0cc2dbcf66b82c839589e22a89339350ac4a0fd5733f964a32e2499d3426dff90b2499e8256378bba057ad2b5f2751405eb4567242d6be0f35e80adcf088f6ff1998631cd08895bf85d89efa0cd81a4ff3b31dcf13ab6a8465a6e60d17ea4c88df2521b590b0eb57eb149edeb7ce5744144f4c350c4703726b23c377d0d4495c05d3bbf98c62e24d7a149321898f6ee86891ccea5531f2a1ee688b6344cf554232aa1a31ed26e268dbdf6709a9a5c9039880833617f19ed9977b24199b62d8030eb324a4da84536fb67d00df3f98ce5d4b245a637a106ee20e6678e1fc163a6742f5c29c7c059d2bb2f748ea75eee7bd2a8639b8a515cc83fa316d038f72e3367678dd5ffa3028647854257471317becdcad097cc1881f8603e2edc67efe3b3851455b367d8e5ce1b09c81c35be8f1b30aa1b0f8f5f2ceb1d283df74ee42ab357c6326692da5a26c01d843205c9cb3d85c6b18746ada43cd0f1b2a5309c799f49fda2440310060cb130f53d39cd428237912273747c8e5a162b3b8acf7146e3e61b33f03b224ffc78f4999244218b85e0a9ec78bb5441cf7715270c6e0b193db6af55df9d79be8281d8efc5b76f0cb4fb618dfb6dcd75095e7003aebeb276e9363a8686bc9ec82b664e767bf62e5c9c026875701e308e9446ac5fe6140fd692ef4d547a1af9f34390d5bbf992b7e1b7702f317b4f3604fcca2aaa47108bbeb73c483e2e3b23c6878bff3ed31fc44273cf16506173366ebf539b615636bea5b2b7cba2179fa4c853c23b6d9cffbbe56d99be30e72cca22387d4f2377f9011231ec382ecaaae57f34de1ac6bbb50741014a978160ce59c60491e64f30da0b8aa1442e42bc0f7e31973a0dd8c3c24eebeb7c329072ea7dd0b04bc163254c26758d5a1e7c601fc7a61760852229c9fb5c6889000c7203aec8a805910da9d1fa795288794a5b6e6a3321dc2121621e8509250b9043f2ac55147859b58d430deffc9d79cf1b126dce7f43176255114284788d6e53d57947095a8db2af8095529f85ca88909d09b07cc107bcb94babd862312e4bdb4f8a5653f1749aff860542518b764f6e1eb5b8edcecc06a6638632b6a9740e97008a6c9d7fb99d25ec074fcea40d38a83ebaf9a9ff1cbfba3b54f3ea77fb3107970dfc7e5bc913a3413fed6f360bceef6b6df539c8763255318cae85f3105dad8199884f2c2fa9082403adabd7fe8ca423633e05b174f907f491a511c17fef194ea192b85749b7b4e2f7031cf0620c57051f36a640758e52f2f87a0659866fab5caa9e2273c3ea4a2c8e802b15b2a8786f1661840c146cc69b45bfec31c04a044a392d15f81a9b285f3e976ece8ceb98ffdd51376abe1ec37bfdc92bd0ba188485c1a22b5aca54e0098bdb50714d603905d88828e2ff0eea0395485dbce055dc9dd8afab123fa20199faae68a46080c93f9c78e10b43d79ad0809fea5cbf8c5d00e2a84dc4f70cfdaf0f932fde82e7d9fb9da5f85a28e3664154426a46b426863d741e5bd98cf044b73f2c0e9610efdbd85081c7560accdcf484c245f16aaf08d201948dd67de667311dcb9d6197135f4459bee66585fe5f6896b215e35fa0253d1f8d3c222669e5ab001444a781ecc4ce1d9fce2f16e26dfc1e7452a2ef849bfd227aef6332f530839a78acfe6df6bcd410b6f7093a33a94d609b74a6b6d6ad80bee020100012e869517b2eccb7aba804d786e99a6c4c61db219a046522010a66494f769f3a4d7dbaa99e52a8fb8606cee6a22e3929a75803b5f27a74ddbe132c663b4b872dff50f62744b0f9a6106990a27b2d8c0edecc75b2275f4c364858317a16275e77c302ba4f20b25543d53108af847009685d6faf9acb1b51c84a5a141972829b941323557594ef42613f0d8572509e27d29d91ffd430473bf03e9952a8d2f5b50f7a03865f23b0376ad84f957f61f06dea39d404e3096b416a9f866bcca9e9314662539b505fbdaadd1b87c74b3b2f41fb9cb64d6bb8e03883e7b1cdd989e5a6d5567422fdab5013448346895a3e935aa340b947c2b15e57d8919c0773d5736c38d0e5abbb8920171da9fc5a20fed50e5db04d728ca52e45d537b597102f0b27ed7c38a41e9ba60ce4ea29c823fe5cd3a785f35c2de6e87916448efb32f925306f92ed9a9b354a9b26ee4f41f7bfa3510d1c3b633b090567f84298b250c64a3c3bbf64fdb5f886185000ed5600b540eceb0d9636188e1da907bc633afe18f291ee7c3f4c0348012aecdc7472d361ae3dedb494335ae899a2c10c6f239f53a6d7d433fd13e7c6143979db8536e467539a71aba5e9769af1fbc0dd2cdab918ef8499910ed3e7d567da73888000b818c9a9137d5bd70027befa63891ceedfdb351ebafde50a98184474665e057ed30888d04f84167a6c116945459acfce781d000c94d520365ce1629dcee685efa9a909b6827a66423eea8962c3aca5f82650d8e4d3d130d5cac32abd199c71f1b09cd4a258aaebdcdd1587b98a29400a4f09382de46ca76746501568e2fa6a239c36625a3eaff798eb24fcdff58b1e6366b8a64e32f1f479740aab17977aced3a1184b14b0e41a04dd8b513c925ca19211e1abdc6c1b987ac845545fb3b820a083b4f7883c01d3bf28cb1d65dd187a24b516913eec4413e9b7a2c987d41cf018989ee01b4c63a5164166b9d25248f889e4ca2f1c3005e744c6a543465523cd8a7438ad447e942ea8dbe0cf088e68bd30156ebdcad3cb932a69bf8a11c36719948b04a7aa2f1da0e54ccbc57eede228c5bb96c5e1442fa7f93573e650bb5154c5619577a2fa6acc6a187a25bbfd5fdba96bb4ffe60d8c864fbe44e0a9997d0f7b8c6d85c55d060195c38e7836493c46599a5b945f9c7cbe8c48b51182da34ca456fff6a97b369e106e27b25843e01e954cbfd4b948d6ac13 +MD = 70f11edf0cb3977c317cc4ccaa9da562c59e452e2cdfc7375c1530c70c37655a + +Len = 27440 +Msg = bc8905d2d9eee4553473d3495a3ff68fb3ea0d3e12cda3fd8b7d88b1859282590fad403578b98f2e1970d1727621aa5f86b1fca24ee116a0b5ce281593befafa0b19dead1bb6e44c71584c61807941c5d446c4bea2eae66ba40f3a6223a28a9756d7c980ea6e4976e2342e5fa1cc238a45af4bda37727a270048a6e15fc798f698efe7f60e682776140b5eb201a4b77682f67b3e35003c9c737f54da6db48ee07a672259af2ce712b1e5c4a2c788675033233a31c31d9391a3be2c9475f1d21da34961eff443ef135ecb48791c019be2003c72fc094fe7cf380c1559a007ce75bd9d8c020634a940c5c3d27d2796b9f28f4b0ae83021a11fdb72fa6f157de8b06d698ad80d877b638ed84af811cf2a498b57ea3b6018274734f6c01ffddb8a955db745b930c5cf42610f9830013456af9a69fa3dc0bee20feaa350b180aa1bee358ea4ef97750ca7e472a46e204ea5eb64882238799a3a41a67e926dc57103819cf78fc16b1f9a58c20856f995a480c792bc4a72b23498a30f916e9bf5b8a9173bf8ee76d44be11da1d9971b89be4d09cc0d5a34941562ffcee3cd8237087777ba9ca957f98249c02aee4d1a2425757ab9843ac647c4021b8a7c956bb4e7d46bc0e8a9ac034b3a07044e623f8d6061e20228d270f2c9debfec65b09e94e028b9f5e6d4bd192f1cbcd701bcd2edf778094f020a7abead60b59ba50463fe78dc2a039d13d164b557a54d10451b6b7321b64718cb2bd2f7eec440447b021a3956868f154f310c65538b0c82e361305bc6b39274fbcd572ff2b3834bfcc211aaff9544576e2638c77835bc5f80ee6437cec6d91e84a674ded34b0bc16eed0b533f1ec76a5af610642f6d06b003082d90a1b8c41c4cff528bf95481aebbc92fbd7febc356f9e9bdc3def9927c54f8b6eca750fa783d1f18becc968c1aca9fa66f25c2de243549676cefa207cb5b0625d64858243a3e50efffb4d8d50e83b698f19b6cc0dbf45c35e8c8300da50079a3d3ec96e96836d8ffd719e40491ce582ccc47b11283206c50bed36b4e132b9b576dfbd4f20c0f006fcd6380c0ac93cb8a8793587c25a0bfe076761b6f1cc4b26a2bddd8e62db010686afa75b166ba58dbaae62ba5c75c9d0c991b071bc9b3070395fa6a6ed401501134468a80c72b4747bea7f036743c50fcae29f8f821e0e24b34ba543208ea0793b5b089d5d7cfe0f54a4070d631281fd93d08b6ae2c338a6a8f865dd9d1537f15759e38579f8c6b0ed618732e080851cbce1f09e6f29549872fc44c0c3724fec0fb7961af264b2fb9ea97c1e600c42ff9ead8b9487cec65ca9adeea724345cdbbcfaaca8574f5751f0f2521a52144018c189a8d7bd122275c5a3affb4fc9e342f79973c8092708567cc2a5c1374710fabe1ce4e28f91dd765f74253796b187a4481aa7e4887a6a7baaa0e3ad90031a07fccdac4f6fdc7bd0cf75cad6a9699e921704a5a865b7d23403039839fce6dfd306127b78ee406217ae4f2d62e870ac7efcede96e217df4020e614ff0ce40e6fe5281def97b6c44ad7456b976e46545dd521d0fb03c2b34783540576c94cfa3cc6aa2433ba7be8814aa32fb6d2d95df3fcf387519264e180900375af7e0e1bacfc6ea54d9f3c5a0efb85a6fb014a0fd18ccb6b6036065033707acd73d2305709affc0603ed01023913733830a4a1513eac32e4ef98aeeaa84a41738a6dbc989906ddb11e4cd0c84abaf54d1b62e40a8484af5ac85f67962747e1d1bcf8b9c5a62a980c6666b3948817944d86e41d24e93dca35b134363cf78fe14dd11b30c67643b581a2e0b14e3c53d7a037d25386b6ff0bdd73bf25c56149c951907d28835178bd779c65d2deae9547aef6d38f1832f1fbbbd6a73b17ad9e2244c2c7a9e381f137561a9b1f2c26066adf8d8fd8c2a73c2135a195801b23b5728e2fa0bcd14dd7ab85e52a9f20eccecb9cc2af366c5b0705b49e30fdb90ab744979fb16732fc52a16ec5bb5ba34714ef4b5fdbb1fe977b30a19321b9daaccb1dc6daa2b4efd789a27881f6599b810060562aba5260a3c02962490fbc644f1a8785a71aabf026a5350be382a3f2e0bca523ecf5207bc7fd786188a30f413ccb093cd0c1531d31cde38fb108418ead6d461c6c3323354b5ba6041785b957bb072c511b40b45e3f2a336cb42f39592f3ecba7741d647776013ab5c05cc29013f6762d513fd69c99e4ad0bb4a09539b055bd2eca5bea2a9217bcdb49d033d28ebf71383a65c2bd8822d9d279025d1876daa4183794be34e5c7b5dd7b8b1307728ba5da9d5b7fab520c402acafe97ddcaf606cd8370e67fb837ac251e326a160881997c43c9154c3fcb697c703c4d70f4d06db576996cf1528f291afa7041e798cad584f5558d8a9987dc2e346386b93c926038d8b45774fdf8b424d6ea9f626a8de15c79aaee4ca66722aadc1b4b9fea6168be706cb0efff9ad6ab7c4b8c6fc5f3466a976e4079b094c256300ea30d45680caf07667e49a19c1617b23910f6f3248b18194a8bfbfd36449cfae296e896ccd473654dc96c2b26fdd1415c34df3a4738cdc5e5d8b9d57431e3003f2c1925b8487252c79a3fe562123ff15eff12e384d5f065e82e9b827610920bce6e883a52f114967cf8aa1676ddca89e47a773504ebebbffa96894b656913e336631d1dc256c2f816eb95088ae6dad399abf77aef01259cc4176b7769c5cd502013c11531ffe2423a7be801c7b6d895229c78f86da006c3edb9294fa9aa281a34875a6cc775de3a92b18b4a54d42a982a55e3f9a44ff6fe1e84ac1b4ea38c0819c6d168ab3f1ca9c694672b5ac83aa457dc21c3bf965d13ff81da237f3561e478d80f5206e506567e2c62eb011b6f81513b199ee4fda3cb37b79cae65ea0f74f8c6fb72fff0020b618265d4705430f6c17ab2d43c0d30ee6f2fdb052749fe8142977c0fbfe77a8e179d592cd0fbe7cc4f9fd6acee4d6d444eef7d71efda97d2fd537c726d52d5a84986243c4898fbcba2b46c6d2246c0947d016b38e2264031d203e2e432ba7b219f43b04c01b4d4bb63c05b60027e92a8a36c8ea22ab4626469ae96ab36a5d4c1c0dee3a423d6da6439cc8dcdb37f4c466939cdf9ef0c6634695c7f0fa09e4850555ea78bd587758ecddfe9fc60d15437776f0f8358b7b2697b15875a982a3f9505cce34b3f4e0d00c70157342ffa144374163e8a8e3cb0cb46e295d248d32159792f7f2a8ab30a83ce3abfbe4884f23109374154b923c72173ca92c1d6205664588f6271de3ed4df8a9309e2d4f758cbddd90029fff55e35a9d6646d6a99467e4bf576676278d3dca4131ee8fbd9add7990463538b39dfcd910df41f2dc7596ffa67a2563fe86f41c4c3e418e4b4591ee4c052198377b1b2d2772a1e4631f8fe0cf0ce849c1711d891a944bab80fc4686716b5c210383cac151ceeb4de6089f52a95e23aa28b1f67b4cf26159e73567dc90d74975902e883020529271dda761afb60c7c079ce03b7d43d7372bf677724b3ae77e087601dfe4039c1c02a2925362858635e486823909afa111943738f27cd00a6e5c1d743e678c0a0c72ed4001058859f5c37dfe9baae0eea52511f064cbe0beaed30f1c20351a3ac8450646d7234f0640170bdbcfcb781e56511f4445c2fd72941fb35021d74e9cf3eb960d62263a098971889031f5e5be999ac79b11ec76d4d2a4c2b6cfc889af03f9050a2e98e9d24645acc28ec4aa5e0384a37b55c2fd43cee485c666736bff7cdfebd398f5df0f1b15c0d92282367b18812b4b9dc0e14e0d5194f5928265ecb312b2e03dc77a0e6c546d4a99e93a744d22d7a23670d361f29e78cae05ff8256b33e2b689885b5eaea41aad515406f815dc3115dc5d440e330d99ccbc76a307f9a603cd08a2e38e76675157e54d2c65073fbffcdbe0a3d133418061a360e722e30b8eaa37b1b30c482099f0c24f2b5995afdcedd1a5732977bcb520119944f4bbb6fbc4933f4a5698625d0e74d4842445bf205f4a06529574d1b09ea39a3d0bf84ac3b2a7a60a0bebaf32f77977b7839be022d7919d9293af430b23c5fe4fb70d398edae180727aa65984425ca345c60cb54cdd64e5e3b2ab731d55f51feda47f05b5c3ed4924518d13f9757ad1af8a1ca116d72049a660fdd47fbbbd89a752c221c104077a9ffed440eb17609d653e5026096b50635b2cfaf99abb8bb60d208b203901ec9f35f12072d19eba60f7512bc6ace071bd8275375506dbec4f7fbc1e839643e92196c6f62c5571d4c6e67124056a0d00a2bce837793c935b908f8410ce6140a9ac22eec9cfef473c39a30cbd64d91789cd5ae47fc8b4885633acf6e663128e8a997ae72ffff7757d23cd827c6772b67997fcf884e5f71168a368a323e4329428640f3e7d1f1683043fc680d57fbf506c9d03a2cb338cc50f6a43174db449f7ffa6405355bfb5065dc81e764d20277bbf371f61d743ee29c6e2aca1c865b1007cdabed42e546b56066745d167fb33aefe1090b41d8983a60bb735f1187b00642c7bfb2f8b7fa2288a87cd20aa637c50b59418282296f5d05a525f73d266c0898af455c3d183e1c456c424f288fb5a07524c162c7adead1f4f4e99b87abb79f714fe8f4fb523a2dff786edb58825654970a30b3f7ae322094706652d75db851356d4e8119ab17dc1e95a77f82c64268d8d2367efc726ed14ce14524158598a94cd21f0b7f6cfdb10a8b95428ea4a0649f467ccabd42c76d860e2d19296b7e2c1e46049b15dc13352c22e12c646498d1562caa9f2265657ba9c0c73afc5793641391a437c34582efea223345ed4e5436644d680513256f83 +MD = 95c2851523aff68fa1e7fd197d0bc9dd0b09ecb9d8872a82bc9d7dba909e397e + +Len = 28232 +Msg = 15d403a2f26bf3edfccb98f34a00d9d019a6f497bd0a1496de8c25dce048e7f9a3f541056d0cd9e4242de1c7c1c034f601d8a1ce5d5c86053d68a13669f12499c0a807112c21a26dd5357be795a55df1adffaa32b6c6f1cbdacdc3de43e4c351d4b6fdcf17f2791077a90f5bb0f87c4983e6b6cbae8f7d6e1b8333de5869eda947e8ca4617c7845672524429f800bb84ed546ea22e0151786a51983e8ec7ca2a8104177f12e7ebc62ff8c35b5707402c511079be1f6296712e009b04cf48815bebd28b80f19bd7e9146334f9b45333c819e3812767fb73dfce58e33a02323bc5eb1ccf539d2b70458a5a3d09f62dbde1ac952be6f014114cb42119e70fce1feeeaa88a00fddfdd64faa7899507dd06fe72ee2102a0f5983f4723e414dd645660513f658df8fe47ceca10bea4ceab35a7d3b60b8361e52f41ef26edc8563c07a386a9080478d2d509645e853f33df726537b490721a2efed914f1db0b619d5b3df3ae1a6c64a1b09f2e59856d1ec0e7be06b159d6b3162e8f1e4d57e5e6d17ab8fe1644cea3b4ff1892c867367797b93ca8750eb713e6e7eb7602095fce1e8b9c11a82d311f53ebfaf674d2a226ac136786c8561d24e5507682d89880ffcdb66f932d7d9dbfc69ccfc4266fba14471bc60672d911cd5d92b7ab97ad51622525bbec6ede1b6b54391e63a4e68527b0f9e1913a409af694d4365906efd8df70fd078330f6b10b46ea703bb6de0b482ed64090e933c187d33f7cf5ee071f5ff469dcc23e6d6a88e4d94cb426ff55600bda6c6947598d6962fb10e5179c2ec8fb8fc1105fec4bc8762b3a36bbf26a558d2cec861c5b0682892f7a9349570b04cb973ed55a1b5eb4440bc2293c5f5311fdf5484d30e034bb900443654ce0c0f9acaadb7af8a1aa34969f6df572ed167aa35c09284b9120fdbea1f2c5e7de5591e8f0216501273731b30fc2022545bd7ac68ab67e3416d12e5d2e0f1ae4f9d0b2c69097ff3d540e91e4844ab91c0f4ff8afa6d7b6b4164f37b3d523cc09da3b468db2c6b073d1363e71268b8021f2d5dba7d9f43a933aa30109bcb5431f299d34868034e16d45b71ea21c0fc0fa96560df44b96719929d473a60b4de6ed8dff64f91f6bf8f1599a1bbe8f5ee270a4da75de2344c38d8bea74d4eb731f3daf68be2dbaf35fc8b5e61c0fa6fe4c4bc46afbaf8a8798390aeeeed984b056d537e02a6c77527cba00a308db8a7968539d0c87ada7e658634ce7c8fefd8bf17ecc7090fc7e12b98ee2d9c96b62579d50d8ca0122a3e96bd4f9ddea8b7e8d5900161ed826f8ba7d0e05914607571e52091cac5154a5183a54bad83cc8313cf623bff4ea320dd32f000ed367f79158f14712b9608cd6fc2bab37e1a5fc3c2330af6cfaae68e4e4392da8a51482378ce1d262f914115d1ca7a017ff1071c7c7706bc7370d10a675025d791135f171438a72b374562d630017fc023b626dfbb21c2078b3ed717a0ff257291eb28c690454efad330f261031e187a29c8439ff6b9e96277638d4893971e561d4739b4457a710f93d25458b366f099c2a5e1dfc7a5c957b89d481fb7be7cdc93c61662dc4eb9e3f9a82d2fd97274a9bedd8601a68c0e51cf3abc0f75dbcd8085d62354ad4886226530c158ddd731145eedb4c80bb304db3bca3d9a56858cec7405f4fc30ee621576fad55648fba2842344d2757fe1697e8eda6132e232477adeb41fdc1fb6da67af64cdca93563553bc7183ac6b6d989628c9bb8ba16869b6368ee876c2186b836f1d0f08558d861d8b022cdf66de1eccaa4690e70cae70190bf5035eb0a971e336723da207f8014c0f655280faa9687c73afa5e79c6b072ddf64e4e673e0aa11a602ce2a132c3359ca1979238f66024025835effd9247b6f117cf1c0743450993e4d34f31f9098e13bad25599d8a7892205020b23b716957629bde5f4a3b21e45fc006bf75dbae5ce47edb75bd8d37fd04a49f813bc83d71135fff255e6b7a7d9af9b7c1ce53e037453d001a67e4cceb42ef2fff629f8436c427d8b5392be6ef6068ccbc71afeb0aee3637aa1537a3e75b9e668f487dca22f581ff816312e394507bba0218260b324018e6c75dec697bcf30b7b345d97bc027fcd80c54a6fd16ebc114352a7cdd67db4391d49a796a030e54a80df3391598bc06f6c8866e9fe182d74fb8111aedf62054cd6463753227a968cbe1c9231417522ed04890c0487eb61cd11d64669977afaafdf941566e6410eb77e1400e13b66ae2f90edc42836916005cd7ad068c66e9e4a805ac935b12e56b408ee070911066b1d58df17bdd1af32027795371134e5f60501c1dc2a4ee9756ca4d32f0f89ff61a0a4858b2b21f0e0ae574e01cea8880cc9a9f0d5ac831973c69aebff5c6cf6989ebb07aadaeef970f0b5ceb806ecffe77cc20f3c221a6659a9315dff5881961900e68efc320075edafd83de320c6f18f0892489af6d97a2effb252b76b9284ebaf6d42089c1e0a5cd509c20b86ff060d5362c1768f89fafaaf65f1b0fe656b1692984a567e1260c7499085b79f5fe7684779a25855f291c5a192637177c4f1a390aece6e41a22035f3b5af6fd3ad3ca8cb2114c8b0dbe598bd81cf824075be9993f9f8d94e97f2afbbc068bc8ab3acd6c6a03f4f080d9e7aeb7a5e6cbf407b0082bfee1e0cb87d3c89f8d7242c37e0f8223f4a74c551657413c438b65eefd0e04449d8c5e2cf6ae445a6253121028019c6465dc04f6de28d1da884e884486442c3dfdf563aa260afd712796bd2dc333e9afda2ba0f29bccdf16e6b8b9815e02de6c92b5a7bfb08a62784fc59a58ca17186ab3eea6b4f9b3c775e1426041cebaa954ee3590ca00ad01e44d68303dc73b9729a5cd8cca529e398bfa7412f262ec0b8b72fd957590d36a2992e715592511f4610220d9bf50bc93adb4e6481fa5177384c3864c3f0b9de9ccd2cac0177e2a9ea56b8103e05ecf646f82f186262fbd7fb552681b82bb8d2f526fabb7153cf6146b447691f9d7273a55f72e43a24d4e9ea1a21b99ed4af1a93edbd260beebf4f4371f7a1a48745473d584051710985b4ede35092deb149bc6069a076390f5b7ac7d7ef3f378a0e7af82ac1e66fd9b640edf7db96de8b2cc243e4c83262804beabb2c58cb3f6d7515bd1f1c2b9d5c0e96d09feb4d0729003323a460e2ed0736a708b959cd24f9211f737d7aa8615936bd8023a83ec1556e18eaf28e0e446dc5ba94c61bce4df6bba0048d02e6249ad6bde3cb39f175d51d787f167a3fce799f2a499bc656242ceaa15797dd6c4fe5959fe3dec6ee8972b75bca584efcf3f56cff0e7f81eb1062572854e332c248031b6a67a679be67f4e1cab3002fce1ba7d641cabc74177962aa40e3b82a7179bc1126566978e8752345cb2255473cae5983f96798c861c7f28aeeec60ed0048d71fdc9a70ebf41dc78b69ffa0bece14d11b2fcc5ca55163db9f3c5721a2f71f1eec931a03fb6ac6a75ba93229bc0cb6d847e9e14f3270b3e492310c4471df65572153be6acfd3d78c5b95a338687ffa35af318ebb984520d70bd5f410833e824b65246eec91b7ba3e36343b15eaae49b2fa0ebbe6fe59137bb131f5cf009fdec2610f12d2669cd685928ee0086b210c15d08950198d32f2972d4cf8c71087e184bd1b9265780c932918ac7b581361a927dba8359c6d5a26f4262fe642d980f3582051d6eaef8e59f16f95f54e09f58ab0c07553b7c559185a45e0a58686117c0732b7c7acf3ab90a63f513432766515782af890b2bdb52f9032691fdb3dc3e45a9c584bf2aae9a01032e9224c813ab446bf38d5d47ff8d26094d13a8b261c931606394b033fd3f2f7ee64a6e353fbcee3273d0b6730a96b901421e0dd6ba6f1061764b028d8eeec231bcaa7401330ca180b0f18b1fb5161e95960f81831e967f178e060a99ec4f75c62240facea6212ab13b7e6fb06771c330c966a85a36c5b9ed1b545ceb8dc7c696b79c56d00180d64e63c5b8c79a30436d4cc1e6ce6b736d6c9ec46df4ebee113ddd1b1cb7cda230d2da661ae7d5e81b95a09fb1525526161088b4a238af390226034bb108630bc6c8ffddfa73a2efb864555ebc786c64207379d3be39202ef5e9eabcb8248a3404bb54abcc0d79eda633eb8d6cb31994390fe2700678e73688e3c3dc96be7ba17704695e2417c338619ed3ba26a4f56cbc3043381f7a7cf617ce5f39d118efeaaa3ebe4387253776770f9e538e908824169f2c8a6db049c44ee3fd32fbd63f55fae4c41a69a81f1e52f0bbf809383a70f4a6fef575acf6578adf2e867b68e299f5810b3140331296920cacf62afe94c9c2e24af7cbd2daf6581a7372e463822d368e0436af389a85909df1fc78461fa50ddb810fd4d4804733106ca6ab3896661a763f790b3b1f51fb3f1b7955b1438931ed41ac24f48eb0a87b6a80546a87fb3dd42d96f8bd29821e6a99db67c2a8ecdbb20d6b30e55ed924960d9e547bef52fd124f1edc2141ac969afdb102fca84667a434bb9d195917340ab66f4fef24e3f4db245f3a29e027e06aa798dbc1ca3c624e681badf335f1534405618b26d144a1794e06a7199d8a783427d146a49725681b0819f8155dfe1edc6b13bad56ceb8f871c738782c25aea920f18c83797a7c584a5251ff249a3d32e67f4435d605f0b8f10447ff806ffa40ecdcdf4dd341a1725bfcb7a1c71792cc48c91b9315405c1fbd9d7d4ebc41f3104d47f41180512e988c88b8af66de49849397a80f3a0763f57d9dc4ac092001e0ec39b316a832899085fd3e702b78c8206fefd3f06ee26d01d80903638f968c7a71ba04a6716a1c22ed63302d3c6c796886db8480d85ae20c77eb22b9752afca483d2cf0706834e186dc3752ec142c3267d62a305a1f62bde024a08f7e465b927ca8afc828d058639ac24f7bbe3830d20ff8c18c8f03fae3f202f9f6403cd2bcbf0e9735f2f762e4c538e9d1cc9b6c1 +MD = 58475763bc0a97d5434e97401924ffd219e4da9beef778dd0384dba227739d5e + +Len = 29024 +Msg = 9bce10abe974b342df9871c946b46c2c64c246d216ffd8801fef277ac0a193eb893452866e9a1d6e1d9c29538f1e59dedda5b25056160f66cec1167f389d6a0078d522f872847b0067bdc96681cfb48aacc7a087a8366d165c3461b06ea462f310ba69471dbb33c164043a48444ee3f67930f9c035e55a5a7250f055873de38bfaea0dbc96c6af79bd786241ff2350ebebe9a34324ae3ef8b81eabb6aef1558fde6df89f062d55f019222a9bdad76130aaf988589e1681b9d5a57b1a094721c8634c103894798fed21087a9cfef1808f5f688f47cba78b6572ed46cbc0c7adfe328e3fce6931c43a7d343b8e93f914ceb23f9f57d2e8c5c436fff60ffcf962f8f33b6cabacdd5b9dd4ae53b7c07885b64a85a2d2dc61959dcae2712fe566a8804d5c7f158606bedfce7cac60aef53a0fd0427ffe109b64bad59ea172a295e85ce8f85f551f3354c814a82dd085f89da1eb7e1e24971d9be1003c6c225c0e88556d17f6b39eec851f4e3abd516c0915334442678b986fa0dbf3c3bc853a5af23384c12b762bb9b9ae243846298bb10a8f8295427d3c1add70553b78e565008cbed4ffe6e8f023583b3cacafa10b77e47b4e809740aba5b867cfad88880488c0be06d80f4f12b1ca8f419de00114e40cc0500a4e1d0c989b8a0820d4b7407bf5fac1558ff4bcec7872d914c091cd7fe8262f3b4f5c877ced9fa99c43b94160923bae7d4c1f145ac8abac1839995fd0e174941b824546d8166f5929bfd82ebf014975582f184285230463b13260f25f607426b3cf206e347ec2c1d0305a2f21a9ecbdee20266ff5f243a6e7942facb5cbec8e0a1f342a188d6088987c886e0cf2ec2e480892c3309b311cc3454eb8598ba5732858caa00dab10578a8caa100b4410716dcda565c088966e4c2e053cd309677e16642af89a409bd6ac480840a307212e6559a47e2d1f3a448b379c61acacf957db299c5b48b4caac0898e9245ea3e80c3992da35fdcae44486495a4e6bdb25a57f9168f19e6f6382a66597e4c3812ab4f0628eb3baf05e19474a882c9800b1100b83d5e124d92eff8c9558a95a07b2ce92b0071febf86e69d6246e22bb82664286e62c54625af5ccc412759bac9e470128638ea2194cdddd39bd54595dc90ce0f8a4b671e15b7e9056c236e140aeb0f5b8656b64cb53721c7aff82f8053d6b956aa4b861284292f4488fe2a49ea0b6534d9de68c8975f7cfa1d03f283c464a06e2ce7d4bbf79f9a0a460c30b4fda21c3ecf34743dc1a329db41ad511894c73de6b0a4c582f667b3b721c1f3fdac6b9ec9f4fd5b04aaaed2fbdc48ada74b7acc30a406cafff73e06db8ad3f67c7cb45776d99d9fc5d8dee2cc3b6a7ac85efbe5ec958267ab707efe080fa6bac9f508f0b5fb99b4e9d2cfe3dcfd873ae455c7156af3ac2dee0897139d1ebea36e9bf5d517b9863cf91ede40ae81238093b668c53c4cf880501632f23b468062c2d7f78f1cb1c79a6c1396a3a164c3ce4f076d9ff11fdbf17a2fcee442f5905b6f4f8a892572e24fdb5795675616ec968eaf21eff9dadb13b4bbc79444da630fec492b4dc25b7aef9f6137165d26025bcb34424fe71c8a49a850b97cc1338cf2928b56679409d5dc40b7183b0700a980ad3d2b3a29334e15cd7510f848bf52a62a5c9840eadca7a867cf954fe44546c77d00693930ddbb0a8caf6aa13bcc688cfc536d74675244c66d215abf85427e72d34478b7ae7a358a6e5623022ae9333980f6427c6a1951d8d942c5145aa69535486fc64ff27762380b0fe69586a4571e60bbc3c39390433234aa50f8e4e04f6134f8fe6c9d73b575bb3301c5ef7c28be142a4dd454358d84f7ceaab7b46de19931667d981feda3d62776113db5df4c9b03b85d492c97b5139b362edb39ce103fc63ec05cea53a1dba83fa1478a5c2727c7ec8e7c9d254e90a76759fdf58f4fe75bf863259d3453f8e5f61e8ddd613d06c94d3df9267cbe7ea4e8b87a680fe5026b09d27ca90e2ea04940057b1f8d129a9041083948fc89200c20c6fb11ee94238c099adc8e4f96844a93e289c14e3c65a56e59d78523334755a601da8399c1cd377e28cfbd873ff77268225483031efa813bcf3e5b8f413709ef05931daff261e5ce08c0c7336f8c59436145a57a3ebbbc2fc4f84caf4771a1722edf708faa842f7fc74a3be2b9b5579c1be7d8e2104baeb0d77fd8f19aa9b4c5f9fa0cb75e967d09c0e67bf3a2f50608beb57df9380cd175733f70f4cf31ac51039d52b5832b3702a2001804cfeddcefc629051e1a81ecc424d1b537699bf0b9b813d318bcb515e0c731809474e254d7cedd1ecf3c4d295368b10627de5b4a56a4081e4f6fc6722accf5560156850647352c2b9b11c14f79bb77e454b1f1e1be33d484d820d1e4570fc608f9c94859c495a0abf04f70a7cd9970f02c68f28f670423b7215459d4ec2c1e09ec619ec7b66cd5107d29fdcab58f469a3d87cf7bd7815025d98ed0dc509e77e937941ae8b32734197055ab30c8095342f6830b6f8637f4416f44d9532ac37e1789f52f354161480798371b728ba4419af5df18b309848a9a30fad5e1e1576b1541f95e25d7877b6b5362c0f866cc7bf2aa1089eeb8138db0ed3558f11ab6f9830e152a42ec1658c5104d2e4af00e7d0a81bbd18b485177f5f278c5191d6e93c13cdd1604f5aa6a957d7ad5d29dc6cf132b35721100cac409cf29ccc28feab4505cb593f49a902b7ce9603a37e6a1eccce5120e0897ec0c3cf1ecb275d8b7e5c0fc33369a218415bbf291ddd3510c50987dd5e7ea6441bb3ff92628bb8e52a29379da805e50e2a3f31774334d7382850623f5a23efc485b63536a81fc27577538741fe3c97f3860b2c6abcd0eb49104769605cf5ed67c67478f2e70c02a12d8307977d35422e1d67b9e9d2d8f9ab4599a326ab1f2795a597d0ae657901d21360be886f196d29b7f9deddcb748ac58fec187a91c726b7ecc445526c8f4571f293b4fa1a0fa14b1c6ca52cf0ce2501b6e9d1455416703361a5e0c6427558e492c3f1d6c84065fc136616bf890b52c68137d56d3d338f73cde2a8f22f54c295bb997e05bfd341a4668f387ede56997db97e2cdc94460bddf723a6bf7d5409ea35bc626e47f1bdabdb91135136d5838c2668df78a1796adba90fe013729cb74dc7d6a5f8aac2627a3b11af21dbb0975c909bf52babf236d4a94e60d8585553253b8c508d2e6db7774dba15d413105d55bfbf76dbfcd9f630c0892ef475a666da578869141d1b450bdb314c54271d5edf7b7d6b72da573356b668505112b877d4e472fb74bdf3929eab215c875ffe21638b7ddbd78e9474b05392d0d576b30e7aa9f10b97571e289987304e5702dc2f47b866cef260b741a55fb0b56aebbeb43670aea36432c38f62350629ab5ade0ef5cae04cab97e8229da16908f7b701ef6fff51cac3980b4d637d4cf56aad2d48d389955eea7d51a000e266d06323a54a8e1f81899ccf1eec0329aaba7e44f0654bbc2a0b9758174237ea4e159877d24af998e6e7d72023f4a9ffc781ce6750ebc42d4a5c9a716591a881cae07dfbaf79193229ec5dd342ebbfc94c51425d7564a6a29b57db106114bc6f8238faf7655e56b5f2a01430a55bac4de033c270865758e4c506437d3353db7b1d25f7b21b8119e8e80ce57f71cbd8542c2e36e6ab4d44bb7171b8ff04d66e6f44af5c75fa6bc894b437b807d1c4aba5d84a86080ecdd1ee479f23dffc26db119edf11882aa3cd81fe297611ebcd8d0a8b8f9b1ed45f6747ee986d6642ca8c2ad4bcff33d2b18e776deb05e5e76ee649ed065b70288b6e8c0f647cd9ff4ae7818d4e0cbe1b1e753ea9844fcbee2f1e2ba7b6af4530da4e86510c3a835a2f56e0729e21702c71e89d5bfc3b0b28999d7861a87fe714d370fd5d978eab7cff400d2ab327922e32515e2b5cb0ecbc33cbf8c2e2b49cfdff3ab9da0d5f988c450dd15e96046c48ea1747c0ab98b7d2851172736e34ad13e4158171769793b38624f4b64da246a320a221c3f1dab59418d5b01c54e9627d0c6a1ecadb1de4194cef3ed9e2e768665c5ab3db365e2b28738078649aba0264ff9f598c43d9d3e51ed577705cbd19ba26a7c7b1830c64b61f7b93f34a8ed7ef431ef85fb7b3a840853e6622c40ba3c707f123ecdfcca767a22dc9726b4f2747624dc3ed3e93aa510892d49821b94cb486a0903553863b6286fde18906e43b93e49684dbe06122412f3a897a7bae5daa2c1cd634e62269d05255a5df22355bfc4f6001d4a5055837829c4d6fdbd41dd07fcdbd90a08879d98f9cdb1dc72aceaa2d12037e9667945c8a21e81f4812d64f091c0df289a0b3a4c4394ceafdabdec405165281ba701ed7ce312133ca50ce4e526f8d01aa535e5a7996c0efcda0d17260d3b6861a063dd1d635c15369764ff6e02f06660a87c422371affd43ef1f0dec5b1f735bc123b722b9391262e6d9f6e3dc541c8b1252b25842dd0405986832dbc18dc35aa7d5ee154b55655201b06dff19703d0a816dc8beb37fcdb2547d28acd702f2fec2def47d901db874769ce71820f1726f6401f7bf1a04c4eaa1d241b8121b6ca880c35cb43e1e765ac3f3d4b7a944471a38d3c1d20d18541f0eec3085f933aaf88017a9619bc419756869d96618d5159b8e47a9aff30725b00a4f57af02f8285f3f304cfe3fab2c44d243479bd6407883c2c221a1626da45e1250399ba5b58f5d2cc1d9f2a0202949a034b1d18802ea3374f7cc4ee1c84a79b5b358c478082a72c730b2e743ef9b1440929aaf9498e55b234d0c10e783927372cd27c1f07c94209d016a34c155ec053201847e927ee43b3c36639fea3c170bc822490c856f56f72cb882737effb6cd02f5e1c6f82171845e485534706e428324471f1ccd7ced56d4ca7e1bf34965ac21e445213c2d27a6d7f773770086af8a15a02c6b3f11b1d053bbdfa6b4df83531d512115d4fe512357c820e01101a8712ab1f38030ba6ee3f801099c3a0e9a3263b1080d6921887a4c3ef008388bd7e8c210f6f468f35f12503e8e75096314ca73a86c805f13581c23d06347dd71b8418a31c9203e491cdbead8f0c999897dabfb9bb +MD = 9d1ab78a86f0bc7139e8827816e619e0c154c262aac57e1e115e2376c78ec29e + +Len = 29816 +Msg = 7a427181eb8df8f0cc9cf6b96a19bafd3051ad916ee834545acbd8bf5567a5bd6f19cfbd2ce59c06896a7d4b3a157e803696e1ec7590067ef8958f640b51c1dac7052c40da388e708ba9f54ef88724a1a2e438212c688bd06042d98e7364a1e88af0ce327ced97d5da3fa4e92dd672077e25f8581cd68bf299bcff6516090f90c0c1feba9b6e7fde7f16d345606a315ad2406abbcb43cd8cabe948107ba6d17a72600400be220e328114c98a19ab2844a41dd66fc3181a459fb3feb82aa5b04da8b4282d6d710b7ae823d0dfe001216bfea4849f8cbb3ac57c016784ac6c74b268a7b26931c3405dbc2a2e6c3ed4e277e7bdbb71ac96f5b54abacd9d8865e550bc20e9db9080738406102c5aba8c35116850c50dad0f13bd12c8762a46f6cad0ab0817ac14106d96cebf12d1dd91e0e18745e89c17905b84db12ab546f89edd93d45820345dcf63c1a1e28f82d4bab8e4e846d46708096b3ad80b3438a8514147bc07209aa4ad61ef415b5f8342360c1c5f59c3242478cf190fad81e1f5208286c6131e6cbc3d4e3638c03f97a7fc521f381bc89144d05e78d68600eb65891be191106c130b0b933706b582286c8a457e00e17726ff9c93dabb2943ad8fe767e88b638c262774db8219afd9be067c30a9485f316dab59f9af3c1bccb0cae810fc3391013e882581780023a8d10c2eae318cf999ddde951a66b7b20e8dbd0781ad283d6d94a37a2fb958956209e43e38973d2512e00fba50a1dc907baccca2446bb7bd23f1100f20a67189b7b135175a6ad7862f1cc54646e1194bb6867054d3c88084b6ac44412ecfe984fc7f75367dfcfa8160fc85c56794ec2821b34e9bba441148b85eb6ac84a62efbb2bd0b382dedf4ab3b07d7b42d4dc3ca5fbbcdf3525ec86d8b60edcddcc9c0727d028d88e4be84582fb711af127c3eb6b2f864d856793467b25b6011919b2c6dbdd862a53cdef83cb192e9f2c190bb61ee01a9c71133d3bbcfc6a4143daaf161e7b7311980dfeebd6323c74b952bd8404350135c2d1f34fe260b30425b698de3ad276f527b31c65ea6d21ff607be13f6757c27e3f48bc69377b18b2855677067509173ec66652d950f267aaeb3c7dce8d6de5e1b221a071017521b32c6153751849de543ecea72f51ea95dc203c9b19bfa0f3c5e103a75089765670e28035156ab954a05694234f337d34fcc9244208441873929697daec17a5404f6e5b24cdb5820088d860ce223ed2cb74ac9b7b8366fcedaf9785402ef22a66b99a9928853fcb6a758ad9b18ebc12e2ab924a4d726b74e986ac74e1fe642e50172ce3492552bd1bd036a8d37cf364020942d8c0bd9caaf07e9f0cc645b3d987cfede0909634809affa2753cd52cf1b1f686eedc4c41c389ff37f6f6e92852924ba53904be2d3b6f6c97e7f57fafe07ada2434aa07a2ea3d713bda79d40bc2f9f11c95ae868716237ddca60564c45ae21de55131d70645933d745f58eca450452b199d94d6883a3d9c3b5b746bb387732791ee79a2b7fc13c9aa2e9a1b3a25fd6066f9c0977acf45307aae4b7bc38eb461f0b28b52fb38457ea4ef47481768a9f7c9503aafa3fcc4a16246917e3e982d31c9466ecd1b21b2c42c49685b8142d25a0b4a08084cea4156bbcc4e5b6acc6700e6512afd5edee10408e4043bc1dbfff0f4903489bcc144b94de78afa9053e9370d7cc8c80e985aa4016923d21f5ab8214bcac6193da85531df404e43f7543b3c076f4f187176a60edf80cd07e2e78555daa0c4a215c7fd263b7ea11ee9f8e6799cd1c7d4d1a14ca86ad00bc254aceff467b8380b8d47c300274a8c73ac677154934b39e47440d4dc6a02e4ebbbce7d66bbbd293ced5030286c4c162a89c86437b684ac30a37cc711a6bd616b6078b8149e55a01c7d09cb04d22b472bc8434889cb25289fa57dacaee7aa89288bd02664d728a495859b1cfd2090275eb102a4b29bd5b51bc46a0b1df571640b84fe51bf30df3d8e4c2eab7c2022bfab8c2a001aee3d5c8c466b6dc598b9fafc922bc18e6f2273f01be801e7988a16fba0e6e4298c0424d874aa580e982a54e4fe7ffc375d984fa13af4a5a7516f3434365cd9473cd316e8964c5760bc6d79a911218c24c2ead88af1781f25137a224096b466dcc75238a4f47cef23cd2a7135103af9bb66c01793889df8c8a553e70508171450f62894f4d560aabf9408456e46f1c96610c012a5468ab7f7d1a18b6dd4ad6a0b8ffe32c183200f9dd6b0fc3efa6f868c8a95d3a67468e41c5d0c175f419df0755a7b18f144e5a6235eca9e8c73dbb7949ae562805a5e079e123e92c298102ef62148506e61d7f8baf3fd343ffa5ee5e80959c5194095a9e5b8dc0480222dadf7aa0ce21e221d8cca5cf1c441d72097ef9e98065b6e34515917917680241df4debe70d4ebcee0eabc624f597952485511234b2d2c2b648862f602eeaae9078b15251c30bcaf479bf6cdbff8cfb3ffa8b65e194076c14dd5681fda77e6b814fb02a7b7fe780b7b26e265e8ab2b416c164619ab49207616c0d358bf161cd86bcb0f0ce944092ba313e7f173797545b829291aa84f1293e8d10b6a5ad534923683a31b5c0c5657e8eb6c3b076b95070a69c82ab95b345fea91781d52bb162e9aac259db55d47d67235db094d8774cf8b5d891086746e24458782384fd0abf4c1cdff5b9f40c4f268799b24edd7f8e5628dd596b6a2a828203c9285fb1dd92bd36e981ac0bbb5f1f24014548e630a90b9811582f1edcab5a4360ecafba9891df71758a5c0d9021c3a10ae60d831931ab5c2af9de15ebc11f8ff60d0fa7da4105651a7c3489f94bb6574d112754c79c980d70daf2cfc6684461fee5f9e9f104d18a3ed3b001751169ef1e5300ab9a6e6424895807ad0b058b31c223f8f19b71c649692d68f4822740b115283428100b8229eb1d774e083d36980633776f37fc462b1fe5c9e3aef1fd45b80d3c2ad71894960c87dc136c53f90d21810fb33528f3c7c9a95d4f6a15d2257d8e83545e09fdf16413b0ada60e24f9bab92c5e317c3177fcc48da831e771d8ec089414f34440b4886d7f7d23a05cf6283857d0ab6a91e43fd3f57e950b5ec87a1808ed557bdf57ffe192f283def38af08b1cab11689764f9640f4311e5eb8cae493c5de3055c64211cb5be450eab10ba2de55df21ab4a2bfd1459626fbca8e0ef8b8e73a753a61a27b3220c5a3c62fcb9d3c69cbe56c0609c832d842d15e5502c2f909ba4febc8ea89b2daa452e740cb559c4f0d5d40075da5418a03fb296a20149745e0fa03126fc4924c5f8080fc3fe38f7e44f6b33f21e51c4bc8ddbe45fd89fe1c4d07f2c6a8c85ad665b125aa8fc38087f12648160d240d6e3ffd7f70e18fb80d6d0e3d6e3be19739456947e4318209fca070711455deaf91a7df0f6372923f99bf5165718fbcb1c57d1d5a31cb8ba63cb169b0c2c2717d36bef6c096373dff31b285fd691ac6551b7b41eefbc46ccfd8c286a999a988e0cdd3d945a185ef9175f52057bd737adb9bde7b78daa281f141523bae11918194d784fb00ee152370c6e59517071066cfd7052e8a36ec87b516cf1d40c300f7e3e450d085043b7637a51278bdae77f69c4d9def95a918ca85c9b78004168e586864b60e346c8f5430b0ea2fbe4c20c6eb7fe7131d99ade6ddcaaa285a84702f9cd932e8b18f774a065afb4e8b38914417ee9f4d9491125937a9f55ad6a57ce9fbd236146ef589c41303b449c72c4ffabc0a25039d17ec8e3dd847bbeaf20b240fc05df5df374d6f015bb395d47fc3474252f6b999a6a3122ad60fb019e2914a3324192184bd28873bb367d745ab71d64579a2f41cb5dc71b943cbdbe60fa5d9108dd60be20fb1c93ccb4f729d4802143fbeb83788dddf295381fa93d1c1bf6d225e333999975f818ed3e8fc3dddca8d8bc284e8808741a574111a7c5fb15452e335af2efdfca86cac8da2d8c9c551aec3f5b7ab763a9a72a581b9f9f256eb46dd74b850919812c710593b9ca3a72e0472f8bee4ec70401d625437914c1b1aa56bbbdd32f702354d44c6e1bc6dfbb60b132c192945b0e91234f931d6af8638fb287b8c6a80c3765bc43753cc8b1b903f2f0044ed3484ebdd97f1373e9f10eca49e34545be1445c7f195af0217dbf331d1135c0a51b54deebf5cca64dbd539c5e3756a39b7b0d6e13be82456fd83f2531840d1ae58cb918d9e8fc0d686cb6de748e83188dc0a711d62e5dd21c0d23ccf8d216c222eb1a4003ebffdb234fc31983fe2a21b75479ee22d33e149a9ef5b0ff95e344e1b900eb167958ae12b8f0d40920bc4daca92e599657a38b80002d779239f321b69905506e1b86e4ab3ad8947070d9fad2211cfa8d264eb540d353677d58b6c6f5ed8036973d2b1d4167e2e16678d3b7dc7ece3783c97010717ae0270d5caec3444919f41e7885c699a2983137936a130ff4ca9716bbb82b76895c2ccec05ba5061e2b2f6038475f089d711a707add8b01359aafb2779774e4613fff2e2e4dcadfef4c3f0906e075029af5e3ad79de8e34b3a6d7f3779e7b3fa50404c7f0e5c3162ef5a9655ed1773c3daf435b3acdab3ee187b636462dacecc730d418b2c41c6d7fa00521caaaf409e7f5bfe6182b507461a5a1176dc588703a4ee39cde59453a33d3b8bab4dd69f04c719ffa9c881c6996994ef35916ac6e90d6c9c0ee25cbf0fe196aacb7d95783bdab89f552646da302cb16768261773c4d30ed316caa1f4630e961544e2f3b38cdfc0452b430d2a538c37e0d9466876dd215d44ad466cd9e7ebc535de25f8393ffeb75bf5c8dd9e49b1b0c24e9763b77c1de0589bfec456e3a1aa7261eeacf09c612748795cbf1e5cc2a37490c1121fe9ef1f77a799b1539e57cd3594e418c1eb2d977480a8ba92d2e79960676d7d946bc0a20a9bc03bb86136b7e440b04394738d9047d154d6e2f44a19ed9a43abff4bb8f2773d1a6b6d7466efe92dfa35527da7992936071bf70a10ab83f3eaa449d2fe96285650485b1f0efdaa2369f7e151a33a82756992b75c64d78a380b705845bb1683ad09da68aa576a91eaa5902b37aafbba5723420b316c266a324d1816ef16fbf20cee2a7d5c68bd044957081777e46539a4dd34dbd3501f8ca959a36a1738cbdc39a63f837e6a7e6d0a27688c5878ff67243e6e1088394b5665d6193b044811a9fdda226058843633f3bcb774238e51ad9eeffa90994f30312d6d8273ff6f52c02032d9fe32df6cbecd +MD = b65f97c19c96192c0adafc3d3e976ccc6492fd8383a7e2ad938c70f282bdc7ac + +Len = 30608 +Msg = 3d0519876d99292e2d796a06199e82692ee07a8ddfb87164644a92c056a343bb793f9f56d9ce27601837b49a06deb118722386ea402b57fcbce2ef3b2e40f7f9afcc6c933a5f5051062b9f8d13fb841803bccdd92c3d9db7eb3360ba3b80046c86b56786bbd50bc8a05c11296a7f65308bb636a2cb78a95d9a45ce84a4ead3dca701777681b7c28f8ed2f3b430f2bb2aaf16a88c4463e4b670211fe29207ca11b9b886adb78ddc6c77952e7790daedcc19e60de0c086b68916ce3d1c2d5d52d265e37b7183e0c12803aea8bab0c165df712e4ce7666a88a033540e7a9c76d4e953883d0b0d36d88bdb244bc5b82e8a2a5ef44de65f96c0c170bc7c4308dab61c2ab2b6c37e1a8b5ca7fffedfd1aac4778942f828d292c8b5750d6ec1980f62349266cde0fe1141650e47a85123bc7b8c9a1f35f4e8e70644e94fcb3a759f3ef935ae6aacb4a5636cb9053364d5ec17323894ec91c81ce435758b7df7c612b432b891756dc95d573a5041865d0fc200310ba705489cb9c852c0c86b40b4ee2aa9c618d76c65c186977a018987fbc79f51bc62686189471c61730e7d5d67bd0a24054976f1ae5a584adf4f2429be825a5af3cdfd24b94d472b35659b950606bb6c1d2e3b43cfaf361d28323f8a837b9a1357efadd85453b178afd6ad31ba52a549b7cf0eacee4986d6fdb3c2f3703bc84591d05ec781e1c21088689b79aa2830827b32d87234aeb13e05d895acad494ab84978f9376980e2ba69244db5ff10c4e110617fdec868201de9aba1fd632d8a3426f0677134b77940fa10ac2de092c92c1f64ed38d2ff3a3b5134cc2eba70ee81d03f8ebd090fef68e2379e297637a72c4f4108c87cf9665fe37aff86d999e066f06d5862100facfbca9e0cf0e886c6a94902bad5ece00e534a85234ee930c7ad2e83acaa733f18c0594fdfcb5f088f6bb4afeaa94a3b99dd2c5d1ecf11be0b1c318871db57279c813851fd0203436839394e808abf936fc6320bda4e7aca137ca284913ee6509e040eac50ddfbc1badc80e963c1736ff8d503963d164bdc4994287ff31b484188128468bfa3700aee1d30877d968d579bd44806316ead7c142e6c827fbaa582c073428e319e89a46ac2f131b55035d3c389a8639d9dc833dc1015941d62249cb0efef2690146f1998936deef339956cd5beccb668ecc3880a03ccbeb55ded16be4e3336c34e49f1df5a49c61f97d2a93a395b077ca3c70404cf39072ff129785457b8c8b29440b2a6dd30c122b317135ac3fe5cc00afb2d333c03777367004bd9d323e3452e7ce657e5c8e8e2d58a309d235dbf1c68888eff12d3166a079915b58b1f9064632414593ab9424845538b6c231f37780795acd11850edfa181d614f4452d6f77c61c514a4acd73c4a9ba92d89ecccbc2d4b110f1723030ce4b3b411c964bde6c15a80f0eb49b0a72d8a144a1e6e87d123d24423d8f36089b1849862e1fe4d197a38cd55d637d46f37475329aa4a6f9d3151cd7320690d57c8b894aa53c88f78ef2234ab2f1f4b7eadfbee34f52b8d099ef03569ba2d116071763152e8698aec68413e5abca81ebadacd6dd1c6b7e7fdb4d9026b6de6748af3e6f5c0688a465b2cbc72ca467b540d05e6596ae6968862b931bfe3003c3fbf98316a5d9bd2ccaf84bc5963943ff55e756d3a661e71751ef623f1383cd979e6a67f189148ea23ceb869798e709d0a94738b962d34f0b71bb3d422d2e9622ae766f786c5397953a210ea5db1a03d9a994768f727f0ba573f386fd919cf825aaa20c23c5f34286511d3688a36edc6ad54392be4bc1c785d74cc1a9f75b5df12161c07c2c9029f60054b0a8a831fe14bad91fde6547ed1cfa1b8fdfb4e64215915a1efa1696b854c65bef9e302fe357d8c96058457e06eb7ae4542750ca5f1388ff8a260a936823219755c2019516b4ad9916c462d08f61c82b80e95173ef7b66a6a4787f02d401908b85cc632e22abb7cca59b43ebe1207075c8ce4d7f7dadb8f3d079ea51664091ccf215fb4771bd75e89f557f2cc6a7f2478e1e9b59a42afe6b9092e32ba990a3c01d27307d9e5a6651667b6b2f9a58cc153382c17edd93b572876befee185255097988893d031307ab8d859e40c6c36c736b73666ba4486cbd075d77152d06141d99a28bf24a77e86b970c9f2ce66861c69868e0bc72e9828fb2f00f3d723c7f50f01daf59cee976f5f568d42073c83a934cebc6cdc3d7a58efcbc1ec36265d5581f4279d01af831ff3b32d3e7e953656dfb749f3c3193341f472a2c438802d49779c951d1b914b7cbcae324cfd1aa50cb168bc07436bcbcd544c2ce3a5d93fba3820aedeb23df670047023d64a73dab1f30a9d0f23db4be35580e6b245db998e0da9fa488e5a8ce2112188432e47dd2eeec475752c10ba6a41375997e02c45af3e5f00c4769116b92de7eafb713eb46ce7bfcba026b3204c5e980bfb3d744b03136948b8348a9adf9eedcf66db016952292227f8d96b8670f5cc8647255cb174d3f05a8d8eec233bac59c2ec343804c7fb1611e50ce1f3be4dfa52e1608b81e9c81bbfac4d60b6b5a15448f5438b8bb5a4c312cf89bd6f1eb04bf533b6abc3493813fe7b398d5d35c305ebe9d1a008036d50b11e16a6027864e7f9a3ef617d7e6cff9f64191c1fa35c953230a62282999ee6773a7c44b5b4b2f5e69bd257b96fac082aceb6b405e7b22ba5328ab7025f7faceb8c82408fbae29d428228357e0440562821d9fe15ea0df0cd5745078f3d57cb957af24298723c0997c0b9a2d5256f1021c448a15992b70c31089ebb311b706afd6d93f1d9c5085e6cbd4d47c4ba825f9b21cc46d9c8f7a65aab5f7bf0e110b2acce2cf659998dc74ae0accc56abc16a209f2c959c7514e6ceaa4eeed57780cb290386f821d8146ab8939dd890e0745a37a63235aa7f57f5176b34bde7c508dcfc7669a03768e56f3e3eea137c42e356699ea4cf0bd008fbbd58d8902fb3ef0dae8d9c96a53348ff6447592721b756873cef4b0ac84e6f1f46d7040db32a7f88c6b2e981731f8542b317b3b9872814143a02ef8fe7e3d38a3c527edf7d10fe72cc4c160aa716e35fb216bf74b77e6626eb3d580573767e6426300fac954fb5f648c3ecd84bffab7eeaac47fdb89f94e5d6094d1571eeb6d48dd97f1d01cdec39c37e339466c126c9e14211ff9275e67883cf9767eb35c402f8b596d9cb74eb66c5e7b3e501469966213ee7204ee7a3087af5fea2e832f017ef2c1c89fb2af9a3d465337423754f7d320a8f08f3dc15bc44e54a6f71cd813bfaa6d8d497d95f187a607de8d4368f379a0cd160893e82bd680543758deec195a28b9363a96866ef3e4057ea1c71a0bbe3ae77d019f433326ebfb15d447df64e6e4315dd38bf534da86e8a22040ecb32945747ffa9e67044df7a5bce9e62698de73626eb4dc6715c4150de3793f658c4366e0b9644fc811b419d0a71a485627b93cc8e35ef650744904f1ad2d20f8f98505d893cef1eadde1f9286ee5dcf2840fc6e146226845c2d1ed4089ac742b7d76a8b8a9ab4343db6fec097ecd2260503aa82821afa0bb93e71456e387c781aa80d60d5589a2679ca688f051309743fec24729e0774e2669f130b1553f997fe34bf44341da9dca943e467970c0c9f1f25f2a431cf9bf1ab798c8fc5944488aca30b9f6d91ea3e1548fbb0167fe390edd39c82021a7821d0f4623845a267346c1c76d9495d6435050233d24b139430f121aa72db9111581c371f6d5f276a8286c78a5a902920a7c0981735fb7129667335a5de82db707fd86b4a98d9c8535941cdce8b0a9c247e8f332c42f141a919ba37152dc0a19d7f4db76c207c2f2ca3e656cad27e5f7aa0bafbfc5ff42a1d330f5080c75d8b9e3ec0440c6d1004fd47bd890798b61a2af789170ef5cbd48c9bbaa7701421407da67c39b2e75deecc2d0e8f0c4678743a6943b0ea6d3fe8fe3903666c7cd469429ec8bfe7f62a96a33d219061428d15b4e032ed192d180e7cf531b2fd673dadf30debfe310241a4895f3db38ff6bda69f439cf7229f1eed0cb78eb6a93d25b59add2e1d1b7368bf877bac201dc8cfcf047acaf58d2a182eb9676097fb6654293ef5d9452ab1688fa379b40093228d37ea6c0410e335d07888edf080784a92b0e83d349de82409bde7419e7b7a6bbd8759039270aa2a0c7483318697aa51a7f29f9d864edc3412f15bbbb2b8590b28665a26bb3c6d7095cab11c6a0418e45a986bfd197f8e4a4dd206d037e0b86a967df3bdc89db16f33211a94e3f04a69744a5445335987cc8009f066771a1ff0cf742eb101ba008fad21c7823a83c94abeaf635d1d044e24743e2166b88f17059af213e8aebce138cd73bfcfb8e41cedfd709f2d1fa76bb8f118a2b943662711c09fa94b17caddd259bf0a61a23ccbbcfc34119e806a67f2bf3f7a4560c8d87c0a24f8c2840d7bc51aacb12243b25f1d82a4bf968a76c939a55cb1f456ddb1ae3d2908363cac4379d8e3bbf9e26f5f7a5668b3fe83f319f46c1750ad6fcc3a0f2455e28d88d0bd575b0c30cdc69a533a4127f5bfb409e08ddc175d57f1befb0886518db1b0a172c56ace1988385cc3c50b898bbf65dea46bbd05e3dc25da7dff2ac41188fc46e92ccfd17d1180dd38837c387fe8de9df0f6d788e7235349475dd95777fcb3e8aaf550be6450e6443adc5bd9d921666c4996f2497314c332e18b5bb2c6f41fae3e86b63dd62db2ba4f3872179f51467339b3d5ef8e97bcbed4ef787c065786c12c49c8f5dc902b6601ff8797db62c7dc47b5492341948815a7f3f85e3f0f3148fca4508f7d619a71d7996304943b2fccfc04168d93f36d5ee2fea2ff7a03686c370114b2c2884702596ece04d3c4c66dde0804d48c9cb4c20e773f08bf1b735564c7de07b1ed7a4210e6903f9fe5d6e7772adaa13478a468b2c89720143f992a0b5e743655797b58836a705f0086a5624fd0629b946d8778565872f083572314b42e9ee6b312916d3b603709fe8f7c05ec64626bb364a31c828f981f134b593ae89f26bfd5a106a9be32ade7a2e8a3f8d84ca3b89946427abfd5d156cc0383c52e19d36bc20f203396469aa1f37a62649bf2ed2b4ff9aaba9492e43db768e9dc0f046c8f824228344a06c6dff92b0171bbbc086cdc6723058a2e9a7bdb60d3a812c8bad61e2465d363d9f948bde4c746c214bb224876f7832811bbb941d48850bfcd85e59d9c21396826fa84468efe0c3861cff59c106c5bf6a40f9eefad51fd9e7b94670791a28de157923c9d0feceaa30a0d8fdf1cccb67c4d5dd3efd176d7383bb10264ed32f857d38918c851d9098d793a9519825dbb43756fff492a3f051473a25ebd9717a25102a7bfd13a0f907d1521b252 +MD = a93bd433938d777293ba34f15bcde4155bd5d7ba9344b126f9f458acd732dee9 + +Len = 31400 +Msg = be4afc96a800c0db6a4c6a702ac9fae981be6be6dcf3368b23c317309973135904c2bae80dc1aa91e9e5548f395b03952f9b1a08f3409c6b4517f21b6376e93c2dcffbf38784cfd5fffd03a0b0f9282965210e9602e342cd207dd62df858607b8298451fdef13890f2bcfd0d554a738e6b78d1fad283309afd1e4ace1fc281fe4b4623d4d9afeca80b49cc3cf1f7ebaa89c7eb9a2bc96db82422d666a25c53add0001a7a4167f30792cdf7974ba798660736e2e0d55d0111ddb0025d47cdde7158efb479dec05693cf6f07842d0383ab2cef403397e6f48c70f0571bd7be2a302c3a783978631c360958836d5db2b35f42178cfa3a0d4e10240b5c0819d640d4950bee23d7f74dd78aaff3b9a45d306b8fd94f9f8779188743299a8cd7be2743d9879f9dc225f25e989de0d0caac03b85c5b108943d25ad813719710d71de76740d81210039511b27c4ad11a9746332df0c5572039c21aebdd0cddfae29c89261426cfe560eeb5bd7edd4effd3d4c8b19540adcc30ef62a8e822f4b4c0e3136a9b985f82a2d9e366e57fdfe745fdcb2e91f498f5ef0139f77eda62a43999901a1f57495191fda595fb570d3ab66a438b2d08a2033fa1a8c0e55cb1341566051ee68a15b8f4030232068e5f60eec338b0b1a4535ee877b5eb66d168cb1bf47c5e385a4c21949203264f4b5ec1b5afb38565f2326eb22a6b60496110d014e8fcc15fef75f33a53ae571eb790c5d3d6baf19017c79c6563cf07d63330adc9ed8e31a2701896aced0daebbfa7fd50fe158df7c3e9a4ec8c9ebc8557050c9ffa939964806be72b30928136d3bb357327892346f8d34eda405c68c0d3ff98c81c405d69ad8eeef164f056f7da2b3b5044272d9b22c1ce2c1be683947c9b15e16e7fadae00f30759f66aea8335807554de8ffb68d44da94e79ddab94b3503a785ba218a62d20c6c14f72ba8d78537a1d51141b347fdf76ade4923f261ac74cf97e481ce674a0b3c3ea98255b150cbff646641b92a7eface6d6b4bced1568e3e140e228f399eb44de525bd9909e24cd9c18f06ae7cf06b275eab5b34e25ad85dc4df0db31ef78f07d113e45b26634296b533987c867ad3dc77b05a0bdde1da926e0049245f7d25d3c919fd8351fa339e08fa00099045b8578123503d0a121d46dc18dec84357fd1796e212f8d2cfa959828e453fe279a5ff43ab45b1b11628e2d4d0d58914aea03c00142aa4f10b2b2fea946f04c33d1f3c87f1424f1a1483cc1fd0354e18a994abcf584e6ef6d642880ab787427db9b076139d4eff8d35b76e85bf06fe997163cbcb55853e285774cca89d94e05616df15b05672a951a14b2fcd455183dd2d9403bcb4d7fcd0b74c638dee9ec6977c348126c4b535af7fc776c10b1dc42d06b0bd691c4c90361d4fb58153aedc871238233d901f8beff7b4ad27b972a9d0243e609b36ede3a2b2072a4c73ca0a70017261bd62b8945933993bc8f7581a10aec6541aaac1db5c9efb2bb5f8fd3898706ba46de189363458fe886c6bd8ff33cdd100ae1fd061ab08b31e85874c4e4888a95516b6995aca916bfcdac0f94082a8e6ce1f3d235ed918b86d84cbc134c871b6da8089f0e9610469ffdc9cc4c645688d2534adc1b82cf8917e7a6963d260521a9d730197c942d97ff938a83f77c4344e6db617b259edcdc6bb2f0c3a1058535b04b7c695e4b5393652b78b743c4635b20f6e22ff2763c2e08b6b5a4fd7f79e03791381f220014c157221ed6bfe159240712177af0cd8fc6655f5fba90d87589a6351dab7677039a4c13e782ba3777481fc9abecaef92a6e0839698509c4eaca62a3778eba048296ba8d6d2bc14b503fb18a09e59b7dae6d67c16d94d6a95c0b1358e0496b3d243f38db0a3263a1666382efabf634ef8e4d1a83d65a761a3bc42ee1d25c08756b0c3d9959471fce4c6c0a471caf09b34ca596fd2e56668c2c9e2bcae8472061c9763f54d4ca641654a19e4cd670986d6bdf4399f009366380f170707c8b4176b215c47a074cdf3e31bcd54d63db4f725e72c6e6a5f35454eb56c38f19a8ca28d75353956b4ecf9a460645e53f5fbd66a708876fca954ec4ce366b534a20490c8bd763236b30d3bf14264690e36e60bee8090b91d87f8437ac38fe7988723c7651ea89a091a37a111e957dccda97c7ff63dcda094a12a321f7a6e36e5f2f130abc252d8979073134e7cc42159f6c518cdd2c6912b9ef1a185338b0be28a77b3e4d1fc56a8bec879ee24349f7ac4c9bfba6503f5a8275678f2146fcc58f8bc3956722e7b044c3ebb3a082ebef7bb915d041f0d35d4e3609faf45a1e310e3c8a84bce71af72e1ddc17a513ae69a8424d8f4276bb7777b17fe04efa9b6cff4a4ea090d4c5abc25ae73f626e07f29c78a1ad2a6a5e55996837e383a10af60d357e5d85648e4a8c2b8baf5b0a9f16d2bcc09e6c3442641ddad05954d5d348a27e98302d1ebb6ff5d037cc1161ca52e59f18f77a7cfe1f9f79c7c615118af149863aacea8c03688a198a3a081c20134f90193ce79ce80478e58cce56dca87c7d0cc4483004ccd0d337e15db19216e46b205fc3462ca6af447eadb69cafa246b742c386a0419e354bebdbcb905c3552e2c03b4ef8a4a07c8cc5993358f30eec82f8c6ecbd9aee127e85e7e846e301cb21006a24718d6bf8ac5addb90e5f44da5a6f3ceeeaa932d4c596845827bee2d9b0613ae8634f6fa04d9ef9ac4f4cfa9cb8469401a9d51318bbae3f8fd5587eeb0b534c0f2083320fcb126ba17e3486a036ff6ac98da6f54aeb3d87f3b2383c9bbc670c0d5b914993bf55a22d2dbe8f8130fa3fab18a75fd7beb4ec2850e682582e0d096757222cd894c93ba3c0335bbc30e7712aad5eb96bc0b4da8223ec069cfac5a2b1b59e325ad5eda6a9f84b91cdd117bdccee25a8637badd1b5cda12ff68d218650e96e10771d4361a4185fc8127c3b54164da4a35b5a10703790be74e15f9122d9852a4dc9b56b0b26c2f85536bc92f27b3e4410bfd68d246c2f8c6bea0c94f6cffb5b20df48b4f1a66aadcfb6fcef1780429c970d9b647cd7fca37b7cfecd7088ce69500441c1b3b771d89dffc78011a9fd169cc0f336c80f8a8c2a16c07b2eb870ed51f53b01cfbe9b01469d96f69f7cc03aa8768884b4774bbf0e43dc5e9fb3854f8d1e8f05b43028d0600d05c31f5d3e71209ac5dec0b3d2a48e80bcb8222e6e1887dcd84dffc0cd9e70ba7e75ffefba62bbaa35955b2991e53169dc48846dbdc0d8dc813b00c4dbf3df427b7fdf98e687d0314259026d1bf97d4bd5600515d6e0d68a245d75d0e659222187512cdd2548e4ac969a54d2c349e8b3129f42ab5bf127623c45bd596f36dfd42c8a7641093e9f888cc9a11f4a6f0a4c2e66bb92bf6a31f1235445e2f9257ed6c59c3a58f4c13761af679596f3c138538356ee6063c49cb38439bdf1f6ad75a60d06e7899a8952b47904a0ce71f91985bbd049990b88ae25e94673fafa275ace4d4b0c574cff87ed6421314a276f244f32735ba0f93f1cc4ad0b0682762b94bc10d927469e8c4d991b3de58e96abcf0c71a0931ccf403f1c5a07e41cfd42ca0bf241b6ec01c7fa33e8cb2c003237906a03f89e60f044aba96acdab2ee1d5511a5c15499c192b343a67498343ac8b0ed463ebcc220ea4d8d879bcba3ce68bc073d8b43deb473e7239114969cd482ea0d81beabab46cf94d35e155afcb5dbeaeb4d2bf226e0e6a4aac714b7e01a78aece19675c8acadba8f5e4c48ea5ec9e66239e4869578e1471400f1b00e954d38498d5e3d948f4351059e14d6f87bbdab819f88baf5a0624d64d32d17b9dcabaf4d37ed72acb0c0654691d5b058869b76933229ccb18903f5b39f9df2fe5c35687e7dcee55fd5a75fd8c5f945991405c00dbe622c878748d896d29ed24aa89cec43cb7ce64c526ab922970a0728b86f205780ac6ab61f935e74f8da263d2624b343ad71f5e0ab7d09baa1928585c84a00171572f7ebd6860fe48eca7f34697f55d4a048a4cb6560ba07620d414ee828f7b3095054973093554c10da3dcef6ff3c9d205b635b04b842af54d4bad27c8e6fb1c8cf2126b24dd7320b93f27b4346e003ca34d21e0de64c08f6a362bf19dce099d039ce38d017fe3ceb823db7c2c8d88eea6f4192e57d3ebac3d3c97334b6f2e1bc4abc3c1e8442a34d2f60031a179eb52d6552382fdf832b49006f8d518f0f1fe95c8bbef2054d2b9cf619fbad959b1cefa184ac419fc1d0f293b56be4d7adbaf3f9bd1fff2d663c4760bbeff1d5660ccdce593dcf3063425d084b9d8313473948acb0fd9a6f263bf909d68e8b49882b3426208b2d33f005f4f892a0a0e4741163d017d6584d25c11e5bea25de8469eebf53ab02f01cf08236df1b03c2adacd9d22e4228cd39bd5223d177646ff893ddcbd139339c4ddd4daf1655456cf16a092ff1d0634dd78575a604feb8b4288e6ee6196bab96691ededa48c1d414323415b9d533146e88f6921160f0914f96c2189ab6a2c982d14dac24e0f13e3ce283862c42facab3d0893df26ffd9c96c5c76156137f1bc628e23c3b7953e25ba4d0e0e3b587e49240c5dfc59c66293e2816efa4ca7120f4c265157a6c7a7ef4dbc4ac6cc77af0ae4c350e0770dad58a50290a0346096783505ebe5e44d552ad19a74f43d3448d5c754f3f3487bc002fb08656fe10a85de635379d73ace50bc8c1214ff57364f9113e7ce9e93b9a5772dbb74d01a4ee82b1f3784946df2a18fc749b34fe226cf2811a66a47226e64a182424529a8d4c646b1d9938448624f8ac96ad84ca6abcd8109b74e58bb43036644c660e35443271761622e0f92c66294dc9b0c5e6b6e53844342023727e08cb0b96e4e67e443138677fadd9d12c5e3974604d6edf817681906700f4e2eec06662b63961c207e937b3ac829969108d97a50cfbe61164d15289c68fc0397107a70e0ccc069d299aedef3f59962d7374c2542214c228db861994b5351c02cf3efb621d254b8c03f6d97eba8b669acf9447f64250998250154545c5997ecb33e6d1f359ddb70b316d68e670a0614d8f6ca72fd007c2ba5d0f64217a155eef598fd956654ddf873c6f4acb24313c922d7e5e657dd2e44d7cc5049c3541330baaaa500fa20e0bac8f8ccd7137a65f154449ec1b8e2a549819e6952a9995a19c91b6f463a286e1d7a5468f8d1d882f534e4fcec69376ba46cee49461299b011ec9463506e950e895081cff83584f43b8b60074fb20508bb6063f90b447ca080e9bd8806de8e4966142809bd87a6432d205fc7d2da7402f825a5808b8869afce893de650d13ca51d8cf01f310f68f532bd8a455e2babe3c2825de6ac2588676494bd851791c6ac148182183b14f094b1288988d9ebd332804033345865024fa8d2e46e416455e6b4ba85fcc2e066a8142a03982d6313789c27ce71768effef030b5ba8b89311da6501a2d3b0b9f3b7c28ba17e40db943c7dffd7a5eee9a6d0de06c93b62652110901c81a6ece8bf4b23130a41fc9b7d068b90 +MD = de6b6fdf8b6b83ba756cbe0e714d3dc0160df45c372d8b198cf0455b52f49831 + +Len = 32192 +Msg = 95530985e73134f6fef027c8c61f4b9308afd67de19ce70173d0d2efda44b8b461685cdcf6c531d5dce0b8f6a06208bf4e77ae63e474b88307bc0d3df5e40065bb152412a8b2615d013b4765f672a397d5bc502c7ec950f217771b5001f437840a230930e442eb15d6c97f1eb19542a0064564e096e5d7d60acaa630e4bc889ab65bb53d91bbf885c1520528b7140e6447dc9188140e74b5487a53e68884192e2782cd419966af362b9d848bf2372e6a01477f2adf8d4f193952cc79d39412c8c463fc45e38b39af7d73a2504945ca3a9d4fd7d1e1aa91894519b9f1af339cf1f7c5e84f5772bd781d9c077ea3880c5d81bc418201ac628ed496c15703abdf2f286f396add62641a75e05c1dea461a5a1756644727dde9af4e928db2b742020dbd2a989b5da5561ceb07493605c81cb9c6e5e9273b834f741bd5c50ab2412d101fbeadecbf81ba06e9d875cfdc563b03f530772b26e7bb65a3271067def08ac2b6f31f64eb3fb861d61c89f357379ebf0e00b759ce51560b4e5016d222963eaaea91960bca267ab41a9b2ca75eb56f75781d51bb1c0848ed85178052667c7450245fbcea428025871d1d07f5d916d3ad9b4fec59f856b893ae46f6f092eb523dca2636083c93e463466ac2e4b0a3f4f0df5e30394b81ce8633a31fb38f2900f846aeaf6ea1a9ddceff49047ccba4fac5ac11c765fbd2b44d7af7a4a3437ea709febfcd2257083852b08475c612610db56a3156e5f2918f70ed092cc897346ff95c21382e48f81e77bfe1bec96e215347818688bf16068a78f2a3602b73927f4fc69b99995ac3b7c49529878ec52ef70359d802fd5179caecf38be8d3c0df0093a6f7986c77b02ac19a23771b01ce1f715aef6fa78a317a54578a6bc86464194e63fbdcae8606a0f63699377a084af41aed9375c3a977c039866892134969f30765700e676f0e40ecd2516fb3c4ea9d85788bbc5b9593c421e8ed04bb5535b546141dd5a01a10332ad415c6cc1bf5423a65a0ed7638cdaf97e5e169c872128893d8ccda606f53a038a6abe4cff7b50dc21a9ab01d796ca920e50b6b43874694771943c5af5621b09faedb72c33f7024a40141ac5740bad9465034b0337c1a00793f4b3d95b7c08ae6566f18b1db6faf68805c8a2c75fd68908e24e0a039d6f522b2acea1b7a795895052d7da0b2fad79701b5f1a4017e7e8607a3a492a5c29af8da2e754887943f3522df4a98ae58c3b8eb128ac8ca8541b12379a412aa26188520998625c659694d174b26a2b6d39d53a63cfd9fb95adc984b6d87272f499651eab4c4b81f10fe654b3abac4b3b18af09afbf131b64475c4e549f5da1d743de2a148d80b7b0025052673ae088b3bb4182f160f87aa8c35bb5bd398325aef35c2ae1d6926c07207b610c0a97627b94352cd57fea87b7b430713d41537cf02a57977fb200fd8aeccff71e753156f735f27dc84669c1357c82f771317f164f5b58d66aaa5d0a9fc9b69b1b155ed4bb02e1ec466f16c5868ebbced5a4469020f8f88e2f19f711da49c7b38e65706a4badbbfedc5451f34f8d535df6f44a68f9958f2529ab7f81bedf9bd6f4e006960d78c92bf690abd8e4dad22b41bc0b0f4db3b51206b946f8a21d7b7bcb0f91d69506a20a319e94f4db09c0cd42660901a1d5e2fb32ddfdd548661f288d6e92aa56d9cf0ff9f89dc5b69ca7aa758cb4de8a7e91373a73f4b6064bcf53c867999fe754a8a3cc1946c9fc05ef49579aaef45c00586c8a35dc0960513483e8951715bb29e77c348af0801fd80020650a47f1bb2da0f1ae7e044deb08c74f8a718baa36abe3efbfb84b669675a2d62a6620351c38f36d13d71df20ac4f00d0a7777cc0e6d2674ba4bb80bf4711fc11438b86cf3c4c83556bb89a44428574305315c0996e037b1d09fc6eebe5d0f87befc80d7d653b7f0f395c7c32ba56597f719b8d16497801d8f4ee87d689bda70872c1a2438581b16571068ed35ce93525cab0ec1fc15b81e32b39d3667b009321931d4c09e549a1c0d95dd70d6f67938a26fde49c1cd183a876865a8402c2442c1b8514b7ceb9d8893b0a5fc93df7f8164d297d75a304908e9f7d2519682b4193d3a0003586f9dd265db42ef00cc2ee3106ddbf939e1c2ffd6cc53b0bf36212bc80171b6b5532380107044d6825f0fc431ac1b3dc5540e95da707a444ec903f11ed916a41858c728003a1c31bd0a8abb4527c60390f99451716ea69aa9bdc50f8e1b7f7a05d2e120d183598ef551281ec74b7cf92164fcb9182179127476fcedb2331c96e2441a00f0d65d4cefb570853481906d0b0890334b23524a2397041217ca6e89523eca5eeabdb809f0b9fc851984b0fd9266f766870ed2b02ba082f32b4be5dfba258a811ba3fa44acd11484f2af4f297c02bab9682e7ac31105f227693222f8ae8ac31e2023846b689d610b3c7bdb5f1c5e22a24b1cab216839ca155e17a66283f11c8c84a6f70cd8715a8e7374e62ce7fbf7c7cc53e42995de83537656d0bbfedaff62b5c8c29760ef79951424e001834e7280486ed66a2e46a6484e8a424363bad4273fe367a9968a4695bb06698b62d85b626bc7c2519624bb9a432c7bc7571343509f915691fdb43a36c483d3190b2bfaf492e9688e61db2b9ff0b7dd864d76b555314d201eeb0fdccebd37cd38e0abd9ad4a5e195f25ec8eefd3b6e82ebb57b2dba191547ef2ff96e421aca86987fa8ff31e90556236cb4df078943c1f2528b42a7ce85450a9f6010d8e2d0539657a866c7c2abd362919f1483bea49e61f7c41e80fdcb02284a593b15f6354170dbe458fef87b139813b116dba2381f20ec4e48ae6c8f862f760d76611da2590e53855c3e521c1eab3b116c75fda84f177950489ae478da096ca349241ebfa25807b2fbef9937fc8551e89ebb979b332fe6f2a7ab2c2e059c74443cc6c23324373e94bc799573b60c9d5d351338bad54e7a5eec480e5a0fd2d518d8afd1a7e791425327450e79522a6699b8e7a7ad3c5d7eb99fdb50a40191d946a44813c2f4505916c4b9ccf0dbc6f6c4af9ead1b70453a2e48cbbbb3e2c3c6f729f74f2d525acc051c3e968156c79305a2a012ad7aecf6e270801730ba4fe552ed254f8f0999e34ab63d36d4cd1786841a559e0a613cfa009e622cc2911d7e807a3bd99122f3e50a1a1c7290479d176a9f2518da2d1c8dae5bd9c1127015d9a8589fb6dba4521c70d145135dcd418ddfb7784ac7e673f9142e4da0c75e1f3df30dbbae14979dcea1621ee1e566eb320aecb6fa77952b845c9f268f8a6423f48923f688e403bc44c85511a3cd1a834c14c547f192422b77ab36cc57038909449122b70ef5f196c60b338423c0f1f12424ca93f7c1f35b1a2c7ca7c0d9d5b97633906806ec68159b9283e12764f41d02638403d4acb2a3b404f81f91b5501bd199f770397471200d86cd8f78612af02df97afd4ffa86eb8f5e339d943e03189fe8de376f33139f620f9af6de609c50ef0d34ea3153781bf160b3878f1df596264bce256fd1567be354707e200950268ec73b3342618e1b233202474bf92e7eb0e84ea203f7429ad87eda8f0803505b5350163e4ac9d2d36dfda843907bb7b983e7e616f14de0e589b45d915cf7a4d586d04d7511364c2c16e92be5254b972ee7711ee9027a37443d1f83ece58c527e6f6e693f5e4e030c681d1594d410d6c426ae7f83fe274fa03ee7d3086b6b643d5653f103fbb9ff5da9c2edb763727d6587c5904cadfb31dfd233d54eb63be1f982a76d2bae20480522ff3cb89b1b93f851ded9add79fe4eb422b12248da5d29c3c91661e402be7ee1bfd89fe44b02064cd23e30c43ba70aad6f911f3b9513e0dcc3963447981e3fedbe35cf126dc2d9343ba35d2baf5de06d5c25a2403e62d347ac8ec0520cb441facda3df90845c06cfacb586804f835e689b1761d300da8f98e6689c9ffb01238d40ab57eb493e4d73c7fd234e96a7d3138ebec480b6db5444f3ac3f8dcd956309c9a4be8f06f9ebc4ffd2da031f3bfd12b9b440c5baf5ffd066d21fa80ed18f14cb3889f8581f8037c6ef013a33c02adaae707d0e77aab0cfb262c37b3955e622c7cf30b3b70f9950bfaa4f508ed4eadfcf7bcfe7877a359768e6a183c79326b841e1495d9e4a95844c8d0ad28aeabb96bf4ebfdd64d4ecdbfcd6503e5409bf49bc073a3298711356f01fca5cb2522b93d061d35c9a5b44e1d0aa5617493a2e5ba8b999ff1fe3814d3ccb144b9fdba95bb54d80e1927dec5da6eb09bb2194d2629a70deffaf427deb95275f2b9dc7c352d07a7f08d7ad31b3c201017677ba6a0303b57fd0c0fe47969bbd317956b6e82db460f43ef479b368c484d3f5b60b539176f002feff779cf2b2e501b13519a620c3a9a6f05353f001110ed7a557181da256c8fef6a55edc747d37667fc3608be0a0bcfdc98edc660159e7a2f1f56126ca35a8ca446d1494804d3cc6117c4bf7f1be036f26f16383dde1a7cc87fb670d5d9617fb54b12943cac56da722ea1c78b88e1581a54599e81b5ad79ac3e39a4ff0fa7f18c41c1d68a85832902077528cc9938bcba0d5eff13e27ffb432488b5d08d576a90f085181ad883407a6ce9ea29950aeb3c63cc63dbadb789f5f84bab329a977029200761d4ec7ea74023a41689c6826b061e4cd2c15e7dac2a84298e0c808f8dbf98efb9a00b9be7bef44fb4d672c5c682068555ad3cfbea4a8ecb6745856948ba21e428667b02875ba992caf7e2fe8316e220f3879056cebddfd93dc7f24a2983838eb70e85dc0f7e081462d45e532b2c7cc4b537a2b9ddeb3ffa19790f5cb98086966d8071510891db7e83552dec452b9a1aa1a5ba4aa13d75d6024323c77f1af1a453a48788f9fbe877366299f2597b05c9c2ba2031a1194b16000d78b304b98e5f6f620faa6a24f8a882e3e88df084857a1d5c1b9765e887621bbf5447cec62370cba350dee374d2b96fc063e491ade2d5bc74f5a47613f2615c4200ab67a7797e6f4d934ded53405105e15220c460e381a6ebf47f5b0054bcca7cc40857c65832614a201e0f2908184d2efd6811055127e3a761519c19751b6e56e786248a8834ab803f7ad25ef3b84e90abe50102f46e7c928441c2c51c244eb8b34c585ad02b55d93889bd5ac9d610eda6bf1bc094ff7893a478546b1382748b6e837aa0f9c0653c52725885521d9c2f341de7a7f981df910a1dda7520dbe8b5615213c3cc9ae590d65e2b485532f93c9e27ee20ea9db976ff59dc4a0cd8b020d4e2aa2b0e62dcbf0c74bf099cc02ffe2c07b79131fb0f29c954e3529e20d6b20e5ac7408abf53b03cdd9b31ed6d475b25e2cb639442e892b03576f5a05c625559e3f369075a514baec0472911e1483dd3e3b0ffdc1b4d99fe251e9bd8335af0fba5b4114cdade78aa464c58d0c53a8b7c2ff0cbd12d4526f94b62ac104ec86b3dc7959d22e8021f77973125f1c1262d69f113313a21d821ebd0ca900e54b3ae67721b76512cc6285eda7efa3e7c130ae24f9f98e09e0e721adbdeaf9bee24a0c1cdd004a14d317ba738bc3e7d9f090c2e711e688c4df001cf9527727ec4222b93013bafdaf44c019ad8725877d1101a9780170804d585b651252c3f817db5362435e4e0c3c81ea07ee328b2f4bb311c63a413e210e0d67aeab475 +MD = 7d42d418cbd32cd65e2222ac5bcfd5a3c77caee2b2c231234567621f569c351a + +Len = 32984 +Msg = b33ca16381699941cb1b15582957976e56c2c3e53f61169a5aa4d40c39a342c15fa716e552ec2c35f2a57a1b0841461a22ed966d9f5ae9eb06c0242e9c23cff435d581c54a3c99d74cd52f2e38794b076cdf5477b963cb50b905394462b5654ddccecb4c90e04af082b21dd9e0870cfddba1e34bb504248f1b7cf996b6e16c92fd9adabf4d60a5473b442a6429f4f3c4173a2d31bcc55c71d52c4d6bbe304c8c3f429869a84514a620943f163a476623c9b21971f62fdbbe8f1e1d0da2296e034bcdec91ca15fed3d8a945383c08cfe499128e528ac9093ef05852c28b5538bfc843bd7eda5bcb970c8c221256c095cd2e61761da01b4fb8a1e4d2d3a13a13875facf579019ce2ba6443c0ecb1f620a731a7b81b62ae13f64aca87880b626824b8117bca6762ad0487d8050e7432d83949ec3c91f609bebe92105828f2559d5f7a7937b93334933d1e52dbbfc8fc254d1f39eaca84b5b9d921c02cfd7d991cfe4ded118e8e9bfc2cd0ba2949d5dd6fa95a95aa0d35386b0fa0e1ed4dd5b84bc9db74f1909f1e509a4617d7f2c25c1e16a30964a1301c3b27b77c8261213a948ac916bf088f45f84f2871cc03b8029a5ca29c00cf9ee893eb0d98d3818aa55e07c2db633e85985a131dd1f2c3de554b43fe5666dfa725da214b3dc8f4388310096cccc57aaaa0dfaecd3e307c5ddf9a93603f7e19725a779218734904525b14586ff0ce0425e4efe7e1c06e745c28ed136f6031c4280fd4061d433ef700b6d1bc745064231fecf387015f94f504b6ad8cd4c0652af0cd584502b48f166c1baffd23f27021c0415157d4248b457c1343c736670391f31a6b166ecf24a9bb1216e223e0db442f6a731c031639acedc715893e5ef44259817542099be5f818236e351d228bd595efbfa1353d87747f588d9d94ac1e854987de927c20bb4aa9d71fbcb8be6a1b19599fad13a25de3595012cadf596ba2ebb60fcb6f668ce996b591409dbe5f60e42f7a07454ca443a4370bd7c76ec2e068956eb88976421b08462d88732951ea1df9b878724342da8793e28df6f20a88e8ac64207357c3292710595ee3082a03ed40c0c8429021f12beefeb411ed2de292845acad511f95b1a9d7e889562d1f17c8afcbf5f3a27cfb8cfc714c36812368fa4b67f55adcaf80a7505cf303f2efcf162d3246e493ebe55bfa574b169a1cc0794e1079e32204a1e1e54fb5da8296e754dadc11ac64d042a45009d86fbc2eb21dd442a56a8e2977f22d5d4c3a3aa8d2fd5f25c08b83cea60e94058e8235ddd050646b02617f8285409ef210b3b99a348810bbee327f3b81f33cd6b80eb5ae8dc974e60b5884945c65909acdc75def6e7d95eaf511c59b68eac109ef55aa155ce19c603ac02bf35fd9c8d3bdf5b61ce356654f7fa9d582cd6db6fbbef781b6c02131561b28e41422059e297bbf40b755aaf565d88b5d7611e485388184eae74a10da3427033b8b2571970881948c2327d3dcaaaa069bf9e8f7c25cf15e343b7d28fd86e8df90acecc639fd6a1606f4cc69619a6ecc3f62b51fe4b569140c37bbe221cacb2e820dea4bfd748fa43fb0c5e44ac1914ca65508b562fe6326b14098c4dd7c68709e22a0ab580a7cdf94cba6dcfeacbc086f455660d3746a06e20a965997182b36338f924ce02bbc18b4c9e1abd3a8497008c8109aacd408451cda2718d52a9dffe0b951a91c54c7f00e1ff8e98060b413f131d9cb5589a861a053ed7b1e203b2e3414415873222ae60f527f1e7b529674b737149b7401d4dd3afc3c08d8a57d519c44f3d36af04f7b46f5c6a33afa6b12d92c53637ec918283b37a53aab06fefa87afeb928a5bc020337e721035b4ac6ec5a618bbdc6becc33f9abb98fbe11a9994d98b2e57d10765535103fdf23dc4f90b18c71d1356bd4ea689e19c41a06abf324674ff39dc9fcb2511eec4f6e26f322819010fca16242b0ea9a9cd22e159cbee6b1b9dc6faf3b23735b4fdca5ee5ba9b1b38fc57269bd8d66e96a40600825037dbf17285989dcaf830d910d2efd2e2d293e16b51149ed8ac5d1aa961aa6edc9d0d9925dc521865f697dd96b721b15b7d179cf52e4ca7baeed9b855dc3b69d18c74652051a3de23a0df3507dd90fb84d91abe02754b30f02c78e221cc201dcf84a507ea7c0a6974857b61ecbcca3befa511d71b9cace508c3bf4aa5b814f5372413d3ecc1f244e9130106addb19dd0c3f918ab92ace1e756321344a26767a98d9456bcfb9f7eaf1e7e475c3cf1c695b271e2b53963b57b689235197adc1387522ce31dbca87e61f62ba41e6ff5e6b6cea1c3b8365812b5c845a0506a481995c7ef2c8c97a2ea0d211d6fd5fe24c5da1f7105dc12f2bf3d80319c12fb14427af6c6782f15f58b5aa83ef0ac72e52aaaaecaef48549886ba98407387b3a656dfe799112ebd0929f192746fc951a2dfcd8292c82584b42dd516596bd61d671d6ba1513db218468c79e7a9335426c2aaeca3b3d99a2aad7d350463ce28bebf5fc72cd445e3ac157b9bafc4857676ad54af1a136ad0cfeb3e826948e2a42017e39a900c71e804dcbffff3adad56cbcaa5bdee9cc2effad638664eeff073cad5728dd5e008eaa504204cbb4cf31eac8364bf27342b1e34d63287ba403fbc4463d4480437541019f6662b0d899ef3a23f5b5ccec5eb850453f68db52319a81727d17225fb9b83e7195943f34cf8ff3467503dea364b4df2b54a214880c45fca8b30b33e13266a97d4c13d747d476aea610c0a836f939e8664f7eb793f8908e5f5bbb559673deeb19165c09804d45c4c96576aa2580b9f49c8c5925248b0cbf0cf381d7ddf2737beb70e7568c9e7fce36ef8054dd9fb79c2497bbfdb8381d174807096b3632e6c46ae8403ebb4c8723652b9848fdaaa537a50e3191bd94442f9702bc602db98b5cfdd8f142aaebee7cda8608f6d436156f743c3491a30404605073155722fae3be3aef74d2b9d128331d9b6cdf1fc68aac38ce4f6e072be0322ad49ec0b47b82609888358f86b0d6de94e83e722ed077666910ec9768506a4d7ca3d33d60bfe9ecad3fddd99fef4ce7d6e8f8408ff86e266bc0869e353604facc6d3d1da64c7caacf82b83144012cd76a0a14dac182c184d749c802fc2142d2a09d46f1f385dd2395dd5f37317ae935b4e83ea1521423da22090b363bc6965d8fb07b4ae7106dff96bc5d5be6d0f47b4dffb024b03107cee2aadac8528a81f3f0536498ef50b19738ac2d0fb297e120abbd23d57a4defbb8f9bb13a0ed1a85e58d27d5c7aeb4a72f23938c3433431ce34ad04540eef4e288f5828fb9f504bc54fda301628248b1b59c01b27073a68ccaf3bcbf0ec8995ae686c9c9da27b1ef14bb7275665b11618e5fd4eab8d1ef8a44215f56ca19178b5b145a690a6b6844ab315cd8db2055dd41d2d4db13356540db3982b07bcbb49c6e07fb1652a970e3a3c529d2cab95d4d565fc82e898751d416a4eb7529c5b9b5a8c77578b8c912f584e1a00d3a0d71da556d7a8a22affb6e7dca634edcef6e0090bc903847b496a2d4ec8b2e3306d8acc763b098e795ab379913b1e39d311aa2ae4f13fe045044111d4eb0e0bd8bdcea34ab3300df21a956f1e89fdb737306c68ae6c871f986636be66ed7c9e185c3bc22accb69123c3cf40eaff3de679d7b92adeb753a2d3f3dd7b8b6ca91a6dad64b1bce3f7b89ccae3976d276968097bf2e9ec4e301a861187e1a8d50e115735dbfa67959df4bba454cb3b7f0a8c6491ac3e5dbda6d73d53d88945b30613438a0404c15df3d60ef4a564dc829bf419cd6790b9622269584f41cae8933b80d11e6f4930a9a3cd152047eca6be881fa763a77975f82d516558562f17d218ea8e7790606c15285a5cabdedb40af796f8c18de6119dc322ff2f3783e4a0c28d0ba09f9c2aa0cfc0e441bbca920c1ca7436318ed01b7adb457fc53a7105add5b4026a1df8910d894979e483eedd9205ce44623b5f017083426a321f5fb143ca04f5fc7f6aa7a37a9c5c9aa714cd9ca5ce250f56666249c49740ce9962f34a5053e3558091544b2a876a9298a3774e450456bd827e946319c4a1ff3b23424e131178f9e4253d81239b2280fb2361234df167e122003e58ed4afc48670904ab8cee254dfc7eb9c1e03822da210d21b84b25c70ec7a3b697c9aace3ecf8cd10f181a56e64c065faa0afeda12ccd92f79a701f2bae5d193bc39648646b7372dd56f46ac475564a595ee4fc6af310ff0e3ec26796a0f026c12b6f8b2f4c090818adcf383e59b02020224bb67140029fc83a503d990a5ce9647cce7d2cd7e1162bbfb918c45af872b9b28c239e5acafd8e55c1a81c33c8eb8c7d5a27445324247d545b103ebe53c58bd64e4bda8b929ec656beb107645db2a2f7bc905d0af9bb76345d2b94ceeba3fe5839370b197f0cda06ee5f42e543c80cb29bc0604289627e26666eafd2e8937afff6ee1a4dbbce302dfabab6fea1b53476a0c03644fba1fdf31ee37512721e67922d78f06f6e6c329389ca49f79fff800b7397c55878005b632f91cfd5afca2dda85de73c7bf6e46ff4498e41767305a38bb4df7c52808003e3e80a565ca22349fa7278d9cd75dd63ad22b70a71ecf29c620ebb3d53240554cf6b9e008e9abe5a83b5b2538dec1490ddd8bd3efef65557e4c78e0cebf30c055fc43660735efa6bfe88323e1fb20073d0ac1f73700794625e4fc68f9f661aa20fb2621aad575e0aa56a56ee05604789503d4c2c7799363869380329e005a7c76996bf838f1c5fc322eccf07d18f404dc70cc1ee6833c1668ff0a260504a39c1f7e19d2fbb368601f18fd90ff697913d9f8b2f2de46fac792d0a52c752bc574e35338993941e57639bb4236b0701a0d55448d26f5e958dccdaf562c389d476a8ac0d1343bc3c4a548c0a2cad6565f5a18fc65a17494dbbee144270e9481b1e8db6cea8b49628e5413ce2635ba42d062eac7424da3710dd596361fbad2ff8c559f008e86aa45caed638ed45da45df68d934d2d11c9a57589b42d461939415f199e23c20da89600d700a8b62bdbcf5844da372dd52f5b9b4302d3a511136cb29ca07e9008897ab87ab2c3d487a9bf7eed892d4b811eb9086949cd438ba6ab0e456db9ff5f961b7b3e4187345a5455f1f266d68efedce7436551c629703c24f97ecc7b17fa17a1d08b749ee08a25bb38b93adbfe32b10ed49de2645da61bfffdaf876ce1c1543440c914ade0016416dbaccce3a306e756447bc44fe9178b65a23e6435649d94fa5260e95f3aa559916331e6978662c5e61a65be30d4a9d67e6f942c7ea974211e8eb8bb59f8604c5157b24e9fae2f92e7dec59aaf27464371ec19a6eeb63041c67c395246221984813f96cda22353978019021e73e9d51967a1359c2e95b73d1ba54c76ccbeb84a47a4452b49eeb81cda52841325223ea1871751d4e64ef35d449057ee93d624e6cb0c27303b1644681c11b3406cdb6923fad5d318bde7cae869c5c483447147a03602a4a420a3e1c56fdef76ff11b3ee6e763252e5b6a2628b4cdf9fd879808bfb00b244ea29e7679fb42b8665ceaa534774aadde69deee634b2f602403524f8d60b10ff7670eebcde7c45eee54508653d111d5f28f4c0ae256735fbf61a704506f7bcd6717fb28095ced51cf8156c98c1f40043074bb61edfe226098489f105105f1c6665b6d14758143f9d18c0356278660a162c133ddcb6ac3ca75614359d8489c62bcdb6d99597f50bfbc1d60156c30f8164e1dbd65c6c4de051f549ac82d63030a303e029efc7d9c0957db73eea34590cabd315fe2 +MD = 8ba9a76cc804d89ff99f96fc6d3130e4066e8ce2ddf61a94db67e5d7ac9bd3e9 + +Len = 33776 +Msg = 9c354b967e201bb8a63b49eb151a6e76c45df8212c28cd470bd3312d66e2e992ca37a087d8868b81010a49ad8d760d83e22ffe9e03b8decb576dea60ac7502cf7bf20a7a6d7a90c91fcbaf7a22ba3339476dfd7119caaa61aa2f6f72936447c836ce511746e573b88ae844fcddcf29c07a81be41764777328e80870c239700a683333c056aad7d75c9c7d0d8c59b373f03d106b723158e668ac8f9d665f67590ea8995ede1bcf32964d21bb9e307a4de6bc7a07b271e372427708e77606aeeaff4382276b4f820fbe36fec453dfbbac738c953348a48b994ebde0e981cd9b22a28a8ac49ea4b4b14cf080c24de60bf1ff541e68a557d5edf607b41e0a22d0a2a0f41fa0d8b9cbb9bb00444ffcb1cfc11279622278fa46c2d0eafeef8f94c3ed72f6cd66ba0d2b9b90ccb5a7e0d19b9c25830cfb040a52ca57ce3df8729209658138f060b30d78d966dc51648ad3d3e5d0f77b5d07068e670327dda363b8f59d64014539443927f595a5a4206b372d208d5d39b2d28d4e2b5b8e7a8ad3683d178406185afe1ebd72b5cf2a45f259fbeeb31ac4a6f6fd3679d9787119322e3446799e0640313cadc33faf506fc0dac4b30ab6a8b3f4e4dbe5056c7dc900897fbcad6f7b739e017d79abccb2e847280befccb752445cc2830f57d0ed34eef863eca7c1048f851ba10872adce4a05d05627a1a35dd28f14d03b594c3bc72df9a558f1592dde96d9ccf23cd90f2f8d5227ecf1f138090c5a47fb7245060a7e0ba874029e53fb33ca35c952c501f33e2bf59266275d3275115ee24b41c8793fbce1d063e7136ffc6b8fe06cf8232fa8cc53ca56cc4a0929c899623cd8ff8de37bf5f08de9d8a7514c4ff9e3f90f4f4dc1a6f74c469ad7caee6c1ddf6117d319d73956f90d302bc2dada58403e02dcad9a73abcf2cac28b9016b579b70adc3433d30762dd7b677d195d39e1a3dca4238c54e5a57f51a96749ffba2098e2de8e03c7fd0a4bfb815fe1ba02dca8ea23a8fb0ab756f26529b9e18b1afa22014be71538be8e64bc180b8cae4a9e9974700130aff9f8d36d092961a11b2edcd0ebe96f0c9317b026f4282220574ffee154d5332cf4b2abd3125ed02807e54fb5863a1b2dc4cdb6a2dc5facf77315609997cc0a6aedad01fe0c01360a24460119e382218199d7fe969a58301de41b4504018fbf502f105d56bfb99c2ebb7a7c65cb6a87f2595e106bf4bab979f287388a5ac65ac501044743f22f097c13a848ff069957674e89758ab32e4cf3e782be936919e1b3aab1482d6f0b85dc76f9eb515cb999c7be81b4599f5bf37309336187f72e5e01733ee77cfcf418362a95efc1956f53fcf26d55427feab5e1a2c3a8ceccb0d897a4d4ad986292cb7278a3dcb978658fed3276e0ac1c829b25f8591bd0b045585d859a21ea688ea578a84b38a0ce435482c6c4deff3fccab28531e43f56b95e53b5db9cbd8d890ae3002b78dde5fb0aba3f57ed7a2ae6fefd0fd3aa7a6c4498719765833cb793fef83ce0c62dbf3559a3808cd51ff32146f063dd4d049850946df16a0e22c12446f57537540fe52da2c2947d8d67d926332b35a144448747c2b7586b95f616c463796da18aeb143e6665efac8ed84980340bd9d238d095a4b3dc30eca32d44fee4d26ab1d345c902152c069c41f7c0a9da10e4e2933f6fe1e85b1f5fbe4eb82e4bbf10ead5a65ff35f735dcf5f2cdb1d85e8cb54dbc752a9b09288576fc10cfcf89dd4bf0a93559c75da69a82f0e0555d7d2119b8b2f0a46dd30e046002aafc58bdd4a90da83465828dfcec94a11bbed309b4c4929cce353aeb4dbbe47e21d22661bd712ce0caed0b8e1d1a538ce7b3e3072cfc020377a5ab57cbf227f9dc19e27c7fec77d760b70d68f36ce639adfd3581730a306e53bc672172f154fb45993317045f14175c8d2e2465297630d364707e70364565ca42175128ff910ac319c23933152b28283516c95a9b2afac3b03d070bc7697044fe62edd76506b0be6336eaf455e5902a776e5fbc082b1ee3a943232c07c31829b9f1ff666cdd749e3d38322f6669d9cc1ddeef72b9a0249d172bdabb3c7ce4e13b6b8ebd593bdecc70701acc91e08a75ed0d7f64f6b29558c19c34a0afbb5dd44c79a3c4774a77aec485a9b41e722c8cb1a41a7a0789f77b703f3ac3a8a9096ab4c345630d32c6ad0020e8cd5546467b2f4ac59c334cd570ecbcf30d6e6e720c3af07c82621b5432eee8dd007d8560a930a88ab2c324b49efdba68644b312020a8a85009bf2ca7a354869236e056037e7b6670a4ff381e6d6be19fb2851a9a10c495cae06c8d4969fba10f55c4e2b562da2b7f5a2fb19a45fddaa2dd65536842575df1efb167c2edabe25a46725101bd139fc0bc9bb6b18e7c4d79ce3301122028a8ce1fd6e298962bf07df232ca6cf7ef6b3ab38b70e9b0b1e12a6e374f2010011f6756222555cb457580404c7580783637f6254606cd13613fbfa4b9631b7ca869c67dde5980f6bf166917077bc4a9b0aafafc15a1e220570f3f5700658bcbe62ff37d53a5a27e627d4261ac04c0f0246d501e4069b23d5af8b371557ef6658319f43cc63242cbf65213058337fdb65c2800750f85c4d331a222d900d5e6b247ced3a48227e845433ce2ebd43d02641e8210e7c91ea04ba5b694774994e21afaf7989ccead1d5410e4b9fbe73e576033238a5eb85bcf0b7edc123377e07305633b490bf1ec676027f29f1d0361851463b475c12265d87d84bba2f5d4e41fdb4b43f0db340b51d14e0d9d3972ce13e675dddaf8506343087efc4fa5a6c571047ab794f3df33600f4eddb9377aae89403345c0ea8a7e991336461e2b36aeeee8b83e3e3b3a8b1e82ef0bfdff6429708963952f8118de60087242196fccc520efcd80f59b8c3c1292f83f717978664f29ce7430a441aa234efb98475ab0328e828026c1fb1f6dc4a833201c8efd8eae883c8bc93b4e0b674d99efb0d2291ec0079ad8aa433947bd2a665706243dc8150e7582042f8728b66d13ef5dc080b13fe8e43db95b23f284825a8c37247e3d0d234000e966342a97163341550dfe12928b23fef52b2595a116d766b87709141d2f66ad7fc99d3893b0bf8da09fe86a415a22c2679c86589d50a58d90032676ce9ab032ce400a7b31a3807a476089e0d5bba83215949064ff978baac7b21c8ba7cce337deb4c21af9573eb15137289dd5187cf609fc89e14f525265666b357a302dca63b80b0e3e7335c1dac60b0cc8c9d867b54bbdbaf716ebc2657315b76cf1262c5f632f360f28a3d09cafc67e8a39633117e1bd6bccdac9a353f99aeb88731dd0d2e70682b49f0a359f134fc60bae21a2c6d5e6e48b2654bdd6fde119f73d7b7f654d7a395660d3b68cfa8e2c72b07a81672f1f6c5a7ff4d89789d289e0d7a901c09c72a51cf4641c0b6c6bf8e8c5d698a5f54f4c616f11bb3da455826cca0d1e8adcd50c2fe2272ec372ce7194779dad253160cdca7d132f7157524ec39d119e6c158db7b6b282b65d139fe09f4d378992ea3935ba3262fcdba9b1330cd81c480d5081eedaeddf7a8058c68d30cf0cf49229c2cc5b1466ea22a25a7a700495e5169599f9c31aa544d5472bc0708684b6cdf5e3dcd5ad88c0ef4a366a16a8e63d2eeabd1f98c13cda04ebb7c186f90896ed5684ab50852e48e9aa2b4d264c7618fe59d5a9826a0c04b44950d79bb1fe5d97548d82f322c248b9c92269ca78ad3e2de9c9dfa89e7d8c8d6bdf4cd734d0d375f8e6a9e60eaa8906af040828b5f37764a2810933e4f73939584d66610ce4c02f49786852d150d37965b770688ab08a4b8de66f4ac5e2d25d18806e62c0a4ec6d4f29075ff11aeebaf225e9b3804c4089b1de5916c8a620a4b462ab01d9771fd613e2cd34f872a1705e34bd311e2f61c717520ebe75abebb333da6767dec420129c8c04fa6ebfb543b2ce3209ecc2b5acc52bd76b5459fa359dcfe8bb57f5b8caf30df2d8d968f3ddf5da9264726b03e1c54ffc45ee1917d0fa2b7826cd71afa61e4fdff7c3d720e32f4023693993150d1fa8c573ca51082c53d55dd0c7a0cd4d2738157eb373070068e82e41c8a3b1d9d91d791e706b96f2afb5dfe0cdead96815b2db9632a46fdaa9bafa13a701a0edfd95626d69cd89ca17b3487f67b79d9ef1a47867c7d21f19f99ed1085f17a9f092fac6893ce1a95b92b7ded41e6fdf98c2f53518fa65e066617cf948774c968ba133ee99710dbe4e28a9eb08797a68fd908f5ad253c57a69e83cbbfa77072e65312822c691bb8f4ae171b5420140007664592fbc5b5bb5c996c65f46e7b238274ac1aa382352e5f8c6f785ab3c2a6eab453bfbff998d592e73022d5550b47d78f4e6cd16af3a8800de24a26bb49e7c433b1d08c295c42d4288d86d4f3a75c501387fd488bdda400932de56a9f105f0e74ee79c2ed869faaadc31665c2b5dd7691d7407b8d69cd5bbc80ee78d79c8933e8781006be9e2881177f361a2add47d59acadaecb81e70ec0aa9d9e40d64d2df1edd47ca050999f1d6208a64c47427d79ec1211ec4724b4bde071c3ea90fe86a788c657f596f40776a4567d80820fa070e58c7841afb98f5d70749eb22d4265096140db93425d87c545c72e66e4a3aee79f012af2410f6745648c76c1378094be7f2b4ea2dc3be9b24e420028f7666f85235b7028858e0420c3a3953f3622d96feb6df949edf6f3e4c6ae3deb43c1abf37880920b049e2e9496a04153b08ffdc4abf024b1fcf66e04b5f52bda4f1a29d8a65ad8c245a8ac49e46bc3252f2fc864c99a170291a221b924fe121aa3dab2ddb6cf8976d01247e9b5ec63de3a6a01f84c5519633464d6ac19b13cd6c76a0eaaafc9ef4e2e46c719120b68a65aa872273d0873fc6ea353859ff6f034443005e6992f5073e6aaf48301b01ca41551e19aa39b6ef6c6c861ebbbb5755ca0965e397ce9f50c80a895cf8dc3c501f6cd17f986f55079c539c88677d614776603e34d61de264285a774a5bb2cace48284dcebef0061acf15f50ffda4115ad1bdf5ac74ff82b3d7c0f57ab95d3197643dff718e4a3ebb8d5a2c1feecdfc02549918c524f1e4b24ed47078c22a053dfc044322970c634c5f66be22ab6965c08778341946838cf1f60b94cee6a7ca446811c53c6985185fade207c2c3f4f337d2e1c4135a22fff585ecced7a764d52d30fd02396662d267f142b57ab90f38badf5c453de05e923f46ee8b4d74dfda6b0f1c66a42e1405f7d20f23b50af68adc054e341379a4f831e197567adf772e802af68f0711173781c8bdff0c3a698e1ddd3e1d1e7684967fce6dbcfa67d9660f4d21d7cccffafb883db583dab7d696f2cfb27cc9777c016b65d83b468e64f56abe14cd8fbb2da69db9bc7ecb13ac59ed6531bf9eed09ad97506d3de9b3a871152645fcaa532ddd14b5093c37ce793b703642622957ac1f8616a3414e88225da0fe3bd1b7288a138fc84248bb58bbb02dab4b10d337d1bbba1100f20f7c511f90ae7ce930cbb0de815bee20b032f24c784cd228371e292695e80cac86f0b33b66df7faf918d30828bf87350d0fdab84e2937e24cf7b00d4cbf43cfd5f85c73585d9ca91741d97c3f2266855780945edeef785a306cef73aaede0840e3cc1b929045d43b32cd4507665e33ab3ff65fec1011af1f778a8aecc0fdf533de041ed6f8ac2309684cc6c15b186bce73456813d85a50e68c4e2a5fa4ec9a3288fe5f7731753d888efcab8642dd873bbc66ecd9ba49f1b4df8a5407cd225db98efb4bf7dd199a45015d41caa0260c8f95eb6cb2385927f6cbcf96799c27b6555a8b62dd5e31bfab8a0f5803157a62167a334631c5105a28db6e7029a4654a82763f32ac2736143863532cc3f5533e7cf3ef27ed02f81ec7a9176f9c788360cd6c8749c8daaf4e8837e95e81d238e83f7d6f80285488dc5faf3af34 +MD = e106b1dc3882faa7b7f3a0fecabb21b5b9f4474662318d7102f16ea42b527413 + +Len = 34568 +Msg = 3c346f85602ca0ef6e595076518e5a9d4997a8b7337099b50bb5a53daf5a43fce69c0a3ca03717b980dab0b097d8263a732000d8586f554fcdc47ab65a15decd914031904b44cc0c34b14d728a5d816a215988a9ab2333c6361db149f63e6b0645082ca9e8ba859194c670e2b08533d55d2a8753b4f5fac34ea992200a3fb34e0adc42aeff010bf0a701602894b903242e7b47fdfb4b71ed1e4e64601e7f7e4ee9a4bdc7198126d0754b676dbb5fbbff9d340ed0098e62edadf57134bb6693ade948e31ebda19dd9078acbd9afe1210db03d25f46527936a0487ffc2685cbc1413b0fdd873cc3ab464a8d593f7a5fef7717ed490977ccc0d29ea5732adc9bf2b6dc55220c367c309948bcdc41b151964e8e062cd28f7d77e2608c1ad12156599026d2c1c36db017fa01dfb93a3973cfd1c4919d29fff7b6403c7845b20a87607d791d1f45390bcbf8f44a62918952d6a15a23fc884fb7f67c611ea635eebba1cf61a8ad1a2eebc7169ea18ad0276b552dbd41dd66055ac3079cd39ed5444f98166ee9fdbac5ec83c37f69748e7a29c5e77c6fb25b974ca6723e3ba238b1cfadd2ff75839f846aac800506c225181aa35f05f21dc1ac0a1b4cd3ab52b8adc86d95a1bfd140f0f28becce0df62c77ba77f4e89d62408a1f8bd7ebc722dd9ea651ded44d59377220bc6a38e3731d2f85ae6992b63250d7f982d3e50385201b05f50f35929dfbae51a878e42beb6f9608c10da2c1006b0c24aaa15de51c189943b1a7142411f5fc21faa94e4ba1ac41b05a5197625f07ad2d4dc0c4f03a3f900c32571e7657cef20e0d6be5c7484bb918d4e5cf0ea0af118fe6d2a899720da5bbd16fa30dd1ef16727b41392341d672aecb3ad82a77d9ffa92027875555fb30df2981505f02cedfebaec9b6e420c4f4fe97b1314a3700ce15646fcfb84890c7e2a51c94ee8ce6c4f61255ed9e57afb664e4e978e270cbe3614dec0046dc56d162de91ef30b2ef5c1e60765b9668ff4d9e1d63fd87b783f5f9275cc76593c5f3dc2091cdca27110bc103cb7f80d72c10e6bb815dbe7dd17c699b1263b8e16695bb359ccf1f4c245a8a6695c7c224cea6fb39f217db363ccd1f03ad839557a14d8c680351b4b471dee71395d2fed44f86283316aa72631e8ea61b9ea5af590e71cc4275f40ed281ff43951c1f7b6837251a116f8428970f378b2d66284b8816a8f74f55349238ed423c55c90bec431e0a3d6f7d334244773e3ac384aa1e4752599a093181f35a1c2e3df00d26b6075cac0ea7c04673fdff2921788a998c293a1a30ea8b6a86b88739d4de590e6d277b910a54c92c12260f7efbb6d88519a04651387dd36ce0d6c6fb7d8b4d217626035fbcf10852c15f10b615f90eeb4b4f0f953d3da9f7862743c9b48159ee65858c4e92f6fe58f5fbab550cd98e3a9577ee6c9ba46f98eb3c964af65affe3bfb86f0428e12bbd149e47d24cb2e7018ccd6b3df04c94df748926f5df72bf9fe9413406eb4a00edc1b97eb4622fa9be95c21e8fc780ca29d69f8e30cc53097176b263cd569c2e7971dfa881c9aa36e044c870e87e0b700675e234a239867e16ec8e86ddf75204dea9636db0ffad2f151e72facea02726f3d6e3a2b0c3878deebf3815af59f6148bdd0726c880c2e2bb974424a8ca6e3f807e3650f2e6d0a977733188c7db02ee0f811d7c4ed966024223ae770d596b5a2ad03ce7df1ffc512f8d2d589e1712e1e84a28d6aa7610fe4768247a72d998e7618179afdbdb553595816e1db87a70a0947cbbbe61f35e4749b948976fc76177a2e66f417fa5859747d486409d91d69aa2ad38ac1bcd987db7bb8d766aaf6f7b8d83a025410b0826951af859c3d9af40715042182e5179f21fc3656fe9fe1d638ffd9ec3b68857342ba956d1b1de5532af1a4a9b104b5d44f085530c644ff5e01898cdb55689fd707a240440ee0c72d1ba4fc49d7807cd06b865f8d46ff17351a609bf72879c654bef0f931feee082ae018542a7bc13438805d9a940739f3038e6a4e673e04c192718c085c72af70f38333f473252fa5b793774f6e905b59716291ed541f6f593a275db5eef28bc6300cdf234d5d3296f3aebbc54269cb1226a0bbbfe5512356f4e94d480f06ead48881032ae0ac32d194d81146391bf3e6cb50d20d435e898067be4308e6373460a4ec87515399971c431a61187b2d3a9c0878bd1f95ce089e3cae283f9c0cd1332c5452e0ceadc940a87b93842f2707fe8422643d0427077a1bc1e233580e2915c7c24e1f7b6e30056a0390d27e92c4d2e855afafb8f3f0daaa005a2c43c3a4ce1d3d62568066343231ba3e4a8ff4d8e1db1a86bcd8b92a879472787485b5ab25d7cd76cc051d3e91a7a986348bd8abf30678d1ae8c021d497f1f2552456ca4e39d7a73ca331ab4e872d750d799c3a5d0117778cbfe5531e71410470dab6ff9d0164d3f9831e500003a4c857ce23f2e3fa31f635c533ace2bfa4cc7eee14610b4eb4dc37e280688a1a8110b6b8dd3ae0964797ba8b6395cdbd9db8e3d0c795357c483e7c44005b692632dccecc3088df6fe8ca6f94ddb43c05bc683425790288147f594b1a06bf19d14a8af47ac6433ce1660cd9540a7eba226148d44e814f9f91fadb08e71c0a088638b9bc36f71085957fed9c5b826bd49e2cd968de78d2d88f2b324a3da8a2d1cf7dd7aa935b7755f666db0d1ddde1f7c38fa85637d812cf6690dd9380453ff2179a6334125bde0a7eeb53c01d6597a05cfa2420fd27a5e0b2bc5b69517a27e5f90eeaed3680bb2fa95df639dcc1f37aa51cdb4d80dff2b8ee1e3a2023a00129ee5bed3a72529542003f20fece6b6bc346383c5085699fb49326d87c695f423a5201d8a0585a02ce1e1f627374da8736aafcd5ce6d7ce3602c76d4c2a5106193de814bb34b0f6a405d7f493c6287dc216ddb261b9b529448247ead97696be5c2ee5aa4e7dcdb623538cf23be1a0bb13fe953bbdca1b2f8d915bed16f28ba55440c0e72b2804651094a9fb07d0ddeccdeb7e6f56612f6a7af6ab7debe559426a3a21d33a7d7f8dd590d514dfda069758a6405615c51961717bdea24099271d04e6af7764c363b5d90fb947ab4943451cf484f8e240029cdbe69c64fd541ebf8c0a13da8f44db6684d9fd9b5363be7d81a0f25ea61812a421008fcc0a5f66af686ff504a4460c273eb54819bf719cc7ef70318f47967000a9915de14f02267502ddfbfe8c1221806f6d42c7d7ba08abce2eea93af024538dd61aeacb484879ac01cd0cf2df040f97fc794af848828b286a0c473c4a4b8d524372b33222fb0a50cf31a7f7127921bd78ce6d9ac2124637f8f683670c3f25ee5dd7b807f49c91e4d2b82173f013e6ddd84df4b38ce254721c27de49aa91a5b8a19479bb51bfc8eea8caf9e7ec46c78fa76280f11d753e4d503ac862a9c59547ab4378aaaed6f7c4dde4a1c18b946c2962b692d1d84d5c501189d2207e5d7d21d76f25748074a70dde9fa9af428f1d51a6c49ab461dd46f0fcaf7c31bccbb5cdb26210a75b0b6f20275681efa599839ecff709373e9776c65e1626e4d982e7b1c8e6ba91b31db8b24493bb31293617476ac87ed8c31e7426d25882d859357b64874793e21d2e0c2ab2e1c5e242074101f3d36bf783d4b7c8d5e0e07ab035f95c7a1f2d06fdbed2000ecb3291846fa954e7824132155cc9f2f539f05a8316da001dd7f68ed942c2c894ba71bd64e1b896d27faf06ec19235bacde12d6265aa605fefc80d8345c36eaf13a13c4780fe76e3105f5f47c8c4c696947c89c2e73d5c47a174c71935da6eda0b48955123cce318fcfc6694b48ad82a701921b0fe4f1c22b92c9e97ad9ab573fc452ddd81ac5974b279103dcb0df5e02960fb15f308295900979be5f52acae0ae3f0dd4e0c75f5ffc7d622b5675a41f86f821d70e8f0a523e5ec5eb55b3358be9df3b1c89457d41a0b066449cea6e50508a9be0970d47773b282592155d7fda75cdc19fc44d3b8267bb2371e793d9d94fbd6f16d6a9692fbe9ec1c07c4f2f3719b0a743d807228a1946a19b7d986f234b3aa763138cf7e19168a35ed3b2cd099e30f3f20f9cb9c17ef8e9a8a722b8960ca84bae95dd79f77a2dd35562ade1b8cdf6af93af3488905d7a0282ad593b9a59b061dfa5c578d84295578b7169f4ac6caae20e01f6185d8073f40fd7648098fcfaf3dd8b6c7becb14a39ea480e8d4c43f4954b4d0bf091ad8cc8396d6b0ff6bb2d08928ff90a9b8ef181592fc335021c7acf31db9b9995ad6d85e6b698711e5ff1a9e5f995ad4da33535bf6db07336bde798aaf2cd99d048bd3300fb112d76b0f0ddbe1067ed6ab6bb5f064bfecf4eefe1f89edbc97aa94525db6e84fecb6875cfac051d98515a902e061511d5d1b37a10f8f3dfb8c38a6e4c83189988d35b78391ea2684f6285f93433d4075c02cd261e9f9244c2fdda89db36e682d7ceb77fd43c7e39b5a654b875ed2b74bce904bbb0f663520eaf005f79f9c0861244e353480d7fd8f2a72d979b3c02a21c0fc10071034e53c56166b8cfd68eef61bb49bc3e998e8c2ded795c4b2841d7a5fa6abe06d03c8d0e9c735c84d43803edbd50815ee9949f8efea1d02fbad05c7f3469bd1a65134912e68f1241fba60bded1606c4f0477573e640bbbeff99779d14524c553c8bdcff8ca22a3ae54c14e5c80e143baf221fd65a721e533ee7f75c3b3059e59032067e9cd94d872e66f168e503bcf46bc78d82a4d4a15a29f6e9a7f08720fd51e26590d794e7736ba99a99ccbd7d89c696632b6e0ed15e4164d2e2acbd5e26f1fb6ec8b55b648a1d62850af791b266301d25131e874aba25b057aef8595ddce10b76a8ce935155c440253efe17080448da37ec2eb46a084747cc6f4bd1ac99bf8131937be34a40e0c11fa838b3fafe714c3019173cbbb316b9c5a61fbcc6d7de0b142b55b19be60343b8d93ffee7cf39e1922c7076bc652484c7d5fc813931dcf792c2d484d2bfac66a5349c6e7ac11348d298c308e878e11737816aa570122cd5321c80e39b383c98595cb67900ae8dc075d07749cc88ed0fb93ad2b008035e32767ae34441ea446749b416a535d21a06f08615efd4ff98ccb164cd376d8fe17dd470642d53304441fadd458976c6388ad70c17319e4784ecb491d2921d124735d09f8c156bb4ccb6e13abb7c300579baadd503d5951b31de37445b56a3350ff8ff5ae382e7f23e44914f01241e1a4e14c993643235d5101fbdeefffb7c529c25c534d2fc544329598fac8ee78d7f3627ceb9a0de0cffb02fbd04190715058c4aa6a002e83d520e8430b5dd5d0aaec27231aa424f9705829cb9263ef019c840d6383edbed0f996e53290d74eb1213637276f7e0fd408117d546c7ea4cd7156a66de63c6614773c934dd05ee283067a9a72324d56db5fcd067ca6ba383f977696b2db16afb718b9fa7d151817ae1f5f59eaab3c82753c35cd2c873e32bed58be518aaa32021a4b622a8a530789a358e7b7921701a0968f0d94d58331ab1f53d9b899a0a41bae3da14b7c9cc8ab00fae0806de14a601aca733c562c07982bd36c1ecf4749aeb9cced793c915d75677680978284eaec4ce02e17eea0ed598f61b5f280108b41a99397322ed32e6f5336485b94846bbba96a8ed5e3b45b95b68977b2706ef16b1a0c4f14e7d4b3ff60c4984b08626544bce425e4f9c8caa33da501fd04e5048167a1758fec08a6bbfcac00e45291302df3c773d38540b328815ee520b2054d3b3efd9b01aff15f1ba35702c607b374cdeaaf09100acebd8c2e21a1dc0c3223eeec6b201898214594e1402e5e9c2babab0de556291ec542449077c86d780e41131c94c543591b02ce2311d42c847c4d4bda04db9d25c6d9f864cbb98399fbfd5e3be4cb0057410f0e0526a49e6527b236eba809dab435fd0df7b7f58cc68dd116b6e5d1ee1725e30af409004292a0a2e29f2971604eb5140bd5a72d07922664d33a125a5b1d5bf71b7c3387b7a19977d57123a2cc59a6c7589b33a0729178211a21e4c4d5de35d3d60a20ab5c2654b9961e010e8d799d8f9a94c7f05c28d57e620af7b1e +MD = f765505e0b86e82a2b0a0c07a10399635ebe888422d747ad087fd69145850857 + +Len = 35360 +Msg = e139e47cda78e7723cccc68a180cc9799fb741df438bc97a1954cc9a820347d50affd0fb90c0d84da8992de93dd5c2897b06b36deb9a8496e0afaa3513294c638a014a12bedf7f44fcec437b0ce1347011653707b095b98374e43bf671250dfc28e659a9ab0064c0026c1126cc58a796297ad395d8a5f1a99d9a87c6e6201209ad5706a9a049102a80c29ed3c762a1638df09100acf1b2702379978bb842e4f0e2fb58f8e5e20ae83f95f26b4325ac3f046d792e74a28740cd2b722f30b20a1b8c7b577fc2f4da64078e16d489cc4f925599920878dff5816455209896990cf0767e0b267fa709049f5511f8e17d13c4491ee476ffd1869bb1a2aab0321e73d967ad7dd663221e32d191ebbd92607e3da8a17761539fc1f679b7175d4b6ac63d26b0b475b78ea15563eaad0de69f1a653acd54afba722efa873f6f892ba48d847c2eb8ecc3121ad41e0a5ecf235f6fa5c647824a7d725610a2e0ba1b18f5511531cf9224cfd71219ca9606eb92cb036316ba0918e4c6c09e914201fb5b85985a0d3c49042305118b2f39ad487b086108f0ccf2033697f40e1d0e4c113c7bedbad81de57307c39d9214995cd026410efd1d2544f2bd0c7bc60eeca14502ffd59d59196f5bc2394096435e1b6ada9c93a9656e07ccbf4edc302c830a7ff73bda6b59d9eea39d9081ff8231f0fee14179738f4f437b85849fb23e7c8ea76154838da0056a33e0f0e8369abae575815948c5656f01e657d74db60e7e35a589755869f644ebf3d380fea153a001b5030c8606ad7749f57c6f6da362320861b7c4e268233e7acbbd694aa9748b4ca7af81bd9d300e21903e7387e103400ec33369a8f2ee9c1ea3e8d255b6c725cf33cce174f4b6dd939fe30c24d8b94f50b4448d33702006e0639ae4a53112139142a4533472078ca60ab461cbf04b07d41a335809488123c6f31cc7c4801e009aba7d00847feac262b9f99b04918312a4df49f1b4e4d99cdb3bb6a23a0db392f385a010ec832827d095fae157232715c8e9cb81bcaaf0182423af9d8d3f9871a38955aaf4e68964f784fe5c4d0e00bb4622042fa7048e40ab9451e2477d9746b2b0e3f62511d521e06f4f336dbad6a928703b24ff597abc7774e296ef3176b929e0941d066ad405913f338f3f8f718a76bdb7874b117d3390adabe40ec2fe710f03ae47205a4eb914daf3984cf6980436f0c18114945f4eff25f4f22b98f7176c007a9bf94a0ae5712ad7751b5515bf72f1a13ae149e8b4cbc605e8ce1b295249bf40421ba0d130ae16264f3515ae6431a89fd93a9adf0dfc7625ef80b35ccbad2848640ec66b42d5852a4d209f2c9b7cfd0387a7ee0e039b1f9d2fc7c8572aa023d9275822a0c4ed612998665a560b5ad8146bb1ae3b3caea8b6cf2ec2e3162a983cb6831e385eff916c578eadf65dd3211baedf402f6040f9b5f73a09c837546fba371720fab712fd3bb32102d239efc06077ba0db21856fae5d17505ce36259099d39a92af782e8dded4a6c0b445b79d2befc97d8c0cfa938d82661ebcbba6e321b196db1f485b299ce1a54e622c32a0c43d94f984e333acf43595bd5c6ddd519cfa926312d0a2b9be03a716a49468b2728ba3e763450a2d63108b4874f5d4c050d5179250b80a258c61337f442662b97ffe7fb0f1dc85fe223bcf29cdfa9319866bacd0a0a79c554e24d1f10889279e31c0afbdf64daf0779dfe9c62f25204586e3d985cc455f314c7309d4ba65bf4ad1f9bb753a438d31b0246289621e852b986626199a3b5ba2ce776491206433a4a6d02c3f846429620e31c1d92d8ccab2041c1cf4d331988e1b57698e032c8a93fa6e88859e588a83dc2f8e1d5918f5c4112c427e3fce1fdf7c3ca1342a65cc0113fb5aae4ec8b87d634552bfae69104809bf2020a5bbf77b394e92eb5fb802d53a9e27225d5cbc36e89c9326f428222532fc3f40cea0284c9ab4c61c68cc33f7b77f794893bb9d98b65bdcbaf3fc3445d50c26488323bb38e697c52d0e4b674ed2c7d78ab78e638a14abb2e3738e4d8f39165d9e8aefb729671e158819daa6c4d39eca4f937c16f349b49f093b8575eba8436dacabaa2406637240935123f940012bd900ed2ebfbd9e9d2a94148ab44168bbddd8b0fd0ab723baceb87ece67aba6978c038e4b66cf5b8fdcecc6451379c2a5358c5f8f7223ef1f455e6783f9eb08096bc13e7c1111c8b13b79195d997cfe29fe2f820963340fc92fecd5e9b6e96faaffa2c469ca6b2c2cd1a4d57b4f306471bf29df12e6d1cadf13cc90a8a68d25a2cf0feab998c5d12726d3c1463b7e3ca200e13f5302e2698a7a656069d1c07118636e76158407fdcbc06fa667674ecde74ac16973bf5034f1eb1f0dd440689a34442831249419f94029e14c85db8960662330271b2501733dee625e90fa6ee920f9a6e38fd2e30dade9907b499e153d4716963ff33dde6e950b961c4607bba6010a4f54fd464e803a86e3fb5ab7dcacb3a85c7aa20ecf6d22cb230f9d70361902008a4b17f7409c118a44936231c5f5d263e8a0d1a0bdb70bb572ff3e3cc6894862c19285eda2a7577d1a0d0611b75fcbcea37927fc8e957952e9b4d0735540feb85befee305dea37e5cc2ff0619c33c771f5cc4d292c4f9428f1f5fc1eca844a8bc02bfac957add74cc4c2c8295bbaedd54763ea2f7d2d83c1f38c6a430c9e5461570e52bf7a385f39698d356fdc396681ff04a7176b766fa5553fc1ed05d645c58a5f9e1aadd2f835235ae03d07fb59fd87782ce8dd747f5a81d7a9219c73453cc0e885e2d7c4cac75aef719ac447efd2458720aaba6ddc6add1ccce9b9bf7b50626fb020e257fc7776158f8ffb644f87a3f82c66ecaaad5dd3d5cf4c44001088d6bdc7dcb5d0b6cddf94e222949ba3a40795f7235a731bb9c9cc5d53267f2c6c859a711c387a2252fe34135d773410b2db242ae9ec104e0829c71c044584f585d7cd56ea539c658d39bdca488c77c038866e6cc08ac86dd15a8fb4698a56965a35201f4dee7daa06f9f6aeeabcabdbbe703b66b11ce4a19dc4ecce8add3f35740559744ef1661746a7a8684bed1a88cc0153bfc38aac11f3cfa5126d2785fb59b041fcf3449fd4d4a99ba073080af0eba17d20ffbc68e65be384271c4e710f939fa06046d0700a386997fd6bf6c43ba2b883316b9b60475d684fb69f3c4b99aa393e484f7b21e1fb4d64273a9d90907aae2b99120ddc5d82c6cf66fcd75bc324e5e25a152ef980a4bfc9c7e8e7b517faeb3e01f9fb234f5165cce03d09e8b38b0d5641a0d24110bb2690857ebb7dfaaad783102a4e7e4653ae0ecb6ab93c91661860a3f84d42b8c9ea7f0803002e5e12dbc46facec356a0e075cd089cf9d863e6ec929268941a155725ff97fa0116dbb5dc7c587bf90e20cd97f97a43254ba9a77587a316c89f2e728f7fffa826e4f2cc755bbc3aed6d7d58d40c7c2cca954029ad73f21e061d4077311c37d8e8d2ced7f36f969a05170ef896508ec84e37cfe420c1ffecc106f3ebb73ec0facb52b87ef3226817f47d6e437b60429424c5c17d4c1c3d117dfea1369e623b9c43074817d11ea113201303cfefd6081ee2a19d4b9bcd2a2ab166e0fe3321082be443063939aef23a1c7a77d4500c7fc71c6debe59c6f5776ffd22b8921f5a72823a87b69896dabeb4e163317688dfa3b168d15b1ca6d45a4bdb2f99de75aa91f95aa000f4ce56eb53968bdff85d507d97581a366b26165227fabc3730fba7e809eba4cc0e0709b1662f48103347c3920bdde2d4ac0c6367eba0f21cee7afa7e9b37ba9f500c9b18d5f4c14b8f0ee0ebf64051bf492165a28016f9cf82bb4a5b98840b0321a4b528882d1f1874794e8f3eca8e7ea82dc10acca4f8d852834088e61bbf7fe996ffea672289ff4a52b686cdc0c29933f822a8b89117c0c89d840c6f44fd9c11ab20655b1b2889795fbfd9896d149850492e822c27800d4ad0bdef1946ede0ffabc1a14a5f233d6969128f5c18ad0469e98da311ac584a42e3933ace6bb8d51c5e89a71e37a3a4823756b02d08b465e5a1e8104d69cafc179fb0f475f98603d08b217ebdebd0442d933445e38652412c37e7d2caa6fbad31ccb925f6397ef184fc302e11c3d1a8d043545568daaf22a67331f26eab16e4f83259d53973c9279e775fc00006cf55d5105de8a34cf28fbb1f6f7823bf412ad498360d25ef8e2d88c5563b74fef1d5a2c2f8067c244411d301486ad02ba4062dc7f8d4a4f4f68ca8aebca754f160aea121ccb8dba9cc2f56e365d25d3869006b8848339ecb29cb68f9390d8828436b38f48205a824b371ac8b6db7b12bb5a0f6a1ce31f9bd4e722f707774f7ebc391d105c1f6cbdd205f3dc10922b64fb36f36da31d69e108e0964d91be48b8208aad31a32922d1c3c82714fe11a53eb88f494fd192a750c101971fdd0652b34393ea6fc7ce1b4292e61b1fc9ca770465fb776d0303666fbfd29bda43c00bf4a7fd3b27348eb494b1f84638fe3d1f6a95e41451d1b015a237cc2b09507bc300c01f35e473eb9d5cc3774f1d15da1cb5cad196aaa859337ceb66bb29adaa264c2e825143f05523ef29db8c18ab31ed8a775c74b3f14f5e742d2ac2b795db844b45bf23c2446be6e067ad83d818c5105d2ded452a6702e50c7f90d83fb3708b82a83e03cbea8064b4ff55dcb8091403b240fc7e6a642465ca7531722e8109aa96b87797dd5d431bf1737ced54d6af560e631286e063246f228075171089274fdc0904567317147b1a468b3c2b1be785d616b80548fe735f9943e44d62363a09e71c6cb639928510840ae95fa7435cf1bdae656ff090a1b5b311f76ba002b2672c65093d7d7a155ae3134fae55e7804819cc932d73c4201ff48d3718668930c630657252cb1835e8abf206deb372f1f76ee3d9c44ef38eecd2081bda023425c587b020acbf0777184349b7374c60226e4176a1daeec94eaad0352e072f9e21e386b7ac91a5c249884d6cc96e8d49723b260773c7df9fdfd87376e6462b21858ed1fe6ea83bc33da72efdc5daf29991dc8118d8219df1b304305fcd1da158e145edf6ff56dd94b4036c5f250318dae1d0e72d376eb65978ac9b524ad41ebec5973f33d73407c15d0b9a037f8d6c87e2a6cca72a059551913018f1082fffcd93014a277ec636b3894e1cad3dc07a1b24cca639188cc7648d4d4dbe5d77c10fe9f293546e6406f5d94978aed852ae2f28b108359b7ad8fcdd428e0ce351fef03b19af4d1eb3e4f2cd7c427ad79a951e5f02673f2b462694f1ce7e7f12352608f6b4f274182c5d54c654eea3c42eab73482f47b830755cc77b2f73876297d2d4ad73116bd343dc766461f1bc26857db874a62e23439ec7feda0421b86cf061cdefc26096e870eee21831d0266715687844e59f22fd1914c58eeaed8499e56f6f0e217477b05a112262232e651e75181d698bff19957abf961a225b6e61dd5822b92ed190d365cfb1c2e4511ab51af9223307e289d53a24fafc68efe85d5eb8a34138ec74ca1a870acac3dc99b38d882141c7cdf604edd16eb61d0f9504c01d4b66de4995fceee3a7ea60457492334195066a35e0dd0c616bc7cd5ec6d0c7d2a57a9d6d66f45942139238103de9a2b1f8016d9ecca5fc416cb1e8422049dc952bfce4bc8a38f04ed862c9c148225255b4b3208d2bf853fe0bf4fc5e23e854b1497e42db52433a4660cc83dd45c4d8a965ac4175916c99f3a41178073424e6d3a87f463e619b9de5474ff4c899599c29854d3eec6f4b34dedf97f9d1e397f968a3604d5a3abaa197e65d9b17c54923529e268756483ccafc18e8e052b4ba12dce4d1f6b34028cbcad885f54f5c2be4b11ac8a947aeb9b2e7da94d9ee29f3b9ccc734a0de045ea31a985981e3b07a76d175941334f54a933ebf1c2518a5ed54a4d518fa3f09d49df3a038df5984ad5010591953a2ce57c24d10ff7076daff89f188ff515ac31332e28aa44c352b3cf71a1fe8f9159c69e6af8aaf4a6d1bb2a03f7d4844b5c2a2f863a23c76eb26c1d23b44636201e20976e286bbf17ffaaf6deb0c8452d48afc64f39161edf009a4781051193d0c31bed9728f962433fa3e1980c143fa4b8e97ef1ee2a4fff8468d5f15e08ac878fde2a4cc2fee511d9ce7599d3607b96f3ffe2d41e0864b586fc50dd85d28b2ecb92d5f7bc1f4e681454394acd53ffed421a7761945864e84d7e40ac431838ae +MD = 227873c9cf295ea7ecd033ad887ae817e6264234111acb502bbcdb088917f3ab + +Len = 36152 +Msg = d520072ba3414ab550976e18fd542e33d77ccd4de299fe61f6b102b8077510bda9bbf90ed22e0ccfe2443743e271709d099b531385cd0d35782f787d40368727fb18e5424a83d908568e6d6b11f0cff0bf6ff7c0b49c8afd5fbeff52870c00ced51f13f293a67908b35c56b7133713d5ffe2017cf86e3f60b345dd5f655f415a3eb8ca443301b47801953c506fb004f3d3dbb86ed7abf2077dab5bcd619714743fcb5460b4fa52004923655dadc169f3424366bfdbbb6c99c5dac1c4041c3fc4de40f76f9efb1a4792ed1a0756d40c7c540051968c0775bf91b9576bd4568af125fffc99776bd5f6e4dba276f150b33712fbc11c71f5d521eb3064eb5baebfa41cf0ab05c9b24bb447d547d1069d27cb831c007912ee5366da27326c218aa484cafc4bdc1b38442ac4c34f411d2330e1b04c55d4f75bb83667860715ad53033a37092645f6648800628d03edbf4995219f710755a9a2cc3b98352c0e8772a26d6b008269e1a0dedd2a1cabfe737920325a745f26af2d571a771de980374d49c66fcaa8706454106922568f9bc21b97bde93ea56c9162217e0c248593454ec2ec4a4de08107e6e44d5424f6ed3395c36952b62152d8abf10d5e334a6e3adcd489047371c453bf2331c86f2a1b4e506cdf9fc31afd0b6f916f75337e3a9e5e4642a623a562cf4795bc851d714e9bb45ac7d84fda98b215c74d590a6a1ef73ee1c13645c28304e60197931714aea32a54c80341a74955075c4f13a25643cfe36daebfc0114e7805306afa465a62ed18248a2a81ca387dac181ca9e18ad0adb5b2b0467edaecb50aebdcc2918d9301e790b654f68b8fb16cc25d26b14dee1a1c7770d5666585435ff895f4dff368680061f48a8a31737aaf24b98ff9e9c59d8086967360f940a86a1f3e981ad60aa9c95eebd324060e5fdd04d9eea1a47cbe49a5c92954df456e952a7fb4297ca04cac514437ac5088e85e2b644a90c73c05df9db1fe2a60bd1c47dfff52f42e53da1000a6be0b58099d9b6103acb0992cfbab35f7facac2d03be708677963334bda5d35ba712766b807fa6d5e1be8647527133743251d4da552df6b5e325ed5afd4fab62857e9c1bdade4191c9f206e3e1180693c88094b65e996d18d84cd5aa750514b977839b34117c22be6404001b0425b958b2a7702378974019b77980b5dd7c9beafdd00826ccefa6c63073163f3410a81d81350bb44b8e1c53113a730f6f0cad6198d24776559f6a43cfbd9dc2e96f7f6ca4c7abeb30145e3f761e2119d24bc5a7d908fda55401c9b182521b689ca88bb09dcdf53ade90824946832f578fa081382ef27f3630cd618a08bf1372d64279a3ecb66c25afa9250b1307d26affa14c9d1b1d609b8448be57c3732a942ec3b591122f652e1bb4c2ff5c2adea6bac494312de83667b70a2c85331ca52efeb2cc129e8794d6bb49c880925a88ad4990f4bec7f1650d519858acd7fa37b5de8619a2f25d6f91f6eeb259461584d1148cfa7079b7610eec69bf3932ba46bb46b44accae1f59f2670a2cc3f7fa37d4b41ef200c3a8deeedff4cca4d3db46c1bfc3cbea325be86a7422746b2867360a90dd97ea3644231fa4c00d9a3bbbdc4ba24b19a61f819f8cb6de45b947eaf405433f38973227d233f361fe63bafa6bcba6a0b06ad63ee3bba783fd28e703f63733ba709257b260ae14411bac020579c4357b3cb2f6d25989beba27547630b122fae5cc56078262f0bff3f1dd817b7ac7c720fb18e1ea657964f740a685ffa94b0137986cd2063dae3ed0fd62b9bb0348e43887f737e59c0d52b1d5a986cf6331df26814147bc6539198eaaf62b4297ba15287ff8596261b7d07052d8093e7359ed49037dc9137e13e88396e256a0bcadb2872f76d6df6afb96b944bc7dbb3e35d3f59b7cd6b9fcd124362dc1bc63c69674cb230d20bafc5afe0327b164d43857fbe2b5b9010e4603453cfc1edcfa5a06b46b0725d793ba587ed478615ef7f632fd66eeccd88f0dfcd40e6e5438e2eb7109fd384b6be80976a1b3b356bcb4fc493118a332bdca9950490110fc309c0f57dde823084e268e380f1764ec1e99cf2d3f6e8f55313f9c902cdb709184a41a3db8b273c6feedad0f0f76099be4f4c33180deefded35c7c2ee7e3f99e8599b09512e297121e9bda7e3b561e00b0749d08adf0512a04bfac9f12c1388dc3cb46f0850f0973fdbfbb180b4e2e94f19791150f395fb145b7c26335e9a9d9bfd761d2778e47674cd7b33f07b497d338bc63d93d10781f2703421db9c3ca2cea4c75ad72f6dd565c525785a9200645f67179e7a02c16ce28f0a02126f615d1c37917040fcf37ebdcee1c7e7826d667ab5537a2e0d2d848bc2e610ff5d71982ec0bba58967de3722ed9767bed2fa4b2c7b641ad67ab2909610b094cbf0d419ab462d42dbf896c93d2c2fa1090a0eda1fc331c69bd2b75aaa8250d69db0f3a93cd2cf8e5d3883fcb59291bdedb310dcf894a2c5a59ca6a8701eaf1e9e24340f896b89d338ae0d973227a60394546a1a62f79f611b60e64390eeb3b4f5d400153919435793e39d645ef454ba2675835903f210e025a7dff3b1fa45dfcc48c081f4e4e564975d9929de00842cca9ec3648390dd8bedf7f97f7b484ee94809da1c64d557406ba66baf5d541f9fa95892028bd6efaa98db9cb198e3b418939eb8ae2ff38133394679be81f60b5ceb2a58fac3ce2c8551d8304fadd061b5d58fc0fffd474b8726c32d1ef2f032abb79d7d15d27f7d633e781d2265183b0735655cd677d79e825ca7ee96594a7ad33538691b61f1ca8e8742cbf265c42c58dca7f3fc44ad606e037923ef5e0acd1e8f8385d4172dfc4c55bea38758dc1beef2ddec3a0dd17b9142c236f1a83a12d2ea0637079d3af9e6d0750ba8e466ef139e8fb1567a49d53442098e64e0e13138714ae87e9a20aba41fee6c1fb16c920c0846a918321f589e2bd69310ad08119849d601ffb7e8f9cd6bb12fb268f5eb2459893c4ade5beb1924b2adbdb8b69c3a9d32e8539c99caabdb47ba2ab10ae2a2b9e1d2b2250375eb55234432a9f3b96593e70742f03b08849837774e33b25fcd4fd5d31ab021e05de7b3c03827c75063537cc5935bd79aa1c909cce897f54aef44eda74827bc13b702ea8997da3b4a7a067989108773684a974623be84db8b4ebfb1b70430ddf641cd4f07176b568df3d467bd7f191a5ac62a75e39aa36d0b32e9aa6918768b7143716aa37f82210216e4ccc8a9bcd1585fa91e74429cb2b0e5ea5f264a9fce6c0416c3c399c6a2912a5f33125616a24a5b3cca3e7e16b263aee958576454aecfcde2e3d12be0e323796c21034dcf9418030dffa918ba760dd40e1e622c3c3482e6005133fe77ec9e493420035890afaa9f41481dd62f0594a08338b16b00676d97969553da34c3ece3dfb77a3d01fce877032a02821d68e25a6d2eaae847507928cd389787bf72f38f946fd0c5c982bbd2792fc0e22ea5dd4af789b76dbaf58ce0ccc169ccbf019d947bce6db8904a09facbdebfbf08c66fb746d03fc001608f08bcb83072dd76d03cbd5eb9de005abc3522bf67e053d27feb858baaaac3996be8c4a55342c0db76cd82a71dffbfbcbacca65b210fb8d2f42cda435ff3a8a606c80d113c0110377690f130ffe27578ed077e395312decdb8c36d7ec8635a914af0be84527a7793b8cd3381c850cb943b2dd3e267b26fcbb2f867c74cc27e621ea70084fd749bf624cc6f22e111681a8e88ccdcc3b710d5ca12f0a353d7bf1f6937fb9ba5b62468a2d4ce9cb0edf611cd5e92b1d1e96bf1e85b2f9c456bc2d215e6d650b209bbf21a2e78759fac1a82e0f84ce8f710282af4194d398b46328209fdba2b8c35089a7423943815157e74ae9e230a9ff3ef85d69572028b30b5382dc3ceb59c02b26a98f94b6a7af1caef21973f9e305b660c7717c480aef1f3fb69823b754838626a6ef8c4953508a6fc202dc72c121038c6bde66e3a5c5096d3a58028f4f99ebfa1df6a2840b022b8a194a6e33dacda0bbb914c96b9fe1743c8c907beb818fd7217d1959ef45207abe8634bbd58688188f4dc8f6583fa0ca4e3bd5d244b0b1d22d42dc34f38837e25d976647a05adcc567884f80222baf8612b69ca83353cc678e1dc3a6294ab51ce7bb53945cce4841d4f73cf951ea4a222a9b69803fc11c01b45c5420090324650d608114436737187828f5c48fd22d48e638a0dcb2af4d2b508cf2551b5812650f258369fcac35b3a18c2e641499b544d63cf7304464cc6eb33e4297c8afeb879d88bee7f103c0ade19f2b7a88977eb08b16b10d5d9816267cceb98aa9812c6708f8b820c9146461c8e0915a6461d616753482d676afb6fd1decbb802652516e01f3e3a6dd44ad69c7eee496307f77e11534c11e28121b4d06e6ed2ad7ba0726f918e5dcb62ae8305f1899b06546c0aafb861066da75dfb0d86bb2dd262e9a0c5ec62354dc1dc15ffefc252b7b5e4cce88b6e523062160a302d9a139aa06a688b38a1081c7b3a54348181b8a0b3c78d65d35a3e543db5aae06cf3ca2dbf8a94697d351f5f18320749aeae13e6d57e15cd980f1201bda0a3c54aae9bb247b0ea06c405c23f1e2bf8e97f31acb4a46f2cc9e374165e6c40bd88cfb4ce51be46340b14f938e4178dedbafaf2cb30a7039a01bb719294d1fdc0d103ebab34aeb3381f76f9cb758abfaf6429dab88266a2261c28eecdca74407347ef3c7a809e5fbfebf1edc11a002b069014cfbad369b59ac332d31029de6f9f939a8f826017b290178dbd63fd0038b9e6c2ba1a4b39a2bc9de208a3d996f40c5d0ccd0cfaa014754a5252f943124e920d3b8421115dd355533f76ce012435824c4edc6076c1ed342c4992cb17bed557ae8713144e5dae2c8c5103d9ca119cc90867a6c6fd02a596667966209f8d35d170af513e29c29d0bf121980b5be48fa83a5f1286b7eca463a0ebb6420306d7c8fcba25e6cb1207b829b61eaddd2578e98a3f07e7cb06526381a56b776cb22104f9b076535bd854fcdd197b07775dbe529f0e6f3261d8185db2b16b0802177c4c10992ece0299eb9fb55099615213c9ac22d431b0a3eb5c1bdb17a03decbf5169e97e349fe8df366958655e0395cf01beba9935a6b7c68763a3ddf15d533206242b66700e34319c226f5fb4346919ce521066635fc5f202feb20d45b25ef605437e5aca630f188591a147823ef67a982ecb42a322f6f534b4b1ae86823695b48e8c612ae5a01b597f9724b0676379c71b9436dd367159844c48c99b1602977dcffa8378dd10c281b4f9fe25f8d99fc3e11349f9e45fa55c901e656cb6eb82c7cc73c89c93869563f86edecb387f72f448ef83df74e8622346dc8ae1a919e0f94e9d397e4f2b1d68139ecb89717e7cc318d1ec772e331740372940e239b3387d1d20dd075926e1f8cc32cd47e9fd459618608daa59694c1d2bae9057ace113ba01a5bd1df8a0697cecd2ecedea2553d611456d5e3fb18a21ea1381284bcdf818c2d4dfa976c13e5a3c253164ba1d30eccc27947c263457b43bff1c3d5e9c6fff27544d9419b0e7fc81d4a392a10e643e0eaf0bed571a3e3ee71a687e2d7900d7face0fc42a96ecc886864a60e9207536a285d9971a8ac427b70d6dd4ff8a340801e92b23f09ad62812e42fb6d87aed3b4f500664b7ac73d8708033251ef792fa054eab98b5e52c83ec96597db84554b4dcb89b3b75a9d2b7dd1ac35bd0e9a316cda4960abf9e7641dd43d09bcfa8300b12679f039da9692dc584245c5e88edc22394f56358ee3dc9ad939dfa66cc0ba7b9021aa677d3c1a3ef665e1210fbfa67cdc6cf8ac6fd07852430c780c4d96cf09934150b4b50617f24667a632d6b526e94e12c6751f25fdc09bf561733f6dc4e79a2961a6148d12a2c2f7f39ffff7b3d408e15e243f6ca3626eb53a6f94be22922f7a8bb00e29a0dcf67757bcce0ff3e997490e3e230d2fb4159c5155f0106e95dd950d67246438fd5b76411dd3566d8663ca85278c9fe9423b4b44cad40d0f6f0f19853fd9d541705c655e27a273672718d62174be8d66794a229322b2fc9b9a3e6871aea0f560f283d4fd8eadef9768010c81aa3b6e3dd5ccb2ab121f778984060251481c3d0de06c35bda7781364b5c6ce144ca5bac5f42d9c2b0d6bf65fc8d097b2709e24aec670180d167387659cd4ab57b07feba530f71f61893b0194e5486903ccc934ca1139ec6a3032d40089b524da8a1c793228b3dd0cfa0f21bf45b826d3c10ff5f65d143353993851cc08d2bb0b4e1dfc1357ee557be45acf3586ba3180d1e4d0aa06b98d67b5f6b92e96c7ee6850f6eccf3b01193cdca072ae04b919b993ea6d6baa7 +MD = b5bcde1cc2926424b7d76aec3e6c33b793af22049a5fc8f8cb0a8546231c7cec + +Len = 36944 +Msg = 7eea1a63703cecd59f5dc1eadf5eb857e2bda5b1b6dcb4818fb24f9ac7c141aa23481b1058b9d6edce6dbb7ea39780a9f377b4d557d05dffab9bdf0a15fd1f574277e996f35d8fdcb989d3f5fc5007fb42b57327aeddf7e8c7c3f2327c2d621964df4c9e4a0e5ec9e817d3f8f371977658e0ab4fc6eccc636c924fba0439501710e80bd063b58adce481812e8fe27641bc6124f5a4e622992170c049b509327acefaf0d3483b5c3f342da540d88bec86f69ea6c052b142b26ec50b8798864f69267dc15001861c17608509d5d655436a8f01f958d73774d5dbf9f91eb496f10da1d947ee9480128ff1ef74969226c1170ef1e4663b5eff2af17452b311225e8ec6764a560b1085cc6ed5ad2a13e8b0b5fbd6319286102dda379fdef1b813df131ebc922f6d1dbff95f9e7d3b6181566bdf17a683c134440d36e0647db04fbcc43014e622c391063c4cb2ac6e85dbfc62411e0ce2f4b28dea74a0ae0201c03dca84e40fd71453a3bdbe79026d86dce9c2a9522a562572509a7b488226b44daa4da295d6f5684bdea53d5b47e06c6e67b29f1bca885e5bd545d33ea991d0dd4a7413900125c861fe1c4fc0426e4078bc5aace1b21fa657631102ecebec5d5a66685e3c580e3a7d4d497e10bcc009e131e3570cabc4064e432992b80fdf64ab46510b00a559c987115551b37d7ecf930e7529047d1f8426beb30b0cdf11ebb83256a246aead7a67936850114d4f9a759b37a932f0d72bc81ad8f34f212bfd69729fac753cb357051ba80492f4db736f20525ffccc95001c9fbfd4e99ed49fa64d55b1f417126749f040f49f39cb6169e4eed3cbd8000d0a979135421eb5db570da0372d0773b21c5c56a99ee5c76d4b30318e08ddc1597b48759fc26976b864f8a7c887d47e4164a513a9f9c0769efd4c461719a37fec55fb9499d146be3fb55793eb6a45da1b0b149e7e169281fc688053f668f2e3cf82f915abd77e357632718b293e243048f7f120af5f238f8f721481b45b929509e887215d3cd98467c490b8086c3727d11284c0c53a3b4960044ff7d85c4a3ca271f0e038681f531a51fa42125a4768bd4214a74711a15776077adeead2e480a3047a79c3c3184995c2f850cf711b9a1471ebfcbd4b1e60d961dd5d7225260b13886f1586b68c0fe200d20ac6197d66df864fe8b0507a0c92fcc09df9bcd982fae715db0aa7424d09f2d0997fbb337425698993a7887d05a8be6bc50601c5906008b5f4d6ff03aa107f3a2582bd066bee02e1242a5beef0239125fe225bb1db4ed39687732797ce019157d55889bef442399ec3c13197780c5c3870d432660bcb3002bd6785c662e30f70d2888523b62af60a9af5723e436a07ea42a4efadc9e0073fbe3c83580ebfe0cd449a1bfc5aad216bce4d86acf94579849d1af84cbd944096b1798814799ceeb65216b21387d4a20a8a52d5a943a59c4da8bfb60b8eefc34fbea7fbc34c8220732485b12ee6a6612ff48ac8fdc993578f8c1a91b4e4f978b20f4d462d2e7a5e4be36f82161e2b4622347fc56f3216929070b4f20d69bb4807c9f3d01ac88a9088b75a8c93d86b3a2a73b935c82637359a7d133fe0c33c199517220152c2bd9e70c7d0376dbc6f2390d9bf81d04ffd29f3dac1e2f39a84d5a51f60419cc318714c3c58eb6b713eeb9d8d180f4f527054e3b146410e979c627f0938f8c273a5ef633d7b1056a0e07896b84f490dda989fb42728c6fb618baa6bfe2f8e8a7b6b01fff3bf0ef6f05eb4c681e996d18d7ef2ac66f1d781a15993b126cf6bbd8372906686af4e130abf857411705d65132936159628de67ff0f0798a89ff82332c382e11dd03675950bd5e78f6c088f15a15135de56427622b4ed69ac279b833165c1b8e0ac2fe33a4a8b682463fe183bef2d5567026b76b3502c6d5cf0bda627603333f8caa227a1858f3ff8dfa7c82c1ab1bc59b4c12f59ecaee9de81c755bdbdc29a8db2f50771c4c9b432676b66912ac4b4dbf5ac68bd8e5a285a621f569b835534c6ed924c530d210ffb84b2bc11285083154b94eb87411871f91c2f7168bad34acc02dfbeee6a7f977abce490551b3c723041e17e5e0ad00be2365e70cd6a2624c7794624ebe2cb95d89a69ab040b70c9545cfbeaeaf36a3f3f381319719c350adedb2d47f17ded513ca3a9d5c700d3d0a8264af6d403cf5535abb836fd58e84439aefef0a944cd13cf610dd546034fcf5526376cc442e595ee16b48d18a42719017d20e5ba3e5323b85bfb75281bcb0d82e4281261b9954692016fe76b8adad35ecdfbefce7468c82019dc7b165130d358e986b2546fc8b248f4510b9d11e9b87728f7d58aecf24c2f2419b0b7ac6469ffbcba12446c641f3978c2c357413c1175157c6198b0daf50c0318dcb43450179ee52afbdab952d68d142ad54123bc257f1df259a0c8090ce03e43c7b4f1dc255eed4034be5d7b1f6b51f10a02be4f3ebec6c186493a66d8d25e013860ecf1da665b63879760c641fbb67f2a431bdea25a9b51b03c10d8a30beab9f9602c757fdfb7faba0ecb1a8667cb3cfdab40529a7a210b9e215249b3b36ad5d05bb9525cf08a6f96caa56134d418914ae337916e46e2551a9f06a052f166bc86f99c6eb9c25a29e374f682946c26e4db92088566e76598ea5e36c5c6ed67d6e3e3dcb3de7cb29069b3c765ee577c9e7661b914ca85323dd707e99f57d0f48baec181071247170cef301ff28abda228e4f85428e147d2aaa94228184fc29643b13a94549f4b13053f920611afc521e8edfee0a8f456cc4928b6fa17f4ead466b2f71b81cbaf2de31f8284aaa7978048581c667c4bdaa8811c0c67859071365c7aa02176df9cee0e58a8a2a5b85c47afeff9ed8c2efaefb94ceb7748697e448dd1dcab1b2239dcefb2ab67ea2b3cff85783e7dc0e5de285b81fc3349c73a87627e53c358deaf81ecf434dc61485e2f31bc921e00b7afdbce83e7a270f4cd86414bae70155925656ee8ea07f356eb5f1d839ed934ee95907a1a53cca6375ec993fe95bb3addc40ede5476f2869f0a17b09509b544d0b7d0c70ee8bad1d715d9c160afaaafb0b306a2017fa50369e4e052b97cbb18a63e221d264f73da1d1b3d3139a5485c1a1bd524b7ae2653fda1416bb99ff298b7510fe42b30ffaa51987d4d511e9a29652401ca3dab7f5ca368c3635b1962ad4d191e84e6326728bbb3227c6fc3aaffd7f514fe5d1db808a261eca36893133daebed7651cfeb23ba295b3255d3c7fc4bab79627ddacd73e44b54791a7b40e312367c2ef983ce8cd5066b8b2e130216254910dac8601e6e6cf8c5996e2255a72f43c688b219312c50b4dba8ac44899bfeeac03f720c4ece78c0dac1bdf8dffe76966509f7eab370a1c724015cd2beec5cf30ff6f739df22bc361c78667950677ca0d0295782d5f86cbfed2bbc681285a41448a7c4632ff99bcaf324042e5760c5e5807d3d7c192205f19f8e475f450688a102b86632e1b19be2076b23824578d6e70e6c3630ed9c022ea3bf8a42a6cd6f3bd6af590374e9312dc1a4311fab1e1427d27cbe3bd3b4e5a9a225f19cb878cc473cf3296f5a1ef010aa65a94118df222a653552175c1b3505036819d80a6724559e3a33d121b15d1d3a2618b0ef2a75613f1c8e3df72d54c35fdc7f7f1d370be982db14c33c5eeca5e97bfbc9ce9e825ed898cf2a3569d95710197f1c5156e765735c48d02a56036d40ddcef61799dd95ca309166875f3752bca5a51a47554b6bf8445c627c6545b5c8a20ee05aaaeb887c8a716d6d8c0328cde79e038f90ac6f8a19ac04a2db3831f98f3803184040b977fcebc9686ea15bbc75a6626ab78ee29142d4312e463f444bebd6c8d108519b351e6ce50875b66e00d67ab199387767b66651727f24ef6f485e67bc0551a2c04c55715abe4f96d25360776b7b81da5151ea903325f5ad35773d675735bac8ab263895950a4ae72b0cca190a82223c41fc463d0db3371d19412f5224d2b217ce4b3e462e7cf61bca9579fc295d9821bc3e1fa46c9777a3ad4eaac49f7cc634ac23ed1f7176efa94395d68d226e620f227fcd62da5335d543e8161b41846583c758bb6e288876042886864880250e791739d5f4d166d0268fb617d2959a2ea9a2522fce9e3257d0ebdfffbaed21fbe3fd04cfd6ec52f51bd3212697162e700abf98c0cd5d04d383f00ab950a3d5b8c46669218575980329d0c1a8c54da1d81b81a504c6df609791f7bf29a66ec0d3bec5cf618d17b698d4eb1034d99694d5709b0f6267bfe6028f4535f7288863db27ada0165a4d3f04a194855160ab87e69e6e20701c58f5b2e07b3778538b4f1d9370a39679808205146f9964e6d6fb89f97d80a4515520071a0c1c43c401e33986d12288674c3fe8a1dee505c8b3603e163bb875931ef59da07a5cdfd676b0ad7621a562b02ab94dde64c0aaa2cb3681794b306a7e10d6e5183881a3174447f7e604b4abc0869e933e83e4d9f1791ee2970e71096ef5445bf5d92344130509875adcc8ca34fa405726ceaa0a316769eff40802c8e216ee80adeeaa29363385fa491c6a4469f05f184ba788b1eef0b7e824ba5e3f741005f1c4bb9ec91d4a3dcf456611b0fc034b44f1a1196786bf79998db7fbc3a15b5b0dbef269ba24d3a164b42c4776579d856bdd4dd4a1a52e2f42a36363fbd6632e531115a362d94a515939f1843af9399e0b52f032e6a6c769921a5f1f4e9fb220605f87c459c738be1b2b3840457d721591e74abcbd181588f6370d864269e2b193eedb55056af948392c73144c40a15c9e2ecffa7b85833dedadf1416dd15f528c6382de0c31369021922478a5ef72038e8dc244c85baad8f6c3acd927429293a84210b7c4b66b266310eed5f8d65e8af188f4542a26f6ea803c82a6155a26f5860f078ad566f16b7c1d14b4ab91b15355a4c880f753f1f3486d2540ae6486e8942ec9bfa4cf73efeb0b48ad34ae250d3965a153d68f26838dda0731591e3cfd5125e9deb95c6d243e8ffd282a8824190b4021554e14ff0bef07aae0bbd3a3944b88ea50899a4798c50fa4ae03bc38f749c8cb0da4a1f60cda7a82d73d11655df1dc4dcdac159dbe3d0ed1b746c6de28737400d590a2a5f6eea7119d5373fcbad274869e873aca14f501f6cc6a147e4d26b655558893896a8a11f9ab9567d42b6bf6175ba186773d9b8d9665f431a3b5c2145af602f11ad83b4f8d7a896986303ce5928d91950f887f06331c6bbae8f2d422644f8647c4b070b45f92a5f57d59b3a76a9ccdc30d963e105f48370cb894eb4513ca89043183d8e4d27c519834087ed01211bcbcebe757107d81fc939d0c6610ebef81b2cbe2c265a8a032ce44ecdcd41b74f4df44dc489b0042130bf0d9d2fa5f2716d00e2dcb9b24a6b0142a577c48094efc96831581249a0110c27e8dc085d019aee862f56309e8e85fe65ed8cb904df83a9f31039f21ad678c437088ad37f13fb07884aa174667eda8c15cf159317c194545d9370136bccddc2b816af78534f1d1eccdec56c5243f11419f2193cff62a9326e61035b84aac86d71b954de21de879d1c91cbffaa0552fc3a00a09b04e94aabee23fdb4ac99c12d2c9a7fef31e8c1ea3e0bba17b5eb86ad409eb398707fff27a48063052dc1516aaf613b92ca94546ffaf59a9bbc1e1490f376581b894b510e59213f364d49ff8cc3b58daf360ac7921af7747207c6840c1a30990c9976c7c8d5ad982e555954fb303e7f2fbb73a2bd64b84f86de095f887f747e53e627eabde0cd77d78d1bd720bea518f8a2f76e57a2e133be89122c6ee8e80ed9b98740564229e3183cb51061359260f333bdb2c89a1928024f0773251e37518459be53f9c268e4d9ab4f87275cac6008b5eef6771509373a7a11bd15e9074f3d10f3ab0f2a3282022312c5dbfc9c1f2072b1c3ceda59674e505790a6100111ed244ece014031c67cea2551e3dd09a521b02f9f34b3b0c1271a0277405dcc9e7adef84635cd0ab72d48b1b3a9c79cfbf5b88f151166b64bab1f39f74b9610fece86199b1598685efe87de749382fd2882d2faaacebc140fc3a9259a2f84773acf64d853086bf1c1d7eed31b0bd5d334b24598e8d17d721558feede754efa75967bf5ef8750c4deaa1c4b930788ac7286b5b9056837177635067bb66239f48637de1d311c64425e14252b73b4267800b975a0b7c4c5fcc03952cb4a0025b0361f8105e2762db21aca4e0f6c5d035a7e51d8b30e3951119fd0d95021c5aec805ac29527c1b199e855adb59e558cbbe3bfe5362812c44d0557a2eacd62941b6656c2b857671b4623e4471bd674ddc3dda0d7a31a9143dc381b3b723cfb16ae5d5de0c016a208a9795f5958c6a92b133c90db192fe978865b51bf76786e4a6d0f7804f78bf8e08b93d0cbb5977cdf75a997d9e28fa1cd1216ff183ea943972221ae16a3dff30bb4183e857a71755faeccbeb9446141a84a102f2d12f50364933e08fe0d391bf1 +MD = 04d080afc2b26faf57e3b91ba0202f187ea08b64e7ac3560b9af97db98fed4d9 + +Len = 37736 +Msg = a67ec4b7fd790a754c35248931604c4d7044fd62f3b213480f382e2b099a5700d980e6d12d6da255b1f02bc48e1e95e9303f56794dc862a3238a94e80128502d08ce670f33203a769571236de236103131ba7187001355537954cf67f4049f99bccf0e18167c1a007f1fd32b3690054bfa1b17351579338099ffa84fea168c6b7ceba595de688a1af86205a79114bc5f14cc102b93e446510cf4e449eb465eccd18af22d94cbd1ec87a27f89fbaa7c9605332410823bd4ef599a4efc007c5fe34214bf893f8f389fb4470a787c3a8f1757ba1b8deb6626820858ad1130a0d5d957f1d250e79b075b07b96e1c1dac3b0b91c8bc49d54c8431a298c82f849a09d5988af32b94d786470961731ee5e8c99a3cc4d0ed48d73524aec168ff025243008e45ecc24f2bfc8c41a5e126ddd681ebdf181f204cee8384b43b5528b4b1cb81c08b84bc1f7fb35137ee7fdb0b5faa27022b718bea79b4793c6d5753a29de881b6c582c20dbbf1bf74a516e679698d752e658ed52961112acfc13628d3ffe328f959af7b20c7fffe7f306eee2fdd73fee92e3ea7128ce2c0f49eb94e4fc0049d10b1d390608b2535e0f94f9c33a4a2eabeee48a9abe36f62346caa6e1ec693098333b6a8d5f0aa8d206681988fa46360320d7582fe4eff391694cf2f49fbd893db491f6c88dcd82dc6e1cb894bc7fd88cff38ddb13b6dc6d227cf03ad6461b649f5ad7838038f53d5ad1f7186df4ba8b1c09585bf0014c25e08dd736d08ea3a357cda797c5ed4ae7659ecbecff13e091a1b59dab9f199889d92f4bcc3cbdb9798c0c554d60e21f516eaf10ae080bb8c1e760267228e408c294cb13a424baa50ec47ea94f58febca3fd6e8d0591c68a447573b959914ce3f899c7f8658f6daf898a8b6d45b52b68069a420c9aa12b9e42d3541f08e4387352718dc2b886be1f13639b67d680506ca2ce93531440223be28a6d2026298ffef9a383394410953cd3d91660abc054109e20ca2c1c7693aa4c2125835b663bcd15b71324b235da4ff27365216c7d219c22194d5d5a4c6634a920e31251a52328cd36a44da9fd75a097baee6fc0bf9e58583f85ae75c9831f21101193aded2f5649a79d7ad2714e77eb341a154f8fb38c661ddae916f6d3b3db7816cf1a4747a1b2926874d5984e1c166b51d9c2f4487f7438b5d4e4d93c3a00e05a8e3eb9534f307f6c03597b5bd63fe7fc85c1f7457aab1a7c39887da7fab7d04597c14e3ba9eaf711ee06205eef8e2e81dff39f92c5324a99dea9e7fd3c29d13fb44c0be7f70981bfff859140ad2cca4ab001f418a83250728bf02124487d6ab0ab87fa4081b4a6defc7ed6e7594143bdbf92febd6bd3b5710a04320666dc24004519222c8e14edd6ae98f53d3af41f44d64fc66a553c00fc228f228ade6e86974aab8b946851de10dd7cf8299a6ee846bbe05308af96b97d9a36f997f75a18dd82e43e61559201f251d2e692bfd7252b37ecad7dc108685b3ba3c017fbc9623bb56d42799effdfe5d141c862f2565f5a121bddb3d3bb96fecd7e7ff130e2ed17aaed9fc68bc1ff522771a5807b131d3d1417ea902dd7cace186e3c0ddfce40da2a0d5e2f6300e99f190b85d4a237e73b0585dcfe17838d33e31c01534fb4e3edfd75869b70e3263670b77146afea45bcac10bce4d8e76695f830d5abcabd5fb6ebcc1ff4f8933d7df31c6fbee953c028d25e9129b92cdd5c1d51c1fd96113b9fbcba32214438b6de6ce38a249a9bdfe83f1763b7027a7af01b27cb31fcd7ff0f37e9c50a9cf91abfa1b3c76008e92b62bbe43a75fbf8c6b9b95bfe2f4438346e25fee39747fef08a5c35305a7b662bff0e6d1f4bebcf4820c1955fdfb65b61234ea491b08f70c0a66311ccfb3d3a6727ff5919211c26888bf97cf8299a690e987a81d93dba77137b7eeea329958c6743585031dfd4260f632bb9d0f63789c334713dc226113a6f717774becdca84b4b9dffc6e6e5cf764111df4ef2cd6e4095ffa815453dce25ff0154c24d0254cd5f35d02d8b4fcc010fb98d45eb5bfa16781dff598ac639668601f1edd18ee095257990d779afbaa998b630124773ae96602e640951aed7f14295e91f28f6de6b44f5dc35408a3dc89284824495c8fe48c4bd80a5483c4c4eab39a4e6a1ce90981426fcc76e73a7e67390de5d64b05b964c27cfddbd12e8f72679afd4da6ac9a449898d1e51d09babc287bebd22be59173d09cbf34ea740535ab2845a417fcc282b8a07aaa9458b60f5c5adf45e6779343ddfef867b8de50bae80ace765622a8c50c4f6ecc326f9ae83d7268376303e85b526b517a21b39889870941cb4b667694fb6d5653e1958fcf338a2fb18ad1b74395ab71770f3d042beeed46abde0f5178edc1d9488813bd4da66cdbba432929841086026569c2bd27877e841ff76763f84a14a0b20f314be9fede155b765266a52ac4a94d178beb05b984a42e7eb4d49c7b2e52995d37612ca3a9859b0b95952e4a2c103600e0b44eebc64de15b3fccece6d798055c6d299dfe95d282ea3adea7da88df280e084389870d283f76507271f4d71afff31bc8c47569a518fc896a99419ebe2c284dbe3ef421dd50b72eeeb20df57f8e0a88692971efa56627c9618ce736534836f54ef69aca131c072369379afa70bb8afd32555bed7b735444eb06341a498621491a37e1d072ac4c750b8901af948d59c24bcf992cce476c402e91901146eecf914b8c31faa407706dfb2facd9940c601fdd1f957447eb550655b463e2f2872915087af2114e35595362b101431740875c10ceb58c8e66f9de86f81556f759171c7a8b8cde1b3ff16f67986ab4c632b7c00b63633e4ac03e0fe9e30e35fa6c82f0c8466726b02c1e08336b4ef349e9d694f766065023020ee3a8ffb647a6c950d71b33ebb4b804ca68edb215c9476dcd20fb5f058bc33350a0e8d47653a0776b1a9bdb814fd9cfdcd5bef626fe68c785ac40d7cab7cf5bec8fd4e8b423937eb9016fc58fbebb963c98cebdeb5a55fee580ee56bc9cf282c9f891c6d97d25e724d3c0797fca0761d2f94492cba5b61ad4e42c624301d2b1d1234af34e2afeb993dab580b73b6536863f48fa2ea632243c1f2285c7b017f0eb5725f87af2c7fced5c7761a1d97c1f40b4047f7c267223047af946b06f6a45ffde4a5ec49c28b81ca22da4a36bf523e89e9da81eed1e1f143dd92d670773baf6fee2ad96f2c8f607f400d227bb774a66463efd7ac3dd2054b0e9c35240d956b600156b57ba50be96991872948fab9da2f40d07f970572fac1a528fdae14421282c0a226ebd6716b1db9c0c52b0392384f0324d03bb355304c53b1a67b45e2434c9ea5945c3b6084000b529c9e6c8e5f581d658016d1f9544f7cdea627fcc66c321dc994394e59b2b518a5061f800e9dbf021ae594ebcfb54f93089310b39efbb7a0969d0f79bd75a16440982b08b3920863ad97526b5901c138b7f3e204bc8061d995154b580c5b6970adc94d40eddaa884a61bbbdb159848c0652f085aaf88a52b3d937963d6c251b0552ff2d34db634178cc95db596075aecb8cae04ff8731607f8ae2627ad590ec5cf22b83a23d31f8eda46a4755acd5bfffb4e263f27ee19126ebbbe1de06e0503844809e030bfef4d070a2ca4c458e08cd53f36b2ae4842bd0852bdb1209fb90c1d16745fd4bb17e4ab9a52ce73486d15bf049e450c10177a4de9b17bee6cbf41e204642380732de8306da35cd80a762d1134c960b1e40bdcb80715e89a337c378ba865b5d46695ca2dfabaca631d70258456449040229456df317781b4a2647f625905914113e40d0cc7f5b1c5000fa180cf9c4e375a456b0bdf32d1de282c6c1ebcb03046f99d13456bf08d5e3099338f373d04f7f9939bf686f453774328900939e23d6686258f704d17c79f5da12e07f3a35f029f037c07cf18710071ed8dca6737f3204811d405f1e7fb18b5bc23a3ab6bb6f7a9196dc7fe3bc51a32efb7dabb1e1be4cde6838ee0ed925af74ea6bab4f29747b649e3afbacaca1504a390a2abf0f2547618106390a517c680dd19e5a6e49a63252990377b41fa9175adbacac07d10dfdf3afd4c878b05ebf0ec0f9d079e1aea941cd5e7c63dd11ff46298ab8f0f11f777a3cc724c1be75ba5fffa494daba33e81a83749121ad8011f66bcdd6e23502bcdf6e09d44e436664e8d6c82ef79cdef5c6036c3e56599e5452e99c8e45675ed40b8ec2608607dcc2928d8d273a4f57da2c956f0b6aa714d043eb2069824dddc8e5e31951d0d17dde436b1a060a9a459f3381a581c5608a8dafb880eeffb0259f54b7372d966bf1bfe4b99853ce46514ac50e3527cf4ca7948099e5a62557de614250447f3f9be16d5ec02e97f01b22e5c9864885f13214ec9cd677175c0cb11796f767cc332af5f197c50558d7e16177262f052491db799dedb75dcb0d9545c838f4c89ed9e0d45279134421eb60b509c652958b19107cb05983c04a9ebb447c0f8f907c9b842798ebf114779460c7a290361f42ef97c82cca84c71a7946533b0510e7efe0e095cbd4a69de43aa83e4a6c25ccd27d38031927009bc504fe1c0e01bef47e11bac7f41e7b06ef4501c3094265c4c229bdd67f584063d3a9ab47fcece3e0b194db641bb0b878211d33fee8fa3f2e9a5dece867448c48cacf147c0eacc5d210d20b154672a51a002a0696ee7dfb32e3808fe2d8d52c7234dd02624b2aacf3243311827f4c891516d5423424b1e1fa24fa6c6bdbf26708983d3da1bb4ee26b7420b752cd26ae90eb84ae7f907f39abe5324c2c778386337f568de26601ae6188ffc32e39e85ab405a013203ccf4a70af92f6ccb471d11a7090bacd552957fde939febdc97ad6a9ee9239be308a5d6f088134f49aa290e6f3538b098faf26691e3730a887c46a962ec1e8027396bad07b67cc4c32ff0bbe9007c93f1c7c63caaf6021967baf5da34b94e8930cdda9bc8dad877b83708acbd0143c160577564b251b9830ac21f9facf75001b0646725bc8b92d2a95de54343ae3ac375187461107d25f1e220384c042cbfa3f66b85cd4b3f48600712fb22257dae14908967d47ddec3c07e53e47202afd9ca9361db050d6c659a61e4decbdad62a2f5338b411330d1f893feb88a401175af017e5cb7f6ba9870c3a41e4a2cc6e4b9e3d84ddb9d86e85b6b745b95487e9afaee445db6efe6d091000c8c13982ac6ecba02c6930e6a9b2c374f0eaf61fad447199208f862e2d885055d7e91285f720422b6ddb08e6151359e97b821b30c8b5c2a6f45c478371614799fdb0a05ef4ec9c5fe7a7c44f5733c49554334653c2702c8e4fc61586cf40505db8dc75662c40248e1853d59ad670ae091962d9f1210019bf715182c09d82250187b10443e3a795668e73cf51196670a5199578b17af214cb2783119972c31035e8d2df70d1af4959986c13eaa681a6f9f34f94ed26a2a831d0df4499d57fbc5b5ab659656cb3cad7e4b135fff46edb8824f5a13cbaae3e73fbda8e4a3c1483f26bd014aa2b519471f1e7c7e9996a68d03d2c3008bd81521206e971131d2e018b8ab493a7840520b82e842c4fec10e9528a57c3d995a88d9c80907f9d0f28af9745d858f60d4b1a0b18fae58b830ed79fbb1cdf37d9a04b6407741c40789108a60bcfd70e2d9fcafb4fd08624f4a0be184dcfe4ac0fe51608f9e8d995fff387287aef90687b7fcdf9118980c49762f73ca0f5669e9f03680bd6832a05fbccb5aee1cc078d6d679d952caa57c301e23dad5331e7980d77dbed3bc7a038f2890e99fef9bef589f3b44fffa79da8ba9adbcad2e9fa10e1becc1d881abe777ac51c8a10dd293937809c99e905a4fe37f96c25bea1e0a1a234c32d4a10e76a0aed49efc60ad8b11caac1039739103bf08a593e64de6db2c5964b8cf03ebd89198e214b8cf73005afeedc0d78d661da7aba4d856413e3dcc24fefcd28f8a35d2d043d2de416e19f47a928181c520c523d35938b3ad6d5883ece0a5e42d32b4ecc0bf7f76a0e4ff69a863fd3e030925bce58e5c0678bc53d81ad35c0ec52d7d66ce1ec386d31ed941ef2ad9162f6762f94a09eb578c735754149fc9573fc1b9c864274818c264d002b6adc0113283a7636a938eacd0da8b7d430c93c78337909be9a3b33355fe0c3667b55838f2a51a80adf3ed0f2c3818de0fe263667ad72965c55bafe07433b464690a49925815e3db7cf3af8788d725fce1e8e03d0ae8adb15f14e226074cf11524743c274c1a2bf93d597c1cccfddb611fe7b3531cb443042199f40df691ead000bbd900b7fd1a645aeefed7e1f3629433a883b0998114e872b18e9d294ac81d65a6c7247f07d7a3397adabfad01e11d83f0f95d679848e4ba2358df88bfb284bbffaf9b8e7d8b3e44c5bbdd196e8085798abd617041068162b8f9dafc38d18e6a8c386ecaaa5dbde19647370d8469527b3d76c49ac37645d0381a966bfc4cc2da160ba41dd576a97ab626d87289c10ff3d0cc8fcf68c1ba6d6b621cbf544ca97364cf456e45fd8a76ee01c52ec6b341480c69c9f6760f68a1187a73de88f9c99e402d5aa4431be63d0480072b836472e2b9f27af73687d6d50909a3b2e07aadc170cdeaa917f84737c04aa74f08ff29299f12aa +MD = df8b6db68dd4dfebdd1a7b8faa80b3835d561119200da32210e5d4bc7a8a4bb2 + +Len = 38528 +Msg = 84a4e5f24fdeb35dd247d807c7ca6c39a70952d9103abedd6a34f505cac954ca165794926b9a4c25bbc4b764bbd0b839fc131bca57141ef28f9d30f13212f862c002996e0ffc3540eea4b0b80905b6640d29ffac0ce7d14c22fdc708595fd29acace7df005ab7594b30e486c7a136da3217485e7f55de0d56b7b43b10657e85b7be2c77e1450140b522a09e6d69fe5df811c35e3db1c5273b1402b5603a2448b1d67ff8203931b8c12217a8fe55427fe7648970885cc2f103e74075e16e9ee14f684ae639b1b91fe3d1b23cf6ed73aea462034bfbd168093583d603108d4ecdc4f625b89a4917e4b193f8d0f3bd3268939cd936e49a24ce448c6bc37a00a48cd6f288e5ce69cea5aefb63fb512eef4c599773c7ff2179beb5635a6d8a8340acea0ffcf4428e5de1306a8c12bbcd0ab84ac45b858801d7590c9b3a37ce6f938c6280fa7a93414615ea83c9cd7012253b0bc608e63bb5ee3bbeb673d8b2402dc9f507f9df3d0d07c231b9a5723a88cf5300ff046066b7fec54027afb6d28f6fd4060783a8ac5c1364aa8eb7a767bb597eced1c69ab572b99435713658aba7ea491a02104d6da9097bb97578e37404644cca00c7eb94808f170325b044aa442d87a57a38540d9e5a75f30051ad0c0e601b86fe90d9806befcc3da7a5f16ade9a1e3cf25452e88676f1cbb1ea6a8c33ed898a1db9eaf59f6c2259997ff549c1c07b44ed0cb09b1bff6db7fc9ba2711f6d0547f09ba6809584c7cb5da6a6e3a8213d51dcb9f3a1a954485c52fdfb571b5f1d4519ce82add8ba1b2776c2aca4fc4cc2e843f49278c906200d5779cbaac2344015fbbb15e9e38c9ad2775c7d2a3893ba8ca54513ace585736f7ca7a9e8ae9d0c1f08f9c6a1406cd570d1cc7ecfd7a6629393140daaa962b0d735000c9d3af9efd4d4031b7079eb496718ab482263e579a17ff9e6ee6f2e76f9030b6a44f1cb49ebff5f8ad3fa786549ae715fbe77e16e4ade5f1604b13924397932495c6d91c8a8cd67ab483ca4b78d15a73bf06e2a9ed430cc317a1a23471d0a0d305ff8edeabfc0c3e359daf0cea5e0b55364b111a9f219c9bfbb046d6e083804a5dc3e200e759bfcc9653fdd192892343c880b471e18ebc02743fa87e7af85a1103da7d8c28e916ad416e5ca0589acac5dd6b72b49ad4947fea186f37267757b1610c088955f63a689cb6768324d82764ddd6f4edb4394d9ac5014406cc479fb1dd212b0056c6538511f2f081de8c63a73087e22316060fdb6dc3cff555b15999e1e08df813a1888d07ec75a26efea5173e46e35fa88201cb4b26b70ba7fdaef2d412d77973d10107e66aabefbc76163a6fdd9fa852f74cf1c5f1a550ab73c5421e7fb08c619de77b15353a6fb03cde9b2c12bf06fcab17d544ee40cd495ac71427efc137c24c6271fe15cb2b339724bfdbafeb818ee78b0031e331896afcdbed562ab2847f27997208d106292bd11030e67aca22f0f3d0f9f2991f8cf49f2a5715f72a7b8076b5059b3392738230cc75b33c05f00b170d48f1d8b3dfd18cdbd9cc20d123ad81ddb31f0118111efd7d16acbc43f3c59b6b7694679589e70b17fce16b5084ee8f3a03fc043f09e97f4e9b37c42d3407c6110a45106c9220630646bda14fa62ce9f47d9b04b065c900658dbe1a6bbabae2278c6b99e00362decf41c88a75924dd832a962c9122da8c6ea74a887a48ec435d7856dcb9be397c29b756aed6b4f3ba21c10ba1a0e676d1a06d65dd380b60f08477cb56e423aa65891690c93d9e5dc8fdb390cc04c1d0044e03d45c6a93c81a29ff9aa4a801177e8daa51445655d1ae997acbe847356498ca230c828c427044d0884b426fa6ff2ba9db1ecc9babedcf677f23a2c2b1b2f3a71384ec07c807f4faaa63bcc5b5cff150316fae77e100900a492e6801e739d9578dc3f57764ed9f1ace6a70249e08643345ba8695a5b8b4d46142c4af26678e6dca403b55d99fc7b36cd61916c046f8a57085d15f5a84925840173504ffca975c81802a2d76acf3572e2cf416ecfa23394a580b5f8fe2bd286e0225bde3e188a62c1a4e68cc83a6686ad5ad9f44a078514bb7b0f0a66199b7539a3334633ad6dd226524826bb25589ab66a23a97b87caffd1b5ecd4e7fbc779955da030e3516541cf72924a4b7851d78668e5326c08487d709613fd89b99fb97ab86a4457eabcd7456e8aa2811b9a64a4bae83a257349b41f864e2e543c6b5e731c58299661b8bb0facf9d664f77b6a98caf467acb113cf66ed630f516a738f05f13488a89fa216b596a68efcf23b11ebffd1610ba9eef4cd331b47872cfe75ba9fc408968bc20fc0925b7152f5248024c046d14a42244cddc03e7fff6b5537198ed152670c5fcfb70ade276de97ce0cb771c5f6f66fcfe1dfd945ebf0dc1ffaa27220d230cc27d2265f85956b48c58688b1bb284fcbd321650e48dd1fb88f2f6d081e2d37234428a0b71af13409c1184640b7390ebb0124e22f8b33c1ef23a84f2b4797e26fb46756411d0ae73f433a66ab4499c1d1dc34fdc9679095d49ffdcf684792c0f5fb06ed8a0652e37dbe55705deddaf794c70a1e487873f9fd3688742b98be517aaa8facfe5159c739b4f1e9d50d7d1e7843fcaa49384e6ceda9e0c401b56b2252258a3b1a989ff0f7a9a839ad3de0a4f0e585482811907d1a4c9f35771839a2211e6f0e6b4685ff2c1ee0e642f9a639932e4c7e81beda990790fc5ee85b9a6f4bd7a69d6ce5bc506b77248632cb4e3ae380ba93d27a9d4f3a39b096f1da1dd846f3d97e9bf0a3732a64fb8ff91d4937468f484e96ef490e26993474102e247ba6e5601884e1cc05ed4ace7a128a179d40ac8df54b877e645122008ccfc25ec7e04ee3019453a65728ab25bafb7c49fb665ae43e6cdd9dd04e769d278d312d5b9772daa066a0b305710899e9307e40d03c2cf370774c37e07309730ad4e500951103af9b5863828f3ae5838b3e0aacaa16953431f77ddd03635d1a7d336889030173ea4906068552fac47af790abede7aa261ef969ccedb7a3d40c1525361733cd46034fdc244c0f451808d4c4cc75175b521c4d4ac3fa7b9910b05926d84b95f8ec9306672737028e72859936f6e2b79e9bc49416ed73ddd7a5cfbfc4c986a808fa02032399e6db4b46a9cb83c5a7570885a0745ac3fa4cc3e582cf6b7468f871d0e8dc9df6dc081016cdd2278333741d82284492c1ee47025291fe978362e5b813bfe932c8770761556a439eea377d4223d4ab3b71d06af79f75c3e550f52e6034efbf8e895857a3a517a6565503f11add3e1ed15e4107380e96c5b177a000fea700c60da3e0877b685e50ea4e296e0c30bcf5d0e1a0da38428d6aa861e42be80c8ba33cb2b0054d2196f9c74028529aa0d9e6d6a670227cbdb229169a41fdb0b7f8cd9830475f9d635a0779d5812d4ab02d584f075f9e79d2bd97a89b3a04fd4bc0bbaca70704e0a03ff07e78b48c90e12fd0969e9f9ca444082ccaff4cb0023a8bd3e6817f73ab5a814b51a442cf01b649d669e6e0bba0741a5efa10eaad7406b2cce24a215a8214f67e7fd2ac8311a213d0254aa369f2d57cb4b28aa45bc722ce0d0c7b9cf7d941e810659e62375527066455645825fffa97b480b70a298021360ae19032fa2573de97bf61f45a20c7a9e976be8f7e3c5603d4e1407cb51384934cee2293cffb2d527ad9c7e37a2906670605a3b9e13c7a399c50918c8d15cf6e49aead2fe7cec0ec40313aa005b265d6108ece57ed74c9b1815b34a9ffeb641f878f9a77e024f0f47e7224ca8b71687fbf7e98f9f189e6f41a6da465ac28e53f9d2d650c377210138c0930c389da70bc59619e00abc03489ce046b401042b546f0f4a74d5c5ab0b20f52c91b7f42212474b4381c6adc44eb22cbe3a9aacd66be0971dbbbdd2355685f0b6842da6cfc30a7f3119dbd128a80af00b832fa1d7c0d6d217cf8288070af218f88ca29af647959ba9515212797f2d95f535c7cd767cd828ff552ccd684eecd5bc521fb8dfc5700574d13257fdfaa18444f96b17fbc76f019ff8c48ba24afd8fc87eabe8d26624275a408387fe42f024c0762267adc821c5bd5e51a9fb27acaee5b74f121652386822464e8cc27ea1dc3155f4a5d5a879dc222fdb0fbc0d819adba5121ef4b0342f968c9a4d92d73d165e3de9b9bb8efcae96146ba52c2305bc72f1fcf4b4a8a1e67cba6fb2b5754b3910d70a8ca7a334a3e1b407539592bf7a7243157d9e6406f49d78d5a3757f53ad0fcb5e04e10fa824cab9ba013d81383da242669ff909ebc1c16cd508181eded923c0ed0ab0f9e0971ac889976d19f66ecb97f6430fc2d8b5af4176c9e7797327145ec0875e896566998c7efd6d828373b5eacd5226b55638319dc1cf2ab99afea94ede6131e9bef70faaa01b85e367b628e2f4b2870aecb20d29bc002905dbc6ab384f82723e73b444cdf7d9fd64289dec27724d7aea238b0c8c71452b86bfe8e3c31cd068b30d04009b8c201c2f5092c8624f09467d822bf66ee8877a63cdca16984c355d6d134e0abc66d62c6967fc863b94d035ea91fa937928ac5cc58ed50f5fe79897970dfc2bd98de5733df343ec5948898d5ad861ab53399d1ad4887195bff6e05f5783752b9a0a333ad17ecec365731c97f4e0c605a42343fbb745076f6080f7fdd5fe21d2a6e4aac84d8f07d2061d709be130926a15ee8549974dfd66eb8dc4b93b0668e7a6233167daaf55e3e54f6fe148502ea24da34a4a9b26bd4208262fdbae21b23441d0af5da06420bca91100b052c90075f54a7c48ec5aadcb5e5120aa58d9677f20f20ef3c639d126fb690b52262272abb5e90289b17137c896187f6f61b5ef91ea91357174b3cee98361790deee3eb0b348ac45613f1c20357833473f13db23248b50c1fd45c80cde800302acf95d35e1b34aaf63a64b5424a9928fb2efa1929e2677b440bbb4f9ad34e19f0f3bf916c11f09cb34d517a4e1762415243738a405fae6a2a4458a417eb541ca982e98ffdbfc582d3754178ef65e668bf56306e3d6893c117a5bce50dd919229ba39b34d9cdbb449fd9bb17ecdc2e868990ba2ee9a41d6854566e7c4544a511107f5ee8c7e2daca5fa247bf0f254181f91898300cbc54472980f6cf84d501d34e3eb91391a62bfc5bf76dd81ee82743571752de6e574047dd4bdd489534344e9d07351dfdc3b5c3da01b6cae2cce9b2ebb4719fd61eea4ebadeaa4d3f08466c4702586fd4de800526e7a9fe237a8eb8fc187cda0eb859450662e54849f940139359ad6fdda295ac85d2cfdaa99a1e3cd36afbf9dccf95150afe17a07cb1292dc831b986e2b4fb9e40eaaec73bd3a225b9d377630908a7a40edbc7bda0d509a12fb5061ca9bfbac59e56d02ea3cd205df47b77805d0d96dc5a207d077d10e957100a1b9afc69db07e93fbd75a731a3cbcc8983b89f866aa435f6c1e6da07d037b35b8066a15a654e67ccfb0610a730578b252373991a2ce3e9851cc28065c6295fcebeea603b608162261447a5d6d1e97779e0191172e383bcf4150338d0d3155d8b5c8d03b4d588207490a230678d69daaa4112d036976bf76c3511c8f000e3f6bbe2b6506ccb4beadff57e77016dbffae3cfc69e0d5083e1140254f86f547b6f86d8cf110c4ab1078fcd42444d77d4204a109e429f17b3c415063592f2d8c51313c73f0c3b5aa4c1ab9f585df3b58e93078e008695f3e3e696c91a5c2492aa298b376e0aa2040c5e5cf4278a9a2fd69d43d1553097edfb91c0d26c20aa8c10f815aec4d2e94fcf27c9531795eaec9584265f06094c0ce30bbba994a42fcee1c9dab6a92eb744d6641b4490448df4b191d7c279d95d58849caed6f8b1595e03e402d685e4b4e9095d794ffa61284f140c7f82186871d9c48ec1e1020ed0466091b497c0bd894850590cfdbdb26606a43d45254a7d31988c271e5319853d8ede18187fc281de6994a2fbd54100ec1f4b6b523576e2459cc5b1eab4a4dc483c67c05718f3f85a52bb7e6f60ef1265a5efe0cd3a065d54ed5572508a0ddc985ae2d399eabce9a60daf3690242db2779d7ae2dfba61b7069426b3765fbb4dd6ef3697057b831e6aa2561185ab64a6ca11d3bab03fefb805981ebb84ba16f7a9044d55c456b15d4d179a59777dfdb70708e2b067501827f60127d4a32486a1baa00e54fd00af6ff77662548d205eadd68b8f0b2d7644cd84d82844fb247315b1cb61ded902e41c11c7954cf01ef150dea1c2152937db7355240854b3424519358d2e3980e5b72b43101d87c7ff1d68c8526314841e45df11edb14cf3066476eeef5dae19319266345be14e3b4949bc3ba65a5165b0eada613b0a74e5f939f485f8d785cd6cdc938dafc9e87486df15e0a68f14f577332bed17fb13aea22a5aa2b18206c320fc7bf515bd9f993d463b5f59eba55bfa869c5c886c737989a072ec20477924d45ce61593a5b9d3f7e6f65fc8544bc0c14cf3569745da6c3704020c4f0f251711639c9534697f493b270e88f9b34f4c55eef9854b6e91af33bcd3a946c053c55e79641cfdf2392491714a84f6f1f9263dd2768eacd0e06b0532ad6c0c434b5543060752f8262f8b812c73f8c7f491770162321cc2510ec836cc57fda88155f048724ee02ceea8a794c0518f72a65f662a05f4d596da65ed4df49b032561b9bef626fe6ea133ee9f5195acef01eeab1c3f2285612f542b03d2113f2788cabee6d488e2a360db479c41134cc07bb3bcc1c823ae6995a5a9314e8a0c10dba6ad916b01c12870cf +MD = 0d184f0a28e8c8ca71c00c8b25aeeb663d73dd0c31a2e334021ce9f7494e3bda + +Len = 39320 +Msg = 2a63bbde60c8ba994ceec43c572d29efdeffc23032fc1d6ae309daca3ecc554e1463861fbd5525205dc811c766f5f22c5eda1d5fe32eb9ffec9a2008512688ed8ef2e3e7c426048c002b02a3c01ce137b3776feac1196d8c4b69efecb4d306ee20789bde7b239e04be7f61796d883e3964408078d4a3813a89dc0f1e6eb9147a525d76adec353db11d2df4f076235159fa9b18b225b53c302d5d474587c2fdb9ad093cfc1f4227bba79b84b1e2d361c0fcf2fe40bb38e797bf53610908d507d2b8e4b5721a33a549e432d863b982b895f2acfbc99e12ca96c7262314f8d97ceefb57a9b8e7f1ff835b5abaaf04179c016531d7f5d72d2d56ce3d560b5fb8a234ffc8df768e637d92947cf03dca7a562cdce95a6e6d6f58fe5b02c2994559c2cd4ba020531570679e17fe43b413932e3ddf3c4bd968c292b7f7dc2e64b3a423e0684834f7860204ce6d4a7bbde74a6b5cf69274e1d10d25a929336314b0810f96dc26e30be8009d4b1dc660ff4f8757b3aa539b2caf3857fb79702a5245d8cc1731a4f53744517a3dafdcb9235232386782e789620a2a71d66ff949c67991a38aee293122a1dfe3cbabf350d0f93357a307b6062ceacdba61943788175494dc179c1c60750791201d9a72ebaf4b72fc8dbf29da3258087cc56f92b1eddec9bfe8c2e74ad77f4f785c04c3536750d76f4d34a6cc1b5bc3fd2989738af220199422e8f1b7f10f0135b06f4d50a1104bf70cee96a58ffce687b66840ddcc216aa2f097a26f6bc28f9d406578aa0594b4ddf274622d38425a609396637023e9a63278556239ec9de2f9356dac283ae3fc6a264d702cbb3505d0ea9b420ba081b38ce2ad99df1caae090b6105193e90509e3d1042a6ac3ddd021e0fd4778eaf07bf85724af27a4f072acecd4cfb3b903c5931a1ef7aef643a3999f46d87eaa3ee4beff440cda2c778193ff448f5053e416c12a253ec2fc6e67824ffd5fe48874d825019419c05b48f38e16e5f7325eb0e6b428a1696c7e66022217ab43732b993e76859c3ca0da6ab2e559417020836f1cb53d18df7524345ec220d7ecf33cb5fdfab5e5de4350e5a4e0f1df63e46a2aa00c911408a595df62a99209c22c62d1fff6b7f6687266c2b3c706473644bae95a014b1c4cc37a6ff52194ca2de546f32bb5b35740f3c408c6e1bf0253091cb232dc94b913997aed01704ea095e89026697ed291d08e11bfc477459720fb378f10e49371c5ed3e606ddfe91662fbe76fa1983b2b7f0df6ef97d1c08e07e1b487dc6271cfca886dd021b68db1fce7f3d8bb4c18adb4361aa1263757706e843aa27e9e55588a32b045043d61fbcb735d68a0e28ea0d9d326dd59f132c3bfad72e9dee068966eb2afc800bc8e7b3869cd2736a2c78b55aac1a918467a1261220363e470d110dcd21160fc7a3bb9a98fea1e66d3ebf69084940f4b8057e2bcac97197995b94e3d587f16e1c0913e87af5d5419bf2169f2284616dae5f0bd3812d311839948d9fa0da0f195d6b8913b8fcdd135ac926de36080c6adbe6e2a3d1e6155ebc2a53879b91df90104d73a2bf8e39ea3e36689cbf2ea28ad52f8b23396e9ed9a59f9f324249d360d9217c2c1b147c24cacc44612a72b43c0ebb7db824312df77a56b936215c9b1a2c79fb06484a045174ed42b2047ec20cfcfd33092ed853569f0249f9a564971a6ec988c7b379730eb13c0c05d9ad4c5c3477336cc5beaf75a804c9f36adc47e034929df7093d38ab241ad8d32678c3c829bbf779657e82b319f0a1b9de3e2e19f267b2faa60fd5b5321c51b0578bb8df613e07a59a727dbd693869c37c04ca164cbb5079166bcacb6fb30f13f930abe05f7fec77e14500e30a4e9a96c0baac6387f00ec8d6cb984c3171697498121d9998e40e76b660bcd291c5bcba48ea359058c8468063c9beb62bc9e96890aa7e59921cf618a65ff1fa8410389470fe060b2386802649c0be97b34f07569f545ebedf8d3bd42d9d50c965d0a6bbd5709e627ccd5430f55b187f6c535bc500ca2f27d5b7384fa89349cd9b697f96e2ec5f04c8ff2b1702f34ccbbb895f4a61567023192d73d1c3ec5d85a94d3bcc35bbc8809cbe8d6edf13dc1b25537a4d2d93b23f1e428700fc030c70141e63b22a897b546c6de3aef65736cc4e344543e20c75ea59b8ea53bd71c71b704f7fef4dbfe80ebcafd63df517fd7d7ace38c51b2b2ba35fd3065084b31df62242e8ea2bd98efe01d6cdb237e080ad4f63dd57356a54089533737dee31818ebeab47292160e0d0d07542a25b4b70ba40a7ab60cd648f789e4caa4256879243b9eb1322eae07df5ad2ddd64bba34e42d30c1b884f842e71efa123345a3fb0c39884c57dd4c2c6fb0c42e69ff5a269d59af3a6144853c182edb376ca65947d7ccefae6806ba25c4f527706ba85a353c0fd10e3cb244dd93a2d060d7b055058dde1dffed13be99e61341ca62ad830acb37dc65ce37ffce5f6321b5fdcc5edc375658666f6b2131def05b65d8789d4d51b81966a13c7cb68458165f65603b74dc1be90b7576aa94b376bc69547070a6d77cd03a3c27843e0b68f78697d6b57684171817879c236a6d8baefd5ffdc3bb646a49082761df0efb7d0b511c94948a37312cb22d45525d1519774980876037006acbf9eb5355cd5c7e9be97b04a057fe516f03f0d90113b10760763f760dc0b3649f350f64ae233652ef763c8ca086e05f273357c0f6344c3db1ac243393fe86400ee31bfbb1ba92e34f1fe8965ebee6449d69eb62fa69eba3b212b824ba9b80e65e2c978228377718030c0689a0a817e619ce3228d45a9821abd182b2493caa3fd7370c60d945eed952661ecd2fec7b2ee28ab6784eae5a9fe3100a450a8b0a31c32d02fd8c8afe0e8655b8cad3311a0442c4ffbb2e0d3a05a3f8d946c330aba56835ffc10baeaf9fe5005de8531ffd517fa5935a3d213e3b33b1761b3dd3928410788d141d5a0975b890948f795f2bfbe254fcbb438f7029db62692e401bc9b4011d335e89361576462ce6270b99acecb3f9c2480802d8b8e3343be694b0571f834d7a0718e9da8bd9fdda18d274890a3abe6b6853207dce924e73aa003b44abe030e877921c609db72bf8ca9699c93fbfc98182ed91675431d899e44d6498425eed0716bf76b09229ddc8a51fb0747289428c009ffe9e3308fc36fb43d25ccb47ad5f4d66a0d154773bd3123460938be15212492f0f2b515fe0d157aa2e982ee19776825141cbc9e96ea0779f512c710f219dc5656b15987eacf2604a1f525375d4d61e4602a7dbc79eb73d262c4a0e5bd6b4dc0bbb64efac89217eeb4e94224a8b078a0e8b6c7158f2a1cd9299f2490c99e0f6e7a6203d339fe71954626583aae58f2d71832272e593e58daa3f2e0a6c94a77bc3d5526c5915cb994e04ce5edb0af86e3692d2c8b6a90be738c70539c1ec94d365ef026367135666a1dcd59b2621cab72761835a135b9c4202d880bf54cc2c66959d360aa4c30ee815918522d3528b6f0a983d1044d11f06d21ba5826d5af99d1d87f8495a4b7d8771cce3db2ac7c5fda8df08d290341c9a6e387e6b54be82dec4544f08cfd32bac7f34f9ae73a5ffcbc9dced8841ac1b689ed6136250214f9251ad442f4d849fbd0572ce84f517c240343af31a9d60a5d72c9d6a50aaabe9228d39dda61a856124cc2d6a43f94395c4b39f2370ed79414fde378d1bab83d7f440a124557efff9479c0ed6d5c75100bf0cb48373781e78387e4984ad98d2a172318c2125c31af0903dbd1920a76a8b9908201e098878d1fbd27e55ecbcbfd0032aa3dbfc2ffdcc6676e13b0ee1b6bfbb6f8bf91b63afd4fea37b0ac25e73eb0ef18e5ac40cd1183010224586bc5c238b099f1e9252ea09aab8ebab16c5157afd50f4a663a0bd5958d42a3e6f818440729e0194549d51f967db743ecf3ace05370c7dc8c334ea1945879e2eb379589cd9f55c634b8c0d2b9ed2becdd705c61524f0d2c7ca0f80df5ff4291d39e9fdc126d756945d674627b566725f156e24312cc39bab627ba6340ee27114e91c9e37c30c972d74752376165f38fd71bd11e2b74c7f7c72be849fba181e1aab596184165cc83977ffcd9f2785b7aed339b4af2d542743e12143a8cb5fd93867e76e32898f91bd4e4d6c2a52a0987a232b3620f6a33b0899ec0bd7a97f4a75050feec9826c99c3e1a727a0fe77826949dbbebd7a0162d1816703b5bc4018d96d1909cf6bbc89521855268892d31e842e91750f223644a881da54c96d6aeb6c884de6ceab470873db9e926a787c14d2b895829d54098a94818c259b22c46d373cf2ae4daad5bf2d12cc93ce173a0b5bd02e0eef7944dc9e69c69fb444174441725288d5d02e5688a525503dd7d5ac285fa6418efaade1cc21d0ea9b3c2b189213b39ded8519748c7cf2f23f20149e404b4342013d0d422892f22dd871c89233055e151d3160c1427f7aa05a5ac089ac7e4e3ad0ac2ba7baa27491f44ab6592b329b17ed3cc9e7b197078318eda11772de0e5084aed1b6893a9d3d7631bc168280b2cbe60e1d8be1aadfc300427fee9c55cdada4aac51a9d43b659e68da47141d9ea5a8f0f2358dba14b879abf22b631cad178b80ad079fea3070fcdc534116f248cec70a8a5f3a66593f76fcd52183a2464da4935ba7cb544d885b243359f1449e0a8123f69074addff3c06d5d6bbbe4dccfbde934bcac80c71e31d6e6ec2392f2eb7fc3e393ad0f0d77ee73d7749c52c5102ff8c4b0c42e5195296aea923e4c0be41b60bdb343f8862e49b6efd6758a93d18348881e928b61afaa66bac6a20e3d76dc910179e9f8ce997a9d130bf7dacd66406efb60a8467ba02d40d403ef280c363bcb3b720f9e3b4bf99cdd7f93e1d660ffc29b2165ddf4292a9fc2d476480c84c175e816154770b82f4c9bcbda3e433409f9e3db6bc08fad4aca13b2e7dc92f5063783f0ab82f360b412fa5b1b3ea862075b71f92a8c929ee6562329b454440962769b7c22df37c8008665b807615a6d708da1f51290a18085ca8d935c5d94247eb98b232bcab270ad2d6a6d0f44edd8ce070079b47b3104b1adcf9a504717f8a386ff7026c3f7dd025e74d4a367e716783e29d1a0bad57de26645a920af23d88945550d94698c7fb8c011a95438bab917b96aa737cde35ea08aac4a5e046c5688ab2835f509c4cb28c8cd359235fd33250f6f551a32ff4974914ff868d535f539fef593d9434561eaff04140dfe031718869485a8688db0c700cd2dc190352715d729a1b1a492b667c952cf07ef80c77ad5669362fd2317205f907508d3ce8e94ba40ea0e8c114b47be45c11088eae6c4627218ea6f33ff090436489f0e867e4f1ed7c750886592d3543984c86895d77dc43380af1d54daf9a51b2304aee1889d8b6ae42827e42fb311ba949ffd362c0f61276511a5ea2d7aa8db8eca436430187656aae5c931746f7d558af7b5305701cfca30c2978888f495e406605a8307386647961a0ac1f3510d76b2602f18dafd76986e2240a45fffe2c1045752c26085e19a30456b0a3f1038baa589d9544a4adc1e87c15fc22505160f232fcaa6fe896eeaf3f8489eba25858dfea53277078286c9181033667aaca60abd5a30a513ab64967b9341e3f6e98a5d0872d8f5a52d0d2499af79f5c34f29506d5713415274794911b6d57e7804adc46d531b54a5b2c5cd86ff82149175067cadb6f1002d6d036f60c381c2afef664097c698287bbc47005a70ea3757a6d3fbe8ea387626fd9975e359c55521125a5e125dddc5b99207899eb410e2986cf83ac97177f7b1cea1f913da1eaa5e05d07967894ad0c1dc9da5de29a48ad63009d5a9dd3e197038c3656ce4fc36c9429f2ef1c96dbe37146001635203a493888f39049dd96fc4c4644768dafc9ee540eceb6baeb4f28ba1f508f8bdccc452dedef18433f85f220a1b1ba24c8e275499603b1f99cf22323dd348f8dd4e7e86cb9f7b9320195c3a724e5e73ba2f7479a48f9a982afab1cd10713dde312717b1a73753abe29b0b5085749c87946f1ad70ac1865fc2f615aef255442349e544662a4d06490c1bd126cc2432487bbb6eff34bc9af1021fe26a3bf6186287e76916ad370ff50d0a320faee3cc20c0930554aac724d668f69c8155ea17168bcc1a45a88bdd3a65f4c28db629d6bb13945279e587d08a5808a886f897cca9c601bc65b4c1fa738759f7136a6cce71e52dfac16d550a875fd49add6c95a5b6c706e4195a5fe44b11a8445344333fefa5ce52ddbad55f5800d8e8174a5a3ea7ef6a15b2f1ec273b756e3eafdc03878ee603ff21467f2b76bb8414a71a5bf407df99c5d513cd3faf232a4a9b8a5451ca164d543ea8c91b5e1064a51f55117250f82478f258999a10cb5b0ca8d7bc1b3bc738f6885a399b8880091de27321161dc988a38d08c7d32aae8ed95a5c81405e69255a80c34728808adff392fcf16bb8d434da17dcde57377d144522817a5dac8cb0f4da8c883ed0a167aa936b08ffcca8b781352d53a2e187a9d483eeddefa0925a59d80e636af3641eb77645ee2ec3a79f3d4772be52938ebe1c00dd4262d52a9ffe1bd16f29533383bece06079538614a62c15574c2d7d2bf602c053e53a4b5d056086e02068aa03504ed33ebaf95665796554e2d9018f41c6567df384ea9b4ba06404cd26f042a814e564810fa6507255c65b53f36f173838046c3a6905eb7bb6335e646df5a4316efbbcb0df211f4520965332013dbd153353b7b2fd53e2f33016bd2d5d3f77a545d60253913369e6c41e63086d3428e2a18d83e3a89b29bdf75549b15e95640d83bf5ff38fa4d75b27a6b45b9e1c01a769f8fb54d3a767e1f2382977d9c113700ffefb17403c10ae33756eb6fcbdef6a73dc448de43d45650807860834892bd6d1dbfd470cc2 +MD = a248734b02b14f0c26119dc57caa8072b390826a3d36f05cc8c9d429f87fe698 + +Len = 40112 +Msg = 21876510eda9ac6f736d9b2dd0ce50c526b61f07911e2a615d76315c7647ab691f1715dee78d8a3cd9d594b3f44642e8db427af5cd5e91b1d6c3193347d5fa916512c5ed5e3c44b381ba561cad3cf9f70a9ea9a8f80fe97145721ff0a304a4e9593f1c4638ff035cd1e48970e5f7a07a1d905328fb7759261149ea9d711dd1fa6468c3f05f1eefc0321ad6b883c05df97be1207ebfde0a5aa21123419968a84aef5361f3b9e12f660d26e5fb6fdf58fd8c59bab12b8e2394609171e5022d526360c99f58308fecd6c8ce5d41919cbb0db8bfc6c926cecd5db3937d9096b4f7cd20922526ab724d99cddbe692d13eabb267ddefcf9ae5303c03ddee4a3c44bd0e98769a6511d07b3682142af7170f52730179daca6e1c73b9b8396d1bdc27cfb02f3da61e4cf29d355143ce774b55d8d8ee5c32c28abbbf5c3a6da20c5fa3533b4caef2584320dc1fa12e7d1b55596569964e9dc0d60a3baef1413424ab0172355993261bdea2607bd99eddea1d631faf6216c3ca3a501036467fcc6ca9895328bdb2ea6f05bf50d1635b96ec8bbb3131b87e4eeb9ed7657c9fed11ea41821f9be0d3e45da0c0d4aaa62d512988a8c177014ce328eae563096555aca85c36fd172ac0bfec97ed168c0adcb6aafa73f80aa6492c8b06c33164017d44aee0eb162303402125d28e3b02f72f6c76cb65fd710d3dd11bdab9f915d92d8202b7ea9147d31ab30e3aeb6e91d5f01c95e1c4f934a0f07ae04e0ee0a5572f0eaec77b970b02171cb2b54cd5c30ce56d1026d813dcc629cee34b0c109be24a8fbafae550f8f8ff04162cf8981f04d708ee80eb74f0e6b2752bb7f9b17fe145ad2c3672e3951d9a15448838e02d268d9437d94343f86a5118c07c1eeadabee9110e6568796adaaff543af54d576d8d1baf31829a97db9cf5fab80c3e433e0fe63676e10390095084c1b8b949e818369222b25e5ce063bf3f1f3ad30c712af4c4a4039b24cdeb76bc3d5033f64d6901e73e7e8bfd91b588777a0e9acbaff939a6fa0ae96d98da9a10177fe9f4efe65b8552d49fff244785198bb1e80e583f4b17a8fb5030993d272af0c66fa85806cff720730ec430a031bfd4b33f571253a5a12163643047a99a57599229930e40cbb6f7c85cff1f461ab4d581051866ecd5bdf3b199cf1c96804fa281ac478b3acb3f79430f0278bfac931eb9ddc4be5167c8b084657f809a655e7c036c38574b6b0b05819970b55373f510ac2e0e9127b87bb85a5bb43c1ba61e36a5edd7eaf917a42cf280cc5dc7ed454c067a3887d654219b91f12f7790ef0972d7a5b8beda5d9560246967ea8384fe312746e4eaf3d774dac9aa23fba09caab117285d6b45a9594f7597f5e3fce79a50ad189662f69ecff66ffb5410a13b6c61e2ea3848f1875a3b84a0d8c2ba61a43af663cf685536ad6f0379125f4947d905d96fdc00347422c4d028931f42afa64091bcf273a61b87a51297e14fdf4e7b3d593dbb09a4fc4d6bc683b7420c1e0b121d98920d5fda09491bcc636af9cbcd48e0b847cdb98c34a0f636a7e39d295d1fe86b40ade8ee8ccb9dab0b291f2c49e91e8414d4e8a072f4edd5f76c7c7e26da80c960cdd7c59c9cf6a83b02b5fc7b6e5105a4b7c8e572e7fbd638550078d2d2851774f5b2ebb34de53885a064c8cc7926d179dec0a7defacebbcd35efa5eb8853fa1fae00ed6b4eb7f07d6a91fdc77a1e5bf6c26683f19dc4eb28778081fb7c7bd5b36f28371f200d5474c9c427f6e19629cdfb30e665418d08fca279996d1f7b2ec2b1bf55695243d92e5681b3d5502cbf41f1a66ba4a675899c3f1158caf1c089d00e2cc4b46609f2ec89414ded465081053e3d602a0d1cf1a9b61e4caf93ea6b6decf7119adbbe3641fa8932992490038a497c808015e1b5879fc6e155665747fec6b4a88713df27c0f2d02e738b69db43abda3921317259c864c1c386e9a5a3f533dc05f3beeb2bec2aac8e06db4c6cb3cddcf697e03d52de9d854f9eae440403ace3c68b2d70c7260a74ddcda4c63c6d280b455eb2a1455cb287f22724c0ec8caa424697fffe8df10acf9a327855ded262dba1d0295c85a54c50679add9ac202a49e12b496e2f4efb4234fcfb689a885d6c498b6a4bda85ab364fc7449302908445dc76b92dc70749f066b1fefb03dfa2c5c965cc54331ef903c4d3de82f95ffd1e7c1177439a52213ff788d948803a1bc1a274cfb9b96d65b5cc6724af77d7bf5e28c62ab88f77abb64f4a3457fae0f0e73c801c8156b918d3ce49be21653ef28c4a5b7a958dbd11ddd6bfb62e571a4abfff515ab4f14c3ae5344253e0acddbd31499911e17e6e783cf5ae08d7813051d254ae325b726cf273651a8bf532fc49d48d4894a449d00a5c12e0d25a5e6a2ca7a1604c7dc0626806c9991067e1e3befd7e30aee6d62cefc4971ebbbdd80f04c74f304f22c576c525c887873ea0d94335841805b00dc94ffcea2e6b0ad66900b8c7e3e45268ef3159caab9b835627000207ca4109d6f1518d75d88b493fbe49047044b2169117d32937cef23ded161eef6f0c0bfa19ea1dfe9ee6c380fd570632b11a62752834d41d77b834744cecc58124a70b8abefddcd7cf1ebab9f77c60cbf42c9b78168f5bbdf2310a305bf11c428e63e8c1ad72b6a16f4a19fb15757f56a04306264170919211011c7a026f4cb915074aa7ce91d2e2e630874f3f898a5b1d274a87921e9e233aef115929ac7c6e225ddb4509a159259b99adbb5d01a963d2a010a3f1e3a9f8d6c591d6b8f1d5ea1b2b40a247ec72eff84c324a572506f5297600834705da9a4e4946f897867fb46a3a24c66eb846ca6413c001153dc6998970c12e7acd5a900844d5c7afb3a15475522dba684efd3d47b4fcea809114d75a58fcac748351626e7de94be6c06453a63a03851bf6bed10af8900c7e69163805f458061b6fe799e7be288d25f4ef3864bc4f2f71f8b10c13a7246ff80cf443f00d7e4359d942bcdacd3a9455996b8b169eb9c1519bff79cb895f1cd7c3d781846a156b15088d53b173c8685cf5ffd526a9e842a228d09d9a65ea1a01d6e77829d5c6873745eee7d3787a122450d49cfba585ba4ee74b02e9056c71608d4bb24814399da6d88dffa8a4f79993f4116bfd5a37323c20992f1e2f8e2adb2f2cb747f015b84c09932398bfe8059328dfc79490a7b0541be1aca3acf84c5906b10d903103dd102028db0b90f45f0b33663a280e7d3f7e1f4c02de4451dfc458033e899faa16da6473b069e0c4aee25ecd4b219d60e4a27602b839be42ec036e49d29c01b36a921e9d291a77fffa02f13d83e705f8a9a8662a561ae47279fe90ac4f3021c5e22196cdcf861d4e4b5234dd68e20eee957838ed64eb7c8a919d06543facc589846d142c28169a59aaba6ed6847b7feab0fb34726b134f3139c81768297ab6a65a5fe0e2be30b5c71e22e94f5f1822930317a1e2f3fa25107b670c109601bcc56cdf4116193e3741b072eb717f23bd9295b5c9648208c6ce5e622d760da99e8ec0d681f1bfa6e96e6792bd636e02198e6fbef221a2a5f914eaa1c2bf16da26a8602ae69a3ad290f74b6ba74eb41ffe3097186540da39878a280c131639fc1abc54c5b9391228f78364e3f05ad7e0342017ad6aeab22c39d71f8c68a1ff774371a28d41f8cd12e5bbbbe3e2ae61af8205f7634847b3e6d5a4d8070888efb46970546cc8fdf5f621465754c373daf3b1883d24497e64d0239859663cf49219546172499470113e74ce401cdcd0c8138950f3d7b3b84e50ed5cac924c0d6e0fcbea020bee7aaa51a6f87f2575eeb579d2062064cf1cf7cff997d97280fa0dff98b60e9c1e4347977f6e1b55d6f5288c5451cdb2e5d3e9b610f2e6ed1fe4f74f816b9de36cf27078c7d81c96460caab4d7da01ab3d04ac6bfa15dded73f2b2694fb2b8c820afae5c45dd8bcf0f5bc2592248c4361ed8c6587fa7c559c24dc8b3ca32663381a487abc2266fe8770bf8e3fe441e3bd277c1e36751a718551cc197b994af0cd8f685cd065bd0c8c744d4bb337618a39f08257679ba8a147488237be57f9b3b6dd0302bd923b659462ddf478985b954ceb378787e8a763467b978c9179c33a988580f2b03262a823eefa0f0c81a0a37a6a244513f6b746075d647e815937e3c71b6aa364b0d332bf5b19f1eb7dc113471fa106881038a80e7071940a70b84dd6f1389b57a80da3cb49c653a1f74d83475e665270ffac37d0576753997ac4e75cc97350e5826269ec3d879aac889671dfc8ccaf5b0f9243d1748e33bac1fe3eace6935abada81f376a8c63d87ac4c4d94c14c73a2ba8b7a965a8ebaead0c4c26beb211f241adcdf0f1e1ac2afdcdf94eada7e45f49ae83a937bc16fa631a8f0fe499524ddcde39b29ffedb0a184b0e66696daacad2b49026d4aceb8796f2b68f87477f2345e36a63be0b78df95e60907c78da0e48e61e70685a1f3be0d3cc88df0e320db456368ec94320c113a47f41b0e2f4f15445e8f3392c3b405929fcef06896bddfa4073c366a991e08d016d689877d3dc6be5290934339b8c5ebc3cfa23588df962a76ed288768362b1efab8397a9cf45dc2e6f310df2c8767e151d38a9fe00d689e5883a935c8dce4ee9ca1132eb7fc4419c2bf91b0c3a7513cf1e390f0c7d0bdca5707a3bae1999b06a499ffedf4dbe18b8dfcfdfc27a2edc44a059c6e64affd741980fd5fdaf4b62fb9a9e5fd7b1b9edfefb23e0c7f00a24105439663e032906546f69f6cdb769e3183d7ada77543e2df92ea3b28f447d77ac9a5661562e1df65877171290ea5bbd4ac2d3f330adc14511bacdc98ae01f6383f32f5cd1345503c84fa5add990c75e0d9b383e9616d9efe35fe09a3d4b566430ff229d21ae54cb1e49845d2a430351cb4706211a37ee7ae86eaaa928eec8f63e0edeb6ea0493c8d4f54174e589b6151e56cc2f2f7985728b677a7ad062dd9605a2c24e7cdfa86986f35b99adcd4634714af8dd5864256366eade83c6100ac0126b6ba86c87f949ae94313fe5963a1c6e842a90278044c9e56955687caed700fec939793ba60cc5b68860dc1f7d18596092c00c1f466a1291536d7d6677d8d5353cca156ca2698a29207902ddda4757e2075785a22f1bd9f5499547060376b920468c21621585f390fcd82883467db48d526fb142b2c09c8bac4b69edea47297a76fe11de67e88e688e0cd1b239f1ebacf457039379feb6cf0c1e3a8094a0b29e3eae5b142217d72a549572ed3d6a69db7ddbe0f6dd3cc529d98c5d608b39c0f60e0b81b5dc8a5a50d0f0a096c93dbb834f3cfdff64f15436a4f436f04678f12c75941a35efb6846693accf3155f25d5ef918af0fa9b2c07fef044bd24ec4afac05d68906e422e1f60d38736f6c1ecba8fbed78ca0407b660382b20691cc378ff2f5152cb4265ff69be0221838419830bd839ef910c568281e0e7493728fbc98062830bd592e6394c16c85e2036791ff21e7c78073b25d14f99b72acf0bb43dfa3ffa18c84e3a3c17b7c98db7ebc3fef62f23b69f190c1f33c31949933da332a728050e15ecb8544711a434dd2c70bc829ace0fcb1e6fc8d8fd8c2a16273f4421bb526040f7072e74a4d6e7e26105b511d1e9f81dc3c76aa9899e40da50feeef45a6093cbe5ad370af1e01b7a3209853e74f613f991b9612027be225263589f8985ae2d2930f0ea84793e440717e2b972e470c7f1109c68c7387a4310a6d2d27bed99a0eb7198d57bbb7ff61b7b27ae29b0f89896b906ee293c412797c4042425c2b17385200b645b28f3a629e45efffd6aec1a5d038f4da0c3a1545a23430121d5943988b4af339d5257e8a4dbef1b4862c9b1b6888c13d83f193dca4d35f5fa66905768b81abfdcc80b123eca5e7cb5392fe325a083dd2a3f27587aba537f1a26644197a2c45573ea8bd73a5833b0ae7e7d433cf40d0631144a48edf31218fb755eaca7fd42b10d3a688c39edf543ae7330466eeb9e3b678ef073967ff83038d40ded1c200c4f03481fc5aff419a23fe7e7613e0fadc957efc85cf6b97c613cd2e08766c3878be09410082f131758cd2d11282cc8b25c6cb72089a158253881f285001a505af44f9ef7b819c384d3e0b33c0fbdbf52411085977e08b4791292a359eb994edd148ad9157a027dd8a0252ad68c535bf4340ddb9b9eaf56ee7c0975ddae7627a4693cd327b27baa9949e4f46f2290171e919f19bb8007c7fbf130da8ecd3363477ed00d7cf5e7f23d4daa906466f68947d66ed065b6a480380ec351fbcc539a2ca1dee8a3b8c9bd3b08008f54cdf91af69ed78038a6f80829111b7c93305934ca8ed4052a7fb39419156161cedc0a44a14773b992d584c825c4a3aaf37da6bba7a239e38fbf17ff6e02678820f5ccbede6cbded02d6dd58d486166d7b18ee975a688af421fb7957903b6d92f9bf92c2147b308b070f6432abd1ce54b8a67370496e41c7afb95a45264cedf2c7ae0ef6d9ff56142df3bbee223455c13a8ae7aefb0ff8ce878d2d40a6938328092593d5a565a928d62846d3be3a27635f5aaddbf5ea0a8937cb84c287cbb7b33cdab3e6fd4aa4399e21878bf63fcd9bb58a585fb07911883f08d3534041e624e1220193482ad1b6f454008f60c1a2dacb8e59d2b129883c0bd9ab6b6692a8ed848fef731c62ac3167544456746c61b11ffb34bd7e97e9253c927f83712a7a8d9598effef09ebe396586c569a7ac64af11457b788f30aec43fe7c233f695d575a2c185af5b4b622f8d8ff63170ee36454df190bc59806399843e05e54d5134461a9e42fcb2d542843dc4796676ce50e4348416c174038235a7f9dd100be9317f9b839a7fade8d9e7f4b8a1511fa94f2c437160405536a50929cf9a5ca8ca377274161ea092d282cb50f11089d22b8b8e294e1fb1739626848813d023aa80c0cf52ca21f8084ef79ec0f2498934b1808a247ea79d55be9148216b00fd978957f6a61456ee84aa82e2c330bec7cdc7d880e3879a5c81fc6fc4a439cf52e6508788ec99100c7e71cf27d630d2ee03fafe32d50d6a777eec3c7a7f047 +MD = 49ffb48c3b64584e0945d92c7c783cd55eed7f749f3fdc534b5e41239f1136eb + +Len = 40904 +Msg = 972567cf3d7301bd86a19bb77671891b09c4b0817fa583e6f789320a3fd51d16eba18f82a4bca936c3f09cef1f871ce5220d11ab23588f56efc608e1a9c6c0d0d59a8214af5b922fc13de298b4148861671770173ee44eeabdc5d70d553231607d97a84d0557a2efa710d57ae021b7d7fe69368e7952aae9860e0857ea21580e0c2069f44fb8c3c09ef1dd5c49b4908e0f8cccd87ca98a9d752a0184119c1d22aabd2dd33486dce8ce69620897d8fbd0c30698bdeef1d54cafa02c5f71a968e37ef75cb05dcad4b05effcc447392e0e3416104057733753f5ff8f0afb353219ab1555e54718c9560773c83d985ec2710b2247777c07651beabbbb43b7e9f308f6a609b8719d2064040a7ef8f74edb99f3ed859dc71c25110bb70e2cc7b977d0ad29e7c10fda60f98e2c8792de89d7cd80c0411fc321f5d7fb89fe12a5142f153119967b9c40f98af8427877d8b0559034530099fa9965d51cad1191da9a872b14ed9c548171689ce4f4d8345022c386710e5a88d812e39cf188cf26d2bd2e96eb2e4ff869dc1ca3d6bc1d34ef81b024d96a9568d60f0d941cb5bd4e17ec73fd064447b3bff1a4444ff0be16013d89dfdff077b69efe226ef0ac327434b8f5a208c81a32fe429dd2b33b41343fb6df3bf72847fe7d50e0620fe4e5359393324a55421de29f5f57e393043d3be59e1ebdb17aacbd0ba7c621ecf83c0ecf1ba84a9e2ae93f3da8610b71e40889ad53d6c981700c5eb4833232fa4ead6c31a2c61725eb02c533ae479ed2533999f168860409a0ed602253b2f9ca50cfea85d92a549f1ad1012bd18a3236ba57095c5caae19c75d66dbf99c70adfc709e6162f33776c32fa7f80c2974a11b1e7444890c3e6cc774de406d5ecda9ce9f20b7d057ff41fbbd59cccf1fd6ae5b240d740b55f880c2dba4f7288a2dda461fea7250c6e5f2c1e08e58ad02b0945341a3ecf3adc49fdf1b22c8d3287a86897a665a8949d1d03f1eae624fdbe9992dfc9e75e81c8a0f46bbbf7d163e9bf6c237fa3624e7ab249a0221b35db16b060edd67d792ab32192043e2dc98d6787217df10d0c8a95b36fd114f137e8d1d23206d64da9a61a405953cf5af02f7f941b0f90fee1e95c94e8ed5a1495a76e7378b33fe45a847c81bcc2d5fbcfbaa06adb60d5f59cdb6deb475d57d1f9a74b18c77b89de2636386a3ee9e88cc2cf687fc51a468d97e1180afdb994c5be68f63680b82aa7774bfc7e42217d8a63de36477a8459136d9b09889e8aa77c6e5d0e6146f1b8bcd826371279121b714d5798566e4784437859a0f88c38f6428403e20d8cc0baaac36556eb462438ddc9cc1d2112cc5e9a52bd7cbf595d07d499fe2fafb4ad86edc389fa4d3be06c2c73cc234bfa9b5e6487270b61885f629f0a8c25cc7100c3e242f49fdcccdf1be9d5a8491ba83cfa4e8036cb738bc88cfe706e82f82472e844dc45960e6b68ce926a110d348e19b8b4d85d3b59e610ed9f45f5c597516c7a7209ed9b46aa25fac29b66de0b2eba2043ea1ad9a939d10aee05c24c4e8a65e0f6266d0e3a0b8f36d7044a3a240cb6b7585ff034d5d9817b672a44a56221e7b24dec347d4d021cf95c1f1bbff39a67f47e846dcb64479aa5974e0d6f96da7a74d5b5e456f42047b8de565bce1e7a764e3301f41bd926952ffacb7ce940f6968f5a0ded29c3e8a80bca449ae2f90f3a4af2531394a8d8f9610e4d23c0f518b498176ecf6430bdb6589c5459ad17db5c7158e25cc457f14fef4e2d827527b36cf5aa530ba4cf21eb25e120087aef613537c34a20296ae1f12136f729844d59184e8f551259f3b7cf0a251237db04235d24ce051e42563d95bd6524896cfa7c5ef932ef840252e1ca6bc4b5584beab44cbec58d979dae56960a3550129da38f998c417cc12c412275c16c83fa5c07768c7c664e4ca9e7ef8a9e33e45594ed15608e17976a36531c49a179089e79fefc84d41ce17dd5774aebfffd6be2f11ba04c6541c9dfbf1d11ce9276ada53415b8de5c55d1cbcef10b2295de512b20c3b2a5a83c8ea234e3b56d0ae1fdaef8f03de17bad89b6f4c9a2d6f6733e9eb279cf04dd845042266b79bd8147832c5712ee46c89083bfc585a461a8487ece04b247f26b95a95001f8c1387c23a8addd026c76b98b5a56df99726b11baac29b5e1cff6d90d142c56304e5681e30893d9231ae9d50a681ca199bf4bc9665142449cc98abc470b57a19653a009121d8efa198c18819a576199facd9c45c7e8a81f57c7066bd00962729f839d984d41ffbe3a32ab65c782c647313fd50d5bdcbbc4974b229e3488cd27a050b7a5d12056742990eaf7fe84cb27d1887e869ec80dd2cfb84799e124085f6d4d76b86a3323da5c498f9ecbd7e0ca502a01480d150ea885b0ee056245a4784acc635654f4f85f36aed1e09bf6979d31b6f5d8236e4ed44da79e5734781210cd7005f64de044516d438a640b6b601efa91d4ad7e1e3ed48c1ed115d435d19779bac71e917f887f54a9f17f8690cace1f5d164e79af6f37c5891ea7ce0973aab41f2f35ec3d45278134afb98a114839147b4311b2bc506c8e68efa39e6d7899110fb6e2aaa3faf877962d98a26768de7e7ee3bd95bf72e14b50cc9fa1cc4101152ef6ab594e2a40ac20f3a35c0d9d2cc1ca60a8af13573480b32dd284b07d6144df66d6749643ce93778a50137e55b262f042497b626de4c3128c02c3b48e3804b3601a8906f7c0c20c6a25652432fdf68311366727376086f17fa6cb42e403f92daade033a86e5cc520b99cda9b56dd0f555f61ecc344640c2711527e61f4376a08fa77f8b919bf6daf733b9894d90a6c978eefeebf4e49527f8f45608a07521de86ed5a84a851e629b579b51d7bf4cc7202a773e0f9e9d8748fcac24518276f2a493620b02bb62ea0bee25d00c108d6718bb63a55a3c4af4a9def1905d6c8d3061f187e88ac2714e27be3fdcdad5b495a6c71aeb482e36e1cbbf7b6d57cd7e204a0eaa0889a235d61951523ce915a999f2d804d8827e4b95d526b282e6ad310a84743534a86495c9062fc7b9e2d854bb25758934b0346f5af09cfe99b3158e363aab8e328f0f787119de041b6d269d43672711c67a568c7644a8c778650c7deb92391fcae5abc81477e8732a31086c78df74045786ee8932f8d275e8a59be672b4a84ec653416cfb4bd57badd785a9a3b6e7caaf7f034ed635a270b11bc9b113c98085ed80d74c6ebb2b836e06a63c0c1305cb960b9ec3aa22a1219b6e9ec616f9472b06157850b4ef74f53367720dfb1f5870d4d2c6d0f6e856ee6e47220dc36b87a7dab9296017103738c5a2f104b802671f307d835d01ae4940f14d5e6f6248c7633115f464dd46fdb4ec5e2b0a8ae3ba4174b4dd52149d0380ed2959d23ab790c6d2d0e0444fb84dd16f432905bbeada3f661edd9777dd0b142b821b2094e169388793f5e8b58faff718faf2df91414e7fcf648a147295e9667001ad3fb8eeda2116063c3857f2ab8ead2b8e7e550d9e6b762eedb24ded26dc874e1619ee056bea48d0bc1d7c0acafef77e06cc4e79536a25230c574f0e49e037105e947e4ea5f9e59a7e7d6eff93afbe9961afc6aaf4e3a2ebf1ecc120dad947ef8e9aaff20fb7b50b884273f88f0aca27a71103cb0940b62fa45aeb4a622f8095ad12cb19328c7fcce452d41d4475e2cee0d94e021ae829972b8715b56849aaa7c3e318ea94e10d849a97d9973c59d03615efef77b043c3ca905d878974918dd0d9f7df8ebf1c25dcb0f7c98eff1f5a084e3b2e5452b94c71dbc388ed0e6ef0b6f535672d3ba7907c305cee29132d49ec91a453be89b28b3312a06209bf489c012285faed8ee8160b21ad8e9102ed6489e815a5dfdc9649b93fde5b060e885a5a65cfdef942497e328cd2f2ee54c575885a736ddfd3cd4eaa6964bc0c8494f069c8fb5c77df30929878b262678f1f4290efa7f4e6f6bf62af991acd42a7d526d552f2bc90eb0718e6ed3725243d62954ab0997f1bced54d70d6e8d5d102b3c6460b9a466bf035d9c3f448854ee5f6345ea43159a6e275d69428b61ee11a979666fcdc423175229dd893cdc80d1043e773d458c9b0ba08c7c4976cee9979e760da2ca1f70903362cccd4af378845b1783146f41661dff7e6a72cf28e21a60dea4da3cfae1c21d94d48bfd41ae80ca8ad4204ee89e0d8a9fce6ee3046a2296ffd656a4faf915773caf45b25b954ed90504b162f6a562d85d028e60f5d448b7760ca880a42912d6c6977b08a5bf571d127f7829e01ea67f52c161a751d2e538bdd2505e7af442c2cf37ac6ec4af31fd3fbeb522295c50d5fd657944bcc8909153a1eeacd3dd1db1b2fa4a631cc7580fe93d28ea56f0ea72d97945c7ab37c357c405c3ea63561c2a2e79e57432aa31abbb9523c0ed8eebec6377578e91a306028b7880959df1b6a27e10fe108aca6787033136645168dd9927ea1f27f48cc1181674954ce83285a14e6a04d6a99a61f87cabe1331711280f934c1d2268779d1ef174826ed69af1acfbef9a2503bca996646fb4cbc33a53b63207c1ec51d5f27da912d879ed9d933c231c1e8a1d83b6c776f7118cda27093380b7be04353a59baa9b9f7fc91ace2c5307a02747b92123200dc97f4d08980fe0bd661f8a7174b5c7fe46175675b58dec0740682926a343cbe7ab8922ab4838c4fee4e481bff3fe9982cb562d32b6dff4fb46b22f66e956dfc6bd3f35d4a6944a969d3610854bfd89eed6453699fba9d3a95d0e41c31ce4c472aaa86ecadaaddb4c3a1d1f0aa33afd0c0eea5af1a973f0d92b8347836473e1b318ccb5d70d0be0e963a19697243e5ea21c4f7f84ebc6b555581929efe88da051b0b4f3416734bf36bfcb5d74f5901579a77c8e98e72889e48dd8cf4fd1b9681319670e510fb2e2f8f7a25de940b9885958777076c524d44d72c922eb4680a2c2fbedf04f2e0daffab22e7c3e2a3f2109d74a0b66ae3fff59aef3080a7068b426004f7f83ebcb90039978a3baddac4753cbfd49afca0370d0ea5f6af677fb0707ce94a5346f76ecda5487bba6818761fddd96119b40f7907acd1331f582c1032d0dc449ace1952a488a64aa4a3d59d9d0b41f4a7039a3c71e00194350b941106066e853316ab1b415e3155aee3aa91694f99fde77dc907e862a798a4f450397678007aa0c3251f10909a4b1daa0ff8011531fb4f852451b78f439ed394e8ffe0b0529388560fd49eba118995596e37f0e6ba6b43bc24a08bd05635358fb6eaf149a56e4e31d3e2485567af9a944de7b55e83cc6875528ab1d07fea6f27527104ae9979670909aea9dcdd1b81cd377dcac73e9d22632666e5f9f13cd50e4428b749af33672e29b03fcb125c0f76b370adcb4b6c05e838cb84d77a9b0ba6f47875c5573ad323ac9d86aa87ff88233a56ead52aa78786d23f0ad37c837773ebf6cc8c11ee1f8c1abcfaf5ae6480454496ee6f6cee3bb1ab2804887784ad17a32a18186fcbb0c9ec95192716298c7f6ab73514728e771b2c1cfe60dc2d10e4b26904f4d1523b5faabc7dc92fbd0113f54e6b4eec36de05cd8454f74adb477d825a0f9be72023cfdda975567bad92b5acb2dd892a45e5241804a4a6242db544ab63949801a3ee9cedd2bc598a6995d6d98b285dcd5a00d894046a080882eedc862c3053c15c104963ce9f4cdc7f9eea144db82735d1d5a5ba1a119758796897bafa6f6996c71d57c803baaad26e1281d5612990144bb80df2ac37de947f9728b274be4402638a4a93088aee0ca3a510a56be902b9264c93f63159486d141ee1f521897d84bfdb845d437c90fbceab28fcc46309b50ff7ba0d4fd26f12c54465fb776d60ae4a85a77f4b2c3e202db93d5411441f98674df2d06e4fad5601cc274dece6a7ef720d26719606400a6f33c033d8f8bec3aab3d0b8033d9d8767fa9864f861cdb8f4f683ecaa97312af1cf442461fd51d768bdd65ca508ba2756745bc9308b2c9b11c642490f5babf263d04bae62ce93441fe06616da5d8dc65bbdc3f31baf4f2676f0d40f2acffb0123eb492a41e8dd8a4ec0127f098882e4e63b737b106acfbb830acbb78360b8c7b064cf3085e8ab1a53b17e0db93623f39461ecb9c53a08fad4789bcaafca6fc6a7f14049b52a8684fd48db4b7fd2fb82d4e5823780899544c9dec6c116497a8e59054eee463aea5a79faeca0a3eb7403362af68d08f5ff29f181df334d7a837f72153d86cf9660fb784c14b5fbec280526a69c2294fba12aea163789bbe9f52a51b5aebb97d964f866c0d5e3be41820924fcf580db0725c7f210823cf7f45a0f964b14e5555070d1c3ddb2c281a80c7fbf72953031a4e771d7e521d578462cafae5a02ac8eb81f082e173ddadc8c41d964bbfda94f5180c8da28a8ebb33be77b0866fa798a6cca0bf3e1d985354aacc6a33d81646a996c2d873f79e84f62050243065ec4fedafc6db3e2185a027fb797f98be2fa49e914207dbe373393452fc5dc9cb22742af30adfc8c6cd1ea97ecede60b74c333dd03322c1943862541a24633ae97090c46013d2c356985542fd738e750c957dec1d3e2f0c531388c041703f6c07ff2a23be8abc19170dcc5b3e1097bd053309143e0b38a6682c32df8f87f8466df7caafd516a5b152550b5a0b4c0222e94e5f1efc4144761bace819cb1296af637ff9d06d6096734e979aa92acfd68b020d08701f885c64b4bb32d6bfb8229130bf3dee4d0f964755fc02ae63421bdf96998b746f8a87587a80997e3122a3d31de021713eccae15adaccad3804dda08ee1a7091b4eccd3ab624a479eaf8215d720a2ac1083fe5c59fce7a7f47971aed52b7402eb55936f2b1cedc30b2e1a5177764e246730f433f738b9a1982c9e376099882b53b77cb69b0a7c709508535e97317d06847e5d06b710ab30bf78a3d8b5de6be8d0eee9385fed7ef6d8e8ddcbbb04a7c904b689532e1744cbc6f83311494c97c1ef667962fe285dcc532a19f7574266f244841997a0af0ee94b15cc6f9f76845d0bb8add50a3da1477056888ff08d3308e0617e42d35a720fb87bc0522ceeca00b24fe6fce8afd21edcf8b9e41b47847344d937f31aac06a59b74bf478617c1637fa6c5593df168b8d58b1e923bf3e3d80e55d7170b16454160ab29ee1f7412ebc057b9585ea4fd8c16783728e734c99d8951cc2d092bb679a48990846da63 +MD = 91293d4167a5ef272fc7d01713f24e25f1d7df45f4ff5e764362eaed32f21f6f + +Len = 41696 +Msg = 87f6c62fd6ed70c0b9bed0699fac69b5b5be7603ac72cedcbcb00b84e9fdebcf85f1f736f6eb622ab90333a9a740a70e770cd02d85e4839fd154715b4b2394864ecbcd8d6a2bcb7066802e618592ec8d092bf43af6cd121218a413be47ba29b7ea6a9159ba17723ac91e09b9c20803da72052a51879644dc988938d6662a730a62b88ac56f16212fe8c30bdae50cb39cba80ba9ac1a5e1a65ae92acb2fdb3a25bd9b02f6108f9ef7cd587dec7605c37bea86eb3e2b63b11764ae2fc42b3646b303fd3f1725ecb23b80c6a716fe5bfc2109fe07654e387bd8c0be90e9e0a15e5a3cc58a4e369425a307f3d181047526331fcf5436b08d099076039563d8854cc271db2bc3ccefbfd66cc9435510bd095c35e31bdadbc821e88c63855a9b4bd694aa276aa06e65487db72f44b9aa9a6c425121a37957538c880cc8aaf5af59c578ed908f0aa55e873fee0c1ed55b74188d7e713639aa941217fd194a5d9e19e0154401e12bf84245c51b4a17d2aab4d6e6c1bb1a455ef57a3e683eaebaf0f1f114b65fa92bef794ab645d078d820c06cf524e798c3fbdc8ea4541e1e332b4bbe1c4b933032126b5ebb7586890e4301a261aedef8dc07b314f2c9a3e1f0d98e11d60c85bb67ea81497cb254919d9edf42d2678682b70ce1d5cfd0b4411a8122b0ea001d95f2fe21d2a00422daadb6c312f258c87e7d91ce99e46f3984d9ac6f63ff304405fcd6b4c3d073d8aa651513dc66888d33551fe228d8b01bf354e1ddf4bda2e052adfba3e2b3085e4aed423966d9ffbbea683d8549549b40d6b4a8d429ce60dac52cf455f8f2ca9c026ec59b79f1c63bebdd731fc6003791752089bcccd7721ba6a24931cc34c27b191027a3dc56e4f67edd491865838cf617c10dfda383de8a3d3683a12822f6e1d9faefb759b161d3eb9048d8ef86a25806bfbbff7777ae0ed111290bd26370b78855a541b6aa46b9791df7c72bb0829d88411c2a0f5eea91ab5ac3d993a038e66f48d1a8bce89a9271adde4ee3aa33afe66fb6e735de98fa143ada7233815455d6fcfc54331465451b6786d3dd1bbd746872149caf9fc23152d9f53e7aadceeb0498adade3d5b0babf7476c0e2ac29d65572bbb3464a6f1dad5e9ca530cdae9243456d1b93d482d9a5fb367bba057ebcf7963592c287a8a86ff1570f1c88fa31d92bc3060db9e38a15254f6e2dcdc40d940708a3ebfd74b9debcafe40787bcaf0f7137d6172bdbb5561a48ff03ac03b375edbf4c8955db3944e42b8cb972fbf62d4051f37ad27342b101a998034c4495e26fdff76337e50ee7945470faf0c0ed7bbf9ac5fe57b2196e02fba0f7528e9b22b5f20b42499b2110f2b0f692a9127c411799b56a62a122d547c57fa569eaad7fe880f0ee36045a0626c9874846f98bc66fd629889a46462df58f9cd5375fb33f300f0d2fa428a11359278ce56f7d0253f0da8a1ea8ab6bc037e2615164f595abb429cccd3c10df7db3506b32cba7c930c12c41f533d87ad4334435e099b43b0b9d55948fa5c3fa8d5bce8ef4037ec9a50c55b4d5e4d35cb2114080497ea58ea7121cce3e8749dc8b7a295bf6be0ae8faf6db4d8563a6f7a2fa5bab55bacf74c63c04e0a28cab6bbf37e73cffa5540f76a94873cf575935eb161f1cccf63bd6b2439733835af09170bb9298d6606327624d238d7969f2fdd78c133c76d9ef9db14e5d2fa9992035e82db1d6449640160609f5054c407b36ac85bf731a0cf5af0c85dd3cdcf2443f6db6cd6011eff1c6aa0645421085fbcab328ac2a823655f60b119fc3e30c6396487e6d9d0515801d966c9bac8ddf7ba0349e61c774001559f51a2b2a87918524c1ac19f5e7adf40511627fab8af702a0770e66b4b9113fbf14c70adb9026b2d01f695ad08162566565107aa7d17498b2c3a144571913da12ae41c33cc675f382acdcb69699d9ad24d89f130828ff45be627e821a5babef390cb0deb7f0264f22ae2eb7aff8bd012cb337d336584012ac9acfa8644983851c763be3b3d8e1cf996e86e58466b45b643eff419a29de0664b4b93f9ca943a4a3330a5b98444d7acd340dc77bab66c2b4c020e59a62822acff766ce2c449354b68d46cecdfd1258a748eae5fd8e7d3e0483c2479fcdd384d3adfedd7be2199e3dca17c2bccbd9710ff146c773d89ed73ccd0bf012307a1f591ca8f4f14b80892033a4c1cc754aceee7849f64351739645e7266759541e004a8e8d9cf6466e1e4710165265c50c762a251af9d7c1a48205193934de0168318c49d55cf29c8c649aa994feef81c871ad40e25895f0d9a365aa6de007feffb90996a7bd4d1581630245474bd27225c85d11c89ce7a6b9024de4e9f23e158da0a7bc2b466f79f523652e57c37760cc8224e0f54c34aaeca6a60dd6f2ea0cb7ee50058b7fc19092adadaaebee441364a7e9f491f0e3c51b98566e5b6872ac27acebb7ecf0a922fd08c0022b53a25296409496c3105ebfeede474fa1dd40bd85e2601b792290f6e13c887e407afae60a530c0eb3350c600c825ff8cfd9bb0778969779579cdfd5e452eb6552ebb29867eb3ba48ae6556f1e8b88b00ee24b51a9d27719b1e6fc87ae51d301882f342e550d08a070aca1b6cb02a9c086825865c09dea42ad8951d4e84127980bcde6707ec35b498c0e58fbbceeaa705e404a096400d83d730c44843a2acf73034d322887141ce80794e20798577208bfa48a063d0127532cf73f5e4b15b2da97387f1c1b0933c508c6a8a20846ebd0d0377e24f4abc0c900d3a92bc409ba14ef143415e0a88928b82d1093b4c1fc10ba808f2a31038bea1626eab34c0fce6b346cbbdb7efb04593f5083a443d38d0fa40825e29b1370fd977b6abe8c2ed6258ec57b369e0a8d9fc4b76a9b5e818716b755a912dbe25849aa5790142c6ebb8b24a9dceee8db0d446feb2b41acd5d06d1af18183997829177844c67cd3d763e51f9f46ca03796a8e6973305ed6d6515cf66417fd7cdecdaf29c974c02972b77ba630219498e98ec6dad7dfba838cf22b7334d2482c1b2a59e46f00a6d8469f94e2e2d5124e345f33eaa0a21c5c009c21b8eb192b52372a5dd1bcd3f7855b047afb40ca0dce63c71fbf55e04e08393587ee10566f963bb402193a557adabacc7318cf694cbf7eadd0847e0016303fa6a53c2cf0dc9f2eaf92e471eef97f6ae1c861191899ca8bf88f5fa46c3d7c1bd8c3cbc64f3a1618055359e8073a1c7329c1ffa540ba979492a4784e8b8b93d4b229c366db51a2019d8ea127060758de8ea51afb4a78cda06257f804c5c71e721b1f4b95fce9ecf25f8ae3b65526dbb2f7bed9a49c9b14b850f0074e82bbc4fefdec8bd91ac99bf23391481e5a5f4ef74b526527a0eb16e344b6ccb52a2d2e7f3fd9acbd9dba580a01e9f8e67f7c59b674aae60cbd30782926f270c025e604fdc92ed6c6ed84cb41b1db1a962b43a3f6590e83dc5a31e592deed1af8dcaeed818333307e72ef9b9f2bafd7b6c57ed5bfe2c5641ee1b7032755ecf3e3b54c9111552fe36c94c3712c57ad56cfb7f39619f719b25ab98a7aef713a230b198a99b8276c1618bcc7f4f11e1dc068686b8f0d805095184a72f3f21b1ed1f8712ead7be130f20b50c4cdf566463c0a40ad68a265b334e1fc3716393cdf2630230174646bc49fccba82a3401971f33ca783c8e18e8ab83c37a08acbbac6493d99cb977aad7044e360c91fdb1de60c8605b357d0e41d48b26376f8b17f1b62a73954bdc58f7b0ad9ac61e9cd5cedb070c206be7a4db30dcae88107f171269bf46d638f4efa2f18350411a81ebcce07834644a5e4b2962f0c2e8960957a2e1aae9cc2b51cd4d2977fd2a204d727d03846fa35b318fc0cd5009e56aaa4817d075c2d37d63707adae407ddda7ff843c6c4244a0911d115e272f9eaf8e276d598b878a8b9aa8790886fe6d87369ebb5acafd8d4fe7fbdbd44e20975eb425280bceb61a86ab76142b46440a6b5cbdb3727b013e085cba41b5725bf229c3a699daf77145efaea9be5d1797bc50bf6256cca6d6bd9498632a4bba6915d964b3a8102e4173904e4a61e72181ebfd07988bb0740274bb44fe80dc4fd16a363e523df49dac0c2f3160e4118b89ff3bdd643a650d0fc94408912ab1591b5707fa8e40cd693c7895fff32f237e3860d2e9d04b34988526f98b261012ffd046163f6c99e4bd79208a610c2a652114768ad2e3a7653deaf2a076c41a4669779e29b6f63181bfea6ad5feb1bd1f9da7aa2b40a5344026c8950270743097c098c7090633eeeb9717bf4080edd0981979627cdd1fdb0c78a677e7223d3a4b2cbb297ed82bb96c6e8888918cc54b19be1007464e5885135e0d0017332720abd4692c4fd4e77b4a6cc62b91cd4316eab3f602513e58189bfe8498594c3acaffe1293846a16e1aceb8581208e86e195321b3b96553287eed8093a776157f208f7a84b529e8c880407bc6a3be884e3d9c30cd964a35cf9d510dc2953735fd0ba2c8010bc150fe93e8dc99487a53ec680c07ce00c78d555f0ecd9aca6155bc7182f328a2d682173d0d04586806f14f83eccf3e5fa603c3aa6ee7a2aebf1cc53c752281e230251b64f91a8b6a280b7f7784afa31aad3e2068b78362a918331f52c47d953496e213f2f247bab8a949852a1cd0879ba5e7748032cb63243341d29db72debfed16106ce41b36eb950526886fc5a714955a5c8da27e52c85d9efe703955a0ba9aa49fce02e852ed5e7cf30726c74ea8c8721235edef94636d2e5656ea82b7e9ee643fd1000e683743467e6d5b34679cc01038df49e30379de6ca54c536c9cb4450f6124601fdf4fe01c391991af9a6718cf20e84b1b18924dd47bdf0885c7a02af0b426a77f309db148a39a5e9b5f9e3f096aff65da5c3327e03a7d6e60b1442ca299664abef4a743565e6e168a1fb8bf5987732eb346e2e92a71a6197fe206b6af9141ce51a402f2efca135dee633cf63a06f20a3851182e1da1e78e55e26e55722c67b6d9b7275c6f6718995ab291801559da9ccc134953345bc031653ae17594db4678a9b68afc4fc5fc5d31966cf98600bb3af0f60cf508ffbeb7304416b3822e5c98542ab43f1b572d1e158715af068c12795981b980061e416449a6648bb48618aa6b7c29b15cab295078fd223d116c5eec484f0580a637d6dd13ca616ac6830903523351df8e227fa8ce71290031221ee85fa6477373cd0d86113883ed1295bc57aad8d3361a6dae6ba87b80b4d03dd111f22015d4f95e5403e479426f234e810bd7e514419bdd242d7974cfb7992ff3edc254e731a15c28baeff5237d930e25845bd09b7e9d117f72c4157c84d66915d022bd31f5f6571a3fa634bd94dc64e875b933ef69787b2ec01ab60d992289a55da5b19cae82cfa6e6a9c0675159e368447287668eb89aa089efdef980f7f2310acdea7dd7b1363d645d20b71fa5fa13751a33c75af7f07354a608c6c8e143375c0dc05bee1c2b6c2d52ce337c4b29888c12d1585a910d25a4efcc0bdd58ed26c5d7cbcd7e2e0fb1960d3152d3b3e225fdeed8b00a2e5125ef2f812f4ae9608ddcce6538f451538c52fef29bd26ac47a4f10c254f63a6cf2b7e7c0b77dfd4deb05643524dd40b77ad8aa7a84e4fa30f3f42b16cd8b1fa11a83ab231af30ef5bcd41bb427b5567bfb9b82319477ccc83181905e6045789e1bd6ec00f046b90881dd575aa8091d419d1038c041276cfaa18be301d3b1bfc465261ce2adf565e6b865c9a12c450f88bddb10af11605538d25785999e6c7fb494f5c050ca6bb020ff11c5102af597b20c50bc469bbf000322891a8e06b212df19ca78c3cc3602379475ec303a97606dd7159e3f369017fa30a4f467c34f23b46228a8c429c0d6ab36e6a179c1a6d41cccae38e1888fe78e8b1fb5bf5a701cc50c74d2da79b8c7ec4508876566a07d3f4b6f0ee5f80b0920707dc0ed12e188918743796f226a409b4d40008b8010c655d1eca2b50badf760af33c889a30fd1aa51291f0aba71cb08be119f44a47449e10ebb76c739c53ccf85c61f1d7157926ff87a3625a85bd1d52611d6394a57727140300d9518fd33bda2c9470114454552fbdb51588284ff8113b527c1f816ca77150ed9b71fc296bb74a1d2dcf2756513c9a0f31bcf89ae8ce5701687244ecc730b9c5da5b491b05979e4451992547bf2e08f9dd7f5d6596939d714e1557bf2f5825d2bd98e072b183105104f7a6ee4a0eeeba4158bf7aaa67f5ec579120ad86f17e5a6daf27f51681888b6d72121498e3339b86cf869fcb5347b8ab6d097e7404aba61228886edd9cee3cb591d28151b5c1e4d46c1a9da15d7b1e713179f9a39794fed38c69a3add92aaa03dd4cfd1e8c7fdd52b8e33bd5907966d266d8e7b8b521a9d862345e2f42241d80dde950a77155cd293a4a430ff129d8f5938d105e633af14a3250650bdec5df54191141936b2bfe807ab57bf68a73bc0340023c3babc71c51852580e8b5f337a6192d9a8a83e9b680018dad3362405923f59e33f794b07314e11b796ed0976c9e66a32136c0783e51563b9f6e8176f87e3bc9bc3b26dd3ebcd19a1746369ac76687dd9f3c2abede1a02251a4ef0ffe13b99eba1af6a36c570da0a2118efe290230441db47c9a4dd048bb5e57bb6c15c83986ca8fa67a44f5986d3608b04590f0066399ffda61285367b52ca9edba6b17ebeb59ac4260d269e5c5d9c487ce68b23332cb106c8f11cd859638f5f68952753962c3eb7ad5b9069e4119cf75f704eb4f682da0b3727eb14ae52fd656475072ba53a5e790674d6dfa7552a3fb6e19edc34a2e2b4fc9e3a100186dc59d730992d7547c0b23942402a2c920cc88820c4c277f691a81e3c51f4da67f4e2c9ad25828dbc2d0b4cab1572fb310b3bdd15089046e5af90a5eb77e9c15d0ca943d4f35175ff6d2b49999fde9d98ef40bda8b16b2ad703139a92f5173fd0ee554c8d4bc3b67a48bc37f324979931807e31c1097daa3456da041913a5db28608fedc07400d79486631fa1edc57763869e404856ee4e65708ceb6719bb1ecd2bff2d55b72f60b4eeca088a428ec095c847f325e1e69ed019d257664f838f28174c14345c78d9444a99fa986a1dfb310f225140f28c23de195451fdfd22b69feb1faa46ab04cbab6078feb2af98b09e23d76281d00864f737b9e0146ac31b9b711ff871ebfbbe51f80d1ac057286844cc0d2ed1c583e9843caa0d94df8c47856ff5059e6685389edc0358ababf4a98bd26cbe1617253bebf1cedf63a4a5c1c3ae48d9b662c8c3fad300c059f325fedbfc9e193a0f15e1961bce5e6a013711bff6c17d9f28efe6cda4ac59b377e2 +MD = 491b5da9bdbafb93924090114bf8ab7ad14e7b771248ddf06ce6cfcd9a55a196 + +Len = 42488 +Msg = b51e73f84965d85ca8ef84b9b2aef2aa6929de10f87262abf5585fe8e3dd1efafbeb372c2c42b27660b56d4e0196bdc0bb6f58c184f273c1da33277f4c1519213c025a84e3e08cd19640475147d8bb824e33966a6aa7282b0288c4d8b19b6a8702cda4a77825ae94d2f8d9698c5c3116a9de5eb2b078c812f5bdff9a19575953d4b3dd3ef2fb5fe89c45ed3fd90a6aa455d97941604c9d9d393c9e6d8d312eae3b1cccf05a49e9f57d8f497a35caad55d88bafc0810dedf5586b69fb141130bfbe703a66b7f792e2fc3eb6c3a9844150bc5bc7d71ca20141dab42ae9b6dfa8afe518ef4811eca3d8a2bafcc23c206fbe88b38b2d38f321aa457ea7e27b83dea5387ab33d711263fef56be31ef6867fc7c5fac16bdde894582330a98c6ce51aca40ff4eedde501c7d7fba3380df9eb992fa9732381369a472fb34f88f90eea445840f8701608e147cc80db38f00516448aff4a63de35e972056f15c94f084c33f8c132721ffb4952456cd2cf46085ca106d78e52254afb68cbbcf9d439290c1e0e171f7f4c4abe59cb363675607233113ba8bb68e6f4449dbb236824380fbe44f0a93bc23b6594c0d6735295efe14e2792195e2293b059838c38ed53dc2ab75b58fdf4155dda7149ff8ad3db44c3e256927fe329cc0dbeac9773f5cd85e8abb39f9bf4d33427d8379f0326afff98b420b562f6b8f06ac89b655b1e0bd5e7f0004cf9aa765ecc4e3c4d72b77e70ee28088358e58a91662bb28e64d2893c9718a3d99d81892e3627aa733022d16922a28084c84c093f7e3c947b079fe03a84aa30de0e068623041914b8e1e54318d4d82b2247a6af5b119fb3a3d9e28b502f1919c2a1c5f7fda476fd86fe7b4e30832d6af44d61f754dea982a15256f50df4e9c1102f3c48ee95e5e755fc514d109c16c273401a7bed240ea3ebe749b7d48490e95edcd613a666da44ae5203da69be28b417d64ca764802379fc2f574e343ca2d4f7512fc28585c8a808960f808c37d7d25a6665046b718c874a90fc12bdbb94368212b5e03c713583fd3ed0ba08b7a88fc376e00d52869e5e6f9294cfc15fe9607797e4f71bc7956ae4c303e15fac1f5eeb9e6a3cca2dfd51d3caddbfffb816e550674971a3d78ccf67b8f5b0f183b0c22b33501d22e61e240f90237db942b157a4f76fda855f7013ee8732838eece14c1adc3e290d3d85277b9902839e8e2d29dddea4ac009df3eaf1c456f35836357f22ff80ead992a6eec03bf76c1008fece63639460c6316cb719e6bf6b1e0e31bdec23c4cd288407ec45ff7e81ae31bac7ee4ccb9346a85f0abf64f86520b34a9acedf766a7a902ca2a55a047ed996c5a8d6f0a6be02614f586ad57e6c00e404985399122d3035899446e225be12b6c3e3a5d5a24b7a0ac21294aede0a4f1ed42912d7249ff9e2b353a31e5ec9fa0019fae3826ab61df33bdbc55783aa6ba25def75102a3d28361e4352752c2ce0015c71187d5c987eb9311695760bd6d73cf63e02daaf7f5b9e4ef5dd6cfa417548ffc8ad3cf46d1cdb26556d70c31a223d31a734ad00f0f489a9ed9c8c55c22a3578741a37beae68c7a01ab5de65eecd3194bd92fdeb1c9396d38d2859db096f555b05f7f437c6f30d12c9171550bf48a883e39643aa6cb9344076f93bd691c5271be0cef8ec613c2a130309cc10262500a3abc724eb5bc5e0651d97c8f4f5bc393fb6f7cc58e7b49d153af659209dd2d86898ae080a845a39d5f37c87929fc4fa3adb1ad4e9d4ecd49de365531e90d2ae571ca363a460d69f079b2fde5c1a6ff891df90b92bb3557f119eff2046a9b4e0d3ba5fde356bdb8e7e672a53add02da2d93701df9afd8edb14b00c774532fa2e72e42bce2a1fc986af09e47e046b7e877563e6bec43de9a71bd9159ea6e702c5b94cafba1ef731261dd5e6c3fc46e3150b08a7dd13df06319b8cb32cc8107f652b364428707c92db4f6dc9bbf1ecfbe9ee77cdc1166b5529182d5d983559b08b2d5391afcb3a7f24c833d5cc81e81964b443e0f1586d66ec163d8d678b2d5686540700a68b9b5670fccac37c28a2dc13d0ff59e4465fabf91a5fcb2125f5d20513c329b34e29a96e6184fb5152b7a485e90cc1205caca4eea8f68f4b826da386013a753c6f6ff87b9b14e5d29c91132940fe9f1c27fed22b2684524d4cdf5b6790bf6bd87bd8b4171ddd2b8662c9987c9d374c6e24a0c43d379bacacd1d55a4836e485edfffe7ccf4e5034c351bbb4fe4259616cdf4cfba330af06f0bdea2096882c4c03783ba302c1108a4fc5f1f93cd4d766bea45dd8ebc620f9af6d886ee0f90936af512ad7500a80a4524c06c5b6c933e4ca304dfc754cb3ed4f6d2a75a60dfdce4837468a457f430b916064bada93e13425ffb7c6ee58ba5a47396ad5543b9c8b7477192c51b3ba38739f963936c981fd487f05d8a56eb6d92d5ea41e8a0647f6aabd0d3de33c68a37f4615d149de78a8a81ac2a238f33be2684970b195f292885155bd5f987dd0e51b105e03824747cecb6f78a4278abbfe9e865b2f26850eb90efd83d1dffc7575ed7ae9508e9871c838e9825edf99b9962691bdf7ba321f114a010b65383ce8ce6ce24238bd46892d67259a42ffa4a731a708339bbf9e4629990cbe6a2fb38d56ffd2f34cace5e076dc800af0d63017697636369ba50e066a527d175124f4e5b83ce976dcbbdb2a3d1f956ed911c08ca63ac841680925e23c2cde90cab675846a9a82378988bad8d896e2307c20da79606b1aee916a5a6c477eadd53762b9ebe6af39dfd391e94ee1d8e2fa4a81f260206dca8898373006f4ce673f17a8467ea4c18cba3b460b2ed16c0416d4c38cc38ed943ca0cfe2b44dca29748fbf58fdf2d97d751313374eb3fb6e230ab541e25d424030d303dc0985781ba7d44e91a6ff998b65f55e8daf6754ff9b22eb23b09c8e4a4dcc2548483fdf25d6692e15ab3913aa62f09b491e32aadb725df7c47e1b58195b33400dbaa585adc7f567ce54c7cf4333acd453e33c836a7065e00e9402281522af5915a4dcf41d432102a2e8d155bca1d2109346ac6a135cdfaee8397a86a669e97a47510fb4db1295067bb1812e7f740a58f18faae441ff766a39b7abfb34fa89aa8b08644b51fcf87b40f5fde1f274fbb35505607b5922d01beb54bc0e279b36f2c9100343e5c9f26ad9fd6df67f684e29a7f1f4b6c48b95c9e559d548e7159858e9b2152401402dda2d11faf58d1aaac2cf9b8e1dea036e7c0f0e2030dc3058e7d436c2740c2b4ed32678cc678350b887b54b57393351033d51bac24e6fb31ea470e431bd6e50005dab7c0ad4cbd3207f41497691083ffb1393a6e62a06689199a6038b868e77e981a563dcc2cc6b89b25cdc14aecf93fe07bd1bb24d0b155acd5fddf758d66ab146fa766bbbeedf9b29ec4e5916f216b620b75f4e3ee483214881b89ebaadf001b593fddf4699f9ffebdae56c53d790c86669bae385fb7a8d13f5dda8347bd081d4584060ec357f5d000fea76ede8c9dfe1bc7699abb6c24635a4943c4ea9d3d8ad318614332a3a5c7172a49e6a8b88a19a96da97377f22f5b6752582919dc1ae48071926a6e1f2a545ea5d0d542a97b698e12d06b1bd63429f4fd7a384c062adabc03fbccac06fe084615bea322cbcc7e383b80da1d74dd4f71cf3c7b07a7d7be04641ff293078b437bee85e8df9c07c8466c3d59037a854c6c3c1159b34dcc0ef7f67164a9ad7c965e94a91ecf96a7c8270958606443c69142c89b6cf544525de55f829b56452c816c9c9aad7948470e58b78478966d1bcea3f93d2d4448151b7af3e62f3f8b2595248afd2d632d4ffb69eb240a3052ef44fe42690306a58ee82747fe78bbcbe23224d4230723b24d2fc908c9adb891cba4c038c186d3091a1458e04e0051a40cf8dc1cced32173a90bf4b4e7db95b63b6e8840b9312fdf6140ae41576ea79fe049c8a93309f2edee207b64010c6e1cb8f2b4fec29a8384defd85ef9d0c040c26b5691e0223fe8da70ddb9aa7c89841cee1d4c7701b64b5fd9b8e4fa1812d952acc3befaea9daef5e1483cd3e88bac1d7ac764f344c49df47bb05e5e7365ab766eebfa2bb23ee6f6de5127047d52c297dc307daa195b96d47dcbb46e0b431ef859d72bb99facfaa60eff628563682c52bb6080e2a9029ec6860ecf7208339a9f168e3aeddb6e50cd1a5ad69ec1555416c06056e41b411d933e8395b292be87324d18100f8e0c5233a96a6997bf9fa0ab9337e5f898a07b034f31ef75cf6a4d7aa57e9367df0e669f643804b787d07ad8dbed176548a820de5e20c505eac2543fc7c7ad3cf7fdf6daf2cb90473e6f4966408bd37552e075ec165900a8094b05485bfb45d8fe6169adfd2bf38f0f05751e6c18006edfd0e0f51ce386a7558fc65f082343811bc027dd2a6117d7201966c5049c88991601cac01bc6414af515004a76458e8076a498352374e26799338326b320523e20fa9c16b90b18d811651cd24e6c101d3894247c906c3e86a3dc36081faa46a52443bcbf9eb9f29bd30880bf389db09f891933791852127e669ae732f0454c154b65948373d8b9d9618596d9dbe2565090ba2df5642d469509f8fc6dcff64cd8bde78a2ae07154dbe364c5e8e042ea7676ff7ab81c05c114b47bde8164c72e34a151087b8c8aabe9822e74b3eec6555a6270828ae7e26d4391adf53656bfda721f2c753f202ea64a656a0d03ae747d447d96ad336dcd3169c515a9544de639d961ff393e43622d48b6a0f7a0c8564b7beff8647a57cdf5cf7b3b63a2f34531b38c52bc409e3028299a589a52e374a749df1e0d294deba1bed9a889e9ede3ab46cbae650dd99f7f363b1b5ee1a7d47af475911206f62e1e7c07e385f1e6c990dc44999e6c9bb71ab7c170ab14be80aac5dbd8d9dafb9e52512e74bd8284fdc6bb1f9dcf278c81e1f454e0e9b4cd802104367bcc6c0343268776e49b646f89372b85425e045504bd341af280897fdac5f9b1035186b726826506ba855e5074c9769e0fb4cc9e4994c13e2ed85b799880ec71f7d2eebf4e4f32077ee53acfc766e3918c39460e5650e1e61c59f266c23924a1dfb66dc2c37337a0b922be9389f5b98741553c4e35d7dd3b456c16ec5ed8ea674465cb698ed8bcfaf2a4b345c25e41a7b7717406ee13fd6430778eb3764486ebac47d05bb664083cb1d3e08c7b89c31a75f3b8dd87ea888965e4236411674056a2c444404301658f7e170f11bb5e86070345ce7b0a46c8d46d199da738285fd0ab44eec23e96191be2d8067c8ac5d497eacd7e897e0e036bcf80c423f26f2d80512f9787ae0b6d07647e8e74f0a6f3f1b1f592afec2a8276137f5f814724f08f1bed07379b48a97c8d716fa1f6e92c3fe024d0945b818d1ec28038683f30f12591e6067b0d3415a1e31971aca376c7a600c102e1d3fd6b8a63ea1581e37978683c825cfb0db9f99ff0df5c3d00350c509836ee3d5d8566e47e25bf743ae8cd83a32ad05ea2be9c9d3c29f7fb130e436530ea5d51ff02c4519b99fee84c65379c4f442c4cd52c47c44d600b8fe6eab30c504516c5c35acefb43ae998622d9ffdcc63a366fade9423caded60a081afa56e81afe340b176cc0afdcc5af5c32a6e6a9272b76c32ded52ce436bed7ea4761b34a908a6ad03e06a6525b07dd3742ca6f3a5676ee6cf348bc78a5eddc2b982f023450d4ec289ac3f5c9c369e887075b12474c3d9b6411e216f3a1b4564c8c5783c657896ec1734d22ea6c48bcba636b7c40bed21b211eec5fdd91ddee530a2060880e7197a4afea533dbe6c01d83d40d4ad13fe17ab03aec2bcdf2e4b4af9d4be02db5310d838e3b14b229c60ea7c234317b389370ba970651af270163843b9c8bd27f98065f480639bfea280f70a5cf105063b2248f77a707e326af626cf17a3405b299054cd0891b5bb440b07ce3305ff74dc816ad4130c7107e6941b85387a13ddace8acaac56522c24ba623b0f0a78d6533fb7a2a85617ad9aa971f4d6373bf174a2f7572fd05697a7efb5198da01384109397ee01696211080a83a0fdfb6cb6fca0eb70ff999124aa7b29b6e3a38877026e281de0fd3ee142e6f75b3f56cbf4ff62c7b68014aa69c8c73091a5877035a529f880cb8426a4e7c93d721edbd241e9432c8655c3facd7f7e5a2857ce4326755189d5258081c2434bd69420fd080446dc7a7ee54a2ac62aeb06e95eea79e00f6f4c79838508cff1c9432fca2ce5e2949941feb2f982ea7797d7533f5e9cf8bfedc0fc6a1404348fec13a38f0de4335f0403844364bbb0d22f4c048dbd24c7236777bc4d900c865a0eb89df3f29b9d02974fae2b1e3dafc6fbc56bae6899d1b636e167a28b9a3c0cabb28d7d8d74762bdd86eabe88714dc2a7e3f735f374af05068e5d0d8935dbf46d81e0a030f765375139b882260f01619e184598e03db57c40ef2af30b57dccdbec735e08f9cc0b17ce8a61a996f610058e2c56ba16d9ba860844fd77488b4e509c2fbd2ebed3f26bb0411fc350ae33b52c3f512c97cc805ffde3a4f67310ad6e925b0ebe8613703b62caa8b9b6a1e7f364c6312daf3a111795d88af55f9350fd76ff39007813ee4d8b2de6d3f2569585dec7e00386add576792a99bb339ca1c5ef21253cbd5bd26ad470c0582955a334414d45f643ac344451e1b79218b3078da6cbbcba7c73865ae59d1d9286277bc8355d48500fc09648c406cec03661ea1f4304e5c1dee470e565bbe7c72e5383096401d157116f634b7b9fc58eb42db2416dd5889b0b34fad3fdd305404c6125bf7340c855724403151eb78444bba0c8bccc448e8e2aee8beb54ec5f4506dac8b10d23159059c4de6e5453f32a72409257095cdde364978af6130edd1d8445d3a8d8b0a151ef795c1ec57dfa88029879dccc225ee2e0b961bde1416712ef2ab06c7cf152df5beae6ec1a3c81a5922de611bca0f9d2c7db7705678ee56a6f11c6c5a2ee1184c69fe2a1fb9970ca4b893fc082dd97fd408634994cfc3f6e2b837d7bf2aec7865821ba050f9aaf3f5533edafc6e11ea97441004039945d664c073d5513395a2e38f7d4e0ff4a264cd7b359a72fb5781f8a9443c1d65d279af9266e1cae97b4c48fa99afa72aebe39f992ea6f65608ba7ab0765e5ca5f86515b6778986ad1bb9084c0721b11d05d4de55707d111ea4188ff23ce74bea260d59a52c491f0ed59d940c3c60a84b7ecd1c08a1a93db5c800cad6fe736592f9f6cdd6fb8cfe7f675e9eb3afd90726b540db5b38a7e6abd3279de7416f2440d295f4c47bd19f8f1f606acad7f7584f57b49e95bbf5a67153e18b9b8c4722644e8f611613c39cbe8c679aba5b481615c4bcd870921ef796c8c3167c55a7ca8ddc27851459bf507e2cc8a11aa047bb1a8abe0b546180449cb040c0f233ed972dfa12f377c441654e8f0800642d72d1ee182cc9b990c637e398ef0da58da512b526c61e88d9d645c011aa5 +MD = 787904b92d11b4be88c6728765190713532d134f7e846925f9ac6a6667ad7df0 + +Len = 43280 +Msg = 783dcfe6eee019b3c5e1c3e9c63406ae0ed4fe7dbfab0026f5b22d16fc5947d9c029c4dd84a82179d77d792dc4d4562c4a04c7170c6fb30c48aa6cdf0ddf87a7a96fec7d61db298066e40c1d04f1708d1bb2579ed30339b78c139c1614c5e55d1d566e4dee41d8d1585fa33eec53fbd96b25d59a7e2d3b2fa733e44478d40802032772d591a1d7739736661ae5c1a01821a66a9174b6617d83536df0a1d4999e422b229eb3c4cd6e09b17e3858050753257d3e0d1d6652a807ba5fa2f78d3f3ac4a7a42fbd7363cb98181320abe5d7925ff27895e104b7b81ab2e1e3e2c6a3dc70e62010157441912bb24c5b482ab9dbb74d41b2285a37b6a6811b39ca496d8f2e2fbfca258f0ec8a9c85270959c543815d5c0ea5a2e7ba99270362f17dc4458e6c9a8e4548e7378fca24de7fc0251b061d31ec8df492a99c6c75a4a3148d04180fd05e6093717aa0b886449e325574b838f82d11f73ed8e29ceae148054ba51e513fb59ae54a366bec2bf1cb4ce0f126351158f83736c91a5cd5b146dcaaa90fb53b4c4aaabbeb2fd9787ebd6c3200ce961fe8971134ea9210b88d25e704707ab0458af65051198b051e43bb1cd3442fe06664752193cdf86d15ed7bc103abdde700ea24729431fbf36fd96adb3f0ba888a75528f4edd3aba6705aaf0702aba7addff26b8e1fd4f128ffb83323ffe7e703352318e7adac2a615a4d36059c007689453c220f3e73192a3058ba83706969f4a266cb965da7f322364db7692a4ab91dd31ffe728a8cc25bc44347764af08fc16188c77d6867a47d86c4999e57daedcffc1647548e929b420e009078ea2de6ee151182f9786bacb7de5a53018f41930442d79321b514e2818008fc17c8720dff1f9984b6e8147a85af678a5f4b0f377f29ac68768894567eccc500bf805d43690379432241f2ac4b7c8485f415a44985232d4daf938165be46dd34ec8c4045b0433954c81096a09dc82a0c6c799157bac1d2a949407c7ea480ba0f3b56db735951622014ce70f5d104d05424d166d084883501e029e62fe5fcd406087a8f6ae8d08c4b94f6022aa9d51013b9d7854276d8bcfde0ba4ee7e72dc3aff061cc8ad323002dc501da9d7c9b51b197d68d2c0655d2e3e76c27452c9601637fa72351bceb764d218c6afccdda2dc44b68ef0bb7622f5a50d9ffb62ac805d6f2a5145dea7c472036f023971203fca251091b500e902ad7b96e48b96636496115f6201df0580b5d81c7951aedcb56f22521a2a770624dd27da382cd635354984614d70063213b4b7e9d4fe6b572b53a446d0550914b10d13a144e70a6c1bfe30f8b99a3c75a4f7099cbb4990dbcafc14b25c409c5dd0c5a6b3afc31a4e3d3e7dec4e8867155b0737fed53805aeb9f4d85f65f31927aa8e48d722c9ee24c490d304b541705b616ba7d7cbd6b21821c35a15947469bb67ef61d745006e35d77d9a0996cd408fdeabc3ef44287f632aef009b91cd72612e715979bf7083cb9f8c3ac49835bef9f950f20de93855d5fb0234bb03061e60279a99863921132c44451bfa6480d1e0dbe19bfb620d1ab8bd845d3b922554027bf587c55a1c07a1ed30a576a2b6638eace6287f56afb85297fbe2e4e734fc8d52078c00cb684872c2d641fff9e05b4993e800626e2715ecb2f12d7eaa3afd4ad35a11fd330dbde7ecbe555c1105a05ab86e8b6b517c1bcd36eda5d18340418127757c853b144d4893704b56932d1c0944003164a7b6b03f4a78b2a4184daf7a75e036608b84e2dcde7589b52760b69d5f265a131adebe881619bcc114692f7ce624a856ca6563ecf654794174a7566030696e4250fa2cf1c3582bee1d9ca9d0a2c8392fa0bfb7c0039581c12309e498e050d5b7f115e2c279bd68f4dbef05bfd05450b2b79bc8a02cc10bffdb8f498e9664f73ba634c8435fd1d99bf8692b8f995057a9b4007dd4995f7ec145406b8a7b2b3d951761c6bc9e1be7aa191304882445b5da42f7bea373f742d0092433d3b72f0d8feba3c4745d23faebe8f376f49abbd20d07877357e211bff4ce4389b371f8d0efca03aab4c5727b240d146a192238160cabb884360d365df43ca65670d20cef7e5e8760c4fe8fd01e307bc941e546e99ed792da891ded849afc54805301f5d0044c39ceec2f0263a1f83279b20a6cb38a331e5b9739bf9cacb655f1a4263bdd493f21dd7481549b750d4064b4ba33dc996663f0aa8a330df311b28fab6b647d14dd4673a31b0cdf6118ad70911d21cc931969820838d13f37b67244b0f6fa172eceb079c225b2992ec181878f5ac0eb40f339f7fa6a219a404d9df7faef851560bb67d819c9cf30a4afc590f89a98a2679dda39c848ac87d57d3c90d27f8bde704c7476f02dea0c8b8b817312042f57d2be542ebafbf96cc0ee55f680ce96da2628de3d8f798b95abfcbb1826c10f7347ffb0c018ab90b2c749f3134c032d714cf8ad143dd63a33ccab7d677bf8c05f8f08f5d6297ffac2b3361bce7d46d90ba863e9e2446c804eb53fce485bd2c88272802b5736a0be024b5cd70f5dc1201004129b91ea62e44e2f61b7a30c77b143b70f5b2d873664dc59642ebe32998de826accb0878e0ef9b02b93e60d70e030c285e8c3f646875b7a3f529c445f9a5fbd6da7f2f3510279df6ee6e6704bf44448b15c675155e78fbf3b8ce07de07f2b2de44c1ee6b1816bcd2a94ca0dbb4fe52a9dc11b7e141f50f0f55277045ebfb730591982d602044616091e2f3a412b8a04a5976ed1239745dbf733ce7c1ce48a7126a0dd45e5138f2664f3749a604fb953537fcffee6d7e4ccdba13559bd862b7ce7626cbabd27ad9ad8a53882ab04e99341cacd5be069a44ffd4b6a01c30d009015eedfa8fcc927cfdeb3f9a783e39140db18c58c92b51ad1f662db289ff1a0772c96a4a546709451e1a0265d8d7446e899da76e59052af0f31b7e712d6cc918eb60a4a140ca659bd7bea4d392a3f81070880200b4bcad734498b3c74fa064a332cba3e99d1e31e5f17f2ecbedc9dc608a1ca7f72377629fd988d49b36c2731211b16f08b18af28d3507a734327179c79ffe9d39ee5ed2dc7c91e7d42bfb7ecc4dba11e8c53732fa68fb17f8aac555ae76d9ecb05d9a8493f35bf65c76730e39b18f906f204d7894550686fe9aeafa7bd8539d42b853002a078f081a5f51aac104d8f4870cf34dc3c3cefd2e4d0bf0988d14b6d946b0cf0b80d526f62ebedbcc0d3c4517cf5138ef79fb83700a4ebd6b5dc5425c50da789c26d457d82ae128c295648c06b290c180403621ac18dbeb5e100e46b31ef98347c135a3a89ce3190b64f8d13efdd870dee027decac0db02d76d96ccc6f8347973189f124ecceb360f429f1aa6f850ce712175c2b24a7688403d06db7d26b3e187f4bbadb302220837f7017126eb2162a2cbc8d54dfed3070048057cc0ef9f43ed1d317bbd86af16e94ac7dda61d72b4d7a5ca2081231b067f563cb6779d20270c5ba884559fbbe88e0599670ed76c4d797821aa3703750e252f53918a765d164c76c9d164976e078fee1e15466137b4f10c757b58e40aa65a9af115e1c37f9815353b69d0b4effa52cefff13703fa71a6296f9cca0f02568661be4b64cbad33cf61a655833f6749416ce403c705de0dff97b61477cc84a6114a643afcd81071e2c2b49b637ffd7dc3927352dfae0a0f661df3eb4563b81f631e88ea8f30d0d9b7200b455abeda1d3f0657e66847a6ff4285ce2a1e1bc748e4a4d564061c14f3b443535a4f4225b11f9136c74818dc66fa95eed8e93dd9a9fda6f0af4ae4044842f335e3295507c2cafbb9fe6969d2cbf816fcfd8e1115cb14ea84d342d0c95fcaf758e7d23da8d7a80c8791b182b0b6a3cf9fa2f4dfa435933a37d9d5288bc0b218666e31422f78218c498b0aaa9faf638a80cd05efae6fe05cb1c8ed3371f4631e04812eaec52d9d42a6f15b2bc73fa00d4789a8885a0265189ba8713aa48246d1dc26b1c7917f84f747cd8c4b4fedc2219bdbc5f4d07588389d8248854cf2c2f89667a2d7bcf53e73d32684535f42318e24cd45793950b3825e5d5c5c8fcd3e5dda4ce9246d18337ef3052d8b21c5561c8b660e60bd1c4dc087419407989a24c64edc6ff7cd6ecce04f716e3abbfe979378ae09f18360beb8bf36d8cd8de1dbfc9d1f1a9704816f608e722fa955755dba92ae1e73b4a46d33af4510f8972bcbc76d1dd34e39d985c85810582118b3115a826d36307771c4f8ff7524ceddfe5cee67df836294fc77de5754d2e82b3f193beff3376ef54d2ad156cffd9888e5f63b326c101c3e74ab6b30458346b7a1df2582490b7655c307845c59819dbf65017476cc64c45fc98b368eec5485e462c9e0e3769890c058c4daba1d9927ab08e562dd0865a21e817e09174f2decd9094133b982c8035e96c79b18232e7c73550acd0d27fdfda426ebaa7378f7c2bf1eaee8ad7681195604798f1d7126e541d4d97dae31131f193f3ce24b6f9850bd2978c56659ad18d12a427d72116baa3a0eb839692f8e4ea455d879473afadefcb306938d333349f6918b2fbf0be313888a10cae62858d36def27370ee303b3a443c219c90dfbf4eec0ba6bab65786853d04af9cc2458f69d9591e449729d19dc621321c3eeed61e03f39fade2911f0c269cc8cc32b76fe5cd07e479fedaf56cc97617122def1d7f5976ea4015f95f4fedc004b75469a35d1265629b95e21b39d6a15d38fe5efa0554fc330bc0deebc2fb14d00877cace1252181523eccdb787763950cb20ccf0227ef9e68b63d03907b711a71a4d6944b7f49678ad740c4ed810b4ae7325a79469400691298f6bcb80da3d167725a3abb082571992cc1c65ae4e99c2bb8d8d5b3c3098bf70941017b0bcfd9aa99128778e83d0546e457c806c786f49feb8ccc93dc926cdfb225ba239e7e9a02c20661cc46198d5aa80ab33a5368b80d7480442c092374923aaacff6ed367c37953db2fd4a426f9e1fe36d3eb019523bfabc26c870450bd74bd8283d2182e710b9bf60541e3f15d7f2e9df5a052128f126465bad397f99778ab8ae3f61e74357d7945419e798e5d0c825f1d67a06a4f9a028ca238d5a863ba1514746d6eff8d296c57794d0d649504a9d8cf939522c1a0f6a5a74945d3ae838abdc98a7216e4a9f58b00dfe80a81e205b960c678c2a1b1b12f5e675101e49f6cf567efd050d869958e6cb9c1e6903f167f9572f3d05c56d2a82c359fb982584c49b4000243e502dca0317d038f6c765c79b22b7ec25e0adb9e85167a7114389929526d705676e03b8ee39c257b632258566b52721f23483c811d9c89bf26cae422a78ab31f2a9c2298f799c02110bd9a94057a865d488955ee4a2a35fa1689bdb447da32e45c91226ce1e83c26f1c29391352623e33a58e8349f6217c88fff765ca7ee886ca969db69372a11e382bbb3fc6ec7c377754143f281b6a790df96be9a4c3a1c0e7d808e1c6bb1e9ed4013ac2416e1ed5085bcf9b695aa5de9a1d9e6dba94f7650656feaf4f4222caac664ccb6c2072a24e82699ef5fbfa34963439fcf43912fc8ed92529164fd42b262299612f499d25b2938751b24692016906e39b3af9190de7292556042a5c48abfcca8c7232cae69a54d4ba898395d07a5b4554741e3521780ea73fff1ae3a9a4bd87541d241f6e6f8ff5e362f92b2633fb062e8aee8dbfab5053eaf06891d7772d77c21865c4449a0a95d426f17a8dfbaecf3264b24a6fe7b6d061c05d8d598e1443dd4b3de2f0818e5a94bbb3ad8c3a3b4866eab193b99509c7ac553f00b74f3a93ae9ef6a1fb8ee2ec2a0b87eaac596b18d4053591261b11dfd19956117a24670d3bfad728ec28d0f4a1fdb55973be06e8849b846b3de296c1da73ece92974625c8e4527a04bb61e1afe7884246bd2d45f7c95e74a86526014ceca47af4ca6f426af692f30a1a295054b663e701cfd9c26c6dca6568ad33681b688b08c6c24e514a44c37017453fd5e90ae29680da828e46a5709b6d0cee2b099946fa81055fdcd77d8863b4f311eccd3388d31c6393e426eed5893e1a92a487fd6cc2ac0a103fa30f36605b7a4bff81eecb4f6cf1aa7e8dc88da1443ced7f271360f3a0470c142d5871d873614aa8978b2e5ddb1b12b7dbb0fd86280a3b155759c7f02652afd4e707bf4ea53e9a528ea72670ef36891aa14699aa420927f1a96f065a76a3780c508b73356978b797d7a1483b21da6a316ee806803a9020be8d91a09549c001250a62322f28863ee2f328081f1b7d22769513b8aa7a55b1b684802b32f81eb7a9751a709e7b0d7cbe71a9ea9f24a56e64d468247b79b047841ea91ab60a3618241112b2f5c9750da4c395742de5d99a868d33de95c1467ea1cc7ad38108acbf0f7ee97dd7ac337e107979196dc790334620354b6bd97eb38a1e83fa467bc8f8d60f1d35b69bef2a9bf3c35eb1525fc54e4dbb0f703acf82c775430358cc317212521c7f15010ebfa1d312c8ab1e9ecce966537f355dbf68c47136634a827c974ed875ce7573f889bc97d5cbbd74d3b6b1fa8d2f4dcad4d21b82ecbe9e26e0f4d61297884a8d533566a28afc6afda51f328ac6a40bfa966b373ac469b6322507628110411685a53f1a83b0cf26217972e587ae5202758a70a1f95be9352caf3b5eb47e9d6c2544f352dbd5a88188d73e458192ddc3c4079ed65f21d1ad8ef62d352d10d1bdc4d91ea9eb683d0f8c24edccf9128bc25eb4525edca4a761d18049804b95a28decc80d8a62e6e122b4091df66ebc0080be1717b5e252def48cd41cbaa07b744f15a84c6eb2e0396d98fa2b5c52edc0715a867b4610baecf82978136ebc10bb93d7e057e15bd2aa32835eb26936263026cca8d9b9d85b55cf2fc2c9f70f140cde9c06bc6cde4cb8343bcd2fa788f3f4137cf4df7bb9a2ae0c186aacfe19e3dc91da81f67bbaace7c50acc1f81ebe570c9f3d0e8f6253f5a116bd648ee5d1eaf503bf872986171bd7788b1fe92af793abcc9e372c3bb6fee81a28c0a324912f98c08c0cd3d6339bdce2e354954740db65e5793296edce2efcf44f27d847e6f4fb7f97162f550734d2b73bc8c41ba317841357669521a06b27cdba02f3f6d8216766690e03a99acf031e1ce33e4e272f4e7dbf3bf17f369eafcdf2b7bdd8709e229d895a187af455b5400d0dca89d40b0c4c391971ae97b0dd1b7eb0fe96b553744d7f6436711eac314496ae3274b39405a74d68df57cb87f9e0e6537ed7b029a79ed49324351fbebf533f2e3cb6cbb083b784900121db0d4b43b30a0444670602b70f4eac6fff71a69591f5b1f72548cca365f99fb5ce281a6d6c3c5a85e4d4ccc1b8ff94c7c7af3031136b58e1c7452994790c83baacc2b086995046412f794ee3580da5e47e5fa3504ef8fb1abb8de2b2462f74d97dc253b5c2b091204edfd04676e0a76f2c694819c805604a090a3f2456cb39ba4a104c2270c303cc4bec99119ae0620fd9b467b50bf8501ab7a2881331499b041a94e3f62af163ea2d8af36d4c759e6d8e2a484b9f3b9331cf3f04a65d0f6260f6365f5979a27b25fda024821507223153b232040a34f13958c8fc0664875675e5de0a72e43e1122c21575777cfeb7022e346f +MD = a42ae5e146b8736668d7836e5d1fe82e5525d9b0631ef2a8866a9a492b2fed39 + +Len = 44072 +Msg = 009e12ffcd53e104a45c553a8f3353fe4b283456939e25caa277cd75f3cd315b4be3d5fdf95b242b5ca9121aa7c700b6e12ae03930f699fd566ead8e7cae19042f9c7d90a81c7c5450836678834f147a941514c512ba07864ae646bb0db6cc8cb4b150df60feb12787d4977cac3158f16dcf1822c354350c86c8e2222f4d119de20a9713ac698a4b0982ee50a9d791c473413477cb2aeb3810fdc7eb69dbb1dcc290995311c5d169de76b31902a78a9aaf53b0ecb0a6f3b2f26c3d3f44c875f35b29a0c8197a4c280f992e02400b0a1c27eed3abfc2e142134fc8e46477c228ab5bef2994bf0c431a2d2a730ea6ad8f2e5f8e6d9362c152ddc970027fa608348d938d8ef2f8f002ba20865ce882bbdc3f15b31a1e707bf7ff424dd0be5da5fd6ce7d9af24ec0cabf1425b102a2b8813751fdfc299627dabf838a6b1991537ddb9c7780c92fe9e8950210d3f4c178ecf70fc88f99cbf42e9592b3f37a8534a6004c0cd29d5b74235473b113ce6cd3c5ab33a2311a0fd682a72886bc5549e3a2ede526d79558c743a470f0b8b52c31d6fbc3752cd4e8359fa04deb10d366ca39496facd8dab04c102f00b50cd388fae58dc928c6eee1794e2609ca351c634f33bdf3861d93ea69529a2be855500896bb0c4ca348907f0a55e1650b7457c8dc57f0779ceee98f88d090f971dc54346e201e55cefae44c507c7b689715ac1ed86e8b06d69304261053b77338e90695e8dc6beb91230fcfb48d991b546044ebab4035a51c530b3769a3b7a026c48eb26db69c16d40c3c909c4ee6842b9d47babc95975e5678274bfa88398921b41513667759de7ffe9118718907ad0413dd10753558386c487fe92dcae5341202c34139e7494c7a3f36ee9c04a79ec80b2c773de8213c460c3c99693062abe2f7bfc350ce1567ad17549a83886c5e5dcd5f767c759a70cc0b85e3178359f677d9322111f4653800d013a590dcfef4ada19c969ba56adee78f83509d8b711bbbf043e4e621dfc55cb19a962aca066b9fcf0b5d00403a8e7dde5d676410532495861b93361c2e18a70112f5b8182cc81a9ed655140eb18677413cb0d4daa618ece1e1b668aef839cb09a24ba48f1715085822063fd678d0be0048b455b01300aa4abed6e69fe62eae11731e55f7705a50431af7ea6236743963a8fa505c42e3b609da7a17b79f013a60adf93318de9ddaa7e3b07b789478cfb2850b2ba4dac9f8665c2a63bdccba55407761a6b90ae88ecea8b95ce13ae66a34066d505184bb58a96c6e327b145fe9f7f9e016a49b4254ff8f9bf365cfc5f13254aa252be7bfbe1934cfecb720faddce5cfdeb9f3ab41481c0ddaacbfc1e4bf4964a14f9ace012ffd9d4f93a9792190dc8418d738f44b69d6407e8dd68f862c2f5d384857a233ca38606c2cc223085fc643265e841fc229ba3a11461bb5b1de499cfdd95fa92244d61ebad3469db09e3595ad9c5f9e440c3a43498209f5064a1a9c586f2d334b345920d233c139b8d09ce4152d45e03f95c9047dbe2badd1f434e3ee964ae11cfd242f48daac978f9b7ec6d39db196133b08e63456eb40d3610afc16db23332613e99265147327b3535db68f4a3d106d705c70f3e8e36e59251f5d67aa6099e52cfbe2dd9dbf7ab29cbc2baedf42ffbcea463d32e08e86f194d47057806d95d88ceda918b2ebf11bec1c9e98a95db47fed589377da571b2b44eced7cf9b4a78ed8314d8d10733b3da5e1a7f35507cf251e061c4932d7ab64c9ab1d3e82d05f66835958c1230fa9b66ebda0455ebba05ae0c1401d968aa84c77a19822984b1dfe02d8434b56fbdd14bb034fe512f3f87fca2ca77b51eaa230f362e6afb67f73c3fb40a59248d245b6ff54ef793e4b08025eaaaac9016219b0a161715c79f7f146c104f82c652d643bc02507682d2b8f8102cdd2ad319b8f5a262fd0bf3f5f06f4f897a3703857c91191e630486c0fdf8a5b08b79e4ef1738be6107d2e92ef355d069b40143f0bd4b6d93af2807782787ccbdda1f2d60e56c455c5ef40f152fcfd7f62466ee59427ba2a75b6a6dc0dfae6d9df5a61434ca99219b29f9cf714de44c7af3f06c89b3289fa38f522161cd7470960296033270c8396691679009f49d173b48272648b75b4ccf7569892398e1bdf12a7561237c017505bec8b9a6cd0020824c92825df61b917232360ecde8fd3df694cd96cf994abdbfd7a3b4107f18509626b9e992197056d5f141182967d1d6ec69250afe6dadf9de0581e80fb3ea8dc1ff24c4adc8628341d81310fdbb64711dd0062578a03111a86fe9bd6b1180c049ff5c7977aafa00fc0f335c128cbef7cff2f74f04dbdeed663e639beb40e1d2774de872b8683fb54ebf29663083e84e4bf680f06cc6bd765f9977ea59e915a99312501538a93a8b81107e951e47e960d90529707608d592dda9ae127bb3252fe5751dccbe16f168dc29b950a681c913c0477b37eb492f2a26958f7b1947184ab49fd6fe14576e36a63362018ed991514ae3fdad9233d1278386a38efd4cf6e44ab803120013b9db2855020f9ff64801bd02383a356cc56f3ca470b1ee6bc7e4ede72c724bf2d841aab820e2a181f60b62cbb2479a9c13ec9916804db34c9432e654da85bd9ed54e738344e25c21a3568167f53a8a6cc184e2055bcb159664b67d2894b31dbcb7eccddff677987f58cc62fd897dcd83d9215e988791dcf24058f98be36435f78702fef4bf091c431d544cb6f4762b8b62aa56f88e09d0072f00a4a44e00cbf44c774fe92600b114f8d689bac08f6c296507124cf89ab87e3996c49c5defa85e0e3508e7b4c41f9af33b5f30742f5707e920dabd4bab5efe6602a29a989a94dbd6237115efbd2e7e1569174099bdb6cdf6ddf67311a68830bf2c86c788675613ab29d29c6153a5686649f814b6a34f239426ad95d1f2ffbb4bfcb74bb4bfb8b0952f72a392ef4effefc34cd15348eaafcce3494c14f78b49135b7f4da40b80579c1d9a5309f7efecb7c059a2f914511ca5fc10bf611df37f1d2f24f5e1b177b2c9db92d44ed551d7c62669ad2e6f4b1028594b1740cc01077362ef6cf21b65692352a24de9ef3c6625dfc21a7dc19f335ce2417b396c7b891dda28da5faf1224b26812e663af7844dbd1ac126b72162f49803c14d5652aac21811767b1d7458a7f0629c9427ccc17f0e671bd82ea78a9f71982099b1fd619893d04396ffac8439115301b11bd01886d04584249928d4c6f965c83140347785df8367b217f61f8f17b6f0755dcdf3e5915a8c948d01cbdb8e012aac6774470a399f65350d0d951a5222eb298402ee2bc00aa7c080defa7daddeca53be497a965088ce98354f7f5b7f0b5476151b61b9fada68110b2ccb0de77329dfbb306ccaa2d40664273858d2ecf4bec39773f920904e300e8257c80cb952bb98c4a5a817bf059f2159549c013a63ac9a71a90ee02edab2219d0c7c0a91f202278135a6fdf3921b485220d376d5cc80833a272d89250440e2a1a741880fc59ff4774d03fdef0ded51982979944db3ece6577adf8c215f7eda36a4d2f59161e797fd7829880fdd97c5a1eaf8fa10ae446c60109f599240ce70d2a18ae3b54b7b8aaa33a23ce485ad2ce5c1fc18bd10195dda94e781f65cb23efc19e3c2f9e6be34f40be88cfb9a9ffffa5aed60a18dee632d543285dc17ccad197a7823cdc8423f716d66e8b390d2a7562237726c7c45f4eeeb1ae5a1e66033b14fb286af6489f298d4c7d0baed07cb6f9474be8c7f928b85d60b11f66d2f7b6a061d5c1d500806d0de75e5602381c4cd4e2fb57fec56af88918dab27f08cec9a3a2314a5ff3ed4bfe6eb9741b8e32bf59bc2e7b55724d97d9a1d11d5350affd8586e50c7d6b0f4cc8aa356ee319e895f29c8d5db447f81cb7c23d68c8f2c2d9aed5990f18ae0df7d3637b4b40236458064bbf04048b940f8a45c699c83531e58657f45c160510d5876033131cf2ce8ffc926d782b8748f9b9f015ba3a6321a976d49ffa61b8406c4d6b04cf5ecf4fc33e373fc213833d61ae8cd2d205c2bcaee41342f1df0fc4478b4a9686ee020f7b3302dce9a2c69acfd0e0a5ea139b2a7b39dd844a7a52c5ebaac69240b4d3353f43bdedf5c29a88cb87b634094b359398defa0d0c18c86ae213a7a005978ae997d62e19ef5a452fde3bd42a3795da1e8e3932863fa3badcb32db567de826e550c541f09de5210b68f54032d7cd9d0f3e4b44d97ec027042e65fb890d25ac89e25265665ca924346673a0be5e1ff603b22b612e71a1d32c5031377c2ea08e0ef6bb29bd4bc012606ed56b4fc6df0d21ed1a64a1fd1dc488d93b0bba62d74fe6e6561b8feba89011fa90ec61729926ec378eebde61927f9c11e9e4ce4a3866a439b9b738ccf111bb823cb08e11bce7c539ff533e5fbe68f8a2a44f22354276b9795c996260082bdfae4f643ff4d8d43f5ce2374c47e01500f410c750b493d4b92dc51e77357c22f0d73f53f1cc7b50cd28ee0472aab608579ea5d9c4589b1505bf79d2f1cdbbab9185832c4de8f2f1f11669476bf88ec75efae9f30791c6cc31b6e1335c89452a3431c139aedafe4c4dcdfa7c72c208b6a9a133bfa4e0b55ecf9ca1dc3208b7334b8460288f22fbb43587f8203197826aaa1a397bf6d5d53121e91229fccc703b59c5e665895159be3afd18bf22d9aa67e2de61c4a7e1a507eb14e8a927350eb6e1aeca7d07d6b6eed095a2b5b118df12e66633262284a3379db86bc64bd2f14a757792db953391ba98da4ca076d59f10273a242ce13f6e449c4c322dd546b65a87e8c5fdabe858a5f6436d1bfe8078c427d2bb257e8264a36938c23c5dd0cc5b8b5aea7fd6759a357b598a6492a9dac35ab87ecc54fe04f8a716a27e3031b1e2124666ce8f5bc4ed8a953b36ddc263824263d56e0ef2eda8b85e496006b9f5729f53c176411b7732c68ee5ff5a6a7185715d55a6f7117d483f882d9e4c0a058194db80e396350fa9919f111a72f2a3416a1d75f3c7ca423b8f1cc5657a82709395763ba2f9291cb68e5e4334d20b674a9f2cccd0db9dbb073994b7621cb3a52d038c4830e4782cee1f3502cad2054c0572f3c0babd0c663fb1786a109d3e41b281b64d29d292aec4b6cbd6490d80b006a81ad83de686d249a940540d9652a4c8726c90da5e1910bf077b143bdefe31c280fa99c6d29d6dc963851b9572c16cd36817d9eee16bf14163db631fe0ee4fcda02b7be22bd0b71382af1764ccdaf867d5508eb4071bdf006e5539619dd1788c7816051c3c914cdc8936ddd7ff3fd5fa3caf05e639a9285089811dad70383a939b52abd19f8f7d68e9a4e58ba440941f207bf5d1e3846bd637e76650029304576c59f6becefbe76d1681b4ec368da12b035fc523bf3e27f61be0c9f5cf62745c7da47c104597194db245c27630878bc267b30a480756cb248815bf1b2136f92741ca92828dc1618f2f79a4a62ccec259c02e2bbb663ef4061eeeac1cc271012c5b24d092220b7e95f095b21885b3d3759f19affa5687010f42e417870db13af02c5bbcab8ce5bf16a812a139d5e73d8a771e1d8142af90a4968e87f67d77f50727c7cd5b38e0b175a888c88687c97f2ccaa3daecc519116a7c5683c79c25cdd5e001790da07ce4379450be8b25eb06c11c339e99686411c586d47196d45b33d0e781465f7e2ac5d0de12e9c43abc62ebee55af138711004a287107d0d078b5aca0dfcbbd0c6ad4e5f837d0ae30ce2201b372a2e7ab906b6ce3b48d01fb1ec1bdae755f92f5cdafcb754819b5a290a2a70e2300926062b1b23b379796ceade68852daa89da4c3a505d7cc1b76fa94934040df4e802028819eb142ae2bc5b6a29150880d2993dd5329822c6c7ec35a42620e1ff34d85324996c89e472d7ab9746d09f613c36d8b48bb16e1631977425e80c86d8566ea10784f0372e9184836ea8ff1bd42f77c4de41f0893b5f380fd362102307b48c953ac0bd4990a78d8bf535e9a3621326a95b3e9d9bbdb799adb67d74e015b8fcd6c4371be5921cb86a36d6d86091500931346800cb22a381f7d71f7fe689c9850dadcf5434bd59cec939741279ec4ee90270a96142f48ab7943d317a5deb4eeee2fe72af5d98c4964f04f5e017f8768dc417e80728bad4042df09cad6dc4b100fcbe077388acc6daa5a1438a623f2ebf20320d3ba4fde8306af946603c9a598304f576e9df7fc860721844588148df45bdc8ff45de443003f25f19dbf5f8ae3fa1aba759879b30f15f6fe2929d9bf2e845e1a86dff1713456e2afc65be6318fb7ce9810aab88675514b0037fddc1cd705d85effb2ffef9bd8563d648bf65ff813db6ee4671ccd65438e391686a41daa5afbdbc3695824a34e01191ca2285cb978b1bd65301f1e4b6730e73956ba3804fe390f7675a2a6f72273c14340c4ce4060e1f1f7a847ff8426f3b914e09702635a10789d6a57fce3f01ec47cea740b3956fcab20322fc7cc1d171d3db6c2f3620902958cb9f08d063162a12df1beb9e0e5624773602f2d7fc44b92183bb6817d858fe4d8e704ddda50ffd5db190d50e376a36565b4de871b86e1a63901fa33125a28e50663fd65ece946e108a2d846cda540738b92a67b2c0f79c8148bf69eccf16e24a9d342cb9a64c8413b31a821ebdbc9f0399c2f602db884763f4c441b09d5b01217979d658f5e0474e7480578ea94807a1433d1dc9d0c924f2db55b4e5581af3bf43335ca183f7bfaa1487892265a346f8ffc2646f68613a14479b49f3c8fac10a428d47fe183af50ddd56a244bb7364f21579545c6bf991b27ebd8842b5a472ecc0ad1dd67b51f06115162a5b71616a76cc8b74f8a13832b5c9e4f93ae7bf0e4c03bb699175e3b88c05eea7cf50145f6b6e204cacd1c724037038254425f49e1154e0b096ce985678f507a30720354bbb415f65dec54d6f86bbe093c639eb2825fb437c4f4e1ad10b2c88a56da96b374d8e7146f843731c24f205cb2ae94bb76f400e5423bc0e312ff49a3668b25f2a099c7e776014e132c75cce56d6febc50d76b66c17ae21f7fcb9365dd6005b82cd7b5ad8180003eb9564264bb3440e8fd45c3754abd86f3c2c6521022bd681f459f1f26ebbece32bab9ecee82aa7674c5a1916377527132020a79c48de8a43c7e4923123d8448673bd8a29534a26a0bb1d31d58d0a26b85477e50a8a74781b6debd099900393482479bac815883e253c7c4af7bde153c949a0a1fe5f743c6366de419e2bb445b2ee3ea51d976b5a7f4115a8ff42814ab0602962da205453d6334a49b16f60f851119addbc616a08197977e05ec36058183880ac3085ab3ace63ae6d65c3a0179d3f0cc906fc1ac37e46019588b915186b5334e293f7df6dc66889313dd0d82011d712fb9fdfe4193827411d1f8c06182410b4ba76ef677958c24919ac0fafae397a2be9d9756c75b1adb50b85c4b9c3dd218e785bd4e9d9e0018cab32e86d1e8e88d62866650a658539dbc55debb697e0e630b0a550ccfc1696c24a64f3b70d8b83a01ba91744652d6c33fefa797320f9df3a07f5eb877c46f2689ba4aa03d7bb1af8482414a0f114a55c0cfde675eb628d08c2cffdbfc70bb50e038483da19979f6d4269e5b6a5c5859263eacb4553c5703b95961fcc68df5f11168709b05f9b817d7eecf2ebdfca8d95b8239047e69d1930d4eaca33de3c5120392eb41cf6417187722fd4b71bae1dc46e3ace243043f8872520758c939d1baa0fee0b769a23d039b094f3b +MD = 9f513f678eaaeeba2f7cedf1b455f8e318cba538e66833946be8d1a346623512 + +Len = 44864 +Msg = 95f07516d6214c9782c7973c43bb60368f6104c2c675e5087a0860420dc5ff208279ef6b8dd3b4eaec681b82faf970a082f9f2dcd14a84d60f48a564cf08a2f0e4e10a1b762c63a656491b938fe3c2873e747673a30b9e73774ddbf780b93b206431b06dbbb6c196677480b828febcb36bda77d063409aa85b1fe8414b613179a970c8a881f93781c8f03039eed4c7ecb234df3c3a72e23b63c7b68b5687ecc35ca63a15f37c2b2e21c5155e08ec4cf9bb8995fd5028ddf4364c2b1cc9b3d4c624dceefc36c7066619fc166f9eceb1a32de1815bcceaf39d7db6313ecd6e5149aa19cba5756231f1589b1ab3da0360b2b0448ba0d6408cfcdf0daf378a3ecb169565bb57d6d6129787ad0b73e212bfeeeebb9b1298b310db055a8c5027aeaaf38ec8a65b81a913204e37d0f7de83381e8c4d99fb37cae70096a5b2d1cc4356a93d4b72fa9f669b5354435187f7df310c35036da1de0e7a333bf40802a387370049f50879589211f942d8766b54ac147e8fe3ff4db3052f3e9c51762ad101b5bf5bcf5023d3b7dfdabfff27ea1f75483d42f83746de396fe860c3e493813939b01adf323f395c6cbe74bf4c4d7dbf3511f747fed68832a3f830533a83d9b829992f2f9714b10a206d0820cddd981443c156da3a43d9763137b30760430105ef4341c765eb644863ae242a92df98fbda1706b8d5d6f88f836d92e93f1b22a8f176f9ad860c7a9e9d4b70e6839ea5fd62d9b0e9b5d70e05ff617401bd52642a99f9ffebe0bf1a94360a935b8961e5a143d0fb76c48e425e0fdd0255c332ee124e96fa895d4c6cb396b436918a6f836fe5c49066e842bd241aa7e4f03a01e9e87713928de4fa9982261100916f11a5efb17d16c10b3da6de8888c1d708087c357e3970015c13c98a4ce89a62218f74aa0dc2368f14c52615c0484114178fd07fcad03cecafdd23517102ab0c87311727625c98d9eb2365502caf0dad4dde0c51c3a09d57c4a1d061fe28dc98883fb6ee1914e3a7789f8a173385cdad943c5930d1703c4983a6f8425920d50d0e007b8898b0bfffa380bef23d912819d3f3dfa65c0ac1cad436c17aecb23d7300bd8c7c49f8d6eb5410286ab29cc7fbf249c53acc34d3e29f9756931ea8bdd345be115293b6cd727395f106fb6e525ad887347589b71a9acc12dd1556c9fc34c74b3393ddb04f9ce858404f7ecf703f6ff453ddfb5b40f943ef7f86fedca39e6dac19c691af02729ba13ecca487c9b19eda4bfc8be7ea08ed7663707daa59191f28ed73167b8efb74b81205d55d06b84d7f435a9f25c2ceb0efb25a3bfbc7aec508d422d4dc9c405ce4e6827a1bcf5c642c647da1db705375a193cda09694644895f85c339ad447396edfccf987cba6cc29d6eff7d29c9f25d52f50144569448e1481a89b7cdd1af59e276abc6aa39d6bbec0380bd2edbba6d3ad6bffceee5480d0978f744c60c176bce6e4298bff4a2a334ade43a30baee2e336a6c9faca9e0610609826d00442a61043c3aab485b3f1cf9e6b090c9f80bf4df28ada91a62a091b074b19d172a76be2678da6abe0e2a9dce167c4d651392758089e9a5b29fe6f3ab230b51651f8af797acd8539b6df38a03e58dbc9c8e2014da16a7220fc2422b58ad063694a3b591ea308ae26b0b08864dbc8b8adad833574e477c8a7c6a408d4b6b28990057a51190ac88b3a755f806fe03ec24aa722aa15fa4c05b930840bdf5e5e915429bc7fb2d894833daef4070b764361685fc94a780a72921ee2ce121dac5de17d5e0acb3135f5fef60275077ec55efdce7c7ffce53d6fd59e838a04d7c636e3d34e6b1ddd4872642e1aec6711f417fe45a74da8a3bbcd3800bbbecb55d471fd1e9fe75dff3a931ead9d600f0c2bf6cd95883936fbab13220e34744edfff979925f98673df32e0923b34dae6b79484d086c64e8f3535cafb8e93b375bd6e2f1eb1055147c559e229a08761d659544870df0a91999983792a49838428364bc1f48a6a4fc1f9d7204ba33dfdc73c96ca156afb0c3d6ebaa81907aaed4f93bbd58378d188cac2d322610efeb69fa6809328ed42c664fe05e02f90b0f9d21de8f43243e205486a7571d1a7749547e03a2a0f3186c7f48f8aa7d4ab3ead9919faa56bb244cd2537e794053745a1a732ed1734fe7018d76a71887022fc138dd21971968ea0e847724e13638519e3a7e3c1e3fd1ca8c0f3d7e3086bbb9132948f6bdf199f9d5f9862d577555b9961303ddd15d452d5c7321d08b12e3fa61297971b775dade439fe51a147427f6c2528866a3520699f367a86070a1f75e2bc7f334fc1ca801c7e6385dd0b92ba3b3779078fcc492ab014b558089ba727ee3732ab3046c9dfee37ae47af4cacd4ae9d09087561b75aad69cadc35ed2f1b718b9a47e58dc094026bc7df3f90fa956c61c2d1437cd1c4413da15ab4871d1a14c19e4f961e1865ff229695b662e3c51e8b8aa922a5012f1299221aadf1daec7fe0250a6d823a1b8e6402b13c47cf2b6b214bda3a65af62c884356349b4cf5959f019c18f408c7e563af57af8c92690fc2decaab24341260c07c27faf5763294afa61bc27e0785500ab5739136f51bc78b65562b3c820438629b1b40962fd23fc04e5435beb656a33c00e37b5c1b67788c56e49647ab481ddf2ea4b7c5e071114198d9e53e8bb83988003b90448be89d4611fa9eee465a8b96a558b32d2e8b93d3e4114385fe169d6f31e0a2b8bd1b9039250c8788b9c7fc49adbbe534608e31d7de9ee32d841e496214871501358d0be60e9f02bf9bfcfa389622a0642cf595cdd6d7568dc42bb801367359c66b997acd4d2672fb53860013fd319744fa5e2a367b5ee03f24cb83bd0649f360e5ed376f5f375ab476dfa84c517d1c5f4f2459a21a9a42aa3c7a1706028f74693ad4fc3cc3464c738c865d422149b20ba1e4be81532de06761b3fc6cc9a85f67b10d23c5f7e7aad0eaf689a5eb4bead2891bc354b36e3bff3b15ae61ba1906c50ee2389b8b70182548ccd7e82de8496c6b3602bc99efc7ca2efba77552762d099af0b51dfc93f718fc65a27957a33001cedfe70995371650c3e26228313414bdfba523cda9a7d9f49c5d83e9f6f1415b3a560acc33c8aa4b807678fab4d7605a979c0f4b314023709f10e6aa9a76ffd12444c884d408f5e2eb04565d8bc48257f531c1e721e185f58b2c654b9098ce0c1338bab4149c7bef7a3884d0f4a01d3e9b030651d9f053fbd70c6a4da7db2e549d9e5bfa63e7be99a46f8ee5adee83970f8c26ebe811201c093d70111eb2a34319d21698506f30a9f035df1c060447c9b949be45cab87cae983c113683b3df601e90953e58b77478f417efd4ab95ec7f3ea836d0005acc5c1a84c83e655305342246325ceb44fc8f16724bbfecf7e40ff6342b1b177c817cf6b40f993224e727bb5f8864969c2b64ddf17d2e68beb0f47679f5a77e925eb9b32641c7888de7c3406901f5c9219392c101feb0ad5ef5d535f630d5a430967ae6681959c702798f57ef39812189d78146204ae7096d052acb15674636dbdb38f705f0b08c372ef4785e89870e1939c903d8dc222b4d715d9c74037994f89f8c6b6c627c26707a9b18338c780d646cc250984d028194ccf6208e9fe05d2b45edca27e91d4462eedbce0abcf49dffd315d2eaf7f88ab77a7d0db1970addc880c589b4ef045472fe3ee050955d3e5fff3bf14d6784c549fc6a9aa97359b564b2bc20800ed1e5151b4d2581a0427ce9539d324c3637cfb0e5378dc2cf6d72946e2a3535a2f664ede88ed42a6814c84072b22c43de71e880a77c2d9a05b673bc15a82e3255f25251c86c92c74774aed9df3335d0bac3ce2dc5a1108bb0b557604bae720282464be54d7ed7c4d8c2af39fb68e58f65bddf3cc23ecd344afa9c1562b5a722d272a01cda2e19cf968f37d549fbc1bc69c0aa221fbdca105ee690301d56441fa0f7fd6d1102ef240b4ad7205d344104316cad7250968dbc4719f264bdf8cf559856b25a6495be8ea1860bcfa7dae9e3472257a1e7618e74adf52117d725bf60f31f7d69574f0e4be3b15427bc3832c635723745569742e5fe18bacdeb558ade7ba2ad1e6ba755085c6d4ecd0cd4a24966ecdab120b0518ca1f51dfb8d10b80a8c90dfee14273930760a3a240c48bed965f2a089d83520e5540ac9251edfcd81905a645ce3572150cb28c4c14d0cfef2bd142733dfae376c6eda4adf332b41e0417ff8ff4baf83e5c6496d295189c921c6c1ed53b9841b9e6cd4218e4c8bab82fa620c29cfa8f76be1dc91c08c57d3e33d9c514df84f3407d898dbc6cd69610625b0fc80e1cbe25fc852e13b8fef75b36c03f1a71e7817253c88e7fd584d18c67ded68792490eb3dc45cc9decec9451eec895cd39e874b62f334b4a65fcf29605d67de970a905882705aca3ebb7db88239ace177fb05376db71ce066663819503eb0ad5ef632d0ca46cd40efe8654699ddef2df8a66a6191d2b1f991ee406f12ac6873258a00ea81d234ec46d81885a233b0a0da333f607be0944edd6a40a11420ffbeaf3872ec258d222af80d2fec47f591d88123fc9a786b247e8d5ce155f136d6fe4084117c41f2056b67f9e3e1077e1333a1fb1aa633ccf2f746588ad426489ea08dff5511438b5f4c0b110d1a4d47b540a12b21ea2aa070578ccfa5c22fe0b743ec0cc621c6b3a03b75f4d3eea5dce89e03269afcd9603d0db534ea968aa9a156ef2eed44282578c82d1800d48dc83d9a4c8ffe44ac96b988742a91c7a2eded680be822ff043b396094fcfc72817414d3e1c9b45820be66663e1353ec15281be5c6cb0f98d78f729342162f3f1d8b1ec9776665bdd231c4157771a96a5e028d6eb44a2bc81e7ca4deb8e62190be57bbe951e88adc4dbb6314b4e80ad8f9e7d25138d7dff3359d50b16dff7c2de0646cb215b28c49df95c3e27ac8e09e55628b3bd916c4b0d95c06a9d5d4875d205ba1c24776e26d146b571d3da6c3410ced188d296952776653273684d7eba4fa980b884b8835dc98a6ad1382043b679cf1fad38e5201bd68fd32d5ffac019bdb940a72b678ff1ec8d22663cc53b158720ba29d9c636af96dc4ca06bab371b84fea1f2ffcbb968a1168639c8137bdba18b4b049b80ff6c1c1445d472a70b470c404ca0ea2e2a4c52ef3e51c5502c8f31d67a46685da2d9d1ff65d25d376325bd46e9b9d3d60a2466def1b719c575ba9ecaeef827a3477f1d6455a115a3673e00da1f46a10c807945ac4771aeba7fe3502f5022c09b18e4690dbd49813341193bc2964d3e18b4d25721ea896a777192afcd47ca1a8d3a921bc043d3882f163fd8c7f7d99142cfb703047f0637437450236b7cfa1fc1d8119d46924614de11363db1eaef82d2f9b0b41fb1f1fc68b0a314d396b9b67e18e7556750aa0c895788d4481699f90f5946cf382551a12c4c16eacb3e10c70e229eadea2607577813bc035424dede431800bd18862e0dd8712e0d1c1c053bb71fbe0b99bb66dff36b5b349cbbc719b45d67e6877a912ab34675e58ed7a3f8c237cdd93ab8ce8b4287eccee9845a93aa5101b24ca981df07f472dbe818efe77791557e96c44843ac90f7390327a1326f1c598a31bd06141aa2ad55f486f3f01d56dd627588dbef7aae05dcb24ba4df4ae5f4d4fc5b28b13679afbc78cab6fcfdadeeed9fab8f78f5089d21be986a8382d45cf9762df09fa1a1ff793d8b40f160bf0f87dbd66cc462c7476feeb8fb046013186267db65c4a34125f20b729ab98cb4c898f2b17bbc0c128b2f0b505f4c2cc7b076970d8f098681aa91a927cb3acab3a188ade3c3483a12f2c7dd0b9e412e1bac9ccd6a7756908a15bde151db5e61e423bfd2154c5133ef03a02c8ec1cdad35953ed39a24940b84eedd7998d30b9b70d5a629ee1fbd40d04722c084d0d7f33df3c36f469ea93d97be5b3aa6ba2bbe7f3fa37c174376a9dd44b56193d146465c4c936a16ee7f6fe90b9eec2098a51338ea1f9137c062b64084c2d663ce04efb92a168bb11bfde8a5600e57b17561e2c45d8331f79f6baf1e8fafe89dcef8357e14b49cc02d0af2f1421342ff5a47734b203524ffe778dba2ebe65fe9da0a62d093d563ea2d90d3f53b1577b24e3f0df4bc9f32f6a07083f122cd03eef922bdd92ee1aad82276d4dbd27cbc735a31f9e7b8272385d33def36bcce9b5533288dc16d40373114a43dc890b0daea8505804d9c37be5387c667973f50f1c590041bb0d85ad29e0c0156e6fb1999bed7a3e84ef136cc09c4f3333c35bbcbe7199fafcdf89745c71077665d9d20c09758f379113e8c154e92ac9a4e2576f263d5df9040546057532bedb755fe2b191f11de7dbf0ba061cbfad9e5f598eb2ee0cdad0832741bcfeb624c8ff5a4a46afb094a3a7fe1dc782703625d581581460607f25dcbe1327636bf7a376519f17cd64821f97a46a7220bb62f47a024a0047f8d94d832220b14dd4960f7cee57c1756d74902d7c569261f1929eef44db02ef0677dc190bf10718708e616588eab0223bdac9dbfe38b4d0a3736997d19198d049b93600c41a754dd05f5de2a9ee807e60230125a2a735f75153f8f630f44e96133c0fccf2f3a86864773956d9d9aec47afbfa8cf218a2407bd2d19cdb8970aaf36eadf001130d02bd64a844811287aedcb40a9475038636936e67fe39a7bb797adfb4fc870f1f874bb60f3e484fc79815e9a5be940e6e642885409cf3f59bac09fda954fd2e5c608fd9f2a687d7db1aa71b707de78fa733bbc5effb62f97d9d4146ff9bcc2740490a4ed70fd8513ea110a7ef44d80ded3fcd8eba8c3f09fdd7815a2c237c50678b3b9340fcb2326eb5e34d76c5fe1f8ce2ce7e54d1b0cd78d56a85b3aea6503eb1a435b4df9df1e7d38f4aab53c22b22b73ee3336e90ba9b316d882a7fb29d3266d4a4a73b04164684754df180bcb73b47bf7bdab53737c1560aaff529299deee53d7e9c817d25e74345b5fddf565a22fe9096bf481ceb77dda28ba83d83e8c0e74f0209657197568a711104c2177a965682d25589ca3c4b12f599c82f49f464c79a0d723979e110e477fdbadb789ef1e9e6ad320cc7b0a7905458b960f4572720aecf6b900ea9b2cbdaca847e123dc2133c85d9538ddf19f05f5700851b67a46cede659eba84798bb0a16063c5ced838d04fabfc0951e1e9d6703420e17cc4916e7d0c1aecf415f3c964e9498b114b291d08a5a0665f422120bebd26e81fba1a91d1d377bec3d62cb0ff2d415c759dbdc1fa34c878907c0d8de8f5628d25c2abe0e3a3fb597823fd0c791393608136bc652d3ebb676bf776c3f5c31cf918460a03ba62f0e59b662f86db8286bebd7feeb0aaacc25a791c236aed0e9b537fad00a15efa9c89b5068ac52c64639fb1de1b4b786725794051de2bd9c028c4e35f5562d851486e4d6bd67274a0722ae6bc0add9f562ced4aff6daec0c00b74cbc4d1f02f513bbcebfddb34bc1efb88e382840f28601fde1f8f999aaaf68c8abf443cf06be1bf9a172461b40bc646e0309651891a6f457345672a979f4af32f47475d0d95e81a305a482f9969809b5b566239f27d6ae7d546f1e84fa8a4878aec35fdedb45095a73bd10e8cde344121dc4c04f25a384d2caa949b67ccec91c43576e438d00078274327c63573ca81594abe7933b8c3bf9ff7b70a8a140a5904ab72da97f2e00bd7f8b21f3b2f2aa32b291f615a9ff28556b7c4fe5e86e62773d491a7b120d896e0e4dae1471b3cefc0ffd7841217ade67a71223f8b2d6943393b3c123064d0606a8f08d3003de9ac40574eaa0129dc2b33ae3995ba0e79f47d65d9e5b9c6b0b29c80a2be0f9f1724d3b6eb9bcfdc689da8f571c89333ff8467dcd2e6f74d60d49e3f126a1b49af9d9fa6181e +MD = 1e0a456193c2501c2f050b88f8f319f2422ac4e4a434b53de5ba3b8ad53982af + +Len = 45656 +Msg = 7129497dd7d8df1b23c2eec5dea451bbdb50a4fbb15157046ece02df8ab1f8601a071faa46aafff1fd1e1884e8ba790a9c088e0b136e3ab35d0d25d393e958290d4a07e1d463ad5b5a325f2f69a7596f5a08de2c87943f3b03673938889d83ccb0baa82c684a13e2a2c468d04bb41b727d193b63f50c8e23c7a3e3175015a4d16d1fab92eaa6560d3e9dde6e7529e49b6d034dba451f50f3138bcd77d599e1c1ab40b71c43c0a16594856712cf4edf73928ebd385f12ad344ee59f60fe716223d1e675d059e01a710d44abc3416a3181558233e52c30cc6ddf7a00dbb3e4507f49d98cb8154de9b911a15489b3c7054d1ca656ca92c0d626301299eedc3bd35e7ae1a5dc5f5137c50965076c0dab816050c3cfee7a09f2e7a87512a462bf1246ccc6684220322c1e5b586e75375fcd415aa1455acd544939af6a12022bb536c2a74f7cf43e39ef4b714231ab192b1278a008611471e903a3adba41122068665773468afaa3aea9d4b2ebf8179c56788e8cc0cb26501047ae0a2d49db291fcb8f9871395a35d98142851b6abfa62a260a85902a9751113de02f8bcf652f218df17e98321ede01a01b54992fad20ed4574f24227705b330ec4829c7eb918b7d3058e851d4e85702dea862ef0e9f3e8fc553d9c69b858c0e2df6c28fbdece29c5542effa1f0126c513483a2557905637434cd6799772ffee0bb56f6f1dc37bf8d65c7cd660e6c3e3483b2bd056740a6d4990a6a5eb6c83631dfa6cf06bc3dc150c0c2b815af7d2efd5e7d46a9bb8bf8450c5c6f617c0baffcd3c67be285c77639ee858856dc2c83d54e4b07e87bcda3ef162b3c49d1e0b36a201cc22e3fbc276d767a05d09c6187e3da85c66bb1f0edf93edf9bbfbd2f88a34d126c92f2061c17e008f62cf70480508a914cd964db1f8c0de0516b49e077cee20e40b5a78c9d5db5962511f5feb743e6d861db9d7680cf0a9729f47cdbc814677a07406636f2677c8e58289f3574e577c2cc1963a95aebbd6aea035f08c39c65bd89da35ec625ebd575819fc92ff5dc4b8573abe5cf307aec25b3ff84fb08f643f8e2c1e96366a0159ed8b14fd9fd45520c8e7b677954c660846515199d614ea68dede281cb7b2cefcde26f05f9d72b363e8c754e286e26ca271e072cc7e5481a040975b662a5fafa8f593979e415e65ea7f839f860ef048faa49561d2f076b04f7effc05dda9829c5f87a11a4d3c1f31c55c2a049779e8376a918289174a300dd5ebf5ee70e86c6bbb08267579bc2e660312d5d140716a4804710cff35203f7b2a97f3eed0d510df2e554a0a1e18ac520dd6be0d0087d337f45255cdfd1bd1f3626e66658202086d35f98c469ec4018c31f253163c0feb8db6c00d93c3afa00d29f9de00e8f1bbac4e5f5dc97050d68b1c00356b778bebcfb84494df4d5e120ecda4cb4f9a26c302e4113ef1274193b5188ac59b277e8c74955a7c1eeea9b09eea19ae800a138707a399b05c4818b1c0d3ec9413e07a25f2ca6c33c12c14f433eba2f860ad3aa030e96352694748c904cac0117426e140e0c4045c648a2265446edb4950181e770541f885b6a9443217798fde2a5f5685b52ecd46778d448c66c04d11eccf31a3fb29e3dab2e2ad956f4cb65aa51e4c3ce647018288aa0dc211ac52d28537169f992d9fb1fc87e75b72c0de0782d834ff0ab94bb10664e0aebb7fa71bb7e43fc255b9a6bbe21d840cd87251653211934488f226228f526fcaeab6944df35b0fc4b75a735901f80621f6eddb04315f09a5f79e0b7771d6fd7f15ddb4f9d600191f448c8009dabbd023647fb5650f14ea8bbcf986205c773c63d37173afce77fe2a73cc774eeaed948987b48af839d7c86e6fa100bdadc78ef19a0e7ac05b26f18ecb96b3a8a0e1a5dcf738c64e302c25d68631159ff42c77a0d00114dbfa91c5a4b277bfa79b5c96963968f1c78066755c77162f47be3a890a1c05ec632b5cdd14deec05bc4892d93da4b18804b92b5958d8bcd8556a562595e4696bf66bcc9a57976020672749004befcf138638ff246411b18b498723ffccbfb81df64a759fd572708a38b5d38e49610e0ebc9e3678f6c880c284a3185a17147e6cf335fc501706a9cd9182b6e5aebefae4183785c99953a718a74ca7d72d6938f37dbcb55db4ba584501fc87a8e440123e49b34198b44990f811c246f94844542bd65d251b0714289b1ab1ba4a929ad06791801e58e020dadb64c29a33203c7c80cd85e00ab68a773a4c10c34d3225e21ab03c60aca55fe15d00bc06072d97fe9ca3c56abf1ba3e0ad06b837133b8793a1f636bce66c8d40d7862d1f07c90d76ca099a19aadee6d16deb068a5f272671a8040d77a8be0f75e5657459979b0351b35f82915058d9e5e7599a31637d9908974a3f4556027cfd011f502a491bf03bc3260d564211e38ab3e2c1d0c2b735c4ea393a9a90e24c52a5241f159eb47a8183eda8dce2a29a3c5e173bcd1f6cb3433b718debcbc5f3f36c045faffb0cf8cf7026d399c48374674057669acbf667efe553a7bd89361a6ba040806df07e017212521c217a2cf8b80523c0de4aecea37827026943bbb1637fc592fb421901b15d50fe0e846179d9b072cd8ec2ed8a0c69d5778e455bd7dc4dacecc36e0ebac2742b0d062eacbd99cd0a31d68ea122209907a1d3289b5c7beb611d44ac0d93b22f5d55925cac24319fc570cb90f51e46cf64892032a4c7a7238b2d68433e15e9548fde9b5589350aee4893570f0f07e8d594365ead9ea0c7bbd225157dcac7d0ab68b107626a798c823ea2615517656d7140b073dfb170457ce00c35a0d931cdfe91d5c0cb77761f234da3d0a836be3d6c1000491103bd882e5aeaaff592dc4913b152acd8dab62c981da08e51939cc08dab2dc78abf12f899ebc76bc41e4fadb37131b5d1b8c119aa57a0829758865e9eba3fd4940bf4fd8439ac5155a5125fa67979c2fd3c1d5021a3ac94c4aa057f65e43f5a750fedffb9eca049ef4eaec9b47032baa58b5437c5a8cbac1fb3a08bacd2344076f58466feadac3bdb41aa51a5ff658711d0ee385d0f05b2ef9bdfea392b266edfe2429a1c24d70f62a78e6140cd1910893171bab37f628e7d8a4a04d4981ecbf800ad03dbf829adcaa8e3604e83563d55d667258da1eb2911a76a4147c1224108774f0a02d1aafd5b6b30b697c824f6bce857e0b41da769f21ac60a594d3db7596fb0155b5963e85f19fdcae3458c23078fca55f09a9f376a0ce6c5d1e57416310f568eac355b541cd9d306faa195ac7ff247eb08c0d97cbfa553dc7830d144d97fcbdbbe109a2bdbd438d1a4854879693a560ac6395f1e3a0c94b516d75b2a99e8976659902953e431b793a899ab73108e7f1af0aa3907236a31ba73811ab0b8724095445d0fb67f19d5b5cf84c980bb174b834fbe6d1dc2e6b35156d717bf804450d24920543af4b41c9de1efa789b1fd41aeab1b054a5ea9a1e48880593d37874f842e8101c98a2913b4a6814f773b67ea01cc69087441da83dad225e8142662c312bc271d4a8ba14262e5e3c830a17dcce579517f85b1a2e29bfa6ecd2a95fe36e6bbbbb0a43d43321068bc1a9e2b6971c37c7a7164f729448fc8020f69cc822f67f3e4c3c1e9386a24f5b54ea8215061019b8ee6f95b96341e068ab6b7121737fd2c4b5c88d6a7720855766a35ca5d22099f32e72c241137b07aadcbfeb1e5d5102d9886e14eb9d32250a6792f6fb53e414f107ae59cc4d7aded145525ef139108bf7246b4979614dcaded807d58833d1375d0aa0c09d59b7d28675c1415caf34eaa81a6e9fa65bd9d36f58907cdeda5e6d71a7c89b46c0b88f04de9b36a318448b66ead69bf4f57ccb1639bb5161b00213f94fa44e5b2b036106e02ea3871cb5faae1631a2e7b69d3e7e2bf6f7a36d52e73e92b26e4ce11f04e73b2a1c5b150fb5081d1e58f117b19a018fc1d4266ad743bbf1715f8e9b71c7404fec05b1a9c856ef7feb2293b1506a3ad5aa7b7d20f5b61bfc7fa6a2b282448c8f02f40d43663cdeaf36a451fc002ba4ae1f51ea3834bab9042be82bbee6e93688fd6bc06a6ff3503b6f32be50375ab979aefc20091ace3da904788c291641c8be39d19d875c06eea513723b667c73f3b8c7eea12c2e6cf47ba7fc467976caddaf56d9d732a0d3f46cb1d75ba73603edfbf88dd019d61387dc74d7ed38af00cfdcc2c92ff4d5071c02d8c6818afa9702a3cf6e4f4ab86e524bf98fd2df157029b70c43ea367f0ccff7e6e45f9a3089dc50ab1471372bba0e5ab4a8a9e5509575cea1bea88ff5518acc6aa5484d8e68c5731a04e877c692f68924a6d4e3d6ed3ea411bddd69de71d6e0e28dde2d5ac0689baaa417851f95b547c80ee6431ee3eea7dab61b4c90ea3ee5dd0283a22c0d303acb9670d77d1ec5171d45509b9f15f07a7b2bc4a0c3271d3bb8a7db5488cbb6c0fb4096f785baa097a2ee9645edfffe7c61a37c1edbb50c6303e237bce76866cec826fc6dcfe5d219e76f39ea720e632e2ca1a41f511086fc5d463b33ce8fbad4a0de1392921cc44e694bbde1d1cdc9104aaadf1aa9c6175813485851b49e3d4313ca7f0e92ec0185870894d463ba9ab32a238fa96c423816d46d11af101068ca9f70814a38c0145fff3a513ade6142a769a028441f2153a8ff38e9a49782c7bbb264dcde0a35774e0035657d783e7b3d87a54b6328c0049f121062da8151d496eb2bf4227db8a4d0589e6414e7ce8f15f2a76b8f1fcac559bb97ff99842a09fcb81a39c009c6177756e9bfa9937e0891392b0b306a8e10793a44229a0677f25d87c4402f34ea59b3898beaa401e9626fc9b4acffafa6707e3c897e349ea80829f8be99d89591e6057f19678cb97d46e232b8b33535805fc930fc54f19346c5e2897d9954925946fd9606d8dc30c60098f2bbc089c2c858ea96016979aad0a6379865d11bc1acf6fc6cc8911b0e403a0488425755addad662fa2d0e054bd24379c42bd3968a19609261f332b188785db571c0ea317d3462c2cbf3c55cecd808299b14136d720b3e50240b303855dae61c3ddbfb95a761788a99ea21b9043e8ed76bd31309101ecaa611751c27ece46db94ae7fe0ac2eea20ad274a5d2289211f3d4dd44e1caa0a004c8c55908c4214f0d37698409463859f40427b410d05f6c1f64873b90285d591ca8706943521e149871f50009a7db1ab6ad77fefd8212e7ba7985699cbf81402e3f0aef704d3758db890f04946e436ec34ce9c900b4490f45a24c515fd6d91fe9faf93e07ec098656eb1bf422100dc0ca50f1b4c2ed5e6d516d40855224b122b07acfd782d501279b26a0714b23a6bb0c683444aca3ef6c5e4906682c1fa603122d036e798ecaa708ba30ee681f8aa829d105eb366e6896dcb4029c463e243b9f901855447fa2af302441ee117a3622a359fb3ae8b356675d3cc97428f6b826b922831e7c3e458a91e357d2cfba45b5093198964c0935784041cf925cdfde7eef72e83ca9310fc3be75e73f1b5615d9bc16429fd8d68224267199694a50038eb30f9c3223fe8e05065a84a55ce4430b3c66adba07a1c905903a9b8b8a0dc3e094373391a50d2cb91a1f94882cdb49b41aa11e6751017696ee0b5a5b945f9c1f13a832cd74d3884a5a23bb7a03a1968ed754394a5d6c2752c0726a6be1dbf894a1c10e684be81d4367054ddd69eda5d5e30e72b5855837b387fe203efaf975dbdf204ad472b1583e9142e034d8061433de3e5f4b513c3453d50d3047583e706f2c346ca481d5c596895af702d6815e131942537e59aeb99e183e0f17821184d9097be85b01cbe1e5bfbc16e9dde5e01e34d8e3c10726140cc1ff0111f1293f840775425a7aea399694f4b43c56ba469fa150a4a5c218f02a72cedad93ddbfcfa969f0f4545d73933b983438ce964fe21ff581aaf431dba61ab3be0dfc0a039c74787a38e0b096d479de6695e0e8c734faf3d9a5fe2aaff6ccba4b798121c92548a9da3a732f7424ca29c8a222e87527321afb81a39272b8664c7c394aab7833ce06f8423363754bd68242a7bd1ebf83706fcf860af38cb58f6e39948030778ead96bc974bd3021046f0bcebd9120e0f5bfc3dfe5cd465b5f02a6ad44b3630fe8e610f83e108813cc27c1eb79c4dcb949cc82e2fc0be65803187f73fd2470a4b1970d74c1e885c97f12d505331565cdadadb88625f38f4ddf98ec81e3eea6d3cf5cafe3b29ddf9e97c0b3b07beb52ba9be3e35e060ca7a95f045c5b8b6a8c19bcb776a982b8ec2fa0a1ec51b6cf39ec9f0f81beeecfc5f70bfb6d75763076f2e428005ab4b241d92446fd7d662971f01171124d72b570b360ee9e4416d91ddbe03ecb5bbb2267478d2055a81c929151bdb9237e14462e6af84e4d5bffbce7412b5c36412871c2e755be83464c831e8dde6823b5660a559a3cab1931935459cf4010ef9f6f38fb35187214fc78838ff10dde91a7ca6a9cad988580597447ebe2a8fd45cb01e066bd400b791f230c5c47c6bcfbb9c3ff5a21a65df12815001407d061d75882f09bec56bb2e42ce9619ee8363d06fd52124a2e0950a41e80578cb50ff12cc54e2014ee731b2fbfdb93f51de63ae3e9088628dd1db2a2b7fd07089a515969b1a5d4d515bef95af12de332e424cf3aa689dba6ef490ef394ef991ef3755c149259ac6903f4544c0b08d9bb039803f37dfc982b2b346b81fd7d95358a220315b195313880be34ef5493fef942e9def6b689461e5a87d1333acf84b425015554567fe9ab54c4a22a16f7d9546bbf682b995a6ce944e949f1920eee058db95ab9c93f5e2846ada5e5975bf33544c4aa7b6e9492f3b103d9a34f62598f8af31a2d51fe18181f21460821e8d202979eabcc7c6241a4697d8c31b7f24fbae4579e9637e49ee4a7ca8c7cfac500252af573080ceaff6433fe678413e757ee628ceddec41877f2a64d7f276a1c0504c5720b156654579bd92e7482aa68fa93cd3b0feb3dc32eace45527f2bb12670932bc7addd2c9ceb121b6ba14c69ebe11ed0b0da7ed0c487928888dc533d1b09a387cc8469871ee0ed43e4123adb12ed18aa5eef81b1c4fc03c8eb8891c8167219e5afe3aff733e1bba6d1295a8c8cf396cb0bac80e1acbebe610b024bc4915052dfd23a050f7463e9aec3454ff0b2bb25ad579fe0f2f4261efb67e805c5241aead0e3f5fd4278fe03d62af46faa3c9a51ebc348266833e8a1f27298443c47384e6345b61d029a06a6c788c55e1b831787e0cf33c5b3d46ce3d0cb917bbc634ef9f187d8d8f250142edd6d268fb71ec95436ebc143686e395130c37230a800a57a262b0cb58443bd28823896691f78162358999f23e859b4767d0aa8f791b8024b5b9f90372add5810708b939eb7278491b0691bebc63f94c02ff1a4350bf1bbea1c5621d268a57b6302c6bc851095ab0be8cac60f847820cac428f26d793658d2d2ff202bc004adbcd38a7fb0be4ad01e7c4f3c03a5ac0f02c41122256c0e5fa239fb1987c393557a4d373ba602cfca35c556dc6cac33a5e4ca3aa1e146d236b49bca8c8ad5da0927ea6d9ed9a09ccfee6e9235befab78bfd21160035ac3a849692fde7b999313f42258e07cffa2a77a4c251b65f33a037c87323bb770eafbfd499f5b97860417e55a92904fd820147f58b35fcd1c9762fb33af43239e09a4edb2b52805bdd833cdecfcf24f6caa9c75d03bf77cb3eb1da69e2f802f2c492c836b194cae8636f014a13d0d620569c5c47d64e959ff5dbde48f5bfbc461d11a263e72cf792846d52241feea71e9851ad427d73f4b4a16c91cd0dbbbc886caf63df169ba4ded326a5f94e68f656125200e953c013cda3ec9b82756c825e35b49324da514141b1f3734619e0624b57161d8913a3513f9fc451f5d742bc1c0ad996c1acfe5b5fb37c50772cd57982d92649be179e5b8ed78c6b93adeeb8665e77153208e3618d5a29b418d1c88a711b0b1c04ea21812fedbd3ee853c105a1932564f268b0e25f188414b7b33a33ba8f2d1ada05dd70b764df5260835 +MD = 763c5409e919b477735af72977fbac1ab79a6cefac081ef8edd4aa2a42bec9d5 + +Len = 46448 +Msg = a25f26cc1cd56088e4c8ea094c11c49884f6ae4869ad9b919e1c633bdee3b87d909c5b679c618f7d7e8fcfa599cabc43cd4259a24b347a96a8b37a5f31a82dd17f1815b24ba5d9648358f2c39c9da8512b8f3d91af7668b0b18e056a100b0a2c9659bd76cea824841aa8bd2d0091700bc567c2dc3d7c4b28e1366a25221237d7fde9b97bd0735a266c0997aa6baffcb9c451504d9c4d0d465f32135510c79c1add507389f70c6192a002e80186fe34a34fd64faa75f19452540a66c58132223c5e145168eb7d2310df1c19fbf88601108f7c27bc6f71ca94e747cd3c1e5aaf87a7bfbddf55ce86e851dd9060694f494aabce404b33d495544170af818f472c41e1d91eb8dd0574611dcfb6f88362f697cc51031f6822dfd9890d735d7b0182b333e8dcb92a2cd4c46c7af38aebc6ee401a8fd6ffb7648f6ce8a783988a919725c6765fabe54a8d596565b0e04c831b8cbc0f22b4c8a18d5586c546fa65fe55dfc10a0e55b5688968311853c04ca263c5db59500742e1c1dc8aef244bb450a3284d2d5381438daf39f71b46f3932ab0319ef6c6bdce2c13491dad85521e8f684a926595f537c1e714e0f7ef41ca23e91a2e6deea1138b6be36688d1d84cc48e8bb73d3d7a380c19401433b8719995f6c6b2462f7aba05b1f38e0770a5e6f7fc34e53ab1d8ee772d06ba57084da789bf7e530af00f6aa3cdc1bcb3cb81932e9a8c43e65ad702090caefaeb469b9d062b8939409b29cc6ca79519124834fb7350ddfac8a03f1ccb9c80fd78dc24221524318b709790876827b7cdae5085c7cd066d3168ecd7e3c3c6c3eb8631b0dfbd92bc72224c0c449f366eff0f4c3d9f45a486114fa46800fb73c1ec9bad077c065b7315df2265ab1aba04d7bba2242ae1126ec20432ba1a7b89c02641b8f0a0f8689e9d2e816263e09cbf7e3cbc0211ab386d6b0ffc95da49f209c4ffba34f39ca1853198d1cd15f9c5e81c1a009ffbabffcd34f96cc1e86f94e4ec5d1b9b1ff9ee6ffaa47a6c686e1cc6d8dbd8c391e84dd44649e805ebf55998c7e443edc91738a61fdae408054688a3db09ab357b6a0cccc987da2b8ce1276f7c1b9bf29bff6570c9c277689389f3c54d2be0be603922fbe43ca9f9723de8af338b89723db85f1620e59c56bb3f447555cae126e95e79aac0efbd38451183a116ba7634574a0cdf4bcab998257163fb1b6d1535bde0f72085287eafaf63e08d4a32cb0190be561573f938f77827379fc89ce4b285c786a75a6f5428563de7bbfa7beea1901b24febffb7f3b5d67aaa984e0b667e81b0d85674da769e2a680724c1b49dc00695de45857f82c7b3ba36076bff31a8fe57303d549df3cfca793fc689c427a88b1eb0d659509917baa0b0ec7c30394212da269ccec64674c46089f77864342cffab5c20f3e1c3404bcc8f99e744f9d47f981ff73bc9eb2798dc7a4a15fb3fd7e4ca34a7ed998dbbf7ac36924593dfda953f80cf343f6e72c84b8530db1fa733caf9defd9eee54f53ebe4a881fa367bee42efda7409d2cc0c32c4f3e403806cb22c8bf749056b58691814fddcdfa3e0becf4eaf1d959b2bc29fd1ce4ddeacb088ca55abf5a791bda90739af5d91eaf4c300fdd4166fbacaf5d3c82a71c9e8066592e453065bc148bac23c072e97757fa2dfe591881f95714ed79250784c9c38f18a1e37a3aa63bf4551064d7479aa490674ec2d9b2d96ea74b2158889ef2e0cd5bcec9ef51bddebf1ba7ec95ac0f31995c6fbf2762224fc116c3b19cc3b074bb93037d22336989467078bc205f3b7b9f7ddfb264286a66eca0eeb4d6ab78fbd44ede5195683fc824f401782a09a5defd5c1d21226df8609499e0d6a8bec2e291ffbdfbcb68b727c506b094f513d4f84d77b6afe4bb72b95362788b956604d58f2620e026ad5604c129249724065f440a411a932d895fdda38ae4682f49d5213642a59359be92fb83ebcbe339799b4eae58e79f5f602649ff83d2e0d8d2ba7201d5ca79b705048897cf252d97b62f74c41f7c191cd85c8ae1edb28a14890b247c600e27e12911186733becae1647252c6156694c84a691cd51911c874d56dd52071cf124a834f479cc9f74f890d0a653ecb2586f44ed27c53966f208c5048f0787babcd65bc258282e26d3001185e3898b14784134e3f35d7f62926ad8232f30efe12bdb53c2a55d42d9ef0ec0ef4295e683b00c7d0f5b5fcb8de5f5ad3a2793e69a267db7bc42deb0bfb169c5952c41a407e81646f9c891c4f0d1f36dd1def915ec9502af3899731fe0015b49ff0a536ea808a9b82aa3bd13923faa3f71bc2923df60b365bf11e63745c82a74b64294eb6ff90bfb2952a9607b18634ca029edb97b6fd8fed812fea1f5ec1f6d413eccc463a184367e3f1e52b44266bbe98d0b7fc9aab9a50c048205f857825d2864c3a08de95e91b2d0e39144a7fbb5d1504c1cd0fa9d80e2503b0a57ef9b6bf41e4028f3b9df354c6fc2c6332e6a62e2da78399845ceb7e25cf159199eb1c02cd30d049ffa514ad48381998abefae9a394577d2a75927394916b9a464b0e8358eaf0db9992faf7d374e9b15041f5739ce4b0918d7032dc81577374e7def8dd01cdb255e76b2365d0a9c2b78d9ea12756334d1cc920f5193017cf8f033eb8f6aee31b1b936c13bc538cd45249bd472e58eaf4c7e76b255329374894a25596f5e794f2d5a57c1423e484e62b8d862eaf2a6f6e3aee3b08b1f521a62bcc0ad9023448012b23856cc20cf9c2e960e1a0d3552c831ce677e85c1b3bb1fb8a45cb471e670ec3176e64c252532e35cbb6e3c26087fa16d8070b7b23ef31ade3eeb2e92c59e248881f444b3ffbf3b7d5ed40a3d3ea9dcfcbd3ba3796a4ede8e0eed713e78745607f7f54845a57d916866eff9e37bc32f0c7c23cb8fbc1ae55882b82ebd557feb30378dc962bd0a7fbe62168dd13658220d4bedb25dab03c9ce38efb998032d7ea1cf123a93acf270dfeeec385ef4d5508fbafdda6bcd85f64f9ff8946708196add2d372e310ba1ff5d5be57c153dc734f437b8b6527a1df55d367751a2baa04a32e04116f34fa585a73776db7c87aa39eb50b2d87a673831878ac083c3b17e975376d48732ef89ae5e1034d8fd58fae9d57470b37beb61455f0b887d5282e0dcbf6f65f18871bac3e26483f7203835df333176c9bf9d25bb344713d0c7859374b71889d85c6ca580c4a308b88d9be764951649adbde301ddb7bc1710ab5ff31a0b2094be3736f64f756a278f8dfa8c146b714db20f53625759d8f6af66687c170c163b159167199a951854feb9da908936f117892c74d3a28b3c271f9145bb064a47c17103838bfc743c359889c2a11d78141b958dbdd239cc344ce3b46e2c523653ec52f602c9efc3543dbf86391a5bbf38ee59bb94fa97ad8fcc9e38484ca560c8f02df17b5fded2ded20627a488ce7cfdf4682ea09946af7d2aa1a57a985a49f591848e43ba64536a96fef6ab58e021d1b2236f575ac132aaeb80745b9c0b628834d914f265faa555f0fc6ba4273b4e32cc2de62fab81e78783cd3d81c4133aef5eae3e0def1c594f74911f25602a72bf96ea3baff8232ea187ea5983bd1c43a97366520cb243dfa5965f59b580480fc6a6dad84eed0f88677c6a60c7c3711d3517b409655bfba8f6eab9c3cb242ea5f670923482e6b18567b5cfdbc483dc1810bff9bcbe58ce65c1c622e5dcb818b5ad8882d8f271b39620d87d43008a97c4cad0c9f45e15166684cd4d2860b8c0bf8a533f5df41a703b0169150f12244ec3d1fe8738eb3d7e5bce747b140da2a133eb752a0c3e4d9204b7cc09b8600d6b75b49db412ec1e6095ed304f312a0224b36f42d59c078773538295ddd77082785af132f2eab75467a58fa53bf85c53d5ae7450b4660654aed8003af3d4da4feff3f662a648f36bee1b2427b3d20b143e95992368f2a131aed2cf400e48f3b24cc1528160b616b17e67295c6976bcdfc9f95c4f45da6ebafe044e396fac53462953943394aaa7e1930a2da7af2ee7f2f25a2c18ed85d53d06cceb7bba677f97e02b19ddc4af1d68c6849f9e0793230a62288734c27d6b44739d45ab4102ef140ba87204633bedb383570d94051be49273f50c175739977daf05db3cc6171847266c3b3c12c9af5e5401e64e2a51a307b24019253e32f02523972aa4ac1c91adaad6b3d935d0b8c5a315b810d9bcf4f6a78a3d02ca01fbf76bb1a277557bd1b423889a805ef9b0860af2f180b5b640dbbe33f6249d1f114101f5d12974cd5ef70af24db5f0ad2d1bf62a312220e61d1380fdb30f29f2e6be60c4353f6c799ff2cb845bee9d5374f3ff3be559bdc4f05a7a182226e325d2bc22bd5d3daf192b140fef339eb7952eba70a89cabeecb410d144392007b106bc6a241a788df2476e72273634ac1eab0bc14e0a59d2671b5a7e9e0a120344b286a69e1a2b56f1409f8cdc169775eacb1953684beb2174094b7557fce0ab15e7f14042ded57c1606aa54c49c4a8e08397b26ff5466f13c084b8018177247493065feb76d5c488b20f99388cf353f9e7d9b02bc2bb48be79fc2658964b01f0b124aaaa5d0aa027516f210cfb841d0d520dfaf47dabb379c5718ed51ea837a8117080ab60da5f2ff71ff95425d5488d4a9b1f44769653c83b6b5e018b2d1a2d3c607e7902e375f4eb887e889c857b0c4a0789a65de98e4c546010688c284dd2aa7af08db3a47938d73f2d24b013390cc8d9b6a48433e758a8f652747248274ae436937403abcd4e22ba71b300ece7015f98429989f3e38f918470afde0b5af86219b3a6635806b7566108be2f91298c66c9aa2fffb80753b69107853fc03d5dbcaafdaf7337aa06faf94ea06cae64f086c459c235eec74770a2939f0825630d4c40bdf983d92baf88b9bff478731df0383eddeacd06a7cd684f8157e7995069a991911f359b00337848d934a3add8ede38fa31435ae2d6805de7d4a2eaa8a054d03f38b092bcc15521d36ebaead1a5c213d45d90023ccb9c205d3d06dc76462bf2e71b77ed9e3d7aead3583da0f56bd69de42a3ad260a15352c2195257e93f47867883ee743fbfcc68f6197b63312a435d9060ead236a0cc7d7d302e64e8d5cf145a38c02e858e7622a4781e3b6d2830dc41c64709a7123028f84a40095c4eeb25f402932359f49ea1463fcb3091afc6a06025fa7f993da6dc9a2f33502bf3c540b0a9105ca4376d6b42342c4b85052c335345aa3cf56b5720cba6ad413e0c82edf5f4dee04ca00a0a0220e99331728b1d84ee0049a4e26a7cf37956e37de14db42caca5b73b779d06eccaaa117e400be459e8a3ad8dea08787a6ed83ed0b94c1ebb990fea570450e56afc16cb52b5d3123cfa3d7097cd599dc94ed85a20dea7b20b83c2808a8e4931e37cd5cb971b0c2e94ee739bacd1847246e00140539687f884326681ba5fb071bf13901933b8ddc1c98aef34b340b2805aeef8f7532a14798e6ea4f6d1bdae2e6589efbb10d56f524397594693600a4d6d3e688706e275bc92fe24e6b6f16bef3fa699bb14b9ea6969dc58d6367ab563e89af7f95605d34af6ab8d5951430e3cb432372029ae758fa52395ee83d5da4a31c84d542add55a9243d87578afabf9d2cf470f336fa384a5e32b89562bba288b29013a069b02463827cbce94960a89b0fb5ed3b22e65c25fdd268d4bb7235a7d2bcf1e5fdc767007a2fd11676bbeebdc63d5500d7ba09a5e8cb4db27643ba2ff8128e2ccd6a4706732071e7f954bc8cb754514b3cbe665488e510377c7659a68e5c937cc1e0ecffd5154262ba73388f4bc28923393a9cb945e8596bb3533c96fb60a7dec1737d7207d7ec91a2608a4eea4ea490b675d25c889bcf5704228886a7e77359b56922e8732e187c9762db51fdc24b9a9bb831c6b7c71b02572a68fffab89ff5850b05e880e16e2a82c25321eae4254ad04be17e3c34e57495b402885c9dd2ba1aa14bfa96ba95a34cc919451b7ddba73e76090c7daad4b6a4087ea9355cb4b15a731fa61d7f36efdbbc5645f65414b9cb81d2f9e4f190cf6e6e05eaedbeeee12ec8a7757df9f81719e631aae533798960b363ccd7d0c2c7da2ebfd4ec8b28537eea0bee1ff08422ed8ed3fa4fe0b11ee655e50dc01112a7cf8fd3ee9a8b090d331f749a692c81183efb63c09c24658143af7f45067a277637da69c060853a1933b00affc4749801f6760a8133c73db861095afb11d4aa3cf958abd3a443637f68e5f4a7999171e6fc47f0c77e91e0cd26ab9db749e64201fd4ebfaecf8b2b45b9055b1a4e4cb3ce38b63c19e44af7c77cdc7101167a98ce2b07cdda4a263a750d5a66de4d6b06c2920b1700cdb929af4ae6fe62e05653aa6bcafedd7cdc39164e2a3e7dfcb614c9f28da803a1a71f8c780f6b610f431c9ea5de7941cc74d03163be0a7fc5f782eb408518aac9dc8166eda0e1870b099bb1c18c678da4b8a6cd345ef36a0ff4fb30643b8e7dab20f64693e0875a3c7077eba71cf04a6b6e64f2a95121c8417625a146f73305b03b2633511986640b4059543fd63bff885fb1a8aae1bb20c545a845cf012ec940f4ba350f91052dde40e8f572017134655336f81f54e9fb02292d25e5a0a851c4145a54b5922d3b1e39cdd526e7b97269129be9f0f3d5e060ea5c47711ec926a264ad992c62251834f4affc44ce3c3ffc6387840506a457474fdcb55cc1b8cf44a95c0b5a49164c86363773b5ff2226860fa2d046d581e81f2256778cd29ed410ae0eb22891285d7eca0d415fc292ac6fdf95d59ca7921c50297193eb98a2be703a6c977e8082d58377d86e2c5fb45b2098089bedc6ff7a422dd613605ded14cb141ec145604d3cfc044003031db1baff05a22b2378f18b5ef52cfed267a65e8905cb386377b018533aef07cb45b15175ed0c8c240690d50a4b1c5d2b00f62511d51b05c20ed4f3efe18a826e1fdba9eb17eec6dab803e2aff54e37526e05efcd4cb82f486ce15438c1bc7dd3f35849c74ceee22bd5733ab6bc69942ff9fa47243147bedfdbfec496a12afee20950b97254b7e701a707638568167daaebfeb27e4e73bb6ea153ca714a7f1083a8ea8255f7efdd4374e8e786c1fcf8ab8a38ba4369e12ddd0709ee318561b89e1a4e2bd7fd3fccd9853d4e208ec4101a20d1e6dc4b3c1c145548b83e1879001ba5a53c5f2d4ebdaa222f1eba9915cadff3f0beafbc2a91fad337b101cb6eefe292173e5750c5b7a092e6e1bea89830e24bbecb2584539279c9ff60e068e88ddc29cbb8262e4bc3a21f891e9384f4490c726394a76a612a787ec74d44b591e3efb1ea32348f89e8990f405ea1f5d21d43af06a29b37f95ee03bb801967c0ef804749b34e93b262e6bab352850c3dab57049cf7b6ab3c5389748fa033c830ad504b80747adf9cb9d013b8d0408b5b3187c89e7a97da66dbf86edb4dba0932b80d5c655f2e893203e4307737a3194064e4db776b43bd899fb95720f122873190361e6aebe02cfcc1819560d1333287a60cd1ba3220b11f0f5ad1e322f3eed7d668e5f3a32637678336c7283567639b855e2fc977d57181ab4b43a45ba49c7ffaf467b20d67350cb9822a1fecc638f673576a47a4c86b6c040940e723cb1ca46e8708089329b246e4e252ca6fb60f130097059731800b38aa233e2df3cddbefb18f4b79ccf41bc085d5b5ba26dd629bbd8b864aa682cd71fe17bfeb442376bc548ba688234cfde42ceae751baa2efdafaa360d48c474e9280552a91ad626984d7fa9db62e9ab53c4a805c43838ce36b587d29b75b43fb34c17a22d3981120f3bc5ab5765773fe235f3478e22a1209c7478745858c1f6fb341e52d038ca63963622a726b365f1553eb85e1c006d8af69584048a1a72ff8a87224adb3f3a82f6e69f868e733b2b7386fe31b6fb22760ebfb46a7ae250c328ee2c72967857d5f7f4432ed8ce825403b6cda8a33b4a4baa9b0f8e70d9e2aa9c1142b24809acc5600817884bebc1d3ce752dab2de76c7193d09d58b327b01db0976ff23a1abebbfbc9217c31f380129c6c27229a271150910766b18df342822a29b81ab5d4171d8ee06bf3d00d47783442c2f53325c0506be8737f44652142d36e2712ff5e3e54e2f4fdd372629f6d60a0070d400601d9eb1acbac21a7d4c6730fc3c260e1bbc9bfaedd065d190f59e62efc +MD = 8dd79361e81666bccdca844e7229c88b66bfdb559bb0511379f85f5bded35938 + +Len = 47240 +Msg = e3cc8337029dca793c2f8c0463a2be0ea5f7acc157c5e08ff12d45c6590f8c64647ecf2c9a7274f939bd55537d411d401f5ff55c1bb3612cb7fe64b0c163eb3718d769776ed3bedd4b4b5d2255e4ae1fd062b1e2615fe5011743682eab705f0c07bd984206266ecd7bc2ed9a74f53754c0e6267bae3333b618e4976aa09eb08b3a19a5b2ebd44d70d0084de361da8186f7d49e4d8c9615f2c2c93a892755a55bb8d4d8f1a446236f5206c524a4fd545e7e155f8382f0515d1edb98b6c9fd072589d47927b9e3b87109a49d85c6c478845c8fb14319aab0a03300fb170dfe9e90b603d07bb212d31ffecb1c2f4e99b49f992cdeb5d72afa630a21a9d47bc1324546482516183d3e2138618b4ac4e3d1573ed32d0347d9f74da927eb169bac8beb418abf2073cbbf1ebf4f32fdb1099856516ce552ee1f6e071af80905f628702bb0b3e7c049241fbf9c7e59719c75ce41ddde4fcd56652939657e4bc8139eabad9aaae51e24b025abd6d548ce0d8e3ec3e713b3990611ee8a909ff9887a740218075701638bd69b8a753b463b8cbcaf8279f259e1868d86a2a5455a6cb4143e15ffa283b707014706829a9de0a267e8269a6388cb5f3fb92aab57b79d48e4274b8b73b2411f96f3c503d993e6d6f7b258534e897f18914ecaabbd5842be4e8463b2b2d72a5bfe656f03e07175b1d4d5c0ab9ba52639ea0f29ac5f85849fb81f047d473a9943a166ad87977fb4ba671905aa3321e84ab1c2f0b625868b728cbed7f21a23b760e7bd2799e604cc791646cf58fc48ecd45030c6d1f7a27ebf312a831c14daac3939348440b54ae5764a23c8bedf615b5f2e215406bd23850f0f2bb1001ba69f56fd916c85ec97253a6c7996e3c4b35c71b35d425c5f4fcae88e8809a818d1b8409d9d896e7334b74ce210e1cf9487189447ab37dcc56f72d5160b321bf4a1217e7f2080063269c13416b0528b3525b74f52d4db8dd7caa85b0f7ad561955fff980de2fc52117d6c7b6e21901e91d5602a3ca1d7777eaa9204e19e9983e5527d17adaaa35cf9badfa8542a44908fdf3bae6dd7d3a2a0555857f43f2788cbc4c082c9411d2bd06643432f9516ea168a71624e417617261423dcb12526782efbf361c87013c780cabfd46728ad3310202acf45a669ddf92f1b1c7e173f5bf8403c3d12fd2d39ef2e7ce464acb27364e78d7bbbcd54fcffee679ec4de1a3a10dbc39c0fb0128807d9a1fa8de8ccb2fa28c3f0197fdd7d229930eaec425e1c5e14b10927536bbcae15579f4ca6a4f9ba2af3b6c584af6749779d895c0bb40aca332e09c2acdfdece28c65a08ace24f8c37465329a470c25cd1d7027e01c30b3c7f6126488517f44e5b15b32ac32dbd5895e451aba7c99642ef05ddb9ec34279c4173e721a4ba0916f66d3218b32d4a068df438b55461ece51950a37493ae66d2c28cd4b5d171220e41f5603b448bfe7e679f8eae74e1cb2c97e0db19bfdad1c647d2766cd6e4491e84d6c4fb3eefe1a86b0cddfecff03cffb0dc0d0f385f6f611b7054af7aba852e0637e7c16800fc6ce164ac0c2d374646ae6cc2bec6e74989858cf7e4849cdf2610414ff38b6756b310ce8442565df1e9d7ba808e31176527cc4fe575bd315deeea1b86fb6fccf7634173ec07110b45d174ebd2e74099cd2439e0a8c8ed220a6edcef143fdcd5e866bc7a6cc328e94be4cc2a3d31bd1589661467c847dc16eb8f2ee27f299a2d30a2c90c8cdf619e0a0b299d4bd46e329fd7a50ecb5851b60a37271e511f707ad701b051d5c185d38a2fd16c83381b99195e33fb3b6515aa6e4f10cb118b2865e66ab870ced25c2fd4360dc06dc58ef2fee208569fd5f1991fc0311048d4889564c42a92007aad5bef0a25c192e48ee4574d6a488010aa2b2670d2167d6259b359f94edef12242fee391619679fbe2172b86a2f9657e0b098a493b05389d6266cef06c7d2b30e1c1b9b50968ab7453348275f790d687dbdb5332b40402ed6d57c991cc96360e534c785c645eaeb5a9e36502b3355b93e1488912843b61ba402d55c4b65298225f462870bba10c28accbda151c127d0ae6f935d3f4d3df6ca591777171d9dbd6cf58d2d856584c332395ec967c4cc354b2965f5c4cf4046b612b3980465286916a297d7c7dacf740d8e8a06d190eb6d90dc60d95d4c5571f3fa2a2d97de522baf762314478c594b6916d00823c7edc01bf314966d36f60f1069fba655ebc36bb3faaf6188ecaabfd17cc13bd2cc4c0358f801ab79319a7477dc98a0a30fc4afb0aaad5e009e3c57d32ace1073309e7db475b89705aecb58a6ec919b13dd0e7e21f09d5842f3a699da9b573469775db5dad699c79711011239f467043cb5e94d84870ffec49f41fc84690d064a12f23218a535dba20ac4378d8e995a623ced9454b8759019e3c6f63cfe5004799604791a5c0d41caee9d4f3e35a92c48d493e91f1f5eea97838e2d70d5b0cd9c72fcf13c859088565ee4bfb87406f8350f74c240263c3cd1d10ff8cc89bfb0072c54411b9c601de8be430f78b4332cdb6ff8a674678e256d6ed4eeac84dd5a6e4492ef241aec71069f20c51b80ce589058980c085dd522aebf7585ad418a3b263e4131e28ba630247416570d6438f9f86bfb79886391b33a455a442b6a46c0c38be7dfd3691dc9b6df8c6bcad9039f681c7b658123546574930bb0b349a389cabfef3f733db3ac52240b49d0499ea783ec90566f179d98021af231e17a20f4a03cdfe74e6428567af41b97ba409aa0c04ee2d2cebacdf9575fb66e12663fafe8a5225dc186cc6685c225cbe5686819a1d5db510c7765d7e8d3b0bbe2b8600a086b6f097910105b2710c26cee0b8780bcf3f257c4f815d23b1989b1cecb22a184020e70d19aa482c36269d140a49964563bc06d74972e66c293a9d6333907f4e00b993a6780f99bef3994bf69edee43121fbdf897ef401413c4899fac6c8072a0ea87bcb75d7ff50ef8cb8dd622268b7502538fab6adb58a34ea184b6d01ca95b11627e2daaa83ca73286a3220ba2cc039619992b9450a2f574aa1bdf2e3d175322b20556d322b14c794eb5b9e51383225d88bb94e650818ee8dbcb81c1823b4d90eed8af714011733f9c3c2a58d92f75ab295d73fb5b82d40def1a4b245c838eee816eb3ffb0db9ff7f78cdfc1644f52116405452dc21579763c9ea7d15c9ebb9e024de0f8d56e3724d94e66d955616c12c139850834b7c3944cbf0452d2db3821f9ecd2d72e47ed58c9f74beb2ce40841d960b00513f856faa801fd138fc7a90cd0c1f6253bf7070631fdfb814b65db01151152cef045b81bd6edfebdc3e272c11f63c76d8f0a38bfb9e8e236415548e2fcd1f9a04a2e4b7a41f9959c1fca29e13e58c31a87efd6e7ca3ebc749f40d66a0918f1339220a59881bb3e4903ed32efc61775b6c7168610db75d6b6c5a70808c25cf5f368bb4ae90e89754f10aa224f4f065bbcbd1cbabd6614cd9744f65231a124546a2e5caffe510ab718b6af7c7221cbe1a6ea70d95002920d70adcd49872df5b9025393394ae1b59030765ba60af6cea40fcfa1867b397422ed607a528bd147804688ed9b5148f08d10c03d337c26851f51ed3d369163418a67fdac018233a036c13eca3aa3ff61fa4434d2a9484995b017c3926e252870b06ae5d0db3cbd8668ece5b79ba56d70844544aa7bf1d86712bbd34f91c8e1884180a977540de7608323fe4432f81bb2a79e60333ffb4b8f93c8acc345df370e9a23c90de06839c5122118ee94fea29ed0ba17eb49e71b55dfd8a0ac0eea916a36deb50324ee3d3a925ea625463b6a9b9c12fc514e27d07033366f58317d7921b41c0e0576025a2780273666ab210c3f66435e03914003555a9c596661fa66db8e5634737847392268253a414861e000cbc5ed50d7b21c8b92650f351503d2ee1237b8db802f22a1b6d32243b2508e764914fae766109479971af162df0c55d00c1b0bbc421ccf2c08bbaedc5d8f70164abb3735e0ce03a5c538907e04865837c88acd7422b29727ba391069ce713d475d2302aacc5cd2a6a9486cc54a04627bd4014ec19663033b57f5f7aa69a83ea00cd6edd48d4f89e2bfc4f6f6f408fd12bb193ff331b0abcd7e5cd4ecd3970cb6b65169319818a1e07528cf81b6f69092ea2cf1a7791de95479e828cf70b01fd1f62d0550914ab326660e46d3f76fc582edd7044cd12d5476f72273c0e595f0a858c432affd48263b0ec00d8c39d6f4593281f861de41759b6286464f96bb17a04aa181ae40b38384dbf88408e2cea59c54c84e74f50cb53838ae00ea08920d30386f72d9efff43aa5a123ae8a6b971a2c11466f4c9e1abe405e4441ebfbd49fece6866c16f8dfef205a79299ea29c12303e0d26fa162b20546d3706c208f465269370de344021e127b133b9b21821c93a9d831542002704277f62640dfaa8ae19555b8be11ee198206ff966af164fc6b0f44e430ca335ef215c6d63b4171a012df3f07c03d9479b755c72397be44d91fc0c16b841487e6baacbff0b9fa86fe6ca37d6b883ba7d728c404739ffca44b284ad847dc73729ff2a95c065b7f4d2e558e7b5474a09a8a5cfe3206f23105cb1b29e3f9988b85f3409825a78e24569873fcc37323f0ef3bca40da3e1d0fdbc17eda9f0146b134890af5a724c09e15c53e7ae02804910844075857b99ecda8d6c9c943ff7578f0b9d84e5b3ea1511d4d2b955be39525983b9a9144e9f60eff6362928d3493675d1e3f1ebc259ec1df98a1b881466412f19ada882c5f9158420fffb2d5512ef0dc1e95c334aa1784df2057611ab0efedb6ea6da9787b1f2e1334e7a6b6c5a6a9f04372e86f1cb9fe9e8cb33b62d3970a4a92ba71a3dcfde4e56ac0eaac12a8f73c155d0ac5fde4b380262b8403fef81d4f2c577d58e59c312b1a01fb1fc8946d121cca86d3de2638369546f768b3918b273fab28e235988766db21549c48077004c22209133e0cf124429be22b91e1d855155c00ea3d615c2b26a583ac1160a4969e29fdfe8de772dbc670f0a71a77996b75b091db7d9523ea751504c9c53e7f4a0918c2005e7431cf998c9f75adb122dcb96f6820769273175ee6646fd3ff6491bb9511c31001b26224354b21cc2d191b58ded073a8e7ce543c900f28be3208fffe1559b1533e7955ff1180060649e0c9ec85772f85039a03a6b8816ef464b107792006559878fafda297dacceca62e4aed09d8cebb846ab825b647bd1706012a853ba41a405fbbdb873eb7c0dfb03620c2c251db9cd8b4e4221fee9d76a48debdacebf99eb313062457ca3ac6ff6bcee16459ed0a98f0d0a346bc28ac3be9bcdc25fb53f09bc0d4445e82aca0df80705401a0c3871f5e7bcc5108fff6eb2df32e47531842c5e86d400f7b9b44a22c8f8e8a6169d76cbb95e5ca49375e83fbcdda9959103b37741a41f31dce59505675b68706a5a387f167183ae6988b0a3a9008a4760284fb4d236f90d10f88f2e668f580f6409376e6398b2849ea2688d485e2ee12b7c51959d0f171fd24798ec3b173fe99024e438453661cd9f5d606b0f48d0196f8a5978269f01b0bd6d32fd798578857b27df6b1fcd29efe81448ab6253465688bcc7faf35931861ed3eda0964caa7981ac795577df7372055171fce5ffda0f238e3d9c87d03ee69316499415ff3e2c400d52a5d1efc6ea73af8cae0ec103c9bc992abb4896728896aea7367cffbc1432d4ebcab2709ccfcf88f95d41296c1ca0480ff5da1e84b2b5f7b7164fd09cc7d69db5429e048d885578387921ab7b5e9b356dcaa0daee1b6d9bd991e31468cdb7b24f9bf91df1aab1f7da8034c9aa25f9cbb4b8314e07292a058f57eb3d988c32dd0b35581f61ad61724010def680f94885852d000a684267cf58d6ccaeb489e45888ad3f9b6616f082199994d4885f03ed5fc791729a1dc353c67d1bfa455d58cf38721414676dcba1b7990ac638bdb88d94e67a291501b92d48d93da2b36cecabab127a1cfe187f5bba7d855e1a9bd2c0c5280e8061a4c5c66079c63a973f3c78411ce61792bd681a92d5b90e967fef3170fad33af85d55b99dbd2a24595ab4afaadfcc86bdb33258c13ffa4a34e06a5a28dd7c9b41b1f5716131fdf28235d1dc48f9a1fce7905aa0c5faedb38e53d0a54d5e4f33e64921884b76a6179a5730689bf91aec98db4d9d21b4f7bd0b40ce9d6eebef975e796658ccd9b7161a454cef143c7bd85a0a878864ecacd9244d90ccfe04b23802c9408d65f995708a7683da62526942a39484fd0010719a71c0d39e8b475b987bbf2c709744e5b9536171a4d6d957bdfe1fe28563beda737c51139c9712202b41d1a6bcd15a1c531d9c92f9121fbb9cc1f32c9c30466be69c54cd4191f3c472dd972bccc497adc0319e642174b42971a7b4afbbd645aa765a625d181c7aad01a776481ab18c1e9347dd61c8af2515df17daf86ec64afab54ef06faa86f54e5a47f5784158a5e34eb8e0185901f105378aec932fa0b4e105e295615372222cef37ab38bb0a83a0551d2d044d1d967c0d89500c78c621f1eaadb7cebd5e5fcd22ef0df5f24793ba48ed3a923f7283eee38bbbd0c4d6f0a1f618de2442bc2ca3b7d6745c81a054a58c919f5e8a7147d23c1a666cae23cf859aac8efe8e0c0744f09694c8d3a55506b2a2a1d5c8ba60ca89be065c9f6d1cf15ae120b9e9de7e257fa7d5c782b703323da9087474be5d3c5edf120d12f34799b94f69e2f0a40fd9a782cdd4f965eddc901d39d718fdabbc1df5f01aa356fdc3385f91064ced2ab62aafc37db222834a4c679c6a1fe8baae69bb46e1bb18ae225a9a5ca0392a6d5f5b877d3e478d522fe520c69a14002897a4677d1ee4b8b72b8278132d4fdc2649ccb2517323f6d8e1dcd14f037fe4741c60b3191e9aa7c73362815b1a1b8303e9f0b8d6c8c20f95f4a5e17c22ce060b812106916d57764cfe5d3eab0306af84d469f373bbbc3807fcd2d9f47478d57d8a67da7c879594c6d0e5187954abc2077d9afabea88cf0ad5ee6333e752ae3488c97b740f9ff93b35f8c974c9b756b2a69f6572e3b8eda049f5285c0a13eafdafc43256530dfe390fed643ab53fdfb5c1e1e7138c16c448c329a3a01854eabc37dfc9d7fc8c114fe3334a60c0aa0032b0e75d164f69fd0c2bd4fd8a79db55780762687f72e4da839913a26e51bf60305bf9f00493783ff4693c5d9f9570d43a079539d51ddd00df19d594edd247a8b7aa5fc763bf0c330766a9ec69d5dd0f091fc06161663f2c6b4bc14a64aa0b7fd085600cbe3ded804d0865d26f9fe9aded372a0babb3d1052e181fe95b41d08e81d446e49a74e3cfce38b736395c5b57ee371c5d3c6d5c343066369c5aff617cd47f577981ccb6c893dfe6405075fcb41507de7f9bfda860791f4f89ea4c85f2d16edcf3faad2d12a3e33b1a3b50946d6990b89a50c97d321229b2d8929003987f891c7a8e7f1256062efee98257eb29f2b8f2d6e43ba352026ea7b2db33a415e6b96134c3aa2b3bc5a677d8aef1c891b968d35adebae16751d4763f4c9d30120ee4f14c2496416ae735ed0c4685f44cc589a44fc6ad0119074566a66d366f3600f315e836ac1b8a74c2aab0d27d38031f01aedc257ec9122da8c010c667282ac3cf1531835283447534f4eada405a5ecdba362a819402f7cbe4cda4e09625955f5e394e92f13f40f17514e2e7362204d99a876165577473e7e3d28b422d2c20dd8ac967ebf21825f06c52c280c75a9e4a8be8a8562fe62c8b8c1aec74920673443a0ca617bbd69c7a01f5af2e5bc8d32974a027de8421cabec7ecf0ff2f7b359c564b319db6414c981c47d3785a364c7d3cf80784beeef6897c8fbe6a6a520eedc5ce30054a20de51a58e56e62c6ab14ecd3870d0451358f2934c803dad55a84071ddccd8de3df9ae84136000392ca9a50ea8894b82589704f56b5b015f4aa89c41c02c9cdc5e46b5a21e174fea46dc89e78f7b7cdb875bc48834793de7fab90a1dbe7adcab4c6c70e5f6a65aa57ef30240376decb9664e3c35ee0279af2d8191ed21db1db3cf14e736e533a9d39e961801e6882185bf1673e5e31e3d1eaaa839992f79e95caee6217e31e7c5dd6c6cd413e5f4a5a5585b717e59f3129c3bd70a0a317cc70eb38926a323e93529b11e3d5c7cd80083f9c63fe999ac7f91a6b60d266e0c4031a4a6fe8f0362812134535bc5f25cb8856cfee40feb6f0d65b4ec49d6304fdb2d4ae4b2281979322cbfb4373691aa571578ac68d7966442812d22c603bd70206a6dec4858ac57cfb118e9d8989fe7659ae478d4 +MD = d00b3e79de1aba35bb386d6e939bcd0d407eb5e6a09bfbc50524587acfd057c5 + +Len = 48032 +Msg = 50bf7a65c2fd46ab2e4221646a9b2e3063d1653e629bf11b8e13d6c7b367d70e41d1971598c9fe348279de030171d7b84c9c78b01472a64b0b7042fda7c506a2234fb012c8c563f66a364ada35b27e83aa472a82e42fed0920477ffe7cc3984eff200d84da5b3c9aed61ab0e8dc6ec3985b9c4dd5a388cfdd480d6f1b9c854b9dc2ef69256f253c714e24aca9215e983e5dc8de8fff64bce2f038ffee73b038cc260b364c5f16e26e6a16f34ca083d09d397cfcc5ad1f42439b8f24f8d866d6eba9e8b23afc2565e6b866274bf05af7256d2d0b0f4324da9fb88470933105a08cad0c8f79accd318ab7a6ab3f97508667775dabd537f20037c59d55762419202fddeb0071077adfcaf63d019ffc1108f3d69331a012233dac415e55fa081dc0358b18c7c982babb17e2bddcd584f8f92b09423f186814ed7dca2bf49783802b3e52fa37dbb5096e020b8d6f88f894d1ad8dff46768063ba1cbeaab3e6fcecabbab413f33ff4e36309ef406c129d611cdbe32eca63117c1e199d3f1660fabfdc3b2d0a6c6ef8e534affc5b451b09da553697655d6681ea73f4f47d8e8df38637203c2215d1076b5d54b1527cfac48cf55e191751e9682b662f42da9ec67dbc371a501f820ec6f237a8acba864a33e587b2f6d95a742abb6f3906cad9c30fde667a07373380ae267e1c5cf7f381fe7086c5af1fc99f4016f992cee291ec10795fdfd02dacdf23547b10409f472a7aba6d16a04f41b35eca8fdce9a689aa25f96dbc39574062dd28c934d614f3bc4f2fc516890c3558bd42bc78158b1395c6fb1a8fa138a0c421ffe2eaabfd7bafc24d0955b7cb2708121be9e4a104b22769eb00daa666407b986642b220bd518daa9eb444bb009949c3b2a2a33aa7f7f785359b1dc754a1e1b6d8731bd2d917ce3e91507401310e8668a3614430f9575ebf8763d98288479ee3e30e9840d530fa14d1586438f0f956677ac048225d52e56f4cd58e4675941bd6025fa7e9363f89b3bb5685b0b4dc2246852a1f9d586d241af27abca1a139e0d3b2f0eb4a80860591cbb569170139829c6f294af08f28834914bdd5129f8b7683715ca2c328c6f6459f0f7eca4a93ffcfa5284aca45f79b8020397817c51b555bca1d8f01a354c43581cf4749057de256a3b1af99216cd546a158163fc65bf5d3299e008494c207e8307f4311c659e2d8074fe9dbb5fab91314a42fe8f7efe0601c6897aa618129e4178a02c311aa69ba3c7d7a006813bf6bf6a835b1ee29adb91f07c5018e34b2af939a06cb5bf1ff73afa4e0b5ac6a70b7c3deb8092daba614bde619289f3f3aa15109bf9929c30caafd60ae5a1741458d18a2377d1ae8622955adf46e09231a6fcc639dcaef9029a6923b436c2d4ac66241bd248c5a627a5d82a9e7605062da71623231cf31ebcf2d0a9f307a52e97bcdeb6a1f9540ac5727d174729df971034cbee01c1475287574c2f705f32cafde26824389468218712eae98268588f02d683f17ad494df8b53457fd24651ef0561282d3e20e834960c8968f63a57342a14a6f2375bc10bef6d235fc2c4eae7d7c088985ca6bc8b1ae8c15c4ca7c5d0b1769cbae061b61fdc2e4e98e8e2e5f89c87ef2f392dcc6e3a2ff98c2bb788a9be84cd111ceb5b62791c2ff2eba72a6b7c3fc5b87ebd00251e689bc13c7389077ac7a2be9303981eefc12c34741ca1889e6f71fcd25e40f7ef1b0ec327e2b0340dc6818beeb0559965a5ae282a4733962b9f5dc3de19742ed5d0ba5a930ce6779e09d33ed5fb7a1d044e1e94b632c6df4a57f0d549f58410f710074e28fa1117551901a0efeaeff0f346e241bfe543a9242092f9bcfb58e67e625d668fb31a5d5b7d7179e5889c5a5b1564f7ee66933de181abf9df32d8f7914f246b703fea91d8bd8d915eda69a564410a7debbf9ce3a803a39b59a2ed8d595ec42672a768fbf362bcaf03ea3f1735543e9d5df848e2a12ce3a8d3537deefe17a55c3ef27be2d5f3659d7cbf04faf7d6671dec177e84f587d1e7f44e7163a7022fd87c280d90a6f8f2217061a294d14decc64126260fcc99d622659ab2347ca8cb61d352054b8dfaca0488d9ff2eec433760042c27cc4dec5b1fcd3f27a9a690dfbeeb774a5cb280550d6b2e050f703fafb3dd326b03a107c6a7d546b70a4d42d5b86d9fc60b3e12fb06c1689a8184cabc86723fd9fcef72808225b64c9e9847131701d2609f593824b53490a8ca506bc6a36e5b59fe60b6f2786497cdaeb02603a34e1900622a7b38e46aac1633fdaa35d0778ed3521c5a83513af12182bd670b23fd7b8e9ada629f590bc7cc04b30f72d635e12f414ae69ad451cd3262e6939561b501f3909076c1ddc0e6b2859923e37d525b551113e2a1cb4e32e796533108231fb2158c753d07373113b0fed86df18c73052e0a9ed7fffcdc2928652dc9cc32e396ddd5b141d7310555aeb6977504cd42e5a076144d1c2fa1b9dd199ce34956a8b533b56b0a9a91e4b594f6ffc485066706949b9cca602e45eaeef8c708e75616180072cc1eb92078394a0638e1da008a6df3c35fd833c071c4444bd7bf0efcd6c62a55fb079aa666ebb82e69546d835224a33484fefdaccd50c559f391260e90c79ba6204da7eb59d3c7b6bba6a55767328e3634c526bb00955a6c44059755eb2439ad657647b6f7f85de5555ee943729f9a1397b316b5b39beccaf2a3c99990e4eeb2f00ce1d0e86263045f04a3101b73b111d45235628d6b61bc24f324a2270fa1fce997df02d519c25b03213a8609b7ba7a142aec89370ca38a027e113757ae3ad4799da81266266032673c166de5739d947ec1a1f45886987cb5cbf622c8c7a082c8a8a4c8429027d1b3dd9f8d56ad42a83ba1bd6999e22ada65623c292365bd4efd3f3bee125ffe7f108c3dae056f91fd7252a9b1a22740eb39cc4c15108d787f40ebd54a7d9bcc86a6d2589799c072dd4c5acc941a5dc1f85a908cad3649b95fbb32daa62c4d7b2c9c365811bba9cd8ef1438dd9a98d9749f03666bb3ea06834939fb2c8c67df2ba1a41a5e413308a598895564af8bea92622474105cf9b6e47f3b7c578f43119774a79a7d84860918639d68eadaff8dfd7184a85559240b1e001047c805e73d8ad5268c6b4033eca5d2e909ccb764321a3fbc799712f991a47e50d3da7ab4a17a25a966b42ebd41d268c4aea6cf3a857d4f346e7214dae91c3c85a71b484bfbea08b8afc48a92973287e8ddf57d12e69b02750d62f9485ff9dd274817090d8b5ed0ccce38fe445b2ac2ae0e356b6de3f80c06cce61ae284a1e2ae2d3a3789fe4d106e486df4531c4fab8cb5e2f4bbec28be5233781409f5c8bf92cd114e31c3496a15b4f0074f48f5a51d6b8ab37d9d81bbffc7a55f5f01b2f66dbe28d7a568b8204b7a5b91896fd141d8a5a9222346a76767ffda6722571519a766dd4e555d3df5883efd3d920f56f436eaaacb6d961e53134293b62464538bc85dcb3cb21f2f3c444971761995eb4eb0b11c198cfa3b018a466de6b597e2df59096efd4c3d2077184044a5509222c3fe7f898731e1a1f54561d55356806786d200353a942596287ca9e376078281c648cc5faedcfac7a0dd2b469697ac4614bbc8ba6f2a6714e2d9fcda528ef58cf8582e2afaee843086aa195e2af98a030b8ed96af56f701118b8af95b55759a8cc84fb57f5f74c612944a2688aec9822cdb3a8c377e3ef0f4ca138a229013d69a557da832a8781de0b355d1230f15529edd2bd5061283283f12c2e8c281d0f4425594218f30fe30baee4bfd7a7984f8cee548d9e4b9cc903a8a207b03cfb4dcccf01a8a5fa00de7e86db31156951f5d041c1a01991b23102d5bb4acad22c777804d994a6a9fae2ab15915777f0bed6788a928b3ece18f905fac06e1872412aba59598c978d6e8e15fdaf996bd82f6ffa1b5fa58a7b319f819a69f835a7b9c6185efa06f51edc3f43817e8d6d8a3430e996819599038c730a37106fbeecf6d82668438a4bc8b474b85396a9f9715db7ab6e90c1c7019a3214534c3b00bc98ef4917ce8d083587dce8d670559c380c72d41615b0b0efeb5b147185f09791006a14efe385b6cfe6c669aca436c248e0d0d81f78f8d348d04c9f0446170ff4ddd6fe532b1ad40221cf9f28aab4182e5b704c0d42f09a871985289e0514c67281c489d41da2ec66f9670decec53ea52dccf9441fc3e9335079325a16b8047748ca13bf533b47c88ae1b4a6be1acc550f55d35701d4949dd3b053ab0c1d02f856efb8938f5d5e0c1e05ac928331545932597c3fa2e972aea1439bc4ea08adb1f9941e611ec7dd5cd10b3fea45923c7a40e0db44298aeb2e633df4ecd9016d6cdabf2f7128012a7e4bfa57f52bc6ed80def3d8b0bf3f67e4c0a3456d0191aaefa17bd20ad494af3a35dadbfc5e54d033b6985bc98b914e99617f768d893fcc03f5cdef764a07d25a37b4b24706c44c5a70d94cd9b6070815edd86e9599943b707ebf6ffbb3e2fda4f88fc61e499fc8bfb4be9326672afd200db717cd5b1760fee55838e237ae97e22173fec9526cae28284e19f9c78096826923587cf550a175d2a03373fdf208da5968428f47b3655e7791c499fe933902a82419eb8fc7679ceca048f52e36b75549777aba51fd5529478f7d5033eb4f6a72c2426352051b3cdc5f60b2f1030e1a99a78e9097d0e65041512d648e0e41807106bc2a6591231d49e561f06fdf74f3f001675a42b7809d0cdeba1e3886750d4af76d88f1f3e907dc3b35f8cf5551a6f68beb5f79378bd6503e0ec659db55d8a89e3ec71eb4d3c23d68c2123aea0efc544f03e965da6fc4b77a0fa4189348ab3101172e135b4b151374f285d82811bdb255983e2d27942fe799a7ff9e38b54c8d2ae104f970b8ca0768ab9bd096c3b1b7a390a7fba663df88a3bd211351068465218292f77b82a7c04bd79a4bbc8c9f0c43d56cf4e0429b43a138509e67a21b61ece42036051075e7255dcb7023d551593d4dd5425c9a2cc09a02d56701f1d92895edf5de95ccfb23ff25766852048d4597e22a0da2d45ba69602f897a75b866324875b16b41d031de017e35ad1831c785b7bb27c3b56ee9d9d200056e248e9b99f999806e96b537cd01b596f29b8c69b91ffb6b8ae8aad4fb84437cb3820cbd3100bf5d7bc1fb5e9d71922cfe10d52563f587ee983d76261ee56e31f334bf4587ec5bab1b59fee0cfef984a181e88a506f6d523543a4d37e483e4d795b312cf1f2ae2fbb5d54c98c4ca3c80e92b3343228267ac7755bc94ccce4bd02373b3b4673b09c1e3ba60d12caff353d9bd519a3736b3dc5a1630c7384317ae24fcfe8fe09b24801d8fe81457ef6155624b6014c5724e5585024649c780bce402b57fcc2bc9d7c8dbac2efce726eae83b5beb4d4dc39b8a70806996faf5cff4454394039955780ea6b5c1d54ae504aead755f9e50a92ffdb54717293310a561851df790c9bc99c3f7332d38038852fb311e39924ea18011bb9cdb9b106fe1be1aaaf72e2d7db18b458aedbfa1af4a507ecd05d3b83b10890c1823470372196cae813f2644f763b73a436fc695c84f60eef840ad2dd465a61f3f8ac79ca5a0ff89272c03a0d804ea1de34fd75041f68efa2686b9001c040b7d797e873ca90cd963033a50b19e399698f0fa7c71cac45d38de2471ef60502baf6c8b2073cad19ca4ac0697f798564f13e2fc207ab12d3e1395b6523c4ffe891d7f1d0dd2a983bbc6980d43f3750f76173fc16ddba3b5b422d3c8e4874943a65037c0b9c9b397b9614dbadf35b2a99e2b7de6aef500e241df1eb8a350dae3f5d00cf2bec9878207dd439be43ebfd949c903d87e87573789b0ed22191973440a25854f877283d749b3002cdd5f1b02eb68981366e31529de40b571b051b0e855b92713ae25370bd18b09ea354742bb05827123d298d93dc1f70e43f389f2456b13790b8d821f9441cdc7608667d5662acf45864c3901f7d74c6e056d32e5efbccce183bff9bc051ce3df0c4b313198bd777bc75e143dcc80c93b3287dcda4bbd3df718bffc8ae2c565a759ee43e5c740438a4362eacb3050f62c47ddf86dee0eff3027081b1a91cddbb6e5fa106076659c079714fd58c7ba5b87d1da060f4b0479135b22d5c9a6a8be941cf917402a7fe96a4ecefc65073f41f45d06964ce7404417118aad36a5f876b58b65d8f357f1c428b70b486e535271e845de29854734d8b1f6ba11eff41fac919dcad608838db4d98c4461c3509643ea38db2066ff74bf8a573b94343580b8cee0927ede419623e32b24e932737d305082882b60546250f6cf89b4c1deee33b3e0476402f69da9dc00074f0a2069efd1cf6f9aeffa90458dcc2ee407449a95e7096406153716af3ac775f3d90c0eaae47bec0f84668105c5d985b2832b2867eee872e5636793bc65ddfb882d8abe29ff24a7e9cc1cb70a258448a0b3e71a2221f9fe729c2c875a13b0026c5620fab588360dca0571a4db3338c22f180ce24d26ba514e2dda83f09aea152101636706164c9820ef29cce155839cce3e01134163a635c87715fc1881e8ce36adc675743fb4d17ed799a1c522d132fe74681fc77f49f6822653624a5f38782dc9ce98885b2b34446d35c5ef21ce1f4089a67a17c0122dfbaa17590e9955bd76c3e052caff0c5b020ea2abd7b8c6dc24bc40b4eaecab46a580d642cda6dd08924aa036b491c490383a54c6177e57d42baacb52993b51cb103914b2102e1ad410cc82b6cdca008e778ec09716d8eda1b5c3bad5ab52b245bc3157196e95abca62b81c458efe3ca0205a7ab16e6f14cf639573a0a9c959211a0811fb41541c36189bb18560b4d56fc35be787769759a7b5ae9a661ce592f7aa3bd9da310fc8b192e5f6d8fb746767e0d1ab9bd7e828e51c6da3786d5e1c33fd3b1338a62f5dc7723560c2b7b36f03097a1b50fad80ee21851036a2399316073946299191927d236f863d51df858db9da3cb6967fd78392a075ebdc80d9ef7bdb62c6e2273d38c41ad948296c9b15c2ded402797bf0154d1ef09d5d341a1842c3ee53a2ac5dd3022d3674dca9e150f2ac4fe2e12a316cf90768954cdcbd5705f9d318fca6591787af840a921fbd06f24b979ef612034f3f64c71cd2012c756c83f75d169f9bccf8a8ad52725498fe69c3927edfbdcf87c73cf478172ace3a1e6b446a181e8aba00209894a5d2db01001d2acac5b3fbdd3897d7f142df0b6dc4b9a1862bac8ea845202d185321ecd75f6046c9cf7af1163b7d58d17ca94bd80573f5fb77d00f606faf5425a2c735482d94cdc4269c17fd77f75f5eec0ef6418aa32a0f231275a827d6f505bd4e1c1c12c1a903f1a1d759950cd4e2bb987471fb50270b57fa2949159cf8feca3e0b1ab8f0c1ce590f98f13cc59fa310cf2e30ff83d4373d11910be0094559f21d690bc429fd6d8670c18e1528a8ea143a8a453e4319dafade16b53025c55e5c759eb7e17245279f4bbcf8c740d8feee61f17a6198de3db9e92011aff95e5431cd12e6b5d58146cd29f0f7fb121529c7cccc95108a0ba9a0bb18e5038cf98598ae2d60e85999103791c55359a848b1c704815ff2228864d7db64fad4e67f37ba9f57ec230675ce060ba3d388095adf15907aa0b0673db687d16e18cb10d6b3be28f8540ee5fec7611ff241313d31fbdaf81d20f16213e9d8269d068f11e841cdd1785e50fd1a4571561a63fb4db74d3dc5d4a65e19f044f161588ec9f19b280f233fd39157b28e5d3783018f40d21c677e06fc9f96be0efb0a097621b9d9b2aba5b57a7bf9afeb4e4b96e5941e6cb280ab1ae85be163901daa17873e708925cae0421db4edf7a46c18b9d6b3ef6c55afd47a333a00c91280c8ea89c91e93ca935a4f82e43b7401de28559b94bcba4e1c828da5e6fdd6db4becea4469cbdee92f9d4272b4e90c4acd03d3fdde8c3ee5f03cbb0504df7435a79e7f80c78054cac53185b5cb01a9c6602f99c43a68e061538b6c1d3faf8a66bc6711048b45dcb47e9c7e13d38a32bec03611b84f57880c6cf608b33c74ffb7b1ce08995c205ef182689754718d8f7a14a0a2a0c6611e2c6405f790a636bd70af5ccc07e21bc3c7f81c373f4f11a84285f3b346468e8a0a6240a27c23feabd9dd97c516c63df17f0841c59e151e655e3bb9ae7078e7b4ee8f306f3e5bd3b13a64095b8db08ed160dc5eab376bbcae155d79fae70373841f135cc7a0f8bdb7da6b3af73647174bb499fb50d2f7f46bb114bcff73913be3e7154c13689fc4a5021bb1ffd734df48c16aa11c3964cd8478870925dbc745b78cbd89b95ffaf163fa9cf6dd391feeaed175d677335850e1b3dfe8d4e94f9bea57349a234db14bda0a1591f724ae4d672ae225c9877b846aa943e17463d1456290a207b7fa6cdaf07aae0bb7608c035914da137afe777108a4dc7d6d12f449097f2f59df2dd2a78e9191 +MD = 4915a5b5c893cd4ef6a7b3aefbeb997c00c240c5b40091759d9d52944a89e419 + +Len = 48824 +Msg = 51d87c952fe3b233d4b43cd953236635f17336c48828f2442918e26d05c557dc8eeaed50d9540c1847f3b5cc64317b3c0f82cfa6dc3d812cb6aa8484c95cf2f29fc14f7388f7123b40e16162cc7b1ddba56a1ea518d8c045ed7e9e7347029d14cb842d680474cb8506a6ca0452a854fafa53ac2a06a0b57815bdb8a14860622a5b5c0c96157240dce3697818c06028815764ff9b6c3e6aae788e5b76931e481c977076658399772a1d52f208dc4da25804c5a1611359e7cd5c1a0d5af2e357d2c7e9f23d15927a55fd8bc03a6f15c967499f1ae5c39a32be0a8959b52b57983433ee098694055146cb396a184060a6976e1af08e43a8556aca02c4ef0723122b23a841a8c99902e6cf87780819d73fceba5dadc35d2d58b8e4add8704eefce9dde3e250b79f7971c519b7374c0219ef57691d8eed7ce418f9fb31ca1c862d274add93a186fc717cf989de3c3fee7cbf5ebddfa767a351ad9443c18e83c252896d8a10a3572b08be9edb64e5d9bd1ccb45e6a9ac30e0aeb7d1b6f55ae74e0d8eda7bd1ccb495afa51980d3eaa5f86ab1c1a5f403d5bf4ba636c755a5c363ae85f6156f843bd6e6cefe1cc3a1212af701466e5754c289c91737f76af584bdb62d6509327039694eaab0f18cbfd7bf321838924bf583faa77959b99dd0c7b6c4d39ba9d30759c737a6d6c1c77d363fbc853cc43a9c966c575b10a066bde8d95b270e89b9b0096b4271d3efdc9fc926f6c6b776bb807669591af12e6e1384bfd986222b6f10b4efef6a3cee646e0d0f616b3d2c3767a07c3d577fc61c8817b4d07f9b016b8008afaf1e764fd78e7e538cd1324746a8a10f749f1109ea721e62c081cd9e27b4613501fd2486ae67a98de9973b7a51ca04bd8f40695c606805443a1b3e643bf45b1a7884ac15618ffb29082bbd17f15227e0fde9cd5006d068d3adca71f600e652ba7353818e997e0fcf591d3bb2adc7a72440f9c1675651b58b8c1decc62ef0e4bf92d85964aea833bb6cda3bdcdf90eef1e90efa14c75277e6557413570eba8d745781780a299523a7a3f141e90f548bd45687bbeae2692c8eaa6b8a2b3899b98321fd821182db3c0eaed0c289c578fa3629f2ab4c3ffc4fbefb62c5a52514f566929afc0d52d1094aee1742119a74a6a1d3ee3cdb28825e21b9083a676cb2dd9929e83a40021d07f6d2335522f6ee3da1d4b8d4fa4491e44173ba7ce47809be854873e16c2915b49cfb935030432c1bb0bd11283c0cb15e88abf7e1aecf7024d57ebc75e430619ba7ead5e7cc37e4cd58ed559b12f9573971d25f2d18eb8cbce44d206c4aa0872991f07970492d7ecf04f614a21182fa1197874ea3d544c5c34c344e390201dceb05dcdc7e499c709d3f57ccd1aa422053642b44da4673a1f467b4a4609cccf95c5dd09d86502d50b47292fcae6fbf509b624ed054fee0a7ace15eb1778d7a52fa14ac2b1cdf28a5a14938129cb44301460c528f9861245d79238303e256827040c4a013a64936c5e02da7ad212a85c8dfdce6d1191fb729d5c8d1fa358a8de7cce85cd5b740d0580d8a722ae024e00de55e6c235b7d01934f2bcc32f59be5100aea52efc4388dd2660a182a3e55ea46e30b6314d41bac2041c6c21c86fd309f6754f2c051a2b7aba6071a19a0102d0a556e5c14177e0f675a4454357e40f8cc8eb2dd05e411e66a2a1be877ca0600deb8f1c7af9a16b3cef51f130c5fe9964dcd8e721f0008a2948eb313d2f08a0e2a8a203655e07821ddaea15f0f8069a189c042527a19f9749120672ca9d81ebd84458418956f14e209e385c8cda4339316f378eeb5a656c506ab92836ac55697627797fefcaa6f6cda3036b0b52ff9f36bc38ca74049c32c6b7cdfb8a46ca4144bacd649da36fa3ac5112ed754780f3afedd082cb858a1031600b95cd522a9cca631b999dc7947d46112f88d2a3105e2569c75ef6c7772f1bcf389b07b8bba1918b2dc5f7205dab224920e42b4df5081f98e505ffb0adb60b6b1fb84060c679209bc991b1951156c863aeaa872d771825e2f120ed2a73ce8a9c87928132924bfff9b8a5d50dfaa5c1c5a182ef2be0b7bfafb556c91c109f1fca37d1d1166940b70fc1a86a725ec194d9c1136a2f760c7667f7509a6dcd50525df81e39f49180cf44ae4379ab86d1c905d60600218340d17280b56807f20aabbd9221c0b45332cfff461d09a0bafee9b3a702b9e94d7a5938182e3cd1c7f4b353cd816e3ef77e3faa50df223942707b4afdb09e6f1de3942286631db39337f18571e64b7ac58da8ac9530cc5e654e0732a0b8b69c3aa30c9694fb1395a0faedbc45fa60500587926dddb910f76cc015d258c10a56eee149fd089f265f346630611262b4a9fe948355ef21f5ec9ff02e94ed73a0867fc5d1c0abf65ff998a341daa0c94f6bf9da05cc951184254603d9df2678821536782e4545a9c54c14d8a891b7d53a803e849f3a9531c48aa9249f1ccc75b8e95b22e8f69e5f603eef2deeec1f2e7cce15b8da07b828bd04107907b1a71548ec36ea853a7dc139b873cb9a559f7d1d3fc69e3c9bc69f7779c22a99077ffd3c040ef98f78ac7657a3e6da3433016a26ba98604f5e873dfbd30860dd861cd89b1b2d778e1af127c3e5918145ee0b9c9e26d5239bb9c3ab50f82a435c96464c6e18d98b0887157c8368bce954ee86bc8d6dc312a71241907ed270fa9da0c401bce35b5d8727e01ca112af3ae99a3971fc76aa52fbd2ca958e4721ae280a5fa18d64fb16926219b024cdb19b8c5cee64f129d40e1f62266287418786863edfd1ea8300deb2a08adf15800b34c69b6b3d776e886c9c281d9e71a7e8ab3ea20c3bd928b4dc6d49f9527b13062e1ec079a3932d0d94f88e76f154618d44d8a0ad87653b5d394ec52fb15e6de8b11d31e03e4f4eacafbefbfb053956be7add9f8c5d93a4441cda7cf4a3c778f9e4495768b7b2b9ade573d7727f2770c375d4076f636d4bb1ae9bd70fd0bc1b83f02d9ad9b6c457585da189a40a2796e35c453f1f44fa18eb17183c4ae1483eccfd4e63fae28e0ef440cf7b594c40b06757b8b164a642f43c7ed9146b7e70c91d32361894e417c7cbb5861459ed7aa79790b6c405324ec5ea0b67c83b4e3ea5beb76c236f63686b23e54dbc6b96dd61bb2cc6e0cc8f25753ee849be82fab9b8f7b578ea530887e045f8acdb59ef72c71b56716d7f65cfea803a07600829e9eb1054e3d7087b7e1079152bd9e99f40c1ff343ed3e75e550ef82c2a159484d72750bb3350556355e10764531fe44f4f38aeeeb57bcc20bec7eee33944f0b38a520113f3bf0469123d360eab1311a6a81271ad5ecbf65312ffa98abc57e25d0a556983a88bdb34bf0b4f3bbc1e3a4d52399099c22c2ca05a9d72473bb5332a6019d034dc1ca36d63339a120ca925eb559353d9680738af9d8991423fc6abc49385804d16da23bb079c5fbc251a9b29ba0a0196d8c2e027e3ab4ea54ff211d0ab80c0f7df2d25c7b230e6618fda64af8885e4f79bc7edb034ebf095f4a12ff9b1f4d75abe7d6f386cd67627d0524824c7eb4225387c26f49931c13cb53bcbe4acc80e9d3b32cbb73d76593972e90f3080266447374b5598196507c21a28ae3ca4e4ade9deb4ffec2ef9d5bdfd06807cba1d9286219b4047bd6f0b4fabd0a0a7a230fc65306bd37e464533dcf71365b07db8140a7dd3b0a78c371509f19c68cdac94423ab8c011168e43bbbdea778474d1df31fad35d6d608ea56d1b73f2d058cdf8c98ffe197f5b0cdbb4895d9aa56ebf7a327eaca03f1bcba25aabb93b9eed0a44d78d8bdfe7f6caf66867d9e492494e715fc08e04ee804c1425e24ce09b366d60b55be67b0f8ed07a1d80e5bd12ab87ac00e504f1413618e517e7b3478fdbfd34ab239753bfcc24511cfb098dec3d70145d1893cf02e637fb76e376da4284c2a8000a27d1c158d061ad01cdbce9a6148fbe7fc506f737b2408afd1e007bd8c5a5fe3a1d5cdcd9dc9417babab2d18e78066a4221fee9d2909a9d5e3220047f0d11ebdb015bd7f74ed0a44d57d76c9fa662aa8a2f209f5ed9f3f52d3aa4a322a2d610145c387b5b30ff9ae32c94817fa589c67f78d2e3849532db93bff321698ddab50eb55a90ad890842a3c24fdad67d650648837d7beccd3f97b8487545fbd50722f19429de9462d3e4b6a0713d4d37ddb10ed88a303d890271c35d92d98182439ee4810d2cb9c248c8434f63738bd9d811f8005fca1fcf63b1dc86b2a3a29d78720f056e43c4b14f3573558c44396e406c2f8266113ca94a9e2d4c3d6d072d8de79ba7b4ec5c38d0756e3c5377fffbfc0bdae606cd391e9f81db369bfd573a6a43b0f047ed295db3ce5b8b22d6848af43622b5a6c5c1364aa211cd341b3bcdf7ce7567900ed52ae08962cb6027712210352f76b0c27afa3349f59771915bec1cd21394f51905a73fedad8374336dcc384f28b18b8c0c7142beaf1eb8265ea2c195b2ffdfd463dbb944613bc8c2218f54cd35ef9feb20a4604868ea72a1edf4ce607831b70997ce34d4a97cc39c35734cf780b654a75e997331488108cbafec2b7b90b1e37e498899e7abcccd88508008152e9112876d5a64bf766de06c4d91c02e2007cdfc2012d1c38fb64e4f1abf706f6a054154f6ef1c3b1b36644c6eeb75c151bcdb4ac473c3b07ebfaeb93d376d4d5a9c49d6a05e82ed5e62fb32bb03337b4a577732deb356f8a071568e5ef0e5f626dd92d514b17d1c687b0ce7dbe0e0a63460087a16db74e21c53ac9628f3c2b3f7508419f9f0f71160090134778a6688365ff6eb13f104b51aed19994047eaccf57e8869f821d7156f9241df370aab6979dda84d7e00edbac4c8065e51f4478947ee048fb94e056ebda034b0c267999324628868fe0d1939406bd9ae0103bf3116286251e37e686471ba4271c1a9174d6074fd033c226f79b65efc51f87b3c0e89b508781ebaea41b469d3e8dbd90cde559d6fe8df46d7c44f2ad50fdf64a566c91c60cc1409724bad334fdeb9fe628f2a6446dd908239603256ceb05ec7e282fde5d0146a73e9cc85a31e1c032000a80851ebabf7dd7d96896a4dfb1cabdaaa4e99c21acb00350a633ea8676047ce7116edc41abb5f8cae79efbcb9c2187726e4bf9da4ddb93f4e708e568a787cb4317dbf3af185104cf02c6c82b2f716a03de6dfc97b48a5efdfd31a8e4bf4c69a326450b6fafcf9a6a4ca6907ae64ae3d387c82ae67b5cc2e07b56ab9747c2e68baf4269efbc92182117a6eb375b1e7375fd02fb42fcc37e20c3e0740cbb7bb061254cb5bbd9390c9806504eece85ca74fa076e439d34edf437957889194e755c82aec75608034f6139b3b22083885ddd514cc7c37796f64dd0e345fe25e864535127a0f6a3c16534848b01b15a63aa5aacc5c39c86995bd31f4ff706b92e91d1c9e9e0a25874da29a91578091cbeb9d4529ae93692e623706b0215089bc803bf301c0ec4edc4b727ef7b9f90914090318cf4c1f96324560bfe24276e945dc206cfe7b3c32b5b0318a0e2feaf8092395ba2fbd44ec0fcfd8c1edcb59f6c95d78cee735607dadec6e302741eccb25cbc38dcd6a99b72161fda14524803eb1a493bd5e87ff8c2f808705e598651f0451fb281aec9494219c4df28af6702d99120facb6db7feaa4fd2a7fbb9bea400f56cb0dbaabac1f5aef482a11b9b04fda565b0192a84815c8b2b7023bb4f2faa15ab1930f3066a567cb8abc9bd6b7120fc1f47084871e99e551cb31c87c058b84de2d7c9b034ab2c2c1742e6be5fb10a3e56a6deef039e3955ac582f469989f0441bd1ee0acdee3e651a304145ff2c831412b5e346c408f532e347a42063291ca35defe729589a55d0c85b227bd44b53265c5c61763b8f9994c968c33ca4a00211b119fb345d17391429acd0886574411b3b839ea6f09cef2567a3d3c3e7556b371d37735365ccb2da450b95933a10179bb812e3ff6c95bd8ac4e11edcb1b21ebcac3197b0f72388ca2561b7c4dc889b50daf178a936e4cc6ee808eab08c1ee54a63efaf709b83828bd0947f44d24296dfa909a5cbd6efe477dc028067ff0186864c5a03bed9546ac64e8e353ba4a8cff32d40b28ed520cc4da7b5282893c4ca1a6e58dbc03aff0622a83521d1db2110326f7fe619bade4e99510b2a1bcecd79aed1d27e9e45ea1f48e5738b2cfe141f4476af8b950d903003e3ebcd693b855be97eb13581837e7cdf0d2fba7795ebc5d24ab6e72957a03b32643c5a3a5f5437747cdb48917a23e7902951f7d8290dca84f47e42fe1e7537cfdce819b5c4a3d7f6d33afff5b44226033fc08a7741e2f6017bede63bed77ec8154d65203f1d801188cb5a1d6b94102df5a66bb7d65d211f2e7ed1a09490e22f1d2ee4d4b6e5d7e82ae33785b0f8a43cd7f2ad2121d45e2fe41652590bca2a0c7611851b6c49816db419ecaad4083b174b8f4165df2a332ce903c50f7cd9b2faa063ca86c7af390cc4edde0f3d496137d0cacd0876b54c909dc5ce36705619742cb42989418d4b6fcdbd80256512a338f843b48b711c06f582dac2607ea5ca038b7126a5726a54e14f37778fe41a6d7532687c6166a50ec638c14600006f51134d29566dc2dcd21bb9ba289122b74c870fc7992cc006a07d1007cdb79e192b4dd25b1d34cb5b4f79add417eba98fbce8f0ef9f3005b78894b92ccdd9b019d4fdcb74ffbce44c29858c03c9f200fa3b05862f033db01e03b7849ecaf8df07cabd89158248b645fcb9e4c7b346918d43872024498847c0ce2012dc599783699907ab9b297aa9cf359148ae685c03bf62c86f6df6b235462498d463de284595ac66a39479c5474e60b618166da4b0171553b44a7f3e20f4c37c59d3dd4d8e329144f19fd7ab175a0a72e3ae17a32f1ae7b3af6867ae73730735039aeb59d5c6d43d25fbe7be8268af522bb40ae9e9413662b1463465a5378c6d82276cefa4a8d1b9a1571e522100abfe60e6cbeb77009ddb4a425a064ec8bf802617f671837f3645042fe0186b989cb213b4cf2a40ff9aa80b0b6d02d89d1d178fdafc81faa06e69bef4c173dab70e27c48c7918ef94993353ffd1edcb2b219e2fef038362c2e692423456f6e6e25cc9f3fc7e59cb463617c5ae2d299f09697e76d29018544d3b492e6d0504288125131273334f7caaddcfc084d338ec9e51430514269357a5d908e40d504e1839d39db09f2c7c6c391cb5e51268ae0c7075865b222b96e5635c5c03a3dd172e7304b44eceee6322575f7493d551fba72652b2d98b3385761c11bcfdbee001d3a325014d80ed9637ac32966d5c33a42516555300cdc3019226a5a642cd1d80c060b11f5d63ae78049e2275d205623a0ec709d171585e7db2198492633cea364d222538dec5a59b11b3ab9d526f721fdcbefcc8abc96a6c6e7b4b1befacea75027e1e184255777207733a976f08f7e817748aa3008f8b502fb245ad389b72ef68caf8283861789f2e535bee98504805377e5ffb201915cb6e5520c0ee6737e7e89f4fd321983d752eda8bfd6ee40709c532c93b7af4ae30b2ea48f171be8df11a6191b38e583a96618f475e43129968394872ee81b0c91285d84aa9530009bd76c84a43ef2004656ed81a8bc58a93931c15d97ed4cbdb035fa5927302ba1f9f7629e60eb49e0f74bf5b81f066aa7a2cd6215976d4a46865c8e8bcc9116b5409911cf16e8f10d046db6ffa469700a1a80ff19f6111e905cc3a0826260f823b9e7ff8090dcf26db5e3babffd8d71bce77221d07c80cf827992b8a5b044dad3ac06b617947055ea51d68961f31b75a451ca4fa2f062650327f25e5e80e6c3ad6021befeeb4c216b226da94b4ebb85aaa2b112f71c61e9fdac0b1b1598eebb991f5e9d9b5d175ed76ed1a4e7d614a7b6204ef137c623625751047630c103cb7f2fe5dd58b17914187e29029c53cfe5b015ca74cab750d8f95e05f818c3cdf947d9df059cb11c4c159a9e49d18c934780c74c2319b79153cb1b38273566f64fd965749ece23a50eb60a5803f04a09d40f7ffd878a8e8edcb4cfc38eef7223d51d1bcb2f58d0bf60e3157eb76055d994438404278603ee7a9fc4ceb2afaefe92fc430d40a180104c840438ee8975aa8f05208a8b76df59367140821ddbe32f8e5c24615a11fa40d9811fb02fd37224ce3e99b73cc0ea7917138c0656ddd95ed12707f0041008f80fc2ae0b02a613f058d438b2c1ceecf3256df083e51b5832644334e2c60670e0f730f974ef6a21b635b145a4a206ad726867b32153ff28534e9af35e285bfb9f98b148117f87651d6ebb08b468d2f49ce9ea1f0726ef106a97128c8cb37771defb2ee20a3965a4ce0adcc80b9a998b19afdc7a5ee955da1f48954695eec39a4426901088a66ca97111fbcfd0c0c23892c2270d4d21984c19670a6ba161a53e7a23bd1ab34c053bad8cff632c63b7c4af2bb120fd58202f01ff5841d795862427fa9f48b2b596212a82d2cd470adff717f164fb9615554a7e1569116011cf15f4b11de1ae69892491fb5b55483da298731c26e53fe19f6739b32422645de6d988521e2fceee440c8aff8242588468716ab5e1282043664cd9e0 +MD = 099332a09450c58f4e5a2d172c00cbc490997954f6d74c7a6f50462e58eda142 + +Len = 49616 +Msg = f35acbf8a106e87dc1dc058ba92b4686c20974e2393c4f2ef75b2652d430a6150761f0e2e14feecbbc3fe6ce2eb84f57822be40768daf8b4ebf209b1a4fa974f2d7136a3d9b3e38aa21d94eb6371133c487c0b4882f6632f3fa9ccaed9d696a04dd4c8c5f0fa6fc35dbf366ab220373cfc42112def593ba7dbc898d1db8a4b1150d0ccd08deb3b7dd46df5d4828b666086c61e3e17cb2625a79794a312de5da91cae6b4a1a50efc0ef6ff9b03a7b46afce5058046313ccaf8b5de9abe79c75719ab6ccbdfeef3394960c698644b87f31bc28ea0639fbd7506f64be71c08a3a6fb22f18b0a190ad02b18d6ddf070abaee3995facc0249ec0d3bf23c7e067255ad4d6376ac6bfd0811283a2f41eb399fef2be0b1df27c6b5f0d7508a59221a6d3351980f38c4fdeacae35bd437580cd53b7c5236c60e3ada002bc6d28a7a4a2b07a8170adc1457fc33cb388746b64d05da1231b209216d03451f9b399a78cc373338289020c3d4e557c6196ef86dc2d6d5d7c54c31c726d7c89c19e910836738bfeb12c98d393c4d3bbd45b1d4e534f133b1582dc5672ffe9088860a7402e2d6b1a71fdcaade57dee999057962876afdfc8a307c4d6b4e21a5cd2bc34f5f06ba135695f2ff1bec3e6840a1ee2bb92ea338499662523a4ce81051503d28019b8cecdfbd321556c515c09c6137b6e4468bf0d6d2075b3cf0fad8fe3da0875069f3452adfc573f8a80cfa948c7d8b717b5c2c192c92f0d9040005ba3913f4b43798251f43d2a26a5eca1c0f6ce733c695bef2faec2b99794ea1a06f8dbef895ce2394a630822813aff831f7479e354d5c5b4c6159fcdf849886b00482ca1a5bf73b9ba7f0fd8f5a623e3e3366c9196d98d84136bc2a4962a8563d615e5fe36e7888400ac96a5ea941434dab1191688d10e0d9615de0607b46ba506e69a4da3719b48db704f11e6712b06547901ea9178d191dca8444aa383c5aef13edc2871ca4648a96e8bc56fb9e2c8fef2a976472d72b1459797eb1ff51dd253830e17286df423e90bff08ecfad60d28b28242206b6bfc7f783b7fd394cecf7c57b2724de94f6b18bcfb84f4a07f43603d2ef693bf27d3c8aec17144ff62e6fa216bf248a8928eb70623a1fd4738fc33f701dc479520c7dfbfac580a7174c94b749cffaf4877ff528be9e89d5bad982274ad9b8289f159233f6eac9ab77ed6eec5c802f8255a3d69a2b0d12b5a47c7aa4a849cfb0a13f811928ad75c2ddba062a96f94a9ebd3d96adf3af44ddf91db39cd195907920335494d7370e53125a63574163d3af85f53e4b5daba6b3816736f90ee683ebe498138e4caf1cc8df768d5da3e5521d7672d45bb029c0a004ff0aa1a764316fb417c4eed03e25880ab68d2204a8504f585d63c435531b0d4990377ee436216b5a58719ca90cb3fb5bc16a90aed355aff35df070344f3e6019c0c6760c85db499c02217f1f404d899c402c8ee88fe7a40e1b8546f445b1033c37be736978e86f43bddd817c037c9a93dadc03f9049096733e292ebf5efd5c7a9e275c4138cf471733ac89067cc696093881d92a59d7ede86fe510dbc1a9d59b9d0a19ddec1837df09968007d4b6e5c70223f7c3b744123656c0d491983dd466db6e9185bd4ca965eaa34cc532d1ef92dfca450c45606b259ac263290842c3a4015bae81d3f2046f7cdcd689bfa11d35777fab4c2cb2617ce4f3a3eb3b3f091db6d957185592b0c66748069aa2add576734911cd93c35d05db5c7d1f59bc0e99a3f174936bb5153254efc542047d801f7b315fd5a319c5862804d90c89413ae070aaee3a3fe29b7aebdaf9c70d9a87f6363e7dad833e02c872f3a0fbf457f5b9c40dab55f6a1aa68d3108b72e48b50c44d78539d5dba7d936232b834c285a7ee4720942cbb7aaac2b599648bb2d8455067e7caec56139daea0c80bff1a54b845a2ed9107b4f60351387e6a5a9e0acd642d94c8e498d3c9e3d3bd80a4244b90877d7c8b2d099c1ddd05c68726d1a84fc6478636cb4b816bf8a31afe6a0af2977c7fd368e7e3f4602ec379a239733a353f5cc5fdea96a6eab6bae66f9bf1d136eb51fc127d6a87350b1ba0a3d9ab48e697145a0389a2c9aee5bd29ba7d0371d39d9bff6f37c5dc023db542714fa15bca96194c32f097721f4d57ebc7596859d85b04e2695c1d7c308d3867f6e37efa490410a371669c2aa5b52e357e764811abeb34afe73699ed28c04d1719dc6aaecba8a468a734d977a8e7ea0ec71eca22b615d46ed00b62b951a19b5bc2848cfeb84b7ba2bea377e490a9347f8a9716135fa38c250e249f6712f7cb3ad9210d7278b53d599df99ef6c5c4b48faf2a556c105b03de88c97980d58984bd47fc149273ae93952c7e7537af0011461e1fafb63007e2a02642188b01206febf25dcae712fe255f537c252eb624f3acbfbe4b77276dd074d0d6a310fe8433ccc38b57f8bb6c9abefa39d56343fa04ca7a4e523a5c5676606ece4298337d7968a2d0e24dd7c29abb09feae5fbc48e9a73819eb8439897b6fe8721faa0ad3e9c87872936fcfc6cf5d6813d8a98bd74d4bdf653fdf25d089a6260a5fceea4d2af32bba93e50941deac00c07ac9166fd6bf597b76d288f1450f11de2d8c3bb5e5f1a5f00a37effa72b0b74dbd48c7d72c0a8ca3b7e6cbb559b18f36af6d66d1c1cbcc5c20eee8bb31727601c8ad05d9f83462252aa154e46d9489590df8d16a67888a46fb915b4ac3f92626c480373be246c248f88e8c4628c1e89070b6e5477e30c6f5c6a8b270d14dad02d84ac7c6914793554932dba2333f9223002d0a32afcc68b2a7bc54f50377f5dd2d911c42ae3fbf944417aac23516715ae4e7a9f1a26257c5c654a9a1007ee401eae09e77e0372d4d12c45f6cd74f6c7c456c284dfefd7d764cf8193c716a64b538bcb52dd035c5c8dac16469c1f16ad34a42f10e6ca2c10d61300c8dfd445c403fafc92b26446f4cc5971f819a0455a51cf36afc935b0bd12c85ea5d4d13b3eb2640423a89691323fbcdfa7b0b91143be207fdde1c2f430bd67e1b7408df53fe16f88822a1ae9993a3eb5b21bb9e8fddc504117eae27520386a4079ad7b023c1365d03ab171ae9e5e679ac395336aed3ed740da2f2491e01657d1797628f0b7baff91c9c93b5ec61eb00548c7a5e596481de5b138f9f904d9b93b1325083f376a85439bfbc88884edb08bbe2d92078d9a9cb62992e31902e4f6e3f344a95c3f84af4c4da3b9aa6f6dd1749031783f37a8fc28afb770507eeaa942766f7cc634abc6323b6b7f42f9f1ab766b6dd8fb28f584b3b031125dbd3d38fd38d0030bcb42729c01bd99c0992b96f7ac4d34d9d602feedd77a599f626f2e7a9740cc9b47db3cc01d1499c1e17e3c7edf6a0c49d353a34d820da673e2e312213e2c4a034ef87d6509faefc5475c0482712edfd9855a1a495c659999d35b6ca779ecfbc2550cccf144eb1c295f6777991e061fe77098dc77a31ca37fa81a9663f71d7256de9a93db4a6f9f8c8e031e3912aa5d123992623f028d3473c5b337fd22381e4f60247aa9a6f2fa5d57c150c90b6607e834d934260751fd34d0b7c9c987c7700a6e3ce9d2d71fad2a3124c7ef74d3b0b7e6cfdac30de54e214d9ab45f944618167d3659fd57403861ceafdc12cb7de82fe408be7ca2c1b7d790de8035d42e670201c3437fa3ff1c9274b515b99bcf0eaea0f667d94271bab64ee5d5c2c3fafd4b90464ed049b6da3ac7f70d6a4241a4c2922b5f6f896fd74bdc52fdace0364b519d41d495c501f1d94cc81bab7b603afa5c1a1d85c4268e06cda8905ac56ac1b2ad386d46826ae3ec57bac8d393b531b453452ad2af405f85a7591642c002f0fd34bc81591e5c30f28d31bd9927cb499f1c2effcc9727cc36dde6f7fb7c89698fc820a943f540596a51ef325293ecc2f91b4a04ea18474498e5c4cdeb67789bf8dc175dadb3c1ddd25a25ffa684c43e80e528f2a1af49593a639500a8fd5af8b6f50316ecb65b2ec8ea985dfb66dc2c94ee4e1189c8988a89bbba28aacaab104887765d879976dc9ca798d5c7b68f1dc3ab2c1a08f0af591572b6be673be3632c17e3aa14b9af67ebf5aa0f920067728ba04554b5b408354c0d1d2a74ed9e71e03acd750ab35f4135796e63f0b0ffdb5b721c5a068f3dbfbc0f40054a4c26ccf344b646d00320f8e787486b5a54b2a8c17523a281feaa58d3edd1c75dc426c4d3da10b81b257f0f90c3ba8e45681a7b4c4dfdc69e6ef881321d54f92602190a107f7f213296d3f5bfa347652877b1b35a410d2ed26c82c945322c13497277fd2799441abcc3ba3bd2aa715899eff2f18a12c453c483e3a18bb0c99e2e91be1e87ac221d1058bc52684dbb01105d68b64a27d5cdcb2195aa841dd0025bec760ecf4c7ba0e3c234d9ef01a6d7022c8d6218e494057ce21334acddb1d847ef1a2e5ceec33e9d7cce22e56aa74305f9cb8574fd91835031e6e084750198791624fdbf079b4eb3f4e2cdc9ed4eed8231cdb0fcc750dfcb8d7b2ea97821bb660e210d642b6679adc71d5b2b0e003f1d50ee451ed6547365715a8f7a6ba4c9a51398ddfabea728116fd82b87416da02df3b7e239af0ed6a47a0f8375a3fd3bacd2e6dfd165ffd2556b9ddf5d3be9c93a86b4f8fbb5f2721f04049b29c5bd99e3d8a5839685b3110026e8e71b31f702d9865ff9c38fa1fe2babd4371555486cf0715f89a8a2735c984e43d34fe827f5717f33752f909fa350dde8f7b6b7301d49597f228640b32d842e391479a2ff1998ddb9fbae7d4e3a2516cd5d8c80073354dd8f1ebde4e50c6a63332b1716eed7b62e6dedbe8a300b2ee30bc915243037b999f9bece13ab619169bc97a69879b86fedc9dbee5bd79ec4cefedadf383da2de0b6983253158d5cfce5feab6cc12441ca858369c76b77d9d3741034920a1fd389e391c51e28fc14bfd7784a6166b0342ca939e674f522ffec86cc2f161efbf6feef2eae28bb2ccbc73ae0622fbc66e88d0f663dd6a3a1e8fdecc9a56908961da6a216f45b1645087cd5ddf8c00c6fe45680b374d4bc1d1c706fb09e721017d0e9c3f29f9d806e5446721816fb9df3b0edc4c795558abd21abd72922197da7972f1c69b8d843cf368dd738c3c8b919d5bca34ca74353aa8118ecdb3a46996dfbe0732445f3a59136b9cde6080fa609da29e5e7b385600bc41d756fede1aa92836491ca51d6efdcdc321ccaecb8adec479e5142c003f90970243c8c44d2f93db8243e04e16968d7b1608c8b77ac16eaa582b005d6a566cc0f9407db4501ce972086417aff945aab3cace5d2b1d1292a7b3dcad8fd53ee7b28d59f04fa5771c845f364d3b23f0b7f057cee46a3102ed5513767613ef5da3e444fccae6bba29f7afd46db80352c47c9539709054526c12b0d74f4ba073723fea6a55819f133f4ce48f25d0f8b5cdca734c3457cc7d2c0a1e87493c2cb5fea3a28e04279e4bfbf06e8e54c49c506e90271bff44147ab6e425af1fdce9a3c695f5239f457048a50bd537c23bf40beff73a109cff333252c94db597d5df26123b6991ef861ef485c49ff436de0acf97263392d12f318c48e11d027acc162429bd8840bc8fae36e344562c7a55e582b0459a08687c176fdf531dfe8f6c97865444da98ce0b2bf506b3814654478d0e807ef8dc2790ecc56048d511a05a6935dbf8e602eca09a1b3738a9ac8d5c0b5950f7d475d710b87513e7cea473419418060034e4e0f6058fbefb55c5ed3d664d67d8b63b40a7836740598f1dd2c721161c844ca770b67339e3250df93b92a6d10f4a269629fb56832fc5a0e68394171967aeb7b46588ed01eede5ab04102d4cc8e75adee5bb438b128548a654e517e082da4fc7286137acf264dc252c536f6282d80d2ab9f7b32d9722ed404fda65ecab78ea3489d00228bd49bcf4790d617cc34931e35bbf84be3567a062a563ac0494d9534a070f6ed1d40ef09f86a893ca0ebd818f577d28bb71c61a93e23b6ab6c37e138e1c99ee46db272f7cb1af76f8c997448519db1fa3d0c0a44aa2ac1281bbc9937726ea00e64724c21296ac9b778889236b2f33fa15e6d9d5fd534043e3e25e5b7bd27a374e8c7a40f7b20a71d4cfe586b8143218700894482270827f5bebaee4229be4f1ce2fba24a270538a7f044ee6e245302b40ca625360870d15581c3dc5f1ef94e103b54705997e1255f4ca27dc705eb88316b0d6802e032aa677088d79704a24558d91b33c4317c154d495f2dff8ad55b050306366f17175b3273510670447fdffaa69716145f9db178cdc5259d1dd82438bed8b70415e78cbe736591744459c20089123ed0880ea1e8c11a8e2925bb8bd383cd1249436ae414560da12b6df7967169d2d68013958ca50ea78f2b0a4737dd392b70c607670c3b06915e1c27230456302004ac6afb1bb89ab4512c3344d15eca3bf804caa8ac3b6939efcfdba3b3b6c544f0ddf407f5284f89fcb40a7a005f1d45d38af5f36b1d694c7cccef404d991086c49a1983c2fd146db749f6b06de61a9128e0ee11f1e8ed142f9ccdc27708f92ea56c41352c3fd0aaaa755fb0c0fea966208f1fcae7a4dcd72ec6dbf1db096883bddad4e7d9f76d86febfad40a0acb20ee31eeee5f55a20dea1d2839521a745ce346c3a5f712dd24adbaf4929b5fa1dcf9815c52cc211a071b1482c75f1e7785732aadc669de7e73d68ce9932a8efd2f267fd0b65f7d144d885b13d5af1d3e966de1d20c3052f94a9cea306252193babe795c28593ba2f45a4795200ccc728143604c6f40500cc1d434b7f9c9c7efbb7df6bd84d0378d98401c7a3c5328cc2636e1bf32a326875607c390d8e5430abe7506a58792939918d32eeaf9f7aeeac18689ffcfb531a63b8aa3b80c423cedacf0cf9e9966f6cf5c58a56cbfbf05d33b7c7f93b03e167359a5fbb7fea85b9e6b347c2f221508354d1aa989f674d58f7a60ec033b0680f696a0f31315de4827e58933e18a6872d6d16060c706dec827687af7d8dad41536dbc2b556b8aeaa8f00391c3a3924dcb7d171f5b158c584a2ec11c999f4717d3b1155660751de2adfa68b61c49714ede236968ecc52f1b108ed6e89cef0a6610d1e9f31af47376f1ebec627070dff4e5ee61754a25d2af86255da6000383969b5ece93cd5028122543033998a01aca733cb3c6ebae23701b70b9b76b633f23c3a617aaf01ea84ea8ae41adcd5dce49f6acc4d049c47e1730ff7f9f278499b83a4679cb3bc670770c7c1c31b70076fde09d09140d1f6f0f672013efccee2fae5fbe595708ce1d45b13b1757ce4e8150d1bc15148e0552c34e911b0be4166d90b48c2ae0dfcc0b154769c7927b7e99ed4a586d54451ce5cd27b0f995d583dfe9c93e82fb2916c6703f96818457471d1dab107655dadc74a7b31e33f049cd03141e23e6089d54dbe0fa3fe97fea0e777c8462c49ba7aaabcd51175ebd993853ca23fac88b74fcb7d217d464179c5b558456dddc88543de7b8826ade404c7c5e666b11af167874f6ee08d285ddf6a423cfa2d022be38dcb4f3d757474aec0f9f6364170e1bf063f57f5dd8d325718f6eb8e8e83bbfee2d9ff9c08b0e1ff048735b9f596a1e753050107755b090a56392caa9848bdfec970554ce64b741e1dd96b98d7757908f60734bf5b7c2a20ac73c9f654397c0bcbf817f6172b753493555f7aeff3b04a78afb7c599d6ddc0a20c8819c93f3f4b6fd90e41a43a2c68ec65db0843f990d4606454c037536a12c16c32bcff404de93d7b02d6945ee0e3b270a5eade705fcf368dd1583bda183f90fc8f86ff25ef0bbd47bb5cef81dbcc6cde86c7c53e66628394f736af52316f98226620d0d76dda78a3007cbd8a634ca3164647024dedb6cde08e029aa5fbc95f4780317a3d0f7df5f89ade0761c18bde82ad139b833cf29fd95e6305babf766fd4a662063e1d1cbcaf5229d5ee3db0a58983d39bca9a3f7ee72e02f779c49e502f9e5b7bc4dee1562eee052d191ee480938f2e070951c5f472c88778ca546788c230c3e1b69bf24adf361c19caae4ef8089acde928a7ab88e2f2999095b5fca1f4264341fb9c772029f413a0e9331794516c58480ee51ac39f75e048c23083232c4782a27d29996173ee95ca5ef666ddd4cd762da552392b111906a7390d2594d45a290c238a7f9427ed48a0113f645afa85cf9fd438314aa1a5b0b6e394097e5328df87d5065341acb9d429ea5638932b5b0ca683dd29a8b5e3887ca60d586811794d1c7be63af06a1ae26ed2820c10d019d54a9a8a4acbb79936016bbf39db76141ad2fe735e2ac9d81a75af0c055a4f85d1940287bc3d0d90624d1bf3d55eeac3efb244f2e77631ba23486b3c4df81268a98ba11ca6862190b3699cf15379d54c74c236aefd5d0a8aa6efec5a0c727f8905386091302c5961d15cd801dcb49f78500cbceec666bc0e4a701cae695100b28ba1272d84b91fca652eb56b9898b00f2c98bff96d19af0fb8d5e1808d1bfca9e6d0df3ac7b5da9417e71d76aeac70d9af6c251818fe4b5497262517a05bdb37bccd6efe24a6f1878e90f76b4778489e8292d893f09ef9a79069cfbcc9960424b69ebec2c116ce6b73312b928a859e254c12beb21c801fce4ba8c7b73056e1387b4db6cdc68cd8086dd0a033a05adb37b6f2c1bdc42c27926feaf550fe22d93bb4e23d695c91772625774096b080689c683cc8fb122b77bba43841cf5b8354f408633ddc +MD = 892c9210b31ed9b387c75d41922378235fe9681e48a8367428cf77d09636bfe4 + +Len = 50408 +Msg = 4edfa1e99865265892e2a91e9324540e362ab7c5ad2bbdd558dbde2396e9978ddccc17d004bf3ca9e70abd3b2d84a9b1645610245001ffbf82a3b2212c76060234992d1a8713a53eb0156bcda97f6c4af1a63c4ade540a913511d478f8a1d7927fce4a8eca684b5f16891a9bae1d852104a2a3ff002dc59398aeaaf0a174f282e5f4d5f675c6155441f0316ee567dc7ec6d3ad0b5e93180cd4019d50d0f73f1d8d9238183035eb6458d11a0ef66459a95fc0c3359f8eeb46109216622c31a7aaa030dabca1beb5d983b53c43881de5e9f6f24b466c26268775ea7bec5e2a1070455623ac73685bf9ec23ffd543986688b3efaf076c64b2182b9035b70dea64b8a58d7baf4c3cc60db8a3cb8bd1dfc6ccbf41553d484f7541590cad8be27a89cae75c4a8cd540dc5c12bd082ed7faebfe426fa7b3a7f0584928e74a2f85e169ee354cf80cb57e863020fa1e8600efbf6563020b30324d437abfa8736d9d27ea6cb4e4edf794feadcf0ae1765bf1c8284b4b81eb7b91701f1a47d7920bd255f68b8eac92151cc73782f9fb7675558d10f62274ae5d6b61d272e7fd0ed2ce717495eb2c4d2df3e00e9115ce879cd2445eaf0f64bc9e682646cac8a14f8a36864bd0f2ed8709c154184485e4129710f7fabe3ad87d0631c9616a114bbdfbb5996585cc76a96f2f283fe372c57d2fb8adcb6bcc58595c6e520d99eb83c0ecf1b4a9fba04f1928e46669b503f7312c726fbbfeed6cb86ac6c731a07ed2c02792deff7c970141fc8916800361049756e544b1bec49d02f6e232b5c7f1bf257241204f4ed91388b2c63e6b15b3741674ba3496f57a729fc96a9a80566cd35796a68181ba8d0d551442e8123322cd1550994750e93674f7ab05087c951994be5b68097e08dc7812e8a61b5da5d699feb02886c8e2212972645b8390cc1e8cc2882fc02c80edda26f799e034b2f65f385d12f8e62a631b79bb1513a442a343cce7a5af746ae9bef909c43e7fa4aaa82b1ffda5930823d27279dbc0a140d140423e70dd3e0df7a9f3e6cf3d26c11cfb3fbd9296b5c389d5c76654936d0ecf0b8e56385273b240257c5561e5115271e0dc0178d235a4bfacde4a2993f1f4c62c16f7a617f9a1ebb9fc1f223f299ed4df6ab15761fcf3eadf21ed02c9153ade2b44e86133ba2221eedb0cbc5254ef6b815196d94cf1f835f6f617853bc2273e917ff312ae9d7d0a4a81e4d4267b8b5e4df978a49afbfac67ac78f5df3de040fe62ede619189f9cd57566f15c487bbd6cccb1f60530443c5f3fb1e30f9521978b0bb72f5e368df939dc37524335ec7fb842d52b680f3195be7fa8ca75307aea2798d7777ac217783a32ebdac7beaf7f4ff88db4d28b0c5b0e02ca1690be40bb5c80cb58ef49c09c6f1001053a51193eac54580cf53228eeb65f9241f29d078d826a0f4e3c4c1dd830fa236c1b8bde2045cca0ae10933be34ffc9df70b3b53c331ab1fb1e23783be3867af79fbcd52d6b4e81402d53ca9cb534049805b37aa0ef2ca793e61aa96a0edcf21b95ba41bc4623d0ec5b38cf6f938f1218853007ec34e4ea84e3b03cb32b9c71694ab8e9d7be6121d413c12b80f9955b279933446829cbe296beed195e624b5eaa67c1b5c6fb92dbc1fcf5c4170dd0488ce9c3195bf768f8901fd928b3dd7323a693da8dd0243d667cbedc837bf7c73f111ce86e0fc543923cad7d52f9c19b2725770d593f61eb2aca027e50f6e002a97cdaaa2bcabce51a6011e07d7a394cd2efbb610159dc238f7670e414cef00aef96cd1238d504d5f6c5f30a927c6a0d8ccb06df6d67ba6dfd46af15b54c4e6677279b277d78c49b9033f9047a487f66bd83008d85b02651dc0468191db8239eabf7ecf2e2fa25c04e72ced51b269edfcddd5275327e4658947642f9325a963bf2cd697950a54ecb9a4918855f5df00125a2a49f5a1742098d65e6bcde79d0c4b373b9c6adbf6744db81801d2d379c532b9a9d11e6c443ed2f98fb6a085ff8c158af85e1e3919ab478e2ada46cfaca5e488ce6d5bfcd718ae3d92a0c985237ba484a75d0d8630da2db34482206efa4a8e44127f3cb7af36b0fee1ba8759bb538eb0c309d767de8966b3ff8a0e25e4fbb68820771f413f2151da07549898299c2a9bc5f50a326541890cb6624e88ff61f3a152e5921df951273b7e0f4bb4e0ce1ea24a9ef49a779b1b29f39b900c9bf5ac4c245b33a2705e87bfb06b3f349351c160ab7844f487ee839841a641256d2f66d53f485263369229b348c8d19b93dfb953730169d518b468e42b12f067c587b9c8ee2d9cf4bea453d291d8b16e74b06cf73bdae1b0aca5217a1a521c484796fbb3db8b61cb7b0dbc8a35fb3d01b88c62d850653b1bb61943d699f4235b65c5c31261d25f5bee26ca46afa0f309d1bc21537b20d47ab78946861469b3f592ac96612ba2c42aaa87e384697a71eb42d82f04f6ae4c52338db01524333cbb70a3fc2c837d6ebc12b9beeffde8183a9e68f2796d5e1136bc8f06e043d13c2162545ad123b28d94c934a2d5c76a745c46d7020d49c0b19cb515b193fdd410abfa3638fb66e2cf29208145e2608214e4debad45d1666bc08bfba568cbcbc78dfaab21d07d79e91fddb17fe7253bf5848c87cffd54dc07eef2ed55c56faead310e6508d82f04674973b6153121b82dd1c96a5daf27a6e98c4950f397f42ef9e045fa9f0f94b6af569d405ea4e226d11c4bbbdfc5106b1983d84b074623f4b581e5926ede7338c830a377e1a82f2ee74d5ba3dea6d8d39db9e7071a3ac2a8e8fc3754feab9631babdcd8226a6d278794b414ae1ba47887f18beacb3da99f29b398369d6dfc34a8ee76389b50491ab8e0045d77069242fc787a5615b907278d51f11f97fe3c32b4b94acb6172c356f2f53af73131b39737bede34e99c413e59e98282b7f1e5e7bf9aef12fd384866e632cc64553384cf9a534c19cf5dc45dffe8c112760f75be3a11c7a1c71764b4d3273d376b728266c4c438773f741d00efee11516a9d8840a49c68fa679694eb7a4101e2dc8538f7279027dfa285b7c1ca5807a20e3289f99fc9478f574c55552c2ecef930c224eb33359ea5a0f9211aefc51886c954e7537bf6e7c30eaf129c693ed8ed00dfb2dd9823018ba354f566f093c892347b4ce8d9c3ce57f615792bc1ffc420b5347f2896e6f4d4320f81404d62ac36c82c172429ae6f90b635e57dc6f02556c646f666d00fed21d5af713186b017f70ccdd28ffc15401fc776e42cd8ae50d1ccad9512d3fc5ef6f6bb21b51ceab0556b070b96c1a6f447a26ef1938788fb3430def7b7134adeb61d993f457090e9d47b3e2ee30ac1d0cacf649a5c442e68e08b318abe0e59c101d2e0065d324148f6b5f9c8df480479fba71e5ae1aefd4e89446bbab225c7ba4c8f163386d25a422e93b045e5f9cd646cd1f29fce18740070f4e4241e0a133f08dab2333cc16a5a0eacf832b1a0ab0490d877e56c2131134a0511436c2baaa3c92e3a81f99fe014f95a482baccd2bff0a1314d85659a31b76fd999516fb1cad0ff215ac37be69f78134167d41efae983b1a5fc52712487d8a56d395c908e7af3fdeea1e91bd567628b2e9b41b88c1849676cf5828fbafbdf6a965c1dcc57a1eeb4d0e55720d3415726f487c9418f338be90d9ee066627513e5da6a5ecc1629094b518ed633e9159d0c1a9234620c22915f1061339f26ddbe3fc4cbe537d2f98ceaf9042efc1dcb7d64282349c20acda3f2fea542e10e1b269fd9e77ab694f9bfbb4faf2722794b3f56a7a4d10a911c09c95dd1d6d52118932ea327e7f16311eae3dbf8894e057d2b0c1e7c95e1aaf70a0eb84fb72267ba4f14a9f1f38f4729548d25451b27c84a89ab15135af05b46f0e69486ad71e8eaa17873ae6539482946dfb6ffa656ca98a05e14d1ebdeaef1017b7bde806aad91d0828ac706966ff90801158ff2821351b94ba41e0f54abe086f5f4bff7b4bd95255c75a29e4fc382e21cca5bc754ac5b1c9a4c628dfa59fbc67c8891dcf820e0e82bbca9f50b4caa1c585ecded749ca0117495052e77c02b0b36bdbcf5dddf58611ae843d273135afddc584c2b89eb06e001066fba74e8569b4e1ea80b0c01e7d74e80d7fe2e1f7bced1403f4b3ba177d0682708f998da65bfea30bee52c8e7494f20ccf42e579f3d85e9f101334c7da2ad28039b28c9d41bf337d644de68fe6de2c1492644027ac60acfb264c19651637669a68aff739d0e3508c0309e20b27fe2421882ce6338cb1e3dfe9be9581153c4dfcffb682b7fc7369e504e2c70a1e3c04ba196480a47d122ad0c1304e25be84ae2e6490d51eacb6a811cda03e94b3dff168add2b58366caa958166bec58f956b2b901059776c8f53397c80beeb2ce3115b2ac402ed72e2289fe50381823aef980243cdc70c7377832ff5cea806b577898207e7493a8bf62f24ad75d7a8cc5b642f77fdf0a1ae387ced2f0079bc836fda23a8b368bff00d20bc514a2b99e27d51dbb31d40a76b36a2e96ee28e8cf540859893c50bee3d9b9fdf66dd17d5eba9e3bf7b9841be48f687cd6bd160e8a97e0e894f788d55c3261ef664bb070d66758c43381b7e36b5fcbdd17c599b601e8cf75e325a87872f3100a9b1709380d174de0f7f0340a130bd97be36e78883b301b29ff2f764e2e050f761f37a27d0bb0c3b5cc6ec539e47cdb7ec1207d2b40550d2b6f7bbb00974ea65a7a1543e8d91b036e39633018e798180e3a436e481841eda4bb733e35b5b71cde3217b6207e415531c7373e4e2348da51d53f1486ccda03bb6c7ec9969128bb2cd1a7c2ce02090026fc53b784a07567721a7c378e620a9699090322cb328ac969df2c2e9a6e5a4e77631d63616705099791639f07e5b7f0651a6c127ba1c38fc0e20ec32bc91e854981fe0a8e7fe205e9c35a139a5acb57482820614ee4bd555764b4492a1b3ceec7e05f73b2f0f2a68f37ca5defcb2d146aba87d7ee055e6356ec88883e6c9cd11607a66776c31f33b1751c43ad3fc56ff258093c000b9000e603f14710c52676617e3dae82ff4ff37906b68e7dbf7baf088a0e572fff3a752f2f5750482dc224cece8a107dac6c2f0d7102060652371ed6d9fef120e8440b58fb22698dad5825857ef7550fd35d30953e6672f100e10281cc41d27ece950789ecbb5b874cd0bfaf16ea44e17b0a3b3af64c9be5d161a434ec3fc2efba17b4ec8c88eddf12123b741ecda69bac5b9b23201b4a8bce9f4c15bf61891bb2b159a662f2e93d0706e1fb1f0743e56e38967a443b458bfe84424ccf0deeacc14b3de2f66215483495f86da100e365ca897664ea14548c6af6cd02a4acbb47eccea9c6d13e3ba9a0a5caf12a204ec6c736810b9b0e413618de365fc4a7b6963d20e57a7aef2108531f9db044cf4bae6e270097de91d3321225c68ab964a841bb2a392779de900b56ecbad27675a4c6c6453a303c05d12860b1c2ac0b4d58f06ed4edf557724f5db0f2697e487a1fb5d77679fc3cd204bf086c75ec40c9904a5f07480b9b1228a4691bf1dc43468523a9a30326666034a0143d2673e23f16f795a99392cd28e1898a4e9c15ee419dba45b522d4421728738b0b1c687919b3a018a317b1761b43b31a73b051d2d4311fb2921b2f5960aadf76c0a0f48bbe2fedf1de19911d5316cb217176b7756507fdf824395e32a1808cdc43fa3fa29652852741e4594a382278a8323670615ee9fa2051c38955437323c57c72704509e411c2b3bf3285322e63b59d38a31e259dbe300300da4baf4b4c3a5350b0fd7fac38cb1ef14457a90433539ac3793224ebf2332139779b4cd0ae41b0db26506073a34969c3b647056a918711201a27c19d3e2e93b788cd81caf2e57b5cfbc81401f9447c7db1deae29255bea98ad856679492b41bf366ab800bf2b9c1b56ed031ee3c53f675ca20c0996d60d715bd27a49bc31139ca8f9583bbe1dfb606046969209d29ac8e01d87d18d0063f34b9865d33e49f1940802c94397c28173405b3324127675ea64d7884bb1e2d268a65e8ee0787ac3f17b0d72e0f122149b1fb4449ea7b6b8131157753dab83431693ad5f3712cc71f92ba3bdda74469d2225da2fc66f9c4b8c0f25b87022ec9f463b0c3fa2b347e3f5404b11f8c935054e79545e65132f169d85c9b7acbf23cc41c50396e703f4012ce28ed60398f7326844aa37423a77018d9bcbdcb82a32b44c5a1acdcfacdab4e837f375c488950eb7ad6524278d7df5a67bb48e5e0a203db222da4a225301e26f6a02540042168085dd0c8bdab348d82e4a0c346407f651b944ca76a8a372740ba143dc826e826f18fc27d62455e0946e33593893cabbd7abe973b92841345301043f7511b3e2c5ba313e6ccd1b4e0fae5c2501b3fb77b7ce385b7c6cd84f659cbd7d8874b93d69b0a4dab59dac993336edf7f78c4233d96b5a0c253a0ecc9423f1857b74299b43457e82195cb1c9e64d0f5882e545f625c9760e1e5b8bb2c7ddcbe0b8d9ab043bc0e7bf00d1d1e7123ce9cf0a88afc88332b5e7cd97f809e6137015a56be68139680618d2c5b5fa9e4ca5e4f73b26b1dbec3f219cb5fddad80e0bacacf1831925870415f700050a72c2681fb1c752ba15403b43f27f412c8713c22e343529d5e763083ed84a682076e95d09a0f4ddea1976d1d636bb6d07da6dbd22a4fd81bb67443b1cdb6b86429208a9292d896c4acfd62b61d2322873b9622510661233d68e74c536692a087bae667707be50aae01fa86e6c2dac1b790c3c2280e13ce62b423acd14eb5096d0b24ced2cbd0f3cb6f233c580aff1ee20bb41dbfb7d4242c46cdd7b3fc7a5d74b8602331f908fcdd42ec05624c0c84871afba7908a2eef1a8f5a6f83e67f174f312d07268a1980340bd9749e0c8fad172ceee2330b80698dfc3dd6c9931fc14d03ffed29056f286048500c73c2f50322d012702fa2753e272c0caffd98f8e60ebf3d37a1e1964ff287043f8c15d8f13aa31ab3eee589d7468d2b4d785e86e004b1798939a51b716b265a703f6bb821bf044c4fe94b1acf9c9e3e51f25a3659bf89496448d65b372ac4b751063aff0f30724b76a759b47179ddaa3fd422a3bd9fb5012b67ebf20bc1d0cf64991a2a043f7b7cfac187f3876ed9f379963e4b8645b355710f5c6c69b0e8f6fd407fd5bb2c8e753e905c345bfc01ae91c1039a3e1202aac7b7ae26db886bc2bd94d26e9e8839a8a4cc5d1379a1f3300aed191c6fb5316581f967bdcba8d7b7181ec87128e30babdfadf0fd5ae11d2c6762f54e758fbe3a423d0f9dc4a2bb488f36b869e4cd52e351edbe7e9a49edf819db1eacfa02078d8b0b1c53510694fb958528d54c97cde37de42c03923ce427a4ae0bc467ccabd3cedc045afb34e344cd82a03fdae2cb20e629b018fd4aae3f9a642301494029a170385e211dce34c899a7a5061a2ee9201d36e14b15f39aa45d961af008fcff7b319880425322f7db7c7cadb484ec96657594460676b8480a80ac5a2d3153abc56585214b15e3ab02086a30e7a59c516591ba34d7ba0914b6862f46f55d04ad149e86a787e070cce0a008b50be6cea8a4f421643b3a86af5ce0878804e65071ed4f0589a54d6aebdbe5d0c0ade2f41ab81f522aad92817642224d93b867f798c3e98a5e1fb73276784c4aea2a049d15f365d51eab3cb9e82ace09d0ac5c4a901d10ad8b43a857fb2a35df881cd63a28fb7a22a6b0a360935b3624e54d2dc9e66d36b797ddab4be886551720f2d24bd244deb3596a514606781d27380767060a48de610a3a4aaedd010c8a4b4873529043e60fbd14e0ba9ff5c5995f87928f8a147a0268e5d0c1472ede917d9a43dee19d22b0385cbc3eee58d1f3b23a3ab6d4749c442a5d085395544dd52e44de515495371d51be5e636015c4bed69bba2c77dda78ed52c4bb66635dccdd3f48d5a57e075dfaf964198a3b100534328bb40f2a43e4aefd0056a2837fdd41505db4a69f3814f9891006f17bf37796e6d98a4c38cd320d0c4dfff69df4380581562b21942cc15a32b15573a94bc69ded6ecb868ebd8792e8735e689a0206b139fae11c452b8aa65b0eae18ad611dd1b01220c5145e0ec6f93a1a0360f26fcedf107fa29a7f97646ef0b7e96f7da2b9958c3112b2f7ec30a76adbccd80c9ae3dd61acb87b6f111cd21f1bedd7e77ddd05a6a57450cf4c595bca4bcdea97b0789ab51168d0422057ef63802ccee6d7c5692625f4d62f54c77b23100d7fddd8157ed355b98141eb9b2d848faf3ac3d8fa27d558992c5f2c04713dd2947d243b43f18521b476b49b73f449ef7d05c7a703a97be76b3ba7fd98a3e03a6bceb500895b911d5f97e35764ac7b489e15376d6855e07972e94fef097bd4ef9958d8507024c0f0c4cd1548f8bde2441b545e51b295cbb7b71f9e29e15fe09a2605d4537fb4da43ebfe9396b68f4689fba8837c68d0064841c6ddd4a7b9cee31bbbf3303e74a7bdda13a668268a6fbf46fbed15126d57d618c45517e4f064717f647b1035caef079bf594e6d117258f0534e54538d6870645034b1b1f6c6bed5ae7b51aed1f79c8368aa53a3e9c2fa13f3bb33463725e82cf690a07e095aafeb42ce977eddc0ea9b1bc2389f583569cfcf89f091aa9a3f2bee0d904b0d3eb4d961b5f4ebd677652167254fe7f3262284453f1ede6e320fd1b4fff3a158ef482079c5ec8e62a796a6d9482be63131bee2034f0074e889b4ced9dc5d0992e8e4410972f0def8bde9abc09f3f4298c48969783e580da00dd873cb473efc41b813bb8f41b4460f46f890dbbefc65a07b3c8b228187f12b4ae55107b51be1dbd9510079b6896c2ccf2df6791c05c7deb222b780bd12d7f0ad55e72daa6662c7d926b +MD = 569cde2d4311abaa60118ddb5e5d4768a986394817626e9f24d79c3446123bbf + +Len = 51200 +Msg = f60b4d76d90c920f1b5c966147b24875d4f9f43299f55d2387280b7a96f7e65500090441aef0c0fcef0b0c8070aa083c6974d3a51406a0ed63dd0d12f276b11b3bb3f49f098124862fb8c51379432823e3803faf09e9af98dff527a4a239f0c30ed3c698d208e734412c69254ac2d0afaae5e05960e7b0ac613700378e88ccd6e32f2234f1cd308f8e2fa1bbcb722a6a266b5faa0146ccaf536c41d39eab6ddb2191ae7c4e18281e7e8915dfe49a5bdbbfd964abd44e2a2b1c5c9180bae9fa5a2fbf1577d131f6697a016c987d818e8adef99662c249f3a724cf9947ca8b9cdc7781fd2d635fc4f8e8604eef7e70e900e9919ed9b17d4eacd38d012fb6d97ae860a10fa7eaecb754316e65eacfaf94c44a6a23188a3364c1915d7041661bbd0652e5f2ec4f1ef904bef356945886b85e674cce2536b35c6ec6098e84c2998cbeb5174e047b3eb290f6b7ccf2023d7d57aaff470a9c455f3bda570400b39b1099f2fdcdf85593098140816d0eb31b0a367a4a35cfa33195b135107abd1f68701e6f6015cfc467275d061be1ef546988833ef6417a35be25573ffc97c4f049d5d69507ce91b20034afaf4bd19dce701ec760cb1215393638b561e2041c0c866747ccbca14706a757fca3dae5210775f588479151a796dff554018b69cd5d674dfb7d4535f8a8a4b8ce4990c482e9c334515b10a539360285bb89c06ce0c933b07a0e6b34ac7f3f80ac0b3417c85ba104a70410b7d200e60f725f47b85c3a34b74ae9f6436b75c0d71f509085fb44568d14aa582e7adcd5bc02ede8f34997b08bf574ae0c3e716ee4ae816ab7248e2bf61fb5b1b339b215b4f2996dc6afc8f05303195b372c5c93d0e1048b544b206868518de3ee186aef1ecacd9cd897b43c38fa3fc46c3e1c75c24042bb0576e2550a309ab6861eedab2213f03fd20845dc62644db2527b9a5ce354a3c172afbc39054645f224542191ea546a1c5b0b6217f8c8aded91ebbe925ba4906742fd965e801bf45e6fc0efe99b15a2fc1ca7f33623afc63dd296715e51b86f731e69580aa43510c3106c3ffa60df02a6bce4e1810aa0006abd859907ed19a9aeadf9ea86991e02e9ae60fa0d5f38f1e4e4ca1240d623c33bf9bf1fd6594ea7e098b7341a865e3198f2a3066ac0abd77c3c626fbbaec077792f4cec13badfd0d186ab1f0d937b0498833c4d59acbd1d376bb3e03abb0084ec0635e7063b558b4820dc91a9eaffe5b00b36b6224bf829dd1ac54e04246a535c2781f7f60137420f0e527334b0723baa2f96280cc4e36436f0a19f6212874a913938062d370d5cecf715aef7105a6d4c99668d6040063609964ebd9cadddd252e563fbf1036041a8832e283a3041e55ff1aecc67e6ea0820b3d48efa1cf65469d308bd8b8db6580b5ba4cb4538ae0aaade74cd66df164041f03cfcc3885a369caa323643fe9a0bdc277f7e5f512a44f709c278a852124835f58dee41188fe2b412e64d607e91c1e58ec728d1a33cfb0c1a9fb574686786c469cf4bbaf51fbe79b52eea2c3425e3ec3985b3e4556c97b2b8146c11489c64b5f50bfd77469234b23811f5ed49ddd7bad0c106dd8f4280b18b2785c81c3948d24048ebc0346eaa29469857ece5410617fa8109077b471fd13ce2e8e109c79ce1f38efddde73d8aa485c9f6712edad8ca5fcfa4a93e02dada734d7da439cdc7abb5e51b1586863bec9daebbc34f2fb69da8b2bf0a03fb1a93d76f2d58d4d331f82f562db13ad225c9374f8e2c6ec906567d334273f0bb48c51150de470161429008e81bf92aa8b002fbb258f2b42e31be8558152c2dc9ca38c9f879b7e900623ae9a4cd357f90446190e1ff5e48e8a09d692b217de3ad0ab4a670e7f1b437f9c07a902cad601249ac9fe46db8527fbabbd1b44cae3af06e0150bf0e3d898f6fe862b71ea9f6b727accfc18848fc79e6df63fa7f06591960e670edd8e2908f2c7b4a1e8c7068064629c9823a556c608ed3ca05a3ce69b0472dae032c2af3bf9840d9cf5f4bdf880feb342f6a29cabb195dacdd9e4f913e8b9cb108f15bd7a71c01b8d17d8283c3e8b9b9ce000a3f13ef46b28b5acefa4a93fc220411be66d01e848e2cd05d7b413a5c0069e341f3ef78558316bd96cb5cc914a8ff739bc8c1089204e83f23f08a6e9db007fd160dd71b54c886b1ee2dfc94aeec02ff3a250240f3c20eb11e0924ea4271b135d0b553430928e31d1d48b35c9095149de2a41c306f6fa61094ef991813ed6e73b915ec553e4c36e86c43088a834c3e35dd6d963eceb3b643cec9715fdac9469f175229bab9db87fc234784844fb987af71a9f8d4d738483214c032265db041a2339793da437edc408a7badb3bc83f7f3e780cb5953a363c5aefc66d765486862550ab01da3dd3f9ce8080e7f925396ea871995350b9f10e4e3a494d9ba39c2c8c5d30beca39fb7f887152c5198d06d7a989de1cfc4d25677fce14594242c57bcca1b29ad096c4c3cadcb918f97a3838c6433349149e43d6641da00706bc93027ad0a94ca9eee0751a352c4a35873e009310418e2617ecd99fab84dd556b754efb7c7d3a92acaef1db1d14df3a0e98dd74838142ad3480ff86fa2b42baf9fcbfe2d7b6eb475ab0d891e70b5e93aad91e0f1f6b1d268e90a6ce8c1beda3c289e3a5a4ded514637677d345982ebed66f40a73667540e80ac6dbac3cf24ac6fbd48d8566d9ea661608e239b13f6380bcbf3f18b1eadd1b524c2f043cd9e314bf75def5edbae69ef1f59e76a371b8bc59f96626ff9811c86aa34e38e9f90ef01d8a14f30b16adb470379b3354a25269e2aa67e6770645b9f9d322906add3120bd1a19c7e877a7703ad7bfb8ef59994f02da2aa042bcdfb4a8e59153e80ab66d462dd4b9ab643c9cf8ddf44c9a1ff5355f92969c874249821fe085cb8a0a039f61cb2d117d66d4fe514f21387d7bcee4a1d995216f21e9eb05cce53e7963827eb5fd0c168504d760ee372ec5c2f58c2571b80f7822e029b602b299f5dca099d1ebca5911ecc6ad88769c02388e1597be7736eaeac70770adc0998838dc46b262aa3bfc4ad934be3e928787dc0c6457775a5b0fbd871e2596e4899c4fa1df34f79b57de0975d7724ceaffa4f86169351ac22f663989aeb23a198abc8152f387596526e596e7363279250c41d3b8ac976d59bbd7a8f63e7e6105a5d01718081350b1b0fa3858d9648cecb647b637b6e63ac4064b50f557f1d250e1c1591aa83fa427fe0639f049724ee6069ce9060e8b47ae18a87baf807357a347758f815a751c6e17efdfd60dc287bc0329b44e3cec5cbdfad86f4b416cb6a6ddd50174a71d812f039f7333adbefe15b6d65f37c9734399b3c174f22244b800adc9f71c159d9b11cbfc3c2eb2cc7d9a258c31e83c87c3eb4b4dd4ccac632559bf3ab8a02e5e32bd76f084f0a356caf35a31738a1d8fa35bcb63d5006632c55b190e8d297ac80eda0c6291a108c3aec75dae6e44f5f5ac903aeac1b7d91760acc52fbedf8044f6119639ad676a7bf1be34ec673f4b20a633a0ccde188b7bbdf4cb8393e9c838b40a1a5f1e6d4fe65b81e9d2a9a2a77859eb06f0754c06c7a5dc31f45370da0d0e6ca3bb2cd9426cb4b884477b9691658c61733ecd7ad261e00b0169489b3f2ccde0363521d4c875c30b0b352443924f093def9e30cb75b3362b43c9b8937efbb90dddb543856b6951208883edd0319e962682f8e46779236fe1fdfeec7f1fe4999c9f23dc15b2b026a202191e66f7bafcc435343275661b52d739ef2c88aa4e3634856732ab25b20a3782dfff2c6b0c02c00f3a621dc202a8b5fe84c0d6a8a1597e956a8d704dd7c5870fbdd74b15fa72c218f2bc891740392255a5ef90a144c821d912378cb1881e3bb19bf0ea7ded1371594588deec3dcdc7443a02df1ba14cc659487726da2bdffb706190322c4eac76d9190d47ca602c4cd62b41eaa01fac151cf594664e2ace6e55f7004ba9830678a15894ea38131d581060f4dab726b2b52affd77597ebb43d6745885c7cf6e920b7e865efbebe6a93fcc263d6e91e244f8b50887b3dd85810af336f8d2e0d1c1625b3c87fe4c7d9a7a137d607bc6fcb8a48ceef9fc657848d33aaff0846326901f39f05c23397333907a89494ba826f0f6763530abcd2fe5ffd907ef24ccc968a279663df32963ff437fee6a66bbdd885f3f6fee4a6b08f2c15cf3576c8436c58cb7f2bfe6a2cc77d381f14655689cd95f16e36540d59ff9d814d6cb943feb314e641a64961c2917f12f566f8034f17e76bb54482783516594bf46be64567336581c619e6a1be67a0ce672388fa757e2268b270976fac9c097baa792354e5b3f4a3f5cffdb28a0f88735c953cc465caeff14d01bb7a2658541759df98fae0fd6854b60fb71a8c51e009be023de885c3f50d6e4115220b13e329e8e66fbec0d76a9cf1203b632ef7509974b3b2ee3f31ddc4fd76ceeec3955db83fd3cd28ee0aa2848e4bb214d7c77f2966f0c45ffadb4e1ee2e90d67b6a66bcd46f1dcc1d05eb71376d844b6ee8b16c47c019bc11d8af12405e2fb134c0eb56fe587c410cf9a52528f0f18d0dd09bc6f9e2d5e9f12066edd4fa8c07cee94e2a604dcad9e54881a47c23757ea0b0a1a34b4bd367e40176c52a685832a02029a7a8b39bef1c5eeb8fcf89a288de055d81aa6f94ae80f859389f4bf6ca4f21e87f462e61f938b95d379177eb43fc4b49d295c29c364e7178c8c1f9fa57224b14f1b712bf90c0f4514c4082c238b1fed116abe95c87b3096ff63106d531c02829af8a15074e2b8c522e7b4ec9cf659c9dde4b58582b352cb9314b071a12af25b1191d89cb79feddfa7ea0206470ada10a9a027401897b57bf1a9e6f3b5255e025bf0ff58ebca185948d3d9c14d4e0b8a1ca4fe0fb3acc271c129993ab795ad40211dffcd37eca0fcafac2366d64a52fedffa203a7b7cdf74aa9db38fd00047dd0b1ebe40c48ced90847dc73d098718369aaa7709978e754b540c1b3a27f094a1c0fd26fcb93267dd6e4cad8e0f8cc6f8f4bae9c3306aedbf687eb983e6ecfc54e9c21e483f6776aa1623bda110e1c20d953460b26d99ad988efc75b1327de7bd2d738d6b7eb182c12409dfbd330f763d261fc31c77a21f9e6d8c370e3629bda5351a5dae9d9bf3e83f07fb2ca09d484f4f84fa4a750daa98ae39e7e0177be6d4a9be7559c5aa31e80f23f9348013a20db76aec849063b550f8086d7000f8ca123068bdb41d68a4893d67c11efbfaeb3d07d98312f02aaa8cf403b106172ad127721f1d06ce5cb49271db3b3238d98ba8e6daa63bbcedf0154a319cea849864da18eb7d99ff0ecacd528650b76038ea16fd733d481d31efb3a19a146370cae9f4cad4c5b3d9074c008970e6f79a9f704ff4ae31813a800f2da14702ba0349ca3e2fe3dd9d84cea4f4bea1e6380f97851a7293682e3c61b84df33f4f38649c6d7df01fad9f27eb3871982239c3e6a791401f29cb974a5d52d93f8ae122bc4b3c7cb4911e00eae7723fbffac5e04858fc8aa47842048dfb459a2c31a2c332df9d02243f160af649b925dc3174d65d312ebda988b6bc2cc3f958633b7962efdffad6e8337e03739974ec97d02def4cba8fa4d5620d08503dd7db8cb04d461ad3bac1a7753f3489600d5c97ddd7713e7b8806d10d313021f245ea4e9908b8dc43458b090b3fe55e24eb3d85635ca55afd7faa4491087cc669ac4f51fd91005db803fcb8ff685e1d7076570867a3d3c9c7dd59d7f77c33682a75d03ee4d066c4ba5cdb5959a1e6ecc91672c9f39443b2610bdb3246749f2ebe0636bd56ad323acfb8f2971fd1c6f3b933556f0e173c3e546ff8fc86d70641acc948755c10abe6817f07175be2475cc735c9a3c1140895277378debf8fb1c87c24d00ffde11af15719e38414bbaf4c7c84960d1373edde627e227ffa83e8ecb78194324208c782d9ee4e84534446ed5e8884540c1c34428ef7bf883f9bf3d5e4475e87316dfac2906610bf1f655667f7aa5a21b4f824e8324817a094bf19aa8bdef4b6d5f9fbd803eaf0df800625e2cf50e21b14ed07f8d6d8f27003d7a39434ae1e66339211edbbe0b7897e0ffc856ce4e2eb33e4239c020f189f93cbd9ba681fa63f552186293eb22d672268237858cc233819c6c2fa3f5551d64c830345ae9953eb428fa0b316c61a2173fae2e41b726dabcf792a3a141264bd37e8695c8f84ec0f02c2a8b4ca86465f79ab81f13b3c88ec5ce7a3850aae1afb5be0532892483a569ea4e553e35979c83d6447c642943ba2c8f67703a8913b39c15408d03f4d05651d1ca1b9e8a67a04c60e7e8cb8e14f751c90ecdb76248f1e6f2dd17d1efb14e78711220d61d712bc1d8f6c6a238a8d0f5f9c4c36fccddd536f51f657b8bb3182e46db278d753099848d159890df9ba159902dd3bc3f5ef7fc9aabf8594f322de3d179722d182273f51ba8f10fd95a132d2aae81352058b4b831f73303a0db0a499f71932d7cc335a3f3455287cc6090c137cb4e531637a5fa7975c7f336fa37c01f582d17199f7901b26f2f911f4b94b63608bdae97983623cfcc09b0683c30d7cf918262851398aec77afaa44877a98cb3eb31a01ae70fd4b35e8ab3bafd80012eb255a835cc2efba11d4649de7149b52fe75cc016908d7db2a1cd85b5da9fccbb3ef940b225a688edba94ea57d4ffb0088191871141299f4c3a44aedf4ffaab039bffd460cc89d6fbd7591e3aff360ddc4e727da1657ea9ee8c72879dca2b2c866dcbdbe80d635659f8254dfe6c774f29a2721c4d79f73e281ce9a877c5abb1c2090fbfbe74ad9786916c0228b94dc46f3202eb5bfb1dbc77601caa03eef6db25021df83aaed30b1037afd33042243e1b51b74373657cb56afa8dd4b89287294dfd892e02f87e31756f6329abb394fccca601ed1a457eb96140bfe11c6ce6fcab3fd3c9ae0e099b248d187e016a1a80e1837520c717ae28f8e7253795ba90f5ab6d8043724bffb8bc255258c7f21f7af89e8386e058859490324040bb181f74eceb0134162eeb0a9adc834265d83e4b804bafa81c849f7cd5d6a3a4f301ed2ade5cf914004336115ef73db37188d163070f7bdcd23856522828c1dce40484680e27ba5ba7157b6d5729e43461808361fb7e5acd97c034a505cd2d40f4ac6fbceadfd7739112256f31c9194dbc4bbeb8ec0ccec2d3c8c4f60d183889ab4619b9f2e9d30444c5bea76d793f57e8670de8373f6a851cce81c59cbe960f8e8e1cbfc4da2f8648acc19678aed8eb8c5edb709b8aa06ce92df5843314a85b04c0e35ebf256f61f333b8ccd1de88810eafb1d25772f2e2af838ab26ebef1e4a4aaf817705ff5300af71ebb077ca0b0f5b62b8e198ce49f065bdbf0be020544f498e57a56ee6368c6636dd1982db3e3b81ea314403cf7fa5413439f9fa254f46b1715d7f1553c84dc1510a0e25654a1fc45b3056a17af7d3f366c4f9204536b7e9213e0ce28d31ca268c1b9a48ae57408d7c5c205816da01e51b06123ac9312a5b66a054bede988bfeadb8c2d3ff8c2842165ea911ed4fb87e1ba74c31f96a286e072c608f8c2519b27d8890afa0115e4df1ddfab5457f7f262d50afeb1d06388ace89373fe002fba8c4340bc2d90f6a14d582192a6792de451ba944517d30e317815fe1b42254b94a4a633bf5f2aed5018af5105a9baf5d43ab59124b610eb07de95867d89a46dcffd6be29313215257ad7dde72b29fe8589a60921c210c82725ce1ad09190fdeb2e32eddc5ce36de5e986e3a48758a8dd7dd3607a9cd387d075f84d24c94ba46e4124975c5f4bdd9ab55dae515571d5ee88fc0724c3f27334d62e9a6c671461ed9f7564b223b28ece4625e7f57dbcac3e13e7a5271db5b3dab13aa9af53335cf1b0edfee58f62a70804a53599e6815657845de38c9463704a6ce221f575f0bf01dc530afd8aa251d157a741447a08fbc14426695a0f46d10d71efaa46b592afa68b713303feb9b4b0a7f1b2fe2098c102bc0ade9975a4ffaa2628eeabfb635667250d1efed2f0f72d5c4d31cfc07bd3a453d1ea52b0c621a9f557922b2fa9dccc12f076f6ee8f43d0de8166c043f7572f7042368ca7f46093454241cf39ad695dbae2e1f43adebf229555f8d88f5576297d276a4f4276e4ef7db2a19e01b723a386aa07fe9e2494aaea9390208ddd571ce1462ea36993d445076f5aa06f0f3525dc12921f02abe9f04301d59e25d6238f046728910494581e4a4115dd6cfcc56b25e0275c4eb9e77d0969705c408a010b4e540320fbc19a00aef07a5edec7fcfecadd70bf6a97b5d8a5910862c43f1a1727d465593662bf769b43302aafb9016531d1154f3e8d7d897d4146b69b3e953bf7aef7429ebff2057904e049c518fd28c484be14b2e26419fb43d262abcf9bff26ab60e619205937b0f931c40a2c17d0eabd1217afe0940f865e536ede3954ec1c93484a90cc1c93a8ebcca2643f78e40a46b95f1bcd35f3855971e01ac6e789412e5978ec0c64a1caa158ebbd9747ec8ee55cf4e0f26e4e62fdd5c249bc7d5efe433977132859ea7ce57ea7fc7dad71dd63a3dfe49768a78412271b52643df4b99c904fef6822f5277de6df0939d2fa5f87352711044b8653600ef41d0650d2dbff07096713e84a3432379bcc13dd0f7c1bbbd44d803e7337ae335492eadd81cd3545ab6273d27209cc19e12d53f6389ce5dcef825469f798c53e4399570d87f606f340cace09f4101336bb144047fe27af417f97c9f599de6ed6ca1a97086ebd39b9cd866db458b0cf33306923f5e8853f918c74250ae2716fa3effdf0f5bd8c983e5c7e98fc2750c7bb4814442b7f1e5d751f01b0cf59ba904fbc2aabfcfdcae92bf49a9709e85ac4740cfdeb0f495bd3953e26b46d861f9b7f39890f47b5def5279ec2b10223358e06830c60c9d0a26898f4cb770cf10956dd6d0366fb6d3284db61de2f0f6149ed1ab62aea829c5ce32746d842d223e18b11607ef643ae2d5eef45d6595a28 +MD = 776b9d5aa2f2be8fd77632a62627dd5e690b8c283243c469e7c22c7df3f5ca1a + diff --git a/src/pycryptopp/testvectors/SHA256Monte.txt b/src/pycryptopp/testvectors/SHA256Monte.txt new file mode 100644 index 0000000..e96396d --- /dev/null +++ b/src/pycryptopp/testvectors/SHA256Monte.txt @@ -0,0 +1,309 @@ +# CAVS 5.0 +# "SHA-256 Monte" information for "s" +# SHA-256 tests are configured for BYTE oriented implementations +# Generated on Wed Feb 08 14:59:33 2006 + +[L = 32] + +Seed = f8ae5b970f4f0630b3584e681b2edbd6d14b0ceeccd63b30d877429f3f693d75 + +COUNT = 0 +MD = 09ee2a32d22292aa0824b3bf94cd541a257d20c1a04b974540982a282489054e + +COUNT = 1 +MD = ba7be8f8df73cf7af75fee72edd757c5d4c2caef1a6671079841565b98a43e7b + +COUNT = 2 +MD = 6e628c0a11e0fe3f25e0f6ae7a7fed0c4cd768f9e152735e4791fada9ae53155 + +COUNT = 3 +MD = 5638936e971f778fa3c4265d39afbc443569c549b34c1a3a7333a78ccb2f2177 + +COUNT = 4 +MD = 231cd2497dd4316bcc5dedca7c1c49eeb530f5012fb3eff909cd44f24902ed09 + +COUNT = 5 +MD = 07597b37cd575dc0c85658ee99cd9b94d587f48d627f12ce4acc2b2c15f1c1be + +COUNT = 6 +MD = e61f9624f6e95770b34ef6fb41ef71910efdf30030ce5710f2b466050182848e + +COUNT = 7 +MD = 2367e6b4948d2b7e4c8dc881988799927c5494e572f0e0973412581adb680091 + +COUNT = 8 +MD = 2ad0dc580ec372f6c5d51ae963f6a916332e5bab7943de967d22ddde2c410b5f + +COUNT = 9 +MD = 68fe11a2f396c16331206d4b34a66bbd2e18ebf56959e5753c1c474fe01b3361 + +COUNT = 10 +MD = f4c4bd653944a3782de1dc03848576e7df0f4088e03f1a33c50cbf084718f108 + +COUNT = 11 +MD = 892824f520dae3f505b3c7597769fde7c83809e9512123a8f1cb51452240dec0 + +COUNT = 12 +MD = ce53b5caea0595133218a9697e5a19c39e24b47703df4e27ed1603588f632308 + +COUNT = 13 +MD = 00f76278f86deecf65fb8d625086d262fbc92452f18facb690b723a315245bc0 + +COUNT = 14 +MD = dad692604724b15a7bda74f4fb314030a7e41dad74b85dedf7d80fa6519ee1fe + +COUNT = 15 +MD = 747b9769d7c8a38295413c2158acdb58352b7a6b5d96b28ed19bd69c1bd73288 + +COUNT = 16 +MD = 7c0df1c6ee57c2699c734fca01f34294be4eb3d3593137cced9072f4848769d1 + +COUNT = 17 +MD = 4a8ba3e99a23c13755ea87a9cff35ff819b25b05c95ca9ac60a0fa3fabae7896 + +COUNT = 18 +MD = b896a76e6da426a571985588f6a8ef3cd2472a0c523dcfec16028839246e8549 + +COUNT = 19 +MD = 6362feff7380064c763eefed1695aa1319ff4bc53baa5b1b990105607393c655 + +COUNT = 20 +MD = 158a21edd73b735a9553e67422969c98959a7db85c90b7668b6ea0daad65bd64 + +COUNT = 21 +MD = 5b19a6e1070b9e11add233fc9ea5220904ac94d6314c344495173bdbb45f3866 + +COUNT = 22 +MD = 50def9a51f9e1bf9139e7e7f8ff6e9f5235f02e9c5b354e8f5ca2c7e13c2ce34 + +COUNT = 23 +MD = ff1005549276b4d7bb9f38a112de25298471a9cf3314056f46c11e73a351f0fe + +COUNT = 24 +MD = 3402617e1e0e7708d83a52fa092b6aa909908576aed1d26b1227f339ffebfab4 + +COUNT = 25 +MD = 13cf2cf2cf15541b63982bbf519d77aa09b483a974b2bc4697527fafa62dc189 + +COUNT = 26 +MD = c9c3218c1c4d7427339680cc0453eee73623fb2e3263070d4c88208f920518b6 + +COUNT = 27 +MD = 354181b335df0fb7e6ed168fd39b7846adb2d0ba80e9042c9e0c2c60ba9cdf29 + +COUNT = 28 +MD = 1d7b7a3a5132fa30ca4320238a5ad21e6fd5db73df2fe86038654ad5b1bfc84f + +COUNT = 29 +MD = 16e37238d08a22215eb0a1c6c6091a2a3bb58033252f0111dae92e5e7235b4c0 + +COUNT = 30 +MD = 5e27313155783b27e9d807ddee76abdee5cd46092fc7643cb35fc40ef4a96673 + +COUNT = 31 +MD = efb9f27b1dead16decf8f12d6e2448a2532e2a8bc7335d84c7ab12ed8e02fb6b + +COUNT = 32 +MD = 44760c03d905b13f3c30317c3640f46dffe6666e14e15cbbe51f32021071e59a + +COUNT = 33 +MD = 6f3904cc784f30cec50af89b7ebd55c2eae42b466bf9cc0bb25d8d726896a4c5 + +COUNT = 34 +MD = 7c0143342e2f349c9a6f672ffc84497a066e489cb6daa6420c1402ce2d4ff621 + +COUNT = 35 +MD = e89ddce4e1180323dc91046f0fafab6d6c9f58635b83236e8417651473da7403 + +COUNT = 36 +MD = a6264c5fa97d90727b3c6eedde63dd98b406ccfdcc9412a02a22164581acd1dc + +COUNT = 37 +MD = 1ace95b10c616735eac1418845b517ef90ee720b16437f402b41f5ff155c3a03 + +COUNT = 38 +MD = 9bf8bb64cc4932b79ed5ef3931f804f010aa75907b327ec0dad2e1aeb0c513cd + +COUNT = 39 +MD = d1fd03544852358ed4aa7a34d9ba725465fa0e6276347808b716ae20b6142e7d + +COUNT = 40 +MD = 83d60511c5d40671dad61cc6ff7276765185155d94c5b4207b4d1efcc9445af3 + +COUNT = 41 +MD = e7dfcb3bee49d94e7fe69ef6e18810e6ca7714c9e6a30860b375e877ffc4899c + +COUNT = 42 +MD = 85bae087e9fd30bfdc4ac661628aa13041cbad8b754a8ef649722c87fcd8271c + +COUNT = 43 +MD = b638925c3d3d01a69ee8c3d49037929c2b0ce40b2d947ad569a9bada6377c9f1 + +COUNT = 44 +MD = 94021cb567befbcb39896da53c2652bdf45bbf11a8558c96b2c78b48f0e2e8f9 + +COUNT = 45 +MD = a80a47a151fac789971406cf564bd495023e22bbb1692c2a371e206bc15a81ed + +COUNT = 46 +MD = e01b864141592511803e8af245d4cd5a03d87c7fa92c675378bc6b82983bc83b + +COUNT = 47 +MD = e4b8f81ea92b63555116fcd1ec5ceb4eab5211e47233f877ca496eabf3bc7a50 + +COUNT = 48 +MD = 29a7339e8944af2550d0f0aebf7ff3daa9b48e8e56832661e7ed339ebf03fe33 + +COUNT = 49 +MD = 273c9b49e7ac633f8764d78ce3c93da0a9ca0ebc977112ce418e3be108f2a193 + +COUNT = 50 +MD = f0730c968990642f31983c78079c10838facdad31f9d4bebacf114a70f0f9ed8 + +COUNT = 51 +MD = 11e9c8c01be733bea0f5e8b2c818c2dfc2595dc438d8b079615a56e7cd22e4ce + +COUNT = 52 +MD = c2d150a802f57ebd346c8d18ef2b2f16adf0e8e5b3d7f51ad38fc868c6afcb09 + +COUNT = 53 +MD = f5f873e2c00c71f850ca400f0d83d24d3c89285a4dfa51c5faa6597190414134 + +COUNT = 54 +MD = 6ac1adbaabbda9bdc6a5eee91865effb6d77bbeff368b8081030a6c1a9abfcfc + +COUNT = 55 +MD = 9122b914fda8edc3343496fa97221011d6a6ee601f9ceacdd47a9acdce5b5c48 + +COUNT = 56 +MD = e7554826e969494bd2e51d9696cdc3acdcfaf3e40595b8975f3c41c636bdaf15 + +COUNT = 57 +MD = f99581ba1dbaebfb0d36662c87789587814b0ac59713be372dc3a275b4944e5f + +COUNT = 58 +MD = b3eeedded2c1d0faa0d98559eb39e632c64aa5fc907e2363e4a4b1991284f630 + +COUNT = 59 +MD = 6da9d793de479d8776bb97e934ef4b60ce05402db9b4e01d8da9a1f7e58538db + +COUNT = 60 +MD = 6d2e2dc25ae12e221fb90267c7c8f38986be70c3016299bc43f8331e92243d97 + +COUNT = 61 +MD = ffa69b8370840ad7a899b593079caf266be680560323ab3b5c06308576576634 + +COUNT = 62 +MD = 26cdbb571cc6428b40b70f705599afdfaf11b0400a7a59c5233e64cb39721ad4 + +COUNT = 63 +MD = d1f1c0b2cd13bd370d7ffea815fda3e16f33a0977088d7351d35f02cd2aec150 + +COUNT = 64 +MD = 8f28c49126339b44f0b4b39b3dfd454fabf21578e2c16af0bbc1ddb7b6d2ed8c + +COUNT = 65 +MD = 1ce2820507b8fa01764eaa846def8ec67848d7088405905d2f141d755a8ab98c + +COUNT = 66 +MD = c15ce1637d55784423140f5f5b8ebb94e459872c04cc431cf48a573e54120ac3 + +COUNT = 67 +MD = 66eb577bd140e0f04de9369d18835fe2f7c0b1c5eca7a2061156a855053a52e0 + +COUNT = 68 +MD = 8550df9ac711398138a2112b01a8b84dc05dd76d56029bfd3e4de1a9d1cfde29 + +COUNT = 69 +MD = bb3678468a71042d91609a23c61b09b8e495724a572382a9be0d1fba60bc8486 + +COUNT = 70 +MD = 4f1607c64b1fab340ddeaa4788399eb3490b50b5578452c8a7ef1b5e77bd2554 + +COUNT = 71 +MD = 5d8dc29cda8d327b670079bb3a7b0ed85274173ccbefef9c55b0abd2744f844f + +COUNT = 72 +MD = 47cf16deb9329e32e394aa7a21cc9ba751a3a28565d99c7446e291504ade4450 + +COUNT = 73 +MD = 4bded81824986b7c00a6b033992e85b581c375369d293642014c998dad1cd0d8 + +COUNT = 74 +MD = 6c0b1fa62d160897b7eab9a66d2d95523f920d753504f55b67b57c3cd8e9209c + +COUNT = 75 +MD = d7f1854c446e07095d7a43a43dbc426be36627c839985a624e62eb72ac805a87 + +COUNT = 76 +MD = 8b1e6d1e6c7622edec8d79cb6148b9a426cd39be50d8c3466ba0694fa8c50dcc + +COUNT = 77 +MD = ab59f72305f4d6ff6aa59a56c2019cd1395e09048e0084048ffe9b71ae90cd01 + +COUNT = 78 +MD = 7516a477b87f681e09860ed1d733c13ec950e99e5f368af288fedf6d626edd14 + +COUNT = 79 +MD = c36e14b9e2113a97fa4af6dfbab1cc459c8b51b88af67092447fa0e6b655f847 + +COUNT = 80 +MD = 6857b96120b5162b28270d3a4d494cbb85eaa561d7944b3e9c82fd194d8e21d6 + +COUNT = 81 +MD = a92f35c6bc90606f21eb1ab2c1ff5686bcf16d17396c8791e6d04b933ae65a52 + +COUNT = 82 +MD = 2eb7b3fe45f98255f0b0f9c06b22491e4529b443bc3f3469aaa86d094cebfde2 + +COUNT = 83 +MD = f9c4f44331bce44c374e70a01ffbb0c68fa8294d5a1b644cec589efebdeba8af + +COUNT = 84 +MD = 197f8dc01ec7dd651d427c3dff0f7ee92c48d2b3e8eefea3446241aa85d7149f + +COUNT = 85 +MD = faf152566f1147f26d10e1a5ba17aed6f0de76c1a732bbcd739ee492d944f208 + +COUNT = 86 +MD = 5ec46420a6db67f05849d9824ba14f18544e8ff3aab0d47f28096e497dac3a21 + +COUNT = 87 +MD = 590f1bc2bed8d47f5fdd4610ddc7f424c7a928730d41985100e04d5033f7339f + +COUNT = 88 +MD = e246ab37d4b2a2b4adfb0e0d4b2da2e06e9e46d30f5e0c0dcfa6e267fe3566ac + +COUNT = 89 +MD = 6f8fb3f1a68a78f3246f500d988b3e40511a01f4dc3c8b5f1744d3ea54e6e1ca + +COUNT = 90 +MD = dd9a32c79c216a69a1d11c7403845592980125153b68f78f1ac07a311ecab1fd + +COUNT = 91 +MD = 0bc729d8ad18522c27468e5bafc2c056264492e6bf9806a38f7555c585a10b82 + +COUNT = 92 +MD = 870347b7cbfe42a151f9e895b1b2acab394ee75cf65814a19d2d49ac7f5eebdc + +COUNT = 93 +MD = 7180ec50dd7e6c36dc84070ba715cfe31c2a928070b90f3367319029e8ae75f1 + +COUNT = 94 +MD = eb07ebb21f1733a9535fdde391670cba3770836c194bdddb8909d2d56bb95ebb + +COUNT = 95 +MD = e40479c983a83a4d675af2085be9c37d9e376073eeed91d51915ad34ca720608 + +COUNT = 96 +MD = 62d496f020d1ad5866e99162f8e8b2de33d6b4be69440b6b6dceb8a170daf9b3 + +COUNT = 97 +MD = 8ee2f635187ba7ae412f5372eae2cc4b43e88be59e1deed354dfae9c0c45de87 + +COUNT = 98 +MD = a0e64d2ce09db5fc47300d30e9f8292bff2232f3ac29ece64e9f80d0d0029205 + +COUNT = 99 +MD = 17d79c61aec50de7b7cc0a2cd6fb50fb16af40ff985fd5d5f39cb0672c3f0bf5 + diff --git a/src/pycryptopp/testvectors/SHA256ShortMsg.txt b/src/pycryptopp/testvectors/SHA256ShortMsg.txt new file mode 100644 index 0000000..4eef712 --- /dev/null +++ b/src/pycryptopp/testvectors/SHA256ShortMsg.txt @@ -0,0 +1,267 @@ +# CAVS 5.0 +# "SHA-256 ShortMsg" information for "s" +# SHA-256 tests are configured for BYTE oriented implementations +# Generated on Wed Feb 08 14:59:33 2006 + +[L = 32] + +Len = 0 +Msg = 00 +MD = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + +Len = 8 +Msg = bd +MD = 68325720aabd7c82f30f554b313d0570c95accbb7dc4b5aae11204c08ffe732b + +Len = 16 +Msg = 5fd4 +MD = 7c4fbf484498d21b487b9d61de8914b2eadaf2698712936d47c3ada2558f6788 + +Len = 24 +Msg = b0bd69 +MD = 4096804221093ddccfbf46831490ea63e9e99414858f8d75ff7f642c7ca61803 + +Len = 32 +Msg = c98c8e55 +MD = 7abc22c0ae5af26ce93dbb94433a0e0b2e119d014f8e7f65bd56c61ccccd9504 + +Len = 40 +Msg = 81a723d966 +MD = 7516fb8bb11350df2bf386bc3c33bd0f52cb4c67c6e4745e0488e62c2aea2605 + +Len = 48 +Msg = c97a2db566e5 +MD = 0eb0281b27a4604709b0513b43ad29fdcff9a7a958554abc689d7fe35af703e4 + +Len = 56 +Msg = f53210aa6ed72e +MD = dee684641421d1ba5a65c71f986a117cbb3d619a052a0b3409306c629575c00f + +Len = 64 +Msg = 0df1cd526b5a4edd +MD = 47f527210d6e8f940b5082fec01b7305908fa2b49ea3ae597c19a3986097153c + +Len = 72 +Msg = b80233e2c53ab32cc3 +MD = c60d239cc6da3ad31f4de0c2d58a73ccf3f9279e504fa60ad55a31dcf686f3ca + +Len = 80 +Msg = 5d54ed5b52d879aeb5dd +MD = e0164d90dbfcf173bb88044fac596ccd03b8d247c79907aaa5701767fad7b576 + +Len = 88 +Msg = df866ecb67ab00515f6247 +MD = dc990ef3109a7bcf626199db9ab7801213ceb0ad2ee398963b5061e39c05c7b5 + +Len = 96 +Msg = 0757de9485a2eaea51126077 +MD = c1c9a4daadcc8678835872c7f1f8824376ac7b412e1fc2285069b41afd51397e + +Len = 104 +Msg = 7c66f5d443c11cfb39dd0aa715 +MD = 6840619417b4d8ecaa7902f8eaf2e82be2638dec97cb7e8fcc377007cc176718 + +Len = 112 +Msg = 329624fed35639fe54957b7d47a9 +MD = 0f5308ff22b828e18bd65afbc427e3c1a678962832519df5f2f803f68f55e10b + +Len = 120 +Msg = c34e59652acc043873ecf6a4ab1060 +MD = 0fdf1604ac0d717ec9587b4de5444aaade807589d90eb326eaf6acb58a051e79 + +Len = 128 +Msg = fdf4700984ee11b70af1880d0e0fefd4 +MD = b01ae16eed3b4a770f127b98469ba26fe3d8e9f59d8a2983214afe6cff0e6b6c + +Len = 136 +Msg = ea40aadbefedb0e0d78d067c6cd65c2c87 +MD = 36157bbe61931d58a3a644953eaf131bbc2591c673a1f20353f51ca5054fc1c2 + +Len = 144 +Msg = 6d1092004670efab3af483d265d8e7b3da73 +MD = 67fbf35d360d72b101410794ccf197106c0e784afa9c80206a550b600dbf1f16 + +Len = 152 +Msg = 55a10148ae7b09ac4e71df438135bc70e873eb +MD = cbe7965513af46dfd596dc5839cb82a5c6c7328034b1dd0042a9f4b71fb14430 + +Len = 160 +Msg = a03f8fcd777bd933b4b0af8c5ce3d61308565649 +MD = ddfce4e8c7b38845e2a81b7fc27a06366467a9e111316014013f9701e2413ce0 + +Len = 168 +Msg = 8e5d6cba8d4b206381e33ca7339bec504f3d6119ba +MD = 92f678a3e59d0dd3610eec3222b8c6ebd28eead530723fbd226747534da22b6c + +Len = 176 +Msg = 96db1b62eed85f2628d0c25da534401fe80d13d09beb +MD = 725bab4457c789d6a4cc4736b9c2c662cda18407150844d74d6aa4efd72dbb05 + +Len = 184 +Msg = 1c482a45dfbcda549729126b533477edfaf7476fde498f +MD = 6523f24f225b996aad1a8b317e6e0f8e97673dcff3fd62a27ff9f3888ea1302d + +Len = 192 +Msg = 0f677d8e4c6d6a057492670d99adb870adf68a36ead37919 +MD = 44acbbc6b48bf37ee088b9c8546fc46e5a5f0d637b5e444f628de186144087fd + +Len = 200 +Msg = c09056d597816542bffe4bb33e475dfb2d6293016906ddc18c +MD = f4baeaef70588a0820d63c2401dd84f98adf7366782d196f8698d7dfd3db1c29 + +Len = 208 +Msg = 72f313fdcf52d0749c9937cc2e53f50b44d65a544876bab7d2f8 +MD = cfa67aa52fd675fca985f69f9ca58af62baead8c39723bb6bfbae8a5d4bb9beb + +Len = 216 +Msg = 09f6fe6cbe6744149f792a4a827e4e8909627abf75301bf7bbd7f5 +MD = 657633891dc6274d6aeda78e7313dfb960eac9a24d29293a057b9746a18de4ec + +Len = 224 +Msg = 9e1cfeb335bc331744247df4bbd56876a7f69298aaf6b9e7a8731889 +MD = 930058dd21cb48b2cf90eaca55322ddf48582687838a584928440504a2fde578 + +Len = 232 +Msg = b8913001efb1b7f4bd975e349c5b2cbe66045bf0d2fb019b3bc0f059a4 +MD = a0eb0b7fad1d1b6de4f9096724a621720538a9c3f2f6d11134d68cb9ee52fc88 + +Len = 240 +Msg = 8f08537d50928c911a68b071d65b9e8f038264d3b62c5f33de18a484cde9 +MD = 10aad5cd4484387373577a881974f1a550782108bc88b4e2e8085e9c3e938bbb + +Len = 248 +Msg = fd846162c4da936d004ffe0cbe844d940f1c2953157cf4765dceba2a6f4c64 +MD = c13ba769aea0e478816f2f608b5cec3fe14672ea033088a8641cfe69b4ff57cb + +Len = 256 +Msg = 8cf53d90077df9a043bf8d10b470b144784411c93a4d504556834dae3ea4a5bb +MD = 56059e8cb3c2978b198208bf5ca1e1ea5659b737a506324b7cec75b5ebaf057d + +Len = 264 +Msg = 1bbc2b15253c126e301f9f64b97be4ce13e96337687e2e78fbfd4c8daf4a5fa1cd +MD = d973b5dcdae4cf2599f4db4068e4aa354f22d8901adc463ca3938c465578147b + +Len = 272 +Msg = c1bdb3bfc65dfe9a393331266c58d05fb9c8b7476bb717dadc29bc43dabd91504fc9 +MD = 57844e1d762e6b7bb86dbfcc5c5a59578d39cc665d1ddbe4de03a61778061af1 + +Len = 280 +Msg = 26eb621a45bd9c9c764ccbb672b99f2a8379c7bbf4fb07eec58a8b0ea4747b72196ccf +MD = 73dc27bd45daccd0f811381230cf7f2a1d3ed1202e9a770af733146b1e166315 + +Len = 288 +Msg = 7e3e3986109162e0c56357048bbd86ff49b93644b7fb064e7280968650978466f02c9adf +MD = 682c474799f5103252c3e2efef7f747783e514b54e93b8303b0e07ee4218f78e + +Len = 296 +Msg = 763c1a9ea50bd72bfc516989ddf3eff2f208f64fccea3cf0ca8dba7f3d10e237c99226510f +MD = 54d6cb2b09825eab064c8952113b9897a3344737cd186a8e6be0a0b258da3e57 + +Len = 304 +Msg = e1a7ffea8417e7cd49b96e355fd44f3f7a150fab6dd8343dfba3b262eaf3a6175a3c4607552b +MD = 83baa80caade404c446833ecef2e595bba6dce2cb7f7422fad2972a9fe327aca + +Len = 312 +Msg = 692a18effad8317a11a5cddb917f7389e1be6dba34572a300e52e056047e758bc363a0be53784c +MD = 0c0c6a6b27a6d7a7a5130d70db3b8bc1bd8001d103efe72f45b082cadbd03742 + +Len = 320 +Msg = 73fda1e1cb7dc9a9ece858d040d7105cc126eab153fb0bb55703f4317dfff97bd980f4523aee3a09 +MD = 9878f8804e00828b39261843f2b3eda19a7e9b9ff4cc2e23f7ea1f62f4491ff2 + +Len = 328 +Msg = 2321d88c19e3e6a8309a09a5428c01991e16446823f13b2f0db4ade30e9a7c3521868fb99b440f4802 +MD = f1bd3a8a74c8f0093038499ef63794d86fc6d82602a802a435718e61e7b396cc + +Len = 336 +Msg = b9eaebda29172b052bcc1e3a9c7f2eced43c084a86f89f61e7237425137c167aac29e4cac4071afafd3f +MD = ea43ec91285145d8f29915b227a0e35c89f90d968f9a14332dad275cfd52d619 + +Len = 344 +Msg = 332daf07d3a6775b18572549a6e12b8a27d81b7c4abcc5bd0b2b9ff936546b0026af131cd3ecd8a10c29ab +MD = a573959ba6b1c3bebfd6288c806b72a65650d23bd46d123816a2a6a0e47d1e66 + +Len = 352 +Msg = 30ac7eace1f2e41034c25a3d3e2db979c23dfaa7a4914b0da147625b3e1f12e9fedc1c41d8ee47dde84fb332 +MD = c0c3f40d34e711bfadf517b3a78140e379fba5f7edf2c1bc3ce82469dae4d2d5 + +Len = 360 +Msg = 02c3964c4ad9c4af97d373099302c2cd770ad06c7d8bd11c970161d861e917a854265e223da28031ee38041534 +MD = c13c622bf08a3d3cf1fd6fa5e26e505e551b1643bc5a0f59ed29541235218f77 + +Len = 368 +Msg = b9eed82edcf0c7ba69f6f6ac5722cb61daecaf30437511582117ad36ad410ebc6582511ef6e32dce5f7a30ab543c +MD = 6ac64caaeda4763d28a44b363823a6b819285410fb4162af6ca657396f6028d0 + +Len = 376 +Msg = b574865024828bf651df070ac0cec1849aa6470901d2e30fa01dcb43862d9827344cf900f46fa9ef6d709e5e759f84 +MD = 4c839e8f8f373c25a9a3351257c6152258ff8e6a88dad42f30f2bbecab56c20b + +Len = 384 +Msg = eebcf5cd6b12c90db64ff71a0e08ccd956e170a50dad769480d6b1fb3eff4934cde90f9e9b930ee637a66285c10f4e8a +MD = c117b9dce689c399ec99008788cd5d24d8396fab7d96315c4f3fe6d56da63bb3 + +Len = 392 +Msg = 1b7a73770d168da45bf2e512eee45153e02f4dfe3b42e50304a3d63d7826f0469562be8fdc6569b056a7dafcd53d1f597c +MD = 0b42cfc3dd3d3198f06c30e087837ec6a6dd35d08e54e886c682709f8f42457a + +Len = 400 +Msg = 0072ae2f3bda67736b9c66e2130260b3a4847bc3968e037cb6835efcc2014273336725cd5a94f592aef20a0a65b459a4415b +MD = 217cf25b8b343c28336b1c1e9bed29e0c96045bc93daf426e490b608b0905c90 + +Len = 408 +Msg = 2ac748680f3bc1bf098c4be38c7194643b0d009e51c43630404cdfaf9807aa9b299094916c9466c31fe37fa630c6d3eadc9434 +MD = 3ea59e2e79513679a22e962f22408306f7e8f6e562c2f1f210e279fad8eaacc6 + +Len = 416 +Msg = 893d1a8863d234ee50e5a8c7650a4de047230ad03d268dde8921401ff97b79dfb97cf2426b0f782b79c7e75daa2155e1f4098ea7 +MD = f7808e03e5d5af43c2bffb66e35d1ecbd79f4d8fec44f821f73a235d17c70a89 + +Len = 424 +Msg = cf673b96eaf241cfa3e262dc6fe65f08bcc2be56d8a2c9710eaddae212ded6859f0ff83e5e57d0e80a968b8ed24e74defeb5bbdad6 +MD = 9bdb7cf0492ace4620a47660acd127f951767b0738b5504451d6ed56e4fa3cbd + +Len = 432 +Msg = 0d545be1f47b966214691c21278704e89a17d52dd96aeeeacc5325a9a1ddafdecd39407a4dfa72bd32856b4c5cc2ba838618830c8399 +MD = ad53e0db7e63211c8b00947908ce29660c4376e244e19cd30a659af65dc6f1fe + +Len = 440 +Msg = 9eabfcd3603337df3dcd119d6287a9bc8bb94d650ef29bcf1b32e60d425adc2a35e06577d0c7ce2456cf260efee9e8d8aeeddb3d068f37 +MD = 83eeed2dfeb8d2604ab5ec1ac9b5dcab8cc2222518468bc5c24c16ce72e70687 + +Len = 448 +Msg = 2fc7b9e8b8dcaac64ecef4c5f91877543ac36ae494d9faf84b1d347b6cf925570db84043d6f500dcc153cef81d6f2437d913f3dbffad42d9 +MD = 6ef7e9f12267ebc4901267da147effdcdebcd6ec5393c7f62ec4c4f06ca72649 + +Len = 456 +Msg = cf95929ab732f9ef5e8c3e6b4ed753852ee74e4fddf31b56c29a6ec95d23fcde2209eb7288b787f05d9036735c32ae2f01fc650d9cce4995a5 +MD = 3e5854169da065407fa465a4694f3fcb1d141480a8f84c970a0f63364ec8f590 + +Len = 464 +Msg = 826378013988684c40f4d917c7ed8b72aba66fd68f085d0b2eb20948ef3f349dbbc71f8e0ba845014586495a48902ee44505c673d2f76d473950 +MD = 5b506b823ef6658939aca22f52bbe5a4b849c31b8fa1d09139352e501137bc04 + +Len = 472 +Msg = 0cab6d38ce9849fcbd589f7235a6d2c2cb933e26e1ca6f4e78189104452c280c069b024e162769373f409d5cd0cb8160f0239418325d23ee6ad1bd +MD = 92943076cda4c46718e55df64d7580e12b8fb2c2911e87851246ccf6791fa3e6 + +Len = 480 +Msg = 3fb4a8c5b57c14731179256608614c95c9725ddad5fbfa99111d4fa319d3015ad830601556e8e4c6d012d7da0e2c4f60f1605f6e4c058ec0f46988a3 +MD = 8e90da3eb146935264576f874fcc5a64b7a90ab6c8a36c15d855b0179f52f899 + +Len = 488 +Msg = 9050a6d002c90f6036c592b0f6b866713e7894d29645f4a19e0858b3ebd8078711c26d2601ca104d962dc6ce6ae92634ee7f3ca6baf8810e2126097a09 +MD = 03c516677735ae83dbe5a7e4c22c1ac1bfedcd46e7dd785f8bfe38e148eda632 + +Len = 496 +Msg = d659ec136bacfa0b5c906aabedc93c01c5f1efa3f370a1432ea8778461703f0c67c454da12bac2da73b8abb755e5eaf10bddf52f6ca908d61bee80da0c64 +MD = fff2852957a0eeb577e73fd7d827f650261dfb9a8a65f52df4bbbc9b2d0ae50e + +Len = 504 +Msg = b498555658332b197bc5cb7adc5c1997aabbdcf1f7ffcc2b6b82eb0f350019d247f8e399c3559d3bb04eb049f28b344c7989c24db83f839b59028dc82fa670 +MD = bfbbf242f79bff4ae0aafb4ccf69b24fdca4342d83db1dfd1822c74a9e218e8d + +Len = 512 +Msg = 3592ecfd1eac618fd390e7a9c24b656532509367c21a0eac1212ac83c0b20cd896eb72b801c4d212c5452bbbf09317b50c5c9fb1997553d2bbc29bb42f5748ad +MD = 105a60865830ac3a371d3843324d4bb5fa8ec0e02ddaa389ad8da4f10215c454 + diff --git a/src/pycryptopp/testvectors/kat-ed25519-short.txt b/src/pycryptopp/testvectors/kat-ed25519-short.txt new file mode 100644 index 0000000..237721d --- /dev/null +++ b/src/pycryptopp/testvectors/kat-ed25519-short.txt @@ -0,0 +1,100 @@ +9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a:d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a::e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b: +4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c:3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c:72:92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c0072: +c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025:fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025:af82:6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40aaf82: +0d4a05b07352a5436e180356da0ae6efa0345ff7fb1572575772e8005ed978e9e61a185bcef2613a6c7cb79763ce945d3b245d76114dd440bcf5f2dc1aa57057:e61a185bcef2613a6c7cb79763ce945d3b245d76114dd440bcf5f2dc1aa57057:cbc77b:d9868d52c2bebce5f3fa5a79891970f309cb6591e3e1702a70276fa97c24b3a8e58606c38c9758529da50ee31b8219cba45271c689afa60b0ea26c99db19b00ccbc77b: +6df9340c138cc188b5fe4464ebaa3f7fc206a2d55c3434707e74c9fc04e20ebbc0dac102c4533186e25dc43128472353eaabdb878b152aeb8e001f92d90233a7:c0dac102c4533186e25dc43128472353eaabdb878b152aeb8e001f92d90233a7:5f4c8989:124f6fc6b0d100842769e71bd530664d888df8507df6c56dedfdb509aeb93416e26b918d38aa06305df3095697c18b2aa832eaa52edc0ae49fbae5a85e150c075f4c8989: +b780381a65edf8b78f6945e8dbec7941ac049fd4c61040cf0c324357975a293ce253af0766804b869bb1595be9765b534886bbaab8305bf50dbc7f899bfb5f01:e253af0766804b869bb1595be9765b534886bbaab8305bf50dbc7f899bfb5f01:18b6bec097:b2fc46ad47af464478c199e1f8be169f1be6327c7f9a0a6689371ca94caf04064a01b22aff1520abd58951341603faed768cf78ce97ae7b038abfe456aa17c0918b6bec097: +78ae9effe6f245e924a7be63041146ebc670dbd3060cba67fbc6216febc44546fbcfbfa40505d7f2be444a33d185cc54e16d615260e1640b2b5087b83ee3643d:fbcfbfa40505d7f2be444a33d185cc54e16d615260e1640b2b5087b83ee3643d:89010d855972:6ed629fc1d9ce9e1468755ff636d5a3f40a5d9c91afd93b79d241830f7e5fa29854b8f20cc6eecbb248dbd8d16d14e99752194e4904d09c74d639518839d230089010d855972: +691865bfc82a1e4b574eecde4c7519093faf0cf867380234e3664645c61c5f7998a5e3a36e67aaba89888bf093de1ad963e774013b3902bfab356d8b90178a63:98a5e3a36e67aaba89888bf093de1ad963e774013b3902bfab356d8b90178a63:b4a8f381e70e7a:6e0af2fe55ae377a6b7a7278edfb419bd321e06d0df5e27037db8812e7e3529810fa5552f6c0020985ca17a0e02e036d7b222a24f99b77b75fdd16cb05568107b4a8f381e70e7a: +3b26516fb3dc88eb181b9ed73f0bcd52bcd6b4c788e4bcaf46057fd078bee073f81fb54a825fced95eb033afcd64314075abfb0abd20a970892503436f34b863:f81fb54a825fced95eb033afcd64314075abfb0abd20a970892503436f34b863:4284abc51bb67235:d6addec5afb0528ac17bb178d3e7f2887f9adbb1ad16e110545ef3bc57f9de2314a5c8388f723b8907be0f3ac90c6259bbe885ecc17645df3db7d488f805fa084284abc51bb67235: +edc6f5fbdd1cee4d101c063530a30490b221be68c036f5b07d0f953b745df192c1a49c66e617f9ef5ec66bc4c6564ca33de2a5fb5e1464062e6d6c6219155efd:c1a49c66e617f9ef5ec66bc4c6564ca33de2a5fb5e1464062e6d6c6219155efd:672bf8965d04bc5146:2c76a04af2391c147082e33faacdbe56642a1e134bd388620b852b901a6bc16ff6c9cc9404c41dea12ed281da067a1513866f9d964f8bdd24953856c50042901672bf8965d04bc5146: +4e7d21fb3b1897571a445833be0f9fd41cd62be3aa04040f8934e1fcbdcacd4531b2524b8348f7ab1dfafa675cc538e9a84e3fe5819e27c12ad8bbc1a36e4dff:31b2524b8348f7ab1dfafa675cc538e9a84e3fe5819e27c12ad8bbc1a36e4dff:33d7a786aded8c1bf691:28e4598c415ae9de01f03f9f3fab4e919e8bf537dd2b0cdf6e79b9e6559c9409d9151a4c40f083193937627c369488259e99da5a9f0a87497fa6696a5dd6ce0833d7a786aded8c1bf691: +a980f892db13c99a3e8971e965b2ff3d41eafd54093bc9f34d1fd22d84115bb644b57ee30cdb55829d0a5d4f046baef078f1e97a7f21b62d75f8e96ea139c35f:44b57ee30cdb55829d0a5d4f046baef078f1e97a7f21b62d75f8e96ea139c35f:3486f68848a65a0eb5507d:77d389e599630d934076329583cd4105a649a9292abc44cd28c40000c8e2f5ac7660a81c85b72af8452d7d25c070861dae91601c7803d656531650dd4e5c41003486f68848a65a0eb5507d: +5b5a619f8ce1c66d7ce26e5a2ae7b0c04febcd346d286c929e19d0d5973bfef96fe83693d011d111131c4f3fbaaa40a9d3d76b30012ff73bb0e39ec27ab18257:6fe83693d011d111131c4f3fbaaa40a9d3d76b30012ff73bb0e39ec27ab18257:5a8d9d0a22357e6655f9c785:0f9ad9793033a2fa06614b277d37381e6d94f65ac2a5a94558d09ed6ce922258c1a567952e863ac94297aec3c0d0c8ddf71084e504860bb6ba27449b55adc40e5a8d9d0a22357e6655f9c785: +940c89fe40a81dafbdb2416d14ae469119869744410c3303bfaa0241dac57800a2eb8c0501e30bae0cf842d2bde8dec7386f6b7fc3981b8c57c9792bb94cf2dd:a2eb8c0501e30bae0cf842d2bde8dec7386f6b7fc3981b8c57c9792bb94cf2dd:b87d3813e03f58cf19fd0b6395:d8bb64aad8c9955a115a793addd24f7f2b077648714f49c4694ec995b330d09d640df310f447fd7b6cb5c14f9fe9f490bcf8cfadbfd2169c8ac20d3b8af49a0cb87d3813e03f58cf19fd0b6395: +9acad959d216212d789a119252ebfe0c96512a23c73bd9f3b202292d6916a738cf3af898467a5b7a52d33d53bc037e2642a8da996903fc252217e9c033e2f291:cf3af898467a5b7a52d33d53bc037e2642a8da996903fc252217e9c033e2f291:55c7fa434f5ed8cdec2b7aeac173:6ee3fe81e23c60eb2312b2006b3b25e6838e02106623f844c44edb8dafd66ab0671087fd195df5b8f58a1d6e52af42908053d55c7321010092748795ef94cf0655c7fa434f5ed8cdec2b7aeac173: +d5aeee41eeb0e9d1bf8337f939587ebe296161e6bf5209f591ec939e1440c300fd2a565723163e29f53c9de3d5e8fbe36a7ab66e1439ec4eae9c0a604af291a5:fd2a565723163e29f53c9de3d5e8fbe36a7ab66e1439ec4eae9c0a604af291a5:0a688e79be24f866286d4646b5d81c:f68d04847e5b249737899c014d31c805c5007a62c0a10d50bb1538c5f35503951fbc1e08682f2cc0c92efe8f4985dec61dcbd54d4b94a22547d24451271c8b000a688e79be24f866286d4646b5d81c: +0a47d10452ae2febec518a1c7c362890c3fc1a49d34b03b6467d35c904a8362d34e5a8508c4743746962c066e4badea2201b8ab484de5c4f94476ccd2143955b:34e5a8508c4743746962c066e4badea2201b8ab484de5c4f94476ccd2143955b:c942fa7ac6b23ab7ff612fdc8e68ef39:2a3d27dc40d0a8127949a3b7f908b3688f63b7f14f651aacd715940bdbe27a0809aac142f47ab0e1e44fa490ba87ce5392f33a891539caf1ef4c367cae54500cc942fa7ac6b23ab7ff612fdc8e68ef39: +f8148f7506b775ef46fdc8e8c756516812d47d6cfbfa318c27c9a22641e56f170445e456dacc7d5b0bbed23c8200cdb74bdcb03e4c7b73f0a2b9b46eac5d4372:0445e456dacc7d5b0bbed23c8200cdb74bdcb03e4c7b73f0a2b9b46eac5d4372:7368724a5b0efb57d28d97622dbde725af:3653ccb21219202b8436fb41a32ba2618c4a133431e6e63463ceb3b6106c4d56e1d2ba165ba76eaad3dc39bffb130f1de3d8e6427db5b71938db4e272bc3e20b7368724a5b0efb57d28d97622dbde725af: +77f88691c4eff23ebb7364947092951a5ff3f10785b417e918823a552dab7c7574d29127f199d86a8676aec33b4ce3f225ccb191f52c191ccd1e8cca65213a6b:74d29127f199d86a8676aec33b4ce3f225ccb191f52c191ccd1e8cca65213a6b:bd8e05033f3a8bcdcbf4beceb70901c82e31:fbe929d743a03c17910575492f3092ee2a2bf14a60a3fcacec74a58c7334510fc262db582791322d6c8c41f1700adb80027ecabc14270b703444ae3ee7623e0abd8e05033f3a8bcdcbf4beceb70901c82e31: +ab6f7aee6a0837b334ba5eb1b2ad7fcecfab7e323cab187fe2e0a95d80eff1325b96dca497875bf9664c5e75facf3f9bc54bae913d66ca15ee85f1491ca24d2c:5b96dca497875bf9664c5e75facf3f9bc54bae913d66ca15ee85f1491ca24d2c:8171456f8b907189b1d779e26bc5afbb08c67a:73bca64e9dd0db88138eedfafcea8f5436cfb74bfb0e7733cf349baa0c49775c56d5934e1d38e36f39b7c5beb0a836510c45126f8ec4b6810519905b0ca07c098171456f8b907189b1d779e26bc5afbb08c67a: +8d135de7c8411bbdbd1b31e5dc678f2ac7109e792b60f38cd24936e8a898c32d1ca281938529896535a7714e3584085b86ef9fec723f42819fc8dd5d8c00817f:1ca281938529896535a7714e3584085b86ef9fec723f42819fc8dd5d8c00817f:8ba6a4c9a15a244a9c26bb2a59b1026f21348b49:a1adc2bc6a2d980662677e7fdff6424de7dba50f5795ca90fdf3e96e256f3285cac71d3360482e993d0294ba4ec7440c61affdf35fe83e6e04263937db93f1058ba6a4c9a15a244a9c26bb2a59b1026f21348b49: +0e765d720e705f9366c1ab8c3fa84c9a44370c06969f803296884b2846a652a47fae45dd0a05971026d410bc497af5be7d0827a82a145c203f625dfcb8b03ba8:7fae45dd0a05971026d410bc497af5be7d0827a82a145c203f625dfcb8b03ba8:1d566a6232bbaab3e6d8804bb518a498ed0f904986:bb61cf84de61862207c6a455258bc4db4e15eea0317ff88718b882a06b5cf6ec6fd20c5a269e5d5c805bafbcc579e2590af414c7c227273c102a10070cdfe80f1d566a6232bbaab3e6d8804bb518a498ed0f904986: +db36e326d676c2d19cc8fe0c14b709202ecfc761d27089eb6ea4b1bb021ecfa748359b850d23f0715d94bb8bb75e7e14322eaf14f06f28a805403fbda002fc85:48359b850d23f0715d94bb8bb75e7e14322eaf14f06f28a805403fbda002fc85:1b0afb0ac4ba9ab7b7172cddc9eb42bba1a64bce47d4:b6dcd09989dfbac54322a3ce87876e1d62134da998c79d24b50bd7a6a797d86a0e14dc9d7491d6c14a673c652cfbec9f962a38c945da3b2f0879d0b68a9213001b0afb0ac4ba9ab7b7172cddc9eb42bba1a64bce47d4: +c89955e0f7741d905df0730b3dc2b0ce1a13134e44fef3d40d60c020ef19df77fdb30673402faf1c8033714f3517e47cc0f91fe70cf3836d6c23636e3fd2287c:fdb30673402faf1c8033714f3517e47cc0f91fe70cf3836d6c23636e3fd2287c:507c94c8820d2a5793cbf3442b3d71936f35fe3afef316:7ef66e5e86f2360848e0014e94880ae2920ad8a3185a46b35d1e07dea8fa8ae4f6b843ba174d99fa7986654a0891c12a794455669375bf92af4cc2770b579e0c507c94c8820d2a5793cbf3442b3d71936f35fe3afef316: +4e62627fc221142478aee7f00781f817f662e3b75db29bb14ab47cf8e84104d6b1d39801892027d58a8c64335163195893bfc1b61dbeca3260497e1f30371107:b1d39801892027d58a8c64335163195893bfc1b61dbeca3260497e1f30371107:d3d615a8472d9962bb70c5b5466a3d983a4811046e2a0ef5:836afa764d9c48aa4770a4388b654e97b3c16f082967febca27f2fc47ddfd9244b03cfc729698acf5109704346b60b230f255430089ddc56912399d1122de70ad3d615a8472d9962bb70c5b5466a3d983a4811046e2a0ef5: +6b83d7da8908c3e7205b39864b56e5f3e17196a3fc9c2f5805aad0f5554c142dd0c846f97fe28585c0ee159015d64c56311c886eddcc185d296dbb165d2625d6:d0c846f97fe28585c0ee159015d64c56311c886eddcc185d296dbb165d2625d6:6ada80b6fa84f7034920789e8536b82d5e4678059aed27f71c:16e462a29a6dd498685a3718b3eed00cc1598601ee47820486032d6b9acc9bf89f57684e08d8c0f05589cda2882a05dc4c63f9d0431d6552710812433003bc086ada80b6fa84f7034920789e8536b82d5e4678059aed27f71c: +19a91fe23a4e9e33ecc474878f57c64cf154b394203487a7035e1ad9cd697b0d2bf32ba142ba4622d8f3e29ecd85eea07b9c47be9d64412c9b510b27dd218b23:2bf32ba142ba4622d8f3e29ecd85eea07b9c47be9d64412c9b510b27dd218b23:82cb53c4d5a013bae5070759ec06c3c6955ab7a4050958ec328c:881f5b8c5a030df0f75b6634b070dd27bd1ee3c08738ae349338b3ee6469bbf9760b13578a237d5182535ede121283027a90b5f865d63a6537dca07b44049a0f82cb53c4d5a013bae5070759ec06c3c6955ab7a4050958ec328c: +1d5b8cb6215c18141666baeefcf5d69dad5bea9a3493dddaa357a4397a13d4de94d23d977c33e49e5e4992c68f25ec99a27c41ce6b91f2bfa0cd8292fe962835:94d23d977c33e49e5e4992c68f25ec99a27c41ce6b91f2bfa0cd8292fe962835:a9a8cbb0ad585124e522abbfb40533bdd6f49347b55b18e8558cb0:3acd39bec8c3cd2b44299722b5850a0400c1443590fd4861d59aae7496acb3df73fc3fdf7969ae5f50ba47dddc435246e5fd376f6b891cd4c2caf5d614b6170ca9a8cbb0ad585124e522abbfb40533bdd6f49347b55b18e8558cb0: +6a91b3227c472299089bdce9356e726a40efd840f11002708b7ee55b64105ac29d084aa8b97a6b9bafa496dbc6f76f3306a116c9d917e681520a0f914369427e:9d084aa8b97a6b9bafa496dbc6f76f3306a116c9d917e681520a0f914369427e:5cb6f9aa59b80eca14f6a68fb40cf07b794e75171fba96262c1c6adc:f5875423781b66216cb5e8998de5d9ffc29d1d67107054ace3374503a9c3ef811577f269de81296744bd706f1ac478caf09b54cdf871b3f802bd57f9a6cb91015cb6f9aa59b80eca14f6a68fb40cf07b794e75171fba96262c1c6adc: +93eaa854d791f05372ce72b94fc6503b2ff8ae6819e6a21afe825e27ada9e4fb16cee8a3f2631834c88b670897ff0b08ce90cc147b4593b3f1f403727f7e7ad5:16cee8a3f2631834c88b670897ff0b08ce90cc147b4593b3f1f403727f7e7ad5:32fe27994124202153b5c70d3813fdee9c2aa6e7dc743d4d535f1840a5:d834197c1a3080614e0a5fa0aaaa808824f21c38d692e6ffbd200f7dfb3c8f44402a7382180b98ad0afc8eec1a02acecf3cb7fde627b9f18111f260ab1db9a0732fe27994124202153b5c70d3813fdee9c2aa6e7dc743d4d535f1840a5: +941cac69fb7b1815c57bb987c4d6c2ad2c35d5f9a3182a79d4ba13eab253a8ad23be323c562dfd71ce65f5bba56a74a3a6dfc36b573d2f94f635c7f9b4fd5a5b:23be323c562dfd71ce65f5bba56a74a3a6dfc36b573d2f94f635c7f9b4fd5a5b:bb3172795710fe00054d3b5dfef8a11623582da68bf8e46d72d27cece2aa:0f8fad1e6bde771b4f5420eac75c378bae6db5ac6650cd2bc210c1823b432b48e016b10595458ffab92f7a8989b293ceb8dfed6c243a2038fc06652aaaf16f02bb3172795710fe00054d3b5dfef8a11623582da68bf8e46d72d27cece2aa: +1acdbb793b0384934627470d795c3d1dd4d79cea59ef983f295b9b59179cbb283f60c7541afa76c019cf5aa82dcdb088ed9e4ed9780514aefb379dabc844f31a:3f60c7541afa76c019cf5aa82dcdb088ed9e4ed9780514aefb379dabc844f31a:7cf34f75c3dac9a804d0fcd09eba9b29c9484e8a018fa9e073042df88e3c56:be71ef4806cb041d885effd9e6b0fbb73d65d7cdec47a89c8a994892f4e55a568c4cc78d61f901e80dbb628b86a23ccd594e712b57fa94c2d67ec266348785077cf34f75c3dac9a804d0fcd09eba9b29c9484e8a018fa9e073042df88e3c56: +8ed7a797b9cea8a8370d419136bcdf683b759d2e3c6947f17e13e2485aa9d420b49f3a78b1c6a7fca8f3466f33bc0e929f01fba04306c2a7465f46c3759316d9:b49f3a78b1c6a7fca8f3466f33bc0e929f01fba04306c2a7465f46c3759316d9:a750c232933dc14b1184d86d8b4ce72e16d69744ba69818b6ac33b1d823bb2c3:04266c033b91c1322ceb3446c901ffcf3cc40c4034e887c9597ca1893ba7330becbbd8b48142ef35c012c6ba51a66df9308cb6268ad6b1e4b03e70102495790ba750c232933dc14b1184d86d8b4ce72e16d69744ba69818b6ac33b1d823bb2c3: +f2ab396fe8906e3e5633e99cabcd5b09df0859b516230b1e0450b580b65f616c8ea074245159a116aa7122a25ec16b891d625a68f33660423908f6bdc44f8c1b:8ea074245159a116aa7122a25ec16b891d625a68f33660423908f6bdc44f8c1b:5a44e34b746c5fd1898d552ab354d28fb4713856d7697dd63eb9bd6b99c280e187:a06a23d982d81ab883aae230adbc368a6a9977f003cebb00d4c2e4018490191a84d3a282fdbfb2fc88046e62de43e15fb575336b3c8b77d19ce6a009ce51f50c5a44e34b746c5fd1898d552ab354d28fb4713856d7697dd63eb9bd6b99c280e187: +550a41c013f79bab8f06e43ad1836d51312736a9713806fafe6645219eaa1f9daf6b7145474dc9954b9af93a9cdb34449d5b7c651c824d24e230b90033ce59c0:af6b7145474dc9954b9af93a9cdb34449d5b7c651c824d24e230b90033ce59c0:8bc4185e50e57d5f87f47515fe2b1837d585f0aae9e1ca383b3ec908884bb900ff27:16dc1e2b9fa909eefdc277ba16ebe207b8da5e91143cde78c5047a89f681c33c4e4e3428d5c928095903a811ec002d52a39ed7f8b3fe1927200c6dd0b9ab3e048bc4185e50e57d5f87f47515fe2b1837d585f0aae9e1ca383b3ec908884bb900ff27: +19ac3e272438c72ddf7b881964867cb3b31ff4c793bb7ea154613c1db068cb7ef85b80e050a1b9620db138bfc9e100327e25c257c59217b601f1f6ac9a413d3f:f85b80e050a1b9620db138bfc9e100327e25c257c59217b601f1f6ac9a413d3f:95872d5f789f95484e30cbb0e114028953b16f5c6a8d9f65c003a83543beaa46b38645:ea855d781cbea4682e350173cb89e8619ccfddb97cdce16f9a2f6f6892f46dbe68e04b12b8d88689a7a31670cdff409af98a93b49a34537b6aa009d2eb8b470195872d5f789f95484e30cbb0e114028953b16f5c6a8d9f65c003a83543beaa46b38645: +ca267de96c93c238fafb1279812059ab93ac03059657fd994f8fa5a09239c821017370c879090a81c7f272c2fc80e3aac2bc603fcb379afc98691160ab745b26:017370c879090a81c7f272c2fc80e3aac2bc603fcb379afc98691160ab745b26:e05f71e4e49a72ec550c44a3b85aca8f20ff26c3ee94a80f1b431c7d154ec9603ee02531:ac957f82335aa7141e96b59d63e3ccee95c3a2c47d026540c2af42dc9533d5fd81827d1679ad187aeaf37834915e75b147a9286806c8017516ba43dd051a5e0ce05f71e4e49a72ec550c44a3b85aca8f20ff26c3ee94a80f1b431c7d154ec9603ee02531: +3dff5e899475e7e91dd261322fab09980c52970de1da6e2e201660cc4fce7032f30162bac98447c4042fac05da448034629be2c6a58d30dfd578ba9fb5e3930b:f30162bac98447c4042fac05da448034629be2c6a58d30dfd578ba9fb5e3930b:938f0e77621bf3ea52c7c4911c5157c2d8a2a858093ef16aa9b107e69d98037ba139a3c382:5efe7a92ff9623089b3e3b78f352115366e26ba3fb1a416209bc029e9cadccd9f4affa333555a8f3a35a9d0f7c34b292cae77ec96fa3adfcaadee2d9ced8f805938f0e77621bf3ea52c7c4911c5157c2d8a2a858093ef16aa9b107e69d98037ba139a3c382: +9a6b847864e70cfe8ba6ab22fa0ca308c0cc8bec7141fbcaa3b81f5d1e1cfcfc34ad0fbdb2566507a81c2b1f8aa8f53dccaa64cc87ada91b903e900d07eee930:34ad0fbdb2566507a81c2b1f8aa8f53dccaa64cc87ada91b903e900d07eee930:838367471183c71f7e717724f89d401c3ad9863fd9cc7aa3cf33d3c529860cb581f3093d87da:2ab255169c489c54c732232e37c87349d486b1eba20509dbabe7fed329ef08fd75ba1cd145e67b2ea26cb5cc51cab343eeb085fe1fd7b0ec4c6afcd9b979f905838367471183c71f7e717724f89d401c3ad9863fd9cc7aa3cf33d3c529860cb581f3093d87da: +575be07afca5d063c238cd9b8028772cc49cda34471432a2e166e096e2219efc94e5eb4d5024f49d7ebf79817c8de11497dc2b55622a51ae123ffc749dbb16e0:94e5eb4d5024f49d7ebf79817c8de11497dc2b55622a51ae123ffc749dbb16e0:33e5918b66d33d55fe717ca34383eae78f0af82889caf6696e1ac9d95d1ffb32cba755f9e3503e:58271d44236f3b98c58fd7ae0d2f49ef2b6e3affdb225aa3ba555f0e11cc53c23ad19baf24346590d05d7d5390582082cf94d39cad6530ab93d13efb3927950633e5918b66d33d55fe717ca34383eae78f0af82889caf6696e1ac9d95d1ffb32cba755f9e3503e: +15ffb45514d43444d61fcb105e30e135fd268523dda20b82758b1794231104411772c5abc2d23fd2f9d1c3257be7bc3c1cd79cee40844b749b3a7743d2f964b8:1772c5abc2d23fd2f9d1c3257be7bc3c1cd79cee40844b749b3a7743d2f964b8:da9c5559d0ea51d255b6bd9d7638b876472f942b330fc0e2b30aea68d77368fce4948272991d257e:6828cd7624e793b8a4ceb96d3c2a975bf773e5ff6645f353614058621e58835289e7f31f42dfe6af6d736f2644511e320c0fa698582a79778d18730ed3e8cb08da9c5559d0ea51d255b6bd9d7638b876472f942b330fc0e2b30aea68d77368fce4948272991d257e: +fe0568642943b2e1afbfd1f10fe8df87a4236bea40dce742072cb21886eec1fa299ebd1f13177dbdb66a912bbf712038fdf73b06c3ac020c7b19126755d47f61:299ebd1f13177dbdb66a912bbf712038fdf73b06c3ac020c7b19126755d47f61:c59d0862ec1c9746abcc3cf83c9eeba2c7082a036a8cb57ce487e763492796d47e6e063a0c1feccc2d:d59e6dfcc6d7e3e2c58dec81e985d245e681acf6594a23c59214f7bed8015d813c7682b60b3583440311e72a8665ba2c96dec23ce826e160127e18132b030404c59d0862ec1c9746abcc3cf83c9eeba2c7082a036a8cb57ce487e763492796d47e6e063a0c1feccc2d: +5ecb16c2df27c8cf58e436a9d3affbd58e9538a92659a0f97c4c4f994635a8cada768b20c437dd3aa5f84bb6a077ffa34ab68501c5352b5cc3fdce7fe6c2398d:da768b20c437dd3aa5f84bb6a077ffa34ab68501c5352b5cc3fdce7fe6c2398d:56f1329d9a6be25a6159c72f12688dc8314e85dd9e7e4dc05bbecb7729e023c86f8e0937353f27c7ede9:1c723a20c6772426a670e4d5c4a97c6ebe9147f71bb0a415631e44406e290322e4ca977d348fe7856a8edc235d0fe95f7ed91aefddf28a77e2c7dbfd8f552f0a56f1329d9a6be25a6159c72f12688dc8314e85dd9e7e4dc05bbecb7729e023c86f8e0937353f27c7ede9: +d599d637b3c30a82a9984e2f758497d144de6f06b9fba04dd40fd949039d7c846791d8ce50a44689fc178727c5c3a1c959fbeed74ef7d8e7bd3c1ab4da31c51f:6791d8ce50a44689fc178727c5c3a1c959fbeed74ef7d8e7bd3c1ab4da31c51f:a7c04e8ba75d0a03d8b166ad7a1d77e1b91c7aaf7befdd99311fc3c54a684ddd971d5b3211c3eeaff1e54e:ebf10d9ac7c96108140e7def6fe9533d727646ff5b3af273c1df95762a66f32b65a09634d013f54b5dd6011f91bc336ca8b355ce33f8cfbec2535a4c427f8205a7c04e8ba75d0a03d8b166ad7a1d77e1b91c7aaf7befdd99311fc3c54a684ddd971d5b3211c3eeaff1e54e: +30ab8232fa7018f0ce6c39bd8f782fe2e159758bb0f2f4386c7f28cfd2c85898ecfb6a2bd42f31b61250ba5de7e46b4719afdfbc660db71a7bd1df7b0a3abe37:ecfb6a2bd42f31b61250ba5de7e46b4719afdfbc660db71a7bd1df7b0a3abe37:63b80b7956acbecf0c35e9ab06b914b0c7014fe1a4bbc0217240c1a33095d707953ed77b15d211adaf9b97dc:9af885344cc7239498f712df80bc01b80638291ed4a1d28baa5545017a72e2f65649ccf9603da6eb5bfab9f5543a6ca4a7af3866153c76bf66bf95def615b00c63b80b7956acbecf0c35e9ab06b914b0c7014fe1a4bbc0217240c1a33095d707953ed77b15d211adaf9b97dc: +0ddcdc872c7b748d40efe96c2881ae189d87f56148ed8af3ebbbc80324e38bdd588ddadcbcedf40df0e9697d8bb277c7bb1498fa1d26ce0a835a760b92ca7c85:588ddadcbcedf40df0e9697d8bb277c7bb1498fa1d26ce0a835a760b92ca7c85:65641cd402add8bf3d1d67dbeb6d41debfbef67e4317c35b0a6d5bbbae0e034de7d670ba1413d056f2d6f1de12:c179c09456e235fe24105afa6e8ec04637f8f943817cd098ba95387f9653b2add181a31447d92d1a1ddf1ceb0db62118de9dffb7dcd2424057cbdff5d41d040365641cd402add8bf3d1d67dbeb6d41debfbef67e4317c35b0a6d5bbbae0e034de7d670ba1413d056f2d6f1de12: +89f0d68299ba0a5a83f248ae0c169f8e3849a9b47bd4549884305c9912b46603aba3e795aab2012acceadd7b3bd9daeeed6ff5258bdcd7c93699c2a3836e3832:aba3e795aab2012acceadd7b3bd9daeeed6ff5258bdcd7c93699c2a3836e3832:4f1846dd7ad50e545d4cfbffbb1dc2ff145dc123754d08af4e44ecc0bc8c91411388bc7653e2d893d1eac2107d05:2c691fa8d487ce20d5d2fa41559116e0bbf4397cf5240e152556183541d66cf753582401a4388d390339dbef4d384743caa346f55f8daba68ba7b9131a8a6e0b4f1846dd7ad50e545d4cfbffbb1dc2ff145dc123754d08af4e44ecc0bc8c91411388bc7653e2d893d1eac2107d05: +0a3c1844e2db070fb24e3c95cb1cc6714ef84e2ccd2b9dd2f1460ebf7ecf13b172e409937e0610eb5c20b326dc6ea1bbbc0406701c5cd67d1fbde09192b07c01:72e409937e0610eb5c20b326dc6ea1bbbc0406701c5cd67d1fbde09192b07c01:4c8274d0ed1f74e2c86c08d955bde55b2d54327e82062a1f71f70d536fdc8722cdead7d22aaead2bfaa1ad00b82957:87f7fdf46095201e877a588fe3e5aaf476bd63138d8a878b89d6ac60631b3458b9d41a3c61a588e1db8d29a5968981b018776c588780922f5aa732ba6379dd054c8274d0ed1f74e2c86c08d955bde55b2d54327e82062a1f71f70d536fdc8722cdead7d22aaead2bfaa1ad00b82957: +c8d7a8818b98dfdb20839c871cb5c48e9e9470ca3ad35ba2613a5d3199c8ab2390d2efbba4d43e6b2b992ca16083dbcfa2b322383907b0ee75f3e95845d3c47f:90d2efbba4d43e6b2b992ca16083dbcfa2b322383907b0ee75f3e95845d3c47f:783e33c3acbdbb36e819f544a7781d83fc283d3309f5d3d12c8dcd6b0b3d0e89e38cfd3b4d0885661ca547fb9764abff:fa2e994421aef1d5856674813d05cbd2cf84ef5eb424af6ecd0dc6fdbdc2fe605fe985883312ecf34f59bfb2f1c9149e5b9cc9ecda05b2731130f3ed28ddae0b783e33c3acbdbb36e819f544a7781d83fc283d3309f5d3d12c8dcd6b0b3d0e89e38cfd3b4d0885661ca547fb9764abff: +b482703612d0c586f76cfcb21cfd2103c957251504a8c0ac4c86c9c6f3e429fffd711dc7dd3b1dfb9df9704be3e6b26f587fe7dd7ba456a91ba43fe51aec09ad:fd711dc7dd3b1dfb9df9704be3e6b26f587fe7dd7ba456a91ba43fe51aec09ad:29d77acfd99c7a0070a88feb6247a2bce9984fe3e6fbf19d4045042a21ab26cbd771e184a9a75f316b648c6920db92b87b:58832bdeb26feafc31b46277cf3fb5d7a17dfb7ccd9b1f58ecbe6feb979666828f239ba4d75219260ecac0acf40f0e5e2590f4caa16bbbcd8a155d347967a60729d77acfd99c7a0070a88feb6247a2bce9984fe3e6fbf19d4045042a21ab26cbd771e184a9a75f316b648c6920db92b87b: +84e50dd9a0f197e3893c38dbd91fafc344c1776d3a400e2f0f0ee7aa829eb8a22c50f870ee48b36b0ac2f8a5f336fb090b113050dbcc25e078200a6e16153eea:2c50f870ee48b36b0ac2f8a5f336fb090b113050dbcc25e078200a6e16153eea:f3992cde6493e671f1e129ddca8038b0abdb77bb9035f9f8be54bd5d68c1aeff724ff47d29344391dc536166b8671cbbf123:69e6a4491a63837316e86a5f4ba7cd0d731ecc58f1d0a264c67c89befdd8d3829d8de13b33cc0bf513931715c7809657e2bfb960e5c764c971d733746093e500f3992cde6493e671f1e129ddca8038b0abdb77bb9035f9f8be54bd5d68c1aeff724ff47d29344391dc536166b8671cbbf123: +b322d46577a2a991a4d1698287832a39c487ef776b4bff037a05c7f1812bdeeceb2bcadfd3eec2986baff32b98e7c4dbf03ff95d8ad5ff9aa9506e5472ff845f:eb2bcadfd3eec2986baff32b98e7c4dbf03ff95d8ad5ff9aa9506e5472ff845f:19f1bf5dcf1750c611f1c4a2865200504d82298edd72671f62a7b1471ac3d4a30f7de9e5da4108c52a4ce70a3e114a52a3b3c5:c7b55137317ca21e33489ff6a9bfab97c855dc6f85684a70a9125a261b56d5e6f149c5774d734f2d8debfc77b721896a8267c23768e9badb910eef83ec25880219f1bf5dcf1750c611f1c4a2865200504d82298edd72671f62a7b1471ac3d4a30f7de9e5da4108c52a4ce70a3e114a52a3b3c5: +960cab5034b9838d098d2dcbf4364bec16d388f6376d73a6273b70f82bbc98c05e3c19f2415acf729f829a4ebd5c40e1a6bc9fbca95703a9376087ed0937e51a:5e3c19f2415acf729f829a4ebd5c40e1a6bc9fbca95703a9376087ed0937e51a:f8b21962447b0a8f2e4279de411bea128e0be44b6915e6cda88341a68a0d818357db938eac73e0af6d31206b3948f8c48a447308:27d4c3a1811ef9d4360b3bdd133c2ccc30d02c2f248215776cb07ee4177f9b13fc42dd70a6c2fed8f225c7663c7f182e7ee8eccff20dc7b0e1d5834ec5b1ea01f8b21962447b0a8f2e4279de411bea128e0be44b6915e6cda88341a68a0d818357db938eac73e0af6d31206b3948f8c48a447308: +eb77b2638f23eebc82efe45ee9e5a0326637401e663ed029699b21e6443fb48e9ef27608961ac711de71a6e2d4d4663ea3ecd42fb7e4e8627c39622df4af0bbc:9ef27608961ac711de71a6e2d4d4663ea3ecd42fb7e4e8627c39622df4af0bbc:99e3d00934003ebafc3e9fdb687b0f5ff9d5782a4b1f56b9700046c077915602c3134e22fc90ed7e690fddd4433e2034dcb2dc99ab:18dc56d7bd9acd4f4daa78540b4ac8ff7aa9815f45a0bba370731a14eaabe96df8b5f37dbf8eae4cb15a64b244651e59d6a3d6761d9e3c50f2d0cbb09c05ec0699e3d00934003ebafc3e9fdb687b0f5ff9d5782a4b1f56b9700046c077915602c3134e22fc90ed7e690fddd4433e2034dcb2dc99ab: +b625aa89d3f7308715427b6c39bbac58effd3a0fb7316f7a22b99ee5922f2dc965a99c3e16fea894ec33c6b20d9105e2a04e2764a4769d9bbd4d8bacfeab4a2e:65a99c3e16fea894ec33c6b20d9105e2a04e2764a4769d9bbd4d8bacfeab4a2e:e07241dbd3adbe610bbe4d005dd46732a4c25086ecb8ec29cd7bca116e1bf9f53bfbf3e11fa49018d39ff1154a06668ef7df5c678e6a:01bb901d83b8b682d3614af46a807ba2691358feb775325d3423f549ff0aa5757e4e1a74e9c70f9721d8f354b319d4f4a1d91445c870fd0ffb94fed64664730de07241dbd3adbe610bbe4d005dd46732a4c25086ecb8ec29cd7bca116e1bf9f53bfbf3e11fa49018d39ff1154a06668ef7df5c678e6a: +b1c9f8bd03fe82e78f5c0fb06450f27dacdf716434db268275df3e1dc177af427fc88b1f7b3f11c629be671c21621f5c10672fafc8492da885742059ee6774cf:7fc88b1f7b3f11c629be671c21621f5c10672fafc8492da885742059ee6774cf:331da7a9c1f87b2ac91ee3b86d06c29163c05ed6f8d8a9725b471b7db0d6acec7f0f702487163f5eda020ca5b493f399e1c8d308c3c0c2:4b229951ef262f16978f7914bc672e7226c5f8379d2778c5a2dc0a2650869f7acfbd0bcd30fdb0619bb44fc1ae5939b87cc318133009c20395b6c7eb98107701331da7a9c1f87b2ac91ee3b86d06c29163c05ed6f8d8a9725b471b7db0d6acec7f0f702487163f5eda020ca5b493f399e1c8d308c3c0c2: +6d8cdb2e075f3a2f86137214cb236ceb89a6728bb4a200806bf3557fb78fac6957a04c7a5113cddfe49a4c124691d46c1f9cdc8f343f9dcb72a1330aeca71fda:57a04c7a5113cddfe49a4c124691d46c1f9cdc8f343f9dcb72a1330aeca71fda:7f318dbd121c08bfddfeff4f6aff4e45793251f8abf658403358238984360054f2a862c5bb83ed89025d2014a7a0cee50da3cb0e76bbb6bf:a6cbc947f9c87d1455cf1a708528c090f11ecee4855d1dbaadf47454a4de55fa4ce84b36d73a5b5f8f59298ccf21992df492ef34163d87753b7e9d32f2c3660b7f318dbd121c08bfddfeff4f6aff4e45793251f8abf658403358238984360054f2a862c5bb83ed89025d2014a7a0cee50da3cb0e76bbb6bf: +47adc6d6bf571ee9570ca0f75b604ac43e303e4ab339ca9b53cacc5be45b2ccba3f527a1c1f17dfeed92277347c9f98ab475de1755b0ab546b8a15d01b9bd0be:a3f527a1c1f17dfeed92277347c9f98ab475de1755b0ab546b8a15d01b9bd0be:ce497c5ff5a77990b7d8f8699eb1f5d8c0582f70cb7ac5c54d9d924913278bc654d37ea227590e15202217fc98dac4c0f3be2183d133315739:4e8c318343c306adbba60c92b75cb0569b9219d8a86e5d57752ed235fc109a43c2cf4e942cacf297279fbb28675347e08027722a4eb7395e00a17495d32edf0bce497c5ff5a77990b7d8f8699eb1f5d8c0582f70cb7ac5c54d9d924913278bc654d37ea227590e15202217fc98dac4c0f3be2183d133315739: +3c19b50b0fe47961719c381d0d8da9b9869d312f13e3298b97fb22f0af29cbbe0f7eda091499625e2bae8536ea35cda5483bd16a9c7e416b341d6f2c83343612:0f7eda091499625e2bae8536ea35cda5483bd16a9c7e416b341d6f2c83343612:8ddcd63043f55ec3bfc83dceae69d8f8b32f4cdb6e2aebd94b4314f8fe7287dcb62732c9052e7557fe63534338efb5b6254c5d41d2690cf5144f:efbd41f26a5d62685516f882b6ec74e0d5a71830d203c231248f26e99a9c6578ec900d68cdb8fa7216ad0d24f9ecbc9ffa655351666582f626645395a31fa7048ddcd63043f55ec3bfc83dceae69d8f8b32f4cdb6e2aebd94b4314f8fe7287dcb62732c9052e7557fe63534338efb5b6254c5d41d2690cf5144f: +34e1e9d539107eb86b393a5ccea1496d35bc7d5e9a8c5159d957e4e5852b3eb00ecb2601d5f7047428e9f909883a12420085f04ee2a88b6d95d3d7f2c932bd76:0ecb2601d5f7047428e9f909883a12420085f04ee2a88b6d95d3d7f2c932bd76:a6d4d0542cfe0d240a90507debacabce7cbbd48732353f4fad82c7bb7dbd9df8e7d9a16980a45186d8786c5ef65445bcc5b2ad5f660ffc7c8eaac0:32d22904d3e7012d6f5a441b0b4228064a5cf95b723a66b048a087ecd55920c31c204c3f2006891a85dd1932e3f1d614cfd633b5e63291c6d8166f3011431e09a6d4d0542cfe0d240a90507debacabce7cbbd48732353f4fad82c7bb7dbd9df8e7d9a16980a45186d8786c5ef65445bcc5b2ad5f660ffc7c8eaac0: +49dd473ede6aa3c866824a40ada4996c239a20d84c9365e4f0a4554f8031b9cf788de540544d3feb0c919240b390729be487e94b64ad973eb65b4669ecf23501:788de540544d3feb0c919240b390729be487e94b64ad973eb65b4669ecf23501:3a53594f3fba03029318f512b084a071ebd60baec7f55b028dc73bfc9c74e0ca496bf819dd92ab61cd8b74be3c0d6dcd128efc5ed3342cba124f726c:d2fde02791e720852507faa7c3789040d9ef86646321f313ac557f4002491542dd67d05c6990cdb0d495501fbc5d5188bfbb84dc1bf6098bee0603a47fc2690f3a53594f3fba03029318f512b084a071ebd60baec7f55b028dc73bfc9c74e0ca496bf819dd92ab61cd8b74be3c0d6dcd128efc5ed3342cba124f726c: +331c64da482b6b551373c36481a02d8136ecadbb01ab114b4470bf41607ac57152a00d96a3148b4726692d9eff89160ea9f99a5cc4389f361fed0bb16a42d521:52a00d96a3148b4726692d9eff89160ea9f99a5cc4389f361fed0bb16a42d521:20e1d05a0d5b32cc8150b8116cef39659dd5fb443ab15600f78e5b49c45326d9323f2850a63c3808859495ae273f58a51e9de9a145d774b40ba9d753d3:22c99aa946ead39ac7997562810c01c20b46bd610645bd2d56dcdcbaacc5452c74fbf4b8b1813b0e94c30d808ce5498e61d4f7ccbb4cc5f04dfc6140825a960020e1d05a0d5b32cc8150b8116cef39659dd5fb443ab15600f78e5b49c45326d9323f2850a63c3808859495ae273f58a51e9de9a145d774b40ba9d753d3: +5c0b96f2af8712122cf743c8f8dc77b6cd5570a7de13297bb3dde1886213cce20510eaf57d7301b0e1d527039bf4c6e292300a3a61b4765434f3203c100351b1:0510eaf57d7301b0e1d527039bf4c6e292300a3a61b4765434f3203c100351b1:54e0caa8e63919ca614b2bfd308ccfe50c9ea888e1ee4446d682cb5034627f97b05392c04e835556c31c52816a48e4fb196693206b8afb4408662b3cb575:06e5d8436ac7705b3a90f1631cdd38ec1a3fa49778a9b9f2fa5ebea4e7d560ada7dd26ff42fafa8ba420323742761aca6904940dc21bbef63ff72daab45d430b54e0caa8e63919ca614b2bfd308ccfe50c9ea888e1ee4446d682cb5034627f97b05392c04e835556c31c52816a48e4fb196693206b8afb4408662b3cb575: +de84f2435f78dedb87da18194ff6a336f08111150def901c1ac418146eb7b54ad3a92bbaa4d63af79c2226a7236e6427428df8b362427f873023b22d2f5e03f2:d3a92bbaa4d63af79c2226a7236e6427428df8b362427f873023b22d2f5e03f2:205135ec7f417c858072d5233fb36482d4906abd60a74a498c347ff248dfa2722ca74e879de33169fadc7cd44d6c94a17d16e1e630824ba3e0df22ed68eaab:471ebc973cfdaceec07279307368b73be35bc6f8d8312b70150567369096706dc471126c3576f9f0eb550df5ac6a525181110029dd1fc11174d1aaced48d630f205135ec7f417c858072d5233fb36482d4906abd60a74a498c347ff248dfa2722ca74e879de33169fadc7cd44d6c94a17d16e1e630824ba3e0df22ed68eaab: +ba4d6e67b2ce67a1e44326494044f37a442f3b81725bc1f9341462718b55ee20f73fa076f84b6db675a5fda5ad67e351a41e8e7f29add16809ca010387e9c6cc:f73fa076f84b6db675a5fda5ad67e351a41e8e7f29add16809ca010387e9c6cc:4bafdac9099d4057ed6dd08bcaee8756e9a40f2cb9598020eb95019528409bbea38b384a59f119f57297bfb2fa142fc7bb1d90dbddde772bcde48c5670d5fa13:57b9d2a711207f837421bae7dd48eaa18eab1a9a70a0f1305806fee17b458f3a0964b302d1834d3e0ac9e8496f000b77f0083b41f8a957e632fbc7840eee6a064bafdac9099d4057ed6dd08bcaee8756e9a40f2cb9598020eb95019528409bbea38b384a59f119f57297bfb2fa142fc7bb1d90dbddde772bcde48c5670d5fa13: +0d131c45aea6f3a4e1b9a2cf60c55104587efaa846b222bf0a7b74ce7a3f63b63c6729dbe93b499c4e614a2f21beb729438d498e1ac8d14cbad9717a5dbd97cd:3c6729dbe93b499c4e614a2f21beb729438d498e1ac8d14cbad9717a5dbd97cd:b4291d08b88fb2f7b8f99d0dce40079fcbab718bbd8f4e8eabc3c1428b6a071fb2a3c8eba1cacccfa871b365c708bef2685bc13e6b80bc14a5f249170ffc56d014:a9c5ee86fb06d9e46b379c32dda7c92c9c13db274dc24116fbdd878696045488cc75a52fff67d1a5113d06e333ac67ff664b3f2a405fa1d14dd5bbb97409b606b4291d08b88fb2f7b8f99d0dce40079fcbab718bbd8f4e8eabc3c1428b6a071fb2a3c8eba1cacccfa871b365c708bef2685bc13e6b80bc14a5f249170ffc56d014: +a75e3b6b4170e444781be4eeac3e0fdaa4b4356f705486bcb071a325ae071fba993d38a7d72f0aee15ff6f4fdc37ca7724fd1373a3766b275dbc77e647980e0a:993d38a7d72f0aee15ff6f4fdc37ca7724fd1373a3766b275dbc77e647980e0a:4037866f6548b01cc6bcf3a940e3945aa2d188b4b7f182aa77ec4d6b0428ab5b84d85df192a5a38ada089d76fa26bf67736a7041a5eb8f0c5719eb396693c45160f8:a5db4d3d3329abe3697959e6b5947ea8601b03ef8e1d6fe202144931272ca0a09b5eb0f390572ea7ef03c6131e9de5f16bf0b034244f7e104ff5311bbf663a0d4037866f6548b01cc6bcf3a940e3945aa2d188b4b7f182aa77ec4d6b0428ab5b84d85df192a5a38ada089d76fa26bf67736a7041a5eb8f0c5719eb396693c45160f8: +bcbcf561ecc05a41c7d7e55e696d32ce39b4d03c1f5f3f3a8927fe5e62e844b24ddf53fad6a7a9ed30f3afecca136fd7843b72c243090891ae4021a32cadff1a:4ddf53fad6a7a9ed30f3afecca136fd7843b72c243090891ae4021a32cadff1a:6f6716b6784740980aebc3248807e31c1286ac7b681c00b66c88ff7a336d441fa5c3eb256d20cf6d1ac92ccfe4be6dcc41b1aff846d360c243001cabdfbf1a9b240455:9ff15115f6661f3211d7a40764967629ba6a5263951bdc3c6a4c90d070f7be00024b80d83b6bc27587fcff5f5ccc0eb3cde1497cf56895147a063f61f08adf0b6f6716b6784740980aebc3248807e31c1286ac7b681c00b66c88ff7a336d441fa5c3eb256d20cf6d1ac92ccfe4be6dcc41b1aff846d360c243001cabdfbf1a9b240455: +210532805fa9cc9be916d213cac374e3cd6fc2602a544d0c1ce29d30105d69ab10699e499be99e2b11b98f6f86b67cdc4ccf69f3c53ce094875647d2d0d0ecc5:10699e499be99e2b11b98f6f86b67cdc4ccf69f3c53ce094875647d2d0d0ecc5:9fc4d28cfd25e6c0c5e724e19ca39d71e53bf4aa2796c54c3351f108fc70f2611a62e0ab90af6ade5216788e9eb2a873059b1e79d7d59debd68f2d4d80ffe31bf74b928c:4c2d31d5bbc42e026dc1e079ecc4dd072c5d2cce65e3db8d8a1dd9057faa0371727f727231a0f060fa27097533b6db3b8f6252f2793d75662caadf5f0fcc710e9fc4d28cfd25e6c0c5e724e19ca39d71e53bf4aa2796c54c3351f108fc70f2611a62e0ab90af6ade5216788e9eb2a873059b1e79d7d59debd68f2d4d80ffe31bf74b928c: +185d64b69479e0ba0a5844a10ad84125ba11c4b40d63eda2c57afc7e019c8e0ca5764f6398a5ae2266a38f9714533c4bbd8d07826f63e204cbac374b0acef1bd:a5764f6398a5ae2266a38f9714533c4bbd8d07826f63e204cbac374b0acef1bd:4a0824fe70d4315413d0a0cafbf4f5fe117d5e07e1c3a4effb9d0ae91490234878ccf6792a91f68c6a520de16071f08abe35dc5ea428f1957b663371ce24c609dd55b8f493:43e0387da5ba09a190f6e7b2680578d889769bcc445e5ef571b492871c155c5b9f620bfacfbf2df1fd87444604b71b2e237baaa7ee2093ede4a601edf883e3074a0824fe70d4315413d0a0cafbf4f5fe117d5e07e1c3a4effb9d0ae91490234878ccf6792a91f68c6a520de16071f08abe35dc5ea428f1957b663371ce24c609dd55b8f493: +cfa9d9164b3c4f6f722635d2066cd7ea5e5533d2c74f8add669c371faa47642641169a66f9a63f285782a6c2db81cc3f70b3ada21a68c84745c88a74c3b0a2de:41169a66f9a63f285782a6c2db81cc3f70b3ada21a68c84745c88a74c3b0a2de:757621b1675db7cacef7f2782587ff3af51a3ef2f4bcf9279c4ce94002e1f00424bf0eb621982cc85cb4d171e564a0c2f6e3567a1aae2cddb7e9b25f47dc20a51050542969ca:01d7c9b5701af71e2f4877ffc9b7b5305f52816d4458e37e41c7719fac1d76a01fff3f50fe1a5875ccc3fb70001c947a33fc8b207de13572ccdb8ba98933ab01757621b1675db7cacef7f2782587ff3af51a3ef2f4bcf9279c4ce94002e1f00424bf0eb621982cc85cb4d171e564a0c2f6e3567a1aae2cddb7e9b25f47dc20a51050542969ca: +1acb4a256c2f8993ca24de1e0014606d668b5e756032d269f1d24d351c8eea4acbbdcd8cbc885ab43a057e5f9579f1161954159e7b562ea26cd9a43c88d3f96d:cbbdcd8cbc885ab43a057e5f9579f1161954159e7b562ea26cd9a43c88d3f96d:c46a6d61aa0aed1c1d8547a70b89b7196475d5a4870881b1ecd0f0cb9c745f8a2adc8024e2dc55b53aa5d383a81aabc1a47e8d07d00b7f0b56ceddbfb1f424bb5c02184678a666:05aa76f7fe51892303d78914715995e7d768ff7714ce270f175e56af17ae018d3fa939f5f620de82bcd1549687b205c7871203e624238c4e309fab7f92fbaa05c46a6d61aa0aed1c1d8547a70b89b7196475d5a4870881b1ecd0f0cb9c745f8a2adc8024e2dc55b53aa5d383a81aabc1a47e8d07d00b7f0b56ceddbfb1f424bb5c02184678a666: +ace3c46424823622979fc3a84a7da69c1d527d8312e8fb018375bd3a96c29c18937cf34136d9e1cce0de11b12c70cbfb7455448421e92c82e7c40934bff8c676:937cf34136d9e1cce0de11b12c70cbfb7455448421e92c82e7c40934bff8c676:a9f137bc9021bf105aee25be21cd9ee5b3547cf10cc5f98476fb588bd70e2d6d6b0834e842e4ee94303cf96b09c1715381b36e14a491b80f895ea421b8ec2b1d3c187e02935c5526:feb8896dd3fe6001ffea171b37b788a69f7f850193a63406f56376dd263d099aef80ece67e2c43f40eca462c6b71e79406b18db74ae5d49844e3b132bc2a1307a9f137bc9021bf105aee25be21cd9ee5b3547cf10cc5f98476fb588bd70e2d6d6b0834e842e4ee94303cf96b09c1715381b36e14a491b80f895ea421b8ec2b1d3c187e02935c5526: +88f681934e33c35c07dc6e5a832942ae3d59903ccde2f76ccb7587cea7ec41b66a4e8aa5adb63d22fd7b14a26fdb03b7c8aa6ccd5a196f2c54b0465adb5092e1:6a4e8aa5adb63d22fd7b14a26fdb03b7c8aa6ccd5a196f2c54b0465adb5092e1:6e8bac1f853b81fef94707e18cc61c6f0a9cbc2a41d078dcc83fc0229c7f8dbe6dbdd90854b1f1ae2b9f2b120b86a8786b4e78ce23ab86baaf88754af0f3d88881dae0bc5261bfd038:45b27bf1b9eac06b62b686f6d546563b2dfe5b175dbef32bf78c35a16c958a9d4f26d291de9bb2066c0a286113cc09172d40a36d4cbd951708860226eb30cd056e8bac1f853b81fef94707e18cc61c6f0a9cbc2a41d078dcc83fc0229c7f8dbe6dbdd90854b1f1ae2b9f2b120b86a8786b4e78ce23ab86baaf88754af0f3d88881dae0bc5261bfd038: +48050a6e0158f6ad253412e4497cff62d5ee555edffe59e4dc401522813295ce975e010abb9a3e56659137b0506057f283982f886ca172c7bc2c500ed9bd26c1:975e010abb9a3e56659137b0506057f283982f886ca172c7bc2c500ed9bd26c1:ed6eec29fb7049dff707f0a4426ebc8f5b350e95870b9d6198c8139e9c3e1e409937d1a858a0dea482a5cb1a854ed3b5a9397acb63bff6b64039ef2eb1159e99858310bbbd86125c3e0e:7216ab60c35168187d0fce4753c86e80058d540b76bf95843a5898841060a99a44de6f439625a3f6365f59c377bf45909bbfef5c50b25f3194e5fbd34ea5e706ed6eec29fb7049dff707f0a4426ebc8f5b350e95870b9d6198c8139e9c3e1e409937d1a858a0dea482a5cb1a854ed3b5a9397acb63bff6b64039ef2eb1159e99858310bbbd86125c3e0e: +18d13d0c00e8e3386a5cfb30a9e79fe88b1861ed2d1201eb170038e194770403a4afc833401876090d9b880c41267d68cbbeeaa38afb20884e27328f3b7f535e:a4afc833401876090d9b880c41267d68cbbeeaa38afb20884e27328f3b7f535e:910f6c272dd97931ac47310d244cadb43251365e02ba9f6a5b3c3226be9d7d3a74a2ba4906e8e71a4bf3d3556ebdfc666cd6b12f20c4a00834b88fbb244575199286b0b9344cf334aff007:033988154c5d79d2510be83e778015dfe2fb85b8111f7ec139918b5400e3d656ee80a9f5c9072b5b467a5cc5a57cc8ad1062b5bff10862d9d369dde2cc966701910f6c272dd97931ac47310d244cadb43251365e02ba9f6a5b3c3226be9d7d3a74a2ba4906e8e71a4bf3d3556ebdfc666cd6b12f20c4a00834b88fbb244575199286b0b9344cf334aff007: +4adc8c28646a93a817293a14d29b48e2c6d712a68993547a5c5e4d1452acbc3a7f40473628f23fc0dff0021afd487740d4916a9122e6c97d36433e5ebf04f88c:7f40473628f23fc0dff0021afd487740d4916a9122e6c97d36433e5ebf04f88c:09fb5501f1688f80a0ab9e22d778ae130acaf74d7f5185b4da198c6b9edac4302e2b753e578766e17d4056dc40d95cf4ca8bcc6565795e97d68bcda79fa77c493397716356164caab5d19cfd:6d3b4e90ec408311f9b15b9253d3d95c5d152620c260d56302555a8804a5104ba5e8d29ee108e764a64219297298ab7674bbca784dee28773b34e185a386c20809fb5501f1688f80a0ab9e22d778ae130acaf74d7f5185b4da198c6b9edac4302e2b753e578766e17d4056dc40d95cf4ca8bcc6565795e97d68bcda79fa77c493397716356164caab5d19cfd: +f26e1c84697a4908151b447dcf6c7c7a38b04081db9e7c7738e6fec900bed0c1a86e1422c1235ff8e1aa083470d5e42288cb007ab50e795dd0b4ff87394966c4:a86e1422c1235ff8e1aa083470d5e42288cb007ab50e795dd0b4ff87394966c4:54ed47606a1487c2f900cefb6e899dbaf6c31cc88ebe3558b83b93f6d422c31e888e48e520eeaedd7e554a9cd40c2c519d533b6144cee484c389e976b1e4022b50e7dbb87ead7e541a2004daf7:44f3344b9566c9dfd22d6198e1cbf95d9e28f2982fc7f166ab25dda30c46f768c558e0394fb9ab3e1d4db4cf487c17641a13f3f48939e0c64827a75103c5740654ed47606a1487c2f900cefb6e899dbaf6c31cc88ebe3558b83b93f6d422c31e888e48e520eeaedd7e554a9cd40c2c519d533b6144cee484c389e976b1e4022b50e7dbb87ead7e541a2004daf7: +cc0c33f3a86f5a17d30c186ce0f3b740bafa5fe3c7090f143541e2b2c1e534bc967a71c7cf9b82cc78cbe109104d8b438a8d1fd71d260d029046a9a4526866ff:967a71c7cf9b82cc78cbe109104d8b438a8d1fd71d260d029046a9a4526866ff:1944e5e155d75e0d0be92e1be14cec370ad13791f2bfd40f271214e94fcf213c71bc20d7ce0c7584421ac4efc451883cc3f4956f21f73a4216720438bc38ff2cfdf3709905a50a9d94b1d9e7932b:e277b3dd655c33ff75fa920af1fcc859401e6c7a6ef4c6bfbfac5069638f19ca115baf13c09c82af793facb6abd0cd58e8481b08c1b68ad7a2665c4a614a28061944e5e155d75e0d0be92e1be14cec370ad13791f2bfd40f271214e94fcf213c71bc20d7ce0c7584421ac4efc451883cc3f4956f21f73a4216720438bc38ff2cfdf3709905a50a9d94b1d9e7932b: +f0bc979375a7073068dba7f6c094db6598b4e45df7d549583c22fded8048fa2eb42b6c57a78f1d90090a7181ab2ae09f426cbc2be96eb2cf27abc70d7d32a4b3:b42b6c57a78f1d90090a7181ab2ae09f426cbc2be96eb2cf27abc70d7d32a4b3:27ab3049b5c6351f6cfe38b13a059f5037257ee3d65d6079656856edc876ea081fd8a9480466f8839478088466f51ecbfaf2d65def25f0c4dd8d08588202812232f57945df8a6fa161ed8c0343b583:19dbc3027f9fae707deb76f588f9fd07aa8eae29bd4e1d04c2c984388286b3b122248a6c03ed67eca35df4db3dc1e4237f267892518497d9552a21de19b5140f27ab3049b5c6351f6cfe38b13a059f5037257ee3d65d6079656856edc876ea081fd8a9480466f8839478088466f51ecbfaf2d65def25f0c4dd8d08588202812232f57945df8a6fa161ed8c0343b583: +3022975f298c0ad5ddbe90954f20e63ae0c0d2704cf13c221f5b3720af4dba32b845bce38e26ab027b8247463d437a71bbddca2a2381d81fad4c297df9140bd5:b845bce38e26ab027b8247463d437a71bbddca2a2381d81fad4c297df9140bd5:9aa19a595d989378cdc06891887ef5f9c246e5f83c0b658710673e4e7db760c76354c4f5d1e90db04a23b4fb434c69384593d010e312b11d299c9f97482de887cecfe82ea723bca79a1bd64d03ef19ee:ae14a860fad0051b3eb72b3721a82f7b9546b2867261e2b7b638979e2561bdeb89b600768f82450a66c8b0481283fa21cb6c53bde350effb68a7d1114bfdb2039aa19a595d989378cdc06891887ef5f9c246e5f83c0b658710673e4e7db760c76354c4f5d1e90db04a23b4fb434c69384593d010e312b11d299c9f97482de887cecfe82ea723bca79a1bd64d03ef19ee: +0f710b6c481f71449589753312ef64932b4652ebe0e07597f7da1c4f3dcffb806973ff2932ccddfc1d16c4c0da50c8b29fe6452d1ee84d52064ebf3d628d403e:6973ff2932ccddfc1d16c4c0da50c8b29fe6452d1ee84d52064ebf3d628d403e:85d85744ad55e9ef9a65ca91e85c8a4f80e4c58f8e4e9354e833986098b7d9fe9fdc0dedb0d75d2539fba00034fc0c2e84344d1edaa09d4f63d5546d67803dd6b54ddcc0b1d3f2582dd75289e31de42e69:02a8d26aee11420fb4f09d1163e14b867df7c6f6c8f8dc7a78034659f0401cad0aa90397efdd0704b798db1936503026e2a1adc297e27974d4be312a3753f80485d85744ad55e9ef9a65ca91e85c8a4f80e4c58f8e4e9354e833986098b7d9fe9fdc0dedb0d75d2539fba00034fc0c2e84344d1edaa09d4f63d5546d67803dd6b54ddcc0b1d3f2582dd75289e31de42e69: +7a05f121f60112dd16fee8c91bc2a11479f4b67ee33456042c8de167fc588017b3b05be989cea7197505d4b54335e5e1d77a4b52ba7282604bbc1cf6c4e87a6c:b3b05be989cea7197505d4b54335e5e1d77a4b52ba7282604bbc1cf6c4e87a6c:d9c59e8cc4ede537be2122ab492a5b915a9b0a114b2ade356fc0457ef98722d5f567b86211e28369d14168ec4a3c804076e154adc70a668cf64a20d13cf190d115cd688d036e46938251df4964dc3517b10c:d30ce8a322b450a2fb1afd329cec8559ccf112bd83965f9ec4736270a0914e061196bf5209778c9f8ccf39c4668bbf0e1363f81afe45dd74e80d5875ddbf6f01d9c59e8cc4ede537be2122ab492a5b915a9b0a114b2ade356fc0457ef98722d5f567b86211e28369d14168ec4a3c804076e154adc70a668cf64a20d13cf190d115cd688d036e46938251df4964dc3517b10c: +bf381f8dfb5d0c6d64e416ac23e0d0fcb86ebb899b1d146abd911b92a7808eb6863fad8d1f1bc630a15f6fe8ecefe6b4497b60b21ae8830da46742045fef156f:863fad8d1f1bc630a15f6fe8ecefe6b4497b60b21ae8830da46742045fef156f:8654f2f5c6dcd2cfcbb6ed8d2bc5fb5fec53e3effb0de65aac507fa56c897732395aa09946d3b6586a92edd6dc99315e1ba74c6a0247c4ba7760b948eb3c0932d9fe1f0e9fea6eb61a548a9ab48ffdf1547329:99b75378738fcac8067669e8509b5d2607e1ef76af9004e13fe5d3932df60b168216f58565340fa4d638055a89044ee7d45e2bd082a53382289a34700648980e8654f2f5c6dcd2cfcbb6ed8d2bc5fb5fec53e3effb0de65aac507fa56c897732395aa09946d3b6586a92edd6dc99315e1ba74c6a0247c4ba7760b948eb3c0932d9fe1f0e9fea6eb61a548a9ab48ffdf1547329: +36983241a0a8e60ce02a61b3fafab15a7313a5a270d015b9c9ec070dc42deeda6647984d42b9a5b3b1afa3b7f8f49d4c2b05e38984e99cea8fd68235d2ae4627:6647984d42b9a5b3b1afa3b7f8f49d4c2b05e38984e99cea8fd68235d2ae4627:cebb9e404451818253c0392a4554ee7323c5d5b8b226775700b806ed5b91337916ea7ecbc3d4103fc65e5372ae7e5f9ba2d8f5aee24ccf6e631ae20c4af9b5f728cdf89e8189def1a5b3d35347aa203525ea1d2e:ee37df8af422f91f85dfe43efe79f62378068ccdbaf3916eecbc3adfed0508bdebaf5ce06b3bc279f78087f0db8db3c6823edfb32c12217830be723d8872b30ccebb9e404451818253c0392a4554ee7323c5d5b8b226775700b806ed5b91337916ea7ecbc3d4103fc65e5372ae7e5f9ba2d8f5aee24ccf6e631ae20c4af9b5f728cdf89e8189def1a5b3d35347aa203525ea1d2e: +d06899f93a408dacb41c969718346f1e289bb5ea65e283ff79c705a074517c3546bf2a08a076c47d7f11b733f8141c355363ed85d7def26ba6a0ce15ac5f2be8:46bf2a08a076c47d7f11b733f8141c355363ed85d7def26ba6a0ce15ac5f2be8:0864c39ac4fda8eb9048597bd40be0401021fd2dd3a3390a8facce984b260a13fa2c7cfc00d192fadf134a0ad5a181ee89eff0c795eaa0fbfe2f3b26115d07168db42ed21a51303b1958e4a42dc065b22ce48f17a6:6f89de92a66bc5f4144339124950bdf588144cb372f6736245351c9476becc59a258f9a933ffff2bef4b46cd1057395225799fd09dede6823db0e325dbc8140d0864c39ac4fda8eb9048597bd40be0401021fd2dd3a3390a8facce984b260a13fa2c7cfc00d192fadf134a0ad5a181ee89eff0c795eaa0fbfe2f3b26115d07168db42ed21a51303b1958e4a42dc065b22ce48f17a6: +eebca7966970ee9f2cc4d74c6f1d8e0ebff7c45aebad349fb9f86df628dfff0e89101e0309f767e64ae9c98c4a5d8d2328fb3ef262d082f49b64ca209e1990f6:89101e0309f767e64ae9c98c4a5d8d2328fb3ef262d082f49b64ca209e1990f6:0fac790adb9f59e5cb0ddcb2b667172f2a21034d93bcaddf188606fa9e776db33a8fcc6bd7f5567883fc0de351aa9afaa36d2075b1ba853bada849b8661d5c8154e7b0afea656dd15e01a9c5ba21589b02f8fc5481c2:7d447ee5328c9fe7f11936cc42998754a56cd1d2a6951af4fee7c4a8eb319d4923707c793c55d79067f822d5b16bb5776e38dffabc67237a916a81a63339b0030fac790adb9f59e5cb0ddcb2b667172f2a21034d93bcaddf188606fa9e776db33a8fcc6bd7f5567883fc0de351aa9afaa36d2075b1ba853bada849b8661d5c8154e7b0afea656dd15e01a9c5ba21589b02f8fc5481c2: +3820b6b15939d0afe18c9cb3d9a2a08f167dd458eb6c7e3f1558b0c6db4c689080b85c6559fea8b400e1999cc5bfed507ad7fc294cd9ba0ce2dd2584a91089b0:80b85c6559fea8b400e1999cc5bfed507ad7fc294cd9ba0ce2dd2584a91089b0:3e5ad92d44b40e8614d8087c9c743de0c0861a07f1f5146d71cac2f3740024e841cc2d46027cf5d261d3ee7c1875b39551017b5fb1468114fc3e098a899cdbd558b39f098e156b6e9801ebcdd65fed56dbfcaf2c8c787b:823ee2c0c8d87faa0ec0141e9ce08b51e57c839792d1fbd97a967207fd415849ebfb5dadb5a1dc2c0a8b7fc63fc354857b8c90c44720e13f45cd01e7aa23140c3e5ad92d44b40e8614d8087c9c743de0c0861a07f1f5146d71cac2f3740024e841cc2d46027cf5d261d3ee7c1875b39551017b5fb1468114fc3e098a899cdbd558b39f098e156b6e9801ebcdd65fed56dbfcaf2c8c787b: +0d20fa4a37ff30c4dcc3e44ea7ac501137e5807e9781330ac310982cc3d39dbd67bb0a01bc8617b491eff1a326c1c70f7d0c5b95a5ad48241aedce1c6f0883cf:67bb0a01bc8617b491eff1a326c1c70f7d0c5b95a5ad48241aedce1c6f0883cf:35e0f4b4a517f9c7aa4514f03e6d65f19b27c62cc069f6bf07dd6378bd6afe2b766560006cbd5730a00919ed11191fb0c8dac56e153fc1cea4bdce5046cccb717759a4083e1c16f740763264cc804de0d0e1a4b5a23067af:deab12ed82ba94b469ca98b66fa20444b4b7881c4f0f853409c9a1504a5b2b6d7860f26ada6bf73459b9cdb573c8017121338efa60f4148086d7a3a8ed59bb0735e0f4b4a517f9c7aa4514f03e6d65f19b27c62cc069f6bf07dd6378bd6afe2b766560006cbd5730a00919ed11191fb0c8dac56e153fc1cea4bdce5046cccb717759a4083e1c16f740763264cc804de0d0e1a4b5a23067af: +bee161881d819b370d240d509ba46b06fb828e20310d9f6b309780703e98927b10854380de89162bfb9f7835a2716a3a6e0265671b250b389d01c3bcc03736b8:10854380de89162bfb9f7835a2716a3a6e0265671b250b389d01c3bcc03736b8:5a6fe599b6b09b05c0ba6a622df3a92b3d376d24d04ea85ebe767bc2ec4d14e83e6937dc0b914b4809fdb607906841a6fd1dcdf61aaea8f9bb81b2ccaa32df412989ae53646680a71a211c8440eab0f1aec5e4fc00e6a2c96d:b07d072eb3831fae8a06effa9201797496dce126b8e11fef2fa07f664dc5cf3d4bf9c38a8b3c09fb5f14fa2deb219e7d852fdd27c7ba32d309942f2746dfe4045a6fe599b6b09b05c0ba6a622df3a92b3d376d24d04ea85ebe767bc2ec4d14e83e6937dc0b914b4809fdb607906841a6fd1dcdf61aaea8f9bb81b2ccaa32df412989ae53646680a71a211c8440eab0f1aec5e4fc00e6a2c96d: +70150e9516164a3d7b7e8b6f255b65cac9f07459b32d11bb94b3d277208abc992328bec8e40351047882e8b43bc1ab085386fa47987e46ea87608814c5da713c:2328bec8e40351047882e8b43bc1ab085386fa47987e46ea87608814c5da713c:77be8eceaab431a13c2a28d0d1556489d8c392fd7ae41157f7caf082cb54e45f08626be0076be844d38fde901a5eab0e8832d69dac22fb8507fb8ec4faf7c88fd26da308461afe385987972b5e760a34a5e18b9a82b4aaa529b7:eda3f5033ea7953a0d583c6457522e84ad78445304d48e577d4d69e8641febe15248d8d90ce0944a8f801d39099bc77494bac4ce2a20b38369c6adfb71e03d0f77be8eceaab431a13c2a28d0d1556489d8c392fd7ae41157f7caf082cb54e45f08626be0076be844d38fde901a5eab0e8832d69dac22fb8507fb8ec4faf7c88fd26da308461afe385987972b5e760a34a5e18b9a82b4aaa529b7: +3f87fcfdb421422a9c5fb98268313c15128c78844ef9eb3b3713fa77b6718903533ec59228374bd03a4699e3a8896b86182fcf8fc3085fdb8f5c4671524d6fe0:533ec59228374bd03a4699e3a8896b86182fcf8fc3085fdb8f5c4671524d6fe0:c00fed2d689468bcbacccd446e8d8f299e2a86925e62e59709afaf4857469ff1e006d00fa3e18a3615f8f06b6ebdff785dde58851d2c239038a0c344dce985bd1fc8deb4779ae5f8932e2f9ed5990b6472dbe4e6fef6917657e0b5:f6519d7edb6134111974033f03b8d89e9c76caec8965a8e17cd45fff19de2615d73eccdb4a6664a8f0e23adf98988e96251bf26eb7a4ccaac1079f0a772f9b05c00fed2d689468bcbacccd446e8d8f299e2a86925e62e59709afaf4857469ff1e006d00fa3e18a3615f8f06b6ebdff785dde58851d2c239038a0c344dce985bd1fc8deb4779ae5f8932e2f9ed5990b6472dbe4e6fef6917657e0b5: +44ceef044ff998d4abeaaf374eb41d086718b63097b1e35f89634c14897132eae83c86677d03ed3a5e8c95f41f0b325ff4333702f2ff6936f57ff30aa31485c7:e83c86677d03ed3a5e8c95f41f0b325ff4333702f2ff6936f57ff30aa31485c7:8d3e2dec4644c7b51633b13e6375ca42ff9138465f43d7800c7313199f67c9cf1b520b1820bd630ecf1c992e2767b38eb5bbc441a4ab8d317db441db35a0fe3abe7a9e4541881c2d7b1a2612306959815d1da41267d9649dd4494ace:554552d6b790d421d06b0a67f8e002ad7a1ed01c06cf00cbeaec2a268bda29f1183f0ceafc625fa5fdb847dc86fae1a20406e459d4a0177cb515220a568e08008d3e2dec4644c7b51633b13e6375ca42ff9138465f43d7800c7313199f67c9cf1b520b1820bd630ecf1c992e2767b38eb5bbc441a4ab8d317db441db35a0fe3abe7a9e4541881c2d7b1a2612306959815d1da41267d9649dd4494ace: +98ef2a44d4c8476dff05aa78dcf9c6dc086cb2f622a06745d60cbf223faaba6642fdb1daa39f0159119beec1bedf6f0394b26a2a29bd1fde081eccdadecc226a:42fdb1daa39f0159119beec1bedf6f0394b26a2a29bd1fde081eccdadecc226a:c8b5fcfc3c18c7d95957b668e91c731d50c7fcea4f9575bbf784625870e238df546e2cb1a19d2808dd5b230d3871fdec16100ee1fbf9b722fa3744a750a3b396b05f9c21b8c0f61ead57a78c5ecf72b579cfe88a3f404c8acf524f9ab9:ab5e8724a3e6ff76058cfb214d574e04d05574ecdd4ffe8c07c7af396e882687c5d79ef1e62fbb4c5f1bd06b9bd897826edde0d111d918e8ef961ff2a00d7700c8b5fcfc3c18c7d95957b668e91c731d50c7fcea4f9575bbf784625870e238df546e2cb1a19d2808dd5b230d3871fdec16100ee1fbf9b722fa3744a750a3b396b05f9c21b8c0f61ead57a78c5ecf72b579cfe88a3f404c8acf524f9ab9: +93a8c792a239c931917c114824a0174f8bc4ebbf98af8c7e321e0f5bea4015ec9b2eaa8a9c2c25ff4f6e13bb12bae5d06fda0eb1105fafae5880ff168740bb74:9b2eaa8a9c2c25ff4f6e13bb12bae5d06fda0eb1105fafae5880ff168740bb74:901bf4e041caf16e04f2ffde8d6fe97e93d0900f6bc0fc09a9a0179d137b4b7788e57eb92766a9c634f35adb5c2988af1e86208f461998f59cfec99204b484fbcad3951e7ee4405523705d9739b44307db03f713fda78db421ef3121b3ba:cfe32c4435d911d772dc0727e78d689d0164c5069597cb441b22c1d26236479f1afd7089121b9ab4f61bbb1fae1ab42f7635a92a53784d7170916b703aa5cc09901bf4e041caf16e04f2ffde8d6fe97e93d0900f6bc0fc09a9a0179d137b4b7788e57eb92766a9c634f35adb5c2988af1e86208f461998f59cfec99204b484fbcad3951e7ee4405523705d9739b44307db03f713fda78db421ef3121b3ba: +7001fa0c4404c28aa5b5fcff30a961f21a22f5b85a9e382e07aea8a8924d0ec1daebb63c4d8f40ceba8ec35e3dd946a6b75bc74fcb29ade7b55eee3cc3aea5ca:daebb63c4d8f40ceba8ec35e3dd946a6b75bc74fcb29ade7b55eee3cc3aea5ca:44f48cfb02f08777a57873855f96be4c0291323f2739b275d90757a15472e5750436e0107408fe3026c00625689983f990eba9becbfce403ccd56356ad2741fd21445dfb23d76112e578b3395cf9d960955f1da8f399ca286f21390e25a59a:64eac9ce87460618636b41fd2decc1673bfc48c5f479dfacb51e86686407374b1d10bf65d6d7474214d7770c9e5c7f806c80d53d48b720870e5e78f32e3a7e0544f48cfb02f08777a57873855f96be4c0291323f2739b275d90757a15472e5750436e0107408fe3026c00625689983f990eba9becbfce403ccd56356ad2741fd21445dfb23d76112e578b3395cf9d960955f1da8f399ca286f21390e25a59a: +3adce3a3d3fbc977dd4b300a74749f13a3b04a5d73a2cd75a994e3195efebdac6ff19b1f18d64851d5c74845c6407f0bf596a52e385e020127e83e54cff5ac19:6ff19b1f18d64851d5c74845c6407f0bf596a52e385e020127e83e54cff5ac19:fe6c1a31068e332d12aab37d99406568deaa36bdb277cee55304633bd0a267a850e203bb3fabe5110bcc1ca4316698ab1cf00f0b0f1d97ef2180887f0ec0991e8c1111f0c0e1d2b712433ad2b3071bd66e1d81f7fa47bb4bb31ac0f059bb3cb8:7dda89f85b40539f5ad8c6de4953f7094a715b63dda30ec7cf65a785ceae5fc688707ee00be682cecbe7ee37d8fc39ee6d83c64409681708a0898a183b288a06fe6c1a31068e332d12aab37d99406568deaa36bdb277cee55304633bd0a267a850e203bb3fabe5110bcc1ca4316698ab1cf00f0b0f1d97ef2180887f0ec0991e8c1111f0c0e1d2b712433ad2b3071bd66e1d81f7fa47bb4bb31ac0f059bb3cb8: +14803c1f23a47fcdd35e5d146e20ca630cd712c047d5330b652e31857acbc9e836f2d5bd6d8324fa6e9db7f7d854ebe48c0e6299998122e9d44b8adbef54f093:36f2d5bd6d8324fa6e9db7f7d854ebe48c0e6299998122e9d44b8adbef54f093:555983679d026e5354b4cc055ae1bc14653c7281ec722372f3feb778e841da821b3d0b8ee7a9a9129ea06824be8379fbbdcb0748f423721ccb172a1bafa1d5ae9fc1c51e93d41dd551c3086079b620286c1c40c1223bbcbb76722e92ca21d8410a:07a7de6ce97664b3ea0928e1385c3309be08a47cbf4daa9186a1b948c86fbba39c4efcfcb7a0a3866bc94c6788ffe6be0d4972e56d0c3292d1cc6e25447b9904555983679d026e5354b4cc055ae1bc14653c7281ec722372f3feb778e841da821b3d0b8ee7a9a9129ea06824be8379fbbdcb0748f423721ccb172a1bafa1d5ae9fc1c51e93d41dd551c3086079b620286c1c40c1223bbcbb76722e92ca21d8410a: +1a61154d3472cd96b328ee674beb4fc86763a969fb410494e0678414e31a46a67576d93ac85d0fc61f258c55cf90bd87a635099c0e810ed0b937258d13b42559:7576d93ac85d0fc61f258c55cf90bd87a635099c0e810ed0b937258d13b42559:64c565efbcb8b9528ed47253f3c6a4035db781d6f0976b5e5ba8447d4ed54b04105293ef4c000d8b2e1b5b75e727e5d2a077743b50d183b491764801a2504d16ee6d7d8ac4fe40e6bfc2a8129c7285a5ac691c35e642ed162cf7fbc64516733a23b3:ada1666c9c3b8284b8a21c4f2618ef0808a646f3f10941e470f738e1785e2de9fdd9c8cb526f945c7a8c6994f151b7d066581b1d755307947c62befc8ab7070f64c565efbcb8b9528ed47253f3c6a4035db781d6f0976b5e5ba8447d4ed54b04105293ef4c000d8b2e1b5b75e727e5d2a077743b50d183b491764801a2504d16ee6d7d8ac4fe40e6bfc2a8129c7285a5ac691c35e642ed162cf7fbc64516733a23b3: +f215d34fe2d757cff9cf5c05430994de587987ce45cb0459f61ec6c825c622591ed506485b09a6450be7c9337d9fe87ef99c96f8bd11cd631ca160d0fd73067e:1ed506485b09a6450be7c9337d9fe87ef99c96f8bd11cd631ca160d0fd73067e:fbed2a7df418ec0e8036312ec239fcee6ef97dc8c2df1f2e14adee287808b788a6072143b851d975c8e8a0299df846b19113e38cee83da71ea8e9bd6f57bdcd3557523f4feb616caa595aea01eb0b3d490b99b525ea4fbb9258bc7fbb0deea8f568cb2:cbef65b6f3fd580969fc3340cfae4f7c99df1340cce54626183144ef468871634b0a5c0033534108e1c67c0dc99d3014f01084e98c95e1014b309b1dbb2e6704fbed2a7df418ec0e8036312ec239fcee6ef97dc8c2df1f2e14adee287808b788a6072143b851d975c8e8a0299df846b19113e38cee83da71ea8e9bd6f57bdcd3557523f4feb616caa595aea01eb0b3d490b99b525ea4fbb9258bc7fbb0deea8f568cb2: diff --git a/src/pycryptopp/testvectors/kat-ed25519.txt b/src/pycryptopp/testvectors/kat-ed25519.txt new file mode 100644 index 0000000..bbab0e6 --- /dev/null +++ b/src/pycryptopp/testvectors/kat-ed25519.txt @@ -0,0 +1,1024 @@ +9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a:d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a::e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b: +4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c:3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c:72:92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c0072: +c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025:fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025:af82:6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40aaf82: +0d4a05b07352a5436e180356da0ae6efa0345ff7fb1572575772e8005ed978e9e61a185bcef2613a6c7cb79763ce945d3b245d76114dd440bcf5f2dc1aa57057:e61a185bcef2613a6c7cb79763ce945d3b245d76114dd440bcf5f2dc1aa57057:cbc77b:d9868d52c2bebce5f3fa5a79891970f309cb6591e3e1702a70276fa97c24b3a8e58606c38c9758529da50ee31b8219cba45271c689afa60b0ea26c99db19b00ccbc77b: +6df9340c138cc188b5fe4464ebaa3f7fc206a2d55c3434707e74c9fc04e20ebbc0dac102c4533186e25dc43128472353eaabdb878b152aeb8e001f92d90233a7:c0dac102c4533186e25dc43128472353eaabdb878b152aeb8e001f92d90233a7:5f4c8989:124f6fc6b0d100842769e71bd530664d888df8507df6c56dedfdb509aeb93416e26b918d38aa06305df3095697c18b2aa832eaa52edc0ae49fbae5a85e150c075f4c8989: +b780381a65edf8b78f6945e8dbec7941ac049fd4c61040cf0c324357975a293ce253af0766804b869bb1595be9765b534886bbaab8305bf50dbc7f899bfb5f01:e253af0766804b869bb1595be9765b534886bbaab8305bf50dbc7f899bfb5f01:18b6bec097:b2fc46ad47af464478c199e1f8be169f1be6327c7f9a0a6689371ca94caf04064a01b22aff1520abd58951341603faed768cf78ce97ae7b038abfe456aa17c0918b6bec097: +78ae9effe6f245e924a7be63041146ebc670dbd3060cba67fbc6216febc44546fbcfbfa40505d7f2be444a33d185cc54e16d615260e1640b2b5087b83ee3643d:fbcfbfa40505d7f2be444a33d185cc54e16d615260e1640b2b5087b83ee3643d:89010d855972:6ed629fc1d9ce9e1468755ff636d5a3f40a5d9c91afd93b79d241830f7e5fa29854b8f20cc6eecbb248dbd8d16d14e99752194e4904d09c74d639518839d230089010d855972: +691865bfc82a1e4b574eecde4c7519093faf0cf867380234e3664645c61c5f7998a5e3a36e67aaba89888bf093de1ad963e774013b3902bfab356d8b90178a63:98a5e3a36e67aaba89888bf093de1ad963e774013b3902bfab356d8b90178a63:b4a8f381e70e7a:6e0af2fe55ae377a6b7a7278edfb419bd321e06d0df5e27037db8812e7e3529810fa5552f6c0020985ca17a0e02e036d7b222a24f99b77b75fdd16cb05568107b4a8f381e70e7a: +3b26516fb3dc88eb181b9ed73f0bcd52bcd6b4c788e4bcaf46057fd078bee073f81fb54a825fced95eb033afcd64314075abfb0abd20a970892503436f34b863:f81fb54a825fced95eb033afcd64314075abfb0abd20a970892503436f34b863:4284abc51bb67235:d6addec5afb0528ac17bb178d3e7f2887f9adbb1ad16e110545ef3bc57f9de2314a5c8388f723b8907be0f3ac90c6259bbe885ecc17645df3db7d488f805fa084284abc51bb67235: +edc6f5fbdd1cee4d101c063530a30490b221be68c036f5b07d0f953b745df192c1a49c66e617f9ef5ec66bc4c6564ca33de2a5fb5e1464062e6d6c6219155efd:c1a49c66e617f9ef5ec66bc4c6564ca33de2a5fb5e1464062e6d6c6219155efd:672bf8965d04bc5146:2c76a04af2391c147082e33faacdbe56642a1e134bd388620b852b901a6bc16ff6c9cc9404c41dea12ed281da067a1513866f9d964f8bdd24953856c50042901672bf8965d04bc5146: +4e7d21fb3b1897571a445833be0f9fd41cd62be3aa04040f8934e1fcbdcacd4531b2524b8348f7ab1dfafa675cc538e9a84e3fe5819e27c12ad8bbc1a36e4dff:31b2524b8348f7ab1dfafa675cc538e9a84e3fe5819e27c12ad8bbc1a36e4dff:33d7a786aded8c1bf691:28e4598c415ae9de01f03f9f3fab4e919e8bf537dd2b0cdf6e79b9e6559c9409d9151a4c40f083193937627c369488259e99da5a9f0a87497fa6696a5dd6ce0833d7a786aded8c1bf691: +a980f892db13c99a3e8971e965b2ff3d41eafd54093bc9f34d1fd22d84115bb644b57ee30cdb55829d0a5d4f046baef078f1e97a7f21b62d75f8e96ea139c35f:44b57ee30cdb55829d0a5d4f046baef078f1e97a7f21b62d75f8e96ea139c35f:3486f68848a65a0eb5507d:77d389e599630d934076329583cd4105a649a9292abc44cd28c40000c8e2f5ac7660a81c85b72af8452d7d25c070861dae91601c7803d656531650dd4e5c41003486f68848a65a0eb5507d: +5b5a619f8ce1c66d7ce26e5a2ae7b0c04febcd346d286c929e19d0d5973bfef96fe83693d011d111131c4f3fbaaa40a9d3d76b30012ff73bb0e39ec27ab18257:6fe83693d011d111131c4f3fbaaa40a9d3d76b30012ff73bb0e39ec27ab18257:5a8d9d0a22357e6655f9c785:0f9ad9793033a2fa06614b277d37381e6d94f65ac2a5a94558d09ed6ce922258c1a567952e863ac94297aec3c0d0c8ddf71084e504860bb6ba27449b55adc40e5a8d9d0a22357e6655f9c785: +940c89fe40a81dafbdb2416d14ae469119869744410c3303bfaa0241dac57800a2eb8c0501e30bae0cf842d2bde8dec7386f6b7fc3981b8c57c9792bb94cf2dd:a2eb8c0501e30bae0cf842d2bde8dec7386f6b7fc3981b8c57c9792bb94cf2dd:b87d3813e03f58cf19fd0b6395:d8bb64aad8c9955a115a793addd24f7f2b077648714f49c4694ec995b330d09d640df310f447fd7b6cb5c14f9fe9f490bcf8cfadbfd2169c8ac20d3b8af49a0cb87d3813e03f58cf19fd0b6395: +9acad959d216212d789a119252ebfe0c96512a23c73bd9f3b202292d6916a738cf3af898467a5b7a52d33d53bc037e2642a8da996903fc252217e9c033e2f291:cf3af898467a5b7a52d33d53bc037e2642a8da996903fc252217e9c033e2f291:55c7fa434f5ed8cdec2b7aeac173:6ee3fe81e23c60eb2312b2006b3b25e6838e02106623f844c44edb8dafd66ab0671087fd195df5b8f58a1d6e52af42908053d55c7321010092748795ef94cf0655c7fa434f5ed8cdec2b7aeac173: +d5aeee41eeb0e9d1bf8337f939587ebe296161e6bf5209f591ec939e1440c300fd2a565723163e29f53c9de3d5e8fbe36a7ab66e1439ec4eae9c0a604af291a5:fd2a565723163e29f53c9de3d5e8fbe36a7ab66e1439ec4eae9c0a604af291a5:0a688e79be24f866286d4646b5d81c:f68d04847e5b249737899c014d31c805c5007a62c0a10d50bb1538c5f35503951fbc1e08682f2cc0c92efe8f4985dec61dcbd54d4b94a22547d24451271c8b000a688e79be24f866286d4646b5d81c: +0a47d10452ae2febec518a1c7c362890c3fc1a49d34b03b6467d35c904a8362d34e5a8508c4743746962c066e4badea2201b8ab484de5c4f94476ccd2143955b:34e5a8508c4743746962c066e4badea2201b8ab484de5c4f94476ccd2143955b:c942fa7ac6b23ab7ff612fdc8e68ef39:2a3d27dc40d0a8127949a3b7f908b3688f63b7f14f651aacd715940bdbe27a0809aac142f47ab0e1e44fa490ba87ce5392f33a891539caf1ef4c367cae54500cc942fa7ac6b23ab7ff612fdc8e68ef39: +f8148f7506b775ef46fdc8e8c756516812d47d6cfbfa318c27c9a22641e56f170445e456dacc7d5b0bbed23c8200cdb74bdcb03e4c7b73f0a2b9b46eac5d4372:0445e456dacc7d5b0bbed23c8200cdb74bdcb03e4c7b73f0a2b9b46eac5d4372:7368724a5b0efb57d28d97622dbde725af:3653ccb21219202b8436fb41a32ba2618c4a133431e6e63463ceb3b6106c4d56e1d2ba165ba76eaad3dc39bffb130f1de3d8e6427db5b71938db4e272bc3e20b7368724a5b0efb57d28d97622dbde725af: +77f88691c4eff23ebb7364947092951a5ff3f10785b417e918823a552dab7c7574d29127f199d86a8676aec33b4ce3f225ccb191f52c191ccd1e8cca65213a6b:74d29127f199d86a8676aec33b4ce3f225ccb191f52c191ccd1e8cca65213a6b:bd8e05033f3a8bcdcbf4beceb70901c82e31:fbe929d743a03c17910575492f3092ee2a2bf14a60a3fcacec74a58c7334510fc262db582791322d6c8c41f1700adb80027ecabc14270b703444ae3ee7623e0abd8e05033f3a8bcdcbf4beceb70901c82e31: +ab6f7aee6a0837b334ba5eb1b2ad7fcecfab7e323cab187fe2e0a95d80eff1325b96dca497875bf9664c5e75facf3f9bc54bae913d66ca15ee85f1491ca24d2c:5b96dca497875bf9664c5e75facf3f9bc54bae913d66ca15ee85f1491ca24d2c:8171456f8b907189b1d779e26bc5afbb08c67a:73bca64e9dd0db88138eedfafcea8f5436cfb74bfb0e7733cf349baa0c49775c56d5934e1d38e36f39b7c5beb0a836510c45126f8ec4b6810519905b0ca07c098171456f8b907189b1d779e26bc5afbb08c67a: +8d135de7c8411bbdbd1b31e5dc678f2ac7109e792b60f38cd24936e8a898c32d1ca281938529896535a7714e3584085b86ef9fec723f42819fc8dd5d8c00817f:1ca281938529896535a7714e3584085b86ef9fec723f42819fc8dd5d8c00817f:8ba6a4c9a15a244a9c26bb2a59b1026f21348b49:a1adc2bc6a2d980662677e7fdff6424de7dba50f5795ca90fdf3e96e256f3285cac71d3360482e993d0294ba4ec7440c61affdf35fe83e6e04263937db93f1058ba6a4c9a15a244a9c26bb2a59b1026f21348b49: +0e765d720e705f9366c1ab8c3fa84c9a44370c06969f803296884b2846a652a47fae45dd0a05971026d410bc497af5be7d0827a82a145c203f625dfcb8b03ba8:7fae45dd0a05971026d410bc497af5be7d0827a82a145c203f625dfcb8b03ba8:1d566a6232bbaab3e6d8804bb518a498ed0f904986:bb61cf84de61862207c6a455258bc4db4e15eea0317ff88718b882a06b5cf6ec6fd20c5a269e5d5c805bafbcc579e2590af414c7c227273c102a10070cdfe80f1d566a6232bbaab3e6d8804bb518a498ed0f904986: +db36e326d676c2d19cc8fe0c14b709202ecfc761d27089eb6ea4b1bb021ecfa748359b850d23f0715d94bb8bb75e7e14322eaf14f06f28a805403fbda002fc85:48359b850d23f0715d94bb8bb75e7e14322eaf14f06f28a805403fbda002fc85:1b0afb0ac4ba9ab7b7172cddc9eb42bba1a64bce47d4:b6dcd09989dfbac54322a3ce87876e1d62134da998c79d24b50bd7a6a797d86a0e14dc9d7491d6c14a673c652cfbec9f962a38c945da3b2f0879d0b68a9213001b0afb0ac4ba9ab7b7172cddc9eb42bba1a64bce47d4: +c89955e0f7741d905df0730b3dc2b0ce1a13134e44fef3d40d60c020ef19df77fdb30673402faf1c8033714f3517e47cc0f91fe70cf3836d6c23636e3fd2287c:fdb30673402faf1c8033714f3517e47cc0f91fe70cf3836d6c23636e3fd2287c:507c94c8820d2a5793cbf3442b3d71936f35fe3afef316:7ef66e5e86f2360848e0014e94880ae2920ad8a3185a46b35d1e07dea8fa8ae4f6b843ba174d99fa7986654a0891c12a794455669375bf92af4cc2770b579e0c507c94c8820d2a5793cbf3442b3d71936f35fe3afef316: +4e62627fc221142478aee7f00781f817f662e3b75db29bb14ab47cf8e84104d6b1d39801892027d58a8c64335163195893bfc1b61dbeca3260497e1f30371107:b1d39801892027d58a8c64335163195893bfc1b61dbeca3260497e1f30371107:d3d615a8472d9962bb70c5b5466a3d983a4811046e2a0ef5:836afa764d9c48aa4770a4388b654e97b3c16f082967febca27f2fc47ddfd9244b03cfc729698acf5109704346b60b230f255430089ddc56912399d1122de70ad3d615a8472d9962bb70c5b5466a3d983a4811046e2a0ef5: +6b83d7da8908c3e7205b39864b56e5f3e17196a3fc9c2f5805aad0f5554c142dd0c846f97fe28585c0ee159015d64c56311c886eddcc185d296dbb165d2625d6:d0c846f97fe28585c0ee159015d64c56311c886eddcc185d296dbb165d2625d6:6ada80b6fa84f7034920789e8536b82d5e4678059aed27f71c:16e462a29a6dd498685a3718b3eed00cc1598601ee47820486032d6b9acc9bf89f57684e08d8c0f05589cda2882a05dc4c63f9d0431d6552710812433003bc086ada80b6fa84f7034920789e8536b82d5e4678059aed27f71c: +19a91fe23a4e9e33ecc474878f57c64cf154b394203487a7035e1ad9cd697b0d2bf32ba142ba4622d8f3e29ecd85eea07b9c47be9d64412c9b510b27dd218b23:2bf32ba142ba4622d8f3e29ecd85eea07b9c47be9d64412c9b510b27dd218b23:82cb53c4d5a013bae5070759ec06c3c6955ab7a4050958ec328c:881f5b8c5a030df0f75b6634b070dd27bd1ee3c08738ae349338b3ee6469bbf9760b13578a237d5182535ede121283027a90b5f865d63a6537dca07b44049a0f82cb53c4d5a013bae5070759ec06c3c6955ab7a4050958ec328c: +1d5b8cb6215c18141666baeefcf5d69dad5bea9a3493dddaa357a4397a13d4de94d23d977c33e49e5e4992c68f25ec99a27c41ce6b91f2bfa0cd8292fe962835:94d23d977c33e49e5e4992c68f25ec99a27c41ce6b91f2bfa0cd8292fe962835:a9a8cbb0ad585124e522abbfb40533bdd6f49347b55b18e8558cb0:3acd39bec8c3cd2b44299722b5850a0400c1443590fd4861d59aae7496acb3df73fc3fdf7969ae5f50ba47dddc435246e5fd376f6b891cd4c2caf5d614b6170ca9a8cbb0ad585124e522abbfb40533bdd6f49347b55b18e8558cb0: +6a91b3227c472299089bdce9356e726a40efd840f11002708b7ee55b64105ac29d084aa8b97a6b9bafa496dbc6f76f3306a116c9d917e681520a0f914369427e:9d084aa8b97a6b9bafa496dbc6f76f3306a116c9d917e681520a0f914369427e:5cb6f9aa59b80eca14f6a68fb40cf07b794e75171fba96262c1c6adc:f5875423781b66216cb5e8998de5d9ffc29d1d67107054ace3374503a9c3ef811577f269de81296744bd706f1ac478caf09b54cdf871b3f802bd57f9a6cb91015cb6f9aa59b80eca14f6a68fb40cf07b794e75171fba96262c1c6adc: +93eaa854d791f05372ce72b94fc6503b2ff8ae6819e6a21afe825e27ada9e4fb16cee8a3f2631834c88b670897ff0b08ce90cc147b4593b3f1f403727f7e7ad5:16cee8a3f2631834c88b670897ff0b08ce90cc147b4593b3f1f403727f7e7ad5:32fe27994124202153b5c70d3813fdee9c2aa6e7dc743d4d535f1840a5:d834197c1a3080614e0a5fa0aaaa808824f21c38d692e6ffbd200f7dfb3c8f44402a7382180b98ad0afc8eec1a02acecf3cb7fde627b9f18111f260ab1db9a0732fe27994124202153b5c70d3813fdee9c2aa6e7dc743d4d535f1840a5: +941cac69fb7b1815c57bb987c4d6c2ad2c35d5f9a3182a79d4ba13eab253a8ad23be323c562dfd71ce65f5bba56a74a3a6dfc36b573d2f94f635c7f9b4fd5a5b:23be323c562dfd71ce65f5bba56a74a3a6dfc36b573d2f94f635c7f9b4fd5a5b:bb3172795710fe00054d3b5dfef8a11623582da68bf8e46d72d27cece2aa:0f8fad1e6bde771b4f5420eac75c378bae6db5ac6650cd2bc210c1823b432b48e016b10595458ffab92f7a8989b293ceb8dfed6c243a2038fc06652aaaf16f02bb3172795710fe00054d3b5dfef8a11623582da68bf8e46d72d27cece2aa: +1acdbb793b0384934627470d795c3d1dd4d79cea59ef983f295b9b59179cbb283f60c7541afa76c019cf5aa82dcdb088ed9e4ed9780514aefb379dabc844f31a:3f60c7541afa76c019cf5aa82dcdb088ed9e4ed9780514aefb379dabc844f31a:7cf34f75c3dac9a804d0fcd09eba9b29c9484e8a018fa9e073042df88e3c56:be71ef4806cb041d885effd9e6b0fbb73d65d7cdec47a89c8a994892f4e55a568c4cc78d61f901e80dbb628b86a23ccd594e712b57fa94c2d67ec266348785077cf34f75c3dac9a804d0fcd09eba9b29c9484e8a018fa9e073042df88e3c56: +8ed7a797b9cea8a8370d419136bcdf683b759d2e3c6947f17e13e2485aa9d420b49f3a78b1c6a7fca8f3466f33bc0e929f01fba04306c2a7465f46c3759316d9:b49f3a78b1c6a7fca8f3466f33bc0e929f01fba04306c2a7465f46c3759316d9:a750c232933dc14b1184d86d8b4ce72e16d69744ba69818b6ac33b1d823bb2c3:04266c033b91c1322ceb3446c901ffcf3cc40c4034e887c9597ca1893ba7330becbbd8b48142ef35c012c6ba51a66df9308cb6268ad6b1e4b03e70102495790ba750c232933dc14b1184d86d8b4ce72e16d69744ba69818b6ac33b1d823bb2c3: +f2ab396fe8906e3e5633e99cabcd5b09df0859b516230b1e0450b580b65f616c8ea074245159a116aa7122a25ec16b891d625a68f33660423908f6bdc44f8c1b:8ea074245159a116aa7122a25ec16b891d625a68f33660423908f6bdc44f8c1b:5a44e34b746c5fd1898d552ab354d28fb4713856d7697dd63eb9bd6b99c280e187:a06a23d982d81ab883aae230adbc368a6a9977f003cebb00d4c2e4018490191a84d3a282fdbfb2fc88046e62de43e15fb575336b3c8b77d19ce6a009ce51f50c5a44e34b746c5fd1898d552ab354d28fb4713856d7697dd63eb9bd6b99c280e187: +550a41c013f79bab8f06e43ad1836d51312736a9713806fafe6645219eaa1f9daf6b7145474dc9954b9af93a9cdb34449d5b7c651c824d24e230b90033ce59c0:af6b7145474dc9954b9af93a9cdb34449d5b7c651c824d24e230b90033ce59c0:8bc4185e50e57d5f87f47515fe2b1837d585f0aae9e1ca383b3ec908884bb900ff27:16dc1e2b9fa909eefdc277ba16ebe207b8da5e91143cde78c5047a89f681c33c4e4e3428d5c928095903a811ec002d52a39ed7f8b3fe1927200c6dd0b9ab3e048bc4185e50e57d5f87f47515fe2b1837d585f0aae9e1ca383b3ec908884bb900ff27: +19ac3e272438c72ddf7b881964867cb3b31ff4c793bb7ea154613c1db068cb7ef85b80e050a1b9620db138bfc9e100327e25c257c59217b601f1f6ac9a413d3f:f85b80e050a1b9620db138bfc9e100327e25c257c59217b601f1f6ac9a413d3f:95872d5f789f95484e30cbb0e114028953b16f5c6a8d9f65c003a83543beaa46b38645:ea855d781cbea4682e350173cb89e8619ccfddb97cdce16f9a2f6f6892f46dbe68e04b12b8d88689a7a31670cdff409af98a93b49a34537b6aa009d2eb8b470195872d5f789f95484e30cbb0e114028953b16f5c6a8d9f65c003a83543beaa46b38645: +ca267de96c93c238fafb1279812059ab93ac03059657fd994f8fa5a09239c821017370c879090a81c7f272c2fc80e3aac2bc603fcb379afc98691160ab745b26:017370c879090a81c7f272c2fc80e3aac2bc603fcb379afc98691160ab745b26:e05f71e4e49a72ec550c44a3b85aca8f20ff26c3ee94a80f1b431c7d154ec9603ee02531:ac957f82335aa7141e96b59d63e3ccee95c3a2c47d026540c2af42dc9533d5fd81827d1679ad187aeaf37834915e75b147a9286806c8017516ba43dd051a5e0ce05f71e4e49a72ec550c44a3b85aca8f20ff26c3ee94a80f1b431c7d154ec9603ee02531: +3dff5e899475e7e91dd261322fab09980c52970de1da6e2e201660cc4fce7032f30162bac98447c4042fac05da448034629be2c6a58d30dfd578ba9fb5e3930b:f30162bac98447c4042fac05da448034629be2c6a58d30dfd578ba9fb5e3930b:938f0e77621bf3ea52c7c4911c5157c2d8a2a858093ef16aa9b107e69d98037ba139a3c382:5efe7a92ff9623089b3e3b78f352115366e26ba3fb1a416209bc029e9cadccd9f4affa333555a8f3a35a9d0f7c34b292cae77ec96fa3adfcaadee2d9ced8f805938f0e77621bf3ea52c7c4911c5157c2d8a2a858093ef16aa9b107e69d98037ba139a3c382: +9a6b847864e70cfe8ba6ab22fa0ca308c0cc8bec7141fbcaa3b81f5d1e1cfcfc34ad0fbdb2566507a81c2b1f8aa8f53dccaa64cc87ada91b903e900d07eee930:34ad0fbdb2566507a81c2b1f8aa8f53dccaa64cc87ada91b903e900d07eee930:838367471183c71f7e717724f89d401c3ad9863fd9cc7aa3cf33d3c529860cb581f3093d87da:2ab255169c489c54c732232e37c87349d486b1eba20509dbabe7fed329ef08fd75ba1cd145e67b2ea26cb5cc51cab343eeb085fe1fd7b0ec4c6afcd9b979f905838367471183c71f7e717724f89d401c3ad9863fd9cc7aa3cf33d3c529860cb581f3093d87da: +575be07afca5d063c238cd9b8028772cc49cda34471432a2e166e096e2219efc94e5eb4d5024f49d7ebf79817c8de11497dc2b55622a51ae123ffc749dbb16e0:94e5eb4d5024f49d7ebf79817c8de11497dc2b55622a51ae123ffc749dbb16e0:33e5918b66d33d55fe717ca34383eae78f0af82889caf6696e1ac9d95d1ffb32cba755f9e3503e:58271d44236f3b98c58fd7ae0d2f49ef2b6e3affdb225aa3ba555f0e11cc53c23ad19baf24346590d05d7d5390582082cf94d39cad6530ab93d13efb3927950633e5918b66d33d55fe717ca34383eae78f0af82889caf6696e1ac9d95d1ffb32cba755f9e3503e: +15ffb45514d43444d61fcb105e30e135fd268523dda20b82758b1794231104411772c5abc2d23fd2f9d1c3257be7bc3c1cd79cee40844b749b3a7743d2f964b8:1772c5abc2d23fd2f9d1c3257be7bc3c1cd79cee40844b749b3a7743d2f964b8:da9c5559d0ea51d255b6bd9d7638b876472f942b330fc0e2b30aea68d77368fce4948272991d257e:6828cd7624e793b8a4ceb96d3c2a975bf773e5ff6645f353614058621e58835289e7f31f42dfe6af6d736f2644511e320c0fa698582a79778d18730ed3e8cb08da9c5559d0ea51d255b6bd9d7638b876472f942b330fc0e2b30aea68d77368fce4948272991d257e: +fe0568642943b2e1afbfd1f10fe8df87a4236bea40dce742072cb21886eec1fa299ebd1f13177dbdb66a912bbf712038fdf73b06c3ac020c7b19126755d47f61:299ebd1f13177dbdb66a912bbf712038fdf73b06c3ac020c7b19126755d47f61:c59d0862ec1c9746abcc3cf83c9eeba2c7082a036a8cb57ce487e763492796d47e6e063a0c1feccc2d:d59e6dfcc6d7e3e2c58dec81e985d245e681acf6594a23c59214f7bed8015d813c7682b60b3583440311e72a8665ba2c96dec23ce826e160127e18132b030404c59d0862ec1c9746abcc3cf83c9eeba2c7082a036a8cb57ce487e763492796d47e6e063a0c1feccc2d: +5ecb16c2df27c8cf58e436a9d3affbd58e9538a92659a0f97c4c4f994635a8cada768b20c437dd3aa5f84bb6a077ffa34ab68501c5352b5cc3fdce7fe6c2398d:da768b20c437dd3aa5f84bb6a077ffa34ab68501c5352b5cc3fdce7fe6c2398d:56f1329d9a6be25a6159c72f12688dc8314e85dd9e7e4dc05bbecb7729e023c86f8e0937353f27c7ede9:1c723a20c6772426a670e4d5c4a97c6ebe9147f71bb0a415631e44406e290322e4ca977d348fe7856a8edc235d0fe95f7ed91aefddf28a77e2c7dbfd8f552f0a56f1329d9a6be25a6159c72f12688dc8314e85dd9e7e4dc05bbecb7729e023c86f8e0937353f27c7ede9: +d599d637b3c30a82a9984e2f758497d144de6f06b9fba04dd40fd949039d7c846791d8ce50a44689fc178727c5c3a1c959fbeed74ef7d8e7bd3c1ab4da31c51f:6791d8ce50a44689fc178727c5c3a1c959fbeed74ef7d8e7bd3c1ab4da31c51f:a7c04e8ba75d0a03d8b166ad7a1d77e1b91c7aaf7befdd99311fc3c54a684ddd971d5b3211c3eeaff1e54e:ebf10d9ac7c96108140e7def6fe9533d727646ff5b3af273c1df95762a66f32b65a09634d013f54b5dd6011f91bc336ca8b355ce33f8cfbec2535a4c427f8205a7c04e8ba75d0a03d8b166ad7a1d77e1b91c7aaf7befdd99311fc3c54a684ddd971d5b3211c3eeaff1e54e: +30ab8232fa7018f0ce6c39bd8f782fe2e159758bb0f2f4386c7f28cfd2c85898ecfb6a2bd42f31b61250ba5de7e46b4719afdfbc660db71a7bd1df7b0a3abe37:ecfb6a2bd42f31b61250ba5de7e46b4719afdfbc660db71a7bd1df7b0a3abe37:63b80b7956acbecf0c35e9ab06b914b0c7014fe1a4bbc0217240c1a33095d707953ed77b15d211adaf9b97dc:9af885344cc7239498f712df80bc01b80638291ed4a1d28baa5545017a72e2f65649ccf9603da6eb5bfab9f5543a6ca4a7af3866153c76bf66bf95def615b00c63b80b7956acbecf0c35e9ab06b914b0c7014fe1a4bbc0217240c1a33095d707953ed77b15d211adaf9b97dc: +0ddcdc872c7b748d40efe96c2881ae189d87f56148ed8af3ebbbc80324e38bdd588ddadcbcedf40df0e9697d8bb277c7bb1498fa1d26ce0a835a760b92ca7c85:588ddadcbcedf40df0e9697d8bb277c7bb1498fa1d26ce0a835a760b92ca7c85:65641cd402add8bf3d1d67dbeb6d41debfbef67e4317c35b0a6d5bbbae0e034de7d670ba1413d056f2d6f1de12:c179c09456e235fe24105afa6e8ec04637f8f943817cd098ba95387f9653b2add181a31447d92d1a1ddf1ceb0db62118de9dffb7dcd2424057cbdff5d41d040365641cd402add8bf3d1d67dbeb6d41debfbef67e4317c35b0a6d5bbbae0e034de7d670ba1413d056f2d6f1de12: +89f0d68299ba0a5a83f248ae0c169f8e3849a9b47bd4549884305c9912b46603aba3e795aab2012acceadd7b3bd9daeeed6ff5258bdcd7c93699c2a3836e3832:aba3e795aab2012acceadd7b3bd9daeeed6ff5258bdcd7c93699c2a3836e3832:4f1846dd7ad50e545d4cfbffbb1dc2ff145dc123754d08af4e44ecc0bc8c91411388bc7653e2d893d1eac2107d05:2c691fa8d487ce20d5d2fa41559116e0bbf4397cf5240e152556183541d66cf753582401a4388d390339dbef4d384743caa346f55f8daba68ba7b9131a8a6e0b4f1846dd7ad50e545d4cfbffbb1dc2ff145dc123754d08af4e44ecc0bc8c91411388bc7653e2d893d1eac2107d05: +0a3c1844e2db070fb24e3c95cb1cc6714ef84e2ccd2b9dd2f1460ebf7ecf13b172e409937e0610eb5c20b326dc6ea1bbbc0406701c5cd67d1fbde09192b07c01:72e409937e0610eb5c20b326dc6ea1bbbc0406701c5cd67d1fbde09192b07c01:4c8274d0ed1f74e2c86c08d955bde55b2d54327e82062a1f71f70d536fdc8722cdead7d22aaead2bfaa1ad00b82957:87f7fdf46095201e877a588fe3e5aaf476bd63138d8a878b89d6ac60631b3458b9d41a3c61a588e1db8d29a5968981b018776c588780922f5aa732ba6379dd054c8274d0ed1f74e2c86c08d955bde55b2d54327e82062a1f71f70d536fdc8722cdead7d22aaead2bfaa1ad00b82957: +c8d7a8818b98dfdb20839c871cb5c48e9e9470ca3ad35ba2613a5d3199c8ab2390d2efbba4d43e6b2b992ca16083dbcfa2b322383907b0ee75f3e95845d3c47f:90d2efbba4d43e6b2b992ca16083dbcfa2b322383907b0ee75f3e95845d3c47f:783e33c3acbdbb36e819f544a7781d83fc283d3309f5d3d12c8dcd6b0b3d0e89e38cfd3b4d0885661ca547fb9764abff:fa2e994421aef1d5856674813d05cbd2cf84ef5eb424af6ecd0dc6fdbdc2fe605fe985883312ecf34f59bfb2f1c9149e5b9cc9ecda05b2731130f3ed28ddae0b783e33c3acbdbb36e819f544a7781d83fc283d3309f5d3d12c8dcd6b0b3d0e89e38cfd3b4d0885661ca547fb9764abff: +b482703612d0c586f76cfcb21cfd2103c957251504a8c0ac4c86c9c6f3e429fffd711dc7dd3b1dfb9df9704be3e6b26f587fe7dd7ba456a91ba43fe51aec09ad:fd711dc7dd3b1dfb9df9704be3e6b26f587fe7dd7ba456a91ba43fe51aec09ad:29d77acfd99c7a0070a88feb6247a2bce9984fe3e6fbf19d4045042a21ab26cbd771e184a9a75f316b648c6920db92b87b:58832bdeb26feafc31b46277cf3fb5d7a17dfb7ccd9b1f58ecbe6feb979666828f239ba4d75219260ecac0acf40f0e5e2590f4caa16bbbcd8a155d347967a60729d77acfd99c7a0070a88feb6247a2bce9984fe3e6fbf19d4045042a21ab26cbd771e184a9a75f316b648c6920db92b87b: +84e50dd9a0f197e3893c38dbd91fafc344c1776d3a400e2f0f0ee7aa829eb8a22c50f870ee48b36b0ac2f8a5f336fb090b113050dbcc25e078200a6e16153eea:2c50f870ee48b36b0ac2f8a5f336fb090b113050dbcc25e078200a6e16153eea:f3992cde6493e671f1e129ddca8038b0abdb77bb9035f9f8be54bd5d68c1aeff724ff47d29344391dc536166b8671cbbf123:69e6a4491a63837316e86a5f4ba7cd0d731ecc58f1d0a264c67c89befdd8d3829d8de13b33cc0bf513931715c7809657e2bfb960e5c764c971d733746093e500f3992cde6493e671f1e129ddca8038b0abdb77bb9035f9f8be54bd5d68c1aeff724ff47d29344391dc536166b8671cbbf123: +b322d46577a2a991a4d1698287832a39c487ef776b4bff037a05c7f1812bdeeceb2bcadfd3eec2986baff32b98e7c4dbf03ff95d8ad5ff9aa9506e5472ff845f:eb2bcadfd3eec2986baff32b98e7c4dbf03ff95d8ad5ff9aa9506e5472ff845f:19f1bf5dcf1750c611f1c4a2865200504d82298edd72671f62a7b1471ac3d4a30f7de9e5da4108c52a4ce70a3e114a52a3b3c5:c7b55137317ca21e33489ff6a9bfab97c855dc6f85684a70a9125a261b56d5e6f149c5774d734f2d8debfc77b721896a8267c23768e9badb910eef83ec25880219f1bf5dcf1750c611f1c4a2865200504d82298edd72671f62a7b1471ac3d4a30f7de9e5da4108c52a4ce70a3e114a52a3b3c5: +960cab5034b9838d098d2dcbf4364bec16d388f6376d73a6273b70f82bbc98c05e3c19f2415acf729f829a4ebd5c40e1a6bc9fbca95703a9376087ed0937e51a:5e3c19f2415acf729f829a4ebd5c40e1a6bc9fbca95703a9376087ed0937e51a:f8b21962447b0a8f2e4279de411bea128e0be44b6915e6cda88341a68a0d818357db938eac73e0af6d31206b3948f8c48a447308:27d4c3a1811ef9d4360b3bdd133c2ccc30d02c2f248215776cb07ee4177f9b13fc42dd70a6c2fed8f225c7663c7f182e7ee8eccff20dc7b0e1d5834ec5b1ea01f8b21962447b0a8f2e4279de411bea128e0be44b6915e6cda88341a68a0d818357db938eac73e0af6d31206b3948f8c48a447308: +eb77b2638f23eebc82efe45ee9e5a0326637401e663ed029699b21e6443fb48e9ef27608961ac711de71a6e2d4d4663ea3ecd42fb7e4e8627c39622df4af0bbc:9ef27608961ac711de71a6e2d4d4663ea3ecd42fb7e4e8627c39622df4af0bbc:99e3d00934003ebafc3e9fdb687b0f5ff9d5782a4b1f56b9700046c077915602c3134e22fc90ed7e690fddd4433e2034dcb2dc99ab:18dc56d7bd9acd4f4daa78540b4ac8ff7aa9815f45a0bba370731a14eaabe96df8b5f37dbf8eae4cb15a64b244651e59d6a3d6761d9e3c50f2d0cbb09c05ec0699e3d00934003ebafc3e9fdb687b0f5ff9d5782a4b1f56b9700046c077915602c3134e22fc90ed7e690fddd4433e2034dcb2dc99ab: +b625aa89d3f7308715427b6c39bbac58effd3a0fb7316f7a22b99ee5922f2dc965a99c3e16fea894ec33c6b20d9105e2a04e2764a4769d9bbd4d8bacfeab4a2e:65a99c3e16fea894ec33c6b20d9105e2a04e2764a4769d9bbd4d8bacfeab4a2e:e07241dbd3adbe610bbe4d005dd46732a4c25086ecb8ec29cd7bca116e1bf9f53bfbf3e11fa49018d39ff1154a06668ef7df5c678e6a:01bb901d83b8b682d3614af46a807ba2691358feb775325d3423f549ff0aa5757e4e1a74e9c70f9721d8f354b319d4f4a1d91445c870fd0ffb94fed64664730de07241dbd3adbe610bbe4d005dd46732a4c25086ecb8ec29cd7bca116e1bf9f53bfbf3e11fa49018d39ff1154a06668ef7df5c678e6a: +b1c9f8bd03fe82e78f5c0fb06450f27dacdf716434db268275df3e1dc177af427fc88b1f7b3f11c629be671c21621f5c10672fafc8492da885742059ee6774cf:7fc88b1f7b3f11c629be671c21621f5c10672fafc8492da885742059ee6774cf:331da7a9c1f87b2ac91ee3b86d06c29163c05ed6f8d8a9725b471b7db0d6acec7f0f702487163f5eda020ca5b493f399e1c8d308c3c0c2:4b229951ef262f16978f7914bc672e7226c5f8379d2778c5a2dc0a2650869f7acfbd0bcd30fdb0619bb44fc1ae5939b87cc318133009c20395b6c7eb98107701331da7a9c1f87b2ac91ee3b86d06c29163c05ed6f8d8a9725b471b7db0d6acec7f0f702487163f5eda020ca5b493f399e1c8d308c3c0c2: +6d8cdb2e075f3a2f86137214cb236ceb89a6728bb4a200806bf3557fb78fac6957a04c7a5113cddfe49a4c124691d46c1f9cdc8f343f9dcb72a1330aeca71fda:57a04c7a5113cddfe49a4c124691d46c1f9cdc8f343f9dcb72a1330aeca71fda:7f318dbd121c08bfddfeff4f6aff4e45793251f8abf658403358238984360054f2a862c5bb83ed89025d2014a7a0cee50da3cb0e76bbb6bf:a6cbc947f9c87d1455cf1a708528c090f11ecee4855d1dbaadf47454a4de55fa4ce84b36d73a5b5f8f59298ccf21992df492ef34163d87753b7e9d32f2c3660b7f318dbd121c08bfddfeff4f6aff4e45793251f8abf658403358238984360054f2a862c5bb83ed89025d2014a7a0cee50da3cb0e76bbb6bf: +47adc6d6bf571ee9570ca0f75b604ac43e303e4ab339ca9b53cacc5be45b2ccba3f527a1c1f17dfeed92277347c9f98ab475de1755b0ab546b8a15d01b9bd0be:a3f527a1c1f17dfeed92277347c9f98ab475de1755b0ab546b8a15d01b9bd0be:ce497c5ff5a77990b7d8f8699eb1f5d8c0582f70cb7ac5c54d9d924913278bc654d37ea227590e15202217fc98dac4c0f3be2183d133315739:4e8c318343c306adbba60c92b75cb0569b9219d8a86e5d57752ed235fc109a43c2cf4e942cacf297279fbb28675347e08027722a4eb7395e00a17495d32edf0bce497c5ff5a77990b7d8f8699eb1f5d8c0582f70cb7ac5c54d9d924913278bc654d37ea227590e15202217fc98dac4c0f3be2183d133315739: +3c19b50b0fe47961719c381d0d8da9b9869d312f13e3298b97fb22f0af29cbbe0f7eda091499625e2bae8536ea35cda5483bd16a9c7e416b341d6f2c83343612:0f7eda091499625e2bae8536ea35cda5483bd16a9c7e416b341d6f2c83343612:8ddcd63043f55ec3bfc83dceae69d8f8b32f4cdb6e2aebd94b4314f8fe7287dcb62732c9052e7557fe63534338efb5b6254c5d41d2690cf5144f:efbd41f26a5d62685516f882b6ec74e0d5a71830d203c231248f26e99a9c6578ec900d68cdb8fa7216ad0d24f9ecbc9ffa655351666582f626645395a31fa7048ddcd63043f55ec3bfc83dceae69d8f8b32f4cdb6e2aebd94b4314f8fe7287dcb62732c9052e7557fe63534338efb5b6254c5d41d2690cf5144f: +34e1e9d539107eb86b393a5ccea1496d35bc7d5e9a8c5159d957e4e5852b3eb00ecb2601d5f7047428e9f909883a12420085f04ee2a88b6d95d3d7f2c932bd76:0ecb2601d5f7047428e9f909883a12420085f04ee2a88b6d95d3d7f2c932bd76:a6d4d0542cfe0d240a90507debacabce7cbbd48732353f4fad82c7bb7dbd9df8e7d9a16980a45186d8786c5ef65445bcc5b2ad5f660ffc7c8eaac0:32d22904d3e7012d6f5a441b0b4228064a5cf95b723a66b048a087ecd55920c31c204c3f2006891a85dd1932e3f1d614cfd633b5e63291c6d8166f3011431e09a6d4d0542cfe0d240a90507debacabce7cbbd48732353f4fad82c7bb7dbd9df8e7d9a16980a45186d8786c5ef65445bcc5b2ad5f660ffc7c8eaac0: +49dd473ede6aa3c866824a40ada4996c239a20d84c9365e4f0a4554f8031b9cf788de540544d3feb0c919240b390729be487e94b64ad973eb65b4669ecf23501:788de540544d3feb0c919240b390729be487e94b64ad973eb65b4669ecf23501:3a53594f3fba03029318f512b084a071ebd60baec7f55b028dc73bfc9c74e0ca496bf819dd92ab61cd8b74be3c0d6dcd128efc5ed3342cba124f726c:d2fde02791e720852507faa7c3789040d9ef86646321f313ac557f4002491542dd67d05c6990cdb0d495501fbc5d5188bfbb84dc1bf6098bee0603a47fc2690f3a53594f3fba03029318f512b084a071ebd60baec7f55b028dc73bfc9c74e0ca496bf819dd92ab61cd8b74be3c0d6dcd128efc5ed3342cba124f726c: +331c64da482b6b551373c36481a02d8136ecadbb01ab114b4470bf41607ac57152a00d96a3148b4726692d9eff89160ea9f99a5cc4389f361fed0bb16a42d521:52a00d96a3148b4726692d9eff89160ea9f99a5cc4389f361fed0bb16a42d521:20e1d05a0d5b32cc8150b8116cef39659dd5fb443ab15600f78e5b49c45326d9323f2850a63c3808859495ae273f58a51e9de9a145d774b40ba9d753d3:22c99aa946ead39ac7997562810c01c20b46bd610645bd2d56dcdcbaacc5452c74fbf4b8b1813b0e94c30d808ce5498e61d4f7ccbb4cc5f04dfc6140825a960020e1d05a0d5b32cc8150b8116cef39659dd5fb443ab15600f78e5b49c45326d9323f2850a63c3808859495ae273f58a51e9de9a145d774b40ba9d753d3: +5c0b96f2af8712122cf743c8f8dc77b6cd5570a7de13297bb3dde1886213cce20510eaf57d7301b0e1d527039bf4c6e292300a3a61b4765434f3203c100351b1:0510eaf57d7301b0e1d527039bf4c6e292300a3a61b4765434f3203c100351b1:54e0caa8e63919ca614b2bfd308ccfe50c9ea888e1ee4446d682cb5034627f97b05392c04e835556c31c52816a48e4fb196693206b8afb4408662b3cb575:06e5d8436ac7705b3a90f1631cdd38ec1a3fa49778a9b9f2fa5ebea4e7d560ada7dd26ff42fafa8ba420323742761aca6904940dc21bbef63ff72daab45d430b54e0caa8e63919ca614b2bfd308ccfe50c9ea888e1ee4446d682cb5034627f97b05392c04e835556c31c52816a48e4fb196693206b8afb4408662b3cb575: +de84f2435f78dedb87da18194ff6a336f08111150def901c1ac418146eb7b54ad3a92bbaa4d63af79c2226a7236e6427428df8b362427f873023b22d2f5e03f2:d3a92bbaa4d63af79c2226a7236e6427428df8b362427f873023b22d2f5e03f2:205135ec7f417c858072d5233fb36482d4906abd60a74a498c347ff248dfa2722ca74e879de33169fadc7cd44d6c94a17d16e1e630824ba3e0df22ed68eaab:471ebc973cfdaceec07279307368b73be35bc6f8d8312b70150567369096706dc471126c3576f9f0eb550df5ac6a525181110029dd1fc11174d1aaced48d630f205135ec7f417c858072d5233fb36482d4906abd60a74a498c347ff248dfa2722ca74e879de33169fadc7cd44d6c94a17d16e1e630824ba3e0df22ed68eaab: +ba4d6e67b2ce67a1e44326494044f37a442f3b81725bc1f9341462718b55ee20f73fa076f84b6db675a5fda5ad67e351a41e8e7f29add16809ca010387e9c6cc:f73fa076f84b6db675a5fda5ad67e351a41e8e7f29add16809ca010387e9c6cc:4bafdac9099d4057ed6dd08bcaee8756e9a40f2cb9598020eb95019528409bbea38b384a59f119f57297bfb2fa142fc7bb1d90dbddde772bcde48c5670d5fa13:57b9d2a711207f837421bae7dd48eaa18eab1a9a70a0f1305806fee17b458f3a0964b302d1834d3e0ac9e8496f000b77f0083b41f8a957e632fbc7840eee6a064bafdac9099d4057ed6dd08bcaee8756e9a40f2cb9598020eb95019528409bbea38b384a59f119f57297bfb2fa142fc7bb1d90dbddde772bcde48c5670d5fa13: +0d131c45aea6f3a4e1b9a2cf60c55104587efaa846b222bf0a7b74ce7a3f63b63c6729dbe93b499c4e614a2f21beb729438d498e1ac8d14cbad9717a5dbd97cd:3c6729dbe93b499c4e614a2f21beb729438d498e1ac8d14cbad9717a5dbd97cd:b4291d08b88fb2f7b8f99d0dce40079fcbab718bbd8f4e8eabc3c1428b6a071fb2a3c8eba1cacccfa871b365c708bef2685bc13e6b80bc14a5f249170ffc56d014:a9c5ee86fb06d9e46b379c32dda7c92c9c13db274dc24116fbdd878696045488cc75a52fff67d1a5113d06e333ac67ff664b3f2a405fa1d14dd5bbb97409b606b4291d08b88fb2f7b8f99d0dce40079fcbab718bbd8f4e8eabc3c1428b6a071fb2a3c8eba1cacccfa871b365c708bef2685bc13e6b80bc14a5f249170ffc56d014: +a75e3b6b4170e444781be4eeac3e0fdaa4b4356f705486bcb071a325ae071fba993d38a7d72f0aee15ff6f4fdc37ca7724fd1373a3766b275dbc77e647980e0a:993d38a7d72f0aee15ff6f4fdc37ca7724fd1373a3766b275dbc77e647980e0a:4037866f6548b01cc6bcf3a940e3945aa2d188b4b7f182aa77ec4d6b0428ab5b84d85df192a5a38ada089d76fa26bf67736a7041a5eb8f0c5719eb396693c45160f8:a5db4d3d3329abe3697959e6b5947ea8601b03ef8e1d6fe202144931272ca0a09b5eb0f390572ea7ef03c6131e9de5f16bf0b034244f7e104ff5311bbf663a0d4037866f6548b01cc6bcf3a940e3945aa2d188b4b7f182aa77ec4d6b0428ab5b84d85df192a5a38ada089d76fa26bf67736a7041a5eb8f0c5719eb396693c45160f8: +bcbcf561ecc05a41c7d7e55e696d32ce39b4d03c1f5f3f3a8927fe5e62e844b24ddf53fad6a7a9ed30f3afecca136fd7843b72c243090891ae4021a32cadff1a:4ddf53fad6a7a9ed30f3afecca136fd7843b72c243090891ae4021a32cadff1a:6f6716b6784740980aebc3248807e31c1286ac7b681c00b66c88ff7a336d441fa5c3eb256d20cf6d1ac92ccfe4be6dcc41b1aff846d360c243001cabdfbf1a9b240455:9ff15115f6661f3211d7a40764967629ba6a5263951bdc3c6a4c90d070f7be00024b80d83b6bc27587fcff5f5ccc0eb3cde1497cf56895147a063f61f08adf0b6f6716b6784740980aebc3248807e31c1286ac7b681c00b66c88ff7a336d441fa5c3eb256d20cf6d1ac92ccfe4be6dcc41b1aff846d360c243001cabdfbf1a9b240455: +210532805fa9cc9be916d213cac374e3cd6fc2602a544d0c1ce29d30105d69ab10699e499be99e2b11b98f6f86b67cdc4ccf69f3c53ce094875647d2d0d0ecc5:10699e499be99e2b11b98f6f86b67cdc4ccf69f3c53ce094875647d2d0d0ecc5:9fc4d28cfd25e6c0c5e724e19ca39d71e53bf4aa2796c54c3351f108fc70f2611a62e0ab90af6ade5216788e9eb2a873059b1e79d7d59debd68f2d4d80ffe31bf74b928c:4c2d31d5bbc42e026dc1e079ecc4dd072c5d2cce65e3db8d8a1dd9057faa0371727f727231a0f060fa27097533b6db3b8f6252f2793d75662caadf5f0fcc710e9fc4d28cfd25e6c0c5e724e19ca39d71e53bf4aa2796c54c3351f108fc70f2611a62e0ab90af6ade5216788e9eb2a873059b1e79d7d59debd68f2d4d80ffe31bf74b928c: +185d64b69479e0ba0a5844a10ad84125ba11c4b40d63eda2c57afc7e019c8e0ca5764f6398a5ae2266a38f9714533c4bbd8d07826f63e204cbac374b0acef1bd:a5764f6398a5ae2266a38f9714533c4bbd8d07826f63e204cbac374b0acef1bd:4a0824fe70d4315413d0a0cafbf4f5fe117d5e07e1c3a4effb9d0ae91490234878ccf6792a91f68c6a520de16071f08abe35dc5ea428f1957b663371ce24c609dd55b8f493:43e0387da5ba09a190f6e7b2680578d889769bcc445e5ef571b492871c155c5b9f620bfacfbf2df1fd87444604b71b2e237baaa7ee2093ede4a601edf883e3074a0824fe70d4315413d0a0cafbf4f5fe117d5e07e1c3a4effb9d0ae91490234878ccf6792a91f68c6a520de16071f08abe35dc5ea428f1957b663371ce24c609dd55b8f493: +cfa9d9164b3c4f6f722635d2066cd7ea5e5533d2c74f8add669c371faa47642641169a66f9a63f285782a6c2db81cc3f70b3ada21a68c84745c88a74c3b0a2de:41169a66f9a63f285782a6c2db81cc3f70b3ada21a68c84745c88a74c3b0a2de:757621b1675db7cacef7f2782587ff3af51a3ef2f4bcf9279c4ce94002e1f00424bf0eb621982cc85cb4d171e564a0c2f6e3567a1aae2cddb7e9b25f47dc20a51050542969ca:01d7c9b5701af71e2f4877ffc9b7b5305f52816d4458e37e41c7719fac1d76a01fff3f50fe1a5875ccc3fb70001c947a33fc8b207de13572ccdb8ba98933ab01757621b1675db7cacef7f2782587ff3af51a3ef2f4bcf9279c4ce94002e1f00424bf0eb621982cc85cb4d171e564a0c2f6e3567a1aae2cddb7e9b25f47dc20a51050542969ca: +1acb4a256c2f8993ca24de1e0014606d668b5e756032d269f1d24d351c8eea4acbbdcd8cbc885ab43a057e5f9579f1161954159e7b562ea26cd9a43c88d3f96d:cbbdcd8cbc885ab43a057e5f9579f1161954159e7b562ea26cd9a43c88d3f96d:c46a6d61aa0aed1c1d8547a70b89b7196475d5a4870881b1ecd0f0cb9c745f8a2adc8024e2dc55b53aa5d383a81aabc1a47e8d07d00b7f0b56ceddbfb1f424bb5c02184678a666:05aa76f7fe51892303d78914715995e7d768ff7714ce270f175e56af17ae018d3fa939f5f620de82bcd1549687b205c7871203e624238c4e309fab7f92fbaa05c46a6d61aa0aed1c1d8547a70b89b7196475d5a4870881b1ecd0f0cb9c745f8a2adc8024e2dc55b53aa5d383a81aabc1a47e8d07d00b7f0b56ceddbfb1f424bb5c02184678a666: +ace3c46424823622979fc3a84a7da69c1d527d8312e8fb018375bd3a96c29c18937cf34136d9e1cce0de11b12c70cbfb7455448421e92c82e7c40934bff8c676:937cf34136d9e1cce0de11b12c70cbfb7455448421e92c82e7c40934bff8c676:a9f137bc9021bf105aee25be21cd9ee5b3547cf10cc5f98476fb588bd70e2d6d6b0834e842e4ee94303cf96b09c1715381b36e14a491b80f895ea421b8ec2b1d3c187e02935c5526:feb8896dd3fe6001ffea171b37b788a69f7f850193a63406f56376dd263d099aef80ece67e2c43f40eca462c6b71e79406b18db74ae5d49844e3b132bc2a1307a9f137bc9021bf105aee25be21cd9ee5b3547cf10cc5f98476fb588bd70e2d6d6b0834e842e4ee94303cf96b09c1715381b36e14a491b80f895ea421b8ec2b1d3c187e02935c5526: +88f681934e33c35c07dc6e5a832942ae3d59903ccde2f76ccb7587cea7ec41b66a4e8aa5adb63d22fd7b14a26fdb03b7c8aa6ccd5a196f2c54b0465adb5092e1:6a4e8aa5adb63d22fd7b14a26fdb03b7c8aa6ccd5a196f2c54b0465adb5092e1:6e8bac1f853b81fef94707e18cc61c6f0a9cbc2a41d078dcc83fc0229c7f8dbe6dbdd90854b1f1ae2b9f2b120b86a8786b4e78ce23ab86baaf88754af0f3d88881dae0bc5261bfd038:45b27bf1b9eac06b62b686f6d546563b2dfe5b175dbef32bf78c35a16c958a9d4f26d291de9bb2066c0a286113cc09172d40a36d4cbd951708860226eb30cd056e8bac1f853b81fef94707e18cc61c6f0a9cbc2a41d078dcc83fc0229c7f8dbe6dbdd90854b1f1ae2b9f2b120b86a8786b4e78ce23ab86baaf88754af0f3d88881dae0bc5261bfd038: +48050a6e0158f6ad253412e4497cff62d5ee555edffe59e4dc401522813295ce975e010abb9a3e56659137b0506057f283982f886ca172c7bc2c500ed9bd26c1:975e010abb9a3e56659137b0506057f283982f886ca172c7bc2c500ed9bd26c1:ed6eec29fb7049dff707f0a4426ebc8f5b350e95870b9d6198c8139e9c3e1e409937d1a858a0dea482a5cb1a854ed3b5a9397acb63bff6b64039ef2eb1159e99858310bbbd86125c3e0e:7216ab60c35168187d0fce4753c86e80058d540b76bf95843a5898841060a99a44de6f439625a3f6365f59c377bf45909bbfef5c50b25f3194e5fbd34ea5e706ed6eec29fb7049dff707f0a4426ebc8f5b350e95870b9d6198c8139e9c3e1e409937d1a858a0dea482a5cb1a854ed3b5a9397acb63bff6b64039ef2eb1159e99858310bbbd86125c3e0e: +18d13d0c00e8e3386a5cfb30a9e79fe88b1861ed2d1201eb170038e194770403a4afc833401876090d9b880c41267d68cbbeeaa38afb20884e27328f3b7f535e:a4afc833401876090d9b880c41267d68cbbeeaa38afb20884e27328f3b7f535e:910f6c272dd97931ac47310d244cadb43251365e02ba9f6a5b3c3226be9d7d3a74a2ba4906e8e71a4bf3d3556ebdfc666cd6b12f20c4a00834b88fbb244575199286b0b9344cf334aff007:033988154c5d79d2510be83e778015dfe2fb85b8111f7ec139918b5400e3d656ee80a9f5c9072b5b467a5cc5a57cc8ad1062b5bff10862d9d369dde2cc966701910f6c272dd97931ac47310d244cadb43251365e02ba9f6a5b3c3226be9d7d3a74a2ba4906e8e71a4bf3d3556ebdfc666cd6b12f20c4a00834b88fbb244575199286b0b9344cf334aff007: +4adc8c28646a93a817293a14d29b48e2c6d712a68993547a5c5e4d1452acbc3a7f40473628f23fc0dff0021afd487740d4916a9122e6c97d36433e5ebf04f88c:7f40473628f23fc0dff0021afd487740d4916a9122e6c97d36433e5ebf04f88c:09fb5501f1688f80a0ab9e22d778ae130acaf74d7f5185b4da198c6b9edac4302e2b753e578766e17d4056dc40d95cf4ca8bcc6565795e97d68bcda79fa77c493397716356164caab5d19cfd:6d3b4e90ec408311f9b15b9253d3d95c5d152620c260d56302555a8804a5104ba5e8d29ee108e764a64219297298ab7674bbca784dee28773b34e185a386c20809fb5501f1688f80a0ab9e22d778ae130acaf74d7f5185b4da198c6b9edac4302e2b753e578766e17d4056dc40d95cf4ca8bcc6565795e97d68bcda79fa77c493397716356164caab5d19cfd: +f26e1c84697a4908151b447dcf6c7c7a38b04081db9e7c7738e6fec900bed0c1a86e1422c1235ff8e1aa083470d5e42288cb007ab50e795dd0b4ff87394966c4:a86e1422c1235ff8e1aa083470d5e42288cb007ab50e795dd0b4ff87394966c4:54ed47606a1487c2f900cefb6e899dbaf6c31cc88ebe3558b83b93f6d422c31e888e48e520eeaedd7e554a9cd40c2c519d533b6144cee484c389e976b1e4022b50e7dbb87ead7e541a2004daf7:44f3344b9566c9dfd22d6198e1cbf95d9e28f2982fc7f166ab25dda30c46f768c558e0394fb9ab3e1d4db4cf487c17641a13f3f48939e0c64827a75103c5740654ed47606a1487c2f900cefb6e899dbaf6c31cc88ebe3558b83b93f6d422c31e888e48e520eeaedd7e554a9cd40c2c519d533b6144cee484c389e976b1e4022b50e7dbb87ead7e541a2004daf7: +cc0c33f3a86f5a17d30c186ce0f3b740bafa5fe3c7090f143541e2b2c1e534bc967a71c7cf9b82cc78cbe109104d8b438a8d1fd71d260d029046a9a4526866ff:967a71c7cf9b82cc78cbe109104d8b438a8d1fd71d260d029046a9a4526866ff:1944e5e155d75e0d0be92e1be14cec370ad13791f2bfd40f271214e94fcf213c71bc20d7ce0c7584421ac4efc451883cc3f4956f21f73a4216720438bc38ff2cfdf3709905a50a9d94b1d9e7932b:e277b3dd655c33ff75fa920af1fcc859401e6c7a6ef4c6bfbfac5069638f19ca115baf13c09c82af793facb6abd0cd58e8481b08c1b68ad7a2665c4a614a28061944e5e155d75e0d0be92e1be14cec370ad13791f2bfd40f271214e94fcf213c71bc20d7ce0c7584421ac4efc451883cc3f4956f21f73a4216720438bc38ff2cfdf3709905a50a9d94b1d9e7932b: +f0bc979375a7073068dba7f6c094db6598b4e45df7d549583c22fded8048fa2eb42b6c57a78f1d90090a7181ab2ae09f426cbc2be96eb2cf27abc70d7d32a4b3:b42b6c57a78f1d90090a7181ab2ae09f426cbc2be96eb2cf27abc70d7d32a4b3:27ab3049b5c6351f6cfe38b13a059f5037257ee3d65d6079656856edc876ea081fd8a9480466f8839478088466f51ecbfaf2d65def25f0c4dd8d08588202812232f57945df8a6fa161ed8c0343b583:19dbc3027f9fae707deb76f588f9fd07aa8eae29bd4e1d04c2c984388286b3b122248a6c03ed67eca35df4db3dc1e4237f267892518497d9552a21de19b5140f27ab3049b5c6351f6cfe38b13a059f5037257ee3d65d6079656856edc876ea081fd8a9480466f8839478088466f51ecbfaf2d65def25f0c4dd8d08588202812232f57945df8a6fa161ed8c0343b583: +3022975f298c0ad5ddbe90954f20e63ae0c0d2704cf13c221f5b3720af4dba32b845bce38e26ab027b8247463d437a71bbddca2a2381d81fad4c297df9140bd5:b845bce38e26ab027b8247463d437a71bbddca2a2381d81fad4c297df9140bd5:9aa19a595d989378cdc06891887ef5f9c246e5f83c0b658710673e4e7db760c76354c4f5d1e90db04a23b4fb434c69384593d010e312b11d299c9f97482de887cecfe82ea723bca79a1bd64d03ef19ee:ae14a860fad0051b3eb72b3721a82f7b9546b2867261e2b7b638979e2561bdeb89b600768f82450a66c8b0481283fa21cb6c53bde350effb68a7d1114bfdb2039aa19a595d989378cdc06891887ef5f9c246e5f83c0b658710673e4e7db760c76354c4f5d1e90db04a23b4fb434c69384593d010e312b11d299c9f97482de887cecfe82ea723bca79a1bd64d03ef19ee: +0f710b6c481f71449589753312ef64932b4652ebe0e07597f7da1c4f3dcffb806973ff2932ccddfc1d16c4c0da50c8b29fe6452d1ee84d52064ebf3d628d403e:6973ff2932ccddfc1d16c4c0da50c8b29fe6452d1ee84d52064ebf3d628d403e:85d85744ad55e9ef9a65ca91e85c8a4f80e4c58f8e4e9354e833986098b7d9fe9fdc0dedb0d75d2539fba00034fc0c2e84344d1edaa09d4f63d5546d67803dd6b54ddcc0b1d3f2582dd75289e31de42e69:02a8d26aee11420fb4f09d1163e14b867df7c6f6c8f8dc7a78034659f0401cad0aa90397efdd0704b798db1936503026e2a1adc297e27974d4be312a3753f80485d85744ad55e9ef9a65ca91e85c8a4f80e4c58f8e4e9354e833986098b7d9fe9fdc0dedb0d75d2539fba00034fc0c2e84344d1edaa09d4f63d5546d67803dd6b54ddcc0b1d3f2582dd75289e31de42e69: +7a05f121f60112dd16fee8c91bc2a11479f4b67ee33456042c8de167fc588017b3b05be989cea7197505d4b54335e5e1d77a4b52ba7282604bbc1cf6c4e87a6c:b3b05be989cea7197505d4b54335e5e1d77a4b52ba7282604bbc1cf6c4e87a6c:d9c59e8cc4ede537be2122ab492a5b915a9b0a114b2ade356fc0457ef98722d5f567b86211e28369d14168ec4a3c804076e154adc70a668cf64a20d13cf190d115cd688d036e46938251df4964dc3517b10c:d30ce8a322b450a2fb1afd329cec8559ccf112bd83965f9ec4736270a0914e061196bf5209778c9f8ccf39c4668bbf0e1363f81afe45dd74e80d5875ddbf6f01d9c59e8cc4ede537be2122ab492a5b915a9b0a114b2ade356fc0457ef98722d5f567b86211e28369d14168ec4a3c804076e154adc70a668cf64a20d13cf190d115cd688d036e46938251df4964dc3517b10c: +bf381f8dfb5d0c6d64e416ac23e0d0fcb86ebb899b1d146abd911b92a7808eb6863fad8d1f1bc630a15f6fe8ecefe6b4497b60b21ae8830da46742045fef156f:863fad8d1f1bc630a15f6fe8ecefe6b4497b60b21ae8830da46742045fef156f:8654f2f5c6dcd2cfcbb6ed8d2bc5fb5fec53e3effb0de65aac507fa56c897732395aa09946d3b6586a92edd6dc99315e1ba74c6a0247c4ba7760b948eb3c0932d9fe1f0e9fea6eb61a548a9ab48ffdf1547329:99b75378738fcac8067669e8509b5d2607e1ef76af9004e13fe5d3932df60b168216f58565340fa4d638055a89044ee7d45e2bd082a53382289a34700648980e8654f2f5c6dcd2cfcbb6ed8d2bc5fb5fec53e3effb0de65aac507fa56c897732395aa09946d3b6586a92edd6dc99315e1ba74c6a0247c4ba7760b948eb3c0932d9fe1f0e9fea6eb61a548a9ab48ffdf1547329: +36983241a0a8e60ce02a61b3fafab15a7313a5a270d015b9c9ec070dc42deeda6647984d42b9a5b3b1afa3b7f8f49d4c2b05e38984e99cea8fd68235d2ae4627:6647984d42b9a5b3b1afa3b7f8f49d4c2b05e38984e99cea8fd68235d2ae4627:cebb9e404451818253c0392a4554ee7323c5d5b8b226775700b806ed5b91337916ea7ecbc3d4103fc65e5372ae7e5f9ba2d8f5aee24ccf6e631ae20c4af9b5f728cdf89e8189def1a5b3d35347aa203525ea1d2e:ee37df8af422f91f85dfe43efe79f62378068ccdbaf3916eecbc3adfed0508bdebaf5ce06b3bc279f78087f0db8db3c6823edfb32c12217830be723d8872b30ccebb9e404451818253c0392a4554ee7323c5d5b8b226775700b806ed5b91337916ea7ecbc3d4103fc65e5372ae7e5f9ba2d8f5aee24ccf6e631ae20c4af9b5f728cdf89e8189def1a5b3d35347aa203525ea1d2e: +d06899f93a408dacb41c969718346f1e289bb5ea65e283ff79c705a074517c3546bf2a08a076c47d7f11b733f8141c355363ed85d7def26ba6a0ce15ac5f2be8:46bf2a08a076c47d7f11b733f8141c355363ed85d7def26ba6a0ce15ac5f2be8:0864c39ac4fda8eb9048597bd40be0401021fd2dd3a3390a8facce984b260a13fa2c7cfc00d192fadf134a0ad5a181ee89eff0c795eaa0fbfe2f3b26115d07168db42ed21a51303b1958e4a42dc065b22ce48f17a6:6f89de92a66bc5f4144339124950bdf588144cb372f6736245351c9476becc59a258f9a933ffff2bef4b46cd1057395225799fd09dede6823db0e325dbc8140d0864c39ac4fda8eb9048597bd40be0401021fd2dd3a3390a8facce984b260a13fa2c7cfc00d192fadf134a0ad5a181ee89eff0c795eaa0fbfe2f3b26115d07168db42ed21a51303b1958e4a42dc065b22ce48f17a6: +eebca7966970ee9f2cc4d74c6f1d8e0ebff7c45aebad349fb9f86df628dfff0e89101e0309f767e64ae9c98c4a5d8d2328fb3ef262d082f49b64ca209e1990f6:89101e0309f767e64ae9c98c4a5d8d2328fb3ef262d082f49b64ca209e1990f6:0fac790adb9f59e5cb0ddcb2b667172f2a21034d93bcaddf188606fa9e776db33a8fcc6bd7f5567883fc0de351aa9afaa36d2075b1ba853bada849b8661d5c8154e7b0afea656dd15e01a9c5ba21589b02f8fc5481c2:7d447ee5328c9fe7f11936cc42998754a56cd1d2a6951af4fee7c4a8eb319d4923707c793c55d79067f822d5b16bb5776e38dffabc67237a916a81a63339b0030fac790adb9f59e5cb0ddcb2b667172f2a21034d93bcaddf188606fa9e776db33a8fcc6bd7f5567883fc0de351aa9afaa36d2075b1ba853bada849b8661d5c8154e7b0afea656dd15e01a9c5ba21589b02f8fc5481c2: +3820b6b15939d0afe18c9cb3d9a2a08f167dd458eb6c7e3f1558b0c6db4c689080b85c6559fea8b400e1999cc5bfed507ad7fc294cd9ba0ce2dd2584a91089b0:80b85c6559fea8b400e1999cc5bfed507ad7fc294cd9ba0ce2dd2584a91089b0:3e5ad92d44b40e8614d8087c9c743de0c0861a07f1f5146d71cac2f3740024e841cc2d46027cf5d261d3ee7c1875b39551017b5fb1468114fc3e098a899cdbd558b39f098e156b6e9801ebcdd65fed56dbfcaf2c8c787b:823ee2c0c8d87faa0ec0141e9ce08b51e57c839792d1fbd97a967207fd415849ebfb5dadb5a1dc2c0a8b7fc63fc354857b8c90c44720e13f45cd01e7aa23140c3e5ad92d44b40e8614d8087c9c743de0c0861a07f1f5146d71cac2f3740024e841cc2d46027cf5d261d3ee7c1875b39551017b5fb1468114fc3e098a899cdbd558b39f098e156b6e9801ebcdd65fed56dbfcaf2c8c787b: +0d20fa4a37ff30c4dcc3e44ea7ac501137e5807e9781330ac310982cc3d39dbd67bb0a01bc8617b491eff1a326c1c70f7d0c5b95a5ad48241aedce1c6f0883cf:67bb0a01bc8617b491eff1a326c1c70f7d0c5b95a5ad48241aedce1c6f0883cf:35e0f4b4a517f9c7aa4514f03e6d65f19b27c62cc069f6bf07dd6378bd6afe2b766560006cbd5730a00919ed11191fb0c8dac56e153fc1cea4bdce5046cccb717759a4083e1c16f740763264cc804de0d0e1a4b5a23067af:deab12ed82ba94b469ca98b66fa20444b4b7881c4f0f853409c9a1504a5b2b6d7860f26ada6bf73459b9cdb573c8017121338efa60f4148086d7a3a8ed59bb0735e0f4b4a517f9c7aa4514f03e6d65f19b27c62cc069f6bf07dd6378bd6afe2b766560006cbd5730a00919ed11191fb0c8dac56e153fc1cea4bdce5046cccb717759a4083e1c16f740763264cc804de0d0e1a4b5a23067af: +bee161881d819b370d240d509ba46b06fb828e20310d9f6b309780703e98927b10854380de89162bfb9f7835a2716a3a6e0265671b250b389d01c3bcc03736b8:10854380de89162bfb9f7835a2716a3a6e0265671b250b389d01c3bcc03736b8:5a6fe599b6b09b05c0ba6a622df3a92b3d376d24d04ea85ebe767bc2ec4d14e83e6937dc0b914b4809fdb607906841a6fd1dcdf61aaea8f9bb81b2ccaa32df412989ae53646680a71a211c8440eab0f1aec5e4fc00e6a2c96d:b07d072eb3831fae8a06effa9201797496dce126b8e11fef2fa07f664dc5cf3d4bf9c38a8b3c09fb5f14fa2deb219e7d852fdd27c7ba32d309942f2746dfe4045a6fe599b6b09b05c0ba6a622df3a92b3d376d24d04ea85ebe767bc2ec4d14e83e6937dc0b914b4809fdb607906841a6fd1dcdf61aaea8f9bb81b2ccaa32df412989ae53646680a71a211c8440eab0f1aec5e4fc00e6a2c96d: +70150e9516164a3d7b7e8b6f255b65cac9f07459b32d11bb94b3d277208abc992328bec8e40351047882e8b43bc1ab085386fa47987e46ea87608814c5da713c:2328bec8e40351047882e8b43bc1ab085386fa47987e46ea87608814c5da713c:77be8eceaab431a13c2a28d0d1556489d8c392fd7ae41157f7caf082cb54e45f08626be0076be844d38fde901a5eab0e8832d69dac22fb8507fb8ec4faf7c88fd26da308461afe385987972b5e760a34a5e18b9a82b4aaa529b7:eda3f5033ea7953a0d583c6457522e84ad78445304d48e577d4d69e8641febe15248d8d90ce0944a8f801d39099bc77494bac4ce2a20b38369c6adfb71e03d0f77be8eceaab431a13c2a28d0d1556489d8c392fd7ae41157f7caf082cb54e45f08626be0076be844d38fde901a5eab0e8832d69dac22fb8507fb8ec4faf7c88fd26da308461afe385987972b5e760a34a5e18b9a82b4aaa529b7: +3f87fcfdb421422a9c5fb98268313c15128c78844ef9eb3b3713fa77b6718903533ec59228374bd03a4699e3a8896b86182fcf8fc3085fdb8f5c4671524d6fe0:533ec59228374bd03a4699e3a8896b86182fcf8fc3085fdb8f5c4671524d6fe0:c00fed2d689468bcbacccd446e8d8f299e2a86925e62e59709afaf4857469ff1e006d00fa3e18a3615f8f06b6ebdff785dde58851d2c239038a0c344dce985bd1fc8deb4779ae5f8932e2f9ed5990b6472dbe4e6fef6917657e0b5:f6519d7edb6134111974033f03b8d89e9c76caec8965a8e17cd45fff19de2615d73eccdb4a6664a8f0e23adf98988e96251bf26eb7a4ccaac1079f0a772f9b05c00fed2d689468bcbacccd446e8d8f299e2a86925e62e59709afaf4857469ff1e006d00fa3e18a3615f8f06b6ebdff785dde58851d2c239038a0c344dce985bd1fc8deb4779ae5f8932e2f9ed5990b6472dbe4e6fef6917657e0b5: +44ceef044ff998d4abeaaf374eb41d086718b63097b1e35f89634c14897132eae83c86677d03ed3a5e8c95f41f0b325ff4333702f2ff6936f57ff30aa31485c7:e83c86677d03ed3a5e8c95f41f0b325ff4333702f2ff6936f57ff30aa31485c7:8d3e2dec4644c7b51633b13e6375ca42ff9138465f43d7800c7313199f67c9cf1b520b1820bd630ecf1c992e2767b38eb5bbc441a4ab8d317db441db35a0fe3abe7a9e4541881c2d7b1a2612306959815d1da41267d9649dd4494ace:554552d6b790d421d06b0a67f8e002ad7a1ed01c06cf00cbeaec2a268bda29f1183f0ceafc625fa5fdb847dc86fae1a20406e459d4a0177cb515220a568e08008d3e2dec4644c7b51633b13e6375ca42ff9138465f43d7800c7313199f67c9cf1b520b1820bd630ecf1c992e2767b38eb5bbc441a4ab8d317db441db35a0fe3abe7a9e4541881c2d7b1a2612306959815d1da41267d9649dd4494ace: +98ef2a44d4c8476dff05aa78dcf9c6dc086cb2f622a06745d60cbf223faaba6642fdb1daa39f0159119beec1bedf6f0394b26a2a29bd1fde081eccdadecc226a:42fdb1daa39f0159119beec1bedf6f0394b26a2a29bd1fde081eccdadecc226a:c8b5fcfc3c18c7d95957b668e91c731d50c7fcea4f9575bbf784625870e238df546e2cb1a19d2808dd5b230d3871fdec16100ee1fbf9b722fa3744a750a3b396b05f9c21b8c0f61ead57a78c5ecf72b579cfe88a3f404c8acf524f9ab9:ab5e8724a3e6ff76058cfb214d574e04d05574ecdd4ffe8c07c7af396e882687c5d79ef1e62fbb4c5f1bd06b9bd897826edde0d111d918e8ef961ff2a00d7700c8b5fcfc3c18c7d95957b668e91c731d50c7fcea4f9575bbf784625870e238df546e2cb1a19d2808dd5b230d3871fdec16100ee1fbf9b722fa3744a750a3b396b05f9c21b8c0f61ead57a78c5ecf72b579cfe88a3f404c8acf524f9ab9: +93a8c792a239c931917c114824a0174f8bc4ebbf98af8c7e321e0f5bea4015ec9b2eaa8a9c2c25ff4f6e13bb12bae5d06fda0eb1105fafae5880ff168740bb74:9b2eaa8a9c2c25ff4f6e13bb12bae5d06fda0eb1105fafae5880ff168740bb74:901bf4e041caf16e04f2ffde8d6fe97e93d0900f6bc0fc09a9a0179d137b4b7788e57eb92766a9c634f35adb5c2988af1e86208f461998f59cfec99204b484fbcad3951e7ee4405523705d9739b44307db03f713fda78db421ef3121b3ba:cfe32c4435d911d772dc0727e78d689d0164c5069597cb441b22c1d26236479f1afd7089121b9ab4f61bbb1fae1ab42f7635a92a53784d7170916b703aa5cc09901bf4e041caf16e04f2ffde8d6fe97e93d0900f6bc0fc09a9a0179d137b4b7788e57eb92766a9c634f35adb5c2988af1e86208f461998f59cfec99204b484fbcad3951e7ee4405523705d9739b44307db03f713fda78db421ef3121b3ba: +7001fa0c4404c28aa5b5fcff30a961f21a22f5b85a9e382e07aea8a8924d0ec1daebb63c4d8f40ceba8ec35e3dd946a6b75bc74fcb29ade7b55eee3cc3aea5ca:daebb63c4d8f40ceba8ec35e3dd946a6b75bc74fcb29ade7b55eee3cc3aea5ca:44f48cfb02f08777a57873855f96be4c0291323f2739b275d90757a15472e5750436e0107408fe3026c00625689983f990eba9becbfce403ccd56356ad2741fd21445dfb23d76112e578b3395cf9d960955f1da8f399ca286f21390e25a59a:64eac9ce87460618636b41fd2decc1673bfc48c5f479dfacb51e86686407374b1d10bf65d6d7474214d7770c9e5c7f806c80d53d48b720870e5e78f32e3a7e0544f48cfb02f08777a57873855f96be4c0291323f2739b275d90757a15472e5750436e0107408fe3026c00625689983f990eba9becbfce403ccd56356ad2741fd21445dfb23d76112e578b3395cf9d960955f1da8f399ca286f21390e25a59a: +3adce3a3d3fbc977dd4b300a74749f13a3b04a5d73a2cd75a994e3195efebdac6ff19b1f18d64851d5c74845c6407f0bf596a52e385e020127e83e54cff5ac19:6ff19b1f18d64851d5c74845c6407f0bf596a52e385e020127e83e54cff5ac19:fe6c1a31068e332d12aab37d99406568deaa36bdb277cee55304633bd0a267a850e203bb3fabe5110bcc1ca4316698ab1cf00f0b0f1d97ef2180887f0ec0991e8c1111f0c0e1d2b712433ad2b3071bd66e1d81f7fa47bb4bb31ac0f059bb3cb8:7dda89f85b40539f5ad8c6de4953f7094a715b63dda30ec7cf65a785ceae5fc688707ee00be682cecbe7ee37d8fc39ee6d83c64409681708a0898a183b288a06fe6c1a31068e332d12aab37d99406568deaa36bdb277cee55304633bd0a267a850e203bb3fabe5110bcc1ca4316698ab1cf00f0b0f1d97ef2180887f0ec0991e8c1111f0c0e1d2b712433ad2b3071bd66e1d81f7fa47bb4bb31ac0f059bb3cb8: +14803c1f23a47fcdd35e5d146e20ca630cd712c047d5330b652e31857acbc9e836f2d5bd6d8324fa6e9db7f7d854ebe48c0e6299998122e9d44b8adbef54f093:36f2d5bd6d8324fa6e9db7f7d854ebe48c0e6299998122e9d44b8adbef54f093:555983679d026e5354b4cc055ae1bc14653c7281ec722372f3feb778e841da821b3d0b8ee7a9a9129ea06824be8379fbbdcb0748f423721ccb172a1bafa1d5ae9fc1c51e93d41dd551c3086079b620286c1c40c1223bbcbb76722e92ca21d8410a:07a7de6ce97664b3ea0928e1385c3309be08a47cbf4daa9186a1b948c86fbba39c4efcfcb7a0a3866bc94c6788ffe6be0d4972e56d0c3292d1cc6e25447b9904555983679d026e5354b4cc055ae1bc14653c7281ec722372f3feb778e841da821b3d0b8ee7a9a9129ea06824be8379fbbdcb0748f423721ccb172a1bafa1d5ae9fc1c51e93d41dd551c3086079b620286c1c40c1223bbcbb76722e92ca21d8410a: +1a61154d3472cd96b328ee674beb4fc86763a969fb410494e0678414e31a46a67576d93ac85d0fc61f258c55cf90bd87a635099c0e810ed0b937258d13b42559:7576d93ac85d0fc61f258c55cf90bd87a635099c0e810ed0b937258d13b42559:64c565efbcb8b9528ed47253f3c6a4035db781d6f0976b5e5ba8447d4ed54b04105293ef4c000d8b2e1b5b75e727e5d2a077743b50d183b491764801a2504d16ee6d7d8ac4fe40e6bfc2a8129c7285a5ac691c35e642ed162cf7fbc64516733a23b3:ada1666c9c3b8284b8a21c4f2618ef0808a646f3f10941e470f738e1785e2de9fdd9c8cb526f945c7a8c6994f151b7d066581b1d755307947c62befc8ab7070f64c565efbcb8b9528ed47253f3c6a4035db781d6f0976b5e5ba8447d4ed54b04105293ef4c000d8b2e1b5b75e727e5d2a077743b50d183b491764801a2504d16ee6d7d8ac4fe40e6bfc2a8129c7285a5ac691c35e642ed162cf7fbc64516733a23b3: +f215d34fe2d757cff9cf5c05430994de587987ce45cb0459f61ec6c825c622591ed506485b09a6450be7c9337d9fe87ef99c96f8bd11cd631ca160d0fd73067e:1ed506485b09a6450be7c9337d9fe87ef99c96f8bd11cd631ca160d0fd73067e:fbed2a7df418ec0e8036312ec239fcee6ef97dc8c2df1f2e14adee287808b788a6072143b851d975c8e8a0299df846b19113e38cee83da71ea8e9bd6f57bdcd3557523f4feb616caa595aea01eb0b3d490b99b525ea4fbb9258bc7fbb0deea8f568cb2:cbef65b6f3fd580969fc3340cfae4f7c99df1340cce54626183144ef468871634b0a5c0033534108e1c67c0dc99d3014f01084e98c95e1014b309b1dbb2e6704fbed2a7df418ec0e8036312ec239fcee6ef97dc8c2df1f2e14adee287808b788a6072143b851d975c8e8a0299df846b19113e38cee83da71ea8e9bd6f57bdcd3557523f4feb616caa595aea01eb0b3d490b99b525ea4fbb9258bc7fbb0deea8f568cb2: +8c9f95083075a43fe426d19f1e87719b40043de88eb0ee971f70e10c7694ce4ee91d167aa3ebc23e70aab45dabe905e416262f910e2a955dd8619efc74c24e85:e91d167aa3ebc23e70aab45dabe905e416262f910e2a955dd8619efc74c24e85:b69d70e860f55c427ef2a71df36e05bbc43bb2e06463aa5de34419c6a614eea6695335a87526c1226488d842891d0574df343c9c1e17aed6958ecee87474221eb77a599ecb059344c0d052c0002a66e5a6013185af69a01ba5dbc660d36cae235f67fe0e:cac555222dafec76a0b47b9d2c586b3b3b9b3b9c8364beb3cae1e8dd7f1ae9dd74f22b8dd4ad2b290f81351a415a99f030f10778be4cda85d1d353331e70f109b69d70e860f55c427ef2a71df36e05bbc43bb2e06463aa5de34419c6a614eea6695335a87526c1226488d842891d0574df343c9c1e17aed6958ecee87474221eb77a599ecb059344c0d052c0002a66e5a6013185af69a01ba5dbc660d36cae235f67fe0e: +d7eb1fba424feed100777eedb4874bf20810ad686b67e31d27ecf610609a33f5a25acb11a6c825713a085fa754692886a87d07fb9be1a53eb961728bb66c9060:a25acb11a6c825713a085fa754692886a87d07fb9be1a53eb961728bb66c9060:a1d0f81e3d59089cc2b19e07d2fce43db4cf171faa642f3b0bbde77ae3d53af5c02bf8fc12ffb4e57f7c8a015d6c2d178944fae9f7c8fc969d4b77bea51876ae99d59e94ad2456e0ed72c52cf4e5340da17c44dbff86457a519b6fffe269066290d629fe69:2bf719682b07cc5ecc0480f37e9d123ff6f44c26e6958e59f080466f9cd373a16500daf123dc3f1334774bfc9fa84503b16dbf21a815c1ada6ebef4920461702a1d0f81e3d59089cc2b19e07d2fce43db4cf171faa642f3b0bbde77ae3d53af5c02bf8fc12ffb4e57f7c8a015d6c2d178944fae9f7c8fc969d4b77bea51876ae99d59e94ad2456e0ed72c52cf4e5340da17c44dbff86457a519b6fffe269066290d629fe69: +4f6aeb35fce14fbcbb9aa8a4f6451bf95b98df047fa8c43f1ead3b404d3f928fbf66a9edd09481db8444a176c8ce0578d2934f0cdc9734e86fcaac05bf3330f1:bf66a9edd09481db8444a176c8ce0578d2934f0cdc9734e86fcaac05bf3330f1:2dfbb3f59e19ea17d44a5bde4ad227a1a351dda17af840ee0a75da21a5cca89b6d1c567c333e9cc910e2157e05e86ad5d931145064594c47baeea8663a34649c43e90eb95ca10f7d51597b378a722f1f704adf9f22e9f885b89d1f938006a2efcdb42aaff5e3:6adb07e364f2a455cb05867abc511acd9d658977f0cacafc92828e7b724f6bbf98bf0bfb29f4e5e6c74738d4fdd816d9252407ae4f3afc574c4f00614824e2032dfbb3f59e19ea17d44a5bde4ad227a1a351dda17af840ee0a75da21a5cca89b6d1c567c333e9cc910e2157e05e86ad5d931145064594c47baeea8663a34649c43e90eb95ca10f7d51597b378a722f1f704adf9f22e9f885b89d1f938006a2efcdb42aaff5e3: +ef4a6762b400975204ccc13abb47344015454906850ff14940cbb83aa22414aeeaca450996f50cfaf2bd7f9d7fa7087f09ad49664206a80bc2e5bbbb85bb668e:eaca450996f50cfaf2bd7f9d7fa7087f09ad49664206a80bc2e5bbbb85bb668e:a4b63eaed5a64a94f2cad212ce2ae71092fd3ea744f5bd89562b2fc2a6c9e4d7aa27add56264a5a55016610be6c19ff7d4989e9504740853012715a79ece9e12c301b3317c7d9b6730db862a4a1d28058e0f8b5ddd9738c7c62ea572cfe59eae08e2b8b6593b58:02697d44cad862f1daf5708205f450d408525b10c01ffd06cfee80374f3db16fa9a49c19a9844b345f2f9559ea74aab173baa078c54370a5166700c6dafb780aa4b63eaed5a64a94f2cad212ce2ae71092fd3ea744f5bd89562b2fc2a6c9e4d7aa27add56264a5a55016610be6c19ff7d4989e9504740853012715a79ece9e12c301b3317c7d9b6730db862a4a1d28058e0f8b5ddd9738c7c62ea572cfe59eae08e2b8b6593b58: +55017e5f61f0c5bafbcde6f849f42a31e5e7a878c1d3f9126fc569fd417ea9f266914f74ed932fc881ff0166683f675a7c28a926fddd6469cdb3f28e6dec42cc:66914f74ed932fc881ff0166683f675a7c28a926fddd6469cdb3f28e6dec42cc:2fc84a0998fa6e168a866410bb68105df249a28cfc76604be94fd7dffff2fc1dedd220199465575e8df860190f16aca4084169be16c6ba32eb67042ffd4f230316a26b2624a42f8f90ad57f6916486fa91fd94ed68aded4e632430ef719446979bfaf345409c387f:b1a5e7c49b8fc6b4331e0416ce7e4ed59edd56300b802e0d72abca4a6fcb876c03bf331579124ae0d3fe43f7898bc87e93fc2da3970fc8638957d18c6613c8082fc84a0998fa6e168a866410bb68105df249a28cfc76604be94fd7dffff2fc1dedd220199465575e8df860190f16aca4084169be16c6ba32eb67042ffd4f230316a26b2624a42f8f90ad57f6916486fa91fd94ed68aded4e632430ef719446979bfaf345409c387f: +0553fba866942341217cf278ac57cb21acd09d9916cc6af0ac46941ea139d545840c66e57c2d4f52a4a2796d2a53c5709b96a628c2e063fe6efd47f283ef5e82:840c66e57c2d4f52a4a2796d2a53c5709b96a628c2e063fe6efd47f283ef5e82:c1fae6262a0e98a6b1235fcb62283b7f0a097f9d002416d318fefc60c5a1584f900ad0ab26ccfae0d6d84aa9aa2df16d4c117ea2724676cb866d4870a872fc829a7c2a5d21ba83340adb339a34c5184c7f5ead0f077289b33677ed6a1ba34be1994e25763bd1d9faec:bc3364c152ee5c808ac340f49ea2cc404e93517121220cce6f7c30a22500e41bcdb6e820480f8fccdd22ff9ad96da532802f431e94240fb83d4bceaa09b92b0dc1fae6262a0e98a6b1235fcb62283b7f0a097f9d002416d318fefc60c5a1584f900ad0ab26ccfae0d6d84aa9aa2df16d4c117ea2724676cb866d4870a872fc829a7c2a5d21ba83340adb339a34c5184c7f5ead0f077289b33677ed6a1ba34be1994e25763bd1d9faec: +7a5ac602de19f3c21040bcddbff42f6aee6f95c1b093868f48e50482dbf4f9c7fbb6c7531cda21e7d17ea903c4d14be6c68b4ca803a16bd87120f5aaf7dce1d4:fbb6c7531cda21e7d17ea903c4d14be6c68b4ca803a16bd87120f5aaf7dce1d4:bd1685419279eb81e4cf3c909031f0f09c5ffae7e2ce6ba9d96c2bce87b8ba0dd763231001e532c7ddd62103abf701288e19dd8f5302e8f5d31b64cc339bd8b7a95550c8a116fd486948772bd5af8dfd46001c59767b0d6bdce383a7078992d1022fbcaf90710687b9aa:84101dd4b5e8ca3ed98c1e8a06e11d7e424b0d12ca714ee7374b64c29d51a2021cc77ac75389d9b0a646a447623d7d04d1241866b0ca6edd1b7ac015666b700dbd1685419279eb81e4cf3c909031f0f09c5ffae7e2ce6ba9d96c2bce87b8ba0dd763231001e532c7ddd62103abf701288e19dd8f5302e8f5d31b64cc339bd8b7a95550c8a116fd486948772bd5af8dfd46001c59767b0d6bdce383a7078992d1022fbcaf90710687b9aa: +50414cf549bcc55b5b6b75ea3782b2ea7c087b6a0106175e469ca2cc764aeb01d0f30c12e997f96e7aeecd1bff6a012ec388ebf8f3f4af664804d1638e4c346a:d0f30c12e997f96e7aeecd1bff6a012ec388ebf8f3f4af664804d1638e4c346a:75ad77e8c54b0b05fb2d162e7cadb8a7528081b863f76a441b374469413e5714edf54f800496af0157c17e425583414d4361f2134171c0b87c22ce6820a4850ab49d99a9badce9e36110e7f3060118b3590f82b43771e9fbb081afe62227e024d98de6cdec028d7c49490d:b309800160de43a63a89a0acb8a6050059589b3eaecac20b256fece438042f69415d8a56883ee3836d3134a7fc1de64fa8c8cecc3ce27589f606058820857a0c75ad77e8c54b0b05fb2d162e7cadb8a7528081b863f76a441b374469413e5714edf54f800496af0157c17e425583414d4361f2134171c0b87c22ce6820a4850ab49d99a9badce9e36110e7f3060118b3590f82b43771e9fbb081afe62227e024d98de6cdec028d7c49490d: +93cb00d8fe9c9777a683631f39ba0f48761482cf1c366bd863cf71510153255587e94a1ea5258d61180cb828590ff1418a87d01e702686ba8abc2692c8dc3c91:87e94a1ea5258d61180cb828590ff1418a87d01e702686ba8abc2692c8dc3c91:88d8538d31867813d88fef7228d49a7e950d738396f116dda1025f7913547c5d1dc5677a6de4b4a5880507b361780b61b43f7795263db22ff341645f2f5914fd6088c2811211ed4756ac019a6035d66e3170c1d82bfaa30596b396b3260cc1d10d413dd47ebe6daa0c30dc42:09824fa2dfbc4d6ef76a9e4145961116769130553b3edffa50d04f39b8b79facbd237acf71354a53a6e5fee754e823b0b290f9619320a13d561269a221639f0388d8538d31867813d88fef7228d49a7e950d738396f116dda1025f7913547c5d1dc5677a6de4b4a5880507b361780b61b43f7795263db22ff341645f2f5914fd6088c2811211ed4756ac019a6035d66e3170c1d82bfaa30596b396b3260cc1d10d413dd47ebe6daa0c30dc42: +2b4cae380e95ce694c26ac7957447347f98e31b4bf02d744e131529071e2301de6fc705a79c98e115b4e28d3aa1506b74ee74276c5fc1109a7f4d89c6fafb889:e6fc705a79c98e115b4e28d3aa1506b74ee74276c5fc1109a7f4d89c6fafb889:e0b8250e27b7c0291dbc47a6da6f1268987afdf0a1e90be69bcbc4370865217830d5208693be7b7045099a22ea27f952eb3f79a9a0f1b5a87b19367790788d34c219c2e2a6b834020fb4fd149dc56b544fddbb42071a162fc7cb33c146cac05a31b183e9daadc616f3af449b17:555e45656ba9cfbf5155d0e52576e5197abbbc9dd233993eec2a1ee7f6a86409c0b71b0a661978ff5e0acdc9463dc449906f474f8e79bb86168bf70741e34b02e0b8250e27b7c0291dbc47a6da6f1268987afdf0a1e90be69bcbc4370865217830d5208693be7b7045099a22ea27f952eb3f79a9a0f1b5a87b19367790788d34c219c2e2a6b834020fb4fd149dc56b544fddbb42071a162fc7cb33c146cac05a31b183e9daadc616f3af449b17: +b56491e54999bb5a1715ebfa2feb14a545a3a43c2fdfd4be0c95fc11819ad695cd42bf414f9bfc72ec069882a800557cdf31bc3464fb102c310e6dbd3ae20863:cd42bf414f9bfc72ec069882a800557cdf31bc3464fb102c310e6dbd3ae20863:eb4418ba30683ec7959bdb1ec7b263f83e81f054ddcdbe0a6738ca7763e246935bac419026c22bfbdd1236336cc16107c53513e3ddf34e120846962c3bdd54f5ad5749597208f15a8bb56667baa895f08340db89b85c435e770931928d8abc99262f839aedd9be2aa138c9259adf:e3be3e71a89852df3cffd72d68207869dd3eceb49b1f029493eccbb932444ebe8c8c6db5f0a5a67e2194408df9841913a5ac1a606896419a668f4f47c56c2b08eb4418ba30683ec7959bdb1ec7b263f83e81f054ddcdbe0a6738ca7763e246935bac419026c22bfbdd1236336cc16107c53513e3ddf34e120846962c3bdd54f5ad5749597208f15a8bb56667baa895f08340db89b85c435e770931928d8abc99262f839aedd9be2aa138c9259adf: +6579c247dd2cd02ba2f7d7a950a330752681e92c0dc62984bbea279ea521c3810b087bea1a1b3d15805cb604f4bb8d68edde274faf521fe6df50c55f8ad4a70d:0b087bea1a1b3d15805cb604f4bb8d68edde274faf521fe6df50c55f8ad4a70d:df7c552ffc89374b9571a6024a8d0471d7eb6be8dfca6f4166b581b65479015a0568129074cc04d6342c758ca18f7987dec536b7033d5f9681504340e20986f027b8cf1f263be76db3525d173422950ea8dceddc585640918aa9d25ca89cba701c2020153873f46108c772cb388d55:eccaf801ae0a912e21c6b83a5f0e4e88d4b2713459ff93449fc0b21a9f416050113cbae4e814d20c0a798f76d2f9d326ed83959ea02abdc1ab350a467123f709df7c552ffc89374b9571a6024a8d0471d7eb6be8dfca6f4166b581b65479015a0568129074cc04d6342c758ca18f7987dec536b7033d5f9681504340e20986f027b8cf1f263be76db3525d173422950ea8dceddc585640918aa9d25ca89cba701c2020153873f46108c772cb388d55: +18fba60c5026f3c9dd7aedc04209d5260361de400e190aeb60169e05a3367c9fdfff347f3dd255530bf7fb34d02ba486d112bb46e950e2ef80e517014cc95734:dfff347f3dd255530bf7fb34d02ba486d112bb46e950e2ef80e517014cc95734:34f08a804d7829cc3914f000ce1a3288acce2149c8a02086b9f67afccd83a178b0bcfd4970c056997da7dc3d47562f16663cedc52f82d710850cf4050379efdac23bee17c330a383ad137f788473b2b0723603b6deb1fdbf6c523fc948a0ccc4ff100fb946d874c1f990436ae8c4f3b2:4bc011e40f0f59c618f6bbe230b6f7bc2f50e3617c7faab7f4c21cb84f77eba994cb7c2a1bf10b01bb20084497fdf0a6ab5d9bcd22c4a2c5a78f79926825940f34f08a804d7829cc3914f000ce1a3288acce2149c8a02086b9f67afccd83a178b0bcfd4970c056997da7dc3d47562f16663cedc52f82d710850cf4050379efdac23bee17c330a383ad137f788473b2b0723603b6deb1fdbf6c523fc948a0ccc4ff100fb946d874c1f990436ae8c4f3b2: +073cc15b0536285933b2be39253cf4fd696b81610f5dd3adac2e9cbf338ef2f600b551d371544375dac5c4e96cd1f0215207e8e166a1fe49d5b0a51ac18443ec:00b551d371544375dac5c4e96cd1f0215207e8e166a1fe49d5b0a51ac18443ec:c285362bc8ef628f7aedf654231ee51acdf2cf69a886b942bb9bfed8155105d9209ded2af24f169ad5fcd451370f5827a85111c7a52e032c5038617c0c0170e2a6c231dc401d12062edb186036114e38793b79089077581b9783f40007103ef17472491c00e7138aecc5084d3c85010470:3aa52a83062a8f28a5d6b7607f484b66cc374896b766123126333c579581316c742806f627b5bc55cad705cc1d4782b044080c8ac840f38c0c50d35e345c7803c285362bc8ef628f7aedf654231ee51acdf2cf69a886b942bb9bfed8155105d9209ded2af24f169ad5fcd451370f5827a85111c7a52e032c5038617c0c0170e2a6c231dc401d12062edb186036114e38793b79089077581b9783f40007103ef17472491c00e7138aecc5084d3c85010470: +fd894a1e8232203b289505d5c68c68791ffc0e54f2a87530fbba5b3a3f2caf00e95ab565945c7ae5d533df5d0cccc7e9abbc838e20a0b61c930f5d41d81a6fe7:e95ab565945c7ae5d533df5d0cccc7e9abbc838e20a0b61c930f5d41d81a6fe7:2669624a94f2c44a05b7dc3ebf93e58a4bf3a01c273657e7e7878976f6b6ea737fa3f22cc8365b8b220c007d5b642726a408fe2fab69ebb3bd072b349f4dc3377ee7cc752934254215d23989bd3cd02ce999adec9784993f4c19940815f39c9e229247f5205c36cba44e714266369289b4a7:f51102219e8804be713e556df4e4afa2f8866fe86541a1c2a0934d24c3c9beb280a70dd8d527fe8b7e0b948214d5f2f9638619914b72d55dc198b0229a8487082669624a94f2c44a05b7dc3ebf93e58a4bf3a01c273657e7e7878976f6b6ea737fa3f22cc8365b8b220c007d5b642726a408fe2fab69ebb3bd072b349f4dc3377ee7cc752934254215d23989bd3cd02ce999adec9784993f4c19940815f39c9e229247f5205c36cba44e714266369289b4a7: +18ef464e28f87ffcfa4d3a9c09a22910951b8c719fdacdb56de62c4b406df00cc5064c9d43ee2da75b06bb09c77267dbd0d39128f1cdc6bfa451a03e93af4a70:c5064c9d43ee2da75b06bb09c77267dbd0d39128f1cdc6bfa451a03e93af4a70:9c825707d9358365ab9d38f7e728d628aa722a4f1a20a38e47c999fff8fc32417fbe072f96eb6a0e11e4da9b6de9615445280e93c77a3634d3d2c6879856c248f9800f60a0d38dc1cea8b7f31f286cb0374827b4c6ba144a6694f2b908ead68d18340124cb59cf1701863bd4f3efc709f3627a:d1e7f16e8e597d428adea65591d551b54b667aff2020c464f7f4e53c4773f70433249a3c71b4d11c89c3faa892809227b9f29ef4f7f5d020d4674d40213594059c825707d9358365ab9d38f7e728d628aa722a4f1a20a38e47c999fff8fc32417fbe072f96eb6a0e11e4da9b6de9615445280e93c77a3634d3d2c6879856c248f9800f60a0d38dc1cea8b7f31f286cb0374827b4c6ba144a6694f2b908ead68d18340124cb59cf1701863bd4f3efc709f3627a: +c911bdf2f9e7cc5fff35c96e15cc12eafd05ab0db31f649f7408acd0cada76e0de44696cd6bd2cbe9b11a0ef18b88164801a969d5e06ed453eb4008cce9a5725:de44696cd6bd2cbe9b11a0ef18b88164801a969d5e06ed453eb4008cce9a5725:76c471241d17192984b00362696e4d9d4d2b7f839c2064117e50a1598f3a1172b16c55e5396866084752024f3a7eb68bb3ffdb80979a0af6d0f6af26b6f0bc0c0384433bcfd44c75eb654a8a8225cb9c4a7fb3c824c3af6125fd46db287e70492d154632cb8f62432659d958d6281d04a54f5f5f:d584b5da371ae4f5c9859b25f70dc56c1b7b4e02d1ae6636283b1b7b11217afdcdf65d1b49ca2c8ef17966e9bc65f10c310b77bb5df7aff5ec1b379a2ce55d0d76c471241d17192984b00362696e4d9d4d2b7f839c2064117e50a1598f3a1172b16c55e5396866084752024f3a7eb68bb3ffdb80979a0af6d0f6af26b6f0bc0c0384433bcfd44c75eb654a8a8225cb9c4a7fb3c824c3af6125fd46db287e70492d154632cb8f62432659d958d6281d04a54f5f5f: +d3703299c41db36d77dd3a49541f3fb21d0b2bad1f6e074affd96f1c40d0f927862c5ef616a5f066fd87758a56ab45056fea4bd33f008be24f7b540e095e148e:862c5ef616a5f066fd87758a56ab45056fea4bd33f008be24f7b540e095e148e:ac92edbe22257bb06d94aa950e62d18ca2ac0a8fc106000d2231f8a13b8d7a209ccd8cc49a6cd68a7f36c02fb8f728d15595167f0ba8cfe95c8a1e435f327513014ac428b75d4f72e7c834dd70e1a448f1847d3498475f74e3d9334dc7dcc4fed72bf6c7fe3b1d4f53d429616f1df44f19733158b6:df28277121eac44630084cce75917ae9f6bec65af5572dc30719bde661cf696b85b8672dd4983cab30bd05cc3a119d7db9babd522d7b3a6bcf3886ecd25e080fac92edbe22257bb06d94aa950e62d18ca2ac0a8fc106000d2231f8a13b8d7a209ccd8cc49a6cd68a7f36c02fb8f728d15595167f0ba8cfe95c8a1e435f327513014ac428b75d4f72e7c834dd70e1a448f1847d3498475f74e3d9334dc7dcc4fed72bf6c7fe3b1d4f53d429616f1df44f19733158b6: +d411cd33576d0efe9ec413ccdaabd4fcbafec01a3af4b3cbe34f8b05ef8b59bae870344df98dd3a8702c4519bf9e8b35a9d189e746f7203dbbf9bbfab22d6f63:e870344df98dd3a8702c4519bf9e8b35a9d189e746f7203dbbf9bbfab22d6f63:11d2c2a7f0190988126696431b4bbcd90ab7b56a32da6404ae446aa762a4ddc66094971538eeb85bde0470a510be0d6d85780ee730a9854138728ae6816162268da852858eaed4ec74c7ac62e6e7096dc002df0bdf5fa40da565b41d181a3f0ad0c5e0b976743e315d9db8ed4160abe69c13a2b3f09a:83460d15461d6717710bafd6a47a1eaa900a80f2bf8b8aae2468773614ee84bd628c9717476368ef3640cf760acac83ad60232a76963b7d52588b11dc004d70d11d2c2a7f0190988126696431b4bbcd90ab7b56a32da6404ae446aa762a4ddc66094971538eeb85bde0470a510be0d6d85780ee730a9854138728ae6816162268da852858eaed4ec74c7ac62e6e7096dc002df0bdf5fa40da565b41d181a3f0ad0c5e0b976743e315d9db8ed4160abe69c13a2b3f09a: +e10a2f1380c3e4720e8a8707a9bcb25a0f58270d7059cd7626c7153447edfb87a3c717acab366a40b51187bbf35b2d15e97cfeacd7349c06ef1c91ac93e90656:a3c717acab366a40b51187bbf35b2d15e97cfeacd7349c06ef1c91ac93e90656:135212a9cf00d0a05220be7323bfa4a5ba7fc5465514007702121a9c92e46bd473062f00841af83cb7bc4b2cd58dc4d5b151244cc8293e795796835ed36822c6e09893ec991b38ada4b21a06e691afa887db4e9d7b1d2afc65ba8d2f5e6926ff53d2d44d55fa095f3fad62545c714f0f3f59e4bfe91af8:094bf6f953ca0eb77df45129b7bf10d192cf6ddeae94ad6202b8eacfbec119e5291578fe64a084ae600fe07efdb8a782610dbdb0b49eb5f2a46c432355552f01135212a9cf00d0a05220be7323bfa4a5ba7fc5465514007702121a9c92e46bd473062f00841af83cb7bc4b2cd58dc4d5b151244cc8293e795796835ed36822c6e09893ec991b38ada4b21a06e691afa887db4e9d7b1d2afc65ba8d2f5e6926ff53d2d44d55fa095f3fad62545c714f0f3f59e4bfe91af8: +b2e697b3d3efec976ef3369530c792717bdbb428d9ed0c11ec0ea9b2e5f39f82c4d2e4b3c236d6c9b8c74fa384612c4710d83aa16ad7ef01fbb7421d4fb3f0f6:c4d2e4b3c236d6c9b8c74fa384612c4710d83aa16ad7ef01fbb7421d4fb3f0f6:7b436232ac2111a84059510c48362588fcb7383426be5e6f62f372e4f7cca83c81c2357f9b54f4a15291065b6d41aad1ea93cffa776b9acaa58afe2b51644b97af9a3e53f84e40aa6d86051e6914cd039d4170a9a526dd69955ff507c33f74e2176591fb0b3cd7f00ee418f2c258a9981cccee72f01c8430:5047fa38197b8328e78dd8a10e966afb7bd3d43608280f1c257d25ca43bc1c06e94a5747ab6215ece54cdeff8c56567d70d2f91f9ec8c260aa1080a6ab5a7a027b436232ac2111a84059510c48362588fcb7383426be5e6f62f372e4f7cca83c81c2357f9b54f4a15291065b6d41aad1ea93cffa776b9acaa58afe2b51644b97af9a3e53f84e40aa6d86051e6914cd039d4170a9a526dd69955ff507c33f74e2176591fb0b3cd7f00ee418f2c258a9981cccee72f01c8430: +19a679a7a905a1e2b3038e6e418b3da97c3089c7cd351ea07bc8d1af64eacc4619f08361f469b4ae1e0ceb94f47a7de7317410a92dd013b16ae0d0532fa4b3ef:19f08361f469b4ae1e0ceb94f47a7de7317410a92dd013b16ae0d0532fa4b3ef:980c7b4d2939061ac7b9ba441117a19485661781a4083067c55acf93026c082a93cc124f095e1b4f2c3f6c135412a5096228e8a071e8b4b668ba9d9644ea9f4dabfc54a9856c3e965e6363395ab709037dda229baf927cd01f9af5e039afc42f3cec634f5d832d2ab7c7cad3ad7b8cf27ebdac698431ad8236:4347b7b4f7c3c4dd315b8384a0b0caeed84bdabe24b2915f12512dfd04770fc996a1bfb729afef9edd611447081a5330617eaea1c1dab1bf13cea8997204910c980c7b4d2939061ac7b9ba441117a19485661781a4083067c55acf93026c082a93cc124f095e1b4f2c3f6c135412a5096228e8a071e8b4b668ba9d9644ea9f4dabfc54a9856c3e965e6363395ab709037dda229baf927cd01f9af5e039afc42f3cec634f5d832d2ab7c7cad3ad7b8cf27ebdac698431ad8236: +f03b8363ee5b0eef7018a49bc02adf731da54ee50a7f03b88a29a2082b189c4331287ef5a2e64104ab7790b312f35c7ad4af6beb0d7ceb8a58f36a54ce272c3e:31287ef5a2e64104ab7790b312f35c7ad4af6beb0d7ceb8a58f36a54ce272c3e:24191b5464b35ac7bcf4a375f033efba8943b09b9ff0fc403ca7aae702a3cbf396c5131bc008132cf5f12910d586dc1db9c084574a96babee95642f922371c0382ec0402a26feb142e4146bbd3360c2b36834fe45af5e2868d4d56fdd504cebf0c2d7f5791b4429417c8b65a98e0b15c466c137f410524fce737:e8fa967e6afadf6a877d87e5f5c52bb634b75a7804199a2bc9d027b63a35654d9ddd06830455641dbfb49edce42e20e7d4104a071c2cbbec23018c297ced990824191b5464b35ac7bcf4a375f033efba8943b09b9ff0fc403ca7aae702a3cbf396c5131bc008132cf5f12910d586dc1db9c084574a96babee95642f922371c0382ec0402a26feb142e4146bbd3360c2b36834fe45af5e2868d4d56fdd504cebf0c2d7f5791b4429417c8b65a98e0b15c466c137f410524fce737: +11086b0d11e415ab1ce02aaf8f0621b54430f6fb135c74f40d38e8c64737064b7166dfbc691eb8c201114ba0d1a2c7b87f7a1fd8d0b36058b0d7dcabe1ae30da:7166dfbc691eb8c201114ba0d1a2c7b87f7a1fd8d0b36058b0d7dcabe1ae30da:4b5b2936c5e360a38455503721078f8adb404a7ee7ecc14801dc87a67a152b769569fbeac0afa25a2070a1686b900ac1633d499808cdb2e81ce3916d5a3c04d19c5bb2699a662b8aba4af94d390bac7ccc8ec910ed2acdf86ebb71adb601877885eef3c91662fc30738e352cc74353ccf8d8edeefacc042c10a0e5:e907459d5adcd0d0c36418581f19d0eebda7138ebd9faa0b262201f458c856310bb77f4c7de922495dcfe8b248eda2ad0df6a73f47bbfb894baa7d88698758024b5b2936c5e360a38455503721078f8adb404a7ee7ecc14801dc87a67a152b769569fbeac0afa25a2070a1686b900ac1633d499808cdb2e81ce3916d5a3c04d19c5bb2699a662b8aba4af94d390bac7ccc8ec910ed2acdf86ebb71adb601877885eef3c91662fc30738e352cc74353ccf8d8edeefacc042c10a0e5: +efce7667a8ef91228caed14eb477a345e5e8239234080848760ed0970713fa869193055a84df1eacca28ce2a08c2a07a50f04c024ecf1fe4a47d2efbaf63ed58:9193055a84df1eacca28ce2a08c2a07a50f04c024ecf1fe4a47d2efbaf63ed58:aa1bc80d7bcc1d94a23a57cedf5027482477dc46b86890bc0e5ac29ae6c91bbc43130348797305f75543580a8a069b348a7bd8fc3e015230b7c1940c7f80a82b12900910dbcf0630da03f081d44c7f955d4a1172f56ecc7c5ac646696bffdf4eb6d88bdd9cc3843528b72583abb3bad02e56ef7646eed5139551cdeb:e5a63124db1696b64140b6e9612fa9587b3eef710109398d44ba0ca63c0ebad06f0a6c8994ea34b3a2af91a89bf41ae614d7727d716fd42f8b92e1ac64fdbf03aa1bc80d7bcc1d94a23a57cedf5027482477dc46b86890bc0e5ac29ae6c91bbc43130348797305f75543580a8a069b348a7bd8fc3e015230b7c1940c7f80a82b12900910dbcf0630da03f081d44c7f955d4a1172f56ecc7c5ac646696bffdf4eb6d88bdd9cc3843528b72583abb3bad02e56ef7646eed5139551cdeb: +88fccaa96ad884d1165be71dd0c4f5f8f4421c60fbfa498bfee9b967462443bdc75cb0e0237b45b8656eea9f3d1a9d4acd01a103aa269bb24fd54122fd81f2ac:c75cb0e0237b45b8656eea9f3d1a9d4acd01a103aa269bb24fd54122fd81f2ac:9d0eac98556bfa8672c35705d1d61ac4d0fca19dc0d993015877857d27fd80f74acace666c563485d81e53603a6aef40875fa551cc105f2cc10b39694679cdf4a6b073bc88645fc51a36da179d3d1e3c7722454c5e73577c61aa7d148c4ba50ea46c56a1c3b3b3c470f93100494e08bc5514ac763a85483c42c7cdc27c:27d3a197cc9994212063bce8d799e77b6853b7355ebe369bcf1889a418a82caa3a7987a663f621defe86b3ac4ad44faeed16c9116ace28fccf915557fa7799039d0eac98556bfa8672c35705d1d61ac4d0fca19dc0d993015877857d27fd80f74acace666c563485d81e53603a6aef40875fa551cc105f2cc10b39694679cdf4a6b073bc88645fc51a36da179d3d1e3c7722454c5e73577c61aa7d148c4ba50ea46c56a1c3b3b3c470f93100494e08bc5514ac763a85483c42c7cdc27c: +670b30626fe367d8b45f43733d6f25b37eccbcb551963f0ac8b666b48041c72d65aa4c6d4ba0ab34bc75b39f09527ca6f2425f52415cdffdf2dff273f8ea612c:65aa4c6d4ba0ab34bc75b39f09527ca6f2425f52415cdffdf2dff273f8ea612c:d00bcca7e184d10e1f1fe420b50639e1d5deba52a751236e68c59bb4bff9802f5fc165ed42fd6d534670a7c6fb60e4307d947915a248bf2f93465c2cb44d8f453d2c015afbc8ed58818ea51726a25177930e9ea192ef4514f4bb0eb4e0f5d4ae3c46e357c81187f7ed174733fff959c3f9fae6486cfa1356a95699211de5:1b6b4377d2b98e0f9d24ae8dfe30e2396e2004380d3431488e5843cf8d2d7a0070ab21f8a3b51ce84d2f4ba209f739f922bebf798096693f5622873d79ae6f04d00bcca7e184d10e1f1fe420b50639e1d5deba52a751236e68c59bb4bff9802f5fc165ed42fd6d534670a7c6fb60e4307d947915a248bf2f93465c2cb44d8f453d2c015afbc8ed58818ea51726a25177930e9ea192ef4514f4bb0eb4e0f5d4ae3c46e357c81187f7ed174733fff959c3f9fae6486cfa1356a95699211de5: +813c4daed67a190d68bb635d73af6da74f32fdf7c48cca6e59262946b8e8c71fa2095457d7697020e2b884d95a96578c2a900a7666ac0dc7bd38f1931d7945d8:a2095457d7697020e2b884d95a96578c2a900a7666ac0dc7bd38f1931d7945d8:ce54cb0450e689a0dbef785308b3177472fcd6d38203e58a0590b31fa253f9ea590be5368a922de88b63450102684443fb8189e601282003323b89c81e92eaef2b5ddc4a55c53fa3cfad4160248b3c286ff80d31d161b7b8dee713552b56f1507fb72eadfa89054e9d1600ac874c4b0a961004eb6d0d4bfd2ecb9c734f00ba:b446574ff6a4bd2b572e487c4ab443ca641075168aa4e1092f71f30bdb068ce46a395efee1ee660b9fac26d54109722c15cdb791bfb87fff63c6596ad4f2270cce54cb0450e689a0dbef785308b3177472fcd6d38203e58a0590b31fa253f9ea590be5368a922de88b63450102684443fb8189e601282003323b89c81e92eaef2b5ddc4a55c53fa3cfad4160248b3c286ff80d31d161b7b8dee713552b56f1507fb72eadfa89054e9d1600ac874c4b0a961004eb6d0d4bfd2ecb9c734f00ba: +8400962bb769f63868cae5a3fec8db6a9c8d3f1c846c8dceeb642b6946efa8e398be21001993a7eb1a1277ff74c15504183d25fdfcc05f0d4dea892f6e301890:98be21001993a7eb1a1277ff74c15504183d25fdfcc05f0d4dea892f6e301890:f7e67d982a2ff93ecda4087152b4864c943b1ba7021f5407043ccb4253d348c27b9283acb26c194fd1cbb79e6afc32ff686b55b0b3617218dcf39316b4b66b3c8c0d67267a86db8adf3750801bcf9327d4c25441b96197832b4cde0eac3ff22892a2f0bc17c2c213c02377a333e308ed271658049383b7e2e57b6b8b125512e0:0ad71b0025f3d9a50db338414d6d670e7799b7270a8444f6ae7f12ae7eb71bd03ffd3c4f36631f69fdcc4061468ff582ede495243ef1361a3b3295fa813ba205f7e67d982a2ff93ecda4087152b4864c943b1ba7021f5407043ccb4253d348c27b9283acb26c194fd1cbb79e6afc32ff686b55b0b3617218dcf39316b4b66b3c8c0d67267a86db8adf3750801bcf9327d4c25441b96197832b4cde0eac3ff22892a2f0bc17c2c213c02377a333e308ed271658049383b7e2e57b6b8b125512e0: +6288722035d1ea699bc7cfdf18d89625423180b683fa74639f4f30f15359cc85e17faa019572861a064e1bc571256dea1468f3a48590a89138aaa85925080cd7:e17faa019572861a064e1bc571256dea1468f3a48590a89138aaa85925080cd7:8b6caacac51d8949fb86acbcb1b99d859ff67c64147bc1216909dcab07ee6ef09f403863327394689dc34abc778fcb5c1f5091acf5a08f9d842211d1ae2eb40be9bb8d6679077471547a6c71ff77b519d4b7108e32bc46251c60dee8e332b6229316e6d57c22ab826ff1bc33f2b0213807c19280af110fd26ee27468201cff49cb:9dec92b6e89adbe8f4e1b5e93ac4fcf957de7d1970a226770ec4eda647c8e3b3dffb2731a39e16e4a0119d3662a937e560522491ec7a1696be04c076b12e35018b6caacac51d8949fb86acbcb1b99d859ff67c64147bc1216909dcab07ee6ef09f403863327394689dc34abc778fcb5c1f5091acf5a08f9d842211d1ae2eb40be9bb8d6679077471547a6c71ff77b519d4b7108e32bc46251c60dee8e332b6229316e6d57c22ab826ff1bc33f2b0213807c19280af110fd26ee27468201cff49cb: +13038a3a65ef32759a9cd903acb554b252de00e7cdb77bbed1970b20680ee17bb6a308e67f9b46c66499456ab5cd135cb2fe84a32eb045358626604da4122c8f:b6a308e67f9b46c66499456ab5cd135cb2fe84a32eb045358626604da4122c8f:ddf00b4033a2a088022dabe93356432f50ddc6c6e1a659dc1a93124a4c2ffffd182765a2f56c43ea0bfd8de8015060889ae6941c3f3e255d4421a1c36201be846a2738a71f120cad598ca8527d70ff8d5a0993b55cb5153517110a41962daff42250158f2096d1ddaf7186e50298cbe51fcb429cbea411293f8a7bd9cf069fa237e4:5261558ecc3c98ff36351f42f504cad4a32ffda5a744560960b4c106e4492f02e20478887afee4f770f05597a7e388caceae805ae351e0e45e8e578e6a6ff20cddf00b4033a2a088022dabe93356432f50ddc6c6e1a659dc1a93124a4c2ffffd182765a2f56c43ea0bfd8de8015060889ae6941c3f3e255d4421a1c36201be846a2738a71f120cad598ca8527d70ff8d5a0993b55cb5153517110a41962daff42250158f2096d1ddaf7186e50298cbe51fcb429cbea411293f8a7bd9cf069fa237e4: +b9de5b063d3ca3a773f114941b2e4227c07511c0f5c06017b9c8845018f234325295243c8646e096674dda15979b322b9dd0faf27d024a0ed5771334e1179ed2:5295243c8646e096674dda15979b322b9dd0faf27d024a0ed5771334e1179ed2:9493cc23896b84096046ae1053afe39499e9424254b366fe143f4da321e2dc9e4784208e12a542d899828dde7eff625a7f12416990c2841ffb095bf94c0c610e5a663918b689031ccd6b519349d04de1c212ca2a9d7abf52e1b4fd467bb665b6919ef8f91617e205565bf56647e5f8d508ea200a84467f8fa122e74bc3b9979f1174e5:92ba760d14d1415cfaf218ca847014088ae51ad821113a6f8630356f7ba85c005e2330f1066d0df464806052a4174610050462f3e013d702e7c77185a032580b9493cc23896b84096046ae1053afe39499e9424254b366fe143f4da321e2dc9e4784208e12a542d899828dde7eff625a7f12416990c2841ffb095bf94c0c610e5a663918b689031ccd6b519349d04de1c212ca2a9d7abf52e1b4fd467bb665b6919ef8f91617e205565bf56647e5f8d508ea200a84467f8fa122e74bc3b9979f1174e5: +8ff0297cc08842b5e67552ec2843e04353a34d74ef89b8565d97205b74ca133a0f7ef98c5ba4af984dfb77bc4e537b2b39e6273bb3e7b95fe1b7e6781952bd4a:0f7ef98c5ba4af984dfb77bc4e537b2b39e6273bb3e7b95fe1b7e6781952bd4a:2bdc3a486c5e4ea62dcfec8a9d4fcf9ea9490dbcc715615d58490a72ce833fa22387ca50a0052508cf0aff1ca727f0fed46ffa7d3c8e23c5bb01d47e90ff06d3858a557d9926481579daf4384aea50e96ec615d2a3bf3c1122f1f24dd6ed98a5de421883589c213998ca5432373e68bbbe89428ca9885d0593d5e6215116b8266386452b:0783737f706e6ff36614f850074fca1f485f24fcde2a28af544f37abd69b7a581defd8c771b031e108d19d788c74c5f20bb3f1c21cd92be317bacd8f650b49052bdc3a486c5e4ea62dcfec8a9d4fcf9ea9490dbcc715615d58490a72ce833fa22387ca50a0052508cf0aff1ca727f0fed46ffa7d3c8e23c5bb01d47e90ff06d3858a557d9926481579daf4384aea50e96ec615d2a3bf3c1122f1f24dd6ed98a5de421883589c213998ca5432373e68bbbe89428ca9885d0593d5e6215116b8266386452b: +050d553d282dca3269c83c181768ec067b81c9fe0c94f2a0ebbb0c942d0fcd7c63e230b003c53a5672e832ff7f24430be223e497de840233f595a3e200c7127e:63e230b003c53a5672e832ff7f24430be223e497de840233f595a3e200c7127e:15e13b8c01004f6aa5b236dbb281677f746d81e548e0aa80f0e414521521d856cd694e7c9152bb5e43776b60f6b560ed1ad3e4b390dbf3e46ef9257443f39c149e0240a02d021e1e3d7d046b26fd004eee7ca16a8059e126c74cb3f2194db47bf60465ecef5c704d2e2c75e2e50060ea2a31cb72b7b3c6b1b5ec72ab38004085281a22fe86:3f0e83765b31bbe8e1fb92e9678d6cde571a03ba7f1dcc1128461f708525457f4e0e2353aa2b598c063ff1bffdac916b5a2200655156904b0585577a1628560d15e13b8c01004f6aa5b236dbb281677f746d81e548e0aa80f0e414521521d856cd694e7c9152bb5e43776b60f6b560ed1ad3e4b390dbf3e46ef9257443f39c149e0240a02d021e1e3d7d046b26fd004eee7ca16a8059e126c74cb3f2194db47bf60465ecef5c704d2e2c75e2e50060ea2a31cb72b7b3c6b1b5ec72ab38004085281a22fe86: +69497cd7b4e868cfa0328d92bd6052d772b2767395c14595b279851a9cdd31aa5d276d626e230d18e7bcd61141cb93c90ef0f79e01321212d838ec71457b1aac:5d276d626e230d18e7bcd61141cb93c90ef0f79e01321212d838ec71457b1aac:53cd080a0c61f1a093d3b3a74571c296303f363b4107edbe880b7aa9dfe44ab5d5dc5f74be9c8d876f04d754653491ab51b135fc953f71287b62ff41b67c742bd3445671a9d4f2dc174ca1b0335f78627a0dd4b30650504178039e7393638510ffe84091b57298d3ac9001c367c1452fbcb33dc54a5dc316fb2a5270764a2ac820a0b63fbdc6:beafa58340960908e8d86e40329e3a4523fc7be770addb86e34c3772f84cd9fb338d1f3b65bfcdb09f35c6da36d1a3adf8f91f1ffd5782cc830206433a08410d53cd080a0c61f1a093d3b3a74571c296303f363b4107edbe880b7aa9dfe44ab5d5dc5f74be9c8d876f04d754653491ab51b135fc953f71287b62ff41b67c742bd3445671a9d4f2dc174ca1b0335f78627a0dd4b30650504178039e7393638510ffe84091b57298d3ac9001c367c1452fbcb33dc54a5dc316fb2a5270764a2ac820a0b63fbdc6: +2165a486b612bbff529cd00346964a3cb8cdcffa51dc3d524dd5adc5ac936d687ebc839a465e14f5892476e4a13b3988f83b3cd27ef79e193f86fa16f34a1ce1:7ebc839a465e14f5892476e4a13b3988f83b3cd27ef79e193f86fa16f34a1ce1:b728da7a36167c6085bd2d962cf63959facd95c9ad4542028afba90ec9c6c0760bdae935429c3feb3933e2f00042c672ad2cd7348d92bc33f81751e294ae9171b945b193144ef8acb9a1bd9abf0475ce0d0ac789b200c32e9c9a2736b168369ce5f97b1e8d2e7900e1a759178441f1fc430564ae129bae7857740511a668f32c0a3b077a9d8b19:7ec6fba56ba52460a1b4f2738689c1883dda9aaffc8bde17cb6029bdce3a0ebe2fffda55939b70bbd07fdbf6fc5cda87fed8ba58575f894a366e45e5705eea09b728da7a36167c6085bd2d962cf63959facd95c9ad4542028afba90ec9c6c0760bdae935429c3feb3933e2f00042c672ad2cd7348d92bc33f81751e294ae9171b945b193144ef8acb9a1bd9abf0475ce0d0ac789b200c32e9c9a2736b168369ce5f97b1e8d2e7900e1a759178441f1fc430564ae129bae7857740511a668f32c0a3b077a9d8b19: +1c64ad63dd147034598e128f7406ec0530746ea1c5b72ecf79e888065486fa1bbaa6bcc1c3d8d3b11ffc1587adddc58bfd96c2b992b6c6f59fcc50ccbcdd0eb9:baa6bcc1c3d8d3b11ffc1587adddc58bfd96c2b992b6c6f59fcc50ccbcdd0eb9:9ebd8e337893bb053ef2b9e3269df54848494f03cd63576b33e64b1080be4be015264a403fb9602bbf90ca19b241a9b66863909b9008ce1b2ffcf236efa4c2668f0f47db9ff5fa157d9cb605412be7dd8b07ea878cccae6bf50f935b86d19e1b648b69e528553a56d8afb78221ad53307b7a4ec8d2fd4861b55dc5dae8e93ef387fbbe0b4ce7f788:7477e54158f13b7128c0a110ca6b65f42514fb70cd5cf28a8b1cc6110ea06fcf94290da13f85a11c2351d3bbccbb4c64e0215d6d0f0099e7f27bc94e949b150b9ebd8e337893bb053ef2b9e3269df54848494f03cd63576b33e64b1080be4be015264a403fb9602bbf90ca19b241a9b66863909b9008ce1b2ffcf236efa4c2668f0f47db9ff5fa157d9cb605412be7dd8b07ea878cccae6bf50f935b86d19e1b648b69e528553a56d8afb78221ad53307b7a4ec8d2fd4861b55dc5dae8e93ef387fbbe0b4ce7f788: +55abbc5dac4128134dc8c6018a213ed4b60fcc8e90cbd41db2d21eda5373e936251afaa2646926b2a371f2a09d5865b98c9a5eb6ca047cd0d8ee36e5e0416974:251afaa2646926b2a371f2a09d5865b98c9a5eb6ca047cd0d8ee36e5e0416974:47010e1398ad55fabe371dd8648f768d90df4b965a3b396100b303b40a17518bed6d86b09f734ab7c10b5f3a01b53deec5f8534b70c79f3f29b284fdec486f22f44c22ccd5c6463594415267baa611f70b1b316caa1b68b5e0e99b31c5bb0ce13679a23c31a63999698164cbf37d103ba92490188be59937f123043ec786efe3d411f9b0623a6ad972:f6a61c2e661a9eb7bde182e38ec99af985f61698a5d7fa430d16e3f1a93709b75522320de48afcc595ab209122ae0ce132cdf4b0391746e7ff341177570c810847010e1398ad55fabe371dd8648f768d90df4b965a3b396100b303b40a17518bed6d86b09f734ab7c10b5f3a01b53deec5f8534b70c79f3f29b284fdec486f22f44c22ccd5c6463594415267baa611f70b1b316caa1b68b5e0e99b31c5bb0ce13679a23c31a63999698164cbf37d103ba92490188be59937f123043ec786efe3d411f9b0623a6ad972: +f2dcf4a1a0d46ddb2d72f8fdd80bbec5b7dea5913da4966c2f4d12c261f0bf98d39570a25ca59f2257f93f96600df4f63e684bf63ae8dffd914e4629c3d5095f:d39570a25ca59f2257f93f96600df4f63e684bf63ae8dffd914e4629c3d5095f:3b00e808fca4c11651d853d6b90f952ccf5647e102d4ee0ad7a5d181d5b4258c523cd39e3d9825298d84c8cba09f43dbba119988222c76059caf17b4bf9931c45e617448aeade151181497b24552367e52bc45ac79088806d3368207aafefd3057845dce819d5aaaa77b218e2aed3da76d40c1f07699f8172e4a5c803f7a2aceb9a47a8952e1b2f053f2:42882a811dad2d851885e4cbe9044708d91a86f15dfa1d66c3eb304314531f3015208c711b9bdbc5fb233951e569b59d34e415eec4b37ffd374d412c9a360d0c3b00e808fca4c11651d853d6b90f952ccf5647e102d4ee0ad7a5d181d5b4258c523cd39e3d9825298d84c8cba09f43dbba119988222c76059caf17b4bf9931c45e617448aeade151181497b24552367e52bc45ac79088806d3368207aafefd3057845dce819d5aaaa77b218e2aed3da76d40c1f07699f8172e4a5c803f7a2aceb9a47a8952e1b2f053f2: +2246bfb06155859e10a748ff8f5919ad5d1daab756f01057b790d07474775f4ffa6349b62dc8c6a2feeef6ffc33ae085c649795c1c9d9898e75c13ae1625db34:fa6349b62dc8c6a2feeef6ffc33ae085c649795c1c9d9898e75c13ae1625db34:63ee1c7bbb15cebe1c22532d481682754bdaf58b8bc997ae30a34c9d23c33f1690c346ab0a7365ff62457424b6105f8421eca0ce3c630acfeb9a1cc416390edf4920e22b2367e9fb5d2ab25bee56da03ea55e3f57882d48b89229314d734cb83c79f4e17ee64bae6f7addbe9b525fcd03a91409a2dde907751db8cc97e08d0ea89c4d18718d26d0b897b64:2be4915a352f7785483046d8ae9625b8b63257af57c073691256ee076d6e1b972a101f551c705d3f96157c33b56ea049be4af4dc561cbe3c1ec5072d7f134e0763ee1c7bbb15cebe1c22532d481682754bdaf58b8bc997ae30a34c9d23c33f1690c346ab0a7365ff62457424b6105f8421eca0ce3c630acfeb9a1cc416390edf4920e22b2367e9fb5d2ab25bee56da03ea55e3f57882d48b89229314d734cb83c79f4e17ee64bae6f7addbe9b525fcd03a91409a2dde907751db8cc97e08d0ea89c4d18718d26d0b897b64: +c088a3dd2cb8bd5d684db8538dc22473b6f014f64fe86af168b4bb01b90a1dd0aad615a9c28759f03d373abe666691dead8b84f9b8b50a67f8f0aa4a701580d1:aad615a9c28759f03d373abe666691dead8b84f9b8b50a67f8f0aa4a701580d1:74906ae05a5af8e9968b6feb498569d6345a24f9711befb136e6c3b5ed49339e59a7938b4ba1a118f169b9ace0f7842a26a645f14c0ad22ebbcda93e67e4c348efc3d9ecbb1419e6262d0436a58ea82c2202389065ccf67c4f550e45b5f6a12a6c011b2e0a30101d5c62328bbf99c8c95563a6e33bdd9cce72b1f720139c2fd3e04913146ae5bac5288e0e3e:3bb459d1ac575a180c1728d8b8924970492a0c8d2a378c29d1d41785c8379a58e2ba3606785e1c5da29e5527552bc6dc89a2b69c27fe51ed253a9f3b565b270074906ae05a5af8e9968b6feb498569d6345a24f9711befb136e6c3b5ed49339e59a7938b4ba1a118f169b9ace0f7842a26a645f14c0ad22ebbcda93e67e4c348efc3d9ecbb1419e6262d0436a58ea82c2202389065ccf67c4f550e45b5f6a12a6c011b2e0a30101d5c62328bbf99c8c95563a6e33bdd9cce72b1f720139c2fd3e04913146ae5bac5288e0e3e: +45667d1e7b5910979c4a328317968371c864d564a661c5cce557c9ecc61bab9eedcdf5e1a170e00c8c687e7e9c18f9893b5fe495cd2977ceb7f446c0149aa9d3:edcdf5e1a170e00c8c687e7e9c18f9893b5fe495cd2977ceb7f446c0149aa9d3:cd66cec476c87c8dbf47ec91dac48fb5b42db1282a573e0a5cf0b91768986608e1d7ebd05f5251bcf8b47a17093229acefbd44beb21c0c0c928dd3cd3f8966ecce6910331c508ea76baf904d8c21f6c17c2c58d00afd3259b8bf794c146b12b995cddd1c4289c5be3168ebd616b384c281ce1b38a10e1807808853c681a640a009b4d2acd7934f8c6d07578161:6de668f1ca6f292814625289a0808020c87c89ac94f5b0508e557bdf8000a5ca808f021c9679b50ee2f320064c95a464a8439379828c3b76cfa766455e128c0bcd66cec476c87c8dbf47ec91dac48fb5b42db1282a573e0a5cf0b91768986608e1d7ebd05f5251bcf8b47a17093229acefbd44beb21c0c0c928dd3cd3f8966ecce6910331c508ea76baf904d8c21f6c17c2c58d00afd3259b8bf794c146b12b995cddd1c4289c5be3168ebd616b384c281ce1b38a10e1807808853c681a640a009b4d2acd7934f8c6d07578161: +24897428ae6546d85b3190ebe3f1f7bf7c712528ac851a588b07d5c8f94eecd15f348fe3ea5b2c023d0af7ede60e55f91aa55199699da15a11c3791d68d710bd:5f348fe3ea5b2c023d0af7ede60e55f91aa55199699da15a11c3791d68d710bd:5201d9725f1dffa1863fa4d84c301861141acdfb64be1fbfdd5b9386db20ef394099eebcfdfecc62c6268607a84d55c55cd0efdc372ecf3067343e7b0731c2685461e24b953f99949e59ba3e67ed0f0848313793962a292c459814c5e28690ec1f45171f1abab86fdd14568b00caf48581115ee5ea83b000282fbbf0c0b2a1116039a35cfa3f201422207a3d4948:1b5e75def49f51d6b2de008c71fc1a909bd42ca813298dce4eeef717815d7a6c078c2f3d9a3fce1ab5b3ad8ef8d45cdf2eb4901c32eea2d5e018dcf2833cad0c5201d9725f1dffa1863fa4d84c301861141acdfb64be1fbfdd5b9386db20ef394099eebcfdfecc62c6268607a84d55c55cd0efdc372ecf3067343e7b0731c2685461e24b953f99949e59ba3e67ed0f0848313793962a292c459814c5e28690ec1f45171f1abab86fdd14568b00caf48581115ee5ea83b000282fbbf0c0b2a1116039a35cfa3f201422207a3d4948: +7b04aca7cf926216cb960a3890786339d0a615967680190123fda3b60c6aeb11cdbc3e70e4e8fd13d0cce2852a3b9372c3a6160cd6deaba90f9b3022f70c91f9:cdbc3e70e4e8fd13d0cce2852a3b9372c3a6160cd6deaba90f9b3022f70c91f9:1cb09624b1f14a0260c7f56d8c60b5fe45837114232551ef5966386e0c2b441b75cfdb8df2185785d22cf526fa9df7fd45d9d83881b66c1feee0913e238121eedbb7ab504da0bee8998016684535031991f11bfcd9b95690aad2d19bd6a9de1844ed1362302df4217230b25c0552ce277534c650cae526577f25d8b1fe9f9febca2c814670d4805b21adef852daf94:25d2d361751d52b4fe66ea18e4b9866bde3d121a7312fd9e28a1e295e087e3176c94c874a2e81600f24c4654f43d1b67d47b64822648590ce5ce44f3b5ddc5021cb09624b1f14a0260c7f56d8c60b5fe45837114232551ef5966386e0c2b441b75cfdb8df2185785d22cf526fa9df7fd45d9d83881b66c1feee0913e238121eedbb7ab504da0bee8998016684535031991f11bfcd9b95690aad2d19bd6a9de1844ed1362302df4217230b25c0552ce277534c650cae526577f25d8b1fe9f9febca2c814670d4805b21adef852daf94: +ea73bf64a1a97877c3c3e7ca4644b71aaa66314c8f1b66bafaebd5edfb888bcdcaac93902e5764ade47294edd51faa14620940c668b5c1c392a6928325d4c3fd:caac93902e5764ade47294edd51faa14620940c668b5c1c392a6928325d4c3fd:362eec68b912852786bb4f9afff9ecf7cb28c9de6b18422a8ca940b0d7e6dcb83aa44be0afb5f1806d43f0e31d71f922f853615a26e287a27f08a04fbce3d45a0c6c311d4b7cb17e425bbeb0a6b410b5d6dbb7ac11df9850a131a691e3b60b0b214ebe044106e982433287595267b031b5d4a09262ded8934fdfdf964d868ef9a2c842f804eafddefcb71d9f16a59bf8:bd86cb9c70a055279a86a9e64870988b8a7345c3cd2948a0fabcfb38abce3c420b4d5521618e11d2de827d9de569f6bc3be66aad40636cdaa64760ded3b7c209362eec68b912852786bb4f9afff9ecf7cb28c9de6b18422a8ca940b0d7e6dcb83aa44be0afb5f1806d43f0e31d71f922f853615a26e287a27f08a04fbce3d45a0c6c311d4b7cb17e425bbeb0a6b410b5d6dbb7ac11df9850a131a691e3b60b0b214ebe044106e982433287595267b031b5d4a09262ded8934fdfdf964d868ef9a2c842f804eafddefcb71d9f16a59bf8: +b8123c116b33bad0dcbc2c4dc06a3d66850dab360cdb5a033c14895c4ee31bfbbdca151ba32c6bb31531b05fdf86c6d78c8cd1935611d5ff111a0f00635b1885:bdca151ba32c6bb31531b05fdf86c6d78c8cd1935611d5ff111a0f00635b1885:7970f6666634548c848bb52338817b26a4d0ca68df3d28afff207c2d028067a18e4c9543025f5b0228aa691e5088513151a94494e15d1f54210328e0df159b352c30aaa7a844f18a9f4c395dcbb3fb9fcfbed1103e0706fbf9c35fe2666848fa35dc2cf5227ebee89e7d3bcfae2721b25fdec3d3174ea7ce267a55dd61d58201e96bda303cf418edf6e32fb92f5dc1a0b1:9cf13eba3dcc37b8fc70ccb2327436b9f08855e726aa7ed82bd5cb7df45fdf9ec1f96afad193f47572d770444b65b74a37cc034fc514cb3f91b2d8ada5b020067970f6666634548c848bb52338817b26a4d0ca68df3d28afff207c2d028067a18e4c9543025f5b0228aa691e5088513151a94494e15d1f54210328e0df159b352c30aaa7a844f18a9f4c395dcbb3fb9fcfbed1103e0706fbf9c35fe2666848fa35dc2cf5227ebee89e7d3bcfae2721b25fdec3d3174ea7ce267a55dd61d58201e96bda303cf418edf6e32fb92f5dc1a0b1: +b18e1d0045995ec3d010c387ccfeb984d783af8fbb0f40fa7db126d889f6dadd77f48b59caeda77751ed138b0ec667ff50f8768c25d48309a8f386a2bad187fb:77f48b59caeda77751ed138b0ec667ff50f8768c25d48309a8f386a2bad187fb:916c7d1d268fc0e77c1bef238432573c39be577bbea0998936add2b50a653171ce18a542b0b7f96c1691a3be6031522894a8634183eda38798a0c5d5d79fbd01dd04a8646d71873b77b221998a81922d8105f892316369d5224c9983372d2313c6b1f4556ea26ba49d46e8b561e0fc76633ac9766e68e21fba7edca93c4c7460376d7f3ac22ff372c18f613f2ae2e856af40:6bd710a368c1249923fc7a1610747403040f0cc30815a00f9ff548a896bbda0b4eb2ca19ebcf917f0f34200a9edbad3901b64ab09cc5ef7b9bcc3c40c0ff7509916c7d1d268fc0e77c1bef238432573c39be577bbea0998936add2b50a653171ce18a542b0b7f96c1691a3be6031522894a8634183eda38798a0c5d5d79fbd01dd04a8646d71873b77b221998a81922d8105f892316369d5224c9983372d2313c6b1f4556ea26ba49d46e8b561e0fc76633ac9766e68e21fba7edca93c4c7460376d7f3ac22ff372c18f613f2ae2e856af40: +93649c63910b35718e48c590d261c48e4ef8336613f6aa077b462676b3ba882906a685898b855212ebc289915d105a4320d620d85771b8c6b15bf10a1be6e9b8:06a685898b855212ebc289915d105a4320d620d85771b8c6b15bf10a1be6e9b8:2cd1a951056c9ebae1399b6bd2d82c0ae277856290d06920ac56cac8fb42435101c72aa9c08dd2d12426325562c2f0a49cd821b11b939aafa593b4095c021bcb4827b107b9664d68282888bc4a44af3e3bdc861be6af309044c3daab57b77023dc902d47ebc326f9bdd02dbc02cd540ff81b2ddf7cf679a41193dfe5f8c8ca1aaefc41ef740280d9823e30a354717c8431f5d8:6274f2d4f431d5affefa35e7cf584a599017193da99094ca908b75acb608d1bf981857be93a7dafb0fadb3ff0906f48a5ee950456f782c2d605b14095ba0ff0f2cd1a951056c9ebae1399b6bd2d82c0ae277856290d06920ac56cac8fb42435101c72aa9c08dd2d12426325562c2f0a49cd821b11b939aafa593b4095c021bcb4827b107b9664d68282888bc4a44af3e3bdc861be6af309044c3daab57b77023dc902d47ebc326f9bdd02dbc02cd540ff81b2ddf7cf679a41193dfe5f8c8ca1aaefc41ef740280d9823e30a354717c8431f5d8: +1c15cbeb89362d69476a2aa4a5f3ef2089cf87286349e0dfe0e72d9e3e5a66c713a882a1064182582c211847e19b4dac59722c9ffd34826d96f33113400fac7a:13a882a1064182582c211847e19b4dac59722c9ffd34826d96f33113400fac7a:091c9b9b116ae83d23d01a6295211785d446b6228dd687ddf79bd0d5a4daa8c79d2cbfc37365f1f285e361738123e34e2bcbfc664ce1253a11d9e4a7982e58cf9468e1017ea14d2cc6d0865d40fde8cb560241e96ac1617c791f0ca7c6410cadf328611b18aef333d8350ac497f0a4ae2d03fdf0e23e426d34f4514780d1474e113583541f3c043672057172618cb2059eaaed56:5998b2808adfdeeaebe2c3eac026d3f825f9c7f2af97ca324fbd57aac1bedff78a8ee621d037ee3ad2a712e9a009c58ea3e6f2a828f74b86da275a44a4b1e50b091c9b9b116ae83d23d01a6295211785d446b6228dd687ddf79bd0d5a4daa8c79d2cbfc37365f1f285e361738123e34e2bcbfc664ce1253a11d9e4a7982e58cf9468e1017ea14d2cc6d0865d40fde8cb560241e96ac1617c791f0ca7c6410cadf328611b18aef333d8350ac497f0a4ae2d03fdf0e23e426d34f4514780d1474e113583541f3c043672057172618cb2059eaaed56: +11241ffdf34ae8ab875475e94c6cc3291f0b8820dc85e20f32fc53b24ae6897809c045e4bd5137314c0ec1d031faf914910c45a4676f5a3cd8f581bcccb03c97:09c045e4bd5137314c0ec1d031faf914910c45a4676f5a3cd8f581bcccb03c97:3b89deccb7023e4b2b7aff2c3951870af413a9b04dd86ac78b7c8fd887492d8dde49d8fda149edd54781ae2b508030d14416a9a38bed2b9aebbbb20250b3c931acd4e32fbeeec5a26501beab7268d144fce8951a101c4b5178166fbb5927b1dfb1e1ce90d1d123068e3f472c888fdb01fdf70e7f8de9b0adb284b7119f55354316f84ed090030f9c2662061ca48447cc0aef964126:72ce9f91be2e66cfc90f952595946ffc90bfce53087d49e5dd7c087f3faa8f18f2356de971e4429d985a99194b4f92ced3ef47cd7114379e0b3267a9f8b1e7063b89deccb7023e4b2b7aff2c3951870af413a9b04dd86ac78b7c8fd887492d8dde49d8fda149edd54781ae2b508030d14416a9a38bed2b9aebbbb20250b3c931acd4e32fbeeec5a26501beab7268d144fce8951a101c4b5178166fbb5927b1dfb1e1ce90d1d123068e3f472c888fdb01fdf70e7f8de9b0adb284b7119f55354316f84ed090030f9c2662061ca48447cc0aef964126: +3bdb162465eaceff98d69c86f70039c517d168aefe6bb101b4f769a86b17c972d76cb7be74328289fd1c64be747cca5bb30295dfaccd0f2e43f51703fd5d3683:d76cb7be74328289fd1c64be747cca5bb30295dfaccd0f2e43f51703fd5d3683:fbf368feaeba87918b1b8c7b8a26832be6e7fc1cbdb8902519281a0654ec73de0bb07101a9d603f745d4ec2357aee9870cb19a56cb44fbd9c91fc34752612fbd83d6fc1a16bf8a85a215d0148e4af37d298467e5cc486b131352ce092182ce8284159a3812b30bacbff595863811bf9a30a9da494565c3ac1814430018ea0eeed39cdbca27f93140e46949db570bfa2ed4f4073f8833:6f1362a402063791f950984f544928e616a4ef79bbeb6854e9615aab9cdbaec483fb9a04bf22de5d97a15bda2d390483c7f61dbee07bb5141fc173b1aa47650dfbf368feaeba87918b1b8c7b8a26832be6e7fc1cbdb8902519281a0654ec73de0bb07101a9d603f745d4ec2357aee9870cb19a56cb44fbd9c91fc34752612fbd83d6fc1a16bf8a85a215d0148e4af37d298467e5cc486b131352ce092182ce8284159a3812b30bacbff595863811bf9a30a9da494565c3ac1814430018ea0eeed39cdbca27f93140e46949db570bfa2ed4f4073f8833: +d5efe51d5cd8e108bd922fc0ea126190a94628ffa53c433a518022792ddc78ef426b01cc61ff5e0e724da1d3b297f5325c18c62f64d5eb48d4a5216a8e9a4073:426b01cc61ff5e0e724da1d3b297f5325c18c62f64d5eb48d4a5216a8e9a4073:9d17bcfe2dfc742f411cb53a94f359c001abf096c741f34af48679f281e7ce6bbd9e87709fc0728a563db2b9cf8ea4fbdcc344c1848e653ce970c6ce29de2ccd520300649adcddfc753971f846aac1ba42ae4528952d94980aa7c6cfa2142907647f894ae974a74d59035a73ef56a10b6612624809520190ace661c3a47095e0322efd781d50d1163598f2da32f31bc9c4f913d1b14861:2306f58fcd4cff2222d81b05a475532b8b19dc67e6d78ddb4205a3b7621cc5aef0b393d5d24dd96c88ccbc53a3208da323be4587d5ec067c820f0723aa44e90e9d17bcfe2dfc742f411cb53a94f359c001abf096c741f34af48679f281e7ce6bbd9e87709fc0728a563db2b9cf8ea4fbdcc344c1848e653ce970c6ce29de2ccd520300649adcddfc753971f846aac1ba42ae4528952d94980aa7c6cfa2142907647f894ae974a74d59035a73ef56a10b6612624809520190ace661c3a47095e0322efd781d50d1163598f2da32f31bc9c4f913d1b14861: +18af89025ebfa76bd557cfb2dff148245214641fd5bda159f73da04b08e87c880c584459b9ebcccad587b272160bc60b27f4f772b4321de7723afef577edc7b4:0c584459b9ebcccad587b272160bc60b27f4f772b4321de7723afef577edc7b4:e82f46652ab914af535d8fb720b557ac95018d9f2a3fcce85771bb40ab14cb9a986e096f3afe5bee829dfd8b97335c536ac971a21655af16a2f8fdba183a4e18564c21492956537a419abbbbb02a4bbdc01481f5c6e658ecf3c34f011ad846f5edcd4939195df85e41303fb9a88fdfbd704396f7559a327318b952b3e60ce8ddde56378579232faf950c78e7f0b17c3b8dece36b788a8473:26bb0882297c2c08a752d3981145dcde55893a11df77f8aa4c19d0b9ed6e5220ed12e9fac3af13d0f0c71568f4a547d30114a6599a236806c4beee6765284408e82f46652ab914af535d8fb720b557ac95018d9f2a3fcce85771bb40ab14cb9a986e096f3afe5bee829dfd8b97335c536ac971a21655af16a2f8fdba183a4e18564c21492956537a419abbbbb02a4bbdc01481f5c6e658ecf3c34f011ad846f5edcd4939195df85e41303fb9a88fdfbd704396f7559a327318b952b3e60ce8ddde56378579232faf950c78e7f0b17c3b8dece36b788a8473: +0c93d99815fff8fe22b9e45aa02b3e6445ce1d6bf5a65dce3da107aa1055940e4d27a47b0fc80800d84d244eebb1deb4436d97633a83e67125ad52ea01685057:4d27a47b0fc80800d84d244eebb1deb4436d97633a83e67125ad52ea01685057:11e877de58c134eaf4c9f1b53c3dc451d3c055f16b09622725b279768512fe10a7adb0765b689ec21d5b6efaa19f1b9d36254df0a9367f441b26bdb90b28cbc403e5074082fa1fed58e140dac97aeaf483e2c13f3cc560abffaba05b763feedb51e60698151cf56efdf1d37d6ce0564486210f052e937f2ea26f63efa5d247ff188329bb1aa83ce3f4f35a3d7dec14599e5feb7b6d5fe4296a:7dc4467abcf6431adb7ccfe868eac8cd8a615a0ff65f6a9e338375b1aae3c49a126c9eba79426d1641c6b97c3e92c194e5ee4431efa2439fd450f2cd018c870011e877de58c134eaf4c9f1b53c3dc451d3c055f16b09622725b279768512fe10a7adb0765b689ec21d5b6efaa19f1b9d36254df0a9367f441b26bdb90b28cbc403e5074082fa1fed58e140dac97aeaf483e2c13f3cc560abffaba05b763feedb51e60698151cf56efdf1d37d6ce0564486210f052e937f2ea26f63efa5d247ff188329bb1aa83ce3f4f35a3d7dec14599e5feb7b6d5fe4296a: +989e99945635192c023cc5186fc25bbaef47240775d15a56195d88cd07c3748eca0beafdf731d89301f7723c5bb7e5a1c3ff3eab27c97d711bcd76e42054bee4:ca0beafdf731d89301f7723c5bb7e5a1c3ff3eab27c97d711bcd76e42054bee4:c48414f5c757d03c523ef3f3b8510771b0ff3b4b97de279625d349ec185a29927a66b9593ba19338c2f5e4131f1ac07ea46d2c1b6e4ab5229280b2e2bb9d140d1ef7af7b1692bf2d097b80f811adcfa95d5cbf9eee92a1641c552b4be4a0d734f0afd470b9d7f4e45778951e21fc534f200a128b96adb8373f10cecec2dac2996a062fb3c294315965a9d5d7b077c4b013c64a38429769d23eab:aef756bfb8a7266e17d15f3f11ee50ed25be420e95a0742271ebd12294e2cb96ead083b8ff0b829d2edeb14da86e402ef25e6d4a5a7958c184ed10c176cb570bc48414f5c757d03c523ef3f3b8510771b0ff3b4b97de279625d349ec185a29927a66b9593ba19338c2f5e4131f1ac07ea46d2c1b6e4ab5229280b2e2bb9d140d1ef7af7b1692bf2d097b80f811adcfa95d5cbf9eee92a1641c552b4be4a0d734f0afd470b9d7f4e45778951e21fc534f200a128b96adb8373f10cecec2dac2996a062fb3c294315965a9d5d7b077c4b013c64a38429769d23eab: +6bdbbe06d9f4219eea6403a357b25e561992fae0f0f614561dd86d23de415a43ed52dd1cce32d9b485e0940746421d36b9fde6cdf0211545b634044d4b3cb8f1:ed52dd1cce32d9b485e0940746421d36b9fde6cdf0211545b634044d4b3cb8f1:582ada13d69293e49bbd461032dfea1ca2025b52e013a33a0387fcfc5f7c0b8ec955982607fc901e1b7f636a9d371e1f91fe476bdd44856e275d67efa14238164354c231124c84de8f5b89d5a58ea6744b4d3b3d7906905233cce694a64d696f5a7024fc9033b1ce390899a3b441a48e53c7c9b30ba12e7d61f35f15e658c7cc4407e2f689ea8a55d01bf5dbacb11954754f920f09dbd48409bbb5:950206605b0f417c90843e2c8d8e66c828bb10b99b36eeeee8caf2e0e5484d93fe02bf533405f4bb74a50e5585fa0daef4821f0301d01b46321baa31e1f08d03582ada13d69293e49bbd461032dfea1ca2025b52e013a33a0387fcfc5f7c0b8ec955982607fc901e1b7f636a9d371e1f91fe476bdd44856e275d67efa14238164354c231124c84de8f5b89d5a58ea6744b4d3b3d7906905233cce694a64d696f5a7024fc9033b1ce390899a3b441a48e53c7c9b30ba12e7d61f35f15e658c7cc4407e2f689ea8a55d01bf5dbacb11954754f920f09dbd48409bbb5: +d761c8c5a9601b9145b7d051249b004107e452e563100c6c788038c9ee8adad7e6488775d6407efc7b2bca890a7fc62266fc54cdac893343b4f59a196d948898:e6488775d6407efc7b2bca890a7fc62266fc54cdac893343b4f59a196d948898:84ead5eabd2fd4b7c79a9a928ab8ee0a16a5fd667a057f8a254663d56daae156d1a49affb2996137b9d8b340e635732f9d2b4c60218442541e72d2b00e1ee7a73c3f67caa499fa9d070b57d076dcde96b0764723c3c659c7a00c1b78b15ccc2223890b51067fc81e23e9458ab0683ba626a53d0c3793a58a9857bb44b3bd85bb6ce53a85694e7f53cc1bd46d50eda37d81f5381b513d1f38339d291b:7ab78b64e6db359a2dc8302e1092ed66fa736b536253a1cd90fdb8c10efd78300225e191963599ba549cc859209df0ff61cd069b03d254e6e7d76c798440f90784ead5eabd2fd4b7c79a9a928ab8ee0a16a5fd667a057f8a254663d56daae156d1a49affb2996137b9d8b340e635732f9d2b4c60218442541e72d2b00e1ee7a73c3f67caa499fa9d070b57d076dcde96b0764723c3c659c7a00c1b78b15ccc2223890b51067fc81e23e9458ab0683ba626a53d0c3793a58a9857bb44b3bd85bb6ce53a85694e7f53cc1bd46d50eda37d81f5381b513d1f38339d291b: +c5e0c7a7bb8b7ca07bf0a05ea67eff6deebfe3714ee3e1a227f4dc8e242a2fa05135efcd9052bec57a4431caabe82680eec0a33afd59b30203b280ba12be485c:5135efcd9052bec57a4431caabe82680eec0a33afd59b30203b280ba12be485c:3770a6786652c4b78a043edce07f3e204d81997c42afc22331f75a5494a826d7cb69ab4314a473721058a1839981d5b7022d0cd8670377daf3320476d25b9f559561d66ee0a709fe17361e2a52898f5753c4fb43bd0c98b368f512adc09cd927c6622676926d8c2d91a14aca32f226f70036c1c858bcffc2b59f54c1c37bf81eb52ecb3f00da602c94361b52a5afddbfd7e05036e377503050333be512:2e7fdeb3484d0a5e8dce94448979496b0642cabc3733a51f8c3c5c51c19ae319018da91091c2385f2f4e9a59edbca2abd0d085ee40d3f0d42061a5a9832a370c3770a6786652c4b78a043edce07f3e204d81997c42afc22331f75a5494a826d7cb69ab4314a473721058a1839981d5b7022d0cd8670377daf3320476d25b9f559561d66ee0a709fe17361e2a52898f5753c4fb43bd0c98b368f512adc09cd927c6622676926d8c2d91a14aca32f226f70036c1c858bcffc2b59f54c1c37bf81eb52ecb3f00da602c94361b52a5afddbfd7e05036e377503050333be512: +11bb4748d2547e6196be823c9be7aa18150c204b12ca8d73c1bd46b11a54b475efeb42da28d764966403dd300d9f9451b258ab1c80df06fe5943153f5301cccb:efeb42da28d764966403dd300d9f9451b258ab1c80df06fe5943153f5301cccb:f4b765b258ba35b427525c7f10a46f0bccd357ec1ad52a5b139417a9d3894c512d89eb88e681b1f30aac4c115ccf36545e83f37834c82e8300cc1eb289af4375968c29c0ffefb40e156c20c0432669ac8dc0a83c13b1e855a84ad0133c40c82c87ee1e7dd4084d741c80de8a7a9f7759e843a562099c4d7df875352039ff4d3824651386c97759ff7dba52064e6d3112e080819aee8ce723a1a2aa464d8a:44c58da49d2365d27029d1eebb3bebf7c032d858aa07e0756b1c26a5412d22691176031341ad37d7bb7843289eb39db491584c1b2a1da2e4a2649c2293826606f4b765b258ba35b427525c7f10a46f0bccd357ec1ad52a5b139417a9d3894c512d89eb88e681b1f30aac4c115ccf36545e83f37834c82e8300cc1eb289af4375968c29c0ffefb40e156c20c0432669ac8dc0a83c13b1e855a84ad0133c40c82c87ee1e7dd4084d741c80de8a7a9f7759e843a562099c4d7df875352039ff4d3824651386c97759ff7dba52064e6d3112e080819aee8ce723a1a2aa464d8a: +7452a00156d794edebff4adb1f7a7eec26217fef67c3d268352b2b5460a7dc255f4dc338cfbd384b5f1c14c226701446b52b1e3e2a3cba1a40ee2825080d1de6:5f4dc338cfbd384b5f1c14c226701446b52b1e3e2a3cba1a40ee2825080d1de6:8c4ee2867656e33f5269414d77b42d8e4750dba93c418bacca10938cc3b570c6603d52c2344488607b2f934f6d269fcb2ad966219b1ab11472f42c672ce20592490ec5baf6a2d2fc8a3ee35374b1902fdefc7870b1b626fa46b12b6cee241f601a9b3fe4c50812e573e6752ce2c7644e3367a6a6b77758d8e4934b58af23abae8fecac25edd734030ee7cf39907e3eed8186a19a807103a9fc49d38f4c8460:a8f9fa24a3dea1022e73f0d88b1c37d06d0f0b20bbff0ecdb4a40c86d7e475617c03570a7419d74ba0f1327096bf19f0d0cf9f51d483112f26922378682f48078c4ee2867656e33f5269414d77b42d8e4750dba93c418bacca10938cc3b570c6603d52c2344488607b2f934f6d269fcb2ad966219b1ab11472f42c672ce20592490ec5baf6a2d2fc8a3ee35374b1902fdefc7870b1b626fa46b12b6cee241f601a9b3fe4c50812e573e6752ce2c7644e3367a6a6b77758d8e4934b58af23abae8fecac25edd734030ee7cf39907e3eed8186a19a807103a9fc49d38f4c8460: +880ef106733f04e76195eba280b3fadda0f25dcf96a6a99c8ccf842c68afdae570cee33d41c728ce7b141931e6e8524567d7601eb79f67fdcd07b9d682c650f0:70cee33d41c728ce7b141931e6e8524567d7601eb79f67fdcd07b9d682c650f0:f4f38d077f2b03da821bd36fde673d666e52f4832e1c0dcfeef049328acb7bd71ad2bfc49c123516e196c470df0847b3848a45a2c69bea03e2afa7e58205b63b523814fc8e242f059c69ff7e40f97be8125b70a54fdaf35aeafac79114a7b419e6bb9e70bf07adb559819600dc25e51b4b700d27ca5472a0e7cbbfd14e099faa3a72002da538cbe45d621ef0d5252ba29d83f8b3ec8389c9ceb6c6b2e8d8a20f:ff6caedd8a468aa07d4c6e7131bbda76182ba958649376e711f44c7bbacba6077bea878ba5949cdeeef05cfd4983b0057d275ea3e18c32659468c30c47ac8f0bf4f38d077f2b03da821bd36fde673d666e52f4832e1c0dcfeef049328acb7bd71ad2bfc49c123516e196c470df0847b3848a45a2c69bea03e2afa7e58205b63b523814fc8e242f059c69ff7e40f97be8125b70a54fdaf35aeafac79114a7b419e6bb9e70bf07adb559819600dc25e51b4b700d27ca5472a0e7cbbfd14e099faa3a72002da538cbe45d621ef0d5252ba29d83f8b3ec8389c9ceb6c6b2e8d8a20f: +a2d88f37ecc2b2c05dd6cb3159962c5f646a9815b2fb37791fc7b606e2913ed558dd67d7a15d4ca0341a4c869566cad8c4ee16e583a10b4824173b08290d92d1:58dd67d7a15d4ca0341a4c869566cad8c4ee16e583a10b4824173b08290d92d1:d1b87e9e886dfbbdc8ca8ab9010ecf9bbaf23f72ab3cbe769db1d43c2a474a81651c464e9fb92734634641c9485a0239b3110771e7f75e05252e4d8f4c0aa1ba08626d7e96317c20acde2ad99b23bdadfd6f17468eb402ec5eefa57b47caf972b3dd21d89f0e2989ff87d51ed2e2d639c1644e698cbe0221b8e179f3cfb04a20cb2470216a6882fb4ff799e11536cf64219f0c075176bc7cf0f6c5b7925fcd6155:ccf2400cd673e1effd20161d7b68a5fb87c1e99d3635d78c2da1b509fac33346c069163a6c46c7826a48bbbd03b05e6e2351fa62bf89bf7ccf9a9024bd157d07d1b87e9e886dfbbdc8ca8ab9010ecf9bbaf23f72ab3cbe769db1d43c2a474a81651c464e9fb92734634641c9485a0239b3110771e7f75e05252e4d8f4c0aa1ba08626d7e96317c20acde2ad99b23bdadfd6f17468eb402ec5eefa57b47caf972b3dd21d89f0e2989ff87d51ed2e2d639c1644e698cbe0221b8e179f3cfb04a20cb2470216a6882fb4ff799e11536cf64219f0c075176bc7cf0f6c5b7925fcd6155: +42aafd0ae26df1e7aa0276860d752783af97280439bb23eae46e3f84caac78dedaa2350adb55dba9df7d7af5101998fe515d311c3cba3eeab9138233190c3b4e:daa2350adb55dba9df7d7af5101998fe515d311c3cba3eeab9138233190c3b4e:72131b80ad599b6f5ff698547d16e7499d71275e4e9b30526a5aac0b0c8b14fa4a540cfb1145fc004418bcd318c1a70e6269a3fb69baed86f363f5b8f97f569c20d4f4990e7bb4d0c39921268d636ed0554bd62acfcacd3b8e030217aafac3044c037e0f94da18c6b9a0932c3c5875d3a93fbdadcf67964eec9ec2be69b48f020f6c9874de5f8a5167b5ee024a2c2efd0cdcd2acd8c1f787814141e30b38b163175b:116143650b6c133d617859db2429c2913579790b2197d7b7b1b4962b328721032ceeca58b2d56439e233bb84dc525e284ff8df2bde1db4986fafd21b3d7d6a0a72131b80ad599b6f5ff698547d16e7499d71275e4e9b30526a5aac0b0c8b14fa4a540cfb1145fc004418bcd318c1a70e6269a3fb69baed86f363f5b8f97f569c20d4f4990e7bb4d0c39921268d636ed0554bd62acfcacd3b8e030217aafac3044c037e0f94da18c6b9a0932c3c5875d3a93fbdadcf67964eec9ec2be69b48f020f6c9874de5f8a5167b5ee024a2c2efd0cdcd2acd8c1f787814141e30b38b163175b: +b69c33b11ba67841c3d4e6f9234e35370a28b47662ac560b27c078b66ab1b0219df68e9acf67379261744db5d1e377892f2b692ed5a38b37073c04de5d226737:9df68e9acf67379261744db5d1e377892f2b692ed5a38b37073c04de5d226737:f9ea126d3ab21961aa2433900a3982b83e0ef86d52d13440afa4817f9b822fb582cc3932bf450d4677c9188181fe7526ad6fe5abc61d0ae759f215013c0b2b41064cb6278ba7e39e2f4c10d6cc9605b3869e169d7da42e88eb857870fe6118bb02bc08c8055f0c189b62f79fb146b4c543aa30cc0cd57f037e9ef7a63711f66e6f2878931702202702614277d513f0850b758549336b30cf40ab8bd460e60e12deed04:24368fee5bd848b4c661a3be4f310cfc436e79ec4a78501b81095fe51614231b6ca1ab1269996ad2e98e299781af8e29804b24fe5679ca3ba650c5c4cc58ce01f9ea126d3ab21961aa2433900a3982b83e0ef86d52d13440afa4817f9b822fb582cc3932bf450d4677c9188181fe7526ad6fe5abc61d0ae759f215013c0b2b41064cb6278ba7e39e2f4c10d6cc9605b3869e169d7da42e88eb857870fe6118bb02bc08c8055f0c189b62f79fb146b4c543aa30cc0cd57f037e9ef7a63711f66e6f2878931702202702614277d513f0850b758549336b30cf40ab8bd460e60e12deed04: +7b63613f6dae01cdcd5e6b37686971cd8d8a99542f6329a12854a9d8ff8105ac72ec43faf34d8730177d1f0743c74c20bf72c2394b8a7d471ffe2a04ab00811c:72ec43faf34d8730177d1f0743c74c20bf72c2394b8a7d471ffe2a04ab00811c:1816488f1fc83e1ed5911637dd42ba2077657dfe1ae422ad0aee59df9dd56a2763c2dd0ef61a12bb825b0dac1eda5fbb691c5ed58f3fb325050b4563a4042099982fffa5d6ed742d95823da8e1787cf746ef63b3fbb0e88a6c0beae4f7318366936b4917f507336068b194680900a7bf4a6fb69a5c387b97e31bc7f9be53c2a89e3651ce1de41b10e921b206ebf32e5621ef8081616dcd7a2059437efad014bb8e2c8221:76f50b2b9c2ad97bfb9499ee41928ac072da5e8bc71d0212550942332b62e70c8bfe1c722542394688decd917aec8f95353e1d72624b70ebed5d17f6c54977021816488f1fc83e1ed5911637dd42ba2077657dfe1ae422ad0aee59df9dd56a2763c2dd0ef61a12bb825b0dac1eda5fbb691c5ed58f3fb325050b4563a4042099982fffa5d6ed742d95823da8e1787cf746ef63b3fbb0e88a6c0beae4f7318366936b4917f507336068b194680900a7bf4a6fb69a5c387b97e31bc7f9be53c2a89e3651ce1de41b10e921b206ebf32e5621ef8081616dcd7a2059437efad014bb8e2c8221: +3558d3a74395bdcba560e2c45a91960cec6cb3edbcd30e722f7f055210f37b51534f43eba403a84f25967c152d93a0175ec8293e6f4375319eadf957401fbbd2:534f43eba403a84f25967c152d93a0175ec8293e6f4375319eadf957401fbbd2:be75444f9ce6be1d83af622a8c478d510127db56f1de6eb8a5126522b09fdc6ca0862cec0b8b2aafa31c17a2cc477da533d276a1ae4f8e0759d6afa0b17411b5170b52f20547c72f3e88d48cb456fe625b62feb0f81317edf1ec09ece534b9f500d4e1b1bda2db21982aa95094226ee9f5b0a65da83f91121c96b3b4010ae7826c9e80636cba00f70c3c8a279b01b95294cb850f91709f4376662a580b15ac2981afe9f854:b365b5561a13a54517cf90d88b35eb0967d6d58414b8c1547e693159e01378563654c50fb42323f09dd78ffe28056ddfa54febf44891e8a741b6a1687d728605be75444f9ce6be1d83af622a8c478d510127db56f1de6eb8a5126522b09fdc6ca0862cec0b8b2aafa31c17a2cc477da533d276a1ae4f8e0759d6afa0b17411b5170b52f20547c72f3e88d48cb456fe625b62feb0f81317edf1ec09ece534b9f500d4e1b1bda2db21982aa95094226ee9f5b0a65da83f91121c96b3b4010ae7826c9e80636cba00f70c3c8a279b01b95294cb850f91709f4376662a580b15ac2981afe9f854: +a35b92f244063a19bb5e3ed4d699ed2069607116d2bd08113f0d8373613f35b77ec93601864ee4995a4f7abcd3dfc101e9e7f369e63de1ae68a07aa7f075b329:7ec93601864ee4995a4f7abcd3dfc101e9e7f369e63de1ae68a07aa7f075b329:65cd36dae0168d69974f95f09dd9a59db799f911e1a15b85a00893b8c9a3d48a2f58ac126bfaa0a606c05d94701d273abf7d68817f2c71b1c541795c4f6095e26c9dff803f032f75663fd1698edd97ff3a0e72e1b7c9948b08bacb5f7de502b2fea67ca2fef190d60eae92d15158da444a49d2e9d5a573e8e177e8bbf7e6c49f907136e71d2a66cb07636d48768ff417c8beccf4323181fefb3124e434049ea45dd5019e40b4:a23dbe3757e478dbc84d3db3a933b0428cedb6b01b86d8d73f3959878dae6f0588f505cd4d39f2ab4677b64805d629652a22529825c3a91d043749fc71f0370665cd36dae0168d69974f95f09dd9a59db799f911e1a15b85a00893b8c9a3d48a2f58ac126bfaa0a606c05d94701d273abf7d68817f2c71b1c541795c4f6095e26c9dff803f032f75663fd1698edd97ff3a0e72e1b7c9948b08bacb5f7de502b2fea67ca2fef190d60eae92d15158da444a49d2e9d5a573e8e177e8bbf7e6c49f907136e71d2a66cb07636d48768ff417c8beccf4323181fefb3124e434049ea45dd5019e40b4: +72d4a564ca15499b5e4e75d8ac0f28217d32114a0c649a7c8eaadd0cc78c520bc766bd73837c4faa5215502f1efc90c003f711bbef55170091028a34493408a9:c766bd73837c4faa5215502f1efc90c003f711bbef55170091028a34493408a9:6c7e7b62eb244a45d78436e2970dcd6c0f7db82297a86140ea58dd22c2195adbc956d4c4ec05354b21efe24cfcfe10e17622368848180d2c4680cc215e8ceea6cce222161f1e092239253b9746f7887df2425ab5a880bdba98153be786dc838cbeca016b1d06524bd6bfba809a8bb37adab15d42415f86ec0358365ea87b8150b05441d9d49846871485caae6de359736c27189736d8f1765f3e5c5f6b92168396390bee94cfbd:8fc4f179330b642dd86ca9362651b83b006d8375ccef811d3c6706f91594651df2769953723046ccb9bfe66a667e0d11fc3ea2d8226234fdd5164765260f7b056c7e7b62eb244a45d78436e2970dcd6c0f7db82297a86140ea58dd22c2195adbc956d4c4ec05354b21efe24cfcfe10e17622368848180d2c4680cc215e8ceea6cce222161f1e092239253b9746f7887df2425ab5a880bdba98153be786dc838cbeca016b1d06524bd6bfba809a8bb37adab15d42415f86ec0358365ea87b8150b05441d9d49846871485caae6de359736c27189736d8f1765f3e5c5f6b92168396390bee94cfbd: +2e5aaab298e66c2dc1d77ea7421ff895255f9d900db0450d63f9f79c1a7013cf0381f3f19045719b9e8ceb562f0e965dc07b09f371a963a281c749c2532f654a:0381f3f19045719b9e8ceb562f0e965dc07b09f371a963a281c749c2532f654a:3df0e54c711e3132d7ae953deb7b66869ee531ee40b63ce693206cdb2f4bda0a2569e913ac3e6532c5d9648efd4627780fb8a31d107e033f054d19ed8b7c49dc407d2e949de25f99307221d35843f6d5eb7de5cdf41b91dbbf34cb6c9c530021014b56abc44ac2300313615608a7b4a235e99c14cef8050887032209488b9eaeaa82c09405fc75bec94dd42d6ff1b599a63ee5742f3364093ac92cabab3035822aa867ae56dcc99d:7c7430305b361a9e35b2780c4d4408071b2130931d39830ec8d313aafbc83a65dae19cb747d9d1c4ce3f359cc824ea8c92f66a42b8614e7848b884ac8aa4ae023df0e54c711e3132d7ae953deb7b66869ee531ee40b63ce693206cdb2f4bda0a2569e913ac3e6532c5d9648efd4627780fb8a31d107e033f054d19ed8b7c49dc407d2e949de25f99307221d35843f6d5eb7de5cdf41b91dbbf34cb6c9c530021014b56abc44ac2300313615608a7b4a235e99c14cef8050887032209488b9eaeaa82c09405fc75bec94dd42d6ff1b599a63ee5742f3364093ac92cabab3035822aa867ae56dcc99d: +b636a02448003543db864b40b5d8d6dd9ad611624c9b0fc6890c51ea5592c7901ef360495968e56e6d3fe740b1c84c4e4490ed682deb4305afd596efb280223b:1ef360495968e56e6d3fe740b1c84c4e4490ed682deb4305afd596efb280223b:4aa85aac25034f614ed44f7adcdbeeec25fcc2a9eea32ab6a8699506f7a1cad3bc892e9dce934e75b0a8cd14642b778599286cfd8f50a9e4f2edf9f9d6291a2e2979cf1806b93ed8c9a78fae199b2854a03ec406ab3f720835ee263fbbc91cb4ef0758d775fc784c7d5b251ac8937919a9e67be88c9e44cf2ec7f560269aa0f1113d91b84401db15a3c48c7dacff4939ee01babb982fb95625c6c3ad78749060551bfde8cce4fb8a29:d4ba80300d5cb51353c03f28c44fd0a424ffe1e40d78ed7bb1133e8fe4e187505293b20a391da962c6a8ac0acec9c67226af3b6195dabe39b3662294da3e0e094aa85aac25034f614ed44f7adcdbeeec25fcc2a9eea32ab6a8699506f7a1cad3bc892e9dce934e75b0a8cd14642b778599286cfd8f50a9e4f2edf9f9d6291a2e2979cf1806b93ed8c9a78fae199b2854a03ec406ab3f720835ee263fbbc91cb4ef0758d775fc784c7d5b251ac8937919a9e67be88c9e44cf2ec7f560269aa0f1113d91b84401db15a3c48c7dacff4939ee01babb982fb95625c6c3ad78749060551bfde8cce4fb8a29: +5ca0543c71f568a00eedf50a9520f4c15b526e3fb0da816c29ea3d50b2f62a12d4a2933ce19454e331b5280100209a6ce8e569f993c2acab51dbe864c5cb2563:d4a2933ce19454e331b5280100209a6ce8e569f993c2acab51dbe864c5cb2563:4ef8496978d28c10abd54a26356ee55921ceb350dd4b742c4161fbeba8a1601f8ad0484b21a8cf5a294fac00ec8a6f59e3362e47bfae1e28a2e6d017c5caa75fb0f48482808037ca21476954d778ff1a0586da3ef69d6cef6d2d8df4ae7a85442a1e46c998cf407a6ad4c5463a43c248f3b6937fdbc845b60c6d85e0563cc16ba9675d364f525f669aaac95f428bb58205099f9e4a6dbbd0151fb65babe123e5393ad64026935cb488aa:436823eeff3edce5d8587d68e5473ef3d8dc9465b558b6e8e7cd3137eccc80b4c4e806edf13619d8e717e69f48d7061b68de02c8209be1f7ac26ba8edf606d024ef8496978d28c10abd54a26356ee55921ceb350dd4b742c4161fbeba8a1601f8ad0484b21a8cf5a294fac00ec8a6f59e3362e47bfae1e28a2e6d017c5caa75fb0f48482808037ca21476954d778ff1a0586da3ef69d6cef6d2d8df4ae7a85442a1e46c998cf407a6ad4c5463a43c248f3b6937fdbc845b60c6d85e0563cc16ba9675d364f525f669aaac95f428bb58205099f9e4a6dbbd0151fb65babe123e5393ad64026935cb488aa: +5f87117da9bbb6091c94da6b230b7d8f6de0ed2a076413b92eacdc43abbc6897aa786a146226832aa73c434b0edc2d41d2558f820ab8f87e09e6cda91072b9b6:aa786a146226832aa73c434b0edc2d41d2558f820ab8f87e09e6cda91072b9b6:2297c40a2e8365bae4c5f0630c50b13bdd9ad9770a5d9a9451d00874b023d25ecd468b96571b2f16dcb1b0d3d756c1f044fcddd1c51f27727a0369c9cf25bd6aa59551b5b07cf8f807d92b159198639704740fe6eda0f26dba7e75d4530b2800f03fb6aa677d84df75d68d4fbb64ad21001e3fc87b609b9c251e8ccb12bbca927447e2054e07688eb8a20521a52249e7b943bed60e6a93c01e3eb621f0460c18a690b6f6b66edc6e8743a6:0f19e6ea0c05f38185c01c2d6477995daf5065ba9d80173fa6bb23a774dc88b3aae879d8a62471d2d304cc3dc66278a7abcb0bb0771cd278e11e7b932e9f9b0f2297c40a2e8365bae4c5f0630c50b13bdd9ad9770a5d9a9451d00874b023d25ecd468b96571b2f16dcb1b0d3d756c1f044fcddd1c51f27727a0369c9cf25bd6aa59551b5b07cf8f807d92b159198639704740fe6eda0f26dba7e75d4530b2800f03fb6aa677d84df75d68d4fbb64ad21001e3fc87b609b9c251e8ccb12bbca927447e2054e07688eb8a20521a52249e7b943bed60e6a93c01e3eb621f0460c18a690b6f6b66edc6e8743a6: +b53a644c92ba2dc7108b16833f09ad5917846437225a773d32d79c97733c0a58515818c69c0e0a1706b04143842f3e9e271448fbaf3a899119c32f42566ffd33:515818c69c0e0a1706b04143842f3e9e271448fbaf3a899119c32f42566ffd33:13036daaee45fcfde0c53e06d05aa9c01ea94a67e86c6c538ccb283b368daf7078d3fbab580c76ecf82b4e9660f068dcbb500b80595017c5be3c448fbd8a17d97c5643197890e167b35345bf65e75b82c8d65229f2f60aae2772581bc99c49d416bc3d78746ef830f1af944f4a6715ab4ffb01591bac2857f1a9c9d1700888780006a31607338f7af7bedf6efe0b57299ac915526fe5e1e101298708c6e61b84220afe95b53f895987456152:13d2cbac7976ad27f0bf669ad588efb2c91bab8507d57fb16bfea9caff2b0964e75625c4d808d7bbb78c5b464edffe4949ecfbc8b95ff6fdb1bdca274206810013036daaee45fcfde0c53e06d05aa9c01ea94a67e86c6c538ccb283b368daf7078d3fbab580c76ecf82b4e9660f068dcbb500b80595017c5be3c448fbd8a17d97c5643197890e167b35345bf65e75b82c8d65229f2f60aae2772581bc99c49d416bc3d78746ef830f1af944f4a6715ab4ffb01591bac2857f1a9c9d1700888780006a31607338f7af7bedf6efe0b57299ac915526fe5e1e101298708c6e61b84220afe95b53f895987456152: +d27c9eafcf88151990bb5b2fa8443e709b5fd8d78d233803322dc86d93d9329508e0eff529776714686196d817fdf71eb5b6e8326516ef489bfe186ac5c5bf6d:08e0eff529776714686196d817fdf71eb5b6e8326516ef489bfe186ac5c5bf6d:77c35bda32a5967d8b302fa7a47583ceab89c9a609a667b753155fa6996f8631d0ebedfe0ac364c77e85ba37311f0de57a0dc2c1e9e400d58b424a322e1d5771e0a9fd9502ad0232ce544f07d8c66e7c3147f8607ac6189bb69066f2fad631185f457f467eba33228ecc40e894a77b571698a9bfac841a54eac5219da99c6a9125c469a22fe81f3b951433896f19ce39b373fd7e5c7b650a5ef2365ae7510b0da5e49d7c07073cf166a98387e8:c254e371445633137442eefe40ad4a82e69b1ebf48a685a2bc6ffbac126d228487b2e3537c97ef7410342091962e50c0cb85de7b39ceb41ac4078d40f340710677c35bda32a5967d8b302fa7a47583ceab89c9a609a667b753155fa6996f8631d0ebedfe0ac364c77e85ba37311f0de57a0dc2c1e9e400d58b424a322e1d5771e0a9fd9502ad0232ce544f07d8c66e7c3147f8607ac6189bb69066f2fad631185f457f467eba33228ecc40e894a77b571698a9bfac841a54eac5219da99c6a9125c469a22fe81f3b951433896f19ce39b373fd7e5c7b650a5ef2365ae7510b0da5e49d7c07073cf166a98387e8: +70213d3a79c65d6dbba542a3679635003a682af5fa58de6b0d65bfa24184901c4402fb92cc1249dd1ae1690f03b3ec4f1e9bdab0de5bfd289f10296830fd403e:4402fb92cc1249dd1ae1690f03b3ec4f1e9bdab0de5bfd289f10296830fd403e:cd6e1cd9c90f566de043d75d7244ecfdb38e8bde2f9a6cd5a4fdac72b5ede6af62d981918c5e610a38789274fa10e527f85fad209b76ca1c281ad5890f9c96d35de522f1ddccb539b8798a0067acdd45b6e344a5d9a97731f545ffa4b17b875c67b48e9d4c4ba72c98a4505583fdbf1e12f22b5a7a494746cc9b6c1b571906c67fcc883a9c15a3806875b659e5816b4276c3190e25cc1ac3de47bf99c49965388f54f3ef8eb569906c6008e5fbbd:5b6ce2774d400ecea8a808f5fd0a797ffc6116752376cd7bfa3b2cca3a84d5593f5c03ad3eec1d89532275c47b7ce2a0e9c59cc4028a8a65e5bb9097ea71c208cd6e1cd9c90f566de043d75d7244ecfdb38e8bde2f9a6cd5a4fdac72b5ede6af62d981918c5e610a38789274fa10e527f85fad209b76ca1c281ad5890f9c96d35de522f1ddccb539b8798a0067acdd45b6e344a5d9a97731f545ffa4b17b875c67b48e9d4c4ba72c98a4505583fdbf1e12f22b5a7a494746cc9b6c1b571906c67fcc883a9c15a3806875b659e5816b4276c3190e25cc1ac3de47bf99c49965388f54f3ef8eb569906c6008e5fbbd: +5d540b3b14f0c0175c047eaf026c9070659ef13e9d28e0c5c516a428269b14eb1d2d4d551a57c6fb2b04181049d4039d575cf80c0bc6ec7033067f27309344de:1d2d4d551a57c6fb2b04181049d4039d575cf80c0bc6ec7033067f27309344de:e4c9e8706898cad4ac68d73c130efa04a54f8ca25919ea6bfaa54c8c720ced854c5e9509102c7b885aeddffbd1b7f2c5922583677ac9eea9a108c7e83e8871aed5a084f5440b0f391ad7ffc6bab4574af1b96770f4370e8e988e85ecb1a8d6034fc3d7f49f7422023b9dab5d0c16beab5f5d37b0a4d7de197ad87cd4ff8ce78eb12e1daf739d8b47ab380abe9093356db5b59717751a49e1948472fdacc259ffffc8c1dbae592607d4ec71cc6a8f6b:32527da755312889935dd5ee91b1bb117a5d377dd23ef5b7e15baffae9a54391a3fd234bdce073e098c58d05bf195b4c3cc63972383ba4b51072971aebcb620de4c9e8706898cad4ac68d73c130efa04a54f8ca25919ea6bfaa54c8c720ced854c5e9509102c7b885aeddffbd1b7f2c5922583677ac9eea9a108c7e83e8871aed5a084f5440b0f391ad7ffc6bab4574af1b96770f4370e8e988e85ecb1a8d6034fc3d7f49f7422023b9dab5d0c16beab5f5d37b0a4d7de197ad87cd4ff8ce78eb12e1daf739d8b47ab380abe9093356db5b59717751a49e1948472fdacc259ffffc8c1dbae592607d4ec71cc6a8f6b: +ca41769caf1717b4e45c93c121dc82a534fbc6ec0986662c3222d71492bd1176af3f89f6187dbcf9217750c67ef89ed47b039f9eb062ffec9df64ab52b0b45cb:af3f89f6187dbcf9217750c67ef89ed47b039f9eb062ffec9df64ab52b0b45cb:9de8476c5813848ab1451537841cc178002181a2182af305b12e5f7c3b1d56b22cf46ae6276d1826ec0a8c9a7d9f68083b7225bbfaefce82b3b64594052a7700f309233a79fffdfccc5c21400c91cc0e418d5141d486b5219901d6dd2447c1f7b7cf5a0879e70e1dd658d0f2ecf31ebeee11a5c74440c63b9d8b45318c3465d7ff03365edd0385edf80d4fded51f0f7533ee4099f19e93bc9d08dadcd13485db239522ffc81e2c051f8796d62e979fcf:5cda872f7ed6d7c90218ac10bee8e214f3b34d15d25c39255ec9e6b0177aa3cb7368d11cb8ed6ff5cf0c04281d06bc4272b8bc09c23f6f4cd5a810ddc7b9c1039de8476c5813848ab1451537841cc178002181a2182af305b12e5f7c3b1d56b22cf46ae6276d1826ec0a8c9a7d9f68083b7225bbfaefce82b3b64594052a7700f309233a79fffdfccc5c21400c91cc0e418d5141d486b5219901d6dd2447c1f7b7cf5a0879e70e1dd658d0f2ecf31ebeee11a5c74440c63b9d8b45318c3465d7ff03365edd0385edf80d4fded51f0f7533ee4099f19e93bc9d08dadcd13485db239522ffc81e2c051f8796d62e979fcf: +fedd63ffd4cfbf618894962e121a9025eea318a80a1adf169d6490445d2e02a0542f2244bdb7d84b87e628a8e6a12f17bf74a9a6d0ea46c595dbfdc680c04b26:542f2244bdb7d84b87e628a8e6a12f17bf74a9a6d0ea46c595dbfdc680c04b26:2e2ae584641be03dd48f9c618077aeaa18212a4241f0c0194ed23e370d741a3ae11a5fec3b040c16eafa4ac8d18abaa7ce8f286967337189f0495ffdd61995cde31dd8dfc3df5700b57a7a29980e9c823fee85d61451176729e72787c6109b47359b93dfd62e1e5a2d642c057242dae500a94ca1a93bc57be1ade76fe4501c0f6377ed0e9246179aecdd9946b671e8190e1ed23f966e96409b948222d8ea5839de904fc51348073b8f40edbd9b4a4b2275:ed59d9e23dec3494b0fbc5d10cd02bab86b3eb35abbf9e4d4a926479f134583a44ce72dc4122aca377a4072b7156462b74e8df46b686698636836ef203179c072e2ae584641be03dd48f9c618077aeaa18212a4241f0c0194ed23e370d741a3ae11a5fec3b040c16eafa4ac8d18abaa7ce8f286967337189f0495ffdd61995cde31dd8dfc3df5700b57a7a29980e9c823fee85d61451176729e72787c6109b47359b93dfd62e1e5a2d642c057242dae500a94ca1a93bc57be1ade76fe4501c0f6377ed0e9246179aecdd9946b671e8190e1ed23f966e96409b948222d8ea5839de904fc51348073b8f40edbd9b4a4b2275: +38f2184eaa553656ee2902706bcec4acb5af25157ca0f6a2d48de85285fa3bc07ff03fb4c82e9c15d659df424b3e73ed1d78006f3e0b79eb64d98c13aec6ba37:7ff03fb4c82e9c15d659df424b3e73ed1d78006f3e0b79eb64d98c13aec6ba37:c2df77c9e479f61983b6c7483ef93fb85a103b213923926523065ebff2257e85427e05cdc27582ef6c16be353a3b250372d6370eecb6c8962917eb656f2641690189d172a111051557abc2494e32cab65ed0633affe92408b55c4ed8af65e2c5e7aab887a3cc8d28c52e9e1336d0b7bb3fe2cd843e7fa1680342f8a4aafa02c4ab252f08c3d46d5f00fd01484263ee635284f6db26d6298de5b0dd238da40a8d2a93376da0302783a0e3be23d9e7f990d25b:4a6413c2c87f2b3856a8decbce493adeae0c69c94134707fb0f18f3049fd3e3d051abdb9d4bee253c6107c02d57ad7cc9f3101db660afac2b7981938e9564f01c2df77c9e479f61983b6c7483ef93fb85a103b213923926523065ebff2257e85427e05cdc27582ef6c16be353a3b250372d6370eecb6c8962917eb656f2641690189d172a111051557abc2494e32cab65ed0633affe92408b55c4ed8af65e2c5e7aab887a3cc8d28c52e9e1336d0b7bb3fe2cd843e7fa1680342f8a4aafa02c4ab252f08c3d46d5f00fd01484263ee635284f6db26d6298de5b0dd238da40a8d2a93376da0302783a0e3be23d9e7f990d25b: +8bfca48462d2536f74b84f6af59f5d8582ff8f7ec28745d672e72eb72e79d3e99d10d275c3d3fe459f7fe2901bce389191cc8483c0f51140d9c62b08fade81bb:9d10d275c3d3fe459f7fe2901bce389191cc8483c0f51140d9c62b08fade81bb:81ee4cb9c45da691dacd7dd09aff59737267bb55c3ade1ba32c17b7d0d2d0c6079c39d5fd5b29ba5f9c1762097709843eee5612bd20bc8185bf64d5c934184e13624e6f877a2a5dda15c0df62afbb97057cc91cac9a18406a0e0109cc39b2e3f812e227a4062d5ef81c92c22a7dc797c845d71eb6ea9e42ec8417fba90a96d2bb1439418330b4bb2f99c6d63d304a0e506dca9653e5de0dd56e309db1a76a0faabab163774f000088cef3d1b7a6cf661d2e1d9:44d77e439ef6ca5eb940c60ff8732ddc16269ea023bb2613bd447eba7fd69851226c4819ce8d44985a49f3f41ac7af33c47ffe5f89304a3256e445f8d686e30781ee4cb9c45da691dacd7dd09aff59737267bb55c3ade1ba32c17b7d0d2d0c6079c39d5fd5b29ba5f9c1762097709843eee5612bd20bc8185bf64d5c934184e13624e6f877a2a5dda15c0df62afbb97057cc91cac9a18406a0e0109cc39b2e3f812e227a4062d5ef81c92c22a7dc797c845d71eb6ea9e42ec8417fba90a96d2bb1439418330b4bb2f99c6d63d304a0e506dca9653e5de0dd56e309db1a76a0faabab163774f000088cef3d1b7a6cf661d2e1d9: +d7480d4272bcb1557b1bbee04915c126a52ca6d6a8bb5314a0e1a52b59bfc99c99c839d36d8f5b8652618ed7b0fe9ec3d94efff4c453c540631476a5979bbbe0:99c839d36d8f5b8652618ed7b0fe9ec3d94efff4c453c540631476a5979bbbe0:615cc19f942017365ba8bfa256ceccc85ee289a1c34bb1442acc0716c7fc2caeb76a9de19adec106371e47a30d2e1239ce1f7dca25526d604bdd647659d942bcbac368911349c3b946a97da10a42dbcf3c73416d2e6ba22bd29d9f705672e9e338944cef01ad21f009742e07bcd888ca31e1ee953e8c1b1fd954b7dcf1a0b1d5a069065a66cb721adc020f4efe1abdd16742746939285780d753137ae0140bb410fb6ce33676c27aeec593a88cbc73afd9f40511:e04dc8442d352173e931818e290858de85688a4649ea3e3c3ae74edaa54ad01b64622ad8a090b6ad60adfd01881882828d39078bb5b2714fd3ea8397a342fd04615cc19f942017365ba8bfa256ceccc85ee289a1c34bb1442acc0716c7fc2caeb76a9de19adec106371e47a30d2e1239ce1f7dca25526d604bdd647659d942bcbac368911349c3b946a97da10a42dbcf3c73416d2e6ba22bd29d9f705672e9e338944cef01ad21f009742e07bcd888ca31e1ee953e8c1b1fd954b7dcf1a0b1d5a069065a66cb721adc020f4efe1abdd16742746939285780d753137ae0140bb410fb6ce33676c27aeec593a88cbc73afd9f40511: +3c2d3650735b41ef9006bb45e4be2e0aa5cde851aeac421ee9c1b492d87aa18a3e46ddce298844fcafa00a1b47eaf3de70596df1bbee3c809d1be7dd94080e34:3e46ddce298844fcafa00a1b47eaf3de70596df1bbee3c809d1be7dd94080e34:1425d8d218da1a10a80b6a9c3c2750efe41657984abd5100f451ba949db01046b7126be8402334ed57528bac05622553a86b726722695a8fb331d8565417c4ff0f251a320ad06dedbb750def35d521c3c4cd571a45ada8450653d5e81fe0beb53aaae787b3eb653c2381ed55aaf2590ee5ed8b6626f1c4b0430a54f39658624e6635fefc98fee8fc3e1cc7ff3dd420de9da11a62fcae0e0cb454fc6f7df03954291d26202f1b188b657b3bae07389449b75e67422f:3f2af01ad5377ac39040d41a41e36e7b93fa7235b841791f432ecd7f91a3b21ab7196c883ad5a7db446f6c06672460f3f63ef863d9432be9caeabb79e87e22081425d8d218da1a10a80b6a9c3c2750efe41657984abd5100f451ba949db01046b7126be8402334ed57528bac05622553a86b726722695a8fb331d8565417c4ff0f251a320ad06dedbb750def35d521c3c4cd571a45ada8450653d5e81fe0beb53aaae787b3eb653c2381ed55aaf2590ee5ed8b6626f1c4b0430a54f39658624e6635fefc98fee8fc3e1cc7ff3dd420de9da11a62fcae0e0cb454fc6f7df03954291d26202f1b188b657b3bae07389449b75e67422f: +74965996268cdc4c09220bd31ce07b217a03826ee981fa89f3a2359ced095ef14096d027c1c5ee4cbfc04b9d534174029fdb50cf5610d3021ef933b4caf33985:4096d027c1c5ee4cbfc04b9d534174029fdb50cf5610d3021ef933b4caf33985:45b2f064615bf774fce97f51c464685d7b3e4fefff9231240a719b3b0621cd4ad83305675cd6eaaebff791000b0b1fa31d82d8181b7fe57c5e00cec56ff9022e9ce8db66356e408e3ee262fe627789e65535ef1a63e8fec933be3dee34d2facdb8928cc456abf2f3e8cab47eff1ca42e8b0e48d2c73e7bcc5de3f1056fc523dfef6b0023f32889ed394eeda032abf6bcaadaa7f3ee74118760ab6d91df528bdc5807972c85fa7cb56e387d7332e779e52d0dd7db0cfb:8c6628344317a63aca6f78cfaea965b3aa5522ce914195141c08870a1b8dacf34b79c7abc693cd9e5ebe1a2e86f0332d2048db3cbdef01687962d6df249e380045b2f064615bf774fce97f51c464685d7b3e4fefff9231240a719b3b0621cd4ad83305675cd6eaaebff791000b0b1fa31d82d8181b7fe57c5e00cec56ff9022e9ce8db66356e408e3ee262fe627789e65535ef1a63e8fec933be3dee34d2facdb8928cc456abf2f3e8cab47eff1ca42e8b0e48d2c73e7bcc5de3f1056fc523dfef6b0023f32889ed394eeda032abf6bcaadaa7f3ee74118760ab6d91df528bdc5807972c85fa7cb56e387d7332e779e52d0dd7db0cfb: +0abf069c08b2691c3a26f79dc8ed05cb71d220ff78f3a5c5780ae9da18e456439ef3b5cc016cc82dbdda705766aa448bd61fa1aaf1170efe9149daa9fe64a1ae:9ef3b5cc016cc82dbdda705766aa448bd61fa1aaf1170efe9149daa9fe64a1ae:0d055291b2e861eae19ea0fb2069d8c9eef4f1347f3576d78411ae7c0b1c1caf31fde736dc8accacb662df76b620b62ce90b9f92c83309128621d057cf845805949088e938ddbc3d41c5e5541fec8298687ad2f79acda01aa215d25821436eac9d268716d4cd6050260cb4ef6aada4835e073a845821ff211ae2baadceb6e57f06f88345edbf93bfdf54fb74123b57c0fb4a79608d8db6740889e15733507799f7a1fd3017bcd77b28a2bb6c91ecd154e9c5a5ffa0eb62:c7566fb3b4d8def667e040f276d3ed98d36dff460126a75b4cc2100386bb01c642f6d8de7e649be6e0818b08d77ce60f4ee5e7717a50884bdee02034ecf1cd0c0d055291b2e861eae19ea0fb2069d8c9eef4f1347f3576d78411ae7c0b1c1caf31fde736dc8accacb662df76b620b62ce90b9f92c83309128621d057cf845805949088e938ddbc3d41c5e5541fec8298687ad2f79acda01aa215d25821436eac9d268716d4cd6050260cb4ef6aada4835e073a845821ff211ae2baadceb6e57f06f88345edbf93bfdf54fb74123b57c0fb4a79608d8db6740889e15733507799f7a1fd3017bcd77b28a2bb6c91ecd154e9c5a5ffa0eb62: +f3fd5ec5e230b6dad1ac3d3aebadc7863ff89de2a1317f424d15989a3efb0afdf99e5d5eeeaed1205cfb5c2cc4e5e9f6b4e7f64129f860104ca6244eb9feb564:f99e5d5eeeaed1205cfb5c2cc4e5e9f6b4e7f64129f860104ca6244eb9feb564:71f28973ed3df05945fa0bdb23e9beca651d3ee6bf9fa45ffdc6061e42fa2e8d76235f0e9e2daa65e52631fc3bead33da055bb492e4758e598a030a33b3c40b34371459b233ccc043cccc3a3cbce549e20e0b2b43305b64aec661aadba6556b17d76e3bbed62c4a4eac4f88603996752d2363c8d4a2789d128f6e959945c68c30146d194ccb6839ec65344601652c18b0074e2bc7668311697d960c7066597924d704d02a0193fafbfdf571ee0dfe414dc2f52896912bc32:44b0124663adb0c73aed49f73403461fcb19111b0ba17aa996566f477e37d524b0e1f107612fc52a7c767b181fbf4d629bddc08f30584dec6124c5d39d42310271f28973ed3df05945fa0bdb23e9beca651d3ee6bf9fa45ffdc6061e42fa2e8d76235f0e9e2daa65e52631fc3bead33da055bb492e4758e598a030a33b3c40b34371459b233ccc043cccc3a3cbce549e20e0b2b43305b64aec661aadba6556b17d76e3bbed62c4a4eac4f88603996752d2363c8d4a2789d128f6e959945c68c30146d194ccb6839ec65344601652c18b0074e2bc7668311697d960c7066597924d704d02a0193fafbfdf571ee0dfe414dc2f52896912bc32: +738f1310a4e08f917a0a5c1fbaf4ef72f95ee62fcded50868a3daf98856a448d42272c2c8b08470ee5dd8af8849c01b7508d3a3c65b0330e695c841d5dccb2f5:42272c2c8b08470ee5dd8af8849c01b7508d3a3c65b0330e695c841d5dccb2f5:f0e7ef6782d04c6943b19eb66ff6226b736e3b0940c09bb126bfc4c4ca7a5e7016c286b7bfd73aa6a79a96031bc81cb5da68cec71a6a0d39780cbe6a0cd4774d3aa06a881610444a8c9d19102294e5f635187aa6f48d11912c7094b38833028d570cb110db60625bb1bdc37affa25ea3c8f8dbfc2514f4365c62b2989a66d27c80384e74ae5fba8c1c2af9c72c4971e64fa6a1dc2517b31ea57ccb0815a7fe2da0f146caa08431d25d151662d9d26e95229d0c62823664123c:ce1e3577b6a21016b9dd0b517baa0ccb107bc199b8bbaef68f950c8ed58013c853b4d338eedc675079ab1390462ffefa6a959b043f8b5651c6ca375ce0b4a403f0e7ef6782d04c6943b19eb66ff6226b736e3b0940c09bb126bfc4c4ca7a5e7016c286b7bfd73aa6a79a96031bc81cb5da68cec71a6a0d39780cbe6a0cd4774d3aa06a881610444a8c9d19102294e5f635187aa6f48d11912c7094b38833028d570cb110db60625bb1bdc37affa25ea3c8f8dbfc2514f4365c62b2989a66d27c80384e74ae5fba8c1c2af9c72c4971e64fa6a1dc2517b31ea57ccb0815a7fe2da0f146caa08431d25d151662d9d26e95229d0c62823664123c: +8841d22aded69c131ef5ee0a10ab0a9b77cb754ede8d257a5372726e2b499c6e715ecca63681bc6e9e31d18848902f4d96feaf43b95d008642903b1763bc9fb8:715ecca63681bc6e9e31d18848902f4d96feaf43b95d008642903b1763bc9fb8:087ca6be2a950c024b3e7467fe00a7d364555d5dc6770f5ebd260642525bd3c0f965db36d7b229a57421eec64e4d991cdde59123034470553f4eb0be81ad2936c8ca26bcab4e5d79040e29798728601684a468323cf3baae4d948d0a1fd905effe16dc44642088df53f6388bc480edf4aa207d0ed161eda345712b4c00cb05fcf635ec2588785bfb8a27cdc28996a1db3e6787023393c075d83c9038fed7899c55fec307de3249c14bda49e8b895860942c36d640bb893779142:bb2bab7003f1311be9b8c883fc4fd528adfd51a9c99db3dca8da0fca958da19a10eb22332667b1a0065d3dbc0d06269a1259b6a890484aa2143a52695f145b0a087ca6be2a950c024b3e7467fe00a7d364555d5dc6770f5ebd260642525bd3c0f965db36d7b229a57421eec64e4d991cdde59123034470553f4eb0be81ad2936c8ca26bcab4e5d79040e29798728601684a468323cf3baae4d948d0a1fd905effe16dc44642088df53f6388bc480edf4aa207d0ed161eda345712b4c00cb05fcf635ec2588785bfb8a27cdc28996a1db3e6787023393c075d83c9038fed7899c55fec307de3249c14bda49e8b895860942c36d640bb893779142: +c02135e7b65aac72f63c32bf5bef5b68c7f3b8ed56208e59e4752070e9d07095dcf600f244037a75203ae11ac316e8dbe9986f0dce23473939334bf5cea48b0d:dcf600f244037a75203ae11ac316e8dbe9986f0dce23473939334bf5cea48b0d:86d9491350d2566e708ed356185d610c73465b2a5c7012919958af2cf76af995230d360de400b7137170dd0835f10fcbec224ee4e42c7d1cebb7f580fea8ed6223163bacdd1923a572cbb6dc26ca8b17ade68c6d2808c4ca1eca28eae9a145f68d4079d8d59d140e958228e7e99520e342dbd7457a9159740f48bdc27b93bdabeba465cbf0c8df5ef2c0f9386eebe656f5d749d5f9147f525266910d7b80396a90be5cc188a9a945f93e753fc99bafa18ee0a6dff79bf8484898ef:dd5cbae479eb5e229574c21ec3bed911113a57a1916d3313457515d55cc5b6e6ebc52c93f821d13988dbba8df5096d55ff9c39e7f9d561cb58930c96a7a5d60b86d9491350d2566e708ed356185d610c73465b2a5c7012919958af2cf76af995230d360de400b7137170dd0835f10fcbec224ee4e42c7d1cebb7f580fea8ed6223163bacdd1923a572cbb6dc26ca8b17ade68c6d2808c4ca1eca28eae9a145f68d4079d8d59d140e958228e7e99520e342dbd7457a9159740f48bdc27b93bdabeba465cbf0c8df5ef2c0f9386eebe656f5d749d5f9147f525266910d7b80396a90be5cc188a9a945f93e753fc99bafa18ee0a6dff79bf8484898ef: +154a47eba1b8c38362ea61faeb0c0ad7e61e412a3cba4688af0db2a487208b1c16de2c894a50cbd4ca90419a4ca64942cb14bd335c5d3f4a53e239c280bda725:16de2c894a50cbd4ca90419a4ca64942cb14bd335c5d3f4a53e239c280bda725:bf607e8b6e14d9c8acd96815af0c035ac73c4104c93786ccc1c9f859395dd781900320ebf356aa991cdc9f503fcee9f83675888a7d592002d2a54a573a96994b3fa865538c617ed8ad1ff62018288a674f449be0aab5222f74c4fd475ed6a8dfb27f45287b22b2b6c3bd15179f267d157d7d8a4159679be85b25c2bb2ba850aaed9ae3ae571be4f75836329cf36f412c1c80f1413b7661eab4a8e11b6024244fc62323ff02e38aceb1737bd474bf1e98015dbc788b027bbe217cf4e7:f4b6eb1a8d950e887fd2f30f70a23b41871495bfa5b8a4ad3996cd9bf51eb742e07f4c4d2da4b01ab087367a50e2b65b3cef514e40d837540b8c89966485910fbf607e8b6e14d9c8acd96815af0c035ac73c4104c93786ccc1c9f859395dd781900320ebf356aa991cdc9f503fcee9f83675888a7d592002d2a54a573a96994b3fa865538c617ed8ad1ff62018288a674f449be0aab5222f74c4fd475ed6a8dfb27f45287b22b2b6c3bd15179f267d157d7d8a4159679be85b25c2bb2ba850aaed9ae3ae571be4f75836329cf36f412c1c80f1413b7661eab4a8e11b6024244fc62323ff02e38aceb1737bd474bf1e98015dbc788b027bbe217cf4e7: +d3028431ce2eef73bd940ab84ca29f13fb26436aa25e1b7bf26cb33f17fdf81763df203e2860bac4d352e722c1c91fe3776e1cbcae8553a4f19890260bf0e457:63df203e2860bac4d352e722c1c91fe3776e1cbcae8553a4f19890260bf0e457:086335d61275d168eaac0540477f50d4b15f9e50b9be693921ed54a9941bc40643cda62e1d805d0250a81146bd5fe2d39e81444d21e2b21b031c111306cacbf52717f6fb4cd3416f1215f8dddcedd2f0096b0fcfa0a6cc2cde7a2bab7f1e32790b5361df3671424cc722f231bf71895bcdcb7b22ee074e8fb4a9678504e735366c172f07637b7a93149bb21f38883378a1db273fc23239e35337f9ce566d8ddf3b3133cad7f2ce81edb503ce1d27c5a657160b78dca9aeaea379be9c85:ce9729a96c3ed28943b27839c73382ecd572960c1f9e90c5eff9dd499ff48f17d25edd1268effe41ee6a81ce48d84de513df9c41442621b2f5491e346be18c04086335d61275d168eaac0540477f50d4b15f9e50b9be693921ed54a9941bc40643cda62e1d805d0250a81146bd5fe2d39e81444d21e2b21b031c111306cacbf52717f6fb4cd3416f1215f8dddcedd2f0096b0fcfa0a6cc2cde7a2bab7f1e32790b5361df3671424cc722f231bf71895bcdcb7b22ee074e8fb4a9678504e735366c172f07637b7a93149bb21f38883378a1db273fc23239e35337f9ce566d8ddf3b3133cad7f2ce81edb503ce1d27c5a657160b78dca9aeaea379be9c85: +ee8985dc27504440a8758d4c53e4225215797a00cd8631d59bd93bc66f373d5ecd647bb065693d486589156a9fa261437534dc86f46f72d0a800399a7af010f7:cd647bb065693d486589156a9fa261437534dc86f46f72d0a800399a7af010f7:f2220485addfebce02a833aca33381d1df917ed609950ed24f85e3b02b2b994b4d939784e332f41064c8b4a2630ab36961742aa1cffdcb08c144eeaedeafd48b5dbe96bf24350e14fd68286bc08eeaef8bc6ad9e195d1484afcd30afa8ced4848126d56c81b43c27a5dbbdec1a50c11062ce21c61d860c25a862fbb75c3bd51c8dc07636668669bbf751eacaccb3b51d2c0d4140316cfce2eb18d2908cecd5a188679bc5f5de290f548e7ebc57d41b589a24ce88ee48d97e8d0c7c769960:5bd60ad5e9bad9932ca9c75f231a76889ae7a8b864b91d1fcba5c5d4bfa1d92838adb974842a0710779b3e3094044909e92c7cf046ce519f4c68e8f19ec03c02f2220485addfebce02a833aca33381d1df917ed609950ed24f85e3b02b2b994b4d939784e332f41064c8b4a2630ab36961742aa1cffdcb08c144eeaedeafd48b5dbe96bf24350e14fd68286bc08eeaef8bc6ad9e195d1484afcd30afa8ced4848126d56c81b43c27a5dbbdec1a50c11062ce21c61d860c25a862fbb75c3bd51c8dc07636668669bbf751eacaccb3b51d2c0d4140316cfce2eb18d2908cecd5a188679bc5f5de290f548e7ebc57d41b589a24ce88ee48d97e8d0c7c769960: +80dfe2bf7387bad4654eb076f8dae9595163e40127f5df492dad7df04c7221c4d1783ceeb9cf8e4d07764c473fa4061b8274397103f2076d703249d758b8fbd5:d1783ceeb9cf8e4d07764c473fa4061b8274397103f2076d703249d758b8fbd5:aa09d784bb09dc999931ebb4c00e424cefeca104818d8eaf0661f09728ad025ef47393210571f17404e9aa6d8cbd5fd88cd7dfb8e2e8a108c05de206f3408234a3b463dbe71a07d05587324524b7326ee79d3348ddbed7871b86fcb488031dc9ea93f6b8d7fda6239348a562444faf1e72d31af35443e9df53e762f3e56b48668f9784b3368ab278a48ef4546a26cfad0d0a5161698f26ee8d34fc2b3d6dfb93b009ac296f6afe487ee335eac9f02cfcae5fcbd1a16ba4e71be1b112562fc2:27279e3cdcb03ef557a5defc2f6c58128a6dc3f8b0385958014e709c1f61b0ae6b403576f0e454d5e4c64c173138ee4bbd5fe7b60d06c5abe23fe99ee3b46a00aa09d784bb09dc999931ebb4c00e424cefeca104818d8eaf0661f09728ad025ef47393210571f17404e9aa6d8cbd5fd88cd7dfb8e2e8a108c05de206f3408234a3b463dbe71a07d05587324524b7326ee79d3348ddbed7871b86fcb488031dc9ea93f6b8d7fda6239348a562444faf1e72d31af35443e9df53e762f3e56b48668f9784b3368ab278a48ef4546a26cfad0d0a5161698f26ee8d34fc2b3d6dfb93b009ac296f6afe487ee335eac9f02cfcae5fcbd1a16ba4e71be1b112562fc2: +da1f868542cd7cce7a5ca3fa3c24081b4d2344b21a157f0264a347132d19659dcb3a25a53f272ea813804468d6500e96a1eaf822705b7790a8ac3e98cc4e524b:cb3a25a53f272ea813804468d6500e96a1eaf822705b7790a8ac3e98cc4e524b:c6987ef380d5d0e74196443aaa3a32356cbc02636c5a4b6d62a8114b2111bc1abddd9e44b3672c18b58d4ef591af4562e020049f8e1274688e1f8e5296d2f9252e7fc84cd1d0c58e98f0f160530aa22c871eef652e71974ce91b4a65fc25fd09fa1b6c32086e98ec708d9abcb1d9cc8e1a089ed8db2206ee9570236ad69b3de6821862fd2c70cd83a32a68b0486229553d928de48d03a104e87381964abea76683976d527c84163a12eee0a55986cf1431e9c86cba8182ca94689bacd165fbce:75c517ade4f08d7746305743d1a776c3c55eb5eedfdfcb5eb1d5634a1bdaf7a4b8d24187d6c8850e3ced6567a03c4c59389a4cf47114ce5473160f230546e60dc6987ef380d5d0e74196443aaa3a32356cbc02636c5a4b6d62a8114b2111bc1abddd9e44b3672c18b58d4ef591af4562e020049f8e1274688e1f8e5296d2f9252e7fc84cd1d0c58e98f0f160530aa22c871eef652e71974ce91b4a65fc25fd09fa1b6c32086e98ec708d9abcb1d9cc8e1a089ed8db2206ee9570236ad69b3de6821862fd2c70cd83a32a68b0486229553d928de48d03a104e87381964abea76683976d527c84163a12eee0a55986cf1431e9c86cba8182ca94689bacd165fbce: +f13daec0ef33ddd133c7d244d10fd27ddb23705280ff5f1815f0f656d836fe842dc7f1367de672c51e005c74f876f982593996873acba079292734c209c2b111:2dc7f1367de672c51e005c74f876f982593996873acba079292734c209c2b111:ec02ff1804b2b309af3158b66272a14a3aad83c41a719846f7088ca9792af575c78913c432759f0b9a748bdc5568496e41658cc1cdb8da6c91d07c3ec2f4af504249b996aa00c0071cdfa793f82d0ec5d267262f518fc029b88e20b6201fb9e05abd3f9524c5da2fa8978ff2efd48120cf00822d1bee90df816125d8edc0cfb5de66d16be63896a412a62b031b7118ac13fe2c9faa6b1a3342f9ccf7884166cf489a84de26b5ce5b21856a3af289bc6622c0aab9f2142d393f5d4b236779dbb066:db771833f7fdbacdab2b5cc80eed50afdf13783b7fe5e903d5dbb4c2e535316a6eef4c34f004d2b9a4e2700bd6e2acdd564c3c80cc68a303f5fb091cb4340f0aec02ff1804b2b309af3158b66272a14a3aad83c41a719846f7088ca9792af575c78913c432759f0b9a748bdc5568496e41658cc1cdb8da6c91d07c3ec2f4af504249b996aa00c0071cdfa793f82d0ec5d267262f518fc029b88e20b6201fb9e05abd3f9524c5da2fa8978ff2efd48120cf00822d1bee90df816125d8edc0cfb5de66d16be63896a412a62b031b7118ac13fe2c9faa6b1a3342f9ccf7884166cf489a84de26b5ce5b21856a3af289bc6622c0aab9f2142d393f5d4b236779dbb066: +42dc16c57fb6f128945fa101e05bbf548ef7d97726b692fe404069cc57ccefa00a1ba5df523996f954b34ddcfabad3f3dee21a5fa7a4ce322d216bd8ccaf438c:0a1ba5df523996f954b34ddcfabad3f3dee21a5fa7a4ce322d216bd8ccaf438c:f2714c23a3a6fc11ad15c980b7350fc84217877661188055ff750d82c49c5fef7bc8e6aac574a1b79a3f26d16969c0f406eeab3e9e12850a55709745e30dffa62a69dfb2b64b3c1bd2bc3586e26d4eea714d2a7b71cf79fb8ffbf2aaad00ca3e4f2b6f503cc1fef2eab3656fb44f8d62a8db8ab58f394693949eea57fafecf005f6ebf1287dba4d2d623c02ea171f567e526add20709ebcab962f83d98ef668ebd01ef20488b3665e3a446fbfb13d34050942c749bb2dffc766367fd452e68e5b0c6:c75977e83bcfe9df7292a860ed972555b5c24416fd4b7ee3285388fa5b1447608e4a347813cfe093512a7651e422e9867db7b97c0b0867f0b8c7b7f4f02c310df2714c23a3a6fc11ad15c980b7350fc84217877661188055ff750d82c49c5fef7bc8e6aac574a1b79a3f26d16969c0f406eeab3e9e12850a55709745e30dffa62a69dfb2b64b3c1bd2bc3586e26d4eea714d2a7b71cf79fb8ffbf2aaad00ca3e4f2b6f503cc1fef2eab3656fb44f8d62a8db8ab58f394693949eea57fafecf005f6ebf1287dba4d2d623c02ea171f567e526add20709ebcab962f83d98ef668ebd01ef20488b3665e3a446fbfb13d34050942c749bb2dffc766367fd452e68e5b0c6: +90b455c6bb9cec83e137357065339d030525d0ea7f5b923a2d5972c3c12aa37b5cef038c16bfa4b4c923a0fe70cd7f25c8bc837fdf5a7efb9d95f21b96be925a:5cef038c16bfa4b4c923a0fe70cd7f25c8bc837fdf5a7efb9d95f21b96be925a:c62cfdb9d21eee6be47f30727aaee51f0703789a431d32228533350217a93a18900669c95956f3f2ae90dc745a71e18340d058d16b4c6fe33b64af8dad973fe5dc02e8520705c7a8bb3ccbe1838c6c249337f9b6a4c0e1f8a4e5d103196fa79998923d0422e9d079a72cc2a8f86d659031a607d4cca0b947b3abeeeef64c28da420d05de665a5510fe55f77598ecad7faa0ac284800b53829394c4ae90be66678ff04ab46da265ae06402d8c83cad84d61a051de0260559888e779f74b72a5d71c132f:c9345eec2c4a0aec732386494a69a3fce8b8a1be366bbed1659f131fe97cc037fb1b7c1b68b0f3023945d20090a0cd2c1553a47faec4d66fd816ce121168f309c62cfdb9d21eee6be47f30727aaee51f0703789a431d32228533350217a93a18900669c95956f3f2ae90dc745a71e18340d058d16b4c6fe33b64af8dad973fe5dc02e8520705c7a8bb3ccbe1838c6c249337f9b6a4c0e1f8a4e5d103196fa79998923d0422e9d079a72cc2a8f86d659031a607d4cca0b947b3abeeeef64c28da420d05de665a5510fe55f77598ecad7faa0ac284800b53829394c4ae90be66678ff04ab46da265ae06402d8c83cad84d61a051de0260559888e779f74b72a5d71c132f: +dc185c2ba0b378dfe5dda510c32feff535ca2e8a02434b326e0158bc878e884833d6cc05a434e419280d5864a1af209a2c676814b70f72f8141ac7e0573ee63e:33d6cc05a434e419280d5864a1af209a2c676814b70f72f8141ac7e0573ee63e:e276b11912cca5a84bba650c172aef3a4d5f91ac722913bb891a3ab0424ab07ea709cb8bba3a3d11f82f51c2af0162a82f7219ce27b35a30507d536a930817e40f85a22a5a432b94d192c3c8911777cfdb7fe937a67502770d6d75753d3ae88229e08f1ed23b4328d862ac61863c063ea9848f8ab96a0213d7b936c48fe754836c98487859d199b3d940392716a1d569e6c0cb1ba918932cf88525e256c8abb11aaf0b454655d5db55713cebba287ae202651ac872bfc80feaa7e00d47c0be38e658f7c5:f1e44514d2ecbcc8d1a7e84bf584ce731835e9894f88974f098d456b60718f575ef4d8062f2182504250cf83bb2af2a79b1f58a6a97bd98da467132d7bec2f05e276b11912cca5a84bba650c172aef3a4d5f91ac722913bb891a3ab0424ab07ea709cb8bba3a3d11f82f51c2af0162a82f7219ce27b35a30507d536a930817e40f85a22a5a432b94d192c3c8911777cfdb7fe937a67502770d6d75753d3ae88229e08f1ed23b4328d862ac61863c063ea9848f8ab96a0213d7b936c48fe754836c98487859d199b3d940392716a1d569e6c0cb1ba918932cf88525e256c8abb11aaf0b454655d5db55713cebba287ae202651ac872bfc80feaa7e00d47c0be38e658f7c5: +90721c43bc366f24bf4e8c993e138024682f1029dba35abeb0d60c7fa710021c7c63a2f13b7b220a0bb752e3800753b8b6b32669378ce131bb77a9a8d230e9ae:7c63a2f13b7b220a0bb752e3800753b8b6b32669378ce131bb77a9a8d230e9ae:651c9617cac958c7edd4a5f3fedfb83dc971abfbb69a31e898cca8472ef068034a6d2376ee0e72d0a9bfee275796c3795adac8ebe1d12b66ec268f6b75fa3941154f99e223faf2cbab5b92e2b3ba7b79be7700ef9dba69253cce5356b0c4e74703cfcafdb5546850b46232675c90c02d5e426d33d60cebf0c7930182379dbb007f536163c8ddbbd3157bb2da62340133f00ae2682ec6baa6416b5a01521cc10e04695295f2e5b94c05f00383ffe954830797f6df823172532f98165fe314ab325929af8385:d2064a6d6c99c6c3f152d2d435f24e34b5459b082ef11e944a77ff54ddf9862737ecb2ac8d54207d36c51ad41f36490a111ba80e126bfecb09def6accbdf880e651c9617cac958c7edd4a5f3fedfb83dc971abfbb69a31e898cca8472ef068034a6d2376ee0e72d0a9bfee275796c3795adac8ebe1d12b66ec268f6b75fa3941154f99e223faf2cbab5b92e2b3ba7b79be7700ef9dba69253cce5356b0c4e74703cfcafdb5546850b46232675c90c02d5e426d33d60cebf0c7930182379dbb007f536163c8ddbbd3157bb2da62340133f00ae2682ec6baa6416b5a01521cc10e04695295f2e5b94c05f00383ffe954830797f6df823172532f98165fe314ab325929af8385: +9cec246758e412e7378b4579eafe9fac5a25d5405f9270b5d7e543414ec3d5da975a9e6a152caebb2f9dd0deb76dd922b6dc77055dda03fbae9e7c685d073aa1:975a9e6a152caebb2f9dd0deb76dd922b6dc77055dda03fbae9e7c685d073aa1:17ec9bd47add6ccfbd787af0d9013e9cc979aaf850e09426d3b28edfd71296eb31ff8b21c5fe7be050f536324c3ec48850e0b508a36bb4cb7e754b327183a1b394d88a7941d1ce8dac62a5d8291874d78485e51f29ed05865a206e52ecb12c5d107d4ff96f25d3c5d181d2c4ba6463600db1cca32857fcf597cbdfb2fda2708a8aba281b43c3d28c4a4e7983361509f61a1074e6f0ad6101c7b567ee4078e9839c47f46531b729ff0efeef7c9d1a8d833d9c0f42812a34187c3a778c165c09d6459c9c7ceaa2:9bad1e3b1279ef658f4d071644c63ae2b7a780357e9dc426f1650ec0634dfc520f8eda9dc8f10aa7324c5942d2347ff8802bd90e95fcec313352cdae64f32a0417ec9bd47add6ccfbd787af0d9013e9cc979aaf850e09426d3b28edfd71296eb31ff8b21c5fe7be050f536324c3ec48850e0b508a36bb4cb7e754b327183a1b394d88a7941d1ce8dac62a5d8291874d78485e51f29ed05865a206e52ecb12c5d107d4ff96f25d3c5d181d2c4ba6463600db1cca32857fcf597cbdfb2fda2708a8aba281b43c3d28c4a4e7983361509f61a1074e6f0ad6101c7b567ee4078e9839c47f46531b729ff0efeef7c9d1a8d833d9c0f42812a34187c3a778c165c09d6459c9c7ceaa2: +d1403f63202e080525843bde255eeb6b6783c1caae9d6ed00ba60805bed1941f238aea3ad6d6f27783e70516bbfcca4770366b50ed0fe6a4e966b53af121a721:238aea3ad6d6f27783e70516bbfcca4770366b50ed0fe6a4e966b53af121a721:c4f17d442fba4ca0df8dc1d0628d7d7f36b60b5758d7c13b80b8f97a62124d96a23b279565495a8accab5997115b13a4ba220a73957eb7930520acbbfb6f54cf68726b6450c6ffa9470b055ea262914e2bc612633f1ac3d0618a23dff188a733d76bcbcc460f52ab61e19938f9c8caaa792c208d1f6c754728905fda51d881a347a53da744d3baadc0a76c474c558680269095f9084a74471d5c09ffc29141b5bfaf4954dfacbca663d037b17ebf9559882233e5ca5a8bf75cca4fc9c5a4109f32e145f3853b17:8e60e73c063816795e29f5d64ece1159f1b5d5021a6f8f655e261a4d0026f5b94ff2923250499d995298480512e4126276aa4a226d015a95827b3ce692e23302c4f17d442fba4ca0df8dc1d0628d7d7f36b60b5758d7c13b80b8f97a62124d96a23b279565495a8accab5997115b13a4ba220a73957eb7930520acbbfb6f54cf68726b6450c6ffa9470b055ea262914e2bc612633f1ac3d0618a23dff188a733d76bcbcc460f52ab61e19938f9c8caaa792c208d1f6c754728905fda51d881a347a53da744d3baadc0a76c474c558680269095f9084a74471d5c09ffc29141b5bfaf4954dfacbca663d037b17ebf9559882233e5ca5a8bf75cca4fc9c5a4109f32e145f3853b17: +bdf6bdc31ab0b5313784483abeca6ea5e9cdc68f81b21f350d09c3907bb9b6a103627712b755e5069fb9ab8f9e899724029a7f268af9398821eeec9360c9285b:03627712b755e5069fb9ab8f9e899724029a7f268af9398821eeec9360c9285b:90a66aafa5642a98e79f0d88147080167b11e4466518f195cddd8940d12ee4918d31a6d4cb77d0bf5af29983bbe5085610a79daf0c75a78ccbcffbbdab2189c394ae24e265bd8c55fd3f4098e1b175577549518e7a4dcf7452086dd1278dd58ea4c0aa690e917951ef39fcff60cbfa1e90910bab5374928d4722f702bf5ad6028ffda6541fa5ba1a3779ec78b0a95fe3850c748b6c8f42f330ec79541a52a1cf57db72df4f92ce7f748aeef1af33bc5ae0a82c89dff216f23aec168a7dbb510aa632daabcc971b3f:38fac603ed246f833f1c0fd4585698b0a71305eff0d14a0049b3cef073bd036dd451b3dabadaaeaea2aeaf83d395746f4e86866ada971cbe482edb0419332f0e90a66aafa5642a98e79f0d88147080167b11e4466518f195cddd8940d12ee4918d31a6d4cb77d0bf5af29983bbe5085610a79daf0c75a78ccbcffbbdab2189c394ae24e265bd8c55fd3f4098e1b175577549518e7a4dcf7452086dd1278dd58ea4c0aa690e917951ef39fcff60cbfa1e90910bab5374928d4722f702bf5ad6028ffda6541fa5ba1a3779ec78b0a95fe3850c748b6c8f42f330ec79541a52a1cf57db72df4f92ce7f748aeef1af33bc5ae0a82c89dff216f23aec168a7dbb510aa632daabcc971b3f: +57b3b14ace1cd0cd603e6328bd219ee7d9d094487fa668f28aeec02b43c909a724e6b6395f97ea0e237186d469b71923d2113adf403beeeb4a2d27909aaf3eda:24e6b6395f97ea0e237186d469b71923d2113adf403beeeb4a2d27909aaf3eda:b2e0dedd802eed996dbd5836bf8688b0d1201bf5442ff9bbd351aeefe1a0c21fea2b5c9fe5edee47e921099b05aedaa80367c1ce08821d783a5b64cf059c0f4335083986a5a6ecff8c84fd40e0ba5dd5e5d2f01112a84ce5cf8e0db78beb182d9139c0b0f3e0060a3fa73869e96423f170df9af1cb9c35566d87dff542223f6d439bdb54729d366aff637b0f36a5d14b15d612bd03076cc4d04c1f25b3ba84e0d1fe474e5718d1a17d5a488465662ee4c3f664b4c9274b649d78cea4e85243f3713239048a908ce3e1:fc79fdc6d090887a61e43c6b9187b657d2e4d9cbafd6e7caeb7ebdea842825b78fb949d2c49a0cf38b6c73296d82c8ddeb1fe2d40aaddd7964da68acf8c66f0eb2e0dedd802eed996dbd5836bf8688b0d1201bf5442ff9bbd351aeefe1a0c21fea2b5c9fe5edee47e921099b05aedaa80367c1ce08821d783a5b64cf059c0f4335083986a5a6ecff8c84fd40e0ba5dd5e5d2f01112a84ce5cf8e0db78beb182d9139c0b0f3e0060a3fa73869e96423f170df9af1cb9c35566d87dff542223f6d439bdb54729d366aff637b0f36a5d14b15d612bd03076cc4d04c1f25b3ba84e0d1fe474e5718d1a17d5a488465662ee4c3f664b4c9274b649d78cea4e85243f3713239048a908ce3e1: +018a2c3deea50ab506751f9c2adaadfd9e2192121609931684eb265e193e7f89af410bdddefc644ef12c9899ff71b9e1d0dfa3d69d8c2cd676c1916b34591cfd:af410bdddefc644ef12c9899ff71b9e1d0dfa3d69d8c2cd676c1916b34591cfd:cf7813efac12ad1c7c7322ccbe54aa0e9a8ba4fd4345b06e4ce7a35c8b1cd5e3f7f0688533849ba2cf4c75b6f20926a1194a72df0e1b1b34456a2133112d006722fe811d5e40c4121159ded88990c0ac2bfd34f35af4f07cc402e9a381a675d03fec7ec438c4ad9d929aec8f242def023c993c9e8ba18c7428e88fde68a4711e506d7969f63c8e0bc83ff0de4e1336106c05e09d5922400e8a81bf54885667899785882b70f20dd8fb1e75f5855b765a256da4341bf23ea0ffa18aadda381816946001045669c8d04df0:7a44e6a31932dee6dc2d8394e29a6551d13e6c6ffdfa218fa5b998668d8439db5e05379fbfa0da5b563ed966435ae2c54e3ad16e1a9fca1f5a157a080704ab03cf7813efac12ad1c7c7322ccbe54aa0e9a8ba4fd4345b06e4ce7a35c8b1cd5e3f7f0688533849ba2cf4c75b6f20926a1194a72df0e1b1b34456a2133112d006722fe811d5e40c4121159ded88990c0ac2bfd34f35af4f07cc402e9a381a675d03fec7ec438c4ad9d929aec8f242def023c993c9e8ba18c7428e88fde68a4711e506d7969f63c8e0bc83ff0de4e1336106c05e09d5922400e8a81bf54885667899785882b70f20dd8fb1e75f5855b765a256da4341bf23ea0ffa18aadda381816946001045669c8d04df0: +bea445e9b6d3f21235912cd6c42ec0577297ca20a10357880c2b846dd8e2cc77024174966221699ea4b0a37e517ff9b16598ae4d4e83bfa3ca50bc616841f595:024174966221699ea4b0a37e517ff9b16598ae4d4e83bfa3ca50bc616841f595:4743c7c099ab815927b3674d0054b6de59af2811abc2cf7fde08f62929185adc238fadd5e75ae3ba0036ff565a79405b424f6552331e2789d9709ac1ecbd839aa1e91c854817597958cc4bd91d07377507c2c8d3c006cfeb6c0a6c5a50eee115e21153dd198ea0a3aff62b7075d5a461788783f050e659c572963d7a59e5afaa2b9c501f43c6ac08ab4797c4566d22b93cdf65a99a2a1d638e79f72b5f4631fe5e9e5f968f6db7a1880df51d8febc14942672f8ea6fc3a72814a44d66d148420a69000f68c330de5b80fc6:6964b9c5903e74e99328acef036558eecd3369150a52e2cbad4bbb97d461b3dfc6b3e8455813a4f4bdca46302e02e683ecea1820171c538e54c3de6c954aa4074743c7c099ab815927b3674d0054b6de59af2811abc2cf7fde08f62929185adc238fadd5e75ae3ba0036ff565a79405b424f6552331e2789d9709ac1ecbd839aa1e91c854817597958cc4bd91d07377507c2c8d3c006cfeb6c0a6c5a50eee115e21153dd198ea0a3aff62b7075d5a461788783f050e659c572963d7a59e5afaa2b9c501f43c6ac08ab4797c4566d22b93cdf65a99a2a1d638e79f72b5f4631fe5e9e5f968f6db7a1880df51d8febc14942672f8ea6fc3a72814a44d66d148420a69000f68c330de5b80fc6: +6447540ed7be0a11c2a8de793d83c6e244983db18d78ec9d75f1729c92e0fdf1391212c8edc4d334a5bec860ef0f5ebb5ec44e8bb51c0f6741998959b2b379fc:391212c8edc4d334a5bec860ef0f5ebb5ec44e8bb51c0f6741998959b2b379fc:a4381c7638c48799e9b5c43f67fc3aa3cbb5ec4234f37e70ccccced1627a57683d1e53f4e0883d8b462bf83f1308630368c89b491533ddb8c9a5b9e8155002fdd581a9a5be0e430b9086a6beac4720210f87b14e862d97e5cc69286786a7586723f231ef0e3e1b932dbba3a18a0cb221cb07f80e6a8e1300056c13e702b23bfb3250ec7cc864d5c7ec5786240709c56024ea6be5f7b15a4fa5555e39a744a1dc557df5b948db220b3d5745746691dacb4421641cdcc12e7ec0450293f19ec57b09cff135847aabe446a61332:3ab5f88e2f7276b5b6583dffba5639993a905dbf9b88ceeaaaae3335800e4a5f10f83da6d6225a8dbe99ae80075009dd508786b3975113db478e14ba101bee0fa4381c7638c48799e9b5c43f67fc3aa3cbb5ec4234f37e70ccccced1627a57683d1e53f4e0883d8b462bf83f1308630368c89b491533ddb8c9a5b9e8155002fdd581a9a5be0e430b9086a6beac4720210f87b14e862d97e5cc69286786a7586723f231ef0e3e1b932dbba3a18a0cb221cb07f80e6a8e1300056c13e702b23bfb3250ec7cc864d5c7ec5786240709c56024ea6be5f7b15a4fa5555e39a744a1dc557df5b948db220b3d5745746691dacb4421641cdcc12e7ec0450293f19ec57b09cff135847aabe446a61332: +0c587a811add88b994458c3c808ac4e3a83afab26d4cff5c961b9df0b5c8334406783b0cdcc5028c5638bd748f0bc76f7e94d1aa2015ca948738a3500460aca0:06783b0cdcc5028c5638bd748f0bc76f7e94d1aa2015ca948738a3500460aca0:f56dc6b76076325b2126ed11d1f09decef9d15c31d0e90cdb1a27e089cc56329f6ec3f665eb6739ec5678b3f37ee1fb37deb9e240092b7a88fd25525acd55e294eb1046f9b1b69a847eb9ceb7b1593b9f6978ef618c15de4e059ecc3bfda3297a19c2df202adf72155cf21eabd03948df15198e8a68b0884f93ad5e36eb0983cca30e45a8b4b5fb8136fdea8a3341dd7877540a557debf7530cc33aeeef6271c3f0af6d09787e815f2f1dd25ce4d2fd09ffa9f53081b469c500da4d44180c04eb1869329cbf2d823187e831c24:33b4f4274f20008a721d1e8d054a2b4e95327e38bb07b33c4bee7e1ce020a442fb2627eda3b7ac93cd3ab0b12b99935a1a9233111604da4acffb5315b907120bf56dc6b76076325b2126ed11d1f09decef9d15c31d0e90cdb1a27e089cc56329f6ec3f665eb6739ec5678b3f37ee1fb37deb9e240092b7a88fd25525acd55e294eb1046f9b1b69a847eb9ceb7b1593b9f6978ef618c15de4e059ecc3bfda3297a19c2df202adf72155cf21eabd03948df15198e8a68b0884f93ad5e36eb0983cca30e45a8b4b5fb8136fdea8a3341dd7877540a557debf7530cc33aeeef6271c3f0af6d09787e815f2f1dd25ce4d2fd09ffa9f53081b469c500da4d44180c04eb1869329cbf2d823187e831c24: +66cf401a2142fcf4a8018046cf4140bca18d76ef6266e7a024757df172a5d65367d48dfd23743cc2ca40e4dfd6b8cc5d84be82dd2b1120cc476e6af6f25ecc98:67d48dfd23743cc2ca40e4dfd6b8cc5d84be82dd2b1120cc476e6af6f25ecc98:daa8efb3fd41f12fbc55bd60464157a26d718632d882aedb6bf98e47dd2337879e0b46452e062e6dfbff3e7bca7289e4ef6b3f41d4b03bdc2c842afe97f3029883ed45f6054dde9690649abb2b8dc28f5fe8cecf80fc1ea411bfc40bbf4fd20b218cf47ea8ee118d4d5aefa5c1bfa08a8fb1b30d6de0977cd15e50292c501f2e71ce2740ff828b8432da5a594bab5223760b64792ed3a69dd75e2829234943656513df1a17a2a067a9a8eaa64e19569f46939d34b99271ae50a47d7dbca3620c81255b0e1fd1f3cec851f1b11b35:d6b0e80e60bc1b29ab8f74808fc460847795ccb887bac0ecaa8e135297a85097712b24b0a1fbaf7a67c5d530a47d0643fc8702c059d215fb112dbe475e5bca0ddaa8efb3fd41f12fbc55bd60464157a26d718632d882aedb6bf98e47dd2337879e0b46452e062e6dfbff3e7bca7289e4ef6b3f41d4b03bdc2c842afe97f3029883ed45f6054dde9690649abb2b8dc28f5fe8cecf80fc1ea411bfc40bbf4fd20b218cf47ea8ee118d4d5aefa5c1bfa08a8fb1b30d6de0977cd15e50292c501f2e71ce2740ff828b8432da5a594bab5223760b64792ed3a69dd75e2829234943656513df1a17a2a067a9a8eaa64e19569f46939d34b99271ae50a47d7dbca3620c81255b0e1fd1f3cec851f1b11b35: +5dbf885aa598e895571f5f65090b72323e9d70b0f58110687afbbc383afedcacfa17eba76e3bc3ea6dab3a5b120dc5ecb9ae6f00138f7d36dda9268bc4722174:fa17eba76e3bc3ea6dab3a5b120dc5ecb9ae6f00138f7d36dda9268bc4722174:1e0b6cf15ce03337179c02d65408df5be9200c3782b6004af94ea4decb257999d6fdff301d11d00c98c372fac0d026cb56dfefe3def7eb99ac68d6968e17124d8446f53e8d2d3dd890d37a23c7e0b83a484b3c93bddf6c118e0281959d27bd87d37e843d5785f4a40771398494e6c4322fbb675c1d479321032148f7fe52564ddf7ae7ac269d0cd2e552fec589aeae0fb93fe3eeaef0856096cf4f6b3497e7235cc8494d810a0b46c5eac87f187e505bb7764f8045c9541983f7b025698009a23d9df0bd1a473cbee4cf5e9488ecbc:e1429dab2e42cd035b7fc602efd6baf94706f16eaf2f8b5fed329239e875605fb172f5dd9ae2bc2eb42eb474567e292f5206e82e694bca0d6d433b867634cb0d1e0b6cf15ce03337179c02d65408df5be9200c3782b6004af94ea4decb257999d6fdff301d11d00c98c372fac0d026cb56dfefe3def7eb99ac68d6968e17124d8446f53e8d2d3dd890d37a23c7e0b83a484b3c93bddf6c118e0281959d27bd87d37e843d5785f4a40771398494e6c4322fbb675c1d479321032148f7fe52564ddf7ae7ac269d0cd2e552fec589aeae0fb93fe3eeaef0856096cf4f6b3497e7235cc8494d810a0b46c5eac87f187e505bb7764f8045c9541983f7b025698009a23d9df0bd1a473cbee4cf5e9488ecbc: +84b3aedd4797a565c351de7dfa0700b9ff7c4d7291c8808d8a8ae505cdd22590d7ad72caa7c22209ec4678d11d5590a6cb28a07117fe5aef57b50751583201a5:d7ad72caa7c22209ec4678d11d5590a6cb28a07117fe5aef57b50751583201a5:532567ffa53b5c0fcd29c39499d2e78ecd20e63123499240e775088b394dc65c8baaa0fe8f6aa7e70181f9e10add8b4a8beb0b2ec38a43309f100cd4be91c6f48e79dc0aee93a15c9403773b354a8d42ed48d8f276230fa6de5ada501ee0a653b4458f0ecf6d5b3c33e2141c662f6ea055f741e54586917d2e0c4eb2b56621f9665fef3246f0bd800b533e3bc615c4021f8d0e2ad233a11e7736c493acc31faee76a097dc40db9efc22446eacf1cc18f51fd10236a2f942d0a53c3ce209108b5938c0a9e536b89ef0ad6b405a10f22c3:9220f0edaaaee1b876350dbe9266061767b86296c351d4cac99d07cd612c6efb24f8f9b0b975f95c42c5b6afedc892f87efedd39d5160294c27658bdcf42850b532567ffa53b5c0fcd29c39499d2e78ecd20e63123499240e775088b394dc65c8baaa0fe8f6aa7e70181f9e10add8b4a8beb0b2ec38a43309f100cd4be91c6f48e79dc0aee93a15c9403773b354a8d42ed48d8f276230fa6de5ada501ee0a653b4458f0ecf6d5b3c33e2141c662f6ea055f741e54586917d2e0c4eb2b56621f9665fef3246f0bd800b533e3bc615c4021f8d0e2ad233a11e7736c493acc31faee76a097dc40db9efc22446eacf1cc18f51fd10236a2f942d0a53c3ce209108b5938c0a9e536b89ef0ad6b405a10f22c3: +6950bfcf480b98ea18a2d5ae5ba6e7668f4c283ff2711357740ffe32cf25819a8e4c6f233f7b86321c9d6799bac28aafcd2503d7aa0a7bded8722727fbbcaeb8:8e4c6f233f7b86321c9d6799bac28aafcd2503d7aa0a7bded8722727fbbcaeb8:a401b922aba57ee0c6ac1c8f1b48296a8562eef137526893886a08306e2203667788618b939864467a31f16edce152a42c25546b640ea8bed189a4f89886a37f106911eae1f50081bf795e70c6504437d2a80cb839479ecbb87c129bcc5fe31d716ef978c206d7f08a793466594f4d75e215bb6374596f8e7d00eea724780943e89bd3863c951bbd24efee23c97c2c797c7fafbf8f2c8b43f37a5f881129a09573fa7a034a285e80dc4ba4bc9564a4dcedeb33167e0b30c5a00b9a109a2231cfa0012b29b2b3450b892eccef0808e503f8:94de5df7a25ecd70205d40bc9499fc7cd7136568060a419a93be6e318664bb6dfce60e2d4e633f7ec148fe4f834ed277c1fec4c4e2a86f44c4589c817888db00a401b922aba57ee0c6ac1c8f1b48296a8562eef137526893886a08306e2203667788618b939864467a31f16edce152a42c25546b640ea8bed189a4f89886a37f106911eae1f50081bf795e70c6504437d2a80cb839479ecbb87c129bcc5fe31d716ef978c206d7f08a793466594f4d75e215bb6374596f8e7d00eea724780943e89bd3863c951bbd24efee23c97c2c797c7fafbf8f2c8b43f37a5f881129a09573fa7a034a285e80dc4ba4bc9564a4dcedeb33167e0b30c5a00b9a109a2231cfa0012b29b2b3450b892eccef0808e503f8: +61b260f5b848b271ef48e5a56d297432d89f2ab85bd538fa668870d0560220e56086fe8735f399f1af2e395e0fdfb5629ebcb04b6ed4a54a9e47052c6e8191d4:6086fe8735f399f1af2e395e0fdfb5629ebcb04b6ed4a54a9e47052c6e8191d4:2826295d79945f675476bc4d45ef800d80b1f0398e4be60e3de4571ed108df989f032de6c2345d9948d677927ea0b8cf1a5ca36fd5f23c25dc0d2ab5bd565a54af46fd97d338d770e3a7b47efb54c07a1664707771eb4e37d9d70ba779251dcdcd3bf6d1248adec53f787259c4d594d5fd4ced8e3db7621d4965d48298178124931a3d0cd269b2d53b7cd261b96d370c5d9693c8ad133ed58945ee3540e10625d924aeba9bdafc656100aab276fa996b1db477bf85ea559081d5b4c7307dc1595654aca82f7b6d2ddaf7357c15a4d7d8b908:9828fec8ff5cf85a98f450770b5bdb4b80daca44379d8f53c91c348e22df64ac48f2b6e2a7b3b642bc8193a194316229e69447ed241cd423d83b6fe7b2d44b002826295d79945f675476bc4d45ef800d80b1f0398e4be60e3de4571ed108df989f032de6c2345d9948d677927ea0b8cf1a5ca36fd5f23c25dc0d2ab5bd565a54af46fd97d338d770e3a7b47efb54c07a1664707771eb4e37d9d70ba779251dcdcd3bf6d1248adec53f787259c4d594d5fd4ced8e3db7621d4965d48298178124931a3d0cd269b2d53b7cd261b96d370c5d9693c8ad133ed58945ee3540e10625d924aeba9bdafc656100aab276fa996b1db477bf85ea559081d5b4c7307dc1595654aca82f7b6d2ddaf7357c15a4d7d8b908: +936dc1cef6a310747f350088055a39aa762d9a4b52c8c8e4c682794380c2725c03b31800412df4d56f1532c05828c0b72528a67a781bef4c06c1fb6ff2ce324b:03b31800412df4d56f1532c05828c0b72528a67a781bef4c06c1fb6ff2ce324b:eb58fe86c4ef349c29ae6fb04f10850e38c6823dbe64a09a5bf1e0ce600d394efa6fb96ed6a8f2c9d4bec05e6a5ebd5a1bf4d0c51db934e57b79e5c6a879d975197dbb10475f65c7f8a8c6a77a420384b5062a2740f1401740ee0f5e043aad7a2a2b4260c5d907f705edaf65b0e375dfc7b00bd660db6147f2ebe870a0ee18dc2ba3c92b0b76fae2b90932cdb6c149e46f3feecf4c26f0441f3a9e006678aecff8ccaecaeda73a18a68ac988b62e83a9bb5188aede38df77a9a164abbdd9d58e52a6caf7222389f198e85fbf966236dcdbd4c1:3f994b8ef528f6421c6a6a22e977ade5cee887263de38b719acd12d469bfd8c3f68e7ac07d2fae80a2092778df0b463537ad3a0551997a3d5b51f832d9c8230beb58fe86c4ef349c29ae6fb04f10850e38c6823dbe64a09a5bf1e0ce600d394efa6fb96ed6a8f2c9d4bec05e6a5ebd5a1bf4d0c51db934e57b79e5c6a879d975197dbb10475f65c7f8a8c6a77a420384b5062a2740f1401740ee0f5e043aad7a2a2b4260c5d907f705edaf65b0e375dfc7b00bd660db6147f2ebe870a0ee18dc2ba3c92b0b76fae2b90932cdb6c149e46f3feecf4c26f0441f3a9e006678aecff8ccaecaeda73a18a68ac988b62e83a9bb5188aede38df77a9a164abbdd9d58e52a6caf7222389f198e85fbf966236dcdbd4c1: +f89eed09dec551361fa46f375973d4fbfa5c5c12f1b5e5abf45cfa05ff31a3403e0efdca3919fa10d4a849cef1de428851bd08efd248594fd89cdeb9deee43b0:3e0efdca3919fa10d4a849cef1de428851bd08efd248594fd89cdeb9deee43b0:4cf9773da05fd322fc147be900ef5cf256c88afdad4b08c230dfc8981fb69f476f7d45ef7c9006bc10032ba53436ac22843e0d76289cf68f9818fa64031d4b40955059aa69110915889f5e22732a1343912581ab3b11a3bae7a471359508596575f888160beef966e5708f0e3147eacfcec1caa3ef240c5e0a14c186546c8eeb64658350b1affc0cfd2ac213af670afca7bbc9dddd28a465b586e69c388cd73478d68efb322bdf86d9213011e711b2b95fefa7bb9b5939761706aa7121024906420bddf1d8800a4338d938fa137cf27e9ffc51c6:897e6f2797c3f326d2cdb1d2673d360631f063304580ff5b4eb43d39ad6851834c9cf891d9f0905bf8de075f7635dfca601adc0f14e7b2c76f7571bfa468ed0c4cf9773da05fd322fc147be900ef5cf256c88afdad4b08c230dfc8981fb69f476f7d45ef7c9006bc10032ba53436ac22843e0d76289cf68f9818fa64031d4b40955059aa69110915889f5e22732a1343912581ab3b11a3bae7a471359508596575f888160beef966e5708f0e3147eacfcec1caa3ef240c5e0a14c186546c8eeb64658350b1affc0cfd2ac213af670afca7bbc9dddd28a465b586e69c388cd73478d68efb322bdf86d9213011e711b2b95fefa7bb9b5939761706aa7121024906420bddf1d8800a4338d938fa137cf27e9ffc51c6: +400796ef60c5cf4084dee1801c4a1975e482e70aef961cd42e2fd5a3fa1a0fbef47da38128f2d012cc5797571d479c83e7d8a3409802f9a7d976c27067cbbe43:f47da38128f2d012cc5797571d479c83e7d8a3409802f9a7d976c27067cbbe43:c473325e785b27df4471eefb9ebebd6461d570800181100ff36caf3c38f67c1921b157ec8e6126f955aebd90ea3fe5385f8042cd704b27cc1d6978c0e2a296695f5ef97b7c2e16ae4ff4d063c688d7f46e964e1f0a00503f357345977683d6e4c3423d56bdb6ce864b6987e085e83e70c7c1a14e0e413f592a72a71e017d505b64c24f1a1a6b813e064e6e0cf8bd4571d0ff2f267a6a13e0cd430463b6ca3b88f0cd40b0fb83d5bedf6f7d47e170e87d0a750093693eda232a6daf98125727b9588ecb894ae373bae3a445a106306469a4c2cd77ff:84d3aa3f361844396754d80d9fa05b8b2fa4abf3a0f36b639bee9cfb5c8530a3a9cc34677f92a913c41e800f2e8041f7666d07ed85f16a57d817b1241fc5ee04c473325e785b27df4471eefb9ebebd6461d570800181100ff36caf3c38f67c1921b157ec8e6126f955aebd90ea3fe5385f8042cd704b27cc1d6978c0e2a296695f5ef97b7c2e16ae4ff4d063c688d7f46e964e1f0a00503f357345977683d6e4c3423d56bdb6ce864b6987e085e83e70c7c1a14e0e413f592a72a71e017d505b64c24f1a1a6b813e064e6e0cf8bd4571d0ff2f267a6a13e0cd430463b6ca3b88f0cd40b0fb83d5bedf6f7d47e170e87d0a750093693eda232a6daf98125727b9588ecb894ae373bae3a445a106306469a4c2cd77ff: +6703a6232c5e2e65e0ab3b92e2aaf9f5fbd33fb46988047d6f4d0ff5387fa029047cffca8b7b11ac6eacc0eaa0c5b73c75b9c637956973af9d97b2dd5b605d6f:047cffca8b7b11ac6eacc0eaa0c5b73c75b9c637956973af9d97b2dd5b605d6f:a26b30a769197932a3a62854968d760151612366778dc994576a2e0e0355496b46200e506948a0d102b6651b2e7334ca6c6eaef8bca44b425970a0b37d6bde0da9d3c1b9f51cbb25bc335cd6fa928a74f2c0dc2c6e99d37a12863a474d4df43aad35415ffcaa24d8c29f914572ab2abec3892db49e679c5ea220c2f519a7d033ac1a2c5a467869e30eda3d2635ca863431473f958d552bdc5582352c290d0ce4fa9cfd0ad42799c227ec90b7c9e5db9f5a7b6d569212eed94d323326805f2b3a0010d6c11eb4107c8283037652f50dc067b6dc81f4db:cae96879e5b603be866609d4a053bfa12a51378e99b2a2812e4789267d8f32f473243f8af74b9be73f47dea50f0d165ebf49458b73e53d88580c191a182d1904a26b30a769197932a3a62854968d760151612366778dc994576a2e0e0355496b46200e506948a0d102b6651b2e7334ca6c6eaef8bca44b425970a0b37d6bde0da9d3c1b9f51cbb25bc335cd6fa928a74f2c0dc2c6e99d37a12863a474d4df43aad35415ffcaa24d8c29f914572ab2abec3892db49e679c5ea220c2f519a7d033ac1a2c5a467869e30eda3d2635ca863431473f958d552bdc5582352c290d0ce4fa9cfd0ad42799c227ec90b7c9e5db9f5a7b6d569212eed94d323326805f2b3a0010d6c11eb4107c8283037652f50dc067b6dc81f4db: +e0e72f8f178633626733bcbda2ad2a50e653890f15359b6c22fc7345ad333109d13cee540d84b5667d516fe7ec7239bf8da91546ee791f84edd8ffcf3a083e76:d13cee540d84b5667d516fe7ec7239bf8da91546ee791f84edd8ffcf3a083e76:791fd613c1095292c8a4a2c86b47ae026155b8465b607dbb416477ef79a297c9d7758ce34af9dcbf1c68474f30909fbe74b7ba429632f2403aad832b486b72c23054ad42f7653a9ddb456cc791f348886a7ae5dcec7c0ba815f7a93a10fe331e903b970f7b5028be49d14bc5620d63792672b98b9488c67ae16646693e112047f0ac8921ff561c92dd0596d32df0a6e507ac1b07de516c98428d570a37db9bcd7c7e61c6948ab3fe91250dd1d5bd671275df9a972f22c2ba36804747aec1ea2416c1f41ab87befde31629b2d43317ce41cda03626286c0:14552171b95245ac0f0e5a6e7a2f541721068db650c6dada04c28cab7c49195f6436712144cb31913c562e30c39d8a8549fb64ffea81c7445143b5f23286da05791fd613c1095292c8a4a2c86b47ae026155b8465b607dbb416477ef79a297c9d7758ce34af9dcbf1c68474f30909fbe74b7ba429632f2403aad832b486b72c23054ad42f7653a9ddb456cc791f348886a7ae5dcec7c0ba815f7a93a10fe331e903b970f7b5028be49d14bc5620d63792672b98b9488c67ae16646693e112047f0ac8921ff561c92dd0596d32df0a6e507ac1b07de516c98428d570a37db9bcd7c7e61c6948ab3fe91250dd1d5bd671275df9a972f22c2ba36804747aec1ea2416c1f41ab87befde31629b2d43317ce41cda03626286c0: +544dafd9960d829756c6d4b3eadd44375fe78051876bf978a381b0decaaa8096ae4f6425c1b67ccb77f9aacfea28eaef769c8cacee035205cdcd787e8d07629d:ae4f6425c1b67ccb77f9aacfea28eaef769c8cacee035205cdcd787e8d07629d:447fe7344cad1fae09d6a7d05f09d503c1b3d3d5dfa584810c35bc41e4955693706154e2d751b2f1b525e1a14547ba7f8b232088a6fc922702d93a11cd82949c27bed645dc351fb4c1242cf41d01575412e792aed214531d94fd66e03dd32e972fd77f6947a353e1ae5e00f5a6ca77992472f096b6e7475fe534e913a77bcb0d681fdfb3a7a0dcb56d274df4aa109d4a8a37794a9276f50006696ff12ca4d0254039df0fb3f72a960da05c9872f2e33ee81d1cf7a6f48bbce0aa18c7c0f06ba55e67689e0af587b500eab79cc7f9640bca104b7fbf31f08e:a2ae117c8de4ca6d6fe75e466023bd550c26fedd3e74ca13adb625f272e175f14d5df550ace7d82288efefabf96311a123bee23889ad3711bff2b8087946bf0e447fe7344cad1fae09d6a7d05f09d503c1b3d3d5dfa584810c35bc41e4955693706154e2d751b2f1b525e1a14547ba7f8b232088a6fc922702d93a11cd82949c27bed645dc351fb4c1242cf41d01575412e792aed214531d94fd66e03dd32e972fd77f6947a353e1ae5e00f5a6ca77992472f096b6e7475fe534e913a77bcb0d681fdfb3a7a0dcb56d274df4aa109d4a8a37794a9276f50006696ff12ca4d0254039df0fb3f72a960da05c9872f2e33ee81d1cf7a6f48bbce0aa18c7c0f06ba55e67689e0af587b500eab79cc7f9640bca104b7fbf31f08e: +bfbcd867027a199978d53e359d70318fc78c7cc7bb5c7996ba797c8554f3f0f07c5ae3bab9201199dfbe74b7d1ec157125bdbaa4520f501da3f248579dc6c22d:7c5ae3bab9201199dfbe74b7d1ec157125bdbaa4520f501da3f248579dc6c22d:117fae13e78777b6219f020214c1b87c57046d1c09ce82ee2b5629898d9b0de74a15cfe99f80548ba913d7036c56285a4cba493b52d2cb70d6365ace3da12b1f34a2778af36ef52ab82ede04cacaf2793f5f89831e3b205a9ee4c1d6fbdab4ba4d9fae65dd79a5fe76b4b39a3092cc7148d211e85ee82ab463d34dcee9061d9c21ded2051bbd50b413f0e21a0e48d1ffa8dcae240b3495be25d93151b57aa271ab99aa708ca28080cab4804fcefa929f5f1ef3f4c6c0fbfb40bef7ea1b509b36ba1260323512379d7bc3fdbb5d3faac9b00e21f12ea1ca2e29:e48615b65633e61993b0aaa1fafb74b9629c384fd592bd735fa1f62c5cad11291fcd8c2e91a50bfe0b03b43502fff3a5c382b9c2821907efc34da5ba054af00e117fae13e78777b6219f020214c1b87c57046d1c09ce82ee2b5629898d9b0de74a15cfe99f80548ba913d7036c56285a4cba493b52d2cb70d6365ace3da12b1f34a2778af36ef52ab82ede04cacaf2793f5f89831e3b205a9ee4c1d6fbdab4ba4d9fae65dd79a5fe76b4b39a3092cc7148d211e85ee82ab463d34dcee9061d9c21ded2051bbd50b413f0e21a0e48d1ffa8dcae240b3495be25d93151b57aa271ab99aa708ca28080cab4804fcefa929f5f1ef3f4c6c0fbfb40bef7ea1b509b36ba1260323512379d7bc3fdbb5d3faac9b00e21f12ea1ca2e29: +df2df8a9d66d5638cdee09324e7b10f8ed29ab91387e3147b7dc03f7cd8005085c042e157fb7fb12d4d4fef2847141ecfb57c1253e14eaf3004d6513f52fe625:5c042e157fb7fb12d4d4fef2847141ecfb57c1253e14eaf3004d6513f52fe625:21576615c9346a63dccf0c50ecbd7c6d72ad452cfed43ea73202cc7a98576056b9664b54622905a1e7221720730ac685d3bd3977ec3959d446bfa941e725b6fe16afe5432c4b4bdee7aa0fd8030948ed6fcba7c0bdb40c2e517da97456e74e1f93d5ed676de0f4a8b0aea449404bd15b6da79dc1b813965fe5572410d76f5b5eac663050570311dc9842b6fbf8806aec03151715cacf7f21802e8bf5e98a89c0d7d0d098b73c6efc09962e36b4e030c1a64b5d349f5f2042c74428671e4a2c7fea0caee2422d85c4fcddfed32213859a69955d4e3ebb7e1b2022:9a1074531ed43d07bffc7f2b6c13b8838fc75cba02c7d1ec7ba38bca3cef20dc9badf3a3064a2c93b1842441420b6a8d421a960d70dfb7c70eec295f21f83f0a21576615c9346a63dccf0c50ecbd7c6d72ad452cfed43ea73202cc7a98576056b9664b54622905a1e7221720730ac685d3bd3977ec3959d446bfa941e725b6fe16afe5432c4b4bdee7aa0fd8030948ed6fcba7c0bdb40c2e517da97456e74e1f93d5ed676de0f4a8b0aea449404bd15b6da79dc1b813965fe5572410d76f5b5eac663050570311dc9842b6fbf8806aec03151715cacf7f21802e8bf5e98a89c0d7d0d098b73c6efc09962e36b4e030c1a64b5d349f5f2042c74428671e4a2c7fea0caee2422d85c4fcddfed32213859a69955d4e3ebb7e1b2022: +e8ee065f9907f1efa2daecb23a0425f353094da02bc2c931f0a587efc0d13de1c72651b7fb7ac0337a172977496fd7f2a72aea889385835e563c6b6053a32dc1:c72651b7fb7ac0337a172977496fd7f2a72aea889385835e563c6b6053a32dc1:a2f0c1373473a305d8f1d99138b06b9a9694ffaa8a88222de9f729bee1305175dfb17001cc77f67b6d40c90c1a28fb226c11286db4a13e45e69211242bcdd01cb6e2c454e76c0cab881b4d2d9d3ab100a5d61d1725d866e4fdb66d93d77f5b308693b9b5a333e57fa25d1e5d2e38df6e4e9ec84159bbee1ffea926836a0101c91483bd5bc88a6f1cc4d4e7f008ad08453a0123429dd335781c7cbf8d685a8999ed1177607004a13c4cb5ea4908c542607d3f2cd6690cf1f2a7455bbd38f538f07a103964317efbcee37eb46931c027cf153ef86e43d78281ebd710:a510dff42d4559a19a7bf0fe0bea53d3e1f22dfa6be55039895e12a5d07da5f2e37713ccb2eb216011628f6983f871fee286e66fff4be7582c961a1ed7568404a2f0c1373473a305d8f1d99138b06b9a9694ffaa8a88222de9f729bee1305175dfb17001cc77f67b6d40c90c1a28fb226c11286db4a13e45e69211242bcdd01cb6e2c454e76c0cab881b4d2d9d3ab100a5d61d1725d866e4fdb66d93d77f5b308693b9b5a333e57fa25d1e5d2e38df6e4e9ec84159bbee1ffea926836a0101c91483bd5bc88a6f1cc4d4e7f008ad08453a0123429dd335781c7cbf8d685a8999ed1177607004a13c4cb5ea4908c542607d3f2cd6690cf1f2a7455bbd38f538f07a103964317efbcee37eb46931c027cf153ef86e43d78281ebd710: +c72e67d8c3fec004ff618718a9099eb8ad7b06ff3b8c542a7e8b9847313475e14eb002d3cceb188c6658fec51cb479a65264ac555c75cdc2249cf1ce3defc16d:4eb002d3cceb188c6658fec51cb479a65264ac555c75cdc2249cf1ce3defc16d:a8f34135c0132ec95b64b0cbf51d66900143370406791fbb55f2b8ca953cc74a46e08b002fa2da21b951b8871f7a29bc6d38790afc66a329c397d9f9250bae0e30ae3426e08d8ead0179a3b313c908839192f289a3f3b6e960b4c5cebef0a09daa9c7a15c19d4ebc6fc2ac3cd02232e832b234edd7965d687bfeb758f70fa7963841b7859bb97c971bd557bc8769524ac4c6eeb3579793334b522d176bc62f86b4d5c0d4017036d2b6bd4e4384416ef8263139691a8606170d73c93d6417dcc1a08a537c9ed4400471a46f52907b46b10a8b6889dbb4647a8bbc7149:2d7bab8ebda7fca5bb3c25f51dc51b73e6ff6a3bb1b52acc7811a7d2595cd6fdaf730494418e2f57efdc5617b066fd7b6207680d94fb8c43d3d4740b41cb6901a8f34135c0132ec95b64b0cbf51d66900143370406791fbb55f2b8ca953cc74a46e08b002fa2da21b951b8871f7a29bc6d38790afc66a329c397d9f9250bae0e30ae3426e08d8ead0179a3b313c908839192f289a3f3b6e960b4c5cebef0a09daa9c7a15c19d4ebc6fc2ac3cd02232e832b234edd7965d687bfeb758f70fa7963841b7859bb97c971bd557bc8769524ac4c6eeb3579793334b522d176bc62f86b4d5c0d4017036d2b6bd4e4384416ef8263139691a8606170d73c93d6417dcc1a08a537c9ed4400471a46f52907b46b10a8b6889dbb4647a8bbc7149: +696450b557ec3c94cf1af1326475634aa81def3814ff30a02ba7f2044b59c0fe8584773c566b0eed3f43281705b575a434e47d6cf6b251b89803fef53534cb29:8584773c566b0eed3f43281705b575a434e47d6cf6b251b89803fef53534cb29:cc257829f30a5f90dfdbc247d42e388738b76c41ef8a82a5e0225ddf1e386d77080b3b9df86c54b85cdf2c32f367aba0c3b6bf888a5a6903529b6aeb4d5407a10180149114130228fc4356ccf366b77be89796a9e71a0c693f31e584a4f143097ba370363b67b2f2e2fd8d6fe8b4e8dbf0d7dcc1a8360041158aa2aff7e2a325b8e518f193a28bae05e3d52b26621af402026d7f250e86dcee301a58b631eadf4527e958f02a61587f0bb516cefac009fe51052fff53336dbd94e7266d3b43caba8a1b38e5d871c2a24a4c412fff3f7a9a52a8ab23bac9791b2b5a669a:ce8b0a5779f4f5f401e84d65927a0c28df829e95d09bfa97111b8700078ff894cf7277e34a716144d55306fc9e2f64cd287583cc8003be0e8faf26af7640140ecc257829f30a5f90dfdbc247d42e388738b76c41ef8a82a5e0225ddf1e386d77080b3b9df86c54b85cdf2c32f367aba0c3b6bf888a5a6903529b6aeb4d5407a10180149114130228fc4356ccf366b77be89796a9e71a0c693f31e584a4f143097ba370363b67b2f2e2fd8d6fe8b4e8dbf0d7dcc1a8360041158aa2aff7e2a325b8e518f193a28bae05e3d52b26621af402026d7f250e86dcee301a58b631eadf4527e958f02a61587f0bb516cefac009fe51052fff53336dbd94e7266d3b43caba8a1b38e5d871c2a24a4c412fff3f7a9a52a8ab23bac9791b2b5a669a: +a8dd35f054fb6ff6f0ab094a0d3d1c262832181df35ccd5192545ebd6a9cf529ca412338d3814b886d964b71925e1aabb3ffd07834dbe7dc512568882b53e4a3:ca412338d3814b886d964b71925e1aabb3ffd07834dbe7dc512568882b53e4a3:55a7ad9132d63ac161e7adb132b9189fdd84c361c1e4f5419a6df73df4d7aeb29a8dc4bf01490d4f484e2d12077517f5fc7ad0bdeda20a6cb0227942290b08c3fe33ab9b2135bc38a6579a54bd982f7d1417ce867117aea918dbd3dd476e7eb5b5d3c3e48a864a2f942a31501aa2b29b53b80513c95d6a411844f0dedf16a29ac267d331e53bdc2539bfcf32dc9b5d640f1231e2cafb0ae94bb5189426863364262efb47b5b5ccdbbc93324216a799b6f50d3704f15ed59af6cc7d910cf062d1be632dca5df213d487d8564f2b2bd7d818bba27c364013d92d7f72625462:fa709fbc8382af83d11812618dfaca452eab83e4c53fe9e5858467d07b6767e17975c1e06393d6dde15a34d9473d1cf4d6d8c2d57394520080fac4e43448be0755a7ad9132d63ac161e7adb132b9189fdd84c361c1e4f5419a6df73df4d7aeb29a8dc4bf01490d4f484e2d12077517f5fc7ad0bdeda20a6cb0227942290b08c3fe33ab9b2135bc38a6579a54bd982f7d1417ce867117aea918dbd3dd476e7eb5b5d3c3e48a864a2f942a31501aa2b29b53b80513c95d6a411844f0dedf16a29ac267d331e53bdc2539bfcf32dc9b5d640f1231e2cafb0ae94bb5189426863364262efb47b5b5ccdbbc93324216a799b6f50d3704f15ed59af6cc7d910cf062d1be632dca5df213d487d8564f2b2bd7d818bba27c364013d92d7f72625462: +ae1d2c6b171be24c2e413d364dcda97fa476aaf9123d3366b0be03a142fe6e7dd437f57542c681dd543487408ec7a44bd42a5fd545ce2f4c8297d67bb0b3aa7b:d437f57542c681dd543487408ec7a44bd42a5fd545ce2f4c8297d67bb0b3aa7b:9e6c2fc76e30f17cd8b498845da44f22d55bec150c6130b411c6339d14b39969ab1033be687569a991a06f70b2a8a6931a777b0e4be6723cd75e5aa7532813ef50b3d37271640fa2fb287c0355257641ea935c851c0b6ac68be72c88dfc5856fb53543fb377b0dbf64808afcc4274aa456855ad28f61267a419bc72166b9ca73cd3bb79bf7dd259baa75911440974b68e8ba95a78cbbe1cb6ad807a33a1cce2f406ff7bcbd058b44a311b38ab4d4e61416c4a74d883d6a6a794abd9cf1c039028bf1b20e3d4990aae86f32bf06cd8349a7a884cce0165e36a0640e987b9d51:909008f3fcfff43988aee1314b15b1822caaa8dab120bd452af494e08335b44a94c313c4b145eadd5166eaac034e29b7e6ac7941d5961fc49d260e1c4820b00e9e6c2fc76e30f17cd8b498845da44f22d55bec150c6130b411c6339d14b39969ab1033be687569a991a06f70b2a8a6931a777b0e4be6723cd75e5aa7532813ef50b3d37271640fa2fb287c0355257641ea935c851c0b6ac68be72c88dfc5856fb53543fb377b0dbf64808afcc4274aa456855ad28f61267a419bc72166b9ca73cd3bb79bf7dd259baa75911440974b68e8ba95a78cbbe1cb6ad807a33a1cce2f406ff7bcbd058b44a311b38ab4d4e61416c4a74d883d6a6a794abd9cf1c039028bf1b20e3d4990aae86f32bf06cd8349a7a884cce0165e36a0640e987b9d51: +0265a7944baccfebf417b87ae1e6df2ff2a544ffb58225a08e092be03f02609763d327615ea0139be0740b618aff1acfa818d4b0c2cfeaf0da93cdd5245fb5a9:63d327615ea0139be0740b618aff1acfa818d4b0c2cfeaf0da93cdd5245fb5a9:874ed712a2c41c26a2d9527c55233fde0a4ffb86af8e8a1dd0a820502c5a26932bf87ee0de72a8874ef2eebf83384d443f7a5f46a1233b4fb514a2469981824894f325bf86aa0fe1217153d40f3556c43a8ea9269444e149fb70e9415ae0766c565d93d1d6368f9a23a0ad76f9a09dbf79634aa97178677734d04ef1a5b3f87ce1ee9fc5a9ac4e7a72c9d7d31ec89e28a845d2e1103c15d6410ce3c723b0cc2209f698aa9fa288bbbecfd9e5f89cdcb09d3c215feb47a58b71ea70e2abead67f1b08ea6f561fb93ef05232eedabfc1c7702ab039bc465cf57e207f1093fc8208:b6c445b7eddca5935c61708d44ea5906bd19cc54224eae3c8e46ce99f5cbbd341f26623938f5fe04070b1b02e71fbb7c78a90c0dda66cb143fab02e6a0bae306874ed712a2c41c26a2d9527c55233fde0a4ffb86af8e8a1dd0a820502c5a26932bf87ee0de72a8874ef2eebf83384d443f7a5f46a1233b4fb514a2469981824894f325bf86aa0fe1217153d40f3556c43a8ea9269444e149fb70e9415ae0766c565d93d1d6368f9a23a0ad76f9a09dbf79634aa97178677734d04ef1a5b3f87ce1ee9fc5a9ac4e7a72c9d7d31ec89e28a845d2e1103c15d6410ce3c723b0cc2209f698aa9fa288bbbecfd9e5f89cdcb09d3c215feb47a58b71ea70e2abead67f1b08ea6f561fb93ef05232eedabfc1c7702ab039bc465cf57e207f1093fc8208: +6bce4dfd53bfa5506f2f554d2d994a0dc40cafcdec7e1be050006e5c5a4b38a1c890023728d8397070291771e65e034d34d4aae5e247653e4ff4c074591da702:c890023728d8397070291771e65e034d34d4aae5e247653e4ff4c074591da702:3239190747ee33d40bf870ac9ad49d88ee320f63c05257e8ab2c60306597ce76d1f1e792ab6a65caa544fbec20892fd4960594f31b3763ef07d4982eae4a2dbf3377dcc1e3f95e46ed39b7f0222f04bb5c3b434c8f9f310de9f122a29f8241e81e206549ae628d2b8ad768972c98847c1188ad04c835356378bef79cd126869405b129fdbdc3bc489cbd1399505dadef7617b5be5da173d3e80e5838c99e349276242729e0219bd7476ae5c4f81a12878fb483a6c0e9b0df2962eb0bf00157782cf768a1b71c010169ee8522def0024ad7e45775a290639c53aaf48198c42de75c:99ae6782ff27646c27f61e23636ae1881521cfa5ed256f70bce7ce00b68280ce8e0c82aa765afb8b5a1ff2fe42c57441e458e443dc8b123477ae33d884888c0b3239190747ee33d40bf870ac9ad49d88ee320f63c05257e8ab2c60306597ce76d1f1e792ab6a65caa544fbec20892fd4960594f31b3763ef07d4982eae4a2dbf3377dcc1e3f95e46ed39b7f0222f04bb5c3b434c8f9f310de9f122a29f8241e81e206549ae628d2b8ad768972c98847c1188ad04c835356378bef79cd126869405b129fdbdc3bc489cbd1399505dadef7617b5be5da173d3e80e5838c99e349276242729e0219bd7476ae5c4f81a12878fb483a6c0e9b0df2962eb0bf00157782cf768a1b71c010169ee8522def0024ad7e45775a290639c53aaf48198c42de75c: +17861a8d4154acd4fa9c8fc947c1886c11290be222872ff4f8cd25939e4d136143773f4449065eaebaf8937baf758560b0c4d2de46977839b3b873d5d7d5fd8f:43773f4449065eaebaf8937baf758560b0c4d2de46977839b3b873d5d7d5fd8f:184df5ea3215ebe180390b0ff042ba2381155a038dc732f76a01c7e70f82d1ccc9de9a0596b3fee447209c992684f643df21f4cf9d179262790e8623e42472dc351997e6da189c07e1e8882c07f86c6337ec0113912cf92215c8de1982b8fc57bfabc55a3e8736f73610429d97feb51d794f505d0c5a0b3abd48ef7f55a628f90b8567a1c15ea9d190d7bf4ec2bc9334ada6cb92808dfc2064836fcfa46b96fd7a5d6f4b054dab09b73595feb89ed005b9ec9d3188121de69696d64e7c7bbdfc1c469faf148c38a7785970afe1acd06a92c99478fe44974e3bb2095e4467e9b2e996:a5ee024ccdbdd4c21a24709ec53dccb7ee17626dd00a093d0884f5b45c4c9d1691840151c33c8aa07b69b34e16f61647ebe793ae4daa70cff48e6ab42ffdbc00184df5ea3215ebe180390b0ff042ba2381155a038dc732f76a01c7e70f82d1ccc9de9a0596b3fee447209c992684f643df21f4cf9d179262790e8623e42472dc351997e6da189c07e1e8882c07f86c6337ec0113912cf92215c8de1982b8fc57bfabc55a3e8736f73610429d97feb51d794f505d0c5a0b3abd48ef7f55a628f90b8567a1c15ea9d190d7bf4ec2bc9334ada6cb92808dfc2064836fcfa46b96fd7a5d6f4b054dab09b73595feb89ed005b9ec9d3188121de69696d64e7c7bbdfc1c469faf148c38a7785970afe1acd06a92c99478fe44974e3bb2095e4467e9b2e996: +0a84baa54f11cf17090fec61f3f9401508a3a03887aca1a7939394b1ee40a925309a73c62d23d740f2e93c18587ac15e7ec480d25ac0794e10f8cd461cc2b130:309a73c62d23d740f2e93c18587ac15e7ec480d25ac0794e10f8cd461cc2b130:fe70017b14678b0d3ad03e183d6f53314378379ab3da65b3511257b3d54086e86f2031139021391af9d72085ff7c3dc8c1e2d91e53333855423d0f785e2cc5f8b7799fcf1b70e6becb788e53e9020f2995ddb0c383a1f81038fc3d543ce0a38c9c288a9bc4077f4277dcc6c5642263fcfe19688005a603f57675d2434f3ed1f46d32f14eaeb073e83ee7086da2fb67659d3fb68c62320b7727b3b8ea006576bc2c7e6b5f1ecefa8b92e70c92c88951d0c12d91de801c38b7ca5a0a04b4c3429aba86386e96e06afd20d4c5c2fe2b9b4273eb05201a79273abdbeb37ed1830d226b6bdb:4d870bd53af8f13f214d9934ec903ac48284092cd9b162a44ccec851fa942de715ccda07b7991d712723e7a4d5b4f0374ab85ac3867e0b53ebc46b530f9fed05fe70017b14678b0d3ad03e183d6f53314378379ab3da65b3511257b3d54086e86f2031139021391af9d72085ff7c3dc8c1e2d91e53333855423d0f785e2cc5f8b7799fcf1b70e6becb788e53e9020f2995ddb0c383a1f81038fc3d543ce0a38c9c288a9bc4077f4277dcc6c5642263fcfe19688005a603f57675d2434f3ed1f46d32f14eaeb073e83ee7086da2fb67659d3fb68c62320b7727b3b8ea006576bc2c7e6b5f1ecefa8b92e70c92c88951d0c12d91de801c38b7ca5a0a04b4c3429aba86386e96e06afd20d4c5c2fe2b9b4273eb05201a79273abdbeb37ed1830d226b6bdb: +38379423dafdbf25e19d7231bddd80b4cefcfe2aed932584dfa0cc3c9f9232de597e81dcee9448b77de6829e7921c8a390535d89a0849430aed66364ee140d8b:597e81dcee9448b77de6829e7921c8a390535d89a0849430aed66364ee140d8b:36125ca66668802906237e63a2fe5ae610f11a7cf92520d19e6690a3adfafd5d07a784bc1a0e185273d11d340d5eff901597dedf450c4699d43f3fb168d557f6c9c03077c3cdc370d34832ccdf2a8e3d75796490ed0242899d25ddf44bfc66f329cf4c45168703c31bc9202d890f3969ffd3ac35a12818dca751ceb8808fe81efa26a5e0d200c5ec1d94a5097ea74b6498fe288f30c48d727e9d3d35c8e12d85420702556f2861484ffd09b4f12265cc9abafeb82cf590028895a7d050ff57ccf5f28022d016ab4094b062e48b66fd36d1e19626e5215efa40fb7e3b7062f81e954830c9:d8b50a88aed6f2a96d082213adf8b2519f6a0bbd30dd3cb0f3fd3ce1c643fc029946cd43462ed22513f1d65fca24bde3818166baa86daa798792afafe0c1a10a36125ca66668802906237e63a2fe5ae610f11a7cf92520d19e6690a3adfafd5d07a784bc1a0e185273d11d340d5eff901597dedf450c4699d43f3fb168d557f6c9c03077c3cdc370d34832ccdf2a8e3d75796490ed0242899d25ddf44bfc66f329cf4c45168703c31bc9202d890f3969ffd3ac35a12818dca751ceb8808fe81efa26a5e0d200c5ec1d94a5097ea74b6498fe288f30c48d727e9d3d35c8e12d85420702556f2861484ffd09b4f12265cc9abafeb82cf590028895a7d050ff57ccf5f28022d016ab4094b062e48b66fd36d1e19626e5215efa40fb7e3b7062f81e954830c9: +f925d274aaf1fe1a21656237385e97f7783e78090c5d4217fece7057c80f426d3b0fc370be3a4b19a88ab998c59504ffb59a87606338e673df5b3fab4d9bfb8d:3b0fc370be3a4b19a88ab998c59504ffb59a87606338e673df5b3fab4d9bfb8d:143caafa5f62b13e43dffa49d420fa99f771b1926d40d6cb2bbb427f27b6c266eb3deb2d8bbbd47b8214ad40251cb1907ad65eb94193e54ad85c6700b4189e80f1cc0154c63ed151a8bbbd30e01637ca58e70aa3ee52ef75d0873078a405014f786eb2d77b7f4422f927823e475e05b24245f9068a67f14f4f3cfb1eb30bfede7b3262230ced9e31361db19636b2c12fdf1b9c14510acd5bc18c0ddf7635e003503e6f71e1c365cdfb4c65ee75b4de0694af87076374d631e6c4b8e240fa51dab5e1f80ca2a06c49f42ea09e0475defb184d9cde9f58f959e64092aac8f2027e468126f2fb:79549a317d10a0be322a94a151ad11e77efc4836cc8006a85081273d7602a638963a9caf19c3edf1e25fad1e9d68701a71dea727da6a5c5bcac9339589224b05143caafa5f62b13e43dffa49d420fa99f771b1926d40d6cb2bbb427f27b6c266eb3deb2d8bbbd47b8214ad40251cb1907ad65eb94193e54ad85c6700b4189e80f1cc0154c63ed151a8bbbd30e01637ca58e70aa3ee52ef75d0873078a405014f786eb2d77b7f4422f927823e475e05b24245f9068a67f14f4f3cfb1eb30bfede7b3262230ced9e31361db19636b2c12fdf1b9c14510acd5bc18c0ddf7635e003503e6f71e1c365cdfb4c65ee75b4de0694af87076374d631e6c4b8e240fa51dab5e1f80ca2a06c49f42ea09e0475defb184d9cde9f58f959e64092aac8f2027e468126f2fb: +971f806be6f07d41be8830ff8dae704b08638ad6cff722d8432538127b769625af6ac98dce2078a6c73f6097bab63f205caf6953afa284d042bd50a4fce96cb4:af6ac98dce2078a6c73f6097bab63f205caf6953afa284d042bd50a4fce96cb4:013455d049aa54ed995fbd94e6369955495395e4438822259b1060e9a34779042a1a69211f6ea2077399dd234806ba0b353cd79a57e1c49b250ab27106dcde576ecfa115eae461febb12d2da25ffcf17b715f8d95c2f0c425d5a81f700115b70d49e1cfe49fcaa14fa205e28ec85247f1a6e7128bf3bb3060dc08464bda6538540d0ac472093e5a0720fde2f3dc4788e0e9b0dbfe2a2b5f1a0f3f80de984025b15c65af77f671e1c5e2840444de5c7eda025e6dc1a3ff16e26cc54cdeed56be73f9b01ab2b1bc16c8ef58a5b76dd47287807e5c50f0d7c0a5b8120dfde645a012c5cf11491bc:2037a0a7674b84ff27d0b22f62b4bac65e2dc0f5fdc899feb7800f25c29981dee641c5a50f8b9410970b49d2d53658c89ee16961dccf5391a6918f2a84eada0b013455d049aa54ed995fbd94e6369955495395e4438822259b1060e9a34779042a1a69211f6ea2077399dd234806ba0b353cd79a57e1c49b250ab27106dcde576ecfa115eae461febb12d2da25ffcf17b715f8d95c2f0c425d5a81f700115b70d49e1cfe49fcaa14fa205e28ec85247f1a6e7128bf3bb3060dc08464bda6538540d0ac472093e5a0720fde2f3dc4788e0e9b0dbfe2a2b5f1a0f3f80de984025b15c65af77f671e1c5e2840444de5c7eda025e6dc1a3ff16e26cc54cdeed56be73f9b01ab2b1bc16c8ef58a5b76dd47287807e5c50f0d7c0a5b8120dfde645a012c5cf11491bc: +2bb0652f8fff6901991148c68a3267877271006ae9589149bb206850cdf52fb0c03b77be983e74a234c1986496b292e139992eb7529e70b3afad7ae4fdcf8a66:c03b77be983e74a234c1986496b292e139992eb7529e70b3afad7ae4fdcf8a66:b923ca67e396d8656fa3dbce8289a38bd3c128cefb30efc1862bb944b4507805419824ce2b83d690ef4cf107492817143bf64c024989af1a7d2e1f5ac97874f86bb0d3773ff840f514d9a1394a3959b011d3a6b816a3fae5de17b2a9ff349863d27fbbb50cca734108751000d6358ca0647a93eb49e2e7af06287d48f2c09d5c1c73e4d8f77ea2bcaa7356795b26728719bed5ffdb821578bd5d66bf92edaf8b238b2bbd7d1e2c30a787f901a33d0a76669a9c3c7f2b552ccb8349c7ded5e1a46170cf28e359e2fdd54b05a562f528c68a56974df82d466637c8e53246a7217e4386801e0e3266:4e158deaaec3d88941296af2d27341012b0241d4e0f46e435e375c9875e89f5e32c057b527bc3411af096a77bfceb45b983efe455e3f03155d6bc7b0acc8e60cb923ca67e396d8656fa3dbce8289a38bd3c128cefb30efc1862bb944b4507805419824ce2b83d690ef4cf107492817143bf64c024989af1a7d2e1f5ac97874f86bb0d3773ff840f514d9a1394a3959b011d3a6b816a3fae5de17b2a9ff349863d27fbbb50cca734108751000d6358ca0647a93eb49e2e7af06287d48f2c09d5c1c73e4d8f77ea2bcaa7356795b26728719bed5ffdb821578bd5d66bf92edaf8b238b2bbd7d1e2c30a787f901a33d0a76669a9c3c7f2b552ccb8349c7ded5e1a46170cf28e359e2fdd54b05a562f528c68a56974df82d466637c8e53246a7217e4386801e0e3266: +db9b812cb3c7c03b977f487d3d65ccd9cd2f3dee11602067dbfb72b589ff3f79ffa038ad8c3b378ce75d65844d08e3d6a92d194a1b7862e9d9720d20679b2944:ffa038ad8c3b378ce75d65844d08e3d6a92d194a1b7862e9d9720d20679b2944:a70092c7697cd4a209567c38ba7fb71aa8f15e5827a20876923943fd6adc659c9867ac6f58a61dc7cec3d362411682000c1a9ad1295eb8b70f242d86b5865eb76b87e3f2c6941d2612ee3bcde8f19765566733152ef54e95690943285f78b375f4036585d4739deedeef6d946db61ca458ef4f650da963c385e29dfdee415fe495845f55197a870f8cdeb5a010ba6bbb32bf1a588cc774d4890184c4b2924a5b8073313bce226585f1adfc229c90bc6cc9d212e62f05d33bedac961d77cf8c2620e451de817f8c1bb16a2c59ff804b635a73a8cf8c181b3f9401c3b643d18a2f706ea9cae47071a6:a628a77421b2abab576eed35d2ee3d14561b21fa14a6e2fac263c3eadd79f2fc0669f9429b910b8422b4b29ac026a42e98d181be3507c5ed7c748a1fdcf1d807a70092c7697cd4a209567c38ba7fb71aa8f15e5827a20876923943fd6adc659c9867ac6f58a61dc7cec3d362411682000c1a9ad1295eb8b70f242d86b5865eb76b87e3f2c6941d2612ee3bcde8f19765566733152ef54e95690943285f78b375f4036585d4739deedeef6d946db61ca458ef4f650da963c385e29dfdee415fe495845f55197a870f8cdeb5a010ba6bbb32bf1a588cc774d4890184c4b2924a5b8073313bce226585f1adfc229c90bc6cc9d212e62f05d33bedac961d77cf8c2620e451de817f8c1bb16a2c59ff804b635a73a8cf8c181b3f9401c3b643d18a2f706ea9cae47071a6: +ce379bbe2fa8abcba51c7a7543de5b7180771b3c44bc6b41892e7b88979bab907f3cff89f41babf4fa64cba33a5bb17f413bbf2a1e112b50a8e9b1f821d849bf:7f3cff89f41babf4fa64cba33a5bb17f413bbf2a1e112b50a8e9b1f821d849bf:001a74f095c814d3beed67a8d15fc18efe235dc3f6457812a4039b7a46fe9a0e9de81a7a4e5fbab5ebe9e1e4801bd11b45c9f7ad0636a09bff42164be5749a04c02f0ab61f0ecfdfef799b827da6a274c8d3b39f2e3805a6791287eedb2314d3f842b558b9b489afe1ed37bbbcfc5e60a431d5ac60b39e946d903d6bf6b140e12c7e07f9ed7ac46a3999c6245c8ab1bdb21879a317a3dcd257a5c4f349b7f59e4e43d62d9f1cd16f518f1ca6cad37e2cb20f2598c4134291c6b8a98aae5247e26eefb76aa38c9c8231c17e9dbf271cec80fba5b4a834bd9be81ea841637aa9cdd4c4bf26d7ad24ca3c:da98dfb189385b2c853b6cf375738046a8f27ef27974abcecea1db02989b951fe433a6ce1e225b3fa82032fe060a7d3f6c183fd1157f791a064b407650571600001a74f095c814d3beed67a8d15fc18efe235dc3f6457812a4039b7a46fe9a0e9de81a7a4e5fbab5ebe9e1e4801bd11b45c9f7ad0636a09bff42164be5749a04c02f0ab61f0ecfdfef799b827da6a274c8d3b39f2e3805a6791287eedb2314d3f842b558b9b489afe1ed37bbbcfc5e60a431d5ac60b39e946d903d6bf6b140e12c7e07f9ed7ac46a3999c6245c8ab1bdb21879a317a3dcd257a5c4f349b7f59e4e43d62d9f1cd16f518f1ca6cad37e2cb20f2598c4134291c6b8a98aae5247e26eefb76aa38c9c8231c17e9dbf271cec80fba5b4a834bd9be81ea841637aa9cdd4c4bf26d7ad24ca3c: +2b2ee809d647023e7b77fc541f44875a35fa941d37f7c5b21fd34934d23919352c29d53e1bf2c7879d73d20ba88ca07a0b216d7f6d05d93663a65c3d9e10633a:2c29d53e1bf2c7879d73d20ba88ca07a0b216d7f6d05d93663a65c3d9e10633a:c4147d64ebfda41a1be5977262958104e940c3876bcd5b6956acfdec32c660914d62623c210663cb2cbe6249d7f5274991c60e950e8e2809049953c69581d2469f4fe982c7434fedd9d4e00ae08896d62cc1fb984dd233150cc2483e159cff4097df8c036bb633003abbfbe18c8fa79b5a22270838123fc9be39b8892c80384a385028c1a81ec58c8f21060e78afd2c04bfd2d30ca3977c6edad518cc1e2004cdc14bf3d15f5f528e5af277fa182275870e5c012f5f82fb1afd04edde4578ddd2160a1a3dbc050e80bdd811bc88ead79bf93f010cd0fd4433d0bc348dacfd0947cceda62bfa49711d013:12d90685775572c9eabc9be2574ca9ae66f0e652e578b21736cd6e654f7c6b1545883d56bf760ccfc3cf87544e0004c798061257e130030cb997a788369a9a05c4147d64ebfda41a1be5977262958104e940c3876bcd5b6956acfdec32c660914d62623c210663cb2cbe6249d7f5274991c60e950e8e2809049953c69581d2469f4fe982c7434fedd9d4e00ae08896d62cc1fb984dd233150cc2483e159cff4097df8c036bb633003abbfbe18c8fa79b5a22270838123fc9be39b8892c80384a385028c1a81ec58c8f21060e78afd2c04bfd2d30ca3977c6edad518cc1e2004cdc14bf3d15f5f528e5af277fa182275870e5c012f5f82fb1afd04edde4578ddd2160a1a3dbc050e80bdd811bc88ead79bf93f010cd0fd4433d0bc348dacfd0947cceda62bfa49711d013: +4ea18d6b4af8053b885ec188be48deb86ffb2a69a4cec86637bbd7b41b807c46e5986059976233ed77382c3d9959f34e317962696553e86ed1e5902c4bedd167:e5986059976233ed77382c3d9959f34e317962696553e86ed1e5902c4bedd167:e9c89a1a1119373206ce40ede3b89a82f89462a1dee9e789e9845eec21f571c0faefd430ad338e4a72c047a39a4259580387fb9aacaddc36a2b51e7b60a87ca1321ff806794cd6dd4549a4df45c2dae3e539c4d7d06b6e6e9f466ffca2fa4978ce3dc792e44a6283880cd138a75a226f985da41ffdc0e32a5a85c85fe9a43ae78fcfe57f4dd7540a6dd3924a49ab39eb69950d421151d96b1e4fd3935890f634cd52a73a755f5c2fb72f9cd5a2e67ea930915e133b47cf6b7c10a9d889c6af6b5f1f4f51094d27fbba228ac2268b344027fd49e426343cc0134399b4b510aaea50234df42c37fa1c4f4d0e:27570c002a487d000ca3928b83cb4319722c46dfb4cca260de790ec0e3c1932688f87362952818b54f51bc7aeeb263f960bc0da8964bf312ef93e81f06c80b04e9c89a1a1119373206ce40ede3b89a82f89462a1dee9e789e9845eec21f571c0faefd430ad338e4a72c047a39a4259580387fb9aacaddc36a2b51e7b60a87ca1321ff806794cd6dd4549a4df45c2dae3e539c4d7d06b6e6e9f466ffca2fa4978ce3dc792e44a6283880cd138a75a226f985da41ffdc0e32a5a85c85fe9a43ae78fcfe57f4dd7540a6dd3924a49ab39eb69950d421151d96b1e4fd3935890f634cd52a73a755f5c2fb72f9cd5a2e67ea930915e133b47cf6b7c10a9d889c6af6b5f1f4f51094d27fbba228ac2268b344027fd49e426343cc0134399b4b510aaea50234df42c37fa1c4f4d0e: +fc1b75d17d3807217351d2aa40d9b04f525b89ed3f5fcdb311bec2aec5cb7ece55e484e774a4392a9d6eeff835a8fbb232cf6276a89c74fc0d1bb2045a8b21be:55e484e774a4392a9d6eeff835a8fbb232cf6276a89c74fc0d1bb2045a8b21be:d031bd11da308097e3beb6ffdb2600ee6a193ca6d8324501c972b1a25166fa7a369f5bc882ea45612cf02580254d21b40b0363237e835dae2656c1b7f4736e88be53d6b119c07f5729bbd82f67de03588322879243c5990a7e61f56907b24171a57cbb0bbefba2316277af9326f9cbf3538bcbf6780be41825a2ca774b41bdb1cd5c608851ec2339eb2f4feeddaa891a6326b29d97d7fbf311e3bb749c5d4c058dcc14f452f9334991e271c16d6508c818633927f429804ca7a38170f1b9f6bd73ed675e11e8c0d321fac912730b4ba2f7c428534adcaa4dad314c55807e6c642d494c6b2f0e8cd129775cc0:9a68d151fea3909893359e60b96b68b2a3e2946f2b47b875398a1e39eb01463d35eae7d976f833a762b51f2726ee0dccad5ce3600564fd9dd58c23807fdffd05d031bd11da308097e3beb6ffdb2600ee6a193ca6d8324501c972b1a25166fa7a369f5bc882ea45612cf02580254d21b40b0363237e835dae2656c1b7f4736e88be53d6b119c07f5729bbd82f67de03588322879243c5990a7e61f56907b24171a57cbb0bbefba2316277af9326f9cbf3538bcbf6780be41825a2ca774b41bdb1cd5c608851ec2339eb2f4feeddaa891a6326b29d97d7fbf311e3bb749c5d4c058dcc14f452f9334991e271c16d6508c818633927f429804ca7a38170f1b9f6bd73ed675e11e8c0d321fac912730b4ba2f7c428534adcaa4dad314c55807e6c642d494c6b2f0e8cd129775cc0: +0d0bf4d42ef810b179eb841771de6dbde76361caf894e42a14b1e09787ea3e067171510b43fc17efa80b15e320b1b0a408332542e0d36e4ab9a649cd941b5aed:7171510b43fc17efa80b15e320b1b0a408332542e0d36e4ab9a649cd941b5aed:8e2179975d0a8e5a69fe875a3cb1e79aec49c3853e30dd0320fe3ebfb638b82f89ad1643036b37e56e0b55e0a9e22a4e283d7a27485ce9102db6787d6628b77913e10896774e495c26e8bab26e7f9a94d29aaa36aec9c26ad3f50e5d8c0b7698bb5f01b876d0d65fcf5e9e32cd7b89829ed05b0b8f63a93858985bc9569fce429fd37a211abed650f585c3b55900443b6c5d6e8a48ba67deeed07b76e969fc88430fce2709c0bb5ce926ab7f44e0cd79f4ec359ef76748883fcc3d026edd06c8b9cba54b990d30aa41f1448a10893fb0539280c599d42361433a34cdafd8ebdd92efb9c38a36daf4c74060c696:24446bdf03416a4d08614466fb851db50e91a623cacd1b0b35660f3cf933200e15308708da3499a5ad25f0f0306b7942762e20a765b7ca9b901c750b3a95320a8e2179975d0a8e5a69fe875a3cb1e79aec49c3853e30dd0320fe3ebfb638b82f89ad1643036b37e56e0b55e0a9e22a4e283d7a27485ce9102db6787d6628b77913e10896774e495c26e8bab26e7f9a94d29aaa36aec9c26ad3f50e5d8c0b7698bb5f01b876d0d65fcf5e9e32cd7b89829ed05b0b8f63a93858985bc9569fce429fd37a211abed650f585c3b55900443b6c5d6e8a48ba67deeed07b76e969fc88430fce2709c0bb5ce926ab7f44e0cd79f4ec359ef76748883fcc3d026edd06c8b9cba54b990d30aa41f1448a10893fb0539280c599d42361433a34cdafd8ebdd92efb9c38a36daf4c74060c696: +57b5194d26abe4ab2116c0f03d23dbe116d48825a25e77d64648b43692ae25bf499c02dbad2a4eab3b6ff1aba3944b91c3f273a382c548a6f3a19c83f0a86724:499c02dbad2a4eab3b6ff1aba3944b91c3f273a382c548a6f3a19c83f0a86724:b4813c9d13215fe9f63a78ff7ac95173eb810b4613f0f48d6876b2bd3b2c72bc7d98cb1ac32bc41ca47f09896f79204ecfb8264ce8f3c3e76dc124da8ddc6e0dfc1e13b5a529f20c82613fb9a82e5f5d77326a861faedabc7325c59af33dae6744025e649774fc4f79134bf9f6e3d5875dd91bc8a14cc36a66283d01d8d108c13327eca53057ba50bf210c19f139de6494982646198a1246c271b0a368c10aab95cd8961235d742df4545be68bd010dc0db23b673e623609e420ee76b1056c520f9ce8fbe8ee1863df97d17b7174636c3a2b612295091948810d1d4b8a5843760a2887dc55ef512af041ec54fad3:4c7345960c8fd48a7dead71dbd61908468efa865a135568c8f9ca0055483468617a7e335840f57c6cd8f2c9805cd47a9d7cdfde53da8ef4f1adbb6f698aaf100b4813c9d13215fe9f63a78ff7ac95173eb810b4613f0f48d6876b2bd3b2c72bc7d98cb1ac32bc41ca47f09896f79204ecfb8264ce8f3c3e76dc124da8ddc6e0dfc1e13b5a529f20c82613fb9a82e5f5d77326a861faedabc7325c59af33dae6744025e649774fc4f79134bf9f6e3d5875dd91bc8a14cc36a66283d01d8d108c13327eca53057ba50bf210c19f139de6494982646198a1246c271b0a368c10aab95cd8961235d742df4545be68bd010dc0db23b673e623609e420ee76b1056c520f9ce8fbe8ee1863df97d17b7174636c3a2b612295091948810d1d4b8a5843760a2887dc55ef512af041ec54fad3: +068d27b21e2acfcc19c3e9673dd44142d98aacae894930e20ca067439e749a79e22ddd396f955bb90e284776aa76e921e50699d0ca8914a9b7b841eb5ff47d6d:e22ddd396f955bb90e284776aa76e921e50699d0ca8914a9b7b841eb5ff47d6d:1c6815423d1a2c5ebe8828d1646527c17b2006e547f016b5350f010d79b13df4fb8c6ed57ba9c26c3cb0e0a64178b650a3ea5444a4fad5b20a3eb8caa702634011cf7892a0727b6e8150b0770429a37a8a0bb3a7edb891a7c90240bc0360b14e6dd770a990b31b31f33ddbf653988f82742e5eec31b27368eb0e4f1ecf4d676f49214a520d1e5b2bbb59ac2e13267e07a0cbacbed9f94d7473ed697828b0928fcc616ee02e51fcd8db4d8f7533b7b139a05e06f9e0eae32993e3025aef0590b3fbb4292a3ac40765e8584ead00266acdcbdde1457a03b7d57bd5c9e64fb06b64a50f35f0a1ec34b6ddbde767b96ffd:0c173c488ad001cbb9c43d7b30a7c071a2fdb08cf7f37daf71d7ae7128dc0d43f0f095b2929c54b773ed4a1f0bf0dc4f364f0601e8d5ae062f5b78c05bfbc7021c6815423d1a2c5ebe8828d1646527c17b2006e547f016b5350f010d79b13df4fb8c6ed57ba9c26c3cb0e0a64178b650a3ea5444a4fad5b20a3eb8caa702634011cf7892a0727b6e8150b0770429a37a8a0bb3a7edb891a7c90240bc0360b14e6dd770a990b31b31f33ddbf653988f82742e5eec31b27368eb0e4f1ecf4d676f49214a520d1e5b2bbb59ac2e13267e07a0cbacbed9f94d7473ed697828b0928fcc616ee02e51fcd8db4d8f7533b7b139a05e06f9e0eae32993e3025aef0590b3fbb4292a3ac40765e8584ead00266acdcbdde1457a03b7d57bd5c9e64fb06b64a50f35f0a1ec34b6ddbde767b96ffd: +a34d52563159e0723e9f3fd133bd96e20adae623f8c798013bc36b441489bdc21fb658e645de6d3efdb083a73fbd592fcd4b800e03c7bd681aeae6576bfbbe2f:1fb658e645de6d3efdb083a73fbd592fcd4b800e03c7bd681aeae6576bfbbe2f:1d215f85c089f35f307a746c66c7c1e41d6ba37730d759e6e5622d6c6a198e40f63d37873b715df7518b3c6bb5e95a467726b97c9a0f8f5dfcdbfd1e0de357661ddeab555042b945fd899fad6d382d7917da9e12dfbda0d69900b3975165a73d0ac9de01fd3048b8fe5f0b90be67e03dc22f653a0a13eb4b0b753f3f3bbf787369ebd8bf5e00eb78bf0b3515a91e68b1d5fc6920bf4f4259f8a730efc7f1016d501ef6fb7cb8366fc8e716cfa50ea8b203cca1a316707e0b0fc57eafce82d62f7ff3ae04ac8fd041b55b19a352a69e6d4b79d0e650175168e34fa3358eac816cecf2c8dd1bf2a589113e91bb818f91f8:5fab5a7140d47873684305aa6353d3862f5fc13e54a40c9563cceac8f74008c6c445631fa864e0f1c345b5954f80056aeba25662b78827b5e8e3a9437813720f1d215f85c089f35f307a746c66c7c1e41d6ba37730d759e6e5622d6c6a198e40f63d37873b715df7518b3c6bb5e95a467726b97c9a0f8f5dfcdbfd1e0de357661ddeab555042b945fd899fad6d382d7917da9e12dfbda0d69900b3975165a73d0ac9de01fd3048b8fe5f0b90be67e03dc22f653a0a13eb4b0b753f3f3bbf787369ebd8bf5e00eb78bf0b3515a91e68b1d5fc6920bf4f4259f8a730efc7f1016d501ef6fb7cb8366fc8e716cfa50ea8b203cca1a316707e0b0fc57eafce82d62f7ff3ae04ac8fd041b55b19a352a69e6d4b79d0e650175168e34fa3358eac816cecf2c8dd1bf2a589113e91bb818f91f8: +58dfe768bf52118494b29975154cf452bd9746dc7de1d6bcd18ee6a05acfd8580f1476c6cc2a1b4764af75805e77341f14a0d8b09c6a5b2ea287fd517c3fa6b9:0f1476c6cc2a1b4764af75805e77341f14a0d8b09c6a5b2ea287fd517c3fa6b9:609794201c4f6faf488790d61dbff3f41b328c5b0695cbe9aa8a136d72b4977b21b500f216e9f32168ada8c13bff25327647e30d8a244d74d88303abc90b7f71aa07ca04d17bc8a0167d6e63fb88baa1dab81d50f1e91f46f5af77f2e8408b826336a35052efffdf4af79596af1bb2259f83c1bc109cfdc3dd50fd96d310f27ea4c6c7690f21815ea92bd79389680cfe3ed40c80181190688d24222d9a1ed52ce6a16b41dbd9107eb6d2e3594e4494d75dd7c089e3b26ffd00d1003c92c4c39ae5382ef9291491a880ca4ec3ac2b86e66719b92b6f7cea2cb0bbb1cf624d0d1abeae556e5f73909dd546277037ec972fd4:977137a38af44f4b262abff7e07282433c58926d562fbc6180bde6cd9497861fb6d955cf383d999fa1037b8b1754ce888c9ffc1560a451d0e9db8d74d2940604609794201c4f6faf488790d61dbff3f41b328c5b0695cbe9aa8a136d72b4977b21b500f216e9f32168ada8c13bff25327647e30d8a244d74d88303abc90b7f71aa07ca04d17bc8a0167d6e63fb88baa1dab81d50f1e91f46f5af77f2e8408b826336a35052efffdf4af79596af1bb2259f83c1bc109cfdc3dd50fd96d310f27ea4c6c7690f21815ea92bd79389680cfe3ed40c80181190688d24222d9a1ed52ce6a16b41dbd9107eb6d2e3594e4494d75dd7c089e3b26ffd00d1003c92c4c39ae5382ef9291491a880ca4ec3ac2b86e66719b92b6f7cea2cb0bbb1cf624d0d1abeae556e5f73909dd546277037ec972fd4: +5a63ef9bd7dbf0e89fef155983659e8a0a6ca002bc42fad5a45af8e0281923f4e632f4dc994231cc1790c21afadaa977a589b0eb0da19fcb2792911b15ecf8af:e632f4dc994231cc1790c21afadaa977a589b0eb0da19fcb2792911b15ecf8af:796bc8361c6e8eec39838b24f53971e820f82361e0510eb4def1db2512387d6bf35bbdfa318879209435d6887b1410b3ebc1455f91f985e0fab1ce1c505c455576bca03539d048ad3a0ed1f11c73bac6809e2ea147975bee27c65261aca117df0fae7008e2c3c130bec5533ab89351c2140c9d1a62bdf688629787f954e1c610cbb75edb86209d7c357cd06ef41931dd5dfd1c7d407fa4ee1ef29393beab5713173802cce2d56229cfa76b601662c4d9a84a4936c52abb1981378b717eb55cb604a68d34f03b219f32226ca0e669348a2d8d2453930eb6e9c2bf66fa4e92c75136e148cdb034130d3f646382e1c71579ac70:75461f99650c0368058113a15ba16bd2337b2e633da38112878c4834fac9ba2e307c866c02af79bea33659614cbb4465c57ec3effd4c478ae38a34a05cf1ed07796bc8361c6e8eec39838b24f53971e820f82361e0510eb4def1db2512387d6bf35bbdfa318879209435d6887b1410b3ebc1455f91f985e0fab1ce1c505c455576bca03539d048ad3a0ed1f11c73bac6809e2ea147975bee27c65261aca117df0fae7008e2c3c130bec5533ab89351c2140c9d1a62bdf688629787f954e1c610cbb75edb86209d7c357cd06ef41931dd5dfd1c7d407fa4ee1ef29393beab5713173802cce2d56229cfa76b601662c4d9a84a4936c52abb1981378b717eb55cb604a68d34f03b219f32226ca0e669348a2d8d2453930eb6e9c2bf66fa4e92c75136e148cdb034130d3f646382e1c71579ac70: +8b2f06141e401163f90f674b04dc90dcb6dd3386419339662ecb0dffadf2500b54da934a659119198553fd4566b660d8d610adc3290cb84829c894148cf3f67e:54da934a659119198553fd4566b660d8d610adc3290cb84829c894148cf3f67e:1deb25d43458690323a7d26a26695090993474f467c6fde5ddb34da945be3cea2f6b75652ae21cbc4fd22763a1b45583e1c3e88bbb5fea2049b7336c91159988c01526824ca3bef16b362b9202b8b9754185bd61bea8f539aadf4a1ab135fbc31d2a8e33178073106cbbc02d4cd0d3c8feaa8eb733084356251795afbd78ac3c4f8a3ba19aed755c646f35569c7a6c675b6d6918e834969aca03f71a2e72ccb17003bb75b62e852aaf58b3baea89bcd64a32eb14a6b9e10de48971e53d0e9ac99a78f42de0382ef0e80ed3cfa343f35e4a9983b9aeed986d3a57f47e5e46d40e9d677302809a2d37e4ec011f051b4d031ed600:d68e3750dc56432397401c98ff1529db9ed48fea246dd4ed383ec74c1a463aeb784c87b1fda8bbce970fc97aa9807ddbe95d41fb022ea68c1e311654fa1da2071deb25d43458690323a7d26a26695090993474f467c6fde5ddb34da945be3cea2f6b75652ae21cbc4fd22763a1b45583e1c3e88bbb5fea2049b7336c91159988c01526824ca3bef16b362b9202b8b9754185bd61bea8f539aadf4a1ab135fbc31d2a8e33178073106cbbc02d4cd0d3c8feaa8eb733084356251795afbd78ac3c4f8a3ba19aed755c646f35569c7a6c675b6d6918e834969aca03f71a2e72ccb17003bb75b62e852aaf58b3baea89bcd64a32eb14a6b9e10de48971e53d0e9ac99a78f42de0382ef0e80ed3cfa343f35e4a9983b9aeed986d3a57f47e5e46d40e9d677302809a2d37e4ec011f051b4d031ed600: +dc649fbb1bee0a44814d6d9e9080d5d90c1fc173ab5fefed826a74723a774e0a0214c89f3867ad2e8870e50f8c2a6254986d9c220e3338411300cd9c6404d4b1:0214c89f3867ad2e8870e50f8c2a6254986d9c220e3338411300cd9c6404d4b1:328700a8ae581c1edc4e2c00c78bf4606097f9bd75aade205a243c5fd7434d6222da937e2881a2e3c574356d4d5679301da99e11cf749c27921c8caa2ab2a564d87c5df8ecf1a72b680184824f6986022e3fc98bd2a21c3455abf1154954fb30c89882947b02f35af7b1bfad05237d242e2b74832fc536196f2e59d1acd0c1db6f1943d0f6043bbd6a769083ed66ba0e05a50feb0acf72b6c16ba9af039afb7fe2a4aaeb4d06181c5a1878689e67a3f5d0ad39e794d6239a7e0a12ce820c5be60fd5f1dd79702f49d02b79755fe873f5785c72f74625cd7e2428262597d31482c2c0508801fd96319d61b91ba253a5e722f414cf:0e0c5e4e184375da4ef7e2a2e4888050cd84e2fe21d08e84a852db2be3fbc372c472de0954dcd1dc11aec493c569f40fc6f77f03ee524fb06ec40faa1d6cc10f328700a8ae581c1edc4e2c00c78bf4606097f9bd75aade205a243c5fd7434d6222da937e2881a2e3c574356d4d5679301da99e11cf749c27921c8caa2ab2a564d87c5df8ecf1a72b680184824f6986022e3fc98bd2a21c3455abf1154954fb30c89882947b02f35af7b1bfad05237d242e2b74832fc536196f2e59d1acd0c1db6f1943d0f6043bbd6a769083ed66ba0e05a50feb0acf72b6c16ba9af039afb7fe2a4aaeb4d06181c5a1878689e67a3f5d0ad39e794d6239a7e0a12ce820c5be60fd5f1dd79702f49d02b79755fe873f5785c72f74625cd7e2428262597d31482c2c0508801fd96319d61b91ba253a5e722f414cf: +39b8062da43e64e1676765d62c7fb8e0a99c4fd417d6f7e3319bb13044205f3b6227cefe88ea4fb27b37b5f797778bd72fdafeadccd9aeb67ad437ce08fba6a8:6227cefe88ea4fb27b37b5f797778bd72fdafeadccd9aeb67ad437ce08fba6a8:740af679e3069fad059fa4825fa41c59fbd484aa649303c27c4f7a94711c5b713b2a6b8987859e2271a6a71eb0b4a15abde4f5168f6cb9dbdc6a27a2a13d52c9720896a1f4ce3a5345ee793b6cc3ad80d7d58163d5455b9cbd073e2b7adbff95590c7172271bd91fefdbd01657ee1750651036cdc3560b444ca2184bf4f3ea89fc973aab6fb4a8ee5704bbe5a71c99fa3b5ef0d0396249758297699ae202b819690dc7ac4692770346907845e2210d5363adeec03f0fc7761b7e0ec0fea1bcf6b04fc54b3e4c40d19b8fa649ac8479e8f80730c0c94e9f4a1ad506f2bcab0c49540f6decaa77b3d657dc38a02b28a977ece482545a:c5f626490c0ef4e1efc3edeb0cbc3f7de267057fb7b6eb8f0c813584965bc5c421feedf54241cae001ec6d5e25c9b1fba0385e5dbd95a06ec1d8ae519144960d740af679e3069fad059fa4825fa41c59fbd484aa649303c27c4f7a94711c5b713b2a6b8987859e2271a6a71eb0b4a15abde4f5168f6cb9dbdc6a27a2a13d52c9720896a1f4ce3a5345ee793b6cc3ad80d7d58163d5455b9cbd073e2b7adbff95590c7172271bd91fefdbd01657ee1750651036cdc3560b444ca2184bf4f3ea89fc973aab6fb4a8ee5704bbe5a71c99fa3b5ef0d0396249758297699ae202b819690dc7ac4692770346907845e2210d5363adeec03f0fc7761b7e0ec0fea1bcf6b04fc54b3e4c40d19b8fa649ac8479e8f80730c0c94e9f4a1ad506f2bcab0c49540f6decaa77b3d657dc38a02b28a977ece482545a: +52f4675d8ccd0eb909df0a516648db26fa033ba41d43fc3845896d456e14265ff39e7dafc97b0a84dcbf7fa14a9403ee1fa92b85e5a7e5d05f031b44ddf1f794:f39e7dafc97b0a84dcbf7fa14a9403ee1fa92b85e5a7e5d05f031b44ddf1f794:74427110857cb4af0a3342c2b52997bce1a0db6405c74e9651c5b85979acb071e567fe70412c4e0d8c9fa421914f6a62f2ae420b7b2f4cf80c90574221222288b65867eaa66e7e0a0557a26c549f9a7a4e70838ba4074b4cd7a9d758b378b88dd49441df802a444dcbc30624933b59922f33c20f019fe78ee24b8fba79a682f388505ac9c97f4eb87c611880026b4c23306b865173f5d716abc6cd9a9906db3430136f754129c443b20c42be2fbcbcd44034d714f58a4ba8e756607a02b608ef49648f2ad0cea99e7ab30a8dd7814004f725f49301d7b304dcda625c296d928cb581736ab739c86b469241a8259351fd37b4780a9993:4bf668827a720af68898a06ea7b44545a34ca896ecf311feea47e0686d911fadaa03118997153c65361fea15de9bb891b8909872045508ffad0cd9eab21a970274427110857cb4af0a3342c2b52997bce1a0db6405c74e9651c5b85979acb071e567fe70412c4e0d8c9fa421914f6a62f2ae420b7b2f4cf80c90574221222288b65867eaa66e7e0a0557a26c549f9a7a4e70838ba4074b4cd7a9d758b378b88dd49441df802a444dcbc30624933b59922f33c20f019fe78ee24b8fba79a682f388505ac9c97f4eb87c611880026b4c23306b865173f5d716abc6cd9a9906db3430136f754129c443b20c42be2fbcbcd44034d714f58a4ba8e756607a02b608ef49648f2ad0cea99e7ab30a8dd7814004f725f49301d7b304dcda625c296d928cb581736ab739c86b469241a8259351fd37b4780a9993: +bad73c9fda4ceb9da6c701c2a6e2efc0467afa0a74f8750c52cf1fd4c8e7489abb0f027a9035376e1aa3206c3d774475e351f5767ef86ef48a72c037c24cce62:bb0f027a9035376e1aa3206c3d774475e351f5767ef86ef48a72c037c24cce62:74b966cb780771aee63d734df3756702d1d5fdeddf32136c6358b836318a4f984fe71e7716adddbd649eba44cd4282e0055d8c1ed2d35123d66e5a98f1c0838ded563b9a20eb8007538fc7b0713e7e485e3c28f6ebc421a29dce2524db7f29205761036ada62e5b0b7d5b7f294ff17f338232fa5fd42b6f7253304092d848f50735248595da0f7ef28e568e9916bfc56d7ed0d811b59d5d891ae43e1b198071306bf525c678c6343998005fbb7869d1c40f8cac807fe2ef03f3d5b933f58978ef2906fccf7444a2936e63d928c690926c9c994ed3d666263e956fdfea27764bc5f74125bc46bc102dd3e5ff93b5e123e4b38bdef697e15:197d6b6cc88a98c06dfca0c01225edfe38a0b2289f29f8a44ec0816a952d585e2d59b5b08de100c0606296ccf5e92a99e093623144b8b22db87d92922554600574b966cb780771aee63d734df3756702d1d5fdeddf32136c6358b836318a4f984fe71e7716adddbd649eba44cd4282e0055d8c1ed2d35123d66e5a98f1c0838ded563b9a20eb8007538fc7b0713e7e485e3c28f6ebc421a29dce2524db7f29205761036ada62e5b0b7d5b7f294ff17f338232fa5fd42b6f7253304092d848f50735248595da0f7ef28e568e9916bfc56d7ed0d811b59d5d891ae43e1b198071306bf525c678c6343998005fbb7869d1c40f8cac807fe2ef03f3d5b933f58978ef2906fccf7444a2936e63d928c690926c9c994ed3d666263e956fdfea27764bc5f74125bc46bc102dd3e5ff93b5e123e4b38bdef697e15: +707327a431dba77639b3966b2bc095f8eedf57f7a200e3b0077ce420389c92feee2496910864189fdaa3c7757eb3cda9ab1e70fc9e7f71a38a0bfc845931c95a:ee2496910864189fdaa3c7757eb3cda9ab1e70fc9e7f71a38a0bfc845931c95a:32ef31b64eee700fca2ab21a267f8d9d3bdc689c7538fe959bf713fa995db2c0ad36dde430a8417d437b72c74e26dbe31d93701d4617fe51825cff7a544fc9f44e4345e14b4b11e15f26ffc2af8035f3f970e4dda44c0ebc0363c2b56fde218663bf78839092538fc2f39153d4eb29da0c1a08aa966601cc68ca96e993b01b173a261b2ef327650382f568fe944855b0f4fd9d15e752ac74dcfd37b3786fffcef23339c21e9270dce8891dd5eeeba9608fdc7b6fbcc99fa1b5903daa0968e1b691d19d06f215ded047ef9d76610f5de220f5041b313faf9e96c9fd7db54b5225726af435f9cbd9fd87ab40ce8f2c6940b55f0faae87850ca:fb99029feca387a5d765961e361d7172b98b7e0f11290bb1e5b57b51bc2123d0bce29020392a4fec9ae6a72c4c386cea1857cb8f9c50aa9a76d7f1687fcf290032ef31b64eee700fca2ab21a267f8d9d3bdc689c7538fe959bf713fa995db2c0ad36dde430a8417d437b72c74e26dbe31d93701d4617fe51825cff7a544fc9f44e4345e14b4b11e15f26ffc2af8035f3f970e4dda44c0ebc0363c2b56fde218663bf78839092538fc2f39153d4eb29da0c1a08aa966601cc68ca96e993b01b173a261b2ef327650382f568fe944855b0f4fd9d15e752ac74dcfd37b3786fffcef23339c21e9270dce8891dd5eeeba9608fdc7b6fbcc99fa1b5903daa0968e1b691d19d06f215ded047ef9d76610f5de220f5041b313faf9e96c9fd7db54b5225726af435f9cbd9fd87ab40ce8f2c6940b55f0faae87850ca: +6aa5c9f008f990473ba4a6286a416614026661f11e1a24efa81ac35852d1d070605ac9b4dbdd5033d6c828bfafa93c0039440aa11ca724ae834043e07bd032d5:605ac9b4dbdd5033d6c828bfafa93c0039440aa11ca724ae834043e07bd032d5:b5165d3963f6e6f9ea5657e9f07ff3a321eb338f9a8c3d3c42306b2b278978b31c623a631be3b04c41edfdeddf538e1b765bc8785401c1af29d0467a64411c497395d755dca03ae3272f4bc1fb1918dcc1ed6f04d6498404a8ce1409d447f570a4359522cc54629202ebe507ab693843141bd5ea0573b20f321a483ff383a46897f5926fe0b8afc25572707b63eeed283532928a4144196497942c572ac547605139256b0aa0eaf04db1a256012ed453b173ee19ad6e9b1af3f45ff3044a641f8c8eb0ac7bb45abbded47286b2a069d3908694ee06f2fbd0ef605a7911026ea9ea3c4913f38c04d8b69565a7027867ab3092d05f4cfb18fc7c:9756303b90655e935251032ab19cfc95ca1c2a2c3ea28b033bd47066cbd4c7d8982a8b9886f1b9cd02e88a65564da8dcc34f308ba9f10144ba469c2efa49e004b5165d3963f6e6f9ea5657e9f07ff3a321eb338f9a8c3d3c42306b2b278978b31c623a631be3b04c41edfdeddf538e1b765bc8785401c1af29d0467a64411c497395d755dca03ae3272f4bc1fb1918dcc1ed6f04d6498404a8ce1409d447f570a4359522cc54629202ebe507ab693843141bd5ea0573b20f321a483ff383a46897f5926fe0b8afc25572707b63eeed283532928a4144196497942c572ac547605139256b0aa0eaf04db1a256012ed453b173ee19ad6e9b1af3f45ff3044a641f8c8eb0ac7bb45abbded47286b2a069d3908694ee06f2fbd0ef605a7911026ea9ea3c4913f38c04d8b69565a7027867ab3092d05f4cfb18fc7c: +8efb8b79742be21e6d31de678bc81450ba8621082cd6f0003e22861e2291c48133381e356c4fd386a3f7b969afd9f5c00d2067b698b3f1f00f3784202d3084cf:33381e356c4fd386a3f7b969afd9f5c00d2067b698b3f1f00f3784202d3084cf:6b750325d3a0f08a147700b51a9b3725571094818ed69d1f761013eb86f323f73c49f5e439877c2783b336d1f1a674ef3e431fc1ae0180082df5fca69f848139fe6ab6739a0592ebd6d4705c7f0136b22189a11d60d4d3c9bc80fe7d7c00952d5742f9c0c2121fe792df133f221db991fc960ee64b9d32e0178e542bce8efa8d03ac8026cd77ba8bf0b24215b9faed2eaec920e925d5ec46fff6bde725e91c8280e4ada232a5433ae9680ebb53eb55553147c93370574854896154514299c093219a111dca4e637ad5001338c6d4d5ee9098c65832f7af835bcb622128423036c79a5737738a7539f8d4a6b8b221b56d1401aeb74d4571bc009d:923005cb4848402aa8f9d5da74030b009444924c214ad600ddbab4c153a6ff022b53cf6364cd7ee99bef34fe144da964edfc38a0ba633312650ebf0e55a060096b750325d3a0f08a147700b51a9b3725571094818ed69d1f761013eb86f323f73c49f5e439877c2783b336d1f1a674ef3e431fc1ae0180082df5fca69f848139fe6ab6739a0592ebd6d4705c7f0136b22189a11d60d4d3c9bc80fe7d7c00952d5742f9c0c2121fe792df133f221db991fc960ee64b9d32e0178e542bce8efa8d03ac8026cd77ba8bf0b24215b9faed2eaec920e925d5ec46fff6bde725e91c8280e4ada232a5433ae9680ebb53eb55553147c93370574854896154514299c093219a111dca4e637ad5001338c6d4d5ee9098c65832f7af835bcb622128423036c79a5737738a7539f8d4a6b8b221b56d1401aeb74d4571bc009d: +ed046d688b2b0a1bc3daf2119dd321a607b16d2a2d1d963add1209c665b5ccba8734f1ffcbd71cfde290017ea6253e580d59e65b541b46521f5e5ec1451eaec6:8734f1ffcbd71cfde290017ea6253e580d59e65b541b46521f5e5ec1451eaec6:b9cc90fd8de2a141f95116db3b04be83e98522597ec2174964245180b9a473767d6d470a217db5ff5a1ab777e1e28a0b16975e2bacb873020444b47ed8326421b90ebb503688f090c11b3b13617c5c5052c297a41e2893775e34d59ada49d994c0e4a9f5220e9f0315a67705a3ec08af0dc724b5cf67ff34fada8ba7109ed2b5a8907bb403fb1a838b4b059f18c792d7bfec05dee0c9cbbf1753409d7db3aceaf47b4c61398497b0eca6c1f8ac08a7ea1eb9c40bc4e92e888212f7d9ee14fdb73158160944ff9bcdfef1a7469cc70f9474e5f24dfffea585f09eaaab4be2afebbe8e6cf86d35680dc5d1b92913e848256ec736316fd0a2142063b0:721bfd4776cfba13330fd37269e979c1d7b6ce54a51b82f456e137378e582f192a12089da5aba76a7b161813dce56b72892a35330c94f7ff21d09cf09e553504b9cc90fd8de2a141f95116db3b04be83e98522597ec2174964245180b9a473767d6d470a217db5ff5a1ab777e1e28a0b16975e2bacb873020444b47ed8326421b90ebb503688f090c11b3b13617c5c5052c297a41e2893775e34d59ada49d994c0e4a9f5220e9f0315a67705a3ec08af0dc724b5cf67ff34fada8ba7109ed2b5a8907bb403fb1a838b4b059f18c792d7bfec05dee0c9cbbf1753409d7db3aceaf47b4c61398497b0eca6c1f8ac08a7ea1eb9c40bc4e92e888212f7d9ee14fdb73158160944ff9bcdfef1a7469cc70f9474e5f24dfffea585f09eaaab4be2afebbe8e6cf86d35680dc5d1b92913e848256ec736316fd0a2142063b0: +76ac8e570a39b3a0232c45497537fb2155acec3617865ed1df210f00b49d1b8d312a3ad899ae6a25507ae6e4524e10b63a6e7ae53d9cffd39cf28521d93533d6:312a3ad899ae6a25507ae6e4524e10b63a6e7ae53d9cffd39cf28521d93533d6:53ced9db2b479e59d3ed643f7cc3784c24b8bd4c63206c72e23fa850028899a41ce1a8bdc003f12b7c29972c9a08bcd231fe0e1a0fef0bafbfa4e0e027d72004075ba37d490eb9964e783bb98f9e503e9c1fd3d23fb0017cc7c7a9f86d171f041e2355d8c5e6229d34c7eeacb6358cf3060d5d265bae2004a558878659a30dfed5f2ec788b4e14397b5d00c29db5d4ebf16639a8df292a3d24f6983cbca760d903e976f5b698642ba1fed49e79c38f4bb3946efccc9d6aefad336d558f78e4f205422e10384a4e531e75807efb389d2af4cab43825fb87f196a9080769fe7585782970a6918affe10d20d629b705845597418d699de3f1de854f94bd:cf03f525913c44303b2f80079393c21c1158146ecf99636f5d97adfdd9f35839804c23804cbf1e553cfd4b73f689a9143aec298f8276e1e4ee0891f1ba75de0453ced9db2b479e59d3ed643f7cc3784c24b8bd4c63206c72e23fa850028899a41ce1a8bdc003f12b7c29972c9a08bcd231fe0e1a0fef0bafbfa4e0e027d72004075ba37d490eb9964e783bb98f9e503e9c1fd3d23fb0017cc7c7a9f86d171f041e2355d8c5e6229d34c7eeacb6358cf3060d5d265bae2004a558878659a30dfed5f2ec788b4e14397b5d00c29db5d4ebf16639a8df292a3d24f6983cbca760d903e976f5b698642ba1fed49e79c38f4bb3946efccc9d6aefad336d558f78e4f205422e10384a4e531e75807efb389d2af4cab43825fb87f196a9080769fe7585782970a6918affe10d20d629b705845597418d699de3f1de854f94bd: +f64a66ba0f0819f3001416c220bf52d860130a19764aa8ab38d15b2aa75ac0228125253cd337e00d45b45079b585349561e5f542a81f6d2fcfd985c10feab2af:8125253cd337e00d45b45079b585349561e5f542a81f6d2fcfd985c10feab2af:8072862ed0ab35921db5ec2cba8e6aedb0441fdf47491006c01e6456ad70fae3c4152dcfbfdbb8f0fddec5e96b12bf67989ba96793f4861a11b63909ce8d19b8ca64a544b31ce051fbc88e062806d9965cbd2967b01614e86b532fbf59843218dc9c19c80315f044731719371092a3da38878bc4cf77de972e860466b8fc45e465dc3d0ebf94bdea60ef0b9891ced41b997b11b31ee4167db60c9cfc8b85beacfe223cc1829213774085d7c06d2b2e632cc21cd9660df47c4fa918bdd596ddf622dcb652642b67527ba8ed15a819a8e21f48d7ee70247f5200e37c259dffd17eec8c232f970cb03182fe3964132993f6ecb7c4db18ccef390c9eb3639e:4de6f5250822d7c9d5bb98582500b5c085f541ebdc450ed1acaf83684827ed1dc77147aae4b19e14a7dc5bbe1f1e4f5771d8a6e4f2351739afb08c806d5587018072862ed0ab35921db5ec2cba8e6aedb0441fdf47491006c01e6456ad70fae3c4152dcfbfdbb8f0fddec5e96b12bf67989ba96793f4861a11b63909ce8d19b8ca64a544b31ce051fbc88e062806d9965cbd2967b01614e86b532fbf59843218dc9c19c80315f044731719371092a3da38878bc4cf77de972e860466b8fc45e465dc3d0ebf94bdea60ef0b9891ced41b997b11b31ee4167db60c9cfc8b85beacfe223cc1829213774085d7c06d2b2e632cc21cd9660df47c4fa918bdd596ddf622dcb652642b67527ba8ed15a819a8e21f48d7ee70247f5200e37c259dffd17eec8c232f970cb03182fe3964132993f6ecb7c4db18ccef390c9eb3639e: +8439b1d60aa48460135eb1002cc112792995079a77e6e8ab020b9abaca8920b4eadc3e0c5bddbc3052c3b2f8b0a94566c2b2c879ed17034ac0e6a45f2b3e32d2:eadc3e0c5bddbc3052c3b2f8b0a94566c2b2c879ed17034ac0e6a45f2b3e32d2:5419f6d24eb46635d4a7f8eab803cfd0d04de092afbd86f2a6961a8d1eb8c0d197ba55ee08c991822a5aa702bae0337abd5ca7faa15e1f1ae369946e9b81216c0f5fc22bbd4433c3de93c5caa2741683bbd0e1a78df28dda19174101876334d40339659f021ae766162c6cc5421b79cf9d5c090ed4af07ec84493035bd0b2421b533684295bbe76a70fec596ef8c89c5c9dda3c33b7735d2d2f20b28f1a5402e72d04ba291dd59f14af08adf56eeb086d769c6bec3451891372345fd6bd02dcf95e803af0353150e182e323aaf683e036d9a135d2e6f98cb4d327e2ce7d54247f3592ed067b4ce7627174f996f28165c9c11f07e5ee9cee63851c6b68ea2:62da81e16440821b593b6ee6540e15d1aea75d23e0a1bbfedc808c9548f87e8bbf36915a39a74716f645cca5714d170af907576d4f3705e543d2adddc5ff23035419f6d24eb46635d4a7f8eab803cfd0d04de092afbd86f2a6961a8d1eb8c0d197ba55ee08c991822a5aa702bae0337abd5ca7faa15e1f1ae369946e9b81216c0f5fc22bbd4433c3de93c5caa2741683bbd0e1a78df28dda19174101876334d40339659f021ae766162c6cc5421b79cf9d5c090ed4af07ec84493035bd0b2421b533684295bbe76a70fec596ef8c89c5c9dda3c33b7735d2d2f20b28f1a5402e72d04ba291dd59f14af08adf56eeb086d769c6bec3451891372345fd6bd02dcf95e803af0353150e182e323aaf683e036d9a135d2e6f98cb4d327e2ce7d54247f3592ed067b4ce7627174f996f28165c9c11f07e5ee9cee63851c6b68ea2: +3a046397f0afc072bc7f907c74d38fd1b9afdf27e14a3534768b0dd2df3a1c2299cd70ef3be342493393872f54c47deaa081021892d11a3268f3145ed4f3abe5:99cd70ef3be342493393872f54c47deaa081021892d11a3268f3145ed4f3abe5:f08ddef46cc6c34179820c9861375172fddf774f8dc3f7d64aa432da8e5fae644c0a8a9e6908517d505debd612868ac6daf95cd7e1699750022ccd4b88dbae2bbf73546ee4b835d319a842dae8b9ed683323f31e5cc57919bc9dbe3bcfffb2ada48072697ff4a7d310c91adbca81faf26a0eb7bb0c404ac9d8dfec63e9c64e2f420c07d323b7c0dc3b73507283aeb1cee51db4e1a83a692c7c1ea398f6f30940fab85e2138d4b85aa4e231e5424f5b064ed026f0ccb99d1c85a9eb15f5934a11359d411cf94ae8ffa3361a224f46bab852d184a248b4c31fe3a7e7f5134c051031a9f328a7be4a7cbbb1d8d863a400fd2d58daa44f1b9d8e9ddf961ce6322f:5024ce60257965687080c5b1fc7d1301c32aa6fcc835497d9cb23a74a6ca2724f55353c1b757827ca5440c9ef8f8c1050913e20aabec35c497b56041b5deb209f08ddef46cc6c34179820c9861375172fddf774f8dc3f7d64aa432da8e5fae644c0a8a9e6908517d505debd612868ac6daf95cd7e1699750022ccd4b88dbae2bbf73546ee4b835d319a842dae8b9ed683323f31e5cc57919bc9dbe3bcfffb2ada48072697ff4a7d310c91adbca81faf26a0eb7bb0c404ac9d8dfec63e9c64e2f420c07d323b7c0dc3b73507283aeb1cee51db4e1a83a692c7c1ea398f6f30940fab85e2138d4b85aa4e231e5424f5b064ed026f0ccb99d1c85a9eb15f5934a11359d411cf94ae8ffa3361a224f46bab852d184a248b4c31fe3a7e7f5134c051031a9f328a7be4a7cbbb1d8d863a400fd2d58daa44f1b9d8e9ddf961ce6322f: +124f7416a80453e4cf1cd7b5e050a9761418258bf7d27beb7f23238c4540be2d0da34ab173990150df7399b6bcddba93c6dbcbf4d176941cb5071e8734c5dc92:0da34ab173990150df7399b6bcddba93c6dbcbf4d176941cb5071e8734c5dc92:9dcb9873ff054db11d0a9b19de6885ffba7f0e681cf7fb8f6cd950c48328d1f919ca46054eeee6c9e57843ebdda7b24bc3503c4d612abb1a314f39f58221d2b54dc755acca7969740e7fa8b1a9523b8c7379fd395253f4e6cd054ee24b75613c3581d49e19246a7b3be1cecb334be44f3d626fe3b7b269e628d44580c20636eba2642f2744b959e65757d0ee601843f188e95d17253fef567068a5405a3a9e677fea3d7d55f7ead19a3f30c5f985671b55fa120cb9d05f471b6e1e8d779a2c803a19e6d0d7cd507887ed647c2a95483f933991ed45ae301a2b0e954a5703d248c78810aa0b199cc2bebb2f1d71cc40487dbd42eee0f745f7d285685b1fb31b15:b0572104aa69e529e3465a6fd28f404a4ec20276a993b1725eb8c5f650b4a216f1871b24e368cc46cd1ee0174cda1b5e4ae2200aa9fc44522d975a9c518149089dcb9873ff054db11d0a9b19de6885ffba7f0e681cf7fb8f6cd950c48328d1f919ca46054eeee6c9e57843ebdda7b24bc3503c4d612abb1a314f39f58221d2b54dc755acca7969740e7fa8b1a9523b8c7379fd395253f4e6cd054ee24b75613c3581d49e19246a7b3be1cecb334be44f3d626fe3b7b269e628d44580c20636eba2642f2744b959e65757d0ee601843f188e95d17253fef567068a5405a3a9e677fea3d7d55f7ead19a3f30c5f985671b55fa120cb9d05f471b6e1e8d779a2c803a19e6d0d7cd507887ed647c2a95483f933991ed45ae301a2b0e954a5703d248c78810aa0b199cc2bebb2f1d71cc40487dbd42eee0f745f7d285685b1fb31b15: +25d13b3837601b07a975693e5a33d5337c34c1127fe4c27490612aaf7f642e9a3a07cd68ee2692d51cfad1a80e7763b18a043c74f4e1b01edc55ba9a9e07795a:3a07cd68ee2692d51cfad1a80e7763b18a043c74f4e1b01edc55ba9a9e07795a:115b3220b45ca8f36c7ff5b53887d47e669b78dac13b98cc7aaca5c2e19fce81ec8617ca410e11c9a9118a668453b329ffb718eaec739172f0a849a0848192a5bdea18ab4f60d8d1a0d338952d77b2cc13efe83c76e8dd58803b1d8b3c9729ef102b20835b7de872bef3010f15a4caddf07cf7bdd222d84b174bc21527cffb1b7ffde81e281d30cb7bce25ea3dffb6ea1fbb06cb70569a95ed1a07e97ca42de70aa218159efd608fa9b0896e0b58518a322f251d133e58c8fc1428ab0a170ed845c75fb403f1ffb97d2d2a6d4f277911d326c1cabbb8516cbc17908ab81ff8d79af44611ea1d05879c1ec81d06936e0f4a0aef6d5748e181d30ec25236597a973d:20cbf08392fea6a99cf446a95c199caa0c0f9813cc217b8d228e2ed90bab95ea92cd73ac95834764d33e42243c80a7603491c8d3e49ac715fd8a5b9e4789bb03115b3220b45ca8f36c7ff5b53887d47e669b78dac13b98cc7aaca5c2e19fce81ec8617ca410e11c9a9118a668453b329ffb718eaec739172f0a849a0848192a5bdea18ab4f60d8d1a0d338952d77b2cc13efe83c76e8dd58803b1d8b3c9729ef102b20835b7de872bef3010f15a4caddf07cf7bdd222d84b174bc21527cffb1b7ffde81e281d30cb7bce25ea3dffb6ea1fbb06cb70569a95ed1a07e97ca42de70aa218159efd608fa9b0896e0b58518a322f251d133e58c8fc1428ab0a170ed845c75fb403f1ffb97d2d2a6d4f277911d326c1cabbb8516cbc17908ab81ff8d79af44611ea1d05879c1ec81d06936e0f4a0aef6d5748e181d30ec25236597a973d: +7b3a76decaea60c41e95b05877a7da82064c27278c8d7df5f0bb95f0ad2d0435f80db5c28721b1c611bd87eb145a98bbf383b068045df2458d1a6fda099f7fc2:f80db5c28721b1c611bd87eb145a98bbf383b068045df2458d1a6fda099f7fc2:375fadaedd9cac49b64e1574028046069f4c83654c8a7011abdb64db16b47fa311798172f9072217b0a6a43e5df6ffcc1154bcec1c68e1d35ec05880d012ce76e4cebf301bb2ec983d00b4a0540c937ff1c6df9441c61bdb3be8e0c7c11a35d49b6f55c381269a0e768efbd453447fe48b75ac39646ca82eca7d149304423491871c10dbcfc5973a57fab8371c30cbc4e90becc0b67152226ee177b4ff368ec879b391eb95e36dcbb07b2c16ba395545d4529f727b1a11ef65d120976b7ccc86af4bd204cb9489c921e43ba5e850cfe59899f1c1ec4aa5c92b6dac6914b1952b53dcb540b409231381568987bb2236bc40895df3f17eab7c0274f2244f958612e88e:2cd26fb3c4f7440a72affe93564f6f6559adb15cc7a2ba10879fb7d67e47d4ebd02fe4823698a5fbd4a907fd69184c255a170e5f1747fce968102dc219b50d02375fadaedd9cac49b64e1574028046069f4c83654c8a7011abdb64db16b47fa311798172f9072217b0a6a43e5df6ffcc1154bcec1c68e1d35ec05880d012ce76e4cebf301bb2ec983d00b4a0540c937ff1c6df9441c61bdb3be8e0c7c11a35d49b6f55c381269a0e768efbd453447fe48b75ac39646ca82eca7d149304423491871c10dbcfc5973a57fab8371c30cbc4e90becc0b67152226ee177b4ff368ec879b391eb95e36dcbb07b2c16ba395545d4529f727b1a11ef65d120976b7ccc86af4bd204cb9489c921e43ba5e850cfe59899f1c1ec4aa5c92b6dac6914b1952b53dcb540b409231381568987bb2236bc40895df3f17eab7c0274f2244f958612e88e: +5ff8d4052608eb033a5e94b603ce384d8452f60a26498b9112567f3410c18666c4900de24d9af2482763109926af7c481380fabcda9440c1a53ea1cdc27e6568:c4900de24d9af2482763109926af7c481380fabcda9440c1a53ea1cdc27e6568:138c60557c2e9008afc03d45bec71f961149a0835926751c8ff3935c7d652d83e1b0b1da7d5bbe0b8e171a4e49aae06fd8a9deff78dcde4d25b1aa899998a0f99e1df6f9337a3ea2f24b76c317a7014db4e5283191795a70d8821d217846490f958701d39dc2c8ce47d928938874d87b3558989bc77af820979a351eef9594aa5b94f3341eded4ea20b08c3e7c5610d43267818dfac0a87ddf527fbce8512bbf85b66c9bb5d62f0fe84048f23b19604a5c8d82b1f25a8da02731feb2ecae489b8475f7bd326ddf1a08189e46c08cf50538c2a363e2f4eb2c01a204c7ffbc0b981adc0fd997aafdf2a222ee84c309f6e95ec7de4fa85d4768d5c003165028225e22e09e:b737d4e5be27deb6d87729c636dff7a406c013f313c38cf683fe14f75a3b3005d9535d7e5815c8f8b37c51d6927111c979f7d9d81a347aa9cc09ed4e6c18e90f138c60557c2e9008afc03d45bec71f961149a0835926751c8ff3935c7d652d83e1b0b1da7d5bbe0b8e171a4e49aae06fd8a9deff78dcde4d25b1aa899998a0f99e1df6f9337a3ea2f24b76c317a7014db4e5283191795a70d8821d217846490f958701d39dc2c8ce47d928938874d87b3558989bc77af820979a351eef9594aa5b94f3341eded4ea20b08c3e7c5610d43267818dfac0a87ddf527fbce8512bbf85b66c9bb5d62f0fe84048f23b19604a5c8d82b1f25a8da02731feb2ecae489b8475f7bd326ddf1a08189e46c08cf50538c2a363e2f4eb2c01a204c7ffbc0b981adc0fd997aafdf2a222ee84c309f6e95ec7de4fa85d4768d5c003165028225e22e09e: +eedefc1757e3a7e5ed3946dbedc396a362f683d2c51b0b9f60765d4bfc5134dea9872bc2192fc02b189ceed403ab9f270a032a835fdebfaf1c9d6934ed8304bc:a9872bc2192fc02b189ceed403ab9f270a032a835fdebfaf1c9d6934ed8304bc:b194db73f994cbdc3cbe630ba72c47c2249bc0592ab547942b1d1b882b44f5b3855e568bdddf92ef05022d88fcfc294e76b64a00e9c74355373763e49a4ebc47243d48a9ad588994a518f80f8615c2b31da587a53e529d435a8697350dfcde02d20cce7d5eeefe3f5ab2aac601259cda38538a1b8301f9832e75ab90f8a932f267eac181003965d5266f206180c6c380ece803577ccb46176bf607159486f24259747e2ca6fb1912db7b78a973b2846387c1208030ee1f400d0c5b5e8bde9635ae55638ba17c734de8638bb85dfcd76629a7f9f40d6ab954d55bf8575fc9c9a595097e0893db5a7b8a6c455ecbd3d22d725e19de2941f467f9eb93d66a0e2bbdbf92ed1c:d5bea8ea9a5fe9ed6d2bf839930c0c6cd5039e988f551fdedb5437e1c1af0ed7b3897c035711c3c51926be8d1b32024d5cd582f5f8369ad84d18b12502652f07b194db73f994cbdc3cbe630ba72c47c2249bc0592ab547942b1d1b882b44f5b3855e568bdddf92ef05022d88fcfc294e76b64a00e9c74355373763e49a4ebc47243d48a9ad588994a518f80f8615c2b31da587a53e529d435a8697350dfcde02d20cce7d5eeefe3f5ab2aac601259cda38538a1b8301f9832e75ab90f8a932f267eac181003965d5266f206180c6c380ece803577ccb46176bf607159486f24259747e2ca6fb1912db7b78a973b2846387c1208030ee1f400d0c5b5e8bde9635ae55638ba17c734de8638bb85dfcd76629a7f9f40d6ab954d55bf8575fc9c9a595097e0893db5a7b8a6c455ecbd3d22d725e19de2941f467f9eb93d66a0e2bbdbf92ed1c: +09d22bbaa5956cfacbbf9fd5510975128686c40c6ea96b89ef4c0f0c649bcd7fe559ea8acbdc61b6709a7d83ae15849a6c78b203923dd0a299239ee4886930ba:e559ea8acbdc61b6709a7d83ae15849a6c78b203923dd0a299239ee4886930ba:1c26a0f3a1a5b2d7d5b297af8a6a689d7c62a25267e197d23becd2f2b816c4de92fbdaffb941c3fc8db7a84335a84cfbc92cb3ac806ed58df16b6b8e119a48df4f27c71e931a5938e7d002734885e13a258a15b6e1136efba72f1d096b689f7618f49c968063e8f991fa0b55601e430eee13492a1b09413eb23813591a7a9f070cc396ca9d1facdd4f4ce37c40f7245f55035e10fad6b85b5f01a1daacc0df94069f7de8f6467f96d1fb98648e8a0520a8cd723c98e9dc2dd4b2934d8228f0ae1a415bd3a7cda38d7a9983ce1af6f8c970a2a591635fe12b917536ef815eaf1a3138d70ce70a794264d7c986d9ee3290445f15a9248f2765271e5a992196ae331abd4164bf:e65275c4328a70ad62408ed7fb1728be87a73a814fee8ebd94f2665c71bc66ab0c1b07a600b30bc081a74c536857c20610384be268d9af3e3ecddd3eb0c14c0c1c26a0f3a1a5b2d7d5b297af8a6a689d7c62a25267e197d23becd2f2b816c4de92fbdaffb941c3fc8db7a84335a84cfbc92cb3ac806ed58df16b6b8e119a48df4f27c71e931a5938e7d002734885e13a258a15b6e1136efba72f1d096b689f7618f49c968063e8f991fa0b55601e430eee13492a1b09413eb23813591a7a9f070cc396ca9d1facdd4f4ce37c40f7245f55035e10fad6b85b5f01a1daacc0df94069f7de8f6467f96d1fb98648e8a0520a8cd723c98e9dc2dd4b2934d8228f0ae1a415bd3a7cda38d7a9983ce1af6f8c970a2a591635fe12b917536ef815eaf1a3138d70ce70a794264d7c986d9ee3290445f15a9248f2765271e5a992196ae331abd4164bf: +77826ed351a3f09254ae5692885d774cb3f24410a4809fd90f8a00da9aee99033eac8f41ee73e6ef136821f7957a1c27e15638d0e3916e6caac6fb7beb7bcfb0:3eac8f41ee73e6ef136821f7957a1c27e15638d0e3916e6caac6fb7beb7bcfb0:1ff06c0b3999cecb1900a47d267beafbb35d93d14cb2c8925e3e3fe5d967586925ee4baa41998edd0103205810aad5c0bbdc77874476810246d13089a64db576424fae0bed9664a42a491147d1ee3b9c3b1ba4875be15462392540f9978d9a4630ba4c525499751a45efc299ec7d73b17f9ad275ee71a687e72690d7320242d2dc2bd4d5c5cf0f17a465185dcf60f8efff53903f20b0c2ab2192d44368f2f2fb36048af071f7aa857b14ad1d11461205bebe17e02be2e3ccb6092821885c4e0d4811be3f45b1fea088453e022432f562562b43a355cb56270cedb6c2c42dbf9be850e77192fdc65cfd36834be988dbe9a93e2518c138b090fb9da827cb1c91c8fe52fe7c57f7:977adccdb829b40bbd8e53856a783db346a39dff62041a2972d29009f1c9ff81b8ad54cb901e497c1d3021b50b6c69ee73558fd7be05d625f5727f9af2ce87021ff06c0b3999cecb1900a47d267beafbb35d93d14cb2c8925e3e3fe5d967586925ee4baa41998edd0103205810aad5c0bbdc77874476810246d13089a64db576424fae0bed9664a42a491147d1ee3b9c3b1ba4875be15462392540f9978d9a4630ba4c525499751a45efc299ec7d73b17f9ad275ee71a687e72690d7320242d2dc2bd4d5c5cf0f17a465185dcf60f8efff53903f20b0c2ab2192d44368f2f2fb36048af071f7aa857b14ad1d11461205bebe17e02be2e3ccb6092821885c4e0d4811be3f45b1fea088453e022432f562562b43a355cb56270cedb6c2c42dbf9be850e77192fdc65cfd36834be988dbe9a93e2518c138b090fb9da827cb1c91c8fe52fe7c57f7: +99a99531c3cd6e3e9c900a9eeb26267e72f09d11b651a897ebb79be016f64c6e9bf9f8b48a2728e02608fc19899d219656839d1cc1e9a8984df674ec26662f41:9bf9f8b48a2728e02608fc19899d219656839d1cc1e9a8984df674ec26662f41:7a89c0c1952fdc4298dcaea854efc134656be147e9e8e82fc9a449059d80570f75676b81c4a94f76a968200cdeb0988c73f59afc72ad4c3103e19fe63b7e95e140b5cb2efc7b97a6ffbb6c298ddace3be6d2ed3d598b8bdf0c2fe6c97602142a76e978514c196c1b9a88efdc1925fc506155cff9a2f21ab634e2b93e96928a5d8f7ce4cb7326d9689469242ba9c6a01b77496badef87578f5a17284e900a72df141c6199b0e71ab5da4375037617ec6196d4f4e23ae2916a72d0fce796022305ac9fbbbbe4705b340e42b78e1c02bb1001860cdcaf71ed89255dd56cc0b31c59d4596dcef84e22234be562bd801e94111d83a78064c90f9d82fce91f68abb03c73b6bd8d7e02d4:0e89da5d949cf2bf40c7e17c2d0f9ceabc88a092eb4d49cfbfeab7c8bff43245c67b9e2e92f9bcb9b34b3fcf8b01fa2ea7a9649f814c3aa98b3dd04540c31d097a89c0c1952fdc4298dcaea854efc134656be147e9e8e82fc9a449059d80570f75676b81c4a94f76a968200cdeb0988c73f59afc72ad4c3103e19fe63b7e95e140b5cb2efc7b97a6ffbb6c298ddace3be6d2ed3d598b8bdf0c2fe6c97602142a76e978514c196c1b9a88efdc1925fc506155cff9a2f21ab634e2b93e96928a5d8f7ce4cb7326d9689469242ba9c6a01b77496badef87578f5a17284e900a72df141c6199b0e71ab5da4375037617ec6196d4f4e23ae2916a72d0fce796022305ac9fbbbbe4705b340e42b78e1c02bb1001860cdcaf71ed89255dd56cc0b31c59d4596dcef84e22234be562bd801e94111d83a78064c90f9d82fce91f68abb03c73b6bd8d7e02d4: +aa58403e763bac405db065eb11eb6be3e3b6cf00ec4a222b52bff4b6e3d156ac167f9b9a4665f93f5d7d3016ace6fbd13420b2e51e72bde59eedf26993b66cae:167f9b9a4665f93f5d7d3016ace6fbd13420b2e51e72bde59eedf26993b66cae:3baa0998ff02b32b90b51f9a840c7b5c5870cfb1810a9b0f77b55909d47ad335147a991c29fbebfc592e9307175c1964129a2d5efc6215807453bcd726969781222bcad1c99a49748b9ee667c4d0c82889e2f50064c115dbd8fb483d72ab0ccadf76bddb2dc727dbc3fa5c4624c283d8921c8aa4425110dcdd69c05e5ed59b359625eeaaec1e27eafe9d9a5ce736c3f9c527ea547818b9bca6811be4cc15058a6f5b683303b80c90c94a83b8b15869713a66b1e0f656331b286d1ef7698834ab3e138417aad6bb3ab3bd9fc78761a482dfc654f3f8628c8d9fc16018898f1641e8622bd272e38d41706cb9cebe6ee5e173576bf61bb1188cf2f39c62220bba88fcb4de4898b25b04:64b598ca5b8f9ae742e46ee0d8c1aaf31458b50c25d267a677e44be5b755f14d51801a30399bfcc38d14071aa0ae93da825a581ab6c20725a0a910b4735dfa0b3baa0998ff02b32b90b51f9a840c7b5c5870cfb1810a9b0f77b55909d47ad335147a991c29fbebfc592e9307175c1964129a2d5efc6215807453bcd726969781222bcad1c99a49748b9ee667c4d0c82889e2f50064c115dbd8fb483d72ab0ccadf76bddb2dc727dbc3fa5c4624c283d8921c8aa4425110dcdd69c05e5ed59b359625eeaaec1e27eafe9d9a5ce736c3f9c527ea547818b9bca6811be4cc15058a6f5b683303b80c90c94a83b8b15869713a66b1e0f656331b286d1ef7698834ab3e138417aad6bb3ab3bd9fc78761a482dfc654f3f8628c8d9fc16018898f1641e8622bd272e38d41706cb9cebe6ee5e173576bf61bb1188cf2f39c62220bba88fcb4de4898b25b04: +1044ee3708c0b0e909a8cb2ba2cd0af8d28a5de01d962e826087fb232df7b2d246d241ea0c702c1889d44655824629b67284d4e644a48fa45455d27ac5f62529:46d241ea0c702c1889d44655824629b67284d4e644a48fa45455d27ac5f62529:b8a445455fb66e17e3143d35204c9ea93474eebeef93963ee5c1d377ca217acd4ca63e5755da08fbffdbd4352bf165193896c8d6f76bb4cd3bc2d3a476a4e320824a1210ce74d0014d747f111eec310c5c89ed4d0850e811f80a8bb28dcaf6f411df83e2c1dfd90c4ad23561454eb5d756b63b4ea7f37dc5d466c16ef70d11190c4f5316fe2aa8597440e88bbebaeb35ea5f04f07b0339264158ef909ad5163bfc248cd724133e274f812695f290e57176a96b9393d07bb310299f5d2a6b6dd1dabcb51bf29c5afa7ebb0701c6c84767ac137793091fe0ed6e47d780628a32c84f83e00e9c16742a523ecb63c24f4a338ed299a06194924f44c5a5d3c937ff9b0945982ad24a2d1c79:7d6bed7f87d090abe013c31e1203903bac9c93445d06c7b53d31d15f970d88647a7ed2c3a63050ba19d68043aadd18bd861de1ac4715b8e828b2b16f8a92b001b8a445455fb66e17e3143d35204c9ea93474eebeef93963ee5c1d377ca217acd4ca63e5755da08fbffdbd4352bf165193896c8d6f76bb4cd3bc2d3a476a4e320824a1210ce74d0014d747f111eec310c5c89ed4d0850e811f80a8bb28dcaf6f411df83e2c1dfd90c4ad23561454eb5d756b63b4ea7f37dc5d466c16ef70d11190c4f5316fe2aa8597440e88bbebaeb35ea5f04f07b0339264158ef909ad5163bfc248cd724133e274f812695f290e57176a96b9393d07bb310299f5d2a6b6dd1dabcb51bf29c5afa7ebb0701c6c84767ac137793091fe0ed6e47d780628a32c84f83e00e9c16742a523ecb63c24f4a338ed299a06194924f44c5a5d3c937ff9b0945982ad24a2d1c79: +95dd1a5e658fa6c8d42507b3e5b8edb5baeca62deb00fc5d4dca8e1ab5835e593a5323dd1e07f323bb6d83e9c2db92a29f62e2e003ee0deacd7e2e4e030d8d27:3a5323dd1e07f323bb6d83e9c2db92a29f62e2e003ee0deacd7e2e4e030d8d27:9b7afd48c474604c26367531556840c388668b0f3840063dfc9869ad5b901274b931293d04f3c8e8f7f8eab815a641d7c351284e8bb0437ac551bb29438964e6a7c7ba772344b333f9eda5a77568c8931ddcaf21e32e07b10bf4820fb859bcf87b81c4bff426f24a4d468f2e9aeda8f17d939709970db11df76247e98a39eb8b38f5949f349f2ae05ab48c018517c48fa0205dc7f1566453e105e48c52eb455c0c40802f797b3eefb1e2f3b1f84315aed5b0711c6499a691b74b91f12ef70f76c4c05c1aa1a993e2f3e528ab343dd2368162f4036a61a13a88045dcdefa85d68532275bcf5b8f5f00efdea999a95783175d9ee95a925d48a544934d8c6b262225b6ebea35415dd44df1f:d02a7523dcbd29576ba809b531037774df41734a41175813119c6a6a788cd9b8ad780865678667699ae66d010919a966a051c08163df67a977ee6e220d0dc30f9b7afd48c474604c26367531556840c388668b0f3840063dfc9869ad5b901274b931293d04f3c8e8f7f8eab815a641d7c351284e8bb0437ac551bb29438964e6a7c7ba772344b333f9eda5a77568c8931ddcaf21e32e07b10bf4820fb859bcf87b81c4bff426f24a4d468f2e9aeda8f17d939709970db11df76247e98a39eb8b38f5949f349f2ae05ab48c018517c48fa0205dc7f1566453e105e48c52eb455c0c40802f797b3eefb1e2f3b1f84315aed5b0711c6499a691b74b91f12ef70f76c4c05c1aa1a993e2f3e528ab343dd2368162f4036a61a13a88045dcdefa85d68532275bcf5b8f5f00efdea999a95783175d9ee95a925d48a544934d8c6b262225b6ebea35415dd44df1f: +1abc0b9aa01dc57ca53efe7380962b1a88d50a964f5cd98640982c74393f29268d4fd14394d7c1405700306983fbf76ea9f171b15a6b56612a1feb1cbdae5dd5:8d4fd14394d7c1405700306983fbf76ea9f171b15a6b56612a1feb1cbdae5dd5:da2dd940d5e1db6e80bf7e2b782e7e745cd4fd252e981517975887dd05ac77ed837d082961575efedf301fdf24b70718b991b8d92bdd2e6bee17c8aa4bc694a727bcfc78fd85195c42caf883a2c38d161cadd79cfda9a39110e1264d30bd4c5c4a5876777f233b071b1b0b408935f0468954cc744af8063b004ede56cd981c4dd5608abffeaec9e58f3fafaa671467804b7fa2558f4f95174201f183d80a5914065fed53115b41ebc338f78df050053b8a4e75ea7c6fdc354dad27bfd8a2e66fcd7ae2f587d24be0d4a33da30a220e51bc05fa4e412b959fd95d89ea6ec0162516c096a9433a9e7cf599c928bd5305c2173bf7493ed0c1c603cd03f082cce44237a79ffd8be9a672c2ebaa:f738af2d3e290b3d23d9aff7414bfc5ffa47235dc053687a8ba5c8541b8511f781566cdaa130e0677db55fa8be9d81a092cb58923a8628494d2f62d95c167100da2dd940d5e1db6e80bf7e2b782e7e745cd4fd252e981517975887dd05ac77ed837d082961575efedf301fdf24b70718b991b8d92bdd2e6bee17c8aa4bc694a727bcfc78fd85195c42caf883a2c38d161cadd79cfda9a39110e1264d30bd4c5c4a5876777f233b071b1b0b408935f0468954cc744af8063b004ede56cd981c4dd5608abffeaec9e58f3fafaa671467804b7fa2558f4f95174201f183d80a5914065fed53115b41ebc338f78df050053b8a4e75ea7c6fdc354dad27bfd8a2e66fcd7ae2f587d24be0d4a33da30a220e51bc05fa4e412b959fd95d89ea6ec0162516c096a9433a9e7cf599c928bd5305c2173bf7493ed0c1c603cd03f082cce44237a79ffd8be9a672c2ebaa: +cbffce2c9bd3e23e406e5f66e632dcfa726654d29a955cec983173235fa359d049653edd64a55f7cd40eaf3f8e72eb96dbcdee398f34817f2c95867949710b14:49653edd64a55f7cd40eaf3f8e72eb96dbcdee398f34817f2c95867949710b14:1ffde6826e4f0c24a7961f191e74cc0bbc928e3f1aec3efab32765c2501cbc1620e7ee6f61fccfb00cfca9fb98143b529bcc8c3d0fdf89ee7c342f101815fabf7deaf9f302a288fe175826d590d99ee6fd92da74f9596b783c0e7d47d711a32f39ea4165e5212431441b498c6b70db3b09d1f4e4a14a6bae39da5088bb85b3285ce9df2f90681af2c74dece439aeb91e1c1b0712eddbee8d72569828f37cb720c509d02aec476070484e9b16ec7179947ac96caf0e1be8b6b74f372d7235fe6e3999df733bccd482dfe2e631f56b582667dce5e3121763adfacf3b18cf2095f7394dee4927fc2bea6b5824d90cd59e854ec5872b4551b02efaba5ad54a9b7a8f6de5d7cda5825b325b076ded:e7ced4fa2a7dff73f1068bbad0ec9a1109043c97a62effa148876f0969ed4dc608e28bce797af3b82532c94dec4d6811b7f563679129facf17bb73d69375eb051ffde6826e4f0c24a7961f191e74cc0bbc928e3f1aec3efab32765c2501cbc1620e7ee6f61fccfb00cfca9fb98143b529bcc8c3d0fdf89ee7c342f101815fabf7deaf9f302a288fe175826d590d99ee6fd92da74f9596b783c0e7d47d711a32f39ea4165e5212431441b498c6b70db3b09d1f4e4a14a6bae39da5088bb85b3285ce9df2f90681af2c74dece439aeb91e1c1b0712eddbee8d72569828f37cb720c509d02aec476070484e9b16ec7179947ac96caf0e1be8b6b74f372d7235fe6e3999df733bccd482dfe2e631f56b582667dce5e3121763adfacf3b18cf2095f7394dee4927fc2bea6b5824d90cd59e854ec5872b4551b02efaba5ad54a9b7a8f6de5d7cda5825b325b076ded: +9f91231497484cab39b9e20f861181d397908577bbb2968242d071bca4813ffb8824bc6cd6a6f15a5f41668f2b3bae8fc4967383078d08b51d6d1b2b93a1071f:8824bc6cd6a6f15a5f41668f2b3bae8fc4967383078d08b51d6d1b2b93a1071f:21d4fbc98163c3fb6e09f775c2ab7b18b18792340bafedacb49605622e3c08aa3b2b8d0e0902f361aa1c0f652e2732b10a0c5c6a05098996b588267cc8951a78b5d431e7222bbb508eeef1b5e8b8d01d3991e18dddc6ca8d222ef177ce62938d1810eecf06f4738b28f440946ccad2a12e39d38611bed3a39f93419a179ec2b1b52d5fe5c80c23b84d8803755f5146092cc199b4bdcea5bcf2037bd53ff6346694155f027d8ce2baffe30a5666596c00783aaeade9c77fc8637942ece017d6484c2899b1918d3a480bd5157678d4772d271f9b99768ee1bcc46b2489ae87cd030f47d1333c7672cb902cb4f5fe746e853de57940ba2264d3e629644d653a5b7af78ce64a993f36250f8cb7cb45:0a1c706dd8a13077ab18386c65fa97cf9dfc43542d1846ecbddeb7b3c93f3c66f3ccd0447aacdd4dad8fbf736c4ff9dbdb62bfc14d8883e385bce9bac56a350c21d4fbc98163c3fb6e09f775c2ab7b18b18792340bafedacb49605622e3c08aa3b2b8d0e0902f361aa1c0f652e2732b10a0c5c6a05098996b588267cc8951a78b5d431e7222bbb508eeef1b5e8b8d01d3991e18dddc6ca8d222ef177ce62938d1810eecf06f4738b28f440946ccad2a12e39d38611bed3a39f93419a179ec2b1b52d5fe5c80c23b84d8803755f5146092cc199b4bdcea5bcf2037bd53ff6346694155f027d8ce2baffe30a5666596c00783aaeade9c77fc8637942ece017d6484c2899b1918d3a480bd5157678d4772d271f9b99768ee1bcc46b2489ae87cd030f47d1333c7672cb902cb4f5fe746e853de57940ba2264d3e629644d653a5b7af78ce64a993f36250f8cb7cb45: +1e2bd5487c5f5ced461f604dccb4e78eb91608f0b821f5afc4e3e534f7960392ef825475cf2051a2017ae532f077d96774347d2767ea7b45f9c1b860ab993506:ef825475cf2051a2017ae532f077d96774347d2767ea7b45f9c1b860ab993506:1dbbbb13cdad88854b809ceded273343d306a8deabf3ff02c9cec6f002b8e9e10ef5d1b0f5711f33267aa91c171b61e960f740457b81d751a473f44f750a080cab80af7ccca7dffcfac9ee4c39dc85cbdf51259ccd3470d9bad3ad30f4ee5dbd4fac6bd5c6c4df7311a470044695a7e1a7e18572207588afa57eebcd4d575b6d424457ee92465ce1863e3c677cf875fdb98d4078ebe7144260807052577144cb8e0359aa42ad155d79dae3deb99c4632c191c799cbfe587d954787068d663bdfc0fab1334f1876bf498c4db5c53db7b0204ed5a521c62f09eaca8d0189f3b394143f29c421cb5c8d07bd751baf4cbe3bf4be1701df4b2207dfb2904d84f4dbda51cba576d5a5bb16efe698edd608:4d33c96a2e3a5db7391adf65c1cc3565fe76eeafd0b5c7abb0b492a0b51e1fa33639946a243b2ddef357552298ce0aa95eac6fbfe660988271877eb2a7da18061dbbbb13cdad88854b809ceded273343d306a8deabf3ff02c9cec6f002b8e9e10ef5d1b0f5711f33267aa91c171b61e960f740457b81d751a473f44f750a080cab80af7ccca7dffcfac9ee4c39dc85cbdf51259ccd3470d9bad3ad30f4ee5dbd4fac6bd5c6c4df7311a470044695a7e1a7e18572207588afa57eebcd4d575b6d424457ee92465ce1863e3c677cf875fdb98d4078ebe7144260807052577144cb8e0359aa42ad155d79dae3deb99c4632c191c799cbfe587d954787068d663bdfc0fab1334f1876bf498c4db5c53db7b0204ed5a521c62f09eaca8d0189f3b394143f29c421cb5c8d07bd751baf4cbe3bf4be1701df4b2207dfb2904d84f4dbda51cba576d5a5bb16efe698edd608: +f78db14d6d1a643dd7735baf2635321244e7ec8ca72c5c38c98c809db9cb5a555414f75f52f3864afb0c79c2c5c1d06b4bce400fbddf17fe9cfb2a8bac47a0dd:5414f75f52f3864afb0c79c2c5c1d06b4bce400fbddf17fe9cfb2a8bac47a0dd:05caf1b8edc3b173fbc1ed29b95e2bf06d814ba2407d4b31c728d04ec273d25394423ac7d4fff2ca36ee90273093c756e2bd13c96d4a3dc7f5be1759fcd328eb66c5882b58fa4588e5b2a3713a4154a2340d0b06ad019601b0e028e497f898256b028af95cd8168df5e58a57cd1ebfc0a0c91ced61dbb480aca7df8dca91eb16e98007cd2cd1a2045b0e4477d12d5a4072f365426567c9d61577f3485c8f46605e7f475ef04a3948f60dba8c5508d14bfddb9b11dd044ef2d84c16b9a9038d8e78eda43b91297df35f4361a383b41d49677a687d5b344ad1ab0fc73017b3bebf32306fb3fd7b3d5071f3ab5f6e49aa15540cad6503bea7784cf9421801ce1385839893362a97fae121300d6783af0f:d7cbd4181f67712007b7f0e18452e0a024464d9dc9b5ff9cf669d1b91169d7573262f83336b97c861bfab3fcf669223ce8caf319f21d23f1fa331a2d89b6ca0b05caf1b8edc3b173fbc1ed29b95e2bf06d814ba2407d4b31c728d04ec273d25394423ac7d4fff2ca36ee90273093c756e2bd13c96d4a3dc7f5be1759fcd328eb66c5882b58fa4588e5b2a3713a4154a2340d0b06ad019601b0e028e497f898256b028af95cd8168df5e58a57cd1ebfc0a0c91ced61dbb480aca7df8dca91eb16e98007cd2cd1a2045b0e4477d12d5a4072f365426567c9d61577f3485c8f46605e7f475ef04a3948f60dba8c5508d14bfddb9b11dd044ef2d84c16b9a9038d8e78eda43b91297df35f4361a383b41d49677a687d5b344ad1ab0fc73017b3bebf32306fb3fd7b3d5071f3ab5f6e49aa15540cad6503bea7784cf9421801ce1385839893362a97fae121300d6783af0f: +7dfa328e90a1b849c219e3da832df9ed77448234f0d89ea5d17a3d64e7883dafe30ce6fd5f5800389a70cd117364f59945afb180f229927360b06b4835f8dc91:e30ce6fd5f5800389a70cd117364f59945afb180f229927360b06b4835f8dc91:e5e495d663f47236714532687a24308f942ca9c33e088f7f106a5a723518cacbbef4a68c939a6950b2dc2589f82d354e575272d42b1383d315ab8a20aa0cdc9d4df678ab3b26612b5dca66e71f9f3fa7d9e731dc481e2bc7127cea3b6203ca6cd8162e90886a73dc46c83ddefc4b9e2d53d29dd387c624e08bd8d53be928a40a9aa8ae8b1c8d0fb6a7bd6dce5f62315b7a2181f627f256bbe7e2a95bf464e6132204c174209629840235b2c39913301a4b40325d118d384bc7ac028cd4f12702e161191b149e4209058a55122bbb8b22b24683ba4f8e2e6ccfc08dc8c8b1bcfb6d60bd8f062196933df319ab16906d085730eba1720d4b02c67daf38cce6aba38e25d68ef95b2f521913a1d77d5eb650:1c61d53b872f8cde598609682c79f6c5df007c513a71cfb3a06dcb82d85c4b00ccc40b00e59f595393088b4cd0432855c67a207da71f87e72c409b3e50279507e5e495d663f47236714532687a24308f942ca9c33e088f7f106a5a723518cacbbef4a68c939a6950b2dc2589f82d354e575272d42b1383d315ab8a20aa0cdc9d4df678ab3b26612b5dca66e71f9f3fa7d9e731dc481e2bc7127cea3b6203ca6cd8162e90886a73dc46c83ddefc4b9e2d53d29dd387c624e08bd8d53be928a40a9aa8ae8b1c8d0fb6a7bd6dce5f62315b7a2181f627f256bbe7e2a95bf464e6132204c174209629840235b2c39913301a4b40325d118d384bc7ac028cd4f12702e161191b149e4209058a55122bbb8b22b24683ba4f8e2e6ccfc08dc8c8b1bcfb6d60bd8f062196933df319ab16906d085730eba1720d4b02c67daf38cce6aba38e25d68ef95b2f521913a1d77d5eb650: +6ce13d3c2ec71fed83131a69d5d030314ab49e6565ef68163fff09ac5d9b47e79c7b1118fab91e0e7b192a23d95fb877cb7936cc6c8a330592f48e6784edc292:9c7b1118fab91e0e7b192a23d95fb877cb7936cc6c8a330592f48e6784edc292:10bbc311eb2a765e0167ff37618ff70e13f02d7b0617ae4ac06befbbe149c972a994f680ca4dc9a92ec7efa53997fad356b9ff4ebdee629541d1f4dea62ed0d2494f9ccfdf07a9310491f61c4b3e2700b4a3c668d678329a38c2eff9d8cba431fb959e7f7655bd0fbd77d53bbbc2eb8dc51dd718ed98728a181686be122b844d3da331e329d3959b5923f7734325a021026e2754e17a15108be801465ad958dbcf21df890cfe5d5b883ca43c61cedccbdb58b849ea75374f1e918e803e577a5dc7a1c17936eccfcd3481bd2b1eb075b83237ca6f3c07c19e9af9731267be82d4898eee96ebc900d48b059d51b0dd415b1c890660a88d25f5c5f35d8e45e523e0ce3336923ab43670e35c5057d56c758876:608b2bf6f6da05c2ac5bbfd795a2ac32c79c74153f9431dea59768ff4c225e3b693b645a506766b860850ee97ea43032b05b69e56767e8eb9d1918df9afba80510bbc311eb2a765e0167ff37618ff70e13f02d7b0617ae4ac06befbbe149c972a994f680ca4dc9a92ec7efa53997fad356b9ff4ebdee629541d1f4dea62ed0d2494f9ccfdf07a9310491f61c4b3e2700b4a3c668d678329a38c2eff9d8cba431fb959e7f7655bd0fbd77d53bbbc2eb8dc51dd718ed98728a181686be122b844d3da331e329d3959b5923f7734325a021026e2754e17a15108be801465ad958dbcf21df890cfe5d5b883ca43c61cedccbdb58b849ea75374f1e918e803e577a5dc7a1c17936eccfcd3481bd2b1eb075b83237ca6f3c07c19e9af9731267be82d4898eee96ebc900d48b059d51b0dd415b1c890660a88d25f5c5f35d8e45e523e0ce3336923ab43670e35c5057d56c758876: +d45ee69a5f1a7cfdd0343f8770d1c6bc026f067a70dbe839a86f2aa068c33f81fc8d9fb0e4f34793090755e0328096e01e281ea351b8d95cd9116e131a5ca54e:fc8d9fb0e4f34793090755e0328096e01e281ea351b8d95cd9116e131a5ca54e:eb5ed8ab79cbfe61c25981b9d1d6b70f10b60194b4161fe17d11aff1767994aa0813e9ece2f4c5d531b99e8adf1888c30a63893eb451aaf55acd5a52ad8c401faa88d6eacf3e49470566114fd0c6a274e9544846b0ae9bfa124d7951eb26715e19253ff7edc8a70965776f23ce46031e034a200723ba3d11e11d353d7e7cd84aede267ff64bed418cb9f28c61cd0f63b6ce2ecae14b20bc6bdaed8c428bad18be4b7d66338364acd8042a8256f258a69969b8d3ca2eab3aea3706e5f21c3b1efcc254a824bb4e7ea7aba8827c8eb82786c665aa973821931ff990a63fd34a74a6d8c22a882b0b935152ccb36fcc76f4eca65d67c8680942f75dfad073439c0916065e83877f7ba209303f33548d9e40d4a6b:156c51c5f915d89b8d1400350f8f217a5c02e2629ede9f4a30b6e71d1ea7a953cc6db31ba5c778c269920b649fb4221c6d38cf2cea2a7de3ad423e04faaa0607eb5ed8ab79cbfe61c25981b9d1d6b70f10b60194b4161fe17d11aff1767994aa0813e9ece2f4c5d531b99e8adf1888c30a63893eb451aaf55acd5a52ad8c401faa88d6eacf3e49470566114fd0c6a274e9544846b0ae9bfa124d7951eb26715e19253ff7edc8a70965776f23ce46031e034a200723ba3d11e11d353d7e7cd84aede267ff64bed418cb9f28c61cd0f63b6ce2ecae14b20bc6bdaed8c428bad18be4b7d66338364acd8042a8256f258a69969b8d3ca2eab3aea3706e5f21c3b1efcc254a824bb4e7ea7aba8827c8eb82786c665aa973821931ff990a63fd34a74a6d8c22a882b0b935152ccb36fcc76f4eca65d67c8680942f75dfad073439c0916065e83877f7ba209303f33548d9e40d4a6b: +8a76eaab3a21ec5a975c8b9e197a989e8e030899eb45d78968d0fb697b92e46d2d9c813d2d81e2730b0d17d8512bb8b5d33f436cabaa13e141ca1cb785014344:2d9c813d2d81e2730b0d17d8512bb8b5d33f436cabaa13e141ca1cb785014344:c6c78f2e2080461aed9f12b4f77c989b19716780fab60e6ecb9793b4bc7ed69e5f70fa6bdba16e9bd3194969eea6665abfd630deeefa3d717b6d254dd24bc97dde21f0f29f9ed34b8bd7a013380f4f82c984fdbd95af9805b744bcd952c5a71fbb57d11f411c18cc30bc3594f7ad8228cb6099394a1b6b0a818581bdf93cce58f3a4a23e55db3e69ca9d60cfb3a907fb68329e2ffb6c65f1e828d28127109c9e9fb70160f2ef82a2ee9f9bd170c51e13fd3fc1866b22c79fe6d5101217979dbe2724dcad8a9bc69acc42c112dc697bd271eea550e9e50406bfd28245b83b8f012d34db6dbdd55ae6e575745c153d6e7534901027eadc2fcc33a5287ddbca6d3aeab8972294dc6c712b9942547277340e7ad19e:fceecca4b014fecd90b921b0fa3b15aeaa4e62caa1fb22729c70269232c33cef0d0aeea66432c128afb9a3646bc7f03a12774da8758398c2a0dcce0bbbf6740ac6c78f2e2080461aed9f12b4f77c989b19716780fab60e6ecb9793b4bc7ed69e5f70fa6bdba16e9bd3194969eea6665abfd630deeefa3d717b6d254dd24bc97dde21f0f29f9ed34b8bd7a013380f4f82c984fdbd95af9805b744bcd952c5a71fbb57d11f411c18cc30bc3594f7ad8228cb6099394a1b6b0a818581bdf93cce58f3a4a23e55db3e69ca9d60cfb3a907fb68329e2ffb6c65f1e828d28127109c9e9fb70160f2ef82a2ee9f9bd170c51e13fd3fc1866b22c79fe6d5101217979dbe2724dcad8a9bc69acc42c112dc697bd271eea550e9e50406bfd28245b83b8f012d34db6dbdd55ae6e575745c153d6e7534901027eadc2fcc33a5287ddbca6d3aeab8972294dc6c712b9942547277340e7ad19e: +18a8f93648cdcf47133630af1e11c0ceea3de07327314c96580df775597d7a9c2912f41ab4c87e3937a03331802cba87716b4eea14b9fba6f546d0ac2c0973df:2912f41ab4c87e3937a03331802cba87716b4eea14b9fba6f546d0ac2c0973df:592093ac7cd671d6070b0027edac1fb015cc205d78bb603f378eb9f8aa388ca830db3cb23420c7e852db0b55241eb88a02cc627aa94143be439aab4bf2634757470406e842f20eb10f0700e3c2da364f588a8000f23850c12ce976f326d2df1bac13e95020b412b175bf74bd7ebbacf3ae55c0daebb5c010bf804feee1d7d49fae050bea55996f53cfe1f15a0cf20727db4ee311c260bad9682d7b965e27a9491f471d4a473aff646c7d424d5a0bdcbb8a0233f4b3060dd04c98ec98dfd05ec7247884e2d8e152d4ae52b3d5865d9efd6706a60e088e1e7c9f624510abc7a2045a2c7a7588e2535e73191dd5cf05421563f556a13e8236670343cd5ba4d466e245c4ee3b5a41e70c9a0f5e6ea2c559ebe61ba81e:3b77394cd69f8b45d00cfe3a79a7900628a56518b379ed8a11581fc3a376e5d66807df11e70904f696c741d21d139310fa1b89a93bdc4d2c3997991f5220ee00592093ac7cd671d6070b0027edac1fb015cc205d78bb603f378eb9f8aa388ca830db3cb23420c7e852db0b55241eb88a02cc627aa94143be439aab4bf2634757470406e842f20eb10f0700e3c2da364f588a8000f23850c12ce976f326d2df1bac13e95020b412b175bf74bd7ebbacf3ae55c0daebb5c010bf804feee1d7d49fae050bea55996f53cfe1f15a0cf20727db4ee311c260bad9682d7b965e27a9491f471d4a473aff646c7d424d5a0bdcbb8a0233f4b3060dd04c98ec98dfd05ec7247884e2d8e152d4ae52b3d5865d9efd6706a60e088e1e7c9f624510abc7a2045a2c7a7588e2535e73191dd5cf05421563f556a13e8236670343cd5ba4d466e245c4ee3b5a41e70c9a0f5e6ea2c559ebe61ba81e: +206cd2b8114aae188d81862ccec4cb92c4ef5fc78c24435a19f9ed9b8a22f47e97a67ac2811f529456df532737d76bed7e387da83bd55459372fdfb27ffacff3:97a67ac2811f529456df532737d76bed7e387da83bd55459372fdfb27ffacff3:480c4800f68c79f5dfc0c3666c0ac429b30fe0c5fe848750db2171380b80c8e9fec0a054b16d08674cefe2f64ec28bb6b0596b35235575f189bee259aca766c222ac0a46cf2af75774da4e34a0b54fc2ac49ec8bedf4887cd9b7be4fdb7f686902ddfab04627e26ea2dc3d97d62a4b1546180218ed8fa113334819b5275cc54afdee44309008596507971675e6d8b8a8edec4718f2d4bd735213cbbd18791faa8054174907a7ac17d7143a4757e493beeec4849d0b836f18bb2b3c9016f25af47fb96199251720549f15d149503d41095e25f26209daac39154485c3ded7cb1a8c3e83a52f5a06ec09cf83df00726b7968f64c0cbae299512fb438560f04b3b644346f938ac8e90486614cd844b54eae078bf678b3:73a40d9da08fb98ea25b67e721557a1a51225294d316b53149af895fa4d63cb4a3f56f688566ef6da42fd2941dffa06d497aa902165d50213a6214116299a90c480c4800f68c79f5dfc0c3666c0ac429b30fe0c5fe848750db2171380b80c8e9fec0a054b16d08674cefe2f64ec28bb6b0596b35235575f189bee259aca766c222ac0a46cf2af75774da4e34a0b54fc2ac49ec8bedf4887cd9b7be4fdb7f686902ddfab04627e26ea2dc3d97d62a4b1546180218ed8fa113334819b5275cc54afdee44309008596507971675e6d8b8a8edec4718f2d4bd735213cbbd18791faa8054174907a7ac17d7143a4757e493beeec4849d0b836f18bb2b3c9016f25af47fb96199251720549f15d149503d41095e25f26209daac39154485c3ded7cb1a8c3e83a52f5a06ec09cf83df00726b7968f64c0cbae299512fb438560f04b3b644346f938ac8e90486614cd844b54eae078bf678b3: +59b144a708abec972729a04a6c13f0ea020b4ed4a48298023a568958c21215ecc4f4720092ed6179a082ae4d6145df3771786efca9bd9bb79c9f6667d2cb56b3:c4f4720092ed6179a082ae4d6145df3771786efca9bd9bb79c9f6667d2cb56b3:3857bd260b8aad9d073f06765d37fe893a3f53e23de866ddac33495a39ad33ee9e9d5c22502bc1c4b5470d0e3f3a585223fe4cb93cc4ad2b5ba6d78826a53fc0253dc580a2018cc9ff1cfedbd3ac0b53292deefbc14e589acf496cb5f7670130fdbb6cf38d208953c015a0474675b724bd109f7cb89c33016751fe7aa785d099d09ab20dd5258cd764ac8daf343ce4790ead0863af43121aa527a37a11628f47869668f8eac00d80b6bf9906663d7a2899c1cb678cd7b3eb3bc80226b8b13b6e46877f38f07c3d9c86d3368baac4a6f6b93ccebcec9811474b6a6a4da5c3a5966571eed05edcc0e3fe7cd15915c91f44eee8c149ae451f375518a79fb600a971a39b9433dfa19f91931b1932275747c262eedcbd27f1:1a80850fcbd6e643c6ba8eb684dbef7df015159228daedcf0604709186054db185aa7baacb09d6caad01638eff8e468735a60124de0c5376e94340e541a980073857bd260b8aad9d073f06765d37fe893a3f53e23de866ddac33495a39ad33ee9e9d5c22502bc1c4b5470d0e3f3a585223fe4cb93cc4ad2b5ba6d78826a53fc0253dc580a2018cc9ff1cfedbd3ac0b53292deefbc14e589acf496cb5f7670130fdbb6cf38d208953c015a0474675b724bd109f7cb89c33016751fe7aa785d099d09ab20dd5258cd764ac8daf343ce4790ead0863af43121aa527a37a11628f47869668f8eac00d80b6bf9906663d7a2899c1cb678cd7b3eb3bc80226b8b13b6e46877f38f07c3d9c86d3368baac4a6f6b93ccebcec9811474b6a6a4da5c3a5966571eed05edcc0e3fe7cd15915c91f44eee8c149ae451f375518a79fb600a971a39b9433dfa19f91931b1932275747c262eedcbd27f1: +8d1621eeab83270de857335c665bbf5726e3722225fd016e23bf90ab47aeec3dbecdbc024dae6a94ed4e29c80f2aff796aed8feb2c1b3790a8c72d7b048a2c61:becdbc024dae6a94ed4e29c80f2aff796aed8feb2c1b3790a8c72d7b048a2c61:97facddc82cccccf788c31b3305e93eba956f89613e6e53542b043267fee544c2b0a8ae8886a31b9d321a63c27623baefea840b2a8af5b2330193ffb5baf873c335528afeae2160163c851c5a2e58154a1b0569c2d1366c0710437623b0e08c686e54fc279ed4c45f3e856868375f78224c777b13d75de10d79173552425d15a561904155f2117b2f14713eb0b04648a3bdeb3302167d1973e788a06cb00d48ccb269fa71af8ba68eae55dbbfd9594d5c2b4dc13ae0321718561acdf67dc8cfcc25bc46bb66e096a1941d9335207d3f7d11e8904904fabe3a50a3883e7078047df252f38b67cd28a6ac45c7d7a1d2a1de8d45747cf09301e01cdafd0cd99a6e91b704d509fce692fbdef2f71a5ce0b35bc15c65f876824:e08d6caa5f39327d6e6652ed74dd1a37844b979f5cce747a606f5679f4898bbb7643df7e931b54a2b40ebdefe83003f61ca0f11112f023c6a3e8cc18cafe5f0d97facddc82cccccf788c31b3305e93eba956f89613e6e53542b043267fee544c2b0a8ae8886a31b9d321a63c27623baefea840b2a8af5b2330193ffb5baf873c335528afeae2160163c851c5a2e58154a1b0569c2d1366c0710437623b0e08c686e54fc279ed4c45f3e856868375f78224c777b13d75de10d79173552425d15a561904155f2117b2f14713eb0b04648a3bdeb3302167d1973e788a06cb00d48ccb269fa71af8ba68eae55dbbfd9594d5c2b4dc13ae0321718561acdf67dc8cfcc25bc46bb66e096a1941d9335207d3f7d11e8904904fabe3a50a3883e7078047df252f38b67cd28a6ac45c7d7a1d2a1de8d45747cf09301e01cdafd0cd99a6e91b704d509fce692fbdef2f71a5ce0b35bc15c65f876824: +f2735d50ee3a9a65b58c8acf551663e98809ec406f73e3e7f4e73bc4ea923874df48a5b94a07af3c2c99b8388762243233c850dc175317d602638e5b86ab49ed:df48a5b94a07af3c2c99b8388762243233c850dc175317d602638e5b86ab49ed:ae31e94e7197e4e4d0239348025ed6681e513ce1a6e0aa0e5b979373912150ef113e50ef0569c483f7568c4bbc4703c5dacaa80a0de4e738383fa1f10d6d4071a31b99e6485143972316c86522e37c6887a1c307b29b0dd6f9f1b438310af9d8d7346fb41f9b2dd2e80b14c45eb87d4ed48e37a5260b52257b3e99787a13c55392ba930c08e0240e960def0c29b8550745cf149dee53a5d174ec065d2d6677dee1fc42057062c34e27ea5dbcdb861b9f670c6032c7846cec8e87a7c9520e27967b0186ee71b77ed6d029bbdd70949cec4a709329fa37fee002490cc1bc4c2df6f763f9858f33d750c5b505a67e237063c0486f9456d3c620d9ac7c98f1381de0effe41c18259504a150d68a6a28b0a3eea803b855315c9e0:6942a7696417efaa591b95e11f02d763bef5279b932a8e2a7cbb9f583695c14ce5cc556bec66799b33cb592da4df2735f9eef2c3ceca4362164b6cc93da4e105ae31e94e7197e4e4d0239348025ed6681e513ce1a6e0aa0e5b979373912150ef113e50ef0569c483f7568c4bbc4703c5dacaa80a0de4e738383fa1f10d6d4071a31b99e6485143972316c86522e37c6887a1c307b29b0dd6f9f1b438310af9d8d7346fb41f9b2dd2e80b14c45eb87d4ed48e37a5260b52257b3e99787a13c55392ba930c08e0240e960def0c29b8550745cf149dee53a5d174ec065d2d6677dee1fc42057062c34e27ea5dbcdb861b9f670c6032c7846cec8e87a7c9520e27967b0186ee71b77ed6d029bbdd70949cec4a709329fa37fee002490cc1bc4c2df6f763f9858f33d750c5b505a67e237063c0486f9456d3c620d9ac7c98f1381de0effe41c18259504a150d68a6a28b0a3eea803b855315c9e0: +cad9d21a01c7e1d15df2fbd79c516eb8c3401e9fe28467cc7b21679d4e331a3da7b55c15d6790b40536fcae5ad2892cd66b18689f499c1fdeea66d4a7df39424:a7b55c15d6790b40536fcae5ad2892cd66b18689f499c1fdeea66d4a7df39424:70702bf19c919f9836defd7b846fd9992d8b7eb2e106aeb71e60a31b4ea25a41b212dc7de7c91cbd613d58d0595db833cfe7e50584f25569602c7744fa675d156d0f63cd2b7c089c8a00686a437169826a12dc485b38c068a8007142e5163747011a07a415683622ab1e23ce577c732ba14f401fbc3043e0693a9205c19a92298a3d9b08fb7afafae0a9f016bc750ee631a5f5da5db6f9ba2692c74caaaeb4d097e90e3c02d2e3a7fb3aa000040b7c17b74564e646bea16bad611ebc0859a3828804ab4f5cfba417d254515ca3620a3ad683c46ca6267bb49539bb30e369087e67438e9489562750dccba3aa0b1b0a6c267032d20c2adb75e68df1123b5259bfe4eac6cadca6778138a37318adb30e8d669f3bc9692cc74b68:31927d01db9f2472f4df6f63c18ebd83c2b1aaf88d580e848854df8cba6395d3da7bd6bb9edc1fce1c7d7e1360558fcddfa93915be076efb8ea2dc5ea7b20d0a70702bf19c919f9836defd7b846fd9992d8b7eb2e106aeb71e60a31b4ea25a41b212dc7de7c91cbd613d58d0595db833cfe7e50584f25569602c7744fa675d156d0f63cd2b7c089c8a00686a437169826a12dc485b38c068a8007142e5163747011a07a415683622ab1e23ce577c732ba14f401fbc3043e0693a9205c19a92298a3d9b08fb7afafae0a9f016bc750ee631a5f5da5db6f9ba2692c74caaaeb4d097e90e3c02d2e3a7fb3aa000040b7c17b74564e646bea16bad611ebc0859a3828804ab4f5cfba417d254515ca3620a3ad683c46ca6267bb49539bb30e369087e67438e9489562750dccba3aa0b1b0a6c267032d20c2adb75e68df1123b5259bfe4eac6cadca6778138a37318adb30e8d669f3bc9692cc74b68: +d9be842255e9a16b0a51a8674218cee7cd9a8bdf343508397f4ddb05f3fa00827931bc6dfa3324943aab183d1285515919399ffe0b710677f0915d3a5be51e92:7931bc6dfa3324943aab183d1285515919399ffe0b710677f0915d3a5be51e92:ac6c55b134663e41f02a6dcb8549eaa1c013f59658d81d812f95b74009513723671945e1324f90f8a3f971369181b587bab45665f788d663ab78140c5a22c1c18d4afedc7448a748afe5bf2387003c1d65ab18482ef98922b470da80ad14c944951ce4aed37390cce79a8e01b24c7dfc1141c0eca2c7f773ed4b11806a34615513486e4ee11af08078a1b4054cf9880298608dd9b3faa1a242a452fe511604b3102c313d14cc27c6f0f8471d94555317eaa264cdf52c69e18f461e47903d21298716b172ee9cb178f08ff2d3c9c162121c2ed21d8734b2f0630d399146cbf76e028a143f2bf7bb50af0f57b9ba8021d264b00c6662f84c86cb6d5952b3d241f7dc3e700c96616cbcfb0d0e753ffd5d21ee320e65e97e25cb8609:c93845658c9560d2c0e28f282adbd4652bafd3bb2edec17c94878f7b94d3c77afec906ed292a8dfbf5f8e7c118e8f2ca33dda7909d9b695b8ff5a1c0e97ac807ac6c55b134663e41f02a6dcb8549eaa1c013f59658d81d812f95b74009513723671945e1324f90f8a3f971369181b587bab45665f788d663ab78140c5a22c1c18d4afedc7448a748afe5bf2387003c1d65ab18482ef98922b470da80ad14c944951ce4aed37390cce79a8e01b24c7dfc1141c0eca2c7f773ed4b11806a34615513486e4ee11af08078a1b4054cf9880298608dd9b3faa1a242a452fe511604b3102c313d14cc27c6f0f8471d94555317eaa264cdf52c69e18f461e47903d21298716b172ee9cb178f08ff2d3c9c162121c2ed21d8734b2f0630d399146cbf76e028a143f2bf7bb50af0f57b9ba8021d264b00c6662f84c86cb6d5952b3d241f7dc3e700c96616cbcfb0d0e753ffd5d21ee320e65e97e25cb8609: +cfc48cc6f65811fe7d7bba85d1cd84858fd6f7edd638f4f552363ee7685f69cad29c10694c5e8e3f3447ed78d34dbd74a2b301373ba871b5850c333dff7bf8d0:d29c10694c5e8e3f3447ed78d34dbd74a2b301373ba871b5850c333dff7bf8d0:8e7defb9d16d036bd642cf226e32773e605361c5ec4b951255788db0a042c63e5a4367d61524f10e6258991325a39ab6b03612260c3fe3df20b34202d34395bd4ed40bd61373df781a4c8bcfbd15301060f07437732333d8e49736322dee6b22438e787d8856b70c26ec57d6dade9c3c28e27220c5670e393544ed095937298dc3adc73865f777e90037bdef834716476d78f4e6cb4961a4c68a8a836338a9f5da179c4d5e93c3f70dd35eec709653dd8de37996b12056d4eefcb4b6b3c13ba984d832275c4386ebf4a8ff7f078be3d428c1e0d9b162381f06a5b7bb12704003d91f25d1d8fd43626ce70fff59d2927768a76bf7f9ef76ff95489f38edcd1c9e9b8a8b0ef66c32805776d5ae9fbd84a7af4fa6563ec70ac5733a44:80c5d51e96d1cac8efd3459825e79c1e9f65af701d1d29e1f95b036707113b77984b7b3350f04077333c957f8fbc7d9b040c362651417b9899027cd33edb11038e7defb9d16d036bd642cf226e32773e605361c5ec4b951255788db0a042c63e5a4367d61524f10e6258991325a39ab6b03612260c3fe3df20b34202d34395bd4ed40bd61373df781a4c8bcfbd15301060f07437732333d8e49736322dee6b22438e787d8856b70c26ec57d6dade9c3c28e27220c5670e393544ed095937298dc3adc73865f777e90037bdef834716476d78f4e6cb4961a4c68a8a836338a9f5da179c4d5e93c3f70dd35eec709653dd8de37996b12056d4eefcb4b6b3c13ba984d832275c4386ebf4a8ff7f078be3d428c1e0d9b162381f06a5b7bb12704003d91f25d1d8fd43626ce70fff59d2927768a76bf7f9ef76ff95489f38edcd1c9e9b8a8b0ef66c32805776d5ae9fbd84a7af4fa6563ec70ac5733a44: +15c9f7c4d84a5a479041952e6a8cac24e76fd2d275c197e6b521929b43ba6c5d8633c1829d29091df71fd5c0ef640572e4b64974cd097dbebbcddeba041647c0:8633c1829d29091df71fd5c0ef640572e4b64974cd097dbebbcddeba041647c0:11730dd45dda80d84d080d92e9bddaeea6878e4a0b3b512d9ea733808e1cef51d49048d6c78116a4bde3c64aceaa52beca86b331ab59e9185c70286a02bb5dd04f5c7f4e9c7e445e77458565f159c783dfd4d976a910e937789d2141d416ed3a7f608d26737a86b20b624e3c36af18d25c7d59b8d7427ec6c4d3d438d7ae0949dd7d748c1ffd6f28e8285d440422d22a3761202e9584f5cdb3504547aa4b685730c982cba213de08020a5e4e46a95fac4b481bea0b630abd030ddd335a20fe2cf7094aef4813956991913c6821f4b5410df4f133fe63e22c08092a0a65972722a27ae42011a807c327b417237c540114eecb9f0e96cda5dcf0246f1d2717f49b9cea9dc6a3da9b396f0270529226f5dcba6499918a6c289fe055fec8:1e36bea5a583767ebd80306cab233155b7b42814b43473cf45cdc5039c939744a9694b87220daf4ccd29f25cea405e7c08db2ef17f3f034dbb49cff60283e30611730dd45dda80d84d080d92e9bddaeea6878e4a0b3b512d9ea733808e1cef51d49048d6c78116a4bde3c64aceaa52beca86b331ab59e9185c70286a02bb5dd04f5c7f4e9c7e445e77458565f159c783dfd4d976a910e937789d2141d416ed3a7f608d26737a86b20b624e3c36af18d25c7d59b8d7427ec6c4d3d438d7ae0949dd7d748c1ffd6f28e8285d440422d22a3761202e9584f5cdb3504547aa4b685730c982cba213de08020a5e4e46a95fac4b481bea0b630abd030ddd335a20fe2cf7094aef4813956991913c6821f4b5410df4f133fe63e22c08092a0a65972722a27ae42011a807c327b417237c540114eecb9f0e96cda5dcf0246f1d2717f49b9cea9dc6a3da9b396f0270529226f5dcba6499918a6c289fe055fec8: +6d2d0d823f294746b9a5512e14e73c1d855b5e4bca65fe817729810cc5ef840d1b6480a6a90dfb472984855cef6f1ab31eb7b3f13c8ac00fa556d20b53e5ae17:1b6480a6a90dfb472984855cef6f1ab31eb7b3f13c8ac00fa556d20b53e5ae17:8772721f72eaf7f73040c068a7c3753bffca7dc2d0930c6525f425e6005c25cd4c0ff5095c9c61a5d8a1967b8c86010c884e509e6b1670f79046e22979ebd354734090d3ada21435c1f8254f7b5222cd5564f064e977640366449f4e5008f870f9c4840565bf4fb5f574c9774ba2568e71a9ccd82ffc59b694f26e7de4ce2e3fd880a0eef387931333ede00dcb065e6d0f79591a2aa956df1948a265cb95750d8a233b15c288a05487c515663f93e740fb1570fbe4bd80c68e8d9297345a8a01cdbd88f4a39bed9c5ef09f144bce5de568bf3733bc53b2039a29cb3e194501adc1c10e86383aac8b0f85c67a6689bbe1470a392476313439ca88d98c021c0eaec25fb2f9a160ce5c786170be0238fb8785dd33bfa9059a6c3702d0de05:b515f49eb32ad478692df88f07b7802c6e0e5327aa08a6366e4cb1d1e26f9e65fc81abebe2215d649100f27598273a412b624e842d8130403797e57dec975a0a8772721f72eaf7f73040c068a7c3753bffca7dc2d0930c6525f425e6005c25cd4c0ff5095c9c61a5d8a1967b8c86010c884e509e6b1670f79046e22979ebd354734090d3ada21435c1f8254f7b5222cd5564f064e977640366449f4e5008f870f9c4840565bf4fb5f574c9774ba2568e71a9ccd82ffc59b694f26e7de4ce2e3fd880a0eef387931333ede00dcb065e6d0f79591a2aa956df1948a265cb95750d8a233b15c288a05487c515663f93e740fb1570fbe4bd80c68e8d9297345a8a01cdbd88f4a39bed9c5ef09f144bce5de568bf3733bc53b2039a29cb3e194501adc1c10e86383aac8b0f85c67a6689bbe1470a392476313439ca88d98c021c0eaec25fb2f9a160ce5c786170be0238fb8785dd33bfa9059a6c3702d0de05: +c0cf799af7395bf27bafa36cab437045e39c903bf807548319ce44f287494fbbafbf550ca290c905bdd92fc8831ebe3dfeb6daae4f56005253cc50951e50edc2:afbf550ca290c905bdd92fc8831ebe3dfeb6daae4f56005253cc50951e50edc2:dbe65780e968de9e40ffb57cf59a60fd93b3f9a5e7d8ed5180adbc578ca1bc48bd9fb60a1324c9c2c1141479a0dcf0f1d07e84936526df42333c0d773e3fed9e4038de5b95ad905c92cbe040487bf55e10e1edb429a0ecc4e0e8d00a988a9cd53e2eb372f4fc4cd9537b269ba3a23cefbc8df6476e75434b81d93e8891bf417c82e363f3e4abf80a4f73aca84ac7df6337f536d63d939d92cba64be742221116069ef251abba0b00af01718bb580ddbeb79973ef10a68b4d0fa023d6ebd3079d6b32a1aa20a21e9202f27590c3f0c0cc253073c3f822aac459d39f50758b70c00710a3c98438416508522e512adaa0afd503a7ceb04fb94a4a932ce80cd5a7f11bb861263f58e5749d542a110de7c7689dfcb0c51afa9d54a58ff89f3f67:5bba01a4c7b25542d06912de70aa1e220423fdf8338a9e693395cb6f0dc1fbfd018e3c77e50aef90a9080f30f1f5792b2431078fe6e3e00464245e17cd8dc107dbe65780e968de9e40ffb57cf59a60fd93b3f9a5e7d8ed5180adbc578ca1bc48bd9fb60a1324c9c2c1141479a0dcf0f1d07e84936526df42333c0d773e3fed9e4038de5b95ad905c92cbe040487bf55e10e1edb429a0ecc4e0e8d00a988a9cd53e2eb372f4fc4cd9537b269ba3a23cefbc8df6476e75434b81d93e8891bf417c82e363f3e4abf80a4f73aca84ac7df6337f536d63d939d92cba64be742221116069ef251abba0b00af01718bb580ddbeb79973ef10a68b4d0fa023d6ebd3079d6b32a1aa20a21e9202f27590c3f0c0cc253073c3f822aac459d39f50758b70c00710a3c98438416508522e512adaa0afd503a7ceb04fb94a4a932ce80cd5a7f11bb861263f58e5749d542a110de7c7689dfcb0c51afa9d54a58ff89f3f67: +cdaa50e8527dc7a50fb37e28fa8b9568c37e8567e0b499997b9aed676180c3b07c56e164510268c182b423747904f1d3a5809330f6e1b29266ec46e73be1550f:7c56e164510268c182b423747904f1d3a5809330f6e1b29266ec46e73be1550f:94fcfbaaa303dece7b908f874cc5f095061f1754bb35780db666b63ab8290811bf1c521a7f8f785ea270dfb39d0d6ed95ab71955a11ffaeaa268e081ff3e4f2425b41880a987151e678e89111350942d820c3eec36212426663be175e5286b4ad1cc804e3e3a03b9fa3e82838ebbc2615a645f2ca1468ac4a1cdbe523761e83f4381b0c8550ae5e8c8cd1fda57191436e27cb883bc64be86a9dc6110ef3401d88a7debd1b701d9c257a6826cf01e9e2922e3ae577f2834275fb0ecda80ed8cf1801e0bc5e01e26a77c48bdf46a5c4894d22ab53e741827e24bed5f0750ffad05e53f1d5e61dfd316b191d9797ef713131a8b430abe3fac5f3c4a2ca021878b15adc8c5f542114260e687a9d199d230c4e0d3fc696993b59ccfa3ffa9d8d2fb:137bd10a50ef609384fe668768fb871de741ca0f53ff8477d7ebfa90aafd5e2681fdf1b89250463c15db8e17a58825fe9427de089c34de13cd07bba18d4aa40d94fcfbaaa303dece7b908f874cc5f095061f1754bb35780db666b63ab8290811bf1c521a7f8f785ea270dfb39d0d6ed95ab71955a11ffaeaa268e081ff3e4f2425b41880a987151e678e89111350942d820c3eec36212426663be175e5286b4ad1cc804e3e3a03b9fa3e82838ebbc2615a645f2ca1468ac4a1cdbe523761e83f4381b0c8550ae5e8c8cd1fda57191436e27cb883bc64be86a9dc6110ef3401d88a7debd1b701d9c257a6826cf01e9e2922e3ae577f2834275fb0ecda80ed8cf1801e0bc5e01e26a77c48bdf46a5c4894d22ab53e741827e24bed5f0750ffad05e53f1d5e61dfd316b191d9797ef713131a8b430abe3fac5f3c4a2ca021878b15adc8c5f542114260e687a9d199d230c4e0d3fc696993b59ccfa3ffa9d8d2fb: +0fdea9bee6288f947e0adbdda4dfb2baa03891af25024a5e138ac77984d0050770abd86430d7e8d63209c8b373ec4e4b79e989e6725facefbade3c7574d23cd0:70abd86430d7e8d63209c8b373ec4e4b79e989e6725facefbade3c7574d23cd0:cf72c1a180a2bc37d8478d9a7a39acf03bf2a50790f7902f81121222d31d3ec916f4f24cef9d7c41dc021b0e8487bb892e47305e54520303e89b30b263dac4a9ba375d46c40fcf400535c959d2b746a7fc970cf65b472e84b5f1d0ebadcfa1aed6fc47facce16a366a3b1d6e516813c1960975f8f2b43042fb4eeaabe63c6f65db45ddb7db888a19a9d7ba6ca479fcd70c5d1e970f12c14f4d24fb7e2f357bd3a94aa1b868ccc0847f2eef21853e253bafbf07c4e6176a1ef077167841ebbe5629337157f39f75c71d21e7e96c51a1b16fa8dc60f0b1279fcda2641fc8591e3c492f15bf83caf1d95b2cd91332f1b4202fe72862ca2ea2ef92c11db831d82f8fc3d41fe29a76c211a758e2f71bd89d2c6610f201429f348d56e10e3b7af53e27:80c42dd5df03b285a86ac95ce6669f786a978a813a9d7b8c6a23de76fbd09bdb66c5dd1cc9f1a176cba388d5051764a32fa27f0028ba4898068bd01a3ee17208cf72c1a180a2bc37d8478d9a7a39acf03bf2a50790f7902f81121222d31d3ec916f4f24cef9d7c41dc021b0e8487bb892e47305e54520303e89b30b263dac4a9ba375d46c40fcf400535c959d2b746a7fc970cf65b472e84b5f1d0ebadcfa1aed6fc47facce16a366a3b1d6e516813c1960975f8f2b43042fb4eeaabe63c6f65db45ddb7db888a19a9d7ba6ca479fcd70c5d1e970f12c14f4d24fb7e2f357bd3a94aa1b868ccc0847f2eef21853e253bafbf07c4e6176a1ef077167841ebbe5629337157f39f75c71d21e7e96c51a1b16fa8dc60f0b1279fcda2641fc8591e3c492f15bf83caf1d95b2cd91332f1b4202fe72862ca2ea2ef92c11db831d82f8fc3d41fe29a76c211a758e2f71bd89d2c6610f201429f348d56e10e3b7af53e27: +03d5e466f8298ab5438a30976d1322a7215a642dd5fb4c3f8519409a7522f0924b3ed4db080e2a452e16912c14504424920a60975604e4f379258d1c8b193d6f:4b3ed4db080e2a452e16912c14504424920a60975604e4f379258d1c8b193d6f:1b47b70013cb53e1f8f4971e0f39563ce87edbc2cedd99e5a35585df8b00a852f7b9c97c7e4a5465fc5605ae8c5c36570a99201a7ad6031287ef0c7b2ba6e57b056d0fc8d6ca43bf6cbdab098934b403197b525d22d45e6b29c78f8d6183e41ffe197dae25ba22b06669ae05badd7e1da6932a7d054cbab3f54e5146223ad8671231bc16fe62679bd2817a6b80e653998c4949f81ff53b6173163e11da3e6d3c76d84c713225b4173d6bf06a85b6988a48be4359cb515503ca563f4353f8e7d45e4d94462c89a04a00f1b3b0ca6422d5db029c507d464834a20c78a713661d84edffc496d69282619894437b4487954cbea2aa7261e6a62b6851154a5d25fb6b4f09c59473d385ce03e91ba865eab66c58c0abb0b7a78e4be927e55460ccd70d82:6d7e4658f26f337c98e03f13542e2f39440ff7bf8d88f3f6dfa4d64948cd96b79051492fc28f65f2cc0d23a0c4d5e2307bb1c47e11e53b371f091b69f80dbd051b47b70013cb53e1f8f4971e0f39563ce87edbc2cedd99e5a35585df8b00a852f7b9c97c7e4a5465fc5605ae8c5c36570a99201a7ad6031287ef0c7b2ba6e57b056d0fc8d6ca43bf6cbdab098934b403197b525d22d45e6b29c78f8d6183e41ffe197dae25ba22b06669ae05badd7e1da6932a7d054cbab3f54e5146223ad8671231bc16fe62679bd2817a6b80e653998c4949f81ff53b6173163e11da3e6d3c76d84c713225b4173d6bf06a85b6988a48be4359cb515503ca563f4353f8e7d45e4d94462c89a04a00f1b3b0ca6422d5db029c507d464834a20c78a713661d84edffc496d69282619894437b4487954cbea2aa7261e6a62b6851154a5d25fb6b4f09c59473d385ce03e91ba865eab66c58c0abb0b7a78e4be927e55460ccd70d82: +76cc18a1dafffa100586c06a7b40f79c35fe558c339c2999a5f43875cfade03e4b9da8d2f137dc6c857a99a5998dd89dd5f05971a21e8c776670eb47bc1270a5:4b9da8d2f137dc6c857a99a5998dd89dd5f05971a21e8c776670eb47bc1270a5:4522b1d82373f7a318221e7e57617503ddf44fd53997522a1d963c85b708d0b245de372ad52ec7f54f6213d271f7c91d5a1d36d134db389df0b081a06bc0c7a4875f724092793172c9115641c6d054f1d992e0fae4df58695f0ea3449d7a4b3a8857e19803fe49b6d52c9ff3746a574a2756956579f9fb809a0edec92c55e95ffefa3d05f165822f464a21999f29691f6744ac5a3ee49017880645e837edebfd2e0f24997f041145a72e2376ada283186ca2b836362977195baee30a3acc81b243f3ee376a2c4764c783667a4b1177e7951d3e3c7be4f1bd7ae8c60fd5fb0fd91f0c1c14d0d2327e8f20d92c0dfcc53870e9d99fdbf9dd9a17e882509ae7baa8653e39edc8ee569000d624cb93a0754a798d1f811f6a0ef5501a17bcf25fd0f91626:db74751c66e6b1866044dd9ae99f19e6334f179e79d8b8e0c8cd71d22cefb9eab7e3e7a9c2da225f2a9d93a313d1cbf1b7fe2597b8d702bf3017a6a6bc7b7b064522b1d82373f7a318221e7e57617503ddf44fd53997522a1d963c85b708d0b245de372ad52ec7f54f6213d271f7c91d5a1d36d134db389df0b081a06bc0c7a4875f724092793172c9115641c6d054f1d992e0fae4df58695f0ea3449d7a4b3a8857e19803fe49b6d52c9ff3746a574a2756956579f9fb809a0edec92c55e95ffefa3d05f165822f464a21999f29691f6744ac5a3ee49017880645e837edebfd2e0f24997f041145a72e2376ada283186ca2b836362977195baee30a3acc81b243f3ee376a2c4764c783667a4b1177e7951d3e3c7be4f1bd7ae8c60fd5fb0fd91f0c1c14d0d2327e8f20d92c0dfcc53870e9d99fdbf9dd9a17e882509ae7baa8653e39edc8ee569000d624cb93a0754a798d1f811f6a0ef5501a17bcf25fd0f91626: +71ad980d58ad8e7d33306689358936a372d5190b24ec7f9bde749cb81150efdafd35a75fe5abc20104691a24a4659440b55aeaea902ac3be274af27aa8312869:fd35a75fe5abc20104691a24a4659440b55aeaea902ac3be274af27aa8312869:e87ae073ff5dcc5485a19940e4e3ff263a0618a9025ad4032dfb36d171ce881f71c18a49210eb45819806142e2f00db3041835bf2c3bccf1dba02b8b5a5bdaf8fea316c0623dd48a564ec166f037d587c8c01684e5e5c0ba9dba4d23b49a0309244e282a51408622edb05704747e0cdeec976893777071098972c113a8ab639c31f1613233ee460eea8a8c10e1e6e152214529878cf1adaeaf78cf19bac71361815bf57955498fab4f0f2b7586c86f9f4c2ddf8972f9b9e0eb636d84bcc14385b2d038be55a963702efe225a50bdd0c4da92a2a6a09100ea04a211d396458dceb4487116837d139eb0f122538ed3986ad0af4da2dffc89f3269ca88538086e691e5beae9581e7c63d8e612da2c47f74dde1d94951eadb0df60c3897d2a3095c506093b:81670b1029e481e9ff3c171f05c16861c846ee79cdf2e21e3bf952bcfac97565f2b1dcedf69d2e7eb35caf5662e8bc671fbb96756a63a596264d1b7f4af97e06e87ae073ff5dcc5485a19940e4e3ff263a0618a9025ad4032dfb36d171ce881f71c18a49210eb45819806142e2f00db3041835bf2c3bccf1dba02b8b5a5bdaf8fea316c0623dd48a564ec166f037d587c8c01684e5e5c0ba9dba4d23b49a0309244e282a51408622edb05704747e0cdeec976893777071098972c113a8ab639c31f1613233ee460eea8a8c10e1e6e152214529878cf1adaeaf78cf19bac71361815bf57955498fab4f0f2b7586c86f9f4c2ddf8972f9b9e0eb636d84bcc14385b2d038be55a963702efe225a50bdd0c4da92a2a6a09100ea04a211d396458dceb4487116837d139eb0f122538ed3986ad0af4da2dffc89f3269ca88538086e691e5beae9581e7c63d8e612da2c47f74dde1d94951eadb0df60c3897d2a3095c506093b: +61594e24e75f996b4fb6b3e563f6a4f9915cfa65ddb199b01fed7f8ed7824ecb8627d2141579cd2521aa076800ac354b9e3a47d71cedc8547434268225e33005:8627d2141579cd2521aa076800ac354b9e3a47d71cedc8547434268225e33005:bc01b08c7caa236100a012a726477d0ec389dbfadac73d5106424c5d1f3d1cef1695cfd93a7062ec8bf1067047854920162f651357bedf1cd5a92ec29bdb5dff716e8f6025515a9549ba36cdc35ced7c5c0c368e6cd92f2f10ae146a20728c374bba509641ce88cb42fff0cedfd9fd67f310f9d01a3f3690eb21db17bce67ae35c4cd24c209f09f044759d8d5a7d248e2bd966524ba8c0c28974726b43bd05de843433cc400598922974623d9acbfdc761c4c04375a952ce54caffaa96acff6d9dc278742af476e1865cb8c20d13d1c1900863bca231e44c6b0d47cb41d510f7958f48f304d03da033484a3e1f273faf6983375b7d3be03d8a0a002def6365beb2fa8ccf1a94987adcd33d0da1177fc5159b6e56d004301e921dbc12ec0a73f413cf2c48:6302b3ff2710be306c92b9aae30d23c3d4beff394e63201e6ad11713345c4fcb5cc8d3dd10adfb82bb11a189ce7ec3e4222727624fc17881c14788d2710e1608bc01b08c7caa236100a012a726477d0ec389dbfadac73d5106424c5d1f3d1cef1695cfd93a7062ec8bf1067047854920162f651357bedf1cd5a92ec29bdb5dff716e8f6025515a9549ba36cdc35ced7c5c0c368e6cd92f2f10ae146a20728c374bba509641ce88cb42fff0cedfd9fd67f310f9d01a3f3690eb21db17bce67ae35c4cd24c209f09f044759d8d5a7d248e2bd966524ba8c0c28974726b43bd05de843433cc400598922974623d9acbfdc761c4c04375a952ce54caffaa96acff6d9dc278742af476e1865cb8c20d13d1c1900863bca231e44c6b0d47cb41d510f7958f48f304d03da033484a3e1f273faf6983375b7d3be03d8a0a002def6365beb2fa8ccf1a94987adcd33d0da1177fc5159b6e56d004301e921dbc12ec0a73f413cf2c48: +54e6bbfbf8c06ff2c066318c2ebf03d506547bf43c2d7a5d4df305a3032b71383b71aa1def666d9188f403f82ed30454aba5bc9f470f6eb988da187c92523284:3b71aa1def666d9188f403f82ed30454aba5bc9f470f6eb988da187c92523284:0318d7cb4805af9821dd3f914b0e076fea04a7d2db3a59a00affead3325a2be40c1f87f53276a8552604f228b976e288b9be906a7bd25b2ffab8a8af5d0f6e08786fd034e2fe1eb7ee033979860dd1e5327287e9e615f5dc5a960f17026b56842fc8d44cad002edc8501cfb956001502e4ddc81a7700d9c0be88eb4aaa64a6cbc39de82f13c11086de1a4270d3af97284bac1caef1d3edaa1071666bd83b2ede3962d98b9d93497ddfd8e97dab3089950cf30ed11db77ad1437a0af5889d8efc44e612420e3907267df3acff4bd3fb6e8ca5badf8e72f9de39528653058524456a81da5f84982afac34bef5f71e91f8f90938a6f5f1f287716de56a0946d261e87bc775ce189e41a77baede7320a3c608fc971e55d0a773c4d848d428637f11b4e4460390c:3df4d09079f830e3f982283681ba37b50f3c73de2c5d22a291358ebb1fb854e510f63f9a48e9fff7fd8311302ea3e969394e6d49c9e3182054942f6a744cee030318d7cb4805af9821dd3f914b0e076fea04a7d2db3a59a00affead3325a2be40c1f87f53276a8552604f228b976e288b9be906a7bd25b2ffab8a8af5d0f6e08786fd034e2fe1eb7ee033979860dd1e5327287e9e615f5dc5a960f17026b56842fc8d44cad002edc8501cfb956001502e4ddc81a7700d9c0be88eb4aaa64a6cbc39de82f13c11086de1a4270d3af97284bac1caef1d3edaa1071666bd83b2ede3962d98b9d93497ddfd8e97dab3089950cf30ed11db77ad1437a0af5889d8efc44e612420e3907267df3acff4bd3fb6e8ca5badf8e72f9de39528653058524456a81da5f84982afac34bef5f71e91f8f90938a6f5f1f287716de56a0946d261e87bc775ce189e41a77baede7320a3c608fc971e55d0a773c4d848d428637f11b4e4460390c: +6862061be0de9dfd998118204b2b98db3ce7d7e819dbc10794af0ab2b06e84349c5f7c2265dde1b25e4f27ec71580d52dc89f2c3a712bc1ad5d6d69e711e08d4:9c5f7c2265dde1b25e4f27ec71580d52dc89f2c3a712bc1ad5d6d69e711e08d4:1740dde8434a0d689925679b0c180300cdbd0cf6a89ad8fde34653316cee4c571a4105c9e9e0284238fef2c38a09157c5db94340571b390adfb69ff4c0dc5053253a679d42cc1f1bf1ff429229ea0a5044c6f79564e0dd287f53f015b83187d9ad27d91039af062c437b1575a0eab6aeb8aa0d27b27665d6dea9041ff9963a3118b3298a8544e3fd69ac6877e3e4052fe4422bf03560b2c57ec531ee8b5ff53c28dbde35bb45c35077636e6f841b59d7eb77bc7791b6093858a3a80a3aa6d778dbf53db9d06119c50b71c791c0495c576d1b59d396873ed871485352c8299a359da5ee9d7f36ed1455f89851a30851bea719685aecd08f25562609dd106630735277e1d6519bb1687de8b8c68b9671452edbb3491da264cdfa0017c512d2769759cb925fb664:965edb34e8ab8bc3204a3201d22186372de4242600297cfdb57aa1df074ec50ddf10105e9d4c89a266c34db7772aa94cba946429e68ba62bf9a0ac90f5f05b021740dde8434a0d689925679b0c180300cdbd0cf6a89ad8fde34653316cee4c571a4105c9e9e0284238fef2c38a09157c5db94340571b390adfb69ff4c0dc5053253a679d42cc1f1bf1ff429229ea0a5044c6f79564e0dd287f53f015b83187d9ad27d91039af062c437b1575a0eab6aeb8aa0d27b27665d6dea9041ff9963a3118b3298a8544e3fd69ac6877e3e4052fe4422bf03560b2c57ec531ee8b5ff53c28dbde35bb45c35077636e6f841b59d7eb77bc7791b6093858a3a80a3aa6d778dbf53db9d06119c50b71c791c0495c576d1b59d396873ed871485352c8299a359da5ee9d7f36ed1455f89851a30851bea719685aecd08f25562609dd106630735277e1d6519bb1687de8b8c68b9671452edbb3491da264cdfa0017c512d2769759cb925fb664: +b2250bbcb268d2477c8312b1900fd99982baa29a68974fbf8778a1228dc9755044aa8df1181674b05ade980f7eddbaf3bd7422a920287cb2d2db59a063eebf74:44aa8df1181674b05ade980f7eddbaf3bd7422a920287cb2d2db59a063eebf74:7ef0ae1336a6fab37f99da5fa7d0dec7409c072623ead84f241d53d0596b461705fb1b3c537d36b89e8960febb4cdc0d427ce2fc1be58dbbce151e35acd8b6ace40a19822914a4bd8c4af632f136418ac49b184d55193ebcc32d0d798709b1a8fe294fba8a1fe72d976b4400d4a393242311b0f8cc994e89475b0038ae5d8914938e8f6e87c6f50b9d656c45d7b14231efed97f3c90668913670bf5be2efd5c270c7cbaf01e8572e9800978dfe2e10a2fc0440b855629bf9cd409ea941cb69226cac771b15ea77c0326848806ff8d2e201e6e26cd5f45430dadcff8f59c321c1c9c6a29b94882935447d3e6c2e8804b1161576bdf0320fe53c307d9cde426077a7677cde3c1bc83e18e60a0c4ee6dccd877c213a8e4cca640ee04929804570ae1f96157c04357a:f2b8d92ed51ebd1000bf9dd3411a9fa9e7aee54c4c86e24ad0f9ad5c55643a12d680019ca03f216bd4bd32c9ce1cd8a528c3ffaa5d5b1dc91a4be56f0e2c5e067ef0ae1336a6fab37f99da5fa7d0dec7409c072623ead84f241d53d0596b461705fb1b3c537d36b89e8960febb4cdc0d427ce2fc1be58dbbce151e35acd8b6ace40a19822914a4bd8c4af632f136418ac49b184d55193ebcc32d0d798709b1a8fe294fba8a1fe72d976b4400d4a393242311b0f8cc994e89475b0038ae5d8914938e8f6e87c6f50b9d656c45d7b14231efed97f3c90668913670bf5be2efd5c270c7cbaf01e8572e9800978dfe2e10a2fc0440b855629bf9cd409ea941cb69226cac771b15ea77c0326848806ff8d2e201e6e26cd5f45430dadcff8f59c321c1c9c6a29b94882935447d3e6c2e8804b1161576bdf0320fe53c307d9cde426077a7677cde3c1bc83e18e60a0c4ee6dccd877c213a8e4cca640ee04929804570ae1f96157c04357a: +b809361f55cfe8137fbda880fc62cbe44c216e141893346302b336045de21878fd23e42ff06644ead347abcc1b3e03b0e88593b61254981dd8ae59454e61b3e0:fd23e42ff06644ead347abcc1b3e03b0e88593b61254981dd8ae59454e61b3e0:17ace197d083aaf1726f53e5ef81b5a8c09222f260ee5f1f5404ab78d900d489688449b843bad3c498aac6d80b4639b76e6e81c55276a6f9c7cecd70b71aaaf2018ef76c0e30154aae86a5c86d4e8d0e4ec68cc427060bd56514f7238086bbef5bfca1f5671b18041838fd013572443dba48fbdd95ca740b0daa4327164a1e34677249708f77bd793e7caa6638b5dc9fbe6f0dfd4120209097209c93cedfaf21b6bf59ca6e99e6209639444f0e827bbcc0a61c3a237ca22a283213223ab658e712c7556238d3a5fe31722d65f5706ef6d64d73232d3043220f14e5cfd3c2c83a83d68e20274b6f96b29de040cec8475030b6a8a87d29808dd381795c3d22acf5dc193b720d95a752d9f123c209ffba004e48dd06dd8c9e172bc9e087d80bc5216c0b0b6e77031241:b5b5950d3772d2eef88e1b0f5df5ffae2f2103885e71446d346fbb5daef94967a6b7b6e4be885110065876c665b7812de46ad31ec3bfcbeaee13ed0c1e0b300e17ace197d083aaf1726f53e5ef81b5a8c09222f260ee5f1f5404ab78d900d489688449b843bad3c498aac6d80b4639b76e6e81c55276a6f9c7cecd70b71aaaf2018ef76c0e30154aae86a5c86d4e8d0e4ec68cc427060bd56514f7238086bbef5bfca1f5671b18041838fd013572443dba48fbdd95ca740b0daa4327164a1e34677249708f77bd793e7caa6638b5dc9fbe6f0dfd4120209097209c93cedfaf21b6bf59ca6e99e6209639444f0e827bbcc0a61c3a237ca22a283213223ab658e712c7556238d3a5fe31722d65f5706ef6d64d73232d3043220f14e5cfd3c2c83a83d68e20274b6f96b29de040cec8475030b6a8a87d29808dd381795c3d22acf5dc193b720d95a752d9f123c209ffba004e48dd06dd8c9e172bc9e087d80bc5216c0b0b6e77031241: +eeef8074c2eb9a1cee2f2d3bb05325546a9fb7cbe44b599461fc5885f5fd9cac9b892941a0573b7a1673ef480f081168d9b7496a81f9177dc427ca1f84cbbf7d:9b892941a0573b7a1673ef480f081168d9b7496a81f9177dc427ca1f84cbbf7d:9ae39feade905affcbedd2e72a6f2429b3d1108e5bc1a9dbaf490a6299bccd94acc413adacc918b14afa85c78bc168cc00740c3da0e08183915f79b7fe3868ce2a7e886b32ad45009805bfb81b8c07b3b1022420c0f009b889d7fc22fd1997ae34198438ca94778575122fcaaf96e6502c33a75a129a2d0dbb073d93820d9c96683db318990be3fef4cafc890afbd9b1504c7439a08a065e7814ee4f9b6f57ee16baed3f0e3aa35dd23d3528a458919ad77048b4e2e6172346be249a50af02bc6c853304c208ae0ba02771262a0d8a465f71fa0635e53eb2ef0a847d56a0bcd7dd3fe077c92bcdca3069a4a682a2859928315ce3eb445c6072a71492ee82e172a20be0b648b756e6c775376f0c7c3df8e64288089c2f81ce9593c6e08bb1cc1b27fcbd392fc7952c55:6f7101984fd6892e2144b7d45619830caeb6713bfab4eebbe217c5becd249bd9d752eb76e9fa995e7c71ff7df86bb260cdda173ff5deec6af204b7dde011de099ae39feade905affcbedd2e72a6f2429b3d1108e5bc1a9dbaf490a6299bccd94acc413adacc918b14afa85c78bc168cc00740c3da0e08183915f79b7fe3868ce2a7e886b32ad45009805bfb81b8c07b3b1022420c0f009b889d7fc22fd1997ae34198438ca94778575122fcaaf96e6502c33a75a129a2d0dbb073d93820d9c96683db318990be3fef4cafc890afbd9b1504c7439a08a065e7814ee4f9b6f57ee16baed3f0e3aa35dd23d3528a458919ad77048b4e2e6172346be249a50af02bc6c853304c208ae0ba02771262a0d8a465f71fa0635e53eb2ef0a847d56a0bcd7dd3fe077c92bcdca3069a4a682a2859928315ce3eb445c6072a71492ee82e172a20be0b648b756e6c775376f0c7c3df8e64288089c2f81ce9593c6e08bb1cc1b27fcbd392fc7952c55: +61faeb15f857f6557862c8b8c7ef41f80545520996fcc1127b8c2491822201ae60a290c0fc425a0874673d94f9bb1400f9dacde9954f9f5b05dd48ab747a3950:60a290c0fc425a0874673d94f9bb1400f9dacde9954f9f5b05dd48ab747a3950:253b566eccb563bd6e480c69739b8e372519a3437254e0e5029cac86c71638f2df2a6cf9e56db2569934deba90db75547e3671747df64d6f2aaf3c110fa67a7094ccbe4cc5355f0d43235136ee26dbe37f4225d3bbfe245595280585fb548f894e86c516102580291fa7a02859557fb98eb588870828b0990ae9d74f3831da58946bc7a5ce1ba498b4e8be8989a3b50d7e8789f56b8b4fecbc2a33bfa3ef591a0fbcd932fa93e19f3a812ae5e4e3b4b242be7705a5874af73be310b0058266a378f23c1348524715b0ccc18d6634b23636c316ba6a1dd2fd5092c06716a717b54d0eb9fc7f636f85bbf225a2cf035b4b7cfddd75351682c0576c6b3ba5a1c0b25ec594e7709dd09a0079772ff3acc67fb6c1b37bb3742b726e77e80561d9ab73160b73362581da5b9c7f:31f90f50b2dc705f1d92f12ca9975d76f1b2826ada3cc185b0ed6c83860777bd8c489b59855a91f64839d49ba467985abb376c47a4908b271b8f77c58d01fd04253b566eccb563bd6e480c69739b8e372519a3437254e0e5029cac86c71638f2df2a6cf9e56db2569934deba90db75547e3671747df64d6f2aaf3c110fa67a7094ccbe4cc5355f0d43235136ee26dbe37f4225d3bbfe245595280585fb548f894e86c516102580291fa7a02859557fb98eb588870828b0990ae9d74f3831da58946bc7a5ce1ba498b4e8be8989a3b50d7e8789f56b8b4fecbc2a33bfa3ef591a0fbcd932fa93e19f3a812ae5e4e3b4b242be7705a5874af73be310b0058266a378f23c1348524715b0ccc18d6634b23636c316ba6a1dd2fd5092c06716a717b54d0eb9fc7f636f85bbf225a2cf035b4b7cfddd75351682c0576c6b3ba5a1c0b25ec594e7709dd09a0079772ff3acc67fb6c1b37bb3742b726e77e80561d9ab73160b73362581da5b9c7f: +e6b9cd4da07cb34f30391cf68f0d87c7cfcf68f810ffa40f9739c95deb037f71569ede0f04630b43a04c5a66b6a5636b766c75965984a7477e15491960fdd864:569ede0f04630b43a04c5a66b6a5636b766c75965984a7477e15491960fdd864:69def0523afda696f8448f9c1143abc26533e68695a090df0d9e43d0c0eff43583e6f709d2043c815fbb3f96ba2b0dc3be6fecad5dd38148788e4a0385a9fe7a921fcb8ccee0e4d3aed4bc3d216d84b414f9580b02820c03d92e675e685c4b5851f363bb4df97b417c3fd90022eeafa20dfbe82964f2ff073d255758fbe567c76b2c35e2b09f8a8d7afa32c6f5ad01bc3ebf6e210606db038ecb6820ce1ea4dd529fc1adfbc2a138565ac6d0f4a4109bdd47b8aa6ef4b8bede454680d1dbdb75fe1eb2e548d5de7cb6d792fef3aa0d8480a6030b30f104d7e76b58e9f476ebf2cc832923b50c50c111c3515fc518852323426ca778a596d3195da8585d8c3aa92083313a6e6585b70c98b185b472798a61cde77e62ec272f14b0d9eb4f22f9c7c05817da6fdefe7879a584:1e375c94bd809ca0cdd02f89ecec4e437732dd20a0a84b254eae889d8070e682d113b0be22e41e6cdc3be877680e7eeb7f0995e6622dc0b434fb0949dd994b0c69def0523afda696f8448f9c1143abc26533e68695a090df0d9e43d0c0eff43583e6f709d2043c815fbb3f96ba2b0dc3be6fecad5dd38148788e4a0385a9fe7a921fcb8ccee0e4d3aed4bc3d216d84b414f9580b02820c03d92e675e685c4b5851f363bb4df97b417c3fd90022eeafa20dfbe82964f2ff073d255758fbe567c76b2c35e2b09f8a8d7afa32c6f5ad01bc3ebf6e210606db038ecb6820ce1ea4dd529fc1adfbc2a138565ac6d0f4a4109bdd47b8aa6ef4b8bede454680d1dbdb75fe1eb2e548d5de7cb6d792fef3aa0d8480a6030b30f104d7e76b58e9f476ebf2cc832923b50c50c111c3515fc518852323426ca778a596d3195da8585d8c3aa92083313a6e6585b70c98b185b472798a61cde77e62ec272f14b0d9eb4f22f9c7c05817da6fdefe7879a584: +4d9044f17b5a0977dc5aa9916a924300a244a1ef7f060277ad4978351ea64291ab9c0692a606b2567c19c30f9faa3b4cfe72fb237077767b76d3b2ae1490a6d4:ab9c0692a606b2567c19c30f9faa3b4cfe72fb237077767b76d3b2ae1490a6d4:7c8c7189af67327af1c6dd2c30e975f190e3b38d008b4585167e0d450740d46734587f6d208784245cc5cb062a2a277f17ebb2746f9bdf4a8237ca479ab0a430177e19ed7dd3622576b14cdc08282214fe5ee4d76b43c16ac90864c51be8aed45d7b980df7917f290fdf795846465f27fcb7e5730637944f0577c92f32375e995bc0cda9d7196f2c0c1ac8b80d12a0439963ebd2254c347703575816e7964c13d44d629280c312ea265344de38f3b18d9150f8f924afb44b6bfb9eda513d59e65e2ef18666e6c2a21c4018665befe92cae581d3cb14e23e97d830002cb90931ae0210068af394ebe351be5b817f3674bfbf40049030e4fe505d34a1d502a2c50d8e638e926c230676b7edefb6bec77b1c0ce609325287ba5fdd7a9976987bd07fc6a4344956ebf818f08586c:6fa48aea4d5b9af65af964cdb709443a11fa84f7d44acddab16e04a6fcefb27ae33c05b36da13c23de517d6e6ac574a03ea630ba4fbb958131129aa7f1354c017c8c7189af67327af1c6dd2c30e975f190e3b38d008b4585167e0d450740d46734587f6d208784245cc5cb062a2a277f17ebb2746f9bdf4a8237ca479ab0a430177e19ed7dd3622576b14cdc08282214fe5ee4d76b43c16ac90864c51be8aed45d7b980df7917f290fdf795846465f27fcb7e5730637944f0577c92f32375e995bc0cda9d7196f2c0c1ac8b80d12a0439963ebd2254c347703575816e7964c13d44d629280c312ea265344de38f3b18d9150f8f924afb44b6bfb9eda513d59e65e2ef18666e6c2a21c4018665befe92cae581d3cb14e23e97d830002cb90931ae0210068af394ebe351be5b817f3674bfbf40049030e4fe505d34a1d502a2c50d8e638e926c230676b7edefb6bec77b1c0ce609325287ba5fdd7a9976987bd07fc6a4344956ebf818f08586c: +75ad76bb4c0c229a5adc79e444b13f88a96459862c8cf0ba498d0c996af94a7af074dd2b9c1c309105ec951bb5812a91ddb54023b3809ab379c56af0461af617:f074dd2b9c1c309105ec951bb5812a91ddb54023b3809ab379c56af0461af617:0ca8c1c74128d74e9d0a7bf8964291d074917f2f9920efb911520567642a50a615abcbd00aed4abbfef1a983cce333e1d0df3e6404fb9043c6803914cd5fffbc66a0790c7878a24089a571f895662a1d18be3f01ff97fb3323334b6f5baf96551448e4090d033c464294d09133b151d5b5c6321b50e2241de0ef6f882889ccf4ad3540d5a1e3f7548fb13be71c16516606e79d0449c2a08e5dc23148843c84e97ed24069161c8e75208f33e95b3e10d1d49a2faef9d986ab62809f62ad39c7cc871f375a4f5a6faf104d7e11b890cfb0589902685216ec07cb8e8e9e7a7c43635e23212b69ca3b7ed54f0b97949e3d9a6662f8e4b3ab09cd495294c331c047d86ee785ff658bcd7fcf9c480605ce05e810068d60fc9b26b5f063eb9000d2657a5094284ac80f1375d0b66d6f5f:0c4643a8be6dc22f4beb6bcc70c6172ec7608378653cb4e99f3ae795eadf4e982a297609ca7938f5df632b095628cb75062d3d51fc0f3323bfa7b22ec4d472050ca8c1c74128d74e9d0a7bf8964291d074917f2f9920efb911520567642a50a615abcbd00aed4abbfef1a983cce333e1d0df3e6404fb9043c6803914cd5fffbc66a0790c7878a24089a571f895662a1d18be3f01ff97fb3323334b6f5baf96551448e4090d033c464294d09133b151d5b5c6321b50e2241de0ef6f882889ccf4ad3540d5a1e3f7548fb13be71c16516606e79d0449c2a08e5dc23148843c84e97ed24069161c8e75208f33e95b3e10d1d49a2faef9d986ab62809f62ad39c7cc871f375a4f5a6faf104d7e11b890cfb0589902685216ec07cb8e8e9e7a7c43635e23212b69ca3b7ed54f0b97949e3d9a6662f8e4b3ab09cd495294c331c047d86ee785ff658bcd7fcf9c480605ce05e810068d60fc9b26b5f063eb9000d2657a5094284ac80f1375d0b66d6f5f: +adc6e9b2e103b62c24ad4346410e83a1a0bd253e4abf77911850c6d9666e09f9fce316e33c910821beeddd634bedc58ee57999a76ece384605283b99b543b78b:fce316e33c910821beeddd634bedc58ee57999a76ece384605283b99b543b78b:8cccd98ebbf2439ffdfac41687638faa444e1ca4b63d13e898eaa8355492f28813ab813fd01510e112be106b2045d30f63335d248904d521de181abac03e3d2cb2d16c44b3b012a0c51f9901aef9056c724d7a2c6b2acb0a07555940e4c6e21154890611adeb6489f461d3e5ecd1af5a4d2b0adaf41747436eb414757a8fe4775674e3c6e5de4569d6fc6c788e10905eba32c270a393e6f721a765294e2ac99a9b6e534d3df08d1db97d602ac3195cb0b77f5bd4acaf737fadd6991f0688abc74918047574eac28289739a664e0e0e20574a2c25fde49d14539db1cedd4a9204a70acff0a62c8f25cd768ffab15c4db316840a4d1bc92e212670be07c5bdcf537590607dfbbbb4d9f98b89da0b4df7d88f3eca4814d16bfa20c8d2fa94f9f259f2ee2d3a83c9e4171b1a262c4b99:cb017d6d2682c9854366259aa35f30d491cfaa930998c297dbddc6aded5b3d401cf76d80d8a2764de131718b6e0c481d7196bc72579716b0c0f6ff053e68c50c8cccd98ebbf2439ffdfac41687638faa444e1ca4b63d13e898eaa8355492f28813ab813fd01510e112be106b2045d30f63335d248904d521de181abac03e3d2cb2d16c44b3b012a0c51f9901aef9056c724d7a2c6b2acb0a07555940e4c6e21154890611adeb6489f461d3e5ecd1af5a4d2b0adaf41747436eb414757a8fe4775674e3c6e5de4569d6fc6c788e10905eba32c270a393e6f721a765294e2ac99a9b6e534d3df08d1db97d602ac3195cb0b77f5bd4acaf737fadd6991f0688abc74918047574eac28289739a664e0e0e20574a2c25fde49d14539db1cedd4a9204a70acff0a62c8f25cd768ffab15c4db316840a4d1bc92e212670be07c5bdcf537590607dfbbbb4d9f98b89da0b4df7d88f3eca4814d16bfa20c8d2fa94f9f259f2ee2d3a83c9e4171b1a262c4b99: +37fc1beda4060b6c57883ddba0776c2bcf5ac28a651326021cca97723730fbb07bd7bf1c99dc82e06f08bb454d8fb288a57927e07ff1b12af15ee2c12fbb6b3d:7bd7bf1c99dc82e06f08bb454d8fb288a57927e07ff1b12af15ee2c12fbb6b3d:3dfcac0265a024a83cb932674489a163aac314bf3d969f27596e451733b99deba5eeb779210baf95bf545a1ae6b8a915860693ee890f939320e06a844483d18c6a1bcd03c638bb7d1fe2a82eb448a311b1302ea6428f54a39f45a4d560be1557a2b254c45c137f45cc68356836e21bed0b7f73a518ce09db0be393927c339bf2a4b5987539404ce650284de12e3b553b262efe23848332ccfdc35e791a0ab43f139c71ed0fcb2d173bb377ee46b1a9dca9277e77df855f2830251e31e26acd86763c8d7eac22c882fc174f2b5e75ca6ad1ade03f942bb2a13bf541906159158c68363c7480c5b27a99320f8283a2699d4369c071c50dbd90b7792e4772efbc0b195bce84cc4dcfff7072a48968db69f9feddd0f9ced659eb5db7167f35f988cec114887dcbfdf27d02d300b3e1abec:a01dd65fada27039f168b123419d8abfbda48c572ece24fda06e1a5ec31e084f4ee1cbf9961e88ed51e189fcb7f5f235de1e5b28d08f2bfca190b0f019ecc2073dfcac0265a024a83cb932674489a163aac314bf3d969f27596e451733b99deba5eeb779210baf95bf545a1ae6b8a915860693ee890f939320e06a844483d18c6a1bcd03c638bb7d1fe2a82eb448a311b1302ea6428f54a39f45a4d560be1557a2b254c45c137f45cc68356836e21bed0b7f73a518ce09db0be393927c339bf2a4b5987539404ce650284de12e3b553b262efe23848332ccfdc35e791a0ab43f139c71ed0fcb2d173bb377ee46b1a9dca9277e77df855f2830251e31e26acd86763c8d7eac22c882fc174f2b5e75ca6ad1ade03f942bb2a13bf541906159158c68363c7480c5b27a99320f8283a2699d4369c071c50dbd90b7792e4772efbc0b195bce84cc4dcfff7072a48968db69f9feddd0f9ced659eb5db7167f35f988cec114887dcbfdf27d02d300b3e1abec: +8d42f4ddd2bbd2b827b0a0d31d8f758ebd13a1b9b3712228948ca610bb8858e5b7354898794f9db0a8af6eeafcdbdf011d3fbef0212ad938a4a4ad27ab16ebbf:b7354898794f9db0a8af6eeafcdbdf011d3fbef0212ad938a4a4ad27ab16ebbf:e3a2bebc0496d8974a8f4061880369314ed9e440c1b77e26fe5071ce694ffd2136db0c4d5e880e6000083a75c90d3cf72b9cf5a2b1a9002c2701a2ff59b0699a8f42d79dd8a5fb71a8125453d91fb80080a3f0a16584282f17ec7dfdc2e5c69c4d9bdf484d55944dae273f211cfb76ad37da45871365439af35eea1fbecd4ca679b59b5e01bacf49c7f4e5efaa406ba1daeb085482af5ded89dc6885ffbe3d14d2931b83897e28ad06e5564e2789baea81bd932aa279fe8e324b9a8ef111c2abe2f137d4bb50d8ab76cebc0bd982a23919751ad4d49e88eb14173d3310289a872317e4a451e88d54320891870f15b2d53324430877a9fb5b49bb929f211c5b89764dd9c3a595a1451e9f85a238540002566e53a99ed1e6ddc9b4853f455edb4cf1980d56bbdc1313a36e76ea9cbb048a:70764be39c6dca0f067abe1eca490fda951fd4e9499695266e270b9b05eae706ca8d1ca6a92d7c488ec6ad8ba11457a42a5e31702a9c2bce892dc40535c09f01e3a2bebc0496d8974a8f4061880369314ed9e440c1b77e26fe5071ce694ffd2136db0c4d5e880e6000083a75c90d3cf72b9cf5a2b1a9002c2701a2ff59b0699a8f42d79dd8a5fb71a8125453d91fb80080a3f0a16584282f17ec7dfdc2e5c69c4d9bdf484d55944dae273f211cfb76ad37da45871365439af35eea1fbecd4ca679b59b5e01bacf49c7f4e5efaa406ba1daeb085482af5ded89dc6885ffbe3d14d2931b83897e28ad06e5564e2789baea81bd932aa279fe8e324b9a8ef111c2abe2f137d4bb50d8ab76cebc0bd982a23919751ad4d49e88eb14173d3310289a872317e4a451e88d54320891870f15b2d53324430877a9fb5b49bb929f211c5b89764dd9c3a595a1451e9f85a238540002566e53a99ed1e6ddc9b4853f455edb4cf1980d56bbdc1313a36e76ea9cbb048a: +b62de5a1acfe4ca2d1f0c132afcbdae66fb29a02f297fbc2407fadbbf2454200b63b2d0bf355f7b6d0bac07403411c40afbbb2f707503b3fc2cee8a1c7d0a838:b63b2d0bf355f7b6d0bac07403411c40afbbb2f707503b3fc2cee8a1c7d0a838:e659e51d7b193c4b8e2b3ed73a9d7557ed2bab6153883ab723592f730a914567142b3fa435db3219f83a542dc7a4bd805af666ea865b853146f8e3a9fe870711f90d12b0693492af2a1edf99a16458f781f1266ec437a5296a822ca9d69ce844b5c59097a2a56f3eb8fd273a636116db774300922d45b744657a692f5e8bfbcb06d2422818aeb51e7cda68acfbeda16e7c79580dcccde24e8e3d601b16e063b43a6d0d1407552f7504f5be19882e4ffe32344f5f473e73a8f6ed37b0d8d9e5e0a0dc9828395bcbd8f3a4e3124869249d058be0e045de0b1e12b1c83ba0aa227c95b82bf742c3eac0152b33e6d19be8b33a35bf705daab10622a90aed022ea6e439ed50a9308437929924ba3ab111ad0caa6feb0a6eb165824ebdb0866571efc07e5222ed8686b14d9270bf76b945d52014:5cdb00e98de73eab480be42f8a8a6163809a0d37101b6a5a4eed6a0c92030d09a5562c729080ce6f6594c8fafb1f594772db7a90a9e7da15896e82f70569390de659e51d7b193c4b8e2b3ed73a9d7557ed2bab6153883ab723592f730a914567142b3fa435db3219f83a542dc7a4bd805af666ea865b853146f8e3a9fe870711f90d12b0693492af2a1edf99a16458f781f1266ec437a5296a822ca9d69ce844b5c59097a2a56f3eb8fd273a636116db774300922d45b744657a692f5e8bfbcb06d2422818aeb51e7cda68acfbeda16e7c79580dcccde24e8e3d601b16e063b43a6d0d1407552f7504f5be19882e4ffe32344f5f473e73a8f6ed37b0d8d9e5e0a0dc9828395bcbd8f3a4e3124869249d058be0e045de0b1e12b1c83ba0aa227c95b82bf742c3eac0152b33e6d19be8b33a35bf705daab10622a90aed022ea6e439ed50a9308437929924ba3ab111ad0caa6feb0a6eb165824ebdb0866571efc07e5222ed8686b14d9270bf76b945d52014: +9732059d7bf0200f5f30412430336be4ef1e3cae62938ad08729ce3ba714cfd40de8425f5e30b2b8aebb8072009a30cf0411c3c8238f4e4208760c56c33e434f:0de8425f5e30b2b8aebb8072009a30cf0411c3c8238f4e4208760c56c33e434f:1a13e7ab603b48eb896fe17173fb31950b0dcd5a35ffdbe1371c7a5bfba593317589d9652d88797729180b8d0e515abfe6548f160421e537d5c94aef2b34c7ebb097420003bc0f361b423e7e14630a803c118202540049f68c9cf46fae0368d162e400d77bb4523cf6c753b975c245bc99ed2f413a9d06c2da6ce0cc0987b6406b809e8eb319033d2de9131dee3b1b7b5c95d653ced8fccf998da1768511eca4d3c5f735adab96503b3551803e4922635095ef811be4c08a6cbac917cbe6cd91a4ae5a330ccec0e8e815371217a3de62f2d2d61466219833f33447132f4d43350c58cbaf422475edb128c56d80a495726b1fdbc56551eb72d0f4fec26ba8bff5eed6774b85039a5292834b5d1cc1b09ba0a3954d29323673f5e71276a12ac4c579355bf1ecca48e6a716b9fcecdc565c51b9:fba1749b641dd4df34664bc43c00468c7d75e84afad72de473fd1e9c87da15ea604fc2549a1a867fa80850e9c2a59cd99053886760a8d9764b84dd672676720d1a13e7ab603b48eb896fe17173fb31950b0dcd5a35ffdbe1371c7a5bfba593317589d9652d88797729180b8d0e515abfe6548f160421e537d5c94aef2b34c7ebb097420003bc0f361b423e7e14630a803c118202540049f68c9cf46fae0368d162e400d77bb4523cf6c753b975c245bc99ed2f413a9d06c2da6ce0cc0987b6406b809e8eb319033d2de9131dee3b1b7b5c95d653ced8fccf998da1768511eca4d3c5f735adab96503b3551803e4922635095ef811be4c08a6cbac917cbe6cd91a4ae5a330ccec0e8e815371217a3de62f2d2d61466219833f33447132f4d43350c58cbaf422475edb128c56d80a495726b1fdbc56551eb72d0f4fec26ba8bff5eed6774b85039a5292834b5d1cc1b09ba0a3954d29323673f5e71276a12ac4c579355bf1ecca48e6a716b9fcecdc565c51b9: +9c7f6f379e3857007e2ac6324cbbced57ac9eee4477813f83a81fc8cefa964d5a54ba396d687634d3eccf41c5782494f5f10a521a1e5d388523d80eeba5b0b2b:a54ba396d687634d3eccf41c5782494f5f10a521a1e5d388523d80eeba5b0b2b:3f2d3072fe7383e541551ea9abdbaeae6a464ae6b9f0ba786a441b2d08da5bcada3c5424dc6931d6b39523e2de0a0c2e4e6b5b8cda925e5eac938416a2c51bf13d49531d7ec7114b1c82feaf90f3f87591e397d02702f8ec1b30d99f5be7d2203e4fe4db2ea47e7b4589d8ac506248d7347466edbc96ea32bf3a6ea7502dd60c9e84902715ab2c6ca68f5b00e1d909d83aa6ab662d8aea870ecd861fec69f2eec0ae677d2995b0ed688faa8ef78244e0d1195697b07122ceaa11f5a6ea58fbdfa2e2ec2df9d18693ae96d47127556e91f0864982c13419b04a63f208e730d26951882aefe001bca3408bd9862748c6cc876c28cac3bb2eb3395818c2091e0fbd7a0b4468c6b0d00cd008c11c3c3ad01080a1f5a40ae2e4b0c3a071efc8e1d1ba6ace6d4df0ff19829b0c680b3aeb759177ed34:65685f9ca5982e15a22ba3c83a0348348482dfae57cea178f0780c057baebe4af632f984540a26019a7fb34253c9ece7ff308ada233ce0686347ab5b21ce570b3f2d3072fe7383e541551ea9abdbaeae6a464ae6b9f0ba786a441b2d08da5bcada3c5424dc6931d6b39523e2de0a0c2e4e6b5b8cda925e5eac938416a2c51bf13d49531d7ec7114b1c82feaf90f3f87591e397d02702f8ec1b30d99f5be7d2203e4fe4db2ea47e7b4589d8ac506248d7347466edbc96ea32bf3a6ea7502dd60c9e84902715ab2c6ca68f5b00e1d909d83aa6ab662d8aea870ecd861fec69f2eec0ae677d2995b0ed688faa8ef78244e0d1195697b07122ceaa11f5a6ea58fbdfa2e2ec2df9d18693ae96d47127556e91f0864982c13419b04a63f208e730d26951882aefe001bca3408bd9862748c6cc876c28cac3bb2eb3395818c2091e0fbd7a0b4468c6b0d00cd008c11c3c3ad01080a1f5a40ae2e4b0c3a071efc8e1d1ba6ace6d4df0ff19829b0c680b3aeb759177ed34: +a478f35abb73727b6be6ee5e56eec323c9517882fd6919360ebbbf5d5cb8b83a7a6e266a54d135dda0009ccda8a94a4712ae5cb14761e8436e97c4b7814d8e8c:7a6e266a54d135dda0009ccda8a94a4712ae5cb14761e8436e97c4b7814d8e8c:0173a34050b43748061ff8f5a3d7c43b6360847786e8bb75e536fb47b645b214f221ba24d83d28bc025024663e534f90f6e83a93d8bddeda2cd8808155652a908c437c2db6f3ed4912f57ca5b97928a73be964af59df4439854bb006fc295a87b7b72239c7fadfec40715509d98579daadfb8d524b4cec6620705efd4104c297144aea722974e12c5ecee5391ef2d93ac2b124e4ac496147c8b70363585d7078ccc53e2ae593350bc25548a0542526ab00afe477a0f4b27397c72bc74a8a8ab156e62b8bb47c3fbb4b34913e459687476bf33142c614702107ffe2cc01e25fa30275e1e2e63cea9168e4a47c02de097d4d853b27675c5bb330b94a974ead85e2bdee8ee17cbb5653346658df2f91f6bd739491dd71988b3a976a3e2e7a9d137410f4acba9feb5f11798c9a43b6adce14365a7c6d:9d16fd40b9f8dd9b4a1a8c6d703b9fccbb940b1e0ae77a5970374af0cf726f4479fd30d7dff5cf53494d9a296ab6b9e46ea6c136b4db2c71c21b97c1c8254d0a0173a34050b43748061ff8f5a3d7c43b6360847786e8bb75e536fb47b645b214f221ba24d83d28bc025024663e534f90f6e83a93d8bddeda2cd8808155652a908c437c2db6f3ed4912f57ca5b97928a73be964af59df4439854bb006fc295a87b7b72239c7fadfec40715509d98579daadfb8d524b4cec6620705efd4104c297144aea722974e12c5ecee5391ef2d93ac2b124e4ac496147c8b70363585d7078ccc53e2ae593350bc25548a0542526ab00afe477a0f4b27397c72bc74a8a8ab156e62b8bb47c3fbb4b34913e459687476bf33142c614702107ffe2cc01e25fa30275e1e2e63cea9168e4a47c02de097d4d853b27675c5bb330b94a974ead85e2bdee8ee17cbb5653346658df2f91f6bd739491dd71988b3a976a3e2e7a9d137410f4acba9feb5f11798c9a43b6adce14365a7c6d: +ffe825148c0959b3a68de86ad8e8af7fa5e078f363dc124213c90020da0c9089139152a0bd22962dd919ae3e0b1620e03c033c2ad0a3979ec6bcd1705e23d598:139152a0bd22962dd919ae3e0b1620e03c033c2ad0a3979ec6bcd1705e23d598:f125780d0cd088530f0c87b70bd42ebab56adb5ad4345f929ae5deae07fb55322153a8f023d38843bf5d6a93fe993eee71bc2ee563b25a50918f03efdb5dbf7269add69ded3e66953895620d9b6cf46ba2348f8d66d7f092235e378c1e3edfebeb78084bc8dea013f9933aae14a041948276d01f1cb5834b0e590e13d931d19292bb1d8041ff2fe2e1171a2e0b9a059821d0924dde7f3b1bb59813f5e3c63520aafb8801ba62c7097d4d8cf437a568a7f0087c6ea0fce6e568c4883f1cd12c749d06a6feb278f1086a8b04769921f78a9959062ab06f98ee80c2c7854ffa760f86a89ee1a51266053d195e61bb1dbd18dd89ff394e408ace0f641a395d56118ea72b7d8adf78b1655ecece7e8250e8a3a91cb8fca0d9ce0baf8980a387c5ed4318663280e5b4531f3187c47eaea7c329728ddd0e40:fe4e89ee31786c0a3d3de3649bb93f0b8aef1caf5a832ec5e4067810705adddf539b8f4e05ad08cf3479e45b42c96528f6d59a4625703ddbf15b63093965d80df125780d0cd088530f0c87b70bd42ebab56adb5ad4345f929ae5deae07fb55322153a8f023d38843bf5d6a93fe993eee71bc2ee563b25a50918f03efdb5dbf7269add69ded3e66953895620d9b6cf46ba2348f8d66d7f092235e378c1e3edfebeb78084bc8dea013f9933aae14a041948276d01f1cb5834b0e590e13d931d19292bb1d8041ff2fe2e1171a2e0b9a059821d0924dde7f3b1bb59813f5e3c63520aafb8801ba62c7097d4d8cf437a568a7f0087c6ea0fce6e568c4883f1cd12c749d06a6feb278f1086a8b04769921f78a9959062ab06f98ee80c2c7854ffa760f86a89ee1a51266053d195e61bb1dbd18dd89ff394e408ace0f641a395d56118ea72b7d8adf78b1655ecece7e8250e8a3a91cb8fca0d9ce0baf8980a387c5ed4318663280e5b4531f3187c47eaea7c329728ddd0e40: +49aff421a7cd12722aa84c48c1fb1c5f8d9e277d0a99ecbc9348c3aaa74be42288d2c26266f493bc67578ca0b1f51160cf0fdb6a09a906db9faa686f11f8208d:88d2c26266f493bc67578ca0b1f51160cf0fdb6a09a906db9faa686f11f8208d:70a1ac144b75fda75586a79c36fd39cce5f5cae2e6375852d3b62a9630336a293ea6d2ac6e5b57da21ef364a595bb0750f5bf4d2b320676423870e4b8e0869601f16680619048c4ede276da69f205a70176e25ea04bd089763e709ba343fc8831e52044eabf9441e6997f8ba1aeb9ef0f491170667a7f5fc9627cbd0551b76be27283a4b0c5f667846688226a115ee8020df08042b19b59fe551316a6cb6916860b9ecd74154b4051038a17352372ec14d3c957d2ef50ff786189a8aeb9c08f45eeb5eb8b040339974aa9798c425d7becb228c447a6d0b3cef271893e0f7076e223a7e87c6a3d270a033bc97a4565edce0aa91ffc3f7801775a6f29b230245bd71fa034353de372395d1bfcbdebba081330f7c076be99c2cf4867f15b78d52f46fc7391c9cb95e5d64643baffe72a8e3a650667fbb3e:749181284df05dbe5974b91782a1a76ea08642cb0f0c98db586c575c210cdc8b651bd34b757ae38e4b6be9465235bd0eca430e26c3eede561c6e824dfa200e0a70a1ac144b75fda75586a79c36fd39cce5f5cae2e6375852d3b62a9630336a293ea6d2ac6e5b57da21ef364a595bb0750f5bf4d2b320676423870e4b8e0869601f16680619048c4ede276da69f205a70176e25ea04bd089763e709ba343fc8831e52044eabf9441e6997f8ba1aeb9ef0f491170667a7f5fc9627cbd0551b76be27283a4b0c5f667846688226a115ee8020df08042b19b59fe551316a6cb6916860b9ecd74154b4051038a17352372ec14d3c957d2ef50ff786189a8aeb9c08f45eeb5eb8b040339974aa9798c425d7becb228c447a6d0b3cef271893e0f7076e223a7e87c6a3d270a033bc97a4565edce0aa91ffc3f7801775a6f29b230245bd71fa034353de372395d1bfcbdebba081330f7c076be99c2cf4867f15b78d52f46fc7391c9cb95e5d64643baffe72a8e3a650667fbb3e: +703a6e2b62d0090c61d8659b6a963e03c9d62c1b38f7d70e5f9ff05590cd0360370c21de6ef2fab534ada999869c90bc9b92ccbf249b79d39d95441d1ede210a:370c21de6ef2fab534ada999869c90bc9b92ccbf249b79d39d95441d1ede210a:d42a1756e84df4b4e9773f86f7674a2cd78e71e40aa8f644e6702dfbc2c2c5ca90fc242e9cb0099cc8f2c2d3136baafc0ff695482fdacdef9f565610b6e1900722f435c6385b35e9f6c436ca037e03f64e2233dffa58db3b91cc1daa0bb0c54c8a43e469d2cff7fa2bf8f5d1d877931089c82ed89aba42f2ee2b86e445cfd09f4cd78b35191bf467e784eef75dc987e046d37d4d4e8e9bbe14af80d03a1f40898384b9d3279fac9c57fd9c7eecbe19a5acc15033b84e07fd0e409bdbd5a57f65641183a6c0a8ec426d1f1d223166ff0a1900b2e92b7d85835d019d17775e5093ccd126f90f63cb7d15cbeb531324219cd64ded6714b21a65371af07210dfdf0e4e58ddc7d59f4cfa65c421d814ee2c9bf6dbf64873d579b09ee5dcedd733063e039ac9a5f9ca4c2525a4cc8e984da7185e2d64fad81c8a:e5fd64da028800c6ceed068a5e596f1621c70a8cb138b31b32647eb4b07bd2ecc5942c18844f367033f67398e314ba2c7ccf299c069787777025d845f2aad60ed42a1756e84df4b4e9773f86f7674a2cd78e71e40aa8f644e6702dfbc2c2c5ca90fc242e9cb0099cc8f2c2d3136baafc0ff695482fdacdef9f565610b6e1900722f435c6385b35e9f6c436ca037e03f64e2233dffa58db3b91cc1daa0bb0c54c8a43e469d2cff7fa2bf8f5d1d877931089c82ed89aba42f2ee2b86e445cfd09f4cd78b35191bf467e784eef75dc987e046d37d4d4e8e9bbe14af80d03a1f40898384b9d3279fac9c57fd9c7eecbe19a5acc15033b84e07fd0e409bdbd5a57f65641183a6c0a8ec426d1f1d223166ff0a1900b2e92b7d85835d019d17775e5093ccd126f90f63cb7d15cbeb531324219cd64ded6714b21a65371af07210dfdf0e4e58ddc7d59f4cfa65c421d814ee2c9bf6dbf64873d579b09ee5dcedd733063e039ac9a5f9ca4c2525a4cc8e984da7185e2d64fad81c8a: +76849c188e3edd0ff5f8fb874dc0456645518445e41a7d6833e616c3c48c9868d670e2ea07db60c22ab79a93ebf49d22a6245ee3af07b3be584eda694c37729e:d670e2ea07db60c22ab79a93ebf49d22a6245ee3af07b3be584eda694c37729e:1eccb0bc8eca3ab5bee68c5f8caa34536766c705f50827db7ac375d4fe30b58ffb7e2fe490cc71a8ff86c006d6174d05793ab8a55dd51b06de417bc0ac452cdc7cfb0bb00362b6765d20db23eb1848027064a1d9091d3b10ed776f28b76768bdfc08f0bc511f76faeba76cfc4cb5c83dc9ebe8a8d79edca923eccd524009cafedc90e3ad87d1392e1fccf4e60ccab95dc0ab54bf44245a007a96d46634b1b2965b829c3d7daa765972b54a7b365b6f34d77d7176acd8d894f6b417091b6c00edb7a4e81379988bfcecb692e9c3c4310a7e240e5c1063cde113f22a684a50a112ff47d3898812efb92637072b86163ad89316d221195acbfad0a03a1fbc2d967fe83f84c8459fccd490b9c5b3e55d27e9484e943c417f2128d73701da28f49fd3683f33a39cdee234bd305b9491e2f3eb621be3dd1dbbb31b:7141399d51daa6eb4519bf3f01b233920fa908fefa612f0cd7d5af8a9a3c44190e3f6384a8d14d37c97030ef5018cf8aee8aeb1569a73d84862a59b7df72fe091eccb0bc8eca3ab5bee68c5f8caa34536766c705f50827db7ac375d4fe30b58ffb7e2fe490cc71a8ff86c006d6174d05793ab8a55dd51b06de417bc0ac452cdc7cfb0bb00362b6765d20db23eb1848027064a1d9091d3b10ed776f28b76768bdfc08f0bc511f76faeba76cfc4cb5c83dc9ebe8a8d79edca923eccd524009cafedc90e3ad87d1392e1fccf4e60ccab95dc0ab54bf44245a007a96d46634b1b2965b829c3d7daa765972b54a7b365b6f34d77d7176acd8d894f6b417091b6c00edb7a4e81379988bfcecb692e9c3c4310a7e240e5c1063cde113f22a684a50a112ff47d3898812efb92637072b86163ad89316d221195acbfad0a03a1fbc2d967fe83f84c8459fccd490b9c5b3e55d27e9484e943c417f2128d73701da28f49fd3683f33a39cdee234bd305b9491e2f3eb621be3dd1dbbb31b: +83ae48ad70da0bb3cdf87481ee2c0c8571c2ca986712f8bc2329e9a3e33383c5b785309000df95f5a04f7d89c4113301057adaeeb29bcd28d99371b537bba2f6:b785309000df95f5a04f7d89c4113301057adaeeb29bcd28d99371b537bba2f6:b7521d3f71c679fa7037fe7488a641f6b97c49454acc8e36b903d8f9ebb54d89cb56efd19e04ba6a7c8f48a7d3ec9decd3f1cd0faf6e978118e6adce9c6c6be63c6a6a1ae21651828479a46bc9a0f7943040f940a0d470c8e577c5d575cb53c1bf3ab1feb050dcb6fef0ba4447f299fdb9f27ecb0714ecfefd74bad7b122a462c24a209848a03389074578c5bdc36396d809b0f14018da64917e6bf87ef405c8f3e333ff9c3baf6339667620794bb4743f0514b5de7d7fdd947a7e3501ee88efad159e33a1072fbb99c7c71e9d13a502d5a07c4f817eeb7f0c5319aa41a96d5ff4f15a73c29b571fe211090e172c8db518624612a5c371a9d7cef6de35ebef96e88e1a78af3bd5dd35251ab54d73718f3e70d2d59021531dc73184f0fc69c2e92965844ec27c1c02af5e9a3469de355db2256e0ec2a4eba30a:43332351d3fb7b45fcf37c607d442ea80dbda2cb69c2884f424e65ea3a331ed8472d4368405cb736b2d6685ad782e239fe833ed789a2923185166f608342ee05b7521d3f71c679fa7037fe7488a641f6b97c49454acc8e36b903d8f9ebb54d89cb56efd19e04ba6a7c8f48a7d3ec9decd3f1cd0faf6e978118e6adce9c6c6be63c6a6a1ae21651828479a46bc9a0f7943040f940a0d470c8e577c5d575cb53c1bf3ab1feb050dcb6fef0ba4447f299fdb9f27ecb0714ecfefd74bad7b122a462c24a209848a03389074578c5bdc36396d809b0f14018da64917e6bf87ef405c8f3e333ff9c3baf6339667620794bb4743f0514b5de7d7fdd947a7e3501ee88efad159e33a1072fbb99c7c71e9d13a502d5a07c4f817eeb7f0c5319aa41a96d5ff4f15a73c29b571fe211090e172c8db518624612a5c371a9d7cef6de35ebef96e88e1a78af3bd5dd35251ab54d73718f3e70d2d59021531dc73184f0fc69c2e92965844ec27c1c02af5e9a3469de355db2256e0ec2a4eba30a: +39e56a65623a0aebade0da12ce1df378bc924073f73a549effaebc465d1a78e283da8ad50bad09eb3e94c725df3cc3a119736adc859ca1a10503f48ff2fec596:83da8ad50bad09eb3e94c725df3cc3a119736adc859ca1a10503f48ff2fec596:a96dc2ea3fa1351492a4619d9194681f8ec400a97158244482653838ccb7e156a82d564368f83a6ee1be46bc34b817200e8464c3d12b5ef2c50b19565b881c4c3d4563fb947eb47c3ee9c1ee7853269874455bfacba305f307d1ac5309eeae5c07fa5c4d428edbc8b9528c4415243a9ef580aff8fcfb12000a71fceee89de97f90279529bcc822ed3cb34c82ba5fec15f4945663636d67b5feceacc31d25f98aea07f7800d5a1034251cb91dd0963ec2c1a54773a4d96c18357f8d101de58e932f8c6cdde8e3cfcef5a7443fdba7b78320403c0196844724a612183e34bdd808ce7b958861ca37115730eaede1fd0baabe976efefd0365fdf926776c536f47ff80de5c18291bb7e9f1b913ffd1d94468b789752fae6ca897c0cca53ef1e731d00c8bdbe8929ea6b1dce1f31a20688d37b0f3a2b4153b306bdba1:398e8260011f57d8ac8c58d5457bc652c7414aaf6fb2f426b7899056605c0afc28392423b2b571f5e6c3c7f6d60245e53ebd03bdc5ad3c1ad8738cb32214d00fa96dc2ea3fa1351492a4619d9194681f8ec400a97158244482653838ccb7e156a82d564368f83a6ee1be46bc34b817200e8464c3d12b5ef2c50b19565b881c4c3d4563fb947eb47c3ee9c1ee7853269874455bfacba305f307d1ac5309eeae5c07fa5c4d428edbc8b9528c4415243a9ef580aff8fcfb12000a71fceee89de97f90279529bcc822ed3cb34c82ba5fec15f4945663636d67b5feceacc31d25f98aea07f7800d5a1034251cb91dd0963ec2c1a54773a4d96c18357f8d101de58e932f8c6cdde8e3cfcef5a7443fdba7b78320403c0196844724a612183e34bdd808ce7b958861ca37115730eaede1fd0baabe976efefd0365fdf926776c536f47ff80de5c18291bb7e9f1b913ffd1d94468b789752fae6ca897c0cca53ef1e731d00c8bdbe8929ea6b1dce1f31a20688d37b0f3a2b4153b306bdba1: +4b9921852f409a323ae38175e8d76a211fc4d9c654178eea3baa7a767a6fda064c723e436b6bd97f44af52503b21cc50d5f6ad6cfc8288345dde8054e995582e:4c723e436b6bd97f44af52503b21cc50d5f6ad6cfc8288345dde8054e995582e:3f33d8fb83e68741090a37bedd745cf141aaaed8c92ffa742a52561777885805ace14246ab98a8cb598c9ce3de9b29bae5fa04b1cf828de11aff80a7ef8a3a38aede4f3c3563a25d049badcad5ed7e47fdbba6e111307eebe9ef4906bc989728b76e84afe808e6653b271e21104aa665f1898dd2aab23090e22b4e344a2616fbd8ee4ad8ed8108395eba817fbd14fec5c17dcf56b8220856b2b833e091407d5089b35ddf34b86ff7dc9fde52b21ef12176ef3370b7f3a0a8cb1b058a51aefff3d279d80f51a68bfb592587b45c5c63a7e4d625b887de486a118316c3b6a238575f92ac5b1c94c3f5dbbd96686000d6d39cccd558d420e4d447a8cbc4bc7b8c6a03af0f0034fb3518d93800f0f713e4b13732e16ada51801d7e559cf839d1058f64955698311399345416850dddcc5601a684fd09e6afd3944f5e19:cbf1f1642df950eb71fd09590d34c265922c58bd8026bba3fc0e594a6bb1f2b90da3dc1d5f6b6d5b405a896d1dbb71b8685c4dfc444acaffe65ab8331789f5073f33d8fb83e68741090a37bedd745cf141aaaed8c92ffa742a52561777885805ace14246ab98a8cb598c9ce3de9b29bae5fa04b1cf828de11aff80a7ef8a3a38aede4f3c3563a25d049badcad5ed7e47fdbba6e111307eebe9ef4906bc989728b76e84afe808e6653b271e21104aa665f1898dd2aab23090e22b4e344a2616fbd8ee4ad8ed8108395eba817fbd14fec5c17dcf56b8220856b2b833e091407d5089b35ddf34b86ff7dc9fde52b21ef12176ef3370b7f3a0a8cb1b058a51aefff3d279d80f51a68bfb592587b45c5c63a7e4d625b887de486a118316c3b6a238575f92ac5b1c94c3f5dbbd96686000d6d39cccd558d420e4d447a8cbc4bc7b8c6a03af0f0034fb3518d93800f0f713e4b13732e16ada51801d7e559cf839d1058f64955698311399345416850dddcc5601a684fd09e6afd3944f5e19: +1bff652a2c8309a393ac11da3aa97fb078bb284ed5e1b8ccc983652ef8556cd0aaabdc091fc3682354201744e9b73fd2a6cfb281914bf2c70ec3dc1dec7216b0:aaabdc091fc3682354201744e9b73fd2a6cfb281914bf2c70ec3dc1dec7216b0:48d02698a97bdcb3ef078dcfcf5750005f1702d300e7e89bc436e381113401f852b8b4acff60ffbd4ab46d202168d98b8735e79cb350e35b070ff6bdcafd954b551969b6b1a70c9131ebd40d96140291d8d2b091540a8b18d8e5465915c25dbc6b5c9a687942533c372c8b4e95a953677169b950edd3464375cd43132ff9bd541ee22bd418ce23195f65d8b289f633ec8d71e1a801b06c3c827f627e723d2199100ce73e8e4a4440e778317a474910793b47b10ffb55db7f281c7d7a033bd80048b82673b87cf95e99422ba628688f3c971890ca15d12f572fa1977a17307069da304ead3026eb01042668890d17008cd1e92c46cbe9c857e7193de3aba3911e4f86fe0a1698ab7cdb9251a8424b2848b96ad81ea239d365fdea92ea5c0473d0a6bb1e371356bdfad2d0350336d3e1947c936fd0c25195445011731b:93c9c33493fc64172d51e16a0a1cd729a0d99e3cb864e89a42987f39dd8cd26545fdfe37581911e803677da4c55b0a683ddf62b728f8f30685ae58f628ebe60948d02698a97bdcb3ef078dcfcf5750005f1702d300e7e89bc436e381113401f852b8b4acff60ffbd4ab46d202168d98b8735e79cb350e35b070ff6bdcafd954b551969b6b1a70c9131ebd40d96140291d8d2b091540a8b18d8e5465915c25dbc6b5c9a687942533c372c8b4e95a953677169b950edd3464375cd43132ff9bd541ee22bd418ce23195f65d8b289f633ec8d71e1a801b06c3c827f627e723d2199100ce73e8e4a4440e778317a474910793b47b10ffb55db7f281c7d7a033bd80048b82673b87cf95e99422ba628688f3c971890ca15d12f572fa1977a17307069da304ead3026eb01042668890d17008cd1e92c46cbe9c857e7193de3aba3911e4f86fe0a1698ab7cdb9251a8424b2848b96ad81ea239d365fdea92ea5c0473d0a6bb1e371356bdfad2d0350336d3e1947c936fd0c25195445011731b: +002fdd1f7641793ab064bb7aa848f762e7ec6e332ffc26eeacda141ae33b178377d1d8ebacd13f4e2f8a40e28c4a63bc9ce3bfb69716334bcb28a33eb134086c:77d1d8ebacd13f4e2f8a40e28c4a63bc9ce3bfb69716334bcb28a33eb134086c:5ac1dfc324f43e6cb79a87ab0470fa857b51fb944982e19074ca44b1e40082c1d07b92efa7ea55ad42b7c027e0b9e33756d95a2c1796a7c2066811dc41858377d4b835c1688d638884cd2ad8970b74c1a54aadd27064163928a77988b24403aa85af82ceab6b728e554761af7175aeb99215b7421e4474c04d213e01ff03e3529b11077cdf28964b8c49c5649e3a46fa0a09dcd59dcad58b9b922a83210acd5e65065531400234f5e40cddcf9804968e3e9ac6f5c44af65001e158067fc3a660502d13fa8874fa93332138d9606bc41b4cee7edc39d753dae12a873941bb357f7e92a4498847d6605456cb8c0b425a47d7d3ca37e54e903a41e6450a35ebe5237c6f0c1bbbc1fd71fb7cd893d189850295c199b7d88af26bc8548975fda1099ffefee42a52f3428ddff35e0173d3339562507ac5d2c45bbd2c19cfe89b:0df3aa0d0999ad3dc580378f52d152700d5b3b057f56a66f92112e441e1cb9123c66f18712c87efe22d2573777296241216904d7cdd7d5ea433928bd2872fa0c5ac1dfc324f43e6cb79a87ab0470fa857b51fb944982e19074ca44b1e40082c1d07b92efa7ea55ad42b7c027e0b9e33756d95a2c1796a7c2066811dc41858377d4b835c1688d638884cd2ad8970b74c1a54aadd27064163928a77988b24403aa85af82ceab6b728e554761af7175aeb99215b7421e4474c04d213e01ff03e3529b11077cdf28964b8c49c5649e3a46fa0a09dcd59dcad58b9b922a83210acd5e65065531400234f5e40cddcf9804968e3e9ac6f5c44af65001e158067fc3a660502d13fa8874fa93332138d9606bc41b4cee7edc39d753dae12a873941bb357f7e92a4498847d6605456cb8c0b425a47d7d3ca37e54e903a41e6450a35ebe5237c6f0c1bbbc1fd71fb7cd893d189850295c199b7d88af26bc8548975fda1099ffefee42a52f3428ddff35e0173d3339562507ac5d2c45bbd2c19cfe89b: +25b0f0bb3dcb422a6f3c6c220eaadb11dbfe489c2d455b276cefe8cba057f9f3fe03c9c4394adc74b13f47654bead8bc855958b4194fdab2097ac1b157933c05:fe03c9c4394adc74b13f47654bead8bc855958b4194fdab2097ac1b157933c05:54d99f969efa8870fc20fa9a962bb372619c324439728af3139c2a07e8c1b29c1e4eedc2d40ba722f63ce37670362af6f5202add668c4fb4d62fa8bacbc7d07ff3bd38c15a01064259cc34134861632967460541a99b8d5182bf59347b5a59879aa3b091a1f3e04135bd6301be5226d4895e5e9c2b15e48e5ecdf44129e6122853a606fc118466fa720b5ab165635c3bde04d74289274fa03547accbde780e1fa0bf2c56f8436a53e73878a424a29aa9de385dba419ae6a5d12e004276152b58d325b302400a55333c38cde4908ae1d0121cbeca950809c543314277c1485e68d9f9c0a962d1b1e0dda1d4a52b56f8308a80b92acc9f4ebc3ed45d91a129da8675621af676703def3b84113183b2e3a8c56157f243f13980f3d1756fea7668c91503d35c839a2120c79ec954fb546d7b542f987289534ffdef62d47fd5ec:da50d5242bf51c3951780cafd926d67bdf5640d5d3bb08433831d56e48e2592a1c375968bb4d2fbea56145abf2d82991363b1565fa1effe214011a686e39950e54d99f969efa8870fc20fa9a962bb372619c324439728af3139c2a07e8c1b29c1e4eedc2d40ba722f63ce37670362af6f5202add668c4fb4d62fa8bacbc7d07ff3bd38c15a01064259cc34134861632967460541a99b8d5182bf59347b5a59879aa3b091a1f3e04135bd6301be5226d4895e5e9c2b15e48e5ecdf44129e6122853a606fc118466fa720b5ab165635c3bde04d74289274fa03547accbde780e1fa0bf2c56f8436a53e73878a424a29aa9de385dba419ae6a5d12e004276152b58d325b302400a55333c38cde4908ae1d0121cbeca950809c543314277c1485e68d9f9c0a962d1b1e0dda1d4a52b56f8308a80b92acc9f4ebc3ed45d91a129da8675621af676703def3b84113183b2e3a8c56157f243f13980f3d1756fea7668c91503d35c839a2120c79ec954fb546d7b542f987289534ffdef62d47fd5ec: +bf5ba5d6a49dd5ef7b4d5d7d3e4ecc505c01f6ccee4c54b5ef7b40af6a4541401be034f813017b900d8990af45fad5b5214b573bd303ef7a75ef4b8c5c5b9842:1be034f813017b900d8990af45fad5b5214b573bd303ef7a75ef4b8c5c5b9842:16152c2e037b1c0d3219ced8e0674aee6b57834b55106c5344625322da638ecea2fc9a424a05ee9512d48fcf75dd8bd4691b3c10c28ec98ee1afa5b863d1c36795ed18105db3a9aabd9d2b4c1747adbaf1a56ffcc0c533c1c0faef331cdb79d961fa39f880a1b8b1164741822efb15a7259a465bef212855751fab66a897bfa211abe0ea2f2e1cd8a11d80e142cde1263eec267a3138ae1fcf4099db0ab53d64f336f4bcd7a363f6db112c0a2453051a0006f813aaf4ae948a2090619374fa58052409c28ef76225687df3cb2d1b0bfb43b09f47f1232f790e6d8dea759e57942099f4c4bd3390f28afc2098244961465c643fc8b29766af2bcbc5440b86e83608cfc937be98bb4827fd5e6b689adc2e26513db531076a6564396255a09975b7034dac06461b255642e3a7ed75fa9fc265011f5f6250382a84ac268d63ba64:279cace6fdaf3945e3837df474b28646143747632bede93e7a66f5ca291d2c24978512ca0cb8827c8c322685bd605503a5ec94dbae61bbdcae1e49650602bc0716152c2e037b1c0d3219ced8e0674aee6b57834b55106c5344625322da638ecea2fc9a424a05ee9512d48fcf75dd8bd4691b3c10c28ec98ee1afa5b863d1c36795ed18105db3a9aabd9d2b4c1747adbaf1a56ffcc0c533c1c0faef331cdb79d961fa39f880a1b8b1164741822efb15a7259a465bef212855751fab66a897bfa211abe0ea2f2e1cd8a11d80e142cde1263eec267a3138ae1fcf4099db0ab53d64f336f4bcd7a363f6db112c0a2453051a0006f813aaf4ae948a2090619374fa58052409c28ef76225687df3cb2d1b0bfb43b09f47f1232f790e6d8dea759e57942099f4c4bd3390f28afc2098244961465c643fc8b29766af2bcbc5440b86e83608cfc937be98bb4827fd5e6b689adc2e26513db531076a6564396255a09975b7034dac06461b255642e3a7ed75fa9fc265011f5f6250382a84ac268d63ba64: +65de297b70cbe80980500af0561a24db50001000125f4490366d8300d3128592ba8e2ad929bdcea538741042b57f2067d3153707a453770db9f3c4ca75504d24:ba8e2ad929bdcea538741042b57f2067d3153707a453770db9f3c4ca75504d24:131d8f4c2c94b153565b86592e770c987a443461b39aa2408b29e213ab057affc598b583739d6603a83fef0afc514721db0e76f9bd1b72b98c565cc8881af5747c0ba6f58c53dd2377da6c0d3aa805620cc4e75d52aabcba1f9b2849e08bd1b6b92e6f06615b814519606a02dc65a8609f5b29e9c2af5a894f7116ef28cfd1e7b76b64061732f7a5a3f8aa4c2e569e627a3f9749aa597be49d6b94436c352dd5fa7b83c92d2610faa32095ca302152d91a3c9776750e758ee8e9e402c6f5385eaa5df23850e54beb1be437a416c7115ed6aa6de13b55482532787e0bee34b83f3084406765635497c931b62a0518f1fbc2b891dc7262c7c6b67eda594fa530d74c9329bad5be94c287fbcde53aa80272b83322613d9368e5904076fdbcc88b2c0e59c10b02c448e00d1b3e7a9c9640feffb9523a8a60e1d83f04a4b8df69153b:7a9b736b01cc92a3349f1a3c32dbd91959825394ff443c567405e899c8185ce8fad9500e1fce89d95a6253c00477435acf04bff993de1b00495def0834ee1f07131d8f4c2c94b153565b86592e770c987a443461b39aa2408b29e213ab057affc598b583739d6603a83fef0afc514721db0e76f9bd1b72b98c565cc8881af5747c0ba6f58c53dd2377da6c0d3aa805620cc4e75d52aabcba1f9b2849e08bd1b6b92e6f06615b814519606a02dc65a8609f5b29e9c2af5a894f7116ef28cfd1e7b76b64061732f7a5a3f8aa4c2e569e627a3f9749aa597be49d6b94436c352dd5fa7b83c92d2610faa32095ca302152d91a3c9776750e758ee8e9e402c6f5385eaa5df23850e54beb1be437a416c7115ed6aa6de13b55482532787e0bee34b83f3084406765635497c931b62a0518f1fbc2b891dc7262c7c6b67eda594fa530d74c9329bad5be94c287fbcde53aa80272b83322613d9368e5904076fdbcc88b2c0e59c10b02c448e00d1b3e7a9c9640feffb9523a8a60e1d83f04a4b8df69153b: +0826e7333324e7ec8c764292f6015d4670e9b8d7c4a89e8d909e8ef435d18d15ffb2348ca8a018058be71d1512f376f91e8b0d552581254e107602217395e662:ffb2348ca8a018058be71d1512f376f91e8b0d552581254e107602217395e662:7f9e3e2f03c9df3d21b990f5a4af8295734afe783accc34fb1e9b8e95a0fd837af7e05c13cda0de8fadac9205265a0792b52563bdc2fee766348befcc56b88bbb95f154414fb186ec436aa62ea6fcabb11c017a9d2d15f67e595980e04c9313bc94fbc8c1134c2f40332bc7e311ac1ce11b505f8572ada7fbe196fba822d9a914492fa7185e9f3bea4687200a524c673a1cdf87eb3a140dcdb6a8875613488a2b00adf7175341c1c257635fa1a53a3e21d60c228399eea0991f112c60f653d7148e2c5ceb98f940831f070db1084d79156cc82c46bc9b8e884f3fa81be2da4cdda46bcaa24cc461f76ee647bb0f0f8c15ac5daa795b945e6f85bb310362e48d8095c782c61c52b481b4b002ad06ea74b8d306eff71abf21db710a8913cbe48332be0a0b3f31e0c7a6eba85ce33f357c7aeccd30bfb1a6574408b66fe404d31c3c5:4bac7fabec8724d81ab09ae130874d70b5213492104372f601ae5abb10532799373c4dad215876441f474e2c006be37c3c8f5f6f017d0870414fd276a8f428087f9e3e2f03c9df3d21b990f5a4af8295734afe783accc34fb1e9b8e95a0fd837af7e05c13cda0de8fadac9205265a0792b52563bdc2fee766348befcc56b88bbb95f154414fb186ec436aa62ea6fcabb11c017a9d2d15f67e595980e04c9313bc94fbc8c1134c2f40332bc7e311ac1ce11b505f8572ada7fbe196fba822d9a914492fa7185e9f3bea4687200a524c673a1cdf87eb3a140dcdb6a8875613488a2b00adf7175341c1c257635fa1a53a3e21d60c228399eea0991f112c60f653d7148e2c5ceb98f940831f070db1084d79156cc82c46bc9b8e884f3fa81be2da4cdda46bcaa24cc461f76ee647bb0f0f8c15ac5daa795b945e6f85bb310362e48d8095c782c61c52b481b4b002ad06ea74b8d306eff71abf21db710a8913cbe48332be0a0b3f31e0c7a6eba85ce33f357c7aeccd30bfb1a6574408b66fe404d31c3c5: +00ad6227977b5f38ccda994d928bba9086d2daeb013f8690db986648b90c1d4591a4ea005752b92cbebf99a8a5cbecd240ae3f016c44ad141b2e57ddc773dc8e:91a4ea005752b92cbebf99a8a5cbecd240ae3f016c44ad141b2e57ddc773dc8e:cb5bc5b98b2efce43543e91df041e0dbb53ed8f67bf0f197c52b2211e7a45e2e1ec818c1a80e10abf6a43535f5b79d974d8ae28a2295c0a6521763b607d5103c6aef3b2786bd5afd7563695660684337bc3090739fb1cd53a9d644139b6d4caec75bda7f2521fbfe676ab45b98cb317aa7ca79fc54a3d7c578466a6aa64e434e923465a7f211aa0c61681bb8486e90206a25250d3fdae6fb03299721e99e2a914910d91760089b5d281e131e6c836bc2de08f7e02c48d323c647e9536c00ec1039201c0362618c7d47aa8e7b9715ffc439987ae1d31154a6198c5aa11c128f4082f556c99baf103ecadc3b2f3b2ec5b469623bc03a53caf3814b16300aedbda538d676d1f607102639db2a62c446707ce6469bd873a0468225be88b0aef5d4020459b94b32fe2b0133e92e7ba54dd2a5397ed85f966ab39ed0730cca8e7dacb8a336:dc501db79fd782bc88cae792557d5d273f9ba560c7d90037fe84ac879d684f612a77452c4443e95c07b8be192c35769b17bbdfca42280de796d92119d833670dcb5bc5b98b2efce43543e91df041e0dbb53ed8f67bf0f197c52b2211e7a45e2e1ec818c1a80e10abf6a43535f5b79d974d8ae28a2295c0a6521763b607d5103c6aef3b2786bd5afd7563695660684337bc3090739fb1cd53a9d644139b6d4caec75bda7f2521fbfe676ab45b98cb317aa7ca79fc54a3d7c578466a6aa64e434e923465a7f211aa0c61681bb8486e90206a25250d3fdae6fb03299721e99e2a914910d91760089b5d281e131e6c836bc2de08f7e02c48d323c647e9536c00ec1039201c0362618c7d47aa8e7b9715ffc439987ae1d31154a6198c5aa11c128f4082f556c99baf103ecadc3b2f3b2ec5b469623bc03a53caf3814b16300aedbda538d676d1f607102639db2a62c446707ce6469bd873a0468225be88b0aef5d4020459b94b32fe2b0133e92e7ba54dd2a5397ed85f966ab39ed0730cca8e7dacb8a336: +1521c6dbd6f724de73eaf7b56264f01035c04e01c1f3eb3cbe83efd26c439ada2f61a26ffb68ba4f6e141529dc2617e8531c7151404808093b4fa7fedaea255d:2f61a26ffb68ba4f6e141529dc2617e8531c7151404808093b4fa7fedaea255d:3e3c7c490788e4b1d42f5cbcae3a9930bf617ebdff447f7be2ac2ba7cd5bcfc015760963e6fe5b956fb7cdb35bd5a17f5429ca664f437f08753a741c2bc8692b71a9115c582a25b2f74d329854d60b7817c079b3523aaff8793c2f72fff8cd10592c54e738df1d6452fb72da131c6731ea5c953c62ea177ac1f4735e5154477387109afae15f3ed6eeb08606e28c81d4386f03b9376924b6ef8d221ee29547f82a7ede48e1dc17723e3d42171eeaf96ac84bedc2a01dd86f4d085734fd69f91b5263e439083ff0318536adff4147308e3aafd1b58bb74f6fb0214a46fdcd3524f18df5a719ce57319e791b4ea606b499bfa57a60e707f94e18f1fed22f91bc79e6364a843f9cbf93825c465e9cae9072bc9d3ec4471f21ab2f7e99a633f587aac3db78ae9666a89a18008dd61d60218554411a65740ffd1ae3adc06595e3b7876407b6:a817ed23ec398a128601c1832dc6af7643bf3a5f517bcc579450fdb4759028f4966164125f6ebd0d6bf86ff298a39c766d0c21fdb0cbfdf81cd0eb1f03cd8a083e3c7c490788e4b1d42f5cbcae3a9930bf617ebdff447f7be2ac2ba7cd5bcfc015760963e6fe5b956fb7cdb35bd5a17f5429ca664f437f08753a741c2bc8692b71a9115c582a25b2f74d329854d60b7817c079b3523aaff8793c2f72fff8cd10592c54e738df1d6452fb72da131c6731ea5c953c62ea177ac1f4735e5154477387109afae15f3ed6eeb08606e28c81d4386f03b9376924b6ef8d221ee29547f82a7ede48e1dc17723e3d42171eeaf96ac84bedc2a01dd86f4d085734fd69f91b5263e439083ff0318536adff4147308e3aafd1b58bb74f6fb0214a46fdcd3524f18df5a719ce57319e791b4ea606b499bfa57a60e707f94e18f1fed22f91bc79e6364a843f9cbf93825c465e9cae9072bc9d3ec4471f21ab2f7e99a633f587aac3db78ae9666a89a18008dd61d60218554411a65740ffd1ae3adc06595e3b7876407b6: +17e5f0a8f34751babc5c723ecf339306992f39ea065ac140fcbc397d2dd32c4b4f1e23cc0f2f69c88ef9162ab5f8c59fb3b8ab2096b77e782c63c07c8c4f2b60:4f1e23cc0f2f69c88ef9162ab5f8c59fb3b8ab2096b77e782c63c07c8c4f2b60:c0fad790024019bd6fc08a7a92f5f2ac35cf6432e2eaa53d482f6e1204935336cb3ae65a63c24d0ec6539a10ee18760f2f520537774cdec6e96b55536011daa8f8bcb9cdaf6df5b34648448ac7d7cb7c6bd80d67fbf330f8765297766046a925ab52411d1604c3ed6a85173040125658a32cf4c854ef2813df2be6f3830e5eee5a6163a83ca8849f612991a31e9f88028e50bf8535e11755fad029d94cf25959f6695d09c1ba4315d40f7cf51b3f8166d02faba7511ecd8b1dded5f10cd6843455cff707ed225396c61d0820d20ada70d0c3619ff679422061c9f7c76e97d5a37af61fd62212d2dafc647ebbb979e61d9070ec03609a07f5fc57d119ae64b7a6ef92a5afae660a30ed48d702cc3128c633b4f19060a0578101729ee979f790f45bdbb5fe1a8a62f01a61a31d61af07030450fa0417323e9407bc76e73130e7c69d62e6a7:efe2cb63fe7b4fc98946dc82fb6998e741ed9ce6b9c1a93bb45bc0a7d8396d7405282b43fe363ba5b23589f8e1fae130e157ce888cd72d053d0cc19d257a4300c0fad790024019bd6fc08a7a92f5f2ac35cf6432e2eaa53d482f6e1204935336cb3ae65a63c24d0ec6539a10ee18760f2f520537774cdec6e96b55536011daa8f8bcb9cdaf6df5b34648448ac7d7cb7c6bd80d67fbf330f8765297766046a925ab52411d1604c3ed6a85173040125658a32cf4c854ef2813df2be6f3830e5eee5a6163a83ca8849f612991a31e9f88028e50bf8535e11755fad029d94cf25959f6695d09c1ba4315d40f7cf51b3f8166d02faba7511ecd8b1dded5f10cd6843455cff707ed225396c61d0820d20ada70d0c3619ff679422061c9f7c76e97d5a37af61fd62212d2dafc647ebbb979e61d9070ec03609a07f5fc57d119ae64b7a6ef92a5afae660a30ed48d702cc3128c633b4f19060a0578101729ee979f790f45bdbb5fe1a8a62f01a61a31d61af07030450fa0417323e9407bc76e73130e7c69d62e6a7: +0cd7aa7d605e44d5ffb97966b2cb93c189e4c5a85db87fad7ab8d62463c59b594889855fe4116b4913927f47f2273bf559c3b394a983631a25ae597033185e46:4889855fe4116b4913927f47f2273bf559c3b394a983631a25ae597033185e46:28a55dda6cd0844b6577c9d6da073a4dc35cbc98ac158ab54cf88fd20cc87e83c4bba2d74d82ce0f4854ec4db513de400465aaa5eee790bc84f16337072d3a91cde40d6e0df1ba0cc0645f5d5cbbb642381d7b9e211d25267a8acf77d1edb69c3a630f5b133d24f046a81bf22ff03b31d8447e12c3f7b77114a70cbd20bbd08b0b3827a6bbcf90409e344447a7fbc59bdd97d729071f8d71dcc33e6ef2cbab1d411edf13734db1dd9703276f5eb2d6aa2cb8952dd6712bfae809ce08c3aa502b8135713fac0a9c25b1d45b6a5831e02421bba65b81a596efa24b0576bd1dc7fdfb49be762875e81bd540722bc06140b9aa2ef7b84a801e41ded68d4546ac4873d9e7ced649b64fadaf0b5c4b6eb8d036315233f4326ca01e03393050cd027c24f67303fb846bd2c6b3dba06bed0d59a36289d24bd648f7db0b3a81346612593e3ddd18c557:bf9115fd3d02706e398d4bf3b02a82674ff3041508fd39d29f867e501634b9261f516a794f98738d7c7013a3f2f858ffdd08047fb6bf3dddfb4b4f4cbeef300328a55dda6cd0844b6577c9d6da073a4dc35cbc98ac158ab54cf88fd20cc87e83c4bba2d74d82ce0f4854ec4db513de400465aaa5eee790bc84f16337072d3a91cde40d6e0df1ba0cc0645f5d5cbbb642381d7b9e211d25267a8acf77d1edb69c3a630f5b133d24f046a81bf22ff03b31d8447e12c3f7b77114a70cbd20bbd08b0b3827a6bbcf90409e344447a7fbc59bdd97d729071f8d71dcc33e6ef2cbab1d411edf13734db1dd9703276f5eb2d6aa2cb8952dd6712bfae809ce08c3aa502b8135713fac0a9c25b1d45b6a5831e02421bba65b81a596efa24b0576bd1dc7fdfb49be762875e81bd540722bc06140b9aa2ef7b84a801e41ded68d4546ac4873d9e7ced649b64fadaf0b5c4b6eb8d036315233f4326ca01e03393050cd027c24f67303fb846bd2c6b3dba06bed0d59a36289d24bd648f7db0b3a81346612593e3ddd18c557: +33371d9e892f9875052ac8e325ba505e7477c1ace24ba7822643d43d0acef3de35929bded27c249c87d8b8d82f59260a575327b546c3a167c69f5992d5b8e006:35929bded27c249c87d8b8d82f59260a575327b546c3a167c69f5992d5b8e006:27a32efba28204be59b7ff5fe488ca158a91d5986091ecc4458b49e090dd37cbfede7c0f46186fabcbdff78d2844155808efffd873ed9c9261526e04e4f7050b8d7bd267a0fe3d5a449378d54a4febbd2f26824338e2aaaf35a32ff0f62504bda5c2e44abc63159f336cf25e6bb40ddb7d8825dff18fd51fc01951eaedcd33707007e1203ca58b4f7d242f8166a907e099932c001bfb1ec9a61e0ef2da4e8446af208201315d69681710d425d2400c387d7b9df321a4aec602b9c656c3e2310bff8756d18b802134b15604f4edc111149a9879e31241dd34f702f4c349617b13529769a772f5e52a89c098e0dca5920667893a250061b17991626eb9319298685be46b6a8b68422444fa5a36bcf3a687e2eccb9322c87dc80165da898930850b98fc863cada1aa99c6d61c451b9ccf4874c7f0e75b0a0c602f044812c71765adaf02025395b0:985ca446ddc007827cc8f2852cbd8115ef8c5975e9d7ce96d74dfed859aa14a4c15254006bea5e08359efe2625d715e0897ee5a16f151203be5010418637de0527a32efba28204be59b7ff5fe488ca158a91d5986091ecc4458b49e090dd37cbfede7c0f46186fabcbdff78d2844155808efffd873ed9c9261526e04e4f7050b8d7bd267a0fe3d5a449378d54a4febbd2f26824338e2aaaf35a32ff0f62504bda5c2e44abc63159f336cf25e6bb40ddb7d8825dff18fd51fc01951eaedcd33707007e1203ca58b4f7d242f8166a907e099932c001bfb1ec9a61e0ef2da4e8446af208201315d69681710d425d2400c387d7b9df321a4aec602b9c656c3e2310bff8756d18b802134b15604f4edc111149a9879e31241dd34f702f4c349617b13529769a772f5e52a89c098e0dca5920667893a250061b17991626eb9319298685be46b6a8b68422444fa5a36bcf3a687e2eccb9322c87dc80165da898930850b98fc863cada1aa99c6d61c451b9ccf4874c7f0e75b0a0c602f044812c71765adaf02025395b0: +beedb8073df58f8c1bffbdbd77ec7decb2c82a9babecefc0331507bdc2c2a7e7b27e908b805e296fc30d2e474b060cd50c0f6f520b3671712183bd89d4e733e9:b27e908b805e296fc30d2e474b060cd50c0f6f520b3671712183bd89d4e733e9:35ca57f0f915e5209d54ea4b871ffb585354df1b4a4a1796fbe4d6227d3e1aba5171ed0391a79e83e24d82fdafd15c17b28bf6c94d618c74d65264e58faaacd2902872fdd0efa22e8d2d7ce8e3b8197f0c3615b0a385235fa9fd8e4564ee6e6b1650b4cfb94d872c805c32d4f3a18f966461d3adbb605fa525884f8eb197627396ba4d995d78ac02948a0eaabb58519b9a8e2e7985cd1de2c71d8918d96a0168660ce17cddf364e3ec0d4bd90f2104751a1927ee1d23f3e7a69840ed040b00e5f6e4866ec58813149cc382aebf6162608c79574d553f47230e924a0ef1ebf55d8e1a52abb62a2d7ac86027c7c03cc83fa1949da29e2f3037ab986fd2fffe650e3149babae5a50b1ee9696f3babec72e29697c82422814d272085500fd837fe3c7a973ef4c169af12dd7f02700620bb045bdbf84623f326350570b3cadbc9aea4200b28287e17ab:8c890cccadc7760e1e82e43c44b3dc0b685a48b479ae13cc0a6b0557d0fb1cbabba63d2a96843412ea8d36c50acbf52b92cfb2dce49dc48af6ddcf8ee47a860835ca57f0f915e5209d54ea4b871ffb585354df1b4a4a1796fbe4d6227d3e1aba5171ed0391a79e83e24d82fdafd15c17b28bf6c94d618c74d65264e58faaacd2902872fdd0efa22e8d2d7ce8e3b8197f0c3615b0a385235fa9fd8e4564ee6e6b1650b4cfb94d872c805c32d4f3a18f966461d3adbb605fa525884f8eb197627396ba4d995d78ac02948a0eaabb58519b9a8e2e7985cd1de2c71d8918d96a0168660ce17cddf364e3ec0d4bd90f2104751a1927ee1d23f3e7a69840ed040b00e5f6e4866ec58813149cc382aebf6162608c79574d553f47230e924a0ef1ebf55d8e1a52abb62a2d7ac86027c7c03cc83fa1949da29e2f3037ab986fd2fffe650e3149babae5a50b1ee9696f3babec72e29697c82422814d272085500fd837fe3c7a973ef4c169af12dd7f02700620bb045bdbf84623f326350570b3cadbc9aea4200b28287e17ab: +9184ef618816832592bc8eb35f4ffd4ff98dfbf7776c90f2aad212ce7e03351e687b7726010d9bde2c90e573cd2a2a702ff28c4a2af70afc7315c94d575601e5:687b7726010d9bde2c90e573cd2a2a702ff28c4a2af70afc7315c94d575601e5:729eb7e54a9d00c58617af18c345b8dc6e5b4e0f57de2f3c02e54a2ec8f1425ec2e240775b5ab0c10f84ac8bafda4584f7e21c655faecd8030a98906bd68398f26b5d58d92b6cf045e9bd9743c74c9a342ec61ce57f37b981eac4d8bf034608866e985bb68686a68b4a2af88b992a2a6d2dc8ce88bfb0a36cf28bbab7024abfa2bea53313b66c906f4f7cf66970f540095bd0104aa4924dd82e15413c22679f847e48cd0c7ec1f677e005fec0177fbd5c559fc39add613991fbaeae4d24d39d309ef74647f8192cc4c62d0642028c76a1b951f6bc9639deb91ecc08be6043f2109705a42c7eae712649d91d96ccbbfb63d8d0dd6dd112160f61361ecdc6793929ca9aef9ab56944a6fa4a7df1e279eaf58ce8323a9cf62c94279fff7440fbc936baa61489c999330badcb9fc0e184bc5093f330cbb242f71fb378738fea10511dd438364d7f76bcc:b3c24e75132c563475422d5ea412b5c1e8e6e5ea1c08ead1393c412da134c9a1638284ea7e2ca032fe3d3e32a9066a8c8839903f6ef46e966bb5e492d8c2aa00729eb7e54a9d00c58617af18c345b8dc6e5b4e0f57de2f3c02e54a2ec8f1425ec2e240775b5ab0c10f84ac8bafda4584f7e21c655faecd8030a98906bd68398f26b5d58d92b6cf045e9bd9743c74c9a342ec61ce57f37b981eac4d8bf034608866e985bb68686a68b4a2af88b992a2a6d2dc8ce88bfb0a36cf28bbab7024abfa2bea53313b66c906f4f7cf66970f540095bd0104aa4924dd82e15413c22679f847e48cd0c7ec1f677e005fec0177fbd5c559fc39add613991fbaeae4d24d39d309ef74647f8192cc4c62d0642028c76a1b951f6bc9639deb91ecc08be6043f2109705a42c7eae712649d91d96ccbbfb63d8d0dd6dd112160f61361ecdc6793929ca9aef9ab56944a6fa4a7df1e279eaf58ce8323a9cf62c94279fff7440fbc936baa61489c999330badcb9fc0e184bc5093f330cbb242f71fb378738fea10511dd438364d7f76bcc: +354e13152ee1fe748a1252204c6527bdc1b1eb2eb53678150e6359924708d812d45ff6c5fb83e7bb9669aa8960deb7dbc665c988439b6c9ef672c6811dc8bcf6:d45ff6c5fb83e7bb9669aa8960deb7dbc665c988439b6c9ef672c6811dc8bcf6:8e5fccf66b1ba6169cb685733d9d0e0190361c90bcab95c163285a97fe356d2bdcde3c9380268805a384d063da09ccd9969cc3ff7431e60a8e9f869cd62faa0e356151b280bc526e577c2c538c9a724dc48bf88b70321d7e1eeedb3c4af706748c942e67bdabdb41bec2977b1523069e31e29b76300288f88a51b384b80cc2526f1679340ddec3881f5cd28b0378d9cd0a812b68dd3f68f7a23e1b54bee7466ac765cf38df04d67441dfa498c4bffc52045fa6d2dbcdbfa33dfaa77644ffccef0decdb6790c70a0d734ec287cc338cb5a909c0055189301169c4f7702c05c0911a27b16ef9ed934fa6a0ca7b13e413523422535647968030edc40cd73e7d6b345b7581f438316d68e3cd292b846d3f4f7c4862bc7e6b3fb89a27f6f60cd7db2e34ec9aae1013fe37acff8ad888cb9a593ef5e621eae5186c58b31dcfde22870e336d33f440f6b8d49a:de2b46e65f3decef34332e500f2e11306fbdcf1be85a1c1ee68ba3045dcec2c7be608d22927da1f44c0e2083ae622cf3c29d893887994efcfa2ca594f5051f038e5fccf66b1ba6169cb685733d9d0e0190361c90bcab95c163285a97fe356d2bdcde3c9380268805a384d063da09ccd9969cc3ff7431e60a8e9f869cd62faa0e356151b280bc526e577c2c538c9a724dc48bf88b70321d7e1eeedb3c4af706748c942e67bdabdb41bec2977b1523069e31e29b76300288f88a51b384b80cc2526f1679340ddec3881f5cd28b0378d9cd0a812b68dd3f68f7a23e1b54bee7466ac765cf38df04d67441dfa498c4bffc52045fa6d2dbcdbfa33dfaa77644ffccef0decdb6790c70a0d734ec287cc338cb5a909c0055189301169c4f7702c05c0911a27b16ef9ed934fa6a0ca7b13e413523422535647968030edc40cd73e7d6b345b7581f438316d68e3cd292b846d3f4f7c4862bc7e6b3fb89a27f6f60cd7db2e34ec9aae1013fe37acff8ad888cb9a593ef5e621eae5186c58b31dcfde22870e336d33f440f6b8d49a: +7ff62d4b3c4d99d342d4bb401d726b21e99f4ef592149fc311b68761f5567ff67fdfdb9eca29d3f01d9486d7e112ce03aa37b91326a4283b9c03999c5eda099a:7fdfdb9eca29d3f01d9486d7e112ce03aa37b91326a4283b9c03999c5eda099a:99c44c796572a4823fc6c3807730839173774c05dbfc1492ed0d00509a95a1de37274b3135ed0456a1718e576597dc13f2a2ab37a45c06cbb4a2d22afad4d5f3d90ab3d8da4dcdaa06d44f2219088401c5dceee26055c4782f78d7d63a380608e1bef89eeef338c2f0897da106fafce2fb2ebc5db669c7c172c9cfe77d3109d239fe5d005c8ee751511b5a88317c729b0d8b70b52f6bd3cda2fe865c77f36e4f1b635f336e036bd718bec90ee78a802811510c4058c1ba364017253aa842922e1dd7d7a0f0fc9c69e43fc4eaeffaaf1ae5fa5d2d73b43079617baba030923fe5b13d2c1c4fe6fac3f2db74e2020a734b6121a0302fce820ba0580ce6135348fdf0632e0008df03ee112168f5cfa0037a26a1f69b1f1317edf2a3ab367455a77e00691215d7aa3133c2159d3da2b134cf04f0defbf07a6064011e64dd14d4f8f064356655428804c2771a:058f79927fbf6178724815c7b11c63baaa90bcc15d7272be082f8a9141861c816433055f6cf6491424853f9ec78bb91ace913a93411b4e5ed58bc4ba5715c60a99c44c796572a4823fc6c3807730839173774c05dbfc1492ed0d00509a95a1de37274b3135ed0456a1718e576597dc13f2a2ab37a45c06cbb4a2d22afad4d5f3d90ab3d8da4dcdaa06d44f2219088401c5dceee26055c4782f78d7d63a380608e1bef89eeef338c2f0897da106fafce2fb2ebc5db669c7c172c9cfe77d3109d239fe5d005c8ee751511b5a88317c729b0d8b70b52f6bd3cda2fe865c77f36e4f1b635f336e036bd718bec90ee78a802811510c4058c1ba364017253aa842922e1dd7d7a0f0fc9c69e43fc4eaeffaaf1ae5fa5d2d73b43079617baba030923fe5b13d2c1c4fe6fac3f2db74e2020a734b6121a0302fce820ba0580ce6135348fdf0632e0008df03ee112168f5cfa0037a26a1f69b1f1317edf2a3ab367455a77e00691215d7aa3133c2159d3da2b134cf04f0defbf07a6064011e64dd14d4f8f064356655428804c2771a: +6cabadd03f8a2e6ebab96a74f80e18164e4d1b6baa678f5a82e25604af989aaf2a4a3179564194e00100c18bc35351d8b135bbae5b32b28fce1d7b6766ca4b32:2a4a3179564194e00100c18bc35351d8b135bbae5b32b28fce1d7b6766ca4b32:279f78cf3b9ccfc6e1b01e1a82f50ed172e9a8e1e702bb15661dd7dc3a456ff7a7a7fdfb081db3867079630c7f70fd753292ec60ecbf50632e9aa45b996505c66e6dc3c6ae892e21b6a8705e4bbae8f16a3378554b31fdb0139dcd15c96a8a7e4b88756a86d18db5dc74fd7691197dd88e2c7d5df52b049344cdc477c9cd7e89eda99ccfb1d00814d0152b9654df3279372ca5f18b1c946f2894a76b079ddb1c3cd61fbb969aeec9193a6b88fb7d136c07f9821e5c1074b4e93bcaf6fa14d0d1d7e1707589d77ec1337206e53a1f06cc26672ff95c13d5ff444766931ba30a0afdcdadd2098e9c41fd87a3f23cd16dbb0efbf8092ce33e327f42610990e1cee6cb8e54951aa081e69765ae4009aeed758e768de50c23d9a22b4a06dc4d19fc8cbd0cdef4c983461755d0a3b5d6a9c12253e09568339ff7e5f78c5fdf7ec89f9186a621a8c0eed11b67022e:4e65c6c1d493045e8a9250e397c1d1d30ffed24db66a8961aa458f8f0fcb760c39fe8657d7ab8f84000b96d519717cff71f926522c1efec7f8b2624eae55f60c279f78cf3b9ccfc6e1b01e1a82f50ed172e9a8e1e702bb15661dd7dc3a456ff7a7a7fdfb081db3867079630c7f70fd753292ec60ecbf50632e9aa45b996505c66e6dc3c6ae892e21b6a8705e4bbae8f16a3378554b31fdb0139dcd15c96a8a7e4b88756a86d18db5dc74fd7691197dd88e2c7d5df52b049344cdc477c9cd7e89eda99ccfb1d00814d0152b9654df3279372ca5f18b1c946f2894a76b079ddb1c3cd61fbb969aeec9193a6b88fb7d136c07f9821e5c1074b4e93bcaf6fa14d0d1d7e1707589d77ec1337206e53a1f06cc26672ff95c13d5ff444766931ba30a0afdcdadd2098e9c41fd87a3f23cd16dbb0efbf8092ce33e327f42610990e1cee6cb8e54951aa081e69765ae4009aeed758e768de50c23d9a22b4a06dc4d19fc8cbd0cdef4c983461755d0a3b5d6a9c12253e09568339ff7e5f78c5fdf7ec89f9186a621a8c0eed11b67022e: +0fa0c32c3ae34be51b92f91945405981a8e202488558a8e220c288c7d6a5532dd6aee62bd91fc9453635ffcc02b2f38dcab13285140380580ccdff0865df0492:d6aee62bd91fc9453635ffcc02b2f38dcab13285140380580ccdff0865df0492:53f44be0e5997ff07264cb64ba1359e2801def8755e64a2362bddaf597e672d021d34fface6d97e0f2b1f6ae625fd33d3c4f6e9ff7d0c73f1da8defb23f324975e921bb2473258177a16612567edf7d5760f3f3e3a6d26aaabc5fde4e2043f73fa70f128020933b1ba3b6bd69498e9503ea670f1ed880d3651f2e4c59e79cabc86e9b703394294112d5d8e213c317423b525a6df70106a9d658a262028b5f45100cb77d1150d8fe461eed434f241015f3276ad7b09a291b4a7f35e3c30051cbf13b1d4a7fa0c81a50f939e7c49673afdc87883c9e3e61f5a1df03755470fda74bf23ea88676b258a97a280d5f90b52b714b596035bae08c8d0fe6d94f8949559b1f27d7116cf59dd3cfbf18202a09c13f5c4fbc8d97225492887d32870c2297e34debd9876d6d01ac27a16b088b079079f2b20feb02537cda314c43cb2dca371b9df37ed11ec97e1a7a6993a:7e9ab85ee94fe4b35dcb545329a0ef25923de5c9dc23e7df1a7e77ab0dcfb89e03f4e785ca6429cb2b0df50da6230f733f00f33a45c4e576cd40bdb84f1ae00153f44be0e5997ff07264cb64ba1359e2801def8755e64a2362bddaf597e672d021d34fface6d97e0f2b1f6ae625fd33d3c4f6e9ff7d0c73f1da8defb23f324975e921bb2473258177a16612567edf7d5760f3f3e3a6d26aaabc5fde4e2043f73fa70f128020933b1ba3b6bd69498e9503ea670f1ed880d3651f2e4c59e79cabc86e9b703394294112d5d8e213c317423b525a6df70106a9d658a262028b5f45100cb77d1150d8fe461eed434f241015f3276ad7b09a291b4a7f35e3c30051cbf13b1d4a7fa0c81a50f939e7c49673afdc87883c9e3e61f5a1df03755470fda74bf23ea88676b258a97a280d5f90b52b714b596035bae08c8d0fe6d94f8949559b1f27d7116cf59dd3cfbf18202a09c13f5c4fbc8d97225492887d32870c2297e34debd9876d6d01ac27a16b088b079079f2b20feb02537cda314c43cb2dca371b9df37ed11ec97e1a7a6993a: +7b06f88026fa86f39fce2426f67cc5996bedd0cfc4b5ebb1b5e3edbb47e080aa3f1469ee6a2e7867e2e9012d402cf5a4861497c01df879a1deb1c539830b58de:3f1469ee6a2e7867e2e9012d402cf5a4861497c01df879a1deb1c539830b58de:71175d4e21721297d9176d817f4e785d9600d923f987fe0b26fd79d33a5ea5d1e818b71f0f92b8c73afddabdcc27f6d16e26aafa874cfd77a00e06c36b041487582bb933760f88b419127345776ea418f83522254fed33819bc5c95f8f8404cc144ebf1486c88515409d3433aaf519d9920f5256e629419e9a95580a35b069b8d25533dfcbc98ad36404a951808e01378c03266326d120046975fde07daef3266caacd821c1403499d7fdf17c033c8d8c3f28f162b5f09dfdaca06285f00c6cb986dfdf5151aa6639608b5b13e78d65a4368585b16138754fbd113835a686cd066c2b89bb0953c24d50e77bf0fc457c1e0fcf5d44da8db9a88f062be3b688d5cdcff1d1c00e81ec9d413882295b341fee8fa427dc109adeb5f284eec202f1bef115bf96b1782d3ccdeb682b69bf92d170c007d5df80e1ed962f677dc24a145a1e4e829e8dec0104e5f78365944:42f133e34e3eb7032a133ed781537ec62e44a5ce8381e5e0bf9e13a914a4b2c757811d6d3b1e86672424ea4230d10f7c610abb7069e61e319b4066a2bd7bc90071175d4e21721297d9176d817f4e785d9600d923f987fe0b26fd79d33a5ea5d1e818b71f0f92b8c73afddabdcc27f6d16e26aafa874cfd77a00e06c36b041487582bb933760f88b419127345776ea418f83522254fed33819bc5c95f8f8404cc144ebf1486c88515409d3433aaf519d9920f5256e629419e9a95580a35b069b8d25533dfcbc98ad36404a951808e01378c03266326d120046975fde07daef3266caacd821c1403499d7fdf17c033c8d8c3f28f162b5f09dfdaca06285f00c6cb986dfdf5151aa6639608b5b13e78d65a4368585b16138754fbd113835a686cd066c2b89bb0953c24d50e77bf0fc457c1e0fcf5d44da8db9a88f062be3b688d5cdcff1d1c00e81ec9d413882295b341fee8fa427dc109adeb5f284eec202f1bef115bf96b1782d3ccdeb682b69bf92d170c007d5df80e1ed962f677dc24a145a1e4e829e8dec0104e5f78365944: +c3f5e149968a24f4de9119531975f443015ccca305d7119ed4749e8bf6d94fc739aaccdb948a4038538a4588322f806bb129b5876c4bec51271afe4f49690045:39aaccdb948a4038538a4588322f806bb129b5876c4bec51271afe4f49690045:c46370e37f2e0cadcf93402f1f0cb048f52881ba750b7a43f56ab11ce348732fb57e7f9aaf8dfcbe455e14e983c248d026a27e7f148d5db5a53f94635702b895127771047a876d14107386c5e0ff8933345bbd7a936d990d33efa28c2ec4e4864ffd2ff576f7c88f954cfc1c459e883bb712dae3cdf6632066f1f4d13a509615b3360cadc5a307f23e52a51b40a6feebe0b18d0e9ee4e348f33cd81a8def222f6a59b12861d335bd9af85cc004be46f1d3a424f4870ae9dc587e5a4ade136b9370649348c33ac3bf1febeebffea37085ed59cac9d9e696470b234609e9a10a9d431ff91e69cb5135fd117ff58a36539744ebe70cea6973c00c7a4d57b62f4a7136d731b8e46ff18ec0ed69070031905075d8541d568cfce6eeb76242b7819a7b6a93552111bb88f165527cfa6966d39fcbe0a7dea008e39c7a3e577ab307cd1d0ea326833d52654e172955f3fcd4:5fa2b531677b00b85b0a313cbd479f55f4ab3ec5cfce5e454d2b74176ccc3399c899f9d6b51ed4c1e76185ac9fe730c4b4014044f7041185bc3c85722eb2ea02c46370e37f2e0cadcf93402f1f0cb048f52881ba750b7a43f56ab11ce348732fb57e7f9aaf8dfcbe455e14e983c248d026a27e7f148d5db5a53f94635702b895127771047a876d14107386c5e0ff8933345bbd7a936d990d33efa28c2ec4e4864ffd2ff576f7c88f954cfc1c459e883bb712dae3cdf6632066f1f4d13a509615b3360cadc5a307f23e52a51b40a6feebe0b18d0e9ee4e348f33cd81a8def222f6a59b12861d335bd9af85cc004be46f1d3a424f4870ae9dc587e5a4ade136b9370649348c33ac3bf1febeebffea37085ed59cac9d9e696470b234609e9a10a9d431ff91e69cb5135fd117ff58a36539744ebe70cea6973c00c7a4d57b62f4a7136d731b8e46ff18ec0ed69070031905075d8541d568cfce6eeb76242b7819a7b6a93552111bb88f165527cfa6966d39fcbe0a7dea008e39c7a3e577ab307cd1d0ea326833d52654e172955f3fcd4: +42305c9302f45ea6f87e26e2208fd94b3c4ad037b1b6c83cf6677aa1096a013c3b97b1f11ce45ba46ffbb25b76bfc5ad7b77f90cc69ed76115dea4029469d587:3b97b1f11ce45ba46ffbb25b76bfc5ad7b77f90cc69ed76115dea4029469d587:d110828d449198d675e74e8e39439fd15e75bf2cc1f430abfb245836885bafc420f754b89d2fbbf6dd3490792e7a4f766073cfe3b302d089831ace869e2730fde45c2121ec3ef217aa9c43fa7cc7e9ed0a01ad9f1d2fc3613638ca9fc193c98b37455bf5dbf8f38b64708dfdca6c21f0975f1017c5da5f6434bda9f033cec2a631ab50318e017b170b240bf01eb8b36c7e1cb59e7736ac34444208132a8f59e4f313d65d849c6a4fdf13e20ecaee3823e589a171b39b2489497b06e6ff58c2c9f1dc5d3aa3bd10e6443e22d42d07b783f79fd43a46e1cde314b663a95f7246dea131fcd46d1dc333c5454f86b2c4e2e424dea405cc2230d4dcd39a2eab2f92845cf6a7994192063f1202749ef52dcb96f2b79ed6a98118ca0b99ba2285490860eb4c61ab78b9ddc6acc7ad883fa5e96f9d029171223abf7573e36230e0a81f6c1311151473ee264f4b842e923dcb3b:18d05e5d01668e83f40fa3bbee28b388acf318d1b0b5ad668c672f345c8eda14c2f884cd2a9039459ce0810bc5b580fe70d3964a43edb49e73a6ff914bbf040cd110828d449198d675e74e8e39439fd15e75bf2cc1f430abfb245836885bafc420f754b89d2fbbf6dd3490792e7a4f766073cfe3b302d089831ace869e2730fde45c2121ec3ef217aa9c43fa7cc7e9ed0a01ad9f1d2fc3613638ca9fc193c98b37455bf5dbf8f38b64708dfdca6c21f0975f1017c5da5f6434bda9f033cec2a631ab50318e017b170b240bf01eb8b36c7e1cb59e7736ac34444208132a8f59e4f313d65d849c6a4fdf13e20ecaee3823e589a171b39b2489497b06e6ff58c2c9f1dc5d3aa3bd10e6443e22d42d07b783f79fd43a46e1cde314b663a95f7246dea131fcd46d1dc333c5454f86b2c4e2e424dea405cc2230d4dcd39a2eab2f92845cf6a7994192063f1202749ef52dcb96f2b79ed6a98118ca0b99ba2285490860eb4c61ab78b9ddc6acc7ad883fa5e96f9d029171223abf7573e36230e0a81f6c1311151473ee264f4b842e923dcb3b: +c57a43dcd7bab8516009546918d71ad459b7345efdca8d4f19929875c839d7222083b444236b9ab31d4e00c89d55c6260fee71ac1a47c4b5ba227404d382b82d:2083b444236b9ab31d4e00c89d55c6260fee71ac1a47c4b5ba227404d382b82d:a4f6d9c281cf81a28a0b9e77499aa24bde96cc1264374491c008294ee0af6f6e4bbb686396f59068d358e30fe9992db0c6f16680a1c71e27a4a907ac607d39bdc3258c7956482fb37996f4beb3e5051b8148019a1c256e2ee999ebc8ce64c54e07fedb4fbd8953ebd93b7d69ce5a0082edd6209d12d3619b4fd2eae916461f72a4ce727157251a19209bbff9fbdbd289436f3fcacc6b4e1318521a47839cba4b14f7d7a21e7b5d6b6a753d5804afcd2b1eb7779b92abab8afa8aa4fa51caec0b85dcd0fc2a0676036d3f56630a831ffeb502861dd89161c708a9c006c73c930ce5b94756426ff18aa112fb4eb9a68500b48d4eedbd4167b6ffd0a11d49443a173ce9d949436748fc0634f06bb08b8f3423f4463dba7b4d199b64df578117f0a2645f0b2a1e2ada27d286f76733f25b82ed1d48a5c3898d4ad621e50ed9060daad40a39532e4d1bf162ce36804d5d4e2d:1edef9bc036971f1fa88edf45393c802e6c1a1631c8a06871a09a320821dce40beca97e53a0361a955a4c6d60b8ca8e400c81340911ccb4f56284041cdbb1804a4f6d9c281cf81a28a0b9e77499aa24bde96cc1264374491c008294ee0af6f6e4bbb686396f59068d358e30fe9992db0c6f16680a1c71e27a4a907ac607d39bdc3258c7956482fb37996f4beb3e5051b8148019a1c256e2ee999ebc8ce64c54e07fedb4fbd8953ebd93b7d69ce5a0082edd6209d12d3619b4fd2eae916461f72a4ce727157251a19209bbff9fbdbd289436f3fcacc6b4e1318521a47839cba4b14f7d7a21e7b5d6b6a753d5804afcd2b1eb7779b92abab8afa8aa4fa51caec0b85dcd0fc2a0676036d3f56630a831ffeb502861dd89161c708a9c006c73c930ce5b94756426ff18aa112fb4eb9a68500b48d4eedbd4167b6ffd0a11d49443a173ce9d949436748fc0634f06bb08b8f3423f4463dba7b4d199b64df578117f0a2645f0b2a1e2ada27d286f76733f25b82ed1d48a5c3898d4ad621e50ed9060daad40a39532e4d1bf162ce36804d5d4e2d: +2dddb6b8fd04fa90ece1a709f8418f2e5d0c9c43afe7cfce19e6ad15a73476f78059de6a7c4776489ecc2e7d707ffce30285bf30a23f78d72db49cfd6ed0d492:8059de6a7c4776489ecc2e7d707ffce30285bf30a23f78d72db49cfd6ed0d492:474baa590a4cd72d5424e51d8257b3d44325bc4c5063a0033c86ebbe99ed7212184c19944d082a115379dd4cece973faa0bca6485bd25f3744a719e70aa0291e1b5a96e637c140616a98263357c76b6eb0083fe51414e386870d0fdc7dd9abe4ff6fb5bbf1e7b15dac3e08e2615f655c3104ceb32a4cc2c9e9c43cf282d346ac253ccc46b635ae040973b49735720ffb890469a567c5824e0c00d7ccd5509a718092a906461c4d6163eaf422418f5fc6e009fc3f529ac61a2f89bb8e0ed45d940c4c2331ff8d8e1d6d58d417d8fc2656a02e8701aee75aed918724eebe4a2cf4744c5c401e217023df68a6f6a0228bd05a679a697d8de7036b9ed269090d3c65486afb91e27954eb15b964665ede7ad008f12fb3a9d0e69c13b4254f43819e0818a4195f68b8a38ae81f3fcb1879c95ab4cd0ffc38e381089260cca967ace5a085b457ab5eb363852101377570f9ac9e38:c634ea7bf72e895a2e796e2834201415b8b45e05e045559284eb9052c0e84f62a5a9f0c9764f7576788c7228b19ef517c195497325a48a9344b147c12fd75509474baa590a4cd72d5424e51d8257b3d44325bc4c5063a0033c86ebbe99ed7212184c19944d082a115379dd4cece973faa0bca6485bd25f3744a719e70aa0291e1b5a96e637c140616a98263357c76b6eb0083fe51414e386870d0fdc7dd9abe4ff6fb5bbf1e7b15dac3e08e2615f655c3104ceb32a4cc2c9e9c43cf282d346ac253ccc46b635ae040973b49735720ffb890469a567c5824e0c00d7ccd5509a718092a906461c4d6163eaf422418f5fc6e009fc3f529ac61a2f89bb8e0ed45d940c4c2331ff8d8e1d6d58d417d8fc2656a02e8701aee75aed918724eebe4a2cf4744c5c401e217023df68a6f6a0228bd05a679a697d8de7036b9ed269090d3c65486afb91e27954eb15b964665ede7ad008f12fb3a9d0e69c13b4254f43819e0818a4195f68b8a38ae81f3fcb1879c95ab4cd0ffc38e381089260cca967ace5a085b457ab5eb363852101377570f9ac9e38: +5547f1004baedfce5cfc0850b05302374aad24f6163994ecd751df3af3c106207ce620787385ee1951ac49a77352ee0d6f8c5cd47df74e9e3216a6324fc7cf7f:7ce620787385ee1951ac49a77352ee0d6f8c5cd47df74e9e3216a6324fc7cf7f:a6c17eeb5b8066c2cd9a89667317a945a0c7c96996e77ae854c509c6cd0631e922ad04503af87a3c4628adafed7600d071c078a22e7f64bda08a362b38b26ca15006d38acf532d0dedea4177a2d33f06956d80e963848ec791b2762fa99449b4f1a1ed9b3f2580be3ac7d7f52fb14421d6222ba76f807750c6cbb0b16f0895fc73d9dfc587e1a9e5d1e58375fbab705b8f0c1fd7df8b3ad446f2f08459e7ed1af59556fbc966dc249c1cf604f3e677c8a09d4363608774bf3811bef0642748c55c516c7a580fa3499050acb30eed870d0d91174cb623e98c3ad121cf81f04e57d49b008424a98a31eeaaf5f38e000f903d48d215ed52f862d636a5a73607de85760167267efe30f8a26ebc5aa0c09f5b258d3361ca69d1d7ee07b59648179ab2170ec50c07f6616f216872529421a6334a4a1ed3d2671ef47bc9a92afb58314e832db8a9003408a0487503fe4f67770dd4b6:29df3ad589009c667baa5e72dabb4e53cb7876de4e7efe5cc21ead7fa878db57f97c1103ddb39a861eb88653c1d4ec3b4306e4584b47b8bc90423119e7e4af00a6c17eeb5b8066c2cd9a89667317a945a0c7c96996e77ae854c509c6cd0631e922ad04503af87a3c4628adafed7600d071c078a22e7f64bda08a362b38b26ca15006d38acf532d0dedea4177a2d33f06956d80e963848ec791b2762fa99449b4f1a1ed9b3f2580be3ac7d7f52fb14421d6222ba76f807750c6cbb0b16f0895fc73d9dfc587e1a9e5d1e58375fbab705b8f0c1fd7df8b3ad446f2f08459e7ed1af59556fbc966dc249c1cf604f3e677c8a09d4363608774bf3811bef0642748c55c516c7a580fa3499050acb30eed870d0d91174cb623e98c3ad121cf81f04e57d49b008424a98a31eeaaf5f38e000f903d48d215ed52f862d636a5a73607de85760167267efe30f8a26ebc5aa0c09f5b258d3361ca69d1d7ee07b59648179ab2170ec50c07f6616f216872529421a6334a4a1ed3d2671ef47bc9a92afb58314e832db8a9003408a0487503fe4f67770dd4b6: +3dd7203c237aefe9e38a201ff341490179905f9f100828da18fcbe58768b5760f067d7b2ff3a957e8373a7d42ef0832bcda84ebf287249a184a212a94c99ea5b:f067d7b2ff3a957e8373a7d42ef0832bcda84ebf287249a184a212a94c99ea5b:db28ed31ac04b0c2decee7a6b24fc9a082cc262ca7ccf2a247d6372ec3e9120ecedb4542ea593fea30335c5ab9dd318a3b4fd5834299cf3f53d9ef46137b273c390ec3c26a0b4470d0d94b77d82cae4b24587837b167bb7f8166710baeb3ee70af797316cb7d05fa57e468ae3f0bd449404d8528808b41fcca62f5e0a2aa5d8f3acab008cc5f6e5ab02777bdcde87f0a10ef06a4bb37fe02c94815cf76bfb8f5cdd865cc26dcb5cf492edfd547b535e2e6a6d8540956dcba62cfea19a9474406e934337e454270e01036ac45793b6b8aceda187a08d56a2ce4e98f42ea375b101a6b9fcb4231d171aa463eeb43586a4b82a387bcddaf71a80fd5c1f7292efc2bd8e70c11eaa817106061b6c461c4883d613cc06c7e2a03f73d90fc55cdc07265eefd36be72270383d6c676cae37c93691f1ae3d927b3a1cd963e4229757ae5231eea73a9f71515628305410ac2593b325cc631:4c036935a96abc0d050d907bedbe9946fb97439f039c742e051ccf09add7df44d17da98c2ca01bdc2424da1e4debf347f8fff48ac8030d2cc07f9575c044be04db28ed31ac04b0c2decee7a6b24fc9a082cc262ca7ccf2a247d6372ec3e9120ecedb4542ea593fea30335c5ab9dd318a3b4fd5834299cf3f53d9ef46137b273c390ec3c26a0b4470d0d94b77d82cae4b24587837b167bb7f8166710baeb3ee70af797316cb7d05fa57e468ae3f0bd449404d8528808b41fcca62f5e0a2aa5d8f3acab008cc5f6e5ab02777bdcde87f0a10ef06a4bb37fe02c94815cf76bfb8f5cdd865cc26dcb5cf492edfd547b535e2e6a6d8540956dcba62cfea19a9474406e934337e454270e01036ac45793b6b8aceda187a08d56a2ce4e98f42ea375b101a6b9fcb4231d171aa463eeb43586a4b82a387bcddaf71a80fd5c1f7292efc2bd8e70c11eaa817106061b6c461c4883d613cc06c7e2a03f73d90fc55cdc07265eefd36be72270383d6c676cae37c93691f1ae3d927b3a1cd963e4229757ae5231eea73a9f71515628305410ac2593b325cc631: +282775df9ebbd7c5a65f3a2b096e36ee64a8f8ea719da77758739e4e7476111da2b49646033a13937cad6b0e914e3cec54989c252ca5643d076555d8c55e56e0:a2b49646033a13937cad6b0e914e3cec54989c252ca5643d076555d8c55e56e0:14cc50c2973ea9d0187a73f71cb9f1ce07e739e049ec2b27e6613c10c26b73a2a966e01ac3be8b505aeaad1485c1c2a3c6c2b00f81b9e5f927b73bfd498601a7622e8544837aad02e72bf72196dc246902e58af253ad7e025e3666d3bfc46b5b02f0eb4a37c9554992abc8651de12fd813177379bb0ce172cd8aaf937f979642bc2ed7c7a430cb14c3cd3101b9f6b91ee3f542acdf017f8c2116297f4564768f4db95dad8a9bcdc8da4d8fb13ef6e2da0b1316d3c8c2f3ed836b35fe2fd33effb409e3bc1b0f85225d2a1de3bfc2d20563946475c4d7ca9fddbaf59ad8f8961d287ae7dd803e7af1fa612329b1bdc04e225600ae731bc01ae0925aed62ac50d46086f3646cf47b072f0d3b044b36f85cec729a8bb2b92883ca4dfb34a8ee8a0273b31af50982bb6131bfa11d55504b1f6f1a0a00438ca26d8ab4f48bcddc9d5a38851abede4151d5b70d720732a00abea2c8b979:15763973859402907d8dcb86adc24a2a168ba3abf2246173d6348afed51ef60b0c0edeff4e10bcef4c6e5778c8bc1f5e9ee0237373445b455155d23de127a20214cc50c2973ea9d0187a73f71cb9f1ce07e739e049ec2b27e6613c10c26b73a2a966e01ac3be8b505aeaad1485c1c2a3c6c2b00f81b9e5f927b73bfd498601a7622e8544837aad02e72bf72196dc246902e58af253ad7e025e3666d3bfc46b5b02f0eb4a37c9554992abc8651de12fd813177379bb0ce172cd8aaf937f979642bc2ed7c7a430cb14c3cd3101b9f6b91ee3f542acdf017f8c2116297f4564768f4db95dad8a9bcdc8da4d8fb13ef6e2da0b1316d3c8c2f3ed836b35fe2fd33effb409e3bc1b0f85225d2a1de3bfc2d20563946475c4d7ca9fddbaf59ad8f8961d287ae7dd803e7af1fa612329b1bdc04e225600ae731bc01ae0925aed62ac50d46086f3646cf47b072f0d3b044b36f85cec729a8bb2b92883ca4dfb34a8ee8a0273b31af50982bb6131bfa11d55504b1f6f1a0a00438ca26d8ab4f48bcddc9d5a38851abede4151d5b70d720732a00abea2c8b979: +4730a5cf9772d7d6665ba787bea4c95252e6ecd63ec62390547bf100c0a46375f9f094f7cc1d40f1926b5b22dce465784468b20ab349bc6d4fdf78d0042bbc5b:f9f094f7cc1d40f1926b5b22dce465784468b20ab349bc6d4fdf78d0042bbc5b:e7476d2e668420e1b0fadfbaa54286fa7fa890a87b8280e26078152295e1e6e55d1241435cc430a8693bb10cde4643f59cbfcc256f45f5090c909a14c7fc49d37bfc25af11e8f4c83f4c32d4aabf43b20fa382bb6622a1848f8ffc4dff3408bb4ec7c67a35b4cdaee5e279c0fc0a66093a9f36a60fdd65e6334a804e845c8530b6fda363b5640337d027243ccfb3c177f43e717896e46ead7f72ca06aa0ff1e77247121baf48be9a445f729ca1390fc46151cbd33fcbd7373f27a6ba55c92cbf6945b09b44b9a4e5800d403070ae66048997b2197f02181a097e563f9b9acc841139258a258bc610d3bd891637356b2edc8c184c35c65af91aaf7b1c16d74a5f5f862548139254ecf550631d5f8849afdb5b64cf366ff2633a93f3a18c39b5150245fb5f33c9e4e2d94af6963a70b88f9e7e519f8fa2a0f2e3749de883d0e6f052a949d0fc7153a8693f6d801d7352eb2f7a465c0e:552c7347bdfe131646ce0932d82a36d2c1b76d7c30ee890e0592e19f9d18b9a56f48d7a9b68c017da6b550c943af4a907baf317e419fbbc96f6cf4bfad42de00e7476d2e668420e1b0fadfbaa54286fa7fa890a87b8280e26078152295e1e6e55d1241435cc430a8693bb10cde4643f59cbfcc256f45f5090c909a14c7fc49d37bfc25af11e8f4c83f4c32d4aabf43b20fa382bb6622a1848f8ffc4dff3408bb4ec7c67a35b4cdaee5e279c0fc0a66093a9f36a60fdd65e6334a804e845c8530b6fda363b5640337d027243ccfb3c177f43e717896e46ead7f72ca06aa0ff1e77247121baf48be9a445f729ca1390fc46151cbd33fcbd7373f27a6ba55c92cbf6945b09b44b9a4e5800d403070ae66048997b2197f02181a097e563f9b9acc841139258a258bc610d3bd891637356b2edc8c184c35c65af91aaf7b1c16d74a5f5f862548139254ecf550631d5f8849afdb5b64cf366ff2633a93f3a18c39b5150245fb5f33c9e4e2d94af6963a70b88f9e7e519f8fa2a0f2e3749de883d0e6f052a949d0fc7153a8693f6d801d7352eb2f7a465c0e: +2770aadd1d123e9547832dfb2a837eba089179ef4f23abc4a53f2a714e423ee23c5fbb07530dd3a20ff35a500e3708926310fed8a899690232b42c15bd86e5dc:3c5fbb07530dd3a20ff35a500e3708926310fed8a899690232b42c15bd86e5dc:a5cc2055eba3cf6f0c6332c1f2ab5854870913b03ff7093bc94f335add44332231d9869f027d82efd5f1227144ab56e3222dc3ddccf062d9c1b0c1024d9b416dfa3ee8a7027923003465e0ffaefb75b9f29dc6bcf213adc5e318fd8ba93a7aa5bfb495de9d7c5e1a196cd3a2d7721f8ba785aa9052a1811c7fcc8f93932765059cab9c9b718945895ef26f3ac048d4cabf91a9e6aa83ac14d43156827837914eb763a23cba53f60f150f4b70203ec1833ff105849457a8da7327661fb23a554164e05fcf0146b10674964be6f6aa0acc94c41ad57180e5180d199bd9102f55d740e81789b15671bbd0670e6de5d97e1ae626d8a0ebc32c8fd9d24737274e47d2dd5941a272e72a598928ad109cde937bf248d57f5d2942983c51e2a89f8f054d5c48dfad8fcf1ffa97f7de6a3a43ca15fc6720efaec69f0836d84223f9776d111ec2bbc69b2dfd58be8ca12c072164b718cd7c246d64:f267715e9a84c7314f2d5869ef4ab8d2149a13f7e8e1c728c423906293b49ce6283454dd1c7b04741df2eabedc4d6ab1397dc95a679df04d2c17d66c79bb7601a5cc2055eba3cf6f0c6332c1f2ab5854870913b03ff7093bc94f335add44332231d9869f027d82efd5f1227144ab56e3222dc3ddccf062d9c1b0c1024d9b416dfa3ee8a7027923003465e0ffaefb75b9f29dc6bcf213adc5e318fd8ba93a7aa5bfb495de9d7c5e1a196cd3a2d7721f8ba785aa9052a1811c7fcc8f93932765059cab9c9b718945895ef26f3ac048d4cabf91a9e6aa83ac14d43156827837914eb763a23cba53f60f150f4b70203ec1833ff105849457a8da7327661fb23a554164e05fcf0146b10674964be6f6aa0acc94c41ad57180e5180d199bd9102f55d740e81789b15671bbd0670e6de5d97e1ae626d8a0ebc32c8fd9d24737274e47d2dd5941a272e72a598928ad109cde937bf248d57f5d2942983c51e2a89f8f054d5c48dfad8fcf1ffa97f7de6a3a43ca15fc6720efaec69f0836d84223f9776d111ec2bbc69b2dfd58be8ca12c072164b718cd7c246d64: +4fdab7c1600e70114b11f533242376af7614b4d5da046ac4bedea21d8a361598a25c9a94d6e4ecd95a4bd6805f762eb1c457a8d45d243238b1839cbba8f441cc:a25c9a94d6e4ecd95a4bd6805f762eb1c457a8d45d243238b1839cbba8f441cc:da405890d11a872c119dab5efcbff61e931f38eccca457edc626d3ea29ed4fe3154fafec1444da74343c06ad90ac9d17b511bcb73bb49d90bafb7c7ea800bd58411df1275c3cae71b700a5dab491a4261678587956aa4a219e1ac6dd3fb2cb8c46197218e726dc7ed234526a6b01c0d72cb93ab3f4f38a08e5940b3f61a72ad2789a0532000fac1d2d2e3ad632ac8b62bb3ff5b99d53597bf4d44b19674924df9b3db3d0253f74627ccab30031c85e291c58b5fa9167522a46746fc307036745d4f9817786e5d300e6c5d503125fea01dec3e3fedbf3861ca2627a0518fb2b24e5a7a014178719e9b345f7b249ce3a413280c8deb674f59a25be92a8ab6400c7c52b0728ae34e22b2ec200c1cbaba2ccd8af29249d17af60c36007a722fc80258a7bebab1cdaad7462a8b7588c2f7e27c6d07afcf60117fed11bd6859e75e3b4fcee3981881e95dd116827dd4b369af069d3c8f2676f8a:5075c090cfbeb6b01802af7f4da5aa4f434d5ee2f3530eebb75c85e08621f83edc08aa96693894a4277633ba81e19e9e55af5c495daa5e1a6f8cbb79c01c7207da405890d11a872c119dab5efcbff61e931f38eccca457edc626d3ea29ed4fe3154fafec1444da74343c06ad90ac9d17b511bcb73bb49d90bafb7c7ea800bd58411df1275c3cae71b700a5dab491a4261678587956aa4a219e1ac6dd3fb2cb8c46197218e726dc7ed234526a6b01c0d72cb93ab3f4f38a08e5940b3f61a72ad2789a0532000fac1d2d2e3ad632ac8b62bb3ff5b99d53597bf4d44b19674924df9b3db3d0253f74627ccab30031c85e291c58b5fa9167522a46746fc307036745d4f9817786e5d300e6c5d503125fea01dec3e3fedbf3861ca2627a0518fb2b24e5a7a014178719e9b345f7b249ce3a413280c8deb674f59a25be92a8ab6400c7c52b0728ae34e22b2ec200c1cbaba2ccd8af29249d17af60c36007a722fc80258a7bebab1cdaad7462a8b7588c2f7e27c6d07afcf60117fed11bd6859e75e3b4fcee3981881e95dd116827dd4b369af069d3c8f2676f8a: +264504604e70d72dc4474dbb34913e9c0f806dfe18c7879a41762a9e4390ec61eb2b518ce7dc71c91f3665581651fd03af84c46bf1fed2433222353bc7ec511d:eb2b518ce7dc71c91f3665581651fd03af84c46bf1fed2433222353bc7ec511d:901d70e67ed242f2ec1dda813d4c052cfb31fd00cfe5446bf3b93fdb950f952d94ef9c99d1c264a6b13c3554a264beb97ed20e6b5d66ad84db5d8f1de35c496f947a23270954051f8e4dbe0d3ef9ab3003dd47b859356cecb81c50affa68c15dadb5f864d5e1bb4d3bada6f3aba1c83c438d79a94bfb50b43879e9cef08a2bfb22fad943dbf7683779746e31c486f01fd644905048b112ee258042153f46d1c7772a0624bcd6941e9062cfda75dc8712533f4057335c298038cbca29ebdb560a295a88339692808eb3481fd9735ea414f620c143b2133f57bb64e44778a8ca70918202d157426102e1dfc0a8f7b1ae487b74f02792633154dfe74caa1b7088fda22fa8b9bc354c585f1567706e2955493870f54169e0d7691159df43897961d24a852ea970c514948f3b48f71ee586e72ec78db820f253e08db84f6f312c4333bd0b732fe75883507783e9a1fd4fbab8e5870f9bf7ad58aa:eea439a00f7e459b402b835150a779eed171ab971bd1b58dcc7f9386dadd583de8dc69e267121dde41f0f9493d450b16219cdf3c22f09482ce402fe17ca49e08901d70e67ed242f2ec1dda813d4c052cfb31fd00cfe5446bf3b93fdb950f952d94ef9c99d1c264a6b13c3554a264beb97ed20e6b5d66ad84db5d8f1de35c496f947a23270954051f8e4dbe0d3ef9ab3003dd47b859356cecb81c50affa68c15dadb5f864d5e1bb4d3bada6f3aba1c83c438d79a94bfb50b43879e9cef08a2bfb22fad943dbf7683779746e31c486f01fd644905048b112ee258042153f46d1c7772a0624bcd6941e9062cfda75dc8712533f4057335c298038cbca29ebdb560a295a88339692808eb3481fd9735ea414f620c143b2133f57bb64e44778a8ca70918202d157426102e1dfc0a8f7b1ae487b74f02792633154dfe74caa1b7088fda22fa8b9bc354c585f1567706e2955493870f54169e0d7691159df43897961d24a852ea970c514948f3b48f71ee586e72ec78db820f253e08db84f6f312c4333bd0b732fe75883507783e9a1fd4fbab8e5870f9bf7ad58aa: +2ca7447a3668b748b1fd3d52d2080d30e34d397bb2846caf8f659ac168788ca5ab331cd40a31d0173c0c8c1c17002532807bf89e3edb6d34c2dd8294632b9fbc:ab331cd40a31d0173c0c8c1c17002532807bf89e3edb6d34c2dd8294632b9fbc:a82bcd9424bffda0f2f5e9eae17835dbe468f61b785aab82934737a91c5f602cb7c617cdffe87cad726a4972e15a7b8ee147f062d2a5a4d89706b571fa8aa2b95981c78abeaaae86203fa2c0e07297406ea8c27111a86dbe1d5a7c3b7ae930904d9890f6d4abebd1412a73ad5feea64acf065d3e63b5cbe20cf20bbd2d8b94f9053ed5f66633482530124446605918de66455e8cf4b101a127233c4e27d5d55bf95bd3195d0340d43531fc75faf8dded5275bf89750de838fd10c31745be4ca41fa871cb0f9b016706a1a7e3c44bb90ac7a8ad51e272389292fd6c98ad7a069e76e3f5f3e0cc770b9e9b35a765d0d93712d7cdabd17e5d01dd8183af4ad9365db0a0fa41381fce60a081df1c5ab0f8c18f95a7a8b582dfff7f149ea579df0623b33b7508f0c663f01e3a2dcd9dfbee51cc615220fdaffdab51bdae42cb9f7fa9e3b7c69cc8ada5ccd642529ba514fdc54fcf2720b8f5d08b95:f93ada15ae9cd2b54f26f86f0c28392aed5eb6b6b44d01a4e33a54e7da37c38e8d53366f73fd85be642e4ec81236d163f0d025e76c8bbdd65d43df49f09c1f01a82bcd9424bffda0f2f5e9eae17835dbe468f61b785aab82934737a91c5f602cb7c617cdffe87cad726a4972e15a7b8ee147f062d2a5a4d89706b571fa8aa2b95981c78abeaaae86203fa2c0e07297406ea8c27111a86dbe1d5a7c3b7ae930904d9890f6d4abebd1412a73ad5feea64acf065d3e63b5cbe20cf20bbd2d8b94f9053ed5f66633482530124446605918de66455e8cf4b101a127233c4e27d5d55bf95bd3195d0340d43531fc75faf8dded5275bf89750de838fd10c31745be4ca41fa871cb0f9b016706a1a7e3c44bb90ac7a8ad51e272389292fd6c98ad7a069e76e3f5f3e0cc770b9e9b35a765d0d93712d7cdabd17e5d01dd8183af4ad9365db0a0fa41381fce60a081df1c5ab0f8c18f95a7a8b582dfff7f149ea579df0623b33b7508f0c663f01e3a2dcd9dfbee51cc615220fdaffdab51bdae42cb9f7fa9e3b7c69cc8ada5ccd642529ba514fdc54fcf2720b8f5d08b95: +494ea9bcce26885b7d17d1fc114448f239f0ce46e5f247b4c999fa86296924726901e5efae57536ba5fdd96b59657359065f25d391a1aa8cdc0d38bb5d53c139:6901e5efae57536ba5fdd96b59657359065f25d391a1aa8cdc0d38bb5d53c139:3badbfa5f5a8aa2cce0a60e686cdce654d24452f98fd54872e7395b39464380a0e185557ea134d095730864f4254d3dd946970c10c804fcc0899dfa024205be0f80b1c75449523324fe6a0751e47b4ff4822b8c33e9eaf1d1d96e0de3d4acd89696b7fcc03d49f92f82b9725700b350db1a87615369545561b8599f5ea920a310a8bafc0e8d7468cbf6f3820e943594afdd5166e4e3309dddd7694ef67e694f34fc62724ff96ac3364176f34e8a02b4cf569db5b8f77d58512aedabf0bcd1c2df12db3a9473f948c5c3243309aae46c49efd088b60f31a8a72ad7e5a35acc5d89fa66807eb5d3ba9cdf08d4753cb85089ee36f5c96b432b6928352afad58012225d6157f9e3611426df921b6d1d8374628a63031e9ffb90e42ffbba021f174f68503155430152c9155dc98ffa26c4fab065e1f8e4622c2f28a8cb043110b617441140f8e20adc16f799d1d5096b1f50532be5042d21b81ea46c7:548a093a680361b7dc56f14503b55eeec3b3f4fd4ca99d6aedce0830f7f4ae2f7328539b34c48fc9760922333dae9c7c017e7db73b8faa6c06be05e347992b063badbfa5f5a8aa2cce0a60e686cdce654d24452f98fd54872e7395b39464380a0e185557ea134d095730864f4254d3dd946970c10c804fcc0899dfa024205be0f80b1c75449523324fe6a0751e47b4ff4822b8c33e9eaf1d1d96e0de3d4acd89696b7fcc03d49f92f82b9725700b350db1a87615369545561b8599f5ea920a310a8bafc0e8d7468cbf6f3820e943594afdd5166e4e3309dddd7694ef67e694f34fc62724ff96ac3364176f34e8a02b4cf569db5b8f77d58512aedabf0bcd1c2df12db3a9473f948c5c3243309aae46c49efd088b60f31a8a72ad7e5a35acc5d89fa66807eb5d3ba9cdf08d4753cb85089ee36f5c96b432b6928352afad58012225d6157f9e3611426df921b6d1d8374628a63031e9ffb90e42ffbba021f174f68503155430152c9155dc98ffa26c4fab065e1f8e4622c2f28a8cb043110b617441140f8e20adc16f799d1d5096b1f50532be5042d21b81ea46c7: +00d735ebaee75dd579a40dfd82508274d01a1572df99b811d5b01190d82192e4ba02517c0fdd3e2614b3f7bf99ed9b492b80edf0495d230f881730ea45bc17c4:ba02517c0fdd3e2614b3f7bf99ed9b492b80edf0495d230f881730ea45bc17c4:59c0b69af95d074c88fdc8f063bfdc31b5f4a9bc9cecdffa8128e01e7c1937dde5eb0570b51b7b5d0a67a3555b4cdce2bca7a31a4fe8e1d03ab32b4035e6dadbf1532059ee01d3d9a7633a0e706a1154cab22a07cd74c06a3cb601244cf3cf35a35c3100ba47f31372a2da65dcff0d7a80a1055d8aa99212e899aad7f02e949e6fee4d3c9cefa85069eaff1f6ad06fc300c871ab82b2bedb934d20875c2a263242cdb7f9be192a8710b24c7ea98d43daec8baa5553c678a38f0e0adf7d3ff2dcc799a1dbad6eab1c3d9458a9db922f02e75cfab9d65c7336dae71895d5bb15cac203f2b38b9996c410f8655ad22d3c091c20b7f926d45e780128f19747462abc5c58932fbb9e0bc62d53868802f1b083f183b8a1f9434986d5cf97c04e2f3e145730cba98779c7fed0cab1c05d5e4653c6c3f6736260bc78ee4372862ffe9e90371d762c7432781f35ced884a4baca05653ef25f25a6f3d5628308:dcdc54611937d2bd06cacd9818b3be15ce7425427a75f50d197a337a3b8ba6714ef48866f243bd5ac7415e914517a2c1c5a953f432b99db0e620d64f74eb850559c0b69af95d074c88fdc8f063bfdc31b5f4a9bc9cecdffa8128e01e7c1937dde5eb0570b51b7b5d0a67a3555b4cdce2bca7a31a4fe8e1d03ab32b4035e6dadbf1532059ee01d3d9a7633a0e706a1154cab22a07cd74c06a3cb601244cf3cf35a35c3100ba47f31372a2da65dcff0d7a80a1055d8aa99212e899aad7f02e949e6fee4d3c9cefa85069eaff1f6ad06fc300c871ab82b2bedb934d20875c2a263242cdb7f9be192a8710b24c7ea98d43daec8baa5553c678a38f0e0adf7d3ff2dcc799a1dbad6eab1c3d9458a9db922f02e75cfab9d65c7336dae71895d5bb15cac203f2b38b9996c410f8655ad22d3c091c20b7f926d45e780128f19747462abc5c58932fbb9e0bc62d53868802f1b083f183b8a1f9434986d5cf97c04e2f3e145730cba98779c7fed0cab1c05d5e4653c6c3f6736260bc78ee4372862ffe9e90371d762c7432781f35ced884a4baca05653ef25f25a6f3d5628308: +8c34b905440b61911d1d8137c53d46a1a76d4609af973e18eb4c5709295627bbb69a8b2fdf5c20e734c2ffb294bc8ae1011d664f11afe7fbc471925cf72fa99d:b69a8b2fdf5c20e734c2ffb294bc8ae1011d664f11afe7fbc471925cf72fa99d:30b57a389b48a0beb1a48432bff6b314bded79c4a1763a5acb57cea1bfb4c6d016cf090f5bd05bbd114e33ae7c17782dfa264f46c45f8c599c603016fe9ff05b6b5a99e92fe713a4cd5c41b292ed2bb2e9cf33a440542e821ec82cbf665c3f02e3dc337d7fdb58e31b27cb2954541468814698510df18c85c81fad12db11ec6b966f4930da5646b991db97445097da30dab61cda53a41083cb96add19de6c5eec323bca9d3530e38c00b35af7360077601be6ac97f3030f930a27b90fe8b6911bae389065adc15e1882300e2a003274d23182d5efd5ba4b9130c07bd5c65fecb8b5cb7eb38836b318befdfd77de4d6ca0181f77ae5740891683225f549dd8426145c97c5818c319f7ab2d868e1a41ceab64c085116069897bf2ca3667652406155ed0646431b6de1ccc03b4279ae4d326679265dce82048e7298e1f87fcec0768ac0f5d8ff84f7210be54d411af8edea7217f4e59413121e148c60da:3e0b72073dc9375eedcca6c4fc1cd315938a050c92716bd2284f4629a962beec0b7d7cf16ab923d58f5b90d3901a8e5c75c8f17dab9998e007d8c49511973d0e30b57a389b48a0beb1a48432bff6b314bded79c4a1763a5acb57cea1bfb4c6d016cf090f5bd05bbd114e33ae7c17782dfa264f46c45f8c599c603016fe9ff05b6b5a99e92fe713a4cd5c41b292ed2bb2e9cf33a440542e821ec82cbf665c3f02e3dc337d7fdb58e31b27cb2954541468814698510df18c85c81fad12db11ec6b966f4930da5646b991db97445097da30dab61cda53a41083cb96add19de6c5eec323bca9d3530e38c00b35af7360077601be6ac97f3030f930a27b90fe8b6911bae389065adc15e1882300e2a003274d23182d5efd5ba4b9130c07bd5c65fecb8b5cb7eb38836b318befdfd77de4d6ca0181f77ae5740891683225f549dd8426145c97c5818c319f7ab2d868e1a41ceab64c085116069897bf2ca3667652406155ed0646431b6de1ccc03b4279ae4d326679265dce82048e7298e1f87fcec0768ac0f5d8ff84f7210be54d411af8edea7217f4e59413121e148c60da: +77a83e18c9f000eeff7deeac959ecba2206c0aa39d2f0e2aed5729482a7a022962b1b316135596bfbca6037ed847c61fb7f09fa36ce90abb7789b86f768b59dd:62b1b316135596bfbca6037ed847c61fb7f09fa36ce90abb7789b86f768b59dd:f3d5fa2acaefd858f1df26e03059cdcbc2468ad74afc993d0db9c4cde4113f8d55c7da71d38ba06520531c61fddb5f33d5f0353be2376e580711be45c0a30b1fa01b55e228c6fa35e3f95b67909fc7df3fd464d93d661a926f9d11f7550c17fbcc3496526e8f10e0c8916677b2be5b319b688f21e81aaa9482e5c93e64ce8c437b9c1e14fefed70a3fee568811dc31cadab3d5b220254465336dc4d97a3bd096b5e065e0cfbe82849e2c1905aca486533f0da7a61f1e9a55b8e2a83262deeb59f2b13d3a8aef5700845b83b25ae2183c0ddac0ce42f8d25674cb0d0d220a6de7c1858bb07d59a3372344d944602aa451d2b937db0fe6feca0beba81721fc361ea7509e2b6d397e1c191b56f54ab436d0d27ab4c061bd661ad1a4452387e8735754d07fa7ef4d4548b172582425b299046e6301b5ba6b914418f149cf722e10bde2e0d41700f12c8429fc897b7819da92292240cd45565458c9a7b29c12:1eaad8420ac12c99ac1ff4476678e3cbbe94da6a797f174664d5ee0f641433fb1e7cb2f5613e10805df8654cd8e0d45d96230932bc7f20b04eae836435134309f3d5fa2acaefd858f1df26e03059cdcbc2468ad74afc993d0db9c4cde4113f8d55c7da71d38ba06520531c61fddb5f33d5f0353be2376e580711be45c0a30b1fa01b55e228c6fa35e3f95b67909fc7df3fd464d93d661a926f9d11f7550c17fbcc3496526e8f10e0c8916677b2be5b319b688f21e81aaa9482e5c93e64ce8c437b9c1e14fefed70a3fee568811dc31cadab3d5b220254465336dc4d97a3bd096b5e065e0cfbe82849e2c1905aca486533f0da7a61f1e9a55b8e2a83262deeb59f2b13d3a8aef5700845b83b25ae2183c0ddac0ce42f8d25674cb0d0d220a6de7c1858bb07d59a3372344d944602aa451d2b937db0fe6feca0beba81721fc361ea7509e2b6d397e1c191b56f54ab436d0d27ab4c061bd661ad1a4452387e8735754d07fa7ef4d4548b172582425b299046e6301b5ba6b914418f149cf722e10bde2e0d41700f12c8429fc897b7819da92292240cd45565458c9a7b29c12: +73b03373ef1fd849005ecd6270dd9906f19f4439e40376cdbc520902bc976812663719e08ba3ba1666f6069a3f54991866b18cc6be41991b02eb3026ff9e155f:663719e08ba3ba1666f6069a3f54991866b18cc6be41991b02eb3026ff9e155f:d5c2deaba795c30aba321bc7de6996f0d90e4d05c747fb4dae8f3451895def6e16e72f38eace756f36635f8fb0b72a3a0c1f54663817a94d4fd346f835ab0e657f001a6f2cecb86d0825bd02639254f7f7f38ca99dbb86c64a633f73baf933aae3563281f4005e2d0e7cec9fbde8e588a957e211068be65b3d3d35bf4e8d5bb3478333df9ced9b2abaf48697994a145e9321499fc5ee560f4fbb6849e1ae8eb3d1de0083a21a03f6a6b28176f0130d3895e50e75e3d7d0947a7bc2c5b9ff69895d27791442ba8d0f2180712b567f712ea912f3b0d92c19342e0106ff1d87b46ad33af300b90855ba9769d366e79425d98e4de19905a04577707cbe625b84691781cd26bf62260b4a8bd605f77af6f970e1b3a112e8918344bd0d8d2e41dfd2ce9895b0246e50887aa3a577ff73be4b6ae60feb0ca36f6a5f8171ed209e5c566529c0940d9b4bd744ccee56e54a9a0c6e4da520dd315c2872b02db563703e:a40abe98fc69da8a1ff9ff5c2cca93632e975980ee8b82c3c376022d6524ab736d01b072f2b681b5f1cd3ea067012ed6d074e949c42327a366caa9e4750a3c08d5c2deaba795c30aba321bc7de6996f0d90e4d05c747fb4dae8f3451895def6e16e72f38eace756f36635f8fb0b72a3a0c1f54663817a94d4fd346f835ab0e657f001a6f2cecb86d0825bd02639254f7f7f38ca99dbb86c64a633f73baf933aae3563281f4005e2d0e7cec9fbde8e588a957e211068be65b3d3d35bf4e8d5bb3478333df9ced9b2abaf48697994a145e9321499fc5ee560f4fbb6849e1ae8eb3d1de0083a21a03f6a6b28176f0130d3895e50e75e3d7d0947a7bc2c5b9ff69895d27791442ba8d0f2180712b567f712ea912f3b0d92c19342e0106ff1d87b46ad33af300b90855ba9769d366e79425d98e4de19905a04577707cbe625b84691781cd26bf62260b4a8bd605f77af6f970e1b3a112e8918344bd0d8d2e41dfd2ce9895b0246e50887aa3a577ff73be4b6ae60feb0ca36f6a5f8171ed209e5c566529c0940d9b4bd744ccee56e54a9a0c6e4da520dd315c2872b02db563703e: +eab179e41ed5c889ffe6aabdc054faf1307c395e46e313e17a14fe01023ffa3086f34746d3f7a01ddbe322f1aca56d22856d38733a3a6900bb08e776450ec803:86f34746d3f7a01ddbe322f1aca56d22856d38733a3a6900bb08e776450ec803:971095cebe5031530224387c5c31966e389b8566390054cf45264b44e18964b7be52c33c4ffb259af16283438fa15dd66bc7791b7533ef10cb0beab524a6437626f4cc74512851adcc2fb129055a482c61107383fb7c5241831d5551634eef0dc0b8f9053a00971aa8fa1ae0898e4b481b6707e97c0f942040b339d92fc17bbade74675af243d8b2dafb15b1db55d12415b85f3037291930ab61600ba3431f8eb425be4491614728af101e81c091f348bc5ffd1bde6ae6cad5c15b3aa7358078cc4effb54a86e7f0e0c55e4cfe0a54605ed443fdf2aaba016585da617e77341d52889d75dd540d39fe8b7993ed705cfddea0cb0d5a731d6bfcdb816afaff47e963eedebdf241af5593353d6d401a34f029a8cdeb1904cc2caa4f9635cc2ba6b7b1a29da625ffc383be2f5a8f1fa4f39b2d4b4f4c2d8838ce258a04d4a120493fdf07f68c0ffd1c16b768a35c55fea2cac696b5c20efc10865cde8a64627dcd:143cb28027c2f82e375e5f340e7fe6e60ce7bd51000b49c74168af85e26ed2ed630ed2672090164cc54b052da694ebdd21a21b3053f4dcfd7895ea5f6c8aa80d971095cebe5031530224387c5c31966e389b8566390054cf45264b44e18964b7be52c33c4ffb259af16283438fa15dd66bc7791b7533ef10cb0beab524a6437626f4cc74512851adcc2fb129055a482c61107383fb7c5241831d5551634eef0dc0b8f9053a00971aa8fa1ae0898e4b481b6707e97c0f942040b339d92fc17bbade74675af243d8b2dafb15b1db55d12415b85f3037291930ab61600ba3431f8eb425be4491614728af101e81c091f348bc5ffd1bde6ae6cad5c15b3aa7358078cc4effb54a86e7f0e0c55e4cfe0a54605ed443fdf2aaba016585da617e77341d52889d75dd540d39fe8b7993ed705cfddea0cb0d5a731d6bfcdb816afaff47e963eedebdf241af5593353d6d401a34f029a8cdeb1904cc2caa4f9635cc2ba6b7b1a29da625ffc383be2f5a8f1fa4f39b2d4b4f4c2d8838ce258a04d4a120493fdf07f68c0ffd1c16b768a35c55fea2cac696b5c20efc10865cde8a64627dcd: +fbf146ebd51075570ec51ac410ae9f391db75b610ada6362b4dbd949656cfb66be7c2f5b21d746c8ea3245ce6f268e9da74e00fa85c9c475260c68fa1af6361f:be7c2f5b21d746c8ea3245ce6f268e9da74e00fa85c9c475260c68fa1af6361f:cd7ad4f17fcff73acc402dc102d09079b29aaf2a0f4b27cf6beeb1e2b23d19ab47deb3ae1becd68861ea279c46691738f4fff47c43047c4f8b56b6bbcc3fde0723d44120dcd307a6310dc4f366b8f3cd52db19b8266a487f7872391c45fe0d3248a7abf2c20022d3769547f683067dcc363cd22fd7cda3cadc15804056f0e2aa2b795008c598be7a961805e6df291ba3041c47ff5640275f46e6ae82092d21abcbcfba11e730216008822de3ce462400596da79f7ae5d1df8389112ad98868fa94fb0546bfe6a67aa8d28c4d32072d2eadd6256255f18c2382e662dfa922a680e06a43622c4871d27d1807f7b2703070c83db8dd929c06038b2183cb8e2b9ec4c778d7ecf9e9ffac77fa7737b055feac2e7982aeeec0b72f1bbca2424e1a844bbac79cb2e7400f81dc449d0560b521a7c16bb4167e6696586058a9b8ed2e5116690b77f2a17e5c0b16a83dcbd2e24552293e258b32ba7f844944379342698627:6768006fe0f201b217dd10eb05d4b82adcfeb2ecfc8373c3308f4150394811eb60491881a2e53d1289d96478e18a64c34b2a19832cdccfd96a2e4a0c469fdc0bcd7ad4f17fcff73acc402dc102d09079b29aaf2a0f4b27cf6beeb1e2b23d19ab47deb3ae1becd68861ea279c46691738f4fff47c43047c4f8b56b6bbcc3fde0723d44120dcd307a6310dc4f366b8f3cd52db19b8266a487f7872391c45fe0d3248a7abf2c20022d3769547f683067dcc363cd22fd7cda3cadc15804056f0e2aa2b795008c598be7a961805e6df291ba3041c47ff5640275f46e6ae82092d21abcbcfba11e730216008822de3ce462400596da79f7ae5d1df8389112ad98868fa94fb0546bfe6a67aa8d28c4d32072d2eadd6256255f18c2382e662dfa922a680e06a43622c4871d27d1807f7b2703070c83db8dd929c06038b2183cb8e2b9ec4c778d7ecf9e9ffac77fa7737b055feac2e7982aeeec0b72f1bbca2424e1a844bbac79cb2e7400f81dc449d0560b521a7c16bb4167e6696586058a9b8ed2e5116690b77f2a17e5c0b16a83dcbd2e24552293e258b32ba7f844944379342698627: +dff0eb6b426dea2fd33c1d3fc24df9b31b486facb7edb8502954a3e8da99d9fdc245085ece69fb9aa560d0c27fdb634f7a840d41d8463660fbe82483b0f3cc3a:c245085ece69fb9aa560d0c27fdb634f7a840d41d8463660fbe82483b0f3cc3a:e7c9e313d86160f4c74aa0ae07369ee22b27f81b3f69097affae28dae48483fb52a5c062306b59610f5cdbff6332b1960cd6f2b8f7b41578c20f0bc9637a0fdfc739d61f699a573f1c1a0b49294506cf4487965e5bb07bbf81803cb3d5cb3829c66c4bee7fc800ede216150934d277dea50edb097b992f11bb669fdf140bf6ae9fec46c3ea32f888fde9d154ea84f01c51265a7d3fef6eefc1ccdbffd1e2c897f05546a3b1ca11d9517cd667c660ec3960f7a8e5e80202a78d3a388b92f5c1dee14ae6acf8e17c841c9557c35a2eeced6e6af6372148e483ccd06c8fe344924e1019fb91cbf7941b9a176a073415867210670410c5dbd0ac4a50e6c0a509ddfdc555f60d696d41c77db8e6c84d5181f872755e64a721b061fcd68c463db4d32c9e01ea501267de22879d7fc12c8ca0379edb45abaa6e64dda2af6d40ccf24fbebad7b5a8d3e52007945ecd3ddc1e3efeb522581ac80e98c863ba0c590a3ed95cd1:6b48b10f545ddb7a89cd5829f4e5b20146cf6bc96e550d06f65de8bdae7ccdded26cd630f86c9266bccf88e924033e04f83a54f8290d7f734cf8673cca8f9703e7c9e313d86160f4c74aa0ae07369ee22b27f81b3f69097affae28dae48483fb52a5c062306b59610f5cdbff6332b1960cd6f2b8f7b41578c20f0bc9637a0fdfc739d61f699a573f1c1a0b49294506cf4487965e5bb07bbf81803cb3d5cb3829c66c4bee7fc800ede216150934d277dea50edb097b992f11bb669fdf140bf6ae9fec46c3ea32f888fde9d154ea84f01c51265a7d3fef6eefc1ccdbffd1e2c897f05546a3b1ca11d9517cd667c660ec3960f7a8e5e80202a78d3a388b92f5c1dee14ae6acf8e17c841c9557c35a2eeced6e6af6372148e483ccd06c8fe344924e1019fb91cbf7941b9a176a073415867210670410c5dbd0ac4a50e6c0a509ddfdc555f60d696d41c77db8e6c84d5181f872755e64a721b061fcd68c463db4d32c9e01ea501267de22879d7fc12c8ca0379edb45abaa6e64dda2af6d40ccf24fbebad7b5a8d3e52007945ecd3ddc1e3efeb522581ac80e98c863ba0c590a3ed95cd1: +9f32958c7679b90fd5036056a75ec2eb2f56ec1effc7c012461dc89a3a1674201d7269dcb6d1f584e662d4ce251de0aba290ef78b97d448afb1e5333f1976d26:1d7269dcb6d1f584e662d4ce251de0aba290ef78b97d448afb1e5333f1976d26:a56ba86c71360504087e745c41627092ad6b49a71e9daa5640e1044bf04d4f071ad728779e95d1e2460584e6f0773545da82d4814c9189a120f12f3e3819813e5b240d0f26436f70ee353b4d20cea54a1460b5b8f1008d6f95f3aa2d8f1e908fced50d624e3a096938b9353854b96da463a2798a5a312ec790842c10c446e3350c764bf5c972593b9987bf23256daa8894d47f22e85b97607e66fc08a12c789c4746080368d321bb9015a1155b65523ad8e99bb989b44eac756b0734acd7c6357c70b59743246d1652d91b0f9896965141345b9945cf34980452f3502974edb76b9c785fb0f4395266b055f3b5db8aab68e9d7102a1cd9ee3d142504f0e88b282e603a738e051d98de05d1fcc65b5f7e99c4111cc0aec489abd0ecad311bfc13e7d1653b9c31e81c998037f959d5cd980835aa0e0b09bcbed634391151da02bc01a36c9a5800afb984163a7bb815edbc0226eda0595c724ca9b3f8a71178f0d20a5a:9881a5763bdb259a3fefbba3d957162d6c70b804fa94ab613406a6ec42505b8789465ca1a9a33e1895988842270c55e5bdd5483f6b17b31781b593507a6c1808a56ba86c71360504087e745c41627092ad6b49a71e9daa5640e1044bf04d4f071ad728779e95d1e2460584e6f0773545da82d4814c9189a120f12f3e3819813e5b240d0f26436f70ee353b4d20cea54a1460b5b8f1008d6f95f3aa2d8f1e908fced50d624e3a096938b9353854b96da463a2798a5a312ec790842c10c446e3350c764bf5c972593b9987bf23256daa8894d47f22e85b97607e66fc08a12c789c4746080368d321bb9015a1155b65523ad8e99bb989b44eac756b0734acd7c6357c70b59743246d1652d91b0f9896965141345b9945cf34980452f3502974edb76b9c785fb0f4395266b055f3b5db8aab68e9d7102a1cd9ee3d142504f0e88b282e603a738e051d98de05d1fcc65b5f7e99c4111cc0aec489abd0ecad311bfc13e7d1653b9c31e81c998037f959d5cd980835aa0e0b09bcbed634391151da02bc01a36c9a5800afb984163a7bb815edbc0226eda0595c724ca9b3f8a71178f0d20a5a: +f86d6f766f88b00717b7d6327eb26cf3ceeba5385184426f9cfd8295e2421ff2cb1d250504754183704dbe21c323d66f9f9011758f6d8dab6f597b199662145b:cb1d250504754183704dbe21c323d66f9f9011758f6d8dab6f597b199662145b:da8423a6b7a18f20aa1f90ed2331b17b24067c40175bc25d8109e21d87ac00528eb3b2f66a2b52dc7ef2f8cecb75c76099cfa23db8da897043ba1cce31e2dfea46075f5e073203eaeb3d62c84c107b6dab33a14eaf149aa61850c15f5a58d88a15aba9196f9e495e8dbecbcf7e8444f5dd72a08a099d7f6209990b562974ea829ef11d29a920e3a799d0d92cb50d50f817631ab09de97c31e9a05f4d78d649fcd93a83752078ab3bb0e16c564d4fb07ca923c0374ba5bf1eea7e73668e135031feafcbb47cbc2ae30ec16a39b9c337e0a62eecdd80c0b7a04924ac3972da4fa9299c14b5a53d37b08bf02268b3bac9ea9355090eeb04ad87bee0593ba4e4443dda38a97afbf2db9952df63f178f3b4c52bcc132be8d9e26881213abdeb7e1c44c4061548909f0520f0dd7520fc408ea28c2cebc0f53063a2d30570e05350e52b390dd9b67662984847be9ad9b4cd50b069ffd29dd9c62ef14701f8d012a4a70c8431cc:ec61c0b292203a8f1d87235ede92b74723c8d23408423773ae50b1e9bc4464e03e446da9dce4c39f6dd159bea26c009ed00120bc36d4a247dc0d24bcefcc110cda8423a6b7a18f20aa1f90ed2331b17b24067c40175bc25d8109e21d87ac00528eb3b2f66a2b52dc7ef2f8cecb75c76099cfa23db8da897043ba1cce31e2dfea46075f5e073203eaeb3d62c84c107b6dab33a14eaf149aa61850c15f5a58d88a15aba9196f9e495e8dbecbcf7e8444f5dd72a08a099d7f6209990b562974ea829ef11d29a920e3a799d0d92cb50d50f817631ab09de97c31e9a05f4d78d649fcd93a83752078ab3bb0e16c564d4fb07ca923c0374ba5bf1eea7e73668e135031feafcbb47cbc2ae30ec16a39b9c337e0a62eecdd80c0b7a04924ac3972da4fa9299c14b5a53d37b08bf02268b3bac9ea9355090eeb04ad87bee0593ba4e4443dda38a97afbf2db9952df63f178f3b4c52bcc132be8d9e26881213abdeb7e1c44c4061548909f0520f0dd7520fc408ea28c2cebc0f53063a2d30570e05350e52b390dd9b67662984847be9ad9b4cd50b069ffd29dd9c62ef14701f8d012a4a70c8431cc: +a5b34cefab9479df8389d7e6f6c146aa8affb0bec837f78af64624a145cc344e7b0f4f24d9972bc6fe83826c52716ad1e0d7d19f123858cb3e99fa636ac9631a:7b0f4f24d9972bc6fe83826c52716ad1e0d7d19f123858cb3e99fa636ac9631a:e21e98af6c2bac70557eb0e864da2c2b4d6c0a39a059d3477251f6178a39676f4749e7fbea623f148a43a8b0fe0610506fa658abd2f5fa39198f2636b724db22d1aebc2ab07b2b6dbffdee8cece81e1af1493ec1964e16bf86ab258ca0feb77e3c8717e44038abe152c14be15660bf93b2d48d92c4ed7074d2494210621bcf204fba88c654d5ffe01e1a53d08f70bb237089dc807216ff6a85dbec3102237d42590778acf6c1dc566d5a2bb9a63bc21c329c272e5965baeeb0fe891de3cc8cbfa8e541a8881df68942e7ff8dc656bd08575f6aaf924a176d663b1a1f43574d11768c701b269561e55438dbebfd443d2115cb933d1cde4a915b54c325c27f499ef02bd012ff1f9a36390922887600fe712bcdc23eb5974a305372ad52951f83f0e58cc49e289841621917f1fcb0235147240dae4cf3b99b6ac6d8de94efe7c4436714508bcd0114c56068ff1b7c16d51bd906437874d6549ab5d8087896872ec8a09d7412:2fbd899d72b6d39e4f45b8b62cbbd5f3c0acb1ad8540913fa585877e91ccfef7bee50a4b0f9fedf5cc1e0d1953ad399c8389a93391e1b7c929af6d6f3b796c08e21e98af6c2bac70557eb0e864da2c2b4d6c0a39a059d3477251f6178a39676f4749e7fbea623f148a43a8b0fe0610506fa658abd2f5fa39198f2636b724db22d1aebc2ab07b2b6dbffdee8cece81e1af1493ec1964e16bf86ab258ca0feb77e3c8717e44038abe152c14be15660bf93b2d48d92c4ed7074d2494210621bcf204fba88c654d5ffe01e1a53d08f70bb237089dc807216ff6a85dbec3102237d42590778acf6c1dc566d5a2bb9a63bc21c329c272e5965baeeb0fe891de3cc8cbfa8e541a8881df68942e7ff8dc656bd08575f6aaf924a176d663b1a1f43574d11768c701b269561e55438dbebfd443d2115cb933d1cde4a915b54c325c27f499ef02bd012ff1f9a36390922887600fe712bcdc23eb5974a305372ad52951f83f0e58cc49e289841621917f1fcb0235147240dae4cf3b99b6ac6d8de94efe7c4436714508bcd0114c56068ff1b7c16d51bd906437874d6549ab5d8087896872ec8a09d7412: +ad75c9ce299c4d59393367d77a4c9f8df8dcec765c6dbd25b527fb7669913604b9910548fe6312a119c9993eebcfb9dc90030ffb0e4de2b7ccd23cbeb4fef71b:b9910548fe6312a119c9993eebcfb9dc90030ffb0e4de2b7ccd23cbeb4fef71b:62fc5ab67deb1fee9ab6cca3b88a1df1e589f0fd4a88f4aa7738948761fe84372c5b18e4655220c1d84d52acad32e229a5c756c20fc62fe4b4b4e5fd7077ae4ed5397aa796f2307ceedb6505b39297856f4aeb5e70938e36ee24a0ac7d9868306f6b53910623b7dc89a6672ad738576ed5d88831dd338321c8902bc2061f65e94d452fdfa0dc665cefb92308e52301bd4627006b363d06b775a395914d8c863e95a00d6893f3376134c429f56478145e4456f7a12d65bb2b8965d728cb2ddbb708f7125c237095a92195d92fa727a372f3545ae701f3808fee802c8967a76e8a940e55fb2d810bfb47ada156f0eda1829b159cf05c7f36cf3847d7b21de84c3dc0fe658347f79396a01139a508b60022db1c0e5aeef47e445e66f783e62c96597bdb16f209c08a9132c7573136170ee3ebf24261265a89fb4f10333375e20b33ab7403464f5249461c6853c5fddb9f58af816892910393a7077b799fdc3489720998feea86:6b7ef27bcfbf2b714985033764fccff555e3f5bc44610d6c8c62117cb3831a07f4a8bddb0eaed1d46b0289b15de1aa4dcc17d71be96a09e66ba4dc4627c7870562fc5ab67deb1fee9ab6cca3b88a1df1e589f0fd4a88f4aa7738948761fe84372c5b18e4655220c1d84d52acad32e229a5c756c20fc62fe4b4b4e5fd7077ae4ed5397aa796f2307ceedb6505b39297856f4aeb5e70938e36ee24a0ac7d9868306f6b53910623b7dc89a6672ad738576ed5d88831dd338321c8902bc2061f65e94d452fdfa0dc665cefb92308e52301bd4627006b363d06b775a395914d8c863e95a00d6893f3376134c429f56478145e4456f7a12d65bb2b8965d728cb2ddbb708f7125c237095a92195d92fa727a372f3545ae701f3808fee802c8967a76e8a940e55fb2d810bfb47ada156f0eda1829b159cf05c7f36cf3847d7b21de84c3dc0fe658347f79396a01139a508b60022db1c0e5aeef47e445e66f783e62c96597bdb16f209c08a9132c7573136170ee3ebf24261265a89fb4f10333375e20b33ab7403464f5249461c6853c5fddb9f58af816892910393a7077b799fdc3489720998feea86: +1ced574529b9b416977e92eb39448a8717cac2934a243a5c44fb44b73ccc16da85e167d5f062fee82014f3c8b1beaed8eefb2c22d8649c424b86b21b11eb8bda:85e167d5f062fee82014f3c8b1beaed8eefb2c22d8649c424b86b21b11eb8bda:1b3b953cce6d15303c61ca707609f70e7250f6c0deba56a8ce522b5986689651cdb848b842b2229661b8eeabfb8570749ed6c2b10a8fbf515053b5ea7d7a9228349e4646f9505e198029fec9ce0f38e4e0ca73625842d64caf8ced070a6e29c743586aa3db6d82993ac71fd38b783162d8fe04ffd0fa5cbc381d0e219c91937df6c973912fc02fda5377312468274c4bee6dca7f79c8b544861ed5babcf5c50e1473491be01708ac7c9ff58f1e40f855497ce9d7cc47b9410f2edd00f6496740243b8d03b2f5fa742b9c630867f77ac42f2b62c14e5ebddc7b647a05fff43670745f2851eff4909f5d27d57ae87f61e965ee60fdf97724c59267f2610b7ad5de919856d64d7c212659ce8656149b6a6d29d8f92b312be50b6e2a431d36ae022b00a6fe360e3af65432899c43be0427e36d21cfec81f21aa53b33db5ed2c37da8f96ac3e7dc67a1de37546cf7de1008c7e1adbe0f34fa7eb2434d94e6a13f4cf86a98d497622f:e0303aefe08a77738dcc657afbb9b835ed279613a53c73fdc5ddbfb350e5cff4d6c9bb43dc07c95bf4e23b64c40f8804c7169952e3c8d59a7197241bfed0740f1b3b953cce6d15303c61ca707609f70e7250f6c0deba56a8ce522b5986689651cdb848b842b2229661b8eeabfb8570749ed6c2b10a8fbf515053b5ea7d7a9228349e4646f9505e198029fec9ce0f38e4e0ca73625842d64caf8ced070a6e29c743586aa3db6d82993ac71fd38b783162d8fe04ffd0fa5cbc381d0e219c91937df6c973912fc02fda5377312468274c4bee6dca7f79c8b544861ed5babcf5c50e1473491be01708ac7c9ff58f1e40f855497ce9d7cc47b9410f2edd00f6496740243b8d03b2f5fa742b9c630867f77ac42f2b62c14e5ebddc7b647a05fff43670745f2851eff4909f5d27d57ae87f61e965ee60fdf97724c59267f2610b7ad5de919856d64d7c212659ce8656149b6a6d29d8f92b312be50b6e2a431d36ae022b00a6fe360e3af65432899c43be0427e36d21cfec81f21aa53b33db5ed2c37da8f96ac3e7dc67a1de37546cf7de1008c7e1adbe0f34fa7eb2434d94e6a13f4cf86a98d497622f: +f0790d93e2d3b84f61ef4c807147aba410e415e72b71b0d61d01026fed99da3defdf649fb033cf328e0b287796f8a25e9c6e2e871b33c2c21a4028a8a25a4b28:efdf649fb033cf328e0b287796f8a25e9c6e2e871b33c2c21a4028a8a25a4b28:7973e9f32d74805992eb65da0d637335e50eff0ce68ea2d1f3a02de704492b9cfbe7e7ba96fdb42bb821a513d73fc60402e92c855deaed73ffeaf70952029062c833e14ec1b14f144e2207f6a0e727e5a7e3cbab27d5972970f69518a15b093e740cc0ce11bf5248f0826b8a98bde8bf2c7082c97aff158d08371118c89021cc3974ae8f76d86673c3f824b62c79c4b41f40eaa8943738f03300f68cbe175468eb235a9ff0e6537f8714e97e8f08ca444e41191063b5fabd156e85dcf66606b81dad4a95065584b3e0658c20a706eaf4a0777da4d2e0cd2a0fca60109c2b4403db3f03cd4781c1fbb0272202bcb11687808c50cb98f64b7f3fd3d43333bb5a061b9e377090abb1e0a885cb26b73c163e63ff6451ff2f4ec8249c7e152bd03973a1e964e2b5b235281a938399a112a24529e383a560dc50bb1b622ad74ef35658dcb10ffe022568ac3ffae5b465a8ed7643e8561b352ee9944a35d882c712b187788a0abae5a22f:08773a6a78762cbb1e25fcbb29139941bdf16f4e09a1fa08fc701f32f933edd74c0ae983c12a0a5b020b6bcf44bb719dde8ed0781a8298265640e1608c98b3017973e9f32d74805992eb65da0d637335e50eff0ce68ea2d1f3a02de704492b9cfbe7e7ba96fdb42bb821a513d73fc60402e92c855deaed73ffeaf70952029062c833e14ec1b14f144e2207f6a0e727e5a7e3cbab27d5972970f69518a15b093e740cc0ce11bf5248f0826b8a98bde8bf2c7082c97aff158d08371118c89021cc3974ae8f76d86673c3f824b62c79c4b41f40eaa8943738f03300f68cbe175468eb235a9ff0e6537f8714e97e8f08ca444e41191063b5fabd156e85dcf66606b81dad4a95065584b3e0658c20a706eaf4a0777da4d2e0cd2a0fca60109c2b4403db3f03cd4781c1fbb0272202bcb11687808c50cb98f64b7f3fd3d43333bb5a061b9e377090abb1e0a885cb26b73c163e63ff6451ff2f4ec8249c7e152bd03973a1e964e2b5b235281a938399a112a24529e383a560dc50bb1b622ad74ef35658dcb10ffe022568ac3ffae5b465a8ed7643e8561b352ee9944a35d882c712b187788a0abae5a22f: +4cb9df7ce6fae9d62ba09e8eb70e4c969bdeafcb5ec7d7024326e6603b0621bf018069dd0eb44055a35cd8c77c37ca9fb1ad2417271385e134b2f4e81f52033c:018069dd0eb44055a35cd8c77c37ca9fb1ad2417271385e134b2f4e81f52033c:14627d6ea0e7895460759476dc74c42800ceef994327518151490d9df23067914e44788a12768ccb25471b9c3ba9d14fb436dcba38429b3a0456877763c49175d0e082683e07a9058f3685c6279307b2303d1221b9c29793d8a4877f6df51587384dadf751c5f7bfbd207d519622c37b51ceeee2c20d8269f8cb88d3fe43d6d434d5bbd0e203c1532d97ba552147227496c87f67b50bb76193add0144df1c176657585408362ca2ed04ad62acf1c25e341dfd1498d85b4b1349a8b0b9b02c43523c55853419bfed37d5a2cdf17dfbf1a3bd7759d6ae180f9d27dcd9a8933e29a7c0a30771eea7c2e0fa242925d2336dce585629057d844323964f6d3d11ff0b3f829a3be8c9f0468a6823d8e70ab5a2da21e15fa8b041a29812222e9c30b2bd9a12d1fdee6f87876e8ce81009637a8bb2236129a47ca74289ee4aad429ffe29f47430241ca8cc3848b7200fd6e1470651a9a0a6f72c9033e831df051408a6260f65cbaf6e012b18e:e33c07836c537d6bfbd0f4592d6e35b163499ba78dc7ffcec565d04f9a7db781943e29e6ce76763e9baddf57437fd9c6b03239a6e6850e4502a356c2e12c370514627d6ea0e7895460759476dc74c42800ceef994327518151490d9df23067914e44788a12768ccb25471b9c3ba9d14fb436dcba38429b3a0456877763c49175d0e082683e07a9058f3685c6279307b2303d1221b9c29793d8a4877f6df51587384dadf751c5f7bfbd207d519622c37b51ceeee2c20d8269f8cb88d3fe43d6d434d5bbd0e203c1532d97ba552147227496c87f67b50bb76193add0144df1c176657585408362ca2ed04ad62acf1c25e341dfd1498d85b4b1349a8b0b9b02c43523c55853419bfed37d5a2cdf17dfbf1a3bd7759d6ae180f9d27dcd9a8933e29a7c0a30771eea7c2e0fa242925d2336dce585629057d844323964f6d3d11ff0b3f829a3be8c9f0468a6823d8e70ab5a2da21e15fa8b041a29812222e9c30b2bd9a12d1fdee6f87876e8ce81009637a8bb2236129a47ca74289ee4aad429ffe29f47430241ca8cc3848b7200fd6e1470651a9a0a6f72c9033e831df051408a6260f65cbaf6e012b18e: +a136e009d53e5ef59d0946bc175663a86bc0fcd29eadd95cfc9d266037b1e4fb9c1806ec0454f58314eb8397d64287dee386640d8491aba364607688841715a0:9c1806ec0454f58314eb8397d64287dee386640d8491aba364607688841715a0:a49d1c3d49e13c2eda56868a8824aa9f8d2bf72f21955ebafd07b3bdc8e924de20936cee513d8a64a47173a3bd659eff1accff8244b26aae1a0c27fa891bf4d85e8fb1b76a6cab1e7f74c89ee07bb40d714326f09b3fd40632fad208ea816f9072028c14b5b54ecc1c5b7fc809e7e0786e2f11495e76017eb62aa4563f3d00ee84348d9838cd17649f6929a6d206f60e6fc82e0c3464b27e0e6abd22f4469bdfd4cb54f77e329b80f71bf42129ec13c9dfe192adfaa42ee3ddeeda385816fbad5f411938c63b560f4ecd94534be7d98725cd94c99ce492f0f069ba0ec08f877a7812ef27ae19d7a77be63f66bcf8d6cf3a1a61fc9cfef104c7462a21ca7f03afb5bb1ac8c75124b554e8d044b810d95ff8c9dd09a34484d8c4b6c95f95c3c22823f52ce844293724d5259191f1ba0929e2acdbb8b9a7a8adf0c52e78acdfdf057b0985881afbed4dbebdebbdae0a2b63bd4e90f96afdcbbd78f506309f9bdb650013cb73faed73904e:bc094ba91c115dee15d753361a75f3f03d6af45c92157e95dbe8d32194b6c5ce72b9dc66f73df12dca0b639f3e791d478616a1f8d7359a42c8eae0dda16b1606a49d1c3d49e13c2eda56868a8824aa9f8d2bf72f21955ebafd07b3bdc8e924de20936cee513d8a64a47173a3bd659eff1accff8244b26aae1a0c27fa891bf4d85e8fb1b76a6cab1e7f74c89ee07bb40d714326f09b3fd40632fad208ea816f9072028c14b5b54ecc1c5b7fc809e7e0786e2f11495e76017eb62aa4563f3d00ee84348d9838cd17649f6929a6d206f60e6fc82e0c3464b27e0e6abd22f4469bdfd4cb54f77e329b80f71bf42129ec13c9dfe192adfaa42ee3ddeeda385816fbad5f411938c63b560f4ecd94534be7d98725cd94c99ce492f0f069ba0ec08f877a7812ef27ae19d7a77be63f66bcf8d6cf3a1a61fc9cfef104c7462a21ca7f03afb5bb1ac8c75124b554e8d044b810d95ff8c9dd09a34484d8c4b6c95f95c3c22823f52ce844293724d5259191f1ba0929e2acdbb8b9a7a8adf0c52e78acdfdf057b0985881afbed4dbebdebbdae0a2b63bd4e90f96afdcbbd78f506309f9bdb650013cb73faed73904e: +ff0f1c57dd884fbeea6e2917282b79ba67f8a6851267b9f4636dafda33bd2b5bfef6378ad12a7c252fa6eb742b05064b41530ff019dc680ab544c027ea2836e7:fef6378ad12a7c252fa6eb742b05064b41530ff019dc680ab544c027ea2836e7:522a5e5eff5b5e98fad6878a9d72df6eb318622610a1e1a48183f5590ecef5a6df671b28be91c88cdf7ae2881147fe6c37c28b43f64cf981c455c59e765ce94e1b6491631deaeef6d1da9ebca88643c77f83eae2cfdd2d97f604fe45081d1be5c4ae2d875996b8b6fecd707d3fa219a93ba0488e55247b405e330cfb97d31a1361c9b2084bdb13fb0c058925db8c3c649c9a3e937b533cc6310fa3b16126fb3cc9bb2b35c5c8300015488a30fadca3c8871fa70dfdc7055bf8e631f20c9b2528311e324a7c4edd5462079f3441c9ecf55fa999e731372344fdc0d413e417aaa001a1b2d3d9bc000fec1b02bd7a88a812d9d8a66f9464764c070c93041eefb17ce74eff6d4aff75f0cbf6a789a9ecde74abe33130fca0da853aa7c3313ada3f0ae2f595c6796a93685e729dd18a669d6381825ab3f36a391e7525b2a807a52fa5ec2a030a8cf3b77337ac41fceb580e845eed655a48b547238c2e8137c92f8c27e585caad3106eee3814a:d5008486726cce330a29dd7e4d7474d735798201afd1206feb869a112e5b43523c06976761be3cf9b2716378273c94f93572a7d2b8982634e0755c632b449008522a5e5eff5b5e98fad6878a9d72df6eb318622610a1e1a48183f5590ecef5a6df671b28be91c88cdf7ae2881147fe6c37c28b43f64cf981c455c59e765ce94e1b6491631deaeef6d1da9ebca88643c77f83eae2cfdd2d97f604fe45081d1be5c4ae2d875996b8b6fecd707d3fa219a93ba0488e55247b405e330cfb97d31a1361c9b2084bdb13fb0c058925db8c3c649c9a3e937b533cc6310fa3b16126fb3cc9bb2b35c5c8300015488a30fadca3c8871fa70dfdc7055bf8e631f20c9b2528311e324a7c4edd5462079f3441c9ecf55fa999e731372344fdc0d413e417aaa001a1b2d3d9bc000fec1b02bd7a88a812d9d8a66f9464764c070c93041eefb17ce74eff6d4aff75f0cbf6a789a9ecde74abe33130fca0da853aa7c3313ada3f0ae2f595c6796a93685e729dd18a669d6381825ab3f36a391e7525b2a807a52fa5ec2a030a8cf3b77337ac41fceb580e845eed655a48b547238c2e8137c92f8c27e585caad3106eee3814a: +0bc6af64de5709d3dbc28f7ef6d3fe28b6de529f08f5857ccb910695de454f56fb491fc900237bdc7e9a119f27150cd911935cd3628749ff40ef41f3955bc8ac:fb491fc900237bdc7e9a119f27150cd911935cd3628749ff40ef41f3955bc8ac:ac7886e4f4172a22c95e8eea37437b375d72accedcee6cc6e816763301a2d8ef4d6f31a2c1d635818b7026a395ce0dafd71c5180893af76b7ea056c972d680eca01dcbdbae6b26f1c5f33fc988b824fbbe00cacc316469a3bae07aa7c8885af7f65f42e75cef94dbb9aab4825143c85070e7716b7612f64ef0b0166011d23eb5654aa098b02d8d71e57c8fa17bff2fe97dc8193177eadc09fb192d80aa92afa98720d4614817ff3c39d3acce18906fa3de09618931d0d7a60c4429cbfa20cf165c947929ac293ae6c06e7e8f25f1264291e3e1c98f5d93e6ecc2389bc60dbbf4a621b132c552a99c95d26d8d1af61138b570a0de4b497ebe8051c7273a98e6e7876d0b327503af3cb2cc4091ce1925cb2f2957f4ec56ee90f8a09dd57d6e83067a356a4cfe65b1b7a4465da2ab133b0efb5e7d4dbb811bcbbde712afbf0f7dd3f326222284b8c74eac7ad6257fa8c632b7da2559a6266e91e0ef90dbb0aa968f75376b693fcaa5da342221:dbc7134d1cd6b0813b53352714b6df939498e91cf37c324337d9c088a1b998347d26185b430900412929e4f63e910379fc42e355a4e98f6fee27dafad1957206ac7886e4f4172a22c95e8eea37437b375d72accedcee6cc6e816763301a2d8ef4d6f31a2c1d635818b7026a395ce0dafd71c5180893af76b7ea056c972d680eca01dcbdbae6b26f1c5f33fc988b824fbbe00cacc316469a3bae07aa7c8885af7f65f42e75cef94dbb9aab4825143c85070e7716b7612f64ef0b0166011d23eb5654aa098b02d8d71e57c8fa17bff2fe97dc8193177eadc09fb192d80aa92afa98720d4614817ff3c39d3acce18906fa3de09618931d0d7a60c4429cbfa20cf165c947929ac293ae6c06e7e8f25f1264291e3e1c98f5d93e6ecc2389bc60dbbf4a621b132c552a99c95d26d8d1af61138b570a0de4b497ebe8051c7273a98e6e7876d0b327503af3cb2cc4091ce1925cb2f2957f4ec56ee90f8a09dd57d6e83067a356a4cfe65b1b7a4465da2ab133b0efb5e7d4dbb811bcbbde712afbf0f7dd3f326222284b8c74eac7ad6257fa8c632b7da2559a6266e91e0ef90dbb0aa968f75376b693fcaa5da342221: +2f5e83bd5b412e71ae3e9084cd369efcc79bf6037c4b174dfd6a11fb0f5da218a22a6da29a5ef6240c49d8896e3a0f1a4281a266c77d383ee6f9d25ffacbb872:a22a6da29a5ef6240c49d8896e3a0f1a4281a266c77d383ee6f9d25ffacbb872:b766273f060ef3b2ae3340454a391b426bc2e97264f8674553eb00dd6ecfdd59b611d8d662929fec710d0e462020e12cdbf9c1ec8858e85671acf8b7b14424ce92079d7d801e2ad9acac036bc8d2dfaa72aa839bff30c0aa7e414a882c00b645ff9d31bcf5a54382def4d0142efa4f06e823257ff132ee968cdc6738c53f53b84c8df76e9f78dd5056cf3d4d5a80a8f84e3edec48520f2cb4583e708539355ef7aa86fb5a0e87a94dcf14f30a2cca568f139d9ce59eaf459a5c5916cc8f20b26aaf6c7c029379aedb05a07fe585ccac60307c1f58ca9f859157d06d06baa394aace79d51b8cb38cfa2598141e245624e5ab9b9d68731173348905315bf1a5ad61d1e8adaeb810e4e8a86d7c13537b0be860ab2ed35b73399b8808aa91d750f77943f8a8b7e89fdb50728aa3dbbd8a41a6e00756f438c9b9e9d55872df5a9068add8a972b7e43edad9ced2237ca1367be4b7cdb66a54ea12eef129471158610eaf28f99f7f686557dcdf644ea:9f80922bc8db32d0cc43f9936affebe7b2bc35a5d82277cd187b5d50dc7fc4c4832fffa34e9543806b485c04548e7c75429425e14d55d91fc1052efd8667430bb766273f060ef3b2ae3340454a391b426bc2e97264f8674553eb00dd6ecfdd59b611d8d662929fec710d0e462020e12cdbf9c1ec8858e85671acf8b7b14424ce92079d7d801e2ad9acac036bc8d2dfaa72aa839bff30c0aa7e414a882c00b645ff9d31bcf5a54382def4d0142efa4f06e823257ff132ee968cdc6738c53f53b84c8df76e9f78dd5056cf3d4d5a80a8f84e3edec48520f2cb4583e708539355ef7aa86fb5a0e87a94dcf14f30a2cca568f139d9ce59eaf459a5c5916cc8f20b26aaf6c7c029379aedb05a07fe585ccac60307c1f58ca9f859157d06d06baa394aace79d51b8cb38cfa2598141e245624e5ab9b9d68731173348905315bf1a5ad61d1e8adaeb810e4e8a86d7c13537b0be860ab2ed35b73399b8808aa91d750f77943f8a8b7e89fdb50728aa3dbbd8a41a6e00756f438c9b9e9d55872df5a9068add8a972b7e43edad9ced2237ca1367be4b7cdb66a54ea12eef129471158610eaf28f99f7f686557dcdf644ea: +722a2da50e42c11a61c9afac7be1a2fed2267d650f8f7d8e5bc706b807c1b91dfd0b964562f823721e649c3fedb432a76f91e0aead7c61d35f95ed7726d78589:fd0b964562f823721e649c3fedb432a76f91e0aead7c61d35f95ed7726d78589:173e8bb885e1f9081404acac999041d2ecfcb73f945e0db36e631d7cd1ab999eb717f34bf07874bf3d34e2530eb6085f4a9f88ae1b0f7d80f221456a8e9a8890b91a50192deaaacc0a1a615a87841e2c5a9e057957af6e48e78cc86198e32e7aa24dcf6cffa329bc72606d65b11682c8ba736cce22a05785df1146331e41609cf9ca711cf464958297138b58a9073f3bbf06ad8a85d135de66652104d88b49d27ad41e59bcc44c7fab68f53f0502e293ffcabaaf755927dfdffbfde3b35c080b5de4c8b785f4da64ef357bc0d1466a6a96560c3c4f3e3c0b563a003f5f95f237171bce1a001771a04ede7cdd9b8ca770fd36ef90e9fe0000a8d7685fd153cc7282de95920a8f8f0898d00bf0c6c933fe5bb9653ff146c4e2acd1a2e0c23c1244844dacf8652716302c2032f9c114679ed26b3ee3ab4a7b18bc4e3071f0977db57cd0ac68c0727a09b4f125fb64af2850b26c8a484263334e2da902d744737044e79ab1cf5b2f93a022b63d40cd:c2695a57172aaa31bd0890f231ca8eeec0287a87172669a899ad0891cea4c47579b50420e791cdec8c182c8a0e8dde21b2480b0cfd8111e28e5603347a352d04173e8bb885e1f9081404acac999041d2ecfcb73f945e0db36e631d7cd1ab999eb717f34bf07874bf3d34e2530eb6085f4a9f88ae1b0f7d80f221456a8e9a8890b91a50192deaaacc0a1a615a87841e2c5a9e057957af6e48e78cc86198e32e7aa24dcf6cffa329bc72606d65b11682c8ba736cce22a05785df1146331e41609cf9ca711cf464958297138b58a9073f3bbf06ad8a85d135de66652104d88b49d27ad41e59bcc44c7fab68f53f0502e293ffcabaaf755927dfdffbfde3b35c080b5de4c8b785f4da64ef357bc0d1466a6a96560c3c4f3e3c0b563a003f5f95f237171bce1a001771a04ede7cdd9b8ca770fd36ef90e9fe0000a8d7685fd153cc7282de95920a8f8f0898d00bf0c6c933fe5bb9653ff146c4e2acd1a2e0c23c1244844dacf8652716302c2032f9c114679ed26b3ee3ab4a7b18bc4e3071f0977db57cd0ac68c0727a09b4f125fb64af2850b26c8a484263334e2da902d744737044e79ab1cf5b2f93a022b63d40cd: +5fe9c3960ed5bd374cc94d42357e6a24dc7e3060788f726365defacf13cd12da0ce7b155c8b20ebdaacdc2aa23627e34b1f9ace980650a2530c7607d04814eb4:0ce7b155c8b20ebdaacdc2aa23627e34b1f9ace980650a2530c7607d04814eb4:c9490d83d9c3a9370f06c91af001685a02fe49b5ca667733fff189eee853ec1667a6c1b6c787e9244812d2d532866ab74dfc870d6f14033b6bcd39852a3900f8f08cd95a74cb8cbe02b8b8b51e993a06adfebd7fc9854ae5d29f4df9642871d0c5e470d903cfbcbd5adb3275628f28a80bf8c0f0376687dae673bf7a8547e80d4a9855ae2572fc2b205dc8a198016ddc9b50995f5b39f368f540504a551803d6dd5f874828e5541ded052894d9e2dc5e6aa351087e790c0dd5d9c4decb217e4db81c98a184b264e6daeac0f11e074cae2bfc899f54b419c65dcc22664a915fbfffac35cee0f286eb7b144933db933e16c4bcb650d537722489de236373fd8d65fc86118b6def37ca4608bc6ce927b65436ffda7f02bfbf88b045ae7d2c2b45a0b30c8f2a04df953221088c555fe9a5df260982a3d64df194ee952fa9a98c31b96493db6180d13d67c36716f95f8c0bd7a039ad990667ca34a83ac1a18c37dd7c7736aa6b9b6fc2b1ac0ce119ef77:379f9c54c413af0d192e9bc736b29da9d521e7ba7841d309f9bcc1e742ec4308fe9f7ba51e0b22aed487cb4aa3913b9bebfb3aacd38f4039f9bbbebe1ad80002c9490d83d9c3a9370f06c91af001685a02fe49b5ca667733fff189eee853ec1667a6c1b6c787e9244812d2d532866ab74dfc870d6f14033b6bcd39852a3900f8f08cd95a74cb8cbe02b8b8b51e993a06adfebd7fc9854ae5d29f4df9642871d0c5e470d903cfbcbd5adb3275628f28a80bf8c0f0376687dae673bf7a8547e80d4a9855ae2572fc2b205dc8a198016ddc9b50995f5b39f368f540504a551803d6dd5f874828e5541ded052894d9e2dc5e6aa351087e790c0dd5d9c4decb217e4db81c98a184b264e6daeac0f11e074cae2bfc899f54b419c65dcc22664a915fbfffac35cee0f286eb7b144933db933e16c4bcb650d537722489de236373fd8d65fc86118b6def37ca4608bc6ce927b65436ffda7f02bfbf88b045ae7d2c2b45a0b30c8f2a04df953221088c555fe9a5df260982a3d64df194ee952fa9a98c31b96493db6180d13d67c36716f95f8c0bd7a039ad990667ca34a83ac1a18c37dd7c7736aa6b9b6fc2b1ac0ce119ef77: +ec2fa541ac14b414149c3825eaa7001b795aa1957d4040dda92573904afa7ee471b363b2408404d7beecdef1e1f511bb6084658b532f7ea63d4e3f5f01c61d31:71b363b2408404d7beecdef1e1f511bb6084658b532f7ea63d4e3f5f01c61d31:2749fc7c4a729e0e0ad71b5b74eb9f9c534ebd02ffc9df4374d813bdd1ae4eb87f1350d5fdc563934515771763e6c33b50e64e0cd114573031d2186b6eca4fc802cddc7cc51d92a61345a17f6ac38cc74d84707a5156be9202dee3444652e79bae7f0d31bd17567961f65dd01a8e4bee38331938ce4b2b550691b99a4bc3c072d186df4b3344a5c8fbfbb9fd2f355f6107e410c3d0c798b68d3fb9c6f7ab5fe27e70871e86767698fe35b77ead4e435a9402cc9ed6a2657b059be0a21003c048bbf5e0ebd93cbb2e71e923cf5c728d1758cd817ad74b454a887126d653b95a7f25e5293b768c9fc5a9c35a2372e3741bc90fd66301427b10824bb4b1e9110bfba84c21a40eb8fed4497e91dc3ffd0438c514c0a8cb4cac6ad0256bf11d5aa7a9c7c00b669b015b0bf81425a21413e2ffb6edc0bd78e385c44fd74558e511c2c25fee1fec18d3990b8690300fa711e93d9854668f0187065e76e7113ae763c30ddd86720b5546a6c3c6f1c43bc67b14:84d18d56f964e3776759bba92c510c2b6d574555c3cddade212da90374554991e7d77e278d63e34693e1958078cc3685f8c41c1f5342e351899638ef612114012749fc7c4a729e0e0ad71b5b74eb9f9c534ebd02ffc9df4374d813bdd1ae4eb87f1350d5fdc563934515771763e6c33b50e64e0cd114573031d2186b6eca4fc802cddc7cc51d92a61345a17f6ac38cc74d84707a5156be9202dee3444652e79bae7f0d31bd17567961f65dd01a8e4bee38331938ce4b2b550691b99a4bc3c072d186df4b3344a5c8fbfbb9fd2f355f6107e410c3d0c798b68d3fb9c6f7ab5fe27e70871e86767698fe35b77ead4e435a9402cc9ed6a2657b059be0a21003c048bbf5e0ebd93cbb2e71e923cf5c728d1758cd817ad74b454a887126d653b95a7f25e5293b768c9fc5a9c35a2372e3741bc90fd66301427b10824bb4b1e9110bfba84c21a40eb8fed4497e91dc3ffd0438c514c0a8cb4cac6ad0256bf11d5aa7a9c7c00b669b015b0bf81425a21413e2ffb6edc0bd78e385c44fd74558e511c2c25fee1fec18d3990b8690300fa711e93d9854668f0187065e76e7113ae763c30ddd86720b5546a6c3c6f1c43bc67b14: +6132692a5ef27bf476b1e991e6c431a8c764f1aebd470282db3321bb7cb09c207a2d166184f9e5f73bea454486b041ceb5fc2314a7bd59cb718e79f0ec989d84:7a2d166184f9e5f73bea454486b041ceb5fc2314a7bd59cb718e79f0ec989d84:a9c0861665d8c2de06f9301da70afb27b3024b744c6b38b24259294c97b1d1cb4f0dcf7575a8ed454e2f0980f50313a77363415183fe9677a9eb1e06cb6d34a467cb7b0758d6f55c564b5ba15603e202b18856d89e72a23ab07d8853ff77da7aff1caebd7959f2c710ef31f5078a9f2cdae92641a1cc5f74d0c143ec42afbaa5f378a9e10d5bf74587fa5f49c156233247dafd3929acde888dc684337e40cdc5932e7eb73ffcc90b85c0ad460416691aefbd7efd07b657c350946a0e366b37a6c8089aba5c5fe3bbca064afbe9d47fbc83914af1cb43c2b2efa98e0a43be32ba823202001def36817251b65f9b0506cef6683642a46ed612f8ca81ee97bb04d317b517343ade2b77126d1f02a87b7604c8653b6748cf5488fa6d43df809faa19e69292d38c5d397dd8e20c7af7c5334ec977f5010a0f7cb5b89479ca06db4d12627f067d6c42186a6b1f8742f36ae709ba720e3cd898116666d81b190b9b9d2a72202cb690a03f3310429a71dc048cde:eb677f3347e1a1ea929efdf62bf9105a6c8f4993033b4f6d03cb0dbf9c742b270704e383ab7c0676bdb1ad0ce9b16673083c9602ec10ae1dd98e8748b336440ba9c0861665d8c2de06f9301da70afb27b3024b744c6b38b24259294c97b1d1cb4f0dcf7575a8ed454e2f0980f50313a77363415183fe9677a9eb1e06cb6d34a467cb7b0758d6f55c564b5ba15603e202b18856d89e72a23ab07d8853ff77da7aff1caebd7959f2c710ef31f5078a9f2cdae92641a1cc5f74d0c143ec42afbaa5f378a9e10d5bf74587fa5f49c156233247dafd3929acde888dc684337e40cdc5932e7eb73ffcc90b85c0ad460416691aefbd7efd07b657c350946a0e366b37a6c8089aba5c5fe3bbca064afbe9d47fbc83914af1cb43c2b2efa98e0a43be32ba823202001def36817251b65f9b0506cef6683642a46ed612f8ca81ee97bb04d317b517343ade2b77126d1f02a87b7604c8653b6748cf5488fa6d43df809faa19e69292d38c5d397dd8e20c7af7c5334ec977f5010a0f7cb5b89479ca06db4d12627f067d6c42186a6b1f8742f36ae709ba720e3cd898116666d81b190b9b9d2a72202cb690a03f3310429a71dc048cde: +f219b2101164aa9723bde3a7346f68a35061c01f9782072580ba32df903ba891f66b920d5aa1a6085495a1480539beba01ffe60e6a6388d1b2e8eda23355810e:f66b920d5aa1a6085495a1480539beba01ffe60e6a6388d1b2e8eda23355810e:015577d3e4a0ec1ab25930106343ff35ab4f1e0a8a2d844aadbb70e5fc5348ccb679c2295c51d702aaae7f6273ce70297b26cb7a253a3db94332e86a15b4a64491232791f7a8b082ee2834af30400e804647a532e9c454d2a0a7320130ab6d4d860073a34667ac25b7e5e2747ba9f5c94594fb68377ae260369c40713b4e32f23195bf91d3d7f1a2719bf408aad8d8a347b112e84b118817cb06513344021763035272a7db728a0ccdaa949c61715d0764140b3e8c01d20ff1593c7f2d55c4e82a1c0cb1ea58442bf80a741bca91f58ab0581b498ee9fe3c92ca654148ef75313543d1aff382befe1a93b02190ce0102175158e2071d02bacad8dbe9fb940fcb610c105ad52c80feb1ec4e524f4c0ec7983e9ce696fa4fcf4bf0514b8f0432b17d5448fc426fea2b01ac7b26c2aed769927534da22576fc1bba726e9d65be01b59f60a648ace2fc3e5e275789fa637cbbd84be3d6ac24457a6292cd656c7b569a52ffea7916b8d04b4f4a75be7ac95142f:17f0127ca3bafa5f4ee959cd60f772be87a0034961517e39a0a1d0f4b9e26db1336e60c82b352c4cbacdbbd11771c3774f8cc5a1a795d6e4f4ebd51def36770b015577d3e4a0ec1ab25930106343ff35ab4f1e0a8a2d844aadbb70e5fc5348ccb679c2295c51d702aaae7f6273ce70297b26cb7a253a3db94332e86a15b4a64491232791f7a8b082ee2834af30400e804647a532e9c454d2a0a7320130ab6d4d860073a34667ac25b7e5e2747ba9f5c94594fb68377ae260369c40713b4e32f23195bf91d3d7f1a2719bf408aad8d8a347b112e84b118817cb06513344021763035272a7db728a0ccdaa949c61715d0764140b3e8c01d20ff1593c7f2d55c4e82a1c0cb1ea58442bf80a741bca91f58ab0581b498ee9fe3c92ca654148ef75313543d1aff382befe1a93b02190ce0102175158e2071d02bacad8dbe9fb940fcb610c105ad52c80feb1ec4e524f4c0ec7983e9ce696fa4fcf4bf0514b8f0432b17d5448fc426fea2b01ac7b26c2aed769927534da22576fc1bba726e9d65be01b59f60a648ace2fc3e5e275789fa637cbbd84be3d6ac24457a6292cd656c7b569a52ffea7916b8d04b4f4a75be7ac95142f: +fc180035aec0f5ede7bda93bf77ade7a81ed06de07ee2e3aa8576be81608610a4f215e948cae243ee3143b80282ad792c780d2a6b75060ca1d290ca1a8e3151f:4f215e948cae243ee3143b80282ad792c780d2a6b75060ca1d290ca1a8e3151f:b5e8b01625664b222339e0f05f93a990ba48b56ae65439a17520932df011721e284dbe36f98631c066510098a68d7b692a3863e99d58db76ca5667c8043cb10bd7abbaf506529fbb23a5166be038affdb9a234c4f4fcf43bddd6b8d2ce772dd653ed115c095e232b269dd4888d2368cb1c66be29dd383fca67f66765b296564e37555f0c0e484504c591f006ea8533a12583ad2e48318ff6f324ecaf804b1bae04aa896743e67ef61ca383d58e42acfc6410de30776e3ba262373b9e1441943955101a4e768231ad9c6529eff6118dde5df02f94b8d6df2d99f27863b517243a579e7aaff311ea3a0282e47ca876fabc2280fce7adc984dd0b30885b1650f1471dfcb0522d49fec7d042f32a93bc368f076006ea01ec1c7412bf66f62dc88de2c0b74701a5614e855e9fa728fb1f1171385f96afbde70dea02e9aa94dc21848c26302b50ae91f9693a1864e4e095ae03cdc22ad28a0eb7db596779246712fab5f5da327efec3e79612de0a6ccaa536759b8e:a43a71c3a19c35660dae6f31a254b8c0ea3593fc8fca74d13640012b9e9473d4afe070db01e7fb399bf4ca6070e062180011285a67dd6858b761e46c6bd32004b5e8b01625664b222339e0f05f93a990ba48b56ae65439a17520932df011721e284dbe36f98631c066510098a68d7b692a3863e99d58db76ca5667c8043cb10bd7abbaf506529fbb23a5166be038affdb9a234c4f4fcf43bddd6b8d2ce772dd653ed115c095e232b269dd4888d2368cb1c66be29dd383fca67f66765b296564e37555f0c0e484504c591f006ea8533a12583ad2e48318ff6f324ecaf804b1bae04aa896743e67ef61ca383d58e42acfc6410de30776e3ba262373b9e1441943955101a4e768231ad9c6529eff6118dde5df02f94b8d6df2d99f27863b517243a579e7aaff311ea3a0282e47ca876fabc2280fce7adc984dd0b30885b1650f1471dfcb0522d49fec7d042f32a93bc368f076006ea01ec1c7412bf66f62dc88de2c0b74701a5614e855e9fa728fb1f1171385f96afbde70dea02e9aa94dc21848c26302b50ae91f9693a1864e4e095ae03cdc22ad28a0eb7db596779246712fab5f5da327efec3e79612de0a6ccaa536759b8e: +a2836a65427912122d25dcdfc99d7046fe9b53d5c1bb23617f11890e94ca93ed8c12bda214c8abb2286acffbf8112425040aab9f4d8bb7870b98da0159e882f1:8c12bda214c8abb2286acffbf8112425040aab9f4d8bb7870b98da0159e882f1:813d6061c56eae0ff53041c0244aa5e29e13ec0f3fb428d4beb8a99e04bca8c41bddb0db945f487efe38f2fc14a628fafa2462f860e4e34250eb4e93f139ab1b74a2614519e41ee2403be427930ab8bc82ec89ceafb60905bd4ddbbd13bdb19654314fc92373140b962e2258e038d71b9ec66b84ef8319e03551cb707e747f6c40ad476fbefdce71f3a7b67a1af1869bc6440686e7e0855e4f369d1d88b8099fba54714678627bba1aff41e7707bc97eddf890b0c08dce3e9800d24c6f61092ce28d481b5dea5c096c55d72f8946009131fb968e2bc8a054d825adab76740dcf0d758c8bf54ff38659e71b32bfe2e615aaabb0f5293085649cf60b9847bc62011ce3878af628984a5840a4ad5dae3702db367da0f8a165fed0517eb5c442b0145330241b97eeca733ba6688b9c129a61cd1236aff0e27bcf98c28b0fbeea55a3d7c7193d644b2749f986bd46af8938e8faaeafbd9cec3612ab005bd7c3eeafe9a31279ca6102560666ba16136ff1452f850adb:e6a9a6b436559a4320c45c0c2c4a2aedecb90d416d52c82680ac7330d062aebef3e9ac9f2c5ffa455c9be113013a2b282e5600fd306435ada83b1e48ba2a3605813d6061c56eae0ff53041c0244aa5e29e13ec0f3fb428d4beb8a99e04bca8c41bddb0db945f487efe38f2fc14a628fafa2462f860e4e34250eb4e93f139ab1b74a2614519e41ee2403be427930ab8bc82ec89ceafb60905bd4ddbbd13bdb19654314fc92373140b962e2258e038d71b9ec66b84ef8319e03551cb707e747f6c40ad476fbefdce71f3a7b67a1af1869bc6440686e7e0855e4f369d1d88b8099fba54714678627bba1aff41e7707bc97eddf890b0c08dce3e9800d24c6f61092ce28d481b5dea5c096c55d72f8946009131fb968e2bc8a054d825adab76740dcf0d758c8bf54ff38659e71b32bfe2e615aaabb0f5293085649cf60b9847bc62011ce3878af628984a5840a4ad5dae3702db367da0f8a165fed0517eb5c442b0145330241b97eeca733ba6688b9c129a61cd1236aff0e27bcf98c28b0fbeea55a3d7c7193d644b2749f986bd46af8938e8faaeafbd9cec3612ab005bd7c3eeafe9a31279ca6102560666ba16136ff1452f850adb: +f051af426d0c3282fafc8bf912ade1c24211a95ad200e1eef549320e1cb1a252fa87955e0ea13dde49d83dc22e63a2bdf1076725c2cc7f93c76511f28e7944f2:fa87955e0ea13dde49d83dc22e63a2bdf1076725c2cc7f93c76511f28e7944f2:b48d9f84762b3bcc66e96d76a616fa8fe8e01695251f47cfc1b7b17d60dc9f90d576ef64ee7d388504e2c9079638165a889696471c989a876f8f13b63b58d531fea4dd1229fc631668a047bfae2da281feae1b6de3ebe280abe0a82ee00fbfdc22ce2d10e06a0492ff1404dfc094c40b203bf55721dd787ed4e91d5517aaf58d3bdd35d44a65ae6ba75619b339b650518cefcc17493de27a3b5d41788f87edbde72610f181bf06e208e0eb7cdfe881d91a2d6cc77aa19c0fcf330fedb44675d800eb8cff9505d8887544a503cbe373c4847b19e8f3995726efd6649858595c57ccaf0cbc9eb25de83ba046bc9f1838ac7b8953dd81b81ac0f68d0e9338cb55402552afb6bc16949351b926d151a82efc695e8d7da0dd55099366789718ccbf36030bd2c3c109399be26cdb8b9e2a155f3b2cb1bfa71ab69a23625a4ac118fe91cb2c19788cf52a71d730d576b421d96982a51a2991daec440cda7e6cc3282b8312714278b819bfe2387eb96aa91d40173034f428:b8f713578a64466719aceb432fce302a87cf066bf3e102a350616921a840964bfc7e685d8fd17455ac3eb4861edcb8979d35e3a4bd82a078cd707721d733400eb48d9f84762b3bcc66e96d76a616fa8fe8e01695251f47cfc1b7b17d60dc9f90d576ef64ee7d388504e2c9079638165a889696471c989a876f8f13b63b58d531fea4dd1229fc631668a047bfae2da281feae1b6de3ebe280abe0a82ee00fbfdc22ce2d10e06a0492ff1404dfc094c40b203bf55721dd787ed4e91d5517aaf58d3bdd35d44a65ae6ba75619b339b650518cefcc17493de27a3b5d41788f87edbde72610f181bf06e208e0eb7cdfe881d91a2d6cc77aa19c0fcf330fedb44675d800eb8cff9505d8887544a503cbe373c4847b19e8f3995726efd6649858595c57ccaf0cbc9eb25de83ba046bc9f1838ac7b8953dd81b81ac0f68d0e9338cb55402552afb6bc16949351b926d151a82efc695e8d7da0dd55099366789718ccbf36030bd2c3c109399be26cdb8b9e2a155f3b2cb1bfa71ab69a23625a4ac118fe91cb2c19788cf52a71d730d576b421d96982a51a2991daec440cda7e6cc3282b8312714278b819bfe2387eb96aa91d40173034f428: +a103e92672c65f81ea5da1fff1a4038788479e941d503a756f4a755201a57c1dee63a5b69641217acbaf3339da829ec071b9931e5987153514d30140837a7af4:ee63a5b69641217acbaf3339da829ec071b9931e5987153514d30140837a7af4:b1984e9eec085d524c1eb3b95c89c84ae085be5dc65c326e19025e1210a1d50edbbba5d1370cf15d68d687eb113233e0fba50f9433c7d358773950c67931db8296bbcbecec888e87e71a2f7579fad2fa162b85fb97473c456b9a5ce2956676969c7bf4c45679085b62f2c224fc7f458794273f6d12c5f3e0d06951824d1cca3e2f904559ed28e2868b366d79d94dc98667b9b5924268f3e39b1291e5abe4a758f77019dacbb22bd8196e0a83a5677658836e96ca5635055a1e63d65d036a68d87ac2fd283fdda390319909c5cc7680368848873d597f298e0c6172308030ffd452bb1363617b316ed7cd949a165dc8abb53f991aef3f3e9502c5dfe4756b7c6bfdfe89f5e00febdd6afb0402818f11cf8d1d5864fe9da1b86e39aa935831506cf2400ea7ed75bd9533b23e202fe875d7d9638c89d11cb2d6e6021ae6bd27c7754810d35cd3a61494f27b16fc794e2cd2f0d3453ada933865db78c579571f8fc5c5c6be8eaffce6a852e5b3b1c524c49313d427abcb:2aa2035c2ce5b5e6ae161e168f3ad0d6592bcf2c4a049d3ed342fceb56be9c7cb372027573ae0178e8878ebefca7b030327b8aad41857de58cb78e1a00cbac05b1984e9eec085d524c1eb3b95c89c84ae085be5dc65c326e19025e1210a1d50edbbba5d1370cf15d68d687eb113233e0fba50f9433c7d358773950c67931db8296bbcbecec888e87e71a2f7579fad2fa162b85fb97473c456b9a5ce2956676969c7bf4c45679085b62f2c224fc7f458794273f6d12c5f3e0d06951824d1cca3e2f904559ed28e2868b366d79d94dc98667b9b5924268f3e39b1291e5abe4a758f77019dacbb22bd8196e0a83a5677658836e96ca5635055a1e63d65d036a68d87ac2fd283fdda390319909c5cc7680368848873d597f298e0c6172308030ffd452bb1363617b316ed7cd949a165dc8abb53f991aef3f3e9502c5dfe4756b7c6bfdfe89f5e00febdd6afb0402818f11cf8d1d5864fe9da1b86e39aa935831506cf2400ea7ed75bd9533b23e202fe875d7d9638c89d11cb2d6e6021ae6bd27c7754810d35cd3a61494f27b16fc794e2cd2f0d3453ada933865db78c579571f8fc5c5c6be8eaffce6a852e5b3b1c524c49313d427abcb: +d47c1b4b9e50cbb71fd07d096d91d87213d44b024373044761c4822f9d9df880f4e1cb86c8ca2cfee43e58594a8778436d3ea519704e00c1bbe48bbb1c9454f8:f4e1cb86c8ca2cfee43e58594a8778436d3ea519704e00c1bbe48bbb1c9454f8:88d7009d51de3d337eef0f215ea66ab830ec5a9e6823761c3b92ad93ea341db92ece67f4ef4ceb84194ae6926c3d014b2d59781f02e0b32f9a611222cb9a5850c6957cb8079ae64e0832a1f05e5d1a3c572f9d08f1437f76bb3b83b52967c3d48c3576848891c9658d4959eb80656d26cdba0810037c8a18318ff122f8aa8985c773cb317efa2f557f1c3896bcb162df5d87681bb787e7813aa2dea3b0c564d646a92861f444ca1407efbac3d12432cbb70a1d0eaffb11741d3718fedee2b83036189a6fc45a52f74fa487c18fd264a7945f6c9e44b011f5d86613f1939b19f4f4fdf53234057be3f005ad64eebf3c8ffb58cb40956c4336df01d4424b706a0e561d601708d12485e21bcb6d799d8d1d044b400064ec0944501406e70253947006cabbdb2dd6bd8cee4497653d9113a44d4de9b68d4c526fca0b9b0c18fe50fb917fdd9a914fb816108a73a6b3fff9e654e69c9cfe02b05c6c1b9d15c4e65cf31018b8100d784633ee1888eee3572aafa6f189ea22d0:627e7ca7e34ed6331d62b9541c1ea9a9292be7b0a65d805e266b5122272a82db7d765acc7e2a290d685804922f91ed04a3c382c03ff21a1768f584413c4e5f0088d7009d51de3d337eef0f215ea66ab830ec5a9e6823761c3b92ad93ea341db92ece67f4ef4ceb84194ae6926c3d014b2d59781f02e0b32f9a611222cb9a5850c6957cb8079ae64e0832a1f05e5d1a3c572f9d08f1437f76bb3b83b52967c3d48c3576848891c9658d4959eb80656d26cdba0810037c8a18318ff122f8aa8985c773cb317efa2f557f1c3896bcb162df5d87681bb787e7813aa2dea3b0c564d646a92861f444ca1407efbac3d12432cbb70a1d0eaffb11741d3718fedee2b83036189a6fc45a52f74fa487c18fd264a7945f6c9e44b011f5d86613f1939b19f4f4fdf53234057be3f005ad64eebf3c8ffb58cb40956c4336df01d4424b706a0e561d601708d12485e21bcb6d799d8d1d044b400064ec0944501406e70253947006cabbdb2dd6bd8cee4497653d9113a44d4de9b68d4c526fca0b9b0c18fe50fb917fdd9a914fb816108a73a6b3fff9e654e69c9cfe02b05c6c1b9d15c4e65cf31018b8100d784633ee1888eee3572aafa6f189ea22d0: +fc0c32c5eb6c71ea08dc2b300cbcef18fdde3ea20f68f21733237b4ddaab900e47c37d8a080857eb8777a6c0a9a5c927303faf5c320953b5de48e462e12d0062:47c37d8a080857eb8777a6c0a9a5c927303faf5c320953b5de48e462e12d0062:a7b1e2db6bdd96b3d51475603537a76b42b04d7ebd24fe515a887658e4a352e22109335639a59e2534811f4753b70209d0e4698e9d926088826c14689681ea00fa3a2fcaa0047ced3ef287e6172502b215e56497614d86b4cb26bcd77a2e172509360ee58893d01c0d0fb4d4abfe4dbd8d2a2f54190fa2f731c1ceac6829c3ddc9bfb2ffd70c57ba0c2b22d2326fbfe7390db8809f73547ff47b86c36f2bf7454e678c4f1c0fa870bd0e30bbf3278ec8d0c5e9b64aff0af64babc19b70f4cf9a41cb8f95d3cde24f456ba3571c8f021d38e591dec05cb5d1ca7b48f9da4bd734b069a9fd106500c1f408ab7fe8e4a6e6f3ed64da0ed24b01e33df8475f95fa9ed71d04dd30b3cd823755a3401bf5afae10ee7e18ec6fe637c3793fd434b48d7145130447e00299101052558b506554ec9c399f62941c3f414cbc352caa345b930adecfaddac91ee53d1451a65e06201026325de07c931f69bba868a7c87ee23c604ec6794332917dfe2c5b69669b659706917f71eddf96:6887c6e2b98a82af5ee3dfa7ca2cb25d9c10745620a82956acba85cb57c8ec24279fa42f092359a1b6bbeafba050f14b6288209e6ef7bc1e0a2b872c1138f305a7b1e2db6bdd96b3d51475603537a76b42b04d7ebd24fe515a887658e4a352e22109335639a59e2534811f4753b70209d0e4698e9d926088826c14689681ea00fa3a2fcaa0047ced3ef287e6172502b215e56497614d86b4cb26bcd77a2e172509360ee58893d01c0d0fb4d4abfe4dbd8d2a2f54190fa2f731c1ceac6829c3ddc9bfb2ffd70c57ba0c2b22d2326fbfe7390db8809f73547ff47b86c36f2bf7454e678c4f1c0fa870bd0e30bbf3278ec8d0c5e9b64aff0af64babc19b70f4cf9a41cb8f95d3cde24f456ba3571c8f021d38e591dec05cb5d1ca7b48f9da4bd734b069a9fd106500c1f408ab7fe8e4a6e6f3ed64da0ed24b01e33df8475f95fa9ed71d04dd30b3cd823755a3401bf5afae10ee7e18ec6fe637c3793fd434b48d7145130447e00299101052558b506554ec9c399f62941c3f414cbc352caa345b930adecfaddac91ee53d1451a65e06201026325de07c931f69bba868a7c87ee23c604ec6794332917dfe2c5b69669b659706917f71eddf96: +a8d73d639a23cc6a967ef31bcabb5d063e53e1eab8fcc7cab9bc3a17fde9c2f88daa9f4c8b1a44691bf44521f2f7ca45dc7fc61f6a4ce6f98faa41c2a74977d1:8daa9f4c8b1a44691bf44521f2f7ca45dc7fc61f6a4ce6f98faa41c2a74977d1:fd1fac3d53313b11acd29f5a83ac11896dab2530fa47865b2295c0d99dd67c36ed8e5fa549150c794c5549efb5c1d69114d5d607b23285b7212afaab57846a54ae67b9e880e07b6586607cecf6d4eed516a3a75511fe367d88eb871e6d71b7d6aa1367a01421b1088fc2d75e44954b73625c52da8a3a183c60be9da6050f59a453caa53520593671728d431877bfaac913a765fb6a56b75290b2a8aaac34afb9217ba1b0d5850ba0fdabf80969def0feee794ceb60614e3368e63ef20e4c32d341ec9b0328ea9fe139207ed7a626ff08943b415233db7cfcc845c9b63121d4ed52ec3748ab6a1f36b2103c7dc7e9303acea4ba8af7a3e07184fb491e891ede84f0dc41cadc3973028e879acd2031afc29a16092868e2c7f539fc1b792edab195a25ab9830661346b39ef53915de4af52c421eaf172e9da76a08c283a52df907f705d7e8599c5baae0c2af380c1bb46f93484a03f28374324b278992b50b7afa02552cafa503f034f8d866e9b720271dd68ccb685a85fffd1:c4dcef1a2453939b364b340250c3129431431d5ba3f47670ab07ce680c69bf28b678627c76a6360fc40dc109aa7dea371b825e46134f624572182acf3957e70ffd1fac3d53313b11acd29f5a83ac11896dab2530fa47865b2295c0d99dd67c36ed8e5fa549150c794c5549efb5c1d69114d5d607b23285b7212afaab57846a54ae67b9e880e07b6586607cecf6d4eed516a3a75511fe367d88eb871e6d71b7d6aa1367a01421b1088fc2d75e44954b73625c52da8a3a183c60be9da6050f59a453caa53520593671728d431877bfaac913a765fb6a56b75290b2a8aaac34afb9217ba1b0d5850ba0fdabf80969def0feee794ceb60614e3368e63ef20e4c32d341ec9b0328ea9fe139207ed7a626ff08943b415233db7cfcc845c9b63121d4ed52ec3748ab6a1f36b2103c7dc7e9303acea4ba8af7a3e07184fb491e891ede84f0dc41cadc3973028e879acd2031afc29a16092868e2c7f539fc1b792edab195a25ab9830661346b39ef53915de4af52c421eaf172e9da76a08c283a52df907f705d7e8599c5baae0c2af380c1bb46f93484a03f28374324b278992b50b7afa02552cafa503f034f8d866e9b720271dd68ccb685a85fffd1: +79c7dcb7d59a8df6b2b2ba0413059d89680995c20e916da01b8f067dc60cdeb4298743c73918bd556b28f8d4824a09b814752a7aeae7ee04875c53f4d6b108d9:298743c73918bd556b28f8d4824a09b814752a7aeae7ee04875c53f4d6b108d9:5fe202f5b33b7788810d2508a13b3114d69b8596e6eacda05a04a2eb597fa3279c208b5a5b65daacb699f144e1d660e78e139b578331abec5c3c35334454f03e832c8d6e2984df5d450ecb5d33582a78808a9c78f26ebcd1244ef52e3fa6dca115c1f0cb56e38eae0e5b39f5fd863dffd0b2fb5b958f2d739db312fc667a17b031c4c9f8c5a2ad577984cc4146c437580efd2152173fe0d5782cc2ae9831a8d9a04177256018ff7631e0b0d8a99cb28f008b320421e27a74c31359188663456d85e098c1ebd281701097b6ae5a871e5ccc02058a501416cb91c12cef5be6f1914370e563f1a1b2aa41f4b8ee84cd32a1d509e529787d14a445438d807ecd620e2fa26de0da6426864784d4a28f54103e609283b99ee9b2b699c980bbb7882c3ea68ddc90802ac232f2c8e84291987bf3c5240921b59cfa214969317673d0be7f34b1ca0e15ea73c7175401ce550be106b49e62f8db68695e740e0f3a3556a19f3c8e6b91ac1cc23e863fcd0f0d9eb7047aa631e0d2eb9bcc6b:7b7cbe44c771e4371bae13b0722babcc1064155732962f407cba2acd35381d42210bece822f4681121fd4dab745a1f3077922fba1a78045b712902baccac660e5fe202f5b33b7788810d2508a13b3114d69b8596e6eacda05a04a2eb597fa3279c208b5a5b65daacb699f144e1d660e78e139b578331abec5c3c35334454f03e832c8d6e2984df5d450ecb5d33582a78808a9c78f26ebcd1244ef52e3fa6dca115c1f0cb56e38eae0e5b39f5fd863dffd0b2fb5b958f2d739db312fc667a17b031c4c9f8c5a2ad577984cc4146c437580efd2152173fe0d5782cc2ae9831a8d9a04177256018ff7631e0b0d8a99cb28f008b320421e27a74c31359188663456d85e098c1ebd281701097b6ae5a871e5ccc02058a501416cb91c12cef5be6f1914370e563f1a1b2aa41f4b8ee84cd32a1d509e529787d14a445438d807ecd620e2fa26de0da6426864784d4a28f54103e609283b99ee9b2b699c980bbb7882c3ea68ddc90802ac232f2c8e84291987bf3c5240921b59cfa214969317673d0be7f34b1ca0e15ea73c7175401ce550be106b49e62f8db68695e740e0f3a3556a19f3c8e6b91ac1cc23e863fcd0f0d9eb7047aa631e0d2eb9bcc6b: +b9ced0412593fefed95e94ac965e5b23ff9d4b0e797db02bf497994d3b793e60c1629a723189959337f5535201e5d395ba0a03ea8c17660d0f8b6f6e6404bb12:c1629a723189959337f5535201e5d395ba0a03ea8c17660d0f8b6f6e6404bb12:555bb39c1899d57cabe428064c2d925f5fc4cf7059b95fb89a8e9e3a7e426c6c922d9e4d76984ea2383cabb4f2befd89c1f20eaa8a00dbe787cfa70ae2ae6aa90331cbbe580fa5a02184ed05e6c8e89d576af28aeeaf7c4e2500f358a00971a0a75920e854849bf332142975404f598c32e96982043d992bcd1a4fe819bb5634ad03467afc4ce05073f88ba1ba4ae8653a04665cf3f71690fe13343885bc5ebc0e5e62d882f43b7c68900ac9438bf4a81ce90169ec129ee63e2c675a1a5a67e27cc798c48cc23f51078f463b3b7cc14e3bcfd2e9b82c75240934cbdc50c4308f282f193122995606f40135100a291c55afdf8934eb8b61d81421674124dec3b88f9a73110a9e616f5b826b9d343f3ac0e9d7bdf4fd8b648b40f0098b3897a3a1cd65a64570059b8bc5c6743883074c88623c1f5a88c58969e21c692aca236833d3470b3eb09815e1138e9d0650c390eee977422193b00918be8a97cc6199b451b05b5730d1d13358cf74610678f7ac7f7895cc2efc456e03873b:f1b797ded8a6942b12626848340fb719fcddafd98f33e2992d357bfdd35933c7ac561e5b2f939464338c5666854ca885c4d046eb2c54e48a1b5ed266ad34de05555bb39c1899d57cabe428064c2d925f5fc4cf7059b95fb89a8e9e3a7e426c6c922d9e4d76984ea2383cabb4f2befd89c1f20eaa8a00dbe787cfa70ae2ae6aa90331cbbe580fa5a02184ed05e6c8e89d576af28aeeaf7c4e2500f358a00971a0a75920e854849bf332142975404f598c32e96982043d992bcd1a4fe819bb5634ad03467afc4ce05073f88ba1ba4ae8653a04665cf3f71690fe13343885bc5ebc0e5e62d882f43b7c68900ac9438bf4a81ce90169ec129ee63e2c675a1a5a67e27cc798c48cc23f51078f463b3b7cc14e3bcfd2e9b82c75240934cbdc50c4308f282f193122995606f40135100a291c55afdf8934eb8b61d81421674124dec3b88f9a73110a9e616f5b826b9d343f3ac0e9d7bdf4fd8b648b40f0098b3897a3a1cd65a64570059b8bc5c6743883074c88623c1f5a88c58969e21c692aca236833d3470b3eb09815e1138e9d0650c390eee977422193b00918be8a97cc6199b451b05b5730d1d13358cf74610678f7ac7f7895cc2efc456e03873b: +81da168f02d46bb87cda845da43f8a6cba2c016878d6f49c6f061a60f155a04aaff86e98093ca4c71b1b804c5fe451cfdf868250dea30345fa4b89bb09b6a53b:aff86e98093ca4c71b1b804c5fe451cfdf868250dea30345fa4b89bb09b6a53b:6bc6726a34a64aae76ab08c92b179e54ff5d2e65eb2c6c659ae8703cc245cbc2cf45a12b22c468ae61fd9a6627ad0626c9b1e5af412cb483eaee1db11b29f0a510c13e38020e09ae0eee762537a3e9d1a0c7b033d097fdc1f4f82629a9de9ef38da1cf96a940357d5f2e0e7e8dbc29db728a1e6aad876e5e053113d06420272b87cf0c40dfe03a544de96c7aea13ba0029b57b48d99dcc6a650492d78c4cdd1b28e1a115a7e3e7a7cb21333d4ff80858dfb67782c16354b8716596560d7d8e389eb15a052a0bf5d16eb54fb3e4973ad4984e72a187f5347d5b262c32b1647e42b6a53837096cc78c2a05ce1c6e12493a03f1a667584cb97f4fcd57ee944c65b7eed25f7ae0f3f6cede173fdfacf5af1db143730d18096664914ba4cfc6966f392022781c66a9417ca2680b51f63e4fba424ecfdbc6a2f01787d0e7484f8a8ab390aeaa6d1f7ed325d82feaa1692a4984fae43da87329b045da8f0a4f56b695aa935de152ce0385153720979a2b7006d405fcb0fba09e23b85fd19b:4aaca947e3f22cc8b8588ee030ace8f6b5f5711c2974f20cc18c3b655b07a5bc1366b59a1708032d12cae01ab794f8cbcc1a330874a75035db1d69422d2fc00c6bc6726a34a64aae76ab08c92b179e54ff5d2e65eb2c6c659ae8703cc245cbc2cf45a12b22c468ae61fd9a6627ad0626c9b1e5af412cb483eaee1db11b29f0a510c13e38020e09ae0eee762537a3e9d1a0c7b033d097fdc1f4f82629a9de9ef38da1cf96a940357d5f2e0e7e8dbc29db728a1e6aad876e5e053113d06420272b87cf0c40dfe03a544de96c7aea13ba0029b57b48d99dcc6a650492d78c4cdd1b28e1a115a7e3e7a7cb21333d4ff80858dfb67782c16354b8716596560d7d8e389eb15a052a0bf5d16eb54fb3e4973ad4984e72a187f5347d5b262c32b1647e42b6a53837096cc78c2a05ce1c6e12493a03f1a667584cb97f4fcd57ee944c65b7eed25f7ae0f3f6cede173fdfacf5af1db143730d18096664914ba4cfc6966f392022781c66a9417ca2680b51f63e4fba424ecfdbc6a2f01787d0e7484f8a8ab390aeaa6d1f7ed325d82feaa1692a4984fae43da87329b045da8f0a4f56b695aa935de152ce0385153720979a2b7006d405fcb0fba09e23b85fd19b: +af2e60da0f29bb1614fc3f193cc353331986b73f3f9a0aec9421b9473d6a4b6ac8bfe2835822199c6127b806fabeef0cb9ff59f3c81ff0cb89c556f55106af6a:c8bfe2835822199c6127b806fabeef0cb9ff59f3c81ff0cb89c556f55106af6a:7dbb77b88bda94f344416a06b096566c6e8b393931a8243a6cab75c361fde7dc536aec40cded83296a89e8c3bef7d787cfc49401a7b9183f138d5000619ff073c05e2f841d6008358f10a2da7dcfac3d4d70c20d2ec34c7b6d5cd1a734d6bbb11c5fd8d2bce32ac810ef82b4188aa8ea3cfc3032233dc0e2600e9db6e18bc22b10044a31c15baceaf5554de89d2a3466807f244414d080ff2963956c6e83c8e144ed0066088b476ddcb564403447d9159f9089aba2b4d5575c4d8ae66fc8690e7349ed40832e6369c024563ec493bfcc0fc9ac787ac841397fe133167283d80c42f006a99d39e82979da3fa9334bd9ede0d14b41b7466bcebbe8171bc804a645d3723274a1b92bf82fd993358744de92441903d436fd47f23d40052a3829367f202f0553b5e49b76c5e03fa6ce7c3cf5eeb21de967bec4dd355925384ebf96697e823762bac4d43a767c241a4cef724a970d00ff3a8ab3b83eed840075c74e90f306e330013260962161e9d0910de183622ce9a6b8d5144280550fc7:50f9f941a8da9f6240f76d2fa3b06dd6b2292ed32d1c05218097d34d8a19dfe553f76ae3c6b4a2ed20852128461540decf418f52d38e64037eec7771bd1afe007dbb77b88bda94f344416a06b096566c6e8b393931a8243a6cab75c361fde7dc536aec40cded83296a89e8c3bef7d787cfc49401a7b9183f138d5000619ff073c05e2f841d6008358f10a2da7dcfac3d4d70c20d2ec34c7b6d5cd1a734d6bbb11c5fd8d2bce32ac810ef82b4188aa8ea3cfc3032233dc0e2600e9db6e18bc22b10044a31c15baceaf5554de89d2a3466807f244414d080ff2963956c6e83c8e144ed0066088b476ddcb564403447d9159f9089aba2b4d5575c4d8ae66fc8690e7349ed40832e6369c024563ec493bfcc0fc9ac787ac841397fe133167283d80c42f006a99d39e82979da3fa9334bd9ede0d14b41b7466bcebbe8171bc804a645d3723274a1b92bf82fd993358744de92441903d436fd47f23d40052a3829367f202f0553b5e49b76c5e03fa6ce7c3cf5eeb21de967bec4dd355925384ebf96697e823762bac4d43a767c241a4cef724a970d00ff3a8ab3b83eed840075c74e90f306e330013260962161e9d0910de183622ce9a6b8d5144280550fc7: +605f90b53d8e4a3b48b97d745439f2a0807d83b8502e8e2979f03e8d376ac9feaa3fae4cfa6f6bfd14ba0afa36dcb1a2656f36541ad6b3e67f1794b06360a62f:aa3fae4cfa6f6bfd14ba0afa36dcb1a2656f36541ad6b3e67f1794b06360a62f:3bcdcac292ac9519024aaecee2b3e999ff5d3445e9f1eb60940f06b91275b6c5db2722ed4d82fe89605226530f3e6b0737b308cde8956184944f388a80042f6cba274c0f7d1192a0a96b0da6e2d6a61b76518fbee555773a414590a928b4cd545fccf58172f35857120eb96e75c5c8ac9ae3add367d51d34ac403446360ec10f553ea9f14fb2b8b78cba18c3e506b2f04097063a43b2d36431cce02caf11c5a4db8c821752e52985d5af1bfbf4c61572e3fadae3ad424acd81662ea5837a1143b9669391d7b9cfe230cffb3a7bb03f6591c25a4f01c0d2d4aca3e74db1997d3739c851f0327db919ff6e77f6c8a20fdd3e1594e92d01901ab9aef194fc893e70d78c8ae0f480001a515d4f9923ae6278e8927237d05db23e984c92a683882f57b1f1882a74a193ab6912ff241b9ffa662a0d47f29205f084dbde845baaeb5dd36ae6439a437642fa763b57e8dbe84e55813f0151e97e5b9de768b234b8db15c496d4bfcfa1388788972bb50ce030bc6e0ccf4fa7d00d343782f6ba8de0:dd0212e63288cbe14a4569b4d891da3c7f92727c5e7f9a801cf9d6827085e7095b669d7d45f882ca5f0745dccd24d87a57181320191e5b7a47c3f7f2dccbd7073bcdcac292ac9519024aaecee2b3e999ff5d3445e9f1eb60940f06b91275b6c5db2722ed4d82fe89605226530f3e6b0737b308cde8956184944f388a80042f6cba274c0f7d1192a0a96b0da6e2d6a61b76518fbee555773a414590a928b4cd545fccf58172f35857120eb96e75c5c8ac9ae3add367d51d34ac403446360ec10f553ea9f14fb2b8b78cba18c3e506b2f04097063a43b2d36431cce02caf11c5a4db8c821752e52985d5af1bfbf4c61572e3fadae3ad424acd81662ea5837a1143b9669391d7b9cfe230cffb3a7bb03f6591c25a4f01c0d2d4aca3e74db1997d3739c851f0327db919ff6e77f6c8a20fdd3e1594e92d01901ab9aef194fc893e70d78c8ae0f480001a515d4f9923ae6278e8927237d05db23e984c92a683882f57b1f1882a74a193ab6912ff241b9ffa662a0d47f29205f084dbde845baaeb5dd36ae6439a437642fa763b57e8dbe84e55813f0151e97e5b9de768b234b8db15c496d4bfcfa1388788972bb50ce030bc6e0ccf4fa7d00d343782f6ba8de0: +9e2c3d189838f4dd52ef0832886874c5ca493983ddadc07cbc570af2ee9d6209f68d3b81e73557ee1f08bd2d3f46a4718256a0f3cd8d2e03eb8fe882aab65c69:f68d3b81e73557ee1f08bd2d3f46a4718256a0f3cd8d2e03eb8fe882aab65c69:19485f5238ba82eadf5eff14ca75cd42e5d56fea69d5718cfb5b1d40d760899b450e66884558f3f25b7c3de9afc4738d7ac09da5dd4689bbfac07836f5e0be432b1ddcf1b1a075bc9815d0debc865d90bd5a0c5f5604d9b46ace816c57694ecc3d40d8f84df0ede2bc4d577775a027f725de0816f563fa88f88e077720ebb6ac02574604819824db7474d4d0b22cd1bc05768e0fb867ca1c1a7b90b34ab7a41afc66957266ac0c915934aaf31c0cf6927a4f03f23285e6f24afd5813849bb08c203ac2d0336dcbf80d77f6cf7120edfbcdf181db107ec8e00f32449c1d3f5c049a92694b4ea2c6ebe5e2b0f64b5ae50ad3374d246b3270057e724a27cf263b633ab65ecb7f5c266b8007618b10ac9ac83db0febc04fd863d9661ab6e58494766f71b9a867c5a7a4555f667c1af2e54588f162a41ce756407cc4161d607b6e0682980934caa1bef036f7330d9eef01ecc553583fee5994e533a46ca916f60f8b961ae01d20f7abf0df6141b604de733c636b42018cd5f1d1ef4f84cee40fc:38a31b6b465084738262a26c065fe5d9e2886bf9dd35cde05df9bad0cc7db401c750aa19e66090bce25a3c721201e60502c8c10454346648af065eab0ee7d80f19485f5238ba82eadf5eff14ca75cd42e5d56fea69d5718cfb5b1d40d760899b450e66884558f3f25b7c3de9afc4738d7ac09da5dd4689bbfac07836f5e0be432b1ddcf1b1a075bc9815d0debc865d90bd5a0c5f5604d9b46ace816c57694ecc3d40d8f84df0ede2bc4d577775a027f725de0816f563fa88f88e077720ebb6ac02574604819824db7474d4d0b22cd1bc05768e0fb867ca1c1a7b90b34ab7a41afc66957266ac0c915934aaf31c0cf6927a4f03f23285e6f24afd5813849bb08c203ac2d0336dcbf80d77f6cf7120edfbcdf181db107ec8e00f32449c1d3f5c049a92694b4ea2c6ebe5e2b0f64b5ae50ad3374d246b3270057e724a27cf263b633ab65ecb7f5c266b8007618b10ac9ac83db0febc04fd863d9661ab6e58494766f71b9a867c5a7a4555f667c1af2e54588f162a41ce756407cc4161d607b6e0682980934caa1bef036f7330d9eef01ecc553583fee5994e533a46ca916f60f8b961ae01d20f7abf0df6141b604de733c636b42018cd5f1d1ef4f84cee40fc: +31010d1d67eb616348e84792b92d5dc128553cb52f6368159fe7b816cd0e7c37266543d96787ca901fcff06e6e434491ae0970880a5a187d535edb19db5cabeb:266543d96787ca901fcff06e6e434491ae0970880a5a187d535edb19db5cabeb:39f89a5e7aa530b5463d498f8035b9909d55da527cdbd4de6d228379f089e608a9207a2c5b9c42051a60c8ca3fb97a1c06cd747d9d0739970ceb88ce526f971140ea2ec21f090ba075bf8975faa508b1cc10efa494dc172e6d3d3f3f75dc8e0e96f05c0cccb2f96e911cfa7a2c82c9845018bb1f9d75f82e3dfe1139347b2ac058b014ac93760c90f5567ab5c4eba04b49fb09ddadd305be511dfe05c96ebc86fd67b5d0ab57d85f4fe5e2f0fa9d88a68f0f6b6bc8bb944eb3c0b17557e55d5ea187d922a42813e69057c9b6a7f75e49921b7079e58f8a63719ee3e1ad10cf0e8a70c4f1540218b70494bd029ee02ff9727a7d85d377919ec4051479b70f7cd6767723fe42c1c7899c2b7c1f702dd6b4d13b672d488f34a0e969db79cc2cb2524a948a8de4c5b623ecd90d6e82d97033c125637d1cd8c84803d8fbc012846ffe484f6c02149258f9462fa1e99c307dd0062fe0b6f11eee40c2629ef7c0f6a5107259ea5b9ffb6f29f12c32f7b5228cabc986ab66450af9dcc3da09d0e0b9a4:7b1eb677c3e5e6a8b4ba69fcb7f6b1870e42a8d58958a35c674e2db82107481c4c7b37f0f689d39d9f51e181b17b1108c15a3e27b29df3a4315dcc4faf12220539f89a5e7aa530b5463d498f8035b9909d55da527cdbd4de6d228379f089e608a9207a2c5b9c42051a60c8ca3fb97a1c06cd747d9d0739970ceb88ce526f971140ea2ec21f090ba075bf8975faa508b1cc10efa494dc172e6d3d3f3f75dc8e0e96f05c0cccb2f96e911cfa7a2c82c9845018bb1f9d75f82e3dfe1139347b2ac058b014ac93760c90f5567ab5c4eba04b49fb09ddadd305be511dfe05c96ebc86fd67b5d0ab57d85f4fe5e2f0fa9d88a68f0f6b6bc8bb944eb3c0b17557e55d5ea187d922a42813e69057c9b6a7f75e49921b7079e58f8a63719ee3e1ad10cf0e8a70c4f1540218b70494bd029ee02ff9727a7d85d377919ec4051479b70f7cd6767723fe42c1c7899c2b7c1f702dd6b4d13b672d488f34a0e969db79cc2cb2524a948a8de4c5b623ecd90d6e82d97033c125637d1cd8c84803d8fbc012846ffe484f6c02149258f9462fa1e99c307dd0062fe0b6f11eee40c2629ef7c0f6a5107259ea5b9ffb6f29f12c32f7b5228cabc986ab66450af9dcc3da09d0e0b9a4: +8ff2398cd51f51d4c2c57869a2218b8486822031f400729f4ac4d5909c48bafea5a88704b68677be3d16c3dc0052cfee6e2b30e08609059d4cba52c6d96061fb:a5a88704b68677be3d16c3dc0052cfee6e2b30e08609059d4cba52c6d96061fb:993953e47a341188bc592942e1557af29546e4e9368e2f1a5ee9806e2baf66b6190191fc5d2b7e47de37ff054fb2bbb1f031684ada5d607adda3d65433122fa904e0456faa84109bbc517f8ad39660876382adcfed0f7620cf1164622eacd91eb37a8596462ebe9ebe26bdc1e32cc34ad46fb1cea420e73c31215408e6d35425f44a829b132f631a3f6dd4b873a000667e19eb22fffd5903aaa7d4c8fdf21953c3c6178f5f8cb2aa6bff92894ead835888df060a3c9043026e0e2cef275497e7d105df3b644a98f26bf00105c99413ee0af8851954d65ceb8d79ad3071b8bb87f0b19743d2556ffd9819830b6eebf7ecc7e045661f43570ce9fdbbe2d252406fa90d04236f222c429ec16b1287224ada1a532161ae8b481bcab8d47afb3ed0445b3060fd6759179856f4085c1e585fd7c1409799af693cf427bd1d3dc10b5ae3447a8d2a18dc3a12a6860b22175dd5eb53a0950432e2d7aefece8af0ade3d8567743de43690f2d253723c5d7e48bd30d2937593701cecde9154b7665cb611d7d:417a647829c92898e520ff5311daa0a139cd8fffcb25a18e6d9b50cb52cbc35424c39ebbb5d5ac6a6d63f1f53c4df212f7025a8aaef8e36493c874c3ce341a0e993953e47a341188bc592942e1557af29546e4e9368e2f1a5ee9806e2baf66b6190191fc5d2b7e47de37ff054fb2bbb1f031684ada5d607adda3d65433122fa904e0456faa84109bbc517f8ad39660876382adcfed0f7620cf1164622eacd91eb37a8596462ebe9ebe26bdc1e32cc34ad46fb1cea420e73c31215408e6d35425f44a829b132f631a3f6dd4b873a000667e19eb22fffd5903aaa7d4c8fdf21953c3c6178f5f8cb2aa6bff92894ead835888df060a3c9043026e0e2cef275497e7d105df3b644a98f26bf00105c99413ee0af8851954d65ceb8d79ad3071b8bb87f0b19743d2556ffd9819830b6eebf7ecc7e045661f43570ce9fdbbe2d252406fa90d04236f222c429ec16b1287224ada1a532161ae8b481bcab8d47afb3ed0445b3060fd6759179856f4085c1e585fd7c1409799af693cf427bd1d3dc10b5ae3447a8d2a18dc3a12a6860b22175dd5eb53a0950432e2d7aefece8af0ade3d8567743de43690f2d253723c5d7e48bd30d2937593701cecde9154b7665cb611d7d: +ef816c8f5ec34ef41f68831d90cd29e52de8973782d003ee4edada2ada2691d647f9b363a88a45053a05bb72160852bfe8f7dfefc2f37283de346752caf092cc:47f9b363a88a45053a05bb72160852bfe8f7dfefc2f37283de346752caf092cc:9593c35cdec535bebb6965da68eab0b646bffcfbd04883bc4cef90d5d01f018c63c9b0ddfb3cef5e786284d5218caaaf060e9288952f16301ed8a4c1bcee256356a0c8bda359fbaa2782b10c86d18e20f7a0ec99b27a0b4dbefc0a262a3bf68fe81444dcae5f693eb0f16e6ee03f8fcbf3a3398146d20ec4d2657761fd0320fee7ea703c49a6a543bc9bba911e7925038710e8c36552d476d6027f58b2c52ba51ad65ea4f039c78f96b889102bb4bdd69b68e9c3d45b5176a2d82b0b95dc321016370dae30c3936515db0464c41774301c74e42d89b8bf4b9c19ed554b12febac0f60ddb3219ccc5603531dbf2eb5f293425d72ccefa0c7f144aba89347b296be87ff18994b4a0c70c930f059303b5dd4c8fe1e6bbc3cd68c6c0d84246dc6e6140a2abd1780b13f1594a6019d1778b7cbb3a3e3a34bfae7297f0b3edc376941c32352a4be314b84a9d8d6d7f1f38a0ad3798020aa2a331a402be9c704484744a730cbdedcb904b6fde708fbd14bfdc29efd461d1d0b5825de0bc79422b69a2722f:65c5d10ea7bfdbb38d55364a9968f82b548224dff3363b2ddcf585163dea27dc63b0563eb1a8dfbee951d3c9b33fcd6bbf0921c3abb21786b229069bd9ca000a9593c35cdec535bebb6965da68eab0b646bffcfbd04883bc4cef90d5d01f018c63c9b0ddfb3cef5e786284d5218caaaf060e9288952f16301ed8a4c1bcee256356a0c8bda359fbaa2782b10c86d18e20f7a0ec99b27a0b4dbefc0a262a3bf68fe81444dcae5f693eb0f16e6ee03f8fcbf3a3398146d20ec4d2657761fd0320fee7ea703c49a6a543bc9bba911e7925038710e8c36552d476d6027f58b2c52ba51ad65ea4f039c78f96b889102bb4bdd69b68e9c3d45b5176a2d82b0b95dc321016370dae30c3936515db0464c41774301c74e42d89b8bf4b9c19ed554b12febac0f60ddb3219ccc5603531dbf2eb5f293425d72ccefa0c7f144aba89347b296be87ff18994b4a0c70c930f059303b5dd4c8fe1e6bbc3cd68c6c0d84246dc6e6140a2abd1780b13f1594a6019d1778b7cbb3a3e3a34bfae7297f0b3edc376941c32352a4be314b84a9d8d6d7f1f38a0ad3798020aa2a331a402be9c704484744a730cbdedcb904b6fde708fbd14bfdc29efd461d1d0b5825de0bc79422b69a2722f: +45eb0c4dfafa2a7690ef579c095456ceedcd32f0b6144d0c380f87fb744a0b1ffc85632c98384b5f9682aed9cd664cf1f48e588be2d568e5c734494df4c712b8:fc85632c98384b5f9682aed9cd664cf1f48e588be2d568e5c734494df4c712b8:6f66d847405a03d7bd6f8d2897dbdf04e76d7df2d9470a4996b7dd6db88500f8f4f83e960e219a2486e24545add13614550414d827c41a9b08318daf01b15214c64a4266cbf8a5717ada3e62c26729073e16ddbd66f2d520e1e09935de05e4db11c396d477010aec66aafb762e69238d0b9e76b452454bf9e451e76ac79e6990d41b932bc32917093783c91bc9cf0bbe3b514070a1e692ff34fd06b66ea11f39e10af933ee96d8e9b677cb03737e7964eeaa725f121207f9c1b26a96c616df7cb7caef47bda901368ff2ea586e422e65bf21a691bdd2c13e67fff58cfbfed81782049dafa0f727df88623f2f7e8f262daf939542a187b8720a9b6b2b09890e54876b28a43874abbe3bfa981f8138b772c5d51736885f86acac2215a0b010dfc2c6b150845d4f8296252586a3e115f303c3d8a582e20fd2d43f6c446e5d00280ec179823b7fb4c1b0feb94eb4ef1707f5184e3b52461a7562d1f307cb751cdbbf6eae49ffae91862358e74e9548822b8a049fec6bf4c7a99cabbe09206577b657e31f:55851de8e1092f78944f6c6dd95bf07e2dbc8df7f57ad576829b978e3af58a7a8e94ed4dccbc0182467edf0bad4bae7ca84aa9a0c17c61a9e0ddff1d7525d7046f66d847405a03d7bd6f8d2897dbdf04e76d7df2d9470a4996b7dd6db88500f8f4f83e960e219a2486e24545add13614550414d827c41a9b08318daf01b15214c64a4266cbf8a5717ada3e62c26729073e16ddbd66f2d520e1e09935de05e4db11c396d477010aec66aafb762e69238d0b9e76b452454bf9e451e76ac79e6990d41b932bc32917093783c91bc9cf0bbe3b514070a1e692ff34fd06b66ea11f39e10af933ee96d8e9b677cb03737e7964eeaa725f121207f9c1b26a96c616df7cb7caef47bda901368ff2ea586e422e65bf21a691bdd2c13e67fff58cfbfed81782049dafa0f727df88623f2f7e8f262daf939542a187b8720a9b6b2b09890e54876b28a43874abbe3bfa981f8138b772c5d51736885f86acac2215a0b010dfc2c6b150845d4f8296252586a3e115f303c3d8a582e20fd2d43f6c446e5d00280ec179823b7fb4c1b0feb94eb4ef1707f5184e3b52461a7562d1f307cb751cdbbf6eae49ffae91862358e74e9548822b8a049fec6bf4c7a99cabbe09206577b657e31f: +709d2e199006f5369a7a0bdd34e74dc784be33880ea3c5dd10ed5c94451e797206f989202ba2cbc9c150be611262aca00c45f012f89fbaf89f8ceccba0b1934a:06f989202ba2cbc9c150be611262aca00c45f012f89fbaf89f8ceccba0b1934a:62f003140fa09e0387d187a0ff96c4563df9f4e28c2282c0183ac3eede1312354921f780fca5361d3068d29949630b7530cd5914ace0468d014b6f53d839b82e38817dbf2d8392c3ce3424eab86a24d804c7acb1ce7acfe0a1cda4393924283105da4a7741196e027550047f85b7a0a01d454124efc0e299f0ef9ad14350543053482261528baa56e65999ac802c00a336267c635106b26403c19f391d53bd82861d6d48a4380b3043aa91d649536881204eccb0de20d43e5a3755b7f600916eccae42a0c9053b462d9417a13d67d778264a896e8eaf90baf66d29e5438a716781123a89fa9b8beef91d965af2f4a1a5bd5d2e2aaf46d5c94b7709cdd38d05feee4bfb76a359077c16bc4be9116e69001271cda565bc19bf47d4f986bd9c0d184cd8a3520ca1bdb4b505aaf7cb4ec9f94789779d30714e79116dd5019d59b28b17dad96f4e2155ad9c61274addc6b638109504e9ed19f4eda5377762648c4098224e3391043e4c2ad591654c9e7f974efdf0b0504b6fa5f646cecf44cd372412372505:629bf97b0c78ee6a9c8759fbea28224e27abbb6cbe4dea5bb797e6e0fe80c913f953e3a9b623352d13acf4ce6250fb029a1e198d72bd5e7402e60e9e48ca350162f003140fa09e0387d187a0ff96c4563df9f4e28c2282c0183ac3eede1312354921f780fca5361d3068d29949630b7530cd5914ace0468d014b6f53d839b82e38817dbf2d8392c3ce3424eab86a24d804c7acb1ce7acfe0a1cda4393924283105da4a7741196e027550047f85b7a0a01d454124efc0e299f0ef9ad14350543053482261528baa56e65999ac802c00a336267c635106b26403c19f391d53bd82861d6d48a4380b3043aa91d649536881204eccb0de20d43e5a3755b7f600916eccae42a0c9053b462d9417a13d67d778264a896e8eaf90baf66d29e5438a716781123a89fa9b8beef91d965af2f4a1a5bd5d2e2aaf46d5c94b7709cdd38d05feee4bfb76a359077c16bc4be9116e69001271cda565bc19bf47d4f986bd9c0d184cd8a3520ca1bdb4b505aaf7cb4ec9f94789779d30714e79116dd5019d59b28b17dad96f4e2155ad9c61274addc6b638109504e9ed19f4eda5377762648c4098224e3391043e4c2ad591654c9e7f974efdf0b0504b6fa5f646cecf44cd372412372505: +5151617421aadc9c95a442b45e7ff6de06a2c733b85bd789fbad414ee3c91add14941d559761b30ab0a86d47e0f7d1896b33784527c80af41cb84810cbff9dbf:14941d559761b30ab0a86d47e0f7d1896b33784527c80af41cb84810cbff9dbf:216e9d40bcdc3b2650188d121c9f8ef29e914facd022fe01b90ed11225f2eb93538e5fcee5ab8045e9199aa76a16bdd0616805660e247fecd7e22821b69b1f8e8a58ac3fb85691d75d5957a1daf53ff9ee6476d7c4bc541e6ad38e3a34ea90fc52a48b9399f92d17c9bb0d7fc3104c55d0efb4ea5b831ff9490b3f79f4d9d699594b741566f2b50a8fc78cc403fa40f5abb6638a32f449a8b3ef029c402f46931ad2bd3e8e683108714c989ae21689e9c444b9f55b81119bb5035bcf73e97ce43a2218c7bc3e430d1e814f34dee057265d3194b9f43875d8381f525f78576e64ce692584faa30fb743a12d1b77614d2e10a6b856b52be27cdb630ba1f0d3a6f8ea9844542e584ea0a2777527d0c52aca949aacda45ad83d16d5c83d663adb79cad6f3e39e990fe282a14c353aa2379d7f06adab74cea021b8983a57f1d0cf703292eb05ece89c53f3a1265610e0c1ea8ddd444d1ffd6bc3d03f0a6e4d0df5c5b8dc1f95d9f5558b118afe6bea0f6c2931363f03ab34e757d49364174f658efbbf38dc177:fae4773b334460c77bf01ec6366c4fe61c0cab57d8a4b03909c619e11ee3461c13fa21576f63870e423dd04181e4a7013a7524f246fe33853c674162a7815104216e9d40bcdc3b2650188d121c9f8ef29e914facd022fe01b90ed11225f2eb93538e5fcee5ab8045e9199aa76a16bdd0616805660e247fecd7e22821b69b1f8e8a58ac3fb85691d75d5957a1daf53ff9ee6476d7c4bc541e6ad38e3a34ea90fc52a48b9399f92d17c9bb0d7fc3104c55d0efb4ea5b831ff9490b3f79f4d9d699594b741566f2b50a8fc78cc403fa40f5abb6638a32f449a8b3ef029c402f46931ad2bd3e8e683108714c989ae21689e9c444b9f55b81119bb5035bcf73e97ce43a2218c7bc3e430d1e814f34dee057265d3194b9f43875d8381f525f78576e64ce692584faa30fb743a12d1b77614d2e10a6b856b52be27cdb630ba1f0d3a6f8ea9844542e584ea0a2777527d0c52aca949aacda45ad83d16d5c83d663adb79cad6f3e39e990fe282a14c353aa2379d7f06adab74cea021b8983a57f1d0cf703292eb05ece89c53f3a1265610e0c1ea8ddd444d1ffd6bc3d03f0a6e4d0df5c5b8dc1f95d9f5558b118afe6bea0f6c2931363f03ab34e757d49364174f658efbbf38dc177: +38bed445556de74482bf5fec0506f9af330b151e50d4774dfe8591d7b7e0276b4c0f9c49a42f4047bfe6885551c5e4b856cf771a67af3f89dbf602f9db9220f3:4c0f9c49a42f4047bfe6885551c5e4b856cf771a67af3f89dbf602f9db9220f3:0ff0031df0beeff3710c6b763f9b8ec81719bfa1528ce46519adf3d3412d93fb188fd497d5d17091c0f0345960dd0eb0c09fc4005173665d4d97f95c13828bc76b3492b87a4b64253c8b5fa47aa75fa3b86d5abeea8de5959a602289136f60a69b309e773b2255cde19ed2a2e199c33db11c16ade08a319750b851d92c692924fc9859be523431cbe78ec092db1129210ebbeaa7c2a2c000eeb105ca0301a48f3e45fdfb15b275cbab83ca5c99d737a585320e9e3b317179bd86467fa9694fcdb2ac6ad36ed7144843dbc34e423d35afd7d8972a1c43c199a191abd6ceba4936d395c995a3eb13cb057f88a9dc9490fe98845ee5d26a89fb642a2a516dc3056c54d3637213363a8628a42a395d942b954a89e8ef7a744d8ae5adac88c616efaa90e2077205a60baffede5c87bb14dead306229495f698f3e490616966b1636387d0d86183f945b24a9dcfccf4d36722cd12ebb6bd8e78325752afa2b1abd13c4bdbcadd170869136826242acfb721de5ff27ba8aa0c018b225ed3404803ce9fa2d508d8944:f702d0d463282fc7fd5f8f9029b89c626cafd83450c3bb9dd8f6589f0c4b4b71f649ea212e5e33487c59c168ea3ad83150f1fcdfe8c53eba65adc2023c25830f0ff0031df0beeff3710c6b763f9b8ec81719bfa1528ce46519adf3d3412d93fb188fd497d5d17091c0f0345960dd0eb0c09fc4005173665d4d97f95c13828bc76b3492b87a4b64253c8b5fa47aa75fa3b86d5abeea8de5959a602289136f60a69b309e773b2255cde19ed2a2e199c33db11c16ade08a319750b851d92c692924fc9859be523431cbe78ec092db1129210ebbeaa7c2a2c000eeb105ca0301a48f3e45fdfb15b275cbab83ca5c99d737a585320e9e3b317179bd86467fa9694fcdb2ac6ad36ed7144843dbc34e423d35afd7d8972a1c43c199a191abd6ceba4936d395c995a3eb13cb057f88a9dc9490fe98845ee5d26a89fb642a2a516dc3056c54d3637213363a8628a42a395d942b954a89e8ef7a744d8ae5adac88c616efaa90e2077205a60baffede5c87bb14dead306229495f698f3e490616966b1636387d0d86183f945b24a9dcfccf4d36722cd12ebb6bd8e78325752afa2b1abd13c4bdbcadd170869136826242acfb721de5ff27ba8aa0c018b225ed3404803ce9fa2d508d8944: +055460b32dd04d7f4b2311a89807e073fd556565a4771857d882794130a2fe5d260f8fed4bba30b9e12ad8523fbb6f57f0a7a882550061f1da46fbd8ea442221:260f8fed4bba30b9e12ad8523fbb6f57f0a7a882550061f1da46fbd8ea442221:7407f96ee3e79c69d36ce1f64e4f188655ea68b947e7e2be97b05ebc6d4439e950276ef3f0e6a03dd48b24f66929b49c1580eb468807e1e7a25eb9b94da340c53f984f8b81603efb61047bf3f14b686d9798003d2f68589a79ebfad54409c71c90ff67c11fbd76cc72c2d145f458e42f88b75d250eadcafe66bf37ffc837b62ff006685b7f85a9d875fc078c82e61fe35d1922527a551dab62f9e477499146bad912203e664c417c3679c02d872abac0032f8cc77f77bfe54d3326fdee9276a48ea4eb251350406882d08c830e7649fe6854558a7513ab2d8d2ac3e5ced8a808d2aee454779edabd1aa63bb19f718f470bdc8451cd9b294941e3497063b1e39b6ca184562fe838cbfeee922de24ddfcf9882c5e615b11bf904817fbd647139db80b4e8feb37f11e1852d7e876db9cb63c94d7ee34192f7200b5bc77a0311ae43b806ebd4c2896c53f58f7ebc1625cb20d7107ef9db0da28788523de991ef6c5866b18d8de83a954d3281e06dbf27c4f2382e08cd0e0f6ebae3f961b77fce5a95a9b0621b756f:23f4f1627fbabd7891d7d8489631c7231d22de71864e262ab4da84ea8a13a60feac4dcfb1812f1200444b775f121d7266d755ce9b6a9ad796559c0a26b516d027407f96ee3e79c69d36ce1f64e4f188655ea68b947e7e2be97b05ebc6d4439e950276ef3f0e6a03dd48b24f66929b49c1580eb468807e1e7a25eb9b94da340c53f984f8b81603efb61047bf3f14b686d9798003d2f68589a79ebfad54409c71c90ff67c11fbd76cc72c2d145f458e42f88b75d250eadcafe66bf37ffc837b62ff006685b7f85a9d875fc078c82e61fe35d1922527a551dab62f9e477499146bad912203e664c417c3679c02d872abac0032f8cc77f77bfe54d3326fdee9276a48ea4eb251350406882d08c830e7649fe6854558a7513ab2d8d2ac3e5ced8a808d2aee454779edabd1aa63bb19f718f470bdc8451cd9b294941e3497063b1e39b6ca184562fe838cbfeee922de24ddfcf9882c5e615b11bf904817fbd647139db80b4e8feb37f11e1852d7e876db9cb63c94d7ee34192f7200b5bc77a0311ae43b806ebd4c2896c53f58f7ebc1625cb20d7107ef9db0da28788523de991ef6c5866b18d8de83a954d3281e06dbf27c4f2382e08cd0e0f6ebae3f961b77fce5a95a9b0621b756f: +e9f6d31b936942c526e0f9ec4f5a7ac25fa789e0c434bcd9199d720c743c84c432126d26e28231c5b585b13f43a01c6fe542946b07d3a91e57d281523f5cb45c:32126d26e28231c5b585b13f43a01c6fe542946b07d3a91e57d281523f5cb45c:e88133f3d17642d5c22779a85316ba0df34c792b4efee49ed7dd93ca3322ef47c72e5b2e4595c77800434b60719adf54e4c1a34c89fa1e27ee8d35a0921f9755ac4a77a6c1684ea0f5c8ee5f759ce59bfe8315800a67aa6c64ddfaac92eabe6c2c613779784b3affafcc620f2a6dc5cb8d8dc7d74aa4d79494678494e5e6394c433c14809ff40c9a592d0d694a81103b44531e1f48bc13965d15af8bf3340488f8cd58f09ae1a6616bf85ac9de7e0c6696aa2f1bec15e17a44da4a84edb4ec6d77247788ba0de3ae12a155cbedc0da2f568eef0b75a877ea5b0c2c0d4bf2c61d468a46faadfaece35fc263a9be9987f4f7f78f05c707784378c7b8f7daf9ac3a122aad39a1677966da9ef286c9e062c4f439ad0bddea26e54b2f7388e238b2a64928450d34564c5a447e7afbbedd1085f1f24c11ae084322d1a32cf8aa473941f00d56b1618213cab3900aa606463d9f800e926f9f42d4b082d8c5ec3a4a025b45f9aadc8bcbd17091b3da49e9453dc55e89b5b5fe6b31f5eddad10b6601572568d8e205d3251a:7e3b1c4c716c808e90b974458915f3b2239c42077119fe270788fae520578bd7da6488044132e1bef23e3b23c34d9c1862744f28fcaecda6cac0fd72b93b6a0fe88133f3d17642d5c22779a85316ba0df34c792b4efee49ed7dd93ca3322ef47c72e5b2e4595c77800434b60719adf54e4c1a34c89fa1e27ee8d35a0921f9755ac4a77a6c1684ea0f5c8ee5f759ce59bfe8315800a67aa6c64ddfaac92eabe6c2c613779784b3affafcc620f2a6dc5cb8d8dc7d74aa4d79494678494e5e6394c433c14809ff40c9a592d0d694a81103b44531e1f48bc13965d15af8bf3340488f8cd58f09ae1a6616bf85ac9de7e0c6696aa2f1bec15e17a44da4a84edb4ec6d77247788ba0de3ae12a155cbedc0da2f568eef0b75a877ea5b0c2c0d4bf2c61d468a46faadfaece35fc263a9be9987f4f7f78f05c707784378c7b8f7daf9ac3a122aad39a1677966da9ef286c9e062c4f439ad0bddea26e54b2f7388e238b2a64928450d34564c5a447e7afbbedd1085f1f24c11ae084322d1a32cf8aa473941f00d56b1618213cab3900aa606463d9f800e926f9f42d4b082d8c5ec3a4a025b45f9aadc8bcbd17091b3da49e9453dc55e89b5b5fe6b31f5eddad10b6601572568d8e205d3251a: +6bf4caaabb96854a38a572f4ce6c7838f7e750118c73f2723582618e2307f83808126373d056f00e54b8d43d77c35f5f919833e90d8aafd6c8246d27917ad091:08126373d056f00e54b8d43d77c35f5f919833e90d8aafd6c8246d27917ad091:4776e9d60085481fa537bf295bdabd8b1cf632a8cd40bce6bd325c129f977000e88468ebf2dc158ac0f207212db00fb60b8ec8bae229372e9a6b01530a7ed1bc9d389ec8913f59030d5b54af56ae1ccc28f37cc96a8e53204e92a677766adfaada99b0281f867f61ac9ff7d972ee3ed427d72faae75d4aec01b5ffc37061b6f0f7e5714c4cf30d5b731b0746065f19e4c8922dde642f80fe24a3c8dcb2e5f1c266e2af6c37decf55a2baa54f0d5cf0839370c3e0b4e77a4f36bbb3162014933a4a4ebcae8c60961ac6dcf134f30828d31402ae74e7e8513c9d2ad8ee46b7a9d53a1f87ebfce04f461bded1749b6fc4c4f25793525692d7a0e426c84e06082cc3e6abb51368370cbb106c7a0897f66d92c9739cff9f2706d6a2980ecea3ac4945f0f47e656bd9637777e853d2a839104327dc049ebc34f049d6c2f80eca99db7b418424acef752260d2d427949323997cd9617edf50d441d0088b1d47912e35cf542315265829f383f45860d3b45e735bb2f8586dcf58db4f2acfb4a68853a96eed7b89769d365613:d2113f80d6cf928486a250a679d6e74b35ea9d26061fa94d769e1a8fbfa0a734227f55537e4ebff59336db141cf5d6d482a0711f1e9fc72ff70956a11b4fb9094776e9d60085481fa537bf295bdabd8b1cf632a8cd40bce6bd325c129f977000e88468ebf2dc158ac0f207212db00fb60b8ec8bae229372e9a6b01530a7ed1bc9d389ec8913f59030d5b54af56ae1ccc28f37cc96a8e53204e92a677766adfaada99b0281f867f61ac9ff7d972ee3ed427d72faae75d4aec01b5ffc37061b6f0f7e5714c4cf30d5b731b0746065f19e4c8922dde642f80fe24a3c8dcb2e5f1c266e2af6c37decf55a2baa54f0d5cf0839370c3e0b4e77a4f36bbb3162014933a4a4ebcae8c60961ac6dcf134f30828d31402ae74e7e8513c9d2ad8ee46b7a9d53a1f87ebfce04f461bded1749b6fc4c4f25793525692d7a0e426c84e06082cc3e6abb51368370cbb106c7a0897f66d92c9739cff9f2706d6a2980ecea3ac4945f0f47e656bd9637777e853d2a839104327dc049ebc34f049d6c2f80eca99db7b418424acef752260d2d427949323997cd9617edf50d441d0088b1d47912e35cf542315265829f383f45860d3b45e735bb2f8586dcf58db4f2acfb4a68853a96eed7b89769d365613: +5d9585736ab209b0abe8bf74aca4eea4f6d1650b532550a223e044580f8e20dee77729edfd2144b2b12078765417fa21f1594f09b269e9b6706802b4f3bdfe85:e77729edfd2144b2b12078765417fa21f1594f09b269e9b6706802b4f3bdfe85:08693591e6c58a5ead9c85fe8ec58508f81a3467636c2d34fcc1f466e5c6dafdc37c35cbee35589c6997e2b15448132744e5a1e131bb49bf5c2563f87ead3efe01e88cbf24cc1769c78cdfc167e378215b15859c7a28ece70e188fa330267d3fc57b4ace6c1520ec67875067fd33be86f4a1967afb3eb164c797cf28d8072aa69d82afa38374f8e5797c4c28471b7d69f5b9c7b4acdbc19f3c5c5d400808a982a47837aed1b3841d69890eeb31494e10e3e513d12d0ca686c7ce651778092703fef0dcc0214077dfb361251bdea4364dd41b97bceb0fb1475a50e4708f47f7878c74401e9771cc3fceace89169981aa77250850090d181d8358ebba65e290acb0352bece8c579832a601551816d1c05621ccbbee0fbe39ea2f195393199e69c234c2fb1c37e474840860ce609161fcfce2869574be0d38f95e20f4f8725247b9627b46e834905101ac12b934cbf87cb2d190d2f51490a82c4e810eddb81f956a9f36bda497bca506a49ee9cd47fda5b7f2b884a3648cadd12ab61898ada46ecc970f81dc9f876845db:e7b08e1d5809fdd8529443d65ada5dd655ea55b5415a011393be7071676486d358e8d2a460ebe075b0e701b24c9e3ab5f2b033592d4de3b7f37fd541f692090908693591e6c58a5ead9c85fe8ec58508f81a3467636c2d34fcc1f466e5c6dafdc37c35cbee35589c6997e2b15448132744e5a1e131bb49bf5c2563f87ead3efe01e88cbf24cc1769c78cdfc167e378215b15859c7a28ece70e188fa330267d3fc57b4ace6c1520ec67875067fd33be86f4a1967afb3eb164c797cf28d8072aa69d82afa38374f8e5797c4c28471b7d69f5b9c7b4acdbc19f3c5c5d400808a982a47837aed1b3841d69890eeb31494e10e3e513d12d0ca686c7ce651778092703fef0dcc0214077dfb361251bdea4364dd41b97bceb0fb1475a50e4708f47f7878c74401e9771cc3fceace89169981aa77250850090d181d8358ebba65e290acb0352bece8c579832a601551816d1c05621ccbbee0fbe39ea2f195393199e69c234c2fb1c37e474840860ce609161fcfce2869574be0d38f95e20f4f8725247b9627b46e834905101ac12b934cbf87cb2d190d2f51490a82c4e810eddb81f956a9f36bda497bca506a49ee9cd47fda5b7f2b884a3648cadd12ab61898ada46ecc970f81dc9f876845db: +60b142f165114143ca30a604fef51c686436aa1b9afdb266b3e398ccb3c4d855eaf6c5a76ca99bf7306498888c3b7a1feae98bf8988d7f2e1547f8f53a4528aa:eaf6c5a76ca99bf7306498888c3b7a1feae98bf8988d7f2e1547f8f53a4528aa:1815dee1173b78264720d35b7cc2454a000a65fff214e2473e20bc83f3ecde9c04c1e0696ce6e55519dd2a75ce0464bf601adc381e793ecb9f8ce7ab87b6ca2a3e410f639069451978d14873d3390fab8623969713c3dfcd58d86d124073761ee09a652a48767f9646cb726ac454ac9a1bc5faed3026b703982bc2b1e0758210e1d62519230eb2b2f4a486bc55168560c4363df5ff5adfda11ac7ef51b18196c94337c07aef117990f770c0f1e8c0f88eb6ffc40e8ed7c3a80a632db1e7f63b63096e2ac49e57792b31143e2f4faabceae66b27471681c36fc1139007f9b548cdc6e3b8fbbdaba7a8adb843431238bb461ba24f6e09f62c72d6377b4048cb0134c25a5411a20bfcfc13e48d80e36bfb0da7e0185d33f1928636e15dee0e5df8992a16572b13ea8f7cf85cae32d529f66e8f6d2fb2ad0bbfe7199169b2567ba00c781b20a48e1d70df9fa3119cd7e5bbe58884b0b51218940fa815f85625fa203471cee8084780eb0b9356f9f3d4f6df740301d707ef1ffb3519e3f90b8064b98e70f375d071426881718:a621f084ea1a36ef812a9755c9afbb53dadaae6b3a53fa8344ca40d3612a268a35fed0fd398ab75bcd639c547937c94155ab1a7a3467dd4bfddfacab1655e9081815dee1173b78264720d35b7cc2454a000a65fff214e2473e20bc83f3ecde9c04c1e0696ce6e55519dd2a75ce0464bf601adc381e793ecb9f8ce7ab87b6ca2a3e410f639069451978d14873d3390fab8623969713c3dfcd58d86d124073761ee09a652a48767f9646cb726ac454ac9a1bc5faed3026b703982bc2b1e0758210e1d62519230eb2b2f4a486bc55168560c4363df5ff5adfda11ac7ef51b18196c94337c07aef117990f770c0f1e8c0f88eb6ffc40e8ed7c3a80a632db1e7f63b63096e2ac49e57792b31143e2f4faabceae66b27471681c36fc1139007f9b548cdc6e3b8fbbdaba7a8adb843431238bb461ba24f6e09f62c72d6377b4048cb0134c25a5411a20bfcfc13e48d80e36bfb0da7e0185d33f1928636e15dee0e5df8992a16572b13ea8f7cf85cae32d529f66e8f6d2fb2ad0bbfe7199169b2567ba00c781b20a48e1d70df9fa3119cd7e5bbe58884b0b51218940fa815f85625fa203471cee8084780eb0b9356f9f3d4f6df740301d707ef1ffb3519e3f90b8064b98e70f375d071426881718: +734ba47033c6140232dd4a7a14f1a7743eefe9070bad9662491630cc9d28c1f32fa5df3026d60742e2aff6b57842c7126846c8a7bbe9266efa7b3f2398c357ea:2fa5df3026d60742e2aff6b57842c7126846c8a7bbe9266efa7b3f2398c357ea:5d3c659810c3fea52a6df3861e5cdc5b703cc1cef48558c61d8c51d0edea5a1479cfe5063d82ded9ca681e5748887c40ecfb9e1a9a8b7f8509d10776461c3923399693a78189089178d5aabd15f8c846642be47d6d4caf13824edcefb809868fa72ddf035c4de8ef0a9c832264f66f012761ce6955bc3c416e93e29188025ebbb13a553258c1d7c499c9a4aeb10bb36f61d1bb4cec5ae55d175722b9a9696df881951e35200b9653cf6ed4b3d15de087a9d1c319fce8582156bebf3fc91e0e610ff7a15308fd1d2c6069fbbb2947d3110731d245ae2963014bd76dea42db125cecc493c8e9091a76646577729aed4966fce9699fe12e367d665df9e95a9193e1133e143af92f82b66ac7764e5033178690521809a7107d8ae9b88e0ed1f35b1719901b930ad0e1cbce7fb30267b1155204f605f525e49de2988ea7f74be8815177fd976a1bcc126d9c9c135c5b4276d38019c34aefb7a0220f7f5aeff380aed627b070c2c9e21533bb35c08e394c85ae25e6862942599c65dbae5977a584a88180e0c8c71e5a8409e04ef7:9bd074d1d0bd28001baf7d2d4e82435df08c4264d8cbb1c381183c2f01223f79f94923ca178cac75564e16c7f56079088f7ed885de4d509fbc78f438fba3f6075d3c659810c3fea52a6df3861e5cdc5b703cc1cef48558c61d8c51d0edea5a1479cfe5063d82ded9ca681e5748887c40ecfb9e1a9a8b7f8509d10776461c3923399693a78189089178d5aabd15f8c846642be47d6d4caf13824edcefb809868fa72ddf035c4de8ef0a9c832264f66f012761ce6955bc3c416e93e29188025ebbb13a553258c1d7c499c9a4aeb10bb36f61d1bb4cec5ae55d175722b9a9696df881951e35200b9653cf6ed4b3d15de087a9d1c319fce8582156bebf3fc91e0e610ff7a15308fd1d2c6069fbbb2947d3110731d245ae2963014bd76dea42db125cecc493c8e9091a76646577729aed4966fce9699fe12e367d665df9e95a9193e1133e143af92f82b66ac7764e5033178690521809a7107d8ae9b88e0ed1f35b1719901b930ad0e1cbce7fb30267b1155204f605f525e49de2988ea7f74be8815177fd976a1bcc126d9c9c135c5b4276d38019c34aefb7a0220f7f5aeff380aed627b070c2c9e21533bb35c08e394c85ae25e6862942599c65dbae5977a584a88180e0c8c71e5a8409e04ef7: +45e34d0ef4c196fa6d572b6b1774b5218f7c3291304c13500df7070d90e8039e13a7304dff423359177abafa5e6508d26769ca99cf8af45c383f3ff634406003:13a7304dff423359177abafa5e6508d26769ca99cf8af45c383f3ff634406003:3d9ed5c64b75e135df2f5e85300d90f21b363935e2817556fc9311751ba7535477dec8356ec385efb82b414062f35bb6d3edeafde305f9900a25e9813c9ee0237d46409650cdcdb5dfa2301a8e2647f8d3819d86f7b7e3070d33440f82c4054b1ab5edebeb27f95b3c4c6fdd468f21600f03b3494da200bab9293c38d02fc44048e52ff5fd0f7217a04d4ce912a180d1628f368280b6892672e8ff98d4629ac28b60c02a301e6c6026c1b9e9ef21cf0392df225008d5a0e0284b282631ad1710f811615697066c98296519948a7cfed5aeeb454ee7a61cc271bd3d499be17df09d3a0e790ee6b9bd99e1b919bed4a063b8d1a34f1afd2e952b9dfefd770969c8b2fc37977abb0fee6317253a23ecc97578168973334c8f91763ab97f29c49baeee7b35f3ae7f5cd3a4a6e697ef255a3c2ec0c752a3396f69f663ca1fc2b332dfe6c0faf78afe9c68d99571e8e896c5093085e9863a27648a9e58f3a9a84cbbfe2b41ca3633dd5cf6e82cb77cecacad8d78b353f48db42d99c36bcad170ea9e98abb2788c33a3c706268f3631:b42c1f925f4baccd129efb109db354aca31c6898f4f451294749a26a6da1677bd3a5c04119e35f47319f20cfdfc08bb4528b21009e00bd41ebc0f46863bed10b3d9ed5c64b75e135df2f5e85300d90f21b363935e2817556fc9311751ba7535477dec8356ec385efb82b414062f35bb6d3edeafde305f9900a25e9813c9ee0237d46409650cdcdb5dfa2301a8e2647f8d3819d86f7b7e3070d33440f82c4054b1ab5edebeb27f95b3c4c6fdd468f21600f03b3494da200bab9293c38d02fc44048e52ff5fd0f7217a04d4ce912a180d1628f368280b6892672e8ff98d4629ac28b60c02a301e6c6026c1b9e9ef21cf0392df225008d5a0e0284b282631ad1710f811615697066c98296519948a7cfed5aeeb454ee7a61cc271bd3d499be17df09d3a0e790ee6b9bd99e1b919bed4a063b8d1a34f1afd2e952b9dfefd770969c8b2fc37977abb0fee6317253a23ecc97578168973334c8f91763ab97f29c49baeee7b35f3ae7f5cd3a4a6e697ef255a3c2ec0c752a3396f69f663ca1fc2b332dfe6c0faf78afe9c68d99571e8e896c5093085e9863a27648a9e58f3a9a84cbbfe2b41ca3633dd5cf6e82cb77cecacad8d78b353f48db42d99c36bcad170ea9e98abb2788c33a3c706268f3631: +888ce2ecceda9ca2b948ac1443c2aedd7595aacf36edaf27255bde7a6991dcc0016e572b4f98417c6ee297abd784ea48226ff4fbf0050a5ade8806e7046d3ba3:016e572b4f98417c6ee297abd784ea48226ff4fbf0050a5ade8806e7046d3ba3:5c801a8e664e7660760a25a5e1431a62159fc3f3aa713780ae7cbce23b8564782799bf2be4817ee2921965bab7e1d44833824c1628d42dcee3e46ae42b2816d0a432a1ab0bd21fcf30adb63d8dd76569544343d0035c760522ca68bea72c404edda1e9095ec90f3325681c6de0f4c12d1afbcba2c7871a1b1e1f19c35b0bed9ec2a87c043d36d819396bd5d099e1aa090391297c733f65a8c5d2120c67635316fab25b4d4847a45fc3f76f2e2426dbee4629975062fce14e2189dba27fb1ded2453f001debfaa899c11660612d2ce2ad2f762ea5dee7e71e58adcdcefa79e8e8b27fc4ccf89aabf176b5d34f82dd15d889f9f087dc9ae8a42a72f3b83583616e170637cd1adf38aa6551cbacca3602bdc7ae210c4a446b3af8db2720e549bbedb8bed215ae00f19da29d8fb0b642d27b2d88575f0ee84f3d129eb774d20f537a1c0fdcf717bdebcfe47f8331a341864346fa6a1c6bbfd178819e387a0d5499a68e81cc9f82ad39e31e4dfe71952d5ea5cc8052a3ceed1751f59dc7ecc9742fad144e18dda8d0582e74e39ca8c4:99d83f148a236ebbef1cad88cb3c7694f4986c9250e21c3603a0d941bff199cf77d6ce99efdb20533188d68ad133de033a1fb3468abb706d2b8b4fbac08dfe035c801a8e664e7660760a25a5e1431a62159fc3f3aa713780ae7cbce23b8564782799bf2be4817ee2921965bab7e1d44833824c1628d42dcee3e46ae42b2816d0a432a1ab0bd21fcf30adb63d8dd76569544343d0035c760522ca68bea72c404edda1e9095ec90f3325681c6de0f4c12d1afbcba2c7871a1b1e1f19c35b0bed9ec2a87c043d36d819396bd5d099e1aa090391297c733f65a8c5d2120c67635316fab25b4d4847a45fc3f76f2e2426dbee4629975062fce14e2189dba27fb1ded2453f001debfaa899c11660612d2ce2ad2f762ea5dee7e71e58adcdcefa79e8e8b27fc4ccf89aabf176b5d34f82dd15d889f9f087dc9ae8a42a72f3b83583616e170637cd1adf38aa6551cbacca3602bdc7ae210c4a446b3af8db2720e549bbedb8bed215ae00f19da29d8fb0b642d27b2d88575f0ee84f3d129eb774d20f537a1c0fdcf717bdebcfe47f8331a341864346fa6a1c6bbfd178819e387a0d5499a68e81cc9f82ad39e31e4dfe71952d5ea5cc8052a3ceed1751f59dc7ecc9742fad144e18dda8d0582e74e39ca8c4: +617390857dc10cdf82b5c94261f58ce2d44aa2f57d298f08a2d6c74d28147daf89e0c3e0a0f130d1916e0e3849b7286fa2e3ac4c17bd1f716ee5a72f0257fb8d:89e0c3e0a0f130d1916e0e3849b7286fa2e3ac4c17bd1f716ee5a72f0257fb8d:1fd9e7453eaffd7c9b54055622dde170dd58b71cb945de75351d5fceb1f536bde25158f03786155f953dc207a1708f90d95b15aca0aee3097fdcaae85e4ab1c2cdb705c53e6c2ed21a994b304a75caf2ce4fc7d61f561e74e297397e2cde5cc69056940343aa81375d0af18d17d2f34c0a71dcf1de3c4fc488a14c5fa6b3337a3174b1da7958fb00bd5955148221427c60dba04117c80d2488656dbd5343de891287b50ef4df9825eda76b4977f3acd4ab6d3102fa56878306cd76561491bcfdaa1da567e677f7f03bae5dbf4426c3c4a6c3d082f9178b2efdd2bd49eee97ef4dcf3f0f51bbdeffe5ae6601e28019518f827f02e51f6679b8715978bec3e69d577156dd719959371baf034219fbbd17a2369a8541490f6a02013e33e74f4769be37aefa4defb6bfb3f351c2a261482c2fbec49f85f8445456e8f5a474030cd72d095ef6a622030e1e43a0c5debb034731d2f5e8e4ba3990f077d0c162649d1fa3ea4fe1e81d74aa849e21b059d966cbad4c493ca10bafe7a69243e3c0a6ebfd13d697906303392ba65d4fe06b6a5:63e90a6afbbbb0ee696bfb56efd679d68a9851a8947640a97f41f68edfeadd216ed8698e2e43c820c9044caa7adaab5b76762b681831a9f760476a8443c43c061fd9e7453eaffd7c9b54055622dde170dd58b71cb945de75351d5fceb1f536bde25158f03786155f953dc207a1708f90d95b15aca0aee3097fdcaae85e4ab1c2cdb705c53e6c2ed21a994b304a75caf2ce4fc7d61f561e74e297397e2cde5cc69056940343aa81375d0af18d17d2f34c0a71dcf1de3c4fc488a14c5fa6b3337a3174b1da7958fb00bd5955148221427c60dba04117c80d2488656dbd5343de891287b50ef4df9825eda76b4977f3acd4ab6d3102fa56878306cd76561491bcfdaa1da567e677f7f03bae5dbf4426c3c4a6c3d082f9178b2efdd2bd49eee97ef4dcf3f0f51bbdeffe5ae6601e28019518f827f02e51f6679b8715978bec3e69d577156dd719959371baf034219fbbd17a2369a8541490f6a02013e33e74f4769be37aefa4defb6bfb3f351c2a261482c2fbec49f85f8445456e8f5a474030cd72d095ef6a622030e1e43a0c5debb034731d2f5e8e4ba3990f077d0c162649d1fa3ea4fe1e81d74aa849e21b059d966cbad4c493ca10bafe7a69243e3c0a6ebfd13d697906303392ba65d4fe06b6a5: +877d017436369ec2453fed46e977d6acc3a7be60d31395ad6e7ea9e07480e4c94e65422fed334a55e8b673893eba7c181dd724dda002817b0bae28acdc3f7fc0:4e65422fed334a55e8b673893eba7c181dd724dda002817b0bae28acdc3f7fc0:4ed3f5bdbd41d0e3b0a8a7fc3752eea496d6141678cbfe06757f61e1a168d761b6da83052f7994950d24626f004fbe9b8c9562e0c955fb3b5c08fd2d3d258393a349030c8e156205b40483038be1959f1cba490a87fe13899e4f3752063b68fe3e1c5071f7db0002f01494b4a3ee2e07992bdd200db4316629ee8a95ca347f0b28d6402a6da8b53e6b32581c3691e11ae9b6e0f0494894e649a92d03eb49c4d6833fa1f54f8dcd91d06936a6e62d491e2cea46dd07d9f02d3254b850bc9749f258a61ad3b9cc24b03287331b85a24143aaf8fcccac5f18bfc72dec75c0233516aa6e4589c78c665a186ed902091df97b0d04e83a2d74d789891aea2cacf813fffb5efaf78dbcd7af54ef55c77b1c4c8ace9e9278adc23d76c779d64b3bbbd1fb33b09836ea64a71e4711e89e8da0f709213342176ae22c6e7852c3973b60d9f98889b442aa48d7bfdfdef64c36c586c4fb2ad2e27ebe479f6d722f069fd6106b0d08975d5f721547c3b9c52f9fc5f45bb45b5b632188e80626518a79056bdc4ee1d2be6c6542a21fadea92c6dfb776:7688f3f2401eacaf2dd88e170ff1c4d7e94822a77f6b550b569e82152bbbb434057e01230b05ce58ee1dee5226b5c7cdbe5a8ade3b9465f59aed74145d14330c4ed3f5bdbd41d0e3b0a8a7fc3752eea496d6141678cbfe06757f61e1a168d761b6da83052f7994950d24626f004fbe9b8c9562e0c955fb3b5c08fd2d3d258393a349030c8e156205b40483038be1959f1cba490a87fe13899e4f3752063b68fe3e1c5071f7db0002f01494b4a3ee2e07992bdd200db4316629ee8a95ca347f0b28d6402a6da8b53e6b32581c3691e11ae9b6e0f0494894e649a92d03eb49c4d6833fa1f54f8dcd91d06936a6e62d491e2cea46dd07d9f02d3254b850bc9749f258a61ad3b9cc24b03287331b85a24143aaf8fcccac5f18bfc72dec75c0233516aa6e4589c78c665a186ed902091df97b0d04e83a2d74d789891aea2cacf813fffb5efaf78dbcd7af54ef55c77b1c4c8ace9e9278adc23d76c779d64b3bbbd1fb33b09836ea64a71e4711e89e8da0f709213342176ae22c6e7852c3973b60d9f98889b442aa48d7bfdfdef64c36c586c4fb2ad2e27ebe479f6d722f069fd6106b0d08975d5f721547c3b9c52f9fc5f45bb45b5b632188e80626518a79056bdc4ee1d2be6c6542a21fadea92c6dfb776: +4f0b3607d70b0f2698327ef4f1982c5b4b94be78f50c76f43bd642f1f0ede39b942b43089fd031cec0f99e5e550d65307fb6c3e793449fb390ff730fffd7c74b:942b43089fd031cec0f99e5e550d65307fb6c3e793449fb390ff730fffd7c74b:9f700a1d2560f69d9bc105bc83bff539e4258c0248602013a959b978a19cc273280d90c0178089578b50518e06ad1eab790ffe710c63d78887a95569144f3e58a8837f93dd516fcddd22bc97a7f14411d424b2e8e9aa7c280119ad94ce92533fc7fea6c66248644ac3e1beef2553a6f61e91b9379b0fe0c68b40681455b311f40df0c97f53fc954242c375e7708d61bad9f51296247274fa01a7328fa5009d9995f501ae8683552b11a49d2638116723b1319450a90138d278cd9512b80ca5792ed16c683bef92ec87884c9f07f137dc47a13146e511065c2e1b4b80efde88ae12e29431beb7aee365c16d80506b99afa6a1406edb061766875832dba473e519dd7018f402eb1bb3014b7cee4f02e980b1b17127e7d25dfe0c168c5344f1c90044f827707dca03070e4c43cc460047ff62870f075f34591816e4d07ee302e7b2c2ca9255a35e8adec03530e86a13b1bdfa1498813098f9ba59f8187abcafe21ba09d7c4aaa1ad10a2f28334ab53996147c2459c01b6a10839e0301123d91a35ced7af89afbac7d9cf8ac9a38ceebef83:f396a11f2f03c61439684f79001bd4f346a348dcf1d3beb2d3bfe33ea73a5ad4eb97506acfbffb784e77548189cd599f8ccf17355dde80e75024ef2a78d5fa039f700a1d2560f69d9bc105bc83bff539e4258c0248602013a959b978a19cc273280d90c0178089578b50518e06ad1eab790ffe710c63d78887a95569144f3e58a8837f93dd516fcddd22bc97a7f14411d424b2e8e9aa7c280119ad94ce92533fc7fea6c66248644ac3e1beef2553a6f61e91b9379b0fe0c68b40681455b311f40df0c97f53fc954242c375e7708d61bad9f51296247274fa01a7328fa5009d9995f501ae8683552b11a49d2638116723b1319450a90138d278cd9512b80ca5792ed16c683bef92ec87884c9f07f137dc47a13146e511065c2e1b4b80efde88ae12e29431beb7aee365c16d80506b99afa6a1406edb061766875832dba473e519dd7018f402eb1bb3014b7cee4f02e980b1b17127e7d25dfe0c168c5344f1c90044f827707dca03070e4c43cc460047ff62870f075f34591816e4d07ee302e7b2c2ca9255a35e8adec03530e86a13b1bdfa1498813098f9ba59f8187abcafe21ba09d7c4aaa1ad10a2f28334ab53996147c2459c01b6a10839e0301123d91a35ced7af89afbac7d9cf8ac9a38ceebef83: +b8a0010c784d8d002a31da11d022d30188a4197a1d5f14ea4c0dab29a2e406688bdc63e50bede13c91a41e4b4b7857b9e553f484e3c1ec167dc04c281ea86622:8bdc63e50bede13c91a41e4b4b7857b9e553f484e3c1ec167dc04c281ea86622:5c6ccb298be216808b811e56d972f456b69ad39594eee354701ca6b3e38d1f41a359e5512af98a3a0873265fe5191f4f2ecaf66bee75a3ac0b71a4ddf2a759ebdddbd88a6a1c6fd0fcf7d7cb92a84e3307b4a4f98c710abf4f553dee74f652d2ac64bc30f72bf4354ef7e806a19071a051bcfcfb27e37fddd41eceaec1758e94695c670ef4c5a5902178329db9585c65ef0fa3cd62449bb20b1f13aecfdd1c6cf78c51f568ce9fb85259aad05b38c6b485f6b86076928ddb4e2036f45e7b9c6a7ff24ae1776030e2576825019ab463ebf7103a33072033eacbb5b503f53266afb82f9b2454b8dc057d84f30d9d2cb7c3a31a7dbdfba5b8e49231c231396c47ca042c8e48a1a5e3ec9afe4020595390f9990dfb874e0825ae9ae5e752af63af6fd3e787e75e8d8dc4c66302277ac01b30a18a56cb82c8a7ebdc915b7153255a1fedc492e49660262bb249780d173e1fd20d18c4f6b0b69aa2eca024bf3c80d7d5962cc4a129a7943b27f33cc799a36045541275a2cdb92a40e485ba8b737a04b43d29c3e25f76cb3d93a6b94461f88f5696:b3f6cf4c0e0f9074ff2c2c47e163202f1e9d6ee117cf757633e4abe74423aa70008ada1509ec1dc117c1c230e9b23786f3d0f29b73aa284536e9580106a8a70c5c6ccb298be216808b811e56d972f456b69ad39594eee354701ca6b3e38d1f41a359e5512af98a3a0873265fe5191f4f2ecaf66bee75a3ac0b71a4ddf2a759ebdddbd88a6a1c6fd0fcf7d7cb92a84e3307b4a4f98c710abf4f553dee74f652d2ac64bc30f72bf4354ef7e806a19071a051bcfcfb27e37fddd41eceaec1758e94695c670ef4c5a5902178329db9585c65ef0fa3cd62449bb20b1f13aecfdd1c6cf78c51f568ce9fb85259aad05b38c6b485f6b86076928ddb4e2036f45e7b9c6a7ff24ae1776030e2576825019ab463ebf7103a33072033eacbb5b503f53266afb82f9b2454b8dc057d84f30d9d2cb7c3a31a7dbdfba5b8e49231c231396c47ca042c8e48a1a5e3ec9afe4020595390f9990dfb874e0825ae9ae5e752af63af6fd3e787e75e8d8dc4c66302277ac01b30a18a56cb82c8a7ebdc915b7153255a1fedc492e49660262bb249780d173e1fd20d18c4f6b0b69aa2eca024bf3c80d7d5962cc4a129a7943b27f33cc799a36045541275a2cdb92a40e485ba8b737a04b43d29c3e25f76cb3d93a6b94461f88f5696: +efc86cbe40363abfbb2a4b1fcce5fd6084da96e7e814de71aadf9a618f30362522f295cee727d28d2b9317153e7d9412da1065c1b16ae2a251dd1fb431c62b01:22f295cee727d28d2b9317153e7d9412da1065c1b16ae2a251dd1fb431c62b01:9e4fa45dc026710f6bef4ed0f07c544b0bb0d88fa79e7177d8448bc209d71cfe9743c10af0c9937d72e1819e5b531d661c58c63141ce8662c8839e664db79e16c54d113abb02a75bdf11b3453d071825bc415741e99483546b8e1e6819de53017092e4ef871f1ca0d3508f937828a4667db11ffff9416eebb94bf9b84d654603094834a99ca70b90f562a86823624dfe9cb2f9e88c173f13464d4ce255f222db50dd63ab42465734e75295c064b64cc3f15e6237e37f33d615f7c243e4ba308960cfd4393402525500bb7902970b3931d48b35666a2d4d2ab08fa12af366a004346c9dd93d39fb1b7340f104e51fedbb533605b5ff39cf6d59513f12856dcfa198d793b0fc875cdea0741f1455746d8a19c3e9d928f0021b01c25131811e48c3c75c6f41422a8810c6c81f35b454eeae8cd17cf3f2e6f0bcd9f290984f496578623ab8e2738d2d10840eb91d101cb4a23722b72e3dd185440c3b9f44d46a393a34c187a20d610bb698c50531741efe96323512329800772a408065a7ef8e4e4105eb1f5bf6d3fd6b217fd836d89f53b96f45:f8818310228ca76111524ce94bfcb0246ea63508cee9306592b2f77548edefcf76bd1454508ea715042cec169cea5115ab54235cb1097b10702aa38378028e0c9e4fa45dc026710f6bef4ed0f07c544b0bb0d88fa79e7177d8448bc209d71cfe9743c10af0c9937d72e1819e5b531d661c58c63141ce8662c8839e664db79e16c54d113abb02a75bdf11b3453d071825bc415741e99483546b8e1e6819de53017092e4ef871f1ca0d3508f937828a4667db11ffff9416eebb94bf9b84d654603094834a99ca70b90f562a86823624dfe9cb2f9e88c173f13464d4ce255f222db50dd63ab42465734e75295c064b64cc3f15e6237e37f33d615f7c243e4ba308960cfd4393402525500bb7902970b3931d48b35666a2d4d2ab08fa12af366a004346c9dd93d39fb1b7340f104e51fedbb533605b5ff39cf6d59513f12856dcfa198d793b0fc875cdea0741f1455746d8a19c3e9d928f0021b01c25131811e48c3c75c6f41422a8810c6c81f35b454eeae8cd17cf3f2e6f0bcd9f290984f496578623ab8e2738d2d10840eb91d101cb4a23722b72e3dd185440c3b9f44d46a393a34c187a20d610bb698c50531741efe96323512329800772a408065a7ef8e4e4105eb1f5bf6d3fd6b217fd836d89f53b96f45: +33556c60de2f2c9a9303b99add378592060505f8e49861085a4b15f072a7ef28231ec8cd845859f69961275119dbe4f715e5ec5aa98bb8741675b3c2d0c89fee:231ec8cd845859f69961275119dbe4f715e5ec5aa98bb8741675b3c2d0c89fee:96af540ea2b1923f5fd0aad321ac032070c2d65ba13d164e75c3469758fcf31bb31655cb3a721f9cb34be2c90c77eb65be37f606d32a917a4cb9a709ac0705229930ef6eb6fdb0fa3c0fd3a90ce171674ee3ed06354bafc3c7075467a57445b80385640447902be39262894b1f64fea58287dc322d19875972a7c8be91d31f021c70eb682fdf11a10f8f582a126e064794838c69fdf64f5b6e8ba59d48b4384f8e9fb5c087cc7738295cd32344ba3b697ee6b6a8b78ee7a9575c97972a4d1bb18486f9037a0f3c6f471a90f86498dbc0df5232c07e8c01b690bee75302992a7a36fb4437c25a8bf5e34cf7d5b55572c700a079848d381364f9946a91eb1603ff3de5ebdd523bd92564818e237a53e8f522deaa2c29b897e961586e100ed0fc0ad70d160934e694027e5c957920bc0546e901be39a84535597e1f280c222267abe97f41205d8171820dd2faafc0699419321a9160f69b99fd41180945b62d2dd105cc7bbe821d28605e098edfa8b2309aeb0534e756377f59937c67463fd87c8b92ab58119cf4ce6c665af572fbae1de4a2cc71:e06a7a414457bbbef2bac3775ccad087dacb1fa4bf938894e8c929118e09e678dd19938bc88f43ed0f7d31cc6a0e602c4e4d1fee33d41e74a119fa2d1e4e340f96af540ea2b1923f5fd0aad321ac032070c2d65ba13d164e75c3469758fcf31bb31655cb3a721f9cb34be2c90c77eb65be37f606d32a917a4cb9a709ac0705229930ef6eb6fdb0fa3c0fd3a90ce171674ee3ed06354bafc3c7075467a57445b80385640447902be39262894b1f64fea58287dc322d19875972a7c8be91d31f021c70eb682fdf11a10f8f582a126e064794838c69fdf64f5b6e8ba59d48b4384f8e9fb5c087cc7738295cd32344ba3b697ee6b6a8b78ee7a9575c97972a4d1bb18486f9037a0f3c6f471a90f86498dbc0df5232c07e8c01b690bee75302992a7a36fb4437c25a8bf5e34cf7d5b55572c700a079848d381364f9946a91eb1603ff3de5ebdd523bd92564818e237a53e8f522deaa2c29b897e961586e100ed0fc0ad70d160934e694027e5c957920bc0546e901be39a84535597e1f280c222267abe97f41205d8171820dd2faafc0699419321a9160f69b99fd41180945b62d2dd105cc7bbe821d28605e098edfa8b2309aeb0534e756377f59937c67463fd87c8b92ab58119cf4ce6c665af572fbae1de4a2cc71: +7a5c74314e1183334a4b6226b9a82d70fc2a124e3f87db6a2283ee05b68e34e0beae7d3dd97c67f6273bfaa066131fed8ace7f535fe6464e65791c7e5398576c:beae7d3dd97c67f6273bfaa066131fed8ace7f535fe6464e65791c7e5398576c:98bac6724755912992adc2a48b5442376f2d927997a040fb98efe544eb0c8e1866b9616e298d3360316ed976bd946a411fdd3a6b625c0c1a37af0f41cf6569a7884ab8467491a987df3ea7a0b7ebc4692569a34ce3a2ea3503495b2c02d49d7d7db579d13a82cf0cf7a9547a6eaebe68e7267d45a60b8d4772455228cca4036e282e1a1216f34cef7ea68f938270bdb04293c885d005f9f7e638a8b4ead2626c0945174ff2a3e2d6e15a4c0338c09e1260f0928ca9d3499824f3fedc4785da49c5c34a56855e241facc6347a399ddcac4399a8b158198c151461a3b189e58ec1f7efcf2ab2031fb17b6f035ba1f092e9eee2e92c2d6cc2032287f854b41e70fc61c8d11a2e4f0708f02eebd02e8c7e8c7b38a57bfa1a745f3a86c23909f6f89ab16ce7e1813c1d20147f31b4cf2ad0b606fb17e5ac1ab51ef4a7d8093cee9a655f471dc5b146bd1b93e540a3d3d3e2de8105911c10d6ab5ff79c2d06027f7a54561f2071414bd330a8785442251c810e232f83c367f0be7799a93f5238f7f17b5be829fd89123c04833af8b77e5a4363047ceca7:c2ab1f6f5114a84f218502582c567b37a8bdbcdf6340fa4622873be89106f0a90b4829505f72129df0ab3d8513268774a34df3ad21ce254b464488addd6c9b0498bac6724755912992adc2a48b5442376f2d927997a040fb98efe544eb0c8e1866b9616e298d3360316ed976bd946a411fdd3a6b625c0c1a37af0f41cf6569a7884ab8467491a987df3ea7a0b7ebc4692569a34ce3a2ea3503495b2c02d49d7d7db579d13a82cf0cf7a9547a6eaebe68e7267d45a60b8d4772455228cca4036e282e1a1216f34cef7ea68f938270bdb04293c885d005f9f7e638a8b4ead2626c0945174ff2a3e2d6e15a4c0338c09e1260f0928ca9d3499824f3fedc4785da49c5c34a56855e241facc6347a399ddcac4399a8b158198c151461a3b189e58ec1f7efcf2ab2031fb17b6f035ba1f092e9eee2e92c2d6cc2032287f854b41e70fc61c8d11a2e4f0708f02eebd02e8c7e8c7b38a57bfa1a745f3a86c23909f6f89ab16ce7e1813c1d20147f31b4cf2ad0b606fb17e5ac1ab51ef4a7d8093cee9a655f471dc5b146bd1b93e540a3d3d3e2de8105911c10d6ab5ff79c2d06027f7a54561f2071414bd330a8785442251c810e232f83c367f0be7799a93f5238f7f17b5be829fd89123c04833af8b77e5a4363047ceca7: +da8006adc492ca5dc86c2959437a75deb6120ff787d2ecb9c20c30b52c26bc41ff113bf0aa58d546f2385d444ecb7888f8caba43a174a89fd6065f2b7dc17bf0:ff113bf0aa58d546f2385d444ecb7888f8caba43a174a89fd6065f2b7dc17bf0:3eb4324dbc0149d2e7d6df632bb0cbe9a9f6dfa83e227fc07bde1b577b3611fb921c9f8313f068e6295d4913a8196be530f6a01f57c09c028491444b784720e909ea1fb69c1c1dd6304400327b7731b33cc46deb046cdab6ad1b53f1749a0c65cb9a7e376ffa02230f536584aea243c639103adbba764321649d7e0126f82e0b4fd9dcb86c731cbcc517f2016841e916bcd5fde871dc098cd913dc546284d1b2165c63e88f32a2789a500856371b50d22fb8c87d1a3caedcdfd01ee5f870a53c284181d632ec66d48b6bdd5646ac39c9e75338a520212062bc3466ef5c58765570b905f63a93d07f8f1baac3526b016da799f3e9e03a4f7f81355e0f7a76f30a42b807322051b71c626a7a296d75b9d9d1a23bcb13c9ef48a912dc057325d3bcfb3f9fadaf0c249b102aeb854aa3631e34f69ad90c2ab2ed33bacc40b9ed1037fae67cdf799d5a9b43785961127d62f8e0bc1589fd1a06fca2aea7cfc012cbf7b5b207ddc4e677d8ae4aec100045ce36c00b74d1d28250791236dc5dcc1ed313c8c246172666f75217437c6034acd64198cd96df2a:1f5375dcb3ad2baaff956d8554ecb424176be9a6eb9ea54e814e0a73df2a5d848ada26ba8e1805cd51c5e16950c1ff7d4d2764daa6f4c7502fb865cbe55aaf0b3eb4324dbc0149d2e7d6df632bb0cbe9a9f6dfa83e227fc07bde1b577b3611fb921c9f8313f068e6295d4913a8196be530f6a01f57c09c028491444b784720e909ea1fb69c1c1dd6304400327b7731b33cc46deb046cdab6ad1b53f1749a0c65cb9a7e376ffa02230f536584aea243c639103adbba764321649d7e0126f82e0b4fd9dcb86c731cbcc517f2016841e916bcd5fde871dc098cd913dc546284d1b2165c63e88f32a2789a500856371b50d22fb8c87d1a3caedcdfd01ee5f870a53c284181d632ec66d48b6bdd5646ac39c9e75338a520212062bc3466ef5c58765570b905f63a93d07f8f1baac3526b016da799f3e9e03a4f7f81355e0f7a76f30a42b807322051b71c626a7a296d75b9d9d1a23bcb13c9ef48a912dc057325d3bcfb3f9fadaf0c249b102aeb854aa3631e34f69ad90c2ab2ed33bacc40b9ed1037fae67cdf799d5a9b43785961127d62f8e0bc1589fd1a06fca2aea7cfc012cbf7b5b207ddc4e677d8ae4aec100045ce36c00b74d1d28250791236dc5dcc1ed313c8c246172666f75217437c6034acd64198cd96df2a: +a284e26b97e538839c808d45bde6f012a354454aef81caa8c55914624f2b7d665ae46e34695efaf463a4208fc4e35b81f2c63593238a56f2444b850f058c3c5c:5ae46e34695efaf463a4208fc4e35b81f2c63593238a56f2444b850f058c3c5c:9ebfe910b50a5cb719d95b961e5905f00ec7943b55468ab5956692017645b366071f8fbb77eb49ec73ea7d64511405b90de22db98c3eae39c4039c7a133430e8010bdd39a00fd1a528b113dae149cfad3ae340da27dcc507782ecd8929237517afe7463eca2473c7acf6f7aa04efc9f266ae7b6d63bb8cc2a438b344827f0713d1f1736f0cbb65b99353f20355fa0230d4fa707328a8662654e83ad0530a10f9a69e17c099e1e2b5db18e5f6f1dceda5883e8cab79701a5e9089562ed153ad08c674f097c28e4d16633e092969a8f0bdac54527c0ee03bc200e5be612e3d1eabd87091101b4962afa07b310806992f373076d76a58185118137c9d26ee2cd4c618c18283dd19f0e7a089ee37305b6b9518a78d8098436ef62be7d699808acecf67939d61b3e02937cd8c5f1e746d4274334bc9c37fdcba234c166fd712893f3a040832ec5425e57d80f11ef9ca5fbcd6c147fbbf5e2fae746e0ddb605867e3bd050483c3cd1329abe57a60bf88898dc7e80ede0f4517de8fc807e888b621a00f663084ff94b99996628f3b11690a60f0918cb5c9a7ef:bf110e2e9cecbc31fa3e0c2438cd1f4321f92cd287005a48528addf76cad8d88bb22719ef91b139562a1511838682674faa9ff7e7ade6c9d573f845036d189059ebfe910b50a5cb719d95b961e5905f00ec7943b55468ab5956692017645b366071f8fbb77eb49ec73ea7d64511405b90de22db98c3eae39c4039c7a133430e8010bdd39a00fd1a528b113dae149cfad3ae340da27dcc507782ecd8929237517afe7463eca2473c7acf6f7aa04efc9f266ae7b6d63bb8cc2a438b344827f0713d1f1736f0cbb65b99353f20355fa0230d4fa707328a8662654e83ad0530a10f9a69e17c099e1e2b5db18e5f6f1dceda5883e8cab79701a5e9089562ed153ad08c674f097c28e4d16633e092969a8f0bdac54527c0ee03bc200e5be612e3d1eabd87091101b4962afa07b310806992f373076d76a58185118137c9d26ee2cd4c618c18283dd19f0e7a089ee37305b6b9518a78d8098436ef62be7d699808acecf67939d61b3e02937cd8c5f1e746d4274334bc9c37fdcba234c166fd712893f3a040832ec5425e57d80f11ef9ca5fbcd6c147fbbf5e2fae746e0ddb605867e3bd050483c3cd1329abe57a60bf88898dc7e80ede0f4517de8fc807e888b621a00f663084ff94b99996628f3b11690a60f0918cb5c9a7ef: +cc97a96301ceed0f922731b685bad8ad4f06207be340f5a44fd187f29903ec20eb563a7bce12db97f1891d0f610bebd55101a3125ca8dbb50b25a6b5050d3784:eb563a7bce12db97f1891d0f610bebd55101a3125ca8dbb50b25a6b5050d3784:b9ea3b3df7187ea415a3c335e0834e10f440915b2ad41c71f255d6950a4e9120e4d494fd9e672ce53206fdc417d865897b47ac1054e1ca1068195232d4297435e44e1224e66a912d9d7d182946ff5a9f085bb8ba19c54d16b586a9b30461b6773b93950311e1619886f5a5b3f111aaad094bae31c48f1941080968bd0277bb6fa92eebf324b192df5cc969516c78c7b2d12159b4d1c8eb03160c4cd1907f62ed4b854c569ecc481c08e636f44ed7c390e58b5937d2906b2817bc3769dad9da1b0f79391b55942063055da0d6f249a3e452baddaa032998d7f73398ccd0151bfc92c5e2fdfa9b14855e6b0d3746dce248e219672987252ec747df2747fd3fbd8b714c882d707ee302a904950c34754f85350e1aa3f8ea6293cf01f717cefb6b83a22126df5c4f5698aafd06a2244ad7d01f34017ca0ece6f21040048aba6ca4aeb04325b9402bcd43ab130a105788ac3d7b7da01ea9426dd0ea1933a8189933a6c0c6cd648ea316a7469a5fdc6e7c934d9186586097b55dd51ac487bb80ed11d4df8d33626bbce95e4f13bd49922f00c920223f4cbf93cb:ffbdd3244181cdf6034f4a450fdd95dee4971a933f8be022bb0a4106aef39af3055b721881c9b54d1e99b9409096fbe6dc2c9966e3679964bd7ef4c808cabf01b9ea3b3df7187ea415a3c335e0834e10f440915b2ad41c71f255d6950a4e9120e4d494fd9e672ce53206fdc417d865897b47ac1054e1ca1068195232d4297435e44e1224e66a912d9d7d182946ff5a9f085bb8ba19c54d16b586a9b30461b6773b93950311e1619886f5a5b3f111aaad094bae31c48f1941080968bd0277bb6fa92eebf324b192df5cc969516c78c7b2d12159b4d1c8eb03160c4cd1907f62ed4b854c569ecc481c08e636f44ed7c390e58b5937d2906b2817bc3769dad9da1b0f79391b55942063055da0d6f249a3e452baddaa032998d7f73398ccd0151bfc92c5e2fdfa9b14855e6b0d3746dce248e219672987252ec747df2747fd3fbd8b714c882d707ee302a904950c34754f85350e1aa3f8ea6293cf01f717cefb6b83a22126df5c4f5698aafd06a2244ad7d01f34017ca0ece6f21040048aba6ca4aeb04325b9402bcd43ab130a105788ac3d7b7da01ea9426dd0ea1933a8189933a6c0c6cd648ea316a7469a5fdc6e7c934d9186586097b55dd51ac487bb80ed11d4df8d33626bbce95e4f13bd49922f00c920223f4cbf93cb: +679e3e34773abe4ae25cae7d07ccd0eb3b0ec0a35d570257d62570de58ea251618acffce253b27259579ed9924f479cae312167bcd876edba88b5d1d73c43dbe:18acffce253b27259579ed9924f479cae312167bcd876edba88b5d1d73c43dbe:fb2b648ebb16688244f78b2ee9a273599d56b6198900d438a9e99c191425c72bec4f235847e18e47f57c3cb396655f778921f908580e8e83c96c108b20dd416678021bca259b98518fabb2d3532e4851d9d52add2542c0cb3efa3857a17e512438bc0ec4762e2f9baba429c03e99bec4038e6b0ca42bff5b233b24c333b4caead2de374a87b2ab5d80d6e49e4456329d51ae973bc83d7862f3d315e514481b12854a9dfc09e7d14f0d022c0ba3022578eba8f874deba4aa8c833f2b132861d4d51e50fe9aa4b787bd2f051aac50c375390cbbcfba2002b80ad00cdc12980f8ba8bcb7064afc04d5c4682c1029b10a6d45fe6ecd704245faf598c4659597c5d68a192cc1cd4fa45e84b549e8e5e67daa879ae5a520a6b5550519876a562ac49c6db0aa76ec69bb64dd6b5e1a3af2e131e722e7cdd05be34b5fcc6259aa124ccf814cf5b500d176be28ebc40bb21f03e24ccc131e0f41daa1ca02e6b00c9c53fad1248614e940d4b237760ab7569a767b7515dd2d623e57a2841b7d2441cf43049e4698d2f9c9eae7b2910f6ad65edf9cb2bdbd9b29f606e0d:1a51022628ccbb88eae9b21773c3f830b7b6e5bc36c9903ce70fbcf459d6a1ed8a1dceff5b19269ebf5a6fd3d8958860f554461f0e9fc0e29af9b1fb1744a80bfb2b648ebb16688244f78b2ee9a273599d56b6198900d438a9e99c191425c72bec4f235847e18e47f57c3cb396655f778921f908580e8e83c96c108b20dd416678021bca259b98518fabb2d3532e4851d9d52add2542c0cb3efa3857a17e512438bc0ec4762e2f9baba429c03e99bec4038e6b0ca42bff5b233b24c333b4caead2de374a87b2ab5d80d6e49e4456329d51ae973bc83d7862f3d315e514481b12854a9dfc09e7d14f0d022c0ba3022578eba8f874deba4aa8c833f2b132861d4d51e50fe9aa4b787bd2f051aac50c375390cbbcfba2002b80ad00cdc12980f8ba8bcb7064afc04d5c4682c1029b10a6d45fe6ecd704245faf598c4659597c5d68a192cc1cd4fa45e84b549e8e5e67daa879ae5a520a6b5550519876a562ac49c6db0aa76ec69bb64dd6b5e1a3af2e131e722e7cdd05be34b5fcc6259aa124ccf814cf5b500d176be28ebc40bb21f03e24ccc131e0f41daa1ca02e6b00c9c53fad1248614e940d4b237760ab7569a767b7515dd2d623e57a2841b7d2441cf43049e4698d2f9c9eae7b2910f6ad65edf9cb2bdbd9b29f606e0d: +9bfa60923a43ed0c24e2f12f5b86a0716329f93d4d8d3e06238002893278c19afb1c00687781b55b893d6b2f4f49cf5f73d2903c316d1eee75991d983a1868c0:fb1c00687781b55b893d6b2f4f49cf5f73d2903c316d1eee75991d983a1868c0:a99028b0f4a3aa5e79abef6c0df4a783ef470f1a29ba51eba00f6214e840fe19e5b6dc6021ab599bb2ee3699576015d79a7939af823535b630e3938c723f6e0b9229d46bb3379acdba587c238567e3d89bc3bd3519b727fc694fff1118bf22c8bc8bc82c4df7f5ad38de05fe9f762999ecaa795f3ae630a9a316d26dce9f1568ffa3f22b0295214020b3d3f5337c149568192218132a90709279c01d23baefa669e1c4e42038173f1319c212da144f1c4ea4c52c005cbc0b5bc283e74483a0dca69279deb17ae5b29cfafa7d0063f4e1bc93537efd937e58a8aca737228f937ff2a741890e96c5725da11b45c413a9bbb4180a419987bbf046bfd346295d62f081c76daf2b0e1eb4f6712feebe6f0a92e358e7ddb85896507c340a01f68d1b0f085778b7c44b014aa6673e501796959a17a688db0959058488a7112572f23cf9cdb53b5eb4b45f5953ba0c0c690f86bd75e89a047bebaf847c1dfc345a4f3c7d3beec98b84b0219003e819f5c2adb45f8717903d1f5bd5d71914c56fcabc7a290f9c41699c95584d6a3a16340cb17baa1fc5e5467af7ac3221:55f202efb2a57be8b4e4fd894dcc11a4fc5f8276618ef5cd34a4495adb016a298e6480a35cfc53edb25ff1499fc532a33061cc01a250458aa5e4f7f16f51440da99028b0f4a3aa5e79abef6c0df4a783ef470f1a29ba51eba00f6214e840fe19e5b6dc6021ab599bb2ee3699576015d79a7939af823535b630e3938c723f6e0b9229d46bb3379acdba587c238567e3d89bc3bd3519b727fc694fff1118bf22c8bc8bc82c4df7f5ad38de05fe9f762999ecaa795f3ae630a9a316d26dce9f1568ffa3f22b0295214020b3d3f5337c149568192218132a90709279c01d23baefa669e1c4e42038173f1319c212da144f1c4ea4c52c005cbc0b5bc283e74483a0dca69279deb17ae5b29cfafa7d0063f4e1bc93537efd937e58a8aca737228f937ff2a741890e96c5725da11b45c413a9bbb4180a419987bbf046bfd346295d62f081c76daf2b0e1eb4f6712feebe6f0a92e358e7ddb85896507c340a01f68d1b0f085778b7c44b014aa6673e501796959a17a688db0959058488a7112572f23cf9cdb53b5eb4b45f5953ba0c0c690f86bd75e89a047bebaf847c1dfc345a4f3c7d3beec98b84b0219003e819f5c2adb45f8717903d1f5bd5d71914c56fcabc7a290f9c41699c95584d6a3a16340cb17baa1fc5e5467af7ac3221: +6e3af45e66e22890c3f3c934f523a4d69427976e6e52625f8bad558993963219e097364e76ff9f2e1d167f6b20c1bc5830085e7ec993c138f8b1b2175637e741:e097364e76ff9f2e1d167f6b20c1bc5830085e7ec993c138f8b1b2175637e741:5cfc2f4b559f8205b39102087617f4d86c7ce6cb251e5f89601dfc88ed28e8d7a670ec0087d2ea5d893021c7044da2899a22d776fe90170e51c203250690d37a294555e74af9234cbf1ad8f22cee8974828a0d09e9554b71ee3bcf880ab98325f706272194eb2e80c701d441b5f8668561b88849f827af703ab0954105fd3c54b3f6ec5493596d0e3bc67818048310c4a3e0c556bc80675f201f9bb9c6538a41d99aa40c886fc431467218d819c23e78498aed0613fa6f973e2211df9fb87f44116f3fe4c26d6cb2fa334c87f78c08ca8c9b9041d83a1230677e0af788598a42e44cfdf6964a4ee80e38402ba67c73a581e552baa2282425cb2ca17ca92edfbf98299102fba761b9b71a5452141bb9c18dd95febc2a782de9ceec08bd2ee3f7f0c1bd8946dba99cf9ea086abafd37c9ca60213f0de17c61ff9c391c9818ed5cd8571778b7dcc13224962386fb8ca14f861e99f3b18edac8a5f130f7bfcd45d045d0ff34c81572a512363d6530f93813e5fb10e9cb8338a7f93800491006f4463e89f0ed4530e5f12df674f598904780ad0812b1e3521fcd0f83e:26ba562e8a4065708207c25e239b780aee38794cf983a37acbb9d557a65ceed3c0da47d17f3e8b8f4eeb1b65a2c182ea6f29623b63bb0f1c72592683b126b9015cfc2f4b559f8205b39102087617f4d86c7ce6cb251e5f89601dfc88ed28e8d7a670ec0087d2ea5d893021c7044da2899a22d776fe90170e51c203250690d37a294555e74af9234cbf1ad8f22cee8974828a0d09e9554b71ee3bcf880ab98325f706272194eb2e80c701d441b5f8668561b88849f827af703ab0954105fd3c54b3f6ec5493596d0e3bc67818048310c4a3e0c556bc80675f201f9bb9c6538a41d99aa40c886fc431467218d819c23e78498aed0613fa6f973e2211df9fb87f44116f3fe4c26d6cb2fa334c87f78c08ca8c9b9041d83a1230677e0af788598a42e44cfdf6964a4ee80e38402ba67c73a581e552baa2282425cb2ca17ca92edfbf98299102fba761b9b71a5452141bb9c18dd95febc2a782de9ceec08bd2ee3f7f0c1bd8946dba99cf9ea086abafd37c9ca60213f0de17c61ff9c391c9818ed5cd8571778b7dcc13224962386fb8ca14f861e99f3b18edac8a5f130f7bfcd45d045d0ff34c81572a512363d6530f93813e5fb10e9cb8338a7f93800491006f4463e89f0ed4530e5f12df674f598904780ad0812b1e3521fcd0f83e: +5f1f271844d9ed5a6a6f209a21408daea470f6fd53ba6479d7407105b7de4d656085d7fb5a9b2ed806c1fd30a2afde760961f7a36b48f4875246e615a2bd9928:6085d7fb5a9b2ed806c1fd30a2afde760961f7a36b48f4875246e615a2bd9928:eed6b4475dc263bd2207fe9d41d48282b713f680f2e037384f18b4bf224347f5e4c4b060b808d412eaabcf733dc39a40c6bda0505ce71fa823bd1b1794847678dc034e7999c16369340bc60c64d09bb9187b2e326055a053f8e505ea4196861471622db0e46f0f8954d8a1f07332da4d8ac55712626009912f8a15a9cd63a74a03c92f246cb63cc73f92e51dad1bc9715b1ed3fe5f2e1b2959b9b71e0e37360eb29536cf797147fab10864d6146c36b82335a0ce931408479c7ede484ff73e2dbfffc6c9227e16d7a23f4d90f15584514c39594e17bfbb295de9d62adadb589dbbe0b06dc8dac5b3bf517b24c1837b39472a6dd38931ffbbff5b763638805b4e22321f7afe92cdf502fb63d109ddcd9e4051ad6f45598532be179523710851d3931e887d02c345c79c489fc106a4ae162f7df71ab90b751da7038a6df7616cfc11887e21068fb9e33be566402be504f3fc2742b881509bd4fe6a0fc722649883f8cb655598a15a1d4c229dd86b5caeb711a028defd431154bba46b48172a4d8cbd45bc90aaf874b6085fa284f5fed655ad6fa17d67b3b9a796fa3e:319bb4deb2178112241b3fb8f46e105c3b8e4ef721eb200d762ef363e2716f2a89f80b5b9e89970890a09892ad6a58808b477e943b3cfa77774a3645bc745f03eed6b4475dc263bd2207fe9d41d48282b713f680f2e037384f18b4bf224347f5e4c4b060b808d412eaabcf733dc39a40c6bda0505ce71fa823bd1b1794847678dc034e7999c16369340bc60c64d09bb9187b2e326055a053f8e505ea4196861471622db0e46f0f8954d8a1f07332da4d8ac55712626009912f8a15a9cd63a74a03c92f246cb63cc73f92e51dad1bc9715b1ed3fe5f2e1b2959b9b71e0e37360eb29536cf797147fab10864d6146c36b82335a0ce931408479c7ede484ff73e2dbfffc6c9227e16d7a23f4d90f15584514c39594e17bfbb295de9d62adadb589dbbe0b06dc8dac5b3bf517b24c1837b39472a6dd38931ffbbff5b763638805b4e22321f7afe92cdf502fb63d109ddcd9e4051ad6f45598532be179523710851d3931e887d02c345c79c489fc106a4ae162f7df71ab90b751da7038a6df7616cfc11887e21068fb9e33be566402be504f3fc2742b881509bd4fe6a0fc722649883f8cb655598a15a1d4c229dd86b5caeb711a028defd431154bba46b48172a4d8cbd45bc90aaf874b6085fa284f5fed655ad6fa17d67b3b9a796fa3e: +048ac9ec3ecb30a3b1bfda9b3b79a48c0793b490879e3c8a5e23ee2babcd9b7c946c186feafc3580a58ddd526ff229c04720250f4cf6bde0271eef9b12b1c3f3:946c186feafc3580a58ddd526ff229c04720250f4cf6bde0271eef9b12b1c3f3:d68be8ef7b4c7a4289f2b18b16ade97f4e4fa16452976afb581693380cc54de38a07587f32e2d4549f26595fee2393bd062e9b00bae72498e4148c8b882a8840e15b585c82b5c0defb233518409916615deb3a55a5f84e6b3aab93844de3b1e4d86e09f889ac71c324eb12d0fbd861cc31229540e843a34f8d5be47c0ec0d23df43e06813fca309439904c167d1043c0dcd444b004be1ff27b7862b00eba9433b94b0fcdc67521da0c1d5358636c78f530431164dde20a1cf164f51e29b8e63eacdecc869b41392c667664d91680d9ac516af548f09e60564e814e36e0b563dbae55c627ffc14158a56d8eb3609e174381b21de4ba82344466dd577f4d1103c43c27fb83cb833d87afdf7412b4090909b1dde264daddce967f496bf6f17112bf351e417db5953b13b8f0fcccbf30f5bcf376861c12ef20eec89ed23cf384ee78dc6eb40fd5811a7b23927c13e7dc5da3a921b883a9b2b1155970fb0da7d2993dcdfd4343642a9d5a6347e43c193b5793e4453ac1537aa3d04dc9f774e840934881d78a39ba250438c507250eed2f6e07cc953f783d6b72b1cc619981:2ecf5b8a59a8e27d25890a2aa32f4a0673275d539b174afa7b2cebf2e76280dffc338ede85ac8f614039560e2806d9e1e3cf9cce2ceb7874ffe1a7e80cdef40bd68be8ef7b4c7a4289f2b18b16ade97f4e4fa16452976afb581693380cc54de38a07587f32e2d4549f26595fee2393bd062e9b00bae72498e4148c8b882a8840e15b585c82b5c0defb233518409916615deb3a55a5f84e6b3aab93844de3b1e4d86e09f889ac71c324eb12d0fbd861cc31229540e843a34f8d5be47c0ec0d23df43e06813fca309439904c167d1043c0dcd444b004be1ff27b7862b00eba9433b94b0fcdc67521da0c1d5358636c78f530431164dde20a1cf164f51e29b8e63eacdecc869b41392c667664d91680d9ac516af548f09e60564e814e36e0b563dbae55c627ffc14158a56d8eb3609e174381b21de4ba82344466dd577f4d1103c43c27fb83cb833d87afdf7412b4090909b1dde264daddce967f496bf6f17112bf351e417db5953b13b8f0fcccbf30f5bcf376861c12ef20eec89ed23cf384ee78dc6eb40fd5811a7b23927c13e7dc5da3a921b883a9b2b1155970fb0da7d2993dcdfd4343642a9d5a6347e43c193b5793e4453ac1537aa3d04dc9f774e840934881d78a39ba250438c507250eed2f6e07cc953f783d6b72b1cc619981: +2f057d20b1678531611f48f003b7d22eba5dbbd7e2dd41b7c79d09071f85e993620fc4eaa34d787df675ccbf7e893204828db92ead17a1165ac7fa1ab42719d8:620fc4eaa34d787df675ccbf7e893204828db92ead17a1165ac7fa1ab42719d8:6e35f6eaa2bfee06ea6f2b2f7ab15fa97c5180958af2e90af918adfb3db8323f447c7bf26dc534997c38b7fc977f642de288cdf253071cacf3564e3b8ed6dce57ddfba9ff783bad2e76df124828fc1031acfadf01a44d41b42161ad9060301c1af1928b9e5b73b9bd21cac60a842b504dc3cc311c522e3bb048bf221444f53ceb08e77e948590e94ed98f1b604cb9eadc93bbe7431c1149b23193ff93e8569f113e1684d8976ecae6f09e0103614be418a472ef55bb8890d72b341cdd7505b50a45522ab63ed791ce8f82feddd7a620a4f6fb1d2fb0ed0c4560d78446d83b3d1b1bb56b366d196020d0624b1fbdb75ce735dd43e8e8df163c44e236993dca341f5132d825d0a4e393a19d38f61e11e0cf392cb9b646ea23c58099824dd8d9fbe26a49e33b23df80607abf19715799c19acc722ed9bcf94a0c29ad24b78b0b035b3241c64cd86edeac810e66745694b5eb1625060edf2d949de0d34f522df2dc60ae694a193f3b82c1d6f83a0cbb840f46c49a3d7d1cf06deaf96c64f8f9e17bd9ad512ae6309c486d9e2a78dceeca473a0421dd1b643c78754271b53ce:30df7b0b1c04fb1efa3517e928d6d57c2ca0d07f4e04ffb1f08b4792c5937dd271ccabdc00dce850afe50af5990f224e8420a681d95f9f7f515afec102efd10e6e35f6eaa2bfee06ea6f2b2f7ab15fa97c5180958af2e90af918adfb3db8323f447c7bf26dc534997c38b7fc977f642de288cdf253071cacf3564e3b8ed6dce57ddfba9ff783bad2e76df124828fc1031acfadf01a44d41b42161ad9060301c1af1928b9e5b73b9bd21cac60a842b504dc3cc311c522e3bb048bf221444f53ceb08e77e948590e94ed98f1b604cb9eadc93bbe7431c1149b23193ff93e8569f113e1684d8976ecae6f09e0103614be418a472ef55bb8890d72b341cdd7505b50a45522ab63ed791ce8f82feddd7a620a4f6fb1d2fb0ed0c4560d78446d83b3d1b1bb56b366d196020d0624b1fbdb75ce735dd43e8e8df163c44e236993dca341f5132d825d0a4e393a19d38f61e11e0cf392cb9b646ea23c58099824dd8d9fbe26a49e33b23df80607abf19715799c19acc722ed9bcf94a0c29ad24b78b0b035b3241c64cd86edeac810e66745694b5eb1625060edf2d949de0d34f522df2dc60ae694a193f3b82c1d6f83a0cbb840f46c49a3d7d1cf06deaf96c64f8f9e17bd9ad512ae6309c486d9e2a78dceeca473a0421dd1b643c78754271b53ce: +3a3d27970fe2acb6951edd5ca90dda0fc6dd229c0a56df6eb11a9c54d242dbbf564f0dc3dc4720e68e44dd16711e049e6112000098fa62a1b98c288042f7c3bd:564f0dc3dc4720e68e44dd16711e049e6112000098fa62a1b98c288042f7c3bd:4374f61c2cd88a3b8972249bfa79b36ab69e3ed484cc60e5d9541fa7686cf4eed1210c5d0dcf42dd25972501909193ca76ae6eb7f471d8bd0d5fb5a6b431bc3de0e0318d50514524de87c4b83005dfb41245fb1af79b84a97b83d3cac7ad7a53364e2e9b21c97b769bdc57f0703116168380f3cc883689eb4a7fa3b26dbe12bc28f8c40381af64df4b5361d174cf75acbd46428740b0d1322d32bbe94845215966ae588777a8c05336e352306d49278d328e496db65e9ecf6ce6405ed1c893490bc48c13a134e1fb6e80debe6d32fce6ef74783c8d77980a441a26aeb4fd83cc855352cedc188f5279ce211f744a40b23ce7ff24437a1dd3373ec5b290da1f94f43a07a3ffea5b5f67b52c196185bce9e9a858257fcd7a8ebaf9040ed091face5a155aa447fa15e12122d25e8fc36eaee2137c7b3aa30b7e3ff6cc86b6dcb9eaf49c9576f0f462008439cb1a3aba013e897a0faf994cb7d59ede5774bb144774f73ca30e6414a7cc7c74b20c51a1404ddc419ef7624593e9bcfb37c0a762eab68faca5863443e16edb759dbc8788732b9e4f59c11192c3fcc872af55f32d:22eb8ea0507349b6a0ace25cf9180cb08e0357b04502905fbe69b4e21b2bd94e22cfbdb851ae716a5c253c70d5e2b24ea78f35bc213292543d94e14110b241064374f61c2cd88a3b8972249bfa79b36ab69e3ed484cc60e5d9541fa7686cf4eed1210c5d0dcf42dd25972501909193ca76ae6eb7f471d8bd0d5fb5a6b431bc3de0e0318d50514524de87c4b83005dfb41245fb1af79b84a97b83d3cac7ad7a53364e2e9b21c97b769bdc57f0703116168380f3cc883689eb4a7fa3b26dbe12bc28f8c40381af64df4b5361d174cf75acbd46428740b0d1322d32bbe94845215966ae588777a8c05336e352306d49278d328e496db65e9ecf6ce6405ed1c893490bc48c13a134e1fb6e80debe6d32fce6ef74783c8d77980a441a26aeb4fd83cc855352cedc188f5279ce211f744a40b23ce7ff24437a1dd3373ec5b290da1f94f43a07a3ffea5b5f67b52c196185bce9e9a858257fcd7a8ebaf9040ed091face5a155aa447fa15e12122d25e8fc36eaee2137c7b3aa30b7e3ff6cc86b6dcb9eaf49c9576f0f462008439cb1a3aba013e897a0faf994cb7d59ede5774bb144774f73ca30e6414a7cc7c74b20c51a1404ddc419ef7624593e9bcfb37c0a762eab68faca5863443e16edb759dbc8788732b9e4f59c11192c3fcc872af55f32d: +06d498318da456242b9c3b9ab6d532a128fce044f53882682e9262149c165288413517aa63200a17173209a4b3e78ab9383cb4e39efd6794c46a2d13fafa99c0:413517aa63200a17173209a4b3e78ab9383cb4e39efd6794c46a2d13fafa99c0:3fe30ecd55077a6e50df54bb1bf1248bea4063e3fa755f65fcd1159ee046efd0eb5f2fbb38b5c00947c97dc879b36b9e536192286086d0dc12053610386174a7c56f22a85b73ff208c5944f393236c32415809da036e73cad8fc3c30378064a76afa930a3baae9aa357061a8c5e8e756a9cecf94b72df43facd88fa49cb4948c6368318a6b1e5cff52e587ecdfaefdb69081f28c2d13bf8eab81dbaa5e3728c4317fb793dd196bca0fe54a6c242cf26e2d129ba0d82a2c3a45bc8d1dfd6f54f8da4f5189c91ac214fdabf4c597381b2e5c40cc71fa7051cf2ea93906a37d57df12d5c7e5cd77c907e442566315bae51a2222d62e3f42d1767882637d66a1d5305ab4010a0e49c57def69dcea839e1b76a41135ba952cc424950e8d3aac19e1d93de7757c15ff9997b3d2a8613cd9a164781d1be331799fa6109cef614305a1958f62903c8c9ea0b23ba706d49c54baccc1e63cb4bf14785fc7b062a9800349bdb0bb927260b677b60f10e62c8780f3ebb5eb6ff0360263d457ab52fd1125c9ce046a95d89d287350c804cfd4ff2b2ddd18a9e13519f20b4d1e051af624640f:8250f76dc599c5128787e4f6d3da23173330ce3320dba959bd714cc8cc07c67945d63e75662c075e267460ab7bf561f24faae3b41dbf676899191e3b02b5af0a3fe30ecd55077a6e50df54bb1bf1248bea4063e3fa755f65fcd1159ee046efd0eb5f2fbb38b5c00947c97dc879b36b9e536192286086d0dc12053610386174a7c56f22a85b73ff208c5944f393236c32415809da036e73cad8fc3c30378064a76afa930a3baae9aa357061a8c5e8e756a9cecf94b72df43facd88fa49cb4948c6368318a6b1e5cff52e587ecdfaefdb69081f28c2d13bf8eab81dbaa5e3728c4317fb793dd196bca0fe54a6c242cf26e2d129ba0d82a2c3a45bc8d1dfd6f54f8da4f5189c91ac214fdabf4c597381b2e5c40cc71fa7051cf2ea93906a37d57df12d5c7e5cd77c907e442566315bae51a2222d62e3f42d1767882637d66a1d5305ab4010a0e49c57def69dcea839e1b76a41135ba952cc424950e8d3aac19e1d93de7757c15ff9997b3d2a8613cd9a164781d1be331799fa6109cef614305a1958f62903c8c9ea0b23ba706d49c54baccc1e63cb4bf14785fc7b062a9800349bdb0bb927260b677b60f10e62c8780f3ebb5eb6ff0360263d457ab52fd1125c9ce046a95d89d287350c804cfd4ff2b2ddd18a9e13519f20b4d1e051af624640f: +8e8e1db5b1102e22a95c47af3661469f000a33f13b8b87b115d2452a411f6f3956d7b3169a95c22998ec937925bd7cad13cc65808cd5d34a6c4da870eaf32364:56d7b3169a95c22998ec937925bd7cad13cc65808cd5d34a6c4da870eaf32364:b24634fbdd1b7661315d9dc153ba90d66a88622a4158f8bcff25ba9c29e65f297f8e60311800b7331b69fc20c9f85bb7c184bd4086b3a9f9a27102b62362bdb4fa5b201594250fc628fd2e0e0d1be03dcf818c6094c4c29121cb2bf6d908ed8aab427c3771c0c95f0ac1469a0810b603a470282e5980a60729197fe6c20ef681cd1b96932d2058f896ea7416422a7e541f224a5f04253080741c5d4e3eb039db6ba051b4ca5417ce8afdc70214ba4dcc85b623d11e681c6009aee4e6130a83edd0d2c99fb0647e11ede7301ae56b59904ef7025732cde038801ec7e8d90a9a1bba047fe628351b3b89d0bc5ae665a700891f09ebeec05591842adfcc25adc3c71c1ebc4a312e5471be67253b0e9428b0cae37645a0f7ecb89dd79fbd9be2875433667ae07d74a7983c4cea601e72e975c21df993e7fa22a9fabd45455d45e37031558e13a7a4f5f497ea78fb7399f8838c0fd5de4ebb66db290f43a4867d505309f1c1bc27e9fabcbba71302fc1204715ce3fcb0905bfa411c9d1c9ab4a39954e50b8e0cf736c10289563bdfa967553c36cd9e555bc8cc56be594847de9f26f9:f6ee5e13cfaa362c8971d5a4a879a7e36966525ccd86c5a48cba08d913ece1a79c4cd146b8e9c65125fbadf17bac1cabcde8fd17cfd68fa1f9c44ea61c08a405b24634fbdd1b7661315d9dc153ba90d66a88622a4158f8bcff25ba9c29e65f297f8e60311800b7331b69fc20c9f85bb7c184bd4086b3a9f9a27102b62362bdb4fa5b201594250fc628fd2e0e0d1be03dcf818c6094c4c29121cb2bf6d908ed8aab427c3771c0c95f0ac1469a0810b603a470282e5980a60729197fe6c20ef681cd1b96932d2058f896ea7416422a7e541f224a5f04253080741c5d4e3eb039db6ba051b4ca5417ce8afdc70214ba4dcc85b623d11e681c6009aee4e6130a83edd0d2c99fb0647e11ede7301ae56b59904ef7025732cde038801ec7e8d90a9a1bba047fe628351b3b89d0bc5ae665a700891f09ebeec05591842adfcc25adc3c71c1ebc4a312e5471be67253b0e9428b0cae37645a0f7ecb89dd79fbd9be2875433667ae07d74a7983c4cea601e72e975c21df993e7fa22a9fabd45455d45e37031558e13a7a4f5f497ea78fb7399f8838c0fd5de4ebb66db290f43a4867d505309f1c1bc27e9fabcbba71302fc1204715ce3fcb0905bfa411c9d1c9ab4a39954e50b8e0cf736c10289563bdfa967553c36cd9e555bc8cc56be594847de9f26f9: +3884b8b79abfd3be6c13985eb859ab743f157cd9deb81b2fe97ea4d6173e46f5bd7fd9a8def13a542ed2f2fb048886885ba9b5ce59cb7019fb54667986eebc26:bd7fd9a8def13a542ed2f2fb048886885ba9b5ce59cb7019fb54667986eebc26:12adafe30eaf2b9c7203ca5d44b97ffed4bf6517a49988e4e676c8e314adbdbe23d8f2d3e2b081a7024fa525ab5aae26e60057c101e8f368d3addb9376c4682c1f4224d7f149a8474bb9a8f663ef210e9572ce829da388d8aae72a467141adc153473be3653baaa64b5b1e2e30683f6f06dac2784d5bbf0d082aab47305ed8a8efd0886ce63a179315225d1e4d4ffcf1f24ac2f464cf5ed3a8b6d3998454f1c02cdbf0a444ee2b59ddbe0a174a0d937fa62865088ac647499957d281c6949803a5fbdfdd0dd9e91b6976861f3c5f2126f39aac935be09f4b9715bd4f0d5c55df73a6b9f2c0ad26ce49d822bf85bfa2346f3165b03859a71c3d2a7b86db6e9f2e5d7b169a910eeb7ef38fbdfbbec43a9a25f04bc3acfd3b0691542ab6de9db6f03058f9584024f9918edecd90fbb85735d6dcec5bd593ae63e2cc96553599a310f8f2009ba95371196b4d5b80e7559637f22926778be5e1ccef5126e2443fa939c2a53dddb04961eefd34e538cd8d7f0bec2bff1ef0d3a4bdd358317637f42d595538c1122251a94e963d1f81e7b9aeb164f95da9a4ed7529b845ebc961b27b5c19:f4206fcd34502441d54a73323f33a5dbb4c98557319f21246f260ffbbe5844886db567f4b63c47943dbb78fc35657d7c04d4feb042ff8536f672925c319efb0912adafe30eaf2b9c7203ca5d44b97ffed4bf6517a49988e4e676c8e314adbdbe23d8f2d3e2b081a7024fa525ab5aae26e60057c101e8f368d3addb9376c4682c1f4224d7f149a8474bb9a8f663ef210e9572ce829da388d8aae72a467141adc153473be3653baaa64b5b1e2e30683f6f06dac2784d5bbf0d082aab47305ed8a8efd0886ce63a179315225d1e4d4ffcf1f24ac2f464cf5ed3a8b6d3998454f1c02cdbf0a444ee2b59ddbe0a174a0d937fa62865088ac647499957d281c6949803a5fbdfdd0dd9e91b6976861f3c5f2126f39aac935be09f4b9715bd4f0d5c55df73a6b9f2c0ad26ce49d822bf85bfa2346f3165b03859a71c3d2a7b86db6e9f2e5d7b169a910eeb7ef38fbdfbbec43a9a25f04bc3acfd3b0691542ab6de9db6f03058f9584024f9918edecd90fbb85735d6dcec5bd593ae63e2cc96553599a310f8f2009ba95371196b4d5b80e7559637f22926778be5e1ccef5126e2443fa939c2a53dddb04961eefd34e538cd8d7f0bec2bff1ef0d3a4bdd358317637f42d595538c1122251a94e963d1f81e7b9aeb164f95da9a4ed7529b845ebc961b27b5c19: +ecd519f287ad395052b0b30deac341d2a9df13d6567c891c813a0c9ca52e871e8ee94c588e0b343585fc6748fd1b54b5770c64e9937a56357a48d44ae2f51824:8ee94c588e0b343585fc6748fd1b54b5770c64e9937a56357a48d44ae2f51824:aa71be5f557e10c9fb5f091a3a274453947c07a0e25b26f9509224541dff76f4d96effd0d5a41d319bc9321a86667d55cf49432fb5c3e715388f3f106c9174b1610c8f3075d5931c290099385ce9249e235128e907c53390036fbf5da968f8d012336958de90c5e8e6b1016ad43fb57c8e288dafe14e90e64b63791e5cbe557e02df8ac9370642a71faf851075e5565f6f9a267f4f6b454ce4c5474810b804844dda38392939719793246aa47454b9b0e82e9803c09935d0027f3995cca9713069bb31027f7b2af12fe5feec7eeb06843d8296ec5682262a07dae747ed7bc821ec17018d899fd167b36a7e3773b427499d99dc583bbe4b429afa6a26593953f943e4673bdd0d2a844256131603cd0903256f334d4f8ec82de115b6ca5338c75c8baa44b4ba963c7c78510d8de9b2a5852f42f3463c685fb3a6da61a8e0892662d6a250fcaa6fef74d450fc457b9871d08bb5be3011294ac888fce215d535c3b1a43bb47efe3ad25da159191aed55195469c59093ffb24f65d60c4020bfbe647ff5db7ab8a01d5e487b0b1b64ef25da156db142e6ad872a4dc1ee9ba668465265379e:e8f51be73fc4e0235aa153a2e1b354e9c5d2d33a11ae0e333478de1d8e6c4456d2e250824c3246ca0e8d6ae3e16677a97344144108c13b959e1daf51cf0fe501aa71be5f557e10c9fb5f091a3a274453947c07a0e25b26f9509224541dff76f4d96effd0d5a41d319bc9321a86667d55cf49432fb5c3e715388f3f106c9174b1610c8f3075d5931c290099385ce9249e235128e907c53390036fbf5da968f8d012336958de90c5e8e6b1016ad43fb57c8e288dafe14e90e64b63791e5cbe557e02df8ac9370642a71faf851075e5565f6f9a267f4f6b454ce4c5474810b804844dda38392939719793246aa47454b9b0e82e9803c09935d0027f3995cca9713069bb31027f7b2af12fe5feec7eeb06843d8296ec5682262a07dae747ed7bc821ec17018d899fd167b36a7e3773b427499d99dc583bbe4b429afa6a26593953f943e4673bdd0d2a844256131603cd0903256f334d4f8ec82de115b6ca5338c75c8baa44b4ba963c7c78510d8de9b2a5852f42f3463c685fb3a6da61a8e0892662d6a250fcaa6fef74d450fc457b9871d08bb5be3011294ac888fce215d535c3b1a43bb47efe3ad25da159191aed55195469c59093ffb24f65d60c4020bfbe647ff5db7ab8a01d5e487b0b1b64ef25da156db142e6ad872a4dc1ee9ba668465265379e: +193f3c630f0c855b529f34a44e944970f4a6972e6c3859359c2e0c8762ba9eaf3256f2c82e7c801201210140569faf18507e60338c2cc4118bb1ce605b0ebe61:3256f2c82e7c801201210140569faf18507e60338c2cc4118bb1ce605b0ebe61:98623f651698085bde02762e8c3321f14da1619b5c3f7c1a568e8c26ff0c62fdcc412475912eb8e8c4b0d30918b8ffeef3509315e58da359cdc2f26bebfb5703953be16b8f3beb1e54a1abee0aebe24e64dbe873402e156f37dfc168eaf8a114ce08a6795d3f64f5151e9a8b8275cc7b49a6b8d8a66b6d4b7632ef80740dc1c1b0a38d1a28f7c1b29fa44541c1aad354d4590c231dae687a2a8fed09e8c1ebbfcc38f347bf06d94577e49ad139f710ed8bb1fd07663c0320846fbb455ab837ef964ae7d4eceea45fd7bd8d509f821e6eb027494efd8dd8e992b88698eec2ebc5e03025be789c18013f201f77aa2d34f5686460e43fb489e08776f98bcde2ceeb9d4fafdffe0375604371ec32f46b81fec474382908e9d250a0ba2780a7d6df407bd2b1eb126748d72511b9b069eb1cd44270f29fe84b9a717751831d04c2818e408f22789376c61c2ca45e32e788ead3a7536bf09da8af4703902f5516a020d89263e93701a2565eef1270418925f35a288e327bab628ac2f0248cfbca3482e265d1621cc343c31f65493f064bad0d7602460715fa486f29426346af53e333b75f5905:b12510ac5f2f6d33360cddc67291d6c270fd9ee62dc086b38d932d26473fe9a24efbd4248867ea7e915a30c5bfb3b8b19aa01aa2febf0dac6cfd6638a2ba7e0c98623f651698085bde02762e8c3321f14da1619b5c3f7c1a568e8c26ff0c62fdcc412475912eb8e8c4b0d30918b8ffeef3509315e58da359cdc2f26bebfb5703953be16b8f3beb1e54a1abee0aebe24e64dbe873402e156f37dfc168eaf8a114ce08a6795d3f64f5151e9a8b8275cc7b49a6b8d8a66b6d4b7632ef80740dc1c1b0a38d1a28f7c1b29fa44541c1aad354d4590c231dae687a2a8fed09e8c1ebbfcc38f347bf06d94577e49ad139f710ed8bb1fd07663c0320846fbb455ab837ef964ae7d4eceea45fd7bd8d509f821e6eb027494efd8dd8e992b88698eec2ebc5e03025be789c18013f201f77aa2d34f5686460e43fb489e08776f98bcde2ceeb9d4fafdffe0375604371ec32f46b81fec474382908e9d250a0ba2780a7d6df407bd2b1eb126748d72511b9b069eb1cd44270f29fe84b9a717751831d04c2818e408f22789376c61c2ca45e32e788ead3a7536bf09da8af4703902f5516a020d89263e93701a2565eef1270418925f35a288e327bab628ac2f0248cfbca3482e265d1621cc343c31f65493f064bad0d7602460715fa486f29426346af53e333b75f5905: +a88ad0048d38c44cebe735ea3802ca576e37121c7d4d760dfd88de1663064abb14dd8bb306803e5a758ed68ad21d07d88161d50f1c74713777da1209afbaea0b:14dd8bb306803e5a758ed68ad21d07d88161d50f1c74713777da1209afbaea0b:2ce8bca26178913b1676e90ffefd945bc561982660e2a75d482ff30aaba1ba43f82d2e6b909ec10fc09789ff5cf32a5180b601ea80fadece6d7e7baeef481dc6979e2f658ae0f6d8e416b93298f7d34031bb76f716ed991a16d09a582e58ba4003ac17be8b4469e1a889b2fbb2289e98af1c6d5bbee77756713c0778b0dc446a1f6c48c4d40818ec799905f069bc95341657ca5d02b7a539a13a02cd0376a50e8343c0dc20346de5275b1dcd4ad7af725131ac75e954825d30eaa57a68bb98dfc41cafe5710556647b387d9b7fd4e47651e5138050798f6d40f4ee7120b58f74da94d73cacbfd393d1347388ee00b79b8dbfeb57814121bdda60c627dce147d4d568d79052e97b9a5f3eb5407cc46461a55e18a960d8094a5fea48b6937529cc4ec919cdbedf9185456dc00e8d98ad1537ee10a057f4eec4b81dc60392fc9188d3e561785965092e44317f2a48e36605fc583fc173b05db9dcbc7557d06487390fbbba77af3a014e1ac35139caa1c53a8d17347f178e1c54d0f52b40e91042c93e7e481d792e288fc27e4c2fcf111fe97d9e2337d2fc1c3098f06684a31d55ebf362c027:1341a148da4593c88ebc5a58821eef77f92186390ff633e76207084e7874ccf0eb1f9ec70a3a3f96b58934bcb061ff920124f7e580fa2b0b279583adf9232d0c2ce8bca26178913b1676e90ffefd945bc561982660e2a75d482ff30aaba1ba43f82d2e6b909ec10fc09789ff5cf32a5180b601ea80fadece6d7e7baeef481dc6979e2f658ae0f6d8e416b93298f7d34031bb76f716ed991a16d09a582e58ba4003ac17be8b4469e1a889b2fbb2289e98af1c6d5bbee77756713c0778b0dc446a1f6c48c4d40818ec799905f069bc95341657ca5d02b7a539a13a02cd0376a50e8343c0dc20346de5275b1dcd4ad7af725131ac75e954825d30eaa57a68bb98dfc41cafe5710556647b387d9b7fd4e47651e5138050798f6d40f4ee7120b58f74da94d73cacbfd393d1347388ee00b79b8dbfeb57814121bdda60c627dce147d4d568d79052e97b9a5f3eb5407cc46461a55e18a960d8094a5fea48b6937529cc4ec919cdbedf9185456dc00e8d98ad1537ee10a057f4eec4b81dc60392fc9188d3e561785965092e44317f2a48e36605fc583fc173b05db9dcbc7557d06487390fbbba77af3a014e1ac35139caa1c53a8d17347f178e1c54d0f52b40e91042c93e7e481d792e288fc27e4c2fcf111fe97d9e2337d2fc1c3098f06684a31d55ebf362c027: +3f59d6a018f50a822117e5b473609e30cd64920ca1c2750dcb09eaab807a3eac457d0e59c11f348f3bfbdd3f327de78c0a7577c0aeef42d4c1e56700d108808b:457d0e59c11f348f3bfbdd3f327de78c0a7577c0aeef42d4c1e56700d108808b:7d103a6c6ba2d09087eef2254c1c903f067695a54c4515e4d13bc1fbfb54d6e7a167349c14809976da04a7e58d96b40aac3b2bdd14b9b50322bb11645f05e5e978bc7fbd02492ef88f87d668280fd708373207ff670fcda97df8485d5e46dc3bd04347f4d7527eab2718f7d93d132ba7758218894e75a7deabe693335ba0dc73bf26c288bfe9be8a736d75e5e0eaa7bbe8d0b77abdd5146e0fc9b30db9f07cf4bf36260a1f41410331f8b47c6b38338c6dc9e801ffe1d585f9b7fc31e9778bca3027c232c074cb18e5b72997005ffeee4bf37c8f874b1b246a6345415dacaca7075a60443ac3319236e23cf6b7544740807052114984b8d8f7e857dcc6faec8869cf96b997dfa9af9184ad623f1d90b8ca759b448eabfce18c17cfdf9a3e3312e63e5f084cea904c1c909913cc4b19d044a3720034973c7384949bd6f9ba9256f98cd394c566da83c31180109f16d10347b7e3e9dd6be3bd3c77ff1a7996a078dcf89dcdce2d1b615695f4cc9f8f4f2a08804641bca82662ce88faa53145b6a45955aec8cc2af81cccb5d7c64f9ece1c9983326484a1e5ece4ce36544d63735f7776f21a20:d7425ea194a6715c452ec4f6d6c76e6dd374d3ca7ae7a11995d02b942d4a31870dd734c12fca89a8eb0213eb139c14a87a6a33e818603b2e313023fa58737d0e7d103a6c6ba2d09087eef2254c1c903f067695a54c4515e4d13bc1fbfb54d6e7a167349c14809976da04a7e58d96b40aac3b2bdd14b9b50322bb11645f05e5e978bc7fbd02492ef88f87d668280fd708373207ff670fcda97df8485d5e46dc3bd04347f4d7527eab2718f7d93d132ba7758218894e75a7deabe693335ba0dc73bf26c288bfe9be8a736d75e5e0eaa7bbe8d0b77abdd5146e0fc9b30db9f07cf4bf36260a1f41410331f8b47c6b38338c6dc9e801ffe1d585f9b7fc31e9778bca3027c232c074cb18e5b72997005ffeee4bf37c8f874b1b246a6345415dacaca7075a60443ac3319236e23cf6b7544740807052114984b8d8f7e857dcc6faec8869cf96b997dfa9af9184ad623f1d90b8ca759b448eabfce18c17cfdf9a3e3312e63e5f084cea904c1c909913cc4b19d044a3720034973c7384949bd6f9ba9256f98cd394c566da83c31180109f16d10347b7e3e9dd6be3bd3c77ff1a7996a078dcf89dcdce2d1b615695f4cc9f8f4f2a08804641bca82662ce88faa53145b6a45955aec8cc2af81cccb5d7c64f9ece1c9983326484a1e5ece4ce36544d63735f7776f21a20: +a1212b34dbca63b7093612d05dab7b4cc8f7b676a934ad01f659851b3bb44e4eba2fccea9a080591be71268d7e951f250dedc00416e5f3f908db6cc571254925:ba2fccea9a080591be71268d7e951f250dedc00416e5f3f908db6cc571254925:07c37c46be3c68d05689577aa64a932b906446b29baf12f6174a6b42bbaefd1f1f373e0bccc473ddfcee1a7f21b96a6260ef0aa1f2d8b2959e71d12c953358a2774cc5e6f379a313e435ed69dfd6d4a59adee3cc7ec4bacbdbb3fee5430b73f6051a6096c60e9bc92cc8fa059fac2a93ef7007d64fbe50064964d5a0ad601175cd9caba453f9103b25485545d301f03c5f9f9478bdf9d414bf1dca3b1c1d9daa9971f9e617fbfaf5b02a7fbd5d4fb894c0975c54592b49a0fc85dd0853f30c51502d98fc1ab85a17cc58961aae9764570ba5cbdbc96dfceb8d11da53364b4025fe0b8ba8a353ad23686720169fe973432ffe291a4b11dedda0aac79a5e42620a64587d2059e787013b40ceec599208f66ed0ca6e1be9092ec27db216ee6dadfebc21705bc4a85aee577e57d239af586efeec22cf38d1cfb3cd74dd0d9a3381aa81e6a297e39b819137ad27d475e2bf54aa426dc29c4ca8176df343137a2d79d12ef9aa7be1cf6775e5d8a4430a85c33db61cd2f35187b4f6ea9ebdd753d1c4ef72471159ff07b77870906496249d4278e3f3ca6bcbf37a265b896539190f9a31f1e7b4b65cd1:fa93ed6595bc958dc042ce1645167b79e8f6734c46f80f631fd5484908f5e51a22427ee686f564ff982f6ef4d2ca1f0ca5624910cdd63c11a3c2b16d40973c0707c37c46be3c68d05689577aa64a932b906446b29baf12f6174a6b42bbaefd1f1f373e0bccc473ddfcee1a7f21b96a6260ef0aa1f2d8b2959e71d12c953358a2774cc5e6f379a313e435ed69dfd6d4a59adee3cc7ec4bacbdbb3fee5430b73f6051a6096c60e9bc92cc8fa059fac2a93ef7007d64fbe50064964d5a0ad601175cd9caba453f9103b25485545d301f03c5f9f9478bdf9d414bf1dca3b1c1d9daa9971f9e617fbfaf5b02a7fbd5d4fb894c0975c54592b49a0fc85dd0853f30c51502d98fc1ab85a17cc58961aae9764570ba5cbdbc96dfceb8d11da53364b4025fe0b8ba8a353ad23686720169fe973432ffe291a4b11dedda0aac79a5e42620a64587d2059e787013b40ceec599208f66ed0ca6e1be9092ec27db216ee6dadfebc21705bc4a85aee577e57d239af586efeec22cf38d1cfb3cd74dd0d9a3381aa81e6a297e39b819137ad27d475e2bf54aa426dc29c4ca8176df343137a2d79d12ef9aa7be1cf6775e5d8a4430a85c33db61cd2f35187b4f6ea9ebdd753d1c4ef72471159ff07b77870906496249d4278e3f3ca6bcbf37a265b896539190f9a31f1e7b4b65cd1: +d9682086fe7dda30b87111060193d847566ab94cfd9c97ab6b43e7a8d3f793828b0b1372d88733ef7233f6379790d1e46e1e07e9d3fb8b0be252ed04c5fa163d:8b0b1372d88733ef7233f6379790d1e46e1e07e9d3fb8b0be252ed04c5fa163d:e8814be124be3c63cc9adb03af493d442ff20d8b200b20cd249367f417f9a9d893fbbbe85a642be2701d1d1b3cd48a85cf58f159a197273143a578f42e8bcc8b6240f93271900538ffc187c0afc8dbcc492bcd679baaef3af5088434a94586f94b49970bba18f5ea0ebf0d27ee482aa83ad0dd0ee609df59d37f818b2c8d7c15f0f6f544dd4c7e7cb3a16724324f77d58948f8475a60d53e5bd510c17137c99e1cfa515af9bc85569d212a21190729f2817de8c46915e021df70ff6d60215f614fc21139904df3b292b749dc4dea02518b62d15862c92d2a4c996701cdecaed84ab628ee984fc111eecb59e48444efc0d456e2c852518441c3db7630ddd5156249a28730983838ae59ac4cc7110fd6de68101ea5b2ff69fd364e3c9448defefe175bcbe117cc11b4ff7549c33e1025b6b592048a8e31969e818dcc188bb19d7a2440a3baba4eb1b81c45679db46b31bcde7776757d9931ec2063fc6f1fcd761ecc57a7d030a85ea273ef1825b05092ab9645359a444ff7d166b575fac298308d9faa68463d1d0f7b7df8a51c6815d37159adc0b593224a818321d7219f09686cfc952259718dfc:1793e497eb521ca74e35d14a63868cbe9499da2f21b4eb5260340fca3c1feca78dbe5b14ac10f3fa76fa2e71e4c91461aa75977e5e70792670ef7ff0e6a28708e8814be124be3c63cc9adb03af493d442ff20d8b200b20cd249367f417f9a9d893fbbbe85a642be2701d1d1b3cd48a85cf58f159a197273143a578f42e8bcc8b6240f93271900538ffc187c0afc8dbcc492bcd679baaef3af5088434a94586f94b49970bba18f5ea0ebf0d27ee482aa83ad0dd0ee609df59d37f818b2c8d7c15f0f6f544dd4c7e7cb3a16724324f77d58948f8475a60d53e5bd510c17137c99e1cfa515af9bc85569d212a21190729f2817de8c46915e021df70ff6d60215f614fc21139904df3b292b749dc4dea02518b62d15862c92d2a4c996701cdecaed84ab628ee984fc111eecb59e48444efc0d456e2c852518441c3db7630ddd5156249a28730983838ae59ac4cc7110fd6de68101ea5b2ff69fd364e3c9448defefe175bcbe117cc11b4ff7549c33e1025b6b592048a8e31969e818dcc188bb19d7a2440a3baba4eb1b81c45679db46b31bcde7776757d9931ec2063fc6f1fcd761ecc57a7d030a85ea273ef1825b05092ab9645359a444ff7d166b575fac298308d9faa68463d1d0f7b7df8a51c6815d37159adc0b593224a818321d7219f09686cfc952259718dfc: +b52b249a7aeae0fbd94ffcf9a9fde10de61c3f4cbda14b289fe01f82707334ca735163bfcfd54f9d352e1c2f3c0170c95c1842ccc7421623ae0496980cee791c:735163bfcfd54f9d352e1c2f3c0170c95c1842ccc7421623ae0496980cee791c:1d445e8ee36f6e1064ee1281e6b4a4cec50a91c2b667c8305d1e9a5f7b73a3445882581fb0c11e64f6ee92e811f9f2d6c59c6344be7691d116dda493cade51c0ce77372b61a7c4fbb633401333cbf71372ad2f044e992ac035f5879c053004f8223f237a24a409b7894f6ad518e046b8a84c3f4c6260e6169fd944d57fbcf9ba2775f2d60ed772c46ccd63c850b80d587c5208dfb1a25878c02dece3e602e9632fc3c2c79b25ab41034c6e26b869255357a686781dfe6e644beba9b627da1fcb5ec0be497cf188e1ef1af0601bf16b2911fd9ff34f0e97ac95a7fe2cf90ea6ced33ccb0ed1ef2d4160efb07c591a5cb16c70ca1694fb36f2ca19eba52be3d4ad895abcada4b36f0261d65f59e0cfd2a6148a8892ddbb45810db3bf4a9e26e92c15ea2618cfeeb462d8628f254f54d2af27113bab4f9a7d06791811942bdc32f845922d7b2ddba959140928f8c28d98b44e1d19b97fd39cc0f9a5236d349fc835ac492192462e40ac629bebffd2eba72d2788b244bb777ad0f7b7f96f23412399fc1d87a1d087ba089027eabbc05edafee43379e893291331b460bfa7332e0842ec2573393de95306:6f48a9f7f0fa192b66d12175a333612303e180b9fab18edabebcdf6674fdfcc53607089bf980ce35894c2f9babdc4438667ab3297a6248ec0269faa99c7248071d445e8ee36f6e1064ee1281e6b4a4cec50a91c2b667c8305d1e9a5f7b73a3445882581fb0c11e64f6ee92e811f9f2d6c59c6344be7691d116dda493cade51c0ce77372b61a7c4fbb633401333cbf71372ad2f044e992ac035f5879c053004f8223f237a24a409b7894f6ad518e046b8a84c3f4c6260e6169fd944d57fbcf9ba2775f2d60ed772c46ccd63c850b80d587c5208dfb1a25878c02dece3e602e9632fc3c2c79b25ab41034c6e26b869255357a686781dfe6e644beba9b627da1fcb5ec0be497cf188e1ef1af0601bf16b2911fd9ff34f0e97ac95a7fe2cf90ea6ced33ccb0ed1ef2d4160efb07c591a5cb16c70ca1694fb36f2ca19eba52be3d4ad895abcada4b36f0261d65f59e0cfd2a6148a8892ddbb45810db3bf4a9e26e92c15ea2618cfeeb462d8628f254f54d2af27113bab4f9a7d06791811942bdc32f845922d7b2ddba959140928f8c28d98b44e1d19b97fd39cc0f9a5236d349fc835ac492192462e40ac629bebffd2eba72d2788b244bb777ad0f7b7f96f23412399fc1d87a1d087ba089027eabbc05edafee43379e893291331b460bfa7332e0842ec2573393de95306: +782a93efe0ef06cb2534330efd0e9684e9969b5258123e490239bf24bf9f6523942fa1406ee2683e29377e49f7ba757cf50ef0723707d4403d2862257045de87:942fa1406ee2683e29377e49f7ba757cf50ef0723707d4403d2862257045de87:46a4e319a670ac993994a53300c3f79144c2f7fec1116eeeb3621c76ac35da79dbff6e189ca9dbfc9abbda054847b2971b02facebbe926d469eb0a860389ac744162bf6fb13b42cb9bb8c9d72607138e7800121ee0cd633ed535c7ae5f4060bbdd271c9d110abff5e060ea6ee83890b1e92a9256d7b2ba982a3114bb6deffee2696f0a2f9c21aaa5b2defa11aab7076de6e57e86f284bb67f5a49ee685921032c95b74e7e3eac723f175af082c858e0dfa01728c38fbbb4c83581f81ace6c63c6bdaac5620eb9a568e7ebb7b72b3d1a164ef524e7b9f00799ab086715976c14d0df65f7b96bf9ebcda7feeef113422001a03a7633df5e49939a121db899d9b8ac2db4fad0c30cf0b8bdbc9e9802a797c8238e46511ff24068cadcff2448cc0bff92769223348d45d6b6f2c8f1593388c0bbbf44b6ddb50b98cd7f09c730f7de4d008156cb3cde0cab3ad0a58a83954e234a0a8a04b573c9a8e9b929ed38b8b228bf55a3c6e2c6b51f682652fbb708e74640e3313e17b4694d7fdf0111f90608c1b5af422dcdecad9ddb7f50d1bf5bc6378ccaffc3201e6c787b48c443ba240d9d50ff6c0e9df7f1a5b:93e7405a4044510166c8ac264ce3b5ba6665d68bad458712dc93c2c390568d7402ef7d57f549b8a1042f7f69a679aa855f34f801d57d79895deb8deadb35230846a4e319a670ac993994a53300c3f79144c2f7fec1116eeeb3621c76ac35da79dbff6e189ca9dbfc9abbda054847b2971b02facebbe926d469eb0a860389ac744162bf6fb13b42cb9bb8c9d72607138e7800121ee0cd633ed535c7ae5f4060bbdd271c9d110abff5e060ea6ee83890b1e92a9256d7b2ba982a3114bb6deffee2696f0a2f9c21aaa5b2defa11aab7076de6e57e86f284bb67f5a49ee685921032c95b74e7e3eac723f175af082c858e0dfa01728c38fbbb4c83581f81ace6c63c6bdaac5620eb9a568e7ebb7b72b3d1a164ef524e7b9f00799ab086715976c14d0df65f7b96bf9ebcda7feeef113422001a03a7633df5e49939a121db899d9b8ac2db4fad0c30cf0b8bdbc9e9802a797c8238e46511ff24068cadcff2448cc0bff92769223348d45d6b6f2c8f1593388c0bbbf44b6ddb50b98cd7f09c730f7de4d008156cb3cde0cab3ad0a58a83954e234a0a8a04b573c9a8e9b929ed38b8b228bf55a3c6e2c6b51f682652fbb708e74640e3313e17b4694d7fdf0111f90608c1b5af422dcdecad9ddb7f50d1bf5bc6378ccaffc3201e6c787b48c443ba240d9d50ff6c0e9df7f1a5b: +6fe7bcf7a684423de1076fd76da783423373b381329efd6157424ec4b2655a947740e91afe45324f8bb990ca2a341279ddaf232c3bb415f178b6092fba195fec:7740e91afe45324f8bb990ca2a341279ddaf232c3bb415f178b6092fba195fec:0baf0ad440612b4c5a136c3a42be1ca2b7c319862a44a9fd50c4ee73541c5e6457efa81825b6dd4a72194a2968688bd49e5a8f4c04dbafc2e7884c0c70c208d4e954cd1675da8e74c65c497cf9dc69424965bdcba5de52936f925f62e201f99505d3777beb3c2e08b2ec9a873e5a9c21fb4a2f3e861f3cf4d6b5dcd1c88bcd9163539ac62cd0659f4ef232c2ce57fc77f90285eb350169edc6a806ff50f61c7e0beeebecec63bfc9d3983f5bb4b261c746471fcbf2892c6108970b68db5e43c4504ddae2d0ffffa28b6759ae1128e16f66d492ad61e3722c960f88692be81a9f412890ffa346e702c867dfa259703b73f525074f3227c49cec1b645a103bd4471f33f9f1bac327d7917861d0ad91abee60222ea2a3c8cac052ae9a2cbd90855d733d5319133f9541bd0b61f0995268351e2863c1ca2ca51e3c976383f5c4c11ff410036fd51d5ac56b023ce9029c620f22557019ad9b4264ed4d71b434f4a4d17a7d5769fa1e14a69f7ae419ccf5947f8c7682697116c2405f5a1959c54b48f0872f596ed45964488ddec12bdb636d0b349e749eb66092ff4511fba59b5962cb93cc85515cc86ab0c6b2:9914cc50fef0935efb89b3d64e3c1c3412aed659b90166222c0d13ec1ce3a68ae6281b7efd9d4ec64b82e73e14479f03fbac8fa3abdb41ea4215c4a4d4949d090baf0ad440612b4c5a136c3a42be1ca2b7c319862a44a9fd50c4ee73541c5e6457efa81825b6dd4a72194a2968688bd49e5a8f4c04dbafc2e7884c0c70c208d4e954cd1675da8e74c65c497cf9dc69424965bdcba5de52936f925f62e201f99505d3777beb3c2e08b2ec9a873e5a9c21fb4a2f3e861f3cf4d6b5dcd1c88bcd9163539ac62cd0659f4ef232c2ce57fc77f90285eb350169edc6a806ff50f61c7e0beeebecec63bfc9d3983f5bb4b261c746471fcbf2892c6108970b68db5e43c4504ddae2d0ffffa28b6759ae1128e16f66d492ad61e3722c960f88692be81a9f412890ffa346e702c867dfa259703b73f525074f3227c49cec1b645a103bd4471f33f9f1bac327d7917861d0ad91abee60222ea2a3c8cac052ae9a2cbd90855d733d5319133f9541bd0b61f0995268351e2863c1ca2ca51e3c976383f5c4c11ff410036fd51d5ac56b023ce9029c620f22557019ad9b4264ed4d71b434f4a4d17a7d5769fa1e14a69f7ae419ccf5947f8c7682697116c2405f5a1959c54b48f0872f596ed45964488ddec12bdb636d0b349e749eb66092ff4511fba59b5962cb93cc85515cc86ab0c6b2: +dda48a0d15a29eba9a76305d360e466e72d8040efe2e89c04b6461315a9b8bf44f5cc36a809416b58e15d24cc57968cb573b76ad90887a8ef36cde7eca400fcc:4f5cc36a809416b58e15d24cc57968cb573b76ad90887a8ef36cde7eca400fcc:f5ac19b81f2111a0db0ae30d1513ed343e7f57f7f77d65b8ac7ce3a601174baed9bfa136035976f516d5a870f45db1919f1eb1cbecbe88ec32d191e9248821a7e7681fe3abec11584bdb33de1b4ca94891eb66dcb8539ac41163736ccfd69abb83814dd38cd60381318728052a25cb665471058650ccc75756dbee688ab826ecad4ad5a7db57e8f65f1b64abff82dd53334b797ac40228dd817f239d3ee804a19aeac8cfe33eb657ec9ce923d6b388914cfba2e72bfc2bc3d6f985c0d97534db958eede57b16491ffb755c1a58d78ab377faec0d311818e899260e3ebd1ccd29246fa82d0b76622b2c4bc52f549fee72a30f554f331f36d2a74d999ec10a08294f002b4361e590279c2fb1bda4312ccb24d75282ce7c061a0ca5520c74f6f6333b18c4b541cb6c51e01575ba80512ffa7ce0accd22d14027c53aba1f7437835f1114d68e3acf3ff8de94c8e4ef6d3ab312c91d02970157508f54a5816f467a214e9b1284300289e65f365a610a8ea284666cfe5518e435bccd21627501c725f0b8eb5725e0e06e0cef5db201b48ec91ebf878dd57ce8dac7334848a1bc82c18b065955e4f59be3398594dc:ce71bc82d531d0f93b57bfdc2f7316cf404ee09af88f33bf806c7cad6b8ffa366236ba74e75c15096ddaa6e3a62a8f5eb1c8c3f6b6c94a6a349fc7c0cbfb190df5ac19b81f2111a0db0ae30d1513ed343e7f57f7f77d65b8ac7ce3a601174baed9bfa136035976f516d5a870f45db1919f1eb1cbecbe88ec32d191e9248821a7e7681fe3abec11584bdb33de1b4ca94891eb66dcb8539ac41163736ccfd69abb83814dd38cd60381318728052a25cb665471058650ccc75756dbee688ab826ecad4ad5a7db57e8f65f1b64abff82dd53334b797ac40228dd817f239d3ee804a19aeac8cfe33eb657ec9ce923d6b388914cfba2e72bfc2bc3d6f985c0d97534db958eede57b16491ffb755c1a58d78ab377faec0d311818e899260e3ebd1ccd29246fa82d0b76622b2c4bc52f549fee72a30f554f331f36d2a74d999ec10a08294f002b4361e590279c2fb1bda4312ccb24d75282ce7c061a0ca5520c74f6f6333b18c4b541cb6c51e01575ba80512ffa7ce0accd22d14027c53aba1f7437835f1114d68e3acf3ff8de94c8e4ef6d3ab312c91d02970157508f54a5816f467a214e9b1284300289e65f365a610a8ea284666cfe5518e435bccd21627501c725f0b8eb5725e0e06e0cef5db201b48ec91ebf878dd57ce8dac7334848a1bc82c18b065955e4f59be3398594dc: +ec57b941adf3ca13e77a780577cfd0df5b49edc85351052da34e99f8a9bf32082859c071978a04b7f5407b6d22401a78efd0394bb966b9a04da6b5ef819de3fa:2859c071978a04b7f5407b6d22401a78efd0394bb966b9a04da6b5ef819de3fa:d2bcbd1bc361ab32c66d72fd48a8e227dc6b8d6b150848ba715ff47dd35c8e49381bb4e2933f42cd26b75b14d9c0039282b62b8556aaa11cd691e828382be306889fc9205137b169d3bf17b7f37693fce286039f03809d7d9d98c8fde46f1101942a279c516706f50191a9112f6a24630e1a26c321e46c9ccc85b6ef942f353a642b9e7ef998c0fce2d3a75b999eeb77f31f9b0813a97e3014c3a86e2558734621a3066dae35845031e35665f1922907dbb739786a8b7658ab60276f2d921d1a51230fc74d19e80184a4f10e9e834abc9a36c429726bc055dc8c063f0eca9c61a8a970bd4bb5f424ee4d04bfc295e3bb1f34becbd9920fe2e77fcf36763f32fc9cfd5e465979c167cabf5a1244b491fc06b8946419046ba516c5b233c414ddefb6da04f2e13daff7a9a0c02a518ede57ad9521de64eddf6f49a9670f632d3f7d42425207d053604fe39d13b9f52c8bc292b0076ea42a560056df25de51ad35881d08543224d7fa5d70b8603ef23ce06339d6cd09e22a95749e50dfbd3b8ad69fd30496b984d1c0a199c8594805f38ba44631a2c59eadc6554d19f9bc98366dfdec2a121d0e4814d2cd3f5871:118e1462126b45b8c6803523755c56dfc4e123e4acbb66ba0ba6fe3e053da4119f5719295e0c82ac64d7c5cb1ac898df263ddfd360f3008d91018b26f6a1730ad2bcbd1bc361ab32c66d72fd48a8e227dc6b8d6b150848ba715ff47dd35c8e49381bb4e2933f42cd26b75b14d9c0039282b62b8556aaa11cd691e828382be306889fc9205137b169d3bf17b7f37693fce286039f03809d7d9d98c8fde46f1101942a279c516706f50191a9112f6a24630e1a26c321e46c9ccc85b6ef942f353a642b9e7ef998c0fce2d3a75b999eeb77f31f9b0813a97e3014c3a86e2558734621a3066dae35845031e35665f1922907dbb739786a8b7658ab60276f2d921d1a51230fc74d19e80184a4f10e9e834abc9a36c429726bc055dc8c063f0eca9c61a8a970bd4bb5f424ee4d04bfc295e3bb1f34becbd9920fe2e77fcf36763f32fc9cfd5e465979c167cabf5a1244b491fc06b8946419046ba516c5b233c414ddefb6da04f2e13daff7a9a0c02a518ede57ad9521de64eddf6f49a9670f632d3f7d42425207d053604fe39d13b9f52c8bc292b0076ea42a560056df25de51ad35881d08543224d7fa5d70b8603ef23ce06339d6cd09e22a95749e50dfbd3b8ad69fd30496b984d1c0a199c8594805f38ba44631a2c59eadc6554d19f9bc98366dfdec2a121d0e4814d2cd3f5871: +cbfd91d7695c1f270f69246ab3df90edb21401101ca7f8f26c6d00f4dcb7233e513879cf79d2f46df4b85a5c0949eb2116abf981735a303164cbd85adf20b752:513879cf79d2f46df4b85a5c0949eb2116abf981735a303164cbd85adf20b752:264a933f7d0aecbac13eef644b0b53dd53a1280904100dbc1ab87b51148998f9da0b3a0a6337f5e3486c2b7e548d211259397aaa194ee4695bf98c2d5f4487699f7397e5d3a7e6d5f628fbd05497c556a50a4d05e2b712cdbc351068e42af19538901b8825310e343e1a17a1867dde0eb47ddab456d316f3521554937bf808ae4e4bc1c3c5b4756e4a165ad9e8827f5316f748cac6998ed2d2104f268407c135e62f26a922460eab6d851639a00e5f08b34765ea0244f475bbfeac183e3b5bd1aab798522798a08ec6bf2257d4692f5b03cdd0a2133de970603e3251475aad8d934af6b2bfc7a650b91bdec143f8ad254cfa506bbff28a03beb659ef5e5ddffe76e23230c4ccd46310b37dd91fa6aa68167f62a55c8a69f9ed1ec6cdb144dd81ab0bcbd62643420bcae67869f64c0b169f3cdf3c905895b7d35b6fafda25ccf23c3d10de32e7f271e300d39597da8f843722ef08364a5f7a105b9655172df7c82d7374f98264c9cdccb496f2e10fd8262fb1a9a9965b0b841ac0d0e9c1a3d9493ea7aa600205b8f900be0d7abb4d98a06583d2295c276318be28d421982dedd5bfc33b8865d94ef747d626af99:f336137dfe6f42a6669b55f74b80b3035a040367f90656fcef0a644c52272ddc39273cd7726010ebcd8a30a05201ab70b8ff97d0288a2cb94cbc49020647390b264a933f7d0aecbac13eef644b0b53dd53a1280904100dbc1ab87b51148998f9da0b3a0a6337f5e3486c2b7e548d211259397aaa194ee4695bf98c2d5f4487699f7397e5d3a7e6d5f628fbd05497c556a50a4d05e2b712cdbc351068e42af19538901b8825310e343e1a17a1867dde0eb47ddab456d316f3521554937bf808ae4e4bc1c3c5b4756e4a165ad9e8827f5316f748cac6998ed2d2104f268407c135e62f26a922460eab6d851639a00e5f08b34765ea0244f475bbfeac183e3b5bd1aab798522798a08ec6bf2257d4692f5b03cdd0a2133de970603e3251475aad8d934af6b2bfc7a650b91bdec143f8ad254cfa506bbff28a03beb659ef5e5ddffe76e23230c4ccd46310b37dd91fa6aa68167f62a55c8a69f9ed1ec6cdb144dd81ab0bcbd62643420bcae67869f64c0b169f3cdf3c905895b7d35b6fafda25ccf23c3d10de32e7f271e300d39597da8f843722ef08364a5f7a105b9655172df7c82d7374f98264c9cdccb496f2e10fd8262fb1a9a9965b0b841ac0d0e9c1a3d9493ea7aa600205b8f900be0d7abb4d98a06583d2295c276318be28d421982dedd5bfc33b8865d94ef747d626af99: +51a4197ab7686f82f6003a0c32f39d0f2e47555f4e9f8deee75bcb1bd1ef69e506386df86b61f1f8f4dc45b73edaa841920968bbd131cc5ca1c5294eeed5c8ba:06386df86b61f1f8f4dc45b73edaa841920968bbd131cc5ca1c5294eeed5c8ba:2aedb7e82f1fe4ce469ada48345d006d1b3bff40eb21867f51fce965640c409ec13ad4d52f891bd79066d6b4d944ca868d8986d242b57eccc4c4a488291b159c8de4392be4b86febaa75eac5d22d3c4f8d6bef79adb9b92b4914d5ea07c7f021e2c29f58d07be8a084100bc152d51ca897d7c131644d0895322e9440a8339e1aa390a7f4fcb51ddfb6df48aaf5676337d87ddd85b1d925e1a9c29fe0818f514ef72f747a674946476907a7ca99e9db8d209641057a7f44a317b90974bc86f9617a968a76a6b8387cf5853e608190c1a79f1e1d686e0de22db6cd9aeb8532c5c85cc90b5a018579f28e502a770a4ec675263d0dd781b4fa53c9dbf8098d57b33ae2afbaeb3e68266ad9aab7174ba68c6479883992670ccf3e5ac6a17e65e31e1fdc85e269c80935ef574f20d239568486e7d94a4f724ab7006098b24f3f61587691435c7f29ce4e5ca71b2b1874556433a358c8c5ef3c880843030c2d13d51b78c9bf1a8824e62e111844396f5af2e25c3126ef3626e26efafacf99830aa41212332f378a167233a0b42213afe36d83dc4582a79693b9d571a57712a08b8566d361ac902647afc886603e24283efb:2c072969ff4719212a121938b506c602995b4d02a22e6198d6e87dd6ae076225ac70bb25ef8c0ee81eb6fe953df6b1815949e8ed0506cb012e873cd36cd09b0a2aedb7e82f1fe4ce469ada48345d006d1b3bff40eb21867f51fce965640c409ec13ad4d52f891bd79066d6b4d944ca868d8986d242b57eccc4c4a488291b159c8de4392be4b86febaa75eac5d22d3c4f8d6bef79adb9b92b4914d5ea07c7f021e2c29f58d07be8a084100bc152d51ca897d7c131644d0895322e9440a8339e1aa390a7f4fcb51ddfb6df48aaf5676337d87ddd85b1d925e1a9c29fe0818f514ef72f747a674946476907a7ca99e9db8d209641057a7f44a317b90974bc86f9617a968a76a6b8387cf5853e608190c1a79f1e1d686e0de22db6cd9aeb8532c5c85cc90b5a018579f28e502a770a4ec675263d0dd781b4fa53c9dbf8098d57b33ae2afbaeb3e68266ad9aab7174ba68c6479883992670ccf3e5ac6a17e65e31e1fdc85e269c80935ef574f20d239568486e7d94a4f724ab7006098b24f3f61587691435c7f29ce4e5ca71b2b1874556433a358c8c5ef3c880843030c2d13d51b78c9bf1a8824e62e111844396f5af2e25c3126ef3626e26efafacf99830aa41212332f378a167233a0b42213afe36d83dc4582a79693b9d571a57712a08b8566d361ac902647afc886603e24283efb: +b1119c36118b7a065a195bfb8b79a5c287e09bd287c2daac5e6b01164c5d737f88f218ecba99e770ed214a8d01a92a10400acaf1f6eed420067e136ee2c0c670:88f218ecba99e770ed214a8d01a92a10400acaf1f6eed420067e136ee2c0c670:8816b1eb206d5f6dcc2e4cc391d23209006de935e318152e93fc8c2cf08e26432bad9adb3203d898df0a2e7f1f83dc2f3ed3205bec8efcfd31adc1aca5755db9bd4efe54cc17073077de4a3fdd11996e84b6a052f034b41099226c9c272eae12528f16581b91b812850c207144dbff3e850cca848ec2b1dd164744d7b59337d7e3efef008162e680bd4a0899ced60b171f8cbeb48c5158df6cbfdb26240881bd58ebb8b6a079587279679cb5ad82f371b53c8013804c35596c887e436d23926f994e09d98fbb8ce2704174ef38b68262a7f1a712da0ef0dec639606814b3bdcaf253ff31c48e8a752c111bd7101031cc3d38efb0c9c7f19c59081584a0e015ee7c75b10a4c51ff543a30e52d5f94d8188c6b08e9df1e84a4e2c807170ac124a771b99465a0d38b1f1c6330403c82543582c5bb61b220de1b9e0ef69bdae26023181ba4cc077a5f0d425732ace132ae0c6ff0bb18baea83e8877afbe650fe0bd02093f00a7b5365728dcb66fbb881f592945058a5b350665af91c557a547250ad295e68b4fb72457cfb9d5ea1a7b2a39c9ab7d7ace0af5d51669cb6c2c4c07b2256d10e5ffc6b97c660006313c4eb8d:24ec1e54fc7e722d37551d02cf135d33f5d3ff535773e02991ee85ffd3aa29997f9c464470197fee81dce110609f870b27c18dfbcfd9320548525e93148e22058816b1eb206d5f6dcc2e4cc391d23209006de935e318152e93fc8c2cf08e26432bad9adb3203d898df0a2e7f1f83dc2f3ed3205bec8efcfd31adc1aca5755db9bd4efe54cc17073077de4a3fdd11996e84b6a052f034b41099226c9c272eae12528f16581b91b812850c207144dbff3e850cca848ec2b1dd164744d7b59337d7e3efef008162e680bd4a0899ced60b171f8cbeb48c5158df6cbfdb26240881bd58ebb8b6a079587279679cb5ad82f371b53c8013804c35596c887e436d23926f994e09d98fbb8ce2704174ef38b68262a7f1a712da0ef0dec639606814b3bdcaf253ff31c48e8a752c111bd7101031cc3d38efb0c9c7f19c59081584a0e015ee7c75b10a4c51ff543a30e52d5f94d8188c6b08e9df1e84a4e2c807170ac124a771b99465a0d38b1f1c6330403c82543582c5bb61b220de1b9e0ef69bdae26023181ba4cc077a5f0d425732ace132ae0c6ff0bb18baea83e8877afbe650fe0bd02093f00a7b5365728dcb66fbb881f592945058a5b350665af91c557a547250ad295e68b4fb72457cfb9d5ea1a7b2a39c9ab7d7ace0af5d51669cb6c2c4c07b2256d10e5ffc6b97c660006313c4eb8d: +cbb587514e0a34ffc34cbc04f28c9b4f6465f1eb225cca19b864876daef37d7f6b705d4677d2d849b6744b1ebed167dbcbf645924b1ff2e6360794bdd0e09788:6b705d4677d2d849b6744b1ebed167dbcbf645924b1ff2e6360794bdd0e09788:bdf7d17c706796efd3489559b527b1c0584b9022c9cbda3aac5146da340d9cea69f916037cd21b3eb1104348880fd5c5b7c65ff820f7499346016951cb715d8df2b41c88cd3c66105458b7b590c21c1ae2f6ea9ddea7470f25e02027d171e0e574a2bb21642f8f9da508e21d8e7335b5ace5935299407bd1b01bdd1423133ef045234e701f55549434ade94a60be1e1406ca5c758c36799ce1703084476e484fb1740530aee84266d07adfb4cc689f3265133a59cdf992fbb9a4b12defbe241ddbf65d12b2fbddfc05af0fb8de42080775bad29c6b0459841cbb648a9a95e48d6e36ac514480a3deb4b36554d8da620808ae9d47329710d20aaa6e5d7f547d81ad30f84c0e3d239cde5b169d9ddf294832d67a8060ba329c4ef39be94ac46434dd2185931d1231f9b6df878a5af0831e0e9d8a08d08069ded6a961ef7f39fad501ffd17d6d9b7c654653c1f58fcee1a6cd803d2aef166c78ef5514a3276d6998dc7c09a3fa982e427c785aa6a9e256f7ba72d5a6ba33eb46f1f9fe9be2bfc14109f64773c00c063b4d5cb4f4f8a0beca92a9a016c4f540feea9c3a31e313bbcbc2ff5eca9967857f5f8a909a29d7f20d:1274d6f356eb641472b6b9e5b3ce65d2654e6cb87d3a83fb49d0f7da9c44be2b532604465f6089d680d2d94b0edd2b6b2b805c5e84c379efc059673d31007a09bdf7d17c706796efd3489559b527b1c0584b9022c9cbda3aac5146da340d9cea69f916037cd21b3eb1104348880fd5c5b7c65ff820f7499346016951cb715d8df2b41c88cd3c66105458b7b590c21c1ae2f6ea9ddea7470f25e02027d171e0e574a2bb21642f8f9da508e21d8e7335b5ace5935299407bd1b01bdd1423133ef045234e701f55549434ade94a60be1e1406ca5c758c36799ce1703084476e484fb1740530aee84266d07adfb4cc689f3265133a59cdf992fbb9a4b12defbe241ddbf65d12b2fbddfc05af0fb8de42080775bad29c6b0459841cbb648a9a95e48d6e36ac514480a3deb4b36554d8da620808ae9d47329710d20aaa6e5d7f547d81ad30f84c0e3d239cde5b169d9ddf294832d67a8060ba329c4ef39be94ac46434dd2185931d1231f9b6df878a5af0831e0e9d8a08d08069ded6a961ef7f39fad501ffd17d6d9b7c654653c1f58fcee1a6cd803d2aef166c78ef5514a3276d6998dc7c09a3fa982e427c785aa6a9e256f7ba72d5a6ba33eb46f1f9fe9be2bfc14109f64773c00c063b4d5cb4f4f8a0beca92a9a016c4f540feea9c3a31e313bbcbc2ff5eca9967857f5f8a909a29d7f20d: +8bde3ff61a16995ab9d539f6053219081bcaea1d458ec33684fc1c01fb565bfacd9d782a356e847b7a04c885a9b0907cc33ba97ad5390d4ea5fee5eb198d08b3:cd9d782a356e847b7a04c885a9b0907cc33ba97ad5390d4ea5fee5eb198d08b3:a1f40ec5807e7a27069a43b1aebff583ef037028c02c859525eb8fa4c3ba95a901ff3aed78c4f87752fb795522f5bf715be7e3defac10fcf17e3fa5c54b20089a472333327252ec945718fb455e3f27ccfdef823d12d406e62a4aeba3cb9d1c61b2b17e49e200a8418f935f26eeb57602c7aa3b3a24f7e6238d3e08d2d609f2eada0332bc8cb12916cb03b0d4f9cd602002586d3e4cc7e0e0381c045ad2e1ee28298ae7fcf0c10f212808565296f158d2c32e8cb28156581af52bfc3470c3c9582138d2255e8426d648ca237d7aad2856f171638558241d8ae3f62ba92db596568edee3ec0ef370f83626aa0445af08f967863660e8fba5a41c8e8ede1c960514a14687a4a81e776ae0e8e777fb0f250d51a83b55f8c1ffdd78df3bdc97ff177afeca046c72d72af924ad0d0ab2bfc11b7f4abded51c3987a8bb94d640c8710e5fc9a4190e8a008363d7419cea17c40dea20ea5156029f3debf05241918f54af5039e2c4cf2ca2e139f60e45cc65595cdf54a67d92b6ac66fc0c5a290495ca57b07ef5750d05f57d87d0c228f7e4e15ad0ba0178730f951c697583481c66cbfcd48032544aa8d50908304bd81940308706:7464df0b67eb90b4b73ff082ad0d60ebfe0660dae97069b52c3727223bf70e29e48711a2bbb438f5f8d8a33bb9c48fe7b628fa8a542ff0b5ae36269d4007a505a1f40ec5807e7a27069a43b1aebff583ef037028c02c859525eb8fa4c3ba95a901ff3aed78c4f87752fb795522f5bf715be7e3defac10fcf17e3fa5c54b20089a472333327252ec945718fb455e3f27ccfdef823d12d406e62a4aeba3cb9d1c61b2b17e49e200a8418f935f26eeb57602c7aa3b3a24f7e6238d3e08d2d609f2eada0332bc8cb12916cb03b0d4f9cd602002586d3e4cc7e0e0381c045ad2e1ee28298ae7fcf0c10f212808565296f158d2c32e8cb28156581af52bfc3470c3c9582138d2255e8426d648ca237d7aad2856f171638558241d8ae3f62ba92db596568edee3ec0ef370f83626aa0445af08f967863660e8fba5a41c8e8ede1c960514a14687a4a81e776ae0e8e777fb0f250d51a83b55f8c1ffdd78df3bdc97ff177afeca046c72d72af924ad0d0ab2bfc11b7f4abded51c3987a8bb94d640c8710e5fc9a4190e8a008363d7419cea17c40dea20ea5156029f3debf05241918f54af5039e2c4cf2ca2e139f60e45cc65595cdf54a67d92b6ac66fc0c5a290495ca57b07ef5750d05f57d87d0c228f7e4e15ad0ba0178730f951c697583481c66cbfcd48032544aa8d50908304bd81940308706: +da59bbc523404f07646add7908294977e46645bc8a38bad2809641a23de3b15ab22c0f21aa1c2d45f4b2e56cc9b5e02f9e31a2eaa367ecb482f874cbd8e9fe34:b22c0f21aa1c2d45f4b2e56cc9b5e02f9e31a2eaa367ecb482f874cbd8e9fe34:097106c3624d774dde2551e0c27e19504e6518cc86369ab26ff810969e7de24abc68b4b53f11d945d49ef078eb4f6ba6bf257ff7b608afdcb30a5c59a756fd77a6c1247f6f2a41100d99fc5206af3bcc6de1d3e4968e28fba0123f6045a1b54d693a42bdfa071b2b914b3c3c0c29b2593d07e8bdc86ca42ac555b7dcd9439df9fbd4bbec730d6327bfae4fc41ed498b4f04a0eb14cee608283aaa6e6aa46676bc88aed5d9939037aad4915661af94bb5f6e653a2cac123287073270e0b13fda1dd4871af6a92f992f539df881712fefb038540d41191123b6b3b4b6ff87ffc929a6be53c6cef02f48f2f0cf2fe64a45fd66025cc2d7ee55ebe2316c000855661165e2a5ba41afc2097957b6fe4c55221204b6fc1f317dd3ba13cac39924026bdb66be4542268875631d277f210107a33767f6d9596e25742d7a90ea791ea4bc9ee84a67fd328b80f791ede96d89663e937f0b755baa9d52bda210cee1db339ff1d3c4b000b653b9bde338049af84364e2177f80dd51e2a1672ee555d6317589f6f1d5abe6c2877358bf94b0b808ff857363fbfbe32e97337e4b8a8c221a9e75962a8dc9b5a3d7ca5f9c9b61c73c1469a72bd:1472459cbbae2cf21ce44a15bae9fc85dca40b8182da7d52cbf56ed538d18e03477c140a3ddd0efba43c96aa92f5f9bcdf3481286ce762a7e2bd1e779ba99b0d097106c3624d774dde2551e0c27e19504e6518cc86369ab26ff810969e7de24abc68b4b53f11d945d49ef078eb4f6ba6bf257ff7b608afdcb30a5c59a756fd77a6c1247f6f2a41100d99fc5206af3bcc6de1d3e4968e28fba0123f6045a1b54d693a42bdfa071b2b914b3c3c0c29b2593d07e8bdc86ca42ac555b7dcd9439df9fbd4bbec730d6327bfae4fc41ed498b4f04a0eb14cee608283aaa6e6aa46676bc88aed5d9939037aad4915661af94bb5f6e653a2cac123287073270e0b13fda1dd4871af6a92f992f539df881712fefb038540d41191123b6b3b4b6ff87ffc929a6be53c6cef02f48f2f0cf2fe64a45fd66025cc2d7ee55ebe2316c000855661165e2a5ba41afc2097957b6fe4c55221204b6fc1f317dd3ba13cac39924026bdb66be4542268875631d277f210107a33767f6d9596e25742d7a90ea791ea4bc9ee84a67fd328b80f791ede96d89663e937f0b755baa9d52bda210cee1db339ff1d3c4b000b653b9bde338049af84364e2177f80dd51e2a1672ee555d6317589f6f1d5abe6c2877358bf94b0b808ff857363fbfbe32e97337e4b8a8c221a9e75962a8dc9b5a3d7ca5f9c9b61c73c1469a72bd: +40ea82da41fd15b06ffeb99cd616dc6bc8c1b21477ea239466088e2849bf10165910e580bf412c31a87451d9ddf32b3ab713f9e4a22c590c641c14a5dfbbe0d7:5910e580bf412c31a87451d9ddf32b3ab713f9e4a22c590c641c14a5dfbbe0d7:a06c4e02b83ab7e191ad818cb8187b52a8da004fe838db333c4e02548db6bdf791444642e57fdbc8594e59d7023280bbae82986f399805434bb072c8a27a2dcd5aa62f065bc58b0621fcd365f6cdbf4d57d577d91150301fa48f182f87e8dca7ce45a7d64845ff434d1bab0534ccc83aa0974e88b38fc2508cefcbbc82135b73b384c80eccb8a09e2873cc07129021d81ce129a9df65e613410af950197dbf9afc28edc4e65c3e84da40d2ef841b886bc44719a5d59db2c6dc776401c895e2b3c83783d7817bba68baff59470d6015bba8d975f0eb712f3b8902912805523aa71c90499de689d31ae44e210b8446f2484727cc491b92a8e8b199d628e1df79a28c561e5a7d882e30787d08fb2d5196ba61196309b3bf0c5824a3548c700003fe9913befe12223150012685e90720e9ec6bc4db607425aec531c4fa36086d3b9be391a3f04635a8077a447a16a6fd89afbb9a72d0d355cb0b22d562f43f59d4e37128b3e2d906c8ae23d0aa599c70d3778a076c1a39728f1d6937bd48b978740850566138d34852b63075e89a8e2280edba6f4ee8f61511e9b768e95c78d197b693b109e88818b486a9dfdb74b4c5550acdfbd5:d298fcc9a8ecb76a98d4a71dfb01d276ab2d9670a95bab34cf1d8364516d1ebdb23903460215307125afd09c758e981a452da95c0ac2c0b958c6917e6874190da06c4e02b83ab7e191ad818cb8187b52a8da004fe838db333c4e02548db6bdf791444642e57fdbc8594e59d7023280bbae82986f399805434bb072c8a27a2dcd5aa62f065bc58b0621fcd365f6cdbf4d57d577d91150301fa48f182f87e8dca7ce45a7d64845ff434d1bab0534ccc83aa0974e88b38fc2508cefcbbc82135b73b384c80eccb8a09e2873cc07129021d81ce129a9df65e613410af950197dbf9afc28edc4e65c3e84da40d2ef841b886bc44719a5d59db2c6dc776401c895e2b3c83783d7817bba68baff59470d6015bba8d975f0eb712f3b8902912805523aa71c90499de689d31ae44e210b8446f2484727cc491b92a8e8b199d628e1df79a28c561e5a7d882e30787d08fb2d5196ba61196309b3bf0c5824a3548c700003fe9913befe12223150012685e90720e9ec6bc4db607425aec531c4fa36086d3b9be391a3f04635a8077a447a16a6fd89afbb9a72d0d355cb0b22d562f43f59d4e37128b3e2d906c8ae23d0aa599c70d3778a076c1a39728f1d6937bd48b978740850566138d34852b63075e89a8e2280edba6f4ee8f61511e9b768e95c78d197b693b109e88818b486a9dfdb74b4c5550acdfbd5: +28bb81a17d4584754d52818cd0f1f21baa777e695844a15122ac05344dddc027d5f61d519944d13b84bfa7cd67cb0bea4ef2281efa461f22ade4ba882d11b252:d5f61d519944d13b84bfa7cd67cb0bea4ef2281efa461f22ade4ba882d11b252:92e84c7a55b0bea03e17cfb65f7085ce3f445b1542bae997de5f092a24ff243380286d137091a598f35e6dae1a1c648f5a494c819dfb240652ff908381f32d70bc513100aca16fe7220295b1c71835f16d9310a9d27a04a980ace297d5af3f7cb7c78b24997ccb41f54ecbab507eb73ea6a3ed470e49590509f5d1e6032a2605db87f4a9b9ec91602583f14e2fe1bdb900ecb8971196b55c0d433489f26be9ca157cbd56572887ba859f39674a8e0ca08f2dbb0f27073551d0b1990685178b1ae9e7885499143d9d72c8571d11e0d85bf58df94e2a74d9b6846557f9125ca0944ce5718d2cbae1672ba02b847c17a6f6b445634d2f0175a75cf6883c62e5b521c57141f218b2fb0994b372a716c4a217434beab75740b8e91c622187d03c85da001e00247312a465225f5d6af232064a427d3018700ded774b9026777a5275fc04754606c86600297bf7b71aaff8b9a746677a3662f3750e81b50166f6237000051ffa15868defdf090057722ae229964a4ea085e0dbc04ce1997722c5bb65d2b47ecb746fd83a9f6a69c81545a9b502f5e76d3130c5afcb1c9af99d918740837ce89d7cd213fef2fd062ce8850f69659e4ad327:9ce45a07dbd28d3f6f1b35630a3fd56f1d548f84ffb1c6ae64b21498ae38e596916e77f79905e609fb1ae0da36138a80f242122167068092cc605796c5669e0692e84c7a55b0bea03e17cfb65f7085ce3f445b1542bae997de5f092a24ff243380286d137091a598f35e6dae1a1c648f5a494c819dfb240652ff908381f32d70bc513100aca16fe7220295b1c71835f16d9310a9d27a04a980ace297d5af3f7cb7c78b24997ccb41f54ecbab507eb73ea6a3ed470e49590509f5d1e6032a2605db87f4a9b9ec91602583f14e2fe1bdb900ecb8971196b55c0d433489f26be9ca157cbd56572887ba859f39674a8e0ca08f2dbb0f27073551d0b1990685178b1ae9e7885499143d9d72c8571d11e0d85bf58df94e2a74d9b6846557f9125ca0944ce5718d2cbae1672ba02b847c17a6f6b445634d2f0175a75cf6883c62e5b521c57141f218b2fb0994b372a716c4a217434beab75740b8e91c622187d03c85da001e00247312a465225f5d6af232064a427d3018700ded774b9026777a5275fc04754606c86600297bf7b71aaff8b9a746677a3662f3750e81b50166f6237000051ffa15868defdf090057722ae229964a4ea085e0dbc04ce1997722c5bb65d2b47ecb746fd83a9f6a69c81545a9b502f5e76d3130c5afcb1c9af99d918740837ce89d7cd213fef2fd062ce8850f69659e4ad327: +24bfd4fc45d5093585678101cf563ab8011fd6430de155f2a425f0633ee3b7cd9cf5c5fc0ccfaeb28a08ba67707b18dc84ea0698ffbdbc169a09c28123e6c2ac:9cf5c5fc0ccfaeb28a08ba67707b18dc84ea0698ffbdbc169a09c28123e6c2ac:ba54128f45be2001dbb060d5dcc47144997415d4294f6eba8dceba4f6cf2234683c4265f88032205296e9b27d68506232d57b688407648f87ceb342052bde9d0065542ff1715c942027e67482af4bc278ff71966fb3f62a2a5323cb1b4bae1e7b8fedcbc73ea05b4076421b0b4fae8bc3337416a17fe124e7ee465ebb38d8792306429d8279a1bd54c37bee8f9c85eebe3afd1f64489d4e53ac5f50657bb6ffb97120744b75d47c6226d5a9c9c264ee3e6a6ded05062ca1006669118454550010919c2633cf086950345e514af3843148e5c64352e69037dfe60d4a8eab3eb8cb54bd39af2f353d5ded2e2bc8b11c09f612e128c6efa41f6eb2c958087be34c6335a43005d11a9d3b5a529c2d1b0642f77afdd8c6b1d6fb2a9dcb65f42f4eca8ea9a054058be8613667610e3eed8d1df0739eca171954117989d1b12189ab57904aa960b0ca85541746385efa985be9d97b5a9029989a9c71498dfabdb813681f57e276b64db491b8f082a885145469a531b7f9f04ca0a2c2f8dff20ccb99c2861f54e5eafa962cc53eaf18d3d5e50d337af485f19975f05930700a8a7253f11f184130d0aee70969d96fe08f216951d9dced52388:dc935b60fde44359af8f50ed7f919f483ce3f24e2320c55ba92f3e7617c19bfb54701903ff183b42cbedfef0875f42b12875d36a0aeec73ffd09509d92b28b0dba54128f45be2001dbb060d5dcc47144997415d4294f6eba8dceba4f6cf2234683c4265f88032205296e9b27d68506232d57b688407648f87ceb342052bde9d0065542ff1715c942027e67482af4bc278ff71966fb3f62a2a5323cb1b4bae1e7b8fedcbc73ea05b4076421b0b4fae8bc3337416a17fe124e7ee465ebb38d8792306429d8279a1bd54c37bee8f9c85eebe3afd1f64489d4e53ac5f50657bb6ffb97120744b75d47c6226d5a9c9c264ee3e6a6ded05062ca1006669118454550010919c2633cf086950345e514af3843148e5c64352e69037dfe60d4a8eab3eb8cb54bd39af2f353d5ded2e2bc8b11c09f612e128c6efa41f6eb2c958087be34c6335a43005d11a9d3b5a529c2d1b0642f77afdd8c6b1d6fb2a9dcb65f42f4eca8ea9a054058be8613667610e3eed8d1df0739eca171954117989d1b12189ab57904aa960b0ca85541746385efa985be9d97b5a9029989a9c71498dfabdb813681f57e276b64db491b8f082a885145469a531b7f9f04ca0a2c2f8dff20ccb99c2861f54e5eafa962cc53eaf18d3d5e50d337af485f19975f05930700a8a7253f11f184130d0aee70969d96fe08f216951d9dced52388: +2fc2f9b2050ad7d139273e93e2a0451c7b5cce57599aa6b08d3edc5bb07590c8ffe5a17880d718cc7988c2fd9825b03b93450ac1deb8fbd1f1bf3b8f87805954:ffe5a17880d718cc7988c2fd9825b03b93450ac1deb8fbd1f1bf3b8f87805954:dc1297990cc027d56d1fee265c09bcf207a9583e6bab8d32478228e0bc305b9818154c338ceec34b04c4ade7ac61dcb09bfac8ade00d1f29de317060b8a4daf1987de409ca2c3fe4380088073ccf485e9a69516b5bbb4130f20be69b2dd6a9b465159cca1ac88b328b80c51b66af7f4c50f6228772f28734693ce4805a4163dff14b4d039811ee3fce65935444a6ea9a72d78b915c9c3b766c60b7e0329e43c9c57ede94b91525ce5a075a7297219772ef3c029649b586a95a73bbdf16d8fc20368de4ba44de1064be5826b376be31a86ca478a52efb98f1fa333157719bd6e0da80ed68d0efeafee5a13bcc3b457525258f1f7e031f7b403a461506927b1e6c7d4a0c8d84b5f3dd0eb8bdb13edc2b514a81d088eb077a52c8a831861feee8110e41a325dce206b2d67d25f90ef57e0fde709f3e5a39c04eed31e57c193b283e2da7279ee3f1eed482b3bbcd373902c1df811ac33e1de06429e8f8443f602019650bdc2ee8d7f650036a7a22b8fd88517511229c729a3269b3a3e8fc72b01b5a4b3e33f5272f3ad21629d08b1f717935e9e104add2f0f2033432bec82e2121d98c9c1a58e0daba25536a1be8e5088347f4a14e48d8e3:7aff162a3c0d28dff41715a974af07ecac2132fc18bc43a198fe664659050da19ae22758d52c9cbb94f1358bb02610a8a351c2116279e7245adf69675dfd360adc1297990cc027d56d1fee265c09bcf207a9583e6bab8d32478228e0bc305b9818154c338ceec34b04c4ade7ac61dcb09bfac8ade00d1f29de317060b8a4daf1987de409ca2c3fe4380088073ccf485e9a69516b5bbb4130f20be69b2dd6a9b465159cca1ac88b328b80c51b66af7f4c50f6228772f28734693ce4805a4163dff14b4d039811ee3fce65935444a6ea9a72d78b915c9c3b766c60b7e0329e43c9c57ede94b91525ce5a075a7297219772ef3c029649b586a95a73bbdf16d8fc20368de4ba44de1064be5826b376be31a86ca478a52efb98f1fa333157719bd6e0da80ed68d0efeafee5a13bcc3b457525258f1f7e031f7b403a461506927b1e6c7d4a0c8d84b5f3dd0eb8bdb13edc2b514a81d088eb077a52c8a831861feee8110e41a325dce206b2d67d25f90ef57e0fde709f3e5a39c04eed31e57c193b283e2da7279ee3f1eed482b3bbcd373902c1df811ac33e1de06429e8f8443f602019650bdc2ee8d7f650036a7a22b8fd88517511229c729a3269b3a3e8fc72b01b5a4b3e33f5272f3ad21629d08b1f717935e9e104add2f0f2033432bec82e2121d98c9c1a58e0daba25536a1be8e5088347f4a14e48d8e3: +8afe33a0c08aa3487a97df9f01f05b23277df0bb7e4ce39522aec3d17816e467d004370e6edc34b3e8818667216f5b226b0ff75a58484c8616e1a866444cab57:d004370e6edc34b3e8818667216f5b226b0ff75a58484c8616e1a866444cab57:86fb741f1b9708929195031aa1645fb709a8ae323fff85e5470194452e11b7b1279194b5e2427ce23e1d749c3ddf910b017e4f2dff86dbe482c91bd994e8493f2e6824bba3bc7d7a845f217ae9760b3cd00226d9ff2616d452751a90c3d0d3c36d4ab4b2520f67288171bd3a34b2eacae8d44c1e153dda1f90bcd3595dad37713b8d340156ea90a4e135951ba7169ac175578b81e97a541ab9bfb76328798d7d631c14df2ad613e9c6e1147a0e84062ddba035859d46bade5fadd9b32b43dad483c6b8023b32391e51ef1520c68c6191326c494423080c623dc4ad0aa074748d826c29644c38986a77002f0cab9068e6c9ec73cc2e0c584b80e0bc375721f7a8fc35317a5e240e8c66092fb6305b012c70e17aeaff13386d5e28d06430ca585b0c85b274e7fcbb63e3423a982579e5a64a0262c41908e55dbe43dac1e5cc1bb7298be428720a12e3b072559ec2675d457aaf8f13252e28aad63c1513f5f239564d363c8505ffa4e50f6648c1cb82bba852bff0acb030cbe73f059dd87bbd7318c5586e708618a4f4c9f3bec3f4f07c609eebb24ba878c6bf1e4f2d0fd1450ab94e31755217786fb15182760ffbe5a267cbe998a4ff90a2:63a8aeac025f2dde9a73286e56c2d62dcb79a241ba0b2e2dbaca8752ed2fc8cc7ab8e6600b67645fb5e818a4e82c29180a6b2c3f58d099cb635ce52bdc15700486fb741f1b9708929195031aa1645fb709a8ae323fff85e5470194452e11b7b1279194b5e2427ce23e1d749c3ddf910b017e4f2dff86dbe482c91bd994e8493f2e6824bba3bc7d7a845f217ae9760b3cd00226d9ff2616d452751a90c3d0d3c36d4ab4b2520f67288171bd3a34b2eacae8d44c1e153dda1f90bcd3595dad37713b8d340156ea90a4e135951ba7169ac175578b81e97a541ab9bfb76328798d7d631c14df2ad613e9c6e1147a0e84062ddba035859d46bade5fadd9b32b43dad483c6b8023b32391e51ef1520c68c6191326c494423080c623dc4ad0aa074748d826c29644c38986a77002f0cab9068e6c9ec73cc2e0c584b80e0bc375721f7a8fc35317a5e240e8c66092fb6305b012c70e17aeaff13386d5e28d06430ca585b0c85b274e7fcbb63e3423a982579e5a64a0262c41908e55dbe43dac1e5cc1bb7298be428720a12e3b072559ec2675d457aaf8f13252e28aad63c1513f5f239564d363c8505ffa4e50f6648c1cb82bba852bff0acb030cbe73f059dd87bbd7318c5586e708618a4f4c9f3bec3f4f07c609eebb24ba878c6bf1e4f2d0fd1450ab94e31755217786fb15182760ffbe5a267cbe998a4ff90a2: +6dc7ccf329378e8131b6defcd89370301068946336b0b762ac5ea51487dbd39e04e90d275e79df5f2b6ef4a31505aac05a69459baf2c581b3ce3db29f0f1fc14:04e90d275e79df5f2b6ef4a31505aac05a69459baf2c581b3ce3db29f0f1fc14:20cebbe98401ac8934c3e65a5738cb0ec0cdc75fdb09dc96312894b187c0a46d2c38f4855be3eeccdcdcc56d926a8c08ce6e748e2a858f53532e7e5fc5f7014c8c6f86310cc26efef30ae525a5157940ab535ed8e403112b08e35e2bb3dd91a9ae8f772d2aff37d8c40d2b5cc887a6f15050a0f5bcf0360c3a9d12d5918655edc3c13c86ba6f4a2fa3bfcd405ed38f871cf7dff0f75daf2c321084ee9fa81211adb105b25c2288f0f2f7f93ef656b2de190122e7a4bfd4a1bd9893a8485b509ff0bc46cc961051c1db5a12490c7e741922ccc0a665496470276f69c7b77098c1e670af6b9f851252996875eb8035a817fa9be07f2be0bbb12025e0565414c817e9421ac700373893862f24cb165f9a271a64fd2305c6672c46767f8f075be5d2d4079bfadc3956288b0215605311b5bf32f0037b7c5ad502013e82ae3419d9d8f39c545b5888f47106c94d5fd6084d26034a99f5dcbf26a84eb4ee149c62a0410d8c707b1a9b071f74ed23932585072ce6cbd33d4d54ee917916f5dfc64d26a498018438b455739345dd60ae0f4750625915cc829ab6822d6f05f6d2bda0a7bf5601e9a2ed6de960371d17e6f43709c9678ca743adfbdb45:04509db003a1a6ed3fbcec21ac44ec10cc06d79f2714960882170316275df80423a1c1a112d881fc24d2812526079058aa8b608bfc6b5e57632240c636d6eb0020cebbe98401ac8934c3e65a5738cb0ec0cdc75fdb09dc96312894b187c0a46d2c38f4855be3eeccdcdcc56d926a8c08ce6e748e2a858f53532e7e5fc5f7014c8c6f86310cc26efef30ae525a5157940ab535ed8e403112b08e35e2bb3dd91a9ae8f772d2aff37d8c40d2b5cc887a6f15050a0f5bcf0360c3a9d12d5918655edc3c13c86ba6f4a2fa3bfcd405ed38f871cf7dff0f75daf2c321084ee9fa81211adb105b25c2288f0f2f7f93ef656b2de190122e7a4bfd4a1bd9893a8485b509ff0bc46cc961051c1db5a12490c7e741922ccc0a665496470276f69c7b77098c1e670af6b9f851252996875eb8035a817fa9be07f2be0bbb12025e0565414c817e9421ac700373893862f24cb165f9a271a64fd2305c6672c46767f8f075be5d2d4079bfadc3956288b0215605311b5bf32f0037b7c5ad502013e82ae3419d9d8f39c545b5888f47106c94d5fd6084d26034a99f5dcbf26a84eb4ee149c62a0410d8c707b1a9b071f74ed23932585072ce6cbd33d4d54ee917916f5dfc64d26a498018438b455739345dd60ae0f4750625915cc829ab6822d6f05f6d2bda0a7bf5601e9a2ed6de960371d17e6f43709c9678ca743adfbdb45: +ccae07d2a021fe3e6ee23836a711b97b04e0a441f169607572731cb08c269488a32265e5328a4f49cf06b467a98b9f9d5b997b85dfb7523ca6a0a1d627d32891:a32265e5328a4f49cf06b467a98b9f9d5b997b85dfb7523ca6a0a1d627d32891:a4bf8297d0dc5e4c92bd00ad5b9c09b1238b503d619116ef74260378349a9282b41f3f4676a6215e3ce6d02238480a96043b2942b3feed12620b1fa97f7703b3eb683c1601bd2f51825c450df4fd1f33b0bf9c23c03223789e06e24cf136d3b557403a66981f4b777dcfe890d2ba96da4a4742aeeddd6a611d05fc215694a5d89a5de6760b1d9415155044c049cb02291a1514faa2e77d2ae33d44585bdac6365bf481d9c97833937eab636ed65742a0d5973b24d54089b2daf084d5414765105e4eca14aaadd1053338a8470505232e4ac633345c5cdee1e4653d1d93583af11854b1d9b65fc20281838c56df1148f35ccf9bfe2f3f80ab73f5b791cbed2d920644cf0316f0cb5d3662b9120647da56afbeb47a952953bc1a37de857e4b39fd92b632b85159f46cd05b6abc2338d4632d48e9a178860de8f65d9bc23f24507b7c5629e0bdaac067c476c9c3941d86f788944d744852a61da716f95f3b04f0783a562941bcdda439590fd186b2a8ebf19a5a7e4f4a3aaab7a87a434524fbc9799c9931eb8ce4e34e99b608cac94ab7e74495668df136185f487d9fbcb6605ad725345403ec57f3f6db364a87f38fea4b4c271552e9f2e4a1be:0eec754105447f97d4a9cd246c7eede3fd069018f0d01a41dfabca3e90a741835ea4a9d682342267b250fc1c8c547c89632d9f689af536c7929004ded0d96f09a4bf8297d0dc5e4c92bd00ad5b9c09b1238b503d619116ef74260378349a9282b41f3f4676a6215e3ce6d02238480a96043b2942b3feed12620b1fa97f7703b3eb683c1601bd2f51825c450df4fd1f33b0bf9c23c03223789e06e24cf136d3b557403a66981f4b777dcfe890d2ba96da4a4742aeeddd6a611d05fc215694a5d89a5de6760b1d9415155044c049cb02291a1514faa2e77d2ae33d44585bdac6365bf481d9c97833937eab636ed65742a0d5973b24d54089b2daf084d5414765105e4eca14aaadd1053338a8470505232e4ac633345c5cdee1e4653d1d93583af11854b1d9b65fc20281838c56df1148f35ccf9bfe2f3f80ab73f5b791cbed2d920644cf0316f0cb5d3662b9120647da56afbeb47a952953bc1a37de857e4b39fd92b632b85159f46cd05b6abc2338d4632d48e9a178860de8f65d9bc23f24507b7c5629e0bdaac067c476c9c3941d86f788944d744852a61da716f95f3b04f0783a562941bcdda439590fd186b2a8ebf19a5a7e4f4a3aaab7a87a434524fbc9799c9931eb8ce4e34e99b608cac94ab7e74495668df136185f487d9fbcb6605ad725345403ec57f3f6db364a87f38fea4b4c271552e9f2e4a1be: +db5d5f41fddd6768709747ab8239bb4f42a31d34b4fa88824d94bf78d314926403858ce6b2d24079eead66ca0dfe772ecda9af4d46bc9b5edfdc286b95fe9716:03858ce6b2d24079eead66ca0dfe772ecda9af4d46bc9b5edfdc286b95fe9716:67ee03de45c3e7030db5246ee5b51bf298bba3e4d0934937fc12d9a629604c53c070e30d611999a9cddaf2d9acda6a9f67202b352369d48260eebce0e78e4d5ae54f677521f84a7be0017fab278b2b57275efc5fa57c617186fc1ba49edfbd3308634878d864f2da1583ca8d56ce9fae77c462039abc32d0539c0a60b7bbba5029e9329d275683d9c4ce77d0b908ade98b0e32b4420d9aee2cc10e4be922f9572582dd8967141c1d402e215f20aee0a890e2368e406dea11bd11177f2e038aa2f1a0dff51a128d955d5e5f8d5d0009aaa82440a96864d6c697f910d1df230f467f0e02a2e02bf9e45da95f255410cc5aab8d85f449a5de99aabd44fd763ec14629f3dbab1a247bffb7174648e43b9fb1eb0df5e4109b7a88e05512b20865bad39f9ea79d52f5188e7ca5194405bfb1a09727617f3f6c88192008edbc0c6585dbf261f149dffb593d42716e5a5777f5462beeb1e9a56a2c76e6cb735117cc1183a38d1e00b303d174aa9cf5c731b2c70edd79cc5dc96f4018f1d71d7198bbb7d134cd2ff8c15f9a04280db26a8fa9997eb86b133c022eda15d8ad5e77cc9f62615960bac2f9bbc3ebbd198f72c572b97156fa7fa229a98014e170:5b3d0da7102355486be4d69cfd65886c9d9c8738b293cafb23b2104bfdac8d7d01298eeb18fde3ded6491d41b419cc663752c4e67dbe8986833d20e4ef34180b67ee03de45c3e7030db5246ee5b51bf298bba3e4d0934937fc12d9a629604c53c070e30d611999a9cddaf2d9acda6a9f67202b352369d48260eebce0e78e4d5ae54f677521f84a7be0017fab278b2b57275efc5fa57c617186fc1ba49edfbd3308634878d864f2da1583ca8d56ce9fae77c462039abc32d0539c0a60b7bbba5029e9329d275683d9c4ce77d0b908ade98b0e32b4420d9aee2cc10e4be922f9572582dd8967141c1d402e215f20aee0a890e2368e406dea11bd11177f2e038aa2f1a0dff51a128d955d5e5f8d5d0009aaa82440a96864d6c697f910d1df230f467f0e02a2e02bf9e45da95f255410cc5aab8d85f449a5de99aabd44fd763ec14629f3dbab1a247bffb7174648e43b9fb1eb0df5e4109b7a88e05512b20865bad39f9ea79d52f5188e7ca5194405bfb1a09727617f3f6c88192008edbc0c6585dbf261f149dffb593d42716e5a5777f5462beeb1e9a56a2c76e6cb735117cc1183a38d1e00b303d174aa9cf5c731b2c70edd79cc5dc96f4018f1d71d7198bbb7d134cd2ff8c15f9a04280db26a8fa9997eb86b133c022eda15d8ad5e77cc9f62615960bac2f9bbc3ebbd198f72c572b97156fa7fa229a98014e170: +7f048dfcc2650cda59491d4ce2b2533aecc89cc4b336885194b7ad917db5cd1408001b5d40958bcb270beea9baba3387e3a4b900fc42275657c6c691a2e264f2:08001b5d40958bcb270beea9baba3387e3a4b900fc42275657c6c691a2e264f2:917519cdb33519680bcae04faa790771ce7d1397c345f1b03dd7625776f3f195809932618b1c64acd93ad000ead09654a33d14f748b46b67aae0ff12df3cc163280f47cedc16a8579034e49884296772ecbdbb71ca29c166233533c8de54012b412ca13cc258f7c5465d83422f524e4c05f806313478319fd143cf5088e69837697d3615d80a7fa7e7443fca65e753ac1b11d8eff3476636ae02d7a20f4b2388dad684002f5ce957caddd2053d0ed533132a81ca19bb080bd43be932028cb5f6b964f008b5b1c1c5993bc9b5485b22bbef701f0a26a3e675ea31122bbae91d864b54d895afdc79ca58d4fe449213353b149f3143b5144d747c5b4697479ae68528485384044aa2c99ba4b17b184e94982269bde2de0b17705d0bfc46d6906a90edefe89195de6bb8f3fb6a374186c7cd086d13d1b3525a3994dc8020e1a00554ac8a82d6047c5bff5e7f12450f4865da161e1a021fd9be8bd33a32bb54a4ddf874512e74b5cfd3fc3cd9ac11edd878433668e3fcc782b97b6d905adb0ebec42c9254ac90f35822c00f97ff3f0c7c39ed3c7cb3920f5608bb45838bb242a52a8637d7cecdcf489fa183b45451c6c9fcbbbf914f5f7e6b223bcb4675:583370971d24652ad213c42615911938fa9aa3d9b7196940e6eb08151200c7b6729d1eff8f4f0904074dab3ddda6af1e4e562b7d6220c1a562683beab268f80e917519cdb33519680bcae04faa790771ce7d1397c345f1b03dd7625776f3f195809932618b1c64acd93ad000ead09654a33d14f748b46b67aae0ff12df3cc163280f47cedc16a8579034e49884296772ecbdbb71ca29c166233533c8de54012b412ca13cc258f7c5465d83422f524e4c05f806313478319fd143cf5088e69837697d3615d80a7fa7e7443fca65e753ac1b11d8eff3476636ae02d7a20f4b2388dad684002f5ce957caddd2053d0ed533132a81ca19bb080bd43be932028cb5f6b964f008b5b1c1c5993bc9b5485b22bbef701f0a26a3e675ea31122bbae91d864b54d895afdc79ca58d4fe449213353b149f3143b5144d747c5b4697479ae68528485384044aa2c99ba4b17b184e94982269bde2de0b17705d0bfc46d6906a90edefe89195de6bb8f3fb6a374186c7cd086d13d1b3525a3994dc8020e1a00554ac8a82d6047c5bff5e7f12450f4865da161e1a021fd9be8bd33a32bb54a4ddf874512e74b5cfd3fc3cd9ac11edd878433668e3fcc782b97b6d905adb0ebec42c9254ac90f35822c00f97ff3f0c7c39ed3c7cb3920f5608bb45838bb242a52a8637d7cecdcf489fa183b45451c6c9fcbbbf914f5f7e6b223bcb4675: +9feb3df88c494a99849c6fca194201477a2fa7564e29fb06cb44c1154e8cea3ac35628ca6ee28ec1c239ddc5bba2a9e09e4846816b143c74dfa2aec1f62551b6:c35628ca6ee28ec1c239ddc5bba2a9e09e4846816b143c74dfa2aec1f62551b6:95fb7581bd25ffd442c3ae38a19bea7349c7b7683ba6767e148f0afc15373f67c16d471781202e6da8054ed7fb9ee204cc0f63c210a670a5f9ced4294588196330d31b8e8392bef6b48fe3c92078fae11284b4c3ba20d937e2719de7bf67c00669ad23e61384ebdf8c6e60735428c084fe217fdb4709ccb6083fc0ae4a05273eef739023d34bb73f662dacdf110b6dbd3e74fc1491e8c96596075fae5c36aabe2a0a53052bf77c4462438063aa7bc0c50ab920c9eb288671560ca5ba7af44a53db2e2ff43ca56069ea5517cb214e76faa53dbda100003c4f6175414041be74de22ce155d2281b6f4035be39841afdb96dd89aa808e6865bae62d6bedd919d3e86510b9fa5fedd1977c4131b2b86e0f48d7215eb13d5498ca5d2368f81895ed855a527124657ec9539efe3b2499a3b0b338262f26340e22554c79f4fad2b4e419c70bc1a2107d206456b6368781be4b5e2c54da42d336040fb7ba49c32d752321adcd92986e78bedb226ceac50292089bb579027f702217745afe06a5be136b3998a3604c9ff2acd6fa3f3f71633d3102fbf03047c5486f84c4dc2447d863796383d55f08c981fd4dd7dc1cb72b8ba4435af6abdd74e6f6e6798f1ae2:a1c2607835bec1a1d87872fd8ee488d0ae9ed23d49fd6786fc4996725e49b3262118babb4834877c7f78fbeac02df40ab091b8b420dc9951381e3bcda067050295fb7581bd25ffd442c3ae38a19bea7349c7b7683ba6767e148f0afc15373f67c16d471781202e6da8054ed7fb9ee204cc0f63c210a670a5f9ced4294588196330d31b8e8392bef6b48fe3c92078fae11284b4c3ba20d937e2719de7bf67c00669ad23e61384ebdf8c6e60735428c084fe217fdb4709ccb6083fc0ae4a05273eef739023d34bb73f662dacdf110b6dbd3e74fc1491e8c96596075fae5c36aabe2a0a53052bf77c4462438063aa7bc0c50ab920c9eb288671560ca5ba7af44a53db2e2ff43ca56069ea5517cb214e76faa53dbda100003c4f6175414041be74de22ce155d2281b6f4035be39841afdb96dd89aa808e6865bae62d6bedd919d3e86510b9fa5fedd1977c4131b2b86e0f48d7215eb13d5498ca5d2368f81895ed855a527124657ec9539efe3b2499a3b0b338262f26340e22554c79f4fad2b4e419c70bc1a2107d206456b6368781be4b5e2c54da42d336040fb7ba49c32d752321adcd92986e78bedb226ceac50292089bb579027f702217745afe06a5be136b3998a3604c9ff2acd6fa3f3f71633d3102fbf03047c5486f84c4dc2447d863796383d55f08c981fd4dd7dc1cb72b8ba4435af6abdd74e6f6e6798f1ae2: +bff68955dd6ae0e8ba85ab0d0cdaf04a9f5befd5ef6014f49994a78363dc17f70ad9493af80b15f07a521ccd674fe9e5212a4a28c17c74f6605ffef78a4aed72:0ad9493af80b15f07a521ccd674fe9e5212a4a28c17c74f6605ffef78a4aed72:d8f5650aa3581c4d39bd1b8afc96c1ad7c4bf723426f9d7fabd1a5c8ac1d2fe54a971fac765e05af6e407d7269bab661b3432292a484f952c11095bbd20a15d77c41f8f3731a504d518ee10cd006c96ee57372de5bea348ec8ba159162170c63e970f1c7a3465a3d592e1d56c6540fbdb60228e340909646320c95f25698cd4896bdff58e2561e3b3d9a73b89747912a1cf467d63e41455fda77477f46fe6937bb0e79d92ccd52e82dba908a05a57c7ecf49554ab44c0b718e3bdd5fc0bf7070d9c58f860591c18bca8b3a9a148a06548e0f01602b1e6f686037c94ff732e155d52d5b0b44703b3d11163e3f56e3b9c1b86476e4dcbfc53fa05984e8c75dd21843cf96f9e494abbae7184aa42736633e3811aeff402b2fcb7d7f702e447241e22a58842fd6d0c03d33ff5b8c792200e173daa7b217e4b2f4433e6c020acce501b9323aa0241144434b08e9d2469139ff67342208900546200fd971a65dbd6db6c21e3ef9172abba1ea9ea2a249addf1a1eaa3ce11938b13e30913cd0dad491fcbb3285ea378b8ef9227f3fa80b586ecfeae137066f8448acdfb78d6d3e9ef4a6b362df4241ad9ae253b8e1597d656e000cea447a02fa4933328609bba0:9319eef740633ada1af0e137644c61fb3e11ba4b01d3c6f25392dc9367872a23be56310d312efcb91bdbab78a75e576ebe9081972415f562db41baf5e2338b07d8f5650aa3581c4d39bd1b8afc96c1ad7c4bf723426f9d7fabd1a5c8ac1d2fe54a971fac765e05af6e407d7269bab661b3432292a484f952c11095bbd20a15d77c41f8f3731a504d518ee10cd006c96ee57372de5bea348ec8ba159162170c63e970f1c7a3465a3d592e1d56c6540fbdb60228e340909646320c95f25698cd4896bdff58e2561e3b3d9a73b89747912a1cf467d63e41455fda77477f46fe6937bb0e79d92ccd52e82dba908a05a57c7ecf49554ab44c0b718e3bdd5fc0bf7070d9c58f860591c18bca8b3a9a148a06548e0f01602b1e6f686037c94ff732e155d52d5b0b44703b3d11163e3f56e3b9c1b86476e4dcbfc53fa05984e8c75dd21843cf96f9e494abbae7184aa42736633e3811aeff402b2fcb7d7f702e447241e22a58842fd6d0c03d33ff5b8c792200e173daa7b217e4b2f4433e6c020acce501b9323aa0241144434b08e9d2469139ff67342208900546200fd971a65dbd6db6c21e3ef9172abba1ea9ea2a249addf1a1eaa3ce11938b13e30913cd0dad491fcbb3285ea378b8ef9227f3fa80b586ecfeae137066f8448acdfb78d6d3e9ef4a6b362df4241ad9ae253b8e1597d656e000cea447a02fa4933328609bba0: +1ba919c066bb56e640c3335968e1d1b5bcc093383e2d7cf8b5fff5c61ec47a77804c90bdc2b3618b01f075e041fa971b83c5b6cfa3b6b3974f3fa43599beacab:804c90bdc2b3618b01f075e041fa971b83c5b6cfa3b6b3974f3fa43599beacab:87c5c75d8ad07d52acd781d1bb95f78c70e21c2dd66f7aa44234152f98234d128358a8aee98ea903a77b441db1447ae6ff3432ddd4570f7f58036122c1fdcc93cb21573739c19ccaa411508e08de2606f3d8f2db89df6a44a46133d57018462627e22f57ef36d1de024de3d4ae41b752df4821155934b447b2effe512487521be0356832a74ce0e2d8301b79f93175e8b6b961b1df637d8acadc884543c6864f8025ececec7c6e4fe0fecfc40dcd95e8d6ab93ce25595384436b598b73c74b03d49ed5002c0f858cfd9d0df61ede937cc41659d6708b96fc5aaadee109e2a68846baf2c246dfcf3d27c28bd1371e35fc9412631442ee75f38c6e4958070a74f6e6a220f75c7280eab4737d97e37882f3624811675f16caf60cb944bce92e75884c56483c61f26b6371b1b51237621a06543eb4abea7becc4fc31dbb5475b3deb9bb3c8992387104830c6072afe1af244bf681a40329c9b37772b09c5e88e78f7dffbc04549ffa13b4144ddfa538fc4b3300540ad830215e25f11446d289f33122c2c880de3da71c453d7e88f7ca4ea3d1255e82f4bc9e5533dc401c33040e16940b2cf9cf21feaca1c2c6c33337cf75e1884b483bf801536d304089115a0:503eb7ed6de1b776c952f255bbd4bcfb0e48bc70c2cc2f1f72bf6881479040c47524ec542ae13f6005ca5016b58b736a50898dd0569d4d38ad298630d68adb0b87c5c75d8ad07d52acd781d1bb95f78c70e21c2dd66f7aa44234152f98234d128358a8aee98ea903a77b441db1447ae6ff3432ddd4570f7f58036122c1fdcc93cb21573739c19ccaa411508e08de2606f3d8f2db89df6a44a46133d57018462627e22f57ef36d1de024de3d4ae41b752df4821155934b447b2effe512487521be0356832a74ce0e2d8301b79f93175e8b6b961b1df637d8acadc884543c6864f8025ececec7c6e4fe0fecfc40dcd95e8d6ab93ce25595384436b598b73c74b03d49ed5002c0f858cfd9d0df61ede937cc41659d6708b96fc5aaadee109e2a68846baf2c246dfcf3d27c28bd1371e35fc9412631442ee75f38c6e4958070a74f6e6a220f75c7280eab4737d97e37882f3624811675f16caf60cb944bce92e75884c56483c61f26b6371b1b51237621a06543eb4abea7becc4fc31dbb5475b3deb9bb3c8992387104830c6072afe1af244bf681a40329c9b37772b09c5e88e78f7dffbc04549ffa13b4144ddfa538fc4b3300540ad830215e25f11446d289f33122c2c880de3da71c453d7e88f7ca4ea3d1255e82f4bc9e5533dc401c33040e16940b2cf9cf21feaca1c2c6c33337cf75e1884b483bf801536d304089115a0: +9b36247c17710e95261a7d702f57fe81f2971117a50c87920193b386d494ca9729ae39f273e35fb3f611da091600650efbc4fc4d1e7b4c76aced5a83f82634f3:29ae39f273e35fb3f611da091600650efbc4fc4d1e7b4c76aced5a83f82634f3:e8d9d53ba27e98edd55df3c6b245eacddc8a40e3efb007bc918ec5a869178a170bb4a635b7f8f742e37ad45d14a74344a6b522830a522106eb960daf192dc1e0fd70f16160e122516892d0e2abd0d4ae0f0d2e5adcc99ad55302e251b3e7a4d0cb33774a497049905c33de1fbbc1ad2b6c645295fe416b4d12b232efe0a33cd2ad8732eba1c3cb0eaeb0b2a57fa03ec567ca29210bf6ff9542a766f496fe68058aa983806cbe7ab10a47920bac8248818e54a41551c9a0959e8994cac60fc868ad48b5a24d5f24a7a5a3fd90b847e817ad3dd5d0d6f8de2d204f642483bd53585a92ef925415a9b38fbbf07fc0f35e707569cf488b205453ce5433eba6fde8781af72b52bfbcab85ead385d9d3175e21ad3373ad535cf0e357ed6b5383ef3829a9d5095b87dc9aadbe0ca7abadf33ec3b6ffd6eb94afdcc12e8d66a6fc05acf97368db0f69565dcd8fef4d1e49d7dd4ac053c218f5240c812d4ebba440dc54cacddb1c39329e5bd0c3c80dc3259a80f059f94679aa0794ca0115cc62af25e124cb8a9d4160eace6d22c7b1c44544f81142a19ebb02a9bda6429c50e783db4a07f0219e857c8d3c5655a582831c8eabc3f19b59ad8d2c714adeaf4039d5cf70:035970a672e93f87eb42cc396f6ea7e1b3dd5c5951572826d1075a15c2d7e454df195b51aae8dc61ef7ab895485f64e5989573d98a062e67ae7356fe5c9e3b0fe8d9d53ba27e98edd55df3c6b245eacddc8a40e3efb007bc918ec5a869178a170bb4a635b7f8f742e37ad45d14a74344a6b522830a522106eb960daf192dc1e0fd70f16160e122516892d0e2abd0d4ae0f0d2e5adcc99ad55302e251b3e7a4d0cb33774a497049905c33de1fbbc1ad2b6c645295fe416b4d12b232efe0a33cd2ad8732eba1c3cb0eaeb0b2a57fa03ec567ca29210bf6ff9542a766f496fe68058aa983806cbe7ab10a47920bac8248818e54a41551c9a0959e8994cac60fc868ad48b5a24d5f24a7a5a3fd90b847e817ad3dd5d0d6f8de2d204f642483bd53585a92ef925415a9b38fbbf07fc0f35e707569cf488b205453ce5433eba6fde8781af72b52bfbcab85ead385d9d3175e21ad3373ad535cf0e357ed6b5383ef3829a9d5095b87dc9aadbe0ca7abadf33ec3b6ffd6eb94afdcc12e8d66a6fc05acf97368db0f69565dcd8fef4d1e49d7dd4ac053c218f5240c812d4ebba440dc54cacddb1c39329e5bd0c3c80dc3259a80f059f94679aa0794ca0115cc62af25e124cb8a9d4160eace6d22c7b1c44544f81142a19ebb02a9bda6429c50e783db4a07f0219e857c8d3c5655a582831c8eabc3f19b59ad8d2c714adeaf4039d5cf70: +6fede7396c462033189acd23d2f9d02b68898d35f3a01a798fc24d488de93a78b34062060b2c20076a98fea939b3b3a50451a5f49f8351c0ad7591dbbebb130f:b34062060b2c20076a98fea939b3b3a50451a5f49f8351c0ad7591dbbebb130f:5abcc14b9d8578de08321de0d415e3d40e9de31e1888137475ce62bc6fbee8fdd03b9d47c7b88bbceb804444490bf6a3ccb7a273261e24004ea67cefa3d5d173576d01e38f76c1e0e515083c97e79914acf2be4160ef9360bbe986b36e9ff93346b0e70691d934e47f8a503fa933ab2a50426947cda8e810c9ebe3b36982f09aee6092739fa2358b613c7f129db0dcbe368bee52f2f7f1dfe3d2434605b5afcf256071717d924fd0803bbd0dd1f9555ce834dac781df4cc7aa19e7f11da9fb99cb9e6b9e1e6fb4f7e8dcb2236c28aeb6cbc55a130e03c1b17a991cca1b794e6c13732d5b0a66f6eba860ecb98555aa4c218d112b116bce238295de142741f687be0b2487f58ffc5c12a0a519f1e23793242ef857ed398a20699d4351453fc2f092762abde34f4da2dbe0ce2aabaf6bc4c0159f3fe1aea16a036f7eaecd629538f3e0eed83c9a4dc1abc238f90daaf489fd61b34d937b6f4607a788baa82061943dbab26c1d384d8d49f99348800bf361f871f5d6cda18f689918cec31ad158f1863d13ffac5405c162c32de06e32994cc4106f95bb4fffdbefe7d629ec7797394609fdbfeadb46927370a11fb38471540f951b93c6eb238668dc006c21660ba2:88a83e2012d209ca03b8ebf6de5bb7ef4ccb5e3df5cac78954aa694930e4de82544ef5083c4892db9f05d77bf63f4fdfce15a4d1c3f85bae8077062bec0e7b075abcc14b9d8578de08321de0d415e3d40e9de31e1888137475ce62bc6fbee8fdd03b9d47c7b88bbceb804444490bf6a3ccb7a273261e24004ea67cefa3d5d173576d01e38f76c1e0e515083c97e79914acf2be4160ef9360bbe986b36e9ff93346b0e70691d934e47f8a503fa933ab2a50426947cda8e810c9ebe3b36982f09aee6092739fa2358b613c7f129db0dcbe368bee52f2f7f1dfe3d2434605b5afcf256071717d924fd0803bbd0dd1f9555ce834dac781df4cc7aa19e7f11da9fb99cb9e6b9e1e6fb4f7e8dcb2236c28aeb6cbc55a130e03c1b17a991cca1b794e6c13732d5b0a66f6eba860ecb98555aa4c218d112b116bce238295de142741f687be0b2487f58ffc5c12a0a519f1e23793242ef857ed398a20699d4351453fc2f092762abde34f4da2dbe0ce2aabaf6bc4c0159f3fe1aea16a036f7eaecd629538f3e0eed83c9a4dc1abc238f90daaf489fd61b34d937b6f4607a788baa82061943dbab26c1d384d8d49f99348800bf361f871f5d6cda18f689918cec31ad158f1863d13ffac5405c162c32de06e32994cc4106f95bb4fffdbefe7d629ec7797394609fdbfeadb46927370a11fb38471540f951b93c6eb238668dc006c21660ba2: +d559580134ab050aca446ea7750ef6b371d92d7645ec7635fe7851100bc4e51ede5020cd21a8b32339decbedff24664d9580326327aedf09c5ec6b3fe5405226:de5020cd21a8b32339decbedff24664d9580326327aedf09c5ec6b3fe5405226:6842e3190a110eee96c507d4bcb4c548c3a0ed7b1a8ed77dd93b38613b23c73e830b205e62651921ad8296b08d1e1008ad78f2996e3c7f38032e467cffecd77b8525e243cec021f85296afd545d7be1a62568bb0cfcdb90d614ed798bfb7efc655326816a61082251df01613aac88efcea1e0ea2961b8f921ebe1558dee83374a0113a78c55857ce2055bb2c48badbd3d8f4cb19734d00d0604b619073020d72a99a1923e6160a09946567fd4bda66442ef5a7360786d178dae44922f350ce2edc6af73d1bd80dc03ec3ca7005f4109d10c6d4f7d8fa61735110f8dbaedf91a0bad7d7fb5c04d706373c15c645063ff4b4fbd2d559b0afad432d4c496cd8abfea286fa675dc076726ec522b3a3c2f47aecc539f48a792169c4cc8cd41cd2cb6b63ddbc19373ac9691c2bc2f78f22603d5513715a16d4574e7acc4bea6dcd8ca7f19865a49d3664a210dfad290774b10b7188f255b3be4dc8fa86f8da3f73a4e7c929951df30fe66a17c8cee23e4f2ed2063f0b02ab40372cbe54b9a708df7c48a06566d39b19434c6c766987b3ebb00675f44c4b3c1e9f4504e7a9270589c0d0f4cb734235a58ef074cf9decf3601aeeca9f1d8e356cb2db5fce79cbc36143f34b:6fcb1ac9290ab767d59b598c9a24ecdb6c05bb023ec36014a40d908ef0dc378a4528b3760d889a79174e21cae35df45d427ba6ea812bddca16e35a69b5e79f0a6842e3190a110eee96c507d4bcb4c548c3a0ed7b1a8ed77dd93b38613b23c73e830b205e62651921ad8296b08d1e1008ad78f2996e3c7f38032e467cffecd77b8525e243cec021f85296afd545d7be1a62568bb0cfcdb90d614ed798bfb7efc655326816a61082251df01613aac88efcea1e0ea2961b8f921ebe1558dee83374a0113a78c55857ce2055bb2c48badbd3d8f4cb19734d00d0604b619073020d72a99a1923e6160a09946567fd4bda66442ef5a7360786d178dae44922f350ce2edc6af73d1bd80dc03ec3ca7005f4109d10c6d4f7d8fa61735110f8dbaedf91a0bad7d7fb5c04d706373c15c645063ff4b4fbd2d559b0afad432d4c496cd8abfea286fa675dc076726ec522b3a3c2f47aecc539f48a792169c4cc8cd41cd2cb6b63ddbc19373ac9691c2bc2f78f22603d5513715a16d4574e7acc4bea6dcd8ca7f19865a49d3664a210dfad290774b10b7188f255b3be4dc8fa86f8da3f73a4e7c929951df30fe66a17c8cee23e4f2ed2063f0b02ab40372cbe54b9a708df7c48a06566d39b19434c6c766987b3ebb00675f44c4b3c1e9f4504e7a9270589c0d0f4cb734235a58ef074cf9decf3601aeeca9f1d8e356cb2db5fce79cbc36143f34b: +9d4ce975547876636fea25437c2880c9aa8ee6b270d1b2da197c8d7f95e7dcccbde4993c030477c35890aae82bb5087e914e64b94ffc64e2d7a5a7c919e2d902:bde4993c030477c35890aae82bb5087e914e64b94ffc64e2d7a5a7c919e2d902:ea0fa32a4a288811301b9ee533fa351fdfbf6bc1d0555a7402767a3a9198558f74bba7031857995b9f326226f1dd5df107b06342203eb8d40c5f1dc95b4f3f88975aa24af8769e2670c46671bebb7a0f1b7568729aee477e8988af9c749f3202708171fd94b337ae67ed21a6c44174014b0b0eb5ba71c277978d488c24c4a7841309846b4e30a4fbbcfc45078d7e14014114b1ac64f7c33c9ac25ea5626c2c819fbaa2a4de8a2bf5f1365d6b70407e8094f99197ce1f0c35e11a98fbe372414ea2064a3a12d1cd5c8df8fc0e79f5b770b58f477f91976ca0139895120e246baab5a026f2d39c687dc0788334b5c626d52cdebe05eaf30864b413eebdc5581ef00d439276e52f479c9c05b116395826b60490b3ce700cc0027f61e46ca2f6fbc2c9de2e800806550afb06d4a08eac7a758e24582a4d6d428b433d365fc31d4444607afb64f15e370794005a3a2244e666d5d4c38ad2009c769a51cdbf738d235942f412d07feeb73b3657d0b0c91cb5940bad6a706e14edcdc34225b1c1f38b1abecb2adcaf819155a94fe190fd556822d559d9c470854d3a43bfb868dadd6e443d98ee87e4d8284f5cf3a6dafaf295b902836c640511e610ae7d0cb1b1d3d6079fe6:be17444cd465a87a971df84eb102f9c7a626a7c4ff7aea51d32c81353d5dbc07393ca03db897d1ff09945c4d91d98c9d91acbdc7cc7f34144d4d69eb04d81f0cea0fa32a4a288811301b9ee533fa351fdfbf6bc1d0555a7402767a3a9198558f74bba7031857995b9f326226f1dd5df107b06342203eb8d40c5f1dc95b4f3f88975aa24af8769e2670c46671bebb7a0f1b7568729aee477e8988af9c749f3202708171fd94b337ae67ed21a6c44174014b0b0eb5ba71c277978d488c24c4a7841309846b4e30a4fbbcfc45078d7e14014114b1ac64f7c33c9ac25ea5626c2c819fbaa2a4de8a2bf5f1365d6b70407e8094f99197ce1f0c35e11a98fbe372414ea2064a3a12d1cd5c8df8fc0e79f5b770b58f477f91976ca0139895120e246baab5a026f2d39c687dc0788334b5c626d52cdebe05eaf30864b413eebdc5581ef00d439276e52f479c9c05b116395826b60490b3ce700cc0027f61e46ca2f6fbc2c9de2e800806550afb06d4a08eac7a758e24582a4d6d428b433d365fc31d4444607afb64f15e370794005a3a2244e666d5d4c38ad2009c769a51cdbf738d235942f412d07feeb73b3657d0b0c91cb5940bad6a706e14edcdc34225b1c1f38b1abecb2adcaf819155a94fe190fd556822d559d9c470854d3a43bfb868dadd6e443d98ee87e4d8284f5cf3a6dafaf295b902836c640511e610ae7d0cb1b1d3d6079fe6: +0273868232f5be48592cfa05134e8d5554ed1f9a57bc7e3982a330c57e5a7f3af172208782db66d466cbe4f4417f6fc477b7349f2a98db56c03a47227546bc5a:f172208782db66d466cbe4f4417f6fc477b7349f2a98db56c03a47227546bc5a:f7a1d4614cc64a3bc48f00c6276304f34d4dfd15e0617b93ccef126c5c638c9d9953aabb7df42df4e0aaa7eac96a4b38c7ba758d860c90d05e3d14e479e545f319b0e5a85ad8f0991b43d6e49c24fa060e3e5df95c98d9451ab833e12aa97f404611bba359496265a6db11917d0da5c6a702d0b102de36dd0c98df5b54806ce626bb96374475f68a6060eb350a7d2aae3204b3dfdf9f1e31be81f7170f8a1b9385413ff8f6881e10c1e8da4c88afb50639ab44887aca2abeecedf110d2958c13fd3390d1b96a762d16ce196920ce85f6c415bed545b1445302a6f001eb8d00e97c751887868d481a0b1e4dfa04b6f761086ee8e697b019e017104bafb98fca242e334c6f18f1db5b6f295f05c559361c6831dabc42c2110703f9d1f64e12ddf26a8679854e9f8ef8479e1f12c35447aac02ea7f242e58632cf2fd063fe665070445b80f3dc6a3303bba96e05fa88eec201c5c2d00ca81b8da6969d0a4dd0483b3477d325a71facd6fa2209b48cb4f6525da73c9c05b2d9789b01448e1527e56a09a9bc6136d9837243c2077b925bbb933f8fb1daac963398c5802aeda3bbca8ae3b8f4a9a871f7ea8e2c0ce898c566217b5c06ff55ff9f4fe78398ae7973641eafb521:15e8d8dc7d5d25359d6a10d04ee41918a9c9df4c87be269fa832434d5301db022481bfa395a3e3466f9554ceee0532a8183a0d0550e7d1abe99fc694c6ff9301f7a1d4614cc64a3bc48f00c6276304f34d4dfd15e0617b93ccef126c5c638c9d9953aabb7df42df4e0aaa7eac96a4b38c7ba758d860c90d05e3d14e479e545f319b0e5a85ad8f0991b43d6e49c24fa060e3e5df95c98d9451ab833e12aa97f404611bba359496265a6db11917d0da5c6a702d0b102de36dd0c98df5b54806ce626bb96374475f68a6060eb350a7d2aae3204b3dfdf9f1e31be81f7170f8a1b9385413ff8f6881e10c1e8da4c88afb50639ab44887aca2abeecedf110d2958c13fd3390d1b96a762d16ce196920ce85f6c415bed545b1445302a6f001eb8d00e97c751887868d481a0b1e4dfa04b6f761086ee8e697b019e017104bafb98fca242e334c6f18f1db5b6f295f05c559361c6831dabc42c2110703f9d1f64e12ddf26a8679854e9f8ef8479e1f12c35447aac02ea7f242e58632cf2fd063fe665070445b80f3dc6a3303bba96e05fa88eec201c5c2d00ca81b8da6969d0a4dd0483b3477d325a71facd6fa2209b48cb4f6525da73c9c05b2d9789b01448e1527e56a09a9bc6136d9837243c2077b925bbb933f8fb1daac963398c5802aeda3bbca8ae3b8f4a9a871f7ea8e2c0ce898c566217b5c06ff55ff9f4fe78398ae7973641eafb521: +336a83b55abf4c02e25e540329b5275843c2ecb8df69395b5a5e241bd0d8c10ddd60569844570c9f0a82643f446478b5ac6fc542214231a7ca656a92b5fdaa54:dd60569844570c9f0a82643f446478b5ac6fc542214231a7ca656a92b5fdaa54:9afee8ab482010e29264b406d9b49453d1ce6d550939072182863e4665284ab05d86258e0623b18754c4785238f697f075adfb9e1d31a42e85934ec071ddddecc2e6c2f61334a79526788b4952190716906dde17fba556eea4c8b59727514f6f5615a19ca36da358fae6a6c54f7f4b7a929e31ba7cc71bde7882fa9ffd87300136409caf3ca64eefea616aed58da5dfbf28b668ec1cccffcef6e2e14f8109e9cbf76cfa414f91ac00f48e93eada385dd3d5c16e1a39ea3dd55c761fca361b428f516c05e694fe5c3c345cd94457187a8e604b200a1a0f937ae89f4d6b5421dffcf7ca15f2e2c25378a4113233f7613f4570aa4b909a9135eae4c7b9ead458007ae17126a11d145258af9563db2f7e8925431878b0eeca8affc01ac5913bf5bac4fa3a857c54cc8906d6af77de6b9326b6506151099e87e99b1e819c6fbe082688f34b803d588e416d853169765d62f7e0bdf72c5cd66669a0335562336735e7efb734a2fada327f858bec602d0da08eba4479e7f6dc4def6e4ebdbb730ee91a33445cadc9df52c825ad36149cefbc51ab102033530814bafa7e87961b06367ff896f08ae334a9b1aad703da686706c11a04943ea75e12992dcf6106e372077cd0311029f:d263f56d59cb9b2896a947267c2ed78a945bac5abdbf3c14dc3ad092b2308cb9315c464942a0a20b2024511d766e85c936499a149cd0bbb209150a16432652009afee8ab482010e29264b406d9b49453d1ce6d550939072182863e4665284ab05d86258e0623b18754c4785238f697f075adfb9e1d31a42e85934ec071ddddecc2e6c2f61334a79526788b4952190716906dde17fba556eea4c8b59727514f6f5615a19ca36da358fae6a6c54f7f4b7a929e31ba7cc71bde7882fa9ffd87300136409caf3ca64eefea616aed58da5dfbf28b668ec1cccffcef6e2e14f8109e9cbf76cfa414f91ac00f48e93eada385dd3d5c16e1a39ea3dd55c761fca361b428f516c05e694fe5c3c345cd94457187a8e604b200a1a0f937ae89f4d6b5421dffcf7ca15f2e2c25378a4113233f7613f4570aa4b909a9135eae4c7b9ead458007ae17126a11d145258af9563db2f7e8925431878b0eeca8affc01ac5913bf5bac4fa3a857c54cc8906d6af77de6b9326b6506151099e87e99b1e819c6fbe082688f34b803d588e416d853169765d62f7e0bdf72c5cd66669a0335562336735e7efb734a2fada327f858bec602d0da08eba4479e7f6dc4def6e4ebdbb730ee91a33445cadc9df52c825ad36149cefbc51ab102033530814bafa7e87961b06367ff896f08ae334a9b1aad703da686706c11a04943ea75e12992dcf6106e372077cd0311029f: +88409172618b490393db27d960171cbc187eaf4dd8b320b3d2f824980043718fce2e7c5839ef5632a123dc373dc14b1f0505766e9675407604ca7cf54e8d44b2:ce2e7c5839ef5632a123dc373dc14b1f0505766e9675407604ca7cf54e8d44b2:fb3e82f11bc286267e123817ad8864e077d9f7a8e7a163ac7eeaf93d55dd111de8083b66b53ce7bc771fc5071a2d7ac2f85d6fc6adcfcec446e16aa1046df37209ad7a29cf9665b439a54d6f8d942f89bdaa56f2f11260cc95993038b0e8fbdb3214f142e6c90b61a1d2b142076206af30ac35784a6dc15a1e79251a8c7731a1c53978038f8d76d70c6c1cdf529fbdb84d1507dcffdd42873dfa6a8fe6bd6f7fd29c80e4b2f933d2b6c9e62c9457e665472655059b63b618e2a9a8e5b9e41c3646173a892b8e6d4bcad6a62a6fccd3455890b58ec2681a95cc9776a9fce83c54a9ef312a331959c7ef3f79ee576eb7b79469c9234b1eaef609884708fe4bb0efac662da871ba61ddabb3fcbdeb8f635657dd9a5d7311e639a824858b9a9868d3f9384da612c7f2e771a46bd2624c99ea2b6ccbca996c1d9c375554f2a551619ce6d5e6e4d6b844a4dbea83ba732331fcf46572c1fb0e257ce1041b265df02e690a92814bbf3b5ecac69ee998766a02b0d2f908b3c15f952699616f2c07d589198989e6056c16319aab6cf8771902c078046a88b2570c13bc5edeba2ed1e3ba131daf94e6891862bb3de7d1063fe405307a5cd975693e9d58e17c690eeef4a2603cafc68c2b:93b6e29d63945d5c427387d006c7f0b01956a95fc0436ed42b46d0f17b5bb193ea8c0ebbf3d6d13bb539e35c91f3f0f9fa3414a0223c9060bac83653c6fcd906fb3e82f11bc286267e123817ad8864e077d9f7a8e7a163ac7eeaf93d55dd111de8083b66b53ce7bc771fc5071a2d7ac2f85d6fc6adcfcec446e16aa1046df37209ad7a29cf9665b439a54d6f8d942f89bdaa56f2f11260cc95993038b0e8fbdb3214f142e6c90b61a1d2b142076206af30ac35784a6dc15a1e79251a8c7731a1c53978038f8d76d70c6c1cdf529fbdb84d1507dcffdd42873dfa6a8fe6bd6f7fd29c80e4b2f933d2b6c9e62c9457e665472655059b63b618e2a9a8e5b9e41c3646173a892b8e6d4bcad6a62a6fccd3455890b58ec2681a95cc9776a9fce83c54a9ef312a331959c7ef3f79ee576eb7b79469c9234b1eaef609884708fe4bb0efac662da871ba61ddabb3fcbdeb8f635657dd9a5d7311e639a824858b9a9868d3f9384da612c7f2e771a46bd2624c99ea2b6ccbca996c1d9c375554f2a551619ce6d5e6e4d6b844a4dbea83ba732331fcf46572c1fb0e257ce1041b265df02e690a92814bbf3b5ecac69ee998766a02b0d2f908b3c15f952699616f2c07d589198989e6056c16319aab6cf8771902c078046a88b2570c13bc5edeba2ed1e3ba131daf94e6891862bb3de7d1063fe405307a5cd975693e9d58e17c690eeef4a2603cafc68c2b: +e571189b5cd9e788302de3919d850c227dcbb615022e568bdaeb37ac5b2939c5edda890f42dd5fbc7316a5fadfbec38556f23f51b8efd2625437f6b5069f1ee5:edda890f42dd5fbc7316a5fadfbec38556f23f51b8efd2625437f6b5069f1ee5:b62c867ad6227435bfa6dab830684e38d196e1f861aade0fd6a7699b6d60901fefb2d799c35c6f3d8bb94deee834403981866bab84946ae9476c75e9f1d3602b42cb2db437bff33a775822f0d6a257d4b75400eba5b8abb314b71fc6b46f8a34e861a9a62abf33de8482f63f9d7169e773a2dcebee03705dac117fd1499b68e7414f51ff9437f253a1d9901ec3b0bba86965a19383655487b58010f804909de1ffb2212c0252ddd9bf2a56ac46bd59c0c34dd59e46598b6babd4e5f3fffde55e48dab0398c22af9e26baddf77275e5f017b35a9b8f8435f9631936b391cb95d7adf35d1d8545a0fd066412d508967bbe9a20245a269e3be2777117e75fbac170dba352be69b254d353b3b2cb3b7e21b721aa9fe044f8916b4b2a6f8c28f8abe66ac92b91323ac73afd93dfbeeaeef26d19bd9f67e99d48cd2ad2d3e55e45d24d54b50f44a39b90e242ebe9b42bebdb230c470bdfde1bc7721c3120008477393dcc2e15fd22b251feb0e18b02883c078aee4fb760655a671dc7b8aadb9a562420a3c2efa2d342e1e0099d951b42242984f594e6914fe282b1ee128735984ef93a669e6ecba26c9fcb9f09f09256645617f1392d35908917cb8d29e0897c7503cddd5de1959686:7f797a31715d7c356f8f1f783700aa9974bb936d661661ad968c7cde1ac9e767be56a2dd49b9230e90110c67c0ed187cb7e75c3053ece844984d296f0d85cb07b62c867ad6227435bfa6dab830684e38d196e1f861aade0fd6a7699b6d60901fefb2d799c35c6f3d8bb94deee834403981866bab84946ae9476c75e9f1d3602b42cb2db437bff33a775822f0d6a257d4b75400eba5b8abb314b71fc6b46f8a34e861a9a62abf33de8482f63f9d7169e773a2dcebee03705dac117fd1499b68e7414f51ff9437f253a1d9901ec3b0bba86965a19383655487b58010f804909de1ffb2212c0252ddd9bf2a56ac46bd59c0c34dd59e46598b6babd4e5f3fffde55e48dab0398c22af9e26baddf77275e5f017b35a9b8f8435f9631936b391cb95d7adf35d1d8545a0fd066412d508967bbe9a20245a269e3be2777117e75fbac170dba352be69b254d353b3b2cb3b7e21b721aa9fe044f8916b4b2a6f8c28f8abe66ac92b91323ac73afd93dfbeeaeef26d19bd9f67e99d48cd2ad2d3e55e45d24d54b50f44a39b90e242ebe9b42bebdb230c470bdfde1bc7721c3120008477393dcc2e15fd22b251feb0e18b02883c078aee4fb760655a671dc7b8aadb9a562420a3c2efa2d342e1e0099d951b42242984f594e6914fe282b1ee128735984ef93a669e6ecba26c9fcb9f09f09256645617f1392d35908917cb8d29e0897c7503cddd5de1959686: +371744ab63c115613929a343709bb019b7357dff72d2a149f1d0f71d3a201efee58abfad4a13859f0acb05d0e47d59638f7b1b4936100b988d61e6e70e22667d:e58abfad4a13859f0acb05d0e47d59638f7b1b4936100b988d61e6e70e22667d:c219de1e8d7ad8df08c49377396fe7c1f2d57bd2170633a00d708faadee180ceba92849a7778506cbb366875bf9124701894cecdb3385147d0671843922a649aff7c435eb5a9c74927503072d0067978716dc80be1545a2dbf5a1c38536e12bd7720c1965d3803a4e8aa55765192a13b705ca1059ded0e806362fc5bbe6c76a1c9674bb853790f7e90af00753e00436da48cd082ead64fddb689890162082f8482924f33acd604640f69927352b43f64402d27a883fa6b72aa70d241dffaa1701a25cf1079358260793875f76a2978e9f9f9d68634eb3f5f01bde1ce49e5921252f949f082795e4eafed7be5b49a9f95edbb4a13532e3f3b3be62e2652231253a20c1d5477e8f4bc57ed76fa19eaf03a11bba429b6496ce76246170e043bc14f2d2f703d968f1deb09388715c37cb4752da8d464e348e0313c8993e24133a7c545284e3c9c907d01b260c4883f9cb3e3dc5b6f7fb6d75536365f2132eaeddab570e7273afac0bff5c9fc0b820f2078e0336052e1fe7bdec86674d0998ec78da1c3f34751f886727695f35eca1304b14734766ab05c1186306ded9db3eef65d3c0456cdae8181afee04b296c6722a88c7ef3088d26f7fe74bc89cf5285c688f027b7e68600486af:5eae4ac72af0174ab256527b7cd337a0e5482e615af068db21dae35a64640742604df73fd4ca02ed9515a5608d73195230fadca7b426f02a2fbfd02061af3600c219de1e8d7ad8df08c49377396fe7c1f2d57bd2170633a00d708faadee180ceba92849a7778506cbb366875bf9124701894cecdb3385147d0671843922a649aff7c435eb5a9c74927503072d0067978716dc80be1545a2dbf5a1c38536e12bd7720c1965d3803a4e8aa55765192a13b705ca1059ded0e806362fc5bbe6c76a1c9674bb853790f7e90af00753e00436da48cd082ead64fddb689890162082f8482924f33acd604640f69927352b43f64402d27a883fa6b72aa70d241dffaa1701a25cf1079358260793875f76a2978e9f9f9d68634eb3f5f01bde1ce49e5921252f949f082795e4eafed7be5b49a9f95edbb4a13532e3f3b3be62e2652231253a20c1d5477e8f4bc57ed76fa19eaf03a11bba429b6496ce76246170e043bc14f2d2f703d968f1deb09388715c37cb4752da8d464e348e0313c8993e24133a7c545284e3c9c907d01b260c4883f9cb3e3dc5b6f7fb6d75536365f2132eaeddab570e7273afac0bff5c9fc0b820f2078e0336052e1fe7bdec86674d0998ec78da1c3f34751f886727695f35eca1304b14734766ab05c1186306ded9db3eef65d3c0456cdae8181afee04b296c6722a88c7ef3088d26f7fe74bc89cf5285c688f027b7e68600486af: +498b6ee6492d53231b3532d193578ba75d6a894e2e530034e21ab8ad8d2c0d1fd124665b28facd2d17946a04dfe3d129a4561a2b24eb326d84b62b422e44dbcf:d124665b28facd2d17946a04dfe3d129a4561a2b24eb326d84b62b422e44dbcf:0498a59b87cdae28695547e10863bce804d97de0ac8008f3d5fb652c1757419fdc9e0f9736f4c59a34f21cfc74599fa788fcc10c6730c7df8c3d2c1b6a786d1230b65585719d1cb5c490359b94435d6dd671f54d6e9a19b9b5aaad7e0f233f8797df997828d88cd92ef089ef7dbf1e95277894a2f7c2fd0c8e4dfdfa6d3d14589ff01916dbf9ddd811c2f5e01e94298990a145a6cfc26895614c7c963fef308a4e3856c32dd3e359bc56d2cca496ad199ff1a568d6430ac5cd208e0e2d07803ca523e0d813ad3733ab50bdcadcb988aee758ea50439bf38ee649997604f151c602c82900a8205d8f6f670c8684bf5abb5f75ff29a37eb9bf8105199fbbfb4707e162e64c715270f853e648b0aa26fea0f6db562896bf424a9ffcb292fae85b76cefb8bd5a4b3ce1fb39bd2a50d0c9e6d933e167ff629b8a494f2a9b774eb303c781ea02aff1a8afadc2465cc616968015ed6a5a33c3120b945ed5351981e32fb9fb96b2212dcf8fe9ac56e3cf41dc524f800631020b025919178ce074eef078d6842012a276efa628db54058d1eb5b5b705f1e1818d2df5164baabb0c61956ecdb8c706e562fc4fd64052870530ae425b221f89dd6f90dab882e763e7a7ffa141bbaa8bf7a3f21b0:112f5c6d3bcb3dd99346d32ad69cbfac3e653bef29c68a33f43231f66cea1d0a195427d6e10c0e77c5d55fe2794287ee32e5e22bafbbd8052ad3606b90f945050498a59b87cdae28695547e10863bce804d97de0ac8008f3d5fb652c1757419fdc9e0f9736f4c59a34f21cfc74599fa788fcc10c6730c7df8c3d2c1b6a786d1230b65585719d1cb5c490359b94435d6dd671f54d6e9a19b9b5aaad7e0f233f8797df997828d88cd92ef089ef7dbf1e95277894a2f7c2fd0c8e4dfdfa6d3d14589ff01916dbf9ddd811c2f5e01e94298990a145a6cfc26895614c7c963fef308a4e3856c32dd3e359bc56d2cca496ad199ff1a568d6430ac5cd208e0e2d07803ca523e0d813ad3733ab50bdcadcb988aee758ea50439bf38ee649997604f151c602c82900a8205d8f6f670c8684bf5abb5f75ff29a37eb9bf8105199fbbfb4707e162e64c715270f853e648b0aa26fea0f6db562896bf424a9ffcb292fae85b76cefb8bd5a4b3ce1fb39bd2a50d0c9e6d933e167ff629b8a494f2a9b774eb303c781ea02aff1a8afadc2465cc616968015ed6a5a33c3120b945ed5351981e32fb9fb96b2212dcf8fe9ac56e3cf41dc524f800631020b025919178ce074eef078d6842012a276efa628db54058d1eb5b5b705f1e1818d2df5164baabb0c61956ecdb8c706e562fc4fd64052870530ae425b221f89dd6f90dab882e763e7a7ffa141bbaa8bf7a3f21b0: +cefcfcd1cff4d8910749279131830b1da19dfc5245f78ca68b8c3c1b622b45511d394abd1b4ed1aedf966a60efd3ff882140a7e56b428374ecb443289a9c7f00:1d394abd1b4ed1aedf966a60efd3ff882140a7e56b428374ecb443289a9c7f00:5ec94ed06fc1257ae9c183ce56271207aca37a23fdb4b0e74ac9307a1bb112e05ed5a5d047c93109e2e59477b03378346422de36714c2961bb9736a513ca3671c603a68c2be7317b1b52a076dae2aff7bc88cd5eea0aa268faaadae539c938bb4fd4b6069b1945eb6af0c9e6c8aa5ee4a4af37e90c67e248e8d27bd7f9589c4d30e905651baf45364fa049957ea5d9b7146ca68204e5e973d0f1c91a1c4bded66115028a71114f0f4f851bd115faeb954e3f71a01470b2481a0098d99f9d74898c8ba0287cc7834155214173d1fcbafcfe9b08250384439476055883833816c9524cfd5744aaa259db7ebd3a6aa20b5a6546dadefd140668eb0eccb5f668db9fc62983df980850c9d19882a17550d5dca3542cd36003a0d03cffb04575a3e8e1d07015c7b30eca9115cd2b72e46dfddf6a4dda1faa2dbdc89000d433f6ec9adc46146d939f32121b99b28983d98b9dde8c3f6e5779f2b0700cb023db13de656e0aed1da2d5c6ba2652343648ad420f6ab9e55a97482a1a22b3bc2ee598629abad9547edb5ff790990564bd871f81b24b12f2bf8dbdfe7a88375fad9ccbd9fc0ba1d3bba5e3c4813c18a0348aad83fb1b82689054d99b4600dd1760d0dcce44757467bec1946406d530:7d83ff66ec79307b1c0c093fda3968a96cf6044f5c802888584018845e7caf2a135ac6f1677e84d22e458e227e4f930209919bc11b12f7aaf2b8c94302d642005ec94ed06fc1257ae9c183ce56271207aca37a23fdb4b0e74ac9307a1bb112e05ed5a5d047c93109e2e59477b03378346422de36714c2961bb9736a513ca3671c603a68c2be7317b1b52a076dae2aff7bc88cd5eea0aa268faaadae539c938bb4fd4b6069b1945eb6af0c9e6c8aa5ee4a4af37e90c67e248e8d27bd7f9589c4d30e905651baf45364fa049957ea5d9b7146ca68204e5e973d0f1c91a1c4bded66115028a71114f0f4f851bd115faeb954e3f71a01470b2481a0098d99f9d74898c8ba0287cc7834155214173d1fcbafcfe9b08250384439476055883833816c9524cfd5744aaa259db7ebd3a6aa20b5a6546dadefd140668eb0eccb5f668db9fc62983df980850c9d19882a17550d5dca3542cd36003a0d03cffb04575a3e8e1d07015c7b30eca9115cd2b72e46dfddf6a4dda1faa2dbdc89000d433f6ec9adc46146d939f32121b99b28983d98b9dde8c3f6e5779f2b0700cb023db13de656e0aed1da2d5c6ba2652343648ad420f6ab9e55a97482a1a22b3bc2ee598629abad9547edb5ff790990564bd871f81b24b12f2bf8dbdfe7a88375fad9ccbd9fc0ba1d3bba5e3c4813c18a0348aad83fb1b82689054d99b4600dd1760d0dcce44757467bec1946406d530: +d107cf26f527db71a206e41d17955321013225bb20f93e12df3dc7399e720ca3186bf453c95dc0a2fd589a78e2c80040b3f6ddf9a6f8681d146036cf2146e8fc:186bf453c95dc0a2fd589a78e2c80040b3f6ddf9a6f8681d146036cf2146e8fc:78eb9e13789928a74f360141728ede98389685c836b91fafbf1a7e8c19cfbe21bd3c3d6c6ed83c409ef693f1d735da3fa466497e19f38e30fba2a1023785459070e6e92c1cb7c9bd0c9ba61220157866c3bed2b01e6e6b9b8dd3f0c47c02f181346a0a9b9b5d3d7e18a94d6956855e16e8eaaaab71b10302f35bd8fb1f9b5847304160324926645b0582c2f2f1533a24281461514241db2850ef31c5763b2e3d4fb18fc6d8c1d7e52f7c13392c17e27019ff60008e431f1714370bc0efd9452a61f5c56488d91a185037f1f647f72fa785010d5d78f0a11587ccf66b8088e0e635fff3774193b2edeffd92d6e8a0321128ae64cdb862e631e2ee5ba0da44bbd589dc392b5a113b86a727a8ddb698a334cc668b39b1cde199b88837ca5f00f553f89c622834273641d39bc10c6a24e1eb42587542f03fc1627524ed6b749391f11028706c42364425b2caf20180e1b802c744b49b7bcd9bf7b15c23a0bf1c6965960d341554e1966b6ef82fcfbbe41d1e09d741e309254446777f13c29a67b8bdebc5f7f04d160d60e332e3d0441a0f2f7b192c3e2bdf6dadec2a424f88669806236ee04dea692bd8bb6f91ca0682ece349142575358b9b7be70600b3cb81e1456ba0799fdc01ffd68623:8071d97f324f10358f13ac8c61d424b4f300dd0419571c39e40d99aea5f03140e62ab4c97127ab33e98269966ae1d4557e459bf7f597b313f351a20122f0660e78eb9e13789928a74f360141728ede98389685c836b91fafbf1a7e8c19cfbe21bd3c3d6c6ed83c409ef693f1d735da3fa466497e19f38e30fba2a1023785459070e6e92c1cb7c9bd0c9ba61220157866c3bed2b01e6e6b9b8dd3f0c47c02f181346a0a9b9b5d3d7e18a94d6956855e16e8eaaaab71b10302f35bd8fb1f9b5847304160324926645b0582c2f2f1533a24281461514241db2850ef31c5763b2e3d4fb18fc6d8c1d7e52f7c13392c17e27019ff60008e431f1714370bc0efd9452a61f5c56488d91a185037f1f647f72fa785010d5d78f0a11587ccf66b8088e0e635fff3774193b2edeffd92d6e8a0321128ae64cdb862e631e2ee5ba0da44bbd589dc392b5a113b86a727a8ddb698a334cc668b39b1cde199b88837ca5f00f553f89c622834273641d39bc10c6a24e1eb42587542f03fc1627524ed6b749391f11028706c42364425b2caf20180e1b802c744b49b7bcd9bf7b15c23a0bf1c6965960d341554e1966b6ef82fcfbbe41d1e09d741e309254446777f13c29a67b8bdebc5f7f04d160d60e332e3d0441a0f2f7b192c3e2bdf6dadec2a424f88669806236ee04dea692bd8bb6f91ca0682ece349142575358b9b7be70600b3cb81e1456ba0799fdc01ffd68623: +af7ea8e41c8937a4ec475ad81371a171d3d0f9fd7519a04c751ed4ad8ff8fef915dfc71585bac71ef20f374987c555a3f2f07d6b9c787066c10d63cf06e02ab0:15dfc71585bac71ef20f374987c555a3f2f07d6b9c787066c10d63cf06e02ab0:05f2263f0245ecb9faeb14e57aca436668308c8125df3116c4ee20501d0cde701b366e2b50a1c5edf484144ce16bfb1f7d26dc4275ea9732e264ba4d4a362b40275ba47377dbc332cb65e2f4c8853894aa878a4c175dc5b3b2a757ff3c8d7de660973b89dadf076e2e4fc76239b7bc752a229d44e000ceb667104cb0746bfcf59d69603ae7fc1bcf11d2e33f61dc497ec1b0bd5e4f1dbef435f2f291f30b00a85e833946c8b10484e4abd7d60bdbb1fe6dff5807a53bb89382153013b70ca08efc91b7e9fc5b5dbbb6af123b57be2e140fc471a45d89fa8284cc27e0a1fe771f55598bbdcf068d506dad0a592179ceca39ee9526f9e4fe47bf2bb14fb1486a677d4d7b99a520545676a0f1fa809049aa2414ae7b817d9a036e5c157886e8341d4e819c092a3b48b3606b03acb727c6c2217d0af30121546a94af6b49caa2a8c9b1786fa0c2a524ec7a023e924b5f8a89a53780c7f8781c5b8e869430caa0e6d0437967e3aed44f45c901cbcf1026fbbd4e3dd9a091ecf8b34f7dd5038e543dc7eb6ad5494efb145cf63ec0d355bb8e172f455d8a6b13dacaaddbc56e47de3cf762a1a738ef092f1436680467b5cd82e9e36e2d2b6842b3bd5dce77180ddaf0b643378e698599dd47f5cdbb:c0f1739167274bf91831c74beb645af790459b28bb3f21325365130f409acb66df1d223759a9758e08fd7253737484e285a6fb47404abe2eba5ef249fd025c0a05f2263f0245ecb9faeb14e57aca436668308c8125df3116c4ee20501d0cde701b366e2b50a1c5edf484144ce16bfb1f7d26dc4275ea9732e264ba4d4a362b40275ba47377dbc332cb65e2f4c8853894aa878a4c175dc5b3b2a757ff3c8d7de660973b89dadf076e2e4fc76239b7bc752a229d44e000ceb667104cb0746bfcf59d69603ae7fc1bcf11d2e33f61dc497ec1b0bd5e4f1dbef435f2f291f30b00a85e833946c8b10484e4abd7d60bdbb1fe6dff5807a53bb89382153013b70ca08efc91b7e9fc5b5dbbb6af123b57be2e140fc471a45d89fa8284cc27e0a1fe771f55598bbdcf068d506dad0a592179ceca39ee9526f9e4fe47bf2bb14fb1486a677d4d7b99a520545676a0f1fa809049aa2414ae7b817d9a036e5c157886e8341d4e819c092a3b48b3606b03acb727c6c2217d0af30121546a94af6b49caa2a8c9b1786fa0c2a524ec7a023e924b5f8a89a53780c7f8781c5b8e869430caa0e6d0437967e3aed44f45c901cbcf1026fbbd4e3dd9a091ecf8b34f7dd5038e543dc7eb6ad5494efb145cf63ec0d355bb8e172f455d8a6b13dacaaddbc56e47de3cf762a1a738ef092f1436680467b5cd82e9e36e2d2b6842b3bd5dce77180ddaf0b643378e698599dd47f5cdbb: +0c57cbfcebde10ede02d1cb01df360d41f2e66a50443d58b5d4f0828c9a18bb7c4d761ba189971b9462c61bf46a765f88e2ecaa5bf2211220afb00ac657f7ce5:c4d761ba189971b9462c61bf46a765f88e2ecaa5bf2211220afb00ac657f7ce5:337703243ab5b4e4d3481ee8dd1f4494507174412658a93988b5c30403a7b7ed8522ceb46fa1ee02753a874ef0675d397c575da0b08caa8cee3393784d0f0db8459837af90b9056df4e38e417f3ad2eb1a100ef207ce2ca6c610018021661e307099f2b7c4ae875991140bdd3f0f99ad2c5d55aacb84cc1cdcd579e08072b6951fd45ed289ac9ff7f0986ac88a4fbb9dc9203d9baf180c90edf937258c9d0a6d48e220f72d250c7f2c777eaa7fb9fa11d50a5798772f9fd976b00599f1f0276f3a2e4d988ae92125467a8dedb7a16f9e3a56e8d00662b3eb67a35b9b60e73bd935077ee238df8f6e833b9a5523386826c1f2917b1c3ec98e0a5fde89c48b1d446da5d0c885fef0e374bff30a997c7bafd5e743c85d0c6aaa6ef10a061211a2327c6d84eb747a56e9bf60fcd5b553b798834d0c5ccadb9d4b54e7237d12c679c193a287bb2f511cd4ee2a2d8549b44b21c11fbe5723381c6c5f784687fd90cebc5b495af9e414f2961b06a1c8433b9aa3292bcff4241c227167f8d1de054ba33ad81da3eb3ec6e40a6e26854af349540171b75d75fb9a8d12937827fd594d317b7a8d9f1c2fcabda56375568c3e9e514c2efffc3878363dcfad9fd95436b022e8772a88cb71e803bf90381962:8af7bbe01b8ab93951d16fca05a9c967d1c52c974bea151ea72e4cebaa20cc783bb61d8d69385cac5bc6d72dbd162beef1fcb5dd0e0a08b48ca0b9f6d9a9880c337703243ab5b4e4d3481ee8dd1f4494507174412658a93988b5c30403a7b7ed8522ceb46fa1ee02753a874ef0675d397c575da0b08caa8cee3393784d0f0db8459837af90b9056df4e38e417f3ad2eb1a100ef207ce2ca6c610018021661e307099f2b7c4ae875991140bdd3f0f99ad2c5d55aacb84cc1cdcd579e08072b6951fd45ed289ac9ff7f0986ac88a4fbb9dc9203d9baf180c90edf937258c9d0a6d48e220f72d250c7f2c777eaa7fb9fa11d50a5798772f9fd976b00599f1f0276f3a2e4d988ae92125467a8dedb7a16f9e3a56e8d00662b3eb67a35b9b60e73bd935077ee238df8f6e833b9a5523386826c1f2917b1c3ec98e0a5fde89c48b1d446da5d0c885fef0e374bff30a997c7bafd5e743c85d0c6aaa6ef10a061211a2327c6d84eb747a56e9bf60fcd5b553b798834d0c5ccadb9d4b54e7237d12c679c193a287bb2f511cd4ee2a2d8549b44b21c11fbe5723381c6c5f784687fd90cebc5b495af9e414f2961b06a1c8433b9aa3292bcff4241c227167f8d1de054ba33ad81da3eb3ec6e40a6e26854af349540171b75d75fb9a8d12937827fd594d317b7a8d9f1c2fcabda56375568c3e9e514c2efffc3878363dcfad9fd95436b022e8772a88cb71e803bf90381962: +fe7172278364194bcfefb4783142b79f59d5fd978b1e47c314d78d4cb3f61c8a2e82cce47910c7e2a79bc1f419dc3c3df54f23291fc8193e8258ccd2fd38d548:2e82cce47910c7e2a79bc1f419dc3c3df54f23291fc8193e8258ccd2fd38d548:23509451a059969f2b4bdfcee5388957e9456d1fc0cd857e4f4d3c25a4155d5ee91c2053d558062eea6827950de863bc9c3df9672cde8ba741744ebbddb45ec1f4284570fd0aacd07ea58c581be2afc95ae444e678edc2a02439f387cec982ea3a44814a8a302bb3bfe8228d58de039debdf7c2a7eddb4e71ca474f94f7e2bd89dc65b1610733c91fff89bd499f40154a6198fdf5ec7ad3722d925b292196c429499075be0c5b6da9c090c0791a7019eb5e7366be6ce58ab2f04fecd9127c42718047bf47030691521312c0877aa3f36cc5fbc9caae0fde3945d2a868ee2502a3833208eb850a163cfcbf6da9ee6ad9fe067fe241986fe4436d6ae4edc61561938e2a33f4a33db63f69d3f1a8850ed40028869164103488fb795cd82ca067fe1b4897caa49a7ca9a80f3a8151fd13bbb7ff350e8579f565dc1c4a9ca938d27b15b3f858ef45d3dd78b2c358635356315f55a97528ecfec5d11a5b721503107faa406c17034e601474b3b60cf48692e269261158fc353d4df4274381357790b7756087b00cc79e3b9d28a3f2439febf199e64a8b37c91b5a4334e3354e8faf3a361e856c54bdaa43bfdcd6ee6c9f9679588f6069950832348aacba2bfeebacaa2071ddc7d77898ef0f68793cd25:f6c2a4296b9a3407c6d7a5679dae8666b503d1a17eacf71df493791b8ff0c0aa8eed36b327a29ab7828f46f22de868b628b1cfd501e8599fa31693b15f61080f23509451a059969f2b4bdfcee5388957e9456d1fc0cd857e4f4d3c25a4155d5ee91c2053d558062eea6827950de863bc9c3df9672cde8ba741744ebbddb45ec1f4284570fd0aacd07ea58c581be2afc95ae444e678edc2a02439f387cec982ea3a44814a8a302bb3bfe8228d58de039debdf7c2a7eddb4e71ca474f94f7e2bd89dc65b1610733c91fff89bd499f40154a6198fdf5ec7ad3722d925b292196c429499075be0c5b6da9c090c0791a7019eb5e7366be6ce58ab2f04fecd9127c42718047bf47030691521312c0877aa3f36cc5fbc9caae0fde3945d2a868ee2502a3833208eb850a163cfcbf6da9ee6ad9fe067fe241986fe4436d6ae4edc61561938e2a33f4a33db63f69d3f1a8850ed40028869164103488fb795cd82ca067fe1b4897caa49a7ca9a80f3a8151fd13bbb7ff350e8579f565dc1c4a9ca938d27b15b3f858ef45d3dd78b2c358635356315f55a97528ecfec5d11a5b721503107faa406c17034e601474b3b60cf48692e269261158fc353d4df4274381357790b7756087b00cc79e3b9d28a3f2439febf199e64a8b37c91b5a4334e3354e8faf3a361e856c54bdaa43bfdcd6ee6c9f9679588f6069950832348aacba2bfeebacaa2071ddc7d77898ef0f68793cd25: +a951e4e6ba9f1f0b354831c986942448faede37e11b0f247da2706dceef73ac730362014974bf75c8495c2e271e713d57384384d0a5da88edeea79279c0c58ec:30362014974bf75c8495c2e271e713d57384384d0a5da88edeea79279c0c58ec:20577dcac89174885eedb062489cd512fa72863ec5438e31e95878b75ce2772aee6290a0ba3c8f642c1d0ef55da8d5bc1484f83bb9876c7a8c0b6b609b94d112a06fc83ce8d2c1e08ed6c735e57b244aad6ecf7075363d565ba47865695c8423510909e0a3db4b61ed7aa67a7471331e83a0c58b8220a6245f65661549c1a12d4c0d50c326fb94917cbd07be51e83fe8bb3e46ca01b0a260daaf1d6abe3703d6a925113bb4d57ea1a48b4c7dbdaa03eea814a4b5f02e1dfb545cc623fe17a3bb18e4373f5f7ec2fb5217d23e4fed54a772e11323e730aad7efca8c464400e7679055fcc125a876ef7b8b9de186e229a7abf191d0c56d91815f67872e957bfbc7634aac403576a58f427bdbb30e8c4b6fc6c447741024ebb503a5a9025124a4887f825a43ee940f210a1bd5ae4f6732d60f95f2b83201c4c6dfe279412d7502a5211f8f48f800db30fc3776c4ed3a38bb4634822c98a6d6dd3233be60e42cca45a3163cc84e9e8da647c0711bc4c6ccd65aa1e972c07404d103e74bcc31a7e2c3eea5ac9257ab428947ab3dd3fb153d90694a4073373c4dd9ceb131154fe877473fd996f424f33e316e4eb02b8c7513be6998e516cbba54d94cd0a435e0ffcc2c0a8ef72b630ec24781066aa5efb9:0278c86a15208d9be5b1e1574761861b8af72ae08d40cdcbec354e65a9c3d0a06b5fcbb297d09bef397462395986c3093eeb22644c003c3078178cdf674e990a20577dcac89174885eedb062489cd512fa72863ec5438e31e95878b75ce2772aee6290a0ba3c8f642c1d0ef55da8d5bc1484f83bb9876c7a8c0b6b609b94d112a06fc83ce8d2c1e08ed6c735e57b244aad6ecf7075363d565ba47865695c8423510909e0a3db4b61ed7aa67a7471331e83a0c58b8220a6245f65661549c1a12d4c0d50c326fb94917cbd07be51e83fe8bb3e46ca01b0a260daaf1d6abe3703d6a925113bb4d57ea1a48b4c7dbdaa03eea814a4b5f02e1dfb545cc623fe17a3bb18e4373f5f7ec2fb5217d23e4fed54a772e11323e730aad7efca8c464400e7679055fcc125a876ef7b8b9de186e229a7abf191d0c56d91815f67872e957bfbc7634aac403576a58f427bdbb30e8c4b6fc6c447741024ebb503a5a9025124a4887f825a43ee940f210a1bd5ae4f6732d60f95f2b83201c4c6dfe279412d7502a5211f8f48f800db30fc3776c4ed3a38bb4634822c98a6d6dd3233be60e42cca45a3163cc84e9e8da647c0711bc4c6ccd65aa1e972c07404d103e74bcc31a7e2c3eea5ac9257ab428947ab3dd3fb153d90694a4073373c4dd9ceb131154fe877473fd996f424f33e316e4eb02b8c7513be6998e516cbba54d94cd0a435e0ffcc2c0a8ef72b630ec24781066aa5efb9: +38a9b2d49ba8b82f301a5772cea0efc2218455c8b218b22cbaa2aad2d7ad3b359df5ea1f78f810a521774602bbba4942f0459238966c8bcd21900afbf3d84293:9df5ea1f78f810a521774602bbba4942f0459238966c8bcd21900afbf3d84293:1778167c49b3a44d4a5ba838b7388553b1e13d36ea4f86d30242e1a822a3bbaff5cea63e2ae2a4635be236fef2b8135d14fb621c0bb773c9c17753f80926eb55d0f115bd09a885d844b818c9f04489a331bb5e032b8e58cda36949c5a8d08b55bb8de965e1f90d3b9cfeecfc6ad9a4ee5cb4047e9450acdc64640166a8c069ea849aebddac1ae4afec91ddd17fa5553fa87c56f7e51ec1cd6b5cc23351d057a4ce4a8923c8ae6ac7a8afdcc0881c0e74ebb024ef7296162cb93c68e50bbb074e651ac87dac9ea59d4c3fbf0fe379f3e97a24566ecae54303bcfb6f0cc9f15f6639430e66b19a427849fdfff833df02689e9de44006c903c559183459b9f4a97f54a0f2a28df7b0e9deeda8239d7b516977f5e7d6971b4502e9885f750af8d1a6669e25e77d5f327c77c87a86e0a1872bc96a76060f5f8a0c40cc973bfc7fe6ed9bca78f884e6a2828b94d489d32a0fd337e69db83fb8789afd4e8ef54c22a78c2587468b9ae071bae3b202d3183ad5f0f8e842e5a8de85bfff49e03c8381bca7fd4278ddccaf0134fb5593a395a77a5cbd434593bc4ad0ff4b8400ec674c4ecaf1d57754be0cb2fa9a6441a9abad7b42197ad82e50827e4a4245573a8f0ef87f58228a2867f4b3b834b6635037940a:e19e62ac539a9ca251d12d4c71055b0a3f581d19f2682e672404c78ac1f12bbefc91519276a5cbe16f520cf7a7f687a240f0329157c59f50026a58dcdc50fc081778167c49b3a44d4a5ba838b7388553b1e13d36ea4f86d30242e1a822a3bbaff5cea63e2ae2a4635be236fef2b8135d14fb621c0bb773c9c17753f80926eb55d0f115bd09a885d844b818c9f04489a331bb5e032b8e58cda36949c5a8d08b55bb8de965e1f90d3b9cfeecfc6ad9a4ee5cb4047e9450acdc64640166a8c069ea849aebddac1ae4afec91ddd17fa5553fa87c56f7e51ec1cd6b5cc23351d057a4ce4a8923c8ae6ac7a8afdcc0881c0e74ebb024ef7296162cb93c68e50bbb074e651ac87dac9ea59d4c3fbf0fe379f3e97a24566ecae54303bcfb6f0cc9f15f6639430e66b19a427849fdfff833df02689e9de44006c903c559183459b9f4a97f54a0f2a28df7b0e9deeda8239d7b516977f5e7d6971b4502e9885f750af8d1a6669e25e77d5f327c77c87a86e0a1872bc96a76060f5f8a0c40cc973bfc7fe6ed9bca78f884e6a2828b94d489d32a0fd337e69db83fb8789afd4e8ef54c22a78c2587468b9ae071bae3b202d3183ad5f0f8e842e5a8de85bfff49e03c8381bca7fd4278ddccaf0134fb5593a395a77a5cbd434593bc4ad0ff4b8400ec674c4ecaf1d57754be0cb2fa9a6441a9abad7b42197ad82e50827e4a4245573a8f0ef87f58228a2867f4b3b834b6635037940a: +9a1717873689a03c112dd6b4d76ae73b89b416a598ceec209e27961e7bb1ee8aeecad1e0e4b863291881a8c241db9ccfffe4e55d8b5a42f307b4436acd0649a6:eecad1e0e4b863291881a8c241db9ccfffe4e55d8b5a42f307b4436acd0649a6:e26580470901a07ab0931aa23829802ce04da59fdc2f773bc567f1e65b4f2e2d4a1a6aec1f54158adfce9b099790b503a13d22097ae23ebccf923f3bb1986d6e49111a8cf0d4eb8236bfe0d7c9e93a5efc7feb8e6a9cd1b8d921efa21e449ff49e06c1ccfea31f93e033c3c2a54ddb0f653a09fbd18a70b56315f193e7be56e5168f59563821d4bc3bbb0eaa2048286bbeee5aa3f3e7536cf2b750fd322602bb3847ceca39b75474322d76b1de80fa2eadba152d6f8f020d4d931c53f0a2801224d35deb6ec13b014873e689903607de96d9b7a743a887d2f48daf2ed2eefb202abf6082796981123b966e936dcf3483e2d24d694ecb865fbeb6969f347027fb8b175d24a4c045c0bb4ab5e02ddcbe77d4756c46d137b094473a02307a108340acad9d03bae8403af199cb75cae3162f3815813cc68bf2a5e499e594921149f3bbd214da5137e756521559dc80d9a4b74a0f4943022c7cd5fca42315e0bceeae9069615ce67a04382412313a31d67b346c329ad82e742c0a6ce0a6a02454c113e52022f3cc03fda691ebdfe14c53c8ce5ca9b932ca1a386e3eb4e90a4dc6e8ad8533b5af1aaef5003128655ca64f67fcd97c6ac803002404900bc0fae98463bcc31409f9981748789ade2d07783bc32b:1af8be095538965800d8eff6d723d028d65d0e9c6eb5e9d125bb3b1783f11ef7079a49a807e27ef1260be26a3b231d03b2ae151e49f6f189f15b1c83eab01c02e26580470901a07ab0931aa23829802ce04da59fdc2f773bc567f1e65b4f2e2d4a1a6aec1f54158adfce9b099790b503a13d22097ae23ebccf923f3bb1986d6e49111a8cf0d4eb8236bfe0d7c9e93a5efc7feb8e6a9cd1b8d921efa21e449ff49e06c1ccfea31f93e033c3c2a54ddb0f653a09fbd18a70b56315f193e7be56e5168f59563821d4bc3bbb0eaa2048286bbeee5aa3f3e7536cf2b750fd322602bb3847ceca39b75474322d76b1de80fa2eadba152d6f8f020d4d931c53f0a2801224d35deb6ec13b014873e689903607de96d9b7a743a887d2f48daf2ed2eefb202abf6082796981123b966e936dcf3483e2d24d694ecb865fbeb6969f347027fb8b175d24a4c045c0bb4ab5e02ddcbe77d4756c46d137b094473a02307a108340acad9d03bae8403af199cb75cae3162f3815813cc68bf2a5e499e594921149f3bbd214da5137e756521559dc80d9a4b74a0f4943022c7cd5fca42315e0bceeae9069615ce67a04382412313a31d67b346c329ad82e742c0a6ce0a6a02454c113e52022f3cc03fda691ebdfe14c53c8ce5ca9b932ca1a386e3eb4e90a4dc6e8ad8533b5af1aaef5003128655ca64f67fcd97c6ac803002404900bc0fae98463bcc31409f9981748789ade2d07783bc32b: +43bd924db8156008c6b3994a8130d427d514db8a613b84dfb0b8e0de6ac306761b3461c269d5b0062d5df6fa654a2586f647a0684218a06e5e2f7badfb394131:1b3461c269d5b0062d5df6fa654a2586f647a0684218a06e5e2f7badfb394131:6184e6480c42e96cc877269b16371545ff9523c45ea88e76a1348c68ae7f318b088fe4610928239185b6b55bfa0f43644c4a4c97c56ed77d08b1f4aad2f4aa069994abeca96b7bf81b8064ea4350d8a8b02297a51308b61c57c8f1873c6f97007aca3180429e730a6643f28733547bcf7b9adfe327e85736bd04af7f1d9f4fb84a7f3affdf4e22b574ecb4bc8836b10b8453aeaa5c1bf132248b826cc5230f75e075fac9f037561136e00643d08253e7ad652f702c0d15b6d7d48aa6f8e9b5f5cc146e3f156fb2522751c3710041bd922f37a50377e028b0c4e4bc3465d7c84af6a5fb427acb3b41378b102bda46d8f6f203a5ffcf395d435e93458a0b0a4c2e7782fafe119f769f67058c6677f6d10d9cf5cb8748e1805798ed233f6f930eee0e5075bc58b97af9177fda75d53708beb04dc4f19a43e768074609f14065f48fdad5077ce109bacc357174a6b7956f6e7f32e38415be526370fa58c3c0b31f51e6cd4b2cf27f8bcbc21259d9e5c3b5c2946a9fc1b00d9d15c3b7d80bfd9d05db91d249d3e42d8956682044548d83bda8d5cc9212442f30b45cf4aead80cce9b3512c39c5c737d3f8d747afbab265af5eeef8ca9362ec76e943b0a0d7a39f3db11eca14458a7b592e5e4ff2275dd48b2853:d2a05d88d9d543d94d57ec88ae55681750f20b9be9c1e918cdaf457767f2948dd629e94f068edcf3d9927e330234badc3a02fa5ad3d9d85e948cb0b0cb3cd70a6184e6480c42e96cc877269b16371545ff9523c45ea88e76a1348c68ae7f318b088fe4610928239185b6b55bfa0f43644c4a4c97c56ed77d08b1f4aad2f4aa069994abeca96b7bf81b8064ea4350d8a8b02297a51308b61c57c8f1873c6f97007aca3180429e730a6643f28733547bcf7b9adfe327e85736bd04af7f1d9f4fb84a7f3affdf4e22b574ecb4bc8836b10b8453aeaa5c1bf132248b826cc5230f75e075fac9f037561136e00643d08253e7ad652f702c0d15b6d7d48aa6f8e9b5f5cc146e3f156fb2522751c3710041bd922f37a50377e028b0c4e4bc3465d7c84af6a5fb427acb3b41378b102bda46d8f6f203a5ffcf395d435e93458a0b0a4c2e7782fafe119f769f67058c6677f6d10d9cf5cb8748e1805798ed233f6f930eee0e5075bc58b97af9177fda75d53708beb04dc4f19a43e768074609f14065f48fdad5077ce109bacc357174a6b7956f6e7f32e38415be526370fa58c3c0b31f51e6cd4b2cf27f8bcbc21259d9e5c3b5c2946a9fc1b00d9d15c3b7d80bfd9d05db91d249d3e42d8956682044548d83bda8d5cc9212442f30b45cf4aead80cce9b3512c39c5c737d3f8d747afbab265af5eeef8ca9362ec76e943b0a0d7a39f3db11eca14458a7b592e5e4ff2275dd48b2853: +8fb086206dd95a2621f598560ccb281f8273c8fc72e23611089baac89d3c3c7820276ef479f4d4523ab77420d424e8819c33c83779ed80c7f666e8f4403f94d7:20276ef479f4d4523ab77420d424e8819c33c83779ed80c7f666e8f4403f94d7:f02903ed4266e849a4485205954fffa8a108c323b7e3f84331043514e48556ab019497233a5a127bff3cd7c97086becef538b3f339d7d06e532dc7325e597ae357f816dea42a6a22c79d22074a2e1ad8023c424b7e096e5ad8897b05ef7d00d30a04aaf2981eddff2b347f1e27e20aabbe7e7a9544978e092b00cce420aba06187374ffbb37b4c22d75f04e57590f610a27347286c298312a6c9b1bdf24fbda8513c4f8356ccf757068ffc11bc65113783a5dde7722faf4ceb19fbb62f40702e2c6e6a8bb49ef40446450c4c59a2990944da4744f6ee770b930c246669813ce5a9f5a47dd80388981bfcc3a56b5be2c4c7e659a2e9182dec0aaafe9031aa3954d4fe7c431196a561a5b78eaba64f3db1b586c53b16f679a84921a642c260e4653a61de108ebde6f7053afa2cb3f3668ede121020dd1bace8418aebac3a5bd5142f105ac26fe49e5fb140c19b22d54a6291dfc954670247881646874defad814995519f6260e9774a8d185c37881b4f2543c4b63fbf1985016ab41c4d728cbc90b3ab876267bed41d0c0902f6b50e8fa906fc4788f7b820467306e0fe9e036a0a00f804f91c3ca718b95ff6d9e2204bc3161bf70fcc17b2964b56bc612e29402d96f50986514bc7d831d58e42793786d5806f:a9305e001600d597d05ef671699bf09f0dcc0c44475d3ca31e7ff1bffedc0c67daa1f3b76a035948c59cd87f82453a40950a1c9703c2e7d9280e7303966da301f02903ed4266e849a4485205954fffa8a108c323b7e3f84331043514e48556ab019497233a5a127bff3cd7c97086becef538b3f339d7d06e532dc7325e597ae357f816dea42a6a22c79d22074a2e1ad8023c424b7e096e5ad8897b05ef7d00d30a04aaf2981eddff2b347f1e27e20aabbe7e7a9544978e092b00cce420aba06187374ffbb37b4c22d75f04e57590f610a27347286c298312a6c9b1bdf24fbda8513c4f8356ccf757068ffc11bc65113783a5dde7722faf4ceb19fbb62f40702e2c6e6a8bb49ef40446450c4c59a2990944da4744f6ee770b930c246669813ce5a9f5a47dd80388981bfcc3a56b5be2c4c7e659a2e9182dec0aaafe9031aa3954d4fe7c431196a561a5b78eaba64f3db1b586c53b16f679a84921a642c260e4653a61de108ebde6f7053afa2cb3f3668ede121020dd1bace8418aebac3a5bd5142f105ac26fe49e5fb140c19b22d54a6291dfc954670247881646874defad814995519f6260e9774a8d185c37881b4f2543c4b63fbf1985016ab41c4d728cbc90b3ab876267bed41d0c0902f6b50e8fa906fc4788f7b820467306e0fe9e036a0a00f804f91c3ca718b95ff6d9e2204bc3161bf70fcc17b2964b56bc612e29402d96f50986514bc7d831d58e42793786d5806f: +afa1b846c210b52300e97696f81b8ea774d1df12e612527c55747f29c1937396b609566bbd1947bd7afaceb14389e836227169215fab66851aa5d70d6e2e3b89:b609566bbd1947bd7afaceb14389e836227169215fab66851aa5d70d6e2e3b89:4cac1b1f4bd48284dcc9afc8b5955b64b436db704b0335d9755cc1f97477f8d323cb6410ef146ab8a9efb9526d8b62e3bbad1f7295f47ba9f0de958f8ec9b77ab42232437ed974856444cd22e20be35e91813bff4b016f810d0f61d89f6b614db33f34bd09985b593fe3e06e065b7bc6cd39d55c2cfbec7b6d59c0b37dd1d0d35135ab1d1b04f2f30c2f04f4ba2b36582738081cf59190f528363db944ed612931d1d514c6214f9ab92abb1833926183ac52fba2a4551e20e4c0ac959a49ddb167a381e0241d40c086e90e52aca017258975dbab2ba451ee539a718f076a58709c6697418d9c6f13e4d391368bf0e8bd8f2932dd95ceaf7aaca1241147d341a3acd08dc32905483572b89a80cc47231468ab8de359dd525a6257cf196c2ecb82fa8a78aa3a851c7c96ca25bf7ca3dcf3ca21453d0dfd3323d5a422dec84316102f684c359f226bb53779c0b9950939281ef79a58c011993eace085497afa4daf64c9687b0a11aa116cfa7b03936241a5567b646e7e42e9fb592405b8fa3c0a821fc3121b45b1753cec9a83947d211a45499bd63790b87f01472fe566d87696efedbb74ed00048c384ba7f027b3aa4298dc4110349fedf52a96cd05d08bd635771ed4510738d8f07a6021244d1903579a3ea739:98b0c6313cecaf7c82cbdeb3d0280641c61a060f65e563aa93ce18300a9b58272dc8680b485e8cd11cf80fdca868fab365378384a142727f2f844f87cfdf19054cac1b1f4bd48284dcc9afc8b5955b64b436db704b0335d9755cc1f97477f8d323cb6410ef146ab8a9efb9526d8b62e3bbad1f7295f47ba9f0de958f8ec9b77ab42232437ed974856444cd22e20be35e91813bff4b016f810d0f61d89f6b614db33f34bd09985b593fe3e06e065b7bc6cd39d55c2cfbec7b6d59c0b37dd1d0d35135ab1d1b04f2f30c2f04f4ba2b36582738081cf59190f528363db944ed612931d1d514c6214f9ab92abb1833926183ac52fba2a4551e20e4c0ac959a49ddb167a381e0241d40c086e90e52aca017258975dbab2ba451ee539a718f076a58709c6697418d9c6f13e4d391368bf0e8bd8f2932dd95ceaf7aaca1241147d341a3acd08dc32905483572b89a80cc47231468ab8de359dd525a6257cf196c2ecb82fa8a78aa3a851c7c96ca25bf7ca3dcf3ca21453d0dfd3323d5a422dec84316102f684c359f226bb53779c0b9950939281ef79a58c011993eace085497afa4daf64c9687b0a11aa116cfa7b03936241a5567b646e7e42e9fb592405b8fa3c0a821fc3121b45b1753cec9a83947d211a45499bd63790b87f01472fe566d87696efedbb74ed00048c384ba7f027b3aa4298dc4110349fedf52a96cd05d08bd635771ed4510738d8f07a6021244d1903579a3ea739: +c85913a6877877131001623ccda9cdc12b9d4043b8a83793c44696632cd6421c9cc67c6948f7bf6e556d0849d3b8d203457a7b61549b36681d754f1dc0841e96:9cc67c6948f7bf6e556d0849d3b8d203457a7b61549b36681d754f1dc0841e96:91b5009e83d0f6103399c2d3feec0084973a305bf4176ec782537560472db187a11b4dcb4b2ffb7f0644feb394b28e5bfe97247c4a4a231cf6e916bf99344ccda88a7f5d831d6de3d563dd102eaeb108c5bdce44e0632d17e6fa55b18067df2fa8d200a9869f6aff920c51d46a1ced2d903b1d9b6b075facbf91cd05eb41ad811a8ef40d9118261012c72b8979f15153dbb8561293da9f8b77c8ff14f75387536f0036d1713a72ce8c35b1062f2c6732aebf32936799b51c2cbcd6572413e7dfaab8641a02c150237381cf7a14e22c74c6c20009de7d3b7e69cd1b4584ac2c01babaf973c56b3814bb0089720e41968106cf26509d4aa546fcad5534af303ffca42b16ae6c93ee06bc3cace12e4ec718844bd30d2224cc486d106d1c456bfa165ea0120fab3df2c5ab3a523bbfa789deed44032ab0be86eb7cc09cdb7c07aa948dd5277c3df1d9d1843567dec84f9288e085b05ae4b8af2cea5d9a184d50bef85550c836613d5d3af5f9c2928e6a89660fa62719ebff773e46b77e34bc0470da4d2cdbc7071da758c4d39fe65201c88aaa8e6603d0bbe7c3e9b2d9e41b634682092f147341ad6d667f20c64e81a68d629467a54dd86e1ce12c560a6f9b64512d6f3886cbb9f37c37eb3985c8ac38dd6682f48fe1:01fccfdb1fb6888b0310a913170f7e366816daebe7650d72513d9506e66f7d62208a49ece0af1871497f4541ef605bde711c9e0a1205ef48f26c03dc1ad4af0391b5009e83d0f6103399c2d3feec0084973a305bf4176ec782537560472db187a11b4dcb4b2ffb7f0644feb394b28e5bfe97247c4a4a231cf6e916bf99344ccda88a7f5d831d6de3d563dd102eaeb108c5bdce44e0632d17e6fa55b18067df2fa8d200a9869f6aff920c51d46a1ced2d903b1d9b6b075facbf91cd05eb41ad811a8ef40d9118261012c72b8979f15153dbb8561293da9f8b77c8ff14f75387536f0036d1713a72ce8c35b1062f2c6732aebf32936799b51c2cbcd6572413e7dfaab8641a02c150237381cf7a14e22c74c6c20009de7d3b7e69cd1b4584ac2c01babaf973c56b3814bb0089720e41968106cf26509d4aa546fcad5534af303ffca42b16ae6c93ee06bc3cace12e4ec718844bd30d2224cc486d106d1c456bfa165ea0120fab3df2c5ab3a523bbfa789deed44032ab0be86eb7cc09cdb7c07aa948dd5277c3df1d9d1843567dec84f9288e085b05ae4b8af2cea5d9a184d50bef85550c836613d5d3af5f9c2928e6a89660fa62719ebff773e46b77e34bc0470da4d2cdbc7071da758c4d39fe65201c88aaa8e6603d0bbe7c3e9b2d9e41b634682092f147341ad6d667f20c64e81a68d629467a54dd86e1ce12c560a6f9b64512d6f3886cbb9f37c37eb3985c8ac38dd6682f48fe1: +fa1e11dc8364208d8e1cb66a361be7e84c5e368166587d4fdb06aced7f62e17c4d8e6f4b3415df6cedabfb295c1984fd419923c6ac41764e32d22daf372c50fc:4d8e6f4b3415df6cedabfb295c1984fd419923c6ac41764e32d22daf372c50fc:294e63bacccb801bbf04c1f19d0aee16f5650a6e8eea6fe41110663ec01532bd4960a527f15eca4af2f4e6b7b0fc340cf97aa234e92cf7d69d50e4009c2496e3ed4d9aff000f9e185275b817d26a0bab69b7f7ee1ea30daec8bcee387ae46b4b299c27bdc06eea63f24dbee955a6c0969037eef91c34321e3c5c972fde993183b7d23f6e019c3e0cac7589ae4a1521af87ea42df8c22c2270ec23d6d140f9cf6d4d52fac1b9d6c8939ef8131cb62a035c5261538bcdfd6db419a55ef9fe5d7a5ac44579de700858d74a3434844f28342c565892722e27f407d7f17b74a5934be915b20c2400643235f8ab5795f324e33c50644a04033542cb3816d770fa899e7311c14301c1bd0f5aa60a2eb3165680c720e1efa8096fc25d2779275f1842b2db53b4da0ad3e59c07540c28460cec1fdd3cdb7a3478b91a9caf9ac891cdf3aeaeeca9a9656ac1307259922fca74c5cc69f7e25c6bf587973a4b7d3e3ac0635b0db22a0093a79076881c71736ee1d4d45f8ed2d29a0671a64e6ca2f7a5ef404b1edeb842034f571b699bc59e5a37df02054e8482bf1e7b77d8e8397da15d89d7355a5dce86b1683a9ac4e406c08a94a6eb00e5ae16d96722972e5c50c7bee4a84d0697bbe67ceb7ef295f06aaea5abba44466be0f67:e857db087e28d6750bf54e53797251d8439989576c12da2d9c811a14877c3bd46c4efab861a10eebe7da04c0b0b445c7a390a50c13de36f3a3c7ae0157022c0e294e63bacccb801bbf04c1f19d0aee16f5650a6e8eea6fe41110663ec01532bd4960a527f15eca4af2f4e6b7b0fc340cf97aa234e92cf7d69d50e4009c2496e3ed4d9aff000f9e185275b817d26a0bab69b7f7ee1ea30daec8bcee387ae46b4b299c27bdc06eea63f24dbee955a6c0969037eef91c34321e3c5c972fde993183b7d23f6e019c3e0cac7589ae4a1521af87ea42df8c22c2270ec23d6d140f9cf6d4d52fac1b9d6c8939ef8131cb62a035c5261538bcdfd6db419a55ef9fe5d7a5ac44579de700858d74a3434844f28342c565892722e27f407d7f17b74a5934be915b20c2400643235f8ab5795f324e33c50644a04033542cb3816d770fa899e7311c14301c1bd0f5aa60a2eb3165680c720e1efa8096fc25d2779275f1842b2db53b4da0ad3e59c07540c28460cec1fdd3cdb7a3478b91a9caf9ac891cdf3aeaeeca9a9656ac1307259922fca74c5cc69f7e25c6bf587973a4b7d3e3ac0635b0db22a0093a79076881c71736ee1d4d45f8ed2d29a0671a64e6ca2f7a5ef404b1edeb842034f571b699bc59e5a37df02054e8482bf1e7b77d8e8397da15d89d7355a5dce86b1683a9ac4e406c08a94a6eb00e5ae16d96722972e5c50c7bee4a84d0697bbe67ceb7ef295f06aaea5abba44466be0f67: +24a914ceb499e375e5c66777c1ed2043be56549d5e502a844710364042ba9acb20d21ee764b1f35f94568200d63bd5828aca8c5d3e9047d23f478b925295fa2e:20d21ee764b1f35f94568200d63bd5828aca8c5d3e9047d23f478b925295fa2e:3ff9f66fa2646ec66a1bf933c2b4cc0fbf912b4d6db50534257f97d01e698d05485747de2544e9f5a4a4a075388cf4400ab89b0353ce86198202db3a903767b879a2af9daa155843111af15a2bc35efe41bcc92c8207e00113b04f1303007949ffb6ce8df4b0b34248fedf5d9cb2cee94b812ed58ece2a0ce0454cf14c20e49e09fe664d6e25762e87895932cd5cd32eb6a3abb38ee163078c133e93588791dbf6af499a31ea4453bbcc7a85e406c9848a664052f11113fbb4ffa760dee4c261e396942491119da29a33582f821d4125e0b4162f28beb066031a652d05749aa7244dd4f3d3bb15d268328d6a02fce2501815257f8ad5af4ecbe7cb8ae9661e344f9072318791f3e859091121e08aefca8982eaaf66259d9de4f46a31e716dc033d0f95d1fa936b6c6079b137dd1158d1def113018c73f8ebb9807e0f7415404ea9c78544ace7ce463cd1d1c57e31f4091bc091804cbcddad0e15a40ca91acbe1c6224ed13cafb4df2c84ac9f0c3c9b546007d9dd6e524c467072563d4ac0d700cc1bf30febb334313dae5761745ec0a5e9e8815025958f00fa2e58060d7e9a5f2b727f48699f929c8459930892573f784fef5692518b5ca268e2a73ebead6ebdeb7ec24eac92aa7dcb41b598bd6eff3632d069726291:3ae0cc7bca8d73be83a9b809b13338c12706aaef75c4d1a478178f9dc565514c7529e298043ea78d21a5a09dd04f10ae87441e5686a933c92c75548427ad3a033ff9f66fa2646ec66a1bf933c2b4cc0fbf912b4d6db50534257f97d01e698d05485747de2544e9f5a4a4a075388cf4400ab89b0353ce86198202db3a903767b879a2af9daa155843111af15a2bc35efe41bcc92c8207e00113b04f1303007949ffb6ce8df4b0b34248fedf5d9cb2cee94b812ed58ece2a0ce0454cf14c20e49e09fe664d6e25762e87895932cd5cd32eb6a3abb38ee163078c133e93588791dbf6af499a31ea4453bbcc7a85e406c9848a664052f11113fbb4ffa760dee4c261e396942491119da29a33582f821d4125e0b4162f28beb066031a652d05749aa7244dd4f3d3bb15d268328d6a02fce2501815257f8ad5af4ecbe7cb8ae9661e344f9072318791f3e859091121e08aefca8982eaaf66259d9de4f46a31e716dc033d0f95d1fa936b6c6079b137dd1158d1def113018c73f8ebb9807e0f7415404ea9c78544ace7ce463cd1d1c57e31f4091bc091804cbcddad0e15a40ca91acbe1c6224ed13cafb4df2c84ac9f0c3c9b546007d9dd6e524c467072563d4ac0d700cc1bf30febb334313dae5761745ec0a5e9e8815025958f00fa2e58060d7e9a5f2b727f48699f929c8459930892573f784fef5692518b5ca268e2a73ebead6ebdeb7ec24eac92aa7dcb41b598bd6eff3632d069726291: +5532e09b937ffd3d5f4c1d9f1ffcded26ee74d4da075264844690bd9c86139945093969f377bec3e35f59efda01ab4186c5d2a36740cf022675e01096b1a3f0a:5093969f377bec3e35f59efda01ab4186c5d2a36740cf022675e01096b1a3f0a:add4d7a9ce3f63d1f946e8679065545d8c7bf0a2cc3a4c00b8f142f0945ae362c4c9462a7576a4059d57861662884bd80b96d90d279a952eda952d37d4f95cf0d70da98f4fbaca39e169f9d945d41f872397bbdd5701454303d77d31e86348271da40a1b8f1e57c36fcd803e14fa17716c5631efa01d3a795dc20b2bde36ab73ff6a2d533bc15cce22328713c3c9ccd072c3e450d7f22c0c9f94919752cbfe45ee655d1b53676593cdb448704102631caaa976952eaa1f6c2e876564e420f0c646a0f88365f76415b4085f60a338b29c51633e540f0bf32d4087e7d0fb685be88c7595dc531c99b489584560ad8234b18e39a107cf5d842dabd421e77d26ea5e0f1405ce35fe792714eb4ee1a8017648ac1ae739a33d7b1e089105d1e5add27a62ce64154570340af9eb14e7fdfc2f9a2c2fcfcdac3cc4227763f4d629497479f849216e5d90ec16dfa36b72517f7b5486baee7fda4450c352cffbbae73926c843224f8ce44b38dae53f3ead21890b52a7801075291684fd5910ed86ad33e8a007f6c3f85c16b209293740184f5890874d431cd4e0ea4087c49c3471d789c813c6dc9a78699363a1d87197d3b92c0286689311823f4df22ce8035e75732cdea7f5621f67db0e2a4ca6616193221c0aa3d6de50d85282ee:d527ff0d4a219d61f418121206a54ae4985854a310482744486e4d130a7de97c319df8372c82828c936e6a8afd9c5de1828573d8261ae9365b8f237676182402add4d7a9ce3f63d1f946e8679065545d8c7bf0a2cc3a4c00b8f142f0945ae362c4c9462a7576a4059d57861662884bd80b96d90d279a952eda952d37d4f95cf0d70da98f4fbaca39e169f9d945d41f872397bbdd5701454303d77d31e86348271da40a1b8f1e57c36fcd803e14fa17716c5631efa01d3a795dc20b2bde36ab73ff6a2d533bc15cce22328713c3c9ccd072c3e450d7f22c0c9f94919752cbfe45ee655d1b53676593cdb448704102631caaa976952eaa1f6c2e876564e420f0c646a0f88365f76415b4085f60a338b29c51633e540f0bf32d4087e7d0fb685be88c7595dc531c99b489584560ad8234b18e39a107cf5d842dabd421e77d26ea5e0f1405ce35fe792714eb4ee1a8017648ac1ae739a33d7b1e089105d1e5add27a62ce64154570340af9eb14e7fdfc2f9a2c2fcfcdac3cc4227763f4d629497479f849216e5d90ec16dfa36b72517f7b5486baee7fda4450c352cffbbae73926c843224f8ce44b38dae53f3ead21890b52a7801075291684fd5910ed86ad33e8a007f6c3f85c16b209293740184f5890874d431cd4e0ea4087c49c3471d789c813c6dc9a78699363a1d87197d3b92c0286689311823f4df22ce8035e75732cdea7f5621f67db0e2a4ca6616193221c0aa3d6de50d85282ee: +eb36511009d37a9c46c4d1374d0bbd0d9981e78cee7d188c5aab983ec239e10cb1cc212b4521bbe7b19a7693878a558440eec36205d8439d040a46a9902fbf55:b1cc212b4521bbe7b19a7693878a558440eec36205d8439d040a46a9902fbf55:ba2466e56c1df77f22b6f0241fc7952ae9bc24756419a9446dd2b49e2cb9df594e5b6c77a95aa5fbd9dc57fec83962c7751eebb4ba218253f916a922a5139663e3203e3be482be379ca151c463d9ada21446135f356994fa5449f084478f5bb4f5ba6145c5158eb7b1c43c32ebea25e09c900f01ef91e92f88c03c76504ace9646016ffc2789559d0f3cc9d00fb61bdc6af7d3940f302e588e04f79f7b3d4b91a5d193a4f8222bfeb69bf0347d98ad81ef99d130ebc7b36b0783394eea92a38ddd5e7480d2add4e4def53eb99c449bff94e4718b09f2ea9b1f2b886594a95c33a69e0333154e440ab34b7b6c1134d8179b6f0c56251a9ad8e1b6b0f9b8a5c97081a7f8fd05d0b0affc82dbddc8b0c0ab7e833f300626d4b973b3f60feac55571e89cda0f2b441ed2faa669a70d556cb48f9b1d1cbce32ede5d166b1143e264b11ea327681cb559edd13c364bd2baf1fd54bb781807bd59c868b0e4795a779e67f0bd0d14b5a6b9e440b57a5823328b59affbd027eda7dd785079c5f02b5e32890b038730986a39a5a9834a3fed868b6f45cbdd28acb2709aff556263864f9ae1e757b3278c288dbe2932825712773e431f7c29329857fdaea798ed93920893631402e6b13bab62b4855461edb94620f2d1751865f445c466:9f583724de552eae82f254ac6e2ed483ec1a07346266735c490920690c1e3fb2a9e9a34194ed6473733b300d4f23c9aec0da5a2022054ca43885a15a2984320eba2466e56c1df77f22b6f0241fc7952ae9bc24756419a9446dd2b49e2cb9df594e5b6c77a95aa5fbd9dc57fec83962c7751eebb4ba218253f916a922a5139663e3203e3be482be379ca151c463d9ada21446135f356994fa5449f084478f5bb4f5ba6145c5158eb7b1c43c32ebea25e09c900f01ef91e92f88c03c76504ace9646016ffc2789559d0f3cc9d00fb61bdc6af7d3940f302e588e04f79f7b3d4b91a5d193a4f8222bfeb69bf0347d98ad81ef99d130ebc7b36b0783394eea92a38ddd5e7480d2add4e4def53eb99c449bff94e4718b09f2ea9b1f2b886594a95c33a69e0333154e440ab34b7b6c1134d8179b6f0c56251a9ad8e1b6b0f9b8a5c97081a7f8fd05d0b0affc82dbddc8b0c0ab7e833f300626d4b973b3f60feac55571e89cda0f2b441ed2faa669a70d556cb48f9b1d1cbce32ede5d166b1143e264b11ea327681cb559edd13c364bd2baf1fd54bb781807bd59c868b0e4795a779e67f0bd0d14b5a6b9e440b57a5823328b59affbd027eda7dd785079c5f02b5e32890b038730986a39a5a9834a3fed868b6f45cbdd28acb2709aff556263864f9ae1e757b3278c288dbe2932825712773e431f7c29329857fdaea798ed93920893631402e6b13bab62b4855461edb94620f2d1751865f445c466: +7dbc81902e4eaab3077540f559995c387403cac306d486e959c5eb59e431c0a8e03066139082f613448bdbc27fe53aa3f88994c31ddce002e36bbb2963df3ec8:e03066139082f613448bdbc27fe53aa3f88994c31ddce002e36bbb2963df3ec8:dff798b1557b17085a0634371ded5ddf7a5acb996ef9035475e6826336f64ad8b84b882e30badec2b4a711998752f4a1574bc1f89d4325cf2b39861044dd03691e71d07768b5933a3052cc7c81d571a9de061dc19026c2f1e701f2dcf26a88d3401bc99fb81559dca76d8a31a92044a273587d622a08d1cce61c8f948a34ded1acb318881c9b49f6f37c30a65d495b02d5429e7ab4040d8bebeb78794ff736d1511031a6d67a22cdf341b980811c9d775fb19c6478f05ed98430103ea24c0f414d4cc07d860b72dc542ff22d83845a42f8ba45ca7ff3aab0b1e7de2b1094deac08d16eee01969f91bc16fec29ccc061c54db5345ba64842dacc99ee7729468d80a3f095583d8e8012408519d582cc3ff9a2eb7aebaa22db81ffc78ee90ef4ec589dcce87118dab31a6328e409ad5059a5132c82df3cefe2e4014e476f04c3a7018e45267ec5018ecd7bff1dda9267e90666b6b1417e89ddacb5085943befc7ad2f4df5f1ee0af9431aeeb6b24a5515b93dbcf68640f7daf8c961e567d7534900205c3df2184b6ac2da961c4c1d2bc49b4ea96b8154ffd4efffdc5e55a7119cb8af429e85105dffd41fe4a2ebba48168aa05fa7df27c4298735ff868f1496beb4b2ed0b8980c75ffd939ddd1a17e44a44fe3b02795339b08c8d:5b7f652f08f229fda1b0bd759377b3fb726c1b9c9a10ef63426d352dd0869bd54d876c3092f1cd411c3757d3c6b6ea942aa70c3aaeb4217a4c7364d18e76e50fdff798b1557b17085a0634371ded5ddf7a5acb996ef9035475e6826336f64ad8b84b882e30badec2b4a711998752f4a1574bc1f89d4325cf2b39861044dd03691e71d07768b5933a3052cc7c81d571a9de061dc19026c2f1e701f2dcf26a88d3401bc99fb81559dca76d8a31a92044a273587d622a08d1cce61c8f948a34ded1acb318881c9b49f6f37c30a65d495b02d5429e7ab4040d8bebeb78794ff736d1511031a6d67a22cdf341b980811c9d775fb19c6478f05ed98430103ea24c0f414d4cc07d860b72dc542ff22d83845a42f8ba45ca7ff3aab0b1e7de2b1094deac08d16eee01969f91bc16fec29ccc061c54db5345ba64842dacc99ee7729468d80a3f095583d8e8012408519d582cc3ff9a2eb7aebaa22db81ffc78ee90ef4ec589dcce87118dab31a6328e409ad5059a5132c82df3cefe2e4014e476f04c3a7018e45267ec5018ecd7bff1dda9267e90666b6b1417e89ddacb5085943befc7ad2f4df5f1ee0af9431aeeb6b24a5515b93dbcf68640f7daf8c961e567d7534900205c3df2184b6ac2da961c4c1d2bc49b4ea96b8154ffd4efffdc5e55a7119cb8af429e85105dffd41fe4a2ebba48168aa05fa7df27c4298735ff868f1496beb4b2ed0b8980c75ffd939ddd1a17e44a44fe3b02795339b08c8d: +91b095c8a999e03f3ed749cd9f2faacc0076c3b477a87ab5ccd6631738767446dad174d359daecca9c6b389ba096452ab5ca91e6383c6d042a284ece16ba97b6:dad174d359daecca9c6b389ba096452ab5ca91e6383c6d042a284ece16ba97b6:9b0d8b00299852d68bbf497fe603961a485466a99a5484005db73d4e4bad814e8574efd54d648bd5c91ae8483c54b2f998b02e1abd6f401a25526843a5f2a23a97bd589d1f7e1ab14915b1e359a396d352c360ae6584325ae4bb7d624f61255c5c7bf0a67acab46c3b57b34534c0ee8431d260576606cbd84d8d1839e73da6fe4b0b8b78f0f958827c2f1d93ba7a346dcc75cb563dffde26f997598e8b5c2f1617c6fefc9be4b28b5401b0006413a251690d1203aaae4f6d8a3fb21f24009ab3bff13737a8a7e6646c02732d9ec5a4a510469e2d299e4cc1ad6480a482aa956f89ddcccc64a136fb15b876b6ecd88c7c86a4dfc60e666207c604167d163440ca9ab9cf87a5e0f7bbc5517de4dee876c037f8cc9d959c8ff5dbe944ff54cd91a771e29231f8b5f17d61de904c955fe2025dc52ed480fb3cc90f232459c607ef7e2adb52c7482becd67ad2149a4128f984038b58aa90176782393604aac74c18209a3d6a78630c01955a7cece5da8384da3baf63aa2ddf5963fae05ba3b81c6a03d86a00ef78edb4184fdc89b1d6bfeb310fd1b5fcce1e219524a3cfb2e972577f06b1dddeba00865dae4979000c008ad99f3b638cceb8e8c7a0f998d34d92143d81c0e1c096a925ceba65c43003ee18d494d003e9c61f77d65759:64ee9efdb0c2601a835f418520641e436c7dd47c333d9fc30cfbb9e390fe764530654708b40b03581899a9ac870efd766ffbb4637152f8ff277964fe354252099b0d8b00299852d68bbf497fe603961a485466a99a5484005db73d4e4bad814e8574efd54d648bd5c91ae8483c54b2f998b02e1abd6f401a25526843a5f2a23a97bd589d1f7e1ab14915b1e359a396d352c360ae6584325ae4bb7d624f61255c5c7bf0a67acab46c3b57b34534c0ee8431d260576606cbd84d8d1839e73da6fe4b0b8b78f0f958827c2f1d93ba7a346dcc75cb563dffde26f997598e8b5c2f1617c6fefc9be4b28b5401b0006413a251690d1203aaae4f6d8a3fb21f24009ab3bff13737a8a7e6646c02732d9ec5a4a510469e2d299e4cc1ad6480a482aa956f89ddcccc64a136fb15b876b6ecd88c7c86a4dfc60e666207c604167d163440ca9ab9cf87a5e0f7bbc5517de4dee876c037f8cc9d959c8ff5dbe944ff54cd91a771e29231f8b5f17d61de904c955fe2025dc52ed480fb3cc90f232459c607ef7e2adb52c7482becd67ad2149a4128f984038b58aa90176782393604aac74c18209a3d6a78630c01955a7cece5da8384da3baf63aa2ddf5963fae05ba3b81c6a03d86a00ef78edb4184fdc89b1d6bfeb310fd1b5fcce1e219524a3cfb2e972577f06b1dddeba00865dae4979000c008ad99f3b638cceb8e8c7a0f998d34d92143d81c0e1c096a925ceba65c43003ee18d494d003e9c61f77d65759: +8c568b310ace7d1f0edecefd603a884000544c792565d481c3d3e06e2d82ca965fa6e267c766736841411072d1983d1900acf01d48c3ce11770b26f78da979f7:5fa6e267c766736841411072d1983d1900acf01d48c3ce11770b26f78da979f7:b59f5fe9bb4ecff9289594721f2647047b0da5e0e4941bbe57c5b722b476723f0ac5970b4111f893bcaa411f28fceb4f585a2a7187018a904b70ef8fe1f6569a54d00ada37b69cb5e9c9d26c16a903518148e04a1b936a32329c94ee1a8fb6b591892c3aff00bf6e44dd0a762babe89d7060c17b90390d23bf9d360a293b8308383086916e1182b1ba4336f001b8d20deae9a029f7e85397a9ae5cf3ca10c7f3875588b8ffabb063c00ca26f580f69edc527a1accf4f41397b33766bcf6d55eb8de081a48c981d05c066617b80d8f6f5e60e59dd9b930bc4d04586403bb868df75933bdd86230e447036c175a10de9bb39953dcb1966a1f11912078e358f48c5b209a636c7f783f4d36a93ad2cc2e3244519078e99de1d5158b3961e0fc5a4f260c25f45f5e8585e601db08ba058d2909a1bf4995f4813460d369503c6873685ebcd3330a130b75f2365fb2a5a34ea63d958a2a867e90552d2cec8c390084be0c108b0fd2d83cb9284db5b842cbb5d0c3f6f1e2603c9c30c0f6a9b118e1a143a15e319fd1b607152b7cc0547497954c1f729199d0b23e53865403b0ad680e9b45369a6aa38d6685abd397f07fbca40627ecaf8d8d30133a6d9d5af009192751c9c45f77c0bc011268800bf552512730e69973c5bf362ab164894bf:debdd8e5d3112fd77b394aa0e36e9426bac91df126fa9c317cea7c9d45957cdd96a45ae3ad760413ee1205afd71a29f9c3cb586cd2d7cd1e93bc1652fc34dc04b59f5fe9bb4ecff9289594721f2647047b0da5e0e4941bbe57c5b722b476723f0ac5970b4111f893bcaa411f28fceb4f585a2a7187018a904b70ef8fe1f6569a54d00ada37b69cb5e9c9d26c16a903518148e04a1b936a32329c94ee1a8fb6b591892c3aff00bf6e44dd0a762babe89d7060c17b90390d23bf9d360a293b8308383086916e1182b1ba4336f001b8d20deae9a029f7e85397a9ae5cf3ca10c7f3875588b8ffabb063c00ca26f580f69edc527a1accf4f41397b33766bcf6d55eb8de081a48c981d05c066617b80d8f6f5e60e59dd9b930bc4d04586403bb868df75933bdd86230e447036c175a10de9bb39953dcb1966a1f11912078e358f48c5b209a636c7f783f4d36a93ad2cc2e3244519078e99de1d5158b3961e0fc5a4f260c25f45f5e8585e601db08ba058d2909a1bf4995f4813460d369503c6873685ebcd3330a130b75f2365fb2a5a34ea63d958a2a867e90552d2cec8c390084be0c108b0fd2d83cb9284db5b842cbb5d0c3f6f1e2603c9c30c0f6a9b118e1a143a15e319fd1b607152b7cc0547497954c1f729199d0b23e53865403b0ad680e9b45369a6aa38d6685abd397f07fbca40627ecaf8d8d30133a6d9d5af009192751c9c45f77c0bc011268800bf552512730e69973c5bf362ab164894bf: +3d09afcee3c432fdfb6bdcead54e3da5b1b4165c50d6d310b7fad787b444d680b0d9028c4d1487d293ed585a76bc94fffbafe2c65d980c494e141e4810a35cb9:b0d9028c4d1487d293ed585a76bc94fffbafe2c65d980c494e141e4810a35cb9:767165caae0e578f16537e1750be7de87a789a51ff2de11838f564e2580b2391362d2868a5a4708af15d2e2db7b9be39c16adcc1200b34e6b4d4027ddffc1a2a3595e29e855ec5261b20bd55c428b01309badb59e2ca3edb967fc2f4bac0729ddf54fb6c20057bdda9e7af7cbfc092fba865fd3275b9d3bcb0c346b951d170ac9aa650a86df49855d48a1b37ce56c9f27389f5c8b15f5c2c900c4f107c064f603e4f867ef2e9c10a1b74210e6b89bb011793aa85ded43b51b749ba7f70287b6bc1b89434db8b8c8b5d73b214b41e36b528005bfbfe002e21b1006fb9d24babd72106d093e3c7093b3138aea719d69479084647498cd6c9bbb744509cd7da8dd61a627100f03c21e750acb3fcf4631d7c0f618154d2e5fa6656fb76f74c24795047bbce4579eb110643fa98e1f776ca76d7a2b7b7b8678173c773f4be7e182fd24dd76291ac67d9f26a28c5e3cb025c6813a378b383224642b4aefad0c76a6579517b8f360797dd22613ee682b179381950fb71609a5fb5494d2d57dcb00f26d1e72956f4d6672830e05c01b3779677c07ea00953c6b8f0dc204c8dbdccb381bc01b89c5c261db189ab1f54e46bc3edc4de5ad4f0eb29c0a120e437cd8f37ac67d48c7f0e730278708f02b54aee62b72952bc1c0eb437ca8bd5655437:89739fe441ca0ced08a6eb5796e9bdda0e74fb473528fd4907edb659aab44d3343229046716368faf88e85c1644af66ff2dcaf0b17ac93ca13819f3f241dd300767165caae0e578f16537e1750be7de87a789a51ff2de11838f564e2580b2391362d2868a5a4708af15d2e2db7b9be39c16adcc1200b34e6b4d4027ddffc1a2a3595e29e855ec5261b20bd55c428b01309badb59e2ca3edb967fc2f4bac0729ddf54fb6c20057bdda9e7af7cbfc092fba865fd3275b9d3bcb0c346b951d170ac9aa650a86df49855d48a1b37ce56c9f27389f5c8b15f5c2c900c4f107c064f603e4f867ef2e9c10a1b74210e6b89bb011793aa85ded43b51b749ba7f70287b6bc1b89434db8b8c8b5d73b214b41e36b528005bfbfe002e21b1006fb9d24babd72106d093e3c7093b3138aea719d69479084647498cd6c9bbb744509cd7da8dd61a627100f03c21e750acb3fcf4631d7c0f618154d2e5fa6656fb76f74c24795047bbce4579eb110643fa98e1f776ca76d7a2b7b7b8678173c773f4be7e182fd24dd76291ac67d9f26a28c5e3cb025c6813a378b383224642b4aefad0c76a6579517b8f360797dd22613ee682b179381950fb71609a5fb5494d2d57dcb00f26d1e72956f4d6672830e05c01b3779677c07ea00953c6b8f0dc204c8dbdccb381bc01b89c5c261db189ab1f54e46bc3edc4de5ad4f0eb29c0a120e437cd8f37ac67d48c7f0e730278708f02b54aee62b72952bc1c0eb437ca8bd5655437: +41c1a2df9369cdc927164aa5adf7757136abe51395604266334cc5460ad5683e40557834cce8e043580a4272a8804d4f926e88cb10d1df0c5e28b9b67e1b63da:40557834cce8e043580a4272a8804d4f926e88cb10d1df0c5e28b9b67e1b63da:b64b14ba77d239e6f81abe060accef85f0442b650c44015efc43a0aa2ba10bf48d3018b1953ddfffbcda5bf3bbe0b6b3e4b0d9a32c6b725bbb231e0a2704471ee8bc1d594f5c54226f5dd9dfa163cfc1452c61f93e4f8139ab4ce4476f07ec933661eae91b6d500bf508ac63e4baaf1ffc8f0007d802e005f1b4fc1c88bee4d5e9e76384f5a7043bd660cce71f3b67f01f6ab844298531aac73a39d045370088855005a09c6d04238ea478dfacad1e6b22b2be4c46b0d59b1eba1f060bf7da5d1566cf1fdb5c543a33926af63f01a0db86e1a6711c473dc795ab283c8d93facfb5701fa2f2f6bb99f9b7e3749b071d58607be44a7089bcb503ec1495b5feedb399961fd3677d7493eaa3b3e9cc5e3642f40d47de9bfee7c20b0e519c4eb4a40f4da446ed6ac7aaca053e759c97dabe0a8ec2f58e7f2f9b2072762f9f794a6a4e36060b8872bd2c18d06a85c2c141a78293773ee8cfbf154b9930cd39da31b497e737a7750c90a13f5aaa147cd0dc4311f2e34941252ef198b0c1f50827e56c9f16f595aced6d2a69346531495a6499774d360766ca9be5ed8881c0db26ed7c5e6ff3a4f9b73cd8b654640dc96bf43bd426a0f28c9b25fa704d62ff0288fcceffaaebd3ea3097bcbbd778420ebc520a417730a1b5b3b8c96cda9f4e177d:b8b2752a097196c289849d78f811d9a62fc767278f0c46628b521f62ed2759d74462a175da22403f15020445cae06da3ed61cca6203b7006362a0e198963d20eb64b14ba77d239e6f81abe060accef85f0442b650c44015efc43a0aa2ba10bf48d3018b1953ddfffbcda5bf3bbe0b6b3e4b0d9a32c6b725bbb231e0a2704471ee8bc1d594f5c54226f5dd9dfa163cfc1452c61f93e4f8139ab4ce4476f07ec933661eae91b6d500bf508ac63e4baaf1ffc8f0007d802e005f1b4fc1c88bee4d5e9e76384f5a7043bd660cce71f3b67f01f6ab844298531aac73a39d045370088855005a09c6d04238ea478dfacad1e6b22b2be4c46b0d59b1eba1f060bf7da5d1566cf1fdb5c543a33926af63f01a0db86e1a6711c473dc795ab283c8d93facfb5701fa2f2f6bb99f9b7e3749b071d58607be44a7089bcb503ec1495b5feedb399961fd3677d7493eaa3b3e9cc5e3642f40d47de9bfee7c20b0e519c4eb4a40f4da446ed6ac7aaca053e759c97dabe0a8ec2f58e7f2f9b2072762f9f794a6a4e36060b8872bd2c18d06a85c2c141a78293773ee8cfbf154b9930cd39da31b497e737a7750c90a13f5aaa147cd0dc4311f2e34941252ef198b0c1f50827e56c9f16f595aced6d2a69346531495a6499774d360766ca9be5ed8881c0db26ed7c5e6ff3a4f9b73cd8b654640dc96bf43bd426a0f28c9b25fa704d62ff0288fcceffaaebd3ea3097bcbbd778420ebc520a417730a1b5b3b8c96cda9f4e177d: +a00611489467122c4c164bfb6a616e6a619b9f83c4367206b85d3fbec38cd62c57ab58babb41dc0da0bcd506059aac9f46eca91cd35a61f1ba049a9ac227f3d9:57ab58babb41dc0da0bcd506059aac9f46eca91cd35a61f1ba049a9ac227f3d9:34db02ed7512bf8c67d359e7203a2ea441e20e729766c15aa00fa249a3518fc29ef8905aa5b4670958c6a460d77b3a80efcb473859bbaff862223eee52fe58acfd3315f150f3c6c27ff48fca76552f98f6585b5e793308bf5976bad6ee327b4a7a313214b9ae04b9651b63cd8d9f5b3bec689e0fd000dd501770dd0e99b8f99eafa09c396a245a4a96e56896a29b24190b1ef11063f39b63ee3a586b07627dd3500c4e170b835dc0ec236fa5a35c44184707565c4a50662d8dbccfff7f9a7a68d021b4af64d532b7c3d2747418c2d717bb6aca6b58747ae4dd5641d826f79a8a315c38211a538a929e5b451f623f4fcbbcacdb86c8752ea13a617ab414ab653eb2e68d5420df7c6df92438168dcf9c066581dfe7b2c468194a23707de4659bd67eb634ff024741c5fc8698fd4dc41fe5dfc6299b7a08e6ffca37109c0210c8f94ea2d3ddc977ffc0b3794fe6ba4337c7aab434a68ac665484ea8243a84b79aa181ee6ab5aa37a32d879725edc018f8552181816d7d272ca8818a7b92e6ee4454d1f7828dd8afba1a790364b4ff28d84e028597353ebbef24837bc319e1ae8f2b0b6a851b489c3e170eef53e065f7032653cd6b46d8e57e4e111b789ba950c4230aba35e569e06615403407bce0369aaab4eafaef0cae109ac4cb838fb6c1:c771ba0a3d3c4a7b064bd51ad05c9ff27fd326610fbfa09183039e5edf35472dded8fc2275bbcc5df1bf129860c01a2c1311da602fbaffc8b79c249c9cc9550234db02ed7512bf8c67d359e7203a2ea441e20e729766c15aa00fa249a3518fc29ef8905aa5b4670958c6a460d77b3a80efcb473859bbaff862223eee52fe58acfd3315f150f3c6c27ff48fca76552f98f6585b5e793308bf5976bad6ee327b4a7a313214b9ae04b9651b63cd8d9f5b3bec689e0fd000dd501770dd0e99b8f99eafa09c396a245a4a96e56896a29b24190b1ef11063f39b63ee3a586b07627dd3500c4e170b835dc0ec236fa5a35c44184707565c4a50662d8dbccfff7f9a7a68d021b4af64d532b7c3d2747418c2d717bb6aca6b58747ae4dd5641d826f79a8a315c38211a538a929e5b451f623f4fcbbcacdb86c8752ea13a617ab414ab653eb2e68d5420df7c6df92438168dcf9c066581dfe7b2c468194a23707de4659bd67eb634ff024741c5fc8698fd4dc41fe5dfc6299b7a08e6ffca37109c0210c8f94ea2d3ddc977ffc0b3794fe6ba4337c7aab434a68ac665484ea8243a84b79aa181ee6ab5aa37a32d879725edc018f8552181816d7d272ca8818a7b92e6ee4454d1f7828dd8afba1a790364b4ff28d84e028597353ebbef24837bc319e1ae8f2b0b6a851b489c3e170eef53e065f7032653cd6b46d8e57e4e111b789ba950c4230aba35e569e06615403407bce0369aaab4eafaef0cae109ac4cb838fb6c1: +de1634f3460e02898db53298d6d3821c60853adee2d7f3e8edd8b0239a48cfaf9dc1465b3383f37de00ea2d3c70f2c8fac815f0172029c3f579579c984a5895e:9dc1465b3383f37de00ea2d3c70f2c8fac815f0172029c3f579579c984a5895e:d10c3e4de7fa2989dba87537e00593d0eed4d75ee65846dab1498b4749d64f40e34b5911c5ce3b53a7e37d2d02bb0dae38ed962a4edc86c00207bee9a8e456eccae8bdf4d87a76746014201af6caffe10566f08d10daaf077160f011feaca25b9c1f6eca9fc53314a80547951754355525257d09a7fdad5bc321b72aa28d1e02d8696d4f9eb0ad3b2196f8bcfaeb1d6148287a3faefef91a7a3e0609c28ce59d0ca14d0b3050dd4f096b7bc2513988ba212128d5026daaa7188846db21c5c1d179ab9487c1a5bd346588127c20398d362d4c759cfab2a677750b9e45676a1e7e092ef02edbf278fb19a58e9bf6c9e996e24edad73f3ce31fa04b6d8533436bf80b4b2f805ed91e7fcda3bc2bab3b2bb157158af0ea8e3f0731dfad459d2e79b6d3715fe7bf1eafc5397593208857e57b7feb2f7387943a8e0913470c161aef4fe205d3637f23177ff26304a4f64eba3fe6f7f272d234a67206a388ddd0366e894eaa4bb05d73a475f1b34ca222bbce1685b1b56e034e43b3c40e81fff79682c19f32aa3f2a895c0709f9f74a4d59d3a49029ecfcb283082b067f1a0d9505750fd867321999484249efa725f52c94c7596206a911f3f505d63f0313254bd445f05be3996b58fe1819af87352e7f0a2ca320d9cc00a5fe77ad41640d50be8436:d20506eb846923a0b16ff82fb2c3923b00c1b3bcc6e2f6482fba24807521e8e0223f692e62eac993f498f67102a04fd1acf9c7e3888d857c9a080b8af6361006d10c3e4de7fa2989dba87537e00593d0eed4d75ee65846dab1498b4749d64f40e34b5911c5ce3b53a7e37d2d02bb0dae38ed962a4edc86c00207bee9a8e456eccae8bdf4d87a76746014201af6caffe10566f08d10daaf077160f011feaca25b9c1f6eca9fc53314a80547951754355525257d09a7fdad5bc321b72aa28d1e02d8696d4f9eb0ad3b2196f8bcfaeb1d6148287a3faefef91a7a3e0609c28ce59d0ca14d0b3050dd4f096b7bc2513988ba212128d5026daaa7188846db21c5c1d179ab9487c1a5bd346588127c20398d362d4c759cfab2a677750b9e45676a1e7e092ef02edbf278fb19a58e9bf6c9e996e24edad73f3ce31fa04b6d8533436bf80b4b2f805ed91e7fcda3bc2bab3b2bb157158af0ea8e3f0731dfad459d2e79b6d3715fe7bf1eafc5397593208857e57b7feb2f7387943a8e0913470c161aef4fe205d3637f23177ff26304a4f64eba3fe6f7f272d234a67206a388ddd0366e894eaa4bb05d73a475f1b34ca222bbce1685b1b56e034e43b3c40e81fff79682c19f32aa3f2a895c0709f9f74a4d59d3a49029ecfcb283082b067f1a0d9505750fd867321999484249efa725f52c94c7596206a911f3f505d63f0313254bd445f05be3996b58fe1819af87352e7f0a2ca320d9cc00a5fe77ad41640d50be8436: +c738ef5f0935281ba625fa4014d4a4d0be7e28fed779a9cf658e21dba43cebc195799faf706d195e544c76cafddf09d02d1beafc42c9d6c9ead4c1845587d39e:95799faf706d195e544c76cafddf09d02d1beafc42c9d6c9ead4c1845587d39e:168d0bc5598be02f5443bfe7dfb8829985ca5d282af9cf1b1482602f243d486bd82ba039a0750909e9b3c7d4d5f8b8baf45718af0311854f4d1c7837f31d8ee68d3558e7e51e0c646a4a637596ee90057b01ed0a17daa3950b81ab47ae8b94c17d40746913c46ba1478bfca51b167628fc3ee1e22f2f19d6d8daf93df6540cedb7a859d1a2ba5911ba71766e8b7fce0c0e8663616d0180697d78ce3040d438131982f3f8112acca29ae53e539ff8c9ec4106d132f402018518308485f2aa6c9e8d1e62fed60cb249457db33c6fd1fe07445361f08194a2b5a057cb03cc754e5c7d4a7eea53a7f7d207cacca5e68cafa969a3521dbb810399a17f328ee767cf55926b2bd5f029549d3b464579c42655265398472e1c77cc8dd9aff187f7ac34dd456ace999a736ecca6d405d4922c779c600c47b84c9c1df5e5f8ed3b2811d351339113f8453cca4c4411688cb0388258ebbd1872b83610042249494ed560d4cda6a68455d957e806dd0bdd83004c4ca80774b8a0a1665866f17085014eadb3eae7382fa870deb29dd8c931b53019625740e28392f38575c0e2a9e504fc35bd95df56439a898230a2398cd2225c766ef36f12ae7e49b30a9c0aad469d5895bbf721cc0ff51d840c802d4a7eefba84fe5205a2c2f14011922dde561456f79e6161:f44371e6c3391639d457ed14648184809411e80a3201f8811670e500fcad92f300aabf7fc68e440191e881d6c3474efd6d28f09dc44312fcfcb82701ba3c290a168d0bc5598be02f5443bfe7dfb8829985ca5d282af9cf1b1482602f243d486bd82ba039a0750909e9b3c7d4d5f8b8baf45718af0311854f4d1c7837f31d8ee68d3558e7e51e0c646a4a637596ee90057b01ed0a17daa3950b81ab47ae8b94c17d40746913c46ba1478bfca51b167628fc3ee1e22f2f19d6d8daf93df6540cedb7a859d1a2ba5911ba71766e8b7fce0c0e8663616d0180697d78ce3040d438131982f3f8112acca29ae53e539ff8c9ec4106d132f402018518308485f2aa6c9e8d1e62fed60cb249457db33c6fd1fe07445361f08194a2b5a057cb03cc754e5c7d4a7eea53a7f7d207cacca5e68cafa969a3521dbb810399a17f328ee767cf55926b2bd5f029549d3b464579c42655265398472e1c77cc8dd9aff187f7ac34dd456ace999a736ecca6d405d4922c779c600c47b84c9c1df5e5f8ed3b2811d351339113f8453cca4c4411688cb0388258ebbd1872b83610042249494ed560d4cda6a68455d957e806dd0bdd83004c4ca80774b8a0a1665866f17085014eadb3eae7382fa870deb29dd8c931b53019625740e28392f38575c0e2a9e504fc35bd95df56439a898230a2398cd2225c766ef36f12ae7e49b30a9c0aad469d5895bbf721cc0ff51d840c802d4a7eefba84fe5205a2c2f14011922dde561456f79e6161: +5fea38739c61ca83bf7b4ad175a2117627b971a634a305a84fa57fecb8035624ddd14b0fc06768d5104c50764bfd3b952352a34007c50d5ddd224ff51afcdf9c:ddd14b0fc06768d5104c50764bfd3b952352a34007c50d5ddd224ff51afcdf9c:1013c60a73953549e5ed105bdea150b91e60ec39200d43721304bfc8ec439d39609613c2d878044a9da01b26d86d6d65db93d91a137e9c4808a97d4ef286a903f3f1382cc6d1294216b9fafc013c86b9ff68b55a50ea3766e61dc1ce38348e91d62ce732c152d766b9335c68d6cad77be2b4a0cd50b9a1ec632ba55648a6e7e11a14c06853c02aec4809bd147a5ddd9fbc3be9f0c8158d84ab6795d771b42b1814a17a3c7a6ca0f4a8f7b3a0db1c73ba13b16400dfecbd03d216650e4d69704a707246444d5791fa273752f59cb5ae9fd416a5186613d66afdbd1ce691a87bd7d8b67190e9ac687062a080d2ec39fe76ed8335058251872839e85eb62f18ece187caba55b5f7d5edcade01cdc543cc677e50238b89c5635ad5c8fc220f5e0be1bc667d20989753a6d616fa69f8b12940b8ca9e2c48577132d8691b053779a152cbacff3b8b1bd7af692e56c73bbae4634776cfc213c99b9ae458df1befc8c877742664b0a0bb1f6915c8dae3b3f55dd75aba6a3bcc4176b4e3ba03d0c1c04c3c6408778b2b8e5a8a3eb52ed32a7428c00a98a589d8ca9390a210f4a7ac004fa1fe4c6da694f12276e320b41b0b59f75d264a396d450b631ab353f1612709e7a2e6a50d01cb110e53040546dd3b1e11d25732813aa76be5e81fcf7a5773f6815bbd:f4e274823f2c396f3a329486aa6410c5ff19266f0770fd04fb14a7602d2b69a4a2b00928e9e1d92389f8033359ed6fb2146467aa154cba597dec6a84173f8d071013c60a73953549e5ed105bdea150b91e60ec39200d43721304bfc8ec439d39609613c2d878044a9da01b26d86d6d65db93d91a137e9c4808a97d4ef286a903f3f1382cc6d1294216b9fafc013c86b9ff68b55a50ea3766e61dc1ce38348e91d62ce732c152d766b9335c68d6cad77be2b4a0cd50b9a1ec632ba55648a6e7e11a14c06853c02aec4809bd147a5ddd9fbc3be9f0c8158d84ab6795d771b42b1814a17a3c7a6ca0f4a8f7b3a0db1c73ba13b16400dfecbd03d216650e4d69704a707246444d5791fa273752f59cb5ae9fd416a5186613d66afdbd1ce691a87bd7d8b67190e9ac687062a080d2ec39fe76ed8335058251872839e85eb62f18ece187caba55b5f7d5edcade01cdc543cc677e50238b89c5635ad5c8fc220f5e0be1bc667d20989753a6d616fa69f8b12940b8ca9e2c48577132d8691b053779a152cbacff3b8b1bd7af692e56c73bbae4634776cfc213c99b9ae458df1befc8c877742664b0a0bb1f6915c8dae3b3f55dd75aba6a3bcc4176b4e3ba03d0c1c04c3c6408778b2b8e5a8a3eb52ed32a7428c00a98a589d8ca9390a210f4a7ac004fa1fe4c6da694f12276e320b41b0b59f75d264a396d450b631ab353f1612709e7a2e6a50d01cb110e53040546dd3b1e11d25732813aa76be5e81fcf7a5773f6815bbd: +60f9a14cce5d43fd9aab4ee8cc8379d575949152693bf29a6790b035e42a44debd4a70740d5acabe49f9a2152082fa2025330e6440437f1d047f313de490dca5:bd4a70740d5acabe49f9a2152082fa2025330e6440437f1d047f313de490dca5:dd7f44f9eb728ab48de54ecde6b6184bd5ddd8707545a0129f2e905905b55d3e7fd57e28485d258148f6605e2377d5b267d2eaf4cd4b46e454962219868232b6f41f88a797f9cdd5c39ada51a641214fb9db2c2a9b5a5b16e303575318b625cca970b74348727902a1cf268bd16e107113161c8cbc99303c2b9f235541a7b31e433120feba14febe4bcb0f5b936c7edddd0ecfc72c8d38f64cdb6cfc2910bc29a521c50a51abcbc2aabf789de822cb04f5728fee153dd5501b2db59c59f50cab17c29216d66951019e145b36fd7e841bfbb0a328554b44dd7ef51468c3d5b7d3a1f7b9def58d8cf9d9bcafe92c86cf6d6119e98dba6f38ea57e322ddc9c2198d4bbc3b94ea1329db0d458e01c7081b33925a3e287f599a858c50c3a8f18cc2aa634df63e7f10e403adeab2f41db5578790c3b4f041a8b7a4f69cd6e06215df8201ae5b3e1d1d25a0a39bfc3d041a2f98213ef4141245792a76f06d4de25f6467a0e56f2f5cf69400d22117de7b46149554b70c75b9f99484a4f6f035ad3f10e3753cb14f4f398dcf6a64d10cf6c4fac07c91193cc0f54f0de58c6343e9caaa6b4f475ef91a59e083f9f211f5bc8e7e4516b45cf06bf50beb8fc4ab579d86d4a4190eeac748d06e0852c4b9ba8cfc50dd0a037a7bad7fad55af309a5f13d4c91ed3e0:72f54bb8bdd17e9e422cd339631dd39f57355015d4cbd15acab7542efd784a321c1f6125764c0d154045b32e70dc2e03fbfe1117468ac3e73127b5fac8d42102dd7f44f9eb728ab48de54ecde6b6184bd5ddd8707545a0129f2e905905b55d3e7fd57e28485d258148f6605e2377d5b267d2eaf4cd4b46e454962219868232b6f41f88a797f9cdd5c39ada51a641214fb9db2c2a9b5a5b16e303575318b625cca970b74348727902a1cf268bd16e107113161c8cbc99303c2b9f235541a7b31e433120feba14febe4bcb0f5b936c7edddd0ecfc72c8d38f64cdb6cfc2910bc29a521c50a51abcbc2aabf789de822cb04f5728fee153dd5501b2db59c59f50cab17c29216d66951019e145b36fd7e841bfbb0a328554b44dd7ef51468c3d5b7d3a1f7b9def58d8cf9d9bcafe92c86cf6d6119e98dba6f38ea57e322ddc9c2198d4bbc3b94ea1329db0d458e01c7081b33925a3e287f599a858c50c3a8f18cc2aa634df63e7f10e403adeab2f41db5578790c3b4f041a8b7a4f69cd6e06215df8201ae5b3e1d1d25a0a39bfc3d041a2f98213ef4141245792a76f06d4de25f6467a0e56f2f5cf69400d22117de7b46149554b70c75b9f99484a4f6f035ad3f10e3753cb14f4f398dcf6a64d10cf6c4fac07c91193cc0f54f0de58c6343e9caaa6b4f475ef91a59e083f9f211f5bc8e7e4516b45cf06bf50beb8fc4ab579d86d4a4190eeac748d06e0852c4b9ba8cfc50dd0a037a7bad7fad55af309a5f13d4c91ed3e0: +a39053c5c58bf31d462b27a620b0b37b8052c6b1c4102b6145663aa15e9787183642ac2a3280dce52ad8dfcfd3709436edc4e7e4ae1b452d9b220780b08679fa:3642ac2a3280dce52ad8dfcfd3709436edc4e7e4ae1b452d9b220780b08679fa:f65540d3abeb1ee5ea987062c1b579516d3c29c39cbc6b09d60e18fe274c2befe0f5fe7dbd57c2d5835229bb754ec4341394765776d6a9178c4e6a312cd74bdbaca0e88270628cd84100f472b075f93692830122f00f9bd91ac582836c8bfa714aa48e977003556e1b696df328ef584f413f8ab614760699c4d147c3eea1da0435835c9bf7ad54606f0213eb74a1b476141506ae2cd124cd51d66e7e7e579560576305c5fbe8430be3ebebaacba3f9989dd7d199f5a455a50cdb3755037e1a70674a4fef40b4a3aaf7bd3c95b1ab41bb206211c3a1276d3e37d8a3a5c3d5d0f36ef5b4f3de26b7f20f6b2900716dcc22ab734ebaf1e8d00020e5f019551653b9c2f70a4038dfb2f12d25d6d84e79073a6548fe15e4828fe5de83ac3d8d98b7daf92710482c37f7bd2431a8114c6137657bb177882d8a3c76babf1c671a7055365fe90866167a2d1dbc870be83b3601f09d4a317ae254cac9f98dcc7aead9224cd9c9d8a200abc80a2dd108af28fd46ad7080ae741b50054b9b9a9201efb7838bc4c5c2cc3d76ba0fcc49c46e792c26292b7d0312aff955a9f8edf0c696a70a614f3553ad3869bfde48d26a4d367b6cec057e62a4e548554b48b53ecda790ba7a0ab2e3de587bdc22b02f5947634d73099f547db22ec1bbf82343f9a2ca38bce4eb59be:f7383e966cb2309deedf860100183aaefac672ca16d5419cd6422ca70e16b3976f5f165afc2786117c868234ba1109ede031f8979b50e567358bd4f8bd958202f65540d3abeb1ee5ea987062c1b579516d3c29c39cbc6b09d60e18fe274c2befe0f5fe7dbd57c2d5835229bb754ec4341394765776d6a9178c4e6a312cd74bdbaca0e88270628cd84100f472b075f93692830122f00f9bd91ac582836c8bfa714aa48e977003556e1b696df328ef584f413f8ab614760699c4d147c3eea1da0435835c9bf7ad54606f0213eb74a1b476141506ae2cd124cd51d66e7e7e579560576305c5fbe8430be3ebebaacba3f9989dd7d199f5a455a50cdb3755037e1a70674a4fef40b4a3aaf7bd3c95b1ab41bb206211c3a1276d3e37d8a3a5c3d5d0f36ef5b4f3de26b7f20f6b2900716dcc22ab734ebaf1e8d00020e5f019551653b9c2f70a4038dfb2f12d25d6d84e79073a6548fe15e4828fe5de83ac3d8d98b7daf92710482c37f7bd2431a8114c6137657bb177882d8a3c76babf1c671a7055365fe90866167a2d1dbc870be83b3601f09d4a317ae254cac9f98dcc7aead9224cd9c9d8a200abc80a2dd108af28fd46ad7080ae741b50054b9b9a9201efb7838bc4c5c2cc3d76ba0fcc49c46e792c26292b7d0312aff955a9f8edf0c696a70a614f3553ad3869bfde48d26a4d367b6cec057e62a4e548554b48b53ecda790ba7a0ab2e3de587bdc22b02f5947634d73099f547db22ec1bbf82343f9a2ca38bce4eb59be: +e0c29df4de45c47539e0896b3a59bc3de6b802fd14dbdc9f25e717ac82c328f3a69002b0f5ef354ce3b2d6b8d8ba70ab778432b22f144dc9c2eb92d99d99dd2a:a69002b0f5ef354ce3b2d6b8d8ba70ab778432b22f144dc9c2eb92d99d99dd2a:6a37cb4c749c583590c8d849bce3fa657f10009190cad9be41ede19bf2fdb3c562a6101f27bd37f223cab13ced245a1cedf852f551f857aad9727f62c967c0a921df116f48a80a6040b3c723ab5cb594c4507a3d20cd60514e22164a82b74f19dcfdd83c57bc3652375517414af5d18e0a64ccab36699768d07cf40b7063a83e43d5f607964b1bf0840a45ad50abf83dbc849f40e5b4cfb6a3347b29fec50774046a4b50041032aa4d567e8564b3eed1642040682dd8ae7d7179286cf6e1853dc87d27c3e9e60fa47cf8cb2da0181d53eec40614b07331a4fb7028086d0b1ce2e1115b73a162c527bdd7cab5335b863d108be047bdbca112cc6e776bb453c317314388bb9653efb4444bf5cf1ec8da23b711ba71796c0ae02ba1dcc838455078c3897f07e9e13b76e49274c2e207506b00a0b558883aa122b667db9d670508606a3f54320636cd19f973917fb1875f4363e220f1e12398cc6afd79094743338456813a5826ad3f1aba7cd7beab1fe183859c0cc9ef40a5eab912caf515a8d4c3b93d641b7ab3e76b16c12971ace88ff33e5a1ed9b44e45db8f3085dbf070b256b0d7512ee1069432603d73095db8749ca547963bd71a8a684ab8516b146c4187176386afdf6cb1368a3dd8fcb2cfff77056aaf7823f800b266acce72bf643c6d0c28f0ab:bb3b8c5c27591fd8b9c5ba489d6b6ee5b0fb4a7b0de51f1639afc673d0e5f75e313aa7e1d0009081dbca7435b687ccd12f64f74a386e772b9e24781b925c8c0c6a37cb4c749c583590c8d849bce3fa657f10009190cad9be41ede19bf2fdb3c562a6101f27bd37f223cab13ced245a1cedf852f551f857aad9727f62c967c0a921df116f48a80a6040b3c723ab5cb594c4507a3d20cd60514e22164a82b74f19dcfdd83c57bc3652375517414af5d18e0a64ccab36699768d07cf40b7063a83e43d5f607964b1bf0840a45ad50abf83dbc849f40e5b4cfb6a3347b29fec50774046a4b50041032aa4d567e8564b3eed1642040682dd8ae7d7179286cf6e1853dc87d27c3e9e60fa47cf8cb2da0181d53eec40614b07331a4fb7028086d0b1ce2e1115b73a162c527bdd7cab5335b863d108be047bdbca112cc6e776bb453c317314388bb9653efb4444bf5cf1ec8da23b711ba71796c0ae02ba1dcc838455078c3897f07e9e13b76e49274c2e207506b00a0b558883aa122b667db9d670508606a3f54320636cd19f973917fb1875f4363e220f1e12398cc6afd79094743338456813a5826ad3f1aba7cd7beab1fe183859c0cc9ef40a5eab912caf515a8d4c3b93d641b7ab3e76b16c12971ace88ff33e5a1ed9b44e45db8f3085dbf070b256b0d7512ee1069432603d73095db8749ca547963bd71a8a684ab8516b146c4187176386afdf6cb1368a3dd8fcb2cfff77056aaf7823f800b266acce72bf643c6d0c28f0ab: +198b5fd1c03827e0994ad5bfee9b5b7be9966c9c3a267e4d7430343767403c676682c6f1a866b49b2f8ee97f2e532fa91666bf38da1b4dd65543a1777794cbee:6682c6f1a866b49b2f8ee97f2e532fa91666bf38da1b4dd65543a1777794cbee:3fdaa15c46f25143db972079d7013c7f69a136f45f3f6ba2ced8b828468eb3daa6b50b4f8d3380fec64a0343be116f6f83b6ee64cc4c1b1d08d54fd42029e4285cfc6c6dd5cd181ab533ffcd411f23a1003da94ec9340e2ec71199d678540d5182e139ffcbc505a170b8f07f4a7e694ca92f58320c0a078564ce9de99b0fa8e66b0d822e467a5aeb83567996a48b89db25cade6457794e5414d67e9d4ab7cd6cc2058bb7a513abd709f4caf24bb67ce1c03ab62dbdfe309ec7db0fa3ea7aae8236f259b922d4536115a63bc89acb2051d09e731cbb0df157d9d345bd9109973c2b594f148efc6f3377de5163b7f69869ffef853eaefeb402e23529594fbd65ca05fe4062c529d8e321abc05200cac1e839e87b1fd3fdf021d68cbb3a4142b69cc3af6f632edd65b83f5aa4cb17da5b6ba3fc03edb17c2a3cb5b04836e7660e63c8a0483e243983371dfa9839f9164ad4da0d5953655e3a9518e136da745737c79243c355fc125cbdcc76aec92216846c4574f4f7f298bcde54fd2444ad3025955c100315de5a4e27c333a00284b2f702fdd3de22ac6c240dbc14bf71e62d131b62f2db992473f2f913f60c916ecf57df5f3f021fb330834395b79472caff19fcfa0a271795c76d69b4db3f85b8d2e5c3441965484dcc39aba59b701274f7fc425246856069:f454f35b18538f877e5d614a76b5276a27fc0b433f215dc4e963b3f047694c780c515c6ef6fe2db4b009009bc2733aec4fd46e615357cc0bcc9f1f7fc21e3c023fdaa15c46f25143db972079d7013c7f69a136f45f3f6ba2ced8b828468eb3daa6b50b4f8d3380fec64a0343be116f6f83b6ee64cc4c1b1d08d54fd42029e4285cfc6c6dd5cd181ab533ffcd411f23a1003da94ec9340e2ec71199d678540d5182e139ffcbc505a170b8f07f4a7e694ca92f58320c0a078564ce9de99b0fa8e66b0d822e467a5aeb83567996a48b89db25cade6457794e5414d67e9d4ab7cd6cc2058bb7a513abd709f4caf24bb67ce1c03ab62dbdfe309ec7db0fa3ea7aae8236f259b922d4536115a63bc89acb2051d09e731cbb0df157d9d345bd9109973c2b594f148efc6f3377de5163b7f69869ffef853eaefeb402e23529594fbd65ca05fe4062c529d8e321abc05200cac1e839e87b1fd3fdf021d68cbb3a4142b69cc3af6f632edd65b83f5aa4cb17da5b6ba3fc03edb17c2a3cb5b04836e7660e63c8a0483e243983371dfa9839f9164ad4da0d5953655e3a9518e136da745737c79243c355fc125cbdcc76aec92216846c4574f4f7f298bcde54fd2444ad3025955c100315de5a4e27c333a00284b2f702fdd3de22ac6c240dbc14bf71e62d131b62f2db992473f2f913f60c916ecf57df5f3f021fb330834395b79472caff19fcfa0a271795c76d69b4db3f85b8d2e5c3441965484dcc39aba59b701274f7fc425246856069: +4392f7d4fbd68fe154e4ba38ad5207612a0648556056c39ac116ad468f89bd2dcbeaef41acac02bf1f780ce934aabd631364b369567be1be28e3906f9db120fa:cbeaef41acac02bf1f780ce934aabd631364b369567be1be28e3906f9db120fa:cf1709dc9a0867ee908721b136cb93a84229e83b46204777ca8194d08b7a3ca9c912eb243e5bdabfeed352349d20be801b722af0892238e72edf190e6361f57572781ad3c2590b197357641c805383baa1d4972f76c65448532c110834a0baa8f48863e166b706653708cd4057d3a4f9fcb2ceb4120001277d38c43847d822822b777c2bb4da4015a1c24d416d5062a8718491d855aaa5dbf5579c164d8e524a9f2fa3f22eb09861ffe6ad659fe36eb40431222c22d7137a6cabca8db786e39d81f661afde4e39589b4db4d3c51ca53590a14e115d0afc3a877b839a9638bece80c32c19e51b7532024845f76cfe9bfb2ac05130f6758bf7fe993aa93aa272e4e6bd0c75c14099d43e652a223e5bcd64c362d4b8f4b95e016f9350c7fa74e653525d08011558b2c6e9bf4fdf9dbd5ef9b09bbc846afc2bcbc86c4ccc315f6d1ccd489b0cf8ed0d93f2f532a426265c590ba3a59023347d819d9b281ef85310b05316d46c8a8c0365d068a8708664ea4d77ac0cd150a65a56586babd34b74365bb8fe3e6187262284d64432e4c81ea4c0e57c1d71ae980c7f4d1d871032e188bbf9d1758cdc1dff989f2d1288fef4e205e99e7cbf2cc324b8c93046f476c59d3d0a59db6fe37382dc79c5ec16056ab3934a52f7d2880d0471a377b6a8ae84d56ac22d1d54551c:86e7ccf06e79362d40cdb7fb75a98978bbd334a1db7590367d60849bd53e2fb1a4bdae590d1f47b5490d8702e7c1a87268b8ee9db612de7bdc2e38fa6deb7e05cf1709dc9a0867ee908721b136cb93a84229e83b46204777ca8194d08b7a3ca9c912eb243e5bdabfeed352349d20be801b722af0892238e72edf190e6361f57572781ad3c2590b197357641c805383baa1d4972f76c65448532c110834a0baa8f48863e166b706653708cd4057d3a4f9fcb2ceb4120001277d38c43847d822822b777c2bb4da4015a1c24d416d5062a8718491d855aaa5dbf5579c164d8e524a9f2fa3f22eb09861ffe6ad659fe36eb40431222c22d7137a6cabca8db786e39d81f661afde4e39589b4db4d3c51ca53590a14e115d0afc3a877b839a9638bece80c32c19e51b7532024845f76cfe9bfb2ac05130f6758bf7fe993aa93aa272e4e6bd0c75c14099d43e652a223e5bcd64c362d4b8f4b95e016f9350c7fa74e653525d08011558b2c6e9bf4fdf9dbd5ef9b09bbc846afc2bcbc86c4ccc315f6d1ccd489b0cf8ed0d93f2f532a426265c590ba3a59023347d819d9b281ef85310b05316d46c8a8c0365d068a8708664ea4d77ac0cd150a65a56586babd34b74365bb8fe3e6187262284d64432e4c81ea4c0e57c1d71ae980c7f4d1d871032e188bbf9d1758cdc1dff989f2d1288fef4e205e99e7cbf2cc324b8c93046f476c59d3d0a59db6fe37382dc79c5ec16056ab3934a52f7d2880d0471a377b6a8ae84d56ac22d1d54551c: +0bea98abe7d63f158390ee668aa050e84a25d2893e49fc83f079f9bba6a55a7522192ec0d32ef9835665a61bc88bcf4e1604637921152c116af503365bf6be42:22192ec0d32ef9835665a61bc88bcf4e1604637921152c116af503365bf6be42:c178e38d4e83ed2be57ce1c3ab64253a8171e610008181fbfc6d752269f7f1c5a9ec62cb27f19ad99ce1f5116a363d96fdc5a42f358b6dbe7cabdfc9f60718e4012c1bb1f842c5560811ba8374a0637747ff92eac21ca65ddeaf43e9989b7de2d432520afee364ecfba4da669ad4893d0bf69f9f81e7df69657be22b92069745f216c242ccd46d02d35616e16c755e0e37f961a6f3637752534f6dfab8805ab759a032a4e7e4c81953325a2f686bb69a029ce4e03becb3605637c5a65b52e331c26c926ed4711a504d3733bb53c97b80eafe4e75ddd9f415362888c3d4d37bae0e63fa11bf755666437d72f58c91d7a2f8cb619b7620a070b26b18b4d50184c5818712110e36d3e2830f6a8576ba57f9cccb8fff4028bf8ef9cb814825bbca827d649547bf6f2bef931704ca7f6df15f780155ed46eaa7ca7d72e22434ca0483bfb2f7902dc787f617eb9bd41ed4520adfd430948c710805a73c1ba5492e96484c4baa7da24c7435c46a052bf3515d33e42dcef517caa45f36c879121078c688dd10d76656a119762b6a834136fa1f8a643224b9224c543cf0470b3f8ee017d620dbdcc84d985154e9d1ae80e5f14387b88a0f6a5c35905aa57fb3abeb0ea6eccddb004474633cc483b56b8a8e20e8f2e09e979aa09893087875c6b117b5f13847ad8fc05604c4:7eb3139b880fdf66376a2090818840049767c837f3ad0036b141667052b33609817ca5e240ed8cdf3ccf3aee29274534594db0b4ccc5c6e5bba3280b873f2901c178e38d4e83ed2be57ce1c3ab64253a8171e610008181fbfc6d752269f7f1c5a9ec62cb27f19ad99ce1f5116a363d96fdc5a42f358b6dbe7cabdfc9f60718e4012c1bb1f842c5560811ba8374a0637747ff92eac21ca65ddeaf43e9989b7de2d432520afee364ecfba4da669ad4893d0bf69f9f81e7df69657be22b92069745f216c242ccd46d02d35616e16c755e0e37f961a6f3637752534f6dfab8805ab759a032a4e7e4c81953325a2f686bb69a029ce4e03becb3605637c5a65b52e331c26c926ed4711a504d3733bb53c97b80eafe4e75ddd9f415362888c3d4d37bae0e63fa11bf755666437d72f58c91d7a2f8cb619b7620a070b26b18b4d50184c5818712110e36d3e2830f6a8576ba57f9cccb8fff4028bf8ef9cb814825bbca827d649547bf6f2bef931704ca7f6df15f780155ed46eaa7ca7d72e22434ca0483bfb2f7902dc787f617eb9bd41ed4520adfd430948c710805a73c1ba5492e96484c4baa7da24c7435c46a052bf3515d33e42dcef517caa45f36c879121078c688dd10d76656a119762b6a834136fa1f8a643224b9224c543cf0470b3f8ee017d620dbdcc84d985154e9d1ae80e5f14387b88a0f6a5c35905aa57fb3abeb0ea6eccddb004474633cc483b56b8a8e20e8f2e09e979aa09893087875c6b117b5f13847ad8fc05604c4: +c25878b0d1e0925c8f5f04a1e5799080963c413a1399c118afb1687c797f483913ac2cad41908c255f671f93934ae5d7be325346725c8b40dc39ea80d70ddf34:13ac2cad41908c255f671f93934ae5d7be325346725c8b40dc39ea80d70ddf34:6856cc7144b6bddcc4b58954d1a2e7101d6584b5d5e719a0aea0fbbdf221c2a2aacbacdc4020c5c8ce681ff7381acd607b0f5239692335700655be2d94c53d7b5148e92a2bc16338c2f4c1a7d1c595af622c240ce579a5e0f5b651bf562518cec8aa2ce4b4aadb1f2fda6cf6295bc37803b5377dab65c9b9a2949fdd49bf9ddc8f96d260ff951bf8e8ccf9827e6869c44bfd973358cefdb010db5e1fe5dbd9f5d2b2ca393c17d446f637059e692d7a91aadcc7689f5f9e1b3052175d9b6b208f9026787fdb66783f45372a24946b1bd1687bf0cfcc8174ebe4d32e43284fc78d7844de0fa22e2065e07528baabaf015cb34d629c3596ad040de31c5620eb266defa7533ac0401998e5673a754365047debfcf7e137a20d16cdd6a5521982f444cfc3429397c641bd7e74a770bb11fcb29483e337bae5169ee82da9a91adf3af67cd814c2825d29018ef035ea86f8de4c7563aaf66e0c75d17ca68f49f0758ec2d9c5179d01aaed7d4515e91a222b0b06fbde4f07a7d9df2de3bcae37ca2c8460c2a6b3749e9bda36d08e66bcc356b390434b4a18cfa45af557dca3d857ff3ad347cfb07e2358c2acfd5cd53b3b0ea2a41ee5c0802fd473db5f30526334da41eb4bc7518383898a0b7507ad4ca289d66c5e2eb75cf255dff312cb1e04eebeb47f2930b90d5e002eb0:06f55198b4191914b74306f38e381316eac40b5b5adb8a312464f67175ecf612e0147b1cef46c2518750a5606bb03bc6467bb9321514f69dcbebce8f690580026856cc7144b6bddcc4b58954d1a2e7101d6584b5d5e719a0aea0fbbdf221c2a2aacbacdc4020c5c8ce681ff7381acd607b0f5239692335700655be2d94c53d7b5148e92a2bc16338c2f4c1a7d1c595af622c240ce579a5e0f5b651bf562518cec8aa2ce4b4aadb1f2fda6cf6295bc37803b5377dab65c9b9a2949fdd49bf9ddc8f96d260ff951bf8e8ccf9827e6869c44bfd973358cefdb010db5e1fe5dbd9f5d2b2ca393c17d446f637059e692d7a91aadcc7689f5f9e1b3052175d9b6b208f9026787fdb66783f45372a24946b1bd1687bf0cfcc8174ebe4d32e43284fc78d7844de0fa22e2065e07528baabaf015cb34d629c3596ad040de31c5620eb266defa7533ac0401998e5673a754365047debfcf7e137a20d16cdd6a5521982f444cfc3429397c641bd7e74a770bb11fcb29483e337bae5169ee82da9a91adf3af67cd814c2825d29018ef035ea86f8de4c7563aaf66e0c75d17ca68f49f0758ec2d9c5179d01aaed7d4515e91a222b0b06fbde4f07a7d9df2de3bcae37ca2c8460c2a6b3749e9bda36d08e66bcc356b390434b4a18cfa45af557dca3d857ff3ad347cfb07e2358c2acfd5cd53b3b0ea2a41ee5c0802fd473db5f30526334da41eb4bc7518383898a0b7507ad4ca289d66c5e2eb75cf255dff312cb1e04eebeb47f2930b90d5e002eb0: +0b2ec62763f687593135da1961ef29a288089696d944b265a5f96893cd2d8225c1e234fa8bc96d268e7aad028b03f0a911b697715db3a21c2fc7df48ecda8875:c1e234fa8bc96d268e7aad028b03f0a911b697715db3a21c2fc7df48ecda8875:a83434c68693d5fced91bda10213fcd50c48920b90cee9b73a9c61081a0974933f4fdb0a67e671f8351b0ed5ec0fe7b5fb0c87586fe582ffb1bfa2db5fcedd3302428234b2bb0e726dedf45b13a70cd35ab3e299d13f34503508278c4458eea5b7351b05836bdad5b05f60e445fc65737ae27d2e52df9c39e5da0286392d08fff7ecb7066820fc90fc8a44d5616561c50b52714702302bca5874de85dba045045f9f0e604eb86d6d7fbd775f72ea493b2c4ef7c3be16db2ca7e4d8bd79eb20cfb5f0f6f05336b75cc86d219f3b8f2e91ba7d52b64fdd6a6664f04f2fbab758cdf984168691c32f53e8616b49f76ab7b192b900903082cc89656a9705804cc9b9288a3e42170984f8dc454e0864b9341672686a178c060050178a36c6d906b2ce070d8faaacd9a58c794a5ea4108b4a485c65811c2dca2ee7bb10bffff75d4586b990f43763a16fbc0b48ae1fafb08a9a36fa4326845dba5ba2fbd32bbf66505c5e8657ed0107e3e16144ef31fa6aae72e774097483f5480aa45540568fd08cba0d577768004f58ae9b95be374ed7f0299fe721275e476e0b9ab72dc06ea328384e39bf3ac331c625484312cd9b06b15a2954d33e7aaba6be2261886ca811db96b1143d06dd6e0f3cba7a1ae9b94eaf67771bb2d24e2f94de9c470fcde7bfdb32f410198b5aa9698e32:ff701f34b3594de3b80045f429e5e32dd88d6051d4195f1685be783766e80119368f56b3749725b913f1223f87fb0fb24d9dfa0841d6a0e2eb1fddf775c2d205a83434c68693d5fced91bda10213fcd50c48920b90cee9b73a9c61081a0974933f4fdb0a67e671f8351b0ed5ec0fe7b5fb0c87586fe582ffb1bfa2db5fcedd3302428234b2bb0e726dedf45b13a70cd35ab3e299d13f34503508278c4458eea5b7351b05836bdad5b05f60e445fc65737ae27d2e52df9c39e5da0286392d08fff7ecb7066820fc90fc8a44d5616561c50b52714702302bca5874de85dba045045f9f0e604eb86d6d7fbd775f72ea493b2c4ef7c3be16db2ca7e4d8bd79eb20cfb5f0f6f05336b75cc86d219f3b8f2e91ba7d52b64fdd6a6664f04f2fbab758cdf984168691c32f53e8616b49f76ab7b192b900903082cc89656a9705804cc9b9288a3e42170984f8dc454e0864b9341672686a178c060050178a36c6d906b2ce070d8faaacd9a58c794a5ea4108b4a485c65811c2dca2ee7bb10bffff75d4586b990f43763a16fbc0b48ae1fafb08a9a36fa4326845dba5ba2fbd32bbf66505c5e8657ed0107e3e16144ef31fa6aae72e774097483f5480aa45540568fd08cba0d577768004f58ae9b95be374ed7f0299fe721275e476e0b9ab72dc06ea328384e39bf3ac331c625484312cd9b06b15a2954d33e7aaba6be2261886ca811db96b1143d06dd6e0f3cba7a1ae9b94eaf67771bb2d24e2f94de9c470fcde7bfdb32f410198b5aa9698e32: +8960d7bee8c6b39ca5934d7cddd16f16b3663e6e03e833c057e2181e4597cb6843409095d4f50f5eddbd5cd4d2012298cb41a40e99492d5a2db08be5377ea183:43409095d4f50f5eddbd5cd4d2012298cb41a40e99492d5a2db08be5377ea183:308d84c7a5f786e563e5c1ea57aab5e555c00997749d15aee35439efa645da2c3967703115c6c63ed7f94785c5478f38467b86e7626e8fffa4d51a2dc45e6df2a35cec99555eabc9f7a93e2e2b689459b4e0c92b351562c417b1997113754ea59e4a91510728ff3071a2bbd1f465a687f67dae955615031a8ad551fe738a260bbc446b48dca1d979051ab5840832e19d473b666217a9183980d6b27e3d3c76d93665ba2393e6ab1a42c3904d4025932d601a202a59a4c49fdb77f0e02868247de5afdfaa1b894208ac00d77c6bb54c6b2a73a47657e44c85137963b57521af20976248eb261482147cdf7a145c3643e29e0588bfdae6a082904853ce5a10d24970ebdfb7f59d5efdd6a5e7e0d287971c846acd54d84dd45468a4110bab6ef8d9a5b4b2426788900b7e1adfe0624344f98fe59ef8a1e6c405b344eb97bb204773744b6a2d8c6e65d17cea07de03b7f0fe49f1a55c33d5f15ce55df7c9561b251c6ac807a92553e1ce917012dccfd69e7dbd038c7eeecae98623f18fbb650e2218a0bc0fff43a75a116448bb7362f527ee6bc8e10761cccf9bcfc0d000f2127b4cc19211d095a0bdaa4e4be4519e6c8445eab9b3144a45cab9996135bf7f75a78d22275900f4ce1f0a9eac136364103062893dad4390422b77e5f5d1d94d7029c6097b35ca64a7a476fcc7:7213dd4a79fd54dec0c548ef42e6cae015be77802bf515cd2582768f72f563ebb2da36af4aaeac56bbffc9932c2e24ec95daff00a5f7a0acab9c8bd3c23bb40c308d84c7a5f786e563e5c1ea57aab5e555c00997749d15aee35439efa645da2c3967703115c6c63ed7f94785c5478f38467b86e7626e8fffa4d51a2dc45e6df2a35cec99555eabc9f7a93e2e2b689459b4e0c92b351562c417b1997113754ea59e4a91510728ff3071a2bbd1f465a687f67dae955615031a8ad551fe738a260bbc446b48dca1d979051ab5840832e19d473b666217a9183980d6b27e3d3c76d93665ba2393e6ab1a42c3904d4025932d601a202a59a4c49fdb77f0e02868247de5afdfaa1b894208ac00d77c6bb54c6b2a73a47657e44c85137963b57521af20976248eb261482147cdf7a145c3643e29e0588bfdae6a082904853ce5a10d24970ebdfb7f59d5efdd6a5e7e0d287971c846acd54d84dd45468a4110bab6ef8d9a5b4b2426788900b7e1adfe0624344f98fe59ef8a1e6c405b344eb97bb204773744b6a2d8c6e65d17cea07de03b7f0fe49f1a55c33d5f15ce55df7c9561b251c6ac807a92553e1ce917012dccfd69e7dbd038c7eeecae98623f18fbb650e2218a0bc0fff43a75a116448bb7362f527ee6bc8e10761cccf9bcfc0d000f2127b4cc19211d095a0bdaa4e4be4519e6c8445eab9b3144a45cab9996135bf7f75a78d22275900f4ce1f0a9eac136364103062893dad4390422b77e5f5d1d94d7029c6097b35ca64a7a476fcc7: +ef6b9b51fd4f8586ca62658e042fc09a83b943033526ffc326c65eb3a5fb594b1d6eece805e0887821876b7ed6ed5b0714d646fbecda38764f94c8155e61d004:1d6eece805e0887821876b7ed6ed5b0714d646fbecda38764f94c8155e61d004:a8f3f19665de2390d5cc52b064b4851273677486d8f5563bb7c95fa94db3356161ee622221f10cbb1fa195aac7231ea716d74b46b37bc85a70dba3dfaa1675217b351199e74a971028f729b7ae2b74ae8c6b3a0679c3e3296802844ad5bba343f6f9f7c4661b4a29b44f17e89e114fb220e984cd980e94c3d2bf9873e0605c92301744a3035ef046bad2666b5c63ebecf93cc140291946c0fa170340ce395092deed79841352fbfee03a927eb458f2a633ed3271652f5b0f9960cdf9015d56fdabd89ee71e259af6eb514b4c1bd4a666f5b5a35c90f35b149457af2944dd0aa8d9b542283a7e5412b775e421d2126f89bebc3ca37f73071621f1321eee52e9690486a33cd7ff9c9967fb65ee4e907b6b852211473d21e9d91a93362ac761760e8c7bbea486c3d605f9e11b86136819a7ab3f32f13ffca16817fed197ff880b4d6d9a808f7f878763a045728df72faaa963e4cb1c09cc2b2da920280c8366b7d18bf8972df16cc23448fbe6b2e6e16cbbf0745129854053189637ce115d2398433c15d6f116a205334824af282fa758494c47868ea8f4dfadc705e861aad2eb8ef3dbbed2a4569e15834a760cce0cbbc84b289e779b988346b9069c744c97ab2bf42b086d2fb0a411f5ce99f0819a3086b4fe9d96c7c9908dce28df1ddd30f3501ddaf78110734f9dcdfec3:71d171071cd0fea1c6a9cfad1f7fd835e85ff906778bc6345a4dec4313ecc2bff755a717ebd912a5e02840ac073842f9bfcaa58913e260e3c73393d36685c70ea8f3f19665de2390d5cc52b064b4851273677486d8f5563bb7c95fa94db3356161ee622221f10cbb1fa195aac7231ea716d74b46b37bc85a70dba3dfaa1675217b351199e74a971028f729b7ae2b74ae8c6b3a0679c3e3296802844ad5bba343f6f9f7c4661b4a29b44f17e89e114fb220e984cd980e94c3d2bf9873e0605c92301744a3035ef046bad2666b5c63ebecf93cc140291946c0fa170340ce395092deed79841352fbfee03a927eb458f2a633ed3271652f5b0f9960cdf9015d56fdabd89ee71e259af6eb514b4c1bd4a666f5b5a35c90f35b149457af2944dd0aa8d9b542283a7e5412b775e421d2126f89bebc3ca37f73071621f1321eee52e9690486a33cd7ff9c9967fb65ee4e907b6b852211473d21e9d91a93362ac761760e8c7bbea486c3d605f9e11b86136819a7ab3f32f13ffca16817fed197ff880b4d6d9a808f7f878763a045728df72faaa963e4cb1c09cc2b2da920280c8366b7d18bf8972df16cc23448fbe6b2e6e16cbbf0745129854053189637ce115d2398433c15d6f116a205334824af282fa758494c47868ea8f4dfadc705e861aad2eb8ef3dbbed2a4569e15834a760cce0cbbc84b289e779b988346b9069c744c97ab2bf42b086d2fb0a411f5ce99f0819a3086b4fe9d96c7c9908dce28df1ddd30f3501ddaf78110734f9dcdfec3: +bad47cd4bd89849067cce1e63c3d91e9b787aea8584edb07f3451ef67e7bd79bab0ce9ba1d29bdfb85a0e66b76b5e2e05ff732569e4375ccd75098e9e71d17bf:ab0ce9ba1d29bdfb85a0e66b76b5e2e05ff732569e4375ccd75098e9e71d17bf:b5a61e19e4863e0bb5f3fab6c4970d878596895521fa1e7f678cafa2de53322fd458a98aa6e35805429f651291b95bd9950e155f3ada0b609159a4abda5990c04bc2e764422fb49ef42f12529ff6f6a82029ff0185662e658f83c546eed09f06b5a68e857cdad0eb9ec4eecbfd88f34bc80990f8644a9bfdde1d9f3a90d557a8b828d5ce06a64e3b238582bb4cbeba30edc49e8122c55e95badcf502cc567869c09e9f46c6ff3f6878986b1de00b72a1858046fcd3a6e9cdaf5b073c56f2025063a2d178bd4c1e8cbc1e6e671aa97fb2cb4cc8a62c20be41c776372c8e7be63b482e6c63fa85d7cffbc1b2820bae1fc128343a1e20fcf1bc3502eee81358cc9a74c72af63530f96a25a604648ff570df1eb89d1fddbab28679ba2e9b41977e9a9c1caecdbfc361a1dd055ec51620a9bbdbbaf718c9cc136d2007710399536d13332485ec38879785e0c9ce9915a80251373990a59bce440326031ab1b458bfa5b8a4793da4ee11ab7af20de2a118c9ae521a417b68207fc885e109d8463e9f022787cc730db0b1faaed257bed901710885b74e994f54f6f2aeb64f0f60b59efbf2e3bb6515424603a113c0b8a31ba3c1e9a9b8118c87ec6949b75f49627ea7b1328889391104d4f4a3892cf00f26a73cda2a40f9b7157afc40667f4a04f647dbf93906b84c9a35164e1bc902:e5724a1dd463a97d1222c518c4925d322202d10f04cd078e771e0fb3951dbc1493a234460754c3aae3df93008dbbfb310c99592bede735a4aeab0323a1210d0eb5a61e19e4863e0bb5f3fab6c4970d878596895521fa1e7f678cafa2de53322fd458a98aa6e35805429f651291b95bd9950e155f3ada0b609159a4abda5990c04bc2e764422fb49ef42f12529ff6f6a82029ff0185662e658f83c546eed09f06b5a68e857cdad0eb9ec4eecbfd88f34bc80990f8644a9bfdde1d9f3a90d557a8b828d5ce06a64e3b238582bb4cbeba30edc49e8122c55e95badcf502cc567869c09e9f46c6ff3f6878986b1de00b72a1858046fcd3a6e9cdaf5b073c56f2025063a2d178bd4c1e8cbc1e6e671aa97fb2cb4cc8a62c20be41c776372c8e7be63b482e6c63fa85d7cffbc1b2820bae1fc128343a1e20fcf1bc3502eee81358cc9a74c72af63530f96a25a604648ff570df1eb89d1fddbab28679ba2e9b41977e9a9c1caecdbfc361a1dd055ec51620a9bbdbbaf718c9cc136d2007710399536d13332485ec38879785e0c9ce9915a80251373990a59bce440326031ab1b458bfa5b8a4793da4ee11ab7af20de2a118c9ae521a417b68207fc885e109d8463e9f022787cc730db0b1faaed257bed901710885b74e994f54f6f2aeb64f0f60b59efbf2e3bb6515424603a113c0b8a31ba3c1e9a9b8118c87ec6949b75f49627ea7b1328889391104d4f4a3892cf00f26a73cda2a40f9b7157afc40667f4a04f647dbf93906b84c9a35164e1bc902: +caba8e0533113a4be173408ba83c0db74260802f9186c391402655acde6015cb2d7bef6164c279fa1028a9788e3e8ee8ac15edcf92a5855062952310b4684547:2d7bef6164c279fa1028a9788e3e8ee8ac15edcf92a5855062952310b4684547:2413a32bca5ce6e230e565eb858493d5d04e6d2e2a7ab1f89a3b423311676bfa93c67daafd1cfc7109e040bac52cbfe07c28280bb6acf6e3a31073dab2965378dd77f61fe9247135c1a631b79ad668c9ea1cd4112d8d3a064cc21df32aeac7dd718b091fb6915b8bc063bb5815c376e01476312a2e5433417a7a9315d65999b02ff464a474a597e53988773670eca46a6e26cf96e9488e9e6344bc783ddfb535e76bb3b9a603ff4c59c7dbe2d8b6198d5b24490b4ea96c95959ffbf3d8218e760daf20e01e2f36c84bb097115abddee92bed82d16b15a9e192e9893ac638461df507207b0cf595884d8a99fb9c7045f9bff7b73f00ca3fd595a5cec292adb458bd9463be1204d01678d2f4389b8720115fa597c402b4ff694b71ce4f3d330d5e2f3c3ad6d96a9b3439230fc53a44794cda595557c406ca1589bc7be81e2d79636033253fa7bdd600c67fc55936bd96ce0428c3eb97bad1de0a5fbb9b675157de5f18bc62a7c22c9483e2802e679b5b8f89db0fc37f7c7150ad5ac8722ceb999b2435e6997217092336ef1c8a2292dab9a46ff8a9e10d3355765cac9d6598770f4f01ea639125fd031609dd1a507d96280c7d01a3ee987e9b210ec8744cd48c74f8afee961e8ef221f826a1fe6e7df0cb15ad7c7ef4a91f9d0f4c2e1bdea635d275fac8c4bc0601f490dbdbc734:ec35ec32c8a4008827e178492b3b8bee22a4954fc6b25f4f225dd7ed23698900de8156756a8edc35c51d10f82b830a2a659676eac911f960244766e0c3c607052413a32bca5ce6e230e565eb858493d5d04e6d2e2a7ab1f89a3b423311676bfa93c67daafd1cfc7109e040bac52cbfe07c28280bb6acf6e3a31073dab2965378dd77f61fe9247135c1a631b79ad668c9ea1cd4112d8d3a064cc21df32aeac7dd718b091fb6915b8bc063bb5815c376e01476312a2e5433417a7a9315d65999b02ff464a474a597e53988773670eca46a6e26cf96e9488e9e6344bc783ddfb535e76bb3b9a603ff4c59c7dbe2d8b6198d5b24490b4ea96c95959ffbf3d8218e760daf20e01e2f36c84bb097115abddee92bed82d16b15a9e192e9893ac638461df507207b0cf595884d8a99fb9c7045f9bff7b73f00ca3fd595a5cec292adb458bd9463be1204d01678d2f4389b8720115fa597c402b4ff694b71ce4f3d330d5e2f3c3ad6d96a9b3439230fc53a44794cda595557c406ca1589bc7be81e2d79636033253fa7bdd600c67fc55936bd96ce0428c3eb97bad1de0a5fbb9b675157de5f18bc62a7c22c9483e2802e679b5b8f89db0fc37f7c7150ad5ac8722ceb999b2435e6997217092336ef1c8a2292dab9a46ff8a9e10d3355765cac9d6598770f4f01ea639125fd031609dd1a507d96280c7d01a3ee987e9b210ec8744cd48c74f8afee961e8ef221f826a1fe6e7df0cb15ad7c7ef4a91f9d0f4c2e1bdea635d275fac8c4bc0601f490dbdbc734: +9bf3fbc7308b46f6036bade0c3ca199fac662b07f103bf75181d52ba6a58be052f6ac6fc33bc060c1dc3cb9d1a2b9115845addb16c4b84be37ed33adb3b3d3a8:2f6ac6fc33bc060c1dc3cb9d1a2b9115845addb16c4b84be37ed33adb3b3d3a8:d65e36a6a38195ecb91de3c848b51f639245fa2baba8a6f85947159dec0ed3fae80c5a0f8c66ff24793c89c0c687543bc633547a1f37f730d97012ebbdc7ac339c4890c0856bbfe2ba29b25a7aa6b089c033fecb76db62dd3c00f6421b9e76dd0ea366eb2d4a052ee6cc736e3819191d5ad7a66d2be042cc6539e5f35652b155a727f3888d93f93a9102598f7538a9ab7c777eec79426a6075d6f38d64c485520f6413ff4d358a8a9cbdab01adf4db02adaea26494d1f5d617637f277f8b0e6e7e61e2eeccdd337de2baf0ca264c14c8cb8368000b9c714385f413737d6816e212cae2aecfffc32fd16d46c3ecee6ab074c0d768bdfe99b86cbbc8df9c47cd586d465871268d4a9d1c877236ab78f8859c114e251cabc4be0f8bc25d148c5f543e290745d11803e49f5b53193fe39969c039b3f249b32f2b8598b6acf4ed64d5752bb772ff4ee00ce0f85ecbb4cfc4ce07daf2809868c2903b781e12a274105f06181029e47f2bfb21f49480aa1e444715c0b9ff07ead88975d93585d2ff424832a9783d94906a60f877ae1c85ff15317badca1e61317433c7ce96279b678ec9d174dd0870080b234154f626a53462cfd547842eab8705605b8ee885729ee78d1833aa43f55ac22731989fdeda7dc5fa9c01985f2661e6c7326d346e6db27e6f921fae7c93a2170e10dd0c460bdc:0c3136e01f9bcd99e10d3d124b0cdb0772bec18a864be81bd1daa44d818c3d470dfaa8ab6e9a761cf03f93ef9cc78291096ed6d10c08fa2fba3bac04dde20f0cd65e36a6a38195ecb91de3c848b51f639245fa2baba8a6f85947159dec0ed3fae80c5a0f8c66ff24793c89c0c687543bc633547a1f37f730d97012ebbdc7ac339c4890c0856bbfe2ba29b25a7aa6b089c033fecb76db62dd3c00f6421b9e76dd0ea366eb2d4a052ee6cc736e3819191d5ad7a66d2be042cc6539e5f35652b155a727f3888d93f93a9102598f7538a9ab7c777eec79426a6075d6f38d64c485520f6413ff4d358a8a9cbdab01adf4db02adaea26494d1f5d617637f277f8b0e6e7e61e2eeccdd337de2baf0ca264c14c8cb8368000b9c714385f413737d6816e212cae2aecfffc32fd16d46c3ecee6ab074c0d768bdfe99b86cbbc8df9c47cd586d465871268d4a9d1c877236ab78f8859c114e251cabc4be0f8bc25d148c5f543e290745d11803e49f5b53193fe39969c039b3f249b32f2b8598b6acf4ed64d5752bb772ff4ee00ce0f85ecbb4cfc4ce07daf2809868c2903b781e12a274105f06181029e47f2bfb21f49480aa1e444715c0b9ff07ead88975d93585d2ff424832a9783d94906a60f877ae1c85ff15317badca1e61317433c7ce96279b678ec9d174dd0870080b234154f626a53462cfd547842eab8705605b8ee885729ee78d1833aa43f55ac22731989fdeda7dc5fa9c01985f2661e6c7326d346e6db27e6f921fae7c93a2170e10dd0c460bdc: +64e89304a335e903cb36c0bdf1a6412ef368468006b73d3d2d61cb030cc5f8d1a180ef3a661c3c479d5f69807c902748e35e7f725121e37a5d91b8bec88d83a6:a180ef3a661c3c479d5f69807c902748e35e7f725121e37a5d91b8bec88d83a6:2f51074d981bdafafb02a40fe826c45f3171c1b3184d8c260b82b8411fc625cb02ccfe755dc29dc7895bf759e61b2450da1a656a38d4f70d2ee748c518c6420306e5f01ec7a0ffe0e9dceb93f6c077b12662881584f98ce6ab945f87fc6d123c45d6cdfd8237a1ce3635b623a79d020df44c74b89ac14a321fbf33a8c0a2559fea1c2b156076b813908f842ebe4c2b949089e52b1ae40dc6e4b2abbc439a0bf72369679aab6f4c00018be147f7c0a67b9679ee88a53819c49f7b675e30a8b5af39661ee8db21010411294968f88e5d604d0d88d76a7e4864fad3a56f5f624ba1b34ea9cb720850aad3bd4f0a882a7d25fbec2bb7ca86da616da96c1562c6d6a1abcc641e1b58b2c178e1c3bc8a3b36ec9e144dd2e75b0bc8c08ccb0d6e3427b0322b3d6ab93f3f60b9cc5b61dad02385a14949f9b87a8e3af1e0e0fab7a9a928c753fc6110444af7ccaf8027ed641b9ed87fa5d8e1f76cae465d57a70dad9ebfdd3ce7576ac4de89d98f42e282ad87ad6a5042577cbbbc4d951e2a8676fedc8cb1b1bdf76c3a38846385a85aa24706c20a8b38465fe2ae0e41f78e614b8e9642fe2471a9015747db976e0c7848c23ff3f417cb05a8d5ef40130adf855c998a62104d7e2fb7c0f9aa2a496075623ced2c0f7eec10147ff9608a8a042ef98117459b93837fd1b8d5ef03978eada74cac:92eb4454814001ecfc18025d6421f64645a5bcbb5cb8fd85c14d772617c503e8be7d3bcf117f5e6801d1c3b96f9090a66ddc67f8cf8ff0f1c125b16b15e2ce072f51074d981bdafafb02a40fe826c45f3171c1b3184d8c260b82b8411fc625cb02ccfe755dc29dc7895bf759e61b2450da1a656a38d4f70d2ee748c518c6420306e5f01ec7a0ffe0e9dceb93f6c077b12662881584f98ce6ab945f87fc6d123c45d6cdfd8237a1ce3635b623a79d020df44c74b89ac14a321fbf33a8c0a2559fea1c2b156076b813908f842ebe4c2b949089e52b1ae40dc6e4b2abbc439a0bf72369679aab6f4c00018be147f7c0a67b9679ee88a53819c49f7b675e30a8b5af39661ee8db21010411294968f88e5d604d0d88d76a7e4864fad3a56f5f624ba1b34ea9cb720850aad3bd4f0a882a7d25fbec2bb7ca86da616da96c1562c6d6a1abcc641e1b58b2c178e1c3bc8a3b36ec9e144dd2e75b0bc8c08ccb0d6e3427b0322b3d6ab93f3f60b9cc5b61dad02385a14949f9b87a8e3af1e0e0fab7a9a928c753fc6110444af7ccaf8027ed641b9ed87fa5d8e1f76cae465d57a70dad9ebfdd3ce7576ac4de89d98f42e282ad87ad6a5042577cbbbc4d951e2a8676fedc8cb1b1bdf76c3a38846385a85aa24706c20a8b38465fe2ae0e41f78e614b8e9642fe2471a9015747db976e0c7848c23ff3f417cb05a8d5ef40130adf855c998a62104d7e2fb7c0f9aa2a496075623ced2c0f7eec10147ff9608a8a042ef98117459b93837fd1b8d5ef03978eada74cac: +6f634387ca2c0cb167a740d6afd89e2a28f5307184e81cba3c037046a5ede23c011f2a9a111c38f3490cad1685be78eceedc6fac4a3221301c69c84b1ec7b3a7:011f2a9a111c38f3490cad1685be78eceedc6fac4a3221301c69c84b1ec7b3a7:865c20a94ac3f2e3bd5cb85bec9d33726671fe01f9c537017d59c8d5106e43360bf76fc06186705980c8a87ba3633a4a170426ecc0defb6db2670f5f592533774cda50052ae597d48deacc2637063bfd519f2e79bac81775beccb1ab2f5b39712e2e829469b75a2d2dbd08aa6d24723404b25eb948a4834c55246c8079a82ec64354e8c2388f8c5a616b3cdc371e6263fabc9f6099219e861585fe82a67d610dd1eb5c81c96b5cb354a689fd8aac8db76c433f0cb0b31cf1d855b6a30a3d2a212e9b4f7d7afe619951f98d2f1ba2c101085ba81f49b36037cd6457a7eaa8f4f3bedf68d09fc9fa25a9d754db65360285412d1a6da53788905fcf4efa8a80cd86ca48b845633d8c31c2ae06f16c4c6bbbe9cd1afb59e101be50e03535dd8a65e45bba46d45cb14badfc8e93ab5267f4e492ab1f9a95e61fcab81cbf2bd867a3ec7b4baa189a0f08567075596129dcf9ff1c502d3279e8aa6ce56eaf134582a9e430a5aa8ca10c3da8bc793d0256ad19aea7149f0ea7ea95facfac1c5cfd29d7a3fe1a417975739e14da8edc819900472ca8c69716328e8a299f974edff741aabc1c074a761b3ec8761dda2e7eed7af33ef00409849d415497c5ed5dfaa2259a31d076398170b2d9d210208b4a4c7db8c626d1c533562a1f95489f9819e4985fc4e1d1a707be5e82b005481d86377f424e:fd17c618cdbb5d459ea2aca886f0512c623251284aae3a83eb5d7f60da1d9b2ba083c455a5e2583a3cba736e7b961ba19c1cc8dd90745da82a15dfc662e8e10d865c20a94ac3f2e3bd5cb85bec9d33726671fe01f9c537017d59c8d5106e43360bf76fc06186705980c8a87ba3633a4a170426ecc0defb6db2670f5f592533774cda50052ae597d48deacc2637063bfd519f2e79bac81775beccb1ab2f5b39712e2e829469b75a2d2dbd08aa6d24723404b25eb948a4834c55246c8079a82ec64354e8c2388f8c5a616b3cdc371e6263fabc9f6099219e861585fe82a67d610dd1eb5c81c96b5cb354a689fd8aac8db76c433f0cb0b31cf1d855b6a30a3d2a212e9b4f7d7afe619951f98d2f1ba2c101085ba81f49b36037cd6457a7eaa8f4f3bedf68d09fc9fa25a9d754db65360285412d1a6da53788905fcf4efa8a80cd86ca48b845633d8c31c2ae06f16c4c6bbbe9cd1afb59e101be50e03535dd8a65e45bba46d45cb14badfc8e93ab5267f4e492ab1f9a95e61fcab81cbf2bd867a3ec7b4baa189a0f08567075596129dcf9ff1c502d3279e8aa6ce56eaf134582a9e430a5aa8ca10c3da8bc793d0256ad19aea7149f0ea7ea95facfac1c5cfd29d7a3fe1a417975739e14da8edc819900472ca8c69716328e8a299f974edff741aabc1c074a761b3ec8761dda2e7eed7af33ef00409849d415497c5ed5dfaa2259a31d076398170b2d9d210208b4a4c7db8c626d1c533562a1f95489f9819e4985fc4e1d1a707be5e82b005481d86377f424e: +4b2e1ae60fa5d383baba54edc168b9b05e0d05ee9c181321dbfddd198395915436c020b18552345619ef8837eb8d5494840e85f46809343b4d6f406125da557d:36c020b18552345619ef8837eb8d5494840e85f46809343b4d6f406125da557d:fab98b2bbf86aeb05086812a4b0049a1042abb76df9cd2908755706303efedb1ad21e8bc8d7562349e1e98ce0d752f4b3d99e677368bd08c78fe7425ec3b560e383bd42af6499886c35add80a5828b61d6644d7dc443ba2c06f9bad2eccb983d24458f6ada1b10bb5b77172c5cdd56d273d1e41010b25cf48a7d58d7255702ac12f2a6fe2918466395f460d15236d035ae9410ca86c4605128299faaf09015f1adee7768ee1a8f8ca06d10dd7f95c46fa10253065f9d6f90295908809fd779571be29e0ae66e0bcbdeb7913d2bbb76ac302f3452c55ef199a48eceb0e3596c7b4c0386dae7101ea244a33c4cdc830672df83655b35338052307b94d223cab1af69e07f78e58cbb0cb3c5351e3a6b0c4a927f7562c598d2d3df90569f61db1a3cb0140b56ea02cf7745fbeec2028673d67f1ec5f7daf9715f754a9d8ed46a7a63ef722ee0d5899331b63c974fa880429435767f96254ef46c9968f3fedaafeaf3e8f45634b54f5e0a5fc2d2373ab9e98d9acfe3697e642a18e0dfd9fbc2f094866d401f0a4ca2a456edf6a1a77b9c296c3922067eb3d5a5ca0a77f430e4c8611d8f05a1baac1635ef7ba83dfc69d301949856be4d2c8ab61de29cf39250c5794cbf5750cda95d0468afa2b7f23dba4ef5f5295a3bf4140018b7ed061884444f5bb1b7d239312dd739999536c684456ea06b:2220119e83d69a6a3eed95fa166d1d1128a3f232ca1b78bc94b4d476c4779443614b8772aa2232cb0720a055eb71d8407f3ab19baa1d962c052c84c0bd589608fab98b2bbf86aeb05086812a4b0049a1042abb76df9cd2908755706303efedb1ad21e8bc8d7562349e1e98ce0d752f4b3d99e677368bd08c78fe7425ec3b560e383bd42af6499886c35add80a5828b61d6644d7dc443ba2c06f9bad2eccb983d24458f6ada1b10bb5b77172c5cdd56d273d1e41010b25cf48a7d58d7255702ac12f2a6fe2918466395f460d15236d035ae9410ca86c4605128299faaf09015f1adee7768ee1a8f8ca06d10dd7f95c46fa10253065f9d6f90295908809fd779571be29e0ae66e0bcbdeb7913d2bbb76ac302f3452c55ef199a48eceb0e3596c7b4c0386dae7101ea244a33c4cdc830672df83655b35338052307b94d223cab1af69e07f78e58cbb0cb3c5351e3a6b0c4a927f7562c598d2d3df90569f61db1a3cb0140b56ea02cf7745fbeec2028673d67f1ec5f7daf9715f754a9d8ed46a7a63ef722ee0d5899331b63c974fa880429435767f96254ef46c9968f3fedaafeaf3e8f45634b54f5e0a5fc2d2373ab9e98d9acfe3697e642a18e0dfd9fbc2f094866d401f0a4ca2a456edf6a1a77b9c296c3922067eb3d5a5ca0a77f430e4c8611d8f05a1baac1635ef7ba83dfc69d301949856be4d2c8ab61de29cf39250c5794cbf5750cda95d0468afa2b7f23dba4ef5f5295a3bf4140018b7ed061884444f5bb1b7d239312dd739999536c684456ea06b: +b216cebf878024c20dfc86ce4b37bdc47aa28f29203b5b44925065d993a259fec36edbb6254a913f08fe259e238780638f72ec0b3007264bcc60a9e81ee9298f:c36edbb6254a913f08fe259e238780638f72ec0b3007264bcc60a9e81ee9298f:9c8717cc86fe02480bfd9e922bd76bffee2170c4cb1b13df834ac01d45006086297f1b8a26f2ba674d33e1d162f19367feba97352b7df2e75b309d4b6f8b07cc0eb6777e81e268e02d07f2a08f8f39d5a8320bfc01fc8c9227d2cf05e12891ff4de885a1c93371a0910ba53392aff9ba2eed9a2055977ec4157bd65b34df79372f4d50edbc48924353cfa1692319d88a7a5bb726254c209291e9b1d2c1a6c8236398109c59ed42a0ac9e7633c520734eccfea4fea95a47a8f0a068b4275000439cc97c57871e105cc0790e9dcc9c25d5af7063ffd05c4f3780e7bca4c456d0170da709fc6cb3faa72bdcf562908ae9340aef4d0c8b91f0fbccbcf1cd898b1c716f4f1474c3aa316242abdf6368e57a247ff2fd5ce23d187f694f11e38dfbfbc3d9db20903b4ebb449b9049ee020f6e2f508e8b2b165bad7464dbdd178cbd423233765d371e7ae1c3e878cdb5b824b20cb309867c0e473c067e6744008527b6bc076d077f4867622aeed1c253dbde7c6a76c7015962fb73391698600bb318ffa7b0136ee4ccb07daaf01f40ff9c194f98681f9faef8b6f9e99f95df0080da8966a8ba7a9474c537b92df9799e2fd16f788dad7a7bcc745226e1e6371f52ebcdbd144044ddfe632dfc0a43d3a450923170ebc7ae219e50e078a511bc12ef14cd14b5309f38abd65db2b2a7af2243b229c9fd2e:b7389ee78dd9763f9d2892912edcbe3e8a236b8bdc25f44b9cfdc8c47cd58168ab56eb0402a5bd752ac8f4978d2ea2b65d2fa85265966b9f57227ef4a59ae0099c8717cc86fe02480bfd9e922bd76bffee2170c4cb1b13df834ac01d45006086297f1b8a26f2ba674d33e1d162f19367feba97352b7df2e75b309d4b6f8b07cc0eb6777e81e268e02d07f2a08f8f39d5a8320bfc01fc8c9227d2cf05e12891ff4de885a1c93371a0910ba53392aff9ba2eed9a2055977ec4157bd65b34df79372f4d50edbc48924353cfa1692319d88a7a5bb726254c209291e9b1d2c1a6c8236398109c59ed42a0ac9e7633c520734eccfea4fea95a47a8f0a068b4275000439cc97c57871e105cc0790e9dcc9c25d5af7063ffd05c4f3780e7bca4c456d0170da709fc6cb3faa72bdcf562908ae9340aef4d0c8b91f0fbccbcf1cd898b1c716f4f1474c3aa316242abdf6368e57a247ff2fd5ce23d187f694f11e38dfbfbc3d9db20903b4ebb449b9049ee020f6e2f508e8b2b165bad7464dbdd178cbd423233765d371e7ae1c3e878cdb5b824b20cb309867c0e473c067e6744008527b6bc076d077f4867622aeed1c253dbde7c6a76c7015962fb73391698600bb318ffa7b0136ee4ccb07daaf01f40ff9c194f98681f9faef8b6f9e99f95df0080da8966a8ba7a9474c537b92df9799e2fd16f788dad7a7bcc745226e1e6371f52ebcdbd144044ddfe632dfc0a43d3a450923170ebc7ae219e50e078a511bc12ef14cd14b5309f38abd65db2b2a7af2243b229c9fd2e: +afcecea92439e44a43ed61b673043dcbc4e360f2f30cd07896cda20cb988d4e3d231f69235a2e3a1dd5f6c2a9aaf20c03454b9a29f4e3a29ab94689d0d723e50:d231f69235a2e3a1dd5f6c2a9aaf20c03454b9a29f4e3a29ab94689d0d723e50:0b05f89ebb3397947687afbef0ede87cf3810676277037521d952a3bbbbdc8565988a095d8d4f6f59be572d3d821dd789977ef77a2fd7110ceeed9f3756ed8e188267b97a30ef8957c78aea3a2963deca61860545e0c40824881ebb1db10f607e10ddbddce400ea236ba4745aa99a05641976766789ed0da7db55fdab459ebd4b441a6282f7cfd5a20ea06effa335955e5fd29181671bc92c00052f7f75c39277c9a43b787ac9fb1516e996232a509774d1dc21d8c0513f7844b0a5b5f18957581f99044a14223ccda8a284de12fd424265fe57b270215f8fa9ff2bea517934e4800a47d346fb6c361cfbabeffabd9c4164f45156e245c977edb473642c3940be5ad6fd1a7119a7b18e98d6dc843e0d254c93d0146d18e5c62ede1490f89a605eb454f974778cfae20932e95477bd03bcdb97d5bcb76335942e92ee668f231e69c570ac5446d0f774066737fdf49f10ceb1b52d6d8a4639846a3373a7c6f3b4b3159fe2e7af7eee2f0df172d94d255d017651da3009005e5eac3176c09389ee40d70383bd37117eca083598a1801f592d057186e568e247c252be4b14f723ab7ddb97ae9768c2682fd63acc300779fe04e2b88874751346c9e0f97a2a216772ff9625c33bd7e29fed8003a08dbd33b5d17899c943c25e95ad754fb632e047c112af7f7ceba72362e1a3ddd2935aaf7f818a27c:a65545cf3df456b28d83a6d94c036a19d0d29fb065edc27e5e93a1f40279897e1c6f25959a725ababc87cf2ae727f3467b79570e902711917191d9cb0d2d660c0b05f89ebb3397947687afbef0ede87cf3810676277037521d952a3bbbbdc8565988a095d8d4f6f59be572d3d821dd789977ef77a2fd7110ceeed9f3756ed8e188267b97a30ef8957c78aea3a2963deca61860545e0c40824881ebb1db10f607e10ddbddce400ea236ba4745aa99a05641976766789ed0da7db55fdab459ebd4b441a6282f7cfd5a20ea06effa335955e5fd29181671bc92c00052f7f75c39277c9a43b787ac9fb1516e996232a509774d1dc21d8c0513f7844b0a5b5f18957581f99044a14223ccda8a284de12fd424265fe57b270215f8fa9ff2bea517934e4800a47d346fb6c361cfbabeffabd9c4164f45156e245c977edb473642c3940be5ad6fd1a7119a7b18e98d6dc843e0d254c93d0146d18e5c62ede1490f89a605eb454f974778cfae20932e95477bd03bcdb97d5bcb76335942e92ee668f231e69c570ac5446d0f774066737fdf49f10ceb1b52d6d8a4639846a3373a7c6f3b4b3159fe2e7af7eee2f0df172d94d255d017651da3009005e5eac3176c09389ee40d70383bd37117eca083598a1801f592d057186e568e247c252be4b14f723ab7ddb97ae9768c2682fd63acc300779fe04e2b88874751346c9e0f97a2a216772ff9625c33bd7e29fed8003a08dbd33b5d17899c943c25e95ad754fb632e047c112af7f7ceba72362e1a3ddd2935aaf7f818a27c: +b834c6e0facbff580dd3b23753959a4c2154c219521b3d27035d071f6599bd02d1c384715e3b3d02c13e090605534c7db740da2aa560f53200a3ced8beae8cf8:d1c384715e3b3d02c13e090605534c7db740da2aa560f53200a3ced8beae8cf8:6cf147b1605528a36be75716a14b420bcf067c03f1cfe9c4402f14987fbfc9d3ecc3ccf4f8d2d03a55900b8dc79af3b6e77436f69b1417ad4b68fd44e5e333ed90ea7943fbd1122609ec8ff6bb25e42e9914f5920fc72c4d013b6a9685c996fbd8352aafb184c22d9e47871a5280e4ab7dd6a5cfd10a5994a200f670e0b622a9394d4793d0a420e7d8806cb127c7ac690d45a2e94166cea672bcd982b0e9baad56312d2570ddde7e0b9e7f47136f0481d00f66a2aaca4d1b09d7ce6c5a98a76b68cd97d5793968d667073f8217f9054735340f9b149c0dce845b099e88d0709680f0f77603ff0a2331c558fc36d5f24da9a62d69af5190d21b5c857a1e08f014c6d456468665a7f845c66f9111f9c098c68940efcd87b657070cb9164bc9743aceb7439a0d01c0062a11af2e11349397f5d152872b13c5ab32f51cc58f1475ec82ac671561dcbd343cfb3c5f78d0fc73053c6004b0a4ca3f2043ff4b0c54275c4fcb9cadc6baabe57b1d5acd531e972ef9335136cd1d65512ba1f5b6ccc4b66b4250aafa2967dd4211a2742e0f177d8f4063899f61815cbe6d8fbfcdf74812bd40cc10084e46a99ac128058eaf16a49a24b6ae228ecf0109c52dfc06e37d6a333bcb24aba312164c6c0290485d251280538ce9541c0916640e36d6929dcd9588eb99577f5f6d82bcbb198826267e49f5daff2c0d:0f19b7066d5792328a9800d9d4f8f67d5b089b541226a167dacd439fa485b0025a5dc7f2c7e23fc4a5c6869e7619d356399700c93650e89cd25b90fb9925e3046cf147b1605528a36be75716a14b420bcf067c03f1cfe9c4402f14987fbfc9d3ecc3ccf4f8d2d03a55900b8dc79af3b6e77436f69b1417ad4b68fd44e5e333ed90ea7943fbd1122609ec8ff6bb25e42e9914f5920fc72c4d013b6a9685c996fbd8352aafb184c22d9e47871a5280e4ab7dd6a5cfd10a5994a200f670e0b622a9394d4793d0a420e7d8806cb127c7ac690d45a2e94166cea672bcd982b0e9baad56312d2570ddde7e0b9e7f47136f0481d00f66a2aaca4d1b09d7ce6c5a98a76b68cd97d5793968d667073f8217f9054735340f9b149c0dce845b099e88d0709680f0f77603ff0a2331c558fc36d5f24da9a62d69af5190d21b5c857a1e08f014c6d456468665a7f845c66f9111f9c098c68940efcd87b657070cb9164bc9743aceb7439a0d01c0062a11af2e11349397f5d152872b13c5ab32f51cc58f1475ec82ac671561dcbd343cfb3c5f78d0fc73053c6004b0a4ca3f2043ff4b0c54275c4fcb9cadc6baabe57b1d5acd531e972ef9335136cd1d65512ba1f5b6ccc4b66b4250aafa2967dd4211a2742e0f177d8f4063899f61815cbe6d8fbfcdf74812bd40cc10084e46a99ac128058eaf16a49a24b6ae228ecf0109c52dfc06e37d6a333bcb24aba312164c6c0290485d251280538ce9541c0916640e36d6929dcd9588eb99577f5f6d82bcbb198826267e49f5daff2c0d: +2269a5d8f7ac2cd9048f5f49e349e5c435a159b319fe3b30bfac8d0d505943f41c817943dc39c24b01da38a487b175482460c609e4726349a9aa7aea9bc0fb34:1c817943dc39c24b01da38a487b175482460c609e4726349a9aa7aea9bc0fb34:7153d4d9e641aa61920db0ff4bd537a6d6130a396554cc94537698f9cad16b99eebefa5f2776f2feaff6bd9a6904120c67e0883f6b96bbbb195e95aec753b699bab3d03944c13c72fc84e3f2cbf6296f645549111c93fae1a759bfcd16fc09e60bb9785535ad27da244ef2f857f2de99a6e92188890e452c7f5b9e3a4b968e11743b6fc7faf1275e5360a5468941797894d770fa7da364a337302239fe83ae0b0d084aa12acdc63462524e0eb10fefe81ba96f71f275f3449a3f8db21d58749a38853d39b0ad8e69891bd204dfca8f6c239dc9a0ac27f54db4238d4706df11d607369dc7f704da1d39f2e82af8c283d220c12431f56d803069b4acb77081c031ae3319fc77fca7845097fd727ad0d080895bba23e873d2def8cdc216c3eed61b08761bb9ebce0282cf502aaf6ce7e8c058637958c3ea1b72fe6e8df8d37ac055db6992587fabbdc467f52475644f918863af620492f34680f2056cbcab75e2323626c094759c0e0e99ef19759527250646ad760120ba386699d53934f956b8bbc7395bb496ceb2dd223c7b501b92d36a95f8f0a02eb5ba4dddf166b9b95b4a59e72a30c63cf21e6085751923d54b30281e52a09618e6f023ba0a21675e7f989b8991588c96c2b56a78f5d2945a7baeb6a0c1bbd5d95af3ee830f5809c794a15ab4b5f89dd2be2dfdcd8fe0520fda2b3f02a1ac0155:be0fb3308a076a61a4a92a97f6ac55327190e1341d6dd410d86b41bdaf2d3374093ef720bdb77feb7014e0f77d3b809623c7ca53e2ae4b097113e96db77a2d087153d4d9e641aa61920db0ff4bd537a6d6130a396554cc94537698f9cad16b99eebefa5f2776f2feaff6bd9a6904120c67e0883f6b96bbbb195e95aec753b699bab3d03944c13c72fc84e3f2cbf6296f645549111c93fae1a759bfcd16fc09e60bb9785535ad27da244ef2f857f2de99a6e92188890e452c7f5b9e3a4b968e11743b6fc7faf1275e5360a5468941797894d770fa7da364a337302239fe83ae0b0d084aa12acdc63462524e0eb10fefe81ba96f71f275f3449a3f8db21d58749a38853d39b0ad8e69891bd204dfca8f6c239dc9a0ac27f54db4238d4706df11d607369dc7f704da1d39f2e82af8c283d220c12431f56d803069b4acb77081c031ae3319fc77fca7845097fd727ad0d080895bba23e873d2def8cdc216c3eed61b08761bb9ebce0282cf502aaf6ce7e8c058637958c3ea1b72fe6e8df8d37ac055db6992587fabbdc467f52475644f918863af620492f34680f2056cbcab75e2323626c094759c0e0e99ef19759527250646ad760120ba386699d53934f956b8bbc7395bb496ceb2dd223c7b501b92d36a95f8f0a02eb5ba4dddf166b9b95b4a59e72a30c63cf21e6085751923d54b30281e52a09618e6f023ba0a21675e7f989b8991588c96c2b56a78f5d2945a7baeb6a0c1bbd5d95af3ee830f5809c794a15ab4b5f89dd2be2dfdcd8fe0520fda2b3f02a1ac0155: +e965b3f257356685c98b42b964a253fc495399cc94b099c2445fc81c759c68e5689f5410c8e0f4d37bc07c85d7cce6c9b63601f9bdafecaa448a5eed64afc8c6:689f5410c8e0f4d37bc07c85d7cce6c9b63601f9bdafecaa448a5eed64afc8c6:6f20a9ad27e30dac76b30d4c19a5bd6dfd6d049213f4becdd963d72b8b2dad687b003808201d50f7dd6e599ef58ceb6068c545ed99b9e763f9b0ec1db5fcbd7d490a121ecec6bba1eb5edbd6de85364707c55e300c8b16bb2530f70898136689c988591d5391d9cc347d7931061a9b7696e2c9f35bc0d304a81c2cf954d9c3a88a22e1d67bbe0a85308477f62918c25db504e4762f0e3b4246007908ac701779006b77d72510edc69e17d0f6394c77e5551875a446f81233415d0a91a0460b51c413d644e850f8557281c46699e53b22a7c73b068ea38652cff3b0a7b8ba30971eab18fdbbd8739ee1ee0cd5cbfb7d5d41757b6331271fb7809751e203513c9970f66d91bc0ce062f4fcb28be0a699867b79594c6458a0d307acac91f413c4615877dc53e1b018da5cfce1b63f40be1e55274c4374cdfc21524499a683a231adef779d1921440e5d3fdbd5033dc983cfc931abe638c35d5a95869e9fe3d93eb90bd1861f855ce1f608b7bcad6b5e1bd97edc95ed5ddcbcb715d919f5ff77df2da438f7a3a98286dbd5b6e043fc7372f69704f09d865530f4f0edd3300f185b6d73d8716d32d32b1c9ac2ddf4f902d3f216d35a33f368095ded10be94bb53d6f256560fac2f4af0edf5c5c702143777126e7de32d07493932662129ba0e7fc7cfb36fd2ca531646e8cd2211854fc510af3b1e8cafde7a:8d2bc4e1cd256aad8a151dec010dc93a5e5cca58298dec49cbc9c4717b5cfb5460d430be726b0f302cbd926beea19aa3c93aeb452a44f6007af49adf2f05bb046f20a9ad27e30dac76b30d4c19a5bd6dfd6d049213f4becdd963d72b8b2dad687b003808201d50f7dd6e599ef58ceb6068c545ed99b9e763f9b0ec1db5fcbd7d490a121ecec6bba1eb5edbd6de85364707c55e300c8b16bb2530f70898136689c988591d5391d9cc347d7931061a9b7696e2c9f35bc0d304a81c2cf954d9c3a88a22e1d67bbe0a85308477f62918c25db504e4762f0e3b4246007908ac701779006b77d72510edc69e17d0f6394c77e5551875a446f81233415d0a91a0460b51c413d644e850f8557281c46699e53b22a7c73b068ea38652cff3b0a7b8ba30971eab18fdbbd8739ee1ee0cd5cbfb7d5d41757b6331271fb7809751e203513c9970f66d91bc0ce062f4fcb28be0a699867b79594c6458a0d307acac91f413c4615877dc53e1b018da5cfce1b63f40be1e55274c4374cdfc21524499a683a231adef779d1921440e5d3fdbd5033dc983cfc931abe638c35d5a95869e9fe3d93eb90bd1861f855ce1f608b7bcad6b5e1bd97edc95ed5ddcbcb715d919f5ff77df2da438f7a3a98286dbd5b6e043fc7372f69704f09d865530f4f0edd3300f185b6d73d8716d32d32b1c9ac2ddf4f902d3f216d35a33f368095ded10be94bb53d6f256560fac2f4af0edf5c5c702143777126e7de32d07493932662129ba0e7fc7cfb36fd2ca531646e8cd2211854fc510af3b1e8cafde7a: +bc3b1e0bf8d69ea5b4cbbf10bb33fc955adcbe13fc20af8a10872ce9df39d6bdaccd2628155919bbc7f9d86f91dafec35c711a78c79ad360eddb88fa8a180b2d:accd2628155919bbc7f9d86f91dafec35c711a78c79ad360eddb88fa8a180b2d:4c73e04abe0819de1f84d70541eb1bb61c4f42920e1f2d1d9e6281a8a2e8b3eb45537d83969027f99ef0ea27ca085b13f9db480f00c02f3fd7429dd567708953bbf3b9e8e2c6ac4d321ff8f9e4a3154723085a54e9c9573cc7350c09f8973f948b08730373597a5fd0349821ae0a3cd6c84992b189128f3490987e1e9ad4f6574ca538fdfd83284c1eb0953f24c08f74932d4364dbbef922542440dae80424a92eaef27c1889bd08c44f9df03a3af30dffb48fae445e625f4d9265cf387a1da35fe4c231504535db72ea81a186805f856ebe6a6a65241432530fe6c960c5f9be6c22957060304e9dd8efbc1e482e7ddbd8af03bf2382899c986d916611e4f27ae52f817ef01b6a141fe4f685d94dc8cd52830043934587704c1e642e8fe56be6d6b85bf4a6feb2b6858f1f007f99d39ea04c9fe5fa7ef1b91f495ed0e7fa4213dd68cea42b6729f95031907e27c44098094386fabfb04ab9b4de3d6861de462312c59b27c76f7b6a4fc71ea0d5daf6b7320521a67e5cb37504976ad73dae2d649feb75e2eadd3401a7f2f36e16dfbfbdb2af5716cba1bce20cd47ce1c1d7be00697001fbbeb4915aa6e5393b5ab20e0f31f5119149a2cb4c4d452c8156113ac7824f84f09aeb81202e8dd3dac0aa89399b5a38b1e218301960a37d52632eeaefe3687455464288eb17d9e19a3a72ed9de32c17be79a3b9:6ef7f0e91f2cc6715f8e5a98574b4400c261a643e0545ff26747f8e1739899d76640b6451c43c1d03a4775b54fcf9bce18ed3fccad338b7764024fdfa2de82014c73e04abe0819de1f84d70541eb1bb61c4f42920e1f2d1d9e6281a8a2e8b3eb45537d83969027f99ef0ea27ca085b13f9db480f00c02f3fd7429dd567708953bbf3b9e8e2c6ac4d321ff8f9e4a3154723085a54e9c9573cc7350c09f8973f948b08730373597a5fd0349821ae0a3cd6c84992b189128f3490987e1e9ad4f6574ca538fdfd83284c1eb0953f24c08f74932d4364dbbef922542440dae80424a92eaef27c1889bd08c44f9df03a3af30dffb48fae445e625f4d9265cf387a1da35fe4c231504535db72ea81a186805f856ebe6a6a65241432530fe6c960c5f9be6c22957060304e9dd8efbc1e482e7ddbd8af03bf2382899c986d916611e4f27ae52f817ef01b6a141fe4f685d94dc8cd52830043934587704c1e642e8fe56be6d6b85bf4a6feb2b6858f1f007f99d39ea04c9fe5fa7ef1b91f495ed0e7fa4213dd68cea42b6729f95031907e27c44098094386fabfb04ab9b4de3d6861de462312c59b27c76f7b6a4fc71ea0d5daf6b7320521a67e5cb37504976ad73dae2d649feb75e2eadd3401a7f2f36e16dfbfbdb2af5716cba1bce20cd47ce1c1d7be00697001fbbeb4915aa6e5393b5ab20e0f31f5119149a2cb4c4d452c8156113ac7824f84f09aeb81202e8dd3dac0aa89399b5a38b1e218301960a37d52632eeaefe3687455464288eb17d9e19a3a72ed9de32c17be79a3b9: +10718fa6e2d7f6ed38fd66cb6dbfa087e8f1e8a8a24fab58d79d7954b8720c3e870d4f666d06fda9f9511b58602eec050d754ea6d8e79cdd19f601c477df1aa0:870d4f666d06fda9f9511b58602eec050d754ea6d8e79cdd19f601c477df1aa0:41259b6eef13d6ffe33cdde799b995c40be782cf978440b66be51c440582abd42f526696bb3cb92265b1ed0e4bba764cae2839830a252635dc80ce5f73d521b3d6ff03ac30e198ad20567e75a34fa825ebf9841508da84cd674236ca7b43de3564c94ab079408fd94137ce3f90a5dd5d3ac39a05ec86715a8f025e4539a7640ab88836f4efbabd5e1652c49ea21613acfe343a880ee5a42f2f9134ef4e3716b16d134a9c4c71c39b3c1a857d3c89439783eef1edd71bf4492d05fd18673a5242ff4187b9de47ad4968da49dba5a6092e95ea27ddfc7448dcf5972d9d228d63e5291ba6e6fbd07e3241f9366ca4976bb04b22d01f0dbae794fa9c1d9029f88a83602b0e0ec55e22c37b201125cadb5341ef73f6da1abbe2b1c475f0750345b1be4259d8c28531ffe7788667c410dac339918c869b00ab80f20bf7990d366f9b3d5e8eb2f48d7ed0e64b85dc9fe3bb998b1eecd1231e902d2d152e09da2d2592bdb32c8cd2e2c489496b2980c03dbb09ec7f8a4ea2c7020f2a0faa657cd6ced48d6da27864cf5e97eea9b3c2f0f34abf8d87bd2adeb60c7272fc4306d955bdc8023d7d3dc2f3dafe9ebe8a8d138965a7f6ce93517cd2099663f67c34552176ddb595ac6ea5609febcf24c7d69d412709e578670a21ac8afccb8bf2b18ff3af7de21dc71d50d60d37b6ed729db04beff7d34b2920d87551ce15:e1659186f1f76fe43ac8a11703360fbeff53b5e57b5974aaa08e2575579c27084cf6802e7c206347314475b603197494e7d61fe4b1ee7b78e18d94469352df0c41259b6eef13d6ffe33cdde799b995c40be782cf978440b66be51c440582abd42f526696bb3cb92265b1ed0e4bba764cae2839830a252635dc80ce5f73d521b3d6ff03ac30e198ad20567e75a34fa825ebf9841508da84cd674236ca7b43de3564c94ab079408fd94137ce3f90a5dd5d3ac39a05ec86715a8f025e4539a7640ab88836f4efbabd5e1652c49ea21613acfe343a880ee5a42f2f9134ef4e3716b16d134a9c4c71c39b3c1a857d3c89439783eef1edd71bf4492d05fd18673a5242ff4187b9de47ad4968da49dba5a6092e95ea27ddfc7448dcf5972d9d228d63e5291ba6e6fbd07e3241f9366ca4976bb04b22d01f0dbae794fa9c1d9029f88a83602b0e0ec55e22c37b201125cadb5341ef73f6da1abbe2b1c475f0750345b1be4259d8c28531ffe7788667c410dac339918c869b00ab80f20bf7990d366f9b3d5e8eb2f48d7ed0e64b85dc9fe3bb998b1eecd1231e902d2d152e09da2d2592bdb32c8cd2e2c489496b2980c03dbb09ec7f8a4ea2c7020f2a0faa657cd6ced48d6da27864cf5e97eea9b3c2f0f34abf8d87bd2adeb60c7272fc4306d955bdc8023d7d3dc2f3dafe9ebe8a8d138965a7f6ce93517cd2099663f67c34552176ddb595ac6ea5609febcf24c7d69d412709e578670a21ac8afccb8bf2b18ff3af7de21dc71d50d60d37b6ed729db04beff7d34b2920d87551ce15: +c1d4724c6cb1bc6723b2b43034278b3c5b48fed7f8a3cc2318033e7552047351c27e392e7c3664b9061ea76d2575dd7c41eaf1da3a65f3a986e0a57f6c40c17e:c27e392e7c3664b9061ea76d2575dd7c41eaf1da3a65f3a986e0a57f6c40c17e:deee99d7a77d4300c17aec1ab323c571c6e9e73a43491a3c7888b76fc03ec43d07af42a05a2aa322d00c8560acef314106b10b9bd12654357ffa26f2390050da63d668c9e2df548f87639e096a35853f82e761fd711d2a265438f5d4db5e32775708150da6cb686a2b4ca211d7f00dc0abcb2ca150e791116a10a5efcff3514dab8ed80a7092c3a015152cb25d9f86ec0d1ca67ddab44d64eeb1f931bfab2ab188956c743db4814808c5cde1b0745b3edd340eb03ffcc80a78f3db310f4f5c20009fc0279c2c1bcb3cedf990bd0e20c6f9fb7515ad6e933b07e99da6ac32b97141187ef63bdb1062e37220a4dcd419d6244cdcc34ea41d0bcbc3138b1d54aefc0190e30b187db073aa7d6cfe04bd3fd2ac00313e3ddd64a181935ca4b8b2a85d36bc27d97b7626767b93ee38def8b6b2c8da9b00263614342faa9d3e738d2713c45ffbeef8c84bcdbc8da4309c8445530f5c617dc866251f548950a14f075aa3117f96e41f899dbe7340b1d90a1352d3b8fb41b79f16a82bc2e4a193b8a7232400996b73b1fc00b2ec1c667577f82824d39fb7f6e7692dcd97b1d8ce94083ca197e9a5d40fadff0b9ac57e9de761c156e6d31d52c332d513e9f58697dcbdd80a5e42c551702c3de7beccc3db845b1a04c8cbd41695ea7428abba89e0dce3e3d9e70230ae9147c2b88559dc695d6809a51ccbc1dd9e089c585f:d37a6ec82ed45ca9b4855de9cb942564e883ff70a79b8e712d5f604ec8974de5363ac849cbab28e7aeeff28ed3f2d14b608b3146c2efe0735ad815c7d75a1a01deee99d7a77d4300c17aec1ab323c571c6e9e73a43491a3c7888b76fc03ec43d07af42a05a2aa322d00c8560acef314106b10b9bd12654357ffa26f2390050da63d668c9e2df548f87639e096a35853f82e761fd711d2a265438f5d4db5e32775708150da6cb686a2b4ca211d7f00dc0abcb2ca150e791116a10a5efcff3514dab8ed80a7092c3a015152cb25d9f86ec0d1ca67ddab44d64eeb1f931bfab2ab188956c743db4814808c5cde1b0745b3edd340eb03ffcc80a78f3db310f4f5c20009fc0279c2c1bcb3cedf990bd0e20c6f9fb7515ad6e933b07e99da6ac32b97141187ef63bdb1062e37220a4dcd419d6244cdcc34ea41d0bcbc3138b1d54aefc0190e30b187db073aa7d6cfe04bd3fd2ac00313e3ddd64a181935ca4b8b2a85d36bc27d97b7626767b93ee38def8b6b2c8da9b00263614342faa9d3e738d2713c45ffbeef8c84bcdbc8da4309c8445530f5c617dc866251f548950a14f075aa3117f96e41f899dbe7340b1d90a1352d3b8fb41b79f16a82bc2e4a193b8a7232400996b73b1fc00b2ec1c667577f82824d39fb7f6e7692dcd97b1d8ce94083ca197e9a5d40fadff0b9ac57e9de761c156e6d31d52c332d513e9f58697dcbdd80a5e42c551702c3de7beccc3db845b1a04c8cbd41695ea7428abba89e0dce3e3d9e70230ae9147c2b88559dc695d6809a51ccbc1dd9e089c585f: +37c070d4a53b13be760635110d1bd4f01920225afabec576faaec910f2926d1a0aa85f2ab1dff895d1fad0c119f2bf57126aab601c528d37698e97702d35f525:0aa85f2ab1dff895d1fad0c119f2bf57126aab601c528d37698e97702d35f525:10c646447f81ad94d015d86d0d98b2452dca60a47ab35264035e33a0942b954e3e23b91d8123b8593c6af7c8d3ecd290e0e5ee36fd4e53b7be633a6cf027a5ac3f0f679eb1bdd210a38ea6e48b0558e303010af474e7f6df2a4e457699fc38e36938b05ffcaa1b694e32f3d1b2cc5d00cf256f12184c873e519089ec1df15b0dc76e7bfe90780df58136fe597fce894ca563e08efa0f2d4d208bede9a874882873d251baf019fe46d1d6504b3bcd243b795351f34d2e7606aa975528ee50d59efb6ee6992a89b2426956c2ca4247e0df0129852983e9767a8eed1bc7335ffca8d0289f04807f67ca7da971f58db8b9bc9fdbe4f83cfe9a00f1ca584798bc71d851ff7cd6c51b8990aaba4d38b416b92240dfb70ee3c12b5e731057762ef90823fbf683ca06d05c20d3ae2b97a83ebe70ae17afff9d16609d546d8d3c74bc281884894f3d49e083f10ae7c11c1dca0effefcfa6e0f1535081fac3a2819fd2e3265527182ae9d391b232bb7542e68455cd267760db652d19e22fb2ed11cd1305ba8d98c1ebf2d1969b24d64f3e319af74e092006d2a3ff744872a20ebf18d17748ab7110805096ea136bce2f968b205e650b803c531d06775ae5ceea28bb92e9a0edec8951ce2009a88ee1b64d9b9e89f69051203384210a102a44d2d6703173b68507dceadd3bf6510df2a5cefd9c80e4f385b2f9e6215813ed32:9da60cc4a64d07dee1346bd3d3010995ce2738208ab35b34c2a8fd1787ae3a1e207fe784525154fae4f5794cd8503045fea85cf77fd92f6a70cd0c5a52c0810e10c646447f81ad94d015d86d0d98b2452dca60a47ab35264035e33a0942b954e3e23b91d8123b8593c6af7c8d3ecd290e0e5ee36fd4e53b7be633a6cf027a5ac3f0f679eb1bdd210a38ea6e48b0558e303010af474e7f6df2a4e457699fc38e36938b05ffcaa1b694e32f3d1b2cc5d00cf256f12184c873e519089ec1df15b0dc76e7bfe90780df58136fe597fce894ca563e08efa0f2d4d208bede9a874882873d251baf019fe46d1d6504b3bcd243b795351f34d2e7606aa975528ee50d59efb6ee6992a89b2426956c2ca4247e0df0129852983e9767a8eed1bc7335ffca8d0289f04807f67ca7da971f58db8b9bc9fdbe4f83cfe9a00f1ca584798bc71d851ff7cd6c51b8990aaba4d38b416b92240dfb70ee3c12b5e731057762ef90823fbf683ca06d05c20d3ae2b97a83ebe70ae17afff9d16609d546d8d3c74bc281884894f3d49e083f10ae7c11c1dca0effefcfa6e0f1535081fac3a2819fd2e3265527182ae9d391b232bb7542e68455cd267760db652d19e22fb2ed11cd1305ba8d98c1ebf2d1969b24d64f3e319af74e092006d2a3ff744872a20ebf18d17748ab7110805096ea136bce2f968b205e650b803c531d06775ae5ceea28bb92e9a0edec8951ce2009a88ee1b64d9b9e89f69051203384210a102a44d2d6703173b68507dceadd3bf6510df2a5cefd9c80e4f385b2f9e6215813ed32: +1126496a582ce58d3d618dd8a3933547aa7a8a30fb54063b8dfdd31671c6c73de10229c623fa8ad8982c3e4c36ff52df0f219b57915b6e980e5fe72ea0962e22:e10229c623fa8ad8982c3e4c36ff52df0f219b57915b6e980e5fe72ea0962e22:6a4b52d730ddab829b2a179590cbd4c372498e9f439977c0a10dc13c0ae1736eaaff063371434fd0da80360ec5890607d2fae1c9a2e1ab0b7f3d667f5b1b9c418f18b10c9e6fd669d3ebec168efef44163e577a2ebd0f2cb768f80c23188e86069e4d10f410306cedd7a341a61e0f4f3bc25041bc2f922ed073e1e2f1b709c579d10630f33071754d707894a1c62190de18882c564dc4c01dc545dd8966404ed78fa3267a9469f63b6120abb65f9b3ba3eee28d79c2eb4e7020cc6987dfc5c29672f8c0fa3e690d584fe000c64f352610179621bfd5ff3eb30d18f1a0250416db93b1c1e93cf8a3646517560d1cc8fff822b51ef27b200e987b592390753453ef138bd3d29db7cb1b5f45e4795b89c53f49704192752237c6ab274849f9594ee9777f6efe70483129d067f97199d9ae36090703864f7ca4750a6f3b6ff83824c910484394d1e2eceba18446fe4e994ce07433a740ddd05f0e396d482894e6f14acf7b97bae6c7eb88703039fa785d60a3af78b13243a4f88dde1d998617f2e3fa7eafc2f435dd4ac1ea9c238407aa09b4eea8ed434927b406674ac270458cfb3bf29c347f94559613179b9502192321b88e9af0a90e9a4ab9eddaae382e3734d1415ebe32499c34e6fdeaf15b0d9787985e08dfe495460c54f6743d81ff16881e5e30c51f4b092373783f12423c3e1ae8591130a269980caa1cb5c:b30eb56ca9b120bf849a3a9d56af033de8a590c9e1240c1e36dbc6cf0a71b78a11ec143fb9959a8f25b57711d6a90a67e01be3a4da2b69394869bb8d64b87e0f6a4b52d730ddab829b2a179590cbd4c372498e9f439977c0a10dc13c0ae1736eaaff063371434fd0da80360ec5890607d2fae1c9a2e1ab0b7f3d667f5b1b9c418f18b10c9e6fd669d3ebec168efef44163e577a2ebd0f2cb768f80c23188e86069e4d10f410306cedd7a341a61e0f4f3bc25041bc2f922ed073e1e2f1b709c579d10630f33071754d707894a1c62190de18882c564dc4c01dc545dd8966404ed78fa3267a9469f63b6120abb65f9b3ba3eee28d79c2eb4e7020cc6987dfc5c29672f8c0fa3e690d584fe000c64f352610179621bfd5ff3eb30d18f1a0250416db93b1c1e93cf8a3646517560d1cc8fff822b51ef27b200e987b592390753453ef138bd3d29db7cb1b5f45e4795b89c53f49704192752237c6ab274849f9594ee9777f6efe70483129d067f97199d9ae36090703864f7ca4750a6f3b6ff83824c910484394d1e2eceba18446fe4e994ce07433a740ddd05f0e396d482894e6f14acf7b97bae6c7eb88703039fa785d60a3af78b13243a4f88dde1d998617f2e3fa7eafc2f435dd4ac1ea9c238407aa09b4eea8ed434927b406674ac270458cfb3bf29c347f94559613179b9502192321b88e9af0a90e9a4ab9eddaae382e3734d1415ebe32499c34e6fdeaf15b0d9787985e08dfe495460c54f6743d81ff16881e5e30c51f4b092373783f12423c3e1ae8591130a269980caa1cb5c: +9c167aff3b1b788f133d422de8ca9a64316409f9e35bfe22032ec417ae9abc6defb534f0d47c068e77b28a906d95ad8d213a4d4fc1c70542f01e596d57b5f019:efb534f0d47c068e77b28a906d95ad8d213a4d4fc1c70542f01e596d57b5f019:68ac0fc2b607ba38e377fae845c808c8f9fa614eb1f31158a9620a937d3e301e85acaa69144bc349a39dfb582041c4a197ae99b4d4d59b7a2ca3d16228b5591cbf57c18a781efd19193c47b16c6023a3a8ba3d668f05a37f1e83b0d7febdd10f63e48ef7a20e015b1c6725d4c300a986c60e3a115469c8e52ba05b51c05d0af40d89fd9ed76f36950aee3c7819898a903cfe0361a91c69100b495141e86ee79d63d17403fb1a1629ef63cb7e9d2720cbfff0002b190bcdc26794124dd38d42bcaa7175405eb0bbcf8e37d65d05a37195b479371fa2bbbb167d91cee88235dd72ea88fc73ce3ce43d33b715f25f192ec215dac124899c5e7586e86340d8cbe53735defbe02e4cc9fde69fb9794d1db72b98c0f19766ee5138bbfa78909aa299b4913c499deaf54b4841d5044829984936700dcf92f36542b2fc7e86441b9925f5d0b78c17a85cfcfcb20b0fd751349c27463abde4d27df74265288713f96dea013b945521808b4996b1b2dc0338b6d236efd6d2b27dafda46ec5fa32b965e8bb5e8bb61bd966edeb774681e0ea8c17b8c99fa7d660f0f66c9bc6d95cbd7dc094724098eb05191b53a3df6566b9c90e0d7dff2943848b61a20d48c22b6d3c958e293d709c8f48110230ff51918562877daf6d920c85a82e07c451fe7ae9759c0a77e97bb298b5d0592a41d08f67a4ed5a1bb41e937b6a68aeb38fd5be9:c9ae67fd6415dcbab292fab394ca6c3b7d90ca244dc6a7764e74fd202bf4b2905bd2030e6beb914c3c238db371b1cba6d9261aa392ec871a4b8b12fe9c1c970e68ac0fc2b607ba38e377fae845c808c8f9fa614eb1f31158a9620a937d3e301e85acaa69144bc349a39dfb582041c4a197ae99b4d4d59b7a2ca3d16228b5591cbf57c18a781efd19193c47b16c6023a3a8ba3d668f05a37f1e83b0d7febdd10f63e48ef7a20e015b1c6725d4c300a986c60e3a115469c8e52ba05b51c05d0af40d89fd9ed76f36950aee3c7819898a903cfe0361a91c69100b495141e86ee79d63d17403fb1a1629ef63cb7e9d2720cbfff0002b190bcdc26794124dd38d42bcaa7175405eb0bbcf8e37d65d05a37195b479371fa2bbbb167d91cee88235dd72ea88fc73ce3ce43d33b715f25f192ec215dac124899c5e7586e86340d8cbe53735defbe02e4cc9fde69fb9794d1db72b98c0f19766ee5138bbfa78909aa299b4913c499deaf54b4841d5044829984936700dcf92f36542b2fc7e86441b9925f5d0b78c17a85cfcfcb20b0fd751349c27463abde4d27df74265288713f96dea013b945521808b4996b1b2dc0338b6d236efd6d2b27dafda46ec5fa32b965e8bb5e8bb61bd966edeb774681e0ea8c17b8c99fa7d660f0f66c9bc6d95cbd7dc094724098eb05191b53a3df6566b9c90e0d7dff2943848b61a20d48c22b6d3c958e293d709c8f48110230ff51918562877daf6d920c85a82e07c451fe7ae9759c0a77e97bb298b5d0592a41d08f67a4ed5a1bb41e937b6a68aeb38fd5be9: +e9948805eb341b2867479c668fd3532c309941c0ad4cb2e54231756e6a1bdecb5447a8e34d6a640002d8d60bcf1ddc711e4c465c94c34b50bdef358960ff81f1:5447a8e34d6a640002d8d60bcf1ddc711e4c465c94c34b50bdef358960ff81f1:91cffd7eb1cf6bd4756bce6a30af9dfba26ddd1cce0394c194a3e39cc3d1cbc221b7eb70bea18d29c267457176a3c9e53c18e47d10a67c464505197702e6b2470d38869db5174b158f9992e4435d02246f540258dedd3ce33df582555a681fb76ecaccb1c2989b177e3b7e454aaa529de59bf5a03123d571df2e7f7cb830805c58b74a653bac0e5a888e08dc2236d6cd496aa06d0d67cf3b335e218c49dedad82fc1be9ef20cac61905c30eb132d739b16ca8a8c906619c0e0d8b33985327e36f3d4b8fda387c186cc50443104db761f7ff9301270204a713e58902101fad000ce931647c577fdec148dca95cdc08918ebed037c60332fadf088f036083ebc92e173b7ddcc30c493f27e69cd17a20d30b78f83a72e4f5a747d86d96c5e1bb7a438166204013e2164d6aabc0d562f54015c365c80445607145e5692ee34f6353077fab7452d88ce3eb01d2b3797dc91b341a3a726301516baae18e851f74dfbdf0866bb2376867de55231e362c472c52116544cd4f81e93571c4ec820e7e653f4e21be0a942576c9de91e7d1251683d859de448f822dcf3d2cf55ede2f9c71b6063d1373061f8f5936b698d1384e65459ea2bc26ec96775ef425207432dda0ac1fe28526c5e4559349c3d8df9918230f4044683cc2c1b858d141ab8d0805bb9336067522aa89c810f3eaa7ac2d8dd28c3751225a19ecec8bcca52439946:d3dc62d6ce9c766f2abaf9a7fbe09d6bdb07a4747b56080db09beb4a4e804a70d7ddf4119475c7be834f31956f4a71dad029cdf2363dd0365ce22dc27f07800391cffd7eb1cf6bd4756bce6a30af9dfba26ddd1cce0394c194a3e39cc3d1cbc221b7eb70bea18d29c267457176a3c9e53c18e47d10a67c464505197702e6b2470d38869db5174b158f9992e4435d02246f540258dedd3ce33df582555a681fb76ecaccb1c2989b177e3b7e454aaa529de59bf5a03123d571df2e7f7cb830805c58b74a653bac0e5a888e08dc2236d6cd496aa06d0d67cf3b335e218c49dedad82fc1be9ef20cac61905c30eb132d739b16ca8a8c906619c0e0d8b33985327e36f3d4b8fda387c186cc50443104db761f7ff9301270204a713e58902101fad000ce931647c577fdec148dca95cdc08918ebed037c60332fadf088f036083ebc92e173b7ddcc30c493f27e69cd17a20d30b78f83a72e4f5a747d86d96c5e1bb7a438166204013e2164d6aabc0d562f54015c365c80445607145e5692ee34f6353077fab7452d88ce3eb01d2b3797dc91b341a3a726301516baae18e851f74dfbdf0866bb2376867de55231e362c472c52116544cd4f81e93571c4ec820e7e653f4e21be0a942576c9de91e7d1251683d859de448f822dcf3d2cf55ede2f9c71b6063d1373061f8f5936b698d1384e65459ea2bc26ec96775ef425207432dda0ac1fe28526c5e4559349c3d8df9918230f4044683cc2c1b858d141ab8d0805bb9336067522aa89c810f3eaa7ac2d8dd28c3751225a19ecec8bcca52439946: +b01753efa73bb3de7aa778be7afcbff66a5d3e2c2f8b5aa2b048844050996965d0cc6cf109c999fbf6d16f471fafd0232b0a68d4c46406ec7545dbaba8194158:d0cc6cf109c999fbf6d16f471fafd0232b0a68d4c46406ec7545dbaba8194158:684e612f27eead0d34844cc81ba911c28aaf6d66e71229e8cc3462f7c7a050daa30cb74471150f07dad459b5a91358476c0598255d8a642dd7c0802811bd88e4cac597efe41ebd96cd0f3b5ce72db4be1a3dbd6b84f5446e3da600d3b1d2b460a009bd31cacd98a91518ce33e9a703d404288736ccc43103fc69e67974f31652fa3dadef3337f6c897a3d201303c8f03597b4a87c98f291ccd58a3f1e898332aa5993b47fcb5ddaa1c0868b643742d0e4a4b9cd427038b3b74999bc89ac3484c0ca13f25aae8e78ae1ccee6218accab81a4f694f5324a347629d49b55e4037504a9acc8df58c6841dddcd4fc4347f7b6f1fd9de0564577e6f329ed951a0a6b9124ff63e22eb36d3a8863bc1bf69cea24c605967e7d8948953f27d5c4c75f0849f872a3e3d16d422fa5a11e1b9a74df6f38b90f277d81fce8437a14d99d2bef189d7cac83ddc61377ed348b3c4fc09ec2b9005925d04a71e26d641667bdf549294331c6ea01cd5c0bd1b6a7ecfda20b0f1929582b74697cb262c3927d6b223f4b5f3043aa6eb4571a78e9da11c2b36f64552580caa7b5fa6b90f929e0162e608d1240d7242cd2f47025c03debe059b1dc94770232bc6765148480bb1d9f50da1ee6448cf9c88b19dd459932c06ed811c4a64a12d5938bd1c757bcfaeaee8933fe5fff21763de740482bcf1ba59afdc8fcf873c3d507bb394e32e45f736519:16b7421227ae09130685cbb1a0c60aa57a5e1afe1bbe6bacea0c281bcc8998e6824a772c3208a6b6b4d236695505c9be82700cf93a783985a39e16e377a7410e684e612f27eead0d34844cc81ba911c28aaf6d66e71229e8cc3462f7c7a050daa30cb74471150f07dad459b5a91358476c0598255d8a642dd7c0802811bd88e4cac597efe41ebd96cd0f3b5ce72db4be1a3dbd6b84f5446e3da600d3b1d2b460a009bd31cacd98a91518ce33e9a703d404288736ccc43103fc69e67974f31652fa3dadef3337f6c897a3d201303c8f03597b4a87c98f291ccd58a3f1e898332aa5993b47fcb5ddaa1c0868b643742d0e4a4b9cd427038b3b74999bc89ac3484c0ca13f25aae8e78ae1ccee6218accab81a4f694f5324a347629d49b55e4037504a9acc8df58c6841dddcd4fc4347f7b6f1fd9de0564577e6f329ed951a0a6b9124ff63e22eb36d3a8863bc1bf69cea24c605967e7d8948953f27d5c4c75f0849f872a3e3d16d422fa5a11e1b9a74df6f38b90f277d81fce8437a14d99d2bef189d7cac83ddc61377ed348b3c4fc09ec2b9005925d04a71e26d641667bdf549294331c6ea01cd5c0bd1b6a7ecfda20b0f1929582b74697cb262c3927d6b223f4b5f3043aa6eb4571a78e9da11c2b36f64552580caa7b5fa6b90f929e0162e608d1240d7242cd2f47025c03debe059b1dc94770232bc6765148480bb1d9f50da1ee6448cf9c88b19dd459932c06ed811c4a64a12d5938bd1c757bcfaeaee8933fe5fff21763de740482bcf1ba59afdc8fcf873c3d507bb394e32e45f736519: +4f4b20d899366f2f23ee628f229b236cf80f43ba183177c97ee34829546f1742c94576641f4a893cdfcee7b39fc21929b86b349976d7b0a46d39a588bcfe4357:c94576641f4a893cdfcee7b39fc21929b86b349976d7b0a46d39a588bcfe4357:db8ef02e3033e6b96a56cab05082fb4695f4a1c916250dd75173f430a10c9468817709d37623346ae8245b42bda0da6b60462ccfdfc75a9ab994e66c9ab9fecdd8599610910affe4f10215cb280bf8f9f2700a444796dae93e06c6bea7d8b4fe1301baa79ccec769368feb2442c7de84f095e6b3bff63d388cbafb2b9809dc38e9b12ebd039c0a57f4d522e91ec8d1f2b8d23a4a0ae059af85393bb0a15f749110f6774a1fd731a6ec213e4ff435daab546d31ed9ec3b6d8cc2edacebf4facc5566556eea92e5b3f2542239b25e28012dd4ef40072eebf83ed2a255181f3a442189d68c6c609f4dfdf3db7d67d087a2fcd6d2dc50bbfed8bfbbfcb74d3c41f02a87865b13b8efcf5c3581257be0aa913f60c370527bde11a475c136a17c5eefeb03f5bff28693ed841e8ed1f7c29102f5599dd444009bcea6a92d5574152458e0caf8a36aa72b5dc4908a6461c9b741453005c8fbcc68113ae184208ee14b835480c6efafed18a76000b38e5858290f4d51f52f096cbe490e1eb5cacb226ec495a55a7fa457843d57fab67f8be7e209334785bdd665d7b63e4daf57b6e78928b603c8c0f9bc85464733b61273ef9e2b8a0cd7c3bf8ee0a6872e34d5a27a625e35eaf7ff5440b8b141af704df70c9c18623bd11209513192505105cd7bcfa5f0d919da706948fbe1f761f315846aa3b4813dd9ba3d81b9204e5409c0382b6eb:0f80ff5d17488fe26f93c543b04ed959b5f0643fc61c7f2c3bc60132ba9c6210c8b250ea5e84d07b01de68bc174414eeeb31fdc2ba6823e231e312a91ededd02db8ef02e3033e6b96a56cab05082fb4695f4a1c916250dd75173f430a10c9468817709d37623346ae8245b42bda0da6b60462ccfdfc75a9ab994e66c9ab9fecdd8599610910affe4f10215cb280bf8f9f2700a444796dae93e06c6bea7d8b4fe1301baa79ccec769368feb2442c7de84f095e6b3bff63d388cbafb2b9809dc38e9b12ebd039c0a57f4d522e91ec8d1f2b8d23a4a0ae059af85393bb0a15f749110f6774a1fd731a6ec213e4ff435daab546d31ed9ec3b6d8cc2edacebf4facc5566556eea92e5b3f2542239b25e28012dd4ef40072eebf83ed2a255181f3a442189d68c6c609f4dfdf3db7d67d087a2fcd6d2dc50bbfed8bfbbfcb74d3c41f02a87865b13b8efcf5c3581257be0aa913f60c370527bde11a475c136a17c5eefeb03f5bff28693ed841e8ed1f7c29102f5599dd444009bcea6a92d5574152458e0caf8a36aa72b5dc4908a6461c9b741453005c8fbcc68113ae184208ee14b835480c6efafed18a76000b38e5858290f4d51f52f096cbe490e1eb5cacb226ec495a55a7fa457843d57fab67f8be7e209334785bdd665d7b63e4daf57b6e78928b603c8c0f9bc85464733b61273ef9e2b8a0cd7c3bf8ee0a6872e34d5a27a625e35eaf7ff5440b8b141af704df70c9c18623bd11209513192505105cd7bcfa5f0d919da706948fbe1f761f315846aa3b4813dd9ba3d81b9204e5409c0382b6eb: +d2e01d2578b625a7060aabc25765f168c680cef767aa97ca0e5eb3d667474b2a191ac223575424aa354b255b812dd3025d70ed829e0826c01629f9df3545082b:191ac223575424aa354b255b812dd3025d70ed829e0826c01629f9df3545082b:20d5dd699b2853302a6817094d5ea512bdf8534504cb289c602467410740ec7eb8ea6442c80f145935068f9122fdf4a39f2010f33db55b814d97bf2e5872329f1126d4eb95b806ca1973113165b116be8716371f81331779dc79a5cb3942081ab5f207f6b53db0e0038107d63ca97708181982dcb5f3b93010ec6edfb2cfd31cab00090b3c38515f9781769686cb17ab81d54a8b775754d42fbad086b80b28d636f78b7eb77ed9ca35b6843a510f0ad0ac1b20267a000301b3c707a20f0214d59b5b8199c2f9ee25d32060ace3e0f2594650416a00716cd3f98604a5e104b33310fdae94c314013cdca5ba2414409eb7f1901394f007d6fa0a29dbe8ec3df98c393c8d72695877cc9baf491ef30ef7db3371608ca97cc621562520ee581d5d1cdbc78232d6c7e43937b2cc8549e6f1e08df5f2eac844fe0f822b2483ad0a5de33be64089490e77d69800fae2589ee58712ac15a3f19e6ffdbca42fe1894e889b94c04b04240dafb0b2730c236b8cceb2cb97afd1d515dc19d1067fd4aba8ce297fd6d110b35a21bd3c075c577d93fe1df77d648f7119492099b017af44eba09c807f11a4c3f4a11a2fff306a728ba78983323c92a2fd5fcc80c18d423426f823a73fe04094955284293f5f6b3ca4ff1080dbb1e4c6f74c1d935ed21e30094c7de336b82dd8200b0d659583c5bfd5470f9db342e70ec4000742c5640a214e3c2e:87a010394a9f2c904effefca9fb4d5ce13793301a4925ba51db119123a4d730abf764ce065e48d90a79d907d7254c40cc358987a46949e928bbb3cd085dfab0620d5dd699b2853302a6817094d5ea512bdf8534504cb289c602467410740ec7eb8ea6442c80f145935068f9122fdf4a39f2010f33db55b814d97bf2e5872329f1126d4eb95b806ca1973113165b116be8716371f81331779dc79a5cb3942081ab5f207f6b53db0e0038107d63ca97708181982dcb5f3b93010ec6edfb2cfd31cab00090b3c38515f9781769686cb17ab81d54a8b775754d42fbad086b80b28d636f78b7eb77ed9ca35b6843a510f0ad0ac1b20267a000301b3c707a20f0214d59b5b8199c2f9ee25d32060ace3e0f2594650416a00716cd3f98604a5e104b33310fdae94c314013cdca5ba2414409eb7f1901394f007d6fa0a29dbe8ec3df98c393c8d72695877cc9baf491ef30ef7db3371608ca97cc621562520ee581d5d1cdbc78232d6c7e43937b2cc8549e6f1e08df5f2eac844fe0f822b2483ad0a5de33be64089490e77d69800fae2589ee58712ac15a3f19e6ffdbca42fe1894e889b94c04b04240dafb0b2730c236b8cceb2cb97afd1d515dc19d1067fd4aba8ce297fd6d110b35a21bd3c075c577d93fe1df77d648f7119492099b017af44eba09c807f11a4c3f4a11a2fff306a728ba78983323c92a2fd5fcc80c18d423426f823a73fe04094955284293f5f6b3ca4ff1080dbb1e4c6f74c1d935ed21e30094c7de336b82dd8200b0d659583c5bfd5470f9db342e70ec4000742c5640a214e3c2e: +7cd7ec99dd03aede1ff1073ec2ca7010276e947e2aa9b0e65f877e4ccf1b3a14e4c39dbe9493176b8213f1422a9de7c74fb6a59190fcdbf637c7ad5ee165c04f:e4c39dbe9493176b8213f1422a9de7c74fb6a59190fcdbf637c7ad5ee165c04f:a6034aa3c2484923e80e90e5a8e1748350b4f2c3c8319faf1a2e3295150a68e1eeca1bc84954cc89d4731a7f6512af01464fdbce5df68ee8066ad9a2fd21c0835a76559ca1c7449a933bcb15af90223d925ff61cd83eb935698347a57072709a86b4e5a7a626e07a3f2e7e341c7783a540f84aa73e917e867bb80bace6254705a9d1a1185de56e1a4e78aaf539e749b8f765bd052c4cd15b638bf8ecf87d9814606fed5a69f4dae9da47f3806dd90be64fccd3365cbe9e01c588fe65d6b603280740962aa8ddb95a3f4f674c03bc4043092c544595568270a2c2a8aa06e3f67c31998c50b9a58acad00690d3848114cb193293c8ac21016fd996f5c64214064f82167b2c920cd8a839755852ac77c3d90526dd3adb96837cf4e726f34bd02955cbac5b82c92cf4aa8b54bb6e436dae9bf893ef050c6f135a7e62fcd834dac1d2be8b8e59d696131811701c4318bb6e9b5a20bec656fd2ba192e2732f422963bed4a4fd1ec9326398dce290e0848c70ea236c04c7dbb3b67921440c98d72753f6a332eaad59fd0f57742923fb625fef070f34225ea06c2363d123666b99ac7d5e550da1e404e526b5b229cb130b84b1903e431cdb15b33770f5811d49fbd50d60a3474c0c35fc021d8681819ec794cc32a634bc46a955aa0246b4ff1124623cbafb3cb9d3b92a90fde648e414636192952a92291e5f86efddb89ca078aea7717fc7:6f99202770964535e483a0ee01a529442eb321303fa805d475604d7fc728a9103fb7b558b955f4d03719eefaa3b7ed5b0da75710bb98787f5c2282ed66e9f60ca6034aa3c2484923e80e90e5a8e1748350b4f2c3c8319faf1a2e3295150a68e1eeca1bc84954cc89d4731a7f6512af01464fdbce5df68ee8066ad9a2fd21c0835a76559ca1c7449a933bcb15af90223d925ff61cd83eb935698347a57072709a86b4e5a7a626e07a3f2e7e341c7783a540f84aa73e917e867bb80bace6254705a9d1a1185de56e1a4e78aaf539e749b8f765bd052c4cd15b638bf8ecf87d9814606fed5a69f4dae9da47f3806dd90be64fccd3365cbe9e01c588fe65d6b603280740962aa8ddb95a3f4f674c03bc4043092c544595568270a2c2a8aa06e3f67c31998c50b9a58acad00690d3848114cb193293c8ac21016fd996f5c64214064f82167b2c920cd8a839755852ac77c3d90526dd3adb96837cf4e726f34bd02955cbac5b82c92cf4aa8b54bb6e436dae9bf893ef050c6f135a7e62fcd834dac1d2be8b8e59d696131811701c4318bb6e9b5a20bec656fd2ba192e2732f422963bed4a4fd1ec9326398dce290e0848c70ea236c04c7dbb3b67921440c98d72753f6a332eaad59fd0f57742923fb625fef070f34225ea06c2363d123666b99ac7d5e550da1e404e526b5b229cb130b84b1903e431cdb15b33770f5811d49fbd50d60a3474c0c35fc021d8681819ec794cc32a634bc46a955aa0246b4ff1124623cbafb3cb9d3b92a90fde648e414636192952a92291e5f86efddb89ca078aea7717fc7: +e3ca3713a2fd412ad5336bc356b77be027d5b70815b3ac2aecd8340ef5f889b11d516cb8bef116a0c1b6929009933f6eb62c23050745fe7e8d3c631623778111:1d516cb8bef116a0c1b6929009933f6eb62c23050745fe7e8d3c631623778111:dd99baf295e013eed107ba8af81121aaf1835a3cca24f8e464b4cfcaa3c7bffe6f9536016d1c8cf375038c9327e8e21b004066f5eac0f76a3e8edfb07be8bd2f6bc79c3b456de82595e2c2105bb1b0aaba5eeee1adef752167d633b322ebf8f7cd5fbf59508fdbdbecf25e657a9c7050af26a80a085b0817c6217e39acd54cb9fa09540fc7bdc5226d6a276d492cc8a3dffc2abc6d0b9fb08cbccdd9432e449821a5dc98cfb3a418e539c890fe5a0446b9f81d306700927ade61cfdcc0624f13b5840748774604805731d92e77d5def66be44cc817946f1cd758196cf480f99e7117835c4c87cbd64077a562a80cf11d8ca65be7a94d92b9ddaea997e93f1448577ed6d8436b2f3144692c1fd7d28a03e9274bc9e8669d8575f5de20cfbdbcb04e9f39f3451d7048375e2698e722846cb4f2d19a810c53d4c1a6c3b770fb402df0530e7b2907223fd0899e00cb188ca80c1531b4e37fba176c17a2b8f5a3ddc7a9188d48ffc2b272c3da9c9b89dfe53f2fe7e3672f91d11818491ace140adcae98502e114f4b352b90e2e7fbd333b2459e7f15dd0764c9c34e4cb7cc095500cda035e8e2e4e3c8fd5df5f3aa579a735dd8a9f19ef336fa971114e46618734a4c13d30c81128ca21def47330103d23d80ffe67421a6ccf9f36a93f05603c599ee10b03451f36b2133c187a79ad9e6fdfbb12595ab73bb3e2e2e43030fd37e591cf55d:b3857ea61baa9e62838c4e3a996502d3364fe1ec594258355073dd10e497c600befb1f8f233fd6e3b2c87f10dcb7261aaf3481bfd0902605accc900fef84d407dd99baf295e013eed107ba8af81121aaf1835a3cca24f8e464b4cfcaa3c7bffe6f9536016d1c8cf375038c9327e8e21b004066f5eac0f76a3e8edfb07be8bd2f6bc79c3b456de82595e2c2105bb1b0aaba5eeee1adef752167d633b322ebf8f7cd5fbf59508fdbdbecf25e657a9c7050af26a80a085b0817c6217e39acd54cb9fa09540fc7bdc5226d6a276d492cc8a3dffc2abc6d0b9fb08cbccdd9432e449821a5dc98cfb3a418e539c890fe5a0446b9f81d306700927ade61cfdcc0624f13b5840748774604805731d92e77d5def66be44cc817946f1cd758196cf480f99e7117835c4c87cbd64077a562a80cf11d8ca65be7a94d92b9ddaea997e93f1448577ed6d8436b2f3144692c1fd7d28a03e9274bc9e8669d8575f5de20cfbdbcb04e9f39f3451d7048375e2698e722846cb4f2d19a810c53d4c1a6c3b770fb402df0530e7b2907223fd0899e00cb188ca80c1531b4e37fba176c17a2b8f5a3ddc7a9188d48ffc2b272c3da9c9b89dfe53f2fe7e3672f91d11818491ace140adcae98502e114f4b352b90e2e7fbd333b2459e7f15dd0764c9c34e4cb7cc095500cda035e8e2e4e3c8fd5df5f3aa579a735dd8a9f19ef336fa971114e46618734a4c13d30c81128ca21def47330103d23d80ffe67421a6ccf9f36a93f05603c599ee10b03451f36b2133c187a79ad9e6fdfbb12595ab73bb3e2e2e43030fd37e591cf55d: +29a63dcd48a351771411fddcab46bb071e91498576e8d02f8b6044f5bdd3ed903923fdcc2a9fe5cabf6e9932e46dbd2b7f3632500f9d95552db2b045bc41166f:3923fdcc2a9fe5cabf6e9932e46dbd2b7f3632500f9d95552db2b045bc41166f:ff18ca0c204c8386a4aa74ec4573c7b69216b31470daedd96a4f2302116c7955d72dacc88e3714550c09e6f7b9a8586260dc7e63da4c633bae0162e116e5c1797b78d87d47ffeea3d7819df9c852f0ff30936a105d3af5531a8f89549711c14c2d3ee11564e7c8525bd58864009762a05541d8e07ad841a55a6a9a007ef209ccec4b5640babe35651b61df42de4d910ee73a933c0b74e995757e84a99eb034f41807183c90ca4ea8d84cdba478613c8e587cb5f8fb6a055081da6e90220d5d86e34e5f91e488bd12c7a1a6b3c9fce5305e85346658effa810d0e8a2a039db4a4c94965be4011f9d5e5da266233e6c4e18ed4f8a25a57e40a591c7ed590c0f8b1a119c7c9747f691b02196cd18e6945213f1d4c8c9579c6e0a2ac45924128d6d92c8e4c66065320353d48d1d5e13194d905f837078f8dac0b68cf96ae9e70554c14b2fa29b19630e4b0f5d2a767e190efbc5992c709dcc99aa0b5aaf4c49d5513e174fd604236b05b48fcfb55c9af10596927bcfad30bacc99b2e0261f97cf297c177f1929da1f68db9f99ac62ff2de3bb40b186aa7e8c5d6123980d759927a3a07aa208beeb736795ae5b849d5dae5e3573710aaa24e96d5791e2730d0270f5b0a2705ba515d14aa7e6fa6622375377f9aba64d02569a209d33de686e089ec60118e4814ffc6c0778c6427bce2b6b844cfcd5a7ced0e35303f50a0dfe5df5dde1a2f23:12bf629593e2caadc910ec40bfe2b7a62514126b16ba3a438d88e2d21f595aaee8abfa4af2ec870361d0ea04dfc8c6a330fb2841c2d8211a64fa1e7e7d273800ff18ca0c204c8386a4aa74ec4573c7b69216b31470daedd96a4f2302116c7955d72dacc88e3714550c09e6f7b9a8586260dc7e63da4c633bae0162e116e5c1797b78d87d47ffeea3d7819df9c852f0ff30936a105d3af5531a8f89549711c14c2d3ee11564e7c8525bd58864009762a05541d8e07ad841a55a6a9a007ef209ccec4b5640babe35651b61df42de4d910ee73a933c0b74e995757e84a99eb034f41807183c90ca4ea8d84cdba478613c8e587cb5f8fb6a055081da6e90220d5d86e34e5f91e488bd12c7a1a6b3c9fce5305e85346658effa810d0e8a2a039db4a4c94965be4011f9d5e5da266233e6c4e18ed4f8a25a57e40a591c7ed590c0f8b1a119c7c9747f691b02196cd18e6945213f1d4c8c9579c6e0a2ac45924128d6d92c8e4c66065320353d48d1d5e13194d905f837078f8dac0b68cf96ae9e70554c14b2fa29b19630e4b0f5d2a767e190efbc5992c709dcc99aa0b5aaf4c49d5513e174fd604236b05b48fcfb55c9af10596927bcfad30bacc99b2e0261f97cf297c177f1929da1f68db9f99ac62ff2de3bb40b186aa7e8c5d6123980d759927a3a07aa208beeb736795ae5b849d5dae5e3573710aaa24e96d5791e2730d0270f5b0a2705ba515d14aa7e6fa6622375377f9aba64d02569a209d33de686e089ec60118e4814ffc6c0778c6427bce2b6b844cfcd5a7ced0e35303f50a0dfe5df5dde1a2f23: +c7188fdd80f4cd31839ec958671e6dd08b21f9d7528c9159143734f94b169883019752ff829b6859b9058d00c2795e835655440675753f37e85eb7bc5839c4ca:019752ff829b6859b9058d00c2795e835655440675753f37e85eb7bc5839c4ca:4af5dfe3feaabe7f8fcd38308e0bd385cad3811cbdc79c944ebfe3cd675cf3afbef4542f542975c2e2a6e66e26b32ac3d7e19ef74c39fa2a61c56841c2d8212e2bd7fb49cfb25cc3609a693a6f2b9d4e22e2099f80b777d3d05f33ba7db3c5ab55766ceb1a1322af726c565516ce566329b98fc5dc4cbd93cefb627688c977af9367b5c69659e43cb7ee754711d665c0032ae22934f44c71d31178ef3d9810912874b62fa5e4020e6d5d6458183732c19e2e89685e0464e91a9b1c8d5251e24e5f91813f5019a740a04b5d91cbb8309e5161bba79dcab38239a091f50e099ff819e3a7b5205fe907cdfe9c0dc3ee85e32d7bcd3ce02635e2058388031e317fbf22ab9f39f7f7e3cd1a11a9c1f45f4e1e42d2536c122c591837911847108ceafd990813c2b6344cffc34be37161dd815626900e8fcb85c21afb4f6be8ad01516a31c2a6580315857c6a216735ca991009dbc2ea5034160747a869d5cadb0b47ffbd5d3ac97fdd0526cae6eaa35cff7a16eaf4fb950ca31511346fea6141999a3f754e6281cfba15e8a826932c589c5d247c909d94b4eab7ebcb09077648af065c2d86611eb588453ed7c24780d73c689c8744afd533a86d9ee9e3365732cbd0c351e436f898b7043292097e03e6081a23ac865e19dc8858969b999d01fa65ef200c3f269c818e30b9365ecc683bcfe69c203b4e0ab6fe0bb871e8ecaaae82d3acd35d5b50:35c170dd0c6dc2920a595775d8e2dd65243e9c1bf96ef42779001ed45f01b7dfebd6f6a7dc2d386ef4d2a56779ebe77f54e5aecfda2d54a068476b24dbd78b0c4af5dfe3feaabe7f8fcd38308e0bd385cad3811cbdc79c944ebfe3cd675cf3afbef4542f542975c2e2a6e66e26b32ac3d7e19ef74c39fa2a61c56841c2d8212e2bd7fb49cfb25cc3609a693a6f2b9d4e22e2099f80b777d3d05f33ba7db3c5ab55766ceb1a1322af726c565516ce566329b98fc5dc4cbd93cefb627688c977af9367b5c69659e43cb7ee754711d665c0032ae22934f44c71d31178ef3d9810912874b62fa5e4020e6d5d6458183732c19e2e89685e0464e91a9b1c8d5251e24e5f91813f5019a740a04b5d91cbb8309e5161bba79dcab38239a091f50e099ff819e3a7b5205fe907cdfe9c0dc3ee85e32d7bcd3ce02635e2058388031e317fbf22ab9f39f7f7e3cd1a11a9c1f45f4e1e42d2536c122c591837911847108ceafd990813c2b6344cffc34be37161dd815626900e8fcb85c21afb4f6be8ad01516a31c2a6580315857c6a216735ca991009dbc2ea5034160747a869d5cadb0b47ffbd5d3ac97fdd0526cae6eaa35cff7a16eaf4fb950ca31511346fea6141999a3f754e6281cfba15e8a826932c589c5d247c909d94b4eab7ebcb09077648af065c2d86611eb588453ed7c24780d73c689c8744afd533a86d9ee9e3365732cbd0c351e436f898b7043292097e03e6081a23ac865e19dc8858969b999d01fa65ef200c3f269c818e30b9365ecc683bcfe69c203b4e0ab6fe0bb871e8ecaaae82d3acd35d5b50: +38ba0621704d2155fc2f78555196575de06d80255c35e9dc965b6fe96a4d53894388f7f68a9effbc366e42d907015604daced1727cd1d89d74adcc789fd7e6e1:4388f7f68a9effbc366e42d907015604daced1727cd1d89d74adcc789fd7e6e1:ed4c2683d644b05b39b048ef1f8b7025f280ca7e8ff72cb7eda99329fb7954b700400705275f20b858cf7e349a3510665b630609c5e2e62069263ab9c55e4123a564dca6348c8a01332075e7a5bec9c20a03807957fefa910e60c35ae579778ce2ce42e6a69a1b647681e43ec4b63bd5fbefabb31712cb3d6419ead78dd41c8a92aaceb63cbfa89d2af39606de010a397e302053a615c16e5e95ad9935c079a0b8103125789471a1e3574f429b29e4d225c7723fbb3cf88cbd73823d9f0b6c7d05d00bdeb0fb0ad3d7132033183e21f6c1e8d8e4c0a3e4f52f5001da687171345c6dc8b42c42a60d1f1ffa8fe3e7bcece59a035878f9d4d81127e22496a49bfcf6bf8b46a80bd562e65255071f9d11a9eb0481f4626d4d71ffc38afe6e358a4b289179cbce9764d86b57ac0a0c827e8ff078813306a1d5fadd32b46a1fbcd789ff8754063eecfe45313beb6601c3a3010e8eb97c8effbd140f1e688311092d273c4defca47da6f1f0825744676f9a280b6c2a814fa47fabc1980d0b37f087a53ca8778f39ffb474ff5f1171b442c76dd008d92182f644a714a0f011e215a78b97af37b33520ebf43372a5ab0cf70dcc1dc2f99d9e4436658f8e07cdf0b9ea4dd6224c209e7521b981ee351c3c2df3a50040527fcd72804176046405db7f6734e85c5d390f520b0c08dcbfa98b8742480d5e46f9be893f6d6614340f8161611d5053df41ce4:42bed6a98786f664715f39bb643c405ae1750056460e700469c810389504c51cffd9e1a94c38f692fb316265316d8f4dc3ad1cdd8a6d5991ef010cd1489d7c09ed4c2683d644b05b39b048ef1f8b7025f280ca7e8ff72cb7eda99329fb7954b700400705275f20b858cf7e349a3510665b630609c5e2e62069263ab9c55e4123a564dca6348c8a01332075e7a5bec9c20a03807957fefa910e60c35ae579778ce2ce42e6a69a1b647681e43ec4b63bd5fbefabb31712cb3d6419ead78dd41c8a92aaceb63cbfa89d2af39606de010a397e302053a615c16e5e95ad9935c079a0b8103125789471a1e3574f429b29e4d225c7723fbb3cf88cbd73823d9f0b6c7d05d00bdeb0fb0ad3d7132033183e21f6c1e8d8e4c0a3e4f52f5001da687171345c6dc8b42c42a60d1f1ffa8fe3e7bcece59a035878f9d4d81127e22496a49bfcf6bf8b46a80bd562e65255071f9d11a9eb0481f4626d4d71ffc38afe6e358a4b289179cbce9764d86b57ac0a0c827e8ff078813306a1d5fadd32b46a1fbcd789ff8754063eecfe45313beb6601c3a3010e8eb97c8effbd140f1e688311092d273c4defca47da6f1f0825744676f9a280b6c2a814fa47fabc1980d0b37f087a53ca8778f39ffb474ff5f1171b442c76dd008d92182f644a714a0f011e215a78b97af37b33520ebf43372a5ab0cf70dcc1dc2f99d9e4436658f8e07cdf0b9ea4dd6224c209e7521b981ee351c3c2df3a50040527fcd72804176046405db7f6734e85c5d390f520b0c08dcbfa98b8742480d5e46f9be893f6d6614340f8161611d5053df41ce4: +ae331fc2a14759b73f1cd965e48514e12b29f63b06ccfc0ad49f36820e57ec7208803d48238eda3f9cebb628530121de00f0f0468c202d88528b8bcec687a903:08803d48238eda3f9cebb628530121de00f0f0468c202d88528b8bcec687a903:5716003390e4f5216598a03d7c430dbf495ee3a7557b580632ba59f15198b6180a42469c237db5bc81f29cfaab0aff3c9966309ab06958c9d7126add78e3b32459ff8a0e0bdef874b58e6083668f38ad7d63aae1f12e26a613348f9f03ea5d205f045d78cc8902d47f81e8b52293e70e86c9803d4dacea86c3b67458ae3579bc11113b5490bcf3e1cd4e7979c264d835161fd55efe953b4c26395dd92ca4930920e904fadc0889bb7822b1dfc4452604840df024db0821d2d5e96785a5c37dbfd2c375983283e9b5b43a3207a6a9b833948329d5de41e45008bcbad493de5754dd83decc440e5166edaae0208f000c5f6d9c372153209e5b7578116f89cf2f8b1004d1307ea79ed37480f3194a7e17983a230465ccc30fcc1a62d280fbbaccf006dc4dee0ea796b81accc61a063e2c083daec039bd9a64a77024af82ec1b0898a3154329fdf61673c36e4cc81f7a4126e56290e4b456819bdebf48cb5a40955bab297c2bbcb018adbf24828660a5d12a0613bf3ccb5eeb9a17fb0a0547db8da24d2efb87ba1b843142a75e4ca0b0a333e4a14fab35a62669329ca8753f016ac70cd997e8bc19ee448aeaf0f4bf3ce5230550578ab64c19019446ce2d9c01a03d889a9909860aef76f067c50b61c3d0f12cc8686f5c31bf032a841015cfeff1cfdae94f6b21dae941b335dc821f3284ce31508f5db5c448ffaa3773e9be1a4c85a1c58b009fa3:75f739088877e06dc56daec8f1e4d211b754e3c3edbfa7eda444f18c49b69c5a142db45a0a7650e47d10550ba681ff45dd4463c4ac48bf44b73034bd5659220e5716003390e4f5216598a03d7c430dbf495ee3a7557b580632ba59f15198b6180a42469c237db5bc81f29cfaab0aff3c9966309ab06958c9d7126add78e3b32459ff8a0e0bdef874b58e6083668f38ad7d63aae1f12e26a613348f9f03ea5d205f045d78cc8902d47f81e8b52293e70e86c9803d4dacea86c3b67458ae3579bc11113b5490bcf3e1cd4e7979c264d835161fd55efe953b4c26395dd92ca4930920e904fadc0889bb7822b1dfc4452604840df024db0821d2d5e96785a5c37dbfd2c375983283e9b5b43a3207a6a9b833948329d5de41e45008bcbad493de5754dd83decc440e5166edaae0208f000c5f6d9c372153209e5b7578116f89cf2f8b1004d1307ea79ed37480f3194a7e17983a230465ccc30fcc1a62d280fbbaccf006dc4dee0ea796b81accc61a063e2c083daec039bd9a64a77024af82ec1b0898a3154329fdf61673c36e4cc81f7a4126e56290e4b456819bdebf48cb5a40955bab297c2bbcb018adbf24828660a5d12a0613bf3ccb5eeb9a17fb0a0547db8da24d2efb87ba1b843142a75e4ca0b0a333e4a14fab35a62669329ca8753f016ac70cd997e8bc19ee448aeaf0f4bf3ce5230550578ab64c19019446ce2d9c01a03d889a9909860aef76f067c50b61c3d0f12cc8686f5c31bf032a841015cfeff1cfdae94f6b21dae941b335dc821f3284ce31508f5db5c448ffaa3773e9be1a4c85a1c58b009fa3: +82435f39790106b3af72f91f14c928d2465f98cdd10084c4a44d19af71a1927cc52a92646f5adb21c6dde0de58786837f8a3414c09aedfc27c812218a7e7239e:c52a92646f5adb21c6dde0de58786837f8a3414c09aedfc27c812218a7e7239e:f3d6c46ac5248d5386b6b68462597d647039f544bb01ac2d1067daaaa397d2dbaf125a1cf8fdf280a6afec324d5311f543688a156c849819bb046b911c42ea3ca01b99808c4d1f3b8b15da3efe2f32523ec3b09c84b48cffd13c17c9e26c912d9c3e9346dfae3fd0c56c8858780782f61a4c4dbfff1e9cb4b362cd8001f9cdfeb1a72082dce9c9ade52effc9744688ac0b86c88266b53d895c17ead9e89ed8d24d40642f3ad3b9bf9bbc4dda7966ef8328289fb31e17c81fd028ef1bd9a1d4c792e86ec2dbdce3f937eecc3eeb5188d325941919bbf75b4388e2399507a3d7fb387502a95f421c85826c1c9176c923e316310a4ba45c8a5ef7557cf87b77020b24f5ba2bfd1228109566307fea65ec015019691217bce69aee16f76249c58bb3e52171cfefd5254e5e0f397169186dc7cd9c1a85c81034e037183d6ea22aee8bb74720d34ac7a5af1e92fb8185ace01d9bf0f0f9006101fcfac8bbad171b437036ef16cdae1881fc3255ca359bba1e94f79f645555950c4783bab0a944f7de8df69258b6afe2b5932217195da245fee12ac343824a0b6403dfe462d43d288db31f99097ec3edc6e76547a3742f03c777efb158f58d4053fa6cc8d68b196af4f9de516fd9fb7a6d5d9ee4a89f9b9bce1e4dee357a1e52c0544cfb35b7092d1aa5a6f7f4c7602610e9c00ef5b8761bc72279ba228a18b8400bd76d5b2bfd7c3c04aac4436dae2e98:1daa44ef06d4c10ddb48678423c5f103a1b568d42b20cc64af110fce9d7679a2dee412b4980585c26c320dbaa601c472defc3c85415daecdd6d2d9eacac85e07f3d6c46ac5248d5386b6b68462597d647039f544bb01ac2d1067daaaa397d2dbaf125a1cf8fdf280a6afec324d5311f543688a156c849819bb046b911c42ea3ca01b99808c4d1f3b8b15da3efe2f32523ec3b09c84b48cffd13c17c9e26c912d9c3e9346dfae3fd0c56c8858780782f61a4c4dbfff1e9cb4b362cd8001f9cdfeb1a72082dce9c9ade52effc9744688ac0b86c88266b53d895c17ead9e89ed8d24d40642f3ad3b9bf9bbc4dda7966ef8328289fb31e17c81fd028ef1bd9a1d4c792e86ec2dbdce3f937eecc3eeb5188d325941919bbf75b4388e2399507a3d7fb387502a95f421c85826c1c9176c923e316310a4ba45c8a5ef7557cf87b77020b24f5ba2bfd1228109566307fea65ec015019691217bce69aee16f76249c58bb3e52171cfefd5254e5e0f397169186dc7cd9c1a85c81034e037183d6ea22aee8bb74720d34ac7a5af1e92fb8185ace01d9bf0f0f9006101fcfac8bbad171b437036ef16cdae1881fc3255ca359bba1e94f79f645555950c4783bab0a944f7de8df69258b6afe2b5932217195da245fee12ac343824a0b6403dfe462d43d288db31f99097ec3edc6e76547a3742f03c777efb158f58d4053fa6cc8d68b196af4f9de516fd9fb7a6d5d9ee4a89f9b9bce1e4dee357a1e52c0544cfb35b7092d1aa5a6f7f4c7602610e9c00ef5b8761bc72279ba228a18b8400bd76d5b2bfd7c3c04aac4436dae2e98: +1bea7726d912c55ec78b0c161a1ad3c9dd7bc329f85d26f62b92e31d16d83b48c9ddb42106ccef4e0ef4794551d21df94a6306872f231663e47e241f77cc3e82:c9ddb42106ccef4e0ef4794551d21df94a6306872f231663e47e241f77cc3e82:b11283b1f0ce549e5804730ac3207ac00332d2aacf9c310d3832d879f9634bd8a58adf199e4b863bb17481d28acb2da0e1557b8336a400f6295625031d09e4df4d319bbc1e8f6e9232d23053bb3ffac4fe2c70ce3077fc0060a5cb4692a1cf0b3e62fe454802ae10b83ded61b6bf454ca75e4cdad5532f20b70654f12ba906f003a8b9e986f15a39419deb2ea1ead7598290eeebf9252b0c27605a7a73a6abebb42271d71a3c197a46bcc8db11d9242842f378364a37eecaa34e982135be34182c69ca8e6e3c8c90e1b4b2b475815a178377ae0165a764c8ba2889b5ab290949d8487a88e0d3d2bc7e2520176aa6ff9ff0c409ff80515f4f0b83c5e82c23fd3326cdd6b76252e7fddcd6e4770978cd503ed2d6b480101167d3f191fed8d6d74d74a2007db1092e46a23ddecddcdb984664047b8dd7cc8a576e1a806f52cb027a9480a95cc44b1e6f2e286e9b7a6bf7b396fa5496b7a5b1c03d9c5c27da1a42990d10b12fb8640e1596f26b366d270ba64f99afffe3fece05a9b0254b208c7997cdb512fc77527954a1cb50fdab1cc9a45162741fd6f9d3fd5f2e382853d7335dba1e6b2959dd86e125e67b53dc8e453c810bc01bf20bce7b618dd5d1ed784106ee06a3ecaf6b3bee0b56833b0b813139c5a696000a449c97906a2fbddc2d9de9406ea282ac4ee5ef8bf3854c74a6b7173dd2f79c7a126f3c7b0433fd4ea26e877a14831dd415a19d:f9b04517bd4fd8ef90f2140fc95dc16620d1602ab36c9b165fff3aba978d59767110bb4e07a48f45121447ac0c1abac585d391d4042041898628a2d2dcc2510db11283b1f0ce549e5804730ac3207ac00332d2aacf9c310d3832d879f9634bd8a58adf199e4b863bb17481d28acb2da0e1557b8336a400f6295625031d09e4df4d319bbc1e8f6e9232d23053bb3ffac4fe2c70ce3077fc0060a5cb4692a1cf0b3e62fe454802ae10b83ded61b6bf454ca75e4cdad5532f20b70654f12ba906f003a8b9e986f15a39419deb2ea1ead7598290eeebf9252b0c27605a7a73a6abebb42271d71a3c197a46bcc8db11d9242842f378364a37eecaa34e982135be34182c69ca8e6e3c8c90e1b4b2b475815a178377ae0165a764c8ba2889b5ab290949d8487a88e0d3d2bc7e2520176aa6ff9ff0c409ff80515f4f0b83c5e82c23fd3326cdd6b76252e7fddcd6e4770978cd503ed2d6b480101167d3f191fed8d6d74d74a2007db1092e46a23ddecddcdb984664047b8dd7cc8a576e1a806f52cb027a9480a95cc44b1e6f2e286e9b7a6bf7b396fa5496b7a5b1c03d9c5c27da1a42990d10b12fb8640e1596f26b366d270ba64f99afffe3fece05a9b0254b208c7997cdb512fc77527954a1cb50fdab1cc9a45162741fd6f9d3fd5f2e382853d7335dba1e6b2959dd86e125e67b53dc8e453c810bc01bf20bce7b618dd5d1ed784106ee06a3ecaf6b3bee0b56833b0b813139c5a696000a449c97906a2fbddc2d9de9406ea282ac4ee5ef8bf3854c74a6b7173dd2f79c7a126f3c7b0433fd4ea26e877a14831dd415a19d: +d01a0ead9d694833283b9cd7299a7bd75fa90b1d2d7884e4557b33c998772a68a0f757479ba627efef95d6ec7a931dfac4373df33daaf4ddc4ec6894c8261ed7:a0f757479ba627efef95d6ec7a931dfac4373df33daaf4ddc4ec6894c8261ed7:7627534e9a83d1e406ab948d30d1da9c6a5db08e0feb7fc5ba5cbf76849ee8add4847ef5ca5a0dae411aca097451cb4c2b498c947097407007640dc19ed938e3b91bf51c9581168df860bd94751668dabd721dc73998400be20c9a563d5051ef70e3546fee673312b52a274041057e70848eb7c5a21644c97e448abd7640207d7cdafcf45da6df3494d3585b0e18ac5ac9081cb7a407a39a877705cbaf79a01b915f736eb025c58b4b5d807fb7b7566c5969787c1d6ca4eba97d509ef7fb3550d21d377eceffcf0eb6681895adbd246ee7bf3c935a006478b832ece46de6118b17e466a27fc2a44a896baae272f9ecf018c65cb50cfbfc8d260994a18a832d971928c449675724585131c871533c9897d8f80f9c0416b718786b10fea8eb5bd813a269a1b677b7a2507a44b713d705086530995e59335ddc2855e847e4f4db06c91f1d54023d8a10f69f9e61bdce4b686fb617bd5030e755cadb1f644e1ddd91619b96ecd605b00198b9a6eddb5a84ebd3692b665979766637c677378c1c77041fd4a6b3555c1dc8a83fe9013bb6106cc18a2b037c9377b7a1a5a5d0dcc54918eaad7e32c880767b26fd2ea2d68b0405f5e074f55a19d8a39ffbb7dc32faee6a7f9532aec8a0776c3ff83ae3a4627738496a371eb9e090b74e0eddecfcd41bed0c0ce581275243472d26da8c998e4b6d6b44fc88ba2ab54642225417120294417805742bdb33b7b122:9a0ff7f35174ec3f66d22a6f06df60e09c8f623a5aca810e23a88d0e6a31cb6f1ce1c1f9dccc9e1484b68dd004ac53597e29ad6ab72e8ce2b75ad5b80eb848037627534e9a83d1e406ab948d30d1da9c6a5db08e0feb7fc5ba5cbf76849ee8add4847ef5ca5a0dae411aca097451cb4c2b498c947097407007640dc19ed938e3b91bf51c9581168df860bd94751668dabd721dc73998400be20c9a563d5051ef70e3546fee673312b52a274041057e70848eb7c5a21644c97e448abd7640207d7cdafcf45da6df3494d3585b0e18ac5ac9081cb7a407a39a877705cbaf79a01b915f736eb025c58b4b5d807fb7b7566c5969787c1d6ca4eba97d509ef7fb3550d21d377eceffcf0eb6681895adbd246ee7bf3c935a006478b832ece46de6118b17e466a27fc2a44a896baae272f9ecf018c65cb50cfbfc8d260994a18a832d971928c449675724585131c871533c9897d8f80f9c0416b718786b10fea8eb5bd813a269a1b677b7a2507a44b713d705086530995e59335ddc2855e847e4f4db06c91f1d54023d8a10f69f9e61bdce4b686fb617bd5030e755cadb1f644e1ddd91619b96ecd605b00198b9a6eddb5a84ebd3692b665979766637c677378c1c77041fd4a6b3555c1dc8a83fe9013bb6106cc18a2b037c9377b7a1a5a5d0dcc54918eaad7e32c880767b26fd2ea2d68b0405f5e074f55a19d8a39ffbb7dc32faee6a7f9532aec8a0776c3ff83ae3a4627738496a371eb9e090b74e0eddecfcd41bed0c0ce581275243472d26da8c998e4b6d6b44fc88ba2ab54642225417120294417805742bdb33b7b122: +df648940b578bc31d2a652965f30391caf06d5f251599a737ce10be55f4a9d0d27de920419c186b01be54279fb8f9be4bb4b2cad75ca7e8f792bfa7bb97c7f41:27de920419c186b01be54279fb8f9be4bb4b2cad75ca7e8f792bfa7bb97c7f41:1ae520beeb4ad0722b43067fa7cd2874abcf34dd9237b4478eae9772aea297a67fb79b33070204baee440b9c87e2fbcbeb76801dddea5e4530d89e11583179939a00a32f811332c52291cc7ac91e5a970cd5aa708b1da26be9fe432a9bbda1319e31e4bcc9f1666a05b5c05b876bfd1f766687ccea4e4482e924329aface5ee52e9879fd69b76e0f7e452ec4713bff216d00c82599d27ca481f73aae136f0875c88a66b1b6f34c50523ab602e9d4ebb7eeb9e043a65e41899d79752a279d2ed46993926f3621e7c32c9a9b3b59d8dd57beca39285434de991cbd2dfcbc5ca62a7779f475d0cef2f3e562f29acd474f3c99ec5bd8de01101bed2e0c9b60e2d70fd432c892fc66f8d4619a911b5625163e9a42bf9ea38586d8e764001564d335411225fcb0a06dc2a82da0779a3c444eb7864201b43ebb72b921f34d3c13089df2f4fac366ff1e3c0b96f93d2b4d726a5ce4d6916d82c78be354a1230c2cf0418c78a1913e454f648cc92c8dd0e184645fe3781d263cff69f5c60b1ebb52005a8b78a515c7e8886ffe054dab428e2e221d9d76aff42654168d833b88178293e1fedd15d46cd609483129c4d2d84432a99d31ffe9bdb566f8c75ce65e18288e4df8c16731a0f3fdde1cca6d8ede0435ff7436ca17d0aeb88e98e8065cbcbfd0ff83043a357cd1b082d1703d461881872cdf741e4f99bd146745ba703974be40f579bf5c4dba5bdb8c941bce:62bc991c45ba9b26bf440116264162c34c88597885e9605083c604b5f5d8fa6f662ba214f76e6cf84e5ec04df1beefc5f25d3a3b72f98b5069831916a63296011ae520beeb4ad0722b43067fa7cd2874abcf34dd9237b4478eae9772aea297a67fb79b33070204baee440b9c87e2fbcbeb76801dddea5e4530d89e11583179939a00a32f811332c52291cc7ac91e5a970cd5aa708b1da26be9fe432a9bbda1319e31e4bcc9f1666a05b5c05b876bfd1f766687ccea4e4482e924329aface5ee52e9879fd69b76e0f7e452ec4713bff216d00c82599d27ca481f73aae136f0875c88a66b1b6f34c50523ab602e9d4ebb7eeb9e043a65e41899d79752a279d2ed46993926f3621e7c32c9a9b3b59d8dd57beca39285434de991cbd2dfcbc5ca62a7779f475d0cef2f3e562f29acd474f3c99ec5bd8de01101bed2e0c9b60e2d70fd432c892fc66f8d4619a911b5625163e9a42bf9ea38586d8e764001564d335411225fcb0a06dc2a82da0779a3c444eb7864201b43ebb72b921f34d3c13089df2f4fac366ff1e3c0b96f93d2b4d726a5ce4d6916d82c78be354a1230c2cf0418c78a1913e454f648cc92c8dd0e184645fe3781d263cff69f5c60b1ebb52005a8b78a515c7e8886ffe054dab428e2e221d9d76aff42654168d833b88178293e1fedd15d46cd609483129c4d2d84432a99d31ffe9bdb566f8c75ce65e18288e4df8c16731a0f3fdde1cca6d8ede0435ff7436ca17d0aeb88e98e8065cbcbfd0ff83043a357cd1b082d1703d461881872cdf741e4f99bd146745ba703974be40f579bf5c4dba5bdb8c941bce: +c8ac234558aa69816b368b77b7cccb5c8d2a33ec53aeef2ce2287143bd98c1755364baf1fdb2c63840b30d4031cf83a2e18e620793bae59d1035c0ede55e528b:5364baf1fdb2c63840b30d4031cf83a2e18e620793bae59d1035c0ede55e528b:ce488d26975c1c9328b47fa92e19561330041b23a0e57a4b8bca89eb5f615e73dd7fae69c2380e3212f9b73341c356db75a6256d7a20a97f759d4cba7197178ea724dd932949360e96c50a4b3ba55a953372c397b0969c2b14d3609e0a852d484df70eaab11249ebeb3237921f0a39a55d7dccfef205d94ec80d9e1fd6a2c1efd29844101dfe2c5f668adb7975915dedd086500cee2c1e233e8e48855cc1a6f287d63dce10addd13cac7b7a187efe47e12d1c35bb3974052b23a73668d3e4c87db4841af846e808672c43d0a1522e2965f083951b2b2b0c409548ee6182f0c9850514c9e6c102f54ba4124c92a90274f405891e662f5ebb3771b85783156e9e5836734d09d1baf5b2134c93162eec4be03bd12f603cd27be8b76accc6e8b8bac020cba3479651c9ffa53ce4eb77a77313bc1265ddab803ef7a6563ba6f799d1ef30ef5a0b412965fdac0b9dab842c78ee2cc628e3d7d4061e34ede3797e154b06e8c66cebdf2ded0f81b60f9f5cdda675a435277ba1524557e67f5cefafce929291dce89ecb08a17b67a60c582b487bf2f6169626615f3c2fe3b67388b713d35b9066669960de4db413cd8528ee56ed173e976a3c974ac633a7134cce38319735f857b7d71ba07f477ef85848aa8f39e118118779ed87b4f42aa358a89f7ec844a451e7e8fc0af418b85bc9bf2f26d1ea137d335ec7ee757b70ae2fdd9cc134932f0e5425bf37fb915e79e:32250361df6ed283485f95f3d357a4f1c33a8cf91658327cd453d49c953665510870aa454cfa3b83245220a827d0ec7477f9eceb79c4a29f301f953cc8caac07ce488d26975c1c9328b47fa92e19561330041b23a0e57a4b8bca89eb5f615e73dd7fae69c2380e3212f9b73341c356db75a6256d7a20a97f759d4cba7197178ea724dd932949360e96c50a4b3ba55a953372c397b0969c2b14d3609e0a852d484df70eaab11249ebeb3237921f0a39a55d7dccfef205d94ec80d9e1fd6a2c1efd29844101dfe2c5f668adb7975915dedd086500cee2c1e233e8e48855cc1a6f287d63dce10addd13cac7b7a187efe47e12d1c35bb3974052b23a73668d3e4c87db4841af846e808672c43d0a1522e2965f083951b2b2b0c409548ee6182f0c9850514c9e6c102f54ba4124c92a90274f405891e662f5ebb3771b85783156e9e5836734d09d1baf5b2134c93162eec4be03bd12f603cd27be8b76accc6e8b8bac020cba3479651c9ffa53ce4eb77a77313bc1265ddab803ef7a6563ba6f799d1ef30ef5a0b412965fdac0b9dab842c78ee2cc628e3d7d4061e34ede3797e154b06e8c66cebdf2ded0f81b60f9f5cdda675a435277ba1524557e67f5cefafce929291dce89ecb08a17b67a60c582b487bf2f6169626615f3c2fe3b67388b713d35b9066669960de4db413cd8528ee56ed173e976a3c974ac633a7134cce38319735f857b7d71ba07f477ef85848aa8f39e118118779ed87b4f42aa358a89f7ec844a451e7e8fc0af418b85bc9bf2f26d1ea137d335ec7ee757b70ae2fdd9cc134932f0e5425bf37fb915e79e: +2c47f2b8b9d2cee9e6f654bc24658f9eaf439c23beaa0a79bf35cc8cd2debaf4444af2f34fd32e5a19f61f87d03e107627a3eeb8bd94d2faeaa348b05dea1980:444af2f34fd32e5a19f61f87d03e107627a3eeb8bd94d2faeaa348b05dea1980:044c8faa8c8aaf9f2b8186a6b9b33847ec7b452423b22a91743d2e597ecc1e1e22ae60053e9ee6233b044e775920e4e3d66719901325cfdd39bb532f8aa469aab42e9608c21260c04c27413a7a94e466f63c4952e90ef90c12814b3451b1cad7da9147f8409220f6498cc0a67fef4bc04fc06e1d898a5515591e8be0c43d75a6fe425b7cbefb1b91b1bd78b5bec7829056982efdc5be24af6678006adc6f0446202e7ec3a2d6979cb0df7e25d74233914d9c58b81cf55be06967d3a595c1b9672869994cfba67162833a2143aa91cc93acdafa5b45208df3e88ccc01a2a4d220e360098d9154d225a7ca5f2f1e52b1003d106650a77b283b95e4baf1e7336fa9a747a2b3823d360910412e76db725ce1ab1e1d189d0d3abef82d7666bcf1b76669e0643b44f74e90ceafa0c8371b57c58f3b370a547c60958f0fcf461b3150f848c470fa07e29bf5f0d4b59efa5ab0d0341e0451d0abb29d7414cddc46cc6d74cf3dc233d0d1707387bd8c7780ff78e546fb77294d58a5dda5f05c1297e3d1771156d285635bf7ecedb38a9e5e77449804f3899ea46a50266b255aeb52d18e0fa136e535cc9026f678552fa3ee2146081d999685e24bf7807cc47c130436c544d35b4b875bd8afa312ce3ae17cf1c7f5ea1ececb50f95344720cecf088434ff8e0ba044ec19c98ada7782116304cbeac1c3e35f5a4f44313354dc9a40ece5a0f9ad3a2025acef262c5679d64:8554b01d09ed86e61395b91a2b1ee18715c42f9c7e7f0700d79ff9fb5781293d61c558dd5b431c93718dcc0f98fb652b596f18c30f82215e8e63e4f6568c8800044c8faa8c8aaf9f2b8186a6b9b33847ec7b452423b22a91743d2e597ecc1e1e22ae60053e9ee6233b044e775920e4e3d66719901325cfdd39bb532f8aa469aab42e9608c21260c04c27413a7a94e466f63c4952e90ef90c12814b3451b1cad7da9147f8409220f6498cc0a67fef4bc04fc06e1d898a5515591e8be0c43d75a6fe425b7cbefb1b91b1bd78b5bec7829056982efdc5be24af6678006adc6f0446202e7ec3a2d6979cb0df7e25d74233914d9c58b81cf55be06967d3a595c1b9672869994cfba67162833a2143aa91cc93acdafa5b45208df3e88ccc01a2a4d220e360098d9154d225a7ca5f2f1e52b1003d106650a77b283b95e4baf1e7336fa9a747a2b3823d360910412e76db725ce1ab1e1d189d0d3abef82d7666bcf1b76669e0643b44f74e90ceafa0c8371b57c58f3b370a547c60958f0fcf461b3150f848c470fa07e29bf5f0d4b59efa5ab0d0341e0451d0abb29d7414cddc46cc6d74cf3dc233d0d1707387bd8c7780ff78e546fb77294d58a5dda5f05c1297e3d1771156d285635bf7ecedb38a9e5e77449804f3899ea46a50266b255aeb52d18e0fa136e535cc9026f678552fa3ee2146081d999685e24bf7807cc47c130436c544d35b4b875bd8afa312ce3ae17cf1c7f5ea1ececb50f95344720cecf088434ff8e0ba044ec19c98ada7782116304cbeac1c3e35f5a4f44313354dc9a40ece5a0f9ad3a2025acef262c5679d64: +887fdb4870681d4fb06a936259f75cae0517f501af646bc07a4d72bee7fb1c73c762ebd48b2ce02d06384e38554b825ad322ebea74d259df1547a4d547ce0024:c762ebd48b2ce02d06384e38554b825ad322ebea74d259df1547a4d547ce0024:c5dc779f3f3fac06dd28e5a67e0e524af5b5dc3b34409657b63dface9471e9a41e1132175a0b569c8fea9d2eef2cf5d5962c7e0b6145a9e7a0c1aa33772044f9c3998c5a8c4886458b4e586f9307608361f511e7ab5092ac41ec76e0586ef5b9c236fcf5ca2fc8dd6aaeb789367f2e7c990932555dc52261e44e49423498b524419183b6c1f1d42c45464eccb0c2f7e25177fe5cd463502b403e06d511fcf9dcb64012e0f20b34c2ea7c004d9e484a7ed81f3260c41c8b1953529f47f71e867843cc3c332ad0366a63817ed12dd4730d3dfdbd7572b9ff798045940dd19fad0c8aea0b4ab61c4016de32799c73aa2b92d2c25ee9b72d46fe8f0693c58775efb05e9e17a5c346a81265d35be69a22d095de186066a5c6d8c07a3d38d002a10e5efdb866da4a9bdd54f5092661b6c2d743f5aeaa4c6c318fb59323903057e49c237b45f67542a4f27caf65b57cfcf88b71203d43d7f95322160f95c232dd10abb113b721ddba2226b063229bb44102336b10bf1656551161249786d454f4e0909d500017f6c7564f733c831af4e5ec94dfd3bf8ff5f3021b70a5ca5d28c6dfb8a2c18a1a662a33359f264d169698c1ab55783faca73bd68c0f79d1d04ae0ecdb52ae761892c02493ff35f3d84f66e236fc58134ad6a77d92254905d773900d9ddf2654c70b46f341dacb4793ca51eede45533eaeeb6e3323bc3e6c85a7940651c4f6f98191c618c891ea4e220ea4:410a5af3c59b7c6bdb214b166cb79d96f830cf98bf52dad7b6ff2979c97fea4fed5ef7d3d49f03097279b9a099226e2a08dd30c60786254e2da8dee240bfc308c5dc779f3f3fac06dd28e5a67e0e524af5b5dc3b34409657b63dface9471e9a41e1132175a0b569c8fea9d2eef2cf5d5962c7e0b6145a9e7a0c1aa33772044f9c3998c5a8c4886458b4e586f9307608361f511e7ab5092ac41ec76e0586ef5b9c236fcf5ca2fc8dd6aaeb789367f2e7c990932555dc52261e44e49423498b524419183b6c1f1d42c45464eccb0c2f7e25177fe5cd463502b403e06d511fcf9dcb64012e0f20b34c2ea7c004d9e484a7ed81f3260c41c8b1953529f47f71e867843cc3c332ad0366a63817ed12dd4730d3dfdbd7572b9ff798045940dd19fad0c8aea0b4ab61c4016de32799c73aa2b92d2c25ee9b72d46fe8f0693c58775efb05e9e17a5c346a81265d35be69a22d095de186066a5c6d8c07a3d38d002a10e5efdb866da4a9bdd54f5092661b6c2d743f5aeaa4c6c318fb59323903057e49c237b45f67542a4f27caf65b57cfcf88b71203d43d7f95322160f95c232dd10abb113b721ddba2226b063229bb44102336b10bf1656551161249786d454f4e0909d500017f6c7564f733c831af4e5ec94dfd3bf8ff5f3021b70a5ca5d28c6dfb8a2c18a1a662a33359f264d169698c1ab55783faca73bd68c0f79d1d04ae0ecdb52ae761892c02493ff35f3d84f66e236fc58134ad6a77d92254905d773900d9ddf2654c70b46f341dacb4793ca51eede45533eaeeb6e3323bc3e6c85a7940651c4f6f98191c618c891ea4e220ea4: +88b3b463dfc30d015eefbbbdd50e24a1f7277775bcef14a6be6b73c8c5c7303ef2b6284c930d4ad32d0ac719040ee7886b34722edf53da801acb5f931969e119:f2b6284c930d4ad32d0ac719040ee7886b34722edf53da801acb5f931969e119:17c317fa6bc90c5532328f02ccfb6c099e6fe1000174f2af3a3a9309428506717c5c4335bdd7c367ff4e448a9c047503afba68fd8f7987237be7f7fbdc6d73f24c6421cab422b3fb25f67b2d71042e71570df2af37bfe5c114211fd5524b6c1c6cc52fabc3cd7fb464cd580bb74071cb300f8c9f8a46208e5aa5ddfea5fe90697aa2f14c607950c98f2312a9e16ef6346a8fd129232733827e1501a660c77c29c56d2fdd1c5597f8bc89aaefe3713734fe82858201891a1147efaf1d78a471f920defc880344553eb716cce3260e86a1bc0be28373a6a066116e8ecb10a0c4a70ca2b5364e119f84aec60deced3a4eff1fe688c5e3e251470ab516fa964a4b6f28368dd1e283597934064dc0c5b5691062cb2e267bd15fd422bcfefb83ccef7aa9a2275ef57e473149988c1578fd18708d2ff69f8e5980aa826a82cab7d8b92bb53bdd46db046ecdfc8cd7ae5ce44f3c5b8c0565b5d3c072c76b95ce900ac3ee5510db0e75d3a4150a98f3ccccc69e930c6ba741dbb0eb9fb3196871ba206a58e0dae39c8d6bb72a82399c4b7b9da38577ac17ff1524d653c0bf33679323ca7eef4e9228729031560ed8f2e5193c640b2f5e608075a2ed61428dfccdc00050ba4b99ed6d1536d5ac1e939674b41d16312ae5b07def1bf53589bed4400602ee11b850330f38aad33ef04170a3905c28b50ecc57dccf4f29d0c00f713d32ffc857956588a6326b9549edb0e4fe6185:825aff71f79303bf4592bd8da4d7d9437ff267976f746437655988ddcf29379465a3b48c9fb0f31cef03e6368861c369b4364fb8e4b0c72e26a9a9dded1c250417c317fa6bc90c5532328f02ccfb6c099e6fe1000174f2af3a3a9309428506717c5c4335bdd7c367ff4e448a9c047503afba68fd8f7987237be7f7fbdc6d73f24c6421cab422b3fb25f67b2d71042e71570df2af37bfe5c114211fd5524b6c1c6cc52fabc3cd7fb464cd580bb74071cb300f8c9f8a46208e5aa5ddfea5fe90697aa2f14c607950c98f2312a9e16ef6346a8fd129232733827e1501a660c77c29c56d2fdd1c5597f8bc89aaefe3713734fe82858201891a1147efaf1d78a471f920defc880344553eb716cce3260e86a1bc0be28373a6a066116e8ecb10a0c4a70ca2b5364e119f84aec60deced3a4eff1fe688c5e3e251470ab516fa964a4b6f28368dd1e283597934064dc0c5b5691062cb2e267bd15fd422bcfefb83ccef7aa9a2275ef57e473149988c1578fd18708d2ff69f8e5980aa826a82cab7d8b92bb53bdd46db046ecdfc8cd7ae5ce44f3c5b8c0565b5d3c072c76b95ce900ac3ee5510db0e75d3a4150a98f3ccccc69e930c6ba741dbb0eb9fb3196871ba206a58e0dae39c8d6bb72a82399c4b7b9da38577ac17ff1524d653c0bf33679323ca7eef4e9228729031560ed8f2e5193c640b2f5e608075a2ed61428dfccdc00050ba4b99ed6d1536d5ac1e939674b41d16312ae5b07def1bf53589bed4400602ee11b850330f38aad33ef04170a3905c28b50ecc57dccf4f29d0c00f713d32ffc857956588a6326b9549edb0e4fe6185: +427d6e423917896831601b8f4e21561db6108571be009e29dca49a5960ff314b8d9e6360fdef249975df27b3106a71120587722df3270a85a13a8c3bb8c9809e:8d9e6360fdef249975df27b3106a71120587722df3270a85a13a8c3bb8c9809e:9c2cc7f2462e09c4c58c2709ab4259885a4e887d9fa531881505aaf203c163fb3a0dc028f4ada60670638d4a9727a39083bedbaced58edb779e1ce6ccdfb428c362bb1db0c1053006bd8f4bef89a1a9de01c774e357f910e5c39b22477555e5f7c0498b5b28f369e5d3fa42ab360e4f451c69f81ba0f3cced43a559db600104278f868796b2c911b3b032b729f4b22ac149dc467a0cae48d19e9d985b42b62549de171ff566e1d1e9bb8e56cfd1ae8f7bddcfd8a2341827dbe89c882ab3e498339ff681c7dc1104de738b480316943109f703d471ab86e4ca4287e4cd74c312ff7d037395606fb25f871e7277078a787d02f31cc9e815be8600a7c47c6fdd82331ae9c496a547bdb235b8a56d53259e6296124a32c3b625d202419d064b9a4e83efa87f13537b4f513b916a84fc866d8a899804c7833eaa019e0d7e0e8075bd6b5cb6ffc766479f3f6e20e481e6ab27bd808ad906cdcc7827430e312f740f275ddf51dd83248fa057c43c9cb77557b2fd9c2d52824ff9e146deac1e6691d450213bc590a49bec72d52e38f6b4dc6cca951eef2184d2425031ad59b242effa68b6c72c54c9dfdb419c02eb43ef3f34d338d2a9dd03a78cfdd014098e249259e77282e0c3fc1010b02a67ff851e9cfd9749c1cd8f06cf462e6ade995ac466fab5c795e9eff13e55b4350b94c7316aa498df9fdee9958047793e3bbb89fb81da85f4b9d43e4b0d43b381b94cdc9a99d06:d1c9a01c56e33960f49df37eab963bc5a99f25c600446ce2ca48d9139da5733b718fbf1a987393f6e5823c2d130c7ce60ea3db3543c8854ef12b98d33adde7059c2cc7f2462e09c4c58c2709ab4259885a4e887d9fa531881505aaf203c163fb3a0dc028f4ada60670638d4a9727a39083bedbaced58edb779e1ce6ccdfb428c362bb1db0c1053006bd8f4bef89a1a9de01c774e357f910e5c39b22477555e5f7c0498b5b28f369e5d3fa42ab360e4f451c69f81ba0f3cced43a559db600104278f868796b2c911b3b032b729f4b22ac149dc467a0cae48d19e9d985b42b62549de171ff566e1d1e9bb8e56cfd1ae8f7bddcfd8a2341827dbe89c882ab3e498339ff681c7dc1104de738b480316943109f703d471ab86e4ca4287e4cd74c312ff7d037395606fb25f871e7277078a787d02f31cc9e815be8600a7c47c6fdd82331ae9c496a547bdb235b8a56d53259e6296124a32c3b625d202419d064b9a4e83efa87f13537b4f513b916a84fc866d8a899804c7833eaa019e0d7e0e8075bd6b5cb6ffc766479f3f6e20e481e6ab27bd808ad906cdcc7827430e312f740f275ddf51dd83248fa057c43c9cb77557b2fd9c2d52824ff9e146deac1e6691d450213bc590a49bec72d52e38f6b4dc6cca951eef2184d2425031ad59b242effa68b6c72c54c9dfdb419c02eb43ef3f34d338d2a9dd03a78cfdd014098e249259e77282e0c3fc1010b02a67ff851e9cfd9749c1cd8f06cf462e6ade995ac466fab5c795e9eff13e55b4350b94c7316aa498df9fdee9958047793e3bbb89fb81da85f4b9d43e4b0d43b381b94cdc9a99d06: +be935209f62dea6012ecda6a6156cd166a4d761150deed456816eaf0ce78a7f6d39a89af72293948b13421fb883bbe372af9089c224d42b901979f7e2804e1c0:d39a89af72293948b13421fb883bbe372af9089c224d42b901979f7e2804e1c0:117f427cb68150cafcfa462c42206141427c4dcea1c8eacc2d30bed1e90207d5ae305e1fc16c54e4c54cc6878cdbedc9f51fe18461ec37c557b115d13c8682c4e15f505296a1760e1e75f5ab27a5c15a1357d2c8c40dd5355f7c82fea5d27e28876358c12e9113ee2983ea6f09c64e06e297dd96b34d9b5ed49fc47a8839549c66b002fe945e8f94e7d2315c50ca4dc098be4b3289812fbea96b47ce604540bde0e5ab0b1bc036be9b6a95e09c81e898640c8f05d60ad94218d0e66ceb85a26b78292220bfd061dd073512923b90c79dcf5a1935fafe8e01ef8bf81b4d37c5a571b50c421f9bd2194bef3586fcb8584877bb7e0481655b05c7b643b1e45b04036272841852e31940ef8f3b6d4feb5df079d176f979c18a11a66d1214e52f687e9063c1c2b7277b685d5c72ad569f7873838f910257a053131c83ebce86e69d736362bebc96bbfa35fcba1cb527e748e5f579929fd40c56b1a51a222e863302705c86f7b54ebfbb9482f7e280f7bec8caf3a6b5671ac30cd1be529288797c013ce56bd186de7dfc1828691425c147c5174a290d80cbd59c19da7adf77918882a7b2a9a64e6d76b48b92f2a266eee6e251d2e817652b88b502de7399782d7529a81d0a363996b9df68b15a7630904c8c246081fa4f09299f15757958e089a901c3564615c0f7cf2752b8b9e521338d836e3dae4ce2374642253c4c9831974e5d8c2842f49007b71775093dfe57f44492f0:08e098a749fce6d12354395878a8be35fe9edf72684dd8281224899b1caea4ed687785dff55a19989e03636e1666386f22c3f443ecf6fd34d599ff3ec2faf101117f427cb68150cafcfa462c42206141427c4dcea1c8eacc2d30bed1e90207d5ae305e1fc16c54e4c54cc6878cdbedc9f51fe18461ec37c557b115d13c8682c4e15f505296a1760e1e75f5ab27a5c15a1357d2c8c40dd5355f7c82fea5d27e28876358c12e9113ee2983ea6f09c64e06e297dd96b34d9b5ed49fc47a8839549c66b002fe945e8f94e7d2315c50ca4dc098be4b3289812fbea96b47ce604540bde0e5ab0b1bc036be9b6a95e09c81e898640c8f05d60ad94218d0e66ceb85a26b78292220bfd061dd073512923b90c79dcf5a1935fafe8e01ef8bf81b4d37c5a571b50c421f9bd2194bef3586fcb8584877bb7e0481655b05c7b643b1e45b04036272841852e31940ef8f3b6d4feb5df079d176f979c18a11a66d1214e52f687e9063c1c2b7277b685d5c72ad569f7873838f910257a053131c83ebce86e69d736362bebc96bbfa35fcba1cb527e748e5f579929fd40c56b1a51a222e863302705c86f7b54ebfbb9482f7e280f7bec8caf3a6b5671ac30cd1be529288797c013ce56bd186de7dfc1828691425c147c5174a290d80cbd59c19da7adf77918882a7b2a9a64e6d76b48b92f2a266eee6e251d2e817652b88b502de7399782d7529a81d0a363996b9df68b15a7630904c8c246081fa4f09299f15757958e089a901c3564615c0f7cf2752b8b9e521338d836e3dae4ce2374642253c4c9831974e5d8c2842f49007b71775093dfe57f44492f0: +6818c60bb6439ac2eee2d4e128e9d8691d4ad5d363fed7d6577a62b6569994a47345ec11bccc056fc4effa3e4ef670996aa26a1bb1b83391babc39a1a59601f9:7345ec11bccc056fc4effa3e4ef670996aa26a1bb1b83391babc39a1a59601f9:b2ae658b3c13c3cdeb1dc993b0f45d63a2ea9abd0b7a04f1f5ce5932806c2ca9b7a204fbf8d066b7f0fe6ae0d1da68c885ee11f6f6db7e8320a2ea650b533851cdd99d903aa0b3faa3c950f702f04e86b4eeb3a1c7bc854b2514fa5b4766d375b4f1ad61075378dd92fd626c2b47e01383ea72987959262c562862b45b7557671413b66614bcc9f7bdb9ee46cbed8965bfa505315090c7204bea89175be5f20802e3deddcbd8dd64cfef7ee6a6e3860ce1e5799df5d810d5ecf32e615d16dff87abd4a636ea17aa4ece5b6b2c046b65b5af749862b45790c39176820b36901be649cf4169df7e923956d96064950c555f45acb94507cfd0c3b33b080785e35c0d2b0addc4c0ad3fb216ac2e601c9c7e617dabda333dae603cc9db1fc62ae4e0e45e3ccdd166a6781e243b7daa138806632f538844ee3d140b7a8bb2b540100778c458e066170705e5fb2c88029098b992c39bc9ff6330bfcfe7752320e6ea0949d2c871aedc187be27fef7db5f72a6a773edde0dc52ae2ed931cb26817b85b1545894d92298aaf87ccbc783e8dd6d16493f56ead2ba852ee9c7d10074406440d2a279abc874f15468dd66a717bace37be7b7055dd9681f8be81329ee7af97e3abc434ac1c93aec582f23fd1ec0fa5aafcf7bfbda00ffa97ae317ae918d349d21a7f4619142ba23dacef7b390ae26a17e2e2962ae27005376b72d4da9e2979653a66325a14617638dbe1a5540b683ac0017:1505967a27b9f86e9242444002a1e3197d74ddcd89659ec5140202aac794b8adc193e7d30f3382642990f6fed7a999cac8c61eaa39b7d90816f1d738744be101b2ae658b3c13c3cdeb1dc993b0f45d63a2ea9abd0b7a04f1f5ce5932806c2ca9b7a204fbf8d066b7f0fe6ae0d1da68c885ee11f6f6db7e8320a2ea650b533851cdd99d903aa0b3faa3c950f702f04e86b4eeb3a1c7bc854b2514fa5b4766d375b4f1ad61075378dd92fd626c2b47e01383ea72987959262c562862b45b7557671413b66614bcc9f7bdb9ee46cbed8965bfa505315090c7204bea89175be5f20802e3deddcbd8dd64cfef7ee6a6e3860ce1e5799df5d810d5ecf32e615d16dff87abd4a636ea17aa4ece5b6b2c046b65b5af749862b45790c39176820b36901be649cf4169df7e923956d96064950c555f45acb94507cfd0c3b33b080785e35c0d2b0addc4c0ad3fb216ac2e601c9c7e617dabda333dae603cc9db1fc62ae4e0e45e3ccdd166a6781e243b7daa138806632f538844ee3d140b7a8bb2b540100778c458e066170705e5fb2c88029098b992c39bc9ff6330bfcfe7752320e6ea0949d2c871aedc187be27fef7db5f72a6a773edde0dc52ae2ed931cb26817b85b1545894d92298aaf87ccbc783e8dd6d16493f56ead2ba852ee9c7d10074406440d2a279abc874f15468dd66a717bace37be7b7055dd9681f8be81329ee7af97e3abc434ac1c93aec582f23fd1ec0fa5aafcf7bfbda00ffa97ae317ae918d349d21a7f4619142ba23dacef7b390ae26a17e2e2962ae27005376b72d4da9e2979653a66325a14617638dbe1a5540b683ac0017: +6d1da5b483e64b0365990ff09381fb1702fd8ec3a1a369cd52e4c56713a314a508055c261f26e02a658f66d9ba01fcde53e9ade3edc6bf815e4a6802e1677ab3:08055c261f26e02a658f66d9ba01fcde53e9ade3edc6bf815e4a6802e1677ab3:79a2c37055f189f3247f1f8cea19b2ea40d858db1f5d1392ee6d411c7802ee23de52ad02811725a94d76675da89a96b5d07abcee233a1a2e1fa324fff9e78a4c196147f8570b0b13713d96aa5d750a15d7cd162e7ba2e75333607dd698eb4773c7e91f7668ff8b62f04640eb12ecf122fce6b832e0d0df928eefd2c2002364af6bb55291d3f54929085be338342f09da73e279c87c8324555819ed57e78d7ac40951d33f65b94aa1e555e92a063d11f1ff7b12694341e3fe444933d01aa36753ed3cdda890bdf95a8205b5d893221991c795ad0a4a946f58d40a453451af214fd465e28d3e2f0a56aa56def8dc04aad35713abfc8bd7856d5a9dc3f60a3f2bd3e6366f1f244e941d6aea892f6a88931fe1c313e09078e90bc6392d490533c9ea3ff6deaf3aadfa8dfdc4e90f64af47589ea65a87acd2199602351d3afc2103196e0394ed523aa799d31e11d34fff546d44f436b34859f9cfbc9ce403de5a9830ec3d453f0d45970f572c144f191b2fbb2d0ea6cc9c8e24d9c0b2183b278072ebb0be2d70d037fd2e8ec18dc4c9b21abdc6a4ce8d4668a220eebd6934f04baf0e88a488d2dfc735a7c5a70dbb0166a21ae011fc6e7da10fc320336271d9eead510a6f7032f2296692be508021bc98c170be4235f7ce31f2bcd6341163683376ae2c5662cb4770c96e018ef1bf47913319c9a09b9e965ab5c3e97bbc756a5666b4567f2cff2d0c3a6a4026158cb9f90f950056:a5b8b44a91444c64374b523cb4dcb0cef4ce52408b98126d7e1ae8bdc28cf51470ce4e253e0be62bd68ebf5fa6bce1585eccfa9256c073ee03e54c525bbe2d0a79a2c37055f189f3247f1f8cea19b2ea40d858db1f5d1392ee6d411c7802ee23de52ad02811725a94d76675da89a96b5d07abcee233a1a2e1fa324fff9e78a4c196147f8570b0b13713d96aa5d750a15d7cd162e7ba2e75333607dd698eb4773c7e91f7668ff8b62f04640eb12ecf122fce6b832e0d0df928eefd2c2002364af6bb55291d3f54929085be338342f09da73e279c87c8324555819ed57e78d7ac40951d33f65b94aa1e555e92a063d11f1ff7b12694341e3fe444933d01aa36753ed3cdda890bdf95a8205b5d893221991c795ad0a4a946f58d40a453451af214fd465e28d3e2f0a56aa56def8dc04aad35713abfc8bd7856d5a9dc3f60a3f2bd3e6366f1f244e941d6aea892f6a88931fe1c313e09078e90bc6392d490533c9ea3ff6deaf3aadfa8dfdc4e90f64af47589ea65a87acd2199602351d3afc2103196e0394ed523aa799d31e11d34fff546d44f436b34859f9cfbc9ce403de5a9830ec3d453f0d45970f572c144f191b2fbb2d0ea6cc9c8e24d9c0b2183b278072ebb0be2d70d037fd2e8ec18dc4c9b21abdc6a4ce8d4668a220eebd6934f04baf0e88a488d2dfc735a7c5a70dbb0166a21ae011fc6e7da10fc320336271d9eead510a6f7032f2296692be508021bc98c170be4235f7ce31f2bcd6341163683376ae2c5662cb4770c96e018ef1bf47913319c9a09b9e965ab5c3e97bbc756a5666b4567f2cff2d0c3a6a4026158cb9f90f950056: +5146f5b7f1baa19fc8cd785c896e0f90f9f659b77b1b9bb4adcab5a6267205e4688a8de64eff33ba6bbe36cdd6a384bb67b3f42636db234ff5efe0b31743c7e6:688a8de64eff33ba6bbe36cdd6a384bb67b3f42636db234ff5efe0b31743c7e6:97bd99f518ee0788d576d99c043b449dfc242ac5eeaec344a19432b345962ec412ce55362b3b851d98119fceb9328347f6fcc68dbf56a2814db09e9385843a931189ea3e72da9d79a45693053c035701dc5551240f95b303fba16f89aa53a43882b0f1381202c78f9c7419899f2351eca95e20bfee76351c48d00499f591da56a99524bb74fe1c834ee91077139f1edf67315c07a3fd97f80b7c276b6cf6b5cc36be363b731217f6319f5129ba7b14d054c8d81d8e3a3f3be62ac31ff62df6a3b2ee2596969b991704b31c689997ab4628bc2660c67872132e85da0c4fcf567965f1254a8f432692a17bb86cb3c1dcbaac939552f09e50ec5b0de2ef85e0ac253a4165655db5b5c49803821d859c60961e061d58278b827dd4d3bc47f1c22de094906bdbbf3badbdde22ba24255855eb86d1d7f37082059311dc0728ebeaf26c4473bad1fa9e614b533b811b6bcb0650c06d879a5245788f3401b46197300774a9aa73cd978c0530c81a53bdb3fc932414b3e30440dc127441eff1605e7fd9ac8c632e82bf1b453d4f33a57e4b67b0b6fcf6ed5555b5f5a300a14a00d0385a33750525b00edb312c6bfdd64edd3b5316d19f958c517634f013b008936d34e9b5e1e9283a5f0fd7783377c0e5090641bb9d338cf3133acd0b971e537904f17af92911afad72ee97f9a8283a16a7e26ab428416c1017dae9b1a99c4c3320ad163bdcfc328bfaf9b8d5d7d26d41d1ef21a5208f01:4bdbd7c64f13e278c23969e7eb386bbe499dbdefc3ff4e30cfac5cf86f216c24c9e6cde20e529d147fb7ea08f2593ad50903b5edbf86b4d28f2eb32ef137f00c97bd99f518ee0788d576d99c043b449dfc242ac5eeaec344a19432b345962ec412ce55362b3b851d98119fceb9328347f6fcc68dbf56a2814db09e9385843a931189ea3e72da9d79a45693053c035701dc5551240f95b303fba16f89aa53a43882b0f1381202c78f9c7419899f2351eca95e20bfee76351c48d00499f591da56a99524bb74fe1c834ee91077139f1edf67315c07a3fd97f80b7c276b6cf6b5cc36be363b731217f6319f5129ba7b14d054c8d81d8e3a3f3be62ac31ff62df6a3b2ee2596969b991704b31c689997ab4628bc2660c67872132e85da0c4fcf567965f1254a8f432692a17bb86cb3c1dcbaac939552f09e50ec5b0de2ef85e0ac253a4165655db5b5c49803821d859c60961e061d58278b827dd4d3bc47f1c22de094906bdbbf3badbdde22ba24255855eb86d1d7f37082059311dc0728ebeaf26c4473bad1fa9e614b533b811b6bcb0650c06d879a5245788f3401b46197300774a9aa73cd978c0530c81a53bdb3fc932414b3e30440dc127441eff1605e7fd9ac8c632e82bf1b453d4f33a57e4b67b0b6fcf6ed5555b5f5a300a14a00d0385a33750525b00edb312c6bfdd64edd3b5316d19f958c517634f013b008936d34e9b5e1e9283a5f0fd7783377c0e5090641bb9d338cf3133acd0b971e537904f17af92911afad72ee97f9a8283a16a7e26ab428416c1017dae9b1a99c4c3320ad163bdcfc328bfaf9b8d5d7d26d41d1ef21a5208f01: +5e6fdac9351a637b99f33a264e1287697e2abab0cca16621792484f5606f44c157e5f88acddc8cde7dd07a3146fb1d4f7a9b6383a8f6b2b8d9b07ebc3fc4dd20:57e5f88acddc8cde7dd07a3146fb1d4f7a9b6383a8f6b2b8d9b07ebc3fc4dd20:4d6cd3bc2f86266b8bb1b61d0e1caa9bd2d4a180361aef3a18d390b10f7e860f697e247eb6c3e51d3b976bf0ca183d01a69880f15c94b875668ca30dada0895bedd4d705a0e03304d063dea87c7fdec98b89c06f130dd5bd586b54d9ba737826bb405cd8ac8bbc9500acda3c07461d009440af0b2531e72f3ff5016ae2d86d69b87fb273d1e8dd5f6a264beebb2f885996741ffda277a0fbf8ef08f81f22ee5961d9d3fc938362e1ca12004a91d9b5f7a6833a6c22955ac0cda3390671910cbd51e685fe095973e415fc2db8adf10b147ec7080c3b8ebd07d21bb9556da85430a268eed8486b1e31c94313b01649fe91b222f85adee15eb77707d78ffcb660926544d33be9994a297620dc7aed97f392639053f388b0b3aa3bd0ac5b033cb414be520b43df6826b976890d0c53b97b6c92e7d1a1573d0c7494d747e0cad9bd8ea538d62ad59801ad0716f170193e3009d9959c55d2ff64799bd959359abb94ca9723b5ffc24c9507f8c5fd6e88eaae7a70add84d744ccf8b98363788f0bfb1a02522025751e534710d40a2d38a791194eba293fd2046cc14dd3876d168fc6e236cbe146d6369d225bfa67e53979865f78873a9fcf03c186fa8521f0a5545accee80d1e55107221e21f0f2291c143de023e88d7330cc87d4c51ff29a3090605e9739490c1dcee713495f231c2a36b11ab235547fb6328f747336d9b1ef25a8ab99ceda957b2dccee4075b0d03381b94ae18d041ea:987e32e00a8a1632f47b503194355c980cb22adeb326b4e3115ecab04b704d186cd92e3c3ac7b4e2936cbd07cb794ec0cfe91a97872ff2b41376f5f18f55b8054d6cd3bc2f86266b8bb1b61d0e1caa9bd2d4a180361aef3a18d390b10f7e860f697e247eb6c3e51d3b976bf0ca183d01a69880f15c94b875668ca30dada0895bedd4d705a0e03304d063dea87c7fdec98b89c06f130dd5bd586b54d9ba737826bb405cd8ac8bbc9500acda3c07461d009440af0b2531e72f3ff5016ae2d86d69b87fb273d1e8dd5f6a264beebb2f885996741ffda277a0fbf8ef08f81f22ee5961d9d3fc938362e1ca12004a91d9b5f7a6833a6c22955ac0cda3390671910cbd51e685fe095973e415fc2db8adf10b147ec7080c3b8ebd07d21bb9556da85430a268eed8486b1e31c94313b01649fe91b222f85adee15eb77707d78ffcb660926544d33be9994a297620dc7aed97f392639053f388b0b3aa3bd0ac5b033cb414be520b43df6826b976890d0c53b97b6c92e7d1a1573d0c7494d747e0cad9bd8ea538d62ad59801ad0716f170193e3009d9959c55d2ff64799bd959359abb94ca9723b5ffc24c9507f8c5fd6e88eaae7a70add84d744ccf8b98363788f0bfb1a02522025751e534710d40a2d38a791194eba293fd2046cc14dd3876d168fc6e236cbe146d6369d225bfa67e53979865f78873a9fcf03c186fa8521f0a5545accee80d1e55107221e21f0f2291c143de023e88d7330cc87d4c51ff29a3090605e9739490c1dcee713495f231c2a36b11ab235547fb6328f747336d9b1ef25a8ab99ceda957b2dccee4075b0d03381b94ae18d041ea: +fcfff0932dc86ea5902a8d33073329960cd8188a075dd0bcdfa8382c20b0e78f0c9205a90bbe7f2d505e17fa3d080b522a1d7a152cad2d85d31b34a0471c0d4c:0c9205a90bbe7f2d505e17fa3d080b522a1d7a152cad2d85d31b34a0471c0d4c:3d4b76122373e212a346d19a66bbfc4b623292649bd0ce5cf6bb135648bd01db7403b3d0bdd1697ff4e6e908904116754d370c40d700cdb664c46a91dd84a358b9d2381443e60f2c3f5640261b6b858ba8f828b0971f4122b20288a26ba2090ba14fd276360cc68679cd8419ae19c6d4dc7b6614c06df5e5c0510e2cb686de0ebd75e5210a215562589b28c9ccc7d272b98bd4bf93495efe4fc5b78defecfbcaa9fe126bad30e89b3a389b4256f6a48a76c345de5a36a1449f08345b9a5e6a001da1ff9cd433709348e9aefbc78ba52d3ab3b46986935eba8ecf81edc43c5b2e3b5eb38d9a165e9e7f72f617605463bedba973ebfdcdf2b0889c71412f8f850c7a3b5518ecd89d2e25c0c1c30f085a0ffe540ef9c0e88fc7ec4af1948a4e6f7a6e256b307a1127b71ba686efeadca0e4860947cf674fced6caf7310ccbaa8d9047daed30fd5585d41ddeae4df2fed4b6228032c3e4ae2380e87ec6cd72e4d74b8b4c3813fb043389391e9c13f7d33c3aab5a78fc4c6a634c61a70f02a940548da177c65df6ab17cd9683f37ea821c740889d82e88c834e7d5dc11662ea78b13c6a4b6218d31784219a4767595b1a56216525cd68938b22bdb1f8c5a7f1701afeb961888e2e0ec0c838cd620cb7dd8a1493a02cd56b545125e4700c0889fa2644e644a3af531d1cd6bc95e5df9175f137f28408cb699c7ae66f65d1d2930fac57ca8a60e6311a4078488c9ea404948a9debeb9d5e10:37ddd83f98b057b7cb3208a832c58aa90694563c23548d432291380b73591301f274b04cee2ef78c06d96c3d9b7c17521aae1a8ca50d347c09c3cf703bc8830b3d4b76122373e212a346d19a66bbfc4b623292649bd0ce5cf6bb135648bd01db7403b3d0bdd1697ff4e6e908904116754d370c40d700cdb664c46a91dd84a358b9d2381443e60f2c3f5640261b6b858ba8f828b0971f4122b20288a26ba2090ba14fd276360cc68679cd8419ae19c6d4dc7b6614c06df5e5c0510e2cb686de0ebd75e5210a215562589b28c9ccc7d272b98bd4bf93495efe4fc5b78defecfbcaa9fe126bad30e89b3a389b4256f6a48a76c345de5a36a1449f08345b9a5e6a001da1ff9cd433709348e9aefbc78ba52d3ab3b46986935eba8ecf81edc43c5b2e3b5eb38d9a165e9e7f72f617605463bedba973ebfdcdf2b0889c71412f8f850c7a3b5518ecd89d2e25c0c1c30f085a0ffe540ef9c0e88fc7ec4af1948a4e6f7a6e256b307a1127b71ba686efeadca0e4860947cf674fced6caf7310ccbaa8d9047daed30fd5585d41ddeae4df2fed4b6228032c3e4ae2380e87ec6cd72e4d74b8b4c3813fb043389391e9c13f7d33c3aab5a78fc4c6a634c61a70f02a940548da177c65df6ab17cd9683f37ea821c740889d82e88c834e7d5dc11662ea78b13c6a4b6218d31784219a4767595b1a56216525cd68938b22bdb1f8c5a7f1701afeb961888e2e0ec0c838cd620cb7dd8a1493a02cd56b545125e4700c0889fa2644e644a3af531d1cd6bc95e5df9175f137f28408cb699c7ae66f65d1d2930fac57ca8a60e6311a4078488c9ea404948a9debeb9d5e10: +a1e4fcfde044f1bb0e7bbc631a831a8d07e90ae08a966ad627b620b1e28c42cf25560f31168bd4b72552ededd08bb6bf79a94063c1f1e1d304869dd1ce049b95:25560f31168bd4b72552ededd08bb6bf79a94063c1f1e1d304869dd1ce049b95:8c1454d4e08a1401646bf7a8859e8a145e85eeeb40db38ff0169709641212c81b67390749c01a79807f3ccadbbd2256f36ffc180cf9ba44bf4a7612d441c23b2e25d33c48a73e16ce357562758adb00553c3142fb8176b6ae8fb610a60f923b0911814b10f5679936c3677b70e846e218f587567f2019c7d282a107f3cc84763adaec88993c0cc5003e77af60d67db53f8cb727aa6672de004498c3b3e222aa7082d91f98a1a068374c510ff53a5e559cbe2d6c7c3442d7238907c811d58aa7f5a46b8311244f0dbe1b9c0e944dda1d8010864949c59396c6b346a11f3aa866d6bceadfc909038d22efbc8f1dac810a9f2fafcce7c0389eb0a56c0f68cae24ae3ddbdff7116d2fadeb9b0e7509536fdc3b83e71354da6a1aed16887490dc2f4df57bbaa7244528fa3094b99e867581acef906270b2cf4deda6b8fd9dbb79add7bea8f86fcb1f64dfd50e385b4209ec0b1a9f6d2e519068297a2b5c405c216b4a2ed983ff69c59b530effa60c0367051267dd2bbd1e86a9ab5a114dd4f69b540bfabfe97c0403b8fcbb27625761eda3e2ad8e625cfe4b615b7025531a498918c24e02a00e797bbafd14f9d3f6827e390063c436080688d037a6e2993c56d3a8e95f375c10040bf04f030c972623d9e3801c13b4ec8d01cf183855f5935f10ddb2c54c51c80cbed0c24db56e1ed148931d89161c5ea37c2f9787f88ef7330e5dcd0e43d81bfc8bf23ddf7983cc1d733843a33ccb395dfc:c8001527bd902c15c3dd5ae18180525b5e8202be66711f82885c8222a15f060092a2a6e2f7d7e980311209191b32b8ade48d3ea98cf245f0fad62c009c5a71088c1454d4e08a1401646bf7a8859e8a145e85eeeb40db38ff0169709641212c81b67390749c01a79807f3ccadbbd2256f36ffc180cf9ba44bf4a7612d441c23b2e25d33c48a73e16ce357562758adb00553c3142fb8176b6ae8fb610a60f923b0911814b10f5679936c3677b70e846e218f587567f2019c7d282a107f3cc84763adaec88993c0cc5003e77af60d67db53f8cb727aa6672de004498c3b3e222aa7082d91f98a1a068374c510ff53a5e559cbe2d6c7c3442d7238907c811d58aa7f5a46b8311244f0dbe1b9c0e944dda1d8010864949c59396c6b346a11f3aa866d6bceadfc909038d22efbc8f1dac810a9f2fafcce7c0389eb0a56c0f68cae24ae3ddbdff7116d2fadeb9b0e7509536fdc3b83e71354da6a1aed16887490dc2f4df57bbaa7244528fa3094b99e867581acef906270b2cf4deda6b8fd9dbb79add7bea8f86fcb1f64dfd50e385b4209ec0b1a9f6d2e519068297a2b5c405c216b4a2ed983ff69c59b530effa60c0367051267dd2bbd1e86a9ab5a114dd4f69b540bfabfe97c0403b8fcbb27625761eda3e2ad8e625cfe4b615b7025531a498918c24e02a00e797bbafd14f9d3f6827e390063c436080688d037a6e2993c56d3a8e95f375c10040bf04f030c972623d9e3801c13b4ec8d01cf183855f5935f10ddb2c54c51c80cbed0c24db56e1ed148931d89161c5ea37c2f9787f88ef7330e5dcd0e43d81bfc8bf23ddf7983cc1d733843a33ccb395dfc: +bed1bbcae18643d6f6aac34f3d9b6a1478394d02b931cff006d85f21b7dbc7474f528b38185a424c6fdece46511a0c29b7c04b32eb0483abb52d5f8eb6b352eb:4f528b38185a424c6fdece46511a0c29b7c04b32eb0483abb52d5f8eb6b352eb:ff7c6413e618a056de401ee10c40ade3d7c0e6861495d97c2689ec6abb69dd2ae701fdcac8f08331ea5c5f5d805b5789ee5e241ff4ac8b960f4f2b9fef6a727fad86dcd432de9fad6ba45e00aa3687b0ceeb2c0d430b7d5fde63b4f6b982c4f9e03c430abad9044d06dc49e89df481405d8febbb0653e9686948aad2d9072544df9424fd487f4e24ba7f2455ddec4105828c3981bddbb1b7fbdbac155903e960fcd94c0716e736f519867fbc52c51260f571d7edcb081a23550ad8c70bb268864ab276aa2cc2dbf62383bb66030ebe94354174ccec2d2a907578556444507cbf8488bb23c62423a3a98da7cc968f599d3dc84dca3afad7f14ec306e1db534143216aa22ad18074c719570805ea46bc86b71a8ff58e41e73cb29ad5750fcfc9a1c54292b64b47ec9538f53816e36ed0d0c1ae5ead06d477aa975ecebaf62d9023b77e50e7b6d4abdaa485ea34ec766beb1d9ba03c9c067186e2e38266c6e2531e97480214638a2bb31431ac2086797155fc775b3aad8d5a0b904c381edd0c6bc23c66a1904955ed450a9cbd16459c32f5ca354bbc2da7b1a4d814f1b8710aadb2ccc4f397758b7e9d91f3a91e5825ab8682ff5e41702e07841ac7698c3da9f558edd01f86ce2c506bf4c2149ac9c195a59c7dd7d4ecf93c90b4423b4350588d41672cedc8510a7ad53b4b7edcaf23e43e05669d27a1fe97b78730d3fc060bd4edd9872cffb96285351bef148ef783ab392116bd7b907bad:0fc99dd3b9a0e8b1fc6e635af5c64006b67200fe958f53cce1b9b091a4e70669b593f15594bc0842e5576259f9a6859a0db22d740f9f8024b5baf1ef6f958c05ff7c6413e618a056de401ee10c40ade3d7c0e6861495d97c2689ec6abb69dd2ae701fdcac8f08331ea5c5f5d805b5789ee5e241ff4ac8b960f4f2b9fef6a727fad86dcd432de9fad6ba45e00aa3687b0ceeb2c0d430b7d5fde63b4f6b982c4f9e03c430abad9044d06dc49e89df481405d8febbb0653e9686948aad2d9072544df9424fd487f4e24ba7f2455ddec4105828c3981bddbb1b7fbdbac155903e960fcd94c0716e736f519867fbc52c51260f571d7edcb081a23550ad8c70bb268864ab276aa2cc2dbf62383bb66030ebe94354174ccec2d2a907578556444507cbf8488bb23c62423a3a98da7cc968f599d3dc84dca3afad7f14ec306e1db534143216aa22ad18074c719570805ea46bc86b71a8ff58e41e73cb29ad5750fcfc9a1c54292b64b47ec9538f53816e36ed0d0c1ae5ead06d477aa975ecebaf62d9023b77e50e7b6d4abdaa485ea34ec766beb1d9ba03c9c067186e2e38266c6e2531e97480214638a2bb31431ac2086797155fc775b3aad8d5a0b904c381edd0c6bc23c66a1904955ed450a9cbd16459c32f5ca354bbc2da7b1a4d814f1b8710aadb2ccc4f397758b7e9d91f3a91e5825ab8682ff5e41702e07841ac7698c3da9f558edd01f86ce2c506bf4c2149ac9c195a59c7dd7d4ecf93c90b4423b4350588d41672cedc8510a7ad53b4b7edcaf23e43e05669d27a1fe97b78730d3fc060bd4edd9872cffb96285351bef148ef783ab392116bd7b907bad: +c718823f43db2217c66ab2899704165d208573de60f33bc0b9338d880f193fb52940b879b63f2cb1f6e3ef9c9d333ba91770fe18cc5a347fdf12b0efc5ca2ec9:2940b879b63f2cb1f6e3ef9c9d333ba91770fe18cc5a347fdf12b0efc5ca2ec9:050e6877f65ec726eec701863fab140b994aa1e92a487db1a18701312057db44bfde70911ec26eaa28632d03794d545dfcb2aed4340cab7d092595cd59ed23994043f50ba696e9802bd64990121397286457ae69d76cb8e34d7c1ab245cb07b1b408f2bbbfdf33a1bdd559636702c918f982c2ac0221f7f94db91edefce28118259f89d994dad5bb013c678c1c338b65396b15e8899c169921f278859ce0c856d889b8c63418ebc573d2d625d5b5938839f2b169b6916d8e40dde70d3b72887ad2478ef6fb1284fa0e4fc524e3c6fa1dd22ba6b81def8279f382bcb45048851b17cd659d59409f571fa8a920a20934d9dbe1022d635840965400240f870aceffd5db7c7df08af89e47e1b9e20bb99f96ab073edf53694c7482890e3631340217e687ab27c984b60825169457d435a5409ad8e42da0aa63e20c2bc67bd8b9a267f39673a77f7f3136dc5cb2d24948dbe7bcd7129318c68c6fe95dd4dd4fe942286831ea53352fbb252a1288bcd838921356785d072134cb820f6279cc71461f431be9d3014724321c92fdc576320137705cffb2c23664b705e9be60ae1a190f3e3484f70058e702407b056d7fe5d31cee9c2a6ac6eada3516abc5517256df1243780a03bb00ba00ce248076eeca6fee91d5ef9eb907b801af097f3e9eb256bdcde81efe4baf8189b0399e36f1eaa3ab626617cf3b47dd89caf69c64c5b8f68bd917fe03e4668538460a1be88d9a846cef39934627d474734f:4c9cdb1ad46509560d871d3089afb8734648201b10acc953e8b61f2cce2dbae0fb9b868ac957432b7222dbf7e4cf0bc75309bea360b263abbde188532dda2504050e6877f65ec726eec701863fab140b994aa1e92a487db1a18701312057db44bfde70911ec26eaa28632d03794d545dfcb2aed4340cab7d092595cd59ed23994043f50ba696e9802bd64990121397286457ae69d76cb8e34d7c1ab245cb07b1b408f2bbbfdf33a1bdd559636702c918f982c2ac0221f7f94db91edefce28118259f89d994dad5bb013c678c1c338b65396b15e8899c169921f278859ce0c856d889b8c63418ebc573d2d625d5b5938839f2b169b6916d8e40dde70d3b72887ad2478ef6fb1284fa0e4fc524e3c6fa1dd22ba6b81def8279f382bcb45048851b17cd659d59409f571fa8a920a20934d9dbe1022d635840965400240f870aceffd5db7c7df08af89e47e1b9e20bb99f96ab073edf53694c7482890e3631340217e687ab27c984b60825169457d435a5409ad8e42da0aa63e20c2bc67bd8b9a267f39673a77f7f3136dc5cb2d24948dbe7bcd7129318c68c6fe95dd4dd4fe942286831ea53352fbb252a1288bcd838921356785d072134cb820f6279cc71461f431be9d3014724321c92fdc576320137705cffb2c23664b705e9be60ae1a190f3e3484f70058e702407b056d7fe5d31cee9c2a6ac6eada3516abc5517256df1243780a03bb00ba00ce248076eeca6fee91d5ef9eb907b801af097f3e9eb256bdcde81efe4baf8189b0399e36f1eaa3ab626617cf3b47dd89caf69c64c5b8f68bd917fe03e4668538460a1be88d9a846cef39934627d474734f: +2543d166c9f5f7427ff3034ffa8103cb117bf472331a73d9a2f1bc0a02a6ff1b42678cf3857021aa5567706db031e792715ccaf8abb02a042bad17db3d5fa103:42678cf3857021aa5567706db031e792715ccaf8abb02a042bad17db3d5fa103:746d7abf0bfb2662c25ab5c5e4612c306f16d13e44d0db394a0015676ce609784f0323da1dfa94d2b2f1f6e02444a936d019b143021f73c79df9309e7bdff39daeec4caca00cba4ef31c8310c1a08ef4b36f81c377846b5b90acd411aa671ed7af278a24229b7893c1b415d79888d7637f5cb5c9c6c631ae5ffa29f1340e444096ab533617fdcb80ff81da0a7c6c142ee0fe5ea82f68cc3ea38b56f272b0d80fd5f4f55ca9348c161881435813c3fa9fff66a2ee6d5bd3edba0d2f9aa74b1c44bfd0e64678d3715124963ac575ffb09ee16437da484b3ba58e5aeb8ed8c5c0f47b59908fe580f37ec1de266b295d6be85e62358e9bbdc78964fb837eea29fdb7de86cc56f48bd9a3e6e2be51d8a1dcff3ca4d56ea934c682772bcafb51497be5d0f2a23dd4970c02c44c09ad897b4241acd7d6ab12d8f00c9aadc334b431fec5bb69a285b7550a639ece96952682b7334b68c65152e893b1c8100c694d8c5cfe26ac03c1f3914e65c84f0e777290c76f6acce340bff66da7220f73175e94af52f9f19e61f80dc1f35716b3f48dfa5025c9ebef7382e055830f5bbf15c6f6a95032909c892c0f89c8c15fc3ea40a20ee1a4529b521951df44d9d79d74e0c4c2e0fed849b8785206dbe62bfa2ca21087a912e9b184551659cd8a587e95b04317192596bb0b7fc9f7bbb6ee049c8b02fdd758b4e79882073b71eaab18aa293701c17d55f9ec46c52de1e886b6750fb0fbcd64f4568a210ae451e9:20ea9368a2ccd08bf9cbf48d4a2f7d03f0db08a54b87679cda03e296af9ef378be9b8f04b4065b009da6db016f3df9db64825873e2fb4de30449915cd73c4609746d7abf0bfb2662c25ab5c5e4612c306f16d13e44d0db394a0015676ce609784f0323da1dfa94d2b2f1f6e02444a936d019b143021f73c79df9309e7bdff39daeec4caca00cba4ef31c8310c1a08ef4b36f81c377846b5b90acd411aa671ed7af278a24229b7893c1b415d79888d7637f5cb5c9c6c631ae5ffa29f1340e444096ab533617fdcb80ff81da0a7c6c142ee0fe5ea82f68cc3ea38b56f272b0d80fd5f4f55ca9348c161881435813c3fa9fff66a2ee6d5bd3edba0d2f9aa74b1c44bfd0e64678d3715124963ac575ffb09ee16437da484b3ba58e5aeb8ed8c5c0f47b59908fe580f37ec1de266b295d6be85e62358e9bbdc78964fb837eea29fdb7de86cc56f48bd9a3e6e2be51d8a1dcff3ca4d56ea934c682772bcafb51497be5d0f2a23dd4970c02c44c09ad897b4241acd7d6ab12d8f00c9aadc334b431fec5bb69a285b7550a639ece96952682b7334b68c65152e893b1c8100c694d8c5cfe26ac03c1f3914e65c84f0e777290c76f6acce340bff66da7220f73175e94af52f9f19e61f80dc1f35716b3f48dfa5025c9ebef7382e055830f5bbf15c6f6a95032909c892c0f89c8c15fc3ea40a20ee1a4529b521951df44d9d79d74e0c4c2e0fed849b8785206dbe62bfa2ca21087a912e9b184551659cd8a587e95b04317192596bb0b7fc9f7bbb6ee049c8b02fdd758b4e79882073b71eaab18aa293701c17d55f9ec46c52de1e886b6750fb0fbcd64f4568a210ae451e9: +85e0a80f3b30c20199d9c1ec662e392fdf1546377343f12471db2a0310a705bd540a3a1d83672e495034cff408e1fbe82e538f0917e8a1c7d17aab58e043d3c6:540a3a1d83672e495034cff408e1fbe82e538f0917e8a1c7d17aab58e043d3c6:d2802f1596f8383b64edbdc594060bff0e7013d5b7c85d830fae11aeb34dd594959da624e044474c5409c0059673bdc61a671ef5b0b8a26f30100b3b73968d8e4d83a72f25b513448d2f6b6a4475fdf89e31ca9268a30705af3f649e3fe01dde0cf4b29ec2da5436444af091d62730acd4cab608f0df26f088c6b9b9673794f0747dab2ce190f90592009fdce5464b3661b7e8620bad65509a6c752b727a8dc8d3efa584fde0272c451d65a93bece4f59d87dc6fbeb451401e3e2e003c6aca7b3d3f92719150c6778f015aff2a59bfbf2e91b21b0ad6877536eb54567059f587f54d4e2a6fe1fdcdd6a7fdcb8515575bcc3705d77859352fa0b044166e3c318846a5df33563003cb20bc942d30391093e8d583e8e64dec570ee1c4138762f6483898d32e2032bde9bbe07ec2c3eb47d96876f0fc0f024d753ceb34ff8480b4cf576230bb8263dd80eeac662eba31d8a61f309e175f4c0143e28a852b1c3061ce78efbd16a2873dd28198a46ec0a800b30dc8a93b8dbb81a730de450b864dea7680e509d800e82329c261b07e72aa80ee16ec375ddbbb6fe3d8d47b0e3c5a9f23c4d20b724c1df59835d830dd22d10403d8f15c102c4b3769c41666c3ab8c7e80b940d0bbb58652d10a3ffe8d44df1012a3ddc4e1c518d49019f7c5d3d9f95ed93a319746d1e543ffa69edb49bb3439f8a325ac6a0cb4edd65ba60080a0447c674faa72d8aebdb5d2544f2f2d847c72c2dfa6057a690adc5c441a:185ef2246aba2b1a568032c7df93c667799b8a521a6f97321ead5866b4cb9c65b64a1c40b9b6a910e742dc32a7e66d11ea45dbeaacae9f09511b8101f8af0c0cd2802f1596f8383b64edbdc594060bff0e7013d5b7c85d830fae11aeb34dd594959da624e044474c5409c0059673bdc61a671ef5b0b8a26f30100b3b73968d8e4d83a72f25b513448d2f6b6a4475fdf89e31ca9268a30705af3f649e3fe01dde0cf4b29ec2da5436444af091d62730acd4cab608f0df26f088c6b9b9673794f0747dab2ce190f90592009fdce5464b3661b7e8620bad65509a6c752b727a8dc8d3efa584fde0272c451d65a93bece4f59d87dc6fbeb451401e3e2e003c6aca7b3d3f92719150c6778f015aff2a59bfbf2e91b21b0ad6877536eb54567059f587f54d4e2a6fe1fdcdd6a7fdcb8515575bcc3705d77859352fa0b044166e3c318846a5df33563003cb20bc942d30391093e8d583e8e64dec570ee1c4138762f6483898d32e2032bde9bbe07ec2c3eb47d96876f0fc0f024d753ceb34ff8480b4cf576230bb8263dd80eeac662eba31d8a61f309e175f4c0143e28a852b1c3061ce78efbd16a2873dd28198a46ec0a800b30dc8a93b8dbb81a730de450b864dea7680e509d800e82329c261b07e72aa80ee16ec375ddbbb6fe3d8d47b0e3c5a9f23c4d20b724c1df59835d830dd22d10403d8f15c102c4b3769c41666c3ab8c7e80b940d0bbb58652d10a3ffe8d44df1012a3ddc4e1c518d49019f7c5d3d9f95ed93a319746d1e543ffa69edb49bb3439f8a325ac6a0cb4edd65ba60080a0447c674faa72d8aebdb5d2544f2f2d847c72c2dfa6057a690adc5c441a: +82a2c6493f11ba80e4b8b3b43841be970e2a10a94d2249d8ac6f5414cf5a3cb54c2ee01cdea07db3635f5d4c1082b92f298deb17d0f905df71b66fb2274eae99:4c2ee01cdea07db3635f5d4c1082b92f298deb17d0f905df71b66fb2274eae99:09854d13684950419e0bb16464e09988905c0217183aa1e48adb147bfcc2eb57c2300b0dfc39d4896655a57ae20415408bb5f2c238013955f0a4fc782e0c993fe42cb08cd8cf415ccbd6cf1cee2e8097f04e8f09ae5da5f415b16c2cb30cb2ab6652ba50ebbcae4a59e31fe11e7ef3699ca90aafa586bb242c89cd2e332b2bfa2f8142accaf436f89b6453bb4805a1e7f3ab6270f0daf89389e717d1b70175ec5707c8f512c40ab924c457e9f0914791750dc292bb27d6f63ba8ccf54b90d3eba7f19eb300d9eb8f3b72032ba93037f552b409b580a5f65116faffe0fdfdc6db3881386c3cbc16b67eb25763d7ae3aac0b85aa1e9aa22e4959609d4381e4b6d7159ff3e3b2d37b640f88cfbe4f8a77f8016457228ba6d3af5c4e33125d48bcfcf3678c163b698e52e85617ab1a75ff20c690ab07155ee757598578072d4a09dfc6c6c094ec048567d513ce2b1834e163df1545319d8061e0e57f58ef041b7bffc4966ac1660331b97abbc97be21ae2bc58c6c3274a8adad5fd2c3bc16b92e1f8de877b6a26f0c6ab7162e8aab93af8d85918c13d3e235a273748c62f0d22cb1c93e134a495b1b5ef8f1a1134512d53b7a211263177f7a60bdf474691f224a3b5bac4006db345ca6725f5ee703eca0dea10d712676f63ef3e537e63abd2608cb4fbe200e15f18209153496072908044c95a4e9c5356aae8ed5f0959eac091e227a0b81f5803276b3b3bf4b6865a55fc6782f62ea6d63990f9befe01:68a91d4f8d241c1defbd5ca9e9e1ed8274419506751c967947b10d50118bbfabc765ffd7b31a0167c4fd8b1175332412df19d8aa1a909590861320923dbcb20409854d13684950419e0bb16464e09988905c0217183aa1e48adb147bfcc2eb57c2300b0dfc39d4896655a57ae20415408bb5f2c238013955f0a4fc782e0c993fe42cb08cd8cf415ccbd6cf1cee2e8097f04e8f09ae5da5f415b16c2cb30cb2ab6652ba50ebbcae4a59e31fe11e7ef3699ca90aafa586bb242c89cd2e332b2bfa2f8142accaf436f89b6453bb4805a1e7f3ab6270f0daf89389e717d1b70175ec5707c8f512c40ab924c457e9f0914791750dc292bb27d6f63ba8ccf54b90d3eba7f19eb300d9eb8f3b72032ba93037f552b409b580a5f65116faffe0fdfdc6db3881386c3cbc16b67eb25763d7ae3aac0b85aa1e9aa22e4959609d4381e4b6d7159ff3e3b2d37b640f88cfbe4f8a77f8016457228ba6d3af5c4e33125d48bcfcf3678c163b698e52e85617ab1a75ff20c690ab07155ee757598578072d4a09dfc6c6c094ec048567d513ce2b1834e163df1545319d8061e0e57f58ef041b7bffc4966ac1660331b97abbc97be21ae2bc58c6c3274a8adad5fd2c3bc16b92e1f8de877b6a26f0c6ab7162e8aab93af8d85918c13d3e235a273748c62f0d22cb1c93e134a495b1b5ef8f1a1134512d53b7a211263177f7a60bdf474691f224a3b5bac4006db345ca6725f5ee703eca0dea10d712676f63ef3e537e63abd2608cb4fbe200e15f18209153496072908044c95a4e9c5356aae8ed5f0959eac091e227a0b81f5803276b3b3bf4b6865a55fc6782f62ea6d63990f9befe01: +e55b343a0fa1fb747189cb00dbc3a6aa2dcf5b86e57d7693f30742038976115323a14460ea983cf997c782eb4582ab3c8aa6dde53325b977b78e33d2dc5f27aa:23a14460ea983cf997c782eb4582ab3c8aa6dde53325b977b78e33d2dc5f27aa:36289b5eaff2a85a7c6d575bd15ea594b2fd8510874a469b52109163696d85b68c5b211d2964efdc66e625abe8aafe4cd9220cdb341107ffa8276ed4b370fe376c1482687167dbc8f7b205a3f3301a1664d9072877d9f98b8f69831301df9994717fc88969242391d9b0517d6efb271701eab3f4a9b1204213e8cd13f9d099048b8207562f2e4ebc653cc65e9d5512d65b41022c79b4eb37298769aeaa6efed69e9a8cb445c7012274de62f509f4e4814adcbf4453b4fab85d7c8fd845e00830ef5b7b1e63c67613984caefe915a548e18e505622cb2b39299f427f4d83983ba2aa00d53bee1f59aec8318c5ea345d294252369792762add3e56fcfa6e7797f028c799479045edb2e205eb6dd6ca04eee56f9496d2bf26099357c973835b9936024911e4655d3e22c811c8d4dbd1b04f78973f077523a389b6f28f6f54216142cb93e33d72b4a5052d27e4911e41e6cec7bebe1b0a5113e6b70b479d2abeedf69b7564e5a573b352d16cec890701bb383d3f6656eda0892f8ccc70940f62dbe528a65e31ac538826c138ac66524e331637ba2d37730358e6c732cff8fee940afd22c39ae381e5d8826739b23fdc1b80aea5a62a2cf0ff1525e446cf31046195051d58503eed1befd793eeae1d5d1b62a5c9845157a095cdc08a1d77ba47e84a5a739980f0f5be7aaec9a215b204b4bb7cb1b386ded58d7aaf7285341907c63336ee3e6ef077ad111b974e7504bd989f566fda1b1b59abaa91c78bb40:07266c18650ecf0632e225624ec4c97fc387dc374687a61956dccce72894ee138aabc80cfc90c9eea6dd4c59af4502ee29635a92880786678b14a3931a69f90736289b5eaff2a85a7c6d575bd15ea594b2fd8510874a469b52109163696d85b68c5b211d2964efdc66e625abe8aafe4cd9220cdb341107ffa8276ed4b370fe376c1482687167dbc8f7b205a3f3301a1664d9072877d9f98b8f69831301df9994717fc88969242391d9b0517d6efb271701eab3f4a9b1204213e8cd13f9d099048b8207562f2e4ebc653cc65e9d5512d65b41022c79b4eb37298769aeaa6efed69e9a8cb445c7012274de62f509f4e4814adcbf4453b4fab85d7c8fd845e00830ef5b7b1e63c67613984caefe915a548e18e505622cb2b39299f427f4d83983ba2aa00d53bee1f59aec8318c5ea345d294252369792762add3e56fcfa6e7797f028c799479045edb2e205eb6dd6ca04eee56f9496d2bf26099357c973835b9936024911e4655d3e22c811c8d4dbd1b04f78973f077523a389b6f28f6f54216142cb93e33d72b4a5052d27e4911e41e6cec7bebe1b0a5113e6b70b479d2abeedf69b7564e5a573b352d16cec890701bb383d3f6656eda0892f8ccc70940f62dbe528a65e31ac538826c138ac66524e331637ba2d37730358e6c732cff8fee940afd22c39ae381e5d8826739b23fdc1b80aea5a62a2cf0ff1525e446cf31046195051d58503eed1befd793eeae1d5d1b62a5c9845157a095cdc08a1d77ba47e84a5a739980f0f5be7aaec9a215b204b4bb7cb1b386ded58d7aaf7285341907c63336ee3e6ef077ad111b974e7504bd989f566fda1b1b59abaa91c78bb40: +3973038fa2ef6a278d3c1cff9a225669e465a69d0750503de748c002dbf9278ac75e77c78149d9d2dbc263ddf8ac4d654d1ff455cb1897e1c3ce31b94cfe3210:c75e77c78149d9d2dbc263ddf8ac4d654d1ff455cb1897e1c3ce31b94cfe3210:3392e02f3c84661eaf81a5ff04357f212e92361c5c220739d96b4d3d9c22d18df48be6b55126f581601ffe0da63f38e19cbb12726ca0a6aa325567a003a7849d06783992eb9eb92853297d7228dba980b250bb110f63d0b84670e5ecb319cbfd61278f1f4cabf1fcb3f701f12f6ef8d3cc4282fcbe589eb5659503a2ddd8bba38e5eff092dfaf539fd804f21f73a90adf569a00bf9d25a9ad3a63309cc6093142471a478f0b8992286de023c68efd49987ec270bd946f6db48f684f1c2adeee26d68dce95a55e4cb27bc60523080df6ba2b199996b1f1da6920d1559f79bfde9fa1a02deae1480c76f947f9d213fc43bb2880a1b4d03bb14f5b044a0fd83ce0492f49ca3af25211b86faa5735ad7feaf31a1a7491e708b41829d68e32414f68352b71d1cd23c8e12fb02da711484f6ef97528a00d24fcf91d4e06e9badae9a44dbdb3f778041768d863704d736810400e7f2931efb85c8724a593426aa2af1ec5b664f85c2254896fdcf316db0924e11aae8d683e9a021929d0a9d6fecb4594b1b3fbc16b176d29d1efb1819a4a423fbe0ca0559c57e9e5449f14bce91360dafda6a427ce4a0993dd03082ddee066533f6d3bda5660f42fd7757690d670598ec7096f475a01a519950341a831fc9a281c0947a863f1f6e03bba774de77adc23fbe525cae6ccce47a0ec4979e8bec86f332fc6a5736e3b98fb332e9e8244e68a100455e6499ba8dbae98b92ba3d9c6b4ff980343e4c8ef4d5a4aacf8b1a:fc0c5453839ea99296fffa501d58366628df89f616766942d5040a056056dab18b4405c04abf9059c30868d79c936cccc84c4fbd6fd30b60f8bcbd7a664042023392e02f3c84661eaf81a5ff04357f212e92361c5c220739d96b4d3d9c22d18df48be6b55126f581601ffe0da63f38e19cbb12726ca0a6aa325567a003a7849d06783992eb9eb92853297d7228dba980b250bb110f63d0b84670e5ecb319cbfd61278f1f4cabf1fcb3f701f12f6ef8d3cc4282fcbe589eb5659503a2ddd8bba38e5eff092dfaf539fd804f21f73a90adf569a00bf9d25a9ad3a63309cc6093142471a478f0b8992286de023c68efd49987ec270bd946f6db48f684f1c2adeee26d68dce95a55e4cb27bc60523080df6ba2b199996b1f1da6920d1559f79bfde9fa1a02deae1480c76f947f9d213fc43bb2880a1b4d03bb14f5b044a0fd83ce0492f49ca3af25211b86faa5735ad7feaf31a1a7491e708b41829d68e32414f68352b71d1cd23c8e12fb02da711484f6ef97528a00d24fcf91d4e06e9badae9a44dbdb3f778041768d863704d736810400e7f2931efb85c8724a593426aa2af1ec5b664f85c2254896fdcf316db0924e11aae8d683e9a021929d0a9d6fecb4594b1b3fbc16b176d29d1efb1819a4a423fbe0ca0559c57e9e5449f14bce91360dafda6a427ce4a0993dd03082ddee066533f6d3bda5660f42fd7757690d670598ec7096f475a01a519950341a831fc9a281c0947a863f1f6e03bba774de77adc23fbe525cae6ccce47a0ec4979e8bec86f332fc6a5736e3b98fb332e9e8244e68a100455e6499ba8dbae98b92ba3d9c6b4ff980343e4c8ef4d5a4aacf8b1a: +c71cc10ad2d443e025ad0625686b123503e590193a2bc8cc57a7b9b4158de6cbfc06acaab53ad08e9762dd11cd2122b31599bd2598ce6f248795e732219c2fc7:fc06acaab53ad08e9762dd11cd2122b31599bd2598ce6f248795e732219c2fc7:2e0846536dc6cce19ccf82dc2d0cd21bd4e1ca7bc317067af8d90ee4818c8518bc3ef960ce112a41d2b9979a282ae13d706a005e0034f06b39ff4b0a5afaed70b561bcceb1bbd2ec19f97448eaed4be620e36a962d878c6f80172b9fad43eed07ff93db9b9ca2262d5a3c229c54e30a45e73660892f048e363f37144ed1921f72992b4d01529870cfe373b7e7cbedaf969269fb70aa783d1e74417c7bae0fe03d951fdb8c71c62e9be7fdd5d233e39f46fed057e49b6f34068459148da3d424161ad2c869508602e9c0bb30bfb88acd5f4dfdffd473503cdfedabc4442b743be075e7c6f610e64ffc2e53187745cd719658fc6e62a5be518437c5bd6a4feba94ae3f44f2f29308e831feefed676909ce5e80c84cbdcac47e47d27c9712a01f6bc5daedc02e6414407e911c0a5a53e5328a5a5fd9f040aa7fb70b79b31cd1b6fd9bd5029040bd22ae222fd2f6870d07f435322639cf3193ca5709b882b07a58f952a9963e568f8c5a584a6b9e275c5c07957a4d2cdaa9f1eb444ed1224bac6563b2f9273e80301d44d50ae383b597213b00da5bf27e5d1fe240cc3bb65aa5030d651b6b5b31761d53ce0c6d74a15dad5479f31c915ccf446659853b89a51a28ee8976853553fd2e02fe7243538d00b4ed07d8b8a80b5c165cd46341ffd8163c555702663a4e6ab2952b7e7443d0f6b123b6946721aa63e87b1155eca8a6a1bc9fd25c6762e52742c86bca1ba9d8370415244f0edfdbe0932b5ca0611509c9:2eb33bc2d5deb7f3a2dcc377b0c6a862134bf3191ec40fc128ac28abf2316ef1401649b8f4cfa1a936de79b532dc043b6d36024b4c37bba29290ac9f449ba60d2e0846536dc6cce19ccf82dc2d0cd21bd4e1ca7bc317067af8d90ee4818c8518bc3ef960ce112a41d2b9979a282ae13d706a005e0034f06b39ff4b0a5afaed70b561bcceb1bbd2ec19f97448eaed4be620e36a962d878c6f80172b9fad43eed07ff93db9b9ca2262d5a3c229c54e30a45e73660892f048e363f37144ed1921f72992b4d01529870cfe373b7e7cbedaf969269fb70aa783d1e74417c7bae0fe03d951fdb8c71c62e9be7fdd5d233e39f46fed057e49b6f34068459148da3d424161ad2c869508602e9c0bb30bfb88acd5f4dfdffd473503cdfedabc4442b743be075e7c6f610e64ffc2e53187745cd719658fc6e62a5be518437c5bd6a4feba94ae3f44f2f29308e831feefed676909ce5e80c84cbdcac47e47d27c9712a01f6bc5daedc02e6414407e911c0a5a53e5328a5a5fd9f040aa7fb70b79b31cd1b6fd9bd5029040bd22ae222fd2f6870d07f435322639cf3193ca5709b882b07a58f952a9963e568f8c5a584a6b9e275c5c07957a4d2cdaa9f1eb444ed1224bac6563b2f9273e80301d44d50ae383b597213b00da5bf27e5d1fe240cc3bb65aa5030d651b6b5b31761d53ce0c6d74a15dad5479f31c915ccf446659853b89a51a28ee8976853553fd2e02fe7243538d00b4ed07d8b8a80b5c165cd46341ffd8163c555702663a4e6ab2952b7e7443d0f6b123b6946721aa63e87b1155eca8a6a1bc9fd25c6762e52742c86bca1ba9d8370415244f0edfdbe0932b5ca0611509c9: +0a4f5e1670f1e24bfa37b73c994330b36e7daaf930161b78a4a84866ff25e3d59dcbba903981594c7b677ea8002001d664cff7ce8e5cfae58840cf74aff0d3a9:9dcbba903981594c7b677ea8002001d664cff7ce8e5cfae58840cf74aff0d3a9:f4b05b3efdcb1d5c07da950c46565528440bb48835ee4c13f43d7a1618de119ebbb259ea7480a5048174faecc1055b32dc01ac7156344321e8eba698f302ee1643b5f04b8e7ecca63b91561ce3514abe7851b6fb17fc943bdc94da308c8e4769fec20fadf4fa8e7f62b6ffb5f170d644ed29355ebd22cb3aa1486b1e367c729dd3f79bcd40ffd08af28cebc8d776e1a483e911d79bc613e09cc621cadeb034dd6f72374771985127f7a3a1aa786a523ae6e34ee433dc30c375987cff50bdcbc997fcd51c94567a67aefb6ef5edf9bdd65964d464be9ebdfb88c0e231b07ff6405c00f82531e961bfc5ead266bcc08718878cafb1d37536f183e48bf38d3f6be900252d1fb419e6a2ac5896039f63c31401fff932ce9814b085ab20416972a2b351c815a62de509674628b0d3566fc9c2e0a9237b93f9bbb2deedf02bff83bf6d868b6399326d4809d0419f31b2f3a481285b94078b47061ce91dad583dd5b13bd010fb30f2495bb70420183a930159e4db193df6acd124423e039a67f15688aec50c5927fb271822aaa66f294bc805d3bc7c8341878a541009f30da99fcc0085079ce7fc55e0011685562abdb3a9471ffde6176300ef5b31e0df609a54a1ee6624070da99c8776891fdf6aa78b4d55b1f5dadfc061add5af00fd3adedb448c559bfff204068043a5d1d6214748628c3ebc5f0224326ca18ef048425da9300133fb695d4f263165ac22f3619d405af271a71a9afb198bf631241d3459b95398:dcf353b2b99a4ef45f3fdf6528632e8abdc433342476a8c2b37900404a4e333d387814235757ef7ad03858a0f35d4615e8aba484fd64f1112ec1b1aed2cb640ef4b05b3efdcb1d5c07da950c46565528440bb48835ee4c13f43d7a1618de119ebbb259ea7480a5048174faecc1055b32dc01ac7156344321e8eba698f302ee1643b5f04b8e7ecca63b91561ce3514abe7851b6fb17fc943bdc94da308c8e4769fec20fadf4fa8e7f62b6ffb5f170d644ed29355ebd22cb3aa1486b1e367c729dd3f79bcd40ffd08af28cebc8d776e1a483e911d79bc613e09cc621cadeb034dd6f72374771985127f7a3a1aa786a523ae6e34ee433dc30c375987cff50bdcbc997fcd51c94567a67aefb6ef5edf9bdd65964d464be9ebdfb88c0e231b07ff6405c00f82531e961bfc5ead266bcc08718878cafb1d37536f183e48bf38d3f6be900252d1fb419e6a2ac5896039f63c31401fff932ce9814b085ab20416972a2b351c815a62de509674628b0d3566fc9c2e0a9237b93f9bbb2deedf02bff83bf6d868b6399326d4809d0419f31b2f3a481285b94078b47061ce91dad583dd5b13bd010fb30f2495bb70420183a930159e4db193df6acd124423e039a67f15688aec50c5927fb271822aaa66f294bc805d3bc7c8341878a541009f30da99fcc0085079ce7fc55e0011685562abdb3a9471ffde6176300ef5b31e0df609a54a1ee6624070da99c8776891fdf6aa78b4d55b1f5dadfc061add5af00fd3adedb448c559bfff204068043a5d1d6214748628c3ebc5f0224326ca18ef048425da9300133fb695d4f263165ac22f3619d405af271a71a9afb198bf631241d3459b95398: +b855c81805c7087410e69f96b0240271dc76c1e4ade38c6a9278e3c94fbea2566adb025a40260f569884b8cab3752b4f255c373e2b424b6287ebb510fa06fff0:6adb025a40260f569884b8cab3752b4f255c373e2b424b6287ebb510fa06fff0:85a9bdb70a6c752897e43a91106ee9a99c2ca94ff7b4461a44a39174c17ecd99df46eecd81c3f52513dc9d547dad3721c6d5ee1f8fac0ba5afb3687044739ed535b844008704c09fe1e5d785d4c9c3d0b05889b9c20fc3fd68df12dbeb2c34f6f7ec1c6fb7fa811ff846b5a61fa5fe55379ee63abcd373fed00254ebd06bc8b22f7fbf2f727a5fad88514159e26d78dfdb0957f6efaf51a8e80b585e838b9621d051074a4f5867b4ae2f2ff6d62b85bccec0b4aaa4791637388c0901fd49dcccce7204859f81eefc639fed92280456e69a1509b4b1bd7624447d862c45a0c8b0c5bb2c4ca512cbc037f51b780982b183a5cafa15297585c947a25be8c2240ebfb6868ece5ea2aab2c239c83754c7d594b3725aceef344ba7e6aef49f7f313b0ae82ccacad387a6e9337f05f8c799efe7829b27b4d5b201fd5ae5834351690759f3ea175fd4741be228d807fb54df4a741038faee47edf1f561652598601f27155fc50d9d5011433711c106d4b60785a5cc93b3fdd1dad70c0c8eaa33f1512e35a541745e376c15167fa8f6b3b2c4c3a366fc41497d297357816ae795a804c980e7cbfb0c74d8835d929ae3bb52bab12964566d746bd2c1d132b6233fa34f75e268edee775eb3ce132e6beb2e8d71f0c8762991cde4e26f71439dfa83978f995603861bc0b1d9060bbccaccf86f8745ad96994d5d007d52e83aa5e69412964bdbfbe4780aaa8de41be1298abbe9894c0d57e97fcacc2f9bbd6315d3fcd0eaf82a:3caa813273e753542ffbfeb21bc3e2cf8ca7d920faac7c49dc2aa9911768c7ad43b38b0236db27f3eeae0b1206001e665a607078c522ed7a9dc468853463590085a9bdb70a6c752897e43a91106ee9a99c2ca94ff7b4461a44a39174c17ecd99df46eecd81c3f52513dc9d547dad3721c6d5ee1f8fac0ba5afb3687044739ed535b844008704c09fe1e5d785d4c9c3d0b05889b9c20fc3fd68df12dbeb2c34f6f7ec1c6fb7fa811ff846b5a61fa5fe55379ee63abcd373fed00254ebd06bc8b22f7fbf2f727a5fad88514159e26d78dfdb0957f6efaf51a8e80b585e838b9621d051074a4f5867b4ae2f2ff6d62b85bccec0b4aaa4791637388c0901fd49dcccce7204859f81eefc639fed92280456e69a1509b4b1bd7624447d862c45a0c8b0c5bb2c4ca512cbc037f51b780982b183a5cafa15297585c947a25be8c2240ebfb6868ece5ea2aab2c239c83754c7d594b3725aceef344ba7e6aef49f7f313b0ae82ccacad387a6e9337f05f8c799efe7829b27b4d5b201fd5ae5834351690759f3ea175fd4741be228d807fb54df4a741038faee47edf1f561652598601f27155fc50d9d5011433711c106d4b60785a5cc93b3fdd1dad70c0c8eaa33f1512e35a541745e376c15167fa8f6b3b2c4c3a366fc41497d297357816ae795a804c980e7cbfb0c74d8835d929ae3bb52bab12964566d746bd2c1d132b6233fa34f75e268edee775eb3ce132e6beb2e8d71f0c8762991cde4e26f71439dfa83978f995603861bc0b1d9060bbccaccf86f8745ad96994d5d007d52e83aa5e69412964bdbfbe4780aaa8de41be1298abbe9894c0d57e97fcacc2f9bbd6315d3fcd0eaf82a: +95b9c8a6ef80ebd5cbd47a04ca54387373df4d67a2b475597765ac89fcf93e93f2c947b18adc3ea6a23f7abca364b9853ae85a2b0c8c26f0d3173c2732c3c7ff:f2c947b18adc3ea6a23f7abca364b9853ae85a2b0c8c26f0d3173c2732c3c7ff:7855bc392630ccf531d3061606ddfc81a0fd9294c54791b5f9559b6827254aa1f25c540b7d7df3ec9cdf14256629dbcf9b725feb3412ebf35f0ef9379e4131cc77e0f0fb6f7459a738361a99ae4ccb2b60a99fe92bd6c3a53d6f454ee9005bcec5aedcfa82347392efcf1175e578396a8d800daba0f4c2cf4d4913b0528620e3baa0f6d86e0628e47c0ca26df3b0c788c4e16557f7fc28df820c12fbb6ffbfecb9829ddb65ef8d63e90d68fc7194b5b885913f08edee84567647ffa3f0d0d325d082600ce71a2345c77d65bd96252003e5c125a718a07370c31b5708075cf1837c6925635cc68dd1b751e40ab608b0d9d8852c18d3069219ef807b76d288f92c29a93e3d75b5b2e53681671d3ae0145ac03ccad3162e44703b0401d3eb167cd8ddc1e1a5a326b728b1e0c00a94d86de61352a661e40897175d28d341e4d1d9962e35f4de18a54017611ad05359ce08b97bfedbfbe3992ed58ed40f517aab01c0fefe8b63643da1a454152730bf99af8740adf98a77b8d73adb08e609e00ce9b1ccdfef3e9a9b05aa56e0bc79b6bbba80dd8e461af7cb202892d89b2d05a4458ab3fa54b474b8f8f581795d6c2739e59d0fe062400bae2d2d534b340bb8e2615777a9a5615bb2cf437ba525e00e7038f22a57882ac520b333e75c3c92a8b9f0e37f671c94b15dd8182a08d7c143e94e9262b3cc5544c294f5f335c2b28ac119fea00f9634db063993988b5f150579c7cc25b6a1fb0dde94804fa6ef66ff79fb9107:2c8bf543e2a3e00415ee4f107b2f5a6687176f5d521117759ceb561751bcc77d9b08a6a631f6447cd901de96699aebb168bf97500dc54a0543ef14e4b5a081067855bc392630ccf531d3061606ddfc81a0fd9294c54791b5f9559b6827254aa1f25c540b7d7df3ec9cdf14256629dbcf9b725feb3412ebf35f0ef9379e4131cc77e0f0fb6f7459a738361a99ae4ccb2b60a99fe92bd6c3a53d6f454ee9005bcec5aedcfa82347392efcf1175e578396a8d800daba0f4c2cf4d4913b0528620e3baa0f6d86e0628e47c0ca26df3b0c788c4e16557f7fc28df820c12fbb6ffbfecb9829ddb65ef8d63e90d68fc7194b5b885913f08edee84567647ffa3f0d0d325d082600ce71a2345c77d65bd96252003e5c125a718a07370c31b5708075cf1837c6925635cc68dd1b751e40ab608b0d9d8852c18d3069219ef807b76d288f92c29a93e3d75b5b2e53681671d3ae0145ac03ccad3162e44703b0401d3eb167cd8ddc1e1a5a326b728b1e0c00a94d86de61352a661e40897175d28d341e4d1d9962e35f4de18a54017611ad05359ce08b97bfedbfbe3992ed58ed40f517aab01c0fefe8b63643da1a454152730bf99af8740adf98a77b8d73adb08e609e00ce9b1ccdfef3e9a9b05aa56e0bc79b6bbba80dd8e461af7cb202892d89b2d05a4458ab3fa54b474b8f8f581795d6c2739e59d0fe062400bae2d2d534b340bb8e2615777a9a5615bb2cf437ba525e00e7038f22a57882ac520b333e75c3c92a8b9f0e37f671c94b15dd8182a08d7c143e94e9262b3cc5544c294f5f335c2b28ac119fea00f9634db063993988b5f150579c7cc25b6a1fb0dde94804fa6ef66ff79fb9107: +b786ccfb586d43b8c46bb97b96c918731bc2cc119277f123671e30148158d2ed90c7004600f3dce409fdeadc8ed018f9ea263f75160a74ab54f4c2399a90ca78:90c7004600f3dce409fdeadc8ed018f9ea263f75160a74ab54f4c2399a90ca78:babf48bd55ea91bd0c93b970241b529d9db43d4927fea5f1a1f7082dd6cb50a52b094b3129fcd903a44fec8bfdb5c86c002a2a452887ca25a60eceb5e1f9f5c93dc59423c7afe747c6bf407cacadeccf5d787970cb0617bb3cfe7fd17563d3a0dc91631f71b84be24ae800113750f031d01fd05364b4f27f86f8dc3ad7407e1ae9e768154e3dde58e867129e2474547b408217964844858d056b31c374991b7f161f52f088b806e0f313d68a15c5401ed55b2b77deea586cb054dcd71af2ab6ab11e84b30c539345de3eb43fb7b3a3b48987c3bfa70655d599f2e31d12ad23cc96e86d380bfda812feff3dd3024292916907022891e119bfc3ed9c25546cd19fc992d8a61e6059ca3ce7802af1118756620b87a7242bd83897c94dd5a36ed40fc0f34c2c93110b37d17dd96a22062590bcdb546742ef7218adccc5ad28f4fce6ecf705835f4113d82ea533903aec8c3820fe4b4715f37e20cebc1e71519aa0b240b4840aa4fdcfb52467fedd8f4d1f9bc33ee114f3ef85f5fdb09ca884af388ad3adf84c793f386efe6ff8a46ed81e5d45a37c25cd80f2d7363f43ae45e3772c0df89f11447939806c096ef933a13944f0890d887c2e5bbb6b12ea950b09b8fe425289377352f35f84cc4dcd4d7a449489fa9251c03113489225809cdf3cb63475f10d341709371c6fd4bb7a949483d1bc2b31ddf4d963a07de7ea5c3fee9a0e33f0769f2faa40612a546974bde0b7339179e4124a447bd42879ccda5c8ad1819c53:52ba9658a1a0b3e98ed5209e393e420066a37d3714daa73d5c671d33075a5f5727fe4e081ee0fa3c2133dc953a2da620291371f00ccb57d8792eb596a2ff8101babf48bd55ea91bd0c93b970241b529d9db43d4927fea5f1a1f7082dd6cb50a52b094b3129fcd903a44fec8bfdb5c86c002a2a452887ca25a60eceb5e1f9f5c93dc59423c7afe747c6bf407cacadeccf5d787970cb0617bb3cfe7fd17563d3a0dc91631f71b84be24ae800113750f031d01fd05364b4f27f86f8dc3ad7407e1ae9e768154e3dde58e867129e2474547b408217964844858d056b31c374991b7f161f52f088b806e0f313d68a15c5401ed55b2b77deea586cb054dcd71af2ab6ab11e84b30c539345de3eb43fb7b3a3b48987c3bfa70655d599f2e31d12ad23cc96e86d380bfda812feff3dd3024292916907022891e119bfc3ed9c25546cd19fc992d8a61e6059ca3ce7802af1118756620b87a7242bd83897c94dd5a36ed40fc0f34c2c93110b37d17dd96a22062590bcdb546742ef7218adccc5ad28f4fce6ecf705835f4113d82ea533903aec8c3820fe4b4715f37e20cebc1e71519aa0b240b4840aa4fdcfb52467fedd8f4d1f9bc33ee114f3ef85f5fdb09ca884af388ad3adf84c793f386efe6ff8a46ed81e5d45a37c25cd80f2d7363f43ae45e3772c0df89f11447939806c096ef933a13944f0890d887c2e5bbb6b12ea950b09b8fe425289377352f35f84cc4dcd4d7a449489fa9251c03113489225809cdf3cb63475f10d341709371c6fd4bb7a949483d1bc2b31ddf4d963a07de7ea5c3fee9a0e33f0769f2faa40612a546974bde0b7339179e4124a447bd42879ccda5c8ad1819c53: +dd1a9774f7584d8589b19f92ab6939ac485602fe1644cee2f6f3cd60fbd584004bea7d0b0f4bd590f9e3579f0c5fa4cef4d60a49d2c437a0aaead9d43a73d4a3:4bea7d0b0f4bd590f9e3579f0c5fa4cef4d60a49d2c437a0aaead9d43a73d4a3:e5dc3ed26c1f693cf852465a05e3048b505db5116d9e31592205a9c3d4720bc10b6c20639a0ee2f0e147225b5b19ea511cfba0c21aac10715a2f232f10c2c8aad41112b6b012e75a4155f8c6926253ca2b4ddb7bfe7f86e90a53dbc0cba89e485ceca8fd26e50c7f282a253573cb0a8fa88cc44623e82e8fa2edb6cbc7538ac92c11e4c5b1ea5f68966d15d93c34f396d27572f864382ab76a7be65a557b139766368a207d98bc0c20926370dea27048160363ed85f4099e7cd66d12d0988cfc9e2f16aa565f8f33b39e978c0587371f92db5056317564411bd8a3b6fea09d3487aaf734034918ffed1c9fba7bdec6fe68876fc7360cc5629b92104027fe5759c5ab365354751e7969116c3b9a21b152330a96a9381af730d17822d78ad6ea860006915b5cab447a759372e05d495ebb328e75d248daa02f5d2eb978d2710cf1c5fb824876770e32ca6de2c730564892415bcb53e5981d707add961c5f37fdafa1399af8aea960458d2ca310553f7c9866ccbe8e9d88e08a446872ea66fc308c824514b7dace0334db735e6f14c85b5e619a5d605648a881e876c78dbe0657233d4f7f3bfddf63b445311d6abc476347ec4fb43c8946f9d17c369381d1c564ffcfe2dc7b4726fd57387f0b44db8ef95a0b4e32a7bedf319e53a9e7126c2811f9829d1f4ae9abd9d5f42efef2075f47051c63a4f8202040ec4723686382c6033127c1fbfff4bc82373508752d431dc473f52ddeab0342dc4f5447f8f25738ef65d78556:1959bde0a697a63993ec47d158223739fe65871fa05870d7de0d38086591202a51b174d1c6182808c6ce62631d81dba34ebed4af2f29b06c00a57a3cb6663606e5dc3ed26c1f693cf852465a05e3048b505db5116d9e31592205a9c3d4720bc10b6c20639a0ee2f0e147225b5b19ea511cfba0c21aac10715a2f232f10c2c8aad41112b6b012e75a4155f8c6926253ca2b4ddb7bfe7f86e90a53dbc0cba89e485ceca8fd26e50c7f282a253573cb0a8fa88cc44623e82e8fa2edb6cbc7538ac92c11e4c5b1ea5f68966d15d93c34f396d27572f864382ab76a7be65a557b139766368a207d98bc0c20926370dea27048160363ed85f4099e7cd66d12d0988cfc9e2f16aa565f8f33b39e978c0587371f92db5056317564411bd8a3b6fea09d3487aaf734034918ffed1c9fba7bdec6fe68876fc7360cc5629b92104027fe5759c5ab365354751e7969116c3b9a21b152330a96a9381af730d17822d78ad6ea860006915b5cab447a759372e05d495ebb328e75d248daa02f5d2eb978d2710cf1c5fb824876770e32ca6de2c730564892415bcb53e5981d707add961c5f37fdafa1399af8aea960458d2ca310553f7c9866ccbe8e9d88e08a446872ea66fc308c824514b7dace0334db735e6f14c85b5e619a5d605648a881e876c78dbe0657233d4f7f3bfddf63b445311d6abc476347ec4fb43c8946f9d17c369381d1c564ffcfe2dc7b4726fd57387f0b44db8ef95a0b4e32a7bedf319e53a9e7126c2811f9829d1f4ae9abd9d5f42efef2075f47051c63a4f8202040ec4723686382c6033127c1fbfff4bc82373508752d431dc473f52ddeab0342dc4f5447f8f25738ef65d78556: +66f5ea8cdb95ee1a75e32467d7c83c59447742c85ddd499c43c08673e149053aa8ad04b9c144b97fe867374d4fe57d7ec0c249183e43bdfb5d52644e7fbe1df3:a8ad04b9c144b97fe867374d4fe57d7ec0c249183e43bdfb5d52644e7fbe1df3:c0d01dceb0a2d17191101879abb093fb077571b521be7b93a117c696c0872f70ea1139ab628329ee5655fc0aa77e8111d2fc884748c1f267b9eb09dc26f57fc402d61ba36f63f4d589aae63c76eeee15bf0f9e2dcde4e4e3e78fc6c29e3a93f3ff0e9a6e0b356645953890debf62dbeaf4905178d4f0a5a592c19294eeba7c21cf8f1bb3f4512187376de72f1136a48ac2dfaf32d0f37de064592592b6e1bc0c512cf4d2d85d16797853a80933b09c2f7bfb9e54a69e51a8e423a91c3e5fdeb4790533e87a4b1c0e0e23a9db9573ac17ab6ec7014d8b7c4486e15725f8d264eea3050e835ae0ac449db334502a6d97358fa859106ad0f6f4295f2344920adf9355a6949d8d145c25628a46a104ca099bd9dde941119c83820cdc2cb2d09722694901043c37cf0ae879be2030d0373158b9c4b0718298be45f630f6fcdc190f7b2926d87655a18bb797ac50757fcd3655c9e41d5163293d9a13d984f591f75b7e4e5cadb64c4c9fdfef76cab69381d0f60b483f804bb3b33364df8cffacb3c9b13ff4c8d8d4ea40766a7d42d8256c6b1c11c191daba1b8ef21593e47b18858ec19d817358678d8548ff1535d5fcf4414b6a11d34a3742f8d7149fa681383a9408887f1c0a98ed521e72793277824d6f746d49b63d444e312e6d9b986611258196a5b012b88faa29f9a6c67ed25df87b2dbf0dbd2dc3080c5b8d15a37d34729098ed0de92d75807429b2cae5d7283c4e5c9bd196d1ad436c7c34f3c9466e5cb3196b443f4b:ec5c7e8392fa8b61bc829681866e45ac8be4b5b7b6a822c1bcd0f2cc2c8c44c33cf83fa42d43a2f1884141b4a59aaff47f9be07e632e2018759324eac9d14900c0d01dceb0a2d17191101879abb093fb077571b521be7b93a117c696c0872f70ea1139ab628329ee5655fc0aa77e8111d2fc884748c1f267b9eb09dc26f57fc402d61ba36f63f4d589aae63c76eeee15bf0f9e2dcde4e4e3e78fc6c29e3a93f3ff0e9a6e0b356645953890debf62dbeaf4905178d4f0a5a592c19294eeba7c21cf8f1bb3f4512187376de72f1136a48ac2dfaf32d0f37de064592592b6e1bc0c512cf4d2d85d16797853a80933b09c2f7bfb9e54a69e51a8e423a91c3e5fdeb4790533e87a4b1c0e0e23a9db9573ac17ab6ec7014d8b7c4486e15725f8d264eea3050e835ae0ac449db334502a6d97358fa859106ad0f6f4295f2344920adf9355a6949d8d145c25628a46a104ca099bd9dde941119c83820cdc2cb2d09722694901043c37cf0ae879be2030d0373158b9c4b0718298be45f630f6fcdc190f7b2926d87655a18bb797ac50757fcd3655c9e41d5163293d9a13d984f591f75b7e4e5cadb64c4c9fdfef76cab69381d0f60b483f804bb3b33364df8cffacb3c9b13ff4c8d8d4ea40766a7d42d8256c6b1c11c191daba1b8ef21593e47b18858ec19d817358678d8548ff1535d5fcf4414b6a11d34a3742f8d7149fa681383a9408887f1c0a98ed521e72793277824d6f746d49b63d444e312e6d9b986611258196a5b012b88faa29f9a6c67ed25df87b2dbf0dbd2dc3080c5b8d15a37d34729098ed0de92d75807429b2cae5d7283c4e5c9bd196d1ad436c7c34f3c9466e5cb3196b443f4b: +ed2558e5c56784bcfb4f4ddea3c0dfbef8d96ff1cabf158ec4abe60aff66999e1edc991012ac6f888fa7e6045777e9ba1d4c03c40292d2da6b722b4ad0a3ed74:1edc991012ac6f888fa7e6045777e9ba1d4c03c40292d2da6b722b4ad0a3ed74:2c6433e9bfbf4cfd4e071f15ce6b129d780a4b3de014fac034e0d44ef772e2c8b0d6a3481d7b3ddeb237632673553313deac1efafe3702a7a4411e12bd341e8d8e96c59c5e30c36807a8385a538e9b66907d6a528400bd9f95eedc5216b28fd7437d8f4a029fdbdc7c938e4eb9812fec05ea693229629ace6acc7af6ba4c238e7722f312f7896b004922f7067ede106f8e70154d783fb41291f3c7e2e4826045b5741bcb4a8838f87a32e0049704e9b53234c224ff898a756e529134c1a9bf50fd029819b2238b60b2aec1128f34d21f9d66983bed398659d808b67a2e501b5a1f25f71f0f0c1eb2fea0ab42d82ff3bc9358bb20c27520c144cf2116f4a49cbc61994d2d710546694c4f602dc406e0b0c27e5f5e64667e95c2ec9df2d6529cf53622ea10b956b345ec55b6c39a1e6ed88ae66e5b457179425d1a849037b07c46cf5f363301095837ce811bff4960bf9cbd15201c1b6740bd70102140744c3327aca9d6d6d154936798ac381fa639db436ee8165667d538a6c74a233c124bf604fdad51984c4170b8200d2df73c29bb1e376affc314dde3e86af9d2c2e6c3a6524d321bce93e21fc965564faf77d0cd1accb4d7629485f564c79f4d8a2fdefb465454028c6dd1428042805370743363bb18476a3f2320db2589c72133cf5e29dafb7d07aa69a9b581bab5a83f403eef917afa14b764c39a13c0c5ea7019d2fdfbd7f3f7d40eb63b2a084da921895fe48f4fd594017f82569b467ab901169eb5da9c40171d5f:ab9e01166524fd288e5c689e56d730d4983000551030493334a3984e2223dc9f7a5b910c61760c6157990a4c335e348e3a7bc8223e09c10c5e520c8d61aff5002c6433e9bfbf4cfd4e071f15ce6b129d780a4b3de014fac034e0d44ef772e2c8b0d6a3481d7b3ddeb237632673553313deac1efafe3702a7a4411e12bd341e8d8e96c59c5e30c36807a8385a538e9b66907d6a528400bd9f95eedc5216b28fd7437d8f4a029fdbdc7c938e4eb9812fec05ea693229629ace6acc7af6ba4c238e7722f312f7896b004922f7067ede106f8e70154d783fb41291f3c7e2e4826045b5741bcb4a8838f87a32e0049704e9b53234c224ff898a756e529134c1a9bf50fd029819b2238b60b2aec1128f34d21f9d66983bed398659d808b67a2e501b5a1f25f71f0f0c1eb2fea0ab42d82ff3bc9358bb20c27520c144cf2116f4a49cbc61994d2d710546694c4f602dc406e0b0c27e5f5e64667e95c2ec9df2d6529cf53622ea10b956b345ec55b6c39a1e6ed88ae66e5b457179425d1a849037b07c46cf5f363301095837ce811bff4960bf9cbd15201c1b6740bd70102140744c3327aca9d6d6d154936798ac381fa639db436ee8165667d538a6c74a233c124bf604fdad51984c4170b8200d2df73c29bb1e376affc314dde3e86af9d2c2e6c3a6524d321bce93e21fc965564faf77d0cd1accb4d7629485f564c79f4d8a2fdefb465454028c6dd1428042805370743363bb18476a3f2320db2589c72133cf5e29dafb7d07aa69a9b581bab5a83f403eef917afa14b764c39a13c0c5ea7019d2fdfbd7f3f7d40eb63b2a084da921895fe48f4fd594017f82569b467ab901169eb5da9c40171d5f: +b72798b811e2338431256d2480fe7a3663acecbbe6e6c1b9191e9d9a22447940ce491daad296b55727b09513df02ba5928a371737cd35841e5f735acab7c5df8:ce491daad296b55727b09513df02ba5928a371737cd35841e5f735acab7c5df8:a5d46298b0790610aedc0970fea2a7075081847266f22f12478b93d7e674c6c517f3c14ed061269d170ac31e2a64f9754a565bac1dd9757322c11132e7bbee5f32818e0e3063ab64e552d09b0fd1757639b9b9d1c770016b677465872b669dd48be038665751674dd2f40a966a26748fd3e5dbfd92265eb936f55b094286c010629904347cb4c526e377470aa96e8169a6f211633807a50030e7ff68e38911b3555e728ed8590b2dc45fea69945cc0c9a3d3e6c954b3e80106a5c91d3d22e89e8c0e1de902058e9cd0f8ce806eac4f893ee0429900fb5487b8fd36dbdcb34f2d54fc6cc74a923951b863da70f1b692bf0438484366cd85eeb880b279f8fca9d3242c558330f1ca57c6a58608cdbc0773e16082bca964ddc40347da8a36b2a9328c2f46609e092fd64b4134eee1d099813e1246489e8ee5b19b3d3b891c28f30b38b6a28ec1d3e9b005dec9c63f8b9813bc1de4aaf995f1779dded15c7a430d70ca46e7cafd4e9a543804446ab0807d64f255e201ef428a474dae8a0a75021b62ad3988ffb81cd8221b243085a0ad046fdc16c67f17b9f81820095953a5b98acbdf93ebcf80bc9c99af5fbffacb61a9251c5aafdb22b1129bfc60c98e0f175263bdf93dc9a08b8efc2e8cdaf0f83d6c49ec901645eac5a4ff63385a6f1af2071897662a372219c9301f545a2ebb8f5917db7f29ca13fc861af38d90c35c03ac9184c122e57b057cde426fd76dca79e25e64dbb41c8414a0450da4905b902ae98d2da4ba792801:dcfc6fd47799fec772c2099b3c6437246c3ad07229fc740e05311a206b18b02ecdb026c926f49c6552e347fd35dfde06cb639a797c50612f98e2478a92aaf609a5d46298b0790610aedc0970fea2a7075081847266f22f12478b93d7e674c6c517f3c14ed061269d170ac31e2a64f9754a565bac1dd9757322c11132e7bbee5f32818e0e3063ab64e552d09b0fd1757639b9b9d1c770016b677465872b669dd48be038665751674dd2f40a966a26748fd3e5dbfd92265eb936f55b094286c010629904347cb4c526e377470aa96e8169a6f211633807a50030e7ff68e38911b3555e728ed8590b2dc45fea69945cc0c9a3d3e6c954b3e80106a5c91d3d22e89e8c0e1de902058e9cd0f8ce806eac4f893ee0429900fb5487b8fd36dbdcb34f2d54fc6cc74a923951b863da70f1b692bf0438484366cd85eeb880b279f8fca9d3242c558330f1ca57c6a58608cdbc0773e16082bca964ddc40347da8a36b2a9328c2f46609e092fd64b4134eee1d099813e1246489e8ee5b19b3d3b891c28f30b38b6a28ec1d3e9b005dec9c63f8b9813bc1de4aaf995f1779dded15c7a430d70ca46e7cafd4e9a543804446ab0807d64f255e201ef428a474dae8a0a75021b62ad3988ffb81cd8221b243085a0ad046fdc16c67f17b9f81820095953a5b98acbdf93ebcf80bc9c99af5fbffacb61a9251c5aafdb22b1129bfc60c98e0f175263bdf93dc9a08b8efc2e8cdaf0f83d6c49ec901645eac5a4ff63385a6f1af2071897662a372219c9301f545a2ebb8f5917db7f29ca13fc861af38d90c35c03ac9184c122e57b057cde426fd76dca79e25e64dbb41c8414a0450da4905b902ae98d2da4ba792801: +1fe7327ea907d3ff179b117811d30193fcba4c347b90657feed98deeecda9ac9eef301b16fd7bf3c7b640bf5ee8700ac5a87169eab5f56015b3f499d955e07eb:eef301b16fd7bf3c7b640bf5ee8700ac5a87169eab5f56015b3f499d955e07eb:19a832f26fbb0239f0d9d26a2ebded2403c2a406dd1f68318d677afa64f35043316a5efd729783c7f9d18c09824614652091886cc954be9f9312d4586bf36f3035ac703438b0cfe3dec5077813c710d1447561ab6157bc7ad5eab5b0c0afdcc9db77e66fa8071366829c501096c3d3a938218a6e4207109d1eb81f7d88bd6fbb2aefb1adef3594aae57c46b7b984db9468cd962c6184fb976f0e2aa84152deb1c76aea75ae488442943a80ba7d98a28cb864b5e87cdb284ad6e8d7aadc6b75d69d3bd345783b3ebb676ff95d7b4191e599851c9628835c7c01197e7c8f86f9c8fb49fe3e28458ba9b0236219bd46c28df6532496994ac9ba733c0105a02a269a2be8b7cb40074b881602ef9247052de9d637089188bd4c185ccae258a2ae9856a2cbf8451117683ce341f8096e1d91e874c5cb8a4e0939eb77373a9a0eb791645b8f5460472d669d8014681a5e778706cb5566bbd4727d1716b23c620d228b5d4dc2b352b423931f8a7e8fb59edad8ae42458729861a98e0c850a77ed655e7fcfe4fe36f9772df1ac3c643ad31db5630d571df9fcc9c50de7622108411962bbf72defbf49e997059c7311bd9ddd5b338a9851938d37e7a262108a291e2016803bbeff4f9c776125ceb7e7272b51c7c33461d8089f8408d8dda92506d5002084d4f414d8a4d28d3694c88630e31801990d95271cef47aa5c263f97b7daca1788701436329b5bfaf72653c166db087708130c5c0d78cc4e9064f860680271afe4c409853c2fad675:9c7fdb53fd606bc7c9c223fe9431e1ad009546d00098812a495197f2541e87f8d6f5da22ecefcbb7da56662a7309d10a6c4a4f7f299278d51bbd11e0cc1b870919a832f26fbb0239f0d9d26a2ebded2403c2a406dd1f68318d677afa64f35043316a5efd729783c7f9d18c09824614652091886cc954be9f9312d4586bf36f3035ac703438b0cfe3dec5077813c710d1447561ab6157bc7ad5eab5b0c0afdcc9db77e66fa8071366829c501096c3d3a938218a6e4207109d1eb81f7d88bd6fbb2aefb1adef3594aae57c46b7b984db9468cd962c6184fb976f0e2aa84152deb1c76aea75ae488442943a80ba7d98a28cb864b5e87cdb284ad6e8d7aadc6b75d69d3bd345783b3ebb676ff95d7b4191e599851c9628835c7c01197e7c8f86f9c8fb49fe3e28458ba9b0236219bd46c28df6532496994ac9ba733c0105a02a269a2be8b7cb40074b881602ef9247052de9d637089188bd4c185ccae258a2ae9856a2cbf8451117683ce341f8096e1d91e874c5cb8a4e0939eb77373a9a0eb791645b8f5460472d669d8014681a5e778706cb5566bbd4727d1716b23c620d228b5d4dc2b352b423931f8a7e8fb59edad8ae42458729861a98e0c850a77ed655e7fcfe4fe36f9772df1ac3c643ad31db5630d571df9fcc9c50de7622108411962bbf72defbf49e997059c7311bd9ddd5b338a9851938d37e7a262108a291e2016803bbeff4f9c776125ceb7e7272b51c7c33461d8089f8408d8dda92506d5002084d4f414d8a4d28d3694c88630e31801990d95271cef47aa5c263f97b7daca1788701436329b5bfaf72653c166db087708130c5c0d78cc4e9064f860680271afe4c409853c2fad675: +5f9dcd93fb140610b0e211b39addb1eb87ba97804877afbcc381388cad650845182a237d878c581933332b4178b67ec408b3194d44e4e69392ef800b267c2949:182a237d878c581933332b4178b67ec408b3194d44e4e69392ef800b267c2949:c38b874d3ff010fff1a6613bfa134257b24833cb536de3e74992c3cb01fe3bbdeed97dc3c4596fa44061442bd31a9d4aa8c81e34ad9888718206635509b133b1ba69cb1aa0e75c7a1893c080161d26152acef40f6ef4210e952a49828b5cdde804bcb536cdc349a8e831b4b69d3785a76bd9fb27080565972d0b8fbd16f3f960a6bf3ba0c5b9c404967ec1affe59b8c4ecc650fdde1cb06b70595ad4d325da0fab4c5540a7a8d5ebeacc4e99bd0dc96bde82f2bd7d9586308465e55b1cc388d750486bdd5c7264d54f5614d48726d99e44d7778d9ed0323958ab9858e2b25df2bf994ba3e625e2803b6c6931e7a9926f1e61ed862403ce392ab83b7d1b66085dcc06d82dbf176d016d9f44cdcb5072d004591e92d0459ef05a51b8f54ba17251e16621ebb753e5b1590c02d21e40f4b75eee4602860b9741fbbc0d2e385b8daca83cce68c34a99bde6a60d13ba64347d0a38d64b2ade250f38852c4eda2e2e4f303c3de1a8a9d4ab3300c9e63622879fc8537ffc63b18561fa1fff65531241515a62bb9b08b80af37667a601ae04171793cc83b11adf9c30ca9f4dabc7b401e16a1814cfc750248cc2f77e03f9c4334465ff6a2c83cbb56db4b734751043832c4000972ee3232f929f23337eba5e651e34cbddfe68ba219b632e7acdbd4630a031bf1689fbbc7fbbb210dbf25ee87e2ef2b3cbaf8d9ebd8fc92c3a58d3c05b1385a76c87791d7cd3741b71b6c329de9a9d7508a0c156a9521a9020563099a82b8770ae9a944a7e94:c1915e052b664797e0d5faadc78f2a009d6fbcfde03f3aaad59b9f4588e7fc3b21990c5208d3d76b4aa95bd934e88d3c98c591930a59de2a056701d9f7577400c38b874d3ff010fff1a6613bfa134257b24833cb536de3e74992c3cb01fe3bbdeed97dc3c4596fa44061442bd31a9d4aa8c81e34ad9888718206635509b133b1ba69cb1aa0e75c7a1893c080161d26152acef40f6ef4210e952a49828b5cdde804bcb536cdc349a8e831b4b69d3785a76bd9fb27080565972d0b8fbd16f3f960a6bf3ba0c5b9c404967ec1affe59b8c4ecc650fdde1cb06b70595ad4d325da0fab4c5540a7a8d5ebeacc4e99bd0dc96bde82f2bd7d9586308465e55b1cc388d750486bdd5c7264d54f5614d48726d99e44d7778d9ed0323958ab9858e2b25df2bf994ba3e625e2803b6c6931e7a9926f1e61ed862403ce392ab83b7d1b66085dcc06d82dbf176d016d9f44cdcb5072d004591e92d0459ef05a51b8f54ba17251e16621ebb753e5b1590c02d21e40f4b75eee4602860b9741fbbc0d2e385b8daca83cce68c34a99bde6a60d13ba64347d0a38d64b2ade250f38852c4eda2e2e4f303c3de1a8a9d4ab3300c9e63622879fc8537ffc63b18561fa1fff65531241515a62bb9b08b80af37667a601ae04171793cc83b11adf9c30ca9f4dabc7b401e16a1814cfc750248cc2f77e03f9c4334465ff6a2c83cbb56db4b734751043832c4000972ee3232f929f23337eba5e651e34cbddfe68ba219b632e7acdbd4630a031bf1689fbbc7fbbb210dbf25ee87e2ef2b3cbaf8d9ebd8fc92c3a58d3c05b1385a76c87791d7cd3741b71b6c329de9a9d7508a0c156a9521a9020563099a82b8770ae9a944a7e94: +925ebe04c6eac49b26738d6c1300f31fd4828478cbe97dab18bb889642e1e110cd7231b6eb74e1fe9f926f00d8de2c513d49640525b0795cab893d0c8929e3e0:cd7231b6eb74e1fe9f926f00d8de2c513d49640525b0795cab893d0c8929e3e0:e6c0bad23a92ae8b1d85778288157ac6c617c63363341d777870341bb10a8d3dfc89be4f55ad4f64e83bf2499b69fdf72174d2844e6bd289daaa035fec5bf7cf45522119dc7a8c811d79578c5bb0f6d34db507ad1fb6dbfff997b79dacfb3da50a415e350c998c0a02800aa50ffdfe5f4276d8e6bb82ebf047fe48711daf7a893bdc7537bdaedf3dcb4dec5d24586811f59b25b19e83ca61e5592fedc08ca54473cea2ec121baa0e77fb2d9d765657de67980ed57f2f177858b6decf84ff90212d9647f41eed9b9d0ea3d8d621e4bb4041acc5146e96dfcf14ea962d30c8ccb39ea2be958c9b8774451bfeb7ddce716e94923cc85fbd3a3130780e2b3b2bb76da5341912a4e994cafa19bba19732f2ea402d71d3d8a969679b9d104243d9839c69ee9e955e1c60449788d1f4f6651f4bc9b94d73522ec0cf72cacfcf19f1f03ad6232104b55cbb8b5bb1e21344713d482742d6abc5a957174f623b8495272cc1e2b8315e5c80f947f500c83d8544f7cd4f65348949ef4420d7fc831fa4ae2ee18dbba614925ce1d767c177a626c4527a8154b57292186b044cbf92894253b00fd9343f9e697b1412eba43597eb72a669aaa2d77eacb968c20fe19505a38074158621b606f77d97bc6ebe50e7589293db27fc7dfe631a4bee83b22682a77328c36d9d7d1d891d65217cc47864f680dc8b5fd1a01a0f7c34430f77060b691a1ad213d22868e61bbd38f43f0c8b4da68a58318666c099766170c2db766aaf417f556cc9a0a3934e9fcef1:2c4d69bed5ad8b9584d849cf3df2bac72282b5f30de266b14f533ca96e9550c4b854c154bdc17aa880cf001a6454ffafaa2e50178de21216ed126b63f77f2d02e6c0bad23a92ae8b1d85778288157ac6c617c63363341d777870341bb10a8d3dfc89be4f55ad4f64e83bf2499b69fdf72174d2844e6bd289daaa035fec5bf7cf45522119dc7a8c811d79578c5bb0f6d34db507ad1fb6dbfff997b79dacfb3da50a415e350c998c0a02800aa50ffdfe5f4276d8e6bb82ebf047fe48711daf7a893bdc7537bdaedf3dcb4dec5d24586811f59b25b19e83ca61e5592fedc08ca54473cea2ec121baa0e77fb2d9d765657de67980ed57f2f177858b6decf84ff90212d9647f41eed9b9d0ea3d8d621e4bb4041acc5146e96dfcf14ea962d30c8ccb39ea2be958c9b8774451bfeb7ddce716e94923cc85fbd3a3130780e2b3b2bb76da5341912a4e994cafa19bba19732f2ea402d71d3d8a969679b9d104243d9839c69ee9e955e1c60449788d1f4f6651f4bc9b94d73522ec0cf72cacfcf19f1f03ad6232104b55cbb8b5bb1e21344713d482742d6abc5a957174f623b8495272cc1e2b8315e5c80f947f500c83d8544f7cd4f65348949ef4420d7fc831fa4ae2ee18dbba614925ce1d767c177a626c4527a8154b57292186b044cbf92894253b00fd9343f9e697b1412eba43597eb72a669aaa2d77eacb968c20fe19505a38074158621b606f77d97bc6ebe50e7589293db27fc7dfe631a4bee83b22682a77328c36d9d7d1d891d65217cc47864f680dc8b5fd1a01a0f7c34430f77060b691a1ad213d22868e61bbd38f43f0c8b4da68a58318666c099766170c2db766aaf417f556cc9a0a3934e9fcef1: +4dd3b478ebdc59472bab14a8cdd0c2fdac5723ee04dd8917c7cfe7a536485c775bccb37e68c234bead49337de208afbaf611811d965859a06d31301247d66acf:5bccb37e68c234bead49337de208afbaf611811d965859a06d31301247d66acf:1cdbd28556ec44e8705afda92bd5a53f95d8fe8b0ffe463373633316c52274c11edcd61551e3199e494dff6d906a739e7b324303fc47827e56def0bdcc46b816017c712305370263babd2c71be478f41ce30b1df63bedd3b2e6a519c53df515852c4137bc1aca49bf4c4631fd6564657d11cd83ea73cc3d0cf9e3b3c3e7ca99b4f12a9c9b67c8798148e0a0dc1ef8bf58642a14f97a572135514c10b19aabec25a9c6b35aa4034a57aae1b6d05bde2b6330f251d78db0993f0ca4c26386e3489a2092833b8acbbc4f4917fd3093df582fff71ece219d3672455582609c0db8d96a70fc8aed6798de54bfb2b3ee6c5d328db163593f58019f38f339fd3753f896a4a2cca8c1400a77ea391935f34e2639c560860810bbbe4be1d16e012c11490aa84f2964c877c293b300f43d379f3eba9af391dee510856a4ddcf76e0a0ae06a6a7c0f9c5e3fa1b8354fe8977b4ea3b20661491fa4613ba62f556d5d5da8213d0121de2c8725df0aae048ac891abbc06bdcef3c3effdf5a31749476f814db9457945f0d91e14080056be921a16aa964a9298221b157594973e32969993310c8707e19f3143abc4fda7c8ad0160acf031aba652801aa81a016b3137039e27d6738d02800a93a86f9f5585c518dfa9e7d8ac727f37437e56d2788386e11653a04e165169f903972a01484751e7cb38632590ec80d5fce4541601a0e095785a9ee8d359edf26b9946e798da5998cbb736f94eb713463f79f561759bbcb4c4ac693cabf2e1e036b2d0b0879a:5788e79e843bde9ef11a9dfac970196a567c6308c348e5174b387795046d590a47491fd71d97aeaa78c1615971b83490e8592820f9592ac76269b9d2ba7029011cdbd28556ec44e8705afda92bd5a53f95d8fe8b0ffe463373633316c52274c11edcd61551e3199e494dff6d906a739e7b324303fc47827e56def0bdcc46b816017c712305370263babd2c71be478f41ce30b1df63bedd3b2e6a519c53df515852c4137bc1aca49bf4c4631fd6564657d11cd83ea73cc3d0cf9e3b3c3e7ca99b4f12a9c9b67c8798148e0a0dc1ef8bf58642a14f97a572135514c10b19aabec25a9c6b35aa4034a57aae1b6d05bde2b6330f251d78db0993f0ca4c26386e3489a2092833b8acbbc4f4917fd3093df582fff71ece219d3672455582609c0db8d96a70fc8aed6798de54bfb2b3ee6c5d328db163593f58019f38f339fd3753f896a4a2cca8c1400a77ea391935f34e2639c560860810bbbe4be1d16e012c11490aa84f2964c877c293b300f43d379f3eba9af391dee510856a4ddcf76e0a0ae06a6a7c0f9c5e3fa1b8354fe8977b4ea3b20661491fa4613ba62f556d5d5da8213d0121de2c8725df0aae048ac891abbc06bdcef3c3effdf5a31749476f814db9457945f0d91e14080056be921a16aa964a9298221b157594973e32969993310c8707e19f3143abc4fda7c8ad0160acf031aba652801aa81a016b3137039e27d6738d02800a93a86f9f5585c518dfa9e7d8ac727f37437e56d2788386e11653a04e165169f903972a01484751e7cb38632590ec80d5fce4541601a0e095785a9ee8d359edf26b9946e798da5998cbb736f94eb713463f79f561759bbcb4c4ac693cabf2e1e036b2d0b0879a: +074d9218c1217e75823c90e010484c2adb88ecccd2bdf0120aa3edffcfcbd4bf3735ad1919033d1617b85bda04b16121da1d861b404154fa961d4946e55ecd83:3735ad1919033d1617b85bda04b16121da1d861b404154fa961d4946e55ecd83:6b5aa40e9167bfdb847daa7d2786e28e7533e1d6ac53beb6f69b5953795a2bf59bbf7d141926968f50969bad742a4fb579d3250fb1be4c57ebf4f9112c70cd9f72a00db1c8896fe2b5bda7c7030f497c0b001ea25ba0d447f08c36db8b907c2f2abbbb620d3e8a2c66e4171285adcaadd1c14fe239bc595f098396aa8780ffb80fe1446a07001ec234d82abdcd8100793915b0b3f80d84e20e51eabc797806f3be8108a4f437550b06694050a82931ac40c0a48977edf6ced2428d7cfea8205506de86408065d1a19870fa33a7081037b3ee4491b6e7f3d10b14a30c209159a1c81231a35f0365b47d3e0da04a32c95d98333c44f572cdaaa905d069197f6e861b5dfcdfb9db6c7b0d0cb00f37c916a1c4c0b8985b09f334095e1283edfdd4e62a2941099a2b693696604d994311e3d5f6106683e1d7a1c7e53df7b790947a9a801a0ccd484395f6cbfd9ca4d9804f18d52bb0f946d1a89f97a6fb0680a8c4c057b6062b2b9de7c0374879b8a6a6d2c10aef780508eb28bb569a08350944c82f6ef28db2304db697c3ae1af43a500b0b974803e9f46ea2a02e85ed27dda616d24d6db3cc4f5aed8240b1aea3dcf69dee5f14f95e6e72987bbe6189bc2045f0d783a7b47bfc19830bc7f4e798abe90245fbd43f37c3f036d1cbf1e73dcb1d9daa87379b1106973481a215c1f4f46c1603a5d5cd97b7076f1f5dc789aa6a71e72ef54ed328a4ab64340539ffd164d0ec645f322d1bc37112dc08d8c8079d19d37abb2353f48b5c492f806ed2:b1f71c3bd1b6bec43337e26dee655a8d5f4a8dad84a51184b775b686fad31d8029e3876927f9576e90c3624875fc0029a5c10a8a0af75d7a880c6844a4a83a006b5aa40e9167bfdb847daa7d2786e28e7533e1d6ac53beb6f69b5953795a2bf59bbf7d141926968f50969bad742a4fb579d3250fb1be4c57ebf4f9112c70cd9f72a00db1c8896fe2b5bda7c7030f497c0b001ea25ba0d447f08c36db8b907c2f2abbbb620d3e8a2c66e4171285adcaadd1c14fe239bc595f098396aa8780ffb80fe1446a07001ec234d82abdcd8100793915b0b3f80d84e20e51eabc797806f3be8108a4f437550b06694050a82931ac40c0a48977edf6ced2428d7cfea8205506de86408065d1a19870fa33a7081037b3ee4491b6e7f3d10b14a30c209159a1c81231a35f0365b47d3e0da04a32c95d98333c44f572cdaaa905d069197f6e861b5dfcdfb9db6c7b0d0cb00f37c916a1c4c0b8985b09f334095e1283edfdd4e62a2941099a2b693696604d994311e3d5f6106683e1d7a1c7e53df7b790947a9a801a0ccd484395f6cbfd9ca4d9804f18d52bb0f946d1a89f97a6fb0680a8c4c057b6062b2b9de7c0374879b8a6a6d2c10aef780508eb28bb569a08350944c82f6ef28db2304db697c3ae1af43a500b0b974803e9f46ea2a02e85ed27dda616d24d6db3cc4f5aed8240b1aea3dcf69dee5f14f95e6e72987bbe6189bc2045f0d783a7b47bfc19830bc7f4e798abe90245fbd43f37c3f036d1cbf1e73dcb1d9daa87379b1106973481a215c1f4f46c1603a5d5cd97b7076f1f5dc789aa6a71e72ef54ed328a4ab64340539ffd164d0ec645f322d1bc37112dc08d8c8079d19d37abb2353f48b5c492f806ed2: +d2ea2dff7af0ba2a6bed7f6cc68c0df664a6b10ce801c42ed5bbe617bcc8b84aab44706344026ed35e21982964f7b4dbbbe207fd27c46799701c19a4d88d1d72:ab44706344026ed35e21982964f7b4dbbbe207fd27c46799701c19a4d88d1d72:03ab5daebc6e70d352977932a03107879bd55dafd0c6ba7ad9697a17b127b3a74a3eaebabd0f8eeebfc0483d63fedde52deb46a3752449c9c4495c51a1c91f57e3ad2e6d01a13d0c470c5291b8e912288340970fbb85787b8b376d72175250e8cd90c07888bfef5ebf5086c8ff2abcdd12d214b9c45d120873b4602e57a6aab0b828d1084dffaa3651ee35662695b7f3433f4ab530c29ac6cc5bb43eccd1b6898b9ef7aec6d5aec68d5c1114bb5df7820966594c994d640891b8f2dc5d25638de43549d86d34306ff3f574575116405b9e8e286ee0cd978a76002c4435feaac6e84eae1654f339a567d8d04fcfa3eb6a04b9adc666021300e9ee5972b3df5d4d0dd4bf7921dc98de82cef2d1b1d61b797fc9968e118484c41342416ddc6adc4ee5d687d94a40ce572f42a2048668c175cf7b1f24c4efd020554fc6f642e14a57baec23e95c2514306d0a6d33648841497eac48eabd96d04731bab08bf5ea9d43e0cf9a37faafa732869d68e7d5fe6954f8a319ef55da1e178e43e84a3b9aa3ad00c29b1d161163df4b79f288e9391d70a2f8813d66622e8ac333fa6aa5311eabec383ba4cc122815de008877efbe6e12c322c975434afad173ebe24203d916d57578bd2bcacc78f6e2564513f8d113a833c2c226eb97ba2e23361a5d02664ab377f964c4300be2d77b62d9240823a09884df307eff3be5664d72d11ad513e1bc5610dbfd1009db39f0cbfe470555ec1b56b871670793d3b704fb06ee950b1ad2a4d7297ca58bbad810c3fad4:9abdb9dd2ab77b6f5e1b91ba0b613f5f360efb500d3fe99290ef7ca14bd2b330f405a4f7dcdaef4923d3111d40bf0320353386f634b40de6f04de9190ad51c0803ab5daebc6e70d352977932a03107879bd55dafd0c6ba7ad9697a17b127b3a74a3eaebabd0f8eeebfc0483d63fedde52deb46a3752449c9c4495c51a1c91f57e3ad2e6d01a13d0c470c5291b8e912288340970fbb85787b8b376d72175250e8cd90c07888bfef5ebf5086c8ff2abcdd12d214b9c45d120873b4602e57a6aab0b828d1084dffaa3651ee35662695b7f3433f4ab530c29ac6cc5bb43eccd1b6898b9ef7aec6d5aec68d5c1114bb5df7820966594c994d640891b8f2dc5d25638de43549d86d34306ff3f574575116405b9e8e286ee0cd978a76002c4435feaac6e84eae1654f339a567d8d04fcfa3eb6a04b9adc666021300e9ee5972b3df5d4d0dd4bf7921dc98de82cef2d1b1d61b797fc9968e118484c41342416ddc6adc4ee5d687d94a40ce572f42a2048668c175cf7b1f24c4efd020554fc6f642e14a57baec23e95c2514306d0a6d33648841497eac48eabd96d04731bab08bf5ea9d43e0cf9a37faafa732869d68e7d5fe6954f8a319ef55da1e178e43e84a3b9aa3ad00c29b1d161163df4b79f288e9391d70a2f8813d66622e8ac333fa6aa5311eabec383ba4cc122815de008877efbe6e12c322c975434afad173ebe24203d916d57578bd2bcacc78f6e2564513f8d113a833c2c226eb97ba2e23361a5d02664ab377f964c4300be2d77b62d9240823a09884df307eff3be5664d72d11ad513e1bc5610dbfd1009db39f0cbfe470555ec1b56b871670793d3b704fb06ee950b1ad2a4d7297ca58bbad810c3fad4: +7a60cdf1870460de8ae7781176d5127e71207faf2f210bd4dc547385b667f2f2ead67a9cf34d0ff14e79afa46f2dc996e9ac0e3e076322fbb4009767b133f01b:ead67a9cf34d0ff14e79afa46f2dc996e9ac0e3e076322fbb4009767b133f01b:9dc023a525d01ba3513798b738c79162926ebccc0adf1e57ac47c20dea6ce1375c3d2aaa1733b7f0c3bd945c335ff3576112bbdc10b6783ba654e8c61047f2773aa229bf846922a89c6a73d5f1051e8d96ed36d7d6747e063a7ac602f19fc52e021a4bbc28b03514fbd51c7b3fd659f12d547d0592dd09f873c9ecc6439c7e931ad0e4856be31c605def2ed9b5d13c5942b2f325397dac6c9760e9b1bb0c06f713cb920c234bccfee9f0b85dd020f7988f3be1cc66e9e51babe2fee237eb84ec7eff9409aa91c194e30db1e065015955de9746bba03f7edf9a587512409a4161fa77ea62ccf431602dcdcf365ed6bf0aeddd32f7c844e3a34d266e28382f4062fd4d6f8214252104d643a9bfd8071716371ccbb54c8cc8db79add65bcbcea0d080d8402803fe232df70f76577247a63d5583bbd5642767bc63f3c5a7bb3a47eb12984e4541f41fdb55869a08fade66c20f69a5a9de25f6b36ba18ace5b4ac336bb2a8ebf630ad03e8bb8731d01e84b91d024d117459a74892e93d53b61e6b8068e4f04b4181f0387b4567ccd45e1b8718a2d7d787872f3dcf87a15935ad7daaa744ed68a28666a51a10d39fc139cdfe9a6873076f7c425009c38faee135e513207b06e7ba35685f5072da34b6045b57cd5d1b1a1fdf017b8aa8ebd27522bc95e47908734e41722a767905c5ecc30c72481b6c12bf4ace94d5bb3a3155691b7075b40ebf5968fdd903d8fd3cc50b8d6464859b10f755132c6d9b6dad1d6f14c4185b264d3497a4e549877fe946e:b2e08142bdd62b786592c091f5fe6a9b7f30ce134c3b236fbc6dfe6734f88270ac58f6d74b4fd99c22451ca465a42c006db25af215ed241af1189627c6050f009dc023a525d01ba3513798b738c79162926ebccc0adf1e57ac47c20dea6ce1375c3d2aaa1733b7f0c3bd945c335ff3576112bbdc10b6783ba654e8c61047f2773aa229bf846922a89c6a73d5f1051e8d96ed36d7d6747e063a7ac602f19fc52e021a4bbc28b03514fbd51c7b3fd659f12d547d0592dd09f873c9ecc6439c7e931ad0e4856be31c605def2ed9b5d13c5942b2f325397dac6c9760e9b1bb0c06f713cb920c234bccfee9f0b85dd020f7988f3be1cc66e9e51babe2fee237eb84ec7eff9409aa91c194e30db1e065015955de9746bba03f7edf9a587512409a4161fa77ea62ccf431602dcdcf365ed6bf0aeddd32f7c844e3a34d266e28382f4062fd4d6f8214252104d643a9bfd8071716371ccbb54c8cc8db79add65bcbcea0d080d8402803fe232df70f76577247a63d5583bbd5642767bc63f3c5a7bb3a47eb12984e4541f41fdb55869a08fade66c20f69a5a9de25f6b36ba18ace5b4ac336bb2a8ebf630ad03e8bb8731d01e84b91d024d117459a74892e93d53b61e6b8068e4f04b4181f0387b4567ccd45e1b8718a2d7d787872f3dcf87a15935ad7daaa744ed68a28666a51a10d39fc139cdfe9a6873076f7c425009c38faee135e513207b06e7ba35685f5072da34b6045b57cd5d1b1a1fdf017b8aa8ebd27522bc95e47908734e41722a767905c5ecc30c72481b6c12bf4ace94d5bb3a3155691b7075b40ebf5968fdd903d8fd3cc50b8d6464859b10f755132c6d9b6dad1d6f14c4185b264d3497a4e549877fe946e: +3379d25c1117cf802ec79c06575d18e6bece4c7093dd43fdee03685c70b2fa9f8525156fe29fc2fbf661ba50182be20c8998d941493d5933dca4d8b41fb442d5:8525156fe29fc2fbf661ba50182be20c8998d941493d5933dca4d8b41fb442d5:7acdb39f1226bd3abffa50350a1497d761f8f0aaefbfbbbb925ff563e38976aa172d407b61ffdfb1cd538a4cd000b57818a0bc92c0e0cd0a5abfcf578300f5f4e6cefa267275d17845da7066fd4e18010027960cd395e682ad71af349bbdad5ebaa0f11a7761e19ea1bef6610743164b17141453b472ae2c8f36ce6b080f1c0745352454ce5aeae11c9d75de3c08004265fc4ca80d33b26eae1400dfd8977bf723a616daeb6d42199010b73e193ab72a58bdd248a7f4111ca50c1de646bfea7b4d5baf0f93dd973ee93649e21ec0c6c4fcca8cd6ff69df761612021d85ff1fb2a95337da4805a76d347ee71ef19c0dffb59f15f650293abb9721053f7406905ae683f96c83a3a7447b1afb14e1208c639f37a9750ba21da5552cc204eac453ca036282f7e0961093c39ec118138dcf71cf2d28fb96a24962b52d3393f880653bcba2c9b9d57b77c522f421fcf5ad75fba9cf3389b123aa97521713fff88467deb8c8991d4b57c1438170537cb50cdcc657e50e5c480e12c0d44939b6399944e7c71e186c2abb81fc57348836d5e57b72b224a6b71b6caf721aca73478cb6cf5fb89071ae3a398202dbb38c30812563bb9a23406657a956d305a3449a60cc8641b62175a7170c23bd5a25f0f12e15a7ed91fada6a4a2f0e7b155a3d6485ec03ce6e34df7e216240bb28a2dd732ff790d2286e200b33c29a31a5e19ad2cd02974badc4bc22deb7504c15241fc1060c8acef4fbb25ec7602fce36a27bb87b6e6423e6b4f6e36fc76d125de6be7aef5a:4c36bfc81eef00b9cb3ab514c6d451b993361e09a4be4b5040926feb0e0d9b52f03de468e7bad83f379154bf2c437a71f754f3f40798eeebd62e55f2be7714037acdb39f1226bd3abffa50350a1497d761f8f0aaefbfbbbb925ff563e38976aa172d407b61ffdfb1cd538a4cd000b57818a0bc92c0e0cd0a5abfcf578300f5f4e6cefa267275d17845da7066fd4e18010027960cd395e682ad71af349bbdad5ebaa0f11a7761e19ea1bef6610743164b17141453b472ae2c8f36ce6b080f1c0745352454ce5aeae11c9d75de3c08004265fc4ca80d33b26eae1400dfd8977bf723a616daeb6d42199010b73e193ab72a58bdd248a7f4111ca50c1de646bfea7b4d5baf0f93dd973ee93649e21ec0c6c4fcca8cd6ff69df761612021d85ff1fb2a95337da4805a76d347ee71ef19c0dffb59f15f650293abb9721053f7406905ae683f96c83a3a7447b1afb14e1208c639f37a9750ba21da5552cc204eac453ca036282f7e0961093c39ec118138dcf71cf2d28fb96a24962b52d3393f880653bcba2c9b9d57b77c522f421fcf5ad75fba9cf3389b123aa97521713fff88467deb8c8991d4b57c1438170537cb50cdcc657e50e5c480e12c0d44939b6399944e7c71e186c2abb81fc57348836d5e57b72b224a6b71b6caf721aca73478cb6cf5fb89071ae3a398202dbb38c30812563bb9a23406657a956d305a3449a60cc8641b62175a7170c23bd5a25f0f12e15a7ed91fada6a4a2f0e7b155a3d6485ec03ce6e34df7e216240bb28a2dd732ff790d2286e200b33c29a31a5e19ad2cd02974badc4bc22deb7504c15241fc1060c8acef4fbb25ec7602fce36a27bb87b6e6423e6b4f6e36fc76d125de6be7aef5a: +ef38c3fc74f054ae43e8d29d6ba6dc80b5af848270d4af58844d24bcf987414e0ae1478b05fb329965ea0fa928dcbe81a0bdbb6ff66c811671635e4388888051:0ae1478b05fb329965ea0fa928dcbe81a0bdbb6ff66c811671635e4388888051:bf290db3dda8763937ae4c83746705327295c2c248068f5ab85c8b5d756f4e3e34062b5549387261476bcbd1e7331990f11910d11f94607c2b71f65b771aacabdc10f42ae918dd2594ac71051c85b330779c47af00a5b98191b56cbcf7efe41a27e87c677168c8abe9496eb2e7abbd0b1604286ed1a1b18d264d733de87d0d3f8055528c4d426d7f8e6ed024a74140abd354007962a2a97a5c2ff976546a8d1ac4924c09223d348ddcd8710a3799f91bb870b3f46d51f1e7f6892d6b08b991748a037a867ecc39ee8d6462a7614488edd3c2ba615ca2e37854889441b13dc835c36b38653f6598616f35783e2e158384bb931c901b703acb3991fb7aa5ba69d9a5bd0570242961a71a52470315e982e341a61c64a619bd16fe8119aae0d7503ce7d7e926146b91c2892f131669d1e39e5b75e9c72452618099a57dc2ee377be65875ee01bb88ed526fc394e2f5c8127a5f69125e67385ef94b1f33ad52629d720e31c02ae0b582339ff0f0bb07ff2b030f48fa7b692716501ad7773ad3151204a2a540fa9436bdd4202a157309ec36cecbe58b33eff557fd33e03fd3eb19009bd7a2dea9efeef8785567aab2a4c98bd1f2a81011b343a9f20c44c577a452fd54ba21029d4706813b2987c76bb242ab2620843c2260b669ad358efee7f9830dc9c7d478a2de4a2cf8c43da770e288e2edbb6d73bcf2ecb023de6b2dcc6b166e87a385eb0adc305665c5bfa57f250fe223ad7ff4518de39c79e87dc101a9faa6821a74442bfcfdf0a9e63a509e2a2e76:1d3ac6b6bf18ab5309148799485b276d20401c6af5f9b2f6032395a3c2f4b673b7140c07cc26f4fc56a5ee00b0746b2a80da6fdad17edd114920101d2c89c30ebf290db3dda8763937ae4c83746705327295c2c248068f5ab85c8b5d756f4e3e34062b5549387261476bcbd1e7331990f11910d11f94607c2b71f65b771aacabdc10f42ae918dd2594ac71051c85b330779c47af00a5b98191b56cbcf7efe41a27e87c677168c8abe9496eb2e7abbd0b1604286ed1a1b18d264d733de87d0d3f8055528c4d426d7f8e6ed024a74140abd354007962a2a97a5c2ff976546a8d1ac4924c09223d348ddcd8710a3799f91bb870b3f46d51f1e7f6892d6b08b991748a037a867ecc39ee8d6462a7614488edd3c2ba615ca2e37854889441b13dc835c36b38653f6598616f35783e2e158384bb931c901b703acb3991fb7aa5ba69d9a5bd0570242961a71a52470315e982e341a61c64a619bd16fe8119aae0d7503ce7d7e926146b91c2892f131669d1e39e5b75e9c72452618099a57dc2ee377be65875ee01bb88ed526fc394e2f5c8127a5f69125e67385ef94b1f33ad52629d720e31c02ae0b582339ff0f0bb07ff2b030f48fa7b692716501ad7773ad3151204a2a540fa9436bdd4202a157309ec36cecbe58b33eff557fd33e03fd3eb19009bd7a2dea9efeef8785567aab2a4c98bd1f2a81011b343a9f20c44c577a452fd54ba21029d4706813b2987c76bb242ab2620843c2260b669ad358efee7f9830dc9c7d478a2de4a2cf8c43da770e288e2edbb6d73bcf2ecb023de6b2dcc6b166e87a385eb0adc305665c5bfa57f250fe223ad7ff4518de39c79e87dc101a9faa6821a74442bfcfdf0a9e63a509e2a2e76: +7e7b39af69380cf44660e2c1ff308334e8250feeb88be0d43aabe5e68b8ef171ccef9daed92523533d4a2dab6d2419f6d08604db64ce37e32904ac77b9b4a01c:ccef9daed92523533d4a2dab6d2419f6d08604db64ce37e32904ac77b9b4a01c:d4a3976dbf8320185667b5a8236640f2ebc9e45e6d5f2a8d92997927dd9bc5db95f44634bd654eefece10d99d92b46715791645004accc6d140f32a1c872e54aa9a7493af94588b7bb400d94d458d43292307c5a1a3882a1c8a6a78d9a945f79d64b3294a28c3d59d82022b009cc4d2da93a16b071c9ab8ee9a3663d72ed344f151d68c666a4b49652d97a46d142a4741127f3c57f1551c40976cd1381a82aeae7bc5adb398720eb433f0899487ed2378446b1a8dc6a33fcd4537a05fb603ec0a90a27532300242b2000108621b65ab000bc06381530f690d7e56f81604dacff1910715040410aa1f944c92dd9bbaa5bd08ea00c8442df94f085eb3de97335b6005e6f84f823d43470ab1c67da12ad449936c6b55f9ffd203dfd6e3f33309e8a9945a59320e66734c79c4814dba5a1c14095c62925a1e1733efd94817a25ef9e479dd9ccde6ca8adb7a8053c1b55134697504af8053d595b844640b61e93168075468450eb5de0358697c104afa6a3796a509c26b4c277c23fff42df146de55e95d0d4b80a7aa177d99227ecb2a0594deedebb9cafb1a458aca8072cc7d77c7175f610ca300efd7af9388346498c22991564500e0b0aa4d2946f18e6f5375a848286f36954c1ca22684c6928c2a25c7fe21aba4a7111d7e05bc8d70b3dcb4f6aaec064845eef5525f85024c2570f3b78698c4bcec0d71aad5378d8819e1fac44ee416370212dbaaae54d2af2939b82cbaae7f42ff485d45b3acc21090f5ba41ec0da309e52ef2838d1de471e0b7cf985:1062a2dc9cd5379675c04f5e21338dcfb77dfbabcedd62b2607100d7649a05e80871e96123214f80f4f73b0d9b06e2d31f56119cea69da2347da84a275b7b207d4a3976dbf8320185667b5a8236640f2ebc9e45e6d5f2a8d92997927dd9bc5db95f44634bd654eefece10d99d92b46715791645004accc6d140f32a1c872e54aa9a7493af94588b7bb400d94d458d43292307c5a1a3882a1c8a6a78d9a945f79d64b3294a28c3d59d82022b009cc4d2da93a16b071c9ab8ee9a3663d72ed344f151d68c666a4b49652d97a46d142a4741127f3c57f1551c40976cd1381a82aeae7bc5adb398720eb433f0899487ed2378446b1a8dc6a33fcd4537a05fb603ec0a90a27532300242b2000108621b65ab000bc06381530f690d7e56f81604dacff1910715040410aa1f944c92dd9bbaa5bd08ea00c8442df94f085eb3de97335b6005e6f84f823d43470ab1c67da12ad449936c6b55f9ffd203dfd6e3f33309e8a9945a59320e66734c79c4814dba5a1c14095c62925a1e1733efd94817a25ef9e479dd9ccde6ca8adb7a8053c1b55134697504af8053d595b844640b61e93168075468450eb5de0358697c104afa6a3796a509c26b4c277c23fff42df146de55e95d0d4b80a7aa177d99227ecb2a0594deedebb9cafb1a458aca8072cc7d77c7175f610ca300efd7af9388346498c22991564500e0b0aa4d2946f18e6f5375a848286f36954c1ca22684c6928c2a25c7fe21aba4a7111d7e05bc8d70b3dcb4f6aaec064845eef5525f85024c2570f3b78698c4bcec0d71aad5378d8819e1fac44ee416370212dbaaae54d2af2939b82cbaae7f42ff485d45b3acc21090f5ba41ec0da309e52ef2838d1de471e0b7cf985: +a9048af0c20a125f5d39c50f22b805ae742cf64f1fe8dfbe8dfdaa511aaa576f158655db94b15ca72983877b6db231a5843df5dbca2810a7e496fb59ab7104ca:158655db94b15ca72983877b6db231a5843df5dbca2810a7e496fb59ab7104ca:8eef2d9f5d59709959c924f87c22789767393a155d5c87de488cef50b7bf7da870e3adc300aee6603b2ef08764d99d9e7751e5dce92aaa71aa18a69cc823134e8552d959a0dbb41117e0a593c31833b6ec2172ddafaf7848ddd18d28d0d4ed33237ec804f65938aed8e8a3280d42e353d01be0187b1301f83d89849067b04a9031f7e0f33e3416240c53d9265ed0663959971f417cb5f210cdc5aebcb5e1db7dfb82df435876a6e98f415b0df869f0d8851535375645eef70faec744ee0dc3acbcb040f68d502c2c62c8db45ebe54854a4b36f43feb49a6d1c2c2ea79914a7c23c60baaa67cb47b2178e12dce76b004c87b7b8346efadf380b9e1e41f63148da51781d75cec040e4268820211f3c462501d80899894e79d618de42461d785aeace53ae14b79d33501ed5629bbdd07128156db0725f5b4bed593a952947830384f61df00ee0aa099099c3cd9765a9c1c7e8a6a83430b8d9867c8e17920ad0ff64d8cd2ff5f114388ce6d43eec1715d035f022fa97969e1a5dd9f58d896b17c1221c9e6c8555597235eeda6ec41b0c117612b00c5f0ed1816b057363582707a8aa0d98d4d4be5e8fa32d6c9d278221ef3067b8ba1516d9e051d2f68b7d1b151f74a3534e7812c051e5f2b63b3035f8e5703b5f68fd2d65bb7565e8aa67bfd2a12caf0bc5481197a9ff89d77df7a0e9655ef029b43dd906d0b888e313ae9d1c7e9368a01352d00c6680dd0f1f574a5877348a7ea2c0b9e8e2727510bf0c9ef744f369eb3c6c4fc16adeb6e1945be8287d0f30:18a312b20d86ac339a58ef2b852d467c23bb2cb1227cb15338af07fd04b9a711e856ee5b2c82e366c17f861713d1088c1b2144d1c37d05bdc00d7396738520008eef2d9f5d59709959c924f87c22789767393a155d5c87de488cef50b7bf7da870e3adc300aee6603b2ef08764d99d9e7751e5dce92aaa71aa18a69cc823134e8552d959a0dbb41117e0a593c31833b6ec2172ddafaf7848ddd18d28d0d4ed33237ec804f65938aed8e8a3280d42e353d01be0187b1301f83d89849067b04a9031f7e0f33e3416240c53d9265ed0663959971f417cb5f210cdc5aebcb5e1db7dfb82df435876a6e98f415b0df869f0d8851535375645eef70faec744ee0dc3acbcb040f68d502c2c62c8db45ebe54854a4b36f43feb49a6d1c2c2ea79914a7c23c60baaa67cb47b2178e12dce76b004c87b7b8346efadf380b9e1e41f63148da51781d75cec040e4268820211f3c462501d80899894e79d618de42461d785aeace53ae14b79d33501ed5629bbdd07128156db0725f5b4bed593a952947830384f61df00ee0aa099099c3cd9765a9c1c7e8a6a83430b8d9867c8e17920ad0ff64d8cd2ff5f114388ce6d43eec1715d035f022fa97969e1a5dd9f58d896b17c1221c9e6c8555597235eeda6ec41b0c117612b00c5f0ed1816b057363582707a8aa0d98d4d4be5e8fa32d6c9d278221ef3067b8ba1516d9e051d2f68b7d1b151f74a3534e7812c051e5f2b63b3035f8e5703b5f68fd2d65bb7565e8aa67bfd2a12caf0bc5481197a9ff89d77df7a0e9655ef029b43dd906d0b888e313ae9d1c7e9368a01352d00c6680dd0f1f574a5877348a7ea2c0b9e8e2727510bf0c9ef744f369eb3c6c4fc16adeb6e1945be8287d0f30: +f8c9183f23105fad0c6e5103358b583288f9ff6c7dfc91106d07987ff69ce1eb4c79628c958cde0cc3cf686095b8a2f44b7193c616f51b21b670b038ce6f67ff:4c79628c958cde0cc3cf686095b8a2f44b7193c616f51b21b670b038ce6f67ff:b1d60595323ff3c844874190e1836e4101409cbceae28d5da81fad298fe47f6bdf44745b7cd0d37131c3ec365b92f5a1a69c09fe2d9e81da10cf19d85ff5ff26f9e7db9f0793b25ab26e6a74f44eb8c4f078eb7ad18e65a16210d5c844d3cef75f1daf44eee558f90e524a032b6cae6c8d23367c28ce1c75fc25ac87433977d597533c92ae65f2913a18907ac7d9543df24127743943fefd9cf83ed833f63ec8367233d897bfa12d466d2c4a9ad70d5a672fc10775ea2d204e636de7010788da271df03881a25c8dfa5af73ee559f81b529b35aa127fdc0ee8fd369c7a0436623986aa6407fa67a1420c46f3211ab84f84466dd58bb79508a1feb0a5a5dc3bb0c1b248098262a064f37bb2f019e290c60afaa1206651a2697caacc3ecc02ecfc077f272e8f75cea71c3bc3356d2b5807276f1955001cfe10a61716b4082bd6f84cae4bb0d9a4b75a4b5762f81079f19d7d19eaff8631c924885bd3a64e129f4cf6b79c7a9829665511e9d85c745eb22c1b7cb2a17a49b6285cce37b3de415940328323efe24a1a07ee87468f6510e42dd206fe7f09e3d433fb52156ae348383115648863e45bf6a371b17e70e19f9627d7f0a58b95c6a4788d5fd7862f1612c0347325b797651be30c3e1e60ea4ae60b5745a38b6a9d4eb4935d6f3cb8d71ad3f39adda5e42e2219de0d381909c9cd317dd4379421a2a84268a7ea7180a64c129be1e5e8fcbbf5ed659e9f7e763ce84f630d5407954f9f755750a6dbf9f7660717de8e2adc1e9ac9ee31654d1837cee39795:c6a8bc7a0d5c6185b6ecd6033e42321d5c871bf889be72bd54cc0083ed60a470b2cc0fb4682c894c75b0df95f1ecfbba2d5acef3e1aafe54b9f7e803a1d0150ab1d60595323ff3c844874190e1836e4101409cbceae28d5da81fad298fe47f6bdf44745b7cd0d37131c3ec365b92f5a1a69c09fe2d9e81da10cf19d85ff5ff26f9e7db9f0793b25ab26e6a74f44eb8c4f078eb7ad18e65a16210d5c844d3cef75f1daf44eee558f90e524a032b6cae6c8d23367c28ce1c75fc25ac87433977d597533c92ae65f2913a18907ac7d9543df24127743943fefd9cf83ed833f63ec8367233d897bfa12d466d2c4a9ad70d5a672fc10775ea2d204e636de7010788da271df03881a25c8dfa5af73ee559f81b529b35aa127fdc0ee8fd369c7a0436623986aa6407fa67a1420c46f3211ab84f84466dd58bb79508a1feb0a5a5dc3bb0c1b248098262a064f37bb2f019e290c60afaa1206651a2697caacc3ecc02ecfc077f272e8f75cea71c3bc3356d2b5807276f1955001cfe10a61716b4082bd6f84cae4bb0d9a4b75a4b5762f81079f19d7d19eaff8631c924885bd3a64e129f4cf6b79c7a9829665511e9d85c745eb22c1b7cb2a17a49b6285cce37b3de415940328323efe24a1a07ee87468f6510e42dd206fe7f09e3d433fb52156ae348383115648863e45bf6a371b17e70e19f9627d7f0a58b95c6a4788d5fd7862f1612c0347325b797651be30c3e1e60ea4ae60b5745a38b6a9d4eb4935d6f3cb8d71ad3f39adda5e42e2219de0d381909c9cd317dd4379421a2a84268a7ea7180a64c129be1e5e8fcbbf5ed659e9f7e763ce84f630d5407954f9f755750a6dbf9f7660717de8e2adc1e9ac9ee31654d1837cee39795: +16089a1b932f8d14995688b48dd841edae3da5cfd2cb16555306f3fe8bd3edb99ecd9fdd7e0b923deff5d887b242585d9d41cd2c7c10f9c345b39f633f4ab903:9ecd9fdd7e0b923deff5d887b242585d9d41cd2c7c10f9c345b39f633f4ab903:58500232388d9aa4b5faf85b0233247e717fd16840de9bfd0ef86e01e61302775513e224125e0d20420ea949f6c26425f70077911f9711310cd6fd8bff27cdea11480c73e8f8b3c37641e7e8dd8607c1640218fec80a020928b93d4d557ebe82ec0bb17538867d2cb14d44d3ea727fdd52820b0da944de21cd5da303d776fe99cbc2648365e6a0a98d4db150842661768be84c68507a5c45d207840b033537786cb21dadad5fbab9c5cfc1e3547de550d313631dd4fbb7ca8f71938627608d2ebf655db4325abf3ed504dc183058f9de1e449312d904c846a184a028f364c028b27eb4946427e31c21e1051df364d499f477bf51e7a8893183e5ecf77d513a1a76b1a6fdfb16be90d74be4c4345a4f9f87ee441a1022d67ee844789f21b0c31adcc0d95663cdfb40a895b922dce8069b932c802fd3ab1ef0ce6bffdcc5653b1cd5257e19a0951687e545faf4aa66065a55c4b4191e34e8047d6a4ab52d1b06c369a426ca2d16b51a0271f27f8d744c711fce3aad9d4ac038ee700e4e971b21ca489ff2b8c778a3721adf47c1ae5a41b9a27fa742fd0f18164ef3c26b8ae7d1fa29b7c0cc4683be65025c96537a12d5fcebbd05e930c3693ebbba0a78adf59d8a3b598a348eaa9f47caf531fe449652db5b20d68994e35afec2c25709055a1de26082e3912d497c647720a3f873621456e6a5b9eb613acb43b66d47d0b954c69e8fbf2c5e634c486e5724930e0b56a516940c8cb0e775274deff97cbb7759ce90a2b93e9efaa624e6b38a39849dca1df612736f:7878ab741ebae2747c7897cbb1d105482f37be2f5f91795232cdfbccc526608918e2756ddb7536b3680c162cf8a1ef38a341b9362bfe5d468b4bce21df234f0f58500232388d9aa4b5faf85b0233247e717fd16840de9bfd0ef86e01e61302775513e224125e0d20420ea949f6c26425f70077911f9711310cd6fd8bff27cdea11480c73e8f8b3c37641e7e8dd8607c1640218fec80a020928b93d4d557ebe82ec0bb17538867d2cb14d44d3ea727fdd52820b0da944de21cd5da303d776fe99cbc2648365e6a0a98d4db150842661768be84c68507a5c45d207840b033537786cb21dadad5fbab9c5cfc1e3547de550d313631dd4fbb7ca8f71938627608d2ebf655db4325abf3ed504dc183058f9de1e449312d904c846a184a028f364c028b27eb4946427e31c21e1051df364d499f477bf51e7a8893183e5ecf77d513a1a76b1a6fdfb16be90d74be4c4345a4f9f87ee441a1022d67ee844789f21b0c31adcc0d95663cdfb40a895b922dce8069b932c802fd3ab1ef0ce6bffdcc5653b1cd5257e19a0951687e545faf4aa66065a55c4b4191e34e8047d6a4ab52d1b06c369a426ca2d16b51a0271f27f8d744c711fce3aad9d4ac038ee700e4e971b21ca489ff2b8c778a3721adf47c1ae5a41b9a27fa742fd0f18164ef3c26b8ae7d1fa29b7c0cc4683be65025c96537a12d5fcebbd05e930c3693ebbba0a78adf59d8a3b598a348eaa9f47caf531fe449652db5b20d68994e35afec2c25709055a1de26082e3912d497c647720a3f873621456e6a5b9eb613acb43b66d47d0b954c69e8fbf2c5e634c486e5724930e0b56a516940c8cb0e775274deff97cbb7759ce90a2b93e9efaa624e6b38a39849dca1df612736f: +94d50915144c7e7dd0f85fef87eddc2206c1569ed1431c8c5a153e32e1cb2fb73bb098cf160f3aec3170b57d6add4f56739270e4b3a8ef7966ec30619b299102:3bb098cf160f3aec3170b57d6add4f56739270e4b3a8ef7966ec30619b299102:4d915f27332dd75051719a24ae8d0e9c30da790999e22d9b587ef20321bee4c07d0a12494ffe599f47f96925f5d92517fc3e5f041d0c709f2a9783125eeca6652997201c429aa6f1ce2f07a0d4a0a18cf20b3e9a4f7663ea5262cad8f949411b05ff5c5edd7b30b217d75d8c86c94e5f92c16734374e8cead61b0b27bb4bf5f43a313c1dd5b83e0ea933b6cadfedd7a64aa5dd5b5d02c695ea20e091fdaa72ef4e7ca40f38395be8bf7a255c6d06a632d7d785d9e047f232aa50fa14529f986f9ef9d7b580a03965b0154788822a225bb5ab3438b89a5c28744ab0bc0b2014e5796acb4935a81b02a04632acb88caa7e39e069c7c8e1758291094a53e362fcedaaa583eca766efebf69b38e8cde9ce58e012c60ec88e8c42beadfa838cfe440fa0c01d659c9634576d7d7a2d3a044f99c6e4263d4c0b374a388a2acf38eff29c777e9daa60d598035a7d9edf67a502c3f573207b119cacac3fa71e2a0207c601cc0dd637ef562bacc35c57042738f1f55815a5268082cd6a508292fa29e34e9645d87a1a2b6e58adb7f4a57fbb53e9213ef3dc873f29396258a1ea546fb5952ce343cee9bbb90c1cda72c65a7c8e40312b328e231920c233077dca34d04f9d89daa9a2f43459165fd102ff5643c7175230b39ec7c3c475650ef131609d3220f5a294a403b1e1c42cfa162cd426f0ae43fd6b7ab547a62b7d5f847403c4e5987953877158cfdee23c04f751c7c86d078e824ca63b5e65543e978b6b0cc689ef664412b01b8ff165e7dbde3c099bf4f34ebddcb4c4:59a1ce55f5a6badc1b9391263620542cfcae87a0f2b9502250cfe4bdcbf76c461977c334a48d916edebd56c21ce217c35a6444cfbfd3b11a3d48fa2edb6eb40f4d915f27332dd75051719a24ae8d0e9c30da790999e22d9b587ef20321bee4c07d0a12494ffe599f47f96925f5d92517fc3e5f041d0c709f2a9783125eeca6652997201c429aa6f1ce2f07a0d4a0a18cf20b3e9a4f7663ea5262cad8f949411b05ff5c5edd7b30b217d75d8c86c94e5f92c16734374e8cead61b0b27bb4bf5f43a313c1dd5b83e0ea933b6cadfedd7a64aa5dd5b5d02c695ea20e091fdaa72ef4e7ca40f38395be8bf7a255c6d06a632d7d785d9e047f232aa50fa14529f986f9ef9d7b580a03965b0154788822a225bb5ab3438b89a5c28744ab0bc0b2014e5796acb4935a81b02a04632acb88caa7e39e069c7c8e1758291094a53e362fcedaaa583eca766efebf69b38e8cde9ce58e012c60ec88e8c42beadfa838cfe440fa0c01d659c9634576d7d7a2d3a044f99c6e4263d4c0b374a388a2acf38eff29c777e9daa60d598035a7d9edf67a502c3f573207b119cacac3fa71e2a0207c601cc0dd637ef562bacc35c57042738f1f55815a5268082cd6a508292fa29e34e9645d87a1a2b6e58adb7f4a57fbb53e9213ef3dc873f29396258a1ea546fb5952ce343cee9bbb90c1cda72c65a7c8e40312b328e231920c233077dca34d04f9d89daa9a2f43459165fd102ff5643c7175230b39ec7c3c475650ef131609d3220f5a294a403b1e1c42cfa162cd426f0ae43fd6b7ab547a62b7d5f847403c4e5987953877158cfdee23c04f751c7c86d078e824ca63b5e65543e978b6b0cc689ef664412b01b8ff165e7dbde3c099bf4f34ebddcb4c4: +0d81926f513db4b25dfa1e52b5dca678f828a61c7c913c828247c2eb0422b7d10f32411ef91d4e4b6941dfcaab142ef3bec160983993a5262ccf27fadd2af890:0f32411ef91d4e4b6941dfcaab142ef3bec160983993a5262ccf27fadd2af890:a93837522f7ec2e93a2e4b4c8b46de926a81ada2d248bcd33b39b6c95fb62a61dbbeda1aa85a21d9b96a08510d8d3a658cf320a10928695999d2c0d605c7f95a12f56a8718507db0f497e3ead613132ab092cbf19d2260358630358d9b26e68d50ddae37c8af0bb7d2741fd2929c21279a78d10e2c5f3c5bf4a42a3617036d54743647765afd8cd910f81b38ced72390630ee68944a37d29c2fecada1cc59ec544075bdbc14c63c6234b884049000c27c73406035604fca8760b49a5e2109ef91285adc4ec48c819d62d948faca90f62cfaef0b07d6fe576d762bfd0eef94cf6b5332c4d422511607f2facc7ac046a59b9617e8383d1029cc91ac592b52084413032be841baa9bf96251a6bda671d4cd4b125da658a4e5a50f4428eebf2614fb0ce5febe80f721a5f4c0325506d27a8d31e33d86253870dd63c08edc7302b280e9b9bdc28beef05c7dcb30d4c162e9be832e1c785e37551218421eec852c4298213b2f27f8f8c706d391b9c69a56db7ce5d81548fca5fed456f2d8afd0b75f79f85868316f4a0921f0c6639926516b3c3e52a9cb22554546ef70e14c77ecbdcd5c0d59a81769b30d5d131f2fb449c996b8de8ac7f8084f8499e1a56f7cd29db6aaefccae8a60e75616a1f702c3bc8deaa1004a8dae0392a59cee54810c6e940eee25fb2e5d573267044b893ffde378fe75ac2613373d84a0ca8187af4a3358e50a994ed03367de645e10390fea4c33bb1a6c0c39858b8db4a69fe894a4223d45af69b36c6117c4dc25de49a63017002ba9ae551ef9:e0cb6c71ebf8d705e50cad9f0b8cba3ecf4b9e3793400092aa5b121e7dbbc8bea71df29528ca9b47abf87c198a8dc4e14d5180ce932dd2114a3cdaa5552cc205a93837522f7ec2e93a2e4b4c8b46de926a81ada2d248bcd33b39b6c95fb62a61dbbeda1aa85a21d9b96a08510d8d3a658cf320a10928695999d2c0d605c7f95a12f56a8718507db0f497e3ead613132ab092cbf19d2260358630358d9b26e68d50ddae37c8af0bb7d2741fd2929c21279a78d10e2c5f3c5bf4a42a3617036d54743647765afd8cd910f81b38ced72390630ee68944a37d29c2fecada1cc59ec544075bdbc14c63c6234b884049000c27c73406035604fca8760b49a5e2109ef91285adc4ec48c819d62d948faca90f62cfaef0b07d6fe576d762bfd0eef94cf6b5332c4d422511607f2facc7ac046a59b9617e8383d1029cc91ac592b52084413032be841baa9bf96251a6bda671d4cd4b125da658a4e5a50f4428eebf2614fb0ce5febe80f721a5f4c0325506d27a8d31e33d86253870dd63c08edc7302b280e9b9bdc28beef05c7dcb30d4c162e9be832e1c785e37551218421eec852c4298213b2f27f8f8c706d391b9c69a56db7ce5d81548fca5fed456f2d8afd0b75f79f85868316f4a0921f0c6639926516b3c3e52a9cb22554546ef70e14c77ecbdcd5c0d59a81769b30d5d131f2fb449c996b8de8ac7f8084f8499e1a56f7cd29db6aaefccae8a60e75616a1f702c3bc8deaa1004a8dae0392a59cee54810c6e940eee25fb2e5d573267044b893ffde378fe75ac2613373d84a0ca8187af4a3358e50a994ed03367de645e10390fea4c33bb1a6c0c39858b8db4a69fe894a4223d45af69b36c6117c4dc25de49a63017002ba9ae551ef9: +6c8c53b56bbcb4c0a25dc40c18240b6a5c7576b89dde45ef13fb158ea17f8ed9238e51d6a44fa7ac64268801261ea35b62638a006cc452bddb9f16fc5803060c:238e51d6a44fa7ac64268801261ea35b62638a006cc452bddb9f16fc5803060c:b60df2944ba015759802d3c587bcfebe521a7e77b9985b761c9676454d24a664af0b0d44225a557512e1c1cd7dd8335c8f6adf928e18f89fd5eedf6f411dcdaf996912e8c3e23d1cb95eca4b9e24e7539c3b98bf3d07ec251392096c19ac5374dcba526132b6d9bb8f6c859ce985d584c7bba5b02a81034b6d8b521bd280e50d77daa2b2413ed679834f8161d5d0573bdd476ac3cd0a3a7d8db45334e89c00ab66bc368a07b423e246434636272aa4e4637a5306b2c3397992781f30238de79ec104acc7200defad960883d391443e70efbd22f1cfceec5112fe9e8e13bb941c083468dd71ffca976cd51ce161793110ef00aff5ee2ccb7706a512b85beb94ac49d19afb6333655cf3aea535a6f9c75e034841e763c5a249b4704e1be78b0ecac6802c343c1b7e7b5770de4c93a3a79c46e6835da8ae5db3838e1796b564a480a4f290b60a1c63a725ff3fef434d2a0b3d8931978742b525c83bae6794ae64193794b370c289ba35ed79d37072a8dcfcadb46d5ffaeeba1bfd4f87d766b504e62b4acdd77446e79ba994d6dbf4765ebd74b0365100da56162c36fe5a95077f6b4265e81796b4a57443782970b96cb4569ba985c55fe3a718380bca39f16624f8e47cc63c1b6fa1bde1aeba9c51f94b702b13108cc1481d42e6fa981e3ebfe064d2dca7420c74595792312ae3fb9101d4b66d9916dfd6c13ae883e661c628228be9794cf60345076db26184b617e272298cd4183f27bd52d40510bb015d2097d4cc76e76c0a62bbfdaf53c7268775bbfbdb8870eb9bab:4bf1e7d49cd4d5c3c1fd4a4bc48ff6b6e52fd9510a411812296996e4fec56be44514c567d1d33477bd5dc083c3958bd95bfe599c153f21ae26252967b7326003b60df2944ba015759802d3c587bcfebe521a7e77b9985b761c9676454d24a664af0b0d44225a557512e1c1cd7dd8335c8f6adf928e18f89fd5eedf6f411dcdaf996912e8c3e23d1cb95eca4b9e24e7539c3b98bf3d07ec251392096c19ac5374dcba526132b6d9bb8f6c859ce985d584c7bba5b02a81034b6d8b521bd280e50d77daa2b2413ed679834f8161d5d0573bdd476ac3cd0a3a7d8db45334e89c00ab66bc368a07b423e246434636272aa4e4637a5306b2c3397992781f30238de79ec104acc7200defad960883d391443e70efbd22f1cfceec5112fe9e8e13bb941c083468dd71ffca976cd51ce161793110ef00aff5ee2ccb7706a512b85beb94ac49d19afb6333655cf3aea535a6f9c75e034841e763c5a249b4704e1be78b0ecac6802c343c1b7e7b5770de4c93a3a79c46e6835da8ae5db3838e1796b564a480a4f290b60a1c63a725ff3fef434d2a0b3d8931978742b525c83bae6794ae64193794b370c289ba35ed79d37072a8dcfcadb46d5ffaeeba1bfd4f87d766b504e62b4acdd77446e79ba994d6dbf4765ebd74b0365100da56162c36fe5a95077f6b4265e81796b4a57443782970b96cb4569ba985c55fe3a718380bca39f16624f8e47cc63c1b6fa1bde1aeba9c51f94b702b13108cc1481d42e6fa981e3ebfe064d2dca7420c74595792312ae3fb9101d4b66d9916dfd6c13ae883e661c628228be9794cf60345076db26184b617e272298cd4183f27bd52d40510bb015d2097d4cc76e76c0a62bbfdaf53c7268775bbfbdb8870eb9bab: +69b320fbd4774030a29767a0cc1550d10b749b44d619d41dce1146f7ac80a755dc508a79c6b8ab866cd117a5a84dd9d931fda450bec29335344d0d219216d65e:dc508a79c6b8ab866cd117a5a84dd9d931fda450bec29335344d0d219216d65e:217e33f88622c96f8d092c9e26664fe9efc0d8d2eb59a036fa464cee65ce4489caf903dce17afafbc4f18dc9bbfd6c1a4be7b83485a6ca947defb1d35125d0773962a344a38b6dca9a40c31c1c4eb2d7f6818f978e573d66b990921b92b777471a4f6f05477ebc353ace1d86b00cc251777aaf6af3aa1179bff78df5048e5ef29968670e535483568d6bb16da829568f81c799b9afd4aad6ef085252c0ce3ac01ac21a9ea69bd58eadc66968f55dee386b653f3334efc398ef3c37a38ce93b21f107cc54dec26f53fee5604eb09a36afe6b665b6324a84c7da7b7dd01d9278e472f15a5ce9ff0fd93d0aa0604dd2df8d5bf6a912734ec51de77f0ce099ba11670210a6a206106b0ede2ded858a6bc411e7613e6f80e1aa52c323e30fa849951cc9b776e4cc58c90cfc8f442df64151a7fd4a3dd61a4336da21d03944635d3fd667be741ef45b1f7cb276d9f4de8107de64582f7917c6eab38e0a8890a4bee48bc92617a361cc7b1d25e089453ce0a52544f868dcb3249de761e79df63efa0794e3c4618c554753ee281c52ac8ad78d5338f0dac360a769381bb4a39f190b887b4723806ac4a4f2ff304bc6f9337ab54c866e6ba51df50c43eab52e2b39794c9917e0c31433f03681d2f1d93a0436018caaae20206a3458ad6c037acb511ef128f6dcd05305f07049a13b6c6c3c5b8170f158c8f12d46e160931ba18bd59ae129ec07a0655fa482ebbd3b850d36b832bbb775f538e3c1b3a43ecf94ca630ca15d502813eed3e35e8fd23d2ab638600427d1597cb29da2a5:697d4d897e0e2cc02bc1c2dda57f0dda620b37e861822bb7f1a701935e959ea0d8453f746fb92c087ed65d980eea1d6fdbf23e99b289aae0dcbb128ef836640a217e33f88622c96f8d092c9e26664fe9efc0d8d2eb59a036fa464cee65ce4489caf903dce17afafbc4f18dc9bbfd6c1a4be7b83485a6ca947defb1d35125d0773962a344a38b6dca9a40c31c1c4eb2d7f6818f978e573d66b990921b92b777471a4f6f05477ebc353ace1d86b00cc251777aaf6af3aa1179bff78df5048e5ef29968670e535483568d6bb16da829568f81c799b9afd4aad6ef085252c0ce3ac01ac21a9ea69bd58eadc66968f55dee386b653f3334efc398ef3c37a38ce93b21f107cc54dec26f53fee5604eb09a36afe6b665b6324a84c7da7b7dd01d9278e472f15a5ce9ff0fd93d0aa0604dd2df8d5bf6a912734ec51de77f0ce099ba11670210a6a206106b0ede2ded858a6bc411e7613e6f80e1aa52c323e30fa849951cc9b776e4cc58c90cfc8f442df64151a7fd4a3dd61a4336da21d03944635d3fd667be741ef45b1f7cb276d9f4de8107de64582f7917c6eab38e0a8890a4bee48bc92617a361cc7b1d25e089453ce0a52544f868dcb3249de761e79df63efa0794e3c4618c554753ee281c52ac8ad78d5338f0dac360a769381bb4a39f190b887b4723806ac4a4f2ff304bc6f9337ab54c866e6ba51df50c43eab52e2b39794c9917e0c31433f03681d2f1d93a0436018caaae20206a3458ad6c037acb511ef128f6dcd05305f07049a13b6c6c3c5b8170f158c8f12d46e160931ba18bd59ae129ec07a0655fa482ebbd3b850d36b832bbb775f538e3c1b3a43ecf94ca630ca15d502813eed3e35e8fd23d2ab638600427d1597cb29da2a5: +66da8b254a37067378f68138afedd66496596a0585524c716bde2b3124c3e7d185bde28a922ab5eeaa4a6294521a2ccac0ef2303dcdf8c7fee228fb4552012e7:85bde28a922ab5eeaa4a6294521a2ccac0ef2303dcdf8c7fee228fb4552012e7:3fae36638837d0edc8dcee517e43c488ed57fa6c9853a745aaedfb109ec1409fb8a2fe51d23e0dd9fbfd94f91c18e6114d808901bf617d2667ceebd205c5c66f5d7534fd2ec33dbfe580ad919f504204eaf242af8700b138cfbe0f372919c06b861a27d720d09df20f4fb7b748e718b0fc486dbdfcb694cb3f1420035ac1be55d31f30f997a043d04708a5c542ee37c0f7fe0b3211d18a87033dcb15c79e6681c4970593d32a13c48f0a3af8bfc136e0f9b56a123b86c4c640b650cb7dee9a89e82aeeee773b5cb032fca41c20c407328bfed29244e46055a83114614d3db56581604b115fba14f618e102a1e16cb036ea69df9275b977a0858118c91a34b9a8519bd0dac3b61434ea088f381ba08bc1583189a4a7c8b6ad18f732d74eff3acef4b6904df58c6469432151372df9327ae71a0f356c94468dcfc2e4a5c0e4ec0b166d90cd465f9260ebd6a7a62ce6c715bcc715be0c7e1f28c4456012d33177a7d4113c9a5a22acfaf2d6b63309078fc1b1baa8f36c7e866c1f972a6500a5eea79201651a7305208b6c93c492bc77cacbc99c9cded179e664a2f4e16938cc26fca8b433eb8012f7b3ad19ba1fb858fe4a00fb3d1f8fd0eddf0c37dcdb2e5d35c2546f22e8c0f8ce90e2df8abf24827a019b2c33fc590bbe712f019287002bc2217c0dc0931dc8ed8f50bb442f8b2de27857362ce5a9fd97f0fd1b2b9251cad2a4aca1a94de2e953902d7228142407443b1d517107648a7bab83074987d0978bc61d419bc84591c969c3d6f4e86fc4738737bc0558755c110a:4082a5bc730fb54b6bd0bcd2a044ed5d3d327dc19ceac8825e629b9e6423cb1c614236f097a6b73d473947cb81c4e270852ee5f13a5b03dc18e1c9c27a9a68023fae36638837d0edc8dcee517e43c488ed57fa6c9853a745aaedfb109ec1409fb8a2fe51d23e0dd9fbfd94f91c18e6114d808901bf617d2667ceebd205c5c66f5d7534fd2ec33dbfe580ad919f504204eaf242af8700b138cfbe0f372919c06b861a27d720d09df20f4fb7b748e718b0fc486dbdfcb694cb3f1420035ac1be55d31f30f997a043d04708a5c542ee37c0f7fe0b3211d18a87033dcb15c79e6681c4970593d32a13c48f0a3af8bfc136e0f9b56a123b86c4c640b650cb7dee9a89e82aeeee773b5cb032fca41c20c407328bfed29244e46055a83114614d3db56581604b115fba14f618e102a1e16cb036ea69df9275b977a0858118c91a34b9a8519bd0dac3b61434ea088f381ba08bc1583189a4a7c8b6ad18f732d74eff3acef4b6904df58c6469432151372df9327ae71a0f356c94468dcfc2e4a5c0e4ec0b166d90cd465f9260ebd6a7a62ce6c715bcc715be0c7e1f28c4456012d33177a7d4113c9a5a22acfaf2d6b63309078fc1b1baa8f36c7e866c1f972a6500a5eea79201651a7305208b6c93c492bc77cacbc99c9cded179e664a2f4e16938cc26fca8b433eb8012f7b3ad19ba1fb858fe4a00fb3d1f8fd0eddf0c37dcdb2e5d35c2546f22e8c0f8ce90e2df8abf24827a019b2c33fc590bbe712f019287002bc2217c0dc0931dc8ed8f50bb442f8b2de27857362ce5a9fd97f0fd1b2b9251cad2a4aca1a94de2e953902d7228142407443b1d517107648a7bab83074987d0978bc61d419bc84591c969c3d6f4e86fc4738737bc0558755c110a: +276548290f3e0f900515dc63366c03fe0fc6ee130c21fb60a4df9cf464797cda7e2a3578000a087edcc9e94fde509fc4be05ca0dd090df01ae1121123536f72a:7e2a3578000a087edcc9e94fde509fc4be05ca0dd090df01ae1121123536f72a:f0db442de29a7a1ded550d120002cc12abfff98b1f576d65bde16deaba687e4e0b0d5a8748d7503da2969c64d6a7c28d27b6c93ad257ce32ecdaee375f43fff97c432d453f7196c709c3bdfb7388d4d8eaf139f182940ce17b4552e2d20aed5557ba4d2acbf845730c0a66b45b40950baf6a946437af6c9e3b33a79e04dceae57c2a549542eabd216bf13948d41ffb9483fe29801fc8c1782840deeb3fb4da3192785bca13ed0a9eff57d6136bafbf9dec697b832447b2b6e730fa7f9995bac6b7832eaa09905ee49d465a5ee450f52d1a6d364c618144e886e8ef633dc79d0af893d16b3eeda0fefefd8759f2a0da1930170dd19eb78f0d7a7b74515403375a95bdbcce018bc1edb08d897bb798a95e7e86a52af3d9b8a4a14b0371d63498dcb2016248ebd0be800e9f21d549e5e0e7b4895ca5cb725a0cab27da8a8b1299be38a4260900ae10df5baba11ae2bab7179dd8453969429ccc4d416055f2bcb93c1cac6d7e804cf812df1462f22ee9e833a9769e8e677550402c4094df212fd2c5fcc09a72c7ce0077510073090d0e63db637d43d4c21f8619d34da5db08033f686ce8b8a0821222f95434ac4e6f703094edded6fb1b846e979650979d3c77453f40f7fee7c3e88a96fd1d702e81c2a4f3f3753c7964842dfd9d3958a743da063d1d648e51b210a28ed2487f14d5f1bc6f339b2dd17a661c39736da99e4a4f07360342d237e3813ea3998d66eb31a2d708af065c32b927f757c37a800660674e9717ba58f280eb2aa464fa74402108a5d5662e8d0feaf329687a:88a146261ad111c80fa4299577e710f6859cf0d1ca80e512a552c725b8384037eecf6465ce97585c9d660a41ab9104e5f7c9b2f8ec6fb21f1ddd50d65b9b660ef0db442de29a7a1ded550d120002cc12abfff98b1f576d65bde16deaba687e4e0b0d5a8748d7503da2969c64d6a7c28d27b6c93ad257ce32ecdaee375f43fff97c432d453f7196c709c3bdfb7388d4d8eaf139f182940ce17b4552e2d20aed5557ba4d2acbf845730c0a66b45b40950baf6a946437af6c9e3b33a79e04dceae57c2a549542eabd216bf13948d41ffb9483fe29801fc8c1782840deeb3fb4da3192785bca13ed0a9eff57d6136bafbf9dec697b832447b2b6e730fa7f9995bac6b7832eaa09905ee49d465a5ee450f52d1a6d364c618144e886e8ef633dc79d0af893d16b3eeda0fefefd8759f2a0da1930170dd19eb78f0d7a7b74515403375a95bdbcce018bc1edb08d897bb798a95e7e86a52af3d9b8a4a14b0371d63498dcb2016248ebd0be800e9f21d549e5e0e7b4895ca5cb725a0cab27da8a8b1299be38a4260900ae10df5baba11ae2bab7179dd8453969429ccc4d416055f2bcb93c1cac6d7e804cf812df1462f22ee9e833a9769e8e677550402c4094df212fd2c5fcc09a72c7ce0077510073090d0e63db637d43d4c21f8619d34da5db08033f686ce8b8a0821222f95434ac4e6f703094edded6fb1b846e979650979d3c77453f40f7fee7c3e88a96fd1d702e81c2a4f3f3753c7964842dfd9d3958a743da063d1d648e51b210a28ed2487f14d5f1bc6f339b2dd17a661c39736da99e4a4f07360342d237e3813ea3998d66eb31a2d708af065c32b927f757c37a800660674e9717ba58f280eb2aa464fa74402108a5d5662e8d0feaf329687a: +972c0616556ef22c214868fdd822c55739e1f96a93ae83512afda9ca7aa74cd29e1c6d4107f8ab8161c5db5b88a37ca1de9f4e291367abb1efc84f83f7076953:9e1c6d4107f8ab8161c5db5b88a37ca1de9f4e291367abb1efc84f83f7076953:8689e2f95c8fd50dc44664a18fb1a9f2c8f3ee73c0f9587ee28bfa35c9231c75bfd3d9534174e5ad3fa9f092f259942a0ff0ba2ca2cb59043d192ca8e3c8869bedd2354cbc5ac782d727c0b69407f68d1326df65a60c4d32f87f19a10f3d765ff923434f5511d134d397c4fef6bb1953abfce60827c359aa4b54f912aa8b17b83dcc7e3bcbc505ba046fe57c16dacf4ee2fad538bc06817c9b9d8dbc5f9d9bbf9f4a934f14a42c29e0e2f3a49f46b20ee76cfe20dea1e97450eb6a8fda048168dd827810207f005a3caa93ca11f4ee608a7a9355494313aec8d7075afc94c7cccc75c2319bb458c0ce373e9d007f753b33b52793d58496b2d25cd1dcd7832aac5ddb38f4db19c427219e1a0420ead47ba95ab6d89c65939041cc734c08eb6b476caf7fc76c598d947ff444b10770f62945ae65044f78098299e2626b638a7328d1b7daa5889e8db94bbff2ded62e14463760227c3f326ed493565ddf0a1761b8e4bb7d2410fa0fdbf35684397eefea95895889a0a9dffc5e02c092383b7ce74d2d90939916f26b71afd265f8bec74f0de247c9643905583df3cee23537d6b568c8338ce5fee42f7dd15dad5247f009acbfd5d769b6366959cd0ae150f58f7c80fa10d989ed90119372e5fea5da48a4e8ea9c727875dc4a2005b0dc2e3f697c0ce0a4bdb2f750c04fbc0c27d02dd8286e54c9c3959b6ffbdb1de2affe9e782651e5168a500afed037b3e1790ddd593851a6a6ccca9fffb4a99e27df43818871536ab04f14a06a1c7cb47bed6241ce7430ad3e640a726752fa06a9:54dd06fbb3d7c63f8cdaf783c2d7bac16b4c826e2d1b1807c84e049f64e271b21cfa3e37c344260287805d718806b62c56b47f6d5c508125c9fb5d5ea35fd5018689e2f95c8fd50dc44664a18fb1a9f2c8f3ee73c0f9587ee28bfa35c9231c75bfd3d9534174e5ad3fa9f092f259942a0ff0ba2ca2cb59043d192ca8e3c8869bedd2354cbc5ac782d727c0b69407f68d1326df65a60c4d32f87f19a10f3d765ff923434f5511d134d397c4fef6bb1953abfce60827c359aa4b54f912aa8b17b83dcc7e3bcbc505ba046fe57c16dacf4ee2fad538bc06817c9b9d8dbc5f9d9bbf9f4a934f14a42c29e0e2f3a49f46b20ee76cfe20dea1e97450eb6a8fda048168dd827810207f005a3caa93ca11f4ee608a7a9355494313aec8d7075afc94c7cccc75c2319bb458c0ce373e9d007f753b33b52793d58496b2d25cd1dcd7832aac5ddb38f4db19c427219e1a0420ead47ba95ab6d89c65939041cc734c08eb6b476caf7fc76c598d947ff444b10770f62945ae65044f78098299e2626b638a7328d1b7daa5889e8db94bbff2ded62e14463760227c3f326ed493565ddf0a1761b8e4bb7d2410fa0fdbf35684397eefea95895889a0a9dffc5e02c092383b7ce74d2d90939916f26b71afd265f8bec74f0de247c9643905583df3cee23537d6b568c8338ce5fee42f7dd15dad5247f009acbfd5d769b6366959cd0ae150f58f7c80fa10d989ed90119372e5fea5da48a4e8ea9c727875dc4a2005b0dc2e3f697c0ce0a4bdb2f750c04fbc0c27d02dd8286e54c9c3959b6ffbdb1de2affe9e782651e5168a500afed037b3e1790ddd593851a6a6ccca9fffb4a99e27df43818871536ab04f14a06a1c7cb47bed6241ce7430ad3e640a726752fa06a9: +e0405d37893e89f53811d6d446e1f193f51afa1bbba725f95eb48033424a250945104d595e443e8ce654de9d655054bf0a99d35613d77d57454ca2d1c899b517:45104d595e443e8ce654de9d655054bf0a99d35613d77d57454ca2d1c899b517:df58c4fd0702a20fafa3d1d4fe7d85938b120fc11e8d41b601f0e60e42236a49f126813bd512ee71359061e13eb314d417f56d6d560285fa8991213284c42bc2cef2dc937bdc0b5e9dc2269afab32db30e6849855951cfbc53ecfa01643863e0328995fe850c0db55421bfa564601b8c9db7552c7e6aa7adfa15a58021a84266e9595c65fca4a15fa70f55f5d212c9e277ffb830f4cad1861f3f495a9d672f5691310639c12dcd07e3ef17a23750bcb46b7ad7eac462eb512225f3be7e32f8f4987a11df341166062b43c63ab858a600497667fbb88e93c7e2e0aab41c09c023eb902ec3baf679e25b96e106921a914fd5de200a47889de23e7b65d0ccdf0c29036467a1210c0030309a2d04ec256d5a4d8b97d46a3e15f345b667170803cdacf6cb48add0a13462dd30fa062bd4566641da07d7f61e063686edd96bfe8f97b986b7c0e44249cd2d7317472999b8ee4ea80c902f3b188936712e89d8bf02ce8ae77b6b31abb0632065455ddd9f9d1cd953a4a49aac1a15169e687d4fd3f7c2edfb3aabc3b66155f7d315f8a294faddffdb4951367a0cb870759e85a838af66ba3fc103da2babc3f381696ef8882d85a8278d5fac3a72f16eb119ee9900b1fd986c2a9f94eed8e0d4f273697e4363a975ff6a7b80d5b4ec5355bf63b42b71cd4842401d38b5e00cc97bfda40e456653683bc8e6dade7dcf985a97b0b5776c4d72ca13a1474e4eb2eccfcd428786ddd0246d73a6377a79cb8da720e226c19489bd10cedde74b49fac2cfa207129c6a108aa164be9d809c4d31147360:77ddd491ca662ebffb12f7f492d7fbc1a1b447f6c85998f2f7cc9adce67de63b6eebd08117845a0302f7349714ba9db2af58048b85837d7660ec3debeee2d00fdf58c4fd0702a20fafa3d1d4fe7d85938b120fc11e8d41b601f0e60e42236a49f126813bd512ee71359061e13eb314d417f56d6d560285fa8991213284c42bc2cef2dc937bdc0b5e9dc2269afab32db30e6849855951cfbc53ecfa01643863e0328995fe850c0db55421bfa564601b8c9db7552c7e6aa7adfa15a58021a84266e9595c65fca4a15fa70f55f5d212c9e277ffb830f4cad1861f3f495a9d672f5691310639c12dcd07e3ef17a23750bcb46b7ad7eac462eb512225f3be7e32f8f4987a11df341166062b43c63ab858a600497667fbb88e93c7e2e0aab41c09c023eb902ec3baf679e25b96e106921a914fd5de200a47889de23e7b65d0ccdf0c29036467a1210c0030309a2d04ec256d5a4d8b97d46a3e15f345b667170803cdacf6cb48add0a13462dd30fa062bd4566641da07d7f61e063686edd96bfe8f97b986b7c0e44249cd2d7317472999b8ee4ea80c902f3b188936712e89d8bf02ce8ae77b6b31abb0632065455ddd9f9d1cd953a4a49aac1a15169e687d4fd3f7c2edfb3aabc3b66155f7d315f8a294faddffdb4951367a0cb870759e85a838af66ba3fc103da2babc3f381696ef8882d85a8278d5fac3a72f16eb119ee9900b1fd986c2a9f94eed8e0d4f273697e4363a975ff6a7b80d5b4ec5355bf63b42b71cd4842401d38b5e00cc97bfda40e456653683bc8e6dade7dcf985a97b0b5776c4d72ca13a1474e4eb2eccfcd428786ddd0246d73a6377a79cb8da720e226c19489bd10cedde74b49fac2cfa207129c6a108aa164be9d809c4d31147360: +5756e752dff69e3eed848e4a49c7a8baca12154f9431dec35626ef8d75a445145910ef00a5b354143c46561da62c41aa13d29c18dc6153bf8e502e0114007728:5910ef00a5b354143c46561da62c41aa13d29c18dc6153bf8e502e0114007728:eb2190a3219c792b6666b2752733ad9f86fc390155c4b438be196959383b25f3a749530d5a4b15ebe2c18d99178e6d45bb4aa2120f95a352e0406c63ac867248d9efba124231064873c82fe995dd031c7cbc7d15ec191fbb6c474dc4c777e8f457841eb4624841c152d15ede26e78479a6a25ffa335563f1064ef09558b910e2608418820f49554b670c6bab34d1d60984dea50ed6a375f45a74beadfb04bd9300bd594e2e20ea5d3052bb7ddc51a949a0047972682ebe66d38aac62927270de42150d58221d03b8ace3589933487bf23d29c5c2c843aefa2e1ca22f9d1680f80c766d143ce5ecef253a745cb71e72f6504ad911f7cb4a819cd074863a92706929a3142f8db7ac164102ac2ca0d2e19a725e1b5f81f443c73e0484f26a45a3aef84f1f3fa04a4ac695d2dab6efba456a281a3973cc186e680a66df521a4d1f9edf4dfb274a427097bf863281cfb0ed80f8d7676638d6cdac937843efbcfce91de1df6c52b594571b9315600e4b6552defb8437a807ba21298e3d972212ba314692917f40075311acd009395241b9f1b256c515735dc674f8e866d1eeb4c328548aee71231c4c9d5bd22e39de88d19fabf49f0b9869cbf835214b15522a93d3a5007b11f0b50e5228d4eebb4571b35da84f4f687e3f43793d54f3825b37a509ea564bdf217ff4adf6847bbea4316a1dbcc7448ecd5363eaabc128decf054ee1a0ee2d871979f8a63b2692b09f6e986a138e7f68f60aa426a1c9b01a4902e13b17bc8312410c28bed29b601b0fc9f3bc2d223f875251100f869c6b5844:8157d8334ded1a32699b350ac0d4120028cd8ef8189448934850e50ee4999d8fa2cd257646d92fba5d662a823e62208ab4fbe01714a848a0b90b55adcd246902eb2190a3219c792b6666b2752733ad9f86fc390155c4b438be196959383b25f3a749530d5a4b15ebe2c18d99178e6d45bb4aa2120f95a352e0406c63ac867248d9efba124231064873c82fe995dd031c7cbc7d15ec191fbb6c474dc4c777e8f457841eb4624841c152d15ede26e78479a6a25ffa335563f1064ef09558b910e2608418820f49554b670c6bab34d1d60984dea50ed6a375f45a74beadfb04bd9300bd594e2e20ea5d3052bb7ddc51a949a0047972682ebe66d38aac62927270de42150d58221d03b8ace3589933487bf23d29c5c2c843aefa2e1ca22f9d1680f80c766d143ce5ecef253a745cb71e72f6504ad911f7cb4a819cd074863a92706929a3142f8db7ac164102ac2ca0d2e19a725e1b5f81f443c73e0484f26a45a3aef84f1f3fa04a4ac695d2dab6efba456a281a3973cc186e680a66df521a4d1f9edf4dfb274a427097bf863281cfb0ed80f8d7676638d6cdac937843efbcfce91de1df6c52b594571b9315600e4b6552defb8437a807ba21298e3d972212ba314692917f40075311acd009395241b9f1b256c515735dc674f8e866d1eeb4c328548aee71231c4c9d5bd22e39de88d19fabf49f0b9869cbf835214b15522a93d3a5007b11f0b50e5228d4eebb4571b35da84f4f687e3f43793d54f3825b37a509ea564bdf217ff4adf6847bbea4316a1dbcc7448ecd5363eaabc128decf054ee1a0ee2d871979f8a63b2692b09f6e986a138e7f68f60aa426a1c9b01a4902e13b17bc8312410c28bed29b601b0fc9f3bc2d223f875251100f869c6b5844: +b904acb19e5cf872d3640cd18ddf3c0b6657e0117ce659dbf50259015d3fbf32e04a8aa56d1818483b10d0a7c919e1d5d8001e35510e1ec62f7114dbe81ae0be:e04a8aa56d1818483b10d0a7c919e1d5d8001e35510e1ec62f7114dbe81ae0be:83f4124d5af955139b1bc5441e97c5fac491b4ea911407e15420a0347ed7fa1f8819e36c8ed5740c99d4505a78b619d560749af50b0573510816d61322cda976a5d4ca3205f5f0e60e759a5df1a0bdf36dfe9717906ac57cbfc970ab43b6fa18e6c0006c84fc7254470a0b774727bf5f8e679423a531e41cb5310f9bcbf5a5445ebc39fbd909ce11e97bc2f66a4a1bb6c2f167f2c6e80eb9b8b72df3e8cfd4e51448dc14c0b837f2949693d1d054c8f95bff7f1e364567d034f2223e1594772a43dcfe0597fd6d133b3f2e96ffc5667dd5928f23ec3c750f845993a34e9776159a6830d6fd9013ee7aeaa1fccd69b96df284704fd08888b15b64e2e90d578c5cfc0f95693f6ab65c6947446a857c029c7ca66080b754c7734b78998abe9b7cc6efd09a4418194d88b34ec6c33af630db81de5b99fe65aac8b73362379119c700d107edfc19f270760468ee8e5f155d9a347e57b5930f327a8d11c6674ddd020f9e7d9b761dba5b83a87302f1833e5abd49526d66391e5bf0e35b4453d630bf7d0adbfe501aef81e6c5938f92cb752f5f14d2806f90ae1546051ccc7f913c5d6a38ff3b7b9a23662ef1f00808edb2fa31ecba5c8d3387e87541cd0616edbf3aaa35a537922861f44cbd9f992b8246d9c64c419881701ab43f7fd464210d802ba656d95c0f24a34599b20b1ec20011485cfcb3186b7bcf69d74581a7a3eed6134c4eecd65574a4320d9c57a849c4e78c8a5ce82505004a54f19d4bdc8223401b34946b7d66e47e63cf9d0f57d0945491384bc6868c4b478690e550021df1:9aaf8ac97140d5508d58f5ac82b7fd47e6b1f68a7c78a2ac06f0416ef8e991953f62c47fd5fbc6c1e01bae1c92a33ef52b7efa5f17bb8633bdc1aeebce318f0f83f4124d5af955139b1bc5441e97c5fac491b4ea911407e15420a0347ed7fa1f8819e36c8ed5740c99d4505a78b619d560749af50b0573510816d61322cda976a5d4ca3205f5f0e60e759a5df1a0bdf36dfe9717906ac57cbfc970ab43b6fa18e6c0006c84fc7254470a0b774727bf5f8e679423a531e41cb5310f9bcbf5a5445ebc39fbd909ce11e97bc2f66a4a1bb6c2f167f2c6e80eb9b8b72df3e8cfd4e51448dc14c0b837f2949693d1d054c8f95bff7f1e364567d034f2223e1594772a43dcfe0597fd6d133b3f2e96ffc5667dd5928f23ec3c750f845993a34e9776159a6830d6fd9013ee7aeaa1fccd69b96df284704fd08888b15b64e2e90d578c5cfc0f95693f6ab65c6947446a857c029c7ca66080b754c7734b78998abe9b7cc6efd09a4418194d88b34ec6c33af630db81de5b99fe65aac8b73362379119c700d107edfc19f270760468ee8e5f155d9a347e57b5930f327a8d11c6674ddd020f9e7d9b761dba5b83a87302f1833e5abd49526d66391e5bf0e35b4453d630bf7d0adbfe501aef81e6c5938f92cb752f5f14d2806f90ae1546051ccc7f913c5d6a38ff3b7b9a23662ef1f00808edb2fa31ecba5c8d3387e87541cd0616edbf3aaa35a537922861f44cbd9f992b8246d9c64c419881701ab43f7fd464210d802ba656d95c0f24a34599b20b1ec20011485cfcb3186b7bcf69d74581a7a3eed6134c4eecd65574a4320d9c57a849c4e78c8a5ce82505004a54f19d4bdc8223401b34946b7d66e47e63cf9d0f57d0945491384bc6868c4b478690e550021df1: +8a3501b76953603c9033e3bcbf3ec378d257011a6c50b89762d491eaa72c5e0d778f2019dcd8dbb86c6737cc8dc190c5a04c50b5bf4588bc29fa2a47af252672:778f2019dcd8dbb86c6737cc8dc190c5a04c50b5bf4588bc29fa2a47af252672:e609f1224a6a451140cbc0254d432ce5fddd08a8e912f81c412fdfd5182ff6ac2f13c576c8145b15f25b409d853f914409e4e02cefc39d9bef4a2a060498570b2d3a2838c9b0b8e3af4fc37e1915f804a80188585b30b68a3ffb2e960c7320e827d2fe36e6a328cc6e7806348adb0b773b784de529bb6f64751b2105859494fd49db0bc7f62df46b9d7ce676975cc5f43856498436812e04f26fb8b8ab7eba12f1d56722eb82ebfafa4735977a26681cb03fa4bc6951ab9cbdf787e3278f2f57f29e12095f8ca2a178cfa7571337f0274237669f97657d4badb39436d786492580fd55d86be3a0cd17d16057017baaaea00c1e14552159bcabc0e666bad3418e4ec13bfe163be256f0c89bc2344a8ddf99ca8160b189875ad322d90f581325281d5389965c0a7b7bcae2294a3cbe35a4e4e83b54c4276353960fad118532d49b7076f25ad190ab5694914f7108b0ab6969a19128fb0aef00e65a04fc832d07696167b9342b355ec57737ca37cbff3bb31931cb58712a4c468952c6459d567a26e79501e4e31b1b0953537632029e9b490f72e5a6e057ddb4b31756fd9704218b1b8f4dcb5430c025042f47169bfc7c80d71cab8ca07f340afa008abbe2e3a0abe141da8d41ca6bd69d36fdb11a41ce0b72fabc00d97ea605270010b259df8e10dd22dc17c13990a05f0233e3ca856b40971cb3e21c8b3950b13fc84e1f266c2a6fbece88d59725c3cfb2225dbc1ee95b686db704fc937b766f0a9bfe95a42b9010f1229c610d7ede095712c8f0f1fb0047c040a870306cd8dc74c4da51bf:a8a309ba52125e76a4a61eb43fd4135c41ab11799b91cc54ffc9c6a20f050cc595b28143c874bdb928beed261d9c0f12aa192e6640bfdad54ba0d478426bce09e609f1224a6a451140cbc0254d432ce5fddd08a8e912f81c412fdfd5182ff6ac2f13c576c8145b15f25b409d853f914409e4e02cefc39d9bef4a2a060498570b2d3a2838c9b0b8e3af4fc37e1915f804a80188585b30b68a3ffb2e960c7320e827d2fe36e6a328cc6e7806348adb0b773b784de529bb6f64751b2105859494fd49db0bc7f62df46b9d7ce676975cc5f43856498436812e04f26fb8b8ab7eba12f1d56722eb82ebfafa4735977a26681cb03fa4bc6951ab9cbdf787e3278f2f57f29e12095f8ca2a178cfa7571337f0274237669f97657d4badb39436d786492580fd55d86be3a0cd17d16057017baaaea00c1e14552159bcabc0e666bad3418e4ec13bfe163be256f0c89bc2344a8ddf99ca8160b189875ad322d90f581325281d5389965c0a7b7bcae2294a3cbe35a4e4e83b54c4276353960fad118532d49b7076f25ad190ab5694914f7108b0ab6969a19128fb0aef00e65a04fc832d07696167b9342b355ec57737ca37cbff3bb31931cb58712a4c468952c6459d567a26e79501e4e31b1b0953537632029e9b490f72e5a6e057ddb4b31756fd9704218b1b8f4dcb5430c025042f47169bfc7c80d71cab8ca07f340afa008abbe2e3a0abe141da8d41ca6bd69d36fdb11a41ce0b72fabc00d97ea605270010b259df8e10dd22dc17c13990a05f0233e3ca856b40971cb3e21c8b3950b13fc84e1f266c2a6fbece88d59725c3cfb2225dbc1ee95b686db704fc937b766f0a9bfe95a42b9010f1229c610d7ede095712c8f0f1fb0047c040a870306cd8dc74c4da51bf: +42b53652d08b5d766e66ad8f3ebf693cfd77907cadd98b5466df77dfa2c637ad88463bb8a4b6388d924cb86209834195435d79d77f8c02f46bbd16d82efe42b3:88463bb8a4b6388d924cb86209834195435d79d77f8c02f46bbd16d82efe42b3:9ee913c74ee3c5e8c90d64b8ae3a60049fc765e176060bcd1cd09f0eda60bf23badb8a1caac3d66ebc5268146ee4a54e1eb231ed25eff95b90a6e98337a540a3f48449794a4873bfc2e84728966bb7c6ff676a2ff57311c1c25e15fbf3d40e9f25ab5db91fddb7a0ae436c8ec070754b6d743aa1d6048fb5bd7f5b8e4ccad20328389530f11374a489b1d50531a39c9b32b40369626006d264a99eec4fac1341f4e74679457b418e6bbfba233f1ca158f7b29d40d50301f9d92536fdc5c23fe5dee4d6df0ebf13dfa3754a14c856009adea1dda409304c1f60d25330fb10957947a00508f2fd76422eac694cc39fa8ae7fcc77a02fd9ee5f910d93e8aac68f145dd878876ba8eda0a49fcb209c34ea220d4d0605546fc4a809baf010d533e45d17b0e16a46e91ea6fec2cdc5a8b3ec5014b25e92d8e5c928ab06993d4fe23ac8d45c890378dd133f00edb937c071f75cfc13a402e3e429a848652a175c9b6f6eac86f6188a4448a96ce2872e5f65f9bdb87166c9b87a7e958e80bb6566e3fcf871190cf4a867e612cfc1e4371d2b73d2a0ad0aa400ba69e66336233b0f3c52b8a68bca05125601255046e6f49d688d2db85c7b821270516e3c0613f3f23f9c57cb4c8714285cdf95e106a3b5afcaeb81b72f343e87bd92f1581dcf9aa90a024fa4a1048059e30de8ff0d16794dcd745d2b2d534c520f8278538674a934c6f14a8428e3da018a36e45aa5827cf4b15284346fd69363149219bb0d1bc927d8d193c482692f97dc88d8ed337d0c9dc99c7a5e111dced42250d580e20692bb7b88:30c4b99e68ec3351308fbc76d9caf0af6221b596b7017fe10cc633023ba97f023896fe322baa347660610e05fa493d218fa360f18d93e275d1eff666b63db2049ee913c74ee3c5e8c90d64b8ae3a60049fc765e176060bcd1cd09f0eda60bf23badb8a1caac3d66ebc5268146ee4a54e1eb231ed25eff95b90a6e98337a540a3f48449794a4873bfc2e84728966bb7c6ff676a2ff57311c1c25e15fbf3d40e9f25ab5db91fddb7a0ae436c8ec070754b6d743aa1d6048fb5bd7f5b8e4ccad20328389530f11374a489b1d50531a39c9b32b40369626006d264a99eec4fac1341f4e74679457b418e6bbfba233f1ca158f7b29d40d50301f9d92536fdc5c23fe5dee4d6df0ebf13dfa3754a14c856009adea1dda409304c1f60d25330fb10957947a00508f2fd76422eac694cc39fa8ae7fcc77a02fd9ee5f910d93e8aac68f145dd878876ba8eda0a49fcb209c34ea220d4d0605546fc4a809baf010d533e45d17b0e16a46e91ea6fec2cdc5a8b3ec5014b25e92d8e5c928ab06993d4fe23ac8d45c890378dd133f00edb937c071f75cfc13a402e3e429a848652a175c9b6f6eac86f6188a4448a96ce2872e5f65f9bdb87166c9b87a7e958e80bb6566e3fcf871190cf4a867e612cfc1e4371d2b73d2a0ad0aa400ba69e66336233b0f3c52b8a68bca05125601255046e6f49d688d2db85c7b821270516e3c0613f3f23f9c57cb4c8714285cdf95e106a3b5afcaeb81b72f343e87bd92f1581dcf9aa90a024fa4a1048059e30de8ff0d16794dcd745d2b2d534c520f8278538674a934c6f14a8428e3da018a36e45aa5827cf4b15284346fd69363149219bb0d1bc927d8d193c482692f97dc88d8ed337d0c9dc99c7a5e111dced42250d580e20692bb7b88: +14cfe00fa7190ae810888ae2bbd0ff6412cf1fd408a308294383a19453b590734e61afe8c174b6ee1a29fa09cf87b4008139f1070bc8531b6d06f54c9562a4f3:4e61afe8c174b6ee1a29fa09cf87b4008139f1070bc8531b6d06f54c9562a4f3:bc66f801daa829858e740293d4d2187b8e1a5afba5fd67b10956c65346aca94429d32e4cfb3584ab0e005d0dd742781d47e89447c4e1d81bf7e6154f8f73af03361ad56ea3c06000754b9f327d4edeacc4d348afb54823e1c9d49cd8ff2b19f42021b40d580c39ce3d243661b85421fec915ba9dd2762f850bd208fdbf20ffaba56a468660f17c00fb1c0f4e8527a509dd4eec13360cf6e3cac542b875182f2a7ce7be0a33302fe26d3629629384e35c06789de634e90e964fbda8cbba98111e22e8d0762684266aab76aeba4a380778696814a1e311943cb3505892640c44e3aac4530c50ac604a8d2ccc7ceabffea4aa3d7f48a66dcd7588b80209dbc173f0c663e8fc87a36e892ec9a3ff8f60d2e0d8704e5b6cbb873275151ad4cc0057165031905039651ca10a95c6fda3b27827a657ef9a5fc3eb5b53cac61ddaf5a41704c878570cbc3c41c475b117c05eab0bb196bcb7c43334debd64b9e37450d23f5c10161ec5ab4fccd7cf308e2a9995cc9e578b85e8285a5208b9efd42af9cf2ac2b3b7464254889a2187317e32499709b913953ad46f1c23e1b6b56f024c4a7d48461192c01c56c54c564791ec0a67b61acbf957e6d0d7da8053ed13a41893d767fc5737cd195553da5d5b07065f47d72a35c42b001eb6dbd0f8e77a4b76a6266192647f4155ea11bd1237ba77c87c62bf4b01149fc58bc28f0b5a286485d3717d323964046218e70c7e38b7d5e74ba6b12b022f18197d92c13bca89335c856cbc5756aa3b64ec1f46e396b1161c871cd2dfded1a4ec9192742937c0704531c7:f785a46f69bbd099fa011124ba9032c189742c9e001dbb8781d8223345a9569dc144ca694d90245e0e513e88ab023f7f0f99b7416159758dd034e7a89cff3600bc66f801daa829858e740293d4d2187b8e1a5afba5fd67b10956c65346aca94429d32e4cfb3584ab0e005d0dd742781d47e89447c4e1d81bf7e6154f8f73af03361ad56ea3c06000754b9f327d4edeacc4d348afb54823e1c9d49cd8ff2b19f42021b40d580c39ce3d243661b85421fec915ba9dd2762f850bd208fdbf20ffaba56a468660f17c00fb1c0f4e8527a509dd4eec13360cf6e3cac542b875182f2a7ce7be0a33302fe26d3629629384e35c06789de634e90e964fbda8cbba98111e22e8d0762684266aab76aeba4a380778696814a1e311943cb3505892640c44e3aac4530c50ac604a8d2ccc7ceabffea4aa3d7f48a66dcd7588b80209dbc173f0c663e8fc87a36e892ec9a3ff8f60d2e0d8704e5b6cbb873275151ad4cc0057165031905039651ca10a95c6fda3b27827a657ef9a5fc3eb5b53cac61ddaf5a41704c878570cbc3c41c475b117c05eab0bb196bcb7c43334debd64b9e37450d23f5c10161ec5ab4fccd7cf308e2a9995cc9e578b85e8285a5208b9efd42af9cf2ac2b3b7464254889a2187317e32499709b913953ad46f1c23e1b6b56f024c4a7d48461192c01c56c54c564791ec0a67b61acbf957e6d0d7da8053ed13a41893d767fc5737cd195553da5d5b07065f47d72a35c42b001eb6dbd0f8e77a4b76a6266192647f4155ea11bd1237ba77c87c62bf4b01149fc58bc28f0b5a286485d3717d323964046218e70c7e38b7d5e74ba6b12b022f18197d92c13bca89335c856cbc5756aa3b64ec1f46e396b1161c871cd2dfded1a4ec9192742937c0704531c7: +ac0f7f0418de67e348fa6d5686c46d21ca72622ee69eaabe00d5c9075a34f179feabde08f00a2b682bce9d45990bf45afc958339dc44106dad33b2c490ef7090:feabde08f00a2b682bce9d45990bf45afc958339dc44106dad33b2c490ef7090:e8d0e8325335e0f35a85467beed1e11c6a2078c35ae4a4a10543ede40c1712bc952012d2f8fec105aef7c6c65b3634b4a74b22b498b913507d1f6cfde83858e6830c0af4f464a6899d5c4e279aff36754c21da80a1bbd1dcf46220375b1e112a5a72f1ab6e8f641942f66d9bbdbb179cf0139ea8deb0f4b814f50c513329a1a0e267c4433a233182bc4a2acb2c6d4f00b24094d3bdc0eb81cf37d38260c2107dd9490613d276ee1f72266c6e4acca5249811a0f8a7dae66aedb75c3df4c8ca3cb5d9c567ba541ee5a9140c50587272af34530ab8b08b9ec032eac06039e692630e2d554df77c1a0388b3caaa3be3754a84961fb299e402227158ce363eac26478d479775e5685adbf828bb355e3c89cce241503c15366432ba94cd3cd95479144b636e0de70b3f16d1a3ca518e399009a4c247a7f96367c7146608aacc0014fc35b84af9933f09babb89937abb8ced111891343ddb79f60b78898ab5938f8ba3814bd8002605b1dfd297fa07c475a0d4f8f4451acd707de8af6c0e8818833a3abe5c96d1a8c6c96e2cb63328eba44dd1d34684e412f288e065209d11eb8094d22e4cc802629ccba33926bf1ad36a6285138abee05c5a39a475f3fdd0b3ec8c370cd957a8379ec2cdaf03e895c1ba12b449d6cd8be0f35d99e2b7fbaa92dd54e64e7c35ceb88a71a680527cb373afe14cdd158a0b90bf2daec80d2edbdc3128cd6b63fa532a1c278cdfe0f8ebb4abba5e1a82bc5c3fed15c5795bd9ffb576082cc479fa1b04c5c5afcad269a0f1addfe76042c3a8f1f25377b6cb72ec1614eb6383:7591cf8257bead39a1ad3ba1918d518e6724356bf625a573eae501d1af946c13c290cb63156ec9d362726ee50b39fc0a7a2bbd69d4a81b75932a90f8c7ac7d03e8d0e8325335e0f35a85467beed1e11c6a2078c35ae4a4a10543ede40c1712bc952012d2f8fec105aef7c6c65b3634b4a74b22b498b913507d1f6cfde83858e6830c0af4f464a6899d5c4e279aff36754c21da80a1bbd1dcf46220375b1e112a5a72f1ab6e8f641942f66d9bbdbb179cf0139ea8deb0f4b814f50c513329a1a0e267c4433a233182bc4a2acb2c6d4f00b24094d3bdc0eb81cf37d38260c2107dd9490613d276ee1f72266c6e4acca5249811a0f8a7dae66aedb75c3df4c8ca3cb5d9c567ba541ee5a9140c50587272af34530ab8b08b9ec032eac06039e692630e2d554df77c1a0388b3caaa3be3754a84961fb299e402227158ce363eac26478d479775e5685adbf828bb355e3c89cce241503c15366432ba94cd3cd95479144b636e0de70b3f16d1a3ca518e399009a4c247a7f96367c7146608aacc0014fc35b84af9933f09babb89937abb8ced111891343ddb79f60b78898ab5938f8ba3814bd8002605b1dfd297fa07c475a0d4f8f4451acd707de8af6c0e8818833a3abe5c96d1a8c6c96e2cb63328eba44dd1d34684e412f288e065209d11eb8094d22e4cc802629ccba33926bf1ad36a6285138abee05c5a39a475f3fdd0b3ec8c370cd957a8379ec2cdaf03e895c1ba12b449d6cd8be0f35d99e2b7fbaa92dd54e64e7c35ceb88a71a680527cb373afe14cdd158a0b90bf2daec80d2edbdc3128cd6b63fa532a1c278cdfe0f8ebb4abba5e1a82bc5c3fed15c5795bd9ffb576082cc479fa1b04c5c5afcad269a0f1addfe76042c3a8f1f25377b6cb72ec1614eb6383: +b5a7c767936380b3e98751cafd3ea89b388a32cf828b321c5bd0cc8dd85baf00be7fa65f1f6be51027f8b848db7a8c404961bf1e21a23df23bb8ce05850cdaa1:be7fa65f1f6be51027f8b848db7a8c404961bf1e21a23df23bb8ce05850cdaa1:6b67c795d66fac7bac8442a6c0992cb5758843b3e3939e3c276c6e9008da82007677bf9e67e9ac5a1a0f486beac0d856191fae25a127392bed469bc78deb0c4b893f67f1716d83509077e4a1bfd4136d03152dcc3b76d9524940a6064c669fbf51f6b91034b6d5f2898678a13a2470f6641ec802457c0102c3ebf6345c327e741b80644b3a99bf72b59ab8016f35d25188a085750dc060e5a8d524ae213f078f288c7b34bc41f3ce356bf2dafdd2e0db4fb8d7c2c319f9906005971702e49ca62e8050540d4121d242f2eeab1bd134e60bf11b3ec71f7765a97c0e098455e59d2235d6b37e7c9f5b21fa112c3ba39e4ea200614f58dfb3eb7b836f0bec1ddd438d1422450ae7ded1df9d71e5d9bc8fa3b6e6f78446ce7c79d0bcfb1c2d26c6fece68682dffc60a9c6e0ad05f2a09f21d7523251cb0c3d08efbbf8ac16339d717024d676024c1ee3c1f62c5aeab7fff937c57454df7bd96f9844a2a399958418aaa6f1848bebf7bf1292c24eb5cd8ea56340c5beb2688024a6953275be6efd1b71ba8be6eb77f0c65a7c5111b96c4c1f39cb7aaf83fdaae8d148d7a8af40ae9e651919f7ce28c8b2b6e45e4d3d56fdd54d00c2412790cbd6f80e10819e0b8f37c84fa004988adafccbbc21c63d6bf2e732d9dd63bd49b0412b9674e1e88f6142f7f867f1f26891b22430423cec4db91b61c2abc5c8fbd46b8b93596fc5160683136e21129822796eb5ea088e0a7d8121b25572e3ec37743d1ff6d8d1c3536439a10e84a665f2c75ee73cdc6ffac4cc28724469f7970b47507df3e1b14d477aec2bb20:60e4d23f1f08fce466c9915dded93256b52b327e5f81fbb31d1d10d321c390366ef001fd759aa9d0a55162d5364d918b48c7327e77cf5358bc4319e325cdd6086b67c795d66fac7bac8442a6c0992cb5758843b3e3939e3c276c6e9008da82007677bf9e67e9ac5a1a0f486beac0d856191fae25a127392bed469bc78deb0c4b893f67f1716d83509077e4a1bfd4136d03152dcc3b76d9524940a6064c669fbf51f6b91034b6d5f2898678a13a2470f6641ec802457c0102c3ebf6345c327e741b80644b3a99bf72b59ab8016f35d25188a085750dc060e5a8d524ae213f078f288c7b34bc41f3ce356bf2dafdd2e0db4fb8d7c2c319f9906005971702e49ca62e8050540d4121d242f2eeab1bd134e60bf11b3ec71f7765a97c0e098455e59d2235d6b37e7c9f5b21fa112c3ba39e4ea200614f58dfb3eb7b836f0bec1ddd438d1422450ae7ded1df9d71e5d9bc8fa3b6e6f78446ce7c79d0bcfb1c2d26c6fece68682dffc60a9c6e0ad05f2a09f21d7523251cb0c3d08efbbf8ac16339d717024d676024c1ee3c1f62c5aeab7fff937c57454df7bd96f9844a2a399958418aaa6f1848bebf7bf1292c24eb5cd8ea56340c5beb2688024a6953275be6efd1b71ba8be6eb77f0c65a7c5111b96c4c1f39cb7aaf83fdaae8d148d7a8af40ae9e651919f7ce28c8b2b6e45e4d3d56fdd54d00c2412790cbd6f80e10819e0b8f37c84fa004988adafccbbc21c63d6bf2e732d9dd63bd49b0412b9674e1e88f6142f7f867f1f26891b22430423cec4db91b61c2abc5c8fbd46b8b93596fc5160683136e21129822796eb5ea088e0a7d8121b25572e3ec37743d1ff6d8d1c3536439a10e84a665f2c75ee73cdc6ffac4cc28724469f7970b47507df3e1b14d477aec2bb20: +e136f398a605d13457848cead07c7286f42e2f28df8c128a3d0bb72b29aacc196aa5045a66f772a571fe3e42d117efcdf6c49591996186012fa98f7c48e0cda7:6aa5045a66f772a571fe3e42d117efcdf6c49591996186012fa98f7c48e0cda7:d328579de4c5372f3b382c48011b2d4c6029f904f3a33e07d083d7e2b03756af2c4c97a2d66c10ec4154d874792042b646e4aae5101d501bd1bf6f511751d0aaf821cd7c0b3ee6d0d7c690a2777fe16bdc7e49b7da4bbb4cce3b618ee9b6f2e3a19240cdb70733b984b1c940ec66960b728cbb874b80643123722db9dbbe88322008931b1c894ef5d21099e63e7c65007acd61784db4994a2fb40c3efe9c47fad63763dde06fa017a26b82e71b9daabc4ff0f6c79b8ca7ccb4dc2031bef1087367c7086974a00566de41a71e11d993abe433569892b8f75d7637993245c884478abe3f95f44b0a4bbedefef8906b75e0d34020ae536455b0e06f9bfee11ec9b8604bac2cc6ebe08c8fd5f5cccccbc1617b7cf69a3c512e1f0bdb585df5e12743061f7c2053bc37144361c0b35fd39d56b1efaf92c610360193ec20598b82858050a6d99e082bcefdbd5318ee5efb3b260f3276f3c73f9c24ce0cda33c7acc50ca5dd61bdb85d793825f6732a6e330ce672ac44fe6b2b9afe6e2e965c02d2a1fe0b57cb1b317c1d313efdc356492fe896fd149dae51c95ccdbb7d11f7d610e0c6e2fd3e57fcfef1c57c7119a0af6c7821fecdb89d80302b49fad41743f3d2d7a075154b3143e51aeb947d4b5e8b7e4ca86fec3e80bd9a786e4e46ed1e6e9f7e0b635266d9fa097aa9e20f32e3d2772d7c1f008bcdd3f92c7283c57790c3622cbad3ca35803c45c869dc377ff36bd7c0e6f1bb892f7329a6e08df1dbebc81dc7b115f852e36ae5d928725fa7c6fb9f28b0fb394f9e38fd87625c5fa23aaba47054e8cfea:75a45c6b9566899829b41ee517b7045a473a4f7a2641439b5d7c5673e00d8f5c066f1291f85deada0502bd16e9709f827d4751f2873862e8219e57746a19a900d328579de4c5372f3b382c48011b2d4c6029f904f3a33e07d083d7e2b03756af2c4c97a2d66c10ec4154d874792042b646e4aae5101d501bd1bf6f511751d0aaf821cd7c0b3ee6d0d7c690a2777fe16bdc7e49b7da4bbb4cce3b618ee9b6f2e3a19240cdb70733b984b1c940ec66960b728cbb874b80643123722db9dbbe88322008931b1c894ef5d21099e63e7c65007acd61784db4994a2fb40c3efe9c47fad63763dde06fa017a26b82e71b9daabc4ff0f6c79b8ca7ccb4dc2031bef1087367c7086974a00566de41a71e11d993abe433569892b8f75d7637993245c884478abe3f95f44b0a4bbedefef8906b75e0d34020ae536455b0e06f9bfee11ec9b8604bac2cc6ebe08c8fd5f5cccccbc1617b7cf69a3c512e1f0bdb585df5e12743061f7c2053bc37144361c0b35fd39d56b1efaf92c610360193ec20598b82858050a6d99e082bcefdbd5318ee5efb3b260f3276f3c73f9c24ce0cda33c7acc50ca5dd61bdb85d793825f6732a6e330ce672ac44fe6b2b9afe6e2e965c02d2a1fe0b57cb1b317c1d313efdc356492fe896fd149dae51c95ccdbb7d11f7d610e0c6e2fd3e57fcfef1c57c7119a0af6c7821fecdb89d80302b49fad41743f3d2d7a075154b3143e51aeb947d4b5e8b7e4ca86fec3e80bd9a786e4e46ed1e6e9f7e0b635266d9fa097aa9e20f32e3d2772d7c1f008bcdd3f92c7283c57790c3622cbad3ca35803c45c869dc377ff36bd7c0e6f1bb892f7329a6e08df1dbebc81dc7b115f852e36ae5d928725fa7c6fb9f28b0fb394f9e38fd87625c5fa23aaba47054e8cfea: +97b6702e246805dbcfc7fa424a8caabcf262d466a05e0dd2d4e7c374d57d5251a716c3d5ce78f4d9c5bee3447ddaf4881c986efdf667ac8977b4fb69b5a7110a:a716c3d5ce78f4d9c5bee3447ddaf4881c986efdf667ac8977b4fb69b5a7110a:eaa86cf76fcb65c6f9fc208ac36f28b200d3b403aca73207461d8d96afa246d7c69d17a7a9bf77f05543563a7d3eca1d4079e22938aba1f6e9e04b49fbc8ed6f63b599730de9979831c02f8cba61e55560d7110d4c6e61679706a7155d5a673c54d16fe4d228c2eca7546faa1339f26d7a0bb4ee339611afdec9a68f5ff5b5d203b600533ad5a3b368c85da11563f098cc26871e7fa99aefd38cc26151db3b0bae38db6a87b6789e5840b10884af511f3ecb3ecbf94ff86fdb905505a8c34b2aa61ff2ec9ec8febd1dfed0965b6fc5b9f8869dc3a47559974a8822996706daefbc6c5bf984ce06b0d32b31cf9d8ad136aed4b052586dce7073b767b234e4a37bebbc393dd2e0f7d155173548c38a1583ef94e0aa84e7fce04fcc9b4e300ad099449a49232abdcf3d1a6e6fcab696f5996f9bd1b9485d074755ac5b4297fee3124c7c03976a40d570beaec2fac992339f885f74d40ed4ac87a4f40cefbc4864f44c3683aa8f1026e2c37aeffcebfdfe24dd0b019c36a79888203004b2ad83e89221f3f636f455bb64e17d1754c7c6dd7fc09a0d65dddded4622fc4f9fba072b45103435e10220a586f15226d2eb377f4064d3ff37cbb4705a1faaf5b348f8c0ef7fd1564d428688f58f3392967cf396a8ff2fd9e7b517b7d6a5ede7440373d8cc1a839900e84d42254283d9699c7ca37e477692a3494008b80444c5cf614cbbc169bfb9296303c645e2ce28d168dc6cbaefae9c73191f57151aa473009d29e1800b10f4c498609ba11520985c78092058696fdbca9c020e2dfb8a043a3de8e452d58cd1ad:90005541dcc1d7ab837f4de5393fadd6a92b26a7d93af3f669e0f1bfd621cbd00c8a23056d2da6786557c828a49be1e4021d99311235ac0d4d56eefc7c953605eaa86cf76fcb65c6f9fc208ac36f28b200d3b403aca73207461d8d96afa246d7c69d17a7a9bf77f05543563a7d3eca1d4079e22938aba1f6e9e04b49fbc8ed6f63b599730de9979831c02f8cba61e55560d7110d4c6e61679706a7155d5a673c54d16fe4d228c2eca7546faa1339f26d7a0bb4ee339611afdec9a68f5ff5b5d203b600533ad5a3b368c85da11563f098cc26871e7fa99aefd38cc26151db3b0bae38db6a87b6789e5840b10884af511f3ecb3ecbf94ff86fdb905505a8c34b2aa61ff2ec9ec8febd1dfed0965b6fc5b9f8869dc3a47559974a8822996706daefbc6c5bf984ce06b0d32b31cf9d8ad136aed4b052586dce7073b767b234e4a37bebbc393dd2e0f7d155173548c38a1583ef94e0aa84e7fce04fcc9b4e300ad099449a49232abdcf3d1a6e6fcab696f5996f9bd1b9485d074755ac5b4297fee3124c7c03976a40d570beaec2fac992339f885f74d40ed4ac87a4f40cefbc4864f44c3683aa8f1026e2c37aeffcebfdfe24dd0b019c36a79888203004b2ad83e89221f3f636f455bb64e17d1754c7c6dd7fc09a0d65dddded4622fc4f9fba072b45103435e10220a586f15226d2eb377f4064d3ff37cbb4705a1faaf5b348f8c0ef7fd1564d428688f58f3392967cf396a8ff2fd9e7b517b7d6a5ede7440373d8cc1a839900e84d42254283d9699c7ca37e477692a3494008b80444c5cf614cbbc169bfb9296303c645e2ce28d168dc6cbaefae9c73191f57151aa473009d29e1800b10f4c498609ba11520985c78092058696fdbca9c020e2dfb8a043a3de8e452d58cd1ad: +d1528c1406a6e494a02f635305fa74d745c69327fd31b7d2c2623de2c030ed850cfe369cf93daf6d53ef028ddb9f000443b0972fe2532f83a41ce657c1836ca3:0cfe369cf93daf6d53ef028ddb9f000443b0972fe2532f83a41ce657c1836ca3:abb3673f3fa17a33a7aff76eac54e7687c04bc84f766651a8b24ba22947908b04ca459feb98ace7cab1e7433a6a6beffd8d9504e2991daa0644d61b8b2e45448f54df8813f50c418b48f49e1034e851cbec3ef0a1850ef726733afaf68e1a461041651c138d54e4ef78187af9a7342f7128727f903bf4fc5ef3e40c64ec26f892f59add98fe394765aaa7d09cae81b9f699a9dd8bf2e2fe8e1ec78fc884eaa0d2dbdbfb8c168833ee0d21803cc35dc628d7c07e04404fb60e8c490a8dd34edbcbaaf80ccdae3f7d3739e0e897023eeb5b1a8c00a9673c59258240ddd4420650fe5771f7e28cb2399f5e1e02ad0b6432d9b49608fcf0b1c0d7c412a445255b8badc5321c24c1ac92c79a0baccb9deffed02d12f5536cd595dc66083b33a3603a9d16ecea2bf38c4f2aaf570f30d21162b2efd7e4d5ebf1ecae9588eee36dd9d3d8e3be7bc6d4bc2185622f11d1da7c49c93e623ac56fee7e3706db8313cf926be92e5c8a539fd16b0f438da8e51a51f2d27640356124ef7be2f91ffa1796a91b12301934ddef0c7938a7a45f36f53b6322d9c8f9d275e1cd2c0f129f8ab8d74155b5d9e5c15c015b0b00003b2bddfa0bcfcc693a1dfcb4f53daec126d1669f33f39ad05519ef7c5ce40e6f4573c247a32c4a0162831352f6d558ff5836a5317dbc4515b3df269a8ac76d6436f264b64561e7968b5822108487b045c92d6c6142a1c2855b38beebd642565123cc827cb1831199e6f12a7e4236856b94dad738f69d1106e7735d711f7c6a3a3378041fc7a21103bbf866907d4edddafa0e7f1bb5ffd41a60d64:b8399bc3326cba0a93a42497168bf57f9106ee43d39bf0fc86685199dc6e0a13b9c724ef17e7882af8c2eb70f6c9e42dfa2fbf0c1cb5002b58f1086619733e02abb3673f3fa17a33a7aff76eac54e7687c04bc84f766651a8b24ba22947908b04ca459feb98ace7cab1e7433a6a6beffd8d9504e2991daa0644d61b8b2e45448f54df8813f50c418b48f49e1034e851cbec3ef0a1850ef726733afaf68e1a461041651c138d54e4ef78187af9a7342f7128727f903bf4fc5ef3e40c64ec26f892f59add98fe394765aaa7d09cae81b9f699a9dd8bf2e2fe8e1ec78fc884eaa0d2dbdbfb8c168833ee0d21803cc35dc628d7c07e04404fb60e8c490a8dd34edbcbaaf80ccdae3f7d3739e0e897023eeb5b1a8c00a9673c59258240ddd4420650fe5771f7e28cb2399f5e1e02ad0b6432d9b49608fcf0b1c0d7c412a445255b8badc5321c24c1ac92c79a0baccb9deffed02d12f5536cd595dc66083b33a3603a9d16ecea2bf38c4f2aaf570f30d21162b2efd7e4d5ebf1ecae9588eee36dd9d3d8e3be7bc6d4bc2185622f11d1da7c49c93e623ac56fee7e3706db8313cf926be92e5c8a539fd16b0f438da8e51a51f2d27640356124ef7be2f91ffa1796a91b12301934ddef0c7938a7a45f36f53b6322d9c8f9d275e1cd2c0f129f8ab8d74155b5d9e5c15c015b0b00003b2bddfa0bcfcc693a1dfcb4f53daec126d1669f33f39ad05519ef7c5ce40e6f4573c247a32c4a0162831352f6d558ff5836a5317dbc4515b3df269a8ac76d6436f264b64561e7968b5822108487b045c92d6c6142a1c2855b38beebd642565123cc827cb1831199e6f12a7e4236856b94dad738f69d1106e7735d711f7c6a3a3378041fc7a21103bbf866907d4edddafa0e7f1bb5ffd41a60d64: +512340f961f142d1915e85fe4fa0f551f80892e75accce7cd1869e6e2c9e80150ca02604fa87e2c20506251f0792cd2125856f0ab16d663f2811963b1f2d8172:0ca02604fa87e2c20506251f0792cd2125856f0ab16d663f2811963b1f2d8172:af37b2c7587a8d5bc895cd357746ab03552a0a561a293dc7164e39b6a1333a920bb6daca6006676e99bb7e928f9ea391e54802a8d31596289fb9bfe30000cf52ebf0c124a5895bce3398c1bf5356be82619b8ddc15a77ca922494bdb04f5c2e1b6e8ff77ae749faf2b8a41d822c17c06dfb7a5f9434d8bd715ec8778e80b81d2e8d06298748690c6555283c98bb9b19b9246667bc41046ff98c2c35d161e1f4d69d254ec5a076f25bd5c7e2c98ca3c09d80833962cf9660287884096eb30c46c54174106af4e2979a112f3e8944eaaf7669c40d5afb91a024abbeb14664e308903e4d26d7009446ee2e830ab5eca0dbbc513fb4e04351df2f6741864fb2371b2502be43dc15fc04431fff5eb8d4b68d72462ae322e57ba2d4adddf15a1902c2113aebd3b5d612917c1bb73e708ad5418e7d45e4b7280fc8896ab80853ff5f8e98f26553fc78e30b3b0d727bf6d064a8f32888768c51ebb61b2c600b4028a77060febbb02eb3d201780e74566c86a34031836bce9eada81e5d0f33960cb2df08aff3c974921fc9b7d3aa7c81e9c671ed6d33e7ae5ed03a5417d7e5cd6faac91b54b8f792f48283c60647de3da816ca9756c5bfe1bb8b5979e575401bda34e9cbc4d77e711d6b73b82da19da473b55e8e72d341b2d8503e48609be0fe291444c283669e5deadeaf52aa8ec48da83f5328cc099fb41f82becdd58d04b1d66203d737bed06cf21c97819ac13ed711ca217a57cf7d80ff082aa1a1cf8fea555cd2e47e4ddab5e3f9941ad4f775f49419dcadb5b004b68caf45b27ef49ba14fb52b09f1b185be9f9c7:6bb4d975afaef41ea9ef085a68c568a05da37ef21dad464ed86ac0d4080e7d0129fb023131eca5f7adb2586a18be40562fa2764ca807e670a0596a5c547bc001af37b2c7587a8d5bc895cd357746ab03552a0a561a293dc7164e39b6a1333a920bb6daca6006676e99bb7e928f9ea391e54802a8d31596289fb9bfe30000cf52ebf0c124a5895bce3398c1bf5356be82619b8ddc15a77ca922494bdb04f5c2e1b6e8ff77ae749faf2b8a41d822c17c06dfb7a5f9434d8bd715ec8778e80b81d2e8d06298748690c6555283c98bb9b19b9246667bc41046ff98c2c35d161e1f4d69d254ec5a076f25bd5c7e2c98ca3c09d80833962cf9660287884096eb30c46c54174106af4e2979a112f3e8944eaaf7669c40d5afb91a024abbeb14664e308903e4d26d7009446ee2e830ab5eca0dbbc513fb4e04351df2f6741864fb2371b2502be43dc15fc04431fff5eb8d4b68d72462ae322e57ba2d4adddf15a1902c2113aebd3b5d612917c1bb73e708ad5418e7d45e4b7280fc8896ab80853ff5f8e98f26553fc78e30b3b0d727bf6d064a8f32888768c51ebb61b2c600b4028a77060febbb02eb3d201780e74566c86a34031836bce9eada81e5d0f33960cb2df08aff3c974921fc9b7d3aa7c81e9c671ed6d33e7ae5ed03a5417d7e5cd6faac91b54b8f792f48283c60647de3da816ca9756c5bfe1bb8b5979e575401bda34e9cbc4d77e711d6b73b82da19da473b55e8e72d341b2d8503e48609be0fe291444c283669e5deadeaf52aa8ec48da83f5328cc099fb41f82becdd58d04b1d66203d737bed06cf21c97819ac13ed711ca217a57cf7d80ff082aa1a1cf8fea555cd2e47e4ddab5e3f9941ad4f775f49419dcadb5b004b68caf45b27ef49ba14fb52b09f1b185be9f9c7: +b1b636e957574c21a957a45bd195c6f9fe4cc1c57e84134d39b42e1a84329edb95e77b15dda47caf69b72888dd69961bacbec3bc75353003e8bff0a43ddf4b7a:95e77b15dda47caf69b72888dd69961bacbec3bc75353003e8bff0a43ddf4b7a:e25d329cad8364d2dec24373e92d9d50fc7abe8fdc3d0b4ee57e1cfa5b7cd58c23be918f05179ba841b61e180034ca7e74d49b0a1a2cebb4be65344c913c46d32652336e6bda4efa3f58730d39a633a14ca3d9a62abb0a7398cc29aff916eeea2e7caac80845562f73d4030f9cab0bf1c6407f5401513ef87fe6dc099dbc5dfc3352911c07af6c523bef4cca78379659e8803f585904ee6ef6fde77366d96d2ccf248a5320d9b8298b2a73363879107a02b47f57213a85203abbca5a4195f8af3e3593ed2fa3504bb76a3e1be24b66d355662932cb67dc88503afaf762bff741ba1cace97ac58bafad5d36c3aa02e0cbe20e5f3dc8092c512eaa9c4943474aad41990076721ad3f53fb08ac22982ed9b15c751a9e23382f6a69c72e6e244e0eb681e6dd228d3774fccb37eb6232f825d169a2ac8b7e18a42cdaa4f2cf05890bb0c598cf8c31f829ef8ca2435bdcceb0e6193ada7841ee692f30aedf88b627311b138ac78b3913e06f7c321cafb39d901dfe17430b1a20bc437a555a578fa31e4b6807954456bd4b04d5d887987bdf04e0f14af3141b24c3a7b9ac75aa32e2fcd2171a12609e15e73094fd09221b4d27090e73219b648bcaabf3807c9280b6c4ad750a468be0e1ad3e6e63016cb5cec3aaddc5689c2955a2a8d5b8984d7c44376fdd94d3f5ff1298f78172b565913704e90e5ac038cb1720e19b080f81b53d6a45d4528530711b63dfe1e4781c24d74aeb2bd8a73fd2a993c5b0891392196ac32c523699960d8b23e01664cf9021d93928050caf97fb985554580e33336a4563247df59ef6cae53:763c7d0d46878e5c7ecf7104fc1f2230e46178a27c75f196169c0279edb01c28fcde3b0d5b8635cfe339fb232774b2206dab8a460ce417abf490bbfa785c0205e25d329cad8364d2dec24373e92d9d50fc7abe8fdc3d0b4ee57e1cfa5b7cd58c23be918f05179ba841b61e180034ca7e74d49b0a1a2cebb4be65344c913c46d32652336e6bda4efa3f58730d39a633a14ca3d9a62abb0a7398cc29aff916eeea2e7caac80845562f73d4030f9cab0bf1c6407f5401513ef87fe6dc099dbc5dfc3352911c07af6c523bef4cca78379659e8803f585904ee6ef6fde77366d96d2ccf248a5320d9b8298b2a73363879107a02b47f57213a85203abbca5a4195f8af3e3593ed2fa3504bb76a3e1be24b66d355662932cb67dc88503afaf762bff741ba1cace97ac58bafad5d36c3aa02e0cbe20e5f3dc8092c512eaa9c4943474aad41990076721ad3f53fb08ac22982ed9b15c751a9e23382f6a69c72e6e244e0eb681e6dd228d3774fccb37eb6232f825d169a2ac8b7e18a42cdaa4f2cf05890bb0c598cf8c31f829ef8ca2435bdcceb0e6193ada7841ee692f30aedf88b627311b138ac78b3913e06f7c321cafb39d901dfe17430b1a20bc437a555a578fa31e4b6807954456bd4b04d5d887987bdf04e0f14af3141b24c3a7b9ac75aa32e2fcd2171a12609e15e73094fd09221b4d27090e73219b648bcaabf3807c9280b6c4ad750a468be0e1ad3e6e63016cb5cec3aaddc5689c2955a2a8d5b8984d7c44376fdd94d3f5ff1298f78172b565913704e90e5ac038cb1720e19b080f81b53d6a45d4528530711b63dfe1e4781c24d74aeb2bd8a73fd2a993c5b0891392196ac32c523699960d8b23e01664cf9021d93928050caf97fb985554580e33336a4563247df59ef6cae53: +10ca413d70eb3db6e337f0f11abc075c95859e825f876176076952d2f18880305028ba38afecc242635f6e353d5f4afd123f860a0425220e966552a057880823:5028ba38afecc242635f6e353d5f4afd123f860a0425220e966552a057880823:ea7faf79f6ff5d78a823a754347134f1b3c3e91ce518fdd633feb4f05d125f05cb54336ef560e92deb685112a5ffcd3dfd3964b2758ce4785f6a34bfeb39784f0aee55955aebd12ddda641d05769f74402f706dad201c44c91081c7d7f65e7aa4246de6dc3ed6496d10f4a412060d493bac9aed5be4f6d74229e3c55eb6876e3bb2ed41fa4504b6670dda8c798f6daa280d1aa72021174f6c01aec49b321d87f53acbcadcc4607d5b1e45d63fc481a6d90576c87c1880b2e8ff3e590a96beee1804768c756beb86bf1de8adc408b1b8d666f74ba28630822f92d18b056ae37ce0293ee61b9e80f33ac269671bd62a4059b24f7c1a440807440d5d538a65458adc8158724b25c12127aa0349e55f6e55bc92078fd1ef274c2aa791905766be394a2628f7bbd1a32da5e487446bbefae88fa6cf3f7b499f131fa19313d13b280adca50f77802d17331b381683b5e7edab99473edd31d77443488214135fd6f26445093e9e2aff7d7e892337fdc8779065d4d97d6d673576794958dbfa6c50b1b13ac39607c1e66ef9629761071155fbca6f36eb02ceeae16367feac07476908c847c9a533ef68c94311fa089ff28fbd87809b0d3876b431d9a18b202f9a4049a0577b8177610dd02e5c520eca955e803c3ad4f50976f7c2ea8aa3ee4836a1985df0a4f16ef46981595419897993560af82651c2b494e680b37802e7537ef68a575c34f8588063ee0197206d9a32bb4890e7c216a4d33feca36b549e532fea68556e7540a4fb169d49fc553b2e6700ae42d9a516e68160acf6b270c77ca5ec26e5ad5dc75c2c393e299:6aec02dc6bdfcb67f0efc1fd31e23e69e371ab3802505b3201a95dd525417ed1a128db4e182cb37c28f62806667099a8ad480b0ac9e94c2a7d5a0e96e2a7360dea7faf79f6ff5d78a823a754347134f1b3c3e91ce518fdd633feb4f05d125f05cb54336ef560e92deb685112a5ffcd3dfd3964b2758ce4785f6a34bfeb39784f0aee55955aebd12ddda641d05769f74402f706dad201c44c91081c7d7f65e7aa4246de6dc3ed6496d10f4a412060d493bac9aed5be4f6d74229e3c55eb6876e3bb2ed41fa4504b6670dda8c798f6daa280d1aa72021174f6c01aec49b321d87f53acbcadcc4607d5b1e45d63fc481a6d90576c87c1880b2e8ff3e590a96beee1804768c756beb86bf1de8adc408b1b8d666f74ba28630822f92d18b056ae37ce0293ee61b9e80f33ac269671bd62a4059b24f7c1a440807440d5d538a65458adc8158724b25c12127aa0349e55f6e55bc92078fd1ef274c2aa791905766be394a2628f7bbd1a32da5e487446bbefae88fa6cf3f7b499f131fa19313d13b280adca50f77802d17331b381683b5e7edab99473edd31d77443488214135fd6f26445093e9e2aff7d7e892337fdc8779065d4d97d6d673576794958dbfa6c50b1b13ac39607c1e66ef9629761071155fbca6f36eb02ceeae16367feac07476908c847c9a533ef68c94311fa089ff28fbd87809b0d3876b431d9a18b202f9a4049a0577b8177610dd02e5c520eca955e803c3ad4f50976f7c2ea8aa3ee4836a1985df0a4f16ef46981595419897993560af82651c2b494e680b37802e7537ef68a575c34f8588063ee0197206d9a32bb4890e7c216a4d33feca36b549e532fea68556e7540a4fb169d49fc553b2e6700ae42d9a516e68160acf6b270c77ca5ec26e5ad5dc75c2c393e299: +1f0a10a2cb111917b9a67a2a1f38fb86f8ed52607d1d653a457d7f4718d9a7de70c075b2e94c4c02f45e73044f24399741b161feb6f69eab635417282a4a9368:70c075b2e94c4c02f45e73044f24399741b161feb6f69eab635417282a4a9368:4f6a434bd5fc77f0f1b7049c91853ccbd89439962a6078a674b867543b6b7d10552ec1758c5283042bd6b4cea88c9520db04746f089cf3a260fb0f33858efd6f680de5b72d9876324ba590299138f85a76f5be0e05e8859c02b23512559c8beafc9cfe901b283e15d16c792eb03b92880f6ff97aa38eeead3f4fd6c0a9214323aa39a1c16515e30dbd08b833ee40a814a28809c870e1d0a62c37932d5408fc6afc63e79a655c5fe3d4026ef09e0299fbde5ab34fceab14130dc4be007e8e6444d7aaaec62c873df77e8010743c31e8757f1eae9edb5597a1b5d84bd77ae7642e1aca99873a152ffde068a8e4ad9240b903332795e40bb32865e5ce034307a6c9fe339a1c93770df5ca46329f6b09419785cbf2847b0c6832837123853ad952653265c5b5740d194e00f23f9e966791f005f8bf55c388c2be9e21538925f8555e0dbd83be073df765af4940e59a3790b9836bab7909e5676fbf1c2126fe226d781a44330cc01d32830ff8ae00b9792e398c2cbb4fb83a1005c245549a89063fbe06c62a48dac43c5101249994e95e37f24c1d8b3bc673538c46055f800db1c0f956869b6b297d990f44f05b50c7ad6b856f46212858471dd0d39372b0db751573ddb6b5b56ba01e371c78fe58dcd1be53112a6a73da9a6bac75d3c39a1a705a36f640fcfad8cd04077594d59685f6e30de71dfd4a44c4e7c04d6ec7c2e8be12785bb05b29b39151d329f587fdc381c2df0cef73fe0e3fd9208d7ccb6e08d02f42d1feed27561d5e323aa148624e552abe87532de15b7f42c22c98e40525b1747cbd758bfb26fd3eed3b:a4245aa3395e7bada2bcdf1603147cc5f3f0ba91f40fdad8f6d371c3ebefb4c1501d07875b576f40797806a484c7a3f70569e232b0c99d29ca23a233b68edb0c4f6a434bd5fc77f0f1b7049c91853ccbd89439962a6078a674b867543b6b7d10552ec1758c5283042bd6b4cea88c9520db04746f089cf3a260fb0f33858efd6f680de5b72d9876324ba590299138f85a76f5be0e05e8859c02b23512559c8beafc9cfe901b283e15d16c792eb03b92880f6ff97aa38eeead3f4fd6c0a9214323aa39a1c16515e30dbd08b833ee40a814a28809c870e1d0a62c37932d5408fc6afc63e79a655c5fe3d4026ef09e0299fbde5ab34fceab14130dc4be007e8e6444d7aaaec62c873df77e8010743c31e8757f1eae9edb5597a1b5d84bd77ae7642e1aca99873a152ffde068a8e4ad9240b903332795e40bb32865e5ce034307a6c9fe339a1c93770df5ca46329f6b09419785cbf2847b0c6832837123853ad952653265c5b5740d194e00f23f9e966791f005f8bf55c388c2be9e21538925f8555e0dbd83be073df765af4940e59a3790b9836bab7909e5676fbf1c2126fe226d781a44330cc01d32830ff8ae00b9792e398c2cbb4fb83a1005c245549a89063fbe06c62a48dac43c5101249994e95e37f24c1d8b3bc673538c46055f800db1c0f956869b6b297d990f44f05b50c7ad6b856f46212858471dd0d39372b0db751573ddb6b5b56ba01e371c78fe58dcd1be53112a6a73da9a6bac75d3c39a1a705a36f640fcfad8cd04077594d59685f6e30de71dfd4a44c4e7c04d6ec7c2e8be12785bb05b29b39151d329f587fdc381c2df0cef73fe0e3fd9208d7ccb6e08d02f42d1feed27561d5e323aa148624e552abe87532de15b7f42c22c98e40525b1747cbd758bfb26fd3eed3b: +7f05baacf167583cf2fe9562a506991ed987f68ffb71567c7ccce3fcc59b78b00dec3952852b96fd75587e97743f9e41c09fbe6ba981bfceb4ebb8892d986a16:0dec3952852b96fd75587e97743f9e41c09fbe6ba981bfceb4ebb8892d986a16:a27d1eab05150920ded1b1c2578af582b294f7837fe4fb1a3169c25efb70634ba66c7e2991b3e75cc5124826a03e057259b5cb706228780cbc8275c339f8340e402a665032a4ab657827b1c3481f7566d369735b82db7628c022b212730db1e47c9b2d9bc4d81b2342d89c6eafc3e0b6de50d484ccef11238c8e2d240dd595dcef8b2fc57b54ff9a8a74111f61f8a652f20ea012c1ade3e280ecde294c0e35717190162ec6a2265e7e6f3f0704cf8ab1a03e5cc953e2926291ccd4b0590d5c20568f94f9ff0fe2ab78cf9ae2c38bcd491e518f23e9b636f880615fc56078e512d7577e09497c1183453d5081fd4737f280ec5e267c4586b78b70fffdfd730d809df560f2e3772191847bbc3f604fb7f8ca49eed318b5e7d1f2b83a10da0c8594b339b6871a5772dd64168ecc27e240a45c76725e7d55bef37e135e3d9e0e34e36c16e34d77459a552f4074d067a31a3ed2a48cdea4895b10bdf1656f4b7a413c6a088c649fc9d7bc56abf64435491214192a6670cb8b9c917f8e1bc7b2cfce78d28fbc3afc2a50e98213e7e026378e4ea711d151adaaa719beb8974656c10ebc7de46b19ec82951ef46a8c68e7f436e1b3ebedb2d09b0575c9914ead2796b53e0061e212994ac5026aea81ec37c81378f4ccfc467700087968597da38fed52fa48093ae4ba1066c31e3c7d8508095bb45c280120f4aa69a24f3efef1f767985aa1a30e140856f76d1520732878487be53f712dbd7d779e315101588fd7dbdb132f92c27575ac1486f176c790661b0148394e92ffa3ae6f8afb2faa2b7f4fbd0ad91e759a702b3c702b4d:0deed2df82acf4529c408a02931f676bec5cb7ade84ebdcd578f70f971382cf311bb83097300456a558bc4c09d8983ff13493fd611eb66c043bf019bad6f3302a27d1eab05150920ded1b1c2578af582b294f7837fe4fb1a3169c25efb70634ba66c7e2991b3e75cc5124826a03e057259b5cb706228780cbc8275c339f8340e402a665032a4ab657827b1c3481f7566d369735b82db7628c022b212730db1e47c9b2d9bc4d81b2342d89c6eafc3e0b6de50d484ccef11238c8e2d240dd595dcef8b2fc57b54ff9a8a74111f61f8a652f20ea012c1ade3e280ecde294c0e35717190162ec6a2265e7e6f3f0704cf8ab1a03e5cc953e2926291ccd4b0590d5c20568f94f9ff0fe2ab78cf9ae2c38bcd491e518f23e9b636f880615fc56078e512d7577e09497c1183453d5081fd4737f280ec5e267c4586b78b70fffdfd730d809df560f2e3772191847bbc3f604fb7f8ca49eed318b5e7d1f2b83a10da0c8594b339b6871a5772dd64168ecc27e240a45c76725e7d55bef37e135e3d9e0e34e36c16e34d77459a552f4074d067a31a3ed2a48cdea4895b10bdf1656f4b7a413c6a088c649fc9d7bc56abf64435491214192a6670cb8b9c917f8e1bc7b2cfce78d28fbc3afc2a50e98213e7e026378e4ea711d151adaaa719beb8974656c10ebc7de46b19ec82951ef46a8c68e7f436e1b3ebedb2d09b0575c9914ead2796b53e0061e212994ac5026aea81ec37c81378f4ccfc467700087968597da38fed52fa48093ae4ba1066c31e3c7d8508095bb45c280120f4aa69a24f3efef1f767985aa1a30e140856f76d1520732878487be53f712dbd7d779e315101588fd7dbdb132f92c27575ac1486f176c790661b0148394e92ffa3ae6f8afb2faa2b7f4fbd0ad91e759a702b3c702b4d: +d00c216426710d194a3d11cfc90a17a86212e7a0e54baa49b0169e57fff83d61cfe6ae8903c6c701aa304695c651bfd850331f9ad481633ae370c86d7bd13fb9:cfe6ae8903c6c701aa304695c651bfd850331f9ad481633ae370c86d7bd13fb9:82f97841b3ba22dd9a4450837ea7bf8d27a9731470cabb0c2078034bf24e4c1a6290c03f4002b86fa09f07b5209f1f53d0ecf4d9e9223bec125a954551fe8bff718f5e264868e207f701194e41de39971fd385f49a4b4adda911eba55259fc6836653273f656f4af60b20664956d4f2135d90d09e9037d5366a0253444e022c7212af5fd4fccd74237d2885338e2fd721522de6763c2549028c623b9cf387d234ab5e7fcbe5a47c685b79e75a57b09574082a02221df64a2e841618087e722a21bac1ba4f0d7d87bdc510aaa8fbd10757f6c029ca820371fc74c3bc50bd898c55d8167f73ada377aecc91629d64c360c2c241c5cb42e3a518c5dabf0f418b2a7f3d82eefd92026d31e8b8160358eae821f730ecafe7ace647bff8741de2f6a131d11c969e9787cfe6a2fab37bf8d1c7f4a2f364d2f1a76ef046c1843e63ec00cf7920ffaae561e7370b719fc16fcebca3cfdfaba43f4f090c46f477303a660ee88dd4e89bf14b9f804b6fd495cb1412753474a056a0d8931cd9ccbd64f8fcc7a3123467c5d47f690679e8871288093734fd6a1326038658156413696594c134d73887f34ee67609ae8ffb3266c16d87f15345a476f72950c158796a88bbb444f1aa809cad875b85fb9151a0e2eef2e00e80d6b7a9ba406c0519effdd94126232fdf6f1e7b9bbc0362aa77516fdf939e7906aab01307128cf824c102c09b929c9b2d7af8f85b7d7f9a838b2aed0c697e8bdfee66ee016bb1bf35eff6b2f7ef4b91b1fc04fac9f116e2edff40f95c15b77c31ee522f3937c7fa0047d6225e0c8e55e278c8103911feab2b7f4:15c45c194297e887029f49d8bdf9d610dd8c34799e1e9230269e7a58928938cf396a02cd42205490391e1c64353fb06b9f8e9b818a9a361c204a386995bf3b0382f97841b3ba22dd9a4450837ea7bf8d27a9731470cabb0c2078034bf24e4c1a6290c03f4002b86fa09f07b5209f1f53d0ecf4d9e9223bec125a954551fe8bff718f5e264868e207f701194e41de39971fd385f49a4b4adda911eba55259fc6836653273f656f4af60b20664956d4f2135d90d09e9037d5366a0253444e022c7212af5fd4fccd74237d2885338e2fd721522de6763c2549028c623b9cf387d234ab5e7fcbe5a47c685b79e75a57b09574082a02221df64a2e841618087e722a21bac1ba4f0d7d87bdc510aaa8fbd10757f6c029ca820371fc74c3bc50bd898c55d8167f73ada377aecc91629d64c360c2c241c5cb42e3a518c5dabf0f418b2a7f3d82eefd92026d31e8b8160358eae821f730ecafe7ace647bff8741de2f6a131d11c969e9787cfe6a2fab37bf8d1c7f4a2f364d2f1a76ef046c1843e63ec00cf7920ffaae561e7370b719fc16fcebca3cfdfaba43f4f090c46f477303a660ee88dd4e89bf14b9f804b6fd495cb1412753474a056a0d8931cd9ccbd64f8fcc7a3123467c5d47f690679e8871288093734fd6a1326038658156413696594c134d73887f34ee67609ae8ffb3266c16d87f15345a476f72950c158796a88bbb444f1aa809cad875b85fb9151a0e2eef2e00e80d6b7a9ba406c0519effdd94126232fdf6f1e7b9bbc0362aa77516fdf939e7906aab01307128cf824c102c09b929c9b2d7af8f85b7d7f9a838b2aed0c697e8bdfee66ee016bb1bf35eff6b2f7ef4b91b1fc04fac9f116e2edff40f95c15b77c31ee522f3937c7fa0047d6225e0c8e55e278c8103911feab2b7f4: +dd123972e628584acc46293b8e4ce2b2dd469cc4ede14ef39521cf08373585b33522f7ae596eedb217035d95395e448dbd6ffbf42585eaeb307026541c78a651:3522f7ae596eedb217035d95395e448dbd6ffbf42585eaeb307026541c78a651:2b2857f45280173e2e0ef9d594e6083f1dc7a65492975b837def6cadd8c8545031ee9d68369a9393cc7b792feb98040b21f1eb84665f878537ce412e9db680d29fbd8ffc7731eae91a20b47548996204fb06ad740e78f0fc590b6791dc7a0f2659286cc16d02c5117b565836b4b8738cf40e285c69c50e412911292367352dfdaed9982d0f899a23c0ab51812b3ec678f6882ea427cdc93ab4b24824377054aa25d82246653340078cf11d14a51f0e686d7e018b36741668fce7458d169293361dd16b3debbed19e1bef7c36934e20f33a09ad3e82b53ab4e94c255d041898b97737df99584af14e404058d0c93bcae7bbbc06395a2aefbdefa7b2ed17cebd1513fa390fe9a9b0ce68cecc2b9e129b7a29f49b6d18c28bacd3af39dc39ca972f0e0d06855d57c2b5fcac2f79cb8c05799e4f65734668dad6aa7a43a11856e23b1e732d00e5fe3885b7dad42ec18ac8e096a080f7d55070fdcff607bc0b852d8a080d2a7405d59414695f2eb7fb0aca23c8635742f8ae57f13780316e280872374e6929598d028a33c05d831cdabd029493c3cc859fff1a67d56216f02a2295665365887a350a80afaa0c367a74d3701ae88f59d8a9d3a1dce0cfd2eabe2af5065a1c7fca4aadcf8e51e75612a1371b4dc8ffc0c0b9c4fadb2f081e2e032d96818e55737adde3e1ac121f56cc86fb58a0a582692f62ce58acce17aafec7bcb7e44f839258cd4a851fc01344ee9f1bd03eb94344f4778693c171dd2892b2426a8829ab0cfe33a7d4a36eb4017f7fcfd24134ab8a45f23717cd138aa6000172e37b4064dc9b6d1e1ef3af84971d:8965a889d54cd8076d35bc2e12b009d56b0704c894f912a0d1d30720c232fe4404bf3009541e8f3283e89ea86f678afbdf1c21c924b23a52b4ca6d63f48fc2032b2857f45280173e2e0ef9d594e6083f1dc7a65492975b837def6cadd8c8545031ee9d68369a9393cc7b792feb98040b21f1eb84665f878537ce412e9db680d29fbd8ffc7731eae91a20b47548996204fb06ad740e78f0fc590b6791dc7a0f2659286cc16d02c5117b565836b4b8738cf40e285c69c50e412911292367352dfdaed9982d0f899a23c0ab51812b3ec678f6882ea427cdc93ab4b24824377054aa25d82246653340078cf11d14a51f0e686d7e018b36741668fce7458d169293361dd16b3debbed19e1bef7c36934e20f33a09ad3e82b53ab4e94c255d041898b97737df99584af14e404058d0c93bcae7bbbc06395a2aefbdefa7b2ed17cebd1513fa390fe9a9b0ce68cecc2b9e129b7a29f49b6d18c28bacd3af39dc39ca972f0e0d06855d57c2b5fcac2f79cb8c05799e4f65734668dad6aa7a43a11856e23b1e732d00e5fe3885b7dad42ec18ac8e096a080f7d55070fdcff607bc0b852d8a080d2a7405d59414695f2eb7fb0aca23c8635742f8ae57f13780316e280872374e6929598d028a33c05d831cdabd029493c3cc859fff1a67d56216f02a2295665365887a350a80afaa0c367a74d3701ae88f59d8a9d3a1dce0cfd2eabe2af5065a1c7fca4aadcf8e51e75612a1371b4dc8ffc0c0b9c4fadb2f081e2e032d96818e55737adde3e1ac121f56cc86fb58a0a582692f62ce58acce17aafec7bcb7e44f839258cd4a851fc01344ee9f1bd03eb94344f4778693c171dd2892b2426a8829ab0cfe33a7d4a36eb4017f7fcfd24134ab8a45f23717cd138aa6000172e37b4064dc9b6d1e1ef3af84971d: +3335ea928117cfeefbeeae146003881bdc8889d6580eed1352370820ad1f584fcb20d4fd7561848013111c3e97617f34181d2e7fbcf1bb2a2cd2e8c1775b8b03:cb20d4fd7561848013111c3e97617f34181d2e7fbcf1bb2a2cd2e8c1775b8b03:0fa7f6a6fca981429b572a6704871bed140dab93ee1992006e9a3bb2e6cc9a09d4c9cf17066b32ff7ef5b6b2e7911178ed7462c4c175603171ca613668b3be193d94c3521e588913b5948b550be99d82d966197d710acfd95914cf3e197536e83e68230dc3d67e67dcdbdee04f0d9c480237ecd28f74338db5f3f697d3d07ff33613bbce542acc9a7fed5d12490b9bfe1d109540f863800dd356da841a45a3cd8a08a945bfa3aa98e1712312c4c0f0d9dd64f6efcf736bd97deafca9dcaa3f06d87f2ed72aeb6a94f3280000c4bf728a01c1862dafd9fc5c7d5a46ec7d3a87af59a11d87f7ff84407d37010e1d946cf225d6b3b1edee2e8bbf1e079e47fb1f66669394fbf2fa68fc56fc89820a6809c251dd62f5b865c547b14fbd3a19504244ffbc7e5240f88d4360f9cacaaf5f82433d3344fcaee0acdeb7beb9c0b3c769eac920ef4f09abc2a2095512045943eccc53b1c03ed24e567f3d7a71977cab9840ce898ee58ed5c73f6adea823394c5c8e3658a6bf5acbbf0055992c312c26c79c5cfbea3860b8764a6d8ffe4491f8a5b8a215e0117a9a68164aee25f8c0bb381195b2400bcb4644ebce1cde5a9a26582cab9dc7f43c33eae350db65aa7dd22a079bdddcf56d848deb0cfa50b3bd732d9da9e8d8ab79e93469de5802b6dff5ac2aa8482bb0b036d8f9d595b8ead94bb8d7418e2ea43192efcbfc05c467bde0a868a516a7c14a889b72c5b73e7d85c2bae902e4e68d1f3ceab2b2773af5bbaee6a00d08063e7833cd4e295347e58f5d1b3397f640c159cc60a674a227b4cd8c10f1dbaed516ccacdd295f11b08147:f7c39f9247d22f018999247f0e0005cd63076ccf2fee4163421f86407a41698c405816647351c04e93b54415b62fc03fc8c25e20f7541dab03197dc900b29c0c0fa7f6a6fca981429b572a6704871bed140dab93ee1992006e9a3bb2e6cc9a09d4c9cf17066b32ff7ef5b6b2e7911178ed7462c4c175603171ca613668b3be193d94c3521e588913b5948b550be99d82d966197d710acfd95914cf3e197536e83e68230dc3d67e67dcdbdee04f0d9c480237ecd28f74338db5f3f697d3d07ff33613bbce542acc9a7fed5d12490b9bfe1d109540f863800dd356da841a45a3cd8a08a945bfa3aa98e1712312c4c0f0d9dd64f6efcf736bd97deafca9dcaa3f06d87f2ed72aeb6a94f3280000c4bf728a01c1862dafd9fc5c7d5a46ec7d3a87af59a11d87f7ff84407d37010e1d946cf225d6b3b1edee2e8bbf1e079e47fb1f66669394fbf2fa68fc56fc89820a6809c251dd62f5b865c547b14fbd3a19504244ffbc7e5240f88d4360f9cacaaf5f82433d3344fcaee0acdeb7beb9c0b3c769eac920ef4f09abc2a2095512045943eccc53b1c03ed24e567f3d7a71977cab9840ce898ee58ed5c73f6adea823394c5c8e3658a6bf5acbbf0055992c312c26c79c5cfbea3860b8764a6d8ffe4491f8a5b8a215e0117a9a68164aee25f8c0bb381195b2400bcb4644ebce1cde5a9a26582cab9dc7f43c33eae350db65aa7dd22a079bdddcf56d848deb0cfa50b3bd732d9da9e8d8ab79e93469de5802b6dff5ac2aa8482bb0b036d8f9d595b8ead94bb8d7418e2ea43192efcbfc05c467bde0a868a516a7c14a889b72c5b73e7d85c2bae902e4e68d1f3ceab2b2773af5bbaee6a00d08063e7833cd4e295347e58f5d1b3397f640c159cc60a674a227b4cd8c10f1dbaed516ccacdd295f11b08147: +32a1883eff57a3a7ecdb310221ee83c4de92b722159613ecf816e382437b60b982dd1a03e5852062ba4a8b6b3b93c5e9c43ff6995bd2aac72606fac85802c682:82dd1a03e5852062ba4a8b6b3b93c5e9c43ff6995bd2aac72606fac85802c682:ed2b123b5dd7f5e718e026c79cfa6111924902d189a406ef2b2e56a9ee5573a76ddd1d0629ebcdecf2aaa74e84fcd0208f14eea2e171e7c8608b818feff4dbea52db354227d023250b1f01cb4cc8c52132a98d4acf55a54fee81e094aed66fa0d6b6a200b6b87414402278538b90529a8c603d927eddda97bc4b8cb95d04b5337fa22ceafc8b340c46fef67198d1fd98d89c65cd089e23f53dbdca967798b5cd923205ad511edf706f1225f4648c985e009ef8a2f6a0117cdbe14e75312d8ac1f03d046b37cdee7d69c0f25ccf18145a688a8b3ca8875fe8d90baf86d43969e4d610214f1ac5dbba87a1ef10377e40d7806fd9d23457fc9df29899239fd1d278849681a943ad9c91fd1bbd92b73cb177a878f9059ee07af7a8731613e33d59df3d97796079d5631ed85eb2245106a5ff6a2bca40df5c6e87473b2c08c2212f56fc2933a969a3c958d37c5343ba2760c813a7a5165d231c5feaae62b755df49feca80041a6535f7e03bc48e5f27f9be26ef53673eb7c37a2b64744a6cf17e887734ae010bf40eea03cda212f512fba0585947179640bcc4544b8deb4ead129bc3322800adf98818f99574befd9b0016d4eec81a8e78dc3a2af13cab01649ae2e33d516b9d4208ad6613d8e278c393baa882340ef461ff4f94423d55cf3cedd2a6b56e88365531dd29d68273adbfe369402e6a7cee053da1f100540091a00929252983449024b1c3391110650082f0e7dfddb8edc2042f3c1713c6944ba514ee7407d32bf06c858efec42a78bee97746e5b4879141a13d9fc5cb123b783273b84d57ad3526b7da3c68b839efd23f5f:8309cbe72f804bd9521def5dad4d8bc13886b1d4f662c9bb5b97ba4790f44b801f3195ead0d4ddb660818ecbf9a683cacf85f1dcc9e82c09116d733658091a00ed2b123b5dd7f5e718e026c79cfa6111924902d189a406ef2b2e56a9ee5573a76ddd1d0629ebcdecf2aaa74e84fcd0208f14eea2e171e7c8608b818feff4dbea52db354227d023250b1f01cb4cc8c52132a98d4acf55a54fee81e094aed66fa0d6b6a200b6b87414402278538b90529a8c603d927eddda97bc4b8cb95d04b5337fa22ceafc8b340c46fef67198d1fd98d89c65cd089e23f53dbdca967798b5cd923205ad511edf706f1225f4648c985e009ef8a2f6a0117cdbe14e75312d8ac1f03d046b37cdee7d69c0f25ccf18145a688a8b3ca8875fe8d90baf86d43969e4d610214f1ac5dbba87a1ef10377e40d7806fd9d23457fc9df29899239fd1d278849681a943ad9c91fd1bbd92b73cb177a878f9059ee07af7a8731613e33d59df3d97796079d5631ed85eb2245106a5ff6a2bca40df5c6e87473b2c08c2212f56fc2933a969a3c958d37c5343ba2760c813a7a5165d231c5feaae62b755df49feca80041a6535f7e03bc48e5f27f9be26ef53673eb7c37a2b64744a6cf17e887734ae010bf40eea03cda212f512fba0585947179640bcc4544b8deb4ead129bc3322800adf98818f99574befd9b0016d4eec81a8e78dc3a2af13cab01649ae2e33d516b9d4208ad6613d8e278c393baa882340ef461ff4f94423d55cf3cedd2a6b56e88365531dd29d68273adbfe369402e6a7cee053da1f100540091a00929252983449024b1c3391110650082f0e7dfddb8edc2042f3c1713c6944ba514ee7407d32bf06c858efec42a78bee97746e5b4879141a13d9fc5cb123b783273b84d57ad3526b7da3c68b839efd23f5f: +22ecef6dabe58c0669b804664973e457c05e4777f781c52522af76b95481a914d4784010ef0403eddc5a62d5d45bb243b80b4b9d69c39ca387c6f5cba028640f:d4784010ef0403eddc5a62d5d45bb243b80b4b9d69c39ca387c6f5cba028640f:c535c13d779fc0985973d6bcd552d81734e92bdf10994b00cd4d53ce365fad8c7cfa96206adb62d4567be5e46631323853e38ce4bdc16d7b8f632a3ad9e02619eff37174eac3f0bf2f7a7517d4b82de6aa1af0063819d5e1f9278fb4f24c8cc002afb15f334c04fadb00303013c01667f4932a6c4b97d39cd4a4598506c0bd740ea9f11696357d7d17fe4d75f9d74241a7af71f9d869ef6cd695687c03fc34ad65a68a4888a1a74126cb55cf7da9cb4a6717f6eb88484089d2c5189ae381f25e7b3bc3b23d0c9d9f9cdbbeecfd1e72a05e67bb483a9764d9fc75ad69e4ab1270fb40f3958fea4da559b43980b24681313e8591e68546a3bf76ee34b339709295a8d46fb2432dda2f221812df692895e67cb29cbf6ff4502b439a4e9e43639ec067bc90ae814a293a7bd46968e656787642300a0ff2697e3313f6a418d3d12a5f7c51a4c57b63385f2d2a21d5d1d763fc8d1b93c13435f9e47ee7a425980a6ae6f1a9d007607476783c6d0c7887380f868c65b382d4cc8c04478bbd79a1d9a964b78171d6bcf0b8eec50a06a4ea234d1c23465d3e75b88bc540dade74ed42675b07f7cf078211e907f86d0dc4b978623d9f08738af928695e542ec2980e55a1de49e25247fa0a09678118e3930bc4d24b3214d6dcfb6ebdf4906c928deb37bb9ba29c8de1bb9418db718b2853ba57ad8cae4677addfd18b6c7e8c242621b35c7f0efe8dd5eb26ff75fd5748b1d783f6d68a7d9d56da2c1a978ac25f84fbb2be5568d91e70938221c102aee60409bcbec0c82e12ddb425eeb6ecd11551ecd1d33ddae871ae0c8f24d0d18018732b5e0e:5d0d2af678b3d1b677516d08a79aafd36ec67c14caf5bcdaaeaacc51a14fb805cf2904e8721db271b20df709bee1a4fbfe62565073b2a7e942724461f927930dc535c13d779fc0985973d6bcd552d81734e92bdf10994b00cd4d53ce365fad8c7cfa96206adb62d4567be5e46631323853e38ce4bdc16d7b8f632a3ad9e02619eff37174eac3f0bf2f7a7517d4b82de6aa1af0063819d5e1f9278fb4f24c8cc002afb15f334c04fadb00303013c01667f4932a6c4b97d39cd4a4598506c0bd740ea9f11696357d7d17fe4d75f9d74241a7af71f9d869ef6cd695687c03fc34ad65a68a4888a1a74126cb55cf7da9cb4a6717f6eb88484089d2c5189ae381f25e7b3bc3b23d0c9d9f9cdbbeecfd1e72a05e67bb483a9764d9fc75ad69e4ab1270fb40f3958fea4da559b43980b24681313e8591e68546a3bf76ee34b339709295a8d46fb2432dda2f221812df692895e67cb29cbf6ff4502b439a4e9e43639ec067bc90ae814a293a7bd46968e656787642300a0ff2697e3313f6a418d3d12a5f7c51a4c57b63385f2d2a21d5d1d763fc8d1b93c13435f9e47ee7a425980a6ae6f1a9d007607476783c6d0c7887380f868c65b382d4cc8c04478bbd79a1d9a964b78171d6bcf0b8eec50a06a4ea234d1c23465d3e75b88bc540dade74ed42675b07f7cf078211e907f86d0dc4b978623d9f08738af928695e542ec2980e55a1de49e25247fa0a09678118e3930bc4d24b3214d6dcfb6ebdf4906c928deb37bb9ba29c8de1bb9418db718b2853ba57ad8cae4677addfd18b6c7e8c242621b35c7f0efe8dd5eb26ff75fd5748b1d783f6d68a7d9d56da2c1a978ac25f84fbb2be5568d91e70938221c102aee60409bcbec0c82e12ddb425eeb6ecd11551ecd1d33ddae871ae0c8f24d0d18018732b5e0e: +8de86330b256095e1114b6529bedce182c166f67a91539cebc4bec25add7a4a933cb054b55bb790ac0f3afdd9a6e7c050efe9006c24f60b8044fd08a5c106c11:33cb054b55bb790ac0f3afdd9a6e7c050efe9006c24f60b8044fd08a5c106c11:39e61e0eccec929c87b8b22d4fd18aeabf42e9ce7b015f2a8cac92a52448a42fed4cbadc085bbb4c03712ae72cfcb800b978350669b0990084f2dab76eca606d1a49fc55c529e1e7dadf39122dd5bd733893858b0523ef62df4f134cf6c26eed02fdbcb30ce474b1ada3f060769f934bbe686ccebd60883ecec9ce3ffb8ac4a0678cdc5b005ae3dba7e4fe8bc045739957d849f69c1474057b428c5425f3cc2516e8bbe3be81afd4e7b575abe88c87f2f03b56f69f9e3b61b3788120daa495ef0e50eb970a645c13d213c7cfb7d0ad555c920a1e5dbcb46797d939fe0401f547bfd17543221a53010de01f25b64519c8f03963e4b9ca58b0113627c05b9608eeaa7b9ae6305c96188160000ee3a7ade96e0b4bde9d0ed6a0ced765d786840a48175a6e090a38af6adeaa1486a9cb5c8c8c9223ee0ae4c6c02691a3547e32582a5b7059d2ee66fa9cd965615c315b476fd861279cd1dd7607743fc5561296312f11e465ca40bce3cf0b1f1d5a30af6087de4de96ce43965a46c4fcca15f281149b5c1a0c88fdbf27409a134ed4f1fb730fa191816ea784d986cc9ec4b694402de1dcca9ccc64fbd07b07e54e931de827a842460ca0bf6b04ebb571fa77787e3884be22f1e402cf2b8a96a5d39770ec4a843036142a0be970bb1ab165a6374dcf43deb8b9830b2c49db9cdfe4b5242e36f95e0c3e077e8d238fa6a8ac0d586bf61b8248fb3a79a270ab22be8a9da055ff3d5bb2d1ca9bc25f7014b96407719de344c3e73b8c114f792075a5c22fdd416154d3494ec3f02fb112ee5737f70704c1b6b07eacbf94562ca7b90dd84d98c3edf:6d01d237dd2bb4188d29bfdec387976a71be7adfbf9e23639b216d0aa0c11932235edccb3b42adcdb6291a0d299aed648de8b1957949b9d1cf2e50493030a40f39e61e0eccec929c87b8b22d4fd18aeabf42e9ce7b015f2a8cac92a52448a42fed4cbadc085bbb4c03712ae72cfcb800b978350669b0990084f2dab76eca606d1a49fc55c529e1e7dadf39122dd5bd733893858b0523ef62df4f134cf6c26eed02fdbcb30ce474b1ada3f060769f934bbe686ccebd60883ecec9ce3ffb8ac4a0678cdc5b005ae3dba7e4fe8bc045739957d849f69c1474057b428c5425f3cc2516e8bbe3be81afd4e7b575abe88c87f2f03b56f69f9e3b61b3788120daa495ef0e50eb970a645c13d213c7cfb7d0ad555c920a1e5dbcb46797d939fe0401f547bfd17543221a53010de01f25b64519c8f03963e4b9ca58b0113627c05b9608eeaa7b9ae6305c96188160000ee3a7ade96e0b4bde9d0ed6a0ced765d786840a48175a6e090a38af6adeaa1486a9cb5c8c8c9223ee0ae4c6c02691a3547e32582a5b7059d2ee66fa9cd965615c315b476fd861279cd1dd7607743fc5561296312f11e465ca40bce3cf0b1f1d5a30af6087de4de96ce43965a46c4fcca15f281149b5c1a0c88fdbf27409a134ed4f1fb730fa191816ea784d986cc9ec4b694402de1dcca9ccc64fbd07b07e54e931de827a842460ca0bf6b04ebb571fa77787e3884be22f1e402cf2b8a96a5d39770ec4a843036142a0be970bb1ab165a6374dcf43deb8b9830b2c49db9cdfe4b5242e36f95e0c3e077e8d238fa6a8ac0d586bf61b8248fb3a79a270ab22be8a9da055ff3d5bb2d1ca9bc25f7014b96407719de344c3e73b8c114f792075a5c22fdd416154d3494ec3f02fb112ee5737f70704c1b6b07eacbf94562ca7b90dd84d98c3edf: +bab5fa49187da1cab1d291900019e6cbafeccd27bf7ecbf1262a700516e7c29ff6fb1985ec591f69e3bac807b2eabf263990cdfa09b17809e48e385da065ec21:f6fb1985ec591f69e3bac807b2eabf263990cdfa09b17809e48e385da065ec21:5cf8ff587e52cccd2984f34791ee6843e77017c3b55ad45c44450965b75d836e78fbd7a1d1729eff6d6d340a903f3cf17d9e2aecaaff2a321fcdde0abcfbbcbcc09f4086f812c46efb01b78343afbe48309f917478455f32000c6a69f79fe211b99f037f5956d72275a7fe7b45296b5f739aa451ff0575bc705885aa5631b0d0850bc2b12c4192435ae5d2f52bc54386497c4a24b8b6db516be09d8ccf1eca785bde97e9be1ac064f094e2afcc307c0e06b4c564cd9a9a95305b37b81f434611dca55caaa031e88495d5dc5a04ff5fafdf0a82a0c03aff1bfbf4ffebae71824e35e751b09270007669860b580035659e23ace76b3b369fa306f2bed95799fafabc2e69c141beb0bacac7eaa347e77be5af3fcdbe7b364a7f9a66d5e17a07df6202fd98c14bfee2ca6f0745651f0c8550f9ffffcafb96ffb3f103e652e78f53916cd6f1dd05b3fe99b34201b07eac2652f5253571fd3822c695d265c7dfdd6c6b14a80b6e87183e6e032e5f2401cd238cdd3769bb6e390823438f5673ea9a479e5c63fe07a07f4e14f57757c4d7d22b35d71c44eaad4873c8eca6f6b21dcfa95520ff9614abf7a0e1885309f2ced3bcdfc319363a2da46ded79a5cc7b6f69383f94ab35c250629cb915d667b6281186754895803e4b95e7418289a6ac3bcdb6e1e7f6f1dc38e77d281914cc404f97cff14fb2c4fd81412d101c1bfb368ce59311e892a8b9cdca86936f3bca7ec79163eddf1cee68f49f1ebaa27ec50f490d61601ca35f8d6ed266054aeb9b199f933bffd6e0050f261b4e13d5ebfe2caa6557c32ddeaeebc2a11f0aa233240da1c7e40f76:e316038d6aa15b1c1b61c1a16b36904fe8a289c8d602becc514d99220086b267859f5bf6e9c0863559ac623a56d7532344e8d2f28b3f9df92089708b1b0590085cf8ff587e52cccd2984f34791ee6843e77017c3b55ad45c44450965b75d836e78fbd7a1d1729eff6d6d340a903f3cf17d9e2aecaaff2a321fcdde0abcfbbcbcc09f4086f812c46efb01b78343afbe48309f917478455f32000c6a69f79fe211b99f037f5956d72275a7fe7b45296b5f739aa451ff0575bc705885aa5631b0d0850bc2b12c4192435ae5d2f52bc54386497c4a24b8b6db516be09d8ccf1eca785bde97e9be1ac064f094e2afcc307c0e06b4c564cd9a9a95305b37b81f434611dca55caaa031e88495d5dc5a04ff5fafdf0a82a0c03aff1bfbf4ffebae71824e35e751b09270007669860b580035659e23ace76b3b369fa306f2bed95799fafabc2e69c141beb0bacac7eaa347e77be5af3fcdbe7b364a7f9a66d5e17a07df6202fd98c14bfee2ca6f0745651f0c8550f9ffffcafb96ffb3f103e652e78f53916cd6f1dd05b3fe99b34201b07eac2652f5253571fd3822c695d265c7dfdd6c6b14a80b6e87183e6e032e5f2401cd238cdd3769bb6e390823438f5673ea9a479e5c63fe07a07f4e14f57757c4d7d22b35d71c44eaad4873c8eca6f6b21dcfa95520ff9614abf7a0e1885309f2ced3bcdfc319363a2da46ded79a5cc7b6f69383f94ab35c250629cb915d667b6281186754895803e4b95e7418289a6ac3bcdb6e1e7f6f1dc38e77d281914cc404f97cff14fb2c4fd81412d101c1bfb368ce59311e892a8b9cdca86936f3bca7ec79163eddf1cee68f49f1ebaa27ec50f490d61601ca35f8d6ed266054aeb9b199f933bffd6e0050f261b4e13d5ebfe2caa6557c32ddeaeebc2a11f0aa233240da1c7e40f76: +74ca122ab60de50cdc04a8e2eda45d9631061bf187d316be5b7cc06f020c483e787defd4fb24a399bd2a4e76dff7d603ed0acb3269813e4df690bbf5b2bc696e:787defd4fb24a399bd2a4e76dff7d603ed0acb3269813e4df690bbf5b2bc696e:a80b46079fa775f8c1a19fa0829be666bdfdca079cad43d70e0842183bc0db95468a539f0db2aea3ab9c7073b45d228a9bde232897a6eb6fc9edf7365e7101ba97c446a519a3649cf527c8a6de7251b92806815ac2fa0082eff75e2582cbca7e1e4da2a446ea233e7cf7cedfb0e2398eb6e11bbaefe3f7ec89f5d73dd34bd47fbcb4d7b22f2aaee373785651841135cd8661a701b21084a316deac3074e24a2e35a0330f7d1479b932f285277c18a441787224fbbe46c62e834a1851ed237998d48dce20ba114d11e941be29d56d02f7370c8f6d6d7e50248dcd8ec89d3b22f4f58778129fafd4bb92ede17714bf022a5bf92be479f18e63852ecdcf8c4211f530dd30f79cbf4bfa5737f0bad3b0106067f41327c3189e6f206f0d4f3c704bf2bd0b161f018fd21cddfb418bac4d52ef02c41c8792e413b04f0836cea1f86c92e5d5703bee2b5c5899e285992024f64e0d16c60ad0fd92547932d0c5cb98d8da22feebdbba8d1de1e7e9bb219a92eb6c1c698d3b33a37f9b8197d26b550febd2601e7a643ea7e1d9e448ae037f629a306ce417aeb79f2e3ca44d8db3848a811f1846811cbcb874f8af09e0fd0173cf175f304115476bf2c6c2d2f332eba534f46aae801c2692c2d2faddfeacc0f1dace440abc2ae5e5a49d578fd7f9de2a841ad6b6769c32b144ceea16d0f3c0cb3a8ee694c38c28073595096c813762cc2c5ec4b0d8d723dd660853278fc72fd6bd9d1272933dd2a38ed9d04b1390ffe4b294a6fffa721ee3bba33a03a149c4a0345265c01ce015e94db419cff7049852ee000048a85758f6d7b1c59c5089ee018ed09b52:bcb4b850696011997eb5dfe143f1a3d5628ef1a5407691ee48c79d69abe4d533f817ad7313b5795e46e595f3ae3a9165b1b6fddae86164ffcba376249837f609a80b46079fa775f8c1a19fa0829be666bdfdca079cad43d70e0842183bc0db95468a539f0db2aea3ab9c7073b45d228a9bde232897a6eb6fc9edf7365e7101ba97c446a519a3649cf527c8a6de7251b92806815ac2fa0082eff75e2582cbca7e1e4da2a446ea233e7cf7cedfb0e2398eb6e11bbaefe3f7ec89f5d73dd34bd47fbcb4d7b22f2aaee373785651841135cd8661a701b21084a316deac3074e24a2e35a0330f7d1479b932f285277c18a441787224fbbe46c62e834a1851ed237998d48dce20ba114d11e941be29d56d02f7370c8f6d6d7e50248dcd8ec89d3b22f4f58778129fafd4bb92ede17714bf022a5bf92be479f18e63852ecdcf8c4211f530dd30f79cbf4bfa5737f0bad3b0106067f41327c3189e6f206f0d4f3c704bf2bd0b161f018fd21cddfb418bac4d52ef02c41c8792e413b04f0836cea1f86c92e5d5703bee2b5c5899e285992024f64e0d16c60ad0fd92547932d0c5cb98d8da22feebdbba8d1de1e7e9bb219a92eb6c1c698d3b33a37f9b8197d26b550febd2601e7a643ea7e1d9e448ae037f629a306ce417aeb79f2e3ca44d8db3848a811f1846811cbcb874f8af09e0fd0173cf175f304115476bf2c6c2d2f332eba534f46aae801c2692c2d2faddfeacc0f1dace440abc2ae5e5a49d578fd7f9de2a841ad6b6769c32b144ceea16d0f3c0cb3a8ee694c38c28073595096c813762cc2c5ec4b0d8d723dd660853278fc72fd6bd9d1272933dd2a38ed9d04b1390ffe4b294a6fffa721ee3bba33a03a149c4a0345265c01ce015e94db419cff7049852ee000048a85758f6d7b1c59c5089ee018ed09b52: +65eea9ffb75612bde1d9ba3ea4fb5eda0aa6f2556ab15bf1817cee3b95bbba125b3936dc749b6b9239f15798accafd884c3659ee01b2d17d74fc7da78274e7e6:5b3936dc749b6b9239f15798accafd884c3659ee01b2d17d74fc7da78274e7e6:c06936323ce3253cac5ab4f6b83270cd4cfe85d0bf8bac1e1b8d5f0b153f541c8e8ed95f28d5c85a2315cd931b7cf3edae50f92830599162804b1363d3ac0da0abd09751023bddc16288944e616d21d91271978bb782d3ebed7fa61284c7490d27593ca8a3d5b475623307010abc1fbf793a816aaab5e0924dec79d60498965cf7f80ab59fc029f782166755b72b869075434ab606cc870a7c0bc8bf29aee033fa9cc122ed7c8e069b547dbae25901b9e249b41fea0bf8daf3826866bcaed2753b5e91ae937e717b508a0acf4c3b061ff0cb9cfd380e2494500951a662fd4928fc5fcaf6c18e84b1d378e49bd9d59686d087ebd552d07fa9ba816fa5402ca9e7252a648d106cfe6c431cc2a053e2294637cdb99d96abe689edabc5ca070f77c1ecd1d52d5385289f17ced768c3971671b9c0b2f855b8461c1e746c7b38f77896b85afbbedd08375fe922984614dd849fe2cb89ae7149dcd1d37f4936e67b1440be72e009398be6f083bf9611480b592fe2f0118e253db5d2e9e4b4541c11da00f7161a736e5f0bb934208e3ef4e0b9a52258203f060d18a195159e5e268aa28053c834f7bd5db9bd71f507d91370b3ffcabbd4acb3071d3f6d52c349acf35095348cebf5a86f8c59ddc965eff610ac425804c0e2f6be42853f5b46434a2c31d9ac99539bfdc04ecf2fefd04598fa63c139ff6c6d88410e73bd328cc4349ab4bb86f2e2ed7c73de96520ef7730ef38345e0f972a84c5388103687e68c50f9d8c9af903bc632d43204062a4f502e214c07059c2cbef72a54110dbf73e425402d17e978ec199b518cec0310bfbf7d9ad300434a4a:baa7113155358c924fed57488a6567f8723850a9f5c03a0d7de85fccd8fb4d17d7753523b00c0d8adb884dc0c8a7a44dc2a60083aa5b3c5b94a8d880f2a94d09c06936323ce3253cac5ab4f6b83270cd4cfe85d0bf8bac1e1b8d5f0b153f541c8e8ed95f28d5c85a2315cd931b7cf3edae50f92830599162804b1363d3ac0da0abd09751023bddc16288944e616d21d91271978bb782d3ebed7fa61284c7490d27593ca8a3d5b475623307010abc1fbf793a816aaab5e0924dec79d60498965cf7f80ab59fc029f782166755b72b869075434ab606cc870a7c0bc8bf29aee033fa9cc122ed7c8e069b547dbae25901b9e249b41fea0bf8daf3826866bcaed2753b5e91ae937e717b508a0acf4c3b061ff0cb9cfd380e2494500951a662fd4928fc5fcaf6c18e84b1d378e49bd9d59686d087ebd552d07fa9ba816fa5402ca9e7252a648d106cfe6c431cc2a053e2294637cdb99d96abe689edabc5ca070f77c1ecd1d52d5385289f17ced768c3971671b9c0b2f855b8461c1e746c7b38f77896b85afbbedd08375fe922984614dd849fe2cb89ae7149dcd1d37f4936e67b1440be72e009398be6f083bf9611480b592fe2f0118e253db5d2e9e4b4541c11da00f7161a736e5f0bb934208e3ef4e0b9a52258203f060d18a195159e5e268aa28053c834f7bd5db9bd71f507d91370b3ffcabbd4acb3071d3f6d52c349acf35095348cebf5a86f8c59ddc965eff610ac425804c0e2f6be42853f5b46434a2c31d9ac99539bfdc04ecf2fefd04598fa63c139ff6c6d88410e73bd328cc4349ab4bb86f2e2ed7c73de96520ef7730ef38345e0f972a84c5388103687e68c50f9d8c9af903bc632d43204062a4f502e214c07059c2cbef72a54110dbf73e425402d17e978ec199b518cec0310bfbf7d9ad300434a4a: +08dabd4e5c119ea907ce45f0a7af9e62c0c3f1c9ec61ad10567d79362854c557945406b85d7b32e0b1ab1200b94222de1aaa68624c60bb4716b0bce9df005771:945406b85d7b32e0b1ab1200b94222de1aaa68624c60bb4716b0bce9df005771:6c4719a5a2a6894835c4ac1ed69159e5ebb5692ad8eaada439f79e96684b36cecfb44b89015631663e0644f6c7ab713989d742da27427253318a52432dfab2121d1e9233ead719e2c86a6be07363d002173f205446ca95fc17b24635827fe315f222408e45e833f29ff08ff31dac583a4bec7076d5cc78cfc94451cbf4f7e2fc5b5ed8070f4ef808be1d8a680ecdff59010f39b1de80bef1719f1e218e0ce0a1e393a566c51764d2370d95a61191d8f7af740dc208fa7831b210670512cd73766e609e9b780021ebb20cc8790d8da5f10f5b6a114a1db88f66766501802d9c366ea3fa6f1b1e1e8b0420943413cc6feab28c6b683cd2b333069c8951bc45e8a13bd522578351c882f7c342fe4331b921f533c92ec04a49b292bc569ddcefcab5727f9b5625b167a902dc896d8bc7d8e99920f5db8dd767839c43e3cdf947080dec954214a6fbbe0487a2f32cd17a6b000370bd414484fb73c510ea0124c6cf0fe56c0846a79bfc59779d3b07a1bd2c7fb7e2d0039f0bd21c8a308fb0f58fdbf94efa0857ac3bdddd86d5763e205ee1b221f060cedb8bc05f031b606cc74dadc5db04232748865a73d6ccddb4d5e930d528348c5be9088bfe34458487a67b19a18eca25c0d3fbe2195eb91707b65d9161ea93eddd64a634b23280195fdb0d1388f6998e1858a45b886999b844e6795d83d31837e4411f71699226de1ba0245608000dcf223dd18359b7c6d459a65dbe66c90f5cb8c09122187a3046a16dd179c3f4373e57cf5ee0eab6a212cc9ed8b54bf37f1d27fbd79848e4ec1f567243ab8740a05149d9602eada920a46d610d3cc823b56498:33adbfcd4ed4fa67c58b5cb59e16987148697812660b3531ff6a21c749b9601660baeee2489b82b4cde132b6e62f2f90d8f9927860aaad25281d03eb17a9520f6c4719a5a2a6894835c4ac1ed69159e5ebb5692ad8eaada439f79e96684b36cecfb44b89015631663e0644f6c7ab713989d742da27427253318a52432dfab2121d1e9233ead719e2c86a6be07363d002173f205446ca95fc17b24635827fe315f222408e45e833f29ff08ff31dac583a4bec7076d5cc78cfc94451cbf4f7e2fc5b5ed8070f4ef808be1d8a680ecdff59010f39b1de80bef1719f1e218e0ce0a1e393a566c51764d2370d95a61191d8f7af740dc208fa7831b210670512cd73766e609e9b780021ebb20cc8790d8da5f10f5b6a114a1db88f66766501802d9c366ea3fa6f1b1e1e8b0420943413cc6feab28c6b683cd2b333069c8951bc45e8a13bd522578351c882f7c342fe4331b921f533c92ec04a49b292bc569ddcefcab5727f9b5625b167a902dc896d8bc7d8e99920f5db8dd767839c43e3cdf947080dec954214a6fbbe0487a2f32cd17a6b000370bd414484fb73c510ea0124c6cf0fe56c0846a79bfc59779d3b07a1bd2c7fb7e2d0039f0bd21c8a308fb0f58fdbf94efa0857ac3bdddd86d5763e205ee1b221f060cedb8bc05f031b606cc74dadc5db04232748865a73d6ccddb4d5e930d528348c5be9088bfe34458487a67b19a18eca25c0d3fbe2195eb91707b65d9161ea93eddd64a634b23280195fdb0d1388f6998e1858a45b886999b844e6795d83d31837e4411f71699226de1ba0245608000dcf223dd18359b7c6d459a65dbe66c90f5cb8c09122187a3046a16dd179c3f4373e57cf5ee0eab6a212cc9ed8b54bf37f1d27fbd79848e4ec1f567243ab8740a05149d9602eada920a46d610d3cc823b56498: +e0f7d00824c5f3701e5517a4abc13e2f2c0b138c836977843bbd1eeffabd968a52fddae3e018a68473b3168d0764cfe274dcc834c90a91fb4fe74b939dd238b1:52fddae3e018a68473b3168d0764cfe274dcc834c90a91fb4fe74b939dd238b1:b39e3ac75a221adcced09a8591ac5e2fe15dfed5b919cbaf14c65eb7cd93086ddee3f7472547e66ddc70062b976297d1a3c170ee525c9c53ba93a4c4fdb23572b7ca6ed13853e70db1d72edeb9944bbc354a520e77ae591f318092efd5e66d9c0981c4a4bda98aa4e59045ff9c4b4ca3acb2ffd893201c70b34a77f24eda54549dc84ad134a35532553815888ae3dd9e241ec4ebbff86f8c1e8adbaac4b91afd18228cbbd5dd805acabf0a1e290ce5dda0251adfb37cb714c139b5a3242d88c64484a37655cc8fcbecffa97fbd14d64d512bf8f6305f89c50922de541692158fb547fd539f1e5877cc649495166332ea2b685cfa3f602019df2ab2c25ed96b68745e9ae89c948da11ad8a830df8b00f2e668192dadf2c5620d35c6e81a2853f841e375a0d9fca2d296efce2ac38d40b030b57560ae6e8341339b3d3c2d061164124319598688fca618fc64c9e8f5f831097a053af19d7dbd61218d926742c2e9a42a79cc1b148912722d8cd5ca793a1ad73b5f141b41809c2fc0530b7630e80390c6b338c71868dacc59bf463ffc489016bf67f9c9d5553c1ede17152813fe0b264b65dca1b2b38e4b809f8c9725ac5b1d8d2e56bec9649fe55c7583ff23b043d6f3768628f1f0516337824a5a56b409520a6a6cb77e4f5fc20b9f6899e00ab22db10d182f09b81e94f3ad568a0b81244df3f1855c6ef222a41a51b62a4649bb82690ab65facac0d81d6fe02601170a8db62cbc5ec9955d7711a1c39656a9f6e1fb6bc183d9bea1503531f17362768bb841f9d21f13a2c991e55dff7f2b336e29eb29507638bdcad7bb31c69e909207ebabcc653ff:ccdfe18ad6d0b65d086d632f83cc46ff3b3f2c07bb8e769d0fb4e82df8a3873f9aee35fdd18a5783603180a95c9f74ced9db5146afcfbbdd40df29e04201200cb39e3ac75a221adcced09a8591ac5e2fe15dfed5b919cbaf14c65eb7cd93086ddee3f7472547e66ddc70062b976297d1a3c170ee525c9c53ba93a4c4fdb23572b7ca6ed13853e70db1d72edeb9944bbc354a520e77ae591f318092efd5e66d9c0981c4a4bda98aa4e59045ff9c4b4ca3acb2ffd893201c70b34a77f24eda54549dc84ad134a35532553815888ae3dd9e241ec4ebbff86f8c1e8adbaac4b91afd18228cbbd5dd805acabf0a1e290ce5dda0251adfb37cb714c139b5a3242d88c64484a37655cc8fcbecffa97fbd14d64d512bf8f6305f89c50922de541692158fb547fd539f1e5877cc649495166332ea2b685cfa3f602019df2ab2c25ed96b68745e9ae89c948da11ad8a830df8b00f2e668192dadf2c5620d35c6e81a2853f841e375a0d9fca2d296efce2ac38d40b030b57560ae6e8341339b3d3c2d061164124319598688fca618fc64c9e8f5f831097a053af19d7dbd61218d926742c2e9a42a79cc1b148912722d8cd5ca793a1ad73b5f141b41809c2fc0530b7630e80390c6b338c71868dacc59bf463ffc489016bf67f9c9d5553c1ede17152813fe0b264b65dca1b2b38e4b809f8c9725ac5b1d8d2e56bec9649fe55c7583ff23b043d6f3768628f1f0516337824a5a56b409520a6a6cb77e4f5fc20b9f6899e00ab22db10d182f09b81e94f3ad568a0b81244df3f1855c6ef222a41a51b62a4649bb82690ab65facac0d81d6fe02601170a8db62cbc5ec9955d7711a1c39656a9f6e1fb6bc183d9bea1503531f17362768bb841f9d21f13a2c991e55dff7f2b336e29eb29507638bdcad7bb31c69e909207ebabcc653ff: +6acd939e422226cc5443d4aabf58c11af650cb40b9648b4da38b927bff9a58db4c0b91756b9e206f7863b155ffc5509bb52477ceacd01ca011435153678646cc:4c0b91756b9e206f7863b155ffc5509bb52477ceacd01ca011435153678646cc:8250d531cf2b66aac2b378d54bc57fd329ad5a414a599255898b3c3b45bf9c0d2c77547566b660eecc76a695a2d608abf11a5f6db3e607fd5a21714b0fad5d814c015ebf48bb73ad75da9c03c4af5489e782b6bf7908a1bd528d7ce788a18ba3528e3537aa7bbf75f6524bbd19a5304ba2a4a3ee58c41fec3132ee6501641215eff746d7800c4d33f52be8357e0ee758041d91cfe43c60c3cedc09b0d46d4cfb9ae2a0239b6f33c6941cff35372670eef5c8859ab65b6e9f7ebce32fa15a9a477aecdc9683a1e33a1edcdc90d420a31e78c153d26020871daa4fff28acc3f11a7206788806b6fa023468ea5a3d186d10f0dd567796663ba37c832fe75aae7dccebf319f93600c46a22f57223812ddd0a68d76baf5e27a9fc8bd68cc10b5b5151d62b41f9348e21b715352f2630b617f813b0c28996285904cf294e9c2856b17ba35f9a82198b8214a035e2896d6568be42392ccef32cd4ebfeebf12be0125206bbe89336d3e762991dfab68fc99dc1649b891383db31fab649e628823f4598cb636a38fe1df73e68d7425fc5d2eb55a0fd1bc9f5ceaabd6dd41f23e4f086c692633dc3c4619a97ab0eada171f84adf20ecc8ecd47c51cca3e59dd809b0aeaa730df94be3bacfd8ee888bba9d570850652cd4d5e6c552a57e9f48a2b06aacdc708d84a376fbc6c94ba6bf64a5f018800a7cc851245aedb20378b329acebb2977c1398082b3a0e5e2a9c2484fa301d3037a8224ddcc095b1dbd8a2315b55bf3318c27810efc3d8e25fa7a8789b73a4f55059080b08abb3699b7b8626cb2a780d97cc1ca8032851baf4ed8b64fc4330865f84ccb12a3dae:79995877ed24c791684f2984bdf9609c3f7b576c57d162ee622d4ce8f36d9c5573169d8801216f1c46ffe2f6e2c09048e47d4beb997e9abc4abb129f9b79690a8250d531cf2b66aac2b378d54bc57fd329ad5a414a599255898b3c3b45bf9c0d2c77547566b660eecc76a695a2d608abf11a5f6db3e607fd5a21714b0fad5d814c015ebf48bb73ad75da9c03c4af5489e782b6bf7908a1bd528d7ce788a18ba3528e3537aa7bbf75f6524bbd19a5304ba2a4a3ee58c41fec3132ee6501641215eff746d7800c4d33f52be8357e0ee758041d91cfe43c60c3cedc09b0d46d4cfb9ae2a0239b6f33c6941cff35372670eef5c8859ab65b6e9f7ebce32fa15a9a477aecdc9683a1e33a1edcdc90d420a31e78c153d26020871daa4fff28acc3f11a7206788806b6fa023468ea5a3d186d10f0dd567796663ba37c832fe75aae7dccebf319f93600c46a22f57223812ddd0a68d76baf5e27a9fc8bd68cc10b5b5151d62b41f9348e21b715352f2630b617f813b0c28996285904cf294e9c2856b17ba35f9a82198b8214a035e2896d6568be42392ccef32cd4ebfeebf12be0125206bbe89336d3e762991dfab68fc99dc1649b891383db31fab649e628823f4598cb636a38fe1df73e68d7425fc5d2eb55a0fd1bc9f5ceaabd6dd41f23e4f086c692633dc3c4619a97ab0eada171f84adf20ecc8ecd47c51cca3e59dd809b0aeaa730df94be3bacfd8ee888bba9d570850652cd4d5e6c552a57e9f48a2b06aacdc708d84a376fbc6c94ba6bf64a5f018800a7cc851245aedb20378b329acebb2977c1398082b3a0e5e2a9c2484fa301d3037a8224ddcc095b1dbd8a2315b55bf3318c27810efc3d8e25fa7a8789b73a4f55059080b08abb3699b7b8626cb2a780d97cc1ca8032851baf4ed8b64fc4330865f84ccb12a3dae: +4deff647cbc45ecaedc3f7ddf22c167af24e3d63da22b0e6a5b8439c0f3b19340c27c9d77ac8c725bb0663933ab30d1aad09cbcf2cd7116c6085a8499f701402:0c27c9d77ac8c725bb0663933ab30d1aad09cbcf2cd7116c6085a8499f701402:d6201ebc21cec1e9bc28f957c9d029cc38f9e85e06dfc90bf297e61f2b73b407d982a66b91e94a24e91d06ab8a5c079d0f69be5788ea8feacebd917291192233862e6acda1e8cf9a48bffb5491dd65af541b6c72af681a81823d98a0abeeb6ba9f95465b8411f99e119cd28479da984259bdf86c9fef3cca34e224691f183cf095037727da9cad29f242f83eb4f736e27fdf67018d711b74c45b2955a6a76ec15330df5bad8030c6b3a88d72f28447652ac8902b5b76cbf6b945ceabfec04a9b8cb30f43d9eb773e6705594f0de1b70f1a20c99fc4b1221f8c81b0bc30da12cd5dea8f4d90f13a811a2cc11a96846aafb4c42a00e9ae7da256a0d22b198afc25cc1041d24e056cf387601d7bf7eb3182d605fe5e63b18d531a5f84e5dbd0184a76c6c467a8263a98b5c005fcb2aaf989f5cbd0a9d903fcfc609d6e57d9c439021cea93e4c4e991f193caf3243770b32578748076b7f4cb97f17c17a79b82253c2423db698cd0a33ab33bb09b0b08cb8ceadca1e29c5de2fc12b2407b6cc5af5ae976dd3ec630d8339b7dd11fa34caac150c7c4791d8c427b0ad92e0529067a88d52011e1e0a18299b969896f8b8360f75c45c496da47b09b450f9822bcbcd43f4293c516802bf747c4abeedfaa3e79cb9103d3770f5607b77516e5b1ce0f64b6eec7bec3c647c006956dc55b6c79f6afb39d1fc3ecf11b974b44aedb72aed1316635083c2124502e5c72d86ecab6ac90243eb39a6aa9cb9480da38e1edb8d28ff90924c05d5d21af5af95957b8020781378711a29d0920acad8ccb39a311693278c9900b470da2bd4c12a01d73962644017b6034713b2a:dd5489fde4ba87d1173d4cee0682afdd4bad80dd770ea7d0dcebaf21acc61dd6324aca295ed0e23a915ecfdad50f175ebc516f1be5b6d87d90bbe38622495302d6201ebc21cec1e9bc28f957c9d029cc38f9e85e06dfc90bf297e61f2b73b407d982a66b91e94a24e91d06ab8a5c079d0f69be5788ea8feacebd917291192233862e6acda1e8cf9a48bffb5491dd65af541b6c72af681a81823d98a0abeeb6ba9f95465b8411f99e119cd28479da984259bdf86c9fef3cca34e224691f183cf095037727da9cad29f242f83eb4f736e27fdf67018d711b74c45b2955a6a76ec15330df5bad8030c6b3a88d72f28447652ac8902b5b76cbf6b945ceabfec04a9b8cb30f43d9eb773e6705594f0de1b70f1a20c99fc4b1221f8c81b0bc30da12cd5dea8f4d90f13a811a2cc11a96846aafb4c42a00e9ae7da256a0d22b198afc25cc1041d24e056cf387601d7bf7eb3182d605fe5e63b18d531a5f84e5dbd0184a76c6c467a8263a98b5c005fcb2aaf989f5cbd0a9d903fcfc609d6e57d9c439021cea93e4c4e991f193caf3243770b32578748076b7f4cb97f17c17a79b82253c2423db698cd0a33ab33bb09b0b08cb8ceadca1e29c5de2fc12b2407b6cc5af5ae976dd3ec630d8339b7dd11fa34caac150c7c4791d8c427b0ad92e0529067a88d52011e1e0a18299b969896f8b8360f75c45c496da47b09b450f9822bcbcd43f4293c516802bf747c4abeedfaa3e79cb9103d3770f5607b77516e5b1ce0f64b6eec7bec3c647c006956dc55b6c79f6afb39d1fc3ecf11b974b44aedb72aed1316635083c2124502e5c72d86ecab6ac90243eb39a6aa9cb9480da38e1edb8d28ff90924c05d5d21af5af95957b8020781378711a29d0920acad8ccb39a311693278c9900b470da2bd4c12a01d73962644017b6034713b2a: +5a19bf6c941f394e93bd3625fb81cd9da81c9020b1c531257a7b5957bb07921120e8699d087ce5e8151d28053dce66c23f28081f35bd26819bbe85d38a09d702:20e8699d087ce5e8151d28053dce66c23f28081f35bd26819bbe85d38a09d702:f721ca3a32c1e81c9c6f46d5e1fb50e7ce2f4e709333ca2b550d5213b6773d670ca59a2b5086a443843ac50813b244c9c9fac6d119698927813512c84fe30a89553010138f91e8176f5cf25789d7281ddb83a246705dccb999c4cd0ae219c645f6d71d451ae1f8d2f9891af8ccce03f438559fb83667b8077fbe435a744af019d6d1399fd2137f5afb8ef3f47bcf735e7c9ed8a54ba0c1c656b6650bb30adb1d57ecd2074639494231a2e9e2f985ed8422ee03cb3fd738c735a1b82806047460ed84f7468c3c64b35db06bc58de4bba463e638a94133df106ac4f470361ccde44157299d225b17798891baf5921986a2bae326dda0b89617c677bd1408ba2748baa67c8a2c5a969bc00cb40dbf490e07e22c913afdde6304a07fc9e60846992456bfb0663a09def68def67a16d29e98c7b55351848a8cf92310c7463c475f249c6f7557fd0d755ca88f877847fe0765756ac34a23f7840d95c3d294e663bb1518b75927c410757e0f5c07c5a7fb215dc7207433ebf791edfcec90e930f8e3ba9dbbb985413c223be87873bd323997581804d8896da386a6e9120050a0eaed31240aa17c7b6694c30cbcc3c6956a6820fc9ab21875533963dc3b0d88358271276c6056528910dd989ae0c330d1798f7d8e7d1184b84a81434325b8c302edf601dc5e6f847fbacbdeeff78c6621d1dafdc239b18b8c1afdcb4b9dabd5d3a92a932ea1599546e625f96d6ec6fb1cccb76b476b330ac59259c634fac9b3fa7de7ae7053773b5befa001b04929f74b71241e1b257696d65a26c1b4ac86b7b1fbd6957fb9b95084ce7d70090f55d44534694305e91769a82941304:2a2fd6054ef4e79b72191a0ccbd2b18aebabe8b9a71861ded98b7cdcb6a6255328bc1aecb0c9335721a9a96ee4b5b43f90d322ecf835f78b264dae6e387bfb04f721ca3a32c1e81c9c6f46d5e1fb50e7ce2f4e709333ca2b550d5213b6773d670ca59a2b5086a443843ac50813b244c9c9fac6d119698927813512c84fe30a89553010138f91e8176f5cf25789d7281ddb83a246705dccb999c4cd0ae219c645f6d71d451ae1f8d2f9891af8ccce03f438559fb83667b8077fbe435a744af019d6d1399fd2137f5afb8ef3f47bcf735e7c9ed8a54ba0c1c656b6650bb30adb1d57ecd2074639494231a2e9e2f985ed8422ee03cb3fd738c735a1b82806047460ed84f7468c3c64b35db06bc58de4bba463e638a94133df106ac4f470361ccde44157299d225b17798891baf5921986a2bae326dda0b89617c677bd1408ba2748baa67c8a2c5a969bc00cb40dbf490e07e22c913afdde6304a07fc9e60846992456bfb0663a09def68def67a16d29e98c7b55351848a8cf92310c7463c475f249c6f7557fd0d755ca88f877847fe0765756ac34a23f7840d95c3d294e663bb1518b75927c410757e0f5c07c5a7fb215dc7207433ebf791edfcec90e930f8e3ba9dbbb985413c223be87873bd323997581804d8896da386a6e9120050a0eaed31240aa17c7b6694c30cbcc3c6956a6820fc9ab21875533963dc3b0d88358271276c6056528910dd989ae0c330d1798f7d8e7d1184b84a81434325b8c302edf601dc5e6f847fbacbdeeff78c6621d1dafdc239b18b8c1afdcb4b9dabd5d3a92a932ea1599546e625f96d6ec6fb1cccb76b476b330ac59259c634fac9b3fa7de7ae7053773b5befa001b04929f74b71241e1b257696d65a26c1b4ac86b7b1fbd6957fb9b95084ce7d70090f55d44534694305e91769a82941304: +b506c01d69746eb4bc6358720e438ad330c88b605aad652f4799573ab0a1aaf97ac8b68863bd69151583789d864a7357e3a045fa86522a9daa6e26fb79ed6d23:7ac8b68863bd69151583789d864a7357e3a045fa86522a9daa6e26fb79ed6d23:f7fc18066ed04b30e633d9865da3214beca60bd796019cd7ecc91866f9ef2446c1fab06d8651be7f101aec7bb84ee21e71ad020215fcfb36f2d11e4579ac39f8e2b1290e3896d522bcf513aaa06771f86ee228cff3a20a1f10c564339589bba9605344c0a6e682ad5ba40d1041941bc46f98b9d09ca17f8f044e983b8a4908933df2263cf78811c24c8f4814354f6f4c68b7ee7b78308293bf78fd0ff122f095c14a73a59797172ae05cfcec19563eb18d2bc5300ed4bf6bdc443ea9b8bc1cbede94cab905eda5a6a931597de402146fac9cf8cd6a8d104669f913fa834001ca4d090fb7949d3109a63c0549b03f151b7117c4f46974ba59c68296edfdde7692ee432acef7610647e0957865e62c1a0cf05659823a55452dd5e471b31c5a49ab05b5aafd5a0e530e896b58cc522ecf19e52ec82fa147f9e385174c7ec33d1d9b86934aeb4f6c5700f7d5eb33ff73c9fc6aa47df51e09229e6ae894e86c818bef065f825971a4cb90adfefb31ebd9d1b79422dc9868f9f74e7a32cd4071efb69b27233e6e5c60dedcd5321c030a46cd26f5602cac747ee4b522d857a3321a03f403a6006250406361e48815afba77ce08903441845ba87225d8b24046745d4065645a1b98410cac48d137cbbb8ab1eba50da9c231e9acf322a6dbec0ef416a446c3b610d93569fdf45aa6cdc1b640d8f301d78693b2826cc6ed468568ad9a0f94aa9b9fb92f7e78d484fdf5d8d45c991e28074dcdd680d3b1f189ef6bdc320ee6e64dd1f80d9264d83042d2c43d83581ef0394b1b5d1f69f3bbbf04b7c808ba34c1580f16f76537b6a7ebd0a1908be9494d3fcaa9871db15750:17a19d2691b7b046d7b19669ad73140db92f0c978c7f61bc3867d92ca9d47580a0380b5901bad82af45f676f74287301980f71871a42261dbe0802950336e60bf7fc18066ed04b30e633d9865da3214beca60bd796019cd7ecc91866f9ef2446c1fab06d8651be7f101aec7bb84ee21e71ad020215fcfb36f2d11e4579ac39f8e2b1290e3896d522bcf513aaa06771f86ee228cff3a20a1f10c564339589bba9605344c0a6e682ad5ba40d1041941bc46f98b9d09ca17f8f044e983b8a4908933df2263cf78811c24c8f4814354f6f4c68b7ee7b78308293bf78fd0ff122f095c14a73a59797172ae05cfcec19563eb18d2bc5300ed4bf6bdc443ea9b8bc1cbede94cab905eda5a6a931597de402146fac9cf8cd6a8d104669f913fa834001ca4d090fb7949d3109a63c0549b03f151b7117c4f46974ba59c68296edfdde7692ee432acef7610647e0957865e62c1a0cf05659823a55452dd5e471b31c5a49ab05b5aafd5a0e530e896b58cc522ecf19e52ec82fa147f9e385174c7ec33d1d9b86934aeb4f6c5700f7d5eb33ff73c9fc6aa47df51e09229e6ae894e86c818bef065f825971a4cb90adfefb31ebd9d1b79422dc9868f9f74e7a32cd4071efb69b27233e6e5c60dedcd5321c030a46cd26f5602cac747ee4b522d857a3321a03f403a6006250406361e48815afba77ce08903441845ba87225d8b24046745d4065645a1b98410cac48d137cbbb8ab1eba50da9c231e9acf322a6dbec0ef416a446c3b610d93569fdf45aa6cdc1b640d8f301d78693b2826cc6ed468568ad9a0f94aa9b9fb92f7e78d484fdf5d8d45c991e28074dcdd680d3b1f189ef6bdc320ee6e64dd1f80d9264d83042d2c43d83581ef0394b1b5d1f69f3bbbf04b7c808ba34c1580f16f76537b6a7ebd0a1908be9494d3fcaa9871db15750: +e1ccb80a262ff8af1eda075c972c8e941e77cef57bdb0a82572c28200b493ca33d37e2a5027effdee07fa511e423b2bc56edcea075b41649766725c6b30a10f4:3d37e2a5027effdee07fa511e423b2bc56edcea075b41649766725c6b30a10f4:cfdc5497b023afa62a7fe592caa92b875c7705747834002f7784ff166189398815d4e8a7a0038e1fdadddeba51057327ad1960e859cee56526bbb4127b6a5f90d04d08b15eee66c9ccf88b4b7d1ee9d3b8b8c6f42db3c34e59048a15c6041f142c4079368b7b11e29970118b99e5670ae31fccfdff1399142ee06b2e3e2b3c9707dd64119786e2fab47e0bad2cc8b558d963bb48a49ad2c637dd35b25db54bc5a2630222fa2acece9ce12ab0813077f7659f5074429ca6b494331032ae792a599c425ee297451dcf5ee195290312742e647a7795b84dcc664ddae2a1fbf8c4548a37fd82d810e2145f01df1a6d3bcc42a91a10768e091f3d69329a7bad6c072cac6d89afa31c029056d6b62212165cebcd49ac672e3830267af9f28ea319bd042f6c59de4701e58248736c8d976acf93b99d2f4647a547d392447a48dac11181e16b1501a94c9316e5a67c990b35810b4cda0473a6a4e57614215868e2e002c6058b42e4eeec84139dc19edf5f80aeeffa4f5b07e8fd23139edda31899ebe6fee78643ce686b2963a32072bd3b3bba68485a05c2cc0456c3da50c7c8c651a3066d13a3660bd47ab6dfec49e01557a6742896aa4bc6363a797dbad1a409cd4a50911e70ea007af8e9b1bb7e3ab56215a575c90f739c2d48b3b34694b5acdf07980ae528de0621edfac8b8fa84954d56dbb4d03082b984f13e5dbe9c7112ff9716f55053064662ce0fb81ea35f98fd2cd51137a46f64e0c1caf44e5407dc961760b2597f7f9200617d471340cf15176c3da880fe4e0e93a72fb94926faed865dfdc772e185292c1e36b1211781c3e938e3d4f24e29af517a379683:fda34b652b79746f897e222d37b77aa250d02c527c4833df80ea41d52189d50700e128b78ee8149c9b19f3abf755acef5348f5fbaf1ceb41c038906ac5946001cfdc5497b023afa62a7fe592caa92b875c7705747834002f7784ff166189398815d4e8a7a0038e1fdadddeba51057327ad1960e859cee56526bbb4127b6a5f90d04d08b15eee66c9ccf88b4b7d1ee9d3b8b8c6f42db3c34e59048a15c6041f142c4079368b7b11e29970118b99e5670ae31fccfdff1399142ee06b2e3e2b3c9707dd64119786e2fab47e0bad2cc8b558d963bb48a49ad2c637dd35b25db54bc5a2630222fa2acece9ce12ab0813077f7659f5074429ca6b494331032ae792a599c425ee297451dcf5ee195290312742e647a7795b84dcc664ddae2a1fbf8c4548a37fd82d810e2145f01df1a6d3bcc42a91a10768e091f3d69329a7bad6c072cac6d89afa31c029056d6b62212165cebcd49ac672e3830267af9f28ea319bd042f6c59de4701e58248736c8d976acf93b99d2f4647a547d392447a48dac11181e16b1501a94c9316e5a67c990b35810b4cda0473a6a4e57614215868e2e002c6058b42e4eeec84139dc19edf5f80aeeffa4f5b07e8fd23139edda31899ebe6fee78643ce686b2963a32072bd3b3bba68485a05c2cc0456c3da50c7c8c651a3066d13a3660bd47ab6dfec49e01557a6742896aa4bc6363a797dbad1a409cd4a50911e70ea007af8e9b1bb7e3ab56215a575c90f739c2d48b3b34694b5acdf07980ae528de0621edfac8b8fa84954d56dbb4d03082b984f13e5dbe9c7112ff9716f55053064662ce0fb81ea35f98fd2cd51137a46f64e0c1caf44e5407dc961760b2597f7f9200617d471340cf15176c3da880fe4e0e93a72fb94926faed865dfdc772e185292c1e36b1211781c3e938e3d4f24e29af517a379683: +4fc512efd86e3a63b395eaff1ba011e1590fb9326ad3ffede7876dcc3e9fabdc26c2a22f9bfad90606dc613ff107021fcddbec7237066660b488964349e0c828:26c2a22f9bfad90606dc613ff107021fcddbec7237066660b488964349e0c828:07cd1e9bfa38a7d8853465a93c77ab4f30faf914e48bc4763ba07bf96ba808c1f59ad4ce9b7d921fbbc779659d7ca36edb7dd3acf7a29452a845b49fb6543a3b6c5c1c293aff618485a10eea60ee9649ac9d481e6949967d3938b52fe09c36b9ade07581db4eb542a97f5ac8ac73d3eea184722556760cf483090564553061b90a0b6d2dff4707be763937a10594a82b766bb2cf6daa52fa8d7b48f32127c431ad9aaed3bfdeb99ad42118a1b4de7b992134ed9cdad0b5296d197a485e493ecfeca3653ad2ce0f9241aabc096d7c4ba603ba7ddd07a8b257fe523276417073a65fa4434256fd1f239ec1de5da1a0a8c5e686ee14d9dfa438c53b99c954afab2f79e60b7126f2cb58a26e290da1dccfc301f239748ede7bcf1bb7ccb4720e692f57e53e6f59075399e1080ac8aa9a61a568c4c569d36e76a2d7271f2c44de4e363a8c916a4e446b027b64392e90ceabf6b6071bc47a1379b6aa6344763b2a0e7ff7c4a27bff3106721c253e4c1d67c37fa3d7c1ecd055b8e929d52a8e45ed89fb180f74b552fe06f066c7e4318ca2f915946e8320d5806561472fb8ff7fa8072d8e6fd1ce63cf87382f7b9404540c1d406c70b226853677092645ce996922e7345dc07fb7339f9a54ff07352dd2b993063c2c83d1281a4fd178e5a5f80a5b33c229d0578367d44192e9a4d21e9734d3bda083b70f47103fd125177021df3e53d79986efea2dc04f02c0ac278788319ef3a9132e6232ea6db39ca5870855f9592fff6c209ad2f1c29dd168552898979ecff8c81127248f8310515300656129d9b7acbb7ed1e46bc98c04d1a35b18913738e9dde4d2b065f4184242d8:82c824a7d1139ec73ae1d023adf62811441e968287f1a580b859cd66cb33b58e409bdeb2a874bf4c23610bd44f693147f2f7c29d443a905084f3eaafd9330e0407cd1e9bfa38a7d8853465a93c77ab4f30faf914e48bc4763ba07bf96ba808c1f59ad4ce9b7d921fbbc779659d7ca36edb7dd3acf7a29452a845b49fb6543a3b6c5c1c293aff618485a10eea60ee9649ac9d481e6949967d3938b52fe09c36b9ade07581db4eb542a97f5ac8ac73d3eea184722556760cf483090564553061b90a0b6d2dff4707be763937a10594a82b766bb2cf6daa52fa8d7b48f32127c431ad9aaed3bfdeb99ad42118a1b4de7b992134ed9cdad0b5296d197a485e493ecfeca3653ad2ce0f9241aabc096d7c4ba603ba7ddd07a8b257fe523276417073a65fa4434256fd1f239ec1de5da1a0a8c5e686ee14d9dfa438c53b99c954afab2f79e60b7126f2cb58a26e290da1dccfc301f239748ede7bcf1bb7ccb4720e692f57e53e6f59075399e1080ac8aa9a61a568c4c569d36e76a2d7271f2c44de4e363a8c916a4e446b027b64392e90ceabf6b6071bc47a1379b6aa6344763b2a0e7ff7c4a27bff3106721c253e4c1d67c37fa3d7c1ecd055b8e929d52a8e45ed89fb180f74b552fe06f066c7e4318ca2f915946e8320d5806561472fb8ff7fa8072d8e6fd1ce63cf87382f7b9404540c1d406c70b226853677092645ce996922e7345dc07fb7339f9a54ff07352dd2b993063c2c83d1281a4fd178e5a5f80a5b33c229d0578367d44192e9a4d21e9734d3bda083b70f47103fd125177021df3e53d79986efea2dc04f02c0ac278788319ef3a9132e6232ea6db39ca5870855f9592fff6c209ad2f1c29dd168552898979ecff8c81127248f8310515300656129d9b7acbb7ed1e46bc98c04d1a35b18913738e9dde4d2b065f4184242d8: +0b7dfad05ba665111e1681bdc0bc8ba973767cb85877020a2dbf918325571d9f9505d9e86dcef56c9db76f2862b90e1f2773202f1750405e7ee5aed0fc54f8b9:9505d9e86dcef56c9db76f2862b90e1f2773202f1750405e7ee5aed0fc54f8b9:c43fd34bb1424cca4e4dfba75c28be801844446ca089020885c748382547164a9d4a7f9570d3d171ad6981ab50eeee08a4a6c66d7699d23edbe1faaf44660c72f4552d87d265ace8792823474b90a5d7f7401deb9377627f60b036b36e044eb76bf132fddfcc0ef5704a633d845e962b47517f0baa34d3d6e9a8b9f8168bcdc84c6d2b30c6f343e75357f7f2c0039bd254b244d36cd61675581fb834570ed4113a78e606f145a111992c2c6b61c4267628ec87cd88c36a3c84706e44ae96a96e0c8480318546d6ea6a6df18a2b4f19f8360cfbce4e9d1cf1011ffea5633a66619aa4a65cf69be4459617945e4359a9d43260ca1a20f4ed7c1ae5ffff3bd92294ea70abbae0385b0935cd1c0eb5183029c585a0294b7999e32ef7a290fcb095675dc4f601e8f2c96f35b7349a37057509f4ec70c9f50f6011f1f5e6b061c091d11c0ed5dec8ece881aa340508f696d9e9cc7298e6bccd7c210e2ce0ded83592a3cfa13e8078fdb3258b39f1d11cdfe09670c1e60a3910a4fff51c6c7f7d6624f4c93df8888c526f484f9b13e0a7f62964783978684e292679800ed5eb280e287c7e639e85faa53fba2fa2045ce27d8fb308360726550df9752db305f8f06647970d014691999afa97b6193ffcc6d532f4fa69e133a1d10f3047fc00381f4997bb84e5b6cd6028c62132cfc024bfeb980301f29512bbd109d089ace182cf9c2ffab1b17eb00b6eb46ae198da993f5efe7c1dc22d25047c1ee5246517e7f5758f996abd83f13da22c13dd205ee191b55afd4831ef078bb6ea073a625bc97c81296160bbf2559b275cc37ccf01b91fd87d4d99a367aa9978dadd0689f8a6:415adbb2f2b9840577fd1841f9aae252afe8f5a72236017d50db22d228cdee9f5b3e8fe9a17a4d4e98b7341381e8d8625cdcea956d253b74e02dacb84920a009c43fd34bb1424cca4e4dfba75c28be801844446ca089020885c748382547164a9d4a7f9570d3d171ad6981ab50eeee08a4a6c66d7699d23edbe1faaf44660c72f4552d87d265ace8792823474b90a5d7f7401deb9377627f60b036b36e044eb76bf132fddfcc0ef5704a633d845e962b47517f0baa34d3d6e9a8b9f8168bcdc84c6d2b30c6f343e75357f7f2c0039bd254b244d36cd61675581fb834570ed4113a78e606f145a111992c2c6b61c4267628ec87cd88c36a3c84706e44ae96a96e0c8480318546d6ea6a6df18a2b4f19f8360cfbce4e9d1cf1011ffea5633a66619aa4a65cf69be4459617945e4359a9d43260ca1a20f4ed7c1ae5ffff3bd92294ea70abbae0385b0935cd1c0eb5183029c585a0294b7999e32ef7a290fcb095675dc4f601e8f2c96f35b7349a37057509f4ec70c9f50f6011f1f5e6b061c091d11c0ed5dec8ece881aa340508f696d9e9cc7298e6bccd7c210e2ce0ded83592a3cfa13e8078fdb3258b39f1d11cdfe09670c1e60a3910a4fff51c6c7f7d6624f4c93df8888c526f484f9b13e0a7f62964783978684e292679800ed5eb280e287c7e639e85faa53fba2fa2045ce27d8fb308360726550df9752db305f8f06647970d014691999afa97b6193ffcc6d532f4fa69e133a1d10f3047fc00381f4997bb84e5b6cd6028c62132cfc024bfeb980301f29512bbd109d089ace182cf9c2ffab1b17eb00b6eb46ae198da993f5efe7c1dc22d25047c1ee5246517e7f5758f996abd83f13da22c13dd205ee191b55afd4831ef078bb6ea073a625bc97c81296160bbf2559b275cc37ccf01b91fd87d4d99a367aa9978dadd0689f8a6: +78188df8c754785621e27ae58e100d5080e16e0a15e277051f95f080900ec0d3a1bdeee98b0757ba9c2d8409b87424e64e42f9932acfa9bc71fb3f8ca0e11d52:a1bdeee98b0757ba9c2d8409b87424e64e42f9932acfa9bc71fb3f8ca0e11d52:cf70cca57feb1beefe985ad5af9d4348d3a46a63de1075381fb3639a044fd6e6091f5db9c94d39be0f13ade6d9a074e67ba706b3a8806295f6b654865728c58ca6e9419d5d043f2110814bbf36fc4070e4d9454965c251202ca395efe3fdbd544feb187e34ca3c80795179552fce9aa804430e5b6c8685341e91d5889fbf3f981904620ffe7013f53b939e17443d614e7e6bb57ad674f3b4b001630526cf7302a7d0afe7dc24d6dadef6feba3f96973aa5b8d6275262e430a82f678696971a8b60e38d3b2bcc170d5bc20302a39c596d27fee39e5da5b10ea9f382299e19819717a718d37d155f13923182b5b7a1c54ca109b22ca8e8b26ca5ca3f3b9062219461bace97e890c94e41ca3d84587fbdf6e240c35ccab71d58477d28168e93372686d42aad324a3f16afe0e9b89ee20e485fe6c864b5013ba88399eeaa159835a8b2bb2f25f579ca3bae675c63da1b50d99d4ed978692e5600233f38ab7e7a5ae0fbf8c0b69cc38bd30eabd977efa05ee2c83514302bd40c4bdce7a4110afbb6579c620e97f8cf2e9bab2dcc7c33f196e57fe761a050122894b7a75a929531996ddaad78de1d4d924cd93a61df227776bc1c39fbb8de1c4438868b6a3a2cd94c07b29e3f6b23cc7e0b63689009d9d0bae1606bafc7a808f2d2fa2562b8dc093842c01fdb840da4860aced3fc525ca334edcf65948bc416f98c450f0012a6107dd7f8ede40e1c48c9e8a565a810b9cfd20356db19f1dbde598921332e0d813f0cb87684370388772ff3cbfcbfa299c198c97bfb9617768a05161f4169ff5de5d9f40062090fb882984d9d5c7aa78eddcb9634e466b8853d512b4a546d7423:b94114eda46ccfc22a4471a64d790892e59c5d505618eb0e701392c709613e2d503a5c2b66601e636a3c1c7d49b1ac798d9089b0f9ccd0579bb90634d0bd750ecf70cca57feb1beefe985ad5af9d4348d3a46a63de1075381fb3639a044fd6e6091f5db9c94d39be0f13ade6d9a074e67ba706b3a8806295f6b654865728c58ca6e9419d5d043f2110814bbf36fc4070e4d9454965c251202ca395efe3fdbd544feb187e34ca3c80795179552fce9aa804430e5b6c8685341e91d5889fbf3f981904620ffe7013f53b939e17443d614e7e6bb57ad674f3b4b001630526cf7302a7d0afe7dc24d6dadef6feba3f96973aa5b8d6275262e430a82f678696971a8b60e38d3b2bcc170d5bc20302a39c596d27fee39e5da5b10ea9f382299e19819717a718d37d155f13923182b5b7a1c54ca109b22ca8e8b26ca5ca3f3b9062219461bace97e890c94e41ca3d84587fbdf6e240c35ccab71d58477d28168e93372686d42aad324a3f16afe0e9b89ee20e485fe6c864b5013ba88399eeaa159835a8b2bb2f25f579ca3bae675c63da1b50d99d4ed978692e5600233f38ab7e7a5ae0fbf8c0b69cc38bd30eabd977efa05ee2c83514302bd40c4bdce7a4110afbb6579c620e97f8cf2e9bab2dcc7c33f196e57fe761a050122894b7a75a929531996ddaad78de1d4d924cd93a61df227776bc1c39fbb8de1c4438868b6a3a2cd94c07b29e3f6b23cc7e0b63689009d9d0bae1606bafc7a808f2d2fa2562b8dc093842c01fdb840da4860aced3fc525ca334edcf65948bc416f98c450f0012a6107dd7f8ede40e1c48c9e8a565a810b9cfd20356db19f1dbde598921332e0d813f0cb87684370388772ff3cbfcbfa299c198c97bfb9617768a05161f4169ff5de5d9f40062090fb882984d9d5c7aa78eddcb9634e466b8853d512b4a546d7423: +73cb02b0bf26a015da1dc301fc125d7e6c30b63c9e6eee9e065d4e847132c325ac9e3dd2ceb9b23e748c04ba7577fedf7ceab9ed87dc430b5fe22eac50950e0d:ac9e3dd2ceb9b23e748c04ba7577fedf7ceab9ed87dc430b5fe22eac50950e0d:0a2b61ba35e96e5819b88bfdb28b7ce02e64ae9cf572b21f13552c0db10f3960d44ba3472f43abc4e6295bdf790bd933ba3975fd4465fa3e2fe2db02b6377752223dec98fcb2404f3aba43265a6fa7976b6c6cb6868b881bd6f3d25cd9d6f70e512f8089c8ef26fd58245053779e59c4725aefa26467c9f500e17f3e1573f1a855e9b8b21925ea0527f3ce8d88fb54a47abeed14f399cc2d9f1fe54665fae0a8f0c68872a600046d1dc36397d310ce393fceafe87c17ebe122fdb543aea71085baec98273f41ac96698c150cf911d0e5de2392d84841d01276aefbfe9995e10a6d46efdc2678d456c9f36b2e10114d1187e7aca739037ea51f85fd62a29429ba529cdd8ad91347497487ed7e8709d4776ef68670792d0615bc96da5178d606db63e4e5cb172acfbc1cbe20269350f1b605f35dcd479135bd30fb4b5a39176cff744ddbb306c9e7b4167de0379a6166be5aaa74d7157fac957d88dc57597cfef23eb5108b3ce53fc632dad1b972a29da5de32d20d8ecede67ff00da4a08a0cc1a98bee7a94e3cb32fee94ae25a413544702c37b3e1778a070cdd4840bd39f5f45795192a867863876ed0d130d46e2913935082809f7e15a496710f255d783da3d016a654c15ff5df907a3ccaf37cfe11c8c3d496507d6760c053820f0f594c3d01ca269178aca525ab2821ef55f92d85fe685ea34472ed1398171064d74a422ec91d1a670618fc9f32424bcb11a77f6fb4e2fefd2c4e8a73c452886e931664d1a83bd927329c04d250b83521d7dc13c91cee1ec050e11d42a4b0c8c069b61c4422d3a49c07eff2905b7bc7f4a5b43e6b0d61dfb50e4eea2e90d298a781d05:1a5dd4c891c8e132570187c23b9a1e4b26f05460e875673819396df561c8af0e48333b62c77729d49fc40e174a7f3c21f85ef4d339ceb80bd2e037d803af560e0a2b61ba35e96e5819b88bfdb28b7ce02e64ae9cf572b21f13552c0db10f3960d44ba3472f43abc4e6295bdf790bd933ba3975fd4465fa3e2fe2db02b6377752223dec98fcb2404f3aba43265a6fa7976b6c6cb6868b881bd6f3d25cd9d6f70e512f8089c8ef26fd58245053779e59c4725aefa26467c9f500e17f3e1573f1a855e9b8b21925ea0527f3ce8d88fb54a47abeed14f399cc2d9f1fe54665fae0a8f0c68872a600046d1dc36397d310ce393fceafe87c17ebe122fdb543aea71085baec98273f41ac96698c150cf911d0e5de2392d84841d01276aefbfe9995e10a6d46efdc2678d456c9f36b2e10114d1187e7aca739037ea51f85fd62a29429ba529cdd8ad91347497487ed7e8709d4776ef68670792d0615bc96da5178d606db63e4e5cb172acfbc1cbe20269350f1b605f35dcd479135bd30fb4b5a39176cff744ddbb306c9e7b4167de0379a6166be5aaa74d7157fac957d88dc57597cfef23eb5108b3ce53fc632dad1b972a29da5de32d20d8ecede67ff00da4a08a0cc1a98bee7a94e3cb32fee94ae25a413544702c37b3e1778a070cdd4840bd39f5f45795192a867863876ed0d130d46e2913935082809f7e15a496710f255d783da3d016a654c15ff5df907a3ccaf37cfe11c8c3d496507d6760c053820f0f594c3d01ca269178aca525ab2821ef55f92d85fe685ea34472ed1398171064d74a422ec91d1a670618fc9f32424bcb11a77f6fb4e2fefd2c4e8a73c452886e931664d1a83bd927329c04d250b83521d7dc13c91cee1ec050e11d42a4b0c8c069b61c4422d3a49c07eff2905b7bc7f4a5b43e6b0d61dfb50e4eea2e90d298a781d05: +db05606356bacf23aff6cddd42b2c694352b5a0fec560aff54d9bd9710efe06a32a5c7cc4909786b48a53f31093f549a9f1730ca6690383fdb5f14c2666e3132:32a5c7cc4909786b48a53f31093f549a9f1730ca6690383fdb5f14c2666e3132:1bc9c2833f37cdf1356fad166768642717701b38a0ab0c2f581a26d222d65ccee4bf0f6dfe64d33bc0239f71d4b82644b01625a1a35fe798676239e0ca779ef23138eebe3bd19de2d8f7c15b4d96f13e51bc633bea5d61225bca1d6339ba53e81f7d8d24c5d60f04ce8c726761d264584f1c7e5b5b6992456c1c76892d6352111e3b926fe025c0009db67ce0ddc7f764e0c9adb0481bc2795484d96373a962a7b74a5596f527a73476498c7823dffa6c8543b07971b5aa271c12255e0918dd73f50c30c9a85ac7c2993dd655da59431263f5914be706374be9c07585c2871328b4dbc39401c95707387e6e069d44b9d8fb058f22e315aa0d5b4f1168fc107962b064f7d845af8e2131951d1cd66dc84dba46d200af4f4c5f51221bc9b2196942f8b40e7ddbc9aeb3d9afc071259513135a016f2866099fa10f4c3b73500bd55c477b2415e10a279ba110d294f3dd1842177d0b4bfb1734dd0ccb7e394b43d16f0b7548362280f434764da57f19ed3e302e5370fba49664c230057433cc647eb27cd2c7c18c7d66906f088246c22f7f790399deb4c5fbb906181769bef5afbe8ad1f5de55be588f52f69c54d4ef5a969a0d995c27407b23edd9243d2499fdf29473b1955c84b3f7cbdcd81b7656ec0be9e0fdb3381356960fd0ca70e7ea74b646fcd313948e6ddb47609476fb6fa4842fa788a0d57be3b0a6ca1819f71614760043ec4904881939968a43b5d1928f84a5919093bc3841588171a9cd390f8fcd61538b54e6ef99770573e1986d150fa96b7a07e1d194af1c0b405500acb3d10e3be647c89862006fa78583e76166842920160eb57f0b2a6edf193c44c5eeacf4:53099b766adf2944b6821374842c25d6e67b0ccde9c637fecb11b8b8b07203e3075732805f4f14aeae73bd62e308b5887d689e29cd89b23a476943110717b1001bc9c2833f37cdf1356fad166768642717701b38a0ab0c2f581a26d222d65ccee4bf0f6dfe64d33bc0239f71d4b82644b01625a1a35fe798676239e0ca779ef23138eebe3bd19de2d8f7c15b4d96f13e51bc633bea5d61225bca1d6339ba53e81f7d8d24c5d60f04ce8c726761d264584f1c7e5b5b6992456c1c76892d6352111e3b926fe025c0009db67ce0ddc7f764e0c9adb0481bc2795484d96373a962a7b74a5596f527a73476498c7823dffa6c8543b07971b5aa271c12255e0918dd73f50c30c9a85ac7c2993dd655da59431263f5914be706374be9c07585c2871328b4dbc39401c95707387e6e069d44b9d8fb058f22e315aa0d5b4f1168fc107962b064f7d845af8e2131951d1cd66dc84dba46d200af4f4c5f51221bc9b2196942f8b40e7ddbc9aeb3d9afc071259513135a016f2866099fa10f4c3b73500bd55c477b2415e10a279ba110d294f3dd1842177d0b4bfb1734dd0ccb7e394b43d16f0b7548362280f434764da57f19ed3e302e5370fba49664c230057433cc647eb27cd2c7c18c7d66906f088246c22f7f790399deb4c5fbb906181769bef5afbe8ad1f5de55be588f52f69c54d4ef5a969a0d995c27407b23edd9243d2499fdf29473b1955c84b3f7cbdcd81b7656ec0be9e0fdb3381356960fd0ca70e7ea74b646fcd313948e6ddb47609476fb6fa4842fa788a0d57be3b0a6ca1819f71614760043ec4904881939968a43b5d1928f84a5919093bc3841588171a9cd390f8fcd61538b54e6ef99770573e1986d150fa96b7a07e1d194af1c0b405500acb3d10e3be647c89862006fa78583e76166842920160eb57f0b2a6edf193c44c5eeacf4: +1d139b1ad0c3af1d5b8be31a4ecb878ec667736f7d4fa8363a9809b6d1dabfe32428cf1deb20fbad1fdc665d825b614122df101fbe1473a79996baf6967434b8:2428cf1deb20fbad1fdc665d825b614122df101fbe1473a79996baf6967434b8:8df2d2df9b984da84433486a813c98c5973a696c11624610b23aa438083464f65a76796615b728c2ed4e60715855afc239450d5bc0911ff2a85230205c6f1349ba5bd87ea6f720db6ba70b77421788e0c654aebc23074c5f41d2290772140d981a6bc4fe709a268e64172a026b270118b4db51ab6a13c99b063186d8d5b338e977eddc6bb5fd7dd57d9845a3c3fe76177d5738dca16a8f9102857500174f23ff4c3bf3c8536f11580ef8514a409f5bbc9c0296f12e3478d4087f95efaa6c636071d21157bf11774bbfe7693306ca7213da4713ebaaab3554edf08011a5ff73da120375aed19628670f28ab24b6f5d5a1d570480f65d3c152bff1b47bf0666929cb7c99d9033faae8534fc35da730b811ebcc25ae10a195aab12c326aa45bf805c62dd4cd5f868623c04a8e1c6aa72f1ea4400c60867dff622f316434f1ec89503c6f9f65c137b4944cbcb35f086c74cceafa2242acca6ffe611c4b5587f5b75ffad349f00bf96e4a580a875b92654069b62eeac0bf78e5aedd71869ee05b9a94e1c98e35a97800a4a21220b039cd5ebbb756d40b4042e2c84a2ae98182511dae8ed3b89f4fa00fb8ed946316459710052ad4c02f63df05d3bb1ace33672151bdf5dab46c7b583db373899d4f035b6c111258b4e5a9e707a11d215e44e68ef1a6f053809aa51bd902e13ca99c1b1cecc83b9c235c710e797d2b1a249b2ea079b5c1674ed7169f1b6e67f1ac77f86b743298969335a772440f7fbfa72513500d84166114a8fd54139464d42b995530d32370b69bffc7589d6dcc97e0bf17856cc3bf4164dbeccc8a881d414d6a62029276c5f8137c0b3c68bc8f4bd4e7cff65ef2:dd645e51edab04db31e33172cf27aceeedcc0463a963914a0eac8efd5a34341f6bbc52e042baaf3b40c89a57efb64574e69677fce955246c1fc0f269ef8190008df2d2df9b984da84433486a813c98c5973a696c11624610b23aa438083464f65a76796615b728c2ed4e60715855afc239450d5bc0911ff2a85230205c6f1349ba5bd87ea6f720db6ba70b77421788e0c654aebc23074c5f41d2290772140d981a6bc4fe709a268e64172a026b270118b4db51ab6a13c99b063186d8d5b338e977eddc6bb5fd7dd57d9845a3c3fe76177d5738dca16a8f9102857500174f23ff4c3bf3c8536f11580ef8514a409f5bbc9c0296f12e3478d4087f95efaa6c636071d21157bf11774bbfe7693306ca7213da4713ebaaab3554edf08011a5ff73da120375aed19628670f28ab24b6f5d5a1d570480f65d3c152bff1b47bf0666929cb7c99d9033faae8534fc35da730b811ebcc25ae10a195aab12c326aa45bf805c62dd4cd5f868623c04a8e1c6aa72f1ea4400c60867dff622f316434f1ec89503c6f9f65c137b4944cbcb35f086c74cceafa2242acca6ffe611c4b5587f5b75ffad349f00bf96e4a580a875b92654069b62eeac0bf78e5aedd71869ee05b9a94e1c98e35a97800a4a21220b039cd5ebbb756d40b4042e2c84a2ae98182511dae8ed3b89f4fa00fb8ed946316459710052ad4c02f63df05d3bb1ace33672151bdf5dab46c7b583db373899d4f035b6c111258b4e5a9e707a11d215e44e68ef1a6f053809aa51bd902e13ca99c1b1cecc83b9c235c710e797d2b1a249b2ea079b5c1674ed7169f1b6e67f1ac77f86b743298969335a772440f7fbfa72513500d84166114a8fd54139464d42b995530d32370b69bffc7589d6dcc97e0bf17856cc3bf4164dbeccc8a881d414d6a62029276c5f8137c0b3c68bc8f4bd4e7cff65ef2: +4d22e331e0cf6f6a272db4d20687ffb059f1225d81e41123b8c89b074de76a3bb1e4cfaeadd67b12d7b9dbfc0f88edd0373f9a88c7fa33fb7f2b1e475eccb61b:b1e4cfaeadd67b12d7b9dbfc0f88edd0373f9a88c7fa33fb7f2b1e475eccb61b:9c8e3f5b4d704030e1ba71f02efc4b87d6fffb55bc3d8d03818f915624fcf701c54adfafa2b694b87751cb9f69918c0f050f4c105d5ccb40100b28dfd4f411d591c12019176ac2016bfbfdf0ddf11db8a7e39aa7b9e216f667c0a15fb977eaa9ba3bc455cc58945f3e944b8ac2fbf4d24fe7e1e619cdbeee3e5e12a9a527d28f5fd7cfd9220f1308d897b6d4314a5a0187864a2d621cf1b2844261247bf520bafa9bf226e115681ecd77427980cd12b08c359cecd1de3f5545f807f81ed76302ffd6477f89b958cdf12954cf70c142532993831647eacab0b4807bfdadb4389d7dff2c4ef0ef5a5c61d0df762e2e9080a7181cecd06a53199f0dfef702627adecf5fcd9b3e68c72333161727f871c7d1c43051ff1c921fd53b642238b97880d64e25fac512ab954bedbca540f5b20091ec72e67f88770afc32f2125ca0da4fe87b56aac9177f1f4f67c851725c5e8afe64f664799833fd79100b77ead25838879fff4747aa0d5672ec0a94348134bdbd4bb39b0c67a0cd30602edf4fec6f7af0cc2bdae126cea842dfaa4391dc5ddea938e1792168240c2d8b25352f9f3a644235ce36fefeb6992ad88e287ad2d85bd850396fc2e517a15209f5920ac98c532b1f4d869beb08bb03cf7c91af3ffced68d5fbfef86ff94ece6e2ead3484ce080db17bbe40f1db432ec1650ed24fdd250f3345745c9b7b9198c9109a37261fc5ecbbb12f83a0e1220a1867d45fddfea81dcf75f4ec7fdb5250e57754d6dea270b628a79530ec28b619bca9493e6305cfc4414c1c1de3389e890197c85f28404f3fa96a1e2fd9206b472e8a0a0d32af55606bb083f76a19b8eae3479ae51d98a99a62:c366b802f682fcd70525264fb1a3cbcd0ee35ecff5977c2a554da939229f17819a961ea74c3d7a7881ac5c1fa16bf984d9456a1388d3463c4494429b1dc454029c8e3f5b4d704030e1ba71f02efc4b87d6fffb55bc3d8d03818f915624fcf701c54adfafa2b694b87751cb9f69918c0f050f4c105d5ccb40100b28dfd4f411d591c12019176ac2016bfbfdf0ddf11db8a7e39aa7b9e216f667c0a15fb977eaa9ba3bc455cc58945f3e944b8ac2fbf4d24fe7e1e619cdbeee3e5e12a9a527d28f5fd7cfd9220f1308d897b6d4314a5a0187864a2d621cf1b2844261247bf520bafa9bf226e115681ecd77427980cd12b08c359cecd1de3f5545f807f81ed76302ffd6477f89b958cdf12954cf70c142532993831647eacab0b4807bfdadb4389d7dff2c4ef0ef5a5c61d0df762e2e9080a7181cecd06a53199f0dfef702627adecf5fcd9b3e68c72333161727f871c7d1c43051ff1c921fd53b642238b97880d64e25fac512ab954bedbca540f5b20091ec72e67f88770afc32f2125ca0da4fe87b56aac9177f1f4f67c851725c5e8afe64f664799833fd79100b77ead25838879fff4747aa0d5672ec0a94348134bdbd4bb39b0c67a0cd30602edf4fec6f7af0cc2bdae126cea842dfaa4391dc5ddea938e1792168240c2d8b25352f9f3a644235ce36fefeb6992ad88e287ad2d85bd850396fc2e517a15209f5920ac98c532b1f4d869beb08bb03cf7c91af3ffced68d5fbfef86ff94ece6e2ead3484ce080db17bbe40f1db432ec1650ed24fdd250f3345745c9b7b9198c9109a37261fc5ecbbb12f83a0e1220a1867d45fddfea81dcf75f4ec7fdb5250e57754d6dea270b628a79530ec28b619bca9493e6305cfc4414c1c1de3389e890197c85f28404f3fa96a1e2fd9206b472e8a0a0d32af55606bb083f76a19b8eae3479ae51d98a99a62: +a5228ff9bbb6f232327eb8d879d7f8b277ca72bae1f9a9d0e260dd90571db4f9d82f6a6974f51c8808d9d617f4cec2d8a37eb11a14237c9ab9cf11ebc80ff6c0:d82f6a6974f51c8808d9d617f4cec2d8a37eb11a14237c9ab9cf11ebc80ff6c0:1df7a6835e3310983ee7ec731125f5b5cf117af0e36b3685bf54ace1c48c46300560a45e9f9bdd96a0bc4d14e89d4b5721a2caff6618b182edb1202f3d0c5d118d09b61812c010e8b196344541cdeefe5fd1f961c5dd75459555ab72ef2aa7a759a4f3ad3caed44f4c9a8ef95b76ed9a99b55dd8a260ba08010d29ff819f2af3513c1a640d6ccdde4999205f9fca8857115d8b5db9f70a62e5eea0d5af065de153f2ededeec63e15c8e09a92582182ac07d81ca63ca4aa597a2220e70481957d415264e258bc263e1cc36e53478aac5ca01694ccb09b4ffd84739972c7dccf3defeafdede162ab6c58a1df27371e3f5493067fc9e2067e579623c009fc825eef0e010fd1ccf2a8d3fbbb3156f9dfde0c7cbbaf8433098517491b78db9698614ea40e0b1e6a1e36b900453a16ea276f3442bbd27a7ecb981511f5c9209eb096e28588b65b96b50188c0381ff712bc06b2c655cca0751c095d8016251585851e677434dc3efd087a12680fc22e5b8310a10e32caac9b71c876eed31ef09f7fa012ba08dfd2ad68c1e147f50598e550467ef99f295a318faa507ebe776ce55c4da164323c30a5e72dbe027c3ccf96c70197a6fb1b74af133a8be2b03c1b99fd25b3ced51fe3882021a3afd9229f641bc6cad4e1d3cb6ed9b6b68a25f1e1397289981f78924bff24c8dee6a18a0421fa32ae3ab60a0d933a6af4ff704874b09b0739e2f29d8f252d79055f89d3bff10a22c54ac3d8afeece818353a6abe2b7fb8e8e0da5b7ac1cfc985df97580b18211a4e3edff95afdda061547d3ae0406d3286cd305bdfd2c3abf8f74af9a03420e5b03f825e9c53907e13a5812174be42898645149d:97650fae3f59ca76477f2547167749c5830248883225e354ff46c7e381965220d9bef2c2057c7d1990f08bca4cfde877fff2b4aa813d9c4b84fb79eced81ef051df7a6835e3310983ee7ec731125f5b5cf117af0e36b3685bf54ace1c48c46300560a45e9f9bdd96a0bc4d14e89d4b5721a2caff6618b182edb1202f3d0c5d118d09b61812c010e8b196344541cdeefe5fd1f961c5dd75459555ab72ef2aa7a759a4f3ad3caed44f4c9a8ef95b76ed9a99b55dd8a260ba08010d29ff819f2af3513c1a640d6ccdde4999205f9fca8857115d8b5db9f70a62e5eea0d5af065de153f2ededeec63e15c8e09a92582182ac07d81ca63ca4aa597a2220e70481957d415264e258bc263e1cc36e53478aac5ca01694ccb09b4ffd84739972c7dccf3defeafdede162ab6c58a1df27371e3f5493067fc9e2067e579623c009fc825eef0e010fd1ccf2a8d3fbbb3156f9dfde0c7cbbaf8433098517491b78db9698614ea40e0b1e6a1e36b900453a16ea276f3442bbd27a7ecb981511f5c9209eb096e28588b65b96b50188c0381ff712bc06b2c655cca0751c095d8016251585851e677434dc3efd087a12680fc22e5b8310a10e32caac9b71c876eed31ef09f7fa012ba08dfd2ad68c1e147f50598e550467ef99f295a318faa507ebe776ce55c4da164323c30a5e72dbe027c3ccf96c70197a6fb1b74af133a8be2b03c1b99fd25b3ced51fe3882021a3afd9229f641bc6cad4e1d3cb6ed9b6b68a25f1e1397289981f78924bff24c8dee6a18a0421fa32ae3ab60a0d933a6af4ff704874b09b0739e2f29d8f252d79055f89d3bff10a22c54ac3d8afeece818353a6abe2b7fb8e8e0da5b7ac1cfc985df97580b18211a4e3edff95afdda061547d3ae0406d3286cd305bdfd2c3abf8f74af9a03420e5b03f825e9c53907e13a5812174be42898645149d: +c04dc09f119d670fb1eae0136fcc06085f290f4ad1aa1ffc9c160ea5cf47f09dff498ce8c9db7867f6d0276452a466724887e6172f6681671b8ae035f5865ea3:ff498ce8c9db7867f6d0276452a466724887e6172f6681671b8ae035f5865ea3:1e42297f8aeef29a842e0e21f5dbae068e2c9ddaa6fd348e48881f0d42c50bf0ecf1706b94a5d19817ca02d83e9ab2f99d8bfaaa5c85ad39a150b225ad3eafa067815b74672fe026c3ccc677255440b684a76e128ca2ccc429f152577d25b69f40db582d49479afae680712dc0fd1fe1418839687ca60cdde974140462f96148295df1ce43a977351c77f2f0b09a6b26d6fe965fceae17d7b8620371402428544fdf91690b44e9afc2e9088c83ca48dc8576f628724798dc90323174c44996596502a35df8b982c570a6cb51b9a197d431af33f02b80011567fe50cf45ac111b3d556f8c8ce5ae8c9972f2a9936b1a012b9c339e30c97312b65ea59c100f79d795b8a24b31a0a97dc25cced6b8ff5ae145339a048ca12a579017fae8d5cbcb61d52e314dd7c2e72010c47217b1d06878bf2818ca188e8e307960c1689d7dfc0202973cd29f2f7ba743469e685e0e704b04baca4fab5488448a922eabf40be581c1994d74d13a366ce857fb40a6e05da8553694172cc3fd28062f538250aa8c11f68139e79cd1191ba3314b5cea0864437ed2e4b6fbd75b9ded0987b41c202a58ec0254d9d371a795f1dbecddac112be8d09e2d7b9ca5752f406cffb911ca36450bc05f1ec1ca3ca8d35124d1286c55f10f61334e46ece4183b92219a9dcd0e5e78ef2a76cfe9a9ab3795dfdcb44f63d45f5f48ffb4156133ad2e9950884c5bbd2c1cb8729e40a8787f784969fa880c07ffcc97d5c0d2d488085e9116d7107cd5db16ceccdead55025eea2edee93c1b106427618ee09dc3dad1e05676a2368069c8045c3ebc6c67afa52d59398248efcf15e904c7142304ff61971f4d9bf6460c1d6417:4bd19f3d9c5116ec6ae0024d0f246d2ce250d9e0634a232ba06fd3566aed55cbe59f12332cbad65d4349a9d22e7d6e46d2fbdc71d5c8f9da15dfbf17ba2251071e42297f8aeef29a842e0e21f5dbae068e2c9ddaa6fd348e48881f0d42c50bf0ecf1706b94a5d19817ca02d83e9ab2f99d8bfaaa5c85ad39a150b225ad3eafa067815b74672fe026c3ccc677255440b684a76e128ca2ccc429f152577d25b69f40db582d49479afae680712dc0fd1fe1418839687ca60cdde974140462f96148295df1ce43a977351c77f2f0b09a6b26d6fe965fceae17d7b8620371402428544fdf91690b44e9afc2e9088c83ca48dc8576f628724798dc90323174c44996596502a35df8b982c570a6cb51b9a197d431af33f02b80011567fe50cf45ac111b3d556f8c8ce5ae8c9972f2a9936b1a012b9c339e30c97312b65ea59c100f79d795b8a24b31a0a97dc25cced6b8ff5ae145339a048ca12a579017fae8d5cbcb61d52e314dd7c2e72010c47217b1d06878bf2818ca188e8e307960c1689d7dfc0202973cd29f2f7ba743469e685e0e704b04baca4fab5488448a922eabf40be581c1994d74d13a366ce857fb40a6e05da8553694172cc3fd28062f538250aa8c11f68139e79cd1191ba3314b5cea0864437ed2e4b6fbd75b9ded0987b41c202a58ec0254d9d371a795f1dbecddac112be8d09e2d7b9ca5752f406cffb911ca36450bc05f1ec1ca3ca8d35124d1286c55f10f61334e46ece4183b92219a9dcd0e5e78ef2a76cfe9a9ab3795dfdcb44f63d45f5f48ffb4156133ad2e9950884c5bbd2c1cb8729e40a8787f784969fa880c07ffcc97d5c0d2d488085e9116d7107cd5db16ceccdead55025eea2edee93c1b106427618ee09dc3dad1e05676a2368069c8045c3ebc6c67afa52d59398248efcf15e904c7142304ff61971f4d9bf6460c1d6417: +6791bd74d3b4620ef5f1ff56406432c26ab646f6d5e9dda6842ed69052275392da9915a7552f110faea12d47920a09601443d4000a9c7e218d5ba72b74989fa6:da9915a7552f110faea12d47920a09601443d4000a9c7e218d5ba72b74989fa6:36a20e66bb29155161ad85eefe893b53ac5ade165f089a77190b0c239dec8a201685b076b4ded4a10aa459b980a8cca47d5f8de4d2a662e446d5f7fb70ed9be05db1cceadd130b3346d9409f9d6ef52824c764ac6fb1cd156dbd6a473ae722d0ebb25638c51265a22febbb14967d6dd8253c1d038895c6737f067c8f73c3c1cbe6cda4369632d7f4c9acebe87d0571c81a58cfd72cce4a5cf53a1e75259f4c993e67efc8d9c3576c43af04a5caf33d856f7f2755d3a975ab2b685c6f65680cba9ac879f3a8c9a4765b879c0ade1e4bd0d4a70bb6f92b24d429dc746cc78f84811f076f32c61e3585cc8aade9b0ca15224bfbfe18be10a33643600f6612bf013f0efcca837246a0ee5b03c02f1573624c4a44a90f9e423d4e56061a71d0144f5a887a8cd4a9d6f247904e26795951959da121c83c6c941e2b6b9ab76209ffe9178591ead68230b94ae97df58f9f172428c95067598ac582ffb950840d826630c4625f5deaddec1305203b4db6b945f991ed7cd3d6fabca51e2166adad0aad5117336d52d59422f0135c8fa8cdd0884be73586bf284e5ddddbcb95b411f98568526fbe71a5592b56ad5a7345f2874db1d57beab43e8cc69547520629f0ee76dbf432a376fad28bfc77e14d840f0c02d478f1e2337c23b89e73e5279108b5609b18e80db0de11cfa94ecf7239bcff59c54118e4ede4fbfc0823ae546016f774c52198a963b5545a3489b89df7626fd11ed4658d715a4657994035d403b3370d14eed9718d598db675f042592fea89056544b32e5b9c8062828aaa3cf59cb476ad36db1daa2482227a9b7afbc153ce93253d1b39da95eb96f83128ff2554a547e34eea4a0000:b1e8d481065bd5121bb3bf569600bcc26df40c499fbaa954b39a619dc40b9590c31756b8b63f860151694b95765d697b2e1ade0806e92a06c4a559e90fcfa50636a20e66bb29155161ad85eefe893b53ac5ade165f089a77190b0c239dec8a201685b076b4ded4a10aa459b980a8cca47d5f8de4d2a662e446d5f7fb70ed9be05db1cceadd130b3346d9409f9d6ef52824c764ac6fb1cd156dbd6a473ae722d0ebb25638c51265a22febbb14967d6dd8253c1d038895c6737f067c8f73c3c1cbe6cda4369632d7f4c9acebe87d0571c81a58cfd72cce4a5cf53a1e75259f4c993e67efc8d9c3576c43af04a5caf33d856f7f2755d3a975ab2b685c6f65680cba9ac879f3a8c9a4765b879c0ade1e4bd0d4a70bb6f92b24d429dc746cc78f84811f076f32c61e3585cc8aade9b0ca15224bfbfe18be10a33643600f6612bf013f0efcca837246a0ee5b03c02f1573624c4a44a90f9e423d4e56061a71d0144f5a887a8cd4a9d6f247904e26795951959da121c83c6c941e2b6b9ab76209ffe9178591ead68230b94ae97df58f9f172428c95067598ac582ffb950840d826630c4625f5deaddec1305203b4db6b945f991ed7cd3d6fabca51e2166adad0aad5117336d52d59422f0135c8fa8cdd0884be73586bf284e5ddddbcb95b411f98568526fbe71a5592b56ad5a7345f2874db1d57beab43e8cc69547520629f0ee76dbf432a376fad28bfc77e14d840f0c02d478f1e2337c23b89e73e5279108b5609b18e80db0de11cfa94ecf7239bcff59c54118e4ede4fbfc0823ae546016f774c52198a963b5545a3489b89df7626fd11ed4658d715a4657994035d403b3370d14eed9718d598db675f042592fea89056544b32e5b9c8062828aaa3cf59cb476ad36db1daa2482227a9b7afbc153ce93253d1b39da95eb96f83128ff2554a547e34eea4a0000: +234ce4d39b5ebabe9a2c1e71970d718138dcb530cfd296023427d892bf88f8a4cb73930db421f6d24536837bd0bff6fa75bbd141c98a405d4244a3c424550779:cb73930db421f6d24536837bd0bff6fa75bbd141c98a405d4244a3c424550779:77730cf8c8f96b9187902acff9ff0b21746ccaf0a382a7b343d1c72027ae3c3168a73a6b8f49bc8798141e15c2732b6a6b3f757f8a8e86c7a4bacb39551c54874d6bf716897ee4af13253aa5bb79a192104f44dcb3de960745a8e6aa9880524a629fb510a4ce4cbda7e2957dff1d62e705606a2cc84f91850beaac5e5846e1420bc91dcdd2427b69cfa46ae38a4fef4146eae35f9c22e967cb14a1af9cabf83b180465bed6ef2cda382a84d9994aad655d8952e0fbb0f96fc8089f2e7489497facdcd656a8a451b928c11e7a4075072aafbf17d8f1054c9196288ded3ae21f9afd5810a100d8e4d84c4a35a98b30d3e18524438dd4402dfd8e7675f09d080cd915f14af4372f7ce58384972d5d111079651b2acf39d2a167c6a00b2b17ce0b268791bd2be5178fe0f82d64dacdde377a1e8be9e7d8dfc82b08644537bdc870c5819286fd51f6792dc5f67b54be336d44d54febf81b8df8dec5d8686db12f164d0e8ff1aa2c16bacc9806010ec8e91196597ef06a4cf1707def5067a04889d8e48a9bc2c0bef664f5acd1b4f5bc2da7da43dcb5f963245ba552fd493001d870a9517a179c2f0de85be0c682d057488e35c7816ff4ba529aefd7c66091f206f5f4d75cac8bd209ec2fa55be74af231e2f389dcc2d668bf695ed267c3594bad9efc00217c7a0e9e7b6a56a33079a30e73c3733f2d24efecdde87f72f948d277d6b6d5b035b4c53180d23d66cc0ff17c15dd468585e389d91a4c97fd80110b218a0bf7a5e0353f4609d2cf018a065571001c7888555eedbd3622c3b1769cd13f33374772aa6c8a8f588102017d4ee4e50dcbbdb1d610c32670934a6d9e6d9b784bbfe71862bb38:f6d060ed7d18273f18f7a69cd1d8126e478e88a1d7294ff6040846d46107c3e41a423babb2417139fe587d2910271a357fe5bf57c92ee3a7b77533729d0ac20d77730cf8c8f96b9187902acff9ff0b21746ccaf0a382a7b343d1c72027ae3c3168a73a6b8f49bc8798141e15c2732b6a6b3f757f8a8e86c7a4bacb39551c54874d6bf716897ee4af13253aa5bb79a192104f44dcb3de960745a8e6aa9880524a629fb510a4ce4cbda7e2957dff1d62e705606a2cc84f91850beaac5e5846e1420bc91dcdd2427b69cfa46ae38a4fef4146eae35f9c22e967cb14a1af9cabf83b180465bed6ef2cda382a84d9994aad655d8952e0fbb0f96fc8089f2e7489497facdcd656a8a451b928c11e7a4075072aafbf17d8f1054c9196288ded3ae21f9afd5810a100d8e4d84c4a35a98b30d3e18524438dd4402dfd8e7675f09d080cd915f14af4372f7ce58384972d5d111079651b2acf39d2a167c6a00b2b17ce0b268791bd2be5178fe0f82d64dacdde377a1e8be9e7d8dfc82b08644537bdc870c5819286fd51f6792dc5f67b54be336d44d54febf81b8df8dec5d8686db12f164d0e8ff1aa2c16bacc9806010ec8e91196597ef06a4cf1707def5067a04889d8e48a9bc2c0bef664f5acd1b4f5bc2da7da43dcb5f963245ba552fd493001d870a9517a179c2f0de85be0c682d057488e35c7816ff4ba529aefd7c66091f206f5f4d75cac8bd209ec2fa55be74af231e2f389dcc2d668bf695ed267c3594bad9efc00217c7a0e9e7b6a56a33079a30e73c3733f2d24efecdde87f72f948d277d6b6d5b035b4c53180d23d66cc0ff17c15dd468585e389d91a4c97fd80110b218a0bf7a5e0353f4609d2cf018a065571001c7888555eedbd3622c3b1769cd13f33374772aa6c8a8f588102017d4ee4e50dcbbdb1d610c32670934a6d9e6d9b784bbfe71862bb38: +103d118c7dd65d07e8d5582e45042a75792417c692001ee6bd9a927b2b3d9016b45cc94514a6ad672496cd4eb9fdafc1d4a167072c6874dc8ff16d761fb66986:b45cc94514a6ad672496cd4eb9fdafc1d4a167072c6874dc8ff16d761fb66986:5a8ee079186b51cf4629834de0c6bd7334855039a7631d6887652a7728995972e362c1c409f084f5aaf2986ae3f536be0070c4baf459ef60a015ef9d70dfa3ea96711cbb18e92af50c527d7ed457877a07ab83721518c89f7a864191b1e97433b7c6cd634a832e19891e76c62122a49dbffd83498aa416acccb7737fe75f4fb2c35328e6f6ececaaa42e43dba5bc9689673dab96f0befa3c83eb41d4d887b3a117d055e30bb87fbe7c719472f6c7a4cc45f628f5faddc48ca344f77b733c0e3b9f5079dbd07af3a3847af141719cca2f6a766552b45d0fdcdb9868f2c762b6d4933ba10836f95bff71cb88040024c90534c4d7a95a2303b04c2961012af58bc784a96327bbfed039d0802a05262d8e663b78508e92508bc1f2ea2b9be7580bde10a4d663d0d25b0e973b8c5ded59debf19bb044aff1c60c70ea1aefe85f6d15c2c1b84753b59576a49473d65af3ed941a3d514b5c4522c141bdbeed9cb339695b2e02dc07000867f1bf8ed8cfd3b1afe688fbca80e2f9ba5c0b188a19adaff6686ca0ff0edd444661291fa27ca1fc529429a5d8ff79ed2027c60ffe3b2c03fb8a66a3985417ba4ace7d14fd0e2371edf5d71bc02b9052767c7f72c4e6f3f30e0638276b9c420aa4333095d31313033090582e3ac4d9fd3203120ba2514973ab9d1c7fc42290116b51dae9fd579410ae078ed320a5a1b49aa7b5fefcd756395213af8641e29b0ebb5b83e3780e5d10e9d3d11998148f6c6f86c4d4eb252e28c70fa3a55c43d4d7faafcbcdd45ad2637f215e81549eb8a4cde4715b7107207503a79595060b83ace8feb673b997968469dd9b4ad6a7ea81c6e61810033f3edfc137d974209575c:2fafc13c43afe5054372b923d24f292b283afca3aca3b3e432380684961713c8d23e86b3580495dfbae424b767e4795a0f922f71b50f5d7a369ab8c6e880420c5a8ee079186b51cf4629834de0c6bd7334855039a7631d6887652a7728995972e362c1c409f084f5aaf2986ae3f536be0070c4baf459ef60a015ef9d70dfa3ea96711cbb18e92af50c527d7ed457877a07ab83721518c89f7a864191b1e97433b7c6cd634a832e19891e76c62122a49dbffd83498aa416acccb7737fe75f4fb2c35328e6f6ececaaa42e43dba5bc9689673dab96f0befa3c83eb41d4d887b3a117d055e30bb87fbe7c719472f6c7a4cc45f628f5faddc48ca344f77b733c0e3b9f5079dbd07af3a3847af141719cca2f6a766552b45d0fdcdb9868f2c762b6d4933ba10836f95bff71cb88040024c90534c4d7a95a2303b04c2961012af58bc784a96327bbfed039d0802a05262d8e663b78508e92508bc1f2ea2b9be7580bde10a4d663d0d25b0e973b8c5ded59debf19bb044aff1c60c70ea1aefe85f6d15c2c1b84753b59576a49473d65af3ed941a3d514b5c4522c141bdbeed9cb339695b2e02dc07000867f1bf8ed8cfd3b1afe688fbca80e2f9ba5c0b188a19adaff6686ca0ff0edd444661291fa27ca1fc529429a5d8ff79ed2027c60ffe3b2c03fb8a66a3985417ba4ace7d14fd0e2371edf5d71bc02b9052767c7f72c4e6f3f30e0638276b9c420aa4333095d31313033090582e3ac4d9fd3203120ba2514973ab9d1c7fc42290116b51dae9fd579410ae078ed320a5a1b49aa7b5fefcd756395213af8641e29b0ebb5b83e3780e5d10e9d3d11998148f6c6f86c4d4eb252e28c70fa3a55c43d4d7faafcbcdd45ad2637f215e81549eb8a4cde4715b7107207503a79595060b83ace8feb673b997968469dd9b4ad6a7ea81c6e61810033f3edfc137d974209575c: +47eee2024dbe09953e981f6986520f666082aa9ef4892dfdfbdbd250d2a1df289f13cd8ebf5080347975159f360296a7164014d8d069e831dab0332607997cde:9f13cd8ebf5080347975159f360296a7164014d8d069e831dab0332607997cde:c133f033cf3bec6cd19212ea47dbecb13f2c6018f9e0878ac884bfb575c0f5d3fc5b4999580eb8acbcaac83ae9ac9b443e6d1cff449c3689b433d50900b2e8b71d00e119c8b875094bdab916adaab75bcc852959d8d759795bbd6b360ee484afe47b1ad28391f25afb8d4e3afe0c5b600498a12833fe2a1a5483df940b173ba0d9d8c4d1321fa4b733334b0f6d878a0e5a76f4f180ac119a82082acb1488e49bbca7a0369c191bd6d0c5d445656821a99ccbc945949eca8136cc6e127d9de92ef64f174a6c04c8b5e52495f0dd674bb5ca128a9209968fd450dce319913fd6a30c3382798163e6585f58ef208be4d0c6a2513a752388397a4ae444838c8466dbc36fbc36ae08bec88eeda131c14d06366b673151454100dea1118150fbe441b1e7826e545d9868242e899f5ea53e434c37936ce6fd06146283e8fbd536480de55a16102c44754bc554d5bc2de2f25e19e567a023df4640e74ff3a49e4dd30e0e2558b3dbc2aab92fdd5e79425ecbc4c699fe1f161965f1d0b45d8bdab52ec9bf7a69d8aa0bd171e755ce7b8d0718f7267afb733efca54b213e6f5adab4c9d76c867fcb69ae05c74bd21516cf342c6161f6fc9eccacf970ebce540cd892bc106c6bd563610298b70968f091bcc6e1f7ab4a5b2c6374a1903f4d3ad5e1bd8643a9c2f878c3d7a4dc49ef3197edbcda7bb91e7e06606087d4e981bfab93a6024977962e45262517f338b6857eec2158a297b2aa91524b677a21aac57be0b63a8074fe54e7a9dc70c5a5c3de728b9c17ec1212ab1130eb17622cd7b22ab6eba9185e8d67be6c47a2e5adc663d4642cc120222e299fe134fd7fcd00adabcfaa642fe2e08dd52e2c3f32:5defae0e173ecc18d5f01ec9291be160d5eabff63fd5423f2bc66e3f6408c196353502dcef21effa4b9c14bf27b687d1b6e86b2a205a89eb35c376a3a325690dc133f033cf3bec6cd19212ea47dbecb13f2c6018f9e0878ac884bfb575c0f5d3fc5b4999580eb8acbcaac83ae9ac9b443e6d1cff449c3689b433d50900b2e8b71d00e119c8b875094bdab916adaab75bcc852959d8d759795bbd6b360ee484afe47b1ad28391f25afb8d4e3afe0c5b600498a12833fe2a1a5483df940b173ba0d9d8c4d1321fa4b733334b0f6d878a0e5a76f4f180ac119a82082acb1488e49bbca7a0369c191bd6d0c5d445656821a99ccbc945949eca8136cc6e127d9de92ef64f174a6c04c8b5e52495f0dd674bb5ca128a9209968fd450dce319913fd6a30c3382798163e6585f58ef208be4d0c6a2513a752388397a4ae444838c8466dbc36fbc36ae08bec88eeda131c14d06366b673151454100dea1118150fbe441b1e7826e545d9868242e899f5ea53e434c37936ce6fd06146283e8fbd536480de55a16102c44754bc554d5bc2de2f25e19e567a023df4640e74ff3a49e4dd30e0e2558b3dbc2aab92fdd5e79425ecbc4c699fe1f161965f1d0b45d8bdab52ec9bf7a69d8aa0bd171e755ce7b8d0718f7267afb733efca54b213e6f5adab4c9d76c867fcb69ae05c74bd21516cf342c6161f6fc9eccacf970ebce540cd892bc106c6bd563610298b70968f091bcc6e1f7ab4a5b2c6374a1903f4d3ad5e1bd8643a9c2f878c3d7a4dc49ef3197edbcda7bb91e7e06606087d4e981bfab93a6024977962e45262517f338b6857eec2158a297b2aa91524b677a21aac57be0b63a8074fe54e7a9dc70c5a5c3de728b9c17ec1212ab1130eb17622cd7b22ab6eba9185e8d67be6c47a2e5adc663d4642cc120222e299fe134fd7fcd00adabcfaa642fe2e08dd52e2c3f32: +b6c88b4c90fd19a149d381671953b9b16d428f6361cf503a110477e297f8d2f88ebfb084f997b2ea7932a2353b2c8b16bd825e1af587a8ebc51a6c45aea343ae:8ebfb084f997b2ea7932a2353b2c8b16bd825e1af587a8ebc51a6c45aea343ae:7f4bf4f52173eff072f818d0aa97e6935d8baccf4839663253b2414fe6b1f34cf43ab120155a1a3aea7b4819ddd1031673b8a7a6bd0b9dda4adefe692a56162c646180794264c5122115eb90a6d3054f084302dce3d836ac3de820638bd89a86bf0a4c01547cfdc543d676fe1639ef72c5b845c494e07814cec8a47d03df73be4e33c05afe9a190dda043360496be4cf3a6319da9ab06481677f1a4374d60d3d3b6394f8843c869b0f41a1e81c2b1a54bf5aacbd98207c8dbacb36422a3aa013d5e849e044af928545c046097caf149d970215115dea0b5a85401ff672e02ed40bd0f5a440cd56494053c896c3bd32606349f7cbe7ece2a2230cf236dac59f7817965f3fa80fb48aa30b0b19efa9a96591646bd25e67c185f77e21d6630b288d4e55146b2abc15e95088d936080775618154bbdda115702a2afd6fd5f56b923e188833ec448944d30283e337254242c5812d7245a4e92670bce3546efaed22d274e1e6048b5a0f01efbf895dc42494baf1747185cb1a4b88fdf1e6099baabc6a5ab5a2727b1e248789d170caa2449671a8f6e094c11332ea0ac2afe88132c644ff883d0c499ad76a93df472fa013eaa27ab4dad679d2511b5049c4e98baa2e7b00a534891e290265edb076f7dca8e6fef3f433034a16575f0e53da4577e6b13f0cb0d785870d0d098d5d80f413a268ba84e0431a786923771378cd57b8192258e2633cdbe03cc316a0950970526fd3e09376bcef0d03b7074e59a5a84fc64e795a812156d960567650bb1e1424b3cc9a4d99d57ba858dd1a0cad3532e998146e79264045e28ebbfd75a426b0bb851a244ad6be7bd5765af493dfc44ee378cd04daf3917eef2a6206:7447a20181b02cf1b6ad529569ce437c2a0508116f50205c41e6378b74fe2fc53630aa0dc4b80c31cb26c8f09bf8fab27e3abc8f1f604a5ec06631a84f6f2e067f4bf4f52173eff072f818d0aa97e6935d8baccf4839663253b2414fe6b1f34cf43ab120155a1a3aea7b4819ddd1031673b8a7a6bd0b9dda4adefe692a56162c646180794264c5122115eb90a6d3054f084302dce3d836ac3de820638bd89a86bf0a4c01547cfdc543d676fe1639ef72c5b845c494e07814cec8a47d03df73be4e33c05afe9a190dda043360496be4cf3a6319da9ab06481677f1a4374d60d3d3b6394f8843c869b0f41a1e81c2b1a54bf5aacbd98207c8dbacb36422a3aa013d5e849e044af928545c046097caf149d970215115dea0b5a85401ff672e02ed40bd0f5a440cd56494053c896c3bd32606349f7cbe7ece2a2230cf236dac59f7817965f3fa80fb48aa30b0b19efa9a96591646bd25e67c185f77e21d6630b288d4e55146b2abc15e95088d936080775618154bbdda115702a2afd6fd5f56b923e188833ec448944d30283e337254242c5812d7245a4e92670bce3546efaed22d274e1e6048b5a0f01efbf895dc42494baf1747185cb1a4b88fdf1e6099baabc6a5ab5a2727b1e248789d170caa2449671a8f6e094c11332ea0ac2afe88132c644ff883d0c499ad76a93df472fa013eaa27ab4dad679d2511b5049c4e98baa2e7b00a534891e290265edb076f7dca8e6fef3f433034a16575f0e53da4577e6b13f0cb0d785870d0d098d5d80f413a268ba84e0431a786923771378cd57b8192258e2633cdbe03cc316a0950970526fd3e09376bcef0d03b7074e59a5a84fc64e795a812156d960567650bb1e1424b3cc9a4d99d57ba858dd1a0cad3532e998146e79264045e28ebbfd75a426b0bb851a244ad6be7bd5765af493dfc44ee378cd04daf3917eef2a6206: +7949a9472f725ce7c68d7ea8fc16e13d9e0e0a58f58c24f9228c88e80264090da370f82833f88b4f5f5310b918e6af93bb724bfbdf3c02c503780b2c83ab6cc6:a370f82833f88b4f5f5310b918e6af93bb724bfbdf3c02c503780b2c83ab6cc6:955386b92dd6bf92601bf81e84d25144b5fc0bcd7d23c76e7deb5f5ba6316bb61a5d8e74185b012967f0a4438b531696deb4b8101089e0c0482adf13c0613191b977f77b0419814147f5da64a1d3beb1275b9849d1297ba8532ae0a647a8ace395ae0ed00f67348c5ee5ea19b5f1c5bd2e622818e8adcba3c17c27987e4e3d6d910a56c7e5149d3f5574fc06009bf4dd3e37cfe3ebda2c2116d366dd88ce5ea72ab387490585443b086e8aa38d11d3820b72c658e463cdb59c5393011d4a8f4cb6a195229304e76239fa5e8c2cbe0f39dcad138a0ecb3c51579ec9a120a51607eefebfa59a44620ea5b1916087ea338533fc132ff2e4a43d052fd08b6b1b24fb672f73c9b9ba20b7c1c41ea24d912de9b555b6e5682b970608ff229ad3086f431f9be190ec39224ba2ed8acb4c8eac8582e23aaa79827c44e248c5ba092ddac0f2f79684aa93fc061073e1821a56afb9bfec952df2719a9c7a403e6a93f7a656d74b61c1d19083f8d3f19e659fa2b718e0bd04b693d63dafb86adbee5d87c75b7d129122f178a0e669eb035ca4d8eb45397f1851264e2cf0a0cdd30720c5e139cd6a573f1fa241cae9425805ac79603e8de350efdb0b9bc95ba7b085c1ed92c12acf53f5d4a1137598008f2a3672c84e5f769a25c7a4a16579d86288774972606e4e7d85263ad217e0dbcf343fe554c109c5d9409b7939073ac55a03420fec289b114a5c54c20b45ea69938533ade7b3ae85e1a783dd97897c3ae8254183cc54045c2a18ecbe521691f2619d9b8f1fb347ca055a7b0b4c24f64d1773e01416441efe159923217a84874b9c4ec265cdaab643908068497812c1af15c188071e78f597fedfce91c5d4c6:e02898cc7c30ee01648247497be8a9c6378593dc8820bf7c17ffcd18118af09879a769f539dd9237e96821166634998f946da65e6dbad8271511669e2d6cad02955386b92dd6bf92601bf81e84d25144b5fc0bcd7d23c76e7deb5f5ba6316bb61a5d8e74185b012967f0a4438b531696deb4b8101089e0c0482adf13c0613191b977f77b0419814147f5da64a1d3beb1275b9849d1297ba8532ae0a647a8ace395ae0ed00f67348c5ee5ea19b5f1c5bd2e622818e8adcba3c17c27987e4e3d6d910a56c7e5149d3f5574fc06009bf4dd3e37cfe3ebda2c2116d366dd88ce5ea72ab387490585443b086e8aa38d11d3820b72c658e463cdb59c5393011d4a8f4cb6a195229304e76239fa5e8c2cbe0f39dcad138a0ecb3c51579ec9a120a51607eefebfa59a44620ea5b1916087ea338533fc132ff2e4a43d052fd08b6b1b24fb672f73c9b9ba20b7c1c41ea24d912de9b555b6e5682b970608ff229ad3086f431f9be190ec39224ba2ed8acb4c8eac8582e23aaa79827c44e248c5ba092ddac0f2f79684aa93fc061073e1821a56afb9bfec952df2719a9c7a403e6a93f7a656d74b61c1d19083f8d3f19e659fa2b718e0bd04b693d63dafb86adbee5d87c75b7d129122f178a0e669eb035ca4d8eb45397f1851264e2cf0a0cdd30720c5e139cd6a573f1fa241cae9425805ac79603e8de350efdb0b9bc95ba7b085c1ed92c12acf53f5d4a1137598008f2a3672c84e5f769a25c7a4a16579d86288774972606e4e7d85263ad217e0dbcf343fe554c109c5d9409b7939073ac55a03420fec289b114a5c54c20b45ea69938533ade7b3ae85e1a783dd97897c3ae8254183cc54045c2a18ecbe521691f2619d9b8f1fb347ca055a7b0b4c24f64d1773e01416441efe159923217a84874b9c4ec265cdaab643908068497812c1af15c188071e78f597fedfce91c5d4c6: +d68a5e3c47eedb3099dffc804cf19c5e74bf7bf5f01f54d4d91d7574f3d3dc7c46467fe9ce3acfd0d74346be21c46216db81aece6ce0308fb8dc6386fc3446cf:46467fe9ce3acfd0d74346be21c46216db81aece6ce0308fb8dc6386fc3446cf:596c03d0873f572f45c3b16f0ef4b52ad2bf59ec76d3c0e534d62c1f84164ddaa425fb85c9548485b7064677e99d04c39b6eba04c966397ba6a5f4ebaa69a241df95a6e44502509d6350557ebfea60264b62ad7f74d16e5d25d45970cfebeb33e7b1bac3348dd03a8e99133b26bbfd7aa722c2587f72d5526e980da9eebdf108211dae50bbe8c65f9abee69a1bbf84c03e40448babad03d3cf3b7de4887d2b47737702796482d2265c566b0f623b53c8671bd3719edec0ffd5f49b49b072c1564a57f9bab6b92d1f068d756639a4331452e61aa7b218a88b9db77a19fb82f13e9868edb798d5beeca55d1ab095b316225f3f6390f89578f0160428747bcd21be6ae1d86991b48ef80d569250858febf3276bd5de3db65a245c8bdcf1488c4825968945786bed63f3d13f1409363b948560476858b396bce588e40b311ddfc22ad622ca7d1e69561464dda5009e638aa5ec9f4c039293aaec75001ffc68a7cb3ae01874dc7f39d75027f59a28965fc19530c0752fe99b153da7c0e542bda76ca1e10b7ea158efb4d821fbc65e7271ad9941095315447abcad0880a0075dd04b1325c72633acbcb261fcb407c264a34d70bf1f044feead069af5a87dd352f4bd8110fa178adbd8dbf23c6b575cdd5df22cc9a5cdd37d9c8faab81a4cb3fb5c4fe7ff629dbaa9fc06b80c1fb691c28655955cfe5ca44149b150b3cf140d9acacb14313a72c84098de72bacc0272d79ed6617f72dec88e19b84425492a429ec6d2ec08b86346dfbf20ea2a3619e77b6ac64230ebe25fa0067abb5f33ee49adc7c44bda7046d7f224f2e7a4895683fca8684ed6a031844f5786bcda48b5042394487b52402a09907788a1e140:896fc3caba7fd3fc285d5eddddc0120cd46da7c6efabe66b150b002760b8414a89ac9e7f1f7b7c7b33598f61f45718e4ff4ac368ff129614b4fe9219f237b009596c03d0873f572f45c3b16f0ef4b52ad2bf59ec76d3c0e534d62c1f84164ddaa425fb85c9548485b7064677e99d04c39b6eba04c966397ba6a5f4ebaa69a241df95a6e44502509d6350557ebfea60264b62ad7f74d16e5d25d45970cfebeb33e7b1bac3348dd03a8e99133b26bbfd7aa722c2587f72d5526e980da9eebdf108211dae50bbe8c65f9abee69a1bbf84c03e40448babad03d3cf3b7de4887d2b47737702796482d2265c566b0f623b53c8671bd3719edec0ffd5f49b49b072c1564a57f9bab6b92d1f068d756639a4331452e61aa7b218a88b9db77a19fb82f13e9868edb798d5beeca55d1ab095b316225f3f6390f89578f0160428747bcd21be6ae1d86991b48ef80d569250858febf3276bd5de3db65a245c8bdcf1488c4825968945786bed63f3d13f1409363b948560476858b396bce588e40b311ddfc22ad622ca7d1e69561464dda5009e638aa5ec9f4c039293aaec75001ffc68a7cb3ae01874dc7f39d75027f59a28965fc19530c0752fe99b153da7c0e542bda76ca1e10b7ea158efb4d821fbc65e7271ad9941095315447abcad0880a0075dd04b1325c72633acbcb261fcb407c264a34d70bf1f044feead069af5a87dd352f4bd8110fa178adbd8dbf23c6b575cdd5df22cc9a5cdd37d9c8faab81a4cb3fb5c4fe7ff629dbaa9fc06b80c1fb691c28655955cfe5ca44149b150b3cf140d9acacb14313a72c84098de72bacc0272d79ed6617f72dec88e19b84425492a429ec6d2ec08b86346dfbf20ea2a3619e77b6ac64230ebe25fa0067abb5f33ee49adc7c44bda7046d7f224f2e7a4895683fca8684ed6a031844f5786bcda48b5042394487b52402a09907788a1e140: +31e82bc1cc5ced21cdc8bfc2dbbb976b08780afc6944af7e88e50e67874d84f18df977e2b040acebd3dafd67b87f9216e8c371beced618fef3a496d651a5d7b5:8df977e2b040acebd3dafd67b87f9216e8c371beced618fef3a496d651a5d7b5:69d461b6b7a866e94cd59a5a23bba4a1276602f042baa850d5b29249d6743ada04d3d938219abbc22ada66a1778197f70bf80b597a8b4ae00bdb876812d3ab4ec011df73341c85053eebcc2df0acfc21548283b553ecde0154828ed5af47571985f89767b005b622c9e7c079dde694e49dc0550c7918cc515c274dbd9c5469d2f18ecd90de664e03ca41e53be20b96e25af40c54ab0f7cbe9e05ca3fa5a37c1aa8ebfb6444a32c496efc68157c69f358c15f6ac09d46efef9a685df7e8dd63b304bd3c638ccf532fe901f11cf97c5b1cbed33c70637c721b0289adf6bb6d87c30479fa926e043074302b76f1157d0a81dec493e87a3c643e7a20b7a41525a38db04e78dae5e7797066bfae2cf448a447e9004cce8e41f0987991fad30311ddaa459a2644f4b941c068c0d6c0771afcf42bf9139a684da298486ecf67523bf8509a45ba5cb8b3864ad22c0c6a828c6db72e371de410b47dac49ae9d3b5702b1739b8d760ce98611c07d88df5f04683808a21afc2e61713fc2c025cb25fcc4ee941841083b22f61e2656fb3b8dad41c262c89d2f17610309f2d5c29589a2df61e55149895032ca981e4557e130a237fc0826fc872529861bbb8328d673f39b58b73d060ec596bf22e7ee081f44e92c02a5677679520e2a2b4d22c77f2b212d5aaf050bf2c141e3e28b8571d4321937426235c7a646d647e3efe183c27b7492565ecacd7f43c67a74453f4780e88711ba2dd4a3941b12ddd3909270fb3debd422436ab6166f08c99c886cc0e8e3cecd0642e44285b8864aa416943c5a186974f464535a870a012861bc2e587149cae971624e61c31d8a507e3ad82773e723bcb75df54bef847a407bcb7b1d57:240702ac6c68d597d222da949d0c47d16b390a477d1fb579e9d8948adf9b3b6a7fd4458ae6385b7e2b684a05b55c63fa6cd087bb90113cbab8e4af142fcf810e69d461b6b7a866e94cd59a5a23bba4a1276602f042baa850d5b29249d6743ada04d3d938219abbc22ada66a1778197f70bf80b597a8b4ae00bdb876812d3ab4ec011df73341c85053eebcc2df0acfc21548283b553ecde0154828ed5af47571985f89767b005b622c9e7c079dde694e49dc0550c7918cc515c274dbd9c5469d2f18ecd90de664e03ca41e53be20b96e25af40c54ab0f7cbe9e05ca3fa5a37c1aa8ebfb6444a32c496efc68157c69f358c15f6ac09d46efef9a685df7e8dd63b304bd3c638ccf532fe901f11cf97c5b1cbed33c70637c721b0289adf6bb6d87c30479fa926e043074302b76f1157d0a81dec493e87a3c643e7a20b7a41525a38db04e78dae5e7797066bfae2cf448a447e9004cce8e41f0987991fad30311ddaa459a2644f4b941c068c0d6c0771afcf42bf9139a684da298486ecf67523bf8509a45ba5cb8b3864ad22c0c6a828c6db72e371de410b47dac49ae9d3b5702b1739b8d760ce98611c07d88df5f04683808a21afc2e61713fc2c025cb25fcc4ee941841083b22f61e2656fb3b8dad41c262c89d2f17610309f2d5c29589a2df61e55149895032ca981e4557e130a237fc0826fc872529861bbb8328d673f39b58b73d060ec596bf22e7ee081f44e92c02a5677679520e2a2b4d22c77f2b212d5aaf050bf2c141e3e28b8571d4321937426235c7a646d647e3efe183c27b7492565ecacd7f43c67a74453f4780e88711ba2dd4a3941b12ddd3909270fb3debd422436ab6166f08c99c886cc0e8e3cecd0642e44285b8864aa416943c5a186974f464535a870a012861bc2e587149cae971624e61c31d8a507e3ad82773e723bcb75df54bef847a407bcb7b1d57: +cc56bc7cdfa611924e72b07f68abc6ca5b85ff8bbacdff406e51ba720d09a8665ffee221ab4d0fe6f4c9346c5e5a4b8a636a6a0badce9667be739f4c9e6733c1:5ffee221ab4d0fe6f4c9346c5e5a4b8a636a6a0badce9667be739f4c9e6733c1:088304f22e1a286062defbebb1827a64b76a14e87015e7f646178777aba79704688d7bf32e1efac97a9fc339810ebd3df93e4ea024686953ed91fa6d2ab6e07ec7811a6d91ca91b098db4725df65846a95b808635a8d0c5fe5ace25f0780e896177bc1bba1cdb4449251c01b482f023862f88e072e79cde5dbd6c1d9ad9c07c606f5df85a6eca2966cbfe0a1673968112f26a317053f167f611af297efa802e0a94b3e1f33a27b73e5597abb224115ebe75e294a1bcdcd979255b0a80265c089aaa7d6bed2e3d0c918f56f4a55f448d863365c6c5846fb9b2b9bb55f6b7c6dff5847b71bfdd4bb5b9bb2e4249bc0243a02ab4d22ba78a43d182195aed78fece84cb1ddaeb9eff68156045b2932e638d7731d0e8b4c9c8c383b0d6d392d21fc640762c87d3692b1810bcc4a42392ff13d45169ecbf0135055093105098c869b68887e934e2b9da5232ac6c9373800f70b64ec64a4aa0ca044c0777ca3a3acaa138c14249672a55b24ddfe4dc357573241e14ad0ac16475a8e3867886d41eea35fe7932ba9aeaa0c86c9eb6db7808049ade7b5cc1a40822c66dea93ad22d44b9e42904b5b83684ae2931fe36c608ff7096f1b09f811b02672804406e08ed9e7745676ce047f0f7f64708e49bb78754720b8aa226f5556abf05b56584645292dad08e2473639a8ce5475e0ce9192f8ba2dd32ce14c91975ab602f7c13538c52952d0396158c7cc6b942be7d923eeb523a73b5b411966d14ac96e5b096a52932a416292eccddb91071c88560e70ecd4fe2fe24d523fafcb98e4021502f4190a0515edcb24019eaca09ec2615a9bfdeb60eb354c84a1f3cec7ffd7e65a5515d47959a4c4ec48d8021b1754ae2bf84:9b86a192b64f4f044ffbf87b41c7ee52f7a721aa320e7bad6425995990315cdd502be4e1116019d131a9218d19614ad95543b1889af0a97ed4d256dc33d76e08088304f22e1a286062defbebb1827a64b76a14e87015e7f646178777aba79704688d7bf32e1efac97a9fc339810ebd3df93e4ea024686953ed91fa6d2ab6e07ec7811a6d91ca91b098db4725df65846a95b808635a8d0c5fe5ace25f0780e896177bc1bba1cdb4449251c01b482f023862f88e072e79cde5dbd6c1d9ad9c07c606f5df85a6eca2966cbfe0a1673968112f26a317053f167f611af297efa802e0a94b3e1f33a27b73e5597abb224115ebe75e294a1bcdcd979255b0a80265c089aaa7d6bed2e3d0c918f56f4a55f448d863365c6c5846fb9b2b9bb55f6b7c6dff5847b71bfdd4bb5b9bb2e4249bc0243a02ab4d22ba78a43d182195aed78fece84cb1ddaeb9eff68156045b2932e638d7731d0e8b4c9c8c383b0d6d392d21fc640762c87d3692b1810bcc4a42392ff13d45169ecbf0135055093105098c869b68887e934e2b9da5232ac6c9373800f70b64ec64a4aa0ca044c0777ca3a3acaa138c14249672a55b24ddfe4dc357573241e14ad0ac16475a8e3867886d41eea35fe7932ba9aeaa0c86c9eb6db7808049ade7b5cc1a40822c66dea93ad22d44b9e42904b5b83684ae2931fe36c608ff7096f1b09f811b02672804406e08ed9e7745676ce047f0f7f64708e49bb78754720b8aa226f5556abf05b56584645292dad08e2473639a8ce5475e0ce9192f8ba2dd32ce14c91975ab602f7c13538c52952d0396158c7cc6b942be7d923eeb523a73b5b411966d14ac96e5b096a52932a416292eccddb91071c88560e70ecd4fe2fe24d523fafcb98e4021502f4190a0515edcb24019eaca09ec2615a9bfdeb60eb354c84a1f3cec7ffd7e65a5515d47959a4c4ec48d8021b1754ae2bf84: +7a57f2dda0ad0338ab9a13c9a3497e9c75238c1531589789227cd2749bc6e9506f738dc5e7d9e240c9f4d0c06a5e021747568b69a75d507a2e0be7ea613526c5:6f738dc5e7d9e240c9f4d0c06a5e021747568b69a75d507a2e0be7ea613526c5:8c8575a11d2ff2c238e419ccb00633d04e8b8bd7742901d588dd6a2f00aa12f08ae41dcaa9338f8c47e95312192cf6b245a00ce688a029da56dd1b1deb0d34b5414fe1c21d6b63d06b8534ace8e866c933fd7c5a65eda95a1737a9ecdb17859149ac696951b82c230e8275e96dd02fd455ea675379e67ba63484b6283831fe3ffe52d6ec49b709106705c9d19b859de9fd200887cb44d8fdfe6961fa4ca2340944c764c704491208257e735482af8cb69041dde685241d3fbf46fda057248b8987be1f80b54eb54009f324dc450e886e79f912585b91c9dfafe9012262c471403b1e8b5c31fc5375a1ddf99b68edf9ed70af8594f7d84b2cc4911fe90500c6eebfbac085553550e35bd2e52514e979e7241e9f8e34cdf8513abe72510dff3cfec7e2bc6488641cfd0a65ae0e09ebe99b15b29d45ea67a57aad554d4f8bfce1386ace228839e3a8a534140eec3d37d51be361f5ea1883739f56615f75b055a06a91471be98bc9453783c358382bd0555ae9eb0bdcd66629a611fc1a11c653c82214587dec12ba120e2513070fe69e982f7a80ad159f6a325d977d01d050d116a62a4f8acab6c3d69ff6c878213c60a94845cae106de6c5d6fe2508d94565b7ba75d58d1ad47d76a20defa7568cb7fd66f57cf3774a21d3ffa7d8aa6d86dc284b70e0f17e7630bfc10cd1fc9a8d9c592d39f24a7b5c8e8aff353577e6ac9008690c7a159a7e83be5a6ae8fca9644bddfa37a92b07055f9fac9fa97fb3e8f5f4d917dda5c6dc6ea34b64d302405bc38062e07ce93a1a88aed5fbaf995a09b45b28ad4a6b273dec1413c5404529d825b5edc2e27a390eb7e8c2b43905e116d887ab5fb993dfe150ebdcf817ae62e03:989123761d93563278fd0a78aed64e2de6f4a700fc9a70d2187748ac06d9c2c377d1995f89c7727fe2f120784e4171c42d6353ac3d4e3f620c639c75786c460a8c8575a11d2ff2c238e419ccb00633d04e8b8bd7742901d588dd6a2f00aa12f08ae41dcaa9338f8c47e95312192cf6b245a00ce688a029da56dd1b1deb0d34b5414fe1c21d6b63d06b8534ace8e866c933fd7c5a65eda95a1737a9ecdb17859149ac696951b82c230e8275e96dd02fd455ea675379e67ba63484b6283831fe3ffe52d6ec49b709106705c9d19b859de9fd200887cb44d8fdfe6961fa4ca2340944c764c704491208257e735482af8cb69041dde685241d3fbf46fda057248b8987be1f80b54eb54009f324dc450e886e79f912585b91c9dfafe9012262c471403b1e8b5c31fc5375a1ddf99b68edf9ed70af8594f7d84b2cc4911fe90500c6eebfbac085553550e35bd2e52514e979e7241e9f8e34cdf8513abe72510dff3cfec7e2bc6488641cfd0a65ae0e09ebe99b15b29d45ea67a57aad554d4f8bfce1386ace228839e3a8a534140eec3d37d51be361f5ea1883739f56615f75b055a06a91471be98bc9453783c358382bd0555ae9eb0bdcd66629a611fc1a11c653c82214587dec12ba120e2513070fe69e982f7a80ad159f6a325d977d01d050d116a62a4f8acab6c3d69ff6c878213c60a94845cae106de6c5d6fe2508d94565b7ba75d58d1ad47d76a20defa7568cb7fd66f57cf3774a21d3ffa7d8aa6d86dc284b70e0f17e7630bfc10cd1fc9a8d9c592d39f24a7b5c8e8aff353577e6ac9008690c7a159a7e83be5a6ae8fca9644bddfa37a92b07055f9fac9fa97fb3e8f5f4d917dda5c6dc6ea34b64d302405bc38062e07ce93a1a88aed5fbaf995a09b45b28ad4a6b273dec1413c5404529d825b5edc2e27a390eb7e8c2b43905e116d887ab5fb993dfe150ebdcf817ae62e03: +32ef6d789a1ea393f1bf9f11de34f57d653c4e77d51e6050fef4e8d7bf183db5c1aa181e620f60525c2b17da8d290bae5d339e17eabceab58cd76ae066f41179:c1aa181e620f60525c2b17da8d290bae5d339e17eabceab58cd76ae066f41179:11a9c3c1ba7cfb61ad103305c25886de9f8815c6c21f17a8733a024f9497da0540db3603a671aae837dbbba19e19f82ddfc8af855980a70125fc61cd7ffd10777e366e5e9569927af0f245d4f39b3fd0f45879c253401412855e5761905ed6ef318b6a06ea6e9f906f9bd016bcb694a0df65a016bdfe845a09f23e5086c5aaf375efeb86da51239ddc350bac0cdb03b874db1507e6ad4e2c9f46028ca2388363541493b6cb92c1dfcaa3efd68c6b4e91efb46751d23f4c48a973f0a5c7c6fe2a1269d2a69e9fc4ab8ba3b92f796449ba3dc70245ed505cc0eeee1636647a68c7679d0b6d651bba35c29b81478d17ca3685707ad616e6e5604381f84ee52b25ad02fc0dfb85432efb1fecd090c02ad002c1857fced88fdfb2ff26dd0f5018fb47d813581f6508ca637c7365177c513d1ee05879a65c5b676b3aa873a1935c5437eadcb66dfb052a5e7c3e81d44b3daf698f42244ee2ee4b6ed2b7e6e56e61ff9cb45e719fd746198bf2a7de6d25af3bc6c7b0ed8abe3cb389afd84ffa2a230d93bc0c29d5a9419cbff11b7883329921480b5844655d996c7cab29dfb2a3927b82ba7c306c4577b6f8b5dbe2afaf9bf14a8f9554cd01a69a991bf212828de1e63172e833de06698cdb3b28716380314572bf5bcfd34ef52a6fadda87babe6bacdb20ce63c725cb0ff61fe30c1b51dbda2c2625f99dfeb029a3e58cba7d01905111caf42f27025e720e18eeb07dae9155c55aa300e22eb5e94dc7a0a84ee67d91a960ae08ca632dbb1737fc9a43dbcfb3a879eb9fbffd7299338e264bc1237ab6a5bc2a263cfa99e8544439d96331639fe9408e54a350610ff01de3f85799adeb73d82be938074dea858ea636b63abd:88f3a6e0bbaa3e060bc9d91fe2968c61126b20317f59842e4ae48711cdbaf62c6c0207405d1c4849950271f0aaa7593091109e478d13f356964f7dbab729af0011a9c3c1ba7cfb61ad103305c25886de9f8815c6c21f17a8733a024f9497da0540db3603a671aae837dbbba19e19f82ddfc8af855980a70125fc61cd7ffd10777e366e5e9569927af0f245d4f39b3fd0f45879c253401412855e5761905ed6ef318b6a06ea6e9f906f9bd016bcb694a0df65a016bdfe845a09f23e5086c5aaf375efeb86da51239ddc350bac0cdb03b874db1507e6ad4e2c9f46028ca2388363541493b6cb92c1dfcaa3efd68c6b4e91efb46751d23f4c48a973f0a5c7c6fe2a1269d2a69e9fc4ab8ba3b92f796449ba3dc70245ed505cc0eeee1636647a68c7679d0b6d651bba35c29b81478d17ca3685707ad616e6e5604381f84ee52b25ad02fc0dfb85432efb1fecd090c02ad002c1857fced88fdfb2ff26dd0f5018fb47d813581f6508ca637c7365177c513d1ee05879a65c5b676b3aa873a1935c5437eadcb66dfb052a5e7c3e81d44b3daf698f42244ee2ee4b6ed2b7e6e56e61ff9cb45e719fd746198bf2a7de6d25af3bc6c7b0ed8abe3cb389afd84ffa2a230d93bc0c29d5a9419cbff11b7883329921480b5844655d996c7cab29dfb2a3927b82ba7c306c4577b6f8b5dbe2afaf9bf14a8f9554cd01a69a991bf212828de1e63172e833de06698cdb3b28716380314572bf5bcfd34ef52a6fadda87babe6bacdb20ce63c725cb0ff61fe30c1b51dbda2c2625f99dfeb029a3e58cba7d01905111caf42f27025e720e18eeb07dae9155c55aa300e22eb5e94dc7a0a84ee67d91a960ae08ca632dbb1737fc9a43dbcfb3a879eb9fbffd7299338e264bc1237ab6a5bc2a263cfa99e8544439d96331639fe9408e54a350610ff01de3f85799adeb73d82be938074dea858ea636b63abd: +0a5525a4598f60992f86ba1ab9eee6e2675622f943284fc0553e4446ac5a4c53db60d7ea29f8d60dad33d02ec5f42232057bd1c4bd6180a242cb7ab6f4426781:db60d7ea29f8d60dad33d02ec5f42232057bd1c4bd6180a242cb7ab6f4426781:f787321b42c08d4052449a488593d885b4e0c34a5d64149fa8b9c85ee54bcbecb50909b2a86b88258a10e07e8f8c2d068a89fb165a6ace7e64998ba57d89d9bf2b8b38a1f6d8364aee05ce3348bed48b88c2473bf5f2665f51ca073a5305358eaad4365d58b83bc9814e25f54c37cd9b68a808a57d6c2d7d7b6deb5fe20f4f96fe725f8de65c29a4f1ccefd7c2c6f2fc0116d58676acbc58691c79c2b006785a0975a31d8d3c949161596a068aaf2226ab842550e9c0b2610a29531d1f3f7f00826bb6c7dbe04e28ae1b9ff6f888a49d82812f452e1b32740b234ddd9642e18f32ad9a9af7f8952528674a2cda25b4f7ba867007ffa7f78f163db8f36914956bfaecd50f6d1af4ee133275a8eaab94bbc0ae52b6d9b2832634232ec0e8b5f8022d3ef1ead9b79ef9a16564277194f2380d9021e1f17b184b8d3a7a34d15139a39c7728c22e1a3a67a27a6ca4b8a8a0636c6054d0f741f046673619fc6b070e62ff4862f59d269007f3431339637a89f564c0db3d9bcfcd19fc25138ac66d474d80f4ad79f6d1e7844408e88034eeaff4a790338d546bfcd7424c119e211f363cb89c888749346a89d32f023bb6b0366a1ede4325032aa35f52e9df938a5027ebee9688ae480dde1a9c9b42d1a9c08f719223dfae1cfcd49dd1053aaa381c24cc9c7abfcf8f6d86d6af72eef05304412f3db2585aa9e0f3a4f1b6d710d02ab11db1fc90ad4de25d04299f3129c212e9cb73c0047953455bf98ec8fd2674e47b949957deeda018badc9f2f68a1b18ef5c583b095e08dd906da5f220da029b9c400e3ca91c7cbd87f3430c742337f61cf54745b0622bcb90762c6bafef87e1ec888c364fad646c33acc22af5438b84cd5:8fa6b0aeac71132ad882975868f1bdb8c11f1a6c1b9c54594e0e46286ea6c9a5d6d5b0eaeaca9ae3af74e72326b3b6f2eaa893c0ec42a49c56ef514f75c77f01f787321b42c08d4052449a488593d885b4e0c34a5d64149fa8b9c85ee54bcbecb50909b2a86b88258a10e07e8f8c2d068a89fb165a6ace7e64998ba57d89d9bf2b8b38a1f6d8364aee05ce3348bed48b88c2473bf5f2665f51ca073a5305358eaad4365d58b83bc9814e25f54c37cd9b68a808a57d6c2d7d7b6deb5fe20f4f96fe725f8de65c29a4f1ccefd7c2c6f2fc0116d58676acbc58691c79c2b006785a0975a31d8d3c949161596a068aaf2226ab842550e9c0b2610a29531d1f3f7f00826bb6c7dbe04e28ae1b9ff6f888a49d82812f452e1b32740b234ddd9642e18f32ad9a9af7f8952528674a2cda25b4f7ba867007ffa7f78f163db8f36914956bfaecd50f6d1af4ee133275a8eaab94bbc0ae52b6d9b2832634232ec0e8b5f8022d3ef1ead9b79ef9a16564277194f2380d9021e1f17b184b8d3a7a34d15139a39c7728c22e1a3a67a27a6ca4b8a8a0636c6054d0f741f046673619fc6b070e62ff4862f59d269007f3431339637a89f564c0db3d9bcfcd19fc25138ac66d474d80f4ad79f6d1e7844408e88034eeaff4a790338d546bfcd7424c119e211f363cb89c888749346a89d32f023bb6b0366a1ede4325032aa35f52e9df938a5027ebee9688ae480dde1a9c9b42d1a9c08f719223dfae1cfcd49dd1053aaa381c24cc9c7abfcf8f6d86d6af72eef05304412f3db2585aa9e0f3a4f1b6d710d02ab11db1fc90ad4de25d04299f3129c212e9cb73c0047953455bf98ec8fd2674e47b949957deeda018badc9f2f68a1b18ef5c583b095e08dd906da5f220da029b9c400e3ca91c7cbd87f3430c742337f61cf54745b0622bcb90762c6bafef87e1ec888c364fad646c33acc22af5438b84cd5: +2d5ddffa2e58c90451ea05de47b8c49234e26ced54854e3acef11d8ee6852da77bfd1c8a4a0bbb4606d2e5bc090f56b20d58f2204b6aed831d3df4d406b47605:7bfd1c8a4a0bbb4606d2e5bc090f56b20d58f2204b6aed831d3df4d406b47605:4f1c5b4e6fac3baa3e9010f3bf293c779e61fd7bbe05a586f5aaf08026371627a209acd188afb2dbe0311547940559711640f78aea9a62818962f445a8e7ed6fe6c5f49162e7435d1b625b88ba39dab0ad56fd2c0ad6512661362bf78afe5a1416b647f3b88a056c9e7289c9b0cc3afb43402198563493e737b1da052506b6c9306d75ad6693db6d1571f96f6f52990c4df19665a6bb63073fdd9f55596896a2e9c2622f2b0c2cc99ddd1b649fb0318058d74794e38ec657ebc82abd5bedf8b3f4bba3bb6c9935fdf6826502b769046b36d96dc695d7c85404284d2a2ab7fcf3b02f68a1493dd383ca6339fac1cde47f53c5e026d0869faffe40abdb98195230f17d0cfaa533315afdbfe7d1afc3a615b4f75090233a503f8861e32374e1ea9557674231d9d737d477b33ff82ac0b2c0ba93c11fb523e613618ed370524a60f4d4c83694c033606d1d069d544dccd3900c37a3b3363efbcf6697f9f762b33b1294583953fc53773ef56726eeb470ebe92149b73648a16161d494120a318bfb080cc38e4996f4b263ffe78c7877fe13c2fc55219f44260e8f253bdd379d870e6c91048b1d8d4e88b88218b2b049fef53b2ae1f8c921ed2bcb434669e3975dcc3fe4520ca8024842f7ff2ba1e22cfeb5d4c9e435eada601ff183b26364eee1faa59d19e6aa4f0975238496a709e46bf68336b068bd80b346f11faa3817a07d1cbd84382b2102986f295a1398077ba291d6b5f5bd860ec6177273468f0ee0f2591b575c4366e189b224e9ffa35bc78a4aa8c06954fe33d080ffc0b23e209fd0e79421f1bde818a86890cf172236db211657d1003119fe91d4e27c524ccc11fade0a25f57a7a1d677e1da0b9c043d02fca38:ced9d61010339c471ddf9fefcaa82d1eab3a2e0e60278553b4dd9f395be58149c91594e5618b0b10bf3aab94f159b530f64463eed66fa2ace54fd92572a06a0e4f1c5b4e6fac3baa3e9010f3bf293c779e61fd7bbe05a586f5aaf08026371627a209acd188afb2dbe0311547940559711640f78aea9a62818962f445a8e7ed6fe6c5f49162e7435d1b625b88ba39dab0ad56fd2c0ad6512661362bf78afe5a1416b647f3b88a056c9e7289c9b0cc3afb43402198563493e737b1da052506b6c9306d75ad6693db6d1571f96f6f52990c4df19665a6bb63073fdd9f55596896a2e9c2622f2b0c2cc99ddd1b649fb0318058d74794e38ec657ebc82abd5bedf8b3f4bba3bb6c9935fdf6826502b769046b36d96dc695d7c85404284d2a2ab7fcf3b02f68a1493dd383ca6339fac1cde47f53c5e026d0869faffe40abdb98195230f17d0cfaa533315afdbfe7d1afc3a615b4f75090233a503f8861e32374e1ea9557674231d9d737d477b33ff82ac0b2c0ba93c11fb523e613618ed370524a60f4d4c83694c033606d1d069d544dccd3900c37a3b3363efbcf6697f9f762b33b1294583953fc53773ef56726eeb470ebe92149b73648a16161d494120a318bfb080cc38e4996f4b263ffe78c7877fe13c2fc55219f44260e8f253bdd379d870e6c91048b1d8d4e88b88218b2b049fef53b2ae1f8c921ed2bcb434669e3975dcc3fe4520ca8024842f7ff2ba1e22cfeb5d4c9e435eada601ff183b26364eee1faa59d19e6aa4f0975238496a709e46bf68336b068bd80b346f11faa3817a07d1cbd84382b2102986f295a1398077ba291d6b5f5bd860ec6177273468f0ee0f2591b575c4366e189b224e9ffa35bc78a4aa8c06954fe33d080ffc0b23e209fd0e79421f1bde818a86890cf172236db211657d1003119fe91d4e27c524ccc11fade0a25f57a7a1d677e1da0b9c043d02fca38: +4df5e11dec80ecd882837554fa3135b9d5029df42027aa3b3c929246329fee96efd928898fa144c2d1c8334fa2e6b5b6a325a7102a2c344a145541ee9a6c046d:efd928898fa144c2d1c8334fa2e6b5b6a325a7102a2c344a145541ee9a6c046d:fbd6f371b4c8b152c9ce0c6396a77c0fe480bc02007f336ac58fd4addda9d69855ac9e93a45d3e350f41ff502aa1d8fe159ce89b064802a0a1890f6a40a7ef57c6e5e5ed040280df07e7f48fe819be63176710757cb6e440b4f78b5759dce028bf585b3c3feca1cf5981dadadfd27ea124af45ef638542a8617ff49f9470ac2285943c7c3b1163b903955ab99b6eab17f4d49ffa87207abbfc111c4b91f5413dfc9bea31843d115ddeb1da40b45f58f47c417b5e77d5818934e730eba9c4557bbf48cb7fd4e664558af4fb44ee3d94c16e883631f38476f4837db94d54122fa134ca51a525aad5e24b76018fee9a2e8f60e2bb48d24ab8b146f84ffa9820120e7c50d45c0cfbe35c8c31419b078e90712cfe934c3be3a94ff2158873aefe34dc6e36902b1675e1a47cb608dfe960fb4da8d2a8490cc38ebadc73a1003c4941fda8fae944a1de8e3b10ef6d9e67ceec745977d333ac9e71214121ede8892295e27799f206675a9d54ac12159d3a1f954fd0eeffbd30a31904fb2eee77a8aa9dc4ccbbe2851096146a4ce0e81fb9c62498dbd83bf83b55029a5e900086b9531ce3247a98f8654efd8fe7a836431f75daf0868f0108326e23026d2db4a72124ec4e39d4bbf3d846c9f51ca3cc31eb1d02c2ba321e4619f2b659c0bf0fe5c19b213f3c79124f3643f74dd0ff9ce5d27727be6c6958159c164404f43301fe1742e279de9efd441e73e4ea7a842587a79d115d36eca9c03c90ff0d147474109fc20a91d7b3cc22ebcbb8c7f71bd61e8cae47c5050cec1d4849a1d4a8e7a6f845548437706c25331c9e57c2cc6da117f2e5a0f4b368c4cb206265c4178e0655ff675ffc1d4c58eceb9edb4da3ad2c5f62cd13ab48:62545e6c07801fde95b461e2e753c4b6c84c25124eb330a2725989d5e340dcef0c7456d4c7c6a178a221b6328348253db787a9e5510ab9cc278515ae3e58fb01fbd6f371b4c8b152c9ce0c6396a77c0fe480bc02007f336ac58fd4addda9d69855ac9e93a45d3e350f41ff502aa1d8fe159ce89b064802a0a1890f6a40a7ef57c6e5e5ed040280df07e7f48fe819be63176710757cb6e440b4f78b5759dce028bf585b3c3feca1cf5981dadadfd27ea124af45ef638542a8617ff49f9470ac2285943c7c3b1163b903955ab99b6eab17f4d49ffa87207abbfc111c4b91f5413dfc9bea31843d115ddeb1da40b45f58f47c417b5e77d5818934e730eba9c4557bbf48cb7fd4e664558af4fb44ee3d94c16e883631f38476f4837db94d54122fa134ca51a525aad5e24b76018fee9a2e8f60e2bb48d24ab8b146f84ffa9820120e7c50d45c0cfbe35c8c31419b078e90712cfe934c3be3a94ff2158873aefe34dc6e36902b1675e1a47cb608dfe960fb4da8d2a8490cc38ebadc73a1003c4941fda8fae944a1de8e3b10ef6d9e67ceec745977d333ac9e71214121ede8892295e27799f206675a9d54ac12159d3a1f954fd0eeffbd30a31904fb2eee77a8aa9dc4ccbbe2851096146a4ce0e81fb9c62498dbd83bf83b55029a5e900086b9531ce3247a98f8654efd8fe7a836431f75daf0868f0108326e23026d2db4a72124ec4e39d4bbf3d846c9f51ca3cc31eb1d02c2ba321e4619f2b659c0bf0fe5c19b213f3c79124f3643f74dd0ff9ce5d27727be6c6958159c164404f43301fe1742e279de9efd441e73e4ea7a842587a79d115d36eca9c03c90ff0d147474109fc20a91d7b3cc22ebcbb8c7f71bd61e8cae47c5050cec1d4849a1d4a8e7a6f845548437706c25331c9e57c2cc6da117f2e5a0f4b368c4cb206265c4178e0655ff675ffc1d4c58eceb9edb4da3ad2c5f62cd13ab48: +85d32330e2e073a46030ca0ee2df2f8eb874a9fddf5624c8031775111f11eea26ea7de2ed5ea5cdf50bfffee77f7bd2fcc21d48666bb1f4890c76a69cc7ba4e8:6ea7de2ed5ea5cdf50bfffee77f7bd2fcc21d48666bb1f4890c76a69cc7ba4e8:ae6107f38ff94ed0327903cbaf6c3e3a3498c47abb2989a8b37b3a19df88c6de790accb4b7258177b9151d1fe04063577d3c3acdb4c929968afdad6f252a67ed4ca89d060f1a4653983f7ab58ddb93e2878fbab0637dbbeb95d25c5986839de2748d9f34027aeebf1d9eb936cb6770e08d45b8095bac9cbb71db14e8a34222b1f2237b9f0bc9766a231a6d102799f7c081d500fbeade603cdcdd7d5b965fbace4be5c2cd932dcf5f6ed31722f41d5a363b34babf3f636fb303824aa701dfe1d3e41263078c1ebbdcb1f73f1245b83e3fa70ab8e3f1413e6b06bdae022b714d60a401d57480dc64e7aac6d3de85fc94d853ca13b7e67415579d5c672123a5af194bee14ae35dc2724ff209f1166638661f881b1194aa4e31b42a527964781591504ba76103f97b7f5520315473ec94bb017a16667b22a8576a7cc2ac0b7756303c756f0ddaae9d0189e6c8de349f91957c72a529e9f7e9b9456524840ba02344f55ad3c11a0b259901439f2655ab9f8c6c8e8e960c057d9c7dafe425c75d4a33b801d4547cd0551a6802a8005dd72424764dcf57e4aa22290ea4f5baac51d7939c05342882ee14380ef2d4704b41949b2282a1e1a3fa7ddea9fe83b9fc51d4eefa2ebac722e4c0a7c599b6925f01b8a2066dc0c26f92196f4f503e887c1e6efb093f1531387bd88c691997b9b89e3cdf7da12d3734183a4b6126be9e0774704b529659b5548f1b87512cc1878ca4ef55990b483c9af6aa97635f4f07949727065abf21e21e32990b1a7d07d74e02d9b07ec639931bf9e2ca3941f2ba6b5ef14dcc2a247d2117e9cb41efa3fcca24716641452beed2f92657c2fb731f0b94e8c892a81bba91f639df43796acd3013ac044f608:414363fead6e59a3438ce5a3a277d62bdd00fa2efac6463dd13fcdded93a7f108ae1f528ffc8ff4eca331dab91ae5b1416e2ddb73b6daf853b03c81e9936560aae6107f38ff94ed0327903cbaf6c3e3a3498c47abb2989a8b37b3a19df88c6de790accb4b7258177b9151d1fe04063577d3c3acdb4c929968afdad6f252a67ed4ca89d060f1a4653983f7ab58ddb93e2878fbab0637dbbeb95d25c5986839de2748d9f34027aeebf1d9eb936cb6770e08d45b8095bac9cbb71db14e8a34222b1f2237b9f0bc9766a231a6d102799f7c081d500fbeade603cdcdd7d5b965fbace4be5c2cd932dcf5f6ed31722f41d5a363b34babf3f636fb303824aa701dfe1d3e41263078c1ebbdcb1f73f1245b83e3fa70ab8e3f1413e6b06bdae022b714d60a401d57480dc64e7aac6d3de85fc94d853ca13b7e67415579d5c672123a5af194bee14ae35dc2724ff209f1166638661f881b1194aa4e31b42a527964781591504ba76103f97b7f5520315473ec94bb017a16667b22a8576a7cc2ac0b7756303c756f0ddaae9d0189e6c8de349f91957c72a529e9f7e9b9456524840ba02344f55ad3c11a0b259901439f2655ab9f8c6c8e8e960c057d9c7dafe425c75d4a33b801d4547cd0551a6802a8005dd72424764dcf57e4aa22290ea4f5baac51d7939c05342882ee14380ef2d4704b41949b2282a1e1a3fa7ddea9fe83b9fc51d4eefa2ebac722e4c0a7c599b6925f01b8a2066dc0c26f92196f4f503e887c1e6efb093f1531387bd88c691997b9b89e3cdf7da12d3734183a4b6126be9e0774704b529659b5548f1b87512cc1878ca4ef55990b483c9af6aa97635f4f07949727065abf21e21e32990b1a7d07d74e02d9b07ec639931bf9e2ca3941f2ba6b5ef14dcc2a247d2117e9cb41efa3fcca24716641452beed2f92657c2fb731f0b94e8c892a81bba91f639df43796acd3013ac044f608: +66590d369984c6f5ad3a89c78ddfca10a0a7657995dc0188b6b57ac3164731a498873ab13346ee48677c4f8612db31ebd13db58b2b034fd155afa8720f4e93e8:98873ab13346ee48677c4f8612db31ebd13db58b2b034fd155afa8720f4e93e8:2ec1c6b0829737832c9c798a92eb490b23d334c3bbe627cb582d17a9e42960efcdc7d34750e0b4aa864c204fb8d62b47992e91dbfcfd69f51d937dc06c48c0ad43e8598371cd0e3bbce416bfd44b0944b993aa2993fdea487134cde42277723e0683ec98e69595e9b7b14c8cf9617a1e30ddb8060eacba48d88253b165336108de0cb02ff20f5424b567830869c9b4329c9945f0bf2f3c7acd1e774358930cd890fd9cb864d950935ad8a4a3beccae8f833f6356191371c32633dcf882709b0d98bd807b383aed8d7bb097b6e262ef700c9d768f4b5690e3a1a8f21755d658db2d1bfd2f7071e0caec7c2c5381c5ef5c2c2281c6bcedc867390b90f3b27b0f0f64a33658578a5c0d66e211e6fff6e86488acf82bc0f5e2664b83699046037c0d33d340ff98ed6263354c24273136ff0e4f0f233a6c8254fc0c90764330e3b1057b1e666d5ecd5a2efeaa6a105bfc858431b88ed7fe551eb32ac0af27c66a9803a3bcf87634c66c7066dd0197a3cbd2d6f4e65cfdb8f3daf9f3ca5c4f4e0add45f5541aa18d041f706e4fa87c34e9a223d88572eb50083ee8c7c475df568bc73bd08c0f0deaa374afb1c178d0dddb236e15a8bc2385ed3f52b8761e637887407a20aec3e99ec830dae3167ef0cdb3f3ffd200d83b75b749690b9e25e2171d072ca56f71baecd21f7d45a12c91b2c0fb3fea3b158e54648284bb0095b36244b0b121f9f1384ce9004365e7772fa30828250f51985f1b17b2d2f80a33e8fc6d8565ea15cdaacd42a87bd7c9408b1fe1c770665bdded754bc2ff2ef91b973a86b99f1059c6f227246a698b38541509dd5449fce60d386224183b7dce1b3884f7bae1c2e4eb594510b5ca585279d9041df8817b0619:f0db63a1bc7624161ca0063853b2dee45fccd22471e012366f868a4a9c74654e13f1a315ad83916ebfb8dc31a420f83cf645c4c9d16bb4d5d99d23c7b43e23002ec1c6b0829737832c9c798a92eb490b23d334c3bbe627cb582d17a9e42960efcdc7d34750e0b4aa864c204fb8d62b47992e91dbfcfd69f51d937dc06c48c0ad43e8598371cd0e3bbce416bfd44b0944b993aa2993fdea487134cde42277723e0683ec98e69595e9b7b14c8cf9617a1e30ddb8060eacba48d88253b165336108de0cb02ff20f5424b567830869c9b4329c9945f0bf2f3c7acd1e774358930cd890fd9cb864d950935ad8a4a3beccae8f833f6356191371c32633dcf882709b0d98bd807b383aed8d7bb097b6e262ef700c9d768f4b5690e3a1a8f21755d658db2d1bfd2f7071e0caec7c2c5381c5ef5c2c2281c6bcedc867390b90f3b27b0f0f64a33658578a5c0d66e211e6fff6e86488acf82bc0f5e2664b83699046037c0d33d340ff98ed6263354c24273136ff0e4f0f233a6c8254fc0c90764330e3b1057b1e666d5ecd5a2efeaa6a105bfc858431b88ed7fe551eb32ac0af27c66a9803a3bcf87634c66c7066dd0197a3cbd2d6f4e65cfdb8f3daf9f3ca5c4f4e0add45f5541aa18d041f706e4fa87c34e9a223d88572eb50083ee8c7c475df568bc73bd08c0f0deaa374afb1c178d0dddb236e15a8bc2385ed3f52b8761e637887407a20aec3e99ec830dae3167ef0cdb3f3ffd200d83b75b749690b9e25e2171d072ca56f71baecd21f7d45a12c91b2c0fb3fea3b158e54648284bb0095b36244b0b121f9f1384ce9004365e7772fa30828250f51985f1b17b2d2f80a33e8fc6d8565ea15cdaacd42a87bd7c9408b1fe1c770665bdded754bc2ff2ef91b973a86b99f1059c6f227246a698b38541509dd5449fce60d386224183b7dce1b3884f7bae1c2e4eb594510b5ca585279d9041df8817b0619: +41cf071f4842ecd494191b8cf28cc0923185ef1b07458a79a59a296d3549822e6dc8e446db1da353b58d0c45d8b4d816ba59e25bb680712d62d6d3dbf78d0698:6dc8e446db1da353b58d0c45d8b4d816ba59e25bb680712d62d6d3dbf78d0698:daeb5f0e84f1590bca2b9d9719ef5d1cfa79e0583446332f18e9e4feb0b1f15340297ac9ad6724c85bb16558ea54eb5d702a47248badc6252a804371b74cfe1062d1dba1ec68fd1d4dd029cb55034bbf61068251eff3983636f6debd5727be91993b3e4d0abc96ec196421a47b7893f83986d6c0323f0d19aaf2cde9d3565c104c9d3176ecb5ed5e173fee52b5a0c42b6ab2fcb1ccba9649c2c67c520e9b96cea693df3e58609ad6a0bd522efaaf03858d245dd0a38f84a2fb1020f4dd97c3aeef0e24477d30d256701e900bef26a8a6269ab660d74293a2bf1d20c2cfaebb7c2820f5f5b07453bb69ee769b52391539f0c606d22eb3923ee6f5a1d46050af90f011f851ace76327d3d18c48170a9a25b04b770fd938ef8a30b7bd03391dd36c516b62f0cb78670740e00e69595c418d967253820b754c4fd666e3cce16ee0c94183bbea706fe298e1c99ddb821217ed9008cc8e8b83bc8b819915b07b146fe745024ac3c46116cb4cce5e32ec5d7524a2388d9fe297eb02811af4546fcd5860e14c0d13f03dd75a4249615900078a3c358c5342962bc1beacf68c246821a459ab5321ec9f574f49d10389f40f14ddfc8513ffe3deaa7336035a675fa5858b490c5d247780064adbaf75a76335eec9ab918771b0b1df5147642aef4a166ab172ed601fed210f6c0cffd91869f7490b57e7c65241863e7e8c0a26eba63b5342d0fd8214ac731e1c438d0177115f6a19e0935c7af6bc7dbeb75511d9bd8e63e3e2f47ab0dd1cedd7b180d74a4b44d461197aefdd3620465166a39b45395043ce8874cdd72c602bd3d2eecbad3466b5cb1aa41ae92a8afef2d764cec0c449d27efac437938f280bea9c50a582e57c27f9b3de872f0c:41052bc417b24dc48383966af0143f9c0ba85bbefbdaf791b16a4dad1f570eb80703c0a2cdeb2f7ad6dcd3fa7bdb5c225e869cd8fb278dff0667d38accf3db08daeb5f0e84f1590bca2b9d9719ef5d1cfa79e0583446332f18e9e4feb0b1f15340297ac9ad6724c85bb16558ea54eb5d702a47248badc6252a804371b74cfe1062d1dba1ec68fd1d4dd029cb55034bbf61068251eff3983636f6debd5727be91993b3e4d0abc96ec196421a47b7893f83986d6c0323f0d19aaf2cde9d3565c104c9d3176ecb5ed5e173fee52b5a0c42b6ab2fcb1ccba9649c2c67c520e9b96cea693df3e58609ad6a0bd522efaaf03858d245dd0a38f84a2fb1020f4dd97c3aeef0e24477d30d256701e900bef26a8a6269ab660d74293a2bf1d20c2cfaebb7c2820f5f5b07453bb69ee769b52391539f0c606d22eb3923ee6f5a1d46050af90f011f851ace76327d3d18c48170a9a25b04b770fd938ef8a30b7bd03391dd36c516b62f0cb78670740e00e69595c418d967253820b754c4fd666e3cce16ee0c94183bbea706fe298e1c99ddb821217ed9008cc8e8b83bc8b819915b07b146fe745024ac3c46116cb4cce5e32ec5d7524a2388d9fe297eb02811af4546fcd5860e14c0d13f03dd75a4249615900078a3c358c5342962bc1beacf68c246821a459ab5321ec9f574f49d10389f40f14ddfc8513ffe3deaa7336035a675fa5858b490c5d247780064adbaf75a76335eec9ab918771b0b1df5147642aef4a166ab172ed601fed210f6c0cffd91869f7490b57e7c65241863e7e8c0a26eba63b5342d0fd8214ac731e1c438d0177115f6a19e0935c7af6bc7dbeb75511d9bd8e63e3e2f47ab0dd1cedd7b180d74a4b44d461197aefdd3620465166a39b45395043ce8874cdd72c602bd3d2eecbad3466b5cb1aa41ae92a8afef2d764cec0c449d27efac437938f280bea9c50a582e57c27f9b3de872f0c: +a2c8e161a8d9d6e888c3d09b0b972737307a2cbd2acd7ccd804d2431ac6c58d23a325775886732deca406857a8056010aaea2875545ba6f3df30754571386992:3a325775886732deca406857a8056010aaea2875545ba6f3df30754571386992:83a3bebcac5f28c5433e3c4f1e7bf5d2e4dcd2f5e59dbee0a83b07025715350746f85675f1dfea374aa7d794287b892ef9097ff6d2e122f0a656fba0798cdcfcb3645dfcfd788c740c0fd04520e7a06a02a05829630a2bf0cdfe2ecca009ec44049946bb1d2326ddd61d7ec640bf69eb44fb23cc1ff478c570c75db7e766e35b7c43db73680d1407a94399fb621baf3845745c1c4ed0b9f0b485be2d53c568545ddf18775a837a05d9c9157b084e8cd01fc324f07f116877e4075dba2432c8a7752e9e939586ad93f0c0aa5edac94b8d82e5449997b15b8c8961589c442821aa83b60239ec5f158c3f5e9ec5bea5115d5fed61918e8fcd5bce61c777f20b6bfe803a69c6fc794ab8c57df271da863872a61335b1fa29f4608ff037f712069809ca642a0307c79aa92e10cb893a29d17201a0b6d1b46a7212b3baec9703c0b0392ba6b76e5c9c10f83599b81ea22283f9547aacdaa7f30896d1ff731e11fb9e56ad06030417119805bab63521496c3bb92a12f5e55afcf60ed4217737f3046b16ca506657a6d696d75a6d8e18e9efe2b08c8b1fa0728238e27cfb322166eee4ee76968b777b50ee6a2b804e1e9b46016620132b6588718d978ca2c0026979c400d3c5336751210f0b00d269ec8f4e2f9559e180332dd270e50cc9465c5558936355521bc3c9560fc19ec14242121e6bb2fff8f50337fc264acf1ac1704328334b3b52cba96d9303b1b5db859dae31d80f1711fba251e10b4d122128f9faff6872d0c0b81eef59541f832b0a9df3a4cdd591c87736b1aecf242c275a10c3fd67839dad4ef399b9494ecd77f7ba5b5d4f2ca304e5b22921307cb18fa64aa3d01c4411c8369ccede465ee369ee637d43d28826bf60ddde:560d01b94df11d83347752ff51b3545ef55c5632ae7c8efb11aadd8312def72562e8f5d75ece10ad46bc96c860deece39e634a5f50654d4cdba84a8e6f70240a83a3bebcac5f28c5433e3c4f1e7bf5d2e4dcd2f5e59dbee0a83b07025715350746f85675f1dfea374aa7d794287b892ef9097ff6d2e122f0a656fba0798cdcfcb3645dfcfd788c740c0fd04520e7a06a02a05829630a2bf0cdfe2ecca009ec44049946bb1d2326ddd61d7ec640bf69eb44fb23cc1ff478c570c75db7e766e35b7c43db73680d1407a94399fb621baf3845745c1c4ed0b9f0b485be2d53c568545ddf18775a837a05d9c9157b084e8cd01fc324f07f116877e4075dba2432c8a7752e9e939586ad93f0c0aa5edac94b8d82e5449997b15b8c8961589c442821aa83b60239ec5f158c3f5e9ec5bea5115d5fed61918e8fcd5bce61c777f20b6bfe803a69c6fc794ab8c57df271da863872a61335b1fa29f4608ff037f712069809ca642a0307c79aa92e10cb893a29d17201a0b6d1b46a7212b3baec9703c0b0392ba6b76e5c9c10f83599b81ea22283f9547aacdaa7f30896d1ff731e11fb9e56ad06030417119805bab63521496c3bb92a12f5e55afcf60ed4217737f3046b16ca506657a6d696d75a6d8e18e9efe2b08c8b1fa0728238e27cfb322166eee4ee76968b777b50ee6a2b804e1e9b46016620132b6588718d978ca2c0026979c400d3c5336751210f0b00d269ec8f4e2f9559e180332dd270e50cc9465c5558936355521bc3c9560fc19ec14242121e6bb2fff8f50337fc264acf1ac1704328334b3b52cba96d9303b1b5db859dae31d80f1711fba251e10b4d122128f9faff6872d0c0b81eef59541f832b0a9df3a4cdd591c87736b1aecf242c275a10c3fd67839dad4ef399b9494ecd77f7ba5b5d4f2ca304e5b22921307cb18fa64aa3d01c4411c8369ccede465ee369ee637d43d28826bf60ddde: +d3d188b390baccd95024526146b82b9184e197e46a9340a0e6ec18bf75be7fc5d8f794948aa6986100214e9b7b9024420806b4c67846d5bd506113b353a2ea3d:d8f794948aa6986100214e9b7b9024420806b4c67846d5bd506113b353a2ea3d:5e65658e420375433fd7c1f6be678841e58104f10b4c676359d84fce7992f5c57557d738f830b505fa0c2b9eabf8d1a9f81fe8f315d662e2b84ce95299ebf4e503b5e1f7f8cdb668ae733f3d0cdd4c742ab5f272bea4f18d183e8923847662f9a39cd4b14ec76d11032fe573c26201aef66601cec683e34b89afd964e987801c706a85e27bab33701cd109bcf07b27ca67f022c494a04cbe5a9c6d63aad936cdf1a180fd05865198b96f06a78da95799d3aa4df3b170033c69e8fb04288c3546553b579c0ae3938062d3d8421cfa66268529bec0271e53b4ee7d099e7148a802df80fe5eedee1c903ae8ed4d640ead761262dd4014f25f9397ba3f1c08d83a3c485cfb55f89919aa972d6b7e7711be9e30c1eb96a0c3845309fb23dbc75b6991dd6e48cdde90e04f228e8ccf3ba23f2747cfb9d3381a9305f816f26cdde41c0220fad228ff6a8b095c77b6bae8fa3368142724bf1f5e0f6fbca5320c215b6ba86b91e3a8acf750e93fa7eaa65c4f785ef8421a19c1e27bc24b428e08a90242abac9bd4aa03c656f8f46dc40b36152c1bd0def1acfc0da10a2fa1dc3da7ace5a8fd76227bb1a602390fe57afd32efe281f2ea6b2e4d2545cb88d2308d72691c9a52b4ca25231a0107f25d117cc935397621c683bdc8f22e810340f2cbac4ceaa3468665261879f0074200743e0de5f3e58308b98b04b8c7148a4e004e667e832b0084b5f2bdc6fdc959f2fc28a8d31d9a9e78e5d5f9c0b119e5ff1f68f7c0daf0c0f16947cca5b7ced09601e2ebed282ef2bf8fe9a27ed27fc5bcda8aed6c71bee3e7751004472689bbf6d9d07952a242ff870d7c3f5e1ffc2c1f40fc9ab7579b392b554f3dc588c03ab957431fe5d02cbc711ad489fe:16976b267de96e38dddc8478075f6bdd7159e56334b2d2d1920946294f33cd6b7f9c50f8057f496cab5d94bb4dca262f9f0fdf9b1b64741f4b722d32efa822035e65658e420375433fd7c1f6be678841e58104f10b4c676359d84fce7992f5c57557d738f830b505fa0c2b9eabf8d1a9f81fe8f315d662e2b84ce95299ebf4e503b5e1f7f8cdb668ae733f3d0cdd4c742ab5f272bea4f18d183e8923847662f9a39cd4b14ec76d11032fe573c26201aef66601cec683e34b89afd964e987801c706a85e27bab33701cd109bcf07b27ca67f022c494a04cbe5a9c6d63aad936cdf1a180fd05865198b96f06a78da95799d3aa4df3b170033c69e8fb04288c3546553b579c0ae3938062d3d8421cfa66268529bec0271e53b4ee7d099e7148a802df80fe5eedee1c903ae8ed4d640ead761262dd4014f25f9397ba3f1c08d83a3c485cfb55f89919aa972d6b7e7711be9e30c1eb96a0c3845309fb23dbc75b6991dd6e48cdde90e04f228e8ccf3ba23f2747cfb9d3381a9305f816f26cdde41c0220fad228ff6a8b095c77b6bae8fa3368142724bf1f5e0f6fbca5320c215b6ba86b91e3a8acf750e93fa7eaa65c4f785ef8421a19c1e27bc24b428e08a90242abac9bd4aa03c656f8f46dc40b36152c1bd0def1acfc0da10a2fa1dc3da7ace5a8fd76227bb1a602390fe57afd32efe281f2ea6b2e4d2545cb88d2308d72691c9a52b4ca25231a0107f25d117cc935397621c683bdc8f22e810340f2cbac4ceaa3468665261879f0074200743e0de5f3e58308b98b04b8c7148a4e004e667e832b0084b5f2bdc6fdc959f2fc28a8d31d9a9e78e5d5f9c0b119e5ff1f68f7c0daf0c0f16947cca5b7ced09601e2ebed282ef2bf8fe9a27ed27fc5bcda8aed6c71bee3e7751004472689bbf6d9d07952a242ff870d7c3f5e1ffc2c1f40fc9ab7579b392b554f3dc588c03ab957431fe5d02cbc711ad489fe: +61917a975cb7ec564c708a565388c57236a66b697dcd5a7f10bae671572ac7f0ecc0f0b99276e528f82b42f2efce8579f83e638c6acefd072828c04e434f55af:ecc0f0b99276e528f82b42f2efce8579f83e638c6acefd072828c04e434f55af:6e970e0b1c92a7f496a82d8ae80cfd0ccef1d2c799d41728f35ddcd603b421c2a5ab3b489e78f4b62297de437c5ad1a9683ff87fa28eb3cc38ce242af59419f9fd43fcaa54fc398992f8c8e31f2b33dcccd0ee11ba7b388e8d2a36ead067c6beced5890ab7d4a94f55dab92128a0f814c0e68971df57bd5078a7403175c7c2fdd4a52447153ab37456729aee33e5fc93db8e7f480309875ecf6db07ce7f3cac5de49e361275ca50b6b719f4b715b3e30863cbb3b7164ba9eb96ef3304b19ad4d74dce4bd25e77bbbbeff1ee7d1fb55b9c4f7fc4cd9bd55108afcf99c1a41cd6f6b1adb297b106c8ba24e3134f87dd8efe5cf85492291b94d6600958c28b9122fe6e01bd3e329e42d1926b89f7a8c40a49867e5aa3ad749bd98dae7d006b453609e7dae26364d9172be7283330121ed2b4027e0885118743a6ea0cb7dc27409a9b2820bcc242ea10a00937bf849201e0fb6199421f163e9794f2dd4b332014a09d3ee8071da787747f990f5179919027ddff7cab0f55e9afa8eccb16cc2dd3cbbead7ff7ec818c253393f748741f55407f7408ee33a42ae2d6ecb3fb600a71f30ab630606e553b43678e59854f3a2947bcf4ea0fcfedc314d8370d1266395fda3c9105e975952f60e3086bb82481513d6fe8adb4f95efb9a95b66d480d2bb171078cf40684ac69a789c7fb7fa425333d705db00066755df728de02df25bae34f1d7d49caffc51e9ba2b10b98fe4cd9d22b7764ed931edb5f0b554496e995391e0af0b8d1c7a8295a8d15a7c6556d29cb19e0855ca505ad01d2aa30928a84bc48959576d812d9b27b8e88879faa2806c0841360ecd0fe83f5b848fc12f658f1e7f40e561c2e78d3b0125210a92061c2db21ba660e8608ff5:6abb3e377b5c80b74f77219c1a9e096fba0eb68990817acff12dba7f61c77ccf595fb6608552003cead06ca1317c9cd51ac4724b29f40921fb928433768764016e970e0b1c92a7f496a82d8ae80cfd0ccef1d2c799d41728f35ddcd603b421c2a5ab3b489e78f4b62297de437c5ad1a9683ff87fa28eb3cc38ce242af59419f9fd43fcaa54fc398992f8c8e31f2b33dcccd0ee11ba7b388e8d2a36ead067c6beced5890ab7d4a94f55dab92128a0f814c0e68971df57bd5078a7403175c7c2fdd4a52447153ab37456729aee33e5fc93db8e7f480309875ecf6db07ce7f3cac5de49e361275ca50b6b719f4b715b3e30863cbb3b7164ba9eb96ef3304b19ad4d74dce4bd25e77bbbbeff1ee7d1fb55b9c4f7fc4cd9bd55108afcf99c1a41cd6f6b1adb297b106c8ba24e3134f87dd8efe5cf85492291b94d6600958c28b9122fe6e01bd3e329e42d1926b89f7a8c40a49867e5aa3ad749bd98dae7d006b453609e7dae26364d9172be7283330121ed2b4027e0885118743a6ea0cb7dc27409a9b2820bcc242ea10a00937bf849201e0fb6199421f163e9794f2dd4b332014a09d3ee8071da787747f990f5179919027ddff7cab0f55e9afa8eccb16cc2dd3cbbead7ff7ec818c253393f748741f55407f7408ee33a42ae2d6ecb3fb600a71f30ab630606e553b43678e59854f3a2947bcf4ea0fcfedc314d8370d1266395fda3c9105e975952f60e3086bb82481513d6fe8adb4f95efb9a95b66d480d2bb171078cf40684ac69a789c7fb7fa425333d705db00066755df728de02df25bae34f1d7d49caffc51e9ba2b10b98fe4cd9d22b7764ed931edb5f0b554496e995391e0af0b8d1c7a8295a8d15a7c6556d29cb19e0855ca505ad01d2aa30928a84bc48959576d812d9b27b8e88879faa2806c0841360ecd0fe83f5b848fc12f658f1e7f40e561c2e78d3b0125210a92061c2db21ba660e8608ff5: +7ba25f2797a2836f379d6bbcbe9abf4f2def5e52f72bd9e0b006571022fac2f36c2ed4e8c0124d5d0540796d3945d1de71aa6969e6abea0f1b0e6fc429c7046f:6c2ed4e8c0124d5d0540796d3945d1de71aa6969e6abea0f1b0e6fc429c7046f:171a3409878097b3b22b2c00660b46e542c2164c00bbee54554837940e70f03da9916a40f9bde8288f45e47bef7ffe4e557cd4474045e740fd959d984f4ec81da88d44a373c1eda0cfc6b08e351373d3b82ab0902df8063fd908e703e0cbec410ab5cdfeaae00188ce2ad42b8bf04f7daa5f0ee333a6f9311b4ad9810952d5d5a64b20f37e845415fc3cdd616febec50db296fb3f3bb7f6b366bbe52e4897a05617bf7c981a62edcbbbe5da4c39cafa869aa2b2734e6cfed90ed8be75949390ee44566892455b890cf568b945aabb758d3854be6539f3b86bf01d188e48cf2626a0d7d381703be6ed1290dfb947bc2e0f83dbc58703080d7f5b9ef19aef930908f68f0c80010a9401b303a9f6da805bb8a0ed0f39413eefedf919ffd8ea6391bf95d4229604e49457b8e23bec611484cc7f9832dd95bdc3ad177c050f4ab633dcdb3e691f5902873b38cb0720b9113357fe0cfb98a68cccb5d5f0809d59a375cf7b5a275d43c4c34ff68e448526e8e1aad44e20008a232afbcf532a42b50a025a1b2ee4e077eb0125a593d51a200ec20d872c05838ad36aaaeeccc3ed9ef41f6d122670217d5c08f6e13c172194589acc3c59f7ef790c7c85aa6d5eb69d4c89a72f5e7c9246985c1ac0c5d197f76a73e3774839d4aa2096aca190a30f4aac54057b64f358e0e06400c0df2f876412d34484c4344f4d7c866517d3efba4a90fa7144c9ba5db3361db5769403ec81626a511f93e30f8586eadfcafd9a36ecff8d24b42079ada8e579ac30851177bce9038b0e1300072d68efdd723f6355064843275815a66b9d73a1299aa59a1812f6452fb4115ea2b1f9ff4a99690596e3f2022d81ed874dd67e6189ca0e68b9304e993a95b66665e0d074c:f1f590a907ba980eb0d648ab4ded5f92faf7cb851d81d858a78fa6b77cbbe12f64d20df52771a7d5e539a152d731e1903d4211fdcfef9a48b46c8fd5394ca009171a3409878097b3b22b2c00660b46e542c2164c00bbee54554837940e70f03da9916a40f9bde8288f45e47bef7ffe4e557cd4474045e740fd959d984f4ec81da88d44a373c1eda0cfc6b08e351373d3b82ab0902df8063fd908e703e0cbec410ab5cdfeaae00188ce2ad42b8bf04f7daa5f0ee333a6f9311b4ad9810952d5d5a64b20f37e845415fc3cdd616febec50db296fb3f3bb7f6b366bbe52e4897a05617bf7c981a62edcbbbe5da4c39cafa869aa2b2734e6cfed90ed8be75949390ee44566892455b890cf568b945aabb758d3854be6539f3b86bf01d188e48cf2626a0d7d381703be6ed1290dfb947bc2e0f83dbc58703080d7f5b9ef19aef930908f68f0c80010a9401b303a9f6da805bb8a0ed0f39413eefedf919ffd8ea6391bf95d4229604e49457b8e23bec611484cc7f9832dd95bdc3ad177c050f4ab633dcdb3e691f5902873b38cb0720b9113357fe0cfb98a68cccb5d5f0809d59a375cf7b5a275d43c4c34ff68e448526e8e1aad44e20008a232afbcf532a42b50a025a1b2ee4e077eb0125a593d51a200ec20d872c05838ad36aaaeeccc3ed9ef41f6d122670217d5c08f6e13c172194589acc3c59f7ef790c7c85aa6d5eb69d4c89a72f5e7c9246985c1ac0c5d197f76a73e3774839d4aa2096aca190a30f4aac54057b64f358e0e06400c0df2f876412d34484c4344f4d7c866517d3efba4a90fa7144c9ba5db3361db5769403ec81626a511f93e30f8586eadfcafd9a36ecff8d24b42079ada8e579ac30851177bce9038b0e1300072d68efdd723f6355064843275815a66b9d73a1299aa59a1812f6452fb4115ea2b1f9ff4a99690596e3f2022d81ed874dd67e6189ca0e68b9304e993a95b66665e0d074c: +d1e1b22de5e04c9be4651dd73995a3666cb5352c65ac7b7051b366fe1ac0c31012fe56f1012d5c12f135ed5982f382ae5f1143bc90e8cb8c93051754551ee90a:12fe56f1012d5c12f135ed5982f382ae5f1143bc90e8cb8c93051754551ee90a:c7f218b5aa7aae1799625a56c4d7d7b02637e572f1411a6122f113791aa3c628e819602fb4f0335a6123013fa64e9fdc4e4ae497bd169c2fa77bc236129717f462886b410893fa7809cbfdc892223b40ee041ebd4ec7ddab55be6081a1646643a9120baa46289acba15b3b48af3b7adecd69f43eede79d9b1957e1d8c3129e0fa0579d3d395370461b0e1255c9caa94e4725601cb9d0e2d60244d15b64e1f7bc9015590ad0991f12f8267311206e9eb5d16add0ba5218fce5fffe1c9ce5ffe1f731132f4b12cacb02f97451710846b7f824f4fa9e08919266469789c00ce0d94d38fa8fec3f51f2f886e9db09b804470b19ec9e80663f155b4984d2bbd0b2ce99302e06c64444b696e3129fcef34c3dd00f7ab5beda747a3fc6339192b740f3569b67dbd6ffa39e271faa400d9616bff86ec49a659def2e7f5d451f2a2b35e662a6e7cc22f1e5cdcde8a59988135b7e76562743c1e6a099901b3ef97cbff23f209bd7088c2f03245279a1dc78dddc1bb0c1d35100357882126b328d3d94e0871b60be253fd1b6ecf03c1db731d9eed0edf2b2643230780a4d66e99179aad1b82402e55f6d785ebc80f8dd2fd2beb09f31035df62c17f428ed0b2d56508db31e6d2dd5fb69ebeeea3257070cf2fe67d42d28816a55dbae0b185db4421bbfdaefc79c08cdc1accf71642562ec70036da2bbafa4a891954c4ee4049b55c640e91930e39e3ef1018dc1647f26942c6dbdf4d56e41eb2c898c821fac17cc273e8e4aa5608a812cf4b82f96019c252d56e7805298ccbe8ce40b0bd0f933b884c0faf97a958b20408b8a5297cce5527b2ca212806e72a3264457a7fac8662b82ca233e1c7758dc6e4f1b9995863f25f747bcee43b639b1f8f2026d2d2:abaab4fa6aeb0a0b34ee0d613a0af049edb4cedbfe9d3bebe9c00618b115b9d1fa524ec3495e1330b0936181eabb14299faccc40eaa8cca57ed324b7a6420c0ec7f218b5aa7aae1799625a56c4d7d7b02637e572f1411a6122f113791aa3c628e819602fb4f0335a6123013fa64e9fdc4e4ae497bd169c2fa77bc236129717f462886b410893fa7809cbfdc892223b40ee041ebd4ec7ddab55be6081a1646643a9120baa46289acba15b3b48af3b7adecd69f43eede79d9b1957e1d8c3129e0fa0579d3d395370461b0e1255c9caa94e4725601cb9d0e2d60244d15b64e1f7bc9015590ad0991f12f8267311206e9eb5d16add0ba5218fce5fffe1c9ce5ffe1f731132f4b12cacb02f97451710846b7f824f4fa9e08919266469789c00ce0d94d38fa8fec3f51f2f886e9db09b804470b19ec9e80663f155b4984d2bbd0b2ce99302e06c64444b696e3129fcef34c3dd00f7ab5beda747a3fc6339192b740f3569b67dbd6ffa39e271faa400d9616bff86ec49a659def2e7f5d451f2a2b35e662a6e7cc22f1e5cdcde8a59988135b7e76562743c1e6a099901b3ef97cbff23f209bd7088c2f03245279a1dc78dddc1bb0c1d35100357882126b328d3d94e0871b60be253fd1b6ecf03c1db731d9eed0edf2b2643230780a4d66e99179aad1b82402e55f6d785ebc80f8dd2fd2beb09f31035df62c17f428ed0b2d56508db31e6d2dd5fb69ebeeea3257070cf2fe67d42d28816a55dbae0b185db4421bbfdaefc79c08cdc1accf71642562ec70036da2bbafa4a891954c4ee4049b55c640e91930e39e3ef1018dc1647f26942c6dbdf4d56e41eb2c898c821fac17cc273e8e4aa5608a812cf4b82f96019c252d56e7805298ccbe8ce40b0bd0f933b884c0faf97a958b20408b8a5297cce5527b2ca212806e72a3264457a7fac8662b82ca233e1c7758dc6e4f1b9995863f25f747bcee43b639b1f8f2026d2d2: +df294e477b1b91c5ac5b98c330d222d7cd2d53e7d0bc0ca403df4ec75327a2745f0bd22f2f1896d1563b4f6940c7df89efc258c0ff6c2fcd674daf4f59fcdb60:5f0bd22f2f1896d1563b4f6940c7df89efc258c0ff6c2fcd674daf4f59fcdb60:3e42d668409630cbb84812ac7ff1154f70fca8bdff3f1a040fa3af868aa1c4e91508b1aefdf5c3a8b4b077a4d162d2c05bd364fbbe8c5a08314c2e07dffbd6e8dd2e08a0dcc96ea92ddd4c97f79db9425a6c6b34c46043d09a68b7687236a918d21a561610a13ac5e446e0881bb26cc8e28aad1654f867ad82ae33f8f7a78a65be57699475516a1a8746843e93a1a294354624fac04d452ccfbe4fdd92a951aaa07d26676d5cb077a5000d439c124276c0dbcf86e7aa153cc24b5aff677c6badc261c289f4a4ae519b2e2fff312fbf0f5b4c4698f6aedd8fcb1d2348942de3fb73ba27f6db14c2f09180356e5fcae1adf65e22425f8c27f19e989483506e5df57a1b613a22e345038b3ea91c0f78ffff46383f38c72225358a34570d6f664a17454a151613f01cba777f62ec831875ec5e27d257f180b6366cb183107c40f50b01b2b9bf91b3b5549ed931a3537aa41689f72b257a6aa39cdc6fcedf143983be5bffe3ae2b29f82f882122d66a7925f5a710826c0dadb7e4fa4ec079ba2e76dada433f3077cb1ef74613fc5dbf8258b6da7c73c866372457ed500f97f9907e1fc26353c70ba3bd9c36151d46865d2c65986562485cf8421febbe777c73e6cd0026d66d35128b9f8f33264aeb56bd3e4b8d1f5266411ef3b23b76b36d4c9df3c512fd560c2be52ac523c19377ad2adc0e8c309cf5bbf72d9eb85d65a94847d497d8d102424fb84381666ecb1c35a3725d7d9e9284fdebb6b362aa6a9c6fb37aba87357f574c0e63b4497d498ffbb7d0692d784b4b18ce9f9150c146d3d18c382eda04938c69d0778f2902d5235a5652b97cef6d5f60da6bd7ed4ff97cd94d4939caca3b6baa3cfdac04cda95596f467cbc6cbcd9264167743eac1:9945ab73b58562b355dabc4e2b6be7e05f37f89571440ccc32c1a94737095b7866747d21007000a0f0e351114b88e0138b55df44fe72ebe9591410e707fa9d023e42d668409630cbb84812ac7ff1154f70fca8bdff3f1a040fa3af868aa1c4e91508b1aefdf5c3a8b4b077a4d162d2c05bd364fbbe8c5a08314c2e07dffbd6e8dd2e08a0dcc96ea92ddd4c97f79db9425a6c6b34c46043d09a68b7687236a918d21a561610a13ac5e446e0881bb26cc8e28aad1654f867ad82ae33f8f7a78a65be57699475516a1a8746843e93a1a294354624fac04d452ccfbe4fdd92a951aaa07d26676d5cb077a5000d439c124276c0dbcf86e7aa153cc24b5aff677c6badc261c289f4a4ae519b2e2fff312fbf0f5b4c4698f6aedd8fcb1d2348942de3fb73ba27f6db14c2f09180356e5fcae1adf65e22425f8c27f19e989483506e5df57a1b613a22e345038b3ea91c0f78ffff46383f38c72225358a34570d6f664a17454a151613f01cba777f62ec831875ec5e27d257f180b6366cb183107c40f50b01b2b9bf91b3b5549ed931a3537aa41689f72b257a6aa39cdc6fcedf143983be5bffe3ae2b29f82f882122d66a7925f5a710826c0dadb7e4fa4ec079ba2e76dada433f3077cb1ef74613fc5dbf8258b6da7c73c866372457ed500f97f9907e1fc26353c70ba3bd9c36151d46865d2c65986562485cf8421febbe777c73e6cd0026d66d35128b9f8f33264aeb56bd3e4b8d1f5266411ef3b23b76b36d4c9df3c512fd560c2be52ac523c19377ad2adc0e8c309cf5bbf72d9eb85d65a94847d497d8d102424fb84381666ecb1c35a3725d7d9e9284fdebb6b362aa6a9c6fb37aba87357f574c0e63b4497d498ffbb7d0692d784b4b18ce9f9150c146d3d18c382eda04938c69d0778f2902d5235a5652b97cef6d5f60da6bd7ed4ff97cd94d4939caca3b6baa3cfdac04cda95596f467cbc6cbcd9264167743eac1: +70c6859f08cf42b4bda9eb62979dffb7cb08eb3dabe93fe94b01384617cf6730401c9e2033e2259fb6383b3e8b9e17b3f2062746bbe648cf484516db0f2f1b06:401c9e2033e2259fb6383b3e8b9e17b3f2062746bbe648cf484516db0f2f1b06:dd0609ea159921395d11fb2da8ea4f747d7f74b58052e01cad40a271fa0bbeed91020f4f0c0846c4f07778a6aa768eb51712294e9e1f32a602b152514f5e6d39f9e08f7a7812bd900c10a91469e47e8a78e54cd4bd7cfededec171ef373f1c4f9bbc2c81402fb14ed0bfac8d043f117d6124521afae0916a510d568acfa3aa3301bc979ac28d551dbbea6ceac4c212aa8c8492b3613ae7395dd4125fc4c25d5b4d99230821d4b17ec2ee6be7d604195a2154333b973526580ca7ef9e30c6c1dd42ef2afe42b11b1aa49b9ccabaca17091eeb380ec5e34ad1e3827cc60dacf144286c7892590bd2671a8dc5f3a702c1de7cd3b42c1b150b09c3e58ef6943b45d89d41df361f1d5c25565591b6ac8deaa73676531f6e5abe5804b0097f8d45ea2939177333cacef12e4b71fe4936bafe00747a8930bcea55b8fd84a01f6df84e7acb931fc7c01ddfd63deec3ad3e69dfa2b73550583d5747eee96c5536368797e247f23f537d79079ab6da314102c7443d41960e3a3d8c359c4a4ec626fcc44e110ea744d417aa850db8ecdbfe340a962db0d8c57dc517be8b40d14de97b1e9e0426447fde0a04e50679c53ba1aa3cdc38c7ede6db6c054b1e9ce7deadaf93ebdd470791535f3ecfabf3416355f7a18a38afe6bfe507ef08c4373a4a69dee1fcb65b1631a0de1488649d0bb2679a9a45f67820b2a4a1e5a548072da7032d172555e788cc9860ebb3c0c359493751b0c2c950a7fcf4803c147f9340fc93d85f1efa57b39081b92d93473fd23516c4950ed4b29a2ed3a042ae3d92a1e52cb709636fc7272fd747208bee2b16d191e4c6deb27672aa34e43914cff2055ca4ee8ba3e1dc58a679c7f7dee2c1d53e28750970f57d85eab1c26b89bb73e0b1:0f03a4f15c339b4f7b88b4e21ad9e3d6bbf3effb7b678ffa500d47383b71a7454f62907b56f59f9b9af6d5b2a0fc1c737a64105195089899f57a2c9dba509e0add0609ea159921395d11fb2da8ea4f747d7f74b58052e01cad40a271fa0bbeed91020f4f0c0846c4f07778a6aa768eb51712294e9e1f32a602b152514f5e6d39f9e08f7a7812bd900c10a91469e47e8a78e54cd4bd7cfededec171ef373f1c4f9bbc2c81402fb14ed0bfac8d043f117d6124521afae0916a510d568acfa3aa3301bc979ac28d551dbbea6ceac4c212aa8c8492b3613ae7395dd4125fc4c25d5b4d99230821d4b17ec2ee6be7d604195a2154333b973526580ca7ef9e30c6c1dd42ef2afe42b11b1aa49b9ccabaca17091eeb380ec5e34ad1e3827cc60dacf144286c7892590bd2671a8dc5f3a702c1de7cd3b42c1b150b09c3e58ef6943b45d89d41df361f1d5c25565591b6ac8deaa73676531f6e5abe5804b0097f8d45ea2939177333cacef12e4b71fe4936bafe00747a8930bcea55b8fd84a01f6df84e7acb931fc7c01ddfd63deec3ad3e69dfa2b73550583d5747eee96c5536368797e247f23f537d79079ab6da314102c7443d41960e3a3d8c359c4a4ec626fcc44e110ea744d417aa850db8ecdbfe340a962db0d8c57dc517be8b40d14de97b1e9e0426447fde0a04e50679c53ba1aa3cdc38c7ede6db6c054b1e9ce7deadaf93ebdd470791535f3ecfabf3416355f7a18a38afe6bfe507ef08c4373a4a69dee1fcb65b1631a0de1488649d0bb2679a9a45f67820b2a4a1e5a548072da7032d172555e788cc9860ebb3c0c359493751b0c2c950a7fcf4803c147f9340fc93d85f1efa57b39081b92d93473fd23516c4950ed4b29a2ed3a042ae3d92a1e52cb709636fc7272fd747208bee2b16d191e4c6deb27672aa34e43914cff2055ca4ee8ba3e1dc58a679c7f7dee2c1d53e28750970f57d85eab1c26b89bb73e0b1: +c5962961815b57cd162403ce08e4105ddb8aae2d3f533fb49cc236b5ff504d6edbade72236ba12d4977ba46c364bb69a887ff402de91d47afa9b93c95be71e7e:dbade72236ba12d4977ba46c364bb69a887ff402de91d47afa9b93c95be71e7e:4ae4148d79ca9425592aa240bd153424a3bf4ae27395872ce5728ac7613596a77d5ce8565d8d6e1b5935b3906cafe1ff888ebc9815e04a624dfc4c6907b85f6f1a0dbddff62e9151220d474462cb9f13d89d3a93a00ba2b60f7e7ca63da17a6379d673551e790b5911727c906dc94f86d8277546c1564a45573a7743bb8a138cde87b3b2f28e5e245940a51e7c458cf8c5f0a70275962553e0d2390d171db44c2f7a5c9e9f93b90f7a5f54f191b0d875bad7e0beb980c2a3365cd7b9208724f4654418117e16ef7134e3e2794b6f9e80ecabeca3254e704c21b7ad30c5dee017ea2533fcd94251e55ae75a8cc6db6674b39c88ca42006043d6bd9b00ecf64ceafeeb402b1f22fd891f2d11c515c1aba6a2d4c0bd2181a48e43fd1c0af91f9b7b7d37f3dcd9e4c0a759748467d348a8b116df6a4eacf178aecccd3066e92dca45da7a3e319f3771eb3490022193c5b652f045687e1705f2e5691c134be4006353d7ecd0e918d5de0f3b87809fca4acfab94e1148ff7cf07f7cfd0c745dd2be01a24a5e069280698bc3f5400a6dcd08e44595c0388e44833768fc49104ee115bdcb02bfbda179d164ce969936629f2335601b56fe8f785cca3805f0403872c62f73c3ce80563d070e976d8ecc51124e2cace7ee18699047cb0f8fb8d9c59b8a60d12c08a09fce58fd92cd36db6a8e89d118cf88a92dc8a2600bd95f5a8e85db5cdbb249ca812ca209c7618051c4564a3a0e192b7e45992456c87d17412c11adead526ab8db21452f7471d17f2ebc90015450edf4f0a44fb2f4905f74d70275ccd89b93a650473c02a7da0cbc67915ceb7a1ea59fa8884472dc917ee9d246339c5926843ecf53fafdc56a695601a276c23a843e4d30f89c97c9eee6dfc7:8101baef004eb6f5ad4de0979ff36d3439b8212bdc928942e431915b3fd18bc2ad67b26f18941dcb16d2c29191421e779fed622fd9f582644eaadb3fe5c098034ae4148d79ca9425592aa240bd153424a3bf4ae27395872ce5728ac7613596a77d5ce8565d8d6e1b5935b3906cafe1ff888ebc9815e04a624dfc4c6907b85f6f1a0dbddff62e9151220d474462cb9f13d89d3a93a00ba2b60f7e7ca63da17a6379d673551e790b5911727c906dc94f86d8277546c1564a45573a7743bb8a138cde87b3b2f28e5e245940a51e7c458cf8c5f0a70275962553e0d2390d171db44c2f7a5c9e9f93b90f7a5f54f191b0d875bad7e0beb980c2a3365cd7b9208724f4654418117e16ef7134e3e2794b6f9e80ecabeca3254e704c21b7ad30c5dee017ea2533fcd94251e55ae75a8cc6db6674b39c88ca42006043d6bd9b00ecf64ceafeeb402b1f22fd891f2d11c515c1aba6a2d4c0bd2181a48e43fd1c0af91f9b7b7d37f3dcd9e4c0a759748467d348a8b116df6a4eacf178aecccd3066e92dca45da7a3e319f3771eb3490022193c5b652f045687e1705f2e5691c134be4006353d7ecd0e918d5de0f3b87809fca4acfab94e1148ff7cf07f7cfd0c745dd2be01a24a5e069280698bc3f5400a6dcd08e44595c0388e44833768fc49104ee115bdcb02bfbda179d164ce969936629f2335601b56fe8f785cca3805f0403872c62f73c3ce80563d070e976d8ecc51124e2cace7ee18699047cb0f8fb8d9c59b8a60d12c08a09fce58fd92cd36db6a8e89d118cf88a92dc8a2600bd95f5a8e85db5cdbb249ca812ca209c7618051c4564a3a0e192b7e45992456c87d17412c11adead526ab8db21452f7471d17f2ebc90015450edf4f0a44fb2f4905f74d70275ccd89b93a650473c02a7da0cbc67915ceb7a1ea59fa8884472dc917ee9d246339c5926843ecf53fafdc56a695601a276c23a843e4d30f89c97c9eee6dfc7: +dee6866c7874c127029e96e025bffd35fcfdf4dc36966c15ee6293368013d37908c94da351bb2bee72e6e196be748807583762c5296e05b1e529c47c6bbacec6:08c94da351bb2bee72e6e196be748807583762c5296e05b1e529c47c6bbacec6:f1aa1977f5311b538b940ae442a3abc89aaccdcd0a79380a24258d4a9f1ce638fc2f5ba2e53f8e1fa6176f178d9024a77894c28cad42d629c793d68a02be9411b527acadae7e5c3851babb45b5fece329e29034cd42571083727f35aecad7c9be5954ec64e8f6ecab7cc0590e54156a4e1a45303849f7897e72cf2fbcd84f56c72f941dbb0b09a32e6386fbe18a43bb9bd8b793e4b9edd532103eab54d627117d28139b64e60fb0b81d09001bb2404d925e265babdc69f96b135e9e6ab7febb1ed3075d6aa2abd2bbf9b65fa9b3b7191ef37b633605910ee88f66eada79f00f536d380b82f2f4b5985112de004a56603f4436d8ff300f42bf5acdc7a4bf1ea9d4196c480495bacb0067630fcc000b4f279dd3f30f353276092d152c3f43efdc041deaa0bc5aaaba7f8bbd85e69c13742d678dbb65360aaf7b548a044c0ec60a57af650bc31973f832f961265bc2318f80775afd51f55194c42423f7bf4e0052f98cb206913ffea4886ecd27a4179b13773f947502e181bf1a1f2c62c6f08c20359f06df2b18127043b1070d0194ef5e5bfd37d227984cfb10989f21c71ad0fe3b81227d3a71789455eda383c22f4d2fcc72579f465e066f3d38befc024efef6c2e329649ce434d627367a900d07fe6234235c84656eac5dd0d788cf4cb31871824d66ae4bc89edeba1b36701298453e8da1e69cfb868095c3be6ed2182da1cff4905afd20731ac1ed984164737903c7d8bb0ad16aecf2fae337404fe35664515d93b701e2f878664454c0decd1c6558adace3cdb227507a51606f0a54df8dfaa420205dd57c65242ff24a405ef85c92d602886932b35fabe9c3bcebfc6235639e873fc2dd084c52cd6a7413b831d1cc99931373aabd847620eb69bb0fa:b78ebd6d65b175d4bbd3d9a2082a0efe6e991cb2e403521eece00f418f2e956b66907880658b9e8e47699653d159132380d9ce1109af9c2757daf4cdf18c9c0af1aa1977f5311b538b940ae442a3abc89aaccdcd0a79380a24258d4a9f1ce638fc2f5ba2e53f8e1fa6176f178d9024a77894c28cad42d629c793d68a02be9411b527acadae7e5c3851babb45b5fece329e29034cd42571083727f35aecad7c9be5954ec64e8f6ecab7cc0590e54156a4e1a45303849f7897e72cf2fbcd84f56c72f941dbb0b09a32e6386fbe18a43bb9bd8b793e4b9edd532103eab54d627117d28139b64e60fb0b81d09001bb2404d925e265babdc69f96b135e9e6ab7febb1ed3075d6aa2abd2bbf9b65fa9b3b7191ef37b633605910ee88f66eada79f00f536d380b82f2f4b5985112de004a56603f4436d8ff300f42bf5acdc7a4bf1ea9d4196c480495bacb0067630fcc000b4f279dd3f30f353276092d152c3f43efdc041deaa0bc5aaaba7f8bbd85e69c13742d678dbb65360aaf7b548a044c0ec60a57af650bc31973f832f961265bc2318f80775afd51f55194c42423f7bf4e0052f98cb206913ffea4886ecd27a4179b13773f947502e181bf1a1f2c62c6f08c20359f06df2b18127043b1070d0194ef5e5bfd37d227984cfb10989f21c71ad0fe3b81227d3a71789455eda383c22f4d2fcc72579f465e066f3d38befc024efef6c2e329649ce434d627367a900d07fe6234235c84656eac5dd0d788cf4cb31871824d66ae4bc89edeba1b36701298453e8da1e69cfb868095c3be6ed2182da1cff4905afd20731ac1ed984164737903c7d8bb0ad16aecf2fae337404fe35664515d93b701e2f878664454c0decd1c6558adace3cdb227507a51606f0a54df8dfaa420205dd57c65242ff24a405ef85c92d602886932b35fabe9c3bcebfc6235639e873fc2dd084c52cd6a7413b831d1cc99931373aabd847620eb69bb0fa: +523623555995baaf2a27adcb1ebafaa802d23ef7abfa9775f2c9bfa07d64e0acd34deae6523e619dd1bfc8f3c4ca4b78b368c0f720035e144c3f2fc105d4ce21:d34deae6523e619dd1bfc8f3c4ca4b78b368c0f720035e144c3f2fc105d4ce21:0553e69ef211652d62bf281bfbdd37be22769d819746361c7d65ddd0fad677cc0438b301d1514578e0da58e55f729fa8e66ddeb7f973a818d24ed8fe027b8491179d07773fb5d2bb96aa85d6b3750454e50de91f9b88aee8aa68e6bb53edc66677b41e601a46ab4bb1e656e7fa5f0179933680a6ec9504275e7adf7a3248e63a0fc9c1ea5ae96cd0c65a89a77cec2b1fd8f4537e82c1c488a69a0ef64f58734d9e73478e1d1f123114ef66085e0ba319cb810b66af96d1308b1a2bd92ba2c265aa309ecd5557d402c3802cae8d7e95007fe610c2aa75fc66196c3fadfe997d6d5998e18d260e9da31da9218cbad103cbfc2c7547765d67e81f24ac83022ef51c6cc50864366a35f6b9b9af94e84caa9fd3d767c831f0967a61462fbcfcc803f12e3739039acd5dbe9366f05a33dbeaf360e2ddcbe5c443f80ef2ad62e03c1d5b70cdeab4a7dd41553064c8d152709deff82076b9071192376f51d4c2c71a84e89f2d9401320c2e459b3e243cca7c26fd098c264ac88ef638921d980b0ae9e512d372037d81adc48126d7c9e4b5afa57ec265d401b9653e928afb7dff9b48e295e470d6b52e88b39d0a40cb8eba249f8b13d81113db1d3e01ef75c722f269488e963cc8182704f8ca018e73dc0714e9a9fc79bc4363c28cb3984374f73b2aa8786e74e0159507a29883fe0ed1c600f525885f2f10ea006c39e59b925b765b1ede534257a1f40f2846584f069746b52f5600430a2863d7936095fbc22a6ada674d41b374e2b8b9a19fa712b5944533bb6d6ec43b89d4971b70205a6acd72a899da12618204db0c3e8267b845791693e0ae6a35f14da1f8f4dd174bce0318fb5a00f672ede42304cf04a62760577590f27e2dfa6e5e2795d66053b30af7f1bf:b1871729fec83aea0aaa472b700acd094813fb7d57b909e0eaaf21ee931847addedd2be8533d0c305cb9cfe5080e76c2808b6e51c9826290ddb7b94b6f7d580b0553e69ef211652d62bf281bfbdd37be22769d819746361c7d65ddd0fad677cc0438b301d1514578e0da58e55f729fa8e66ddeb7f973a818d24ed8fe027b8491179d07773fb5d2bb96aa85d6b3750454e50de91f9b88aee8aa68e6bb53edc66677b41e601a46ab4bb1e656e7fa5f0179933680a6ec9504275e7adf7a3248e63a0fc9c1ea5ae96cd0c65a89a77cec2b1fd8f4537e82c1c488a69a0ef64f58734d9e73478e1d1f123114ef66085e0ba319cb810b66af96d1308b1a2bd92ba2c265aa309ecd5557d402c3802cae8d7e95007fe610c2aa75fc66196c3fadfe997d6d5998e18d260e9da31da9218cbad103cbfc2c7547765d67e81f24ac83022ef51c6cc50864366a35f6b9b9af94e84caa9fd3d767c831f0967a61462fbcfcc803f12e3739039acd5dbe9366f05a33dbeaf360e2ddcbe5c443f80ef2ad62e03c1d5b70cdeab4a7dd41553064c8d152709deff82076b9071192376f51d4c2c71a84e89f2d9401320c2e459b3e243cca7c26fd098c264ac88ef638921d980b0ae9e512d372037d81adc48126d7c9e4b5afa57ec265d401b9653e928afb7dff9b48e295e470d6b52e88b39d0a40cb8eba249f8b13d81113db1d3e01ef75c722f269488e963cc8182704f8ca018e73dc0714e9a9fc79bc4363c28cb3984374f73b2aa8786e74e0159507a29883fe0ed1c600f525885f2f10ea006c39e59b925b765b1ede534257a1f40f2846584f069746b52f5600430a2863d7936095fbc22a6ada674d41b374e2b8b9a19fa712b5944533bb6d6ec43b89d4971b70205a6acd72a899da12618204db0c3e8267b845791693e0ae6a35f14da1f8f4dd174bce0318fb5a00f672ede42304cf04a62760577590f27e2dfa6e5e2795d66053b30af7f1bf: +575f8fb6c7465e92c250caeec1786224bc3eed729e463953a394c9849cba908f71bfa98f5bea790ff183d924e6655cea08d0aafb617f46d23a17a657f0a9b8b2:71bfa98f5bea790ff183d924e6655cea08d0aafb617f46d23a17a657f0a9b8b2:2cc372e25e53a138793064610e7ef25d9d7422e18e249675a72e79167f43baf452cbacb50182faf80798cc38597a44b307a536360b0bc1030f8397b94cbf147353dd2d671cb8cab219a2d7b9eb828e9635d2eab6eb08182cb03557783fd282aaf7b471747c84acf72debe4514524f8447bafccccec0a840feca9755ff9adb60301c2f25d4e3ba621df5ad72100c45d7a4b91559c725ab56bb29830e35f5a6faf87db23001f11ffba9c0c15440302065827a7d7aaaeab7b446abce333c0d30c3eae9c9da63eb1c0391d4269b12c45b660290611ac29c91dbd80dc6ed302a4d191f2923922f032ab1ac10ca7323b5241c5751c3c004ac39eb1267aa10017ed2dac6c934a250dda8cb06d5be9f563b827bf3c8d95fd7d2a7e7cc3acbee92538bd7ddfba3ab2dc9f791fac76cdf9cd6a6923534cf3e067108f6aa03e320d954085c218038a70cc768b972e49952b9fe171ee1be2a52cd469b8d36b84ee902cd9410db2777192e90070d2e7c56cb6a45f0a839c78c219203b6f1b33cb4504c6a7996427741e6874cf45c5fa5a38765a1ebf1796ce16e63ee509612c40f088cbceffa3affbc13b75a1b9c02c61a180a7e83b17884fe0ec0f2fe57c47e73a22f753eaf50fca655ebb19896b827a3474911c67853c58b4a78fd085a23239b9737ef8a7baff11ddce5f2cae0543f8b45d144ae6918b9a75293ec78ea618cd2cd08c971301cdfa0a9275c1bf441d4c1f878a2e733ce0a33b6ecdacbbf0bdb5c3643fa45a013979cd01396962897421129a88757c0d88b5ac7e44fdbd938ba4bc37de4929d53751fbb43d4e09a80e735244acada8e6749f77787f33763c7472df52934591591fb226c503c8be61a920a7d37eb1686b62216957844c43c484e58745775553:903b484cb24bc503cdced844614073256c6d5aa45f1f9f62c7f22e5649212bc1d6ef9eaa617b6b835a6de2beff2faac83d37a4a5fc5cc3b556f56edde2651f022cc372e25e53a138793064610e7ef25d9d7422e18e249675a72e79167f43baf452cbacb50182faf80798cc38597a44b307a536360b0bc1030f8397b94cbf147353dd2d671cb8cab219a2d7b9eb828e9635d2eab6eb08182cb03557783fd282aaf7b471747c84acf72debe4514524f8447bafccccec0a840feca9755ff9adb60301c2f25d4e3ba621df5ad72100c45d7a4b91559c725ab56bb29830e35f5a6faf87db23001f11ffba9c0c15440302065827a7d7aaaeab7b446abce333c0d30c3eae9c9da63eb1c0391d4269b12c45b660290611ac29c91dbd80dc6ed302a4d191f2923922f032ab1ac10ca7323b5241c5751c3c004ac39eb1267aa10017ed2dac6c934a250dda8cb06d5be9f563b827bf3c8d95fd7d2a7e7cc3acbee92538bd7ddfba3ab2dc9f791fac76cdf9cd6a6923534cf3e067108f6aa03e320d954085c218038a70cc768b972e49952b9fe171ee1be2a52cd469b8d36b84ee902cd9410db2777192e90070d2e7c56cb6a45f0a839c78c219203b6f1b33cb4504c6a7996427741e6874cf45c5fa5a38765a1ebf1796ce16e63ee509612c40f088cbceffa3affbc13b75a1b9c02c61a180a7e83b17884fe0ec0f2fe57c47e73a22f753eaf50fca655ebb19896b827a3474911c67853c58b4a78fd085a23239b9737ef8a7baff11ddce5f2cae0543f8b45d144ae6918b9a75293ec78ea618cd2cd08c971301cdfa0a9275c1bf441d4c1f878a2e733ce0a33b6ecdacbbf0bdb5c3643fa45a013979cd01396962897421129a88757c0d88b5ac7e44fdbd938ba4bc37de4929d53751fbb43d4e09a80e735244acada8e6749f77787f33763c7472df52934591591fb226c503c8be61a920a7d37eb1686b62216957844c43c484e58745775553: +03749ca20458a35a37a8d7a26f959f0d59f6dc9973fa363c1ff8ca4e638c2cd3eaeb94f406bde6a7cf8bde2adf3081f8375b87d9335d496c71d042cd2eaa166c:eaeb94f406bde6a7cf8bde2adf3081f8375b87d9335d496c71d042cd2eaa166c:eef5ceebd0445e9c9181aff9c6f2660128fcfb63691a42cfa443d6a649efc5fad8c20803763ee97d1dba08e63e08a2616da05077489f2fa2c56b7534f9402619251fdf9c320de7af109e2fd8b2565ce8a7524c9405ec0f8fcaa7149a6d210efde83b111cf82dc0835cf94f20cdb021b73bd262666555e6d62707b46ee42fa900b4f4f705de33d3dbdc68a88d1a4d0ae933566db6c6237ec8abe1024dac4b7f46d407be16594d9046c7312dda6614d9bcdb01fb8324fc62b8eeaf0abc23cd570e304fca08e88c735e5d31592409ceb583862e6b0a767729f7556fa2c053644d36c8337c0274e749202982fb4a171acac196c02b7f16a8da49071c8ab8076dd5d3abadfe3af82ca85da02dcc1c4a6f2e1930bee2009eee0d971e40dd12175c8d00694f0325a3b3133c0d0bd382a5194fb21422ce67c78a5a6e1537e3b97d5e204e5d195696390f77d19024c1bf6b5125a0cdbf7b9880036181c98e1ac2e5165bd496cf997451a1c12102e66946b1676abd4cbdd2c11673f4f2cd5f3c9a434d747fa05b40fbc72268b4eb2842e4741f51b7709b6accc47fcaf70d9c1c4c35867119d81cb3ff1f16081133f1659aed85f63bc901989e2617fcce153c2978d708fd02449ae4d538d122ddb8527c0a76a102eeff6edb65dba298d3c217f6551814eddeece1aef5f371a54f12bffd6b4961819a0f244ff0d7d8694c14422de9822c13179e4eeb81595079b9dd2ad1e7c39bd303cc44ae3f3634881577a266fd6bb7917812b999dc809dc09c3d7019dacd28e43013a2f9e4f94bb0bf7124ef091783f796397f6463bf1efb39cd46f3790a1d9b6a7c30f149b5e66c2937e39cb9744ddc66ab561bad4e6fa8534d69883822643d63d8bd7b181621a267e955e758d1792b44:78a3877e02bdfd015e7f86a327a48cc3a5230bbdb1243f1a8cf227f78ab5e7680de301a915dc11b336fb5f6566848b42500adb5d673969122ba8f0053cd3060beef5ceebd0445e9c9181aff9c6f2660128fcfb63691a42cfa443d6a649efc5fad8c20803763ee97d1dba08e63e08a2616da05077489f2fa2c56b7534f9402619251fdf9c320de7af109e2fd8b2565ce8a7524c9405ec0f8fcaa7149a6d210efde83b111cf82dc0835cf94f20cdb021b73bd262666555e6d62707b46ee42fa900b4f4f705de33d3dbdc68a88d1a4d0ae933566db6c6237ec8abe1024dac4b7f46d407be16594d9046c7312dda6614d9bcdb01fb8324fc62b8eeaf0abc23cd570e304fca08e88c735e5d31592409ceb583862e6b0a767729f7556fa2c053644d36c8337c0274e749202982fb4a171acac196c02b7f16a8da49071c8ab8076dd5d3abadfe3af82ca85da02dcc1c4a6f2e1930bee2009eee0d971e40dd12175c8d00694f0325a3b3133c0d0bd382a5194fb21422ce67c78a5a6e1537e3b97d5e204e5d195696390f77d19024c1bf6b5125a0cdbf7b9880036181c98e1ac2e5165bd496cf997451a1c12102e66946b1676abd4cbdd2c11673f4f2cd5f3c9a434d747fa05b40fbc72268b4eb2842e4741f51b7709b6accc47fcaf70d9c1c4c35867119d81cb3ff1f16081133f1659aed85f63bc901989e2617fcce153c2978d708fd02449ae4d538d122ddb8527c0a76a102eeff6edb65dba298d3c217f6551814eddeece1aef5f371a54f12bffd6b4961819a0f244ff0d7d8694c14422de9822c13179e4eeb81595079b9dd2ad1e7c39bd303cc44ae3f3634881577a266fd6bb7917812b999dc809dc09c3d7019dacd28e43013a2f9e4f94bb0bf7124ef091783f796397f6463bf1efb39cd46f3790a1d9b6a7c30f149b5e66c2937e39cb9744ddc66ab561bad4e6fa8534d69883822643d63d8bd7b181621a267e955e758d1792b44: +53cbd6f68cee27b9f7bc059b803b447949bbc9c5d5a38652d7789ca15420dea16116990b5331e2165f82743f01d8e7bd5d7088b30159833fa7b939cfb1cc04d7:6116990b5331e2165f82743f01d8e7bd5d7088b30159833fa7b939cfb1cc04d7:306f8e1df0a4ca78bd77e8e1191c94deaa82648355c2aecb7e82fc56d64c504619247e7cf8943328d11f3db4b1dc148e8ef6f6c3bc355969662a281a65576391242b7bd5a62f8fa7acb604e3a344ae1a9d732a254315f31a0464c1e6587462d29212c40e5ecf061e269aa0b90390ba41040721684bf2aa9582d83066221db60d0f7ae2f149a36e16952704fb1f3a982eac6b4583665c63e5a8996f24a566dd506a33d4ec8a02b2bd34b714c745000c0128a3c89d942506d12f4beb900e2903cdb34b35ca9b6d3ad9b350ac99f41db3acfe7fe55a28c0f006b844c9dc4853fd98535ada79416dca5fee5803a2d9f5d68e6b80539ff302e973f24e9bc88b7c4194117ddb9f932b32d5ec74868a13631ece68814b931421dc890249570341f4b423e86e8ee081b22702f649a6c7a0b7bdf5fb756202bd10b0bb2215c7d6597effd852f0b89abec15ea82257689df81e338254f93e81cbf061729d483eb5cf649805d78ed892dd0bd248ca1e252bea51847e1e82d39af58050dc4afbf9115a3a60493e8c0ba2e86e0898cd0d430891b9eb0a40f87431e25f41538a030f884fab36ad11165d267e8dd94dcb05b93a5ae77969430e1810134e157251b982df343dffae6123a99aa0562d5df72408f1a6e29c4059a5a8aaa4e621528fc63a9cbe1f4c0fef25fe3f8e18157774097a9d91020a9006b6c860ec1ee10d521d203a1f8bb82561296faad4b2203da53b207a459b29c18bc0649332b1807c13ca61acfaf90779febbc7f3242164797e6f572cb15a9be5887343455e26b910c8befee42aeb047f9abe6b3750dbd7de99202a0bb576ce1489e61c1f5d27c6792e63218edbfdb9b3dc515b4254d82c859e52ce6bd7ad296dd0e3709d4c466362f90265e99da7d0b701:d82504405ff16ba6443dc482367263a8e200360acaaa83fc4e4b72bd249f16103ec7e5a7e9ca17198f888eaca16b740cc3f5c3b7b617a34b9491c3ed76aab30d306f8e1df0a4ca78bd77e8e1191c94deaa82648355c2aecb7e82fc56d64c504619247e7cf8943328d11f3db4b1dc148e8ef6f6c3bc355969662a281a65576391242b7bd5a62f8fa7acb604e3a344ae1a9d732a254315f31a0464c1e6587462d29212c40e5ecf061e269aa0b90390ba41040721684bf2aa9582d83066221db60d0f7ae2f149a36e16952704fb1f3a982eac6b4583665c63e5a8996f24a566dd506a33d4ec8a02b2bd34b714c745000c0128a3c89d942506d12f4beb900e2903cdb34b35ca9b6d3ad9b350ac99f41db3acfe7fe55a28c0f006b844c9dc4853fd98535ada79416dca5fee5803a2d9f5d68e6b80539ff302e973f24e9bc88b7c4194117ddb9f932b32d5ec74868a13631ece68814b931421dc890249570341f4b423e86e8ee081b22702f649a6c7a0b7bdf5fb756202bd10b0bb2215c7d6597effd852f0b89abec15ea82257689df81e338254f93e81cbf061729d483eb5cf649805d78ed892dd0bd248ca1e252bea51847e1e82d39af58050dc4afbf9115a3a60493e8c0ba2e86e0898cd0d430891b9eb0a40f87431e25f41538a030f884fab36ad11165d267e8dd94dcb05b93a5ae77969430e1810134e157251b982df343dffae6123a99aa0562d5df72408f1a6e29c4059a5a8aaa4e621528fc63a9cbe1f4c0fef25fe3f8e18157774097a9d91020a9006b6c860ec1ee10d521d203a1f8bb82561296faad4b2203da53b207a459b29c18bc0649332b1807c13ca61acfaf90779febbc7f3242164797e6f572cb15a9be5887343455e26b910c8befee42aeb047f9abe6b3750dbd7de99202a0bb576ce1489e61c1f5d27c6792e63218edbfdb9b3dc515b4254d82c859e52ce6bd7ad296dd0e3709d4c466362f90265e99da7d0b701: +8b6574f6d7396981e223a4837bc339c3fd659419845a2121bf85be2e695d860de3811aca70634f5a9ce4b592a17bb5cfda53442422e203cda9504c9d65b263e8:e3811aca70634f5a9ce4b592a17bb5cfda53442422e203cda9504c9d65b263e8:a48aacc0495fa0f1259b27865d3d75dc52c2c828ea8c4c2ad78577072fef7270f6a4d582bb7b962f4c3fd149a60a06bc8efd2970ef03148ddf6198b9b695a69fadb5340951cb75398ac51a4fd55430378cd5da8885210bfd2146f95c627632fe8be06de01a7c27b89deefd67efc69c9b5c62b38108f776229143dae660c10cbea3cd4f7ee53dc3692ed01177e4a6f7e424b5666f7f495f2a65602c7d08c5d572234a567cb6c38afd79cab5c4036d62637aefab5588769a448ab4c65e24554bd4158050e09eb58f99ab40777b0356709b7c025ae5ae5422acf87444931ae4d9a8b3d94476881128ba1eb7328fafc75f6b9dacc96d3b6487ddef7c59262dcada426aacb13922935411566235e058372622d885bd0cc04958dcfb17e08fcd7f147e20156c8e26af85530f5511a68db43dafc4e6a23f667df3743eedd71a3f07f76f94d1688afc8463bfa5a439ae311469948e7447064f0b0506f36719c13466a1b98776d967ec58208ba674037303dfc6190da783ff27303b86b5fc3211f01c915e83a6ad0121447911cbe1cf696f618f60236643f2e94e155db657182944c1a43bdc7bd5eaf3481fe1284092cb3789a892bd79a111fd410143cf91ae332860b1d29aa041d177b50d6cc2b9660d328c0f230a3515e6a0d688709c0cd347ad2ff32d61d1e1e9ba76f81e873a6c420f1707f3841db5196cb53f506f0006352c7c44c080f3096801a57a49cfe84205bdd7a9801f843cf26b9558a2db788ef1b237915d587b9ba9779890f61fdc91e03e4f4cdbefe417cc22d522a86adddb53f3747450ab62b576565db32e0cd44276547d9a16653c279659dd4d17ec04827c533e33390fe94f793509256db67531736ab3fcee2a301ac3f0a24d3b108d7e75c32a5aba36d6:2fd0905475a2cec3e76f9909b8afd83beb8daefa77afcda34cb4f11728ef15fc9c1d7f6f6afffc28f3874f913e17980f0e8e3d5ad23951df2b32efaf6219ce0da48aacc0495fa0f1259b27865d3d75dc52c2c828ea8c4c2ad78577072fef7270f6a4d582bb7b962f4c3fd149a60a06bc8efd2970ef03148ddf6198b9b695a69fadb5340951cb75398ac51a4fd55430378cd5da8885210bfd2146f95c627632fe8be06de01a7c27b89deefd67efc69c9b5c62b38108f776229143dae660c10cbea3cd4f7ee53dc3692ed01177e4a6f7e424b5666f7f495f2a65602c7d08c5d572234a567cb6c38afd79cab5c4036d62637aefab5588769a448ab4c65e24554bd4158050e09eb58f99ab40777b0356709b7c025ae5ae5422acf87444931ae4d9a8b3d94476881128ba1eb7328fafc75f6b9dacc96d3b6487ddef7c59262dcada426aacb13922935411566235e058372622d885bd0cc04958dcfb17e08fcd7f147e20156c8e26af85530f5511a68db43dafc4e6a23f667df3743eedd71a3f07f76f94d1688afc8463bfa5a439ae311469948e7447064f0b0506f36719c13466a1b98776d967ec58208ba674037303dfc6190da783ff27303b86b5fc3211f01c915e83a6ad0121447911cbe1cf696f618f60236643f2e94e155db657182944c1a43bdc7bd5eaf3481fe1284092cb3789a892bd79a111fd410143cf91ae332860b1d29aa041d177b50d6cc2b9660d328c0f230a3515e6a0d688709c0cd347ad2ff32d61d1e1e9ba76f81e873a6c420f1707f3841db5196cb53f506f0006352c7c44c080f3096801a57a49cfe84205bdd7a9801f843cf26b9558a2db788ef1b237915d587b9ba9779890f61fdc91e03e4f4cdbefe417cc22d522a86adddb53f3747450ab62b576565db32e0cd44276547d9a16653c279659dd4d17ec04827c533e33390fe94f793509256db67531736ab3fcee2a301ac3f0a24d3b108d7e75c32a5aba36d6: +29b2881b8caadb336e7880c510b80085f4b1221860b301eb4525650752a6d2890c5c44ed29d21bcadee21cbde61a9cdb6d5936009ba2f5b2e777c924ddfb6751:0c5c44ed29d21bcadee21cbde61a9cdb6d5936009ba2f5b2e777c924ddfb6751:1974a2e2b47949f467a931d1d9dd5ce116e9f5030ad09a8cc728d1aeb148bbf9acf59874da80e708d53c668f2f14d7522071e909808427b2ab5a05f8b94f21505cd26abc53458978c784d479ea6dab105c4f7984a0fb9790e50624f4734b551905aa5ffa60184cd201cf2b26c9795da6e7e08d6a0bc7722400fef94fc21038be89d34bcd14c427b85b6866737196152d4eeb66d05b245ae84bdc7787c14a8bec2eea5360f042433d70794467d47393b93757f331cf2b53c660d71c29582aeea79b12527a28b0c5e110df6f854eead9a2b00d42542ca8276bb8bf988baab8565996fee50cf31b2459c4c50ab475265e83e2285d43fe1f752a55b2dbc49fca04a810f0413bf6bd81b79ac64ee1f89b97bd7d26d62512273e24a6bab2d5f7d2226baaab7b111209bb03733d8a60dfa31a516f4a8c7699d8285c1065159a6c7331c1defb47a30ef5858c50b7d045124a09813d1cfda5c9cc3bb5bfae73c984197f8f857f186c41ab87fb7962b631f4d007cfbee221fc6572784a551194c19777b08e6b596757e7cba7a0e27fe453f90dc59cc08c6472431c020e8dd0917590e79c1f207383afb39076ad24da8ee52486739453a2590e51bfc89b13c2033cfa5f8903cbe9961a8598ba556232869dfab4d56edf4f05e8b77d05871895e63b5351f76cb2d2c8385c109d7306192a25446e4d62dc7d624f0c6673986be0628b2c2d73eb941d35a3433090f59b28a5979d56dbc9fd6973f63647642cd903b0cf7a6acd330d87e2292710de99e0c179ca78929ccaecfaedbf2742414f176b6090c0d59a9db781c9967e28fa4e77d2a082e42f52169167e92d4fdd82e2cc05dd9184c7dfee490a237fdad4dfebc01868e0a4353a2954d090928461821a7a848d1b60817fc3bdefa1:99e996e85a494f1980cb07de9ca6165e7de104d39fe3c3226735c5daa569516fcaf1b6e4dfad0d389b6db0ec8a8f20dd2c602656b5e761c8f3a65583821519091974a2e2b47949f467a931d1d9dd5ce116e9f5030ad09a8cc728d1aeb148bbf9acf59874da80e708d53c668f2f14d7522071e909808427b2ab5a05f8b94f21505cd26abc53458978c784d479ea6dab105c4f7984a0fb9790e50624f4734b551905aa5ffa60184cd201cf2b26c9795da6e7e08d6a0bc7722400fef94fc21038be89d34bcd14c427b85b6866737196152d4eeb66d05b245ae84bdc7787c14a8bec2eea5360f042433d70794467d47393b93757f331cf2b53c660d71c29582aeea79b12527a28b0c5e110df6f854eead9a2b00d42542ca8276bb8bf988baab8565996fee50cf31b2459c4c50ab475265e83e2285d43fe1f752a55b2dbc49fca04a810f0413bf6bd81b79ac64ee1f89b97bd7d26d62512273e24a6bab2d5f7d2226baaab7b111209bb03733d8a60dfa31a516f4a8c7699d8285c1065159a6c7331c1defb47a30ef5858c50b7d045124a09813d1cfda5c9cc3bb5bfae73c984197f8f857f186c41ab87fb7962b631f4d007cfbee221fc6572784a551194c19777b08e6b596757e7cba7a0e27fe453f90dc59cc08c6472431c020e8dd0917590e79c1f207383afb39076ad24da8ee52486739453a2590e51bfc89b13c2033cfa5f8903cbe9961a8598ba556232869dfab4d56edf4f05e8b77d05871895e63b5351f76cb2d2c8385c109d7306192a25446e4d62dc7d624f0c6673986be0628b2c2d73eb941d35a3433090f59b28a5979d56dbc9fd6973f63647642cd903b0cf7a6acd330d87e2292710de99e0c179ca78929ccaecfaedbf2742414f176b6090c0d59a9db781c9967e28fa4e77d2a082e42f52169167e92d4fdd82e2cc05dd9184c7dfee490a237fdad4dfebc01868e0a4353a2954d090928461821a7a848d1b60817fc3bdefa1: +42afe89dac83e7d38996c0dbce0c9874c00927babd77ca8ceac34e564474282ba4c5f5e3803f0a03d5c1c906caec9cc6d2851407f1ca29f72a45f233e6656244:a4c5f5e3803f0a03d5c1c906caec9cc6d2851407f1ca29f72a45f233e6656244:e710a163ad2885aeb7658eb374f118b76842ec36ef3b010c3c6b9559e8b160c2628ded0b8511eb4907180da4b621e9aa4a322288888a1c09130f69f890597a9293e74f9289bdaa5c91b6fd24aa044ab9fcb3402f7abc48d2ab7b3880a048daa448645ad2ecb55b3caee2d68a8bedb5d1865d5e211de39b0eaf22e5daf10f7168203aa15b85aa47bbd3cc4169cbc1fe80b4700b625871edabcd4fe74a3e965569ce245cfcde4209cc8abcd6797d44185b4f96c0181bbd27008783e9358a5394fe3a34a06871d379da35b20bb57eef9e5524ee7912a6f41b4a1f684c3919cfcdc00f4580baf9e09d316cefa0f465dca5d8eec514e95e5a57bbcd27e41f8119b264ae14a319d8c3859babf1f4a6b6b77e442c861d6ee28ad12b82362e90db0c3672b0e0d9ff58146fd159aa8fa99dc755fc85b90cf9419279c0624b93e75eda0ef7c09695ae93bd7282419377b76ca8bdc0521cfee6f6d729c3adff894687b177ef19529a6bdace70b685c6d7a5d74a08e2a9e724035975c80d18cb369470de7299cbd6b0a27c9232c7eabac86d5093a65ffe0b40d40befe80b68cd9dce1ea1e657e45e9c499d0b690f74455fb47096ed8c18d1517f90442901a6c410b7f6415f20ae48c58ade8d675b6c058df16ae7698fceae95aa771b4cd88a0b3f22c51f98c71c1eb46b264bf97a300ecb1fd26226ad8e87a058cf3e708e260f566b685314045133f4a5e8fbc34561b9a0f1ff9339f55231076b736b6e11524319a272bd4453a0af1493daa09167e84643d207a02fee98fb223b01a99aa5cef2b7001e470f6f94a5dc208edfc0cb8cf3114a919600f061172f0efe039036bf4dddbfd0d45f91443bf26f8e15ed7db8e55f086a4a4583f4bda0f556284dcf71292fe70fcaa8259b9faff3:4fba2d6cc1b7193d3562f8c8bfe6905c829db265a5427c5c265714785b83f69514c5e30e28b56684c82dae2637581bf3f4ef271420bc7e6010613a38fa101a0de710a163ad2885aeb7658eb374f118b76842ec36ef3b010c3c6b9559e8b160c2628ded0b8511eb4907180da4b621e9aa4a322288888a1c09130f69f890597a9293e74f9289bdaa5c91b6fd24aa044ab9fcb3402f7abc48d2ab7b3880a048daa448645ad2ecb55b3caee2d68a8bedb5d1865d5e211de39b0eaf22e5daf10f7168203aa15b85aa47bbd3cc4169cbc1fe80b4700b625871edabcd4fe74a3e965569ce245cfcde4209cc8abcd6797d44185b4f96c0181bbd27008783e9358a5394fe3a34a06871d379da35b20bb57eef9e5524ee7912a6f41b4a1f684c3919cfcdc00f4580baf9e09d316cefa0f465dca5d8eec514e95e5a57bbcd27e41f8119b264ae14a319d8c3859babf1f4a6b6b77e442c861d6ee28ad12b82362e90db0c3672b0e0d9ff58146fd159aa8fa99dc755fc85b90cf9419279c0624b93e75eda0ef7c09695ae93bd7282419377b76ca8bdc0521cfee6f6d729c3adff894687b177ef19529a6bdace70b685c6d7a5d74a08e2a9e724035975c80d18cb369470de7299cbd6b0a27c9232c7eabac86d5093a65ffe0b40d40befe80b68cd9dce1ea1e657e45e9c499d0b690f74455fb47096ed8c18d1517f90442901a6c410b7f6415f20ae48c58ade8d675b6c058df16ae7698fceae95aa771b4cd88a0b3f22c51f98c71c1eb46b264bf97a300ecb1fd26226ad8e87a058cf3e708e260f566b685314045133f4a5e8fbc34561b9a0f1ff9339f55231076b736b6e11524319a272bd4453a0af1493daa09167e84643d207a02fee98fb223b01a99aa5cef2b7001e470f6f94a5dc208edfc0cb8cf3114a919600f061172f0efe039036bf4dddbfd0d45f91443bf26f8e15ed7db8e55f086a4a4583f4bda0f556284dcf71292fe70fcaa8259b9faff3: +10f009aa887d91ced809afe192d78e4799d9037762f4a9d3a429fde0f39f7b7acf5116b921212e9b78829a0263463691c6fbccdc0c118be141c96f8c88053dd3:cf5116b921212e9b78829a0263463691c6fbccdc0c118be141c96f8c88053dd3:2edf14d6cd56896eeaa770211c4984bed80eca8d6534d5d510884f55f11f99ffa9f89b586ffe7b1ec7eaab6a9dc1a24a3ee3c7a6ab44ade9917883264ede2f1361be7d7a3817f29dec9581c319f18f95d5be26d9118be678340037a68abfc5efbb9a3f3f3878aae3721ffef5bb6a26c7b1a3a56d2bda6c6e860eb41fd8d8371174d91c74c5eb67c3855c630d641d2e571a9a51c6402cfe1842cef38980cb8d0a64bcc89be3189e6811f47e8f4d0063a5b1601f44fda20c1c4c2fc49cbe27a4137dc4638c2ad2d0a5474747229c568e3805431fa36eeba785f7b97844b5e319fa6a09cc5ae8403474bb91dd896c1ec2bac73d2e505efc62bd502b5ceb08d16e832ec5dc4f98b51b9d0738b9fb28f3abe8966bf22375a0b22c471a9e58e3fd700de15c5296373c1bc9d4640eb7816e1dc9c8ce8619a81183009ec974871e8f0a9772ede0a638b3574bf75d8f55987f3cfa6fec68970bfe00b23b59fb5bf4996ea5d7704fcf2effcc0fd7f3d8e6056008097f26caffd5415a282a276a9b2645e5cab12968872eb052f4d7c10cc7c21d5161818bb44cc856b0de769d559c55df64ad9adc16c0ac65838f660da81386b70b93525ec2f40f6f63f8ea5d4830b9646c46183bb4e6f27047bda2a546bd34bd4db5fb88fd8ab7c75f652e15d5aaa6b46a8acf6e448bf2dd64dee3c105647c7f83ad200d8097c444a158d85a54f0e5dbb12b43de943af1a81856ac969f52a0bd454381bd265041a2691d1a4a0d819fa79092c8803521fa53689ab852f1fbabe00c94b7f682d121cff54391322529c8d5ad7bbb98eafe300ab922f1c89240a1e633cf56a7b02f74a29214e569a057bd585e404d7cd5352041456e6cf90c15342e025670f4fccdf98783b6853214cac3fa808a66c27b653c:c37bb7b73b1105be086ff3076972077262df4d7332f608c7b2b9d978d474cbbc271046080035f396ee36479b7a6711c68e2561c741c0ec5fc9eca1734e811f042edf14d6cd56896eeaa770211c4984bed80eca8d6534d5d510884f55f11f99ffa9f89b586ffe7b1ec7eaab6a9dc1a24a3ee3c7a6ab44ade9917883264ede2f1361be7d7a3817f29dec9581c319f18f95d5be26d9118be678340037a68abfc5efbb9a3f3f3878aae3721ffef5bb6a26c7b1a3a56d2bda6c6e860eb41fd8d8371174d91c74c5eb67c3855c630d641d2e571a9a51c6402cfe1842cef38980cb8d0a64bcc89be3189e6811f47e8f4d0063a5b1601f44fda20c1c4c2fc49cbe27a4137dc4638c2ad2d0a5474747229c568e3805431fa36eeba785f7b97844b5e319fa6a09cc5ae8403474bb91dd896c1ec2bac73d2e505efc62bd502b5ceb08d16e832ec5dc4f98b51b9d0738b9fb28f3abe8966bf22375a0b22c471a9e58e3fd700de15c5296373c1bc9d4640eb7816e1dc9c8ce8619a81183009ec974871e8f0a9772ede0a638b3574bf75d8f55987f3cfa6fec68970bfe00b23b59fb5bf4996ea5d7704fcf2effcc0fd7f3d8e6056008097f26caffd5415a282a276a9b2645e5cab12968872eb052f4d7c10cc7c21d5161818bb44cc856b0de769d559c55df64ad9adc16c0ac65838f660da81386b70b93525ec2f40f6f63f8ea5d4830b9646c46183bb4e6f27047bda2a546bd34bd4db5fb88fd8ab7c75f652e15d5aaa6b46a8acf6e448bf2dd64dee3c105647c7f83ad200d8097c444a158d85a54f0e5dbb12b43de943af1a81856ac969f52a0bd454381bd265041a2691d1a4a0d819fa79092c8803521fa53689ab852f1fbabe00c94b7f682d121cff54391322529c8d5ad7bbb98eafe300ab922f1c89240a1e633cf56a7b02f74a29214e569a057bd585e404d7cd5352041456e6cf90c15342e025670f4fccdf98783b6853214cac3fa808a66c27b653c: +4578c65a7ca48f2774050a7b0ce7a4fd5ad4e696b2b8af2396164a1c7e1b7bd715bf9dbd3b8173e6f03dcfd575d909845f038eaa09c5d908fef908a97458b3ef:15bf9dbd3b8173e6f03dcfd575d909845f038eaa09c5d908fef908a97458b3ef:506f32b96814243e4dd8870a8fd60ddef09bb8c563151070d9bcb2b160a3eabd71a044d71ec93fba95288ed6fe1a7b921651604307d65a45ec5d3f2631ace40e58d53c72e526886e16972f6e0db94d57b55634fd39d55e9bb7f212afab00f7746409267e8d565ff5c2257333c3d04152174fe12de6a57bea057dc219e2fba5f191ed8141c018969de19472d6aaf763f19ec554702bb3dcbe13ca9b23b2418c99e71838a88cf454728cf9208a16c84ea39829b4ba9b4c77e176112bfe1bf35f95c4028c7db80b36faa29d2b89e9e862f31000065f139b3da77d9d868530574b7e391ed97b34f878164f6b8d87b406c7dc7860a5175f920e5a62dc1fc82ed8452543b107360d35d2b4c4239eab466d32bfda34f51037a6fae76f6d8b83e8f7f489dd4c1b49c38f53576e62172c17dee3665fde8cbf015af9665b0f1da2fb77b134f04be271e402f31537c2fc05c2f9b6fc3ffe47de3369133867c69d10e7f537bae4567d468e0f2ed806fe335f939c75994f363ce3b70daa7d5bd2317c833851fd8cc97251ec419023d9d0174d84d5609a6918a1740eb1e309bd127366deb9c5ab12992e9902e015fe58d6adbf52d22a760acd63e1edd8f138e9fb0137188601e1978e7d04fb2ada2b2aee12f49f2836c6842d88cf48c866e3d33fcd269c275c89c25e3669ca90de7b67a7e7a382cb7efa47e9c2bf76571c79a25085ef020487152f06bfa133015a1b8f1c0f6a9f0eae1ba62bf104f1c16ac14e1e96c4ebdf061e0cc7101d38da7e9e0994daf0f322aa3cfef91b616c2d000689ab18ed45268dcd275094f656ba3cf515261024741f7444ab7fc4decce16756032a1be270ff0b0317542ba02662260a376fc912cbb029cac54515f5a551364f6a99ffad0b9cbcd0e693b7a521cb:a1c242b45e94fd180f054c7101e55b396568f483db6f0dfc4168b69b59d385814c19eb3075237d1fbb1feebbfea50c56813c8c39c22752e02db7e57f3e3fbf0d506f32b96814243e4dd8870a8fd60ddef09bb8c563151070d9bcb2b160a3eabd71a044d71ec93fba95288ed6fe1a7b921651604307d65a45ec5d3f2631ace40e58d53c72e526886e16972f6e0db94d57b55634fd39d55e9bb7f212afab00f7746409267e8d565ff5c2257333c3d04152174fe12de6a57bea057dc219e2fba5f191ed8141c018969de19472d6aaf763f19ec554702bb3dcbe13ca9b23b2418c99e71838a88cf454728cf9208a16c84ea39829b4ba9b4c77e176112bfe1bf35f95c4028c7db80b36faa29d2b89e9e862f31000065f139b3da77d9d868530574b7e391ed97b34f878164f6b8d87b406c7dc7860a5175f920e5a62dc1fc82ed8452543b107360d35d2b4c4239eab466d32bfda34f51037a6fae76f6d8b83e8f7f489dd4c1b49c38f53576e62172c17dee3665fde8cbf015af9665b0f1da2fb77b134f04be271e402f31537c2fc05c2f9b6fc3ffe47de3369133867c69d10e7f537bae4567d468e0f2ed806fe335f939c75994f363ce3b70daa7d5bd2317c833851fd8cc97251ec419023d9d0174d84d5609a6918a1740eb1e309bd127366deb9c5ab12992e9902e015fe58d6adbf52d22a760acd63e1edd8f138e9fb0137188601e1978e7d04fb2ada2b2aee12f49f2836c6842d88cf48c866e3d33fcd269c275c89c25e3669ca90de7b67a7e7a382cb7efa47e9c2bf76571c79a25085ef020487152f06bfa133015a1b8f1c0f6a9f0eae1ba62bf104f1c16ac14e1e96c4ebdf061e0cc7101d38da7e9e0994daf0f322aa3cfef91b616c2d000689ab18ed45268dcd275094f656ba3cf515261024741f7444ab7fc4decce16756032a1be270ff0b0317542ba02662260a376fc912cbb029cac54515f5a551364f6a99ffad0b9cbcd0e693b7a521cb: +c21e70c46ede66e68a8873bbc64ba51209303a0ac4fc49b1d83e8193ad46c0379fbf80a42505d2c952f89f4558c3e6d187a7bc1ef446b2e3732343c13b33d200:9fbf80a42505d2c952f89f4558c3e6d187a7bc1ef446b2e3732343c13b33d200:f55aa570ce4fc95f73f51720d254e4695fcdc81aaa040130c7687f039b8ba59ed857ceb29c121025a857feacb4a01f38e01178310ae6e35c998ebf89dd79057b4afc6db340601c81703c87a8c40e5cebb0441df78a6de13a447cb016c65e741bb7df304d83056b72c682c731fac0a0c70b7811ca14a50154613099c2c437521c404b6361de3621f8ea56b08ebfdb07b4f2bb8ba2ecc164336da8efc942766ef0c74dfd3b49e087e9a27ae54a7a2b98281b9af93dc11aa2f09224ab5a730f0218f4a6e1ea4885a77fbd93a1c58277d9e01be73a25cda918fc27dddb453a5da6902ad02ba05775c67e07bea4df86913466744365c1326e0ab5e1254c17967447d591ba5ed1b63a42543b87fed41459a089bceaff219802a87a872a763e692333ce1cc7397825084b2b831e93d80d6737f32980f2f3ae82c62190fe3fa700c5b7329d6d50042bdf831f37548fcc80b11f57cf20f67a3bb651a7beffcc48b70d17eb60f7259cc53bf7ff6080eb2bd0923b0483aa3065a8955f01d23ba80951e0aefd2a9372191572bc52916aa22a2aec393767fafd086839e236fe0460ce6d639c7ce69fe7f9d3aad2130573443570443be6bab93a06a54b8ac29bf33ff9949bc92158e6924b6b68ecda5f6f3aaf42b3d22df6d5e67d5cb3ab71eb8ee0b0e66732e1daca6cd60d9aa74305fcd570076d228d446d5ee542b10488bf8aa988f451faebe74ab669d604d9ddb15106620ea02e8db38ce639b5747812bb9048ee8bf72b1a951a05dffac95417cb43b06dce61ee3da6f2832ee83b2e7288ddd62eeb5893f7f2f6c8090d99e336c9f9069e1815985841bdd505b5f83d895e879593dadee72ceb9765699bf80bd06a5c55331b2545527d0c7caece96584ce3ec7fe02260f20b8a1c0635763ff4:0ae343bb84e3a299078e2434ba220022f3160f968ac04482bf8cad13b423f2670f01fb5f7b32c597520f84607e0f79c075fa7078e6e69d3cec319265d466080bf55aa570ce4fc95f73f51720d254e4695fcdc81aaa040130c7687f039b8ba59ed857ceb29c121025a857feacb4a01f38e01178310ae6e35c998ebf89dd79057b4afc6db340601c81703c87a8c40e5cebb0441df78a6de13a447cb016c65e741bb7df304d83056b72c682c731fac0a0c70b7811ca14a50154613099c2c437521c404b6361de3621f8ea56b08ebfdb07b4f2bb8ba2ecc164336da8efc942766ef0c74dfd3b49e087e9a27ae54a7a2b98281b9af93dc11aa2f09224ab5a730f0218f4a6e1ea4885a77fbd93a1c58277d9e01be73a25cda918fc27dddb453a5da6902ad02ba05775c67e07bea4df86913466744365c1326e0ab5e1254c17967447d591ba5ed1b63a42543b87fed41459a089bceaff219802a87a872a763e692333ce1cc7397825084b2b831e93d80d6737f32980f2f3ae82c62190fe3fa700c5b7329d6d50042bdf831f37548fcc80b11f57cf20f67a3bb651a7beffcc48b70d17eb60f7259cc53bf7ff6080eb2bd0923b0483aa3065a8955f01d23ba80951e0aefd2a9372191572bc52916aa22a2aec393767fafd086839e236fe0460ce6d639c7ce69fe7f9d3aad2130573443570443be6bab93a06a54b8ac29bf33ff9949bc92158e6924b6b68ecda5f6f3aaf42b3d22df6d5e67d5cb3ab71eb8ee0b0e66732e1daca6cd60d9aa74305fcd570076d228d446d5ee542b10488bf8aa988f451faebe74ab669d604d9ddb15106620ea02e8db38ce639b5747812bb9048ee8bf72b1a951a05dffac95417cb43b06dce61ee3da6f2832ee83b2e7288ddd62eeb5893f7f2f6c8090d99e336c9f9069e1815985841bdd505b5f83d895e879593dadee72ceb9765699bf80bd06a5c55331b2545527d0c7caece96584ce3ec7fe02260f20b8a1c0635763ff4: +f2c10577f7df77f0c1157a8c331a7bd2ae6386670eb65f0fae122331690f828a0d4c340fc231aafb3b6f74b89bcef7eeaa0b04f293ec8544247bfc3f2d57c1e0:0d4c340fc231aafb3b6f74b89bcef7eeaa0b04f293ec8544247bfc3f2d57c1e0:38ea1e028a493d1c60ec70749f14d436eb3a2b2de54f213d01a645b580430ecd8ece6b5569cc017a4943e5595c5ed6e48c9443f2fa5eb2227ffe56d211f269bc8f6fa9ee8cd56f6b8470539208afe29ab0a195044d957b31f93e184a9cbef1a14e14f808bbf589ac7770084f998e1b254da59ca6d3e62e7be1790716d2560f015f399cbbce48cfd0391ead1993446f6b2493977d93d7b09a07a79a59ce15dce7a1da9c646f45af2ccad55ba158e638c4a30c5d30e9ac6e3a3339c243426d86491b2d92dac1478e8d74ff0bf149bdb5e09e3fb6b8262eb0687981554ae2cb47196339079da0a1a57239c19bf781f62fdaf4e31560a84317ef030492cf1bb1305ba8518ebaf2b434d3641672c8f6ea2defa696dc7e4f39efc08d288d1c966a6c7148c012eec439f7e12dbab5b87cfa44c9ae1900f8386f24444e1092b23a274c138e95c661e9377e8ad2d1fcaf1939ec9a632a873f7eadbe687b4a033b92a477f2e02e9ed92ce4f95cf170b3901518a062143e56db054df4e4431544785a6dfa24eec0f0de7a699ccf286dadfad85903612250764f25cdea8127d0078d554825ea6e7371c438bc46f29fb8937f8d9a39cf8849052d43ecbff6c4a3762a5f400c1514e85e91384fef9b40f4314e223a9d68c526acc70227d62b8b637a342df113d318202c51edd3c1efd1ff20b1ff078b32068e794d928133037f1e3a34689e629e43fd2b8e88eab50d7e7ab0647014ab5e4ad582006567eff72b5af2dac536892ccc871f8a80b5cb79d90bcc6b77d4cd08f876184ef58c064ae430bb79a6b9e96b0ad87368aa838a8dccffac0cd8ce9ea0d0ec4c4b0f42673416659c984992cf53b1e445431007640d47ece26dee4a2943aa7097dd356cff4754f21ac07f6b3f73c469055512f37aba:60b703115a322ab892c276bfd18f70a9eb0c7323e2c0a6eb5fc7e330b0bc3b07a578a082846264f032c6191d040bd98e5d5a4d4f076fb9062acd36bea40c910238ea1e028a493d1c60ec70749f14d436eb3a2b2de54f213d01a645b580430ecd8ece6b5569cc017a4943e5595c5ed6e48c9443f2fa5eb2227ffe56d211f269bc8f6fa9ee8cd56f6b8470539208afe29ab0a195044d957b31f93e184a9cbef1a14e14f808bbf589ac7770084f998e1b254da59ca6d3e62e7be1790716d2560f015f399cbbce48cfd0391ead1993446f6b2493977d93d7b09a07a79a59ce15dce7a1da9c646f45af2ccad55ba158e638c4a30c5d30e9ac6e3a3339c243426d86491b2d92dac1478e8d74ff0bf149bdb5e09e3fb6b8262eb0687981554ae2cb47196339079da0a1a57239c19bf781f62fdaf4e31560a84317ef030492cf1bb1305ba8518ebaf2b434d3641672c8f6ea2defa696dc7e4f39efc08d288d1c966a6c7148c012eec439f7e12dbab5b87cfa44c9ae1900f8386f24444e1092b23a274c138e95c661e9377e8ad2d1fcaf1939ec9a632a873f7eadbe687b4a033b92a477f2e02e9ed92ce4f95cf170b3901518a062143e56db054df4e4431544785a6dfa24eec0f0de7a699ccf286dadfad85903612250764f25cdea8127d0078d554825ea6e7371c438bc46f29fb8937f8d9a39cf8849052d43ecbff6c4a3762a5f400c1514e85e91384fef9b40f4314e223a9d68c526acc70227d62b8b637a342df113d318202c51edd3c1efd1ff20b1ff078b32068e794d928133037f1e3a34689e629e43fd2b8e88eab50d7e7ab0647014ab5e4ad582006567eff72b5af2dac536892ccc871f8a80b5cb79d90bcc6b77d4cd08f876184ef58c064ae430bb79a6b9e96b0ad87368aa838a8dccffac0cd8ce9ea0d0ec4c4b0f42673416659c984992cf53b1e445431007640d47ece26dee4a2943aa7097dd356cff4754f21ac07f6b3f73c469055512f37aba: +041a97906b5956b9d340f2e0d7a1dcbfefe663e9bb4026f8cc1ae7e2a14de27ef382d32e88c3a72c7caddafcf8aa699e21db7a6bf4edd6e49a005aad702e6a79:f382d32e88c3a72c7caddafcf8aa699e21db7a6bf4edd6e49a005aad702e6a79:71a75957411544975a48cf103aa1f8e2ad15244459cdc0e336966eb8b26c97f2169e5d78537037efc077e86f06e05e9c1dc3418288c0a2be6ba34b3a04ab20bae7f3621094b87d78a7eacb864d4078cb4efcbac5add937a2c6012ee1a8b256cc276b65d5e92b4d00b9b11fad884991dec4c1cb9dce1863c8b0a210161ae6b3f8bf9cc4dce4adfdc8ed57d83e95ab9dd2d92658dfbd3afa99e3f8951e2ad74a148f6f597eb2c945c1f1b94461ae0745481fd0edf838c6286035e36f011238875dbba2289d3d6a3942a7f9554c644305244ddb77c117cb4b56237729dde428b8bb42df9ce29e144dfc96cf6c6767b1ee6d053ce4f8bb2056ab7810aa1368a8910f2f69e061c19d8847184fed534f98758d703a76885f91eb752a21954a10c6f6b4da10464ded36b00089f662915421bfdad496753689ccd03b624021080761e68176b10697dac878e4c3db2fd0b28c655335d98016f19f265bb0b2434cb4637844d91ed0ce05ed2591fd998965f83f3197d10eef448850e792032724701da305cb6d794669483fc3dc6f686b183e2999130c8fc0058dcabbc9188f26b2d63ebd6cb1e18a097c7704a59b5e187e0142593b7083f7400afa9b1bf0c1cc6c356bc4334af772e67153b45b331b990920c24eede2c6e323703f52ecd60735b23bf22b81ee775927c37e53dad7596ea65a73bb96775f3b87c8b3c088ec695bc3a7502c0c510f020bf9aca3cbb7a2c011c67ff27d634caf1dcfc58e5e397e6658252272011c8ffdd64230a93241fff68372c4ba85382bbb229309652922db68836631e55be69ab6adb8e4335357fc923efe154afcc222d60d07f56990a3e5a214b227aecff2cd1bb6f0c79ff545f70a616141a9d53f922a02443f7d2a4689c35b095dd394d50bf49f9680a5f7d9:a23f032e6692a0e8bfee5b2d30b414cb16c35ad08da31f696d461a02857822c4ef357f0ccf31025a4dc95ced30a994f41edd1d087afcaaf3e8e875708320f80c71a75957411544975a48cf103aa1f8e2ad15244459cdc0e336966eb8b26c97f2169e5d78537037efc077e86f06e05e9c1dc3418288c0a2be6ba34b3a04ab20bae7f3621094b87d78a7eacb864d4078cb4efcbac5add937a2c6012ee1a8b256cc276b65d5e92b4d00b9b11fad884991dec4c1cb9dce1863c8b0a210161ae6b3f8bf9cc4dce4adfdc8ed57d83e95ab9dd2d92658dfbd3afa99e3f8951e2ad74a148f6f597eb2c945c1f1b94461ae0745481fd0edf838c6286035e36f011238875dbba2289d3d6a3942a7f9554c644305244ddb77c117cb4b56237729dde428b8bb42df9ce29e144dfc96cf6c6767b1ee6d053ce4f8bb2056ab7810aa1368a8910f2f69e061c19d8847184fed534f98758d703a76885f91eb752a21954a10c6f6b4da10464ded36b00089f662915421bfdad496753689ccd03b624021080761e68176b10697dac878e4c3db2fd0b28c655335d98016f19f265bb0b2434cb4637844d91ed0ce05ed2591fd998965f83f3197d10eef448850e792032724701da305cb6d794669483fc3dc6f686b183e2999130c8fc0058dcabbc9188f26b2d63ebd6cb1e18a097c7704a59b5e187e0142593b7083f7400afa9b1bf0c1cc6c356bc4334af772e67153b45b331b990920c24eede2c6e323703f52ecd60735b23bf22b81ee775927c37e53dad7596ea65a73bb96775f3b87c8b3c088ec695bc3a7502c0c510f020bf9aca3cbb7a2c011c67ff27d634caf1dcfc58e5e397e6658252272011c8ffdd64230a93241fff68372c4ba85382bbb229309652922db68836631e55be69ab6adb8e4335357fc923efe154afcc222d60d07f56990a3e5a214b227aecff2cd1bb6f0c79ff545f70a616141a9d53f922a02443f7d2a4689c35b095dd394d50bf49f9680a5f7d9: +4bc5e05aa003a4492f4bad102a5390f7cebab3d3eca9152142ad5ef7d84030ae6751d3ad8bb6c64d6a17d7e447a27da22f5f0403f437bac9449f13cc853dd840:6751d3ad8bb6c64d6a17d7e447a27da22f5f0403f437bac9449f13cc853dd840:a8f794db1795667d28d24b70ac2200a6239a34e2438ced1d03f97ed48beb4d6bea67c14338f7736419dcd2a2a7973726572e6afe7edfef22c99be8b069f04f6dc61a13b343c6e585abad2214d85c36f02996fabb46bb91b5176ac708e49a0b053017048fbb55453f2b8208d6678d1a8cf6a1ee9ad7a91e380325635d1e236a6ca1d6cc7f6b59f2a2bf184f5ee451d6799f69ba11a0cd6bc04be8a351a80e725b5fc4563e45bd4749ecbc45205229105b9de73261498527f3d4ecfbb583ff532753d07c38526bb482d171a261b9cf89906a7dea8cbd7e726ba31ea68803a6b004f6dcd19e671950463738cca78bb0dffa3d6457e4aeca657ec649b97ee30e97c8cbe6ce43c2aa9a69958e9dc881e4aa7b3278074e787ace5fb601d7faf7ca5103ecbbd3bd554eb1b066f8296d2cc57e8c8a32e9c0e6a926964d6df2d8645864b322c322f1ca8073cedf2b556711a7a20b77c0a1ed277a9a6ca2c07154e863fef5a404e3e89f0d7f30f218ec4de7a53aeb9c41eeaaf6ce749649c9998fd62bcba2872338e19c94e59dd5e2dd776f53719d21746976932ef11abf7a32ae6b0744665d0e0ce513955a9e68531d8ee4de9a8d35ddfb88eb5a486ad63137e8892fd7c689d4f9e7021b1173bb3752a5eecf2992e3fd4642263c7b3d815c29b466ab69285ffe4b8dafcbf3d01d635553ab7575a7a3471edc7be412d3d01e6fe8e3cdc3fa04d2a7599381e22bba49c5539d79c62b52bb0eca33f74255e41a9526a89289b15f1850d9afa87e6b6fa127101c1a6d88d433e0c86aa60bba8fe7100ed61d5a9d00a00764513eb1c7f5f5c3b3efc4532a36b407fe2d17cfb4e6fcd6049cff3a355623a3a41390ea48f42120d897949111be3d169b2d2ef45bdb894fe20b1a95ef66149427a9d8f80a9b2e:a24fee11f7ec6da3e9dfaf6c858ac004b4531abd1c9d3bb64f40dd247f00359350e43b2d4b8fbec5f6b241ecf9f1101485cf418735b05f712018335b20068308a8f794db1795667d28d24b70ac2200a6239a34e2438ced1d03f97ed48beb4d6bea67c14338f7736419dcd2a2a7973726572e6afe7edfef22c99be8b069f04f6dc61a13b343c6e585abad2214d85c36f02996fabb46bb91b5176ac708e49a0b053017048fbb55453f2b8208d6678d1a8cf6a1ee9ad7a91e380325635d1e236a6ca1d6cc7f6b59f2a2bf184f5ee451d6799f69ba11a0cd6bc04be8a351a80e725b5fc4563e45bd4749ecbc45205229105b9de73261498527f3d4ecfbb583ff532753d07c38526bb482d171a261b9cf89906a7dea8cbd7e726ba31ea68803a6b004f6dcd19e671950463738cca78bb0dffa3d6457e4aeca657ec649b97ee30e97c8cbe6ce43c2aa9a69958e9dc881e4aa7b3278074e787ace5fb601d7faf7ca5103ecbbd3bd554eb1b066f8296d2cc57e8c8a32e9c0e6a926964d6df2d8645864b322c322f1ca8073cedf2b556711a7a20b77c0a1ed277a9a6ca2c07154e863fef5a404e3e89f0d7f30f218ec4de7a53aeb9c41eeaaf6ce749649c9998fd62bcba2872338e19c94e59dd5e2dd776f53719d21746976932ef11abf7a32ae6b0744665d0e0ce513955a9e68531d8ee4de9a8d35ddfb88eb5a486ad63137e8892fd7c689d4f9e7021b1173bb3752a5eecf2992e3fd4642263c7b3d815c29b466ab69285ffe4b8dafcbf3d01d635553ab7575a7a3471edc7be412d3d01e6fe8e3cdc3fa04d2a7599381e22bba49c5539d79c62b52bb0eca33f74255e41a9526a89289b15f1850d9afa87e6b6fa127101c1a6d88d433e0c86aa60bba8fe7100ed61d5a9d00a00764513eb1c7f5f5c3b3efc4532a36b407fe2d17cfb4e6fcd6049cff3a355623a3a41390ea48f42120d897949111be3d169b2d2ef45bdb894fe20b1a95ef66149427a9d8f80a9b2e: +a3bed9fe2354bd2860149a3db75a85b129cf83e9d73e6317ba7054521933f8965ac03b4f13d91d066b2ce359e9bb1dfb6bfa5afa382fd1ccd72aef1176079f89:5ac03b4f13d91d066b2ce359e9bb1dfb6bfa5afa382fd1ccd72aef1176079f89:db853808686d6d21f4c57b541e5ad63394d465e60078643cab1e065c9f306c500078f0cc41ef0f9542b5fe356aec4777ef8a95554c97b6a44099e9bd6404fb0b2e41f91914b074d12237cd442ebd40b51b8bc8bbe437a2c53332d2beb2281bf7324a0cf5b741bbf98d1eb9858be926e915a78e8d314b4144f3d20dfc6cb7f48c23af90f871c6cda90845a41aff1707a87b4e5516f18e8bd7683cfd74070803e888338c9a18f792c8d3a704170ff982bffc9e8ec9ea5d1a62592f1688d4f2b01e11f9f88774c47ac1d58f690bcf288cf8a473d350a8239df9d3a62881dadd338531fdce7615807ce965496d6f35d6c042f0ce7f21efe5ce6425185941ed5636b8ae913a75d21ab9dbdb3c3b6687a45e044938a9f1c13a330ea9761e283e61d4a320e1f559882f34b607fefe32c343174abcdc77b065a92904b42d961db8ed916c01464ffd43f93c1077f1df7ee65031cfe05d780d01d08ee036f22a2b0512193b0c0f3801e0a0208eef245c9e519352d2b0096382f2cba06eb2a01dacf619eabbc883c5d4f2fd7c3423179c0f5ffdaf8cafff5c46b34a09c3c50e2949c06000207d70d37d65a743075fdc2be62d412aa63e363706ca90e6ef44e152ea4dc5c2893ecd08d796d41f172254c3d1d14bb067b53a0897bbd73c9954d9648b2af10d9c2703e38b6c62469f6f958a1ca0a320c12339e90cf768c87b4738c219f8093bff4c2cfd29459f6d3281349378e915a3b0e724c74d2bd7a851ac7c6b48e8afc7124fdcbcab5ff80d1dee30a6c024cb4331972366ebab26bbb9f608caac7e51914df058b9b3745d98c5d27e97105475ec017377e6316198ece4ec5909f04fc27e7b382e66adb62ac8a977f376fd5dae434fb55175249ca1ab6bb02dec0696f089be3454887a0c32361d172bd2:33bc1e0bf1b493e0cfb7ea40480a1423e091f7145745013173787df47a10db24c165d00596fab70e68c94c104e8a7407cf695cd3fbe585b5b176b85ccca4fd08db853808686d6d21f4c57b541e5ad63394d465e60078643cab1e065c9f306c500078f0cc41ef0f9542b5fe356aec4777ef8a95554c97b6a44099e9bd6404fb0b2e41f91914b074d12237cd442ebd40b51b8bc8bbe437a2c53332d2beb2281bf7324a0cf5b741bbf98d1eb9858be926e915a78e8d314b4144f3d20dfc6cb7f48c23af90f871c6cda90845a41aff1707a87b4e5516f18e8bd7683cfd74070803e888338c9a18f792c8d3a704170ff982bffc9e8ec9ea5d1a62592f1688d4f2b01e11f9f88774c47ac1d58f690bcf288cf8a473d350a8239df9d3a62881dadd338531fdce7615807ce965496d6f35d6c042f0ce7f21efe5ce6425185941ed5636b8ae913a75d21ab9dbdb3c3b6687a45e044938a9f1c13a330ea9761e283e61d4a320e1f559882f34b607fefe32c343174abcdc77b065a92904b42d961db8ed916c01464ffd43f93c1077f1df7ee65031cfe05d780d01d08ee036f22a2b0512193b0c0f3801e0a0208eef245c9e519352d2b0096382f2cba06eb2a01dacf619eabbc883c5d4f2fd7c3423179c0f5ffdaf8cafff5c46b34a09c3c50e2949c06000207d70d37d65a743075fdc2be62d412aa63e363706ca90e6ef44e152ea4dc5c2893ecd08d796d41f172254c3d1d14bb067b53a0897bbd73c9954d9648b2af10d9c2703e38b6c62469f6f958a1ca0a320c12339e90cf768c87b4738c219f8093bff4c2cfd29459f6d3281349378e915a3b0e724c74d2bd7a851ac7c6b48e8afc7124fdcbcab5ff80d1dee30a6c024cb4331972366ebab26bbb9f608caac7e51914df058b9b3745d98c5d27e97105475ec017377e6316198ece4ec5909f04fc27e7b382e66adb62ac8a977f376fd5dae434fb55175249ca1ab6bb02dec0696f089be3454887a0c32361d172bd2: +88a24f0df3ae2914df79da50ecf8ecb42f68c7baad3b6c3a2e0cc9c25d09d14212e6603f713b2305358568710018685e141553c47591396fb4259e42dc53b9c9:12e6603f713b2305358568710018685e141553c47591396fb4259e42dc53b9c9:654e9edc69fe634c2308ba8c46a955e882456286eae3593cae739c44866c0de9edcbbf0db1c44149668467709dc9706298dd2eac3301dabad5bd8e93c5e8a93f194e0fc1d9f376c144c293aefda086b2218f2e9dfd7c2dc52ba33eb229dcf7bb68ce0f876c5fd4e81afd80169f73cf264e5dc0ce16e1b876cd11c7ad89058ee0820c40005d01f119f8be6f1afbe24ca4aedc18e97896827c3ed67fc45630e7903b7fee9c990e361937bf4ea0a4d8d16cf6d9cf0381e9065e3625148f8ae0491a0341d0ff9f727be1f310ca1ec3f0104aa054321784dd24d53c985b28d44082f8e1c108a44109638ff5116edd85aeb86b6ea512a19b602edd9d211070d044af5bedb6c8527ba3491e345bacc130b36960282ae737b85c769274f0f7c588f40e6625b236bdc1a3b87320460eeeada278124b5668874f39f59c2e6aa208c3b6a9b845c4d0a27a0546786fa13e51cc98b73fd7ee327b6215ec6b629f4cc7e4bd3c0a3db78a21fffe24c70438716bc37b8da7c5ff7c3688a90339c22eb50b7c2cd36b68831fd5939175689bd3e22c3881af337ee14435709e351040ef3da955724e51c24a5e2c09f891808393fbf8ef7f1f5f0298deebdcd8d666cbcf3e866c718999ab6b1feec9c47e02e7d63540f89963d542c5d01fb6fc30768968ae81b20c354b4000c132774764d6d443add64f6dd748f5fb5b7f6eba401db4318be993989fcc2577961fa5ad31f6a2a9d6a755285865cd5dc3a88cfb5aba7d923baf78b5d131b4c214df55b6171f45209e21ca6645490d3a3644dda6dc929c7c409576d37164755ef8aaf3dcd4d22775ee7dea0e565bd54727921c649bc51f20c1f68c1fdeac455c67d71a1cb8837f4691448bf0bf044a46f1685fbe22b1e01877f7477d3499408c4c316510ce2e55b98005:1707cc009186bf3f03f7bb9e3cd4cf6b737b7a6baade7fc6c3ff5c1225dbb2baf54f47c85eafa132c31eaca03e6aec1447733facd37149b7c6cf0cd41f611404654e9edc69fe634c2308ba8c46a955e882456286eae3593cae739c44866c0de9edcbbf0db1c44149668467709dc9706298dd2eac3301dabad5bd8e93c5e8a93f194e0fc1d9f376c144c293aefda086b2218f2e9dfd7c2dc52ba33eb229dcf7bb68ce0f876c5fd4e81afd80169f73cf264e5dc0ce16e1b876cd11c7ad89058ee0820c40005d01f119f8be6f1afbe24ca4aedc18e97896827c3ed67fc45630e7903b7fee9c990e361937bf4ea0a4d8d16cf6d9cf0381e9065e3625148f8ae0491a0341d0ff9f727be1f310ca1ec3f0104aa054321784dd24d53c985b28d44082f8e1c108a44109638ff5116edd85aeb86b6ea512a19b602edd9d211070d044af5bedb6c8527ba3491e345bacc130b36960282ae737b85c769274f0f7c588f40e6625b236bdc1a3b87320460eeeada278124b5668874f39f59c2e6aa208c3b6a9b845c4d0a27a0546786fa13e51cc98b73fd7ee327b6215ec6b629f4cc7e4bd3c0a3db78a21fffe24c70438716bc37b8da7c5ff7c3688a90339c22eb50b7c2cd36b68831fd5939175689bd3e22c3881af337ee14435709e351040ef3da955724e51c24a5e2c09f891808393fbf8ef7f1f5f0298deebdcd8d666cbcf3e866c718999ab6b1feec9c47e02e7d63540f89963d542c5d01fb6fc30768968ae81b20c354b4000c132774764d6d443add64f6dd748f5fb5b7f6eba401db4318be993989fcc2577961fa5ad31f6a2a9d6a755285865cd5dc3a88cfb5aba7d923baf78b5d131b4c214df55b6171f45209e21ca6645490d3a3644dda6dc929c7c409576d37164755ef8aaf3dcd4d22775ee7dea0e565bd54727921c649bc51f20c1f68c1fdeac455c67d71a1cb8837f4691448bf0bf044a46f1685fbe22b1e01877f7477d3499408c4c316510ce2e55b98005: +184d0ce2e9db7f257a8bf4646d16d2c5efc2702ced026b6906d3c8c0118f2261e9dab8fd9d94dc9b24cc79c635cc57ce66518982ba3e2447240741bac0730ec5:e9dab8fd9d94dc9b24cc79c635cc57ce66518982ba3e2447240741bac0730ec5:6a9b876b0bf4189b3cc15f9eb4fbe7932b5577892a22200ce107156853d6d3ca363f025ad7a2d862aadc742d9415bd8d1fca13c9dca3586044e55a8cf5dee1ce564576e3e8e365540546501b34ca675cf200e0771a818c73d37fcda8cb15e48d5a0b9ea3beec0ff6610b2a8a214ca4f7efac0e71381052d9bf3c00c329593474ebd0a687a0b41d144b5e7ab1412b970a74baba4d274bb0dbfdb02b11f7f63964ba6f3ba0ad23341d083b91a4308239e33d50824396126588de72a2390c1c0fc06747c28772f630bf4d143f7a1159f028c093404894e6d16f634635d4fc330f3d7a7313ef756f5d49d8f6205eb1c792a9495da131b43345a0090c12ca56e6adac5be0cbcac3609d69f72415f6c37f3cfb2cf76b3e65f3c93ac92b63f2baa466249075bca69d4c1d1f3ade24ab31effcb90469c24bb410ab4723e1b7e1c88b3a36433563f71a99aad58fe80568f9c102da89bad97963e77d6622483166f3ae261f32a52a86101ebd645f6142c982e2cd3625cf8b46b9b2891246920f697fcaed397cb922c274945167a0e619b0b506377606db045783b0b88ea04e932d21ffc064a12a40ebe9b480f1a2c7ddd395a9b15efdc495c9714f36fa996f79f8eb8efa52d99a24abfef43b32a237c5bc0018da3b162f59b8d3d474e2ce08fa8024c58acc0a99ff614e6cd7fdd9ca4e8f41a1449aa618d03337e8a374d56055b207a9dbe69f5948f901ca7db0410f01aa373d9e0227623599bc212845b006e942fabc582cd726db5c443eb2dffbc9e3e7f0e5cb6744f7ad716050fdf2c60c7c77c253ab745db9c8552655683ea7ea680aa4af34df1325c29b8874b61be23de4ffba25424f4619ec682c26b3a67bda9bc4c94b79a9fc4d82d340495b437a1cbd6b60307cfcb10026f964a017623e33dbf233:b1e3bf5fa74d7e442ced9a98d927d8c45e0e64d874f8ea5920a360a4bf42d83ce18a924ac796e1a77d1b0208294b50f822177fdbdd458c74356fcf6bd79451066a9b876b0bf4189b3cc15f9eb4fbe7932b5577892a22200ce107156853d6d3ca363f025ad7a2d862aadc742d9415bd8d1fca13c9dca3586044e55a8cf5dee1ce564576e3e8e365540546501b34ca675cf200e0771a818c73d37fcda8cb15e48d5a0b9ea3beec0ff6610b2a8a214ca4f7efac0e71381052d9bf3c00c329593474ebd0a687a0b41d144b5e7ab1412b970a74baba4d274bb0dbfdb02b11f7f63964ba6f3ba0ad23341d083b91a4308239e33d50824396126588de72a2390c1c0fc06747c28772f630bf4d143f7a1159f028c093404894e6d16f634635d4fc330f3d7a7313ef756f5d49d8f6205eb1c792a9495da131b43345a0090c12ca56e6adac5be0cbcac3609d69f72415f6c37f3cfb2cf76b3e65f3c93ac92b63f2baa466249075bca69d4c1d1f3ade24ab31effcb90469c24bb410ab4723e1b7e1c88b3a36433563f71a99aad58fe80568f9c102da89bad97963e77d6622483166f3ae261f32a52a86101ebd645f6142c982e2cd3625cf8b46b9b2891246920f697fcaed397cb922c274945167a0e619b0b506377606db045783b0b88ea04e932d21ffc064a12a40ebe9b480f1a2c7ddd395a9b15efdc495c9714f36fa996f79f8eb8efa52d99a24abfef43b32a237c5bc0018da3b162f59b8d3d474e2ce08fa8024c58acc0a99ff614e6cd7fdd9ca4e8f41a1449aa618d03337e8a374d56055b207a9dbe69f5948f901ca7db0410f01aa373d9e0227623599bc212845b006e942fabc582cd726db5c443eb2dffbc9e3e7f0e5cb6744f7ad716050fdf2c60c7c77c253ab745db9c8552655683ea7ea680aa4af34df1325c29b8874b61be23de4ffba25424f4619ec682c26b3a67bda9bc4c94b79a9fc4d82d340495b437a1cbd6b60307cfcb10026f964a017623e33dbf233: +d02bbf70d51351e3b47ad8e5ed263dbf556d1498fa9bd5dbd99fb4269009dced8ce4b59f94ced6ec9614d67d3066d9d3a0df7a46b37b4c1725ef1e57bc68a0d1:8ce4b59f94ced6ec9614d67d3066d9d3a0df7a46b37b4c1725ef1e57bc68a0d1:554560f7a7fd1ae7758a2fce7d780f6b3f043d3af89d4f19ef573c34997554df243faf2aaab65b2afdd28610d4a51e9a4b464db6db09ebf73b7d24054cc9b12814bb29ee99e1a73bd603898360f9dcf01e670836286f8236ed8cef075f3d563312c16c73fc37eedf252f8f42d30a13e7fba3b165238c7f81eaaeb53190f3ec3b5d63f0ee03e3987e390d1d81e8277e9f6c1ee6ec4ec3fa0d720e9f53f9c26f04aa2ed2b5ef3160895999eace29cf5dc254ad71106bb7e8bc29a5b1d2412593d08194e88e1659a73159a2a22033ab066e8d3d8c3bc86b7b01de81a8c66047b07fe24ed240318ba37ba3efb6cf632604ca4f446a75fd8e70c453f0c60ee16ecaf524e703f47df5c282ca3289b3af61dee4709ee085323b1e5c8a6bc0766201c635031446891f3494e9db20dd4e9e0838249a67e138d13ee2c96f61e771061542aa16ef20d81e3a0f4e4521a6cd6c92fc26feef03b66c70e035cafcc19c96fb9d82918fe197780eff0eda6e2512c56e2a73d77032b768919bea9772f5989c8b6c65c3d1e97a2180cc3a37579da70ce9806ac1285a3eab415c0607d88cb86542eab90b9d2d67fafffcad23a714000ee59ed68c956e81c445428882f97af74db362e45c0d1bd8856eed166e4aec4bfdf95eadb251e2a1ef804852a9ea77d34577fe70831a928b101b60ac613e7ba2e6ba0a94013a64c2f8219fd30bff409099667a786f99327bb03e2f2187f445b46beedab6d325afd904e39543e93f4b6c5443249d744b2d1a43e141e4768bd40aabe4057244e1eadd9daec175719e51a093ace32fe82b2eacb5ecb0da6c1ffe98c8cee7886e301670dff87113efed4282471afb6b8a0fdb505e2e8e7dbc1a08a22e9680bd098bf1275802bdb459413a3b237d7713a1bbf597e6adf2b60eaf823791b3:6e7c66acc954ffd9dd4c1c6335ab4fe79dbbed782c4a47ec30d848d8bb2b4f1069dc62e522a1e8017f54a6345e1728c073af6447856d8c1ed35878b571e5230d554560f7a7fd1ae7758a2fce7d780f6b3f043d3af89d4f19ef573c34997554df243faf2aaab65b2afdd28610d4a51e9a4b464db6db09ebf73b7d24054cc9b12814bb29ee99e1a73bd603898360f9dcf01e670836286f8236ed8cef075f3d563312c16c73fc37eedf252f8f42d30a13e7fba3b165238c7f81eaaeb53190f3ec3b5d63f0ee03e3987e390d1d81e8277e9f6c1ee6ec4ec3fa0d720e9f53f9c26f04aa2ed2b5ef3160895999eace29cf5dc254ad71106bb7e8bc29a5b1d2412593d08194e88e1659a73159a2a22033ab066e8d3d8c3bc86b7b01de81a8c66047b07fe24ed240318ba37ba3efb6cf632604ca4f446a75fd8e70c453f0c60ee16ecaf524e703f47df5c282ca3289b3af61dee4709ee085323b1e5c8a6bc0766201c635031446891f3494e9db20dd4e9e0838249a67e138d13ee2c96f61e771061542aa16ef20d81e3a0f4e4521a6cd6c92fc26feef03b66c70e035cafcc19c96fb9d82918fe197780eff0eda6e2512c56e2a73d77032b768919bea9772f5989c8b6c65c3d1e97a2180cc3a37579da70ce9806ac1285a3eab415c0607d88cb86542eab90b9d2d67fafffcad23a714000ee59ed68c956e81c445428882f97af74db362e45c0d1bd8856eed166e4aec4bfdf95eadb251e2a1ef804852a9ea77d34577fe70831a928b101b60ac613e7ba2e6ba0a94013a64c2f8219fd30bff409099667a786f99327bb03e2f2187f445b46beedab6d325afd904e39543e93f4b6c5443249d744b2d1a43e141e4768bd40aabe4057244e1eadd9daec175719e51a093ace32fe82b2eacb5ecb0da6c1ffe98c8cee7886e301670dff87113efed4282471afb6b8a0fdb505e2e8e7dbc1a08a22e9680bd098bf1275802bdb459413a3b237d7713a1bbf597e6adf2b60eaf823791b3: +aa0fdae2a5a4c9c04521913004cd89efbc88b2dadf5abb246f3ca7f6923544afbffcb17c35c1304cdd9d624ff69bee60ec7c9ec327d12350d70fac12b47cc25c:bffcb17c35c1304cdd9d624ff69bee60ec7c9ec327d12350d70fac12b47cc25c:b14184cfdc4a5f0c7f83f94a832f588507e2d72a89329870078571d208a0c4960c2fdc4c236cf88229981d12b10a1b6884c8650ddaf1d4b2eb981575b1e019fe3f60423676f8856a992cce36d6d0a3d026631c8c1e1ffe34134b296f40842b6df4f86f833e0175bae50e86bf856d1ee79925f434b8bf2c84519f1f5d25386049ce3ca61777e30b700a602d395250b60fc64ac6f8db027e8da8b9550f24ed11a11d9f9f9c5e0af145b8659751ac6b55861f6388a64336b31efe45c0802d76a53486a81eba07314b4d961c141ab34e2f76edac0e6de31422df792af081e769c7ed05da9a5af2fdf36f141769908b700937f0e1068c131f176eb96c67afdbe78f40d86007fbcd47e49e2e4c4ce049936adff1ce3eac42b96b3429b5626b1aa62acde07f45a13ce1bd211f32bd7efe4790c8371ebf87c164477a5c9fa3e78c2f88077b097344cffa031c4429c7f42dca07737850ee7a769b36d0f0625adf120ea23ff4e393a4fdcb6558dbf9b266a032e3b0599b9d6692fcebd815a3897607856325fcd0115dc310db3a8792fbebd399494c8371e585727b3d632414496893d03813ba1f99661bceb9dc18ec5dc27f52670318687769fc678ddc7e40227c200522013f5c0eec0e4781e6fc153a0c2f4f3f95e517c8419924ab39992af8c19465057f134486696ba7fd4651768b4e749ef36f02444617cf97f0a423e4c13b7b66ba2b6c456878b0b50ce2ee5ec564ed8854f782aa1d1c6aa760f2522c7d97b9b1abe0ba810959d7aa403a99375aa3e39a115d1fc6fedd002f3830a50a837dc720329ec0c73d5bfd500385c736838287e19201525d189c3a084cd5a3f359875e3b8325289ced18b63b00ff9cd070c3e67444bd3d8346174085cc45135caa0c67b3226e4a52e9a1c55aed7ec5fade6bf16c19:f937298969ca34d97584448907358b0f47841f3023afc7ef7681521c5be0f5e5628a8f607e2f31636ef63646b0e9898a72ad355706d2c8060fbc640efb3d6605b14184cfdc4a5f0c7f83f94a832f588507e2d72a89329870078571d208a0c4960c2fdc4c236cf88229981d12b10a1b6884c8650ddaf1d4b2eb981575b1e019fe3f60423676f8856a992cce36d6d0a3d026631c8c1e1ffe34134b296f40842b6df4f86f833e0175bae50e86bf856d1ee79925f434b8bf2c84519f1f5d25386049ce3ca61777e30b700a602d395250b60fc64ac6f8db027e8da8b9550f24ed11a11d9f9f9c5e0af145b8659751ac6b55861f6388a64336b31efe45c0802d76a53486a81eba07314b4d961c141ab34e2f76edac0e6de31422df792af081e769c7ed05da9a5af2fdf36f141769908b700937f0e1068c131f176eb96c67afdbe78f40d86007fbcd47e49e2e4c4ce049936adff1ce3eac42b96b3429b5626b1aa62acde07f45a13ce1bd211f32bd7efe4790c8371ebf87c164477a5c9fa3e78c2f88077b097344cffa031c4429c7f42dca07737850ee7a769b36d0f0625adf120ea23ff4e393a4fdcb6558dbf9b266a032e3b0599b9d6692fcebd815a3897607856325fcd0115dc310db3a8792fbebd399494c8371e585727b3d632414496893d03813ba1f99661bceb9dc18ec5dc27f52670318687769fc678ddc7e40227c200522013f5c0eec0e4781e6fc153a0c2f4f3f95e517c8419924ab39992af8c19465057f134486696ba7fd4651768b4e749ef36f02444617cf97f0a423e4c13b7b66ba2b6c456878b0b50ce2ee5ec564ed8854f782aa1d1c6aa760f2522c7d97b9b1abe0ba810959d7aa403a99375aa3e39a115d1fc6fedd002f3830a50a837dc720329ec0c73d5bfd500385c736838287e19201525d189c3a084cd5a3f359875e3b8325289ced18b63b00ff9cd070c3e67444bd3d8346174085cc45135caa0c67b3226e4a52e9a1c55aed7ec5fade6bf16c19: +7162fef0aca4974b094a6a08054395f877ff9433f1e33e20e88eaa90f938997da280640f139f45c35a4871537eefe6ef9db02de785ee9fd54f805fb57d3746ef:a280640f139f45c35a4871537eefe6ef9db02de785ee9fd54f805fb57d3746ef:c90f450bda1c6efd8d1278debd7ae03e2eac2740a5a963fcf96c504e31d4d6fcc5e2b52a2518d2741c55e9591867b2423228f9c19f33c6f38705c62036d480ff53df12077e38fdb073c673105da1e11619ba5321a71b5f4993234a11948ea110cfa242bc23fac9aae462606e39641ca7147eebba1eec553fce94e53e4e01b073dd780a2ff678b31572ca11ee0877e756bcdb6653e5e1b4cbfb569a9d60e3ee336182dcb9b25d1be6dbf9b5c7146d775585834cabde0278aee5d57c85e983f84d8833a9e15bcc11198e1c1da6ba59282129f1db966f5460c8fb6530fbc3a98a31fc0f4e9b337366eec1dce108c826d49045abfa12ee88797f08f0683fef77edaa3543b91cb118e424d9c408da547431125107d9b0744c2443ce9917e1e328d81850babbc94d920a1d06e524dbb6c23dd82e1787822d71c4cdc409ae85ba4deb581f934748f75e7a769b9d68c4589e594e65cb6c8f4903ffbabd5a326e89441a542f8ac264ccc64e95a8982a710b6c56ff7d10916afc409ea8a41b74679dd6a766f59c52b9305ba733b13c9e811ee13083925f4200682bd05dea339532522970aa149d004a2ea20ff461e9ec0f3b62565c1a106259c836605cc27cadc9515cb9979e89af287c027d75edbf87d5cff63a7fec9bd10e7877ab9bf868d734bd3a2374cef7025cc4dab710e254806685a136ecd03e36770346513a15145b890eeef47b80ea08e46c81d202e533e9a06a38a6f76ef57a9c736ec78d00b808e3ffd9c79b9dc7a2e589907656c932ab8a8b57da1a495ba7452015e7924b5269ab1f67bdb43a35831487ab9002f52d78b134cd3751925aaab0b45c8e6b0f2bf0cc9a4659317108fba9136aabb0921a58fbb9b50e51243f9b531847dc9657e96fbaf7aa698fe6fe44f90590144c70337250c58bc5dd:ae161cce95403384b65c6bc9b393eb072564c35f3a6c04fa517ab068bcd23767cc0c8edd92b1a13ae9a9ce4864137fb89c1f37b748cfc9134b6741ba1b22280dc90f450bda1c6efd8d1278debd7ae03e2eac2740a5a963fcf96c504e31d4d6fcc5e2b52a2518d2741c55e9591867b2423228f9c19f33c6f38705c62036d480ff53df12077e38fdb073c673105da1e11619ba5321a71b5f4993234a11948ea110cfa242bc23fac9aae462606e39641ca7147eebba1eec553fce94e53e4e01b073dd780a2ff678b31572ca11ee0877e756bcdb6653e5e1b4cbfb569a9d60e3ee336182dcb9b25d1be6dbf9b5c7146d775585834cabde0278aee5d57c85e983f84d8833a9e15bcc11198e1c1da6ba59282129f1db966f5460c8fb6530fbc3a98a31fc0f4e9b337366eec1dce108c826d49045abfa12ee88797f08f0683fef77edaa3543b91cb118e424d9c408da547431125107d9b0744c2443ce9917e1e328d81850babbc94d920a1d06e524dbb6c23dd82e1787822d71c4cdc409ae85ba4deb581f934748f75e7a769b9d68c4589e594e65cb6c8f4903ffbabd5a326e89441a542f8ac264ccc64e95a8982a710b6c56ff7d10916afc409ea8a41b74679dd6a766f59c52b9305ba733b13c9e811ee13083925f4200682bd05dea339532522970aa149d004a2ea20ff461e9ec0f3b62565c1a106259c836605cc27cadc9515cb9979e89af287c027d75edbf87d5cff63a7fec9bd10e7877ab9bf868d734bd3a2374cef7025cc4dab710e254806685a136ecd03e36770346513a15145b890eeef47b80ea08e46c81d202e533e9a06a38a6f76ef57a9c736ec78d00b808e3ffd9c79b9dc7a2e589907656c932ab8a8b57da1a495ba7452015e7924b5269ab1f67bdb43a35831487ab9002f52d78b134cd3751925aaab0b45c8e6b0f2bf0cc9a4659317108fba9136aabb0921a58fbb9b50e51243f9b531847dc9657e96fbaf7aa698fe6fe44f90590144c70337250c58bc5dd: +dea180c91b533aaf736bc5d3c8e474d5e5d475b75b92cde6bd1d10f3b8f55ad430b20fb320b00e77c4e0a8eb3730af3c0b1c5f5ed9ee2b0562707e4f55c4938b:30b20fb320b00e77c4e0a8eb3730af3c0b1c5f5ed9ee2b0562707e4f55c4938b:606144b7d4f96bef7f112b6d41bcb500d2136c134ceda220e24d0f1524eca12c30f2b102c7f378d6bba259c5b4a5ef8ec9309d5c8da7e8d2ded3792aeeea2108f77d66b23045938ed64751f20d48326be2fb99628cfb1873d7dd27581c105ec13249a952a50784b8b34cb3b2c1a004fa8b628a0767fa9abf058d955df85d134a0fc7f4b7d7fb0c8d31bce345dd0a4282145afb2ff19751f2cc3a1caea242baaf538749bf388000e3dc1d739359dfebae64ae1e10fb6fc17cc9fb950535c2de129587a86859b7be36dfe9b6c1141b25e0915c8d4aa1cceae7046b3d7cfa940bc98d4d69fc5a30dde1dee42fb5272281bf8f8e7f3e1a04397fb4f3adefc57532ddbde36833a676e6f39c82aff6bf4832ec971e03be3829c02a203c82d9eb8c1630ee9693f45d26f5f51a3103ca64d468eceac1b29af4c42eb216d76ec8994836b4bec76489ca5070680c2c2eb457210a77c47fdcbf600172073a53f1453bb5c80439c882f0736de40637b4f5ab1f761ff355c6e9bd4abde7560d5fc113c830159a1b77c4e87bc2c69880a40c5805ecc8aaaf57575bccd8177fc6b83569233c0f5ca223ac4013ca106cac2854706aead714fa29f2860a5f9753268a3671d9f59cde6048cf0b8986050f7f549e4fd7557f2fc3fcdccddcefda586a64b3006e5825f27ca31687caf663bd90a05b1152d7c88d7f1051a9d791748651d888a6a12f22d6c8c3f78c2b86eaf5394b4ef7eefb89797b25e542dc93102d021a1d0bed6a7dcdd8102b8f0430a0bc21d904a3c9346c018343dd9937cb35250007a284825db08e9a11fee31cff7a314c48c42d8b314acc27822af03d1954c7cc8bf9ad4e9e98f4ad4efb355288daa8c90de9037e64a7861f5ee43ada9f0fccde34d0bcf50288550f700f215a7944a5380e2a8e3f04f2b4f5:d083333fb84e79c9b33e55e8192d571ffc8dc50745b6b5fdd8c44d92a63fd178c4e57c2ab3a1211c0ba2d39da30b06629d8d1cc1d9f2593263d524fa5a2ebc03606144b7d4f96bef7f112b6d41bcb500d2136c134ceda220e24d0f1524eca12c30f2b102c7f378d6bba259c5b4a5ef8ec9309d5c8da7e8d2ded3792aeeea2108f77d66b23045938ed64751f20d48326be2fb99628cfb1873d7dd27581c105ec13249a952a50784b8b34cb3b2c1a004fa8b628a0767fa9abf058d955df85d134a0fc7f4b7d7fb0c8d31bce345dd0a4282145afb2ff19751f2cc3a1caea242baaf538749bf388000e3dc1d739359dfebae64ae1e10fb6fc17cc9fb950535c2de129587a86859b7be36dfe9b6c1141b25e0915c8d4aa1cceae7046b3d7cfa940bc98d4d69fc5a30dde1dee42fb5272281bf8f8e7f3e1a04397fb4f3adefc57532ddbde36833a676e6f39c82aff6bf4832ec971e03be3829c02a203c82d9eb8c1630ee9693f45d26f5f51a3103ca64d468eceac1b29af4c42eb216d76ec8994836b4bec76489ca5070680c2c2eb457210a77c47fdcbf600172073a53f1453bb5c80439c882f0736de40637b4f5ab1f761ff355c6e9bd4abde7560d5fc113c830159a1b77c4e87bc2c69880a40c5805ecc8aaaf57575bccd8177fc6b83569233c0f5ca223ac4013ca106cac2854706aead714fa29f2860a5f9753268a3671d9f59cde6048cf0b8986050f7f549e4fd7557f2fc3fcdccddcefda586a64b3006e5825f27ca31687caf663bd90a05b1152d7c88d7f1051a9d791748651d888a6a12f22d6c8c3f78c2b86eaf5394b4ef7eefb89797b25e542dc93102d021a1d0bed6a7dcdd8102b8f0430a0bc21d904a3c9346c018343dd9937cb35250007a284825db08e9a11fee31cff7a314c48c42d8b314acc27822af03d1954c7cc8bf9ad4e9e98f4ad4efb355288daa8c90de9037e64a7861f5ee43ada9f0fccde34d0bcf50288550f700f215a7944a5380e2a8e3f04f2b4f5: +9daf6dbb7f762966e7a57c2ec1996e9f5b555b9866b8e31deaab4356eb13816ef021b55a36d9fbfbf2978bc0df736b289c8241d6435309841a134b07d47ce4ed:f021b55a36d9fbfbf2978bc0df736b289c8241d6435309841a134b07d47ce4ed:544523900daa6778c0391ae4044a51c0c4a5e444133fbd7747d539a744fa60ab5dc54e1819dc8e56899c56efd7ef3da341790ecc49645ef325c6568ae971d30d21bb7f23464f46a24b80d49bb93c6e91de79b24331d0707f43d0665d0197743adff690d615a1c9258777fc47d0217142426a4734892eb622ab8e50bb128ec3a895266a3861a39768bc76096f581fd082df9b7223e85a8afbdb5caa4922af2a014bf8a5cd11e5c5ea93e91cd46d5a1b99b85a2670e321de2e32255afd67fe2c37fd932caca22d241faf4ccefeff58d6bd04cfaf11dedd29c8719ffcb02ef65c5d3eb78b4fc0d170a2e3432cc812f0d041d9760c13c12f7c7f2f84fe5e0f700c10b1a69ca466a70bdeff8dbec7d318fb09ddd827ef61caa6910bbc061cbda2b527ef2e59ed4c17229972f89567d705de9231924b41bb6e7c01fe854264474fa76b1f88cd57eac311171af103d23078424a12675f2fa36c2de0bf53c295feeb3157de958922986e32513dfa33b35e15c394a11c0fcc55b82d6dd0597cddd27ede7de12985a616e64026befb5d690482b3ff22c0dd21f27a086d37a0499ea36fe2c4b5a959d10e9a610cab1fe0d28cf1013dcae63d8fdee0ecbd8b4e19d5d040e2fad7d0413a38e8c4e73552ad46047b5bbdd15c09cc0d34e48b91fdbae2a9d162d4b21ee20a1ef535ea883595bc4951692a67163454c7367f134bf645d48f9969e3d4f0f9eaf4144ce980a0a2e3342c746c2bdc3ccdc2f8a7da57a0e8028782d30af5857d9efb37666df65d7cc384716661e61ff5c09752595e94112ca1a840d6e4f6ec0e55494c5b44f7c0f0d4a99cd70905bf8485561748f4dc0fd7a44a1b139113c38a1e8eb5c7a20f3e952eaea8ce38b207c28ed972718f031f477c6207ce433c515f5ac2840f4974f1f16989626c76bc98:49b6bc46b7abb5694da94215efc4b30eea04ae2e73eb2da8e8c9ef9be2222498b17e13939646c29e32d645584640641590b1bbdbfe24f36c6f694bf87238ee04544523900daa6778c0391ae4044a51c0c4a5e444133fbd7747d539a744fa60ab5dc54e1819dc8e56899c56efd7ef3da341790ecc49645ef325c6568ae971d30d21bb7f23464f46a24b80d49bb93c6e91de79b24331d0707f43d0665d0197743adff690d615a1c9258777fc47d0217142426a4734892eb622ab8e50bb128ec3a895266a3861a39768bc76096f581fd082df9b7223e85a8afbdb5caa4922af2a014bf8a5cd11e5c5ea93e91cd46d5a1b99b85a2670e321de2e32255afd67fe2c37fd932caca22d241faf4ccefeff58d6bd04cfaf11dedd29c8719ffcb02ef65c5d3eb78b4fc0d170a2e3432cc812f0d041d9760c13c12f7c7f2f84fe5e0f700c10b1a69ca466a70bdeff8dbec7d318fb09ddd827ef61caa6910bbc061cbda2b527ef2e59ed4c17229972f89567d705de9231924b41bb6e7c01fe854264474fa76b1f88cd57eac311171af103d23078424a12675f2fa36c2de0bf53c295feeb3157de958922986e32513dfa33b35e15c394a11c0fcc55b82d6dd0597cddd27ede7de12985a616e64026befb5d690482b3ff22c0dd21f27a086d37a0499ea36fe2c4b5a959d10e9a610cab1fe0d28cf1013dcae63d8fdee0ecbd8b4e19d5d040e2fad7d0413a38e8c4e73552ad46047b5bbdd15c09cc0d34e48b91fdbae2a9d162d4b21ee20a1ef535ea883595bc4951692a67163454c7367f134bf645d48f9969e3d4f0f9eaf4144ce980a0a2e3342c746c2bdc3ccdc2f8a7da57a0e8028782d30af5857d9efb37666df65d7cc384716661e61ff5c09752595e94112ca1a840d6e4f6ec0e55494c5b44f7c0f0d4a99cd70905bf8485561748f4dc0fd7a44a1b139113c38a1e8eb5c7a20f3e952eaea8ce38b207c28ed972718f031f477c6207ce433c515f5ac2840f4974f1f16989626c76bc98: +7186f8d168d9ddf17edbaf0e7b1abcb26da3e4c0272d9879c7fdff6421c4ea5096b4a656232029fc1b8364703cbea7a5d7387518a88ced1a915ec8d886848132:96b4a656232029fc1b8364703cbea7a5d7387518a88ced1a915ec8d886848132:a3e6cb6b84cc5cf1fb1a848b4b8ea7cb7c87e0445750c61f9aa5d77deddf949463ecd39bfc71f2610c2a9424847fb76f84c5da1fa10ef718a34566cec1b3e899e7252e8d4d346016498ff119972750061660baed312827583181073d1dc74b76c430ca30d409e4e8439c0fc48c00680629d43ae2a77d69228f7f8a1253af15bd2cb6bb1c1696550c4c790f449869630ab92b9c11cde1f961aa2103ec23f7d9f0fe9c3c4132582efa79a66ae3426e5105b80bfe5e04dc8bb1e38a3110cd72984b3ef02a0ca62ab638cbcfbc8a6b593d2613dc06ec86fee34f6518d4a3fbdc157237174564daeb6674cdc34f4d6537cf81d8aa9bddbf3aeda312daaeee336f9ed8bff81e294bc7d44d25cd787072e6cb414b65fb7a846fc065367ba8e37beffdf0b7ba8f98cdf1eb870f4e8b7130fa3429d2e24bce5994daf1aa65e5f603b631053dc510b2f097e86e9b9b552302757968d0136ee6754c42a32c990add9cb529bc89751dfa4e5e3a0badaf4cc40b6a09507f9fcd24c3ca72259599c6ee58d857b3a189e048902e885a3607426093cb0fab437c0fb0ed2f1e96e9441a7e954fe3ef7646e26a39a07033d0a1555dfeed9a6f57794af3a2abf0057e9f853ae5c30138fd80e2f29c2f4a93ad3145da10a3e31ce9ff9786ac65d86037d98b7aa6d11de8800010e133869eb67a5039b9b8feb6ef903d0cc746412607da725ce2dc6a352109dbc6a5e40b170c23050bc4fb1efa0c34fec00eae3219c29040e8f5978c9384ee915d8c9398dd120d5c3cba38f8526b06197cb2c261dec7d726ae130f9bee17261700e99931fac4b4dca0f758701acbf3707d47df5321130ec10bb3b13078c4dc5de3470f158b57dbeb878b3a8524e0ed2c9547545f0fddf13125e45bb23d6a7b383a187f4c5d54a7b4c83d5957f2cd7e6fbc:a9c0499fc216a14532d736365c6355f938f8d8194fa1132848f83e490454d4bbf69269f12259fc6c074c1015e425e4f4f27c029c93334951361a35ad1176540ea3e6cb6b84cc5cf1fb1a848b4b8ea7cb7c87e0445750c61f9aa5d77deddf949463ecd39bfc71f2610c2a9424847fb76f84c5da1fa10ef718a34566cec1b3e899e7252e8d4d346016498ff119972750061660baed312827583181073d1dc74b76c430ca30d409e4e8439c0fc48c00680629d43ae2a77d69228f7f8a1253af15bd2cb6bb1c1696550c4c790f449869630ab92b9c11cde1f961aa2103ec23f7d9f0fe9c3c4132582efa79a66ae3426e5105b80bfe5e04dc8bb1e38a3110cd72984b3ef02a0ca62ab638cbcfbc8a6b593d2613dc06ec86fee34f6518d4a3fbdc157237174564daeb6674cdc34f4d6537cf81d8aa9bddbf3aeda312daaeee336f9ed8bff81e294bc7d44d25cd787072e6cb414b65fb7a846fc065367ba8e37beffdf0b7ba8f98cdf1eb870f4e8b7130fa3429d2e24bce5994daf1aa65e5f603b631053dc510b2f097e86e9b9b552302757968d0136ee6754c42a32c990add9cb529bc89751dfa4e5e3a0badaf4cc40b6a09507f9fcd24c3ca72259599c6ee58d857b3a189e048902e885a3607426093cb0fab437c0fb0ed2f1e96e9441a7e954fe3ef7646e26a39a07033d0a1555dfeed9a6f57794af3a2abf0057e9f853ae5c30138fd80e2f29c2f4a93ad3145da10a3e31ce9ff9786ac65d86037d98b7aa6d11de8800010e133869eb67a5039b9b8feb6ef903d0cc746412607da725ce2dc6a352109dbc6a5e40b170c23050bc4fb1efa0c34fec00eae3219c29040e8f5978c9384ee915d8c9398dd120d5c3cba38f8526b06197cb2c261dec7d726ae130f9bee17261700e99931fac4b4dca0f758701acbf3707d47df5321130ec10bb3b13078c4dc5de3470f158b57dbeb878b3a8524e0ed2c9547545f0fddf13125e45bb23d6a7b383a187f4c5d54a7b4c83d5957f2cd7e6fbc: +e86e8c62566e15753bd5577eaae7f24105b74055a25629580708bfc83aebf06c8c8ce882d5f76586d8ddccc5579bcc1cdf4cfd7162304cb10e7696026e707f17:8c8ce882d5f76586d8ddccc5579bcc1cdf4cfd7162304cb10e7696026e707f17:12fa631b0e482e9b9d633e94b82d8ab436fe548e5b95da92624623d13f2c70da775ba136c5229c16a0c7a6fa914b2feda564e17219e47370f9515bb1d59de6e9586204d943dc560d73e2e757f7eb39bbc7111bb46bc643c13f602112739bec778d7d4f49d092563d68f5776e430e3b0bf2dc1b01beb3040196da6302908bfe91e0fc38e04c150ef907dc736c445ff21fdbd2dc1eac0a0f5d00a30af028afe2ff61162b758c7da9a776666a112359431c48856a87ca82d3dd1c8af376598635432bf891becbc33a8fda44ce883ea8af4ad8b91a9261ce76b9e939c461fac53ae0f076e82d879aace8f38f120bc9b04d8125ed24bcd779d9d24386b1dd2017ebee8197376e8c36fa3aef8c1e713e2b8bce4966d84888681ba78495fbd1d6cca58626e6854cda606b83d6293d01e8e3e13bbf4aac851d9a1e00d0024e26993b0b3091be7e8061bcbb3cbb2302ceab96897a8e1ff367ec8625693cf31534124a9d5d725bcae001d67bc2111d0ab8111fa1d24e4ed06d63583ce690f2a04626d791d29e3e315a415bf2e853a5f2974c833a3fe2e2909cf669c73c1f59392d30c37f3b9c5a3ddcfd75621fda36e4ba2f16147858f6f206b9a140f1ddc1466c9a53ed73f82490bc95322c955f61d11cb51d5e8a58c6b3cb0fdf0419763201beea93a8512b1405245bfc384155adc5ce778aa74d00a322726465119af79501f040dd0a7a84060001ca89d2fe5e9cf9779a547e3ebd3bf8642990a3690e2b2c3e54cb7eeeeabc242b4dd99274c425a867931c929ca70808601c3908cfd788867d687dc366e976350c9e70584bd390d67eeb7cfea26c42686d3d9620f62f64104ef41ed1d130d79e325938486296b7ab2d2adb78526743e400acb2b7af09628d68cf9475101625c20e1dc051d73c997c952e12812c805b68ff:54d2fd44acf9e209bc7e433372bd73074d07806a77c6ce228e9be994418b00c7ecbcb7ac006c294aec9de668572add517c06b4eb4fe2ff3523bf043df44d3d0d12fa631b0e482e9b9d633e94b82d8ab436fe548e5b95da92624623d13f2c70da775ba136c5229c16a0c7a6fa914b2feda564e17219e47370f9515bb1d59de6e9586204d943dc560d73e2e757f7eb39bbc7111bb46bc643c13f602112739bec778d7d4f49d092563d68f5776e430e3b0bf2dc1b01beb3040196da6302908bfe91e0fc38e04c150ef907dc736c445ff21fdbd2dc1eac0a0f5d00a30af028afe2ff61162b758c7da9a776666a112359431c48856a87ca82d3dd1c8af376598635432bf891becbc33a8fda44ce883ea8af4ad8b91a9261ce76b9e939c461fac53ae0f076e82d879aace8f38f120bc9b04d8125ed24bcd779d9d24386b1dd2017ebee8197376e8c36fa3aef8c1e713e2b8bce4966d84888681ba78495fbd1d6cca58626e6854cda606b83d6293d01e8e3e13bbf4aac851d9a1e00d0024e26993b0b3091be7e8061bcbb3cbb2302ceab96897a8e1ff367ec8625693cf31534124a9d5d725bcae001d67bc2111d0ab8111fa1d24e4ed06d63583ce690f2a04626d791d29e3e315a415bf2e853a5f2974c833a3fe2e2909cf669c73c1f59392d30c37f3b9c5a3ddcfd75621fda36e4ba2f16147858f6f206b9a140f1ddc1466c9a53ed73f82490bc95322c955f61d11cb51d5e8a58c6b3cb0fdf0419763201beea93a8512b1405245bfc384155adc5ce778aa74d00a322726465119af79501f040dd0a7a84060001ca89d2fe5e9cf9779a547e3ebd3bf8642990a3690e2b2c3e54cb7eeeeabc242b4dd99274c425a867931c929ca70808601c3908cfd788867d687dc366e976350c9e70584bd390d67eeb7cfea26c42686d3d9620f62f64104ef41ed1d130d79e325938486296b7ab2d2adb78526743e400acb2b7af09628d68cf9475101625c20e1dc051d73c997c952e12812c805b68ff: +a5cab2727e2f131a4d63facee799336663930aa07afda6bd5a8e985a02deb1eaac355f95260fbfea778c55b5af8b3fd1f24d2693da35de4ee508a27ed350391f:ac355f95260fbfea778c55b5af8b3fd1f24d2693da35de4ee508a27ed350391f:483439154dd5e5d109857c24d1c4e7fbbefd2f38651da81289f2ad3d6154306538b82ac7dba9210e740776ede4ccf51d4f63094b03e46ad3aa3c31947d8c36ce6f94e85296bdedcc1ead62eaa1441ecde0a225d0bf02edcacf865014899af66d9808040c2d02000a0f5ce4f1683c1a495276d9c4d728c9ecd6f078db8a0cfc267187238562ab1a1ea2813fb4f12e878e1ba143f4d06a3bc8100c3550118d69dae67b55ed692acf9444daa5c3e3c0a98ee28cf172de0c584c9f2ec9bb6e9b57f572a86ff8729f65f4c65b7feaccaa21720ed79e90618bcafbfd9533da85232b450883aa919f827f04c4a97bf51390d4f8569c191726f44f7e39fb3db73bfc415b6ffca8b91acaad69238572f14b49985ea03c98d7b1d44b3a6554765b19abf9b25274e97e4634e4b0f9e802eb6f743fff950757ee013a6988221881a7443f1f32bccb007e99379c7ca4f906d5fe11cb12f66b53a3d21ac947be0c8150bcd04f1c816b3f0c07c5fbc0905a7136956849da03836daec25c3e1a06ec3aeb205648176f89f4a291fac4f1d3899f56c9065eebb8768b84b31b7cc03108bd0888338d1774994970292d935031fea335d9e7908fe0254889c0b171cfe0af2e6fde7a5ea3de1fdcdae537b6313119c27f772024ef36e45c8b89f26c93d9eea13725e12d810cf9824aea04cb802da7e458e842ca375e3671346e0089dec571be169b0d90966bf368fe3698fd3e72bf16249dd900af6d29ffa48351360f12241714585f7a9b4c7bafc952226735de1462743d78abad0f6711f2495f3313ad4e0ba216b0dea5dc1516a9549f7dfcfeb93e591abeda5ea3c7045906523b40868ca5735d6a3371c3c294c11126d097f4c708e90464c1ad9142fa0bedf07dfc5f4cb67d6ed80f1bfe72683cfb2ad66530dc43d7023f3790ff42d95bd8:138c7a8eca5b5c37158813843c9a904e5f530ad971ee432a44f344f8c64bbfaf102ff41daa5cf722a4bc6640588759b8f36f9c059eab936cc45ed4796394a002483439154dd5e5d109857c24d1c4e7fbbefd2f38651da81289f2ad3d6154306538b82ac7dba9210e740776ede4ccf51d4f63094b03e46ad3aa3c31947d8c36ce6f94e85296bdedcc1ead62eaa1441ecde0a225d0bf02edcacf865014899af66d9808040c2d02000a0f5ce4f1683c1a495276d9c4d728c9ecd6f078db8a0cfc267187238562ab1a1ea2813fb4f12e878e1ba143f4d06a3bc8100c3550118d69dae67b55ed692acf9444daa5c3e3c0a98ee28cf172de0c584c9f2ec9bb6e9b57f572a86ff8729f65f4c65b7feaccaa21720ed79e90618bcafbfd9533da85232b450883aa919f827f04c4a97bf51390d4f8569c191726f44f7e39fb3db73bfc415b6ffca8b91acaad69238572f14b49985ea03c98d7b1d44b3a6554765b19abf9b25274e97e4634e4b0f9e802eb6f743fff950757ee013a6988221881a7443f1f32bccb007e99379c7ca4f906d5fe11cb12f66b53a3d21ac947be0c8150bcd04f1c816b3f0c07c5fbc0905a7136956849da03836daec25c3e1a06ec3aeb205648176f89f4a291fac4f1d3899f56c9065eebb8768b84b31b7cc03108bd0888338d1774994970292d935031fea335d9e7908fe0254889c0b171cfe0af2e6fde7a5ea3de1fdcdae537b6313119c27f772024ef36e45c8b89f26c93d9eea13725e12d810cf9824aea04cb802da7e458e842ca375e3671346e0089dec571be169b0d90966bf368fe3698fd3e72bf16249dd900af6d29ffa48351360f12241714585f7a9b4c7bafc952226735de1462743d78abad0f6711f2495f3313ad4e0ba216b0dea5dc1516a9549f7dfcfeb93e591abeda5ea3c7045906523b40868ca5735d6a3371c3c294c11126d097f4c708e90464c1ad9142fa0bedf07dfc5f4cb67d6ed80f1bfe72683cfb2ad66530dc43d7023f3790ff42d95bd8: +cb6319613779a4ef66be14144b2840ad0167c03f3b8d04ff592cd1d2d722e33018eb03f0a334b080e1af4399d8376d83c533316dc687cf341f0afab450965299:18eb03f0a334b080e1af4399d8376d83c533316dc687cf341f0afab450965299:874a6c81d6db7133a79169760c84d36eea3d42ea0892b7c8dde844a3a6b60aa9f2660726c9c4dd26a01f4ed0dc1c53ba6005463f7ea64a1ec63953bc3d81052a2f1084389a7706df74ed4136082ab5c6e8c7f411df9d3a0f3c40f5a60e2d21a8548e7a25dee34030b3c3e75caa93ddaa9c190cb6deda2413d54e373d4353dba43d39491a2f56c8b36d45016f77d7471691634539e76c4fb41913472b0a23054f548f54b1e7109c8b6521b57ae981d050316a33c49c7116268dcc4b78c2bae53a3ae4dd178bb8b76bb3befe19e41a2cf12cebb71168f971f202461c63f7d6eef107f5b1030edd4e75009e9116c3cd0e8bddc299b41f1a45e784efa646dada64068e9248ec988f232634ad3d5aab19560e830a5bd665457c94295e1af0160fbce272ef4845ddf0c4f24d976f518690ea1f82ff4dfa4813641a67598ea98401e0ff10a0e582e2b90867b4e6232c34ea499c169909a44126f377d8cc1c11905866340efd1e7b077dc7456d59c9b96a124aac3b33bb227441bb7a52e6c3140d7a4f67ca05bbc93c93775b929119a224ed8f39005820f420cc6c530e61e20adca01e939cc031df49cdb1ec8ff493c9efbcad34c57108efd764558966fb1470b0745e6966191a9a9e44581b09faf469f951537203d926bc8a55d080a805181dd7296ed20a818268f755eaa66b082242f4d020f7cd6720890484c01c757fe35d87b5bc906deacc2e3071de4601bcf0dd6b837c433106047fd8ec9bd0e98c9ee806f7ec8c5a10ea2136f1f90f900b853f953f00b076bd1ebd929d08a38bec68d866435047bcb6721e06b64085dc0558c1fa85a2c83b0caf4c816084f10a4c5885295bca15ff7c18e596c62c92ee9921a27c29d195bd282213ff3660b6e7546b4eaa777ce39fc5d20484c71ed6ca06f9b77ab1d872393ab2d10255:c1b399cdc198e9a159e684fc26686de660da54cfe312ca7345df0c7d15a35743014410bd2f6cd11eef33a89b3d15cbc17c7a358937fd997205051f9257c25609874a6c81d6db7133a79169760c84d36eea3d42ea0892b7c8dde844a3a6b60aa9f2660726c9c4dd26a01f4ed0dc1c53ba6005463f7ea64a1ec63953bc3d81052a2f1084389a7706df74ed4136082ab5c6e8c7f411df9d3a0f3c40f5a60e2d21a8548e7a25dee34030b3c3e75caa93ddaa9c190cb6deda2413d54e373d4353dba43d39491a2f56c8b36d45016f77d7471691634539e76c4fb41913472b0a23054f548f54b1e7109c8b6521b57ae981d050316a33c49c7116268dcc4b78c2bae53a3ae4dd178bb8b76bb3befe19e41a2cf12cebb71168f971f202461c63f7d6eef107f5b1030edd4e75009e9116c3cd0e8bddc299b41f1a45e784efa646dada64068e9248ec988f232634ad3d5aab19560e830a5bd665457c94295e1af0160fbce272ef4845ddf0c4f24d976f518690ea1f82ff4dfa4813641a67598ea98401e0ff10a0e582e2b90867b4e6232c34ea499c169909a44126f377d8cc1c11905866340efd1e7b077dc7456d59c9b96a124aac3b33bb227441bb7a52e6c3140d7a4f67ca05bbc93c93775b929119a224ed8f39005820f420cc6c530e61e20adca01e939cc031df49cdb1ec8ff493c9efbcad34c57108efd764558966fb1470b0745e6966191a9a9e44581b09faf469f951537203d926bc8a55d080a805181dd7296ed20a818268f755eaa66b082242f4d020f7cd6720890484c01c757fe35d87b5bc906deacc2e3071de4601bcf0dd6b837c433106047fd8ec9bd0e98c9ee806f7ec8c5a10ea2136f1f90f900b853f953f00b076bd1ebd929d08a38bec68d866435047bcb6721e06b64085dc0558c1fa85a2c83b0caf4c816084f10a4c5885295bca15ff7c18e596c62c92ee9921a27c29d195bd282213ff3660b6e7546b4eaa777ce39fc5d20484c71ed6ca06f9b77ab1d872393ab2d10255: +b298adf38a6708f8d18ff1ed96bfbab421540d096c4e4351b92209b5e6aaab65770edf42b8a039c6cab9ba65ebfb135abc2da314a4c309f46a8f325b52d06593:770edf42b8a039c6cab9ba65ebfb135abc2da314a4c309f46a8f325b52d06593:9df4d5d7565d2c052262dd34d6007d86d9c0f07c7089af6119e304f4d8011d7eaad77b3ef70cc280847d59f297202b7e1861aef334bf38de14740e8073c955a851d2cf3dadc3edce15be490eaa845ba553fc6e8746e52915e655af4b86c629d4c522783635d464a2825777d89d7097677ef0e5eeae38537ecb656e3b28dd07358fd9fb2cd462517286659aefc79d374d1d13ed93967c530cdea4f314a0f91d6289b4c7a4279b6f4c4abca33357f69ed84b9119637adb7c18e694cb3c56e73637da910735d43c38aa8086675a06ad370e5726881da5e1a1dc6144d6a62aff7fb0c352d88dc971a3d72d3071e14b47425356af1b019233538261451a99a6cf4a07ce9ab1c3990de6ab8de2116c756105c512b7a3eeb3157b158b321e444e806d890b3890ed9ddc869f1711723bb99a72bdb923d131ba4edbfbb6dae99a5c7b328d310df9a6d1dcd85918962833e89e20f5c5e6333ac861094ae9e799c8641b9baea11a2e0ec234be5930e02880859cdec0d978237cbea5c7c32c111bafdd4bfbffe4fb3485effecd51bd195a71404ca5b59afa252d7b5ff9d030f48c6faadbdba918f21a0cd39af56966dccfa25fb5a5cf9a4b26a7f5441df6e320e34b27393de2ecfbd69a1594909a6c685ec645fcf3048d0148fa38d3e8a64dc3c21ae44da7e46a5ea7936c2ba083689a78ca3ac60b87be6d23ea40f5961583742842e37525a49c5fe8fd15d7b0c9e8fccd07936d19538212f7373dbbf3df7d46adf9d9f5db09524c65b883ae6f6cefa24b19ec48ce28cfa734d9bd6e77837d1a14d6a19d345bfbea559e7e6bfb71ddad83cd8deeab687fe73c057488f8f2b3e2e26d13009f4d23e6619a23c0692af76669217d5ebd46085b398890e5c91fdb4db5ba40e7773d518d3cf00c0a5b5a4b0f1b85d62916a59e5607b7b1eb80:e55f8d304122dc175cf0274674fc9dedfec2b5f8a2eeb1e3e7f8e0dfba0dac2d32f4e704ce91cd599184133c3bf1063d2fae63d73acc5772d718d811833186029df4d5d7565d2c052262dd34d6007d86d9c0f07c7089af6119e304f4d8011d7eaad77b3ef70cc280847d59f297202b7e1861aef334bf38de14740e8073c955a851d2cf3dadc3edce15be490eaa845ba553fc6e8746e52915e655af4b86c629d4c522783635d464a2825777d89d7097677ef0e5eeae38537ecb656e3b28dd07358fd9fb2cd462517286659aefc79d374d1d13ed93967c530cdea4f314a0f91d6289b4c7a4279b6f4c4abca33357f69ed84b9119637adb7c18e694cb3c56e73637da910735d43c38aa8086675a06ad370e5726881da5e1a1dc6144d6a62aff7fb0c352d88dc971a3d72d3071e14b47425356af1b019233538261451a99a6cf4a07ce9ab1c3990de6ab8de2116c756105c512b7a3eeb3157b158b321e444e806d890b3890ed9ddc869f1711723bb99a72bdb923d131ba4edbfbb6dae99a5c7b328d310df9a6d1dcd85918962833e89e20f5c5e6333ac861094ae9e799c8641b9baea11a2e0ec234be5930e02880859cdec0d978237cbea5c7c32c111bafdd4bfbffe4fb3485effecd51bd195a71404ca5b59afa252d7b5ff9d030f48c6faadbdba918f21a0cd39af56966dccfa25fb5a5cf9a4b26a7f5441df6e320e34b27393de2ecfbd69a1594909a6c685ec645fcf3048d0148fa38d3e8a64dc3c21ae44da7e46a5ea7936c2ba083689a78ca3ac60b87be6d23ea40f5961583742842e37525a49c5fe8fd15d7b0c9e8fccd07936d19538212f7373dbbf3df7d46adf9d9f5db09524c65b883ae6f6cefa24b19ec48ce28cfa734d9bd6e77837d1a14d6a19d345bfbea559e7e6bfb71ddad83cd8deeab687fe73c057488f8f2b3e2e26d13009f4d23e6619a23c0692af76669217d5ebd46085b398890e5c91fdb4db5ba40e7773d518d3cf00c0a5b5a4b0f1b85d62916a59e5607b7b1eb80: +e9cf16d696f63b59e5e25c9ee2d75bb05ed2baa591a7557f9fb129cf983de0ba6d1ae385e80a3955e8d0c593a81f431cd432671e78cdbafe83fe58dbcdb98560:6d1ae385e80a3955e8d0c593a81f431cd432671e78cdbafe83fe58dbcdb98560:a10fea8fc93eccfe2a6b7826079563adf8aa9a666444932200cca9447dd027c5c7204ea62bf8f5e2e39145ac3948ab3f3186887b30bc60233024b483f3f519036a3e94c8d7510a853ac6e20c6e526ee3cdb76de663f67305ad80df2342c8501b4f4a8ee3665a798fc437dd814e4e47e7a466890e0ffa8f510f3e6e19c9c969f70a76e5cf3054d17de459ac8ee99550bd38319f36e433434a926ad68b961e0ca10add4ba992b3650660a2c3c26f5d740a31afb7763f542f723b8a3c92d8ae92a567764efc70530312baabdd3fbbd527fe0fcbca3f6a7064cdde1856e97ab786af7d7022a9d46a338e8e1754afd9adac856a38de2a4c9766dee8dbc709b0671a6a6e6e1e5d12074d22245cd73beeeb1bd8ecfc1e85a21bde253f7c465abc1feaa961c0ff5cff2d896472ae17ab8488e33ffefdb72c105e204f944ada51ee13981a136c0f38426e3e49b0e91841c32794d52f1335dfa637f151c7e40f9b830aed539ac5731b81cde3264d22bead31a6cc68d1a73143b5ba4816139232f3f7f97983f4ecba64c49553be9d6d943f91dfe03d1ee8618cd40d2fb7238a31d1bc38e76a551f9eee22e73a27d7a48b408772ea72c3ed637bb4b168f9d7aead94ea03bc11109901c889927d51cdacf962125962559979d3e4c8e3b5ae582f2dbad4998802856c4df69e8fb54917e2f36bb67a19a26e9a9a9485bce98dbfff0d2b02b9377a9137a734e57b5ce665053017e992677a1aa079240d2cf963cdf9bfea8d460091232daf89801fd75171a6195a5c046815914be1f62868783d6f2cf28af9378d6c6893e75de641111c684727effa31b8bc9b0a01db9c9e81ccd8f4d4e875d4bd90d253f58989a8a52a203a77a496d697986b031e9f699bc6a16cd5f9c36018ebdaa36bad0e014f4cf3b4b746171bf89314e8b72cbd47cc616a:8112ac37eafb749d3f4a1ea1484379df3e383b019c12de8515e349e4f6f998632e30968347a1d15b09da2eb800b03d819d202bd10a6a463bb02b366d6855fe0ea10fea8fc93eccfe2a6b7826079563adf8aa9a666444932200cca9447dd027c5c7204ea62bf8f5e2e39145ac3948ab3f3186887b30bc60233024b483f3f519036a3e94c8d7510a853ac6e20c6e526ee3cdb76de663f67305ad80df2342c8501b4f4a8ee3665a798fc437dd814e4e47e7a466890e0ffa8f510f3e6e19c9c969f70a76e5cf3054d17de459ac8ee99550bd38319f36e433434a926ad68b961e0ca10add4ba992b3650660a2c3c26f5d740a31afb7763f542f723b8a3c92d8ae92a567764efc70530312baabdd3fbbd527fe0fcbca3f6a7064cdde1856e97ab786af7d7022a9d46a338e8e1754afd9adac856a38de2a4c9766dee8dbc709b0671a6a6e6e1e5d12074d22245cd73beeeb1bd8ecfc1e85a21bde253f7c465abc1feaa961c0ff5cff2d896472ae17ab8488e33ffefdb72c105e204f944ada51ee13981a136c0f38426e3e49b0e91841c32794d52f1335dfa637f151c7e40f9b830aed539ac5731b81cde3264d22bead31a6cc68d1a73143b5ba4816139232f3f7f97983f4ecba64c49553be9d6d943f91dfe03d1ee8618cd40d2fb7238a31d1bc38e76a551f9eee22e73a27d7a48b408772ea72c3ed637bb4b168f9d7aead94ea03bc11109901c889927d51cdacf962125962559979d3e4c8e3b5ae582f2dbad4998802856c4df69e8fb54917e2f36bb67a19a26e9a9a9485bce98dbfff0d2b02b9377a9137a734e57b5ce665053017e992677a1aa079240d2cf963cdf9bfea8d460091232daf89801fd75171a6195a5c046815914be1f62868783d6f2cf28af9378d6c6893e75de641111c684727effa31b8bc9b0a01db9c9e81ccd8f4d4e875d4bd90d253f58989a8a52a203a77a496d697986b031e9f699bc6a16cd5f9c36018ebdaa36bad0e014f4cf3b4b746171bf89314e8b72cbd47cc616a: +238a6d4979321a14a997236f4585046cf7a05c0adc6ba1fdb19ec2a32f62beeb0b4ba674e401665b6790cfda080704cd90e2f3d3efab253ed8dcfbd18e406789:0b4ba674e401665b6790cfda080704cd90e2f3d3efab253ed8dcfbd18e406789:97cd619a2251eda916646431d4cd1598c2d44d06af3e48bd18e3de7fb4bd4f78e00a69eeabde3f82065cfee6cd711f07d22637161ff685f65a7ddf54553197fd31c5c6b71d9e365a941dce4c3e225d19cc633a7e12862cd23ebb7c74a704850f761ac0241be517ce7c360936ce07250d9f2eb2787115eec377e1134dc08f44eb0a2a2a2716f00144a49f012a57b3cd06efeb3fae920f285cffd9a401a0b986594e17b2c9c8fdab835d9f3f5d474be733c1925ee6f09386711066c3fcd645eeb0fbe7054169eb709d4a3f0d16f28a1ff5066c842bc63e359e92485b38757ff46c27f79d0cdcf0e16e97e3c7b7e2178dffd270282dd61205d5854d841f0e3fc0e482cc1ee48552cfe658935b5427c366230aef79aef4021d6fab5f1875cc849e321a75500e9e1ba5dd596b438cf88b235b01a67625c4bf84d0724ae6880a3785e33bd9235fd0f5981804d21cbd633cb180f34456460207a290a254d9fe61063d40634ca3872f0935fa28328795ca41b006a2111fc5932b1e779ce966cc47adb7c0dd987333ba7529a1a4996ce9f56e051981fe1f553e578f43c3ba94beacc93c3e739667c7a7c6fa27e1e081695d20ba705c3f10b20df530cbb0ecb87456501109687019318452785d38e766b3cd35b007d7e3cfe0b2cca8aa6ef7395599dcb9c4d28bcc35c76dfc35343cb1348ba3e962f10ee86f86f5b6d4cae2e8c2b185e3eaa1aeb87bcfcf2fb76cc7fcc6895071b168e8b7f6caa0fd6398e778cc07912ff5d6e61021a8a59ae0352160f56d5488fe2f2acc9403da9a9ffc661c1e9dc5be88c420db0fd77d845dc8dd9d8e58f9961b79afc68624baa86aa643a8a3c7edf71d553cc0d3224a6069ec674f52da29a1cb60c4192301a24347a8aa8326269e0a14780c9583cdff515927fd5bef528f9d23787aeb803d70eb916b:2942f708c0ede4cb0ddef13b85d71d7213e0383dd294f534135fd69cafbcfc0e33090a2a0ca3fa572c72cdf5592de903b1584495ab63998150f2b393a3b3400c97cd619a2251eda916646431d4cd1598c2d44d06af3e48bd18e3de7fb4bd4f78e00a69eeabde3f82065cfee6cd711f07d22637161ff685f65a7ddf54553197fd31c5c6b71d9e365a941dce4c3e225d19cc633a7e12862cd23ebb7c74a704850f761ac0241be517ce7c360936ce07250d9f2eb2787115eec377e1134dc08f44eb0a2a2a2716f00144a49f012a57b3cd06efeb3fae920f285cffd9a401a0b986594e17b2c9c8fdab835d9f3f5d474be733c1925ee6f09386711066c3fcd645eeb0fbe7054169eb709d4a3f0d16f28a1ff5066c842bc63e359e92485b38757ff46c27f79d0cdcf0e16e97e3c7b7e2178dffd270282dd61205d5854d841f0e3fc0e482cc1ee48552cfe658935b5427c366230aef79aef4021d6fab5f1875cc849e321a75500e9e1ba5dd596b438cf88b235b01a67625c4bf84d0724ae6880a3785e33bd9235fd0f5981804d21cbd633cb180f34456460207a290a254d9fe61063d40634ca3872f0935fa28328795ca41b006a2111fc5932b1e779ce966cc47adb7c0dd987333ba7529a1a4996ce9f56e051981fe1f553e578f43c3ba94beacc93c3e739667c7a7c6fa27e1e081695d20ba705c3f10b20df530cbb0ecb87456501109687019318452785d38e766b3cd35b007d7e3cfe0b2cca8aa6ef7395599dcb9c4d28bcc35c76dfc35343cb1348ba3e962f10ee86f86f5b6d4cae2e8c2b185e3eaa1aeb87bcfcf2fb76cc7fcc6895071b168e8b7f6caa0fd6398e778cc07912ff5d6e61021a8a59ae0352160f56d5488fe2f2acc9403da9a9ffc661c1e9dc5be88c420db0fd77d845dc8dd9d8e58f9961b79afc68624baa86aa643a8a3c7edf71d553cc0d3224a6069ec674f52da29a1cb60c4192301a24347a8aa8326269e0a14780c9583cdff515927fd5bef528f9d23787aeb803d70eb916b: +59d501393dc5999723810706fad7d6efd163c44710c741c185c27e0425e3c05b8265d43cfb0735b5d7250fcf0fcbd154bfc0eecb13b7ad93b6b02940588b843b:8265d43cfb0735b5d7250fcf0fcbd154bfc0eecb13b7ad93b6b02940588b843b:564ed22c172f5c3afbb0b95ad2fc64e4be6d4db1ebb8d399c43a5e16048e7f8732181e5d0eed8e638ef2a55aa0d7b681fe02bb5423af94bd352d3c2ddec0f84760a4112b4fe017cfbc502f9543cfa41fb2aae75a3a081f8c499033d1fae5d9c50cb44dbc63605a54398fbf079852eba86f2fdfc272d0c4179d7c13cbc1c2a3da0b82845cf1a46ebbe31e79b6009733c7bfe7aa4f9ffd719c77dc7d748e492e14ee5e4179bfa9e649cf0d89534186385ee99410051d6656e623438cc7b2e707e48c84915549ae8d67a306c67b106b7a25f45f8e10dd7dd3eaac31f1052257eb6a7576b685cb9e6c1cd0d73c7a3ced5a8dd27308ae00f95eabdae9d1c4aa8934e2424c9328a5228f4f82dd4a66556d8217c5a22b2beb86a2a43413ee5e10f883f2cd6c2e8749b5508842ecae5ffccb796d9633e87ef4a96c0df7ef47b283d096723ba3135bad75b2e19ec04f70a478428ad5d0aac0dd2ab9905913e7e5ade408801d5d3c54d9cf7b8f0f0c5eb054c1475cc210a2c798d8bd89932ff9f360421858053a707b8bbd32055c44b20712a2678a9a6af9e36d04dcff44f431cf1930cd18fc935d2267775c69096725ed89a291dd60e21ac0b0128734072992823ef87b5efa6cc5b050177f55f4cec92a08a65bcadcab9a41c36086370b7b9dd6298ac7b0ae6a09c9710abb4676a8fc87a3651290144b6b30ef4f6fbe5b9ad25237fe0605e3b9f18a7718ac9fca6f325ea55f49a807fb80a2402ae13423080d327758649023798d5728e0dc64ac88a6e2945dbb3e3ffa9fdb4c7b58fba3f5fbd67c686b2971bbd8ba4d275d573eb796eb9146775d8cdcd5fd3eb5a88ea5a930ec3244e6a37c81f6a2554e5ba787f0e45319fe4b8a2ffbfed50770e7827b3e7bc2b44ce512ae6051b6f9f13931ea6acc096b8dcb0196be422484db5fcb299d:e646f164cfed8c2e060710dcfbc3e9fa5eb396376813190184e346f52bb0ba5746ccb6b59522b1aff9830f2f98b9e5dafcd832077883c44e8a35388f718bf40c564ed22c172f5c3afbb0b95ad2fc64e4be6d4db1ebb8d399c43a5e16048e7f8732181e5d0eed8e638ef2a55aa0d7b681fe02bb5423af94bd352d3c2ddec0f84760a4112b4fe017cfbc502f9543cfa41fb2aae75a3a081f8c499033d1fae5d9c50cb44dbc63605a54398fbf079852eba86f2fdfc272d0c4179d7c13cbc1c2a3da0b82845cf1a46ebbe31e79b6009733c7bfe7aa4f9ffd719c77dc7d748e492e14ee5e4179bfa9e649cf0d89534186385ee99410051d6656e623438cc7b2e707e48c84915549ae8d67a306c67b106b7a25f45f8e10dd7dd3eaac31f1052257eb6a7576b685cb9e6c1cd0d73c7a3ced5a8dd27308ae00f95eabdae9d1c4aa8934e2424c9328a5228f4f82dd4a66556d8217c5a22b2beb86a2a43413ee5e10f883f2cd6c2e8749b5508842ecae5ffccb796d9633e87ef4a96c0df7ef47b283d096723ba3135bad75b2e19ec04f70a478428ad5d0aac0dd2ab9905913e7e5ade408801d5d3c54d9cf7b8f0f0c5eb054c1475cc210a2c798d8bd89932ff9f360421858053a707b8bbd32055c44b20712a2678a9a6af9e36d04dcff44f431cf1930cd18fc935d2267775c69096725ed89a291dd60e21ac0b0128734072992823ef87b5efa6cc5b050177f55f4cec92a08a65bcadcab9a41c36086370b7b9dd6298ac7b0ae6a09c9710abb4676a8fc87a3651290144b6b30ef4f6fbe5b9ad25237fe0605e3b9f18a7718ac9fca6f325ea55f49a807fb80a2402ae13423080d327758649023798d5728e0dc64ac88a6e2945dbb3e3ffa9fdb4c7b58fba3f5fbd67c686b2971bbd8ba4d275d573eb796eb9146775d8cdcd5fd3eb5a88ea5a930ec3244e6a37c81f6a2554e5ba787f0e45319fe4b8a2ffbfed50770e7827b3e7bc2b44ce512ae6051b6f9f13931ea6acc096b8dcb0196be422484db5fcb299d: +839fb132e69250ca1ad94510087f92ce068769213a19b2a6c89490f1f578807aeb586619b44a15379acc4621a2ac71ea58970026c28e2409fc1ba2bd8b236d1d:eb586619b44a15379acc4621a2ac71ea58970026c28e2409fc1ba2bd8b236d1d:c57232fe32f11e894b437d40456207cc306db48169b20e0781103affe802f5aabe8582952ca8e95745e9940d535e00ff65ab3c64bed3d1173a0f3d70ce4ebe2b50d048bb47164d2a2cd9d95a10cf0d073ed1c41b3de333528ee32968223a0d847cadbb5b69f382164e9a28d23ec9bde9a828e8771c9eb49220af54185508aa073a839195f103bc2f32fe04f951ca45bfbf30d2fb8114056a736addf27ecd9af0f6e5e97e5773c4fa902268c32a151410955f3c76aae255549e0f033f89e1a78f265cbab6beb7516d4badc49cda4588316225b4c85ea9fa99c7d6766e9490c49de59da717f667653530071dd2f0c53e31d8768156feb08faf00db0a04533df97957a84aa46aeb7e36c0b0be69018946f1538a6aea71df536f1442c2444a43a043d046abde1a782b0f4f5c6aa720aa60afed947c0cee477dbec00557b37212d93357ca2b6b6f82715ba0e484f6daf2d0b7a98c033519ce38263586796d5d31cb2bc3d1125bc0ccd329a5c21fd27a218ded607a0e7515b571f192c33f5fba514afe4d458100f3ccba3f38eb430b4fc88faef999fa71eee488228903be29f24df81dc911044e924cdaa017cc7d87e56a6cba8760859bd63dd2d4f581b955ec924a49afb47ca0d63e7826fdc712b4943b739e1857755a33c6503675fddeae062706e34f744fd932648a5608ce608a61995783f3339ca3fe107e1972744bf6d4edafbf47ce021e05821fb124c7083930e68e6f5c32d2d9fc4a884c0bc88404e4cfe3c1a2420d41823a385fb3288db65c89545f6e73f0d8004b2ba12a4e07727523ef085670daffaf41c28a4c1157bdd245e68750dd200e023af90c67561e0fe4ba340c433f755eefabd4b039bfc323dc11adb75aecc448a869c7f2a58b9d8617c64b8f89fc583f8c948e2df0251a6c7d8c738c3b5a42b749ad5e8e986bd8:66437b6bc05e75dd1626c3c4ff1f72e6db381ba1590948f8f16ad4d66e5991659aa84405568cfbc0a77c025e59e43fd53ab9ffabba7b258f78796239f90d4501c57232fe32f11e894b437d40456207cc306db48169b20e0781103affe802f5aabe8582952ca8e95745e9940d535e00ff65ab3c64bed3d1173a0f3d70ce4ebe2b50d048bb47164d2a2cd9d95a10cf0d073ed1c41b3de333528ee32968223a0d847cadbb5b69f382164e9a28d23ec9bde9a828e8771c9eb49220af54185508aa073a839195f103bc2f32fe04f951ca45bfbf30d2fb8114056a736addf27ecd9af0f6e5e97e5773c4fa902268c32a151410955f3c76aae255549e0f033f89e1a78f265cbab6beb7516d4badc49cda4588316225b4c85ea9fa99c7d6766e9490c49de59da717f667653530071dd2f0c53e31d8768156feb08faf00db0a04533df97957a84aa46aeb7e36c0b0be69018946f1538a6aea71df536f1442c2444a43a043d046abde1a782b0f4f5c6aa720aa60afed947c0cee477dbec00557b37212d93357ca2b6b6f82715ba0e484f6daf2d0b7a98c033519ce38263586796d5d31cb2bc3d1125bc0ccd329a5c21fd27a218ded607a0e7515b571f192c33f5fba514afe4d458100f3ccba3f38eb430b4fc88faef999fa71eee488228903be29f24df81dc911044e924cdaa017cc7d87e56a6cba8760859bd63dd2d4f581b955ec924a49afb47ca0d63e7826fdc712b4943b739e1857755a33c6503675fddeae062706e34f744fd932648a5608ce608a61995783f3339ca3fe107e1972744bf6d4edafbf47ce021e05821fb124c7083930e68e6f5c32d2d9fc4a884c0bc88404e4cfe3c1a2420d41823a385fb3288db65c89545f6e73f0d8004b2ba12a4e07727523ef085670daffaf41c28a4c1157bdd245e68750dd200e023af90c67561e0fe4ba340c433f755eefabd4b039bfc323dc11adb75aecc448a869c7f2a58b9d8617c64b8f89fc583f8c948e2df0251a6c7d8c738c3b5a42b749ad5e8e986bd8: +adc1e56c3ac94e6cda0411cbc3ce2af128d185a2a273bdb2af8d7e50fb96b5265dcfec1f9112751564ecb60715ebb2c517b5ec37b2534fd6329924429b7fd5c5:5dcfec1f9112751564ecb60715ebb2c517b5ec37b2534fd6329924429b7fd5c5:d4f959474e0b89e2dcd02066984f88d739dd1134a33309f0a8b7802eaf013303c13515dfeb461ea3d248e998b9a4e54dae5b00190a45e70dc67e98f3d4cf906c214d4f636d2952925e22b1a86a1aabb3a892a9f8ed454f39c63d35b71e87a2da55a8e167ac83a866ad167a17aed183c08518c15e6be34858b4cee2b8427314760fffddd5923854b1747f796e1a5249fb3044894ed646829f654316ee52f4010c8dd321fa1dec397e50145ed9e31686fd5203f7233b8da780acaa91ee0b5b47207866aad85f837e03b4e6f6de8c04acafd707bdc1dd45500ab564801bee9a58ece360d004828baaf523e2f5ab69326a03aabe010878fd43ffaa56872244d7681f1618e623e3d474c73af8b080a61821a574ef2fd752d23b605ec521c19c1550de980c094d05e0238f3e008e6b195abfdd4028ee1ee1d6c66a76f178f0b431e4af44ddccfc5290edff36ece63e8385567013f43a2aebb67e3ef406308c20488a76d58a214f3139d983b19afb12e3283607fd75107bd31feb6256174b7a18aecac9f8562582018b0e6de40535e35bef2b562553885129397562900d3417f98cdd1e29d731ff48933f2952958163ba67d59561811b83772bd05710b6e3cc0434609937507223abb71a6a8c838fecdb1d2d37c95dc806f65f3f9663d99f06e6c0f3c32e95af1dd708e81108636a26b968e98339c74128b6cf671335884ac72f75b637195ea9eca053608996c32ed445410f67fa104b39f0fdf3c9b5c6157b76803756b27f4c3ba1b47f328576248e9bc53e7b8ab0b2ed97c2f9998bcc7dfe39e264aad30c6cfef2b5553ffb5a699aa4bd0eabe438ce0522cc91fe4e72bf7eacba4771ccf63a37aafcadbfbf99dd76b85b80ee075d3a7d1a90a55b7729a5416e5be696bf9fb7f3158cfdb5cfdacdde8172ee1ab9486e24ccead29b457acf43:f02e5dbcb68704afad03aca81061dbdb998570049f10ce650ec7a2eff15c793ddf5a272cb683c22c87257c59bdef39efea79bd679556ea1505ed0036cb46040cd4f959474e0b89e2dcd02066984f88d739dd1134a33309f0a8b7802eaf013303c13515dfeb461ea3d248e998b9a4e54dae5b00190a45e70dc67e98f3d4cf906c214d4f636d2952925e22b1a86a1aabb3a892a9f8ed454f39c63d35b71e87a2da55a8e167ac83a866ad167a17aed183c08518c15e6be34858b4cee2b8427314760fffddd5923854b1747f796e1a5249fb3044894ed646829f654316ee52f4010c8dd321fa1dec397e50145ed9e31686fd5203f7233b8da780acaa91ee0b5b47207866aad85f837e03b4e6f6de8c04acafd707bdc1dd45500ab564801bee9a58ece360d004828baaf523e2f5ab69326a03aabe010878fd43ffaa56872244d7681f1618e623e3d474c73af8b080a61821a574ef2fd752d23b605ec521c19c1550de980c094d05e0238f3e008e6b195abfdd4028ee1ee1d6c66a76f178f0b431e4af44ddccfc5290edff36ece63e8385567013f43a2aebb67e3ef406308c20488a76d58a214f3139d983b19afb12e3283607fd75107bd31feb6256174b7a18aecac9f8562582018b0e6de40535e35bef2b562553885129397562900d3417f98cdd1e29d731ff48933f2952958163ba67d59561811b83772bd05710b6e3cc0434609937507223abb71a6a8c838fecdb1d2d37c95dc806f65f3f9663d99f06e6c0f3c32e95af1dd708e81108636a26b968e98339c74128b6cf671335884ac72f75b637195ea9eca053608996c32ed445410f67fa104b39f0fdf3c9b5c6157b76803756b27f4c3ba1b47f328576248e9bc53e7b8ab0b2ed97c2f9998bcc7dfe39e264aad30c6cfef2b5553ffb5a699aa4bd0eabe438ce0522cc91fe4e72bf7eacba4771ccf63a37aafcadbfbf99dd76b85b80ee075d3a7d1a90a55b7729a5416e5be696bf9fb7f3158cfdb5cfdacdde8172ee1ab9486e24ccead29b457acf43: +db89df6a23d890b7f00260e81f4ad98fd09440365131e85e22c7951a187b0218c96763672ee4a2cc5a93b6a683df9b5de4d9386a790835681d1217d19296bdc8:c96763672ee4a2cc5a93b6a683df9b5de4d9386a790835681d1217d19296bdc8:54c1c5111e08c98245ba4f1318ba1db1dcc74d14a5c98ab9689cba1c802c68bcfc81fd87ffc61caa942f66d7e5157f65538c7e7b33170484b4b6543f3620ff29638b64d4dae7b02221cf7783f187ec4231e6b6946d82762074f09c32781c2f3846de3e8217f6e1b6e0d2b5595d742e2c4e325a2841924044dfcf12b479eb69f1bbd40eabddd1ff54a9184d366dff9d8f2d863e378a41f10cd1dae922cd7fbb2a544e47eabf47ca0a38abba34454919bb9a4ef044bfb97b708c2f7428d68f9c57c0ee7e7925f7a2b5c6e7df82bb2680c862dc7cc68b0f54530e64afe2763d9c7baf45cc6fe612d1f7827739c4411398888f7367c3d4377907acc06a06f93f887226798f48aa5464f601c2c1edda77edfeb9b9b5d5f9cb6fed37900547477fca1d09ab52d63e491feb12fd6dc805a78cee3baade4352982061dea5a2653db8e7607772e834b3a505c16dd6e7c71b911e842eba925d77a33c5c57ce1184098078ca2e6a3f69aa6a14639dc97b4b30c99dc4fa3e2cf63c701c306c5e253c5113854c185ebc8b4798f68d1fd780054d3eed2f394c454304966bddbd12280834ec9b40c1e98bc2d98f4845f6eb44f25315eedb3b79ffca4180c1bddd97d0c9affbac58814937682680076fe5a3babb65d28f2517036c0cfb42f0293eb2acb13949fe91e0ad0678aa243d7734a89d997870bf9a6a584ed6e628163e39d8aa610d46b9285b9e1dd7e8f807fdf5ca2bbf6de5e5e68af7cb7ebd43ecce227cd70c7bf4ee1433edfcfe886614670cdd196343fb91e15416d2f6acbae3eadc030231ee9d2ecc52a88ce8dc7d098e7fac77685b4eb540e3019307143221b8ef77f3632c893d556e0bb743a1963ec15886c8545e87c95cc825f200d0f3cf4f55a3d660a536a23aefcc428a43203485ee84342f5c001ee8404e759017006282ab8ba8903e:80b7fc8b6ae6eece8166b7ea534cb5b214c9ea9973921ed05de40c78e14f162b09e978ca6d86ee434d984b8b0070409dd2ad11b53178e239dab5bc39c7ba460d54c1c5111e08c98245ba4f1318ba1db1dcc74d14a5c98ab9689cba1c802c68bcfc81fd87ffc61caa942f66d7e5157f65538c7e7b33170484b4b6543f3620ff29638b64d4dae7b02221cf7783f187ec4231e6b6946d82762074f09c32781c2f3846de3e8217f6e1b6e0d2b5595d742e2c4e325a2841924044dfcf12b479eb69f1bbd40eabddd1ff54a9184d366dff9d8f2d863e378a41f10cd1dae922cd7fbb2a544e47eabf47ca0a38abba34454919bb9a4ef044bfb97b708c2f7428d68f9c57c0ee7e7925f7a2b5c6e7df82bb2680c862dc7cc68b0f54530e64afe2763d9c7baf45cc6fe612d1f7827739c4411398888f7367c3d4377907acc06a06f93f887226798f48aa5464f601c2c1edda77edfeb9b9b5d5f9cb6fed37900547477fca1d09ab52d63e491feb12fd6dc805a78cee3baade4352982061dea5a2653db8e7607772e834b3a505c16dd6e7c71b911e842eba925d77a33c5c57ce1184098078ca2e6a3f69aa6a14639dc97b4b30c99dc4fa3e2cf63c701c306c5e253c5113854c185ebc8b4798f68d1fd780054d3eed2f394c454304966bddbd12280834ec9b40c1e98bc2d98f4845f6eb44f25315eedb3b79ffca4180c1bddd97d0c9affbac58814937682680076fe5a3babb65d28f2517036c0cfb42f0293eb2acb13949fe91e0ad0678aa243d7734a89d997870bf9a6a584ed6e628163e39d8aa610d46b9285b9e1dd7e8f807fdf5ca2bbf6de5e5e68af7cb7ebd43ecce227cd70c7bf4ee1433edfcfe886614670cdd196343fb91e15416d2f6acbae3eadc030231ee9d2ecc52a88ce8dc7d098e7fac77685b4eb540e3019307143221b8ef77f3632c893d556e0bb743a1963ec15886c8545e87c95cc825f200d0f3cf4f55a3d660a536a23aefcc428a43203485ee84342f5c001ee8404e759017006282ab8ba8903e: +00e6bb17af3c2df652b34f9abe19f99019074233686c7114e3a0edf08309934f7b8232a66cec2f915aaa7951d29d2b9ee93d321d15b203c51e61e8ce83d187f8:7b8232a66cec2f915aaa7951d29d2b9ee93d321d15b203c51e61e8ce83d187f8:063281e41e8ba9703ed09ef3bf0ea46e4cabdd6ebd769d05dc045d4f990d69fc554130a4e61aa21e2de4c92db48a20a37b1747a7eac5ebb2735a8938197f139fad1497b351ad064c0f18f8faf1fe11f63979a69968e24cf91e58a3ab032669e4efee274f96b58be7d9e391f36fcf0709b2cb2d22694a6ceb17246945ebb3bc7f0f03bf0b08dc9626e3e715c991671d53ebb9ae83a7d08d44f63635c40f8d4817f58de9eb77cb25b2acd6def969ab569e974a8adac11a86b58fe6c10067499fc914dff56902cbc393a71cc25e8f05c03c94f13b84a2b01a58c10dbcbb60ebcee487f529177466299925da50e2da5b5557f0aeee3fd7f47b5c2e3f84cefab4679691394dd122303bb769afb3adfe8358b02b679273b35abdc6402576ccce5e10442a137ef9456939b289ef4e417b1cc6239f7ceedd68f1a8264180e068b4966fd67f2bad6edd8b4a1e8d2b542daf26db831f1fb51eb86ffadeccd9ac3d664f346e7d046c33a572841ea8334e7f2f417a05712a9e334e487fd3ae175455162fe8f49cc026a640c6cf93cf58875052f41cc9820615653ea2d084c896eafe5ad4725579653084994f956d5c94590a2409581b6fc86e40aa58bf6e6057a6f90af3b87aeaf32994a55a54f79bdf3dbbf5ce0ff812e486b0545d9e9c2b0bce0d4c3647b1827262498834e198a3ec70f3b03d6aad2c49eb80b5e2051439225fd9ce9468d69af70a262ee3b8b62a8e5b41346da3012ffb45816b7becb0e79a60bff71636a3e4bb1b35caf195f55117280f787217b3caa2e793726fc5a74d1160dcad868904c197381134ed8c3db3750b7556f69ccce18b77388b58c5b8113e590ad6eac5b91ece5a6705025c80353ceb1ed84aaa1cc48a416bc016aef173bb80b2ba28c57960c6b011b6b495a3f3311e79fe46bdb6a4c381fb9dc4628b0a83023558f1:04b3b8501e396c4a788e14ac49f6174cdb5c855e651203cf68d1efa89aa58678d4d1f303a9877a3786d203c355b09d5286c1ca0df04a89aa06cc3f9d0fd30504063281e41e8ba9703ed09ef3bf0ea46e4cabdd6ebd769d05dc045d4f990d69fc554130a4e61aa21e2de4c92db48a20a37b1747a7eac5ebb2735a8938197f139fad1497b351ad064c0f18f8faf1fe11f63979a69968e24cf91e58a3ab032669e4efee274f96b58be7d9e391f36fcf0709b2cb2d22694a6ceb17246945ebb3bc7f0f03bf0b08dc9626e3e715c991671d53ebb9ae83a7d08d44f63635c40f8d4817f58de9eb77cb25b2acd6def969ab569e974a8adac11a86b58fe6c10067499fc914dff56902cbc393a71cc25e8f05c03c94f13b84a2b01a58c10dbcbb60ebcee487f529177466299925da50e2da5b5557f0aeee3fd7f47b5c2e3f84cefab4679691394dd122303bb769afb3adfe8358b02b679273b35abdc6402576ccce5e10442a137ef9456939b289ef4e417b1cc6239f7ceedd68f1a8264180e068b4966fd67f2bad6edd8b4a1e8d2b542daf26db831f1fb51eb86ffadeccd9ac3d664f346e7d046c33a572841ea8334e7f2f417a05712a9e334e487fd3ae175455162fe8f49cc026a640c6cf93cf58875052f41cc9820615653ea2d084c896eafe5ad4725579653084994f956d5c94590a2409581b6fc86e40aa58bf6e6057a6f90af3b87aeaf32994a55a54f79bdf3dbbf5ce0ff812e486b0545d9e9c2b0bce0d4c3647b1827262498834e198a3ec70f3b03d6aad2c49eb80b5e2051439225fd9ce9468d69af70a262ee3b8b62a8e5b41346da3012ffb45816b7becb0e79a60bff71636a3e4bb1b35caf195f55117280f787217b3caa2e793726fc5a74d1160dcad868904c197381134ed8c3db3750b7556f69ccce18b77388b58c5b8113e590ad6eac5b91ece5a6705025c80353ceb1ed84aaa1cc48a416bc016aef173bb80b2ba28c57960c6b011b6b495a3f3311e79fe46bdb6a4c381fb9dc4628b0a83023558f1: +fbddf6e61e20d806e55917756de60d0c9a99976f646716ff2ff1312c54dd971dac538fabad4380e60e977126e7695eeda5417d85f7d23db21bd0ad111116f05d:ac538fabad4380e60e977126e7695eeda5417d85f7d23db21bd0ad111116f05d:3e9953ca55d0cd233b98833eb1bc79d3b55f18c8fa1c42027bca25579153b55da0c5a178b8386956d9a54183b24c91dc4be994847237d3666a0a0130fe19924bc0ee50896c35a2e16a29e2e2acf180bdd9379354687f0ece6882d26e980e686698043bb1b01213aa644a4f8d61f9b613e62eaa3576cea0b0b83f05ce2558ff6356495c45ede4a8f65b814ab8a7309403dfd43cbea90893939b7800aa00232b5f6b7714ebdcd8bcf34a5a7e822ac7b1b099ac615f135f8c351dc41ae5f66d5f9c2600454ca01c009ba6de04162ae5f1f270893ca3907aff7f78e03396e32b622ff340537bf123e55995e9209609330b2eee51127484a40e250700823feb0bc97bb509ff732675dec32ecb635ed92c7d78fe3050200cf1d941d6b388800a8419d96a595eced5ec4efdcb6f987f5472a5c43058d3a3a7bb56d7980365ed43dbc2be48f1d18ce76a89185426fd5c69df7e9291ab7823c23a76941ed3836aac7b58c0d5fb6b636c42471a4d1703516f03e935f31f195450e537b2a07d545ba4b68afb0638c65bb0ffaa0cfd69d7104819796619d483a0245b4fd9017f62a7d3a5fc3b7289d75735f287ca0a951ad58344b2ab7d7df8dbd7922a5abb8d7c2e79147e6d36ee31f930473b0727dcfd58d644d7d70a0ed31ca6a13ed9dbd224492efda19e4f8eed46180fe750f07bbe8e99854d13f58ba968ce3859d61189cd2b667f3b2d0665b574c4bac19d9e37e5b7a80eb334e36810530aa5d1766393f8115a52090c91823428c897a5f35e12a8af2cd4fb13907ca6603a4f76f5c2e02374a8dc3a47c1be6f1d1c8ebc59b36d1cfa0ab23e9b0ae9b0e637eeedb9c66bea62dc630cdefa718239617e3118e5b6deb7c294475282e8abe24fd5a54b786fff9028c5a033384e4bc8014dec8da100a94b178ef88ec357b66d2b9098ab64791696b1a66b:8c9b77aa0f1cf52e8f7a918b21b468e62335911bc59306b30ce77bf692c11059b0ee9c5daaf6839bb81373c61d28d072702b595e4dce28cb993822b24813040b3e9953ca55d0cd233b98833eb1bc79d3b55f18c8fa1c42027bca25579153b55da0c5a178b8386956d9a54183b24c91dc4be994847237d3666a0a0130fe19924bc0ee50896c35a2e16a29e2e2acf180bdd9379354687f0ece6882d26e980e686698043bb1b01213aa644a4f8d61f9b613e62eaa3576cea0b0b83f05ce2558ff6356495c45ede4a8f65b814ab8a7309403dfd43cbea90893939b7800aa00232b5f6b7714ebdcd8bcf34a5a7e822ac7b1b099ac615f135f8c351dc41ae5f66d5f9c2600454ca01c009ba6de04162ae5f1f270893ca3907aff7f78e03396e32b622ff340537bf123e55995e9209609330b2eee51127484a40e250700823feb0bc97bb509ff732675dec32ecb635ed92c7d78fe3050200cf1d941d6b388800a8419d96a595eced5ec4efdcb6f987f5472a5c43058d3a3a7bb56d7980365ed43dbc2be48f1d18ce76a89185426fd5c69df7e9291ab7823c23a76941ed3836aac7b58c0d5fb6b636c42471a4d1703516f03e935f31f195450e537b2a07d545ba4b68afb0638c65bb0ffaa0cfd69d7104819796619d483a0245b4fd9017f62a7d3a5fc3b7289d75735f287ca0a951ad58344b2ab7d7df8dbd7922a5abb8d7c2e79147e6d36ee31f930473b0727dcfd58d644d7d70a0ed31ca6a13ed9dbd224492efda19e4f8eed46180fe750f07bbe8e99854d13f58ba968ce3859d61189cd2b667f3b2d0665b574c4bac19d9e37e5b7a80eb334e36810530aa5d1766393f8115a52090c91823428c897a5f35e12a8af2cd4fb13907ca6603a4f76f5c2e02374a8dc3a47c1be6f1d1c8ebc59b36d1cfa0ab23e9b0ae9b0e637eeedb9c66bea62dc630cdefa718239617e3118e5b6deb7c294475282e8abe24fd5a54b786fff9028c5a033384e4bc8014dec8da100a94b178ef88ec357b66d2b9098ab64791696b1a66b: +8a55e77bb0c8740b8c2e8ddfdfdb40f27e45fe81fe457111bf1c8730eab616b49ff1fd0c50eb24f99fe2f7711d52872dfc900380dddcdb86fe6f4a5f350a8743:9ff1fd0c50eb24f99fe2f7711d52872dfc900380dddcdb86fe6f4a5f350a8743:20fb414e264a954784f112bace7e0474b39cb3c9e53dee0a21f4cf6d4a99b9347ddffbe281a6c230a75d63a72fd05f6db53ea7014ef7709d18ff970f485fe83ba1d37147338aded6da4cfdacc1e69d2f3e0ef362f47b5bcfb78a1e179eb5c5b106c8d82a0a0b290df075ab27436929cde656f02309f95750eb676583262e5f2f69f0ff72a8e057266382269205318740bfe06bf5c2cb4533908ef9f9f2869a75b9533579820e3bc0caffd646171c8286c3a4aba1ff0915d93611205e230f39ff4c4caf3f333e753fce2b71213e53d608415ee17fd48212eedd8840f337101ef0d0b6f7be4bffc06eeefe8066dd27a0541a468831acddc4902e2fefefbed19c308e5621e0bf46bcd538aa13faf04d380759c0e107e912001839dfd0b635440e9638f5377ca8450f350c01129ee33764415c53cb2ffbf968df78b742fd0665e78a34abf4decd1fd386289a1364e64555eec58b0af9a4cd6b36d1d5c611a2846dfb5589344bbbb02560241b74b993a25bef50fb1e7319086e6a23986300834ed2dba98a168721c2f784dfb8d3800d06a054aef14d1772b6c574af2563d193ef2e51bdc62d2abce2eebeada79203498e6686c287f37bd88aeb166f7dffc3e6ad0294117ef6ee9da8479ed8a16fe9be246d266804f29658db75e7a0873be71dc7d407e39fabd66f988b457477427fad8130f09ab665f1597c9046e7373af9a8352a86830cb92a804488700fe6891924fe2a7201733d95e591ee0a1fef1c2636078d370e7ad3b6a944fed2cf2b30aba2d56f3495b2849c03bb614f48bc4e507c395a6c35d3eed4c7be8e680f2d45a310b187eb88cf0e8ed4de7d37246a50a6367b97ee3784322c0b71131a283198da4804de751dcf70c4bad00dd98d873a69dd1a09cf69ddfad7ae603500b6a462258098d8b66b85293594e208829b5228fae2fafc39:8aaeba535c511c31d3f8e95cb077a9a7ec7d08441e5342a6abe0bf2a5d7fc930b43dac3d1e8ef2cb034552eb4d0839bc8bf294551dd2d80c53fd6279351ac20c20fb414e264a954784f112bace7e0474b39cb3c9e53dee0a21f4cf6d4a99b9347ddffbe281a6c230a75d63a72fd05f6db53ea7014ef7709d18ff970f485fe83ba1d37147338aded6da4cfdacc1e69d2f3e0ef362f47b5bcfb78a1e179eb5c5b106c8d82a0a0b290df075ab27436929cde656f02309f95750eb676583262e5f2f69f0ff72a8e057266382269205318740bfe06bf5c2cb4533908ef9f9f2869a75b9533579820e3bc0caffd646171c8286c3a4aba1ff0915d93611205e230f39ff4c4caf3f333e753fce2b71213e53d608415ee17fd48212eedd8840f337101ef0d0b6f7be4bffc06eeefe8066dd27a0541a468831acddc4902e2fefefbed19c308e5621e0bf46bcd538aa13faf04d380759c0e107e912001839dfd0b635440e9638f5377ca8450f350c01129ee33764415c53cb2ffbf968df78b742fd0665e78a34abf4decd1fd386289a1364e64555eec58b0af9a4cd6b36d1d5c611a2846dfb5589344bbbb02560241b74b993a25bef50fb1e7319086e6a23986300834ed2dba98a168721c2f784dfb8d3800d06a054aef14d1772b6c574af2563d193ef2e51bdc62d2abce2eebeada79203498e6686c287f37bd88aeb166f7dffc3e6ad0294117ef6ee9da8479ed8a16fe9be246d266804f29658db75e7a0873be71dc7d407e39fabd66f988b457477427fad8130f09ab665f1597c9046e7373af9a8352a86830cb92a804488700fe6891924fe2a7201733d95e591ee0a1fef1c2636078d370e7ad3b6a944fed2cf2b30aba2d56f3495b2849c03bb614f48bc4e507c395a6c35d3eed4c7be8e680f2d45a310b187eb88cf0e8ed4de7d37246a50a6367b97ee3784322c0b71131a283198da4804de751dcf70c4bad00dd98d873a69dd1a09cf69ddfad7ae603500b6a462258098d8b66b85293594e208829b5228fae2fafc39: +163b0cb6a12e8f07b0c29d6a63f6a652ce497270b5e46fcf833c99bd843f8c6468a35de4ba6f0f82ecf4b1e0df8e24cb4f18f2103ff04dc1b5333991b6d314ba:68a35de4ba6f0f82ecf4b1e0df8e24cb4f18f2103ff04dc1b5333991b6d314ba:56a1603f725be07613058cdb3acdc52354e3bb1ff2bed13f895175b15c8c5a90ffbe46b11a06cfe362dadf7323c940417255aa7aa54312103e71463daa0b5cdaebd0be723c732273e3c3f5bf7aa3519d69df6f4770daa1df8280bb3cd2c714ac030200546579f56c60b91ae11f4cf874a35fc59b354bed80f56e11a6cd62a88ce6b4f6bf39d64ce3d80409825f90162c3d96d10e478607365f7a241e71af980042fec2d68891e0c8a37c58ec4e600fd581e790b0aae8e09f35d4cc1876df434b80eee05369f848fc4930577d1684275888f3259cb47376c5169c9937f855a96a9e748ad0a69ae4ab2f2f1744a392f9acc6209975b784984cb12f98292c36a53221994abc56f9a66dae4560b79356ff47e128c0796a7fb0e0bbc9600af48e49eaa9427cf6eb6620b10cd2c085b0b342004d5b0d3edc11d29242a4638780762c9dc6069b66bd84973b5011961ce56db58bdaf48e6be12ab9ad24416297004d02914b959f54e092f8cd4365fa6ab78ddbff4ce8dad4e2f53a05c0cc499bfb47814a2713551dcd19d447f627576ea4ea4bbda8bae18a6465ced747ea17180b009f01212160482b0433aac68e67644d00f41fdf9990b9e11117634deb139b1a40ad3fce4299a17fe1dd225301c7f8d8010a796dc79c13307d3ff992a88be664d4c886d68ca9e4470cfbe63ebffc424010e372b6922aa95c801d1e9406da4bc188ca82066405bcdb3eafc937629b3263dc7d50ee5278ccec6f11d5517f56bc269c873691e7eb53faeff07564ab46b403f15d9e0e692486ee098e7b51b42813469b8235042233ca3f9c4f8ff24a571f47e0adf9144aea488a2d2dd001e31fc961e05c3e85f0d981407c873158bb0d35bafe4b60422e67551e970165ce3fc599d0fcc92b16ac36a92b2c1dc6b3f033fe310cd196da04a4e639031177cd27d7c2fbec65a00b:17738f5726550780651d60199fda39d9c4768db5917e32393631c54a419d59f18ef960ddd439380dabc314761bd0cdb57cce481e6109fed095dea6e865aa670b56a1603f725be07613058cdb3acdc52354e3bb1ff2bed13f895175b15c8c5a90ffbe46b11a06cfe362dadf7323c940417255aa7aa54312103e71463daa0b5cdaebd0be723c732273e3c3f5bf7aa3519d69df6f4770daa1df8280bb3cd2c714ac030200546579f56c60b91ae11f4cf874a35fc59b354bed80f56e11a6cd62a88ce6b4f6bf39d64ce3d80409825f90162c3d96d10e478607365f7a241e71af980042fec2d68891e0c8a37c58ec4e600fd581e790b0aae8e09f35d4cc1876df434b80eee05369f848fc4930577d1684275888f3259cb47376c5169c9937f855a96a9e748ad0a69ae4ab2f2f1744a392f9acc6209975b784984cb12f98292c36a53221994abc56f9a66dae4560b79356ff47e128c0796a7fb0e0bbc9600af48e49eaa9427cf6eb6620b10cd2c085b0b342004d5b0d3edc11d29242a4638780762c9dc6069b66bd84973b5011961ce56db58bdaf48e6be12ab9ad24416297004d02914b959f54e092f8cd4365fa6ab78ddbff4ce8dad4e2f53a05c0cc499bfb47814a2713551dcd19d447f627576ea4ea4bbda8bae18a6465ced747ea17180b009f01212160482b0433aac68e67644d00f41fdf9990b9e11117634deb139b1a40ad3fce4299a17fe1dd225301c7f8d8010a796dc79c13307d3ff992a88be664d4c886d68ca9e4470cfbe63ebffc424010e372b6922aa95c801d1e9406da4bc188ca82066405bcdb3eafc937629b3263dc7d50ee5278ccec6f11d5517f56bc269c873691e7eb53faeff07564ab46b403f15d9e0e692486ee098e7b51b42813469b8235042233ca3f9c4f8ff24a571f47e0adf9144aea488a2d2dd001e31fc961e05c3e85f0d981407c873158bb0d35bafe4b60422e67551e970165ce3fc599d0fcc92b16ac36a92b2c1dc6b3f033fe310cd196da04a4e639031177cd27d7c2fbec65a00b: +8c839381b6a7ce2649c1ea464ae3c2d3fdb1ec666d7b4be4e2a941ab6d6557a75c724a30c6fb32815343a80ddee6eee544516418ea95e1bac80afc8040d63fc6:5c724a30c6fb32815343a80ddee6eee544516418ea95e1bac80afc8040d63fc6:cbcf89c3548964c38d70fd8f68e8ece36cc39755c971d14d7e056f39b023ef166d17f2438522f010d6d835d886e71f474c6727a4221fd03a7574578289ed5493ac4c0947e3f428d8fe064006a256cef21811d72678f5dfc6ba66ac29ecd1b32ff5557cb08c5f130559217a0413b759c24d83388a2bb9b29b6b91d1f3101ed625211e4d73805193478cf995396c10b1c5affacb00899da04e3cce193b494e2a933c4eebe0a37bfb8f1b8371bde5fda09e804e940f344896a529467adee45a8febf85ab036cab880143be4f59b7741d8e450278b06365578d40b19dcecc6e1ee3da34ab29013fa3af7729272962110e385ab9a022fae4146f89716f7bab9d3dc682f4fac7736d3e08973c685bbb275bbf8f217419e5cae0219eba5166a5de1b11e3f9a908b8ac7e65bcd623f8c18bb024f605dcbacda790d8362957444a95c130a37ee9d563d0cbb4cb2b0ff71591d9390b6c8fc28753a0e402d6487cfac607135927d89267512b34f877057d9271bccc024dfedccc6c32edf75c8b7551cdf80154ee8e08a0cc43044e1036bae017eb48b6502c7a9d60c8b370cf3799c464f964a69ee659501223e789a6497b63496df1ada2e808d2434fc8bb9794e5e2a20bbf4d6925cb3c5bb14842f19200905ba9354e00dc33cff5b42d4e9d9668b34e661d44bef76fefe2ed51f94423a933ac94f1523bf37823a238d616c6b17973441e35f9405a04d99eaa8f504534c8b5fa5e8e335c743bcf21f5d492b7112e00fd8642cb12bfec849df62120dbb06bfc2946a5601e25be75011c6f00c65d35f44a46af9e4f7809e5789a3a61ba0a3b213890497296c81e42e88f0ec0f5defc1f5d39ff2a48b7e3026c9e547202edc7eb738c34ad3a15d373ef82a4c1d181f285a98bd3314c2c1947c9e2c60aca51750ee7f943caf0c4e1e5c7df7291e973b1f936b73707619:5d2110d1d2f3edd683bdfdbea3ffa7cf5528a40b8b3d8d8c9bfd22aeac28bad471666e062f7d38ceda8bb37397a1c5c3f733b537967045706478437d4d187a0acbcf89c3548964c38d70fd8f68e8ece36cc39755c971d14d7e056f39b023ef166d17f2438522f010d6d835d886e71f474c6727a4221fd03a7574578289ed5493ac4c0947e3f428d8fe064006a256cef21811d72678f5dfc6ba66ac29ecd1b32ff5557cb08c5f130559217a0413b759c24d83388a2bb9b29b6b91d1f3101ed625211e4d73805193478cf995396c10b1c5affacb00899da04e3cce193b494e2a933c4eebe0a37bfb8f1b8371bde5fda09e804e940f344896a529467adee45a8febf85ab036cab880143be4f59b7741d8e450278b06365578d40b19dcecc6e1ee3da34ab29013fa3af7729272962110e385ab9a022fae4146f89716f7bab9d3dc682f4fac7736d3e08973c685bbb275bbf8f217419e5cae0219eba5166a5de1b11e3f9a908b8ac7e65bcd623f8c18bb024f605dcbacda790d8362957444a95c130a37ee9d563d0cbb4cb2b0ff71591d9390b6c8fc28753a0e402d6487cfac607135927d89267512b34f877057d9271bccc024dfedccc6c32edf75c8b7551cdf80154ee8e08a0cc43044e1036bae017eb48b6502c7a9d60c8b370cf3799c464f964a69ee659501223e789a6497b63496df1ada2e808d2434fc8bb9794e5e2a20bbf4d6925cb3c5bb14842f19200905ba9354e00dc33cff5b42d4e9d9668b34e661d44bef76fefe2ed51f94423a933ac94f1523bf37823a238d616c6b17973441e35f9405a04d99eaa8f504534c8b5fa5e8e335c743bcf21f5d492b7112e00fd8642cb12bfec849df62120dbb06bfc2946a5601e25be75011c6f00c65d35f44a46af9e4f7809e5789a3a61ba0a3b213890497296c81e42e88f0ec0f5defc1f5d39ff2a48b7e3026c9e547202edc7eb738c34ad3a15d373ef82a4c1d181f285a98bd3314c2c1947c9e2c60aca51750ee7f943caf0c4e1e5c7df7291e973b1f936b73707619: +aabbb2efedb599424a5f3e08f90fa8826c5c92170be501a1181fe8e8df974e0ece7319ef88b242420666ca697ba8501d274ec4a5dcf844596608b9dd5a8a3acd:ce7319ef88b242420666ca697ba8501d274ec4a5dcf844596608b9dd5a8a3acd:fcc15cc57970569e9ccfa5a778fc7aed71978a3f5624577b6f57fa3f167ea223ef31764c488d059d06531d016bcb17d544d46977aa241f8e07af4787a0810f98d766460c0841ad81b88f4d5d8164485a1258a94622c5492428d6d575943715766c2b0a865bedba167d5d340edb579c47aa32459b8fc98a79bb0bed1c960b4ccb7f2d4b5681a2a70d505b85b81e3d99672714e4eab41f3ab0ca874f417186feb69ed13fb911f49d1584758b2d18b4673edfae495e68dad513a7ac0d47b2753cb4eda78fb431f04dda8fe8030d7bb4e8dbccb969d7f580d9c1ef935d074d7a41d1f8b9dc45c9a2e4106a5529a98b95529ab0edea0b5722dd686f5a7f3cd8fb2624ab26c42df11f510a103d8a929830ad85f52124e3d5827ba60bfbcd736cb6c590ee777ead7aa2224d7ae46d257a90407247960c9cb03860aeaa7f54c1a8e11160d11bb473065e19b70721c8f072e1909d539e9ac94185904bbbfe54873754ae1ca7bced6f40561af4b505f03ac972a6f0bfa73b5f832fe23b898b2bbb0574a6662ee93b3b360da1ec7e838eb2c77c7cb7fc164f7c4627010489c858900752c92d9d75ad547167e4bdd11a07d28b651aa30f16a850e060dd2882fb820919a398e805eb63699f4ff595f991524731641ece25fb3f8e89ada501192b1eddaecbacc8b898528f2d5b3312694f5ec2dc9142e1513f777a5c833409c171633ff9fa2609d0497f5df4fbf48ef2b77d55e25519d2ee79b5fe9d8fa46000decdb4f25dfb3f2bafb19fbe2cbdac002a359a954bc69bdfe2fb36adfd9a1509f3e3a4c6b1f3f36e7cf80d583d440ff2a144643098974d71493ecb6417c0b8065bd2c21c1e34af09243fb49e9d35297eb0a52d56dd270fea6dc5c080a05599f78581e90fd8cc4cd11a505edde84b892d8953bdbb2379d33aad64658ae20607dd35b0bf3a2637d20c3f86:a0b19cfa6c80de77bfcd321030bf8c03893e2b21ace6c6ba1ff7408e6ff07d847e6b2b688d4fd51aa932701db6402ef22322e6e9fc7e320abb4d24e1acc6cf06fcc15cc57970569e9ccfa5a778fc7aed71978a3f5624577b6f57fa3f167ea223ef31764c488d059d06531d016bcb17d544d46977aa241f8e07af4787a0810f98d766460c0841ad81b88f4d5d8164485a1258a94622c5492428d6d575943715766c2b0a865bedba167d5d340edb579c47aa32459b8fc98a79bb0bed1c960b4ccb7f2d4b5681a2a70d505b85b81e3d99672714e4eab41f3ab0ca874f417186feb69ed13fb911f49d1584758b2d18b4673edfae495e68dad513a7ac0d47b2753cb4eda78fb431f04dda8fe8030d7bb4e8dbccb969d7f580d9c1ef935d074d7a41d1f8b9dc45c9a2e4106a5529a98b95529ab0edea0b5722dd686f5a7f3cd8fb2624ab26c42df11f510a103d8a929830ad85f52124e3d5827ba60bfbcd736cb6c590ee777ead7aa2224d7ae46d257a90407247960c9cb03860aeaa7f54c1a8e11160d11bb473065e19b70721c8f072e1909d539e9ac94185904bbbfe54873754ae1ca7bced6f40561af4b505f03ac972a6f0bfa73b5f832fe23b898b2bbb0574a6662ee93b3b360da1ec7e838eb2c77c7cb7fc164f7c4627010489c858900752c92d9d75ad547167e4bdd11a07d28b651aa30f16a850e060dd2882fb820919a398e805eb63699f4ff595f991524731641ece25fb3f8e89ada501192b1eddaecbacc8b898528f2d5b3312694f5ec2dc9142e1513f777a5c833409c171633ff9fa2609d0497f5df4fbf48ef2b77d55e25519d2ee79b5fe9d8fa46000decdb4f25dfb3f2bafb19fbe2cbdac002a359a954bc69bdfe2fb36adfd9a1509f3e3a4c6b1f3f36e7cf80d583d440ff2a144643098974d71493ecb6417c0b8065bd2c21c1e34af09243fb49e9d35297eb0a52d56dd270fea6dc5c080a05599f78581e90fd8cc4cd11a505edde84b892d8953bdbb2379d33aad64658ae20607dd35b0bf3a2637d20c3f86: +c2e074faa234e99ab20adbbeae11b8109723b708c54586df652b402c35cdd1275e524ece1c696e705a3514dd0082b840795a59c36a96cbc482bff5ab4ef515d1:5e524ece1c696e705a3514dd0082b840795a59c36a96cbc482bff5ab4ef515d1:31290338e46d1cc25ce99cbacc40160341b785823c823c4ab9baee3b612579f1c011716796e56e2693f6ddad43922aa7847cbb4148101651bbe62d50be90825e8eab777aa4b8026dc5385a97d3df76160191f922cdd2f07ba5f85e95f45db22928f90734ff520c44dc8fe3903b4c51cd23e064f01c829ec74fbffe25fd0d369d2765740f43856bd7398a1911ad749836160fd98d04b28ee87e111d40718b5a166f05c9a471a41566557069f7a14de988bbbf6777521fcba6dd65de4c06674a11853af83accb70fb328dd8fd6105a7df5269c9faec8d900147e928d970c36cd834bd6054f70650dface94b7629d16e3703d766ce7638d0ad1e17b77469b958d2ba2a1e631a1635efdcb006ebc6e5d8b9faf7e5fb989dc0896c561a26f3c25f055716b367138ea5da1f81dc72cff7a55afaee5839ef5aa822b2970aa18a8982163bf5eed1b677ccaac1224ff6c6cf256374780ae65803bf5c6e23c80bacd76ec3e2ddd3ab71997506448e19db198efadc9f757491f1b0972c82db29410e1e8bb67bbb23d53563b8807e5e0c2e32ee596b5b4402328f9e179e9ce856d3bd199d58de6c5c252e7a6124d81fc9eeaf23d347d2ab88917aa684450dd58303516c1a4d2bdcdde220c9ae3790f298d7d384b70c2fe258807848fc35320b578b33503b75f38a1df630bd33e6a85a4dd4df9f6e55a6e6867c73801e593e1d591db89ba9a9af0fc292e06fb515ac8a5e8e343a821335575ba48fbaae3fb12deeaaee60f4b3d317ec0a554ddd425c84932c27a7a12f29d6371510783bd75e60e2f6da20052069ed71e695a943182193cb6851a7d2fa3c666c193028015ac8b7e7daa6c5204f77a6232b88b4abffc5362fde7dec36b9d454880849283b1156339ea2e8c3b10e51bfabdf72578c726419a38542cf8649df9a0909f582debad5fd89d8c81f83d9e423e7503:657c3826b3483fd42ab6df869d1b77a8c4df67a6a590c7c6772969e3df3312ae0654fb83847af221935a0512291636ec0595700879ebdba8a1467c53d40c230631290338e46d1cc25ce99cbacc40160341b785823c823c4ab9baee3b612579f1c011716796e56e2693f6ddad43922aa7847cbb4148101651bbe62d50be90825e8eab777aa4b8026dc5385a97d3df76160191f922cdd2f07ba5f85e95f45db22928f90734ff520c44dc8fe3903b4c51cd23e064f01c829ec74fbffe25fd0d369d2765740f43856bd7398a1911ad749836160fd98d04b28ee87e111d40718b5a166f05c9a471a41566557069f7a14de988bbbf6777521fcba6dd65de4c06674a11853af83accb70fb328dd8fd6105a7df5269c9faec8d900147e928d970c36cd834bd6054f70650dface94b7629d16e3703d766ce7638d0ad1e17b77469b958d2ba2a1e631a1635efdcb006ebc6e5d8b9faf7e5fb989dc0896c561a26f3c25f055716b367138ea5da1f81dc72cff7a55afaee5839ef5aa822b2970aa18a8982163bf5eed1b677ccaac1224ff6c6cf256374780ae65803bf5c6e23c80bacd76ec3e2ddd3ab71997506448e19db198efadc9f757491f1b0972c82db29410e1e8bb67bbb23d53563b8807e5e0c2e32ee596b5b4402328f9e179e9ce856d3bd199d58de6c5c252e7a6124d81fc9eeaf23d347d2ab88917aa684450dd58303516c1a4d2bdcdde220c9ae3790f298d7d384b70c2fe258807848fc35320b578b33503b75f38a1df630bd33e6a85a4dd4df9f6e55a6e6867c73801e593e1d591db89ba9a9af0fc292e06fb515ac8a5e8e343a821335575ba48fbaae3fb12deeaaee60f4b3d317ec0a554ddd425c84932c27a7a12f29d6371510783bd75e60e2f6da20052069ed71e695a943182193cb6851a7d2fa3c666c193028015ac8b7e7daa6c5204f77a6232b88b4abffc5362fde7dec36b9d454880849283b1156339ea2e8c3b10e51bfabdf72578c726419a38542cf8649df9a0909f582debad5fd89d8c81f83d9e423e7503: +b9da4e6af07e398ab4d21752a32c8ffa9be0c310d35059fb661bd73afa97e2a8f862803c96cc42adc8252884547230b970047b7e5da996260ccc0240ab71a6ec:f862803c96cc42adc8252884547230b970047b7e5da996260ccc0240ab71a6ec:6b95af0eebb6a08afadaa19621f76a839be80851c6dd315e8276f501995d4ce6d134df5e798ed517a2f0e62aa1d6c98c36ef14bb1e5ddfc98d5a7fcc81140a13c20d2ca0c4b40e6e6a03eed8c899f9d1f792468152199f4b95a432668947a51d7b8e104d8d1f12aacd967e08b08c41c3c8ca3feedaa5b8b63bcec0613864d953d81143ec81425bde29164a0876f23f37ac9ac9473672ce11a08bd5476f6f66d665e9ad617e34eb32ee56ffa459f20d1b9353d7821298545750c6eff3e7d4073dc3185ede0391cce0575f8ba637d800068d9d7e5403ba7038d2db77da144784f2e8ea76aedfe521e7dc6a674ede35579595993fb20d44b4052783f56c8c0bbd0440b69eabde84468dd13c671fb1bbd5cb022c2a4fcf3542d8b3bb518e5adebddc84e714b13be52c56b282b42ac0892a5459281be7160729f4112c7d99df9be5434f823a9ce0501789de1d550ad50bb18c8d89a33668270bff7b91ff118f5cd9909addde90c024a3ad713915174674f28aaa9f94a322baa543738edab4973312b5bfa12155debcee163cfe2b04ac9c122ac8a4e1bc418c14955d9610455bd945e9793b916267c9c5f9e53ac04518926ec98ecb84a4f0445dcb1236c76c3a678c69abe4e92c22971d62217201a1bdf05c04df8420a3de6a917a85e71e2b9725e77b522915d4c9946077637c2d8813f010b9491cf0eddc3d4668cc0f8bc8a683579be543934da2853a16f5715724f779819f44439e1debcaa4270d9b8594ba4c86e1063b3ce479d71a5409bef27ef4e5c1d1c96e8be13865af7bb43f09162ccbc83a2ca9e9b8a2324e6d996575eefed37ef49908185738b8eae43f8adca330c99bc66cc1fd52c530d7371c60869ce42c197dca0ad128b85f61c8758f0d542f3d3298b65e93c6e8a68fa0e9a1d5e8c5fec805b83aff4390e115eb64f3f078a0b9b66c273843fc6c:625e1f42c87434a25d622d80d12532806afb2509332449e696b65e1e5888508f11c4ac25f59b8d94d0bf27e4c8d1867007c408da573082dcf19d15a9d5cccb0c6b95af0eebb6a08afadaa19621f76a839be80851c6dd315e8276f501995d4ce6d134df5e798ed517a2f0e62aa1d6c98c36ef14bb1e5ddfc98d5a7fcc81140a13c20d2ca0c4b40e6e6a03eed8c899f9d1f792468152199f4b95a432668947a51d7b8e104d8d1f12aacd967e08b08c41c3c8ca3feedaa5b8b63bcec0613864d953d81143ec81425bde29164a0876f23f37ac9ac9473672ce11a08bd5476f6f66d665e9ad617e34eb32ee56ffa459f20d1b9353d7821298545750c6eff3e7d4073dc3185ede0391cce0575f8ba637d800068d9d7e5403ba7038d2db77da144784f2e8ea76aedfe521e7dc6a674ede35579595993fb20d44b4052783f56c8c0bbd0440b69eabde84468dd13c671fb1bbd5cb022c2a4fcf3542d8b3bb518e5adebddc84e714b13be52c56b282b42ac0892a5459281be7160729f4112c7d99df9be5434f823a9ce0501789de1d550ad50bb18c8d89a33668270bff7b91ff118f5cd9909addde90c024a3ad713915174674f28aaa9f94a322baa543738edab4973312b5bfa12155debcee163cfe2b04ac9c122ac8a4e1bc418c14955d9610455bd945e9793b916267c9c5f9e53ac04518926ec98ecb84a4f0445dcb1236c76c3a678c69abe4e92c22971d62217201a1bdf05c04df8420a3de6a917a85e71e2b9725e77b522915d4c9946077637c2d8813f010b9491cf0eddc3d4668cc0f8bc8a683579be543934da2853a16f5715724f779819f44439e1debcaa4270d9b8594ba4c86e1063b3ce479d71a5409bef27ef4e5c1d1c96e8be13865af7bb43f09162ccbc83a2ca9e9b8a2324e6d996575eefed37ef49908185738b8eae43f8adca330c99bc66cc1fd52c530d7371c60869ce42c197dca0ad128b85f61c8758f0d542f3d3298b65e93c6e8a68fa0e9a1d5e8c5fec805b83aff4390e115eb64f3f078a0b9b66c273843fc6c: +143f7b4247d549f6b7c0917266c50f962c28a2ea24762f537aa06ad15e40b35ac9959f90a2d5feacbae2c4c803ded5deab86987637064337aa2a0b0ddef2fd86:c9959f90a2d5feacbae2c4c803ded5deab86987637064337aa2a0b0ddef2fd86:e274202347a0d057a48bf2a1f6e9f6cb4256079d800374093c020cbf520e5fa27fe996ff07f33ad3b21f74ab0cd93c86475ff37cf622d3f9fa4d13bc99f013e8502b24e46cc87c47e6b2c3662b50e979a0f345b784ff21a8a4d92adc65e86e33b4dbe17f528ccdf5b4864664ba94ffdb7c7d2412b438e6e43fa9668147ee3328224d1f52a3f5b54359b4f7fef69af8f867b478f130a147bea42ed39803bcbc2557bca8c3999f1d24f0a6b03c98846011f9ec74f666417b95020eb1fb2fb88b6312e5008cff03e2d77a26aa532d1780b5077f9e8b828674455d6bc957975f7b2a50e7fd7c1612ce02362efa4c555a1eef68ec34a5c006a6da008a31d4193dc2cc647685ad3cfa3bd7c560b7aed45f0f1a3d1b5b362268de532857055ab9d1d5d858d9ae9a759a51bb9478e8f0ee93c984b576b8b4ab460280be3de205a32f1dc3d572923fb213ac1512d80eb5ad5c18944be77fc17def13a61bbd31bc71acc23d250ec5894ebc214cfec0c1b906516d32d836adc838802e8de30dd76df6e61c1bc438b68d2b025a84f211facf3f1384d2612d0faef5d17131cfe0cfe833fe950e479bc29cbe7fd6da0cce307cf0b1bd92c80e878e432f636ea0cd42480c07e8b8e57e69b2f938b78120f6af4abebf7d4b05cacd6eed854491c029755c4e66338993ed2ac25d19a0c5b40f5e32c8a8b1bce369718186c91d60edff24a8377a9969757599067dd31263a06d6a61154781f29611ab812ff82e813739646263704cd6046357a23c045e2407b7a89508259391314f2fbee49aef0855c6e5e63d912a19df15b11ece34e276dcb88bf2f2e4756358f34a0ee3952b686fcd17578a884176d34ea2916c5d9fcd00eb9e0aa9f2cf0f16e2564bfd28b6ab5968b8448f068320e4187160f8665781b1e2ed9d049e1b54a7d72720ff9d4f073051996a9db6f0c6821c424fa51d:c1cfae58515713ea728cfa09090e8942f8df18621ba7090e3a3376c3802775a1ecaf436b184978041ebb75226f970df71d6ad353c0fb465023f9e298f64a7002e274202347a0d057a48bf2a1f6e9f6cb4256079d800374093c020cbf520e5fa27fe996ff07f33ad3b21f74ab0cd93c86475ff37cf622d3f9fa4d13bc99f013e8502b24e46cc87c47e6b2c3662b50e979a0f345b784ff21a8a4d92adc65e86e33b4dbe17f528ccdf5b4864664ba94ffdb7c7d2412b438e6e43fa9668147ee3328224d1f52a3f5b54359b4f7fef69af8f867b478f130a147bea42ed39803bcbc2557bca8c3999f1d24f0a6b03c98846011f9ec74f666417b95020eb1fb2fb88b6312e5008cff03e2d77a26aa532d1780b5077f9e8b828674455d6bc957975f7b2a50e7fd7c1612ce02362efa4c555a1eef68ec34a5c006a6da008a31d4193dc2cc647685ad3cfa3bd7c560b7aed45f0f1a3d1b5b362268de532857055ab9d1d5d858d9ae9a759a51bb9478e8f0ee93c984b576b8b4ab460280be3de205a32f1dc3d572923fb213ac1512d80eb5ad5c18944be77fc17def13a61bbd31bc71acc23d250ec5894ebc214cfec0c1b906516d32d836adc838802e8de30dd76df6e61c1bc438b68d2b025a84f211facf3f1384d2612d0faef5d17131cfe0cfe833fe950e479bc29cbe7fd6da0cce307cf0b1bd92c80e878e432f636ea0cd42480c07e8b8e57e69b2f938b78120f6af4abebf7d4b05cacd6eed854491c029755c4e66338993ed2ac25d19a0c5b40f5e32c8a8b1bce369718186c91d60edff24a8377a9969757599067dd31263a06d6a61154781f29611ab812ff82e813739646263704cd6046357a23c045e2407b7a89508259391314f2fbee49aef0855c6e5e63d912a19df15b11ece34e276dcb88bf2f2e4756358f34a0ee3952b686fcd17578a884176d34ea2916c5d9fcd00eb9e0aa9f2cf0f16e2564bfd28b6ab5968b8448f068320e4187160f8665781b1e2ed9d049e1b54a7d72720ff9d4f073051996a9db6f0c6821c424fa51d: +0d1fe9d8b9a2f04c22bbb0edea3833a0ce43339347531fdb67ed513a13d36b3967c49f410f4853293d0c4d39f4c1b3d6c6103c5cfe20a9a59b53932043517369:67c49f410f4853293d0c4d39f4c1b3d6c6103c5cfe20a9a59b53932043517369:64217ac841fd4d6459bfc4a49b8801d6929bf19b408e8a53790ceb51ec341f9b46a351e8c2e59d887e1eaccb914231cdca1d3e5c47d166b4cdb9b58c013c59a3bd283ad10f6bd62c0f15f764ce14f3b265f537c63e73b6c4fa65e06ce1e1f4ae0d11489dd2602f95fc402b7712052abc84bdc778c19f10001b4e0d5fbe463090e83ef438fe068f3bb6fbc2c139af0678ed2a11faa1b9e49aaa4620abfc08439fbfe2c61840769e5fda2677f8e2f0a14564f9f504232a9fc0d9da471e67fbc574c3d56d2aeb937a586ed5583556308a998eb1dc476a014f5a08228dbed95a1208bc1d1f5d76b4e8d0b2434b995ad458e429ee6142a0c971768cc40c40bcb08e9603f09611474471b3859d7fd584219f02657b430e9e56955b3467ac56ff2eab22cc498489036a574120e2db769a3b21500389142c78a87d069f0e2576cafda8cddd7915a9228773d2ac9a075cb387f2a898617213b2cc5059d11941bc4fe58641e7c1750267e53e99c421cb4cf21d098ca2d1f41644f7908983eb174a23a781cf15ef38eb9116eda4123a1522f53b81fb7368e8075fb83859d2cf98d921535a709fafa9873c4a039aae682f7e6286b899257c0924016ca5bf6d3169099211a9a4a6745cdd3198f1337f60928227ce3c7d60960b53dedf011a8940f5c468207a3894bb0872b333ccdec9d5ecd911ecbbb96c9bc4bd4875320e4d3e9c02d9dc76109ec45e61d1cf5ac729f2e34a9647b95bce70b0c633171adaf0dfdb5afba4035b3cce8cb7141ad142bb7add4fc3f961d42d7203754a4e313221d487831e32947da91138ab648b5952ef6956e27aa5d2c175794bf81ef277faa6b905e14502866887d87880606e81b27af01bb263ecf2c5820585ea6ce8d8b391d86fcedadcd11fdbb566fdf147f402010fc35f5157e036146b3736c8a43359127c261f6bf0cad3bd8a34cb1509f7:b05725e7371ed0a91ebc89f3c30baa99183763edb4ce34fe901af3731e001cc54f287118915e90365d91aca8feb1708769f9f1d6eef5aa113bee00b5efab270464217ac841fd4d6459bfc4a49b8801d6929bf19b408e8a53790ceb51ec341f9b46a351e8c2e59d887e1eaccb914231cdca1d3e5c47d166b4cdb9b58c013c59a3bd283ad10f6bd62c0f15f764ce14f3b265f537c63e73b6c4fa65e06ce1e1f4ae0d11489dd2602f95fc402b7712052abc84bdc778c19f10001b4e0d5fbe463090e83ef438fe068f3bb6fbc2c139af0678ed2a11faa1b9e49aaa4620abfc08439fbfe2c61840769e5fda2677f8e2f0a14564f9f504232a9fc0d9da471e67fbc574c3d56d2aeb937a586ed5583556308a998eb1dc476a014f5a08228dbed95a1208bc1d1f5d76b4e8d0b2434b995ad458e429ee6142a0c971768cc40c40bcb08e9603f09611474471b3859d7fd584219f02657b430e9e56955b3467ac56ff2eab22cc498489036a574120e2db769a3b21500389142c78a87d069f0e2576cafda8cddd7915a9228773d2ac9a075cb387f2a898617213b2cc5059d11941bc4fe58641e7c1750267e53e99c421cb4cf21d098ca2d1f41644f7908983eb174a23a781cf15ef38eb9116eda4123a1522f53b81fb7368e8075fb83859d2cf98d921535a709fafa9873c4a039aae682f7e6286b899257c0924016ca5bf6d3169099211a9a4a6745cdd3198f1337f60928227ce3c7d60960b53dedf011a8940f5c468207a3894bb0872b333ccdec9d5ecd911ecbbb96c9bc4bd4875320e4d3e9c02d9dc76109ec45e61d1cf5ac729f2e34a9647b95bce70b0c633171adaf0dfdb5afba4035b3cce8cb7141ad142bb7add4fc3f961d42d7203754a4e313221d487831e32947da91138ab648b5952ef6956e27aa5d2c175794bf81ef277faa6b905e14502866887d87880606e81b27af01bb263ecf2c5820585ea6ce8d8b391d86fcedadcd11fdbb566fdf147f402010fc35f5157e036146b3736c8a43359127c261f6bf0cad3bd8a34cb1509f7: +c10b5ac6055a1ddbca28552e5c72ebd05278c92239b2fcd0c1353651a8e559a0b2183e1b00816d29305f7468e7e45eed3fd8f23c15b305f9fda93e812d65bc27:b2183e1b00816d29305f7468e7e45eed3fd8f23c15b305f9fda93e812d65bc27:3594905f9ea464615f41b87abb9d167337f29d45d97f7a1464ec9f2ee50f90f2e67339874d3f2093be9226107701ec1aab941c4e059f1bb26ce86e148d1d9f0da2a2a0f9829a364fb4f13f58b960d0f8d72323283c4490efdf57878645890ff7bc5065dad6e51dd1e5b9a5075150978b3367f1ba84e45ff1f1276c576e4bc72be8aa8e405fc2b27f8146b999845faaa0595d3cb70e5d3712ed54a0fb3e322d45380b5de3609b967b959bca5a583cc520cdcb7bcbb829aa25d7932095ecb303923c2560afc3fd7324b7b7acd089a9f00c03a73d043dc0cf0ba0d8411e2b1b18d21d2a32a726a53059140f784f7cedf2f33cec66fe4ad5cc9eaccbe4ae10036ac3523bac700a113a98b598e6df0304c6fa3212acc04c4e3c7f6687362ef86d617c6dd483f8d80cea66d1951127428a61c1e155a6850bb2afb7f91c82d73eb2b0543ee8fc1f38e1dcdb3c503ddc9ba0812456a5ce2e11d556487a646974a7bbf86e806c58c68c4269a7c9bbcac0ffef9835b33dc449a75479ecd23f6d149c1e5ea8b69208ff36e5fbd68295550318bfa0d3b1d6c1ad4270bcab0904ae53491f9b1ca502e012eed77c427d49a0962f1055125dd7b53733d8528934b5580dd5fd5bbe854978bae3d25bb4ae944e9065e8e2e07946518a6f548e36e056be824d9e02a7a3eaadd37929f58101cb1853be3d7547f58f49e38b018a748d3f19c48582abbdbe953a8a25ba9d365dea835935899c19fb0b51906aa972c5ac45e99c40b3b76e35d327e321e8ae2306a6eb3d8cb6ec2fa5399add19ea0028a01792c08e27c16cf4f85aaaae72f986b099f9ebe4ad0b25d06d3de44a8bfa52844be4a93944833ce2add51bb554b356a7dc49748dd45ae7ec9e8db426c97a25da5edd3b621e4adbde48197a3314de1c50f4d6002027dd7519dde3e15729e486955ac40d9d66876f90668c689d8ab598:8a9a3217fdf0643aaaa5c8fb2a88a556398859b8feefbcb48ccd88e585a167c94dbb5c0cad24d15bcabbc1edb21f02a8c457c56120a3234ac33577b9af2ddc013594905f9ea464615f41b87abb9d167337f29d45d97f7a1464ec9f2ee50f90f2e67339874d3f2093be9226107701ec1aab941c4e059f1bb26ce86e148d1d9f0da2a2a0f9829a364fb4f13f58b960d0f8d72323283c4490efdf57878645890ff7bc5065dad6e51dd1e5b9a5075150978b3367f1ba84e45ff1f1276c576e4bc72be8aa8e405fc2b27f8146b999845faaa0595d3cb70e5d3712ed54a0fb3e322d45380b5de3609b967b959bca5a583cc520cdcb7bcbb829aa25d7932095ecb303923c2560afc3fd7324b7b7acd089a9f00c03a73d043dc0cf0ba0d8411e2b1b18d21d2a32a726a53059140f784f7cedf2f33cec66fe4ad5cc9eaccbe4ae10036ac3523bac700a113a98b598e6df0304c6fa3212acc04c4e3c7f6687362ef86d617c6dd483f8d80cea66d1951127428a61c1e155a6850bb2afb7f91c82d73eb2b0543ee8fc1f38e1dcdb3c503ddc9ba0812456a5ce2e11d556487a646974a7bbf86e806c58c68c4269a7c9bbcac0ffef9835b33dc449a75479ecd23f6d149c1e5ea8b69208ff36e5fbd68295550318bfa0d3b1d6c1ad4270bcab0904ae53491f9b1ca502e012eed77c427d49a0962f1055125dd7b53733d8528934b5580dd5fd5bbe854978bae3d25bb4ae944e9065e8e2e07946518a6f548e36e056be824d9e02a7a3eaadd37929f58101cb1853be3d7547f58f49e38b018a748d3f19c48582abbdbe953a8a25ba9d365dea835935899c19fb0b51906aa972c5ac45e99c40b3b76e35d327e321e8ae2306a6eb3d8cb6ec2fa5399add19ea0028a01792c08e27c16cf4f85aaaae72f986b099f9ebe4ad0b25d06d3de44a8bfa52844be4a93944833ce2add51bb554b356a7dc49748dd45ae7ec9e8db426c97a25da5edd3b621e4adbde48197a3314de1c50f4d6002027dd7519dde3e15729e486955ac40d9d66876f90668c689d8ab598: +061bddab280b0fdcb26bfd9a0fc721f68f88343b5d3983a16b6dfaa5e76969f3815578bba6e7070ebdeca117568bd77ebff9e14cb8bc200c32bd87db1fb37d6c:815578bba6e7070ebdeca117568bd77ebff9e14cb8bc200c32bd87db1fb37d6c:ee76b40cd429eac7bc12839ca2f7cd31f1e0098a39c5fc19805be0331f44799e318d12571f06e2993753a3685cd2a96b2301e20024209adc5adf7479ff90c477c3695abb99bd28579dbc7831a192beed0ce17b038b20764800653af7af024e2a104ed0f3e52d4bbd3e109cf126291f49b0a21be433c1c5a2589ea572997f63d2bb3972d532be35a0471ef0573d795c072b6a8685b95e47b09ea9f475d93bf12bbd77b7d2bf5d5bddf0ae02375371d1d799ea9204be389e6a8e5deedcd49202e92df7c3e761f92ef8d79fa738d2c5bc280ed32879832ff2b026424589cdbd52d15b60f2aa3526b898849a34a85ff1c47dc6554b85ac76aa7935cbf3f7bc80ad009192a875ca209b40feb047cc446968f970da47b8cd67da7eb4e54a0e5ab20cb35bc6fb7f13307ce67eb6204a67ce9bb1d139c1b4bd5dbed58010c87bf831e6522ee182dad945804b767c4df2554f15b9e9afd2599ef258c67a22caeb92a57988006bbc72c104fac7e5413cd3d3b802c83e639eafe212a38bb7ef779af1a94ee137f6c60667bc48f27bf4a22241bc44bb6033836239bd6eaf3e2e223187841e4641b0f4e9ff8d5a41ddbeabb4138f6b585ace0fb6b53dc3c9edc0373b6047f27d835e8e246644fd832ccfe0df25c3d7da187c9fa05420d43455f2d08b571929386b59c6e0e10a35601da899b1b4dc3d95b67dd9a83818b0a318bfdda06464b4a42d3cb985f30ec97d6a2af13291155d60cec57cbd58d5cfcb35c18535e8d299b5b007590892ea949d1b137a62b39a436cd7e5b9f8d1b6938dbaa62c2268d459c6220a3e6fcbf80ba0118acd2342563fbdbc1f7c9dba7ea2c072afc8ae2128e3ebca0644ffd8163e80a1a557d9d39034ccd9dbd12c8855a6f9165b0801839cf6e07a9fba4c64d9c099e15410e290e677031b65cf7deb0079bdadc573cc056d7666d95d033a0b6bdba7ec:b83297ccdd6d0098ebf5d132d174de1958311a766bcc4da15f864d801f38e09d613e7aa8c336302735d75be4166d73b0184b0e0bc5ef39edbccb6e0e61afeb0cee76b40cd429eac7bc12839ca2f7cd31f1e0098a39c5fc19805be0331f44799e318d12571f06e2993753a3685cd2a96b2301e20024209adc5adf7479ff90c477c3695abb99bd28579dbc7831a192beed0ce17b038b20764800653af7af024e2a104ed0f3e52d4bbd3e109cf126291f49b0a21be433c1c5a2589ea572997f63d2bb3972d532be35a0471ef0573d795c072b6a8685b95e47b09ea9f475d93bf12bbd77b7d2bf5d5bddf0ae02375371d1d799ea9204be389e6a8e5deedcd49202e92df7c3e761f92ef8d79fa738d2c5bc280ed32879832ff2b026424589cdbd52d15b60f2aa3526b898849a34a85ff1c47dc6554b85ac76aa7935cbf3f7bc80ad009192a875ca209b40feb047cc446968f970da47b8cd67da7eb4e54a0e5ab20cb35bc6fb7f13307ce67eb6204a67ce9bb1d139c1b4bd5dbed58010c87bf831e6522ee182dad945804b767c4df2554f15b9e9afd2599ef258c67a22caeb92a57988006bbc72c104fac7e5413cd3d3b802c83e639eafe212a38bb7ef779af1a94ee137f6c60667bc48f27bf4a22241bc44bb6033836239bd6eaf3e2e223187841e4641b0f4e9ff8d5a41ddbeabb4138f6b585ace0fb6b53dc3c9edc0373b6047f27d835e8e246644fd832ccfe0df25c3d7da187c9fa05420d43455f2d08b571929386b59c6e0e10a35601da899b1b4dc3d95b67dd9a83818b0a318bfdda06464b4a42d3cb985f30ec97d6a2af13291155d60cec57cbd58d5cfcb35c18535e8d299b5b007590892ea949d1b137a62b39a436cd7e5b9f8d1b6938dbaa62c2268d459c6220a3e6fcbf80ba0118acd2342563fbdbc1f7c9dba7ea2c072afc8ae2128e3ebca0644ffd8163e80a1a557d9d39034ccd9dbd12c8855a6f9165b0801839cf6e07a9fba4c64d9c099e15410e290e677031b65cf7deb0079bdadc573cc056d7666d95d033a0b6bdba7ec: +2cab5bf55ffa914e9ad07622190d343ec55c13cd91b388cb7500ffe06df7c180b61e432bb97cbae388a2578a7484998e00e9ad3ddfd6cab8d3a5fc5ba04307c8:b61e432bb97cbae388a2578a7484998e00e9ad3ddfd6cab8d3a5fc5ba04307c8:2c2d04dc3ad1982359ecd5bc3ee035f3498eedff6104a93c602af2179aeb2cb1f41c5cdb0a77b124f946aa8a824aa3076c2e1acfd48f68070b26276a656b4a4758ab151a6a9c41bd74e09bbd9adcce1e87a0a80d17fd92e85e4bda472c988b6bb1183b7ee59a09d80570466db90dd3749579c4eb19ab75fc152ecdcd68cd1078ef06e593c73516fa8291481a667d3f95bfeb144bab59d6ddc73a2795c1017e09536b3162e4bc58f8ead38957018cfec72badbf22819ab0b406c64730fc73fd9ee61f74187eda91ed4e7993e66884af43ef4c6bf7f7c379e8f0f63dcb8041e26b8b8292b6b6d190e4adf430fa82dd74c57385b919c446db37b5e8767e4a0c95013be89b2bc4e9fd62754a844418400968aed2dd328d7b1dc91e1a2b3009dc7ad140a0686f673168a60e88d80c520fc2dcfc56ca9d4b0c88859099230714dec83d26b4630554dcb9c4901895f78f3834b09766b67a465de8c9490065bf568339243399fdc9d5100324667c5ab28f35c00f6125638e61dab70d1eec48951de0fb3f7b23d3cd982437c63473415bef374a663296f2986b1ae9579b9ffce71ec35eeca116d194f8fba9a45a91bae27ac455db71a6b01a729d0c135fcdcbc23e504a2943c00aa42070519d9cd77ae6754f31eb46a3e5be9eeb3fc8d31ff182da9b087be3462c8459126e862909232fd5f2d89c01815957611e6ae7caa98b6053776a7715c2f93ccf030887030c56c2b8226dae2977995a6d3f1e9d7911a9c9d2a303f0e01f32338efdaf8ee63fc41b25399cffd0b35f7ee5676bd8fd3da2cbee4ae2ea9808d7e73583d99433993146674a4040f42f63d1b3135cc797a8d8f0b88573a32890696cac9439d1e15d196d9090b62b6db7e63c96472d946e668cbda1f4db889300cdcc25e84c9f3857d1d9e53241cf625f3909af1c8aaff4309f68f654b7a15b67711c5b7f9de76775:4cf08f4fabbd06dccbcce2a7a5941fe9afddc4d2d0bc80802e93b12cb135d3acf6511e0fe4113c5e3c5541b27d3a2150a757742ac65f95a9ce6673ff0cd21c0f2c2d04dc3ad1982359ecd5bc3ee035f3498eedff6104a93c602af2179aeb2cb1f41c5cdb0a77b124f946aa8a824aa3076c2e1acfd48f68070b26276a656b4a4758ab151a6a9c41bd74e09bbd9adcce1e87a0a80d17fd92e85e4bda472c988b6bb1183b7ee59a09d80570466db90dd3749579c4eb19ab75fc152ecdcd68cd1078ef06e593c73516fa8291481a667d3f95bfeb144bab59d6ddc73a2795c1017e09536b3162e4bc58f8ead38957018cfec72badbf22819ab0b406c64730fc73fd9ee61f74187eda91ed4e7993e66884af43ef4c6bf7f7c379e8f0f63dcb8041e26b8b8292b6b6d190e4adf430fa82dd74c57385b919c446db37b5e8767e4a0c95013be89b2bc4e9fd62754a844418400968aed2dd328d7b1dc91e1a2b3009dc7ad140a0686f673168a60e88d80c520fc2dcfc56ca9d4b0c88859099230714dec83d26b4630554dcb9c4901895f78f3834b09766b67a465de8c9490065bf568339243399fdc9d5100324667c5ab28f35c00f6125638e61dab70d1eec48951de0fb3f7b23d3cd982437c63473415bef374a663296f2986b1ae9579b9ffce71ec35eeca116d194f8fba9a45a91bae27ac455db71a6b01a729d0c135fcdcbc23e504a2943c00aa42070519d9cd77ae6754f31eb46a3e5be9eeb3fc8d31ff182da9b087be3462c8459126e862909232fd5f2d89c01815957611e6ae7caa98b6053776a7715c2f93ccf030887030c56c2b8226dae2977995a6d3f1e9d7911a9c9d2a303f0e01f32338efdaf8ee63fc41b25399cffd0b35f7ee5676bd8fd3da2cbee4ae2ea9808d7e73583d99433993146674a4040f42f63d1b3135cc797a8d8f0b88573a32890696cac9439d1e15d196d9090b62b6db7e63c96472d946e668cbda1f4db889300cdcc25e84c9f3857d1d9e53241cf625f3909af1c8aaff4309f68f654b7a15b67711c5b7f9de76775: +dd7b59a33d970bef62e0e21a7b6e4c30960686f17f49afdb4a9f4e808e355c7f53a0e57277d9bbeecf99c4d138fd66fafcaec7bc5f567f8320800c4e584ff82e:53a0e57277d9bbeecf99c4d138fd66fafcaec7bc5f567f8320800c4e584ff82e:75580367930518168b0a764d0958bec4fc46cf591999eb3737e42a02ea72d210daad53e54a7c2c134a6d478337d2633368548170edef0d85179f3023e1503868a6e5e2775e412ac05f0589d42a377e75aa6b8f5220a7699ae8aff01094ec469d6361d3e8f38615edcda4d2d5289acf73db6456985780c92e07f62c77a909fb6ef598822062bd572bf7058dcb835ef3443d3e47b5c603d92736dd1df26be4b9283b76e321d55ce2b638cde22577ca59c963c2479556c575ccb0d6d18c804e2eb01ff53581eb040ffd2cc46760737a74672ea6bf78058a6a0a1f5ebf56decbf94b54afb23c11d34179bf0976b4158017d407c95a401fa6f9624d77135eae8141ebea9f35d5f51b3ded995c7f70c025b094adef2b071f971155d7796d613a550d09e7f4dfc34517b3f8fa4393286a2b228017daf2e015387e13527f63661d3c13e78e90fb2955eee345739119b791f05b07c8f42a436efcad1ec5ea10f308f8e23ca98bc65a5fd9393efaafe5cdefba81058170cc5493c00cedf254097435d2e2fde55f866bb82dbdfb9154344974866359167b466caa909b91530c9c7ee8c53fa90164bbd0b1fadbdcd08127f19be5033071518d3cf10ae6bd6f9827e1206f5ec095c1986170e8d5d8e72e57d4228701df2a48c954873056cfdfbaafb10e46a0c1f144b1a0eacdd2cb66bb912ac471787dabe48353859120b03403567c415ddb88fc0d7fba4069bbfef406eed724a11abc041e8e7beb663d0dc99dcef3ac6a149007b42dd1f22a77dd52901814325172224a2778f366fb9eb02c812b842a42842561c68f2ac231c26ce9e8b19ae91ebfad3c0e9f66363a13ecd8b897a3d00a26d257648d56c6747441ca1c6ee99f08ddad25d116dfadab0383000d3d7225cf2eff7076b2adab9522292555f3193206786000d42ca34d708dc04284a94d174cc92f102efddf3148c2996916d4:87294d22d4ad0d0814e2d6d5faf55749e9b39803b4d4b7879e60b777c1fc41584fe15135ba1123ff5f200db35a3468dd4d58dad77bd96ee2b888a5a8b18c320475580367930518168b0a764d0958bec4fc46cf591999eb3737e42a02ea72d210daad53e54a7c2c134a6d478337d2633368548170edef0d85179f3023e1503868a6e5e2775e412ac05f0589d42a377e75aa6b8f5220a7699ae8aff01094ec469d6361d3e8f38615edcda4d2d5289acf73db6456985780c92e07f62c77a909fb6ef598822062bd572bf7058dcb835ef3443d3e47b5c603d92736dd1df26be4b9283b76e321d55ce2b638cde22577ca59c963c2479556c575ccb0d6d18c804e2eb01ff53581eb040ffd2cc46760737a74672ea6bf78058a6a0a1f5ebf56decbf94b54afb23c11d34179bf0976b4158017d407c95a401fa6f9624d77135eae8141ebea9f35d5f51b3ded995c7f70c025b094adef2b071f971155d7796d613a550d09e7f4dfc34517b3f8fa4393286a2b228017daf2e015387e13527f63661d3c13e78e90fb2955eee345739119b791f05b07c8f42a436efcad1ec5ea10f308f8e23ca98bc65a5fd9393efaafe5cdefba81058170cc5493c00cedf254097435d2e2fde55f866bb82dbdfb9154344974866359167b466caa909b91530c9c7ee8c53fa90164bbd0b1fadbdcd08127f19be5033071518d3cf10ae6bd6f9827e1206f5ec095c1986170e8d5d8e72e57d4228701df2a48c954873056cfdfbaafb10e46a0c1f144b1a0eacdd2cb66bb912ac471787dabe48353859120b03403567c415ddb88fc0d7fba4069bbfef406eed724a11abc041e8e7beb663d0dc99dcef3ac6a149007b42dd1f22a77dd52901814325172224a2778f366fb9eb02c812b842a42842561c68f2ac231c26ce9e8b19ae91ebfad3c0e9f66363a13ecd8b897a3d00a26d257648d56c6747441ca1c6ee99f08ddad25d116dfadab0383000d3d7225cf2eff7076b2adab9522292555f3193206786000d42ca34d708dc04284a94d174cc92f102efddf3148c2996916d4: +d880d2fb06262f57ab8778e33d16b473060978a6549cdbcd5586ba8105f5aca80de486d2115faf2d547266772e430fd9727bdcace6ecbf2fe23ab60f7b5254b1:0de486d2115faf2d547266772e430fd9727bdcace6ecbf2fe23ab60f7b5254b1:114743e82a0993cec9705067abd77c168b53677ede5c159fad36f06fc1a14acd77f883799ed9883f9915aea638ec1741f3f4215855fb5b07df3793bbe5b568eb3594391a9ef5727fab93e57469b37de125b1e9f2e6fe2c3d1a10ecf87b6c0a665c6d460a170eefb9bf716cd8faea9764f579ff34ebfa9c4cfb34706d8dd7c9eb1d10b2df460a46bb5789430bf449158b5824f2a3a7b918b33acf2d9ebe90216d1b7cbf4af770c5db95fc62ff3a3c385c3a8217853b7346634aaf30607288db0c483bd4c222eb332cb89dc4a217e6334a268413a390bb371aec355fbe4c736f7da75f9c887541a2b7d0dac018b6138f021e77266ddece8468452ada39f5e63d0209b9d6dabf975413256dcaa15ac14b6068e177056c7bf0f0f7c884a3402032298cd559a6312039400632327f9c0e763e52798cb177da4475e4b2405c157ca427741108d33ed0b7a3f53438ce6b725c6dd5814af51cfa45dbced557f726db130d55cde7533bc2092d6b699c2c870af282731e18d651ae85b3db4ba02853f8c87fd5e3ab69bc57b08b81f83c239ccf22e817e2ada4d0ad14487ed14612c8b0973ec0650a55f6bf9af4ae9256ad3546a3f67dd35d987ef21909a94c50f0ef0640e755b1c4e1a012af0d31766eeb5df31cd104c64eb62eb4efb139cf305769401d213f96a488d5ee7e3ce32b0192ee8f0831bfbe8fe95de956886b524d3319b73fd56dc60e9f1c72d78155a97c6f43697b20466b3e7aebd357b91696e7348f4599b34f3591eddfce2a7bd849ab16f7b43ebb16e23d6f5210efa30ab3ba8d32c40662b8662fd911544bc2458c6569ef75a9b9df6a0f6d80d658ba86b241ca19ce9a6fcf01d3daa95afb59c3d89a18b948621394327fc5e920a75f98f5e2b3d6c95fd852adf567b6d37c54d2970856a599f749e2c55dac7c23e3fb1a63bb4cc47b8b94f3d589ac4beef0aad4e6292f:4c00a71668d3213c29c7041c5a037edf13c6514bd0ebc880c909caff1506a45d27809fb74e6602ea2aad0f842831b74fb3d6900ccc520652da28368fd90ca30e114743e82a0993cec9705067abd77c168b53677ede5c159fad36f06fc1a14acd77f883799ed9883f9915aea638ec1741f3f4215855fb5b07df3793bbe5b568eb3594391a9ef5727fab93e57469b37de125b1e9f2e6fe2c3d1a10ecf87b6c0a665c6d460a170eefb9bf716cd8faea9764f579ff34ebfa9c4cfb34706d8dd7c9eb1d10b2df460a46bb5789430bf449158b5824f2a3a7b918b33acf2d9ebe90216d1b7cbf4af770c5db95fc62ff3a3c385c3a8217853b7346634aaf30607288db0c483bd4c222eb332cb89dc4a217e6334a268413a390bb371aec355fbe4c736f7da75f9c887541a2b7d0dac018b6138f021e77266ddece8468452ada39f5e63d0209b9d6dabf975413256dcaa15ac14b6068e177056c7bf0f0f7c884a3402032298cd559a6312039400632327f9c0e763e52798cb177da4475e4b2405c157ca427741108d33ed0b7a3f53438ce6b725c6dd5814af51cfa45dbced557f726db130d55cde7533bc2092d6b699c2c870af282731e18d651ae85b3db4ba02853f8c87fd5e3ab69bc57b08b81f83c239ccf22e817e2ada4d0ad14487ed14612c8b0973ec0650a55f6bf9af4ae9256ad3546a3f67dd35d987ef21909a94c50f0ef0640e755b1c4e1a012af0d31766eeb5df31cd104c64eb62eb4efb139cf305769401d213f96a488d5ee7e3ce32b0192ee8f0831bfbe8fe95de956886b524d3319b73fd56dc60e9f1c72d78155a97c6f43697b20466b3e7aebd357b91696e7348f4599b34f3591eddfce2a7bd849ab16f7b43ebb16e23d6f5210efa30ab3ba8d32c40662b8662fd911544bc2458c6569ef75a9b9df6a0f6d80d658ba86b241ca19ce9a6fcf01d3daa95afb59c3d89a18b948621394327fc5e920a75f98f5e2b3d6c95fd852adf567b6d37c54d2970856a599f749e2c55dac7c23e3fb1a63bb4cc47b8b94f3d589ac4beef0aad4e6292f: +585871941cc282e333d57bbfc3d4aeda862cfa0a375030cd594b3692848c5f004f343816cd48050b678d3adf70008877c9fcf5cb662cc4ad2b93864c02090707:4f343816cd48050b678d3adf70008877c9fcf5cb662cc4ad2b93864c02090707:651c101b3e2dfef0783ce9f61bd0a8bdc9307ac0488b9dd70cd90a7ed8f179a78935556295b91cc2b97211e3b981b8dafcb3d06b76d0b6eda7fc61945c0ee2652c5ac454256496cb82f98cc1cc92d81893b1082b31b47e6d22a2de609de4ce8d7cc4f4a152c47f410d7fc37d38ccd629a4b33e6221896081797d0753dd4faa8a8b44d6c4677166dfb4d5215446360a3c28d8f68e38ab54608b98821b83c187b5393ad874a76f4f5d729493a1fd74cc7719caea991d229c5d0c8c4c5f89d8e4345f4f52214313410b8c06b3315f45ed0c2f9138ab966aec0a645b6dba76380a539123e0f33b97f3d060394a3053581ffdef3e6d36531166b553a9dde03105c04af697d95e95217fd6dc968bf3b448d5f3a8e4f5ae7edc30ec78b1aea4f0db189a949a122138cdfb5f9693db004baed1a421dc44122f327287f727cf989fcae3cf3be3e3dd9b9f53502cf5d9fb186de791d310d122869c9fc3b695dec1607477f3e149e52b63cfdfb0d983e89af2f75a8f489843ec05c5ea5f0e721acab387c68025f20abe0d27b4ce29f4a64fb7f8e8a332873d3ed121fb493414b8cb0c00ad3ab616c5be5241471adee9f8f46974eae84a4a8ce6fabb7f5d9a6b75a7e670456fcdcd1d982e8f827a4bbb69dec7e3053dfe835b70301b7b763f0004bc906e145542f487b4dba2ed561bd1a20306236af4b36e4068e8c007b9454f8741a5f8f079ec1db8835eb6544290d6adb52a70d7675d85df4a9a1255bfd936c331fe51c0977d124b5a506d29c6eec33caa25d8eb28952d6ffb9d6e3da890382d888796d374607f6643b89e7326d9edc49a0f53bdcb8cc76ffd393a7706522d04170036ccb66330dbac9da7e6168caa88cb62181e55a7b6d521a2115e23e202ee2480b587be4501447979a8d736f9012ecf00e67b31e8104f6e7df08a9683cdc89c03a4e37ee22928d45fa19094e0d6e7b40b:298856e570188aefcad81bb970f076965770c26762fe29e6554dc7afcdb801723bf6c763b4ccd65f4e15d7d8ea38fcf67ea9d28590c79255c1cfeba7b5e45a00651c101b3e2dfef0783ce9f61bd0a8bdc9307ac0488b9dd70cd90a7ed8f179a78935556295b91cc2b97211e3b981b8dafcb3d06b76d0b6eda7fc61945c0ee2652c5ac454256496cb82f98cc1cc92d81893b1082b31b47e6d22a2de609de4ce8d7cc4f4a152c47f410d7fc37d38ccd629a4b33e6221896081797d0753dd4faa8a8b44d6c4677166dfb4d5215446360a3c28d8f68e38ab54608b98821b83c187b5393ad874a76f4f5d729493a1fd74cc7719caea991d229c5d0c8c4c5f89d8e4345f4f52214313410b8c06b3315f45ed0c2f9138ab966aec0a645b6dba76380a539123e0f33b97f3d060394a3053581ffdef3e6d36531166b553a9dde03105c04af697d95e95217fd6dc968bf3b448d5f3a8e4f5ae7edc30ec78b1aea4f0db189a949a122138cdfb5f9693db004baed1a421dc44122f327287f727cf989fcae3cf3be3e3dd9b9f53502cf5d9fb186de791d310d122869c9fc3b695dec1607477f3e149e52b63cfdfb0d983e89af2f75a8f489843ec05c5ea5f0e721acab387c68025f20abe0d27b4ce29f4a64fb7f8e8a332873d3ed121fb493414b8cb0c00ad3ab616c5be5241471adee9f8f46974eae84a4a8ce6fabb7f5d9a6b75a7e670456fcdcd1d982e8f827a4bbb69dec7e3053dfe835b70301b7b763f0004bc906e145542f487b4dba2ed561bd1a20306236af4b36e4068e8c007b9454f8741a5f8f079ec1db8835eb6544290d6adb52a70d7675d85df4a9a1255bfd936c331fe51c0977d124b5a506d29c6eec33caa25d8eb28952d6ffb9d6e3da890382d888796d374607f6643b89e7326d9edc49a0f53bdcb8cc76ffd393a7706522d04170036ccb66330dbac9da7e6168caa88cb62181e55a7b6d521a2115e23e202ee2480b587be4501447979a8d736f9012ecf00e67b31e8104f6e7df08a9683cdc89c03a4e37ee22928d45fa19094e0d6e7b40b: +0588acd4e09ba90274c8f3d1575b2bf364a776884a9aeb4103415e163ba0bf813ecae697b425d87e34a1d944098e3d32e2c1ec56c3627df80ba2b8a43ddc1903:3ecae697b425d87e34a1d944098e3d32e2c1ec56c3627df80ba2b8a43ddc1903:f828f8c9dad298c5b719daa852b17e762598a70f4ecd16a2fc596eb0263899e983d44edcc7bd240cb07610600ae96aac0dfc3be387b616850899b5cf44e1767ffaca3df38158598424f8071414c704e60b422ad77377fa7f6a8c5d0ebc0235e2d43a984f3adf759eb10447f3c2f6b80d5a11ef41d3a09852c0932a1b9ac23e6f40a167de21041bec8885f9433eb80b95c9785958046cdb7bf147a79947823b4149ae0521d7e5aabc1564fa4044106e2e392e9c344457e9929376ea9b4229c6e7738fe79008d554c429396914c36387f579b46bab146f6a9510eb6f8c85551cbd84c7dc0d0b1c010ccba5963a7f39f181e44dbc98e495aa63c01059cbe6a99b07b449e7759c9af9e0f8d9054a67a348fa19d7f91ec0a4d4f2c7026c3b849259a350417fd86cab2142e4cfe3c0afbf25182a2d52bd2e0bc920e85080832b91b927b62948a67c317eb09091461d493eea5ffc47bf085582968258a3c8dd81a858270bddafe7925684a15ffb51bcfaab931afa465e3090e86be41e3547cba234b85fe7db700496a505002df3ca4eaec7b96278c7d1a77db834a91797bbb826d092aa28b49545ed3b1eda23be11a3f528b955cb0c4fa66e16e957e5704cf319e5f79cc09f2d054e6daf19e2926b11e1e413ff822ca141f7c3d385ae95dd20b346e583cfb0c229ec39cf889a5419cd37bc184ef5fb144622080a302d9d7745c451f7d88242cc26b916a3569abc7d1f216d57797a472bc621761758e840eb8e29bc8efcb7aafc7cf8f4e59330d35ee107496dec6e714b1fa4309837bb47eb3a06b4604dd20733cc0eaac2649e18c07342ef55d19b8d039591ac2869acc34b6c3c1ca3cf263ff84ca43a5f6465ba34888c109013b32bfc0d0d15f5a76cec270ab3ac9a106331312f5a0a84282c3a3d4aea1e7cf53dbf8b240bdd111c34d2a93dfd1258fe9267133f7554dcc21a8f439c165d:a111b9706d242cd36d6e8741cbb097b9e2fffa40f43fd6f2d3d91693667332b5f2db5ee3ea20b83291b8405795b74d633d46f475ab7c47617118535b8051d907f828f8c9dad298c5b719daa852b17e762598a70f4ecd16a2fc596eb0263899e983d44edcc7bd240cb07610600ae96aac0dfc3be387b616850899b5cf44e1767ffaca3df38158598424f8071414c704e60b422ad77377fa7f6a8c5d0ebc0235e2d43a984f3adf759eb10447f3c2f6b80d5a11ef41d3a09852c0932a1b9ac23e6f40a167de21041bec8885f9433eb80b95c9785958046cdb7bf147a79947823b4149ae0521d7e5aabc1564fa4044106e2e392e9c344457e9929376ea9b4229c6e7738fe79008d554c429396914c36387f579b46bab146f6a9510eb6f8c85551cbd84c7dc0d0b1c010ccba5963a7f39f181e44dbc98e495aa63c01059cbe6a99b07b449e7759c9af9e0f8d9054a67a348fa19d7f91ec0a4d4f2c7026c3b849259a350417fd86cab2142e4cfe3c0afbf25182a2d52bd2e0bc920e85080832b91b927b62948a67c317eb09091461d493eea5ffc47bf085582968258a3c8dd81a858270bddafe7925684a15ffb51bcfaab931afa465e3090e86be41e3547cba234b85fe7db700496a505002df3ca4eaec7b96278c7d1a77db834a91797bbb826d092aa28b49545ed3b1eda23be11a3f528b955cb0c4fa66e16e957e5704cf319e5f79cc09f2d054e6daf19e2926b11e1e413ff822ca141f7c3d385ae95dd20b346e583cfb0c229ec39cf889a5419cd37bc184ef5fb144622080a302d9d7745c451f7d88242cc26b916a3569abc7d1f216d57797a472bc621761758e840eb8e29bc8efcb7aafc7cf8f4e59330d35ee107496dec6e714b1fa4309837bb47eb3a06b4604dd20733cc0eaac2649e18c07342ef55d19b8d039591ac2869acc34b6c3c1ca3cf263ff84ca43a5f6465ba34888c109013b32bfc0d0d15f5a76cec270ab3ac9a106331312f5a0a84282c3a3d4aea1e7cf53dbf8b240bdd111c34d2a93dfd1258fe9267133f7554dcc21a8f439c165d: +7d14023eb48bbd437649a241877905a3c932f14640f29a0fb134114e8f33f582ea5c11b4b2c5ef4ab706cca3475043c95818eb565a797e33688afeacd68adcca:ea5c11b4b2c5ef4ab706cca3475043c95818eb565a797e33688afeacd68adcca:9001db31f279be505319b8e72bde1199512980df65f0d8a9b4930467413a997b97a362b572a4b44bc940487f18b208ce6ac5c68716d3af1bcef170383b5c4b5c47e44737726f9383bc4f144768bf5cafb4e9dfe39761e6ed478971d1c70e6dab2fd0499dff9293b239d16c960261c68218b9f5b1bee690f0d240c1b3db711f9e821f0809bbeb9aaf249ccb168c67d965562d24f848516140bfd9fc050d4f20da5a1794468a9c0725ea5c669d5c630d9310e5745107dad37261b5d91e38e08512e6f373ec5dcad5ca09072907c8fb7bf3b926c3339490b3f51f7644e73ae2ec01d61be7c6526536b4ffd1ab6849fe0c2f40d3bda2a49e5550b8df979081da85168d0f71582b903677526d1f1b1511e138b684fc46aac8bd80c3def7ee8138190461807c5536125cb0e2c3d083a187c7269cb531ec3678787b32555cf04ab093c9002e7d792b4d933f2e3070f39ac8ccf8d5f5455f12109d8a8aeb4e212fad4a70b147c04a7b918460b1316376e64020859517eb7ee30c290be8b8d6f9673915256c3b04b9d9054b52338e0d360785e46a182844c5c3766aea8ed311b2d481c0b7b2114e418ed17f8debf01a83ff37517024ee9e28e0c90dce6d059ffee413d27cd62783a8b8b5016ad276e39dfd8f8f3ddfc428101818ce507f003eb58c9a5cc8b1aff05aab8f0d7f1d1f6d4b871dbced1f3d2866239752fb13f6e18034bb2b5a6635caa6ecc462e058ebe2fa651d3d0f36e20a31f765e4b958270bd825c6818aac1ad7563135aeedf14a2b6d398b6e34008401b218461820071c5af77846cb9c328190c061d5aa6e0ecde7ef5856b0e6814f833f704096df0825fa4b46dcdacfa27cd87bd7bfeff7f8cae166a3a04d437c7be716c49045c7bd3d1349627c9cbd04c15f00a696e3cffbb45af29122627e7ed33b4249913bec00f0e28aa11298cce8b649081fe3b169b4aaeaca485bda:31339dce23336df5b2b193522aa3dd2d4114a66af1656289c952bc11c9b210f77a54d46161f4e0c52b3013e40b9e9e8427d851325bd71c4d99353eeed751080d9001db31f279be505319b8e72bde1199512980df65f0d8a9b4930467413a997b97a362b572a4b44bc940487f18b208ce6ac5c68716d3af1bcef170383b5c4b5c47e44737726f9383bc4f144768bf5cafb4e9dfe39761e6ed478971d1c70e6dab2fd0499dff9293b239d16c960261c68218b9f5b1bee690f0d240c1b3db711f9e821f0809bbeb9aaf249ccb168c67d965562d24f848516140bfd9fc050d4f20da5a1794468a9c0725ea5c669d5c630d9310e5745107dad37261b5d91e38e08512e6f373ec5dcad5ca09072907c8fb7bf3b926c3339490b3f51f7644e73ae2ec01d61be7c6526536b4ffd1ab6849fe0c2f40d3bda2a49e5550b8df979081da85168d0f71582b903677526d1f1b1511e138b684fc46aac8bd80c3def7ee8138190461807c5536125cb0e2c3d083a187c7269cb531ec3678787b32555cf04ab093c9002e7d792b4d933f2e3070f39ac8ccf8d5f5455f12109d8a8aeb4e212fad4a70b147c04a7b918460b1316376e64020859517eb7ee30c290be8b8d6f9673915256c3b04b9d9054b52338e0d360785e46a182844c5c3766aea8ed311b2d481c0b7b2114e418ed17f8debf01a83ff37517024ee9e28e0c90dce6d059ffee413d27cd62783a8b8b5016ad276e39dfd8f8f3ddfc428101818ce507f003eb58c9a5cc8b1aff05aab8f0d7f1d1f6d4b871dbced1f3d2866239752fb13f6e18034bb2b5a6635caa6ecc462e058ebe2fa651d3d0f36e20a31f765e4b958270bd825c6818aac1ad7563135aeedf14a2b6d398b6e34008401b218461820071c5af77846cb9c328190c061d5aa6e0ecde7ef5856b0e6814f833f704096df0825fa4b46dcdacfa27cd87bd7bfeff7f8cae166a3a04d437c7be716c49045c7bd3d1349627c9cbd04c15f00a696e3cffbb45af29122627e7ed33b4249913bec00f0e28aa11298cce8b649081fe3b169b4aaeaca485bda: +e8306bada6d55eb188d9f75c815cc914e93c9c7222391c15bbaeaf9354437935bf2798b8e554f51e2286c3034a88e577ff23fa32a67244ea8245912e8bf46da4:bf2798b8e554f51e2286c3034a88e577ff23fa32a67244ea8245912e8bf46da4:d7043809c3e3dc00b17efd52c9130b11b786f1e257b5e22f81a7faae600bbcdfd518537fe852c642359762fb75e8ad859249e6ab49ce1bb04f2492f2aac35446ba6eb03e76de3abd2d5fc7e6146843add042860a4a16b59bdd7d038378a35e1a04b1217a55710d937e2c9032232ea2cdd1d25a0bff71ef5d3e0c056b29cb92f6df692bde14dfa50e132bebd89e9f1833880b657a781e94ecb603041756e5517d4423c56fadc13e2b318088feddf3b5c83c20b46fddbba92305e48606dab748ce3848b843f4711f370c3ec7d5e19ab4c0ac1ae15aaaf23d65fecedabc08049b9e29113e5761ed9d1c62eb075cabb2674cdbe1e3a889bae4b1dd31b6a5b2ea1b8dedcc3c515edc4467c30231176cd44bec8a057951ab5cd39a9623f8af8473cd27d93302bf8aa624c9c3c5799da1dc494494ef8ff1dbe0187ea5162670b8d098c3a94919398dadf79e6c2491c444392c29cd50d57435063290842bfa0e8530faebc006d6ea7801117e0a3f019ee28fb3792235402e2f69b87a43dc227f9de316029756c3167d64a3a3f6d73160331d5a18eee5b0e6e22a663efdcc8d67af3bced041ea843a5641603ec72efd644e173d199a8c830b2ea5fec0378027c37225afcb604c4cdcf409be1c509c9a377be0d0524107c6d92b5f09a29efb7109295670bb1a1dd3ea008bb79185f09b98f020c43f1439685b96f6199311a090870f0d9b10d495cd410aa95b7e53749be3a6c0fbc729f96cf8564397b09c13514016825f72f14eb93294d7010accfd11f17a6ac8f544263d6038d5c7db29486291b30ea49b6b54cf88826dd252cd9dbb57d841b5a4cf702a3264faa4dccc86ab14daf124ef3d5335a6878d065c6ba29991045765ee5542cc9f5d9f354dcd2c6e0cf7ff3a30f649b5912d971d633578f1e9f263874d0565c247301dcbd15d76211ae2d3d506fc64deb7e042565d438e2bfb249243b7:cc6627308e2f424383fa70594f575791600540027a2751619b283affeaebc9c9d29ac6db286dd2c1b596587b878d1df4781d436bb570c1c0f0d33368dc66520bd7043809c3e3dc00b17efd52c9130b11b786f1e257b5e22f81a7faae600bbcdfd518537fe852c642359762fb75e8ad859249e6ab49ce1bb04f2492f2aac35446ba6eb03e76de3abd2d5fc7e6146843add042860a4a16b59bdd7d038378a35e1a04b1217a55710d937e2c9032232ea2cdd1d25a0bff71ef5d3e0c056b29cb92f6df692bde14dfa50e132bebd89e9f1833880b657a781e94ecb603041756e5517d4423c56fadc13e2b318088feddf3b5c83c20b46fddbba92305e48606dab748ce3848b843f4711f370c3ec7d5e19ab4c0ac1ae15aaaf23d65fecedabc08049b9e29113e5761ed9d1c62eb075cabb2674cdbe1e3a889bae4b1dd31b6a5b2ea1b8dedcc3c515edc4467c30231176cd44bec8a057951ab5cd39a9623f8af8473cd27d93302bf8aa624c9c3c5799da1dc494494ef8ff1dbe0187ea5162670b8d098c3a94919398dadf79e6c2491c444392c29cd50d57435063290842bfa0e8530faebc006d6ea7801117e0a3f019ee28fb3792235402e2f69b87a43dc227f9de316029756c3167d64a3a3f6d73160331d5a18eee5b0e6e22a663efdcc8d67af3bced041ea843a5641603ec72efd644e173d199a8c830b2ea5fec0378027c37225afcb604c4cdcf409be1c509c9a377be0d0524107c6d92b5f09a29efb7109295670bb1a1dd3ea008bb79185f09b98f020c43f1439685b96f6199311a090870f0d9b10d495cd410aa95b7e53749be3a6c0fbc729f96cf8564397b09c13514016825f72f14eb93294d7010accfd11f17a6ac8f544263d6038d5c7db29486291b30ea49b6b54cf88826dd252cd9dbb57d841b5a4cf702a3264faa4dccc86ab14daf124ef3d5335a6878d065c6ba29991045765ee5542cc9f5d9f354dcd2c6e0cf7ff3a30f649b5912d971d633578f1e9f263874d0565c247301dcbd15d76211ae2d3d506fc64deb7e042565d438e2bfb249243b7: +363c1ea7c32ea328a055af7bd8b3bfd204fb0bbd4bf42ffe262f3a5ebd54da557a83ecca51ef6e5aa043a5ce04d9288add49a277548bd3016b693ffa79a22edc:7a83ecca51ef6e5aa043a5ce04d9288add49a277548bd3016b693ffa79a22edc:c41c1e1fb75954a0ae0ebc29090b9fc533e693e7c7105cfe40ef526e4e12a7405221f218c7ac019e1d4c92da2853f2d726aa62277924df0c343fc3d47cd5a99a3e279b26a1b13b1f2aa36f7ccb4b54fbef18bd87a55f1bc40ce7b2029145ee7aab391795ac68de6199f50594fc79611b85131c143021f26fa358da0c7c6a65dde076dab488675b722309e5ed9746d18a89309906a7a9df237dd27bd590ccc77c402ef6e19ca63cc86b85160330ee6e1f1f47a2ff807eefadc00963520a1c600a3e45aa7fb2554f47d897bd86d81c3b0877101222fa7850b80ce3bc06c9e58c0c96e32fec8530c9fa1e4163f0ef8456952bf6dd58045a363d61880e9ac976a3603ef77a4c395e6a07e342f6023b8af10225cff240efc0366a799fd86e9d062060d8724033bdf67588cd73ac284de4c6943cf45ee4f75f5937d97d78105f0bbece04d3dcb5e424eff89b773e5d6b4f37efa9a0654cb3ef345278a62d876cfef9a3dcdceb7081441877ebd5fa30c9d954e3684fa476a4f485d426fd3c8c32bea0f9cc20b15e8fdfc3ca4b302c074f508132d15de625c10ae0737811463dcc55fcc4014b20208fffcefa9dd452119b1652de41348f69f2c488f5cc1856d6e78a5cbe3e373dd4598e2d39f876eb94e0b01b21fa9129ef41b639f4e05e69deb1835ed44b9112a6862a5bcea072c6e1b8f0f058f46bac2a845a582d148f17760b9e0a2ba60bbbf3884af94dd4c7ec9db08e9a5bcc6dde1346442ee1f4707d1f79b69ba867f418dc279173f77adbc58ab85ea393b9dc68261900c1caa82d2f50474c42aec911314278c0affa2a6b6c36d1ff88f3b49fb2b7c339d2a7c2b3049f8c0a08d16a9e8df93d130da484bdba6dbec534cd51097a048221106bab48d67f951b7505a1484892b85779c5a3111702124d957acf2dc352ef9ba247bc80e2ce96269ce85e78b9ebda989076dd5ff73e1eb275e5d7:5fd1e5f9922a12f636b72a7d6217091f948a55bcb1826b8fcaf99d26416c7ab1351c10f4093ffd8a2af86914a0a98184ec7e06d2dee87fdc0f4a47f8c63cf501c41c1e1fb75954a0ae0ebc29090b9fc533e693e7c7105cfe40ef526e4e12a7405221f218c7ac019e1d4c92da2853f2d726aa62277924df0c343fc3d47cd5a99a3e279b26a1b13b1f2aa36f7ccb4b54fbef18bd87a55f1bc40ce7b2029145ee7aab391795ac68de6199f50594fc79611b85131c143021f26fa358da0c7c6a65dde076dab488675b722309e5ed9746d18a89309906a7a9df237dd27bd590ccc77c402ef6e19ca63cc86b85160330ee6e1f1f47a2ff807eefadc00963520a1c600a3e45aa7fb2554f47d897bd86d81c3b0877101222fa7850b80ce3bc06c9e58c0c96e32fec8530c9fa1e4163f0ef8456952bf6dd58045a363d61880e9ac976a3603ef77a4c395e6a07e342f6023b8af10225cff240efc0366a799fd86e9d062060d8724033bdf67588cd73ac284de4c6943cf45ee4f75f5937d97d78105f0bbece04d3dcb5e424eff89b773e5d6b4f37efa9a0654cb3ef345278a62d876cfef9a3dcdceb7081441877ebd5fa30c9d954e3684fa476a4f485d426fd3c8c32bea0f9cc20b15e8fdfc3ca4b302c074f508132d15de625c10ae0737811463dcc55fcc4014b20208fffcefa9dd452119b1652de41348f69f2c488f5cc1856d6e78a5cbe3e373dd4598e2d39f876eb94e0b01b21fa9129ef41b639f4e05e69deb1835ed44b9112a6862a5bcea072c6e1b8f0f058f46bac2a845a582d148f17760b9e0a2ba60bbbf3884af94dd4c7ec9db08e9a5bcc6dde1346442ee1f4707d1f79b69ba867f418dc279173f77adbc58ab85ea393b9dc68261900c1caa82d2f50474c42aec911314278c0affa2a6b6c36d1ff88f3b49fb2b7c339d2a7c2b3049f8c0a08d16a9e8df93d130da484bdba6dbec534cd51097a048221106bab48d67f951b7505a1484892b85779c5a3111702124d957acf2dc352ef9ba247bc80e2ce96269ce85e78b9ebda989076dd5ff73e1eb275e5d7: +db2228ffffa9d2534aef918fb85b821ad360e2d39dec5aeb2db0df02497f94166d0195777f8105ff523b79c59e3c3081fe89db6f87033f094fa5a940cef84bb4:6d0195777f8105ff523b79c59e3c3081fe89db6f87033f094fa5a940cef84bb4:fc07cd99040f13e5a84f94746d6bb868f752b448b62d99593ef29e43cc8245f0470f65552d643220f6719285e15c37a6d174aef76088ccda5f88685b52dae284c65b380da345a2e1af2ed76480d269cb934b4317620b792ebb39b2a678247d6d815f2a5cb9aa560e4bf6deba4c0a0ddc82d0e5a5a65acbc478e1ec6b064d7bb7388a73f6eda30b0b6b73dd8f879263ad1a0348671dcf211cb96ed08ed52f3317da68185d6bb2589dc11d755d47a3b6f6a0386a8594d9570b2e9b0d4b5e13dccd9bb7acbef0ab276a7aebe12931be67f10de267a029895301f5662530ad8ab3d230b3b6d7093acdfbf274757a9078e20c23bc822deffa61005486102c01ab82bdc8cdcf1bb37f9b56d39e50fd5a6895416e767f4e36c1a41778908125b5ca3f92a90da9addff155fb1fd7768808a80f203ed737ef007763bd2fea9ff28c84b43551c9fc438ffc47fcfcf64dc7700613aa8b3af8633ae8b6987437c0aa4781be1e821396c536cb3005d05549b1cba70135afb7fe3068961cad3a1463cc0b5560684e27bba77aef419d823868e0cebad1f1ce0ae902744a152dd29451a17e28a89a7158a1836efce4a3e5c7d1faa4c3875bc46c4d9be22d66d366ac6f59538a00b275b02fac6da755a854081997d5d1d0e6e568a5958cf334c518cd517ab9d73c48d6cbc4ae4eea4353113e7e4a7c05920e686bf07afbfb8dd2ec4f18fa7138e57d332cd7a4228fea73bc09252f24427294ebd3645ee0996c2e851a8aa51a7cd9fc2eab47c0ab213f4f51d216091ed089e4592e9bb0828b858f84f60b93ad84a0a22827cbd27414b781322a04d3960828f638df2834c7f7839d70db126bee5af2ee7559a8ac4c01a6c391396af93fa0608940297ddf8900c5ddb466340ae51c60c7ead762447e76d8bccb573997cf6614d188a0b9a2f56eed9b0f9d463a19787f4092581a65c6bf781b93c56087e54ee1343aab:82189d340bc11ceaa400410e08bae9d901af059125e953786f8a043ddf11f7b2f8e3b617accd78e2939adfabf2d2471fafd6f5bc45b14075b328e34d8075b207fc07cd99040f13e5a84f94746d6bb868f752b448b62d99593ef29e43cc8245f0470f65552d643220f6719285e15c37a6d174aef76088ccda5f88685b52dae284c65b380da345a2e1af2ed76480d269cb934b4317620b792ebb39b2a678247d6d815f2a5cb9aa560e4bf6deba4c0a0ddc82d0e5a5a65acbc478e1ec6b064d7bb7388a73f6eda30b0b6b73dd8f879263ad1a0348671dcf211cb96ed08ed52f3317da68185d6bb2589dc11d755d47a3b6f6a0386a8594d9570b2e9b0d4b5e13dccd9bb7acbef0ab276a7aebe12931be67f10de267a029895301f5662530ad8ab3d230b3b6d7093acdfbf274757a9078e20c23bc822deffa61005486102c01ab82bdc8cdcf1bb37f9b56d39e50fd5a6895416e767f4e36c1a41778908125b5ca3f92a90da9addff155fb1fd7768808a80f203ed737ef007763bd2fea9ff28c84b43551c9fc438ffc47fcfcf64dc7700613aa8b3af8633ae8b6987437c0aa4781be1e821396c536cb3005d05549b1cba70135afb7fe3068961cad3a1463cc0b5560684e27bba77aef419d823868e0cebad1f1ce0ae902744a152dd29451a17e28a89a7158a1836efce4a3e5c7d1faa4c3875bc46c4d9be22d66d366ac6f59538a00b275b02fac6da755a854081997d5d1d0e6e568a5958cf334c518cd517ab9d73c48d6cbc4ae4eea4353113e7e4a7c05920e686bf07afbfb8dd2ec4f18fa7138e57d332cd7a4228fea73bc09252f24427294ebd3645ee0996c2e851a8aa51a7cd9fc2eab47c0ab213f4f51d216091ed089e4592e9bb0828b858f84f60b93ad84a0a22827cbd27414b781322a04d3960828f638df2834c7f7839d70db126bee5af2ee7559a8ac4c01a6c391396af93fa0608940297ddf8900c5ddb466340ae51c60c7ead762447e76d8bccb573997cf6614d188a0b9a2f56eed9b0f9d463a19787f4092581a65c6bf781b93c56087e54ee1343aab: +66b50f692e395eb83386e027c82ce3fdee3bd899b0d3179db086fbf524f57459448536e982408437ce89674053e3c589c98c095c60021a118178c6261d8810fe:448536e982408437ce89674053e3c589c98c095c60021a118178c6261d8810fe:7428a964212bcbe8df7d59e48e923480aa0ee09b910d04efb6903662efc3107ac8fdc0c5f39272740cd877e16cd71c549238c337220ce2f6b5a1fc6f7b0a1cd4ed21d93889081e34fb7fdecf4178bbd431e611e539d900c3d0ac3dc7107b36b41d6d0d5d32c19727f908b6eb367febb352a493581ff128b56c4caf6fb8e09981f0d37957d1282017fbb807614c20f465dc02b0cd969983bd5ae1ebf6578d7ff3ceff320e25562199dee934757cc1f58d5540c41aac1ce4f211f0b8ec4107174030e702bc6a8a9c85c505c9316aefea3e4372242de019b35e2bd3c5a956521971c106a3adbbc13cdc4f7f9d3c58b96a344b4ac3ef6bd8aca6ed9876b43e6497faf7fa4cf27fbcb665730c091e13aaf7e9efe7dd10e14eb19a9200424210ec8b8fba7e69444ce1a9e3a7b26c11f6b7145b6983a7805776484031bff52e81ae769b70a282b094ffb5fb5525dc1a872e207e827a2e11f4ecf7b5308c748a9278ea7bd66188194400430c8cd596ebb87221e536f6afe1f1505d6a59f41d16a2f014e1cfa513f7a69731d7bfdb2affcefe0537d42c796e3fd27e41b7ca72051bef28bb7bde7010dcfed8aa16ef676db6e520c3cef8d6f58a9a2813cff0f7041f87fbfb8431e020ede1d4eaf19e23b983445c5915b54adfb557fc20d0058f40f5e09825dba8d8f20c00f43b3aeebb6157be32ec54627d5d42ab813cf97f095d26db8036c12e82cb963e8001167e61ab393b4cca755ecea869954e323fa5262c5fda3e0be9a51e5af51fa6444824fb837cc67be537a87569c30cf0114d39a03942de4e1cd523355dab1af36080a9a9a548be1c2a7fbe5433772315d283e5156df648bee4b7dcda74f15905d542be54873c15c53ff42acabf8c56f257d764722db4e9c718e12098a3457486a6c947ac2de0af53e82cf950bb37ca29c8dadfa3646db4982af572d39b268c7f96b03ef6b653c87945f29bc5:bd13f6362c07078922f30c6330751bf6e7cf42a76916ee653eb17accff1fbbca35258c4cbc582a5e8cc94fd2c7edeb53762f1fc23123d7f4f145409b31cd38027428a964212bcbe8df7d59e48e923480aa0ee09b910d04efb6903662efc3107ac8fdc0c5f39272740cd877e16cd71c549238c337220ce2f6b5a1fc6f7b0a1cd4ed21d93889081e34fb7fdecf4178bbd431e611e539d900c3d0ac3dc7107b36b41d6d0d5d32c19727f908b6eb367febb352a493581ff128b56c4caf6fb8e09981f0d37957d1282017fbb807614c20f465dc02b0cd969983bd5ae1ebf6578d7ff3ceff320e25562199dee934757cc1f58d5540c41aac1ce4f211f0b8ec4107174030e702bc6a8a9c85c505c9316aefea3e4372242de019b35e2bd3c5a956521971c106a3adbbc13cdc4f7f9d3c58b96a344b4ac3ef6bd8aca6ed9876b43e6497faf7fa4cf27fbcb665730c091e13aaf7e9efe7dd10e14eb19a9200424210ec8b8fba7e69444ce1a9e3a7b26c11f6b7145b6983a7805776484031bff52e81ae769b70a282b094ffb5fb5525dc1a872e207e827a2e11f4ecf7b5308c748a9278ea7bd66188194400430c8cd596ebb87221e536f6afe1f1505d6a59f41d16a2f014e1cfa513f7a69731d7bfdb2affcefe0537d42c796e3fd27e41b7ca72051bef28bb7bde7010dcfed8aa16ef676db6e520c3cef8d6f58a9a2813cff0f7041f87fbfb8431e020ede1d4eaf19e23b983445c5915b54adfb557fc20d0058f40f5e09825dba8d8f20c00f43b3aeebb6157be32ec54627d5d42ab813cf97f095d26db8036c12e82cb963e8001167e61ab393b4cca755ecea869954e323fa5262c5fda3e0be9a51e5af51fa6444824fb837cc67be537a87569c30cf0114d39a03942de4e1cd523355dab1af36080a9a9a548be1c2a7fbe5433772315d283e5156df648bee4b7dcda74f15905d542be54873c15c53ff42acabf8c56f257d764722db4e9c718e12098a3457486a6c947ac2de0af53e82cf950bb37ca29c8dadfa3646db4982af572d39b268c7f96b03ef6b653c87945f29bc5: +55328be4b370822733ff3989a6a3282d65fe8f207ab7270d7c2e727ca3cfaac4518e02eef52f5aaebde3d108ea79ecadfc4d994ce1953621e54b7b3b121ff8ff:518e02eef52f5aaebde3d108ea79ecadfc4d994ce1953621e54b7b3b121ff8ff:6c24c9afbbf12dcaee6f10e4089252f2c60b2ab93a02c1602fb5de4ce3bd923eb02fe1039fdc15996a446915e767dee0176dddb78e9d6bbf069675775a829dd808d376b0cf7920bf1a66e1303ba52419785f25f28bb33899ebde840c0ab14b919a6580cbaac3a805627b9c4a77baa16f825a9eac2d6d3641651493370e50eee94c74049764365605ab4dac1a030227a330aa178f2f8da377af73f0bb040bac12366e65e0591055f9f23eaca35e9688d837a3c0d99c168fd886acc922cf37a7118ef8a44bb0a4fa4288049309a7dc1bed80621e1063e3e592c0fba42d7398eb15f74028ac15d7ed65a6368a13b7f956d19547eb506ce7ec90734eb949cff1d98ce414f10adcba8c007320018750a71bd36d3b6bfd6127054508e3ef65d99848514d33d68b58e3a4b224f79b6e34dd480340467fe7f025cc88213d808fbb5b91e2e43cf9d950640798659273d47a25f1f0132f6882faadbafba28fee5fa17272c1a9001172b3ab6ff2c315f26c07734405b5ee8b5e4f08e1e3b8aea019467fb071887f191901a21c5976c1ca8aaf0a1d4a2e698e7623e9bbe9ca2a67a153a16f895e6dd9ea924441b4bd0b674552e398b8d970343a9bc776a3a3fc1a8660c5625d6081b5d87f0f8ac9f07ab5abe77cdb8e30d2fd1f6f46525c75dd0dd1ca3281cc89346fb3e6d7388ebee154cb59bd9e95ed6a41d5df668b59ea137868eb120b8a2cfdf4674414fd279699f28b5a5ccc2e2fc802a4c9e0b85b76f20f6bce2a4954886fc402670a71efd261f5dd7bca16884a287c622fd445f68d44151cc0134b229da38daaab81b5c960d57700ca92b26d0b142134ce94b7be6c18610ea2136f8ba8329a2e8c000b8f02fe05bcf72cb71f8c72535ffcd818e38e7992a8f0c32ac62177d1522ae552c60c1ee616b75e4b3442e79657e4a333c0b3d744eaf260d0c336931686a6d668c64fef440052352c2b258cfb65:f58db19fd834e15194c3c0f8a6a50ebc4cf074e80ea2e70cdaf1e169bd51ebd0990bad77c4fa208b8dd1e2c8574c01b5f596c8dfa6bb8e6ae3a47ff412e7e2096c24c9afbbf12dcaee6f10e4089252f2c60b2ab93a02c1602fb5de4ce3bd923eb02fe1039fdc15996a446915e767dee0176dddb78e9d6bbf069675775a829dd808d376b0cf7920bf1a66e1303ba52419785f25f28bb33899ebde840c0ab14b919a6580cbaac3a805627b9c4a77baa16f825a9eac2d6d3641651493370e50eee94c74049764365605ab4dac1a030227a330aa178f2f8da377af73f0bb040bac12366e65e0591055f9f23eaca35e9688d837a3c0d99c168fd886acc922cf37a7118ef8a44bb0a4fa4288049309a7dc1bed80621e1063e3e592c0fba42d7398eb15f74028ac15d7ed65a6368a13b7f956d19547eb506ce7ec90734eb949cff1d98ce414f10adcba8c007320018750a71bd36d3b6bfd6127054508e3ef65d99848514d33d68b58e3a4b224f79b6e34dd480340467fe7f025cc88213d808fbb5b91e2e43cf9d950640798659273d47a25f1f0132f6882faadbafba28fee5fa17272c1a9001172b3ab6ff2c315f26c07734405b5ee8b5e4f08e1e3b8aea019467fb071887f191901a21c5976c1ca8aaf0a1d4a2e698e7623e9bbe9ca2a67a153a16f895e6dd9ea924441b4bd0b674552e398b8d970343a9bc776a3a3fc1a8660c5625d6081b5d87f0f8ac9f07ab5abe77cdb8e30d2fd1f6f46525c75dd0dd1ca3281cc89346fb3e6d7388ebee154cb59bd9e95ed6a41d5df668b59ea137868eb120b8a2cfdf4674414fd279699f28b5a5ccc2e2fc802a4c9e0b85b76f20f6bce2a4954886fc402670a71efd261f5dd7bca16884a287c622fd445f68d44151cc0134b229da38daaab81b5c960d57700ca92b26d0b142134ce94b7be6c18610ea2136f8ba8329a2e8c000b8f02fe05bcf72cb71f8c72535ffcd818e38e7992a8f0c32ac62177d1522ae552c60c1ee616b75e4b3442e79657e4a333c0b3d744eaf260d0c336931686a6d668c64fef440052352c2b258cfb65: +7da05f04e5d38b989b83f72f7ab26c138776758f4f577e49dc73d6013ff43759b1de5167f4d330804eec9eb565ef4055f1b64dd95e1c9b27c67ffef91482cca8:b1de5167f4d330804eec9eb565ef4055f1b64dd95e1c9b27c67ffef91482cca8:a6a861d8947c5cd6ad0819602e32ea7681c8f73010eee553e5defbf7982098b5f7b39924bb7959ad64c30326bed560bf51e9983cda5dff4f311eea24cbe68c6106ceac9b843aa4e2ad1b6f8ae1e4f96871fc025be4a616385ff2d4b7f56829abefaf6aacbb780d6cbbc951b6e05a787f885e3325611665ecc924274aa531bc133f62c76cb3ad148f3c9579a815a14200b7648dae0b07b327d3bfccdb6fe3b6cbd70ea65e6c0cc2516a896696d07b2e77713b0bee3b92fb1b6f75b0820a5cb62c5fe6204003943e24857166fbdf571f115d45f42e75901df8b12c32618aacb0d24286c8d30396051fc272aa17f4d2d47461152aacd3faa2b7b208312278e809240592d1d1aa585c56280e66ffd92b5717d0cd1eb9fb7401def879487c374e5c530b6febf911122574d24fe104b4f45c7c601e6c917d3c1882c1ad3c555d8f2ce955b5a10db0d5a8b8ac7a6266b2e6b27ad0ee34f47ad857367d52f7096d4bacef0e46725488424b93b89acd429ffb5ef33a0b081dd09479679196023c3967f44ad41eb1a2395527fd3b79768f1b885f0429b495ab60525691be84650632a2f66cb63ad5bf2f6ae70b668c5a193f7499fc4fc42cf8cb308ce5029a5027babef55d1925ecfba9f27eb6081619ed0df8569fd80e9da104db39b5b8140bfebebd29085440065819deba8d469ae8b3ea6d3bac5891f9a4ddfb7f1f06d13c31a07ee53fb54bc97bd08696394c38e7f3680c0f02f975f469921147a409859097813b4c3fa43d174ac402f1a528cb5fc4b807518432eff33407a111ca3a3d7e9e84135abac8a8f52ea631c86d74a1c6e5749edd1491c0024e7de7fe52856829b72fd13da63a1a2343349df662ab3163536032346e5347f043fff528bf67150922fff2026bab742db9cae7cb2e3c74580719652c28447c5e2098231797ee6ef1231f5792054bc3359a32c86d2f94f85fa7d4a7419dd241ff662a:05f117f9bc3ea55d455e9ef135e92e7665d18070d8f5e375df67be1817ce14357a55e70166f326b77d85243227cf67d8f2e0bf8440cabfb05275b373f1e1190ea6a861d8947c5cd6ad0819602e32ea7681c8f73010eee553e5defbf7982098b5f7b39924bb7959ad64c30326bed560bf51e9983cda5dff4f311eea24cbe68c6106ceac9b843aa4e2ad1b6f8ae1e4f96871fc025be4a616385ff2d4b7f56829abefaf6aacbb780d6cbbc951b6e05a787f885e3325611665ecc924274aa531bc133f62c76cb3ad148f3c9579a815a14200b7648dae0b07b327d3bfccdb6fe3b6cbd70ea65e6c0cc2516a896696d07b2e77713b0bee3b92fb1b6f75b0820a5cb62c5fe6204003943e24857166fbdf571f115d45f42e75901df8b12c32618aacb0d24286c8d30396051fc272aa17f4d2d47461152aacd3faa2b7b208312278e809240592d1d1aa585c56280e66ffd92b5717d0cd1eb9fb7401def879487c374e5c530b6febf911122574d24fe104b4f45c7c601e6c917d3c1882c1ad3c555d8f2ce955b5a10db0d5a8b8ac7a6266b2e6b27ad0ee34f47ad857367d52f7096d4bacef0e46725488424b93b89acd429ffb5ef33a0b081dd09479679196023c3967f44ad41eb1a2395527fd3b79768f1b885f0429b495ab60525691be84650632a2f66cb63ad5bf2f6ae70b668c5a193f7499fc4fc42cf8cb308ce5029a5027babef55d1925ecfba9f27eb6081619ed0df8569fd80e9da104db39b5b8140bfebebd29085440065819deba8d469ae8b3ea6d3bac5891f9a4ddfb7f1f06d13c31a07ee53fb54bc97bd08696394c38e7f3680c0f02f975f469921147a409859097813b4c3fa43d174ac402f1a528cb5fc4b807518432eff33407a111ca3a3d7e9e84135abac8a8f52ea631c86d74a1c6e5749edd1491c0024e7de7fe52856829b72fd13da63a1a2343349df662ab3163536032346e5347f043fff528bf67150922fff2026bab742db9cae7cb2e3c74580719652c28447c5e2098231797ee6ef1231f5792054bc3359a32c86d2f94f85fa7d4a7419dd241ff662a: +1b8ec65880edbf039a13e970b15aa67e192aa02ca65cff9ada17d4558f40137d12c1191e4de3bd44d039070153adb7b581f600e9a1dd69aa89f277c7069e76f8:12c1191e4de3bd44d039070153adb7b581f600e9a1dd69aa89f277c7069e76f8:37f18b7f64c5133479d6dae3bef679cdc21ece3f5b579a6a9c3fa2e59e9be87d2009f74e1cfdaccb1ce37d00702369bd169d94fdcf85af9fa3217d27e6ed6d1d8e5df7615e8e37ea55de1fd0b06d77b4c83b929d80586fa0694be72ec8b365ad2cbcdd2b1ad8cf7f036dfa4daa1a9036cdb120432227b1f07b8866b122120309eb914ab84cddeba1dec48ab92636728588fedb3aaad7e7dbb2ac30e63c6f5f90fc6ce62d6d3bd88b0d5aacfa61de9f3267b300917b57a48036ab20c9a05446b8767494af249e7de7bc507a2207cc956f7184555a7d5d8883bb4b3e93f2dcfc57b0da8638658dcdce885d44d9cc68b1d8170a3677cc5e50cbf33d543ebae4477d9239cf83384ec59b4233e8ff3343f06f301877729a53d420bf01c62e66ab7fe55dd87ee823a58fcb87870e1f52e879177cd439c533f5a223e5a3436fe9d6426548dacfc86a0846d3ed23ac042563e887ff46aad005f4e1dee3ee0ee4c27a7251709ae40abc5e256864e4785a4edd8b2adf1bc5b4018e28d0b175867b02d052a6e17e411a3d8beb2a4208b76cc621fd18be148e235d55aa7127706557dec053a13f1a47dfda405b3fe5bd28ef5d348619f51e595ef5055f839efaf110e4901631ac31a02f4f7ee424a3a2c3e00d2602d2cc1e492906eea420a9268238ac6622a08974e5730292e6ed510256efde667e0d9a0ff2213f54120ccd81ffaa6b7cc48141a2b729852af583d26aa51fbde67be4df14e520c2257a73c5c2e3c3d87dfb25361175fd18abd7e99aa09b85f88f19c8d82d45858f3144c5dfb7a49ede45b4efd8710592a3720636e7e889c7e22ad13b2d44bb7e2b47b2963a5fa3f2557b85bc0c693de3d22ef9464f7b814a20a4676ad26fcaa03544c6aad41283095fcd1210aa8cc029ff5a26005a891226c298e94a52aa7133913ec9d22a5b2ac0bc6f15b251d0b93889213cd1b1e5c6fd08f1a8f5cbd4215329a3:bff269a35d6c8e552ce716d1638181ce8583b45c0ec593b4e58c40ac76e7f85ca1dafffd68541e623a1e35a7c0972688b25eed72f4da57eca16857a8263caa0b37f18b7f64c5133479d6dae3bef679cdc21ece3f5b579a6a9c3fa2e59e9be87d2009f74e1cfdaccb1ce37d00702369bd169d94fdcf85af9fa3217d27e6ed6d1d8e5df7615e8e37ea55de1fd0b06d77b4c83b929d80586fa0694be72ec8b365ad2cbcdd2b1ad8cf7f036dfa4daa1a9036cdb120432227b1f07b8866b122120309eb914ab84cddeba1dec48ab92636728588fedb3aaad7e7dbb2ac30e63c6f5f90fc6ce62d6d3bd88b0d5aacfa61de9f3267b300917b57a48036ab20c9a05446b8767494af249e7de7bc507a2207cc956f7184555a7d5d8883bb4b3e93f2dcfc57b0da8638658dcdce885d44d9cc68b1d8170a3677cc5e50cbf33d543ebae4477d9239cf83384ec59b4233e8ff3343f06f301877729a53d420bf01c62e66ab7fe55dd87ee823a58fcb87870e1f52e879177cd439c533f5a223e5a3436fe9d6426548dacfc86a0846d3ed23ac042563e887ff46aad005f4e1dee3ee0ee4c27a7251709ae40abc5e256864e4785a4edd8b2adf1bc5b4018e28d0b175867b02d052a6e17e411a3d8beb2a4208b76cc621fd18be148e235d55aa7127706557dec053a13f1a47dfda405b3fe5bd28ef5d348619f51e595ef5055f839efaf110e4901631ac31a02f4f7ee424a3a2c3e00d2602d2cc1e492906eea420a9268238ac6622a08974e5730292e6ed510256efde667e0d9a0ff2213f54120ccd81ffaa6b7cc48141a2b729852af583d26aa51fbde67be4df14e520c2257a73c5c2e3c3d87dfb25361175fd18abd7e99aa09b85f88f19c8d82d45858f3144c5dfb7a49ede45b4efd8710592a3720636e7e889c7e22ad13b2d44bb7e2b47b2963a5fa3f2557b85bc0c693de3d22ef9464f7b814a20a4676ad26fcaa03544c6aad41283095fcd1210aa8cc029ff5a26005a891226c298e94a52aa7133913ec9d22a5b2ac0bc6f15b251d0b93889213cd1b1e5c6fd08f1a8f5cbd4215329a3: +e75388026a6a6d6c6d199e362993a5b1044901e18a76c2fac7261a6d1c19a4f3b9ce14251c0cdf3bddb206dc6b8b2b7f5b7e4dd1be2ce1863ff18806ae00f1ee:b9ce14251c0cdf3bddb206dc6b8b2b7f5b7e4dd1be2ce1863ff18806ae00f1ee:b99cdc847211c06642dd111bc5e0beca53a74ffba2e3ac93afb4b0947518e8323527330a4efefbe4bafa00bafecb434ab1e5b7ce65656f7a4fd856aa6c385ed8d7bd6285580d7dd60882e69c19da076909d647de095a80e98ad89b814aadcbbf6f033c49202f656c0910503959cf97cd0fa82d5f6d22fba3389951294c4f7cdc21eb8244bd6560637a5eca62a8eba1f4a933d187a75f86711643af358831c8c16a9a0f09e253b2395e9cb371611eecdd66b4ab521aa94b3f20237eae41cd10c5e21a452d48e748187f354a67adf681b0fe61cdaec94a5eaf01269fceb570d514ff3c55ff1dba2fd2df17f86a8aeb747838113dee94a43b1384cbe133cdf6427e8d122e4e933704da6e26cfcee97fe3f629b60b91b2dd863867fa79801e2b916ec4c0fb62e07159421e657974307a1d02f7f2ed4724a8b521a861f55f35521e8b2e1a84904c428cfc5b6014bb0f8ba8434c2209bd40aca31130db97743333597d2351d5f6811741f62688973bd773d30266fd1efbd89d47a964f9d01997153d087d92696616dd103a934ccbac4c1d142f2075d4e22c3da4a0e973b23863196287b79174fa29755fc6d9b5e100ace0a45975e503b254d3f195c261710910fef106892c08bb296d230cdea9f5a11f91acaa6e7c05e92c281d2b3155fe4480b0aa5e0db41d10e05cfdefa4364051cb755dc72ffa978c00b94a5f212dc691f839b49de97e0139d65e8d73b2b289b26a12c6ccd8edc04adb452af7ff094aa901eaf57651eb1b87b833d0a09b4a4a6462f40664623769e95079f3c962850cc3b401bb0058b8475b10c862f32f300a2b143b3dea269ddcbea7be7dd2426d0d4204eb66a39f1318822dcb9c561398637f4ab8de196768ace74f348c012dd1babec17f5300ffe0d7aaaeafef7db650a8f2f309a9793f52c685c7e1d5133274915784899c481d485c9bd30e99fcdc97d96ef07487da663befe68299df:6d0f83d9c55d84bcf9a86147d9b6ba9ad537832fd0f99dae7e72c8139afcb30c7b24f6b292e32f9847097551b7fbfd510c84e89be98254441457bd08e5f05302b99cdc847211c06642dd111bc5e0beca53a74ffba2e3ac93afb4b0947518e8323527330a4efefbe4bafa00bafecb434ab1e5b7ce65656f7a4fd856aa6c385ed8d7bd6285580d7dd60882e69c19da076909d647de095a80e98ad89b814aadcbbf6f033c49202f656c0910503959cf97cd0fa82d5f6d22fba3389951294c4f7cdc21eb8244bd6560637a5eca62a8eba1f4a933d187a75f86711643af358831c8c16a9a0f09e253b2395e9cb371611eecdd66b4ab521aa94b3f20237eae41cd10c5e21a452d48e748187f354a67adf681b0fe61cdaec94a5eaf01269fceb570d514ff3c55ff1dba2fd2df17f86a8aeb747838113dee94a43b1384cbe133cdf6427e8d122e4e933704da6e26cfcee97fe3f629b60b91b2dd863867fa79801e2b916ec4c0fb62e07159421e657974307a1d02f7f2ed4724a8b521a861f55f35521e8b2e1a84904c428cfc5b6014bb0f8ba8434c2209bd40aca31130db97743333597d2351d5f6811741f62688973bd773d30266fd1efbd89d47a964f9d01997153d087d92696616dd103a934ccbac4c1d142f2075d4e22c3da4a0e973b23863196287b79174fa29755fc6d9b5e100ace0a45975e503b254d3f195c261710910fef106892c08bb296d230cdea9f5a11f91acaa6e7c05e92c281d2b3155fe4480b0aa5e0db41d10e05cfdefa4364051cb755dc72ffa978c00b94a5f212dc691f839b49de97e0139d65e8d73b2b289b26a12c6ccd8edc04adb452af7ff094aa901eaf57651eb1b87b833d0a09b4a4a6462f40664623769e95079f3c962850cc3b401bb0058b8475b10c862f32f300a2b143b3dea269ddcbea7be7dd2426d0d4204eb66a39f1318822dcb9c561398637f4ab8de196768ace74f348c012dd1babec17f5300ffe0d7aaaeafef7db650a8f2f309a9793f52c685c7e1d5133274915784899c481d485c9bd30e99fcdc97d96ef07487da663befe68299df: +5b323fc01a16c45d1064667d2ea4a7ea59d20342562d12fbc598d5aa7300688ed4141b455d301642bada2814afcb1620d5eb56d92b1185fe5dadef559625fa71:d4141b455d301642bada2814afcb1620d5eb56d92b1185fe5dadef559625fa71:ad24669ef55c540a8ed162ce1d28f01760a60719a0377336eb00b1ecbe6f61601cd564f92c956804f9bed4e1476b94e5ea8cca80cb49a304ef851f7f675abe58e6681dc012ad55e51b021d9828569d0bcc9e0527a3fc03c891d17a90e6337a1ea67f2f08810587693837081e4c08a3d72c536c2140da200ba456c376f61d05651f0c5f395711f41c0d6eae98c906764d1ebef3f9046cb7c8622640fcafafbfb8f62e1cd32c66ee1c55509489a538ab612999e7997b779c6422eff109da4df82920930d8d363d7830908795a3888f25d667e14d155ed44581be430f7973b574e2bc0b134cf139fb4bb01dbda41b67b98147d8012f40677f4b80ce4a534c90adeabf484b21fa994b7a175f8a8b8a4075564478ddb05024580bab038cd9eaa1dfda552fb31229429b614fa1d80c52614e84faa2217f260ff7ccea8c7b06e3d77ff874eb81fc8597e5fcdcec951b5fe64a1af86e73193a882469eb3ba3c382734b2887b419316ea448afc282478c25f7bca18429cbbffd8871177c5ecc7d8aa9a1b9ec87192d29a52539c081c3593332444cbe66872cf3d0e197292b82b0be5fcd858cd6ca48b53ee5b61641bcaaf31d819c7e1cedaf9ee6b07e09caedfb30b9204a1d4ddb70560cbe1eb0c0ec43f1d178201b290819fcdc92c63e0db60fb87dff00e512648c8958a847efc36346073f1a4f1f2317060f1c543e6f01b42485beeb56cab3bab26e6a0ca6935802c762b799159e320f36b5e83d4aca8962aa2c3c2b7a3870e9e04731f3948cf941e21d50964e5d635a35a53e299811b8cadfcb4416c57598a3fd05410910dbc0ea2c78fdb92574997d58796279eaaa78b36dcef1c9a129eeff82399a26d008ffa3bf0418ff7d39b6427f341895024d16e22a0c62a82beba2e2bac23dee18cfcd5db2397f378c5367309082c44eb43cedc15220253a62320399665f71349cc1b944f58c73a10a0bbfd4caf12891e3:e2eff607f0227a29d582d69f3458acadd3226fceaac0abbdaed52675c51630073cd3a901707ecf05e893f2c36daaf0cc4901116946b5770dc038125f6d131b09ad24669ef55c540a8ed162ce1d28f01760a60719a0377336eb00b1ecbe6f61601cd564f92c956804f9bed4e1476b94e5ea8cca80cb49a304ef851f7f675abe58e6681dc012ad55e51b021d9828569d0bcc9e0527a3fc03c891d17a90e6337a1ea67f2f08810587693837081e4c08a3d72c536c2140da200ba456c376f61d05651f0c5f395711f41c0d6eae98c906764d1ebef3f9046cb7c8622640fcafafbfb8f62e1cd32c66ee1c55509489a538ab612999e7997b779c6422eff109da4df82920930d8d363d7830908795a3888f25d667e14d155ed44581be430f7973b574e2bc0b134cf139fb4bb01dbda41b67b98147d8012f40677f4b80ce4a534c90adeabf484b21fa994b7a175f8a8b8a4075564478ddb05024580bab038cd9eaa1dfda552fb31229429b614fa1d80c52614e84faa2217f260ff7ccea8c7b06e3d77ff874eb81fc8597e5fcdcec951b5fe64a1af86e73193a882469eb3ba3c382734b2887b419316ea448afc282478c25f7bca18429cbbffd8871177c5ecc7d8aa9a1b9ec87192d29a52539c081c3593332444cbe66872cf3d0e197292b82b0be5fcd858cd6ca48b53ee5b61641bcaaf31d819c7e1cedaf9ee6b07e09caedfb30b9204a1d4ddb70560cbe1eb0c0ec43f1d178201b290819fcdc92c63e0db60fb87dff00e512648c8958a847efc36346073f1a4f1f2317060f1c543e6f01b42485beeb56cab3bab26e6a0ca6935802c762b799159e320f36b5e83d4aca8962aa2c3c2b7a3870e9e04731f3948cf941e21d50964e5d635a35a53e299811b8cadfcb4416c57598a3fd05410910dbc0ea2c78fdb92574997d58796279eaaa78b36dcef1c9a129eeff82399a26d008ffa3bf0418ff7d39b6427f341895024d16e22a0c62a82beba2e2bac23dee18cfcd5db2397f378c5367309082c44eb43cedc15220253a62320399665f71349cc1b944f58c73a10a0bbfd4caf12891e3: +be1c112f78cf13aefc5ce7e33764aca4481f9f88b018e122db9f8dac14624605ae389936bbf6d16e3c1eeb6474298970866e12ec9c1d6aea2fd9db6b56aa59c4:ae389936bbf6d16e3c1eeb6474298970866e12ec9c1d6aea2fd9db6b56aa59c4:d77f9aeea0fe98ed7fb74d582a402bcb7931474b4a95d523f3fb769fb7097d2be4c6ec1052140163222553aa8f4f89e421730014ec73469720cea967f88b6a48d02a2ddc1a121fdffb8ae127738e293c4d6b1b74ad03844de6bfe821506b3a7a81d19c37a7f01ca481471219efe2a7b92c4bd2ac07743b4975696441714b84d63c549d7a6fb61f16fbcdb72b914d7882d091f9706da38c1a81a1c6a40fbec0d8e238b5d56d460e909f85479f7ad8b119f35455e34010caa7e5d01f38e301ad37e8005f6ed29e4a102db3f61d84093f78c49a9648c977bf4d5b689f71f406f8ad7b9aeb1ae22133a84ce1b278b2cdde465901b23a179d072a80879d0a24d2af197b322a07bf5d40eeab3af12117f13021dfc1681aba5c083f2596e37f1123422bbdca3b2c32cb594f56c325e0c564a1733288053459c62488925cd80e7c944db998c3c7be546bf89d7a511ccdba4b809eee0fc2873dad72b4cf3ba051289bb3f4e9925732e45ae7741058c8fd11599dd843927e3d14598bb83052d33569cfb02af0c88fa7aea4bb46841cd2ddbdf5988fcf325ff104a5dfc4a30d269d2a949730c3613bddd3673b42f6090e6a60e4a253062463a65d7e7fc0030bba769ca344bfa9ac823f58cb5cee8a5fc0ca37228de5a4d93e0ecf7f10821659a2261f7ef1596eda4e411cf3c9669d81de74547ce4bf833eb432f385ce9038fe848a8c96da7f01fd95bea06d1d747c8ae736495bba2285be5c32afea449520cfe8e1ce25f9077ed0ec0f6598a9b8f7386f15358170ccefc3d5ffb009288154de877c2409ae5fd8fef0093f1c36b3a8f547432cd0f62c4033242ad9921a8f11c00f366da9396930a80c997df429a4f5f4e45c7a6d7e02af033186757c73cbe64d2d4e78eaafe27539528035f2cfcf8eaf0a42bd25f88b2fc69e42668fae6677c9ac9091d9d15a41f3ace65d90a0229873dcf254256cca449ed4c17d5435bae4:f5fc5acb17e9957ea304f123b650e144c9e4377283509d431da6a2bbd527beb382c9f58745a3e56dcc655bd2ebb7aeefc93edc3f20d8d3c37923031eec0cb407d77f9aeea0fe98ed7fb74d582a402bcb7931474b4a95d523f3fb769fb7097d2be4c6ec1052140163222553aa8f4f89e421730014ec73469720cea967f88b6a48d02a2ddc1a121fdffb8ae127738e293c4d6b1b74ad03844de6bfe821506b3a7a81d19c37a7f01ca481471219efe2a7b92c4bd2ac07743b4975696441714b84d63c549d7a6fb61f16fbcdb72b914d7882d091f9706da38c1a81a1c6a40fbec0d8e238b5d56d460e909f85479f7ad8b119f35455e34010caa7e5d01f38e301ad37e8005f6ed29e4a102db3f61d84093f78c49a9648c977bf4d5b689f71f406f8ad7b9aeb1ae22133a84ce1b278b2cdde465901b23a179d072a80879d0a24d2af197b322a07bf5d40eeab3af12117f13021dfc1681aba5c083f2596e37f1123422bbdca3b2c32cb594f56c325e0c564a1733288053459c62488925cd80e7c944db998c3c7be546bf89d7a511ccdba4b809eee0fc2873dad72b4cf3ba051289bb3f4e9925732e45ae7741058c8fd11599dd843927e3d14598bb83052d33569cfb02af0c88fa7aea4bb46841cd2ddbdf5988fcf325ff104a5dfc4a30d269d2a949730c3613bddd3673b42f6090e6a60e4a253062463a65d7e7fc0030bba769ca344bfa9ac823f58cb5cee8a5fc0ca37228de5a4d93e0ecf7f10821659a2261f7ef1596eda4e411cf3c9669d81de74547ce4bf833eb432f385ce9038fe848a8c96da7f01fd95bea06d1d747c8ae736495bba2285be5c32afea449520cfe8e1ce25f9077ed0ec0f6598a9b8f7386f15358170ccefc3d5ffb009288154de877c2409ae5fd8fef0093f1c36b3a8f547432cd0f62c4033242ad9921a8f11c00f366da9396930a80c997df429a4f5f4e45c7a6d7e02af033186757c73cbe64d2d4e78eaafe27539528035f2cfcf8eaf0a42bd25f88b2fc69e42668fae6677c9ac9091d9d15a41f3ace65d90a0229873dcf254256cca449ed4c17d5435bae4: +bd8523eda899b984230e328875b9672edc9fcd24ea5cc12d7b572da4be01fb7b02b734ebbe88c13bfa95a5d964fc7ef9d395bd6303f065dc4ee17b3ac1548b7b:02b734ebbe88c13bfa95a5d964fc7ef9d395bd6303f065dc4ee17b3ac1548b7b:16c216c9be9f0d4b115410bdfd1593c8e262221ab97a2a395a12198f95c30205b08962d4893118ba9ff99ab1c7a6e1f2f175191070ac945327ad6c470babf7928b07dd788c85b64b712e0aae6c0ea20281e42fd561e83e3fbac67f14000ee56d981d2a2f0b9ca00a9ea47ca2f6fc8dca1035fceb142c3f26f20e3c732207ffff11b79695bdafa415214a4499302326605cf0b8c82f2b11392ecc90cd74a7b411b6d907a3d5c130c879b7cf880f22bbd7f0e95933718e96d7d16caea9f2c39e89b13cd52266273604a96b51d6e34f706735ddd9fca44d09cd86bb7217600e0d34d416ac249f2e41bd0f4abcbd2580adae21d7eba5fa44f39d780f17eb85ccbef58fef903a280d95f8f3210789fa12e120e21b6e8cad917835bbdcc3b07e84693954e23a94f99f937ddb0d4a18d42c3ea8fca7d1ea6ed53a00246f99ea520e6405bd2aa549b06e7da722c1ba74aa1c136e8ea58baaf8d37658693f3e0b44f631dd6d08ffdf4f09189d3035a3f03468e29696ef05e02cc1aabfecbda2301b540cb0eb0a75bcce73db9273a9161a98ad898fcd6579fb7e4b3279544f2e0bd774dd1a8157daa88a70321167703c60a608a4b54216590375e597fe21aea97b52185d0e37a53b6388a707a2bc24acf94425f84f3d56bc9f7ee7412a9e1833ad55b7eae6da581698166383a2eba8b6f53920f517a5c80bd3e03faad4087e3ee8fec9a79a01c779512133d7b6e5f1dec766300dc405cc21a8c583fb73bc90cf24385b086049d3bf20c300983c0b351538dccb227a14fafd23ac4b26be81a2b120cf216fc58354f9dcbf05f66339ad6ddc2cac14677b90e247ebb6c5c229007dc60f374a06d404eb23eb1ec49907c6e881629e1867268ca6fffa59aa3ca8f6c295162b9536c2be22bbe3b72380ef11b61b357a6253100e30a586818ba003fa3ffd1fc919881c05022f94848598f217fea222507220d108a28fc7bc39a8a11c:fcfcdb088dcbd0a51bd301e3e1561671935d8b6f719c5d92690640d3c91e775bf4054132efc05a2122fc209db3c3343233ff8aecebd52daa2b3b21eeb15fd10216c216c9be9f0d4b115410bdfd1593c8e262221ab97a2a395a12198f95c30205b08962d4893118ba9ff99ab1c7a6e1f2f175191070ac945327ad6c470babf7928b07dd788c85b64b712e0aae6c0ea20281e42fd561e83e3fbac67f14000ee56d981d2a2f0b9ca00a9ea47ca2f6fc8dca1035fceb142c3f26f20e3c732207ffff11b79695bdafa415214a4499302326605cf0b8c82f2b11392ecc90cd74a7b411b6d907a3d5c130c879b7cf880f22bbd7f0e95933718e96d7d16caea9f2c39e89b13cd52266273604a96b51d6e34f706735ddd9fca44d09cd86bb7217600e0d34d416ac249f2e41bd0f4abcbd2580adae21d7eba5fa44f39d780f17eb85ccbef58fef903a280d95f8f3210789fa12e120e21b6e8cad917835bbdcc3b07e84693954e23a94f99f937ddb0d4a18d42c3ea8fca7d1ea6ed53a00246f99ea520e6405bd2aa549b06e7da722c1ba74aa1c136e8ea58baaf8d37658693f3e0b44f631dd6d08ffdf4f09189d3035a3f03468e29696ef05e02cc1aabfecbda2301b540cb0eb0a75bcce73db9273a9161a98ad898fcd6579fb7e4b3279544f2e0bd774dd1a8157daa88a70321167703c60a608a4b54216590375e597fe21aea97b52185d0e37a53b6388a707a2bc24acf94425f84f3d56bc9f7ee7412a9e1833ad55b7eae6da581698166383a2eba8b6f53920f517a5c80bd3e03faad4087e3ee8fec9a79a01c779512133d7b6e5f1dec766300dc405cc21a8c583fb73bc90cf24385b086049d3bf20c300983c0b351538dccb227a14fafd23ac4b26be81a2b120cf216fc58354f9dcbf05f66339ad6ddc2cac14677b90e247ebb6c5c229007dc60f374a06d404eb23eb1ec49907c6e881629e1867268ca6fffa59aa3ca8f6c295162b9536c2be22bbe3b72380ef11b61b357a6253100e30a586818ba003fa3ffd1fc919881c05022f94848598f217fea222507220d108a28fc7bc39a8a11c: +33a85ae150bbf552f41663b21521c296d246dd6cf8195df851c695bd15f4a502c8c9c42521008d5efff576c7e4a56083ced9a928da6fd5cf93fda572a5a2d0c0:c8c9c42521008d5efff576c7e4a56083ced9a928da6fd5cf93fda572a5a2d0c0:937e05f2f1fdbd41731553e77cf181b5079758940aee8e92623fb1d5f07128b7d7f17e4842707a562c45ba69264c0f730a821c7db6bf82990dc651269b296c335179113053d6f85bb096b2911165fa3900cb102416487ba8078679c6b336dff38763c08dcd20fa66dda45c575df150d851165a4804973830f436df60b81319f9cfb564c0652896ed5f1849cb3354f50f0012f286e8a30c213528693474004e8504012b945560c074a6a163432cf4ac4ba7175cf26005db7199ee96d893cd1aad3fdf5d57460ef02dda6d3a140825196f3f8e2f37da36b6fdad184f2740f116de758a92917030c5fb80f0262496d2df93c7e276f25da7dbed8eb8dd4c563aba55b82af6ba3a70ca5f858b44a033cfb795604ddee746e7c8ae79d272fb9a2341a2a202df5eac08de75ad80c6580d92b169f2e1318857b1b1421c30f3dd461093de2d345ede7404b72a450de07b16eee68ce62887b6eaa436eee684be75ce0e1f96263e8d8736f9ba000d88e9e5860f328ae1e2dc73099d32fceb1bd2c0123698a49bead190a00ec9a6f87133eddd45316f65eb0d329b07b9a66bb9fe42588bf7b8d06efec1986b82a081ed3f6802e9be73464784559a4f2c097ba14b0bfd5d7e0aff65cb69abd03f8616cd7edf7ec368219edcf893e9ee71dad9f18d79e568265ddc6716223213235bb928e908dea827784cd1af396d590c81f4eacdfcf89c5cac96fa050064a22841ea715f8c89d6d5afbf597a4d005dbc6b13856d335b42a9a82edcb949835cca20b0a23de51cc3aec35566eff0c5ae1ab3751320d2c310495238eda383c38a4163152b8815690b8ff015035d1d00ea4a0d6caf324bb71a664a1bed31480784a68f438caa359e8d2673c857d4b8c0b6c695847b86800ea3d734b5ecc4d52b507ac69b3a6778916016ebc2315f44c90bf0c3e7dae01d49cbc303402bbc634ae1191f3f6fd63d303b0c0be033a47b90f8d3a77f0a44:bbe4cd63676e26d675a191151d30db72b5b84d461eec6564af867ab41bae9931147885519ec9d7e6c818743c8ef6d5167b35b421363c09b357367fe8de443a06937e05f2f1fdbd41731553e77cf181b5079758940aee8e92623fb1d5f07128b7d7f17e4842707a562c45ba69264c0f730a821c7db6bf82990dc651269b296c335179113053d6f85bb096b2911165fa3900cb102416487ba8078679c6b336dff38763c08dcd20fa66dda45c575df150d851165a4804973830f436df60b81319f9cfb564c0652896ed5f1849cb3354f50f0012f286e8a30c213528693474004e8504012b945560c074a6a163432cf4ac4ba7175cf26005db7199ee96d893cd1aad3fdf5d57460ef02dda6d3a140825196f3f8e2f37da36b6fdad184f2740f116de758a92917030c5fb80f0262496d2df93c7e276f25da7dbed8eb8dd4c563aba55b82af6ba3a70ca5f858b44a033cfb795604ddee746e7c8ae79d272fb9a2341a2a202df5eac08de75ad80c6580d92b169f2e1318857b1b1421c30f3dd461093de2d345ede7404b72a450de07b16eee68ce62887b6eaa436eee684be75ce0e1f96263e8d8736f9ba000d88e9e5860f328ae1e2dc73099d32fceb1bd2c0123698a49bead190a00ec9a6f87133eddd45316f65eb0d329b07b9a66bb9fe42588bf7b8d06efec1986b82a081ed3f6802e9be73464784559a4f2c097ba14b0bfd5d7e0aff65cb69abd03f8616cd7edf7ec368219edcf893e9ee71dad9f18d79e568265ddc6716223213235bb928e908dea827784cd1af396d590c81f4eacdfcf89c5cac96fa050064a22841ea715f8c89d6d5afbf597a4d005dbc6b13856d335b42a9a82edcb949835cca20b0a23de51cc3aec35566eff0c5ae1ab3751320d2c310495238eda383c38a4163152b8815690b8ff015035d1d00ea4a0d6caf324bb71a664a1bed31480784a68f438caa359e8d2673c857d4b8c0b6c695847b86800ea3d734b5ecc4d52b507ac69b3a6778916016ebc2315f44c90bf0c3e7dae01d49cbc303402bbc634ae1191f3f6fd63d303b0c0be033a47b90f8d3a77f0a44: +ba9e686204975c3bded4c1e9f74c7e4c7a7e3c9981d01bfca0ad0115c3f0f5c34990fce6952e8b7d0afcf4bf9dba9bce1bc4815e37511da7c2ad4892581de03a:4990fce6952e8b7d0afcf4bf9dba9bce1bc4815e37511da7c2ad4892581de03a:46bb48952ae58f2bf58f5be8df4f316b50f363ec84eed8f82ff4c04b0692d03aef26e8e1e6c9549a2247d540a6e22feb11e57f4b808a2097e8a7b6b3b7af3769e6d81d64886e6962372f4f39e49cd46c1b5f735f380f7c277d099776ed1aeaa57a359c0aa8c72f40eb91a1bf07ea157f5ddb30409d6e3af98990ce7f30affdac5e22010646dca96a540060fc908a3125b000ad1ed3a0f255cd34f15d7dd1fd681c3c35a1cd652056ecc5264d39aaf72a9bb83a551cc934887ae107afdfef063217270d9596891418bd461bba63de65be067b1b7864fe46484c7c9e96349a7c03a80fa055050aa18ace2a44b4a03c947824172b30e21011159443ca3cefaf696a7aa8f98011260c9436bf48991f41d4d507b96ce7323e531adcf66347c55c8855673a9f2ec89b5c8024460617ec7271773b36d64fc14eb5d82652c53a3031457227093d118fd8eb9384e80229041a96a6493450f97e6736263abf1ecd9e9fb9a4f0f6d667fa824151485edc37b34acf3d8c35f9c1be48b5e96a12af8e2d35c23a03580f211da6316b34c56bee872d47641bca77da640fdbbad5a9ad8ab9dc7957913da734ad37492ba4de8cf136cccdeb6ba3f1bd3f003be7263c4f2a40c33f24ca3339596e6c3428338100ebcc0722d4f50d30b33b912d4e7c1a9fe65f6658a6f239140a62c3261e10392ed1930aa917652d3bd2be4e8a08ab97e145b920abb31ee4bcd5a0d71f638180f61c245823a399a734a4dcde0997880245ed71eb9bc65e3c6fc95ab920b8024c17d44ced0037d04a133c2641782f1d622df45269b491d3fa2a1227579eaa386de3e7de7bc455c6a154eee5727fff0437a20076c5c3b0577cac5b4b6934e269380222461a60f954e48979c0671217f16f7027983034121093186c78705fc27dc92e2eda4116a6bf7d23e0548d62b67b25c41ed06192bc26ef1397bf1601f3a6e2a0e7f661fb0505ee382f27aec2805a3e2117:c7d23a58e2fb2a8d4b8ed1e9eae91e1129c2af8bd05f0bd572abebbe0f30825925f0df71cfb7218c686e5548d9427710a690366ba85541c79101a58a10e8af0a46bb48952ae58f2bf58f5be8df4f316b50f363ec84eed8f82ff4c04b0692d03aef26e8e1e6c9549a2247d540a6e22feb11e57f4b808a2097e8a7b6b3b7af3769e6d81d64886e6962372f4f39e49cd46c1b5f735f380f7c277d099776ed1aeaa57a359c0aa8c72f40eb91a1bf07ea157f5ddb30409d6e3af98990ce7f30affdac5e22010646dca96a540060fc908a3125b000ad1ed3a0f255cd34f15d7dd1fd681c3c35a1cd652056ecc5264d39aaf72a9bb83a551cc934887ae107afdfef063217270d9596891418bd461bba63de65be067b1b7864fe46484c7c9e96349a7c03a80fa055050aa18ace2a44b4a03c947824172b30e21011159443ca3cefaf696a7aa8f98011260c9436bf48991f41d4d507b96ce7323e531adcf66347c55c8855673a9f2ec89b5c8024460617ec7271773b36d64fc14eb5d82652c53a3031457227093d118fd8eb9384e80229041a96a6493450f97e6736263abf1ecd9e9fb9a4f0f6d667fa824151485edc37b34acf3d8c35f9c1be48b5e96a12af8e2d35c23a03580f211da6316b34c56bee872d47641bca77da640fdbbad5a9ad8ab9dc7957913da734ad37492ba4de8cf136cccdeb6ba3f1bd3f003be7263c4f2a40c33f24ca3339596e6c3428338100ebcc0722d4f50d30b33b912d4e7c1a9fe65f6658a6f239140a62c3261e10392ed1930aa917652d3bd2be4e8a08ab97e145b920abb31ee4bcd5a0d71f638180f61c245823a399a734a4dcde0997880245ed71eb9bc65e3c6fc95ab920b8024c17d44ced0037d04a133c2641782f1d622df45269b491d3fa2a1227579eaa386de3e7de7bc455c6a154eee5727fff0437a20076c5c3b0577cac5b4b6934e269380222461a60f954e48979c0671217f16f7027983034121093186c78705fc27dc92e2eda4116a6bf7d23e0548d62b67b25c41ed06192bc26ef1397bf1601f3a6e2a0e7f661fb0505ee382f27aec2805a3e2117: +5907a8c084043875238edbdcb7832fbba4c05ea3c5f88a96f1fbf950401ec164e2f49509d1007f618efe4f1fd67eaa6e2ab18afb2decced5a0b2ba8363789260:e2f49509d1007f618efe4f1fd67eaa6e2ab18afb2decced5a0b2ba8363789260:433b2478e18fad5cb81067061d225528229778307885475460fbe3137a5b44024894ddbe56fa6ed021496f0786e42bc6c2d2797ea0a6bf355e88115faa55cd92ed42133d9dcda6b9ebf63ce4a994d1a82d2a49267558be54182a6f85112bd12b247adacf1405fc7ec7a015d43ab40b82c677f7f85a0e48197c5b96576199f4c3343ff7654d523a30c43a054c3e464451278034b7f196c366768c628af94fc0ccfc9a2955f9d32338b944780f8e327085b103781868e4fb79d56122d7f3f5ab309e5d634add15da382c0d2358e647182be4de6e9a9e43e6a3a3b8215b204d9507610d461621000fb1893707af7d2595bfef8a8c5c5cd08f309a5fb55e45519aea9b84748ca5c672bfecd30d25651234a3cc319b43dfcefc1a07b55b4aca714c2e7ef9638fe7884a77b22253a01a2229500e9ce10fda73a843c19cc09626d2456c22a9c901881d521f4b15d2f613cb469d304d579223bc5ff73804df6371517ebaa5b677ea910ff1a02a26fafe48fef469ed799bed6d56ce961834a2edc2e23c0d9426eccdcc934f4c220e37815f7c334b7383607d430520946a881a08325b4164979d5e82cd8134d78cec4861c019f6de301c1b9aec52bb982033fb79b2e9731bab2968bc3f93fa5604b893c6028c204c36bb8c6b074be28c964d2849b5bb19d7e0ba24e22a204d4fda83b10131d383f10b136bd0dba39ec26af30e3ffb4dbc0c921f0cc9910715d51c81fe4c62950e855549a17cd73a09ac91e06d461518376d0fcfa123df0a837103458d9ce221808d1f9ef2edc5cd2e6823145b524894ea48526d985eefd3f60679399548e1edeadb5395b43d87044b2bfe7c6037029b346a402227eab81f333e10e77f1dbc06a211d43b82558676c2dcff9082b1dd53368df002de1329af3000b171a6914389bb80ec0c9f3e412a441b800afceb0486709adac66cafeef248839331f5d892197e25420f1e37d7c0247f669f5fcbf0:8c4912c0f885d76c914059505373a64bddd67dd468369ab918f23ea28e04c19177a8d461144f0a8b51d215176cb08bd65301c3c46237b61bb1498ca79d4be70e433b2478e18fad5cb81067061d225528229778307885475460fbe3137a5b44024894ddbe56fa6ed021496f0786e42bc6c2d2797ea0a6bf355e88115faa55cd92ed42133d9dcda6b9ebf63ce4a994d1a82d2a49267558be54182a6f85112bd12b247adacf1405fc7ec7a015d43ab40b82c677f7f85a0e48197c5b96576199f4c3343ff7654d523a30c43a054c3e464451278034b7f196c366768c628af94fc0ccfc9a2955f9d32338b944780f8e327085b103781868e4fb79d56122d7f3f5ab309e5d634add15da382c0d2358e647182be4de6e9a9e43e6a3a3b8215b204d9507610d461621000fb1893707af7d2595bfef8a8c5c5cd08f309a5fb55e45519aea9b84748ca5c672bfecd30d25651234a3cc319b43dfcefc1a07b55b4aca714c2e7ef9638fe7884a77b22253a01a2229500e9ce10fda73a843c19cc09626d2456c22a9c901881d521f4b15d2f613cb469d304d579223bc5ff73804df6371517ebaa5b677ea910ff1a02a26fafe48fef469ed799bed6d56ce961834a2edc2e23c0d9426eccdcc934f4c220e37815f7c334b7383607d430520946a881a08325b4164979d5e82cd8134d78cec4861c019f6de301c1b9aec52bb982033fb79b2e9731bab2968bc3f93fa5604b893c6028c204c36bb8c6b074be28c964d2849b5bb19d7e0ba24e22a204d4fda83b10131d383f10b136bd0dba39ec26af30e3ffb4dbc0c921f0cc9910715d51c81fe4c62950e855549a17cd73a09ac91e06d461518376d0fcfa123df0a837103458d9ce221808d1f9ef2edc5cd2e6823145b524894ea48526d985eefd3f60679399548e1edeadb5395b43d87044b2bfe7c6037029b346a402227eab81f333e10e77f1dbc06a211d43b82558676c2dcff9082b1dd53368df002de1329af3000b171a6914389bb80ec0c9f3e412a441b800afceb0486709adac66cafeef248839331f5d892197e25420f1e37d7c0247f669f5fcbf0: +6020ae273e0e0537bac881d7549d923eb1cc200d49ca65d4be635e39173df9dadaaf0e699a12a92c16e0ded3eb3450a36311824577e361f05696603300166297:daaf0e699a12a92c16e0ded3eb3450a36311824577e361f05696603300166297:6a8011de09aac00db16ff7e55c2de67d8c9883fcb2040dedbc1e321caba7bb036971530176d1dbbaa927520bdfccbed8840126043edc44cbb7fa3528680e5f1b5664951dc90109aea4b9c336ca043d8221a4c8d2011656bf944efd36ba0a10a4b389196055750b0e388fb52870bbec8c55198131443945c09f3aace3e6915014374073266f34887442d74f468f8d7078bba0bd814cd6dd423c97b56905587b152d1fcfba0eb9fde2112691dafaf4f921562f241b62841001834f6ce36685f82a8faa3b7afad73a5e59bf5f9e713e59163f31dbe696118af33506d2ffea3d9c1556fb152fd2b321c31757d0c3c0f60ee113edac02d67efbb303dce6fa88f7b9746ca110e6a0cd099c0831f53c55c28b6c82af446456b842b2c950a553ee2c765e9729e6b0c546bfc26bd6d42d06b2ed5d4c8cbbc75f2a3ad8129395793d979c031fce7e20b38bd89c9b624748b2013423cebada02cde2052da5664c6c6426cbfc88f84ff602e2e20df9678fbba577a4c134517ee050681151580f7c5c9787b96e55c4075a26f4f8ccffbbb6ea18de1b2cc8c4496b16042770b7ec6eb5429e7ac1891232aa4e47467f4e9a985d80547ecc4c6fd9f59763ede91671f2aa5736a5d148e3a8ffc88e61253a85b0953654958eb2d69401cbeae775f8cb8c3ca42d21693ebe298838df94c1d77b126a1205cc47d50d5367b6f276ec8db6b95324a31e8fd2ed2e43420c4ad02ea277dd948a55193d0f0b4d1cf28386c725975ce5c12d2a6f35673cc22a0694cca4daf6afbfd326d88c1850f834c42ff0e292ba4f13e5ef0774a596d33904c0262d31df2c584a0a4f453f6ae4a88a275f7de79c13ae1a73115be02f425c6f177a1ec4639c42a792809a2b0919ebd321e316001d5b2f84894fcebd50a1dcf44d702b924532fc0e4d3f9ff8486c0ed180eecc3e09e2272a94dc7d24a4e87a931fe2495cbf992c0aae9201e0796298f9363dbac475e8ed:b1ba88fed7e5f4b757f3fa4d1ed9b19e498e5d2f5e6cd46e426fe8f039882f1be77ac9e5a9265cbf7e3cd2a9e9926c18199143798da5be47a4086440496ba00f6a8011de09aac00db16ff7e55c2de67d8c9883fcb2040dedbc1e321caba7bb036971530176d1dbbaa927520bdfccbed8840126043edc44cbb7fa3528680e5f1b5664951dc90109aea4b9c336ca043d8221a4c8d2011656bf944efd36ba0a10a4b389196055750b0e388fb52870bbec8c55198131443945c09f3aace3e6915014374073266f34887442d74f468f8d7078bba0bd814cd6dd423c97b56905587b152d1fcfba0eb9fde2112691dafaf4f921562f241b62841001834f6ce36685f82a8faa3b7afad73a5e59bf5f9e713e59163f31dbe696118af33506d2ffea3d9c1556fb152fd2b321c31757d0c3c0f60ee113edac02d67efbb303dce6fa88f7b9746ca110e6a0cd099c0831f53c55c28b6c82af446456b842b2c950a553ee2c765e9729e6b0c546bfc26bd6d42d06b2ed5d4c8cbbc75f2a3ad8129395793d979c031fce7e20b38bd89c9b624748b2013423cebada02cde2052da5664c6c6426cbfc88f84ff602e2e20df9678fbba577a4c134517ee050681151580f7c5c9787b96e55c4075a26f4f8ccffbbb6ea18de1b2cc8c4496b16042770b7ec6eb5429e7ac1891232aa4e47467f4e9a985d80547ecc4c6fd9f59763ede91671f2aa5736a5d148e3a8ffc88e61253a85b0953654958eb2d69401cbeae775f8cb8c3ca42d21693ebe298838df94c1d77b126a1205cc47d50d5367b6f276ec8db6b95324a31e8fd2ed2e43420c4ad02ea277dd948a55193d0f0b4d1cf28386c725975ce5c12d2a6f35673cc22a0694cca4daf6afbfd326d88c1850f834c42ff0e292ba4f13e5ef0774a596d33904c0262d31df2c584a0a4f453f6ae4a88a275f7de79c13ae1a73115be02f425c6f177a1ec4639c42a792809a2b0919ebd321e316001d5b2f84894fcebd50a1dcf44d702b924532fc0e4d3f9ff8486c0ed180eecc3e09e2272a94dc7d24a4e87a931fe2495cbf992c0aae9201e0796298f9363dbac475e8ed: +932a200ecee7223f24146283a4048c67a6a2d2fc4ba0f9248bdffd82c6cce3cbec9bfb7a6d04e726fc1ea0c424610dcb7967bf15d6d6626858d411198d40e239:ec9bfb7a6d04e726fc1ea0c424610dcb7967bf15d6d6626858d411198d40e239:df953207048213afb8e2af452c889a21ca136a68c929bdc824f9a89ac596dcb90019a46fb682bcfd962fccb27d00baf8eccaf9d9a7d8183cabd7dfa506f7bafb4935ab045931ff8faeb71631f9ed6bb8f8473ad6290d7cf519db310a4442c461118f67d1a6d103bae6f2697c94b7426d9e02e3cb9522fd0b44aef600c962feff5873d98c2790887b8e88d160824f1bba22017639f8dce68f743480deea1f92aa1fd4135dd06457a60f36b7d7f517d40c94c0dddc2e465847d909b9f68245ff2b421d5919001aae5aef24e02c002da907e8605f160ea6096b580b75cea022d402f7f5fdc464f87f78c7906a01e8e48fb5b35174612b48ac8bc750e0f3aeb0a12f7dfc09b0842c1780a5fd9c54afb9399b9408baaccda20afbe3d682248d7bf1efdef4905a319b0ffb108b753b71cc97e9e21ec9b3dd28cee039d9418a1135f0add092aa66312ea2913300d1cc8916524302bd3d1b09e6b29c6857cbdc56ef4b3f35d8ee677208effa846fdb066b05eb717b4d45120cab72a7db7a7ca846e87b16b69047eb76d8f18da8e1399ec0a8c9c328cbe60e0bf42044d2ebf2818b3c047588452fcd2b3efc1e1009ae07688727db8fb6df2a2fe75d1cf22f32bac09c82a6a3d7eed7d00508cbe5b72460ecfcdd3ee911efe5898dbd8e4ce8591326dd1522f9d255da861bf9eb2a1d5725d7d5d427340341945e7bca8cf2ff8a997450953e77d203683e4b0dafc330e05672d2ecd13a3f442df137044e0f556ffbceffea26cbae26cba6f2568cf39f908489e1a92e76afbf297995da4b2cb1abc9ee1fe4dca5aa838b2fbdc109e89bef3ce5a36e5b2f712ac4c889438248fa5a2150cac6c977b5e0543f4010b7314732fd18e7fd5982e83276519e78725e5a5eeb86f4892084ae52da3849c228c809edbf69a2cc47c478d18719f111d737887c7a2eb3250898db34e5e5076fab9f4a9e6e1929a3480836dea07ba4d63fcefce5543430a8:cd1e4bdf4a3e4a31d65254333c8cc4087e4cc40b02e2a347d09a3dde698490c087d7109ad0209c53e987589cbf3ce26412a2b02cb8a3bc93fec75ab5d2c38703df953207048213afb8e2af452c889a21ca136a68c929bdc824f9a89ac596dcb90019a46fb682bcfd962fccb27d00baf8eccaf9d9a7d8183cabd7dfa506f7bafb4935ab045931ff8faeb71631f9ed6bb8f8473ad6290d7cf519db310a4442c461118f67d1a6d103bae6f2697c94b7426d9e02e3cb9522fd0b44aef600c962feff5873d98c2790887b8e88d160824f1bba22017639f8dce68f743480deea1f92aa1fd4135dd06457a60f36b7d7f517d40c94c0dddc2e465847d909b9f68245ff2b421d5919001aae5aef24e02c002da907e8605f160ea6096b580b75cea022d402f7f5fdc464f87f78c7906a01e8e48fb5b35174612b48ac8bc750e0f3aeb0a12f7dfc09b0842c1780a5fd9c54afb9399b9408baaccda20afbe3d682248d7bf1efdef4905a319b0ffb108b753b71cc97e9e21ec9b3dd28cee039d9418a1135f0add092aa66312ea2913300d1cc8916524302bd3d1b09e6b29c6857cbdc56ef4b3f35d8ee677208effa846fdb066b05eb717b4d45120cab72a7db7a7ca846e87b16b69047eb76d8f18da8e1399ec0a8c9c328cbe60e0bf42044d2ebf2818b3c047588452fcd2b3efc1e1009ae07688727db8fb6df2a2fe75d1cf22f32bac09c82a6a3d7eed7d00508cbe5b72460ecfcdd3ee911efe5898dbd8e4ce8591326dd1522f9d255da861bf9eb2a1d5725d7d5d427340341945e7bca8cf2ff8a997450953e77d203683e4b0dafc330e05672d2ecd13a3f442df137044e0f556ffbceffea26cbae26cba6f2568cf39f908489e1a92e76afbf297995da4b2cb1abc9ee1fe4dca5aa838b2fbdc109e89bef3ce5a36e5b2f712ac4c889438248fa5a2150cac6c977b5e0543f4010b7314732fd18e7fd5982e83276519e78725e5a5eeb86f4892084ae52da3849c228c809edbf69a2cc47c478d18719f111d737887c7a2eb3250898db34e5e5076fab9f4a9e6e1929a3480836dea07ba4d63fcefce5543430a8: +5c483e837eb01ed5a4ad5db3792699824df13e576be967d12115c85e0286e628fe1aa8b069da56e676ef3a57d9bba88305ea032808ee635273b37c5c635def4e:fe1aa8b069da56e676ef3a57d9bba88305ea032808ee635273b37c5c635def4e:58d5e2cd899ba985378b3ec33e9a869822b23d5d896a28f424fcd6e4cc28b80d4aaf2de804367efdf5e423b1234d821d63ac05eaed12c73e8e3608af0ddccc8386b7d842b12e60d30cede32553945e7829e9b23f5ccc2e7103a08f2cdd9e75a7b36f5e63720ef0d49b2592bef3740268c89c86a6cbdfe201de0db9985ceb19399c9a1d5bb0586af3c8cdf2713299eb0443a541a47384607243c54a05915058367d3f2db380ed317a8c12c7a63e809c2e84d4acb9d9eef54c6f5af7ab59cb9168b1068f9d2ccd978fe721bad68a669ffedea3e92c76b32e3166658ee3bd0deb1b084194ce35d9a741c57fc2241e68efaa65320b23a1dd19ea8b7ec81e76f1e9163f9592eeee5af8eced0272f33512d0d4ca067f05551b265396e10014783cacac79437b19842de6ab91b9d923bbeb503325bc54869f663e6ea4ae6897701be7e11d16cdfae0eee861862000e7a4160781547e42526af51ba9698d234aaf510da81a0dbf264366153d7a6d5eb3fb08b9bb5ea065c2f5e5b6bb679d2e210b5b40e2bc82f78dc9ab5824b74aadadd89bf8a8b73a0a2f43ac748378921a73a252704a4adbf740cb99c1e1594c37ac9acc19f52315c6a846a57b36128c64d767af44e9c86305bf18ba7cd52680523a3b102fba6fe55567069d2047cbdd9605ea12c8877d399c1e66e33817731f50b84f817d1f0760a40f97468618934105eb00ec50c76db3c53fcf43fe1702907d9a756bcf439f8831d0bfac92e7058fb157be3e591d37eb34165e3c6fc60e72294c083e477626f9001c1d737c290377dfa58ea4ead3028fc762ce8a3afec2e6e132c662df6034ab554f93efac657ad34f6107d347fc5c5e53f3733e178b76014d2f9bbd06ef2dfe60e2083d8865f7f5b2acc025d912e5cf6cda6e798143e9dbbc70a0211d8e4003d78b383d66a6ad29717ca24eddef7df7cd3a7ef652aba5487afe5d026c9b102807294eb27d9824eeb6b40f083de7:c17c2fbf8c00bcea3035bf0a62d30229db742cab1199677c7eb4eb0ef5c7b51ad487a4971b631e794a58bb0823cc0fe62610fda6a9e03f8c4c3381cb154cef0b58d5e2cd899ba985378b3ec33e9a869822b23d5d896a28f424fcd6e4cc28b80d4aaf2de804367efdf5e423b1234d821d63ac05eaed12c73e8e3608af0ddccc8386b7d842b12e60d30cede32553945e7829e9b23f5ccc2e7103a08f2cdd9e75a7b36f5e63720ef0d49b2592bef3740268c89c86a6cbdfe201de0db9985ceb19399c9a1d5bb0586af3c8cdf2713299eb0443a541a47384607243c54a05915058367d3f2db380ed317a8c12c7a63e809c2e84d4acb9d9eef54c6f5af7ab59cb9168b1068f9d2ccd978fe721bad68a669ffedea3e92c76b32e3166658ee3bd0deb1b084194ce35d9a741c57fc2241e68efaa65320b23a1dd19ea8b7ec81e76f1e9163f9592eeee5af8eced0272f33512d0d4ca067f05551b265396e10014783cacac79437b19842de6ab91b9d923bbeb503325bc54869f663e6ea4ae6897701be7e11d16cdfae0eee861862000e7a4160781547e42526af51ba9698d234aaf510da81a0dbf264366153d7a6d5eb3fb08b9bb5ea065c2f5e5b6bb679d2e210b5b40e2bc82f78dc9ab5824b74aadadd89bf8a8b73a0a2f43ac748378921a73a252704a4adbf740cb99c1e1594c37ac9acc19f52315c6a846a57b36128c64d767af44e9c86305bf18ba7cd52680523a3b102fba6fe55567069d2047cbdd9605ea12c8877d399c1e66e33817731f50b84f817d1f0760a40f97468618934105eb00ec50c76db3c53fcf43fe1702907d9a756bcf439f8831d0bfac92e7058fb157be3e591d37eb34165e3c6fc60e72294c083e477626f9001c1d737c290377dfa58ea4ead3028fc762ce8a3afec2e6e132c662df6034ab554f93efac657ad34f6107d347fc5c5e53f3733e178b76014d2f9bbd06ef2dfe60e2083d8865f7f5b2acc025d912e5cf6cda6e798143e9dbbc70a0211d8e4003d78b383d66a6ad29717ca24eddef7df7cd3a7ef652aba5487afe5d026c9b102807294eb27d9824eeb6b40f083de7: +b0d0abdd8444e10f293754ac9f16e31bdcdd97b7067128aae8e4d7f11289e2cd1c78cc01bea15352b63c5697f1cfe12ffdd16ddc1d59e77951b6e9408ee228ad:1c78cc01bea15352b63c5697f1cfe12ffdd16ddc1d59e77951b6e9408ee228ad:aa276cc543fcc62d70a704608d98ce51b645b5c24a640a5df10a5591417d108926df3f0ce1b921033309eb8d8659f489fd6f79aa1bf4882d72ac69cc58d3bce0fa89b16411e9753eb40c6c4d598dc8f4abb0bc48f1370371326c9a86bbc2ac6214478e78a38408bddafaa9592600c49a129c05392f8a7d642b49137a20f3fe9f11ee17cfa3afd2af71565e9c40080b60cd0dbc378eda062c7cbc7fe972bde4509a1de95f14df482f48aacc463cd594f66d648d3794738ad6ab496e2da50b0db2ba7b659185e4587f182e833de750faacddf21af5e0cf4c9af385b04f7be231498ad0b742d5a87c06115db230973a51427f202fa39afb9828b5f03fa327cbd52dfec66d71ea319865dcf6810f1858472d8bea3e447adfb4b60758e86b48133709732d2bcf51c76caa847b6537fcb05bb8c87dc5e9fb022b3260c1d71b149859c9663dbdae6a7bbfd6deb9d123809c241401af10719cf91a6bed16084c444607359ed8f018db111511892b46bdac6c9c613841ded886b9dec06c01e80487e48fbe778e9e97508ffda0577853aabdcaca8b0bab6ce41557aab9631c96d60977e35718b60595273fdba140f5500a8d3576f5a9fc8f3ca4c02c167af2e03d25750b42adb03b1417f2b6d219be5f8429331a26a449b5d4db2b1a09152eea2b25d2df7ef6fe0a32e25fae79360a9aee1511fda8064550937a7130971930c673bb358e5f55951f50b146d85d383f3e01c151ece6c06d836701253280fdcff4e139d3319ab2e2ca71bcc3fa0faf7c702c9c604e5651de4af5700e9ede7258b9bc148d5595cd34170e3e5cf292828390908fda961f2230ac0b8cac64739732706ce2d5e59abd6d5e207bdafea74d28d7a758f2200e4e00a0bcf0306a3cabda47024fabeae488ab5c323715cf3ca7720af9ebbf8582e1158a099d736b569b9d40295817ea2554068bef32442c111ec814c6ed415919ba73526334df30bac666084e5601c2281c:64408bdd2d0fc892a5b62b5acf8e3b3c73c0b5c4fa2a72e39dd608d4937f9332f73e14d08badc6270114d1f1a556cc6ee8488abb907f79ae175c352e9f11ee05aa276cc543fcc62d70a704608d98ce51b645b5c24a640a5df10a5591417d108926df3f0ce1b921033309eb8d8659f489fd6f79aa1bf4882d72ac69cc58d3bce0fa89b16411e9753eb40c6c4d598dc8f4abb0bc48f1370371326c9a86bbc2ac6214478e78a38408bddafaa9592600c49a129c05392f8a7d642b49137a20f3fe9f11ee17cfa3afd2af71565e9c40080b60cd0dbc378eda062c7cbc7fe972bde4509a1de95f14df482f48aacc463cd594f66d648d3794738ad6ab496e2da50b0db2ba7b659185e4587f182e833de750faacddf21af5e0cf4c9af385b04f7be231498ad0b742d5a87c06115db230973a51427f202fa39afb9828b5f03fa327cbd52dfec66d71ea319865dcf6810f1858472d8bea3e447adfb4b60758e86b48133709732d2bcf51c76caa847b6537fcb05bb8c87dc5e9fb022b3260c1d71b149859c9663dbdae6a7bbfd6deb9d123809c241401af10719cf91a6bed16084c444607359ed8f018db111511892b46bdac6c9c613841ded886b9dec06c01e80487e48fbe778e9e97508ffda0577853aabdcaca8b0bab6ce41557aab9631c96d60977e35718b60595273fdba140f5500a8d3576f5a9fc8f3ca4c02c167af2e03d25750b42adb03b1417f2b6d219be5f8429331a26a449b5d4db2b1a09152eea2b25d2df7ef6fe0a32e25fae79360a9aee1511fda8064550937a7130971930c673bb358e5f55951f50b146d85d383f3e01c151ece6c06d836701253280fdcff4e139d3319ab2e2ca71bcc3fa0faf7c702c9c604e5651de4af5700e9ede7258b9bc148d5595cd34170e3e5cf292828390908fda961f2230ac0b8cac64739732706ce2d5e59abd6d5e207bdafea74d28d7a758f2200e4e00a0bcf0306a3cabda47024fabeae488ab5c323715cf3ca7720af9ebbf8582e1158a099d736b569b9d40295817ea2554068bef32442c111ec814c6ed415919ba73526334df30bac666084e5601c2281c: +498497fdcc6a105891e023ff32d75f7c3748d8c52d87dd3b2775aefd8160a1432d79ae9cee4ac6275b05749c438ebe552b413d873cc07f14f5fa130177214c54:2d79ae9cee4ac6275b05749c438ebe552b413d873cc07f14f5fa130177214c54:be38bc8cdf46190e304ab53dd29c2bc40954fd4c6d2bb990f93b2b5c691fdf0527c260f5066187f2d0f31f43a08b360ea1ed8200651764b8fa49595a1594109e496759ab6623fa33378d800e6117e079e13fe85c81b63ebe247b3df6c1584bc7cffbdfa45f2a2ce7c237aaafef8cbca70bcabce0b847d551f46a7d15ce2a0d3d545abacc5930010c53648887d476e0d13a34fc1c54df09d106ed758deedc761d557a73b2bcdddefba4ed005997b19279b9d2de37d041fe013eef05a2e11c9a234e87cc0e16c0c6da42aaa5bf996417bf64e5b785d67dc32547c1f052178d694cf20f1698589e7ed49be29dd59fd5c01ba1d9f5fb06a75895b7b1e15895097ebde84cad6303aa0a86dbc324747d97245d70c5203be01b06cbde06ae037204d23730cd696189f7ac267cf202179929ce5410e0e3ade513d2201bfd20fefa40b4476f27bf907c762eb7262a5be13cfc047a846d20a9f2311b6469b06ab545f0ec9fc446ea250cd3b73a7b6b960c10ca4c2d6c64a156a18c9fb810e49afd0c36daab8b8b856643a4ccafa9ad886e91e544535b8edda27c90c06ab6bcc53628be18d7d6369ca1801f91c2e0b95f36d702f77234b4100719c059951e45b1f916983934e32b4d4d8f29c0a373f8d8f0918b967865cd0e4beca01327c99d5fded4c1a69ac2d4d9b78ffb8305670021040250cc27737e75df75760fec8b8d30b245654f3c12f1f7cea0bce78ab3693578af3ea61ffccdf9baf7c3ea65b88fc854128126476796892c663bd14518c9918629a1095f614e0492446c3d84b16ec94f7ecadaeb6b659bbb4867b579061714fd5bb0faa4ad6be0ffb3888bea447e4e3438c8f0eae644fbd45a3802dc40ec451b212bd592dacd4da96686dc8b2024257f25e9c830bff795eee85d87a090c1a42321e710555764ed8257c9415c7f224b537558cefdc615129f28350267c01ba0403e07f5c6067f91c85a2c50c866dc4388af38d2160203:b0a36a2c934756348eb47c25a32c3f2a5ddbd58fcc72a08c3cead1a2d900335c3001e35bfe1f3fb5a555009ba8e96874494b97e8b09700edcb1f2584b9d0fe03be38bc8cdf46190e304ab53dd29c2bc40954fd4c6d2bb990f93b2b5c691fdf0527c260f5066187f2d0f31f43a08b360ea1ed8200651764b8fa49595a1594109e496759ab6623fa33378d800e6117e079e13fe85c81b63ebe247b3df6c1584bc7cffbdfa45f2a2ce7c237aaafef8cbca70bcabce0b847d551f46a7d15ce2a0d3d545abacc5930010c53648887d476e0d13a34fc1c54df09d106ed758deedc761d557a73b2bcdddefba4ed005997b19279b9d2de37d041fe013eef05a2e11c9a234e87cc0e16c0c6da42aaa5bf996417bf64e5b785d67dc32547c1f052178d694cf20f1698589e7ed49be29dd59fd5c01ba1d9f5fb06a75895b7b1e15895097ebde84cad6303aa0a86dbc324747d97245d70c5203be01b06cbde06ae037204d23730cd696189f7ac267cf202179929ce5410e0e3ade513d2201bfd20fefa40b4476f27bf907c762eb7262a5be13cfc047a846d20a9f2311b6469b06ab545f0ec9fc446ea250cd3b73a7b6b960c10ca4c2d6c64a156a18c9fb810e49afd0c36daab8b8b856643a4ccafa9ad886e91e544535b8edda27c90c06ab6bcc53628be18d7d6369ca1801f91c2e0b95f36d702f77234b4100719c059951e45b1f916983934e32b4d4d8f29c0a373f8d8f0918b967865cd0e4beca01327c99d5fded4c1a69ac2d4d9b78ffb8305670021040250cc27737e75df75760fec8b8d30b245654f3c12f1f7cea0bce78ab3693578af3ea61ffccdf9baf7c3ea65b88fc854128126476796892c663bd14518c9918629a1095f614e0492446c3d84b16ec94f7ecadaeb6b659bbb4867b579061714fd5bb0faa4ad6be0ffb3888bea447e4e3438c8f0eae644fbd45a3802dc40ec451b212bd592dacd4da96686dc8b2024257f25e9c830bff795eee85d87a090c1a42321e710555764ed8257c9415c7f224b537558cefdc615129f28350267c01ba0403e07f5c6067f91c85a2c50c866dc4388af38d2160203: +d962a6719e5cc7724ca4a1d559536812b4e22aa7bcb13e4fb1722d28e045217ca944592dbc7d77039d720256c3fd340d34db892ab13e4812d662e2840c28b6d0:a944592dbc7d77039d720256c3fd340d34db892ab13e4812d662e2840c28b6d0:a6aa7a190d003ab175332b8f58e7caeb690854d9db56dbb6957b3fb654e2e0da991f3154214204135df1e1104317c9e3c58eedff1fc61aba57744c0c7ef486000a70b2c142ebaddc07ab065e2a855daf198a6803ac24ef3724487c1351ddeda0513913457d76860d78a9b6bc3dba66c40e5fc349a873ad6065ce7d7fdc2cc483b3aefbf2f03dd669bd9cb8f63cee47785cacb09d872c9aeb83e9868405254324037982e08613455d9521d88ea2fda020be730cfc8c07cb0b37614ccba2fa3ec498b815bb5adb996e848b38c015a6a5c752ebdac7b9eed8b69619d8c846b66f7816d1df1ebc21071cef0b251e2eab59827f6d6055084370fd27c203e86a189f1ee11e8403abdcbd1f45341a820525d8637dc484a5185d6551cb882a96b9981a5f1a821f27b656fff90e7f69bf286f752f970ffca5c53e0850b20b94f9431627094acea912a880b749a6f80bb206ccaa746fa70c833c9f323089ce0558c9dc200d5739d1e499634f2c16e54b7f6d7819c47071b60bd54dd0f273a319750fd3c510a49ab56f630c7ce6d8023d97862346859bc0b4d605224969708903760301409c60ab25175611f0be98b23a8cd8ac535e3513bc77e1452193dadf4435e63c3629b666a5ea4c4bad36eacad2601404eabd8d9a07956ec2b4b7bb6336ed75b8df8f16de42c0fcae93652e3c407cbd45e8d413ef51e8542df62512ee793e41358a1de19246c6586b3c1407410421f6e865c75a9f4a6a4788f84a9c781d8f8024bfdbe25bdc7d4b69cbaa7719628c0b07ec2c4a234fff4ac3d4935b9ce4c8a16947abe7951ff8d9ac9215e338fa0fe9124176d17bac1e05592c439868ae5a4f75fd1ea82aa454c20a939deda729a0e19646cebd822049c825c7e31c6efad45e306f2d9f0569e0717331f48004c26ebfe68f3843e90f8067032d21e786c8539e01be3ceac5954a0546c84b734d999456a7c45f8cebaa478e548007f9d3af836f754de4123f2f:dfb9b635ac0edf83b7b59d0b8409af475f66fc9946af0b7c63ab8cf5929d4701a1bf66959cde62fbcf59a48ab3bbaf0b9a61b6e00b2181eb934282070a5d5300a6aa7a190d003ab175332b8f58e7caeb690854d9db56dbb6957b3fb654e2e0da991f3154214204135df1e1104317c9e3c58eedff1fc61aba57744c0c7ef486000a70b2c142ebaddc07ab065e2a855daf198a6803ac24ef3724487c1351ddeda0513913457d76860d78a9b6bc3dba66c40e5fc349a873ad6065ce7d7fdc2cc483b3aefbf2f03dd669bd9cb8f63cee47785cacb09d872c9aeb83e9868405254324037982e08613455d9521d88ea2fda020be730cfc8c07cb0b37614ccba2fa3ec498b815bb5adb996e848b38c015a6a5c752ebdac7b9eed8b69619d8c846b66f7816d1df1ebc21071cef0b251e2eab59827f6d6055084370fd27c203e86a189f1ee11e8403abdcbd1f45341a820525d8637dc484a5185d6551cb882a96b9981a5f1a821f27b656fff90e7f69bf286f752f970ffca5c53e0850b20b94f9431627094acea912a880b749a6f80bb206ccaa746fa70c833c9f323089ce0558c9dc200d5739d1e499634f2c16e54b7f6d7819c47071b60bd54dd0f273a319750fd3c510a49ab56f630c7ce6d8023d97862346859bc0b4d605224969708903760301409c60ab25175611f0be98b23a8cd8ac535e3513bc77e1452193dadf4435e63c3629b666a5ea4c4bad36eacad2601404eabd8d9a07956ec2b4b7bb6336ed75b8df8f16de42c0fcae93652e3c407cbd45e8d413ef51e8542df62512ee793e41358a1de19246c6586b3c1407410421f6e865c75a9f4a6a4788f84a9c781d8f8024bfdbe25bdc7d4b69cbaa7719628c0b07ec2c4a234fff4ac3d4935b9ce4c8a16947abe7951ff8d9ac9215e338fa0fe9124176d17bac1e05592c439868ae5a4f75fd1ea82aa454c20a939deda729a0e19646cebd822049c825c7e31c6efad45e306f2d9f0569e0717331f48004c26ebfe68f3843e90f8067032d21e786c8539e01be3ceac5954a0546c84b734d999456a7c45f8cebaa478e548007f9d3af836f754de4123f2f: +e1d1416518921d07c8c39e2973d8ea1249caa8bf659cc36c7937f84ece7ad4fc48bdcc3f1a5b8058ed9a32ef1cc48cf7a8ab76a6e4519e5a82855241ad6fff8a:48bdcc3f1a5b8058ed9a32ef1cc48cf7a8ab76a6e4519e5a82855241ad6fff8a:3d263de1ab91e8dd7b317f7a27fb60a6e1838c0c793b03abbe7082b6bda0c7c46062262192c88b65c026c174584d29649710429ae44a46140b4c82c8a0b74d56a004f8e2f5c18f84f0464153772f8312633fc6ad28a7d9fb55f7d78cd6488ca58117eaf923fa28875e2b3189893185aa3ccd044d3f110e2e7cabdf6f814b9fdd6733bd5f307a87bc73b6250d5883936deb1db0e0af1be7ab329b5c6bd935bd8f8dc888f0d1c464edbc023cbc080753ee8f799f1072bad1144dfaa615a59e2aedc662e83cb1f8e52096a7ee483bf873b25a0c04c1851a0e87375063aa1a94fa835c052640366b79f735d3286197ab32ebdb5123f6b47ad3f442c44c530a68f8512759e9cf386fba07b8064bc8fe83e245495ec45f8938f8259dc8016205f78d3954442ec1b445d83d95ad1805a5e0e8b3d56b870a20da18d74f26f550a9c7534a4144dcbc1c3cdbbe470cc153905043088facf1d303559de41e96c0ab409bb36dcf38cc9038a6a4908dea82a653195c16f290a7c3ac487636cc5bcb18d15a14ac624c70b6f6462bf249e000cee924018bdf7dde39114cb4f652e122e8744da28b0589e1284d70d9f106de16d073648080e6437ff384e68177d5cb718e2ce3f17ba1e990ae3ce940660130e93750b82e2fb41aa369774568d7cf286725e3c58f63e73f8697aeecc717c5cf1af7ad74f446292c905d84e22b23d4e0d2604bff48fefc40c6204b5e34c042292e53bec9360159a5cd97b2df5786b8f5a292c0b39d14a870a4588e67bd12b2c2f7a4408462851d2aa787971d9315190f42cc588af0d2dcd91f31bb715e9250f1192814f7b8a21fef4517b0cf8bb8a1a1a5f500ee219dfb46132efe8e90bc49093a5559f9681b4fb59e5ba9ef3f05d34eed034c14d77ee95ebd76ffa5af0befcba18fdf932af4854510b75db00a7257b234887d49607dfd16180db516c7a20ccfcaeda6aedfb6a2377fbf31e67b517655db73ca29e118624d6080:4232d2a481084d1196db62f22dc74cf2eaf2db0df05ad7cdde67bfc29bff56cde019ac9f03d81f1827eb1e3b0abe0204ca7f77fa874ab5268354ff08bb7f48003d263de1ab91e8dd7b317f7a27fb60a6e1838c0c793b03abbe7082b6bda0c7c46062262192c88b65c026c174584d29649710429ae44a46140b4c82c8a0b74d56a004f8e2f5c18f84f0464153772f8312633fc6ad28a7d9fb55f7d78cd6488ca58117eaf923fa28875e2b3189893185aa3ccd044d3f110e2e7cabdf6f814b9fdd6733bd5f307a87bc73b6250d5883936deb1db0e0af1be7ab329b5c6bd935bd8f8dc888f0d1c464edbc023cbc080753ee8f799f1072bad1144dfaa615a59e2aedc662e83cb1f8e52096a7ee483bf873b25a0c04c1851a0e87375063aa1a94fa835c052640366b79f735d3286197ab32ebdb5123f6b47ad3f442c44c530a68f8512759e9cf386fba07b8064bc8fe83e245495ec45f8938f8259dc8016205f78d3954442ec1b445d83d95ad1805a5e0e8b3d56b870a20da18d74f26f550a9c7534a4144dcbc1c3cdbbe470cc153905043088facf1d303559de41e96c0ab409bb36dcf38cc9038a6a4908dea82a653195c16f290a7c3ac487636cc5bcb18d15a14ac624c70b6f6462bf249e000cee924018bdf7dde39114cb4f652e122e8744da28b0589e1284d70d9f106de16d073648080e6437ff384e68177d5cb718e2ce3f17ba1e990ae3ce940660130e93750b82e2fb41aa369774568d7cf286725e3c58f63e73f8697aeecc717c5cf1af7ad74f446292c905d84e22b23d4e0d2604bff48fefc40c6204b5e34c042292e53bec9360159a5cd97b2df5786b8f5a292c0b39d14a870a4588e67bd12b2c2f7a4408462851d2aa787971d9315190f42cc588af0d2dcd91f31bb715e9250f1192814f7b8a21fef4517b0cf8bb8a1a1a5f500ee219dfb46132efe8e90bc49093a5559f9681b4fb59e5ba9ef3f05d34eed034c14d77ee95ebd76ffa5af0befcba18fdf932af4854510b75db00a7257b234887d49607dfd16180db516c7a20ccfcaeda6aedfb6a2377fbf31e67b517655db73ca29e118624d6080: +2bf74f004d7d0af73a83ea208cc206723d188f4cf607bcad4b6980268ff21fa78fdcd99352438beb52f0d1742bae71844512dd0685aaf1c909e38fc4b5aab6cc:8fdcd99352438beb52f0d1742bae71844512dd0685aaf1c909e38fc4b5aab6cc:898e4303ea5bebd200a5f7562be5f5032640a3f5ccfa764292045a1a368d02aa591077d8f304f74dbdfc280734454ed8c2727aff392c108c526e527e672c5397b2d77c01f7741ef8dcc2510ee841b59dd10f4e1d3ac501af7cbdb85ba31129c262fde1a0c8bc83d6ff944b6bae3fa7fb62587c681d8e342965c5705fd1a6ab39e5a0770ee7798d9fb6c0018a514d53af848db6047cd02db352d5563b53662373b971935a1ac2b7b6361dac6748771813f7749316694961b940ff3805811a49fa27a9ba457ad28848c697050e0188d0773e17fb52194e190a7872a398f31c0f0ae06537a273ffb50c2c816445ab882811922c0621556c46a3a0ec40bfedb411e90b6db1ddd4bbebb57d10df566a63d726a33308514ce3b499d5e526c22b956d8b99913dcb13e437e947b666c41c54d8b3ae2356647e8017ab678386c927219ae7bddc0d821265f9dc4ff3f8ce5be60f8e9defc5ca335068ee29fe8304917b788784a2388a320192f9325d0e6cfffea21e6eaa29e7707f63a9ea4fbb2558e3d0835bab1f52361037ae59e503ee96b9d708a47a3ae4bad113e2a460a269ccf25a0003cb3e68a551864e59840914791126f954788b25b5af5aaf586ebb87fa5f377b4d7d7f84c000dd2cb440e214d38d5ecf70f20e9881828edaa1dbec37093db960686ca123f1ecba6336b37f46cf765be2814b9e6705bc9d6a49318118c7529b37c84ec88d58a8453dcb692c9a36016b948ebe6fb2c1d0adf5f198ee3097a6ff0b8eebbad8b0769330b18689516bc0fe668b0d05e3a584fcf89c49db501d61c2def7ed3722070193a5b683c5087ef274ce6a193dd4a303536c67934b4660a841ee1b446a6892b14d0b0aa3e98fdffd43c797add36583f74c94d0e2d68e2de818d9af200598f0b2beae169c8dfbc4d397e6d1ceb6daa6c9f6bbf4f8311ba26ffb194d44216c51305267074e856a1d6e922780f4798e2f220223fff1dc370c8e34514aba42df51:3eb5b339e191a3b6168545da5fb0ca9be209043919b9c70a07b4a7a3bf64b102f6ffd6d2b02559dc681ed3b9c82297b201dc25c4973880e155e13a29426eb40d898e4303ea5bebd200a5f7562be5f5032640a3f5ccfa764292045a1a368d02aa591077d8f304f74dbdfc280734454ed8c2727aff392c108c526e527e672c5397b2d77c01f7741ef8dcc2510ee841b59dd10f4e1d3ac501af7cbdb85ba31129c262fde1a0c8bc83d6ff944b6bae3fa7fb62587c681d8e342965c5705fd1a6ab39e5a0770ee7798d9fb6c0018a514d53af848db6047cd02db352d5563b53662373b971935a1ac2b7b6361dac6748771813f7749316694961b940ff3805811a49fa27a9ba457ad28848c697050e0188d0773e17fb52194e190a7872a398f31c0f0ae06537a273ffb50c2c816445ab882811922c0621556c46a3a0ec40bfedb411e90b6db1ddd4bbebb57d10df566a63d726a33308514ce3b499d5e526c22b956d8b99913dcb13e437e947b666c41c54d8b3ae2356647e8017ab678386c927219ae7bddc0d821265f9dc4ff3f8ce5be60f8e9defc5ca335068ee29fe8304917b788784a2388a320192f9325d0e6cfffea21e6eaa29e7707f63a9ea4fbb2558e3d0835bab1f52361037ae59e503ee96b9d708a47a3ae4bad113e2a460a269ccf25a0003cb3e68a551864e59840914791126f954788b25b5af5aaf586ebb87fa5f377b4d7d7f84c000dd2cb440e214d38d5ecf70f20e9881828edaa1dbec37093db960686ca123f1ecba6336b37f46cf765be2814b9e6705bc9d6a49318118c7529b37c84ec88d58a8453dcb692c9a36016b948ebe6fb2c1d0adf5f198ee3097a6ff0b8eebbad8b0769330b18689516bc0fe668b0d05e3a584fcf89c49db501d61c2def7ed3722070193a5b683c5087ef274ce6a193dd4a303536c67934b4660a841ee1b446a6892b14d0b0aa3e98fdffd43c797add36583f74c94d0e2d68e2de818d9af200598f0b2beae169c8dfbc4d397e6d1ceb6daa6c9f6bbf4f8311ba26ffb194d44216c51305267074e856a1d6e922780f4798e2f220223fff1dc370c8e34514aba42df51: +f5f7d5b73c5a65301b5b4c6710ed12c16e7903177db792ca715e23389d05d83e7c4762e979f0c7e207be1843e2666aca27ea89bff5b61d573c985fc7025e1e28:7c4762e979f0c7e207be1843e2666aca27ea89bff5b61d573c985fc7025e1e28:7c9318d56e63f16535436fa45afe278e74e61881bb468997d0418bc720b630dadb8128b4b65ca6e921e501813df9fe03b4ef0aae8035dd08c5f820ce5df12ee118d9c36d3b151a52c3f96ae1ca4c82fd19da669ddba94febf8eac8c42b447babc8a60b36e803624f7d2047bd8d8a153687f10dc1ca82100b7c87d32370ec8f2671ed7d067cc80587cab8db3a71ce5e406327f763ec1b3c166770a75536630c815fd8267582d1b5051f0f821c02150b2eef349b50590314aa2570793fa64a76ed2ed83d2ba1f9b9f1163154612b49a64ad8d5573c25b1cd37c41a44e3df78f1053d90b068f0d37ae00c4a32b1a3ff874c41da4a7043392f18efe5518d76e88b41ced69e6f4c014f06ebc5146e61e82fae1c49c37c394fea34199ab86c11a4467a374e40255a05d426971430d56cdba25a21ad779cc7f62d22cd87b60f0891bd856a517e14b72a9ac7672e4e8fb374a9758ab0c4e5964aae03228973f173a5d42aef9db33736c3e18d8eec204a1a17b9d04593dea4d804cbc81b9ac5458050495539999a9985487e7ca11c37582ef85c841e8f065ea98fdd6b1c60dea1ec2883521568856a6ebb2749f2072eb43448be0705ed477cf4b2004865217de5fadbe2a0f9d6b84b3fe7f7bf6c77537496246ec796b8ef2c04f68ab5b14fce0c6d287b836227d9f08fa0ee19722f6798a5d8280d107cfc1bd592d9ddc724ea86fc39dc94a394019e3a3de9e0d1c735e862de2bb9525b5fb4bd121212bfaff9ff586ac3c75c5ace746d9ca307f795ff2697f2b41a6346ed23397eb38898691e6f66841637d0ab0d968309e0194002309015416e74472fe32425d45f07c7711918b1e5790f572ce4441042d426033792297b5f81e0809bd9691f0a505e3259fc03c9ff107eb9b48795f49fb09c1bab5659d39ffecbdcc403e3803dc012438c2fb36f683015c5df0482cb7d7fc5757364a0a3c10d0e1259c01fcc4dd5494b5290a694aea3f6fae547ac576f:58fb392f82d5e52ff072cc77efe048f2235250c71125ee821c5f3b393bcf2fa46be4c5d8caf13cb519efe0c2fad9ee231ae9b6fd1fd509c98c69c2d36c753e0e7c9318d56e63f16535436fa45afe278e74e61881bb468997d0418bc720b630dadb8128b4b65ca6e921e501813df9fe03b4ef0aae8035dd08c5f820ce5df12ee118d9c36d3b151a52c3f96ae1ca4c82fd19da669ddba94febf8eac8c42b447babc8a60b36e803624f7d2047bd8d8a153687f10dc1ca82100b7c87d32370ec8f2671ed7d067cc80587cab8db3a71ce5e406327f763ec1b3c166770a75536630c815fd8267582d1b5051f0f821c02150b2eef349b50590314aa2570793fa64a76ed2ed83d2ba1f9b9f1163154612b49a64ad8d5573c25b1cd37c41a44e3df78f1053d90b068f0d37ae00c4a32b1a3ff874c41da4a7043392f18efe5518d76e88b41ced69e6f4c014f06ebc5146e61e82fae1c49c37c394fea34199ab86c11a4467a374e40255a05d426971430d56cdba25a21ad779cc7f62d22cd87b60f0891bd856a517e14b72a9ac7672e4e8fb374a9758ab0c4e5964aae03228973f173a5d42aef9db33736c3e18d8eec204a1a17b9d04593dea4d804cbc81b9ac5458050495539999a9985487e7ca11c37582ef85c841e8f065ea98fdd6b1c60dea1ec2883521568856a6ebb2749f2072eb43448be0705ed477cf4b2004865217de5fadbe2a0f9d6b84b3fe7f7bf6c77537496246ec796b8ef2c04f68ab5b14fce0c6d287b836227d9f08fa0ee19722f6798a5d8280d107cfc1bd592d9ddc724ea86fc39dc94a394019e3a3de9e0d1c735e862de2bb9525b5fb4bd121212bfaff9ff586ac3c75c5ace746d9ca307f795ff2697f2b41a6346ed23397eb38898691e6f66841637d0ab0d968309e0194002309015416e74472fe32425d45f07c7711918b1e5790f572ce4441042d426033792297b5f81e0809bd9691f0a505e3259fc03c9ff107eb9b48795f49fb09c1bab5659d39ffecbdcc403e3803dc012438c2fb36f683015c5df0482cb7d7fc5757364a0a3c10d0e1259c01fcc4dd5494b5290a694aea3f6fae547ac576f: +43d4be6de9cb00898e99ddcc2e1530110fa2cbc4376c485e9ca57fd65586d8a33632ad389be2fab3fba0d804bf6345cd322eddd6a75d8c37fd4b5ba1c9c25e8f:3632ad389be2fab3fba0d804bf6345cd322eddd6a75d8c37fd4b5ba1c9c25e8f:d9d55dab0fa6da76b68e841c24d971bac1f79af513d834e426a5d08114ce8b54ce8b7afe016b0fad03ee7450c6c3097173681a4b2eb9f9c179a88e7cc36813f2f5d15f7998afa9fd4e546c73bb42e7f9522be6afabca8c7b64fed0e292e4375f3e1e5fd9fcb539f4e5e543fb6a11a0df321e70084aaabb70a9950ceee3d879c386efca1e59c3cb7c45b560095e7af00ff52f8a1aaa9ccf092f0bb806d97610742ac582a3abbeddf39f49d229d32a1186d021518d74728d13d962635d63baa6743b126bf458fa2ac756fbf88096c8d3340c622390534a743f1864d54deab5e5536372ce5ac93762287414eae158a76bf81df5417cf4c047be3ac1475c517ebd3ac1d1d1bdda11b3f99c18173e030acd51d2b5cf79516509415405077511bdd9cbe17d04f47805e98d0d145e60a5d0e0f453cd9b5c1a24f12b75e8cc34d5e00691ffacbff788fea834d9d779c1e610294dce19170d28160cff909bea5a0aa749401740ea3af51e48b27c2b09f025444276c188c0671a6da94b43d1e525e6a4a8a1a73dfedf12401846ba43068a04092b12912270d2b60df6099779756b8bbb49ece82d55f0f8db1b80fb4b59bba860bd18c75d6c834d69442ae0314cf2399f5392a3c6728c63e5c516c4222aac60f916dd63d1d0517e8eb10bd0e15eb90614deb296403ad15b8c12b9e971ef2f01e59fc35d90c55a8e20e9437dd434b26d5c2c6ec2d53acec17e81e47831dc2de82183d713b59a4d1f46969ddcddaf27f44e5a311aaac39c3d5a97bc90cad712f46f85e6c8fbf5d58d8bc3ec27d310a9eaf2c369cb00649770390a3f988f362efc155f56a146a62650547e9153250701eead1bd01c89462272dfaf0a431af4bd7c3db451ada603233fdad3aa8999aa21e2d3a43b0b56fc6a9124d33598b3737f4e5cb258beda756ad2e17d0691d15d416bb7cb07ec8d8c7af5de80e5b9394e320c4c6e43efaae684ad00f6dd20a8750e959c2f04206fc023aa190c:86ae9325f80b9886c8381f96a18c2120e6db016a0d6ca282ed93ba9b61caec02de88efca8b8e916a4b16a58525a2f68d21e5fbe67db4c4d6209595c4abc32b09d9d55dab0fa6da76b68e841c24d971bac1f79af513d834e426a5d08114ce8b54ce8b7afe016b0fad03ee7450c6c3097173681a4b2eb9f9c179a88e7cc36813f2f5d15f7998afa9fd4e546c73bb42e7f9522be6afabca8c7b64fed0e292e4375f3e1e5fd9fcb539f4e5e543fb6a11a0df321e70084aaabb70a9950ceee3d879c386efca1e59c3cb7c45b560095e7af00ff52f8a1aaa9ccf092f0bb806d97610742ac582a3abbeddf39f49d229d32a1186d021518d74728d13d962635d63baa6743b126bf458fa2ac756fbf88096c8d3340c622390534a743f1864d54deab5e5536372ce5ac93762287414eae158a76bf81df5417cf4c047be3ac1475c517ebd3ac1d1d1bdda11b3f99c18173e030acd51d2b5cf79516509415405077511bdd9cbe17d04f47805e98d0d145e60a5d0e0f453cd9b5c1a24f12b75e8cc34d5e00691ffacbff788fea834d9d779c1e610294dce19170d28160cff909bea5a0aa749401740ea3af51e48b27c2b09f025444276c188c0671a6da94b43d1e525e6a4a8a1a73dfedf12401846ba43068a04092b12912270d2b60df6099779756b8bbb49ece82d55f0f8db1b80fb4b59bba860bd18c75d6c834d69442ae0314cf2399f5392a3c6728c63e5c516c4222aac60f916dd63d1d0517e8eb10bd0e15eb90614deb296403ad15b8c12b9e971ef2f01e59fc35d90c55a8e20e9437dd434b26d5c2c6ec2d53acec17e81e47831dc2de82183d713b59a4d1f46969ddcddaf27f44e5a311aaac39c3d5a97bc90cad712f46f85e6c8fbf5d58d8bc3ec27d310a9eaf2c369cb00649770390a3f988f362efc155f56a146a62650547e9153250701eead1bd01c89462272dfaf0a431af4bd7c3db451ada603233fdad3aa8999aa21e2d3a43b0b56fc6a9124d33598b3737f4e5cb258beda756ad2e17d0691d15d416bb7cb07ec8d8c7af5de80e5b9394e320c4c6e43efaae684ad00f6dd20a8750e959c2f04206fc023aa190c: +7d010d760f24e5a2de34089c9fdb19c33b155b0a37ca455a5e5b1dae7a0731764c877b3c4971fbb551166e214d1c7624c52277903c59a562a80b91a85483fb47:4c877b3c4971fbb551166e214d1c7624c52277903c59a562a80b91a85483fb47:86e2115572bf4c013e6b4b04d0b03e606ee70d929cb8ec36f4e2f355db3b5e1573d658d17bb1a310c16989a16b9558922ee493f359042103c4dc1b40dff7709901fd5830133f42c4651eca008b499ee4f84cd4ec1edaa78256edb62f24021a0076256919e4e2ce0a5a20f921c278cc299159644b5e3a3bbd089dcbbebad3766aea77e9f08ee5f7d4c19d8170bc3de1ba779a769914f965dbde2b61bad214c508186041f76c25be957656f5cfb7334eb838a3cfbc55cfbab67adf1552619941b835cd3e34103b18b49131e82096f05f570b899804bab8b6cbaddbbc02f9f3b559736d99ca7b02d3268fa273996fcf0571977d1cc3008c4ef848970ee350b158c47ec277add4742fa2bcbea9bd5549c7bca038020ece68f188c1ea3a62dd9a073d4c138ca8a9ac0408dcfd46e36bdff73988a58b9617caa08bd41bf3e812e7824f0f7e8146a444f36bf53a1cd892039ccd335f5a2e79745eac96148c2a299947f1b2e328a3789bf13c6d73506f3bdc68ea48abf002270fe4ee9ef9ed6b10c2fbb4ff1275b9d7dd35d8a52e371758574cb466c57b5abc242976befc8d98a0131b9bb846b219e4669186a83c056cd8080661de16b51ce5767b22e9a93242bf8d3205c66a673ce783d1c0d37b6300fbf0d6127940f88f1819c450dcc90543ed794f1fd44e6539febaf19a4cc98870014d7ccad74d1876a123ecd145516c743b4bba62d821ca9a7951e0dfb23f38d9e3a365fd8322f2ee4799e9ff11e1c5c30b55a355c8a5deea81a545e34705ab56d17b1fa06ed76415556702f364808246f863c319f75cdf6bd748438d1a2eaf4206c560bfafc235679ad6049c1a01526fcb9a3ce1b1d39be4df18b15fa0ea55272b17ebdedf6c30498a8a14f2042be1c2cdb09e9ef3846d6659a9f6d673df9afb7eded04b793d9731f0accc41468dc1f3236c99acadee6239c361b8bd7e2d0cfe8bb7c06687e08e76b71ad57a036179f291d096ae2fa0818ef4bf4866:5570613879ae22778bd54f14fb6e8c0256a71f3d79c3e5cd8e41aea8cf773e24d29f1f1b24f8c80d2949e8201465dbde8940b1fab6483b085d418e251014200c86e2115572bf4c013e6b4b04d0b03e606ee70d929cb8ec36f4e2f355db3b5e1573d658d17bb1a310c16989a16b9558922ee493f359042103c4dc1b40dff7709901fd5830133f42c4651eca008b499ee4f84cd4ec1edaa78256edb62f24021a0076256919e4e2ce0a5a20f921c278cc299159644b5e3a3bbd089dcbbebad3766aea77e9f08ee5f7d4c19d8170bc3de1ba779a769914f965dbde2b61bad214c508186041f76c25be957656f5cfb7334eb838a3cfbc55cfbab67adf1552619941b835cd3e34103b18b49131e82096f05f570b899804bab8b6cbaddbbc02f9f3b559736d99ca7b02d3268fa273996fcf0571977d1cc3008c4ef848970ee350b158c47ec277add4742fa2bcbea9bd5549c7bca038020ece68f188c1ea3a62dd9a073d4c138ca8a9ac0408dcfd46e36bdff73988a58b9617caa08bd41bf3e812e7824f0f7e8146a444f36bf53a1cd892039ccd335f5a2e79745eac96148c2a299947f1b2e328a3789bf13c6d73506f3bdc68ea48abf002270fe4ee9ef9ed6b10c2fbb4ff1275b9d7dd35d8a52e371758574cb466c57b5abc242976befc8d98a0131b9bb846b219e4669186a83c056cd8080661de16b51ce5767b22e9a93242bf8d3205c66a673ce783d1c0d37b6300fbf0d6127940f88f1819c450dcc90543ed794f1fd44e6539febaf19a4cc98870014d7ccad74d1876a123ecd145516c743b4bba62d821ca9a7951e0dfb23f38d9e3a365fd8322f2ee4799e9ff11e1c5c30b55a355c8a5deea81a545e34705ab56d17b1fa06ed76415556702f364808246f863c319f75cdf6bd748438d1a2eaf4206c560bfafc235679ad6049c1a01526fcb9a3ce1b1d39be4df18b15fa0ea55272b17ebdedf6c30498a8a14f2042be1c2cdb09e9ef3846d6659a9f6d673df9afb7eded04b793d9731f0accc41468dc1f3236c99acadee6239c361b8bd7e2d0cfe8bb7c06687e08e76b71ad57a036179f291d096ae2fa0818ef4bf4866: +aaaabb7ce4fffe4dc35747baea2bc5f050bef06ee0c1fd632a067fece1ef4fb5820a2442d5f45f3c791478e098fb3b068da52ec4e8dadec85065c35659f437e0:820a2442d5f45f3c791478e098fb3b068da52ec4e8dadec85065c35659f437e0:f9d28597a3e2b64ba327ac5cd29f081e74bf461b2eb2d3cfd9d5e92158d21d1d2a47ab50981cb19fe3f8c6fe488249b1c49fb897a0fe21ab5404414fd914875c220f1cbc12f5c38cfba79f7ac303a5231a372b02fad6c8462f8cc49f0f64965b651dccef0bb9608215090849177be47b2d3072944d36e856da185c7b3a689f7edef988338e0963ed31a6b0a80d5cb0b1cccf6f394837aa6f8b2f3da5efbdf4d360d4bf4dd708ce6445587d942b79761ce951b1bb4d9050703618a6d930a80c69576fc4af306a2a56dbd884a05a1e4e9f3136cd0b55ae474bb5d3d0fbc9b0339cec344fdd085c1928101481c68794f5c890137108cea791d21f81683d3e1a9eec66ace5c014d89e69808e5fa83d3812ee680f5a9971681b8adcd4a16e9a4c165b5ef9932c5ed825237fd5037bcbefe4cb11564fa707c8a93290751414891b1edd3313c65f8b91c2e925a3c12a9d3aa45fd5a667b78393c3e39df88a8f0d1148b5311e3d87c4a92e0a3fb915bc90d5558d05b475a8834778aa943ea39b8eaa95ad1832e5916ea3102d7de0b836cde8f3759dbb3b9d56ea817b3e49c983210277c2c7c5b0db187422532fca98a28b3b659c6b815ac126fadbe2f400c73e9d2dedcbbd2d3a365ffad7e666c896e31e61b384ed3a9fcf1290538df11b9474c6281cc592c71c8808868b4292c17ece6b3edf5e3542a70b911593e93f35ecd9729bd8880a24eaf41fbc6574dfe167ec2d0e7ab3df5ec34b8b55d548ab93738a2eeaf21c884c5c8551db2edf2b049f1a2a84fa72ac8978a4c27809f209c1b2195aff504f699856cc4f22d44ebdd0fe50374468d0b1792e574b5110a1f4cd0e221e824a78ddc4845feb46d66d633d23cd23f4b6fbe4c8ce16cd1af61536da5fa67b10ac7555a68c0e0bdbf2f8d72309d995516b8118bf43835d0a01c08ffeba3ea3ed05cd2d54f0eabcda05d0037d52caed3b19374faf73999094f79055924bea9aec4470135f5e8bf183c9d1c9:050ae8aeceec9627b80137357a22962ac8b45048661708d394d0a51aadc381fe8535023d6e1bda0e72b349b50b26da7c3a3085e81e9dd6cf127868fc5baeab01f9d28597a3e2b64ba327ac5cd29f081e74bf461b2eb2d3cfd9d5e92158d21d1d2a47ab50981cb19fe3f8c6fe488249b1c49fb897a0fe21ab5404414fd914875c220f1cbc12f5c38cfba79f7ac303a5231a372b02fad6c8462f8cc49f0f64965b651dccef0bb9608215090849177be47b2d3072944d36e856da185c7b3a689f7edef988338e0963ed31a6b0a80d5cb0b1cccf6f394837aa6f8b2f3da5efbdf4d360d4bf4dd708ce6445587d942b79761ce951b1bb4d9050703618a6d930a80c69576fc4af306a2a56dbd884a05a1e4e9f3136cd0b55ae474bb5d3d0fbc9b0339cec344fdd085c1928101481c68794f5c890137108cea791d21f81683d3e1a9eec66ace5c014d89e69808e5fa83d3812ee680f5a9971681b8adcd4a16e9a4c165b5ef9932c5ed825237fd5037bcbefe4cb11564fa707c8a93290751414891b1edd3313c65f8b91c2e925a3c12a9d3aa45fd5a667b78393c3e39df88a8f0d1148b5311e3d87c4a92e0a3fb915bc90d5558d05b475a8834778aa943ea39b8eaa95ad1832e5916ea3102d7de0b836cde8f3759dbb3b9d56ea817b3e49c983210277c2c7c5b0db187422532fca98a28b3b659c6b815ac126fadbe2f400c73e9d2dedcbbd2d3a365ffad7e666c896e31e61b384ed3a9fcf1290538df11b9474c6281cc592c71c8808868b4292c17ece6b3edf5e3542a70b911593e93f35ecd9729bd8880a24eaf41fbc6574dfe167ec2d0e7ab3df5ec34b8b55d548ab93738a2eeaf21c884c5c8551db2edf2b049f1a2a84fa72ac8978a4c27809f209c1b2195aff504f699856cc4f22d44ebdd0fe50374468d0b1792e574b5110a1f4cd0e221e824a78ddc4845feb46d66d633d23cd23f4b6fbe4c8ce16cd1af61536da5fa67b10ac7555a68c0e0bdbf2f8d72309d995516b8118bf43835d0a01c08ffeba3ea3ed05cd2d54f0eabcda05d0037d52caed3b19374faf73999094f79055924bea9aec4470135f5e8bf183c9d1c9: +e95cc2a4d1193b7539fcbbeaaeed985b6fb902dd0efbd6387457550d0d6a2fea72a1ff1e9bb11c8d88968a7b169637adee438e2263f006dca4fe02fe066cbad3:72a1ff1e9bb11c8d88968a7b169637adee438e2263f006dca4fe02fe066cbad3:84267439201b0591db60c0f17a9c15e45409295652d5f55b87fb351967c846a567f5cebaaed1762bff5485f04853ca9269f464094e512df1f02e13e517b1daa58d34caa2d5ff9f9e79bcafb4ce96e8a089258ad61343b446628ebc4f5b2a84d03b72ef3f738589fa13c42519a828299a3faec035037bc10b44e3bdfed9e0870717cbaf31bef8b22c4ea16e8157fcbc63eefa39ed822efd4215c247dda48786277ec030a86c0ef4851d673cfe752d0677883c2c452038970c09bd481714bc3fbecfa4ff2a3c245695d7ecc2f4dec7f5ede04ff6db43e2bb91c066b649ef73fd3be860cb83fa80b074149f431eebb917ec8478da870c11e317703859f9f2f4008a6c7c754b06e1f7d2479689da84e88922f38274985e11ce13cdbdb0f2ece68fb602ade03dd549a362491f4a203ff80744f663c523a026b431aad45c5829e029ad6256d1276fd7b7a12ddbf1727d9e233fb534457370a426e56fb39cf404a3ecbf0c4b50bb522dce981e0830fd8406e6d9725ceb1ddd3a1947937d90e04d768ae1d126e2aeac21b8c9efc54c40961b7f4e9e88025f7e0b9de901ebf0049e741b797997d8db78e9283bbb5f90f35a2c4dee273142ec258c02ad0ecc61cc5c9f12132db28af41c1fb78e524be5327b5ffc35962779fb11ff0c5d3ee0a31ff47e73b1729dfa46e8986b1b89abc88ad06abd5b6f766d23abf642257894ebdfa79e6309f1272374ee9433677ba13e451baa95330e660c8052ae872e0e32e2b2d1286d01a0ab5810424ed8b9405465bdeba03b698384676fe5ea464a03446c4f7cd7b43312ecf151360464571ad28610581fbadb945a1d68181deb403aa56eba0bb840328eee36103c7de073a6879c941c7554c6f6f2a080809eb0e5bd0e130f29a229e930db01fecac2e036bdf0e001e2a8ea3264f8649d5b60c29103f0b49c24c97facaf7e81069a2b26ab3f933f427d81272c6c8b7cd0dfb7c6bbe9c0eaab32bbda2218b9623a2119aab1f3eb:1b8d7cc2adf36cae1631250c82431bd88437163a6349ad96e7a864447e9fee753ac3655c9835b4d1ecbb306c638ba5402ad02ba6d225d96882889fe8d204a60484267439201b0591db60c0f17a9c15e45409295652d5f55b87fb351967c846a567f5cebaaed1762bff5485f04853ca9269f464094e512df1f02e13e517b1daa58d34caa2d5ff9f9e79bcafb4ce96e8a089258ad61343b446628ebc4f5b2a84d03b72ef3f738589fa13c42519a828299a3faec035037bc10b44e3bdfed9e0870717cbaf31bef8b22c4ea16e8157fcbc63eefa39ed822efd4215c247dda48786277ec030a86c0ef4851d673cfe752d0677883c2c452038970c09bd481714bc3fbecfa4ff2a3c245695d7ecc2f4dec7f5ede04ff6db43e2bb91c066b649ef73fd3be860cb83fa80b074149f431eebb917ec8478da870c11e317703859f9f2f4008a6c7c754b06e1f7d2479689da84e88922f38274985e11ce13cdbdb0f2ece68fb602ade03dd549a362491f4a203ff80744f663c523a026b431aad45c5829e029ad6256d1276fd7b7a12ddbf1727d9e233fb534457370a426e56fb39cf404a3ecbf0c4b50bb522dce981e0830fd8406e6d9725ceb1ddd3a1947937d90e04d768ae1d126e2aeac21b8c9efc54c40961b7f4e9e88025f7e0b9de901ebf0049e741b797997d8db78e9283bbb5f90f35a2c4dee273142ec258c02ad0ecc61cc5c9f12132db28af41c1fb78e524be5327b5ffc35962779fb11ff0c5d3ee0a31ff47e73b1729dfa46e8986b1b89abc88ad06abd5b6f766d23abf642257894ebdfa79e6309f1272374ee9433677ba13e451baa95330e660c8052ae872e0e32e2b2d1286d01a0ab5810424ed8b9405465bdeba03b698384676fe5ea464a03446c4f7cd7b43312ecf151360464571ad28610581fbadb945a1d68181deb403aa56eba0bb840328eee36103c7de073a6879c941c7554c6f6f2a080809eb0e5bd0e130f29a229e930db01fecac2e036bdf0e001e2a8ea3264f8649d5b60c29103f0b49c24c97facaf7e81069a2b26ab3f933f427d81272c6c8b7cd0dfb7c6bbe9c0eaab32bbda2218b9623a2119aab1f3eb: +77ad0f942c37f0313e6b0456dabaec81b2d61f6c118ddb29eaf3ac5bf19504d4692d2da5a95f48611a6da89cfb3b3540f6aa0c850d6d98deea870e397fede328:692d2da5a95f48611a6da89cfb3b3540f6aa0c850d6d98deea870e397fede328:87e6dead2c85549e3d8d2588a0a3360603a624fb65aebbc101bf7f1fec18d0b28fbd5dbaeed38752cdf6355ce8dc84e18ac1a4393d2ab888882c4ff1c9c8137f83bee36336bcbfbb72d5049e0a400874514fdc3633046e89383dded93ca31fde0d898e11e9268d3d5c240666ed5527613da79fb7e49625b44cde78b41c67902eb0216b3a7a3e560e261d71d764aacf15959c17fcd6176fb25e249ee6bb1b3bd7bd90f60b0b0ffa0315a065a24bbae8f255bf298d7e4d44f0b430c415b4fb36cfa6626a83f49a2567f6244f40e923add1d49a72f57b1530f5b379de3a91c2e9a1ac79ab37bc3b9ba73d8828136bcc87d2c01190de5457facd90f369553f7ac521c5672b0867dfa8da3b952ad95b67dab99b4820572f2d4a298e9518637779289c031b793dee859cde7b24add649fff871248a6602d2516279da6058cbb696fa8b1d89a20d2099e646443210483e5d4134e928faeb38a3b508199e0d69bb55ee34774205c0a61205b50b08febeaa401e6e3a51a2bf98efac78b7ae2b852c5395a12c40e2c7dd1b202504b5a7d2f7e4fd4f8610930d2868cba8864339e041da21c0715f41b2b23d14d0b545480bc3bd7d7215cf2f816a3332081ecaa08c0f8b99525251f57231b6750c2dbd1109ac4160486b768324b6bac87ef5a226448c431240328f42cca586be7aff3cbe7605fa341514fccfb966af3d4530e8cd9037a11ce593c2d383e1035a0c2eda098de90d50c5184a9c01b57f26b94dedd1454c340637ecccee70625754a328c65f42645b5e1a5655eef97dfb1c6308edf49fa368d17d17e06adc512b3973ea652ac40a9978e1bb1b2f86c5a9ffbf60dcc4f6bbc98a64f4de65e7ec61721edeb0e5238456f761d2d1293af0de9f793b11d8cadf01a94319a02a4273ffc4d3ffa7b34d74fd2e0b100fca58b5325f907a749193e751d6c116687aee3747b59460d4ef156e72476eae1b8455d76e71b306b98129b72fe1cb5eb405a7c2f4327f3862d4:696bd552dd01db80b3d67d61eeb7ecc56878404ab119442a1c7422992cfa35aea920825d2dafd892ad7eb6825ad999aee5c83b7b507906534f91ace759c5510c87e6dead2c85549e3d8d2588a0a3360603a624fb65aebbc101bf7f1fec18d0b28fbd5dbaeed38752cdf6355ce8dc84e18ac1a4393d2ab888882c4ff1c9c8137f83bee36336bcbfbb72d5049e0a400874514fdc3633046e89383dded93ca31fde0d898e11e9268d3d5c240666ed5527613da79fb7e49625b44cde78b41c67902eb0216b3a7a3e560e261d71d764aacf15959c17fcd6176fb25e249ee6bb1b3bd7bd90f60b0b0ffa0315a065a24bbae8f255bf298d7e4d44f0b430c415b4fb36cfa6626a83f49a2567f6244f40e923add1d49a72f57b1530f5b379de3a91c2e9a1ac79ab37bc3b9ba73d8828136bcc87d2c01190de5457facd90f369553f7ac521c5672b0867dfa8da3b952ad95b67dab99b4820572f2d4a298e9518637779289c031b793dee859cde7b24add649fff871248a6602d2516279da6058cbb696fa8b1d89a20d2099e646443210483e5d4134e928faeb38a3b508199e0d69bb55ee34774205c0a61205b50b08febeaa401e6e3a51a2bf98efac78b7ae2b852c5395a12c40e2c7dd1b202504b5a7d2f7e4fd4f8610930d2868cba8864339e041da21c0715f41b2b23d14d0b545480bc3bd7d7215cf2f816a3332081ecaa08c0f8b99525251f57231b6750c2dbd1109ac4160486b768324b6bac87ef5a226448c431240328f42cca586be7aff3cbe7605fa341514fccfb966af3d4530e8cd9037a11ce593c2d383e1035a0c2eda098de90d50c5184a9c01b57f26b94dedd1454c340637ecccee70625754a328c65f42645b5e1a5655eef97dfb1c6308edf49fa368d17d17e06adc512b3973ea652ac40a9978e1bb1b2f86c5a9ffbf60dcc4f6bbc98a64f4de65e7ec61721edeb0e5238456f761d2d1293af0de9f793b11d8cadf01a94319a02a4273ffc4d3ffa7b34d74fd2e0b100fca58b5325f907a749193e751d6c116687aee3747b59460d4ef156e72476eae1b8455d76e71b306b98129b72fe1cb5eb405a7c2f4327f3862d4: +29321469ee9f2bb165a069640332b489bf5c3fab682e93dae9d86317bf50c52c96f730f8ef8970268dba0f7570410b6188a1a3c86397740913d53ada262ab87e:96f730f8ef8970268dba0f7570410b6188a1a3c86397740913d53ada262ab87e:9c712c83d54f2e993ca68a9632846004499c5195448ddc491c3a0d2e3a666d6b33098e4864fdf86e619d50f10b7cc6c39b3ff2801a9491f6fa97c5f1c4afa7aeff31d738f9a768a79c73b25577310fb0ad4faf8543a098f859571b6148e8b52926445757d5549fd25a26518531566379d1c274e6c6a9d64132e4ac25ac9af9381bcb885332113f43014a139a81f8d43c8a6ab54c11a5c92e06191c1e51b757ac9f11e3dc15db4486d167ff9f2d65e23e6c96223d9aff8d10d1502cf3dbce5e357e6b12dbe9b7e997c3d0a507d3bae3cfef1ffc8d056ef7dc72ddc1c81e310ad205be16e77f2738354b10b484d3076c27e6b4f166388581f350befe22fbb082b54121ee59ecc7ae5dece89882acf26cb747ffaa3e2d05a696f60fd9e829c709d8f02daf537b2369b891fe6ccbf8dfcdd7f4a364b19985be7edec67ddc1db713c0a90fafa48837772562deacc2d2a0e789e18a8b5b3bd9e083ea92fffc3183d5d414153259b33a4329cfc80824ebcbe044a7e33ab8a24fde54bd9520aea284b0c4c4fa9427d251c0ddd013ecdd8290ef5565f608508e363589e529d84ff0f26f9ecb03052d5897fabc917e56e601b64abfe5a17c3950289d0cdcaf1f6005a9f8106f43e17adcaa2d1e269166762f8054de05135d5d1393d7000a15b87bd68846a89d5bc22863325151aac843f72278ae6f4af72a4e449adb7eae6d436a1ec7e58e59b7b8bb9ef0ddaaa001826f8dcb446479deafd8b8d542041c19a05b1e0ee47b4640910c31930ca4e20b105758ec75f1950356947f6261d0037fe30773a3ece6a96c8d5433333d822c2777ef7ff8be6033345b5055d58f5eb3729af5ae8824f331ee0731c89b20ac118f550427cd958a55f6b1a2888a087bb7db55bfc73b29429b4448dbe9119c45a87339b4497a69a4cf833e8f3770cce5e01faf5e73bbaf627683c0a28c73052fbece203043389dfbfd45495e51dab86a252e5bc1b4b7fe2807e3d0e2363beab51c67fb31:4e1aff8463bca1b7deb1d3773df2e7a06864111b6dc42a62ae98deb2313943b3153ee46696b15c24efc2a808aaba81c78e3dfa4dfb50ca9fe84445ea68bc8e0a9c712c83d54f2e993ca68a9632846004499c5195448ddc491c3a0d2e3a666d6b33098e4864fdf86e619d50f10b7cc6c39b3ff2801a9491f6fa97c5f1c4afa7aeff31d738f9a768a79c73b25577310fb0ad4faf8543a098f859571b6148e8b52926445757d5549fd25a26518531566379d1c274e6c6a9d64132e4ac25ac9af9381bcb885332113f43014a139a81f8d43c8a6ab54c11a5c92e06191c1e51b757ac9f11e3dc15db4486d167ff9f2d65e23e6c96223d9aff8d10d1502cf3dbce5e357e6b12dbe9b7e997c3d0a507d3bae3cfef1ffc8d056ef7dc72ddc1c81e310ad205be16e77f2738354b10b484d3076c27e6b4f166388581f350befe22fbb082b54121ee59ecc7ae5dece89882acf26cb747ffaa3e2d05a696f60fd9e829c709d8f02daf537b2369b891fe6ccbf8dfcdd7f4a364b19985be7edec67ddc1db713c0a90fafa48837772562deacc2d2a0e789e18a8b5b3bd9e083ea92fffc3183d5d414153259b33a4329cfc80824ebcbe044a7e33ab8a24fde54bd9520aea284b0c4c4fa9427d251c0ddd013ecdd8290ef5565f608508e363589e529d84ff0f26f9ecb03052d5897fabc917e56e601b64abfe5a17c3950289d0cdcaf1f6005a9f8106f43e17adcaa2d1e269166762f8054de05135d5d1393d7000a15b87bd68846a89d5bc22863325151aac843f72278ae6f4af72a4e449adb7eae6d436a1ec7e58e59b7b8bb9ef0ddaaa001826f8dcb446479deafd8b8d542041c19a05b1e0ee47b4640910c31930ca4e20b105758ec75f1950356947f6261d0037fe30773a3ece6a96c8d5433333d822c2777ef7ff8be6033345b5055d58f5eb3729af5ae8824f331ee0731c89b20ac118f550427cd958a55f6b1a2888a087bb7db55bfc73b29429b4448dbe9119c45a87339b4497a69a4cf833e8f3770cce5e01faf5e73bbaf627683c0a28c73052fbece203043389dfbfd45495e51dab86a252e5bc1b4b7fe2807e3d0e2363beab51c67fb31: +04657750497e68152c43ce34a58d2106e64c557cd7a84ef05d9eb82e6bcb05f53b3a1947b4cbf60b826d609f192dc230aa9b9baf4cd6a6092e495f1d2e47ad62:3b3a1947b4cbf60b826d609f192dc230aa9b9baf4cd6a6092e495f1d2e47ad62:2948227a890f6f845b775e62c53af3805064a1576446f085d90f8b9a5ed68df1ea393ce479c4414149a9ec5a171036424dff0344b4958f6132298d0e24c926d28ad9d79f98c6e6bcf1c5767606ecd291c6ad47b4f9fb2b0201155ada627b7a1fd5b07419874083059eb52b2f6ec22818b78246228f3fe6355dfda70ebb9bbe73229378736399557ce24b30bf645a14e2256f70019b3336b203fb77c6ec94a7a2634888feead4d72c2391e99e8c8d533fd8a42b08c11f887ab2deb6ebbfe3d251de63536c36cd53422398e544cff87b07a63349fc5085dde93a1bfd7171133a2043981f607522c8133c63428d1b92626c79b7358e7021cf1f412a78afa7cb3f59ffef9279885a5bdb2466acd34cd51580830b8351ebd440a96623907ad1f4b56203f5e159a429e3546ead0c011dbed09028717e3c3dfed39197764d4d245ef228b98044718ef4d8822f21b2c5685038473bf93dc0937451eb02d31a46c8dc7e94c3e8678c83b98a43818f125b528b476aad31d1584ffd48f149e5736e58f94205d3889e567e4dd1eac2fac1f8f4dc540e5322460fb940e12e93c4c98ded1941c1904f967fb4643684c19a4d5c441d60b0e9f40855e523fe7f99107657a68076275bf84b7c69a3f2b3855bc8026ba9b00bc6fe34b99da0631700a67f52b34e1796339887a48305121d53ab4440fc4b5c9bf72394d5ed372ff18ca3f007bd02df651dc3ac438275f1a3e52422b86c4586766a21cd89f805805dbb44fd89fe24fb2c0b40d1b754c335dbaffc3b3bb8bb46c74c36374504042d86789227599862312e99ca89eb504cc3d75d19495aa86b20b2736b121bb2075c88ed4a3fbdaa6b2c3f76d1ff5525d3a2863e4d83c72bfe01e10278809474e1822de2d96283489320029611aa9dffc4829d66869e63494f9aade70b77a7b80fbc93e3de4d935913752d045e13b312c5d082f6242d4985b053b3783eb02c6614963dc0d55d4cbe887bae29cc18979e5e2ea945bcd40d89:7e2eae5a293f418391f6d85a7994b07c452280017ee653bf617a8d5be24cbb5d0efdfb7f7f001312260f344e6fb915ad8d7de9c0519827c05726f9ce2545dd0b2948227a890f6f845b775e62c53af3805064a1576446f085d90f8b9a5ed68df1ea393ce479c4414149a9ec5a171036424dff0344b4958f6132298d0e24c926d28ad9d79f98c6e6bcf1c5767606ecd291c6ad47b4f9fb2b0201155ada627b7a1fd5b07419874083059eb52b2f6ec22818b78246228f3fe6355dfda70ebb9bbe73229378736399557ce24b30bf645a14e2256f70019b3336b203fb77c6ec94a7a2634888feead4d72c2391e99e8c8d533fd8a42b08c11f887ab2deb6ebbfe3d251de63536c36cd53422398e544cff87b07a63349fc5085dde93a1bfd7171133a2043981f607522c8133c63428d1b92626c79b7358e7021cf1f412a78afa7cb3f59ffef9279885a5bdb2466acd34cd51580830b8351ebd440a96623907ad1f4b56203f5e159a429e3546ead0c011dbed09028717e3c3dfed39197764d4d245ef228b98044718ef4d8822f21b2c5685038473bf93dc0937451eb02d31a46c8dc7e94c3e8678c83b98a43818f125b528b476aad31d1584ffd48f149e5736e58f94205d3889e567e4dd1eac2fac1f8f4dc540e5322460fb940e12e93c4c98ded1941c1904f967fb4643684c19a4d5c441d60b0e9f40855e523fe7f99107657a68076275bf84b7c69a3f2b3855bc8026ba9b00bc6fe34b99da0631700a67f52b34e1796339887a48305121d53ab4440fc4b5c9bf72394d5ed372ff18ca3f007bd02df651dc3ac438275f1a3e52422b86c4586766a21cd89f805805dbb44fd89fe24fb2c0b40d1b754c335dbaffc3b3bb8bb46c74c36374504042d86789227599862312e99ca89eb504cc3d75d19495aa86b20b2736b121bb2075c88ed4a3fbdaa6b2c3f76d1ff5525d3a2863e4d83c72bfe01e10278809474e1822de2d96283489320029611aa9dffc4829d66869e63494f9aade70b77a7b80fbc93e3de4d935913752d045e13b312c5d082f6242d4985b053b3783eb02c6614963dc0d55d4cbe887bae29cc18979e5e2ea945bcd40d89: +8bd99070c50a9fa418ef7f75c00129916a41c86070961ccb2b202be18c2d10d7ddd73308fce8ca6552d039428c7a1a94923320a31c0f580d3c235280f03c1830:ddd73308fce8ca6552d039428c7a1a94923320a31c0f580d3c235280f03c1830:485f8d680f79ee2d828be7d018a65e0b64b0f0184819863e7110eea8f299a72c4dc87f8ee8a8aeaa81af91dc71adea79fc9797421ccc646e6cd5dd48b4dec1de968693fbce0d0021a3d98d38a8bbc58195e6dfc3b5e1461b2a594103e80a29441d5aaaf889e31cc865141f0c6b2c8c81f721679ea2394ec6e4081ec203c2ea397d9484757a7a0ecd53e652db9df17bea0e32fe8b2cbce0d1d97b961ed74e8e622bcdd3558b7c48695adf18aae6110ea9a339b9da407a9edaf2ab081a681e1832cc215b1f08a67d559a4744af7cd50318c206ee91157582f82eb6c0fc29027b4461c30733b8169d1481322c4860509ba096bacb71a579246751d567540e41431e14f1b46ef16eba276104bc01650d5c4926e47c9c6040784b043cd0aa4854efe8797fd0462d4539f38035aef08b4577c1a9118d004b6d01862f5276776dfef1371864f155ac0f078389c205cf0538d85fa348244d7a422911310ff6c10132b1598bb445c7e2077b763c473d1e7a61a38b64929a648b60b2e543543739224b40fbf6d87f1079c30bc873ac38991d51b89e9d261c4bccb375355c072c1ea20e4ff91d55d9f7544e90d1c6646c59af72424d8aaa8e0aed07b3889d4e450c1209684ce138d0c9da079525f5aa02050af570e4315c2fa8b099b7765bfbb894fad359b8e24804ece052ac22a191705335e98840a624e4cbf3a1a1a327812785b2c0f5d6381457b72fdb633e81938bbb54b8c37cccb5d59c5827c7683a5247544977e984442178d0852906ca6f945c4229eb08ad27e6c275d7b4ec8dc25fb2819337e53ead6c7aa787f91a7dc6ddafd536eefcbdec2c50167be34306a82e16d5d52b3b1be008a7a611274ce2cf8d62e3b900c09943be70ccc77b070637c25061d61be910eef50df18744c33e76f6701e0a8ff6297fa67e4b4108c13756727a9d74bc9e17983eec08f866b7c7ffb37f3ccb0141a80feff6322b2ac62b84ce2797fd98d6ff269a41a0c38482db679862a38cd2:b14a7b262012c5909e21d587fb4f29a9093c8e1c2999816a82118fefbf10e68ea898bf0da18ebfd0341ea8f82a1844c8e0dd5306e509b9d0c35b473a7d209507485f8d680f79ee2d828be7d018a65e0b64b0f0184819863e7110eea8f299a72c4dc87f8ee8a8aeaa81af91dc71adea79fc9797421ccc646e6cd5dd48b4dec1de968693fbce0d0021a3d98d38a8bbc58195e6dfc3b5e1461b2a594103e80a29441d5aaaf889e31cc865141f0c6b2c8c81f721679ea2394ec6e4081ec203c2ea397d9484757a7a0ecd53e652db9df17bea0e32fe8b2cbce0d1d97b961ed74e8e622bcdd3558b7c48695adf18aae6110ea9a339b9da407a9edaf2ab081a681e1832cc215b1f08a67d559a4744af7cd50318c206ee91157582f82eb6c0fc29027b4461c30733b8169d1481322c4860509ba096bacb71a579246751d567540e41431e14f1b46ef16eba276104bc01650d5c4926e47c9c6040784b043cd0aa4854efe8797fd0462d4539f38035aef08b4577c1a9118d004b6d01862f5276776dfef1371864f155ac0f078389c205cf0538d85fa348244d7a422911310ff6c10132b1598bb445c7e2077b763c473d1e7a61a38b64929a648b60b2e543543739224b40fbf6d87f1079c30bc873ac38991d51b89e9d261c4bccb375355c072c1ea20e4ff91d55d9f7544e90d1c6646c59af72424d8aaa8e0aed07b3889d4e450c1209684ce138d0c9da079525f5aa02050af570e4315c2fa8b099b7765bfbb894fad359b8e24804ece052ac22a191705335e98840a624e4cbf3a1a1a327812785b2c0f5d6381457b72fdb633e81938bbb54b8c37cccb5d59c5827c7683a5247544977e984442178d0852906ca6f945c4229eb08ad27e6c275d7b4ec8dc25fb2819337e53ead6c7aa787f91a7dc6ddafd536eefcbdec2c50167be34306a82e16d5d52b3b1be008a7a611274ce2cf8d62e3b900c09943be70ccc77b070637c25061d61be910eef50df18744c33e76f6701e0a8ff6297fa67e4b4108c13756727a9d74bc9e17983eec08f866b7c7ffb37f3ccb0141a80feff6322b2ac62b84ce2797fd98d6ff269a41a0c38482db679862a38cd2: +1af4cf6d24ab3782867d96a1c275ceeb022c691a308e6245665d616bf67c2c3219d317ea98d35ba5fa67c12ecfb32750df275d7a45b8e211a7ac47ede7712d9f:19d317ea98d35ba5fa67c12ecfb32750df275d7a45b8e211a7ac47ede7712d9f:f445fdcfe28c17bd4427aea5676c0e1280841597e9d66de7d7a71723110939bed00f4ebaf9603d53c9cbf6271be547af29b2a045ec41288a7bb79d662dc210e215957fa84688c916543e5617f560e4d38f73baefc37e11914e47c515067851e8ed21393e13dd19ed9b73d98945fc826a258e957dc083dd8e535c30a54b4266dd71d113ce856b46282a18033627a98e6472ccb463ed3d96fa7b355d3b2c2a2b6010dd14f4ea3965dd87be1c429bdea8300b4b0b44458635b4979f5e3e8eb5c618d4e13e1d688bf88c7e4a3d938e84336d67be68df3435c5c99086321c02e13b4a12524b34e46a0b4d27f30d7ed4f5cecb36deadf09e7efcc755ca667568297914c6bc240627d9d09aacf85415412c0635623453278d9bf0e10eec65fc72affffa9392dc7881d1e5c760a40280f16b1475127b91b69ccb65dc4b35de10f94325c0cbe1c47019a2eaf2b4ba92d785229aacfad1826ebbdebefb7dad4b05f88243e15f279766e3321dd8dba650444d81fb0878767a9c63534bb4ba21285a2416cb8f856d11a96e0a8c8de1e1a75132f1564cd994995690bbed2ee154537fb6f279fb09c8dea6f6afabc62856e3d128fdfa79fc4976193bb9b336861e47b56dc2582393d2e544651ac85bc58e9e6a94dc4c39c4ef72538a14f856cd95c3e2790adee03ab2e52ca0ae471de502cb19e676af35f5f93d840fef9606cbe92d8bc25006105d92344588838842c3be505c7350e351b735e6cc6fb79275b27bd9ebd36ba4d060acee73b5a315ceffab86d06f2168a67065578196a0ed04a4dd71d6734837db083857ab1eb5e0eec4ffbac9544f4ec19bde194df84b1c848341574bf10daee85b8178196fb608123a808171d73ce4206ad65216ad1a5cbde40b19d6ae7f40df97ab8432e2c53a504ed122e25fb7a51c14354ab3928edeb39c29eb246b74a076f89d03504f401bd176b5cffee4b9db097c45764f51aa376704b5a7f210b3f1a905e25d67002f6557ebb749737cda31:7eb46cd0de3155b43747d732f1045d8ef74492ad827a2245bd17102828442e43a0ce7e8b268ed7fd8d3e7b28f072795da3e070f12bc4e23eaef57b853cee880af445fdcfe28c17bd4427aea5676c0e1280841597e9d66de7d7a71723110939bed00f4ebaf9603d53c9cbf6271be547af29b2a045ec41288a7bb79d662dc210e215957fa84688c916543e5617f560e4d38f73baefc37e11914e47c515067851e8ed21393e13dd19ed9b73d98945fc826a258e957dc083dd8e535c30a54b4266dd71d113ce856b46282a18033627a98e6472ccb463ed3d96fa7b355d3b2c2a2b6010dd14f4ea3965dd87be1c429bdea8300b4b0b44458635b4979f5e3e8eb5c618d4e13e1d688bf88c7e4a3d938e84336d67be68df3435c5c99086321c02e13b4a12524b34e46a0b4d27f30d7ed4f5cecb36deadf09e7efcc755ca667568297914c6bc240627d9d09aacf85415412c0635623453278d9bf0e10eec65fc72affffa9392dc7881d1e5c760a40280f16b1475127b91b69ccb65dc4b35de10f94325c0cbe1c47019a2eaf2b4ba92d785229aacfad1826ebbdebefb7dad4b05f88243e15f279766e3321dd8dba650444d81fb0878767a9c63534bb4ba21285a2416cb8f856d11a96e0a8c8de1e1a75132f1564cd994995690bbed2ee154537fb6f279fb09c8dea6f6afabc62856e3d128fdfa79fc4976193bb9b336861e47b56dc2582393d2e544651ac85bc58e9e6a94dc4c39c4ef72538a14f856cd95c3e2790adee03ab2e52ca0ae471de502cb19e676af35f5f93d840fef9606cbe92d8bc25006105d92344588838842c3be505c7350e351b735e6cc6fb79275b27bd9ebd36ba4d060acee73b5a315ceffab86d06f2168a67065578196a0ed04a4dd71d6734837db083857ab1eb5e0eec4ffbac9544f4ec19bde194df84b1c848341574bf10daee85b8178196fb608123a808171d73ce4206ad65216ad1a5cbde40b19d6ae7f40df97ab8432e2c53a504ed122e25fb7a51c14354ab3928edeb39c29eb246b74a076f89d03504f401bd176b5cffee4b9db097c45764f51aa376704b5a7f210b3f1a905e25d67002f6557ebb749737cda31: +2aacc8197ff8fae1c1cf3862e3c04a21782951f8e48e40b588f8bc7460c30a039a1b01e2154f1c36a8e16b79ee7d2d05b8712e0d27a061a6d41d475778b0df8c:9a1b01e2154f1c36a8e16b79ee7d2d05b8712e0d27a061a6d41d475778b0df8c:5d82752ce5da3180faf4787aedfb19294b4348a1d9202c85398331323e0f42b0835227e68e1156f2d4ba2fe450e6d6ef2b92d89bbbe4096e12ca8397eb2f45e676f1673aa41c959fcd30d5578853b5dbd1c0d5b3a0f0d870eca71ea13390111b258f6548b32f37a05e9744a656fd778d65721965c6d9b328600b45704770e04b099790aa7884f00d7bb7659e337210bdc23eaa71d7b016030aca6223b5569bdfc290811aac409524dccbf9babcbe4bf20946b544317ca6f2f91831c79fb273b6404eb4e61e1f7b106ebd0db9f2b1974d2f031bce25803606552c3441655efcf2c7ea52adcb30993d85f2dda79603e9415a023245a66c07a956933146f53c993c08891808b8166b30721fbd1f8a1b937d14070d786e9eb451f2ab5142f83a60f35d76ad8b81d6a57cf368fc6fcacc0c4758440d9cd595b1b0942a3655e250da983b7241546dcfbe0ae81077650295409ff9e90977fb9960cbf40a2af5177402ba2faf50db6f1a7365cf99e992429e38db43ea83fddc95a648676c0b16bc952b15de99d52f6b5233da4eae1978e8ba25e6235afbc511c76c4c874c9237922b1cef0847d07a80200cbae3c7c81fcbd0d17252ed8c61ad1954fc862e1e04444c32086fee380d1c17541322b9a60da662352e210e9ae215e353296db922339aa17d2173ec31f1c530a24b1f348a31572e1469caac808f9c76ec2731873b803ead3e54ea24bc24499b9704b3bdce81389b9d14d49527c04b3bb9e3ba6d946cea58cf786d4d28b89b41c58274035a86905ad95758c3161366ab93da81e6b4c808364e087daeea4c4c5c2aa6871937c5feaba2149f01f738f45396e66ea8063221e1c81c05255ba564ad440cb5d07cbd4bab941ea593244930bc5c289b3165d3ec8847ebc4b674c0a49f9169adef786d7767bc8f213db7d95c06e99bc11e200055b65eb79adaa01bcd2c85da43ce6370e12e349bf6d475487affdf92e20a3acded1d76f9e83e919e98def195072a50d0c571dd25:647cdd6c1a67290e57676a78113aaadca69ac57b997715c509895b8c5c94e82c0b6aceccf3ba8bd7cf61752b1b19d13b49f15f8bfa046eb442a55cd5bab142025d82752ce5da3180faf4787aedfb19294b4348a1d9202c85398331323e0f42b0835227e68e1156f2d4ba2fe450e6d6ef2b92d89bbbe4096e12ca8397eb2f45e676f1673aa41c959fcd30d5578853b5dbd1c0d5b3a0f0d870eca71ea13390111b258f6548b32f37a05e9744a656fd778d65721965c6d9b328600b45704770e04b099790aa7884f00d7bb7659e337210bdc23eaa71d7b016030aca6223b5569bdfc290811aac409524dccbf9babcbe4bf20946b544317ca6f2f91831c79fb273b6404eb4e61e1f7b106ebd0db9f2b1974d2f031bce25803606552c3441655efcf2c7ea52adcb30993d85f2dda79603e9415a023245a66c07a956933146f53c993c08891808b8166b30721fbd1f8a1b937d14070d786e9eb451f2ab5142f83a60f35d76ad8b81d6a57cf368fc6fcacc0c4758440d9cd595b1b0942a3655e250da983b7241546dcfbe0ae81077650295409ff9e90977fb9960cbf40a2af5177402ba2faf50db6f1a7365cf99e992429e38db43ea83fddc95a648676c0b16bc952b15de99d52f6b5233da4eae1978e8ba25e6235afbc511c76c4c874c9237922b1cef0847d07a80200cbae3c7c81fcbd0d17252ed8c61ad1954fc862e1e04444c32086fee380d1c17541322b9a60da662352e210e9ae215e353296db922339aa17d2173ec31f1c530a24b1f348a31572e1469caac808f9c76ec2731873b803ead3e54ea24bc24499b9704b3bdce81389b9d14d49527c04b3bb9e3ba6d946cea58cf786d4d28b89b41c58274035a86905ad95758c3161366ab93da81e6b4c808364e087daeea4c4c5c2aa6871937c5feaba2149f01f738f45396e66ea8063221e1c81c05255ba564ad440cb5d07cbd4bab941ea593244930bc5c289b3165d3ec8847ebc4b674c0a49f9169adef786d7767bc8f213db7d95c06e99bc11e200055b65eb79adaa01bcd2c85da43ce6370e12e349bf6d475487affdf92e20a3acded1d76f9e83e919e98def195072a50d0c571dd25: +ff862156c7eab681c95efff8003e00a14f1f0d505d5507e6e5b39179df9b1cdae1b89fb31114ea46107ffd0329f1066428de54708edbecf3ed9d4708cd143fe2:e1b89fb31114ea46107ffd0329f1066428de54708edbecf3ed9d4708cd143fe2:b3d1db72a6a985ecd70a2cff6c18c179e217d4f410fd3934969685901bd071bce6c2fb6763e10c6fa16e75a1176066b8ec81ae3a8039e71dc2cdc64a40fd62b7cee7be4ba0332fe45d0b60158652e33f8d3aff3cb4d6b021744d0dd178b1bf0a1cc1d3fe9321be28421eb88263a124f49792d079475a8c555ff5690873514b5d483e53217e0cbb12862b850fe390c8f83008086e649ac904b018350ab49157ee9bcae6c07a4b878b48e25e984fbb4d36b61d689b13468a28d1e387e0e88657f8c8ac9586a6e26cf94dff6f8264e3ff6258865c6dcf857b00147886e175df0432e32f04400e299f21188312b32dfc050e7b7e87eeaa0cbaac6be9937a5e0cc31113de7c8b233e1ce8e5d9c564fbe9f37bbd411df7a5e44e6c7ebb676d85894dccf4865e4dda0cadef2bbc55000b3a29f1f71ef4461ddc3b331d91566534c5d6d84c731376295320f80adc90288f9953554fcdf9213de6a905210d4c8064af91cd98325ef91898d33d70038202e32fb6709ca3d788fecbd1b841fa4e5e9062d64267c35cfd444fb69e2f6047f58b1c2af4cc7e4cac2f890888360592113e96ad3a857ed05eaaba6f9153ef89b93e00e8743733ec472d9b0eec1cd8fa52425c4a26bd7df73a2712bebe51ae3b25eb78db82149031fe7b281af6cb7714edf89de915f3470f153eed7f456243bb90342e190e647f39e046883ce28a892003315ea379429e9582a935eb78963396d136845f86c466e8faf2272f43ffefc2ada5601f8a6b2ac4cc6b92820917f2e0393c8faf982d6c5f4f230e27ce2278a7237747fa85a9c857bf1802c3eae0d235b5ad58497d66a0d3a9baebcc417f1833e9cc4460f975d72858cd118d7aafaf1c878297cacf71ac75676dc1b4fb51c1775810d03537f2d766278b9971bb97d3c49b51feb26d375e0cb9109574a816f84e76fc7ef072d5793c2f65ab2efd9052e6b8569f2805861c31a7344a3c44069a94320d274e271271eafa3bfe64de7537846a01e51fdae0:4b8137042d6784757d4a9c06bc7432f4809b1c6a903542736d9a57668c20845c17d468557085c57fb63213dad3be0fa36a118f7c1aeff2562ff4b8888c26900eb3d1db72a6a985ecd70a2cff6c18c179e217d4f410fd3934969685901bd071bce6c2fb6763e10c6fa16e75a1176066b8ec81ae3a8039e71dc2cdc64a40fd62b7cee7be4ba0332fe45d0b60158652e33f8d3aff3cb4d6b021744d0dd178b1bf0a1cc1d3fe9321be28421eb88263a124f49792d079475a8c555ff5690873514b5d483e53217e0cbb12862b850fe390c8f83008086e649ac904b018350ab49157ee9bcae6c07a4b878b48e25e984fbb4d36b61d689b13468a28d1e387e0e88657f8c8ac9586a6e26cf94dff6f8264e3ff6258865c6dcf857b00147886e175df0432e32f04400e299f21188312b32dfc050e7b7e87eeaa0cbaac6be9937a5e0cc31113de7c8b233e1ce8e5d9c564fbe9f37bbd411df7a5e44e6c7ebb676d85894dccf4865e4dda0cadef2bbc55000b3a29f1f71ef4461ddc3b331d91566534c5d6d84c731376295320f80adc90288f9953554fcdf9213de6a905210d4c8064af91cd98325ef91898d33d70038202e32fb6709ca3d788fecbd1b841fa4e5e9062d64267c35cfd444fb69e2f6047f58b1c2af4cc7e4cac2f890888360592113e96ad3a857ed05eaaba6f9153ef89b93e00e8743733ec472d9b0eec1cd8fa52425c4a26bd7df73a2712bebe51ae3b25eb78db82149031fe7b281af6cb7714edf89de915f3470f153eed7f456243bb90342e190e647f39e046883ce28a892003315ea379429e9582a935eb78963396d136845f86c466e8faf2272f43ffefc2ada5601f8a6b2ac4cc6b92820917f2e0393c8faf982d6c5f4f230e27ce2278a7237747fa85a9c857bf1802c3eae0d235b5ad58497d66a0d3a9baebcc417f1833e9cc4460f975d72858cd118d7aafaf1c878297cacf71ac75676dc1b4fb51c1775810d03537f2d766278b9971bb97d3c49b51feb26d375e0cb9109574a816f84e76fc7ef072d5793c2f65ab2efd9052e6b8569f2805861c31a7344a3c44069a94320d274e271271eafa3bfe64de7537846a01e51fdae0: +582619ab3cf5a3ae776688bf6dbacb36330a35ad7524e49ef663687764cf6ec72002ea0a38a327e0384aeae468db0f6c8516a69609af9eee93e9ecb94b449c66:2002ea0a38a327e0384aeae468db0f6c8516a69609af9eee93e9ecb94b449c66:ca74284f11c56e2598d78a4ecd03b40e017a558176012b26fdf695c3de98a74f8f40a47d7978edc24ee8092bfe5e61596834deed1d9d34a0f5cdaebe3421aa19e012de865b9ee1b73479b2bd1ac982f97ed9c7cd20459c60fbb11e1e2b4eac5db6844c71d72949502bba503acec905adba25f6b119eaf9639fa8abb302dff9932d850cc44c57cf90b2e58a8b5251c126a9e28f5c761b6280e2cddd79cbd68e53ff4a6226d3bd4c961b9b9e4345a2545862c7973866f0420b898e7baea90ea4ee004042ef38a1fd956a72fdf6fd43257da9fdb96680ef4fdf9e943d265cdcf2e52e3201d5408bc6ce10e5700adf12b55ba14aa829d8691c31f24fc4a51ce6faa1f3ef2ead78e5e753446ad3fa4a84c193979aebc8309bad60814f4859b931d70414764491c6c9ed8db673c543d35185cd2888aa21c1a9203427e0ac0b1fe34c0e4a4001e0956c13cb59a3baf87c2109a888a4c9e7aa481767d8020ff35dd7c5ccec7c08e971a7e218138c90546a7ddf36ad114be58557432c2ddf34ced3379f70d4407e5879f9842f381717051b1685aa7ab0ad38541ec168f51cb688f3cd1a019a336c9f4f3f82de785c074867fdc8800fc76fba04c8ad8de10d2e9b430581be44c41ecc8fc8a616314399d18c6479f57e573b22a6ee5ce2dcc08948a0de1f0dd25b65715ab18c70c762fc3d7d600cad63226038509c19ab35b5493eee73a703731ec535c90c6f06d94d3e5f7e51a09f9f8f42c501b8504686365ceee9e0fe001329f303522146717c6a1258d0f157cbea4b5a5e3d13bc907e95fd6e8a71896a02c3106bd26a510051f1b30258ab27f875673b1337ee36b71a376e0f9e7809a67c67d9acc16c251dcb8c926c8e932516d38b7233eac6159c59cad0307c590e7131b62219145aaa355bfb4acb6af0a5500006cdd8b813fe1908602e0874c9622bb37673ba1acba414231667bcc4907ac871f87e6ce3f591c19171057a9f457f5362aeda105d18fb84f7d0f0a7da7ef8da9114:fe9701da1aa81c55bac33638f775542b804480f34b7bfc78da9916e5246a604d390bf920c872a77924246ee8d0393b202e7b25b2484f654ac367cb0925ece305ca74284f11c56e2598d78a4ecd03b40e017a558176012b26fdf695c3de98a74f8f40a47d7978edc24ee8092bfe5e61596834deed1d9d34a0f5cdaebe3421aa19e012de865b9ee1b73479b2bd1ac982f97ed9c7cd20459c60fbb11e1e2b4eac5db6844c71d72949502bba503acec905adba25f6b119eaf9639fa8abb302dff9932d850cc44c57cf90b2e58a8b5251c126a9e28f5c761b6280e2cddd79cbd68e53ff4a6226d3bd4c961b9b9e4345a2545862c7973866f0420b898e7baea90ea4ee004042ef38a1fd956a72fdf6fd43257da9fdb96680ef4fdf9e943d265cdcf2e52e3201d5408bc6ce10e5700adf12b55ba14aa829d8691c31f24fc4a51ce6faa1f3ef2ead78e5e753446ad3fa4a84c193979aebc8309bad60814f4859b931d70414764491c6c9ed8db673c543d35185cd2888aa21c1a9203427e0ac0b1fe34c0e4a4001e0956c13cb59a3baf87c2109a888a4c9e7aa481767d8020ff35dd7c5ccec7c08e971a7e218138c90546a7ddf36ad114be58557432c2ddf34ced3379f70d4407e5879f9842f381717051b1685aa7ab0ad38541ec168f51cb688f3cd1a019a336c9f4f3f82de785c074867fdc8800fc76fba04c8ad8de10d2e9b430581be44c41ecc8fc8a616314399d18c6479f57e573b22a6ee5ce2dcc08948a0de1f0dd25b65715ab18c70c762fc3d7d600cad63226038509c19ab35b5493eee73a703731ec535c90c6f06d94d3e5f7e51a09f9f8f42c501b8504686365ceee9e0fe001329f303522146717c6a1258d0f157cbea4b5a5e3d13bc907e95fd6e8a71896a02c3106bd26a510051f1b30258ab27f875673b1337ee36b71a376e0f9e7809a67c67d9acc16c251dcb8c926c8e932516d38b7233eac6159c59cad0307c590e7131b62219145aaa355bfb4acb6af0a5500006cdd8b813fe1908602e0874c9622bb37673ba1acba414231667bcc4907ac871f87e6ce3f591c19171057a9f457f5362aeda105d18fb84f7d0f0a7da7ef8da9114: +2bbd830ce7def3fecea1ecd6ea0ae9c9f4fa8ffc3b1f1938c505051bab40cf7a0fdfed8de3c1eaf891ce37e34cb4a2441cbbae0883383d70de2464850b4a642a:0fdfed8de3c1eaf891ce37e34cb4a2441cbbae0883383d70de2464850b4a642a:5f1edeaa3c0b2a63311d97f1c54e7e2f687170e6b46e2169cbf56c66f231bfc4a576bd2b8420bf357d3a90f8f32ea1ad9939b467254b66a1df1f5b4cbac63a5c2724260d24d8df8edb58ae247a2591e920b1a420cf8d8539ea57db0dadff1ad3e98c3172d033163cb434a766b0c118a56abdcce79c82af7bac74ed0ea024ac4ce0222d0aa914f432092b1b517804db5918a845e9cca55a87db7c2852f7dd2e48360185cc442c7930afe15dd622cc02bcd1ee778b59705f14333241588a522de24407e8e6e10d5ef3a88e3a3c4438c17f7504674fd7e418cb2f77ad0a56d2386703155e9a401c43ddb51ead5520aa7ba038e7de5331418ad552bdcd185f503a8548f55b6386e4687ca515f7c0eea570983bfb24be16f7b3003fb756e326562f2a32fe65ff844c3984c72e40dd49e4f3ae8c0f819a7939b2e736e381f5823cbc61b2ed01d9b05cf8b14648a48b0d7cbe882ac16cadd8c42aa2c70246347b4d849536a7ac22c720da3cf178725ee557a92c25b12b8b956d3bf4802e9e8a15b5ab754235cca0e5b7e55e4aece45a47e084ce1447440598ef5d4f5fdc2c98a5ad136cffbf87d3cf52f6738cca7948356092078fdf254577f55969a0c65246dac809a2fca1f60a1d929877b9a6540e88a9e6e9155938d22c687e63b387534d385e8961e5886743f95f4a7080d916624517b15336030a46714b168b83d6f9cce0606649c01f0a1d0a2a53f5e378f6aa98c384aafb3eefdb3421fa3ac98a0d3a9c029c2300ae0241067d1a4fc92e438688ea889fcb1a1a9e8634b916c60baa0c18bfcd139bfe3017bfbe16291343ce8605bb7872558c6b5fd56dfd221577edcffaa8bda34d7a11ab8cb278288e5834842676fccffaa9111bced2b3575fdd49621b76e8d129b61700eeab0314ef94d550506a4b8d1ee65508d89d0e99e9336b41d9f74aa4d722114de0f31ecf00b097f53c9aca9c7a285b58a35d70298c5c34f74b4a705308033100349f0c62f9c2ebf7dead0a77b298eb:13ebc979a88710e3c5f345cfbb824813b308a9d5c6dee328bfd235a97de7b326de6c738f96f69831949209996852dd9c098d5808418709f2bf510d46b7f036065f1edeaa3c0b2a63311d97f1c54e7e2f687170e6b46e2169cbf56c66f231bfc4a576bd2b8420bf357d3a90f8f32ea1ad9939b467254b66a1df1f5b4cbac63a5c2724260d24d8df8edb58ae247a2591e920b1a420cf8d8539ea57db0dadff1ad3e98c3172d033163cb434a766b0c118a56abdcce79c82af7bac74ed0ea024ac4ce0222d0aa914f432092b1b517804db5918a845e9cca55a87db7c2852f7dd2e48360185cc442c7930afe15dd622cc02bcd1ee778b59705f14333241588a522de24407e8e6e10d5ef3a88e3a3c4438c17f7504674fd7e418cb2f77ad0a56d2386703155e9a401c43ddb51ead5520aa7ba038e7de5331418ad552bdcd185f503a8548f55b6386e4687ca515f7c0eea570983bfb24be16f7b3003fb756e326562f2a32fe65ff844c3984c72e40dd49e4f3ae8c0f819a7939b2e736e381f5823cbc61b2ed01d9b05cf8b14648a48b0d7cbe882ac16cadd8c42aa2c70246347b4d849536a7ac22c720da3cf178725ee557a92c25b12b8b956d3bf4802e9e8a15b5ab754235cca0e5b7e55e4aece45a47e084ce1447440598ef5d4f5fdc2c98a5ad136cffbf87d3cf52f6738cca7948356092078fdf254577f55969a0c65246dac809a2fca1f60a1d929877b9a6540e88a9e6e9155938d22c687e63b387534d385e8961e5886743f95f4a7080d916624517b15336030a46714b168b83d6f9cce0606649c01f0a1d0a2a53f5e378f6aa98c384aafb3eefdb3421fa3ac98a0d3a9c029c2300ae0241067d1a4fc92e438688ea889fcb1a1a9e8634b916c60baa0c18bfcd139bfe3017bfbe16291343ce8605bb7872558c6b5fd56dfd221577edcffaa8bda34d7a11ab8cb278288e5834842676fccffaa9111bced2b3575fdd49621b76e8d129b61700eeab0314ef94d550506a4b8d1ee65508d89d0e99e9336b41d9f74aa4d722114de0f31ecf00b097f53c9aca9c7a285b58a35d70298c5c34f74b4a705308033100349f0c62f9c2ebf7dead0a77b298eb: +1a7a3c2f5481131be5f868456aa2fa90e56d52cb721c7184ebff06fed2fe685d7c2ad0f2a570550326fb50a850835821676de1de127f6de1670299d814f6e3ce:7c2ad0f2a570550326fb50a850835821676de1de127f6de1670299d814f6e3ce:c62834d9d55d1a4403e925d0a5b552da174c02f4e945dec338c1bbb2aeb4ff40020ef70ff505205cf881b629960abd62764e5a54f2b5105667b11c7d5b7a4ccc3f488bdddb958a7be9546207e6c4671897c053508e1fd83222130a7933976d2bec614ed8f9b6a6b9f4efb2a58b9d005b943e42f171b709a7313070cb2e068da39cf99922b69e285c82ad97f2d6c77922cae2b5e320e83577c0d088761ec88152c297492978a9d7a3ff67ede44c2a707cf3e2352e232f53c8782ba48928a97f8a36b20a416816e94579b9d7250a29dc8470f63a7058e2d2a99d6f0ccb530df5969505ef5c7844eb167d20f412a508fab1f8cd9c20c5eb9a417a5412b5da6a57135759fab17f6314f68df35b1772421443676f312579af6b1411535ada8f76012b69bbeb60b2897ee6607cb369cdf52f4f6ddf88cdb2630d78896f1361fea22ae634217696ff114fb42dbe4f4346f1be5b57adb384ae7e49b41f74b31b9a62bc69dca16589c634eb9d7c6c94f8ece44b60628f98e1024cf32e3e3dd6dce55a1222532f490d63e6a275281c0f3a6c101891b8d57a45de11de35ebb151c0dcd75e6c050b3cd8babae845c39f66c36c77cde05b683e4fb0103d93e7659335c87fc0e3235b2e82488cdabeb5c5c875808745eea92de86b8efcb63e16d082919aee2e92899cb0bcf1c1421577a4a0d9db09ee1f9feb92a5382103cf7c32cfe463725ae4866daafeda0534c169f8f9be404f3baae123fa768ace46178d4b9bbc5bd7aeec7903b0a5bc57538986ee09e07e32077b3b9de50dd1967a372c385ac886287c18451a64efb37d056f9f4194c08b1e3ec97022267bf0043c13d26b9ce1f53905f6e41b3d99dc81b331909b722666ef2432e6af8a453107531230ce4a1af8eed626da223da76b46507e33d7cdbde02d411040c89a11d95156ed4ac2605b826939c6cf877b4ee736c5da77cf4650a9997a3b9cf46a82ba2bc01333c04478b5c92e2498bd002f013140aedb301b95993d1d750870d988:976160fb5bbdabe5c8962f23babacf0b0ab41c2bb13e9c0d449067b7decc7db4e94e76a71b9c0ac4d6af387a72a8cd73e3bc63b7ed650beebf17424c490bd60dc62834d9d55d1a4403e925d0a5b552da174c02f4e945dec338c1bbb2aeb4ff40020ef70ff505205cf881b629960abd62764e5a54f2b5105667b11c7d5b7a4ccc3f488bdddb958a7be9546207e6c4671897c053508e1fd83222130a7933976d2bec614ed8f9b6a6b9f4efb2a58b9d005b943e42f171b709a7313070cb2e068da39cf99922b69e285c82ad97f2d6c77922cae2b5e320e83577c0d088761ec88152c297492978a9d7a3ff67ede44c2a707cf3e2352e232f53c8782ba48928a97f8a36b20a416816e94579b9d7250a29dc8470f63a7058e2d2a99d6f0ccb530df5969505ef5c7844eb167d20f412a508fab1f8cd9c20c5eb9a417a5412b5da6a57135759fab17f6314f68df35b1772421443676f312579af6b1411535ada8f76012b69bbeb60b2897ee6607cb369cdf52f4f6ddf88cdb2630d78896f1361fea22ae634217696ff114fb42dbe4f4346f1be5b57adb384ae7e49b41f74b31b9a62bc69dca16589c634eb9d7c6c94f8ece44b60628f98e1024cf32e3e3dd6dce55a1222532f490d63e6a275281c0f3a6c101891b8d57a45de11de35ebb151c0dcd75e6c050b3cd8babae845c39f66c36c77cde05b683e4fb0103d93e7659335c87fc0e3235b2e82488cdabeb5c5c875808745eea92de86b8efcb63e16d082919aee2e92899cb0bcf1c1421577a4a0d9db09ee1f9feb92a5382103cf7c32cfe463725ae4866daafeda0534c169f8f9be404f3baae123fa768ace46178d4b9bbc5bd7aeec7903b0a5bc57538986ee09e07e32077b3b9de50dd1967a372c385ac886287c18451a64efb37d056f9f4194c08b1e3ec97022267bf0043c13d26b9ce1f53905f6e41b3d99dc81b331909b722666ef2432e6af8a453107531230ce4a1af8eed626da223da76b46507e33d7cdbde02d411040c89a11d95156ed4ac2605b826939c6cf877b4ee736c5da77cf4650a9997a3b9cf46a82ba2bc01333c04478b5c92e2498bd002f013140aedb301b95993d1d750870d988: +191a1d90321c7f4e7494bb982909a9eb40c3341dd32ae4d96750b7d02966b40f9562d9e213f145c456935b7031c680669f8bbd31a4c2ed3c91c4002a5629e97b:9562d9e213f145c456935b7031c680669f8bbd31a4c2ed3c91c4002a5629e97b:85890db4e2fbce093dde5a80bf8fe09a984b83a49b7ccb5d4b06cdafddd382e4b8a8a50530e82c200612c9d7d8a089bc8aa845c3cfcc38a6195d21c2618c3dba2b570920eccfcd236f17f08d814268f882242ddf0702da8785f407aa8f86fecfa903c48da83f839777eb6b4a2bbf5df7a4da53475af1ffe44b5fe0072b8fbf3d26e6d89ea67d8ac8459492890ada657eb3dc2492b88de175b4bba1a508064d619674aaae2af09d31a5c27c8d5d5a29b03779f4286b8966ce407e6ff692fb942520a9938d69cc70acb06b014b6dfc19834206cf1ac6c448ae6f078025b55f3d827201268a92add9ad178ef76a2989fedc6e39f4ebb9f96c9b8352694fa54fa022019c0ec0012d0d769e2367803f925f175f9fb9cbec4a0c9c1e2c83ea57e6a92a17f555cab934271e72c8cc3215fcb87c20539bf14277b1bfbd6e5880ef953fc75f23c0dd4fcc1e0be340af947de02e877fd5c77dd1df7b414b5c0b40c74956a545a115b0c6993ab233b7e72c822b6b3381bb1fc10875bffe3e2ed1190fa33fc15da083794fcc2c5bf5a07909063cb289a08a2c8a33d343842c2d6a3cfa2a16ca2eafcab7ea100d1c714baabb7149f07e25dee323e780757dfa8016faa7c0626222c365f8f2f6687d1ded234f799cc50d1cd26b4cfa4045917056fc79c3b88b2b1908e372df66dac8734631648349bc37fa34b25fff3b0747b6bc16b94e3e5895e4bbd93d478a6c1f75e4fa30faa922049ed4c50f12f4b312a8974d0fed8d44255dcb2bf0febe47fb3fb8ed9903b5ba4ca18e3cc6762cfa1eaf04dfa944d496e0fe8bb7dc045451396bfaba5485d9d5f391a954c3714253ccd9b19964d4280680720783036b3abfaf2884583ea5bdbcf69d08897ab288314635abb4c2964b71ad9291feb5b61f80e9b0cc07f912a8e5598d5548defe0eea1c448573710aacddb152f93c7c6fd3f7e4ed9f7442a6b900f23c3c544ce5c9ba5f5e92aafd11c9ff5f79c08b9d045fef07970625f62e2f4334a4d664caf7:74cb028dc6b75b37a1daea1cf88465db83a0093fecb22d99ba855e9ab59d05cb22c87d0b09df7c116213baa8f189b2703ff953cd202eb9dea3976ee88f5fa70385890db4e2fbce093dde5a80bf8fe09a984b83a49b7ccb5d4b06cdafddd382e4b8a8a50530e82c200612c9d7d8a089bc8aa845c3cfcc38a6195d21c2618c3dba2b570920eccfcd236f17f08d814268f882242ddf0702da8785f407aa8f86fecfa903c48da83f839777eb6b4a2bbf5df7a4da53475af1ffe44b5fe0072b8fbf3d26e6d89ea67d8ac8459492890ada657eb3dc2492b88de175b4bba1a508064d619674aaae2af09d31a5c27c8d5d5a29b03779f4286b8966ce407e6ff692fb942520a9938d69cc70acb06b014b6dfc19834206cf1ac6c448ae6f078025b55f3d827201268a92add9ad178ef76a2989fedc6e39f4ebb9f96c9b8352694fa54fa022019c0ec0012d0d769e2367803f925f175f9fb9cbec4a0c9c1e2c83ea57e6a92a17f555cab934271e72c8cc3215fcb87c20539bf14277b1bfbd6e5880ef953fc75f23c0dd4fcc1e0be340af947de02e877fd5c77dd1df7b414b5c0b40c74956a545a115b0c6993ab233b7e72c822b6b3381bb1fc10875bffe3e2ed1190fa33fc15da083794fcc2c5bf5a07909063cb289a08a2c8a33d343842c2d6a3cfa2a16ca2eafcab7ea100d1c714baabb7149f07e25dee323e780757dfa8016faa7c0626222c365f8f2f6687d1ded234f799cc50d1cd26b4cfa4045917056fc79c3b88b2b1908e372df66dac8734631648349bc37fa34b25fff3b0747b6bc16b94e3e5895e4bbd93d478a6c1f75e4fa30faa922049ed4c50f12f4b312a8974d0fed8d44255dcb2bf0febe47fb3fb8ed9903b5ba4ca18e3cc6762cfa1eaf04dfa944d496e0fe8bb7dc045451396bfaba5485d9d5f391a954c3714253ccd9b19964d4280680720783036b3abfaf2884583ea5bdbcf69d08897ab288314635abb4c2964b71ad9291feb5b61f80e9b0cc07f912a8e5598d5548defe0eea1c448573710aacddb152f93c7c6fd3f7e4ed9f7442a6b900f23c3c544ce5c9ba5f5e92aafd11c9ff5f79c08b9d045fef07970625f62e2f4334a4d664caf7: +628563aa3ee2fc611bcff78bfb2a75e9fd8780e87a939499a61beaa6a4b71913da20616ee4a41c2ebfdc50ab54953b6d387b06c6def75796b08809565c6cf805:da20616ee4a41c2ebfdc50ab54953b6d387b06c6def75796b08809565c6cf805:056fb954fbe6a6014fadac1e1a9f56cc08af37348ebaf6920683384efa47626ccddfead2d5e9e8cfff45f7ac63de63f69d12848ce3c0ef1f530ade430f0afd5d8ecfd9ffd60a79746a2c5beedd3e67249982f8b6092ee2d34047af88a81feab5d52b47d5b3f76c2041725f6f813293050aaa834b01a3a58f69aa4a8ca61f5b746f600f3d452c6282ffdca4429b9338967ba3a7266690aec75ebfbf7be98d999b03eddc7292581b0d69e30a0351a151db70412b0bfd43d3baa9d456cb3e0b4fc19cb09e6cadcb6d3f3be5137cc7a8d3219ec2036ec670ed7ec523b1b1c687b5465307882fe38d7472d0ba87a471868309d2f773ff24c87d39c16b708a4ed9af43f74c8d85cfe8ab5406907e941a14970e209c29ff7ed8a2f935ae41709f270d0d08555ef7af2edfe40df399223c785a43e7f3691589e2ea4c036f11d03d7d1eea14f620035325cf2b33baf386393e8a972a7af6cd9b8543b32e2533d1fcc3177fd96d1e13bf8b68deb222f94497265d3ccb345751bd5b669078081998d608ca5fdc134839d4ed2bebb2952fea5a39c6f033c1558f698ce4946e4f6c08af874f27357f870ebeeb2199976ffaefac951f8e17fe7d0821e1b92a90aa4e9defd3fafda052a444476db1ce38a9e176e841189abd8fecde0fbc5cb55f511f5fde07ea97deb39b7aa8dc84a3946a6cf926d39b95c11af9d64d98b807f4704d0a2bda97dad9881ada1bf6636366e60a522b4821047861c7aae2146a02eef6b25d51371a0f17d24bc187dcdd05d541c2f72201427915a3928cd378689103ac50b33f87a47e8cdfa687a5f0af8a56731dabe662f4f2836de0ba8fafd86a3854bca012d7088a00b9854c2d3c708ddf58faa355a89afc2c80f3f5336da01d72a2771a055813fb35330f7d2e01b1d12daa95ed55d3bdc5df7739cbc3ca097a41b6b2bd7f0ff9dd1d8658983ba3ff7920c15f292a1ef9fcada1c607ecb45d3a73c9ffd42f3e16022fdfe12744926395f74fb3111793fa9281821a66a01d:c9a6aaa9b4e1cce1b58445725f61f552c8fb45831f03482798f01f663e9983db1a82fd33aba3eccb96226426d50ae17cc51274ce18a38860f40b2f82361b5c03056fb954fbe6a6014fadac1e1a9f56cc08af37348ebaf6920683384efa47626ccddfead2d5e9e8cfff45f7ac63de63f69d12848ce3c0ef1f530ade430f0afd5d8ecfd9ffd60a79746a2c5beedd3e67249982f8b6092ee2d34047af88a81feab5d52b47d5b3f76c2041725f6f813293050aaa834b01a3a58f69aa4a8ca61f5b746f600f3d452c6282ffdca4429b9338967ba3a7266690aec75ebfbf7be98d999b03eddc7292581b0d69e30a0351a151db70412b0bfd43d3baa9d456cb3e0b4fc19cb09e6cadcb6d3f3be5137cc7a8d3219ec2036ec670ed7ec523b1b1c687b5465307882fe38d7472d0ba87a471868309d2f773ff24c87d39c16b708a4ed9af43f74c8d85cfe8ab5406907e941a14970e209c29ff7ed8a2f935ae41709f270d0d08555ef7af2edfe40df399223c785a43e7f3691589e2ea4c036f11d03d7d1eea14f620035325cf2b33baf386393e8a972a7af6cd9b8543b32e2533d1fcc3177fd96d1e13bf8b68deb222f94497265d3ccb345751bd5b669078081998d608ca5fdc134839d4ed2bebb2952fea5a39c6f033c1558f698ce4946e4f6c08af874f27357f870ebeeb2199976ffaefac951f8e17fe7d0821e1b92a90aa4e9defd3fafda052a444476db1ce38a9e176e841189abd8fecde0fbc5cb55f511f5fde07ea97deb39b7aa8dc84a3946a6cf926d39b95c11af9d64d98b807f4704d0a2bda97dad9881ada1bf6636366e60a522b4821047861c7aae2146a02eef6b25d51371a0f17d24bc187dcdd05d541c2f72201427915a3928cd378689103ac50b33f87a47e8cdfa687a5f0af8a56731dabe662f4f2836de0ba8fafd86a3854bca012d7088a00b9854c2d3c708ddf58faa355a89afc2c80f3f5336da01d72a2771a055813fb35330f7d2e01b1d12daa95ed55d3bdc5df7739cbc3ca097a41b6b2bd7f0ff9dd1d8658983ba3ff7920c15f292a1ef9fcada1c607ecb45d3a73c9ffd42f3e16022fdfe12744926395f74fb3111793fa9281821a66a01d: +9141f79ed30bf600611a13f367b40396f2ec839c5612bbf1e6e497f83954bc88f14eda962640becb66c4d1f1a021110251917b8b1d34828298d32145baf6e5d9:f14eda962640becb66c4d1f1a021110251917b8b1d34828298d32145baf6e5d9:8fecaa7ae9a3d4a4851a66362b366e167b9f4300fdab205654751987f085de61bec9344aa86f5e5c6477514c2804ced7ac0cd0628529a3a1599236ed67bebe1f2e95aa151fe0f3b3011a1d4be9901cafab2f1891904d4bff0128c1d35ececb322b3cc01dacc5ae3dca6914a7d34da8c9657b950f89d1d6aec3299bb690111071fa87282774943d96a4ab7c3d6de7d1bf119363068cc82d45e4b76454c608bc3566b7f9b385cc7eb38ee429afc2da99669fc5c1be82161a1b0c33f7ba9ad4419d2062971901db003bfa23c44714995cb06bfa966e5023aa9346fd375ae2a1e84084314df3f08ce20800c2c2adfbb81366f6b104243d62d5041e7273433f17581bf93f4c6146fa966f638ab07ea16694a7ce305cc609a6e10623ff7f6c7916b6e4dbdebb7b52eca7f0d5187ff664d7c370ed22886aa2671329d928e0a3bea3b4711a128b9aab90266f8651d220b9cc1cbf5b1ce7265931803690d3291c01ead4dbc3329a97e85c4fe1d356608cc9e60b05bc14838a8608279a0061de28ff7b8e81f59c8a8c5523924c4c485e6ea80ac81750bb0e419efc7858cd4af50c8b8c80650facab4d8258f9cafa0310a007cccbc4185c82fd146df1d811879da3650d5716f1004b71d2c7f2bd6503c354589f8602c950a1f5139f811460752880a341116630e4ff84948e74a9eb350d64d8293002200233f209b17d78897c7ce6ce29e29f82d4ad6c61eb79f5739cb668b21a745555c96e19526845e82c6ed2b1c6bdd6364b8fc79ba9a32dbd3f8b975eb923623958ae0daa4ffa139217c00e021f937e9b791c37991a35e5231a1914c045a787432f97b8e2063db105e14da979c1c4cba785210eb02011334b230cfb6831998ccce25386f4f3ba0dce2006e9c3940b4d5a56aaccdcab02718689816360f18852fd1998a99fce9a04da3f5e23af94c6e8a5badfd39304b9e2a376a1f9bac09a85bd042476e26b58ec73f1236d41ab4b4e7a54def9d66a38f8e546de7b388e1e7d6681e5e2a096f160:cf202d7f2f9ed117f429502b2a5aff54a7f751d2171515a4d203753446df0ebac86984c88bd42bd1fb8dcb408776722a38f32cceb25f32a25d7393f138eedf0a8fecaa7ae9a3d4a4851a66362b366e167b9f4300fdab205654751987f085de61bec9344aa86f5e5c6477514c2804ced7ac0cd0628529a3a1599236ed67bebe1f2e95aa151fe0f3b3011a1d4be9901cafab2f1891904d4bff0128c1d35ececb322b3cc01dacc5ae3dca6914a7d34da8c9657b950f89d1d6aec3299bb690111071fa87282774943d96a4ab7c3d6de7d1bf119363068cc82d45e4b76454c608bc3566b7f9b385cc7eb38ee429afc2da99669fc5c1be82161a1b0c33f7ba9ad4419d2062971901db003bfa23c44714995cb06bfa966e5023aa9346fd375ae2a1e84084314df3f08ce20800c2c2adfbb81366f6b104243d62d5041e7273433f17581bf93f4c6146fa966f638ab07ea16694a7ce305cc609a6e10623ff7f6c7916b6e4dbdebb7b52eca7f0d5187ff664d7c370ed22886aa2671329d928e0a3bea3b4711a128b9aab90266f8651d220b9cc1cbf5b1ce7265931803690d3291c01ead4dbc3329a97e85c4fe1d356608cc9e60b05bc14838a8608279a0061de28ff7b8e81f59c8a8c5523924c4c485e6ea80ac81750bb0e419efc7858cd4af50c8b8c80650facab4d8258f9cafa0310a007cccbc4185c82fd146df1d811879da3650d5716f1004b71d2c7f2bd6503c354589f8602c950a1f5139f811460752880a341116630e4ff84948e74a9eb350d64d8293002200233f209b17d78897c7ce6ce29e29f82d4ad6c61eb79f5739cb668b21a745555c96e19526845e82c6ed2b1c6bdd6364b8fc79ba9a32dbd3f8b975eb923623958ae0daa4ffa139217c00e021f937e9b791c37991a35e5231a1914c045a787432f97b8e2063db105e14da979c1c4cba785210eb02011334b230cfb6831998ccce25386f4f3ba0dce2006e9c3940b4d5a56aaccdcab02718689816360f18852fd1998a99fce9a04da3f5e23af94c6e8a5badfd39304b9e2a376a1f9bac09a85bd042476e26b58ec73f1236d41ab4b4e7a54def9d66a38f8e546de7b388e1e7d6681e5e2a096f160: +695c960bbb0dd57ffa36151c85de735154fe5ad5f5fc77d005a0a32011deb30c34125e4e21f789ed0e1180c1f6369c721dcae9859b6f7b04f957e51001eede8a:34125e4e21f789ed0e1180c1f6369c721dcae9859b6f7b04f957e51001eede8a:3706696c7a906690d0d3b71e7e211c7b067168f3a8f1ed984a0a5e6078597662e4e7889d52db0f78e0d5ef0e5f7a0a0f4263b6848b0725caa4b1cea6987409511c8e5e982d3f5b82bb56a4a7947121937f8e105c5a14b53e6c37cc716b1eba922421828b046f6856c44fabf13a7516c62a5ff98568450cee78b140335047bf1ca77e1549a894feeb078045e4641832253bf695485452ec369065a60029a6c9077a379db20485ea2edb6c969547bb2653289bc6e81ffcb84bdbf773ddea4b3750e9a72395d117f644b0e22061d4f3bb7c5b612e4b70395e0779516b46659116902fd0fbcd2340eea45e9c23db2564a5e11dc79e8f4b332a443ec35aad9604fe791252088295e84f65a307312550d9ebf61f367e4a0f2b5623e53ef6bc132825fc24ebee4ebf338cbfb5df69b32d030d447c44f313ba96fe07bbfe5b0166eaecbc619bb6b2e5924010ba3ec150ff6a69fec4ded9c442f98c15e77f319b4843b3b748b5d26089a76c2b834ff93c413e04ca9550cd211ce2d6a583d782575066db6dd33e8d5e8374355d068a5eb96f8b3da8dddfb5baf5c596daaf556a8f2cb5781e5042327f92ae0621eae088b5f013592e77873a81d7e068d7b8337db9f109a835b475e5caf7cea5af3b4ad6d90baaf1c73655ec676747fcdd41775b4fbe3924c3f41d8a737528d12d6156653a22358c6821426b2c0a33e1634c62c7c8385649bc233e7daf9439f09db9bd11ea01e28b77ecbbc4590e29fdcf0fdde152f6478132fe4c3a5b45a7305af6e381cadd72496e66bbb866cea47f7e7d7e63341600af3f49ce9c9e4e37394df5df71dc10cd391fdcb8a193dc98fc19059fa3ac230ec5476bf94d85556ace6e1ba32421bf59dcbe05c5e15d34c6644e27d0a02be97fa8387ee03706f22a8f4b3b4040ad7d3f8a86971a20a09ec81b7696d834c526b8e51cb97d27643f9abf5e29ffd0333f95de15d110c2064ca49467c14ef227f4babf1a55e7b1cda0429cff256be31cf116719a81b9c5fb75fdf64e:4af41c554d990812686c329a875c41ee24b4a7fd7b3d4f8c8d5275f2e7cb242b258b5858a466de595ce2a2177e351c7f08c7fc4e0bf97ec5fb2dcb8252d2c90a3706696c7a906690d0d3b71e7e211c7b067168f3a8f1ed984a0a5e6078597662e4e7889d52db0f78e0d5ef0e5f7a0a0f4263b6848b0725caa4b1cea6987409511c8e5e982d3f5b82bb56a4a7947121937f8e105c5a14b53e6c37cc716b1eba922421828b046f6856c44fabf13a7516c62a5ff98568450cee78b140335047bf1ca77e1549a894feeb078045e4641832253bf695485452ec369065a60029a6c9077a379db20485ea2edb6c969547bb2653289bc6e81ffcb84bdbf773ddea4b3750e9a72395d117f644b0e22061d4f3bb7c5b612e4b70395e0779516b46659116902fd0fbcd2340eea45e9c23db2564a5e11dc79e8f4b332a443ec35aad9604fe791252088295e84f65a307312550d9ebf61f367e4a0f2b5623e53ef6bc132825fc24ebee4ebf338cbfb5df69b32d030d447c44f313ba96fe07bbfe5b0166eaecbc619bb6b2e5924010ba3ec150ff6a69fec4ded9c442f98c15e77f319b4843b3b748b5d26089a76c2b834ff93c413e04ca9550cd211ce2d6a583d782575066db6dd33e8d5e8374355d068a5eb96f8b3da8dddfb5baf5c596daaf556a8f2cb5781e5042327f92ae0621eae088b5f013592e77873a81d7e068d7b8337db9f109a835b475e5caf7cea5af3b4ad6d90baaf1c73655ec676747fcdd41775b4fbe3924c3f41d8a737528d12d6156653a22358c6821426b2c0a33e1634c62c7c8385649bc233e7daf9439f09db9bd11ea01e28b77ecbbc4590e29fdcf0fdde152f6478132fe4c3a5b45a7305af6e381cadd72496e66bbb866cea47f7e7d7e63341600af3f49ce9c9e4e37394df5df71dc10cd391fdcb8a193dc98fc19059fa3ac230ec5476bf94d85556ace6e1ba32421bf59dcbe05c5e15d34c6644e27d0a02be97fa8387ee03706f22a8f4b3b4040ad7d3f8a86971a20a09ec81b7696d834c526b8e51cb97d27643f9abf5e29ffd0333f95de15d110c2064ca49467c14ef227f4babf1a55e7b1cda0429cff256be31cf116719a81b9c5fb75fdf64e: +25cb17fc33d2bf8384ae4df20c1fad5c35fd765affde04b5256d4de01ca8de14b86ca312fe598520c64be5c72f5b23816507f69e070f828e02d2afcfe11bfa01:b86ca312fe598520c64be5c72f5b23816507f69e070f828e02d2afcfe11bfa01:4b4a71cbf8cbaf57a77d4ea188a6f964840f0d714a5f38a095a13b4e571297a88b792417d16184427f90e043dd8a55b7f1c13e00dfa60516445cbe77068c79c8c35ebeac330c33f1121d05731a8f5132d6480073274641195a75202116fff1c318817178fdd768bbdf105fa069c7a3d143fdf5d17bfad7c0624e5292068fd7bb6d303b4a27cb20a4e61875076787d19fa6f729c94dc0ba9b8c0bfd9866da5cb2e7a2cd2edbdc95ac349e5e5c2172e5a4cf7bd90cabe2c6e2245980bd72d0f6f5479881e8c4c354f68aa72841d0c73b986ba51021203161026ee3d729ddf1a049ffe9eb25439802f03011d144e50b02bd4aca5e5506d32fcf69e32f542544798f4e87f72bdf2433b1ff3259292e1d90812cffd79f6a543270baf24a3c39dd3598e1c661612922522f387d51597692f314c4d5ac4bf1883a614636336a5544d59ff41d1e0dbcf8e6627e7c8085646322dfc20c332cbdf35370d47dcabb802e17ca84780eec661c904d5bfbc240ad6a14a7533f71a27500c61dd3e473983887a86835187abb0df08fa62cda69dce86e21fa5ae954c22eddb60ee3131504a69b50486a17767091883760638a29c38030e1e05fdb28e158633010385a620613cc10d5a5f350955f4a347c65edddb7e25159da8dcc2655928ad6f6d8c4c1abb817d7fef3bae5de0402eddee7b51521ce280a66b796140f56af9bc20e465875ce2628a8a10477ce9b2eacc7d86f88272457bfd443e712526996254380f0135227e9fc151c8695e9cc64d272b256ab95c9a9f568e93716e0e53d29882e3ce74261257a02cd497c37d764d90f7fd478a17a890a8b2ea61ab81f6869b120a2f6484a88c151953391eca445015377b3a5dffe4cfbacfb5bab2c47f654f72a9d19cbc4d29537198405e3a04b4bfe11bcdb5c1f30d9ac02f54849c57aa96f7b56636116f2bb6f2583d9af94c86aff5c137f63ce54e8f0c21b6c25c1f0472a229c90817e6162eac71ccda309a1643bd6312a5263a2efe646dffe79ebd8157a28:8ccb0dbcf7cc03e83e21c57474afd3ad8898097b972ede175acaae48e3ec17b2db06fc82776b0751c0f956fd7196f3d1c96321a6cf3d892415d8f8eeb4a141084b4a71cbf8cbaf57a77d4ea188a6f964840f0d714a5f38a095a13b4e571297a88b792417d16184427f90e043dd8a55b7f1c13e00dfa60516445cbe77068c79c8c35ebeac330c33f1121d05731a8f5132d6480073274641195a75202116fff1c318817178fdd768bbdf105fa069c7a3d143fdf5d17bfad7c0624e5292068fd7bb6d303b4a27cb20a4e61875076787d19fa6f729c94dc0ba9b8c0bfd9866da5cb2e7a2cd2edbdc95ac349e5e5c2172e5a4cf7bd90cabe2c6e2245980bd72d0f6f5479881e8c4c354f68aa72841d0c73b986ba51021203161026ee3d729ddf1a049ffe9eb25439802f03011d144e50b02bd4aca5e5506d32fcf69e32f542544798f4e87f72bdf2433b1ff3259292e1d90812cffd79f6a543270baf24a3c39dd3598e1c661612922522f387d51597692f314c4d5ac4bf1883a614636336a5544d59ff41d1e0dbcf8e6627e7c8085646322dfc20c332cbdf35370d47dcabb802e17ca84780eec661c904d5bfbc240ad6a14a7533f71a27500c61dd3e473983887a86835187abb0df08fa62cda69dce86e21fa5ae954c22eddb60ee3131504a69b50486a17767091883760638a29c38030e1e05fdb28e158633010385a620613cc10d5a5f350955f4a347c65edddb7e25159da8dcc2655928ad6f6d8c4c1abb817d7fef3bae5de0402eddee7b51521ce280a66b796140f56af9bc20e465875ce2628a8a10477ce9b2eacc7d86f88272457bfd443e712526996254380f0135227e9fc151c8695e9cc64d272b256ab95c9a9f568e93716e0e53d29882e3ce74261257a02cd497c37d764d90f7fd478a17a890a8b2ea61ab81f6869b120a2f6484a88c151953391eca445015377b3a5dffe4cfbacfb5bab2c47f654f72a9d19cbc4d29537198405e3a04b4bfe11bcdb5c1f30d9ac02f54849c57aa96f7b56636116f2bb6f2583d9af94c86aff5c137f63ce54e8f0c21b6c25c1f0472a229c90817e6162eac71ccda309a1643bd6312a5263a2efe646dffe79ebd8157a28: +49e24d1699833726b18c78ea6568401a971e1ca39dd06d7563ac8b4250d4a9f571cf05e90d301a6d9fad7f0b38ec8bb044fcfd97c849b04c003625de29be86bb:71cf05e90d301a6d9fad7f0b38ec8bb044fcfd97c849b04c003625de29be86bb:6d2605f61e1a04b6ae18c2c25ae100dd42a61e664e2db5c34d7ad1f84ac507552b741c2086c17c852babe07a91e129a506ee59edb9ce73be1b1d06d120ec36a1e94c6281054e78ceb1bdeffbcbf4f01051ed381bfc8ad1769f41e240bf6059d9704cacec666611f41e4dd438b7f50242ea86756bb1f81e5942c092129fbc6de4955d28dff35237db30e4a5036a9914c9f84dbd8ccf82ba2b1b3b5554a2b7a74cb0b2a1e1963345286e258dc8e7d56718035f95f313811cfbd852a0f8f49a29ef933e7cda7ed9c7e8b162cdba1a82262cd4df7cf8ea4b586db43dcc1e3764598e9ca46673822baa2ad87fb14b6fdb9e2032d0ca51c26c5ef3d9f79785fac2491cdbf7c399f3cd1774c1a6b1e4a67f5436d80db025f8fb6409e275bd0ed508b5e039ed2e4eec8b0f4d5be99dcafa6a1401252732a65b37c943c07ef3acbcfbb3dc06dad0a88f2f5eb551a3997ad6c6eed95edd9a0af4a288d5e43286b2ac072977c436b7c5ff7ab61c9484f257f58e010c9b6ad41581d742cd19752cde54d2b420d643654e9096a81eb9dcf804c7c2ed0e38d13a5ce39978cdd02b25350945de78feecc0c2c22ffd705c3ba8113265c7b9a7c8ddb59178bd21d7f6c31c6be2c36749ee0f9ab8bc1dcf5da5cb2d2d5962358f71f96ab3792a252a519e415351f43e7e12035b0328f28208cf4be529d299aa5c128c9d5ed575bf90c5350569eaa6f2d5521de1180309f686c97e9ad6fa1ec1dd8627ae8951581cf604b8b917c5ba434a637be1bc8b79f4acaf7795f4e51aabdb885077bc4f3c68fc3318de5823d7e0804ee995b70387950f799353682300d4e797f3cad611b4c562c8640ff2b3fe292916a970fb98c1475c1f4e27b9b33cfe0d3ad932a1ebe6a27fc3b446622954aee1683668c8bd4a3f903be5c77dfdb8e8914cedc51f65fed2d9c4d03e13a668d4c7ea5e31883e1b3db64363e2ac5cc54b54ce69c6ad52f874999b5dd2c5782f03c3d51505df536a1fe0d860d33eabed641a940089f1297dd0f57f:a0b6a2af15b6be9e951ef3f32cbd1c6702e8e017fbd315a3f2599c3f1a11865d46e78459a0d7f7be046aae293cad09137ec847e26928106d9aa35e0982b992026d2605f61e1a04b6ae18c2c25ae100dd42a61e664e2db5c34d7ad1f84ac507552b741c2086c17c852babe07a91e129a506ee59edb9ce73be1b1d06d120ec36a1e94c6281054e78ceb1bdeffbcbf4f01051ed381bfc8ad1769f41e240bf6059d9704cacec666611f41e4dd438b7f50242ea86756bb1f81e5942c092129fbc6de4955d28dff35237db30e4a5036a9914c9f84dbd8ccf82ba2b1b3b5554a2b7a74cb0b2a1e1963345286e258dc8e7d56718035f95f313811cfbd852a0f8f49a29ef933e7cda7ed9c7e8b162cdba1a82262cd4df7cf8ea4b586db43dcc1e3764598e9ca46673822baa2ad87fb14b6fdb9e2032d0ca51c26c5ef3d9f79785fac2491cdbf7c399f3cd1774c1a6b1e4a67f5436d80db025f8fb6409e275bd0ed508b5e039ed2e4eec8b0f4d5be99dcafa6a1401252732a65b37c943c07ef3acbcfbb3dc06dad0a88f2f5eb551a3997ad6c6eed95edd9a0af4a288d5e43286b2ac072977c436b7c5ff7ab61c9484f257f58e010c9b6ad41581d742cd19752cde54d2b420d643654e9096a81eb9dcf804c7c2ed0e38d13a5ce39978cdd02b25350945de78feecc0c2c22ffd705c3ba8113265c7b9a7c8ddb59178bd21d7f6c31c6be2c36749ee0f9ab8bc1dcf5da5cb2d2d5962358f71f96ab3792a252a519e415351f43e7e12035b0328f28208cf4be529d299aa5c128c9d5ed575bf90c5350569eaa6f2d5521de1180309f686c97e9ad6fa1ec1dd8627ae8951581cf604b8b917c5ba434a637be1bc8b79f4acaf7795f4e51aabdb885077bc4f3c68fc3318de5823d7e0804ee995b70387950f799353682300d4e797f3cad611b4c562c8640ff2b3fe292916a970fb98c1475c1f4e27b9b33cfe0d3ad932a1ebe6a27fc3b446622954aee1683668c8bd4a3f903be5c77dfdb8e8914cedc51f65fed2d9c4d03e13a668d4c7ea5e31883e1b3db64363e2ac5cc54b54ce69c6ad52f874999b5dd2c5782f03c3d51505df536a1fe0d860d33eabed641a940089f1297dd0f57f: +f8ff97032a34cf9999088058af56ff70b6acb2edf759e131faec8440fdecf6c45438b4e33f1c5ea112fb1bafef4059bf095a11409b64d46bfb4d25473c1c0874:5438b4e33f1c5ea112fb1bafef4059bf095a11409b64d46bfb4d25473c1c0874:dfb41fb9d53702cb2b9e3ffcad4ea602716f718a7ea33e21843e2a6c052c70c6c51485d72b53a5bb4e34e03e3e1d1a52518eb3e7f18f2a1e1caf78acb2116089bed4c617138e716a91431f2cf644a1210f6d1920d285994264d6466b0d8d2c62638044616f576edc7d0d93cb660131d4bb50875e153640123a96f15b75a5bcee46d5cc5eb1a431c59d2eaddfd5531502feb1551bf7791cd5989d17d10296d01ba3ae3e384c674526cab62a7c24c0ff677de71ca172621a28a85e01eefe07f6eef9c3ecfd7f9498ac42f46a43716f615318a3b28757c3a15f4f1c3822ae7a75c203a298258d753638cf425e15bbc46202b093b8e4f3e670fbb663db2b69c8fb0f625074d85a44d350e042bb1b74021d192997a2c27dd6c8634841d100a0344baed750a39ff5dcd9848dfcf09e5c8c47967b96556e2332ca17d8e42dd8f393a5445a372244600b3001b8fe86c45eafc6e738aa7e117b4a79fa2e6b00f464928d1856c83ecfe87dd34d158f5cb4e4f4d610f59717ec790bd3ff872040b67e8d3939e804e3b5db985a095621cbccd686c0934ece3e27ab2c6ce33fb52b111f48e4f274bdf320d0b02384c83c49e1a041bd2319109c85a06d8048a993357abfd811ac2f38059d077acbc36aa966c028903748625f92e8f79d51bda10f78522977f76ec4e885e49a46c68de09f3da8f86b71ae6423bd29deef1cc6a113eac115a6cde2ccd011fc1c0f0e3427f43c3e96fc4156edf62ddfb7b0836b888bab3c4345055a6c4178e9e22829fd8cfce39b0b8444eb26487cc9dc82606feaadaf4978694e6564f2729c1b13ab37c9072db4e9de940ee5f1d05884ae7fd9d9ec9cb7de56347600a88dea9208a63419fce29ee50055a374a8f22f9ae2be9805a9f47615aa59576b44042ff126a89824e36ad6bc58e06bb90fbeefbae5d6d7d62430f373b6296fbfcd4d6620168353583fbd3d5a292b9572517534e2fb0beef2fa98a464e59103e7a04287f15dad0fac54970e7715078d63ec26362f6fbabcddeaf7:509e9eadfe8dde7914ac20cafc0b0af22b84dd8a210a4812cd8cae39b0a272e53e02246dc8939e9226920336e140b31532d068137a34161e599a8694a95ddf01dfb41fb9d53702cb2b9e3ffcad4ea602716f718a7ea33e21843e2a6c052c70c6c51485d72b53a5bb4e34e03e3e1d1a52518eb3e7f18f2a1e1caf78acb2116089bed4c617138e716a91431f2cf644a1210f6d1920d285994264d6466b0d8d2c62638044616f576edc7d0d93cb660131d4bb50875e153640123a96f15b75a5bcee46d5cc5eb1a431c59d2eaddfd5531502feb1551bf7791cd5989d17d10296d01ba3ae3e384c674526cab62a7c24c0ff677de71ca172621a28a85e01eefe07f6eef9c3ecfd7f9498ac42f46a43716f615318a3b28757c3a15f4f1c3822ae7a75c203a298258d753638cf425e15bbc46202b093b8e4f3e670fbb663db2b69c8fb0f625074d85a44d350e042bb1b74021d192997a2c27dd6c8634841d100a0344baed750a39ff5dcd9848dfcf09e5c8c47967b96556e2332ca17d8e42dd8f393a5445a372244600b3001b8fe86c45eafc6e738aa7e117b4a79fa2e6b00f464928d1856c83ecfe87dd34d158f5cb4e4f4d610f59717ec790bd3ff872040b67e8d3939e804e3b5db985a095621cbccd686c0934ece3e27ab2c6ce33fb52b111f48e4f274bdf320d0b02384c83c49e1a041bd2319109c85a06d8048a993357abfd811ac2f38059d077acbc36aa966c028903748625f92e8f79d51bda10f78522977f76ec4e885e49a46c68de09f3da8f86b71ae6423bd29deef1cc6a113eac115a6cde2ccd011fc1c0f0e3427f43c3e96fc4156edf62ddfb7b0836b888bab3c4345055a6c4178e9e22829fd8cfce39b0b8444eb26487cc9dc82606feaadaf4978694e6564f2729c1b13ab37c9072db4e9de940ee5f1d05884ae7fd9d9ec9cb7de56347600a88dea9208a63419fce29ee50055a374a8f22f9ae2be9805a9f47615aa59576b44042ff126a89824e36ad6bc58e06bb90fbeefbae5d6d7d62430f373b6296fbfcd4d6620168353583fbd3d5a292b9572517534e2fb0beef2fa98a464e59103e7a04287f15dad0fac54970e7715078d63ec26362f6fbabcddeaf7: +2e4c39219fc92a538e48e95fbfcfef30f5a21b78940b81053bdad4602b4c9690f8eed892176620434c7f0ec53dcff39863109e7ca4d0b3c6c4b56410be01e537:f8eed892176620434c7f0ec53dcff39863109e7ca4d0b3c6c4b56410be01e537:c87d1fba9d94a6a5408980fc8083980fd2d252fae540f6eec19ed6746c29e339a1c29f6f53bc23fd6bfa438507eff5daf903403cda707b4dc5e844805d6b1ceb4afff4b232e8e69d7d271f3c067c4854f3d94f27fe325581faca79d1f02a26290ad23af71100c12c09157647ca9da43d7690ddcd94db65e000989c878b75a0ff22d2c70962594c9b0808f27846ccac8567bce5d2e3b7602809f23b59cd718a0805d108f31a632a05b8dfa5035ab9461aeba416009d74fdf9e007202856890d2cff80fa240b978a48270fcb2f473697bcba8e730a55c28761919a23be41da27ffea09e3559caaabf9519ec08e1ffa86817aa3e8874fa816e7718c5b2f344967ba1bc2819c4f045a97b40544ea61d717083ccaf11e9ddc04a3598ef181e7bef4acef45b6551b478a0d7731c4f08ce5802f78258d419017661076d7d6d2ef39e57cf9cd9397dcc5debf64ab82b66159f578316e74cd49f5ad2c6fef83cf08683b9570a946ad4903df4e96ec008e14a501fa9386bdaf2a63993c6c9bdf231fd09ea6f96ef4d4e29a3a3327cbf74ea831054e66ca86680c6ce53b66f9465d06b3fa0798bb6905ae38455934f2fb7e0ba472328989f001308671cccb566d222c72165bb3a744fb98e2210f9620680df3e3cd14a8bd94b5745c0016dda77f059f26053b64cf4523c3d429112fb6b328398bc630a2e906b95a6c5780cfdc0641be4751bebddf7724dc9c27e78d60ed0fd736d5abd88929c1795d473abd2b0320c540475728821867a409a2ff13cc44ce35e5981e9f6b87a28d4fa8b8675e503faefca7c1d7984737871fe919ac414eea265ee31f9f78f521f3f4f8d00c3fb79171f3c6a5dbf5e1ac8bf63b4c3d8d8bc121036e9e55bb702ea6c86e925ec0b984ded2c71f3bfd4932e6c41b582fd02ca59f53ce297445785cc4cac247b0b84e7fa0bcdcf79b3e4a155f9878c1f643be9c42f7a4f27260444505c1845bd53b550a31d7953cc738861f46bdf4870f3a77ace191abd63c45adb153909fb59ab5db9b:394520122bb0a564648a7a8bc8dc73636c517746a3c8a05b901e7252fef0e5023d90991e311b5382d49100e52633c70fe9c26c1450e0603e6d452299af4dae07c87d1fba9d94a6a5408980fc8083980fd2d252fae540f6eec19ed6746c29e339a1c29f6f53bc23fd6bfa438507eff5daf903403cda707b4dc5e844805d6b1ceb4afff4b232e8e69d7d271f3c067c4854f3d94f27fe325581faca79d1f02a26290ad23af71100c12c09157647ca9da43d7690ddcd94db65e000989c878b75a0ff22d2c70962594c9b0808f27846ccac8567bce5d2e3b7602809f23b59cd718a0805d108f31a632a05b8dfa5035ab9461aeba416009d74fdf9e007202856890d2cff80fa240b978a48270fcb2f473697bcba8e730a55c28761919a23be41da27ffea09e3559caaabf9519ec08e1ffa86817aa3e8874fa816e7718c5b2f344967ba1bc2819c4f045a97b40544ea61d717083ccaf11e9ddc04a3598ef181e7bef4acef45b6551b478a0d7731c4f08ce5802f78258d419017661076d7d6d2ef39e57cf9cd9397dcc5debf64ab82b66159f578316e74cd49f5ad2c6fef83cf08683b9570a946ad4903df4e96ec008e14a501fa9386bdaf2a63993c6c9bdf231fd09ea6f96ef4d4e29a3a3327cbf74ea831054e66ca86680c6ce53b66f9465d06b3fa0798bb6905ae38455934f2fb7e0ba472328989f001308671cccb566d222c72165bb3a744fb98e2210f9620680df3e3cd14a8bd94b5745c0016dda77f059f26053b64cf4523c3d429112fb6b328398bc630a2e906b95a6c5780cfdc0641be4751bebddf7724dc9c27e78d60ed0fd736d5abd88929c1795d473abd2b0320c540475728821867a409a2ff13cc44ce35e5981e9f6b87a28d4fa8b8675e503faefca7c1d7984737871fe919ac414eea265ee31f9f78f521f3f4f8d00c3fb79171f3c6a5dbf5e1ac8bf63b4c3d8d8bc121036e9e55bb702ea6c86e925ec0b984ded2c71f3bfd4932e6c41b582fd02ca59f53ce297445785cc4cac247b0b84e7fa0bcdcf79b3e4a155f9878c1f643be9c42f7a4f27260444505c1845bd53b550a31d7953cc738861f46bdf4870f3a77ace191abd63c45adb153909fb59ab5db9b: +f092e6be8d2d9ad069a3e2b976d244e34c15c28c48d32f5560a54185d1501502cfeb3e74e4b5c8356a81757b8f1be4b429fc18fcaf497cbf8d8bc0480ff978f9:cfeb3e74e4b5c8356a81757b8f1be4b429fc18fcaf497cbf8d8bc0480ff978f9:2c255fb25d45b086c071e03e525b4d728578fbb6b0c60da941e6bf2a4898b2d5b6988c53302785ab7a3bc4bb2c205acd27d6a4cbdd1a0c0889ded784264cb7c02889c5c7113fc90bbbcd31ff001432c053f971073cf6712f667fce4698776b98cc5444c692abd1288198be5ad5674609f7e139ad1b9ccb943f8dfd9d12c54ecee278341b2ee1277991ca62cd3bfe128d1392964e9588e2f97c321704a3de106188c5eb335aa5a19acc9067b4a94129b9d1a6167c4bbfb56fb97684cbbd720c86869e0020ab0776cdc9954feba862124b073fba8de9ea9a38eacfa003ae4f1cdcbf15c32fb6b970c73115ddffcd4fa3b71846110edec257fcaed6113604f7192572577264b9905ca6aed8daec138403ca41aa954278a5720b267b90ca163a9bdf447eade8deb769a3b49237a73516977c28734555dd234ca7de4999261bc7960f536ba8a35ad3d02c75f1c2bea0a0612e7d49c40397dd6af5ff58bae6a64b6a77e981f92d159e0b2bd205ab157052f47017a3e18aec944d0465ee0017e96148a6129f74d3ccb489fea13a15a9b9aced58c6ee0e6e84e05fdadfae07b334a98fc37f7e511cd5a44e9c74e478d349e30e29aeb46a4df01e4307fe65e1394a758f6ada2fb120225ccd50a49013e6c9f175af90f3fc8c57e7a6a969a916c3f1aacc22f3e01a070cc48e6fd878e2bd073df9ee6f059b98568404fc7eae7d4bf6fa16c0c803c6be84e8b79c67affc8c88cabdeebc1134bb2386e22ba4d2e9e0f3e1ab3a0dac7c80ddeed773cda0c41dc9defa67fea37769cb4a1e1522d7e0b3d7c4638bcd983153d478be5ecf2b6ab1b40124e4222b8caa4647bd50d74d203943ab20938d5f27d908a673674046ce2ef18e858b0a01a7e7530ded0f8cc89ef09b73ca597cf73afbc9a271a4d23c92fe591883c440109c4ef416670b7f2c5905b77f65f56d09d40250356f9b1dbcaf1ee2c0b63696f84d68ddbea160085151a9526274d7b846cceb6c4348098484de3bb723ae5e85276df49f5634130ff905754f:63cd4c0ba3be9397cc0f3c1af348ec4b8a91e42fee675da1d05900b9a86c138f9174eb996bbdf31c4295e0c578ac0f9d537641a2afd5dff93a39c5cd9d3c480b2c255fb25d45b086c071e03e525b4d728578fbb6b0c60da941e6bf2a4898b2d5b6988c53302785ab7a3bc4bb2c205acd27d6a4cbdd1a0c0889ded784264cb7c02889c5c7113fc90bbbcd31ff001432c053f971073cf6712f667fce4698776b98cc5444c692abd1288198be5ad5674609f7e139ad1b9ccb943f8dfd9d12c54ecee278341b2ee1277991ca62cd3bfe128d1392964e9588e2f97c321704a3de106188c5eb335aa5a19acc9067b4a94129b9d1a6167c4bbfb56fb97684cbbd720c86869e0020ab0776cdc9954feba862124b073fba8de9ea9a38eacfa003ae4f1cdcbf15c32fb6b970c73115ddffcd4fa3b71846110edec257fcaed6113604f7192572577264b9905ca6aed8daec138403ca41aa954278a5720b267b90ca163a9bdf447eade8deb769a3b49237a73516977c28734555dd234ca7de4999261bc7960f536ba8a35ad3d02c75f1c2bea0a0612e7d49c40397dd6af5ff58bae6a64b6a77e981f92d159e0b2bd205ab157052f47017a3e18aec944d0465ee0017e96148a6129f74d3ccb489fea13a15a9b9aced58c6ee0e6e84e05fdadfae07b334a98fc37f7e511cd5a44e9c74e478d349e30e29aeb46a4df01e4307fe65e1394a758f6ada2fb120225ccd50a49013e6c9f175af90f3fc8c57e7a6a969a916c3f1aacc22f3e01a070cc48e6fd878e2bd073df9ee6f059b98568404fc7eae7d4bf6fa16c0c803c6be84e8b79c67affc8c88cabdeebc1134bb2386e22ba4d2e9e0f3e1ab3a0dac7c80ddeed773cda0c41dc9defa67fea37769cb4a1e1522d7e0b3d7c4638bcd983153d478be5ecf2b6ab1b40124e4222b8caa4647bd50d74d203943ab20938d5f27d908a673674046ce2ef18e858b0a01a7e7530ded0f8cc89ef09b73ca597cf73afbc9a271a4d23c92fe591883c440109c4ef416670b7f2c5905b77f65f56d09d40250356f9b1dbcaf1ee2c0b63696f84d68ddbea160085151a9526274d7b846cceb6c4348098484de3bb723ae5e85276df49f5634130ff905754f: +01a247943afe83f036b6b60f23d97774fd23208edc31cf3d8820e9dc636611038c97a58be0e847c48a6a3987cfe250a8d7b07d97f961f6b7b79e7d8042b8bd7b:8c97a58be0e847c48a6a3987cfe250a8d7b07d97f961f6b7b79e7d8042b8bd7b:08d81495da77f407255cc41a818eefa727e2c47ae411f4b541f01f811d906d55fb1e3c9c484df30565364de9dcb9fea0af66112fe75fd11ae81d2641b547589f8b974a97e7976ed692aad640edd288bd863d11c4ca9836f9d7c115c3d98830d64247cb6f8fb603c6981133552a3204041961bdd83e2f9deba770c0394f9b602a453551074921a3de28321369d7f8ca640c45109e8f522c97ed9f35b9277a350e295931b42e0135e94a92fed363d6cae392f7c45199327e24b4cfa5898ab599ae7bd50bd3a00c0d007e95faf8f2ae103802ca7e53b279184d06905f5748ca8be1f72e668cb83283dd00406491f8b9b4e5a9d4a5438b2fa4371e0b05686f87575baa796e302f08ffc425662750a33a0c9cfaa4b4d7041f9264fed7be4f9fde2cac68a2158236f6ac43047e911f4c4e8bc663fdd50517dfaa8fbcd219dd7a0e9369f43d0dd25b4f0cf930f20b7b7c6db9d5be0c6e1960941a3e04d141c03e5961aa33e9024477d533c995378796bf2292ade922695b14569fc339b3d9085c63fc6e5bef4d990c80333a6b57af478f938e3ee738b1d129bd976afe686128bcac08ccbeb0349b9b537313bc7bf591c65d4a7123ad30bdbe1486b428084748b6507f6f5ef67c26ca862cf726aac140b861ae0dc74bb3c0b489789f17145e9a855a3e2b5daac418d8353733239ef69c7b565b5303eb87bd7f649abf40a2f135a29ed27e3be4c12cd6ddd2e5418a99974383663f5849bf3ce5532bf64a80aa521191d25390bc19a45eed1d3feca1d9fcc0db031bfb48e450be3d4593356d5ba0f31047b457745f21e32ebea3ca6c35f05d78d8c31640b0fecb9401165675c7f9cbb19bc4b5677c2ccedc4e7aafb84184c19199aca0db21cf5067dc3af769bcc629355ff7257a9efd71a6a92d130d35abee6e70605b5cab93c028fac3aa2344ba861ac1e8ce9a4b070c3df740d28c5ece0f1bc31c2d7d1e5ecc76104480939133a18660e4a3e4846b2517be3b8e7afafe078391d8aa8e5c30137e85d94d64a279fbee:ed2ced1a4fddb3442a637348179a6a5beedcb44c8e988ca26f78936d2c8db5c516d54b8c4f08d91dd7042ab6ab26d87f230eb2b2156f3ce2994fce7c2b0f100e08d81495da77f407255cc41a818eefa727e2c47ae411f4b541f01f811d906d55fb1e3c9c484df30565364de9dcb9fea0af66112fe75fd11ae81d2641b547589f8b974a97e7976ed692aad640edd288bd863d11c4ca9836f9d7c115c3d98830d64247cb6f8fb603c6981133552a3204041961bdd83e2f9deba770c0394f9b602a453551074921a3de28321369d7f8ca640c45109e8f522c97ed9f35b9277a350e295931b42e0135e94a92fed363d6cae392f7c45199327e24b4cfa5898ab599ae7bd50bd3a00c0d007e95faf8f2ae103802ca7e53b279184d06905f5748ca8be1f72e668cb83283dd00406491f8b9b4e5a9d4a5438b2fa4371e0b05686f87575baa796e302f08ffc425662750a33a0c9cfaa4b4d7041f9264fed7be4f9fde2cac68a2158236f6ac43047e911f4c4e8bc663fdd50517dfaa8fbcd219dd7a0e9369f43d0dd25b4f0cf930f20b7b7c6db9d5be0c6e1960941a3e04d141c03e5961aa33e9024477d533c995378796bf2292ade922695b14569fc339b3d9085c63fc6e5bef4d990c80333a6b57af478f938e3ee738b1d129bd976afe686128bcac08ccbeb0349b9b537313bc7bf591c65d4a7123ad30bdbe1486b428084748b6507f6f5ef67c26ca862cf726aac140b861ae0dc74bb3c0b489789f17145e9a855a3e2b5daac418d8353733239ef69c7b565b5303eb87bd7f649abf40a2f135a29ed27e3be4c12cd6ddd2e5418a99974383663f5849bf3ce5532bf64a80aa521191d25390bc19a45eed1d3feca1d9fcc0db031bfb48e450be3d4593356d5ba0f31047b457745f21e32ebea3ca6c35f05d78d8c31640b0fecb9401165675c7f9cbb19bc4b5677c2ccedc4e7aafb84184c19199aca0db21cf5067dc3af769bcc629355ff7257a9efd71a6a92d130d35abee6e70605b5cab93c028fac3aa2344ba861ac1e8ce9a4b070c3df740d28c5ece0f1bc31c2d7d1e5ecc76104480939133a18660e4a3e4846b2517be3b8e7afafe078391d8aa8e5c30137e85d94d64a279fbee: +91fdefcdbc990d3e8eeb60170434da10831b03081f6afd0d7e12b10011e02aefc58d3e20b8d47ba455b912572dc840815e3d885fa5917d1da48408b9a9564098:c58d3e20b8d47ba455b912572dc840815e3d885fa5917d1da48408b9a9564098:5b0c1a3a95e0ba7474766c9badfae34ab860e0a6c033a22fba721127f5bbeee8e2cbde1a1dfeb18d551c95994d21e3ebc68afae685444a3a4195bc755538903acfa6715592dde256e7a1b4c363eca71ef0f3a48ae3442d50d5661b394096b7ec27bbf52953f3040cd25b78ce475527e0cc59f1ef9ae2e0590431582b2df8141499829a2c5f7bbe3598e4c96cc01ede2f43b65605b488593709c094b5a042b28555fb5227a6d156376f3ff07bd5c8bc6804d39a3282ac5970ba08aebf7542b845f6b5c238c2ce20443f7f7755d75fe4fa16b9644ca3e21d91a9a87c686115748a16c0ae4ae4e16d1c71ae600b39cd25e5633b399fee7ff2e362bed25125c6fd5c7f5ffa2da2353fd35b784a1b1b0319774758b7390c44dcc92fca4201dfe1a37569de05f0664d08b90d6e2badc21b92f9ce872142357b9615080ab7659a246ff0852adb17dfda70cf1754157b13bc032b4c5deb8e1068b4692b93165da35efc9da86acbe6f80f01bbc26f575ec5af5b050e9828afde6c3b78e733eb5a912492f765bcad731b95e3ab8896b61758bf913b9a1568f9c5b46033cf45dcc1750da2066c608dc3d343738e848dc390cd474432e991d7aa2c5b2781421efe55e36b0b42c1f49ae277480b0fc5ff685bb5a31be3a0fa44823816077037548a5c9b0e1cc6c63504a407579a3632b3c96fcd0de5ea1e4d6e87c0caf7b6cae3120db8b1f4615ce6a75a81654f390428b64c213e727eec3ae7f9f42db906f4de1fdadd34a3da2aeb12b4d9a185f4a60cb0c26745f530b481fc976a093ce24a30916af605ee94b08785193a949d569c4b7ef59603bb624360e7b408d98ca509daf5a92a6d4015bdb6f97ad4ff0cf05c8f0cd5476a934426a059f2444446e5864f089e0f0675615910662d7c1e79a6c75fa314b7ba2c643b0d37653eefe593172d1d332c8dd64492eaf104fb1957baa52049442d10b56af8eae8ff82cd8f46a0494bec2fcb9fadf10cf71a6eecd0547dafdc7adbaa4503783f943a46b4ad0e6dd7f2cab55617:510112223b33a5ab1564f7537191cd292a9dbd5a323d7add0584c1b0ad00d0ac7199c3fb758e913ff3d716c2e90dd90d4e8f59951e87ef8b78214a5175c4e6085b0c1a3a95e0ba7474766c9badfae34ab860e0a6c033a22fba721127f5bbeee8e2cbde1a1dfeb18d551c95994d21e3ebc68afae685444a3a4195bc755538903acfa6715592dde256e7a1b4c363eca71ef0f3a48ae3442d50d5661b394096b7ec27bbf52953f3040cd25b78ce475527e0cc59f1ef9ae2e0590431582b2df8141499829a2c5f7bbe3598e4c96cc01ede2f43b65605b488593709c094b5a042b28555fb5227a6d156376f3ff07bd5c8bc6804d39a3282ac5970ba08aebf7542b845f6b5c238c2ce20443f7f7755d75fe4fa16b9644ca3e21d91a9a87c686115748a16c0ae4ae4e16d1c71ae600b39cd25e5633b399fee7ff2e362bed25125c6fd5c7f5ffa2da2353fd35b784a1b1b0319774758b7390c44dcc92fca4201dfe1a37569de05f0664d08b90d6e2badc21b92f9ce872142357b9615080ab7659a246ff0852adb17dfda70cf1754157b13bc032b4c5deb8e1068b4692b93165da35efc9da86acbe6f80f01bbc26f575ec5af5b050e9828afde6c3b78e733eb5a912492f765bcad731b95e3ab8896b61758bf913b9a1568f9c5b46033cf45dcc1750da2066c608dc3d343738e848dc390cd474432e991d7aa2c5b2781421efe55e36b0b42c1f49ae277480b0fc5ff685bb5a31be3a0fa44823816077037548a5c9b0e1cc6c63504a407579a3632b3c96fcd0de5ea1e4d6e87c0caf7b6cae3120db8b1f4615ce6a75a81654f390428b64c213e727eec3ae7f9f42db906f4de1fdadd34a3da2aeb12b4d9a185f4a60cb0c26745f530b481fc976a093ce24a30916af605ee94b08785193a949d569c4b7ef59603bb624360e7b408d98ca509daf5a92a6d4015bdb6f97ad4ff0cf05c8f0cd5476a934426a059f2444446e5864f089e0f0675615910662d7c1e79a6c75fa314b7ba2c643b0d37653eefe593172d1d332c8dd64492eaf104fb1957baa52049442d10b56af8eae8ff82cd8f46a0494bec2fcb9fadf10cf71a6eecd0547dafdc7adbaa4503783f943a46b4ad0e6dd7f2cab55617: +ef00b3c181f6327d02256751cb51c2c36c0c0a78076340548f5bc070d86d9e26db14cd32588fd741e8f42e5121cc811ad45063f28141e83c668f07d91228f049:db14cd32588fd741e8f42e5121cc811ad45063f28141e83c668f07d91228f049:7d6abec7a11af67324ce17b1d20bb40c668a219bc95df05e325d86f88795e264d454fc5fa7d9c8aafe77e90a6af6b57453d85b970b552a856ba659ab31bd8a660eb7d3587b453e5c5fc6b79472b26e8ff7dd6db6be3572548b0d754ed4d985b8d9965f88b952fc4fa3b761ccffc35354db0eb9c5a171718a8a5592870213827d3691bae7fd9c63f20503e04319b5e953579de47e3ef8e1628549503cb4f6871ba25db87347080e531a517a8b7221e6ad84dff83256d9ab9a433de871b9cb9c5044589e67206b317a5206aeba96c92fd6094071c644fe52658ded9220cf6abd50e2305a1c90fd66aacfb38eb05eaff6ca5f85f429cd57716eb87739a02b64cffa08c4f685b00310b5b4844920df215a9f24a17613aef85fec94f511dc8a4294eddcea11c08c0b399a23d916383e29adeb98c65d41c705a57f840520fa808d7fd25fdce159f7a084d062974b30132a571242baff4196246d6d757b312e9d608553d2dc53b623b2e95c7538fbc5deb62ba73776d85e5118fa1a302d4d076d99e100f0df119c33fc66cdfe6fd44d71997b78c8f7890c707346056220d1e9de88bc173cf0b76cb302877ec16af46e4c31639f54eedc16da9d9eb0ad95bda545dfc4a732b6da9814136ab1b9392a071b022473b3490557698b77e7447ac8590dcaf4f242ad3dfbc0df716cc0ea753626973df08d935d178e3312fbe2a7ba9c5093c53b9255eaca29b72578e3ba1bdfaf0c9ece21a5dff6ea421524f70fc1904e9a2cf7c518bfcc7e3673ee87ff27e1ca2ac32bcb4091cb34a82a71563ff6a6a15da0ebd5bd10256ce960f4eaa7fe35e128886050d049fec3a4ab16d5b0c107267eae1ab801ea5b91983839da1c488c12f864d7c3a77f2b6ae27d540109f68d78364bb627183bd503917547aaf3b3a1809da02577b3f03a9a3f5af48c8802e297c8bb63db6a86d3ea727a6d7148b3aa444b8d168f38c6c8f24088a49af33177a344adab2cf6e08e0cb0371ed52bdead132f77e7ae3ee5d8fb17afc0a0bb7311b9560b67:139f9cb99b995be6588cddb5051694838f9d82a60761fde304b0027ff86584bf65c73cc6d253e560f65525df04bfe146c83b42269cf3780f8bc392437894ae017d6abec7a11af67324ce17b1d20bb40c668a219bc95df05e325d86f88795e264d454fc5fa7d9c8aafe77e90a6af6b57453d85b970b552a856ba659ab31bd8a660eb7d3587b453e5c5fc6b79472b26e8ff7dd6db6be3572548b0d754ed4d985b8d9965f88b952fc4fa3b761ccffc35354db0eb9c5a171718a8a5592870213827d3691bae7fd9c63f20503e04319b5e953579de47e3ef8e1628549503cb4f6871ba25db87347080e531a517a8b7221e6ad84dff83256d9ab9a433de871b9cb9c5044589e67206b317a5206aeba96c92fd6094071c644fe52658ded9220cf6abd50e2305a1c90fd66aacfb38eb05eaff6ca5f85f429cd57716eb87739a02b64cffa08c4f685b00310b5b4844920df215a9f24a17613aef85fec94f511dc8a4294eddcea11c08c0b399a23d916383e29adeb98c65d41c705a57f840520fa808d7fd25fdce159f7a084d062974b30132a571242baff4196246d6d757b312e9d608553d2dc53b623b2e95c7538fbc5deb62ba73776d85e5118fa1a302d4d076d99e100f0df119c33fc66cdfe6fd44d71997b78c8f7890c707346056220d1e9de88bc173cf0b76cb302877ec16af46e4c31639f54eedc16da9d9eb0ad95bda545dfc4a732b6da9814136ab1b9392a071b022473b3490557698b77e7447ac8590dcaf4f242ad3dfbc0df716cc0ea753626973df08d935d178e3312fbe2a7ba9c5093c53b9255eaca29b72578e3ba1bdfaf0c9ece21a5dff6ea421524f70fc1904e9a2cf7c518bfcc7e3673ee87ff27e1ca2ac32bcb4091cb34a82a71563ff6a6a15da0ebd5bd10256ce960f4eaa7fe35e128886050d049fec3a4ab16d5b0c107267eae1ab801ea5b91983839da1c488c12f864d7c3a77f2b6ae27d540109f68d78364bb627183bd503917547aaf3b3a1809da02577b3f03a9a3f5af48c8802e297c8bb63db6a86d3ea727a6d7148b3aa444b8d168f38c6c8f24088a49af33177a344adab2cf6e08e0cb0371ed52bdead132f77e7ae3ee5d8fb17afc0a0bb7311b9560b67: +d071d8c5578d025949932aa6bf6a80b1cc412f106f91574ee24654b445ee9a979bcbf7d2212fb62cccf8b6c76803a5ea24409da6287efbb8b1f0c7b30ebdd93e:9bcbf7d2212fb62cccf8b6c76803a5ea24409da6287efbb8b1f0c7b30ebdd93e:3e8ee70e51e56ef57f6e66b3a884aa04a7b4d4599fb9b43996b393a868093512ea741a0c6a94f40ce49862d2fd1f7551f4647abd8075bc1b742ad40e29a60461301224fe8f7692b14772782b4e896b63fe05abd5ff5314f9ec8075f28d908ccaaace5e905ea7f57a491b99b3591eea54a6b7819167749d38a047620676a1a7af11f485a55b7c879e6850380858c8f45c0c1ccbd7406ed099d84a7471b9350c4ddb28470bf5bf327d5b3c22d899b4c660839e104a0622ae85c84aa9fc7f0a2c7ceb6e691c49c064b5313499683e8e03b2115eda7ddad55a49f9fbe62544f914511cfbec6b84dbde7e80909b45fb10502e2caaa72124fd9456a3872f9592707e9a4c5012daa972eaf65fabe553debe825701efef5c756bb465e966ab68dd52f3dd00a45cf6dc3f19b86bb0db4a86e4669885a074696a67d8ea2118c766ef625f8a98026f9f4a3c5cccf9846fdc90ed93ec7c1f3c7086954fa2f0a4ca96d40184aa57545527a1f965c11d843c90c5a5e08d7c11f2d561004e90574852eb5046aa1ea7b61009fd5dd7d6242a8df58a9e8e555c7f4cdc130d6901bfe6797fdc6c39beecfbbab6625b2e4fb9d8000276d4a94fc6fc1051fefff5adeb724b87090db0a2c697d056664d991fad80dc80fab700b1f1f2ee27734ebc26b2a641c32a0c911b270ac76b0da5c08914971c9112463a70709c0ddac7910016f913f6210086d7255cef11955710f651889c83621dd8a4fcd5366302d6c9b56eefcfac85c14a9478b6d718075428800760515cab5f3d4455e2b970df9fe4be8383d70483bbdd756071f53b2f9c275c7c8512d163518fe555837514c86776c947f29a77570287446b69be40c8d4abbd65ef2507249b5aec33acb7b8bd3f35bc859ba4e37bdb49cf913d93989c4438d2abcfa388cc89d78ac06270656492e7528f29bdfe8cbb9bfa9e73c1da013fc3ce2105657613ff62bb0c3bf4dee3b0d2659c726e7bcd9e97ecce9247d4600dfeaf60444ed862b00ba11e70ea88d4f0b6b539fc9f36bb2a1a9ed2b3:0c297abe0fd8ebcc6b771998755e2c6be07c812b5a80544957063170ca69432e72b60daae322958a2238cd6a462894a387eef65bf96f63f54c085687a502750e3e8ee70e51e56ef57f6e66b3a884aa04a7b4d4599fb9b43996b393a868093512ea741a0c6a94f40ce49862d2fd1f7551f4647abd8075bc1b742ad40e29a60461301224fe8f7692b14772782b4e896b63fe05abd5ff5314f9ec8075f28d908ccaaace5e905ea7f57a491b99b3591eea54a6b7819167749d38a047620676a1a7af11f485a55b7c879e6850380858c8f45c0c1ccbd7406ed099d84a7471b9350c4ddb28470bf5bf327d5b3c22d899b4c660839e104a0622ae85c84aa9fc7f0a2c7ceb6e691c49c064b5313499683e8e03b2115eda7ddad55a49f9fbe62544f914511cfbec6b84dbde7e80909b45fb10502e2caaa72124fd9456a3872f9592707e9a4c5012daa972eaf65fabe553debe825701efef5c756bb465e966ab68dd52f3dd00a45cf6dc3f19b86bb0db4a86e4669885a074696a67d8ea2118c766ef625f8a98026f9f4a3c5cccf9846fdc90ed93ec7c1f3c7086954fa2f0a4ca96d40184aa57545527a1f965c11d843c90c5a5e08d7c11f2d561004e90574852eb5046aa1ea7b61009fd5dd7d6242a8df58a9e8e555c7f4cdc130d6901bfe6797fdc6c39beecfbbab6625b2e4fb9d8000276d4a94fc6fc1051fefff5adeb724b87090db0a2c697d056664d991fad80dc80fab700b1f1f2ee27734ebc26b2a641c32a0c911b270ac76b0da5c08914971c9112463a70709c0ddac7910016f913f6210086d7255cef11955710f651889c83621dd8a4fcd5366302d6c9b56eefcfac85c14a9478b6d718075428800760515cab5f3d4455e2b970df9fe4be8383d70483bbdd756071f53b2f9c275c7c8512d163518fe555837514c86776c947f29a77570287446b69be40c8d4abbd65ef2507249b5aec33acb7b8bd3f35bc859ba4e37bdb49cf913d93989c4438d2abcfa388cc89d78ac06270656492e7528f29bdfe8cbb9bfa9e73c1da013fc3ce2105657613ff62bb0c3bf4dee3b0d2659c726e7bcd9e97ecce9247d4600dfeaf60444ed862b00ba11e70ea88d4f0b6b539fc9f36bb2a1a9ed2b3: +e9d486c29ae811b942e10d81f0a6716317b842c2c5bfdef55cc432b7fcaeb81843a52d15b9f731d737b1c4dbc32227a480963091d2c6286f482ef1e8367054e5:43a52d15b9f731d737b1c4dbc32227a480963091d2c6286f482ef1e8367054e5:14fe1ed5bbbd76cc73dc5650bda92de86326e24d2f1f6224ba8568944d6fe3442675db96f1d8498f1634ff9b6e50cba9db4eb0b0b021b2becfce4bef33c4ce0e32c8a98389eca9e059a662d6f037c54aa40c76cdeee85650f089ea56e1383ab0f5c36f6d6645ff7e87667301f944fdc2ed35b0d2c35cb2e4b45636e7498e927f5846b3e1edfbd160a4aef3320c3428496bdaaf7d3ed56ef0b7254ac597be589a70584416300c1adcfba4f22cfd4cd661e1f50f155d172fa5748d296b29cdd7eb8121483ff1d9fe953f9451c7c7a542007285ee7246bc0fdea938814029abce057a0ecb974b12d360eab6afd30797d61445ad2bac7e52bce4346315f78eb87542d59528b2f6c56d66241cb442033f643d3d2a67cb637d8da95d4fd1234b031a3e51723a1d26e6f5ca07987321ad11a90fcc1d4e2b0b896650c3a7518d565529bea806a05d447e08d2a6a3dbf1a36915b2957ca5b40e58b97ad0369735c428bd6d69bd210044b651418d98b059d90c83e46011f41c032c5655a5ef21ac2c8c2bc94be07e45426a7ae5d47b45f27cf4289ca4ddabe08a12b910207dabb34a46ab75ce69b58e7e17664bf3359a8fb68eb032c9eaa6df873829f0e0848553f732e1c3c084b32b7af75074e7bbaa4eb5d7ead7aff97580109b60f4c792f9e2a65137b0aa48175b8115d91305f4c77e2d08e7e8d7e7785c966842c2e350fed4f9e33bf6e184c550b4b06e957414edf52fa079e81973458461fbb9b7d7d34bef150357f432caac3ae9f3dc96eb5a2d123e09eda1702e1d1070177bb220c423c096ec24424385c679be02ef84d09ed102f49cad3b1fd670679a39714ff1d6e4228d8d7d0e19ed0eba132f2128d47baa569a8ecb7bd48a826282f9cfcbf60ddeceaf1d02132c8affed3a03d2340deb787cd649c51c6ecb9ff75d7a7b4ef9b15139cfea2762ab18615197a6b51f6e75dbd04573a2448094d0cdeb0fe4585883ff9b68824a04b83ec91cf84acd6a7446cb1f5ee37d5df80f17cb2bdc3f3122a8faf76ebd06cfe817:65191aa885ddab9f67271879952fc6affe41ca20eb3bcd86673161b03b532694d6dd88908eb1b1eec003cfcbe6146b4538e21df55969912a0d7d8818ad79590d14fe1ed5bbbd76cc73dc5650bda92de86326e24d2f1f6224ba8568944d6fe3442675db96f1d8498f1634ff9b6e50cba9db4eb0b0b021b2becfce4bef33c4ce0e32c8a98389eca9e059a662d6f037c54aa40c76cdeee85650f089ea56e1383ab0f5c36f6d6645ff7e87667301f944fdc2ed35b0d2c35cb2e4b45636e7498e927f5846b3e1edfbd160a4aef3320c3428496bdaaf7d3ed56ef0b7254ac597be589a70584416300c1adcfba4f22cfd4cd661e1f50f155d172fa5748d296b29cdd7eb8121483ff1d9fe953f9451c7c7a542007285ee7246bc0fdea938814029abce057a0ecb974b12d360eab6afd30797d61445ad2bac7e52bce4346315f78eb87542d59528b2f6c56d66241cb442033f643d3d2a67cb637d8da95d4fd1234b031a3e51723a1d26e6f5ca07987321ad11a90fcc1d4e2b0b896650c3a7518d565529bea806a05d447e08d2a6a3dbf1a36915b2957ca5b40e58b97ad0369735c428bd6d69bd210044b651418d98b059d90c83e46011f41c032c5655a5ef21ac2c8c2bc94be07e45426a7ae5d47b45f27cf4289ca4ddabe08a12b910207dabb34a46ab75ce69b58e7e17664bf3359a8fb68eb032c9eaa6df873829f0e0848553f732e1c3c084b32b7af75074e7bbaa4eb5d7ead7aff97580109b60f4c792f9e2a65137b0aa48175b8115d91305f4c77e2d08e7e8d7e7785c966842c2e350fed4f9e33bf6e184c550b4b06e957414edf52fa079e81973458461fbb9b7d7d34bef150357f432caac3ae9f3dc96eb5a2d123e09eda1702e1d1070177bb220c423c096ec24424385c679be02ef84d09ed102f49cad3b1fd670679a39714ff1d6e4228d8d7d0e19ed0eba132f2128d47baa569a8ecb7bd48a826282f9cfcbf60ddeceaf1d02132c8affed3a03d2340deb787cd649c51c6ecb9ff75d7a7b4ef9b15139cfea2762ab18615197a6b51f6e75dbd04573a2448094d0cdeb0fe4585883ff9b68824a04b83ec91cf84acd6a7446cb1f5ee37d5df80f17cb2bdc3f3122a8faf76ebd06cfe817: +e6fa10dbb478e1e36b35dfeb0250f63c08515070ae79b22f047e271708d64f5ce02e1f2bd8792ef483481c6d11f7c7c9dbdeecc9859432e7f279e9d173d31164:e02e1f2bd8792ef483481c6d11f7c7c9dbdeecc9859432e7f279e9d173d31164:ad3160758d8c08a661525c95280a3718874969859f1cc918e34fec008acf23b8896e8d50c3c0512331dc89780f8b10fc349c675c4cd82a5df8586b43c864448fac00b847b9c98054ab793f63c71aa5e5248e22d069bd3f852a3b8c6e2ac8ef861d90bcd984bfca87583e59e9a7468f29b808dc2fe5302a989d6f2ecde7585cd9be4e4c761c4d4b3eeaf4699f6556ef039af2b80f9407605ac397351dd85595584495baa177b08c88d2ec1fc4e32d1c0b8d7e7ac5839dfb923f09b323e78eceb7e96c0604b01a19e49c9beaf4f25ec4a84c1a08f2380eddc3a7f012184959ccd19ecbbac65eaca155cee9ecfec11e7fee058e174fc4ed7c679f2c15631d4e1527bcdb0e3bb0815ffdffc0c856bef0dc0f5c8237f7098e26bdb69e8782d1ca5111ec3c7edb425dff8032026cba3d2e081b71310db9badad1ad02f1eccc537d874cd18c6bb01221f71ee66250d94cf8ecceaa96d3c57eea2b0a8ec72429d7606488bdf19ec3bb16e50867c7937def09fc783f20a2a5ec99253d6b240df4677dd2d5277b01c5b8e5bd6c7df0874205bc8c2fffdba1314674d31c9b2c9199228e19e0421834c1657d0698286916c7e392f0abd5545b963ac1ffa99721616c23796f85c34a5c664ae81d16b216a5b0cf5bc6b5a908297285d61644128f886f38af9edd25193d7ecc77a79994278da071f54495937feef5a51957527c3eec7cb0b4e8aa7a4e856defd57dd92334151b986aa69ca69260d1e2d7b53c05677ee0d216b28d036252dd3006debe1b6574a25e6b19dfb48fa64316af8fd68d7893b397e7db5780ab27bf8726fff605d3b46d800595b4624bee302c964326034b5234d175dfdcc2ce882e65b3d93a0438f692e9695de1f24c70a79beed25415ec5aaecf3391953b2ffd453a8f0467561a4a47ee144a43fdff83df2bea5f66a722b52abe8613f20c594af0982eb3f04505a52461dd034da86c36ca16217705c04823911d72a24769517633562886f250f2cf788b8f32864a9474f57e62e57de8fdaf959a6b72287440a8:c03c470359127e9de3af0e0ed7d3b19faee0ec140b79c299e2cb6dac0a3e7e314141cc854b4596ce4c51c7b0dec8a5c8cf0936205361d5365f4bcc07c4287c07ad3160758d8c08a661525c95280a3718874969859f1cc918e34fec008acf23b8896e8d50c3c0512331dc89780f8b10fc349c675c4cd82a5df8586b43c864448fac00b847b9c98054ab793f63c71aa5e5248e22d069bd3f852a3b8c6e2ac8ef861d90bcd984bfca87583e59e9a7468f29b808dc2fe5302a989d6f2ecde7585cd9be4e4c761c4d4b3eeaf4699f6556ef039af2b80f9407605ac397351dd85595584495baa177b08c88d2ec1fc4e32d1c0b8d7e7ac5839dfb923f09b323e78eceb7e96c0604b01a19e49c9beaf4f25ec4a84c1a08f2380eddc3a7f012184959ccd19ecbbac65eaca155cee9ecfec11e7fee058e174fc4ed7c679f2c15631d4e1527bcdb0e3bb0815ffdffc0c856bef0dc0f5c8237f7098e26bdb69e8782d1ca5111ec3c7edb425dff8032026cba3d2e081b71310db9badad1ad02f1eccc537d874cd18c6bb01221f71ee66250d94cf8ecceaa96d3c57eea2b0a8ec72429d7606488bdf19ec3bb16e50867c7937def09fc783f20a2a5ec99253d6b240df4677dd2d5277b01c5b8e5bd6c7df0874205bc8c2fffdba1314674d31c9b2c9199228e19e0421834c1657d0698286916c7e392f0abd5545b963ac1ffa99721616c23796f85c34a5c664ae81d16b216a5b0cf5bc6b5a908297285d61644128f886f38af9edd25193d7ecc77a79994278da071f54495937feef5a51957527c3eec7cb0b4e8aa7a4e856defd57dd92334151b986aa69ca69260d1e2d7b53c05677ee0d216b28d036252dd3006debe1b6574a25e6b19dfb48fa64316af8fd68d7893b397e7db5780ab27bf8726fff605d3b46d800595b4624bee302c964326034b5234d175dfdcc2ce882e65b3d93a0438f692e9695de1f24c70a79beed25415ec5aaecf3391953b2ffd453a8f0467561a4a47ee144a43fdff83df2bea5f66a722b52abe8613f20c594af0982eb3f04505a52461dd034da86c36ca16217705c04823911d72a24769517633562886f250f2cf788b8f32864a9474f57e62e57de8fdaf959a6b72287440a8: +058e3680b8fcc0aa1490089c1124677f98d74b1bfb71ee8663f025f0d946cd20ec72ce0e82c6a3b21243d2f00e9e883adbc5cb63b3d936efa50c07cb929148e2:ec72ce0e82c6a3b21243d2f00e9e883adbc5cb63b3d936efa50c07cb929148e2:e63d14f5bea7a1abb8fee697746c2280dfd0622de7357226cc0742722a3229be126b083e868aeaf07d2fc97adc3342709674193ca281744e850ea15440050aec930e45d7a87b8ac8015c8967c20033a532d29591b135586ce0fdd2e668b5c864b3bde70c7e719ad241931251861933ffbfa96483ff82856748c56dc26e257d692e5134d82fc7191c110d9590d3fc751cd636b0c46f44f8803e59e2f93fa0cbe247a1a625b4bc2c7b1fdceb5a2b22591fa6137c5404dfec6a69639e3f632b5976ab9fe1c63aa3da9d52b044008f3ae44b7c364f085664323a88eb4583e87140f763782bff8819cf741a875d506c929d34bbd43007de4b18f687a758111128b1db86fc5ad2fb9fcad12c9dd28fee5ad10de0739f8efd9bff66f840b11b3f91c5e07c21452cab24242b6e32165cd1e69572bf216e860453dad2fd129c333758580bb7d0f19509745e851463d127a5f9be21fe549cae55d56b8bea80bfafdac10acd838ea8af31c007dc32bfd74082d9110a3e91e61e0357587e4ed32827ade9b6910a988c1d3b2dd22c0ee76ef35fe15e099404a45d4b2acab9123ecc45550a40faf8336b46c630a9080358ff8b8e58af0bccbd35010c1ecc12816655a5eceba95ad3f503a18ec5bece3a33f469dfe917e1c55ef1d81e5a75561e6bbd99c653a6d095b9f387911e40332f6216f956a35cf7d99a9fdd0c44c51e90a564f1c36bf3d40a7faf4ba28b1a120b3205fbac1a98569290be37c58bbd745ce0fb74835270aba2252adaec157dc42461221a2cff687b9e65ceb57c2d77700aea6320486c5b1bec9cc53e7ef9e48fcd1b7783acbe75a6be0267278812dbf3d2576cf7ad3911271acebe0f2c04602a080c8b96c120fd86fda282aa4e1c131fe97c907c15855f87755f511c037befad0f56b39f32a2133a22f3d5a9bec3443f29a694e97fe05e10fb8ef9991302b9e0d84d929a19eb03471f3a8613d39368e15883a7e4970b53cbaf2929d8de431b48b435d7533caa2e36ceab6cddb346e535e515c4b3db76de07d9855414:5734ec50a7f82e48536bdc4370cfef2e150a631dabaf89edcf0fdabe4f5839f4f5fbd8df8ec4a3acd40a8bfb963d1855ff9274dbc33165b5e6d37a239dace903e63d14f5bea7a1abb8fee697746c2280dfd0622de7357226cc0742722a3229be126b083e868aeaf07d2fc97adc3342709674193ca281744e850ea15440050aec930e45d7a87b8ac8015c8967c20033a532d29591b135586ce0fdd2e668b5c864b3bde70c7e719ad241931251861933ffbfa96483ff82856748c56dc26e257d692e5134d82fc7191c110d9590d3fc751cd636b0c46f44f8803e59e2f93fa0cbe247a1a625b4bc2c7b1fdceb5a2b22591fa6137c5404dfec6a69639e3f632b5976ab9fe1c63aa3da9d52b044008f3ae44b7c364f085664323a88eb4583e87140f763782bff8819cf741a875d506c929d34bbd43007de4b18f687a758111128b1db86fc5ad2fb9fcad12c9dd28fee5ad10de0739f8efd9bff66f840b11b3f91c5e07c21452cab24242b6e32165cd1e69572bf216e860453dad2fd129c333758580bb7d0f19509745e851463d127a5f9be21fe549cae55d56b8bea80bfafdac10acd838ea8af31c007dc32bfd74082d9110a3e91e61e0357587e4ed32827ade9b6910a988c1d3b2dd22c0ee76ef35fe15e099404a45d4b2acab9123ecc45550a40faf8336b46c630a9080358ff8b8e58af0bccbd35010c1ecc12816655a5eceba95ad3f503a18ec5bece3a33f469dfe917e1c55ef1d81e5a75561e6bbd99c653a6d095b9f387911e40332f6216f956a35cf7d99a9fdd0c44c51e90a564f1c36bf3d40a7faf4ba28b1a120b3205fbac1a98569290be37c58bbd745ce0fb74835270aba2252adaec157dc42461221a2cff687b9e65ceb57c2d77700aea6320486c5b1bec9cc53e7ef9e48fcd1b7783acbe75a6be0267278812dbf3d2576cf7ad3911271acebe0f2c04602a080c8b96c120fd86fda282aa4e1c131fe97c907c15855f87755f511c037befad0f56b39f32a2133a22f3d5a9bec3443f29a694e97fe05e10fb8ef9991302b9e0d84d929a19eb03471f3a8613d39368e15883a7e4970b53cbaf2929d8de431b48b435d7533caa2e36ceab6cddb346e535e515c4b3db76de07d9855414: +51ba3a4f3d85d1548c2f2494a3511f3b9515663d7e85370fb6150237e9bc980b7749de0210bce06d48f59b95aeb1528fd9b4e52cdde22fb8193bedd5df12817c:7749de0210bce06d48f59b95aeb1528fd9b4e52cdde22fb8193bedd5df12817c:d18d0cbfc16d0f9b67f2539ad6207cd9217ad5ed0333cddb1041e0ac2bdd920276629652b49cbc9802593ec364ea795abcd1582085f55bc66c48fd3eede618d6369617100eaeccc15f249d6eee5bb2c43c01b0623fe603ceeee49b40fb7c53fc68473673c09b1ac77ea9beb7e8530379a86d69ecd1ff11813fbb88f692f05ef1320742b4fe7e06d5ba71656646cd7500de19bb93d844536603f40bd4aeeaf0c4dbc0acfd202b286b64afb83d4a378dd45ee3c1df6b3ef16b8b1accbc04063250ec47b86ae5a71d1dab38b5eb80d663faa788f8b59a754c0f9c9f6d906252af46ab1fffed276d2388dbe70d96ba6747d1fed4fc0b55293d5f787bda0c0df46a73f4aa7d29e1c9cc85cd043e3dffe057462ca5fe5c6470e739276f8b534c0172e460f340487a569468aa5890cc14f20d67d79c661e87febac6275971c3730807ebf175e0de1049bee67c895e57b71ab8a2f3cf3641fd548d09414f5fc3026a0a35f6ba951673944941cb236f3d1976dc69077d951450e7660316988f6f2a6fbbff3b37ceaa02fd6f0273bd803185a109039c63f2519b983daf6554253bed5497c0b0bdaa0bd4a1fac90026ade3e40c554cff2ccb36990e71556708c5c4039256ffc7337e5fea11f5e90d3e4d93359179116a85c24136ca34835cd34012e4d7ddc7b721c246c73700e276dc2ff9f2770b43c8e80a17f01d32680bae228e6423a880c3fb996ab8d221bc6274ac5fa770d205fc878fba9bbd776a3d79ed77048950f36dc0aa3ccd28e4756a991904ae051b8a4b7de3a1f2ad0fb45a33d0c68225841f8eb65b6a16e95f893591e1aa73a64f0d2ee938ab69adcc8c59518bec501c39f139174bbb00699e1a0f0e0d889aae543a55e6ac56d5204c1ade1f27d82a6a95e14b2d6909dda7bfaa7f487fb61959014b78795cb4639f09f0d329feb35ccf52edc2db721914e423306889a483fee876360ee326335319070c564f3a8b953f52f41513a2260883c38dd978a248604a41bd4bfc9e84184dc9e84d2589f4afff8417824ce5adba:16fb290c913b20eb1c3d7b798249eb8459d4bee8125db2b3f1daab8af9d9a700ed798addd802dfcd297a412593cda7be9979a1f09350e86f698ac3380e341d07d18d0cbfc16d0f9b67f2539ad6207cd9217ad5ed0333cddb1041e0ac2bdd920276629652b49cbc9802593ec364ea795abcd1582085f55bc66c48fd3eede618d6369617100eaeccc15f249d6eee5bb2c43c01b0623fe603ceeee49b40fb7c53fc68473673c09b1ac77ea9beb7e8530379a86d69ecd1ff11813fbb88f692f05ef1320742b4fe7e06d5ba71656646cd7500de19bb93d844536603f40bd4aeeaf0c4dbc0acfd202b286b64afb83d4a378dd45ee3c1df6b3ef16b8b1accbc04063250ec47b86ae5a71d1dab38b5eb80d663faa788f8b59a754c0f9c9f6d906252af46ab1fffed276d2388dbe70d96ba6747d1fed4fc0b55293d5f787bda0c0df46a73f4aa7d29e1c9cc85cd043e3dffe057462ca5fe5c6470e739276f8b534c0172e460f340487a569468aa5890cc14f20d67d79c661e87febac6275971c3730807ebf175e0de1049bee67c895e57b71ab8a2f3cf3641fd548d09414f5fc3026a0a35f6ba951673944941cb236f3d1976dc69077d951450e7660316988f6f2a6fbbff3b37ceaa02fd6f0273bd803185a109039c63f2519b983daf6554253bed5497c0b0bdaa0bd4a1fac90026ade3e40c554cff2ccb36990e71556708c5c4039256ffc7337e5fea11f5e90d3e4d93359179116a85c24136ca34835cd34012e4d7ddc7b721c246c73700e276dc2ff9f2770b43c8e80a17f01d32680bae228e6423a880c3fb996ab8d221bc6274ac5fa770d205fc878fba9bbd776a3d79ed77048950f36dc0aa3ccd28e4756a991904ae051b8a4b7de3a1f2ad0fb45a33d0c68225841f8eb65b6a16e95f893591e1aa73a64f0d2ee938ab69adcc8c59518bec501c39f139174bbb00699e1a0f0e0d889aae543a55e6ac56d5204c1ade1f27d82a6a95e14b2d6909dda7bfaa7f487fb61959014b78795cb4639f09f0d329feb35ccf52edc2db721914e423306889a483fee876360ee326335319070c564f3a8b953f52f41513a2260883c38dd978a248604a41bd4bfc9e84184dc9e84d2589f4afff8417824ce5adba: +7ddec526a4971d8912a6bd43c69f92ed86442b15f42fbabbf2d17eff989931610dfeffb2762309b4734e4ce2523cf1863149f7e19a7c147ec0899e110ca9d87d:0dfeffb2762309b4734e4ce2523cf1863149f7e19a7c147ec0899e110ca9d87d:e8774a45d4d8f86dda5c08802ba2472ef3c8d36c7f383ac04612a464382e9d6c07d8d35822c53f4388f5153614fefaf46374747b9d4fd446a864769a4cade843c1eab8574319112f0179d2ea9e3c195dc068f0697462b9e07c8794870f8fb8ffc081e4586afbcdba7a4f5925e9fd9ec942d8434733c2ddd5e29bbdfc7342b92868719b544088a48eba4c82f187ddca8f474625a71cf6b7aa5f081c74f7408f53b781636e7e9d29b07fdb6d9c35e5eb382db7a31a8ba516915df8dee9e1ad3f182843683e8d1dc5d8669dbfcf09541a43c0a04613381a5b5e4e71b23c5ad09b8eaa51cb938d0c752cc3d3a10f10b42be8ee7f6bdac8078568434946bbf56da70e7d54157a6efd4846eb155278c94c3888658a7a2f8ea3bac147aa891692ae8b23f1afe71ecfdecaa6c113b5caaaa19398c7dfe73facb4155fd6bac18d5df2129e8b2907ecee151bdd147a7c3e46ea72754de32ceb066d9db1c26e80df3631292b16174cfa6f1d9c0828b849c22d29651a73e910d9275877f464ce9326c6e4ed6b07dcb3a35363c1aa6472e02c5cd855e38aabe965ace9f3f5a4f5de03008694cb90afe416c9d48688de7f75cfe243ff7f41e059310934903db568844508262c899dfa750cd6a2829824ba027aea1b6d0177726a343add4ecdc5f7e6e909ab7de615ef2807f9e7d71ce2f78acff57eba79c3f5e07c8b661c1e3027f8176d28bfef767dd68d4e5d628fec0bfe88799341f306128734fad202aafc9f11123fb3e363d10aee0db5e27a1570dfaee47e24da473b07fee59a6c93f0981dbe325cd8cc2d2ed7dc17166b267c1b110536f2636bba34751a78f7f6298182442d83c123bbee4f50c5b0facff03e7c556ed9e64ca27c4bca5ab0de0d5f9c2cbb54cc2d9473a32df999390ac2ffeed3d4cba34973dcec3fbabafc4d54cae4e7e85d4a6e8afe45cacd71e0f2e6d04b4f9d3bcf43d3fa41e998ccbed0f150d5ca1d5272932d93eca10495c68334fa3268f31de522cb12a7449ffb5cb5e8f1462cd9b51770ccaf58b1e0d82ef929:9e603b015f42871b78eb27523fbb7ce962fca32ae270e8e12dcadd25aa852b891f6fef77b59a546c9a7a7cacb55e1d32adc805ae5f61a69e6764c7c08292eb03e8774a45d4d8f86dda5c08802ba2472ef3c8d36c7f383ac04612a464382e9d6c07d8d35822c53f4388f5153614fefaf46374747b9d4fd446a864769a4cade843c1eab8574319112f0179d2ea9e3c195dc068f0697462b9e07c8794870f8fb8ffc081e4586afbcdba7a4f5925e9fd9ec942d8434733c2ddd5e29bbdfc7342b92868719b544088a48eba4c82f187ddca8f474625a71cf6b7aa5f081c74f7408f53b781636e7e9d29b07fdb6d9c35e5eb382db7a31a8ba516915df8dee9e1ad3f182843683e8d1dc5d8669dbfcf09541a43c0a04613381a5b5e4e71b23c5ad09b8eaa51cb938d0c752cc3d3a10f10b42be8ee7f6bdac8078568434946bbf56da70e7d54157a6efd4846eb155278c94c3888658a7a2f8ea3bac147aa891692ae8b23f1afe71ecfdecaa6c113b5caaaa19398c7dfe73facb4155fd6bac18d5df2129e8b2907ecee151bdd147a7c3e46ea72754de32ceb066d9db1c26e80df3631292b16174cfa6f1d9c0828b849c22d29651a73e910d9275877f464ce9326c6e4ed6b07dcb3a35363c1aa6472e02c5cd855e38aabe965ace9f3f5a4f5de03008694cb90afe416c9d48688de7f75cfe243ff7f41e059310934903db568844508262c899dfa750cd6a2829824ba027aea1b6d0177726a343add4ecdc5f7e6e909ab7de615ef2807f9e7d71ce2f78acff57eba79c3f5e07c8b661c1e3027f8176d28bfef767dd68d4e5d628fec0bfe88799341f306128734fad202aafc9f11123fb3e363d10aee0db5e27a1570dfaee47e24da473b07fee59a6c93f0981dbe325cd8cc2d2ed7dc17166b267c1b110536f2636bba34751a78f7f6298182442d83c123bbee4f50c5b0facff03e7c556ed9e64ca27c4bca5ab0de0d5f9c2cbb54cc2d9473a32df999390ac2ffeed3d4cba34973dcec3fbabafc4d54cae4e7e85d4a6e8afe45cacd71e0f2e6d04b4f9d3bcf43d3fa41e998ccbed0f150d5ca1d5272932d93eca10495c68334fa3268f31de522cb12a7449ffb5cb5e8f1462cd9b51770ccaf58b1e0d82ef929: +0b6590dd7c2f15f94a56e240169363c26732302b9d440b532723002e155d02d9cd18e032577c5576f223f3e3d8a1fa8e9a870fef09e9409faf40d7143e52fc44:cd18e032577c5576f223f3e3d8a1fa8e9a870fef09e9409faf40d7143e52fc44:71fe0fd55d5ed1206f28ee16e419fab6fa66a251fa6b0601da261e429f55b8d5ae3f3c52a17fe1ec734b810ab63aade4447039ca0ae4687c2435f561e46c5b309717ab31e0f64076b2169211572b74e18a1f4525a64fa717a5edf149758129cb04035e7e20ba4005b74809dec644504c2454a77f99b20c5374f3cee7d8c6b68b243cafb30098dce90490fdc3b92f54948f424639e19f8f2020d15513daefadd9e9b12a84761e5ecea088ad561f06209fd4423fcd003fbcd1873ea54963a2fa07c7476b1388f9015d9eac305bea5a3de194f55a17b42d599e5ce62c8b7c19e7e7096137b9d0a65e63c1a3b84538ca65369a20e8822fff5ecb57fc09b4e6845b4f24d4886971ac1ac28c77580ea5672ad14ce4441719c214546d0736cb7ad0bd9fb5b26c6d9c536bf8c857ae42577b36341d392b43323bdae7dfaa491986872a23d827c6ef8b57e7d00feae3834c466400aad1d367823984aa02d2ef492914ae1127e7551b812559378305e4fd52d8bc7e4157ecca451f43ee9f54c82153c7dbfaf7ec35238773051b4e587db136957ec571382b90590b5d1026024580966b7252d2cd3f4f1625c485ba906bff175992188978f2d6274f3a031749ba7e702f56547edc96ec267b84892880d750d7310ebf6db241253cabe4b25a977458c6ffc9e353e62adf05e6efc0fc1ebe89f527705bcc26b701285610d98aa3bf23872b6996d3de480e8d09d783c4a08cd383c9012635aa68978b5006818bbde44f2987479bcb2b711c1beeed27cf09970a164e454f710822eef555c1c7bf9f76d5254ce220c9aaa716847a249488f9cdb44c48f452ab52c40f6d03adc8bf3f197b25e3d127830e74fd81eb14f754205b3a4844c596b6e3a9936ad6fd9e80a16320b381c3ffc7b69eab54536f55abe22c91d898408e880c6dbf0fa5648d517772caa5353b25db6050d753faf198ec1d375de0fa72180a93bab03ded7716cb87505b68ac6a35e73d0fcf34457eff82178952142c7bac9dfd872a9a82f85b24b88fa42d4be0a0ca0b2c70f4c622:642d81acf38cf099a833a74f2d80b85448ec2b1a5ddc64470b213d54b7be6133689a7194f5d89792e16e5df755a4fd9ef4689ea952926e0e4ecb3bd481fd910271fe0fd55d5ed1206f28ee16e419fab6fa66a251fa6b0601da261e429f55b8d5ae3f3c52a17fe1ec734b810ab63aade4447039ca0ae4687c2435f561e46c5b309717ab31e0f64076b2169211572b74e18a1f4525a64fa717a5edf149758129cb04035e7e20ba4005b74809dec644504c2454a77f99b20c5374f3cee7d8c6b68b243cafb30098dce90490fdc3b92f54948f424639e19f8f2020d15513daefadd9e9b12a84761e5ecea088ad561f06209fd4423fcd003fbcd1873ea54963a2fa07c7476b1388f9015d9eac305bea5a3de194f55a17b42d599e5ce62c8b7c19e7e7096137b9d0a65e63c1a3b84538ca65369a20e8822fff5ecb57fc09b4e6845b4f24d4886971ac1ac28c77580ea5672ad14ce4441719c214546d0736cb7ad0bd9fb5b26c6d9c536bf8c857ae42577b36341d392b43323bdae7dfaa491986872a23d827c6ef8b57e7d00feae3834c466400aad1d367823984aa02d2ef492914ae1127e7551b812559378305e4fd52d8bc7e4157ecca451f43ee9f54c82153c7dbfaf7ec35238773051b4e587db136957ec571382b90590b5d1026024580966b7252d2cd3f4f1625c485ba906bff175992188978f2d6274f3a031749ba7e702f56547edc96ec267b84892880d750d7310ebf6db241253cabe4b25a977458c6ffc9e353e62adf05e6efc0fc1ebe89f527705bcc26b701285610d98aa3bf23872b6996d3de480e8d09d783c4a08cd383c9012635aa68978b5006818bbde44f2987479bcb2b711c1beeed27cf09970a164e454f710822eef555c1c7bf9f76d5254ce220c9aaa716847a249488f9cdb44c48f452ab52c40f6d03adc8bf3f197b25e3d127830e74fd81eb14f754205b3a4844c596b6e3a9936ad6fd9e80a16320b381c3ffc7b69eab54536f55abe22c91d898408e880c6dbf0fa5648d517772caa5353b25db6050d753faf198ec1d375de0fa72180a93bab03ded7716cb87505b68ac6a35e73d0fcf34457eff82178952142c7bac9dfd872a9a82f85b24b88fa42d4be0a0ca0b2c70f4c622: +c6d9acc5175fa2b8965c158c56ba0a5a666ad2c740cd5bb679bba9b1dc509284f5cfca211b02fba7720347703bf1631cb308fabcdaa67429527c5b7b676dbaef:f5cfca211b02fba7720347703bf1631cb308fabcdaa67429527c5b7b676dbaef:f245100cd2d31648f5f351bda564c9db4a35820cc30ef651337c4cd888070569d117a934b9c918e5df8b3744dd6620ccbc49f6b3e5782a30339dbb9cbed05dd2b3b8c5bf1546e70af636e6615c48b2c3c2d19fe35420df5314f63c4812b58e82a2a60b1802f38e505ce748017afa977d3f9b1b6bea2192acec73bdce12d65e684da4d8b41fa9a86f11086edc2d5296f67efc53ac84070fde13693eb2318f5a8c3b117c233422adcdd352f328f0ec699a4650c93f9b4a7d795d7fc2622a03d99b64f7b3dc3194f6c3b1b69d9907ce092401073f47a28f4799d229092a1b074129954be80ca4a3e6582ee05c302cacb7431d1ca6a451aaed7278abc7f78575241c2a2eea2e84cbf9a334df402109c028e345473a13af9b008e20bc8cf0bcefbb7aa727ec856e9925b4ddd99deba8f252911a590154b579a8aaa31f07dd5025df5cd8a09f742964cc8c365d8aff4eb1d79f6e5a07dac5f4ede92b4e2e61d34cc2d4f0aaaab037ad5fdb95de6cd5984ebaf7cce7f08d0ca0dbbe483ce3cb35cd790ca0427065a34df7f4c2af86efe9b765713aff257f5c1d54709527ad18ac33abcdeedb208064ebaea4835be4942b8fc666ad1b79b6651309e5ea1da302d7fba2e99f0e6319e82b9905a1ea482ba043b6800b330dc48b3313f59bb2f9e8a7f07eb1800a702745db14c6299a982dad897954445b7d98eb5837fd70bf190c649552c8e86feb7ff5b3ed8e0a06704d4553a3c2dd74f18ea8233ae0a50d914fe08fbcd3a1435fed56a9f3a7effa140fb552ddd21dffff7fa47332ddfc1e5317f4177d5e2f11a06ec84ccfb89b654ea81bd42d7e07a387301d0f40264abbf9f9107b30ede864cc7690c06d2e247a060bb2244ad78ed5c5515a1a2a612d61e3d931e28bc939b4d3435eee4f7331b1f0f85375d82ac9a77c43740032051746dc9269458c147d188d84401954a489cb4fbf9bf84ba7d8f100903ce67831b4054d0f58cd883d542c4933103ff070cdfc9dbb0fcc31efca466e77a33f1a813da6dc0c7c31585e8f4fef1ebf42fbd1:4d2ce707090b0f3f41462fd75bd609a2724fadfe5ca390e313a42cab42868ed6e9a8914dc13909c0d6f61e63712957c76f3bd8b7f55349715a3a317515c07108f245100cd2d31648f5f351bda564c9db4a35820cc30ef651337c4cd888070569d117a934b9c918e5df8b3744dd6620ccbc49f6b3e5782a30339dbb9cbed05dd2b3b8c5bf1546e70af636e6615c48b2c3c2d19fe35420df5314f63c4812b58e82a2a60b1802f38e505ce748017afa977d3f9b1b6bea2192acec73bdce12d65e684da4d8b41fa9a86f11086edc2d5296f67efc53ac84070fde13693eb2318f5a8c3b117c233422adcdd352f328f0ec699a4650c93f9b4a7d795d7fc2622a03d99b64f7b3dc3194f6c3b1b69d9907ce092401073f47a28f4799d229092a1b074129954be80ca4a3e6582ee05c302cacb7431d1ca6a451aaed7278abc7f78575241c2a2eea2e84cbf9a334df402109c028e345473a13af9b008e20bc8cf0bcefbb7aa727ec856e9925b4ddd99deba8f252911a590154b579a8aaa31f07dd5025df5cd8a09f742964cc8c365d8aff4eb1d79f6e5a07dac5f4ede92b4e2e61d34cc2d4f0aaaab037ad5fdb95de6cd5984ebaf7cce7f08d0ca0dbbe483ce3cb35cd790ca0427065a34df7f4c2af86efe9b765713aff257f5c1d54709527ad18ac33abcdeedb208064ebaea4835be4942b8fc666ad1b79b6651309e5ea1da302d7fba2e99f0e6319e82b9905a1ea482ba043b6800b330dc48b3313f59bb2f9e8a7f07eb1800a702745db14c6299a982dad897954445b7d98eb5837fd70bf190c649552c8e86feb7ff5b3ed8e0a06704d4553a3c2dd74f18ea8233ae0a50d914fe08fbcd3a1435fed56a9f3a7effa140fb552ddd21dffff7fa47332ddfc1e5317f4177d5e2f11a06ec84ccfb89b654ea81bd42d7e07a387301d0f40264abbf9f9107b30ede864cc7690c06d2e247a060bb2244ad78ed5c5515a1a2a612d61e3d931e28bc939b4d3435eee4f7331b1f0f85375d82ac9a77c43740032051746dc9269458c147d188d84401954a489cb4fbf9bf84ba7d8f100903ce67831b4054d0f58cd883d542c4933103ff070cdfc9dbb0fcc31efca466e77a33f1a813da6dc0c7c31585e8f4fef1ebf42fbd1: +7dfae416419d7b0d4fc1f823840c3e4bd4adcd4dc2dc17b38637acedacbdbb45bc51d7745931317e1e346e2e7c92039181b6bf38ee2f5a44fbe2339c4f952ab9:bc51d7745931317e1e346e2e7c92039181b6bf38ee2f5a44fbe2339c4f952ab9:ec843dc4dda6e902e9be31b70f11763b757ab6ce7334dc00764b2d084e9daf2484485984ee28a2830fcb94c541cb469440036731de80ff560f530c9d9e6e1f7d9c4c5bdf50b04f5403c29f76d7e36e00bbea35db1cc60da8d776526266c3324ce7efec6450859609266856d701a47a48dee8bf37409565c7fbfa99a204e5530c971c605b44305d5c7467894114253cf43cddf18b6296dd254a4d96ac7000918186dfd4bf454ed30974c553d0ae151ad4cf540cecaaa0b5948b0985a9c7b6e7815932bac11732fc7d10267f6bf8f1e7c08d650e567b4edd15ae7958410e42f1f537fa732f727a268388321d5344c4e78bb9a74eab9d6abf968965c66693d5f112dd4c14fdfdd96005eaa6757fa2cc1013fe4327ab0999d117f3dbf325b07cd454d4b141991ef7e23db5ee24beda35884aa3704808648aa43cd6256259f7d3db5e055311f253e8b57a4cda5afe0b0adfc364e160ca37e8dec6b95aa6152e5d5da6eb91be0e44ffe8e49533267b7eb795f5f8e0b2c35b29dfbc87585f22bd5b909dfd6a5edc0e3a9d97b0c4f3adc51e969937c08fd65f537aacda8f11275af02c3354542630f3920c393f5c42b9fc633de9d94c72e3f20002349ad0418035b3f25f02ca928e5b2d40a77a1c3e56221f4b9db0c25b096d6e5d0fe758da2c69053e8d086def4edc6e3453783ffc63a4960122d923671a906008bac10561ae6219d2b51d5367bf13ccabf5931b9f186eb109bacde40e1af2b56481e0c6dc6f5c5473f8001cf371919acb40cec5b962ebba80e32d6ebac4806d04d24768c2ad2e3f92a8cbe47754f9bf615953522b263dc24937fbd932c8c459eb8b109443af6c195a59fd2721b0125628f2b8143cf3c128bcec1392efd16b734c10716d96ba7d1f413917ccafa5bf5f83f524fe8406a152115ea770e1745e82e8b51d752b8bd785df48bfc12041bf874fc73afb42ca5d69c6416479ceb4aaa0492b6ff21ee12db2213a4286fd5605c93a7bb8a3b071b0b25fb01d77abbc8771489470a107aadae9f640c24dfd5328f60f4b7d:da34b1983e8c55e41fda8ec8abf23b367a0da606c8cdbb1e8b57e0343c0557a5f0e815e7f22f8605ae93b27d03776ac1f7de3d792ea2933ac22d2dc23b323d0cec843dc4dda6e902e9be31b70f11763b757ab6ce7334dc00764b2d084e9daf2484485984ee28a2830fcb94c541cb469440036731de80ff560f530c9d9e6e1f7d9c4c5bdf50b04f5403c29f76d7e36e00bbea35db1cc60da8d776526266c3324ce7efec6450859609266856d701a47a48dee8bf37409565c7fbfa99a204e5530c971c605b44305d5c7467894114253cf43cddf18b6296dd254a4d96ac7000918186dfd4bf454ed30974c553d0ae151ad4cf540cecaaa0b5948b0985a9c7b6e7815932bac11732fc7d10267f6bf8f1e7c08d650e567b4edd15ae7958410e42f1f537fa732f727a268388321d5344c4e78bb9a74eab9d6abf968965c66693d5f112dd4c14fdfdd96005eaa6757fa2cc1013fe4327ab0999d117f3dbf325b07cd454d4b141991ef7e23db5ee24beda35884aa3704808648aa43cd6256259f7d3db5e055311f253e8b57a4cda5afe0b0adfc364e160ca37e8dec6b95aa6152e5d5da6eb91be0e44ffe8e49533267b7eb795f5f8e0b2c35b29dfbc87585f22bd5b909dfd6a5edc0e3a9d97b0c4f3adc51e969937c08fd65f537aacda8f11275af02c3354542630f3920c393f5c42b9fc633de9d94c72e3f20002349ad0418035b3f25f02ca928e5b2d40a77a1c3e56221f4b9db0c25b096d6e5d0fe758da2c69053e8d086def4edc6e3453783ffc63a4960122d923671a906008bac10561ae6219d2b51d5367bf13ccabf5931b9f186eb109bacde40e1af2b56481e0c6dc6f5c5473f8001cf371919acb40cec5b962ebba80e32d6ebac4806d04d24768c2ad2e3f92a8cbe47754f9bf615953522b263dc24937fbd932c8c459eb8b109443af6c195a59fd2721b0125628f2b8143cf3c128bcec1392efd16b734c10716d96ba7d1f413917ccafa5bf5f83f524fe8406a152115ea770e1745e82e8b51d752b8bd785df48bfc12041bf874fc73afb42ca5d69c6416479ceb4aaa0492b6ff21ee12db2213a4286fd5605c93a7bb8a3b071b0b25fb01d77abbc8771489470a107aadae9f640c24dfd5328f60f4b7d: +709416074997b9c9af4d37a01139e8a3f9f2ce5d72a57d805e822a81186d017eaee110f1f4d46ea60649d786b150052e287a9da60122c47b0908fa8b2ca28a80:aee110f1f4d46ea60649d786b150052e287a9da60122c47b0908fa8b2ca28a80:eddaa369c0e31a1fcc1da46f65362442a0cc21c7dcdd5cd90e0a2ee9f25110812ba114931c868a708607ac16084d79715d13b338c05c6aef7343e7dad282f96fe28193188f0cc893c7dce805fd3a7cd268b72894160b5245fed9fa9943b7c80adb3c2d1a353d8f12df25a31dde7fa385bbec351da66f153032e17756273f8d54e9a3b9ea25ae67d1e9c18cc68be601e3d68282818ce0e7cf88a4d1336453021732f08d9e76cd23637929b0911d5f8614f4842e670c142860afc265c50172b13bfd35ad8fc54b28657da32bac153ba9affc897afb3c721f48caa46240585710b0f2d24d5ff4965d1d10f1a07b06abea6a08e1d6f1500da12c434a6d778c941067108000475ce831bcfe2d0afe40b7419d07059bc0cd8dce4be9587ff29ad8bf0b268ae23ce0da5bb5bf74ff0b2b31b82112a9fd5abd9bfd0a90e6f4723548c6bb2f99dc061ba32eba2d53e6bc79bf441b23fb7460de04e8e8efbcd4d4cc7355de9e3b0861a681b983839d4488e551751f23e9a6e2e4d443273b9e0fe64d8acd1c748b5559438223dd21b5183189e0f3c0e8ed414c0356bab77a654de1a5771462ef14344970a491511a722914f4a89f4f1a827e18cd84479cc92592eadf8de2df824b976dcbd284a3ba64bcdb0df15e8f41c0b2471586b26a06353d905028235c1c6e5c4587222725af083e11e79c943aa444d4aa41218d3e974336e372813e99e2b0c5f0ae810ffed9a7a3d6cb74c5473d990a5911329b8e82ec6bf2bd4321bb487370f8739e7a2a4a53430833d45b9fe3deb93f79fc6a51d563695ecdb97858d213da584434b7c71546aae8d967e1c6d0082b10d4a72de1742e53c4b2f92eb8b5c8c35ab6535ea8100b37924a0a91d2a728d0f5642437aa66c82ab74b5d0745ec08f7705cb81fa079d89ecdc9aa1f8d7d82dc7746d34615343a6925dc318f352a2b45012438424f9098fddf6e61fd1f8fb49da40b3eece89a1af1996de70cd1696cbfd9e301ea5f4437c71ac2a032254c140a90e85fb8ffc4667fa139c1ee9bbf12eed906a967bc0921:8e4b41f097d83614184ba7f52ba2fd9f0565f8a63721ef55f93162826b9f0ac070c0e2864b5ffd8eccc18efad18b2ce84be57c0b4a41c52e20ef37722377c60feddaa369c0e31a1fcc1da46f65362442a0cc21c7dcdd5cd90e0a2ee9f25110812ba114931c868a708607ac16084d79715d13b338c05c6aef7343e7dad282f96fe28193188f0cc893c7dce805fd3a7cd268b72894160b5245fed9fa9943b7c80adb3c2d1a353d8f12df25a31dde7fa385bbec351da66f153032e17756273f8d54e9a3b9ea25ae67d1e9c18cc68be601e3d68282818ce0e7cf88a4d1336453021732f08d9e76cd23637929b0911d5f8614f4842e670c142860afc265c50172b13bfd35ad8fc54b28657da32bac153ba9affc897afb3c721f48caa46240585710b0f2d24d5ff4965d1d10f1a07b06abea6a08e1d6f1500da12c434a6d778c941067108000475ce831bcfe2d0afe40b7419d07059bc0cd8dce4be9587ff29ad8bf0b268ae23ce0da5bb5bf74ff0b2b31b82112a9fd5abd9bfd0a90e6f4723548c6bb2f99dc061ba32eba2d53e6bc79bf441b23fb7460de04e8e8efbcd4d4cc7355de9e3b0861a681b983839d4488e551751f23e9a6e2e4d443273b9e0fe64d8acd1c748b5559438223dd21b5183189e0f3c0e8ed414c0356bab77a654de1a5771462ef14344970a491511a722914f4a89f4f1a827e18cd84479cc92592eadf8de2df824b976dcbd284a3ba64bcdb0df15e8f41c0b2471586b26a06353d905028235c1c6e5c4587222725af083e11e79c943aa444d4aa41218d3e974336e372813e99e2b0c5f0ae810ffed9a7a3d6cb74c5473d990a5911329b8e82ec6bf2bd4321bb487370f8739e7a2a4a53430833d45b9fe3deb93f79fc6a51d563695ecdb97858d213da584434b7c71546aae8d967e1c6d0082b10d4a72de1742e53c4b2f92eb8b5c8c35ab6535ea8100b37924a0a91d2a728d0f5642437aa66c82ab74b5d0745ec08f7705cb81fa079d89ecdc9aa1f8d7d82dc7746d34615343a6925dc318f352a2b45012438424f9098fddf6e61fd1f8fb49da40b3eece89a1af1996de70cd1696cbfd9e301ea5f4437c71ac2a032254c140a90e85fb8ffc4667fa139c1ee9bbf12eed906a967bc0921: +3dcb7ae7d9f0f141f1d9f07883635b913ed29fb61d0f741c9afd05a27b045b06ae62b7ee1b8db5764dafddd9724acc106d6c0a4d1e85d8906f7584b558f577df:ae62b7ee1b8db5764dafddd9724acc106d6c0a4d1e85d8906f7584b558f577df:38116a572669070dd5863218c91a77a4ab47553688488c792838509e9aba25067adb7ea4249848009d914ae987a6032348c1c0681cf977a9552dd6bbf4e6ff32acc9fa61cbee25a39307650f8ba6a7ce421ef2f71bccc0958138f9324c86bf2e528fa3e4d1b19f9f2ca5268409b8cc19c62dd979b89697e457ed2d98bd2096f62d3d9e247388795927803e79ab71d4f72f568e945a8a162159d9b84836e4585644d4979f614aada73ad413a83391e9cf880c42ac2a98343b6a82cd2b61581456f6de5ceb24fe46b7625d52ab2c2c324ac74703d15e15f1aeff8055d2f739f7363e16ec1d78be2c6299436c8c8d336bd29271a897a6ec932ed08725be21b28f9aa14eaf4f71853154db14587c930ab3eb0227ad7ffb45b3baa6a999499cc8a6e45b1ab4d0b339782bcd9cfbcf88cf7eae891cc841e9c88a1f6a691f3948a6bc85ba7f4611642e84223c3b178946ddbeddcfcdef4ae4c4e1a814b9b1f02b1eaa824db93f44b27d14206b340465a1cefcf535c63e55c4287224262733d98aaaa154f3ad42cd8546a461ce0d46d886d3461a2150cb45dbe56473ff63d3dc7a2b957b823969f19b5968e8b424c879741926d82c6386753b0fa1f080284e5578942363aadeb21f8e1e8909fa6c380764149bc915b228604efc56d92e4beb720edc74c4d78f925d6cfdf7ba2f14b5623775810d2d07bd388c573e36523f215738e69114dcf8d80f170bfa676e31fb626a7d449ed96647363475970c8c47809709bcb5e7200f2a227c7c8e7b000f30c0bde61d67bd6895361629a36c8fdd5a56b81efbacf15c1b3530a08cded5b1fd457fbd2f03042f56f1b37ed15cdb912fa0298c276725087ee27d3cf2550fe6e8a0330af417f4f5baf03627ed67c5f8323363abac5a1fe34823180e3e0e2080f75bfd91c207cf6baa9a229cf443dd442c5902e0673f3252b8526346585872f6cd366025a56992b70ede39bc8d322f9c22a1dc599e9f0d524cb6d2ea5ae2878ef6bed4b702807f1e1e73ebf290eb6c0eeb85c13716f626aa90d364b4904837ce05:09a1e6fedf971b3edbfaefbeb89aa539ca0b02b37e7ac4ea8920d6d4348ee0cf9a2d5e96fce517c665e7c38368baf24979249a95b70ea7436c00785f16a3ae0938116a572669070dd5863218c91a77a4ab47553688488c792838509e9aba25067adb7ea4249848009d914ae987a6032348c1c0681cf977a9552dd6bbf4e6ff32acc9fa61cbee25a39307650f8ba6a7ce421ef2f71bccc0958138f9324c86bf2e528fa3e4d1b19f9f2ca5268409b8cc19c62dd979b89697e457ed2d98bd2096f62d3d9e247388795927803e79ab71d4f72f568e945a8a162159d9b84836e4585644d4979f614aada73ad413a83391e9cf880c42ac2a98343b6a82cd2b61581456f6de5ceb24fe46b7625d52ab2c2c324ac74703d15e15f1aeff8055d2f739f7363e16ec1d78be2c6299436c8c8d336bd29271a897a6ec932ed08725be21b28f9aa14eaf4f71853154db14587c930ab3eb0227ad7ffb45b3baa6a999499cc8a6e45b1ab4d0b339782bcd9cfbcf88cf7eae891cc841e9c88a1f6a691f3948a6bc85ba7f4611642e84223c3b178946ddbeddcfcdef4ae4c4e1a814b9b1f02b1eaa824db93f44b27d14206b340465a1cefcf535c63e55c4287224262733d98aaaa154f3ad42cd8546a461ce0d46d886d3461a2150cb45dbe56473ff63d3dc7a2b957b823969f19b5968e8b424c879741926d82c6386753b0fa1f080284e5578942363aadeb21f8e1e8909fa6c380764149bc915b228604efc56d92e4beb720edc74c4d78f925d6cfdf7ba2f14b5623775810d2d07bd388c573e36523f215738e69114dcf8d80f170bfa676e31fb626a7d449ed96647363475970c8c47809709bcb5e7200f2a227c7c8e7b000f30c0bde61d67bd6895361629a36c8fdd5a56b81efbacf15c1b3530a08cded5b1fd457fbd2f03042f56f1b37ed15cdb912fa0298c276725087ee27d3cf2550fe6e8a0330af417f4f5baf03627ed67c5f8323363abac5a1fe34823180e3e0e2080f75bfd91c207cf6baa9a229cf443dd442c5902e0673f3252b8526346585872f6cd366025a56992b70ede39bc8d322f9c22a1dc599e9f0d524cb6d2ea5ae2878ef6bed4b702807f1e1e73ebf290eb6c0eeb85c13716f626aa90d364b4904837ce05: +297311ddeffec9d2be68ef7b2a20fe2d277e1d8e51648b03572ada27ec1f9f436a6c28e761640c4008333aae5a3366302e2f4677a953ba482ab6fb4a1d70b447:6a6c28e761640c4008333aae5a3366302e2f4677a953ba482ab6fb4a1d70b447:2652acfc3bdf09a599ec6786bbd94fe577cf578e0263cc68d9f57a6c83458f80acd8a75ef03040a635672b968ff2afdb288d28b9996f6415b2f3175e9ea37aeb05df81812e38a4c976eb92856cedb91a269a46fca5df9bd730fd84452b4bd93577c61f42c14113979882a86a9fe632e4756afd89816fc4670a310503fdaad2db764c3721213c3e60f29c2668d4de8f42b087f25cd56c69a4e48f134f5598cf145be638a5c2318863329061729aac91da6a191fd774880cf9cb555eec15b0044f10e5433fb46a9b8892da8f6d24f142588b70ff0b49200c506b88bed449ad10d3f92c2baeda6bbf58676c5bbc67d31f64fb12e8d5e78876d5c849fc314b2cf8010c510204c8633d0cc31856ec6a114ea8a89c48927b07a31ab842c9b8352d9367345141a99b40049d5c48e7d27cab427adefd1f0fc1136b353cb01c3def91fffee8ad91e88f4bb7d2615c0dcc95344cd01950938ecb14b8446b56a06bf2f2f65fb8735e8a7bc96bb46ce9cac71a88eb8fda5e69d69eb29aa42a016b8583893e9d7277cb1359c5687eedcd599d8a46e6c14963637db04a929f4bc79304ac2dae733b3a839eb74fbe3de5042fd655eaecb15f39b2fe16dad8a6ff8dbc054fed51282a856e9da6316fac6db5d56f77f18da8412eb377e5b1b8f4cb1354ecfe8fe8fd54e62d767a80de04cb7620229a8831dbc9ecd4578ffa2ff06b5445e440d69aabc94c47bd17f22b69f52eeae5cfcd01a5cafe0580072ae9166b95743d68c3564c5a7e46f24bc48a898a1ab2ebe63f36851d2aacfa0c4f32d993771d314e725a43d9805d1371cf723ef161d42e63ffca688d7f0e21ef5b3f9a561a6210702b85fbd1f8ca75389cc7a22739bae4ded93757f1520dc38844a1a88be8e09645059148807b933770878cb8a9ad9211317131e69324532fd0279b83185b628fc2f9e21500384693fa29f26bd1b9c301601367665f05f372dab4e3107726cd3f639ca62bf63a75f77eaa75f7136157ada2374e65fb4fd349b45e25441fd21b13e6911366b97cfb4d6ad522b850adf40c:4bf0b92c6ee4eace5e8eb10370ff9d9c68a5749d59899d04327aaa38f8f825e032e59742b37de23107a3ecdd3f7a0d08122614b78fdd37293c8d05e28f5f71082652acfc3bdf09a599ec6786bbd94fe577cf578e0263cc68d9f57a6c83458f80acd8a75ef03040a635672b968ff2afdb288d28b9996f6415b2f3175e9ea37aeb05df81812e38a4c976eb92856cedb91a269a46fca5df9bd730fd84452b4bd93577c61f42c14113979882a86a9fe632e4756afd89816fc4670a310503fdaad2db764c3721213c3e60f29c2668d4de8f42b087f25cd56c69a4e48f134f5598cf145be638a5c2318863329061729aac91da6a191fd774880cf9cb555eec15b0044f10e5433fb46a9b8892da8f6d24f142588b70ff0b49200c506b88bed449ad10d3f92c2baeda6bbf58676c5bbc67d31f64fb12e8d5e78876d5c849fc314b2cf8010c510204c8633d0cc31856ec6a114ea8a89c48927b07a31ab842c9b8352d9367345141a99b40049d5c48e7d27cab427adefd1f0fc1136b353cb01c3def91fffee8ad91e88f4bb7d2615c0dcc95344cd01950938ecb14b8446b56a06bf2f2f65fb8735e8a7bc96bb46ce9cac71a88eb8fda5e69d69eb29aa42a016b8583893e9d7277cb1359c5687eedcd599d8a46e6c14963637db04a929f4bc79304ac2dae733b3a839eb74fbe3de5042fd655eaecb15f39b2fe16dad8a6ff8dbc054fed51282a856e9da6316fac6db5d56f77f18da8412eb377e5b1b8f4cb1354ecfe8fe8fd54e62d767a80de04cb7620229a8831dbc9ecd4578ffa2ff06b5445e440d69aabc94c47bd17f22b69f52eeae5cfcd01a5cafe0580072ae9166b95743d68c3564c5a7e46f24bc48a898a1ab2ebe63f36851d2aacfa0c4f32d993771d314e725a43d9805d1371cf723ef161d42e63ffca688d7f0e21ef5b3f9a561a6210702b85fbd1f8ca75389cc7a22739bae4ded93757f1520dc38844a1a88be8e09645059148807b933770878cb8a9ad9211317131e69324532fd0279b83185b628fc2f9e21500384693fa29f26bd1b9c301601367665f05f372dab4e3107726cd3f639ca62bf63a75f77eaa75f7136157ada2374e65fb4fd349b45e25441fd21b13e6911366b97cfb4d6ad522b850adf40c: +4db2b58144a8d2d0ec03bb9bc29b4ca893854c80b64afa4af7a9c936935ecb04fc5cd750e174ed718bd938fa8ed99a1b9d556ba7670f2a77daf1c720113732a5:fc5cd750e174ed718bd938fa8ed99a1b9d556ba7670f2a77daf1c720113732a5:c8d1dbc936911e122cee18f92b16a39a2eef0823b227f898cdf5842b93d59fc002edb5498a20872e19554ef73999eb3a7b3e2fdd9070e1efa9228e9e93b29a868ae3799e4e572324836b1ad5aa812bf00f845bc217ebbc3fabdc4e1b6e51ef9efac2770aa0a4a11ee52ab956ac6448aa2629cb61dbb1f1edb3bde99b4876da392a6e0b9a0c31849a5890aea9522f56d015a1935015b91bf4c6a0011d2377d671c3d0d753c27f8c76e405d0230f1f4b9b88fcebba1eaf13777235e55324b7d3f81e686109d91ce689530b90d2c5c71dd18772b385d62ccbfd2e089a1b670983f60c21c4455cb9d1a0dcaa74c874e35211f8227ff7c234dff85ec0b07e368cfa50a343578395a14c68f1f89bd4ecbc172ef805e5831ec89475fcc8d685ca9255a77e3ba3c147508ec92d7bcce879af0abdd2416b67b5f50507337914f390bbe0b450b6a2f1159372c4bccea382ce3d6d9fb2515ecf7930059a0552b75f978862bf97e8325af24d1b8ce9512bfc7cef884232042341d82f9b5dad2e502ac6ac795f99dac7fc60e3b8639d0e1500dead4e78aca109957d577a13c1925d7403c1acf989a9de6711e23c67bf8722f551b774cada931b5fd973434e3b7172819883e70c52785e3b49d323d05636641158640dcf6a4c200eb2c13b1beeb2dc360352470d15386e59e6fa60367e5e7f172b21159d5ee7cab0d7f5868239858e2a93550480fe8fb4dcaf4f224c4b2ad5448791632df30e8e5fb998b35ea9aec8c934a4403aef82187ca1abf82a344d00ffb993d9ff3461d6fecdaf5d3b481e0d31153dbf6aed288c8add064e8331550141bd5f7a7e047b8607d846a6bfb72d683446a445114606250d8d2d3a8b9508bb07d4623cdf1788b5499e9cb9a1379849bfa19c9a9f4cd3d9253adffda25f47c811be833b02f3327ebba83730195d614bae6fe4e7a3830815d2af400d20a9417a095e7e8eea1044917cbe512c4018d656e2db67bb989c00e1e507623e8278d729925b84fb5c186a7bac189e6d6ab14fd7b62fdc632bebb5f77cb5cc2f707df4053099:424517aadd853ce3985759a327e7760d9156d3b27345383f0e4ad6661ee4a3724d18d820f6c557f82797beb62d2f085433744f89a2d85293796481862ef8a40fc8d1dbc936911e122cee18f92b16a39a2eef0823b227f898cdf5842b93d59fc002edb5498a20872e19554ef73999eb3a7b3e2fdd9070e1efa9228e9e93b29a868ae3799e4e572324836b1ad5aa812bf00f845bc217ebbc3fabdc4e1b6e51ef9efac2770aa0a4a11ee52ab956ac6448aa2629cb61dbb1f1edb3bde99b4876da392a6e0b9a0c31849a5890aea9522f56d015a1935015b91bf4c6a0011d2377d671c3d0d753c27f8c76e405d0230f1f4b9b88fcebba1eaf13777235e55324b7d3f81e686109d91ce689530b90d2c5c71dd18772b385d62ccbfd2e089a1b670983f60c21c4455cb9d1a0dcaa74c874e35211f8227ff7c234dff85ec0b07e368cfa50a343578395a14c68f1f89bd4ecbc172ef805e5831ec89475fcc8d685ca9255a77e3ba3c147508ec92d7bcce879af0abdd2416b67b5f50507337914f390bbe0b450b6a2f1159372c4bccea382ce3d6d9fb2515ecf7930059a0552b75f978862bf97e8325af24d1b8ce9512bfc7cef884232042341d82f9b5dad2e502ac6ac795f99dac7fc60e3b8639d0e1500dead4e78aca109957d577a13c1925d7403c1acf989a9de6711e23c67bf8722f551b774cada931b5fd973434e3b7172819883e70c52785e3b49d323d05636641158640dcf6a4c200eb2c13b1beeb2dc360352470d15386e59e6fa60367e5e7f172b21159d5ee7cab0d7f5868239858e2a93550480fe8fb4dcaf4f224c4b2ad5448791632df30e8e5fb998b35ea9aec8c934a4403aef82187ca1abf82a344d00ffb993d9ff3461d6fecdaf5d3b481e0d31153dbf6aed288c8add064e8331550141bd5f7a7e047b8607d846a6bfb72d683446a445114606250d8d2d3a8b9508bb07d4623cdf1788b5499e9cb9a1379849bfa19c9a9f4cd3d9253adffda25f47c811be833b02f3327ebba83730195d614bae6fe4e7a3830815d2af400d20a9417a095e7e8eea1044917cbe512c4018d656e2db67bb989c00e1e507623e8278d729925b84fb5c186a7bac189e6d6ab14fd7b62fdc632bebb5f77cb5cc2f707df4053099: +c820413c2456747104662ef4dff3ac233ac4b91a76d3c4ea754490bc9b1e291f8993cea2f7f2806c77b3981b54bfa9bf1762151b418e5e725371ca2c04d223ee:8993cea2f7f2806c77b3981b54bfa9bf1762151b418e5e725371ca2c04d223ee:d2992f83924a594887e6ef13f2ae808fc8639c7b2c994faf0f795e36016dab7700a0ee530170f0b9fe98ab7588ce03bc50c2bae65e052647e756735b35d0b59c964e917d8c83e2f9fecc4cb05564287f0e34c9494005e25b1a8b1b942b54d89035f1b1c3c945fcc84e4a39efa2ca50959b459af74d21b6242e2f56518f70e8679257c089d26c3bb792687c923355b2c18ee2136d40cba45acb64240d9667f39dba3639b6516d4c4947573ef4ced876b5b2ea3489eaea539f557f58da204691a76e29c94b8b0538232c5f7d0bb0fdd016910431354b3e1e7ce62ad436917cd5c315a5be9b971c80f97bc9d5c156ffd64fd4e31da56083e02a0c8fce554db68674cb62700ba951752b829b03c542327412eec9ccc6a50adf47bbee15446682da2fea42048936d763060cd8f539652616dfa808d623ff777b4113652e789ec025b85e04efe8ad4c960b190bf4a5a6324d6f57c1ad22018c83cd7e7e097fc67b80269c13b4dd9701ca98f9876958ba7689c6f6f10a732a64bef22e8b98bd304d5dbf4fb1f9e4ca539a5c4aa619c44d6f58f824b2dbae77b7e83b56db5e5aa7b0ae9ce1cd10a69f04a80f1379eb0c474e4782df0e3ba6a148226bd1a662d95ee2d67c5207333cb1d54176d9e506459479029f31dcace269938f6bc562787841dcfe101f4db60bd66016e1eebb6bfbd9cd83042dd1379a464f405aaae3c11807848cc4f95c3cc6fa92ab4ea5305834eb86b873fa30ed1f7f470bf663f1a70cf9e60ab680cd1dbbd03ac0433b3d4bb482f8b344d46b3aa934b8633f57090bea5fccca6488799835f133f8bcf6e887ca59d19076d6ca19d4e28349051e016b03e9a920f4120fb523d1371d0e38467319543f127ed914b43ad062226a536582db728ccd76e983f11766a8863c2f424f65508dcb26fe0c5a800c35093960a121976e3051e2ef1a2a99c12fb7bd8bc037a439686806eb72017a071a91b3e39c90e86bc335f9bb543b127c9886738cb53806b9cb3c2594c7effc2a5920aa834be65c49f47964e89eec74728de771f3d675de9d1e:7ef70e4a14954d509f117f4bd01b220bcc192d3b5fdfc3482fbbc3b69dc068a7c4761d1bebc2317d6db74f906a155642b0a3c6592bdc72e64eac6f203fb74e02d2992f83924a594887e6ef13f2ae808fc8639c7b2c994faf0f795e36016dab7700a0ee530170f0b9fe98ab7588ce03bc50c2bae65e052647e756735b35d0b59c964e917d8c83e2f9fecc4cb05564287f0e34c9494005e25b1a8b1b942b54d89035f1b1c3c945fcc84e4a39efa2ca50959b459af74d21b6242e2f56518f70e8679257c089d26c3bb792687c923355b2c18ee2136d40cba45acb64240d9667f39dba3639b6516d4c4947573ef4ced876b5b2ea3489eaea539f557f58da204691a76e29c94b8b0538232c5f7d0bb0fdd016910431354b3e1e7ce62ad436917cd5c315a5be9b971c80f97bc9d5c156ffd64fd4e31da56083e02a0c8fce554db68674cb62700ba951752b829b03c542327412eec9ccc6a50adf47bbee15446682da2fea42048936d763060cd8f539652616dfa808d623ff777b4113652e789ec025b85e04efe8ad4c960b190bf4a5a6324d6f57c1ad22018c83cd7e7e097fc67b80269c13b4dd9701ca98f9876958ba7689c6f6f10a732a64bef22e8b98bd304d5dbf4fb1f9e4ca539a5c4aa619c44d6f58f824b2dbae77b7e83b56db5e5aa7b0ae9ce1cd10a69f04a80f1379eb0c474e4782df0e3ba6a148226bd1a662d95ee2d67c5207333cb1d54176d9e506459479029f31dcace269938f6bc562787841dcfe101f4db60bd66016e1eebb6bfbd9cd83042dd1379a464f405aaae3c11807848cc4f95c3cc6fa92ab4ea5305834eb86b873fa30ed1f7f470bf663f1a70cf9e60ab680cd1dbbd03ac0433b3d4bb482f8b344d46b3aa934b8633f57090bea5fccca6488799835f133f8bcf6e887ca59d19076d6ca19d4e28349051e016b03e9a920f4120fb523d1371d0e38467319543f127ed914b43ad062226a536582db728ccd76e983f11766a8863c2f424f65508dcb26fe0c5a800c35093960a121976e3051e2ef1a2a99c12fb7bd8bc037a439686806eb72017a071a91b3e39c90e86bc335f9bb543b127c9886738cb53806b9cb3c2594c7effc2a5920aa834be65c49f47964e89eec74728de771f3d675de9d1e: +6769cc8e125617c22ce57237a4fca1507f941234661df74328d04ab62ef86c4705112ca60baff79b4916c1bee2b9390c047af08c35ebb3c381b9748d1dd4c4fd:05112ca60baff79b4916c1bee2b9390c047af08c35ebb3c381b9748d1dd4c4fd:685489739b98564749587ff1ac96ba682da30b40a4de24f54ec8b083dda45333162167cb3f97b2c7314ce7a3f3f3d319ccc35bb6a9f0077d563161e281469cf08968d9dcf7ae5fff830a5db00bc38010e6662d494f3c8647c4f70ce2d29a9da84610a080b5759a3b582052dfde66e4a7fa5fb27f065073fe723d83701d5bac06ca43b46d1e58097670c194a13af8b573a3791a9661557cbc042757ab8add0ef7cf4f35435a4212353fcb3c203c73dbc9d26852d0e91732e3621ce828929cdca4d9192048751922ed225eab2900cff971a2a2d342463648bbb1944319a8ef6d43db62480fbf1d7257d22694539793f25c927917caab25c1193a2d2b23bb5cb8569aefff4f0ca423d19bbd46fc5ef7524ff8cb706ffc47076509c05a8158af77f98df6a9b5cb3244aba4b5c5f9ce597e7d29ba07013dcac1911b6de7113c736a4005c459992979019a45b2dd802a07660909eb4ce205408170d82545dacba8686dbde927dbc9c7d962058e9a95ea66b8dfd3ea435357a93c73948cd355f6ac6552323f17c2a678662bc0e9726ad5a5251dd27647404cbfe61ceaafdcfc08a475ffd87cb7f597e56ac1670409dd9408ae4770420c6e5e6dd8e748fe03a72dc12803d02771d92f47e6e717ccc144fc037275b6f745dd30da1a45d29db6d9073eee5009cfd5462733414a495f349db0b6dbf2cea9ccd57238ed5ee91ad8bc86179ad5695a85a50484e617751de5ef7a7d8a8db950a98a6b7f7dee9d42a5df692fccf555c940dc39cf2eac48cb9d15cda14dd2a7ecc0b76ebec68ad4177d1117e07766c48590d43ca7662868eb9790ac29f4f2392b9a93f89759e7ba546b925bd86f807d8d16c7e637dcc666e90590bf430d986a67f1b0c7c2c94930845869ed8d8adde18fc1887456881b4b26b53dcba7a526f0eca14e8bb689d66f0aa1b253c3dcfcf59540d5d2f5ad617f52c30938a5a92ea385077d75aa4ac07afc2b35fb8c1d5e78eb295fc20fe37c41ac06959d3a1797843ad7056c1b412dd0b480aa3b39bcc20587d9a0fef92c6c950ebc5bb8e142:d39d853d2c2c5d21b5871ea5a75c041048d93a47dc599a5fddc0856285ce636fcdfd8564083d06ff284a524bc633cfdfc3b037163d674cb9bb5ba3bc25bed00e685489739b98564749587ff1ac96ba682da30b40a4de24f54ec8b083dda45333162167cb3f97b2c7314ce7a3f3f3d319ccc35bb6a9f0077d563161e281469cf08968d9dcf7ae5fff830a5db00bc38010e6662d494f3c8647c4f70ce2d29a9da84610a080b5759a3b582052dfde66e4a7fa5fb27f065073fe723d83701d5bac06ca43b46d1e58097670c194a13af8b573a3791a9661557cbc042757ab8add0ef7cf4f35435a4212353fcb3c203c73dbc9d26852d0e91732e3621ce828929cdca4d9192048751922ed225eab2900cff971a2a2d342463648bbb1944319a8ef6d43db62480fbf1d7257d22694539793f25c927917caab25c1193a2d2b23bb5cb8569aefff4f0ca423d19bbd46fc5ef7524ff8cb706ffc47076509c05a8158af77f98df6a9b5cb3244aba4b5c5f9ce597e7d29ba07013dcac1911b6de7113c736a4005c459992979019a45b2dd802a07660909eb4ce205408170d82545dacba8686dbde927dbc9c7d962058e9a95ea66b8dfd3ea435357a93c73948cd355f6ac6552323f17c2a678662bc0e9726ad5a5251dd27647404cbfe61ceaafdcfc08a475ffd87cb7f597e56ac1670409dd9408ae4770420c6e5e6dd8e748fe03a72dc12803d02771d92f47e6e717ccc144fc037275b6f745dd30da1a45d29db6d9073eee5009cfd5462733414a495f349db0b6dbf2cea9ccd57238ed5ee91ad8bc86179ad5695a85a50484e617751de5ef7a7d8a8db950a98a6b7f7dee9d42a5df692fccf555c940dc39cf2eac48cb9d15cda14dd2a7ecc0b76ebec68ad4177d1117e07766c48590d43ca7662868eb9790ac29f4f2392b9a93f89759e7ba546b925bd86f807d8d16c7e637dcc666e90590bf430d986a67f1b0c7c2c94930845869ed8d8adde18fc1887456881b4b26b53dcba7a526f0eca14e8bb689d66f0aa1b253c3dcfcf59540d5d2f5ad617f52c30938a5a92ea385077d75aa4ac07afc2b35fb8c1d5e78eb295fc20fe37c41ac06959d3a1797843ad7056c1b412dd0b480aa3b39bcc20587d9a0fef92c6c950ebc5bb8e142: +1df7acfb963304e51ec471caf181102556783cb7d91ead30bdc2534d078a148805a31ffc70e4e3569fc2be110c643ad5f087913c7aa476dcd8d6e4bc7ec22d24:05a31ffc70e4e3569fc2be110c643ad5f087913c7aa476dcd8d6e4bc7ec22d24:b0c3eeb57f14606ab7abeab2ee0573843ca22e6db2fdf2c9064cea5198dc5830eb158da8e2daa88857af8b8eefccf0c26c3ec0f330e92cff06bc05a29bfc99f940b61f3cfb2964b337097a6550a3e9a328c85be6f160d2c0a57ff6f1b3c5ffcca89089425ab6be0172e175baf40cf12b24a815f70f29a3a4cd0a6a132f120097752f4bc743ede08f5f21d42f282f7671f7783e27b2a8e2c14692f1e0e5de82855dabf98a1a63976006ffbfe5f5a579b460e26d06bd542842a5f9261bbf260451d2321c508932013cc6e904f79b5e4686d033e12c7bbd7eb1c92379c5ec341bf6457a3f17264a7c278b27501ecaedc361eba844442342b4b10fa94d265865116acf43fcbec965d2ab4bbbe614c4f90ab6b3e0d5383fa04988bfbb260307dde22d84098b6331d155141a927bb78d664b341d2f2a93e291cf79baaecd2612f6b104f3fc81373a7c6a045b5924bf950cd542f7b7accef3aa7d725de053055d951bd768111392596638ae097170f4492ba50a468f8e347763db612d3c7de7e56459b26ee029c630827a353aee73de68d6d72b27afd75d22164527945c7226844fab15b8dcc914349e3141c61316adc894dedcdc843984d9c7feae39db332dc393e9e8961bbde071c3d2858b3cb5f33b164a15616c6fe1bbc24a35f21336d261c5d8cf759e27e22c9101c4aebde3e126cf646ca7b2e03128095c5976bf3f6e491af0f0b640c7310966ac59c59fbc5bfe0548f88ee61ad9ec40c1c06dd29d794c44a3ea22c3d4762622ec1e8b333e45074db93741fda193c911f6db5879e55ee36ef602614ae64a5cde9d8306d22fbc4ae9c881a594bde6796125fcb628b9f3b6fb3ffd511b353f146a27272afd3e5d28b77f58a67f1fd27285c25ecc1ccf64e38d21f3b9ff22e00ee900629ef1a63e713f258883dd911f30c0d398b74bd797149be5e2696722da09d52d4ebf3c673929d298aac34ce05bea08ea9a424e93459c2eb8fc2222c31cc13d803b90a8a70bcd0a30c209211dc2ccc85b0bcd4582c695f58d80bf6ec471a2505f68847a75f6e911fd87:b181938de10142f32407b4e786cddde932eb11dbc0bf0e5ac509fae7a5bcc32961fe3448f912c8500fc6db4e1d3262a83c9dbe769bb8c3a761000fe36c0d7104b0c3eeb57f14606ab7abeab2ee0573843ca22e6db2fdf2c9064cea5198dc5830eb158da8e2daa88857af8b8eefccf0c26c3ec0f330e92cff06bc05a29bfc99f940b61f3cfb2964b337097a6550a3e9a328c85be6f160d2c0a57ff6f1b3c5ffcca89089425ab6be0172e175baf40cf12b24a815f70f29a3a4cd0a6a132f120097752f4bc743ede08f5f21d42f282f7671f7783e27b2a8e2c14692f1e0e5de82855dabf98a1a63976006ffbfe5f5a579b460e26d06bd542842a5f9261bbf260451d2321c508932013cc6e904f79b5e4686d033e12c7bbd7eb1c92379c5ec341bf6457a3f17264a7c278b27501ecaedc361eba844442342b4b10fa94d265865116acf43fcbec965d2ab4bbbe614c4f90ab6b3e0d5383fa04988bfbb260307dde22d84098b6331d155141a927bb78d664b341d2f2a93e291cf79baaecd2612f6b104f3fc81373a7c6a045b5924bf950cd542f7b7accef3aa7d725de053055d951bd768111392596638ae097170f4492ba50a468f8e347763db612d3c7de7e56459b26ee029c630827a353aee73de68d6d72b27afd75d22164527945c7226844fab15b8dcc914349e3141c61316adc894dedcdc843984d9c7feae39db332dc393e9e8961bbde071c3d2858b3cb5f33b164a15616c6fe1bbc24a35f21336d261c5d8cf759e27e22c9101c4aebde3e126cf646ca7b2e03128095c5976bf3f6e491af0f0b640c7310966ac59c59fbc5bfe0548f88ee61ad9ec40c1c06dd29d794c44a3ea22c3d4762622ec1e8b333e45074db93741fda193c911f6db5879e55ee36ef602614ae64a5cde9d8306d22fbc4ae9c881a594bde6796125fcb628b9f3b6fb3ffd511b353f146a27272afd3e5d28b77f58a67f1fd27285c25ecc1ccf64e38d21f3b9ff22e00ee900629ef1a63e713f258883dd911f30c0d398b74bd797149be5e2696722da09d52d4ebf3c673929d298aac34ce05bea08ea9a424e93459c2eb8fc2222c31cc13d803b90a8a70bcd0a30c209211dc2ccc85b0bcd4582c695f58d80bf6ec471a2505f68847a75f6e911fd87: +7ed87c36dfdbae60c940a3b325c19fded814d76a544820a32f286a5c0ad71d723c4ac510b36222c252a2dc1afcb40fb0eb85bca90391196a5883aa2cc912b2df:3c4ac510b36222c252a2dc1afcb40fb0eb85bca90391196a5883aa2cc912b2df:62d313912abbb006b7774a6737714a349970ce0421112f400463d3db0e2f7f128d7b96939f43c1e7107b5118a77c119683d866b7e3d72ac21f6b4272b4be9289b6556fe31b6051a0b42ed5ea0cf347696d30fb8bff6b8b572719de19a231cc85459a990c37801f0837186cefbb5521569666967cd4243d7307f1b0b24c8e2b9b692317304fbe3dd0a263650191b35216f52916573af90524f91db1a92471d758c92dc6d14d1a4b26f41b40403ca87dcfabdca47b9fc2533578f161f3b0199b5c698e080704b21c9e615269fcd0d40439ed8bc3bdfbc9afb44c11fa89275f0eaaa5d08fa959d6378d0db89910d48f2d86a1ebfc5cbf10eb2d5aadf51bbd8344ff8bbb5b8afe05a45011b5e4b72eb864ad263e8a03a6c7f98aeeb354f730a318aa30fb56d33d80748c98ebec15878ccf3ce822f69d3456843c400dc56b481a95e688b8a4735bf3843f5833dda0efe09e7175b567c661387afd2ebc079a48e34967ec97b927dfa581888f231a98a7ed33103bfa8e8f9ba6513527900b39b86231da7911a2fc935888a75f1129584afff2025249c4188f09052f85687706d05e299144d40de8898b7c8b2dfef0c3708573d8b0563a6bd0a504c0b6745702b1b57121c6f040aff27198948ba69c21253a28d39eba726219beda1f8209fb83e9adb07ad409fbd6d25565889ab45123f9d945ecd7d9ca7028ece092e35fbb7cb3f328126efddac5d859f2b2c6eb090133690e20c17deaf3882685f07e9ed2653b803b9b383b70748a1fa92c86f86d6c47ea87b10b12e363ba508060f47ce2a2f3b6a3eefcd4dacfc71c41f436fe0c2bc34d4baad49574e7443c126a589f6ef7bca44954f0bb28ec7151b0511c23c6bc42d5e85983ec16bb5f50a382d688150a49609cbde5698e86dcbf0212c2292299dc4dcf87429f6cd2eec80948ce867e25c94584cdc64b099029eb854edc26ea21421eff48cf4e41f49e2d89478def06c42bea220a133e50f5c74464c7e73fb1c1a77c507cf6cda85be402b7e6d6d21e810d6d0b5972b9fe77e54e74aee1f3bbfd6e7de6b5c0:579b38124bd0591a597cc9a389127ceaf55156077363edb811d0b65552acfcc677b272942199ca25ab790de6e084603ad1052ec210cf6fcb1417289067ce3c0862d313912abbb006b7774a6737714a349970ce0421112f400463d3db0e2f7f128d7b96939f43c1e7107b5118a77c119683d866b7e3d72ac21f6b4272b4be9289b6556fe31b6051a0b42ed5ea0cf347696d30fb8bff6b8b572719de19a231cc85459a990c37801f0837186cefbb5521569666967cd4243d7307f1b0b24c8e2b9b692317304fbe3dd0a263650191b35216f52916573af90524f91db1a92471d758c92dc6d14d1a4b26f41b40403ca87dcfabdca47b9fc2533578f161f3b0199b5c698e080704b21c9e615269fcd0d40439ed8bc3bdfbc9afb44c11fa89275f0eaaa5d08fa959d6378d0db89910d48f2d86a1ebfc5cbf10eb2d5aadf51bbd8344ff8bbb5b8afe05a45011b5e4b72eb864ad263e8a03a6c7f98aeeb354f730a318aa30fb56d33d80748c98ebec15878ccf3ce822f69d3456843c400dc56b481a95e688b8a4735bf3843f5833dda0efe09e7175b567c661387afd2ebc079a48e34967ec97b927dfa581888f231a98a7ed33103bfa8e8f9ba6513527900b39b86231da7911a2fc935888a75f1129584afff2025249c4188f09052f85687706d05e299144d40de8898b7c8b2dfef0c3708573d8b0563a6bd0a504c0b6745702b1b57121c6f040aff27198948ba69c21253a28d39eba726219beda1f8209fb83e9adb07ad409fbd6d25565889ab45123f9d945ecd7d9ca7028ece092e35fbb7cb3f328126efddac5d859f2b2c6eb090133690e20c17deaf3882685f07e9ed2653b803b9b383b70748a1fa92c86f86d6c47ea87b10b12e363ba508060f47ce2a2f3b6a3eefcd4dacfc71c41f436fe0c2bc34d4baad49574e7443c126a589f6ef7bca44954f0bb28ec7151b0511c23c6bc42d5e85983ec16bb5f50a382d688150a49609cbde5698e86dcbf0212c2292299dc4dcf87429f6cd2eec80948ce867e25c94584cdc64b099029eb854edc26ea21421eff48cf4e41f49e2d89478def06c42bea220a133e50f5c74464c7e73fb1c1a77c507cf6cda85be402b7e6d6d21e810d6d0b5972b9fe77e54e74aee1f3bbfd6e7de6b5c0: +6a29f81b8d9aa48a1b23364eac8f6a4bdd607a84cfe8e88d90175d80643a58a84c3be3a2a8425ff31c3a0db4a52a0cb1416ceb48cc3e4c28a4f2284ab3460715:4c3be3a2a8425ff31c3a0db4a52a0cb1416ceb48cc3e4c28a4f2284ab3460715:7876a3f4eb69bb7e54e9ff954ebd3b10b93a4c1afeae92fa03c103cb6313a201c5b33a9a7223755cb510e25ec582b54e81b84956f6c53f1f08a63bf0c4a261af450e523fe8f61ddb3c0eeab8751072688801b2a473b71a2e38708da68c2f37925cb05a20c4283b3af97b6f0ba65a5403554375e215d9e3aa1b0f9fdb0f849923edbdaa0ab481c545a5df8f51d1f68b223507ea0eccfaebb5fccf5e3dfa65a44eea504568a88180a060bb06c51557b81e667b4b04e3210fa4c379876c49f3e56bf2be1cf519a7418393d240dc8a224c6c38ac2ab9d8fadfc5362030c7930c3ce7795b147c26c8a28c653429d90a173a86a8b18a009e62aef6eca95d39bdbe45647778a2532a415ae19bad231129127842fe1d0f11fab4a1cf0b17e498cd5952c939e090090287b144895dff00cec8d6aedaf62481a41783e021082ce352063e62811fd99990104d8a46cdcaee2bab458e5247fb023e923330a428c7bcfd20b08f520e8946dd658347352ae0c4be73c3d5eccd11149f3ab7b8052cfd95c35d4164546f5d8f377517a7f432c0d5563a7bcc7bd119d3421dfebaae844599b29b383bb8d5dbf140d9bd47a078b7ae7c6aa87b1e29236c9fcfd654b7f809794cccb261588e18dec6c4046a934067d0dfa03791d03d83b718ac4d24dce785a3028de0c9592dba7c5c5845184afc9c0dfcf94095860f0eb802ebea20178e78b5642e5dd61c33b39769052d9d854dce902f476e21f96c650b463b7bc3d0ff2996b65c57831f8b7c0fb915f4dd7226ac955cbc7dfb03f9b758dd3e0dfce2e0e580c91a30c783ff567b17f12dfd5d3137646e20011cdcaae11102dc716886cbf123c09488b173636abd54e962caeec97d5eb940682e703b730f61562cd14b9e6561b5e93f60cd0e1e86d1a1b4719c5b508242bd6b2d9a548f59bbb875075969ef2032f3196b8aeccc45a44d9dbdaf878ed16f1d855e8918ed65a45ee5c7fa32a1ec6932a159cfb50ffc87be06dfcf7228ae8870ccd357fc656e33fa4b6b8b7d1a7215553cabacc70a39c980b971e51a17ed6318b43b29bb:df09cb9b878d3dc9e542dbac28943e28e41dcecb92cb7ea44009885e46499743330561ba1d36aedd467675fdca2baaa4701b6fad979fd839c470d13c82daa9057876a3f4eb69bb7e54e9ff954ebd3b10b93a4c1afeae92fa03c103cb6313a201c5b33a9a7223755cb510e25ec582b54e81b84956f6c53f1f08a63bf0c4a261af450e523fe8f61ddb3c0eeab8751072688801b2a473b71a2e38708da68c2f37925cb05a20c4283b3af97b6f0ba65a5403554375e215d9e3aa1b0f9fdb0f849923edbdaa0ab481c545a5df8f51d1f68b223507ea0eccfaebb5fccf5e3dfa65a44eea504568a88180a060bb06c51557b81e667b4b04e3210fa4c379876c49f3e56bf2be1cf519a7418393d240dc8a224c6c38ac2ab9d8fadfc5362030c7930c3ce7795b147c26c8a28c653429d90a173a86a8b18a009e62aef6eca95d39bdbe45647778a2532a415ae19bad231129127842fe1d0f11fab4a1cf0b17e498cd5952c939e090090287b144895dff00cec8d6aedaf62481a41783e021082ce352063e62811fd99990104d8a46cdcaee2bab458e5247fb023e923330a428c7bcfd20b08f520e8946dd658347352ae0c4be73c3d5eccd11149f3ab7b8052cfd95c35d4164546f5d8f377517a7f432c0d5563a7bcc7bd119d3421dfebaae844599b29b383bb8d5dbf140d9bd47a078b7ae7c6aa87b1e29236c9fcfd654b7f809794cccb261588e18dec6c4046a934067d0dfa03791d03d83b718ac4d24dce785a3028de0c9592dba7c5c5845184afc9c0dfcf94095860f0eb802ebea20178e78b5642e5dd61c33b39769052d9d854dce902f476e21f96c650b463b7bc3d0ff2996b65c57831f8b7c0fb915f4dd7226ac955cbc7dfb03f9b758dd3e0dfce2e0e580c91a30c783ff567b17f12dfd5d3137646e20011cdcaae11102dc716886cbf123c09488b173636abd54e962caeec97d5eb940682e703b730f61562cd14b9e6561b5e93f60cd0e1e86d1a1b4719c5b508242bd6b2d9a548f59bbb875075969ef2032f3196b8aeccc45a44d9dbdaf878ed16f1d855e8918ed65a45ee5c7fa32a1ec6932a159cfb50ffc87be06dfcf7228ae8870ccd357fc656e33fa4b6b8b7d1a7215553cabacc70a39c980b971e51a17ed6318b43b29bb: +ef12df479d983ad96e8ba65330b36d49aadb983164e1c0b452b560ded1d08d60f761cf2826927a7cda8cb04faa2c59f8425a8f7d398f76e867021c951f073809:f761cf2826927a7cda8cb04faa2c59f8425a8f7d398f76e867021c951f073809:e58f34daea755ac4e41333d6f0ed0135f7dbce50309bb1956bc71acb12c77067a647ffd86aa5870c0c0007e8f995a22b88c467de225444544201c557495e253e3319cc5ca376d3e7cc1eb467346e52ad956a6fa733720b17117b5b7585e4d559409aaefa95580f91e502015f497c5cdcb7d4d561f544efa35c1e2a53b72bddeceec2d1050f177d480f687405664dfddec06eee4bd147a912fdbf74f2a95d1fd1e11268694ce4d4ec4fffd6ddb3254d360f236fab4d1a17f8d0d1a511f944692f239639ae03d64facec6538427ab71f7127f4a276f9bc45bba611dfcce6446cc13968976c8bb6d6fe2106d705922dcac956966a76d48f2aff4b86514e39a67e1643fcc321858024e693189833c8ad59b4b625298ebafe64626b480f326f1340723cb3d383f4fccbfc237a3f4c4f7ecf0ba436b32c2fe35179da93111b48cc9ea24202bdc1b2fb60a4319dfd9864470f73f54137206e0bf007f5ae88a88747008a60f4789ad167724f179c02b63aed002573d28a6bcf88e07ce8daea5d5f1acf487b4c5c16c2bfe11231ea5ea763e8f332cc73da1b2f8c198ea8173fd33d4b2ae69e5d4d1aadddf2fd821b85be45151962d1f99df81308618852ad7cf41d72da08a1b39df7d8b994b4ddff37f9dfe8f38ce30e91061d95d58f7ae826b02385272ec09f01a7b3e4b391d09bced665dad69505b419da8481bc3792bf8b8e7ad64b63f245666c8c32fd5c1b1b48c9951e1c21a1eb5f507cff137cfb862c2cc98766e878c930a083828c9d8db18bf16716685f39d6572a8ca8b2a514f77003d4e75bc154aebf14103778f365b1c3f03541ddbd07d6e23e56762d971eb02983e93c4e01ba4b8a2178928c4337d302f31c9ccb75b249a82dc96821e95a03ab6b770df2c3dfdbf1fe9773f8bc1bc5b3afa0440b102578f3d213c8d019cff124f75ce4accc8c667feb27c751a6120074813104e0cd070c9f5e451dccff4c80d71107c975abfac07d4d270c727d8a2fec349b533968e271892d2b62c125fb7974603c305ea3bfa30fb610fc5a23eb68a8406444391a521337:4c8010866d9115f05293b934cac68104cc2c3437568cb9d5c570b1a8bee706603075537033bd708a9c9f3d1e2519a915b1c4ae4ccddfcf0ed0c049d342a02e02e58f34daea755ac4e41333d6f0ed0135f7dbce50309bb1956bc71acb12c77067a647ffd86aa5870c0c0007e8f995a22b88c467de225444544201c557495e253e3319cc5ca376d3e7cc1eb467346e52ad956a6fa733720b17117b5b7585e4d559409aaefa95580f91e502015f497c5cdcb7d4d561f544efa35c1e2a53b72bddeceec2d1050f177d480f687405664dfddec06eee4bd147a912fdbf74f2a95d1fd1e11268694ce4d4ec4fffd6ddb3254d360f236fab4d1a17f8d0d1a511f944692f239639ae03d64facec6538427ab71f7127f4a276f9bc45bba611dfcce6446cc13968976c8bb6d6fe2106d705922dcac956966a76d48f2aff4b86514e39a67e1643fcc321858024e693189833c8ad59b4b625298ebafe64626b480f326f1340723cb3d383f4fccbfc237a3f4c4f7ecf0ba436b32c2fe35179da93111b48cc9ea24202bdc1b2fb60a4319dfd9864470f73f54137206e0bf007f5ae88a88747008a60f4789ad167724f179c02b63aed002573d28a6bcf88e07ce8daea5d5f1acf487b4c5c16c2bfe11231ea5ea763e8f332cc73da1b2f8c198ea8173fd33d4b2ae69e5d4d1aadddf2fd821b85be45151962d1f99df81308618852ad7cf41d72da08a1b39df7d8b994b4ddff37f9dfe8f38ce30e91061d95d58f7ae826b02385272ec09f01a7b3e4b391d09bced665dad69505b419da8481bc3792bf8b8e7ad64b63f245666c8c32fd5c1b1b48c9951e1c21a1eb5f507cff137cfb862c2cc98766e878c930a083828c9d8db18bf16716685f39d6572a8ca8b2a514f77003d4e75bc154aebf14103778f365b1c3f03541ddbd07d6e23e56762d971eb02983e93c4e01ba4b8a2178928c4337d302f31c9ccb75b249a82dc96821e95a03ab6b770df2c3dfdbf1fe9773f8bc1bc5b3afa0440b102578f3d213c8d019cff124f75ce4accc8c667feb27c751a6120074813104e0cd070c9f5e451dccff4c80d71107c975abfac07d4d270c727d8a2fec349b533968e271892d2b62c125fb7974603c305ea3bfa30fb610fc5a23eb68a8406444391a521337: +f731317cf5affe58704c4d9497ae860bbf739d0fd96b7c02efb6777b3c858a19d7d638aecce1461e314255aa29d9a6b488aea1396e9682695a470eff23f3ed84:d7d638aecce1461e314255aa29d9a6b488aea1396e9682695a470eff23f3ed84:16f51c59e9aefc26b0da5e0085eb2e2f1f856def9725769e3af12f860905ae133f65074da76dbf25c67f6257d2dc66c05f9b31ae177b69929fc183b588c519bca14796a0896d2905fd942d7ab4a3fd9541a5529f729c5851419b5fbef7b134d6762eb97e8a951a8ff52aa0d7e67444d06b07aa55e4eb9ab892f47bfd111df5b62f6f3fd1a5ed84125feebb77da637c05d5265ced113dfe8782dbd1cecd2c6c032b8fa8855b3ae78de74faa5aa20a761463c2a30be66bd38cdec75f8957cb94c113a45d546daf475d89aa1482f8d2803a23c939202015a08e94b132728fbe8f6019d7168a08a5930170e5639d110e4739db85e61e64495944b5423a74ad5a8a0a510612ece655ce18864051525b908e0b19290abe8b1182c48c700d350515fd349956e8087327f30b6fc3f131c2144abb3f0e9ca331172b35064a82811a68e2cf36b43e3ad2e8dfa5b1cef50e2a60293fc5f635c9a9998d8c1ad296e7c78fc0582022d63067186b65e764828cc0f5f7632d5eef863e6c6d90e38ccc87d7b747fac8491d632cf7f54b9a9eed16eebec01b6cc33d2463f7f950d828b55ee3f77cbe974f48948eb757aed4e0dbb00ad95ee01323486eba3c8da886ed7f57bb400d63a1b2ebeaa2e70adf0379e3393001ba626c0dd54b7f0c9a25aae6c9875d4e7622f3ed428fb3124b29c5db9a7ef16ebddd6805f095f5e769823c43f262868ff43e3e0525746d9497af124a01dff61ec718af3b5bb746fcc08aebd16684d456ae7932ff5ed7d6b0f1b25c7adeef598b5d58877590ac1dc05975156796998774081e5b66822a94a6a802c3a2cd9f489e1628aaf4652be1184b0fc7c5ee7f97ce08b9233b4b83d9367be5f4aae9782593a35265154dea4c375c16f0caf6dc4594d2bdbfc3375bb2a0432c482f13941ce2aaab4d83e74d116f5de4ab28f8dc3d1cd19d271e56e10398bd1df5c870fcbf93a7d1df3939547c107bfd90643f6f5001ae7e06397ae1a271bb82a1f38e097bec667466b80ee3e50dd4fc9d5d54f18faf7a5b55a8834594ef0cb7e508bbd28f71fd34235bbfd3:2a4fea98f9240171a1823f2f69352062672e6c6e6652d388a87714d647995df75b6e1ed1746af2adf4e806135d60754e60fea032128e35abc1f1615181125f0b16f51c59e9aefc26b0da5e0085eb2e2f1f856def9725769e3af12f860905ae133f65074da76dbf25c67f6257d2dc66c05f9b31ae177b69929fc183b588c519bca14796a0896d2905fd942d7ab4a3fd9541a5529f729c5851419b5fbef7b134d6762eb97e8a951a8ff52aa0d7e67444d06b07aa55e4eb9ab892f47bfd111df5b62f6f3fd1a5ed84125feebb77da637c05d5265ced113dfe8782dbd1cecd2c6c032b8fa8855b3ae78de74faa5aa20a761463c2a30be66bd38cdec75f8957cb94c113a45d546daf475d89aa1482f8d2803a23c939202015a08e94b132728fbe8f6019d7168a08a5930170e5639d110e4739db85e61e64495944b5423a74ad5a8a0a510612ece655ce18864051525b908e0b19290abe8b1182c48c700d350515fd349956e8087327f30b6fc3f131c2144abb3f0e9ca331172b35064a82811a68e2cf36b43e3ad2e8dfa5b1cef50e2a60293fc5f635c9a9998d8c1ad296e7c78fc0582022d63067186b65e764828cc0f5f7632d5eef863e6c6d90e38ccc87d7b747fac8491d632cf7f54b9a9eed16eebec01b6cc33d2463f7f950d828b55ee3f77cbe974f48948eb757aed4e0dbb00ad95ee01323486eba3c8da886ed7f57bb400d63a1b2ebeaa2e70adf0379e3393001ba626c0dd54b7f0c9a25aae6c9875d4e7622f3ed428fb3124b29c5db9a7ef16ebddd6805f095f5e769823c43f262868ff43e3e0525746d9497af124a01dff61ec718af3b5bb746fcc08aebd16684d456ae7932ff5ed7d6b0f1b25c7adeef598b5d58877590ac1dc05975156796998774081e5b66822a94a6a802c3a2cd9f489e1628aaf4652be1184b0fc7c5ee7f97ce08b9233b4b83d9367be5f4aae9782593a35265154dea4c375c16f0caf6dc4594d2bdbfc3375bb2a0432c482f13941ce2aaab4d83e74d116f5de4ab28f8dc3d1cd19d271e56e10398bd1df5c870fcbf93a7d1df3939547c107bfd90643f6f5001ae7e06397ae1a271bb82a1f38e097bec667466b80ee3e50dd4fc9d5d54f18faf7a5b55a8834594ef0cb7e508bbd28f71fd34235bbfd3: +498e5a21a9b0c347ba83a47ac10069457f5783c2e1e6e4640045e594b1c69332fb3948c81199569105cc1b7d9ceb3b41a343bb00575538592e0984f4f4710abe:fb3948c81199569105cc1b7d9ceb3b41a343bb00575538592e0984f4f4710abe:e4fbea864aa51190826645d2f772cb0f9eddd3034473fa3177c7af9a5d41e1a73ad5784c7096559fcddb7b7c85891cf24e82c588d74774ffcac0c6b4eebc2f3fa43e9d45f259d67564030cfeeab9236c665b650af0c92c875189f5f9383504b15360a0b9a5a00da31f635b96f6c73ef47b6b06f02811d1d19c2e8e53550ce22e42ec50a1eb2ea2f4cd03c442d4aa436894238ceb1835fe99b240358aa0562c249698a3f123c2c17e591010bd6fdfcbd7dbe70b04520502ece37a9a1dfa1ae3370417b004217a5b8fe9903c9a3b9f4b6d5c46c0ed0c538cec22f2dfcb2a280a42adc489cf2e062912be9928f0c060891e432091177526f1b3a968069d4a57ade828559810ae0360681ff99329fa0f59e7e59cdf87f9f33c40e97031b9f81d48fc12286efbb3d4e5a62ef57bc0d52d533b99c5106aa79cfe1793a908518596c383483ec49ff98ec557bfff7490a46daf6714f2c2c32f57932ca0d730f03f381d69decdbd9a7a6d4afc62406543c8ebe90ac76e6afabdb82492a206a369e04286d313e11107d8cd9b4bf68f815dba4e990b049d79216d3653138342cd118b130f66b006f3d89ac3cf89837048b0f8a62d94051d2eab891ac5f47888879d88e546676d1daeeb4d175d3f04a9d74ffcdd47746016f84ad0d112afb59ad12187e94f22535d77e9e0516fa42185c197ba774b393227f741fe68273f423fb0e0e0474bfdaf2da78aeb1cd5b98c1dc0832124742a4754125fc78b19c559a5b3f7711e068c440cc0469a1cfa5c1864be18735aa8bcd406c4371eb857754d908bf379b91fcb24e34396bf87c19a04a83d59dae71f3f3839829d06221301ef595696e719d56b79520a0e509929833b1d804a6a0ea40400bb45028ce5d36933883e17406e27a8109057b1a1a5e5da210a6921994f467ab41aa8f0d88775a8a8ebb4ec77d7c80e45a7bb422a4c00c90583911465e6b5f0fdcdeab72871ca542e1d1a2ca94df4ed2eabf90ded0045290324a9fffb30145470209f3826580989349199dc5ab8d4a25df7a0529cf91471e30842abfacd44ab781dfc1395:2860830ccd1d41d95076816a398424f7b739c49fdacf5654529da85fe3565584f6aac2614c63f774b61db9081f1410fba8e50ab3b4c39dc06314243f3f0d8e0fe4fbea864aa51190826645d2f772cb0f9eddd3034473fa3177c7af9a5d41e1a73ad5784c7096559fcddb7b7c85891cf24e82c588d74774ffcac0c6b4eebc2f3fa43e9d45f259d67564030cfeeab9236c665b650af0c92c875189f5f9383504b15360a0b9a5a00da31f635b96f6c73ef47b6b06f02811d1d19c2e8e53550ce22e42ec50a1eb2ea2f4cd03c442d4aa436894238ceb1835fe99b240358aa0562c249698a3f123c2c17e591010bd6fdfcbd7dbe70b04520502ece37a9a1dfa1ae3370417b004217a5b8fe9903c9a3b9f4b6d5c46c0ed0c538cec22f2dfcb2a280a42adc489cf2e062912be9928f0c060891e432091177526f1b3a968069d4a57ade828559810ae0360681ff99329fa0f59e7e59cdf87f9f33c40e97031b9f81d48fc12286efbb3d4e5a62ef57bc0d52d533b99c5106aa79cfe1793a908518596c383483ec49ff98ec557bfff7490a46daf6714f2c2c32f57932ca0d730f03f381d69decdbd9a7a6d4afc62406543c8ebe90ac76e6afabdb82492a206a369e04286d313e11107d8cd9b4bf68f815dba4e990b049d79216d3653138342cd118b130f66b006f3d89ac3cf89837048b0f8a62d94051d2eab891ac5f47888879d88e546676d1daeeb4d175d3f04a9d74ffcdd47746016f84ad0d112afb59ad12187e94f22535d77e9e0516fa42185c197ba774b393227f741fe68273f423fb0e0e0474bfdaf2da78aeb1cd5b98c1dc0832124742a4754125fc78b19c559a5b3f7711e068c440cc0469a1cfa5c1864be18735aa8bcd406c4371eb857754d908bf379b91fcb24e34396bf87c19a04a83d59dae71f3f3839829d06221301ef595696e719d56b79520a0e509929833b1d804a6a0ea40400bb45028ce5d36933883e17406e27a8109057b1a1a5e5da210a6921994f467ab41aa8f0d88775a8a8ebb4ec77d7c80e45a7bb422a4c00c90583911465e6b5f0fdcdeab72871ca542e1d1a2ca94df4ed2eabf90ded0045290324a9fffb30145470209f3826580989349199dc5ab8d4a25df7a0529cf91471e30842abfacd44ab781dfc1395: +c24cbf401ad03bd88dcc7b519ecf624db2223e990289309e1e9f1f8f6127c6c9a74666f357209f7189903788f107563e50c051c3d40c3f3dad10d3c3cff1e678:a74666f357209f7189903788f107563e50c051c3d40c3f3dad10d3c3cff1e678:e7fa359e6a09b2c54aabed3bbabfb72853a805aabcf4d18ddad39f03f34601e55b6ce263c9a3ca6a3e5f1425c821928c61e7f750919bd3af32bcb7b94d459a7a9a35f61c941792e2cc2e4327beb344a841a07f32068af102b3de61eab64ef6d5e69062e393ab5edf6ac9ef7b38d49a01bef0003f421174c8885975c01832899c3135e7a86e5b55d9b1328bb4289b5c40200f49e5523b3c461dc7175e1465022297c3d380f2b1fef39cb82c00fd160f447eb51263fa25b4df0fca41ec0ca2ece7472201af86c3038c49df099a9aefa1f88d0edfd17c0b3c86046629c09454054aa0fb2c6949dd9c130185dfa5d903891e08742cd0429403f57f4052158b2f401da4756854e4aaf024221e37513cf677ee6a0b159f501d377ea32eb71e778004f27203cd6d553fda5d65e1879477046f3ea3d1d75c9d0d30311456709cc7f6ab68c7b0d52be40f04cf655655323285318329e84c6a5b07e0ceed5f78f7f1fa6229bef878793c584728abf4510b7f27794b5942916254c589a09c8e911f0b954211a63699a752147f2a4e1a18956644bea2ca2692ba182280e04a72dd89b0d1268500938f347bf43f2a242ee9b9a6baac9b350d656fb19ec834abe3164440f2d2071fe5e32c8e4cf905539b839ceeca2620fcb2a087f780e6c7f5e05c506888250ea7c856fb30983200aa8f78fc1771054ada0f3fac38ae2f33dc4a4f851b76ed740c0962a76a4de44080dc620a44ad8f23d3462b792ab3afb19cb8a9f4d9e59ad765a771899da8cbec89e5077e85c0c93126376c941bef1f8bb992d3a35f270725846fb252f8b5fbb7567e406a1b53b619769e632b2b4087cd4c276e5d58ff2b56e89edec48ce53a52e329ca1559538f10902c01a85fbb3cd72e6b8291e5fe639bee9d47d34c249a7a07d7a1427a01f63d60984c450bef819b19f65e2614fd9c2fae7b9231a0bca414ed94a5ee7e66327d2a99c84878b7bee087e891f253fa1fece313648c06c45db2d9f3bc8599937b752d38ce5063d0ed9a43ec9d4015893d43bf5b2d1c60478510468968b796f0153789595441722a:581e6c85aec623b62b3d4c9bc9c77759d5492722e252d44c1f8ada9da2ecc67c17083273aa091bbac046ae63c78893152e14d926c41ae35f0e6e3959496b1306e7fa359e6a09b2c54aabed3bbabfb72853a805aabcf4d18ddad39f03f34601e55b6ce263c9a3ca6a3e5f1425c821928c61e7f750919bd3af32bcb7b94d459a7a9a35f61c941792e2cc2e4327beb344a841a07f32068af102b3de61eab64ef6d5e69062e393ab5edf6ac9ef7b38d49a01bef0003f421174c8885975c01832899c3135e7a86e5b55d9b1328bb4289b5c40200f49e5523b3c461dc7175e1465022297c3d380f2b1fef39cb82c00fd160f447eb51263fa25b4df0fca41ec0ca2ece7472201af86c3038c49df099a9aefa1f88d0edfd17c0b3c86046629c09454054aa0fb2c6949dd9c130185dfa5d903891e08742cd0429403f57f4052158b2f401da4756854e4aaf024221e37513cf677ee6a0b159f501d377ea32eb71e778004f27203cd6d553fda5d65e1879477046f3ea3d1d75c9d0d30311456709cc7f6ab68c7b0d52be40f04cf655655323285318329e84c6a5b07e0ceed5f78f7f1fa6229bef878793c584728abf4510b7f27794b5942916254c589a09c8e911f0b954211a63699a752147f2a4e1a18956644bea2ca2692ba182280e04a72dd89b0d1268500938f347bf43f2a242ee9b9a6baac9b350d656fb19ec834abe3164440f2d2071fe5e32c8e4cf905539b839ceeca2620fcb2a087f780e6c7f5e05c506888250ea7c856fb30983200aa8f78fc1771054ada0f3fac38ae2f33dc4a4f851b76ed740c0962a76a4de44080dc620a44ad8f23d3462b792ab3afb19cb8a9f4d9e59ad765a771899da8cbec89e5077e85c0c93126376c941bef1f8bb992d3a35f270725846fb252f8b5fbb7567e406a1b53b619769e632b2b4087cd4c276e5d58ff2b56e89edec48ce53a52e329ca1559538f10902c01a85fbb3cd72e6b8291e5fe639bee9d47d34c249a7a07d7a1427a01f63d60984c450bef819b19f65e2614fd9c2fae7b9231a0bca414ed94a5ee7e66327d2a99c84878b7bee087e891f253fa1fece313648c06c45db2d9f3bc8599937b752d38ce5063d0ed9a43ec9d4015893d43bf5b2d1c60478510468968b796f0153789595441722a: +8b3dcde4abbf4e6211c4a51c4b026800a8a2a061cb38a2ecc7c9cf113f9270bf514535580f0de359bb0d41f2efddaa04c2ec950119f31634b2c1a32f195f6968:514535580f0de359bb0d41f2efddaa04c2ec950119f31634b2c1a32f195f6968:481425027da672b6f26c91b80e55582caef47bb15a2de8fca852221785180b20a7fd6d4907b5881cc1d6e39ab9612cc74d6977e9141f7087bb27ab3084a26285586f8411db1f503adf52dcb25ab8fffd2ec1504c1777b9d6dd4a29e2019e5cbae1b7eb26f95bbe07d90c2f6fb0884a59a8d58dde5116edc3bc349d37c160b27befbe5a5c181ce7256392354d221b58c47eb0bb10929e7421795f4b7a7c275edd08c088568772e993218dd6f3c2cb4ac657a0a3f91f3126b991adf6cbe7d1b19b8cd83be3602ed18f039633fbd2387bda69e2cf0387d8644d97b303fb00639aeee7ae463f6fe1a2c4b89aeba3e9094c11fc29114b20283f287c6dd28cb098dae8dabc48e85bb59c0dc6e78c956605cb7cf06942353e7a22e96f80a37a66f718d9e4db8c52452aa0a35772e81ba2b303205b412dd2bfc15ce9b436f99fbb32126b63ce9cb43199f157d81751a7c4937d13af4c582952b5d606b555b046bf1de06cf39b63a80287371803609a387ee80f3a5d88b9d6219650ed17d3cc183b2c70d5eb94e3bc52aea7aa7f53be0e20b8972f143d8e20162e803edb4aa83d5553fdd553398b0fa176b959cba140d6e980c9251b0fa0b65e908417f82f451ff9f2de6b9ca5e3b5f41ba40d05a54f3dab4886aacca05c9c2798139a4cb33e96a91494749910a17ce8b392fc0fc7762974d79d33db924bfef8655a723776ff87f950fdc568b1e526534541f572723b840663c19188c424f7c489235a424b09fe25c30727ea1cb04953d706d68bfe12100ef6f64c35c6b8de67edf0e3ad014a400e821ea34024321999867b43c82c450184b78f7425cebd7319dc6f65d360665dfbe7c36674dac3a54e96da910c02d3640780b22d512ca0e3ca3587b94ea9fcd7a31b4af69fd6207c68fed25f89921c1cdcdefd1c090204492bff9bbb52e08885829d012bc2dfb4fe8c35e59cd13bcb8ead34193c40b03ee4d825ee1322ff4ef071279574cbaee7c07f14be606b9cd0e261111ef20d9681d76cf78c89a8c397d6b8dc778f4984166ad5df3a81aaf2e6de09f700195ae2c1d4609647:4f3d4d228503017e74a6bb58aafae35c3f37bdee4ff6be2e6240b5082feddb222735e12f31e056fa685447e5384803007ea7910e605c1b78118cd5acc587a606481425027da672b6f26c91b80e55582caef47bb15a2de8fca852221785180b20a7fd6d4907b5881cc1d6e39ab9612cc74d6977e9141f7087bb27ab3084a26285586f8411db1f503adf52dcb25ab8fffd2ec1504c1777b9d6dd4a29e2019e5cbae1b7eb26f95bbe07d90c2f6fb0884a59a8d58dde5116edc3bc349d37c160b27befbe5a5c181ce7256392354d221b58c47eb0bb10929e7421795f4b7a7c275edd08c088568772e993218dd6f3c2cb4ac657a0a3f91f3126b991adf6cbe7d1b19b8cd83be3602ed18f039633fbd2387bda69e2cf0387d8644d97b303fb00639aeee7ae463f6fe1a2c4b89aeba3e9094c11fc29114b20283f287c6dd28cb098dae8dabc48e85bb59c0dc6e78c956605cb7cf06942353e7a22e96f80a37a66f718d9e4db8c52452aa0a35772e81ba2b303205b412dd2bfc15ce9b436f99fbb32126b63ce9cb43199f157d81751a7c4937d13af4c582952b5d606b555b046bf1de06cf39b63a80287371803609a387ee80f3a5d88b9d6219650ed17d3cc183b2c70d5eb94e3bc52aea7aa7f53be0e20b8972f143d8e20162e803edb4aa83d5553fdd553398b0fa176b959cba140d6e980c9251b0fa0b65e908417f82f451ff9f2de6b9ca5e3b5f41ba40d05a54f3dab4886aacca05c9c2798139a4cb33e96a91494749910a17ce8b392fc0fc7762974d79d33db924bfef8655a723776ff87f950fdc568b1e526534541f572723b840663c19188c424f7c489235a424b09fe25c30727ea1cb04953d706d68bfe12100ef6f64c35c6b8de67edf0e3ad014a400e821ea34024321999867b43c82c450184b78f7425cebd7319dc6f65d360665dfbe7c36674dac3a54e96da910c02d3640780b22d512ca0e3ca3587b94ea9fcd7a31b4af69fd6207c68fed25f89921c1cdcdefd1c090204492bff9bbb52e08885829d012bc2dfb4fe8c35e59cd13bcb8ead34193c40b03ee4d825ee1322ff4ef071279574cbaee7c07f14be606b9cd0e261111ef20d9681d76cf78c89a8c397d6b8dc778f4984166ad5df3a81aaf2e6de09f700195ae2c1d4609647: +d4a7a9524d30a6337c0a0be95ca90591de9888038e3e59e1b25a4181ef9466299fc3ebd139cc5b7c0e05af47bff6619b812815bb01ceec392a3ff0aec3811d2c:9fc3ebd139cc5b7c0e05af47bff6619b812815bb01ceec392a3ff0aec3811d2c:171980c03fdf7a727bd5bab3ba0945e6ad5faf0a7f506a56d1d0edd9a306b3158d843266d3091fc1e42281df97559a2201f5bdddfe683d0e1028d1d95b2f313b484c392ffdb1cdf88508afde3d6fd2a12888bacedeb79ff3db40c9ac0ec3fb901b228698adf8d845ff4fce10de55d42436dce930973a34be05d1401f334d4ce8e3a793799eafdb94d0f2ab0950b079e6653eeb499fc7447ccbeeed8dbd5456808cd7a38f9a15a2a9c738d61334cab8ceebbbf4a4814d94c61859178784604e0c2154597e72cf587cd1f5dafe5922051890e76d616d8cd5b05d6478d0626ea83ce808c46143e6fb06b4182d228da8f6d4139eca5b8f3b1b98af68c59b4b5a53c136ee90432aca2bb915529d26367949826233b43e55804b55fc9f215eb0b0b79291465bb34edaeadffabfe6cf41bc07b5dd4d0142f0361f058ee1b3b9fcc196eb9b35b134be3d1d232004489e8f6993f625a63015bcd3f1e87588324858ccfb770dddd894bf297bd763ef5828e21f5c89aa98cfbc1c082dd7fbaa4307bda40b4a758ca8f39f4e4aaed309041268dbcf0af32de0d7fa90a523963b780b6a932cf89499025f0e0d0474c74348947510e6c5ec7c9e05066eeb4a73520c3d927c39ac26ad7596325b2cc47c5e82a775455b7af03120b1cfbfd6ec3fc0c3be6078b00cfdf8342ae8bf147159f50e9d564e2f68306dae3caedd1019f323c478a1e1f67598dd834bd1d1a8733fd7fdd8a876526c531518936edb72d01656b344c7d65ac1cee37ce5997ba48d3f4d064d88057efe9a482d9e00ab5caeb5aca2d660e337bd15487365697956a5e47b02abdc30d8e353fed4e1ac41d2bc2120021143635935c620186a522bde54be0446fbd2dc88b56304b3a64227d0acd5f85a6b6787a3adcf2d7cfc86c634b4d7ab4315b97de9e666cff3ff1b88f3295e7bab9e9fd46fafddb4f5fac51cc0170129c651b4ef4d3950d6942ff020d1668a528bde1da936c0ec1ae09e84f8205861fff491502a872c8154a96e7ea25eda955a7fd2e4b4c7a8d273f60bc74fab7b4968ca6f75daea5040f839fd56c2a980:d15788bcd88d1d81b9e61d4fe26ea49e66819a59d2ae4832321b814d5062fadb87807db6852e1d8295e31a291b1e785d01d834895f88f400df8832c1607b5b0c171980c03fdf7a727bd5bab3ba0945e6ad5faf0a7f506a56d1d0edd9a306b3158d843266d3091fc1e42281df97559a2201f5bdddfe683d0e1028d1d95b2f313b484c392ffdb1cdf88508afde3d6fd2a12888bacedeb79ff3db40c9ac0ec3fb901b228698adf8d845ff4fce10de55d42436dce930973a34be05d1401f334d4ce8e3a793799eafdb94d0f2ab0950b079e6653eeb499fc7447ccbeeed8dbd5456808cd7a38f9a15a2a9c738d61334cab8ceebbbf4a4814d94c61859178784604e0c2154597e72cf587cd1f5dafe5922051890e76d616d8cd5b05d6478d0626ea83ce808c46143e6fb06b4182d228da8f6d4139eca5b8f3b1b98af68c59b4b5a53c136ee90432aca2bb915529d26367949826233b43e55804b55fc9f215eb0b0b79291465bb34edaeadffabfe6cf41bc07b5dd4d0142f0361f058ee1b3b9fcc196eb9b35b134be3d1d232004489e8f6993f625a63015bcd3f1e87588324858ccfb770dddd894bf297bd763ef5828e21f5c89aa98cfbc1c082dd7fbaa4307bda40b4a758ca8f39f4e4aaed309041268dbcf0af32de0d7fa90a523963b780b6a932cf89499025f0e0d0474c74348947510e6c5ec7c9e05066eeb4a73520c3d927c39ac26ad7596325b2cc47c5e82a775455b7af03120b1cfbfd6ec3fc0c3be6078b00cfdf8342ae8bf147159f50e9d564e2f68306dae3caedd1019f323c478a1e1f67598dd834bd1d1a8733fd7fdd8a876526c531518936edb72d01656b344c7d65ac1cee37ce5997ba48d3f4d064d88057efe9a482d9e00ab5caeb5aca2d660e337bd15487365697956a5e47b02abdc30d8e353fed4e1ac41d2bc2120021143635935c620186a522bde54be0446fbd2dc88b56304b3a64227d0acd5f85a6b6787a3adcf2d7cfc86c634b4d7ab4315b97de9e666cff3ff1b88f3295e7bab9e9fd46fafddb4f5fac51cc0170129c651b4ef4d3950d6942ff020d1668a528bde1da936c0ec1ae09e84f8205861fff491502a872c8154a96e7ea25eda955a7fd2e4b4c7a8d273f60bc74fab7b4968ca6f75daea5040f839fd56c2a980: +d08f4babba3b5365faf738795c9da45db1862cb28b93eb6635d1320da0f4d937ef31b454f734e52b3438ee2f1cbc35631b1969de54ac98fe4633f2f500ac8712:ef31b454f734e52b3438ee2f1cbc35631b1969de54ac98fe4633f2f500ac8712:a394d8854ceb5c43afee1a48926bbd6685aa8aecfdcf854133333974d624bf2f1f9c30f005bbf34cee3afe2b290600eeae6f1dd12a0c346fbb2ab9c916c5d5d80dcd87887875a0ac847678039fdcd3a9793541f5d675143a6abadc3b18f0fef5108c19c2dbfb59710eef9866a4f3f297a09ee48c6803007dd6ba8fd4be841cfb10ff0514c30fc4dd49a3cd43bbd16e460443a11afe649e901d63d89af598aa686b2f607ec11f35e17a798a4213b75a38788da4f27cf2b02caddfe61c3729a87ec6e6b098f68e7aed28a800c484dfa0130401208f986d792f54635add2848e151262a365eb21e2727191e1f700f3bf5c73b0fb4c546d0048a155c18717920fc0425c8c8fa8f167c43a277bb366e0ad702c89bc5aa06fd470943be05cb9e3259787229714c30a4e87b00a633aaf7be6b5875010d12e107c9a5261ca562d67025bea0fe223463edb92ea01cca92c44ff24da9d8a80a6421f3d4135d647d1bb0fd988c46c8a170ceb4f33fff9c0ffb6abad1092c84dfad8290898b249516a292e8da96fd51a81005eecfdebb05933099277d073a480c3f9eb8aa11968c4d8dc0787a9aec3e0527b7fe4c0635411335a1811689e88f6d5ced0d40d6b48b7f2d992952934894153076a8d37372fa00d9cefc5cf8c26adb5acf325a01cd005ab8d474a52d67114078c6516aef804bba19b887a28ed5e46ee9995e5ad3a82fb9cd93283433680921114b4d9af8fcb6b2b535839c36de8df12b17ea6ddcfcb3334ff40e6cf04ccd5ca6403ba0b62b4cb71bbde91d8babda69152c9c93ae769b5529c8d52fd9a6909a15e1a0601a714649c96ec996c1706d1021b97487980d7b2c2a39bbb0e470d8e46ac4aa609a0922c9bdc01612eadeaccd5fa523b2a8d0e62ffe56281647d61fffbbc840535745d144259cc81300fe99dfbffea6b0b9bcd28473982d32e93ed46634a9987906d6f48939d8dfbfb37d33b888db608cb2ffe39a8cf67b72644611c7d32a4a8df612468cd5e5d75fbba79e638aa1daa28c4e0eeb9a637ff8a08b65f7a7612414df76bc7b0b56b5537d666facfddaf65af1:acebe4c86fa9fe2c1a5c576ac0501e8ab0f640fa40380536fcf95059d53d4a3555d220ac363587175e4bde163c0d00650a12963d46766c99bb62bf7573e2870ca394d8854ceb5c43afee1a48926bbd6685aa8aecfdcf854133333974d624bf2f1f9c30f005bbf34cee3afe2b290600eeae6f1dd12a0c346fbb2ab9c916c5d5d80dcd87887875a0ac847678039fdcd3a9793541f5d675143a6abadc3b18f0fef5108c19c2dbfb59710eef9866a4f3f297a09ee48c6803007dd6ba8fd4be841cfb10ff0514c30fc4dd49a3cd43bbd16e460443a11afe649e901d63d89af598aa686b2f607ec11f35e17a798a4213b75a38788da4f27cf2b02caddfe61c3729a87ec6e6b098f68e7aed28a800c484dfa0130401208f986d792f54635add2848e151262a365eb21e2727191e1f700f3bf5c73b0fb4c546d0048a155c18717920fc0425c8c8fa8f167c43a277bb366e0ad702c89bc5aa06fd470943be05cb9e3259787229714c30a4e87b00a633aaf7be6b5875010d12e107c9a5261ca562d67025bea0fe223463edb92ea01cca92c44ff24da9d8a80a6421f3d4135d647d1bb0fd988c46c8a170ceb4f33fff9c0ffb6abad1092c84dfad8290898b249516a292e8da96fd51a81005eecfdebb05933099277d073a480c3f9eb8aa11968c4d8dc0787a9aec3e0527b7fe4c0635411335a1811689e88f6d5ced0d40d6b48b7f2d992952934894153076a8d37372fa00d9cefc5cf8c26adb5acf325a01cd005ab8d474a52d67114078c6516aef804bba19b887a28ed5e46ee9995e5ad3a82fb9cd93283433680921114b4d9af8fcb6b2b535839c36de8df12b17ea6ddcfcb3334ff40e6cf04ccd5ca6403ba0b62b4cb71bbde91d8babda69152c9c93ae769b5529c8d52fd9a6909a15e1a0601a714649c96ec996c1706d1021b97487980d7b2c2a39bbb0e470d8e46ac4aa609a0922c9bdc01612eadeaccd5fa523b2a8d0e62ffe56281647d61fffbbc840535745d144259cc81300fe99dfbffea6b0b9bcd28473982d32e93ed46634a9987906d6f48939d8dfbfb37d33b888db608cb2ffe39a8cf67b72644611c7d32a4a8df612468cd5e5d75fbba79e638aa1daa28c4e0eeb9a637ff8a08b65f7a7612414df76bc7b0b56b5537d666facfddaf65af1: +8f474f88cf863c485456a5a2155281ff27b28459f63bc4f1db00e0031064f64943144a329d751d04e07169b779ee920dd029cb445bf376ba3a668572182344a3:43144a329d751d04e07169b779ee920dd029cb445bf376ba3a668572182344a3:840891d948ec19c8c7f7c9d3c4775362a544a0ec97457ab5d14e125dc54b59c8dc9a635e7badb6be73c3a58dc0e9929f2b420d8356d617c3d41bfe69b4e158d4bf08fb17e688d3cf3c948b69b35f0b6db66272a8eb2bd410d6509f6c828b6a20d6586eaf857601ed9d6054799c25320eba8077fe1ae22671b33a1588ff2b235d3c71a27ce5c6c66e18889198d116933676bc4fb0710db7ff1ac2f20ce369bef56b43cd1d406cefdacf00f1f348b8ca7aa614db11a3a640fdb59389d1a6a394755c133f1b019c8308ca5a951e73b810a180f6ff25b29dbbccef4c13a97503393907a2dba096a8ce5c86c0ee6f97c1441b8d6331cba53b19606b421af52f65f9c663e63d3982718f948c6bae961b8e4bf8cd9e31cd09928e4e80616597ccfadcb8a614154933bc37589c85c776e34e5a90660f59a65b5e93ad438842f982d02b041e6dbddf171099f8db70995731a0db8c4625c9bca710805961fb176dae819768fcad7ff9bfce36403ca7f783e7613726d7dc59f24e247cf15068ff3b19c725fad65ea8e8a7f722d528c95fcef1c0cc79d18ef07cee8b011eeabd9921634d76a61a8a3c8931b827e8189881f81f7a175f21fb0378b8188e58bdb2017bef390f1800d9d74f263a81df8e67522d092e775d01e004e7f8d8281ae2c2fdf8c3a445f9eff7fdf13f261a773ddf2dd9cc6ba5585d990c995e6eb89dffd9ff0a9dbb76ce5e10dd0272d5001497881366f5d636a9cceaa283228d3ac614db217ab891d6689dbeb950e1200c3de53bc5da07f1d363dae9be6ec36eda6e687d26290f7abca268a7fa03d9318864eda9a11e3b26140605920ac13adec1b5548c9a7a3215a5876b7e941afa1cb5d7f7f0c11630cd429f3b2b37dc76c6cbea4f3b726aa8a5f8b9f705b05d7e9451956f8af13ce0a85955c7135d64ade5496ea542e70f8da5b573aaf137085dc96c6927099695672668b3c7c6f93c977a4e8e9e770295f20d52dff187f8dbb25ee7e774024eb9be08121ed74b6d5462f4bb7dc2003874caa31bb7595cd93a99ebe1eff928bb5fcb9e9c89dd31d487fc0e20bbe150:f61f7807c33e196d0fe182efa4d4516a9815ddd449538bbaa6b86b6901a05f5ddda0601ec90f39f1554779db7a09a60572effd4d128d0d3c2dd4e883574bc60b840891d948ec19c8c7f7c9d3c4775362a544a0ec97457ab5d14e125dc54b59c8dc9a635e7badb6be73c3a58dc0e9929f2b420d8356d617c3d41bfe69b4e158d4bf08fb17e688d3cf3c948b69b35f0b6db66272a8eb2bd410d6509f6c828b6a20d6586eaf857601ed9d6054799c25320eba8077fe1ae22671b33a1588ff2b235d3c71a27ce5c6c66e18889198d116933676bc4fb0710db7ff1ac2f20ce369bef56b43cd1d406cefdacf00f1f348b8ca7aa614db11a3a640fdb59389d1a6a394755c133f1b019c8308ca5a951e73b810a180f6ff25b29dbbccef4c13a97503393907a2dba096a8ce5c86c0ee6f97c1441b8d6331cba53b19606b421af52f65f9c663e63d3982718f948c6bae961b8e4bf8cd9e31cd09928e4e80616597ccfadcb8a614154933bc37589c85c776e34e5a90660f59a65b5e93ad438842f982d02b041e6dbddf171099f8db70995731a0db8c4625c9bca710805961fb176dae819768fcad7ff9bfce36403ca7f783e7613726d7dc59f24e247cf15068ff3b19c725fad65ea8e8a7f722d528c95fcef1c0cc79d18ef07cee8b011eeabd9921634d76a61a8a3c8931b827e8189881f81f7a175f21fb0378b8188e58bdb2017bef390f1800d9d74f263a81df8e67522d092e775d01e004e7f8d8281ae2c2fdf8c3a445f9eff7fdf13f261a773ddf2dd9cc6ba5585d990c995e6eb89dffd9ff0a9dbb76ce5e10dd0272d5001497881366f5d636a9cceaa283228d3ac614db217ab891d6689dbeb950e1200c3de53bc5da07f1d363dae9be6ec36eda6e687d26290f7abca268a7fa03d9318864eda9a11e3b26140605920ac13adec1b5548c9a7a3215a5876b7e941afa1cb5d7f7f0c11630cd429f3b2b37dc76c6cbea4f3b726aa8a5f8b9f705b05d7e9451956f8af13ce0a85955c7135d64ade5496ea542e70f8da5b573aaf137085dc96c6927099695672668b3c7c6f93c977a4e8e9e770295f20d52dff187f8dbb25ee7e774024eb9be08121ed74b6d5462f4bb7dc2003874caa31bb7595cd93a99ebe1eff928bb5fcb9e9c89dd31d487fc0e20bbe150: +e42b30d49c43c4fad83dd51fdc2a4ac5901327add800b66972c8c70bde180adcf734aafaa4dbaf315c258cca8bbc1d4f34e83601109874222aa05589f3a6635f:f734aafaa4dbaf315c258cca8bbc1d4f34e83601109874222aa05589f3a6635f:0d497051861e22d8a9c60e5f7de6c895cba335b2e82e602118ad8342b4d4edaa80f95efbb59cfda1fcc0291725700e8a81bb12a0b8623b1fe2891b8d98f7a84c59fd92f8a7adfc065042f7f4fd7e1a79f55a1d4d5e54e04e672f1c9e4c4cd8d0003f3cd54b76e2163dd737acb2de5c263ac102a48f696b60caf9be39c665cce1e0f3d498553f579061889a5ec5603e4d141cfdede8e7317572cfe76a0f48e4ae06062c9157b5eaac3468938192db4b16105c7364a94432b215a71797fee14c3c9ce2f746ed790302fc41dc492d37d9ef024ab51da3bdaf0f81d9a930aa0e025c04fd71026b6afeb7ed01a91a1efd6c39f5e447c66dd38a7656c613d02126f3585dfaa02df930253f83bd42196463ebc50f8cfc949ed350392e61ceec1309da15a432f80dfe948e261ce6d8421c5459cd21f3ffa2edb500982b2abfa52e82437ca230f609116320d9893eb82a14df72b7736667516fc012b28a03c9dd88ea4308d8ceea44cc604454cdfa2c797615bc0a6b3e0089af0a81be54d1b110a13ab911b452c342800cee2ad239a2b188a7fa875e941daaebcfc88b70ae4b1c575cdb6e6d89448136f60ee81c703c47822d2c0e50c7f1e8b7fc7ebd80789fcd7e06c7e50b5fc8b776e8b9a4cd5905a29069bc3a558d7cabce2af4f310767d5b117e3076b3a0d527175543b2ccea28d5f716fac32efed3d2e0276be44a8956fc8240f2db3397614f2f2da02166694ec6a7feec6ece39d72b64bbc6b476a4f84f8d879380a38488e4d6e58cac0390ae25a5fcb73d47414b4c26bbb9b4cc66e42594bd56d841a360923491d117be2c6eb2320f3c6175e44e27b6653c5dac6fae73600b67960dca50aa855a89e0ff511ea04f143e89f1da028476be4bf6d94c80ff726339e8bcfb7dd9f8cf202259c0acb6276c281e3847c2cc8d2fba84438d2d3c6031f2a7b95c1d8f9f3cc86a5eff65cc011de95ad896858e1f7f6d6b94bf49dfff5de2d7fd71ef108134285f61ae475483442dc90bf013faedf3771c47c5b96dc3cf8e48510060ad8d45fd5461622780d869d4617b57fe3cb5cc0203153aae:ff8e076e343c8b73aa453bfee9b2bab6d5c2f74c35e1bad1e52ae777d69f79764083f994368a1ac851a641cd247008a34f3b608962f4dd5109ac71cce978ec020d497051861e22d8a9c60e5f7de6c895cba335b2e82e602118ad8342b4d4edaa80f95efbb59cfda1fcc0291725700e8a81bb12a0b8623b1fe2891b8d98f7a84c59fd92f8a7adfc065042f7f4fd7e1a79f55a1d4d5e54e04e672f1c9e4c4cd8d0003f3cd54b76e2163dd737acb2de5c263ac102a48f696b60caf9be39c665cce1e0f3d498553f579061889a5ec5603e4d141cfdede8e7317572cfe76a0f48e4ae06062c9157b5eaac3468938192db4b16105c7364a94432b215a71797fee14c3c9ce2f746ed790302fc41dc492d37d9ef024ab51da3bdaf0f81d9a930aa0e025c04fd71026b6afeb7ed01a91a1efd6c39f5e447c66dd38a7656c613d02126f3585dfaa02df930253f83bd42196463ebc50f8cfc949ed350392e61ceec1309da15a432f80dfe948e261ce6d8421c5459cd21f3ffa2edb500982b2abfa52e82437ca230f609116320d9893eb82a14df72b7736667516fc012b28a03c9dd88ea4308d8ceea44cc604454cdfa2c797615bc0a6b3e0089af0a81be54d1b110a13ab911b452c342800cee2ad239a2b188a7fa875e941daaebcfc88b70ae4b1c575cdb6e6d89448136f60ee81c703c47822d2c0e50c7f1e8b7fc7ebd80789fcd7e06c7e50b5fc8b776e8b9a4cd5905a29069bc3a558d7cabce2af4f310767d5b117e3076b3a0d527175543b2ccea28d5f716fac32efed3d2e0276be44a8956fc8240f2db3397614f2f2da02166694ec6a7feec6ece39d72b64bbc6b476a4f84f8d879380a38488e4d6e58cac0390ae25a5fcb73d47414b4c26bbb9b4cc66e42594bd56d841a360923491d117be2c6eb2320f3c6175e44e27b6653c5dac6fae73600b67960dca50aa855a89e0ff511ea04f143e89f1da028476be4bf6d94c80ff726339e8bcfb7dd9f8cf202259c0acb6276c281e3847c2cc8d2fba84438d2d3c6031f2a7b95c1d8f9f3cc86a5eff65cc011de95ad896858e1f7f6d6b94bf49dfff5de2d7fd71ef108134285f61ae475483442dc90bf013faedf3771c47c5b96dc3cf8e48510060ad8d45fd5461622780d869d4617b57fe3cb5cc0203153aae: +5cb514217482bf42f611fcec36a5286807c2bdbb56967691353f54310e1ad553280699003d5d3e1c05ad10fb10959bbc595cfe213069965cd8cf39dd426a0568:280699003d5d3e1c05ad10fb10959bbc595cfe213069965cd8cf39dd426a0568:2f57258cca7932e58bed546cb0041115bbad23d18346ef7ab5e3110082b3a9712f6cbe1270e6dc0cea3364a06a5f2f283ec39b63058d34d59979072fcbbd7a5d0f442bbdf082d5bfe2998aeb51bd26127803e5c796c38843200ae2f6e605af312f54fdff17ed1dfaa89d28fa67dce462de4fe25268212b282e222a443e2f31e269054171aa73c719a896cdb7a539dfd1d42991978197d7c4f2d30a641be34bf1380a4f4dc6d9b101636636a496beb357e347c1666516df8eb560a0e0d1e1529ce36a60e00ed278da3802be192342989bb611b4e3cbd9c37e8cce07efc12d29befd7e2f3adb13d28f708d97b63e107482c862956d7ce8dfc2af5cac8d51659267b0bbeddd5efa414ddeabd17b23ca6e843ff49effc82a5d07e36a83b67c2ad7e48eb9990b421c5558009bd6934e86d54a8a6ac4078796e305c7cc810d3f66ea6b9504fe0ae6757c504c5552530a6f8bbb52409be079d8e4a28a6fd7dc8935f8eb9498adc0f23d0807ec86295f4898f5d05e150bdc43aa8b7bdc893a0a684c3063898b6c95e7d56a4c102690438e9df99758a90f47c608dacc4ca240266faba35fa1eb2eaabe288d2c2ad50b6cbf107c002575e91ff472a4417940667be8180173854c93df84464bcd312b7a7ae4dc2b9059fbe6f83f53806425bdff031c6aed6efafd9de8dcd0dfabea8e6fa681e99193fb3c647e442112c9a23f596e65411d8d6bfc3923004ece91ea6deb881111b1dc29943f578981ee8c3bce8525f78565f34b85ff20015feae846f95b18700bc5cdf14b2db6cac69814d63d74bf20329303e5ca9f04731f6881cec6d3abf87f5eac08734faa34cff4d3cd9a4a11d7b12f73253b4dd0a43178f0d3c19c0c40d9ed918dd17646f616af79fdf6194262f0fa4f71b3187dedca48d9cbcc19931a1519677456256ed38354567c3a67571cdf82170a2c85bd2c5e68e05a0f3b93903f191b894f84946f89000568054c1cea9fd0b8bb55019506c54341c24931984548ba458a4d813089896e86a2dc33d94604003f354a7cc941c754aaea24253cbe4cf2147ffec5e7b950cbf28e284481:d53ee2e0f0fd657b2052478fd15df1d38fe0e93a5483eb4a6e7de93d02a4cd544d8fdddcea822b71576ed02853d9a6b14e1a548aefe90d92f883792b7f1d86092f57258cca7932e58bed546cb0041115bbad23d18346ef7ab5e3110082b3a9712f6cbe1270e6dc0cea3364a06a5f2f283ec39b63058d34d59979072fcbbd7a5d0f442bbdf082d5bfe2998aeb51bd26127803e5c796c38843200ae2f6e605af312f54fdff17ed1dfaa89d28fa67dce462de4fe25268212b282e222a443e2f31e269054171aa73c719a896cdb7a539dfd1d42991978197d7c4f2d30a641be34bf1380a4f4dc6d9b101636636a496beb357e347c1666516df8eb560a0e0d1e1529ce36a60e00ed278da3802be192342989bb611b4e3cbd9c37e8cce07efc12d29befd7e2f3adb13d28f708d97b63e107482c862956d7ce8dfc2af5cac8d51659267b0bbeddd5efa414ddeabd17b23ca6e843ff49effc82a5d07e36a83b67c2ad7e48eb9990b421c5558009bd6934e86d54a8a6ac4078796e305c7cc810d3f66ea6b9504fe0ae6757c504c5552530a6f8bbb52409be079d8e4a28a6fd7dc8935f8eb9498adc0f23d0807ec86295f4898f5d05e150bdc43aa8b7bdc893a0a684c3063898b6c95e7d56a4c102690438e9df99758a90f47c608dacc4ca240266faba35fa1eb2eaabe288d2c2ad50b6cbf107c002575e91ff472a4417940667be8180173854c93df84464bcd312b7a7ae4dc2b9059fbe6f83f53806425bdff031c6aed6efafd9de8dcd0dfabea8e6fa681e99193fb3c647e442112c9a23f596e65411d8d6bfc3923004ece91ea6deb881111b1dc29943f578981ee8c3bce8525f78565f34b85ff20015feae846f95b18700bc5cdf14b2db6cac69814d63d74bf20329303e5ca9f04731f6881cec6d3abf87f5eac08734faa34cff4d3cd9a4a11d7b12f73253b4dd0a43178f0d3c19c0c40d9ed918dd17646f616af79fdf6194262f0fa4f71b3187dedca48d9cbcc19931a1519677456256ed38354567c3a67571cdf82170a2c85bd2c5e68e05a0f3b93903f191b894f84946f89000568054c1cea9fd0b8bb55019506c54341c24931984548ba458a4d813089896e86a2dc33d94604003f354a7cc941c754aaea24253cbe4cf2147ffec5e7b950cbf28e284481: +87d3ba95c40df80069b1797ddf68e866e66d46c51fde60e768a9dbc5c92f57a92b812b2c9b60ff31975c429a86736dcc17a58d3dc1daa34623a4bbcbe2cc0581:2b812b2c9b60ff31975c429a86736dcc17a58d3dc1daa34623a4bbcbe2cc0581:e11256f82ad76f3f4a49d7bad3ced8718d36d2f2bb3d31bb61edd1ecbcee6621fd2eeed3e3deb597b149ff71b851f61c8c6819e131f9a2af7673c3f20702acfdc8b8f9064b415c9a3e35568e371d740a38127c1f27b391b45d07045aeaf00a54e5b7fa548afb5f96feb5f5b44f60cd1707e8fa9567f7806e15f6a01aa02077733fe738b08f21efbcf98c19d5b970e6163e5fe8f4800ef9ed22a0f9b5126ff1eb1c7d65019c8b440391927029b813dab7c7e863d48229f8df85394345fcc88a300f60a8d516d877a5a3a7e3c49a9eb06cd9f2665ce2a89022962b1d49592b09c7543da835ce63bc9abb822145762b71cbe150292ce5c8704e5ad34fb4592f972044e43e69f0e1672d6c83cf25aac68efe3d27af2ad34274b9d2b77742d9c6dfbd57f92ff64d3e4c67c541d8502a7d031895af85319a4eae2d254335835eff11e7a3671a6a0d21b72ce1fc2acba1a920183834bc0a4b73f639ffcb0f6b81cd920f2e9420d612166d5682a06060ea0b6fa695fecc7704bbe4b052aa3ec8f720f7d4f32e8aff86b80b8c1cc12764a04874037c3103e9dfecb8f7abcb0e073b23e67ca0a9b1fc72993abf31dbc24a8fee095b3251c22626af5dd1b6d34be5ea06a02ae176c7b8cb9d063501be6f612082889fdbdcbfadc33a0d311b080b8d64e49f16b16dd8edd3b2ed1193a74e5be507609b042727ccf08afb05cc6c50524ef0e2664621dc8b05b15ffa81ab6f7e3c8a5bb3eab1f68e3656c119d969e4144cf3285af23c04dbecc038aefd9183c4e72447b2aaa8315f4696ce6d1ef429ba0e5c3d5ffa7f050be39c7f612f4e10f8ef070df72f8addbeaf3339c1ad8b5fc39a2ecf29a87f82e29a0117baac6625ad5c80cfe759fa1dbcfaa12b374477d80bfcf06796c30f2c39cf0303d00dc56a32d1d039592ddb06c22aa068841c0b46fd48df8fbb7492ccbc590c563c8fecce4263c8c7539218bb97b35711537e988195dbf5bcd5ccaf06faf508470977a5358e6f02608349fbb99a23fbe36b8c97155adc246ad7d93a8c203f75446c83c4342c35ba104ecc67e669db4a95466ee68f458a:fa0d12cd53236c41086bea8c0cc60b7764a3ed72bdeb9d1ae5eeacb48811fe529762a2c6f2bb06d9b318218d968f644435497a1bd0d0d8c1612ab8996d98d707e11256f82ad76f3f4a49d7bad3ced8718d36d2f2bb3d31bb61edd1ecbcee6621fd2eeed3e3deb597b149ff71b851f61c8c6819e131f9a2af7673c3f20702acfdc8b8f9064b415c9a3e35568e371d740a38127c1f27b391b45d07045aeaf00a54e5b7fa548afb5f96feb5f5b44f60cd1707e8fa9567f7806e15f6a01aa02077733fe738b08f21efbcf98c19d5b970e6163e5fe8f4800ef9ed22a0f9b5126ff1eb1c7d65019c8b440391927029b813dab7c7e863d48229f8df85394345fcc88a300f60a8d516d877a5a3a7e3c49a9eb06cd9f2665ce2a89022962b1d49592b09c7543da835ce63bc9abb822145762b71cbe150292ce5c8704e5ad34fb4592f972044e43e69f0e1672d6c83cf25aac68efe3d27af2ad34274b9d2b77742d9c6dfbd57f92ff64d3e4c67c541d8502a7d031895af85319a4eae2d254335835eff11e7a3671a6a0d21b72ce1fc2acba1a920183834bc0a4b73f639ffcb0f6b81cd920f2e9420d612166d5682a06060ea0b6fa695fecc7704bbe4b052aa3ec8f720f7d4f32e8aff86b80b8c1cc12764a04874037c3103e9dfecb8f7abcb0e073b23e67ca0a9b1fc72993abf31dbc24a8fee095b3251c22626af5dd1b6d34be5ea06a02ae176c7b8cb9d063501be6f612082889fdbdcbfadc33a0d311b080b8d64e49f16b16dd8edd3b2ed1193a74e5be507609b042727ccf08afb05cc6c50524ef0e2664621dc8b05b15ffa81ab6f7e3c8a5bb3eab1f68e3656c119d969e4144cf3285af23c04dbecc038aefd9183c4e72447b2aaa8315f4696ce6d1ef429ba0e5c3d5ffa7f050be39c7f612f4e10f8ef070df72f8addbeaf3339c1ad8b5fc39a2ecf29a87f82e29a0117baac6625ad5c80cfe759fa1dbcfaa12b374477d80bfcf06796c30f2c39cf0303d00dc56a32d1d039592ddb06c22aa068841c0b46fd48df8fbb7492ccbc590c563c8fecce4263c8c7539218bb97b35711537e988195dbf5bcd5ccaf06faf508470977a5358e6f02608349fbb99a23fbe36b8c97155adc246ad7d93a8c203f75446c83c4342c35ba104ecc67e669db4a95466ee68f458a: +7c27ae47072b0c9b9c2c351f1327899895efa536c9c067d0e0ce8e82e6292793f9febd121e17db7229b56709021849c35d69fa08b50620e667f842ec7ac782dc:f9febd121e17db7229b56709021849c35d69fa08b50620e667f842ec7ac782dc:1547876a988d1be714a42fb91cb03763f1913a892ecbd4de2ccf8344d20758b7b6d00259101fe97225b297f87bfe222004325db7f632ceaffbd134c96cbd57e985bec8434f81a4ee6af85c3fade50e4c4ef20cb0393545e4d4a86e1fa39aaf333fe4ded054bfc050a8983a03dd1ecf2b5e9517baf9e1152129a8a75935711edb20af5c8cf9c694a33cee451cd950b2fff08e3158c5cfb7b15cb3e90d46f494b6a108d8888d5ec29a33c066023b497709b2d9401feaf2e74ff26c16d36c39e6517ff954bd98bce7700671988f66e85107644ba2ea007a13018c1c144e3c5bb80db9511fcca4101bf49f8c80ff3ca7d298257cbfea629f83d5e06639d31f639db4b8726cbe224d758829bab10905171c9c0ec370d58031efe4cc5ae72a495acff6cb2ed9eec658ba117088dd3c6ed1df8f9cb10bd4fe0e5e8ad9f5034e34652d98668db15c8533393a6e9ec0870c35666ce54efe2bcb45c34a7230e6a700676349c7b3abf31de7b7b0521f89b30ac4034c2a4ba8218eefdf8d2a5c1f8ed9b701579e47af8a529a95a1ff64d8fdb885c36839b4c5f6d72a99257e8678dccf312754b9d4619beeceb825526de622bd9676fd5f357693abab078b9e03ae21e87ca161e778af77096eaac2d2d32bfec8ec94af7965f61d68ef66a4523c1cc70c9519b0750b3c9eed5aeba9f0a9b7ef52cd4a2de29b395b705fa53f028fa766159f20e75f4d384ec4fd66df06e744c99ac88cb849c285757cc557e2eedd86959da2c1b81f5b2715a6519848901ae4f89d0913c8de57c53dadf2e5e1aa2a9c5f464fc7610e8ef5f5cdd8203a67a93c33a06dab358dc5ae23edfee6334262f47b19b113d6cafedac1b43902539d74fba29aaa7bce68884b72616a0542c9fc69547cd19ae1df01723abdda65e9bfac5da0d04240c6a2175c0062e4e1ed8a5b397afcd4de38e86209272c7a424b5ae8d5a40b484ce1b4704af2831609ad0f36e90e07b2afed01dc05574ad3971723c5b5c1ddd4fc8bd263bcdf568af75e73d8abd1008c9ec712f80ffc65ac34e2a79304eade1d2a1dffec0e4c98c3582468f320bf8f66:327196ddd43bb602d04d1964ccc059ed627cef0a88d8ad91be4931f17c250d5529f552794a3e269d17a63bd32933eb5e519c1d506574770ae4a72964e06f7d001547876a988d1be714a42fb91cb03763f1913a892ecbd4de2ccf8344d20758b7b6d00259101fe97225b297f87bfe222004325db7f632ceaffbd134c96cbd57e985bec8434f81a4ee6af85c3fade50e4c4ef20cb0393545e4d4a86e1fa39aaf333fe4ded054bfc050a8983a03dd1ecf2b5e9517baf9e1152129a8a75935711edb20af5c8cf9c694a33cee451cd950b2fff08e3158c5cfb7b15cb3e90d46f494b6a108d8888d5ec29a33c066023b497709b2d9401feaf2e74ff26c16d36c39e6517ff954bd98bce7700671988f66e85107644ba2ea007a13018c1c144e3c5bb80db9511fcca4101bf49f8c80ff3ca7d298257cbfea629f83d5e06639d31f639db4b8726cbe224d758829bab10905171c9c0ec370d58031efe4cc5ae72a495acff6cb2ed9eec658ba117088dd3c6ed1df8f9cb10bd4fe0e5e8ad9f5034e34652d98668db15c8533393a6e9ec0870c35666ce54efe2bcb45c34a7230e6a700676349c7b3abf31de7b7b0521f89b30ac4034c2a4ba8218eefdf8d2a5c1f8ed9b701579e47af8a529a95a1ff64d8fdb885c36839b4c5f6d72a99257e8678dccf312754b9d4619beeceb825526de622bd9676fd5f357693abab078b9e03ae21e87ca161e778af77096eaac2d2d32bfec8ec94af7965f61d68ef66a4523c1cc70c9519b0750b3c9eed5aeba9f0a9b7ef52cd4a2de29b395b705fa53f028fa766159f20e75f4d384ec4fd66df06e744c99ac88cb849c285757cc557e2eedd86959da2c1b81f5b2715a6519848901ae4f89d0913c8de57c53dadf2e5e1aa2a9c5f464fc7610e8ef5f5cdd8203a67a93c33a06dab358dc5ae23edfee6334262f47b19b113d6cafedac1b43902539d74fba29aaa7bce68884b72616a0542c9fc69547cd19ae1df01723abdda65e9bfac5da0d04240c6a2175c0062e4e1ed8a5b397afcd4de38e86209272c7a424b5ae8d5a40b484ce1b4704af2831609ad0f36e90e07b2afed01dc05574ad3971723c5b5c1ddd4fc8bd263bcdf568af75e73d8abd1008c9ec712f80ffc65ac34e2a79304eade1d2a1dffec0e4c98c3582468f320bf8f66: +08eddcb5625ae19ffe7b49a7dc829c893c7538b0885e18f98db78c8beb569c2683478b1c58576a0d1834b28d46fb80516d6fb6f9f591694b44352eecd1e7e89a:83478b1c58576a0d1834b28d46fb80516d6fb6f9f591694b44352eecd1e7e89a:015b1d3eeb00929ea80bd8687d18286f0adfe645ccf25a22b5061921e2a030fc76d033fb53d0937c69b31c5be49913ca1f2c3dca121b2b87c59b3c84c7ae52af19c6b9fa1bd675fb6dd8b329d5668786dc7883e2d2e8586ff4128b90dee84be0ab54d6813f7a8c6134757173981775de84c4dd39e336f8a4ef8dcadec943e90d421b229c11785fcd3fe963037458e76c820b3bc2c9476001262b261d28b65b489d76b4be2365e4a80fa871b0a53b6a5fb243688235acc5f4774db15d47b42dd6c8d9e12dcb0b5d980dab0f3ad8a496f76e5006c2ca82675ff194caf8070d04bd384f97e583e73cbc4f7f257310a61b1c8062322dce8115f6dd93eee8a93ffa5cab6634116e1ab705fa86c4a8eaa556c6c89dbcad010436bffe451822491f1ea86c20207e4d12dfa362616c589f97107ea5d8bd8a7215c600ffc70b80e2abb15acbe4becca20d72155abc3dbe8e37cfd73f7420f21c9bcd0c3273513b5049670874d5519b3bc1db523c1d7e90c165967c4cb2845a2e8b47b5889254f58a9bbb826f94521cdbd0416f5f18ff78a3fd0d7ab897906264483cde642d8e703fd82e5ae70a9f978f64ee80520554850528581ca9a0b38c196fd166dae5879b3f72f59cde91cca2c8bfaa478b98d624cd34724402de578e5754825ce227d2871b45a5117149515bff81a923246f3b72d07bd458125c70a14d87c3fd13392a3bda6553016e8b2d07bde903cf687b445cfd6f761492eba46522ada84a9615d8da3498b258067269b788e559b659d4b48a87d880d6378be6a88746f35b322b047845aadc523beaff3070f721c3c071eaa319b7a47c1b20d300dc0321909b669e57d39a1ce2fdbeaafac21350ec2d6e6d5b880186c028a861474d5076a4adc5032fec9140787c36806ef79c72e3a19d8c8b70bdaf207295542d96825a5de7dfe108ef574599b8f184c63a5a131db19b3be53f699c10fc4ca7c63f3500211b356a0ac664ddfc1a9252590026395b479be9a5e4758423560b65bbce5bbade493b13d00cf8c1d3b7e9221367e8f0eadab6e6d1b5fffde7b2d741fc2c830224fff7ff14ae5c07:ece75322995154b292437e47d38a6a70af37e2020716fde46bfd393b3d369bddb53253b556621cfb34c8a90254e132fd28ecd098433413a21bd3a9798ca1f309015b1d3eeb00929ea80bd8687d18286f0adfe645ccf25a22b5061921e2a030fc76d033fb53d0937c69b31c5be49913ca1f2c3dca121b2b87c59b3c84c7ae52af19c6b9fa1bd675fb6dd8b329d5668786dc7883e2d2e8586ff4128b90dee84be0ab54d6813f7a8c6134757173981775de84c4dd39e336f8a4ef8dcadec943e90d421b229c11785fcd3fe963037458e76c820b3bc2c9476001262b261d28b65b489d76b4be2365e4a80fa871b0a53b6a5fb243688235acc5f4774db15d47b42dd6c8d9e12dcb0b5d980dab0f3ad8a496f76e5006c2ca82675ff194caf8070d04bd384f97e583e73cbc4f7f257310a61b1c8062322dce8115f6dd93eee8a93ffa5cab6634116e1ab705fa86c4a8eaa556c6c89dbcad010436bffe451822491f1ea86c20207e4d12dfa362616c589f97107ea5d8bd8a7215c600ffc70b80e2abb15acbe4becca20d72155abc3dbe8e37cfd73f7420f21c9bcd0c3273513b5049670874d5519b3bc1db523c1d7e90c165967c4cb2845a2e8b47b5889254f58a9bbb826f94521cdbd0416f5f18ff78a3fd0d7ab897906264483cde642d8e703fd82e5ae70a9f978f64ee80520554850528581ca9a0b38c196fd166dae5879b3f72f59cde91cca2c8bfaa478b98d624cd34724402de578e5754825ce227d2871b45a5117149515bff81a923246f3b72d07bd458125c70a14d87c3fd13392a3bda6553016e8b2d07bde903cf687b445cfd6f761492eba46522ada84a9615d8da3498b258067269b788e559b659d4b48a87d880d6378be6a88746f35b322b047845aadc523beaff3070f721c3c071eaa319b7a47c1b20d300dc0321909b669e57d39a1ce2fdbeaafac21350ec2d6e6d5b880186c028a861474d5076a4adc5032fec9140787c36806ef79c72e3a19d8c8b70bdaf207295542d96825a5de7dfe108ef574599b8f184c63a5a131db19b3be53f699c10fc4ca7c63f3500211b356a0ac664ddfc1a9252590026395b479be9a5e4758423560b65bbce5bbade493b13d00cf8c1d3b7e9221367e8f0eadab6e6d1b5fffde7b2d741fc2c830224fff7ff14ae5c07: +2273942db3e5d3221e80d994fd5e1163af55f5455a8e52be852dd3adf762b440bc58674e996b6f3e3220b3e94f0067bb0e9b0d97d9e1059cf13997a193ac032a:bc58674e996b6f3e3220b3e94f0067bb0e9b0d97d9e1059cf13997a193ac032a:8aa0509e4b914186ffff07aeb97a04b546272da2f9ea7bfa659a24cb50966c23eb6542e4f22debe33b65769245c4d1b5dcf3e699c70c5c2baad9734e9d1efe5448ab71c8946aecce5268d26f19cf605eb3bf38b0b3322694ac0dcb76b0f946842f6c5c68d763fce74701bd6b78e71c8c3142add4ed46e0969bb9555be03602d562e4c89f3a919940e883a96940542f2779fbf9ec0a285d9d8a72360146e3ffbdb78d210316038d95d6ab757165aa943c033eebb321c05a399569bcf66b4ddb0b2e0e33c4793d817ccff57f99b3189c60d5d7b9419d1ebc943a79d4d8c394566180594f559a80529cc1ba28877af8f5c0503e943cd3aad99811645272dafb49b9b3e6107eb5e5186e1608757126053debcec75dd9565ceea06a1391a8226d1f4593792240ccd97c67a6c2b1344c22c91f42033adef52861f32a4e0712a917879a0b0518b5424bcdc054b44e972ed24d01689f4f27f5f176f0a578ab2d3c0878272e8c08c21582118654124dca39585337c13c1865814caf0996cadfa65be580dee322ebccda704b2280582604067dc3c6b1f7d8a26978a65cffd1ed3196a2b065fb3caa79e6b5b66c13d7bd7d0ec14a3a4d58413f212f471ecaad3a84af35e598a89fb3447d3324f020fbf1b73e2a986e0da16c0183bf92a398c419a0f9f30537bea0df8df2dc53c154e8ea160689e7bb4d729dd8ab90031427aa3945863a85e89652b9353805166f7c0a18c939954b2787c37094f92512722e52b0c976b9e42af4039d2c0578ff14fae1d8c2d1396beb2d6aa6ebd55474a9349867a03f3a99d78780634ab4b35cfe1b87a9133252a698bc407d63842870e22ccf3933620ac0423c3d1f681dd73c01d06c3b941506c98eed9b7868e017b7f99716b0b77f11321e5ab23dbfcfca9350845ee180444c50ff0a9c965fcbf777708e4f34ccc637c6a08d854384f8d3e2516956c151d031bb1cbe712a5ef9ee16619228bd296f2afe582d9953d590d18bb205f70f844c16c0a2d8318037d43dd80f65c6a753f2a8e27c89c83e7ed70c52f7062dfbb1f544aa236b5c704e7b39ce0a55fd46528083ca61:874ddece08f30b30f0d4c8b3ed7c615149b8aa740daa347b55958f1e2119044f695a21069690506448d8e7352b9046511d7f39a5415bb9c57050fc17055c38088aa0509e4b914186ffff07aeb97a04b546272da2f9ea7bfa659a24cb50966c23eb6542e4f22debe33b65769245c4d1b5dcf3e699c70c5c2baad9734e9d1efe5448ab71c8946aecce5268d26f19cf605eb3bf38b0b3322694ac0dcb76b0f946842f6c5c68d763fce74701bd6b78e71c8c3142add4ed46e0969bb9555be03602d562e4c89f3a919940e883a96940542f2779fbf9ec0a285d9d8a72360146e3ffbdb78d210316038d95d6ab757165aa943c033eebb321c05a399569bcf66b4ddb0b2e0e33c4793d817ccff57f99b3189c60d5d7b9419d1ebc943a79d4d8c394566180594f559a80529cc1ba28877af8f5c0503e943cd3aad99811645272dafb49b9b3e6107eb5e5186e1608757126053debcec75dd9565ceea06a1391a8226d1f4593792240ccd97c67a6c2b1344c22c91f42033adef52861f32a4e0712a917879a0b0518b5424bcdc054b44e972ed24d01689f4f27f5f176f0a578ab2d3c0878272e8c08c21582118654124dca39585337c13c1865814caf0996cadfa65be580dee322ebccda704b2280582604067dc3c6b1f7d8a26978a65cffd1ed3196a2b065fb3caa79e6b5b66c13d7bd7d0ec14a3a4d58413f212f471ecaad3a84af35e598a89fb3447d3324f020fbf1b73e2a986e0da16c0183bf92a398c419a0f9f30537bea0df8df2dc53c154e8ea160689e7bb4d729dd8ab90031427aa3945863a85e89652b9353805166f7c0a18c939954b2787c37094f92512722e52b0c976b9e42af4039d2c0578ff14fae1d8c2d1396beb2d6aa6ebd55474a9349867a03f3a99d78780634ab4b35cfe1b87a9133252a698bc407d63842870e22ccf3933620ac0423c3d1f681dd73c01d06c3b941506c98eed9b7868e017b7f99716b0b77f11321e5ab23dbfcfca9350845ee180444c50ff0a9c965fcbf777708e4f34ccc637c6a08d854384f8d3e2516956c151d031bb1cbe712a5ef9ee16619228bd296f2afe582d9953d590d18bb205f70f844c16c0a2d8318037d43dd80f65c6a753f2a8e27c89c83e7ed70c52f7062dfbb1f544aa236b5c704e7b39ce0a55fd46528083ca61: +dbfa45abaa55415238b1287634d5eec402dadf622e270c04a8914ced270a72bec0fe323581ea296750797eb5508ca19a583b537fa7df4529f0804a33c1a4bef4:c0fe323581ea296750797eb5508ca19a583b537fa7df4529f0804a33c1a4bef4:e26e8dcb44e641fc20080e95474bd39d716c5afe5a1ffb056d1eaab0c49f8570717db6437a03228a9ad9f4bb0b343b95e16023c0807eb2a15106a6eb12dc76683e69dda3363148c5d7dd9713af6f87a09410ea8f76b6b78a114429bc85f784812fca31acb0309552cc188c6e9697093cf404c6f0f4abe8a1608673fdfa5eb78f65fc1d49cdec4094b1bd234a46e0ec62a4b6d31b829611540127876bff4c173de058cf61004b014a7bdf793dfd6b63c507d2b23e0f56bc2fe6baf637cee40d18992295d848ef498f8a161bd87e60c91f97a91e9ef3f6d97f2b2d2104ba6fddd6c680706273dae87e6eec1af2a45984985069e809e8de32c12889299a32d40f38774599ac3324b7cb0a4ea632c5f910ad87f5adbfa5c3bb20498279fd53c1c267fe0a84773085da266b253cd853df7e963558cb06880780973423c564cd0bcd6b93334c195953d7cd899f8a547d1a1a0a8deff1381b4321574728cf71b96ff209e899daa8f13f41b230e17bffdfdd2a8943aa5d21e5f36e1da07edd6cee92dc48b5b2a7580146a9baf713950ce676255a89e34f8787547d62868db14ba46594da310d7e2d9e7c7dbe17dbd71eb47c56c5721dc96d696470573794809411cdfa276b059d0007c25d74b2a67d38246de11ef46dfe2670926fe4b63656231bc7268bba23f378e84a428c3cbf45cc539678fd467cd33dd0757cfa024e54da1ff54ce820229b778b184be1fa2e8468cc19955940735eaaa884022f6418b0b1f26bccf169f1bcac7d82a35ab6ef847e1dba537dcaff57250a8d1c71facb134cd06b01c45319132745dc488888a1d7761b8486a37e6988a1120bcc1682dbfc89143fc35b46935d8acf6ef3c42f0f4bf679dfd6ff44b6ada26b01a9f89f374c7d2ee48dfe1a410e897cdfd97f626d2668502814400793b3b07c8720bbddc59cb0f9de964ae075b4af3dd4baf6d0e4f94f294e8109d6577c4f8a9c7a5f7d694bf88f1a5ea7eba0a66da6c770c08b3abffc534df219dc3e3323b022e96cc86002b189181a1d2b527d27950b7f425a47da4013778bd00b71105922204921e9dc692c233f7baa04:a462a9baa56dc0f7a71bf87b95f48d642022d9d1733ee3683777a3782228ac85fcd83026be4ca97a345b084f50874e9124e16ba17dead4ad85c0e56f16ef1804e26e8dcb44e641fc20080e95474bd39d716c5afe5a1ffb056d1eaab0c49f8570717db6437a03228a9ad9f4bb0b343b95e16023c0807eb2a15106a6eb12dc76683e69dda3363148c5d7dd9713af6f87a09410ea8f76b6b78a114429bc85f784812fca31acb0309552cc188c6e9697093cf404c6f0f4abe8a1608673fdfa5eb78f65fc1d49cdec4094b1bd234a46e0ec62a4b6d31b829611540127876bff4c173de058cf61004b014a7bdf793dfd6b63c507d2b23e0f56bc2fe6baf637cee40d18992295d848ef498f8a161bd87e60c91f97a91e9ef3f6d97f2b2d2104ba6fddd6c680706273dae87e6eec1af2a45984985069e809e8de32c12889299a32d40f38774599ac3324b7cb0a4ea632c5f910ad87f5adbfa5c3bb20498279fd53c1c267fe0a84773085da266b253cd853df7e963558cb06880780973423c564cd0bcd6b93334c195953d7cd899f8a547d1a1a0a8deff1381b4321574728cf71b96ff209e899daa8f13f41b230e17bffdfdd2a8943aa5d21e5f36e1da07edd6cee92dc48b5b2a7580146a9baf713950ce676255a89e34f8787547d62868db14ba46594da310d7e2d9e7c7dbe17dbd71eb47c56c5721dc96d696470573794809411cdfa276b059d0007c25d74b2a67d38246de11ef46dfe2670926fe4b63656231bc7268bba23f378e84a428c3cbf45cc539678fd467cd33dd0757cfa024e54da1ff54ce820229b778b184be1fa2e8468cc19955940735eaaa884022f6418b0b1f26bccf169f1bcac7d82a35ab6ef847e1dba537dcaff57250a8d1c71facb134cd06b01c45319132745dc488888a1d7761b8486a37e6988a1120bcc1682dbfc89143fc35b46935d8acf6ef3c42f0f4bf679dfd6ff44b6ada26b01a9f89f374c7d2ee48dfe1a410e897cdfd97f626d2668502814400793b3b07c8720bbddc59cb0f9de964ae075b4af3dd4baf6d0e4f94f294e8109d6577c4f8a9c7a5f7d694bf88f1a5ea7eba0a66da6c770c08b3abffc534df219dc3e3323b022e96cc86002b189181a1d2b527d27950b7f425a47da4013778bd00b71105922204921e9dc692c233f7baa04: +ef64e17a53f7fbcafe3ea4687684a0dadb18d03735a40a53b3edb04907ee61629186e6bc142961c4d3eb369e9e11578292de5b6af534d423ff240fa26e21a781:9186e6bc142961c4d3eb369e9e11578292de5b6af534d423ff240fa26e21a781:6882456cc3d1ad0daa9b88eff0969f15e97b48d051967e1390847225f26ac25559f0246bf7d683fa28ecedad21491d77bd2696fa835d0fd119884fece9d803691b2fd3de17ee087c74007a7de9bc6534bbfe95fd32e97c375f4cb65731aa1e8346bea21be9f2c3dc874af0431906ccbc2c600127f4d3b069eb091d165ec453e672e93cae8b72f03371d8b8a8244ec4ec2e09f31df40206a2b1c84caa1b993cc675fde1c79bd4a7d15974fa29ce2e892c2899cf482c3d9663f6d2a79784f41c1f5866d37c8546f357d564d3c4218dfa6d20b6c282b400fedde52439d472212c5767a35da5201032da8730968b0720e8a604de6c1baa3f4e896ac2614fb1ab6e3f6cf387a8eb2ff8a92147ab349238432e509d829cb75b2c1765c51221848e25afff5f16e4dd0cd5c9f713c4aaab2ce836f8494506b5309dc2b0ae745bb9c4798098fb8641d520a08b02f75ad80dbc2ce29e890b4d72a3ffb2a1cbd538e1229f579c29ae66bca85e0fa08c8647a1abcfe8a49f5e508d4d2495556623d926ce49efa4350aaaab5cec2cd885be1d63475e3bab7c7cdc8d656173b8d45602f4b3d281241d17190327b24c3836b19311a193af86a6768f04852ab06e67c8ead591cdcbf3789c613209cfe03f58c0305f63203b487f7c5fc098877ec98a689c9d35af81e84078d66fe9e4eccbb1cc6c71991c03017bb811f41f07de68fad194146061324f3d0ef217a54cf38f7a625a38869f67d0b7431df937cde349c175ce8b26ac88d39a43e279b018764efa4dd627cbf591f6209c4a5bb19ebfa7c7135592d02e501cae5e6b31c90e72faab47f7dced2c48adf88443b3ede60cefb0d6379d6922ec437f086bad6217d4d4ffef18e22523664bf4e9ca1e65a28c2a7a60c5f6bc906b737c29935f9097463048575befd1a2549dc474b13e68aeecf166043e075aac515540f831b43066cef932e63dcd5b37b61578c35b09e45cc2a8def57103edfc5f649831a8961fe4a4b3721f1d6df4ea9f033881b474300e0f12cb9cd3babdcffbb918dd9bb0e2f5b21033e43023a0d2e66da3ab0f07ee988b16889ca5d51abdc05fde:f58f396ba27e067a5fe003e385582ae3490e05957715d704da0da63a6419d2e4f6dc66b7e88e428a6f21b9ea202299a3c36b242b0ea06476ff12d0b6580c04036882456cc3d1ad0daa9b88eff0969f15e97b48d051967e1390847225f26ac25559f0246bf7d683fa28ecedad21491d77bd2696fa835d0fd119884fece9d803691b2fd3de17ee087c74007a7de9bc6534bbfe95fd32e97c375f4cb65731aa1e8346bea21be9f2c3dc874af0431906ccbc2c600127f4d3b069eb091d165ec453e672e93cae8b72f03371d8b8a8244ec4ec2e09f31df40206a2b1c84caa1b993cc675fde1c79bd4a7d15974fa29ce2e892c2899cf482c3d9663f6d2a79784f41c1f5866d37c8546f357d564d3c4218dfa6d20b6c282b400fedde52439d472212c5767a35da5201032da8730968b0720e8a604de6c1baa3f4e896ac2614fb1ab6e3f6cf387a8eb2ff8a92147ab349238432e509d829cb75b2c1765c51221848e25afff5f16e4dd0cd5c9f713c4aaab2ce836f8494506b5309dc2b0ae745bb9c4798098fb8641d520a08b02f75ad80dbc2ce29e890b4d72a3ffb2a1cbd538e1229f579c29ae66bca85e0fa08c8647a1abcfe8a49f5e508d4d2495556623d926ce49efa4350aaaab5cec2cd885be1d63475e3bab7c7cdc8d656173b8d45602f4b3d281241d17190327b24c3836b19311a193af86a6768f04852ab06e67c8ead591cdcbf3789c613209cfe03f58c0305f63203b487f7c5fc098877ec98a689c9d35af81e84078d66fe9e4eccbb1cc6c71991c03017bb811f41f07de68fad194146061324f3d0ef217a54cf38f7a625a38869f67d0b7431df937cde349c175ce8b26ac88d39a43e279b018764efa4dd627cbf591f6209c4a5bb19ebfa7c7135592d02e501cae5e6b31c90e72faab47f7dced2c48adf88443b3ede60cefb0d6379d6922ec437f086bad6217d4d4ffef18e22523664bf4e9ca1e65a28c2a7a60c5f6bc906b737c29935f9097463048575befd1a2549dc474b13e68aeecf166043e075aac515540f831b43066cef932e63dcd5b37b61578c35b09e45cc2a8def57103edfc5f649831a8961fe4a4b3721f1d6df4ea9f033881b474300e0f12cb9cd3babdcffbb918dd9bb0e2f5b21033e43023a0d2e66da3ab0f07ee988b16889ca5d51abdc05fde: +3347dc47bb3d2e5d0286ac06a54fd921c9e96b6899862a54e5cc8115d3d0ba99d00b645d86dbb7e524757ec778c62b7e60d0b6576883338c9b67c2c7e4509268:d00b645d86dbb7e524757ec778c62b7e60d0b6576883338c9b67c2c7e4509268:e2f48edf9d643320ab991c8ff9f6aa75fe066e7d88ff1e472a5ac9c518de1fb62983b1007f6422809117bdbe8a0e5787f66bb057d27f129a200b40576e1719cf9e98fcb72af94bb82ee70f3719a2e2cd9b64777cea5e446459874b74bfbf56b2d2526400592a9b45a5cb798092b60a81b71d82f0685fae7f810b52d226adac7ad8a9183f09febee9d25046c0fe306681ace2bff91b3482b0bc30b2021c4341645d675134fe3081c51e5c59e40b375a1434f63b426e30530da9353bb2a9423220434ae59d7b6fdc143f4982eb8cfa7751b75bf3e9c913c73b760b07d395310c59f3b77ebf12ed2d7b03590d3317af17df421e78b0849fd56d945c5696a040fcaa78a93ecc16d5ac3445063611f3013e9a3ae2e1c270dd01a8ffe3e6126bc1e4c95f6547a8651f26b6404e39ee4ce7618918f3f937a52573ec277b771e91ad096fa15c7a340a809b470318a4636423eb4888a12160c4663fce2996d638896c839b2c7ad4b3a9b2e6cb71e912fe39b843c6e0832eca22de938b50ae863e48582c10851232f75e5225b8896b5a470f818b6fa39eb7bb590357678612d25fe1a40ea1b9d71d880909c1bd4ad176cc0ceffdcee7099e7882a7c907e4bec79830c6771acb89944bd54a5165b31870916921b198acd4432e7eed8ce1deb345b107eda760266fcbda3ba5229400a30360a4645ca8db38c3d5f4a8def157bbdbbf2c1fa1dc6b0514a4f5a0364f928381b40f95579a26467f2282a8a255758402ac9ca80e89b9cc6860a34bb3f90c3237657c2129ea48c852b92569e81106bce461e2024454821a917592d1991b5b69f27bbe019977528a2fc01192c56b4aea873cf8c58dfd7cb4b0e917e87a8704c992820f98d77404d3f1d2050c6743f6e93cdb51a61aa6f45b351b26461d1329f3151272ac396234d0d67c178acf91fc510d86429c69a87fdf101155da8d94de6722238a6fb17016862b11d502c667ee9ca0aabe1c20b97789f1867add78b8b87e9ab51934c0b4a16c2cbc4d2efedb79c05b23e0cf789201ac75fe076d315fcbac20ba0d31e4dc616927d6eab1b1c87a1c9c778e4bd285295874:9ab4299b17729344750b69dc6037368c98f47be627fbd9adfd8db39f9964ddb7bc92d674c7be740756396baaeeacbf74947b6191c6ed1f5d32a63df36d542601e2f48edf9d643320ab991c8ff9f6aa75fe066e7d88ff1e472a5ac9c518de1fb62983b1007f6422809117bdbe8a0e5787f66bb057d27f129a200b40576e1719cf9e98fcb72af94bb82ee70f3719a2e2cd9b64777cea5e446459874b74bfbf56b2d2526400592a9b45a5cb798092b60a81b71d82f0685fae7f810b52d226adac7ad8a9183f09febee9d25046c0fe306681ace2bff91b3482b0bc30b2021c4341645d675134fe3081c51e5c59e40b375a1434f63b426e30530da9353bb2a9423220434ae59d7b6fdc143f4982eb8cfa7751b75bf3e9c913c73b760b07d395310c59f3b77ebf12ed2d7b03590d3317af17df421e78b0849fd56d945c5696a040fcaa78a93ecc16d5ac3445063611f3013e9a3ae2e1c270dd01a8ffe3e6126bc1e4c95f6547a8651f26b6404e39ee4ce7618918f3f937a52573ec277b771e91ad096fa15c7a340a809b470318a4636423eb4888a12160c4663fce2996d638896c839b2c7ad4b3a9b2e6cb71e912fe39b843c6e0832eca22de938b50ae863e48582c10851232f75e5225b8896b5a470f818b6fa39eb7bb590357678612d25fe1a40ea1b9d71d880909c1bd4ad176cc0ceffdcee7099e7882a7c907e4bec79830c6771acb89944bd54a5165b31870916921b198acd4432e7eed8ce1deb345b107eda760266fcbda3ba5229400a30360a4645ca8db38c3d5f4a8def157bbdbbf2c1fa1dc6b0514a4f5a0364f928381b40f95579a26467f2282a8a255758402ac9ca80e89b9cc6860a34bb3f90c3237657c2129ea48c852b92569e81106bce461e2024454821a917592d1991b5b69f27bbe019977528a2fc01192c56b4aea873cf8c58dfd7cb4b0e917e87a8704c992820f98d77404d3f1d2050c6743f6e93cdb51a61aa6f45b351b26461d1329f3151272ac396234d0d67c178acf91fc510d86429c69a87fdf101155da8d94de6722238a6fb17016862b11d502c667ee9ca0aabe1c20b97789f1867add78b8b87e9ab51934c0b4a16c2cbc4d2efedb79c05b23e0cf789201ac75fe076d315fcbac20ba0d31e4dc616927d6eab1b1c87a1c9c778e4bd285295874: +ff15d6e74e28e41d05a8663a702f038d5b8578c4275e772b73ba440bc5f55a064747e2e9b82637b3844b85f75b59f7136b7fdb1a62e7b70d6aac17b3c5752f2f:4747e2e9b82637b3844b85f75b59f7136b7fdb1a62e7b70d6aac17b3c5752f2f:ce7bf972844f5184ae8eac87b12be9202c7239961dc23cd41ff55b9bfaac0cc06f3f1decfa9571095c8e82b4eb6f8a1c52c8d3deaa61a9aa94e2ecd9ab5b8063f2da6d8015df0a5144fa3a48e305ad9f41eaa11c4d74854374ecbf382e3002579a9a249efa1e1ca04d338447d7f2206703e6cabf5bbd332b42573bcbd3b6f71b7c3bf73d4c774aa01e866841432829d07f96e1f61a20216d968c90e3ed11f663f7d6271622fefcf3ab68f344328515d5cce2ce85e8bf3d1d09043692e1fb8bbddc07a4ab0a3eef8ca6a420e74bff8d3d715596aa821682954fe89629ae27c1bb03b6aa09f36a39a3e37ba98132f4e23888f9f335e7beaa2cb2727acc3d2777309b85295232e54da88ebb6f1053d6de79ac6609852eb93a0a35bc1a7bdc22d628bc86124d696c3f9828b6f8b9aade1a65216177486c252a4b42d90a4e0fea2093489e244d808ef7021a97d5608c0ae1d663c775e8bb9e9a7315f1feb6d129b5a541ea5929a2c633b6d8c3c45441717946cf873e9b4c512180135d54f053abe44c6df39b7b062ef7240162cbd0b851afe5f91536a9499418e8bff4996473d805ebc1ae48da2d0b129e8e8252f1d53c328f32db252de3befbe5f31280121143a8004a4cae631c827409e520e394cd0f8950cd4c3cf3f3dbd4952a4dfe69875f565389061ad0a0cee6b6aff09ceca26d990e896a2aba9f3b26015b63423768684c03ed0de6cee7ac5bbdf9f485c2275cd12aefa8f907b851a02d51c34f121b77f3a56a9ebd1d65ffe89bee381ff2a7480e8968cff25ac8d04e149a9d5027d14b88f8ae2604d2ac22ac67d13e90ada620c2046d28299384d0959fb76e22588796ce427aaeaf4e2a8aaec3e87f84ccd082524c96d766eec66f0bec3e799558145f09d330134f1c63f37053cd4bdc1c37fde97291857551f50ac8e15f06ac1c73daa1e8c5bc9277e3d69cb44a3237ec57dbbccfdf6685ada20b74a1bc6b74ab05690eaf9bd0c4be17042f5cd320cdd613dc08d29af346aa4191ce0b4f85bb2ad7f3bac738a9377ec6b84062cc70fca9ecfbe1f57fe5b2ce7a4f739c81cabcde046451dd61ce1dbc:42c1295fafe26de3ea34926bf1ef80bcafe47b21b90eaed19635ed7538d767cbf3a1e5dedaab82adf75120373e923202f7fda0826784292eba8b238b6cb88304ce7bf972844f5184ae8eac87b12be9202c7239961dc23cd41ff55b9bfaac0cc06f3f1decfa9571095c8e82b4eb6f8a1c52c8d3deaa61a9aa94e2ecd9ab5b8063f2da6d8015df0a5144fa3a48e305ad9f41eaa11c4d74854374ecbf382e3002579a9a249efa1e1ca04d338447d7f2206703e6cabf5bbd332b42573bcbd3b6f71b7c3bf73d4c774aa01e866841432829d07f96e1f61a20216d968c90e3ed11f663f7d6271622fefcf3ab68f344328515d5cce2ce85e8bf3d1d09043692e1fb8bbddc07a4ab0a3eef8ca6a420e74bff8d3d715596aa821682954fe89629ae27c1bb03b6aa09f36a39a3e37ba98132f4e23888f9f335e7beaa2cb2727acc3d2777309b85295232e54da88ebb6f1053d6de79ac6609852eb93a0a35bc1a7bdc22d628bc86124d696c3f9828b6f8b9aade1a65216177486c252a4b42d90a4e0fea2093489e244d808ef7021a97d5608c0ae1d663c775e8bb9e9a7315f1feb6d129b5a541ea5929a2c633b6d8c3c45441717946cf873e9b4c512180135d54f053abe44c6df39b7b062ef7240162cbd0b851afe5f91536a9499418e8bff4996473d805ebc1ae48da2d0b129e8e8252f1d53c328f32db252de3befbe5f31280121143a8004a4cae631c827409e520e394cd0f8950cd4c3cf3f3dbd4952a4dfe69875f565389061ad0a0cee6b6aff09ceca26d990e896a2aba9f3b26015b63423768684c03ed0de6cee7ac5bbdf9f485c2275cd12aefa8f907b851a02d51c34f121b77f3a56a9ebd1d65ffe89bee381ff2a7480e8968cff25ac8d04e149a9d5027d14b88f8ae2604d2ac22ac67d13e90ada620c2046d28299384d0959fb76e22588796ce427aaeaf4e2a8aaec3e87f84ccd082524c96d766eec66f0bec3e799558145f09d330134f1c63f37053cd4bdc1c37fde97291857551f50ac8e15f06ac1c73daa1e8c5bc9277e3d69cb44a3237ec57dbbccfdf6685ada20b74a1bc6b74ab05690eaf9bd0c4be17042f5cd320cdd613dc08d29af346aa4191ce0b4f85bb2ad7f3bac738a9377ec6b84062cc70fca9ecfbe1f57fe5b2ce7a4f739c81cabcde046451dd61ce1dbc: +1ed37b610b8b35417d04e59aaadac688ff81f1e507c89b4f400160941908cb8c48e8cbeb1240bdebf0a2d92953aa89b282c49aab2c38ae69044c51515c3300d5:48e8cbeb1240bdebf0a2d92953aa89b282c49aab2c38ae69044c51515c3300d5:1e6767df97db1cfb4088da7b200d9f59ec8dd4533b83be309f37650031065727cd5202cef48426a5f3a11d50b381f8bc22ff101827359f2d0a610a4f755464a0c891cbd98d2dcb41d9779d288fcf1fea62e52163ae67e90428b86398efa218f1b982081fc513305fd3e8ece7f9acb0e10e001d2ed299a48a80870b3d5d8ab9006309b31591caf0583380073a2db61f45254ab965b5e4672c4bfaa86e336c49278552729fb2da76ffe502ec61e1696c7fc9ef19f7cc2a2775b29700cb384294063a17fed4fc635bc13282a90dad0c00aadbcd569f156a854f8ba9e7d607d20f2e9e5337981161d804644668d064fa63dceb9f5801353d0ab9f41d1d8bdc76c13ab2f023ea01adbc4c8168d939e98f64fd8919384abe76709263c0cd7c3efadc2801cc4abd80a09bb3ed6bb78cd620969cd35c6a3a5d01485ead4c45ebb6ac6a83212a7c76675427b21da8a7a5047b30a6100cda02476c186e6ce40d2768a942c9f87305e9d363b524c0094a9e2e29f585894c0adbfcd60690fc7fb0a9c717cf43b484fd45151b1304169c26921db2276ec05ad22ad166854fd2f94085778c470dc452e5cfa4aee04facb770526e1f248d3d15c27280fdfa1fd2c1044bcbc881c3d99815c97fbea46110be02dab774f3a610e5802abf36a49875c682638e0ae4cc8277c5e9aa7307445e6bbcbe549eec2a45b1597f7447107b62e2cee0a5fc51beae3e1fe9befb1885d9b30f9b4f1f56206dee0d67779c57f484c8c3c899a515a9d1c10f6059840c1c73d3f05bcb88590c52f7da391838dc2e73228f0981c289a4c27f0c757faf7b3b89146e33dafa490d9e0f9275b0cfa6a7710a73831459595bf732112b62fc864ca4c829784a3f16eec4e18f936918a7b9891669e933223f745fda562bc0a4e61e3d14ea45dfc327e2fc0cdfe6f2f97546c90fce82f522291480111a1e6b9388272c0be28d20ed84bb84d49bc199cd599948b8f2039d07827a3f4075d3a67ee572a01379a36213fe116e768b4114e8a4b3134c3818960772d727b0ca6f7c997ca99843b7eb02ffc013971cbe0e6e60d49773f1e8c0b30606131cb10c3e04:8608815e10590d5504874d8999fd6f09626f950be20c912c27c9de6e79b0faf777a533bd5bb667ab513a49458ecd6787a09ec0df6c9c9d6333c5e3ae61ea370a1e6767df97db1cfb4088da7b200d9f59ec8dd4533b83be309f37650031065727cd5202cef48426a5f3a11d50b381f8bc22ff101827359f2d0a610a4f755464a0c891cbd98d2dcb41d9779d288fcf1fea62e52163ae67e90428b86398efa218f1b982081fc513305fd3e8ece7f9acb0e10e001d2ed299a48a80870b3d5d8ab9006309b31591caf0583380073a2db61f45254ab965b5e4672c4bfaa86e336c49278552729fb2da76ffe502ec61e1696c7fc9ef19f7cc2a2775b29700cb384294063a17fed4fc635bc13282a90dad0c00aadbcd569f156a854f8ba9e7d607d20f2e9e5337981161d804644668d064fa63dceb9f5801353d0ab9f41d1d8bdc76c13ab2f023ea01adbc4c8168d939e98f64fd8919384abe76709263c0cd7c3efadc2801cc4abd80a09bb3ed6bb78cd620969cd35c6a3a5d01485ead4c45ebb6ac6a83212a7c76675427b21da8a7a5047b30a6100cda02476c186e6ce40d2768a942c9f87305e9d363b524c0094a9e2e29f585894c0adbfcd60690fc7fb0a9c717cf43b484fd45151b1304169c26921db2276ec05ad22ad166854fd2f94085778c470dc452e5cfa4aee04facb770526e1f248d3d15c27280fdfa1fd2c1044bcbc881c3d99815c97fbea46110be02dab774f3a610e5802abf36a49875c682638e0ae4cc8277c5e9aa7307445e6bbcbe549eec2a45b1597f7447107b62e2cee0a5fc51beae3e1fe9befb1885d9b30f9b4f1f56206dee0d67779c57f484c8c3c899a515a9d1c10f6059840c1c73d3f05bcb88590c52f7da391838dc2e73228f0981c289a4c27f0c757faf7b3b89146e33dafa490d9e0f9275b0cfa6a7710a73831459595bf732112b62fc864ca4c829784a3f16eec4e18f936918a7b9891669e933223f745fda562bc0a4e61e3d14ea45dfc327e2fc0cdfe6f2f97546c90fce82f522291480111a1e6b9388272c0be28d20ed84bb84d49bc199cd599948b8f2039d07827a3f4075d3a67ee572a01379a36213fe116e768b4114e8a4b3134c3818960772d727b0ca6f7c997ca99843b7eb02ffc013971cbe0e6e60d49773f1e8c0b30606131cb10c3e04: +84364478ec94bd25c4bdb82d296229e6dace2b1359d6d21be2b3afcd7bda19c7a1814f8ce0fc3b236093a50f468c1316211fe6c52e2345d9f0766b3688a03cad:a1814f8ce0fc3b236093a50f468c1316211fe6c52e2345d9f0766b3688a03cad:7bb7293de55f058fb2ec22b687260543dcaa90f140b9f45eddd4bc22e40977e00ed33cd1ef1bba13c1d0990859005569a80767e4864a2cd288c81393e04ad971782e2bc493108cbe80dacf0b7b9cd534988407a4f9327ec8e9c4043284ef6ee5a26a5b417765d3eabb48a007e7c7f32987d70a139ac41678cdf7a55cb80cf9db5eaa45f3de0fbfbadffc40996370e48b1ff5edd97940e750792164836a4a5ac2e3ff53e48a1e556db9ad0c5c0b944f4aee519a2b0a88bb1c1fc7454524cd57aa5350986243d34fc58e24e819ec0b8545d8dfcf6b20311441d3a35d3e71b3e3ecd7884dda8433a405e3d9969000c820a89b95d197841d98ae734a2e81daf6a7dcf56cb2fc26f2165a5f42b86c7e9e5b11161700a1ab9831f3fae58e14208be1bf33b58ecce81b0c6b7e02f88adf9ab030263e2cc9b6e33ebca3f495492e32bfe372537de6c6b87644828f74942a02b007f14c3fc5dbde76333d36d07631b7a9924f717550040697923fa7b9546bfb0217024ea3f252b515b5d64a62c48e027cef6750beda49a02447039b250a0bda07dc062491a662e26874c8d00f80e6cfc8b30f2c3bf7720b57f2615fc478fefaa6d31705b43c5a54f758666b302a8d34953131941b7957730476794d0bd9d2dfa72fd203f22df5ec6bbaace8b9394bebdaeaa561461011b4fca6185c9a38283f5403fdac326d1f734c6a5ded6724d9f384aebd6cabfcbec12abab9820d080732515e0500cf5d3e2f9ef80a4d7646a7da9eff410f507c69873b32d540ec32b283ef3179a4c632b366576dff058faf8c8c70bc69be808982ec1497ae8911b00165a66695f4d3b987e7390b5cf878e35e676541285e4e13dfaeb2f368cb511b778b106a428778a1b8f2a7d2e093519bc9b5188e38c6793e96bd0d30e2a3db9ee1468c3dc87cc365c810f9dbdf01a4b51421f6fc8dfda3a16e2da7ca7159b686a5e167338937882ff715d3e750d958fc9e4b1f0553129299aa8430183e506cd7f2b279076e0e1cca9749cf123ce507fe07ddbbc4dcca6cdb9ef1b833f61d4bff00bec012158f432ceb75b4f2edb1bb84e5ebb9259e09f9625ce3:b4c2321ade3c19ed4ed4c639d5a4d6f2be8e2fb13bb7bd625ad6dc87e2c20f93ad6be7b7e42711a878db9d76054bfd7bc25e3774a93da1543c9b4f6633b0be097bb7293de55f058fb2ec22b687260543dcaa90f140b9f45eddd4bc22e40977e00ed33cd1ef1bba13c1d0990859005569a80767e4864a2cd288c81393e04ad971782e2bc493108cbe80dacf0b7b9cd534988407a4f9327ec8e9c4043284ef6ee5a26a5b417765d3eabb48a007e7c7f32987d70a139ac41678cdf7a55cb80cf9db5eaa45f3de0fbfbadffc40996370e48b1ff5edd97940e750792164836a4a5ac2e3ff53e48a1e556db9ad0c5c0b944f4aee519a2b0a88bb1c1fc7454524cd57aa5350986243d34fc58e24e819ec0b8545d8dfcf6b20311441d3a35d3e71b3e3ecd7884dda8433a405e3d9969000c820a89b95d197841d98ae734a2e81daf6a7dcf56cb2fc26f2165a5f42b86c7e9e5b11161700a1ab9831f3fae58e14208be1bf33b58ecce81b0c6b7e02f88adf9ab030263e2cc9b6e33ebca3f495492e32bfe372537de6c6b87644828f74942a02b007f14c3fc5dbde76333d36d07631b7a9924f717550040697923fa7b9546bfb0217024ea3f252b515b5d64a62c48e027cef6750beda49a02447039b250a0bda07dc062491a662e26874c8d00f80e6cfc8b30f2c3bf7720b57f2615fc478fefaa6d31705b43c5a54f758666b302a8d34953131941b7957730476794d0bd9d2dfa72fd203f22df5ec6bbaace8b9394bebdaeaa561461011b4fca6185c9a38283f5403fdac326d1f734c6a5ded6724d9f384aebd6cabfcbec12abab9820d080732515e0500cf5d3e2f9ef80a4d7646a7da9eff410f507c69873b32d540ec32b283ef3179a4c632b366576dff058faf8c8c70bc69be808982ec1497ae8911b00165a66695f4d3b987e7390b5cf878e35e676541285e4e13dfaeb2f368cb511b778b106a428778a1b8f2a7d2e093519bc9b5188e38c6793e96bd0d30e2a3db9ee1468c3dc87cc365c810f9dbdf01a4b51421f6fc8dfda3a16e2da7ca7159b686a5e167338937882ff715d3e750d958fc9e4b1f0553129299aa8430183e506cd7f2b279076e0e1cca9749cf123ce507fe07ddbbc4dcca6cdb9ef1b833f61d4bff00bec012158f432ceb75b4f2edb1bb84e5ebb9259e09f9625ce3: +00db37ad2a195f08a08440d059259e539feb40b474928255e7c94ebc3b05038c04f88bf639e0f71a57d0d0afff5fe97dde3809ff28ec68eb6fc423f4faff4390:04f88bf639e0f71a57d0d0afff5fe97dde3809ff28ec68eb6fc423f4faff4390:5a94f729d30dd8aae2a5c8c28547bf4506295dc61bfead9727746082d43b0f8114c8c18c5edaf2fec7cae819356338f0bf115a17b038acfd7c96ba6262cabd5710fc0efb43d13df4065becbf1b9e279c03ec9bbfed54d9a13fe06a55a3bd05c807858b41e18dbde13b0907d4034132262d9c2f4d2d376e1609ad280de20ba709844dbd12950257f1b07ef8cc3337c01a702693fb4d92d047e698c3a6dd46c4a92a10d4c780e52e5025e09d56535d7eeb9fe7f033e6e9260a68f9d54b6f37cc069656e3bcee06922b349681a8e7751cdecbe1ecb663fbc6f7c861f853dc310f33defa98ee343a68632ec22cafecb7f3212f81e70b71843b9fe8c86a68b5c86f0322d348a76da7f1ba0ca3cd7b6fd15ff89292b3f636cd08cf625c74d5102cabb571a3dba86a1c92f41c7203b44942f5a24625ac37d77e49a57f118238699d807c250d5bf46f7a3cec5779a6e5ae1a6ca160cff37fb3b78388fe9c030c40e7154601081a517fc0aa1802cd3b845b946efe94aa8b9e03f68a80ded0dfbfad4daee40fa838c133841ae8a3ce0d79fa8a2b9434bac5e1da6e0c7193e8dea435a03a85f76184f7ebe2aa749be9413104a178689ba6d27e94fccf61eb3aba0e6a5a63af0ca8f05a35cb63705194e44d9293de3929b0d92be6f8e627c350a83fc9000aa95b93820be9795c80b5662cd7b34822328061356dc580578d1a35b10140dcd248e4853104d2c5b2c13ff683dd5c30794be4a76858af1c0d9af347ce1dcd972ee49aac12bbcd899c9329871d3e7a0683d175779afe35f26a2d248fd780ea851dc4ba6d21f8a171aa6cb8697d9d112161540307cd54f931775d70b33d3b6de1091fc1750531c08fa70f7be38aa110d6746bb565db7b470f900850fbbf1c662fd613e4f3a5689549e3107e9b0f17def7a5bd7fd7596c4d04c7f48c779fc35e09335e1df784084e55d8551d1ff49de5b311cd350f347a0bd2863a2a30e6ea183ad2e3eedebc18dd28c6a596e693dc3389f7d90b713e3a85a62516305a70667fc1fb3cb10e8a955750273943c568e10769cef78199df4450dbc490fef1b304b052221b2db9c44fe00345:f4d1c80f5e7b91c5c7a82a682d49ba6fb19d400a299748a0c969bb99816998be634e84da78581b06e3470efec39804fed93d29739f0439a8095ac40d9d385e045a94f729d30dd8aae2a5c8c28547bf4506295dc61bfead9727746082d43b0f8114c8c18c5edaf2fec7cae819356338f0bf115a17b038acfd7c96ba6262cabd5710fc0efb43d13df4065becbf1b9e279c03ec9bbfed54d9a13fe06a55a3bd05c807858b41e18dbde13b0907d4034132262d9c2f4d2d376e1609ad280de20ba709844dbd12950257f1b07ef8cc3337c01a702693fb4d92d047e698c3a6dd46c4a92a10d4c780e52e5025e09d56535d7eeb9fe7f033e6e9260a68f9d54b6f37cc069656e3bcee06922b349681a8e7751cdecbe1ecb663fbc6f7c861f853dc310f33defa98ee343a68632ec22cafecb7f3212f81e70b71843b9fe8c86a68b5c86f0322d348a76da7f1ba0ca3cd7b6fd15ff89292b3f636cd08cf625c74d5102cabb571a3dba86a1c92f41c7203b44942f5a24625ac37d77e49a57f118238699d807c250d5bf46f7a3cec5779a6e5ae1a6ca160cff37fb3b78388fe9c030c40e7154601081a517fc0aa1802cd3b845b946efe94aa8b9e03f68a80ded0dfbfad4daee40fa838c133841ae8a3ce0d79fa8a2b9434bac5e1da6e0c7193e8dea435a03a85f76184f7ebe2aa749be9413104a178689ba6d27e94fccf61eb3aba0e6a5a63af0ca8f05a35cb63705194e44d9293de3929b0d92be6f8e627c350a83fc9000aa95b93820be9795c80b5662cd7b34822328061356dc580578d1a35b10140dcd248e4853104d2c5b2c13ff683dd5c30794be4a76858af1c0d9af347ce1dcd972ee49aac12bbcd899c9329871d3e7a0683d175779afe35f26a2d248fd780ea851dc4ba6d21f8a171aa6cb8697d9d112161540307cd54f931775d70b33d3b6de1091fc1750531c08fa70f7be38aa110d6746bb565db7b470f900850fbbf1c662fd613e4f3a5689549e3107e9b0f17def7a5bd7fd7596c4d04c7f48c779fc35e09335e1df784084e55d8551d1ff49de5b311cd350f347a0bd2863a2a30e6ea183ad2e3eedebc18dd28c6a596e693dc3389f7d90b713e3a85a62516305a70667fc1fb3cb10e8a955750273943c568e10769cef78199df4450dbc490fef1b304b052221b2db9c44fe00345: +6ca1a1482a07f2a6c57f041197b34a5119e68903cf6dfb51711d9550973163c08034a55e3b6ed799f49e2e703a81f4ac02573c445d765e3069be42f09cbd18ad:8034a55e3b6ed799f49e2e703a81f4ac02573c445d765e3069be42f09cbd18ad:08fd8487503c3f3296b6f1b64d6e85906fd5986cf9c5d9fa8a59d92f44e6470af34bcdef336ffdc86456ec7a7b5761f1adea027326630e68abc6b8cd5ddf40b641a259ad024321bf3ef98e7632797149c492d53594752c550dfbc4fa6bf47176f423a2705693947aa90d68ddc8efb6cb9dbecafd2830d04fd93b1e9e7c12b93e0d0f3e2634900f25860ddadbaece1780ff2d3f3d9fb838fd0d5d66f8afb305ff1a1aedca2b974b63e43f5b3cc9dfed1bcf11999176ed9585ac829bc6794ef3acd872e8d2e92608b320f894996a562e1eb177e21be57c22c41ec259a3dff9c7c9491db838d76cf9b0383111598e357f44babebf121bdb24ee9d557b7d5af491a0a0365c90361fe4f7e3d13a17da3a39fd43f690dfb0b2d860cab419f775ab7152cdc8f2afdc50e8d5da5da01706eea2a2ffad4babee8b03da336a4d843d9d7e0a93f36a92e6610a368b63133f05a3fdc55e3e1a440b0f87a53364c1d37242c57a109e6df69345b01c21c1089e790a66f4f3380d3b76ffb420dfe1e6200eace579265a427fbd355514ef953e1a6e968e37021b3c6a290dcd0293da6768dad7c66311633051c0accb0b9165464dfddfded23bd13ef908744f9c2111dc153142d2f10534d893fe0b545fec53fdb3b35b518398b02ab21791fa977e30cf4b404e7a299d3787108b836aa0d59c114f1f36719a7acf85ac994d9cb72306f258f78ac0a3b6c05343e0b7a9aa726e52267edf97f4972f7664f43720ad33ce6e615440e36537cbc569bd6ff94ffdaea51e06029dae78c5b915c537caea6f1504147979b8aaae0bcd9618437ebed0b55efaec320e84c75959a37a260a02d4ef1bb62641520f1a03ddea8c4c1de8d7fac58da408b0ab4757a135f1d075c9f7c99fb99db9427ce9b0d626cb1ac189ad8663d7a714fb5cd1585c3bf99a0aa46d763978d0b12d65c438bbb73feaa51ba26a459e7bea25439466c08613e42540c8c6d54367f221fcce0c5eb6af2faa181ea21521809be75649cf8dee7671db7f948f346cbd0302bf9a06eabc72e2e512b3df885f6daa398f93e36dae2d6a04478121f97787d4cedff6db09aaf10f27b1:dd9bdbadd9fdc81ce230288c4a068df07e18b4c7cc51c0ca4811dfbd04765c56bc883240e46e3a42c01d8d2424fbc332b7c5a17bceb1f6e8dad0bfe562cad30208fd8487503c3f3296b6f1b64d6e85906fd5986cf9c5d9fa8a59d92f44e6470af34bcdef336ffdc86456ec7a7b5761f1adea027326630e68abc6b8cd5ddf40b641a259ad024321bf3ef98e7632797149c492d53594752c550dfbc4fa6bf47176f423a2705693947aa90d68ddc8efb6cb9dbecafd2830d04fd93b1e9e7c12b93e0d0f3e2634900f25860ddadbaece1780ff2d3f3d9fb838fd0d5d66f8afb305ff1a1aedca2b974b63e43f5b3cc9dfed1bcf11999176ed9585ac829bc6794ef3acd872e8d2e92608b320f894996a562e1eb177e21be57c22c41ec259a3dff9c7c9491db838d76cf9b0383111598e357f44babebf121bdb24ee9d557b7d5af491a0a0365c90361fe4f7e3d13a17da3a39fd43f690dfb0b2d860cab419f775ab7152cdc8f2afdc50e8d5da5da01706eea2a2ffad4babee8b03da336a4d843d9d7e0a93f36a92e6610a368b63133f05a3fdc55e3e1a440b0f87a53364c1d37242c57a109e6df69345b01c21c1089e790a66f4f3380d3b76ffb420dfe1e6200eace579265a427fbd355514ef953e1a6e968e37021b3c6a290dcd0293da6768dad7c66311633051c0accb0b9165464dfddfded23bd13ef908744f9c2111dc153142d2f10534d893fe0b545fec53fdb3b35b518398b02ab21791fa977e30cf4b404e7a299d3787108b836aa0d59c114f1f36719a7acf85ac994d9cb72306f258f78ac0a3b6c05343e0b7a9aa726e52267edf97f4972f7664f43720ad33ce6e615440e36537cbc569bd6ff94ffdaea51e06029dae78c5b915c537caea6f1504147979b8aaae0bcd9618437ebed0b55efaec320e84c75959a37a260a02d4ef1bb62641520f1a03ddea8c4c1de8d7fac58da408b0ab4757a135f1d075c9f7c99fb99db9427ce9b0d626cb1ac189ad8663d7a714fb5cd1585c3bf99a0aa46d763978d0b12d65c438bbb73feaa51ba26a459e7bea25439466c08613e42540c8c6d54367f221fcce0c5eb6af2faa181ea21521809be75649cf8dee7671db7f948f346cbd0302bf9a06eabc72e2e512b3df885f6daa398f93e36dae2d6a04478121f97787d4cedff6db09aaf10f27b1: +2784df91fea1b2d21d713de2edc6652451a0c15954b8656062ea1dedc2445b2a9556db5370f8fb3c7478de03d23df1cda96f2740118efdd3d1a9fa4c3bfe8849:9556db5370f8fb3c7478de03d23df1cda96f2740118efdd3d1a9fa4c3bfe8849:2e3bc54df416741dbe7916ad25f04e48d5a9d77a623e57f9cd61ecb44f09f76833eb2a3e9ab7aa89ff5d2d560c07177d854d7c49cbef492b7f4f7e567de1275124e16ca4a7980162fa0fd162a8e5fd6f35617007034bceec57c8faf7664f4b3baffdea8d8fc2ba22d585e9e2d739f5ffc99b4e0dbe9c3686547ea04815a59c4a25b5f2390668e418ba0fcbdf4c4a51f33905c74fbb830a19f9bc8636dbaaff209995447996d2e5b1c377b4cb87a4e1efe12de34d33599ff397b74017d711edd3e772155be5a4406e74cbe2931ef51359afd51b5b1a7b3ea22ee8eda81476bcc17ea7680f6f3104703b9f2a35cf2627eb741d1a30aa4beef6579ec7d0b07a4ef32abcb4d756970f70a3678e17e6e5731890aebc8c92b956d4b3b5fe2adfd79b211a1883dfc8c9a4b1b9c8c1bb265e1f3dd392445ea59b590a019551f8121849f435b3ac1b29902fc8392554056b93903d5f263b3d540843d6afa75a2ad8304b7690de99a734c3d130b69547b18b09e98cbf252730e4aedb6dc4b58b2243fe55e80939d37b0a59d72226d8a2cc5153095e15994ad62195aa310f2a6426676b661e47b9fcfffa04d6dc625f29f44c7cf620b378a65d238344b380448cd119cc7f373f62cdfad64149906353f3a54107c5dba65e3cc494b0531f4d64749363f230738b2cfeed983520227dd5bc43be59b3268e283216f6e9c75e0c1c71272e54fdb29c7858d287d1efa1917be37c8eeab5e44c3ad7b36e8ac9f66991eb82a5148e5972034ad01c62615a45154579fa50869e7be9876b5656eaad2e43025a62dd134b612d8f4d5ebcf8056e198b713438e8e0e347cafbfcb89e394aa330d4c788d49c658fcfc80b3e0078f0e8e19aa9b8fe8eb0bab93de785d043e0f475aeb60d62e38fb1f8384a00b7a902daee13d2136269e50801b80a65b2f913cfe3ffb365d9aa2fd19372a0b0225695444e4bc54871d108e09c7e1c2b42dcbbacce24ea5bd5bf1fcf4ac697a3fe09a54677b7a8dc8d5eecb86cc792ee9b6fea2de16a473269fdc65dbb73c258c821440407c642f7d3d3f5c708d55332da8343106c19b230a51427f3b771916ae3688b:17d171d946de3516158407e132cc1acecaefd6d092112be653999523e20bd495f7b7f600e8d5a671330d32693d6019c08d2d003b176e6319c35394200e027d0e2e3bc54df416741dbe7916ad25f04e48d5a9d77a623e57f9cd61ecb44f09f76833eb2a3e9ab7aa89ff5d2d560c07177d854d7c49cbef492b7f4f7e567de1275124e16ca4a7980162fa0fd162a8e5fd6f35617007034bceec57c8faf7664f4b3baffdea8d8fc2ba22d585e9e2d739f5ffc99b4e0dbe9c3686547ea04815a59c4a25b5f2390668e418ba0fcbdf4c4a51f33905c74fbb830a19f9bc8636dbaaff209995447996d2e5b1c377b4cb87a4e1efe12de34d33599ff397b74017d711edd3e772155be5a4406e74cbe2931ef51359afd51b5b1a7b3ea22ee8eda81476bcc17ea7680f6f3104703b9f2a35cf2627eb741d1a30aa4beef6579ec7d0b07a4ef32abcb4d756970f70a3678e17e6e5731890aebc8c92b956d4b3b5fe2adfd79b211a1883dfc8c9a4b1b9c8c1bb265e1f3dd392445ea59b590a019551f8121849f435b3ac1b29902fc8392554056b93903d5f263b3d540843d6afa75a2ad8304b7690de99a734c3d130b69547b18b09e98cbf252730e4aedb6dc4b58b2243fe55e80939d37b0a59d72226d8a2cc5153095e15994ad62195aa310f2a6426676b661e47b9fcfffa04d6dc625f29f44c7cf620b378a65d238344b380448cd119cc7f373f62cdfad64149906353f3a54107c5dba65e3cc494b0531f4d64749363f230738b2cfeed983520227dd5bc43be59b3268e283216f6e9c75e0c1c71272e54fdb29c7858d287d1efa1917be37c8eeab5e44c3ad7b36e8ac9f66991eb82a5148e5972034ad01c62615a45154579fa50869e7be9876b5656eaad2e43025a62dd134b612d8f4d5ebcf8056e198b713438e8e0e347cafbfcb89e394aa330d4c788d49c658fcfc80b3e0078f0e8e19aa9b8fe8eb0bab93de785d043e0f475aeb60d62e38fb1f8384a00b7a902daee13d2136269e50801b80a65b2f913cfe3ffb365d9aa2fd19372a0b0225695444e4bc54871d108e09c7e1c2b42dcbbacce24ea5bd5bf1fcf4ac697a3fe09a54677b7a8dc8d5eecb86cc792ee9b6fea2de16a473269fdc65dbb73c258c821440407c642f7d3d3f5c708d55332da8343106c19b230a51427f3b771916ae3688b: +4bb79236fada3144b68296499ba44ae534074ca94d4b581e5edcfffe13b3ad190a8399f1e5a423dcf7b25b2fb0ac9e1e9548148bea84d021e0428760e05d58bf:0a8399f1e5a423dcf7b25b2fb0ac9e1e9548148bea84d021e0428760e05d58bf:ad81abf6937a7acd7f1837f04d3f10e708c61a5fbedeee4db76e1598570384e6efece97c925d2e5c3488cab10b5b52b8a5486e99d8ffe86c1981a1f1d532dcd4d489e5546d86653298e7a5f96e8144552dda8a18e75b5f7355b13541621106e497e51a56d8659d198fe10037e22128afc2714a2cb5a12cc5db0968a343ef918e8769dd6a3e5b9e32aab66cb0239ebe4c17f18218e252eba6162e977049ebac0b38048b3aafb7d4d72263e9212899a3bfe0a69c99e22ac61c5e9612456303d92458b5c502916c34a8ee5cd9a582a52576b6dc9d7d4c642f212998bf3358d4a8c2ea67686e55d489f6a76e6b070e6e995a745326c9aa63630a0033ad30721aa65fac604a6e58c750721a56ca6760c94134d611fab4d354e4f66a29677b1a666601e9da79f213f582037433c07f94d5f0de6aa9faa0b32f7b023fb9fc135a26f97052ac80b39b306aed13926c285419a29b20e2370d8a095b32258fa9893489ee21089c752ec062e120359e2f3515128254c8098cca65a91a022dd057a2c2a1b6b85d137c3c967dcb70aa17a2ff4b37678b382902f0f931ee743fc398ac1b8c10469867308479e40d7f2f04a4b04c4489158488ddb7bec5a47f20ff356d99a1b3e9d0b7fe9b0ad949f298960efa4d9728f8101cf53da3bffdd9524bf440a58b32738d0b6293e853f466ffd42c5607ac9e353ba03efb578cc9963d8aaa9d2e266d1d2ae9296f30c9ef44ec691030d596a401b6cee72a540ef3c42ec0174266ba5401f354adc8e25404437e888b08286939bede308acd30327ebff06270097cc294f0a0f39f9aa3c66585ca47e60c4b8ea36089eb8a9088bb18b0343135bb6a456d2f6a3bf390723e78b42c037c2de2e1432caad3a594021294d43f5b15a2e819dc748e451de40068c8f032f13b4711377012edcd4f11dec1111b12eb6e1b00633818706d7132d991ce20df3b921db2185ee25bb6f5827576ec01ad890f79793baa358c2bbfb6faad11d8cb0d0d2d2b2981fbf4e372349fc6a01c36077b59325f702b380059a65cf2f5ea98d6bdc8152053b85b28c81e413c4cac7e226c13db3267d21830f0e5431102917005:698fab68510db8121a465db77e4f8b586aee895816e63bbf0beb242db4e84c157f4be201ae6564517a870d17f60c858370c01cca17189cb4189e814391d1500dad81abf6937a7acd7f1837f04d3f10e708c61a5fbedeee4db76e1598570384e6efece97c925d2e5c3488cab10b5b52b8a5486e99d8ffe86c1981a1f1d532dcd4d489e5546d86653298e7a5f96e8144552dda8a18e75b5f7355b13541621106e497e51a56d8659d198fe10037e22128afc2714a2cb5a12cc5db0968a343ef918e8769dd6a3e5b9e32aab66cb0239ebe4c17f18218e252eba6162e977049ebac0b38048b3aafb7d4d72263e9212899a3bfe0a69c99e22ac61c5e9612456303d92458b5c502916c34a8ee5cd9a582a52576b6dc9d7d4c642f212998bf3358d4a8c2ea67686e55d489f6a76e6b070e6e995a745326c9aa63630a0033ad30721aa65fac604a6e58c750721a56ca6760c94134d611fab4d354e4f66a29677b1a666601e9da79f213f582037433c07f94d5f0de6aa9faa0b32f7b023fb9fc135a26f97052ac80b39b306aed13926c285419a29b20e2370d8a095b32258fa9893489ee21089c752ec062e120359e2f3515128254c8098cca65a91a022dd057a2c2a1b6b85d137c3c967dcb70aa17a2ff4b37678b382902f0f931ee743fc398ac1b8c10469867308479e40d7f2f04a4b04c4489158488ddb7bec5a47f20ff356d99a1b3e9d0b7fe9b0ad949f298960efa4d9728f8101cf53da3bffdd9524bf440a58b32738d0b6293e853f466ffd42c5607ac9e353ba03efb578cc9963d8aaa9d2e266d1d2ae9296f30c9ef44ec691030d596a401b6cee72a540ef3c42ec0174266ba5401f354adc8e25404437e888b08286939bede308acd30327ebff06270097cc294f0a0f39f9aa3c66585ca47e60c4b8ea36089eb8a9088bb18b0343135bb6a456d2f6a3bf390723e78b42c037c2de2e1432caad3a594021294d43f5b15a2e819dc748e451de40068c8f032f13b4711377012edcd4f11dec1111b12eb6e1b00633818706d7132d991ce20df3b921db2185ee25bb6f5827576ec01ad890f79793baa358c2bbfb6faad11d8cb0d0d2d2b2981fbf4e372349fc6a01c36077b59325f702b380059a65cf2f5ea98d6bdc8152053b85b28c81e413c4cac7e226c13db3267d21830f0e5431102917005: +afd765e6aac0146d4811ef9597bc3f44763f03378b7be033d6e64ca29decaef96bb76123d9258922686c53fb6917b9a459cabd30be8c43970d80f5350c2d98ef:6bb76123d9258922686c53fb6917b9a459cabd30be8c43970d80f5350c2d98ef:183b1092c7904e47a1420317a25d0f59110aa84d6b3419ad456865c43b29e9d1dacf755d9e5cf94c5591d5d912d05ca9a52d015d6e8f5dc94efdce0d7cf5651203b11e5427a9f679429e00414a48eab13fd8e58b87eba39d1025d6a18b2cdcbe147436dbf38a1ce86413ae318765e1bb1df7e2b3be97e90408b11717cf459bcd0f3cac58b4a0d35bffb533e20df37451c11401ce1dab02055c7e08c5ec46390cd617a6b5f22f651830a1112a06ede4c40ab7957851d6c66f171cd16241590900b852a3d019957be1b7bb7acb8923f2a357c3264456cfca9b429d71fecb7edae39b252b4eb610e8c718835699754b8d4124b492488ede62610cce44b59218663b6c9646a14a8417eddbb6f4fbe5a4bbbb482b37a445e3c16b65a141cd3e12a5b2c0481d614d6d208479b9b209b828854dae0ea1eded506555fe18e1854005cf001a8077083498d27fadf118286b53b8974d69fa2825be8ca3d6036a92ca52f91dde6d5b1ffe2888f4d60779fad1fb41d8c0714049af681b755f2d4204eecd09e077210a48a195e72c80e127c3d4875095c6570a1f78095907528cf7746f31d97111c6f4cb25b3741299a7574822d46b6e79ed23c2fe057b3ac7290b460b166ee90a45562effedcc6ba8f4795f7395818db56b6edd59ca2cc4aea1841fd9565becd6c08104cdee26ba9de200773d091bc77a57c547f1a6ba0a2cd717ab32561d7422ea7235adb0cb36bf5cbdf88fcae06630a15647d9a357b4e0e502d273f3796a51e0bc3fedbf7a1e64aad722aac5fd022fa79d60fc707325f127eb1f03868795ccdc0b4cb26f2023d152153a97a260bff11745d2e2cc0bf860d4a6e358a6d8176d2ac178a9ae1a2dc75e8b490408ff7cdf991329f33cb0c05e1e356925087e0b8d96a52351d1d17768eb134cdb21a1546aaedcc687dfa1b22e92fb5241a83677a153445b77d5e703508e2abc588a9f42e5bc710673e4dd8ad703fab2d7db1eb84226c89d8762a709e3e9138a1fa790f2929bff61bc1ea6e8aa1ad0e3887d70a56d4e6547fc606a50d3be3bd6db03663e00ca9e4f24fe8cbfd7d8c9738d6367554b7b601f74190b5970a398:3dc9194d50811419049eaa07b655b7d4064bcb0e7fb5f9e5326b5fc856fc0ab8705973ae1001df55373977dde2d9b81079551414adc71cc852d499b0cf824f07183b1092c7904e47a1420317a25d0f59110aa84d6b3419ad456865c43b29e9d1dacf755d9e5cf94c5591d5d912d05ca9a52d015d6e8f5dc94efdce0d7cf5651203b11e5427a9f679429e00414a48eab13fd8e58b87eba39d1025d6a18b2cdcbe147436dbf38a1ce86413ae318765e1bb1df7e2b3be97e90408b11717cf459bcd0f3cac58b4a0d35bffb533e20df37451c11401ce1dab02055c7e08c5ec46390cd617a6b5f22f651830a1112a06ede4c40ab7957851d6c66f171cd16241590900b852a3d019957be1b7bb7acb8923f2a357c3264456cfca9b429d71fecb7edae39b252b4eb610e8c718835699754b8d4124b492488ede62610cce44b59218663b6c9646a14a8417eddbb6f4fbe5a4bbbb482b37a445e3c16b65a141cd3e12a5b2c0481d614d6d208479b9b209b828854dae0ea1eded506555fe18e1854005cf001a8077083498d27fadf118286b53b8974d69fa2825be8ca3d6036a92ca52f91dde6d5b1ffe2888f4d60779fad1fb41d8c0714049af681b755f2d4204eecd09e077210a48a195e72c80e127c3d4875095c6570a1f78095907528cf7746f31d97111c6f4cb25b3741299a7574822d46b6e79ed23c2fe057b3ac7290b460b166ee90a45562effedcc6ba8f4795f7395818db56b6edd59ca2cc4aea1841fd9565becd6c08104cdee26ba9de200773d091bc77a57c547f1a6ba0a2cd717ab32561d7422ea7235adb0cb36bf5cbdf88fcae06630a15647d9a357b4e0e502d273f3796a51e0bc3fedbf7a1e64aad722aac5fd022fa79d60fc707325f127eb1f03868795ccdc0b4cb26f2023d152153a97a260bff11745d2e2cc0bf860d4a6e358a6d8176d2ac178a9ae1a2dc75e8b490408ff7cdf991329f33cb0c05e1e356925087e0b8d96a52351d1d17768eb134cdb21a1546aaedcc687dfa1b22e92fb5241a83677a153445b77d5e703508e2abc588a9f42e5bc710673e4dd8ad703fab2d7db1eb84226c89d8762a709e3e9138a1fa790f2929bff61bc1ea6e8aa1ad0e3887d70a56d4e6547fc606a50d3be3bd6db03663e00ca9e4f24fe8cbfd7d8c9738d6367554b7b601f74190b5970a398: +eb347145f339edd802785b6fbecd5cb80889ac7ce4ebad2f67076765db939bca994a456eada03020921c3d109c135eb961fcd4a0a400bafd32ca061bbc862543:994a456eada03020921c3d109c135eb961fcd4a0a400bafd32ca061bbc862543:5b8b31baf88483f095b5d02e17d8b7b46cf46460e64c6b02c56d8dafe34823706cb5c15f338ad9b56586a949711aa7312cc93450d2fb9af4613fc30793a631a55c14e53c0cb15f06116399398c8dd61876c62915f9f9e4cdf8f7d89ade129e6dde7d63671a1863f5da8f42ea64c079ecb9a2c1b1dd9adae60e96b9cbbc7624532aa17975eba17a7af02bfb219aac02b3d4306cd38933a85060cd62ab513a3965b09150a488c92bf7cab0482eee56463f0139009b9fbb3ff4ecae211f428b5bfb8876f004983b90c447846ca4b74566e979bc30c95e99faab69a3ebbfe4da6034c82d63e9c5ccaf8486af3b5e0d381422938b0c22f516955bdc36943173f5832708a33cf52d8875d97fde585b4917e4adecdd1e79856762033af22f254b50ce9d0c700e77a731554fa0113a0c666683f3fdb19e3a426302230b63e33a785ef24a9289455b3b8fc618fffef49c2c6e48fd4bb422f504149de2b4c0355c363408e66da81cbb581552a411e364fe3e4ca96d7072ab072e7568c13d35e41c7825a13a5c68fb9fb5988bbbfb9a0b51165764660cdfa2411f3d42165da187c58edef0105a6db177420543e958d5d5e8a371f7987051c4e1786d018eb3d732c210a861acaf671be95bb63fbc88bf8be7be5390939cd9fb2acf3981dda61b787a7bbd78468e1d32ca46af8fb32a18463c180f524be1da910da5508d42a0051741227c9b62de6d19b33c0bd48067b035859ad9bdc2ddd97befca31e65a886cfc753afc4ff2a7212a89d37c046cdf3999c051ff1396bd99cb54945639eb6462db9ece84077b0b3d6b3df3952dd36756c6dab2abc25a51bf32c1e9cdd0a728a7985f7b7e0d9c1a6f66ce1216373d252daf5958f2e8973fd268fad0efe251ce76fe47bd0a4d0c4f1017949d4c2b16717218e149154ed6fbe56f86d82e19ef0a91631912f2a8f3debb00766b6177802f4b2e79f6e7bfa9c62cfa2f75cdb60492630a85c9b43177d2dd9ba8d0548abe24923ae8443eeadcd0f58a7b82dff50d884003889cb560f7ac53e710a75575362464b1aa43d2a9b22f2bd2162d302faa7452344ce7ade9983687b6c68eca47dddb289b15:fdbd15e1e6469df720d9552cb5dd177bcbd292fcda83cd93c88d0114912dc8703109bac0d459ace9957df2293ac16d40d514893556853299b97b4fd4137a3d005b8b31baf88483f095b5d02e17d8b7b46cf46460e64c6b02c56d8dafe34823706cb5c15f338ad9b56586a949711aa7312cc93450d2fb9af4613fc30793a631a55c14e53c0cb15f06116399398c8dd61876c62915f9f9e4cdf8f7d89ade129e6dde7d63671a1863f5da8f42ea64c079ecb9a2c1b1dd9adae60e96b9cbbc7624532aa17975eba17a7af02bfb219aac02b3d4306cd38933a85060cd62ab513a3965b09150a488c92bf7cab0482eee56463f0139009b9fbb3ff4ecae211f428b5bfb8876f004983b90c447846ca4b74566e979bc30c95e99faab69a3ebbfe4da6034c82d63e9c5ccaf8486af3b5e0d381422938b0c22f516955bdc36943173f5832708a33cf52d8875d97fde585b4917e4adecdd1e79856762033af22f254b50ce9d0c700e77a731554fa0113a0c666683f3fdb19e3a426302230b63e33a785ef24a9289455b3b8fc618fffef49c2c6e48fd4bb422f504149de2b4c0355c363408e66da81cbb581552a411e364fe3e4ca96d7072ab072e7568c13d35e41c7825a13a5c68fb9fb5988bbbfb9a0b51165764660cdfa2411f3d42165da187c58edef0105a6db177420543e958d5d5e8a371f7987051c4e1786d018eb3d732c210a861acaf671be95bb63fbc88bf8be7be5390939cd9fb2acf3981dda61b787a7bbd78468e1d32ca46af8fb32a18463c180f524be1da910da5508d42a0051741227c9b62de6d19b33c0bd48067b035859ad9bdc2ddd97befca31e65a886cfc753afc4ff2a7212a89d37c046cdf3999c051ff1396bd99cb54945639eb6462db9ece84077b0b3d6b3df3952dd36756c6dab2abc25a51bf32c1e9cdd0a728a7985f7b7e0d9c1a6f66ce1216373d252daf5958f2e8973fd268fad0efe251ce76fe47bd0a4d0c4f1017949d4c2b16717218e149154ed6fbe56f86d82e19ef0a91631912f2a8f3debb00766b6177802f4b2e79f6e7bfa9c62cfa2f75cdb60492630a85c9b43177d2dd9ba8d0548abe24923ae8443eeadcd0f58a7b82dff50d884003889cb560f7ac53e710a75575362464b1aa43d2a9b22f2bd2162d302faa7452344ce7ade9983687b6c68eca47dddb289b15: +3208837d1554b6511adda09cbae565da78439a472a5d1b107ce0a9b1d7757db79b525e35368a921e3a2e9a35a4de9ea4c436caba27123e5c369e2a6cf5c90ab6:9b525e35368a921e3a2e9a35a4de9ea4c436caba27123e5c369e2a6cf5c90ab6:436a3c31763f93d4d546c6d1ecfb7ae45916af754f839dcfe96d6b69c61214d016fc842f56462a3f07f661b2e2505acfaf482a0b0f4f5501eec4b2d2d7d444544de000b990f4363d3f983f5d4e09309752ff579c7320c915951cc3a1e3238c1ba7a19130eabf6a37f5f0bc56e25242f752061f3c63acad992a7501e967deb925b30ed105431e582102fa4f308c2f0683612b56686d52daed6943a7219f3beea2e0a29242e86d5562ffab83b56b263326664e029e961e7017d8e89f5e3e1d10f5932854550ce6e5cd76971fd235cf9c0027d0cfed3315c2cbf18508624d8acf047f9b968f907d9e6f4cfa5e45c80a272c2dbb62c5d4194580dfabedd82cb4d76492344be96ccf5daaf61e6b2b55efdb3f65210a3d6e1f369887ca0ea0d58c3d146ae3cf9b000076884115fa51b5fd66bec0ccbf0d2920196a7d7a38445fbed22dfc7564dc56f60d6e29e592485374c6bd1e5b15931b69ca6ee6b3aa2525c23585f0929f31cbd11fb1a5330216b90ae5a656df7a074cec64e598184f503fb23cc05e65da9ae7e8441f40e2dc26b8b56d2cb523a7c635dc0847d1cd498abf756f5a13ea14f8fab2c410b1a470f49aa8dca4ac0256b11800de0dd0ec42b142c561128d357e783b12f61c668f5e6e06b7b48b7b2254de5bdc1804b723d5fd6a0f4bc7c59e7c5054182613bbd2fa92b4c1da16bc8c97e16bcb0dbf8c92b74899b37f318757140b6c4fd535e2e1e0570a50818cf78fb988e1f4ce40e76e8fe3d697d7a45850f293ce170fd8ab07cf1534ea5ffad34f6fcfa42d0d21a91dfbfe0597c73fd9b9767614ebdfd02c3ac0c49ad10c94be5969ee0808c0a30b2a1eaa90ea43b8575c3056f423cd4b6f34ae51c2223765a9ea21f64573c1a13961321246e3b5349ee048fb62d5fb61b1714391182562b91598360e5f9bf4ac80db246432afb3a43d349650de03d343c2e97a8eefd1bf30c10c25867f53266bd1f0dc14ae1a6be9efdecff67e7d292c6cdfc90d80b886668f04c2a0f5ad7fa17c178b6e9b45a11f4ddfe2d66960a3f75135ad5ed154e513e1a5d138e7371e84d7c92453e6c62dc59b8e1fa93d773a2540d91c257c:709d1ca9ca2f742ab9dd0b049335f544cffb2f1a3693d5f53f8ba083b9b0d86e5208fa8e1e8156c9cc2242775abb7e15af3085868ef457634e9926c404ecf30f436a3c31763f93d4d546c6d1ecfb7ae45916af754f839dcfe96d6b69c61214d016fc842f56462a3f07f661b2e2505acfaf482a0b0f4f5501eec4b2d2d7d444544de000b990f4363d3f983f5d4e09309752ff579c7320c915951cc3a1e3238c1ba7a19130eabf6a37f5f0bc56e25242f752061f3c63acad992a7501e967deb925b30ed105431e582102fa4f308c2f0683612b56686d52daed6943a7219f3beea2e0a29242e86d5562ffab83b56b263326664e029e961e7017d8e89f5e3e1d10f5932854550ce6e5cd76971fd235cf9c0027d0cfed3315c2cbf18508624d8acf047f9b968f907d9e6f4cfa5e45c80a272c2dbb62c5d4194580dfabedd82cb4d76492344be96ccf5daaf61e6b2b55efdb3f65210a3d6e1f369887ca0ea0d58c3d146ae3cf9b000076884115fa51b5fd66bec0ccbf0d2920196a7d7a38445fbed22dfc7564dc56f60d6e29e592485374c6bd1e5b15931b69ca6ee6b3aa2525c23585f0929f31cbd11fb1a5330216b90ae5a656df7a074cec64e598184f503fb23cc05e65da9ae7e8441f40e2dc26b8b56d2cb523a7c635dc0847d1cd498abf756f5a13ea14f8fab2c410b1a470f49aa8dca4ac0256b11800de0dd0ec42b142c561128d357e783b12f61c668f5e6e06b7b48b7b2254de5bdc1804b723d5fd6a0f4bc7c59e7c5054182613bbd2fa92b4c1da16bc8c97e16bcb0dbf8c92b74899b37f318757140b6c4fd535e2e1e0570a50818cf78fb988e1f4ce40e76e8fe3d697d7a45850f293ce170fd8ab07cf1534ea5ffad34f6fcfa42d0d21a91dfbfe0597c73fd9b9767614ebdfd02c3ac0c49ad10c94be5969ee0808c0a30b2a1eaa90ea43b8575c3056f423cd4b6f34ae51c2223765a9ea21f64573c1a13961321246e3b5349ee048fb62d5fb61b1714391182562b91598360e5f9bf4ac80db246432afb3a43d349650de03d343c2e97a8eefd1bf30c10c25867f53266bd1f0dc14ae1a6be9efdecff67e7d292c6cdfc90d80b886668f04c2a0f5ad7fa17c178b6e9b45a11f4ddfe2d66960a3f75135ad5ed154e513e1a5d138e7371e84d7c92453e6c62dc59b8e1fa93d773a2540d91c257c: +4ec6829b43997056d99685389bd53c528de7e5ff2715d65c956619826e3fb5b57d922d57fdb12792879aec4e8c651463ece064492c721753d22e115509fed706:7d922d57fdb12792879aec4e8c651463ece064492c721753d22e115509fed706:ed26b4130d4ebf3f3861491aa3dd96a4eb69752173fa6c84ca65dfc991c7fe44e02bd61650252a1d23786682ec38c1fee82cc350db7c3c3949a1c935ffebd7baa24f35a393fbd27e7c34c2f9ffda60a18df66c3e465d90ed48fbbad3fa7947dee7e659a3eeadb887f0963f6bdd76c36c11ae46d088ee50bca8187a0a8832db7984b7e27cbe6abf12d2c94f337ec78cb38b26241bd1a3d2f5fa4407fdd80227d2b170144b415978e37201d0fcf43174b9d7b2115d5eb8bcec276a775aea93f2340d4425d34d2047494d917e0dbe37857e6c99859b71c914aad5e54f7b2b033e594e272cc5cfe919f888e55cb6157affcf357246d00b532cc471b92eae0ef7f1e915944c65279315729853da572c809aa09d40365f90875a50d31ca3900da77047c957c8f8bf20ec86bd56f9a954d9988e206b444ca5a4434521bfc9c5f3a8a06147eb07d11dfe1171ec31ff55771588b333eee6215d216c47a8566fbb2b18974646ac5a92c699d77584c0defefd2dfa58fca27199e41ec58a246320b35faab75b97951924226da4ab28f01b47078e712e4fd9f77b251c9667858c28e32ef1cd01fcbe435c542dbad0a84a13cdbb5775e62d811dc690d9555c37f15f91767a561357df106eefe056e7360670650fb818fc6adc59973e9ad5cdcd809807ab56397f3c13948732d98d676f4a4470a95d8b518237e226f0cc5f4765164a5c3ef050714be02a126be8f66546481581b9e94a26aad24c693b7fdbc18acd3ed7cfc47d8ab26745d78e701d0cf05dd844b5b345a29dab684cbc5092ba022e3c582dfc044c3100ad02756697a849822915a16e2a2b810e6815f54421d2f3a6fff588c0d9013c76f33e09beaeef60d8774230e8ce7131289aef2a40686c819fb2040b06124d3d9aa419d56788f17fa7ed9b9b57ceaad1337a0101bea0440cff745ddd9722055d1f9bcfb009ce2c2f41a9e7e86806b872cdc2059bc8ec68f5ee56c4bacf4bbd30ea4c7155864d600c0e2eee73b319bda4372e9c603c772c25890c7610489989475d37a77a4574a2ba55bfd9c9cfd146fb97e6165dcc19559f4f85dfca2f97f3702ed8fa6b3c2a9741974aa07ab6:159ca404f7f74117c5163cf404110949eb57ae2d7662b1ff4178cc6756e90adaeab71b064ce1dff457b2dba7e2dc13c217bcae8a61fcf8ce1487a649c257ff07ed26b4130d4ebf3f3861491aa3dd96a4eb69752173fa6c84ca65dfc991c7fe44e02bd61650252a1d23786682ec38c1fee82cc350db7c3c3949a1c935ffebd7baa24f35a393fbd27e7c34c2f9ffda60a18df66c3e465d90ed48fbbad3fa7947dee7e659a3eeadb887f0963f6bdd76c36c11ae46d088ee50bca8187a0a8832db7984b7e27cbe6abf12d2c94f337ec78cb38b26241bd1a3d2f5fa4407fdd80227d2b170144b415978e37201d0fcf43174b9d7b2115d5eb8bcec276a775aea93f2340d4425d34d2047494d917e0dbe37857e6c99859b71c914aad5e54f7b2b033e594e272cc5cfe919f888e55cb6157affcf357246d00b532cc471b92eae0ef7f1e915944c65279315729853da572c809aa09d40365f90875a50d31ca3900da77047c957c8f8bf20ec86bd56f9a954d9988e206b444ca5a4434521bfc9c5f3a8a06147eb07d11dfe1171ec31ff55771588b333eee6215d216c47a8566fbb2b18974646ac5a92c699d77584c0defefd2dfa58fca27199e41ec58a246320b35faab75b97951924226da4ab28f01b47078e712e4fd9f77b251c9667858c28e32ef1cd01fcbe435c542dbad0a84a13cdbb5775e62d811dc690d9555c37f15f91767a561357df106eefe056e7360670650fb818fc6adc59973e9ad5cdcd809807ab56397f3c13948732d98d676f4a4470a95d8b518237e226f0cc5f4765164a5c3ef050714be02a126be8f66546481581b9e94a26aad24c693b7fdbc18acd3ed7cfc47d8ab26745d78e701d0cf05dd844b5b345a29dab684cbc5092ba022e3c582dfc044c3100ad02756697a849822915a16e2a2b810e6815f54421d2f3a6fff588c0d9013c76f33e09beaeef60d8774230e8ce7131289aef2a40686c819fb2040b06124d3d9aa419d56788f17fa7ed9b9b57ceaad1337a0101bea0440cff745ddd9722055d1f9bcfb009ce2c2f41a9e7e86806b872cdc2059bc8ec68f5ee56c4bacf4bbd30ea4c7155864d600c0e2eee73b319bda4372e9c603c772c25890c7610489989475d37a77a4574a2ba55bfd9c9cfd146fb97e6165dcc19559f4f85dfca2f97f3702ed8fa6b3c2a9741974aa07ab6: +b150a78929ed1eb93269213e1ebc22e2e40a601bdb005499b7beb058917c534028866b6d1c393cb08e464cf5571440a649e50642380ddf4ffb7ad150485c108e:28866b6d1c393cb08e464cf5571440a649e50642380ddf4ffb7ad150485c108e:1bf55d27f9dde6c4f1c0ddd360a25d9493c0ffdca74a7ed5e5a514e95515cda4aad8f45cd6ed7901f8f224a63b38121cbeac2f56dae210dd053750cb207514a8891e245a5d07e7de78a2e3814463f148d2acb7dc71f995c9299ad0d6266cfefc94269657fd47cf5312b92af2750651c479636c9d36aef08f7d1195e7fa1ba3abb5dcb90136b0fb9a37668b87a2db88d1e2b6440d3e6e601e6d4bc10cf1cbdf1d6169c0dc2c4aecdeb6cdd4567d4250b2afa715b166c9467f907d3fa5a6daf200b309c109376830499caf3149001cf3339448ca3d765225d6b3c1cd267cba936e7aa4832539466fd20cbb38323cbb2228a271f2d282561c73ed79a1ad04698e27efe393235f3456c295407da0960f0034d8deefd1c185736fd3eaf1f9a1e32f09174c1fe12720b7c96febdb33e01b1b6a1c637150194be4ffab159e45b24585576846bb64274eca7b39a3ed9357de7b084213024a9e8589263600a2867c2a7cf8b99076a12a07bd7df8d5277bb04ad72e639b77eaca1ec58ef9637e9a2376ba878a457235a06f78fdf0e0d925cb2fd2a38c77188f60372ef6009792424399c9b67928da2e3ba91cbde407e7e876ba98139ed22ca3b983bede0000528796448e4a1055acb2deaa56bc308254c5bd498c275ecedc1357efe1fda01d34d916dd4d8647e5771995a653e0f8a5284cc7bf73157b3349d59e6f920cad6cdd1719f038025c4300e0210ce249faf3c82de1fd1cdabe61c14ecb1df00c5c466aa6a012a9c10dcfe59b7e9d3b155dab6c7b7c1608c1edd51dbdadf6ba5876b5e60fdf7f19e6ef712cd1a7dd3a062a6574a7436b319efb944e4223f542b2502c1ba976be91e05b0f85a09fd793beca883375fb67cd133f5284d89984ff3cafa7e11a9d85e7893232a524ec54b20f975d3c0a1143a0ef41176b7051ea91d40c5f44fd9e100558bf1212a7b891e68b55ca61f4be945266d9a1007a14aaeb68c48e257f0f46310ad16481467ec1773535d5fc084915f5d004ba0dc7591d2123c62207909d84f2b382f5ef12759a95cd3f5189806e273960aee162c00f73e7fa59363957654bb1916b5709bb0a9d040514ae5284951e6b:276dd0962e6ee64f0592441a8af0e5ef8f93bf0baeba20504b9db4f95a00b939ea38def1c797862898cabe9dc4644f0e677e87c0a33b87b6a4d22a807d0e1e021bf55d27f9dde6c4f1c0ddd360a25d9493c0ffdca74a7ed5e5a514e95515cda4aad8f45cd6ed7901f8f224a63b38121cbeac2f56dae210dd053750cb207514a8891e245a5d07e7de78a2e3814463f148d2acb7dc71f995c9299ad0d6266cfefc94269657fd47cf5312b92af2750651c479636c9d36aef08f7d1195e7fa1ba3abb5dcb90136b0fb9a37668b87a2db88d1e2b6440d3e6e601e6d4bc10cf1cbdf1d6169c0dc2c4aecdeb6cdd4567d4250b2afa715b166c9467f907d3fa5a6daf200b309c109376830499caf3149001cf3339448ca3d765225d6b3c1cd267cba936e7aa4832539466fd20cbb38323cbb2228a271f2d282561c73ed79a1ad04698e27efe393235f3456c295407da0960f0034d8deefd1c185736fd3eaf1f9a1e32f09174c1fe12720b7c96febdb33e01b1b6a1c637150194be4ffab159e45b24585576846bb64274eca7b39a3ed9357de7b084213024a9e8589263600a2867c2a7cf8b99076a12a07bd7df8d5277bb04ad72e639b77eaca1ec58ef9637e9a2376ba878a457235a06f78fdf0e0d925cb2fd2a38c77188f60372ef6009792424399c9b67928da2e3ba91cbde407e7e876ba98139ed22ca3b983bede0000528796448e4a1055acb2deaa56bc308254c5bd498c275ecedc1357efe1fda01d34d916dd4d8647e5771995a653e0f8a5284cc7bf73157b3349d59e6f920cad6cdd1719f038025c4300e0210ce249faf3c82de1fd1cdabe61c14ecb1df00c5c466aa6a012a9c10dcfe59b7e9d3b155dab6c7b7c1608c1edd51dbdadf6ba5876b5e60fdf7f19e6ef712cd1a7dd3a062a6574a7436b319efb944e4223f542b2502c1ba976be91e05b0f85a09fd793beca883375fb67cd133f5284d89984ff3cafa7e11a9d85e7893232a524ec54b20f975d3c0a1143a0ef41176b7051ea91d40c5f44fd9e100558bf1212a7b891e68b55ca61f4be945266d9a1007a14aaeb68c48e257f0f46310ad16481467ec1773535d5fc084915f5d004ba0dc7591d2123c62207909d84f2b382f5ef12759a95cd3f5189806e273960aee162c00f73e7fa59363957654bb1916b5709bb0a9d040514ae5284951e6b: +9fc7c49cb8c4f0972d6ed970ae2c6ac337e675425cc8dce730fc41444302935d4782520b06f93344aa766780e54401363dfd7d967cc3bf06488af90920a30f85:4782520b06f93344aa766780e54401363dfd7d967cc3bf06488af90920a30f85:82bc2c700db222a4ac914aa2be8fa28e422067f94f3344f5362bebaabed7612b0e464a73a6c456903564b15393485140dd0f3aff90aa6e1661ddf682850d0490afc3d735dea05ba47c85d97e833533514c198b4cf6e66d360ee5bf00e14a3aab1ad0e7b8ab2aacc964d42830c78453df1955bbed1cd68ada3db0ecdb601ad7667d5c5e2fd49e36f7328eaa337dbd6ff70e7898a3f98c159d045a2427ade5333c88fc4afd3819dc82f4daa3c523cb57e35a2a5a725d63d402baef51e51f1ef4f8f9a595c9379c9aba873fb4e765a931da09148aba6ec5b44859b0e81ff9fc229598ac9fbdb0bdbddb5692a52222df52ea387bbbf36ad64d1946bd282e323ff4822ad9da897ff73f01b390cfe2e64de492d55de77f5d7d0060a6872a0183ccba610f53274ccb29ce6dce6a036c5317a1ed2a7c1068c1b246fc1d5881d00de06eb401cff95e6b69148699db13e94bb5b280212dff54c70e56de235a5f1400b5bea56772d060170f1d0657321561e4b49107eb96d9b3bc5adf451c2a524eba4db003b77b632a5d89827a6224cc798e096ba27fb33bf61e3b8eaf18d001ae8eb52f85c90d9e12544803e67ff02047e0d23c22e7f8b980c01c3d4824b2a9a14a2e8f672a7b0ce03bdbb3bd56d754a0964db01ca899d488001508657b7b022ccf042c38fc1949d0e00af4d301d4f00c3dea20e308a0f9dcacb43222b3824144af77be18a504aa8d268b8a5600725e7cc5f3a2e6256a8074d1aebca123ea53a0767a92e1783a4983c5ef3d7dd7f02aa9d1f4f9aac6ce254593f08792014fb867eaf879b88a4efb18e89ba11006ad09d85431cc26575b538d8e7890646c5988647cc105d582907ae625e09cd089f47249e81814da14044c7014e80e7a8e619c7b735f701616b6a3c6f492cdc6ed463e71a3d22291482d90a1de6f097c4ae254876184c562b16575b9d0d19313ed98864f49fe2e1d074a21211b2b2a6d27ddb28611520d5f7123058fd007bb01001def07b792bb05bb741c129c6a36376c3853b8bb4f66b5760c8eb4ecc7306ba3a90c70da47c965f6dccbdb61a7fda18ee967cf8c5f050311092d0fdeeaedd1265defdd660abe70:5c783a860aa668184dd22c4f9a546b5ec96ebad2e4af00f968c688671354e0cc9b572c73bc6f19937a05f1baf3434763965c96e103407f0eb642c5644154290b82bc2c700db222a4ac914aa2be8fa28e422067f94f3344f5362bebaabed7612b0e464a73a6c456903564b15393485140dd0f3aff90aa6e1661ddf682850d0490afc3d735dea05ba47c85d97e833533514c198b4cf6e66d360ee5bf00e14a3aab1ad0e7b8ab2aacc964d42830c78453df1955bbed1cd68ada3db0ecdb601ad7667d5c5e2fd49e36f7328eaa337dbd6ff70e7898a3f98c159d045a2427ade5333c88fc4afd3819dc82f4daa3c523cb57e35a2a5a725d63d402baef51e51f1ef4f8f9a595c9379c9aba873fb4e765a931da09148aba6ec5b44859b0e81ff9fc229598ac9fbdb0bdbddb5692a52222df52ea387bbbf36ad64d1946bd282e323ff4822ad9da897ff73f01b390cfe2e64de492d55de77f5d7d0060a6872a0183ccba610f53274ccb29ce6dce6a036c5317a1ed2a7c1068c1b246fc1d5881d00de06eb401cff95e6b69148699db13e94bb5b280212dff54c70e56de235a5f1400b5bea56772d060170f1d0657321561e4b49107eb96d9b3bc5adf451c2a524eba4db003b77b632a5d89827a6224cc798e096ba27fb33bf61e3b8eaf18d001ae8eb52f85c90d9e12544803e67ff02047e0d23c22e7f8b980c01c3d4824b2a9a14a2e8f672a7b0ce03bdbb3bd56d754a0964db01ca899d488001508657b7b022ccf042c38fc1949d0e00af4d301d4f00c3dea20e308a0f9dcacb43222b3824144af77be18a504aa8d268b8a5600725e7cc5f3a2e6256a8074d1aebca123ea53a0767a92e1783a4983c5ef3d7dd7f02aa9d1f4f9aac6ce254593f08792014fb867eaf879b88a4efb18e89ba11006ad09d85431cc26575b538d8e7890646c5988647cc105d582907ae625e09cd089f47249e81814da14044c7014e80e7a8e619c7b735f701616b6a3c6f492cdc6ed463e71a3d22291482d90a1de6f097c4ae254876184c562b16575b9d0d19313ed98864f49fe2e1d074a21211b2b2a6d27ddb28611520d5f7123058fd007bb01001def07b792bb05bb741c129c6a36376c3853b8bb4f66b5760c8eb4ecc7306ba3a90c70da47c965f6dccbdb61a7fda18ee967cf8c5f050311092d0fdeeaedd1265defdd660abe70: +08bf059b4da9aa7ffc702f5b2304c4f96ca49b7dabb6afb41dc91c0f00c65b78a6289ba28e80e8d1a319223e4165dc0bce7352aaf242f70cc968d21d77752832:a6289ba28e80e8d1a319223e4165dc0bce7352aaf242f70cc968d21d77752832:bd4fb28a1dd08b07ba66e17f0c4f21853fefef1c9d20ba7977f154641ea1a18becf6bbb80388886294e0756a3c508ffdfe90b51e1356d112d8cde5ee2cc6332e61d169ccc8cc934994f1bb560fa4660c0b0fd4e8149a225ed4883e68fbb69da7af8a524b17141ccb76b50cd8e1b67d3ce037ded7dfa59bc7c2674226ec7e07b78ea3f782fda3e5f1e9caeab608ca387c304654f801d00e10a7c29f4b0da3e5f89513a98037719a1aef4c2506c177af5451a00757a59f16229c4f4414df51580d48210dabc9377370b6068a88e81d3ad1bed4985155c3600ff48768b903022fe02ae480f2e6329f0bcc91d75f5c6a09fdf77bde90499f3ca395cb20062a0984ad6a0141fd01c2d54dfbb1ee584610640773439a1658d2c9f862f183bfefb033a3be271812f13c78704657e7fb4f850175fcd63d3e4405d192242c21f27c51477f3211a9ce248e892b42fb6d85820f41b897836f20f85a1311534b5c404f8b7a4a0319bc6cecaa57fe4d4f20607c99c2df22fa0676f99d1bd87886c928c4988c6e78c57d758330e6922cbe03c10340253d0dd483792ce75e6cd09d12fbbb041f0205e65ad25ce7c1b24e77ee8d6f915e3bc3e10d09fbd387a84bdaabfd1cedb52c0b1733b5f47088c0d35e0ef458c85414c2b04c2d29f63f77586131ee65530f209b518a0f257a0746bbd5fe0a2e0c388a6c480e1b60714fee1c5941bb4e13f707eac487a9666a723b5793134a268b77597786c3a3193b46d355dd0895fc6216c536a542ffd7d7b08010c86f547a5daa38335a8bfa2655d5f71b4d8807f50c8545c583dd0b690022ee65873aea3e8f1a565f3b0e4e0295fb0d321f5c0b397f2fd0528f86a0d1b707f737b175c69e9e7ae3c84d4b2cf3a38a631aa8032b3e65bb4528f66d0bfd34473ed0101d2a61255b215bc1cbab9a26d2b969324b77c8a5464e5b23df6c5112f9d17c587d95559de212ad241d8b126050e5fddfcc839a7e5aa2fda1ca20c0910d863418f195b38adfcc36e92f2396ac3144b537b30fbe4dde614902f89978b7fb42cd99f13d99c45c734fb82c3259f90b88fd52bdcb88f7eeecdde4c243d880bac7614e15cf8db5993ffa:e24765860137689aad50ebeefc8d6db8e936a4cba62ce87a7f580209384a9d7eec9070905f60ad63a7befd7c70f0ae7c8109169aee4e518fcebfaca723c5b207bd4fb28a1dd08b07ba66e17f0c4f21853fefef1c9d20ba7977f154641ea1a18becf6bbb80388886294e0756a3c508ffdfe90b51e1356d112d8cde5ee2cc6332e61d169ccc8cc934994f1bb560fa4660c0b0fd4e8149a225ed4883e68fbb69da7af8a524b17141ccb76b50cd8e1b67d3ce037ded7dfa59bc7c2674226ec7e07b78ea3f782fda3e5f1e9caeab608ca387c304654f801d00e10a7c29f4b0da3e5f89513a98037719a1aef4c2506c177af5451a00757a59f16229c4f4414df51580d48210dabc9377370b6068a88e81d3ad1bed4985155c3600ff48768b903022fe02ae480f2e6329f0bcc91d75f5c6a09fdf77bde90499f3ca395cb20062a0984ad6a0141fd01c2d54dfbb1ee584610640773439a1658d2c9f862f183bfefb033a3be271812f13c78704657e7fb4f850175fcd63d3e4405d192242c21f27c51477f3211a9ce248e892b42fb6d85820f41b897836f20f85a1311534b5c404f8b7a4a0319bc6cecaa57fe4d4f20607c99c2df22fa0676f99d1bd87886c928c4988c6e78c57d758330e6922cbe03c10340253d0dd483792ce75e6cd09d12fbbb041f0205e65ad25ce7c1b24e77ee8d6f915e3bc3e10d09fbd387a84bdaabfd1cedb52c0b1733b5f47088c0d35e0ef458c85414c2b04c2d29f63f77586131ee65530f209b518a0f257a0746bbd5fe0a2e0c388a6c480e1b60714fee1c5941bb4e13f707eac487a9666a723b5793134a268b77597786c3a3193b46d355dd0895fc6216c536a542ffd7d7b08010c86f547a5daa38335a8bfa2655d5f71b4d8807f50c8545c583dd0b690022ee65873aea3e8f1a565f3b0e4e0295fb0d321f5c0b397f2fd0528f86a0d1b707f737b175c69e9e7ae3c84d4b2cf3a38a631aa8032b3e65bb4528f66d0bfd34473ed0101d2a61255b215bc1cbab9a26d2b969324b77c8a5464e5b23df6c5112f9d17c587d95559de212ad241d8b126050e5fddfcc839a7e5aa2fda1ca20c0910d863418f195b38adfcc36e92f2396ac3144b537b30fbe4dde614902f89978b7fb42cd99f13d99c45c734fb82c3259f90b88fd52bdcb88f7eeecdde4c243d880bac7614e15cf8db5993ffa: +dbbd0f7ecb6482cb01c4dbdc3893c0db81e831353a5b01cc75d3b11f2ff3c59c2d4e588d31a384b17858c0d784f6712bafd0b41204cf8f0d57973e59c770d3da:2d4e588d31a384b17858c0d784f6712bafd0b41204cf8f0d57973e59c770d3da:e0fff35975eba78da2b0ffcc5c1b663600888e8255cd208f6dce7e88953b7142937389a337ae82f4cfe32fcb34f552a48fa8899e1a659e3ed3d3d290efc9a0f7dedf33e21d048d8d910757037b76e8a7ee9e4eca30f529ddc02ceffc26d64fda7303cc0d8940e9ef59dc983c12ccd1d2717e64d3006af82ab15bb878bb89d1758be44310420638b96a0b5e1e65009d69395d027a5da4a85e901be9aa2c0b3acc508ee18574c1b2fa9bd5d7ae7c7d830712da5cbf26be09a3128470a12a14909a80a266659befda548fd2b22f24c5fdc206ed3a4e75f5320682ed0e4ce817d63d5c7f1ee2b440643355be6542f59dc6c45ab15772f2219a812ef7527642015bc75fe45ba969e8100c268e24ceef9205a83a3f7b5ae800ad06e095b9b139219489793a7bce84ebeb654ab6669e2855ccbeb694dd48651505b959d32a77020b869533e3256d40685a6120bab794485b32e1169256fb188fe76e04e9efa6d10d286ae86d6f1c87e8fc73ad9b59fe0c27ee92a46415b39d786d66325d7fa6fda712f199da554fc1c89944a4e84c196e979a807553718cb81c076e511e609d5cac23d8f45b38b94bcfcf158d0d61602238d52e3ae84c815322f534f254e63389ae155dee2fa93396f0ea499d5d08c2475908c648bddcee591e1337e9421dc5a257ce89ccce4ceea809d7e87134e039db1be598196d3089fdcfa8978e02c1555832da0a72b08ad07cdd072627409c873937b0e835715baaf2608b2395327467cf69a1cdcce6372418383e7b89c8df4d531f585149509ead1e41b6627fea81c7958cb49d2d3c3e2fc691e0b8cf72679c08b8904654531bc4368fb617ac7557d9db8d329d77e48d8fb4de73abe7cb9388274af585f875c0dab793e4353518bb24695342af0f5df5be4e9c7ad215be90e25540da3489717dd3d29254585a45c13e6dcc7e9c8a3a79ff755cbe465b25e23a1da608e1084fec83bff80cfb7442b1460187307acd75e3f2d12843a77094acc32888fbe5f1fc24c615d19a065391d4176474644246b5343da77626a2d483fe204f839328775b71a4cb567273e169640af93dde3eca9116f400e23a7ad3d8fc3a28e565f125d6:96c00361fb71c52305e1ab7707e0465203eb13df3e0655f095fb331942a40b15584143b370a7dd5761fb03c075d04a8348661ccea9ada53365b500087d57ec0ce0fff35975eba78da2b0ffcc5c1b663600888e8255cd208f6dce7e88953b7142937389a337ae82f4cfe32fcb34f552a48fa8899e1a659e3ed3d3d290efc9a0f7dedf33e21d048d8d910757037b76e8a7ee9e4eca30f529ddc02ceffc26d64fda7303cc0d8940e9ef59dc983c12ccd1d2717e64d3006af82ab15bb878bb89d1758be44310420638b96a0b5e1e65009d69395d027a5da4a85e901be9aa2c0b3acc508ee18574c1b2fa9bd5d7ae7c7d830712da5cbf26be09a3128470a12a14909a80a266659befda548fd2b22f24c5fdc206ed3a4e75f5320682ed0e4ce817d63d5c7f1ee2b440643355be6542f59dc6c45ab15772f2219a812ef7527642015bc75fe45ba969e8100c268e24ceef9205a83a3f7b5ae800ad06e095b9b139219489793a7bce84ebeb654ab6669e2855ccbeb694dd48651505b959d32a77020b869533e3256d40685a6120bab794485b32e1169256fb188fe76e04e9efa6d10d286ae86d6f1c87e8fc73ad9b59fe0c27ee92a46415b39d786d66325d7fa6fda712f199da554fc1c89944a4e84c196e979a807553718cb81c076e511e609d5cac23d8f45b38b94bcfcf158d0d61602238d52e3ae84c815322f534f254e63389ae155dee2fa93396f0ea499d5d08c2475908c648bddcee591e1337e9421dc5a257ce89ccce4ceea809d7e87134e039db1be598196d3089fdcfa8978e02c1555832da0a72b08ad07cdd072627409c873937b0e835715baaf2608b2395327467cf69a1cdcce6372418383e7b89c8df4d531f585149509ead1e41b6627fea81c7958cb49d2d3c3e2fc691e0b8cf72679c08b8904654531bc4368fb617ac7557d9db8d329d77e48d8fb4de73abe7cb9388274af585f875c0dab793e4353518bb24695342af0f5df5be4e9c7ad215be90e25540da3489717dd3d29254585a45c13e6dcc7e9c8a3a79ff755cbe465b25e23a1da608e1084fec83bff80cfb7442b1460187307acd75e3f2d12843a77094acc32888fbe5f1fc24c615d19a065391d4176474644246b5343da77626a2d483fe204f839328775b71a4cb567273e169640af93dde3eca9116f400e23a7ad3d8fc3a28e565f125d6: +748bb3cd477137bc880ea7c61df25c1dac6ebec9e6c3193d81ffa6f7a81ec667106f28cfedf096454226b3b01fc24ab1c9bbd7f2b0973e56fe2f4c56a0b1475b:106f28cfedf096454226b3b01fc24ab1c9bbd7f2b0973e56fe2f4c56a0b1475b:00de6d990c84338a398fda5f4a2cca733c56b2a2ea396c2fe667c268e38145878539bd41bc140a2cdfe7e18360411048cca60f35ce510991df261cbf669039d9d25687a07fc0476a41f50eccf38153ee6ae9ffd392b2bec0cc67101ec3696d7a2ec8cbd447b6a6ea063d33ec128ae8b57577dee17b97162563f15e42b55ca4bedbdfb631a9f6262f94ae35bb35f795c35a01dedb4645a73cfa6ed9ee521e4631fb17bbc06ee57316be527427c8aa55c631187462d4b2c8822ca4e18b7a5d4c114c11dc22069bc832656d5f4d39548718c51f5e4fc828f60e37f01307505265acb22d5e8d767b9aa7b866a157c643873e09084a1a404a7bb58ccc4b5a390fd30601c896935e3556f60d2dc6bdffe47da0a687c8ece1241ff6c07d776111ca6598fca968cb6afa0a14a34ab8f54b95d3d8473a174bc725523f8674dfb2b10f874207fee1b08b42da1f58655305a359757aa0251f14138eedbc280cbd385bf4bbf5530114cc43b0474779e204962f8560d4aa423e17e6aecace66c813784f6c898b5b9cb746a9e01fbc6bb5c660f3e138574f59b9745445486c422bc06a10cc8cc9bc56458ef85e0e8a027cb0617d0337ddda50220b22c5c398f5ce05ec32f09b090f7cf6c60f818c6b4c6830983e91c6eadf1eae4d54bde754f75d450ae73129f6c4ff5c4c606f7cadbf4f78a18db2961cc8c8ddab0578cfedfcf95ef0888afd385537d1d0a07648a5ce2522d0633507d77593e1a0366d1ece843de69867d7ac442ba7dad2a90b59d8984e4a946bbe5f172da427638b2b61209041fff50e60ec02ec2c0b1dc4be2edd13e87b64d1d1663114573cf58a17739f463a1c3d6b2123390183b505c8eeffb20539bdfeeb40776d20c459bac4569968fcafe44ea4cd624a84bfccd7876dd7bf55f83ac7040e30f326dce325588e1ba5bc0790265dfdba09839eef571641e8a1234b6cfc3a36a866bd6b92cd71ec74e0d4deb9e74d158201aa502f07c8ba348ac26aaf9b3d070c9a40b52a44e932552b67a2df05a7f0f03c617b48dc2782366a231e0c4e3938a4274b36aa9450ff936be132dcb692838d654c94542c6e047a7f78ba711919f908a15b30b9:e13ca8e5ce7c268090908d61cf2f0a3e4572412bf5adfc5addfe88556f148b5fcbe3e1bc65ff16117d35c9d5dc3b117198f884925b4035b2c0de6c402ed47a0100de6d990c84338a398fda5f4a2cca733c56b2a2ea396c2fe667c268e38145878539bd41bc140a2cdfe7e18360411048cca60f35ce510991df261cbf669039d9d25687a07fc0476a41f50eccf38153ee6ae9ffd392b2bec0cc67101ec3696d7a2ec8cbd447b6a6ea063d33ec128ae8b57577dee17b97162563f15e42b55ca4bedbdfb631a9f6262f94ae35bb35f795c35a01dedb4645a73cfa6ed9ee521e4631fb17bbc06ee57316be527427c8aa55c631187462d4b2c8822ca4e18b7a5d4c114c11dc22069bc832656d5f4d39548718c51f5e4fc828f60e37f01307505265acb22d5e8d767b9aa7b866a157c643873e09084a1a404a7bb58ccc4b5a390fd30601c896935e3556f60d2dc6bdffe47da0a687c8ece1241ff6c07d776111ca6598fca968cb6afa0a14a34ab8f54b95d3d8473a174bc725523f8674dfb2b10f874207fee1b08b42da1f58655305a359757aa0251f14138eedbc280cbd385bf4bbf5530114cc43b0474779e204962f8560d4aa423e17e6aecace66c813784f6c898b5b9cb746a9e01fbc6bb5c660f3e138574f59b9745445486c422bc06a10cc8cc9bc56458ef85e0e8a027cb0617d0337ddda50220b22c5c398f5ce05ec32f09b090f7cf6c60f818c6b4c6830983e91c6eadf1eae4d54bde754f75d450ae73129f6c4ff5c4c606f7cadbf4f78a18db2961cc8c8ddab0578cfedfcf95ef0888afd385537d1d0a07648a5ce2522d0633507d77593e1a0366d1ece843de69867d7ac442ba7dad2a90b59d8984e4a946bbe5f172da427638b2b61209041fff50e60ec02ec2c0b1dc4be2edd13e87b64d1d1663114573cf58a17739f463a1c3d6b2123390183b505c8eeffb20539bdfeeb40776d20c459bac4569968fcafe44ea4cd624a84bfccd7876dd7bf55f83ac7040e30f326dce325588e1ba5bc0790265dfdba09839eef571641e8a1234b6cfc3a36a866bd6b92cd71ec74e0d4deb9e74d158201aa502f07c8ba348ac26aaf9b3d070c9a40b52a44e932552b67a2df05a7f0f03c617b48dc2782366a231e0c4e3938a4274b36aa9450ff936be132dcb692838d654c94542c6e047a7f78ba711919f908a15b30b9: +393d44dd0ded71fc08477bd25ed0e6629fa7f88f082ebcef091898e5c9e3d5b8c52a993b802d84540d275479a1af5e287d19ea13b380fa3068d2f2c68eb97a09:c52a993b802d84540d275479a1af5e287d19ea13b380fa3068d2f2c68eb97a09:142b6e82501362d55a04b89d541a796863d7783840d34cbdfc516a3c84772f92446f5f0df4c45c6e0dc8ec1e9bb0ff7ec1696a09cd7ae34c10f8e61a9acabd4303f0a9247237621c490e8d9d0fe44482c560d051b82b074ac3d8e49bb2ac715ac4cde3d4709d0ea3afc51bfdef4b656771fbd55f89da9fa6dcaa62cbae561208d98cfa24cb81252b895f6a4a92c8e407af6c1f1ef49d8dde154fbcb1ca457a204b5ea5432e4d71fb7eb24d43f6fe25e7b4c659b0eebc4cbcc8b3cfde07c8f07b18a51570e7163e33b317b61360f9ce08d95de2c3156af1ccc9b55bcf81eabf3c40434046bbe82e02992a2ac8b3b425680a23d934726cb1b7bf26ceb52a39022c00acf425257167b821185f68e3ed17903d8d22275498c39a9e8df884ec00558dcfa43b8a119c2e853b9a0318bbea087f9cec17ca49b70817b8d7c170a8906f3ee9e8f8cb27a1d0f575abfa627e88f08ca4b93c3297c4f317072f421c5e602e2f831dfb82551bdce8d71216f05cf9a2773b90fc93b9d855a91e35ade332a5061fdb82b309bab4f56e2d586a84c67481d1902c261b3f97dc30b184619df9fdfc7a329d061a41df332202133d8eaeeddb4cfcee53536e07aad11553dcf5ed1e949d45355f9ef42c7832b0de7c2f1526fbef86b63649b6b85ae5ca86f0cea6df9c126c1d79489cc3bfc6e8bf0346eb30d01643c010150c5c8d0eb5010a46112215137991085e57493b22e83526b7b172c6c7341c40321e9ceb7c82bfbaa48f3bd8f51372d96d47444ff0d8bb2e5fd26514eb639105e33895fdc41f6df1fbfdcb08466ec2d217fc99fb012fe6540c0c5a5966ed3e66fab1202ab9daffe8e27e8f7462828d662659ea3b2c608cf68e30dbac62ffd8229f4a53f59ae16833b81a159161f19369f60f51c43a217efc5efd6ab7a91fe249c7b8a0c14e9faea533de133849a92447676f6cc18bef4fec7f37319759ce80ea3eac18fa2d9fa02309e1ce93ac6cf4cd2cb2c95f1e2aff7b2a8856405a7b8ebabeb4906d9b9734da9fb5e5d3f322bb5b559fa61ec8f515db9065ab4b91a7a31d5c625061c2fd2bcfe17f94bbde4776302b8aef3d5b52db3bc73ae4a30cc4417acb:84c716e60de67b020cc1a6a24e6549fe56c6d941a8edeae407626666c31cb60dee6be5a71ebd76baf71b75114bccfd37d163a968bbeec1f76972151296c47e07142b6e82501362d55a04b89d541a796863d7783840d34cbdfc516a3c84772f92446f5f0df4c45c6e0dc8ec1e9bb0ff7ec1696a09cd7ae34c10f8e61a9acabd4303f0a9247237621c490e8d9d0fe44482c560d051b82b074ac3d8e49bb2ac715ac4cde3d4709d0ea3afc51bfdef4b656771fbd55f89da9fa6dcaa62cbae561208d98cfa24cb81252b895f6a4a92c8e407af6c1f1ef49d8dde154fbcb1ca457a204b5ea5432e4d71fb7eb24d43f6fe25e7b4c659b0eebc4cbcc8b3cfde07c8f07b18a51570e7163e33b317b61360f9ce08d95de2c3156af1ccc9b55bcf81eabf3c40434046bbe82e02992a2ac8b3b425680a23d934726cb1b7bf26ceb52a39022c00acf425257167b821185f68e3ed17903d8d22275498c39a9e8df884ec00558dcfa43b8a119c2e853b9a0318bbea087f9cec17ca49b70817b8d7c170a8906f3ee9e8f8cb27a1d0f575abfa627e88f08ca4b93c3297c4f317072f421c5e602e2f831dfb82551bdce8d71216f05cf9a2773b90fc93b9d855a91e35ade332a5061fdb82b309bab4f56e2d586a84c67481d1902c261b3f97dc30b184619df9fdfc7a329d061a41df332202133d8eaeeddb4cfcee53536e07aad11553dcf5ed1e949d45355f9ef42c7832b0de7c2f1526fbef86b63649b6b85ae5ca86f0cea6df9c126c1d79489cc3bfc6e8bf0346eb30d01643c010150c5c8d0eb5010a46112215137991085e57493b22e83526b7b172c6c7341c40321e9ceb7c82bfbaa48f3bd8f51372d96d47444ff0d8bb2e5fd26514eb639105e33895fdc41f6df1fbfdcb08466ec2d217fc99fb012fe6540c0c5a5966ed3e66fab1202ab9daffe8e27e8f7462828d662659ea3b2c608cf68e30dbac62ffd8229f4a53f59ae16833b81a159161f19369f60f51c43a217efc5efd6ab7a91fe249c7b8a0c14e9faea533de133849a92447676f6cc18bef4fec7f37319759ce80ea3eac18fa2d9fa02309e1ce93ac6cf4cd2cb2c95f1e2aff7b2a8856405a7b8ebabeb4906d9b9734da9fb5e5d3f322bb5b559fa61ec8f515db9065ab4b91a7a31d5c625061c2fd2bcfe17f94bbde4776302b8aef3d5b52db3bc73ae4a30cc4417acb: +71193640a0a2b22fb22d00a80b33a5514f3d1000034fccd885d8ea8638f0b0f8b1d36f723b7086d923119f46759b39fa1e4038c6418c379ba98b5840c7ea5068:b1d36f723b7086d923119f46759b39fa1e4038c6418c379ba98b5840c7ea5068:e0287948bb85a398e6affa2d25fcff8bdb9326f5d14fdeb60549f5fbf0c1816f11cbdd4e90fea039dca60faad1696003f91515c9b272882c95c9a4ab6e2777bd927e7d8442aea6cea619c9b15255fed612b5cc3158fc705bb7a506f4afecf4e34ed517b2c12b8362610e5ea270485cccb3c9aa97ecd6cb19630900f07d94cb293cb6e089a9a77c0194073a7f7177b0230d25763a2ef98d47704cb2c3af4c3c1b495631b4a5b21b2e56bff2ede03ea4fe7cf82917347e3a9d4dbeef37d1cf17615adaa0fd17057969917d478d03ccd8f8b88e5e5acae6732a8161dfb5f7d02123c8d5a565cf4dd98dfc9aaf5a335058a941ca43073f2659615a72fe78c101c41aed07f3bcf980b0a5b3fbafdbbea92fd889cfd53d403278bc15a59aa140c2d773b8889b963dcea365362e426ef4609845c9bce9f8aeb591d1a469b072b41209f5a8b6dc2395ad9060eb2e370978ae3311d1cf0a8f205142d436bab6b95943a97c23e61bd14b2d95672cb9325e9ab1fc9eeeaaccd58b9f4ac1550bdec8449b036039496c5f07a5ed64d5d85171690144db5c81c81cbc4c16718d52c4dfd1958ca5c9c8ba582cd9d706f27a74744c3a05bf1ccd51f1092010d36f1578b578ae0e9ffa47079055ef94fabc9ff72f738bef68461eb3404ccee953f5ee864c974ce70e9037e3388fbaf2889e1366caa0f651e21b339e3d56b9d95ac30b3592a948912c90bf54473cebc467b09a3943dcac4868acb5b35ea691eff4d8cc1cda0c6c0a9c169a4ee10041f35f433fb53d26067b291056b1da69ff46fbea1ca7213659a990d5d5df1406b093da2a33c8df95ab3ce811afb9c98c5bfd7c4e981b3ea94eefd2e2fe95707d89f307fa76828b5c6774950aee80626714256e197dc7da972158c768bbee7fbd169ec15b4bb7be72976dbed3e512766ef22ef3b812bcac4aa3115afe83d31284af8eacea4ee49afd42d9c44fff2d861c08629b55dae00ff674fb028e738b05dcb38aeaa6963cc3faafc7b69245a2a122a96dd2f03a824d72b0fe0dd798df5c4bb75a87324e764a50a5ff52547ada8f8f88e6f38aee49d58ddb012648854cd59d0ec97bc3d58d0ad4491f08590767ceb1:a9702a3395acd20d754373095dc61445584d8e571080e179adcba3106bb06a7ce4d460f1261aef8643ab1634f47c9414a32e183a327691e65843dd6c05507207e0287948bb85a398e6affa2d25fcff8bdb9326f5d14fdeb60549f5fbf0c1816f11cbdd4e90fea039dca60faad1696003f91515c9b272882c95c9a4ab6e2777bd927e7d8442aea6cea619c9b15255fed612b5cc3158fc705bb7a506f4afecf4e34ed517b2c12b8362610e5ea270485cccb3c9aa97ecd6cb19630900f07d94cb293cb6e089a9a77c0194073a7f7177b0230d25763a2ef98d47704cb2c3af4c3c1b495631b4a5b21b2e56bff2ede03ea4fe7cf82917347e3a9d4dbeef37d1cf17615adaa0fd17057969917d478d03ccd8f8b88e5e5acae6732a8161dfb5f7d02123c8d5a565cf4dd98dfc9aaf5a335058a941ca43073f2659615a72fe78c101c41aed07f3bcf980b0a5b3fbafdbbea92fd889cfd53d403278bc15a59aa140c2d773b8889b963dcea365362e426ef4609845c9bce9f8aeb591d1a469b072b41209f5a8b6dc2395ad9060eb2e370978ae3311d1cf0a8f205142d436bab6b95943a97c23e61bd14b2d95672cb9325e9ab1fc9eeeaaccd58b9f4ac1550bdec8449b036039496c5f07a5ed64d5d85171690144db5c81c81cbc4c16718d52c4dfd1958ca5c9c8ba582cd9d706f27a74744c3a05bf1ccd51f1092010d36f1578b578ae0e9ffa47079055ef94fabc9ff72f738bef68461eb3404ccee953f5ee864c974ce70e9037e3388fbaf2889e1366caa0f651e21b339e3d56b9d95ac30b3592a948912c90bf54473cebc467b09a3943dcac4868acb5b35ea691eff4d8cc1cda0c6c0a9c169a4ee10041f35f433fb53d26067b291056b1da69ff46fbea1ca7213659a990d5d5df1406b093da2a33c8df95ab3ce811afb9c98c5bfd7c4e981b3ea94eefd2e2fe95707d89f307fa76828b5c6774950aee80626714256e197dc7da972158c768bbee7fbd169ec15b4bb7be72976dbed3e512766ef22ef3b812bcac4aa3115afe83d31284af8eacea4ee49afd42d9c44fff2d861c08629b55dae00ff674fb028e738b05dcb38aeaa6963cc3faafc7b69245a2a122a96dd2f03a824d72b0fe0dd798df5c4bb75a87324e764a50a5ff52547ada8f8f88e6f38aee49d58ddb012648854cd59d0ec97bc3d58d0ad4491f08590767ceb1: +bfc9626c91f348fdaf469def2302e9e38f9051e7349e48f850cf352a8331a28b4e8193061c9d65a82bcb25da089b4a80ba41b3dd2f8ed1dc81e1cfd03c849115:4e8193061c9d65a82bcb25da089b4a80ba41b3dd2f8ed1dc81e1cfd03c849115:2f11f40b2a19f640c0044c7b139680c3c3b69f00ff9f6a4186fd7ded569c1d8c5720f19dd35c7816d08a94c08204e47643e264d425e21cefb83129c909a3d78caf72c46bf1a729765ef4b8ca803fdaf8052ffc6cc4a6b579a160b703b15355c6fcd3b9a2ecbc267e60dd59f6a2b19420e55727a80b0bb64167c83ba0c805deed491d93e723f3b43263d17420b85be86c165c552779db960e0aa9eb4d9f3a164a5a21fab3f509a8f0199a6943c4b223cf9daca7e110e056a81d9ce0e0c02ac265eeac05ecd84448468a4d122b87a3e04c2837e43d212704fd41e7f3d198a2e76beca0e7029c432a0654ecd44f984c5df06741964d8372c86e162a8c5418849b41e571feb83eb42fbbcddb8a082143909eaa5012b979931dc7e3cccb44c791e04b8065ee63f0561da1bbf37bf6503477879cfbaf6d9d7d9a7475553f53535f847a76dc3b2b7a3d1d470bbe17124a88e03fe994ba10c24221e39e3d0ff53c79e2faafa19012d5ef192bc6d5260b66f997b644cf48d99f3899d7c485e684aa1e6e30855cf75c2d80c7a3ee4354fe13c676091c8667373d30e60ff8e09fedef175a1a87395fefa0722bf6c01c6555cff068892afe9486cb1fcc5fb6641e82d87079ba5d7a9c139355d6c14c507dbd594724b55351100965be9e5dbfa7708878c4b29f4d54c217746e326ab2a54f99b881d7da5b11edb08a6d79d885691b1f7085517310b309cf9b1b714aabc5c17a509b140b89b3f9dcee50cab441bf5ad3bbc29990f627406170a7a10f2d47dfc9256154f962308e769a2ab1b2a00e27e327f0d1fa164d1e38ead5ceaae238ba526f54b81b45dea6c8974186b1b6725fa4c83e62f3e254f729871bda4dc444bce78f0903fa318eaac822a95532ab019e9cfc5619e2c2067f258f4375d2e0222ea5bf96a253a2a3fa9eea02c3eeccb028c76bc60d38298b95b9afe66031b1a2a26152fdaa7ef4f837abb51185df8b2ef85ad2c9be6dfba75e37dc7d12e1787fc55f866fd066f12291dff1976afc10da913101e70495d8783348d611b011ec671c0da737bf962cdcc9e4a800b513935a56d084ea64a7d4e8e99ee9440a736132e42c909503c2224a141b25ce:660242c1dcf3291369c65c9d7f89872eab482200e344b296e336a0a2e631fa796024b6e1119c27d52264a49815dd781927a7df467e88b801e684fc602296250e2f11f40b2a19f640c0044c7b139680c3c3b69f00ff9f6a4186fd7ded569c1d8c5720f19dd35c7816d08a94c08204e47643e264d425e21cefb83129c909a3d78caf72c46bf1a729765ef4b8ca803fdaf8052ffc6cc4a6b579a160b703b15355c6fcd3b9a2ecbc267e60dd59f6a2b19420e55727a80b0bb64167c83ba0c805deed491d93e723f3b43263d17420b85be86c165c552779db960e0aa9eb4d9f3a164a5a21fab3f509a8f0199a6943c4b223cf9daca7e110e056a81d9ce0e0c02ac265eeac05ecd84448468a4d122b87a3e04c2837e43d212704fd41e7f3d198a2e76beca0e7029c432a0654ecd44f984c5df06741964d8372c86e162a8c5418849b41e571feb83eb42fbbcddb8a082143909eaa5012b979931dc7e3cccb44c791e04b8065ee63f0561da1bbf37bf6503477879cfbaf6d9d7d9a7475553f53535f847a76dc3b2b7a3d1d470bbe17124a88e03fe994ba10c24221e39e3d0ff53c79e2faafa19012d5ef192bc6d5260b66f997b644cf48d99f3899d7c485e684aa1e6e30855cf75c2d80c7a3ee4354fe13c676091c8667373d30e60ff8e09fedef175a1a87395fefa0722bf6c01c6555cff068892afe9486cb1fcc5fb6641e82d87079ba5d7a9c139355d6c14c507dbd594724b55351100965be9e5dbfa7708878c4b29f4d54c217746e326ab2a54f99b881d7da5b11edb08a6d79d885691b1f7085517310b309cf9b1b714aabc5c17a509b140b89b3f9dcee50cab441bf5ad3bbc29990f627406170a7a10f2d47dfc9256154f962308e769a2ab1b2a00e27e327f0d1fa164d1e38ead5ceaae238ba526f54b81b45dea6c8974186b1b6725fa4c83e62f3e254f729871bda4dc444bce78f0903fa318eaac822a95532ab019e9cfc5619e2c2067f258f4375d2e0222ea5bf96a253a2a3fa9eea02c3eeccb028c76bc60d38298b95b9afe66031b1a2a26152fdaa7ef4f837abb51185df8b2ef85ad2c9be6dfba75e37dc7d12e1787fc55f866fd066f12291dff1976afc10da913101e70495d8783348d611b011ec671c0da737bf962cdcc9e4a800b513935a56d084ea64a7d4e8e99ee9440a736132e42c909503c2224a141b25ce: +393b769482375b821427a66d16e4f55185b7a3b7338f1a06f67cdfa7e35c541c84afd70678ffa85a9f6574cbcfe3b15d04a9fd15016ff8550a987c4b951c7122:84afd70678ffa85a9f6574cbcfe3b15d04a9fd15016ff8550a987c4b951c7122:8ae8053e03bebeae544043b8414b385364add1673737cf8ab20193d4aabc8a78e1d69b9c7e52729e69307806e927ce3807b07c68c833c4fcf16db15e7dce604d1798915fd4211689b4864642502d38e91b1997b71823318b69abe5bed6f5e3015bfb22df30db371f2260c5c22eba60df39b3edd3c4d7a1e111cd9b8aa46f67bd0cf3a717af06ec0ce567028e06e4797934ad69b1f5be440ff37a8a034b1533fa946424ac595400ad27d3be76dc89ba9d6c49939a09f2e401c8f20f7f7b4b9e63b9d55201534ab4cc7be885f0432a2c6673d2e765194dffd9b6096dd2b2843918750959a8dde4a3ab407eb2f7e1a49c2597e30805f8480dd0cc8272a320c00aa2b210f576e42577d3aa419703697ca406d43a1a4f99b0733664f6d6b2403cba1bdcc51f541cf24236070570540755c7a8631fcc2f18938fa11bc291155b39d7a762a1ff4dca97b448f70e2d3de447cb08f918ea20cb433fa115e30880c96c8cf5f0ebbcf482309db6dc1fb64e17c04d7cdf7a90f4014d15ae7696b44423b0ba084eed4d3fb28c1efb39828aca2f40ca6df342c20e95f8006b2767a83f50c31fcc1581a09753e78291f0d9931d992ad3604473ceb885ecbe7857cc52ad5585334d1485d022e106b71c29bdfcf23ee8a475df2c090532356a6ffc02232317988a2cbcfbc2a36b4b483cb44510e85599b612596b626572b0996d8a61c0ee3efff1f7c71c05fb5a8d8c5d09d924ebaac8800451c9db2456710a279dfe2d22f6aea9de31801dc742534362b0e810e99e841dbb7f0cf9af1aef542a52c776cc51f287368fbe6ad651fad5787ef77c73535f3dfb3618cc8f0dbb549ddca9b9bf91135a3456001a46215ade388e7ceb9fcdfd0d2d0a0356afbe2cec1c2e78b4d998d4554f4621f1151dd3ffd3ba4c0bc852f311758c5dca425d18ba15a8d67ca401d0e6cf280cb88384a2dad49fae39ba2a77b467b3238aa28cfd137e5c5c0ff9000f8b06a2192e162920692265db24ab6aede535e31c2093be57ebf8805df1788914f3a884f884179015808db4d3020f3e78bc34285d233762e899ebff28428215e244404de291728fbf4124ce5b2435260a8e341180075a5651e6:31f98c0a08fda8e735b57366aa1b83b93dae63b5810c821d99cb39df521feac07f3c410b27ba3307757d6049f22454fb6de9e2c3c2438d68319097d112cfdb078ae8053e03bebeae544043b8414b385364add1673737cf8ab20193d4aabc8a78e1d69b9c7e52729e69307806e927ce3807b07c68c833c4fcf16db15e7dce604d1798915fd4211689b4864642502d38e91b1997b71823318b69abe5bed6f5e3015bfb22df30db371f2260c5c22eba60df39b3edd3c4d7a1e111cd9b8aa46f67bd0cf3a717af06ec0ce567028e06e4797934ad69b1f5be440ff37a8a034b1533fa946424ac595400ad27d3be76dc89ba9d6c49939a09f2e401c8f20f7f7b4b9e63b9d55201534ab4cc7be885f0432a2c6673d2e765194dffd9b6096dd2b2843918750959a8dde4a3ab407eb2f7e1a49c2597e30805f8480dd0cc8272a320c00aa2b210f576e42577d3aa419703697ca406d43a1a4f99b0733664f6d6b2403cba1bdcc51f541cf24236070570540755c7a8631fcc2f18938fa11bc291155b39d7a762a1ff4dca97b448f70e2d3de447cb08f918ea20cb433fa115e30880c96c8cf5f0ebbcf482309db6dc1fb64e17c04d7cdf7a90f4014d15ae7696b44423b0ba084eed4d3fb28c1efb39828aca2f40ca6df342c20e95f8006b2767a83f50c31fcc1581a09753e78291f0d9931d992ad3604473ceb885ecbe7857cc52ad5585334d1485d022e106b71c29bdfcf23ee8a475df2c090532356a6ffc02232317988a2cbcfbc2a36b4b483cb44510e85599b612596b626572b0996d8a61c0ee3efff1f7c71c05fb5a8d8c5d09d924ebaac8800451c9db2456710a279dfe2d22f6aea9de31801dc742534362b0e810e99e841dbb7f0cf9af1aef542a52c776cc51f287368fbe6ad651fad5787ef77c73535f3dfb3618cc8f0dbb549ddca9b9bf91135a3456001a46215ade388e7ceb9fcdfd0d2d0a0356afbe2cec1c2e78b4d998d4554f4621f1151dd3ffd3ba4c0bc852f311758c5dca425d18ba15a8d67ca401d0e6cf280cb88384a2dad49fae39ba2a77b467b3238aa28cfd137e5c5c0ff9000f8b06a2192e162920692265db24ab6aede535e31c2093be57ebf8805df1788914f3a884f884179015808db4d3020f3e78bc34285d233762e899ebff28428215e244404de291728fbf4124ce5b2435260a8e341180075a5651e6: +26cbc2510ee6ea390a2cb948a015d131abf4c0954915620b7816aecf4e11da6d145e8dd22b4400289dafb626d95a94c2f3b69c65197717cbdcd85098c5492107:145e8dd22b4400289dafb626d95a94c2f3b69c65197717cbdcd85098c5492107:9cebe24b4f8ade86430e279a3c433e4ae17e008852a24f08690cbc3d75e3b7f200da897c25f7483b37637d4bc11008d9224cd581fbc038adada02d271ed2a5d285d843a0f8b79e37945dc35bc264becd804307e1d44218a643e4b59a9311de985d24b4c26fb14603be5dba1839ee0c8d2ede6cb50af67c804519037b1b1663318cfc6e75d0f051dbb5d3eaf3aad1f78ef0cff48d5c55b2fd25db1539d0f02dae9f25148a8d338b97879bbd39df961aa2c396315a2a86cc783581e67ea844acfe8645428a27b8d32ea3064e3bf62dcf58010ec4348862fac25e3d9fcd4e5d65be59905d816dfb964992ba7aceef8c2075a312e5ffc4f9530ea20f77f93e81cf8a019dc3945634364babf79772045a0dbaa77c47a22b77223b704debd2d003f6a5c7bf6b19cd2c49b614fd4d47fd251fe622cb981785c146bdb7c1d2ea02b116923bf98a1afbb7858adf2df938a790ec1f9074adb8d1afb5633fa961a84764010d3bded1c033d25abdb4b00fb05ed7640fae61879df88f0b09e3abd057b9a52108a9bc985fb73a5f29d84d1ca6921b62f1b703c7eeb4815d9dd6d066738db118baf61b0422f388f1bfc9e3a9bed83a1a727dcc266a9988364846807f4d5518bc2edd0ecb3413c26fd0c79b75d8cb5bcd85c06fccea4d03fb8988dff3ed0cc9dbae78d6ae8d5fc4024617a23f52bd615385d4eee08f9134eb3b250c8f822b47d91e8c4d4c29298016e6fc81f1f1099253d7945e0798955da0dde14ebb934ecfaeeabae87883e1cc398067400fe462a2c4e9f232db5cdd61eba949188cf01b238be7ada938f002dc3ae31fdfd425c8d46ea032323aaf20dd3de2507d36bb45fbb91c40969a9e5da20f7f936b0f4b137b62fe2ba3a667bc0362d93fc50d3f2295e167fcbab0fb3a39b7cb024b578f9490f734b28c9ccf7192f183947d5a513efa4916e4d82b2ab4ba7ec2ffba213ce82ad6ed3b10e48553e733c940aa9b9ce71337c6c2805dfb8dd6618b6d4090a3d6cc963ecea26d1cdc2bf5ac999c11276168a931d816469d79083c24081a50dcbd222752385267ce1bfc1db76b1554ad57e34752b7f8983147c116d4a3fae6f6d57e654fedd7378d2b4989ea:6710d0dd00545b444cf714b79144fe79f38cb1c0f5b74248d4f01fe360117a26ffed4a3bf21323b28a393ae9dee07d69e583e316c6a573d37c644a8d62c405069cebe24b4f8ade86430e279a3c433e4ae17e008852a24f08690cbc3d75e3b7f200da897c25f7483b37637d4bc11008d9224cd581fbc038adada02d271ed2a5d285d843a0f8b79e37945dc35bc264becd804307e1d44218a643e4b59a9311de985d24b4c26fb14603be5dba1839ee0c8d2ede6cb50af67c804519037b1b1663318cfc6e75d0f051dbb5d3eaf3aad1f78ef0cff48d5c55b2fd25db1539d0f02dae9f25148a8d338b97879bbd39df961aa2c396315a2a86cc783581e67ea844acfe8645428a27b8d32ea3064e3bf62dcf58010ec4348862fac25e3d9fcd4e5d65be59905d816dfb964992ba7aceef8c2075a312e5ffc4f9530ea20f77f93e81cf8a019dc3945634364babf79772045a0dbaa77c47a22b77223b704debd2d003f6a5c7bf6b19cd2c49b614fd4d47fd251fe622cb981785c146bdb7c1d2ea02b116923bf98a1afbb7858adf2df938a790ec1f9074adb8d1afb5633fa961a84764010d3bded1c033d25abdb4b00fb05ed7640fae61879df88f0b09e3abd057b9a52108a9bc985fb73a5f29d84d1ca6921b62f1b703c7eeb4815d9dd6d066738db118baf61b0422f388f1bfc9e3a9bed83a1a727dcc266a9988364846807f4d5518bc2edd0ecb3413c26fd0c79b75d8cb5bcd85c06fccea4d03fb8988dff3ed0cc9dbae78d6ae8d5fc4024617a23f52bd615385d4eee08f9134eb3b250c8f822b47d91e8c4d4c29298016e6fc81f1f1099253d7945e0798955da0dde14ebb934ecfaeeabae87883e1cc398067400fe462a2c4e9f232db5cdd61eba949188cf01b238be7ada938f002dc3ae31fdfd425c8d46ea032323aaf20dd3de2507d36bb45fbb91c40969a9e5da20f7f936b0f4b137b62fe2ba3a667bc0362d93fc50d3f2295e167fcbab0fb3a39b7cb024b578f9490f734b28c9ccf7192f183947d5a513efa4916e4d82b2ab4ba7ec2ffba213ce82ad6ed3b10e48553e733c940aa9b9ce71337c6c2805dfb8dd6618b6d4090a3d6cc963ecea26d1cdc2bf5ac999c11276168a931d816469d79083c24081a50dcbd222752385267ce1bfc1db76b1554ad57e34752b7f8983147c116d4a3fae6f6d57e654fedd7378d2b4989ea: +b1f59e3c2380d7aa414d0bf90893a38dddfc293859303d16f00d9eae6cb3450e84e3f5f72f19095b0f533848a5a91d0f0743b8e3a3e2f52fcbd7ebe7c5b5a998:84e3f5f72f19095b0f533848a5a91d0f0743b8e3a3e2f52fcbd7ebe7c5b5a998:c6174c9ad3685dd648636017837b8d992200319e9a5a0d26d94d2da75e2c3aff46f42d7b3aba472b7f860b0fe1f695529731fdc8cf0da705d1d09acad04f010837ecef419d57e9ea6cacf168c5215696f471f3caa897607c629d443de099d31753c24677d8d75f4bf17246818b58adc0424b762a191ef39a7076a5ad12614cf54c47eb0908bb866518c5fac1ca2d2e5b657520a2b3695c6fb360f16f4ab357998e4c0e97231d6f89c968dc29ecc1aa91fa0d7543b5d2247b0d85e48743ab7cc815cfdaa82bf68ca6d3e2250bfda27024d61b474c6b8154ac8d1b5a36209782515c1646680d37069b8b4412f951b025a4d543625dd02290bf03c6734613f99b7a4c3af5c5f9e9ac3474465e648423018d40a6adbe88a3301d3d259b04ee44cc0562ee0ded4f5e26ad977ab5631f85768dbce53f616c029a8b8f933e2a9264b1c81f517e9ff58ab9f45a23eeed4204358f8fff0c8f975ef1dfa5776a5f7793bae2f281d7b0cbef240b3fc6be058821ea2b800fffe55a7de0afc93ede9c60c8de005abb9a2c88f4e61e8deb3170f1078a36e2d8f2a58239bdee496e90d137d2110f0ad857a88b3527664f781939e0b2f76634ff9f6c57e1c43f58243171cd862ef4284576172af1f6c3bd37d5d74b28a7a98698bd74e57bbc142e67f703f9d62cde761a02268fecb343fc01418836414f1222ca24bcdd69d005901da2a0f94465e4d4ba68898816bf7e3e4bb79c8ca5997fba9a8df84faa2d24b044c4ea61029a46cba703421e361dfa52caaff3bbaab7fd753f2856d7c083aeb9768da11d821e2d309f7a735c399692dac2f262846b891bf6461af23c8c7ce1d4d9032c3c140f739e5584c36f05eaf4349ff4545f283a4e0fea49430a1b180d0871e3742b88ccb591124fc427ed673b5f27b0b0a6f54af22ba4a6d1c6c1db2a1fcaa6d8a0308b77ef2d0c61bbf51b95f1e8b6abc5041d97b6b6f1b569b3f63cec05cb567aaea106727096ee8a9ea87b8804901f7e88a7409c66f152de9dbfcbe31952e6fd83b2877a775fae425b3851e0eff8792ffb3848f84a65cc317253b272475e717e49e9c6ff6b7859d11bba7c4428c82d1789e0dca5bcadca2fdb259e98:60afc1e991fdd27cc472b9acc9d405b4d2b913089290b311c4fa891ae2eea05671fde7a0ef86557bd867d1c0b747caf35229d6ef528fe3e0d0bcf630380ea90ec6174c9ad3685dd648636017837b8d992200319e9a5a0d26d94d2da75e2c3aff46f42d7b3aba472b7f860b0fe1f695529731fdc8cf0da705d1d09acad04f010837ecef419d57e9ea6cacf168c5215696f471f3caa897607c629d443de099d31753c24677d8d75f4bf17246818b58adc0424b762a191ef39a7076a5ad12614cf54c47eb0908bb866518c5fac1ca2d2e5b657520a2b3695c6fb360f16f4ab357998e4c0e97231d6f89c968dc29ecc1aa91fa0d7543b5d2247b0d85e48743ab7cc815cfdaa82bf68ca6d3e2250bfda27024d61b474c6b8154ac8d1b5a36209782515c1646680d37069b8b4412f951b025a4d543625dd02290bf03c6734613f99b7a4c3af5c5f9e9ac3474465e648423018d40a6adbe88a3301d3d259b04ee44cc0562ee0ded4f5e26ad977ab5631f85768dbce53f616c029a8b8f933e2a9264b1c81f517e9ff58ab9f45a23eeed4204358f8fff0c8f975ef1dfa5776a5f7793bae2f281d7b0cbef240b3fc6be058821ea2b800fffe55a7de0afc93ede9c60c8de005abb9a2c88f4e61e8deb3170f1078a36e2d8f2a58239bdee496e90d137d2110f0ad857a88b3527664f781939e0b2f76634ff9f6c57e1c43f58243171cd862ef4284576172af1f6c3bd37d5d74b28a7a98698bd74e57bbc142e67f703f9d62cde761a02268fecb343fc01418836414f1222ca24bcdd69d005901da2a0f94465e4d4ba68898816bf7e3e4bb79c8ca5997fba9a8df84faa2d24b044c4ea61029a46cba703421e361dfa52caaff3bbaab7fd753f2856d7c083aeb9768da11d821e2d309f7a735c399692dac2f262846b891bf6461af23c8c7ce1d4d9032c3c140f739e5584c36f05eaf4349ff4545f283a4e0fea49430a1b180d0871e3742b88ccb591124fc427ed673b5f27b0b0a6f54af22ba4a6d1c6c1db2a1fcaa6d8a0308b77ef2d0c61bbf51b95f1e8b6abc5041d97b6b6f1b569b3f63cec05cb567aaea106727096ee8a9ea87b8804901f7e88a7409c66f152de9dbfcbe31952e6fd83b2877a775fae425b3851e0eff8792ffb3848f84a65cc317253b272475e717e49e9c6ff6b7859d11bba7c4428c82d1789e0dca5bcadca2fdb259e98: +db461b9f707eb2cd7748c44c99562f1302397489353df5f303797fe0d0b58de1635116da8ba5a36a377728e28618e75c5592aecc18e34011c4c42591970b7366:635116da8ba5a36a377728e28618e75c5592aecc18e34011c4c42591970b7366:1a2ac8c1b9ea099b831a6812d2b4261309058ea5883d70b1c607b9cd3fdfdb86e79902b0fe89e80ea7c478207674b2d803b0b9ca147ffe62e594f506c796d68997ce482b51a46e49b4a5d858cdeae2c6ec9b694198e6822f0e33ed57bedb0335c7890a72a7ee3c23823be79b7f9471e033c79aeed52e5760fb0ccbb9d38fded8b47383c19103ce44705834c59ddd86f7033948612d6662f516ce4e399ff20363cc7281a69b2d5c307b10b704150184ece32f390d772ccfa78483bb77a9fba84425366984171cc2bb60b0ec6c628d4e9030746dac1cabca60f05683813346a1a5bc14727549795c1c926869e1aa25093d591b43e086e43a04d170d942c4165e1c5ce76c3e64973d9136f9325bee821682f1043e951b02767f3fb458d02449add3e8a66e516fdb1ed580e056e0f78ee33fd9ee3280912fae07fe1ea02527cd001d6f6f2f89ee649f517414d56f57359a846891f0222c321d7e70817995a8cd8e94760b6e74832bab68d55bc4641884221fd29f122d87a9a868b6a6060c87b2382cf7bbdda4cd6aaa1bbc8e6d634ab580c865f5add6a1d54e61a607dc2c37b08a8cba6e610c12cfebef9c989eef3b782acbd1bcec5f04e835ca101298b5e9bdd8813a71b0d469fcf12727d3de1c3f97ddbc6ab2658440dd6421019bc68f356d6f25536865851d92d90fe9969c3b7c35a2e88ce153476ec3973af9359f1677a4caf1cc481c71bd90228ff5fc6dd83b8a699ffe514929f5c95cb4f04b00dd18a2872c41868d3beb76498ddc9234b63f599d7071801db2c2878f7bef4ffddd813226f06db84eb30217a7183082e3c1242bb6d01cd3a6ce27bff16bfbfdd75b7e5104312c49c43aadfcd5b4edba0ff50d2890ca3cd9cca33e4fc694c057c47ebe1c20a4ad115f985dc7442c6f6da7be530b6902289cab9ca139c6b24cb80ffdd782324e602c45910db63d8b5c44ca29d27f56dbf00186ba583c34e16031df357546b3ab9a3dd65e91d7128c939195e646a0f0b89bf5df04ba233d6a12a271f7e04aa45cda99b4a55a21cbbb738515e32c56aac2496232b1008a6761c8045a1fe0f9a3644047b5966a58a600466c1b1d11ddad5aa573c43ebda887e16a05:dd049ca79beb9eac325acf44672ff578a968502fe1bcf5ea19d52c0f6778c7f1c7bbf742747907786e608123911a920778d2f9596fe29be7cc28fd009d7c440e1a2ac8c1b9ea099b831a6812d2b4261309058ea5883d70b1c607b9cd3fdfdb86e79902b0fe89e80ea7c478207674b2d803b0b9ca147ffe62e594f506c796d68997ce482b51a46e49b4a5d858cdeae2c6ec9b694198e6822f0e33ed57bedb0335c7890a72a7ee3c23823be79b7f9471e033c79aeed52e5760fb0ccbb9d38fded8b47383c19103ce44705834c59ddd86f7033948612d6662f516ce4e399ff20363cc7281a69b2d5c307b10b704150184ece32f390d772ccfa78483bb77a9fba84425366984171cc2bb60b0ec6c628d4e9030746dac1cabca60f05683813346a1a5bc14727549795c1c926869e1aa25093d591b43e086e43a04d170d942c4165e1c5ce76c3e64973d9136f9325bee821682f1043e951b02767f3fb458d02449add3e8a66e516fdb1ed580e056e0f78ee33fd9ee3280912fae07fe1ea02527cd001d6f6f2f89ee649f517414d56f57359a846891f0222c321d7e70817995a8cd8e94760b6e74832bab68d55bc4641884221fd29f122d87a9a868b6a6060c87b2382cf7bbdda4cd6aaa1bbc8e6d634ab580c865f5add6a1d54e61a607dc2c37b08a8cba6e610c12cfebef9c989eef3b782acbd1bcec5f04e835ca101298b5e9bdd8813a71b0d469fcf12727d3de1c3f97ddbc6ab2658440dd6421019bc68f356d6f25536865851d92d90fe9969c3b7c35a2e88ce153476ec3973af9359f1677a4caf1cc481c71bd90228ff5fc6dd83b8a699ffe514929f5c95cb4f04b00dd18a2872c41868d3beb76498ddc9234b63f599d7071801db2c2878f7bef4ffddd813226f06db84eb30217a7183082e3c1242bb6d01cd3a6ce27bff16bfbfdd75b7e5104312c49c43aadfcd5b4edba0ff50d2890ca3cd9cca33e4fc694c057c47ebe1c20a4ad115f985dc7442c6f6da7be530b6902289cab9ca139c6b24cb80ffdd782324e602c45910db63d8b5c44ca29d27f56dbf00186ba583c34e16031df357546b3ab9a3dd65e91d7128c939195e646a0f0b89bf5df04ba233d6a12a271f7e04aa45cda99b4a55a21cbbb738515e32c56aac2496232b1008a6761c8045a1fe0f9a3644047b5966a58a600466c1b1d11ddad5aa573c43ebda887e16a05: +f5c0a7f8f6584c5d2f2e1d0810e8e86103e4e2d45cf9a721d8c47f67493396a43c6d6cce49633141078696131a8d84ed823f30664b289af9dd30c6407f6f0313:3c6d6cce49633141078696131a8d84ed823f30664b289af9dd30c6407f6f0313:d68abc609a7a0ce256699eb17043defe1eb822c9708f65718a06581fab2110ec2db09213bb9e0f3612ce4a3f8fdbe757a9f0eb2c3eba438a9088b18f6c5caabbe5c82f7a9ab2fecf0f5859d175e139263033742458f82a6f38756cd5bcdf9e0736db2cab20a0cd3f0f1cdbea8556d84909358dd8f69f0dacd49abf8ac1bfe75940d6939e6a55385b5ace7ce1fde120679ab6ea7a89d14268d29ffb46df105bf3909242c6605f3e3e2ab7448937d6db2ba054c7b14f432db41dc18a5b957336b7f52d978ec03e7d5764e9bd2f4b68958d937bf29823b27efb31e25b43925c4dacbe6718a60fea3b3270e7b76b0de0e70f7fa3c12c215ef72b95dc1b5276238179dfc52fc48859649fa582d05a60df68599a1ceea64f6412d3f8498ae2cedb124245883a240bc0851f0e324965be120486e1ea89a0182dfa8eabd3b8fa66a99c51491389f3c83a3cdb4267f3e4dbc98f0c44856b044dc88d90eeee8415bf73de171afe84be9035e0dc4c80cf0422469fe0c9bd1c6aa654a59b5e34eed351cda2871269ac478e8d382e740e9ac7ab4ddc4c0def0aeab797b6f1a427b8e4a8497a0b9797dadcd35c414fd55b783130f6cded38a44c1a89288307eb8425484137a8aedb030d54b616a82e3c5acffb08d6cc1a61745c29afc68a0c1838b139159c5fa6674d66b9e338115aad4b1b4710aa5d9517bcf7e1cb12d4e6a51c11789fdcae9d9bbe78f69a33e52df1833c876b02687a404facad32841cb2d52554e7b8e2209e3f88fd948c1ecf83957c96f43b034beda6c476096bcb09301ad61f8367cc43e156131862b42ece285bec2dcc2d02d094d042a16072eb22ab9888013be82371569400ec1f8ec7e79108c41b853365268fa4cfbc62c4ac12cc98d2ec38a87d6085859567c0f27d6d431a046e88a9815558660705fd05eb06c6c05e5b7d62347ceee27dffed7141540d608cb975075a9644acc6328439f9fa682b226b186154549011c3b0f0ff4f74caa71c1944e4cb836ce851d9b5d9e727c553e3c723cf98c273e5675cab899bb66f4633a76dea357341f983c53d9158ad319ada75408b41c06f26b7435b80dc3bc0aaf22a833ddedcd6785c87d196b0af2c9a43d1:d4c30a48c4523b1f84b14b657af8f859755bba6359988b675c6d85ddf35462820da476d84f6c402e65b020d9e8a2c285c16708ae58d1f8dbc65782a898a66508d68abc609a7a0ce256699eb17043defe1eb822c9708f65718a06581fab2110ec2db09213bb9e0f3612ce4a3f8fdbe757a9f0eb2c3eba438a9088b18f6c5caabbe5c82f7a9ab2fecf0f5859d175e139263033742458f82a6f38756cd5bcdf9e0736db2cab20a0cd3f0f1cdbea8556d84909358dd8f69f0dacd49abf8ac1bfe75940d6939e6a55385b5ace7ce1fde120679ab6ea7a89d14268d29ffb46df105bf3909242c6605f3e3e2ab7448937d6db2ba054c7b14f432db41dc18a5b957336b7f52d978ec03e7d5764e9bd2f4b68958d937bf29823b27efb31e25b43925c4dacbe6718a60fea3b3270e7b76b0de0e70f7fa3c12c215ef72b95dc1b5276238179dfc52fc48859649fa582d05a60df68599a1ceea64f6412d3f8498ae2cedb124245883a240bc0851f0e324965be120486e1ea89a0182dfa8eabd3b8fa66a99c51491389f3c83a3cdb4267f3e4dbc98f0c44856b044dc88d90eeee8415bf73de171afe84be9035e0dc4c80cf0422469fe0c9bd1c6aa654a59b5e34eed351cda2871269ac478e8d382e740e9ac7ab4ddc4c0def0aeab797b6f1a427b8e4a8497a0b9797dadcd35c414fd55b783130f6cded38a44c1a89288307eb8425484137a8aedb030d54b616a82e3c5acffb08d6cc1a61745c29afc68a0c1838b139159c5fa6674d66b9e338115aad4b1b4710aa5d9517bcf7e1cb12d4e6a51c11789fdcae9d9bbe78f69a33e52df1833c876b02687a404facad32841cb2d52554e7b8e2209e3f88fd948c1ecf83957c96f43b034beda6c476096bcb09301ad61f8367cc43e156131862b42ece285bec2dcc2d02d094d042a16072eb22ab9888013be82371569400ec1f8ec7e79108c41b853365268fa4cfbc62c4ac12cc98d2ec38a87d6085859567c0f27d6d431a046e88a9815558660705fd05eb06c6c05e5b7d62347ceee27dffed7141540d608cb975075a9644acc6328439f9fa682b226b186154549011c3b0f0ff4f74caa71c1944e4cb836ce851d9b5d9e727c553e3c723cf98c273e5675cab899bb66f4633a76dea357341f983c53d9158ad319ada75408b41c06f26b7435b80dc3bc0aaf22a833ddedcd6785c87d196b0af2c9a43d1: +1ab946c0c1aebf9ca37c2f4e2a4b337d5b1ebccd24734c9cb2a1608c881e57579afc63dfce0d489b40907aeed6dffe4cd8ef5a6ffa22989556445cbf9b3519c2:9afc63dfce0d489b40907aeed6dffe4cd8ef5a6ffa22989556445cbf9b3519c2:9bb071b62c04064b0c96e243dd198c39717b25c99448c2c002b84a99204c5a6e23b4b912028675bfdc4df93c5b2fb80881a23e0d44ba18bde99121eee86adc6f842819d6ebc7a288992da3285805a8b8b6fbcd2267b686b3e1bf7960b45f244f852e82492944e3d618bcc4514c17f722ba49aca7f2f3bb4e91f940e9cef015650c3e40b0c855a17c42f11e3a34acc85287dbe0f9093c00373d50c0b3064a5a5f2b1e89206517528295fd871703a8e762b5e76fb9b7473d2149b85b9461f5587ed7e7fc8b50aa09876deeb6e237078502142cec6bddc70140fe1d1f1658d5d3e910fd7036a2f924b499db1756f7c8ce0d5f0d045b39bc81c5c2f1a761f52ff393e0649b8db0bd8854bd026be2c7c3cd63526ba5a80d48335f033832d63376071b6308f05960cb3fc9fac932edd8376dae51f2c661f75b7c6f4ac856753aca62062877609fc4a0ff60670282c05e882d1a035bf9890cab296ac7a8df244c56f490250f020054b8af51be4fc318beba506232bf45e17f5c740cf09d37515a8bc894bc955c8a460877c7854f8be363b21933e16287ae0cb70f222d4e36b8b424975559bb4bfc8dd1d51b3c0faf4a53e302196f9fedb53287d09315dfffa2bc4b3acff137f9a76d6856217f79cbb25433fc97899fd6540f18088e84417e4833e4a91aaba4658ae9ad7f760dd9c5b7191a0d3c05541b83c025a7992138e6d1080da14c2c887c6d670aab374d436c272f9e96f85a9c423379c0d47c46df6de334ea2057158d33231e1426a66d3c70827aad5511b846e03b94923d5f94baf1f8cf11a861373a5b80ad5e317ec2a529e94e636cdc3aa29e5dac205a0c13f68fb198cf9456e6390aead4d9782a1038f6478d339a81bae7af2a04151c2f22e8d39fe071e1a52168d57c84c36293413f8e6ff6934f05e7efad6fa120c8c1c38ad1886a3d00bfc306459203c02cdf4f06652bc8fa0e8b9cc779d43fbb789e7dad5dc99f41d4cc588c1b65426a4e77389edd04977578f8f316bcdd9461d666472cdd276aa569721c65232256ba1cf0e7f5ea55321729bb0e0386a77b865532024696eddef485b7d7b28c1573b9347e414d4261995482e3b312de1331f84e7548607a84:bfabdea41810a53f8e527acd66ec106ce2ae1a67ff6a9b522e0f08fbbf1252682cb3a1dcc875601944cb88000f72e13907007903a77cd0db0316d419ac38c2049bb071b62c04064b0c96e243dd198c39717b25c99448c2c002b84a99204c5a6e23b4b912028675bfdc4df93c5b2fb80881a23e0d44ba18bde99121eee86adc6f842819d6ebc7a288992da3285805a8b8b6fbcd2267b686b3e1bf7960b45f244f852e82492944e3d618bcc4514c17f722ba49aca7f2f3bb4e91f940e9cef015650c3e40b0c855a17c42f11e3a34acc85287dbe0f9093c00373d50c0b3064a5a5f2b1e89206517528295fd871703a8e762b5e76fb9b7473d2149b85b9461f5587ed7e7fc8b50aa09876deeb6e237078502142cec6bddc70140fe1d1f1658d5d3e910fd7036a2f924b499db1756f7c8ce0d5f0d045b39bc81c5c2f1a761f52ff393e0649b8db0bd8854bd026be2c7c3cd63526ba5a80d48335f033832d63376071b6308f05960cb3fc9fac932edd8376dae51f2c661f75b7c6f4ac856753aca62062877609fc4a0ff60670282c05e882d1a035bf9890cab296ac7a8df244c56f490250f020054b8af51be4fc318beba506232bf45e17f5c740cf09d37515a8bc894bc955c8a460877c7854f8be363b21933e16287ae0cb70f222d4e36b8b424975559bb4bfc8dd1d51b3c0faf4a53e302196f9fedb53287d09315dfffa2bc4b3acff137f9a76d6856217f79cbb25433fc97899fd6540f18088e84417e4833e4a91aaba4658ae9ad7f760dd9c5b7191a0d3c05541b83c025a7992138e6d1080da14c2c887c6d670aab374d436c272f9e96f85a9c423379c0d47c46df6de334ea2057158d33231e1426a66d3c70827aad5511b846e03b94923d5f94baf1f8cf11a861373a5b80ad5e317ec2a529e94e636cdc3aa29e5dac205a0c13f68fb198cf9456e6390aead4d9782a1038f6478d339a81bae7af2a04151c2f22e8d39fe071e1a52168d57c84c36293413f8e6ff6934f05e7efad6fa120c8c1c38ad1886a3d00bfc306459203c02cdf4f06652bc8fa0e8b9cc779d43fbb789e7dad5dc99f41d4cc588c1b65426a4e77389edd04977578f8f316bcdd9461d666472cdd276aa569721c65232256ba1cf0e7f5ea55321729bb0e0386a77b865532024696eddef485b7d7b28c1573b9347e414d4261995482e3b312de1331f84e7548607a84: +04bb887a8a3184ffc7ea09c9bc7c1f7c3411556a7c7c398cb8b2d98ffd9ee8666ab1e4ae4aa0d38989aeefa805b578806e2e971ac7ac05409958bfe60071f4a7:6ab1e4ae4aa0d38989aeefa805b578806e2e971ac7ac05409958bfe60071f4a7:b7ab0c8163f478c6cabf2bbd7ca37cb02456d76e527eea1b0d26db242e37877632985a3e3ca41b52e21d79017bff81ee551ad72af277b410e42af822c608cd69d00bf440b75b787a8c915d70b6c6376c3f67fa64d612a1b449a7e2134d9c23230157d576e06a66a8422a611e2a0f097286c199ea2a162861864bd035076ab20bbae2b4408a2c6433cb23433a889fe6598f47be53bbd2c80f07a8fccb8aae511161e609da4d180acea544811e9449c5dc2250e3e5a0cd41da33a2da632e6038bd86f16d5b7c1be49fc6db499076ca91f7aa028fe38529700b21d072d2b75dcc8b43781d4bc4d3bb584d9da01c3ecc85b1e93fce045dadceea5106468bdfe5f70d66a4fad60e4fb864ec15ea50f6cb797223c8c756f7a1931a39464ebbb9679f6b01687c174eaa32b968b9cface8c167120aa7bd0242f003a0c377702551b30da2488eb2944052934aef4bfe115f0ab7405a3d5fa9bd796b371742bc114a9bf28c5bd25626295ce261a6a83ef60b77d2d32dd7105fc83664aa89765b3f8191eeeed878f2ebff2fb97663a61877c093933bbd0731e63757571b0e37cac99ed01fd214cbd4feb977e856e0a1a7ef0c408c20e0ddaf1fd8f028cfa08c850fa7090dca8cdde0cb6903da18c6290c66a1c0ae0a084bf250c51a9d035e5b16ec616636afb9b5bce36a775fe2175bcc2ee07220834eeb31caee50e9f8063fb1fc8468ae25e3966789a6d8dffe08a6f7a1e6726f93ae7482de0262bb1f8de0c95a99ecb95684d44b3f1a332a18d2cd3dcf253c33d735522f796b651c9a633a8ebe95d02bc0465825ee541a7d927bb5b90a6db5499f8d993ab404b1650b75e792a7c834eb41f0470138b0f578a04c9ba5ad950ac7c9b5d328f3408b645ad9c6bf196dd961445596bc78f284b8914b2a8cf9b7bd3a716d8f144bb6b15d831023713b5e41fda9b587ff9d6cc43c08d35a707f495283e1ace960487e7f02b7543b68a731a29bf3be14b6e9c37174a9f46f561199dbd27b46bfe62243e0c11c0edf13b64f411c8e8eced35d8428f79f10eacffb7234e546413d1eb0fad88c0e938593b43b5ee0e4285d4dddf5295dbf1a3ddbe9f4134dd76d3de70462c2f04fe0aebdf59a:cd84f55e5ef4531924c5a2181ec87a64541388c1059406bc07d53157a168e203cc8aa0f0069d53ff58a95b8a8caafdad26363c7d0f8045c4359e97b43602c606b7ab0c8163f478c6cabf2bbd7ca37cb02456d76e527eea1b0d26db242e37877632985a3e3ca41b52e21d79017bff81ee551ad72af277b410e42af822c608cd69d00bf440b75b787a8c915d70b6c6376c3f67fa64d612a1b449a7e2134d9c23230157d576e06a66a8422a611e2a0f097286c199ea2a162861864bd035076ab20bbae2b4408a2c6433cb23433a889fe6598f47be53bbd2c80f07a8fccb8aae511161e609da4d180acea544811e9449c5dc2250e3e5a0cd41da33a2da632e6038bd86f16d5b7c1be49fc6db499076ca91f7aa028fe38529700b21d072d2b75dcc8b43781d4bc4d3bb584d9da01c3ecc85b1e93fce045dadceea5106468bdfe5f70d66a4fad60e4fb864ec15ea50f6cb797223c8c756f7a1931a39464ebbb9679f6b01687c174eaa32b968b9cface8c167120aa7bd0242f003a0c377702551b30da2488eb2944052934aef4bfe115f0ab7405a3d5fa9bd796b371742bc114a9bf28c5bd25626295ce261a6a83ef60b77d2d32dd7105fc83664aa89765b3f8191eeeed878f2ebff2fb97663a61877c093933bbd0731e63757571b0e37cac99ed01fd214cbd4feb977e856e0a1a7ef0c408c20e0ddaf1fd8f028cfa08c850fa7090dca8cdde0cb6903da18c6290c66a1c0ae0a084bf250c51a9d035e5b16ec616636afb9b5bce36a775fe2175bcc2ee07220834eeb31caee50e9f8063fb1fc8468ae25e3966789a6d8dffe08a6f7a1e6726f93ae7482de0262bb1f8de0c95a99ecb95684d44b3f1a332a18d2cd3dcf253c33d735522f796b651c9a633a8ebe95d02bc0465825ee541a7d927bb5b90a6db5499f8d993ab404b1650b75e792a7c834eb41f0470138b0f578a04c9ba5ad950ac7c9b5d328f3408b645ad9c6bf196dd961445596bc78f284b8914b2a8cf9b7bd3a716d8f144bb6b15d831023713b5e41fda9b587ff9d6cc43c08d35a707f495283e1ace960487e7f02b7543b68a731a29bf3be14b6e9c37174a9f46f561199dbd27b46bfe62243e0c11c0edf13b64f411c8e8eced35d8428f79f10eacffb7234e546413d1eb0fad88c0e938593b43b5ee0e4285d4dddf5295dbf1a3ddbe9f4134dd76d3de70462c2f04fe0aebdf59a: +9776a467fa1400735412a79b495f9fca078ce1d87a8530d85c26055d3a394488c7dbe0e41c0a31c0942793ffd142d8b95cc82e5caa92a379ba23f644edf224da:c7dbe0e41c0a31c0942793ffd142d8b95cc82e5caa92a379ba23f644edf224da:d78553a1b7055b58b213101b1c84c53e164e39c6e9d36db43f30e19e2a125a9a67709eafef964fa5bab7261ddb3a8a0188457dfbf5159c40e51da8208483245781d7131e23a8bee5e506331816b9deeefe6e556e3f0c95c668d1bedb7da635065458ad20467012f59f171352068020ce3c75878693f6437bc4a09f13b9b0f0cddaf1691b872f82008093ebfbe233d0313e72c8632d7d1793f0b81c7688f54470330f04e64860e6446bfc6d96c87569bf182f0f4385af485d4299cac04e06ba473465566c477f07b9db277ab4a9de2fb2ded0a5011cd06d675c0800b34f55bcf3ec72d21ca150c8bf2361287be81efabb96d8688a1dee3f430f06f637dfd06f151464a05c95f5fe76af2e06d0123f6948a26b3be835045aa268cc1be976697107770208a7568f025c2d53c719e524cc369d9b4a337d8fd1ef345b9bca57fbd7b65a6b997cad3fce4cf06f2ca43ebe2986d09682d47c922b2cb7569d98de97a6164f5470eec71ceda520ccec7732bd01689ef81656e9f6d0c58a895558aee863f5469e7ab97915bfe0b80a064c659b183031f7f1a86fb11a9d528c2815dcaa2f0dec3d21a882e106e20493ee0acb7708eaa2912574ae97bb288b41fc0925053a29b0bfbc0ebae8d63cc0b46e3738046c5a202530bcb15b187a72854aa2d8a7a76c89a89a5db46032074e1bd7de77ef2065a08f389d783cf759ebd5a63a44d919f948f560c3e94c4239e274e051a20485a430cbd529f313d9f7ed679a34187b24f8413087a9021e4731730f5f461fc5aad6654dfa1c0504d26124707e63ee57f931b2785908f86b104b3ecb96000251d06ce1fa45e4cd6df91ac15bbf7ca3c3eb8ee0827612a29ecb7a36d5470c40505182fa9ac913570d0c1050d9a43455cb7bdc17d169805f018956f854f8919bbfb719e1867b36a64aabcdb807f48dccc0672f67887450b3f3e958d78499e0d1ab368aa49442e5e8a332bffd44c169ea67629c85724db6f1586b6c6b5be4864dfd53da7c0f7b8bb3573116be5077d332bd12a6300f3a68a89866b479ec2baa277f9f56f6e1d49d741eb322035ff8cb1de85c8dc87ac8e6e4c5d20bfb6d317ab125930c42609be3ae82242a9ef0568858d8:e1317ba2a123ae3b29e7b60e8e93beedd7a08451a013695b6dcf358e4034026dc74037afbdd217ff4b148b029138f4bcc8f9836abbae7e6276e9e769dbd8f007d78553a1b7055b58b213101b1c84c53e164e39c6e9d36db43f30e19e2a125a9a67709eafef964fa5bab7261ddb3a8a0188457dfbf5159c40e51da8208483245781d7131e23a8bee5e506331816b9deeefe6e556e3f0c95c668d1bedb7da635065458ad20467012f59f171352068020ce3c75878693f6437bc4a09f13b9b0f0cddaf1691b872f82008093ebfbe233d0313e72c8632d7d1793f0b81c7688f54470330f04e64860e6446bfc6d96c87569bf182f0f4385af485d4299cac04e06ba473465566c477f07b9db277ab4a9de2fb2ded0a5011cd06d675c0800b34f55bcf3ec72d21ca150c8bf2361287be81efabb96d8688a1dee3f430f06f637dfd06f151464a05c95f5fe76af2e06d0123f6948a26b3be835045aa268cc1be976697107770208a7568f025c2d53c719e524cc369d9b4a337d8fd1ef345b9bca57fbd7b65a6b997cad3fce4cf06f2ca43ebe2986d09682d47c922b2cb7569d98de97a6164f5470eec71ceda520ccec7732bd01689ef81656e9f6d0c58a895558aee863f5469e7ab97915bfe0b80a064c659b183031f7f1a86fb11a9d528c2815dcaa2f0dec3d21a882e106e20493ee0acb7708eaa2912574ae97bb288b41fc0925053a29b0bfbc0ebae8d63cc0b46e3738046c5a202530bcb15b187a72854aa2d8a7a76c89a89a5db46032074e1bd7de77ef2065a08f389d783cf759ebd5a63a44d919f948f560c3e94c4239e274e051a20485a430cbd529f313d9f7ed679a34187b24f8413087a9021e4731730f5f461fc5aad6654dfa1c0504d26124707e63ee57f931b2785908f86b104b3ecb96000251d06ce1fa45e4cd6df91ac15bbf7ca3c3eb8ee0827612a29ecb7a36d5470c40505182fa9ac913570d0c1050d9a43455cb7bdc17d169805f018956f854f8919bbfb719e1867b36a64aabcdb807f48dccc0672f67887450b3f3e958d78499e0d1ab368aa49442e5e8a332bffd44c169ea67629c85724db6f1586b6c6b5be4864dfd53da7c0f7b8bb3573116be5077d332bd12a6300f3a68a89866b479ec2baa277f9f56f6e1d49d741eb322035ff8cb1de85c8dc87ac8e6e4c5d20bfb6d317ab125930c42609be3ae82242a9ef0568858d8: +09d8122697126dfc7e11685a04123fdfb47ccddb4499d8a3aef418cb65aed7a7f8ddb1c00f6e0f4beaa6fc38e5d0a5775ee28c80dbde3f0c7930a33aad7150f3:f8ddb1c00f6e0f4beaa6fc38e5d0a5775ee28c80dbde3f0c7930a33aad7150f3:a0d8d8798eba22f56760c30643e9fc6795547ea5f2f2bbd11c0392b2ebf711aca22f0824199fc3188a45bdffde70ece9ab15a5ea89622a5871e0ef7685d10f1274cc195b4fda81f879d1e9bf42f873b20a859c233f9e49adbf057731e11335e9b6d8ed0e069e134ec461ca8890d7b0473c405e8a9d95d15711b12476103762c626d9f2aa5dd519bd825b60b3234ebf651e0d1933371c52bfd8ce33fc36bba328f7f3f2ccc01000a89904af37e4e1e9e15fffab5c2b0c47f37cdcb068db33ac36a5f0d6de1203fbf8949324bd3efda0f9889db00da2317b49fd186999df7fcdc3cb4e1d18faa254561c251178b8d33fdc9dccd8d2d721b93a536ccd3c0e9c856337f195eee7da9a7f6b0a42b7c541c6a68c595bf34704d9fe3a56d2ec8481d577c96ecc08b8e40acdbf050e20c683f39c414e8cbfcf4a0152314c05987a83bde3025b735cca3023abc5feb7e00d0236b4f24b15e679db052c8d2fddb3bef8663a6df819a9815527a1a2f60a0fa4e5078ddc6d435fe89287b30ffdeb5d9ae05d1a8690fbc7590aad57d43d22c12ace2c8196888e354e9f782f5dbb44149e83fb8bbc9da6d89ce206c1e2b6b2b28f933f3e5ff1175a31a8ff5d31e65c8b00c5ba462224a1e09d4f09cb40fc87c36e7d285c774a96976203651828e783628847ac512e5d1c35b35b030171f92396f5ffaff585cead04b6ae210d80707cc6832d98a20d3a947648da2604937fefd25a9fe0fc5cac083ddd7d2075307f4f382664f687dce8c655ded9c12d48ff7601df2a48d37fe214970844c075f2eab002059fc2271e617c9657a01bec1dd38f6c28ba8a617bd30851e3f9dbac904418df1d0215ad45dfc9f02b5c5e9f9bbc6de8b07af0bd1f7fa8922544f12d2a3e1aadff7e9c6b93320c3a61ef33da07eb87b1617f9e77d7702e558bc7d8122e0dfe2ae83e836c5b1a62aa585c0dffe716f7463c0b33da5b1eda556a1ef1e45042c79bdd3ec3cb8863a7bc1b0f7e1c05bd9920f05b4eda86517705ed07f6dca7bb00ae0456e6787d9fae8ede4ecd0bc572eb5cc6d19e891f1bcb229e9409e06574c7df058173cb58c3fdf20f3ff17c3705af62d9b7225c5743f600607f77cbe7d6e7618abc79:18cfaf6dc8e4e8582bcefe0cdc6fcefe6a4a87ea629585f37d2fba446b3aebd452426382da0d491c39cb7d54d273005dc132121568d2ab674520adda7523840da0d8d8798eba22f56760c30643e9fc6795547ea5f2f2bbd11c0392b2ebf711aca22f0824199fc3188a45bdffde70ece9ab15a5ea89622a5871e0ef7685d10f1274cc195b4fda81f879d1e9bf42f873b20a859c233f9e49adbf057731e11335e9b6d8ed0e069e134ec461ca8890d7b0473c405e8a9d95d15711b12476103762c626d9f2aa5dd519bd825b60b3234ebf651e0d1933371c52bfd8ce33fc36bba328f7f3f2ccc01000a89904af37e4e1e9e15fffab5c2b0c47f37cdcb068db33ac36a5f0d6de1203fbf8949324bd3efda0f9889db00da2317b49fd186999df7fcdc3cb4e1d18faa254561c251178b8d33fdc9dccd8d2d721b93a536ccd3c0e9c856337f195eee7da9a7f6b0a42b7c541c6a68c595bf34704d9fe3a56d2ec8481d577c96ecc08b8e40acdbf050e20c683f39c414e8cbfcf4a0152314c05987a83bde3025b735cca3023abc5feb7e00d0236b4f24b15e679db052c8d2fddb3bef8663a6df819a9815527a1a2f60a0fa4e5078ddc6d435fe89287b30ffdeb5d9ae05d1a8690fbc7590aad57d43d22c12ace2c8196888e354e9f782f5dbb44149e83fb8bbc9da6d89ce206c1e2b6b2b28f933f3e5ff1175a31a8ff5d31e65c8b00c5ba462224a1e09d4f09cb40fc87c36e7d285c774a96976203651828e783628847ac512e5d1c35b35b030171f92396f5ffaff585cead04b6ae210d80707cc6832d98a20d3a947648da2604937fefd25a9fe0fc5cac083ddd7d2075307f4f382664f687dce8c655ded9c12d48ff7601df2a48d37fe214970844c075f2eab002059fc2271e617c9657a01bec1dd38f6c28ba8a617bd30851e3f9dbac904418df1d0215ad45dfc9f02b5c5e9f9bbc6de8b07af0bd1f7fa8922544f12d2a3e1aadff7e9c6b93320c3a61ef33da07eb87b1617f9e77d7702e558bc7d8122e0dfe2ae83e836c5b1a62aa585c0dffe716f7463c0b33da5b1eda556a1ef1e45042c79bdd3ec3cb8863a7bc1b0f7e1c05bd9920f05b4eda86517705ed07f6dca7bb00ae0456e6787d9fae8ede4ecd0bc572eb5cc6d19e891f1bcb229e9409e06574c7df058173cb58c3fdf20f3ff17c3705af62d9b7225c5743f600607f77cbe7d6e7618abc79: +10201bf0084367590de674cc0ed2648ec25d3ba8db40d00ede153398508bc126badbd05e5f79e31169f740ba46a58910a1b77705af45717b2af80856457c58c9:badbd05e5f79e31169f740ba46a58910a1b77705af45717b2af80856457c58c9:7bb1470617d11e45eb602a829ad773ee2bb7e6b88da4c04a7216a450f84993a498cbd3b9254028f2f99fc21a23288bdc1e151a72a9130c3dedda1bbbccd4e6c0f48ae9f35318cbefc959f405045e6e0b5fb2e738f2b765be11b1b6a0f1e8319549d95fa8d1df8167cd4a7717ae1636a9df54d96eaf2d63236900fd11338252a5008d5d480e2b1e9861d1f70688c47eae4689da01a47da3dfb6d2bab3cdf505ee5d801a152c267093d17e9bf7137a6ee7b834d0085500e401c17f3286c1575d1c0100fa9807630c4a990654c1e71a8b715627bb13d442c84a449844c404b872bfbac718a48d0ea0945c77166a53139b0ff0098134764f9ecdb88eabe07ccb2cced4955e08249b2f5770ad41fccd7b5bb372e6c33767e07f5be7d10712de81841b134e193df0776a0fc156ff5d0e96f40a704753e1145e9fa083c4ddeef4416234f6e1a2382c8e5b3ad405458e89d2f493a4d7c29a23de2107485b7f56350124e7e0d695c522b6de7a9247a2924ce6f2863236c10cc21264ad54590d314763ea1a19afacd90eba955870407e8c6365a143a5c1b9a8be5e4a4dcadb72e0d47649bd53abd46b5c6960eae2cab773753cc0e04e99414bc2cb30f48bb54139d066e43e2f0e1a4ae963858bef967df8c84140d2d09202b406d5d85cb7a96cc57f233eb2187ffd02f94e92297b5e69d969d3a5936efe4929144f258bfb39dd0ce26359c4549fc218a0aa54f31bd551b8781acbbf61cb3f732cdaf622c6a69188cf557a3a92ed153e69125a4090ac451536a0e9a63a41782910ffccb4e850021123ffd1f3bf39c73460a65ccfe4dba9bdefb5d5f4da6c469aa1322fa27043238363ee72918688d7ca1c4c2952e430d563256bb86d350a35ee82e01504747f31d02e03aedda546d0f1b2f451b870821602d00e819036ade5a7c7fcd21a6de6af35b1f9632a70af65df6445f6fadfbc0f416755c8246640e56b856b66ddd92a60c03538221dc8fb142ce2dbacdb7425f33cb85d850cc02c315cfc111f6f651dde1bdb67fb208e1f6bde784ddcf7bd18c8051a2e0bbf1018b8f39536c589de65eadc6cf379b77cad13f9089cb323fb2e943d06cdd10705c121134c6548dc53415f8c370ec690:f1d996588b298f271e970cebd2a1b339979cd29dddee3645d07fab8ab465dde3e98667ec01ad7f1c0a6592e0697e665c72fd3814dbe189ed5f4e76c794e538097bb1470617d11e45eb602a829ad773ee2bb7e6b88da4c04a7216a450f84993a498cbd3b9254028f2f99fc21a23288bdc1e151a72a9130c3dedda1bbbccd4e6c0f48ae9f35318cbefc959f405045e6e0b5fb2e738f2b765be11b1b6a0f1e8319549d95fa8d1df8167cd4a7717ae1636a9df54d96eaf2d63236900fd11338252a5008d5d480e2b1e9861d1f70688c47eae4689da01a47da3dfb6d2bab3cdf505ee5d801a152c267093d17e9bf7137a6ee7b834d0085500e401c17f3286c1575d1c0100fa9807630c4a990654c1e71a8b715627bb13d442c84a449844c404b872bfbac718a48d0ea0945c77166a53139b0ff0098134764f9ecdb88eabe07ccb2cced4955e08249b2f5770ad41fccd7b5bb372e6c33767e07f5be7d10712de81841b134e193df0776a0fc156ff5d0e96f40a704753e1145e9fa083c4ddeef4416234f6e1a2382c8e5b3ad405458e89d2f493a4d7c29a23de2107485b7f56350124e7e0d695c522b6de7a9247a2924ce6f2863236c10cc21264ad54590d314763ea1a19afacd90eba955870407e8c6365a143a5c1b9a8be5e4a4dcadb72e0d47649bd53abd46b5c6960eae2cab773753cc0e04e99414bc2cb30f48bb54139d066e43e2f0e1a4ae963858bef967df8c84140d2d09202b406d5d85cb7a96cc57f233eb2187ffd02f94e92297b5e69d969d3a5936efe4929144f258bfb39dd0ce26359c4549fc218a0aa54f31bd551b8781acbbf61cb3f732cdaf622c6a69188cf557a3a92ed153e69125a4090ac451536a0e9a63a41782910ffccb4e850021123ffd1f3bf39c73460a65ccfe4dba9bdefb5d5f4da6c469aa1322fa27043238363ee72918688d7ca1c4c2952e430d563256bb86d350a35ee82e01504747f31d02e03aedda546d0f1b2f451b870821602d00e819036ade5a7c7fcd21a6de6af35b1f9632a70af65df6445f6fadfbc0f416755c8246640e56b856b66ddd92a60c03538221dc8fb142ce2dbacdb7425f33cb85d850cc02c315cfc111f6f651dde1bdb67fb208e1f6bde784ddcf7bd18c8051a2e0bbf1018b8f39536c589de65eadc6cf379b77cad13f9089cb323fb2e943d06cdd10705c121134c6548dc53415f8c370ec690: +c4aa425246b5173f5ef898152eca3d092bb4c2dd02853fcfc7178399f4e2f75829b77a3075f419243c0c1bc39659d73117ac00e55e8de38fe9829a879cc5b8a0:29b77a3075f419243c0c1bc39659d73117ac00e55e8de38fe9829a879cc5b8a0:7df978a1f4976838ffed7449a4dc138b604f4b2a4ae689ce75018ebccdab2eaa0b60768f7208257f2b28e7aa09bf6c05888da46fd396d1c803011750e30eb484870c8806977696f12ebb9feeb4caf92a02dbaa22bbff63f842c3ba147bca7c00314278acd0db173569f4e36527958ef6f1002bd3cd01f407a86531edcbd9f31b3a4ab880a4f5b52b42d0d4a1ba66a2098651ae3e6c9151f40273285f7f6a4e81606bf980f689504b42080fdb97c72846fba9047c7e660ba5c6bf126a9a599e2571fa13505af7581bfebc16513f5c94dc71937e6e61b3ea10939b02ea10859f32d7912b9e3806abef6185fcffa68821478005cbfc1d637dd020425620a318074898bdc30931c59ac0c66c4d1238b097cd5b170f084435d4bae48a03d92fd48fc2caa4ffc505f1bca516fbd6e4f888cced982ae0ddb88fc28aa697b7071d015b0acb2809b01d1d9c7e7b53eee6824cc37cce5b6993d88d83eafc2e928a6f147db6eb80b1a69f01605b046bd2fd1d92c5459d6d3398a9caa299ddd0c3ba2e08941307b120cc13992f7003aced14a4a4d923bbb12fc393ffcf920b9f6d4775e94d4a512267fd26a6997c6062b4c9900f9862b9ea0c8d7df19f05c2b604af5b9864fb2754a8073bbbfb18233e6e150f72a525e3a5760fcda7d32a60034f956e3cbd3436c200830b3e7a14571220bcb627d5a4be72c20b23351b2d920602a51c3eb32c1237039dfbff43c987fd8563777f0e5a39f8146c164bdffce44f3b13ee74d64bfdcf9803f03dd0172ac4fa4bf6c7839cb11f3d34baef0e32b54942fc4fa38f473e2966f4911c0e80d76937b25b7632275ba88309635a60df135489208d3e734b672eda7d2ba21579aba8d8860ea764fd67eaf9c38ea7637d1bad57b2f3d782b91e1d5d92ac300bdba7ab9113ce913d0c793c12a9a726e3fcab05cb479977871640630d459e69e81ca5cf56ddb2a0611d61d481c1b8cef3804bd4e5754a61eb49b17ef2b03c83057b5d20d882058c00f54b6cca86be95350dd7bcb25e4c1c4658f45229c8bb9f5cdfcc44795c978e3388d325760106e52be9834bd81ffc5c62486b6f33c27459df178eb946e7a82db9ce0d295b925bb6126dd55c31f49a68dcefc7:5d8545a4be3fd6da2578c2eccb648d83fcfe587133fa7ae4a1cfca9ae6daa49259c952044a85a20b6f5324f827dba2d1a8388c40a928b950913c634fb30927077df978a1f4976838ffed7449a4dc138b604f4b2a4ae689ce75018ebccdab2eaa0b60768f7208257f2b28e7aa09bf6c05888da46fd396d1c803011750e30eb484870c8806977696f12ebb9feeb4caf92a02dbaa22bbff63f842c3ba147bca7c00314278acd0db173569f4e36527958ef6f1002bd3cd01f407a86531edcbd9f31b3a4ab880a4f5b52b42d0d4a1ba66a2098651ae3e6c9151f40273285f7f6a4e81606bf980f689504b42080fdb97c72846fba9047c7e660ba5c6bf126a9a599e2571fa13505af7581bfebc16513f5c94dc71937e6e61b3ea10939b02ea10859f32d7912b9e3806abef6185fcffa68821478005cbfc1d637dd020425620a318074898bdc30931c59ac0c66c4d1238b097cd5b170f084435d4bae48a03d92fd48fc2caa4ffc505f1bca516fbd6e4f888cced982ae0ddb88fc28aa697b7071d015b0acb2809b01d1d9c7e7b53eee6824cc37cce5b6993d88d83eafc2e928a6f147db6eb80b1a69f01605b046bd2fd1d92c5459d6d3398a9caa299ddd0c3ba2e08941307b120cc13992f7003aced14a4a4d923bbb12fc393ffcf920b9f6d4775e94d4a512267fd26a6997c6062b4c9900f9862b9ea0c8d7df19f05c2b604af5b9864fb2754a8073bbbfb18233e6e150f72a525e3a5760fcda7d32a60034f956e3cbd3436c200830b3e7a14571220bcb627d5a4be72c20b23351b2d920602a51c3eb32c1237039dfbff43c987fd8563777f0e5a39f8146c164bdffce44f3b13ee74d64bfdcf9803f03dd0172ac4fa4bf6c7839cb11f3d34baef0e32b54942fc4fa38f473e2966f4911c0e80d76937b25b7632275ba88309635a60df135489208d3e734b672eda7d2ba21579aba8d8860ea764fd67eaf9c38ea7637d1bad57b2f3d782b91e1d5d92ac300bdba7ab9113ce913d0c793c12a9a726e3fcab05cb479977871640630d459e69e81ca5cf56ddb2a0611d61d481c1b8cef3804bd4e5754a61eb49b17ef2b03c83057b5d20d882058c00f54b6cca86be95350dd7bcb25e4c1c4658f45229c8bb9f5cdfcc44795c978e3388d325760106e52be9834bd81ffc5c62486b6f33c27459df178eb946e7a82db9ce0d295b925bb6126dd55c31f49a68dcefc7: +f13cafde6f39b963dca96626862f4fbc5c2e00ddf08beceac7a6e2fca9e1ccf7c1b01a91e8ee0b9f19a72e5e7e0aefcfdc44a157474e99feebd0ff552d73b2ac:c1b01a91e8ee0b9f19a72e5e7e0aefcfdc44a157474e99feebd0ff552d73b2ac:2bee73b74f1b7622eb096a28d83a819bcec22d9999a32062103d604ae6d78edf8f893895d2220ab75690410c58aab590a98ddff23a94d2350f889e53464200a527d54d62571107b27e574f542ebac249b8e2e3ce08d1bd27bd8d29f2e61243deef0e6938e52ee2992ff2187d7a7f5282edd98fc4985b619acb80aa9d03d6cb84b821106f40d6e5f4c387ab0af6f206615d0a175f7e60ee2755aea34675fdd823eb24109a9bd818ea2d9d9bd199cf8dfe79624b0372ae85e98c60200234bd413f4a62ce68a47b6c9b12857c0d399a448e5a5280e9f22f9b12ea2cd3c68713e77d0a11f3628d8ec5e060639031d3b640021c9c38809dc5f42d2e1c2e2346c86e24eedc5984a115a42de8de7e35c9917539e89885ca916e072afd5d46846b2a935961c2fe28e9eb3c8f896b86fc120cbd3af2aa139c499d29cfc3699db79c14484e9ec257a5f64344b7ad1e3dfb34eee7654c6bf12fd38fbba80fe1762aab57112b3a94e2bee79041d1e88440f85fb72dde68d49e84bced998a2f6335446e4a835e70c5f827fb3ad7823d5fbe3be5f6ec7e434ee524ccd9ff5b7e72a32d091a7e17c8b1ae41a1af31793cce91d84c3622678969c8f517dc26e3cd61d2446912283f9353bb5ad03c111c6233de314c61b831cbf38b04fe58cf44f1d2d0b45f25a6b4e0256859cd5d830fac5ec3c8d76398559e9b26010f5e1da5f25d2200935453ffac5aea51f7e81e72ec8e5f04d2f885c7b45c63f64456cfe231b8cb24aa1620a902639ca78dd391aa4a3d03e11975c8907f964fd55df9bbb140e38d6db93256b4b39c2b7bcbe35b11826bbf8c08f1dcb48edc4bfb70462a35ea8cd8cba79fab8b4c44e73be7ecfa112166f6dcab70d8bb55d8b8428c2da71aaca2fc3d90f3cc5ed01551358d60789b9d571efe10892027fa37404aaf59ec1c2d7111ecc3592467ed1d9b8aba8e229e32d2a00c19db7187fbcb122061961c1fdaca307e9c9c9de972ad51402fa67dc1c2a403b3c5e8b1e246862d6ad6a498db6d761fb566f6065942b60ad4b4309d182bc5154cfc36863185a87e23abaa1d541ab763a4a1066c0a7a8c3d821ae32fd31c8892401046d0a20e91a64779f4bda81120af3fb3486d3fc0a7:6ca9f80a62501faf319fb84af471f676ae3fff85565c97981f1457cbb8c49f97b266316a992db0d42bc502f095a5f2d9a4e1cfac0cc935d3882c8a3a0ea6e10e2bee73b74f1b7622eb096a28d83a819bcec22d9999a32062103d604ae6d78edf8f893895d2220ab75690410c58aab590a98ddff23a94d2350f889e53464200a527d54d62571107b27e574f542ebac249b8e2e3ce08d1bd27bd8d29f2e61243deef0e6938e52ee2992ff2187d7a7f5282edd98fc4985b619acb80aa9d03d6cb84b821106f40d6e5f4c387ab0af6f206615d0a175f7e60ee2755aea34675fdd823eb24109a9bd818ea2d9d9bd199cf8dfe79624b0372ae85e98c60200234bd413f4a62ce68a47b6c9b12857c0d399a448e5a5280e9f22f9b12ea2cd3c68713e77d0a11f3628d8ec5e060639031d3b640021c9c38809dc5f42d2e1c2e2346c86e24eedc5984a115a42de8de7e35c9917539e89885ca916e072afd5d46846b2a935961c2fe28e9eb3c8f896b86fc120cbd3af2aa139c499d29cfc3699db79c14484e9ec257a5f64344b7ad1e3dfb34eee7654c6bf12fd38fbba80fe1762aab57112b3a94e2bee79041d1e88440f85fb72dde68d49e84bced998a2f6335446e4a835e70c5f827fb3ad7823d5fbe3be5f6ec7e434ee524ccd9ff5b7e72a32d091a7e17c8b1ae41a1af31793cce91d84c3622678969c8f517dc26e3cd61d2446912283f9353bb5ad03c111c6233de314c61b831cbf38b04fe58cf44f1d2d0b45f25a6b4e0256859cd5d830fac5ec3c8d76398559e9b26010f5e1da5f25d2200935453ffac5aea51f7e81e72ec8e5f04d2f885c7b45c63f64456cfe231b8cb24aa1620a902639ca78dd391aa4a3d03e11975c8907f964fd55df9bbb140e38d6db93256b4b39c2b7bcbe35b11826bbf8c08f1dcb48edc4bfb70462a35ea8cd8cba79fab8b4c44e73be7ecfa112166f6dcab70d8bb55d8b8428c2da71aaca2fc3d90f3cc5ed01551358d60789b9d571efe10892027fa37404aaf59ec1c2d7111ecc3592467ed1d9b8aba8e229e32d2a00c19db7187fbcb122061961c1fdaca307e9c9c9de972ad51402fa67dc1c2a403b3c5e8b1e246862d6ad6a498db6d761fb566f6065942b60ad4b4309d182bc5154cfc36863185a87e23abaa1d541ab763a4a1066c0a7a8c3d821ae32fd31c8892401046d0a20e91a64779f4bda81120af3fb3486d3fc0a7: +c846344261a34865393834bfaa3a15a3f53ac9e13833b0b287122781b79de392ebade0226195ae254b6115e21696a9c65a19d5e040443131c22b89f02f69ab78:ebade0226195ae254b6115e21696a9c65a19d5e040443131c22b89f02f69ab78:5abd13e95b6ee1d5514768282200a14f7d1a571f3468e22efec993463066a37aec8373e5fb499564191f3294a9b30afb5f1a34d4d88abc3e9bc303c1aba05bd8faca90ee35d97ac3dd9106f6fa3ca81a3810eccefa6a209ea3f3fc3049dcb1b003c728f7f6374ca98c582de6db1af760f0a02133ca4a010324304d26a0e50af0d13c134da34a03a41e83ec8f10ea5b859bec1f51b01cabb2d16c1fc52b058f8e5defaede128171c2e026902316f871b35e3292656f0e5b39bbbc81d0c0830e6ac01fac9b4539f47f9acfbd58b7ab9f5a125600f251a271d7bf167f2954ca8e1e0c96e16b06e8307df88bb8e9d57d5ba044f27f3eaff81d9f150554aa7122fd10d11f35d2be2b1624e3e1a1d77fea4c5c7f8b983e945ba8c08dc1545b3e6b2973ad041c44d0617eccc871a3821a9ffea9db7c2b0d055da55de0b35063e4225aee6b225ab2a7906a8ee329d1b3972e0d1f70817c50ccfe9403d12ad62c94923b9aa2d7f85a8dda47be4dcec0dc2b0b58f7ac190ae0579b9b13bbb8b16a31b0ab4d6f2791253ab4751b536b88d3b4937cc3a110aa82a6ffed6853524b66b3effcd2f63c6f9645cea13aa23cd1c99d9ffda4cd3a9c5df45ec74726c3471128b7089fbd82694d2d3f08dc9306c0fc9ce7c801138eb1ecb756e571e9059b75ed03f92a31502fbeb5fec51de9359010c4397d28b65e356e38001d0d51ac9600728c78b5766e0f217938b410e785b4c01e86a3452bcb3884aca47540859cc49b000f0b61fdbe72752574b27a22d4c40413a43b310924b1bb140fc9fdaae266d65930e3f234fe841d82b26176ff86c5d2bd8d965c52d728064ebdf68dc8e4834941801cca0b2f256d4f6c3dd19d35d5362bbf9b8a3a1c863e092689dd2852add488bf42685b11e1e1ad5745d075628d731f91cfd749159e2e1c837f4ef83d80ea1dd9bded5f88018ce1d4b3371f954353f3d894370062c0965d67986dbc481715f42dd2c91607ab8b5f0d89f66e68d73d50d640524d72e69134b887298e5cd8c4b905ba5efa0e9d685214b842f50a2a3983a1af585af2ca43dbcf02c40897ae2e1ab51dbce570345e8e135fb7b4eb0a1d6a0bb5a8a1807e425b2d628360768058e61ad1cfaa2099:d5e41b47ad0f3400709770ed43919bafdf24381b661544e51d8b5cee9e97b3676a4c0ffaebb2cbd2db798532b65cf654a5b6c166ef886cb0fbbf4a4f844c440b5abd13e95b6ee1d5514768282200a14f7d1a571f3468e22efec993463066a37aec8373e5fb499564191f3294a9b30afb5f1a34d4d88abc3e9bc303c1aba05bd8faca90ee35d97ac3dd9106f6fa3ca81a3810eccefa6a209ea3f3fc3049dcb1b003c728f7f6374ca98c582de6db1af760f0a02133ca4a010324304d26a0e50af0d13c134da34a03a41e83ec8f10ea5b859bec1f51b01cabb2d16c1fc52b058f8e5defaede128171c2e026902316f871b35e3292656f0e5b39bbbc81d0c0830e6ac01fac9b4539f47f9acfbd58b7ab9f5a125600f251a271d7bf167f2954ca8e1e0c96e16b06e8307df88bb8e9d57d5ba044f27f3eaff81d9f150554aa7122fd10d11f35d2be2b1624e3e1a1d77fea4c5c7f8b983e945ba8c08dc1545b3e6b2973ad041c44d0617eccc871a3821a9ffea9db7c2b0d055da55de0b35063e4225aee6b225ab2a7906a8ee329d1b3972e0d1f70817c50ccfe9403d12ad62c94923b9aa2d7f85a8dda47be4dcec0dc2b0b58f7ac190ae0579b9b13bbb8b16a31b0ab4d6f2791253ab4751b536b88d3b4937cc3a110aa82a6ffed6853524b66b3effcd2f63c6f9645cea13aa23cd1c99d9ffda4cd3a9c5df45ec74726c3471128b7089fbd82694d2d3f08dc9306c0fc9ce7c801138eb1ecb756e571e9059b75ed03f92a31502fbeb5fec51de9359010c4397d28b65e356e38001d0d51ac9600728c78b5766e0f217938b410e785b4c01e86a3452bcb3884aca47540859cc49b000f0b61fdbe72752574b27a22d4c40413a43b310924b1bb140fc9fdaae266d65930e3f234fe841d82b26176ff86c5d2bd8d965c52d728064ebdf68dc8e4834941801cca0b2f256d4f6c3dd19d35d5362bbf9b8a3a1c863e092689dd2852add488bf42685b11e1e1ad5745d075628d731f91cfd749159e2e1c837f4ef83d80ea1dd9bded5f88018ce1d4b3371f954353f3d894370062c0965d67986dbc481715f42dd2c91607ab8b5f0d89f66e68d73d50d640524d72e69134b887298e5cd8c4b905ba5efa0e9d685214b842f50a2a3983a1af585af2ca43dbcf02c40897ae2e1ab51dbce570345e8e135fb7b4eb0a1d6a0bb5a8a1807e425b2d628360768058e61ad1cfaa2099: +faaf55d3c29714b65c2281e2c22d6134971a2e74008fb94089a773eeeb4483a639862eac6dd52e381bb34dc196ba8a374dcb7df6cb140fd0cfa6cfa39b8c753f:39862eac6dd52e381bb34dc196ba8a374dcb7df6cb140fd0cfa6cfa39b8c753f:94e661c25240a89e823d7f5dc0e692eddd1370c35ac44d5a8c8798d0c9aafdf0bbfb549260568dba1c69086bee636be8edccd3cbb27016244d54d7ed2feb7fa64614d45449d7e058e71b306c22e6911c2ac74207bae5a84d0fc247be49d356e5d4353ba5586b6e4b2b97ce9e2377b6eed92c849e676944ae90dc4208e300e19cc91dc26bbdd5a30cfa9281a15efd873066f85af3a26f310623e009804853cc6855903ea64a909897e315e73d312948980ef6289db21a5ebbec8c8efe20d1d53dfaad6d9f4296532e887c37350105a633abc773188751b28c3a08f1b5ee0472de4627e6b61b68278dd51ced6a61ecf38886e45339dc6c60c31e850ef8296ae80f9d31701776eb9af21693f4c52ec062625738d4e3afbf71d1c81fc4846360363ea541a976623a5e4e6b6a67237e9237173f1a1d543302858885714c2a591d0a786282a0285a3711f7bc2b63ca7987e9ae7d02035555cf3b6ad6f71ca98aa928883bf81dd6f86493eaab5637b4dd569d1ee8de6a44bcedb62b9706b1db89e3f05df16310017d89ef3e4bc099b721a5c8d38043d6e4a22cf04009c0fcee6be69937829954941b8b4a1ebf4daea0d774d0782be176c8e591907756c2cf75dea6f7877dd6875b8fe1012f3050cfb1289cf088667e1522eeedc927ac86bfe2c407432b4a813a6a7a5504e999206db1827e25fafd70ced36db3b281b6f7b14ed5baa0572315a939c5bf4abb133d2e7b16d52de20817af055df5f141207734610a0c6eebedafffd9cc9f069b67f9a1c0454be41d54c138be542e5e38cfe2f293f7d2d3df66977acb366a42c19b3185acfa1b363c6131a4a8111c3b1f4fd7ac406d0e69103ba15b8c4bf29bc2ed9c45cfd1d279d8d931444b2b1849252b8a70eed80fd260edf5a3c01b9690160d2311851d21c9302d985986eaeeb3ae2c07c7c7672094f91db0bd50be377e4d1eb07ee76af49dc136a145a11b172f0811fe73d6259be370c4dfcab6f19e4a64b151d0a6db8050c3de2cc325f5c5f6594cf6248eb081209539e08ca3422984e7bf803de3a419b14423f1e5a54224042ce4f05488a6044f4042bd649b1a08ce10c2006ea76efab4641fef2897efd724e6054a3bd1a69e39a4a5e2d502:5b0083f7a82061c65cf6c75640c81c28e8d6d2e87f6d5795c9aa3bb3e390e91990e82db6f07e614f507a560abaa1eca656c678ddcae8198251e6af0b76b88d0d94e661c25240a89e823d7f5dc0e692eddd1370c35ac44d5a8c8798d0c9aafdf0bbfb549260568dba1c69086bee636be8edccd3cbb27016244d54d7ed2feb7fa64614d45449d7e058e71b306c22e6911c2ac74207bae5a84d0fc247be49d356e5d4353ba5586b6e4b2b97ce9e2377b6eed92c849e676944ae90dc4208e300e19cc91dc26bbdd5a30cfa9281a15efd873066f85af3a26f310623e009804853cc6855903ea64a909897e315e73d312948980ef6289db21a5ebbec8c8efe20d1d53dfaad6d9f4296532e887c37350105a633abc773188751b28c3a08f1b5ee0472de4627e6b61b68278dd51ced6a61ecf38886e45339dc6c60c31e850ef8296ae80f9d31701776eb9af21693f4c52ec062625738d4e3afbf71d1c81fc4846360363ea541a976623a5e4e6b6a67237e9237173f1a1d543302858885714c2a591d0a786282a0285a3711f7bc2b63ca7987e9ae7d02035555cf3b6ad6f71ca98aa928883bf81dd6f86493eaab5637b4dd569d1ee8de6a44bcedb62b9706b1db89e3f05df16310017d89ef3e4bc099b721a5c8d38043d6e4a22cf04009c0fcee6be69937829954941b8b4a1ebf4daea0d774d0782be176c8e591907756c2cf75dea6f7877dd6875b8fe1012f3050cfb1289cf088667e1522eeedc927ac86bfe2c407432b4a813a6a7a5504e999206db1827e25fafd70ced36db3b281b6f7b14ed5baa0572315a939c5bf4abb133d2e7b16d52de20817af055df5f141207734610a0c6eebedafffd9cc9f069b67f9a1c0454be41d54c138be542e5e38cfe2f293f7d2d3df66977acb366a42c19b3185acfa1b363c6131a4a8111c3b1f4fd7ac406d0e69103ba15b8c4bf29bc2ed9c45cfd1d279d8d931444b2b1849252b8a70eed80fd260edf5a3c01b9690160d2311851d21c9302d985986eaeeb3ae2c07c7c7672094f91db0bd50be377e4d1eb07ee76af49dc136a145a11b172f0811fe73d6259be370c4dfcab6f19e4a64b151d0a6db8050c3de2cc325f5c5f6594cf6248eb081209539e08ca3422984e7bf803de3a419b14423f1e5a54224042ce4f05488a6044f4042bd649b1a08ce10c2006ea76efab4641fef2897efd724e6054a3bd1a69e39a4a5e2d502: +6d7855e30f7a13e237b067144346434bb4b05178c7d88d492e79027c4b0f3cdd7273293828efa349822392dbbab07879577e1a77a6fd6afe33753a9eec88c4af:7273293828efa349822392dbbab07879577e1a77a6fd6afe33753a9eec88c4af:f8b936e793b017580cc0e9cbda2acb6474507f4bca3afc8783ec46eeb82ccd4dd2525676aa6ab5c0dcf7d75f7e0311e6fe6bf27263f8578feb55c5612d1f28e888b76656c41ccd8a70b9bc604b42724fa2bc411d44c31ab68ce84f8393399e34d5408579c2ba2921f2f8d11487aa7e52557feed96757199d3aae6377770154b17f3577c7ac3d8c76cf7461b5e8d42a7185078ed4f862fc57502f615075307b6e103c77c1f6c8bda7aa17e435e21b949af44dff5aa30a62da712fa9966a612ffca14871fd6f860b4a9614012c5369910e0ffd6f0fbd889a9c257c32bdcf90bb80627cb272ecd4599897555955e1fe08cd7ebb21c071be0f48989696cb39aa82ad11baa5d4ac613abf1b6db8a20e686836222833f8b6dd2f0006227be48e8580dcc8de620dacb2f65a693675d6cb45ba5dd1aa70db76bc641d4fb567ecbc7111442e294158be575c71ddc26e94f41266a2fd3a0d435781fc094648fadf5f17cd41ab895821894ec0806b262c393534fe66f21e3783c14a96c88f2e0653fe32e75dce8a463bb97eed6c16f3f3228169abb5b4bf9ea3278c1ff0f86eae71389b6433acd097eefa9e6e05f4955cd517830b8d9870ccb5227415e50f23f6473217a745096470dca93d2b34673c5d6a57ed02c8e0cae119b3f329d8ab6498494c2921bb6f496dd08381e7d39f2db5763b14a2821befcca0a9fd312545de68abf206d12d8e02e73bc7e3cb796e7ee26cc63d741efafc5345f8132951bcfbfddf631fb7cb43ef35b9453c9390eb23b1f9d8b1c72debd24f09a01a9dc60ee6815306188357781af6e1820aa35e4ec121b7ca34d7de7611b246a3e703ed48c7eb03a6fe8f852ee7d32545c9d852d64d5d75930e5f1ebe21a307efa7622edaced6d879026f0f85a9112012803705582269d39f143234df8909ab3d948e76d3daaa24226d9ac601eef277fd2cfc4a19aedf4387a21617b03ec3d3845a38554f5e97036e56ec1ce660df9c062c2c993b77c5ba6a6d05231dae3764183c3e96aa539cfb3415fb163c645b2303b2d6d4bda8ca6c72bc03d5305f9b118e925e27d29ab7dcb196470e6339631b2380744c04d1da348fc0fe274277f82f95bdfb0b64b4cf3b51e571c0ddb3b53ca6:0fe28eadd9e5dd574b3faaea810d44522c8b1bfbb3e3d57ed889faedec91d0e14a86b914c4c766f1bf9b8f18b0db890db6c1b125d57804333619b1e0720a3300f8b936e793b017580cc0e9cbda2acb6474507f4bca3afc8783ec46eeb82ccd4dd2525676aa6ab5c0dcf7d75f7e0311e6fe6bf27263f8578feb55c5612d1f28e888b76656c41ccd8a70b9bc604b42724fa2bc411d44c31ab68ce84f8393399e34d5408579c2ba2921f2f8d11487aa7e52557feed96757199d3aae6377770154b17f3577c7ac3d8c76cf7461b5e8d42a7185078ed4f862fc57502f615075307b6e103c77c1f6c8bda7aa17e435e21b949af44dff5aa30a62da712fa9966a612ffca14871fd6f860b4a9614012c5369910e0ffd6f0fbd889a9c257c32bdcf90bb80627cb272ecd4599897555955e1fe08cd7ebb21c071be0f48989696cb39aa82ad11baa5d4ac613abf1b6db8a20e686836222833f8b6dd2f0006227be48e8580dcc8de620dacb2f65a693675d6cb45ba5dd1aa70db76bc641d4fb567ecbc7111442e294158be575c71ddc26e94f41266a2fd3a0d435781fc094648fadf5f17cd41ab895821894ec0806b262c393534fe66f21e3783c14a96c88f2e0653fe32e75dce8a463bb97eed6c16f3f3228169abb5b4bf9ea3278c1ff0f86eae71389b6433acd097eefa9e6e05f4955cd517830b8d9870ccb5227415e50f23f6473217a745096470dca93d2b34673c5d6a57ed02c8e0cae119b3f329d8ab6498494c2921bb6f496dd08381e7d39f2db5763b14a2821befcca0a9fd312545de68abf206d12d8e02e73bc7e3cb796e7ee26cc63d741efafc5345f8132951bcfbfddf631fb7cb43ef35b9453c9390eb23b1f9d8b1c72debd24f09a01a9dc60ee6815306188357781af6e1820aa35e4ec121b7ca34d7de7611b246a3e703ed48c7eb03a6fe8f852ee7d32545c9d852d64d5d75930e5f1ebe21a307efa7622edaced6d879026f0f85a9112012803705582269d39f143234df8909ab3d948e76d3daaa24226d9ac601eef277fd2cfc4a19aedf4387a21617b03ec3d3845a38554f5e97036e56ec1ce660df9c062c2c993b77c5ba6a6d05231dae3764183c3e96aa539cfb3415fb163c645b2303b2d6d4bda8ca6c72bc03d5305f9b118e925e27d29ab7dcb196470e6339631b2380744c04d1da348fc0fe274277f82f95bdfb0b64b4cf3b51e571c0ddb3b53ca6: +7ee4e7e98c6a40f0e74413f24039bd220df1f8c7f015528dbf5284ab9f7c82e24d5a800f9b22070e016ee23af8a310902b369d589a847f345c2ea2968d6d0924:4d5a800f9b22070e016ee23af8a310902b369d589a847f345c2ea2968d6d0924:8fb01373c42e69614aea99af49323785f33861b94e90f565389ebf70e219f5dec732e0010b58f7290530df222ac9c73e1c2e92a5e6061de5590caf9c0d5021d729eaa11541fa1d082160beaf611e7cfdc0ebb315d388e538b4b5028f9b30d3d973347ffd44263eef083b81b21b82eca5756a494b1d81c07de849506d3e3b668797a5c544254d4ebe5cf8171b39f8724cbc4189291b3c53c21ece49a1d739563c65b49025935647a7303ae0ef7f6d24554645a428dbbb42449f5399e36dc787b7d6958a02eebbb836e5e53e26e487239de94d1d250e7943ac0e22d92750a0cf3473be1a6225cbe79545048269f6237ec9f9ec307e8a34b7bb34cd4906e43162a3708f329c5b989d7a7fcde1099a542546fe9c33182ba51b843e96d11c79e91ad21f7170e257fdc2818e12f9168a974c968a4d273fa3ffa9f35ff905980eaad3721cae802bee36210b40b99319bb669982e943b270a4c4d0a92ecb5bba2dd8b40ac3d2f0325c469d5e9d483f5241974010c5c0da335f16e962196c2ef14eb24aafbb311bfd5fa8dc8d2d61e6878ad2cce0dc9939e44522723d427ef32fb43b967f5e44fc665792796f8cf934f01c325d63d583dc3ca9d4fcc757d9178580daef53aa3ab21d2ce435955d1c6d47638c5edb62ff5561693d1cbd10ec9e399a71bf9db1c9969fd59e4eeb31aa59bf39e9f184178def7246ed4b8f4be5badaa5db4af867f4f2ec39a13704202c8784fa168ce96f9cfac71017236275fd857cc3c51a9c7ac256215e14b843f7214dc9f824b91d1a5170d0ef1d37696f93ee966a2b7dece22b4f3afd39c16d601e5ff8408d45c1a6ce71f060976c5be4c042b1b738df9580ba5ae77880a70c0b94f0e1c9f9aa34c090d612d57a9b931f50a125fa35ce40a2cb7faad530f80908c73cb78258afd2631390041d92617e9bf64ce96e8e4ac7f3126d8af8a04c75ffd438769de06f74c2fc20cc8192da353e79061283bba08a8d24e6e4e2e83ba5b08e4275226062148d8a02afad65b6f627cfbd29b71ca18aee5b1f97169bf0228b376f4106b50fd91a38a66211d69ebb4a7af0e1c2217f1ba014d1e0cd17508d58155d163dd9de2fe1c64c7f88d5b553e9ba1e1f25430d7e125b07a8c2ed:ac3bfe3adf941c934d3349c492de70d5166be389f955be87c2883f41f2da146c910651a3b452c2d739dc9b531c5745565e69d98359f1d7d93ebd36d70abbf00d8fb01373c42e69614aea99af49323785f33861b94e90f565389ebf70e219f5dec732e0010b58f7290530df222ac9c73e1c2e92a5e6061de5590caf9c0d5021d729eaa11541fa1d082160beaf611e7cfdc0ebb315d388e538b4b5028f9b30d3d973347ffd44263eef083b81b21b82eca5756a494b1d81c07de849506d3e3b668797a5c544254d4ebe5cf8171b39f8724cbc4189291b3c53c21ece49a1d739563c65b49025935647a7303ae0ef7f6d24554645a428dbbb42449f5399e36dc787b7d6958a02eebbb836e5e53e26e487239de94d1d250e7943ac0e22d92750a0cf3473be1a6225cbe79545048269f6237ec9f9ec307e8a34b7bb34cd4906e43162a3708f329c5b989d7a7fcde1099a542546fe9c33182ba51b843e96d11c79e91ad21f7170e257fdc2818e12f9168a974c968a4d273fa3ffa9f35ff905980eaad3721cae802bee36210b40b99319bb669982e943b270a4c4d0a92ecb5bba2dd8b40ac3d2f0325c469d5e9d483f5241974010c5c0da335f16e962196c2ef14eb24aafbb311bfd5fa8dc8d2d61e6878ad2cce0dc9939e44522723d427ef32fb43b967f5e44fc665792796f8cf934f01c325d63d583dc3ca9d4fcc757d9178580daef53aa3ab21d2ce435955d1c6d47638c5edb62ff5561693d1cbd10ec9e399a71bf9db1c9969fd59e4eeb31aa59bf39e9f184178def7246ed4b8f4be5badaa5db4af867f4f2ec39a13704202c8784fa168ce96f9cfac71017236275fd857cc3c51a9c7ac256215e14b843f7214dc9f824b91d1a5170d0ef1d37696f93ee966a2b7dece22b4f3afd39c16d601e5ff8408d45c1a6ce71f060976c5be4c042b1b738df9580ba5ae77880a70c0b94f0e1c9f9aa34c090d612d57a9b931f50a125fa35ce40a2cb7faad530f80908c73cb78258afd2631390041d92617e9bf64ce96e8e4ac7f3126d8af8a04c75ffd438769de06f74c2fc20cc8192da353e79061283bba08a8d24e6e4e2e83ba5b08e4275226062148d8a02afad65b6f627cfbd29b71ca18aee5b1f97169bf0228b376f4106b50fd91a38a66211d69ebb4a7af0e1c2217f1ba014d1e0cd17508d58155d163dd9de2fe1c64c7f88d5b553e9ba1e1f25430d7e125b07a8c2ed: +1f28d9091d196cba3d4552e5a337a4d8af3f295e629e4ba6fe99703120ae41e0814d34bf28ee6d90f039599041db810f7c9daa918e03e96197414bc9aa31ecdc:814d34bf28ee6d90f039599041db810f7c9daa918e03e96197414bc9aa31ecdc:a69468bc33ebfef0615c643c49dac6e04fdb6cfb8ec45857bbb7a27e528fd631fc3411baee65cc1f94fcc94aed4a4332fa6861e065e06163541709d79728e01be2b140a022c83e7b23b9ed2ad2832169dfc95690913cf3720130657080c9d5a7827e5660757452c5fc3dcd80cc6be098c629226d5466e02b97126be74a1452ee16815095deb42bf06566715028c11825820a8a23c60da2b68dd9a55dad2a29a4964443817c07d776b244b15186819a3bbed414abf4579a3ece3a3dc7b105d0a9dba37b9eaa78be8e46e1698b59b0940b01f38b283c33a9a4b1d4f8144b16eeb5fc0a7af0d081696645a1eab3a787cbcf88fad93dd6cd46d295a879a1775033a98563822ef1f6b69a581e49736c8d701b4453969340521e4ad4bf94b911b0e2d86f34eece4a6385ff1fe63220cd3cc592f36d6c491fa18f7c1404360d2a7753fe073e09a2fc42a4bbea55bc96d7f05c98aed2cc4a9fae8fd4a0197ff01fa7f0046e3c3eb59aaabca313a4ddaa5d20d27c2c5f1ac6d87fd3cb4bd35a1ec75d104f7c367331a3e295e53c4e80bae14b9792d0d526f740d4ff036faf5487967ffabe8e883d3fb0d16faadb28e1285ded41570c0b07c2559b531e0f9254ef88e5b10f64f4839a9a0b6c3c7f1b7850f4ad9bf0999a7f2ae7c45a658ea53036fc70199842b8e49e60f967de1ff3abfff6cd735b7cd8b8f9e248f156f6c6543869eb99823daea88debaf79f01e6521ec63fe72724ee3c822b88b3968b24852091583c49ab3c15fa1f79b18d98f04d9b6841c9a7ca0de2fcc02f95dd649492e8b56a31ec1e244337af6aaaede8bf99fc814ef57c0d5e08c3c7ecc1897980aa169a9926d20698df6930e2110cb460f49390100741095f8ed00412ae696d98efefd290da5f7d0b728d20a1ebfa6bd7d270f281a98c7b1e408435125aa483c6b7d633ff7588a941658f6129544d62945b9b8af71a8c62c0a50076cb8541ba7e4bde4ede441722c6eb9df8cfd0656339e86d226abaea05ea047f6b8307701f6c9a44cc9cb837b8eb62445925e8a8881d2538fcb2b249e4ee8b686ecfb49c4df86401d249aac35841e914004f9455d3fde375d20a01fba27b197a698d384c76505106801627e8336bd2d76d761a8:5be552fa731e836793f6dda895dc9b1e2ccd669de1c843e00ea6fa3c5ebf97a34b26f1f3ac7ff2225ee4a7e430072c13da4066dcdcc05ba2b5f61a6e8d210709a69468bc33ebfef0615c643c49dac6e04fdb6cfb8ec45857bbb7a27e528fd631fc3411baee65cc1f94fcc94aed4a4332fa6861e065e06163541709d79728e01be2b140a022c83e7b23b9ed2ad2832169dfc95690913cf3720130657080c9d5a7827e5660757452c5fc3dcd80cc6be098c629226d5466e02b97126be74a1452ee16815095deb42bf06566715028c11825820a8a23c60da2b68dd9a55dad2a29a4964443817c07d776b244b15186819a3bbed414abf4579a3ece3a3dc7b105d0a9dba37b9eaa78be8e46e1698b59b0940b01f38b283c33a9a4b1d4f8144b16eeb5fc0a7af0d081696645a1eab3a787cbcf88fad93dd6cd46d295a879a1775033a98563822ef1f6b69a581e49736c8d701b4453969340521e4ad4bf94b911b0e2d86f34eece4a6385ff1fe63220cd3cc592f36d6c491fa18f7c1404360d2a7753fe073e09a2fc42a4bbea55bc96d7f05c98aed2cc4a9fae8fd4a0197ff01fa7f0046e3c3eb59aaabca313a4ddaa5d20d27c2c5f1ac6d87fd3cb4bd35a1ec75d104f7c367331a3e295e53c4e80bae14b9792d0d526f740d4ff036faf5487967ffabe8e883d3fb0d16faadb28e1285ded41570c0b07c2559b531e0f9254ef88e5b10f64f4839a9a0b6c3c7f1b7850f4ad9bf0999a7f2ae7c45a658ea53036fc70199842b8e49e60f967de1ff3abfff6cd735b7cd8b8f9e248f156f6c6543869eb99823daea88debaf79f01e6521ec63fe72724ee3c822b88b3968b24852091583c49ab3c15fa1f79b18d98f04d9b6841c9a7ca0de2fcc02f95dd649492e8b56a31ec1e244337af6aaaede8bf99fc814ef57c0d5e08c3c7ecc1897980aa169a9926d20698df6930e2110cb460f49390100741095f8ed00412ae696d98efefd290da5f7d0b728d20a1ebfa6bd7d270f281a98c7b1e408435125aa483c6b7d633ff7588a941658f6129544d62945b9b8af71a8c62c0a50076cb8541ba7e4bde4ede441722c6eb9df8cfd0656339e86d226abaea05ea047f6b8307701f6c9a44cc9cb837b8eb62445925e8a8881d2538fcb2b249e4ee8b686ecfb49c4df86401d249aac35841e914004f9455d3fde375d20a01fba27b197a698d384c76505106801627e8336bd2d76d761a8: +c64dd20d42627526198a22647690c895b5b45b698f57a69dfbe48dbd426aa4702e01d40416f78acddb34b8445ea4fd0ab3fa9e6643044752213f07c7f0ff43a0:2e01d40416f78acddb34b8445ea4fd0ab3fa9e6643044752213f07c7f0ff43a0:821b9f7c16104b533bd127184fd72ade092b13bbd9aceed29b8d10f16688922d165f8931d53df590fb713b674d805ce0c9d6ce6c43ba6968191d12bfa08a8ce22e8f336b2b491af25d1b1606f930caebe522392a87d42ce7bc167aa7b610597220af31a665353071e8d9e5f42078b9c388bf040258e21f9c3ab38c0427618b2c28d3430df27921bfc58487b3461978bfa8bf586cfe8358e092f8f47466e762451d50164a0d74360f66b4cd3a3575da01da23752430c035da859f577de22290aab4ed7f34d267406ab547eb445cc64df53019427f4eb72bca55397153d01ccf7ec97d7a967d9aff46231d2e2027b38f3b41bd2cb1b798a4ae88abf4896216d315bd5383024259e59742802a911badcf8473db91af319733320cb9521ef9ce437267b6ea17bcafe5d0903b123a35c988f49834f61dd552640a3276da26af17ec21a20296586dd6f4b36c7a4f0b899d70b42af89e29370132edfb72d6834194a1609360b1f1feab89b96b8e8f0f68987c57cce0bab768113718fb1709de2df32177d44085da5efd9da70e1a858c92f245acfee64b71f3eb16e04fc13989e69337999701dd73abc266c9fd4cff91a0fd04fbd8b13b12e6f450385715848e007fa0d463119fd7de6325b640042b654212e0db8da1adebd2a7589f77ee4f752d282ca1119c431b17ad0a021ef2bf95e5ac4704e62d7039d0e651e456d60e63bade401cca77c9a89163174d5022d745abdc76b9ffe2544155235e3063e6e4aeec44ed5d8ab408d966fec12016c130730bbc558732065da800a70cbfb0fccca45d0028cbfd9632ddb2f0ed12edae7b930b106c9d1285a4b870de7507999c74793dd497408719c898abe49f7f33a33e69b50fa5af9480068566d1fddf4482d79704ad8ef11b88b42cc69fce8a557b5ba510e708b9375123038568270de407232e95621e2d04570bec2c41eccfd855b21f0c9bbaa23b5c5815fc888f7fbed482c320ffa1e063e87b55bc8f7eeea374063a9be65f7ed9225bf6ca34cfa311b79f3a258c252e6345ed6ac84748f46807a55d4ba41266169cd262d4f72279ef0caa77ff44933532bd1374756c23ec85f55efe9fc2331f26f881629f80c2692f7f53e4bc6f22efb45457a223f0d1c4:deacc8c23218727676d540a23bdad7810211e6d57ad294c37d4b1c9af6b337a53f7880d2bafa73b30508c008426bf8d7c965a1f4a422a1bc7d6ad6226fd19706821b9f7c16104b533bd127184fd72ade092b13bbd9aceed29b8d10f16688922d165f8931d53df590fb713b674d805ce0c9d6ce6c43ba6968191d12bfa08a8ce22e8f336b2b491af25d1b1606f930caebe522392a87d42ce7bc167aa7b610597220af31a665353071e8d9e5f42078b9c388bf040258e21f9c3ab38c0427618b2c28d3430df27921bfc58487b3461978bfa8bf586cfe8358e092f8f47466e762451d50164a0d74360f66b4cd3a3575da01da23752430c035da859f577de22290aab4ed7f34d267406ab547eb445cc64df53019427f4eb72bca55397153d01ccf7ec97d7a967d9aff46231d2e2027b38f3b41bd2cb1b798a4ae88abf4896216d315bd5383024259e59742802a911badcf8473db91af319733320cb9521ef9ce437267b6ea17bcafe5d0903b123a35c988f49834f61dd552640a3276da26af17ec21a20296586dd6f4b36c7a4f0b899d70b42af89e29370132edfb72d6834194a1609360b1f1feab89b96b8e8f0f68987c57cce0bab768113718fb1709de2df32177d44085da5efd9da70e1a858c92f245acfee64b71f3eb16e04fc13989e69337999701dd73abc266c9fd4cff91a0fd04fbd8b13b12e6f450385715848e007fa0d463119fd7de6325b640042b654212e0db8da1adebd2a7589f77ee4f752d282ca1119c431b17ad0a021ef2bf95e5ac4704e62d7039d0e651e456d60e63bade401cca77c9a89163174d5022d745abdc76b9ffe2544155235e3063e6e4aeec44ed5d8ab408d966fec12016c130730bbc558732065da800a70cbfb0fccca45d0028cbfd9632ddb2f0ed12edae7b930b106c9d1285a4b870de7507999c74793dd497408719c898abe49f7f33a33e69b50fa5af9480068566d1fddf4482d79704ad8ef11b88b42cc69fce8a557b5ba510e708b9375123038568270de407232e95621e2d04570bec2c41eccfd855b21f0c9bbaa23b5c5815fc888f7fbed482c320ffa1e063e87b55bc8f7eeea374063a9be65f7ed9225bf6ca34cfa311b79f3a258c252e6345ed6ac84748f46807a55d4ba41266169cd262d4f72279ef0caa77ff44933532bd1374756c23ec85f55efe9fc2331f26f881629f80c2692f7f53e4bc6f22efb45457a223f0d1c4: +0f8e9f3526b4faea9276f22a1779e6f82709808f6d0c612adfe32a6e8a061005d48c3f0fdef382d1d80313e846fca95e418176bb5dfa9d398c1d2124776f690a:d48c3f0fdef382d1d80313e846fca95e418176bb5dfa9d398c1d2124776f690a:0ccd37c4cfd8e70ca3bb3946d09d70d0f6a4b81d6dfb079d7873748071589880927382f7436a6ef8f51c255473dd01feb52c8edbe4d3255713e68d640f3dcf158f2bfb9fbecf71f0719dfe8ce6b601281ba6c20a56b4f8e7caa4aa9f868fbfc5e4321c22d65f0382c4896bf9bebe3546949e8185a4d817e45b5d1293953821bdd98ec259f64a3de53865b149ea01c8f683ecda61da5dc10e7ebdddfe7484f5eb1031b7916587caa399a06b6fea4c5e6e0be650fbdf06c1036df2cc35f62ea0ea713f52809d77f47c2e55c92392481680b6332056226913b0ce88a6c55a26bdb5b8bab3cf4695a8c522302c4eba37d31ff77e58301bccfc7c7be8580c6342687995f44acd190965ae0d7bf0669592b6ad88743ebb360c73e0484a23d2f9e99e9eb038dcbd87ca9b1a498f1b2d35fedd7f8e1f7fd8ca526486911e076aeab4877bbacf378a2855f9c5ac039130dc690e177d67b244cc8ad032379ef71fe05e9c8613d8f5d6ea3d4e3e47222029cc004253be47f87fb5e3314c4898134b87acf10b2538bad897bdc5012d8f9762c871b653d400fee0ceed5ef6bdd16faf3f0abdbd72cd0a12940546f0995ff14b0f1bd54856ff74c36eb4f22d7287aefdc609998c1f41bcc3bb3a5fa49234f4fa8e929cd0f554b315395dae873c61ca70e0410c2fd5a115d2a6ff1f1c94b27ba450b8194b21f095c61a5f215e3c84f5d43f0e736286d33b8c47814db979f9dc00919846bee685337d99555a24472e6b00b3f4a14311a6c7c904ba5889da6c1ddcc1117580f5fbc41f2b8a4268cf0e9fa5bf412534c9e4052aacb504cb86e2147ab8023d58800b763f9abf9d0440788a51dfe5cbd44230ba5228f1f5960ea3a4e4044d36daf811cbdbec5d696463d8e941f27217563bb44a2118a4f5acd6e794de17e028cbdeefdef2cbf03dd32e7899e65a1cf839f5d90e1f8c364b577fe3105353f66768dbf7af0c521aa8a49f7a22082d88f901498c90b9d7777ed2f9f0e8a552d8a1fa5e9632ed853258c9c215b6dbb4111dcfca554bfbc9bba22f88bc55552c6d862556d741dad59f215e37288346ca7d7fd8c65a380d720caff9efa149f3fda232daa5b12ef11c0af0862bd0229e075a3c6b60ef0bbb3dad7f2908:2f59a2936073913834eb15a0e0bcb9aa804089468f24dd1b2d37a1934ae9ba1020ff64b72eec03268d0a7c012c4e796300f6df7adda01c8bc5e9015ccdee1a000ccd37c4cfd8e70ca3bb3946d09d70d0f6a4b81d6dfb079d7873748071589880927382f7436a6ef8f51c255473dd01feb52c8edbe4d3255713e68d640f3dcf158f2bfb9fbecf71f0719dfe8ce6b601281ba6c20a56b4f8e7caa4aa9f868fbfc5e4321c22d65f0382c4896bf9bebe3546949e8185a4d817e45b5d1293953821bdd98ec259f64a3de53865b149ea01c8f683ecda61da5dc10e7ebdddfe7484f5eb1031b7916587caa399a06b6fea4c5e6e0be650fbdf06c1036df2cc35f62ea0ea713f52809d77f47c2e55c92392481680b6332056226913b0ce88a6c55a26bdb5b8bab3cf4695a8c522302c4eba37d31ff77e58301bccfc7c7be8580c6342687995f44acd190965ae0d7bf0669592b6ad88743ebb360c73e0484a23d2f9e99e9eb038dcbd87ca9b1a498f1b2d35fedd7f8e1f7fd8ca526486911e076aeab4877bbacf378a2855f9c5ac039130dc690e177d67b244cc8ad032379ef71fe05e9c8613d8f5d6ea3d4e3e47222029cc004253be47f87fb5e3314c4898134b87acf10b2538bad897bdc5012d8f9762c871b653d400fee0ceed5ef6bdd16faf3f0abdbd72cd0a12940546f0995ff14b0f1bd54856ff74c36eb4f22d7287aefdc609998c1f41bcc3bb3a5fa49234f4fa8e929cd0f554b315395dae873c61ca70e0410c2fd5a115d2a6ff1f1c94b27ba450b8194b21f095c61a5f215e3c84f5d43f0e736286d33b8c47814db979f9dc00919846bee685337d99555a24472e6b00b3f4a14311a6c7c904ba5889da6c1ddcc1117580f5fbc41f2b8a4268cf0e9fa5bf412534c9e4052aacb504cb86e2147ab8023d58800b763f9abf9d0440788a51dfe5cbd44230ba5228f1f5960ea3a4e4044d36daf811cbdbec5d696463d8e941f27217563bb44a2118a4f5acd6e794de17e028cbdeefdef2cbf03dd32e7899e65a1cf839f5d90e1f8c364b577fe3105353f66768dbf7af0c521aa8a49f7a22082d88f901498c90b9d7777ed2f9f0e8a552d8a1fa5e9632ed853258c9c215b6dbb4111dcfca554bfbc9bba22f88bc55552c6d862556d741dad59f215e37288346ca7d7fd8c65a380d720caff9efa149f3fda232daa5b12ef11c0af0862bd0229e075a3c6b60ef0bbb3dad7f2908: +fe7cdc7966d0ffb9c76f4a18e7f0bf90690eb76dc3d3d50884648e2e3937d020a12ee9812d6af6aa4879fa72bc0a69804ea1a85f9bc4a26a5ba7cfbb914d0dd9:a12ee9812d6af6aa4879fa72bc0a69804ea1a85f9bc4a26a5ba7cfbb914d0dd9:dcb91cf155461a60df07eec29d98616ed1728b34efa9e1f7445a9158a8f88d7faaae0e24725aeff263c3f74f0c684f1858f05b6995d2846b6a832f67085a4276d8661aebd3bfcc73181f1f510293b6de5e4bb23ff2dca1df608cb14ae522ac4b51e1f9b973ab8bafcd534e71c57181b11896ee1061fb369ca4d2939d1e57060d9f4db0a5c0b07d52687f157817e63e2fe7ebcc3e7c95efe05b859910c95eede86d14399e616248a28c24c414dbb693af9be435a3a9cdc33e0e2a586918d91b8a85cedd1612d7c1a21792bdd43a915b157e04bb3a44ecbe23fa49cc55daabbeaa155a737f765b8ddb0f3b15d4ecf2cef7054ca73ec87d91752c2e99195cdb1958844f144edab82a97549fc9cec08e8711cff863b63fc231a77f762e5cd9da9d59409252e99ab04c42bc57097e464e3c6a48d80241e6325e3e4094989b34c0e8b32b1a7829d54df32a050ee87d8f7c4fe3e4f4f7049d1feecdbea67108350db4e8edbe3c3ff8ab2a25d147b1c1c5821b0f8c21042d655db831691f59983f27d2ed1d4906c544e24e79be68653c9b229a7fb61ef545bab16e9881cb4d9265e293590a0bc2dc86bad23007ff40c95861923b498241c10d26bf4848f62ba7383f649dc38af1840d0de928a9bfee5e11b51434163a7ab1ed537415f1e93285e3699205720158f9557d8641ed2bf485b8212c8f82668bac3c228e6924c17d0d98f2e6d9234371c4425eb758689fdb0dc1cea1394a2862e87bb38e624c34799168613278225fb5e19c9247ada35554f2c4addbb61d5a502a708127d6efbca8f735090bdfdd88db29fbd14b69ab1262f0c3e26d263a59c5ae4639065383d5250b54cf592bb7adfeaae0d2fe816b6381e86ea2d1c71813cbc3d8fe2d31de7b30fb6ec2294fe4536a36c6a1835a7162ab4bf89d19466119657b0e4645aef503505b4d55df977bd2c90c64406f4970d5cff245b835322a6fbe234e5efbb5ea45e8f0d3973be4aaa2aadaab077d6c9b25bd4494409e93479d2d1507f66bc8bef82999a13c7943b472b9e61ec29debefbf2241423e0faa42c1a338a7a6131ded935ba03a28662e68593368dde54b462f2a5fb746185ff5503e69ba36bf16f71458cdd057e5c17267f67498d652860b465e:b52d03fdebcd429737ef70920687211fbb4c04f81e355cec7072c5054175d2ed77f38f466f001422da8fcdf067db1451007cab607f049c2e2607b57d44713c04dcb91cf155461a60df07eec29d98616ed1728b34efa9e1f7445a9158a8f88d7faaae0e24725aeff263c3f74f0c684f1858f05b6995d2846b6a832f67085a4276d8661aebd3bfcc73181f1f510293b6de5e4bb23ff2dca1df608cb14ae522ac4b51e1f9b973ab8bafcd534e71c57181b11896ee1061fb369ca4d2939d1e57060d9f4db0a5c0b07d52687f157817e63e2fe7ebcc3e7c95efe05b859910c95eede86d14399e616248a28c24c414dbb693af9be435a3a9cdc33e0e2a586918d91b8a85cedd1612d7c1a21792bdd43a915b157e04bb3a44ecbe23fa49cc55daabbeaa155a737f765b8ddb0f3b15d4ecf2cef7054ca73ec87d91752c2e99195cdb1958844f144edab82a97549fc9cec08e8711cff863b63fc231a77f762e5cd9da9d59409252e99ab04c42bc57097e464e3c6a48d80241e6325e3e4094989b34c0e8b32b1a7829d54df32a050ee87d8f7c4fe3e4f4f7049d1feecdbea67108350db4e8edbe3c3ff8ab2a25d147b1c1c5821b0f8c21042d655db831691f59983f27d2ed1d4906c544e24e79be68653c9b229a7fb61ef545bab16e9881cb4d9265e293590a0bc2dc86bad23007ff40c95861923b498241c10d26bf4848f62ba7383f649dc38af1840d0de928a9bfee5e11b51434163a7ab1ed537415f1e93285e3699205720158f9557d8641ed2bf485b8212c8f82668bac3c228e6924c17d0d98f2e6d9234371c4425eb758689fdb0dc1cea1394a2862e87bb38e624c34799168613278225fb5e19c9247ada35554f2c4addbb61d5a502a708127d6efbca8f735090bdfdd88db29fbd14b69ab1262f0c3e26d263a59c5ae4639065383d5250b54cf592bb7adfeaae0d2fe816b6381e86ea2d1c71813cbc3d8fe2d31de7b30fb6ec2294fe4536a36c6a1835a7162ab4bf89d19466119657b0e4645aef503505b4d55df977bd2c90c64406f4970d5cff245b835322a6fbe234e5efbb5ea45e8f0d3973be4aaa2aadaab077d6c9b25bd4494409e93479d2d1507f66bc8bef82999a13c7943b472b9e61ec29debefbf2241423e0faa42c1a338a7a6131ded935ba03a28662e68593368dde54b462f2a5fb746185ff5503e69ba36bf16f71458cdd057e5c17267f67498d652860b465e: +f6c9ab5ea75f294e8e0c07c4c09ed8eea3113bdfc2ef759e20a264571604108db12ff55bd3ec42610eacea28b313a16e19c9e8b47c2b15170991be088d65cf63:b12ff55bd3ec42610eacea28b313a16e19c9e8b47c2b15170991be088d65cf63:71623b39743e39c7e08638806d468a1a8a6f35c2ae388eefc27374bb52538814c4b36c9b8e389ad83183de02a1bbd0325734e4618754092337d3e7dc1256928e3528870ca7f00613a25b71bb15d1d9eaaff9f2269b71c19769e003ce845614b2ec95ed28ca855b5221d4cb80a6ca9466aa33e2510ddff7dce186159da70fc8b1fbac12a26e1fc0942276892ad6e9b003f56959bd313af289e7a0532a664b76b96b919854e0650cb8c52ec4c5fb5053af2f0cf8c0f22a523f9e2c6419df8d0b714ee3776800ebfa70776084667d6dcf541f14cf166262e0f64c4276ae28885e6cfd097b70c0d6186ea5dbd033323c987613da08645de07208bae12a178d8f7f650a25afbd701c85a1ba639ef9f121c40c5c129a4737343386a48183ff3c591389d89ecda526cffb2674f17bb1c23090554b1340849796a6d444460bb419427e93e6585b0f4f065ad87ee6edf54be6188a1dd5ace1364defa561f74e26769c9b291ee7555276501c6a49080da0924f3792c2a728a52007b1c07c95578fedaf403996239e9c55a9a44c3dfcc37cdf03fb485db5a08dff15a7a4f7b7f154742e8431564dc17dbd432e10337c2276fcfd9d70f7c3d570393a0c19f64051c73a870e205584106531d1fd2a1dd1c9d0fce14ffaaa077bb7e260251eed6c62bc6edc2422519440c2244eba384046b0eddaa6cf2c1c7eeebfcd78fcae18b82290552b59c0463dc450618ba67c770dec0e229b8460936ca819562bcb36969c8ff70bf113c11671e00b941355bf01ad54b05cfe2a048b38728cbdd1b49809e1f207aca3098d9942eec47d6c9d413b37c914fedd38acd5ffe496cac757c2ef8b77bd8403d14b1fc98a903fe2b979468233a7f2aed6f8d509d874e1dce05149af9df3fe4595c71e8bc463dee9384d5e0505d2a6b0a2b8a1ed6216aaae9dcc7602487a4c0851fdf09629c1e99118809a9544a6577af9f915d1e65d816220c48c8490fa9b70da422ad6800223d6d8c340f9eab2cc7e149362124a300b40cbb8c0a65da301dbba931ba564f35973ca8bf2d1edb56c194661955b3b68381fa15d4b8dc6ada1a5cebda3a4ccc55123e0057f4f821041937dd549209c82e116570bc908a28e3299a9441443498f74b3cc88e1a62d:a7f9d08ba14183ef247f2c25fecc2b83eda6de58022e466ce78fcf50f71ce26162446562eea45d63a21c3b22561fd4680058acb825407a15408f271361a1460f71623b39743e39c7e08638806d468a1a8a6f35c2ae388eefc27374bb52538814c4b36c9b8e389ad83183de02a1bbd0325734e4618754092337d3e7dc1256928e3528870ca7f00613a25b71bb15d1d9eaaff9f2269b71c19769e003ce845614b2ec95ed28ca855b5221d4cb80a6ca9466aa33e2510ddff7dce186159da70fc8b1fbac12a26e1fc0942276892ad6e9b003f56959bd313af289e7a0532a664b76b96b919854e0650cb8c52ec4c5fb5053af2f0cf8c0f22a523f9e2c6419df8d0b714ee3776800ebfa70776084667d6dcf541f14cf166262e0f64c4276ae28885e6cfd097b70c0d6186ea5dbd033323c987613da08645de07208bae12a178d8f7f650a25afbd701c85a1ba639ef9f121c40c5c129a4737343386a48183ff3c591389d89ecda526cffb2674f17bb1c23090554b1340849796a6d444460bb419427e93e6585b0f4f065ad87ee6edf54be6188a1dd5ace1364defa561f74e26769c9b291ee7555276501c6a49080da0924f3792c2a728a52007b1c07c95578fedaf403996239e9c55a9a44c3dfcc37cdf03fb485db5a08dff15a7a4f7b7f154742e8431564dc17dbd432e10337c2276fcfd9d70f7c3d570393a0c19f64051c73a870e205584106531d1fd2a1dd1c9d0fce14ffaaa077bb7e260251eed6c62bc6edc2422519440c2244eba384046b0eddaa6cf2c1c7eeebfcd78fcae18b82290552b59c0463dc450618ba67c770dec0e229b8460936ca819562bcb36969c8ff70bf113c11671e00b941355bf01ad54b05cfe2a048b38728cbdd1b49809e1f207aca3098d9942eec47d6c9d413b37c914fedd38acd5ffe496cac757c2ef8b77bd8403d14b1fc98a903fe2b979468233a7f2aed6f8d509d874e1dce05149af9df3fe4595c71e8bc463dee9384d5e0505d2a6b0a2b8a1ed6216aaae9dcc7602487a4c0851fdf09629c1e99118809a9544a6577af9f915d1e65d816220c48c8490fa9b70da422ad6800223d6d8c340f9eab2cc7e149362124a300b40cbb8c0a65da301dbba931ba564f35973ca8bf2d1edb56c194661955b3b68381fa15d4b8dc6ada1a5cebda3a4ccc55123e0057f4f821041937dd549209c82e116570bc908a28e3299a9441443498f74b3cc88e1a62d: +43103df01a48a03c57f32f52d70c6849ee44580b2ab4ee72d548d848134f7ceba3cbe0d64b0560bcb5ae009001e314d9ec907901dd74a804a0059022ed9c6d04:a3cbe0d64b0560bcb5ae009001e314d9ec907901dd74a804a0059022ed9c6d04:738cbf06d00d4dcd5e5f243a1c18dd5ec20278884695a1cf3bea67bb5b05dd7e60a2a24fd325be6bf46b462873ec907f9de88dc2c762620b7e0ef72765d4bda662454993c828a1746e9ed8d19dff43c4c48527ac845f2186a4ad7c1d992a16245cd573073e0940dceed368110bb5fd0a4c8834ce88a77125b9147393c8b58cb16e5ebdc18244ebfa48baba46973fdcd485b1b2e5f3b0e70992cf1999580638d87f1f5b27c4d7f91decf37de2e734e3195535c631082b3ebaa8ce30a9c2c2db016d7d3547e621618850e22040038d0fe0faea2f9bf510b682c4fd14750e89b4c199ef0c990500543eeeab5f0b507a313199c2a2a0262d6d814cbc0933c592e256c3e29d524b066ea5a4543361a10450e0aa675c61408f307f26ee58969d63278f135b7dcb666b93f2cacfd83873471e974a286b09023f5015fa1aaf18bfbfa5f74385d0df6b9add516ffc0c3113e37e097838646ac93054ff4d9602066744ba3396953fd78168130170bb275c152bdd366f73065c0a7ad7ad00758cb99a7ac1b7809d26dfaac758468201eeb60dea368c33f257afe2f1b4c02e37bafe40f5d7fd40c87d1c56a0cb28e9d28369a3924bcef8b6d999dcf4294dd8c4143d75c6c25b5a4544488dde725248c78d93c15b815b01cbd0f31d1b00ac04837ef85b4003fc96d4457ac5a023623e67b66da4700a0859f83fdccd3c7aae09de09a057e00db44a2a6aacaa21746a49b8224689a5cc1854ba3dc4aa2aa34524e7a5a89d11eea356aaea5ef5fbf542c99f544db940f5086838ee2ab218b8d3f2e107d0b29d4b04830eed79c0768e02c2844b3cba326895f4ab38a3994b83ab30600ff511ccb595992f8cc0d2954807972da365b06fbdab539b2e03598b34e53cfcf93990b97aac1d329783366d451f972b8d8a00b6b8ecdb37279644cec1447c0998ee4f7090f34c9cc8530590cae765360aadb0ab3135004941c92302cbb2b350a14e8f30af5325c2b438005e3a9d4585e63265c327ba725754b33256917fb965ae9f02ed2126b481473dc0e931c2522bf00fe6a2ec95c792247b1e03396112f783070e2fe6c2cb982250d13f2d5460c744fde45323e631cccb540cd725f2c55a7058f230e82b79f366afcbb025b492554395:195447beb1de4a7e36ea89a6ce3c99bcc89411df5e0b15f7ba0b1d110c456abc6b3f5f1da6106ed887864ba56aab466a8a63b335cfcf4c64d65c0e6fb480b401738cbf06d00d4dcd5e5f243a1c18dd5ec20278884695a1cf3bea67bb5b05dd7e60a2a24fd325be6bf46b462873ec907f9de88dc2c762620b7e0ef72765d4bda662454993c828a1746e9ed8d19dff43c4c48527ac845f2186a4ad7c1d992a16245cd573073e0940dceed368110bb5fd0a4c8834ce88a77125b9147393c8b58cb16e5ebdc18244ebfa48baba46973fdcd485b1b2e5f3b0e70992cf1999580638d87f1f5b27c4d7f91decf37de2e734e3195535c631082b3ebaa8ce30a9c2c2db016d7d3547e621618850e22040038d0fe0faea2f9bf510b682c4fd14750e89b4c199ef0c990500543eeeab5f0b507a313199c2a2a0262d6d814cbc0933c592e256c3e29d524b066ea5a4543361a10450e0aa675c61408f307f26ee58969d63278f135b7dcb666b93f2cacfd83873471e974a286b09023f5015fa1aaf18bfbfa5f74385d0df6b9add516ffc0c3113e37e097838646ac93054ff4d9602066744ba3396953fd78168130170bb275c152bdd366f73065c0a7ad7ad00758cb99a7ac1b7809d26dfaac758468201eeb60dea368c33f257afe2f1b4c02e37bafe40f5d7fd40c87d1c56a0cb28e9d28369a3924bcef8b6d999dcf4294dd8c4143d75c6c25b5a4544488dde725248c78d93c15b815b01cbd0f31d1b00ac04837ef85b4003fc96d4457ac5a023623e67b66da4700a0859f83fdccd3c7aae09de09a057e00db44a2a6aacaa21746a49b8224689a5cc1854ba3dc4aa2aa34524e7a5a89d11eea356aaea5ef5fbf542c99f544db940f5086838ee2ab218b8d3f2e107d0b29d4b04830eed79c0768e02c2844b3cba326895f4ab38a3994b83ab30600ff511ccb595992f8cc0d2954807972da365b06fbdab539b2e03598b34e53cfcf93990b97aac1d329783366d451f972b8d8a00b6b8ecdb37279644cec1447c0998ee4f7090f34c9cc8530590cae765360aadb0ab3135004941c92302cbb2b350a14e8f30af5325c2b438005e3a9d4585e63265c327ba725754b33256917fb965ae9f02ed2126b481473dc0e931c2522bf00fe6a2ec95c792247b1e03396112f783070e2fe6c2cb982250d13f2d5460c744fde45323e631cccb540cd725f2c55a7058f230e82b79f366afcbb025b492554395: +f9139e579fa96ebd6287db3babcda60f92e73153566f924cb5de04de4493481ec06ce335533af8d8f337f2b38e0aafa2ce9b27223cd9ddc5ef32027f04889b7f:c06ce335533af8d8f337f2b38e0aafa2ce9b27223cd9ddc5ef32027f04889b7f:b330764ddc628e4ad67aa4982ae86d4581071c193ec3c58f813d7921b84d2a54562bd87417ae1de590a1a48c4ec7d556ad931d65c0543fdf0607c749859ee12f9952020c195cf8746095e1087cc6c3c8ef9d24052560ce813d6139b7a75c8f4b8ea30a9c4ab888d0a6341c99abd35e0903bfe56c93152340c41276d7f24e0912b12a4db3d7ee4484dfa53afc0b1aea1409d1e0328aa1c8604127ca2eb1a5e81bf31f8c7a51c6052c534efe6b3d0ee74ff5a9b11c6157e36477efa9382f5751be8c8c6454c446d6f8dc7e929525cc3de78cb1ba4aba9bd4be152610437582c965eea48cbd4caa6f308f85f4f8d006a042f619200762e1bb9ba422e65475b33a9494298cfbb75a152b36d2a05501807705b952765350cd14141d35d4986692d6c3bcfc6d61df0052a620aab8cc13205e754c16f93eca7920bbea5157ef112f0b64c1054f90a5ddc175a89e29242f57646e74cc885e81a1cc144c3d782d1152a9e4cfe76cb3ffabe7dbe603fb3869eca8699698709cc87fc961c1e299cfca22e3242eae788cff11bfca61026745f4976225b26ee200c4f1910c4b83df5ce46ef487d748d9c4c502141b7874caf41e5a297b248c2bac6990a15b07b4cf810e59287442d9a3696c02e8d7324d3cf730dda540536beb13cfdeae6180dd7484832dfa94e94aa6cba117aae17270f48f93b2f98ae9581718163f4463546c0ae0f279c36b92bee66f1ca2d6a4f726d2dfee0bc11c1d8a1fa62c3cc8aba266b98759286c1068483b2376b403c887fbb657dc0f255dea90dbd23308f7e0e842b498a8dfc7c9cd5aef0e87d56be40d50fc1dd4c0aa7dee55aebe4d6b6a52053962b87b0f2ee09a90816155333d5c57a14724e001bc3ded17843b76e2c47a176339c8defc54b55b2358ae7d01b0f6e08f31216ae90340694168a5a79ee883ea7858007d17c37359c99d6597efe460c1a2f7738ac32c5eb5e39e500c49c0dff9c4659e8c50cc5ca79d8ba4e5972d67225468fba64167a6b2c6f368935c7a049d35d355c7672520d3c9e4e43c671c3cb8dee259047495de0f56dd7191d5bd4bbd29517e364792ff89d33799b6e781c20193f5a316fb40de74fee2acc25e47f512214de3b1e9b382a86929c1573d3724c25017c0e5:051d8d7f0b68d2eec72c81adfcfb31ae8558f60ab63c9f5652a8df638f666f1ebc0c6e0b411953bcda6b5151b2b93a39e3c5330a8573e168792272abd36c810ab330764ddc628e4ad67aa4982ae86d4581071c193ec3c58f813d7921b84d2a54562bd87417ae1de590a1a48c4ec7d556ad931d65c0543fdf0607c749859ee12f9952020c195cf8746095e1087cc6c3c8ef9d24052560ce813d6139b7a75c8f4b8ea30a9c4ab888d0a6341c99abd35e0903bfe56c93152340c41276d7f24e0912b12a4db3d7ee4484dfa53afc0b1aea1409d1e0328aa1c8604127ca2eb1a5e81bf31f8c7a51c6052c534efe6b3d0ee74ff5a9b11c6157e36477efa9382f5751be8c8c6454c446d6f8dc7e929525cc3de78cb1ba4aba9bd4be152610437582c965eea48cbd4caa6f308f85f4f8d006a042f619200762e1bb9ba422e65475b33a9494298cfbb75a152b36d2a05501807705b952765350cd14141d35d4986692d6c3bcfc6d61df0052a620aab8cc13205e754c16f93eca7920bbea5157ef112f0b64c1054f90a5ddc175a89e29242f57646e74cc885e81a1cc144c3d782d1152a9e4cfe76cb3ffabe7dbe603fb3869eca8699698709cc87fc961c1e299cfca22e3242eae788cff11bfca61026745f4976225b26ee200c4f1910c4b83df5ce46ef487d748d9c4c502141b7874caf41e5a297b248c2bac6990a15b07b4cf810e59287442d9a3696c02e8d7324d3cf730dda540536beb13cfdeae6180dd7484832dfa94e94aa6cba117aae17270f48f93b2f98ae9581718163f4463546c0ae0f279c36b92bee66f1ca2d6a4f726d2dfee0bc11c1d8a1fa62c3cc8aba266b98759286c1068483b2376b403c887fbb657dc0f255dea90dbd23308f7e0e842b498a8dfc7c9cd5aef0e87d56be40d50fc1dd4c0aa7dee55aebe4d6b6a52053962b87b0f2ee09a90816155333d5c57a14724e001bc3ded17843b76e2c47a176339c8defc54b55b2358ae7d01b0f6e08f31216ae90340694168a5a79ee883ea7858007d17c37359c99d6597efe460c1a2f7738ac32c5eb5e39e500c49c0dff9c4659e8c50cc5ca79d8ba4e5972d67225468fba64167a6b2c6f368935c7a049d35d355c7672520d3c9e4e43c671c3cb8dee259047495de0f56dd7191d5bd4bbd29517e364792ff89d33799b6e781c20193f5a316fb40de74fee2acc25e47f512214de3b1e9b382a86929c1573d3724c25017c0e5: +c8ee954db5a11b292ed97764fae6b283051db57dcdc0aa0df5393bb60c112ed35c2f81824e9975dd7ea353bc66807dedc7610349794e2fc08e5a31e002e3fe07:5c2f81824e9975dd7ea353bc66807dedc7610349794e2fc08e5a31e002e3fe07:7ba3fb568315aa81e21f197780edc2c6ea26d8d06a4378912fca2301cf1eab3d803c8469deddf376703ddb7ce06a77dab20e02344fadcc50022ab3c713cd03c1daa93f1c7ea572629f610b5e3c51411bb8c19694bbce903cac4705f9b5dd0f47bc5d0aa3253f908870299027ffbd3449eebad45332b5d0c4f533dbed18a99a2498b9164e245fb65c0afa0b053703a0cf95940ac7a0195d4f7046609cf04371338706b9b1986c0f118175d2cdfce74a6f88659825854e94ece58f5157636d6235b76d32745a2a81a9671a8f86027ba9e01763888fc171cef7c451c36072bc7499839d431cf18cd7c6c9fba3aa712a054328ccd62be4820abd5e782162764611d4539ba2cebdc209b3f4e4b69c3d64073e920d215214fb0fda44185aada5c36127a15ba15ca28a3ad086e9d03366869c60c3fbcebd869d2e40643e833f894803f980a2da7ea4e59ce4d7c06fd2aff087ee7bcfddaa3b32817ce63a63587dbafef380013a6f1ee3734b94ca3df9644dd0434302ecb324afe35f465c9c1c931b27294fc6ee0272de2242ae90d7f2e067027ef8642e8f171ed880ffabce8a20a1b3e339ad4e3f1a9001f20f90026188fde34b217a6e26aaff18422b7f843d0fdda321c319c778f23137f20ccc1bda1890e5bc916a5456d068d37b5acc6347720c56a5a491bc348d6c848a9c8fecfe58c92b1f302fe14919718cd5e78b7fd601d09dc01e6904861e8d68b3c57535b6136676cbc6e839af0dd739db89a7abd913fdf6b00e9ca02602de6ca0afd0913d992fbaa8ff822b9d9b09dda7a29be91910d8fa3caa2a5e518346c167c9f51941cf7353f3f34c1dab33485d0a8c19daf951fd3ef20d0b119d8038df90c114a25a5b93ae40ec44b9a5d2bc1c6517c682500d4cdc197142bec3af8232c071428dc54c0d30454272e7336b0b5888a6e8fecde859e2accb7fb094acc54ffa481f7623d944691f04fb3613a9954980f17e2ad2173d68cf0ec1b67d8a91d6ec82946bcf05cb90681a71627b590238334e3d5ab9da6a089bd72624df9074cdd2309e04dfcae032812fe84f9db882cdeaae69ee5daa5a66ff427fc452edd0769b6aabcc139d0f70af8b97430e644f58a41287a93f631deda82ca0716d79754c5c503e52a665da:f3077a75101e121e5c3e77d8ed97b578d239bd421803d3455b5654405a4c586a6092e13a8529bace468a305784b373e433fee4a3df8956befa012fd8a8eed10c7ba3fb568315aa81e21f197780edc2c6ea26d8d06a4378912fca2301cf1eab3d803c8469deddf376703ddb7ce06a77dab20e02344fadcc50022ab3c713cd03c1daa93f1c7ea572629f610b5e3c51411bb8c19694bbce903cac4705f9b5dd0f47bc5d0aa3253f908870299027ffbd3449eebad45332b5d0c4f533dbed18a99a2498b9164e245fb65c0afa0b053703a0cf95940ac7a0195d4f7046609cf04371338706b9b1986c0f118175d2cdfce74a6f88659825854e94ece58f5157636d6235b76d32745a2a81a9671a8f86027ba9e01763888fc171cef7c451c36072bc7499839d431cf18cd7c6c9fba3aa712a054328ccd62be4820abd5e782162764611d4539ba2cebdc209b3f4e4b69c3d64073e920d215214fb0fda44185aada5c36127a15ba15ca28a3ad086e9d03366869c60c3fbcebd869d2e40643e833f894803f980a2da7ea4e59ce4d7c06fd2aff087ee7bcfddaa3b32817ce63a63587dbafef380013a6f1ee3734b94ca3df9644dd0434302ecb324afe35f465c9c1c931b27294fc6ee0272de2242ae90d7f2e067027ef8642e8f171ed880ffabce8a20a1b3e339ad4e3f1a9001f20f90026188fde34b217a6e26aaff18422b7f843d0fdda321c319c778f23137f20ccc1bda1890e5bc916a5456d068d37b5acc6347720c56a5a491bc348d6c848a9c8fecfe58c92b1f302fe14919718cd5e78b7fd601d09dc01e6904861e8d68b3c57535b6136676cbc6e839af0dd739db89a7abd913fdf6b00e9ca02602de6ca0afd0913d992fbaa8ff822b9d9b09dda7a29be91910d8fa3caa2a5e518346c167c9f51941cf7353f3f34c1dab33485d0a8c19daf951fd3ef20d0b119d8038df90c114a25a5b93ae40ec44b9a5d2bc1c6517c682500d4cdc197142bec3af8232c071428dc54c0d30454272e7336b0b5888a6e8fecde859e2accb7fb094acc54ffa481f7623d944691f04fb3613a9954980f17e2ad2173d68cf0ec1b67d8a91d6ec82946bcf05cb90681a71627b590238334e3d5ab9da6a089bd72624df9074cdd2309e04dfcae032812fe84f9db882cdeaae69ee5daa5a66ff427fc452edd0769b6aabcc139d0f70af8b97430e644f58a41287a93f631deda82ca0716d79754c5c503e52a665da: +6dbc559e4ab193eebf70c5c32d797be00b7311e8e6691da9afcc187291f2501c38a7034476fb9382f1417768c42162951a2636902c3898c029be278ab4c31f31:38a7034476fb9382f1417768c42162951a2636902c3898c029be278ab4c31f31:88ee2365f7cf9de33acd53564968b2dc7f7370b7e7033f4c663a88c25f60f7f711d61908ebf1f5bb72835553c8aa8c8e4fcdecd37978238289bf6ca84876d228217a28d81b0b457c922e91ecba8d3e1d2e6659c2b0aea051b9c2e09c7dfeb51d30ede767570341ffac1ecf0de20c82d1e9ed0775deac72da7c2dec234865dec83f6715e1c3c59de2033cc24d86bc2d31aa16649686ede0dbbd8964c3a64a3dca5588d7248b1f24df8d75f09aac62c07828ca431a3a2d77a60cc93cfa3495cabeb1904ed5b563984e8c20777bac8774108a64eda58fb320244a3add3e3e7a76cd137cfa4a09b6e6e93011ea0ae65171af130711766cd25b3c74ec54c0bdfa02b3120ac29087ebac9837fca65ba971bc4281dd557c500e225ea66c3c3fd52206c19a9f9395463169f8c7a846bd9f834d7f337d0b61fb30bce294f478ae1f1d977e454e433ee8729fb065cce03fb2e435dcbcbfba01537e7a6762e55e7ed22528303704beb5ae381f2e181056f25133273cf17ddf2b06e2d9477f2c09755fc8d9c73cb33100468c64131c686cac79fd384501e50f8b0bee28ba39583f42e4fd3799e24f60da5fd3c779aabf699ffd2321ed045a85bc6424f60fdcc49c1cb31f249a4236c09491768181b921f58602fd415c1edeb26f39324addff14771324737c6720cc92391b949dcb4212bd6931d4de51401e7f953b7b036b223f0af7a8e408b04ea635a23fa0709ba042a5d992954c09d8581dcccf52568ad27a1cc71d18aa2740f621212e7f4c5e5e5e5e4532d9a67ec2773ac21c8a4b002d6524f6182dd371735d2c2abe6c95c281c6fb1e976bc17e383fd52aeaaa9fbd4abb82a2cc65395f8c2cc7d8182a0d250c685cfcba93a951ee7c503c6e3eec236ce33e086c610728737c1c3b3a24252da7f21672d928ebda993a94c458ab990f5d19d80023c36aa16eafcab143f352e97d6409f3249941119bfd9f5f9084724d9ebad383b10f34d33ac830cce9e5cb8aecee6f40301cbbe309fd061534a7d0c3edaaea02a171d8b2349dbeec628520ac334a5bfe28a9d5f4c0d740f7c72d4d72d89a97326a03002d1ef38522bcd37b42847a314bd843ec88d1f2f9d39f57f2f1a13d0140a8847450448c880b3ae76531e95c4392973250:31f16a7caf2b74f65e057c9333a1a2633dac7346338f798510730eb8d5d325fc1080dd5aad5fce0534e9543f3c93586804464af5886e8644129c77ebaa485f0188ee2365f7cf9de33acd53564968b2dc7f7370b7e7033f4c663a88c25f60f7f711d61908ebf1f5bb72835553c8aa8c8e4fcdecd37978238289bf6ca84876d228217a28d81b0b457c922e91ecba8d3e1d2e6659c2b0aea051b9c2e09c7dfeb51d30ede767570341ffac1ecf0de20c82d1e9ed0775deac72da7c2dec234865dec83f6715e1c3c59de2033cc24d86bc2d31aa16649686ede0dbbd8964c3a64a3dca5588d7248b1f24df8d75f09aac62c07828ca431a3a2d77a60cc93cfa3495cabeb1904ed5b563984e8c20777bac8774108a64eda58fb320244a3add3e3e7a76cd137cfa4a09b6e6e93011ea0ae65171af130711766cd25b3c74ec54c0bdfa02b3120ac29087ebac9837fca65ba971bc4281dd557c500e225ea66c3c3fd52206c19a9f9395463169f8c7a846bd9f834d7f337d0b61fb30bce294f478ae1f1d977e454e433ee8729fb065cce03fb2e435dcbcbfba01537e7a6762e55e7ed22528303704beb5ae381f2e181056f25133273cf17ddf2b06e2d9477f2c09755fc8d9c73cb33100468c64131c686cac79fd384501e50f8b0bee28ba39583f42e4fd3799e24f60da5fd3c779aabf699ffd2321ed045a85bc6424f60fdcc49c1cb31f249a4236c09491768181b921f58602fd415c1edeb26f39324addff14771324737c6720cc92391b949dcb4212bd6931d4de51401e7f953b7b036b223f0af7a8e408b04ea635a23fa0709ba042a5d992954c09d8581dcccf52568ad27a1cc71d18aa2740f621212e7f4c5e5e5e5e4532d9a67ec2773ac21c8a4b002d6524f6182dd371735d2c2abe6c95c281c6fb1e976bc17e383fd52aeaaa9fbd4abb82a2cc65395f8c2cc7d8182a0d250c685cfcba93a951ee7c503c6e3eec236ce33e086c610728737c1c3b3a24252da7f21672d928ebda993a94c458ab990f5d19d80023c36aa16eafcab143f352e97d6409f3249941119bfd9f5f9084724d9ebad383b10f34d33ac830cce9e5cb8aecee6f40301cbbe309fd061534a7d0c3edaaea02a171d8b2349dbeec628520ac334a5bfe28a9d5f4c0d740f7c72d4d72d89a97326a03002d1ef38522bcd37b42847a314bd843ec88d1f2f9d39f57f2f1a13d0140a8847450448c880b3ae76531e95c4392973250: +c9d416830ae2028f2175d22b614c79198c670cfaa0e7a36150ef0fee21a95ce66e3eb4d01873072df946f1792f7106330895e7a76dd9ae27f8a988039490fd4b:6e3eb4d01873072df946f1792f7106330895e7a76dd9ae27f8a988039490fd4b:ff9ad4837cd0bb77d6210fdddc755e6c0f1a73c2bcd03f7a5869e7342cfd73cf7086f865561560277bf6c3421a912d67658b1fa97057c496f4be8edcbe18b5ecd08a1e7db25223abda208fa531f4b280aa03b04b60603411d374ba7cbb020bb9a8ce4c0e45a7e132144843c31f8b45c58eb3ea853c2ceb61376e9df81d9778e721adac77b50354937f34372fccd575e88d9d058e43df942f2c43b523c8098e6dd9e6bd21d5a649b472d41e345fcd5efddd49eab30270cd8788404f28516e09d3acc40048b39d3246f757e482e1459c626b799e04d06727137371e120afb9fec39a25f4e6764bf9792fe492ee0f210b57db9ebb9e8ef41b02c7fee9edd4b6174c570de020a391287133fe8ccb41a83f91bd22382b21e1d7ebc2c7e5018ef5142d82637d02620fbc0569cc09c44e911112bbae99064d68d1c69e77c9930b0de030c8c1d748c414059d5e299b7edc08940651894b303a2b32dd2c365a067c9723585594644d3ee8de1a51faea0e650f2124885a94cb99eb903b7d4579bde591497d953930d363dddbdac627b97a91f49682df8e7250a7073d383a7a22cf113f2858ce6b632a2892c4e88aa9a0d289eb57629b008d3b1b6081e6fe5d3c0a6c802189b5f108e766319e15b33eaa5b8ced4027eaec83b4ac68b14b8298bc51cd8eb3809b7a2d684fe32bbd9fab5c918eeb17cc444d73f730d4c8cc057bd3a2f1f0aebb61632934e61702168829cd7e91de81509629d01a8cdefe0d1ac49e21f0c5fbe1b2244827268a0a27357e158bd76884a21e7f1fac1b6272166d5a9f64f9b672989a8762f512bf1df4b2ab699765f2cd8396f476e7f59995dee7d890207eff0fd27263ec232e37cfedfe7c440555d4ca74e52da246c4b83757beafd2ab2a51efe160bb02b98c26d6b2c3f0c1aacb2f3c34a5b2a3b66fee175b787548073d8b5777c6be880bdc196b3374a2154f94d9360f7755ac6815a28af296271e22a8f23543c74955a609125b02a569218011420295ccf0d7356999a5b895cc88483fadf7970cec6c64240f7079fdb15ffc5c4227e53926d278ba0fed3c3993bc86822823dd581a32ab2e3a07f79430224b274eadd845598a7d1d89676aaf23677774b7b0583bcc83599d155d14b09adcf49ed505e8:47faad4e655293eda156b2a1fabbfb7e009fc290aafedbd5652114a47853bc77a8233a2b179f605477d787878cbb15ea6124df8dc57b2ce7be7d18b7162fb50dff9ad4837cd0bb77d6210fdddc755e6c0f1a73c2bcd03f7a5869e7342cfd73cf7086f865561560277bf6c3421a912d67658b1fa97057c496f4be8edcbe18b5ecd08a1e7db25223abda208fa531f4b280aa03b04b60603411d374ba7cbb020bb9a8ce4c0e45a7e132144843c31f8b45c58eb3ea853c2ceb61376e9df81d9778e721adac77b50354937f34372fccd575e88d9d058e43df942f2c43b523c8098e6dd9e6bd21d5a649b472d41e345fcd5efddd49eab30270cd8788404f28516e09d3acc40048b39d3246f757e482e1459c626b799e04d06727137371e120afb9fec39a25f4e6764bf9792fe492ee0f210b57db9ebb9e8ef41b02c7fee9edd4b6174c570de020a391287133fe8ccb41a83f91bd22382b21e1d7ebc2c7e5018ef5142d82637d02620fbc0569cc09c44e911112bbae99064d68d1c69e77c9930b0de030c8c1d748c414059d5e299b7edc08940651894b303a2b32dd2c365a067c9723585594644d3ee8de1a51faea0e650f2124885a94cb99eb903b7d4579bde591497d953930d363dddbdac627b97a91f49682df8e7250a7073d383a7a22cf113f2858ce6b632a2892c4e88aa9a0d289eb57629b008d3b1b6081e6fe5d3c0a6c802189b5f108e766319e15b33eaa5b8ced4027eaec83b4ac68b14b8298bc51cd8eb3809b7a2d684fe32bbd9fab5c918eeb17cc444d73f730d4c8cc057bd3a2f1f0aebb61632934e61702168829cd7e91de81509629d01a8cdefe0d1ac49e21f0c5fbe1b2244827268a0a27357e158bd76884a21e7f1fac1b6272166d5a9f64f9b672989a8762f512bf1df4b2ab699765f2cd8396f476e7f59995dee7d890207eff0fd27263ec232e37cfedfe7c440555d4ca74e52da246c4b83757beafd2ab2a51efe160bb02b98c26d6b2c3f0c1aacb2f3c34a5b2a3b66fee175b787548073d8b5777c6be880bdc196b3374a2154f94d9360f7755ac6815a28af296271e22a8f23543c74955a609125b02a569218011420295ccf0d7356999a5b895cc88483fadf7970cec6c64240f7079fdb15ffc5c4227e53926d278ba0fed3c3993bc86822823dd581a32ab2e3a07f79430224b274eadd845598a7d1d89676aaf23677774b7b0583bcc83599d155d14b09adcf49ed505e8: +2d277dd55f57195ec072b47cb1448cb582c835739e6c98ba71ab128f70ce6b79dfa92593ef0f0d974a1137830ad13848afef3b810c2a21bf779178ce4b3ab974:dfa92593ef0f0d974a1137830ad13848afef3b810c2a21bf779178ce4b3ab974:14549eddd5f2b7905dda19d74ab207aac6fb3e3df3295d845231ef3aea6e1f04ee033c9038dcb4bd3d5e452c54834d0ff2b7de3f322e5626949cd61d6e890138ff0ea8ad846e8fe887aee15fc48bbe4fba42455f5c17457ae789b405af859611fe1f8746185a65aef2134ea4d8f398d48df7c1bba4304408ae7efb35292409d508dd55ce21de8c28160dc9e877700c763d06b01b8542052d7ddb633554e3584279c796937023c8eac37277be2b8204ff3e0e1031190a01014cf5f5b4d7ad996727f97531e0355b87c9e611525aad079958e9afe2ab10e4a3e7a1b6ba0aff815da2cd81ea9eb9f536986633f316dd06c2503c6b198dc59304807b98b42935f51f637ddb59e233fed566439c1fe96cdaafa49f4412d0c1e654d8c69042470b3a59acb6bf67e40b38a77067d5997b8d35ed61d6eb3cc78b8bdcb9574b1ced9f6f339e9e38f94146ef63f049e6b802bfed2a51ab42e7d489f316ff4d1cd898bcf8505651687440749c0fb7a57dbeff72e64689faa41c07b4ade59933d2fac6d573deb739549eb75f1e6f7385d8c6142894973ed685eb8ed080c2a49f3ac6571161af96635ad057df1486d396773ac8983210978986e1bf21a20806d667a48a555a963221d50614a8976b2eec97512db11a358194492ab5455801baa14a511b26eb0c68289d790523712f2ff8709892695c4db9ad310df8c6ee7bd83c871f05aec33b7ad326f446692a42f7222376246d536a326c4d73eb572feada11b8ac7114f6cb444ca278fcf07b970d2ad465372a687d36b7daac478748ec6a932da20843948efa393097814272e5ca1c73e711973a52683f98c01e55241c154d28e38d3edfade2303a4e7c45c2a7a1c996ee1137af864a98b69809fc9214eea8cf3afe842fee3eb9a9322c3b82fddb05d4d1a2de09c1ce72734453a8dd3a8920d0d0ac96ef778b9e02c6a3f12872e17d3a81ba75fd233baadbe216ea0a58e9dda00840870208ae413540030b3c05e5d0b832df87c8ee7f153487aa11bad9f139c7dd4bcf418f4bcb95bee857d0e96084472387cb39127a947134501963a7071bdb34de6961be2b6b06e403e75918e6f69d08021cf2a8acb80a0111f4d50610c152d39c6621c0578ac689959b1ce6f376f43d18af062e4a:73c1060649a7c014ed01945851b53e285324e60d061c831dda41f033b5658306a1f112327afe93caa921020730aae0069c9a2b45eef55cbb4a5a9cd46cda800814549eddd5f2b7905dda19d74ab207aac6fb3e3df3295d845231ef3aea6e1f04ee033c9038dcb4bd3d5e452c54834d0ff2b7de3f322e5626949cd61d6e890138ff0ea8ad846e8fe887aee15fc48bbe4fba42455f5c17457ae789b405af859611fe1f8746185a65aef2134ea4d8f398d48df7c1bba4304408ae7efb35292409d508dd55ce21de8c28160dc9e877700c763d06b01b8542052d7ddb633554e3584279c796937023c8eac37277be2b8204ff3e0e1031190a01014cf5f5b4d7ad996727f97531e0355b87c9e611525aad079958e9afe2ab10e4a3e7a1b6ba0aff815da2cd81ea9eb9f536986633f316dd06c2503c6b198dc59304807b98b42935f51f637ddb59e233fed566439c1fe96cdaafa49f4412d0c1e654d8c69042470b3a59acb6bf67e40b38a77067d5997b8d35ed61d6eb3cc78b8bdcb9574b1ced9f6f339e9e38f94146ef63f049e6b802bfed2a51ab42e7d489f316ff4d1cd898bcf8505651687440749c0fb7a57dbeff72e64689faa41c07b4ade59933d2fac6d573deb739549eb75f1e6f7385d8c6142894973ed685eb8ed080c2a49f3ac6571161af96635ad057df1486d396773ac8983210978986e1bf21a20806d667a48a555a963221d50614a8976b2eec97512db11a358194492ab5455801baa14a511b26eb0c68289d790523712f2ff8709892695c4db9ad310df8c6ee7bd83c871f05aec33b7ad326f446692a42f7222376246d536a326c4d73eb572feada11b8ac7114f6cb444ca278fcf07b970d2ad465372a687d36b7daac478748ec6a932da20843948efa393097814272e5ca1c73e711973a52683f98c01e55241c154d28e38d3edfade2303a4e7c45c2a7a1c996ee1137af864a98b69809fc9214eea8cf3afe842fee3eb9a9322c3b82fddb05d4d1a2de09c1ce72734453a8dd3a8920d0d0ac96ef778b9e02c6a3f12872e17d3a81ba75fd233baadbe216ea0a58e9dda00840870208ae413540030b3c05e5d0b832df87c8ee7f153487aa11bad9f139c7dd4bcf418f4bcb95bee857d0e96084472387cb39127a947134501963a7071bdb34de6961be2b6b06e403e75918e6f69d08021cf2a8acb80a0111f4d50610c152d39c6621c0578ac689959b1ce6f376f43d18af062e4a: +428066c52445726d0ea2007e504637274d84ee232325b505f2c516357f807583dd40fe8f67c665613b3c459f6ace8dc28d34e0e77e2f6aa060592819be6a9d68:dd40fe8f67c665613b3c459f6ace8dc28d34e0e77e2f6aa060592819be6a9d68:e2796c50d93df812bca41bf2a1e1dd737d8cf6f6b4f76242e39178186758cbae0884e60c6b4aaaddaec9a899a912e5c5b9804d7b0497bab4458c585d4f259222498ce9e80eb6a7979bbed6d52cc38072f745cb2c63e663bc3b9d6caf012a607f6d3b706e1557578717ecbb971aeb7c48e1df95711c550e006993bffba911cb64ad52d517ed18be82369e815819d3175947d4a35b2cc7b9dc6c10051326b3f1dc1edb1b68ba015ff7ca1dc361d8967abcffd3c31f7d6b0cb1396ae541f29759c4130be52ecc11d99261c365bf7cdec781494c5fa0526db4dbbe660a432be56043c66ea07c25627a5f72b78123dcf986ff71ed1affd1659b1393d9621f711dfa63eada383430797058f1566a00052d67ba53c1237b5691de3b039fd4476f1151e5ed5f5a98672fa33a1d854fa01566b33231d46acd7f34b8034479981853764dab87f49844cb62c63d536faca920447d8cd1e8113edbc83e4a6b7815e180cd78b933d9687fd5be99d0518a44662989bc64011124f187d43979994a95e0c903a006c1c0bef1c0f3df1eb700f980c28c3c1e997d0c56d113dae196882b05018fcab314d8117fafbabe7700b932d47c57362b2035eddce2d2ef33641ea90c3ea3fec6ea5b87e161014c4f8214fd03cebf94abe122537a98703239df5821c5ab633f98365cc636e3f1d2f74e0ff8f1fee06a3f73907ee504b310fd5224ad4d05cd23c356df8b34647298c49828725ba5fd60611e829b6337bcc9dcf8e8971cab3ee9c26337d38dfdfa036bf6096b635ac1bd5525ecd377a15272a8ac9bbef133107a42258d8b19ec69dc4261be5300a2d2d5ca99f31efdf259f9d079869a34413779f3028824d747686c460ffc496f2010f403e903e27a87dd075ae0a7f1689416d31bcc15f490caf975c40e715d549903e8bc0f7d9141e020f410f3ca2b2c0797ca0dc8d7392bff243528c7f3be138997185a4b36f45376d9fd70ba20989d2d1a911d4b98d160d2b8de592de2f4c04f35860df320c548440d5e3a346a14d3a63fe485c2889126b7f41d55a6eb23d5620babf8564aa79d156e983f36d9ed498da9ca888d946b53cc4768a5892d52d541526960282524ba6194da65941d1ea30f806bb6d97c7488b93fd0a770a9b15efcd12c5c4694:c938829f598b1ff1b8183360d223f43c594730606876a99a3f31b2065d04e6f075d1396b3c8cffb0e1e2eaabda7da5e789ccd1c020835fe3a71dcdb6af03960ce2796c50d93df812bca41bf2a1e1dd737d8cf6f6b4f76242e39178186758cbae0884e60c6b4aaaddaec9a899a912e5c5b9804d7b0497bab4458c585d4f259222498ce9e80eb6a7979bbed6d52cc38072f745cb2c63e663bc3b9d6caf012a607f6d3b706e1557578717ecbb971aeb7c48e1df95711c550e006993bffba911cb64ad52d517ed18be82369e815819d3175947d4a35b2cc7b9dc6c10051326b3f1dc1edb1b68ba015ff7ca1dc361d8967abcffd3c31f7d6b0cb1396ae541f29759c4130be52ecc11d99261c365bf7cdec781494c5fa0526db4dbbe660a432be56043c66ea07c25627a5f72b78123dcf986ff71ed1affd1659b1393d9621f711dfa63eada383430797058f1566a00052d67ba53c1237b5691de3b039fd4476f1151e5ed5f5a98672fa33a1d854fa01566b33231d46acd7f34b8034479981853764dab87f49844cb62c63d536faca920447d8cd1e8113edbc83e4a6b7815e180cd78b933d9687fd5be99d0518a44662989bc64011124f187d43979994a95e0c903a006c1c0bef1c0f3df1eb700f980c28c3c1e997d0c56d113dae196882b05018fcab314d8117fafbabe7700b932d47c57362b2035eddce2d2ef33641ea90c3ea3fec6ea5b87e161014c4f8214fd03cebf94abe122537a98703239df5821c5ab633f98365cc636e3f1d2f74e0ff8f1fee06a3f73907ee504b310fd5224ad4d05cd23c356df8b34647298c49828725ba5fd60611e829b6337bcc9dcf8e8971cab3ee9c26337d38dfdfa036bf6096b635ac1bd5525ecd377a15272a8ac9bbef133107a42258d8b19ec69dc4261be5300a2d2d5ca99f31efdf259f9d079869a34413779f3028824d747686c460ffc496f2010f403e903e27a87dd075ae0a7f1689416d31bcc15f490caf975c40e715d549903e8bc0f7d9141e020f410f3ca2b2c0797ca0dc8d7392bff243528c7f3be138997185a4b36f45376d9fd70ba20989d2d1a911d4b98d160d2b8de592de2f4c04f35860df320c548440d5e3a346a14d3a63fe485c2889126b7f41d55a6eb23d5620babf8564aa79d156e983f36d9ed498da9ca888d946b53cc4768a5892d52d541526960282524ba6194da65941d1ea30f806bb6d97c7488b93fd0a770a9b15efcd12c5c4694: +3145bc68d82979408e4657b775f150c6d28a324d746ea6de90fd72b17a257982c776186ce47f30ad08fa1d2c616a3644665ba54ff730fc2f4db1dba38ddeedca:c776186ce47f30ad08fa1d2c616a3644665ba54ff730fc2f4db1dba38ddeedca:2ea8dce1487f45d6ff8eb83c54fb7edd76ad6e608bb8daf1a1823da4f4e4e9863173897c197ac65804823bca95091f59e86d63c18dbcdb85743f8893ee694d815601f8f22f4d7df087f0114bb26c3795e1fe4b7f4a8fa31fd9f4ff10fe5dd452c54c5578c752f888213076be467ba30d2e2fbbee877c4be9b6ec4f04021c006f9266311943cab7cea99a2acebb69eec3e618c131f97430075f7975e39f26d5315178b69a1ddf731761051b93fb8df7e0e8b41e82e7f4f75e91d6c890b14ca533e094eb8ea4486d387185966c98295d3f58b17eef6cc3b4d07e93a3d9f4772ee52f18a5bb30aa3972850e658170bddb676f33266c9fd10f5990bad891f0ceb782736b40f01bd86509b06304a96d93da233dbed18afa1818aaf57af9bdbc867b397ff235a83e857224b15065225eec039dd4e2d69a04ee10bea0695041eda59b058ec05f49048ee324d16c4d6107b6ecd04875eb744e9365471b4c5fe6611b261893f9d2b128e135f92e474156b271b3c82e9a7663dad4953d30e10eda0862607dec3372b39970f2a84b12f60e6dae7f31799086d38a7e34948419c1b07f44c2159c86b8c0cfe8747fc2bad5bf475356cfe69de2dc6ad5a519fd65c12564701c05f7c277ecafcf4c87b148df1f9879a9ae443c55aea52138c6fa01ef0c3abb5f2df90a57ab6624178c737b54915b7aa29ea78e8e49ef5a816d8a92c2f81b8a19632779c892d66f753d518c41cccc9e593e50742625bcafa468805c37a21f8e29a6960ddf5c5e5ca14a7b052a7b6015697a0210ed6f0143e6b484c3f5b3b4726c607d07bfb3d54a09c98043f21dcc5cc20bb4754e2e5a73b2f806c2204b72f36ab9e96a62c6277c0ad66be7abffc163b4e8fafceff5e202e5943f4f0e6b92b4ddb953cbb791f83166036938e6c44ad91a596a5573440fb30741e660b6cd5f86ffa746e6e972b805c10b7b7b9a63c0551db8eb4f8400cde2868c0d0d4eb4cf117f8ec4ab9744fc5879dea7f0ef16c291d55c17f08b731b7c65d0c441b63bc8ff5e94904c026a1361dacc80a93a9b9fba3b403617aeb94a568541848011954234aead700f034c47c7def877905255f18bdb9a257ce5bdcf0e17670cdaaf13b1c7e09d58f92a9663af239e22078e180a23ccb6f64d64:24a433337683bc71a6ca3bccd8cc2400c24464fa67714b46515f2a1432712705d570614db6d26bbbd3f0267c1427ca1c2f40dc9a6f1fb0f0fc714a02e24b47082ea8dce1487f45d6ff8eb83c54fb7edd76ad6e608bb8daf1a1823da4f4e4e9863173897c197ac65804823bca95091f59e86d63c18dbcdb85743f8893ee694d815601f8f22f4d7df087f0114bb26c3795e1fe4b7f4a8fa31fd9f4ff10fe5dd452c54c5578c752f888213076be467ba30d2e2fbbee877c4be9b6ec4f04021c006f9266311943cab7cea99a2acebb69eec3e618c131f97430075f7975e39f26d5315178b69a1ddf731761051b93fb8df7e0e8b41e82e7f4f75e91d6c890b14ca533e094eb8ea4486d387185966c98295d3f58b17eef6cc3b4d07e93a3d9f4772ee52f18a5bb30aa3972850e658170bddb676f33266c9fd10f5990bad891f0ceb782736b40f01bd86509b06304a96d93da233dbed18afa1818aaf57af9bdbc867b397ff235a83e857224b15065225eec039dd4e2d69a04ee10bea0695041eda59b058ec05f49048ee324d16c4d6107b6ecd04875eb744e9365471b4c5fe6611b261893f9d2b128e135f92e474156b271b3c82e9a7663dad4953d30e10eda0862607dec3372b39970f2a84b12f60e6dae7f31799086d38a7e34948419c1b07f44c2159c86b8c0cfe8747fc2bad5bf475356cfe69de2dc6ad5a519fd65c12564701c05f7c277ecafcf4c87b148df1f9879a9ae443c55aea52138c6fa01ef0c3abb5f2df90a57ab6624178c737b54915b7aa29ea78e8e49ef5a816d8a92c2f81b8a19632779c892d66f753d518c41cccc9e593e50742625bcafa468805c37a21f8e29a6960ddf5c5e5ca14a7b052a7b6015697a0210ed6f0143e6b484c3f5b3b4726c607d07bfb3d54a09c98043f21dcc5cc20bb4754e2e5a73b2f806c2204b72f36ab9e96a62c6277c0ad66be7abffc163b4e8fafceff5e202e5943f4f0e6b92b4ddb953cbb791f83166036938e6c44ad91a596a5573440fb30741e660b6cd5f86ffa746e6e972b805c10b7b7b9a63c0551db8eb4f8400cde2868c0d0d4eb4cf117f8ec4ab9744fc5879dea7f0ef16c291d55c17f08b731b7c65d0c441b63bc8ff5e94904c026a1361dacc80a93a9b9fba3b403617aeb94a568541848011954234aead700f034c47c7def877905255f18bdb9a257ce5bdcf0e17670cdaaf13b1c7e09d58f92a9663af239e22078e180a23ccb6f64d64: +5a25ea5e182d9bf8e930a20b6cf55e24e83862789b3839b1ce9a71e938c42d37c981fc36f1a6d5f7d451cd5ef39cd3ab02087fcc6af27dd78ea827497e779e21:c981fc36f1a6d5f7d451cd5ef39cd3ab02087fcc6af27dd78ea827497e779e21:214dd1927f2cacd9888714249b85434602ac78453b4af5386eee39295d3d5a2267806eb0cff2c132d364c2420d04e3f6cc0a967bf05a10ffcf1217bbf315e75b98060fd458d67ebaad9380f4adc4dbdf74cbf1c6479202bdd7fed3a946697dc38444d88bfe51d41d7a9b38da60b850c56b48ba984f6a1889514955c0dadb69a8c736cc76cdc49f13f85a8bfb7928ff0a0c0c03f17c74b5e1062d7553fbeb9dd3d5081de1dfd8a6a9976697c6a259bcf7d4bef1c21e0aaf3298b0421b919fddfc1dcb3ec683d86ff3d423d71c8f2d723a42ff68d82e9f391749b82998dcfa112160f52a413a23d95fc42c3bd22384bad77754a710d8b9f84ae0a802fc46509e7f2b07079012b43bfeeab719bde56f00e59b8edf1c472883b1985b2fa699a1ae90cf45d7ac580ceb5f2797def5b8bf4f2b9b3519a727b9f2cd1256a2f076ed2296495b5c2df7887ff89e88e236a14cde6324f43d68d90172b0b88bd28803e999dbedcc501db654544e171ec1f9f32d4d3321d589392e03ca659f96752e1f08a55db553d866985541f5bef84ce2ee323e17d1f7dc164b50515a287d5305fc28c5983b9e5398b2407ae47296fe4a481d22ffb4b865a66b97a6c27935dd8eb86994b79d368363713f101dc37f429eee0fee2441c2dc17bf43924f0c044f143290eaf3f9ee4d946dbe45831a0d83c076e751c14f3b1a7267f5446c188698d2b46d87e6f3b20bb3fdafe24cc096bc312d8678b38a80c3f052a0c96d5ad87a5dd8c133cc9a15be33574cd94308c24dec1a9bdf189ba687199f72ef6709878e10f87bd8a03dc84c8fa96420285898ca3211d8b0ccef64011ec24f38e574da34dab9d2f002105227890f92488c621e5713e47dbcb1a82a6da60d8b2201eb29d494493360ed5a3f4b5225eae7707ee0b4c0407305c16754c7f630fc85c13e4917047bcff3b2a293fe955506c7264ea65bf3a9b25acf343600d8fa0c7c1a290d0271101b7f40b96e7fdaf29def9d9327a5ae05446cb5a6d322453a8b098bcf3aee1f704e14d00be342b8934d19e529218872ea3a2fb2124b52667c01fca5841c66e1e64a1e680e09ba186e04d105186cf6eb728b9d502a66b829fbc992a3881004ecdc80adfd044eda880f8af72a14fb550d7cc74194a945207d:a4f35b49d7e198e5d326e353fbb01fa13b6ae260d1e48e30c1b967737a5e79936c97ca2ba799ca34e5e788cea5ac8ed10d5cd15dae53e42432321cc26dc99809214dd1927f2cacd9888714249b85434602ac78453b4af5386eee39295d3d5a2267806eb0cff2c132d364c2420d04e3f6cc0a967bf05a10ffcf1217bbf315e75b98060fd458d67ebaad9380f4adc4dbdf74cbf1c6479202bdd7fed3a946697dc38444d88bfe51d41d7a9b38da60b850c56b48ba984f6a1889514955c0dadb69a8c736cc76cdc49f13f85a8bfb7928ff0a0c0c03f17c74b5e1062d7553fbeb9dd3d5081de1dfd8a6a9976697c6a259bcf7d4bef1c21e0aaf3298b0421b919fddfc1dcb3ec683d86ff3d423d71c8f2d723a42ff68d82e9f391749b82998dcfa112160f52a413a23d95fc42c3bd22384bad77754a710d8b9f84ae0a802fc46509e7f2b07079012b43bfeeab719bde56f00e59b8edf1c472883b1985b2fa699a1ae90cf45d7ac580ceb5f2797def5b8bf4f2b9b3519a727b9f2cd1256a2f076ed2296495b5c2df7887ff89e88e236a14cde6324f43d68d90172b0b88bd28803e999dbedcc501db654544e171ec1f9f32d4d3321d589392e03ca659f96752e1f08a55db553d866985541f5bef84ce2ee323e17d1f7dc164b50515a287d5305fc28c5983b9e5398b2407ae47296fe4a481d22ffb4b865a66b97a6c27935dd8eb86994b79d368363713f101dc37f429eee0fee2441c2dc17bf43924f0c044f143290eaf3f9ee4d946dbe45831a0d83c076e751c14f3b1a7267f5446c188698d2b46d87e6f3b20bb3fdafe24cc096bc312d8678b38a80c3f052a0c96d5ad87a5dd8c133cc9a15be33574cd94308c24dec1a9bdf189ba687199f72ef6709878e10f87bd8a03dc84c8fa96420285898ca3211d8b0ccef64011ec24f38e574da34dab9d2f002105227890f92488c621e5713e47dbcb1a82a6da60d8b2201eb29d494493360ed5a3f4b5225eae7707ee0b4c0407305c16754c7f630fc85c13e4917047bcff3b2a293fe955506c7264ea65bf3a9b25acf343600d8fa0c7c1a290d0271101b7f40b96e7fdaf29def9d9327a5ae05446cb5a6d322453a8b098bcf3aee1f704e14d00be342b8934d19e529218872ea3a2fb2124b52667c01fca5841c66e1e64a1e680e09ba186e04d105186cf6eb728b9d502a66b829fbc992a3881004ecdc80adfd044eda880f8af72a14fb550d7cc74194a945207d: +42335c30b3f6b359cef5aab6a3ce2858a151b7a4fd78d2fd3ee36fc29d249404301c515a02a4c66bc6401080c6ca7923b7831e3c9a72b55b14027eb2e7b3b152:301c515a02a4c66bc6401080c6ca7923b7831e3c9a72b55b14027eb2e7b3b152:6da2251e6f559536b09bfafb8160a2e8102d31f8b59324083e5227b20c3e5c3a06e2396768dca3ec76dc7fc0eb3d145e62ed07fc1a8b1b2e347013a0527274d0b234fe725026a9d128f8df20dbfa3b6503818edebd7f24934080945a7e1ea02273fe48b6ed1e83fd168d7973fbb7941b4037d3cda555e0e89c2b943fb1e20765ac7d4fa3777f35a0a8bc118f599c847be3fdb2d8e201ae12a30bdefb034ff24e3e2e701a0d1733734078bd1f9a69bbc667e461211f2c769d29db7c4d62d6b1b92b56f5f18a931a926064b78da146e18b48139b9b39862aec37bcce12cb789429e68ea38112d0b5cce30bd2d26c5f7fd415daf7ca317b3368b7617d4525e5bc97d9461d5d64f6b5d318d0bc3b76f25b0605426909f2aa0cd667a4f0e075b9a9fb2e9a6c82704d8a9f1666844edc32f63a3d4e0fd9fdba30b51b3336b96e9eae392a342de49e9b5fa0f9b90171bde09cf1e946499140008159eb1865563c28394b03a8d7a552271b2876687566b80fd3be2b66332fcad196cab8527c56e21536a141652cdc7fa745b26a331d787b93e5e816d8d851a58f6ac07a5827fcdf472e8685433a40cac0c49aa569319a2e57b41c9998165e69723ba77e5c0423c4b4ca07187bb7442e7d31caacb27700c71ae48cd055ed2fe4da363f44821124cca1bf2e63d9b8abd2fa41b1422f52d558bc5f110c863cc600864984ed259b73cddd5796b32979eddf76a07bc59b7368c48e129ecc0d4535dccee2c3b8e56de50e6f5cc6ea515cd6a0ebdf1ca79aa2794821ad2e109edda450c9fc3c84d8c96bc38d4b437a738f818b4ddcb684383c09b11b36052e9d2f76a61eb4d62049ced5f61662c4b9ecd24a67f4519d46528c5b2eb21005f49c73a3370c68e37ac2b18d481fa10f96714fe05c168df11cda54f14f4937e9fce1f516c0371b36a2c0a050bac7fa5122a6e35ec9c40436585f316e6c911bdfd7db4b80b4306479b82a2b243a52b2d2b62742ed11282790cf6fdc7c9c824364cf25636a855150bddbdf7e640f9f952a947ec7974925e8245068b292101b1f4b2018e85d078c2feef4492349729ad4acb38f1c7c0270b61d3dfd7636c6cbf181e4c8a0e64fa06132553c2b9db7019e3b3c485d8d5b7dfd5f515e4d71ede535ae7f2aaedc23:67b0f17449039e8c797bf913aae6e4f0bb99c74d6d10c973b990ffe03e7ee4ab5b35806db15a98c0846a827e7bcd539cd3bc09dd118ab3e52663a357b12991076da2251e6f559536b09bfafb8160a2e8102d31f8b59324083e5227b20c3e5c3a06e2396768dca3ec76dc7fc0eb3d145e62ed07fc1a8b1b2e347013a0527274d0b234fe725026a9d128f8df20dbfa3b6503818edebd7f24934080945a7e1ea02273fe48b6ed1e83fd168d7973fbb7941b4037d3cda555e0e89c2b943fb1e20765ac7d4fa3777f35a0a8bc118f599c847be3fdb2d8e201ae12a30bdefb034ff24e3e2e701a0d1733734078bd1f9a69bbc667e461211f2c769d29db7c4d62d6b1b92b56f5f18a931a926064b78da146e18b48139b9b39862aec37bcce12cb789429e68ea38112d0b5cce30bd2d26c5f7fd415daf7ca317b3368b7617d4525e5bc97d9461d5d64f6b5d318d0bc3b76f25b0605426909f2aa0cd667a4f0e075b9a9fb2e9a6c82704d8a9f1666844edc32f63a3d4e0fd9fdba30b51b3336b96e9eae392a342de49e9b5fa0f9b90171bde09cf1e946499140008159eb1865563c28394b03a8d7a552271b2876687566b80fd3be2b66332fcad196cab8527c56e21536a141652cdc7fa745b26a331d787b93e5e816d8d851a58f6ac07a5827fcdf472e8685433a40cac0c49aa569319a2e57b41c9998165e69723ba77e5c0423c4b4ca07187bb7442e7d31caacb27700c71ae48cd055ed2fe4da363f44821124cca1bf2e63d9b8abd2fa41b1422f52d558bc5f110c863cc600864984ed259b73cddd5796b32979eddf76a07bc59b7368c48e129ecc0d4535dccee2c3b8e56de50e6f5cc6ea515cd6a0ebdf1ca79aa2794821ad2e109edda450c9fc3c84d8c96bc38d4b437a738f818b4ddcb684383c09b11b36052e9d2f76a61eb4d62049ced5f61662c4b9ecd24a67f4519d46528c5b2eb21005f49c73a3370c68e37ac2b18d481fa10f96714fe05c168df11cda54f14f4937e9fce1f516c0371b36a2c0a050bac7fa5122a6e35ec9c40436585f316e6c911bdfd7db4b80b4306479b82a2b243a52b2d2b62742ed11282790cf6fdc7c9c824364cf25636a855150bddbdf7e640f9f952a947ec7974925e8245068b292101b1f4b2018e85d078c2feef4492349729ad4acb38f1c7c0270b61d3dfd7636c6cbf181e4c8a0e64fa06132553c2b9db7019e3b3c485d8d5b7dfd5f515e4d71ede535ae7f2aaedc23: +be6b2babddd2dca1b0e10d12d20a9ce29c6785dac1d60f2edfa94ac2784ba766398f22f0efbf8c38355e4791bf670898951fbbd5518f0e2a605d460023f613f0:398f22f0efbf8c38355e4791bf670898951fbbd5518f0e2a605d460023f613f0:5c9295881b7a670669b04cbe0dabd89693b77f7cce0d4a33f52e02eb26959e713d9aef5f95442bdf91728383325202aaccc037477e3666facaf24eac9534879aa3efe18ffc1a5c54e39c7687d0937b2471bab389b646cbe6b3e5d5961ea63bd452b4743344ce4c793374523795c781ee84d511e2941119bad1f4a746ed9dba89c8d0751a6402718635f6e31d9e18681c6956c5373251d35f53baa1987cd448c9031a07f32c8029119de3a91631dede1d933e0fa32629afe1b42eb591c22f87331e93cc083c23f64a6e5e586ff31cc04e423c56ae3f6a73946c48de4d85ab0017ba24456d69b59dca6d403b64b07c40d3b90e1223215e3f7e876c6701111e37e517770887310ca856f009a0d60654835d94e6587a439da5db0a0c37d7c9d37ca1d703e1b3227631adacaa79421a1c439d60349ae57741b7a8ad09ec293123030bf6bac0689e531ca7e72718223f9ea43becb0ee9d9c1ab845ed1cae443e3c5d4a9b1ede6db3417c3ace281143f42d85f599b3b9d3d05fa0ed07c1ec35ffab0305168b4e56e58afa0617f9a86b1b5b201dccb072b4cef0bb7b95c52daeef9d9e7424a5c0f148f9ffe60a5b23e0ff82c730992ac9c17f97f065cf0ad5377eaccb31d8bb923bd260ea119e6fa9bd6983482d70d9219102402dc6a3499193d0c1cd3ed2a66921a98df69b791413f4970bbce04f639af909c64f4560db0af6003dc46219e8ad2b372f8b5f81cfaa041ab71a348c931e8dfdbc409c22d7ee6e07626e104ec6cc7c6a4116177f93af16f124f196dab619b6f698c2d191858e960c2e947b51f3ac4838759c21fef7ebae35da24f55ebda9b9879aea17a6d8d927de487b175fd7faa21438a20923ddbbca72e6726934bd6c21e8118019f65b3810a07fa27b1cba64d0f39f0bfd49dcfafdefe379bdea82f31a9c39f7e81d294337d10f1e9d8b50eba458ce7b753d36968538513eddb0e84534411c4af3f0214610ee3901a0ebf316173ccaf15cd7ee496dbfc2465eb834df62029d621fe911824d7987df2d46346b4dce1ece7d19d55118c037c9955111d07f1fc362c739f1ea5b275c71c0aebf59655e2def16e123b3eb2526c3ca5e83cb24d5b68d7ac40a67593384c563afe0b552adaf60805035be97b80676adeb1576520833:702ab9acbfa75ea2adbe4be2b6847625aeb409eef9596fabe39d2c533a03431e5e579552e8a64fc4fb7d926aa8fffe0640698464c4454ce35fe83ff263051a015c9295881b7a670669b04cbe0dabd89693b77f7cce0d4a33f52e02eb26959e713d9aef5f95442bdf91728383325202aaccc037477e3666facaf24eac9534879aa3efe18ffc1a5c54e39c7687d0937b2471bab389b646cbe6b3e5d5961ea63bd452b4743344ce4c793374523795c781ee84d511e2941119bad1f4a746ed9dba89c8d0751a6402718635f6e31d9e18681c6956c5373251d35f53baa1987cd448c9031a07f32c8029119de3a91631dede1d933e0fa32629afe1b42eb591c22f87331e93cc083c23f64a6e5e586ff31cc04e423c56ae3f6a73946c48de4d85ab0017ba24456d69b59dca6d403b64b07c40d3b90e1223215e3f7e876c6701111e37e517770887310ca856f009a0d60654835d94e6587a439da5db0a0c37d7c9d37ca1d703e1b3227631adacaa79421a1c439d60349ae57741b7a8ad09ec293123030bf6bac0689e531ca7e72718223f9ea43becb0ee9d9c1ab845ed1cae443e3c5d4a9b1ede6db3417c3ace281143f42d85f599b3b9d3d05fa0ed07c1ec35ffab0305168b4e56e58afa0617f9a86b1b5b201dccb072b4cef0bb7b95c52daeef9d9e7424a5c0f148f9ffe60a5b23e0ff82c730992ac9c17f97f065cf0ad5377eaccb31d8bb923bd260ea119e6fa9bd6983482d70d9219102402dc6a3499193d0c1cd3ed2a66921a98df69b791413f4970bbce04f639af909c64f4560db0af6003dc46219e8ad2b372f8b5f81cfaa041ab71a348c931e8dfdbc409c22d7ee6e07626e104ec6cc7c6a4116177f93af16f124f196dab619b6f698c2d191858e960c2e947b51f3ac4838759c21fef7ebae35da24f55ebda9b9879aea17a6d8d927de487b175fd7faa21438a20923ddbbca72e6726934bd6c21e8118019f65b3810a07fa27b1cba64d0f39f0bfd49dcfafdefe379bdea82f31a9c39f7e81d294337d10f1e9d8b50eba458ce7b753d36968538513eddb0e84534411c4af3f0214610ee3901a0ebf316173ccaf15cd7ee496dbfc2465eb834df62029d621fe911824d7987df2d46346b4dce1ece7d19d55118c037c9955111d07f1fc362c739f1ea5b275c71c0aebf59655e2def16e123b3eb2526c3ca5e83cb24d5b68d7ac40a67593384c563afe0b552adaf60805035be97b80676adeb1576520833: +b1e47ca31c64b68aafafb443512e66787c6592f334aa78fa219a3d93c33a4ab358119b38e6a148a936bc5f92f4f29b982ff2cca64a5affa14ca1b6a62fe328c4:58119b38e6a148a936bc5f92f4f29b982ff2cca64a5affa14ca1b6a62fe328c4:767ec1b3daf204387f3fd3b20010781afb1f38f614474213287fff11307f5ff5ae7ec945a2b9b4870049d4532f8f61c1a7b5f211fca2e67c374d96219d8ea9de73f0e38704fc94c0e9e72f2e15daba3f88f749b1ed702660db1a352a2667d4dfd4e00a18efa4c6609ee9c9a88adacbbb985d3de8ddd17d4e4eb7cf74a1da91edb390852ea4cb9a424f7fa2229e083033a34059117e5efa7b6613d75e58b702c6cee5d004e8599b97503a5f10c4c4e5b9577371d3d05b2dfbf7cbefe6d092d65cbd405138d9b04c5186235983fab6d4ce85b636276206d74a2ee7db6164dac47cce78f50db99af6ac6e7064c13aab793be87e66289c94a09fb0a31d97971edd74ea9c0ce874d2b7d6c4abaeff07f870225151946a5c476f6b978996b87d8c984606c791287da6bad0aa44b0130be88671a556e2de35c4cb038ee781273530ace0a104c27809aee033c8bf9029d90fe7ba06aaa94e16a52c643dfd92a7624fbbee77a7158b2cc151bd3f61a1a76f32b28489307acf0dd8c26cc4adbbb8de430db4e4f58308b6ab90456111deac2978172fe1fc0ce498088add4c31c21f24279025feb48cbb7a920cff2d28710587af52c844db8a7aeb7df10d43411a3c8eeebb406d6efcb19248887d450b573d90305e1f23753e890511dcc77c740e316ad7f52d4902073db3998e4e4acc4e01885bd1188ecd6165aeded1e778702b6a6a79a94999102df72018f792f8f162007e812aef8f956e123282bbdbd0c35612c2d3473f944c6d76be9e86fffa46ccb1ae13505a4a81f31b8426b8b60de8e8a7c16d1e1665b271434665c442a9c6a977ce986f6993b7439af03b402eeafff1456d151526d9c58f515fd2485e0cbb324a503a8d491344cdb2aff4c41aa8e2ed66e58083bf0d2fbf4877c85a4bcd6b9cbb821242c94147e5fd8b7dd792ad0a28d49d41100b431bb4d8c7833d8505dd9e2649f9ca7051be68712ef3637102036b002649473ce259677d82c6062895e161928b752f13c91a45955e80f007de690edf8a0e5eee4422e162b9d2b4a921d3a64845793aa2229e9c239e57a6b1a90a5254c3512f99345315ac7d3457f9154296c66822abe184d64e572b9c38492958e21b0292675410e7348b2b718a0b7592caee94581a948d2f41fa03c61e:dfac86df586ec34c7cfea5d5a6cd1140e50b6bf050f8e41a190ebfd3b1432b95a57d5652dbae8f53e037ae326e7f18cfef7c779f40346f7c0d8644610593f209767ec1b3daf204387f3fd3b20010781afb1f38f614474213287fff11307f5ff5ae7ec945a2b9b4870049d4532f8f61c1a7b5f211fca2e67c374d96219d8ea9de73f0e38704fc94c0e9e72f2e15daba3f88f749b1ed702660db1a352a2667d4dfd4e00a18efa4c6609ee9c9a88adacbbb985d3de8ddd17d4e4eb7cf74a1da91edb390852ea4cb9a424f7fa2229e083033a34059117e5efa7b6613d75e58b702c6cee5d004e8599b97503a5f10c4c4e5b9577371d3d05b2dfbf7cbefe6d092d65cbd405138d9b04c5186235983fab6d4ce85b636276206d74a2ee7db6164dac47cce78f50db99af6ac6e7064c13aab793be87e66289c94a09fb0a31d97971edd74ea9c0ce874d2b7d6c4abaeff07f870225151946a5c476f6b978996b87d8c984606c791287da6bad0aa44b0130be88671a556e2de35c4cb038ee781273530ace0a104c27809aee033c8bf9029d90fe7ba06aaa94e16a52c643dfd92a7624fbbee77a7158b2cc151bd3f61a1a76f32b28489307acf0dd8c26cc4adbbb8de430db4e4f58308b6ab90456111deac2978172fe1fc0ce498088add4c31c21f24279025feb48cbb7a920cff2d28710587af52c844db8a7aeb7df10d43411a3c8eeebb406d6efcb19248887d450b573d90305e1f23753e890511dcc77c740e316ad7f52d4902073db3998e4e4acc4e01885bd1188ecd6165aeded1e778702b6a6a79a94999102df72018f792f8f162007e812aef8f956e123282bbdbd0c35612c2d3473f944c6d76be9e86fffa46ccb1ae13505a4a81f31b8426b8b60de8e8a7c16d1e1665b271434665c442a9c6a977ce986f6993b7439af03b402eeafff1456d151526d9c58f515fd2485e0cbb324a503a8d491344cdb2aff4c41aa8e2ed66e58083bf0d2fbf4877c85a4bcd6b9cbb821242c94147e5fd8b7dd792ad0a28d49d41100b431bb4d8c7833d8505dd9e2649f9ca7051be68712ef3637102036b002649473ce259677d82c6062895e161928b752f13c91a45955e80f007de690edf8a0e5eee4422e162b9d2b4a921d3a64845793aa2229e9c239e57a6b1a90a5254c3512f99345315ac7d3457f9154296c66822abe184d64e572b9c38492958e21b0292675410e7348b2b718a0b7592caee94581a948d2f41fa03c61e: +fbd55fa743c3a5910b3857dd0b6aa584f3b238de056b76ab7617aeb52638fef6a7a163c4183bd84b756df3c8afdfb9cd5b242352d9499ebdab90785c3bd6db2d:a7a163c4183bd84b756df3c8afdfb9cd5b242352d9499ebdab90785c3bd6db2d:bf5252b2aeca1163771f766278768066f21971357ea7996158a8d6e908dd59b59971349fa17882cb9224b972d0ffabe85510dcf25a9f9f9bdefad2f4cadfbbdacc1fca9d948cb5412f474cad23b5b9199bf3c7370641339b750e1f78c2adb460aa5b21b1fa8f97714abb4ed5e9cb51d6de55816618abd3fd2b286bc11c67ba01129373d435b3e7e391ba372614da8322875e46a675b645156024cad2dd13f9a081616bf131a24358894e0efa1d56648ffb42efb54031da7f37d197615155aedb69c4e709c8bbbe7fbfcb598347ac5d0c638407847b281cf116433097f5662158719fcdd37beb489268ce71de7d70ed925f743fc63a715f7eee7549fdb909cc454c988b30ae4d77d62f65a07e2c8f9362385d028a603108c945872f5e1a97419878ed49542e288ef07b5c90f5c4159e162303d080f6ac2b058ddcac60746f9e1c9ec1df8eda42d62738586d3fdd65df55f4374f3294e0868d41ef0bb1fd55e0cbf195bbfcfcde5bdb41fad9a0477e4c90ca27fa8cf503362a33fdeca5a4f0ffea26e8d7e134fad3b1ec3d056055bba5e65d81153ee831873b938df7d2c83c2a52b3c221827f961bd008362232d882a0412a047afdfb8597c865a2aa2c2cf5189934a83ee6b752a626941edce0c20b6f7a69f1cf12f9a331cdfa9eda24c8defa769ccce2ef746c307d8bb04891fcefd49af3e6f96991a7a20f27b6c0af1218be31791d1d0293e081b90af3b92ecb175ec8c789f7a8642e041ec3a61aaefef62a807d1a5054adf8323bed942241623732a2051dc01f9a20a29aa48b3fdf265d0ba6c138fb5793e2875002e7de3f5c3ff7e83ad27d111c848b7e6e2e5ad5f28eb7c363f95f960cbc421336ce985f946b0515b1bdd3a832c3fe903f7b44e20c92ea80826fbf97e2a4fcaf2db1a08698dd62edd0a84589d7462c447b4a896fe00860042496bd51b1925cb79cc3b829016a4c7e62790f8058c546f2145aaaef4d4b1e273ff61300f8008e946b622f60e505f5f6290d51eb997d20fc3fbb3e99edd68ff5cce9e8c283881c364ff215cb50045e60f4a7ee45b6c9d86447f38141d342dbc5308f8c66efc47f7c45f6d25e6564309a862db90f4df331787ecdd89d3aaa46053e29f102624ddfe80e8a3f99287cec19fa83e44d557c0441:effb29da6985971c202e2450301d49711bed25fad85f6199d1eb1e71914d964cbe18e34cc3e32872cdec026bd119a41c1c07ca41e82acba62fb0a7c82aed800cbf5252b2aeca1163771f766278768066f21971357ea7996158a8d6e908dd59b59971349fa17882cb9224b972d0ffabe85510dcf25a9f9f9bdefad2f4cadfbbdacc1fca9d948cb5412f474cad23b5b9199bf3c7370641339b750e1f78c2adb460aa5b21b1fa8f97714abb4ed5e9cb51d6de55816618abd3fd2b286bc11c67ba01129373d435b3e7e391ba372614da8322875e46a675b645156024cad2dd13f9a081616bf131a24358894e0efa1d56648ffb42efb54031da7f37d197615155aedb69c4e709c8bbbe7fbfcb598347ac5d0c638407847b281cf116433097f5662158719fcdd37beb489268ce71de7d70ed925f743fc63a715f7eee7549fdb909cc454c988b30ae4d77d62f65a07e2c8f9362385d028a603108c945872f5e1a97419878ed49542e288ef07b5c90f5c4159e162303d080f6ac2b058ddcac60746f9e1c9ec1df8eda42d62738586d3fdd65df55f4374f3294e0868d41ef0bb1fd55e0cbf195bbfcfcde5bdb41fad9a0477e4c90ca27fa8cf503362a33fdeca5a4f0ffea26e8d7e134fad3b1ec3d056055bba5e65d81153ee831873b938df7d2c83c2a52b3c221827f961bd008362232d882a0412a047afdfb8597c865a2aa2c2cf5189934a83ee6b752a626941edce0c20b6f7a69f1cf12f9a331cdfa9eda24c8defa769ccce2ef746c307d8bb04891fcefd49af3e6f96991a7a20f27b6c0af1218be31791d1d0293e081b90af3b92ecb175ec8c789f7a8642e041ec3a61aaefef62a807d1a5054adf8323bed942241623732a2051dc01f9a20a29aa48b3fdf265d0ba6c138fb5793e2875002e7de3f5c3ff7e83ad27d111c848b7e6e2e5ad5f28eb7c363f95f960cbc421336ce985f946b0515b1bdd3a832c3fe903f7b44e20c92ea80826fbf97e2a4fcaf2db1a08698dd62edd0a84589d7462c447b4a896fe00860042496bd51b1925cb79cc3b829016a4c7e62790f8058c546f2145aaaef4d4b1e273ff61300f8008e946b622f60e505f5f6290d51eb997d20fc3fbb3e99edd68ff5cce9e8c283881c364ff215cb50045e60f4a7ee45b6c9d86447f38141d342dbc5308f8c66efc47f7c45f6d25e6564309a862db90f4df331787ecdd89d3aaa46053e29f102624ddfe80e8a3f99287cec19fa83e44d557c0441: +5d66ceb7c6e58cac91e288279170e818e787180c6b42dfa168787dd07f809fa4efc9b35db81f346198a7acc69f65fdfbf4c22e68dd7612e3b8ec68d378553b8d:efc9b35db81f346198a7acc69f65fdfbf4c22e68dd7612e3b8ec68d378553b8d:94d72f6dec4f7c9206b41510ce71a02955604f3c5de8e447d5871865a75898a4d207a26cf33d10caf05a0b6ed0d389fee9ed49275098a88e1c0d8304e81b4074214c7a5ce157eb2617ef04e1324ba942129faf32c31cb4aae4a5916c750808726856f7180e5797ede44362d747d70cec159d3b6acec63a514c7ef31b2ecd16db7fe68ea9c5ead9d870921800348f695412f3093e61985a31eadb79b59d91dd9a37f8d4ef7a5ddf223d4b24774c2e44e3f271ffb8500d595381b3df2e8e6b79ee65535a519a43eaa5e52b256c2643305e3170cbe57606a0545f8586565cfb75bf5e9564c62af05f15ee6e62afeef8c2c7a9dae235c9edd1d7c25cf49adc033ee7b583f518bc168ea48836b50ffedd2032b3f630cc56daadd513ebda864823610fc67a72b9a7d8117105c1c71d85a96b1d27a441fa1e7c6cf80233a49fe0e76a40278d06e34347d87be77b98ded5e2a3ea1afb13bee1e6cd6ca63be54fcf88a20ccb7a9fc324bf6143201b44483bcc964033dab71cf8f2a591fc050d5724e95aa50d32896eec0f3b34311d2a9934e9f852977e253f15304cae2416c2c4fcd8f1fecc3f1f64bb79759929abb0e8e8f5f7293d691af22abd3b2a6770b0cf144608f2d62cc7e52bfe333b2ed2de39b99afd37e3acf07eda37ddf0df029bff2ec22544b60bd7db238df1975ffa0075a82abd8d6b05b267180b870e21abf36981ae7768de53993b304f1c5453872fdfa8edad45f8001aa0e7342b3b58ec0f389dcbc271fb0f9000628757abba58c057e1a0899f6faf15f3740f3143f5c0b7a9159680de8c557266441b3b01caac12ec278f5a1025df53edb6134c96663a9666ae3baa90fc835111ef051bd912f67967449113b6a85f71df8c6037724eb8fc7d8319bc0385be9b0e99e95f9aedcae8d45a514476f05bcd7235c013ebc3aea9123c67aa6f3b79c85ea5db159eefadfb75a50ac6b95b496b5572581a76112ff6db263fc14c5818aad5bca3b2cb3ac8116d429482781e06f61e7563e6505e51c8ff998bf84aedb5202e2f9ff4c2689820296cc69603091b8b818fbeb2af5f4c57060d98c1a904843a70bf975b3c3ca6031a4cad5b4bbfba7e9b47491ab740d9ebe41d768810cb8cc51a937f7e3b22e3cf07ceae0ce20831495afcdd8c1a98:6ef264abf8b0e5c2d793b2c75279614a39c775eb2bcc0891067abc61f6d644a69ff8f814a30522cca90536f012c6283a76c32b89eee1bd9a4336f4fddac8dc0b94d72f6dec4f7c9206b41510ce71a02955604f3c5de8e447d5871865a75898a4d207a26cf33d10caf05a0b6ed0d389fee9ed49275098a88e1c0d8304e81b4074214c7a5ce157eb2617ef04e1324ba942129faf32c31cb4aae4a5916c750808726856f7180e5797ede44362d747d70cec159d3b6acec63a514c7ef31b2ecd16db7fe68ea9c5ead9d870921800348f695412f3093e61985a31eadb79b59d91dd9a37f8d4ef7a5ddf223d4b24774c2e44e3f271ffb8500d595381b3df2e8e6b79ee65535a519a43eaa5e52b256c2643305e3170cbe57606a0545f8586565cfb75bf5e9564c62af05f15ee6e62afeef8c2c7a9dae235c9edd1d7c25cf49adc033ee7b583f518bc168ea48836b50ffedd2032b3f630cc56daadd513ebda864823610fc67a72b9a7d8117105c1c71d85a96b1d27a441fa1e7c6cf80233a49fe0e76a40278d06e34347d87be77b98ded5e2a3ea1afb13bee1e6cd6ca63be54fcf88a20ccb7a9fc324bf6143201b44483bcc964033dab71cf8f2a591fc050d5724e95aa50d32896eec0f3b34311d2a9934e9f852977e253f15304cae2416c2c4fcd8f1fecc3f1f64bb79759929abb0e8e8f5f7293d691af22abd3b2a6770b0cf144608f2d62cc7e52bfe333b2ed2de39b99afd37e3acf07eda37ddf0df029bff2ec22544b60bd7db238df1975ffa0075a82abd8d6b05b267180b870e21abf36981ae7768de53993b304f1c5453872fdfa8edad45f8001aa0e7342b3b58ec0f389dcbc271fb0f9000628757abba58c057e1a0899f6faf15f3740f3143f5c0b7a9159680de8c557266441b3b01caac12ec278f5a1025df53edb6134c96663a9666ae3baa90fc835111ef051bd912f67967449113b6a85f71df8c6037724eb8fc7d8319bc0385be9b0e99e95f9aedcae8d45a514476f05bcd7235c013ebc3aea9123c67aa6f3b79c85ea5db159eefadfb75a50ac6b95b496b5572581a76112ff6db263fc14c5818aad5bca3b2cb3ac8116d429482781e06f61e7563e6505e51c8ff998bf84aedb5202e2f9ff4c2689820296cc69603091b8b818fbeb2af5f4c57060d98c1a904843a70bf975b3c3ca6031a4cad5b4bbfba7e9b47491ab740d9ebe41d768810cb8cc51a937f7e3b22e3cf07ceae0ce20831495afcdd8c1a98: +62ed8682bd3ab3966eba3bffb775a318a03d99931979e99feb2ddbd69455a0efd32ada178b3ec7700c47dd6d365322033fe431c302b46f8d58798ed83371566b:d32ada178b3ec7700c47dd6d365322033fe431c302b46f8d58798ed83371566b:9eb13bc7facf51a180541ec1dc5f5acb148c8d5eadcd2c4ef068bcdd11b34925eabfafabfe82a284bcbaee1381152af8e5e09f037cf1bb6484ac18e37359bfaa4c87aa07d3d14ed089b053910d1fa473f7bce143e2a59c4daf99b6c6e4e9291d97c864712af3eaba53ce2517a4f75cd7ecf278f34e22b7dffd088fa5ecadc0dd22135e42a536c684f2195d315f6924571e463f5cfc11b9f9d05a7ea11b98a169a1e39360973c50ad45c7491b57138ec050f43cbd5d17eb3fe0013e3d28d526054e07633152246f16554f3054749eea687b9c371b409cd3ecefb111a1d600407344e6d6ec38c60f6e545a92382e46c4d113125dbe5b9826e127f10181a35acfff28ab3764ca7f238ff479fdbc45b7a2ad0ff538c8acd0018d4470febcc6a307651cb5832f326b19241be9867e4eca6ae36f0e2d83fd77b97202b364716e36d1895a36853e7e76e88f62dbbf7726c2180569c66673837ad72ff936cf0e2fdb9ec6afcc79f8829e157f952288f4e00d0410a72253bf605eddceb01440dee5dd32b5a803439f038c06af1c90b27b5fe9843c27ae76609cbf832835c0e3c4bb59976ccede448786d91e438e0775c06a92d0f0b8dc0ef68260f7dd9e6871c4d0c0c09463852615218516f4a6debfdb46273b283382cd9ca744abf9fd439194b8cf1bdbb3175ca9c57a1c373c41fce92bd5fc012b19a0698aef37baf806ae09add8cb972a9ef9a7a5a9b1fd9a41d854c30cca1396140e20c2b98654fe6e511b626a43915b22fb2dad747ba7fe7460d8cebb2006fea19b3284b09c06a6f52f179a32beb56357b929a659f0fe6a26b697033def58ba603f430f74aa35070981db74ccf19190a1fb05144ec0a09a51e54765069730b09a7a2331ffb3de2a7e02c5e184da4013dfe937c371117524f7b210ba60e2692dcdcef36ab227b4c4f02a9f488972b847f0d6b59d02ee54fede8821db6cf731cc8ac895350ac5cd4d6baa3ad036f06f20d10a140c4ad3d10ca985532e3160462773385a2eb5e464d528e1e59c29f66b3de59e9ea28af3f97bfc5589035752a5a5523decd2dff01fc00ff31b30152ff5dafa331c6ab15873af41aa960aace7d2cb4f95c23df44b9e6c6e2f86788a872fd3a5cbe4acc95810daa09dcc1df933465ef040c53d9d959f9dad:3da8d14dc4e71fe6c32ede463788e41b826b4e2160ba10c95f1c8a2749aad8f12e98ae2468303baf6908bdb35ef38a5ecd77741e72ee3a427fd904dae66fcf039eb13bc7facf51a180541ec1dc5f5acb148c8d5eadcd2c4ef068bcdd11b34925eabfafabfe82a284bcbaee1381152af8e5e09f037cf1bb6484ac18e37359bfaa4c87aa07d3d14ed089b053910d1fa473f7bce143e2a59c4daf99b6c6e4e9291d97c864712af3eaba53ce2517a4f75cd7ecf278f34e22b7dffd088fa5ecadc0dd22135e42a536c684f2195d315f6924571e463f5cfc11b9f9d05a7ea11b98a169a1e39360973c50ad45c7491b57138ec050f43cbd5d17eb3fe0013e3d28d526054e07633152246f16554f3054749eea687b9c371b409cd3ecefb111a1d600407344e6d6ec38c60f6e545a92382e46c4d113125dbe5b9826e127f10181a35acfff28ab3764ca7f238ff479fdbc45b7a2ad0ff538c8acd0018d4470febcc6a307651cb5832f326b19241be9867e4eca6ae36f0e2d83fd77b97202b364716e36d1895a36853e7e76e88f62dbbf7726c2180569c66673837ad72ff936cf0e2fdb9ec6afcc79f8829e157f952288f4e00d0410a72253bf605eddceb01440dee5dd32b5a803439f038c06af1c90b27b5fe9843c27ae76609cbf832835c0e3c4bb59976ccede448786d91e438e0775c06a92d0f0b8dc0ef68260f7dd9e6871c4d0c0c09463852615218516f4a6debfdb46273b283382cd9ca744abf9fd439194b8cf1bdbb3175ca9c57a1c373c41fce92bd5fc012b19a0698aef37baf806ae09add8cb972a9ef9a7a5a9b1fd9a41d854c30cca1396140e20c2b98654fe6e511b626a43915b22fb2dad747ba7fe7460d8cebb2006fea19b3284b09c06a6f52f179a32beb56357b929a659f0fe6a26b697033def58ba603f430f74aa35070981db74ccf19190a1fb05144ec0a09a51e54765069730b09a7a2331ffb3de2a7e02c5e184da4013dfe937c371117524f7b210ba60e2692dcdcef36ab227b4c4f02a9f488972b847f0d6b59d02ee54fede8821db6cf731cc8ac895350ac5cd4d6baa3ad036f06f20d10a140c4ad3d10ca985532e3160462773385a2eb5e464d528e1e59c29f66b3de59e9ea28af3f97bfc5589035752a5a5523decd2dff01fc00ff31b30152ff5dafa331c6ab15873af41aa960aace7d2cb4f95c23df44b9e6c6e2f86788a872fd3a5cbe4acc95810daa09dcc1df933465ef040c53d9d959f9dad: +4e57f0311fff0e5d538849b1216f695b1a5277941708204db2f0c15b3c73c82ae3371fe236ad2f6f42f9e1fa4e1eda2c3e29c36c8ad2218a3c037982f0b579ec:e3371fe236ad2f6f42f9e1fa4e1eda2c3e29c36c8ad2218a3c037982f0b579ec:052a1f41ebfd4bf65efb0ec8e74dd7b3065e9c482c49b99262e6dfa8407d9e31ed34d229ba41fc49a94a1309f990a99cb9902fb84f4ede91bb64714564a913d574d4a3c286f0a192a78ce2d55aae5c9fb057ff36120018b2a8b54d98085537ea64aea999d5321c7880b36ab43018ea2c92a5e68350d3de8526e2c8bc9141f4349a18a34f21de0abbf2930987567f0aaf8eb19145580d71306ce8a69e79f8eea26cfa0b8beb49cc5aa2bc77b797d4f8d50326ffb937399e94fdec85e192f1272a80e9a0ebbaf5d01f1b97060802bd4af34c0f7d7e98543f9d66d60e0e6bc0bf9c990be31eea1978ffd16733a8abe49558b3add0dce6defd64dc043f1519b1e9be66e06e41ecab168c8339a85e0b913818644ea7c5334468fd7196a01e1d4ce8dd1e7ee313dd5350b8dce4f5d7a6ac09857c4d3d0f10a3d9062609754592ad1077b2e2096fc9e5b1978c98b5660ddf51b46ede9f9dcd41b2ef44e79f6daff7d3626870e2243cafb2f4367939109ed9c01484b79eaa30a1891ea18f984e161dcdd1bda37134bf6735d2b2149b4898dacbfda61e6002d72a6fc5d21f1098213231132d56df68d6a9bfdf4eddc0524db8fd8f248852049a6825a5edd2360c009af24f0a94c5079ddf6fe796945ff984aac36411ce80d987c6ed67b6b0ddb6d417f6e809991e729d147dd0d21a093241363cf4ef3b8e3ba02d486633b6b217f5493e2e432b8c2e27d00c5b56c9b65f9aed49ce93d77e7d0bf5f92f92f5bb4b595d66f887a4880133f970463ab8b7f3d8c794c0406e88e3eab9ae65f1a185d6e39e2dd6abb8a93d2ac4b9208398dab89dbc07a41a50264026412da022b58f489d4dba31fb882fecb1ff8ca1820dda1865af1551e46cd618b44c4e6eb3037a9333fdccef4b895189e4390e93145d264ca5f45202a3eb2853593feed6c66dbb288ff3a3c0fa832b2aa7e529b5568897b3149402a907e741e1011ce0731c915f91446aa0d5caf0595f1816434fa4576db3bc31e10cc2af33f613f03ca7b9491a0a340525271ab537f62a11a84da01c7f5581ad5738c372b5335bab9b2b9dc2fe91e933304d9401ba8e1ce8dc55c4fb466b3a8ed7f53a122b8381d8f29047d7264d06fb51ec3e70071f2736a4e7e1537a52fa256a04ee86fad27ad2d28a9b3629:4fdc7b6e2827f64ba3c033c7fb6d1b35dd680f532999a0d77aeb276c31bd9e39c670978be47243c113223a57aa10233150678b40db78591c04d08df57a70a209052a1f41ebfd4bf65efb0ec8e74dd7b3065e9c482c49b99262e6dfa8407d9e31ed34d229ba41fc49a94a1309f990a99cb9902fb84f4ede91bb64714564a913d574d4a3c286f0a192a78ce2d55aae5c9fb057ff36120018b2a8b54d98085537ea64aea999d5321c7880b36ab43018ea2c92a5e68350d3de8526e2c8bc9141f4349a18a34f21de0abbf2930987567f0aaf8eb19145580d71306ce8a69e79f8eea26cfa0b8beb49cc5aa2bc77b797d4f8d50326ffb937399e94fdec85e192f1272a80e9a0ebbaf5d01f1b97060802bd4af34c0f7d7e98543f9d66d60e0e6bc0bf9c990be31eea1978ffd16733a8abe49558b3add0dce6defd64dc043f1519b1e9be66e06e41ecab168c8339a85e0b913818644ea7c5334468fd7196a01e1d4ce8dd1e7ee313dd5350b8dce4f5d7a6ac09857c4d3d0f10a3d9062609754592ad1077b2e2096fc9e5b1978c98b5660ddf51b46ede9f9dcd41b2ef44e79f6daff7d3626870e2243cafb2f4367939109ed9c01484b79eaa30a1891ea18f984e161dcdd1bda37134bf6735d2b2149b4898dacbfda61e6002d72a6fc5d21f1098213231132d56df68d6a9bfdf4eddc0524db8fd8f248852049a6825a5edd2360c009af24f0a94c5079ddf6fe796945ff984aac36411ce80d987c6ed67b6b0ddb6d417f6e809991e729d147dd0d21a093241363cf4ef3b8e3ba02d486633b6b217f5493e2e432b8c2e27d00c5b56c9b65f9aed49ce93d77e7d0bf5f92f92f5bb4b595d66f887a4880133f970463ab8b7f3d8c794c0406e88e3eab9ae65f1a185d6e39e2dd6abb8a93d2ac4b9208398dab89dbc07a41a50264026412da022b58f489d4dba31fb882fecb1ff8ca1820dda1865af1551e46cd618b44c4e6eb3037a9333fdccef4b895189e4390e93145d264ca5f45202a3eb2853593feed6c66dbb288ff3a3c0fa832b2aa7e529b5568897b3149402a907e741e1011ce0731c915f91446aa0d5caf0595f1816434fa4576db3bc31e10cc2af33f613f03ca7b9491a0a340525271ab537f62a11a84da01c7f5581ad5738c372b5335bab9b2b9dc2fe91e933304d9401ba8e1ce8dc55c4fb466b3a8ed7f53a122b8381d8f29047d7264d06fb51ec3e70071f2736a4e7e1537a52fa256a04ee86fad27ad2d28a9b3629: +39f0556b1c5dcab387104181bb304de0cf815920b972e871d5f0fb416d8e616ad85fb76e78c3d5bb7ca6b05b310191821a4a7d2d9bdf02292cc7aea5642e4819:d85fb76e78c3d5bb7ca6b05b310191821a4a7d2d9bdf02292cc7aea5642e4819:a8d034e170fc22b57a44aa6269ed1f01cba801f398df1adfe7df044d5fa468bbfa8af4749ab50d24d62e313ac0e73a64b4282b74626af2b4a4b54c274e5a6bc280b6dc25dcfe07814c9c816d2f9e36c05b9bfedff7c6b03cddebd4735e0993d3c3fdc6540443c6005e900b4035e1408a85016aa1b89202990e5d84ed9981c29b77206d7c113052a2029812c6ea13aae8be0aca7a3306bf617242298e68becd0d5d16c8887fd1950b7785a46bb022b39f7607cd8913718b3017fc3f86d6933f75eec5191ad1f1989a8d261786f56be4a988370db82961a9fcc953542e51c2e086db0e02b4fc346694abd9059d5b11722647669e7f17b745a60b02f7339fcc99bc35d59fd0b98b60c314abd4bf8aa4b7eae09dd0097acb9189f02cf85a251ac92aaf691b15cd4a33b58d7663abd0b0444333044af5ce20fd71cbaffc0d29835819f49293fc26e7f9787fc368c4d35cae92747f21ca1f3efd87a0d8104199416482d07bfec1281c66f565285bf672d5e7486400660c017555e9fa2bf6a4e7027f0e7e5f443ed658b75b590612abde0d80d1a26cb8bde76b996eff6a74e3dafc59eb1b584f4597a239cd839fa1f1b7bda1a24d150c4e24b91cec01ee53a3ac852a912de195a3c29dd7079aa7e88aa81e9d31b8fccd435eda113c3f82458b7f7933572b776753c92240cc036158a4ba0e56efed53ecb53fc093fead14343485ae5d9105bb163f262514e48be74159c9fabcb71d1a4280d9ed70d7e42b75f7fdadd02d69198f5f465bf604cb4254417bac3714b3a99e6f1acec9e3b3d097f972fbc36f2eda3926d56112d4e9097d89bdc35937b9a3158e7cdd5da401e180d3ede6b1ff02864192eb729781534f4964ddf2af11800d8b5b6d01b209aa3369366c19a28c79a87d2174ec22fb1489a6755c348a996d0aa56e0f60d58e26befa23a86bef4e3529512e30a9d1c5e4885018cb97aeb7c93c5c41caa34236575c226f3b235eddba364e285b6e352707bbb3b339bbf2a63a9cb9bd333a77e79bd58a48e14ce5886ed0cd07c2d165a81b5e6a31a8ae7806bcf2e0c4ec29a967725e577f1741ee68f345f5f7ab0fad31c8b4b18b431c4977d5c584004b45f7cd1961affe8738e24c382610efe998353d7ebaf919b279bbb691c3052b8b2c5f09808ef3a6:0166afed5a8f7c3f7ad6f3fdd2938eff00898eab815c5455ac90fb51f6e1854f0c0753194b7629594cc1271b003431221c574b0c0d19082feeda51b084ae5e03a8d034e170fc22b57a44aa6269ed1f01cba801f398df1adfe7df044d5fa468bbfa8af4749ab50d24d62e313ac0e73a64b4282b74626af2b4a4b54c274e5a6bc280b6dc25dcfe07814c9c816d2f9e36c05b9bfedff7c6b03cddebd4735e0993d3c3fdc6540443c6005e900b4035e1408a85016aa1b89202990e5d84ed9981c29b77206d7c113052a2029812c6ea13aae8be0aca7a3306bf617242298e68becd0d5d16c8887fd1950b7785a46bb022b39f7607cd8913718b3017fc3f86d6933f75eec5191ad1f1989a8d261786f56be4a988370db82961a9fcc953542e51c2e086db0e02b4fc346694abd9059d5b11722647669e7f17b745a60b02f7339fcc99bc35d59fd0b98b60c314abd4bf8aa4b7eae09dd0097acb9189f02cf85a251ac92aaf691b15cd4a33b58d7663abd0b0444333044af5ce20fd71cbaffc0d29835819f49293fc26e7f9787fc368c4d35cae92747f21ca1f3efd87a0d8104199416482d07bfec1281c66f565285bf672d5e7486400660c017555e9fa2bf6a4e7027f0e7e5f443ed658b75b590612abde0d80d1a26cb8bde76b996eff6a74e3dafc59eb1b584f4597a239cd839fa1f1b7bda1a24d150c4e24b91cec01ee53a3ac852a912de195a3c29dd7079aa7e88aa81e9d31b8fccd435eda113c3f82458b7f7933572b776753c92240cc036158a4ba0e56efed53ecb53fc093fead14343485ae5d9105bb163f262514e48be74159c9fabcb71d1a4280d9ed70d7e42b75f7fdadd02d69198f5f465bf604cb4254417bac3714b3a99e6f1acec9e3b3d097f972fbc36f2eda3926d56112d4e9097d89bdc35937b9a3158e7cdd5da401e180d3ede6b1ff02864192eb729781534f4964ddf2af11800d8b5b6d01b209aa3369366c19a28c79a87d2174ec22fb1489a6755c348a996d0aa56e0f60d58e26befa23a86bef4e3529512e30a9d1c5e4885018cb97aeb7c93c5c41caa34236575c226f3b235eddba364e285b6e352707bbb3b339bbf2a63a9cb9bd333a77e79bd58a48e14ce5886ed0cd07c2d165a81b5e6a31a8ae7806bcf2e0c4ec29a967725e577f1741ee68f345f5f7ab0fad31c8b4b18b431c4977d5c584004b45f7cd1961affe8738e24c382610efe998353d7ebaf919b279bbb691c3052b8b2c5f09808ef3a6: +bab3ff7a4448d8a03d8acfdb913f77fe77804395c3e54ec235117927e32b50d554975e35e5b1d0323f2d6fb5c6158bf6654b084f76bbdcfd72349229e8e4a6e8:54975e35e5b1d0323f2d6fb5c6158bf6654b084f76bbdcfd72349229e8e4a6e8:b647b67cf01c2cacc39de5969e199be6d9320167a4cebbf1625950b1e6b7adf5ca24d1349568865fbbfd90f513f05f79f70a63a23873dc7a195d4b285a08f30ee061d0b8e6b4d6bf9b2ecf2c69f3d5a07a6730537cca4a4e4c7ee684702bff883fab8bcaf89311c5498bccb5a0f7c8d49b54f482fffbca6e7da262452ba59a57a6879d81b73cd7adf72a3be28a373cd63310408461c21b907f63e086b292ff02833e8a2f46adbd671d02b03a69aca2e11d287c522a954520442ecefaa905dbfcc8254c58c3954a89bf56cbe01ad5631971eb39eb432a854e691929df7e48b900ca6e740accf578b31795b49a6ca774bd8b993106a9c4948c18714948315990a5f191692420f289328ab713ec19b7ea894d16e6476100871cf3168e4f935b5505d1ed5b0aa29be36fa3a346ac3e76f143c46ca69123b79c36399a0d2ed302772494adf442bbafbc4d01532692c7859df04d2ca78ba55d77fdf3e5ad993786a24cff2199bb49387873cc414b4cf1137abb7e94ae3ddbf97f534a18fc5ae58523a3cc52283dc7b016f31cd6557981c5076c774f303a47c427870e207ed8bd66640ff092db503fa124bfdcf020051dadd106dd245840b31910b8a9060d5986f02b60aa5e33b4d7550912cdc5776c772aac93ae19c73b7ecfca389e627681a8781eb47d84e93460ba891d3ff6eadf8f2a903c383474beaa42b90e032236dcd898d02a40efb44e47ead52b75b09c7da1cd6a2dfd4d1c0452de69f6acac1a68dd78daf972ae260821e2ec522fb5749bebe0adb452bfa4faa1e97911c1299f16568d68eef405f4b1cdacabed59f7b0fbceab719a34b299f58a4ae8154f98f4d9f4f140b1f085006946725e7c29bb0bc6ccf2534497c61d4c1612624a61d70d26c3efb7d7c351848657f7f8eebf8b990747740e6f910c97cef150375765c8c0b3b449c0d09d66f008e67cfa76ea2b6808b6fe632eafe0587f37e36be98dcb17a3f4a15b65a9f6fcf9642b52522077b1fb4cc3c08df4b467ca716db16b737f782cdf387170a5f1f6a7ae0ab3f5b7c585e3b0655a6456a503595ce8eaea2537855e7f0d5061bc29b4e67daa82463c190e9fddd52f8322ddb4e0f26b68778228eb57e1a185b7025da14987d44baa767b22ee7f4c84591032e88ec12eb8c5a4b9e157ec:d6b4135fc7acb3d7cdf987896d91b8a90db584d8933a6f3029e3261ec1c390cbacfaafeff443b6da4fdb1d84c64a54560feffa2f1c7a91bde9730222923b6703b647b67cf01c2cacc39de5969e199be6d9320167a4cebbf1625950b1e6b7adf5ca24d1349568865fbbfd90f513f05f79f70a63a23873dc7a195d4b285a08f30ee061d0b8e6b4d6bf9b2ecf2c69f3d5a07a6730537cca4a4e4c7ee684702bff883fab8bcaf89311c5498bccb5a0f7c8d49b54f482fffbca6e7da262452ba59a57a6879d81b73cd7adf72a3be28a373cd63310408461c21b907f63e086b292ff02833e8a2f46adbd671d02b03a69aca2e11d287c522a954520442ecefaa905dbfcc8254c58c3954a89bf56cbe01ad5631971eb39eb432a854e691929df7e48b900ca6e740accf578b31795b49a6ca774bd8b993106a9c4948c18714948315990a5f191692420f289328ab713ec19b7ea894d16e6476100871cf3168e4f935b5505d1ed5b0aa29be36fa3a346ac3e76f143c46ca69123b79c36399a0d2ed302772494adf442bbafbc4d01532692c7859df04d2ca78ba55d77fdf3e5ad993786a24cff2199bb49387873cc414b4cf1137abb7e94ae3ddbf97f534a18fc5ae58523a3cc52283dc7b016f31cd6557981c5076c774f303a47c427870e207ed8bd66640ff092db503fa124bfdcf020051dadd106dd245840b31910b8a9060d5986f02b60aa5e33b4d7550912cdc5776c772aac93ae19c73b7ecfca389e627681a8781eb47d84e93460ba891d3ff6eadf8f2a903c383474beaa42b90e032236dcd898d02a40efb44e47ead52b75b09c7da1cd6a2dfd4d1c0452de69f6acac1a68dd78daf972ae260821e2ec522fb5749bebe0adb452bfa4faa1e97911c1299f16568d68eef405f4b1cdacabed59f7b0fbceab719a34b299f58a4ae8154f98f4d9f4f140b1f085006946725e7c29bb0bc6ccf2534497c61d4c1612624a61d70d26c3efb7d7c351848657f7f8eebf8b990747740e6f910c97cef150375765c8c0b3b449c0d09d66f008e67cfa76ea2b6808b6fe632eafe0587f37e36be98dcb17a3f4a15b65a9f6fcf9642b52522077b1fb4cc3c08df4b467ca716db16b737f782cdf387170a5f1f6a7ae0ab3f5b7c585e3b0655a6456a503595ce8eaea2537855e7f0d5061bc29b4e67daa82463c190e9fddd52f8322ddb4e0f26b68778228eb57e1a185b7025da14987d44baa767b22ee7f4c84591032e88ec12eb8c5a4b9e157ec: +486c7b436c1d43d6b703512283c166dc863e5a33802f4ea65fc738778902d014b5dc947d64337cae82122bd68cc80840596de3be56cbd0c833af3faa3adc3776:b5dc947d64337cae82122bd68cc80840596de3be56cbd0c833af3faa3adc3776:af036053672dcf3aa26e28ec6aa642ce284b896c69887dfdcf0824515eb0848d9d970ca272df77a86b3ff6ddaf3cbadd3ab6283bc37cdf7a5607d5dfc7cf96329299cc53edbbe657fdfa2ca24467050a0aeb8cffd7d33d543ec2c191cc0bce89ac37d33293b1888ccb76c28adc671a4935a846d907e4add0110febbee5aec80f9d2ff74e2af4fdbebbcf49105a6469d7380006b2ca44364814454e445e36dc0012f339c96854f836442a05a50bec907327f74ba9f6fd790ff0ad3783d297bdcca76460783703eb5f2b1f51b0a740ce7a8f00a387e3636270a971fa8f15b4496730d88add807a7f7e987cd41595a2e7435df5195576a35f5e91b2fcfac94ed5d77663783b61e6671d34838b6b5644fbc1c539fe159b7792db967e8352618ddaca0cde73437b59e7801b49eb4609b10577ca2692dd6f9d5e9d4b5e5e62c5913e7b87e6b347be6153b17199c916a13f8a885b378ef09e13cae4d8b079d7d5cb9094199b0f20533c90083bc3acb2667697eed22e3670abb4a553e995c9dd9594e592391a0004b6556544f35612c4971359577c476382ca53b3f262a5e33ed26eec809f4fdba4898a113675cb6af717db62579f3980b21463be029cb4160fe5d257c46cd6664f9861ac50fe05c144057dce2f8df1532aa7af589f41270601cef06bbe4f35c31c782bb3cfff7d5ab64a14ec417361f1d32cbd38b6bd0e02505d1416302b8505ae2a96e8d5339c346c2b0662d350259c50c5e48795914e6f88e97c811c393bdf9aec7ef82047ca28ee971c175c27e36e109727960ddf1a1b976ab44f4851607bd966808ac46d54003128297f5f4487108d6a02e7a16413d2b75ecb42fddfb669c801d23de50a6f7bf658f753c6b2b3b47c0640105d0a801b32a1943cdc15c886555eb75bb7927b93c35c5be1f98b196caac2dad991b1044ea863944d54d883abc3c6de66ed868ee84bcf9c34ccdb80fcd9cc0402747732cd630bbfa3bbe8b038dc1dbdaf436d9ac00c02d528ece2e791ee312a868feb2f587ca44db5731384fa1831142061b2ead2b80c66bd2fa5dccabe6a25f2a493feaacd231d2f409646b942a578545ea4feea9a73473f79dcf13e0c9f1b49fd8912ec487328045bd0fa228922ee6e973e61f6e93365296578dcc21c361479ee2d24879f2e9b:31f95cbb7463b87528654227bb1397bf1065b4f576808078207dfaf06d124b41f4c318f4a9315a66085b9e568a71e414ed9414517310c699946db0c976285207af036053672dcf3aa26e28ec6aa642ce284b896c69887dfdcf0824515eb0848d9d970ca272df77a86b3ff6ddaf3cbadd3ab6283bc37cdf7a5607d5dfc7cf96329299cc53edbbe657fdfa2ca24467050a0aeb8cffd7d33d543ec2c191cc0bce89ac37d33293b1888ccb76c28adc671a4935a846d907e4add0110febbee5aec80f9d2ff74e2af4fdbebbcf49105a6469d7380006b2ca44364814454e445e36dc0012f339c96854f836442a05a50bec907327f74ba9f6fd790ff0ad3783d297bdcca76460783703eb5f2b1f51b0a740ce7a8f00a387e3636270a971fa8f15b4496730d88add807a7f7e987cd41595a2e7435df5195576a35f5e91b2fcfac94ed5d77663783b61e6671d34838b6b5644fbc1c539fe159b7792db967e8352618ddaca0cde73437b59e7801b49eb4609b10577ca2692dd6f9d5e9d4b5e5e62c5913e7b87e6b347be6153b17199c916a13f8a885b378ef09e13cae4d8b079d7d5cb9094199b0f20533c90083bc3acb2667697eed22e3670abb4a553e995c9dd9594e592391a0004b6556544f35612c4971359577c476382ca53b3f262a5e33ed26eec809f4fdba4898a113675cb6af717db62579f3980b21463be029cb4160fe5d257c46cd6664f9861ac50fe05c144057dce2f8df1532aa7af589f41270601cef06bbe4f35c31c782bb3cfff7d5ab64a14ec417361f1d32cbd38b6bd0e02505d1416302b8505ae2a96e8d5339c346c2b0662d350259c50c5e48795914e6f88e97c811c393bdf9aec7ef82047ca28ee971c175c27e36e109727960ddf1a1b976ab44f4851607bd966808ac46d54003128297f5f4487108d6a02e7a16413d2b75ecb42fddfb669c801d23de50a6f7bf658f753c6b2b3b47c0640105d0a801b32a1943cdc15c886555eb75bb7927b93c35c5be1f98b196caac2dad991b1044ea863944d54d883abc3c6de66ed868ee84bcf9c34ccdb80fcd9cc0402747732cd630bbfa3bbe8b038dc1dbdaf436d9ac00c02d528ece2e791ee312a868feb2f587ca44db5731384fa1831142061b2ead2b80c66bd2fa5dccabe6a25f2a493feaacd231d2f409646b942a578545ea4feea9a73473f79dcf13e0c9f1b49fd8912ec487328045bd0fa228922ee6e973e61f6e93365296578dcc21c361479ee2d24879f2e9b: +a6e6ad2c379c6fccadb4a49b232a9142618ea30103c33c226ff628bcfd81f426f7c4323f5c419d9b3f34a8eb42ae7f1faa2333079030c5d64f9ffb1e9b16002d:f7c4323f5c419d9b3f34a8eb42ae7f1faa2333079030c5d64f9ffb1e9b16002d:2e857676a5bb1c6e9e94507f83c60a67f547c5de9e94566b197a6af6cf4752e93dbdef6b9f66d1febd957e42a7f5ad64ef1dbcc4fe69ae9525d1a4de67054c88f29c0647bacf8b82f321ff99fe9eedc992ed34c1177fc5421227ccac10feb9ced4082f5658da63714723979737e7dcbfe2e8b5d50f91dfca83e7f95f35d1ad8dd51144502f3df672432611f0e766a90dcc2a5739c805d95fe5b041de9d7fb47b4404afc803a3bd4804c7817ebc5bdfef8add9e250b50966ca8939b22b3c6ff936eaa659a240c0c848b810acecf6181e0e4db8e4cf8fcce7de559cbe8afa9db8499570911a3887e850e509cdb70debc3477d12175014f79f81ba113d0b7b335118f85cf59996f806758eb903cc450f52fee102efc01441e9ae5fae74c231dfd85eb6bad17d6b70e938584facb2172cb03bd5ea07b7f0d371ffa351c0ee4efe9ba4a3fd543874655e7d39c53ae86329802e5c385e9283a2973cab8cf7ac7ff0f91d1d48b58abfdad658d812f07881676bd226bfe957d7df30c4130a448354a6b94405a411650a9c8fc851155ec5a8a3e3b67ae0c4b5cb89bb73fc82974be62da73f0e23092937d405ba4af6cab9465ea43a6253f4457082a06ac12b75e88ec684487f9076373fab8892859d8e8ba431423aa805a220cbfda431b32b1e03121f7fd4de18591f2505cc0f5b2b1a7605fbcc63757b07e299fef5a2b7365230c2e92a25962c2e8012ad3fa9ee94882709625ba68c7b213664ae2532b609d7c9aa0e83d493dbce7632f35580e06d3111ced320dd0190441f62d9e35f50de59c272fb00f568a00b0746c33a9bd2490c074b91cddc487ef2e45a0f030e08fdc1817bca8a9ce29d29279e755debc28dfadc3c4d1b458486e3c8d0c4318e7e6f9eb5a3653b3f7c49507077cd5eb81f10b88107cc0f9316932abe9b64e8886d06856a85be63b0c2b475c0afcb0694426860fb24b5c17ab6ab7733d5e641be74fd5f6a1ff18d2f9a42770fb30750f56f4854e38d58aef18a2a61cbfb49ee576ed97737bc28df3268a334175513d97af009cbbcfdfad5039d69bb46f708867d9b3ce0bf2f569e3cfbcf6136f8870d25208b21a3edcb73393dfcd4172c1402c41f36e3f82a4ea6dcd891686ba66e14320aa0e22ba0c1ef033d662cdb860cdfa3a40f6cc532a08:07d9fc244fdab00159ebecc5a00883453f08310171769d297001e877010e3eced9fb60ec91cb4d88e7ba40c530b1f9237978ccd96d5cba9e4fa27e2a0ad9d60c2e857676a5bb1c6e9e94507f83c60a67f547c5de9e94566b197a6af6cf4752e93dbdef6b9f66d1febd957e42a7f5ad64ef1dbcc4fe69ae9525d1a4de67054c88f29c0647bacf8b82f321ff99fe9eedc992ed34c1177fc5421227ccac10feb9ced4082f5658da63714723979737e7dcbfe2e8b5d50f91dfca83e7f95f35d1ad8dd51144502f3df672432611f0e766a90dcc2a5739c805d95fe5b041de9d7fb47b4404afc803a3bd4804c7817ebc5bdfef8add9e250b50966ca8939b22b3c6ff936eaa659a240c0c848b810acecf6181e0e4db8e4cf8fcce7de559cbe8afa9db8499570911a3887e850e509cdb70debc3477d12175014f79f81ba113d0b7b335118f85cf59996f806758eb903cc450f52fee102efc01441e9ae5fae74c231dfd85eb6bad17d6b70e938584facb2172cb03bd5ea07b7f0d371ffa351c0ee4efe9ba4a3fd543874655e7d39c53ae86329802e5c385e9283a2973cab8cf7ac7ff0f91d1d48b58abfdad658d812f07881676bd226bfe957d7df30c4130a448354a6b94405a411650a9c8fc851155ec5a8a3e3b67ae0c4b5cb89bb73fc82974be62da73f0e23092937d405ba4af6cab9465ea43a6253f4457082a06ac12b75e88ec684487f9076373fab8892859d8e8ba431423aa805a220cbfda431b32b1e03121f7fd4de18591f2505cc0f5b2b1a7605fbcc63757b07e299fef5a2b7365230c2e92a25962c2e8012ad3fa9ee94882709625ba68c7b213664ae2532b609d7c9aa0e83d493dbce7632f35580e06d3111ced320dd0190441f62d9e35f50de59c272fb00f568a00b0746c33a9bd2490c074b91cddc487ef2e45a0f030e08fdc1817bca8a9ce29d29279e755debc28dfadc3c4d1b458486e3c8d0c4318e7e6f9eb5a3653b3f7c49507077cd5eb81f10b88107cc0f9316932abe9b64e8886d06856a85be63b0c2b475c0afcb0694426860fb24b5c17ab6ab7733d5e641be74fd5f6a1ff18d2f9a42770fb30750f56f4854e38d58aef18a2a61cbfb49ee576ed97737bc28df3268a334175513d97af009cbbcfdfad5039d69bb46f708867d9b3ce0bf2f569e3cfbcf6136f8870d25208b21a3edcb73393dfcd4172c1402c41f36e3f82a4ea6dcd891686ba66e14320aa0e22ba0c1ef033d662cdb860cdfa3a40f6cc532a08: +9b6d7e28eb051597324dceb7a18941246725e88d53ab2c34771105330cf1f4ae8872a50b5fe362f8ead1d40e2045f0d40b2e7b50b59d8090bc47ad68ebee09ed:8872a50b5fe362f8ead1d40e2045f0d40b2e7b50b59d8090bc47ad68ebee09ed:d1e1987bff65f62ad67624c6657924f5d673b7824ebe404026c0562ded3143440be637f98c9e01a6afdfa9a47dd49c7cba6e3fd23e4552f7632b14380b27cd3e9606cce350f152ab126bead0a5d3bce4d42092d934c8ca337e987e11d86cfbfbd2acc3223bd16744a927728f485372175cc694df30a73f9d33765ff014ef008d5863210338cc3482cc27ea317eec921b0c568c38ab27c4a564e802b1b94668c651e20a0b55f3a79d215fc3a0d04904010932c4cc68c2a9e7d00e5d38d82df55206bab95cf697bebc7206eedef6fd18d9a20c2cbb285b00efa769a08dab2b3abadf00d198b4f192dd44bcb91431823ae6fdf98458eca39cd29263f0999303e70dc694fe01c53a11c1d1c34c1ee5068a201dbe7e1008d764358968b402aa398549507f7bd1850800e411b1c4e28ddc04a859e179be8ad7e6670e509db027ad7e517e4425954f5a807414a6da267a764e712a998465064982d851a265ea3c4dfb74f992a7cccd9a82687fa61c322c4f589e86b8825213bfa951dae6af354ace18f073995adc95839dac0165511d61753791a53e48e3a8273d44823d2596f2a2db2e5f1ae597221ba7f3ebaf4a7b2888395002bdaff51fa54bfb979de1031404ca7789fe095d4d17f07a35556b10fe8e1417c8a6a631c2ed36cb7a0e6181776289c344814d42131a73b12faa35d77814c681a601374ba71cb9ad5315fad42d3acfc7c1d628810256daf7d8c3c9a2e5bdcfb770082fa638168958523a1c3b035dbc6d5adf26df89a7ccabed3e7dd377c16da841f13c6894d43cebb4e39022f1ccec2274445c78b3adc7bbf70d890b80236cc4468f9569c59a7e33b570e670380d244e4e310e11c392f1e334054b92c8386c161ce04109b037bd628d919dcb62da1435bf94e88b0a8846d486d16778f7a3b880e660f441fdf86e56b8aa0661f55aaece27f9ddaa0e2a22c215b040539726b9853915a1592dffeae32d7b5b67eb6205bb0bd7279f788d5f833c4066780ca0a42d3e4e1aa22bd06bb5eed89b9413771ecab644ca72d1291d00f740901a7311dc036715d23ebd9a59891628f0d87ed489502f06d75bbd11cd1602a35ee7e13335d6a144b08830e669c02e652f3f100d393ef9b4ac05321439bce6ce36ffc5abca890b8796ccb5e16303559c5d9117f0f31d:c6dc5ca1e8560015b493afe2666ccf6fefa803d8526c837fe7f123c7991427ab030d7c770e45f6de8481523b94ece97f3f161cf5b8c7aea39f5ad826bf8d0a02d1e1987bff65f62ad67624c6657924f5d673b7824ebe404026c0562ded3143440be637f98c9e01a6afdfa9a47dd49c7cba6e3fd23e4552f7632b14380b27cd3e9606cce350f152ab126bead0a5d3bce4d42092d934c8ca337e987e11d86cfbfbd2acc3223bd16744a927728f485372175cc694df30a73f9d33765ff014ef008d5863210338cc3482cc27ea317eec921b0c568c38ab27c4a564e802b1b94668c651e20a0b55f3a79d215fc3a0d04904010932c4cc68c2a9e7d00e5d38d82df55206bab95cf697bebc7206eedef6fd18d9a20c2cbb285b00efa769a08dab2b3abadf00d198b4f192dd44bcb91431823ae6fdf98458eca39cd29263f0999303e70dc694fe01c53a11c1d1c34c1ee5068a201dbe7e1008d764358968b402aa398549507f7bd1850800e411b1c4e28ddc04a859e179be8ad7e6670e509db027ad7e517e4425954f5a807414a6da267a764e712a998465064982d851a265ea3c4dfb74f992a7cccd9a82687fa61c322c4f589e86b8825213bfa951dae6af354ace18f073995adc95839dac0165511d61753791a53e48e3a8273d44823d2596f2a2db2e5f1ae597221ba7f3ebaf4a7b2888395002bdaff51fa54bfb979de1031404ca7789fe095d4d17f07a35556b10fe8e1417c8a6a631c2ed36cb7a0e6181776289c344814d42131a73b12faa35d77814c681a601374ba71cb9ad5315fad42d3acfc7c1d628810256daf7d8c3c9a2e5bdcfb770082fa638168958523a1c3b035dbc6d5adf26df89a7ccabed3e7dd377c16da841f13c6894d43cebb4e39022f1ccec2274445c78b3adc7bbf70d890b80236cc4468f9569c59a7e33b570e670380d244e4e310e11c392f1e334054b92c8386c161ce04109b037bd628d919dcb62da1435bf94e88b0a8846d486d16778f7a3b880e660f441fdf86e56b8aa0661f55aaece27f9ddaa0e2a22c215b040539726b9853915a1592dffeae32d7b5b67eb6205bb0bd7279f788d5f833c4066780ca0a42d3e4e1aa22bd06bb5eed89b9413771ecab644ca72d1291d00f740901a7311dc036715d23ebd9a59891628f0d87ed489502f06d75bbd11cd1602a35ee7e13335d6a144b08830e669c02e652f3f100d393ef9b4ac05321439bce6ce36ffc5abca890b8796ccb5e16303559c5d9117f0f31d: +7009edd0795096edc4fed55a17ccf484131e608c6d5d6696bf3376e26924959b77574bf069527145e72d3e85ce7d4fcd671a33e0a71e6bf0da7ea471dd6e86a4:77574bf069527145e72d3e85ce7d4fcd671a33e0a71e6bf0da7ea471dd6e86a4:b12c12470539547c2de6bc4eeac7b63e508ed710f35637d9fdd2dcca322a7a5071dab2b2845e30792806035c9fcdafe2783e3b677d6be5aac70b33910a2b95e8b5d59bda615935a417b7ae19a7853774e89a12aa547b4192979a01ef6ef32a40de79d680057a83a074617ca6501f59e73564927c38b58c19585a2c03659c026e4de3806d6c1ca8958dee47bcb889e76d2c3a9ab5b8b6afb2e842298056567bf9b58957415483336233ef4920fa57f496e1f0348cca20366496fab3a75bf4214ece47a45feaa1392db3f254d96a7f37402c9811140d7358b4ef8f20a298eeef904e37d68f378d33cb96d00c03109fc83fd06a876c92482f61ab7914eb7c2e5e84066e0e91e21e42e9be23df12b5c747973cb86442c32291d3d1ae719b36a62faf3abaa2053a313f625d85c51a5198571915ef8a2b199ba37d25884575ba1b72844cab4328b57fab1ec974ee8ea1df7ca9c78a4d3a03bcb0ab4169bf06a3a438d9566c6c501d8d9ccccb1ac26b4da4ae1a9d8e8b9df662821ad975c9b015fe26f6898d22ab912f0e405a5b27cfd39d657dcd92cdebe6791902713484406dddce71188731e44319381af27daf76792273b8c35251d11b836afe8b3ce9b40273f6915ebe6bc95a75bb941a429209867fba8764bf6c40db6eecb4f21747837cf6ae7fbfe36d5023df7fce2c0c3c57af2898885313c5c4bda35c7da6cb29932fb1991f62bbb080b32e2050619311ae69abb3022d913fa9eabd5d5cb4dc54d75dca638cda9af331c0cf4d2007b6ca39f655a61c01039f12a4b9782bc39aec4d22ef0093388dd7d5b56dfb8a7f9d8669004e2878dd8a6d76857c0845245068fee1c5319631e78d3785165c70afd65299301378551ebf613584c6a7620a0e3b6779f38c0940062497008eb233870868c21cccac239501b63b749a85602c28a095cafc749b0511a6c878edb3b780ea174d07b121e315a826dda6ec8dc54363e2cd2e6305a194825c0ea90efd7a9fd89cd97b99c4300bd3bf9353d82fbcceea71b4ee3f1aae9539b4cce90ca477597c174ef20f4b9f4e62d09a570d3135aabee9551fa60983958c0b7b8c3744553ee14e7f3cd103a19251c99bf6384abb60a76afc6658b80dfc5110adc4c732fe0ee32933fb284828e008887aef80f6f813340446c0217c12ee:b701b8f9a434e06d719ad25dcc54060c7986647f44f3884bcb6e5ee1d7a446cc265cec029b537da7f2523326558ac9ba34f4cc2a97cca3452e70562e7a8f5504b12c12470539547c2de6bc4eeac7b63e508ed710f35637d9fdd2dcca322a7a5071dab2b2845e30792806035c9fcdafe2783e3b677d6be5aac70b33910a2b95e8b5d59bda615935a417b7ae19a7853774e89a12aa547b4192979a01ef6ef32a40de79d680057a83a074617ca6501f59e73564927c38b58c19585a2c03659c026e4de3806d6c1ca8958dee47bcb889e76d2c3a9ab5b8b6afb2e842298056567bf9b58957415483336233ef4920fa57f496e1f0348cca20366496fab3a75bf4214ece47a45feaa1392db3f254d96a7f37402c9811140d7358b4ef8f20a298eeef904e37d68f378d33cb96d00c03109fc83fd06a876c92482f61ab7914eb7c2e5e84066e0e91e21e42e9be23df12b5c747973cb86442c32291d3d1ae719b36a62faf3abaa2053a313f625d85c51a5198571915ef8a2b199ba37d25884575ba1b72844cab4328b57fab1ec974ee8ea1df7ca9c78a4d3a03bcb0ab4169bf06a3a438d9566c6c501d8d9ccccb1ac26b4da4ae1a9d8e8b9df662821ad975c9b015fe26f6898d22ab912f0e405a5b27cfd39d657dcd92cdebe6791902713484406dddce71188731e44319381af27daf76792273b8c35251d11b836afe8b3ce9b40273f6915ebe6bc95a75bb941a429209867fba8764bf6c40db6eecb4f21747837cf6ae7fbfe36d5023df7fce2c0c3c57af2898885313c5c4bda35c7da6cb29932fb1991f62bbb080b32e2050619311ae69abb3022d913fa9eabd5d5cb4dc54d75dca638cda9af331c0cf4d2007b6ca39f655a61c01039f12a4b9782bc39aec4d22ef0093388dd7d5b56dfb8a7f9d8669004e2878dd8a6d76857c0845245068fee1c5319631e78d3785165c70afd65299301378551ebf613584c6a7620a0e3b6779f38c0940062497008eb233870868c21cccac239501b63b749a85602c28a095cafc749b0511a6c878edb3b780ea174d07b121e315a826dda6ec8dc54363e2cd2e6305a194825c0ea90efd7a9fd89cd97b99c4300bd3bf9353d82fbcceea71b4ee3f1aae9539b4cce90ca477597c174ef20f4b9f4e62d09a570d3135aabee9551fa60983958c0b7b8c3744553ee14e7f3cd103a19251c99bf6384abb60a76afc6658b80dfc5110adc4c732fe0ee32933fb284828e008887aef80f6f813340446c0217c12ee: +12fe8e5ce20cafaa3279da7b34aa87752ead679f156128aaefb4afa5db4f2a6fe77f44206bb0c4c59a2870cfc2ecac63362deecbe8115de5cb1afc2d9a3d47f1:e77f44206bb0c4c59a2870cfc2ecac63362deecbe8115de5cb1afc2d9a3d47f1:6b80cc6fbbd332f8c6197cdf2e6dc19a2130faa2ec938ef558b884ba4fa5e113e5b3e4b1aaf51b695f13effe13f77d39cab3c07d04d66d430d9974b1da3d39df1278c00d6bcbfd4bae75b8c076404dbbb83448fb493df67000f97d247e8f23dc081fce992b65a21b35d7bd7fa7dccc54a560afd14b1ec436c10946f6aa59eae1be3ecf311def51e46b6b4d1d080d1784b2334b80cfba72cd931f55ecd298b05dc836ab12d0ad8b5d6e9b1e3cea3d843368eef19f5c14c6bbad9414cc7a4db6a726e4fcaed44440a019fe12a60573403c0e662dc902d1c873ff30c931ba7e43a3b3bf71d5b094ea504971647ca94356f0a53e444b4c008ee5977204221b400deec37fc273452545f8f218be988725bc38c85df212ea73dc0bc7cbbac907982fefad680fbd975c2093a7fe8e6b37c1cced87f81daa57291a5a18476d11a18ec4b5cbce5d55ac9b624b048430f254f671078506e6989df7c09256525039085ab7c130c240004abbb3af6b481cc1a0617e57e388ee4b1f052f34a003fe6bb202cb87d2741bd8e3454ca73d2f612011ecc74d88343510a63c9313ddc36c25d3fb03e188f560bd029c801585ce552988dc55b7d8522a3396c01d5e715ae26c622c64fed5b98e9c559e4aa78d1ed3b7b890d477ec8c50a0ff107a3f83b07bd35e9ce9a08bcfc0f168eec7aa311f71c66a71ceb9d5a2199a14be36865ca8d07e186b1392b9290c578004d584f191c82a53d850890bcc0d12dff840e043dddc2e670c836020924f58c044b218763ca61982bc332d247b2a008ab570b6565a06892a26cfb0853d79da28ef8b910a9329544b792ae4456ba7765066b9d1b4a300210448660ae48b504441017cddd1f6f00938b1072c8ab824adfe8ae34923c82eec754bee1a6550ab1d3da086e3aebbf21169c44469e03bbae0d72ce863457784cfe1dfc276f1afad9ee53ebab5a3c6572eb1cae099a4a5fe19319290e6a1b8b0e7541ed735b3f21b1e2c7509f87fd1fed00007479b3c1bb78432466302d246d8d031996307260a0c41a0e3ecd1e7fd834dac11a13eb036b39c369966fdef394c183e54e7b0cb3d0ceb198bd0e66c00d38db703aace30cbbdab369dfd1d9e514d0968f100c9f07c315089adb3ad02e59c04b9be46e99fbf5a62c6bbecdff5b381e55127824ddb18:04eaf900966e0992d36e3c220a4bd4d82bcc6eb998ed051dbcb9160bcd357409736bcff7e6630e96f5538aeca6ab8b0d0bd82c0cd7c4549917febb9cbada080c6b80cc6fbbd332f8c6197cdf2e6dc19a2130faa2ec938ef558b884ba4fa5e113e5b3e4b1aaf51b695f13effe13f77d39cab3c07d04d66d430d9974b1da3d39df1278c00d6bcbfd4bae75b8c076404dbbb83448fb493df67000f97d247e8f23dc081fce992b65a21b35d7bd7fa7dccc54a560afd14b1ec436c10946f6aa59eae1be3ecf311def51e46b6b4d1d080d1784b2334b80cfba72cd931f55ecd298b05dc836ab12d0ad8b5d6e9b1e3cea3d843368eef19f5c14c6bbad9414cc7a4db6a726e4fcaed44440a019fe12a60573403c0e662dc902d1c873ff30c931ba7e43a3b3bf71d5b094ea504971647ca94356f0a53e444b4c008ee5977204221b400deec37fc273452545f8f218be988725bc38c85df212ea73dc0bc7cbbac907982fefad680fbd975c2093a7fe8e6b37c1cced87f81daa57291a5a18476d11a18ec4b5cbce5d55ac9b624b048430f254f671078506e6989df7c09256525039085ab7c130c240004abbb3af6b481cc1a0617e57e388ee4b1f052f34a003fe6bb202cb87d2741bd8e3454ca73d2f612011ecc74d88343510a63c9313ddc36c25d3fb03e188f560bd029c801585ce552988dc55b7d8522a3396c01d5e715ae26c622c64fed5b98e9c559e4aa78d1ed3b7b890d477ec8c50a0ff107a3f83b07bd35e9ce9a08bcfc0f168eec7aa311f71c66a71ceb9d5a2199a14be36865ca8d07e186b1392b9290c578004d584f191c82a53d850890bcc0d12dff840e043dddc2e670c836020924f58c044b218763ca61982bc332d247b2a008ab570b6565a06892a26cfb0853d79da28ef8b910a9329544b792ae4456ba7765066b9d1b4a300210448660ae48b504441017cddd1f6f00938b1072c8ab824adfe8ae34923c82eec754bee1a6550ab1d3da086e3aebbf21169c44469e03bbae0d72ce863457784cfe1dfc276f1afad9ee53ebab5a3c6572eb1cae099a4a5fe19319290e6a1b8b0e7541ed735b3f21b1e2c7509f87fd1fed00007479b3c1bb78432466302d246d8d031996307260a0c41a0e3ecd1e7fd834dac11a13eb036b39c369966fdef394c183e54e7b0cb3d0ceb198bd0e66c00d38db703aace30cbbdab369dfd1d9e514d0968f100c9f07c315089adb3ad02e59c04b9be46e99fbf5a62c6bbecdff5b381e55127824ddb18: +ee9b6c2e0c9b01472ce32d54d1762ab0303317d76d3aa78f5e08a9024ca1e083016df0f717bcb7adf626958d83bf8aa325c70518c68bc7efd84253b75db08788:016df0f717bcb7adf626958d83bf8aa325c70518c68bc7efd84253b75db08788:772cc25c3b69bb3ff5655664efa478ac414adfaea70ac4a2a887ed3968c54d34dbf1be32cc9a9b5420a4ad3c9a877bc8ccec94ad473aa7a3c7de08a0fdb5ed1e89872be78170be221d279776bbc6ed9c5a67168980d5eaf895e1340f5dfaa3df622d6544b399d74945fd13bb1173621e0561514640137aa7bc9cb7debeff2c626977d447263b7e57d43d69efb230cd25865e4d924828f5e36f964e403e3493f30d6dfea6ca3b781075b5e3b25c05ac50e555f15ba12b0e059bff996484129db6eafd88993d6f0b7ecd15dce2fc99f8b8e43516352ddb461a04b9ff3486452e6aa6a54b2d1062a7714250cd2a88ff6c4c17b6cc6652d8c5ac27d4443aebf3d5fbaaee4521ec76f0413db64421ec8d6949626725fe56160ab307c0e73906c45155efabb47222021f220d32bd3db0712abde2599ea4ff799717811dcdf8182df6716d2a038aee15d778da55ac20f01f25309cead5b5b7b22322e1828ea7c91ae666f2dcd684073148e31bb2247d5f93506ea8085227adc9ae1982e950f006a9da158b9cecff8929761c84f9d976fdcd317ffed36cbf6acda3e50c9b73bd2c8085409d119b64ced7349a2674262a832becb03c2edccac0ec54124e82f810181792da49ea10bd941f9895a06959fde0d3b0ae84c39df05390ab33c36c79ca22e6594d7fc6e3f86922d78eb7f5c25495d822a3b41051b24e57a76fcfc165cde6d096cc7b7e9d055fe864d52942d629a8ac261be1dcd3a21f895f49b67ee47eab7cf1644d571d5ff38c179f5c6a54a3612fb34753412a1b95bf62ff3179804ffbb99051f2b080563a4ae0f27cf996ea8be3bae0a4339dccdff6b6671559266eaff4eff682b8dee89c9d2d45acdbec4aa6cecdbdb1d284609e65efb77bb8f1a51fc4d4568a705fb9c97b2303c1467dff8c8c5ee27559b93ad1c5b9c5c6c7c529fa8c55c75ebb59b2a818aa9bda1e9e79bc66029772f8aea11badd3226565d54fd01bda8cb270e70dc9339b46900b5818e932075be6c28e73a191d02cbdc7454be12387b0d47a1ab14232d2342a6f1518ea97098b815a1ca3f9c70b25722b1bcd7dacda635622fc8e72959f57f767ea563da4c158eef7200109f61416c2e70439923062437b1d082a8c7f4394713c1b7ba0587b841c114475ee3ff059df8cfa12a321d901cb47f5:4b001d9642835d72138d680198e6af70b5de7af015131ea726f4e51b5e8b6d48c2a6ca8e8709cc8222a5047c09a66e518ac5e8b6e53548948261f0701f687308772cc25c3b69bb3ff5655664efa478ac414adfaea70ac4a2a887ed3968c54d34dbf1be32cc9a9b5420a4ad3c9a877bc8ccec94ad473aa7a3c7de08a0fdb5ed1e89872be78170be221d279776bbc6ed9c5a67168980d5eaf895e1340f5dfaa3df622d6544b399d74945fd13bb1173621e0561514640137aa7bc9cb7debeff2c626977d447263b7e57d43d69efb230cd25865e4d924828f5e36f964e403e3493f30d6dfea6ca3b781075b5e3b25c05ac50e555f15ba12b0e059bff996484129db6eafd88993d6f0b7ecd15dce2fc99f8b8e43516352ddb461a04b9ff3486452e6aa6a54b2d1062a7714250cd2a88ff6c4c17b6cc6652d8c5ac27d4443aebf3d5fbaaee4521ec76f0413db64421ec8d6949626725fe56160ab307c0e73906c45155efabb47222021f220d32bd3db0712abde2599ea4ff799717811dcdf8182df6716d2a038aee15d778da55ac20f01f25309cead5b5b7b22322e1828ea7c91ae666f2dcd684073148e31bb2247d5f93506ea8085227adc9ae1982e950f006a9da158b9cecff8929761c84f9d976fdcd317ffed36cbf6acda3e50c9b73bd2c8085409d119b64ced7349a2674262a832becb03c2edccac0ec54124e82f810181792da49ea10bd941f9895a06959fde0d3b0ae84c39df05390ab33c36c79ca22e6594d7fc6e3f86922d78eb7f5c25495d822a3b41051b24e57a76fcfc165cde6d096cc7b7e9d055fe864d52942d629a8ac261be1dcd3a21f895f49b67ee47eab7cf1644d571d5ff38c179f5c6a54a3612fb34753412a1b95bf62ff3179804ffbb99051f2b080563a4ae0f27cf996ea8be3bae0a4339dccdff6b6671559266eaff4eff682b8dee89c9d2d45acdbec4aa6cecdbdb1d284609e65efb77bb8f1a51fc4d4568a705fb9c97b2303c1467dff8c8c5ee27559b93ad1c5b9c5c6c7c529fa8c55c75ebb59b2a818aa9bda1e9e79bc66029772f8aea11badd3226565d54fd01bda8cb270e70dc9339b46900b5818e932075be6c28e73a191d02cbdc7454be12387b0d47a1ab14232d2342a6f1518ea97098b815a1ca3f9c70b25722b1bcd7dacda635622fc8e72959f57f767ea563da4c158eef7200109f61416c2e70439923062437b1d082a8c7f4394713c1b7ba0587b841c114475ee3ff059df8cfa12a321d901cb47f5: +a3d23505d07c5f937f13639dbd818e85145234ee7017ecee8636c7ba76ebef5bfd7fdb3d022ba36eadfed0daaae5bff04505403f171473e4d361ee8d150a0eb4:fd7fdb3d022ba36eadfed0daaae5bff04505403f171473e4d361ee8d150a0eb4:bc298ed69892904028725e21b114462d89d8c006dc884b178756838af4954ff0f1b79517307a258a0e7681e879ac47d7920230b0cc1d66171eb214d77cd97f617c405e6c2172fc589f1625cc5e1b593110531f6eb53f1e6f486d1964612447750a041fe51b332eb3fbc711616ce35f040442b43163b80b751e21ec1245f12e4883c79d3b413282c69bfc6a465d1e7896bab038dc89b4cfc032fccdfc87b07f06110e1f506acca8157a322543bf1ed8906727f28d0d689bcd7dd3df85935204a904ab3f7a0d99c16e5a542cc2bcdebf5b502dbabe33b972480e02e71a438a1980a8766f108bd8ad51104223994d9bfb3c3a4b7a59238ce2ef7d7288383ffbf291e1602b384af60700d7daf0e8fe60f8caede43db06b3f4c8cfff749aeafa46fc61c49b2d5a41204cf86f049254d809e9498aa9d4cfdb94acb2babfcf786ddfb03691516b3838b0d4f201cb2591edbb0b0f674e1e2820316b72e81b48cc5a6b29338bc36681f8f7dca43ee6c0bd2e402afbf967797516453bc01be86bf42299d1b736a0d97bbc922f5a78af2df42e6f8c28e953f2ceadaffc5e93064041e425ad6975f88c7aadf81c368691a581e885f2a6ba72ed68b8fefbcd6ce368626d44892a20270b5f709c2e34b8335d42eebd67a24df73f45455c41944187b6692f054b2fc9591373f19fc71aa7fa27df6006a1d549bbfae7d3c3eb36e5ab2aaa10aa5538da7ef36c8ff354b6058134004d660a4036321caad00a30b1c498ba3d808c4405ef79618fc2212a7b83396a3d7cedceb863c66374dc469ae183c7ed74b3e70d6374a062de0379b21cf25d3c4c5762115cdfe755545e89ad4052bb0279d938e90de3abf504410caad72b7c29f53d01d9dd7f2ec5e459a04592bdd66416613e6edd004569e0e6c98827b8c1d7002a6d1bf303e18259501dd89f6ee94766d18af810463eb13b2efddf1723af735a88716e1fcb4b7b43cb97e1cc903b2408ef453ada4164786f00845fbfa1ffca5cc3e1c4bd9940e7d99aef919166d058b51453c9c14fb9f3251ec5fe4f153c70a4492dc3496296186f23ad47ebad13c66e68727ce50ba9487f1801890b693efebfc37bb5d95f8af548ec8d6498289e55f9883fc5be84c256d2bc5484938c709820d9b6b8059c0aa4267dde69078e487c8865c0b130a0ca8ca:67a667ee0d6254ca0a8f212582c0cb8b6ed97cc967db021296ad6aa99f0ad3a944978cfdaff13fe5f8c6e88cbd831a5473d0742e3734b3e2df00ff3240a5de02bc298ed69892904028725e21b114462d89d8c006dc884b178756838af4954ff0f1b79517307a258a0e7681e879ac47d7920230b0cc1d66171eb214d77cd97f617c405e6c2172fc589f1625cc5e1b593110531f6eb53f1e6f486d1964612447750a041fe51b332eb3fbc711616ce35f040442b43163b80b751e21ec1245f12e4883c79d3b413282c69bfc6a465d1e7896bab038dc89b4cfc032fccdfc87b07f06110e1f506acca8157a322543bf1ed8906727f28d0d689bcd7dd3df85935204a904ab3f7a0d99c16e5a542cc2bcdebf5b502dbabe33b972480e02e71a438a1980a8766f108bd8ad51104223994d9bfb3c3a4b7a59238ce2ef7d7288383ffbf291e1602b384af60700d7daf0e8fe60f8caede43db06b3f4c8cfff749aeafa46fc61c49b2d5a41204cf86f049254d809e9498aa9d4cfdb94acb2babfcf786ddfb03691516b3838b0d4f201cb2591edbb0b0f674e1e2820316b72e81b48cc5a6b29338bc36681f8f7dca43ee6c0bd2e402afbf967797516453bc01be86bf42299d1b736a0d97bbc922f5a78af2df42e6f8c28e953f2ceadaffc5e93064041e425ad6975f88c7aadf81c368691a581e885f2a6ba72ed68b8fefbcd6ce368626d44892a20270b5f709c2e34b8335d42eebd67a24df73f45455c41944187b6692f054b2fc9591373f19fc71aa7fa27df6006a1d549bbfae7d3c3eb36e5ab2aaa10aa5538da7ef36c8ff354b6058134004d660a4036321caad00a30b1c498ba3d808c4405ef79618fc2212a7b83396a3d7cedceb863c66374dc469ae183c7ed74b3e70d6374a062de0379b21cf25d3c4c5762115cdfe755545e89ad4052bb0279d938e90de3abf504410caad72b7c29f53d01d9dd7f2ec5e459a04592bdd66416613e6edd004569e0e6c98827b8c1d7002a6d1bf303e18259501dd89f6ee94766d18af810463eb13b2efddf1723af735a88716e1fcb4b7b43cb97e1cc903b2408ef453ada4164786f00845fbfa1ffca5cc3e1c4bd9940e7d99aef919166d058b51453c9c14fb9f3251ec5fe4f153c70a4492dc3496296186f23ad47ebad13c66e68727ce50ba9487f1801890b693efebfc37bb5d95f8af548ec8d6498289e55f9883fc5be84c256d2bc5484938c709820d9b6b8059c0aa4267dde69078e487c8865c0b130a0ca8ca: +6e265105ee7171d1bd793effd87d1e2c79450d5e188b57be3aa162e2a52528ad1f403c7a755031c13ca63af57635dc6e2c4f23bd6b1d67ca65da68b09943c554:1f403c7a755031c13ca63af57635dc6e2c4f23bd6b1d67ca65da68b09943c554:f8b9d4b027ebb10ee511819e6e56fb1ba9584018418d82885a38a449086007b8785b5105caf782bf9b36da039cc60e227c7e1614f29b640b1e9b22747eea7a6725614e89e0783ebebbb7ee557ef36b2b46cf6461e5be2ad1d7a7c2711a475ca4fbc33092ba425667e34d090060518f2fec636b049123876ab21c8bd9c50dccb984ca011a02eea020564fa821fc362bfe392aab50c273fc7b5a042188e331621b9d2f743e5c8cf3ab1faffafe2a0004c8ef7cdf5e6dbb5eb544e4289f71a6fd15c638ce29d28efb9c039e477429a3497a83827e76ce77a49816d90b41a8e152f37a09e6340dfe069a4ac6f27dd2eac747fd21e3152088c1b1ecd32ac679927490750488c291785147b63b0b8ff11d189b9049b8a396b6932f85bd6a15eff9f0ce1808411af0f9c8e6e97b814f110bd4df1386a9797dc511f0aab6ab65071d9ea836532cec51b92ca7fbdb8de1c8436658de2eb65edd86044f6c1aba3178647ad678612ee74f046ca3c7fe2f39c09dd2e07df2b4227085fe936e794d22fd5f40a25f08771580ac801d9889f5a76aeae1f0cc4a9e1edbdda3750c74c850524b32f44933fd883b5372bfb7e761e069fe7c1c0e7fbd4a7f58467ea6883f9d5b7f66d386b0499bb6fb5ead89c9a1fd2cceb973e2879b5d03eaa452e16022d59617daa0486f4d4c117807fda8499dfb7a286fd2f71a8eb5fe64065c41e4e1e2362ab4e477969e3a408a247e3a56fc86f2b01ef8d3cdda87258234bc7f25b66907f364b37b6245296c4fdf499f20237f4864852fc5d8cd5d05418be8b13859ee9a43e17e1f57a4c35ea282ed68ebcda6828174245a49c6cb6590eb1f2dcfb007bfa1c32077956da9acbe3ef0723799fdb869d8de30706a9c026814d16a01e033c91b59070dfe445c5b848a516612e5131fe8486921e36b8e7ef157a88822886c681b5da71fea94d957dafec26f4147a3b2ac383a5f47c8585eb17a8ac65790641b4218d755f8bea4d97ae2a45bdcdc23236294d852c95d08406d2e9bd30c326452538c1f5e5004d4a1a82720da32e59dc3ab18ea08a058f791d24418556086c1e4edce8982aa23b118fb266e60b542780a6933add913265512c07b114978d44af73b2030ec47b06fd09dda8c4f1d4e313775468c451f9ee611e9cd4c0845c2501948a7b14ef1d4b5cf:b5a83a117a60345a67e4a665f37de722a6ec03913829389959f376ee626477e654ac8d720fc727d4bb8fe1544f5d0b0b850514290b24273c4cd4b73aca4a5300f8b9d4b027ebb10ee511819e6e56fb1ba9584018418d82885a38a449086007b8785b5105caf782bf9b36da039cc60e227c7e1614f29b640b1e9b22747eea7a6725614e89e0783ebebbb7ee557ef36b2b46cf6461e5be2ad1d7a7c2711a475ca4fbc33092ba425667e34d090060518f2fec636b049123876ab21c8bd9c50dccb984ca011a02eea020564fa821fc362bfe392aab50c273fc7b5a042188e331621b9d2f743e5c8cf3ab1faffafe2a0004c8ef7cdf5e6dbb5eb544e4289f71a6fd15c638ce29d28efb9c039e477429a3497a83827e76ce77a49816d90b41a8e152f37a09e6340dfe069a4ac6f27dd2eac747fd21e3152088c1b1ecd32ac679927490750488c291785147b63b0b8ff11d189b9049b8a396b6932f85bd6a15eff9f0ce1808411af0f9c8e6e97b814f110bd4df1386a9797dc511f0aab6ab65071d9ea836532cec51b92ca7fbdb8de1c8436658de2eb65edd86044f6c1aba3178647ad678612ee74f046ca3c7fe2f39c09dd2e07df2b4227085fe936e794d22fd5f40a25f08771580ac801d9889f5a76aeae1f0cc4a9e1edbdda3750c74c850524b32f44933fd883b5372bfb7e761e069fe7c1c0e7fbd4a7f58467ea6883f9d5b7f66d386b0499bb6fb5ead89c9a1fd2cceb973e2879b5d03eaa452e16022d59617daa0486f4d4c117807fda8499dfb7a286fd2f71a8eb5fe64065c41e4e1e2362ab4e477969e3a408a247e3a56fc86f2b01ef8d3cdda87258234bc7f25b66907f364b37b6245296c4fdf499f20237f4864852fc5d8cd5d05418be8b13859ee9a43e17e1f57a4c35ea282ed68ebcda6828174245a49c6cb6590eb1f2dcfb007bfa1c32077956da9acbe3ef0723799fdb869d8de30706a9c026814d16a01e033c91b59070dfe445c5b848a516612e5131fe8486921e36b8e7ef157a88822886c681b5da71fea94d957dafec26f4147a3b2ac383a5f47c8585eb17a8ac65790641b4218d755f8bea4d97ae2a45bdcdc23236294d852c95d08406d2e9bd30c326452538c1f5e5004d4a1a82720da32e59dc3ab18ea08a058f791d24418556086c1e4edce8982aa23b118fb266e60b542780a6933add913265512c07b114978d44af73b2030ec47b06fd09dda8c4f1d4e313775468c451f9ee611e9cd4c0845c2501948a7b14ef1d4b5cf: +c4370d2aaf35acd158fc0d1622a399c99f41b9da4e970b354e5ba05cbe844ca83545d7d4c95c3db6a54530537afafa4d86ddecf9cc7e66c319ba9f7dd7d07ee7:3545d7d4c95c3db6a54530537afafa4d86ddecf9cc7e66c319ba9f7dd7d07ee7:619f57de2b1dbaee209a825d8ca97f84ee49eb12a0b13dcdd2b3a4ee45e0176d474cf09460c831a8ae1d3f39beebd08808b3ed1761213ba953421860cc07e2db312e680df03e60a6870264abca8fd51301e1c1562023d802ccd5c7d196db39fbb8304b0e59e333164192ecc333387eef69c7a78a5d11258862d6c281b19c0bd336cd3edb2f9faad4021ac2f205c16814b38548433ff9eddfd61133779769dc69afac658afc1d1b416d390ad5b45a1ad5cc4b00b4b278fbe4b59d52e61a6a5fd00241c6cbc382d2d621a3ded002019b330560e361faab28f41d1af9c9c0020f2baf99e8d8ee58e3122202147c0adc57d670c5b380af594cc7ed57b87ec6674ab63f3a9849753b9462aab5de88c948a8b109af4d4954927aac58bee953be0d8d7d71aa11d11f1a87b1477b9170bd735cfc2449f051b82bc59b0bee76a172e8d32670f51ddddb804ad110a565e384cdb76fad04cff67893091e41e69cfdf70ea926c26369a5b6193b19ab0a62558da55ffafeb8789757710644aa19f474be4ada9dc1849b07d5e17b85f921e1016a54aa6095777253a73426fc7864b9955f04907023db207f85dd21a65106cf0d622385870c34c2da9a11e4726395121e4a6761fb522229d9e5cc9dab35aeb87d0d79693c006fde1cfaf116208bba962059cfc0d2d6370aac7748362ee6a0a3ca7bf133ebcfa20f1c4ed8307f800cca7e6c4beaa3fb2ab086125364285c44ed1a737a67cbf3b763c9f8b1427e89dfa96d290e9d4842fe6316afef834cd8cd1fdc1f124ca3fe26266da62e275c0bf7fcc8e5f9bba6c0d38e23fafab1e049481794c14f4a8c53be1c96f769c9b13eaca39a0e49366d2c9ffe8f206360a9d503dec598621112e3776713e7fc0649433e257e503a546059a989da89157d76476005fd90e4b07aaf0db0bc0bc0b67db8dcbadff39374e1afae551634e0e32831ad0e5fa7d5216fa7c644f73e1e8e07238394a416c169aa9d5303f469a5d4074308721ffddeff6559e5adf0c2773b3f5264e7aaa8c2db888e28e815c71069c3b4ce6c29034c0ab3b5c19a80a9d8c2e874813531c422752ad62b3c5a1a3d6c5a5db587270693aa75d5f172eeddf4eb839bd793affb1c796a1df0e442ddf99b780aa41eea0fe6f865bb539ca53aa45db9a856cb75d0151d35edea80f2946d:9febab5ae161d692a6a394500a2890d21c7f0ee26f4640aaba4fe66b90b89edcb80ea4cdcabb4d2c3a5c4154e8ff20d0e237fefd00c7ba9782e1748f6488ac01619f57de2b1dbaee209a825d8ca97f84ee49eb12a0b13dcdd2b3a4ee45e0176d474cf09460c831a8ae1d3f39beebd08808b3ed1761213ba953421860cc07e2db312e680df03e60a6870264abca8fd51301e1c1562023d802ccd5c7d196db39fbb8304b0e59e333164192ecc333387eef69c7a78a5d11258862d6c281b19c0bd336cd3edb2f9faad4021ac2f205c16814b38548433ff9eddfd61133779769dc69afac658afc1d1b416d390ad5b45a1ad5cc4b00b4b278fbe4b59d52e61a6a5fd00241c6cbc382d2d621a3ded002019b330560e361faab28f41d1af9c9c0020f2baf99e8d8ee58e3122202147c0adc57d670c5b380af594cc7ed57b87ec6674ab63f3a9849753b9462aab5de88c948a8b109af4d4954927aac58bee953be0d8d7d71aa11d11f1a87b1477b9170bd735cfc2449f051b82bc59b0bee76a172e8d32670f51ddddb804ad110a565e384cdb76fad04cff67893091e41e69cfdf70ea926c26369a5b6193b19ab0a62558da55ffafeb8789757710644aa19f474be4ada9dc1849b07d5e17b85f921e1016a54aa6095777253a73426fc7864b9955f04907023db207f85dd21a65106cf0d622385870c34c2da9a11e4726395121e4a6761fb522229d9e5cc9dab35aeb87d0d79693c006fde1cfaf116208bba962059cfc0d2d6370aac7748362ee6a0a3ca7bf133ebcfa20f1c4ed8307f800cca7e6c4beaa3fb2ab086125364285c44ed1a737a67cbf3b763c9f8b1427e89dfa96d290e9d4842fe6316afef834cd8cd1fdc1f124ca3fe26266da62e275c0bf7fcc8e5f9bba6c0d38e23fafab1e049481794c14f4a8c53be1c96f769c9b13eaca39a0e49366d2c9ffe8f206360a9d503dec598621112e3776713e7fc0649433e257e503a546059a989da89157d76476005fd90e4b07aaf0db0bc0bc0b67db8dcbadff39374e1afae551634e0e32831ad0e5fa7d5216fa7c644f73e1e8e07238394a416c169aa9d5303f469a5d4074308721ffddeff6559e5adf0c2773b3f5264e7aaa8c2db888e28e815c71069c3b4ce6c29034c0ab3b5c19a80a9d8c2e874813531c422752ad62b3c5a1a3d6c5a5db587270693aa75d5f172eeddf4eb839bd793affb1c796a1df0e442ddf99b780aa41eea0fe6f865bb539ca53aa45db9a856cb75d0151d35edea80f2946d: +bd3de1a1d164bd6e9be0a6d107f703a6dd914c8667cd341d139f19578d933b169b024964bdfa852eb2d4144f35b7cdc26781143c2bd7f660233f8b8aa36071ee:9b024964bdfa852eb2d4144f35b7cdc26781143c2bd7f660233f8b8aa36071ee:1769fcdbf51247ed4c83a00bbbf02f4428da6fceddd0161a02fccd1500970665e1c7630ad22e3d9749c792e71a260cfff6053256e02f5b47bba14b761ae53ca7219ed2801d2d788e26419f36c81ef92c2303683735c8a1756adab6a487923153e435603c96b239553edfdeb093298f7ae7dc90f16a7e5664b9e4c02ba731a23cf2234e250ac9742633a932a948bb83dc3d794d059fedf4ec8618c7433c5d8fe5e62cf07b5768c4d9b261c71536804fe2e7ca7098876521d57677361424e47f1b959237f90710421f5bc4f109f7d489c755e94eefdfb3c85b90ec013181a23bb9535feea4941d0a06a540bd6b588e55b7f35757149ca3e640965e1a0ff7f3c8259259957ff5dab9fb8732eae719b624a4492878179b5a83abe51caf02083d737ceb4fcf042f2e60ba0297ac72b87fe3e14ba5fbc54b48091073896823bfa289ce8e16873b48812c32bfea5ff6bb221d1ea5463d325bbe311e7fd1e783de650b7952eae461d63bc7470522af5b7789f8fc2eb192d2cf776c5c24b44e29cdb0cccb1d90361438e4950ff34dbcb3cb0e81cc45f8d0ff570949f78084e1060ff5594ad516f50f1cb0a765e1c0e038d5943b936e4a8b493354e79abc917bb9271266eeba77a93a657f9ad87b291ac7ea386f5d4fcbc582e72d5c23d92ba944b0064c20e3e2dcf504bcc7c6966c63f2080843600ba313ec27cba95e7ef318168c9067dce86c1ef0d5d9eb7a6158489df32ed58b6931030818f00705a0dc55d3dbf8006a8546641b1865d919bc242202cb3ae300bf8653e3b37894c3dc0e477b9d7c41baf8d3887c2eb59b1e4d50bbb6f1792a1c9367c65cdb450c2dfa2145e611a97ad81cff1fd83c6cf7230947eaff4c21dc1bafb71ec41e5bc72b3745ec3e38bf5930c126d060f0c50a895f009aa18e87f2174f58ab5379a721fd83aad5517fd99dff146edeea61521235e2f1a16ee58303e091be8d579094c1d8a20bc74a550d77c00d087571517a63cd4126933a4f09a070bf8ea4ffb846a9780e9734043bac4c0ff47b1afccf5293ac14bc73ebf67129657e4b8a8b33ddac7b0f4d719d2dc65df6ea0a3f24cf44c8338ed601a3939ca358fc4be13e8ede027539712ca23e3ffba706e8fdd62a074ee0ad7420f78060cc96fb2abf30e9eaa241c0f87ebbe3ec73517596f7c3c5a80c:13cc158fd061792fced156879598251dd01d575b400fe3e39a700863aae8db1f9197fa501c0cf993e44d6ac55180b869838e8ae24b214fa35e244b7a6cff6d0d1769fcdbf51247ed4c83a00bbbf02f4428da6fceddd0161a02fccd1500970665e1c7630ad22e3d9749c792e71a260cfff6053256e02f5b47bba14b761ae53ca7219ed2801d2d788e26419f36c81ef92c2303683735c8a1756adab6a487923153e435603c96b239553edfdeb093298f7ae7dc90f16a7e5664b9e4c02ba731a23cf2234e250ac9742633a932a948bb83dc3d794d059fedf4ec8618c7433c5d8fe5e62cf07b5768c4d9b261c71536804fe2e7ca7098876521d57677361424e47f1b959237f90710421f5bc4f109f7d489c755e94eefdfb3c85b90ec013181a23bb9535feea4941d0a06a540bd6b588e55b7f35757149ca3e640965e1a0ff7f3c8259259957ff5dab9fb8732eae719b624a4492878179b5a83abe51caf02083d737ceb4fcf042f2e60ba0297ac72b87fe3e14ba5fbc54b48091073896823bfa289ce8e16873b48812c32bfea5ff6bb221d1ea5463d325bbe311e7fd1e783de650b7952eae461d63bc7470522af5b7789f8fc2eb192d2cf776c5c24b44e29cdb0cccb1d90361438e4950ff34dbcb3cb0e81cc45f8d0ff570949f78084e1060ff5594ad516f50f1cb0a765e1c0e038d5943b936e4a8b493354e79abc917bb9271266eeba77a93a657f9ad87b291ac7ea386f5d4fcbc582e72d5c23d92ba944b0064c20e3e2dcf504bcc7c6966c63f2080843600ba313ec27cba95e7ef318168c9067dce86c1ef0d5d9eb7a6158489df32ed58b6931030818f00705a0dc55d3dbf8006a8546641b1865d919bc242202cb3ae300bf8653e3b37894c3dc0e477b9d7c41baf8d3887c2eb59b1e4d50bbb6f1792a1c9367c65cdb450c2dfa2145e611a97ad81cff1fd83c6cf7230947eaff4c21dc1bafb71ec41e5bc72b3745ec3e38bf5930c126d060f0c50a895f009aa18e87f2174f58ab5379a721fd83aad5517fd99dff146edeea61521235e2f1a16ee58303e091be8d579094c1d8a20bc74a550d77c00d087571517a63cd4126933a4f09a070bf8ea4ffb846a9780e9734043bac4c0ff47b1afccf5293ac14bc73ebf67129657e4b8a8b33ddac7b0f4d719d2dc65df6ea0a3f24cf44c8338ed601a3939ca358fc4be13e8ede027539712ca23e3ffba706e8fdd62a074ee0ad7420f78060cc96fb2abf30e9eaa241c0f87ebbe3ec73517596f7c3c5a80c: +f6ae516a51296fc523cea5f008cfbd09e73f78b6fdd3b69426128041a5604cf9376c82ba7b87aa77418727db33d326ae758bf7a135c10460cd8bf8feb83c2b10:376c82ba7b87aa77418727db33d326ae758bf7a135c10460cd8bf8feb83c2b10:8342f25ac4b17ebad6f79b9a033175c7f28af09e658e8cb98c294f15c3c8342629cb2a3247dfc875b82f5b380c5d11426a2eeb62450bd885650107c68362a3b72ce823f2d15942b7dda301d2fb638f302aa9570b47911dadd3bddbfed554c1c80bd718078b8bd2c9c314a5166f265e8266ee2db357561a5585c414a7840bfae609d7cddde1fade85560f23d638ef3d52e51f5cf313a072c5ea0f817f7281e2cba5c5c8d26c928592b81f0ff8cd18db5a2c41d880d74473863c7bbd0056fa4d4afabd17a3b89d97d3fe5dc06b0f612a1d66423923ba8dfbb8ec8246624d83784eba4f5736ba385e442296c8cb0f1b68e03342b2c6c103346f6dd740e26c3d13caef801d1b2621d89f069391a078d43ae6ff12eeca66bc32637b45f0ac627c2d7bbf8a49d9468175e26885e02821d3a3baa2c3e3a6bb96b57526e224cf3d859f669573cbd5c87393746156f3d1c7a80308dc1f2405bf0d40be1ca73b767dedf4031337c081bfa3ae6e54f6023f42f0cbd87762db55913c707206034010df2aa8753d030f03c267e71a9dd2c6c19de3e1851abfacbbd5dd5bf896fab8e415317b49f1e4096e3da99a5b5d0a3c42daf9de94847c1e53c8818a5b843323f501e3a7fa68df89a5f41f2c62c38d17f250b02a67fae47daf063f558942377ef8a89052f1a215d768f7913a7ec14e98b81e4b2ccf26bacad6f39664afc0e91a3cad691db2bf56a7ab6677b49596db887c97def43508a7a2ec2ab755ec368e2e53d1e16b60fff09c3b52263f0f7c1ea9cc35373197e95c11e6d22fa9d8299c423736f5814f1e798d227518600df6a790358deae38d5639e1983fe018436ea58ba8467548c929efbb16dfea4102253a350fb84d9831c4c2cbcb76e18d7f3e953641ada41421393091e63dfe66de24c99232c7d6a2837a48983cf5b16331ce00050d1c713958ffce5f2e9348c52f53120579a7c9a16008d134838e596129c702fcd21148bdf9174d48e2da0a8a66359edee01c5009ef6742fec41c1acecd03efe1ccc9b130d6e5ac92576a85ccb7cfc7d0e4233106172931a08699790bc41acfbb731adbb26d56b39aaa5b333bc1a10e2c7064ca86119d8c717148f92441af24cd2aa8f57c86ba38a59a100b9276df3827ec7fb4d3faf58be31c6ecafd69cf1c6410a49cd7081ff6e9fc397c2d20:0fe4dd7e1f608ee82b7fe863d1b03a81843ce20c762cd8bb24efd46ba025fff3331d875752ca7220c53dd3c71f2bc1e2c64a2f9c58865a2a244809f4134e53078342f25ac4b17ebad6f79b9a033175c7f28af09e658e8cb98c294f15c3c8342629cb2a3247dfc875b82f5b380c5d11426a2eeb62450bd885650107c68362a3b72ce823f2d15942b7dda301d2fb638f302aa9570b47911dadd3bddbfed554c1c80bd718078b8bd2c9c314a5166f265e8266ee2db357561a5585c414a7840bfae609d7cddde1fade85560f23d638ef3d52e51f5cf313a072c5ea0f817f7281e2cba5c5c8d26c928592b81f0ff8cd18db5a2c41d880d74473863c7bbd0056fa4d4afabd17a3b89d97d3fe5dc06b0f612a1d66423923ba8dfbb8ec8246624d83784eba4f5736ba385e442296c8cb0f1b68e03342b2c6c103346f6dd740e26c3d13caef801d1b2621d89f069391a078d43ae6ff12eeca66bc32637b45f0ac627c2d7bbf8a49d9468175e26885e02821d3a3baa2c3e3a6bb96b57526e224cf3d859f669573cbd5c87393746156f3d1c7a80308dc1f2405bf0d40be1ca73b767dedf4031337c081bfa3ae6e54f6023f42f0cbd87762db55913c707206034010df2aa8753d030f03c267e71a9dd2c6c19de3e1851abfacbbd5dd5bf896fab8e415317b49f1e4096e3da99a5b5d0a3c42daf9de94847c1e53c8818a5b843323f501e3a7fa68df89a5f41f2c62c38d17f250b02a67fae47daf063f558942377ef8a89052f1a215d768f7913a7ec14e98b81e4b2ccf26bacad6f39664afc0e91a3cad691db2bf56a7ab6677b49596db887c97def43508a7a2ec2ab755ec368e2e53d1e16b60fff09c3b52263f0f7c1ea9cc35373197e95c11e6d22fa9d8299c423736f5814f1e798d227518600df6a790358deae38d5639e1983fe018436ea58ba8467548c929efbb16dfea4102253a350fb84d9831c4c2cbcb76e18d7f3e953641ada41421393091e63dfe66de24c99232c7d6a2837a48983cf5b16331ce00050d1c713958ffce5f2e9348c52f53120579a7c9a16008d134838e596129c702fcd21148bdf9174d48e2da0a8a66359edee01c5009ef6742fec41c1acecd03efe1ccc9b130d6e5ac92576a85ccb7cfc7d0e4233106172931a08699790bc41acfbb731adbb26d56b39aaa5b333bc1a10e2c7064ca86119d8c717148f92441af24cd2aa8f57c86ba38a59a100b9276df3827ec7fb4d3faf58be31c6ecafd69cf1c6410a49cd7081ff6e9fc397c2d20: +83f789900f040dc62f4d18784cb64b63c88e8d18001696bbeb4707c469d11a5bedfc2bab7e79f40037fe4d9041de48da9aee8f978098d7b0ae17929025e4273d:edfc2bab7e79f40037fe4d9041de48da9aee8f978098d7b0ae17929025e4273d:6c112a20d30657ab5f8c5c04478d6c42d1c6bdef38cd4fe006ac2a57e290ff29287896eea8c30a0139c18fc8c97564563e86c8d34056a6719bfe479d9e87e81b19452331bfa154806882e5039a20c9e954b1fc7c015dcf5815bd7cf7b6357df9280b9bd43f89ffc91945323b5acb2ae00254d4162868d1c83ec6e0fcbe7a8ab9254192149c6bc9e5fe350694165d6638331eb24e3b1390c698c4838378c01b2c61a3ebe2c060b98ba6ee02b519b4eac1e0bcc09b2324ccf5b1a7fe8fd0b1545a9427832abb25744eeb36326be64efed3a7b07d630a21c3081b55261c353287c66c57663a99db466a5dee22746b81c750ef85be51143e221ecdf114fef1b3082ff54fd044bc884bfb3cc5c5335997009867ce9491a80fe696825f99426defab6a49badcde403f58e8317966210747b567754de53076b3ecbf65346cb83905832e16d01b50b93d37eb9bfe20172a31630d25f3217d87d93465fd8ac554cbbb39d982ead7219391234c889f0b92a2e0413d866cac087d628ce31c61c6323ecb8e689555af10de2b656e6aea2cde932e241f6d1f8a9e3316cf13f135acef83a0c0cf22f95ca818e61f92768774c630e0925be99dbd32b499c0fe7d84a42e393287f6f5ce3d0b271f170045a6d48eab316fe17b1858b1ffeee90888f3a37a2480dfd04a4a8629f868b5c0a80ee1f03719f3a47d4095bef10e0234fc300e2af482285d78937968319da94beb6c40e078577c024f3a5cda0084e2f855a9396aaa9ee9bfaf2cc771fe68c40b629e8dcf115ef03e757a2ac9eef073f1bdf9c5a4410031558a6d382b5f16024b151b1c01ee7817413a3c4de9dd6478785b81101df5522430058780207e790f612d78e5705ceed46b0ec075e7c1dc073b17b2b43d72535927bfd271e92e3c93638e40a9601dc2c1ab76d91a4103df657d911c829ee8a5f747f7642f5a915a5f40f630b43039c7d4bd2ad2b32129d94e5b2f03ad4a3d45577eb81f369c9e3e2a4f6a8e41acf8283be58425ea993b8e98eea6330556648618dad98fa255620d836d3c7f29b907895849286167c7181e2caf55c2c184a9a911f8e41cb042e2cd48b0544ea79fe2ef381ebc5b15e39a9b5c6d998faeaaa7773cfec084c0bfaed1bcab963a4ef3d94dbb3dfe724c040ce4d1e2ee7fc2da4b25127ce3a5df693fcf5a6ed1:ea6582cc23e0460917f782d964e3bb6dcde0aeeac42cc14919d36ce78aa0afd98072f54c795fbfd7a41d99d70606c28a5dcf19be38a0ce2d09bb8f844c31bf006c112a20d30657ab5f8c5c04478d6c42d1c6bdef38cd4fe006ac2a57e290ff29287896eea8c30a0139c18fc8c97564563e86c8d34056a6719bfe479d9e87e81b19452331bfa154806882e5039a20c9e954b1fc7c015dcf5815bd7cf7b6357df9280b9bd43f89ffc91945323b5acb2ae00254d4162868d1c83ec6e0fcbe7a8ab9254192149c6bc9e5fe350694165d6638331eb24e3b1390c698c4838378c01b2c61a3ebe2c060b98ba6ee02b519b4eac1e0bcc09b2324ccf5b1a7fe8fd0b1545a9427832abb25744eeb36326be64efed3a7b07d630a21c3081b55261c353287c66c57663a99db466a5dee22746b81c750ef85be51143e221ecdf114fef1b3082ff54fd044bc884bfb3cc5c5335997009867ce9491a80fe696825f99426defab6a49badcde403f58e8317966210747b567754de53076b3ecbf65346cb83905832e16d01b50b93d37eb9bfe20172a31630d25f3217d87d93465fd8ac554cbbb39d982ead7219391234c889f0b92a2e0413d866cac087d628ce31c61c6323ecb8e689555af10de2b656e6aea2cde932e241f6d1f8a9e3316cf13f135acef83a0c0cf22f95ca818e61f92768774c630e0925be99dbd32b499c0fe7d84a42e393287f6f5ce3d0b271f170045a6d48eab316fe17b1858b1ffeee90888f3a37a2480dfd04a4a8629f868b5c0a80ee1f03719f3a47d4095bef10e0234fc300e2af482285d78937968319da94beb6c40e078577c024f3a5cda0084e2f855a9396aaa9ee9bfaf2cc771fe68c40b629e8dcf115ef03e757a2ac9eef073f1bdf9c5a4410031558a6d382b5f16024b151b1c01ee7817413a3c4de9dd6478785b81101df5522430058780207e790f612d78e5705ceed46b0ec075e7c1dc073b17b2b43d72535927bfd271e92e3c93638e40a9601dc2c1ab76d91a4103df657d911c829ee8a5f747f7642f5a915a5f40f630b43039c7d4bd2ad2b32129d94e5b2f03ad4a3d45577eb81f369c9e3e2a4f6a8e41acf8283be58425ea993b8e98eea6330556648618dad98fa255620d836d3c7f29b907895849286167c7181e2caf55c2c184a9a911f8e41cb042e2cd48b0544ea79fe2ef381ebc5b15e39a9b5c6d998faeaaa7773cfec084c0bfaed1bcab963a4ef3d94dbb3dfe724c040ce4d1e2ee7fc2da4b25127ce3a5df693fcf5a6ed1: +43bff3cdd5307ed7d25cf96fdbba64ab1811c8bb934e2187ea7ffc018d85e0f200f1b5d3cac6e56ca5f894d4cdbf9bebd968d24d5effa5058b0e20bb0898f6f1:00f1b5d3cac6e56ca5f894d4cdbf9bebd968d24d5effa5058b0e20bb0898f6f1:646f8b34182d5e602b51ca7329347c0e198cb747e4da0a6b80f3f6f9f336f6708d85cb429ab2d6bed35d5013129cd100142cddcee8635179021b3e24922b81aef13c1370286939d63d6b6a4195eda1d812ca518204768f87348c6889552c63d1372cde6a5e9daa7f8445ec8d6130a3f5aef0edeace010b6c7f0b9d24162a8d04454b81d48ea9097bd8df093459719ccb54aa10f51c246aa99c580beaf9c9c5bc60faf0ae5cec7f5137f6c5c144df45d12ee995adccf25a9db81b8558bdfb65830186e7b9d4eed9f6b4d732b1b5822d03eb017c0724f48f87baaae1045d6fdb125c9134064faf18dbed58d8fbaceacd4f097df9b342e5c4a5bc85b29597d4b640f1551c5b624ab21b48e94a9030049be1f05aa851d0827eaf8700dfe147fdcdeedbc98c4f15774f0120fb5970a2f8b21794340b628379a802b9f7c068b0df63193e510fc7b2af97ee38de47929785535528d350d88620610cfdb55d249e38fb73c8287113919ce33267d7db924e4919a44e6e29a90dbe3b7b0d3921163feb5ac105624ed852bece3538e99193300c893345699350a8f99e8c6a41095fc9fc08da07f75711f7df034406de14edd8e22a633a86e4a5a5c975ac5d34891cccfc8543771ffa080e0b45d65ab830a361ac4c426294d3685ea8c26039c71c90fc3fb512be9fc94807d76dbdaf8ffaa4fbf9849d68e8a57d30c4a0b9735c23f08ef2e284458467e15d665362cb646fde6937ecba53091264638357a722425bc62d1e30ec5f0dd8fea26b2ea4a8490035de43f274846fb0cf0209ec7437f3c3d0a560373d034e5fd79e25b6424d9b2c1761632b35a12132521827345c55e4e7142dd6fe94d620fe515c153e8395b5d130c744139b6a92efd37f22ba13fe4c095373550e2e4fcba0325b3ea3b9fe25cc7dd92cbf42e15f4554b77ac27a4a346382ff6100451508d602cf643f60b6ca4286356f21a3110d4e2c8a8962a780fcff439b3aa80499df270fc3e6cad8893348872f0f702f9390000c7f6e0627d2bbb7b7cef5c4da25dadfea8032e5023297a70a658e9ae73bddc3b227a1c11741133f012f0f48fe26446fa67e64720fc8dc97f30d0dd026f6dc2164ead857824a0a7aeb20f115d50d1b65dd5d82e09abe834e8ca88957e39984824955a1a13e3b94a00157186dcdc289e34b678c91cb2a1a:a6b56b7686df1dc5f4ed544a4d97e67036195a32b22ecd5d31ea1730e6ed8f810d258b44c08ea45f032b937441b72cd0dc37556fd7874e9fe64f15765c521003646f8b34182d5e602b51ca7329347c0e198cb747e4da0a6b80f3f6f9f336f6708d85cb429ab2d6bed35d5013129cd100142cddcee8635179021b3e24922b81aef13c1370286939d63d6b6a4195eda1d812ca518204768f87348c6889552c63d1372cde6a5e9daa7f8445ec8d6130a3f5aef0edeace010b6c7f0b9d24162a8d04454b81d48ea9097bd8df093459719ccb54aa10f51c246aa99c580beaf9c9c5bc60faf0ae5cec7f5137f6c5c144df45d12ee995adccf25a9db81b8558bdfb65830186e7b9d4eed9f6b4d732b1b5822d03eb017c0724f48f87baaae1045d6fdb125c9134064faf18dbed58d8fbaceacd4f097df9b342e5c4a5bc85b29597d4b640f1551c5b624ab21b48e94a9030049be1f05aa851d0827eaf8700dfe147fdcdeedbc98c4f15774f0120fb5970a2f8b21794340b628379a802b9f7c068b0df63193e510fc7b2af97ee38de47929785535528d350d88620610cfdb55d249e38fb73c8287113919ce33267d7db924e4919a44e6e29a90dbe3b7b0d3921163feb5ac105624ed852bece3538e99193300c893345699350a8f99e8c6a41095fc9fc08da07f75711f7df034406de14edd8e22a633a86e4a5a5c975ac5d34891cccfc8543771ffa080e0b45d65ab830a361ac4c426294d3685ea8c26039c71c90fc3fb512be9fc94807d76dbdaf8ffaa4fbf9849d68e8a57d30c4a0b9735c23f08ef2e284458467e15d665362cb646fde6937ecba53091264638357a722425bc62d1e30ec5f0dd8fea26b2ea4a8490035de43f274846fb0cf0209ec7437f3c3d0a560373d034e5fd79e25b6424d9b2c1761632b35a12132521827345c55e4e7142dd6fe94d620fe515c153e8395b5d130c744139b6a92efd37f22ba13fe4c095373550e2e4fcba0325b3ea3b9fe25cc7dd92cbf42e15f4554b77ac27a4a346382ff6100451508d602cf643f60b6ca4286356f21a3110d4e2c8a8962a780fcff439b3aa80499df270fc3e6cad8893348872f0f702f9390000c7f6e0627d2bbb7b7cef5c4da25dadfea8032e5023297a70a658e9ae73bddc3b227a1c11741133f012f0f48fe26446fa67e64720fc8dc97f30d0dd026f6dc2164ead857824a0a7aeb20f115d50d1b65dd5d82e09abe834e8ca88957e39984824955a1a13e3b94a00157186dcdc289e34b678c91cb2a1a: +063b9025e321e972d653a062be34f99365affdcc98ec9ff43ef422be0f80446010d01a63012ac09956ba9ed61df35bb7afe3658bb3004852e47174bd07dd4de7:10d01a63012ac09956ba9ed61df35bb7afe3658bb3004852e47174bd07dd4de7:a7eed29652844ee0049bafb2cf63402971020d7e65c10b91ac5726eea86f40dbc53c3f0abedebaf6cc449b4fea48c015fe4d907b3e5505cff50a121819a2e4a8a296d5751015bbcd7ef6fb7c2727bb000be1342a7d14bca97904edfe8b18ddb63933418327a5af817e95bad74eb790203615d082e71493ead47ccc0901a2ca9f50133c44ef8508d51fb73c616f0147532245822dd102b337a1b2aae2efc72dca7a9419d598a6475233dc1a4ee0ec6d05da12a2b287cb77ffafdde2d0acc28199933e6621eec16ab4245170cf02da80d4922631a23272915165ad88722750035d2a0977bc791d14fb3d8cb02bc77f7c71be5242629a4c9a588dfdde9578494d8baa4e68f5194b8002c8e378a0e833b7c1a96981c4fb05e457ff48260b72493cbcb82ae11673d14cee85288f6370bd4bca9251a7e214c3eb79e7bb6fcebb16c9e056f29b6272743efa6fe8bfd25597ce86898ab3059eb0231c73b5305903fd1319bdf49e599d8bbcd74a8b9767308b61563ccbacd38fc50c83ab44ca759dc9b65b2a4b547c5097f220c1c88b2b0a48f65f91fe78b1501278e1e304de58b4c82a5c399981098a1784eb9042501859f2a93f317e41772fd52f972e51b07ed94d314e1d1af4ed82909a0bef671f54b55db7b70da1f718c8e648aedd6da64b05770526f12bc43f68b95548dac50809a687db97d73f06f47ed08831b60a28e982920632058f0e6c90c0187ff44564f81efd8fd93e327bc6d80b490e088b9a10036c80dcdad49d2be074fbba31e06f7180e5ad1c8823d60966a9ce15503ce60dd40e91eef2359d83d70d98401dde7be3c6b07e57d4e47d04217633d8e263ca348f81fbe9a4a62f45d77c843b6b1ad28466d9dafb1b910b348ed87c686cab292d480c191d187b404a9b1d132ba4e293d3ada99172acc121fe66b845b98b160c5823f601c7758fb26caee85701595b2d52caa2f5688aa2bf2f6c4bb637f8e00f49ab6c26bc6ad89e1367fd28e4917d250893a7b32d39660bde8db49f086fb739e56012c36bea0b26cf6d9357940b00d5a4528f9059aaf08669e5f46c995e60f887b5c4ab88ac7442ed01a14c6a42006baf1f343fefe3e4aca843a324e176b2fe7ec7883d1cbd068bc2fc962ffa60244f654c77ac5650817dc084465545a9230a74826b0c50eb85252a886ff2b1afeaf8:85c81d6b0d8578fa58e13ab391001528b46a1d63a0327c7a4a04087fc668758aa65c01d5a150f935674ef307507e6f4c91e1fc3500b26f649beea87d27563704a7eed29652844ee0049bafb2cf63402971020d7e65c10b91ac5726eea86f40dbc53c3f0abedebaf6cc449b4fea48c015fe4d907b3e5505cff50a121819a2e4a8a296d5751015bbcd7ef6fb7c2727bb000be1342a7d14bca97904edfe8b18ddb63933418327a5af817e95bad74eb790203615d082e71493ead47ccc0901a2ca9f50133c44ef8508d51fb73c616f0147532245822dd102b337a1b2aae2efc72dca7a9419d598a6475233dc1a4ee0ec6d05da12a2b287cb77ffafdde2d0acc28199933e6621eec16ab4245170cf02da80d4922631a23272915165ad88722750035d2a0977bc791d14fb3d8cb02bc77f7c71be5242629a4c9a588dfdde9578494d8baa4e68f5194b8002c8e378a0e833b7c1a96981c4fb05e457ff48260b72493cbcb82ae11673d14cee85288f6370bd4bca9251a7e214c3eb79e7bb6fcebb16c9e056f29b6272743efa6fe8bfd25597ce86898ab3059eb0231c73b5305903fd1319bdf49e599d8bbcd74a8b9767308b61563ccbacd38fc50c83ab44ca759dc9b65b2a4b547c5097f220c1c88b2b0a48f65f91fe78b1501278e1e304de58b4c82a5c399981098a1784eb9042501859f2a93f317e41772fd52f972e51b07ed94d314e1d1af4ed82909a0bef671f54b55db7b70da1f718c8e648aedd6da64b05770526f12bc43f68b95548dac50809a687db97d73f06f47ed08831b60a28e982920632058f0e6c90c0187ff44564f81efd8fd93e327bc6d80b490e088b9a10036c80dcdad49d2be074fbba31e06f7180e5ad1c8823d60966a9ce15503ce60dd40e91eef2359d83d70d98401dde7be3c6b07e57d4e47d04217633d8e263ca348f81fbe9a4a62f45d77c843b6b1ad28466d9dafb1b910b348ed87c686cab292d480c191d187b404a9b1d132ba4e293d3ada99172acc121fe66b845b98b160c5823f601c7758fb26caee85701595b2d52caa2f5688aa2bf2f6c4bb637f8e00f49ab6c26bc6ad89e1367fd28e4917d250893a7b32d39660bde8db49f086fb739e56012c36bea0b26cf6d9357940b00d5a4528f9059aaf08669e5f46c995e60f887b5c4ab88ac7442ed01a14c6a42006baf1f343fefe3e4aca843a324e176b2fe7ec7883d1cbd068bc2fc962ffa60244f654c77ac5650817dc084465545a9230a74826b0c50eb85252a886ff2b1afeaf8: +883cc1381757b0fe0455b77bc9cd0dd464d2b4bf0c7a3c0c2dc775fb78aa373283a8b669ccd01245ce3b818dcb1b588f86535850e6c710c79217fe439824f3fa:83a8b669ccd01245ce3b818dcb1b588f86535850e6c710c79217fe439824f3fa:ffec293d12ea636ca4c4a0a5e2db15342639c476674d2ebdab4aefd4046b5ddb56aeb210c119afdfb8a89128a34f6d77f261edea0772a2f8db140a2640fd8ecadb0b4792169b6b2810aee2c5cd835288bff493bcebeeea28a7a248c36116540fa71736d66b0a475b5fa92c0d46002fca7a1e69d1b59e81a3a6d4f339769daeb20b5f9d75c4c28f692132d28d3c564c09fe3dcca0359c3c63ec377a33f9ee874d8a789d77c96ac05fdf3ab38b2c8274a902ef8bb7f467fc7e073c77b1db5fc8ef966c120c4dae3fb7f5b74abb990166c812a525d123f76ed512125080a1534f3d8bdccc541fc97590287546096fc880bfcfdd00e65c0ebf4a09fd6476ce1b7c8faaa5a1cc2786719a30d8255811184752a88b08ac9f0ff1d6262f2586940afe1fe45e0b563448a55f3030e4c39c1f3f86a733670380eab088e393de09d1f508d2fbcafc649aeae6b8c30e329ec3fd2829be6db0ab8e637ea1095bdc3df3acc23d3cf705a9542c19e59092ec413a4e2bd5ded28cd34ddb3d32949aa487f1c337d6979cf512622dbfb7da1cbb1c7e5abeea7009e2943ffba2252e1d86eca9d6d5c246cd2e134a3e5dad37efef71ce397adafbd9e72b3f9a86ff0f5d812c46225bebd0703bc5cce9c64582008f7e558c40a3b3522096d1aa2b61bc90cd88c6285d942087d8a4665a0e64d3572f74689b4f24ef400d741b57140613471444decc654af0ffb2edfdf9fdd075098190b34cde28dd166872c6086567a68761cef25da40bd4c3d34fddd72ee565b0b937678ee84349d1160f5f0705f895d0f141ce8f51a1e4fd2dc4704b527a4025a939cb2bb78857eb18d78872edc9ee70e60b2a42700a198f4fff6c31925168be077dc23c322abbca97361fecaa3fcb196e656c128f3982fe11e551a4a0885da60d397d0e40d0d897262f1b4b672f78a2d2adfcdd6e1525c26e7195fb9ac606bb1ba4a9890803b4bd84346ae8d8c7196c90aeccb296a4c3eb4efacbfcb62e383b8a494ac723562d0d8c379187a92e3bda6b1569476aed21aed7a056b4a5826744017cc0060b4d55fa8772b5b1c15f5748ad7298005aecbcbd90a3e5c6159a8674abbba37914415002b5a6ef5df3c649426ea1275a01d80adf490ac546062d93999a6dccacb96a0904ad33d90576dc6a21b672e8ffb06613fb3f14e6cbdde88c2437c9:c7cfd5c9fe930d15a11ebb34e3431f489da010eb193edbfa6f23d5d14dd8feabd7880d2d5a5600d38546ce3bc64a86291a1ce31f272ff020df8cb6a0fd4d3a0dffec293d12ea636ca4c4a0a5e2db15342639c476674d2ebdab4aefd4046b5ddb56aeb210c119afdfb8a89128a34f6d77f261edea0772a2f8db140a2640fd8ecadb0b4792169b6b2810aee2c5cd835288bff493bcebeeea28a7a248c36116540fa71736d66b0a475b5fa92c0d46002fca7a1e69d1b59e81a3a6d4f339769daeb20b5f9d75c4c28f692132d28d3c564c09fe3dcca0359c3c63ec377a33f9ee874d8a789d77c96ac05fdf3ab38b2c8274a902ef8bb7f467fc7e073c77b1db5fc8ef966c120c4dae3fb7f5b74abb990166c812a525d123f76ed512125080a1534f3d8bdccc541fc97590287546096fc880bfcfdd00e65c0ebf4a09fd6476ce1b7c8faaa5a1cc2786719a30d8255811184752a88b08ac9f0ff1d6262f2586940afe1fe45e0b563448a55f3030e4c39c1f3f86a733670380eab088e393de09d1f508d2fbcafc649aeae6b8c30e329ec3fd2829be6db0ab8e637ea1095bdc3df3acc23d3cf705a9542c19e59092ec413a4e2bd5ded28cd34ddb3d32949aa487f1c337d6979cf512622dbfb7da1cbb1c7e5abeea7009e2943ffba2252e1d86eca9d6d5c246cd2e134a3e5dad37efef71ce397adafbd9e72b3f9a86ff0f5d812c46225bebd0703bc5cce9c64582008f7e558c40a3b3522096d1aa2b61bc90cd88c6285d942087d8a4665a0e64d3572f74689b4f24ef400d741b57140613471444decc654af0ffb2edfdf9fdd075098190b34cde28dd166872c6086567a68761cef25da40bd4c3d34fddd72ee565b0b937678ee84349d1160f5f0705f895d0f141ce8f51a1e4fd2dc4704b527a4025a939cb2bb78857eb18d78872edc9ee70e60b2a42700a198f4fff6c31925168be077dc23c322abbca97361fecaa3fcb196e656c128f3982fe11e551a4a0885da60d397d0e40d0d897262f1b4b672f78a2d2adfcdd6e1525c26e7195fb9ac606bb1ba4a9890803b4bd84346ae8d8c7196c90aeccb296a4c3eb4efacbfcb62e383b8a494ac723562d0d8c379187a92e3bda6b1569476aed21aed7a056b4a5826744017cc0060b4d55fa8772b5b1c15f5748ad7298005aecbcbd90a3e5c6159a8674abbba37914415002b5a6ef5df3c649426ea1275a01d80adf490ac546062d93999a6dccacb96a0904ad33d90576dc6a21b672e8ffb06613fb3f14e6cbdde88c2437c9: +5e40a7aabbb0830a9ab0fd79690ee0433901c6cb0676abe4bba06f5bbe58fac24d4f28fe09c4aabfca01ef6ee7fd6372fb62db61aaee827c43fd1a6d1c259032:4d4f28fe09c4aabfca01ef6ee7fd6372fb62db61aaee827c43fd1a6d1c259032:fd4ec8b34fc6b743813f59e2fd1fefa870f5a970e2eb7516ef7c306f4b823ffee92d601f765d79ca146aba8bc6e79844559935cddc242649c059ecf2db84fdc219366688a88fc25b851c3661e51988c2bf73bb8e3dc16d22415ab1a7b35579daac7325e319157d7da5fee87c93a4dfcbafc92fba7e17cc68e3903733c6c801572d907320b2feb51710e856a1f76f85a7ee1a11e62d2e45a352938dd8cfc2bccb902dea444faaae6d84c5f391e10aef76928a45153db6cd25a2bf353d80d97bf4b3808605e89800d29840ea60978d9ec9b2c302749888f9debc84dd1e2a79aa0b6ba02a039193081bdbff0599a14d918c0c8deac4f60b6e99474ab53011741034fe2a20cff4e0f023424c8e5797768ad53df6d01a24011fa90f0bb1d5069cdb36b450f433110c2c56f34a1de4260914cd4696b14a09c0268b2ae2e98e6b4e992b9125f878f1ac09823170628388f0f6e256259ca786bbe144884cb298cc043d02f5c3dc684f787faf16c10fdd8437a8c3097463bdb99b78030f9474fc5c9951dc7526490586fe1c2db05411341460239d5e8bc53065902b95fba282c27665e869a19dae84606d1726675155d38039b9e55db4d5ceec95cd6d87f85e99dde54a04761e6eada6619da895b654fe3845e8a60f3a3b32483d6d27978af54502b220e478db78cff77a9c97fb79fb5acf56289f381acb10de64c3f23842b12bf5f1b283bd25d48d09128fb55ddae255beb7c66a74cf6f0695a4f828cb29e4afdbb3b42a235d4fdb66b963ac8f68e82b00a1c4500863296247178cfdef803bb7b114f0c03276f671669a087d9228a37ae7b99b061549c1cf8ec17246ea1ee03dbc88bf426416d586572ff10a3145606f2784e4357be4edeec6c3a7bf11bb5b0e90cf50edaf891e51d26357bfc853ce23b299155c82c1031dfa64074d72a09d29720ead6ebbbf75d5738e32cda6b6466a8def6b50a1ed9b865a9a88a08018acb501a4de9db54d0522ce9cec7a06bd9a5f86b0b46c07bf3e7f5a426ff6b4bbe1e00313a5ac2719a959ed44ee0a44bd97da6db2cb971bd68334908949ed850fbf73d0e02049da181cce9c2d9ca1b624c8d87cf904eb821dc7959295da5777920660b43ccc25cd389f157f67fa0390feac97a752c1ac204c21df56bb0f4fc01641b480af2b89b5d16d4a0bcb0a50b82b0e0484:597672ab8d3a60de5456fcc9c38253f5f37b80e74a007c9f6db909d27d0ead162789244994f35b80d61be199c417c7ea901b98cc63fe3c50fc3c6338490fa206fd4ec8b34fc6b743813f59e2fd1fefa870f5a970e2eb7516ef7c306f4b823ffee92d601f765d79ca146aba8bc6e79844559935cddc242649c059ecf2db84fdc219366688a88fc25b851c3661e51988c2bf73bb8e3dc16d22415ab1a7b35579daac7325e319157d7da5fee87c93a4dfcbafc92fba7e17cc68e3903733c6c801572d907320b2feb51710e856a1f76f85a7ee1a11e62d2e45a352938dd8cfc2bccb902dea444faaae6d84c5f391e10aef76928a45153db6cd25a2bf353d80d97bf4b3808605e89800d29840ea60978d9ec9b2c302749888f9debc84dd1e2a79aa0b6ba02a039193081bdbff0599a14d918c0c8deac4f60b6e99474ab53011741034fe2a20cff4e0f023424c8e5797768ad53df6d01a24011fa90f0bb1d5069cdb36b450f433110c2c56f34a1de4260914cd4696b14a09c0268b2ae2e98e6b4e992b9125f878f1ac09823170628388f0f6e256259ca786bbe144884cb298cc043d02f5c3dc684f787faf16c10fdd8437a8c3097463bdb99b78030f9474fc5c9951dc7526490586fe1c2db05411341460239d5e8bc53065902b95fba282c27665e869a19dae84606d1726675155d38039b9e55db4d5ceec95cd6d87f85e99dde54a04761e6eada6619da895b654fe3845e8a60f3a3b32483d6d27978af54502b220e478db78cff77a9c97fb79fb5acf56289f381acb10de64c3f23842b12bf5f1b283bd25d48d09128fb55ddae255beb7c66a74cf6f0695a4f828cb29e4afdbb3b42a235d4fdb66b963ac8f68e82b00a1c4500863296247178cfdef803bb7b114f0c03276f671669a087d9228a37ae7b99b061549c1cf8ec17246ea1ee03dbc88bf426416d586572ff10a3145606f2784e4357be4edeec6c3a7bf11bb5b0e90cf50edaf891e51d26357bfc853ce23b299155c82c1031dfa64074d72a09d29720ead6ebbbf75d5738e32cda6b6466a8def6b50a1ed9b865a9a88a08018acb501a4de9db54d0522ce9cec7a06bd9a5f86b0b46c07bf3e7f5a426ff6b4bbe1e00313a5ac2719a959ed44ee0a44bd97da6db2cb971bd68334908949ed850fbf73d0e02049da181cce9c2d9ca1b624c8d87cf904eb821dc7959295da5777920660b43ccc25cd389f157f67fa0390feac97a752c1ac204c21df56bb0f4fc01641b480af2b89b5d16d4a0bcb0a50b82b0e0484: +3a34136a973480d97006dc279358e6606293d8cbc1a44ee55233af2b5264b90ce5effd921be8eec530752fccc576ef0d9bcde4b32cc649d3f7954717562860cc:e5effd921be8eec530752fccc576ef0d9bcde4b32cc649d3f7954717562860cc:981c8e1090e396951b072ef8497062020897bf7dd7ad505b4d6dc11b3e1dbcb0da249984a140e164fc2e02b31da39846554aa8905bc8b3df8a76bf60eb5ffcf22c97b671227d249071da8ff6bba75b2f7668cec19a89e6475a12463dabf368b3ca2445bb3035cc00fae85b7072fbcf595401755b8051e6097065ae429f18eeb13ffa6dde59df6f3c206bfd9ce1f8a800c8590a4021d160f66d6740a369ae835617538b5890231f13c5667baf510a606bdaa84b8d10ee6015e12a4c1ec0bd0421a294c51cf63b5d1f058e1153dc425d10cee8b1b084d6c29347e96f0f31b839607d078b79a90ca3d1f063807a463b7c32f45a534498d71d47edc3b17a4dff27fedcffab301f34f1a64c0278a53589349a233af30b1ec1ae410f7b1630c7145ca42c9663f512e8a578267dc95e83289c17032e09782e2fe8e16efb87f03ca03b1195614f89961ca3939d3bdf737221a22d7a18ec30fc126d0ca663e88d6060d04c6a44e5616e556e07d6d4a847f1711cf43717810c70aa4be730278b3bd6555c954dc6edb09db08f0e211803596280f3c7868d2342cc2308eaae4da1913514664b1db962e99c8a8cffe57931f5dfcddbc1cbb36ce1c842e2dddeadfd7e7d0a5048cdcb961b14f35f435e73a683c8ce25c816812566fdf817e0d336ae0bd247328512b2a8567632bf20553d9bd6fe157f220ffb0b46ebae89a70459728a57eed1796256f1bd50b6d547ea3e25fa5913d389a22583e915eb49de35a97b5acc521db0d005c29575e16611a755f21a3a5a82a20aa900a707ce36825492c3ca15395f1700b4afab94daa7a02f1453b1f9a6bd36efb204d928ee1f4dcc860f3a859badc006fb305fa123d4c79b23a20e32295d040a7f8f6caca25d83f71c62e3af7836ef76b93a83d3c3b493af141753da19e4cdcba56617271034b4f4f394c7c6b7d79666f3afb692244f061c69a8881d1b52b8849fb534990ac2391909471ebbb728e29cd20f422354c4309717ebff3efd1833370806d5bfb53ca2da316dacb50ab7fb739673235a1dc53aa8893072d5b91c9f6db83fc4ea41d1eef49ac28afc1ced8f361890ab9f779d193082831cb8c42fb2792bee3b26296b6295eb78a8d853117661624e11f7f57afd6085a7b9123679fdaca1cf2a78d380bc4c360aa7c3cbfde0c0091fe53e2219c070f2f02f1483:425f272212835755adcc0522c6f6e05f68008a3be9ba5974e420c4c5cb56e6c55dec0de347b16caef8bd33b71b44c8357d05b6321d7bf493d25861db487bd603981c8e1090e396951b072ef8497062020897bf7dd7ad505b4d6dc11b3e1dbcb0da249984a140e164fc2e02b31da39846554aa8905bc8b3df8a76bf60eb5ffcf22c97b671227d249071da8ff6bba75b2f7668cec19a89e6475a12463dabf368b3ca2445bb3035cc00fae85b7072fbcf595401755b8051e6097065ae429f18eeb13ffa6dde59df6f3c206bfd9ce1f8a800c8590a4021d160f66d6740a369ae835617538b5890231f13c5667baf510a606bdaa84b8d10ee6015e12a4c1ec0bd0421a294c51cf63b5d1f058e1153dc425d10cee8b1b084d6c29347e96f0f31b839607d078b79a90ca3d1f063807a463b7c32f45a534498d71d47edc3b17a4dff27fedcffab301f34f1a64c0278a53589349a233af30b1ec1ae410f7b1630c7145ca42c9663f512e8a578267dc95e83289c17032e09782e2fe8e16efb87f03ca03b1195614f89961ca3939d3bdf737221a22d7a18ec30fc126d0ca663e88d6060d04c6a44e5616e556e07d6d4a847f1711cf43717810c70aa4be730278b3bd6555c954dc6edb09db08f0e211803596280f3c7868d2342cc2308eaae4da1913514664b1db962e99c8a8cffe57931f5dfcddbc1cbb36ce1c842e2dddeadfd7e7d0a5048cdcb961b14f35f435e73a683c8ce25c816812566fdf817e0d336ae0bd247328512b2a8567632bf20553d9bd6fe157f220ffb0b46ebae89a70459728a57eed1796256f1bd50b6d547ea3e25fa5913d389a22583e915eb49de35a97b5acc521db0d005c29575e16611a755f21a3a5a82a20aa900a707ce36825492c3ca15395f1700b4afab94daa7a02f1453b1f9a6bd36efb204d928ee1f4dcc860f3a859badc006fb305fa123d4c79b23a20e32295d040a7f8f6caca25d83f71c62e3af7836ef76b93a83d3c3b493af141753da19e4cdcba56617271034b4f4f394c7c6b7d79666f3afb692244f061c69a8881d1b52b8849fb534990ac2391909471ebbb728e29cd20f422354c4309717ebff3efd1833370806d5bfb53ca2da316dacb50ab7fb739673235a1dc53aa8893072d5b91c9f6db83fc4ea41d1eef49ac28afc1ced8f361890ab9f779d193082831cb8c42fb2792bee3b26296b6295eb78a8d853117661624e11f7f57afd6085a7b9123679fdaca1cf2a78d380bc4c360aa7c3cbfde0c0091fe53e2219c070f2f02f1483: +cf33e7974d8f0bf899ac5b834c7cf96479ce1cfd453af07f970527f36aa85c1f578f60338b1f041a97d319fecfa30cfaed369303cc00b3ec8c5c99041158e20c:578f60338b1f041a97d319fecfa30cfaed369303cc00b3ec8c5c99041158e20c:e813144bd116f6ac36389217b5171a902f06b7dd7b144df4f9091553c7c7835753a296cbb0d7fab99cef77b61f34a04c8af04e7d5d1f961302de89e2005f299f5a4aa17924617d006693937745539c3048ee36b8c23afec0af9feaa0066c8af8e0a7f09093498210f6d8dcc0aaada5668786910ff7c5b348d4ccd6eeeffa3acd1816d9011a4c4025f6c2fd2c020a10593627520d4dd99e07c62d2dbebe84139e1c7d867c093574fa601e4ee307ac926e5d36b62d7ed84a261588b7e2883c7926612b4cc67e2bb72544a10d6b4929c88ef6c47c2625d2f6816bd73c3bae89d2e0c86171ac4bd080ae555d62740d1d2a761ced86dfc328ecc27ee3db6d404108ef4e0b64906253b4c0a771adefedc8a2c5b53c425a70cd6f63956f7a0a619fdfbfd00aa078418eb4652f8bc6f3c253beec9838b77f9cbe2ef2b8055c5773539e356bd8192606ec101e3f6058b1dd08a68fdbc549dfe6b7725dc2549e8e3f90dc5be3ccfb0a38baf9377cb3f6501d2e15ccb3556a895ccb23f0b6df9fe59311cff55374c3fb3a32981ca26ab426f3663d04e3167e53a537b7589a9fb73679090a205532c132906634334a7e8749793f8c593f3fd6278ce0050383487f3b245067af94881aa1ae968d0caeba5fa5c7be5f4e4b7257518695d89bccdec507b967b4fd64b6893b3ee7803c1d36ea8a02fc426f9afc8e9f24321527ec9844bc3c54a0f7667e034300bbb4fb020f6d5bb954e7b5a3a706a4939db33c154892643476a291d47dc1e6f72ce91d136f11db26b9c9ba736e40df0a15c1a89149996b251dd988b39004e6ef41bdc061db580b7b74de2a651810bd891753b97386d7f8cbdbb6ec386fa2c342f5ef20e6e3a8bb4d5149a7d4de1224dff1d172c87570f776d5ef45959be0938ad79f5d3395cb2721627122887bd7a8983b647797bd41d882641c81431ce8d9b3067adec4cde926c51313f0cf84c5292562dd4908642dd245288484c5568a787d0ced36a352f032da4f7e4de06b11473f650eec65dda99639af2d42d84ee230f4f83623d9c9aaa3b16bda10ddaad25af5c1c10f81c8c51c811a3aa3e3db58a7025e4380e285da474a61ba59173ff042a46a79ab184b070108416f9d6158cf96d0e6db447614a0d9089ebb6aee4ef107be4593d71e79f6798668a740ae4bac5ac7594ecbd5dc82e7d0f9cb:97a5b6d268a5b4175fb06f1f37d0a633519296edc30011c954d8f0b9bbe2641800396c4b35d4b0d7d2a1d17cbbebdc55a809462d6cc19a6fadbe1bd1bae88a01e813144bd116f6ac36389217b5171a902f06b7dd7b144df4f9091553c7c7835753a296cbb0d7fab99cef77b61f34a04c8af04e7d5d1f961302de89e2005f299f5a4aa17924617d006693937745539c3048ee36b8c23afec0af9feaa0066c8af8e0a7f09093498210f6d8dcc0aaada5668786910ff7c5b348d4ccd6eeeffa3acd1816d9011a4c4025f6c2fd2c020a10593627520d4dd99e07c62d2dbebe84139e1c7d867c093574fa601e4ee307ac926e5d36b62d7ed84a261588b7e2883c7926612b4cc67e2bb72544a10d6b4929c88ef6c47c2625d2f6816bd73c3bae89d2e0c86171ac4bd080ae555d62740d1d2a761ced86dfc328ecc27ee3db6d404108ef4e0b64906253b4c0a771adefedc8a2c5b53c425a70cd6f63956f7a0a619fdfbfd00aa078418eb4652f8bc6f3c253beec9838b77f9cbe2ef2b8055c5773539e356bd8192606ec101e3f6058b1dd08a68fdbc549dfe6b7725dc2549e8e3f90dc5be3ccfb0a38baf9377cb3f6501d2e15ccb3556a895ccb23f0b6df9fe59311cff55374c3fb3a32981ca26ab426f3663d04e3167e53a537b7589a9fb73679090a205532c132906634334a7e8749793f8c593f3fd6278ce0050383487f3b245067af94881aa1ae968d0caeba5fa5c7be5f4e4b7257518695d89bccdec507b967b4fd64b6893b3ee7803c1d36ea8a02fc426f9afc8e9f24321527ec9844bc3c54a0f7667e034300bbb4fb020f6d5bb954e7b5a3a706a4939db33c154892643476a291d47dc1e6f72ce91d136f11db26b9c9ba736e40df0a15c1a89149996b251dd988b39004e6ef41bdc061db580b7b74de2a651810bd891753b97386d7f8cbdbb6ec386fa2c342f5ef20e6e3a8bb4d5149a7d4de1224dff1d172c87570f776d5ef45959be0938ad79f5d3395cb2721627122887bd7a8983b647797bd41d882641c81431ce8d9b3067adec4cde926c51313f0cf84c5292562dd4908642dd245288484c5568a787d0ced36a352f032da4f7e4de06b11473f650eec65dda99639af2d42d84ee230f4f83623d9c9aaa3b16bda10ddaad25af5c1c10f81c8c51c811a3aa3e3db58a7025e4380e285da474a61ba59173ff042a46a79ab184b070108416f9d6158cf96d0e6db447614a0d9089ebb6aee4ef107be4593d71e79f6798668a740ae4bac5ac7594ecbd5dc82e7d0f9cb: +51b1ad0ffc21497a33dbdb85ea2bc1ce3d0c2d95d9461a390973fee377fc75f4bad0412575d3801301edee6bc0f276e787357b4122f52de981885851884249cb:bad0412575d3801301edee6bc0f276e787357b4122f52de981885851884249cb:7882e86ef3402f6dbc65cce8315b39765faa4b1fc876fad5f8220cb22a7df2e3580eab3a7e8fa7fbb6b59482ca0e364a131396df792a3241a060e44143b6767493c6bf75f187a9643aa11e11eba7b0a80f0a68b9f1b79f75b66cc59d9da77955fd7e8799f99d6eb08f90d318f4efcbfe71159b10a83aa5fd69bb75336f5df296ea060a426c9545df940bc1454efc1f9dc965f1f22d947303fb8ec12407fff6b1dbe47e3421c31764fd90c83ac711d19926e229a064c61fe3676af300a1716fabe4e3842264adb32e0d9c9f5d4a65d0d7b5c3770d737ee13cbed21d7a1da36aaf7ec0f36fcc476f659681e5160a5a1f49e759b9d0fcd4fdb854eccd99172a47d2c4efbe0b3757631df1bae175f0fa74dd048bb6a5fed8430284349da3d67df2a6f7e8269bc79fb2c5d5ed6084e9076f455ab638919046369a446d57fcada7011cc771bf6d874a8e5d23c687747de41dd04bffc717d6128183846eb594b3cb1c1a8aa04f0d7eba53af39cb1d4e6fecf3113bd8422416f4c44037aeee9e0fdc517c48731fd04ee9c99f5dbca3d574509d7baf3288f2c230a02d1703bdb1611cde2a766dac193de167443d20090dc34d29277a86b1e998b245645117e5111f12f14606c55446dd912d3475c19876e19ac536d317876c4b0a2e0f98616129a5683732a42317c5e809dca956b2abb484ada810a15c81cc8562b555da9458f9b44338490230c7404f3d48611f84127e73e277d88c62212d2a3a351fc67665b18d77216230632cbc781288e15cebf3ec33a7205eb22b9abe4cdbc7ddbaaa53640875eb763f522c36cfff2eb23ee586d775286259fa94a44fa7ec015096a2a446b6732b80024267fe3d5d39d1c48509b3ecaa2e24e54de4d61c097b70f753b5af9a6db6f975d25f4f83d06f879e17ef7c509a541444ba3eb6867838090e22dafdbb0eb3b0565be1579ceecded20f544256c7c4ede3b62843c65b0466be6b7e27305b963ca914e3b7d21736118edb3d658d9d76f509db3b9ca2eae28964a4b3b3c384a81a4890ee96fbe934a6f2aec8eeb6cfe59ac9d3bbc1646ba32a1142fee59fed6fb7bbc0498cc27dead413b7b4351ec206343c0ab89fcf87243b1ab450e58ff11a1140a383f196aa3976ce17cf34530f049a1de90e31753cd85e7f1fd5cf20426c9379feb8c31b4bfec35ea5a78953d75c5cf:cfb65b6ff0377cef511fd97b90c3ecb80833f142a7cf5022ced30b3fb7862086d01339b8866a238cb070276e1944b5fe32cc409947cb91deb1432c291b60fb0d7882e86ef3402f6dbc65cce8315b39765faa4b1fc876fad5f8220cb22a7df2e3580eab3a7e8fa7fbb6b59482ca0e364a131396df792a3241a060e44143b6767493c6bf75f187a9643aa11e11eba7b0a80f0a68b9f1b79f75b66cc59d9da77955fd7e8799f99d6eb08f90d318f4efcbfe71159b10a83aa5fd69bb75336f5df296ea060a426c9545df940bc1454efc1f9dc965f1f22d947303fb8ec12407fff6b1dbe47e3421c31764fd90c83ac711d19926e229a064c61fe3676af300a1716fabe4e3842264adb32e0d9c9f5d4a65d0d7b5c3770d737ee13cbed21d7a1da36aaf7ec0f36fcc476f659681e5160a5a1f49e759b9d0fcd4fdb854eccd99172a47d2c4efbe0b3757631df1bae175f0fa74dd048bb6a5fed8430284349da3d67df2a6f7e8269bc79fb2c5d5ed6084e9076f455ab638919046369a446d57fcada7011cc771bf6d874a8e5d23c687747de41dd04bffc717d6128183846eb594b3cb1c1a8aa04f0d7eba53af39cb1d4e6fecf3113bd8422416f4c44037aeee9e0fdc517c48731fd04ee9c99f5dbca3d574509d7baf3288f2c230a02d1703bdb1611cde2a766dac193de167443d20090dc34d29277a86b1e998b245645117e5111f12f14606c55446dd912d3475c19876e19ac536d317876c4b0a2e0f98616129a5683732a42317c5e809dca956b2abb484ada810a15c81cc8562b555da9458f9b44338490230c7404f3d48611f84127e73e277d88c62212d2a3a351fc67665b18d77216230632cbc781288e15cebf3ec33a7205eb22b9abe4cdbc7ddbaaa53640875eb763f522c36cfff2eb23ee586d775286259fa94a44fa7ec015096a2a446b6732b80024267fe3d5d39d1c48509b3ecaa2e24e54de4d61c097b70f753b5af9a6db6f975d25f4f83d06f879e17ef7c509a541444ba3eb6867838090e22dafdbb0eb3b0565be1579ceecded20f544256c7c4ede3b62843c65b0466be6b7e27305b963ca914e3b7d21736118edb3d658d9d76f509db3b9ca2eae28964a4b3b3c384a81a4890ee96fbe934a6f2aec8eeb6cfe59ac9d3bbc1646ba32a1142fee59fed6fb7bbc0498cc27dead413b7b4351ec206343c0ab89fcf87243b1ab450e58ff11a1140a383f196aa3976ce17cf34530f049a1de90e31753cd85e7f1fd5cf20426c9379feb8c31b4bfec35ea5a78953d75c5cf: +fa2f461ce8c7126218c47c91569e8799797c83368fc842b6e1c22fd52aec70bf6b89b23f1e11a75a53f992f6ca5775008c6e9e7e49c0d8510b0e8369b7a20bcc:6b89b23f1e11a75a53f992f6ca5775008c6e9e7e49c0d8510b0e8369b7a20bcc:799b39802a1827e45c4112fee026034c0e598affce2c550c193fee73f1df8c30c8d3873340088ce859de3471e9d057686c829b5408795e08b3dc7aa3b637c7de9d2172ad0333c1bea861a6232f47f05a10bf5df80815a271256e37e808a0e62f1f07d9e10ebb947d3efabf8a28fa9dccd9a1d599f5fd6165508efd679cf356015058bf4b34118f83aa3e5bc2ce19eca84f718398adbc0a5276cf9d8caffc27e3e6abbe345b0e9ecf89c6771b0e75d408ba2fbb90fcfd70c53f2e4d52ba54d9784cf71c349ef6f14ae4970def6efb5f30e984d6016a196deaec7e04b47619c48bf49dc02f7fef3e13b756174e90d05fcbdd5e13f0e434efd5421b091d517900ed0d5785968862b4bfe5093ab67217180d97554ccd9cc31429326cab42f3f8398060c19db488b5d1c80b29090afd1c6bac3642264800211bc278fcb99dae9dbf49daf1b24ab569dcbb87d4d3547335e35db98400cdfce6790682e93600220ec499245fa4ee15d843831b56cc26418025bf87001605c6691ca6bd40a4e248c309801b76a795ede8ad5308bcb6d1754ab3371f0003bb8c4e4e471954e28b1e9866379f82e1fbacb79d50adddad5b9778b558cddbb0038a5ff3d5c9557b965de3a7082c45a8ecf3e7721eb690b6c71f3d8975d5300f67c4dc4a736846e4ccd26f93463d5bc6f46edc488664be9696be12b02dd104d10cc6b1d82e8117811214a6487d17367e395ade2ef6b26a1783a7e2f245213bc03a755df3ee8ef9f1eff972c6919065cb7b756678d4ddfd193eddc0b42e8689613643146d7428ca37bf31bdf14e31867858f39d2323709eb3b7d7f4e397022378424bdee9bcb74e9d5dfd371f4734998fc18df4cdfb4b5c21c2e50f8d6c15bc14bf4fda6ceb9d8082cae432dfc98bfb3ecd16b8d74f830b642b042875e921b054bd1aaa581f60d718df669f56dc2f10d478997722162e83940e61a1b6e42df2a4a3a7cbcdd611ce96cbcfb5a95cc473231ca13c0609d0ce1ae5ddb5466d6d65eefad9daf2a36901bcc945847da1ed6e2e240e848b231b7d0e1acd06543ec93e768e59985d7e96c8c31fcd1210f0964271e21877525cb134bc3536257dbb11d30a3c4f949fb82ae0c31ccdfe41943251e50aa4355392ac309ef60fc17432a2be4bdb2fcb28607cc45a52b60016bb1d2e23972ff2c2a247d725585b1ef2b15f:84f79d9e8f30e5bb6362239714556b04736fa44465cabaad23beaf5a99fc451ad4ae5a18c7f6f964fa41039216018ec5a2accae1075a6bb3a6ecbc1fca02b904799b39802a1827e45c4112fee026034c0e598affce2c550c193fee73f1df8c30c8d3873340088ce859de3471e9d057686c829b5408795e08b3dc7aa3b637c7de9d2172ad0333c1bea861a6232f47f05a10bf5df80815a271256e37e808a0e62f1f07d9e10ebb947d3efabf8a28fa9dccd9a1d599f5fd6165508efd679cf356015058bf4b34118f83aa3e5bc2ce19eca84f718398adbc0a5276cf9d8caffc27e3e6abbe345b0e9ecf89c6771b0e75d408ba2fbb90fcfd70c53f2e4d52ba54d9784cf71c349ef6f14ae4970def6efb5f30e984d6016a196deaec7e04b47619c48bf49dc02f7fef3e13b756174e90d05fcbdd5e13f0e434efd5421b091d517900ed0d5785968862b4bfe5093ab67217180d97554ccd9cc31429326cab42f3f8398060c19db488b5d1c80b29090afd1c6bac3642264800211bc278fcb99dae9dbf49daf1b24ab569dcbb87d4d3547335e35db98400cdfce6790682e93600220ec499245fa4ee15d843831b56cc26418025bf87001605c6691ca6bd40a4e248c309801b76a795ede8ad5308bcb6d1754ab3371f0003bb8c4e4e471954e28b1e9866379f82e1fbacb79d50adddad5b9778b558cddbb0038a5ff3d5c9557b965de3a7082c45a8ecf3e7721eb690b6c71f3d8975d5300f67c4dc4a736846e4ccd26f93463d5bc6f46edc488664be9696be12b02dd104d10cc6b1d82e8117811214a6487d17367e395ade2ef6b26a1783a7e2f245213bc03a755df3ee8ef9f1eff972c6919065cb7b756678d4ddfd193eddc0b42e8689613643146d7428ca37bf31bdf14e31867858f39d2323709eb3b7d7f4e397022378424bdee9bcb74e9d5dfd371f4734998fc18df4cdfb4b5c21c2e50f8d6c15bc14bf4fda6ceb9d8082cae432dfc98bfb3ecd16b8d74f830b642b042875e921b054bd1aaa581f60d718df669f56dc2f10d478997722162e83940e61a1b6e42df2a4a3a7cbcdd611ce96cbcfb5a95cc473231ca13c0609d0ce1ae5ddb5466d6d65eefad9daf2a36901bcc945847da1ed6e2e240e848b231b7d0e1acd06543ec93e768e59985d7e96c8c31fcd1210f0964271e21877525cb134bc3536257dbb11d30a3c4f949fb82ae0c31ccdfe41943251e50aa4355392ac309ef60fc17432a2be4bdb2fcb28607cc45a52b60016bb1d2e23972ff2c2a247d725585b1ef2b15f: +1be2949d51e7208175826213ee6ae3c091172742e88caa02ed0f313ecbe5d910d7bf4748d6dded5b57a2abf797facc560b48563dfd9dcff4be522c717a6cfda9:d7bf4748d6dded5b57a2abf797facc560b48563dfd9dcff4be522c717a6cfda9:045e2b0ec7bb203a49bdcba941e2b73c23c1fe59a17d21a0124ea24b337f92ab9c923a20576b62d5d0f624e7932c115b5474e0a46a4dc9ec51f6a0ce8d54744d1d52093320e39be203f74a0f5dfac52cf0f995c66df2914b68ad871fbe81525ad2d88ac69933a75aea74ace4e36343ddc06d3208f16d805f5dd786b4daaa166748cfeec5714c85c10478b597ac7f6ae2c98891e38fd414aa811b7621d805eb8fcc46cf4d568a8a92587cbbc1aecc12f10d90ac1e01ae986d14fe82951c682ceac8c925fc6654d838ac9353ae2f93f3c88bf7b82cbc43b1e49e5cebfb1949ade4b22e4bcf1b400c0a8fa8a6fe7670f69fc3faecd4805b8c954c01a540d1a1e788436eae073ae956dae3176905a8f0a3c60fd980dab419d41ec06e5273fbb13db9381f89b663ccc4bd753fd90f14a77b3d81c45dd3561cd1fa0e94d234cef9d7859a2ec942bfc18849d7f2ada3a5d657bc193d2e1491682f1665a534b1ac2083b738be8f9e963f5941ed483c6acc82e959b81b8af02f471c08f5f8b12e10e008192898a4450202af731592e74efe2a948e51d06e44de9b956b7bc9a69b6e74687ab206dec4d35b3173fbc438829d5064bfbcf743c1e2d46f628f2e51c626d8e416d7be6e555a249691abb167f1d92f4fa3392fde24e993ce7ff5c1b8e1577a7c0e73025cc6fcd727a82ef0c129e91e5533e021a3cdbb99d54bf7cdcd3ff119154f3fad9242b6ed350d10372c976ff3a437d097867d9bfba91d84bda55a6bcd6e3641b213a218b3041589c55afbb344de6e97d8c35b5c86cf3be063f901ffeea8cc91069967d2346035a91eb5706a3b53f6d1c34d4d2116706b65c298ec57de82abc4003ce8cc5e0b88ff710dda1dcef6f154277106b83eb46c045b082d113b361d6a625808c9130584dfc96707ef8955907baa61cf88c66b6d1f60581119cb6217a852157336178c685e6ed48526ed5c4e3b7967d51f99df6876a1acfb845c571b898656e5e3bc73980b9bed1198866359c9e9b1efa915f810d1ef8ad6cb3fc21fbfe654306de6ca13a3a6a48e7a13ed8746acbd07f48eb00c36374b1eb4f3f01c19e2e8d37e9fc064b33c0d669bba554ddc6821a77b4089cabdcafc97f60e6050bca444ae8cfc44d93c40ef5318bee6f8cf0c067b85cdddc45974a4eacfc3ef51315ba0f3f62968c7003a7ff444612400b159:f41f2ef6595f17660bb2fe93e51fc6fa9c31dadc9db90c3f46607a7fb4800bb75ad96325dc7eab782472b04da6d8e6fe64655dea551fbd5049e876ce5a405f02045e2b0ec7bb203a49bdcba941e2b73c23c1fe59a17d21a0124ea24b337f92ab9c923a20576b62d5d0f624e7932c115b5474e0a46a4dc9ec51f6a0ce8d54744d1d52093320e39be203f74a0f5dfac52cf0f995c66df2914b68ad871fbe81525ad2d88ac69933a75aea74ace4e36343ddc06d3208f16d805f5dd786b4daaa166748cfeec5714c85c10478b597ac7f6ae2c98891e38fd414aa811b7621d805eb8fcc46cf4d568a8a92587cbbc1aecc12f10d90ac1e01ae986d14fe82951c682ceac8c925fc6654d838ac9353ae2f93f3c88bf7b82cbc43b1e49e5cebfb1949ade4b22e4bcf1b400c0a8fa8a6fe7670f69fc3faecd4805b8c954c01a540d1a1e788436eae073ae956dae3176905a8f0a3c60fd980dab419d41ec06e5273fbb13db9381f89b663ccc4bd753fd90f14a77b3d81c45dd3561cd1fa0e94d234cef9d7859a2ec942bfc18849d7f2ada3a5d657bc193d2e1491682f1665a534b1ac2083b738be8f9e963f5941ed483c6acc82e959b81b8af02f471c08f5f8b12e10e008192898a4450202af731592e74efe2a948e51d06e44de9b956b7bc9a69b6e74687ab206dec4d35b3173fbc438829d5064bfbcf743c1e2d46f628f2e51c626d8e416d7be6e555a249691abb167f1d92f4fa3392fde24e993ce7ff5c1b8e1577a7c0e73025cc6fcd727a82ef0c129e91e5533e021a3cdbb99d54bf7cdcd3ff119154f3fad9242b6ed350d10372c976ff3a437d097867d9bfba91d84bda55a6bcd6e3641b213a218b3041589c55afbb344de6e97d8c35b5c86cf3be063f901ffeea8cc91069967d2346035a91eb5706a3b53f6d1c34d4d2116706b65c298ec57de82abc4003ce8cc5e0b88ff710dda1dcef6f154277106b83eb46c045b082d113b361d6a625808c9130584dfc96707ef8955907baa61cf88c66b6d1f60581119cb6217a852157336178c685e6ed48526ed5c4e3b7967d51f99df6876a1acfb845c571b898656e5e3bc73980b9bed1198866359c9e9b1efa915f810d1ef8ad6cb3fc21fbfe654306de6ca13a3a6a48e7a13ed8746acbd07f48eb00c36374b1eb4f3f01c19e2e8d37e9fc064b33c0d669bba554ddc6821a77b4089cabdcafc97f60e6050bca444ae8cfc44d93c40ef5318bee6f8cf0c067b85cdddc45974a4eacfc3ef51315ba0f3f62968c7003a7ff444612400b159: +3b6ba6d5cc9cd6241d8b0097a3722e4d066fea3d560aeab4673e86f1f8ec60268ca6520717cf363c4ceffa76328a0a166ff83e45ca7d191cc8ef6ca6e5243367:8ca6520717cf363c4ceffa76328a0a166ff83e45ca7d191cc8ef6ca6e5243367:36de930cc8e18860836a0c829d89e963a58bdd9c6b6ef5bc61f75992d2075242dca23e28de205a33dfea861fc44a32628e8e7cdd3ed7ff49ea6a7097e0090cfd9ff5ecab1de822fc0a4c3776dd56c1919204516a94cec5638da1d99e52b866f5ec4162a912edb41c1e92edfc353f6705e1c12cd41cb62ded4ad8157940059bfcf50719d3f2ad00848540ce89f3f9afa610ccba5ecc37e3e2c1534fcb38fcd39a2d14d5b5da6fea24e006654e309047a29cad0ae4da8e708f97a18cad5fbdc9ac84400c532ced548886539edd6c541074790ae4502fdfe9f3273a876a218623a25706a1525e67e57a16d22c21b6a45e2384e287ac4452aec4e063056b4c178ab0e5b2a5bad3f463c472c4ea1f9c1a66e5270473a835094e8f0eef680cd7b20d0e70f4d6c958fee08a9360aa6066888f4dd7ce5ec22259fa0b53fe9271c083c6fcdb7283b09061088c52f71bfdd2777ce0801f41a6c4ce90ef131de1e183cb8949ce323c9eb13a4b0cacf99defdfdb68d5ed1f6891b48e21047668d69de8a80f8e5634ded08736a4fb5410cdea9c72596e36df6841f2eea46850c87473c895540205b0921960ffa5d9d8ffb8e29cde96a3ede015acbc26974004d3e438a85b2e3385f64d1814003941ffd363992d3940c6e6d81ff8e45fced6d36ce198d8ccbefee432a77d8fcadd73fb799f6bafefb51a2da798721c3d465b163ef13e6ecc65e603b2893ee4cc9e1c6d1de7a65cab5cbdf536855e288c3ccda8d2fa3ce10cf49358a2ef4ef076e5bfa91bbcf3d966dfa3dc6e712f1956d4e58aa36e712dd3347169b19c8d44bec5bcb730778fcccc589ed5d350d44c17bde2eebb6f5ec59fb240d67d81aea9267f34f15eee2de3f4fa67391479bdbb430f484370fb0e0895b9ae065bbdd43e230c62ac07184e8b06b24b8b97ec02dc6f37ef61641ed56e3f5eb8d2080b5144ef760b518752e19754792e19343a3855e1e2f7a7dc623517eed2f5d26548a68eb8ffd7bf70f78fd186db634928bb98138f2b8fe84481cc53f5aa35e2666c6325e1d2b8ac5e2df2935b7f6413952d10d6076ffc75bb6af63b29b0b9663bec37247b66b508dde41f2f11b84333559dfac73f761bcda84a48d266073aef1638460849e7a17206a25f6800770b914cc026baf9e3255914e13258441cef35ad1d66833e987ebe4431e6a6bb222cbb65af:788c9f4554ddba5c7d64ba759ec45694ec79fb85e82368a074bdd8df344213a56dd09f334cd9acb941be283d98c4b15dcfecd14e93f6a2e3cb0c1aa2dee7d90b36de930cc8e18860836a0c829d89e963a58bdd9c6b6ef5bc61f75992d2075242dca23e28de205a33dfea861fc44a32628e8e7cdd3ed7ff49ea6a7097e0090cfd9ff5ecab1de822fc0a4c3776dd56c1919204516a94cec5638da1d99e52b866f5ec4162a912edb41c1e92edfc353f6705e1c12cd41cb62ded4ad8157940059bfcf50719d3f2ad00848540ce89f3f9afa610ccba5ecc37e3e2c1534fcb38fcd39a2d14d5b5da6fea24e006654e309047a29cad0ae4da8e708f97a18cad5fbdc9ac84400c532ced548886539edd6c541074790ae4502fdfe9f3273a876a218623a25706a1525e67e57a16d22c21b6a45e2384e287ac4452aec4e063056b4c178ab0e5b2a5bad3f463c472c4ea1f9c1a66e5270473a835094e8f0eef680cd7b20d0e70f4d6c958fee08a9360aa6066888f4dd7ce5ec22259fa0b53fe9271c083c6fcdb7283b09061088c52f71bfdd2777ce0801f41a6c4ce90ef131de1e183cb8949ce323c9eb13a4b0cacf99defdfdb68d5ed1f6891b48e21047668d69de8a80f8e5634ded08736a4fb5410cdea9c72596e36df6841f2eea46850c87473c895540205b0921960ffa5d9d8ffb8e29cde96a3ede015acbc26974004d3e438a85b2e3385f64d1814003941ffd363992d3940c6e6d81ff8e45fced6d36ce198d8ccbefee432a77d8fcadd73fb799f6bafefb51a2da798721c3d465b163ef13e6ecc65e603b2893ee4cc9e1c6d1de7a65cab5cbdf536855e288c3ccda8d2fa3ce10cf49358a2ef4ef076e5bfa91bbcf3d966dfa3dc6e712f1956d4e58aa36e712dd3347169b19c8d44bec5bcb730778fcccc589ed5d350d44c17bde2eebb6f5ec59fb240d67d81aea9267f34f15eee2de3f4fa67391479bdbb430f484370fb0e0895b9ae065bbdd43e230c62ac07184e8b06b24b8b97ec02dc6f37ef61641ed56e3f5eb8d2080b5144ef760b518752e19754792e19343a3855e1e2f7a7dc623517eed2f5d26548a68eb8ffd7bf70f78fd186db634928bb98138f2b8fe84481cc53f5aa35e2666c6325e1d2b8ac5e2df2935b7f6413952d10d6076ffc75bb6af63b29b0b9663bec37247b66b508dde41f2f11b84333559dfac73f761bcda84a48d266073aef1638460849e7a17206a25f6800770b914cc026baf9e3255914e13258441cef35ad1d66833e987ebe4431e6a6bb222cbb65af: +dd9987b18f9a922c0f6fea18eb00b896c7a2d3093db3ea31d38421da0de51231573921a955feb6dde41b055c8dacaccd1db7fe9e36b509d3c9e36f9735752324:573921a955feb6dde41b055c8dacaccd1db7fe9e36b509d3c9e36f9735752324:48162fdc3abf7319c6caab60cb8d0520875cb4ee8a07092783167d4733ffe5204e5febe7d291e9536bdea3df0637159a653e09fd99af661d8300ae741a3e91a8bd85ead05dc7d9e6f929323316edc4ca624ea7818b25bdc061f71492fd22d465ab226fd9a10d8babfc074c686c436c24a3a53f8ff389ce9ca1dbc8907445889241f8fda3a7a3f5024fa8cb0d044bdaf6716d983a6d839814ffe70ddc55bbba11ac97887bdb4dada96565bb075d5fc1d3c5244b9fff77de58729a059a911fb3e0eb164fb8429e265685d14a63233046d20ecf289c55723169a9d63dda0d5255153d9ef4a61b9212f4b820697ae7c308cfab403b2c3431906226e45ce21920df5201609daf830f28ad796005a9bd8eba620cf839c3ba227b963c7bd0914822df2ca03c2254d0cb8acae0d59e4c3e0ec215c836969dcd1d49bfe197e2f3eea3fa8a373b558d0fb9063cf1568e739aad8f09fb437cafb5a272375f436064eee11bd903d3aaeab4e3fdcd36bd2076eea179a4f0d4fbc8df42bf2660f08de7d5c6397cae10b7277458aa6cfa01e8a6737eb126227856646691681c106a157a26aed21b1aaf0ed2766421cfc3d1c7ddfb72fcdf4b8b490fc09ace49aedd7712b21ac56f8601f625563c784306f3b9174addf764e051aadfe12831af9669e62cab121c74df343724429d6c26660271c32f40cf7c2d08bd0afcc728def4135d4eb55b6a3e7629d806864a85b36a32b9b21ac0d39680a2ae4ec4189709178e349497f39399fbc78b3c6cfaca6edea7c33dda3cc11e4384f1583d6cfc6b58f4eaa2bc56aba42f738a429b93580850dee3fd253994f8b0fa66ee8e273decabd532095fb04a4a3c340af0e55b57efab43630fc02ef20b425ca2187e3c6c5e10f12d618fd243a224f6501ebeb9d321c6385b8127ef9cdcd097ce7fa021cf40d21c39912343f67acce1825e3a51b8a718e8c340622fff65fe0053d24aa3351b6a2400185d7aeb88e87ac4a1d394909d49414aefc22ba009aff6962c9217d755694e4d6aa8a5d6a803cebb15de8f541634b6fceb0cac79dda8a18eefbb537e70ffe9aa5a6a6aaf9240fac2eacbfbef01ad6bdf50758780f86a4e488985362d5825011f5e8b66425a616b7e104eb23fe8f100cb0249823662bda3da47a4c3c1ca2f914b25b9738534026047df6d7ff631df2c4131f680e13743c9ccf2:3e9f2b007c0e29ec875995a6309b973deb8baf113ded13f1e0003e9b9bf93916a4dfe47937dadfc78aa663c55f674ec35c3846258f18e7bb93fbba3e826a1f0d48162fdc3abf7319c6caab60cb8d0520875cb4ee8a07092783167d4733ffe5204e5febe7d291e9536bdea3df0637159a653e09fd99af661d8300ae741a3e91a8bd85ead05dc7d9e6f929323316edc4ca624ea7818b25bdc061f71492fd22d465ab226fd9a10d8babfc074c686c436c24a3a53f8ff389ce9ca1dbc8907445889241f8fda3a7a3f5024fa8cb0d044bdaf6716d983a6d839814ffe70ddc55bbba11ac97887bdb4dada96565bb075d5fc1d3c5244b9fff77de58729a059a911fb3e0eb164fb8429e265685d14a63233046d20ecf289c55723169a9d63dda0d5255153d9ef4a61b9212f4b820697ae7c308cfab403b2c3431906226e45ce21920df5201609daf830f28ad796005a9bd8eba620cf839c3ba227b963c7bd0914822df2ca03c2254d0cb8acae0d59e4c3e0ec215c836969dcd1d49bfe197e2f3eea3fa8a373b558d0fb9063cf1568e739aad8f09fb437cafb5a272375f436064eee11bd903d3aaeab4e3fdcd36bd2076eea179a4f0d4fbc8df42bf2660f08de7d5c6397cae10b7277458aa6cfa01e8a6737eb126227856646691681c106a157a26aed21b1aaf0ed2766421cfc3d1c7ddfb72fcdf4b8b490fc09ace49aedd7712b21ac56f8601f625563c784306f3b9174addf764e051aadfe12831af9669e62cab121c74df343724429d6c26660271c32f40cf7c2d08bd0afcc728def4135d4eb55b6a3e7629d806864a85b36a32b9b21ac0d39680a2ae4ec4189709178e349497f39399fbc78b3c6cfaca6edea7c33dda3cc11e4384f1583d6cfc6b58f4eaa2bc56aba42f738a429b93580850dee3fd253994f8b0fa66ee8e273decabd532095fb04a4a3c340af0e55b57efab43630fc02ef20b425ca2187e3c6c5e10f12d618fd243a224f6501ebeb9d321c6385b8127ef9cdcd097ce7fa021cf40d21c39912343f67acce1825e3a51b8a718e8c340622fff65fe0053d24aa3351b6a2400185d7aeb88e87ac4a1d394909d49414aefc22ba009aff6962c9217d755694e4d6aa8a5d6a803cebb15de8f541634b6fceb0cac79dda8a18eefbb537e70ffe9aa5a6a6aaf9240fac2eacbfbef01ad6bdf50758780f86a4e488985362d5825011f5e8b66425a616b7e104eb23fe8f100cb0249823662bda3da47a4c3c1ca2f914b25b9738534026047df6d7ff631df2c4131f680e13743c9ccf2: +38d2ef509f93051f145167737c22e1a5bfe8f4a91eba0bb87c39ce04a89baec601115f6d89a5daab54f892bb4a4bda1ce5d8f6c9c88a50cee83bd987a2c0ddf7:01115f6d89a5daab54f892bb4a4bda1ce5d8f6c9c88a50cee83bd987a2c0ddf7:427b5a01e8597f04fd422f0a662d0be2dfa853ed5f9d3f60ff90f2c5ee08bb59fd03d402b754caf54d0058f5a2cf87af4fef2177d59e18226293fd2af376bc987bf7b320b9d1e249ab9efb75078e6d3df29e03504776354344aa69e72e1ebc52a3c38a4c2a1673b4e974a2e4e12a2e78ea3e3fe50c53630d096da3e2fe8299f71a1b441b4cf0caeb937afa4a0e3915ccab3996c9f6a8f4fd37543e8f75900cfd47175370efb852a5f69d673683f998fdcff85ff8f32baa807066604422027d51a435ddf988ed2fd8eb191f10b46807420008756eb4e300c4099c2d6450bcc6a4e7d0673156b837f0506338f3d1b5734b166ca5cc2f24a4ef026cda2c4ae3105b63ca8570d18546cfacb86042966a00ef52c7299019f68a2df08c8b704e85e713c348d7f1677660e18ebab59bf4e12e6ff2d783d8d5d42aab6ef017b7a1966aee8dc14ddabed49b4b643df4e9b0b60383c7d8b4b88c65a898c1c77d43d6bd68b2a5743f1fedd654dc84496da02ceb69b9b4d3a8e00ccd72e7c75fc50a8dd087e183e6c1f579baebc5c63f2807936791b5fe4847cdcf151774235205cd2d7b8bf4ae8819225ea708b7baac66998f0cbab2c7ddf251f3b1de1017d397692205eea639f12d77beef6c13bb12100ff8906470bc7b21298053be1a61b7b3a499edc310996c8bc0871907ca468e89ed311adca2e2b82930975b3efbbfc03cddf4d948c4765e8c10590882169acddb8f8c36d84c2dac3b798e7abf844712fa458d277c24e814047d742319a834dd9f927a2b4485ef13745f7a60dd6bb337936304c97d3f9f144eb29bb695b8dc31b9d84910611d28d581caa9365d6dff52d410a4ad52bd121729fff52888f4daae1707f6f56dac61ffb9961cda7176af4460a6d5542a20446fb5147fce727204cec6899b9a3d4ff6226bb8a1c78e36fcdd9e50c040d72d0f4007d3fa9aa767e4abd0add62fdbccdeff6721eb259e00a721632006bede0d173d38344dea44f96b67d9a2eea1d2af5f748e8ebdb441bfb4e58e2d42fec740566acf73a303358f7d89c8158cf21fe85b0d4a417ebdc86d0469f6b91c24ad610d486dedc218b2ce7a8b96754723151f0d0076fff9f19d112d9c0592fb8d92c99dcb8ddfaa46fbe0d92df46b8c00ca4345adb69a5aca694a86cf30646451bb17ba6e607a912bf109d5fc2d3e27d00d945600a8a57c:dec46253509b11e4b52a6ae4f366b680dffc280d0a044fc0cb790b6e751381461e1e602a89e3b3d3064c407f602f1c22404b6823bd2467549314a00001664a08427b5a01e8597f04fd422f0a662d0be2dfa853ed5f9d3f60ff90f2c5ee08bb59fd03d402b754caf54d0058f5a2cf87af4fef2177d59e18226293fd2af376bc987bf7b320b9d1e249ab9efb75078e6d3df29e03504776354344aa69e72e1ebc52a3c38a4c2a1673b4e974a2e4e12a2e78ea3e3fe50c53630d096da3e2fe8299f71a1b441b4cf0caeb937afa4a0e3915ccab3996c9f6a8f4fd37543e8f75900cfd47175370efb852a5f69d673683f998fdcff85ff8f32baa807066604422027d51a435ddf988ed2fd8eb191f10b46807420008756eb4e300c4099c2d6450bcc6a4e7d0673156b837f0506338f3d1b5734b166ca5cc2f24a4ef026cda2c4ae3105b63ca8570d18546cfacb86042966a00ef52c7299019f68a2df08c8b704e85e713c348d7f1677660e18ebab59bf4e12e6ff2d783d8d5d42aab6ef017b7a1966aee8dc14ddabed49b4b643df4e9b0b60383c7d8b4b88c65a898c1c77d43d6bd68b2a5743f1fedd654dc84496da02ceb69b9b4d3a8e00ccd72e7c75fc50a8dd087e183e6c1f579baebc5c63f2807936791b5fe4847cdcf151774235205cd2d7b8bf4ae8819225ea708b7baac66998f0cbab2c7ddf251f3b1de1017d397692205eea639f12d77beef6c13bb12100ff8906470bc7b21298053be1a61b7b3a499edc310996c8bc0871907ca468e89ed311adca2e2b82930975b3efbbfc03cddf4d948c4765e8c10590882169acddb8f8c36d84c2dac3b798e7abf844712fa458d277c24e814047d742319a834dd9f927a2b4485ef13745f7a60dd6bb337936304c97d3f9f144eb29bb695b8dc31b9d84910611d28d581caa9365d6dff52d410a4ad52bd121729fff52888f4daae1707f6f56dac61ffb9961cda7176af4460a6d5542a20446fb5147fce727204cec6899b9a3d4ff6226bb8a1c78e36fcdd9e50c040d72d0f4007d3fa9aa767e4abd0add62fdbccdeff6721eb259e00a721632006bede0d173d38344dea44f96b67d9a2eea1d2af5f748e8ebdb441bfb4e58e2d42fec740566acf73a303358f7d89c8158cf21fe85b0d4a417ebdc86d0469f6b91c24ad610d486dedc218b2ce7a8b96754723151f0d0076fff9f19d112d9c0592fb8d92c99dcb8ddfaa46fbe0d92df46b8c00ca4345adb69a5aca694a86cf30646451bb17ba6e607a912bf109d5fc2d3e27d00d945600a8a57c: +43bfb3dbe4d9bdaa82b354dd596334e660d76fc0b2eb698993aef3767f1c7c7fd00aeceff0ceb832c251d1fe6bcbeaeacbb4113f5281baba4e878f7b95f93f07:d00aeceff0ceb832c251d1fe6bcbeaeacbb4113f5281baba4e878f7b95f93f07:3f3eeddcaef4e1662adb66bb1b207d793fcbef815005e82643ed70c9855403dac28b520727a901a532d28b9bd1348db2f8967bbb8c9098b07f570a2eae1ee482640c0b67a52a38612133a15e258ede38cda878ff36ed321dff87cc6a01383ba84067d60af41776acf80a8a4eac77f7d87c37a704a3e2aca1e8815e49fbcab797c856529538be07d51696321f69b09b5dc5a15e5f0e4c22d22837f62ee4c8bc7f25a9487b962cc20f133fcb870ed125cca585d181bd39f9dfa661f19be76da7f65f22fbbc80752aeb39e8d59ed96e14f595d04929402b5029c60cee37c0217bc531d80db341dace3cce76e643aac53887473edc6e19cb39fecf6af424a2066393d1c33fc7b93676d7e6105b9bfc967d1e29afdc4cf15bcafa09c295a6f9deee331ab3b0d493126e2b2fffb42a6b68e79e138db550827262e487a83f37f01dd7922be75e92fcf5d9d4803b3ac2f35da210fb38b263b0ffb6c2708d4b55b757af52077a7e3184d01e82f64d32cce4fdee0f8d4e364bcfb958ebbfdbb622b38b51e930271c7b1b70aa9d4bb3aa4b997c52144d3aa62162573a3a1d9ce46cdbeeb8449f1225c449631e8897521cd0f637b721a1252b8a10ab0be870afbcd89d58b2ebb63211950cad7ab82c8195026b50ea8b77b9e90ed559af4484308851a3a156716853a8ac4ecb8c5cc7d935b0f466124143b1177f05d08b97d1ad542ed2c2465af185e7db42b69cb802a71794a3139883029670c956742aaad7907a71d95985fc1d45b65997b4ec6ce8255de959270afa7de90f2929de63f9b17211d7f1ae820ada9ce3e48649179d60b0149493481f01d459db7dad0526b5bd9f4b3380d25ba2c502ba8fa3c4d4131b4662addefb41827f759fa71d447d5f029245f48c622eb7c68c8e71081f7f789de7a283d2eda83a7d1722a05fb72e1760c24040c4d834def5df5f742e02b30451c893bcf7d771db784cbbdaec876d8ac86743b529a292007ac753c99a5799cc324fe5ebb5448ab554b10d4136974a12542d25c6147c67c5d2336c9db75cba2fd608cd43ab95beacd043a1349cefa828e23b5f0b6e0e2951f3353bb92bfd1f0a49c33fb3cf3799a0b543198ad5d03d263c1a06c35a26ade1518491c8c1d27a2db033808932cd1c47b5a126985acb8d888360eeccfeb3bf51b0d189b4190440404d12fba65d0a7a14c620c555f822:a9995523020a0d222bc48f98d05504e3068f304a6d197006cc9c035eeade099e7aa97e90894ead17e8c30b0aa4a98088f038b92244c4b20fde964f8534e8fb033f3eeddcaef4e1662adb66bb1b207d793fcbef815005e82643ed70c9855403dac28b520727a901a532d28b9bd1348db2f8967bbb8c9098b07f570a2eae1ee482640c0b67a52a38612133a15e258ede38cda878ff36ed321dff87cc6a01383ba84067d60af41776acf80a8a4eac77f7d87c37a704a3e2aca1e8815e49fbcab797c856529538be07d51696321f69b09b5dc5a15e5f0e4c22d22837f62ee4c8bc7f25a9487b962cc20f133fcb870ed125cca585d181bd39f9dfa661f19be76da7f65f22fbbc80752aeb39e8d59ed96e14f595d04929402b5029c60cee37c0217bc531d80db341dace3cce76e643aac53887473edc6e19cb39fecf6af424a2066393d1c33fc7b93676d7e6105b9bfc967d1e29afdc4cf15bcafa09c295a6f9deee331ab3b0d493126e2b2fffb42a6b68e79e138db550827262e487a83f37f01dd7922be75e92fcf5d9d4803b3ac2f35da210fb38b263b0ffb6c2708d4b55b757af52077a7e3184d01e82f64d32cce4fdee0f8d4e364bcfb958ebbfdbb622b38b51e930271c7b1b70aa9d4bb3aa4b997c52144d3aa62162573a3a1d9ce46cdbeeb8449f1225c449631e8897521cd0f637b721a1252b8a10ab0be870afbcd89d58b2ebb63211950cad7ab82c8195026b50ea8b77b9e90ed559af4484308851a3a156716853a8ac4ecb8c5cc7d935b0f466124143b1177f05d08b97d1ad542ed2c2465af185e7db42b69cb802a71794a3139883029670c956742aaad7907a71d95985fc1d45b65997b4ec6ce8255de959270afa7de90f2929de63f9b17211d7f1ae820ada9ce3e48649179d60b0149493481f01d459db7dad0526b5bd9f4b3380d25ba2c502ba8fa3c4d4131b4662addefb41827f759fa71d447d5f029245f48c622eb7c68c8e71081f7f789de7a283d2eda83a7d1722a05fb72e1760c24040c4d834def5df5f742e02b30451c893bcf7d771db784cbbdaec876d8ac86743b529a292007ac753c99a5799cc324fe5ebb5448ab554b10d4136974a12542d25c6147c67c5d2336c9db75cba2fd608cd43ab95beacd043a1349cefa828e23b5f0b6e0e2951f3353bb92bfd1f0a49c33fb3cf3799a0b543198ad5d03d263c1a06c35a26ade1518491c8c1d27a2db033808932cd1c47b5a126985acb8d888360eeccfeb3bf51b0d189b4190440404d12fba65d0a7a14c620c555f822: +514e070b0190d18cbe981a5a151e7753398a272bcf014813ad379722c36e133d6fbde0474cc4810effa50a07820c965aa00395ff3a5b3e2edd7d356b7d6aef2b:6fbde0474cc4810effa50a07820c965aa00395ff3a5b3e2edd7d356b7d6aef2b:831455762a5d80097bb2845042f4c876e7108535bed683e8c44619d08154a229444b101e3ed7c01507e870941446af978c0f5341d1ac1dd15b14e8966712df19f52feb5103cf62b6632756446cc754df00a3f6dd719968a2cef66c3adfb7d1fc491fbbf3d59294ab34619e176db0d446151e37eaa3daf172406e983d9d23a6b69e92976030f5ac7040ad5114129feaf97af15b2296fae70492dbbeb2b4827687fb798715c9bb2c32557a81d891b897052900707159751f07db074c77f0719671f1766689029a3cddf39df3483cf2b04f71c25de05fc2d02bb48e539eaf1a321646cd80ef2f0ac703f45e7389530800e5d417ccea8a5c086682f04745d50b5dfc8f6edc87a95c7d202a9cfd998714b746920ebbe2335bca1a0171762016f5e4bda89c57d0edc6910c6d22c8f909da3db1352f0c8bd18f3b5aac25f193b89470f976bc4f1affb3c66bc5876c6fe2ac7508533d97bbcf77119d9aae193f07e0b64b461c9c6c3b9d293bd37de3d8e1ab1e8d872cd94e6cf0eb68439fdcd3b25ce8483460bd8b7cce889fb722b4361e118da983ef4a9e45cebc0c1b8229ea53e6f55505f644e09acaa4c4b8cc640b2cd2b312e1c3a2c02669e1f9c06311c78d360009db9e67c39b49d1e5d770c01d284b0a17a41b4e7ca745d665ec07500e4d9fc8ebc1cc6af53a3fc76b0c3f1431d49843f20e182782c82b3b5aae36fe20ca642618068be233d4b5ef9eaeff401536dc593a2bc18344f55ac5d5fc7b3eb506d11cb375330063c620c5334d723c7d1f042816bc4785b35ac0e6f174f736878b7b491658ca67d8fcab538fc6ecd277ead90d954b460da4253a1c3a30b3d8928f69ac9876a2891969fc2d06a668992b8e2115dfe5358a7124ba7ccf421d8054ea043444cdeb40b716dc7a3659a3ca94347293489060e2cf6712a2a6c7b8ad146785fc40ccb9da287830d011d0d24df3e7afbe972d6f417de5cd75f259ea07cafdde205fc0a365135c232cbd7c1bc539fa4b7e1cce35185237c23f80ae97c186d0d3b10503d5984a20ec41c3cd042c28a4c31f9574b06a872bf959ab0add1f5dee14a1e741ef238dfcdec085aa088dcf39a36dda8f2a85ed0d362ccb005d02e5accc092a376dc11a566170d583db35f1de0be3f15908596e9b781ac81be07b9bd2af46c56fb4d9d84276011e4618b7f76f96794cd0fd57ed414b63:b6c355c958b5baa7ebe977a93fcf539589a366d40160e4e031b88ab96402c7bd577ff635fc07782423598dca43668124a8b287510e2cfd07a1e8f619f6c8540a831455762a5d80097bb2845042f4c876e7108535bed683e8c44619d08154a229444b101e3ed7c01507e870941446af978c0f5341d1ac1dd15b14e8966712df19f52feb5103cf62b6632756446cc754df00a3f6dd719968a2cef66c3adfb7d1fc491fbbf3d59294ab34619e176db0d446151e37eaa3daf172406e983d9d23a6b69e92976030f5ac7040ad5114129feaf97af15b2296fae70492dbbeb2b4827687fb798715c9bb2c32557a81d891b897052900707159751f07db074c77f0719671f1766689029a3cddf39df3483cf2b04f71c25de05fc2d02bb48e539eaf1a321646cd80ef2f0ac703f45e7389530800e5d417ccea8a5c086682f04745d50b5dfc8f6edc87a95c7d202a9cfd998714b746920ebbe2335bca1a0171762016f5e4bda89c57d0edc6910c6d22c8f909da3db1352f0c8bd18f3b5aac25f193b89470f976bc4f1affb3c66bc5876c6fe2ac7508533d97bbcf77119d9aae193f07e0b64b461c9c6c3b9d293bd37de3d8e1ab1e8d872cd94e6cf0eb68439fdcd3b25ce8483460bd8b7cce889fb722b4361e118da983ef4a9e45cebc0c1b8229ea53e6f55505f644e09acaa4c4b8cc640b2cd2b312e1c3a2c02669e1f9c06311c78d360009db9e67c39b49d1e5d770c01d284b0a17a41b4e7ca745d665ec07500e4d9fc8ebc1cc6af53a3fc76b0c3f1431d49843f20e182782c82b3b5aae36fe20ca642618068be233d4b5ef9eaeff401536dc593a2bc18344f55ac5d5fc7b3eb506d11cb375330063c620c5334d723c7d1f042816bc4785b35ac0e6f174f736878b7b491658ca67d8fcab538fc6ecd277ead90d954b460da4253a1c3a30b3d8928f69ac9876a2891969fc2d06a668992b8e2115dfe5358a7124ba7ccf421d8054ea043444cdeb40b716dc7a3659a3ca94347293489060e2cf6712a2a6c7b8ad146785fc40ccb9da287830d011d0d24df3e7afbe972d6f417de5cd75f259ea07cafdde205fc0a365135c232cbd7c1bc539fa4b7e1cce35185237c23f80ae97c186d0d3b10503d5984a20ec41c3cd042c28a4c31f9574b06a872bf959ab0add1f5dee14a1e741ef238dfcdec085aa088dcf39a36dda8f2a85ed0d362ccb005d02e5accc092a376dc11a566170d583db35f1de0be3f15908596e9b781ac81be07b9bd2af46c56fb4d9d84276011e4618b7f76f96794cd0fd57ed414b63: +bc790a7385dd1dddc762e3b20221dc078b6c3da8986d4180940727257cfdcdf1c9264626f68fedb5b39c28f030453b54d0d51a98b17721f2611d7f277ef48b81:c9264626f68fedb5b39c28f030453b54d0d51a98b17721f2611d7f277ef48b81:143dd7bfbff2adc71f5d123d474ea069df14ae923ed9bf8f9891e60bae43f0c9f55537ac9d1ae523ce4ecfd33b20ae445e9c426372050fa5217c1e4fb01353ebf2e32904ef7eefcf72e8023bae06bbb640cf777d5b0e11527bc835493ad6980a157bb2d50be23365e72cbf0b3f209ef0c44a00b41a62262488096cae5a696b4d64cbad34500d41fb4e4bc70f8bf62144d01c2275d6d29f5de75b1721d5046b6829164443ebfd9c1781319d88f54010edc296abbed02b7dad9ba585b552e0005dcca400bf4f459eed7db86ea8612be9e918dfd4e2700c4710083283626fac754417e0087d26ba145dfc45b1c9bf7b4dd70e6c508747ef805c9a02425aebc6421e0deb6a79d89aceeee01ececc9f3ca365383826584c430ebd39ecf0a72866ae0aceca5ad4f0405b67779c04c5de0330614da3470b805d787ce79ac5a696dd6f6b5539b1a651b424cefb19491da6e0889223cc98398b42c00414ff8d6c0627eb97cff20a8cbe7fccb41d810fcfe858ca7475247ef628e84a09d012fe12235b38c1cc9d82e2b69d01d6218cfd48e85f26aeadd195408cdd4c2f806a89041fd0317fb1a7b6209f904270d34e606195047288b0fb11a5722938f67c22b313f7f74b2025c75bcd1ecc5a9add4a640a41f2996eb66e5af196198db58a3fb9938f349f922a24d86f4ed8a96a09a196c24d6d01ed76f3816c05c4f26baca9b9d6dcc79b580dfb75d6c905d480dad76951854bda1caa7f4a819543aed01ae956bf3058fe8b3c7d5d724962f1a6a83143ddad274fda3ad578e98aa967c410ee57575ef01c0258560f0a1fa4b79327796de99420cfd0a415506360f1242ccc58a6880927750dbbff13d7c1b4ed519cda357210f12fb0d1c4d48f0411bd7e058cc4cb93d3c77597e2653ffa282d3c2f128ac33a237af2fcbc9ef9c811f37814ba2b0b85093d0fd18b8c6fb09a43ce52254d23d55f32e1d3242aed1f23d9cf204aa0dfd44a346fe09e55a4a06cf1bef8bbf37ba1f1598a58aef89501ecbac0453543e480ed0adde90c841d95ebd6eb23baa9f70f83c149eab32d0913c79b0993d0e1d3574f0f542e56a20616cfe4a8bd7aaeebe0b083dc2ce0146178c07482a01129bc6fefdc8141c1384894b69cbe2f29da188f7fd4ac341a2df6fd90dee6a446d2746324c75c1ef5b1ace187d3bc16d70559892975d7e47138f0406385ea:6d6bd65f372679fe9d945ff56516333ece0b7a25b15ad2487381670e536f5246775eb39a114db2b9cd50f312b360d9d0bea295dc37b817b332890adb65e4c401143dd7bfbff2adc71f5d123d474ea069df14ae923ed9bf8f9891e60bae43f0c9f55537ac9d1ae523ce4ecfd33b20ae445e9c426372050fa5217c1e4fb01353ebf2e32904ef7eefcf72e8023bae06bbb640cf777d5b0e11527bc835493ad6980a157bb2d50be23365e72cbf0b3f209ef0c44a00b41a62262488096cae5a696b4d64cbad34500d41fb4e4bc70f8bf62144d01c2275d6d29f5de75b1721d5046b6829164443ebfd9c1781319d88f54010edc296abbed02b7dad9ba585b552e0005dcca400bf4f459eed7db86ea8612be9e918dfd4e2700c4710083283626fac754417e0087d26ba145dfc45b1c9bf7b4dd70e6c508747ef805c9a02425aebc6421e0deb6a79d89aceeee01ececc9f3ca365383826584c430ebd39ecf0a72866ae0aceca5ad4f0405b67779c04c5de0330614da3470b805d787ce79ac5a696dd6f6b5539b1a651b424cefb19491da6e0889223cc98398b42c00414ff8d6c0627eb97cff20a8cbe7fccb41d810fcfe858ca7475247ef628e84a09d012fe12235b38c1cc9d82e2b69d01d6218cfd48e85f26aeadd195408cdd4c2f806a89041fd0317fb1a7b6209f904270d34e606195047288b0fb11a5722938f67c22b313f7f74b2025c75bcd1ecc5a9add4a640a41f2996eb66e5af196198db58a3fb9938f349f922a24d86f4ed8a96a09a196c24d6d01ed76f3816c05c4f26baca9b9d6dcc79b580dfb75d6c905d480dad76951854bda1caa7f4a819543aed01ae956bf3058fe8b3c7d5d724962f1a6a83143ddad274fda3ad578e98aa967c410ee57575ef01c0258560f0a1fa4b79327796de99420cfd0a415506360f1242ccc58a6880927750dbbff13d7c1b4ed519cda357210f12fb0d1c4d48f0411bd7e058cc4cb93d3c77597e2653ffa282d3c2f128ac33a237af2fcbc9ef9c811f37814ba2b0b85093d0fd18b8c6fb09a43ce52254d23d55f32e1d3242aed1f23d9cf204aa0dfd44a346fe09e55a4a06cf1bef8bbf37ba1f1598a58aef89501ecbac0453543e480ed0adde90c841d95ebd6eb23baa9f70f83c149eab32d0913c79b0993d0e1d3574f0f542e56a20616cfe4a8bd7aaeebe0b083dc2ce0146178c07482a01129bc6fefdc8141c1384894b69cbe2f29da188f7fd4ac341a2df6fd90dee6a446d2746324c75c1ef5b1ace187d3bc16d70559892975d7e47138f0406385ea: +db3a44df40d255a25cf23f53c45223b7d8f1f1f111ba07406b71e184a8cd06126b12bd9580ae207a9b0baa8287b8bb86669373ee5e5a625ab4a6ef2d08712597:6b12bd9580ae207a9b0baa8287b8bb86669373ee5e5a625ab4a6ef2d08712597:52dd8ba4fffa344d1e0811d9675c313f9cc0e5a138478691989d2b7f7389025068fa35f74f9aeaf1e95665ecf8d5707f75f65f2256eea93398be59c0d538f5e8584bfbb3a240f5016d7927234cb3eac35b391b8b53f20ed8bae0ba11089694bfeade11071656d4cf18ef2d368192e04e08e3024fc1d2fda6312afca68d10c9c336a0e36850be1a4f35b033a85a2a9549f2673a995f2a9ab4bd46c8fd2d838e64f761713427329c9af5e4211a22ab208aaab80e194cd0f6a502b308fed6c583517801a48ed4330e2faddcd41809c3919b30e84db3c68731031e79857dd9f97ffd12547da7066798074151ec88a5fa963b9d9d83ba2fee135833950ef7bc62b3401ea11bb36f25561bc0522bb02d8dad0543f63d547be77d0a4c9bf65d42f3a276144d2e474e2942f3790221e26fbae7ca91efd85921990835fafb6dc674635c9601821038b52711343d1aa25f1c46ba4e3c6e712bac19e53eae30e5246e4f04ddf2acdbb34163c243677690be0bf2e3fa164870b5e6f536b22fb89e5e8e1d87cdb34044977ed2836e544d7ba493dd42a2b649bcf313c5b39a1dbfff3e7f2a59ade87d3e7b258f58e565fdba3e4d92b1edb8bff54dc49d86c53c030cf58b97ef066d241b540530213905739d8e1aa72ed90f685d3958eaa242b0cbf7a2eb976ee96a63e66786464169a742d457e4d9117c7d66428445a46930c28ba7a2658241805ebe72c78e02035d263a211e590b490cdb84415062eed14f13b8a1a9e77c8d7b75515b18fb85386e4a7e053980d30f4899e83863bee875585887c5f48b516ccb731c4bcaa3df07d04795814096c79d7c5fdc4dabf5e26a4ca1838e0e5d87db71309b81ea7ce461e5e44c7ab2f105ad75c543c1e9179c36a5fa555ec922ffed1b76d25801dd74f80cd0a6ba7bc20db0ad580b7bbb9ddcfd93ad1c5f20f3e27c3ea3a1e71eb74ff5f944cd3b98f6d04529593011c4aecef6dcaa60fb18368cb12b6e391b3f5df765cbabff15898c84796fc2b53fa4900dad034a13b0ce1445adda4ef719be741419e231e92f1f667a32842a42db79bd7a014a809c81596e826273d16fe5d40458242ae10e12e60b3489530c6622b5bb44454f29616e47e9a297ce1ca074137fd9ae13e3ee8edbcf78af265459db1af342dc0b2fc809bda015b5a82b2b7c54efe4e5fc252eb13d66e808936f1910f4c48be0ef7a:cc28b5ef4b9773637fae7e5f084b6994aa3598f8f4a65d0bb201d172d861a30149b3338d3c3ab75b32b25595cd8b289630c3376acd10ba2ab26bc1aba900840e52dd8ba4fffa344d1e0811d9675c313f9cc0e5a138478691989d2b7f7389025068fa35f74f9aeaf1e95665ecf8d5707f75f65f2256eea93398be59c0d538f5e8584bfbb3a240f5016d7927234cb3eac35b391b8b53f20ed8bae0ba11089694bfeade11071656d4cf18ef2d368192e04e08e3024fc1d2fda6312afca68d10c9c336a0e36850be1a4f35b033a85a2a9549f2673a995f2a9ab4bd46c8fd2d838e64f761713427329c9af5e4211a22ab208aaab80e194cd0f6a502b308fed6c583517801a48ed4330e2faddcd41809c3919b30e84db3c68731031e79857dd9f97ffd12547da7066798074151ec88a5fa963b9d9d83ba2fee135833950ef7bc62b3401ea11bb36f25561bc0522bb02d8dad0543f63d547be77d0a4c9bf65d42f3a276144d2e474e2942f3790221e26fbae7ca91efd85921990835fafb6dc674635c9601821038b52711343d1aa25f1c46ba4e3c6e712bac19e53eae30e5246e4f04ddf2acdbb34163c243677690be0bf2e3fa164870b5e6f536b22fb89e5e8e1d87cdb34044977ed2836e544d7ba493dd42a2b649bcf313c5b39a1dbfff3e7f2a59ade87d3e7b258f58e565fdba3e4d92b1edb8bff54dc49d86c53c030cf58b97ef066d241b540530213905739d8e1aa72ed90f685d3958eaa242b0cbf7a2eb976ee96a63e66786464169a742d457e4d9117c7d66428445a46930c28ba7a2658241805ebe72c78e02035d263a211e590b490cdb84415062eed14f13b8a1a9e77c8d7b75515b18fb85386e4a7e053980d30f4899e83863bee875585887c5f48b516ccb731c4bcaa3df07d04795814096c79d7c5fdc4dabf5e26a4ca1838e0e5d87db71309b81ea7ce461e5e44c7ab2f105ad75c543c1e9179c36a5fa555ec922ffed1b76d25801dd74f80cd0a6ba7bc20db0ad580b7bbb9ddcfd93ad1c5f20f3e27c3ea3a1e71eb74ff5f944cd3b98f6d04529593011c4aecef6dcaa60fb18368cb12b6e391b3f5df765cbabff15898c84796fc2b53fa4900dad034a13b0ce1445adda4ef719be741419e231e92f1f667a32842a42db79bd7a014a809c81596e826273d16fe5d40458242ae10e12e60b3489530c6622b5bb44454f29616e47e9a297ce1ca074137fd9ae13e3ee8edbcf78af265459db1af342dc0b2fc809bda015b5a82b2b7c54efe4e5fc252eb13d66e808936f1910f4c48be0ef7a: +77964dad52b579b8966753da3186d1c5e9d33d33a4db38bc0d7a1a6c112c13c2fc25125e7829f64234375e52ae9f77ae1013f99df5f9965ad2aa16589596d091:fc25125e7829f64234375e52ae9f77ae1013f99df5f9965ad2aa16589596d091:c339e718a757f3f3bd1babdd2e00aaa5cd7fc9005ee34b6fdc09d71fbd9c9289ab1dd14dba2cad58cb805116777bd80c85966433ad46f9ca6e54f13dd3ca7e56e47fea41e5488a45ad53bc5d657427e1d7938f5519f1b09f5bdd98aae5ac9643ef78eba4934925339a155dc66828571002097a11a5cee7b51a441b756b0ce65b779afe19da6a18efc145f6090ce770de9e0e91f543270a0985eab475293ccfdd3141c4142e4722233b267499447641235d728bd75cd1adc0db142f7331adddf8c5eea3d576405d869915b560f964e3e0003c91f5e96bffbeeec73e51024ef52c55c6dcb54d58203e62f4ddb6e137eb08e1bf1326018afd1a86cab6c841e0661ce0a1a7ae967f24c1a77fc7ca505f72e5f7936e39c6f4837e2595195a69cd676510a7161a4dc5e318f3d4f3ac0af03f8c4ae5bce39324e9738aea49f002d32d16de2317e95a9f32ee604e13db8038b264cfc17aed29c9debf8191de9e0efc951ad6d54867068cf50a269c37a241f85206788d23143177f659cca66cfce03bc0502255337f16b3dad6f79132abf80ff12b6d2281e637eb6c71f76e2633a114565240eed00fabea9ed8de28c83221f8cb485f512d9008bfc74a366d4c2b4ed172d367e0247cb65098c110282e831df8e9bd4fbd5f4dd2b7f2420c23b85a637aa2262c3cb88405f70730c9ab4c9d0f227ee4fa4ef91efe9a59b3e6d843db879f5650059e99f0e4a0386838e6f9876f67d50f89832dda5f30a9cbfd710134f9b5b54627496aa3a43212b07f03db11d3d4f875d41d1f4ac45969ddef69f81a06d2b0c646c9cd931cf2502fef0dd32abbf0951ed303f5284825934397fc22e78698d35ad81d82256bf9e15400a1091623a9826f1e57792367417ef02586d64e650da9ace2f18aa0a126d867cac4b5d4c91bf5209e5359556386f827083eb53e8b4709fffabe92c61d78ffb5daf10274e242a70091f3f9b9d596c1258c9a63384f4b05b028661222181c0fca965f0a2cb56e4b556d6fbff71b64d9b358da31aa37c74ff5962fb8d96a383d049724c19e249c9edbb2a375b23ce3104da0ec58d2635ba03b55423fa2db7eb349a4fc58a1ef540ee9a02c2e703c68d7f8475f434ddd3200db1f06745791a3acc3160dba50a393447ffeef6dc7b98fb06684cc90fd85203d119dcd8199e4d9a89ae3467ae4bb19fb71cf747029c24096f9a50e:3d1b4b4e820d250be2a8fa971e599e1e98977528b2f930189681a93b05e1a706fc80effa94e929bc43921656897388288a9b29271f37a14be014b873c68fc904c339e718a757f3f3bd1babdd2e00aaa5cd7fc9005ee34b6fdc09d71fbd9c9289ab1dd14dba2cad58cb805116777bd80c85966433ad46f9ca6e54f13dd3ca7e56e47fea41e5488a45ad53bc5d657427e1d7938f5519f1b09f5bdd98aae5ac9643ef78eba4934925339a155dc66828571002097a11a5cee7b51a441b756b0ce65b779afe19da6a18efc145f6090ce770de9e0e91f543270a0985eab475293ccfdd3141c4142e4722233b267499447641235d728bd75cd1adc0db142f7331adddf8c5eea3d576405d869915b560f964e3e0003c91f5e96bffbeeec73e51024ef52c55c6dcb54d58203e62f4ddb6e137eb08e1bf1326018afd1a86cab6c841e0661ce0a1a7ae967f24c1a77fc7ca505f72e5f7936e39c6f4837e2595195a69cd676510a7161a4dc5e318f3d4f3ac0af03f8c4ae5bce39324e9738aea49f002d32d16de2317e95a9f32ee604e13db8038b264cfc17aed29c9debf8191de9e0efc951ad6d54867068cf50a269c37a241f85206788d23143177f659cca66cfce03bc0502255337f16b3dad6f79132abf80ff12b6d2281e637eb6c71f76e2633a114565240eed00fabea9ed8de28c83221f8cb485f512d9008bfc74a366d4c2b4ed172d367e0247cb65098c110282e831df8e9bd4fbd5f4dd2b7f2420c23b85a637aa2262c3cb88405f70730c9ab4c9d0f227ee4fa4ef91efe9a59b3e6d843db879f5650059e99f0e4a0386838e6f9876f67d50f89832dda5f30a9cbfd710134f9b5b54627496aa3a43212b07f03db11d3d4f875d41d1f4ac45969ddef69f81a06d2b0c646c9cd931cf2502fef0dd32abbf0951ed303f5284825934397fc22e78698d35ad81d82256bf9e15400a1091623a9826f1e57792367417ef02586d64e650da9ace2f18aa0a126d867cac4b5d4c91bf5209e5359556386f827083eb53e8b4709fffabe92c61d78ffb5daf10274e242a70091f3f9b9d596c1258c9a63384f4b05b028661222181c0fca965f0a2cb56e4b556d6fbff71b64d9b358da31aa37c74ff5962fb8d96a383d049724c19e249c9edbb2a375b23ce3104da0ec58d2635ba03b55423fa2db7eb349a4fc58a1ef540ee9a02c2e703c68d7f8475f434ddd3200db1f06745791a3acc3160dba50a393447ffeef6dc7b98fb06684cc90fd85203d119dcd8199e4d9a89ae3467ae4bb19fb71cf747029c24096f9a50e: +5cafd817a4410ccb27121723ef3207c1731a0861945be962714c0ed95038a1954ea086be43ece1c32d08059bbadc9e9a2b2f4f3fe370f1f5ccd7dbdec0aaf303:4ea086be43ece1c32d08059bbadc9e9a2b2f4f3fe370f1f5ccd7dbdec0aaf303:50b2f05342418046d16a30be4fc62b67daf6c18d2a74242b7cb55ba90ad20b6cafdd60155737c29de48aa5d799fe5495fe59df5a9b8c0a8e5418904763fbad83ea6986651bac31117939cef4e0c79930d52dfd7db43c31addae3cf93e3efc5a916efd0d65fdc30909fa356ccbc5247d7aaa067131b6b4820fd02f8e395f5a9704c9bdd7560a611d62559a8dfe1d2859c52486cc11ed3331992488f417520d920dc73a32d4f08110082500f5a962a306932c6a7802955cedad7abf53b0f19fe4794a31d6b855380284306ccff71a4007859a2328bb19024c43e10d77064d866d9622d142c27354b84ac3b4f8232f7a2f8af6409d5cc757a18ef813dfaf4b9bc040cb006d77f143641aa2036ac7bc928dc96585d9e36c7bc9c564d25f1c2cc0beab9d5f207e84b215f1e7aa6fc328237b79c39923a4e09c7c73dc6b24b1416294d798a4ed5f758336d915a870a7d6b7592b5b88aace2dc5f267bdb491141cbbae2a677407cc0955f961962599304ba0b839671a5c000e920108a05298087e49770aeeeaab3632724cb0fc2285796dc414814fda78a54e67f00a02f77d3ccde1ed9d7b1def14ea1f61910bdf30a1196fc6351b62254d6445e6c90445b16efafe289a2784b92e42b78a4a900c35f55630bbb7762ff9eb7fef7d04c90b9571c4fc760a410dbfc252991d0ba27f2d414fe64eefdff4abc18817c9706c631bfa203821d3b92cb338baaf5d1232b462647954d0902462fb1696e991f07fa9c3dbcf2872960831b4ded92a421cf21b753165ff309efe2ef5438c01270d10c6a03d34f71ebc2dab1da90daa357984d2462bcb35ee3de55c3a55f8b98aec2114f74c84341a64127863c120b5ecad9e329a5756ae4a2555d8492cda835225a8deb3f9c1558f0d425bc172ff7640cc79d97800416fd6294cccc70cd1cf5b6a8e2aa07289bd522bf99dc96c36bfee80e846f5dd746dd4c5003e4bf7d29efeea7508a0161236882c9a82a56aa2c2574669652c630923ab470ddb95d456f7b8e8f07599ba0d1d38bc7f8176e3fdf0209bd6f75d4cc11803afb1856cbc0e91c73730e4fb98f3c948a87d5a7edcc0a6a8ac810ea3eaa6e063cec5f5566cd6dedc537db6d686b8021f6ea825ad7475ec7f1c5dbde45d3ff4b5ee51c0d04f1d74018eb91e5040d01c8b71a4aabbde6094d4afeccb18dfcded73ea75e3b9f8ce167df6209ae:288515fa7259f1eb587fe8a2c403434c46f8d7e75b6d22bb3896566c017d09b698c2c807799c2f65f9cdb4eb58151ccfc48d108061a6b3148432b2bfc1cdab0550b2f05342418046d16a30be4fc62b67daf6c18d2a74242b7cb55ba90ad20b6cafdd60155737c29de48aa5d799fe5495fe59df5a9b8c0a8e5418904763fbad83ea6986651bac31117939cef4e0c79930d52dfd7db43c31addae3cf93e3efc5a916efd0d65fdc30909fa356ccbc5247d7aaa067131b6b4820fd02f8e395f5a9704c9bdd7560a611d62559a8dfe1d2859c52486cc11ed3331992488f417520d920dc73a32d4f08110082500f5a962a306932c6a7802955cedad7abf53b0f19fe4794a31d6b855380284306ccff71a4007859a2328bb19024c43e10d77064d866d9622d142c27354b84ac3b4f8232f7a2f8af6409d5cc757a18ef813dfaf4b9bc040cb006d77f143641aa2036ac7bc928dc96585d9e36c7bc9c564d25f1c2cc0beab9d5f207e84b215f1e7aa6fc328237b79c39923a4e09c7c73dc6b24b1416294d798a4ed5f758336d915a870a7d6b7592b5b88aace2dc5f267bdb491141cbbae2a677407cc0955f961962599304ba0b839671a5c000e920108a05298087e49770aeeeaab3632724cb0fc2285796dc414814fda78a54e67f00a02f77d3ccde1ed9d7b1def14ea1f61910bdf30a1196fc6351b62254d6445e6c90445b16efafe289a2784b92e42b78a4a900c35f55630bbb7762ff9eb7fef7d04c90b9571c4fc760a410dbfc252991d0ba27f2d414fe64eefdff4abc18817c9706c631bfa203821d3b92cb338baaf5d1232b462647954d0902462fb1696e991f07fa9c3dbcf2872960831b4ded92a421cf21b753165ff309efe2ef5438c01270d10c6a03d34f71ebc2dab1da90daa357984d2462bcb35ee3de55c3a55f8b98aec2114f74c84341a64127863c120b5ecad9e329a5756ae4a2555d8492cda835225a8deb3f9c1558f0d425bc172ff7640cc79d97800416fd6294cccc70cd1cf5b6a8e2aa07289bd522bf99dc96c36bfee80e846f5dd746dd4c5003e4bf7d29efeea7508a0161236882c9a82a56aa2c2574669652c630923ab470ddb95d456f7b8e8f07599ba0d1d38bc7f8176e3fdf0209bd6f75d4cc11803afb1856cbc0e91c73730e4fb98f3c948a87d5a7edcc0a6a8ac810ea3eaa6e063cec5f5566cd6dedc537db6d686b8021f6ea825ad7475ec7f1c5dbde45d3ff4b5ee51c0d04f1d74018eb91e5040d01c8b71a4aabbde6094d4afeccb18dfcded73ea75e3b9f8ce167df6209ae: +d5cac85521af781f3d5f66862a04b087d0ccdcac926cfe9e747be8d5c2633f78100dcc53039bf05ea0a9f5888212693d4f9e0e752595bbcd020610e0ae213596:100dcc53039bf05ea0a9f5888212693d4f9e0e752595bbcd020610e0ae213596:d5e7dd594909375a4be08e74825d598d535bf46ec084de52b57391c127eff5224ab2d194dfb26633478d02fbda74d1dc5821f791bf962d8dad9e4ef24224891907b0189cccc8b133d3aa2078926daef2898c19c2e0bfe02041a904b9f04be7cb50aed0d962d1add20b40a88ab7abad626cf4da0a78f9f53685501fdfa58543ddf2ea0eea69e7ba160f8a177a25fc21e8a29c661633e30e523b0ec01b2aeee2d426e4aead457488108fe5f569cf6e2fdb68c28f2b3052823577cd934e7b062c8a3424cd4367fb315b744ca35255d7f1af4edc9bc9d8837123d97903b43df367c7d418c79347ffafe7c7b1724bba34ede8d3568db505983ead47f62b56e3618c11db8ff0bf492ac67597d2f96a6f420ff985341b786ad6ceaedd105d0d1563b2d53543d78e7256725d204e82ed3a2e6a6e83df61fc282a62ca06e62174b55bef40a0bdf8d23d1c330c71441485ee85e70ced121eac607f580678163e4bd75c6709ff3b41de80594b9e2f2aa278fefc21d73ee3f72854b958d9a8f63e3d70f7fead8c3dca8e71bf4b9c2a36f212b32eb3292e635580386559ee1a11df15293a0c21cd7360869846ba5b7ba85c994f5b2f9cc50e5eea8e4b3691d886062a18cfb182f1e8b611fe1bc263159cb8a086787c811bea4812530008c70ca0c47e64eb2fbad5b02727a66f2cdd6dde86f5d2a9645a1e9aa66ee0e15b97f5fd229596ee02e661cab9a54eee1b81f98fe256ed6c54feaaa0ba047eea353344f6e5c62be1e9d5c09a2a699411110c56d1949e90c07b1938ba9555ac1be8511b510218d7cde7e1d74a68afb642f81715fe9e6c96c50381ae5a9df306518785dc4dbc3a64f60f245c564b8029512f381b56ee787703426803c80ab1c311f477b891708b59fa748f32debf54d2413771978c265c9b87114adf25b8337aa93b0e632a5b6eda474bec16328159fbed067b00b87add61965492eccc6fd3461c1000e4037ab1e8ac89a8524f78ae09d308ea6c94ff883732b712eec0ef07718d33c011b9398f8cfea733075af331fb3f97cdc1e8c99f6a10725a68c5c58fdd8b0baa50227f34d73d23905203698eaff626654ce83d865108499be6861f6141bfa6219d7ab8b584519199f880cfa1b26d9194d301711c30fb446d6ea764a4310f70e4b859cf95fd44aaf8c1e240e80a71611dbcf52da58edc320311de388d5d9d769eb59be093:5dc03363414eeac0086fb6feba44217cef4c520db61926df680ca602dc11003ce6afbf3d13c8c5b05273d21415e67c14a2ee5d0b1d5352419ab9b39c003a510cd5e7dd594909375a4be08e74825d598d535bf46ec084de52b57391c127eff5224ab2d194dfb26633478d02fbda74d1dc5821f791bf962d8dad9e4ef24224891907b0189cccc8b133d3aa2078926daef2898c19c2e0bfe02041a904b9f04be7cb50aed0d962d1add20b40a88ab7abad626cf4da0a78f9f53685501fdfa58543ddf2ea0eea69e7ba160f8a177a25fc21e8a29c661633e30e523b0ec01b2aeee2d426e4aead457488108fe5f569cf6e2fdb68c28f2b3052823577cd934e7b062c8a3424cd4367fb315b744ca35255d7f1af4edc9bc9d8837123d97903b43df367c7d418c79347ffafe7c7b1724bba34ede8d3568db505983ead47f62b56e3618c11db8ff0bf492ac67597d2f96a6f420ff985341b786ad6ceaedd105d0d1563b2d53543d78e7256725d204e82ed3a2e6a6e83df61fc282a62ca06e62174b55bef40a0bdf8d23d1c330c71441485ee85e70ced121eac607f580678163e4bd75c6709ff3b41de80594b9e2f2aa278fefc21d73ee3f72854b958d9a8f63e3d70f7fead8c3dca8e71bf4b9c2a36f212b32eb3292e635580386559ee1a11df15293a0c21cd7360869846ba5b7ba85c994f5b2f9cc50e5eea8e4b3691d886062a18cfb182f1e8b611fe1bc263159cb8a086787c811bea4812530008c70ca0c47e64eb2fbad5b02727a66f2cdd6dde86f5d2a9645a1e9aa66ee0e15b97f5fd229596ee02e661cab9a54eee1b81f98fe256ed6c54feaaa0ba047eea353344f6e5c62be1e9d5c09a2a699411110c56d1949e90c07b1938ba9555ac1be8511b510218d7cde7e1d74a68afb642f81715fe9e6c96c50381ae5a9df306518785dc4dbc3a64f60f245c564b8029512f381b56ee787703426803c80ab1c311f477b891708b59fa748f32debf54d2413771978c265c9b87114adf25b8337aa93b0e632a5b6eda474bec16328159fbed067b00b87add61965492eccc6fd3461c1000e4037ab1e8ac89a8524f78ae09d308ea6c94ff883732b712eec0ef07718d33c011b9398f8cfea733075af331fb3f97cdc1e8c99f6a10725a68c5c58fdd8b0baa50227f34d73d23905203698eaff626654ce83d865108499be6861f6141bfa6219d7ab8b584519199f880cfa1b26d9194d301711c30fb446d6ea764a4310f70e4b859cf95fd44aaf8c1e240e80a71611dbcf52da58edc320311de388d5d9d769eb59be093: +159a9eddea5de63403987b5670db6fac98ffe5ec3a6cf01516ee2c70ce3b3be0f61f4a04a5a12ccaecfaf44c1c9c1888475a2c89fb02f26bb81ab5f78f4ce3a8:f61f4a04a5a12ccaecfaf44c1c9c1888475a2c89fb02f26bb81ab5f78f4ce3a8:d195e5900dd3931481bc012e77bf060aaf31cccb0fe1a6c40eaf286a6166a166b1ea37053426284b920c67fee1d4b9d86fb861cc6edd34e10c52233734d9cd92f5dbf433512ed255ac6b26e56f5c664bccb260692cf49d08363ee94e336acc489600a6aa512a040f10ebf18f7d2cbee9cad14c4ff87377a3263419d8297529401f15337a4c4d2325ed7def763a0d479caa408266834da242f3a16b79a45866b9d9d71a4829317674cff7ae6c8c587ba4d4980e818613d3ad82507a7ab032bbf99c5e9b640371bb41b91e965dc31e8c7d4b3bafd49570527faaa87abbf6416c47b1b1b09d3401253126cb246ae45acf5f100bb1f92f11a5c6c937e0588d8b146b3e4d3c7e5bf57484e984fe3afc4772f24ebf894cdb39837fbd469a921a96ac5af5e070f6c9624c588e9d4fe6ddfeed1f8fe20eb9c460ce6ee38bf471dd56dcf2e3ee998b8e7fdcf612e78a2e7c7173c0160982bedecc2c621e5f6611b4ef2102e32e7c29803a7e25fee151243158a76ee5d8c1bb2e7d8c88871ba433c5e541c2602693d90110be795b523a8fadb605d8e3d7e493fe245d9cc5320d32b85d6135a44b1168729414c2ca21560fb4feecdeef0cf7d8e071274e8856c004033e80013c73af7177c3197816a5032d9059b1b6e4152c386192dd54b90f9d308be98ed7d0ca9d12e8aaf6f9d869386aa9dbb01593d37e72f090124d3455298e9b4c9ec3cae73bb8ee41eb63e38c56133efdbaf449b84e1e491e496f1c70a44d069986ba8818422069061bb6ebcb7b2054e63df381ba03c6a7674abd61050d693d41bfe3ca5046c65ffb06a0749809e58d4c93a9ff69ed30950bde1f99216fff299f22f16b07c254c265ae0b12e313163ccdf5036d49055f9a9667b0b71292bc3b6260cb87568fd267170bc940c33329d729c9e32d0f9180b134bff8ae93b1bfebfa3842fef20bc04a297b00a84a0f428d5f42fab86142996d4ad9efabc49852f8812f3bfb5e57539e2186eb8ae229580bc60448acdef5723c881588b53789f05b91e02289223252d753f79813779ace705e04aed15265d3bdf2a2e4b15654770a275854e64cf44390607a45d7bba9af3e1a2e283067fcd6e633aa2d2403bd81f7c792765510b598412f6bda07b2a945b9f6d46ab2f7c320075bc6b60a80daa44af391f4cd562131bbdd407d66f8db1259bd76fa7e4d5264e145546c942dfe9007:0543712cefa29a220d90f81baa4e4cf77ac65208b2d5ce9fd17ce214ad4a937b7fc5c786413b58051cca3bb8b2eb55657d89572bc50ea2e5ecdc555088491603d195e5900dd3931481bc012e77bf060aaf31cccb0fe1a6c40eaf286a6166a166b1ea37053426284b920c67fee1d4b9d86fb861cc6edd34e10c52233734d9cd92f5dbf433512ed255ac6b26e56f5c664bccb260692cf49d08363ee94e336acc489600a6aa512a040f10ebf18f7d2cbee9cad14c4ff87377a3263419d8297529401f15337a4c4d2325ed7def763a0d479caa408266834da242f3a16b79a45866b9d9d71a4829317674cff7ae6c8c587ba4d4980e818613d3ad82507a7ab032bbf99c5e9b640371bb41b91e965dc31e8c7d4b3bafd49570527faaa87abbf6416c47b1b1b09d3401253126cb246ae45acf5f100bb1f92f11a5c6c937e0588d8b146b3e4d3c7e5bf57484e984fe3afc4772f24ebf894cdb39837fbd469a921a96ac5af5e070f6c9624c588e9d4fe6ddfeed1f8fe20eb9c460ce6ee38bf471dd56dcf2e3ee998b8e7fdcf612e78a2e7c7173c0160982bedecc2c621e5f6611b4ef2102e32e7c29803a7e25fee151243158a76ee5d8c1bb2e7d8c88871ba433c5e541c2602693d90110be795b523a8fadb605d8e3d7e493fe245d9cc5320d32b85d6135a44b1168729414c2ca21560fb4feecdeef0cf7d8e071274e8856c004033e80013c73af7177c3197816a5032d9059b1b6e4152c386192dd54b90f9d308be98ed7d0ca9d12e8aaf6f9d869386aa9dbb01593d37e72f090124d3455298e9b4c9ec3cae73bb8ee41eb63e38c56133efdbaf449b84e1e491e496f1c70a44d069986ba8818422069061bb6ebcb7b2054e63df381ba03c6a7674abd61050d693d41bfe3ca5046c65ffb06a0749809e58d4c93a9ff69ed30950bde1f99216fff299f22f16b07c254c265ae0b12e313163ccdf5036d49055f9a9667b0b71292bc3b6260cb87568fd267170bc940c33329d729c9e32d0f9180b134bff8ae93b1bfebfa3842fef20bc04a297b00a84a0f428d5f42fab86142996d4ad9efabc49852f8812f3bfb5e57539e2186eb8ae229580bc60448acdef5723c881588b53789f05b91e02289223252d753f79813779ace705e04aed15265d3bdf2a2e4b15654770a275854e64cf44390607a45d7bba9af3e1a2e283067fcd6e633aa2d2403bd81f7c792765510b598412f6bda07b2a945b9f6d46ab2f7c320075bc6b60a80daa44af391f4cd562131bbdd407d66f8db1259bd76fa7e4d5264e145546c942dfe9007: +eda0feac0f2afe0174491552487f3962171332b822dc3da426f9a5f62bef7b8deff27cb51f4d39c242f323019a1234818ef2e4cd1bdabc0f2d8d213458dc471a:eff27cb51f4d39c242f323019a1234818ef2e4cd1bdabc0f2d8d213458dc471a:901119da4ed181aa9e11170b20626e00abf0b548245e3debf94bf5ed50aeefe942b402cc9948947852dedf2b5304017665749cd47c21fc652ee995679ff931e30e94af98b4a98fd44e849e98470fe0a76ce80c61f83fb4e85ba523ee3fd25db000053b49d0930e3b079e866e153f7d86367f23a4c4abc63b3075461e90e4fd896da0492e27d714941e967f52c93ffaec44803f57877d866eb5f8c5281785aa4826792e3964c66590821eea66752074264018a571f5b013b38e152c95c0248ae6036822a67afc9e02694573152b864c56c2f730a08210f85ec46f984a643d516a15fcfaa84840f512047d110e0718d293955f0158257fba0d78eb7df2f0b77e6eeb76db5e71707310e827361cd4e119740e63922db42c2ceb5ee175d50decc7b749fd2325bce1e6a8f710ffcc1e1c9b33c380e52a64daa9585fabe406d9cf24488fe26f3a495fb0ab50e1e2bad82381aa22431099cc8a569813d79c9d78569c0d95da9aad2bfb57758d52a3752752e023d651c9cb66a412a5c80f6ba54793f7ec87b4c598fed2ce24abd7608708895c46727359ffeca6d6c62e10a678caa718b4cd263292cfef535b9fbe2756b7396d697b3146c551e6aac1f5f1c24be9b67a1e2a2aff745301ba6a212217c53d681681bbb401bf4a43656f5d15cde969c1780099a33237eb19a3b8585d6b5dea2fb577845f25ee2a82ccf4b28502f90fe80b8cdcdf2ccf93c434c0e6aa5d8752a44343c2b18d20fe4004c47038659356f87abed5445034d8e2d3d14768f5ef312cf102a9884683bcc0cd8a71e3ec36fbb6334a1bbaed5d2bf10416d82bd6530475380ab6e2577bbc69cebda75faf02ad827b54518213206fd4cd66f252b234aca9eede7e3eeb815ddcd8d519c5d7f5d9d1fb9ca0fa4467990095fa46220c20a2071dfcaad5f024dae3416f7c492d757488c49a2e4df483bc9b80098e0d5d683facb8c960829dff09b303369d46cb57331ff21791ee25d6be7dec7ebaf1b32479a7f514dc647105c944c36f7dbf0a5b589128dbaaa42171d642f25a981ce1f8379f91690b36af774648d5624c08dbd0a90f708716dfab2024dae865b9c49ab27473826cd4a010bfdb52011d8c7cb3f421ca8ca3cd0486889188e67df00fb8c2a643e7adb2f8279f763e5b9a81b6dfc3f721fc5f6849f66736788cc557c4ebc6fc68d6f6ac77bedda8acb362243bda74e7b2:6cbc7e6f5e12145b01687ad9ca6bf6e47f9417c2cefad3fbd68fd65dd74faa9750cba992de4cebcfcd35808cbb3ff12c8d930799af36efe7976bf2fea79e3e0e901119da4ed181aa9e11170b20626e00abf0b548245e3debf94bf5ed50aeefe942b402cc9948947852dedf2b5304017665749cd47c21fc652ee995679ff931e30e94af98b4a98fd44e849e98470fe0a76ce80c61f83fb4e85ba523ee3fd25db000053b49d0930e3b079e866e153f7d86367f23a4c4abc63b3075461e90e4fd896da0492e27d714941e967f52c93ffaec44803f57877d866eb5f8c5281785aa4826792e3964c66590821eea66752074264018a571f5b013b38e152c95c0248ae6036822a67afc9e02694573152b864c56c2f730a08210f85ec46f984a643d516a15fcfaa84840f512047d110e0718d293955f0158257fba0d78eb7df2f0b77e6eeb76db5e71707310e827361cd4e119740e63922db42c2ceb5ee175d50decc7b749fd2325bce1e6a8f710ffcc1e1c9b33c380e52a64daa9585fabe406d9cf24488fe26f3a495fb0ab50e1e2bad82381aa22431099cc8a569813d79c9d78569c0d95da9aad2bfb57758d52a3752752e023d651c9cb66a412a5c80f6ba54793f7ec87b4c598fed2ce24abd7608708895c46727359ffeca6d6c62e10a678caa718b4cd263292cfef535b9fbe2756b7396d697b3146c551e6aac1f5f1c24be9b67a1e2a2aff745301ba6a212217c53d681681bbb401bf4a43656f5d15cde969c1780099a33237eb19a3b8585d6b5dea2fb577845f25ee2a82ccf4b28502f90fe80b8cdcdf2ccf93c434c0e6aa5d8752a44343c2b18d20fe4004c47038659356f87abed5445034d8e2d3d14768f5ef312cf102a9884683bcc0cd8a71e3ec36fbb6334a1bbaed5d2bf10416d82bd6530475380ab6e2577bbc69cebda75faf02ad827b54518213206fd4cd66f252b234aca9eede7e3eeb815ddcd8d519c5d7f5d9d1fb9ca0fa4467990095fa46220c20a2071dfcaad5f024dae3416f7c492d757488c49a2e4df483bc9b80098e0d5d683facb8c960829dff09b303369d46cb57331ff21791ee25d6be7dec7ebaf1b32479a7f514dc647105c944c36f7dbf0a5b589128dbaaa42171d642f25a981ce1f8379f91690b36af774648d5624c08dbd0a90f708716dfab2024dae865b9c49ab27473826cd4a010bfdb52011d8c7cb3f421ca8ca3cd0486889188e67df00fb8c2a643e7adb2f8279f763e5b9a81b6dfc3f721fc5f6849f66736788cc557c4ebc6fc68d6f6ac77bedda8acb362243bda74e7b2: +ec059fc6be983c27eca93ddcdcb53af7286255da91e2a56a684f641ec2d09d6effc6cb751c70071b65ec2ac6b45fd1d55fe836965f80b3e7c784fc704acbdf69:ffc6cb751c70071b65ec2ac6b45fd1d55fe836965f80b3e7c784fc704acbdf69:d1ac6325a4e690fa79536883d5c20eacb7d964c0178f742c2b23727deb62645af7c81922a0e72e5e30b5839a2ed5e567ec31ce224115b82d2bf251b7393f01b0d03a602bc120ae62af7fbc379dfcf95bbbba984aaba34fe212ac99003328b832c3532d42eee1e1874dc22ad67db6c91dbbfb2b45785dbcd39917d36fb48c1b5d6f38bdda5d28fbba64175575afea46c8ed6757ff30164e0df2e72176e8b6c9db5b5ef390b72f2d4d94e3b66f0d44a7e0f06e89debcdf1363c0e75d50db5bb70190d19f66a39c6f7dba70dfcd4a9fed02c2f1d067e7c788c58fdb3e17a2377ce486ec6582f3ba997bb5f70cd621002956f5131aa3a1617c0cebccd9391de1307c85970a8bc155f519872668450c91488689f53c2c1a7ed53f388cb13a2c3896fe5b7d3a0dc1683f27664c8beaea680c8cc54a90e4c6f99fbf05f2c22df60de9aec80c79b7d66207050667b452d7857f9a8ca723280dac7992e2079267ec3ad911404642c4e326bfb96b43c89434ba4bc78c252f4d4ca8d13a8874c6fc8252ea0b56c6bc786847d4318306e1c652c452585eefd0bd9dd3c148a73ba86eedea945f016713ed7df085d0066689e792dacb2bfc1eb5c824372a26c5e944aa7444ac9773d4a1921e49bdd4f8f6d788c263fee04c7b444c5305edb633e1ffe0ba4ea8da011a62f2bbfef4b895ad3f224c3ba3bff0c95d75750c9bcc66ff8a20b6c24bde7581a7ec3866f8716f781f46dcad45a9ebcb6ed46953368397011735d4b52d00e8db397995dbdb3d4f4254687f04688a268c305b2b1f622cf51b174775bad7f6674adc2e58e05cce865f12d7569c8e9b35bcdf3ccce6330d08ce5340a7c630f27a6c8086b5146b292fcbf50ff6aaaef8848a707b2543c618d17bd976c240bc79d33e004e4953482915e7e6ef94964bdea4e02dd7c2f475235f2b99e43229c9ac3aba0db59ac2da03a9ee4f37dbf247a33e6dfe5be7c7f82584f04a46d49f6621da31b91ac3daa4d68d48a56659b448c0ed365cb4aa0cfd908853df5bbfa88e60e10a5a002c32ab3333f2c39bbf3ee01a4aa60d2d01423e6097dc54305f81a2d93e2f6b4e8b351971cbf2457dc76e1fb89293384798ef28234e9b1a47dedc2336f86b8e13c4aef790f5a11239c747d9d865c9a15adeb071070267e5346256648adc0fa4dbdfd787ca1465fc240a324c3caf2931da41499e275fd4b35f6d08db:a7b88e5abf132824bdde77c5f8df94ab26481f6bee660ea162247082a250d390c71d320ad060d8ef341fb69a483294f0d6de726f0c862fa37ea4bc6dab521509d1ac6325a4e690fa79536883d5c20eacb7d964c0178f742c2b23727deb62645af7c81922a0e72e5e30b5839a2ed5e567ec31ce224115b82d2bf251b7393f01b0d03a602bc120ae62af7fbc379dfcf95bbbba984aaba34fe212ac99003328b832c3532d42eee1e1874dc22ad67db6c91dbbfb2b45785dbcd39917d36fb48c1b5d6f38bdda5d28fbba64175575afea46c8ed6757ff30164e0df2e72176e8b6c9db5b5ef390b72f2d4d94e3b66f0d44a7e0f06e89debcdf1363c0e75d50db5bb70190d19f66a39c6f7dba70dfcd4a9fed02c2f1d067e7c788c58fdb3e17a2377ce486ec6582f3ba997bb5f70cd621002956f5131aa3a1617c0cebccd9391de1307c85970a8bc155f519872668450c91488689f53c2c1a7ed53f388cb13a2c3896fe5b7d3a0dc1683f27664c8beaea680c8cc54a90e4c6f99fbf05f2c22df60de9aec80c79b7d66207050667b452d7857f9a8ca723280dac7992e2079267ec3ad911404642c4e326bfb96b43c89434ba4bc78c252f4d4ca8d13a8874c6fc8252ea0b56c6bc786847d4318306e1c652c452585eefd0bd9dd3c148a73ba86eedea945f016713ed7df085d0066689e792dacb2bfc1eb5c824372a26c5e944aa7444ac9773d4a1921e49bdd4f8f6d788c263fee04c7b444c5305edb633e1ffe0ba4ea8da011a62f2bbfef4b895ad3f224c3ba3bff0c95d75750c9bcc66ff8a20b6c24bde7581a7ec3866f8716f781f46dcad45a9ebcb6ed46953368397011735d4b52d00e8db397995dbdb3d4f4254687f04688a268c305b2b1f622cf51b174775bad7f6674adc2e58e05cce865f12d7569c8e9b35bcdf3ccce6330d08ce5340a7c630f27a6c8086b5146b292fcbf50ff6aaaef8848a707b2543c618d17bd976c240bc79d33e004e4953482915e7e6ef94964bdea4e02dd7c2f475235f2b99e43229c9ac3aba0db59ac2da03a9ee4f37dbf247a33e6dfe5be7c7f82584f04a46d49f6621da31b91ac3daa4d68d48a56659b448c0ed365cb4aa0cfd908853df5bbfa88e60e10a5a002c32ab3333f2c39bbf3ee01a4aa60d2d01423e6097dc54305f81a2d93e2f6b4e8b351971cbf2457dc76e1fb89293384798ef28234e9b1a47dedc2336f86b8e13c4aef790f5a11239c747d9d865c9a15adeb071070267e5346256648adc0fa4dbdfd787ca1465fc240a324c3caf2931da41499e275fd4b35f6d08db: +f16abdbcc0bcc61a1aee3abd8767ab52e5f79999bb77a3976cbc82670dfd2f7310f451719db0fd21376e228a41c3035c8c2bc42e5aaa926fe608878dbb0dc7ab:10f451719db0fd21376e228a41c3035c8c2bc42e5aaa926fe608878dbb0dc7ab:bfacd7dd4eea467dcce404f4a3520a45b94ebaa622197d02d61529d2b3bf273c4ee1fb95a180c8f87de190a2e5ea70b84ae1eb6fd4447d8a3a8ded10f6ede24f0eb92bd30bc65d4871e8f5da08cbe8cd3c0ac64fd5a57a6b064a89d5159b42f8b3e5a1838c9cb19d88106c0773a275cd2a1d609930bf6b30aeca62b97e319bbfa934f4d0a1e6ac80baebcba2d8ea4bed9ca8562b4acb56979bf885324ac40ab4a50bfb9f349049fc75a0e03de4cc43eae3c6a6cffb5f6ae6c94504415e6c7ed3045a932f47fd20b9f3483a77b6d449d8dfd4a638dbf56f03f0f031879059b2fb49767943f46b3872e2de567d5fef80b02925e9863e0f1d31a80f4e6451c325694b80cf1f1918c6e498878edc47c4530cac466f1a294d55df09af4fdc8072adb1bf26ca8c92f912a2b9febc8b97b58c1e9d32c780323052972b6fbd53304c05193caeb67c5bd3e67479725d297dffb06890abf8cd9e42458e168a6118f905b1d53486016f85dcd98dd339e3460533d0b8a49fae6dc1a071725e6ae5f294479ee3bdcaeb74061841fb2608e88a49fd0f3895b18f85b90f7241dd1387710053faa62bae75e9ae39369c1c02de5d19242efa16e11d44a4ba5778ce7722a91cec0bc0a08c069bdfa130d1c6c4b56c6e93542403ccf27684def57def26df86ced571282dc960974618f0a74a0cde35b653cc6e7730431b825ffb9b8aaab3c7a397c992bc2fa23270fb11ee431afd5f9a644483011173993f19485dd3cbdd187bd3d995ebf0031b1b0de4a8de9c14eb6f780e36b8925756b97906a1969d85e967d880e6e7dda42fd3c30019f11d7081071eee6626422836bbed27d46dd0df1feb6610dc859f513c0bc653d70220fe048d2e97c2e06af530e11bdc7029bccc5c92edecef5e4a2e0be2d251f4415dca3e55b3a850f2630b879e4e036ce8633bf20920b68094215929accc7be40c5778bc554e6edd7e54c9e145b2ee07b65d061c11de0e83f381ce4f57c6483f51069363511074c7a577353b45c6eb71199dce5059fd2c4611b054238aaadf2b6ba534bfffc2722ae3e31ff79ae2ebca99cc3507f8a033cf4fea70c52f7db5de442b42b8d41e99012e42ca0e85a9fb6d4f165b330de6383c5726efca2fe971340002f562dc6cb8f2faf0665725e097799d096091864d66a950a5790953ee16b9ea582009218708c4accd81381358a2c689a041d02d786121:33d805290869b8e04ff089faa2d1fab83743bada68ade5b38ae5f0cc58c3374eba43943c1f5110678eb39b4658611822a26d35ffe19e9cfcb9ba9589e4ec3105bfacd7dd4eea467dcce404f4a3520a45b94ebaa622197d02d61529d2b3bf273c4ee1fb95a180c8f87de190a2e5ea70b84ae1eb6fd4447d8a3a8ded10f6ede24f0eb92bd30bc65d4871e8f5da08cbe8cd3c0ac64fd5a57a6b064a89d5159b42f8b3e5a1838c9cb19d88106c0773a275cd2a1d609930bf6b30aeca62b97e319bbfa934f4d0a1e6ac80baebcba2d8ea4bed9ca8562b4acb56979bf885324ac40ab4a50bfb9f349049fc75a0e03de4cc43eae3c6a6cffb5f6ae6c94504415e6c7ed3045a932f47fd20b9f3483a77b6d449d8dfd4a638dbf56f03f0f031879059b2fb49767943f46b3872e2de567d5fef80b02925e9863e0f1d31a80f4e6451c325694b80cf1f1918c6e498878edc47c4530cac466f1a294d55df09af4fdc8072adb1bf26ca8c92f912a2b9febc8b97b58c1e9d32c780323052972b6fbd53304c05193caeb67c5bd3e67479725d297dffb06890abf8cd9e42458e168a6118f905b1d53486016f85dcd98dd339e3460533d0b8a49fae6dc1a071725e6ae5f294479ee3bdcaeb74061841fb2608e88a49fd0f3895b18f85b90f7241dd1387710053faa62bae75e9ae39369c1c02de5d19242efa16e11d44a4ba5778ce7722a91cec0bc0a08c069bdfa130d1c6c4b56c6e93542403ccf27684def57def26df86ced571282dc960974618f0a74a0cde35b653cc6e7730431b825ffb9b8aaab3c7a397c992bc2fa23270fb11ee431afd5f9a644483011173993f19485dd3cbdd187bd3d995ebf0031b1b0de4a8de9c14eb6f780e36b8925756b97906a1969d85e967d880e6e7dda42fd3c30019f11d7081071eee6626422836bbed27d46dd0df1feb6610dc859f513c0bc653d70220fe048d2e97c2e06af530e11bdc7029bccc5c92edecef5e4a2e0be2d251f4415dca3e55b3a850f2630b879e4e036ce8633bf20920b68094215929accc7be40c5778bc554e6edd7e54c9e145b2ee07b65d061c11de0e83f381ce4f57c6483f51069363511074c7a577353b45c6eb71199dce5059fd2c4611b054238aaadf2b6ba534bfffc2722ae3e31ff79ae2ebca99cc3507f8a033cf4fea70c52f7db5de442b42b8d41e99012e42ca0e85a9fb6d4f165b330de6383c5726efca2fe971340002f562dc6cb8f2faf0665725e097799d096091864d66a950a5790953ee16b9ea582009218708c4accd81381358a2c689a041d02d786121: +be79d1aeea86e86f398137e62ffd79e50eff9f313f25192f89e52f0b4bbd5d32187dac855ca442fd9a3ddc3289c24eb2d26f7a40fb29d8e74431b25022c3a0cc:187dac855ca442fd9a3ddc3289c24eb2d26f7a40fb29d8e74431b25022c3a0cc:6d632a7d3c9be53649d0d1a5eedf519a413b13ac64e9ad854dfa04f2e17329d822be573d9e35ac066f022213a344620bba289f5331695584d1343e815405aeabe3861d63b3a5b92b8cd8eeed2280222abde30a1bccd3f3e411aab922fa1baa097aa5c780d0eaef94ea10fe21f7d639b76d4788aeb5924a9d262dcbc5688a3e43544bec088ca2e0d06d77a71fb641d55226614452b1e0807a9fcd3ca69bf7f25d8041470ceb7b21ead03ec037a1629bd500aa233b59be44978210b6a366f223acfa0797954007b00efb4ffadb5fc92bdb37863e502d7d70681039edf33770df3d1de343dc35f226d5e73944ba0255e2a88ef6c41e472b214567c249594a50878b6731c1aeb5b10fa91fa76a37e1f9f1c00fdbfe3485ded54a009ab6133927115668b59f5115508da9370f6bc92a1185c0d5ca01d291e18c54acfaca738bd71968a342a0cba62e4bb104a5bb379fc83ee1820d1db980253d6cb383e95af15f53c85d175890dde5e4ed03d2d0135e3d60b18293f5b5641ef83c6ece3d52598fc6353686e6f7b09fdec1f6f153672d34b489b48a0db9e42ceda71755481c047016c22534e90c6d201ed7859602636ea77ae8c6734b7c4c5bd99579c508731c7246a29586e406e1d932f6713071d4bea63dc5e2a3761e16024d2c3284f709a1f2ba085ead3200c7046275cb96b61a60b5ac559bc488bd106467c3de50bf5d740d05c9cd701d65b7daea29e64dd5a97adb6b5c82cf7f23017aa7ca1ac9a39e5827eb47e20d359b67c7d4e1a8e3e27c52d33d9303a592623484d797b402cbb458d1ac2ea53e1c4f7abb70cc029554a234574def9bc3b0d3835dc314902e25abb22dfdeddc679a3cc8f07340b15f5762f4407f380342554ed0c62f73b61816ea8c529461e1bf0e9d1c2d5e4c5746336bc0e132873cde0dc2158b54fa1b678a006b4d95eda8a955714273b7cc5cf2add9094d46e49abc096a45f418e2edbe99dd852911688064df7cf061d07aeef42795690f48c9ba19565475d5468a9ef45d7bf75fd71182dd6e640138f182a6a0c6cbbd00c495c4389530ac8e67960eb5c5763f5484eab1c1ab850140da042ba47ed8528800d41787f075fe0d85501a7ab76635d03410d286c0e17db4023a76397468ccb091cc5ac1f6434587913eab922b50ca5567016ddea32fb53255be67f2dcf9ffa85d117f1a655fa70dd3a54cf991531f19130eaa:6dab593bb1d448c974a65c6a0b6fad22b4732632d00489176ef126aa590109e0a723a113107b53e17d690a0d40b0fa336cc87fd5fce8f541accec67f7d1ebc066d632a7d3c9be53649d0d1a5eedf519a413b13ac64e9ad854dfa04f2e17329d822be573d9e35ac066f022213a344620bba289f5331695584d1343e815405aeabe3861d63b3a5b92b8cd8eeed2280222abde30a1bccd3f3e411aab922fa1baa097aa5c780d0eaef94ea10fe21f7d639b76d4788aeb5924a9d262dcbc5688a3e43544bec088ca2e0d06d77a71fb641d55226614452b1e0807a9fcd3ca69bf7f25d8041470ceb7b21ead03ec037a1629bd500aa233b59be44978210b6a366f223acfa0797954007b00efb4ffadb5fc92bdb37863e502d7d70681039edf33770df3d1de343dc35f226d5e73944ba0255e2a88ef6c41e472b214567c249594a50878b6731c1aeb5b10fa91fa76a37e1f9f1c00fdbfe3485ded54a009ab6133927115668b59f5115508da9370f6bc92a1185c0d5ca01d291e18c54acfaca738bd71968a342a0cba62e4bb104a5bb379fc83ee1820d1db980253d6cb383e95af15f53c85d175890dde5e4ed03d2d0135e3d60b18293f5b5641ef83c6ece3d52598fc6353686e6f7b09fdec1f6f153672d34b489b48a0db9e42ceda71755481c047016c22534e90c6d201ed7859602636ea77ae8c6734b7c4c5bd99579c508731c7246a29586e406e1d932f6713071d4bea63dc5e2a3761e16024d2c3284f709a1f2ba085ead3200c7046275cb96b61a60b5ac559bc488bd106467c3de50bf5d740d05c9cd701d65b7daea29e64dd5a97adb6b5c82cf7f23017aa7ca1ac9a39e5827eb47e20d359b67c7d4e1a8e3e27c52d33d9303a592623484d797b402cbb458d1ac2ea53e1c4f7abb70cc029554a234574def9bc3b0d3835dc314902e25abb22dfdeddc679a3cc8f07340b15f5762f4407f380342554ed0c62f73b61816ea8c529461e1bf0e9d1c2d5e4c5746336bc0e132873cde0dc2158b54fa1b678a006b4d95eda8a955714273b7cc5cf2add9094d46e49abc096a45f418e2edbe99dd852911688064df7cf061d07aeef42795690f48c9ba19565475d5468a9ef45d7bf75fd71182dd6e640138f182a6a0c6cbbd00c495c4389530ac8e67960eb5c5763f5484eab1c1ab850140da042ba47ed8528800d41787f075fe0d85501a7ab76635d03410d286c0e17db4023a76397468ccb091cc5ac1f6434587913eab922b50ca5567016ddea32fb53255be67f2dcf9ffa85d117f1a655fa70dd3a54cf991531f19130eaa: +269952172c3fa976defbf40bd6edd8f15cfd4be10c758e3741d74162d8ea229a4aea57c721e3dcca8239e9ad9b22c19bab8df72c88793b24d8dc47cf9740fcf8:4aea57c721e3dcca8239e9ad9b22c19bab8df72c88793b24d8dc47cf9740fcf8:7ccb6a0570c533737b9a534a341a7a96dc76528b997a9b48e6e0fde10f474b27ec989912d176cab742d89a848b3666e9277d695b022fd53a9eb89e88c720399e24ed25db9eb35d6da009e9f024ef8e655165bdef1c0d797c74f019cd591a0442a12d1ca893836ca2628b33e854f3428eec4aa5ed84f4bdd2eef8b6d225caf9496df9edffd735ea54db1bdea883ad5d47eb0bd4a6653f0ab037f040a41517a7741f91e82fdb6fda04f0dfa1bcf8b9b37bf2bfbd87327a636f907fdf968d0189d1a11809c4230ba69d5cbd84f561bcac3ad002e558c5b9b097a01902f29ce3f1ec264153d668c78b845105b9cd2ef3c943531b75aa428f179e4b3418b1d5a4aa7ab1203efa495c8769628eb1063a937b73e4b5cd0cda33dab01a50c64febd975c57a1e841508e8606094d0824fdd96cc6cfa18fa8209b30f0a2a78eac9a767176f573e78c068809b199a69ac6d335d7c920999c40cbad87cf4cc7ca5c644291d75ad7a74bc1e6392d1ce311ecfd2ebc916e39eb6aa3e7d89fb805a27a55f178912b157bc01a055f67aefa78e55c806cbd9c01baf8ef92cad2260b4bb14cfe61782dee5c59972506941c462a4da7eb899531cf996bc98ba3629effe6fcd1706d1b4ee4f2a14e921bd408f30e12e73fb7aa860536b03e77ca937823281a16453fe827935943201e6ec143a67eefa4f94e9abf94f7e3d41b70a82be69ded8a53060c2305f42f62fe6a2f704b67a1e8fddc7d98ba7f3457119b311d449663ed9e320d618dc2368d4950875b9c38c5d8c03104e2e32c4325dedd2bc267e2accb0112018e9c5a8007ccab2f6d7c737792002acb730d72e9f730829ebc42ca564c1d9271bf1869c4d35835589b7431ef7a31a070060fe4a089fb11f2dd3dce65ae0fb45bc3a2860917d933ba2d090569ef5ed43bc2532db879e0f1f225eadcbef1c03d9ed78299e233e4cf07b064a7baac34c5a0c19fc3a5542089f70167be2f85b4a10e778525223be8ffd5cff9648b1005a098b4b3924398fb0bcabcc6edf30c061ece7aea35fe98a9203f8711369530feb5e67bb2d4f59d9c8bc993854dd4747cde399bd0e63740c1cc839ad0f098a38a80beadd648e1436deee60e931e68f52979ce49f301fe39afbb615352091c8b6585fe88447ed6e59a020b2bbe66a9423ae5228c203bfd4847b5181e2c3b4dad83a6d4fa76985eef76adde3b34edbdd28d6a0b4a4ee:3ac80d1e8f68b4058c3a04dad7187373959f26a27002496f8afaaccd8bea0901c54cab87b2a2302e1f3625c2b06c7ebcf3ce96de3afdf00f5194a35e0552c70e7ccb6a0570c533737b9a534a341a7a96dc76528b997a9b48e6e0fde10f474b27ec989912d176cab742d89a848b3666e9277d695b022fd53a9eb89e88c720399e24ed25db9eb35d6da009e9f024ef8e655165bdef1c0d797c74f019cd591a0442a12d1ca893836ca2628b33e854f3428eec4aa5ed84f4bdd2eef8b6d225caf9496df9edffd735ea54db1bdea883ad5d47eb0bd4a6653f0ab037f040a41517a7741f91e82fdb6fda04f0dfa1bcf8b9b37bf2bfbd87327a636f907fdf968d0189d1a11809c4230ba69d5cbd84f561bcac3ad002e558c5b9b097a01902f29ce3f1ec264153d668c78b845105b9cd2ef3c943531b75aa428f179e4b3418b1d5a4aa7ab1203efa495c8769628eb1063a937b73e4b5cd0cda33dab01a50c64febd975c57a1e841508e8606094d0824fdd96cc6cfa18fa8209b30f0a2a78eac9a767176f573e78c068809b199a69ac6d335d7c920999c40cbad87cf4cc7ca5c644291d75ad7a74bc1e6392d1ce311ecfd2ebc916e39eb6aa3e7d89fb805a27a55f178912b157bc01a055f67aefa78e55c806cbd9c01baf8ef92cad2260b4bb14cfe61782dee5c59972506941c462a4da7eb899531cf996bc98ba3629effe6fcd1706d1b4ee4f2a14e921bd408f30e12e73fb7aa860536b03e77ca937823281a16453fe827935943201e6ec143a67eefa4f94e9abf94f7e3d41b70a82be69ded8a53060c2305f42f62fe6a2f704b67a1e8fddc7d98ba7f3457119b311d449663ed9e320d618dc2368d4950875b9c38c5d8c03104e2e32c4325dedd2bc267e2accb0112018e9c5a8007ccab2f6d7c737792002acb730d72e9f730829ebc42ca564c1d9271bf1869c4d35835589b7431ef7a31a070060fe4a089fb11f2dd3dce65ae0fb45bc3a2860917d933ba2d090569ef5ed43bc2532db879e0f1f225eadcbef1c03d9ed78299e233e4cf07b064a7baac34c5a0c19fc3a5542089f70167be2f85b4a10e778525223be8ffd5cff9648b1005a098b4b3924398fb0bcabcc6edf30c061ece7aea35fe98a9203f8711369530feb5e67bb2d4f59d9c8bc993854dd4747cde399bd0e63740c1cc839ad0f098a38a80beadd648e1436deee60e931e68f52979ce49f301fe39afbb615352091c8b6585fe88447ed6e59a020b2bbe66a9423ae5228c203bfd4847b5181e2c3b4dad83a6d4fa76985eef76adde3b34edbdd28d6a0b4a4ee: +cc3138e502a5ff6f80d246366e84d65c59f12d4f496397e6eb99b5267b8cbe2a9e2d3e88af7b52ddcf00e6d0c7759c1238b8fb3eb14421fe82c34833437835bd:9e2d3e88af7b52ddcf00e6d0c7759c1238b8fb3eb14421fe82c34833437835bd:585ecf2f09eb923df20a8555642a2bc0b68c6a5fcfd6b8401c4a0cbabb4c6e6a206762b7a39f2c5455d7808ebfbed56d6760a431c7d20c2dc6ef1b73caa3c49488e30b1ca2520ad20b26a19700780e5ef3ce0144388d8407b6a70c1cda37db7f12091d892f2e91ad4078bb4db1762e46285a7b664b2ad3a34d26d8a94d64587a84527722ea83cb8aa88984e1489743b4214ea6041aa18e55200954efc7edb319df947efbfc6c8d0fea48a131613465d8f4c49498f2269145c6dae50478052598e1ca3be0e33611571fa384771eee402cc2b1d84836c8f1ad28f2ad23dee9ff1d7e1f2521635874115def4d93e89be76180bc55f761144360a8b222892d64d157ccb5d8f4855dca56701495a0e1002d340a4a46156b9b7fe06b7c0759e0b6df559b691ede78b55af64e7c8dd908b788dd6ba35a902c81dceb3788b615de225afa58a81181ab24a73705ee838b6e863fe1bcc26c1b943239230c27c6b397b23d13de6a02c97f3645da91d413f916473b018a61594b6f51cea44457da1e3dbbba6de16866657e92ef0202718a84ad0333e8336b052b004733e8e95ec13e5f91b3806a98d3db729fb735b8147c4a982a2d5b4efae9c09d0a9bf891cbbc3c8f531e76e4044ec91f4d7c5cf77310e2b2cde2e07ccf3e0a19dd6ae1b3fcb2df42186e9c72922d2d4ce51b306e81b16cfcf8f00d513fbd2c5239b45afc654f6fe21acb7e8a0c9aa87b0b605074df9576a6ddd900aca567617cb79656b3b5ecb9ff68b2f6241ed0d024ac27aa6eb486b69fdc0a0db92096abf86002dec7afd847a006a3f6955b49569053be9f1d0a49b793a5411e5916f418ecab953243553b66e6badc4e909be0ef5cc7c6d27199ec3f21423bc45773fb40b97b61185b57080e8f0b89a3ea57c8444ab27ecf7006a766047eeff54d8556cfed23def1da2cc8aebb48c94e779e8203ae2c902b51de0ede0456fb73fb4d5f514a4cebc47fec3f948469a545c6bc57b4138db34e7cc006de26ef507b54d28147567a8c29ac1ecef5bb84fb99aceb23a20294d74a85ae36b33450668a5c2609d3a93934586ff90c3b6d27329eeef3a754e9a9cbd5617ef3b09397bdc971370766589a12d890050d1651458b3fc533c843bffdf9754d932c4ed7611d4d27c32a087555b5eaa37ae90c4979ef54299c420ab5e29ae2845d4dcf2178920a865175fb9cc0e6b8c524b1ee495805d517bfe0:a2700e3895ed0cc2aaf012a40bc7bd0bd29dd79c69c0b4a6edd0530cf3e267c0f82dd84edaf1744dc411d62c0028715258822d7b63d39705612b3fad4b5efb04585ecf2f09eb923df20a8555642a2bc0b68c6a5fcfd6b8401c4a0cbabb4c6e6a206762b7a39f2c5455d7808ebfbed56d6760a431c7d20c2dc6ef1b73caa3c49488e30b1ca2520ad20b26a19700780e5ef3ce0144388d8407b6a70c1cda37db7f12091d892f2e91ad4078bb4db1762e46285a7b664b2ad3a34d26d8a94d64587a84527722ea83cb8aa88984e1489743b4214ea6041aa18e55200954efc7edb319df947efbfc6c8d0fea48a131613465d8f4c49498f2269145c6dae50478052598e1ca3be0e33611571fa384771eee402cc2b1d84836c8f1ad28f2ad23dee9ff1d7e1f2521635874115def4d93e89be76180bc55f761144360a8b222892d64d157ccb5d8f4855dca56701495a0e1002d340a4a46156b9b7fe06b7c0759e0b6df559b691ede78b55af64e7c8dd908b788dd6ba35a902c81dceb3788b615de225afa58a81181ab24a73705ee838b6e863fe1bcc26c1b943239230c27c6b397b23d13de6a02c97f3645da91d413f916473b018a61594b6f51cea44457da1e3dbbba6de16866657e92ef0202718a84ad0333e8336b052b004733e8e95ec13e5f91b3806a98d3db729fb735b8147c4a982a2d5b4efae9c09d0a9bf891cbbc3c8f531e76e4044ec91f4d7c5cf77310e2b2cde2e07ccf3e0a19dd6ae1b3fcb2df42186e9c72922d2d4ce51b306e81b16cfcf8f00d513fbd2c5239b45afc654f6fe21acb7e8a0c9aa87b0b605074df9576a6ddd900aca567617cb79656b3b5ecb9ff68b2f6241ed0d024ac27aa6eb486b69fdc0a0db92096abf86002dec7afd847a006a3f6955b49569053be9f1d0a49b793a5411e5916f418ecab953243553b66e6badc4e909be0ef5cc7c6d27199ec3f21423bc45773fb40b97b61185b57080e8f0b89a3ea57c8444ab27ecf7006a766047eeff54d8556cfed23def1da2cc8aebb48c94e779e8203ae2c902b51de0ede0456fb73fb4d5f514a4cebc47fec3f948469a545c6bc57b4138db34e7cc006de26ef507b54d28147567a8c29ac1ecef5bb84fb99aceb23a20294d74a85ae36b33450668a5c2609d3a93934586ff90c3b6d27329eeef3a754e9a9cbd5617ef3b09397bdc971370766589a12d890050d1651458b3fc533c843bffdf9754d932c4ed7611d4d27c32a087555b5eaa37ae90c4979ef54299c420ab5e29ae2845d4dcf2178920a865175fb9cc0e6b8c524b1ee495805d517bfe0: +5c692c681198b172df2fac2aec3fcf7015c2bb6830f2a98e30a396b64af4280e33b169d4ca271040926ea87835e5066f9f05782f087fca7a556f7bf4cba2e886:33b169d4ca271040926ea87835e5066f9f05782f087fca7a556f7bf4cba2e886:b160ee3a93cf6bc3456e5bd0197c09aa76c2258052f9a34dbc2ed589f8dbe5ff9969a61cfe846b2f6739dc7d4a1496e9ad58605b5a2758ca078c55a9fc1c4eeb5491a84bfd468a2ceb141a773493a9b3ee828b5dde9c00c236ff0156e4e2e45fa07931da68bbd2030a881405c4f78728813a5e04812404c2a19c9b87b1cfe9af95e273ecf9c518c53935f842563b192fae12a73cef085fe19e899e5ba08979e311fb286fbfc7b248aabd40dc61610e1d4fc9806dd21292392db2db40426c5d196a489c5db77e3e9cf0bd041e3c23b5ba1db781a10790be1fe07a2b00ca3af89cbd46efce880e1ef28b0cd79d53b42cd80eaa137eff7df90bcbcf95c9858dc0ccc6d8ca8ae3547bdbf9ff9024f3cf170115eb28bf12b7d3b701460f48d1b4b23d7f6ff72ffdc9a6c52624d15312d7f19ddb6026a15eb54295d331fd79509103bc59a3b6e1ba7ac8c112e4de2817e51c1e16507ba66f2547bc899f69c1207ae5e37bdb0e161b15b612305bc0940f9d1b382a37ec2da639a6ecba1bcdfc51214c3223c11bbab79f3fae3d55e2d4be584fd7601e4e2e558b3be5707115a61f5a815ec24aac18093457bc46c05cfb7a3f2533eadadc9e6c1fe310779e697f683035ce57873df55d791f6d2fb0e2107e6866f839c3a126e9023865ced1bcf6779955af547e1d87eb32a9bf322857fd126b0cdc5d5e904eb76c6706e3c897aefd6e4756fb8aca8170ca5b39669089af1bb141a25d6b8b06034d8b11abf1ff8f8d43375846fa8fa8a34b5f264820744d31149b7d57326c59b1db74131678f634e7232ca5ea5188760a70dc35dc89f8e453b4c65b772c2b6b62768d8373236551baaf24d3c304c41b62c36e6a3383b3a163b73e78d8badb75741e5001d419d30e2ed77c3096e8d8df713b93762c9707bdd0f365a874b9da8ab710495dd56aea93bb77fb222635c63bce9f63af91fac89c66986b8e2176dd451d583394c1907cba1725f06d25d1d0912b3e5c6c7dcd34358fad59dbc6f6b1c2ef33d3ca82f43518fe4ff31378016e578a7bab0b77676ebae0d48d0889d69029d209f283ce8fe0ec23cd832adc12a9c3e3aec2d6036695556d9313f12a899dd59a66bef28ede175f8aaeeeb2942bb90892a04b440d04b66f5eeff61ada72790294ce55c86c6d92785ddd26c7a731603b069c603c92e4fe8ff782544c8e89b40b8b55f90e2a5e9a0f33c7fec77dad8152:ad8f379caf41f72dccadc3e915357ab0cd304e10f4120e0dbbfaac01bffaf2be893f70072dc964069181bec17fe0251055b21e23dee4363b27ef1fff67aafe06b160ee3a93cf6bc3456e5bd0197c09aa76c2258052f9a34dbc2ed589f8dbe5ff9969a61cfe846b2f6739dc7d4a1496e9ad58605b5a2758ca078c55a9fc1c4eeb5491a84bfd468a2ceb141a773493a9b3ee828b5dde9c00c236ff0156e4e2e45fa07931da68bbd2030a881405c4f78728813a5e04812404c2a19c9b87b1cfe9af95e273ecf9c518c53935f842563b192fae12a73cef085fe19e899e5ba08979e311fb286fbfc7b248aabd40dc61610e1d4fc9806dd21292392db2db40426c5d196a489c5db77e3e9cf0bd041e3c23b5ba1db781a10790be1fe07a2b00ca3af89cbd46efce880e1ef28b0cd79d53b42cd80eaa137eff7df90bcbcf95c9858dc0ccc6d8ca8ae3547bdbf9ff9024f3cf170115eb28bf12b7d3b701460f48d1b4b23d7f6ff72ffdc9a6c52624d15312d7f19ddb6026a15eb54295d331fd79509103bc59a3b6e1ba7ac8c112e4de2817e51c1e16507ba66f2547bc899f69c1207ae5e37bdb0e161b15b612305bc0940f9d1b382a37ec2da639a6ecba1bcdfc51214c3223c11bbab79f3fae3d55e2d4be584fd7601e4e2e558b3be5707115a61f5a815ec24aac18093457bc46c05cfb7a3f2533eadadc9e6c1fe310779e697f683035ce57873df55d791f6d2fb0e2107e6866f839c3a126e9023865ced1bcf6779955af547e1d87eb32a9bf322857fd126b0cdc5d5e904eb76c6706e3c897aefd6e4756fb8aca8170ca5b39669089af1bb141a25d6b8b06034d8b11abf1ff8f8d43375846fa8fa8a34b5f264820744d31149b7d57326c59b1db74131678f634e7232ca5ea5188760a70dc35dc89f8e453b4c65b772c2b6b62768d8373236551baaf24d3c304c41b62c36e6a3383b3a163b73e78d8badb75741e5001d419d30e2ed77c3096e8d8df713b93762c9707bdd0f365a874b9da8ab710495dd56aea93bb77fb222635c63bce9f63af91fac89c66986b8e2176dd451d583394c1907cba1725f06d25d1d0912b3e5c6c7dcd34358fad59dbc6f6b1c2ef33d3ca82f43518fe4ff31378016e578a7bab0b77676ebae0d48d0889d69029d209f283ce8fe0ec23cd832adc12a9c3e3aec2d6036695556d9313f12a899dd59a66bef28ede175f8aaeeeb2942bb90892a04b440d04b66f5eeff61ada72790294ce55c86c6d92785ddd26c7a731603b069c603c92e4fe8ff782544c8e89b40b8b55f90e2a5e9a0f33c7fec77dad8152: +9d5f85d2e7dfd03bb689d900285fd4461538a5f2710a13ed21c775f6eff6b3ffb86797e4be0286ae39e44df0a00c016db4555ef86f2f05d0a3ed89d89a4c3e5e:b86797e4be0286ae39e44df0a00c016db4555ef86f2f05d0a3ed89d89a4c3e5e:f70b5b053a4672512c24b3168392f6a17dd77d8689c21c86efc25829a1a04fab4f76c8521684d32010455907a26908677b40dc6947d654f2914c30ecee724fa68446b59d091e258fc862411c964d668def83034b627ed416dc190bb5a263a6ff8d559e13b8936225fb4dab4f7bda0468e547e708cb04cebe1e5cfc69f76a1d283f28168286f24ecea5535e4490a0c55567a7345ef953ce426b209a3de3df595e80ee61e572a278ab02219551b73da41984808285a83598a02d9b28671210004e31d8af9242c16f90d5ea8f63a1ff66cfe60ecbe537245fa12a9b154115295806ea2d11f3671782b9af4fa86a1288e123cfd2409a5dc98f41b8f6df299bbcc4bb6447dc03a6d60e9b2c5b8ffc40d983956be97768dd0612d47cbfa7571c9969856c152cd3b473ace0b8a144aac2095c0f72f1d3147152b908ef6626d5222819b20bb3350a46452f675490c2a82150eec40d75b66a325d6e929a905ade1e3160ab950181efc66e59230865d5e599698a8a3ff560c4c601a7a9a5da3b5d89bca93f7cf5bcf5bd5ecff8f1a185c8220e4c77821e62adf95a037f2df7cef43a4c60ac75801e9fccdc5b08eed328dd93100904115645ec1ee085cc778b0f4e46e17298984a702eceb3e15283d820004f74a079520d63a75fae33ec3f4b836469e1aa99ea244af1fb08b00a8c9dfd03308dfc20235ea9c8283f4da47cfbcdbd031a02d164160f2a58986700b19526d41e4d7fd458434d7264bc8eb642e6d8dd2759ce2b85c97b3702e70da71f18edc53e9140a645627e0278e8e70539037484dcd18c62fa330717d6148a0d623ff8b65ea8567ec7fa04c892e3a1ecee96e832f4155074c83cbc93e98cc67f1fa112aa06e9915fa4d2dea931551e7c623aa8a3a7619ea24ff914e264f31fc73dfa8c430ac46ce16dc968c5a4085d5c380d30cdc6f43dee806f38d1df420a065574144737056daa62f0c098c9c52fcc04cca642c45d687345a094613d4a3c6c8788bfa218538ad7ece1bdb6c93924eec4baaa3eb15dc1494d65ffa1a23ff8e985263408fb02bfe39a8c55b300b1a02ed36c6714dd5ab750d47f021f65e08c635f1d6b7baf396cb4f93d56c1ca461bb12e94de7e5d98659a8af0bf019fc42280e111e04800ff80e0c157150e165609454281b20007e3edfaa1ea854465547a006a4c3236411495da166098af2823a459cf100a1f3c92c6390c6066cdbf:176b9592f8c25135292add4daacc9c4faa21d4f49b278480c4e8881c01624df9a37e23e18e84ca32d0d8cb851054222f10a495419f197e7b3d18df0adfb1b307f70b5b053a4672512c24b3168392f6a17dd77d8689c21c86efc25829a1a04fab4f76c8521684d32010455907a26908677b40dc6947d654f2914c30ecee724fa68446b59d091e258fc862411c964d668def83034b627ed416dc190bb5a263a6ff8d559e13b8936225fb4dab4f7bda0468e547e708cb04cebe1e5cfc69f76a1d283f28168286f24ecea5535e4490a0c55567a7345ef953ce426b209a3de3df595e80ee61e572a278ab02219551b73da41984808285a83598a02d9b28671210004e31d8af9242c16f90d5ea8f63a1ff66cfe60ecbe537245fa12a9b154115295806ea2d11f3671782b9af4fa86a1288e123cfd2409a5dc98f41b8f6df299bbcc4bb6447dc03a6d60e9b2c5b8ffc40d983956be97768dd0612d47cbfa7571c9969856c152cd3b473ace0b8a144aac2095c0f72f1d3147152b908ef6626d5222819b20bb3350a46452f675490c2a82150eec40d75b66a325d6e929a905ade1e3160ab950181efc66e59230865d5e599698a8a3ff560c4c601a7a9a5da3b5d89bca93f7cf5bcf5bd5ecff8f1a185c8220e4c77821e62adf95a037f2df7cef43a4c60ac75801e9fccdc5b08eed328dd93100904115645ec1ee085cc778b0f4e46e17298984a702eceb3e15283d820004f74a079520d63a75fae33ec3f4b836469e1aa99ea244af1fb08b00a8c9dfd03308dfc20235ea9c8283f4da47cfbcdbd031a02d164160f2a58986700b19526d41e4d7fd458434d7264bc8eb642e6d8dd2759ce2b85c97b3702e70da71f18edc53e9140a645627e0278e8e70539037484dcd18c62fa330717d6148a0d623ff8b65ea8567ec7fa04c892e3a1ecee96e832f4155074c83cbc93e98cc67f1fa112aa06e9915fa4d2dea931551e7c623aa8a3a7619ea24ff914e264f31fc73dfa8c430ac46ce16dc968c5a4085d5c380d30cdc6f43dee806f38d1df420a065574144737056daa62f0c098c9c52fcc04cca642c45d687345a094613d4a3c6c8788bfa218538ad7ece1bdb6c93924eec4baaa3eb15dc1494d65ffa1a23ff8e985263408fb02bfe39a8c55b300b1a02ed36c6714dd5ab750d47f021f65e08c635f1d6b7baf396cb4f93d56c1ca461bb12e94de7e5d98659a8af0bf019fc42280e111e04800ff80e0c157150e165609454281b20007e3edfaa1ea854465547a006a4c3236411495da166098af2823a459cf100a1f3c92c6390c6066cdbf: +4aaf2d132884f30d1127cf187ee09388b4a5c44a9a9267e6728317398951fb6183727e9257349128559ebf759fdc82122cce76746639c0ada9761f0d60b940b1:83727e9257349128559ebf759fdc82122cce76746639c0ada9761f0d60b940b1:d73eaf11413bf4d5bccf6a2e809cd6832a51823aa22bd16e09cf56ff045eef2d1adadda50c2ebd67bbc4d70e493c968cb4de4977065d4463300694c9caa57206d6664693d8462c3c576b525cc7acf79f26f9055a1bcfa7d077f45ebe0b2d481ebd63f7340a33e4ab68f1604975ec1dfec45a791a2abb1044d75a4db55adf59b8394ebde6824c21145b00ef3b1b08ed11fd51dda514ed7e21e54dbaf6abb6d9e317fcf9fd375b18764e64ac9be5b08fec3b78abbab1d12a2ab09d559acdc7133fb2e0008e0c114b7cadb4bf763078674d03e9c807bec1e2ca71adcdaa310d587fa56950fc0fb2e979043d50f9ae23fa8f821cd9d6232789d0eeccfc4f47e3ad804e25cf5a425f94377d17874833e6ae3638178c78b79519d64d9793f4504606a0eab68707f6e1f7cccb515be3d1201bcd19f2f0e255c722eab12b43aff8c8c5561125fbca1f6542076a06152eb7e4b0786324c2495e79d79c0a8e295bb2e3dfd05a9033190065a284552a6e736006ace41f97cc434a2512051b727ce5bc9c4a75529ec53dd7d1f126e793857747b5ba8d03155d4555f59e8baf2f0cdba871ac160e7519a852db004f701641a40a422d4c38b6c0c3cc8fbbd05322ddc0001fb867286e296cbd69862cbccc7447038eb30f8a8123b7b31373984702c3be457a4b8c54e6e5280485a2c4ff84521f298ddeb3b3b2bc91f114ddce67030248044469dc06f362f2919a3fece5082375d04080376fe219d9b4575b1cf1c9ec4dcac5749fc778f515dda13fa0d586c264b9bb61503310762c789ca11608d2fee674c70ac4fc6d5ebcf68c4ab89bd84555fc007523c28a7e1dd08a9862044d5245b91a8778ec9ee984a41a9e13b7abd657ae2a46ae860152c644acd95367678ff64cc54006e36614805ed618a7c6d0fd33a908523090841c230af09846d132bb4c6b60e2441f9d3c498714f470f6bc03a80d14a294b565d1d5e781cffcb1304efdbbc7bfeabdedc857acc42e2762bbf97af839a166752da295672817f10dbd472d381f53165555ac8222a78535a86805f1bed422889f206109aa74772edc0bb51e8a9840cf62c92fa635b90cae076dd50e5aed9deac843fa8a6b539988285ff1adabe4c7b83d9e29ac2d94092daafec9f6673689ba9e9252d864d7577aa89505d331fe7809861277002a0b44a96ba6ae4a52b3548bf268e777780c00209b245f8b1417ee5e701a12334ad5:5f11df3906a712a953f47c859806b5237358d08ba95e49f9e530a37165835e9359d9769dc21fbb4d44497b93905bca8d9917c728493fee3acd5b521dbd1e2408d73eaf11413bf4d5bccf6a2e809cd6832a51823aa22bd16e09cf56ff045eef2d1adadda50c2ebd67bbc4d70e493c968cb4de4977065d4463300694c9caa57206d6664693d8462c3c576b525cc7acf79f26f9055a1bcfa7d077f45ebe0b2d481ebd63f7340a33e4ab68f1604975ec1dfec45a791a2abb1044d75a4db55adf59b8394ebde6824c21145b00ef3b1b08ed11fd51dda514ed7e21e54dbaf6abb6d9e317fcf9fd375b18764e64ac9be5b08fec3b78abbab1d12a2ab09d559acdc7133fb2e0008e0c114b7cadb4bf763078674d03e9c807bec1e2ca71adcdaa310d587fa56950fc0fb2e979043d50f9ae23fa8f821cd9d6232789d0eeccfc4f47e3ad804e25cf5a425f94377d17874833e6ae3638178c78b79519d64d9793f4504606a0eab68707f6e1f7cccb515be3d1201bcd19f2f0e255c722eab12b43aff8c8c5561125fbca1f6542076a06152eb7e4b0786324c2495e79d79c0a8e295bb2e3dfd05a9033190065a284552a6e736006ace41f97cc434a2512051b727ce5bc9c4a75529ec53dd7d1f126e793857747b5ba8d03155d4555f59e8baf2f0cdba871ac160e7519a852db004f701641a40a422d4c38b6c0c3cc8fbbd05322ddc0001fb867286e296cbd69862cbccc7447038eb30f8a8123b7b31373984702c3be457a4b8c54e6e5280485a2c4ff84521f298ddeb3b3b2bc91f114ddce67030248044469dc06f362f2919a3fece5082375d04080376fe219d9b4575b1cf1c9ec4dcac5749fc778f515dda13fa0d586c264b9bb61503310762c789ca11608d2fee674c70ac4fc6d5ebcf68c4ab89bd84555fc007523c28a7e1dd08a9862044d5245b91a8778ec9ee984a41a9e13b7abd657ae2a46ae860152c644acd95367678ff64cc54006e36614805ed618a7c6d0fd33a908523090841c230af09846d132bb4c6b60e2441f9d3c498714f470f6bc03a80d14a294b565d1d5e781cffcb1304efdbbc7bfeabdedc857acc42e2762bbf97af839a166752da295672817f10dbd472d381f53165555ac8222a78535a86805f1bed422889f206109aa74772edc0bb51e8a9840cf62c92fa635b90cae076dd50e5aed9deac843fa8a6b539988285ff1adabe4c7b83d9e29ac2d94092daafec9f6673689ba9e9252d864d7577aa89505d331fe7809861277002a0b44a96ba6ae4a52b3548bf268e777780c00209b245f8b1417ee5e701a12334ad5: +4bc7daabc5407c226d1920db4afd21b2a5b3e59b8e9246053f6a1a6afa54e7e7dc539885fc7bee002ac5debae16bddbe4b553fa15e81ee798876940f38cfc4c5:dc539885fc7bee002ac5debae16bddbe4b553fa15e81ee798876940f38cfc4c5:6acce99843b241afe6edd5d0ab78d0fb21c8c35aff881389d505f2f1dd91af1eb2ad229254927c7f0ecfb7a8141690573a655d69853d74d0708bf8b1e60a03963028a625b79f3dfea2b113ffcab46f3cfd4a621e8fd8ff0a968143b0ae03ccb6f42e25e2d74dbf515bc358699b635009b01d61fe597f1dc2c35a7ba4555278ee0ea456c7d35fa8757a417924b1d0a8351f226a13ec29d025b42696ec1d9925b769cd59c8e2f9cd3ce4e5c020e051e7a36f3f97c1e8ec71974bc16ac4de4651ad4df2e9c0eed686924224fe6de6c60dd4acc26e0aabd80c21d509d959b80b4353958d00e44c511d23bcf44552608bfa56a9c5ae79de62bb23f11d740f48240c27e101999751f2534742c0a6913ff64b683a18995abc393feb9d57c71f49a080557298cc405d11b7988d7116840c5adaf53bc672b46923cc457c7039940ad4d5bf073c6c886b1339525926d281dbd1a79739b2e36414cbd321b185fc88f18d2f81c809975be9a093644cc559ed2ae5cc0e35cbdd1811f70286057a3f703067edddf5eb1690a7427bb73fe3024ed0db82a5ce8f1716428a76fd292ba99a300c4b2f360da2124617590b10e3b162a6e67dd5d5a59bcca10f610fa064affd55f8483b98a68d076f278abf888a08a014e0ea499180fbc79840ceed13cc6b2458bfab9b0dd7ae9d86461fe215e7c9f63f768cee4a882df0dd84e3eb4f2d7f6b18fa57d8bc7d9afb63c21ac465e7903b9bfb8638a29361f7ebfc6e54e5465a6cef463ae22643ae410258779ca74b70401a9455a4d157d74a7029efe6b519a8c4be696756e045ae4081b77dd6031f0d250fa761e60f859d9063fc105aa0a1a7450af153e705477777c442586df407402ba238752faef74f3345c26a4533be9a61f5fc6bde48e3cba75c04d6f7b333e37006dd0c94fd3b6a130bd6fcdb3c6abe21ca60eb431cc2d8a2ece7169d2dcfce2760825657fd4c26f3c3b830acdfd508011d14764b3be91715571a3183018e0d221fb9532bb2e1711e725a273ae0cc2faccba7d5504929459c992517b05c1ddd03aaccd937b86eb67bc8202d01cab3d489586eea1acca7dc20cd0b6475c258ff673661496a22ea96b89db4bf3fcaae3bb04f67db096a47ff7e1ee239562dc10d40f053944f3d7bcc3ff4c0ff765654ba5ea64f0ea63e45a21d9b12949f14f7ea7074e9b659c5c5d44816842de89698a8fccace43eb6b4135e0b333ac:a7a6488839bbae04dec92f96d728c464685d7a96df512b0051163d22538f74546fa986b1b60a6d8cc766a26c6984c9cd2688395898e2b2ae72dc6a2d5a9f750e6acce99843b241afe6edd5d0ab78d0fb21c8c35aff881389d505f2f1dd91af1eb2ad229254927c7f0ecfb7a8141690573a655d69853d74d0708bf8b1e60a03963028a625b79f3dfea2b113ffcab46f3cfd4a621e8fd8ff0a968143b0ae03ccb6f42e25e2d74dbf515bc358699b635009b01d61fe597f1dc2c35a7ba4555278ee0ea456c7d35fa8757a417924b1d0a8351f226a13ec29d025b42696ec1d9925b769cd59c8e2f9cd3ce4e5c020e051e7a36f3f97c1e8ec71974bc16ac4de4651ad4df2e9c0eed686924224fe6de6c60dd4acc26e0aabd80c21d509d959b80b4353958d00e44c511d23bcf44552608bfa56a9c5ae79de62bb23f11d740f48240c27e101999751f2534742c0a6913ff64b683a18995abc393feb9d57c71f49a080557298cc405d11b7988d7116840c5adaf53bc672b46923cc457c7039940ad4d5bf073c6c886b1339525926d281dbd1a79739b2e36414cbd321b185fc88f18d2f81c809975be9a093644cc559ed2ae5cc0e35cbdd1811f70286057a3f703067edddf5eb1690a7427bb73fe3024ed0db82a5ce8f1716428a76fd292ba99a300c4b2f360da2124617590b10e3b162a6e67dd5d5a59bcca10f610fa064affd55f8483b98a68d076f278abf888a08a014e0ea499180fbc79840ceed13cc6b2458bfab9b0dd7ae9d86461fe215e7c9f63f768cee4a882df0dd84e3eb4f2d7f6b18fa57d8bc7d9afb63c21ac465e7903b9bfb8638a29361f7ebfc6e54e5465a6cef463ae22643ae410258779ca74b70401a9455a4d157d74a7029efe6b519a8c4be696756e045ae4081b77dd6031f0d250fa761e60f859d9063fc105aa0a1a7450af153e705477777c442586df407402ba238752faef74f3345c26a4533be9a61f5fc6bde48e3cba75c04d6f7b333e37006dd0c94fd3b6a130bd6fcdb3c6abe21ca60eb431cc2d8a2ece7169d2dcfce2760825657fd4c26f3c3b830acdfd508011d14764b3be91715571a3183018e0d221fb9532bb2e1711e725a273ae0cc2faccba7d5504929459c992517b05c1ddd03aaccd937b86eb67bc8202d01cab3d489586eea1acca7dc20cd0b6475c258ff673661496a22ea96b89db4bf3fcaae3bb04f67db096a47ff7e1ee239562dc10d40f053944f3d7bcc3ff4c0ff765654ba5ea64f0ea63e45a21d9b12949f14f7ea7074e9b659c5c5d44816842de89698a8fccace43eb6b4135e0b333ac: +f26af210e3b20173990c7745922cdf9424773abb374d777a512cf5b97b3a000d54586abf041176e06aec5b6010e190916da54a8c4bde288cf24d8c107cb3b730:54586abf041176e06aec5b6010e190916da54a8c4bde288cf24d8c107cb3b730:88e26da35c54884b47146f4e3f014ab65b3d71aa7e3c3391adbeb19ef2e7b9302e281991b261b6a0992e2e89a49f480ca2d8e684b12f9b1509b38f6a7a98a5ddb4c2d869fd0318e98ecd8fd9df491baf99a9294de49e1cf8dd41ee85730af025a701143e4f0c8e3d92d55b59ca7d4a6c89ad760dffc0c2189209508ef6c2214edf9967b17def123d8692c9e4e20b1e98268808704f5f9fe1a6d6055e32c872564bd17edb7359578629017f0c30feab8b504e228923adc7e81ae20a852db0ad676a78e081336d6b0402f9cdc5d5e90128ca945d10515ca0c5ef03f731b1d40a710741d41c1dd1ca16b1060febf2a0532e6f5d7651ef446375ec18090cb8418b8202f25a0389031b307f223c5b5f6afe36a9adc1068f2c6e0ea5b2b6cfeb8dc004f7b829c80439069b81a7bd907477c6135ef282b771f141dbe75a0fa056e06b8a1a1f98c25fa54d14c8fdb42d6502595c59d25bacf1a19adefcc13170f7a4317b6ab610b609d414b0073ea04ac29eb10ee73cd71a4ca60409f8e760e60f939510100d0c8cd76f264bb37811f97aa5299ac0b12d4168ff38ecdfa80b1e5c1b3bbd4d40d3544735df7167eb158a9a9a234d445f1d663ded7171edc68d172c92214b82ef13fe6b8c43aa89b739b4990ae947a34f020a8d8943b0f7a5d61dfa76adde0272e98c1159c0fd8a1de33f2cef8edd32857b2189ed96128057ebdea81f7a3a3dffe1893b5ba877556c90383fa2c5a6fd680e8a67dee4802d90dfe971623a7be22ab3ca56067b1e5c694aa84c19f16d69e284ddfa039c108d0435813812390d8ebc1e50138176f259dc0f26bca13bc943f50d5a3500b18d593574c620fc097ace430fb80728d3a1aa644e504b1009ad67536ceb011f2a357dbd009e4a63f524d5b5957f331567c5b4d185a61df22d7071d31ae92141e199c12289515aed80c91021456bcd45ccc634037dcf69b41d6b1ff53471010d99f187f04654f43622287871fee6dcf5f3023cbd0913d99aff43fa95b32ea2b133b4c9ac4b017b7cf8f9be5086fe92b42cb8dbed5b630bf097c18e2e55c3dd93271e09c2d1cc6af87d83fdef3c3e3c4cbafbea9b60fd5e9cf0011de2e9e26fbf09afeef5c69802a6c46bdf54c145862944173e017e30149ea5c03c7aefa28a9cac7767002ea3fefbdeae5bae005c370dbc064244d5b9be5500a35726a99bc9e8c2752d510e139af225580098c8189aa9c520:ce454530b922ba5ea162f1a452e05c00363a49a9db8a569497c00caf1cbea99180770554ed4e3140dfca4555159ebf48ef5d2a50f394aebd782116ed6569a40988e26da35c54884b47146f4e3f014ab65b3d71aa7e3c3391adbeb19ef2e7b9302e281991b261b6a0992e2e89a49f480ca2d8e684b12f9b1509b38f6a7a98a5ddb4c2d869fd0318e98ecd8fd9df491baf99a9294de49e1cf8dd41ee85730af025a701143e4f0c8e3d92d55b59ca7d4a6c89ad760dffc0c2189209508ef6c2214edf9967b17def123d8692c9e4e20b1e98268808704f5f9fe1a6d6055e32c872564bd17edb7359578629017f0c30feab8b504e228923adc7e81ae20a852db0ad676a78e081336d6b0402f9cdc5d5e90128ca945d10515ca0c5ef03f731b1d40a710741d41c1dd1ca16b1060febf2a0532e6f5d7651ef446375ec18090cb8418b8202f25a0389031b307f223c5b5f6afe36a9adc1068f2c6e0ea5b2b6cfeb8dc004f7b829c80439069b81a7bd907477c6135ef282b771f141dbe75a0fa056e06b8a1a1f98c25fa54d14c8fdb42d6502595c59d25bacf1a19adefcc13170f7a4317b6ab610b609d414b0073ea04ac29eb10ee73cd71a4ca60409f8e760e60f939510100d0c8cd76f264bb37811f97aa5299ac0b12d4168ff38ecdfa80b1e5c1b3bbd4d40d3544735df7167eb158a9a9a234d445f1d663ded7171edc68d172c92214b82ef13fe6b8c43aa89b739b4990ae947a34f020a8d8943b0f7a5d61dfa76adde0272e98c1159c0fd8a1de33f2cef8edd32857b2189ed96128057ebdea81f7a3a3dffe1893b5ba877556c90383fa2c5a6fd680e8a67dee4802d90dfe971623a7be22ab3ca56067b1e5c694aa84c19f16d69e284ddfa039c108d0435813812390d8ebc1e50138176f259dc0f26bca13bc943f50d5a3500b18d593574c620fc097ace430fb80728d3a1aa644e504b1009ad67536ceb011f2a357dbd009e4a63f524d5b5957f331567c5b4d185a61df22d7071d31ae92141e199c12289515aed80c91021456bcd45ccc634037dcf69b41d6b1ff53471010d99f187f04654f43622287871fee6dcf5f3023cbd0913d99aff43fa95b32ea2b133b4c9ac4b017b7cf8f9be5086fe92b42cb8dbed5b630bf097c18e2e55c3dd93271e09c2d1cc6af87d83fdef3c3e3c4cbafbea9b60fd5e9cf0011de2e9e26fbf09afeef5c69802a6c46bdf54c145862944173e017e30149ea5c03c7aefa28a9cac7767002ea3fefbdeae5bae005c370dbc064244d5b9be5500a35726a99bc9e8c2752d510e139af225580098c8189aa9c520: +39bffe007f8df7ce4e56fd176b102b923ba48aeb8269fd0cd520c23a7b236e6c9532636800010b3dd4012e341fcad6d29afad484e6fd736e89d5bc02ba0ac853:9532636800010b3dd4012e341fcad6d29afad484e6fd736e89d5bc02ba0ac853:7a8c20bf2eff69af8bad6bdfabc7909c58ce746cc4df78b69b33c105ba3bd8da75244758b5172d5c4501bc39970185ee3d437083a9959f81e7665b829a69a5d72e034d351adddceb3d3fff589988df182b46fa53d26e7c9eac062215788f2337bf90f0177d8ca744f95f28fea854593c4362c82e9ded19b904ff99d2bea82432822e52c3da6d462da754ff1f8bd109942df51dba25b7cde838d5f524239f1331f463194e10ff56795b296878feb1f55d43ec7daf0ca5ab3d684b55bb0aa4c720d4b5c2e830c858694d3d0fdbaad0bf67d873182d95b2412fce5e7b00fa6bfc38b132efb96f87bc6c10070a5716ec9b33a2692cdf5bc41c7f737e28c4220317a489b7323d5e20f65d375d769f9e79376fd02d85368671e7e081eb753f888545ebe5c000b2f80143eb358d43185e2f1c294b9f29c8bb91482d4387494aad176deb85540fd005c97d13e6663f09944eb43a46e6236794bf6e21f81d0a42090f9ccef90a6c4807b5ff541300e5934881a8d92196b4cee85d28092a828ea3bfc6b745ad219be9f5e9574117d079e02f4b748e2cc01a32826a3708231914d2772c764119fd99d53ab5b5a2e9d891a48a9aaaacc26338b18248db8ab2d525daf15ff53acbc3aa98d4f2d4a337bbaf6d1be21985a4af600e29bbb42c8d89e6b389c66f42270c3a0b051bdb623881e02f2f4294cec3476386747abae6c7700b8f9b0387cddfb73668fb57693d8474196b33abd12dce59a57cf72ee6cc1ddbaadfb19e90af8131b3a90f9867f4c7e15bdf9e218477016bd0ad3be8dd059671ff656cbd4ed898086de4d423f3dfb270bbf19d9f53f7f6f2d22c6ac9025cbadba442e31d9811e37e847dbd484d80cf743039ffa7048470fbdc6080f6d381dc7e3fa27122df53cc06394ea6fc446e1ba72538733ed3abb685f16dfd5ccf585ae8fbf9954b50f10b7e5432a22b369406a9b7088961f0ae207495ae7185396dccf292dc463f41f376a1ca89eefbae19269152031bfd815288e8b5baf348c4f8ff3dff4fd6d108f871daa352110fa64188b01b8526a845aaed133e456b4c83c4fd4bbb165b4090307e8eb17df176c322520f37599c2105aa8120758394a4222473476764cf0af7c55183eba9683d7270631443f3c51fb8ab0c130ac436ab603ff4f1d8656cdbed229a202b40008ea10b171542f74a70b7bbacc4016b7f636aa89633b7668058f13312f57c5162d18e399e:a27cca4b9f5b95ad0e44e4740c15deaeb93f22a9b254ebbd2329365a00966c9f4ec1e55c5894e7bfc23d398d3970b9465e98a8d23e72dae8e350da3531ae69087a8c20bf2eff69af8bad6bdfabc7909c58ce746cc4df78b69b33c105ba3bd8da75244758b5172d5c4501bc39970185ee3d437083a9959f81e7665b829a69a5d72e034d351adddceb3d3fff589988df182b46fa53d26e7c9eac062215788f2337bf90f0177d8ca744f95f28fea854593c4362c82e9ded19b904ff99d2bea82432822e52c3da6d462da754ff1f8bd109942df51dba25b7cde838d5f524239f1331f463194e10ff56795b296878feb1f55d43ec7daf0ca5ab3d684b55bb0aa4c720d4b5c2e830c858694d3d0fdbaad0bf67d873182d95b2412fce5e7b00fa6bfc38b132efb96f87bc6c10070a5716ec9b33a2692cdf5bc41c7f737e28c4220317a489b7323d5e20f65d375d769f9e79376fd02d85368671e7e081eb753f888545ebe5c000b2f80143eb358d43185e2f1c294b9f29c8bb91482d4387494aad176deb85540fd005c97d13e6663f09944eb43a46e6236794bf6e21f81d0a42090f9ccef90a6c4807b5ff541300e5934881a8d92196b4cee85d28092a828ea3bfc6b745ad219be9f5e9574117d079e02f4b748e2cc01a32826a3708231914d2772c764119fd99d53ab5b5a2e9d891a48a9aaaacc26338b18248db8ab2d525daf15ff53acbc3aa98d4f2d4a337bbaf6d1be21985a4af600e29bbb42c8d89e6b389c66f42270c3a0b051bdb623881e02f2f4294cec3476386747abae6c7700b8f9b0387cddfb73668fb57693d8474196b33abd12dce59a57cf72ee6cc1ddbaadfb19e90af8131b3a90f9867f4c7e15bdf9e218477016bd0ad3be8dd059671ff656cbd4ed898086de4d423f3dfb270bbf19d9f53f7f6f2d22c6ac9025cbadba442e31d9811e37e847dbd484d80cf743039ffa7048470fbdc6080f6d381dc7e3fa27122df53cc06394ea6fc446e1ba72538733ed3abb685f16dfd5ccf585ae8fbf9954b50f10b7e5432a22b369406a9b7088961f0ae207495ae7185396dccf292dc463f41f376a1ca89eefbae19269152031bfd815288e8b5baf348c4f8ff3dff4fd6d108f871daa352110fa64188b01b8526a845aaed133e456b4c83c4fd4bbb165b4090307e8eb17df176c322520f37599c2105aa8120758394a4222473476764cf0af7c55183eba9683d7270631443f3c51fb8ab0c130ac436ab603ff4f1d8656cdbed229a202b40008ea10b171542f74a70b7bbacc4016b7f636aa89633b7668058f13312f57c5162d18e399e: +3c4080cda0fc3c03b614d980f2ff831f5be0e7a981d5381a1618e0b8fd001776f1c3269d870402caa43882135d9dbadbbb162dfca0b3dad197e6b8a7ee679a70:f1c3269d870402caa43882135d9dbadbbb162dfca0b3dad197e6b8a7ee679a70:0ceebc0e8a47720f25835e2b9acf891bcca4bda38637f363274458baa9e2bbafedd0938f5688734e22ac50fb120f665f6c4c61c6531739b929ac83cd77f8963b754488b9b859c13853637cf025c14e8fdd118faa14cf3930ceb35f104d95441e56489440f62041ef1aa7c4b08b2807e32bb9584b9004d76e76533348506d64f112e1ff6f938f642230bf38af010e41987270248b13635a3567b355bba5b57448c6d13b74f3bebf617915821028fca5defa4ce5424ca191cd54a22944a3d940e4ee2e2ba5d504c85f959b514c4fab41ccb5743d9cb2f9bf33d1d8c2a5869e9f4660c3fb224b39141e3110c9ee8aeb871e14c62c6be38fb9a4568d736810bb9d2073178b6c7e87e3582efc62b53c23c5d46520ba33ffb3a9ca649ef26fe74a3cff6188427326b8c96f74354cb3ecaa611b12cded565e59fe1f8f400097e93ea85951b5b4e9009eea7db937e4349c4e5e00c4456c6c5f4e57411baf4e46e700ac400257765f48dab03e439f76c1499b5108047c830109dce7f740d1393787e29d3716d3c47e755cb828e7d440a971975197ebdb3f9b737ba11f7fd0386a959249017de7234d5e5a9b473bb9583a3742c774ee552a12a1f36eb3f26c885bed22e91c74cf32a8dd3edb08b674bf386ef427727912d57c5fafaa1cfeb740cd52b9dee995e3d0161cd9213f38fd681d538ab8bf97b745f54980030ef8b72696d4e27473fb0f1acd5d0aae0297211680ea0fc59d7b6d51c63292585a1d553d0c8954b42a4bd6fcd3a49575bf5c88953f1f4ea7fe0ed7a579d1697e645e2a61c69d1a56bc605bb04060a2778d509a8aadbf35d94697ccee9d3543dd01281a031f2a0eb3a9eb13ae56ff44fa0aed4f3488747d6af820f3989b7133f449ea56d3a7f731e791b7ed2a5db939bb75352de7daec5066fd57557165adffa631cd3f967c3c7cfc11cc1f14fa23defec3eb0239b45ed601a3a8078ccfc7f8380902a859ee9ce2db795efaca0a01dc0879d506ac97d10704d7757b3ccf3b37c339b42db23782278023e4c2e77d74246c9e544149a55c0c920ebf2986b4c5b4b3572f748c4b15c7f863999bc5132adad09761eb76505019769fb55422f603184e24c0d4f3761987b5c50feafcce53302a3a415e20f56a054803e553bacd242a5e1364aa3b2d7cb3bc1e1b86a47431cbd39695b67f554c4645b7236904094c11aa1b40326ba91b8bf4873e9a4de04e2bf4625972:c9d4a4728b8fdd240d9c498aa35de95a4bbd51785b73c8403fdf040dfaed9447efad0069b67c783d4b81d966bef6e3d9a808a0584b98ec2b18322c4c920eb00a0ceebc0e8a47720f25835e2b9acf891bcca4bda38637f363274458baa9e2bbafedd0938f5688734e22ac50fb120f665f6c4c61c6531739b929ac83cd77f8963b754488b9b859c13853637cf025c14e8fdd118faa14cf3930ceb35f104d95441e56489440f62041ef1aa7c4b08b2807e32bb9584b9004d76e76533348506d64f112e1ff6f938f642230bf38af010e41987270248b13635a3567b355bba5b57448c6d13b74f3bebf617915821028fca5defa4ce5424ca191cd54a22944a3d940e4ee2e2ba5d504c85f959b514c4fab41ccb5743d9cb2f9bf33d1d8c2a5869e9f4660c3fb224b39141e3110c9ee8aeb871e14c62c6be38fb9a4568d736810bb9d2073178b6c7e87e3582efc62b53c23c5d46520ba33ffb3a9ca649ef26fe74a3cff6188427326b8c96f74354cb3ecaa611b12cded565e59fe1f8f400097e93ea85951b5b4e9009eea7db937e4349c4e5e00c4456c6c5f4e57411baf4e46e700ac400257765f48dab03e439f76c1499b5108047c830109dce7f740d1393787e29d3716d3c47e755cb828e7d440a971975197ebdb3f9b737ba11f7fd0386a959249017de7234d5e5a9b473bb9583a3742c774ee552a12a1f36eb3f26c885bed22e91c74cf32a8dd3edb08b674bf386ef427727912d57c5fafaa1cfeb740cd52b9dee995e3d0161cd9213f38fd681d538ab8bf97b745f54980030ef8b72696d4e27473fb0f1acd5d0aae0297211680ea0fc59d7b6d51c63292585a1d553d0c8954b42a4bd6fcd3a49575bf5c88953f1f4ea7fe0ed7a579d1697e645e2a61c69d1a56bc605bb04060a2778d509a8aadbf35d94697ccee9d3543dd01281a031f2a0eb3a9eb13ae56ff44fa0aed4f3488747d6af820f3989b7133f449ea56d3a7f731e791b7ed2a5db939bb75352de7daec5066fd57557165adffa631cd3f967c3c7cfc11cc1f14fa23defec3eb0239b45ed601a3a8078ccfc7f8380902a859ee9ce2db795efaca0a01dc0879d506ac97d10704d7757b3ccf3b37c339b42db23782278023e4c2e77d74246c9e544149a55c0c920ebf2986b4c5b4b3572f748c4b15c7f863999bc5132adad09761eb76505019769fb55422f603184e24c0d4f3761987b5c50feafcce53302a3a415e20f56a054803e553bacd242a5e1364aa3b2d7cb3bc1e1b86a47431cbd39695b67f554c4645b7236904094c11aa1b40326ba91b8bf4873e9a4de04e2bf4625972: +45438f91465d74a2825b0f66a35bd7c8d005865479b3dc10a9b56f297d31b926f092b5880330871e5aafdd3ceb3850ee7e0941a2a1dc89f4fb4771d75a22f6f2:f092b5880330871e5aafdd3ceb3850ee7e0941a2a1dc89f4fb4771d75a22f6f2:3071d4b720df1093659967cd4eefef2ef9678475f7dec58fecec1d928deaf802457a1934e60455f496cf4251820ed60a3d8133b624d33af26a262784b5a2fba73cca2aa5e519e1f539584780649864ba5fbc1f011dddac381f8d48d0d60ce8231701173c9d2a307a76302ebc69dcbc930d28431475b516f98f778ed2e1fff272909a272cc3fbb6b31c8041a37cb777e062e49649afad12c1b5f7fcb8065a99e7423362ad16906031265db7e8b89751f8a4a407f2502650fed753e42c8c911e50b94b3800695b0eba7dff06b7a710117e4920d4b1c605a3ebf32e06966716eda14b3042998a3c7a5e9f83542d7dde65e528bed6101deb331deb94cdd46044bef88c097bafd40d6921a7c484c8f96684dc371671d94eee7cbe5d587715314cff0d1877272d8190a90e18bfb321d52bf74705137b2abf9165731767a13adc9c85e0397b47aef96badb2ca7fcb8293b01fd1de316ee1e65f356b9d6e8ea1fdd837bd96081149ea2dcd73c4881f32b7deebc3715e2d7cdb643e0d98f4e846508b04b32439ff14b1164f46846df9afae44464cf550104cd3aab3817540470aaa2ab9559a68b7ff6b1b9c0ce9f5869cbdcdd617090942e353b4c77f09395896becddff1ab7f07586a514d81fb096361557566870f1691983485a80c3413da98b8d19c78e6379f943e5bd5a5697aa33c5e6bfcfb7b8df1e1574ee416fab3c8a7d088b3a057cf865321b74e6103526dd9ad15ca5ad3c0f69718e27081d4b34a7c6d1aab6b96c0a754b989b4940638c9ede3d17bd49f65bf783dc85f1c4b144876cdbdb2282a9564aa81b57092080d6448fb6580ecf09f82a755010d55d4a5e4f305e259dbe99508b479250d80ec17c8760a93e05a29571f6856073022c8706913c46a2efd2e9caae4ffa1b4222e3d70e979e81a71951d7cb830bcbcf901af244f64e4ad9f52fa3b62031e3516da50bc2bce78eb9d61bfedd9b3f57e89355f177db6162bf61da0e454c34288b967c3fb4c341b32d4d13a319869b8e36046f9e338b5f36a1fc1a7eda7d7b0d438e0a75d84bbe4d68c879ada80dde23f7155b532cccf7a63f1bedf84f82f440c9ec3cb0e45f32c92f76438f5b4b910441e6738af3f5d2050d579ee96b88f3b00810ab126ff3a8fefd971044324dd4eb3447dac5b77809cda8c71682549d7cf2dcee340edcf9494aca42901e2c11ed97790af48bcea29521ef0e3d03cdadecdc894dd0756:d9287b7fec017f2ea40a14a1f62dca78b02a3d6632df7c60ebd90fc5e492c5c62c43166bf85658fb30a08b57a5813121b80397571a312b6dd11b6539205416023071d4b720df1093659967cd4eefef2ef9678475f7dec58fecec1d928deaf802457a1934e60455f496cf4251820ed60a3d8133b624d33af26a262784b5a2fba73cca2aa5e519e1f539584780649864ba5fbc1f011dddac381f8d48d0d60ce8231701173c9d2a307a76302ebc69dcbc930d28431475b516f98f778ed2e1fff272909a272cc3fbb6b31c8041a37cb777e062e49649afad12c1b5f7fcb8065a99e7423362ad16906031265db7e8b89751f8a4a407f2502650fed753e42c8c911e50b94b3800695b0eba7dff06b7a710117e4920d4b1c605a3ebf32e06966716eda14b3042998a3c7a5e9f83542d7dde65e528bed6101deb331deb94cdd46044bef88c097bafd40d6921a7c484c8f96684dc371671d94eee7cbe5d587715314cff0d1877272d8190a90e18bfb321d52bf74705137b2abf9165731767a13adc9c85e0397b47aef96badb2ca7fcb8293b01fd1de316ee1e65f356b9d6e8ea1fdd837bd96081149ea2dcd73c4881f32b7deebc3715e2d7cdb643e0d98f4e846508b04b32439ff14b1164f46846df9afae44464cf550104cd3aab3817540470aaa2ab9559a68b7ff6b1b9c0ce9f5869cbdcdd617090942e353b4c77f09395896becddff1ab7f07586a514d81fb096361557566870f1691983485a80c3413da98b8d19c78e6379f943e5bd5a5697aa33c5e6bfcfb7b8df1e1574ee416fab3c8a7d088b3a057cf865321b74e6103526dd9ad15ca5ad3c0f69718e27081d4b34a7c6d1aab6b96c0a754b989b4940638c9ede3d17bd49f65bf783dc85f1c4b144876cdbdb2282a9564aa81b57092080d6448fb6580ecf09f82a755010d55d4a5e4f305e259dbe99508b479250d80ec17c8760a93e05a29571f6856073022c8706913c46a2efd2e9caae4ffa1b4222e3d70e979e81a71951d7cb830bcbcf901af244f64e4ad9f52fa3b62031e3516da50bc2bce78eb9d61bfedd9b3f57e89355f177db6162bf61da0e454c34288b967c3fb4c341b32d4d13a319869b8e36046f9e338b5f36a1fc1a7eda7d7b0d438e0a75d84bbe4d68c879ada80dde23f7155b532cccf7a63f1bedf84f82f440c9ec3cb0e45f32c92f76438f5b4b910441e6738af3f5d2050d579ee96b88f3b00810ab126ff3a8fefd971044324dd4eb3447dac5b77809cda8c71682549d7cf2dcee340edcf9494aca42901e2c11ed97790af48bcea29521ef0e3d03cdadecdc894dd0756: +72cfcef4c9d6a1986d190311840e55cbafacc8a6eb5ecc72934fda535bdcffb2a94464d8cc8f3e43393947649f91c2752327e40daca11a9970c5181eda37d606:a94464d8cc8f3e43393947649f91c2752327e40daca11a9970c5181eda37d606:66a6cbe88a8ab9a33847797fc480b244e8a2b8ec79e80bc2637753deb36fa3014f843e22a47db0a31778385ec1f455672e0dff6ca21ca4cfd2b989471b7ffc307828138b0ad4e647c2d13cef724469054abd3740245aea4b789e244e95cf9ecfd08a0d13c7ced393332727a7f3d8fbdabd939de28caa41cc96c7081198e22653d94e024a61f5f3dc5aa37fa9adddc96cf169d35062a0a29ba45a539c87a68a3a0304361309d213e614ee8373dafba2a7d6ed7d2ad37704c0946e4d093e2d94d061364cc1231063729103a77ccb501891bbc3185457bbd2869eb63dc60f196f10a38b7b36cb3f643d35ddbf438a44bf0c8f570fad41bdde267f0ffcf1f2f927d626d1b0d980a0ce223f2f0054845afe41d39de5a457219f276c67e69be2d5c9e070131639561c26751fb06435e0e42e2508c5f49cd12b517c9833ff97f5e51e1dceafa9426d3dc52fd1379c64ccaabb26db1af6ded7153628842f0cbdbbbd6aa0cfa5407f409496c06532dbeac94dab9baba0b3c988fa03d36f911d80e49b370b6837037ff249e76d692cd17737e0d07965d33f17042bbcd1e990e040f71936f6fca2542ae33748367787c01bdea75c9a0e66150281c468fe5c73af9e5bec372d5020c3d37fa1035a67e224d095f066a51fe1f681c3073939272f6af7750ed8d18349178ab4a2eeb4e9ca82bb67296e9890f316c9d9495953d68436eb1c1a2fb6a1cca45a8e88a09bdd65a5558025618b36d7f3cb389d2e2ab1ed233228ec92a327978c0adceddb6c9632d3abd7971621713754758e21013a0c3d009b6e3193cc152c57ef73107bd4357d528be40873027bf1840f685536080f12c5ffa93ca629736780e015e86d1909f0d8f372010c9cb72c0989845fc88315e6b9370dc92d3683ef44d3f75fc96c4b0e89e13d682d1988b685713eada842be9d2bbe2a76bba15d38cbafb65c40c2159b0ceeb0d769b9be355540734ff37736c0f0facb95159309365b9646bc4b344fb19a5c1639a88e87317bfb3b5e7b5130fa7d5643ed4da06430c8a0c1858ccf2f9a6e3d62012253f0122dbab4a35475a6f65589b2b095992826e4f1b58fa050b8f95c4feba3fbaadd2c2244ad4abd410139adf4c153cb5e69337af176a7837eeaea99bdcd59385afded34ffba8063a35f4f558e4eeb48f1487b56b1f8d1f73067621cb548c808753e3526a2f2aabde126bea521cf673deafa792ca5bd2212795bd66b86:db7270acce78d7fb09080a327941bce7eb145b9e3661866a8683f9a1a3de97fb02b025db9ec76ff32560fe638827742ea2f4ebef6b7cce44f9aaee434fd7c10866a6cbe88a8ab9a33847797fc480b244e8a2b8ec79e80bc2637753deb36fa3014f843e22a47db0a31778385ec1f455672e0dff6ca21ca4cfd2b989471b7ffc307828138b0ad4e647c2d13cef724469054abd3740245aea4b789e244e95cf9ecfd08a0d13c7ced393332727a7f3d8fbdabd939de28caa41cc96c7081198e22653d94e024a61f5f3dc5aa37fa9adddc96cf169d35062a0a29ba45a539c87a68a3a0304361309d213e614ee8373dafba2a7d6ed7d2ad37704c0946e4d093e2d94d061364cc1231063729103a77ccb501891bbc3185457bbd2869eb63dc60f196f10a38b7b36cb3f643d35ddbf438a44bf0c8f570fad41bdde267f0ffcf1f2f927d626d1b0d980a0ce223f2f0054845afe41d39de5a457219f276c67e69be2d5c9e070131639561c26751fb06435e0e42e2508c5f49cd12b517c9833ff97f5e51e1dceafa9426d3dc52fd1379c64ccaabb26db1af6ded7153628842f0cbdbbbd6aa0cfa5407f409496c06532dbeac94dab9baba0b3c988fa03d36f911d80e49b370b6837037ff249e76d692cd17737e0d07965d33f17042bbcd1e990e040f71936f6fca2542ae33748367787c01bdea75c9a0e66150281c468fe5c73af9e5bec372d5020c3d37fa1035a67e224d095f066a51fe1f681c3073939272f6af7750ed8d18349178ab4a2eeb4e9ca82bb67296e9890f316c9d9495953d68436eb1c1a2fb6a1cca45a8e88a09bdd65a5558025618b36d7f3cb389d2e2ab1ed233228ec92a327978c0adceddb6c9632d3abd7971621713754758e21013a0c3d009b6e3193cc152c57ef73107bd4357d528be40873027bf1840f685536080f12c5ffa93ca629736780e015e86d1909f0d8f372010c9cb72c0989845fc88315e6b9370dc92d3683ef44d3f75fc96c4b0e89e13d682d1988b685713eada842be9d2bbe2a76bba15d38cbafb65c40c2159b0ceeb0d769b9be355540734ff37736c0f0facb95159309365b9646bc4b344fb19a5c1639a88e87317bfb3b5e7b5130fa7d5643ed4da06430c8a0c1858ccf2f9a6e3d62012253f0122dbab4a35475a6f65589b2b095992826e4f1b58fa050b8f95c4feba3fbaadd2c2244ad4abd410139adf4c153cb5e69337af176a7837eeaea99bdcd59385afded34ffba8063a35f4f558e4eeb48f1487b56b1f8d1f73067621cb548c808753e3526a2f2aabde126bea521cf673deafa792ca5bd2212795bd66b86: +a6337e4d3b1a49b126316778c613516c03ac88c96d92ff5cc7e0c8527cce1a62f5eac4fe0ea1a5f236b49da33a24e2f3a83d4b260c54d3416c644e05c838bf51:f5eac4fe0ea1a5f236b49da33a24e2f3a83d4b260c54d3416c644e05c838bf51:e33430c38c4a40b3c66e20cf3b70e9fea8cc50761f2afe249ec059c07bc3b37e5b94f4a43e310099b19a85f59dff73a7e495c4df31f74780cdef7bd6e47c394c1891ea3052e3ccf5d84bae082d24ba7178ac65d229ad18a84940f6b4dbc596ee63c181b57b5b49698979c18632fa821ca61e35a0d0351fe13d69e06ddcc8d666dca24502177f344e2f440575d39ebfe5e7f10653b65bef291dc813a0434c975de164c1a76bf6fcef98f23181c009b91830b618e4874847d2e21bbdb93f20cd8b1f4baadf99428a22674386a668152b4b9039ff06abcfe334a062f794056172ecbc0794df98271b9acfe4b7da553a87634237630009a05b257c184cbe23d9cd5a038658010f574899f3b2d154d185ee67230913650c3a05b54a2edc243a4287398e376928ea9c6b2cbaf371252540e2b8043fcf556813196ae572c27cfb5a46abb9729af2dcfc29e033dd11f33e86cc6ac3bce6f3f9577d36781a69ed7eaf8c8263a0f18eba0fe8a481f3e15a55599434195f7cb057dd364eaa07dd0dfd266b807f53a2070fd791e872422fd907134f4a8a78a876bdcb031ac860dfe0bb57e105db8287b31a604eb71269be5ba229985ceabc2bdf165ac741650b1f013a66c9bd243d03a8b1c5081381cb92e23f9057771fc07ca32dff1db94f5adfd2f4ff9af31d250dd4f86b22592f60a74575156213f10846c746a920fe39851b32fe4c8b8758765bc5b8b9d5b99263df36f97888053fd10f1d68f577aed559bcfde744bc6511076cafd68944a0ed10552d11344bc7e4d9ef936dacced527433132959b1c7324ad1c4cbc3a1a736b1f02aae8e0611ae23fdd474f5b8ee7056fcb5af6133ecc084bb9f1f50cbdac66244437b4348f4edfe237fc3c3829ab94eb4f14cab1ccd6caee36fadc20a310cf0690622cdca848aed03ff403a6633f4f657994b780dd6048149c3bfbc17889e37d90b1e5420eb3d4596b91ba11bc0229c65d05b93cd7e0454d1f3c6e1e8071983792c4d4368d0778aef4e123335fd2962c657bd0513571a5fce211de62874f27ca10dc15ba2d445f1cf4be5f833cf0b564c022576b98c0a24349b67085f92202675d7dac48b95e3bfd6555a9ecb7c72f08bfec0d220222492fdc9636f036ec4508a365b7b70979f9eb4a7263a8bacb1c1d0155738646cdd46ab9234a170311500d0bae6e55a863bdaa56f51645ad85297a7381f8d20cf96c474d1bb81fce132b14555d1a:781376c9512fa33c457047a1f4f0da3176e60ee47782869b7e9fa5841d964f3c1ad66b70c114b1771c324c83ff6cd997aefccdc59c114db9f2f3ca7d84a7b60fe33430c38c4a40b3c66e20cf3b70e9fea8cc50761f2afe249ec059c07bc3b37e5b94f4a43e310099b19a85f59dff73a7e495c4df31f74780cdef7bd6e47c394c1891ea3052e3ccf5d84bae082d24ba7178ac65d229ad18a84940f6b4dbc596ee63c181b57b5b49698979c18632fa821ca61e35a0d0351fe13d69e06ddcc8d666dca24502177f344e2f440575d39ebfe5e7f10653b65bef291dc813a0434c975de164c1a76bf6fcef98f23181c009b91830b618e4874847d2e21bbdb93f20cd8b1f4baadf99428a22674386a668152b4b9039ff06abcfe334a062f794056172ecbc0794df98271b9acfe4b7da553a87634237630009a05b257c184cbe23d9cd5a038658010f574899f3b2d154d185ee67230913650c3a05b54a2edc243a4287398e376928ea9c6b2cbaf371252540e2b8043fcf556813196ae572c27cfb5a46abb9729af2dcfc29e033dd11f33e86cc6ac3bce6f3f9577d36781a69ed7eaf8c8263a0f18eba0fe8a481f3e15a55599434195f7cb057dd364eaa07dd0dfd266b807f53a2070fd791e872422fd907134f4a8a78a876bdcb031ac860dfe0bb57e105db8287b31a604eb71269be5ba229985ceabc2bdf165ac741650b1f013a66c9bd243d03a8b1c5081381cb92e23f9057771fc07ca32dff1db94f5adfd2f4ff9af31d250dd4f86b22592f60a74575156213f10846c746a920fe39851b32fe4c8b8758765bc5b8b9d5b99263df36f97888053fd10f1d68f577aed559bcfde744bc6511076cafd68944a0ed10552d11344bc7e4d9ef936dacced527433132959b1c7324ad1c4cbc3a1a736b1f02aae8e0611ae23fdd474f5b8ee7056fcb5af6133ecc084bb9f1f50cbdac66244437b4348f4edfe237fc3c3829ab94eb4f14cab1ccd6caee36fadc20a310cf0690622cdca848aed03ff403a6633f4f657994b780dd6048149c3bfbc17889e37d90b1e5420eb3d4596b91ba11bc0229c65d05b93cd7e0454d1f3c6e1e8071983792c4d4368d0778aef4e123335fd2962c657bd0513571a5fce211de62874f27ca10dc15ba2d445f1cf4be5f833cf0b564c022576b98c0a24349b67085f92202675d7dac48b95e3bfd6555a9ecb7c72f08bfec0d220222492fdc9636f036ec4508a365b7b70979f9eb4a7263a8bacb1c1d0155738646cdd46ab9234a170311500d0bae6e55a863bdaa56f51645ad85297a7381f8d20cf96c474d1bb81fce132b14555d1a: +107da98d0ee8e7c00f6d41ec265944ce67ef8c8ffb51f4f11f4e5f1a27fbe8053bec34b161b1bcff009f8cfc50d84ceb6a2d5b203b5238a8aad8a83618b442e7:3bec34b161b1bcff009f8cfc50d84ceb6a2d5b203b5238a8aad8a83618b442e7:1a7b7f3e1c7c41492a7ce799efdb2d9dc2f2489c84ae28bb7d084f32eca8fbb066885ac6f2ef7449e71226a82e9f153772a993eb6b6bca6491d26aca5dee98b77a1ddc59922b3145c447de737fafacba5a75f2a80137b5594697220d19617674a69113fdf77c343af2b7e3861b5b7822f58d60089c3ca54c749d27f88379c067598f063939ba8631d1f52dc9ab455045fb360cc2a5b6b0127facfcf5b1b4c33e3f194fc924b854168cb1169ab10997b438b71c80878347be887af44810134b514c806908201a3d3e6d0c56120c4314874dc2944d8444f01bafa34aa62ecef0981545e5d02f4016c0b164fc05ae18f535c31bf20b86f31f7a794aba148984c3ff433dc222c443b5d26c1f66e6c5f19d19cd6eadd4dc94101b2f52b58c9d4590cb10dbc5d6eacd11d42ed09f15bde44ee9271def292f731bf3b4ac6cd127e4884c2cb30b285fc9247638a299e416520624d1ec8d0df2498939c719a9e7bd29a3c5c32a3e8241368d6e4f90fea29dc3a3f147ea9f76c5780e73143f55d3dec7b66341d3f3eac1d98f8e7d4e877509b4438c3a52466d242a10b4c27c4a0db9232dad011414ebfbd57906f1a410207b526b0d1f1b6986b3ebd7550a2b3c15fc2409c7626e0dd330ef6722e3ba48b1d9205652ac194c21473ce258559db511efad3e5d55f2a796d65a6ab97d8631062a593a13aaa095dbc93e6217ced619cb16a57e744355a16b15e77d4979119299bb043e48fa3e615460e164882984a223d418ca95340c5bfcda673fcd13b29f2c47d2f97e3e8c613b6c58df0e62cf23061d6f545b755033fd3dc1405e5fef35a13e015f98b1cc42f71b99681f9681258229a4473d86eabb0c17927941e50c08f34a76b43bcc6d042e5632ef9ccc91b6e6950f5d30f670fb3902c3d409315a40b0821ce8a99a97feca5478bfd782e78767b311f374163f5896b0beb95838e645878c64990385123b61575dd842dc76354bac9c6d5acd9935b609bcccb8463d39225da1afb8911d36e609892dd1723852ab9f82758f3f1e4d28dcf02cb06eed26844aae6882ed44bce44abcd1dfba633418c9f155879c97ab27f8ae238330392be5491a078662daaa02a3d5458b77c549c49be201245e7aaec0d94e5437beca6e5ab046d694e96bf51e04fb44379b2b9b801675fe1477f3e089874a601171d8b68f0202014601a53f812f53e581c3b96312b36b9ee04fff11d9eab4e45148dcc8f0fab1:53252b923ad19cc39784d3a9ae59d62a6300dcc50ac8fd0713cb58844501d8d3805afa0fda64c73ea0f60e6a8b3445bfffe6ca6bfdc87e128baf99bf6268fc091a7b7f3e1c7c41492a7ce799efdb2d9dc2f2489c84ae28bb7d084f32eca8fbb066885ac6f2ef7449e71226a82e9f153772a993eb6b6bca6491d26aca5dee98b77a1ddc59922b3145c447de737fafacba5a75f2a80137b5594697220d19617674a69113fdf77c343af2b7e3861b5b7822f58d60089c3ca54c749d27f88379c067598f063939ba8631d1f52dc9ab455045fb360cc2a5b6b0127facfcf5b1b4c33e3f194fc924b854168cb1169ab10997b438b71c80878347be887af44810134b514c806908201a3d3e6d0c56120c4314874dc2944d8444f01bafa34aa62ecef0981545e5d02f4016c0b164fc05ae18f535c31bf20b86f31f7a794aba148984c3ff433dc222c443b5d26c1f66e6c5f19d19cd6eadd4dc94101b2f52b58c9d4590cb10dbc5d6eacd11d42ed09f15bde44ee9271def292f731bf3b4ac6cd127e4884c2cb30b285fc9247638a299e416520624d1ec8d0df2498939c719a9e7bd29a3c5c32a3e8241368d6e4f90fea29dc3a3f147ea9f76c5780e73143f55d3dec7b66341d3f3eac1d98f8e7d4e877509b4438c3a52466d242a10b4c27c4a0db9232dad011414ebfbd57906f1a410207b526b0d1f1b6986b3ebd7550a2b3c15fc2409c7626e0dd330ef6722e3ba48b1d9205652ac194c21473ce258559db511efad3e5d55f2a796d65a6ab97d8631062a593a13aaa095dbc93e6217ced619cb16a57e744355a16b15e77d4979119299bb043e48fa3e615460e164882984a223d418ca95340c5bfcda673fcd13b29f2c47d2f97e3e8c613b6c58df0e62cf23061d6f545b755033fd3dc1405e5fef35a13e015f98b1cc42f71b99681f9681258229a4473d86eabb0c17927941e50c08f34a76b43bcc6d042e5632ef9ccc91b6e6950f5d30f670fb3902c3d409315a40b0821ce8a99a97feca5478bfd782e78767b311f374163f5896b0beb95838e645878c64990385123b61575dd842dc76354bac9c6d5acd9935b609bcccb8463d39225da1afb8911d36e609892dd1723852ab9f82758f3f1e4d28dcf02cb06eed26844aae6882ed44bce44abcd1dfba633418c9f155879c97ab27f8ae238330392be5491a078662daaa02a3d5458b77c549c49be201245e7aaec0d94e5437beca6e5ab046d694e96bf51e04fb44379b2b9b801675fe1477f3e089874a601171d8b68f0202014601a53f812f53e581c3b96312b36b9ee04fff11d9eab4e45148dcc8f0fab1: +8bc229fc234653b13c924710cb468b8fa9b280e2adb49cb4b36bf59d6fa4a63946146975df6704cbf45320a5e6cb6de813469f3131e61d447bbca1a477a0c557:46146975df6704cbf45320a5e6cb6de813469f3131e61d447bbca1a477a0c557:bae2dc7f94ab5ccdcaa8cf49edbef0f6d7aeb1fa8907800533af4492611194e56cef37b1f033303738ae2c3bc4588f5cb3d55f345b9a407e787742a06af0b6ee20dee3dfe9c91d762a3ebd19aed07907bbb91cd776326540ded9f7ff7dda76615f978e9490f406ed2d9116e2093fa785e971b5062d31cb40fff9e3c551a73b20245d46df4d7fd1303a28180172d9a2bf5593c47917b58690917c1fb0e1e2994d1fa97735ae378de6eafd5c1a25abafa3cfd2df7aeabd6e68fc44edf82fc83694e5d841a15b14568b6110be644bf22b71fc47d7f07e1666957d0f87da17f13fcd63c1c2966f687d25dcbd9963f01eff132d5f2b86677816588c123e9457befcced2d3cd1d1bebe8dd8fbb1587e553cbcc4c8762064cd32ef7a1702410f77f15240d7e2bb582c678c0da88ef4522830b143660ac9c434d95772e6eeeed6014ae16824ccdc4df2df64aeb6980b51d118985dcbbd1961f315e6a9433f0b96b1e6351257ead83e05b4cc89c924bf83558ba7d2e7ca37c03179a8f85b831e7217bf4c553838761d32602853b81593b0ebf8e4b9ffaf0ec405b2a83af7de5554daad28b582ee08bd84b375550cae08ae4a5bda71581fc3b7b54498c4e1afb966b4af1d9c843a6b25b34e04cfd9bd2374244f1fe20ec62be3ccfab4edef79ed64e6b71aa9228127c6359ea1c4a8087890896ffa46e0092dec7efbc960a17b770916f954070132e26d98d9774a2acdf809d586df0252f67cfe8d985a3e248db0f90731ace7abd999c746b69648d5c3b4bd61137e08fcc8b2efc5676bcd856a13b362151474c4a1efdedc592cf3ead1ababcd48ee204d27726ad1bda4fe4b09ab51089d016de6ba259ea81807faf211c87e4c9efbf6a4c753e08f780ed55338c0fde14fb99b30722b5594b3abe02047f466242421fb81176c9c4f0fd2b5e7c5a0f65a0c59aa8c3a986087de7ba40baca77bd36ac21ce34e9fe97facc4e298330eece1c8ec623e66a4b0f2342d2c5a02c5f5abddc5ff1f1f2d03c1d4ee9b4b342ed3b1cc26561f3217bf8500e08f027571c53c9232605a53f2bda024e39929163a8e00791ac0656bb0783825e7105ffa9d90969dc094af46f702e85cc11e442b3d5534c1d3275207d6d29a942c358ed5fa07557c3c014cf541f9aaeea6025b41ecdd848512ba25e721e43d329185f8f94892e9e2d5e7cbb99e7ad25f69e5bef732cfceb078611553cc78377375e74e66f1b9d8d20:d243b87d1397d594139d83c39acf8501d073bd4be718b4c206980729e720a4c5b0ea91a28ea12604a987e69591c543049f2973bb91c170213c32a64a0fac8204bae2dc7f94ab5ccdcaa8cf49edbef0f6d7aeb1fa8907800533af4492611194e56cef37b1f033303738ae2c3bc4588f5cb3d55f345b9a407e787742a06af0b6ee20dee3dfe9c91d762a3ebd19aed07907bbb91cd776326540ded9f7ff7dda76615f978e9490f406ed2d9116e2093fa785e971b5062d31cb40fff9e3c551a73b20245d46df4d7fd1303a28180172d9a2bf5593c47917b58690917c1fb0e1e2994d1fa97735ae378de6eafd5c1a25abafa3cfd2df7aeabd6e68fc44edf82fc83694e5d841a15b14568b6110be644bf22b71fc47d7f07e1666957d0f87da17f13fcd63c1c2966f687d25dcbd9963f01eff132d5f2b86677816588c123e9457befcced2d3cd1d1bebe8dd8fbb1587e553cbcc4c8762064cd32ef7a1702410f77f15240d7e2bb582c678c0da88ef4522830b143660ac9c434d95772e6eeeed6014ae16824ccdc4df2df64aeb6980b51d118985dcbbd1961f315e6a9433f0b96b1e6351257ead83e05b4cc89c924bf83558ba7d2e7ca37c03179a8f85b831e7217bf4c553838761d32602853b81593b0ebf8e4b9ffaf0ec405b2a83af7de5554daad28b582ee08bd84b375550cae08ae4a5bda71581fc3b7b54498c4e1afb966b4af1d9c843a6b25b34e04cfd9bd2374244f1fe20ec62be3ccfab4edef79ed64e6b71aa9228127c6359ea1c4a8087890896ffa46e0092dec7efbc960a17b770916f954070132e26d98d9774a2acdf809d586df0252f67cfe8d985a3e248db0f90731ace7abd999c746b69648d5c3b4bd61137e08fcc8b2efc5676bcd856a13b362151474c4a1efdedc592cf3ead1ababcd48ee204d27726ad1bda4fe4b09ab51089d016de6ba259ea81807faf211c87e4c9efbf6a4c753e08f780ed55338c0fde14fb99b30722b5594b3abe02047f466242421fb81176c9c4f0fd2b5e7c5a0f65a0c59aa8c3a986087de7ba40baca77bd36ac21ce34e9fe97facc4e298330eece1c8ec623e66a4b0f2342d2c5a02c5f5abddc5ff1f1f2d03c1d4ee9b4b342ed3b1cc26561f3217bf8500e08f027571c53c9232605a53f2bda024e39929163a8e00791ac0656bb0783825e7105ffa9d90969dc094af46f702e85cc11e442b3d5534c1d3275207d6d29a942c358ed5fa07557c3c014cf541f9aaeea6025b41ecdd848512ba25e721e43d329185f8f94892e9e2d5e7cbb99e7ad25f69e5bef732cfceb078611553cc78377375e74e66f1b9d8d20: +3edb50ff074ef9717f4fb0b6ce252bf4bd049c9083775f529eaf51e975cb32454bc21fe03e679abbfcd8c5ea2bcc4d838a787d4840c3bc39de4b04c417c768a5:4bc21fe03e679abbfcd8c5ea2bcc4d838a787d4840c3bc39de4b04c417c768a5:975ece4e81f0015f5ac3044609d0ac3a8df9145b50c42889dd312f563cf6126e36fffaf21eb6b84fbda15aa85c66145f7541e5b41a8e81700be356224fc109327a6919665673534f5c8a4a001750b199dbfd630691af552d4d26a9d9afb33a16af391154124b53426c9f695057b1814fd6d310298af6c830686a4a007a14e0057b72fbad5b803ad353d1c3fdb890a9c81808e89f229187bcb44fee16a4ebcad5eba459b028272a562c05079fa7ae3ecae804a9e8c4f3f315813c5ee0841bbccfe4a95623b517a4b42b2c6d97a3bf26acdbe2e979633f02aac466526a3ebb14da19bc95f2c3fdf6bdb08be8bde97a864c907e918c679ab726f80177145840216b9dc3f981ef17874f08b2fc6611a6346c3da6a55ecfa753c9919f4f19e3c79093bfd78f861598e4666e1cab688e4604d46c9c582eadb92c988f478d160f5a15182b3340201797d0b955282e4a217b50b14b10c9f49067ea3e84e5274dcaec74474c5707c28bba0db8cde3e838d7313c171b85ff2b9a3d2b167e9061f84df3b13bdd08b2d501e53792d68054d048abfe3bce98d978256f2fd2c6c4e76f39688cccf0fe149af9d347e7b040ef241dd5a53eaa5eab35a18c68c754a06b03399bbe56a25268c829a5ba82b28192041d3bd244eb08bf78e76def87cd09f32beac9bb639823b36967a574d8960d1bd03435679d93eddc558063c540b9c2f609fed2e2e3576d19e6209eab466c206791c3aa199623fbae7d3497e80fdd3fcbaf5b89110ed72244234be85cca4b27a09bb70a26ece4eb8dd970a26e5b04361fa50e90380ed65f414c1be9f5064f71429116267edd6976422ad92deb2b804a92e81c9f6522a0f3b5d8ad36b4f87db516a22873e6f27284f2ca360a2f40ff3d8e23dec8ef8a17a43acbb61271a727cb8690d29bb82016736b31026201dd3d388d2c643a73cfbd0a94e20551fb5f8e1ffc39741272aa2308dc8d2133a3fa9cf109796d69d2cc8addc44ae2527781ee993af2a637a872f02aff474a7073f29d9c89507701fecbbfd5101353537eba17c29669dac0427e38e22dfaac91fc20d9e3fee791f462a863bb1908fb1e4204b68880314ddacaaa35a17af5f57a399f1931e78f5a37454fd38c57a68e8d367848a97345189c70077fd1aa0754e703e352618063b9e3faf3b14b5f0b27113633c5d17363741e96a67e816401e8098c17bffe9c6f3587646f40e9fdb6819fd22a743a7a6e10feba11:deb3d9fc7b2d86ab4b926f99527970abb51838bcc2919e94cda3371fd0e7693fe37e0c40e1233b09ffa903a034dde287c0237dc594f53abc87844869dce92002975ece4e81f0015f5ac3044609d0ac3a8df9145b50c42889dd312f563cf6126e36fffaf21eb6b84fbda15aa85c66145f7541e5b41a8e81700be356224fc109327a6919665673534f5c8a4a001750b199dbfd630691af552d4d26a9d9afb33a16af391154124b53426c9f695057b1814fd6d310298af6c830686a4a007a14e0057b72fbad5b803ad353d1c3fdb890a9c81808e89f229187bcb44fee16a4ebcad5eba459b028272a562c05079fa7ae3ecae804a9e8c4f3f315813c5ee0841bbccfe4a95623b517a4b42b2c6d97a3bf26acdbe2e979633f02aac466526a3ebb14da19bc95f2c3fdf6bdb08be8bde97a864c907e918c679ab726f80177145840216b9dc3f981ef17874f08b2fc6611a6346c3da6a55ecfa753c9919f4f19e3c79093bfd78f861598e4666e1cab688e4604d46c9c582eadb92c988f478d160f5a15182b3340201797d0b955282e4a217b50b14b10c9f49067ea3e84e5274dcaec74474c5707c28bba0db8cde3e838d7313c171b85ff2b9a3d2b167e9061f84df3b13bdd08b2d501e53792d68054d048abfe3bce98d978256f2fd2c6c4e76f39688cccf0fe149af9d347e7b040ef241dd5a53eaa5eab35a18c68c754a06b03399bbe56a25268c829a5ba82b28192041d3bd244eb08bf78e76def87cd09f32beac9bb639823b36967a574d8960d1bd03435679d93eddc558063c540b9c2f609fed2e2e3576d19e6209eab466c206791c3aa199623fbae7d3497e80fdd3fcbaf5b89110ed72244234be85cca4b27a09bb70a26ece4eb8dd970a26e5b04361fa50e90380ed65f414c1be9f5064f71429116267edd6976422ad92deb2b804a92e81c9f6522a0f3b5d8ad36b4f87db516a22873e6f27284f2ca360a2f40ff3d8e23dec8ef8a17a43acbb61271a727cb8690d29bb82016736b31026201dd3d388d2c643a73cfbd0a94e20551fb5f8e1ffc39741272aa2308dc8d2133a3fa9cf109796d69d2cc8addc44ae2527781ee993af2a637a872f02aff474a7073f29d9c89507701fecbbfd5101353537eba17c29669dac0427e38e22dfaac91fc20d9e3fee791f462a863bb1908fb1e4204b68880314ddacaaa35a17af5f57a399f1931e78f5a37454fd38c57a68e8d367848a97345189c70077fd1aa0754e703e352618063b9e3faf3b14b5f0b27113633c5d17363741e96a67e816401e8098c17bffe9c6f3587646f40e9fdb6819fd22a743a7a6e10feba11: +cda4ba93940aa0c0c3150b3929b95ee7769ce43fd98ecaff9c4a509e736d5c8ef4c7a25f1a743daf41417e47e027537f24f481bd1a75e6b1d33ec4c82c55a2d3:f4c7a25f1a743daf41417e47e027537f24f481bd1a75e6b1d33ec4c82c55a2d3:3a1d668c6688414896a7697f3c2e431098edfc457e04d2da869568ad5b3310e59e4c727c903cbf1817408802319a8c231b58023dfae494c013af0fdb78c91d5b457f8c47a3dc31d8c8594aa08f146203fa2c28b3dd796a11a97adede6a7a709b5a1918ef1bea83533c783473703356f5beea7fd18ac44ec6890495ed170d03f15b418608a7d9efd52fa10918638051c448d98d5724f567c8c67fd5b6ec8c3d636008b9bae5e8b1e984f8ffb8b64beebd6345a105c1c1083132fd4508d6ac0d4e9145501210e517d9b22478e215b602599f803762dcd5a409b3460e7f340f47ef77281ad2383de08c5b809538aaec922bfca0d6752f147972646d0a8d8340772c871d3b34abc06037de3ab4e37129865d5ba70b6f3cc9a059efb7dddc3882f4fcfe13f448c9bc664888589603ba98683a93b4b3b1014992a55c8e4ea1baf9cc00d1badff5fd7f5da5e307fbd1b4c984e0fa0edec5d30bfef5f477301263b5d752001b85dd52df3b4a7ac23b930a91c0a45765a66488d8eb5901857060067b82378188549288ddc61831e5b6841b344cae2250042219cfb4ace023e691f9e48d006e9a07c67d2468f93593b4afc161c0768b6ceb744c24c923da34af3d5ed577cc7f85d491560f4c0bcbcd1d5e3421bd1ccfafb373d651bd61ed71c09e99f612001704d0c630d8547bd970b66e7f5ce7a014e0ff5a337dc5c56a99f131b9129140eeea39397c48caa9a8086f9fd99150be7ef87b6d4b94b1bd52878bf3bbfcceacc2cc45e8971c3a4d4a3eb86af9874d4fa5e7caa7f45d1553ffbb41645bf0f5e9b29772e3dc081b25b52e1cb7e2167483d54fba690ddb29d5462d2a27a35d85f007adede2a3dd7281f654336afafb7370782b29cad643d9d9db2f05f281b53e133ec30eec09fb0d061b74581a2bd2790b137391f19328880f64c53be700d0faddb70dc165d2d62e671eb9449a2e6e9df2c16d8f49fa4b5b84309f7335133dbe872c5a8fdcfbc4980abfb3c9597d5d667ad2f688c7ab24c9e440298d72b28b0fcde9c6f071bccc93e8ddbba7b60a0b544a2e06c39c6723d4f7dc185c21135fd13a72770b976119e49a1f81ed476be07c443de0b0ee76fbd919389328b3eb8607bc2fe38f85745e28adb7482b701ccc6690e4ae5a9332ea44613179387dc6fc47c1d1ec366035e991e1404323bdbbf535f1c33cf57b6723f13ca6ca329e2aaa4b46b42607339906c7ef49b32db82cdf6a87ad:31048d334af05a4f275ff827544ea296a4a775fa59efa000c57613fa6e5c493c3a9b79e8ce56e7225b0fa326204f0336c213535ae589177a8eaedb6df8b202033a1d668c6688414896a7697f3c2e431098edfc457e04d2da869568ad5b3310e59e4c727c903cbf1817408802319a8c231b58023dfae494c013af0fdb78c91d5b457f8c47a3dc31d8c8594aa08f146203fa2c28b3dd796a11a97adede6a7a709b5a1918ef1bea83533c783473703356f5beea7fd18ac44ec6890495ed170d03f15b418608a7d9efd52fa10918638051c448d98d5724f567c8c67fd5b6ec8c3d636008b9bae5e8b1e984f8ffb8b64beebd6345a105c1c1083132fd4508d6ac0d4e9145501210e517d9b22478e215b602599f803762dcd5a409b3460e7f340f47ef77281ad2383de08c5b809538aaec922bfca0d6752f147972646d0a8d8340772c871d3b34abc06037de3ab4e37129865d5ba70b6f3cc9a059efb7dddc3882f4fcfe13f448c9bc664888589603ba98683a93b4b3b1014992a55c8e4ea1baf9cc00d1badff5fd7f5da5e307fbd1b4c984e0fa0edec5d30bfef5f477301263b5d752001b85dd52df3b4a7ac23b930a91c0a45765a66488d8eb5901857060067b82378188549288ddc61831e5b6841b344cae2250042219cfb4ace023e691f9e48d006e9a07c67d2468f93593b4afc161c0768b6ceb744c24c923da34af3d5ed577cc7f85d491560f4c0bcbcd1d5e3421bd1ccfafb373d651bd61ed71c09e99f612001704d0c630d8547bd970b66e7f5ce7a014e0ff5a337dc5c56a99f131b9129140eeea39397c48caa9a8086f9fd99150be7ef87b6d4b94b1bd52878bf3bbfcceacc2cc45e8971c3a4d4a3eb86af9874d4fa5e7caa7f45d1553ffbb41645bf0f5e9b29772e3dc081b25b52e1cb7e2167483d54fba690ddb29d5462d2a27a35d85f007adede2a3dd7281f654336afafb7370782b29cad643d9d9db2f05f281b53e133ec30eec09fb0d061b74581a2bd2790b137391f19328880f64c53be700d0faddb70dc165d2d62e671eb9449a2e6e9df2c16d8f49fa4b5b84309f7335133dbe872c5a8fdcfbc4980abfb3c9597d5d667ad2f688c7ab24c9e440298d72b28b0fcde9c6f071bccc93e8ddbba7b60a0b544a2e06c39c6723d4f7dc185c21135fd13a72770b976119e49a1f81ed476be07c443de0b0ee76fbd919389328b3eb8607bc2fe38f85745e28adb7482b701ccc6690e4ae5a9332ea44613179387dc6fc47c1d1ec366035e991e1404323bdbbf535f1c33cf57b6723f13ca6ca329e2aaa4b46b42607339906c7ef49b32db82cdf6a87ad: +217ecd6a7fcc98719210c34cc2e14f5e2d6b5a22f268c14bc4d8a7f2817200c3d59191ce282d72fe3ac45878e24bb2f28c409ba05d76ce9bcf22f50b0c778675:d59191ce282d72fe3ac45878e24bb2f28c409ba05d76ce9bcf22f50b0c778675:9b5337e78fb382f22ea60e03c0bf3ee4700b6978a91ee6acdf6a409e4918d1684881fa1d118c08c9f6f2ca0cab567402c95010e7abdfe848ae79ba249adcb96eae1dfa0843952139cf49b588647895691a2e9880466b7e77e54f6f60815ebfd5e5748f413c0e15f9d576799bcf31284710636f6e9dc7878500796eed80c8af4be2961952ea80bbed1404bd5dae9e6d05fd4f325a3b83cd4528a0869cef84b4d30e02f941d749a8dac97bb3fa839d25739b97ec374536bdea500484a941db9f2299970658d41148295ca0846ca2366238b6201a48b3e447edbea7a4c8f71020142769e15fa72ae5f287140bc5953b8a9a242d205fc019091f2abed0fda47f52d59a0204ce7401c1829b5857b9a0916fcebe2eef991c413acd71b18d8590d6b6d0fb3994302678c29f2b6a53023f9187e46c36790bce73873c545a72beb553294b1ee5d0d0dff239e28ec63b01e4d8fe0d6e69b1601efa2411f0c0601e7e4f65c984f829f0dc2a8421e7f66d9330537151c7243ca524d7a54735c6e344f1fc938eaeea2779c940891d6d01aa55f40cc1adba12e8a67ad9a27fe63fb4f38dc0f01841925718427255bd665d5eb3bc869896db8625204ad4b02f5a22aaeead6e300471fea61dbb1b55c071365c58b1511f38b09a4671bd66b3fedda9c87e43d1ebf301764e18fc0cf16b2d2d67ed239b393ac71968a903c02477fb2df9ef01dbfc3167de7265f891e4fd24d02c63103519b86a7085b1ec2fb419db766bee7a641a4be429614ab89f20f975341072bf04419fb69be7a9ee71a5b49af83ed322bac68a429ff5c5206773be5438b65e53f609729f4f6a21c1333911264d63927017e8136b4725cd1cc964e08ca0933a561e7e3f5987768330e2e54f8d728f59edfe2c91c4f99aef97d18559195a3d8eb315dff96fe276da7137eff93057ac731e06a60a58bd8a9ae8c7cbaff0cb3372c68daa175c428d52f1073a38bf29465d2a7128bb40074006edcb725a831d812864ef43f3b8667c9fb71093a1673049dec05e09169d86fee92df286008ad99065a2929797a913d0233f4d1a95a220bd91c11dd9c45685dcad385780a0c48b9c4ad2d66303e8de4af1db3c04e4a3dd4219fe773f83a8924b0fcbfffcf264abce32832924036bfabba6546b1df4e3f788ed8ad5c2cd92b2641b47090a103cf5bdc46d8b2143174757da801c360a7aa107fac654b34c860bd54f76bbf43c48478df4fe7aa59cf91d:a0b169e8e9ce557555e0334a0de7438e553675489ea4ba9cc63a234d00ded8ab6967a3be90ef69e076db9ea3d5ca23b3248dd25991ee1f4d80620bf4db438f0e9b5337e78fb382f22ea60e03c0bf3ee4700b6978a91ee6acdf6a409e4918d1684881fa1d118c08c9f6f2ca0cab567402c95010e7abdfe848ae79ba249adcb96eae1dfa0843952139cf49b588647895691a2e9880466b7e77e54f6f60815ebfd5e5748f413c0e15f9d576799bcf31284710636f6e9dc7878500796eed80c8af4be2961952ea80bbed1404bd5dae9e6d05fd4f325a3b83cd4528a0869cef84b4d30e02f941d749a8dac97bb3fa839d25739b97ec374536bdea500484a941db9f2299970658d41148295ca0846ca2366238b6201a48b3e447edbea7a4c8f71020142769e15fa72ae5f287140bc5953b8a9a242d205fc019091f2abed0fda47f52d59a0204ce7401c1829b5857b9a0916fcebe2eef991c413acd71b18d8590d6b6d0fb3994302678c29f2b6a53023f9187e46c36790bce73873c545a72beb553294b1ee5d0d0dff239e28ec63b01e4d8fe0d6e69b1601efa2411f0c0601e7e4f65c984f829f0dc2a8421e7f66d9330537151c7243ca524d7a54735c6e344f1fc938eaeea2779c940891d6d01aa55f40cc1adba12e8a67ad9a27fe63fb4f38dc0f01841925718427255bd665d5eb3bc869896db8625204ad4b02f5a22aaeead6e300471fea61dbb1b55c071365c58b1511f38b09a4671bd66b3fedda9c87e43d1ebf301764e18fc0cf16b2d2d67ed239b393ac71968a903c02477fb2df9ef01dbfc3167de7265f891e4fd24d02c63103519b86a7085b1ec2fb419db766bee7a641a4be429614ab89f20f975341072bf04419fb69be7a9ee71a5b49af83ed322bac68a429ff5c5206773be5438b65e53f609729f4f6a21c1333911264d63927017e8136b4725cd1cc964e08ca0933a561e7e3f5987768330e2e54f8d728f59edfe2c91c4f99aef97d18559195a3d8eb315dff96fe276da7137eff93057ac731e06a60a58bd8a9ae8c7cbaff0cb3372c68daa175c428d52f1073a38bf29465d2a7128bb40074006edcb725a831d812864ef43f3b8667c9fb71093a1673049dec05e09169d86fee92df286008ad99065a2929797a913d0233f4d1a95a220bd91c11dd9c45685dcad385780a0c48b9c4ad2d66303e8de4af1db3c04e4a3dd4219fe773f83a8924b0fcbfffcf264abce32832924036bfabba6546b1df4e3f788ed8ad5c2cd92b2641b47090a103cf5bdc46d8b2143174757da801c360a7aa107fac654b34c860bd54f76bbf43c48478df4fe7aa59cf91d: +08d1d06f3ec29eb52293907b705ec56c5ab354fb78673773ae61253094b89e82c1b99a87ad15bd46f6c848452af0fa3ccccb5cdf6e348d816e36c5d0fca66e66:c1b99a87ad15bd46f6c848452af0fa3ccccb5cdf6e348d816e36c5d0fca66e66:120b35573c34914b373051880da27ed241377f0e78972c98d0faebaa767eb7a7c7e7c6fc3405a4336ef95bc5da9225bbd09e9e11f2a1bf142af4e8a0f924d323dd5a49dfe584f090439c08e51511344d470c6200ac7e7ca150d088a91e47c4c9ff74e38a42a332155d8152ae4abd1161adca934c234ce460af8789e53f109d7d31eede0a909bd193fc8d3c2cfec10b143c31476711bbec27e196a54985bc347167acd233508827bad36e548c880642b86a28c6d3404b511da24f11dfaf6a8f46ddcbc9de9e391597669bddfca6560f91acd3459f329bb071dd80dadf35f0e50df5b10f88d267ac9d3062330dd99a6bcfa13187f45c0c214dcde2cdf9c3ba4d59e633a354a4e277c677bbdfa24191179cbcaf05a10d4078d8add93bc9ed8f6c6c499757403655341f904e37d927750c699c269dc90dc26d005625c3f4124bff66feca59d4abff4172ba3df45a874302231030fa783384f50999e3c4baa5eadb451452c888b519272e90f73c6872768e0de20ee2e5f9502f35e49fecc28b75201887fed2818eff545398392f5e5b6876bc556ac13a1903ada1b9d725b04a14204b599ec33d62b7dcaeea8c52877b2cfdc3558a91d2c9157500a3bb6d452e5e2ff093294fc433cbd63465bb191307ed801a15b85dc2ff0bb38312f8b817a436d422cf4607c64ee7035923db6b96a3899910149b0da4aa3e96685d7163aacf9e619dc60813ce4f344f3079b43f187fa31bdacb9a1d7720b939d5bd241b96a177d7b7768ffebf79044cd2956d6f88db1c243a10fede6814852cf404b2cdcfa774076dc125c70a57c6907e99afe39622ae11f557e7d34b39aaaf45f834058d2fe5f15b5eb70ac15a90a3de5850ab1dcb48b06b6ccaa4b42f857e71ec00b8a3d8974b0bea68fa0f665592115b4fa55572cf0b0738641fc868d4a2e714db3ad7219a823d54b7f7c2656ba5c5eebe3594c7db12298c16251d9845bf2f7800b4190b746e21b0c1a5c47a3df9a059ce0956674eb703decb0a0045437da4da10f286d720d1b9df05fb24415d68e065570e6b31503142d03335a807bdca30892edb5f55f8989d9e649659c0744c5433bfb4deeb11c2626a8650e54d4d398ba19b64f68bed06d7fc408f470ac704e2ac922ac1411fee24543e56f2f50b6b08953dc56a7a75edae430a6df28a227adac91ba26f0e198595327739cba303e9aa393ea6618a84f8f503d0056ee8d87e3796e036cc51ccb791deb795:0b8edcb8b15a8cd074c41dc2a1ba29d9648d6acbdc338314707eca6fb4714c99543b4907b9f85e57eecffe0f7a6b7073a80946f8087553f4683109273a604a08120b35573c34914b373051880da27ed241377f0e78972c98d0faebaa767eb7a7c7e7c6fc3405a4336ef95bc5da9225bbd09e9e11f2a1bf142af4e8a0f924d323dd5a49dfe584f090439c08e51511344d470c6200ac7e7ca150d088a91e47c4c9ff74e38a42a332155d8152ae4abd1161adca934c234ce460af8789e53f109d7d31eede0a909bd193fc8d3c2cfec10b143c31476711bbec27e196a54985bc347167acd233508827bad36e548c880642b86a28c6d3404b511da24f11dfaf6a8f46ddcbc9de9e391597669bddfca6560f91acd3459f329bb071dd80dadf35f0e50df5b10f88d267ac9d3062330dd99a6bcfa13187f45c0c214dcde2cdf9c3ba4d59e633a354a4e277c677bbdfa24191179cbcaf05a10d4078d8add93bc9ed8f6c6c499757403655341f904e37d927750c699c269dc90dc26d005625c3f4124bff66feca59d4abff4172ba3df45a874302231030fa783384f50999e3c4baa5eadb451452c888b519272e90f73c6872768e0de20ee2e5f9502f35e49fecc28b75201887fed2818eff545398392f5e5b6876bc556ac13a1903ada1b9d725b04a14204b599ec33d62b7dcaeea8c52877b2cfdc3558a91d2c9157500a3bb6d452e5e2ff093294fc433cbd63465bb191307ed801a15b85dc2ff0bb38312f8b817a436d422cf4607c64ee7035923db6b96a3899910149b0da4aa3e96685d7163aacf9e619dc60813ce4f344f3079b43f187fa31bdacb9a1d7720b939d5bd241b96a177d7b7768ffebf79044cd2956d6f88db1c243a10fede6814852cf404b2cdcfa774076dc125c70a57c6907e99afe39622ae11f557e7d34b39aaaf45f834058d2fe5f15b5eb70ac15a90a3de5850ab1dcb48b06b6ccaa4b42f857e71ec00b8a3d8974b0bea68fa0f665592115b4fa55572cf0b0738641fc868d4a2e714db3ad7219a823d54b7f7c2656ba5c5eebe3594c7db12298c16251d9845bf2f7800b4190b746e21b0c1a5c47a3df9a059ce0956674eb703decb0a0045437da4da10f286d720d1b9df05fb24415d68e065570e6b31503142d03335a807bdca30892edb5f55f8989d9e649659c0744c5433bfb4deeb11c2626a8650e54d4d398ba19b64f68bed06d7fc408f470ac704e2ac922ac1411fee24543e56f2f50b6b08953dc56a7a75edae430a6df28a227adac91ba26f0e198595327739cba303e9aa393ea6618a84f8f503d0056ee8d87e3796e036cc51ccb791deb795: +f0c85c76b1532e89aea975156dddb1d3d066f6409f841bb4410922725f269d86fd75fc75c36f83498d8f0827f01d3b457f8bc4d9dc55e4a46274ddf0034fe16f:fd75fc75c36f83498d8f0827f01d3b457f8bc4d9dc55e4a46274ddf0034fe16f:ae2eb018d48dbd4f210b16778b5bd2fd14c94e6bbf2b3ff85518e560ab8d3e72201f433420f00f11bc78e0e9f3720875b2e9dc11e04325b8b3f0d465ddab21511c457d6acad8f2fd5fdc0d2823fe6caa66a191a3b6326b32a16befd64d15b361a41513641bceba26bfe93bdf854a4f8f8a0b29f7e28262e2d6e98aa24ac27f6f7883ac01a74c40cce947ebac70e9fef2a16e6289e468950e391e9e24ef58e88a44377269cebafed8987d220dcae2d8b126b6bf812167d023d9baac950d9db8cf52de6306bd48999610c0a433fa9e1771cb832d4197aa340dd0ccd0744fc6b62f90bd3ebb5308cab5f940e2916423cf0f3bf080c06a94f026910460dda809374e6457f064f178e308e7a1b5af4def319007d041778c3d6a419f51badf87663879302b53ff269df442d0e05c958d5baacceed7f5f8afc811c18900ee3b0f61e5dccfd5dac85332d32ebba371aa2d47a606f59546e4bbb605a74677b19a0fe8e95f9f77c0b8b71d07e983004dc2ab2cb3793a323c108dfa7970da00db198674bd34bf7310767f76a224e07bdbc62b9d078cbc75367e2ebaa2c5d274bf3427f2a0cc5dbef0af4e63ad889e131b12bc8ca32d827f7260b0449d0443fa288440efd1364e3c9849477e73ee0ba4240d492af5ce13c34561b45010c109d842c1fed1be3fa9e184aaa14064f43f6dea0b659c5b97893cf2a433bcfb1d2a87eb564bd9092c2666704731f83e56434b2a4299650c7060f9ff7e8aadcb4593f609188d8b467646cfe95270067a1d35cd759fe581af4e62602c02ef14744143eb424f2d9f33a60288c1b25f08e4b2f5feae06cbcc2b2052bf384e1a6fcd8471ce5e5658d77f40c35c415e2a9e09fb583bb7471258e7c806f3c21822dd10f56a640cdc00128d3ba556ba51dcaab47c3baf9f0197d3663de8d093e83173325def1e83a2f5f5acf12ae09f3ce96cd888034dcbe6147dc5998362a4bc406d28846ab1503c17c94f9afd903c9a58e1cebb4abb4ff6f2a41024e06dcaad14f5b70c1b26e69f96ecf14b8da31c621f9ad4e30aeb982378671f7d1f2c4b572c41bb8830840ac5ddced881f8fff210c3c7f236d8c5f2cfdacda29893302fde15282db540cb543737dd77852569221fddcdd68d87e2402179d3a5a77734c275a1d560a462f40318bb6819837da3d305eb49b38650efdc8fe409d40fb94cd5dc3eb02738f38852f671a0c41414b76fb436f3417b8ef300921c009ebbd7cf8e11:4218fe4c1dce795ca92a49a6f4798eb5412dc825860314ec469fed45de3a7bf8ea55e853a349584bd95a826a585a503fd50bfe4c635ef183d07301367e90100aae2eb018d48dbd4f210b16778b5bd2fd14c94e6bbf2b3ff85518e560ab8d3e72201f433420f00f11bc78e0e9f3720875b2e9dc11e04325b8b3f0d465ddab21511c457d6acad8f2fd5fdc0d2823fe6caa66a191a3b6326b32a16befd64d15b361a41513641bceba26bfe93bdf854a4f8f8a0b29f7e28262e2d6e98aa24ac27f6f7883ac01a74c40cce947ebac70e9fef2a16e6289e468950e391e9e24ef58e88a44377269cebafed8987d220dcae2d8b126b6bf812167d023d9baac950d9db8cf52de6306bd48999610c0a433fa9e1771cb832d4197aa340dd0ccd0744fc6b62f90bd3ebb5308cab5f940e2916423cf0f3bf080c06a94f026910460dda809374e6457f064f178e308e7a1b5af4def319007d041778c3d6a419f51badf87663879302b53ff269df442d0e05c958d5baacceed7f5f8afc811c18900ee3b0f61e5dccfd5dac85332d32ebba371aa2d47a606f59546e4bbb605a74677b19a0fe8e95f9f77c0b8b71d07e983004dc2ab2cb3793a323c108dfa7970da00db198674bd34bf7310767f76a224e07bdbc62b9d078cbc75367e2ebaa2c5d274bf3427f2a0cc5dbef0af4e63ad889e131b12bc8ca32d827f7260b0449d0443fa288440efd1364e3c9849477e73ee0ba4240d492af5ce13c34561b45010c109d842c1fed1be3fa9e184aaa14064f43f6dea0b659c5b97893cf2a433bcfb1d2a87eb564bd9092c2666704731f83e56434b2a4299650c7060f9ff7e8aadcb4593f609188d8b467646cfe95270067a1d35cd759fe581af4e62602c02ef14744143eb424f2d9f33a60288c1b25f08e4b2f5feae06cbcc2b2052bf384e1a6fcd8471ce5e5658d77f40c35c415e2a9e09fb583bb7471258e7c806f3c21822dd10f56a640cdc00128d3ba556ba51dcaab47c3baf9f0197d3663de8d093e83173325def1e83a2f5f5acf12ae09f3ce96cd888034dcbe6147dc5998362a4bc406d28846ab1503c17c94f9afd903c9a58e1cebb4abb4ff6f2a41024e06dcaad14f5b70c1b26e69f96ecf14b8da31c621f9ad4e30aeb982378671f7d1f2c4b572c41bb8830840ac5ddced881f8fff210c3c7f236d8c5f2cfdacda29893302fde15282db540cb543737dd77852569221fddcdd68d87e2402179d3a5a77734c275a1d560a462f40318bb6819837da3d305eb49b38650efdc8fe409d40fb94cd5dc3eb02738f38852f671a0c41414b76fb436f3417b8ef300921c009ebbd7cf8e11: +18e268b15a2501dd4c979dc103ca6a842216132b3b5081d775f88640f89c8041b34e19c1e208fb48a885079d9fbf37c74f92710960f832154fab18570cfb4c1d:b34e19c1e208fb48a885079d9fbf37c74f92710960f832154fab18570cfb4c1d:424bdcf0b256001439d16958fff648cf7a8604af22cfa5b44331b4dc356dff25cc0563da9d640133acb70b6a1176c482dbc9408cd6793d56bc29cc408823d388ed88b24ceb6621dbac0023ee69f76f8296a7395211685b3ceaa995f0355d9aad3d97358f4a379e5920ec545f469621cf768abf55d2a554c949b0ed70187c2205ad032985c9b5b2e4ba57e0b4a47d344512b84bfe9f3aa560fe6ecfc5bdf8c3b41845293573f81ed3b70edc63a30c70cda3f455901313f6d23db309478f03e34e71356d83fa5db9280cc2b4369c3d24dd9038f247596c391e48b2f3f890a141ca1d12077c69344735a59b1dd4076b22e16189991e5f1be4fb7695af90ebea5df286135cec2a6e99aa1dda328e62c0dfb63742202d63624dcc0c5cf1a5df79e2878dbc71fa96576601af22844f545733126af7d3984c3ed252e6a876445c92259fbb470a10569b49e5791fd0182cfe1c3f88297facc8c31a5332f1f4eb4958db13b6c079aa9c949487263403190c83c11a43191ffec6023fb34cfab2525beb546cf9200a96f5854b2f78ecb2d9a53aa9d287a90d4d410a63ada0e975d304d5148353463fa805b4805fb4687ed8857dfce4bc6e80833c8f9a79cd4f029a2d802bfdc819ed0c0ac8f21023287f2b4bafbcc89993fe46d52a9c6246dead617df797d48ee985f0f0df9aa82ea20e0d0db28a254a9a253f39f9cf01e3db8f3ebcf7cb97cec58c4efe031269b4b37e4cbb361f73ab4b4980bd900849538844c52cb3ac7583b8f89653a0de65a8be91582c55239cb8f5d5318a88d160e1c871e5ea7e75f5a69cba8538221ab42ce2a2c4d9c3b7ec857f230d573731133686ae8a7ed640f42f31029489e4e6af2b3ea4c7948ed537c0c5906726c2b625fd5f949e3a7cf3b6e998ec761dd6e2b5171a68749752e721b788c3477fa190cd6ea81d579dce6462d9c662ad8962e79338710cc8d2738a5fb04adfdb3f1432cfd80e2e967da000d83a0fa85abae2952f3f3683e254d868f4bf809eb2e300e7b209734a3c894e966b16088d5ed354bffbffbbf2ec2be93a32a8be5cfa18fa5653012edae5afd8709ca55c0cf23a550d34ca0f32d8f666fb47a12f2b7353a40c5379f75366c13f4ab9f14cf80a94e1f13d8b09b76fd8d14ffa538f31fd8aeb49d33433f4df7c2ca67399579fe99078aa721d6b6fc0c50e8a91fc71ca25eac1376fc671bf6153e720b25c7e97a3d4ef8442ac67acf58b504b67158f913025:f2dcfc06ef1d8eccd8e40bdf01307dd19683f214d4f084e6b6934f637278300dbb1889f2d37f53b3aef26fbb3e36bd75985fa7c8ea6ddffa72c8e406f24bb20e424bdcf0b256001439d16958fff648cf7a8604af22cfa5b44331b4dc356dff25cc0563da9d640133acb70b6a1176c482dbc9408cd6793d56bc29cc408823d388ed88b24ceb6621dbac0023ee69f76f8296a7395211685b3ceaa995f0355d9aad3d97358f4a379e5920ec545f469621cf768abf55d2a554c949b0ed70187c2205ad032985c9b5b2e4ba57e0b4a47d344512b84bfe9f3aa560fe6ecfc5bdf8c3b41845293573f81ed3b70edc63a30c70cda3f455901313f6d23db309478f03e34e71356d83fa5db9280cc2b4369c3d24dd9038f247596c391e48b2f3f890a141ca1d12077c69344735a59b1dd4076b22e16189991e5f1be4fb7695af90ebea5df286135cec2a6e99aa1dda328e62c0dfb63742202d63624dcc0c5cf1a5df79e2878dbc71fa96576601af22844f545733126af7d3984c3ed252e6a876445c92259fbb470a10569b49e5791fd0182cfe1c3f88297facc8c31a5332f1f4eb4958db13b6c079aa9c949487263403190c83c11a43191ffec6023fb34cfab2525beb546cf9200a96f5854b2f78ecb2d9a53aa9d287a90d4d410a63ada0e975d304d5148353463fa805b4805fb4687ed8857dfce4bc6e80833c8f9a79cd4f029a2d802bfdc819ed0c0ac8f21023287f2b4bafbcc89993fe46d52a9c6246dead617df797d48ee985f0f0df9aa82ea20e0d0db28a254a9a253f39f9cf01e3db8f3ebcf7cb97cec58c4efe031269b4b37e4cbb361f73ab4b4980bd900849538844c52cb3ac7583b8f89653a0de65a8be91582c55239cb8f5d5318a88d160e1c871e5ea7e75f5a69cba8538221ab42ce2a2c4d9c3b7ec857f230d573731133686ae8a7ed640f42f31029489e4e6af2b3ea4c7948ed537c0c5906726c2b625fd5f949e3a7cf3b6e998ec761dd6e2b5171a68749752e721b788c3477fa190cd6ea81d579dce6462d9c662ad8962e79338710cc8d2738a5fb04adfdb3f1432cfd80e2e967da000d83a0fa85abae2952f3f3683e254d868f4bf809eb2e300e7b209734a3c894e966b16088d5ed354bffbffbbf2ec2be93a32a8be5cfa18fa5653012edae5afd8709ca55c0cf23a550d34ca0f32d8f666fb47a12f2b7353a40c5379f75366c13f4ab9f14cf80a94e1f13d8b09b76fd8d14ffa538f31fd8aeb49d33433f4df7c2ca67399579fe99078aa721d6b6fc0c50e8a91fc71ca25eac1376fc671bf6153e720b25c7e97a3d4ef8442ac67acf58b504b67158f913025: +3c393f9df1fb0b1eec09b7f270b85982ba0fd5e4b1795e1a7fa99137fee24d7d974fe23730fc17945670fbc1f80b93f94593c8d44bc75d189a6bbfaabaf5dbd9:974fe23730fc17945670fbc1f80b93f94593c8d44bc75d189a6bbfaabaf5dbd9:54d8b8d5fac28cffa77a0916d6333c16edbc8bb74aa06e56dc00e47e3929e40864b8840d912079597eacd81dae43e2785dfc689f3e85f8c66581efc5e853d1faaac744400ab08cbdb5d16146fa60f99905ed84fd2936dd73f4bca2572b7cf5160560ffaa68da7a67e40e08a7bb7aefc4043ebed5fe80a414817edf2c63f62fac0d47446ed0bb584058f4872fecff621559311a270aea37a6296864e8d168bf1e2f55cd3b276edfa612b5d9c3362e618be6e82a6e5f82667924f3d1d3df825f9d23f4d6142d3100dfc70f70603abf3fdadaca69ef6a18ef9092b3c41ec658ab27216fc6147a080acda60a841984ee83f41ac42a80eaac91fffc8228391ef583ab3eddcf876523c20281355300d86c11a4e7c1ade8e50560f43906c9bc8ca5fbf8339fbebd02e33e8518bee5e806b8c10f8277f410664735a2bf556839635492452e6ca079deb9751cfc6797f49bca9613ff2e7fdd3646f7c5236a36bdf0051745e595dc0072fd6651d57627a6004c0f0cfae856bbc28a1231cb839665ff04152ec31c007b3e2ed0a973b24c93149ce701e6fd6539206ae91bec4ce65a89db26c7d38cecb8919f96fb6cb8f6c1939d90fb3f90b887789f29575ab20e0b08bc358153d8c03521dc891870b5f7eedcc1e62bee7da063ae66ff0a4b7d98d1cb758f69743c3db3ae2a2c9be1be094f17cd28f92d8ccbca983c749c75c610f840836e2c430ccdeff0afa54444f12b4a4f002c609451834244c0c07df8e12202a65f94447cd4903acb606d7725a86e4a2343984e679c4af1b3679c755ea50d0abe2fcc0c1c3351a9ee196b4644c424222be99e2fb373f9641e3faebff43170eb03fb8ec4557d151a55fab6c499d444c84be89f2447682de4e6f6353475efcb8fc53256763a948dc75c515fa353545d0cbad29df5e9db5cc457ed3086cffb3d75e846c4e8d88147fcd0d8aa5abab49b5e05c3d7feef637943347ad3f492ee356ef34881cfd85abce8a144ce7761e284e8b8cb08966049047a996e23559f776b1a9f41cba3954108486e2927beb6433a36ff8b2f03aa74b3d209c488e077f924f231e28345942c7dcc2e61d7c9b522b659fcb53662aff3648f66da3e83e59b0daa90b94c515dadab10d5a839cb3a2f1d3cd092de55d995138c3ac0b907af15ac63ec1874114327e21971345ef17031d52617e784da3771439be2e84148bcfea132bde10e6fda547dcbb1c4d8f74ddce1fccf8213e0da6e97b81f75:22333e56410fdcbf84f6a8de741337691684495ba69eff596db9c03a281210881e6c91efa91b2183c0eac916152817a78ca724ba7c8b51bb4caadea9a341eb0e54d8b8d5fac28cffa77a0916d6333c16edbc8bb74aa06e56dc00e47e3929e40864b8840d912079597eacd81dae43e2785dfc689f3e85f8c66581efc5e853d1faaac744400ab08cbdb5d16146fa60f99905ed84fd2936dd73f4bca2572b7cf5160560ffaa68da7a67e40e08a7bb7aefc4043ebed5fe80a414817edf2c63f62fac0d47446ed0bb584058f4872fecff621559311a270aea37a6296864e8d168bf1e2f55cd3b276edfa612b5d9c3362e618be6e82a6e5f82667924f3d1d3df825f9d23f4d6142d3100dfc70f70603abf3fdadaca69ef6a18ef9092b3c41ec658ab27216fc6147a080acda60a841984ee83f41ac42a80eaac91fffc8228391ef583ab3eddcf876523c20281355300d86c11a4e7c1ade8e50560f43906c9bc8ca5fbf8339fbebd02e33e8518bee5e806b8c10f8277f410664735a2bf556839635492452e6ca079deb9751cfc6797f49bca9613ff2e7fdd3646f7c5236a36bdf0051745e595dc0072fd6651d57627a6004c0f0cfae856bbc28a1231cb839665ff04152ec31c007b3e2ed0a973b24c93149ce701e6fd6539206ae91bec4ce65a89db26c7d38cecb8919f96fb6cb8f6c1939d90fb3f90b887789f29575ab20e0b08bc358153d8c03521dc891870b5f7eedcc1e62bee7da063ae66ff0a4b7d98d1cb758f69743c3db3ae2a2c9be1be094f17cd28f92d8ccbca983c749c75c610f840836e2c430ccdeff0afa54444f12b4a4f002c609451834244c0c07df8e12202a65f94447cd4903acb606d7725a86e4a2343984e679c4af1b3679c755ea50d0abe2fcc0c1c3351a9ee196b4644c424222be99e2fb373f9641e3faebff43170eb03fb8ec4557d151a55fab6c499d444c84be89f2447682de4e6f6353475efcb8fc53256763a948dc75c515fa353545d0cbad29df5e9db5cc457ed3086cffb3d75e846c4e8d88147fcd0d8aa5abab49b5e05c3d7feef637943347ad3f492ee356ef34881cfd85abce8a144ce7761e284e8b8cb08966049047a996e23559f776b1a9f41cba3954108486e2927beb6433a36ff8b2f03aa74b3d209c488e077f924f231e28345942c7dcc2e61d7c9b522b659fcb53662aff3648f66da3e83e59b0daa90b94c515dadab10d5a839cb3a2f1d3cd092de55d995138c3ac0b907af15ac63ec1874114327e21971345ef17031d52617e784da3771439be2e84148bcfea132bde10e6fda547dcbb1c4d8f74ddce1fccf8213e0da6e97b81f75: +f8669c88f1685bbf0480cc9221ac2ead8f551bfa87ecba2fd4ddf3ba3476ebda34723fb8e253ad9c71cefde03628d204e535de479e1048e5188762a1f337fe5f:34723fb8e253ad9c71cefde03628d204e535de479e1048e5188762a1f337fe5f:5b4941beec2241c9fb76d8484f4f3f3ab4ffe8ecc8e7aec76de2ab8c368584d751b0d3feb8a1dc8168cdc694968f66b2a0b052afbf8be3a7d95163e9da9141c59ca55976c292c5c74d31318d6a91e7817c5a8b2f812118cbeba3a13323cd9748bf86ed1a85dd4ebc0df495cfa3d4627434bf14aae8ab6781467a56d965d10e6371989dfa0f6bc0f7859f3771eb9004b34367db2705dbd60fa8f7895c1eadf59f53dab168b4f9363979025501ddd9680debc07cd1ca4a0997876e9211f307d9b7b9d904e48d2861a778b879ad590a9a2f141bd568e3a1bb2494628e9ec0c64255aeea6f0eedca30ad38a1f3ffec3b2b5e942e21940104e914d11a44c00fdd47da3e5513aa8530aee247c95ca66d08a2608c75ba9858da14f9a8a32be713d309e0f584c81ef5be040e0065f07b775ae175dfe2c8b90a88ccda17fa4f21c77eadf5d25b6e404bf004479e05a01ac0042b89937eb278c1c34f33028db780ba3b617918595a39c0fcad674b85c40cac8d345b7ca0bb48a28e66c44d8bb5f27941e40b0e9c7097976c62dfef50c98f17566ccbacc87cb03b94dfdfaf32f1e56ffa639d63611e213cebf54cd0a3e2172d811c0ebd75b1a8646264dd8b1abd46e548972a1b262cd95d511536dddcb49729fe7bd00b3838bd2f20a142640edb1b6e765b65da72e7233261c8892e2f4949bb51f32a1a5a3ee149bea26fdcedb991d2cd126637e2971e9b6f0b785df28a48f301707349423f44e8462289d725498230489df1b51be30f08d7e3250565c6ef824bc53a1ba74a57a25c0686adcb6c825ab1ca70c8a5d46dbbc6fa607461e26d16fe93bb3d3a943a3dc05f30ea6dc8bb12d70821d320f1adf1ceba4be657194f7fccd21990f8629d744601cf52ea6d9405aaa2878f1eec4003b45a4218d8f80bb0f5af047326487752e2b76d68872520bbeae7b309d78282a073fe0b1a1a7a98da23df68caf8c2699b1c7d0f47bd7de2c0bb23369963e68a6974c8e2b595b8293a9f4d98df7e9ae3add2a3f64e83039739642d192204e85e6c48d5d671f6c75a0a8957edbb74187620f2aba99c1c62584c59ac00647e3fb40292b9dc1a3346868553392fd3f11d6dc6f5f2f4e85ee25125cdd644743c7d45281edac6384c77cb98a67d9ae6fc9a0a76b9f6fa696fdf4aceab5f794ee521b1e5a0ee57af53bdf176801b4f45cfb3cae3287234234b77ce21edf8680d68c4a8eecf1b03537ea5699acb562777e42a486fe7cd:3746da6cd8ca108beef06487bee63584f812c8e0695fc863b86e5db132380b62ff8544f6f374825b0e3ea0620ef854c1331114d667df1f9ea776c3963870290d5b4941beec2241c9fb76d8484f4f3f3ab4ffe8ecc8e7aec76de2ab8c368584d751b0d3feb8a1dc8168cdc694968f66b2a0b052afbf8be3a7d95163e9da9141c59ca55976c292c5c74d31318d6a91e7817c5a8b2f812118cbeba3a13323cd9748bf86ed1a85dd4ebc0df495cfa3d4627434bf14aae8ab6781467a56d965d10e6371989dfa0f6bc0f7859f3771eb9004b34367db2705dbd60fa8f7895c1eadf59f53dab168b4f9363979025501ddd9680debc07cd1ca4a0997876e9211f307d9b7b9d904e48d2861a778b879ad590a9a2f141bd568e3a1bb2494628e9ec0c64255aeea6f0eedca30ad38a1f3ffec3b2b5e942e21940104e914d11a44c00fdd47da3e5513aa8530aee247c95ca66d08a2608c75ba9858da14f9a8a32be713d309e0f584c81ef5be040e0065f07b775ae175dfe2c8b90a88ccda17fa4f21c77eadf5d25b6e404bf004479e05a01ac0042b89937eb278c1c34f33028db780ba3b617918595a39c0fcad674b85c40cac8d345b7ca0bb48a28e66c44d8bb5f27941e40b0e9c7097976c62dfef50c98f17566ccbacc87cb03b94dfdfaf32f1e56ffa639d63611e213cebf54cd0a3e2172d811c0ebd75b1a8646264dd8b1abd46e548972a1b262cd95d511536dddcb49729fe7bd00b3838bd2f20a142640edb1b6e765b65da72e7233261c8892e2f4949bb51f32a1a5a3ee149bea26fdcedb991d2cd126637e2971e9b6f0b785df28a48f301707349423f44e8462289d725498230489df1b51be30f08d7e3250565c6ef824bc53a1ba74a57a25c0686adcb6c825ab1ca70c8a5d46dbbc6fa607461e26d16fe93bb3d3a943a3dc05f30ea6dc8bb12d70821d320f1adf1ceba4be657194f7fccd21990f8629d744601cf52ea6d9405aaa2878f1eec4003b45a4218d8f80bb0f5af047326487752e2b76d68872520bbeae7b309d78282a073fe0b1a1a7a98da23df68caf8c2699b1c7d0f47bd7de2c0bb23369963e68a6974c8e2b595b8293a9f4d98df7e9ae3add2a3f64e83039739642d192204e85e6c48d5d671f6c75a0a8957edbb74187620f2aba99c1c62584c59ac00647e3fb40292b9dc1a3346868553392fd3f11d6dc6f5f2f4e85ee25125cdd644743c7d45281edac6384c77cb98a67d9ae6fc9a0a76b9f6fa696fdf4aceab5f794ee521b1e5a0ee57af53bdf176801b4f45cfb3cae3287234234b77ce21edf8680d68c4a8eecf1b03537ea5699acb562777e42a486fe7cd: +ceccc68311fc45b6c2a2f1ff9cdde007ec787fdf25d02ccd2a1cad9de3fb4cff6f804734ef92824180da71e55cf3bf1afef65bcf560962e0b0acbb2d8cca5984:6f804734ef92824180da71e55cf3bf1afef65bcf560962e0b0acbb2d8cca5984:bac186d9fe5abda79c3a35a7a3c2eae6ae6ab28247912770c84efd048ebd3aba57c37cf4c6c7f30a79f68a3f76b20cd8c6631fcc96670522080e6b62e887ae6f4436d4caf56943131c52dd282b251cd075f1f7f8e0bdb6bedfc9a0796f5579042b56e69374961b11dfd61b12de2bb7d49bfc509cdb3138f3356a0dded98f5301b7c4a748bf89b23df4f7472ff8b1f505d765c6ff82dbad74b9d7aef22fbcca0b7f35042f9a762bd06902bb21c7f9f7f66bef38901d75012d61d744dee7afd89fc7e908c40685bd440aeda4204d006f26307d82a496963115f90e09f76688291f4a67d6411f76d16617875b2b9982dfdc5ee9b83b9817009319110b5404c63116fb6e9464846fa009555632f076984c15e1f6081733a0d46f2d6a3cebf79ed9020c9dec8df158a3341f39eaa5fcf1cf42a94849b2352c1a1ecd4fb814c20d07dfda312bd4f2f58c1576b4aa315c96c8786a4cfbb736b2d23c38b1d81c4644ea36afa076e055be5917cd7a92350a7ed66a5ab2253f55c4fd1a0d0e6d4edab5f712edb440c06fac8f07e6d73cc90b2ba713d73c73802361ce46a4eb5ed1060c4cf53207d301f0fcd4f0c9d1580db2fc1059d372076438a01192a7f9fd6f7883f56422866fd9f0afe53fdc910afa5a751cbfa377592579165cb56dc3eb4dce67e3db33a981a56b7d9f7bdea74fbaea3478e6ab2c644fd777b8bfa72aa0f0a52198d36e5b634d2c9a11b7fe0ab2f9a40901c5b148a0192e95a170baf7d5350fe01e569542b93485a41971443485faf57f67f56dfe2c58e539c9f9b449c3f91249a10c1a1be7e0b3eabe8ee0bab1f11f89614dced418c62a07a0b59a1370d6531ba177091c6ad595fb59488204f63344736ea1017affbeb753a99786b1eb64510e2e717ec90e02744bc352d3f1b2ab7be0eb65623d04fb3a046ce7f4da697d829828a52c7b043b2a82ec97fb041bf519b4de316f4e2f5b0db62aed0eed95cad4320c1947c35fd8847a5867872883561119c01b0089213d84db99d439f0f6444d8783dd4b64be3577cd461cf753c8e61c912de2e5d7a7e2baefa258975d16ef3117da59a6c893f3339187df3168b89f0fb0b2198bb6f1594bb88f3d610fcec3e36de04ae10328112e6ff74f5a8ce68d407174b4c0691c7602eab1bb10f3c49dd22b8450782deae9a7315e3b88de79cd15e6c9268165ed3a0fb3f89b183e1a212152003f32a2665d37cdd7f6b56c2453e5580c4d21f9983f38798e9b:3c4462aa47010132dbb26311e444727279edade15a4d662cf647f3275cf3253e6de9333830e0517aa5fa7bc2d0e63ea2597a94b0fe92706ecd172c5ec5c7f006bac186d9fe5abda79c3a35a7a3c2eae6ae6ab28247912770c84efd048ebd3aba57c37cf4c6c7f30a79f68a3f76b20cd8c6631fcc96670522080e6b62e887ae6f4436d4caf56943131c52dd282b251cd075f1f7f8e0bdb6bedfc9a0796f5579042b56e69374961b11dfd61b12de2bb7d49bfc509cdb3138f3356a0dded98f5301b7c4a748bf89b23df4f7472ff8b1f505d765c6ff82dbad74b9d7aef22fbcca0b7f35042f9a762bd06902bb21c7f9f7f66bef38901d75012d61d744dee7afd89fc7e908c40685bd440aeda4204d006f26307d82a496963115f90e09f76688291f4a67d6411f76d16617875b2b9982dfdc5ee9b83b9817009319110b5404c63116fb6e9464846fa009555632f076984c15e1f6081733a0d46f2d6a3cebf79ed9020c9dec8df158a3341f39eaa5fcf1cf42a94849b2352c1a1ecd4fb814c20d07dfda312bd4f2f58c1576b4aa315c96c8786a4cfbb736b2d23c38b1d81c4644ea36afa076e055be5917cd7a92350a7ed66a5ab2253f55c4fd1a0d0e6d4edab5f712edb440c06fac8f07e6d73cc90b2ba713d73c73802361ce46a4eb5ed1060c4cf53207d301f0fcd4f0c9d1580db2fc1059d372076438a01192a7f9fd6f7883f56422866fd9f0afe53fdc910afa5a751cbfa377592579165cb56dc3eb4dce67e3db33a981a56b7d9f7bdea74fbaea3478e6ab2c644fd777b8bfa72aa0f0a52198d36e5b634d2c9a11b7fe0ab2f9a40901c5b148a0192e95a170baf7d5350fe01e569542b93485a41971443485faf57f67f56dfe2c58e539c9f9b449c3f91249a10c1a1be7e0b3eabe8ee0bab1f11f89614dced418c62a07a0b59a1370d6531ba177091c6ad595fb59488204f63344736ea1017affbeb753a99786b1eb64510e2e717ec90e02744bc352d3f1b2ab7be0eb65623d04fb3a046ce7f4da697d829828a52c7b043b2a82ec97fb041bf519b4de316f4e2f5b0db62aed0eed95cad4320c1947c35fd8847a5867872883561119c01b0089213d84db99d439f0f6444d8783dd4b64be3577cd461cf753c8e61c912de2e5d7a7e2baefa258975d16ef3117da59a6c893f3339187df3168b89f0fb0b2198bb6f1594bb88f3d610fcec3e36de04ae10328112e6ff74f5a8ce68d407174b4c0691c7602eab1bb10f3c49dd22b8450782deae9a7315e3b88de79cd15e6c9268165ed3a0fb3f89b183e1a212152003f32a2665d37cdd7f6b56c2453e5580c4d21f9983f38798e9b: +7b30b42dc2c670a195fe2af879fc5de374024588fe3de43e2dd50844f48f42be82a2ac6079f212b5eedd0c19e9394fafacd74d716fdefbfc6cb8a7eaf41c0362:82a2ac6079f212b5eedd0c19e9394fafacd74d716fdefbfc6cb8a7eaf41c0362:c6687aefebc5c816d1a33453beca5020d3a97cda1dac5662f0af72bad444e2fd1176a7b04c1bd09d832618209bf3e33e523538d6daa753046e871dd3b3c7acad33e79c1bb7896407865d168d4bc3757bde4f823c08778626f8c71fb7cfcfdf03a82497bd8be7d8f8ef649030b5f36a339459968e246a1e420853dace41ca850a4eeae834ae119610ca4cd0662aac39621586998027ef2f61485c028506714ae09c76399d873e808158578aa59e8212f58865319f9e0d2b8da7ad529e0ac1f1eb435aecfd35f5abb92bea5073496bf4c0bf15baa273bfc5c3104474a2dcf132c333eb36ec2cbf04fa9580b768f5cea7b5617e5880aff63201c274d669743e1bc556b067902eee29d29111288969cffa879fc9cbf66fbf9326d9d925ac4102fa9f1a06081adec079cbc96746d79b63a012ed77d82c9ffd4e3f161f6cea28cc23fac2a543f5b1d0644ec04838327bcc652b858f93ff463f7e949eec8c9db6569a86984f831df6ac6d95f38f46cebb6e6583657facd2108dbcd0af23ab0101a1301beb48a44caccb91094473d7e5a5c88c644fd3420573b678f17b5174cb14e90fac694d1dbc6c9632b5974aef28ac08d720b2ea30440d2afb0493b40db24efbdbf53c430921e52a10b54661e149d165591a7cf91d6508ea472fb3be16395e30312f19b87c47e46804a0fa29b56b5ac950677bc60238b5e99e030b1e552146a0e88c294cfca835c101c55f3423874cc128756e73a5debe8e97fe2166b65cb44642770c6d1d2390af1b0f31b958c830e9ac4fe2f5ad590582fbb892bf949584477ef7bde23f7dd02b63f7c29088a57251009132ffbb78ed14defbefd9fd31fdcab03ba80a23f333983760abad4f16ddf9dd4414f04d00db56ba72d63a3a13d2c442f549fd66c988d2e4601d13b52f77500dd692bec9d6bd3bafa9242fdcfaeb69b98b0b5789b2803840dec637b49af4381ae3fa429fb53461a0c674eb5aa18dbd607a2b77a96d3ab464ecd97492f6de460c9f11b5c1756cb59cb1348dfd77956b71907c54821e303cb8b14906c003e3484be4ea05a6901d69b07485e858f7b471c635f90395b9a3e2247f1ad12b118ffafc7221a57b10e319b61af1c13606a81616ce3f1d62ba932ff4e63e74b84255e3af5210bbd571bda44cbf44b714422cb45c2ef21f98131ba96b7edb9b03e33d7d188d5b8d904cb4136fe269db146988168e7ee245356354f002a5ea8b35a3a99e83a13272274144b33a60ca:0a63b84f46935faf3ea164b00af227b00868a03f5612935e18619a84a2e57b8851d746e63fd9100787f5338d51c1073c2fc5303099e1873e5e3d3e5c036fbe01c6687aefebc5c816d1a33453beca5020d3a97cda1dac5662f0af72bad444e2fd1176a7b04c1bd09d832618209bf3e33e523538d6daa753046e871dd3b3c7acad33e79c1bb7896407865d168d4bc3757bde4f823c08778626f8c71fb7cfcfdf03a82497bd8be7d8f8ef649030b5f36a339459968e246a1e420853dace41ca850a4eeae834ae119610ca4cd0662aac39621586998027ef2f61485c028506714ae09c76399d873e808158578aa59e8212f58865319f9e0d2b8da7ad529e0ac1f1eb435aecfd35f5abb92bea5073496bf4c0bf15baa273bfc5c3104474a2dcf132c333eb36ec2cbf04fa9580b768f5cea7b5617e5880aff63201c274d669743e1bc556b067902eee29d29111288969cffa879fc9cbf66fbf9326d9d925ac4102fa9f1a06081adec079cbc96746d79b63a012ed77d82c9ffd4e3f161f6cea28cc23fac2a543f5b1d0644ec04838327bcc652b858f93ff463f7e949eec8c9db6569a86984f831df6ac6d95f38f46cebb6e6583657facd2108dbcd0af23ab0101a1301beb48a44caccb91094473d7e5a5c88c644fd3420573b678f17b5174cb14e90fac694d1dbc6c9632b5974aef28ac08d720b2ea30440d2afb0493b40db24efbdbf53c430921e52a10b54661e149d165591a7cf91d6508ea472fb3be16395e30312f19b87c47e46804a0fa29b56b5ac950677bc60238b5e99e030b1e552146a0e88c294cfca835c101c55f3423874cc128756e73a5debe8e97fe2166b65cb44642770c6d1d2390af1b0f31b958c830e9ac4fe2f5ad590582fbb892bf949584477ef7bde23f7dd02b63f7c29088a57251009132ffbb78ed14defbefd9fd31fdcab03ba80a23f333983760abad4f16ddf9dd4414f04d00db56ba72d63a3a13d2c442f549fd66c988d2e4601d13b52f77500dd692bec9d6bd3bafa9242fdcfaeb69b98b0b5789b2803840dec637b49af4381ae3fa429fb53461a0c674eb5aa18dbd607a2b77a96d3ab464ecd97492f6de460c9f11b5c1756cb59cb1348dfd77956b71907c54821e303cb8b14906c003e3484be4ea05a6901d69b07485e858f7b471c635f90395b9a3e2247f1ad12b118ffafc7221a57b10e319b61af1c13606a81616ce3f1d62ba932ff4e63e74b84255e3af5210bbd571bda44cbf44b714422cb45c2ef21f98131ba96b7edb9b03e33d7d188d5b8d904cb4136fe269db146988168e7ee245356354f002a5ea8b35a3a99e83a13272274144b33a60ca: +6656f4d4718157c4bac38ff7abe5eb1f812c0b986d9c014abad5b09aa6c8ee4af3087898e452be9e30aecc4e8ffe0c01169888683f62a45b8da38299014f5b4a:f3087898e452be9e30aecc4e8ffe0c01169888683f62a45b8da38299014f5b4a:94d9e5e5a7b705d9d976fe71e94d3f7fa7866afbf7ece424f136327799b2b206ce4ef4c3f3e705553afc8fd5c1952a4c16658d4a78afbb9a97f27193c65b65b82e8f3b71515fac82640e0f8a5fb35ae6fc6a3db051a22d4a5300413e6e33d19c2013c2983aca8ad6cec2ce64a814164f061a1a3c5a8610a7650bfb5423d4362ce02206dbe4a6fa826f03b42ac3cd9ea4c651401b3cea82c3993f6af8b2c9e2e6ffe69280ab3f09fbe90dd547ccda9d9e8e8a537b3b360554227ed0709f293198982efb5efb0e73e00042d1a063b57452027dce1a39e4b0068f58b111ec5dc142bf419ad893d54f4260cbde7628f783de8496380306a4eff6d82869104259c94c54ad5aa8b067c42496cb88dd31150ea04d499bfac91f4bb3e68af5af7a568a3e4ce7f170d98601163f4952f1d25e12e00ef0a2d8f111afdb0fafbad2bf8e8b9d49363fca68183617b541270dda4609b2616729ab1b8c42dbdd7bf986af8fba52e733e42ba03c892e1e1ec06a90b163f5a79f6165eb7316972ac1adbfcf1dcab07847ef82c2cab1015dbb50aadc79fe11c832098cacc39820ab085b6963bd42160ed6613bae5e201f17c0fd7f32357ae350ce9cbbe926fa42dcbd422ac1bf09a19ad1f69469e4d1dcb124118ed4522d353c174298650ff88382fa2fdbb286c45b18a9baf6f6763ac20c9ca4767d348c4b8ded630076657b85b14c11ae2737ea29a43515b7f05674a0cd3ed4bf6a3d189ae972218f877cd8aa69499d5a08c99e440694ccaccdf1f642e14e90105bee6d98edeeab3b4f339f300188aec0c16bd64521d9287398e648db94330ed8f6b9ab6c7ad93ffc43e8792e637c61bff7d856e54ef4987384e312cb57017a50eae5952abe19d8999c8c82dfc45798cc17c8d9496bf520ecc5b77fe284915566c45685c304a2acd525ef12c86f38aef554d8a2384737cc4133fb7e2b65c13bef31668a6c2f60eecd8412eeff7f6b605cbe95083e233ec1a7bb36de236c8a71ba2872be946cd3b38935f5da64c8fec8e14f45ccf6124bab7f70567c2f2bfdd56667609572037c76146c991707659b5709b074e3451f921a2df283b96aa26ab476625016f181ad64c9919cf41d714a1a9a5e2bb26baf8770b2eba77b778a332677a7572ee3a2b1dc05f7356bdcae5f55e35329e34caa79430b270c036160dc9fcaab5b254543ac94b24681f17172b6159d16621d7ad0eebd895a1e1d09b916a86fb48e4c91661057eee95c0870ed54:9c2c39915aed6add004e7dd684ee3dcdd10d87a487f677e73c2bce0fca7d508796464150a52a440f5237850a009c72162d9d2985470a33490e66d3c401704c0594d9e5e5a7b705d9d976fe71e94d3f7fa7866afbf7ece424f136327799b2b206ce4ef4c3f3e705553afc8fd5c1952a4c16658d4a78afbb9a97f27193c65b65b82e8f3b71515fac82640e0f8a5fb35ae6fc6a3db051a22d4a5300413e6e33d19c2013c2983aca8ad6cec2ce64a814164f061a1a3c5a8610a7650bfb5423d4362ce02206dbe4a6fa826f03b42ac3cd9ea4c651401b3cea82c3993f6af8b2c9e2e6ffe69280ab3f09fbe90dd547ccda9d9e8e8a537b3b360554227ed0709f293198982efb5efb0e73e00042d1a063b57452027dce1a39e4b0068f58b111ec5dc142bf419ad893d54f4260cbde7628f783de8496380306a4eff6d82869104259c94c54ad5aa8b067c42496cb88dd31150ea04d499bfac91f4bb3e68af5af7a568a3e4ce7f170d98601163f4952f1d25e12e00ef0a2d8f111afdb0fafbad2bf8e8b9d49363fca68183617b541270dda4609b2616729ab1b8c42dbdd7bf986af8fba52e733e42ba03c892e1e1ec06a90b163f5a79f6165eb7316972ac1adbfcf1dcab07847ef82c2cab1015dbb50aadc79fe11c832098cacc39820ab085b6963bd42160ed6613bae5e201f17c0fd7f32357ae350ce9cbbe926fa42dcbd422ac1bf09a19ad1f69469e4d1dcb124118ed4522d353c174298650ff88382fa2fdbb286c45b18a9baf6f6763ac20c9ca4767d348c4b8ded630076657b85b14c11ae2737ea29a43515b7f05674a0cd3ed4bf6a3d189ae972218f877cd8aa69499d5a08c99e440694ccaccdf1f642e14e90105bee6d98edeeab3b4f339f300188aec0c16bd64521d9287398e648db94330ed8f6b9ab6c7ad93ffc43e8792e637c61bff7d856e54ef4987384e312cb57017a50eae5952abe19d8999c8c82dfc45798cc17c8d9496bf520ecc5b77fe284915566c45685c304a2acd525ef12c86f38aef554d8a2384737cc4133fb7e2b65c13bef31668a6c2f60eecd8412eeff7f6b605cbe95083e233ec1a7bb36de236c8a71ba2872be946cd3b38935f5da64c8fec8e14f45ccf6124bab7f70567c2f2bfdd56667609572037c76146c991707659b5709b074e3451f921a2df283b96aa26ab476625016f181ad64c9919cf41d714a1a9a5e2bb26baf8770b2eba77b778a332677a7572ee3a2b1dc05f7356bdcae5f55e35329e34caa79430b270c036160dc9fcaab5b254543ac94b24681f17172b6159d16621d7ad0eebd895a1e1d09b916a86fb48e4c91661057eee95c0870ed54: +14383e6e5604c99c248d39be51d164b13442b05e51d78ecd999364221a45036b2fc16138220ab74b3bd446f8a714b58d5463d40d4367925007474c5b9e35d494:2fc16138220ab74b3bd446f8a714b58d5463d40d4367925007474c5b9e35d494:c4753b7f7a6f6dea2515c6e3d29561506f4f36e0de84999221f228e20bd5128ed93bdb8d1193237d8e294169a2bc448af9dd36066301efb7fe1231353c0623ffe1115debb6905ac6946ee382a27c3c09e1b1f5c11493dba37da0ff6eea75d9fab0ee926d701dac2fc5b7ef578880a5d5eeecadc1f4bcc4cd4ec6f2f14f52a8c164072e6fde5ab2ee9cee0b48e51af055f9fec7c63750fedf72332b23863a1e54c52b461a21506dfdfc63880e22d89c894412666c929821c0e439e745415f717969e6058554d64b947a4fc9d16acae3e49aec08801a09d972f79ead68d529768069735caa742b45a5830581b80ca061a6c1515e3f7d5a9337878c19fc94eef22698ea6c4d05f9ed411b6b8f052b5ff15dc23a64beeaae99f84893de3df940a4e0b8e993930139052d99be47bca8775f8563bd4026b71343d51968f2337528f4c9db8bbd0a298af04b27695d86b7f7ba6c4ccc6273febcd8f75cff266995244fc1fa13d8d843f0bff49cc2d508f4a2b3aad1d95fb22a2bc6ad1b966b0812d99070bba07c923ee4d08107486dc01a06dba6f1d5f105aceade33b166510e427ebbce52a3e7831f0f78a3c6e072608334d8021c338a73cc0c47f19c9fae403b9716d0d15fbdf6466b08f6acce3f50a703b1dea8d826df842ca1ba20d29f4548acfc754cf011f570681b59e4da25385ebd6d5c3adc930529e166ce6705f6010210db106462b3333204e7adadee6606a56206b47eef2074b116e22a615418ec2cdc331f1e19e07e8a37b92d69df0734e085daeeb901ec6e8c35f103f1d86ef0d2a2652b01d183597e4cfdeedfe5df9a7ef66a1c796a37a27113b944dd7ba17c460015ab8ace451c57850ec6c290c54e5113f55e99a8e6e4711e3b7817bf91a5adb37fb9461be6b1b55d586046e42a54c5def4076f1ff6c31b806fc602474356aa2899eae70f5e5abf1f75a7f24c134cde11793bb162e03a583d5be046acc73456d12d509d92f7705768686f6c714a4e57ec88b71398e23e835d6d6547225996b7ed08f3b7443bb17c899409493d0efe8455bec8e8c284a3b149a5b4ca631ea620b1bb817cedaba50b044411849d260a6f2a0d3f2cceec3842719a5ea4fe18dde0d42dcb33ad21e6453325af6f3c009f2bb978d30ceeae9aa4928bf73767cda9292ab893ce5fa3aa4c232163b45c64ed7977779b1c0cafcfc2b9fa084a324f113adeec218b4735b6b464db6d46c2791af3455f1ca5ea1e9a048c051a54dfa0:45e8ed1a751dfc3b9b7bd7a10bf5bdcf8ca461865a490c105f10452941cf87721214bfbf3a35606b7ce35d6f70aaf2d5eadcc0de035e9b2f6d7b862fc2849004c4753b7f7a6f6dea2515c6e3d29561506f4f36e0de84999221f228e20bd5128ed93bdb8d1193237d8e294169a2bc448af9dd36066301efb7fe1231353c0623ffe1115debb6905ac6946ee382a27c3c09e1b1f5c11493dba37da0ff6eea75d9fab0ee926d701dac2fc5b7ef578880a5d5eeecadc1f4bcc4cd4ec6f2f14f52a8c164072e6fde5ab2ee9cee0b48e51af055f9fec7c63750fedf72332b23863a1e54c52b461a21506dfdfc63880e22d89c894412666c929821c0e439e745415f717969e6058554d64b947a4fc9d16acae3e49aec08801a09d972f79ead68d529768069735caa742b45a5830581b80ca061a6c1515e3f7d5a9337878c19fc94eef22698ea6c4d05f9ed411b6b8f052b5ff15dc23a64beeaae99f84893de3df940a4e0b8e993930139052d99be47bca8775f8563bd4026b71343d51968f2337528f4c9db8bbd0a298af04b27695d86b7f7ba6c4ccc6273febcd8f75cff266995244fc1fa13d8d843f0bff49cc2d508f4a2b3aad1d95fb22a2bc6ad1b966b0812d99070bba07c923ee4d08107486dc01a06dba6f1d5f105aceade33b166510e427ebbce52a3e7831f0f78a3c6e072608334d8021c338a73cc0c47f19c9fae403b9716d0d15fbdf6466b08f6acce3f50a703b1dea8d826df842ca1ba20d29f4548acfc754cf011f570681b59e4da25385ebd6d5c3adc930529e166ce6705f6010210db106462b3333204e7adadee6606a56206b47eef2074b116e22a615418ec2cdc331f1e19e07e8a37b92d69df0734e085daeeb901ec6e8c35f103f1d86ef0d2a2652b01d183597e4cfdeedfe5df9a7ef66a1c796a37a27113b944dd7ba17c460015ab8ace451c57850ec6c290c54e5113f55e99a8e6e4711e3b7817bf91a5adb37fb9461be6b1b55d586046e42a54c5def4076f1ff6c31b806fc602474356aa2899eae70f5e5abf1f75a7f24c134cde11793bb162e03a583d5be046acc73456d12d509d92f7705768686f6c714a4e57ec88b71398e23e835d6d6547225996b7ed08f3b7443bb17c899409493d0efe8455bec8e8c284a3b149a5b4ca631ea620b1bb817cedaba50b044411849d260a6f2a0d3f2cceec3842719a5ea4fe18dde0d42dcb33ad21e6453325af6f3c009f2bb978d30ceeae9aa4928bf73767cda9292ab893ce5fa3aa4c232163b45c64ed7977779b1c0cafcfc2b9fa084a324f113adeec218b4735b6b464db6d46c2791af3455f1ca5ea1e9a048c051a54dfa0: +59b07263b22c0a38bbc591059594b2bd927e805961dd07e1f94245b23aa2e0160b1e4cf5aff278ec65b405f5108e1b5b18a969ad1f1e6381912c82d698907cba:0b1e4cf5aff278ec65b405f5108e1b5b18a969ad1f1e6381912c82d698907cba:08ce0d4db5c2aa500a19efbc8dc8549250f7dd46a7a9a5407417b3d51820e4b0d61275583f56f897fd942bdd7311ad6baf738128567af6558d75906a02c4343a9955d59b11088c588dc7dd08f67965c5602a56928dda4ae164293163b517ca17ded04fe4ab2f9789130ae96ab231f07e09015b78f3848cef435db0ad9f35e0fbc9851e3ecfc9fb186d14d8da4dda45d0b3eb3ee4500c101e3194b572140689cd75da1287b254f374e3d93326ae5faf114018ac714bd00375d92a8bb659c32912831f4f20776e9e2c25029f0aff39fddac7241543a0366b84de7b1ff23e8e4dc093df0d2dd5e53e6847948cf3d0ff3f564ad94d9cc00a5ea5b695e408bf50f5bab2f6ea87ba8ad3a1940195cf1bc2b5b34847ad3a5effb8a7823de91ef1633869d1f04643af4d826a59e78b9d186312b3d972263654ac5587b80b717646f31003db81ac70860d3fc8cd3a6a0a0d576d25731ef7b8966263d7a05b55009e8a23dac0f9a21a24b06e13900e444446fdfe56cbc1a026df41066b201b1481e56158926c0c9ea90f0c645aab4bef12d4e072cbfdc3c3d5e0c72cf88f166de048874f3534e040c62b1662821bdd16b0e8582817461cb2689279b446d70c8ac20ad03e598cad4908c52c350d4243ee8aedb87a4af977f7db57cd947b47d6bb51409d80d81f6db03cb9a6a6b79812f470690afc1836a531338094cf26d3c1232fd5605d8f8c55b6f8a2a7ef1e0c78155594b237956d2abad6a9adcd58e11ccd35cc995b9a0aecbf7f5741ac051b04ef6b9744b56fccb46398528bb31fbe84e078843e69bf338898cdef69ad41872395e46b593904825547e00bdaf221f8fa587ea2037ffb9ac9307dd3f8f35ec5386ba966333e2ac8727b0e1b80612d3c7f2cb88baacadfe2163bc38c88842e76a394571d40610e8a297602793763296e3eabf720e984b2edd28cf5c4e0f9a0f76aceba28cc1f1b69ff1d35b4bd3347b7f9a95a4c1ea10734e1c918eb96249d0cc70b477f6f23809bbda901d53f485a71f5086002c1b71efcc41cb1aeb5122a3f3bfc96c51a55d75c02984288be657887854cfa738974bcd5440146f9bb14040de54f5444ad43b79af9bdb24ed6a48eb2fdeed71f31f0ece102e918e95635c7a038633ee348d8b5781652d5059d215ac97f30ea20d277ebbf15246905428a7bec02b8f926315bad6723fd64d71fc95f333364cbe90d4646333c40dda6d1d433b7c195a758dbb4038af5dcc7232d4547f540e394:886da33e3553285ea59c1431b6e86ea49bb68b2e0efd2b157e7791b74f35a2421bb359f3dc1e4ce5f11f73652e03bfc0b429c58f0f2d7418c7c20bce2e2d190108ce0d4db5c2aa500a19efbc8dc8549250f7dd46a7a9a5407417b3d51820e4b0d61275583f56f897fd942bdd7311ad6baf738128567af6558d75906a02c4343a9955d59b11088c588dc7dd08f67965c5602a56928dda4ae164293163b517ca17ded04fe4ab2f9789130ae96ab231f07e09015b78f3848cef435db0ad9f35e0fbc9851e3ecfc9fb186d14d8da4dda45d0b3eb3ee4500c101e3194b572140689cd75da1287b254f374e3d93326ae5faf114018ac714bd00375d92a8bb659c32912831f4f20776e9e2c25029f0aff39fddac7241543a0366b84de7b1ff23e8e4dc093df0d2dd5e53e6847948cf3d0ff3f564ad94d9cc00a5ea5b695e408bf50f5bab2f6ea87ba8ad3a1940195cf1bc2b5b34847ad3a5effb8a7823de91ef1633869d1f04643af4d826a59e78b9d186312b3d972263654ac5587b80b717646f31003db81ac70860d3fc8cd3a6a0a0d576d25731ef7b8966263d7a05b55009e8a23dac0f9a21a24b06e13900e444446fdfe56cbc1a026df41066b201b1481e56158926c0c9ea90f0c645aab4bef12d4e072cbfdc3c3d5e0c72cf88f166de048874f3534e040c62b1662821bdd16b0e8582817461cb2689279b446d70c8ac20ad03e598cad4908c52c350d4243ee8aedb87a4af977f7db57cd947b47d6bb51409d80d81f6db03cb9a6a6b79812f470690afc1836a531338094cf26d3c1232fd5605d8f8c55b6f8a2a7ef1e0c78155594b237956d2abad6a9adcd58e11ccd35cc995b9a0aecbf7f5741ac051b04ef6b9744b56fccb46398528bb31fbe84e078843e69bf338898cdef69ad41872395e46b593904825547e00bdaf221f8fa587ea2037ffb9ac9307dd3f8f35ec5386ba966333e2ac8727b0e1b80612d3c7f2cb88baacadfe2163bc38c88842e76a394571d40610e8a297602793763296e3eabf720e984b2edd28cf5c4e0f9a0f76aceba28cc1f1b69ff1d35b4bd3347b7f9a95a4c1ea10734e1c918eb96249d0cc70b477f6f23809bbda901d53f485a71f5086002c1b71efcc41cb1aeb5122a3f3bfc96c51a55d75c02984288be657887854cfa738974bcd5440146f9bb14040de54f5444ad43b79af9bdb24ed6a48eb2fdeed71f31f0ece102e918e95635c7a038633ee348d8b5781652d5059d215ac97f30ea20d277ebbf15246905428a7bec02b8f926315bad6723fd64d71fc95f333364cbe90d4646333c40dda6d1d433b7c195a758dbb4038af5dcc7232d4547f540e394: +5cc115d839e058cdb6518ee9c161c004d88bd3908d3cf6d52c8f296a1a076b9b1e8f3305bf2fa11b17d92416ab0ea762396d88f2f970ef0b100ed3bf5cc13440:1e8f3305bf2fa11b17d92416ab0ea762396d88f2f970ef0b100ed3bf5cc13440:533e49c1d5f33c5ec4be84c619f4ec649c25fd70bdcfe257a63c3373a4d089c89af6eeb7160dd77ab66b1ee7e10850ab4fc1f35132332b53789b2b0140c4f20f97f2142072d624aff7aad324aacd068c035aff52fa712f4e74832de031b2642314d17110dee6fb85762dc30d7e97782fd1fbff7179f00917f55af7503a5b7e23c6eadb65e104f1517b6624c9e5204b3fd29a6585e92ce3a3eee2c5ae177920f7b4ab2cac87d672ab6baac1186d904aea3498534eb5ab23e4ac4c0ddb0d82a5ae531d76549d367628577bac4235e897d9fe205522047d214ff6ccf311c4e397827d97f2868e70ac17d28e334999744d359376a482fdcb414b02b2687b962ee8086e573fe000dc51dee06879c684e25f94cee5e861347e7be7fca549a0f765136a2f4b88fede07024dd2fce1f6d0c0354da1a16ef366b315b3f7233031f979b70eac6e23bf3b349efbd0e4f53f4d5c41fc004276a59670659f6905ef03d2fc098d589fcbc1328282fa22b10db83c5d70865994fd19d760a39d476e02330d2c6d19e742267dd365bbe1fe5c711a95b184508ce48c1c96d7e63990b408d45089be79e32f9cb0162fd1e7d0d19d97d0ae78ff824cc6989486c0bd038352551f37499e9e9826804e9d2624ad0c7b7534560f45fd7d324b8e517e01c9b2743c14979cfd512bc3fe667279b3a277fb463e9d7349b64ffc9fe60884c21e481081ed70e6da5a3539c448971f0d9787289fcb0080f219e99449f8298c42475f87fd10aeb509c530cf6a57748eb8f3562161fa4875ea953f09659c7df7a9950f0317467cb4e5366e196e32f5e2696733a25eacbde49210490762060ea231370d4090429bb06bb867399e8d37bf5d21a0e72147e496cf3b7dd6fe6e5edea9668d802190a91c600e29523f8eb904e48b70412bc10a7020984c5ff0f5f383f214ae594dc85971e480372848d0d7e7cc5c18ff88ba9b262d7884698a41c6c7819c0319fdc6bb07b91dc1694dafe3af37a538bf2b2d8cacb27d24cdc6eadb8c6a2e6b7df8a4654ae937850c890ad930980afcc1492db8a0168cbc9f10657eb48d2ac87f5175d23caed4b5e6f10bbeaa5e33fc5f6418d63ba374ab1a3cbd36b729ddbdaba989d4645e3a66130bae417cad086dadd30843352514c375f2571abaf93e9a0771fa103ae92585b04f55c434769b43d6d22f753f9306036e53524f6f4d9ccbd2c30317a8e899f316149035894da945b76d9082bfee328e7a31b66328ee8b94e068c7:0371c2d64c5ec0c8276ca5ffa615eff42f9efffc58dd8ecfcf67620a9bcb38faf118932bf2cd5b9205fa551334df2a757c597744f791f371fbedd98b21f73405533e49c1d5f33c5ec4be84c619f4ec649c25fd70bdcfe257a63c3373a4d089c89af6eeb7160dd77ab66b1ee7e10850ab4fc1f35132332b53789b2b0140c4f20f97f2142072d624aff7aad324aacd068c035aff52fa712f4e74832de031b2642314d17110dee6fb85762dc30d7e97782fd1fbff7179f00917f55af7503a5b7e23c6eadb65e104f1517b6624c9e5204b3fd29a6585e92ce3a3eee2c5ae177920f7b4ab2cac87d672ab6baac1186d904aea3498534eb5ab23e4ac4c0ddb0d82a5ae531d76549d367628577bac4235e897d9fe205522047d214ff6ccf311c4e397827d97f2868e70ac17d28e334999744d359376a482fdcb414b02b2687b962ee8086e573fe000dc51dee06879c684e25f94cee5e861347e7be7fca549a0f765136a2f4b88fede07024dd2fce1f6d0c0354da1a16ef366b315b3f7233031f979b70eac6e23bf3b349efbd0e4f53f4d5c41fc004276a59670659f6905ef03d2fc098d589fcbc1328282fa22b10db83c5d70865994fd19d760a39d476e02330d2c6d19e742267dd365bbe1fe5c711a95b184508ce48c1c96d7e63990b408d45089be79e32f9cb0162fd1e7d0d19d97d0ae78ff824cc6989486c0bd038352551f37499e9e9826804e9d2624ad0c7b7534560f45fd7d324b8e517e01c9b2743c14979cfd512bc3fe667279b3a277fb463e9d7349b64ffc9fe60884c21e481081ed70e6da5a3539c448971f0d9787289fcb0080f219e99449f8298c42475f87fd10aeb509c530cf6a57748eb8f3562161fa4875ea953f09659c7df7a9950f0317467cb4e5366e196e32f5e2696733a25eacbde49210490762060ea231370d4090429bb06bb867399e8d37bf5d21a0e72147e496cf3b7dd6fe6e5edea9668d802190a91c600e29523f8eb904e48b70412bc10a7020984c5ff0f5f383f214ae594dc85971e480372848d0d7e7cc5c18ff88ba9b262d7884698a41c6c7819c0319fdc6bb07b91dc1694dafe3af37a538bf2b2d8cacb27d24cdc6eadb8c6a2e6b7df8a4654ae937850c890ad930980afcc1492db8a0168cbc9f10657eb48d2ac87f5175d23caed4b5e6f10bbeaa5e33fc5f6418d63ba374ab1a3cbd36b729ddbdaba989d4645e3a66130bae417cad086dadd30843352514c375f2571abaf93e9a0771fa103ae92585b04f55c434769b43d6d22f753f9306036e53524f6f4d9ccbd2c30317a8e899f316149035894da945b76d9082bfee328e7a31b66328ee8b94e068c7: +75a503f48ffc221617672519111bf90da39da9eab2e2914fd3755f10f5393668f680cc0f6358cdcf537aa71128cfadfc0f3a89c100aa34bcd2427e248b6ed50b:f680cc0f6358cdcf537aa71128cfadfc0f3a89c100aa34bcd2427e248b6ed50b:7b01090423236cb4b13c4177fce52a7ff6580588cc2eb5a3f39ff5d0c73e01e01bf7bd74afe4151250c391426ea507271bea1d6d85f0b2fe35c40500f98d0656c6388fc9efba1837db22dfa29d892676f50e575fe89fd29389d09d080bad67ba544cacabf5a7738237c55e2875ed4916302a2b4dc496e74273bf05191137810e50e48195260bab6d81f9c80562ee73ccb9333cd9b61daf5b0038a4e6c5c958a91f68508c1d882519c1aa4ffcc53562463a0ae30163696f84b97ccbd8679820edd3617e7b896eeffe341ec6b5b03f73b625d741c655fe6e82d11d478a7d543ff6c0fa3a3a8c94a616fb847070d1fbdde6010f026b089cd863c3bd29b1c4269f77659e515728890c973be87f0b833ca5af6b4c3133ad4fa4f91655c6adb5b7235c27fe348284f3f13366a6a03ad22b87c6f5584bdeaea48c70325d6e33a475f50511063875192a87edc388089b84395390c2a3ad89a22595dc4a715a42a2c0efdef67b354b34fc75ca98df913e759e51c7f625ddd598ac22d421decb57bebd54220ec6daa5ece769d2e01be7b6bee2ff5a0b06b32d6da1d7bc057e3abfaab242a3f7e6646a159e4f505e4662982b13d0cc1fba91d10309a42dc1087cf10d36e31f170615a0acb508bf683e2de00c87640d304a947bc4971ff3619c72abd83c7b2cbb3464c4040c2662b58508b74680cfa6de06e8d21e3bec8511199312680009071f706b7b133a2487d5745ffadd5dc0eb2b553df440787f011dda37719fa71315e8b291efd77da3ba14fb995f03571a3db522b63c60be5619941699b39222b59d0f23e5eb37ead4b7f750ed4abf4db87c70da665bef4d7a2921b2c99897f2321c9be6075e744c8228639ab736dbeb2beab440c156a39a2efd261db50855e304d9cfeb99141c613558109f21474d272a2d906d4893934aff8e08a4fcee964a5cd00732fd33af29849c8dfca65979421857185cf629f86807a85973d3440a6bf811a58d041387249811ec047e5e8b343b2387d0181e0d0bd461ef10e8164aae357d9b29dc0ace3ec6d743ae3454ab9f842a28d5710217dffe50344e8d932f1801b0e8f966198ef1c9cc6969f34734aa6a63aeaab4339f75d34ffa8acb937ed9c73092a309a9b84a25011e3114c265e4f602337eb699b5a22d572b03e4dad03b0461c00db9679b72fc5b493ef4486f85535d813a58080385afd4e8d871828034334bfe441d18984e4dfcde024403b5ae66cc50a47301b57f9a32f740bdc7ff1d:df28e3e630360867864bc41e43fd7ddeb52876dce9b234a3fcc3d8549db0112e176390a685ebd484936e25c08c8a3878a37b3c4e239ad0a0e5019937ffbcd4077b01090423236cb4b13c4177fce52a7ff6580588cc2eb5a3f39ff5d0c73e01e01bf7bd74afe4151250c391426ea507271bea1d6d85f0b2fe35c40500f98d0656c6388fc9efba1837db22dfa29d892676f50e575fe89fd29389d09d080bad67ba544cacabf5a7738237c55e2875ed4916302a2b4dc496e74273bf05191137810e50e48195260bab6d81f9c80562ee73ccb9333cd9b61daf5b0038a4e6c5c958a91f68508c1d882519c1aa4ffcc53562463a0ae30163696f84b97ccbd8679820edd3617e7b896eeffe341ec6b5b03f73b625d741c655fe6e82d11d478a7d543ff6c0fa3a3a8c94a616fb847070d1fbdde6010f026b089cd863c3bd29b1c4269f77659e515728890c973be87f0b833ca5af6b4c3133ad4fa4f91655c6adb5b7235c27fe348284f3f13366a6a03ad22b87c6f5584bdeaea48c70325d6e33a475f50511063875192a87edc388089b84395390c2a3ad89a22595dc4a715a42a2c0efdef67b354b34fc75ca98df913e759e51c7f625ddd598ac22d421decb57bebd54220ec6daa5ece769d2e01be7b6bee2ff5a0b06b32d6da1d7bc057e3abfaab242a3f7e6646a159e4f505e4662982b13d0cc1fba91d10309a42dc1087cf10d36e31f170615a0acb508bf683e2de00c87640d304a947bc4971ff3619c72abd83c7b2cbb3464c4040c2662b58508b74680cfa6de06e8d21e3bec8511199312680009071f706b7b133a2487d5745ffadd5dc0eb2b553df440787f011dda37719fa71315e8b291efd77da3ba14fb995f03571a3db522b63c60be5619941699b39222b59d0f23e5eb37ead4b7f750ed4abf4db87c70da665bef4d7a2921b2c99897f2321c9be6075e744c8228639ab736dbeb2beab440c156a39a2efd261db50855e304d9cfeb99141c613558109f21474d272a2d906d4893934aff8e08a4fcee964a5cd00732fd33af29849c8dfca65979421857185cf629f86807a85973d3440a6bf811a58d041387249811ec047e5e8b343b2387d0181e0d0bd461ef10e8164aae357d9b29dc0ace3ec6d743ae3454ab9f842a28d5710217dffe50344e8d932f1801b0e8f966198ef1c9cc6969f34734aa6a63aeaab4339f75d34ffa8acb937ed9c73092a309a9b84a25011e3114c265e4f602337eb699b5a22d572b03e4dad03b0461c00db9679b72fc5b493ef4486f85535d813a58080385afd4e8d871828034334bfe441d18984e4dfcde024403b5ae66cc50a47301b57f9a32f740bdc7ff1d: +d8aa2a0aa514fd845f7aa66b83c0eabb9c16023abc1695773450b2bb332522f2e4e8d6b298248c15fe08f87a3bc6084bf2d64d7f1e4b2d51599e9fad9cc91092:e4e8d6b298248c15fe08f87a3bc6084bf2d64d7f1e4b2d51599e9fad9cc91092:08deb3b832f52d6556f78c3f0abe46f1efe45e3d5d88e7f8edf803670ce4612921749e9ece63fdc9bef2ba483812bb622be744d40404fd6e09c9e1cb7ce19de81a9dadf556352ee89810c76a9b1047ac62b16ebb7da23ddc2d4ab76a020561d02d41b58b94953a23faafddd781b7dca7b7fbee706ec10a73125bf74436056bf3b4f2a0701cfef05bebd3dd8eef306c1ac1b00950881ff05ab5c8248ad1096ac91d526ae59ba0583b27db7d1e390f57a5889e2799a4a1519b15d93dbf0b21d450873c76ba520461e8bb5c83c9012eacd557bea640586efcb869007647d449f91ccd52afe3a89477de7c2b647ecc9bf967fbf5769d74889447d9522d9e8069c3499af6a8a1097a95d3bcc5f83433934484314cb30758b525fe53e90721df5cbe03d96f0d0f98521f01a5fbe57ce8804dbd18f8f5eac8f7dbb58c41789a44433f8a8d1245d2adda8c78d881c65ea661ab178d4fc2634cd6cb514ab6f2543e9112183f3ff73a3f450106b0ee8a347a80cb824ac1f80164e3bb5123698de0e747359ca35acaa3ba0c943beacd7a9bdf8ff73978e9fb002045e8fe5648cc0f9cfa88b0d812e81aa62e0d9c73fe613afd9539bcb615721fb497d62f65c83b87a6d2143f9b1c880ec8671bd42c8de957b1a68ee49226ff717ccc6e74f2eee49c30dea53fec3cd4d90f2cccd8f97c55d5c752454be2ba7b6ff2030be67e0df50c5e883843e71612f2b95359543e2ba1bf2e98debcf5768f2be6fd504d9783ce921a81e09416dbcf2bb655a924b1ef0112d671f084a5b690b0b64a8b9bf50333c359ff3fef199694f9b6292424f00666cef6d06d161a79e3a1b9b9629eea53505f5e36aeadfe0d759672b0ffe498397d90a55d9944b30541a7e1bdac53020640137dc252aef622f3819d36ab498d763e4327ba8580dd9f7e5f47c24cc9928734b7e62112c57e3e0cfedecdcbaccb0c45af8219455ee7223c71e7e20410c5244eb827af2f3935ce4755444747aa945f4c26db3a298519e75fc6bace91529972e8691b694d30aa8b5ec4c1a028d3bd10bd0c8a408fb7d9d703495553ecea598d0622dcc74de489ba7195cdae8d5cff9855921837b528433ee55c0b7090857a0c2784d9310b4825a7993ad9c6f18f83bca5cc6a25047168a8376b062e3a48ea90cad88e331187c2b6f281426f81f78804a895c4ec06c341fe846af4527ea26069dcf61d813fddf0fc43c707350bfb2fc1cffcee7d7ccd7d75f7a465a3d14d57302c146aba3e:146f65d43e715542894b7900a2f8cd4b17d3870a6100e37de005b0db5d8151246de4ee3842d3ebca20a5da22a363a7575e7a55128295f27211484af57cd5310908deb3b832f52d6556f78c3f0abe46f1efe45e3d5d88e7f8edf803670ce4612921749e9ece63fdc9bef2ba483812bb622be744d40404fd6e09c9e1cb7ce19de81a9dadf556352ee89810c76a9b1047ac62b16ebb7da23ddc2d4ab76a020561d02d41b58b94953a23faafddd781b7dca7b7fbee706ec10a73125bf74436056bf3b4f2a0701cfef05bebd3dd8eef306c1ac1b00950881ff05ab5c8248ad1096ac91d526ae59ba0583b27db7d1e390f57a5889e2799a4a1519b15d93dbf0b21d450873c76ba520461e8bb5c83c9012eacd557bea640586efcb869007647d449f91ccd52afe3a89477de7c2b647ecc9bf967fbf5769d74889447d9522d9e8069c3499af6a8a1097a95d3bcc5f83433934484314cb30758b525fe53e90721df5cbe03d96f0d0f98521f01a5fbe57ce8804dbd18f8f5eac8f7dbb58c41789a44433f8a8d1245d2adda8c78d881c65ea661ab178d4fc2634cd6cb514ab6f2543e9112183f3ff73a3f450106b0ee8a347a80cb824ac1f80164e3bb5123698de0e747359ca35acaa3ba0c943beacd7a9bdf8ff73978e9fb002045e8fe5648cc0f9cfa88b0d812e81aa62e0d9c73fe613afd9539bcb615721fb497d62f65c83b87a6d2143f9b1c880ec8671bd42c8de957b1a68ee49226ff717ccc6e74f2eee49c30dea53fec3cd4d90f2cccd8f97c55d5c752454be2ba7b6ff2030be67e0df50c5e883843e71612f2b95359543e2ba1bf2e98debcf5768f2be6fd504d9783ce921a81e09416dbcf2bb655a924b1ef0112d671f084a5b690b0b64a8b9bf50333c359ff3fef199694f9b6292424f00666cef6d06d161a79e3a1b9b9629eea53505f5e36aeadfe0d759672b0ffe498397d90a55d9944b30541a7e1bdac53020640137dc252aef622f3819d36ab498d763e4327ba8580dd9f7e5f47c24cc9928734b7e62112c57e3e0cfedecdcbaccb0c45af8219455ee7223c71e7e20410c5244eb827af2f3935ce4755444747aa945f4c26db3a298519e75fc6bace91529972e8691b694d30aa8b5ec4c1a028d3bd10bd0c8a408fb7d9d703495553ecea598d0622dcc74de489ba7195cdae8d5cff9855921837b528433ee55c0b7090857a0c2784d9310b4825a7993ad9c6f18f83bca5cc6a25047168a8376b062e3a48ea90cad88e331187c2b6f281426f81f78804a895c4ec06c341fe846af4527ea26069dcf61d813fddf0fc43c707350bfb2fc1cffcee7d7ccd7d75f7a465a3d14d57302c146aba3e: +de8f1c99e7f8556df20b59b8504cff7c6c5241a8aeeb30b92eab97bf481d0fe9e463791d0f567ee73abbf47dd57167a535613b05cd48d92ebc7d24e6ebff9573:e463791d0f567ee73abbf47dd57167a535613b05cd48d92ebc7d24e6ebff9573:38d93e5c9801db901797ec75c6dddc65ae7980de210bed43b33eb44cdc6dc9933fb6bec7421db10f0a59320b9e642a21f1dd235601fcd6c53be4a877f4fed3fa4a0ad4dc6e9b391bcfa434906925ba45ecc5b435d9ab8cfafc394bdcca9b07d5668393446e3400e9039435a1dc78cbc08807a3fb24ca8b19f64ea08b8bf6c20a195b51ff8015f3e7c91d08e4bc62415595a5a882fba651dc3a675187af618249747b4680d1d15a202ea9df48b1c214fd403466fd1a265f2defaf8ed5a6bf0eb08d1864f2a28e9472143c6fd103b6b108c0d1d1363b99f9202d11f02056c279cca315db1ab6d31018458f57ba3316cd2738e80c492d857cb1749925e331c65858b50983cd9838cfd2188a5e8f05b471fd3cddcd30d96901194020f115fb469ab5849006dffa2d543a13b3b506ed65cc457532b8aa3ee31d9d8d9e5298d7ac707ac15b827a578c81d434f84cb1b56120d667b2afe6d1530afddfb966d953be7e32df07de389e2d04b232d3512c7db9358fc944d1b118078e6999e891bbfa4a4329f65d807188b59858c431211b29576f4496138b7c0c128f7bef5f79b0f446fc6b4a0e20bca4c40a83571a36644abffabd49cb585fd064c8e509d9a0fcff462676f0ebcb61cec61e512be6f182abd59e09f642aa619634853482ece8f89800f9c5bcfb841431ca0691ed8d80e0a2fcb797a036897cfb6537586b31c00b7965efddfda72861845026459157f79eba1bcaf6cd41d618aeb1bd8da1be98f0cdc7f2e09b903de49c0c1be91dcc177b298096836dcea4f601dd86691555128325438bd9ccbfc0e777920ae8bbd57634c6104fe69a3a72012a2360b6e552550cffb4e2f0b41fe15537ee0e6f37e7880fb4d12bef6cad266ce58df9816b35960cd0bf8652862ee789ccc31a7efc21a81bda46146b111fcfd94f04856ab61a557b1ff7c8e4ea6d9c4bcdd93b151aa08461c568defb2aefdfce96394dc822d4ef6cc4b9a3e6c332039f6538aa0df8de8126d90c312ff496887486111565534346a7462625d63df69fcb5741906f19e00fc8003f08b95985c38b8674af423ca56de5f881b59c466243a7adbadba29caf57fa777122e61823b4e708182aaf37206d7d5ed051c12a5c0f6b4371043f562cdc029d5e1ba9b2bf5ffbf1f5f523db06feca427db7a08819ffb2d0585242e20da58e320b16b16e448d8be0ef7402d24a7194257133bdc982314d83adbcd12e8af31303426c59ffd8269ce4b987ca9b6f0ffdbb4d1d12:30abc4e4e4b388581e668bd409ee18a6ede81a136c28a2924df5fc00d7c280d97862ae3a67a935ce492364135e659adb5fbabe689816591f49ac5022a387cc0938d93e5c9801db901797ec75c6dddc65ae7980de210bed43b33eb44cdc6dc9933fb6bec7421db10f0a59320b9e642a21f1dd235601fcd6c53be4a877f4fed3fa4a0ad4dc6e9b391bcfa434906925ba45ecc5b435d9ab8cfafc394bdcca9b07d5668393446e3400e9039435a1dc78cbc08807a3fb24ca8b19f64ea08b8bf6c20a195b51ff8015f3e7c91d08e4bc62415595a5a882fba651dc3a675187af618249747b4680d1d15a202ea9df48b1c214fd403466fd1a265f2defaf8ed5a6bf0eb08d1864f2a28e9472143c6fd103b6b108c0d1d1363b99f9202d11f02056c279cca315db1ab6d31018458f57ba3316cd2738e80c492d857cb1749925e331c65858b50983cd9838cfd2188a5e8f05b471fd3cddcd30d96901194020f115fb469ab5849006dffa2d543a13b3b506ed65cc457532b8aa3ee31d9d8d9e5298d7ac707ac15b827a578c81d434f84cb1b56120d667b2afe6d1530afddfb966d953be7e32df07de389e2d04b232d3512c7db9358fc944d1b118078e6999e891bbfa4a4329f65d807188b59858c431211b29576f4496138b7c0c128f7bef5f79b0f446fc6b4a0e20bca4c40a83571a36644abffabd49cb585fd064c8e509d9a0fcff462676f0ebcb61cec61e512be6f182abd59e09f642aa619634853482ece8f89800f9c5bcfb841431ca0691ed8d80e0a2fcb797a036897cfb6537586b31c00b7965efddfda72861845026459157f79eba1bcaf6cd41d618aeb1bd8da1be98f0cdc7f2e09b903de49c0c1be91dcc177b298096836dcea4f601dd86691555128325438bd9ccbfc0e777920ae8bbd57634c6104fe69a3a72012a2360b6e552550cffb4e2f0b41fe15537ee0e6f37e7880fb4d12bef6cad266ce58df9816b35960cd0bf8652862ee789ccc31a7efc21a81bda46146b111fcfd94f04856ab61a557b1ff7c8e4ea6d9c4bcdd93b151aa08461c568defb2aefdfce96394dc822d4ef6cc4b9a3e6c332039f6538aa0df8de8126d90c312ff496887486111565534346a7462625d63df69fcb5741906f19e00fc8003f08b95985c38b8674af423ca56de5f881b59c466243a7adbadba29caf57fa777122e61823b4e708182aaf37206d7d5ed051c12a5c0f6b4371043f562cdc029d5e1ba9b2bf5ffbf1f5f523db06feca427db7a08819ffb2d0585242e20da58e320b16b16e448d8be0ef7402d24a7194257133bdc982314d83adbcd12e8af31303426c59ffd8269ce4b987ca9b6f0ffdbb4d1d12: +0736f801720a947c5c2f3258ce0d511c3e17e94e37b30adfa52095921171d4004f694255920d0c38de6e72e165c33aee76b1cbf6f4837aa5901475667acd2826:4f694255920d0c38de6e72e165c33aee76b1cbf6f4837aa5901475667acd2826:7f87b51f6ead2d4402a3bd3c3769a267ac8e82f779ad7b986dec82cbfc1ea51291884326d9226967cb66a96873184f0e83b3ab25a5ab2fa805fe3a0e7b190a622d461b7830a3f697c831c29ea7c0cd4b68d8e77aa69711cf864dc1d5394f4845e2fbb5076404e09a88b79f05670551bce2ef5468b79d57888b9852a4bb479a4fd0beb681fd523fc5bf4458abbc38ece72e106e00222015a57ebec55bf47513e25c3c4554843bdacbcfe9f1b8d0ae354e48d03fdebdf20d655b5268d8bbbf33b1288910f0444fcd56c0da7b8903362b7e37a864654277cffbe6c60857f0b3514d22a40b9dd2d3fe5caea5507a0de3051bb3a4015fa0fe4c462b98fef2357dcf6b97dc75def382f901f96f4a04a3efc60254200a2c4cdc8a58b25d94e32954eaff1511ac46e3606663b6875f136499da6a769097879a6e0834d564fa7fdb99581183ed0c9d48fd195d7ecd9f4dd4865565fd17a008718dcd76f68a54e516a2b730ed3dba5c2cf40630bbfe7fa03bb7cdd967695495a7c86e2e84cb017ec69601924631595affaa8cfd048d14267c73e54cfa539047e717691e399737fa50cc4844961257c93d7253d23226b7cd0d1bd31f3f0d2d892d073d8c5073c602f61a04d6437c3903eb4a64a01fbcc0c7e159201cdc4aa42ef3b1ff9c78fc275cfb11a05ffed8f9f22d85ba924d8d32231c254d898da7f0679a64cab84026906e9e85f95efd8ee2a1725633f4de2ba67d99aa7f0550af139e9f8c5293786727d82630296d5daa9e830aa1b3b5b302b8b662ac832e9213016ba493a03a28cc3e9540d0d65acddbfe1252b5c16a84a445ce75415c6cd8ab16fe5eef117097d71eb5676b9a95b35882a7c3506bc5d02f03910a63d46846b213c3c9bb2fc34e6c69017d2065a1ad3ce3fd14ab0014f584e57ea9d903e40aceb230a8693fa2e63641c25438ff7a1638760438844cdf001180f5b177be69edf7ef66b39312805214cb17706cefe545be5a77019a5ec52bbf78850fa3d97de2d4d74aa68b58ca812a1b156a0c4001129f067232a6ec91a5ed4270f2a4c6efeee787004770c859e450e837efb04dc998bd273c27a09855e4eca1a22a9b88c17bdbf253a79761070a76817a7f74ff3f07fb718bffa0b4f326f284e62f836832427be82f483373515b9bf59af4a76a57e2f40b91034dd568ec14ac10e2309b87e2922f9cd9fc1a46a47ed3bc7e1b9feb9ee067073fa5dce2a67530526de67ee0e509663c44467eeb59420103ebcdffa709:c03c0314851279edcde970c23efa236f235eda960d2c27d3ca946f650c200b4eba04be668ff62eaffa6cea351abdfc54401dccce3dba78004aec9581a2ccf40f7f87b51f6ead2d4402a3bd3c3769a267ac8e82f779ad7b986dec82cbfc1ea51291884326d9226967cb66a96873184f0e83b3ab25a5ab2fa805fe3a0e7b190a622d461b7830a3f697c831c29ea7c0cd4b68d8e77aa69711cf864dc1d5394f4845e2fbb5076404e09a88b79f05670551bce2ef5468b79d57888b9852a4bb479a4fd0beb681fd523fc5bf4458abbc38ece72e106e00222015a57ebec55bf47513e25c3c4554843bdacbcfe9f1b8d0ae354e48d03fdebdf20d655b5268d8bbbf33b1288910f0444fcd56c0da7b8903362b7e37a864654277cffbe6c60857f0b3514d22a40b9dd2d3fe5caea5507a0de3051bb3a4015fa0fe4c462b98fef2357dcf6b97dc75def382f901f96f4a04a3efc60254200a2c4cdc8a58b25d94e32954eaff1511ac46e3606663b6875f136499da6a769097879a6e0834d564fa7fdb99581183ed0c9d48fd195d7ecd9f4dd4865565fd17a008718dcd76f68a54e516a2b730ed3dba5c2cf40630bbfe7fa03bb7cdd967695495a7c86e2e84cb017ec69601924631595affaa8cfd048d14267c73e54cfa539047e717691e399737fa50cc4844961257c93d7253d23226b7cd0d1bd31f3f0d2d892d073d8c5073c602f61a04d6437c3903eb4a64a01fbcc0c7e159201cdc4aa42ef3b1ff9c78fc275cfb11a05ffed8f9f22d85ba924d8d32231c254d898da7f0679a64cab84026906e9e85f95efd8ee2a1725633f4de2ba67d99aa7f0550af139e9f8c5293786727d82630296d5daa9e830aa1b3b5b302b8b662ac832e9213016ba493a03a28cc3e9540d0d65acddbfe1252b5c16a84a445ce75415c6cd8ab16fe5eef117097d71eb5676b9a95b35882a7c3506bc5d02f03910a63d46846b213c3c9bb2fc34e6c69017d2065a1ad3ce3fd14ab0014f584e57ea9d903e40aceb230a8693fa2e63641c25438ff7a1638760438844cdf001180f5b177be69edf7ef66b39312805214cb17706cefe545be5a77019a5ec52bbf78850fa3d97de2d4d74aa68b58ca812a1b156a0c4001129f067232a6ec91a5ed4270f2a4c6efeee787004770c859e450e837efb04dc998bd273c27a09855e4eca1a22a9b88c17bdbf253a79761070a76817a7f74ff3f07fb718bffa0b4f326f284e62f836832427be82f483373515b9bf59af4a76a57e2f40b91034dd568ec14ac10e2309b87e2922f9cd9fc1a46a47ed3bc7e1b9feb9ee067073fa5dce2a67530526de67ee0e509663c44467eeb59420103ebcdffa709: +fa75650491047428d363b5822222122dffb5a9fddc603c33c8a608618375dcf398c9641fa9dfa8ea13e0d1c716b8679e264be15dd2d4c06ab43cbee47916ee01:98c9641fa9dfa8ea13e0d1c716b8679e264be15dd2d4c06ab43cbee47916ee01:f54e41b939e37df17c7d6043fded14a915d934e867c345269fdc0177f5bd10c4348f319e0ab9a64cc0b7d4e0c91ca9aadaab2edcba544f14ed2cb539ca8975097d87927095b4ebd490344340061ed93c38167edaa096a230db59624c67fb9a1e1ddac402133f4d47cfc11e2fae6b3f3c5001cba9a8aed90073103240227e716ff71bf68a591ba2ceff2d31b86ef21ab012eccd409ad5c29d659a1b37c4d85505304140fb2c3437a206868b1352c102bbfa3b9a76522a2bfc5406b257696de74ee7d315c8e99caa96bd838006c6da2a4233315a856acb8e80c33168b333551d91d074055734130bd7d14c56811ebabf7d5a250e6072593d9f2f8b97c12a703c2c479cb0b15b7a2775c9dcd2ca4624672368a2e6145467f3be6615f93b8120a0a12da1560663a26a61731966b44b299ebfad2a95c62360f39ce05d9558e305ee23a52fa5ce20f6be5e262aff3a864d5ddabe23ff943f71d5998493d99fe2ac2374b464a69183c3bc4f1ddb883611149d7ddbf1e8380b544335e2b89395054c9f2558dfc56ea93ff14d0f15d2e0bd8937a556387de96e418d8b3a7d666fb190364b2c2190d3c25f1752d5483dcbb5960064f0c87fcf8f313d28781c114a169b690a8701c50d89c77324531c0f849dbad1633d925acd06c16a9cea19a434ebc42aebb1fdb9b0bacc93cec39919943664ea1a958406ff9e4935c92ca7c39708f9cab710a583096b4ed9f48d9e090647240d76eccbaba591f55fe7e36d72c21727acba0f8030954e62bc580b8b670c4457c3403e369ac20e660d662f7f6a414213ea43f7c0105009c1de817adf6ffd9cca3b45a63a822281c6e2772fd7b7809603184b4879b18c887903f0fc8d8e1e2dbf6e772f0b2d9b8a29927acc81714a2256ad8d7b7330527d7dbf8befd82f8c9bb401cf0a90249a64ca6f8833db31bd03b9e7946d06dd04383d7c082d70aeb37ff84c2b057d973b894b4a03ec7bf031aea656a1908488894a4ada3fd7fadf91ede9550d38415f82a09455c0f432fb55987132f00042afd60ea51d1f1c6c1afe0cf87c346e31e63e26f49b137177b2d47ab30f07cea071931274cf010836d683fff3be7134c78b8bfd8b1b8fc2049e18ccb1e18a0a9585a7d8a1e25492608668c96d62a0aca8ef90e048d20378c108d06b03fe3ec4adb27528ae08f7ded9487893ae64ca4b939202aa4c17afe718cdca49ff9616d0cdf8334b6aee2d6d20947ca4bd7df531dd1da99581ff72ea56fe62caa2c95e3587:1effbf9299a1b9354fe1f1dec1766595ea767ab8e4da9bb57b4f69bcbd8cb3d86f768392f59b39fafa8a210a6509fe0d6008d6356111adfb3799c1d559c26309f54e41b939e37df17c7d6043fded14a915d934e867c345269fdc0177f5bd10c4348f319e0ab9a64cc0b7d4e0c91ca9aadaab2edcba544f14ed2cb539ca8975097d87927095b4ebd490344340061ed93c38167edaa096a230db59624c67fb9a1e1ddac402133f4d47cfc11e2fae6b3f3c5001cba9a8aed90073103240227e716ff71bf68a591ba2ceff2d31b86ef21ab012eccd409ad5c29d659a1b37c4d85505304140fb2c3437a206868b1352c102bbfa3b9a76522a2bfc5406b257696de74ee7d315c8e99caa96bd838006c6da2a4233315a856acb8e80c33168b333551d91d074055734130bd7d14c56811ebabf7d5a250e6072593d9f2f8b97c12a703c2c479cb0b15b7a2775c9dcd2ca4624672368a2e6145467f3be6615f93b8120a0a12da1560663a26a61731966b44b299ebfad2a95c62360f39ce05d9558e305ee23a52fa5ce20f6be5e262aff3a864d5ddabe23ff943f71d5998493d99fe2ac2374b464a69183c3bc4f1ddb883611149d7ddbf1e8380b544335e2b89395054c9f2558dfc56ea93ff14d0f15d2e0bd8937a556387de96e418d8b3a7d666fb190364b2c2190d3c25f1752d5483dcbb5960064f0c87fcf8f313d28781c114a169b690a8701c50d89c77324531c0f849dbad1633d925acd06c16a9cea19a434ebc42aebb1fdb9b0bacc93cec39919943664ea1a958406ff9e4935c92ca7c39708f9cab710a583096b4ed9f48d9e090647240d76eccbaba591f55fe7e36d72c21727acba0f8030954e62bc580b8b670c4457c3403e369ac20e660d662f7f6a414213ea43f7c0105009c1de817adf6ffd9cca3b45a63a822281c6e2772fd7b7809603184b4879b18c887903f0fc8d8e1e2dbf6e772f0b2d9b8a29927acc81714a2256ad8d7b7330527d7dbf8befd82f8c9bb401cf0a90249a64ca6f8833db31bd03b9e7946d06dd04383d7c082d70aeb37ff84c2b057d973b894b4a03ec7bf031aea656a1908488894a4ada3fd7fadf91ede9550d38415f82a09455c0f432fb55987132f00042afd60ea51d1f1c6c1afe0cf87c346e31e63e26f49b137177b2d47ab30f07cea071931274cf010836d683fff3be7134c78b8bfd8b1b8fc2049e18ccb1e18a0a9585a7d8a1e25492608668c96d62a0aca8ef90e048d20378c108d06b03fe3ec4adb27528ae08f7ded9487893ae64ca4b939202aa4c17afe718cdca49ff9616d0cdf8334b6aee2d6d20947ca4bd7df531dd1da99581ff72ea56fe62caa2c95e3587: +e1c12946d221a194f22f2762c0e51cbe3f98b914a47d3dc41a1f45c54370637c10408136a68fc56c7d3b36b7fef122094de081031189cc84a48806aaf6cb9185:10408136a68fc56c7d3b36b7fef122094de081031189cc84a48806aaf6cb9185:870f4cd97cfc0aafada40072312fb54bccc07628714e4962d4bef4eeb5de40a19a246b5b7d52d487b7e52d656f2c6403b916d02e02a6d291c1e1828dd945a583b438528d1c39765a572031ffa916b68321f32e6646f0dcc1c60235ffaa3235f484a5c4978fa3e6bf14301d53e12f4cc52118b1f6f07f5336f5d0a93789bb01d162fb3126dcd756e0642e7e698963c0345911a5cf3c9953f77319426cea2cdeda3efe989ecb63cb9eb8b920de766c4fcf6336e5bc4371a068371fed95c8c2b61ee9b7c3e3831c20bffe8707c0c98be96153c8a873d7f28afca1bf71085ce0e3899eef5591bdd666dc2d07641772d745c51644a260815b208c4dd305f05fe463d0d9d5a9eeff9779f5b1d44f26083078566d0e5ff56b3af0e64cc38708af5a65f654352df10437f1ddf945a0da1f4def6a71a060e0c4adeccaacf85e090f7090370ae24e5238d768a08fe6b4bb5ec497a6603198608415c7c6490048aa36737c08503008aece0f494219ddf89b72ea77171c6d3117089eb88907e8c33fb9e70b0dc281f664b5f965b5d2adb1250710ef2352025fb293395ae1d23ee3b592b4c5f2d55569a5458654ce3fc25dd0e3f7e6757aa7b347c1ffd3ba4d4f2c4b6d36afd59863a32a594e74537ece9b8b1ec269bbc4cb54d76238211f62a98a46a4af662fa81eba6f30f514b866b7942bc173f7211a6c014da14e741327a568623d14b8f835ef1d5d62b2523cfe6a85bc69fa05200deac1568b946a816b75c5d7603174fd4e2f9101a79063791bc3d59297cdc10bdaa663abf3c1be2fda17e4e5ce394e90bd76b1f9e0405f5675b99d638abc2c1b2d8b53a6fd3dc8375855ec54ccbda24e672527723b07bb599db54e38793391cf09ef3b1fd7614990065bbd4a19e8d3d1048253ba4c971c2f98d2b359df509087323aa6905029f5cc5e1a0aaf2f7c0108ddb1a40f562be64e57e695ed21dc7db17d533677ef12fcbbe29f3b237bb6344b1109b32a9462abc3ad3c0710b04f38c6f5952db275e77e2f37e95d55096bbaf3e305d5d743d36595bf0567892c210ac7bae7371d164584785dd890174159b3930a9a6ce3a166dda2383e6e2af28c1bf3192447e90511dcd80ebdf9ee2c9bdeddeeb610558641532d07cd13da61254154cc0fd9d481e3b0a237af2ec26256d4ab219faf15ad2b7e8e57ab726ff2723216a574585e2a639d948c2c4f69eeaad283e3a44ff268eaefd7e66b73ede473a8397c76b48d56cb3ccdabc91a8929cf42998350e0:8fd7fa400c032fcfbc402942fc78637526be97ab82f237bb393ea39e35738c67d75409543a8b3c055f08bf69199af63b6911a482fb4f6580802ec9d2dc3c1106870f4cd97cfc0aafada40072312fb54bccc07628714e4962d4bef4eeb5de40a19a246b5b7d52d487b7e52d656f2c6403b916d02e02a6d291c1e1828dd945a583b438528d1c39765a572031ffa916b68321f32e6646f0dcc1c60235ffaa3235f484a5c4978fa3e6bf14301d53e12f4cc52118b1f6f07f5336f5d0a93789bb01d162fb3126dcd756e0642e7e698963c0345911a5cf3c9953f77319426cea2cdeda3efe989ecb63cb9eb8b920de766c4fcf6336e5bc4371a068371fed95c8c2b61ee9b7c3e3831c20bffe8707c0c98be96153c8a873d7f28afca1bf71085ce0e3899eef5591bdd666dc2d07641772d745c51644a260815b208c4dd305f05fe463d0d9d5a9eeff9779f5b1d44f26083078566d0e5ff56b3af0e64cc38708af5a65f654352df10437f1ddf945a0da1f4def6a71a060e0c4adeccaacf85e090f7090370ae24e5238d768a08fe6b4bb5ec497a6603198608415c7c6490048aa36737c08503008aece0f494219ddf89b72ea77171c6d3117089eb88907e8c33fb9e70b0dc281f664b5f965b5d2adb1250710ef2352025fb293395ae1d23ee3b592b4c5f2d55569a5458654ce3fc25dd0e3f7e6757aa7b347c1ffd3ba4d4f2c4b6d36afd59863a32a594e74537ece9b8b1ec269bbc4cb54d76238211f62a98a46a4af662fa81eba6f30f514b866b7942bc173f7211a6c014da14e741327a568623d14b8f835ef1d5d62b2523cfe6a85bc69fa05200deac1568b946a816b75c5d7603174fd4e2f9101a79063791bc3d59297cdc10bdaa663abf3c1be2fda17e4e5ce394e90bd76b1f9e0405f5675b99d638abc2c1b2d8b53a6fd3dc8375855ec54ccbda24e672527723b07bb599db54e38793391cf09ef3b1fd7614990065bbd4a19e8d3d1048253ba4c971c2f98d2b359df509087323aa6905029f5cc5e1a0aaf2f7c0108ddb1a40f562be64e57e695ed21dc7db17d533677ef12fcbbe29f3b237bb6344b1109b32a9462abc3ad3c0710b04f38c6f5952db275e77e2f37e95d55096bbaf3e305d5d743d36595bf0567892c210ac7bae7371d164584785dd890174159b3930a9a6ce3a166dda2383e6e2af28c1bf3192447e90511dcd80ebdf9ee2c9bdeddeeb610558641532d07cd13da61254154cc0fd9d481e3b0a237af2ec26256d4ab219faf15ad2b7e8e57ab726ff2723216a574585e2a639d948c2c4f69eeaad283e3a44ff268eaefd7e66b73ede473a8397c76b48d56cb3ccdabc91a8929cf42998350e0: +762f06ca01e314715f92c90bbe72a25bf26212c81eb1d1a0dae2c31130f7cdbbf9626ffd692731925e5aacfa1bded01aa8f730b772d5e46adbc315565b9bf2c9:f9626ffd692731925e5aacfa1bded01aa8f730b772d5e46adbc315565b9bf2c9:9497483a4fba78433b38e9deb8915c750b6da0f78af4a68b62f9fc0391e338873b1d64b1b7f09f12f056a3c91653498ad56e069b8b160887e8e378a76d8b3c667083c0a2b2d2317d3b874857e57862ef0cb70436a9028f0191ccc616e9d7c9bd869808cf094835ff518677b3fb089f4c9d077cc7742405b4863ac7a59645c9cf540d57399da6ae9d07fd19fca95bc8a86d8b8e24e48733f32158fd19a8a1111d1da1f9b580a39c10484616cf2bc0ec29f63f77c85356158e16da594b5a890e55d0b64599b30293e900ed92ad261969e7df4c4b1d0b6024bdceb69067ef486c20fdcd22a10d5da45fbf905ba1e935c96f50afb63571bcff3130684eda0b56e60b26cf4c0ef9938a92768fc8631fe308236b012f92af24a8f6e6ecbe76629bbaf8ffe54cdbe8671de2ba624a7c0f6193bba4110412902bac2990922a9e5a81053cf876a4c805a04c56a8139d3419e454a622d0342bf426e9802c3dc1b4080c75492afe9d7b1545fe086d963541324ff52a48c6bfaea26668b3e01e5236fd45fe54594535c0b23e287ebd1428c8be0ad141600e91cb51e1ea66271a6421fb689e88a0790a651dbd21ee2089b274666f660ca09ce2d60e39e2ee5f03b6eb82d19976966e79900a810f6d5b5c1a548e5064f5c3d8a9f2def0179df99d143fde69b0712c091c29e9b25f40cafd57a024658d7774037610342f3800fd51f49e79a5b3decc112f58d03e3d2958758588bc4b1c6a6cda7bc5f5be183e41513c1f230f3cc364304bf82484b7cf19a002e150f98c5e97c6166ea15b86340b8c5ebe5c1a183e5588e66f55905086313f37a409e89b47db31ae97453edf69fed7be08113071f374b26ec6043f2a0e9cf8bad802abad69e617e76243b3cc034b099d8729ee407a53eb03bdc6410a039504b3b12c819b64545d405c6a4f084921935bdff4130ae629d909626b062676e538eafdffb1d6229c0889d3cddd3365dc3d6536f7248c49317cb50c56fb57855541d6feebac816c9928fa662d0ae80a0f39e570bb7d22416f98f371b64247968951a8a246f74b3061743c9af7684bbb966ae0bd78a810493ea4ccd71174871c82bb652b2748e5bccb0ab6388a50f053a048087fd97eb15c1a21b1ee1825e54aa130d66318aaf661bbb24763577eb37d310e219b0a9bba0375eb9c9b4af8c4b99a3699e0d3266733b6e4e9c534490a1341cb1990ca5b1c847bc8126026fea903a1f549d65af8fe02a9163ff8ea281e7226243e2a153b921851de10f7:e842b49e533dbc92998dc078e59793a2c2fa636bdfafdb48934c93cf34797102938d137ab7ead1a0f70e94a67d57ef6a02c9ec77d71f70cc57f1533bec87730e9497483a4fba78433b38e9deb8915c750b6da0f78af4a68b62f9fc0391e338873b1d64b1b7f09f12f056a3c91653498ad56e069b8b160887e8e378a76d8b3c667083c0a2b2d2317d3b874857e57862ef0cb70436a9028f0191ccc616e9d7c9bd869808cf094835ff518677b3fb089f4c9d077cc7742405b4863ac7a59645c9cf540d57399da6ae9d07fd19fca95bc8a86d8b8e24e48733f32158fd19a8a1111d1da1f9b580a39c10484616cf2bc0ec29f63f77c85356158e16da594b5a890e55d0b64599b30293e900ed92ad261969e7df4c4b1d0b6024bdceb69067ef486c20fdcd22a10d5da45fbf905ba1e935c96f50afb63571bcff3130684eda0b56e60b26cf4c0ef9938a92768fc8631fe308236b012f92af24a8f6e6ecbe76629bbaf8ffe54cdbe8671de2ba624a7c0f6193bba4110412902bac2990922a9e5a81053cf876a4c805a04c56a8139d3419e454a622d0342bf426e9802c3dc1b4080c75492afe9d7b1545fe086d963541324ff52a48c6bfaea26668b3e01e5236fd45fe54594535c0b23e287ebd1428c8be0ad141600e91cb51e1ea66271a6421fb689e88a0790a651dbd21ee2089b274666f660ca09ce2d60e39e2ee5f03b6eb82d19976966e79900a810f6d5b5c1a548e5064f5c3d8a9f2def0179df99d143fde69b0712c091c29e9b25f40cafd57a024658d7774037610342f3800fd51f49e79a5b3decc112f58d03e3d2958758588bc4b1c6a6cda7bc5f5be183e41513c1f230f3cc364304bf82484b7cf19a002e150f98c5e97c6166ea15b86340b8c5ebe5c1a183e5588e66f55905086313f37a409e89b47db31ae97453edf69fed7be08113071f374b26ec6043f2a0e9cf8bad802abad69e617e76243b3cc034b099d8729ee407a53eb03bdc6410a039504b3b12c819b64545d405c6a4f084921935bdff4130ae629d909626b062676e538eafdffb1d6229c0889d3cddd3365dc3d6536f7248c49317cb50c56fb57855541d6feebac816c9928fa662d0ae80a0f39e570bb7d22416f98f371b64247968951a8a246f74b3061743c9af7684bbb966ae0bd78a810493ea4ccd71174871c82bb652b2748e5bccb0ab6388a50f053a048087fd97eb15c1a21b1ee1825e54aa130d66318aaf661bbb24763577eb37d310e219b0a9bba0375eb9c9b4af8c4b99a3699e0d3266733b6e4e9c534490a1341cb1990ca5b1c847bc8126026fea903a1f549d65af8fe02a9163ff8ea281e7226243e2a153b921851de10f7: +c5cc0b95818c4bf38da1d65f021627e9e57d262b02ec6d917a7d46b11c7fe48a457da4ef14519d541edf92cabed9b04d8a2f2afd1510a92f009bb4e8754f1eba:457da4ef14519d541edf92cabed9b04d8a2f2afd1510a92f009bb4e8754f1eba:d6608bf5ac000ecaf95fc09f9cb7498c518a6e0255586e6337853b1d7d9d7de4dfe1245d59031a317d4e2b6a73c4c3f95b582e72a6420221587bac120fb8ed7348070f2860d85866a09fe756743497f2119bc1bfdf573be35d1091be37f18bcda6741c90d566cc924b72164b749af9a6f40f71d3ea5d8764cdc81714bd7395e5f679973636eff1db1cf0012983f71a2f2b12d45a294e5a389f4cd2483eb39da0df26b736c7af6e41dd35a78e45292c394e34689532888721f863c56db97da1cd10a66a20a670b27fe8ce5568a42b8937790c7be1aa420d203d7a885c1729cd6b8e197189e479d542cbcb9b53656f2b9f539c325c34aa598fd91e7df70f9a74abec467654b1c9a3d14438e7c0836040b793871ecbe9e5f6680ccccd5d4696a87e37e89eab28b6bd679e8fe1627bdc9d373b82f52cd8c49be9bacdc630a32fd12835255a542fb7b12393779d4498aa06a0e7e1a4977939817eb2088af1e19bb0e5aca854c125dc603d835736a03d938051530c9ab1aa3bc779b3bae7450ef57d1b3fc093a37dbe9d1bd6d040f2f8eeba77f7fa88c149f065c7ace33277aa9969c266ea6d85cad62cfaf5508e7032716be684a22856413e0e65e42b6e9e6d865a87363cbb62d5bbb6a3731ddda0fa6ad0293af9893c09a9e743090f2cee2f4437736dd433e2ac7428bdc8c77cb9964355fa4415cc3831d8c7ca5af93d51752e718c6066eca1426a87c29808281a85ac7e0b4044ff6e280e28014b9383d19c9d387d29dc14de433da260784a4944ca76c2fe8a080d0996d9a6c2a3d3a7077280edcee0389aa8e5365d1d9b346eca0947b0ff5265943ccf09939a4b4a8f985f6a5e72723c795da0bc360dce501f673ab6ea8443f129427952453eb72b3a8d0d976c278c5bd1a9853c918e0c240c3c734932953fdb5039fbb04687937c9ff0ab74a16eae212bc6f20e700a77c092d23d2efb580e0c19d65f304129ab8e6cc12e58052257ba09449f30d3d974391afff5633def2f5c4ebd573a9e444bf3a3ddacedf02c05f3cc2e750664a84a1d24c5d28b49670de8a2f2090839483ca38959991a7d3727e21a15e82016c15a09ee71f4f43c0a608b48485c9934a38614794d6291daa39c01c45d3debe579b5823bf3406404b4c80ee6ff342b46b334b0b883b40bfd2f9a53595ab62fd1351ebc88308370497218dfc98ce081407da812a46d6497d7af9ec6d83e1c60eeb712d889dfbed0c805aa11cf817dd8f04396ef871a26112dcb7c0e1d2e68:3ba0af8af127c4584826090ecdaf485ebdf07b82bc499c9a2befca28d49344974addbc8d80a52560e0f3d73ff5cccc72c74b5b47ad2e6de9612d1a00aec92701d6608bf5ac000ecaf95fc09f9cb7498c518a6e0255586e6337853b1d7d9d7de4dfe1245d59031a317d4e2b6a73c4c3f95b582e72a6420221587bac120fb8ed7348070f2860d85866a09fe756743497f2119bc1bfdf573be35d1091be37f18bcda6741c90d566cc924b72164b749af9a6f40f71d3ea5d8764cdc81714bd7395e5f679973636eff1db1cf0012983f71a2f2b12d45a294e5a389f4cd2483eb39da0df26b736c7af6e41dd35a78e45292c394e34689532888721f863c56db97da1cd10a66a20a670b27fe8ce5568a42b8937790c7be1aa420d203d7a885c1729cd6b8e197189e479d542cbcb9b53656f2b9f539c325c34aa598fd91e7df70f9a74abec467654b1c9a3d14438e7c0836040b793871ecbe9e5f6680ccccd5d4696a87e37e89eab28b6bd679e8fe1627bdc9d373b82f52cd8c49be9bacdc630a32fd12835255a542fb7b12393779d4498aa06a0e7e1a4977939817eb2088af1e19bb0e5aca854c125dc603d835736a03d938051530c9ab1aa3bc779b3bae7450ef57d1b3fc093a37dbe9d1bd6d040f2f8eeba77f7fa88c149f065c7ace33277aa9969c266ea6d85cad62cfaf5508e7032716be684a22856413e0e65e42b6e9e6d865a87363cbb62d5bbb6a3731ddda0fa6ad0293af9893c09a9e743090f2cee2f4437736dd433e2ac7428bdc8c77cb9964355fa4415cc3831d8c7ca5af93d51752e718c6066eca1426a87c29808281a85ac7e0b4044ff6e280e28014b9383d19c9d387d29dc14de433da260784a4944ca76c2fe8a080d0996d9a6c2a3d3a7077280edcee0389aa8e5365d1d9b346eca0947b0ff5265943ccf09939a4b4a8f985f6a5e72723c795da0bc360dce501f673ab6ea8443f129427952453eb72b3a8d0d976c278c5bd1a9853c918e0c240c3c734932953fdb5039fbb04687937c9ff0ab74a16eae212bc6f20e700a77c092d23d2efb580e0c19d65f304129ab8e6cc12e58052257ba09449f30d3d974391afff5633def2f5c4ebd573a9e444bf3a3ddacedf02c05f3cc2e750664a84a1d24c5d28b49670de8a2f2090839483ca38959991a7d3727e21a15e82016c15a09ee71f4f43c0a608b48485c9934a38614794d6291daa39c01c45d3debe579b5823bf3406404b4c80ee6ff342b46b334b0b883b40bfd2f9a53595ab62fd1351ebc88308370497218dfc98ce081407da812a46d6497d7af9ec6d83e1c60eeb712d889dfbed0c805aa11cf817dd8f04396ef871a26112dcb7c0e1d2e68: +61fa8677eedaded69b165c8d277c978249663028301df6163e39b06ac2f5625f87339eb57238db2e4e60f3c28a3fd5fb611c65fddc81eed7cf7771df34d92267:87339eb57238db2e4e60f3c28a3fd5fb611c65fddc81eed7cf7771df34d92267:02c581dee03f2c603935af5eceecfa677134a3e0aea54fecaf4271fb52951a27b76877ccd49ab486dfc227cf31c9d957cc97306573fc7fe1d31b6c7df3d780f3a05ca6395657a9424342c9c6b703127e038df0792154e30a49476112cb92d0d5a2d22e895752a86edddd912fdc81b1e64a7bb750f099182132ee4823fde845802a944539d412b2a81a15b00071a950504c5b55a71bdb8c5a582639e855e8be241cda1ba6b3b4f64554d17824904cb30cd7efd9ac049e390bb79f53598ef1e8fc27dd7bf599c9028c9ebf92fc3be11df329612a228e0f5684687bf41ff203e97a7686126a39366bdc26d50be025d5187c6ba0666e379be4a80a9e62effcd916d7f98de651e00b97adf5d2d53daa7f8d695a291560755c744482364c4f1fa47ec0b1da161aa388f9597989a97726d3ed2cec82f1a1bbc4ac0be0a00cb4a8db1fb7c14ba05d896348dc0559d2a90beac2041dd77f82d6b12aeb2243ca0f419a57d3ca9c7d25a30ff0e8bb0d945155d1b36ad107b55beaa95b7d5e32003407629f1515f8a7089e2488d0d7544c2f7cc7c7f0985da42840d4368ff4f0fa4fa298e3b7229303aba514ae94e7026535a3f426ffbb4e001cd50ed12f214b3abef96e301635c987b133fc5e6184e7b7572bc3d99a4523cbd5afe593cedf4c9cd02ff2e36237e4ee12ef1a22d16d7cf4c072dced91cdd26ee144cc2bef4950026349e9444784081fe4e0498bc75f72e6818f459bba9049c561316c9f498e7b1a994b0e93055fe73e444cbdf96ac35e9c4e92e6b49e3bc0e99de1716df8eacaeb8d2fd74870044cb39c0e367a1fe32a9bb2974416364e730d5248dfb1df164a8d58caa1005fdc91bac2bc01cc77decc14893ef946fb3c81be0832c72fba372062f8360f4d8e6d5b741cf7032d8d89de2edf4c714a29f75abd8f5ff43ecdd4b7a04d7db0882d16e74473a0fb79db444a78ea44aa2631b8c0d7b0300d55cb6ac485f24c0acc647747c43db3b2a8677baf656fa735a575f1813f3668a2aca9175711b525eb496e9ef9711d75f590c7d9ef99e0f59e8483cbf9f284e3f5a33ee7781e62b8b05551777efe0fbfd19e54b6bbd142944bc2959a82ebd295d23d3443b6ce658c2d579a7637b549520491908e34282ec2716972e6f0353929547ef1537aecc96b2df616148599b09d9b81394a13fe7db86760b1e2a060efd484e8189939ebdf6f21640d89d8e736dee082ad72a0184adedd8df21474c9f526bcfdf7e85658194bb6d942e7f3fe96c23f:c04ebd11c3eb09396fe8d68279510a9efee391abee4081f0d275674a304794835aad7f3e345bcf0af8027f97477e79e6792b8f299846ae28cb13bd887537990d02c581dee03f2c603935af5eceecfa677134a3e0aea54fecaf4271fb52951a27b76877ccd49ab486dfc227cf31c9d957cc97306573fc7fe1d31b6c7df3d780f3a05ca6395657a9424342c9c6b703127e038df0792154e30a49476112cb92d0d5a2d22e895752a86edddd912fdc81b1e64a7bb750f099182132ee4823fde845802a944539d412b2a81a15b00071a950504c5b55a71bdb8c5a582639e855e8be241cda1ba6b3b4f64554d17824904cb30cd7efd9ac049e390bb79f53598ef1e8fc27dd7bf599c9028c9ebf92fc3be11df329612a228e0f5684687bf41ff203e97a7686126a39366bdc26d50be025d5187c6ba0666e379be4a80a9e62effcd916d7f98de651e00b97adf5d2d53daa7f8d695a291560755c744482364c4f1fa47ec0b1da161aa388f9597989a97726d3ed2cec82f1a1bbc4ac0be0a00cb4a8db1fb7c14ba05d896348dc0559d2a90beac2041dd77f82d6b12aeb2243ca0f419a57d3ca9c7d25a30ff0e8bb0d945155d1b36ad107b55beaa95b7d5e32003407629f1515f8a7089e2488d0d7544c2f7cc7c7f0985da42840d4368ff4f0fa4fa298e3b7229303aba514ae94e7026535a3f426ffbb4e001cd50ed12f214b3abef96e301635c987b133fc5e6184e7b7572bc3d99a4523cbd5afe593cedf4c9cd02ff2e36237e4ee12ef1a22d16d7cf4c072dced91cdd26ee144cc2bef4950026349e9444784081fe4e0498bc75f72e6818f459bba9049c561316c9f498e7b1a994b0e93055fe73e444cbdf96ac35e9c4e92e6b49e3bc0e99de1716df8eacaeb8d2fd74870044cb39c0e367a1fe32a9bb2974416364e730d5248dfb1df164a8d58caa1005fdc91bac2bc01cc77decc14893ef946fb3c81be0832c72fba372062f8360f4d8e6d5b741cf7032d8d89de2edf4c714a29f75abd8f5ff43ecdd4b7a04d7db0882d16e74473a0fb79db444a78ea44aa2631b8c0d7b0300d55cb6ac485f24c0acc647747c43db3b2a8677baf656fa735a575f1813f3668a2aca9175711b525eb496e9ef9711d75f590c7d9ef99e0f59e8483cbf9f284e3f5a33ee7781e62b8b05551777efe0fbfd19e54b6bbd142944bc2959a82ebd295d23d3443b6ce658c2d579a7637b549520491908e34282ec2716972e6f0353929547ef1537aecc96b2df616148599b09d9b81394a13fe7db86760b1e2a060efd484e8189939ebdf6f21640d89d8e736dee082ad72a0184adedd8df21474c9f526bcfdf7e85658194bb6d942e7f3fe96c23f: +7048c6521aefafa4eac6d6c3a702b9525480a66482e4969896757f2cd1ac7d5bed93113c1643a53aa064caa631ceb6e20f6d6ec2fc6c0711cb8a1fe73139af93:ed93113c1643a53aa064caa631ceb6e20f6d6ec2fc6c0711cb8a1fe73139af93:53f74c724db1578a1a296a7ccac904a2504dd9005389b4f8d4ea4b6307298fc6dcce98a6bc07280d20364e405a467e736578965269c81461d61fc6b7e4bad68d2b6dd0005850105f0a67bbc6ee223ec1754af4e3b9afa5062d1c1861048f185b128f1a5c0fb25c3919b4833e29e202bc941a905e63c2c05b1014647bd7ede5be9f996615187a3d3bb2c7dc4c28f7053def9b28b29e2331f16296dce8f1ede484caec996702bd9902e52684c812c87440f69bd141c7e00c6947d1fc7c3bdc0bc5506b6ea462e65f9e743b72c007ddc7a377493777d4eb12620ca6c019c8bfc4c29ec8af382fc3eac841021a74e4674ba3e43e5d7b41e3feeb17da00a7ce455a1cec70b0be6e56f85fc37f64cf0733b7e31241de641a8a8e5b91897bc158fe93d102c01d1f5e166d408165fe3fcb13d5304590ab8ef0dc8d5a8c1d8a93fceb854fc1fa36d0cc480cf8512d80bee69b0650a957daed283cd7638155ed773086e86a8ffb198acc7423b5d1a609a175a56b94c96b731851b93a94977101e255f1ce92e232a05e2e3387fcb4dc13a31bee6ee25507322c73c9883080a74c00f803a998dd530a79126bb144ed5574c4b23180e34e099283b4bb1d28822fce3717046ff32ef9e2cdf967e318ea726a2aeec57806643ad4801d3e0da52a1d77bf043f5ae9f3aea9e4bc4fa795d08401085ca94cfc4ce719dabc7b2390d03d294a65b7af9bc39072285b777b2f133dc11a70c0a9f060e10441f40216acb641637a2eadf1f7b8d262fec1b4d0f0f4faa93f3f732cac382d8ac42e178e2244999d764a9d0e981714686eb4924497e56b50157e9939032c9f88eb657cfde44ad34714af4a51324e5e77d0deea99c9f244d2e09ea425820a746d883a0cf4b705c29df8c037448154dc08a4d4337405fb8765823114370b37ed86086ec5f8bd6c72abf13f518430710f597b06108f65b30a483496e2ed81dab10fee947fe04b5485f2e3074049d22284266651ad10dd086aaa5d452e0d1a61129d1e77c663c26d088962b5545645b7a1a8713d51327a7a359b12daadb85a2cd4b5410d5c20267fa766b8c42a84dc42664588879b3eaefd4cc8dc693f98ac205609e570665b01ea4655e39429a7a7e542efb4f7890dbf4e34c6cff07e4d35bd3eeedf5b46280f4a0da0c2e73c94ea81cfeae7f9bd04fe2d45976500f7dcacb0df2a5dc736a823671db679be66cb33c162fd2c74ae71fbf4d2b05af042b3a977f5b944b9fdb6c34424421bcf4f6223768428fa140fd4:7c45703ed3942e44041c7fa1858aa5f1dc381f493a452dfb52708017898f710e31118e331f00aa64cb738836682b7d177e97955c00319abd79a49e0fcd16fe0053f74c724db1578a1a296a7ccac904a2504dd9005389b4f8d4ea4b6307298fc6dcce98a6bc07280d20364e405a467e736578965269c81461d61fc6b7e4bad68d2b6dd0005850105f0a67bbc6ee223ec1754af4e3b9afa5062d1c1861048f185b128f1a5c0fb25c3919b4833e29e202bc941a905e63c2c05b1014647bd7ede5be9f996615187a3d3bb2c7dc4c28f7053def9b28b29e2331f16296dce8f1ede484caec996702bd9902e52684c812c87440f69bd141c7e00c6947d1fc7c3bdc0bc5506b6ea462e65f9e743b72c007ddc7a377493777d4eb12620ca6c019c8bfc4c29ec8af382fc3eac841021a74e4674ba3e43e5d7b41e3feeb17da00a7ce455a1cec70b0be6e56f85fc37f64cf0733b7e31241de641a8a8e5b91897bc158fe93d102c01d1f5e166d408165fe3fcb13d5304590ab8ef0dc8d5a8c1d8a93fceb854fc1fa36d0cc480cf8512d80bee69b0650a957daed283cd7638155ed773086e86a8ffb198acc7423b5d1a609a175a56b94c96b731851b93a94977101e255f1ce92e232a05e2e3387fcb4dc13a31bee6ee25507322c73c9883080a74c00f803a998dd530a79126bb144ed5574c4b23180e34e099283b4bb1d28822fce3717046ff32ef9e2cdf967e318ea726a2aeec57806643ad4801d3e0da52a1d77bf043f5ae9f3aea9e4bc4fa795d08401085ca94cfc4ce719dabc7b2390d03d294a65b7af9bc39072285b777b2f133dc11a70c0a9f060e10441f40216acb641637a2eadf1f7b8d262fec1b4d0f0f4faa93f3f732cac382d8ac42e178e2244999d764a9d0e981714686eb4924497e56b50157e9939032c9f88eb657cfde44ad34714af4a51324e5e77d0deea99c9f244d2e09ea425820a746d883a0cf4b705c29df8c037448154dc08a4d4337405fb8765823114370b37ed86086ec5f8bd6c72abf13f518430710f597b06108f65b30a483496e2ed81dab10fee947fe04b5485f2e3074049d22284266651ad10dd086aaa5d452e0d1a61129d1e77c663c26d088962b5545645b7a1a8713d51327a7a359b12daadb85a2cd4b5410d5c20267fa766b8c42a84dc42664588879b3eaefd4cc8dc693f98ac205609e570665b01ea4655e39429a7a7e542efb4f7890dbf4e34c6cff07e4d35bd3eeedf5b46280f4a0da0c2e73c94ea81cfeae7f9bd04fe2d45976500f7dcacb0df2a5dc736a823671db679be66cb33c162fd2c74ae71fbf4d2b05af042b3a977f5b944b9fdb6c34424421bcf4f6223768428fa140fd4: +3e6373b265b96789007ad2a10c309a567638f25587d77e28b0823a4f179ae4fea3234e5d13b03472165036404f6de80e702839500f13d9c985a077d45c69ff45:a3234e5d13b03472165036404f6de80e702839500f13d9c985a077d45c69ff45:b9d068bbcae7722f828b0f8c98a738e36a7df4c997c724ba27531af34a2f106c7513a44a461a9aa4309bc15c4e0d42759193ea1cdea956bb815985f57867145e9e2c7585fc8d61027e47d2d735e2448af3782909404edeaac0fd73f6045dcdb04f0377758f02204aae3a7220311c0f4723582710cc440c36c9587b5c9ebc4063fea8ca3f43195894f79a365087137282302dbf2e7a0d411ab58b7026ccde198869aa734334c05238e275e3c3ab217083495769e2fad374051452d7f5b1db0e785836d4bd5e2978a3e991af0ff716f43889a07f5df299603621c39e2cdee089985d9e6bf7b2fbd02373ae1b5e9b88f5b54a076e676d7790bfc8f57dcc59ef52850ce992a73ba7bc991deb4dde5eb0b21670b1b3d4b64f36cca8e307098568497d8916f6b5d0e9e89f99f86006f39bd3a810769c8f7801773c9638abcf5e2711b19d1167593acbe85e4161428997a2194dc5e7b7640f0d2c1eb205553be9167ffbc22b7c2e7698f3afa10754cb44d4b1d45b837303b1669073415a22606b50f21f8265e139f2305ac0e0127ae056ce8abeaba20e1d269a2b2e899c49547268a0696ae450dc0267f7f63a8edf074c47d3c2db1da36393737304e6dd4faccdb6ab55e5f8520c3dff5f6beac30ba85b86082351e3ded8400aa57f650c0c33036d65b39b7d2fb6112863d59b72558242e8b045addd357de6fd37a8f6611765c9b5ff19cc4db7e117c65a00458908b0245d04f7908fc73b165dff6e4be4b42032d8cfd7d6f7772c1bfe721d4bcfe2fc527998f34fb4418a1fae1e6c3767c4d0780621f923da1f0a0d3d219c036acfd3709dad4cf24d90bc691d700e6a9c80ccfd10bde8e791c0fea82880c07baaaa311eef79240784f628a7d2a09184e016f81008e77429a8658b153e44e79a98ad248f7fda23b590d646d7c1d841f4927d6e8bc73214d10a7f3c29c8f839a8908d20a74e827af467ac5abf0f1d0ed39cddd969dde9eeb4a4b7527ab3e2475a195e24474a4e36b09052e2dad4a5eb4691e263b8c61bbde87772207e011c4c1e14235fb24e4da438875d18530fef902619dd485d77b545abb56b69c755afe758606971ab97dd3ace1c1a34a33794c8156da799e8224d885e1868f9cb466d802c827cc3e1ecd0ae6e0b01f8f791b12208fcc0fed385b796eb2f2908b58d30b3733f1470f2e2ef12ad43feb72d0816de3c13a8b5a523e14cdf5ff3720bf87769cde7495d226bf38238a825f75a09f6bb9afce516a7bc70114370bbc40f17c7bc:f51e0f878a5a709647e85fea839fd566e6f35c8a6185d0c9eb13e0d5b9e6e8aa95c333a8f50632a4d6657b518ce4cfde40b8f5a05b2d9f8441fcc9d2d692d509b9d068bbcae7722f828b0f8c98a738e36a7df4c997c724ba27531af34a2f106c7513a44a461a9aa4309bc15c4e0d42759193ea1cdea956bb815985f57867145e9e2c7585fc8d61027e47d2d735e2448af3782909404edeaac0fd73f6045dcdb04f0377758f02204aae3a7220311c0f4723582710cc440c36c9587b5c9ebc4063fea8ca3f43195894f79a365087137282302dbf2e7a0d411ab58b7026ccde198869aa734334c05238e275e3c3ab217083495769e2fad374051452d7f5b1db0e785836d4bd5e2978a3e991af0ff716f43889a07f5df299603621c39e2cdee089985d9e6bf7b2fbd02373ae1b5e9b88f5b54a076e676d7790bfc8f57dcc59ef52850ce992a73ba7bc991deb4dde5eb0b21670b1b3d4b64f36cca8e307098568497d8916f6b5d0e9e89f99f86006f39bd3a810769c8f7801773c9638abcf5e2711b19d1167593acbe85e4161428997a2194dc5e7b7640f0d2c1eb205553be9167ffbc22b7c2e7698f3afa10754cb44d4b1d45b837303b1669073415a22606b50f21f8265e139f2305ac0e0127ae056ce8abeaba20e1d269a2b2e899c49547268a0696ae450dc0267f7f63a8edf074c47d3c2db1da36393737304e6dd4faccdb6ab55e5f8520c3dff5f6beac30ba85b86082351e3ded8400aa57f650c0c33036d65b39b7d2fb6112863d59b72558242e8b045addd357de6fd37a8f6611765c9b5ff19cc4db7e117c65a00458908b0245d04f7908fc73b165dff6e4be4b42032d8cfd7d6f7772c1bfe721d4bcfe2fc527998f34fb4418a1fae1e6c3767c4d0780621f923da1f0a0d3d219c036acfd3709dad4cf24d90bc691d700e6a9c80ccfd10bde8e791c0fea82880c07baaaa311eef79240784f628a7d2a09184e016f81008e77429a8658b153e44e79a98ad248f7fda23b590d646d7c1d841f4927d6e8bc73214d10a7f3c29c8f839a8908d20a74e827af467ac5abf0f1d0ed39cddd969dde9eeb4a4b7527ab3e2475a195e24474a4e36b09052e2dad4a5eb4691e263b8c61bbde87772207e011c4c1e14235fb24e4da438875d18530fef902619dd485d77b545abb56b69c755afe758606971ab97dd3ace1c1a34a33794c8156da799e8224d885e1868f9cb466d802c827cc3e1ecd0ae6e0b01f8f791b12208fcc0fed385b796eb2f2908b58d30b3733f1470f2e2ef12ad43feb72d0816de3c13a8b5a523e14cdf5ff3720bf87769cde7495d226bf38238a825f75a09f6bb9afce516a7bc70114370bbc40f17c7bc: +f5e8597eac0ebfa9d385de85a1fbaa35146395b13457b5b14d3670daca6905e7ce93e642c2f15084bc83bafdaa196763de2a3c513b0e44f68ddbde378514c441:ce93e642c2f15084bc83bafdaa196763de2a3c513b0e44f68ddbde378514c441:273341f219ff5cf381c77b2dd226c58f8f33c4527048cb006affef8cee151e300efef629fed21b70451f729292627d1f3f1b5257359ee5a671cf62ae57324940f2d0b15aac76ff398220c08024e29a8cf36504e12a4e96438f42c3da0c000541bc11f091381b0b72b58a92083f446eca1991996878de35081cc4ab90958c96cf5c99796cba7951ee186f26527aede69db304ce2941ba15cc00ba2f1411f208dad45e87bcf638792de0a68624b667297c27a343db4baf34a0228eaf0d1022009b5d068b2534d920302e71310febf0df1bb02c2ef0ad1ae149deadf8c184373c0f7eb6b25695be82d12c71b6c83267d9a233667e77bc205983f8b8d877d85aead3f60e820ffcb17adddd92a7712bbeb34ee71966dafd9907d193dd9d725a31a613d29e32be72132808926d9437477fee25eda610aeb1dce12ea316c6aec6689e501c551923825a34b42c4f0675b86ab26adeea2e60dae6c6d1cdd0cb3c347b16384039a8e3fd6087381387cb4bc72ddb5f25b374859b02e5bb1ba06d3cc69ec44cec4b985c8476e35032e99abf001a1d44ddc6e2889c3c2c3ecaced609b2b2680e00b1efa7e9d26d62f2b3ab36f921044790abbd49360756dcffccf230f66dbb701aa164dad6069aa2b8b3309f2fe44d5e0b25bd556431f0df4c2ea97ae79ed4a57578d66fc6939c57628a90cac97adfa8702a4a1c8965ba1a90262567286664003003533cc9314caf7d3b982e0a432ff5aa4ed5741983d9b54323ac7e299b2b4956c1a2c191557b27d86be714b5b68fcb1d41f78ca5ddb6b53b3dfc8e7d6b3c3db059af9f2dd765ef04b6d16e6737c727aa11f3df3774a3fc96182e282acc3d233eeabf8c72d3f246ae184505288fef39b36766b10dd1bfbfbfa70f97b3c901726d1e0d0a837d11f0123a34abad1a79aabe80b125b128ee160b511848f7f04c49c8d5c2f2041da7d9599c29b1dac8c68077efac3eca58bbc1637aadce21c774fea42d2bcf4a0b9892307e36fa250acee795ad2bfecfbf60319b81663e2a26571946f75a8d969af16b3b57c3ec3e66158aaf42ccf5e58b937aaef613318606603317e5aa318be70f8da3c0c16be6c29e3ec9fef4e46e8ca241d941d58049a063d90afc953ca32e8a50a6473632588ac41eae97f20ce9b741ed41c9a4aa6551fd823ce0c811a5bb5a171c1ea4238a0246811e469cf498b79621c323eba7985344fe11e67499edf4967491aa749f8f3fe39961d76892c93aac3b19fa4b4fc174d7d4d4d8bd6ee475475008:576543fc21ab0a7c5f63b1cff01bf845df91792e7a9750c5508b51665e7f89f17c6ec3355a0aed87db8c77bdb271fbedc714ffadb78b5e0f978116771ba7cf0b273341f219ff5cf381c77b2dd226c58f8f33c4527048cb006affef8cee151e300efef629fed21b70451f729292627d1f3f1b5257359ee5a671cf62ae57324940f2d0b15aac76ff398220c08024e29a8cf36504e12a4e96438f42c3da0c000541bc11f091381b0b72b58a92083f446eca1991996878de35081cc4ab90958c96cf5c99796cba7951ee186f26527aede69db304ce2941ba15cc00ba2f1411f208dad45e87bcf638792de0a68624b667297c27a343db4baf34a0228eaf0d1022009b5d068b2534d920302e71310febf0df1bb02c2ef0ad1ae149deadf8c184373c0f7eb6b25695be82d12c71b6c83267d9a233667e77bc205983f8b8d877d85aead3f60e820ffcb17adddd92a7712bbeb34ee71966dafd9907d193dd9d725a31a613d29e32be72132808926d9437477fee25eda610aeb1dce12ea316c6aec6689e501c551923825a34b42c4f0675b86ab26adeea2e60dae6c6d1cdd0cb3c347b16384039a8e3fd6087381387cb4bc72ddb5f25b374859b02e5bb1ba06d3cc69ec44cec4b985c8476e35032e99abf001a1d44ddc6e2889c3c2c3ecaced609b2b2680e00b1efa7e9d26d62f2b3ab36f921044790abbd49360756dcffccf230f66dbb701aa164dad6069aa2b8b3309f2fe44d5e0b25bd556431f0df4c2ea97ae79ed4a57578d66fc6939c57628a90cac97adfa8702a4a1c8965ba1a90262567286664003003533cc9314caf7d3b982e0a432ff5aa4ed5741983d9b54323ac7e299b2b4956c1a2c191557b27d86be714b5b68fcb1d41f78ca5ddb6b53b3dfc8e7d6b3c3db059af9f2dd765ef04b6d16e6737c727aa11f3df3774a3fc96182e282acc3d233eeabf8c72d3f246ae184505288fef39b36766b10dd1bfbfbfa70f97b3c901726d1e0d0a837d11f0123a34abad1a79aabe80b125b128ee160b511848f7f04c49c8d5c2f2041da7d9599c29b1dac8c68077efac3eca58bbc1637aadce21c774fea42d2bcf4a0b9892307e36fa250acee795ad2bfecfbf60319b81663e2a26571946f75a8d969af16b3b57c3ec3e66158aaf42ccf5e58b937aaef613318606603317e5aa318be70f8da3c0c16be6c29e3ec9fef4e46e8ca241d941d58049a063d90afc953ca32e8a50a6473632588ac41eae97f20ce9b741ed41c9a4aa6551fd823ce0c811a5bb5a171c1ea4238a0246811e469cf498b79621c323eba7985344fe11e67499edf4967491aa749f8f3fe39961d76892c93aac3b19fa4b4fc174d7d4d4d8bd6ee475475008: +cdadc5b89cb2b6308a006f2f4e955a91aaf3ba70165f2d444ef1ffebbdaaa2210541415ff5467f28ceac839b13a1766e72c99e6545207d9d5d9697411eb6bca7:0541415ff5467f28ceac839b13a1766e72c99e6545207d9d5d9697411eb6bca7:911727036db309d6e2e3369e4f17d98d99ec070c33283bb1244efd62e76bd70a69b9723bd2b520472b98aa065924366de780900bcd8b77b50f87c3c36187024bbc59ccf4482c7b4aadb56e2e5ecc0003d989d6afc63ec10242e57482fe39215261d5fc95a0185f95e9540c55f74d696048bca7ab112681a5558ea93c3b1f1cd364659e9433ceeebe054ee713c47760d7ad132a7f3f8fe3d5041b811a26b65efb1f340e181a4ec720ea136b3af3d9e5461dd24370336f10e6354c8c17acf9998544cec0873efa687cb132aecf70aebbc567ba03c536499ef96cc8412e7aaad5bf96422be47cb9413645df2c1703192347dcbb123127455971ae157e9fa2dbff88745a96c658b865e41f55aebf98395005ddcbd5983e6ae02c4fbb5e17916796325f76edf5b64afa4ec5a7418afed23a97efade68b6a5b3145f08a5d3db9c298a512fabdac68562b3f55377ff44b00c1c2f3efd18132da71f971a953a9318c57523361a160f9b7e3b51c524e95dd5ef4568ef18a800775e9d26e07131942d2be4ef22c0cbc13df01c68b1bcd3bce9bd51c4ced652adc4007be43b37c67a5c55ed4029e8ad15def8305c968621aed4cd4bfe079a6f48884d85680392ca92ba6e12fea6f4a056f79d67b19b05f90d684be7d45725f7967c6a467af43b86a6b1b9d9eed3a4248971c76a7ac29c292dfba4d75c5f7ba709a39058e96adf6dbd760d3cef4024bf3edc441efbf1147a2c108bd6f9eb439c1c5c4d3a6ea4ec3d92cef38136188bec9e0b6c0518d8b79ba59c5dcba393aedfdffb0b70d779c2b9765ce4452e7e3b08c4402b1a608320840fbe96d1eb8656eb1c20d9551ddf533b9f15e4eb5783756c53ddd3b14d807f838ac9680f89f1adfb78d68ccb06731a90beac5f0d709d5b88c75437a663cb962d37f96b8e8928477b5611228015d337f049e8b62e4dff8d0bb6cda24a5df9083e348bef12585f5f4c4d3bb3c7e78d550194a45251a0879a1624bf9dd35eb655c3939fea8909f6df395bebd02b68a17a897c9aaddd6e2e20461e303f57cdeb00ae0f23e60a94c19c771d8aa60533b93cedc1b76d2290a01bf43b2725f125befa575154e986c9c6205a1596cbaa2d13470c23422f2df7bece4e6ebd752e9389ae60857b52969d2ddefa9c034f1bf35ae3316304e949c8990820e26e6cffae4b388d1505f923706297f8db556537919ebbe3086023f12f4ded3b11acf2a6d973ddd8eb27b07c580bf448caa5a2ea116c5eaf36f7a6b17a85b3955dc8a44a620d8:ffede701eb1829ce2361cda2c8bb63338539d8ad2f6677585531e7bf1d3922382679a1ae84ffeb753fc9754e50c01852f955e3fd609ff64bf05bbe7075cdbe00911727036db309d6e2e3369e4f17d98d99ec070c33283bb1244efd62e76bd70a69b9723bd2b520472b98aa065924366de780900bcd8b77b50f87c3c36187024bbc59ccf4482c7b4aadb56e2e5ecc0003d989d6afc63ec10242e57482fe39215261d5fc95a0185f95e9540c55f74d696048bca7ab112681a5558ea93c3b1f1cd364659e9433ceeebe054ee713c47760d7ad132a7f3f8fe3d5041b811a26b65efb1f340e181a4ec720ea136b3af3d9e5461dd24370336f10e6354c8c17acf9998544cec0873efa687cb132aecf70aebbc567ba03c536499ef96cc8412e7aaad5bf96422be47cb9413645df2c1703192347dcbb123127455971ae157e9fa2dbff88745a96c658b865e41f55aebf98395005ddcbd5983e6ae02c4fbb5e17916796325f76edf5b64afa4ec5a7418afed23a97efade68b6a5b3145f08a5d3db9c298a512fabdac68562b3f55377ff44b00c1c2f3efd18132da71f971a953a9318c57523361a160f9b7e3b51c524e95dd5ef4568ef18a800775e9d26e07131942d2be4ef22c0cbc13df01c68b1bcd3bce9bd51c4ced652adc4007be43b37c67a5c55ed4029e8ad15def8305c968621aed4cd4bfe079a6f48884d85680392ca92ba6e12fea6f4a056f79d67b19b05f90d684be7d45725f7967c6a467af43b86a6b1b9d9eed3a4248971c76a7ac29c292dfba4d75c5f7ba709a39058e96adf6dbd760d3cef4024bf3edc441efbf1147a2c108bd6f9eb439c1c5c4d3a6ea4ec3d92cef38136188bec9e0b6c0518d8b79ba59c5dcba393aedfdffb0b70d779c2b9765ce4452e7e3b08c4402b1a608320840fbe96d1eb8656eb1c20d9551ddf533b9f15e4eb5783756c53ddd3b14d807f838ac9680f89f1adfb78d68ccb06731a90beac5f0d709d5b88c75437a663cb962d37f96b8e8928477b5611228015d337f049e8b62e4dff8d0bb6cda24a5df9083e348bef12585f5f4c4d3bb3c7e78d550194a45251a0879a1624bf9dd35eb655c3939fea8909f6df395bebd02b68a17a897c9aaddd6e2e20461e303f57cdeb00ae0f23e60a94c19c771d8aa60533b93cedc1b76d2290a01bf43b2725f125befa575154e986c9c6205a1596cbaa2d13470c23422f2df7bece4e6ebd752e9389ae60857b52969d2ddefa9c034f1bf35ae3316304e949c8990820e26e6cffae4b388d1505f923706297f8db556537919ebbe3086023f12f4ded3b11acf2a6d973ddd8eb27b07c580bf448caa5a2ea116c5eaf36f7a6b17a85b3955dc8a44a620d8: +2ddd79e76064c2e6b322afb0c5c685cdbec62821cdfc0cb14db7d01ba3bf21a5f55b4ab64a2582212b96ccac0640e271944a34a286d035833045810e341824bb:f55b4ab64a2582212b96ccac0640e271944a34a286d035833045810e341824bb:a56674a1e1f09795251abe54ab43c298208fefc9bb9176fdb23e1e9f60f032647915567ebdcc2b869edb7055f4aba67ecfe7fa19eda45c06047c7a51848be9973251f85ff76f1c59e3654382858c9be123db8a9490c6c9b309b82d1e2ca6f4a07d00120283c6c295644995a96628612b8d6791573518e2556a688a09f149bc846a68bd0ef79279035710031ef0a8fed1dd0bf026125dc6648f86f64309942e18f23b12d1dc68c6f2770ca8b5485b369b0c92007a9461c139fcbb41175f316d4467060ab43d1222f5802404bf63c2df7e004bdc400ca80fe0d2cb68a210fbc3fc0b903209d5476e7a56baefb8fad7f328b72f327113e139414ba6f34e99c2eccde044e7a3ac70c580cd26c7450192ca4c823c7ac5eae876c0d1c8c768c1cb0b7ea41fc9b7d29437bbadab18e0f5ed1defe0cf6c0ebaa6b6d777f4dad9abddbfc0fd6ab5eeea803cfa01c0bd46f65fefa46901abbe0d89104e3bc4aee1f0599c69b67ba545ab9b54f5dee340ac69d88299e86822acddddce601122012f99299774aaf17c964edecb95e1277d462de64e9115a61ad98aa3d22e3ba6f8f1cd69b6b52b83382823f30e966bdad1ff5fc198ae32e9b68055d4392bc7c3df1015f128aee1e4fa3d4999e329f22f0ff6aa778bae0294a1df7436cb16a2bfcd74b463abe7cb4bac5362c89c9d1a378a2cb885cc3b26ab4be881ef1afc14430e10d26539ca358c3676286ad81ce1c9e78592af66f182bb1f7f862fe755bffb5be5c5f2b731c132e2388a76a1a7b1cddf05aed2ac9ec408475271942ccadd32e49d8791edf8b8de117551ce264a60b84105eae87e66f6a401d1322bb21a98e8acd277493254e504004f72c76e7903d2fa38fab717e94ce627947c4ea326bd2575c37310f3b4d843b90fa77d32d9952194150b62f850187a4fdf38466dfa0656c0a2e0b3f07492ac8e37e5d0df95cc89df3085a269291dc2512210d3fe44248d7ab996be099af64c22756666f8dea56c00b90677d1182500dd274fd0769253826d677ab16a557b08b3c52265498d85c4cb2b600ee0481b7c1c476a9daa8b88c71fc21b6f89bfdfece58da9e8d565652e4395bdf4c811b4f4f22d2b9613261f88c604c2974d3e977d140d046e1b6625b7071640d352cb7e7e65d46c613447be8dc5a200aa9acab46afccfebb6b1c31973246c34faaf8d26ea5e83be15718f8fdb0cfc444e2eb60f3659b020161c228e6b9240b7ac394cab812de10515766f22473ecca535594ce528a57cf5dab2eb32ab84:a4c396e19dd42e039184cd251188ffa245f0367c69c02d12474e5ca9e5c768a7ee3a3d47eb22d1ac9e04b704a74f416947f3f49a3242594e7b6390e82b60d505a56674a1e1f09795251abe54ab43c298208fefc9bb9176fdb23e1e9f60f032647915567ebdcc2b869edb7055f4aba67ecfe7fa19eda45c06047c7a51848be9973251f85ff76f1c59e3654382858c9be123db8a9490c6c9b309b82d1e2ca6f4a07d00120283c6c295644995a96628612b8d6791573518e2556a688a09f149bc846a68bd0ef79279035710031ef0a8fed1dd0bf026125dc6648f86f64309942e18f23b12d1dc68c6f2770ca8b5485b369b0c92007a9461c139fcbb41175f316d4467060ab43d1222f5802404bf63c2df7e004bdc400ca80fe0d2cb68a210fbc3fc0b903209d5476e7a56baefb8fad7f328b72f327113e139414ba6f34e99c2eccde044e7a3ac70c580cd26c7450192ca4c823c7ac5eae876c0d1c8c768c1cb0b7ea41fc9b7d29437bbadab18e0f5ed1defe0cf6c0ebaa6b6d777f4dad9abddbfc0fd6ab5eeea803cfa01c0bd46f65fefa46901abbe0d89104e3bc4aee1f0599c69b67ba545ab9b54f5dee340ac69d88299e86822acddddce601122012f99299774aaf17c964edecb95e1277d462de64e9115a61ad98aa3d22e3ba6f8f1cd69b6b52b83382823f30e966bdad1ff5fc198ae32e9b68055d4392bc7c3df1015f128aee1e4fa3d4999e329f22f0ff6aa778bae0294a1df7436cb16a2bfcd74b463abe7cb4bac5362c89c9d1a378a2cb885cc3b26ab4be881ef1afc14430e10d26539ca358c3676286ad81ce1c9e78592af66f182bb1f7f862fe755bffb5be5c5f2b731c132e2388a76a1a7b1cddf05aed2ac9ec408475271942ccadd32e49d8791edf8b8de117551ce264a60b84105eae87e66f6a401d1322bb21a98e8acd277493254e504004f72c76e7903d2fa38fab717e94ce627947c4ea326bd2575c37310f3b4d843b90fa77d32d9952194150b62f850187a4fdf38466dfa0656c0a2e0b3f07492ac8e37e5d0df95cc89df3085a269291dc2512210d3fe44248d7ab996be099af64c22756666f8dea56c00b90677d1182500dd274fd0769253826d677ab16a557b08b3c52265498d85c4cb2b600ee0481b7c1c476a9daa8b88c71fc21b6f89bfdfece58da9e8d565652e4395bdf4c811b4f4f22d2b9613261f88c604c2974d3e977d140d046e1b6625b7071640d352cb7e7e65d46c613447be8dc5a200aa9acab46afccfebb6b1c31973246c34faaf8d26ea5e83be15718f8fdb0cfc444e2eb60f3659b020161c228e6b9240b7ac394cab812de10515766f22473ecca535594ce528a57cf5dab2eb32ab84: +3abbdb0ba11aa1063bd26b02c116037862285babd215d240bc9c0926f4ecea81b8fc59438f8ce9e3785a473b22c8892c51eac2568c681dcc77b6f0e0799c4e33:b8fc59438f8ce9e3785a473b22c8892c51eac2568c681dcc77b6f0e0799c4e33:dccd55f922cd274f6975000adc8d98630c6d752c1202a9dd121048b93945af2b1110967788f99ec028e3d3b4cf82fb07173ea4401e3bb4b07b7b0b24b059a766339532d9df3e31b72c958c119d8dfa15a507af6c5f7e78fe270fa81b9df0f2e4af24bd99fbeb14e0033084d7fbf84ddedfd5ce56751d15908475df8af013d091173c1386b9139426cc6081ea165b8ce48194b8e18a9b91a4631344fe29c8e72818b71fa15c9292d13fdf5f9d18e29bd0291b8138de738fd3a36c35239022368b456f1facba90a0d80d6e311c5f6c6f04677e92373a5fc4738894dbed206c30da341b3b196c947858a6d2adc68aac3f20cfdbe0497961dae33470266d17ec719a59f0586f82f99f1c90ed7005a207219a55edc760f4eb8f2402647f6f77971ff7b634357b6b29bbd7ea05e2e25854e99c620f4b8b64739022ff0b338afef35fb6f41a53629a518eb93d66020fb353aef8dd071e09c916d4704acdf776b38ca9c59f211ff88c430a57e8f1713923b3f30ca86970a14a52db4bcbe60df4bc3cfdf254bf10f8afae87bd61b358f43cc296c0412964c4e00f71213397468517cb01379cb729c7b9e35bd50bdd98c3d3b76297a138b57ceb6c77742df0881d07668c08a630a44e6ed7eb206d6a56440710438a5111424b61aaeece40e900f5e3c457e9d6e31a79ec5b4b42b68e66e199309287cad65336fc7fe43f43cd8c773d3c6580d7217e2cabecd3eabc485c4acf47718c39b02c7858ff347cec7535eddcd4fc815df814569a88ae70f2733a6539f208c79cf4e7c4f9ea241a92e9515171361418a4c2e53c076aaabc47e4c971bd04b100c26282308857e06e7e5fbc4342564fb3b1ea4a17a925e91ee69122321d392b246965b86b54fd5c83fa5c474163f98a9f447d88cb59fe2cdf9f5412fcbeb3effac8976791c6a47b669a2fc55abe8e09e74157efcd1ca78fc10fa687010c6826c6e896ef5cd71d0fe4d1bd07c10dac3b03485edd2569a7eecfbc4e5d2ee2379859e265267bedaad69d93b7c1bd18f27ea42483c7e4100ee05b283039bfb9891d37c467ed83b88c794eab6bab9dc677892650e2d896fbfec1b1cdb721be30b0b8e5358709e165cbe3a182c93bc0a0cea2f8cf3a6257adf764534041202241a5279b668e40125fc094585a3c588aba82b67cd91d483e54300428426863a42364049d7c45a169385aa89bf377f0d32b07809b5871395ec053a257d93e48bbf407eb6091401e256546e31f9fcd24d2c5b333cf65785002f08d548db26ad1f3:981f20055a457525aee5616264e6af42e8b387cb08f8b4a73f9be0b366f1035bb30a1c874894cbece0a846d849b7ecc556585d0d3d395645807ff2a3ca5a590cdccd55f922cd274f6975000adc8d98630c6d752c1202a9dd121048b93945af2b1110967788f99ec028e3d3b4cf82fb07173ea4401e3bb4b07b7b0b24b059a766339532d9df3e31b72c958c119d8dfa15a507af6c5f7e78fe270fa81b9df0f2e4af24bd99fbeb14e0033084d7fbf84ddedfd5ce56751d15908475df8af013d091173c1386b9139426cc6081ea165b8ce48194b8e18a9b91a4631344fe29c8e72818b71fa15c9292d13fdf5f9d18e29bd0291b8138de738fd3a36c35239022368b456f1facba90a0d80d6e311c5f6c6f04677e92373a5fc4738894dbed206c30da341b3b196c947858a6d2adc68aac3f20cfdbe0497961dae33470266d17ec719a59f0586f82f99f1c90ed7005a207219a55edc760f4eb8f2402647f6f77971ff7b634357b6b29bbd7ea05e2e25854e99c620f4b8b64739022ff0b338afef35fb6f41a53629a518eb93d66020fb353aef8dd071e09c916d4704acdf776b38ca9c59f211ff88c430a57e8f1713923b3f30ca86970a14a52db4bcbe60df4bc3cfdf254bf10f8afae87bd61b358f43cc296c0412964c4e00f71213397468517cb01379cb729c7b9e35bd50bdd98c3d3b76297a138b57ceb6c77742df0881d07668c08a630a44e6ed7eb206d6a56440710438a5111424b61aaeece40e900f5e3c457e9d6e31a79ec5b4b42b68e66e199309287cad65336fc7fe43f43cd8c773d3c6580d7217e2cabecd3eabc485c4acf47718c39b02c7858ff347cec7535eddcd4fc815df814569a88ae70f2733a6539f208c79cf4e7c4f9ea241a92e9515171361418a4c2e53c076aaabc47e4c971bd04b100c26282308857e06e7e5fbc4342564fb3b1ea4a17a925e91ee69122321d392b246965b86b54fd5c83fa5c474163f98a9f447d88cb59fe2cdf9f5412fcbeb3effac8976791c6a47b669a2fc55abe8e09e74157efcd1ca78fc10fa687010c6826c6e896ef5cd71d0fe4d1bd07c10dac3b03485edd2569a7eecfbc4e5d2ee2379859e265267bedaad69d93b7c1bd18f27ea42483c7e4100ee05b283039bfb9891d37c467ed83b88c794eab6bab9dc677892650e2d896fbfec1b1cdb721be30b0b8e5358709e165cbe3a182c93bc0a0cea2f8cf3a6257adf764534041202241a5279b668e40125fc094585a3c588aba82b67cd91d483e54300428426863a42364049d7c45a169385aa89bf377f0d32b07809b5871395ec053a257d93e48bbf407eb6091401e256546e31f9fcd24d2c5b333cf65785002f08d548db26ad1f3: +8a44d6afc6c8eee1bc7d5f69e495b0b18ca7aee007dea7cf0d1714d785a9f4edd4f366b3377fa39b36f9ae14da404e2240490dbd8d796b1ab872dfcb83a59540:d4f366b3377fa39b36f9ae14da404e2240490dbd8d796b1ab872dfcb83a59540:de80326966536ce94996af2de7a07605cc4fcb9e75ee0a67a1e20932111de9b356d5beeae86cc5f564c10d66e3de95a5b99e844928ea8e77586cf3c10ad3633ddeeb1d9dcf3f94b70bf1ef63d238df204d705c0b174f83282545f5e4075f8d69a48179c29eabf5c1742ef39e1ad963bebbb66fce9491a984651215c2e750e6ee8365766440a84419e52dcf671f1c52eaa2b9902bcca4b37cffdbac8e7e7e6b0a5c8748efbf452df6163f4ca07b61f9a05ec20a2bd633389e670bb5454acd6f3a06335b5da9ec326264e962c7d9d06ce7e9ff04a0a5bbdfaa4c410866a572011651439f2dbce5dee667924ac4934d205496bd1d4df08bd0cb3fd2de73a2ef342ff0091e10e15b3b760a575df93cf1c97c01c5ab11c094bf34878206718f6b285aa5cc5127bd7f988b84a90495306fd9e99d8955e668d1a3ff10f65b7c479fac24119a3c10122d4d18a805b247df168c0a5100169b5572d17012d751a42e83376115e11561c160c15efad76d21f7abb430366475238631f84c88f838b0ac404c913d2fa12450238485c302fc201f44151c19bcbdc1190c12d1540831fb19581cb93172b0d2ff5c65f31caff20f813881f84e5ef9d5c165e096d254cadf895249aab8d4496c940a40f907bd40935a94f5e55b6dd051154100fe331770eff2bad6545619b8a33ef6462a50c0b2c4ed2fba4e4e383ebf2932e6192766a4aad1d6e2b692d9f2bdc23393e8aacfba323b534f84edf2dced7c94d51687daa27198a9144b312b716fe17014a7bed0c14a2438733d555c6564c8c1a3d997ebae7b3de8877af53c1d1a5029158a80aa0c87489fef270cdffe10d34b15c1a9693ae0390243e314cfac06ef6eefebccf43d42eac24ce9879429d2fc7253b3ed175825bc4da0762b4933a98afdb94b06f4fcd2ad3611aa999d7c1c8d852d01dd9e52648455a04eb2330a76fd942c531e514b5ec0728a89d34ca590ea99c88faa20dfb7bbf65654aa6c212beb8ad6bf7c777391cd49c39cf8ab51b95b419e3dfc8d94a93a1ef0223c6de90bf96218d8045bd4952a0d8372a5578c6aafa74ba662e3188e6a6e567e4d2fe8227d0743982a41ebfa0d310fe79fed27041790efd5afac2243e1d150b145015d9deab0eded6394ac36fc5fb201f5204fbd422a3604233015bb0a48a920e2e5e0d4deed672025f23cfba93889597e504c8887add46cfef4024afb8a26eeb7dcddb2397b44a1796367340042137028c3307626816c2931e61ebb6b69edcbcb612c9b181a285301ce46f82f:e0727eb72e84d2b82cdbd0a6bd2f49496316aae8351e4902acd5e3cc57346e7ebafdd92a90ded76fd0c6690d68bb2fedd613e44fa222be0126da520acc2c4105de80326966536ce94996af2de7a07605cc4fcb9e75ee0a67a1e20932111de9b356d5beeae86cc5f564c10d66e3de95a5b99e844928ea8e77586cf3c10ad3633ddeeb1d9dcf3f94b70bf1ef63d238df204d705c0b174f83282545f5e4075f8d69a48179c29eabf5c1742ef39e1ad963bebbb66fce9491a984651215c2e750e6ee8365766440a84419e52dcf671f1c52eaa2b9902bcca4b37cffdbac8e7e7e6b0a5c8748efbf452df6163f4ca07b61f9a05ec20a2bd633389e670bb5454acd6f3a06335b5da9ec326264e962c7d9d06ce7e9ff04a0a5bbdfaa4c410866a572011651439f2dbce5dee667924ac4934d205496bd1d4df08bd0cb3fd2de73a2ef342ff0091e10e15b3b760a575df93cf1c97c01c5ab11c094bf34878206718f6b285aa5cc5127bd7f988b84a90495306fd9e99d8955e668d1a3ff10f65b7c479fac24119a3c10122d4d18a805b247df168c0a5100169b5572d17012d751a42e83376115e11561c160c15efad76d21f7abb430366475238631f84c88f838b0ac404c913d2fa12450238485c302fc201f44151c19bcbdc1190c12d1540831fb19581cb93172b0d2ff5c65f31caff20f813881f84e5ef9d5c165e096d254cadf895249aab8d4496c940a40f907bd40935a94f5e55b6dd051154100fe331770eff2bad6545619b8a33ef6462a50c0b2c4ed2fba4e4e383ebf2932e6192766a4aad1d6e2b692d9f2bdc23393e8aacfba323b534f84edf2dced7c94d51687daa27198a9144b312b716fe17014a7bed0c14a2438733d555c6564c8c1a3d997ebae7b3de8877af53c1d1a5029158a80aa0c87489fef270cdffe10d34b15c1a9693ae0390243e314cfac06ef6eefebccf43d42eac24ce9879429d2fc7253b3ed175825bc4da0762b4933a98afdb94b06f4fcd2ad3611aa999d7c1c8d852d01dd9e52648455a04eb2330a76fd942c531e514b5ec0728a89d34ca590ea99c88faa20dfb7bbf65654aa6c212beb8ad6bf7c777391cd49c39cf8ab51b95b419e3dfc8d94a93a1ef0223c6de90bf96218d8045bd4952a0d8372a5578c6aafa74ba662e3188e6a6e567e4d2fe8227d0743982a41ebfa0d310fe79fed27041790efd5afac2243e1d150b145015d9deab0eded6394ac36fc5fb201f5204fbd422a3604233015bb0a48a920e2e5e0d4deed672025f23cfba93889597e504c8887add46cfef4024afb8a26eeb7dcddb2397b44a1796367340042137028c3307626816c2931e61ebb6b69edcbcb612c9b181a285301ce46f82f: +8a972dd0f1190c2b9d548f4ba58264bb04826775502a8d5c2b209ee88dcea5fb6d80375f3cf1aab283551df445d17e7d3baf9bcbecbbb267052e02fdb69144d3:6d80375f3cf1aab283551df445d17e7d3baf9bcbecbbb267052e02fdb69144d3:30b28948939aa263437e45c5c0254fb20e617ed0f3fa7dace5a0a8e0fe3c1fc4adb2809b61c5e8d92cd2f3de93b173be707bada94240c6262c160e8c782165beef99d0be8ecdad6316dcd734bbb90a66cbd5b1cb4fd8f2226cea948e4df76bbe251d478f5c3fe0d6de4be54f67f502b2804f628b79a550fb1ac483ad2ba16637c4bc9da67fb4f98659c4c4394d16b6d14b3e0b0c1e625d710dcc1c11df5d34147b1ec5a417b9e21f908cfc523d43e3f181c7209cc56bdb5a21628695ed320f8d4c07fd6d84aa03426f21644aaefeeec311c74e9499936047350a9bf5b703962e77ce551336835fc32ccbd2c90ae52e24d47d8dcb987abd121d3f746b5de230f26469603fb0c4a8f6cd7973d7da882ed1d6e4d9c5a46ec2c21940ad3389a186014ee97278e5350988b15ecd9ea7456b3cb55e4d3093f13a875b50d6516378ecaf58d752c6374ed15638409311fcd379d122c8d8c59b86f4e8dc46adb730a933846e0bd248d3608252d970b504c813c6dea9fc88a3de641956dca291204d390b6b39981f8c0a6bcfc31ca0744420662a9b35eb3fc211f810a3e8062500b1e49bdf857665ff32a9ba76194bbb77fb9c15412964244b9865f73ded9f25b49b425aa253d807d9818292763a513ec80747344fba0acfe593cc26b1330bb9ade66c4e88cf1baed6d6e7b750e6c7239d7bcbfa3fbe45405a63b96d5034cc0c07ffc3b50858081d1955e2d2fe5be5fda7a8996943768b055170b7fd52f0a32097fe1b7a94f1bf879a0cbabe10ac9a7cc1f9f55068c48e3ccc065136431018d38d20109dc95d99cc2bbe7c627ab1a8aa5f431613b790c2e6526cf04fdc9e55f51c055f3c2045a675e3a1e54ba409f7aefa7e4aa07a2bbd5e4ab16321a9f099694391fda68a74581e2f1f11dd9a6d524b1b83260db57b72ef29c28c8db5c37fd185b7c2d8455090653af332dbc82bfb0db5dccabfb6b28caa350525cb54cc84e553e1cf3954b612393e7993ff7e8bf5ece3f145094dd7a27cb47f227476f289235251f772b3ba776bb773af0cc5f786a3fb9e931a530cfbd891cb5a5dfe25169ef933cc82c9080f323961a120158e4bbd71134ef1f90108b815c289d4e9a9589ec64c05fbb42a21b23d16e2a64678aecfab65cd9a806c598103d41f7009776317831feddd1c9002d4a92204f97ba9490c61469803072102524b9df519005f98af54d60ca5ba60b55b096a4ac2b16eb9cc81973c3135d3fb6873dd9653800a22bb5d0d6117ca5d916553be39c9a3b511eb3db730:bd45b3c045850ebef7b80dd1deab48037b1346c71deaf1e58f2a7b162674f94d1ef3d4239037330bd6335fe4f0149250901f00a8e46be5fa0aaec69de06d730430b28948939aa263437e45c5c0254fb20e617ed0f3fa7dace5a0a8e0fe3c1fc4adb2809b61c5e8d92cd2f3de93b173be707bada94240c6262c160e8c782165beef99d0be8ecdad6316dcd734bbb90a66cbd5b1cb4fd8f2226cea948e4df76bbe251d478f5c3fe0d6de4be54f67f502b2804f628b79a550fb1ac483ad2ba16637c4bc9da67fb4f98659c4c4394d16b6d14b3e0b0c1e625d710dcc1c11df5d34147b1ec5a417b9e21f908cfc523d43e3f181c7209cc56bdb5a21628695ed320f8d4c07fd6d84aa03426f21644aaefeeec311c74e9499936047350a9bf5b703962e77ce551336835fc32ccbd2c90ae52e24d47d8dcb987abd121d3f746b5de230f26469603fb0c4a8f6cd7973d7da882ed1d6e4d9c5a46ec2c21940ad3389a186014ee97278e5350988b15ecd9ea7456b3cb55e4d3093f13a875b50d6516378ecaf58d752c6374ed15638409311fcd379d122c8d8c59b86f4e8dc46adb730a933846e0bd248d3608252d970b504c813c6dea9fc88a3de641956dca291204d390b6b39981f8c0a6bcfc31ca0744420662a9b35eb3fc211f810a3e8062500b1e49bdf857665ff32a9ba76194bbb77fb9c15412964244b9865f73ded9f25b49b425aa253d807d9818292763a513ec80747344fba0acfe593cc26b1330bb9ade66c4e88cf1baed6d6e7b750e6c7239d7bcbfa3fbe45405a63b96d5034cc0c07ffc3b50858081d1955e2d2fe5be5fda7a8996943768b055170b7fd52f0a32097fe1b7a94f1bf879a0cbabe10ac9a7cc1f9f55068c48e3ccc065136431018d38d20109dc95d99cc2bbe7c627ab1a8aa5f431613b790c2e6526cf04fdc9e55f51c055f3c2045a675e3a1e54ba409f7aefa7e4aa07a2bbd5e4ab16321a9f099694391fda68a74581e2f1f11dd9a6d524b1b83260db57b72ef29c28c8db5c37fd185b7c2d8455090653af332dbc82bfb0db5dccabfb6b28caa350525cb54cc84e553e1cf3954b612393e7993ff7e8bf5ece3f145094dd7a27cb47f227476f289235251f772b3ba776bb773af0cc5f786a3fb9e931a530cfbd891cb5a5dfe25169ef933cc82c9080f323961a120158e4bbd71134ef1f90108b815c289d4e9a9589ec64c05fbb42a21b23d16e2a64678aecfab65cd9a806c598103d41f7009776317831feddd1c9002d4a92204f97ba9490c61469803072102524b9df519005f98af54d60ca5ba60b55b096a4ac2b16eb9cc81973c3135d3fb6873dd9653800a22bb5d0d6117ca5d916553be39c9a3b511eb3db730: +12380c45a79ade0f483c881aaa3730438b083590f404dc9e601f7615f375a628d66fc59ae917f76d24ce8ab8ee03fbcb715d5eea4b08392b591e648591c73c89:d66fc59ae917f76d24ce8ab8ee03fbcb715d5eea4b08392b591e648591c73c89:684523c2e7fa8b4bd7548c4bacaa8678a330dbbb960632940166b2cc9afc1535c80c112c8dc4ada7629233fe909055237d513e292af15ad7692f115aa092da657532f51899c3f7f5d9d407ed5c163eb3950480a4122a0992981f077bc867f906075407ba9849c4ea0473ce540a796744efa3860378e1b89343e583d0807e5a67c4d5bd7ce64129fe902b8cfabd2c21fa3d2a10e9bf9ea5e5473ae250c9160509972678f9a740e6cadb3b52f502fa616cffae1def893d54e41e54d326464c9f435c63505fb15e3eeaf5021c65dcd010f840aab317c8605dfb1a0c8a3d5549861b69af2c93d86c981df3a51c5bf5785c2f852610e44fa4ff1c7161152e5618384744fe83babf0bcb7561789a023125f6242a183cac9549c932733a868aa182656e2ba0a8c0be106996a85cebf1bdad123b982b4e055510879482021daea9d8f26c588e6cd10126cb3196880356bee8f298bca306ec5699c7576b765087c253a60214010c6ed70d871cfc8738018a0edb57f106b4218d855eab2c91f39f858b3f25905631a0eee29856fd34f7b8c9ba51c1c4c6a735d6c7a13d220d7a566c3f506c72bc7417ab37f0d6d796ffc71df9dc7c6e137da56b7a3e10cf0b1abb3ffb70bc66293b5d75b405ed8bec0d6fcd06925c381168ac188d0b8a1af0839f5bde843b6991e5a5d6cd66fe6b0fde867c086ed43876919a1b7233d8d7e1d2742f61c77d8e5991689c8328676655b76a3750560e75d1c7e85e3c0085059331094bba5710032cf679a525c78b31700e6d91f75294c422489297e1735943e417fcd35580582fdd0239b51146530cc09d83b28f0a1d642220dfb99bad62f39541035081d65d778ddf3239ba0e6fa9914b17b397a534cb8fd3b4ff42a8d8c8ee66153fbb1ff0fa54f7bd03278516e6341af80fcd1fcee70c359d205368ac490d75a354512da46ba7634c15b284b24477808f17633360a4b49fb3bcaa841841cf92417eb24ce482d5a24bfd2dac372231da539a05420002ff7a20c476097da06f59f03314e6059fad88c50c3baac03cefa7cd8211d2461b1660ea6bcf476838c91a10074eb4b40e6e974a945a67f6ee6904231ef04188f1ead5baf35694efe301edc7e866da23b5a6c58f01b2a52cf3ab805edc5c1368626b95b94eb4645b693ec880f2b8117a693afbdcd2482431890f410bc580530fef375879c2e46049ca891a2c3ecd6043ae80d8af346634674c6dfe905997de5d05d62009eeed277502fb5a5a3155eeeeb67348b60d89a34a7812639f541ffe:02b25174a3dd5219ed48b2c94ca212b63a6a3a2597703c07b7f0c965c3c6ac2eb450efe38716a2a28b3f89846b06ebdca4bd09aa581f24e84d80fc10ac1a000a684523c2e7fa8b4bd7548c4bacaa8678a330dbbb960632940166b2cc9afc1535c80c112c8dc4ada7629233fe909055237d513e292af15ad7692f115aa092da657532f51899c3f7f5d9d407ed5c163eb3950480a4122a0992981f077bc867f906075407ba9849c4ea0473ce540a796744efa3860378e1b89343e583d0807e5a67c4d5bd7ce64129fe902b8cfabd2c21fa3d2a10e9bf9ea5e5473ae250c9160509972678f9a740e6cadb3b52f502fa616cffae1def893d54e41e54d326464c9f435c63505fb15e3eeaf5021c65dcd010f840aab317c8605dfb1a0c8a3d5549861b69af2c93d86c981df3a51c5bf5785c2f852610e44fa4ff1c7161152e5618384744fe83babf0bcb7561789a023125f6242a183cac9549c932733a868aa182656e2ba0a8c0be106996a85cebf1bdad123b982b4e055510879482021daea9d8f26c588e6cd10126cb3196880356bee8f298bca306ec5699c7576b765087c253a60214010c6ed70d871cfc8738018a0edb57f106b4218d855eab2c91f39f858b3f25905631a0eee29856fd34f7b8c9ba51c1c4c6a735d6c7a13d220d7a566c3f506c72bc7417ab37f0d6d796ffc71df9dc7c6e137da56b7a3e10cf0b1abb3ffb70bc66293b5d75b405ed8bec0d6fcd06925c381168ac188d0b8a1af0839f5bde843b6991e5a5d6cd66fe6b0fde867c086ed43876919a1b7233d8d7e1d2742f61c77d8e5991689c8328676655b76a3750560e75d1c7e85e3c0085059331094bba5710032cf679a525c78b31700e6d91f75294c422489297e1735943e417fcd35580582fdd0239b51146530cc09d83b28f0a1d642220dfb99bad62f39541035081d65d778ddf3239ba0e6fa9914b17b397a534cb8fd3b4ff42a8d8c8ee66153fbb1ff0fa54f7bd03278516e6341af80fcd1fcee70c359d205368ac490d75a354512da46ba7634c15b284b24477808f17633360a4b49fb3bcaa841841cf92417eb24ce482d5a24bfd2dac372231da539a05420002ff7a20c476097da06f59f03314e6059fad88c50c3baac03cefa7cd8211d2461b1660ea6bcf476838c91a10074eb4b40e6e974a945a67f6ee6904231ef04188f1ead5baf35694efe301edc7e866da23b5a6c58f01b2a52cf3ab805edc5c1368626b95b94eb4645b693ec880f2b8117a693afbdcd2482431890f410bc580530fef375879c2e46049ca891a2c3ecd6043ae80d8af346634674c6dfe905997de5d05d62009eeed277502fb5a5a3155eeeeb67348b60d89a34a7812639f541ffe: +d1b3430d4e63aabfa9ef96bcbaf1fa6a9eb5219dd44df3b1a61563dffe1ccb28c28a05195245290ecd38535585ce51f3c235c5d650c8c57c2f79bb0ac0e80834:c28a05195245290ecd38535585ce51f3c235c5d650c8c57c2f79bb0ac0e80834:076c0c8762e4bc003c360a12a19598050551d16b4b8da0fb9c4afcc81adbe61995f25cbc28dca420bfa9461054d3ee00ad78183e7f26df6898af9a4d225fcab67c042e9a13525d1f75ff0e3d8da80896b728f3e2db65944ae0717d775990b59e5b70434bd4b3ee452f10ac0610570b38220832968f544d3e4d119b1d4b5015c6cdf4cf220b56b5c0ccd8e398d5e4a58da3b0e2b270a5d39b82abb7f9d27a419018550b6200ae51c84882f086ae7ea5351671b6dd960923ad6befc13409879a8df619bdf6c88a6fe1ecc0f0f3aa219fb61902be48a53df2bc66c56f1c1d17f7e6167d255165f174baa9caf53c73cbbb7cc2c7c087f43abe2aed5a21fe4290b8d67960a8a9cbc2a57abe22654dc184cff9168bb697270375fe88d5c49cf95b06cf9d0dac81fbd9c0d7b82d05ed2c3fd49ccc29404441712545f9a991e4f0ddb62190838296f967299a38607226d8a681f0a8f3c4384fd18b30257c463c0abd0f4f6f1225a51b762d6d0ac7d59cd2efd698b8d13e23d70409f6b07d695c1671cd6f59443b1db0ab35b9dc0640e4c6d1ac50475d28ef94f81790e2e5b2545514b2a49c5c2153459be540890f53bc18e4a16dcb5dcf50f37a95c606fdf48598e52af3179a2048615d93d97e0599b7088c1174bb9f15e37018f99acbce5b1302f8d8ce2ab85437feeb0caa7784dc83c9e7c36fe059906b030a86a3ded0ab9d8b73529d475e661a0808d6d3f0907f8528873f08d5748be1d69712e85262d77bdf13bfd18a5cde6f71462673ab29b1617315a9a6e936a8e81a8e43bd0f6644a5c69eaaac89bdaa99cca803833705e5afa69b3bd1d0252b854650f2199791e6aca7c75a861283216233a2633a6aeff9d301ee5cb4dd72c08a45cdae8f5458c095b22e759c43b49b98e9f4cb33d5dea879449eae73cb874c73594325ebf68c1ed4064b6f61ab2f014a2f19f32e12b33c5eaa8a29204d5eba58dc075072fe399be7d1ab1808208fb408123bdc0b4ab3130f9f706dc3eb194b605e73a32f125ae491285ce6039fb623c38b81d5aba0f5599f6c86e872486b4e9649daffe3a3d06cb073dd3bc6f4e10a18700e45722d78a6b0972dc94d5c7a7b6641757b796075719d7b8ec36a1e796fb5f8fe6f1b79a0859cb4d67cec05ed914cfa32c1ddfe218ef963436c3a1148ac2cf909df7359890657463a4ea25fed59618a0681a1217e22d64ef9d9b4559d0a0f6b3ce8d847930b232301caf44cdf7a3f18a2ac130b92cfd9c03360557b5f7c4775462a1071f70344c718374b:4cb6ff5dd706b1ae816cdbaf9e9e1edc80a66284f94652d50ec14e283b2adc592fd084337144ffa712dc34ce8e610668a65e969f05ceb54786304d0d58d31a08076c0c8762e4bc003c360a12a19598050551d16b4b8da0fb9c4afcc81adbe61995f25cbc28dca420bfa9461054d3ee00ad78183e7f26df6898af9a4d225fcab67c042e9a13525d1f75ff0e3d8da80896b728f3e2db65944ae0717d775990b59e5b70434bd4b3ee452f10ac0610570b38220832968f544d3e4d119b1d4b5015c6cdf4cf220b56b5c0ccd8e398d5e4a58da3b0e2b270a5d39b82abb7f9d27a419018550b6200ae51c84882f086ae7ea5351671b6dd960923ad6befc13409879a8df619bdf6c88a6fe1ecc0f0f3aa219fb61902be48a53df2bc66c56f1c1d17f7e6167d255165f174baa9caf53c73cbbb7cc2c7c087f43abe2aed5a21fe4290b8d67960a8a9cbc2a57abe22654dc184cff9168bb697270375fe88d5c49cf95b06cf9d0dac81fbd9c0d7b82d05ed2c3fd49ccc29404441712545f9a991e4f0ddb62190838296f967299a38607226d8a681f0a8f3c4384fd18b30257c463c0abd0f4f6f1225a51b762d6d0ac7d59cd2efd698b8d13e23d70409f6b07d695c1671cd6f59443b1db0ab35b9dc0640e4c6d1ac50475d28ef94f81790e2e5b2545514b2a49c5c2153459be540890f53bc18e4a16dcb5dcf50f37a95c606fdf48598e52af3179a2048615d93d97e0599b7088c1174bb9f15e37018f99acbce5b1302f8d8ce2ab85437feeb0caa7784dc83c9e7c36fe059906b030a86a3ded0ab9d8b73529d475e661a0808d6d3f0907f8528873f08d5748be1d69712e85262d77bdf13bfd18a5cde6f71462673ab29b1617315a9a6e936a8e81a8e43bd0f6644a5c69eaaac89bdaa99cca803833705e5afa69b3bd1d0252b854650f2199791e6aca7c75a861283216233a2633a6aeff9d301ee5cb4dd72c08a45cdae8f5458c095b22e759c43b49b98e9f4cb33d5dea879449eae73cb874c73594325ebf68c1ed4064b6f61ab2f014a2f19f32e12b33c5eaa8a29204d5eba58dc075072fe399be7d1ab1808208fb408123bdc0b4ab3130f9f706dc3eb194b605e73a32f125ae491285ce6039fb623c38b81d5aba0f5599f6c86e872486b4e9649daffe3a3d06cb073dd3bc6f4e10a18700e45722d78a6b0972dc94d5c7a7b6641757b796075719d7b8ec36a1e796fb5f8fe6f1b79a0859cb4d67cec05ed914cfa32c1ddfe218ef963436c3a1148ac2cf909df7359890657463a4ea25fed59618a0681a1217e22d64ef9d9b4559d0a0f6b3ce8d847930b232301caf44cdf7a3f18a2ac130b92cfd9c03360557b5f7c4775462a1071f70344c718374b: +033e003d7aab7bc7fc8ac204c733799ae553c3fec53f10dbf795b5f4b87f1c95682f46f5c056dd45ba0b5a782031f9596a73aa292ca2326beda74a52fc32b716:682f46f5c056dd45ba0b5a782031f9596a73aa292ca2326beda74a52fc32b716:596aa2c40b3318878938ebc138db274bb38a5201eb7caf875e6c645791dae012bdefd485e6bd9d8499c42a2ae86cf32b18002e76bb582cca0dec4815ded8a1211f8fc8857fce1d57f6151d88787b978fab56bf926b1533e19499e8bb99158cdd6e980f6ba543ae831f9dd134b0fe6d5c24887dc7a8d4781dd9b7fc5dc9464b045cbf9d1ef5036b5bf28b549ac7aa8fafb91adc9feca7a14554d110e310c749e48533f359c70f05fb7aedef136636b8ef7223886539864ee52d34118b4b8b74e08fe6b65896e4b19b6d7c3f2528265585481710d2d74948eb4b1708a50fa74021bda4b361bc68d2a5d202109f8d28d8aa67d78c1136cd2e903c8dfa175af7bd963b73dae495873ccdae62bfef885636dd83550ff9c05c37ba3389d1543685d89483b0c104e7efbb7702c5a0398ac720484c50936835ee9df253f0ef8cbef3e07de969511ccbf87557493a0b972ef0e8e629cf3822db21286ed727661bd31786fca1421106dacdee1caaf49454e854794f704d22a95a4c8e6b1c2feea57e56238c2096f1cc578647fea544d6764482bdf5148879a25f943db16f29021b9ecfe3e090b425c81c7009842e1c7a02d91ca60c1201c3bdae9c5373af03f2f4dbef40de8d9b21fed68dee510de0427234caa1c20a3ae549954834c93373d913b8750f23a03780d7a9454ed6fe51fd2d276b9d4aa32de05e03816e64e9466f4f0e224651428d342cbcc697170a47ef996bdacbce91117ca1f8455b25b2b08443e9914e3d90c489eeaa7731ddea2123d55d67b16683fb7c8236aaa5a1b0fcaf8d170011dbe9aa2857be612cbb85ef69e56831b4dacfbc7a59b465a66dc7412ddb3d6af4ebfd705864e7d4fb99a6ccb48b118368feab02a340c432768de0e067871e9ea808d6d993815829e71f6c042b664995098fee94d543df15e5b16957031bd238bcadbbdcc576affb640303d69c5b250b3a539afd127f7ee2609e52e5154fbdff3e45f9c44066656d561e0f64dff2805df88e30a380530822413a7ab76a1b9a865378d24763069a814002a9a9d03795ca8d2b5bd1090393e9e4b1ff7d7f0eb84e712a018f68c9e384f0a0aef3967879284f409e30d2365086e66952278ca9b6f90e8f69a48d9b28bb4c4ed632abca3af4144da7422bf51992f734731453c7a33e15e59f5308129d6a774a94586f723311179176c0948fff4e30c1b959812cac977cc74347b007940f2fb962a90d66066a6de8801984dee4a532d4b0acd6dcaf06727bab70b3866232234c9100bfdc669f77ca49:edb4e020d676fac6a845534880bf6136374a8b7f2c5385bb9ee225381f494efb74a55b413ae0ea70add61bfdfb87fb42d5bc0c5359dddd573d538ae93a6b3609596aa2c40b3318878938ebc138db274bb38a5201eb7caf875e6c645791dae012bdefd485e6bd9d8499c42a2ae86cf32b18002e76bb582cca0dec4815ded8a1211f8fc8857fce1d57f6151d88787b978fab56bf926b1533e19499e8bb99158cdd6e980f6ba543ae831f9dd134b0fe6d5c24887dc7a8d4781dd9b7fc5dc9464b045cbf9d1ef5036b5bf28b549ac7aa8fafb91adc9feca7a14554d110e310c749e48533f359c70f05fb7aedef136636b8ef7223886539864ee52d34118b4b8b74e08fe6b65896e4b19b6d7c3f2528265585481710d2d74948eb4b1708a50fa74021bda4b361bc68d2a5d202109f8d28d8aa67d78c1136cd2e903c8dfa175af7bd963b73dae495873ccdae62bfef885636dd83550ff9c05c37ba3389d1543685d89483b0c104e7efbb7702c5a0398ac720484c50936835ee9df253f0ef8cbef3e07de969511ccbf87557493a0b972ef0e8e629cf3822db21286ed727661bd31786fca1421106dacdee1caaf49454e854794f704d22a95a4c8e6b1c2feea57e56238c2096f1cc578647fea544d6764482bdf5148879a25f943db16f29021b9ecfe3e090b425c81c7009842e1c7a02d91ca60c1201c3bdae9c5373af03f2f4dbef40de8d9b21fed68dee510de0427234caa1c20a3ae549954834c93373d913b8750f23a03780d7a9454ed6fe51fd2d276b9d4aa32de05e03816e64e9466f4f0e224651428d342cbcc697170a47ef996bdacbce91117ca1f8455b25b2b08443e9914e3d90c489eeaa7731ddea2123d55d67b16683fb7c8236aaa5a1b0fcaf8d170011dbe9aa2857be612cbb85ef69e56831b4dacfbc7a59b465a66dc7412ddb3d6af4ebfd705864e7d4fb99a6ccb48b118368feab02a340c432768de0e067871e9ea808d6d993815829e71f6c042b664995098fee94d543df15e5b16957031bd238bcadbbdcc576affb640303d69c5b250b3a539afd127f7ee2609e52e5154fbdff3e45f9c44066656d561e0f64dff2805df88e30a380530822413a7ab76a1b9a865378d24763069a814002a9a9d03795ca8d2b5bd1090393e9e4b1ff7d7f0eb84e712a018f68c9e384f0a0aef3967879284f409e30d2365086e66952278ca9b6f90e8f69a48d9b28bb4c4ed632abca3af4144da7422bf51992f734731453c7a33e15e59f5308129d6a774a94586f723311179176c0948fff4e30c1b959812cac977cc74347b007940f2fb962a90d66066a6de8801984dee4a532d4b0acd6dcaf06727bab70b3866232234c9100bfdc669f77ca49: +ee55fcf70a275c726bd4856683b347decfd422f1826c07a932cb85be9fa4ef3cdfcffb5e1553789d56a9f3914bce500d07c5ac311f927854b2cf1e5833c03237:dfcffb5e1553789d56a9f3914bce500d07c5ac311f927854b2cf1e5833c03237:b8c845cf7c5485f0622d1ddc17f7a0f6f0fd7074fe194b0e0cd42650cfc817f57f095f8cdfad1ebe0dfbc1bd7617ab4f204e9d55d81a7c8a433940ec6f17c8a8e3d56c1afb0af374bd32d54ef7132d26b89c470c2ab5be16fabb4c75193d6da59ba2fd157e9ea4e0c5c08a5202f5edc6a61701f08bb344ca6455d75d145adb244c534c8cfc623f4d4b6767594b39a7690beeec4df9746a57ffee051454c4278ea43c810ff13cd769615f9d05d4fe4a51583e80c015dcfed9af05f93d054d34ffd939bdd8f0518fa3030a964dc9d80df00f1635824072cdf29bc80259209d50f56fca9fbd6ae1514a671989cea4f6846bc19179097cca40c624d7edbf91fb5b2539ebbd502d3646711430bae423fd115848093318b7d087ef1e3b894bc3b9ea27af853fca8595d36fb7299969162f2ed6a2b55075b2c630802857176dec4cb5acf2b13a35a9949b912bb57d81eb0c8a8adf3cf64cb571bf5f3d71f987d64d74e919a00336e57d35ee4eecfc657000dd5b12995ee1b116591ce58e56de25b29c94829d1d68521b9558e4725ec77039069c0cd17b2a003359e9e1e112c7590176cebce7f001f1d136e818f4818cfd94745afaab56f1a406f97dd9e61b735266d682ad7df26dd70cde0b57fea7db2df832fa88a35f539794884ddc41218403016cb6d5221f3feb5d3aee4a9840a913072d29f8d1a9367bb0bbf545f7dae7c00a0d0c0342231ae462bb742e1498ee584ae6c83f2f1f2d0452bead982268cd3cfde78ff422e226bf7b2af1137757797fb02e5275c34809d54ca9ee2a65275e6e5cffdd20ad1fa1ee0bd8b21e04ce829e02cdb63c48bfcdd86d3a08c59789c9d78e36181defeb7227107275ed6b5ccb127cd72b374e17f5ee0b5e47b4b3e14a8ec6d86bb7507187f28db32b3f3fa1ca13446fe5253ee783645e794272799a863b4fca99e443cbaa05de3c50edf3d5cd7c10529c6c09a0c1453406ac7ecafa9b3a1f369d68f3c618f58efc359df2f3fcd2478b55a41a11f2487e7f70ec293b3eccc700ef444a33d1eae9849c5b76d29afd5a23861aef4f2a7ba3f666301fdeb5d3d8f0dc9ee2e014b24c7465dee3c0964edd49ed49edabb5ca7afb99574d001e5812a085231f241b6b08c73e80fb44bb2adf554f14fd6dce94a6f63623d9c1deb41ad101651a6b67ae5234daae81979fbd823389649a3b0a06c68b80468a991d3007748751fa69281db1b94d6c160a1cab50943cdbb8dea5750906b3c6595bb580dedbfae57464cc7a651d4c51dbb5fa980597d17669:9d8cb2eaf3ff3e0c2bc672e1d255c5b8e80731bff6f6aba517e13354e851080f4a8bb8121b2624244c9ee95c8a092f103703fbe66f9cba100d2e91ed774ac907b8c845cf7c5485f0622d1ddc17f7a0f6f0fd7074fe194b0e0cd42650cfc817f57f095f8cdfad1ebe0dfbc1bd7617ab4f204e9d55d81a7c8a433940ec6f17c8a8e3d56c1afb0af374bd32d54ef7132d26b89c470c2ab5be16fabb4c75193d6da59ba2fd157e9ea4e0c5c08a5202f5edc6a61701f08bb344ca6455d75d145adb244c534c8cfc623f4d4b6767594b39a7690beeec4df9746a57ffee051454c4278ea43c810ff13cd769615f9d05d4fe4a51583e80c015dcfed9af05f93d054d34ffd939bdd8f0518fa3030a964dc9d80df00f1635824072cdf29bc80259209d50f56fca9fbd6ae1514a671989cea4f6846bc19179097cca40c624d7edbf91fb5b2539ebbd502d3646711430bae423fd115848093318b7d087ef1e3b894bc3b9ea27af853fca8595d36fb7299969162f2ed6a2b55075b2c630802857176dec4cb5acf2b13a35a9949b912bb57d81eb0c8a8adf3cf64cb571bf5f3d71f987d64d74e919a00336e57d35ee4eecfc657000dd5b12995ee1b116591ce58e56de25b29c94829d1d68521b9558e4725ec77039069c0cd17b2a003359e9e1e112c7590176cebce7f001f1d136e818f4818cfd94745afaab56f1a406f97dd9e61b735266d682ad7df26dd70cde0b57fea7db2df832fa88a35f539794884ddc41218403016cb6d5221f3feb5d3aee4a9840a913072d29f8d1a9367bb0bbf545f7dae7c00a0d0c0342231ae462bb742e1498ee584ae6c83f2f1f2d0452bead982268cd3cfde78ff422e226bf7b2af1137757797fb02e5275c34809d54ca9ee2a65275e6e5cffdd20ad1fa1ee0bd8b21e04ce829e02cdb63c48bfcdd86d3a08c59789c9d78e36181defeb7227107275ed6b5ccb127cd72b374e17f5ee0b5e47b4b3e14a8ec6d86bb7507187f28db32b3f3fa1ca13446fe5253ee783645e794272799a863b4fca99e443cbaa05de3c50edf3d5cd7c10529c6c09a0c1453406ac7ecafa9b3a1f369d68f3c618f58efc359df2f3fcd2478b55a41a11f2487e7f70ec293b3eccc700ef444a33d1eae9849c5b76d29afd5a23861aef4f2a7ba3f666301fdeb5d3d8f0dc9ee2e014b24c7465dee3c0964edd49ed49edabb5ca7afb99574d001e5812a085231f241b6b08c73e80fb44bb2adf554f14fd6dce94a6f63623d9c1deb41ad101651a6b67ae5234daae81979fbd823389649a3b0a06c68b80468a991d3007748751fa69281db1b94d6c160a1cab50943cdbb8dea5750906b3c6595bb580dedbfae57464cc7a651d4c51dbb5fa980597d17669: +49c298a2db3d2589c9fe16a4e571e5aa23cbaa777b86470290a3eda7a5d3e96bdac523d6374c8ff15fc4ddc713715ac35cf5547fc1b1b2646b63fb41a7f21621:dac523d6374c8ff15fc4ddc713715ac35cf5547fc1b1b2646b63fb41a7f21621:3582eeb0d371df385de88baad380cb0cdb60eab2baebb3c79837753d08e1cb78c0bd76dd1104454956d571ceb7e6b571a5236835d784b50ff66057b13595e7d0c8f25d08ae8b54b6123ba08151ac7db0c56a980f7f0bb39a54b437f54851979986ab1367835e5c4f3a3b3d760d3827e76c568ae7aebbb612e775bddeccd334ac6bcd3253abc29d4b7c3f10362666f6ae75080370a36cba55db3a91cb5789e4d6f9efea4df1dd7730a5e27960d53b5121948cce5af653fff1d5b4e5b0a88c718c49b31c793d88c1cc45ab8da29d05e906cd0594b5f6638c8ec3f1760ba423b5ab1d08a58770afb0f139abd349c1bf160d8902239ce24f19b4e1be095f7ed165f3931e3cbcc307e9fc5c658031228e55cbbeec0d0bcf8f695154a9eed1bef35228789bfc0d238b8372d318328c1339fea08814db8621abca3aeb82098b5aa87bb98f5e40522a0888532c1748453db2d2b3943e4abb312de319aec48cc1c94775972953fb6496b8168937623510cd48c8b247956d3168486c176ae7a4cb384eacfdabfadd9fba30a23b811bd779f3cba54338c28bb3382238ed3b8dd21beab2f5cade28c5e09b31a454808a5348122e3ae3812296f7869c3865c3c9d8fe18bd812f2e60e914975cfe1bef8dbb8097006f0d7cf3fc15eb95c27854b14312b88d528015af69fb7505b8f32703f64eb1c958f046dd251242f8bea7467fc7291d095e9696e11aa45abe7924e856351535aa0773d3d9e61cc9a2d89b5b0774d7645ee1af7eb6fcd440bc69d43edeaaf935fd2a5295ac19a97d70af9298830f81c0a509f242f473372478fa5879fb2cb8511080fc2ecd8259b8c3ce9e8b640761dc7927c32e7f5bae97a8b8ac935662e5f45d14cad6d34affc9a19414c4566f45f977396710894c5399ed4480f18e90957faa76ccb512a2d07573058a95b42fe1810249d1c85ec431a049d1aecb0f118379bdc3f1ee490bc8a054c32c3dac7659966cdb66f995ac403d5e79eb6b25b3f3f65a6ceec220d66c05f8a8a98b80799ba4f2c6dbbb4dfb5862c9a46bca013ebdfaba7494a30ce14606afc0b0f993143fedee7896d9a6bb81499166ed02e94186aaf32187aeb6e282501bca43b57b7efa0939c934bc8fbbd26c44b618335a35c692ff996a5b95d327df9b2a6621b3b0f190db1f36d911d1a663a4ebf9a2854bb4f4061095b69812c82c2ffe3f92e9b44d2ea63169881cae8453d6eef7cf69c25a28b3f8ddc70148ef26721a3c1f2e62d9d10cea42fca3facd74673a4e7f33507364aa286c0f38d7:2a439c73c98117fb2952e2b161f7f3b99e7d39bc697f794075db7b634d29f1ff5724f677f8312ad515b097cca9dfc30e79ee8a7c9dd728bdd45df859c7bde30a3582eeb0d371df385de88baad380cb0cdb60eab2baebb3c79837753d08e1cb78c0bd76dd1104454956d571ceb7e6b571a5236835d784b50ff66057b13595e7d0c8f25d08ae8b54b6123ba08151ac7db0c56a980f7f0bb39a54b437f54851979986ab1367835e5c4f3a3b3d760d3827e76c568ae7aebbb612e775bddeccd334ac6bcd3253abc29d4b7c3f10362666f6ae75080370a36cba55db3a91cb5789e4d6f9efea4df1dd7730a5e27960d53b5121948cce5af653fff1d5b4e5b0a88c718c49b31c793d88c1cc45ab8da29d05e906cd0594b5f6638c8ec3f1760ba423b5ab1d08a58770afb0f139abd349c1bf160d8902239ce24f19b4e1be095f7ed165f3931e3cbcc307e9fc5c658031228e55cbbeec0d0bcf8f695154a9eed1bef35228789bfc0d238b8372d318328c1339fea08814db8621abca3aeb82098b5aa87bb98f5e40522a0888532c1748453db2d2b3943e4abb312de319aec48cc1c94775972953fb6496b8168937623510cd48c8b247956d3168486c176ae7a4cb384eacfdabfadd9fba30a23b811bd779f3cba54338c28bb3382238ed3b8dd21beab2f5cade28c5e09b31a454808a5348122e3ae3812296f7869c3865c3c9d8fe18bd812f2e60e914975cfe1bef8dbb8097006f0d7cf3fc15eb95c27854b14312b88d528015af69fb7505b8f32703f64eb1c958f046dd251242f8bea7467fc7291d095e9696e11aa45abe7924e856351535aa0773d3d9e61cc9a2d89b5b0774d7645ee1af7eb6fcd440bc69d43edeaaf935fd2a5295ac19a97d70af9298830f81c0a509f242f473372478fa5879fb2cb8511080fc2ecd8259b8c3ce9e8b640761dc7927c32e7f5bae97a8b8ac935662e5f45d14cad6d34affc9a19414c4566f45f977396710894c5399ed4480f18e90957faa76ccb512a2d07573058a95b42fe1810249d1c85ec431a049d1aecb0f118379bdc3f1ee490bc8a054c32c3dac7659966cdb66f995ac403d5e79eb6b25b3f3f65a6ceec220d66c05f8a8a98b80799ba4f2c6dbbb4dfb5862c9a46bca013ebdfaba7494a30ce14606afc0b0f993143fedee7896d9a6bb81499166ed02e94186aaf32187aeb6e282501bca43b57b7efa0939c934bc8fbbd26c44b618335a35c692ff996a5b95d327df9b2a6621b3b0f190db1f36d911d1a663a4ebf9a2854bb4f4061095b69812c82c2ffe3f92e9b44d2ea63169881cae8453d6eef7cf69c25a28b3f8ddc70148ef26721a3c1f2e62d9d10cea42fca3facd74673a4e7f33507364aa286c0f38d7: +823f0c29fbfdd3d1828f3055e9ec01ffd1b5a375118ddd7e4e0c43719f573ff773125fc83abb8b7c658559fc127393231d03ca5846e0c88118d13d55ca44789d:73125fc83abb8b7c658559fc127393231d03ca5846e0c88118d13d55ca44789d:802c39ce7f2a50bd81622add0df4e0fe03ec3d2d305a45a6165271ed79add243b9a00e52183192feb24c4fdbd22c807ae100efcf165b9c996194e00fa817765ea94a03070e486686b445fcb263ccfe1f5862f3b84b10f390080bfcae447ae0069742b8618fa9575f7e637ad54e834caf0394d745032ce1e255c0273250f1504b37a0add94aa245c7de52c80e05d6e0a96a14410543826a49e9b945626d4e89f55027163d4bd6d0e9bd1a2477f67d3d5668a42e94d8b61193d821e0d1b230fcadc53613b75b02cfb8158456077ebdf5a5f00c3b5b186370cafec4a21c69dce1f01efef23c37ab90f858238aefbe212b556d2f073406559f1a51d84efffdce07b00d01bbf33771cc12c960ac89365a9c82c52343f7603381b89023c1a6e702a5b1e4bd191ea6970b5ea451ea05b59bf83e55f29a1f803212bb2e58f0616333d9114708529e8b6c6081deeb7c299a5a2a53ccd24ed58ffbfe503d80614adb05ca11cf29ded00904ea1239f82ba40c793ebc339775f8b0fe3901f5482e310c793c6e2cf01dc157727af238f49c9862804b047551fd886f4a4899e22a6a65701117a3858055bbfe966e370e733e17efada2859fd8ffa9e01fce5606a255367678f4bd4e21e5da0fef30757f34e389f76b7d57c4e410a002e900e48fb218c8f2778f148fee56965f5b473e25256c23a7af198342cf3ef02b84df2cd5800a461c1b07bda2f42628a68ad29dbb82a470967d7302c993b234136e5bf255e6248b102c2bffb20172371f1ca3e10b0810e8649503546d9a731cf19b083357d4cfecc89bedb53506fe199b670391a620069a3081f253b4d790880aa23b53e97c75dc0c360540e5b0a3efb1accffd137414ff8423d54646fc56ba5f53bd84c7267c2f7ee3e37607544154365f9f85081dd7d2ee75d302275c799ef2427ca6496355dcda1d44e0d977bf68db3006500ae3f400d6a8c7cf47057d4fc87eeecb02116b73eed6ce1fccef6e8fb8aea363b2f6f5322a5f0753f45899537646d58651be9037bf91423c2986f5cc2bcbce4faec903498b40fc2deab6603d6eea585d2720d21bb2722bc05b35aed2bcc0e804fe9d239fafda7ddafe1d7860abb0fb28f4bf2b1fbb62a786e455be024b193b7830be0d558f02c9f3ae31dc107ee9421dc5f0b0f89402b71a4581401536bc47308506d96939a206362744e27dde944f4096a12b5f63dab64d041484d3fd91a62c2f0ef9ae787422eb27fed0802e25f9bc775c4915a837fe3eb7b9d5843e4d8210c6b494b61281637a6be32052:fa747b6fe3381ad6bc82a95643c1f4a20b76ba73bff00e635d64202d8b0df03dbc56b0138b3a6d4198ffaf58ccd3d388ed25ebcf770443e41e9d2147950a300b802c39ce7f2a50bd81622add0df4e0fe03ec3d2d305a45a6165271ed79add243b9a00e52183192feb24c4fdbd22c807ae100efcf165b9c996194e00fa817765ea94a03070e486686b445fcb263ccfe1f5862f3b84b10f390080bfcae447ae0069742b8618fa9575f7e637ad54e834caf0394d745032ce1e255c0273250f1504b37a0add94aa245c7de52c80e05d6e0a96a14410543826a49e9b945626d4e89f55027163d4bd6d0e9bd1a2477f67d3d5668a42e94d8b61193d821e0d1b230fcadc53613b75b02cfb8158456077ebdf5a5f00c3b5b186370cafec4a21c69dce1f01efef23c37ab90f858238aefbe212b556d2f073406559f1a51d84efffdce07b00d01bbf33771cc12c960ac89365a9c82c52343f7603381b89023c1a6e702a5b1e4bd191ea6970b5ea451ea05b59bf83e55f29a1f803212bb2e58f0616333d9114708529e8b6c6081deeb7c299a5a2a53ccd24ed58ffbfe503d80614adb05ca11cf29ded00904ea1239f82ba40c793ebc339775f8b0fe3901f5482e310c793c6e2cf01dc157727af238f49c9862804b047551fd886f4a4899e22a6a65701117a3858055bbfe966e370e733e17efada2859fd8ffa9e01fce5606a255367678f4bd4e21e5da0fef30757f34e389f76b7d57c4e410a002e900e48fb218c8f2778f148fee56965f5b473e25256c23a7af198342cf3ef02b84df2cd5800a461c1b07bda2f42628a68ad29dbb82a470967d7302c993b234136e5bf255e6248b102c2bffb20172371f1ca3e10b0810e8649503546d9a731cf19b083357d4cfecc89bedb53506fe199b670391a620069a3081f253b4d790880aa23b53e97c75dc0c360540e5b0a3efb1accffd137414ff8423d54646fc56ba5f53bd84c7267c2f7ee3e37607544154365f9f85081dd7d2ee75d302275c799ef2427ca6496355dcda1d44e0d977bf68db3006500ae3f400d6a8c7cf47057d4fc87eeecb02116b73eed6ce1fccef6e8fb8aea363b2f6f5322a5f0753f45899537646d58651be9037bf91423c2986f5cc2bcbce4faec903498b40fc2deab6603d6eea585d2720d21bb2722bc05b35aed2bcc0e804fe9d239fafda7ddafe1d7860abb0fb28f4bf2b1fbb62a786e455be024b193b7830be0d558f02c9f3ae31dc107ee9421dc5f0b0f89402b71a4581401536bc47308506d96939a206362744e27dde944f4096a12b5f63dab64d041484d3fd91a62c2f0ef9ae787422eb27fed0802e25f9bc775c4915a837fe3eb7b9d5843e4d8210c6b494b61281637a6be32052: +65676633374214c4ac4b7bcea9f1cc84b1b7e79411e310525ace385f4566c1d50e6ec5801d8bd6b1eb421421a1408f134cf712338e0ffc24cdccdc4f7fa31dbe:0e6ec5801d8bd6b1eb421421a1408f134cf712338e0ffc24cdccdc4f7fa31dbe:9d622c206787694093c6f29f93619f21bb64c039416d20dc708a084a9d2e490cf5658e13d62cb0d21eab00e42d851bc6ec75daf405d2373246eea415e866291babf76497680aaf04425a42552b107d58cd18561c8c9483f740744cbfa6054c1b126f5a76659ac19dddad4ab5a09155d8c050b5354e06a4dd3ee3a6f9c91e8b4c7af2749664e7abe97061589e153c58e27cf299a25f2b530c060731ec0f4366bd1debeb4d4e912e76e508534d433ec48f96b62e150de93963a1b3e6c8091b495a96518ce3d3b9a8dbdc2a13fdd077f2231de8d76f56d9ab1c2f9efabce4638364f8fb2a2c683ca819b703ab453b11d37a69fa4bcb8023980834f7b902ad1819fc029212fdea0abf11dec88c55d68ef87a26dbb15dc3d3dfbcdddd5ed71be86f32c76ee2221d9243683df9516564b26bab5c845d4dfe0adcc7cb9fe1ee2c051af5908ce0cc3a90904dbc0d3680ed4992f46ce25c2ee851c414f0187d893e5c3b0189a7bb6893d683f5e3394cc046299a16a1c1b5695933a89bb13030855b81b3c74685f719de0160575a0ff0a91fd94347b8bcbe125d1d3f9ce772a8126e00f563b3189656d5522c187ab831a7ade7ac06fdcac7f1d45882e51f9bf5b44a2daba4a53dbb31970b4a0f1272fe14087e0c3c7e4542312fe74d767f21e7ea487d5284284f46f20f32c5b16e1e0ac8d796ab2f80b344e7a8d84d5de823a50897752dc549a48fc10bcd436a7a93e97cd05d7830138f323879680c343c16467d264d749bf45e40f39fbc3a00c43b00693b0156768ff2e3f8ad9eb6405022f5cada6694e8a33cdc59c6673c44117244eb03fd7fd675930c294edd2940f5f180953d910c55485b2057ae0c9302f4a8e831a5530e3cbbf6f472224083a952a8390ab00dc0f69dfd880eea2d739d218d6a66f237f10d4401aa758ff8120c0ae2766127849024f5a4cc574a5b02b935966812cd1fb6d79d0c4f59ff80f035a0b109cccb22fb08535b874149edf2a0970c14888427d07d1eafa684a6d3454e49b225184c6b993ec8ddb8b5a35ee45f87f69266d49096a317d86ade27f4529fe72364d0b958007299d9de87d6ff9fb04d573aea46bac8eb764752eb465caaaba689a6460c110730bdd08b1689de7b05de59af9fe244ac363e95c98b669359af9031a3a93ba631abf1f61d20ef7fc6883b4840fc926712e13d874b722f6a79b16070c0311325e9a70fcd86916cfa1da7f9d0563a22fe9bfe854b0c186c8663b061b65bc071e839938d8fdd7cf8f6952a6467fad8e58490ed2b26813301:e0b867c9dbda35323433c046e0830c251b4346c5395972286b3a72310ed4526e545dc09d3918f2eb9920bc9b241e9050d848d3830288651591f936d3bae453019d622c206787694093c6f29f93619f21bb64c039416d20dc708a084a9d2e490cf5658e13d62cb0d21eab00e42d851bc6ec75daf405d2373246eea415e866291babf76497680aaf04425a42552b107d58cd18561c8c9483f740744cbfa6054c1b126f5a76659ac19dddad4ab5a09155d8c050b5354e06a4dd3ee3a6f9c91e8b4c7af2749664e7abe97061589e153c58e27cf299a25f2b530c060731ec0f4366bd1debeb4d4e912e76e508534d433ec48f96b62e150de93963a1b3e6c8091b495a96518ce3d3b9a8dbdc2a13fdd077f2231de8d76f56d9ab1c2f9efabce4638364f8fb2a2c683ca819b703ab453b11d37a69fa4bcb8023980834f7b902ad1819fc029212fdea0abf11dec88c55d68ef87a26dbb15dc3d3dfbcdddd5ed71be86f32c76ee2221d9243683df9516564b26bab5c845d4dfe0adcc7cb9fe1ee2c051af5908ce0cc3a90904dbc0d3680ed4992f46ce25c2ee851c414f0187d893e5c3b0189a7bb6893d683f5e3394cc046299a16a1c1b5695933a89bb13030855b81b3c74685f719de0160575a0ff0a91fd94347b8bcbe125d1d3f9ce772a8126e00f563b3189656d5522c187ab831a7ade7ac06fdcac7f1d45882e51f9bf5b44a2daba4a53dbb31970b4a0f1272fe14087e0c3c7e4542312fe74d767f21e7ea487d5284284f46f20f32c5b16e1e0ac8d796ab2f80b344e7a8d84d5de823a50897752dc549a48fc10bcd436a7a93e97cd05d7830138f323879680c343c16467d264d749bf45e40f39fbc3a00c43b00693b0156768ff2e3f8ad9eb6405022f5cada6694e8a33cdc59c6673c44117244eb03fd7fd675930c294edd2940f5f180953d910c55485b2057ae0c9302f4a8e831a5530e3cbbf6f472224083a952a8390ab00dc0f69dfd880eea2d739d218d6a66f237f10d4401aa758ff8120c0ae2766127849024f5a4cc574a5b02b935966812cd1fb6d79d0c4f59ff80f035a0b109cccb22fb08535b874149edf2a0970c14888427d07d1eafa684a6d3454e49b225184c6b993ec8ddb8b5a35ee45f87f69266d49096a317d86ade27f4529fe72364d0b958007299d9de87d6ff9fb04d573aea46bac8eb764752eb465caaaba689a6460c110730bdd08b1689de7b05de59af9fe244ac363e95c98b669359af9031a3a93ba631abf1f61d20ef7fc6883b4840fc926712e13d874b722f6a79b16070c0311325e9a70fcd86916cfa1da7f9d0563a22fe9bfe854b0c186c8663b061b65bc071e839938d8fdd7cf8f6952a6467fad8e58490ed2b26813301: +d2ededcd853206cbf59bd74a25a303fa2d6c3936bb48eb42f6d900cbe80772be2244111e2e769eab81871e06c580178c235c7bf4a52d2ecce11887a9b46c45c8:2244111e2e769eab81871e06c580178c235c7bf4a52d2ecce11887a9b46c45c8:8070bc0db089a5925446019b7e403c74ec78903e4bd54bc1d08a54a6f0ed75a85b763ff54dc33a2600ccb457fdbaeae548477f6d6947ae26deb71eacd1d2d62282a083843be4e5931d91c93b6282c58807ce8f0d880b1438dad8fdcba8612df73b9faff3a9f7db3005250536aabd98ae027a895e10b5cb7b69875c0f3993af245192f4393e9c4d3405746e311d3a91447fcdbd7306b6020c933bbab9e39d13491625035c9c636efa1739c3588710a879d9e3ce1764616f1082e8dff57559c3f5a5d76dd301124fa489fb949e9e039dd4621bda60f0b86b311e78ed0ab3b528965044b23d78ee2f81061f8edbd6929933d18c0207dec4b5b6b2fa4aca2747cf5b110df00b0c9827bdb3d9db2c7b0328d40d99e1f6b228e40dadae78aeda0289b6a23d4eb5837088e5d88413632ccc22e21a73768c673201e9a8d8dc6eb6f7397fedbd398d26f9692ca72f6d6cf056aaac50ac2f3b266dbe5e7be7a024774578ead585245daaa73e0aaf833c070ba4b2044ccb5e5cd16f9c0ad92ea8448055dd828c79935aa6c0741f9e2b810324fdc6e61e842f94572268bf7d5adfa7ab35b07fb19e7815a8aa5d81130130ac5cda8a4751ee76038c0a6bc2faba4c497e62b9f1f194b8a599b07701814b6dfb7d84bcdd5b7b5bc2249f1d3845eff9ef8cc7328535d70d53c7aa0c7305901de7c4ed2fe1838265d4a417b876adbd88eb933f27c9aa48c8c7e34e48147ccffb2fb61a348fea13ef67cdf2e039e33fd89e2c1ad2a4254e3bf748452aa83efeca46e780ede1d13ff4cc5e7d01ed45eb8c74818d4860af4759a83e148896ab68734395760e00146b793c3e72898aa0b3c5e0c1d3fdf12158d2e8ff1123a3a0c64cf6374a7f44f11a575e48a379181b30a4865cfd022aa983275635ce4f2cc40bfe066067ec4fe241fa047b55270a1ad0776c5f96861014cbf40a0432c559f22d79342b79f8e7042dccfb1cf50f83085f8063fb1887ed2dfc9db7efc96daa0ff2bc4f52335b02112d16392e134c0223de458fc072cc22bf9e7eabc06208180a57e7ce4805ee4e0fc015840998fd568644a0386b3d8e7dda52abf64f7dd00868fc84f036ca8a78e9ba8171ca90267c74e6159acac7af5bf23759abc53d82e793db87fdade1363354ffdcb0bd4cc9213f5c845445fc649b2a1f329f9d41d8a031ab46b472160f03434b4b6bc5a401524d6179ad66f9e221c9067fc87fe4a77e21e8023b6169ebf1090cd556a9be50b9187fe4607c5925e60b414f6a5cbf8afa15ed0eb34b67b4c9c5d54adbe640:be3c2b567fe8c208c98e7197117eb01b3c197bdfc858562dc5cd90f8e2c0357042303995baba2f40b7345c56db0b4625580aa8dcc48df6019d23a838ea7172028070bc0db089a5925446019b7e403c74ec78903e4bd54bc1d08a54a6f0ed75a85b763ff54dc33a2600ccb457fdbaeae548477f6d6947ae26deb71eacd1d2d62282a083843be4e5931d91c93b6282c58807ce8f0d880b1438dad8fdcba8612df73b9faff3a9f7db3005250536aabd98ae027a895e10b5cb7b69875c0f3993af245192f4393e9c4d3405746e311d3a91447fcdbd7306b6020c933bbab9e39d13491625035c9c636efa1739c3588710a879d9e3ce1764616f1082e8dff57559c3f5a5d76dd301124fa489fb949e9e039dd4621bda60f0b86b311e78ed0ab3b528965044b23d78ee2f81061f8edbd6929933d18c0207dec4b5b6b2fa4aca2747cf5b110df00b0c9827bdb3d9db2c7b0328d40d99e1f6b228e40dadae78aeda0289b6a23d4eb5837088e5d88413632ccc22e21a73768c673201e9a8d8dc6eb6f7397fedbd398d26f9692ca72f6d6cf056aaac50ac2f3b266dbe5e7be7a024774578ead585245daaa73e0aaf833c070ba4b2044ccb5e5cd16f9c0ad92ea8448055dd828c79935aa6c0741f9e2b810324fdc6e61e842f94572268bf7d5adfa7ab35b07fb19e7815a8aa5d81130130ac5cda8a4751ee76038c0a6bc2faba4c497e62b9f1f194b8a599b07701814b6dfb7d84bcdd5b7b5bc2249f1d3845eff9ef8cc7328535d70d53c7aa0c7305901de7c4ed2fe1838265d4a417b876adbd88eb933f27c9aa48c8c7e34e48147ccffb2fb61a348fea13ef67cdf2e039e33fd89e2c1ad2a4254e3bf748452aa83efeca46e780ede1d13ff4cc5e7d01ed45eb8c74818d4860af4759a83e148896ab68734395760e00146b793c3e72898aa0b3c5e0c1d3fdf12158d2e8ff1123a3a0c64cf6374a7f44f11a575e48a379181b30a4865cfd022aa983275635ce4f2cc40bfe066067ec4fe241fa047b55270a1ad0776c5f96861014cbf40a0432c559f22d79342b79f8e7042dccfb1cf50f83085f8063fb1887ed2dfc9db7efc96daa0ff2bc4f52335b02112d16392e134c0223de458fc072cc22bf9e7eabc06208180a57e7ce4805ee4e0fc015840998fd568644a0386b3d8e7dda52abf64f7dd00868fc84f036ca8a78e9ba8171ca90267c74e6159acac7af5bf23759abc53d82e793db87fdade1363354ffdcb0bd4cc9213f5c845445fc649b2a1f329f9d41d8a031ab46b472160f03434b4b6bc5a401524d6179ad66f9e221c9067fc87fe4a77e21e8023b6169ebf1090cd556a9be50b9187fe4607c5925e60b414f6a5cbf8afa15ed0eb34b67b4c9c5d54adbe640: +b569f7c1aadf56ed1b5fa1b6fad648d0dc544ff8fcd173780de41a7d4de60cb69effa4aed9c658e4346071434468a0b8a04ecf7841699d63e8887ce205570cea:9effa4aed9c658e4346071434468a0b8a04ecf7841699d63e8887ce205570cea:7c5aa4dc8078aa77e8b3b7fee61084cfad764762f1ef26d8deb7f2f3b186dfc772487550197845fba2f4c23c835b9b58dd0b635c649135137f248f5ef713564de3c966efa5f6db6bea9e30970749f8e872d8d7ae4535b75e176ea0489b915f3471d827eb5b444586488cfc3fa6a45082dacb826495e50a3b5dc6bb930a331f30c385bc3b24ce70b89596db6bfb687d99a581987ca876ea0e757696b3fc03779a658130c410b344edacc4277d44845499d678e1414f15f36e166335189569cef3567ac2e3ab821c91c93274f5c28a5d1f7c1bf5099b10f84ecb13a4e4538f6649bf74f7394b703ef53649d81516cb1db521416065cf9f276ab80c9308897a27dfe37e5e142f1819b8d348df50a046a12888e3b7f2dcc70f5218d15ebb9aa7291a1a92ac445c51d3a53dd691efffcf5a01e876a72aa481eb4f121a072397d8cc93bbc2c9a6c28cc89b11ffc0e910d82d9d6298a367a0e1e3e8c865e4326a319b22666e529f1998f1b3c8efb5fc21cce97040fb6247daa0000ac5554d89e7b27159dd0b1800b760b79c91ef6e970b1e6c5ff42442b1b3ae4d3c439e08ec2f6b94177387ca5c01df6f07f8e34d25edbd49d8b74e31a5e65dec1f8760fa22c00e6fb1cd555be68b0ab43599f0b9f4a54a7ccb062683895d5ef66d24dfb1678cb0d0e8c801d8e5ffe79b9139fc96d118eb39b9c8d4404489325d45b4a3202beadca66f831c68efb815941581930ead29fd5f211b90e7a39f0d4ff48c62a545e28ac2ce29bedc356d92fc00347176d77623e0e1809eff3fe62b75a7d9deb727d86172d14edbf2789a57143c69925c917d433b4683b0693b3cd9e7e377996410727f5e6fb8f5ccd1860a20294ecf33faf97a1e0f85b761447d4761b96e4df1b312bd414cabcf498497b0ead67cd1e5901bbf3a16a8891ccced8a907df88726952d4ab370a6b7df2942cf13615a5bc12b4e106dc3013c68b8fb906399df15f1aa90d56aa974b1d2b28c1a8453b9bf0792a51c97ce8a12afc9341bb4c0c37b12dcb12c639449775d9ac5c2ec49673da5aaf7493ed5f1f2116eaef72bb7fb1e093ede2c26317f4f4b6ad585346205df91a6e96bc66d3064bce952398ffce88071ed9ff2750c65c0c304125ac2cadc4fef71a818732496a84ca574d482d5a3bba20e16dd2fa24d3270f6c60992f7f63e88f52eff6222998eb4416727384375f59f00e47512ee464c3184aceaff3ccfb06bd15c183c5e485926288b997bfaaaecf6ecbbf7d2abf4906df76b1277c5f5a87e6817b1c636e91efd7eccf64f:2e32ba0556bde974d7a19b3b9a1e92f183924c4b74c5d751b5ab3d007967016ec03afe91d742fb22b63e5e55b2fcb6c61a46e9dce7fe9fa30bbf66aef4b85f097c5aa4dc8078aa77e8b3b7fee61084cfad764762f1ef26d8deb7f2f3b186dfc772487550197845fba2f4c23c835b9b58dd0b635c649135137f248f5ef713564de3c966efa5f6db6bea9e30970749f8e872d8d7ae4535b75e176ea0489b915f3471d827eb5b444586488cfc3fa6a45082dacb826495e50a3b5dc6bb930a331f30c385bc3b24ce70b89596db6bfb687d99a581987ca876ea0e757696b3fc03779a658130c410b344edacc4277d44845499d678e1414f15f36e166335189569cef3567ac2e3ab821c91c93274f5c28a5d1f7c1bf5099b10f84ecb13a4e4538f6649bf74f7394b703ef53649d81516cb1db521416065cf9f276ab80c9308897a27dfe37e5e142f1819b8d348df50a046a12888e3b7f2dcc70f5218d15ebb9aa7291a1a92ac445c51d3a53dd691efffcf5a01e876a72aa481eb4f121a072397d8cc93bbc2c9a6c28cc89b11ffc0e910d82d9d6298a367a0e1e3e8c865e4326a319b22666e529f1998f1b3c8efb5fc21cce97040fb6247daa0000ac5554d89e7b27159dd0b1800b760b79c91ef6e970b1e6c5ff42442b1b3ae4d3c439e08ec2f6b94177387ca5c01df6f07f8e34d25edbd49d8b74e31a5e65dec1f8760fa22c00e6fb1cd555be68b0ab43599f0b9f4a54a7ccb062683895d5ef66d24dfb1678cb0d0e8c801d8e5ffe79b9139fc96d118eb39b9c8d4404489325d45b4a3202beadca66f831c68efb815941581930ead29fd5f211b90e7a39f0d4ff48c62a545e28ac2ce29bedc356d92fc00347176d77623e0e1809eff3fe62b75a7d9deb727d86172d14edbf2789a57143c69925c917d433b4683b0693b3cd9e7e377996410727f5e6fb8f5ccd1860a20294ecf33faf97a1e0f85b761447d4761b96e4df1b312bd414cabcf498497b0ead67cd1e5901bbf3a16a8891ccced8a907df88726952d4ab370a6b7df2942cf13615a5bc12b4e106dc3013c68b8fb906399df15f1aa90d56aa974b1d2b28c1a8453b9bf0792a51c97ce8a12afc9341bb4c0c37b12dcb12c639449775d9ac5c2ec49673da5aaf7493ed5f1f2116eaef72bb7fb1e093ede2c26317f4f4b6ad585346205df91a6e96bc66d3064bce952398ffce88071ed9ff2750c65c0c304125ac2cadc4fef71a818732496a84ca574d482d5a3bba20e16dd2fa24d3270f6c60992f7f63e88f52eff6222998eb4416727384375f59f00e47512ee464c3184aceaff3ccfb06bd15c183c5e485926288b997bfaaaecf6ecbbf7d2abf4906df76b1277c5f5a87e6817b1c636e91efd7eccf64f: +323465d0313d1001a261abfd44fe65c38c9a00ca0f20335d6553de492699fc46e22f16bd4cc7e94c46ba31961af8c583f9d2718c68f73d85069f608e15ba8766:e22f16bd4cc7e94c46ba31961af8c583f9d2718c68f73d85069f608e15ba8766:bb1082e1cfdcd29bfca2464d5ce446b5ba654ba58c22538da926b8303cabfd284a7bd5994a786fa66aedf0e15f20c382cdacf3d14557ff7a8267fa04672cacab767008650aa9b4a7c9071c4799f1ffa45ca4d586e02047444c14231943467a3abaefa53959da226eb0c15392019760159697748293c025568783588a3910e78e5ea427c4407a8901061b8b992b82a2df58c04a1b2c5fad11c6b379856c2e0fef8a950de7e0fc22310309e08b132b0cce4fc1ecbf94574a388d4ae36675d3299a951554ebf180eb381e1b5df977d938433891bc478d7681850b9dc9c5c769d405f5d8839fc97361d6cb306c203026cf2e2b3d39849e1f4b1225eb25ef8acd40b006f20c644db650c75d38c0fcdd48f598c7b4a60106e69e19cd712589cedccf50864ea5f9e95e01f1dd85c7514f2c94b28359de4132b88c3ee1d10a80a9fadfb690e3d88641b3168f0b896af8990adbf0e4f8e9d3f9d4cd314e12c3bce0cc8738e0cfc1905be5efa071f710b32f8e5898c60eb1bb8feeb74000560f41cb2ebc32b2600b6980a2a4064dfaa3797ec44cfb72d379f8097379cad67ecdc0c32414fa41c72b1b9e4edf5518cb39fe9092b439af3a4ebd5afe79bedc0ea8bf17479a2821f5e9bd91d7f4aa5e384699523719b6957f82367cd85fea9ded6236a207c94cb373e3393cb4fe11f90a1b8779e4ab4c3466136bf21e2aab78f7d2726db6414fa5c4a3f7313ad2116a6d7ce40aaa1001c2704d5b05ae54c7cc6f567217f1a47bfd0ee738eaea5eadb5371075be076c8750aecefc417ea7bfdaac3cc38bf16cc26df7600e3c7e8e431f2676fc2a8c43a6a14368ba62bb32439a06beac38a047b3745e26f407ad823d6ad1c0b6a44341e15fc9b331214ffc89698211b05133d6d3433b5d59f7ab4d109e54e4c5d6f32fcf7230fa4e2528c861bb21ccc9e310e9497e077ea675510da712b1a5df575c5d1bf7362d071180039aecfaa5c8573c24c0f4ebe81c2f889aed3de5a000be12fe3d0af2dc2cd4240e314a176c553efd5cba798d9ff1e3d4bd9e90bb8113e3849d735afa4af6945cc57d4c378db84f206ef7eab11c637a7f7260f122a97dff6747e9b4c174ed0d64f9efd7fcccf981519ec580a8182547d17968c40151fdf6d54bc57a9115f040fab5c100deb039122b7d2bfd98b6adf38f42b296ea3b378a904259b75d60703b4840b3f5da09620a54776280e9ca9e8cd924aed2b5dd2b49834e581caed5271cd78ce08e4bba49b59cd77c1b6276649148ab7247f97fc0131635de474d3c23493ca98d:da3aadb34360b2da0c26542ea71defa8a0bf7fbdae3ee9e11c84084ad05cce7ba7d94de25d8563982616bcdb5bb6395fac4a7e84bc77e21ed36df75dec990b06bb1082e1cfdcd29bfca2464d5ce446b5ba654ba58c22538da926b8303cabfd284a7bd5994a786fa66aedf0e15f20c382cdacf3d14557ff7a8267fa04672cacab767008650aa9b4a7c9071c4799f1ffa45ca4d586e02047444c14231943467a3abaefa53959da226eb0c15392019760159697748293c025568783588a3910e78e5ea427c4407a8901061b8b992b82a2df58c04a1b2c5fad11c6b379856c2e0fef8a950de7e0fc22310309e08b132b0cce4fc1ecbf94574a388d4ae36675d3299a951554ebf180eb381e1b5df977d938433891bc478d7681850b9dc9c5c769d405f5d8839fc97361d6cb306c203026cf2e2b3d39849e1f4b1225eb25ef8acd40b006f20c644db650c75d38c0fcdd48f598c7b4a60106e69e19cd712589cedccf50864ea5f9e95e01f1dd85c7514f2c94b28359de4132b88c3ee1d10a80a9fadfb690e3d88641b3168f0b896af8990adbf0e4f8e9d3f9d4cd314e12c3bce0cc8738e0cfc1905be5efa071f710b32f8e5898c60eb1bb8feeb74000560f41cb2ebc32b2600b6980a2a4064dfaa3797ec44cfb72d379f8097379cad67ecdc0c32414fa41c72b1b9e4edf5518cb39fe9092b439af3a4ebd5afe79bedc0ea8bf17479a2821f5e9bd91d7f4aa5e384699523719b6957f82367cd85fea9ded6236a207c94cb373e3393cb4fe11f90a1b8779e4ab4c3466136bf21e2aab78f7d2726db6414fa5c4a3f7313ad2116a6d7ce40aaa1001c2704d5b05ae54c7cc6f567217f1a47bfd0ee738eaea5eadb5371075be076c8750aecefc417ea7bfdaac3cc38bf16cc26df7600e3c7e8e431f2676fc2a8c43a6a14368ba62bb32439a06beac38a047b3745e26f407ad823d6ad1c0b6a44341e15fc9b331214ffc89698211b05133d6d3433b5d59f7ab4d109e54e4c5d6f32fcf7230fa4e2528c861bb21ccc9e310e9497e077ea675510da712b1a5df575c5d1bf7362d071180039aecfaa5c8573c24c0f4ebe81c2f889aed3de5a000be12fe3d0af2dc2cd4240e314a176c553efd5cba798d9ff1e3d4bd9e90bb8113e3849d735afa4af6945cc57d4c378db84f206ef7eab11c637a7f7260f122a97dff6747e9b4c174ed0d64f9efd7fcccf981519ec580a8182547d17968c40151fdf6d54bc57a9115f040fab5c100deb039122b7d2bfd98b6adf38f42b296ea3b378a904259b75d60703b4840b3f5da09620a54776280e9ca9e8cd924aed2b5dd2b49834e581caed5271cd78ce08e4bba49b59cd77c1b6276649148ab7247f97fc0131635de474d3c23493ca98d: +60ffdbae003fa2794fcabbf8f5b41644fe3a7f44ed6c834193da07a9dc5e266535b5eb31ab556492578b3dbd6cf1687d1fdb216a725818079663482f221ce421:35b5eb31ab556492578b3dbd6cf1687d1fdb216a725818079663482f221ce421:3f8ff20bb4f00834c80f2ee6893d6f73bf7ace2729601bb26a0fb272a4d0eea1fae1d306ac2c5f32add60135851da27e4f12e64ea5e9e9960b1383b04ce05a98b0414dad971ea98944871d415cc2c46da403976d9f21938958d4ea8c7903b14f2a4485fd69afb24abe102d8fec266fb468b411eb20a339677d88eb31c997b4dc885613f0be7c70daf856a3df92da9602fba2e6749d2f426beef68662d5b0c2fd31321b22b5ec597da5d7e6a288ebd9443c5f39eb87dcf4a5ad9d56c6baf6080996a77936bd87dc3cb42ed4c4d42688a9e193829b761ff320e2a66cc67648e70eea3a1f2f9b9d5b4202fb5a39e9adc609086a9be2a8323ac66931bdf6c504d3336211e46fdefc481fbf17f613dab1fc5c097c92db0609906d78b25a455a3045718efd3e3b14e252b1ae59c7c3893e31913b2c264c0ffc3b606ca1b01dc47ee828a08e46af604e590def44d27aab93a403251fca0772e9df0fab7af0cbc5181efda4da913d8eb6452f6cecbda204bc72d7c990f60ce0dd83c634e912236091b0a6673a7c89ea59308d55bd7e63a8526774cbdd7a1339fac2124c9022abd6fece7f2daedfd87fa683dc0e3ef40806a0ab198769d3a99fe81a99b68600319087afa4ea79d7ee45da9cd40809f4ee8f4e25a0177521ee9dba8b56212e88719bb7367336f4a7bc7122b41a7dfaa2672f92f23403a10c4fb25388c6b20081093d49f3be8a9e1c634ef7ba96b6d523dd6ff613c0a23b60457026cd485ba8db61d80a0dc659d9af42a38cae777fec68e39c52986ff9fc20789c10585107c04047b66ba14e93fb904ea90df7ac9f0154c96f3236acf6dc8b44f554c0cd513193e5dfd87e085ad4b38aa4c5e36b2427722088816ecd2bc3a3dda01e4fb3ff5eec7a6417322ba6a27773d24495a839194a4a582fe5abdb8b5d533a24262589241fc81fdf5e79fd26776428f8e1ce9e926cf272716e7583abfc67a94aae0816c1000a196170bbff1f45e5ed9e267ace1e4d915dce7216c5f404def6fe2bd8b28b2eccf3e2aea0c0d6626390274e47e745ed3a23bcfd21d284c395379dc02080f07936bc154e7b99ee73db188bd2a394e03a01ffe2d1b330ceb72158f958c716a81711dbf65aff8cd12f5dfa53b376ebb8b98f8628f17ef8b2ab9c0bb68412f4e347a633e2f8da1a556d96f4af7211c078079c10541c07dc3722d18dab8fa8bc4925aba5c966f805040322dfbbbe87fbfeb1961f5ccd40a91b997e54315a7eefc3a47bb0c87dc23755ce7227574996f4be7aa344fe0d17b97bc50c5838f99292:b8f3e1f3785a2a39bb086ca465c0abf0a3e87443225ac6e966ed9b4531c54a894a9abd01ac31b85757fe75308c9594ff65f97cdd91e8d8a93cf12b9e6dbee90b3f8ff20bb4f00834c80f2ee6893d6f73bf7ace2729601bb26a0fb272a4d0eea1fae1d306ac2c5f32add60135851da27e4f12e64ea5e9e9960b1383b04ce05a98b0414dad971ea98944871d415cc2c46da403976d9f21938958d4ea8c7903b14f2a4485fd69afb24abe102d8fec266fb468b411eb20a339677d88eb31c997b4dc885613f0be7c70daf856a3df92da9602fba2e6749d2f426beef68662d5b0c2fd31321b22b5ec597da5d7e6a288ebd9443c5f39eb87dcf4a5ad9d56c6baf6080996a77936bd87dc3cb42ed4c4d42688a9e193829b761ff320e2a66cc67648e70eea3a1f2f9b9d5b4202fb5a39e9adc609086a9be2a8323ac66931bdf6c504d3336211e46fdefc481fbf17f613dab1fc5c097c92db0609906d78b25a455a3045718efd3e3b14e252b1ae59c7c3893e31913b2c264c0ffc3b606ca1b01dc47ee828a08e46af604e590def44d27aab93a403251fca0772e9df0fab7af0cbc5181efda4da913d8eb6452f6cecbda204bc72d7c990f60ce0dd83c634e912236091b0a6673a7c89ea59308d55bd7e63a8526774cbdd7a1339fac2124c9022abd6fece7f2daedfd87fa683dc0e3ef40806a0ab198769d3a99fe81a99b68600319087afa4ea79d7ee45da9cd40809f4ee8f4e25a0177521ee9dba8b56212e88719bb7367336f4a7bc7122b41a7dfaa2672f92f23403a10c4fb25388c6b20081093d49f3be8a9e1c634ef7ba96b6d523dd6ff613c0a23b60457026cd485ba8db61d80a0dc659d9af42a38cae777fec68e39c52986ff9fc20789c10585107c04047b66ba14e93fb904ea90df7ac9f0154c96f3236acf6dc8b44f554c0cd513193e5dfd87e085ad4b38aa4c5e36b2427722088816ecd2bc3a3dda01e4fb3ff5eec7a6417322ba6a27773d24495a839194a4a582fe5abdb8b5d533a24262589241fc81fdf5e79fd26776428f8e1ce9e926cf272716e7583abfc67a94aae0816c1000a196170bbff1f45e5ed9e267ace1e4d915dce7216c5f404def6fe2bd8b28b2eccf3e2aea0c0d6626390274e47e745ed3a23bcfd21d284c395379dc02080f07936bc154e7b99ee73db188bd2a394e03a01ffe2d1b330ceb72158f958c716a81711dbf65aff8cd12f5dfa53b376ebb8b98f8628f17ef8b2ab9c0bb68412f4e347a633e2f8da1a556d96f4af7211c078079c10541c07dc3722d18dab8fa8bc4925aba5c966f805040322dfbbbe87fbfeb1961f5ccd40a91b997e54315a7eefc3a47bb0c87dc23755ce7227574996f4be7aa344fe0d17b97bc50c5838f99292: +174e993d9b81f2af67e9ffb8ebd5da417966a9e77f66c65c767738fe8357d07c3bb7386f1b1cbfae553703833ebcbfe2dfff8c899a0792d7ce2322b5ba645a5f:3bb7386f1b1cbfae553703833ebcbfe2dfff8c899a0792d7ce2322b5ba645a5f:a401750afc4837dfe3aacc284a597145dfef02629ef87bd0938d443979df76f29fcd66a5b71ea8ab787277e3056f6ea11b08bd238979f9d3b062538c4d6040a86b6e32047aecc59c2377ad0ea4c40c79ff9fe98c958b2bf25f2fd6342432636f5f7d5bb0d2ecf18183426c73147984d95bbe162e11972ddb78a2a7c345c5c0bbbaba9cf38a2d5dd509a7df8b842874a96e64b5d64f5c41a21d208d14cea7066cf22dee0ca41aa46ab921d4ceec89ec873f77960eda60d9676cfd0dbfaec872c2ade8fba4285aacd527143ae0341d67d0078119653b5d23d46e6ef70264b1b0913870877623716d0f1a59021be74c914b432471a43a29f2b6dbeb6a223e2dbaabb820b4adbe337829e1de0c184dd0d09f9d01d42527e5d40abbdacc8ac0f1b2c5c1cb2f23876d2d1b6b43dfe482f9d45a18f5c22b15f1fe521ef57b08aec6a3033925c7454c93e6319e778ac494fb140ae5f1a31cc832ca2488651004063bcff8fd9ae9266af527f2c31f6acb8f3debd9978ef9df0108e3d50c491990c90dd8ee9d64ea4ebfd711c99d9044ec11342c5383ca39232ed97a07e4dc51db4c1fe947348dffe70a95c99db14751314801f13fa2bf42d867375a08ee9b3b799e0b15278e95e91a8968064d6dfd8f5115438ccb8b516ca0c41dbb19873c6e10a236ecc2dad522f80f01c14e2fa14a0d792b9fc486c6fb0efbdf2130f02df1497db5aba8be61ca70b29388e4eec7e0694a38c0d03c59bb6a2dc3ccd6dde1e29ee2c1b325ac72aa8e6fab9138f8b6f5d324d46af3a3542c8bd87cb04fafc54b5db827de606762a097b622799ca827bda9c1c0bb267eba8254a81c6b858a375b94bd09f39eeb88cb14b8d46e4740dc1ab42a895f86d2c57fc28b07b7f60fc4f8847b8bc8ad83a2481a28f29bca3510ff8bf1dd7581e3357164f4fe920f9de839376de064900dc7f8bcf511dc572e0f0f6a75b929797da41c52eae6fe13750ce351e8767630badf6d7d4eab90cd1904c96c048a9acb213a9e5b864615738a84f222986ac23554cf4ce54e80ab5733c065b80459921dd3d8372d0e8594d4364351bf041c146fa8d23a193eb807ece23f24ab6595e932c9ce1a759bf788914db008e87098dd81465e2610647ac38e088666f60ec5d0e2173320a40cd985f0e00dbc2b4570727483a8c25f6fc1e093bb57ccafd1ca202f2986c7c5540a7c3e10c4a6fc26d1d62c2ca5af8305ceebe42ff96e7dc548214375e8a7f9f712ba8bd875e43ca10cf9b183f0c8519512928538a478cb98259bd8b3e334bcc4635595cad3:e607bc9a5360b31da56be1c544c2000284951d8689f4b722bc4673a0c8489b84483ed8e76e297ea046e85b37ba5630585e5375566a187afb5696661e5bfdc10ea401750afc4837dfe3aacc284a597145dfef02629ef87bd0938d443979df76f29fcd66a5b71ea8ab787277e3056f6ea11b08bd238979f9d3b062538c4d6040a86b6e32047aecc59c2377ad0ea4c40c79ff9fe98c958b2bf25f2fd6342432636f5f7d5bb0d2ecf18183426c73147984d95bbe162e11972ddb78a2a7c345c5c0bbbaba9cf38a2d5dd509a7df8b842874a96e64b5d64f5c41a21d208d14cea7066cf22dee0ca41aa46ab921d4ceec89ec873f77960eda60d9676cfd0dbfaec872c2ade8fba4285aacd527143ae0341d67d0078119653b5d23d46e6ef70264b1b0913870877623716d0f1a59021be74c914b432471a43a29f2b6dbeb6a223e2dbaabb820b4adbe337829e1de0c184dd0d09f9d01d42527e5d40abbdacc8ac0f1b2c5c1cb2f23876d2d1b6b43dfe482f9d45a18f5c22b15f1fe521ef57b08aec6a3033925c7454c93e6319e778ac494fb140ae5f1a31cc832ca2488651004063bcff8fd9ae9266af527f2c31f6acb8f3debd9978ef9df0108e3d50c491990c90dd8ee9d64ea4ebfd711c99d9044ec11342c5383ca39232ed97a07e4dc51db4c1fe947348dffe70a95c99db14751314801f13fa2bf42d867375a08ee9b3b799e0b15278e95e91a8968064d6dfd8f5115438ccb8b516ca0c41dbb19873c6e10a236ecc2dad522f80f01c14e2fa14a0d792b9fc486c6fb0efbdf2130f02df1497db5aba8be61ca70b29388e4eec7e0694a38c0d03c59bb6a2dc3ccd6dde1e29ee2c1b325ac72aa8e6fab9138f8b6f5d324d46af3a3542c8bd87cb04fafc54b5db827de606762a097b622799ca827bda9c1c0bb267eba8254a81c6b858a375b94bd09f39eeb88cb14b8d46e4740dc1ab42a895f86d2c57fc28b07b7f60fc4f8847b8bc8ad83a2481a28f29bca3510ff8bf1dd7581e3357164f4fe920f9de839376de064900dc7f8bcf511dc572e0f0f6a75b929797da41c52eae6fe13750ce351e8767630badf6d7d4eab90cd1904c96c048a9acb213a9e5b864615738a84f222986ac23554cf4ce54e80ab5733c065b80459921dd3d8372d0e8594d4364351bf041c146fa8d23a193eb807ece23f24ab6595e932c9ce1a759bf788914db008e87098dd81465e2610647ac38e088666f60ec5d0e2173320a40cd985f0e00dbc2b4570727483a8c25f6fc1e093bb57ccafd1ca202f2986c7c5540a7c3e10c4a6fc26d1d62c2ca5af8305ceebe42ff96e7dc548214375e8a7f9f712ba8bd875e43ca10cf9b183f0c8519512928538a478cb98259bd8b3e334bcc4635595cad3: +e53715fec9d3b20e9c2991e54b5eb0a8cc81875569c95e22a2001360021760045351899b69b2116bc7f8a8814d1e5b9fc785698bebd9ab14277c3ecc01ef8b1d:5351899b69b2116bc7f8a8814d1e5b9fc785698bebd9ab14277c3ecc01ef8b1d:8431cd16d5c093775e18c08252c43f95b1017eb711fcaf73e1e00c0cd6f3448744ab9b0e64335518c483ae94deb97677f818f0e81a7490615b7141b9c35f80556e6971cea28e9a32c328cc2669fca5b123cb662debab2b98157764668070e18edf761ae196bd4b244fea7b74984516be2c00739e76e6c4b621cb3983765a20d84778d5a4350b168f6a0f712a9820a85a636faf92c789c428cfd2962ed207c3ac8899c258cac1adb5159f764ba37229c5cbf783fc9aa4d1ea46ecc85fe0961485d4fc5cb21df0012ac9b955373b1422e51afa1c550988862c86133b760aa630fc0acee8989117d1dd96e3e6287b69287c590bdca9cbc8eecef281ee6d1c8d88822bfea5fa0f530f23278093c7c85a0d44c3a77404ee79f1c8368cd7321bf148fda4dcf2eb07e4630ea422587586371780514536b894c524e6b83d5a76a15c83e95ab314e07b34b98cd99e0770b4eb9b3f3f505bae8a06f7f950258d790748107195eb4f6b84840f8c0590727396ed14e3f53239476c4d2a7269b2e1f972fbff33e4724426745ec886a32916295e70d468d06c7dbb5ff9a354e1ac903bb45ca526f08b49a65e82297d8dd3fb25aa428f64345bca9740d9078dac9e1138c921bdd74881673d49d0cd2006811723de287c6c9583e456a01ab1a34dfa1eaa963b71e8bc7fa8a98cad4f941e4b37b60eef923b3294882350b38ea4eac0e9232e93c532db5d7eec8ecfae65e080473078777ddfdd11508a6e59f0ebaa3f60441f82a71a73c84bca06a371ff5c9f77213a2db795d4a8897823d88fd92ae3e057e8bbd80c990af8386bdf26f12d973c8c5ff9ed6f7b2d8e6183cf6e68f3bb898f59a93ec4de3bea605a5d8b15dfab713f3585c48dc9a5768242b33101438030e7044880d17c2ee84f89d26a1f7b1986193f9663c587d50ca9ddf6186a5176afef1adb2481b79254b78d3b34c69790eb28b90b1461170c3d73818376cdf371af0a0feaf14fdf7016ed6e7f08c0c14b52705c86d4f0003b5e45f974c06416ccb5ca3e9d529aa9d415c25a446fa2d69e82f4994e57e922c17c1c342dd7281e410052d9e4aa1b309b7d470d458c663e17ff2500d0bb8e46a9c4367e091caf87ddfc062aae08a65cb9e0eaa71c99459c5e7cb112a2ee98a5e4cbee0dc520f87c3022da6549be1ee70a0a73ad8499c97dd06aa14c9fd8628a92ca6db487322db9598ada1fce28f4b9fc1d3cc39dcf2ed1df3d862d87f55cc1016fb9e73e7cc897b970d5ff35acfeb05c1c89192808aeebfb2cd17cb1c94fab059898fedc2fbd44ccef:3d0adce77a4e046fcb9b49ad5e6c6809c8ac336c733404e5d3f015c9225c3df46ef21ea34cffb3af69974f8b7eab2d23fcd5a1e1753a4023deb3818629a98a0b8431cd16d5c093775e18c08252c43f95b1017eb711fcaf73e1e00c0cd6f3448744ab9b0e64335518c483ae94deb97677f818f0e81a7490615b7141b9c35f80556e6971cea28e9a32c328cc2669fca5b123cb662debab2b98157764668070e18edf761ae196bd4b244fea7b74984516be2c00739e76e6c4b621cb3983765a20d84778d5a4350b168f6a0f712a9820a85a636faf92c789c428cfd2962ed207c3ac8899c258cac1adb5159f764ba37229c5cbf783fc9aa4d1ea46ecc85fe0961485d4fc5cb21df0012ac9b955373b1422e51afa1c550988862c86133b760aa630fc0acee8989117d1dd96e3e6287b69287c590bdca9cbc8eecef281ee6d1c8d88822bfea5fa0f530f23278093c7c85a0d44c3a77404ee79f1c8368cd7321bf148fda4dcf2eb07e4630ea422587586371780514536b894c524e6b83d5a76a15c83e95ab314e07b34b98cd99e0770b4eb9b3f3f505bae8a06f7f950258d790748107195eb4f6b84840f8c0590727396ed14e3f53239476c4d2a7269b2e1f972fbff33e4724426745ec886a32916295e70d468d06c7dbb5ff9a354e1ac903bb45ca526f08b49a65e82297d8dd3fb25aa428f64345bca9740d9078dac9e1138c921bdd74881673d49d0cd2006811723de287c6c9583e456a01ab1a34dfa1eaa963b71e8bc7fa8a98cad4f941e4b37b60eef923b3294882350b38ea4eac0e9232e93c532db5d7eec8ecfae65e080473078777ddfdd11508a6e59f0ebaa3f60441f82a71a73c84bca06a371ff5c9f77213a2db795d4a8897823d88fd92ae3e057e8bbd80c990af8386bdf26f12d973c8c5ff9ed6f7b2d8e6183cf6e68f3bb898f59a93ec4de3bea605a5d8b15dfab713f3585c48dc9a5768242b33101438030e7044880d17c2ee84f89d26a1f7b1986193f9663c587d50ca9ddf6186a5176afef1adb2481b79254b78d3b34c69790eb28b90b1461170c3d73818376cdf371af0a0feaf14fdf7016ed6e7f08c0c14b52705c86d4f0003b5e45f974c06416ccb5ca3e9d529aa9d415c25a446fa2d69e82f4994e57e922c17c1c342dd7281e410052d9e4aa1b309b7d470d458c663e17ff2500d0bb8e46a9c4367e091caf87ddfc062aae08a65cb9e0eaa71c99459c5e7cb112a2ee98a5e4cbee0dc520f87c3022da6549be1ee70a0a73ad8499c97dd06aa14c9fd8628a92ca6db487322db9598ada1fce28f4b9fc1d3cc39dcf2ed1df3d862d87f55cc1016fb9e73e7cc897b970d5ff35acfeb05c1c89192808aeebfb2cd17cb1c94fab059898fedc2fbd44ccef: +abfd697bfbc5b6ff2bdff3bce1d777e05fbe3ec8b95ce693d623931209313d4fa709321a0210cb80ab58bf955ecdeb8aaf9ee4c375f959c53089d437488c082d:a709321a0210cb80ab58bf955ecdeb8aaf9ee4c375f959c53089d437488c082d:896b7ab8413ffe439a2f4487ec49d64e31c74f50ac83f55da61a7003aa716c2a9df6b438e62f53d8f0192f3736324760d7e8c44ac0baca3ae2a6fb93f13d96886799fd2c4551b0ab36f1730855551265a5a3c3c21d9516a237f5dbc1c8e72999b782c5ca41a4f6e9308e64afdee0bf479e546b89c51bc5e4f71e57fb24ce437a8b81b91dc798b5ab36f29afd5b48e81c176ae5edf95371ba3246fb439405bd10eed3678e3ec62307a3b3dc1badba051f16774b85088188c2a9e320a1618d5f26ce94ee2b933c305f6d9584958eea3156c3d1e0ef39a186275ee62c40f3c1acd15d8be6e074351f5349ce3df69517505f45fa06a815c69ca18f450f42b5cf4ebd99268445e0f68104a7deeb0a115b817b99e1a73e0fa9d87db71f8ec94f8708c9bc2e622b963365ebcfb97cfe7332630070e9654eaa60361a45d402dc0ab297665242667fbd9940f6cd33195246a8c2869af759a862d4b641db144d5732366b20636c4027787f558027d76fcbf8432eb93e6d14567df8dbf211daeb5655db10acddd05eca06accee9fda8d3b70ca1e6dc587fa4b78f63cd663ff0243870570f4dcbaa3fb626b4e113bde47d5c9db2b4ba6ec6dbf918ac056949ef3cfcb115561615771a035a43d33ba2651dbeb46348261ce3c4c9f246d23f94dbc2d0c19b921e24c77da5992f1b4bdf2edea499f5411168ac0c12e96f3b15d2e12ac8d7b3ed8d1e07c4267a25d3a3c353a4208b7406278aab9e700f7b206f48e6ea7cc97e554f15c9be349dd91514dbe8d889f2dcbbfa182c9faf5807a69b2e97fa771a6f231a4c7b31d117b8ed0e630cdf13e082bb4f63c3f9acb3553204ccd76e1835c46eec3d43c561bbf17c92214a6db1212b6003cf2cc26c7ae675fcd053b947e722f9e85762ce8a16e4654ec6342fc646e5cab472797eabf658ba4afd142fc8fc4c8f98f23c24dc99847ae8cef0879e1ab3bb8097e4c3529add2d8e8e2c2069210f50ace1ae32a6c8e6384a2bf7d79c66c746149c84ad75a3a176e45e136d94695aed4bfd08b426ea8c4b9379f3742550e1cf5ac84c18174d680e92af2c1874ac1c13d28232de193768e561947cbd6b79e9b99da65cfb74ffb32f7d3d2025c60763dc07f55539b4d253de1e6c25823a6258c7a9ced1501dce2786898a3e05c9bff8fc5b2125d0f471088a134b4873c8d55c0445f6ca396b3d7b4bc2bf5c4d2240da418293af6a3ed853dedd3bf668d937b35aa0c2acbf23766f9f3e96828475ab086496617a6e81d653589b2fe50b7ba8f0cf1e5a44d8d62f08377abfc26297:8c36b5a111c5a8119f2d9db57ebb592dae86ad4bf678c1492e26f3c10fbe03f105cae0dc68b55259b9b5989289db33d95d2ee6b756c760f9d3aa0e68a189de02896b7ab8413ffe439a2f4487ec49d64e31c74f50ac83f55da61a7003aa716c2a9df6b438e62f53d8f0192f3736324760d7e8c44ac0baca3ae2a6fb93f13d96886799fd2c4551b0ab36f1730855551265a5a3c3c21d9516a237f5dbc1c8e72999b782c5ca41a4f6e9308e64afdee0bf479e546b89c51bc5e4f71e57fb24ce437a8b81b91dc798b5ab36f29afd5b48e81c176ae5edf95371ba3246fb439405bd10eed3678e3ec62307a3b3dc1badba051f16774b85088188c2a9e320a1618d5f26ce94ee2b933c305f6d9584958eea3156c3d1e0ef39a186275ee62c40f3c1acd15d8be6e074351f5349ce3df69517505f45fa06a815c69ca18f450f42b5cf4ebd99268445e0f68104a7deeb0a115b817b99e1a73e0fa9d87db71f8ec94f8708c9bc2e622b963365ebcfb97cfe7332630070e9654eaa60361a45d402dc0ab297665242667fbd9940f6cd33195246a8c2869af759a862d4b641db144d5732366b20636c4027787f558027d76fcbf8432eb93e6d14567df8dbf211daeb5655db10acddd05eca06accee9fda8d3b70ca1e6dc587fa4b78f63cd663ff0243870570f4dcbaa3fb626b4e113bde47d5c9db2b4ba6ec6dbf918ac056949ef3cfcb115561615771a035a43d33ba2651dbeb46348261ce3c4c9f246d23f94dbc2d0c19b921e24c77da5992f1b4bdf2edea499f5411168ac0c12e96f3b15d2e12ac8d7b3ed8d1e07c4267a25d3a3c353a4208b7406278aab9e700f7b206f48e6ea7cc97e554f15c9be349dd91514dbe8d889f2dcbbfa182c9faf5807a69b2e97fa771a6f231a4c7b31d117b8ed0e630cdf13e082bb4f63c3f9acb3553204ccd76e1835c46eec3d43c561bbf17c92214a6db1212b6003cf2cc26c7ae675fcd053b947e722f9e85762ce8a16e4654ec6342fc646e5cab472797eabf658ba4afd142fc8fc4c8f98f23c24dc99847ae8cef0879e1ab3bb8097e4c3529add2d8e8e2c2069210f50ace1ae32a6c8e6384a2bf7d79c66c746149c84ad75a3a176e45e136d94695aed4bfd08b426ea8c4b9379f3742550e1cf5ac84c18174d680e92af2c1874ac1c13d28232de193768e561947cbd6b79e9b99da65cfb74ffb32f7d3d2025c60763dc07f55539b4d253de1e6c25823a6258c7a9ced1501dce2786898a3e05c9bff8fc5b2125d0f471088a134b4873c8d55c0445f6ca396b3d7b4bc2bf5c4d2240da418293af6a3ed853dedd3bf668d937b35aa0c2acbf23766f9f3e96828475ab086496617a6e81d653589b2fe50b7ba8f0cf1e5a44d8d62f08377abfc26297: +dcfad59fc6b697109e727ff66a5fe93a6a226f631a64e5797ad8d8c8b6358734e79f4f511372e355e7e9e0e8b5346fdbcd2df1fc5c3a1890d27fa1fa928d27a6:e79f4f511372e355e7e9e0e8b5346fdbcd2df1fc5c3a1890d27fa1fa928d27a6:7d92ddd8133c61c610c1308c23aeaf993884a4e67f7b94bb886dad509869a932ec4a27d410d2c29ca7aeae6f9280cf6c4b067ec751e5e8c39ff444d422ceabae145d42f047453dd402d1797405033409e72cc19f793d5d268fb3fd2c11ea2cb0d70436e18f9e88a01515dc865f6a1eb23690328fd75de26321a38f12197a97201b1d8452944fbc541cb68c77d49515db5326f2b1d0763eda06d250ce2a5e0bbd7d1676d7d41fb3abe88bdbe372f96bf7bb526d6b65a2515e83a577045b5479b38b852fe4ab011cbf21c085ef5f0a7c1bed76572b0f860228067a899f895ae7f6256eb6514087f9d6f5c35596c1f480c73113546cb9cc30f56ab074a9ff28acab7e42650a961da325ac5b6594b81c93250ae7d39267a19c97625407edda0404cbe5a36e959fc820b27ef5cad796c11eaff1c0e2f9d4b3c6491502195de03659b364e4e87b2b2d733ec25e6f9b63d5f69179e0d27bd4aecc8f12a507a91baa48d99b3a426cecebaef37d7361106a8490644309f6eb4d2596443b6b0118b945acecc6443ea61fcd155b54325bc2c31be0250f9482e13fd8eb44e2aed76be812af5453cb7f8632458fc8a02a2f45480d79b06c7dda38b4695d08b5a430504f1ae2275b05c91e799d4470f38abe77736dfa895c197ea4b63c2df18efeb14184837b8ddf48909520d91045b9d9655c225a83173960b4d7cd0d8bae30237557f869708be138ad5246c866c6c059dc597abfd4943237376896736b97b7e0289ef9bbd29477745cb60f46202f1de984f509b1808833f58018cde8c26bef4c005bdca385b05735110ca02e562b50eddff6fde9fbb8d030cedf7031bbeb32b12b242be49fde0160c1fbde99b03c062a1a47062345c92e0b604d080facce9243481529c70597dfd64382cb540691b59b71b094332baf0bbb125b63a446bb97491c0464328cabd7627c46f392f3b124822f2013c6e16d3ca87cc5becf56b0fc6eb2bf9923b3012ba2b61250a633a4d2ee391256c520957382aff970c5d22385c3344c6d4b4561571c96329bf75615297516b9f2ceb9f997a39523aa0f58b488772d82fc0d78c5dd52ecfa6bfac63a76e148088b36f24a88e68385496ddadf3023f72d87c2efa26e877d32f1da97cdb42c8f15718988e428cd02f4d09543bd0bd5b2f409963d0fa373531f78b592bd137eeaea0b4e7f918208e1d59008a8af5058f5d923c4f32df19990f10dd3f0eb206293b2b3443f4a5d2dcc5f7d3bbaf6af43fe45f5dbbe53ecf4bf1b4a13e2d46ef80298d4f01c402e210fcb9ff2084ec03e42008d:052ff79540737456c6a42c41c97d6bf517b8cf289bc78b503dee6a30ef5168b38f75beaca1e14d971f8773e3941bd6df5cb9778dea125a4c4fe0116b70ee840b7d92ddd8133c61c610c1308c23aeaf993884a4e67f7b94bb886dad509869a932ec4a27d410d2c29ca7aeae6f9280cf6c4b067ec751e5e8c39ff444d422ceabae145d42f047453dd402d1797405033409e72cc19f793d5d268fb3fd2c11ea2cb0d70436e18f9e88a01515dc865f6a1eb23690328fd75de26321a38f12197a97201b1d8452944fbc541cb68c77d49515db5326f2b1d0763eda06d250ce2a5e0bbd7d1676d7d41fb3abe88bdbe372f96bf7bb526d6b65a2515e83a577045b5479b38b852fe4ab011cbf21c085ef5f0a7c1bed76572b0f860228067a899f895ae7f6256eb6514087f9d6f5c35596c1f480c73113546cb9cc30f56ab074a9ff28acab7e42650a961da325ac5b6594b81c93250ae7d39267a19c97625407edda0404cbe5a36e959fc820b27ef5cad796c11eaff1c0e2f9d4b3c6491502195de03659b364e4e87b2b2d733ec25e6f9b63d5f69179e0d27bd4aecc8f12a507a91baa48d99b3a426cecebaef37d7361106a8490644309f6eb4d2596443b6b0118b945acecc6443ea61fcd155b54325bc2c31be0250f9482e13fd8eb44e2aed76be812af5453cb7f8632458fc8a02a2f45480d79b06c7dda38b4695d08b5a430504f1ae2275b05c91e799d4470f38abe77736dfa895c197ea4b63c2df18efeb14184837b8ddf48909520d91045b9d9655c225a83173960b4d7cd0d8bae30237557f869708be138ad5246c866c6c059dc597abfd4943237376896736b97b7e0289ef9bbd29477745cb60f46202f1de984f509b1808833f58018cde8c26bef4c005bdca385b05735110ca02e562b50eddff6fde9fbb8d030cedf7031bbeb32b12b242be49fde0160c1fbde99b03c062a1a47062345c92e0b604d080facce9243481529c70597dfd64382cb540691b59b71b094332baf0bbb125b63a446bb97491c0464328cabd7627c46f392f3b124822f2013c6e16d3ca87cc5becf56b0fc6eb2bf9923b3012ba2b61250a633a4d2ee391256c520957382aff970c5d22385c3344c6d4b4561571c96329bf75615297516b9f2ceb9f997a39523aa0f58b488772d82fc0d78c5dd52ecfa6bfac63a76e148088b36f24a88e68385496ddadf3023f72d87c2efa26e877d32f1da97cdb42c8f15718988e428cd02f4d09543bd0bd5b2f409963d0fa373531f78b592bd137eeaea0b4e7f918208e1d59008a8af5058f5d923c4f32df19990f10dd3f0eb206293b2b3443f4a5d2dcc5f7d3bbaf6af43fe45f5dbbe53ecf4bf1b4a13e2d46ef80298d4f01c402e210fcb9ff2084ec03e42008d: +696dc481f619a9498563c83d0d0e55565c14a07845fe4a66aba2247b113ff8efc9d737abc4a9e73c149eadc195a837899f2cd5019373c30ecaf62e5f8e14b645:c9d737abc4a9e73c149eadc195a837899f2cd5019373c30ecaf62e5f8e14b645:2d4b3ad0cc99f983e41f9b48c4a818eff75fcfb93a1229ec2740ed19c107d621df78058de7c2dd7251f5ff454340865f6c86da65831f6672db231726fdfe4b9ee315d93c7244a920df37054c82449d310f892932ddbad94cc9bb39ac8937cc76c96521d3fdc028ba23410b29023e8138fd3f524319884ee5dad0d234c8df661f8824be477e21699f6369b15ff3ffefc151aa555b3c3d76adb45f25672d380d472b3148dabdef4245b68e828562f25cc5b81d9bbb241bca9d1934ea353f95f7dbf3646433e81a354e1e2056b81c15aa1fa8ed7a9d1af99238cd5a5ae9e841c48dc348ae1de7c41aca23328236bc38b47f47c736b257a3078d57d574b647a7fc8c4d01bc50302150d5032bfacb04bb0fd155d94d9206667720e180a645af462459e3326d460da3c48e7572678e1919268d3e4740d62a26f7c8559c1c439b4b0b0c5942a620cfdb93cc68aa15520ff2864269d7a0c155780adc6c188e0b565fb9594319e6f51d15caf6b280e7158f25799407f3ba0dd1ceea64b9326d2cfdef017e1f172f4dde0f7e4613501af01ee0ac30095f48b59590902b1aecfe093413918d835adf962ecf18580d16f9fd4f6fa1098af1d8a2bc24dc86f71d0a61ff150010867d086987b51dd030f50ab6e374b8e01184b3e2b214ab1c7fdfaedbc545e38c3cd2f6982979541fe0ff88bed67506da95727af1a2038f3240ae5bfd30ee09210e00fdcf2a064d5db4614946bda972c670081a6ee6a10b63f673c83c915ca5573e0ed687b0067c400792a9bcc3344e0e43f5df63fed5efa85e9aaf85e4d7a2c53a6c92828e07fe63e2d23f1bdf97d84adc36e9fc95faadf03e06d65a19c5e285effd0ea0cfa839d55a0a0dbf6da28785c77f5c04bfd59974ef3793cdc398df7a1bbc9cfcfc3a51ffa9a20d60c47b245dafa3e44623cd711d7762c50a67d650c7e8c4fd3bebc0c498d2152ab9827c700c7b2861565749b5864fec95b7f6b1994e78d8f85d069cc11f85bed9712f7a9f060b0bf67532e88eb9df3eb4a8d2fbbaa85eda926d81c49fb86e73731b7ed2a1905078513f7ca0fdcc3b1d576e6a60124c44618df1890e169794956cb1ec501ba2049970c8e74cc180064c184468be4f089a3ae2263c855863b62c28313ddf9ca85bf66b08a264155ad7c328238dfe614a07ede9155a09ccaff92292249341baedcbe0e6466e2c76045e46dad2fc899a1782e00998e79a83abfae9b706f707f58e730203e1d2cca028c922beb6d157fa7a98132a921a3da21f2f769bb6c1f5f19e9e85a13b781af141039d514ee107:ded5d991935cd1f9390f1e85929ca16dabfc83e65e43272eb1751671aa31930c728555341430ce7c80485de58006427129a4d34fd681d52d840a16bafa1530022d4b3ad0cc99f983e41f9b48c4a818eff75fcfb93a1229ec2740ed19c107d621df78058de7c2dd7251f5ff454340865f6c86da65831f6672db231726fdfe4b9ee315d93c7244a920df37054c82449d310f892932ddbad94cc9bb39ac8937cc76c96521d3fdc028ba23410b29023e8138fd3f524319884ee5dad0d234c8df661f8824be477e21699f6369b15ff3ffefc151aa555b3c3d76adb45f25672d380d472b3148dabdef4245b68e828562f25cc5b81d9bbb241bca9d1934ea353f95f7dbf3646433e81a354e1e2056b81c15aa1fa8ed7a9d1af99238cd5a5ae9e841c48dc348ae1de7c41aca23328236bc38b47f47c736b257a3078d57d574b647a7fc8c4d01bc50302150d5032bfacb04bb0fd155d94d9206667720e180a645af462459e3326d460da3c48e7572678e1919268d3e4740d62a26f7c8559c1c439b4b0b0c5942a620cfdb93cc68aa15520ff2864269d7a0c155780adc6c188e0b565fb9594319e6f51d15caf6b280e7158f25799407f3ba0dd1ceea64b9326d2cfdef017e1f172f4dde0f7e4613501af01ee0ac30095f48b59590902b1aecfe093413918d835adf962ecf18580d16f9fd4f6fa1098af1d8a2bc24dc86f71d0a61ff150010867d086987b51dd030f50ab6e374b8e01184b3e2b214ab1c7fdfaedbc545e38c3cd2f6982979541fe0ff88bed67506da95727af1a2038f3240ae5bfd30ee09210e00fdcf2a064d5db4614946bda972c670081a6ee6a10b63f673c83c915ca5573e0ed687b0067c400792a9bcc3344e0e43f5df63fed5efa85e9aaf85e4d7a2c53a6c92828e07fe63e2d23f1bdf97d84adc36e9fc95faadf03e06d65a19c5e285effd0ea0cfa839d55a0a0dbf6da28785c77f5c04bfd59974ef3793cdc398df7a1bbc9cfcfc3a51ffa9a20d60c47b245dafa3e44623cd711d7762c50a67d650c7e8c4fd3bebc0c498d2152ab9827c700c7b2861565749b5864fec95b7f6b1994e78d8f85d069cc11f85bed9712f7a9f060b0bf67532e88eb9df3eb4a8d2fbbaa85eda926d81c49fb86e73731b7ed2a1905078513f7ca0fdcc3b1d576e6a60124c44618df1890e169794956cb1ec501ba2049970c8e74cc180064c184468be4f089a3ae2263c855863b62c28313ddf9ca85bf66b08a264155ad7c328238dfe614a07ede9155a09ccaff92292249341baedcbe0e6466e2c76045e46dad2fc899a1782e00998e79a83abfae9b706f707f58e730203e1d2cca028c922beb6d157fa7a98132a921a3da21f2f769bb6c1f5f19e9e85a13b781af141039d514ee107: +f3f8d62fee3af375669630cbf063bfa930189af136cd7591e24d578d7366bf614714c604aa95e1828a28367ba78760b5896431683ee996cff96871773291953c:4714c604aa95e1828a28367ba78760b5896431683ee996cff96871773291953c:e1dd1ffd737ac6dc24b3b9ce3b79e835bf698e931303d809cea1782dc3af63a0d5e67392823d1439e7b6e337b01c8b215434c2782b3be7443cb5c881e5fb6cf3bb244128b4da6a6f42b2bb2cd75129d56418854348c339dcd912b45557a915e9fd7f37916236510cb6c331c140b87d225311600b8d132ac47473839c720f9ff0f9c1dcaa85815a9d27b9758cd91dc5d3e53326fcdfb2730e52be3103957ac89149a4c3004cb6038c0d80fa72ac630d333be5ad4adb585aeb71aef1cdfd57b915fac4f1af78e7a597f8d1ba06672b19c0b65808a8a071ff8409034379589f3d41302d2d39b3318e8c0090fa36cb958857ff5b211c9666e27bc895ab9d006abaf5950a03ff17ea982178a446dda2466f5a40b8f895509e4f4d4a6a2739997fbd4968f89436cee3d8edb8a6da9bd3d55b066490e8339c78935b77883f95b932fa5e6bb7df303be30fa567249fffb473a1e464322d7c103fe8224c7ec57bd39bcd030b96787aebcd20e9ad651cfa2bf04ba70a1cf648e0a5449567202a937a45becbb6fcded30cf9b5c748f882b5dc2a4d65be69fd7d9c381e83d0dc2a34b6dee91220ba906e512fcd63368e2ce733e466b4b82b84fb0c717dc8945caf6d46ac1c2f6418f7729ef4c35e402422d64b1c3ebd1b32a30fc4c5eece7d4408ff679ff01a1c7b03ca517be52e6ae7650f7bad38901e348a5593bc998f7cf2ea97729cb004f561b3b58fe59809a41fd4b3b76660906ad9eda23bf925437ef452b16f540b3b80a35a7093c2734eefe6fa97d881d79ef5b767d9889f118477b73f58a4c0cb15e0ac8101120571ca32ce871f308ad9057a80c828154fb1bc2b201d0cd1006e022d444dc93f1bcf224db74a5b373e153e851854948b6da147b73287cf17d1fb72b4827611103609cab2a1779e9793b9a70820fc6f3828a64c9eac35ef7aa7b17609d8eff8a9e52e4ebcd86b1e14fd140bea47c6b8ddc41e8cd271eb92287cbd0610512242f76a1ef3eac1e4bbbc1adae50034a7a2647e08b2fd20aa93a93cb2ffdebf2e461eccefbbd1fe894ce70adf790173bae96f5a55a1887e9ae09fced1d4306c291c6b19ecac4707e9ef713ea18a7562c6678326228992077a4669734966108000b4144f45a0c3a2863a4c6a3c07632cb93eb197d294884d9ca3dd4b21f39db707f63a7f9a570f7f0feb99b2ca7da7df92a177abcfe86ec661d30bcdcf1522bdb1fe11673258df7e46ef4d326665093156553f28b3563fe7192f72f5f9b3903d79fea04e2c488b465b4978d69f26e05a59d5ed4ef4cab232acfd564fc6:8d6f7ceeb9308b4a303879fc6cfa5ca8e05dfc3defc2b2cd2910dd4b17c94eaee845abe65fd715df05b0128e4316e2334799c6e8fa747ebc8a040c74f5a1480ce1dd1ffd737ac6dc24b3b9ce3b79e835bf698e931303d809cea1782dc3af63a0d5e67392823d1439e7b6e337b01c8b215434c2782b3be7443cb5c881e5fb6cf3bb244128b4da6a6f42b2bb2cd75129d56418854348c339dcd912b45557a915e9fd7f37916236510cb6c331c140b87d225311600b8d132ac47473839c720f9ff0f9c1dcaa85815a9d27b9758cd91dc5d3e53326fcdfb2730e52be3103957ac89149a4c3004cb6038c0d80fa72ac630d333be5ad4adb585aeb71aef1cdfd57b915fac4f1af78e7a597f8d1ba06672b19c0b65808a8a071ff8409034379589f3d41302d2d39b3318e8c0090fa36cb958857ff5b211c9666e27bc895ab9d006abaf5950a03ff17ea982178a446dda2466f5a40b8f895509e4f4d4a6a2739997fbd4968f89436cee3d8edb8a6da9bd3d55b066490e8339c78935b77883f95b932fa5e6bb7df303be30fa567249fffb473a1e464322d7c103fe8224c7ec57bd39bcd030b96787aebcd20e9ad651cfa2bf04ba70a1cf648e0a5449567202a937a45becbb6fcded30cf9b5c748f882b5dc2a4d65be69fd7d9c381e83d0dc2a34b6dee91220ba906e512fcd63368e2ce733e466b4b82b84fb0c717dc8945caf6d46ac1c2f6418f7729ef4c35e402422d64b1c3ebd1b32a30fc4c5eece7d4408ff679ff01a1c7b03ca517be52e6ae7650f7bad38901e348a5593bc998f7cf2ea97729cb004f561b3b58fe59809a41fd4b3b76660906ad9eda23bf925437ef452b16f540b3b80a35a7093c2734eefe6fa97d881d79ef5b767d9889f118477b73f58a4c0cb15e0ac8101120571ca32ce871f308ad9057a80c828154fb1bc2b201d0cd1006e022d444dc93f1bcf224db74a5b373e153e851854948b6da147b73287cf17d1fb72b4827611103609cab2a1779e9793b9a70820fc6f3828a64c9eac35ef7aa7b17609d8eff8a9e52e4ebcd86b1e14fd140bea47c6b8ddc41e8cd271eb92287cbd0610512242f76a1ef3eac1e4bbbc1adae50034a7a2647e08b2fd20aa93a93cb2ffdebf2e461eccefbbd1fe894ce70adf790173bae96f5a55a1887e9ae09fced1d4306c291c6b19ecac4707e9ef713ea18a7562c6678326228992077a4669734966108000b4144f45a0c3a2863a4c6a3c07632cb93eb197d294884d9ca3dd4b21f39db707f63a7f9a570f7f0feb99b2ca7da7df92a177abcfe86ec661d30bcdcf1522bdb1fe11673258df7e46ef4d326665093156553f28b3563fe7192f72f5f9b3903d79fea04e2c488b465b4978d69f26e05a59d5ed4ef4cab232acfd564fc6: +865a432ecce7e78c42709fc1e531df5e3959132b2b6f318fd1c34521f9a26e3bc7a8caf8930b622a501337f92840ed96611a322080fde5e49f0a2f6e33b88283:c7a8caf8930b622a501337f92840ed96611a322080fde5e49f0a2f6e33b88283:b231b6d2ecde49f513b0df25aafc3e5da45b6a9958d60f5464ca593c03005ecf361ef1696bb6e55d6538e34b38f324c21cea5cc81a0073278bb92727eff81af561802dcef33bec10ad6594e22d9c4418af3988a43ed087b9954bf8d6283e4beae8c096de6606751cbed685846c6630b9528ff364a7c48464113472c9860b3371963c911495a9c628a3e3e47ab0991f10dd1dd33161525262d63bab648819d57d1269e114825c5434e6b2845f42795d4fb083ad79401f2a0761c634a545aec7cdb13b5be449f1d829326378ed1f493fe8c8e9b068cc1dbcf165550b8132c319dac487b87bb22a54cdf60aac71516182a4e69ba083f6e86d1a4f05083a77619ef239f702396d7e46968cc04a3b34df3265ecf16157abe15c642cd7427096d8d40db002d196cab1be304bcf322d9d1a2451b6c11eeaf3e8e3d929f480b6b77804fe84496ca757e04337914ce94475d7990c7457c8e606f8bc207d2d48119c80a6b4a9e07b229226570dcd994989fecc694c6c2fb5975c9a6a9b74e8159c27dd3677dfd5cb651f1e32adfafd810b6e5d5efbace31ae6d9b12191e89398da063f138b7584c58e77e7f9fdd7fb9ef5d68ae49c6ccad28d18bc6009d4187ed1420224a5658aadf135b5a953f2dc3c8bfcaf669ed5da38d0144fd9665e6f0677d3fc8804e21cc25fd5e01a3f3fa83e571eb2f882a7659ce5d864d8bb54072b0986a854f1a7f2d2720df857e6d4219630841b1ccdcfc6726b91bfc17e18c3e3480c23a2c05e4bfeddd4db9ef42388f234fd3e4f3dad666026e2780612374161316afc7665f9411b6c5aa78933b18021c012b084f3244760a4ea1bcf31cc9f5c4044a9bcc75a986707f38f45ac1c7fa139ee95a6d8f16c3c1e12764c4b0b1194c0fc5f7eeff9a848c4050b0e651684719d438aad56019164fae4f48882205ece0b99736791084a753ba7d56e88fceea533566c3a2ca48dd6efc49b27dbf14f2616ced652e13833ab9028ada454431c89b3cb7441fdb8f23e12b60a1a104a2a8cf4a64e878aa26f54e8881a4b151a16a96de8b9807e729396ebe3e3d394f808bd74b7312fe6b84b1312af8a1e4133599d07bdf33db21e016b5c196c1ba3115708f581bb82f4b57a6ca1a529e64d193042c1dc5faa0a03abf53849e1bdefbab64b1cb60fe10a3fc1823a234c45f3b0dce66a46739c01aead12de6f0313c7be71405f3fdc4a507a9d84e8686f6fc92635db0f7856c7373a618a7252c129a7760e2029543d726228c21d00ad4ac52e5b1a6e31200917f15af515859e08f2a79ace67991ed69044:32bb7520e2639c6cca19a2b9836b08f8b083ca33369ddf5f9a877d4c7a9eb05f9c3dc34ed4cfa4b283e51922b094066ce9ffa4d9df621910ca37b0b37fbabb0eb231b6d2ecde49f513b0df25aafc3e5da45b6a9958d60f5464ca593c03005ecf361ef1696bb6e55d6538e34b38f324c21cea5cc81a0073278bb92727eff81af561802dcef33bec10ad6594e22d9c4418af3988a43ed087b9954bf8d6283e4beae8c096de6606751cbed685846c6630b9528ff364a7c48464113472c9860b3371963c911495a9c628a3e3e47ab0991f10dd1dd33161525262d63bab648819d57d1269e114825c5434e6b2845f42795d4fb083ad79401f2a0761c634a545aec7cdb13b5be449f1d829326378ed1f493fe8c8e9b068cc1dbcf165550b8132c319dac487b87bb22a54cdf60aac71516182a4e69ba083f6e86d1a4f05083a77619ef239f702396d7e46968cc04a3b34df3265ecf16157abe15c642cd7427096d8d40db002d196cab1be304bcf322d9d1a2451b6c11eeaf3e8e3d929f480b6b77804fe84496ca757e04337914ce94475d7990c7457c8e606f8bc207d2d48119c80a6b4a9e07b229226570dcd994989fecc694c6c2fb5975c9a6a9b74e8159c27dd3677dfd5cb651f1e32adfafd810b6e5d5efbace31ae6d9b12191e89398da063f138b7584c58e77e7f9fdd7fb9ef5d68ae49c6ccad28d18bc6009d4187ed1420224a5658aadf135b5a953f2dc3c8bfcaf669ed5da38d0144fd9665e6f0677d3fc8804e21cc25fd5e01a3f3fa83e571eb2f882a7659ce5d864d8bb54072b0986a854f1a7f2d2720df857e6d4219630841b1ccdcfc6726b91bfc17e18c3e3480c23a2c05e4bfeddd4db9ef42388f234fd3e4f3dad666026e2780612374161316afc7665f9411b6c5aa78933b18021c012b084f3244760a4ea1bcf31cc9f5c4044a9bcc75a986707f38f45ac1c7fa139ee95a6d8f16c3c1e12764c4b0b1194c0fc5f7eeff9a848c4050b0e651684719d438aad56019164fae4f48882205ece0b99736791084a753ba7d56e88fceea533566c3a2ca48dd6efc49b27dbf14f2616ced652e13833ab9028ada454431c89b3cb7441fdb8f23e12b60a1a104a2a8cf4a64e878aa26f54e8881a4b151a16a96de8b9807e729396ebe3e3d394f808bd74b7312fe6b84b1312af8a1e4133599d07bdf33db21e016b5c196c1ba3115708f581bb82f4b57a6ca1a529e64d193042c1dc5faa0a03abf53849e1bdefbab64b1cb60fe10a3fc1823a234c45f3b0dce66a46739c01aead12de6f0313c7be71405f3fdc4a507a9d84e8686f6fc92635db0f7856c7373a618a7252c129a7760e2029543d726228c21d00ad4ac52e5b1a6e31200917f15af515859e08f2a79ace67991ed69044: +2be1f98ce6553c915b6a0933ec0de347b370e29ca294e8005541239f63b430d07a6f4469c30a63f560f98734fc1906ebd1371ed80125fa3e4c86b43f262cabbc:7a6f4469c30a63f560f98734fc1906ebd1371ed80125fa3e4c86b43f262cabbc:6268201f932a7cd3f879ae6ab83855a2f50291de784d7d9e9adaa1b9afed6f5aea20240e59fe93e5a7088c95ec8e15745fb8fdeb91df0151c7b4605067561ea08dbf00c4ffe1fd0acf103656a7b54fad0f25ab16b4bda347179ed1cadb7b98be0895e050dcbc379d1fd553e99795928b67a752f8d2ec1b9d66bf6ac997e744dc327f242230f92e79ae312745a5ab6ddec1998fb63dc4f6b05f147222d4b65ace9017dc1bcd675e495f9eabb5f602133f6c72e053e9f4ae30d872d78bf71feba37acc595055c3bea53a05ef0c7f212dcf4e0af838ea2928f4cdc9fdc837da25f26966b2456abea66a5dfb8faa8fa091f7331d5436e98a8d6323cc9e9a91d5a02a49511714849b47454baf99c5f850a08d3d98410e939a9e89b15053825f3e9aee71447416140782e1bf3b0d8b4ff62e77a4a03f710a8ab76cf63592c05c440c8f064770099163c12270f3d5ec9a6bc9715bfffec769611d21fa003c3cc8356c975d37b62b88aabb8597daca196c9648a31d15bb0b86cf070ee01e511ef373b4a44c6a00160a797f2e820b716f5ca64464e4189a00fee978d35bf204f71db1f501f9b6e5dfc821a8af5dbfefd353ad3681f9bc3c22c67cb211b430b6a55f3e73da7c3a07ceb7d2fe254b10c2703ab2e2294dd0d3152dc7b21aab87b150f737a947463fb204175de8543236fbb0da5c7d48c57f61744de6f984aa8e61b970c62d0eeb849da7e89a61222d432079cbcf5f8a2ba930301683c0785c26fdf85da3020874604599ac6c847ec2608658b5788c7b8d3a3744fd5442e24c8eeccd420756bdd8b8a77cfd80589605dced9afda2bdb630a0cb612f739ce617d54ede6ccf36aa31e7e373d8a0fb1b7c9906f76b5f9de8c26891de006eb797ead4a86f7016f34bcde92f94ac3e920ba58d6dff772078d802a94f56cb26bf794fd90ca0ad4f2e7acdc5929bc7364997ded98ca69c573991bb9ab85f235b63e76f77e0ab45e78912389869af21e74e66f7c456b827e670beb0f0726688bb1f9036d38da07d69ea3666f76bd605d82e2dd6387ece6e824a569700f01b195d1a9bdcb0f96ab5c54e06c2119b406bc4888480660418bb4288ea2fda96631b0e1f60ac861d6ccc4c844b647a7d7403bc2d15bafe4af677e856fe0d2b5f663be4e480b38f6b766adcd3d05298ef1398d04d1523a68b91dd31cf5dc4b73decbfd7213f981b207e1f6ef225d7948a1aa17d8d57a112f1d4468d2d28f7ec2e54b74a692c5958022e82031a41b315090ed4d5bd7bd0b451476338f739a7d7031af2d36caa09ffdbb7c396507c75:8e659a3f535a589a5fd2d217cbcb8b777e5af20b234432f7dac29f810a2b4737c5cab10b59dfd0144f3090f5f9e0e667f0e21a9f573fe13b1c28eccbb531a2056268201f932a7cd3f879ae6ab83855a2f50291de784d7d9e9adaa1b9afed6f5aea20240e59fe93e5a7088c95ec8e15745fb8fdeb91df0151c7b4605067561ea08dbf00c4ffe1fd0acf103656a7b54fad0f25ab16b4bda347179ed1cadb7b98be0895e050dcbc379d1fd553e99795928b67a752f8d2ec1b9d66bf6ac997e744dc327f242230f92e79ae312745a5ab6ddec1998fb63dc4f6b05f147222d4b65ace9017dc1bcd675e495f9eabb5f602133f6c72e053e9f4ae30d872d78bf71feba37acc595055c3bea53a05ef0c7f212dcf4e0af838ea2928f4cdc9fdc837da25f26966b2456abea66a5dfb8faa8fa091f7331d5436e98a8d6323cc9e9a91d5a02a49511714849b47454baf99c5f850a08d3d98410e939a9e89b15053825f3e9aee71447416140782e1bf3b0d8b4ff62e77a4a03f710a8ab76cf63592c05c440c8f064770099163c12270f3d5ec9a6bc9715bfffec769611d21fa003c3cc8356c975d37b62b88aabb8597daca196c9648a31d15bb0b86cf070ee01e511ef373b4a44c6a00160a797f2e820b716f5ca64464e4189a00fee978d35bf204f71db1f501f9b6e5dfc821a8af5dbfefd353ad3681f9bc3c22c67cb211b430b6a55f3e73da7c3a07ceb7d2fe254b10c2703ab2e2294dd0d3152dc7b21aab87b150f737a947463fb204175de8543236fbb0da5c7d48c57f61744de6f984aa8e61b970c62d0eeb849da7e89a61222d432079cbcf5f8a2ba930301683c0785c26fdf85da3020874604599ac6c847ec2608658b5788c7b8d3a3744fd5442e24c8eeccd420756bdd8b8a77cfd80589605dced9afda2bdb630a0cb612f739ce617d54ede6ccf36aa31e7e373d8a0fb1b7c9906f76b5f9de8c26891de006eb797ead4a86f7016f34bcde92f94ac3e920ba58d6dff772078d802a94f56cb26bf794fd90ca0ad4f2e7acdc5929bc7364997ded98ca69c573991bb9ab85f235b63e76f77e0ab45e78912389869af21e74e66f7c456b827e670beb0f0726688bb1f9036d38da07d69ea3666f76bd605d82e2dd6387ece6e824a569700f01b195d1a9bdcb0f96ab5c54e06c2119b406bc4888480660418bb4288ea2fda96631b0e1f60ac861d6ccc4c844b647a7d7403bc2d15bafe4af677e856fe0d2b5f663be4e480b38f6b766adcd3d05298ef1398d04d1523a68b91dd31cf5dc4b73decbfd7213f981b207e1f6ef225d7948a1aa17d8d57a112f1d4468d2d28f7ec2e54b74a692c5958022e82031a41b315090ed4d5bd7bd0b451476338f739a7d7031af2d36caa09ffdbb7c396507c75: +10bbe6e761a75c935b517f0936fecb9ec6fc215e58130800ea18d1ff442a4f138643ddf8aa8d9c8a78b6eb699fd20a57f6f18636b06ce69dacdca1267acb3954:8643ddf8aa8d9c8a78b6eb699fd20a57f6f18636b06ce69dacdca1267acb3954:e8108c6de4133733dc199a73392e226f712c36a24fa91d6fb09f92df218deb2d2830a668fd694b4809d0253507231247c7f258b4d65c56bb69345ef6aa97e7c59e8153775a5a3cf109c4bca9815569da6932e82183425b42d7483c9dbfcbd8eb38c84729571e8ec93982c317716759598c4f6a1b7f8da7306a7815721caf02e70246712314f766be9cb177cd2fa3bda22cd676c5d2e86e8d798fd34f543c9be3129651f273f484f0b9467b140955cd2981ff2603c0bdbb436ac0955a116c5e5fc30425e1fe78f6410f6ef757f604668854bae79bfe22e1a85ce5ee5d6434b4610120ea7e5d3d137ce207514f8534ad9bf392b7dc5355514b59f835466c8eb56f44eddc5bad20cf0b480b2e822a6f46fd95f30f183c7bb3143e4e6100e2dbc9f2bf0d43073e0fe65f01bcce6a1ae401c12541be3ae68cdeac2a4ac71f1663b5fdfc2e50f0e077fb3a0a8b8eeead627c1c3e79dd7361046f7e57c17436c32dc4432f050028cc7aa4408c2d29d1d7998fdcdda32bb32f704dc263db9b8e06c57630870f8bb6ec661fde1b7da94d53b047701a4588478c1c662346741aeac4c25338556a3d848de5b2a23ecea61b776bd0e8037efb8501eff239c7facca6c8367ed7c8adce919fef1a155ae0d5478a98002c95a16fbf4c0ed016ea5d3866fe1de454832a4e9565976b60b3dd2eaf7fee612f2bc040d93975435eebd12f06eb09ecea2c66768308f58c77ac51ed7bd21636fc9cc3fd14870bd06bdf128a81b14792e608c47ea2d535ca7aa21eb8a8a56d76991663a8190a95057d33671e73c7cbce5a98d31ef0d73bd0b163787b7fdcd2ddfc72960f2be320846d4b29080d7aeb5b7ea645a2ad5a59c012bf7b9515d859e1c1472ef8a4d3c95e711af97ae4618efbab3dffe88c9f6af4a09b0e73387e251b77d7bff5214f791862db6988411e2ae2c75bf28d28602a637c26f49c18d309d2fc58a126667ad3c2ec160c99ba40fbdac17e7e4c21a5d507859762eba09c4160df66f5feefe6715a28c5296cf43e5e771f31fce5133be97cab57301b4c9df9cd9a4acf1c33fac946fa1596fa65c8f3658be47a473a62c52181eca183e4246cd624d8783dcce5fdcc1fea173f8071f7074f55897de9bfe84a6c4fdf802d5026b8145e6c8c8950afc5b40fd0356fc55ee17e1f853a4c2fcc34a1369b87d28dc2fd2010f19903aff8e46de04938f4948245d5b425d074acdf2bd80bfc3735cc34a22590f194af9313eef4ab5fde61f1f9b58578638fcb4f2850b2fce6e03db4d0a834848163c4b27e129f5cc74f67f008a2712d1d:f0f357410373313b7c6252d6d96600360c23752d431ca8075bcfb772d49cd609b65c9cd838d634d8d9b95d1ee30edecc13e3ca997b2437303f8a33a1ffc83306e8108c6de4133733dc199a73392e226f712c36a24fa91d6fb09f92df218deb2d2830a668fd694b4809d0253507231247c7f258b4d65c56bb69345ef6aa97e7c59e8153775a5a3cf109c4bca9815569da6932e82183425b42d7483c9dbfcbd8eb38c84729571e8ec93982c317716759598c4f6a1b7f8da7306a7815721caf02e70246712314f766be9cb177cd2fa3bda22cd676c5d2e86e8d798fd34f543c9be3129651f273f484f0b9467b140955cd2981ff2603c0bdbb436ac0955a116c5e5fc30425e1fe78f6410f6ef757f604668854bae79bfe22e1a85ce5ee5d6434b4610120ea7e5d3d137ce207514f8534ad9bf392b7dc5355514b59f835466c8eb56f44eddc5bad20cf0b480b2e822a6f46fd95f30f183c7bb3143e4e6100e2dbc9f2bf0d43073e0fe65f01bcce6a1ae401c12541be3ae68cdeac2a4ac71f1663b5fdfc2e50f0e077fb3a0a8b8eeead627c1c3e79dd7361046f7e57c17436c32dc4432f050028cc7aa4408c2d29d1d7998fdcdda32bb32f704dc263db9b8e06c57630870f8bb6ec661fde1b7da94d53b047701a4588478c1c662346741aeac4c25338556a3d848de5b2a23ecea61b776bd0e8037efb8501eff239c7facca6c8367ed7c8adce919fef1a155ae0d5478a98002c95a16fbf4c0ed016ea5d3866fe1de454832a4e9565976b60b3dd2eaf7fee612f2bc040d93975435eebd12f06eb09ecea2c66768308f58c77ac51ed7bd21636fc9cc3fd14870bd06bdf128a81b14792e608c47ea2d535ca7aa21eb8a8a56d76991663a8190a95057d33671e73c7cbce5a98d31ef0d73bd0b163787b7fdcd2ddfc72960f2be320846d4b29080d7aeb5b7ea645a2ad5a59c012bf7b9515d859e1c1472ef8a4d3c95e711af97ae4618efbab3dffe88c9f6af4a09b0e73387e251b77d7bff5214f791862db6988411e2ae2c75bf28d28602a637c26f49c18d309d2fc58a126667ad3c2ec160c99ba40fbdac17e7e4c21a5d507859762eba09c4160df66f5feefe6715a28c5296cf43e5e771f31fce5133be97cab57301b4c9df9cd9a4acf1c33fac946fa1596fa65c8f3658be47a473a62c52181eca183e4246cd624d8783dcce5fdcc1fea173f8071f7074f55897de9bfe84a6c4fdf802d5026b8145e6c8c8950afc5b40fd0356fc55ee17e1f853a4c2fcc34a1369b87d28dc2fd2010f19903aff8e46de04938f4948245d5b425d074acdf2bd80bfc3735cc34a22590f194af9313eef4ab5fde61f1f9b58578638fcb4f2850b2fce6e03db4d0a834848163c4b27e129f5cc74f67f008a2712d1d: +186dcc7efc5ed7e61ae53dc42093bae8f15dd99f0f033326c576ff756950d06dc8d141acb642aa9bfbd543277c2dca8aa9888eeff04543b3789b21f26aeb0f71:c8d141acb642aa9bfbd543277c2dca8aa9888eeff04543b3789b21f26aeb0f71:974364d6c838842ccc4e749e6afd537170dcd8cc50d66654d105482339cabdf74e32935ee219272ea1684fb93c1fab42b5631839243591bd07d3be949b0dd15e3196df196ba752ad1121ac7112d566944e153a4e0619b3a232241f020be0719f6bec918b26828eb1670ecfc73c66844ea3e404c6a2fc01beb403c9d6ca551ad8a6e71f46647fa6053f0314f8124d8d2bc12cc8fa8db95f2b735375201b816a9cf40f83ee4b8671618032de229ce76271d03d2672a1ae4a288c85dcd27fb8452a8132e9ff29e1e89bf11b1c835192c04b13be14f3cde5d37ce96f1dc2a9ccda0c4d737bca1fa220d21bf360b90515bbd226bb2a6c8d5f2ab018d4084e24ee333ce4e39bcb6b46e7aeb4db9b6c65b244d982823a770f9c62a0bde2cbb7ec36840d455187faff4e488a5c608ebdb7db84d87dad3867e3b0d04b64715e16560a62f1ee03df6183fd5e37555da1972fca062d12bb8420e082dacb8debb9c1438541d0da2464ef7ec52263fb9b9a4c469c83323e4819dfdf4fa0a770c3a709254e05314830e87fbb6736c72d9dabe01a310e91ebbfae767a1fcb62f64fa3ba8d53400d6469ad1ccb811fb9e115f14127b13e8364aa2fe80bbc886a10df1b9cc4ae4601f5461af091f526d272da9b203857a4447eabdef439830496a5759c21de65ba3a3c8b8e939c461332a924852c205c7711f3a68a2367a945def4fbe5f81c60cbb7e394a2a49be9ec2aaeb1f330575979446ad9d0d54abd436f2860f0423426f4bbc26b3b9f650d69b10072d747a39e478f455eaa12c7c6e12bfc4536a3594344bd02b620e3e2b4e0d534089dd7b04fa634804567586c62be0391c7bdb0a9fbc1ef3b33211edbf8ef58c2b7a49d06667959d7e5d44671ee7357a10ba0cb1a445ae5d709ce255e92de715975af94b89d4a29c71f9d88c85b6cd11d8b335bf8f2c658e6dd7c3f6c80ad4d0e5a6c87dba7b5b8a8a47e72f4d1d3c743631df9adfcfa45cee0498d5a44a9f75c83b75b2a3c230ff0767d3888f941ee1b6624dd0e12d06ed1ab8bb135ffd379e9de3788be541aadb2d6a7cc601316f21eb9aaa922f56a8e3526c9bd1177fefc2fbe3e430b628eebd6661e3ba2d631c6a8422c241ecd969972412f74da6b1243bf0fbee8a84d52e40aee3f1e4fc831402c62f3576b22e8e3c3dc4e160bc3b6b9d2ce005853812eafc0a4e25ba712279b00ba3f9130ff36e3ef1971dde7508b2792fe64d475688fc6f3313aadb785302e6b7f9a84f2dbc2f3cf060ee08b463736f836dbb262d329684c208492d17d811221be02b65ee28e11b54692:8945069787c1c676a84a703cae1e0bacaeffd33e91bec3603e1f13fb170e31e6d7049eda2bf627180f456c3f7aabfcd36c49a8c04f8ae6929ec5ada07b657208974364d6c838842ccc4e749e6afd537170dcd8cc50d66654d105482339cabdf74e32935ee219272ea1684fb93c1fab42b5631839243591bd07d3be949b0dd15e3196df196ba752ad1121ac7112d566944e153a4e0619b3a232241f020be0719f6bec918b26828eb1670ecfc73c66844ea3e404c6a2fc01beb403c9d6ca551ad8a6e71f46647fa6053f0314f8124d8d2bc12cc8fa8db95f2b735375201b816a9cf40f83ee4b8671618032de229ce76271d03d2672a1ae4a288c85dcd27fb8452a8132e9ff29e1e89bf11b1c835192c04b13be14f3cde5d37ce96f1dc2a9ccda0c4d737bca1fa220d21bf360b90515bbd226bb2a6c8d5f2ab018d4084e24ee333ce4e39bcb6b46e7aeb4db9b6c65b244d982823a770f9c62a0bde2cbb7ec36840d455187faff4e488a5c608ebdb7db84d87dad3867e3b0d04b64715e16560a62f1ee03df6183fd5e37555da1972fca062d12bb8420e082dacb8debb9c1438541d0da2464ef7ec52263fb9b9a4c469c83323e4819dfdf4fa0a770c3a709254e05314830e87fbb6736c72d9dabe01a310e91ebbfae767a1fcb62f64fa3ba8d53400d6469ad1ccb811fb9e115f14127b13e8364aa2fe80bbc886a10df1b9cc4ae4601f5461af091f526d272da9b203857a4447eabdef439830496a5759c21de65ba3a3c8b8e939c461332a924852c205c7711f3a68a2367a945def4fbe5f81c60cbb7e394a2a49be9ec2aaeb1f330575979446ad9d0d54abd436f2860f0423426f4bbc26b3b9f650d69b10072d747a39e478f455eaa12c7c6e12bfc4536a3594344bd02b620e3e2b4e0d534089dd7b04fa634804567586c62be0391c7bdb0a9fbc1ef3b33211edbf8ef58c2b7a49d06667959d7e5d44671ee7357a10ba0cb1a445ae5d709ce255e92de715975af94b89d4a29c71f9d88c85b6cd11d8b335bf8f2c658e6dd7c3f6c80ad4d0e5a6c87dba7b5b8a8a47e72f4d1d3c743631df9adfcfa45cee0498d5a44a9f75c83b75b2a3c230ff0767d3888f941ee1b6624dd0e12d06ed1ab8bb135ffd379e9de3788be541aadb2d6a7cc601316f21eb9aaa922f56a8e3526c9bd1177fefc2fbe3e430b628eebd6661e3ba2d631c6a8422c241ecd969972412f74da6b1243bf0fbee8a84d52e40aee3f1e4fc831402c62f3576b22e8e3c3dc4e160bc3b6b9d2ce005853812eafc0a4e25ba712279b00ba3f9130ff36e3ef1971dde7508b2792fe64d475688fc6f3313aadb785302e6b7f9a84f2dbc2f3cf060ee08b463736f836dbb262d329684c208492d17d811221be02b65ee28e11b54692: +0705b336c89ca35ffdde0af0f906eacf623c56c3f76738168e76fcd5882df79eeaaaf2a15f44b634cef15a638b80207f61099a0796f5d43f3e9d048e6ae796c1:eaaaf2a15f44b634cef15a638b80207f61099a0796f5d43f3e9d048e6ae796c1:616fe15fccb3310f9ec7456447dadaf8e0a5fb269be169b0c3ea2cfdaaa55d37937fe75b78324ac278a65047e0ae4f327e97effcb7bed91d09da720b0a101be9e96d0ba85b1ff49d8d1df362d3454f0db6825596101c97e5dacad07ec492d30f2d0cb7e7de4e744bb6a6100b754da847411d09aace8d5d410758b83087db4b5e6297979a21fb65af390952c4f936260e72d7c78327b94aa6cd617278b0ce9e1bd3fbed93b69bc64985dde0e2c4357b502f055ee7b0a0388474dae02d6c1a731f87785d753aeb0d9cfdf85002df566fc2507de7ba6fd035bee17a2e808b4a7588c583375c82407a40ae9eebdf94df2fb8cabf17606c439ea70459b212aae4a3f530ecadc5e88e2548fa643c7ddf5063b2e10673e59d07fe906892b67eb58f9388a56b370452e9977755fc04dfbc77da6c05beddebf0365256b52c9aef8a82173b8c89fbd98cea36a8b896fe66d37ca79bec7fbfe958fe89f6765085b335dc770343e230caddfa2833daa662fe8208dd885a6fdf72e36ecf22bbbbcbe79d370650236940bc2e6d4ac74fe4d554c9bc232f07d2af6220d157bd2da6a6612a081b4c9904a2869b137ee3a0856f12b2eb8762db94ed0ba136f23e7fb4bd1fcdee10dd84e2cd3b0a49148ac74db466dbeef81e6a8ce0861102de9b1a3e1dcf5c6b0308a82e3ac7c2283c7cc2f34ffa145b9f74b79904b32b79e960b814aade63a0df0167dcd24ed90a8da7b934c772932f5a478fe2a72f945a13096ec37ce764b581eb89e5f6b2bd7eb88b85a89587774d458c58cd879457973d648ef771c5f1deb27a0cc5b29246ac2fa12d18ddc6b9f9ac9cf146c3f22b1e4499adeefbcd2249740e13a224e7b6b3ef15605e7e74e68d7b72642409b90c4ec161eb24c9b40ff9c7e6e5da98322aca52c46a8ddc190f1cab157c4c7619601a6b33df6a50da661bc75360dff69750d3457409cc0241c3e8c4b3e506d426af52b70231cd6c91260cc431e4ccfd496ca14ceaae1cda78721e16339d52682b6951f966c7da5c6e10d919ae66a9f52dec10867538d3df6d593a32db695a8d7745703516ea56f8c1c8f0ef53bdeb7f53c2d944f511940ccb90624922ac599f4619c3046207d605f6ff94de788d25342229dc8af92b5fdf0dd71df2b446cdf1d9a20524339ee1c31826287ef72781a7a35289f85a15ba57c7fd5d885bd0553ab40805f517e8f1b1b3c4fc6771e6f224bc031124b9c9aeb19c5a96bf1488e1e66c6e88809230c83a74155554a219ec379ae54a9fe79dbede3d576042a635d197f4d818c778755b8b45e513deac88f60425:d4a9bae8ecc472c376bab805c2ce0c1c2ed5fc773715468cb1a4934564dacecf438b1dd2ac1b5c5e336a1e20701d5dcf3c8ee3ad223b139fa90a1b552e1b7707616fe15fccb3310f9ec7456447dadaf8e0a5fb269be169b0c3ea2cfdaaa55d37937fe75b78324ac278a65047e0ae4f327e97effcb7bed91d09da720b0a101be9e96d0ba85b1ff49d8d1df362d3454f0db6825596101c97e5dacad07ec492d30f2d0cb7e7de4e744bb6a6100b754da847411d09aace8d5d410758b83087db4b5e6297979a21fb65af390952c4f936260e72d7c78327b94aa6cd617278b0ce9e1bd3fbed93b69bc64985dde0e2c4357b502f055ee7b0a0388474dae02d6c1a731f87785d753aeb0d9cfdf85002df566fc2507de7ba6fd035bee17a2e808b4a7588c583375c82407a40ae9eebdf94df2fb8cabf17606c439ea70459b212aae4a3f530ecadc5e88e2548fa643c7ddf5063b2e10673e59d07fe906892b67eb58f9388a56b370452e9977755fc04dfbc77da6c05beddebf0365256b52c9aef8a82173b8c89fbd98cea36a8b896fe66d37ca79bec7fbfe958fe89f6765085b335dc770343e230caddfa2833daa662fe8208dd885a6fdf72e36ecf22bbbbcbe79d370650236940bc2e6d4ac74fe4d554c9bc232f07d2af6220d157bd2da6a6612a081b4c9904a2869b137ee3a0856f12b2eb8762db94ed0ba136f23e7fb4bd1fcdee10dd84e2cd3b0a49148ac74db466dbeef81e6a8ce0861102de9b1a3e1dcf5c6b0308a82e3ac7c2283c7cc2f34ffa145b9f74b79904b32b79e960b814aade63a0df0167dcd24ed90a8da7b934c772932f5a478fe2a72f945a13096ec37ce764b581eb89e5f6b2bd7eb88b85a89587774d458c58cd879457973d648ef771c5f1deb27a0cc5b29246ac2fa12d18ddc6b9f9ac9cf146c3f22b1e4499adeefbcd2249740e13a224e7b6b3ef15605e7e74e68d7b72642409b90c4ec161eb24c9b40ff9c7e6e5da98322aca52c46a8ddc190f1cab157c4c7619601a6b33df6a50da661bc75360dff69750d3457409cc0241c3e8c4b3e506d426af52b70231cd6c91260cc431e4ccfd496ca14ceaae1cda78721e16339d52682b6951f966c7da5c6e10d919ae66a9f52dec10867538d3df6d593a32db695a8d7745703516ea56f8c1c8f0ef53bdeb7f53c2d944f511940ccb90624922ac599f4619c3046207d605f6ff94de788d25342229dc8af92b5fdf0dd71df2b446cdf1d9a20524339ee1c31826287ef72781a7a35289f85a15ba57c7fd5d885bd0553ab40805f517e8f1b1b3c4fc6771e6f224bc031124b9c9aeb19c5a96bf1488e1e66c6e88809230c83a74155554a219ec379ae54a9fe79dbede3d576042a635d197f4d818c778755b8b45e513deac88f60425: +95174a0915684cdbb619b055495b00f19282cffc3b05019e6ab709a4a1742babaa8c872d7e10b67f7ff24172c3637e80825a0a71ee0c48863a2acdcbe8da459a:aa8c872d7e10b67f7ff24172c3637e80825a0a71ee0c48863a2acdcbe8da459a:5e1a7400456cad4f9ba86643bc7cbf3b3568dcb522b37055e8c39d3c80f2284238e5727fd7513cc8b31c57ae7b4050aa819fc2360930eb0dd677a5b2c729feb2da3ad79ae7fccdddb6c08446261ec9bbe59c64e99abbc86d3c4835f00fefe527433a501a3b6d572cf5e12a88010b46a472b9bd8691a407c365f9f71634b4d97edfdff06314c0c1b4eb93c7607f1d6fa354659322c284073f42602518c54fdf26ea2c27c80a6dfa20568391ab357282c06b23bedc1df1264b611c1e9cf18aebe249fd8617c6e3ee98c53c0f6f2175c57ef8e206bd3cf105627a9892eb689920213aaeb63d87663dbfa53f0fb281626948296b2dbcdde1c51af862eecf1cfe8a46a2c4b28cfe7130330ad173f87127aacaff43c0bddea48b0038976e662c04b6b04ad03de12462c2765db535049520cc114afdb6c92549b0546a9027d449755beb8d4c17e6a2a475f9676a337b4e866d96325e389a52c16c51e18e0d8103340c8417b2c57a55d042ff5e5fc65df423e0092b0ea88b96a907c95121c547a68061f27bcfb58ce6c07728d4846bdcbf0c625410edf8dea8cb4c9d0bbeefcde19273365f48d75aec07d1c22ccd23068a97c3fe752e87a30118fe2dfd5218b6b125154e0ea386cf239e3137f8ca6d8b746b6a67d508cf8c1ab63e5715e6721eda5c2bc393a493dbd2f9a1fa926b9a59e45a180aeeb02599a8cdd686f889b4852723cb6dbfb5014cab5f658a309a472239360eeaf64fc8203a3c708970e15cbcf136255d96446c39a927031d267d69ecd51d7af6e91fb4aef9d78c3335e9071133cfb8e2129990c64637c7adf1daef2dc26c1163399f3fe1e792338092ef6f8dfaf25730dd2fe8d978f6f770f52b68238176564cee5fbb9850b3b3a04d948460417826eb2eb24fcc5fe35334bb9521e87bc4dbde2ac9e1c98949dc2d29ad279e3884b905268ebd0808bf418257e75e262b4d01b024a6e9aa7bd501dba94ff506394b4b0ae6081ea73030c43a6a91766e80f9f42c0b68b98419ad4eee4e9a728adefbd79e831f70f41e62b43f0bf42b3b2cd53b5589117664bcebc409a7645b1eedda482f6b6895a657ba789b89e502d6998751d6303ded5fa156ee7c7eafe54626d1032c4d7dff977f1dcc86af89b1e646a4afc2427ed02c0af5d32890f95f13f98c1a5b1d9fbb781a9a89b2d790c1465c2d1520926fdf28c17d9ba1587ad761f065d339bdbe38f4133f45bb5978742642f90c065ee4892573f6059f8b4ce2c13e73b891cd05f23731ed9a07e2b8ffdc963b06a510209c329980949f40d8073a013ef843dfcc4a3394:780f40c20fea3b11c9422a43b9a6f79611e7f1f59d1488c15a5fd2d32c07dadc391c38953edf0de48be52da2af335c47b8d2e44ab9d3dfb76ba538b0664952085e1a7400456cad4f9ba86643bc7cbf3b3568dcb522b37055e8c39d3c80f2284238e5727fd7513cc8b31c57ae7b4050aa819fc2360930eb0dd677a5b2c729feb2da3ad79ae7fccdddb6c08446261ec9bbe59c64e99abbc86d3c4835f00fefe527433a501a3b6d572cf5e12a88010b46a472b9bd8691a407c365f9f71634b4d97edfdff06314c0c1b4eb93c7607f1d6fa354659322c284073f42602518c54fdf26ea2c27c80a6dfa20568391ab357282c06b23bedc1df1264b611c1e9cf18aebe249fd8617c6e3ee98c53c0f6f2175c57ef8e206bd3cf105627a9892eb689920213aaeb63d87663dbfa53f0fb281626948296b2dbcdde1c51af862eecf1cfe8a46a2c4b28cfe7130330ad173f87127aacaff43c0bddea48b0038976e662c04b6b04ad03de12462c2765db535049520cc114afdb6c92549b0546a9027d449755beb8d4c17e6a2a475f9676a337b4e866d96325e389a52c16c51e18e0d8103340c8417b2c57a55d042ff5e5fc65df423e0092b0ea88b96a907c95121c547a68061f27bcfb58ce6c07728d4846bdcbf0c625410edf8dea8cb4c9d0bbeefcde19273365f48d75aec07d1c22ccd23068a97c3fe752e87a30118fe2dfd5218b6b125154e0ea386cf239e3137f8ca6d8b746b6a67d508cf8c1ab63e5715e6721eda5c2bc393a493dbd2f9a1fa926b9a59e45a180aeeb02599a8cdd686f889b4852723cb6dbfb5014cab5f658a309a472239360eeaf64fc8203a3c708970e15cbcf136255d96446c39a927031d267d69ecd51d7af6e91fb4aef9d78c3335e9071133cfb8e2129990c64637c7adf1daef2dc26c1163399f3fe1e792338092ef6f8dfaf25730dd2fe8d978f6f770f52b68238176564cee5fbb9850b3b3a04d948460417826eb2eb24fcc5fe35334bb9521e87bc4dbde2ac9e1c98949dc2d29ad279e3884b905268ebd0808bf418257e75e262b4d01b024a6e9aa7bd501dba94ff506394b4b0ae6081ea73030c43a6a91766e80f9f42c0b68b98419ad4eee4e9a728adefbd79e831f70f41e62b43f0bf42b3b2cd53b5589117664bcebc409a7645b1eedda482f6b6895a657ba789b89e502d6998751d6303ded5fa156ee7c7eafe54626d1032c4d7dff977f1dcc86af89b1e646a4afc2427ed02c0af5d32890f95f13f98c1a5b1d9fbb781a9a89b2d790c1465c2d1520926fdf28c17d9ba1587ad761f065d339bdbe38f4133f45bb5978742642f90c065ee4892573f6059f8b4ce2c13e73b891cd05f23731ed9a07e2b8ffdc963b06a510209c329980949f40d8073a013ef843dfcc4a3394: +5a84af28a5dfbb3233a12f0837f6e8654e7b0de16b02ab3cd17864431e27466780d4ba789f8a4b2047adafa5ed26cd8c546733292e8bf693cfd17e284efc6871:80d4ba789f8a4b2047adafa5ed26cd8c546733292e8bf693cfd17e284efc6871:8aacd1b8a39bf08fd5c918446be576e6a3f27f36111607f27b56a91214e763f9a87fb1d1844898961797644460bff5488c103af605e8740e46588fb93e443c3bb23b92c09870a557653a1f22c218ccbc2f073a272d17a84223ef143f4c7ca258460b798169673da107d71d5356ce9f7559a9b038399951f575c77e5b9d0529578ecaa2e2089266fc526c5d409fbd46bb86841cb554f5bd3c99713b043e404653a7d01344d4db831a217282c4b336405653b85d27a46b259c855cdd85ad6f7aedd835ff5500cc8baf0fb2f0180910c64672b8a8d49d984a78293cf5779c910c3acbbca455a85466e535044f3480262c090fbf4e0b0db4d1ef8759daafdd8d05907482461ff910c437195d5c7fed9d82cb94e7e4ec24da053e47f62b488eb7b244655c7dbb20ed607eed4531449e0780e61cfd574086ffc5dc524283775c44f7547cdab04a51eee4e1b7b65a57573a92484a35900a909f81e415029d22ca937a3acd9e61f8c0e686b2d2ad0377af8ee166e4a20a82aff451e151103e0a1767b271fa9c2b1dd120f805853b3b8a560fc8b9376283b51124324a284a0e9ac49df69f524c8e042df82efbcd16881ec131a15210df73de02943447f22a2ea1dc8bf968298ee97f3ad546d78bc660897e08d2a28b2ba68b54b954f1476451c69207e5dd248ae47ef35694990e6f058bc0017b7495105cc8739066afb11e1f26601942546ae849ff2f56730f1326bbeea640ee178fa247adffefc046494fc7ffc0777d5dbe8a55daee61406fe3c7088d43d9e14da21ca52fd8c160091c8f99a67dad65c64fea9d18b1537d061f5dce879e0bc42648d2eaa02d972185753cb2f6225d8d03bb07f944b10cf4ea22275c3d70848020f30c823b76143acf545999a2cc4b5898d94b4a25efbe5a60331cc009fec0a25bc98947b1b7139e22d23280ff8854a1ec76221b1bf3d108328c8ac463c65263a2d7ca7433482931a1d8fc144bbe9bef678c92e1c2d10921b6ad43a75c53bc075854ed2d99d825f30a5e10d517438e4d4f7113429f1edb387d6bd7aad29274f8d2dc889b7efbeb58686f8d669ceaef92c75ed5307f0c03f5900181ce573c8fa28675205fb1057f626aa230d03e2eaa8cffcde20081475d80b245a1ca6045ba204ab00069079c637fc3fb3e80ca0462e7a4cdd9283ff9008530364816792fdf3b9a4e4dc8379228edcbb154bef387d37760d79afbb736260a1db10138361f24b826dbcd5f0fc9e7830d26d80c52a792189276bce34760fb77be1312ac8cf97d92cbf3d0778028db5e8eae89e0b9bc8778aeb1278f0471cb:a0b84ca5af7646e6f62a6935379473fa6e4c27695851fcbdae2917b2dc68d796e278d70cd67fcedf6ca629b881f7c4f2aa2559b20d670611766bd65aa4fef2048aacd1b8a39bf08fd5c918446be576e6a3f27f36111607f27b56a91214e763f9a87fb1d1844898961797644460bff5488c103af605e8740e46588fb93e443c3bb23b92c09870a557653a1f22c218ccbc2f073a272d17a84223ef143f4c7ca258460b798169673da107d71d5356ce9f7559a9b038399951f575c77e5b9d0529578ecaa2e2089266fc526c5d409fbd46bb86841cb554f5bd3c99713b043e404653a7d01344d4db831a217282c4b336405653b85d27a46b259c855cdd85ad6f7aedd835ff5500cc8baf0fb2f0180910c64672b8a8d49d984a78293cf5779c910c3acbbca455a85466e535044f3480262c090fbf4e0b0db4d1ef8759daafdd8d05907482461ff910c437195d5c7fed9d82cb94e7e4ec24da053e47f62b488eb7b244655c7dbb20ed607eed4531449e0780e61cfd574086ffc5dc524283775c44f7547cdab04a51eee4e1b7b65a57573a92484a35900a909f81e415029d22ca937a3acd9e61f8c0e686b2d2ad0377af8ee166e4a20a82aff451e151103e0a1767b271fa9c2b1dd120f805853b3b8a560fc8b9376283b51124324a284a0e9ac49df69f524c8e042df82efbcd16881ec131a15210df73de02943447f22a2ea1dc8bf968298ee97f3ad546d78bc660897e08d2a28b2ba68b54b954f1476451c69207e5dd248ae47ef35694990e6f058bc0017b7495105cc8739066afb11e1f26601942546ae849ff2f56730f1326bbeea640ee178fa247adffefc046494fc7ffc0777d5dbe8a55daee61406fe3c7088d43d9e14da21ca52fd8c160091c8f99a67dad65c64fea9d18b1537d061f5dce879e0bc42648d2eaa02d972185753cb2f6225d8d03bb07f944b10cf4ea22275c3d70848020f30c823b76143acf545999a2cc4b5898d94b4a25efbe5a60331cc009fec0a25bc98947b1b7139e22d23280ff8854a1ec76221b1bf3d108328c8ac463c65263a2d7ca7433482931a1d8fc144bbe9bef678c92e1c2d10921b6ad43a75c53bc075854ed2d99d825f30a5e10d517438e4d4f7113429f1edb387d6bd7aad29274f8d2dc889b7efbeb58686f8d669ceaef92c75ed5307f0c03f5900181ce573c8fa28675205fb1057f626aa230d03e2eaa8cffcde20081475d80b245a1ca6045ba204ab00069079c637fc3fb3e80ca0462e7a4cdd9283ff9008530364816792fdf3b9a4e4dc8379228edcbb154bef387d37760d79afbb736260a1db10138361f24b826dbcd5f0fc9e7830d26d80c52a792189276bce34760fb77be1312ac8cf97d92cbf3d0778028db5e8eae89e0b9bc8778aeb1278f0471cb: +793ac88d7d3b6fa7f47deec31f68ddccb701820f1b13ddc652f7c6a85b6052a591b6227acdd183da62c51965c635358b204d683ee06443cbd40e71c1f76ad102:91b6227acdd183da62c51965c635358b204d683ee06443cbd40e71c1f76ad102:ec50afad8ade7405e2c6f5c6247bbbccfb2c17166f7884feae10d90f5d83c4b6f0bf76de2f7897ba1194d6d3449ddb80ae74eb8ed68f049b35c6f21916db4dfc2724dc3af7ad8dd5c44f60d2f49fadd7004da1593093942cae5208bf54cf903bee646905fce2eb2e370d0dca48d820adeab16a3b675e5a4a8e267e34ff96f3122b18de0cad9292ab63d26e5f310fa2168c2966bdb63b0de08626767b379de4633b9f3eda7917281dad661e9f772b844a79e800fd842702446e4aa731757107f3fd6547bf4075963d5fd5f58e80853fc42751dca078a9fa8d5bb3d9a34abcab0293d6ceaec48967a1e6224398cad0f605a3be8e6758ea8f29209d8e4c4ca1893baad91e379ba3b17330c12a5b6f219b384a8ab978bf1b37c3731a1b474b24b5d67d4cec28aac6510b11f2cf21bc16963d51f5538727718fc4e2e5172e3c0cdabc277f0d7037c34ca68f73288848b926bde0cf47abfa66600916946f07651c280a2086b14d52570cc8a4b74358b59c302b9d00e1b498f3bc33ee4ecf2bce2c65ed7e8ba74d35b751d3c99f40861968c2b7f3a5be348c57d93b40ffd051edd7caca6ee6bca721dcba8db8d0064f54d36ec5e8d62a71fd1c90f14924f41c163f007afc6fbbfe8645fa47c3c980246d1b92274385953c5341cd64c34ae9717cc2c37f58359c0a9991c23fe637de6cdf0862f7d0329fe758aa892ad4583b9df2f3337d5be570ba654998ed292f11f01772382a04342fdd99e69e0d97c43f10ac9b96f140a6f83c4729e7a900471f2b1df2401bc5c680422b13b0c8007d63681f66a0595a1c5d3acde5b779426e736bc100c5e6f52608dc391e3ef9b1bb6af13d249b7d32ce0680c368f54d5fe039cfe10130251e4db14c79c8d044060465822990d88093cd736532852e447889db89cc60052996a32a64365c0726051c119eda901de576b334fc7049482392e2620b0a3a13fab1d36fc0a5f23db147fd857b26a698048f8b811e23d722e2e9027ed4124b48dc5e578a7aeb19a1b4f948ee5b46f65b979646e2be074714118baa4bfc15b089a0e06627da46e4bb06aa3c7c5dd648e03c9c2dec3facd95626562f3000883230d2b0a1f8a7478cb77f939a5f188f458d1037b90176664d86ea850b8af5087f86605a77e025ef6c7e6a2a59f006cba189fad933f42c532708109bc1af814819595ffcb95fbf5b7e93a71197e477ee7c04b851c1c36622cdd8e6c860d9ab2cac56d2dc98fa69124f2bb2a6471e1c73b661f071f5d86de7d1deafa4edcdc7bf1f705c56300affd058b9697791419e5fb2a5b7f78ce3401ff550:a84f552bf44322a6db245ca006d1cf780c61680fe7429a8947c35f21bc4b44228ba30aea0c744b866459d3b8acad453b06ace247ba69528c6b3bc4b20e75630eec50afad8ade7405e2c6f5c6247bbbccfb2c17166f7884feae10d90f5d83c4b6f0bf76de2f7897ba1194d6d3449ddb80ae74eb8ed68f049b35c6f21916db4dfc2724dc3af7ad8dd5c44f60d2f49fadd7004da1593093942cae5208bf54cf903bee646905fce2eb2e370d0dca48d820adeab16a3b675e5a4a8e267e34ff96f3122b18de0cad9292ab63d26e5f310fa2168c2966bdb63b0de08626767b379de4633b9f3eda7917281dad661e9f772b844a79e800fd842702446e4aa731757107f3fd6547bf4075963d5fd5f58e80853fc42751dca078a9fa8d5bb3d9a34abcab0293d6ceaec48967a1e6224398cad0f605a3be8e6758ea8f29209d8e4c4ca1893baad91e379ba3b17330c12a5b6f219b384a8ab978bf1b37c3731a1b474b24b5d67d4cec28aac6510b11f2cf21bc16963d51f5538727718fc4e2e5172e3c0cdabc277f0d7037c34ca68f73288848b926bde0cf47abfa66600916946f07651c280a2086b14d52570cc8a4b74358b59c302b9d00e1b498f3bc33ee4ecf2bce2c65ed7e8ba74d35b751d3c99f40861968c2b7f3a5be348c57d93b40ffd051edd7caca6ee6bca721dcba8db8d0064f54d36ec5e8d62a71fd1c90f14924f41c163f007afc6fbbfe8645fa47c3c980246d1b92274385953c5341cd64c34ae9717cc2c37f58359c0a9991c23fe637de6cdf0862f7d0329fe758aa892ad4583b9df2f3337d5be570ba654998ed292f11f01772382a04342fdd99e69e0d97c43f10ac9b96f140a6f83c4729e7a900471f2b1df2401bc5c680422b13b0c8007d63681f66a0595a1c5d3acde5b779426e736bc100c5e6f52608dc391e3ef9b1bb6af13d249b7d32ce0680c368f54d5fe039cfe10130251e4db14c79c8d044060465822990d88093cd736532852e447889db89cc60052996a32a64365c0726051c119eda901de576b334fc7049482392e2620b0a3a13fab1d36fc0a5f23db147fd857b26a698048f8b811e23d722e2e9027ed4124b48dc5e578a7aeb19a1b4f948ee5b46f65b979646e2be074714118baa4bfc15b089a0e06627da46e4bb06aa3c7c5dd648e03c9c2dec3facd95626562f3000883230d2b0a1f8a7478cb77f939a5f188f458d1037b90176664d86ea850b8af5087f86605a77e025ef6c7e6a2a59f006cba189fad933f42c532708109bc1af814819595ffcb95fbf5b7e93a71197e477ee7c04b851c1c36622cdd8e6c860d9ab2cac56d2dc98fa69124f2bb2a6471e1c73b661f071f5d86de7d1deafa4edcdc7bf1f705c56300affd058b9697791419e5fb2a5b7f78ce3401ff550: +89de7442d74ba9385969c9651a88fe28e040d593907dac1a3987418bdfdbad89fd3ba9fad320eba45d07b84a497be17d3fc7dd9999c968883cd6ac13b0669b17:fd3ba9fad320eba45d07b84a497be17d3fc7dd9999c968883cd6ac13b0669b17:9d5272f0b784882b94c76dfb9d460ca495025e0aec5d52ccfffece9f8173c10558266c498525891a97bf3878e33c3de2fc2e52550b431562cbe4a3d011ecc9e77ec36ad38341358c88321c03d08bb426a7d5854171c027ec48d57819a91afd02a618ccbc25e68e5309d047b156e35705373ada2eb831321a203e1bd8f0efecc09618647b41dff22b39d02235f871532f6085e9cc52ec009b33eebcdc267d7767c90c927e154f72f3f48a34956319b293c8a8b3e34efc5f62f2b4e8019b50a08f5ccf95bc831baf40811d87e5edbd2fd5365b26a431ae95800ff381cd62ca40e1866d950dce14f030918abac68e7916ddb95adc1971287874d07eb0edef64296652c48044b0c5521a8d270d53d74ec63b890f3363f9207f6652ae8e7835c3820ad6d9e3633f4bfd5379a44f29d65f3609fe355817dca5518dfe3bd769320a031902e9cf6669c24f88b01eb36995bdb8dbed6ee0c9b7f32295c61ba8905e5598f3c9e1c8bf7264f98293faea17747f88440c31818c433ea3d23c01f4f7e9c3dd3d5f32ec9eacd71a09e3a997381f1cbffdf4b5ba4979deb7b09841afa3b03d1c9311097b862cae11707cbd3a4ae6c8a26a306a687c414a4ea1e812f115f60f70bda7f8fbe7bc2d50cc550bba291d5ec523229a08ed568b5cee18fe6f46782c17cd828801639215bc5e9be4555c9a18009767a6c5c74a8229d2ffaa399d8e64324e884223d5070f735a75d85ff6c94a9fbc2b3651386de5a23cce95c87881c79399ae71f090737e2187fe904aab1d92d6186795c9b46c62a5914f3630fdcbac3bd4b0da4ec3136a1fb2ba40322d7cc4085e167009cf7450fc6a286c2f7951d51aae23b8f33020efb5e3245ba6a3543a2bdec447d51ae00b5e1678b76093cf216b9507c963ebfc024ccd6ef6c78c4572273beaaf55076dc44a224b58615705791965307cefd48672c081bccfbc1d15b062b38b4fba9b9bec956cd14444ee437e7960cc601eddc02f1a76b68574d5f8843150c0b9009934a2bfaf605770c136ba29f3dc7e29597a2480db23e2b2677ec6c51bd301f2b5a39dfda7b477bedd1cdaed10e29d2954629b9876f8ee54e4047369d534cab54aea441dc947eb3f59382b218360572f2659583153c0e2b912cf30c815b26f05853dd30551eecf64b858a441bb8c6db8a9fde77a32a7b46af66f8cb9f35ee0fafb0bd42d9e65b2a9058241a31b8ca1115434237670aab4eff36010ed0371f46595da1bdd579bbb67aadb68e77ad3a38c8f26d2af5a7103ba5f22b42cc12a8c3ce5c921c91cfc0e63df9027d26229b1047cbc18f6b0:bab57284d20ee54cc7f9708d717706d8faf6e46332b0691d6f213a8db801155b4e338c1361b592be758501b1821793ae5227cc3ba8df8adfc6ed9acab54cc4019d5272f0b784882b94c76dfb9d460ca495025e0aec5d52ccfffece9f8173c10558266c498525891a97bf3878e33c3de2fc2e52550b431562cbe4a3d011ecc9e77ec36ad38341358c88321c03d08bb426a7d5854171c027ec48d57819a91afd02a618ccbc25e68e5309d047b156e35705373ada2eb831321a203e1bd8f0efecc09618647b41dff22b39d02235f871532f6085e9cc52ec009b33eebcdc267d7767c90c927e154f72f3f48a34956319b293c8a8b3e34efc5f62f2b4e8019b50a08f5ccf95bc831baf40811d87e5edbd2fd5365b26a431ae95800ff381cd62ca40e1866d950dce14f030918abac68e7916ddb95adc1971287874d07eb0edef64296652c48044b0c5521a8d270d53d74ec63b890f3363f9207f6652ae8e7835c3820ad6d9e3633f4bfd5379a44f29d65f3609fe355817dca5518dfe3bd769320a031902e9cf6669c24f88b01eb36995bdb8dbed6ee0c9b7f32295c61ba8905e5598f3c9e1c8bf7264f98293faea17747f88440c31818c433ea3d23c01f4f7e9c3dd3d5f32ec9eacd71a09e3a997381f1cbffdf4b5ba4979deb7b09841afa3b03d1c9311097b862cae11707cbd3a4ae6c8a26a306a687c414a4ea1e812f115f60f70bda7f8fbe7bc2d50cc550bba291d5ec523229a08ed568b5cee18fe6f46782c17cd828801639215bc5e9be4555c9a18009767a6c5c74a8229d2ffaa399d8e64324e884223d5070f735a75d85ff6c94a9fbc2b3651386de5a23cce95c87881c79399ae71f090737e2187fe904aab1d92d6186795c9b46c62a5914f3630fdcbac3bd4b0da4ec3136a1fb2ba40322d7cc4085e167009cf7450fc6a286c2f7951d51aae23b8f33020efb5e3245ba6a3543a2bdec447d51ae00b5e1678b76093cf216b9507c963ebfc024ccd6ef6c78c4572273beaaf55076dc44a224b58615705791965307cefd48672c081bccfbc1d15b062b38b4fba9b9bec956cd14444ee437e7960cc601eddc02f1a76b68574d5f8843150c0b9009934a2bfaf605770c136ba29f3dc7e29597a2480db23e2b2677ec6c51bd301f2b5a39dfda7b477bedd1cdaed10e29d2954629b9876f8ee54e4047369d534cab54aea441dc947eb3f59382b218360572f2659583153c0e2b912cf30c815b26f05853dd30551eecf64b858a441bb8c6db8a9fde77a32a7b46af66f8cb9f35ee0fafb0bd42d9e65b2a9058241a31b8ca1115434237670aab4eff36010ed0371f46595da1bdd579bbb67aadb68e77ad3a38c8f26d2af5a7103ba5f22b42cc12a8c3ce5c921c91cfc0e63df9027d26229b1047cbc18f6b0: +2622bd9bbef7ff4a87629ea0153dc4d608c31fa5847988ff500d880681f11372199758a9c3d0ee3eebcbbda3e1ef5455ff46d736bb4ef0c06a739f9ac5848395:199758a9c3d0ee3eebcbbda3e1ef5455ff46d736bb4ef0c06a739f9ac5848395:891e82122547d61e83b0abaf27c7303f0522a2ec4af44ef0ac196a9978b1c623ef1fa72baf70910a5c51c4f78e0fe9fe37e2439c4795916cfa22ab471a2557cc7ba6b66956063ddeb39c50f14f06348fa66b6064dcffca5043967f05254d577abf22ae8c90000ce2e6a1a8b2e3a6b3abc563ebffb20445f0911cc42a987f8456efba4130e68f01fcdf7bf771fc1d35371a0d75dd5f90002c90b6cbade40d5b23fdb49abacb7219ae27561aa2a879da88df34a8c581f0c67198ffc608fe9195b5555c8ae934c830aae2885bea87487448e11b4f2f172e4d5cfe4fd113f9d2016c24a734512bb918f575e754139718e3d20e790abb942cba3ec8b2db590796dc435f139fc64ddc85a22494ef2bfa1f5c0f1875ea58e84eb374ecf8cec6468b6b09d1e74f1541ed454a2807d3f4053566b0e4e2c6aeced10dc007e9df416f267fcb3fe17b8bace03f0743e0e6d4a48ce76edff60c0e3a308456995413c1076ff37ecf2381a0d4e9e4a913a258d983b9696b5c45af37c8684070e400b8f865a504043f45d78b9713f335aa416a46166410735fb5d82210458d5a08a104d4002ab61188f9df457dd7ed5937ca5077606b418bbc8684a1d525bfa551087640b1d177ca6d4f6471b39b2ce43afbf8285ecd687e438f4425df568ab86fa2316349a1102b4143d71ef4e24f5c530c77afb0100788636440e740675a6174c5f05710b253a411173f9e82ce6e22f4095e7714b8737e147aa0f23191578ffd93823ce4bf91c1d110982a5da0e4b81bd25b9b9c2142a7671ee937c90fd0715ec9afa44d86046898b42f753589d2268d2aaaa985cc90e0f9e827a3923e7716346f4f8931c72821b3eb645daa7452c8afc898d7975545c12da1bdb209045cb00f4bfd5383df01f003680b973440f1a39c9d820959ef6f85bd33639065aefdc8bcfecbd9b9554049738af29f1294639d3915d632995e8faf713ef2ee3c298b5596fa10c99f946ddb32340695df1c194594eaf3778d73c8ba6040c04eb3a4ff8677936b88e0c5f0441480d107d7ac2202b3b694e57ccca6d825e2a07e812ed29b2c20d5c605471579e3edffc223f242c59391db41e98d5f3d6c5b1e32ac8237fcfd1020543a4041e03d92ad3e2ec552914707c77cd01f3e48011444283f0968fa4deeee55c456ed1f877ade04ac8e8d2cb6c85820b4929b25bf31e925435d6bcc50d3e2e9b85102e970d7895c25ade52161a3b6bf501ab01961cb63ed990aeb93eda3828bf04ca52853c7b6b8e9e49e349d69b53be07485f542b7cdd06b527d41dd119c70b564f1a93aec62ae74e6e8f855:4378966b7831def4aecb4989bcaf9cae99461cb9b59d19518cc1ec7b8351bcd1f723aac5f061b38363574ff96ba10e196b1b0531e1183036a425e69c4598040c891e82122547d61e83b0abaf27c7303f0522a2ec4af44ef0ac196a9978b1c623ef1fa72baf70910a5c51c4f78e0fe9fe37e2439c4795916cfa22ab471a2557cc7ba6b66956063ddeb39c50f14f06348fa66b6064dcffca5043967f05254d577abf22ae8c90000ce2e6a1a8b2e3a6b3abc563ebffb20445f0911cc42a987f8456efba4130e68f01fcdf7bf771fc1d35371a0d75dd5f90002c90b6cbade40d5b23fdb49abacb7219ae27561aa2a879da88df34a8c581f0c67198ffc608fe9195b5555c8ae934c830aae2885bea87487448e11b4f2f172e4d5cfe4fd113f9d2016c24a734512bb918f575e754139718e3d20e790abb942cba3ec8b2db590796dc435f139fc64ddc85a22494ef2bfa1f5c0f1875ea58e84eb374ecf8cec6468b6b09d1e74f1541ed454a2807d3f4053566b0e4e2c6aeced10dc007e9df416f267fcb3fe17b8bace03f0743e0e6d4a48ce76edff60c0e3a308456995413c1076ff37ecf2381a0d4e9e4a913a258d983b9696b5c45af37c8684070e400b8f865a504043f45d78b9713f335aa416a46166410735fb5d82210458d5a08a104d4002ab61188f9df457dd7ed5937ca5077606b418bbc8684a1d525bfa551087640b1d177ca6d4f6471b39b2ce43afbf8285ecd687e438f4425df568ab86fa2316349a1102b4143d71ef4e24f5c530c77afb0100788636440e740675a6174c5f05710b253a411173f9e82ce6e22f4095e7714b8737e147aa0f23191578ffd93823ce4bf91c1d110982a5da0e4b81bd25b9b9c2142a7671ee937c90fd0715ec9afa44d86046898b42f753589d2268d2aaaa985cc90e0f9e827a3923e7716346f4f8931c72821b3eb645daa7452c8afc898d7975545c12da1bdb209045cb00f4bfd5383df01f003680b973440f1a39c9d820959ef6f85bd33639065aefdc8bcfecbd9b9554049738af29f1294639d3915d632995e8faf713ef2ee3c298b5596fa10c99f946ddb32340695df1c194594eaf3778d73c8ba6040c04eb3a4ff8677936b88e0c5f0441480d107d7ac2202b3b694e57ccca6d825e2a07e812ed29b2c20d5c605471579e3edffc223f242c59391db41e98d5f3d6c5b1e32ac8237fcfd1020543a4041e03d92ad3e2ec552914707c77cd01f3e48011444283f0968fa4deeee55c456ed1f877ade04ac8e8d2cb6c85820b4929b25bf31e925435d6bcc50d3e2e9b85102e970d7895c25ade52161a3b6bf501ab01961cb63ed990aeb93eda3828bf04ca52853c7b6b8e9e49e349d69b53be07485f542b7cdd06b527d41dd119c70b564f1a93aec62ae74e6e8f855: +aeb13ccb90c8cbef90d553da3f6901b3d75c13011f024974daf79a1789c8c6325faafeb595f16d338f1c72a9f3e498f38bab69a81b37d2d092b7bf7e505d820d:5faafeb595f16d338f1c72a9f3e498f38bab69a81b37d2d092b7bf7e505d820d:861a1018d6bdc4805a5c4df87efaa462c68b4bf4065c684c2af131c6377388baee58c6c8f8842362ec6e3bce07c8af55885e82db87a15227800dd33afc5e5fd15701e95f53501b1a6ff83c64e8517149bf3ff011b094a09c673d0fc4a39ee55e69f071177b8aa364e1e256064cf70279cc76695ae49dafcd80ca0a14e1691db946422ec75ab4f7865915a69bd48d89b12adf487d4db9be87cddca211aa88e9bbe849da213989eb0844592ad63e281b2e4afe6a8836006609926c0f787e84f2a95b46b66f0e4555c9483ce2176fc63f7cc9f4f2a22db055aae2e68b30a0da5feb80c2a60ea10dbf67fbbcdbe0be33f2e9c13c469e7768f2ff5960a55eb482ec11d47e154b7c42a5fb756c8ad539b33d125a4a65192c6c9bd576238ca72a73cd179e8cf5cd048ed330213823abbafc3682b2b7f68c5bc46fd09a8cb2a3fd099573ee2e6f28c82e271bb5ef934b0b0c381cfaaec666d717106a874af30aa74125eae9acc2f1f24118cb4e683a731e37e5e464a1ea3d2a53cc0dcad4c17cea9a43e2365f3ae3dd89eb39977420045550745fc267fc7dcc5602e914972a4da6ebeb687f68a0cd7d8b4fdd73722106a8e436b93e5b58f5982acecdecfdb382fe98538261426ba64052557643ce9fec71ea43cf5b6cbadeb4953193ff3ed1a1f922a9af2ec6f338e7fb0affe3d13c33e395873e4a7a7fb044981e05a67197b996b199b43011119363e561d5b8a51784fdff58ab80ed4c49e93f0cf41924f9835efb09f64463b65517b67b15dc3f28ad9a9b2d29468de2c63e62004b6a3fd0c5c2e2aaa6cfa15e4faafa1e2c713e98d3fd25cab9e5170359c8365152b474276ed0037cdf771828e2fb7ccec4895f21adcc5b6887c86e51ad05f255f6e9dad2c41f56b98b7bbbf9fcb6ba8cadfd38ad8c62f92dd87740fa1e1bd170c00b2049c5130fe733f16b1f2c7f00b2ef97b3a95458c53f199d465336d5ff5977806e1afde3eaa246d85cabf7e123481e23929976ed19c40e29ff33d80e7deab19271decd5ee06172b0b0a139bd62a2e7c83a8a65601d0a05d61af9c6032df58001d473e20dd6c6afd78ddbd7cd178e9c271e0572f85982823ce6c402930cf80f5e0c7cda85122a76d1ce021b1e3de2556d1b45ac7b01b59cada25291d638a52a5e7dbcddf96bb1774ab0b077e4b3da5a958fe11dee4a02e69b918ddbfa1c5b3b7dca9f8784bb6b0b9d5a7fee74bb03747f61c2b2f1b492452d3b560b48d39d8721e983752556d44da6b028d9aef8bff9aa379c8e2b0a636d748860abd8e64fc8e96520a34a27f767aa97a8f77b6095218ead:0611b19a7472a443e87e54d7c6647faab1b79a83fd4371c92b975400fd628acfc32577ccbbaf03d88f893c88f2cac784c722a08f387abc319a702c868479650b861a1018d6bdc4805a5c4df87efaa462c68b4bf4065c684c2af131c6377388baee58c6c8f8842362ec6e3bce07c8af55885e82db87a15227800dd33afc5e5fd15701e95f53501b1a6ff83c64e8517149bf3ff011b094a09c673d0fc4a39ee55e69f071177b8aa364e1e256064cf70279cc76695ae49dafcd80ca0a14e1691db946422ec75ab4f7865915a69bd48d89b12adf487d4db9be87cddca211aa88e9bbe849da213989eb0844592ad63e281b2e4afe6a8836006609926c0f787e84f2a95b46b66f0e4555c9483ce2176fc63f7cc9f4f2a22db055aae2e68b30a0da5feb80c2a60ea10dbf67fbbcdbe0be33f2e9c13c469e7768f2ff5960a55eb482ec11d47e154b7c42a5fb756c8ad539b33d125a4a65192c6c9bd576238ca72a73cd179e8cf5cd048ed330213823abbafc3682b2b7f68c5bc46fd09a8cb2a3fd099573ee2e6f28c82e271bb5ef934b0b0c381cfaaec666d717106a874af30aa74125eae9acc2f1f24118cb4e683a731e37e5e464a1ea3d2a53cc0dcad4c17cea9a43e2365f3ae3dd89eb39977420045550745fc267fc7dcc5602e914972a4da6ebeb687f68a0cd7d8b4fdd73722106a8e436b93e5b58f5982acecdecfdb382fe98538261426ba64052557643ce9fec71ea43cf5b6cbadeb4953193ff3ed1a1f922a9af2ec6f338e7fb0affe3d13c33e395873e4a7a7fb044981e05a67197b996b199b43011119363e561d5b8a51784fdff58ab80ed4c49e93f0cf41924f9835efb09f64463b65517b67b15dc3f28ad9a9b2d29468de2c63e62004b6a3fd0c5c2e2aaa6cfa15e4faafa1e2c713e98d3fd25cab9e5170359c8365152b474276ed0037cdf771828e2fb7ccec4895f21adcc5b6887c86e51ad05f255f6e9dad2c41f56b98b7bbbf9fcb6ba8cadfd38ad8c62f92dd87740fa1e1bd170c00b2049c5130fe733f16b1f2c7f00b2ef97b3a95458c53f199d465336d5ff5977806e1afde3eaa246d85cabf7e123481e23929976ed19c40e29ff33d80e7deab19271decd5ee06172b0b0a139bd62a2e7c83a8a65601d0a05d61af9c6032df58001d473e20dd6c6afd78ddbd7cd178e9c271e0572f85982823ce6c402930cf80f5e0c7cda85122a76d1ce021b1e3de2556d1b45ac7b01b59cada25291d638a52a5e7dbcddf96bb1774ab0b077e4b3da5a958fe11dee4a02e69b918ddbfa1c5b3b7dca9f8784bb6b0b9d5a7fee74bb03747f61c2b2f1b492452d3b560b48d39d8721e983752556d44da6b028d9aef8bff9aa379c8e2b0a636d748860abd8e64fc8e96520a34a27f767aa97a8f77b6095218ead: +73872b14762f68dae4fc10dfd6f42d3f9622bf2afe6b34a95649aa387424ee6cdfab2ce1ab9981aa7cbf3207350007fa6ce6ca60a2ed7b590f3c2f62922d8f61:dfab2ce1ab9981aa7cbf3207350007fa6ce6ca60a2ed7b590f3c2f62922d8f61:433d71781ceab2b47d826e67d39f9b80d2ffd725f8c5aeb40cbe4f9b5f48ef93521ccec604360b9647323190bfef75ac931562d27f4a4e31f46e57bc99fa5158c82e12b737e45c5de9f7dd7c8622d4a7eaadf7202fb49d819c9ad24f8807313c5f37dc20453bdf05c9bf1a3c2117c93e7f3cc8a2542098e8fc1c642fa47b05543657b85f480bc86ec42800bb1422359c7c3e8ff4be598bd54f1dc586acae45a4740622b962742bc86e17cfa63e775354e7707e5079589e8d108b1f11dace0575cb9a6d26b59fce981465d9bc344ea6945a95b862796384fa8170560857457beff95a9b5ac3d6ad282d44929a303026b4bbedd60e2ef055a31f52d7ce8df2ca5d1851c5b167db0809259bb812569074105c734c85d6231273755f3a8b56dc508db5c23dacb7a06167bda51bc01350f016cd41b21e8cc5bc93343a9bb6ea4738c5c84b78fa963c410e433dc598196c22e5b791e12a4b343f7cd47bbb0eb0782bdb1a4e466846a030528eeb89056f73257193adaabc1b229862034878c3258a532548762e29ecc001abd989649da5e144cf35d48699f23bc46c5b34e04a53e72724b2b0b878982575d688e23cbe3a34067f4971e555972ec2908ae5f03e8831ec67755be95687ce6372939e1e2fb6951ec9ecf4bf7d1535431e259f29ad431222b54b65aa7d07cfb5df162a87c4d03481eb441f221d7f58627a14164e7f4c2e3a1d507e899d5358e00829b08cf3aecb8a75b2a31c3185a580e12b13f0642869fffb056723e961aaf6fefe67b4a7c4c93db3fe1f61adcc765569a99c09a3c824ed4a98babeae43efb1f351ba130e22aa97811986be923cc4180a7c4b78bcc140cec15574654aa6d65a06b97ecfa5f3a9355f96e4eeaa7689217b663fba4dab0d99b19c8d8dbf47a157e5d5969a35ef84dff9562edd434e73aee7d0d892dda72a362a22a7e9fa8634a57eebd1a907485ca8921bdc19ee9ee588f395687d3fc8f8c25f2e9576ca60313fbb2c265a99f2cdd5575b1dd530604e9ad6695c9fb35994a8b87d5c8570549a4d329b9fe087069ab7eb0d714a94e19261f86e448f2da9b1cb0c0dbe41d44c3a824783d1bdbd7326051aeb10adab805c5c59d0e83b1c11a2fdd35e444a499ed15dafd83862775f6cdfc67595818407be55ecbf7bf86c73069aace577626a8563536f605042cf7caaf6fc8e3b545b77414df8d9f649b99ee42541da38c3aae627207845b8f414a8074d70868a5c0b07b070c3c653be04076b83cad7b0305d9500aa44455cb860dcc76400af93c3d2efb42ae056f1428b65f122e1c7b9584d814d50ac72efdb:8525c346ca3a6a6c5f65c41778599377659870cb6df9a4a0e55b40c35beba55c8e009e5600b6447dc7402ba27749297e8f9528691856f72d2ad761ed1bc15309433d71781ceab2b47d826e67d39f9b80d2ffd725f8c5aeb40cbe4f9b5f48ef93521ccec604360b9647323190bfef75ac931562d27f4a4e31f46e57bc99fa5158c82e12b737e45c5de9f7dd7c8622d4a7eaadf7202fb49d819c9ad24f8807313c5f37dc20453bdf05c9bf1a3c2117c93e7f3cc8a2542098e8fc1c642fa47b05543657b85f480bc86ec42800bb1422359c7c3e8ff4be598bd54f1dc586acae45a4740622b962742bc86e17cfa63e775354e7707e5079589e8d108b1f11dace0575cb9a6d26b59fce981465d9bc344ea6945a95b862796384fa8170560857457beff95a9b5ac3d6ad282d44929a303026b4bbedd60e2ef055a31f52d7ce8df2ca5d1851c5b167db0809259bb812569074105c734c85d6231273755f3a8b56dc508db5c23dacb7a06167bda51bc01350f016cd41b21e8cc5bc93343a9bb6ea4738c5c84b78fa963c410e433dc598196c22e5b791e12a4b343f7cd47bbb0eb0782bdb1a4e466846a030528eeb89056f73257193adaabc1b229862034878c3258a532548762e29ecc001abd989649da5e144cf35d48699f23bc46c5b34e04a53e72724b2b0b878982575d688e23cbe3a34067f4971e555972ec2908ae5f03e8831ec67755be95687ce6372939e1e2fb6951ec9ecf4bf7d1535431e259f29ad431222b54b65aa7d07cfb5df162a87c4d03481eb441f221d7f58627a14164e7f4c2e3a1d507e899d5358e00829b08cf3aecb8a75b2a31c3185a580e12b13f0642869fffb056723e961aaf6fefe67b4a7c4c93db3fe1f61adcc765569a99c09a3c824ed4a98babeae43efb1f351ba130e22aa97811986be923cc4180a7c4b78bcc140cec15574654aa6d65a06b97ecfa5f3a9355f96e4eeaa7689217b663fba4dab0d99b19c8d8dbf47a157e5d5969a35ef84dff9562edd434e73aee7d0d892dda72a362a22a7e9fa8634a57eebd1a907485ca8921bdc19ee9ee588f395687d3fc8f8c25f2e9576ca60313fbb2c265a99f2cdd5575b1dd530604e9ad6695c9fb35994a8b87d5c8570549a4d329b9fe087069ab7eb0d714a94e19261f86e448f2da9b1cb0c0dbe41d44c3a824783d1bdbd7326051aeb10adab805c5c59d0e83b1c11a2fdd35e444a499ed15dafd83862775f6cdfc67595818407be55ecbf7bf86c73069aace577626a8563536f605042cf7caaf6fc8e3b545b77414df8d9f649b99ee42541da38c3aae627207845b8f414a8074d70868a5c0b07b070c3c653be04076b83cad7b0305d9500aa44455cb860dcc76400af93c3d2efb42ae056f1428b65f122e1c7b9584d814d50ac72efdb: +67cf27155287be6bfab66215e017c3466322f21e6eb140be4f1bdecf55abfdc1d070aab295a8af935727c3be442b251db9e774d2f44b3c2424c52fc89656e169:d070aab295a8af935727c3be442b251db9e774d2f44b3c2424c52fc89656e169:0ff05297031c892774cb2c01e8ca60ddd0ceacc0b8d591a891e33b19e1be9e363bc6420d6f529f04840b3b08853c835a03e036978b04a4f9ec6be4aef331956190996dea272619f1686d33bef03dbc085a923a0f115b78f653feeb60bb9e45f34fb8be5a4cbb648c7d29956f0d0e96bdd3c8d0649720624cbc2079e84fd6d010241124098459f12af2991d3828770f50b104ea6e5f51fdad30a9b8079d2159e46d64af91d07c10ed19814df2afe660d7d8f2403534e92c62e1ea6d688203bca3d97c2afda83b255520ffe92a33625772513b1fe34fafe32b6a9b8cf994df7e634e686591e5f0073ababc64a89210ba53a4991c11557e0334e6c6a5036c642a318f2295117139085fb34075647006758e32bc00ad109fe803f7ee9f5ec2af4d25c3070abc51cf4d78e13a7ce283d4fb4eb41d3e8ce90238500ae0ceda320ec5922efa10b903748e1e853a3729d24c105439df2f7000123db9b2c01533bbf0d028ebb2fc00dce38ad06328ee9ecd849a6efc3ae884ef6933cfebed055bb2968a0b0676b5729216178c7519ef0788593fc0dcff50d7e0b1ebb3cf49bbd1bfa5c30ea7b88c36e1a1593aef0bb3f9e2091c8589f7414beed8df466a2ed87b2cb5f35f1d31246ceb968609253615d78043517379ee6974a669cb48da6ac2f96d700b7e44a435cfefec402a1e3110e76981924f2601c01dc03546fd4f511649302f0633dfbd25651c5a599c90954489c76a65ec05a7e4cc74616ce25601cc37b804e1f0bcc8651023b12e13568441e8b8ef4c305fcdad3d2b13fa080324b2fd6b61998cf864b658bc7fefcc48a5a7681d7c866c342c7f5d6cf10881522cc710257d25a4c1e352d270e902082ab9541d5900ceffa0914b16b55e0dd3786e98d41720875a148eb4abdb0153856679fb98c0ec485e5f458d635b7861a2b3a8ba5ec2c1444d353980200e5e071808854a268cc76c605c94f37329c36187a41fddf92aabdb4996a0e10b315526afeac80eb2fa32af786a34316b36111ee9352108144d70f7d1723b32f4dbaa82201353411d657713e55e35df78580b1bc08680f0159fa116faf463566aafe8aea69857e72e44ac809ac43f5c45939d85a1a5f4a370a18996c8514a46f34371ef9e5fb204422c934a1d293d101b8c16f99cc073ea366a13a45c437d620d132b74409cbf8b9c075b4163f726aa67e509a24874fc1b1fb6fb7c7355159c02aa13e64badf150356b1841b321f8041e13ed77e8461cfbb8e828488bf517a5d29ff82e7367480a8edddeb5350e7a83423bd0b1c55f7bb424ca04c205723cd5405671e733f391600a:c934a3a1aaab78d9269d1e9d13392f72c637bc5de54f04691efc29d473b475025d8d8fe3c523d2d29c41c5f3dec6ca38ce6d68d7ff09b6135ba24d0d32cc15020ff05297031c892774cb2c01e8ca60ddd0ceacc0b8d591a891e33b19e1be9e363bc6420d6f529f04840b3b08853c835a03e036978b04a4f9ec6be4aef331956190996dea272619f1686d33bef03dbc085a923a0f115b78f653feeb60bb9e45f34fb8be5a4cbb648c7d29956f0d0e96bdd3c8d0649720624cbc2079e84fd6d010241124098459f12af2991d3828770f50b104ea6e5f51fdad30a9b8079d2159e46d64af91d07c10ed19814df2afe660d7d8f2403534e92c62e1ea6d688203bca3d97c2afda83b255520ffe92a33625772513b1fe34fafe32b6a9b8cf994df7e634e686591e5f0073ababc64a89210ba53a4991c11557e0334e6c6a5036c642a318f2295117139085fb34075647006758e32bc00ad109fe803f7ee9f5ec2af4d25c3070abc51cf4d78e13a7ce283d4fb4eb41d3e8ce90238500ae0ceda320ec5922efa10b903748e1e853a3729d24c105439df2f7000123db9b2c01533bbf0d028ebb2fc00dce38ad06328ee9ecd849a6efc3ae884ef6933cfebed055bb2968a0b0676b5729216178c7519ef0788593fc0dcff50d7e0b1ebb3cf49bbd1bfa5c30ea7b88c36e1a1593aef0bb3f9e2091c8589f7414beed8df466a2ed87b2cb5f35f1d31246ceb968609253615d78043517379ee6974a669cb48da6ac2f96d700b7e44a435cfefec402a1e3110e76981924f2601c01dc03546fd4f511649302f0633dfbd25651c5a599c90954489c76a65ec05a7e4cc74616ce25601cc37b804e1f0bcc8651023b12e13568441e8b8ef4c305fcdad3d2b13fa080324b2fd6b61998cf864b658bc7fefcc48a5a7681d7c866c342c7f5d6cf10881522cc710257d25a4c1e352d270e902082ab9541d5900ceffa0914b16b55e0dd3786e98d41720875a148eb4abdb0153856679fb98c0ec485e5f458d635b7861a2b3a8ba5ec2c1444d353980200e5e071808854a268cc76c605c94f37329c36187a41fddf92aabdb4996a0e10b315526afeac80eb2fa32af786a34316b36111ee9352108144d70f7d1723b32f4dbaa82201353411d657713e55e35df78580b1bc08680f0159fa116faf463566aafe8aea69857e72e44ac809ac43f5c45939d85a1a5f4a370a18996c8514a46f34371ef9e5fb204422c934a1d293d101b8c16f99cc073ea366a13a45c437d620d132b74409cbf8b9c075b4163f726aa67e509a24874fc1b1fb6fb7c7355159c02aa13e64badf150356b1841b321f8041e13ed77e8461cfbb8e828488bf517a5d29ff82e7367480a8edddeb5350e7a83423bd0b1c55f7bb424ca04c205723cd5405671e733f391600a: +18c21c0d0de13d4c64497ef0260d66cfd34216981a1b49391ae5cb0e41436e9ff7d4dd1e059c36f6d121c0affeb21f0c572b45992f84948b09aafbcd86bb535c:f7d4dd1e059c36f6d121c0affeb21f0c572b45992f84948b09aafbcd86bb535c:68abca7c166afe063e477b80e37db224e1a235de8fcdeb7f427af67e001247cc5e057182fd9b6db8babaa658cf3b3fe4b0763bf88d67311b1190be834018cf57a332922413764620ace05445ee019a06dff98b238979ad6d30901befa3c64f6bd8c6eb092c2e62841388fd8c4e8419e2778984896737ed90a2cdb21996aef7c21638d6cbe680322d08996597a9e303f6f5f47940f8c5ba5f5f76383e7e18064a3d2dff5fdf95e90c5eb30f4d8d459ee1d506a8cd29cdc69b6754963b84d67494b35305d10d12b9487417b2ce28adcb10b65cc931fb3381ae02e7af79a02bf99e258a56361090e0b71222b3ac60bf2fb7ba832d034f5b6bc6fa663ae741f76d97c1ac32bcb7411507d518d2f6054b578328c5f67f758ac01bfe6f4d35900f50a5dcd30d2f9261b6bbec4c1d1fc18d2a7e70c4d36c21faf8cf94a587c3a0d1a9cde7831ae626775468ddcd40a8ba18f42b34188de5741e1be8307b1084586515ec015e4e371d29443a40b0c069c641d8cee5e4611862987c3e356b1293b0518b4a4c8ea97fc5a4db1f0129abee72fb8092ea35c2dab67573850207b8e82718999ad99c4c839eac14636bd5e4d8436a270dd90b8e321302e52a92d891ff1891542ae2caa0d66e0f661eae37b25b08bb2e0eeec4838009778cd525984380983b2baadd7102a1e356734e41d76183829ea9ab8244c336597ca2d67988f281438467e453f562c67b22d0a4dd9fcb46a5f80d299db5f01f59160a19d74c644fa5a940e32c9d8d983bab7efb0d7c7da4e3fda1cd0d18a4558eb9fe46408aab5085912bf2f46ab63a9354f9027c93691223ffaab8463bac4c4bc3b11abc46ba68717c91780d3f30470dbdd88b3780a194c8a40a2c0a81a4d56dec2d8962c34d2ab73369028e1bfeaa6bb58241ff4f898f80ad3bb1c691b8647f2c6983954c1c77957458eebf1c5055c31693abced05384735a4f741968bd6ac31565cfee71c884c1e29e9e7ae0f7ecd04d463b1dc389c36037e81458dcec61d0764032dd589b92afda2fc9028f41ab53cca2d04ec6a9565955cbcf1a3463989c7139bb902a5921e8b2c99c48e13711f0bcc399259516c81ae942a679d4ba33979eb12fcd2860602e4724b1330f1cd257b5b2891daee8ef4c92fc3bfdb34e532d5870f3805986ac97b503fd85873548e30950000f8a70be51fa757603501f2d30e852efeac4826862aed7f6d20c9a8c8dbe362dfee41893f27e6fd5e91d0e7e3d4fd8155f44fd8ef17af14a848d44a87631aeee751462b2a54087068daeab3ea3289ece6212b3b52ce7a8886df2a727b72a570c2fb9c50341:c9c099e21d095afadd4e71c9abf6b7083324776225b587b60a0e6092ecb3d33cff39c67d34776ae99dda754a3c2b3f781135a38c78ed6455aaf0ae0c313b620568abca7c166afe063e477b80e37db224e1a235de8fcdeb7f427af67e001247cc5e057182fd9b6db8babaa658cf3b3fe4b0763bf88d67311b1190be834018cf57a332922413764620ace05445ee019a06dff98b238979ad6d30901befa3c64f6bd8c6eb092c2e62841388fd8c4e8419e2778984896737ed90a2cdb21996aef7c21638d6cbe680322d08996597a9e303f6f5f47940f8c5ba5f5f76383e7e18064a3d2dff5fdf95e90c5eb30f4d8d459ee1d506a8cd29cdc69b6754963b84d67494b35305d10d12b9487417b2ce28adcb10b65cc931fb3381ae02e7af79a02bf99e258a56361090e0b71222b3ac60bf2fb7ba832d034f5b6bc6fa663ae741f76d97c1ac32bcb7411507d518d2f6054b578328c5f67f758ac01bfe6f4d35900f50a5dcd30d2f9261b6bbec4c1d1fc18d2a7e70c4d36c21faf8cf94a587c3a0d1a9cde7831ae626775468ddcd40a8ba18f42b34188de5741e1be8307b1084586515ec015e4e371d29443a40b0c069c641d8cee5e4611862987c3e356b1293b0518b4a4c8ea97fc5a4db1f0129abee72fb8092ea35c2dab67573850207b8e82718999ad99c4c839eac14636bd5e4d8436a270dd90b8e321302e52a92d891ff1891542ae2caa0d66e0f661eae37b25b08bb2e0eeec4838009778cd525984380983b2baadd7102a1e356734e41d76183829ea9ab8244c336597ca2d67988f281438467e453f562c67b22d0a4dd9fcb46a5f80d299db5f01f59160a19d74c644fa5a940e32c9d8d983bab7efb0d7c7da4e3fda1cd0d18a4558eb9fe46408aab5085912bf2f46ab63a9354f9027c93691223ffaab8463bac4c4bc3b11abc46ba68717c91780d3f30470dbdd88b3780a194c8a40a2c0a81a4d56dec2d8962c34d2ab73369028e1bfeaa6bb58241ff4f898f80ad3bb1c691b8647f2c6983954c1c77957458eebf1c5055c31693abced05384735a4f741968bd6ac31565cfee71c884c1e29e9e7ae0f7ecd04d463b1dc389c36037e81458dcec61d0764032dd589b92afda2fc9028f41ab53cca2d04ec6a9565955cbcf1a3463989c7139bb902a5921e8b2c99c48e13711f0bcc399259516c81ae942a679d4ba33979eb12fcd2860602e4724b1330f1cd257b5b2891daee8ef4c92fc3bfdb34e532d5870f3805986ac97b503fd85873548e30950000f8a70be51fa757603501f2d30e852efeac4826862aed7f6d20c9a8c8dbe362dfee41893f27e6fd5e91d0e7e3d4fd8155f44fd8ef17af14a848d44a87631aeee751462b2a54087068daeab3ea3289ece6212b3b52ce7a8886df2a727b72a570c2fb9c50341: +db9aaee198cd26a52b1181fa3fd92abe425e666d890bf969467dd2ce280ed4a73c897cafe2b499ecb2e1dd01ea55f3fc88f68c25b64a636b31a1fd1c78f37f3f:3c897cafe2b499ecb2e1dd01ea55f3fc88f68c25b64a636b31a1fd1c78f37f3f:47fb621561f8b7eecec6033f2bcb6f43ac68c958dfd2656f52a0c29b4acd44f4304c6bf77eeaa0c5f6d3b22db19699c3dcdede698abde623ec4b2b90910c80ac3af39c550b6dd409e63d77706655a9199cb5c0258f5ba38285ffdc64b8a8f373d1fb29ba87f84ddf5f34d8f140bbc17b3961682df5d0a8f9102e379a9998139dfe40ab8ce753bf5626108237771a7d8e109e9e0afe9b66d0420942e163a4f3c03f71813ee078bd090ac3d0772e2622c259e682552c75b08dd055a4a5eb5e609440bcd3f3a6feb876fd16921520c6cb6884710d2e15cdad6daaeed95962dda21c6788f784917917982e1ccbb5fdd9bdc1769db6b6db57ca354e01a1339d8e77e9dbbb5812fbab6a14c54085c0659599f150e22472470f1e5e672c425f375f9e0d6e8d52fa17b7a8d7a4d7ca3e12f4db53836aed2bebd74589baca8ce9100291bfb7e456db7f2f0a84dc0a7488851366a9a5fea0e3efc74b9cdd4bd97b65abf361393ce1703d8571805ee68a13d3654f03dcecfb77a53430d09496ad73ec01759957e51046aa7396f592338650117ac7b4dd3573eb53d9c9f9dfa62e2369c77af9c0d42f61bae74b287ddfa27b7f1c1be9883a044691d56dc13734ad4ee3a32a9f40e328c500d0fed8ea0510e938f2758004022bcaa6902bda1014b8ae3365272829ed94faba63cb14a36cf81390eca83fc1c627172013261b3993779aa076a5c5d81d90d27062e1a6d90b5cf1005c701917b7adac180cb75bbce0f27f2f180e2cb90140c14cc6009d2d41aab1db9418f91d4cf394002cd70ac9dc11ce865347fa3f56f87c149e2b17d2c72b663a58e3187bb19b9bac2d11483ba12f770ac04dc46d388518fa54dc152e9a9dfbff14f14c61cb375897e30c53e6de42d5e1401dae1b22baaa0e8a41c6af9d0e0b13a91a23d9b7d5552047029a3521946c7120d3d258b3aefcf754d1959487a1fe7743ac7e1cc89e368b197809c3a27317e0ec48d546db1e21eb629a29bc6247cdd4a1371437563edd12faea2c5cb77eededbfc58008fad1f65af35843fa274c734e3fbbaa9cc50d683748b75a485f94d630b032a5f1067d1deb30e9d2218c935c981d01c0c547fd68413136edf4c0c770286e823442e1c513651929213c121c1de700989141ab4af3b3fe7404b4d2a38c530bafb498e64953ce1c0fb7d340e21135bf8afdd8dd65b1b18cf1c8fb9f402b2670400b86ddafb184cc51d5fda273b80c26521f912f3583b4ae301dae151cb55c75703aadef032415227d53e395db6c150a1ee839ad26bae552e1ab736214dc04b0f3c41b7cfbd049681bc84c3d16530768:b2e3d9c5d0ff329996bc89d26fb3ac126bded313cbf8df86718638c199e057273d09eb163c6c181fd8bce51f72d4d9d2e84abbe08330773b9fcc2166f140d60e47fb621561f8b7eecec6033f2bcb6f43ac68c958dfd2656f52a0c29b4acd44f4304c6bf77eeaa0c5f6d3b22db19699c3dcdede698abde623ec4b2b90910c80ac3af39c550b6dd409e63d77706655a9199cb5c0258f5ba38285ffdc64b8a8f373d1fb29ba87f84ddf5f34d8f140bbc17b3961682df5d0a8f9102e379a9998139dfe40ab8ce753bf5626108237771a7d8e109e9e0afe9b66d0420942e163a4f3c03f71813ee078bd090ac3d0772e2622c259e682552c75b08dd055a4a5eb5e609440bcd3f3a6feb876fd16921520c6cb6884710d2e15cdad6daaeed95962dda21c6788f784917917982e1ccbb5fdd9bdc1769db6b6db57ca354e01a1339d8e77e9dbbb5812fbab6a14c54085c0659599f150e22472470f1e5e672c425f375f9e0d6e8d52fa17b7a8d7a4d7ca3e12f4db53836aed2bebd74589baca8ce9100291bfb7e456db7f2f0a84dc0a7488851366a9a5fea0e3efc74b9cdd4bd97b65abf361393ce1703d8571805ee68a13d3654f03dcecfb77a53430d09496ad73ec01759957e51046aa7396f592338650117ac7b4dd3573eb53d9c9f9dfa62e2369c77af9c0d42f61bae74b287ddfa27b7f1c1be9883a044691d56dc13734ad4ee3a32a9f40e328c500d0fed8ea0510e938f2758004022bcaa6902bda1014b8ae3365272829ed94faba63cb14a36cf81390eca83fc1c627172013261b3993779aa076a5c5d81d90d27062e1a6d90b5cf1005c701917b7adac180cb75bbce0f27f2f180e2cb90140c14cc6009d2d41aab1db9418f91d4cf394002cd70ac9dc11ce865347fa3f56f87c149e2b17d2c72b663a58e3187bb19b9bac2d11483ba12f770ac04dc46d388518fa54dc152e9a9dfbff14f14c61cb375897e30c53e6de42d5e1401dae1b22baaa0e8a41c6af9d0e0b13a91a23d9b7d5552047029a3521946c7120d3d258b3aefcf754d1959487a1fe7743ac7e1cc89e368b197809c3a27317e0ec48d546db1e21eb629a29bc6247cdd4a1371437563edd12faea2c5cb77eededbfc58008fad1f65af35843fa274c734e3fbbaa9cc50d683748b75a485f94d630b032a5f1067d1deb30e9d2218c935c981d01c0c547fd68413136edf4c0c770286e823442e1c513651929213c121c1de700989141ab4af3b3fe7404b4d2a38c530bafb498e64953ce1c0fb7d340e21135bf8afdd8dd65b1b18cf1c8fb9f402b2670400b86ddafb184cc51d5fda273b80c26521f912f3583b4ae301dae151cb55c75703aadef032415227d53e395db6c150a1ee839ad26bae552e1ab736214dc04b0f3c41b7cfbd049681bc84c3d16530768: +a804c33b4d38cb3ce31cf3bac1049e0d4ec63a1a0b7b59fd8a36ee37541656aa6072256d6574a293bd7c221c551c32cf2f7715e19e433a49d9b8b0490e56ef62:6072256d6574a293bd7c221c551c32cf2f7715e19e433a49d9b8b0490e56ef62:dbfe307f2aae9e07ec7c4b682106d2c9367b0c4aaa58ae804e0a3904754e6cf8fee73cf9e2d45d0289e5078293dfc469d46ea67026c5aa692d2f2c9fb4ec57cdab4c043ff9ae6185f27a704454e5f53950aabd25c9910474d45af8836862723e0e6a27823d82bcbb68a96052422a1819512e3b43408cf48957ad6ae235b7233df18284749153dfa57de35074a30edfab8a56df28ab2e2940306c221aa55490cc664e14683f30ee615e2d93fdf971f596663465843b3add6392ba3390311ef8dc59f251445d669e10a0061991e113561923aa215244463d8264199ac588924e231e8419d8685f338e599b5f40bf9bd1aece772535bbbcb8f6881c2e800491ab3b57b44b8ae43aeb5c4ae5e7edeb228fedc9f6b9cadea176e134936ded60af1c228734fb00570f2374bbbfa1bb170785805d6b6c701e820952eae45b8c2366113a1dfb2e35852af419b754f9cf7a081c3dde6c8053bf1ce0c85339d5699c422476fc21f26ce75d2a7fed09fc0f4175789847d876c51aa4e0bf7ce842b8308dc7a28c8239520714dc233136e09f557c7ef3e0f83bad63cb28ac616d3928f3837dce1dd58acb8ddbc72e822deee45f00776acc88e00cd3a9db486d92d535a57a0fdc4f903b62e517221c308cba2e30ffe7b91937a99417721f56fe6df44840e9e41136929c0ca3dc28ddf2379e4dcfde83723e2d4c9e23299c056afb31d3e70d085d0a312c5cd570b699dea8717458531348c96f6eb52d7ee61d5660f65e909a14ce1033dc853f2f25d09cf4e40d07eff72e15a390564a2be3c042d89a68660a97ffacec4967a4b618712d7060756520c29ee8d9220ad8615c4fcf3969bd3b2e0947e1f0be7e2d80e0a61480c3166db5582218bb0a8be9848efd41b6ce0cd795c486abb67210beb60cd078b46aeb7f4f485031902bcd7131e00b7035aa2d43fee063f7f30bd570da1dbb65c0ca92a4812632e432778553e35e856caa8218221fd6316ab0869173b38409bcefe6d2db9210f9024173b66dbb92677cbc71c8a1cd583fa6f354d3c93fa8b16c71374f25a00c332f85a8befd540388fb50db9f5d96e4e4e698833ce3d63c10b8eec70a243b9015db459431b62f5668bba60f0704f6bdfe9546ea475cef2ebccba4b7680848e82beff5854e49f65bb773a4922e90f9b8afc7cf818730588ed5aa7b399826aadd54372fcb761458b64de66857f4adacd4c32900cb77136a535d7bbbb554597aecf39ff698b45e6a218df1d2abe615eb8d9e1824c0becce90767899ebfd2c730144b32c74604c0e53e2505bb15d28007a87b9931d6eec0a6cb5b0f96d3194b2423:b1b44a142a7c4c3d0bf4661edac5b767005726c14a2769b7c214fb58737ec2e4bc51c3a195d2ba1b74a54eff4c33a90f41ccdefa9e9365fde8dd859fd3978c0adbfe307f2aae9e07ec7c4b682106d2c9367b0c4aaa58ae804e0a3904754e6cf8fee73cf9e2d45d0289e5078293dfc469d46ea67026c5aa692d2f2c9fb4ec57cdab4c043ff9ae6185f27a704454e5f53950aabd25c9910474d45af8836862723e0e6a27823d82bcbb68a96052422a1819512e3b43408cf48957ad6ae235b7233df18284749153dfa57de35074a30edfab8a56df28ab2e2940306c221aa55490cc664e14683f30ee615e2d93fdf971f596663465843b3add6392ba3390311ef8dc59f251445d669e10a0061991e113561923aa215244463d8264199ac588924e231e8419d8685f338e599b5f40bf9bd1aece772535bbbcb8f6881c2e800491ab3b57b44b8ae43aeb5c4ae5e7edeb228fedc9f6b9cadea176e134936ded60af1c228734fb00570f2374bbbfa1bb170785805d6b6c701e820952eae45b8c2366113a1dfb2e35852af419b754f9cf7a081c3dde6c8053bf1ce0c85339d5699c422476fc21f26ce75d2a7fed09fc0f4175789847d876c51aa4e0bf7ce842b8308dc7a28c8239520714dc233136e09f557c7ef3e0f83bad63cb28ac616d3928f3837dce1dd58acb8ddbc72e822deee45f00776acc88e00cd3a9db486d92d535a57a0fdc4f903b62e517221c308cba2e30ffe7b91937a99417721f56fe6df44840e9e41136929c0ca3dc28ddf2379e4dcfde83723e2d4c9e23299c056afb31d3e70d085d0a312c5cd570b699dea8717458531348c96f6eb52d7ee61d5660f65e909a14ce1033dc853f2f25d09cf4e40d07eff72e15a390564a2be3c042d89a68660a97ffacec4967a4b618712d7060756520c29ee8d9220ad8615c4fcf3969bd3b2e0947e1f0be7e2d80e0a61480c3166db5582218bb0a8be9848efd41b6ce0cd795c486abb67210beb60cd078b46aeb7f4f485031902bcd7131e00b7035aa2d43fee063f7f30bd570da1dbb65c0ca92a4812632e432778553e35e856caa8218221fd6316ab0869173b38409bcefe6d2db9210f9024173b66dbb92677cbc71c8a1cd583fa6f354d3c93fa8b16c71374f25a00c332f85a8befd540388fb50db9f5d96e4e4e698833ce3d63c10b8eec70a243b9015db459431b62f5668bba60f0704f6bdfe9546ea475cef2ebccba4b7680848e82beff5854e49f65bb773a4922e90f9b8afc7cf818730588ed5aa7b399826aadd54372fcb761458b64de66857f4adacd4c32900cb77136a535d7bbbb554597aecf39ff698b45e6a218df1d2abe615eb8d9e1824c0becce90767899ebfd2c730144b32c74604c0e53e2505bb15d28007a87b9931d6eec0a6cb5b0f96d3194b2423: +f820e6f24a8418b6acda165f29a360f767cdedde8f64d768b95fc2a5f3f404e779c4b263b2e58f678628d4ea82b175aca230b9a20285c828f94e1ffd63d75b23:79c4b263b2e58f678628d4ea82b175aca230b9a20285c828f94e1ffd63d75b23:ab6bd45bb06dfb9069118ff998f3bd393ea8e944979e89e049f2505cd8931b93086b7e9d8ee764e9b447ea4ea12138bb45275a21a19843f75dc5421d61ffd861838e5833825d67162f3259c26447be51dc1802ef5a04ba73b783935706abb42c513b65f2bbc44f83da1061242f2d5e5198f38c10717a86a3a197e7cd9034f636114499037277acb4722c06a91cb2f65e21eb8d22d36ad73b4265f7a7947e00e722bda67043cd1281bcd87e763fc97b54c8f86836cdbf08c9a1f700f4eaed9ea59a6fc1bc0df8c9ec1fc2977cad60f978abc0c8381aa9fb060e3f99378a51b2d9afbef358d55162a38922ebb87d2a3e0f0f4000b1c39b1502e95945e8ac9f4a3ea7c9ddb581a5ec06c00ba87a737084b384faba09c84871ddd67dc1bebb2f7fbd94a5597d019fe629e5bf12bea2e33ca84c680dc5a3989bbf3af9eeece8ab8fc861e3b8bfc1e67e2aee326b37fb9b51cfa0b5f5fc160069b450b704e0fab7fb6c5ab3c40b8f0b3d0930b9112d64b9dacab4dd875f29d8c58c5d2053ad9148ffde22d90bc0d50f5deca68d3ea25c5b4c7688871c0c77dbceeacbd0a4229f4970ec87b34499e278303c06694c30ac68524d11b172794b481273a5dac46122d2472095a563a435d185d5e91da726e74592999cdac688a33f38f7c035588f625dc6ac73d0047ab3d6d12f1ae33d8b62d6d6c6cacff0bdd894b57e318912ac0cf4a534762b2f6d263c935804423ed868cf8cfbb8be8f6d8a714a268a390edc2dd509d2dc96851d1bd43249bd0f69b0c4cb2ff4080d1fd5622bc238dda6e930025d8a2b12b972f9eba17421d4cea642f40ad9ea8547ae59498c3ad1b9a0c34ed8c01aae3bd21ac17743b577f9515cfbdde2704dc57e80f125323d55100b9f697927d431dfe73631b58e52aa6aeb0478bf459552438689fbeb9c60d87aae09954362cd02a2b0b479efd38f17821af39b21926ee02f7d972ad0f54ea6572cc3ebd020b1ee26882533bd19114323815f672ec8c90568730a58e4e1e35f6821219a32b8a6c52ced6f9573d9f3beb28513ba62fb201f7fd41bb10ca34bb1c70f2fd7bb9299a7c5f7f2e0fa1d1af0e9aef5ede7c16950e860ecd61f1842a1a22c9831c0c0d4eda840b088a54520c9b18c76eba9bebcd591381c180d7f86a0e58add92b9b0c8076a7cdcab60dea4c1afb18c8b94b1b392ccfb4dae2711e7d12d2bc7c7825f63992ec3247163c283b1075e32245f69cf47240aef0db43efae86fc1fd3bb99cf5b789f5bcba9504657d9e622a4aa16f01d4d844413124447d6d1a4423e7b55db7e6a31a319f4bacae430a33a9bdd4ef3680:f9fd72f321ca2133bf8585908d9ca7b8e336227e3ffb3749a1fbe8c9b1e5d50ef01f9db5f0d2a7c7c1399b97c9044e1bc1adc32b8bea46dad7b8102646960303ab6bd45bb06dfb9069118ff998f3bd393ea8e944979e89e049f2505cd8931b93086b7e9d8ee764e9b447ea4ea12138bb45275a21a19843f75dc5421d61ffd861838e5833825d67162f3259c26447be51dc1802ef5a04ba73b783935706abb42c513b65f2bbc44f83da1061242f2d5e5198f38c10717a86a3a197e7cd9034f636114499037277acb4722c06a91cb2f65e21eb8d22d36ad73b4265f7a7947e00e722bda67043cd1281bcd87e763fc97b54c8f86836cdbf08c9a1f700f4eaed9ea59a6fc1bc0df8c9ec1fc2977cad60f978abc0c8381aa9fb060e3f99378a51b2d9afbef358d55162a38922ebb87d2a3e0f0f4000b1c39b1502e95945e8ac9f4a3ea7c9ddb581a5ec06c00ba87a737084b384faba09c84871ddd67dc1bebb2f7fbd94a5597d019fe629e5bf12bea2e33ca84c680dc5a3989bbf3af9eeece8ab8fc861e3b8bfc1e67e2aee326b37fb9b51cfa0b5f5fc160069b450b704e0fab7fb6c5ab3c40b8f0b3d0930b9112d64b9dacab4dd875f29d8c58c5d2053ad9148ffde22d90bc0d50f5deca68d3ea25c5b4c7688871c0c77dbceeacbd0a4229f4970ec87b34499e278303c06694c30ac68524d11b172794b481273a5dac46122d2472095a563a435d185d5e91da726e74592999cdac688a33f38f7c035588f625dc6ac73d0047ab3d6d12f1ae33d8b62d6d6c6cacff0bdd894b57e318912ac0cf4a534762b2f6d263c935804423ed868cf8cfbb8be8f6d8a714a268a390edc2dd509d2dc96851d1bd43249bd0f69b0c4cb2ff4080d1fd5622bc238dda6e930025d8a2b12b972f9eba17421d4cea642f40ad9ea8547ae59498c3ad1b9a0c34ed8c01aae3bd21ac17743b577f9515cfbdde2704dc57e80f125323d55100b9f697927d431dfe73631b58e52aa6aeb0478bf459552438689fbeb9c60d87aae09954362cd02a2b0b479efd38f17821af39b21926ee02f7d972ad0f54ea6572cc3ebd020b1ee26882533bd19114323815f672ec8c90568730a58e4e1e35f6821219a32b8a6c52ced6f9573d9f3beb28513ba62fb201f7fd41bb10ca34bb1c70f2fd7bb9299a7c5f7f2e0fa1d1af0e9aef5ede7c16950e860ecd61f1842a1a22c9831c0c0d4eda840b088a54520c9b18c76eba9bebcd591381c180d7f86a0e58add92b9b0c8076a7cdcab60dea4c1afb18c8b94b1b392ccfb4dae2711e7d12d2bc7c7825f63992ec3247163c283b1075e32245f69cf47240aef0db43efae86fc1fd3bb99cf5b789f5bcba9504657d9e622a4aa16f01d4d844413124447d6d1a4423e7b55db7e6a31a319f4bacae430a33a9bdd4ef3680: +0a056be039fd55dada441d037361273f206e000a74a05c51c0cbb62743f1f34073140217a493a17866fff5154832273df79d5811543c222a39d056b8c970dbfa:73140217a493a17866fff5154832273df79d5811543c222a39d056b8c970dbfa:a5ab147684e4d4a7bcb5a96fb39818e23f56c2d8a744e9123d62083930ab1d0bb532e68714fcec7e6c41134b6b19ddd867fe635c9ed65393ee39c5e8fab456cb5b32797883f3cd9a0902b9796348ee66c691fb4f2bb14764410657c74ab364567879b6fa0a6f4dafd930d9234cd7834fb9d0eedfbb5a394bf0846ec6969c2ef7ce39e3853895ff5b4da31e54341b4272e4a26049189ff28241ceeffb7d2e1faf4f779fa65cac0f5783c60ae77de30ad4465fdb390d42571eff4a63136349937d6caeefcdae229e2f28cea8abf3ffae3c3eccd90670a4212a2bee1ca6a5b54f094fc3231058f5cb9eceb9993be47027d51c18deca41cddaf4e8bc56a99fd270355ff45971950e3437a198ccc3254168dfc1574080802ee101a617fb604e868f8fa8fb30daeb43074de11f2483d916de5643b7cac23d9340508a3fd621ecd25004356a53554ad3ad7d5d25817ad7c9a610008c67ac16ba4211c42f5dadf86c2c3aed825cf2a9b523bfc03dd7de400c67807e139ea5dbce4ee1f7d318889b01a9f44803c322ac3b61e20e6312d0a03bf9927fa33f04ed7e207b16f26502c2983a3a961f224461fe9b64923b1d09189476ae8d001d0ecaae4df60db35f448bb612f9655a5fb144df11d83aa6936886c304949e59aa46df65c22ce7bf289b3c77c25d896be6d51dee10748261688c8b071c856f9962c66775ddf16083dae06587e32a6361199d72097e383ad7439491b5a563a3e6d58da3d5abb1de84890a36b421ce03d484dfd60039638d46edfb60659e3a25ac6e9a935ad6dad50f927bcc2ff99f9924a5b7995dc23c8f301ccc7769f71c18260904a3dcfb817d2d805cb1f196be8b6ecf352bc296bc3f76ea91353f8cf35bcd2b57eb5942773d6834ac50eeadc7e66461d1da098ccec75ff7205215f52459d97620f9f0289e93911db39b21df818fdf0bed45509244633df01cdddb4b75972fa7ea6f73281cbdbbd1bcb00c3bc1b1728eeae0bba172b131f5d30890a341e6b72f7e89dd4b6db3e79b6927586cf2c8ac38dd14f374d7f5bba9f4353def10ddc94d3d1118c5699e38b6b504918e589efe3f7e973fb40e2ebd057de1385e39d699a8f683b962fae4f3902881f1afbed7c783823558c36d68c6875d166fa243eb2ae14f7e6315a6d2ab4e79ea8e16e69d30edc708f1e7af7adafedcd3168898b331878178c4ba8833d20b3cac9d32b8888cc6783206397470a2e7cc4c9809ff79ceac9dc24ca1438c919c8a415e82f0902b4d9cf4ccd576968d5bee81c5f19c7d57b9bada8eab4756ea270dd26129e6122ee2d615242bc7fabff4f8312e686c8f:fab8e5d93d7d46c65ee117c5375e73c9705f8754177fdd46efed4737c28768cc4b95a9c84c529b4b916b28dabd8741183144bcdb483df98af89d8240cf094604a5ab147684e4d4a7bcb5a96fb39818e23f56c2d8a744e9123d62083930ab1d0bb532e68714fcec7e6c41134b6b19ddd867fe635c9ed65393ee39c5e8fab456cb5b32797883f3cd9a0902b9796348ee66c691fb4f2bb14764410657c74ab364567879b6fa0a6f4dafd930d9234cd7834fb9d0eedfbb5a394bf0846ec6969c2ef7ce39e3853895ff5b4da31e54341b4272e4a26049189ff28241ceeffb7d2e1faf4f779fa65cac0f5783c60ae77de30ad4465fdb390d42571eff4a63136349937d6caeefcdae229e2f28cea8abf3ffae3c3eccd90670a4212a2bee1ca6a5b54f094fc3231058f5cb9eceb9993be47027d51c18deca41cddaf4e8bc56a99fd270355ff45971950e3437a198ccc3254168dfc1574080802ee101a617fb604e868f8fa8fb30daeb43074de11f2483d916de5643b7cac23d9340508a3fd621ecd25004356a53554ad3ad7d5d25817ad7c9a610008c67ac16ba4211c42f5dadf86c2c3aed825cf2a9b523bfc03dd7de400c67807e139ea5dbce4ee1f7d318889b01a9f44803c322ac3b61e20e6312d0a03bf9927fa33f04ed7e207b16f26502c2983a3a961f224461fe9b64923b1d09189476ae8d001d0ecaae4df60db35f448bb612f9655a5fb144df11d83aa6936886c304949e59aa46df65c22ce7bf289b3c77c25d896be6d51dee10748261688c8b071c856f9962c66775ddf16083dae06587e32a6361199d72097e383ad7439491b5a563a3e6d58da3d5abb1de84890a36b421ce03d484dfd60039638d46edfb60659e3a25ac6e9a935ad6dad50f927bcc2ff99f9924a5b7995dc23c8f301ccc7769f71c18260904a3dcfb817d2d805cb1f196be8b6ecf352bc296bc3f76ea91353f8cf35bcd2b57eb5942773d6834ac50eeadc7e66461d1da098ccec75ff7205215f52459d97620f9f0289e93911db39b21df818fdf0bed45509244633df01cdddb4b75972fa7ea6f73281cbdbbd1bcb00c3bc1b1728eeae0bba172b131f5d30890a341e6b72f7e89dd4b6db3e79b6927586cf2c8ac38dd14f374d7f5bba9f4353def10ddc94d3d1118c5699e38b6b504918e589efe3f7e973fb40e2ebd057de1385e39d699a8f683b962fae4f3902881f1afbed7c783823558c36d68c6875d166fa243eb2ae14f7e6315a6d2ab4e79ea8e16e69d30edc708f1e7af7adafedcd3168898b331878178c4ba8833d20b3cac9d32b8888cc6783206397470a2e7cc4c9809ff79ceac9dc24ca1438c919c8a415e82f0902b4d9cf4ccd576968d5bee81c5f19c7d57b9bada8eab4756ea270dd26129e6122ee2d615242bc7fabff4f8312e686c8f: +220524860cb89ab295bd884f988a57911868693d6b105a80b230f21e57805a7d4ab32bc1566a7677e799734dc84181fbb654b813379180f1dd35aef2d324c12c:4ab32bc1566a7677e799734dc84181fbb654b813379180f1dd35aef2d324c12c:024a54ac5e0163b3a4fdd02f5936888ae2f9b74a6414b53c6381173b095a4ddacfc3a69f19167d0f1ae0c120bba7e9fcb7ccfc796d89ea46ef8058866ef6da7d01a6a142ea69d720c4f805ac5405a8012c3c2a8263b5372d59bf7f4099299013d26259dfd5193ece56179777be51b86bd1ce5f1fc9156f2b3a32c09d86bc6132de576102e2f03c716db5366ccbe742aee3552ac3b39d0ec7d4e4e9626bf8ece031d678d3480905c0e338fb7cc026e3e79cf2c2781ac2a5a40df4284e235a0389e928fc63557dc6f199fcec5f361ea24759fa7c5f71978c0ba245e4b03ae435941c86c81a51430c2dc9927e3b0f4ec4eba7c2745b493987154d7da85b67de21c598407fb2a760804ad05bfdfa45a613224b22a08588ccea3cbdf47a198bebf8cfed8649d6d5f3fa501376bdfba4003dac2237dcace5315b7fefb879a89a85bce6da526fc360cbb4fd554ef013f33b7384cd2b22a88577f3a2d366422aae46417ba916e1646e24404a88b5d53ff1aed2a47baf81fcb4286397991394b2ecc39667ac46c2bdb6d023b33db013457c4005d839015d8851f028ac334fb24bbad2902a4d63ae68e0eca7eaea1e856529647baf1412213754ed50af3f436e9bafc1601639b39d3e52a93a898fb6019fd5ed6e7dfc050e7ce5f3d35ceb5067021c0fbdc708d3f26bd60568d1ed2b612b696235d5333318f9a6c987235a7a07f8c6a9354fb8e734763065afcd4d937764a4f037cc7e7e2b93217f1641684fa81b7ff7986a28b38e95b332e74649e83d0ded795c57f24cf276e0143901bafef0f1693fe7cf10904fb0d880d72e44716a7069daaae742cf0ff3ed92f5f7d1e10e049d8df043631ed0ed4c4ac4022d8403cb0421b454cbfb6f48a30e9ee1609ad7b68211977acb33b9c1a1be735814c58f66db5f0b8ac773b1d58d4e6bc45dfd48a294bbd25e92671f56f302f29b50d80431c8f2ea33996257b208e057ea7672cc2d1cd4204b85b2ab509027131359aeb42e3eccdbaecfe2cd3e5a3313266e761194ff69cae9e37e51cc0a54f086dde13cb33118e34fe33c74d735582752d68d21c79e5c3aaea94ba107cb7ee8a70a3f9a01e9808c0aeba6665315b45625840a033a6e2a875495057942ed9bb2ce6e4ee60bed47cd9d584bc24524397a109498ee2a973aad6a29b70a1cfbfe9aa5c7cb9f35f0fa00227f43988d07619b6fb2f6d3bee28e10ee705347015a922e2e88d34fb0ce515b08df3a1b634ff9ec15d0594182c86ebb0db783612a7d19e4b22e822d566245aed72e694c3d101bfa4ca879862e5f99c23a5d66083ce06d87f399aa7888ab83b8664472:db1cc0c5db773ec51689be28842fa6791a7d75e29c228ae9593a580e0875b1670f09b03442929a18f1e9414ea34315ff09d91d922ee47f10f71da4ab13b7d901024a54ac5e0163b3a4fdd02f5936888ae2f9b74a6414b53c6381173b095a4ddacfc3a69f19167d0f1ae0c120bba7e9fcb7ccfc796d89ea46ef8058866ef6da7d01a6a142ea69d720c4f805ac5405a8012c3c2a8263b5372d59bf7f4099299013d26259dfd5193ece56179777be51b86bd1ce5f1fc9156f2b3a32c09d86bc6132de576102e2f03c716db5366ccbe742aee3552ac3b39d0ec7d4e4e9626bf8ece031d678d3480905c0e338fb7cc026e3e79cf2c2781ac2a5a40df4284e235a0389e928fc63557dc6f199fcec5f361ea24759fa7c5f71978c0ba245e4b03ae435941c86c81a51430c2dc9927e3b0f4ec4eba7c2745b493987154d7da85b67de21c598407fb2a760804ad05bfdfa45a613224b22a08588ccea3cbdf47a198bebf8cfed8649d6d5f3fa501376bdfba4003dac2237dcace5315b7fefb879a89a85bce6da526fc360cbb4fd554ef013f33b7384cd2b22a88577f3a2d366422aae46417ba916e1646e24404a88b5d53ff1aed2a47baf81fcb4286397991394b2ecc39667ac46c2bdb6d023b33db013457c4005d839015d8851f028ac334fb24bbad2902a4d63ae68e0eca7eaea1e856529647baf1412213754ed50af3f436e9bafc1601639b39d3e52a93a898fb6019fd5ed6e7dfc050e7ce5f3d35ceb5067021c0fbdc708d3f26bd60568d1ed2b612b696235d5333318f9a6c987235a7a07f8c6a9354fb8e734763065afcd4d937764a4f037cc7e7e2b93217f1641684fa81b7ff7986a28b38e95b332e74649e83d0ded795c57f24cf276e0143901bafef0f1693fe7cf10904fb0d880d72e44716a7069daaae742cf0ff3ed92f5f7d1e10e049d8df043631ed0ed4c4ac4022d8403cb0421b454cbfb6f48a30e9ee1609ad7b68211977acb33b9c1a1be735814c58f66db5f0b8ac773b1d58d4e6bc45dfd48a294bbd25e92671f56f302f29b50d80431c8f2ea33996257b208e057ea7672cc2d1cd4204b85b2ab509027131359aeb42e3eccdbaecfe2cd3e5a3313266e761194ff69cae9e37e51cc0a54f086dde13cb33118e34fe33c74d735582752d68d21c79e5c3aaea94ba107cb7ee8a70a3f9a01e9808c0aeba6665315b45625840a033a6e2a875495057942ed9bb2ce6e4ee60bed47cd9d584bc24524397a109498ee2a973aad6a29b70a1cfbfe9aa5c7cb9f35f0fa00227f43988d07619b6fb2f6d3bee28e10ee705347015a922e2e88d34fb0ce515b08df3a1b634ff9ec15d0594182c86ebb0db783612a7d19e4b22e822d566245aed72e694c3d101bfa4ca879862e5f99c23a5d66083ce06d87f399aa7888ab83b8664472: +4ef60f0691d737e64d437bfd3398330e55e3c094cf41fc557b0fe0b643909ab8306ab146e5c8cd630f9b48bf8b685db0b6b553ef69686853b6b531960118548c:306ab146e5c8cd630f9b48bf8b685db0b6b553ef69686853b6b531960118548c:0a188ac26f3c5d89f3d588374fac5ecf9a467e2165b31d0b0f23501bd22e62bf3555ffba94631de74a6a3c3cf63b03ac1bbb37d233eca5993b0970a0220de8d6c41a970307309a52da0576dc334d806447aa09d0b245eacd0b42c4e19fa3d6fbdc229430eb3c7558af5331c6e7fcc2e552ce35d579073b548dc115bbd27e5a33ce1c47fc8461e391b6d767953487cc52ee673bc4be96569c8557369ebb6e02f79238108c3b5856ee381a79ff464c8f6009fd47e67b4c80201e11e61ab8f59ba5d07b15ace3fb374c64b6b4c345e2b00e9151ab8e1c5c98568bc58dd0812aaa3beee165e7eae58fbde63077203c4fd6e16068d76e3d3a13f1cdd73288bd5e4da44eb119a04c4d32efa2f13e7426a2f41c5623c9b066b1303639b8fcea0d8774cc08045f7e346365ff31d3b1ed99e97bca5f25c92b2843ac585d02193a2fd39466f73aaa989b1fa05b9a157fd0277c5e745d258e027803a524ad94309425c3f4dec31c0efc547752f4c7194cbb272f849a52169c6a078d20ede1432016528477b58c2bdf6063f9447e33837ccb437d8d6b95cf4c44be70c8193ad980a105f3db6f9930bab4678c776342faf170edf74248d3b1ca96f731b9d026d8f0f7c34ed372c1cde176f55f558675cc3180c23902f4ba9508d1c91c3c9e688730327f3f7b637a8fee54373759fcb17c9217ea44ce43691a8f6463640a4a5e151e6254c4ef12623b49394da7cc79452693817d6baea9a0a75876948b1f8d3b717f9ec36753f53263710383b98262ae6354ff2a2283220ad42c5cb2cbbdf12c879513710b16be856f3b1355b36f4b80c017c21be85e96053da050c40312100abb640b873d88fb6ee0d19e9e61b04c970bd1f060dd311bbb9a6e35b985fdca17caee8cd5db637acd90cb8e823255c056018fef5920db640d2201c5eddbd8a9c9474da8def7e1325b3cc436c74f815db1e42b421faab626a4378c2d84261bf649a53b321f598c44bbd3002b06cf7f1fdef84ab35f73ed7dc65096cb1dc0cc0e34c561c8a15cf5279abbed9b16ff24a9744e3f5e649cc9d8884f891c3fb78902031ffe0e0121c72080ad10c247b7c93a9ebb2d84d4f877750d7b3416393d03045226bb7994eea58e272dc18c46b382d1f97b23765fda7a8ce21fc6b98d723ffccd99ac4655cc5d10105a2a5b7c8cfbfb90e27a9a809e41ae640063286405a9be83ac5d2907a45f163c7764b09f99a55593220d6901292b9b5803a0fe71b0e4441cbfef841c33cebc98364d666e5a9f5e7e69a1508e4380ed361345b7248a4c1c1ce08769bc7152ddb332fba176200f5abbae3812f406da72dde5db:cbf7cf22081c5f235dba35630fb3f0408fceccefeb28b99d74dbd98c902c7d99ba9ca7fab3747c504cc219f4dd101081f58ce616e29280e362539fe49f34d7050a188ac26f3c5d89f3d588374fac5ecf9a467e2165b31d0b0f23501bd22e62bf3555ffba94631de74a6a3c3cf63b03ac1bbb37d233eca5993b0970a0220de8d6c41a970307309a52da0576dc334d806447aa09d0b245eacd0b42c4e19fa3d6fbdc229430eb3c7558af5331c6e7fcc2e552ce35d579073b548dc115bbd27e5a33ce1c47fc8461e391b6d767953487cc52ee673bc4be96569c8557369ebb6e02f79238108c3b5856ee381a79ff464c8f6009fd47e67b4c80201e11e61ab8f59ba5d07b15ace3fb374c64b6b4c345e2b00e9151ab8e1c5c98568bc58dd0812aaa3beee165e7eae58fbde63077203c4fd6e16068d76e3d3a13f1cdd73288bd5e4da44eb119a04c4d32efa2f13e7426a2f41c5623c9b066b1303639b8fcea0d8774cc08045f7e346365ff31d3b1ed99e97bca5f25c92b2843ac585d02193a2fd39466f73aaa989b1fa05b9a157fd0277c5e745d258e027803a524ad94309425c3f4dec31c0efc547752f4c7194cbb272f849a52169c6a078d20ede1432016528477b58c2bdf6063f9447e33837ccb437d8d6b95cf4c44be70c8193ad980a105f3db6f9930bab4678c776342faf170edf74248d3b1ca96f731b9d026d8f0f7c34ed372c1cde176f55f558675cc3180c23902f4ba9508d1c91c3c9e688730327f3f7b637a8fee54373759fcb17c9217ea44ce43691a8f6463640a4a5e151e6254c4ef12623b49394da7cc79452693817d6baea9a0a75876948b1f8d3b717f9ec36753f53263710383b98262ae6354ff2a2283220ad42c5cb2cbbdf12c879513710b16be856f3b1355b36f4b80c017c21be85e96053da050c40312100abb640b873d88fb6ee0d19e9e61b04c970bd1f060dd311bbb9a6e35b985fdca17caee8cd5db637acd90cb8e823255c056018fef5920db640d2201c5eddbd8a9c9474da8def7e1325b3cc436c74f815db1e42b421faab626a4378c2d84261bf649a53b321f598c44bbd3002b06cf7f1fdef84ab35f73ed7dc65096cb1dc0cc0e34c561c8a15cf5279abbed9b16ff24a9744e3f5e649cc9d8884f891c3fb78902031ffe0e0121c72080ad10c247b7c93a9ebb2d84d4f877750d7b3416393d03045226bb7994eea58e272dc18c46b382d1f97b23765fda7a8ce21fc6b98d723ffccd99ac4655cc5d10105a2a5b7c8cfbfb90e27a9a809e41ae640063286405a9be83ac5d2907a45f163c7764b09f99a55593220d6901292b9b5803a0fe71b0e4441cbfef841c33cebc98364d666e5a9f5e7e69a1508e4380ed361345b7248a4c1c1ce08769bc7152ddb332fba176200f5abbae3812f406da72dde5db: +197e15dce4c47d734dbce4688a7ad5fe41ebf2aa29a2bddb2bee628429c1bc0230fac323048b0c781a9f63c1ee69f2b9e75a2706d249512a2739607f26db138f:30fac323048b0c781a9f63c1ee69f2b9e75a2706d249512a2739607f26db138f:fd971d48946b51ffed7b62c5d099c1e56b1358b92235e1010e3f23844ddb73bcee8d2e1c9977353bc96a221c05602931fa16ccc2ab6d0f01c846c2920e99de026dc2897f3d5f3cee174ce751d4a805ee1959a3c69cfd42d7c9afd31fa9b1cf05786d8f9042a4f9f81cf7ac9c1c39b36f1ee95b98cf7ee3f43e2c343733d1d82cc08b2cdeb78d982034085ff4dc6536cd154a790c85c8613ec4e5e1dc377d38a745d938cfb15c8b8aa86121835f2e25e9e6d0de68025d810c3dc9df991dadad39dc6981fdbac1ff9b7a791c3960d8564366e5aa39a9e9c7cbf1d3f0f820d1b90108751ac764dabe05c51c18529da1b0349614668424ab4e936440c4a2513be528539372eee78754589dbe7994faa1f6229124f839950ed0923f4323315ac963bbe4c8e177dac516e7342238f1cdf140befc8acdca3d002b16c1398d868600304c7e9853b23a51b17d9fd06156e1d1d08a28460909fa209ccccc4cecbdb1a46348089115318681a95ae580ab6766041384651cc4e6145103923bdf4a32a93d93eed318791f20805f7ea84b743ee11ead9e4ca03da76ddd249fd4475fc1a353c70a83389bfac52098db066d1029c4effbed864ebe7f107e0103b3a8f3fd1d6ab4360b99e8b140c5ea133e923c392b8e4063aa6e522638f61d7a71c9225897d9f8a1e16cfcc801e7d54104eb10e61a5ae63c5c85a5b29392ab3ab8e5c039f100d0f4600c610e0209436ef2ece4d0bdb0bab437b2db5f3708fddf96660f6fb1a90d6048d395afafa760ccaf15deaa0effeb26ec17681d172c1330f78e78a8736b285f615f15d4f2c313d25f30aee9d1db39f535fcdd0ebc8e71b89ce6b3fcb567cd0fa288f48ed3a759bb2ed200fdc23091502fd9ca651ce5e3422a98335a81d74a65cc1500e9070abb609c1c1f68fc2ca94cdd550f99bcb2d092416b9bd388410b8fe748fb8c9a5ab8615f2ed968f85dcb2727726984beada7a18afdb0c72aa65de7abb7a86f11169a6eadf1c21d614e52c0c8f019747d341a05d85e37bf58d8327e9939c2387c2744edf838563cb37f0b16e8a06fc628a97230506fa4183954dc74815f3be2eb2aff4a13c065f743b7d85de804eb28efe570ed5ecc71aba97f9763b436173247f38e0cf6297209b65128465a382664ced8011fcc3d0e563f155bc63c94dde73c7b17247b8c3a4e8034ebd4364635185ce9c7081dbdbe8545f79d01aa532a0dc52cb790a31fc2ff41acebad27cce9244554db652fa287bae7decbcc8ce9e01d1a88ab412b6c6578203b42dec982b7f3b82314db2cc7c5c3dc1d3d8b17144da7fe60e7a8725fd0a97c610607cf413c72:2c3c8cd299c9060b65999b03a6579bc50ef1fe0d851f23be9cb58f8fb8c672ee086a539ead949e087df091122d26faaad206a5c52fcd58b514d7a935be017908fd971d48946b51ffed7b62c5d099c1e56b1358b92235e1010e3f23844ddb73bcee8d2e1c9977353bc96a221c05602931fa16ccc2ab6d0f01c846c2920e99de026dc2897f3d5f3cee174ce751d4a805ee1959a3c69cfd42d7c9afd31fa9b1cf05786d8f9042a4f9f81cf7ac9c1c39b36f1ee95b98cf7ee3f43e2c343733d1d82cc08b2cdeb78d982034085ff4dc6536cd154a790c85c8613ec4e5e1dc377d38a745d938cfb15c8b8aa86121835f2e25e9e6d0de68025d810c3dc9df991dadad39dc6981fdbac1ff9b7a791c3960d8564366e5aa39a9e9c7cbf1d3f0f820d1b90108751ac764dabe05c51c18529da1b0349614668424ab4e936440c4a2513be528539372eee78754589dbe7994faa1f6229124f839950ed0923f4323315ac963bbe4c8e177dac516e7342238f1cdf140befc8acdca3d002b16c1398d868600304c7e9853b23a51b17d9fd06156e1d1d08a28460909fa209ccccc4cecbdb1a46348089115318681a95ae580ab6766041384651cc4e6145103923bdf4a32a93d93eed318791f20805f7ea84b743ee11ead9e4ca03da76ddd249fd4475fc1a353c70a83389bfac52098db066d1029c4effbed864ebe7f107e0103b3a8f3fd1d6ab4360b99e8b140c5ea133e923c392b8e4063aa6e522638f61d7a71c9225897d9f8a1e16cfcc801e7d54104eb10e61a5ae63c5c85a5b29392ab3ab8e5c039f100d0f4600c610e0209436ef2ece4d0bdb0bab437b2db5f3708fddf96660f6fb1a90d6048d395afafa760ccaf15deaa0effeb26ec17681d172c1330f78e78a8736b285f615f15d4f2c313d25f30aee9d1db39f535fcdd0ebc8e71b89ce6b3fcb567cd0fa288f48ed3a759bb2ed200fdc23091502fd9ca651ce5e3422a98335a81d74a65cc1500e9070abb609c1c1f68fc2ca94cdd550f99bcb2d092416b9bd388410b8fe748fb8c9a5ab8615f2ed968f85dcb2727726984beada7a18afdb0c72aa65de7abb7a86f11169a6eadf1c21d614e52c0c8f019747d341a05d85e37bf58d8327e9939c2387c2744edf838563cb37f0b16e8a06fc628a97230506fa4183954dc74815f3be2eb2aff4a13c065f743b7d85de804eb28efe570ed5ecc71aba97f9763b436173247f38e0cf6297209b65128465a382664ced8011fcc3d0e563f155bc63c94dde73c7b17247b8c3a4e8034ebd4364635185ce9c7081dbdbe8545f79d01aa532a0dc52cb790a31fc2ff41acebad27cce9244554db652fa287bae7decbcc8ce9e01d1a88ab412b6c6578203b42dec982b7f3b82314db2cc7c5c3dc1d3d8b17144da7fe60e7a8725fd0a97c610607cf413c72: +08b5fd4e419d2370c0fcd6c3b92f8db3afd42268f533085d9fce32b522824e34cd0da699379e4f9425e84b9757300a51a163f358734cc37a91ff0ea488d29779:cd0da699379e4f9425e84b9757300a51a163f358734cc37a91ff0ea488d29779:3ceeeea30fa401563df36b198b9b59698c10e100a2f30e6f78fe62b92ecac989e8aa09ec760e89cac0a16bde3cac73622a8627efedfa4ec09b873f7e1000e76982910ca0aa4afb1ff5a8448b76f7b0d2a2d52a7f40dedefc68d60ce6622ca080d6698ea6c3bd7210b3b648f53252291494b35a55ff40fa1a631a57c510011a46bfb9e271bae1e78ce6c6ea60c55ba0cce36059bfb01e394556987f744b72aebbdb4b1bdbb3bbaaee1b8b2f3174506a793f0a511b2b569049b30a2e0841424184a48eca9e2d83783ac5b61eb947cbd8bab7ad38b0c68427d8f94ae285190dbb6e0c6d580a25142394be948158d8da83b4f34a8d258b97075632b3c28bfae3105ed1872e356e43aed59397b9110bbf9d8ca2a044d5271e6cc361e14e69a932517683ec81818f02cfa0295e5661cea3e586afc0db41ba95553ee75b200b0f9790111d3757a739e563557aff9b70ca14e87b795437ba91a95dd07ea69a11359f36ca03298e0bfa4f912f64a2924ad901975a2a960ba1be89921b1f5485496b7ea5da6d8a6937ac105bf3760e4876990a0f5c5a634f74cb57df7c172c8a415372e6d903298717499616f8971c68bbece92ea878a18e23f327c3649b6a852ef23b7b3e603cdf80452dbf1be2fb77e814d2525496bb31fb6e4ed2533248b39d5fbe2390a9b6fccaba997e8b49b59836e3e09529ea5e4113eee451c9c6bb26741d0e4c586f53d604c6ea0c0e60db02e5109f3734f51cdd8985afeb3ecaff65e059e312cd50fa349ff28bdc9b70b7f532dbab1df43b03167c1d2e3fa6ee8c9b174a0b2cf8aa9ffa406bf5bd7288780c9c4a6b697949b48638d42079c8c66e14d9b572a210a093eaf1d2f7a703b5cd20adc4f9927a6ea8ea78faa61bc62b3c5cbd3a53252566d043ba556590d9a763be7fea4b20e1e9cfbebfae15439b334dc539b17dada2e434e9c83225b1e8f6beb7d556b47d7f69f7eb7df5ede2eebd84e250b7c9468c21fdc0170ea8df662d6180581f657fe76cef1858b6b02f7325c7219643fba2f7e9963a33322d6504ab91bf10a978fa07b47d5db0be000dcd002bddaf676b77259c9f60ad0b11671cd5777c1e80b13f82eb0fb6a180b5666293a43240862fbfa3978d95311971afab9e1cc8ab14a876b6572ac8a4b7e0b40aaf6b52a1cf4c1ebc6c1c487df5a3cbc4005a0ee329cabc286db10f17d0f1782e07d3324f0c73efbd3c2fb52b71f98ad95db95062d91425e73467bc1e4e9bf552e8a24429d97db1d66dd4d995e5f8d24e9c910b2eb1758ef75525c3d65a3f430a027348820ce3053b6f3af4ec96d0493731c818c6b1a70c250ac686a4fc:42a13756b75c6722485fa3f694041b39b7d7c5fd40ebc06a52e0ff34ce14d8d40fa82a9508b568537d26d0dd7c0a31be710da80aab35196a039b60641db1e1013ceeeea30fa401563df36b198b9b59698c10e100a2f30e6f78fe62b92ecac989e8aa09ec760e89cac0a16bde3cac73622a8627efedfa4ec09b873f7e1000e76982910ca0aa4afb1ff5a8448b76f7b0d2a2d52a7f40dedefc68d60ce6622ca080d6698ea6c3bd7210b3b648f53252291494b35a55ff40fa1a631a57c510011a46bfb9e271bae1e78ce6c6ea60c55ba0cce36059bfb01e394556987f744b72aebbdb4b1bdbb3bbaaee1b8b2f3174506a793f0a511b2b569049b30a2e0841424184a48eca9e2d83783ac5b61eb947cbd8bab7ad38b0c68427d8f94ae285190dbb6e0c6d580a25142394be948158d8da83b4f34a8d258b97075632b3c28bfae3105ed1872e356e43aed59397b9110bbf9d8ca2a044d5271e6cc361e14e69a932517683ec81818f02cfa0295e5661cea3e586afc0db41ba95553ee75b200b0f9790111d3757a739e563557aff9b70ca14e87b795437ba91a95dd07ea69a11359f36ca03298e0bfa4f912f64a2924ad901975a2a960ba1be89921b1f5485496b7ea5da6d8a6937ac105bf3760e4876990a0f5c5a634f74cb57df7c172c8a415372e6d903298717499616f8971c68bbece92ea878a18e23f327c3649b6a852ef23b7b3e603cdf80452dbf1be2fb77e814d2525496bb31fb6e4ed2533248b39d5fbe2390a9b6fccaba997e8b49b59836e3e09529ea5e4113eee451c9c6bb26741d0e4c586f53d604c6ea0c0e60db02e5109f3734f51cdd8985afeb3ecaff65e059e312cd50fa349ff28bdc9b70b7f532dbab1df43b03167c1d2e3fa6ee8c9b174a0b2cf8aa9ffa406bf5bd7288780c9c4a6b697949b48638d42079c8c66e14d9b572a210a093eaf1d2f7a703b5cd20adc4f9927a6ea8ea78faa61bc62b3c5cbd3a53252566d043ba556590d9a763be7fea4b20e1e9cfbebfae15439b334dc539b17dada2e434e9c83225b1e8f6beb7d556b47d7f69f7eb7df5ede2eebd84e250b7c9468c21fdc0170ea8df662d6180581f657fe76cef1858b6b02f7325c7219643fba2f7e9963a33322d6504ab91bf10a978fa07b47d5db0be000dcd002bddaf676b77259c9f60ad0b11671cd5777c1e80b13f82eb0fb6a180b5666293a43240862fbfa3978d95311971afab9e1cc8ab14a876b6572ac8a4b7e0b40aaf6b52a1cf4c1ebc6c1c487df5a3cbc4005a0ee329cabc286db10f17d0f1782e07d3324f0c73efbd3c2fb52b71f98ad95db95062d91425e73467bc1e4e9bf552e8a24429d97db1d66dd4d995e5f8d24e9c910b2eb1758ef75525c3d65a3f430a027348820ce3053b6f3af4ec96d0493731c818c6b1a70c250ac686a4fc: +1e85c9e451b7acf801d16bc8268eb42ae85c72c68e9f90927aa0f3b50befd229a69d057f4b743811e07ac74561c225be0381c7d5849e6018793701a8cb6c99b5:a69d057f4b743811e07ac74561c225be0381c7d5849e6018793701a8cb6c99b5:189ea9c8d9ed14b0de82b44cbdd58757a27c68383fba597761f9e862e08de15b1e44c3db1badbde76980ee39e699629f6fcfef32d36b3393da2ca5a81f959c8b0f1b801b5fa4c47ca39591e612a2435c5bafd77a5c7ab74359210906f47533b1879e2a5af5864d961c8146e25dac772555e042a887261419ab8c9f6f625625481da5b93526a131f37b534a0050a8a462b33f20a7e94b891530b19bf654ee9534c9a8361d03635d8d27d46be7bf84781ad0d42d1e7c4854a49ba1ba458262fe5ea19021b935a6949492d70b605e151989ef2641b2bf81ec4b92020fc7074c2a63229d51a944186a28895e8ea95292c2f872bb21a3149399e23ccd8e2fc4f17a46b59c282c51b58d00266a5c16b1ce350d5485e8d8016dd0a50a5984cc948154cd5ce7cda0ee0ab1d7251bdc70a1785b8e9103917f4b917ab2b494f3483389a2f9237541849ed3bd565cffac9e756db56ef5e23495bc771e88bffa8707ceea5c09becadd059ab889d1df7e887b71a9e6c238378fbe0c3630386616363f207b16c3270d39acded511529992f4e598789121d316135810636baade8a28edc66bbf5ede3f404a70b47d35988be706b4eaa03023a39093d583cd4cd8bf4c74341a028c19d60da31b6a7a034c081a2b030feb3cd2f03d0faabffb58e3fc36c006cfb92947a7de5ba87476c1b051e18283c03e9c6e5a5c3c2777d9a0757372379664e82f8485824fedb70a4bc4e356edd1b5ce0fb6e41de0171621b84fafa00189afa8a6a900b14c70758f7aa4fb82400e0d18ab3cd7e48acfd489cab0e72e719f79a07d066c531a891c55291f2245dbbee44e52b1dfc8727aae387ab9e71994a3854e1add73d9a7965c775521c2f540842276dd309e2f6a341e7f0f37f22bb6627b6e9cb25ba24c6c4f4eb9f5e7622d88da1984e29c5da001039c44042b59351406a41336dd772d497d3fc8aac41172eb5aa6417fe422ec7c150b96b0454ee331247cb1538aeff3eca2d50e53d6d13170a76a0049ea0c05904a6390ed14ce7491e97f754c5222dac4b6118ba381f552e73ea8491e3b7ac949569b569cf2d29a80410e065b5cc4a466bb04eb7a15f596792e8490ba7002ec361571af5d8f57675c956449470a2f9955407367e409a232899553120a277db863e9a82ddabae87b789145ba898df3c28b96fbe3014cd085c6e60ee8831701036d99c5425d58e8bcc9fd9271d46aec1eb955130102eaaab44e0770c30b2b127efb0e5f8a3f7a0ca34ec9984a46011bc26bfde0c0819bb54706b565638b7542dc4b8bf8098dc01f161b3b129618b59aded33cb59ce9189a6762dbae5b0d34b71c8dbf:6c36da9ad6c456343ce642aca454923a52a2844ce5ee58947c8df7bab2ebe467823c5633e530b167d71c47ad9549df05943f99421e17475c4d4f08dedf6f3205189ea9c8d9ed14b0de82b44cbdd58757a27c68383fba597761f9e862e08de15b1e44c3db1badbde76980ee39e699629f6fcfef32d36b3393da2ca5a81f959c8b0f1b801b5fa4c47ca39591e612a2435c5bafd77a5c7ab74359210906f47533b1879e2a5af5864d961c8146e25dac772555e042a887261419ab8c9f6f625625481da5b93526a131f37b534a0050a8a462b33f20a7e94b891530b19bf654ee9534c9a8361d03635d8d27d46be7bf84781ad0d42d1e7c4854a49ba1ba458262fe5ea19021b935a6949492d70b605e151989ef2641b2bf81ec4b92020fc7074c2a63229d51a944186a28895e8ea95292c2f872bb21a3149399e23ccd8e2fc4f17a46b59c282c51b58d00266a5c16b1ce350d5485e8d8016dd0a50a5984cc948154cd5ce7cda0ee0ab1d7251bdc70a1785b8e9103917f4b917ab2b494f3483389a2f9237541849ed3bd565cffac9e756db56ef5e23495bc771e88bffa8707ceea5c09becadd059ab889d1df7e887b71a9e6c238378fbe0c3630386616363f207b16c3270d39acded511529992f4e598789121d316135810636baade8a28edc66bbf5ede3f404a70b47d35988be706b4eaa03023a39093d583cd4cd8bf4c74341a028c19d60da31b6a7a034c081a2b030feb3cd2f03d0faabffb58e3fc36c006cfb92947a7de5ba87476c1b051e18283c03e9c6e5a5c3c2777d9a0757372379664e82f8485824fedb70a4bc4e356edd1b5ce0fb6e41de0171621b84fafa00189afa8a6a900b14c70758f7aa4fb82400e0d18ab3cd7e48acfd489cab0e72e719f79a07d066c531a891c55291f2245dbbee44e52b1dfc8727aae387ab9e71994a3854e1add73d9a7965c775521c2f540842276dd309e2f6a341e7f0f37f22bb6627b6e9cb25ba24c6c4f4eb9f5e7622d88da1984e29c5da001039c44042b59351406a41336dd772d497d3fc8aac41172eb5aa6417fe422ec7c150b96b0454ee331247cb1538aeff3eca2d50e53d6d13170a76a0049ea0c05904a6390ed14ce7491e97f754c5222dac4b6118ba381f552e73ea8491e3b7ac949569b569cf2d29a80410e065b5cc4a466bb04eb7a15f596792e8490ba7002ec361571af5d8f57675c956449470a2f9955407367e409a232899553120a277db863e9a82ddabae87b789145ba898df3c28b96fbe3014cd085c6e60ee8831701036d99c5425d58e8bcc9fd9271d46aec1eb955130102eaaab44e0770c30b2b127efb0e5f8a3f7a0ca34ec9984a46011bc26bfde0c0819bb54706b565638b7542dc4b8bf8098dc01f161b3b129618b59aded33cb59ce9189a6762dbae5b0d34b71c8dbf: +51cf868f820eeda0dbd10180f777e6065c93a483c58a778b67e7d842302fb767ab088f502fbcf2150e4846b34d2c8097ff013c02a8b97cfcf2b95a1c72df3e24:ab088f502fbcf2150e4846b34d2c8097ff013c02a8b97cfcf2b95a1c72df3e24:7c2d8ee82d9abf8aa9c724c75b90990473f131763fe93b30cb04723588621da2a327928b22649fa062cdeabd77761538b2709b8fb7a2006e503509134c929c3011e1d728a57a4e175198075e214253f3f30e01b6e04eabd4de06789558e698b186efe34b32129568b3e8d0d7ea3ff00b3f25a42236893aa8a41b674a0ab5f41e7b28cf5a7cb765e18ead6de6a353a7824a3c49786038d6f4937f3264d6ccf0c0a2465bb693e52b3d1e6eb9ae4cb65d09cff54842e85362857a59f7198a688a3df38513cdd61e21dfd859142c8344a3b8b2a7c7db170f39f87ca3ff8ed427962b2b1a14d122fa2d5aea2a6640117dd258fa0fc54ac6e940bc16d211ec9adf914ab16578f521f655d2127e79e871bf7fa7544719d58ed847850cb27b99eb8f29b16cdcc28b15c1259ab4d589705a406688f605a2ebf58051c43a77c4e01fd6f749d32db4e89f263c2c16de181f0e6bdd0a6a64ffe6f1829444096d9f3e2b67e4bb006650b5929d1f82eb11bbed24e8f1018a7384605a3cf29ab598337939c76a3be861e483c5805ec3cee45e3424847a08558dcc99499fb9382acae56cdc87fbd5b26ff94c86f2e108794383501c8b33366850a76a0dfc0a7cd789a03f01a3e9d9e9ae39fd7245dc29299d24f3b4b167caccd223a99b6b20a3b673dc5f7466d0b2f815098a497ccaf80420168eddbf4da57b8666e9d33c48eb304b4cfcf457cd7659543f6d1e661890f562b43b8b6d1c4dcc077b60bfa533ffab928dbfd955dc5116d770950b690e2106ad52d42c31c22b8848894332b5c699e5c331fb381e5812e7526fdf4b8aa2daaa2ca2cfb9c92111b61cbc3d1eef6c8c6737f05588f04467db8330843acc98dc1a16fbd9d9d94bd8bfde26c3f71dee72b50910c36b240f802a61ca16372f6ffaadb2be4e853c5ed69a3d1f6c7b2de513c53a3fdd0a676f83d09d5c51176047d9200716bf22bae45fe01b3e0c2c51c16e46ad0637f79f9b4d83867704feda9f227831dea263399ca2771a4e78b4df8ac0de6a941eab370b1fdb47daf6642aaeaa63170fa9b3d1e1628f7c4e7cf0ea8b8a8e518cbacef9ade84df032484847ffb61bbd07e8727cc4c25da577b264519b4999fa7c0bc323d4f3f9739f780b9b2c23c77855ee5f6dcc401544d6b64b2770158fdc6c12f4d89beb044e0e85ac7a68d42917b1345114b9a672d1231b2c6c0f969f203531e71bbb4005b103a7dc3a58b5b824a7e01b6eb9f496dfa64d64d8c6777f53aa58d5da046d726f55454c88b6d7d4ab0d2198a89709f118a6b32460b9ebceff3fddc605da77ef3d1ba30fecf07be2f5313f4ee635af5e9561d877e99c:e15342a11caf892895e466228863d083b0692f010610748c23df2f11d29475bafce927cafe7f07efb8c347ed5663e73bea89531cedc0c348e79b6e58a75749077c2d8ee82d9abf8aa9c724c75b90990473f131763fe93b30cb04723588621da2a327928b22649fa062cdeabd77761538b2709b8fb7a2006e503509134c929c3011e1d728a57a4e175198075e214253f3f30e01b6e04eabd4de06789558e698b186efe34b32129568b3e8d0d7ea3ff00b3f25a42236893aa8a41b674a0ab5f41e7b28cf5a7cb765e18ead6de6a353a7824a3c49786038d6f4937f3264d6ccf0c0a2465bb693e52b3d1e6eb9ae4cb65d09cff54842e85362857a59f7198a688a3df38513cdd61e21dfd859142c8344a3b8b2a7c7db170f39f87ca3ff8ed427962b2b1a14d122fa2d5aea2a6640117dd258fa0fc54ac6e940bc16d211ec9adf914ab16578f521f655d2127e79e871bf7fa7544719d58ed847850cb27b99eb8f29b16cdcc28b15c1259ab4d589705a406688f605a2ebf58051c43a77c4e01fd6f749d32db4e89f263c2c16de181f0e6bdd0a6a64ffe6f1829444096d9f3e2b67e4bb006650b5929d1f82eb11bbed24e8f1018a7384605a3cf29ab598337939c76a3be861e483c5805ec3cee45e3424847a08558dcc99499fb9382acae56cdc87fbd5b26ff94c86f2e108794383501c8b33366850a76a0dfc0a7cd789a03f01a3e9d9e9ae39fd7245dc29299d24f3b4b167caccd223a99b6b20a3b673dc5f7466d0b2f815098a497ccaf80420168eddbf4da57b8666e9d33c48eb304b4cfcf457cd7659543f6d1e661890f562b43b8b6d1c4dcc077b60bfa533ffab928dbfd955dc5116d770950b690e2106ad52d42c31c22b8848894332b5c699e5c331fb381e5812e7526fdf4b8aa2daaa2ca2cfb9c92111b61cbc3d1eef6c8c6737f05588f04467db8330843acc98dc1a16fbd9d9d94bd8bfde26c3f71dee72b50910c36b240f802a61ca16372f6ffaadb2be4e853c5ed69a3d1f6c7b2de513c53a3fdd0a676f83d09d5c51176047d9200716bf22bae45fe01b3e0c2c51c16e46ad0637f79f9b4d83867704feda9f227831dea263399ca2771a4e78b4df8ac0de6a941eab370b1fdb47daf6642aaeaa63170fa9b3d1e1628f7c4e7cf0ea8b8a8e518cbacef9ade84df032484847ffb61bbd07e8727cc4c25da577b264519b4999fa7c0bc323d4f3f9739f780b9b2c23c77855ee5f6dcc401544d6b64b2770158fdc6c12f4d89beb044e0e85ac7a68d42917b1345114b9a672d1231b2c6c0f969f203531e71bbb4005b103a7dc3a58b5b824a7e01b6eb9f496dfa64d64d8c6777f53aa58d5da046d726f55454c88b6d7d4ab0d2198a89709f118a6b32460b9ebceff3fddc605da77ef3d1ba30fecf07be2f5313f4ee635af5e9561d877e99c: +543d5f1d4a6e1029b1914138fb1f4659e69456557207406688a2035cbbb2a68a3c83790c3b4553deae4f843b501d26f6167093ee54e279759ffad8cbc061e720:3c83790c3b4553deae4f843b501d26f6167093ee54e279759ffad8cbc061e720:fe0057f062fc871324b8bd5d427e9a5276231bd309907e5881d7ae53b1f370c2a43302a16510b46064a30736bac90951f1d9881af62c701483ebb9272ad77212eeb5fcbc7ec228d969f8902732113b98e3bf82dfeadd0de5e765d2870b12d1f9b5a28297c9fdd1495cf87789196a7d644eecd93587dbf20c28eb09da286603c582d2129a657db2d17add3558dde029ce27b88352de3f95aba17e1ed1913722db08a795dfbb70d62a8802724cb0f535f848d052aa3dde9166963a8041fccc4e60bfb11de2bf286eb602a4af842f4d1a340d78bbbcb2857f0c308f44bb101e7bc8b741d506094e27bbafa72428ef666ea6ea16f799b4ee58278f045974d86dc72cf5260d96f9c09b2f1181e1a4500f9283dc677f384ff64e51e89f76582020326c388c08a0fd00de73d5d49c06c0c684191a264fff726d872dc3ae496c7b478cfc61b51714192f76463e3d0aab410ea115e8befedb997ddd169921b3207ea66c1f59450b7623129fd1e2dd3da8f5206391171338ea0ec8ef3c59ed8afc69f3865c29a0723a9bbe95a742681ef9857e81abc80c92d2a718a804f5304fef3c63d799a6ef8782a7db46681d0de3506446982267b2152b0c321869e23cce8c4ebebeaf4aa1ebe9283b692605260ff621b03c10822aa5f6d03bdef49c462a68d471e849e164e3874f6e9f6cb3b5f293eb38ae5245a159ec4261a9bf6b5f7b7615fd339ea12733113ce767f883ae6675417fc770b50bd60e6f20addb29c1f7506233e32a7ebfadabff98cfd09b2b3bbd3eae0069548b9d8987af46ca98eb095bacbd874724ba10f3633aa08ab6ec26494ddf6854309b55d43bdbd29a7556f12dfb23cd0db4eb3937a65c4aed96e87b346555f9fc6897943a0faee65ccf394bd89b381beece25d1ba68f8fe32c23b3354f5be7e3ea3c0dec0f7ec2dd83f92b73058892b638d4c3b7242bb8f55bf087ba45a190a698bae675e0cd5e8446f2b21aeb63d2caea0f679a837e79357308d9f0b8af31f9d08008c39ee8d347528713c8850017a7f4ab98a35c7531940fa7621e67203ee782db3a2faa30f3aa850a5ff7aaed84c00ffd214f2c9261735fac3259d50e03c2652505279d91251927de5e56a8b9064ccf9f45dcbef46e1189ced2bc79e6ff652e69097ace5568bb2d5bef3ce21a25b3f79ee275ea34e621380566d704cd93f24dd9020932cc05218c23b5b22fffa7e99ee7fe457876a5e3364c9a8e8b049cfa20969774f506d1996cbe6ef5a37793ecdb04cfdeaed7dcf79ab278474dd770822d4b36fc68e4b2dd661ef99de01de6eec57fa573ede10fbbd5ac6fd6cd8bb4eee509dbb4610374401:55201194026fd6448b1d52f83ed20ac284e7e77fa92d5295d33825cea3aca47ec7aaca2fc08679f9acfcedb376fda4619be3272c7445e8705c306141cde16c0ffe0057f062fc871324b8bd5d427e9a5276231bd309907e5881d7ae53b1f370c2a43302a16510b46064a30736bac90951f1d9881af62c701483ebb9272ad77212eeb5fcbc7ec228d969f8902732113b98e3bf82dfeadd0de5e765d2870b12d1f9b5a28297c9fdd1495cf87789196a7d644eecd93587dbf20c28eb09da286603c582d2129a657db2d17add3558dde029ce27b88352de3f95aba17e1ed1913722db08a795dfbb70d62a8802724cb0f535f848d052aa3dde9166963a8041fccc4e60bfb11de2bf286eb602a4af842f4d1a340d78bbbcb2857f0c308f44bb101e7bc8b741d506094e27bbafa72428ef666ea6ea16f799b4ee58278f045974d86dc72cf5260d96f9c09b2f1181e1a4500f9283dc677f384ff64e51e89f76582020326c388c08a0fd00de73d5d49c06c0c684191a264fff726d872dc3ae496c7b478cfc61b51714192f76463e3d0aab410ea115e8befedb997ddd169921b3207ea66c1f59450b7623129fd1e2dd3da8f5206391171338ea0ec8ef3c59ed8afc69f3865c29a0723a9bbe95a742681ef9857e81abc80c92d2a718a804f5304fef3c63d799a6ef8782a7db46681d0de3506446982267b2152b0c321869e23cce8c4ebebeaf4aa1ebe9283b692605260ff621b03c10822aa5f6d03bdef49c462a68d471e849e164e3874f6e9f6cb3b5f293eb38ae5245a159ec4261a9bf6b5f7b7615fd339ea12733113ce767f883ae6675417fc770b50bd60e6f20addb29c1f7506233e32a7ebfadabff98cfd09b2b3bbd3eae0069548b9d8987af46ca98eb095bacbd874724ba10f3633aa08ab6ec26494ddf6854309b55d43bdbd29a7556f12dfb23cd0db4eb3937a65c4aed96e87b346555f9fc6897943a0faee65ccf394bd89b381beece25d1ba68f8fe32c23b3354f5be7e3ea3c0dec0f7ec2dd83f92b73058892b638d4c3b7242bb8f55bf087ba45a190a698bae675e0cd5e8446f2b21aeb63d2caea0f679a837e79357308d9f0b8af31f9d08008c39ee8d347528713c8850017a7f4ab98a35c7531940fa7621e67203ee782db3a2faa30f3aa850a5ff7aaed84c00ffd214f2c9261735fac3259d50e03c2652505279d91251927de5e56a8b9064ccf9f45dcbef46e1189ced2bc79e6ff652e69097ace5568bb2d5bef3ce21a25b3f79ee275ea34e621380566d704cd93f24dd9020932cc05218c23b5b22fffa7e99ee7fe457876a5e3364c9a8e8b049cfa20969774f506d1996cbe6ef5a37793ecdb04cfdeaed7dcf79ab278474dd770822d4b36fc68e4b2dd661ef99de01de6eec57fa573ede10fbbd5ac6fd6cd8bb4eee509dbb4610374401: +f8d257fdfcf99796f8ce4d8aade3b225a53c26feecef395b9561d9d587f5a33cf66bd4877df78aec04ca7e77732899de06777e698629f29969f8fa9c2f47ab9e:f66bd4877df78aec04ca7e77732899de06777e698629f29969f8fa9c2f47ab9e:233e1ef901abcb69fb486085d8db0233ff78f37b136f0afe24f7dac1944c3678e74fed58a1ad54835b7dbcb46fff6c3524312273300b6d878a93e0608a4abaca4e3194722bb9e23d17194d8667b84f2db038c24efb8f53409cf5594fddb8bcd61f74cf0726b51c651ce01eb66a59b455f7d8a7d60d3927e0c6c54b138e01925371d2d9d962aa982f5e6085280cc05f356993911fd2039dfc342117970291381d82027db36c799100057d9352b2cd879d9c82af734b7fa297d21149c978aa5e125b20372a9b2e0ed357337efaea1391f3b9ef11e3e5135bb70bdbe32a9bdb7c3c42d5d57cc8dab6811628a01089495cb8a4a76a48296cd8dfafc005ad49d70bb19faca2084a1b6f5e48d23c03fbcf6f106db770f07c33e8e7f4757da904a44dd0e738f3d5733a329375ced74f3c42bfcdbb910100455d6aa7d2e3e3aaa58a829630d376b0b466dc85aac48fe269946a7bc72d91eb37ded2f4a77c684be01093fd12de9d9d83199ccc50959a48d6e9a41427566092f04a0f95ca52372e0762b966ce6232055a4fd757c61b8bad83baef91a3c2772fb32ead8f591ac1e02bbf90a7f6c39079b86fb814cc242e980f0b8b1a2cecb8e6d4e8a5211bf8babf38e829ab9883608bd6d59ea5e836a9b4a4fbeded1bea2ffe977e8cf3615ca4a50fea1f05f1fe53c8eac500323e1f52a806831539957988d79acc7b54f7d02b480c469fd69540fea4bdd68cbdc68cf9c7872fd792591b01e9d9902d8a614f4c21823f23508ffd49ff218bea922ec141eff60da177ccad7d7b9d444f3b03458115f116cc6e37625c39cbadf09362f31d33f4c13c33b6292007f2cafd194f62c643e7a25571564febad7d33e364b633d008b090d7a091358bc69c567b9522b5c1cd01218d38529aebb03d9c2a5eb2285a7176f98c28036f21e19e92b406e94895fa281b35228fbf76e73e1758af1b434a4df98e8cc556b9d83f6b0b7ff52c680f65efe4e00c59b46ce593bf98899805d02b9165b7429849e73953770ae393e4f1f97cb90cd6159cc93952ae8a4d3d56a9a95df7cfabacd4d030d736ea454dfa4b4aed1bcd885d2fbea5ffa2cf2927c137c86be4fe016412628fe7a0a0f02b6b6a9a2168932b943ff8b28dd587e77287790aaaa69a98506c764e6f5ba6338c09f382e1b987d99f14a3e1958cb62ae6705a577f9ffc67306401128741a8d0af03c0aaaf6af06bd88ee4b0af6703e0ea60b0409ace24572fb386e07e9c22c9686bdc66d4fcf3c7461d3833a4c3013243607d4d158217187326df51725a6bc5116e990bef8a5a9579600207206bfc3a6dcf0746ef756fd939e187f668750716c0:9235d44807869816e28e42c81c801ffb121de826c0d33dcc4a4e1c932d5228b639bb294e16090a93d1f6904a7004222fda0a55446d9901c72340007bb45ae103233e1ef901abcb69fb486085d8db0233ff78f37b136f0afe24f7dac1944c3678e74fed58a1ad54835b7dbcb46fff6c3524312273300b6d878a93e0608a4abaca4e3194722bb9e23d17194d8667b84f2db038c24efb8f53409cf5594fddb8bcd61f74cf0726b51c651ce01eb66a59b455f7d8a7d60d3927e0c6c54b138e01925371d2d9d962aa982f5e6085280cc05f356993911fd2039dfc342117970291381d82027db36c799100057d9352b2cd879d9c82af734b7fa297d21149c978aa5e125b20372a9b2e0ed357337efaea1391f3b9ef11e3e5135bb70bdbe32a9bdb7c3c42d5d57cc8dab6811628a01089495cb8a4a76a48296cd8dfafc005ad49d70bb19faca2084a1b6f5e48d23c03fbcf6f106db770f07c33e8e7f4757da904a44dd0e738f3d5733a329375ced74f3c42bfcdbb910100455d6aa7d2e3e3aaa58a829630d376b0b466dc85aac48fe269946a7bc72d91eb37ded2f4a77c684be01093fd12de9d9d83199ccc50959a48d6e9a41427566092f04a0f95ca52372e0762b966ce6232055a4fd757c61b8bad83baef91a3c2772fb32ead8f591ac1e02bbf90a7f6c39079b86fb814cc242e980f0b8b1a2cecb8e6d4e8a5211bf8babf38e829ab9883608bd6d59ea5e836a9b4a4fbeded1bea2ffe977e8cf3615ca4a50fea1f05f1fe53c8eac500323e1f52a806831539957988d79acc7b54f7d02b480c469fd69540fea4bdd68cbdc68cf9c7872fd792591b01e9d9902d8a614f4c21823f23508ffd49ff218bea922ec141eff60da177ccad7d7b9d444f3b03458115f116cc6e37625c39cbadf09362f31d33f4c13c33b6292007f2cafd194f62c643e7a25571564febad7d33e364b633d008b090d7a091358bc69c567b9522b5c1cd01218d38529aebb03d9c2a5eb2285a7176f98c28036f21e19e92b406e94895fa281b35228fbf76e73e1758af1b434a4df98e8cc556b9d83f6b0b7ff52c680f65efe4e00c59b46ce593bf98899805d02b9165b7429849e73953770ae393e4f1f97cb90cd6159cc93952ae8a4d3d56a9a95df7cfabacd4d030d736ea454dfa4b4aed1bcd885d2fbea5ffa2cf2927c137c86be4fe016412628fe7a0a0f02b6b6a9a2168932b943ff8b28dd587e77287790aaaa69a98506c764e6f5ba6338c09f382e1b987d99f14a3e1958cb62ae6705a577f9ffc67306401128741a8d0af03c0aaaf6af06bd88ee4b0af6703e0ea60b0409ace24572fb386e07e9c22c9686bdc66d4fcf3c7461d3833a4c3013243607d4d158217187326df51725a6bc5116e990bef8a5a9579600207206bfc3a6dcf0746ef756fd939e187f668750716c0: +8da9f54da0b6a5a38985b88b71339dc7384cfd5a60bee159c394c22363bc7edd1ac1a8edeb217ae9b3a3de530d24d83e11fb6538cc709b52994fa9c3f1faddc8:1ac1a8edeb217ae9b3a3de530d24d83e11fb6538cc709b52994fa9c3f1faddc8:bd53baba6657d8db8becae6eabffa52b015a5a05fdd2e070647de96f9ca4dd219fe0da608fa0447f46d17c9a358244cd5408596582ccd3cdd0151d6f0923e63d166837845f273fca7af6c89d8d5246175c2167fbb9c2ebf6a7595491f97a9713b02bdf413e209ab22db7dd2b37fc49436918ccebe5746bc64ddd6dce19ec4558c40e0896e21909280cba06d16b72f31d987685d071db8155e99ebcc6c821d92683fdcee08668a5ed58f839d9edafb9f1459d48de8e1bb6f7ce84da0be411c8f7be1b9a24bc5d0fe3a96b02350750a5cb250b49555a487672bdff3c3f784e3fb63c1c97ba6ae43a10e196f188dcc635e214e29df509e5608a5367aa2800c1a96ad936a9e2a579b8592ec13a359336a62788c3ec55c0ffd6a7d49ecb7c682efa308199f708d79d0e8856366d269fab24eb1a075c96c881cab89708ced279230d3f1f3ee173672283eb8d8a824038f648ac437275d75a0e15f71ce56a8aeb771f07a7f32afc9d612a13bd83b7f93990d38fc3f4f4ab8aa9430c65736eb64b16806e995c1ce9dcf4c5544e7b3d01541c5721bb4be4cf0ae382a0c1b169d8e418defd559442acea14b00d705bcfa78be0756a8f377cbf183bf25906874115d8ce4c3ba874102938a4ea16036d91a42c5f8f188655cacb00c88e3a68508816e5e1c31d27180bbba9518a9630726d7d047dd8d2c0401219e14e6badfc9b95b77a6ace9bea71d1b47c218903a115ad029e7f2039ea23cfd1fa6a44d089fcacb678153d674c0e081764995595cb6894895f08e25b984e3a694c92fc7cbe0ffc4697230bcb0ca408c2d7085c11badeb3e6c0e75e6c498db1bec1ed2a3e2445c32b1913a89500f69e7f23f41d62e5c189f39a056cb9fc68a452023a333f75220cb9b94484acac6bbc671f59ffa072b71a1896a1b306e9dc558da0ec20f373e4c355e0c5eccbbf1350c8c07914892c454defcefb717be34d087aeb244a86ff49a6c470afb36b40fe8b71c505a4ff7af2984c65284938ec0e405231521f4810147dc4e373fdab6647b86f79827502fd087e27f310d6b312363113842155c57a32ba03b6cff965530bd795fc292e241c9b6ca085140032efe746f37d57e958421184b8a4c1a6a1e37d45e077319833068ddcb89d38c75beba1a6e8e4052888ec18162dd6ff0c59a2fd0b47f3119195680ffccddf5f76b35f022aa66bd1ac56f1ae333e9b9d046f0b79a892ecc4f8d2f31e17536c4c62a9b5e063dd2dce37d3d0acb42023eb2f2ea329d3876c2386a02276fff9d308abbadb7274301a6962ecaeeb20bef5e36afffc387ca8e185e562b865b49204c17b2a70119b061c29c0fe9004:f6dcc2d27baf16c4f4817f87499157d3ac1f84ed398a5e8b0d50f42edd7385cf06337a0236109970b79ca09d7c9831c876a802799421c2abd07587f5eb66160fbd53baba6657d8db8becae6eabffa52b015a5a05fdd2e070647de96f9ca4dd219fe0da608fa0447f46d17c9a358244cd5408596582ccd3cdd0151d6f0923e63d166837845f273fca7af6c89d8d5246175c2167fbb9c2ebf6a7595491f97a9713b02bdf413e209ab22db7dd2b37fc49436918ccebe5746bc64ddd6dce19ec4558c40e0896e21909280cba06d16b72f31d987685d071db8155e99ebcc6c821d92683fdcee08668a5ed58f839d9edafb9f1459d48de8e1bb6f7ce84da0be411c8f7be1b9a24bc5d0fe3a96b02350750a5cb250b49555a487672bdff3c3f784e3fb63c1c97ba6ae43a10e196f188dcc635e214e29df509e5608a5367aa2800c1a96ad936a9e2a579b8592ec13a359336a62788c3ec55c0ffd6a7d49ecb7c682efa308199f708d79d0e8856366d269fab24eb1a075c96c881cab89708ced279230d3f1f3ee173672283eb8d8a824038f648ac437275d75a0e15f71ce56a8aeb771f07a7f32afc9d612a13bd83b7f93990d38fc3f4f4ab8aa9430c65736eb64b16806e995c1ce9dcf4c5544e7b3d01541c5721bb4be4cf0ae382a0c1b169d8e418defd559442acea14b00d705bcfa78be0756a8f377cbf183bf25906874115d8ce4c3ba874102938a4ea16036d91a42c5f8f188655cacb00c88e3a68508816e5e1c31d27180bbba9518a9630726d7d047dd8d2c0401219e14e6badfc9b95b77a6ace9bea71d1b47c218903a115ad029e7f2039ea23cfd1fa6a44d089fcacb678153d674c0e081764995595cb6894895f08e25b984e3a694c92fc7cbe0ffc4697230bcb0ca408c2d7085c11badeb3e6c0e75e6c498db1bec1ed2a3e2445c32b1913a89500f69e7f23f41d62e5c189f39a056cb9fc68a452023a333f75220cb9b94484acac6bbc671f59ffa072b71a1896a1b306e9dc558da0ec20f373e4c355e0c5eccbbf1350c8c07914892c454defcefb717be34d087aeb244a86ff49a6c470afb36b40fe8b71c505a4ff7af2984c65284938ec0e405231521f4810147dc4e373fdab6647b86f79827502fd087e27f310d6b312363113842155c57a32ba03b6cff965530bd795fc292e241c9b6ca085140032efe746f37d57e958421184b8a4c1a6a1e37d45e077319833068ddcb89d38c75beba1a6e8e4052888ec18162dd6ff0c59a2fd0b47f3119195680ffccddf5f76b35f022aa66bd1ac56f1ae333e9b9d046f0b79a892ecc4f8d2f31e17536c4c62a9b5e063dd2dce37d3d0acb42023eb2f2ea329d3876c2386a02276fff9d308abbadb7274301a6962ecaeeb20bef5e36afffc387ca8e185e562b865b49204c17b2a70119b061c29c0fe9004: +7a2efd390124d3fbefc54a577106e74b2d1f5dd504c050d0d359e53c0f5c872befc303d922e88f70f38c1a2b920684ef663034a1b23ab9d69b6ce8ed8706f7f7:efc303d922e88f70f38c1a2b920684ef663034a1b23ab9d69b6ce8ed8706f7f7:238fbe9fb35c725c6c1f329248094bc7da1b273edc7699a7e3452b5788d87867defc40a00590e87580d2c0275df5abcce0e1aaa18290bf93b44e5ad9d760dd21f1aaca383178f9fff9130f73187ba9d31ea3604a1cdf3911e14377a0ce8b44189adaa7aac23b6cdc7a425b7ea745508455704f9ad7a8952718c398b421b6e09cb78cb52a1814ee2e9639ec68d361f0a32041d6e7425b4bb33c70196e2400eb812db8506c9f3245bd988fbc891be20cb0691559fc916b57ff96c9b14489e0993cb739a39da246d01a6ebd07583581f250bf480bc44b2c3391542d595e4d399490195f8445df638f34698f1a96ed27b3533e3eb67e8f865865fa9555ed34df11157641a00e6d60cf623fec1a92b87a15d765185fd9055acb38d75c99db4fce7b0e39fdc3f851daf65c7a33f464816931839fefe8e58d9ab742b861873fd229189e59cd4ce8239fc9543f539d2d296114266ea8c6fd152ac6b342e5d1a557ab35cac51e2d1212ee317c4d26716829e25746df17d2a622c243f3ecbb65f57ab0f4270e3d0668a962502245b94c06df0c5e39e353aa842ea080cf502708b1dda2d001824de458d37762af2cdfd5a6d3f35e08a18e14aa7a642c51e4047e637517846df646d07336fb172434e0883e2b77d8ed1c52c9cc636a56a19e57a5f161b92d1dcbfa496f344ae6d4dfdc9569ade457a49091362e5a0cdd81b3753243fdac30a2d27ea026a5e601441ecd5537a7201bdcb7fd58b240d0229fdd9babf112b5694812250e768d7c0ce6ca565ad06ab8f78a5c9950eef538726f576c4bd2e0755c7f983929372a5fe11c73f9e1fa453ab54b5817aad3596756127d84e3119453e8825bb8460d851f1f7e4a2838a2be786b233504a691db0fa22a5f41fe3fd3c9b538b04f409e091809486b28ad0deda7b38a42cefc48de7d8679c03bf877238511820d0770cc8d7b4172377823a0b99149abb8918bfb66d5abfcd10060b05cb4f239dd4281d93483504b731eaf5add515f1f3c3b52b4e3bdaf976a17b3c9ec61bfc8e77116715804532cf2dbf20b7ba5ead85afb952beec2fccff85ff5072ba4ed6b5438ab1520c6ef4b0b26f12e84aedd65ce5c7bbe6acb6772f593a6b4f81ddd9d502746505047c812a0067afceb8dc9bff30d4087f8d5a375eca605a0622784d8fea278cd1a5241ad4b3f1b914f74f73bc36ee7cc82d96efda63a3b6799730f20656c12356c79069b2be6f9b77be101983118823ea66e7c2098fbc72fc9c039dfe30f2daba13c3bdefb8a780beb5cb1b6c286a6b3ef48fd15c66c045ba29f0970413b988d0ea004ab84c93919f04f9bf8caf58c4eb478f358ef8b68:c28b34804805d81f7aef784970670edaa417232bcc67da9b51e9c3d74fc4991bde97a06bd53fa00bb440fd5616cd0de6e9b0d19f2f68bfaf9d4c5172c4e5200a238fbe9fb35c725c6c1f329248094bc7da1b273edc7699a7e3452b5788d87867defc40a00590e87580d2c0275df5abcce0e1aaa18290bf93b44e5ad9d760dd21f1aaca383178f9fff9130f73187ba9d31ea3604a1cdf3911e14377a0ce8b44189adaa7aac23b6cdc7a425b7ea745508455704f9ad7a8952718c398b421b6e09cb78cb52a1814ee2e9639ec68d361f0a32041d6e7425b4bb33c70196e2400eb812db8506c9f3245bd988fbc891be20cb0691559fc916b57ff96c9b14489e0993cb739a39da246d01a6ebd07583581f250bf480bc44b2c3391542d595e4d399490195f8445df638f34698f1a96ed27b3533e3eb67e8f865865fa9555ed34df11157641a00e6d60cf623fec1a92b87a15d765185fd9055acb38d75c99db4fce7b0e39fdc3f851daf65c7a33f464816931839fefe8e58d9ab742b861873fd229189e59cd4ce8239fc9543f539d2d296114266ea8c6fd152ac6b342e5d1a557ab35cac51e2d1212ee317c4d26716829e25746df17d2a622c243f3ecbb65f57ab0f4270e3d0668a962502245b94c06df0c5e39e353aa842ea080cf502708b1dda2d001824de458d37762af2cdfd5a6d3f35e08a18e14aa7a642c51e4047e637517846df646d07336fb172434e0883e2b77d8ed1c52c9cc636a56a19e57a5f161b92d1dcbfa496f344ae6d4dfdc9569ade457a49091362e5a0cdd81b3753243fdac30a2d27ea026a5e601441ecd5537a7201bdcb7fd58b240d0229fdd9babf112b5694812250e768d7c0ce6ca565ad06ab8f78a5c9950eef538726f576c4bd2e0755c7f983929372a5fe11c73f9e1fa453ab54b5817aad3596756127d84e3119453e8825bb8460d851f1f7e4a2838a2be786b233504a691db0fa22a5f41fe3fd3c9b538b04f409e091809486b28ad0deda7b38a42cefc48de7d8679c03bf877238511820d0770cc8d7b4172377823a0b99149abb8918bfb66d5abfcd10060b05cb4f239dd4281d93483504b731eaf5add515f1f3c3b52b4e3bdaf976a17b3c9ec61bfc8e77116715804532cf2dbf20b7ba5ead85afb952beec2fccff85ff5072ba4ed6b5438ab1520c6ef4b0b26f12e84aedd65ce5c7bbe6acb6772f593a6b4f81ddd9d502746505047c812a0067afceb8dc9bff30d4087f8d5a375eca605a0622784d8fea278cd1a5241ad4b3f1b914f74f73bc36ee7cc82d96efda63a3b6799730f20656c12356c79069b2be6f9b77be101983118823ea66e7c2098fbc72fc9c039dfe30f2daba13c3bdefb8a780beb5cb1b6c286a6b3ef48fd15c66c045ba29f0970413b988d0ea004ab84c93919f04f9bf8caf58c4eb478f358ef8b68: +ef3648cbe73402ab450cd6ec37e545d0cd2c999ecc1fa381a45c660e1853303252a1a45273872676582cc767339926414cd5d03d980cf629dda2d1a205e9830a:52a1a45273872676582cc767339926414cd5d03d980cf629dda2d1a205e9830a:6a93378f880cf0ffdb8e07d683cc352e2a1033c450baa0e8c4e16205fd0c02743b0ea064971d911e494713e6d94a02172ed014d506592ec6c70a9c97855246bf3d26f3cf74f493c1b697a0c414160c341412830985430806a0cb3c8475e7e5a973686c24d5ef1be7d0065096feb52eab260b5c488af09270de6decd33fea8589dd1021baf41e3f255fb8fa1916ebd8531eeb2f886bb3b3b04f9af6b276c35923f10d3a0af1e3f58b0d15aed165045f206f3f430abdff09449097e4b26d00a8f9f1e8f7a19f38588124c328ec43a9cfb43d3b2c6bdf6a3c1a102e0e333de1ac214a6df76dab44ba76bf035273b7ff6238ec82483b2d2d9d54291a72270f88933b786cac051d990b3cf740845fed3a67867d7c7c05674e7cb02ca5b7acdfba3852803a3d56c4d5c13bb1d7723467741eac1f2a7acd3a95f3a51610a486fc53a9851628c557d36d8a4cd37aae9c4174dbbdb6bd885cf40b382b8ded24a4522a278fef76c45319067e55286e7b08c603486e38a0acf47edef848ecbe942eceadb8636c833feb882a51a4595e24f607ca3c9da1b2404ce5c747e06264174d64504331709bef30055a5d695e09537c8f8c1e5a3a5db06599e319dfdb28729665273bf868955ea56427f08bacd777f179b302f3f68d04f3f3883d344955b655ddc6d5282b6d4df1d83630210e699178e11f722e9e5cda672892ae9b23e8169cbb548093b83e643eb499d937d28f3811597b6484102f0c8eb8c8888cdac229aebf89086a6495ac551f3bbdf2d1c9a93ed1d3a861eecd9eb839949bfbe6a4f6e6486ededab5229d532b58976d67512f9f71ae79b4145ca2fa497a165f110717666ca3340bbda8df1f82b8c054cf7654c35690168f96277d41c1c236b68198173c6e2b0a208ef83c02a43e473d90686ace75b5bd321b3f54281327a673cad4d4ad3040d48cf493ea231b3fec06f39932d7f70a38428df8fee4370532ae5fb112059f0a1d4fbe11b5a23bb87635429ed33ad1f6148014cbc160d93ca2592053a6e95378d6cd3f50db52be928e4092fe5d2b7095a9566864adfda59fd5f2fb6254bd5917b70fa14699665a37297c983c1bb9efe1c67b413dd1a8530cbf227297a8bbf93a8a02454e8e461ac212b846a70d5d56d6c3a6e65a03be0580219bddec88d4038911fd9574563f33e0f9e6044688d3dd48fac703869aa09d96efee7d6c68071d9922d5e8ed8dc40f1b798f1c580f7859cb84f1e14b5e74ddea16ad5cbeea4c48fbcffd29531accc0633938e3bcb2212676b61ef901e9c831a41774d8317ef35af76990bd24931fde6d407e22e763cf6a5790b23761908eee609637a2c11059:f670792942ec414428475638853c42728e86ba12bbe85948b39134cf6e2bd12813e0d83e51e657c90107ad93a4788aa38313fa962f6767a8f7805bde65ca420d6a93378f880cf0ffdb8e07d683cc352e2a1033c450baa0e8c4e16205fd0c02743b0ea064971d911e494713e6d94a02172ed014d506592ec6c70a9c97855246bf3d26f3cf74f493c1b697a0c414160c341412830985430806a0cb3c8475e7e5a973686c24d5ef1be7d0065096feb52eab260b5c488af09270de6decd33fea8589dd1021baf41e3f255fb8fa1916ebd8531eeb2f886bb3b3b04f9af6b276c35923f10d3a0af1e3f58b0d15aed165045f206f3f430abdff09449097e4b26d00a8f9f1e8f7a19f38588124c328ec43a9cfb43d3b2c6bdf6a3c1a102e0e333de1ac214a6df76dab44ba76bf035273b7ff6238ec82483b2d2d9d54291a72270f88933b786cac051d990b3cf740845fed3a67867d7c7c05674e7cb02ca5b7acdfba3852803a3d56c4d5c13bb1d7723467741eac1f2a7acd3a95f3a51610a486fc53a9851628c557d36d8a4cd37aae9c4174dbbdb6bd885cf40b382b8ded24a4522a278fef76c45319067e55286e7b08c603486e38a0acf47edef848ecbe942eceadb8636c833feb882a51a4595e24f607ca3c9da1b2404ce5c747e06264174d64504331709bef30055a5d695e09537c8f8c1e5a3a5db06599e319dfdb28729665273bf868955ea56427f08bacd777f179b302f3f68d04f3f3883d344955b655ddc6d5282b6d4df1d83630210e699178e11f722e9e5cda672892ae9b23e8169cbb548093b83e643eb499d937d28f3811597b6484102f0c8eb8c8888cdac229aebf89086a6495ac551f3bbdf2d1c9a93ed1d3a861eecd9eb839949bfbe6a4f6e6486ededab5229d532b58976d67512f9f71ae79b4145ca2fa497a165f110717666ca3340bbda8df1f82b8c054cf7654c35690168f96277d41c1c236b68198173c6e2b0a208ef83c02a43e473d90686ace75b5bd321b3f54281327a673cad4d4ad3040d48cf493ea231b3fec06f39932d7f70a38428df8fee4370532ae5fb112059f0a1d4fbe11b5a23bb87635429ed33ad1f6148014cbc160d93ca2592053a6e95378d6cd3f50db52be928e4092fe5d2b7095a9566864adfda59fd5f2fb6254bd5917b70fa14699665a37297c983c1bb9efe1c67b413dd1a8530cbf227297a8bbf93a8a02454e8e461ac212b846a70d5d56d6c3a6e65a03be0580219bddec88d4038911fd9574563f33e0f9e6044688d3dd48fac703869aa09d96efee7d6c68071d9922d5e8ed8dc40f1b798f1c580f7859cb84f1e14b5e74ddea16ad5cbeea4c48fbcffd29531accc0633938e3bcb2212676b61ef901e9c831a41774d8317ef35af76990bd24931fde6d407e22e763cf6a5790b23761908eee609637a2c11059: +2c8ee7fa9ba28ce7049676087b1163b241118d34cdf534aebe8ba59282a62ac2244c24f5ecb2dd1d1463512221325d73c81ee4d8adb8e01e23345caf9ca5353b:244c24f5ecb2dd1d1463512221325d73c81ee4d8adb8e01e23345caf9ca5353b:07669a8964f06380d2d4982cb6349de550b38cbc35db2ce572de887f663055736faac7ec07c32df60ee2598422bf37e7cf319ab3c9055608ca0c49757d7688e2013b8244f35404f45ac219497fe924de93a58d0f721aed7825f63b2667077c161eb4dd8bf7ddbdbbc19a9eae5978978d5aeb33a06dde18e612e05bdbcae0161aa2389038026429960dda3aa17e967d10773ca49735d8ecd7409be165c09bb0b509691d591c185c93cdeeae95352316544680523821458caccf528ac0454e4cddc6df0d1ea5f1f5cc1eeee05e19a2ad0b6a49736ed8552336fcfcadbd931b0b8e963be05c8e7037388552512b6823583e4a14384cef5029232d3e0bafe466351b4bb3f567545ab41fa46bffafa877a12b38a27abd64f77fbb4db466ff7f706504141d3add0d7372f16fe3d8c69f6299d93966d624a3070eadb8b49f29fab4844c7528a2a40b66987060695caa66b86718c51049acf4cfad3853edb492e368cbd073968ecaa4a1ee6046b5e826e901f4a808c0427c026fe2f7b2e1968667b53a7d36d702f2ff82c642d34919f8e9aaafe462a3d4f92692deac752be348f54cf089dd9cd051846b04b71931e19e89d125864bfa8948ace0eff33c45110569a0df3753f4c58d8002b5bc38102ec2ecf695fafa8916da9002387e44f96dabf8a982c53c9badbc37bde437f146f77d8f7baf12873196b0c36193af55f542d9968aed8069ab9fbcd6814ec472799ad09c730d41eddeca3b6269d31ab523b59547077376345b05f2ae69b4ee728c863d1bc04e9b7d3d0fcceb359cbd0858597af2d6063e253fae2c3f25034c33ed59edd2782868298681caf564db8d19366f34eae85ba73c1e2389b0dd78a9d2caa0f23c9ad5f6cd9f2c4ad5d58946adb718cb83da58e2fcbb6025bef4660a83e0af55e2030802932f2a896a096079b754c99f7b6423b45a86472e6723ef8896c4324c73d34ad58a4c01b38a97c73be5aa7f74a2fa4d0795af6dbfcd6d4eb442a7e204db4ecb1f8a226bdfa21b6eb171c9e59f1a192e23a76c352b04d8a80233985b77a29c020119ce651c7f4183d0e9c19fe18aa1020c25e4589dee34b901bdaf9ff9450c91af3c1db670b477e0ac2107696c9ec0d31d82647b68ea19499fe34a8e2e7b378dc7e75424e8c45645b0c2818e9f885a1c58415bba1c3f2a77549bdc4680dbcd1650c75d0f452a6b208591df0fa6e181da2abfab444621d5f77c2cd79556467246447a89f0aaacad660c9a925ebafbad43c478a3c850a27e01019d88a5b1dc81b5d2e9f740a028ccb72c1acf897ea5ad89e0f9448888d5b15ce6e42977f7a729155a284d118758ac65f3fbb98deb65:ca0bb6c12356555f6e1d8f5c8aa7b5e80cd280e8b1b9ba2ec9550f622f482c3a9ad3be03a4c9dfc10d0112b0189de94bffafd7034114e0e0d42c23f32dc8180707669a8964f06380d2d4982cb6349de550b38cbc35db2ce572de887f663055736faac7ec07c32df60ee2598422bf37e7cf319ab3c9055608ca0c49757d7688e2013b8244f35404f45ac219497fe924de93a58d0f721aed7825f63b2667077c161eb4dd8bf7ddbdbbc19a9eae5978978d5aeb33a06dde18e612e05bdbcae0161aa2389038026429960dda3aa17e967d10773ca49735d8ecd7409be165c09bb0b509691d591c185c93cdeeae95352316544680523821458caccf528ac0454e4cddc6df0d1ea5f1f5cc1eeee05e19a2ad0b6a49736ed8552336fcfcadbd931b0b8e963be05c8e7037388552512b6823583e4a14384cef5029232d3e0bafe466351b4bb3f567545ab41fa46bffafa877a12b38a27abd64f77fbb4db466ff7f706504141d3add0d7372f16fe3d8c69f6299d93966d624a3070eadb8b49f29fab4844c7528a2a40b66987060695caa66b86718c51049acf4cfad3853edb492e368cbd073968ecaa4a1ee6046b5e826e901f4a808c0427c026fe2f7b2e1968667b53a7d36d702f2ff82c642d34919f8e9aaafe462a3d4f92692deac752be348f54cf089dd9cd051846b04b71931e19e89d125864bfa8948ace0eff33c45110569a0df3753f4c58d8002b5bc38102ec2ecf695fafa8916da9002387e44f96dabf8a982c53c9badbc37bde437f146f77d8f7baf12873196b0c36193af55f542d9968aed8069ab9fbcd6814ec472799ad09c730d41eddeca3b6269d31ab523b59547077376345b05f2ae69b4ee728c863d1bc04e9b7d3d0fcceb359cbd0858597af2d6063e253fae2c3f25034c33ed59edd2782868298681caf564db8d19366f34eae85ba73c1e2389b0dd78a9d2caa0f23c9ad5f6cd9f2c4ad5d58946adb718cb83da58e2fcbb6025bef4660a83e0af55e2030802932f2a896a096079b754c99f7b6423b45a86472e6723ef8896c4324c73d34ad58a4c01b38a97c73be5aa7f74a2fa4d0795af6dbfcd6d4eb442a7e204db4ecb1f8a226bdfa21b6eb171c9e59f1a192e23a76c352b04d8a80233985b77a29c020119ce651c7f4183d0e9c19fe18aa1020c25e4589dee34b901bdaf9ff9450c91af3c1db670b477e0ac2107696c9ec0d31d82647b68ea19499fe34a8e2e7b378dc7e75424e8c45645b0c2818e9f885a1c58415bba1c3f2a77549bdc4680dbcd1650c75d0f452a6b208591df0fa6e181da2abfab444621d5f77c2cd79556467246447a89f0aaacad660c9a925ebafbad43c478a3c850a27e01019d88a5b1dc81b5d2e9f740a028ccb72c1acf897ea5ad89e0f9448888d5b15ce6e42977f7a729155a284d118758ac65f3fbb98deb65: +ddd8e9ff855679896a1397b427db8543abe8bb5dd122e3e302ccfce5fdc63e125a9a312e892a10b98d0dcdd28db3481c3c28add5ad0b194616da4a3df7660109:5a9a312e892a10b98d0dcdd28db3481c3c28add5ad0b194616da4a3df7660109:5e8feec509350d2ee7955b6f3e278278a4cb48ae72b46589e478be59747df5394a169f19e10db53202a6a52320b63a9a2b723fd31aa2db6d58c57332da3178bcf966c53abda35f12daef9edcf399e4a8c5f83d36f44a17d79846bfc96ce690194c219a29892f0367a7ab3844837879e3818db8d70c4e3fba4d28073464df2085951038fea43281b6b606dc8846b30b0763f2ca82bd5021f9117035a77bcd1075477c5f43214334d4d4cedd18f738d676c7b51a185ffa8d04101186a4952bbd8722f53990b60637041e114aeb8ce7111131d4db3fb4d35d995ad8d6650c0c4ccdce9dcc39db188a68785562740626b3ae3e023f40772ded876a45cbef74a058fd78c1a1ff2c2451e111ac1b4b7ee4c81cd76310d4d298fb3c49f5e6401908a630fa85db7471804fe990847f0f759472f593dcf02e113e15e564d30d5984692da55b0b7f2219c4ac1626511acf194dc7026eb9d367a4a2f1dfb515cb2c08da4fe595c85811120cba2ae7b66e67c91fb8fbcb9d99f13e50fd67464d90c8dcf6935523cf6d13fdd10635b9232b7a61dcec9a2b921061410df1de6a45167fb9f6f109dcc08891f203b274a3b68271b3f35e74f94bdced0c5ff8637173a176e7dacc81f2cdc4fb0d52d1dfa7f27b552fd8d87a1c55d6947fd92ed3253f9594db7df17a7fc6a75ecf4faa4d1e21b676b3727d77fbd43fa7be76bfb58fc309e5675f0a859cc47f37b1bf455932d824e86378de7a7e8c40ced22090044dbbf91c70e528eacdef3785ba3c69a3735af6709cd76aab28a6aca6e844974b10b3fb7b0986007a727c2c8fc95b25f31f146b36acd4c537074920aff247de0f179c13ca57790a6a71d62e23321ccc75b7f3b0afa0d03527c9114a7d4e30c1ace6d7712013dee66699af9c561c44ae6198ed39104e6061ae2c45a9a3c74b5d0fbc4a33e8dfe2a8acc9511ef7e6567133f9fe3554284a75a059a649dd24ec04a57730c6d2e9bf114ea58a8994abdb0c1943241572c79ead043ad1c8caaf5c9da53dd05522febc403354d62fe3ff93882df75fb29458d22e6996c35b69faaef2e0c4163886cb3c3d0f60e150d363d6db59fefc626b1bbb1e052a62414c4b7856d72093432b08f821bc784a5a6b0bc2649c2daa508658980d802291e734abaff06afbf2795e4e354d5221dc4f52cc96d6b8cf1808b1a8208db7daa80ab710c56a8b0e9cb8081dee93f5f015f07664463a3dccff7c8ad19923a97e39045bcc4dce0a73d49c56d5e937bd11e61823401c066206e313e60b47537e34704d7d3515559bb9d0532d028e28a57a879fd617cc61f7f776bd6a008cd4f812378ed37f394bb97e6e756da819:df849b7bd29745f8becdddf6c9baf094d7a98cc9338c344eca17fde075fda8d1543299f625982317db7b3c773b64f7d1f28692ac453b81d7ec7b7ec3417ace045e8feec509350d2ee7955b6f3e278278a4cb48ae72b46589e478be59747df5394a169f19e10db53202a6a52320b63a9a2b723fd31aa2db6d58c57332da3178bcf966c53abda35f12daef9edcf399e4a8c5f83d36f44a17d79846bfc96ce690194c219a29892f0367a7ab3844837879e3818db8d70c4e3fba4d28073464df2085951038fea43281b6b606dc8846b30b0763f2ca82bd5021f9117035a77bcd1075477c5f43214334d4d4cedd18f738d676c7b51a185ffa8d04101186a4952bbd8722f53990b60637041e114aeb8ce7111131d4db3fb4d35d995ad8d6650c0c4ccdce9dcc39db188a68785562740626b3ae3e023f40772ded876a45cbef74a058fd78c1a1ff2c2451e111ac1b4b7ee4c81cd76310d4d298fb3c49f5e6401908a630fa85db7471804fe990847f0f759472f593dcf02e113e15e564d30d5984692da55b0b7f2219c4ac1626511acf194dc7026eb9d367a4a2f1dfb515cb2c08da4fe595c85811120cba2ae7b66e67c91fb8fbcb9d99f13e50fd67464d90c8dcf6935523cf6d13fdd10635b9232b7a61dcec9a2b921061410df1de6a45167fb9f6f109dcc08891f203b274a3b68271b3f35e74f94bdced0c5ff8637173a176e7dacc81f2cdc4fb0d52d1dfa7f27b552fd8d87a1c55d6947fd92ed3253f9594db7df17a7fc6a75ecf4faa4d1e21b676b3727d77fbd43fa7be76bfb58fc309e5675f0a859cc47f37b1bf455932d824e86378de7a7e8c40ced22090044dbbf91c70e528eacdef3785ba3c69a3735af6709cd76aab28a6aca6e844974b10b3fb7b0986007a727c2c8fc95b25f31f146b36acd4c537074920aff247de0f179c13ca57790a6a71d62e23321ccc75b7f3b0afa0d03527c9114a7d4e30c1ace6d7712013dee66699af9c561c44ae6198ed39104e6061ae2c45a9a3c74b5d0fbc4a33e8dfe2a8acc9511ef7e6567133f9fe3554284a75a059a649dd24ec04a57730c6d2e9bf114ea58a8994abdb0c1943241572c79ead043ad1c8caaf5c9da53dd05522febc403354d62fe3ff93882df75fb29458d22e6996c35b69faaef2e0c4163886cb3c3d0f60e150d363d6db59fefc626b1bbb1e052a62414c4b7856d72093432b08f821bc784a5a6b0bc2649c2daa508658980d802291e734abaff06afbf2795e4e354d5221dc4f52cc96d6b8cf1808b1a8208db7daa80ab710c56a8b0e9cb8081dee93f5f015f07664463a3dccff7c8ad19923a97e39045bcc4dce0a73d49c56d5e937bd11e61823401c066206e313e60b47537e34704d7d3515559bb9d0532d028e28a57a879fd617cc61f7f776bd6a008cd4f812378ed37f394bb97e6e756da819: +a886f4d3f34e320ec6d5f4caa863f81477df772eff97e64a37a05f4211d190a8e9bc96c81e878110268b55def7ea4007a4ef9f54d383d5fb0f6d4343e1010f38:e9bc96c81e878110268b55def7ea4007a4ef9f54d383d5fb0f6d4343e1010f38:8b831b877bc3a99f613c89cda698b3759d643822b5a88faf3822ecb2ce98f671d7554321b24b74b4e30a663f7a5570ae917f479bda29894b1a8c028c9d193e4e7ac11916dd8e9c3f0ec0ef80bd27fdfeee80c170c78140b24c15271415acf75c26956a4d4bf99d40e861e9078320d097e1259e5ec17b583a95e52430dd8c008ed8c7dd1de1becdd1e6bfec4bf3347a22dd249f3ac307a2945e9137fa4a8c26c8021077239cb324816a8dad32b01ee34a08903098cb9c4245291b903c9627074095249e782813477032ba32ef041a07486eb4478c57b9d532269a4a47cb5e974df7e01096fbe4f1ccd4e663663487974c62cdd94d77716c8479d79f6b6a7d9c155988cf3902fb697424963ec4ec34ff2a35d742c4455a593bacffc4d9699ba7626c76cb1a616253751887f6ffe2be208c713df1ab636d722ea06c1c03a57f2cec0803866cca3335c28bf41c7def81acb38858dc10e59467208624967e2e22d9e5661bb945f9e0517687dc80f9b8fdecc8a97600b6c219a3b23a90b6d18aaace2c78400ff38c8c05967f544b6a606c71ac199eafd07eb5848df1657efb233fbabae63a05638191a0af7484a1bae1581375672c571e264f604225173a54a38dd62ae7130d05dd291ad12354de86a6e113e83f6d668516157b7967020dc6517d8cf42dd7b1a897fe1b4e04553ce26e299980aa5f7ce0179bf4954f01c2a23654e5e9731e1447347fa43aa8b2cbd6d4b2df93fa54af71e5028a6da8c71ef3c50c0de24dcaee785678e92aafabeb233b011f45c1064965085d2547050f21c652aa533afe918aa0f9bdaa2607b873ccd3dbd1d3a8cc62172ceb43b921ef6b25c06b0992e4df2b91e371b0ef2b3947388daec8ec6f7e3867d1f61072af590154fa619a07f87e02bddc7406314270af1c15e8ee88b39c01be602e4f0b52d9a0724e71eddd7fa9134169c5faab915979eea9362d0f1f9160268162dd38db02fcfb41350aa08e1e1409b2288db1fe4a0e586b5910f4de894bf9974f6a4983013a190e7a736d14ec54c3644a3ee958a5bdfbcb6297aba43af6c72746bb135410507d8fdde73a2a48b746f918bef9ed92c5be62dd5523fe14b16d6384ca46ef59b2185fe933383a2c7a9bf02da9d0fd8b0c7d7bde6b439f9960155e345d685d4dc3c71404d656811923aa3c47d4b09a0baef0a12e75b6439ba8135db15865874222cd7aa428f5ca5ce5140e22ff92697f37fc70b5b4c94d3314e6aa16b2146bca4fc94157951fc49245da53f6c43d1bebd894e31a1349884d711b55dbe778ffa727165cf7cb676435866c2d2cb839745ca40166a2f7cfc77a842468b51a8e76575fc9ddfb5f:abf283db1f80c54c583b499dbe20aa04248c1dce121f3911677813ac3e011fd159ad0bf76b1aa7cc7b14d7b550848688252acc7fece90487240c3d399dd343088b831b877bc3a99f613c89cda698b3759d643822b5a88faf3822ecb2ce98f671d7554321b24b74b4e30a663f7a5570ae917f479bda29894b1a8c028c9d193e4e7ac11916dd8e9c3f0ec0ef80bd27fdfeee80c170c78140b24c15271415acf75c26956a4d4bf99d40e861e9078320d097e1259e5ec17b583a95e52430dd8c008ed8c7dd1de1becdd1e6bfec4bf3347a22dd249f3ac307a2945e9137fa4a8c26c8021077239cb324816a8dad32b01ee34a08903098cb9c4245291b903c9627074095249e782813477032ba32ef041a07486eb4478c57b9d532269a4a47cb5e974df7e01096fbe4f1ccd4e663663487974c62cdd94d77716c8479d79f6b6a7d9c155988cf3902fb697424963ec4ec34ff2a35d742c4455a593bacffc4d9699ba7626c76cb1a616253751887f6ffe2be208c713df1ab636d722ea06c1c03a57f2cec0803866cca3335c28bf41c7def81acb38858dc10e59467208624967e2e22d9e5661bb945f9e0517687dc80f9b8fdecc8a97600b6c219a3b23a90b6d18aaace2c78400ff38c8c05967f544b6a606c71ac199eafd07eb5848df1657efb233fbabae63a05638191a0af7484a1bae1581375672c571e264f604225173a54a38dd62ae7130d05dd291ad12354de86a6e113e83f6d668516157b7967020dc6517d8cf42dd7b1a897fe1b4e04553ce26e299980aa5f7ce0179bf4954f01c2a23654e5e9731e1447347fa43aa8b2cbd6d4b2df93fa54af71e5028a6da8c71ef3c50c0de24dcaee785678e92aafabeb233b011f45c1064965085d2547050f21c652aa533afe918aa0f9bdaa2607b873ccd3dbd1d3a8cc62172ceb43b921ef6b25c06b0992e4df2b91e371b0ef2b3947388daec8ec6f7e3867d1f61072af590154fa619a07f87e02bddc7406314270af1c15e8ee88b39c01be602e4f0b52d9a0724e71eddd7fa9134169c5faab915979eea9362d0f1f9160268162dd38db02fcfb41350aa08e1e1409b2288db1fe4a0e586b5910f4de894bf9974f6a4983013a190e7a736d14ec54c3644a3ee958a5bdfbcb6297aba43af6c72746bb135410507d8fdde73a2a48b746f918bef9ed92c5be62dd5523fe14b16d6384ca46ef59b2185fe933383a2c7a9bf02da9d0fd8b0c7d7bde6b439f9960155e345d685d4dc3c71404d656811923aa3c47d4b09a0baef0a12e75b6439ba8135db15865874222cd7aa428f5ca5ce5140e22ff92697f37fc70b5b4c94d3314e6aa16b2146bca4fc94157951fc49245da53f6c43d1bebd894e31a1349884d711b55dbe778ffa727165cf7cb676435866c2d2cb839745ca40166a2f7cfc77a842468b51a8e76575fc9ddfb5f: +497e3ebd9e4caa81c5a8973d52f1d23f60c134ca53f62a853a0ac043e51cb51771c0ca7cfa05cafabb143d84ae41de83846f42c77caa7a91a2e348397d07d52f:71c0ca7cfa05cafabb143d84ae41de83846f42c77caa7a91a2e348397d07d52f:e132f9d67b1729389b828a9fae05a67aa57f0ef7e7d4d1ba244dec8704db969565d1cab809e48fc0abf950bcd4a37d97aeace6da546d4914cb5b86d6ab181d831870c309bca616468f2a34d3dfafcdbb7580b0c5d9ff98e2c54ec803be0d3fda1d4b8c0d7709c89e680b008bf9b8d903b5e934b019705fe0b0c8cfbc3c0967843b0a1fa1b3f162776ebe96b740edd64ad7c35b3fd1a085c99d16f5416782de17358587470dd13b5194f20f23232b2f702f10aafcaa59c7066f24c4c471e42fa86c6b9c5c3e1e8f8365f4dd75acb32fffc053c9af41c6fd2efac30ecf6a2dd0085de9b1d8cdc50b1660a866df7767198bd9c87370615d2bca99f77b84d98d7b24c9c20fd7768fd0380d6b37360340d13598047820dced88a8d42d572937b6efa16921a1b2b2d0eb931673070838e611e6c023290d86fe902f14ac3acd029e3397feb97b17166245ab407a766d2e0904424d33cd3d6e2e62a52c65df7cf004d1415c0b430c1127623dab272a2c2e2b43e02b481be928e89954272832be098b502b8b5643c67482f5de4403032581f08afb0aea48868582607bb39198c1bf13a869b63258a75890b69445ffd34564023e47f8b1884a5e49b7d9425f28d5153013fe3755c6cb114db180e60b3dc4adb36a21428128005a772fb57189345565bbd1759813523bad62855e7928eef5880d3bfff1d0ec65c24592335cda47cfcc5b5fa652b47263225224846a209a3dd7766661fca4ccca59c456fc9cc3e1cf804255aa5f397bab199804336bde29e55c6c377d583f082ce64723739e4f024606f906c110d0a5b610e5fed96dab5f08f4cb3cfc40a35557e1a740b8c7c01f7d3279dd9c4e8764c90bc14f4161db5a37f0989b7bd8035f8bea394ea1d6002ce9c34f1e9c52c6a15d15bc5b25c6c15ab00dfd6a5b1bc917af0b1b05fd10d061b3683d75b5f9effb22ae72085be4f6797b58cb0cab561844121f98bfd9583e0bccb70fad76980a7a73b23c70b3fd02f7757c11a3c21d19e05650ffb82b9e0df8a6735d480156f47949d445851baeaa5ee23814a41b25234fb92cc0df1980d023d51b5cf4c31185c118e3ee3c0c0a46e0a2be6f1d3ae452cbb66f0fd91971342da7b1b996589d94096781552195c433caf19c37f9f14fa0ae15ae0b02b939e402034ff81885939d944e604f474f21524389390fdada06e30d69068c8848cf0a951eab25c4912562944f402468187a23239d33632f29123d49b7de13083398dba97dede12f7959b95247a08fc8e4b5399d1c035c0894cc75ae981c2dd4935413bbeb6853fe04655c77d158c1237b3e0deca5636d69e0dbc5acaf72b60c10bb98ccdd60098a03:12740839b3c9f1ba879896dff6d725e84e0443ef96c349eff94dc4833143e5b419804da9db118a9592b1b1ca48af18f75bef1ca468a1a5c74c7ac813bb2cf306e132f9d67b1729389b828a9fae05a67aa57f0ef7e7d4d1ba244dec8704db969565d1cab809e48fc0abf950bcd4a37d97aeace6da546d4914cb5b86d6ab181d831870c309bca616468f2a34d3dfafcdbb7580b0c5d9ff98e2c54ec803be0d3fda1d4b8c0d7709c89e680b008bf9b8d903b5e934b019705fe0b0c8cfbc3c0967843b0a1fa1b3f162776ebe96b740edd64ad7c35b3fd1a085c99d16f5416782de17358587470dd13b5194f20f23232b2f702f10aafcaa59c7066f24c4c471e42fa86c6b9c5c3e1e8f8365f4dd75acb32fffc053c9af41c6fd2efac30ecf6a2dd0085de9b1d8cdc50b1660a866df7767198bd9c87370615d2bca99f77b84d98d7b24c9c20fd7768fd0380d6b37360340d13598047820dced88a8d42d572937b6efa16921a1b2b2d0eb931673070838e611e6c023290d86fe902f14ac3acd029e3397feb97b17166245ab407a766d2e0904424d33cd3d6e2e62a52c65df7cf004d1415c0b430c1127623dab272a2c2e2b43e02b481be928e89954272832be098b502b8b5643c67482f5de4403032581f08afb0aea48868582607bb39198c1bf13a869b63258a75890b69445ffd34564023e47f8b1884a5e49b7d9425f28d5153013fe3755c6cb114db180e60b3dc4adb36a21428128005a772fb57189345565bbd1759813523bad62855e7928eef5880d3bfff1d0ec65c24592335cda47cfcc5b5fa652b47263225224846a209a3dd7766661fca4ccca59c456fc9cc3e1cf804255aa5f397bab199804336bde29e55c6c377d583f082ce64723739e4f024606f906c110d0a5b610e5fed96dab5f08f4cb3cfc40a35557e1a740b8c7c01f7d3279dd9c4e8764c90bc14f4161db5a37f0989b7bd8035f8bea394ea1d6002ce9c34f1e9c52c6a15d15bc5b25c6c15ab00dfd6a5b1bc917af0b1b05fd10d061b3683d75b5f9effb22ae72085be4f6797b58cb0cab561844121f98bfd9583e0bccb70fad76980a7a73b23c70b3fd02f7757c11a3c21d19e05650ffb82b9e0df8a6735d480156f47949d445851baeaa5ee23814a41b25234fb92cc0df1980d023d51b5cf4c31185c118e3ee3c0c0a46e0a2be6f1d3ae452cbb66f0fd91971342da7b1b996589d94096781552195c433caf19c37f9f14fa0ae15ae0b02b939e402034ff81885939d944e604f474f21524389390fdada06e30d69068c8848cf0a951eab25c4912562944f402468187a23239d33632f29123d49b7de13083398dba97dede12f7959b95247a08fc8e4b5399d1c035c0894cc75ae981c2dd4935413bbeb6853fe04655c77d158c1237b3e0deca5636d69e0dbc5acaf72b60c10bb98ccdd60098a03: +85b4d764169128626fd9c782ad6116229edd77631c2bc9b8ee54b36542c149eb6a09897e629bb43704debb6715c9dea5d892b634306440997c3c9e94be8ab547:6a09897e629bb43704debb6715c9dea5d892b634306440997c3c9e94be8ab547:b2a0493d471c3391f7add1e2cf0bfb32ab05dbcb14f6e4f5f3463aa8d99552f433022046d2f8eb763c0171fcb1e74a049ffeb4b8f0100b8210fce856b2e1a8e739d2f93673ef8f8f40498b3081fa1fd785198c6d370e162d41abe83186f2329783408b9b880d00f81d53100b42d27a261f20cdeed19cc58cb8631281d80db1925310e235e44966309b879bdfc232221433bae5cae46690cb527b6779e11f1bd2a56b59c56ed4d94fdf7aa89dfa9bf20dbfa6a4398b98384517e1dd5d2cd9ce524a47362ef32ac792742a129c9e06130876ab5ad5518eabc5e80b022d8fa13e50d55ded589533e6ea32242c1b3fd7e65f80dee720b6d87dcff3e3df04c802d2e914a87a3629c90bb69e0a6f8bbb5ee505f143c9977375adb065c3e3d391f905fa3c336c9da41e4a2320bcf460976fc7eb1fb6c6a3c395dbd1d28a1b09cdb9ae9f9aaee4d9c566a2ac40add870479faf54ad1b7697710b4eb6f7320244b59757d1eac3d922b7a730b1acf0de9a45d4ac879d21fc616ef3965d74345ed70779eb683280cee25bf3739beb6b4cdfa25d202da13a4a673040d97048658b9205479505d0bee4880a73997c70825a6ec5fd9f952e65fa02225445fc3bdf4adea3d4d22551cbaceb3874798d6a33a6663fe3757081d6243dfd7cd2eebf60a3899fa1f8f6c956a3b183f89b9e7d2ca36448584d53aa8b44e65ad3e527f78723fa6f59224298df31d5e8ada567c8d1b11f3b1314755331c1732dc54a12a4356edda47e3c130b325282a354bfe15c3000d207822931794187e0973ab8ef87bf89c354a035a81f45911223563bfd99f90a75e53d010d8929f4f85a5a5a4f9fcc1c78f0a2fc466f5f1c6522cf62a7be37880796e9b3ca0911ecca3f22c3b24d5d9daa6888f89a8f71a15859359cea468ef238ecf646192783a257addade9047e13edd8bcc1fd4177cb20f88d11998d9c7262d648c2bf66fb227b9b3a9ed46962d2257a420f64bead9e28657b521db2e22165287791f3a1bec4c7822a6cabde5ec770188cb74498a4f08e5a3a7639d240ae3f4fd0353c0dda8ae410b9fa7f43feed13e9f13e6c9410a1d24cdfc2c8e64a15a12f75545b0a575713523d4dfa1a47427a8851ba9acccad78b4ef6a185f5c3b001190dd8f37088a000accf448be8d49371d9da2e1cb5ffe07d41a5c22e94660ac37135ac858cb1769cb66e8269fd53358ecacf5dd92c7eb6186b4d4d6130a732dc10bbb2be32f9b1d6951014a635c12d22f0dc5bd5c2a3f96aec62e7777947eaa022812caced33a5bef9ff8835f880367a37b0b76d2dde396c614e1a4721e000c00f161935b14a738a1b70f6ea54255b7951869646212:4a79c442a4c39c62892617ef8e80b40911c4b9d3ff0a5673b57bdb8454ad736769df27c78a4bf7ad566040e747278b11eb65cf9ec7eba866120a3654f4716e00b2a0493d471c3391f7add1e2cf0bfb32ab05dbcb14f6e4f5f3463aa8d99552f433022046d2f8eb763c0171fcb1e74a049ffeb4b8f0100b8210fce856b2e1a8e739d2f93673ef8f8f40498b3081fa1fd785198c6d370e162d41abe83186f2329783408b9b880d00f81d53100b42d27a261f20cdeed19cc58cb8631281d80db1925310e235e44966309b879bdfc232221433bae5cae46690cb527b6779e11f1bd2a56b59c56ed4d94fdf7aa89dfa9bf20dbfa6a4398b98384517e1dd5d2cd9ce524a47362ef32ac792742a129c9e06130876ab5ad5518eabc5e80b022d8fa13e50d55ded589533e6ea32242c1b3fd7e65f80dee720b6d87dcff3e3df04c802d2e914a87a3629c90bb69e0a6f8bbb5ee505f143c9977375adb065c3e3d391f905fa3c336c9da41e4a2320bcf460976fc7eb1fb6c6a3c395dbd1d28a1b09cdb9ae9f9aaee4d9c566a2ac40add870479faf54ad1b7697710b4eb6f7320244b59757d1eac3d922b7a730b1acf0de9a45d4ac879d21fc616ef3965d74345ed70779eb683280cee25bf3739beb6b4cdfa25d202da13a4a673040d97048658b9205479505d0bee4880a73997c70825a6ec5fd9f952e65fa02225445fc3bdf4adea3d4d22551cbaceb3874798d6a33a6663fe3757081d6243dfd7cd2eebf60a3899fa1f8f6c956a3b183f89b9e7d2ca36448584d53aa8b44e65ad3e527f78723fa6f59224298df31d5e8ada567c8d1b11f3b1314755331c1732dc54a12a4356edda47e3c130b325282a354bfe15c3000d207822931794187e0973ab8ef87bf89c354a035a81f45911223563bfd99f90a75e53d010d8929f4f85a5a5a4f9fcc1c78f0a2fc466f5f1c6522cf62a7be37880796e9b3ca0911ecca3f22c3b24d5d9daa6888f89a8f71a15859359cea468ef238ecf646192783a257addade9047e13edd8bcc1fd4177cb20f88d11998d9c7262d648c2bf66fb227b9b3a9ed46962d2257a420f64bead9e28657b521db2e22165287791f3a1bec4c7822a6cabde5ec770188cb74498a4f08e5a3a7639d240ae3f4fd0353c0dda8ae410b9fa7f43feed13e9f13e6c9410a1d24cdfc2c8e64a15a12f75545b0a575713523d4dfa1a47427a8851ba9acccad78b4ef6a185f5c3b001190dd8f37088a000accf448be8d49371d9da2e1cb5ffe07d41a5c22e94660ac37135ac858cb1769cb66e8269fd53358ecacf5dd92c7eb6186b4d4d6130a732dc10bbb2be32f9b1d6951014a635c12d22f0dc5bd5c2a3f96aec62e7777947eaa022812caced33a5bef9ff8835f880367a37b0b76d2dde396c614e1a4721e000c00f161935b14a738a1b70f6ea54255b7951869646212: +33d477602f296305a6719ea694c044e90d233c2dea85c46abe1920e88c317849ff6feea028ec346dd49107bb713fddbb282ebcd034e2eafc7cdb1c5adf926390:ff6feea028ec346dd49107bb713fddbb282ebcd034e2eafc7cdb1c5adf926390:cfea07a779f1537e498123c676290573efcc5db70245d93dea5c05726f8713d002ae66c1c9690747ca9230b1629d3662ab73d66b949879164b21a35f40cf3799041908ed6f9229ecb390c5f22234e1c5f26b3ab5ba59e78c64969871b428b78516777555af4e89c6fbc193a94695226c6d329991a11bd580d18956089b58a0e42ca35f6c6d2609ade0d0b619d48925c68cd9d2250dff27cf2f0d44448709b679f35bbdce0f496b0a16ca67eaceec258b1aec91775a3a2ee801b1c9a226a6b001926a057a06306727eedae8c577531df04ac09b5b49bcdeabdeb8ac4e8e82cf1e7af835fc611ca7a684b83526042415b1d6652e8634311e194627eae78d011e6f40f645794e36895a23e1bd84883a393ecfe5a248026aea86447059f7a429368f21c89e0145207978b913c80a22d7caf2673f7c76f6c26cf884412e17d0c255430f502bce74e3a310d17f6f4d485da280ed5b5eea6c49ba748d764814b9e3daf6fcc218c2740ca77018f71344519da82ada31e001924fc77679e3e9ff9fab67dd09a61924c821a1fd999f74dfa3f819adb31d15e5ed8aaa52c1bd7cca266711a74dd62104ef3c2bf737fce6942b348a33c3dfd6d92a724b6d5878421aeb230a533fe21c8b2fd3da596a6180a45c986d7ece4cdc8ad681ead69064bbddfc20f3c52125f83395bed1557f67182b9fe99138af3c356c5e652978dd238b761c742f8158e2314b964208330978b0620a13a16d761d52f06e466a4094b65cd6f26854aed6f9a8c2a884a0d0bf4ee587eeb8b602487239a7e58172c809983a8db1c1fc7ce8c48bc8a6fb812d6aa9e83a3ab4ddf7a8d40d3fe00ea16e04062b8aceb9c99eefa41f4f87447828126d0d9c9f8605e8467c5e4d671d5c6d9fa70d747098d941211223b9bcf261938d6704a32d22c61e30f3570a1f5d0998b4791080882aa5623167b63a23f340f0e7c6f9a830a75b74631fa5b57afdb1e6bc22699bb03156675d598353a5d1b55897e4c11061dd145f23e8537c632f75c10df05b25547238574017fe7b64b8e99869157fee35f7ad7e63e99593302929503a96768023b4125ad749dff4b992ee5c2b4f3ada4889e4ae62ec15d2db5969d730db307547f638c3185032b12f75fbb317e47df7b9292ae9e76a2c0a06fcad108cdd235f6e38d967b6379511ff6965c22f2c6680a12b0304eb2b296c99a76c2729d98e0a7824b67f3fe842d6f6ab273e894845b32dc6ddfc7a220f76bd965c69858183c8f357395fc57dc829defaacb5603a757868d5e562f9781ee39e0e94688ad3545b32dd7366b6b047e8d1d3d565997b236e7f7596c5f8d7c1c11bcf4a244620cbd21d559a7c9b3f:caa2879895d4f620b9eb5fed22b4562eeb1ad63822968f76ad91076b166c05ee20864d98bbbc6e79dd0362cacf7a21b4cfc230d6355d43120cfffb948b8f6c0ecfea07a779f1537e498123c676290573efcc5db70245d93dea5c05726f8713d002ae66c1c9690747ca9230b1629d3662ab73d66b949879164b21a35f40cf3799041908ed6f9229ecb390c5f22234e1c5f26b3ab5ba59e78c64969871b428b78516777555af4e89c6fbc193a94695226c6d329991a11bd580d18956089b58a0e42ca35f6c6d2609ade0d0b619d48925c68cd9d2250dff27cf2f0d44448709b679f35bbdce0f496b0a16ca67eaceec258b1aec91775a3a2ee801b1c9a226a6b001926a057a06306727eedae8c577531df04ac09b5b49bcdeabdeb8ac4e8e82cf1e7af835fc611ca7a684b83526042415b1d6652e8634311e194627eae78d011e6f40f645794e36895a23e1bd84883a393ecfe5a248026aea86447059f7a429368f21c89e0145207978b913c80a22d7caf2673f7c76f6c26cf884412e17d0c255430f502bce74e3a310d17f6f4d485da280ed5b5eea6c49ba748d764814b9e3daf6fcc218c2740ca77018f71344519da82ada31e001924fc77679e3e9ff9fab67dd09a61924c821a1fd999f74dfa3f819adb31d15e5ed8aaa52c1bd7cca266711a74dd62104ef3c2bf737fce6942b348a33c3dfd6d92a724b6d5878421aeb230a533fe21c8b2fd3da596a6180a45c986d7ece4cdc8ad681ead69064bbddfc20f3c52125f83395bed1557f67182b9fe99138af3c356c5e652978dd238b761c742f8158e2314b964208330978b0620a13a16d761d52f06e466a4094b65cd6f26854aed6f9a8c2a884a0d0bf4ee587eeb8b602487239a7e58172c809983a8db1c1fc7ce8c48bc8a6fb812d6aa9e83a3ab4ddf7a8d40d3fe00ea16e04062b8aceb9c99eefa41f4f87447828126d0d9c9f8605e8467c5e4d671d5c6d9fa70d747098d941211223b9bcf261938d6704a32d22c61e30f3570a1f5d0998b4791080882aa5623167b63a23f340f0e7c6f9a830a75b74631fa5b57afdb1e6bc22699bb03156675d598353a5d1b55897e4c11061dd145f23e8537c632f75c10df05b25547238574017fe7b64b8e99869157fee35f7ad7e63e99593302929503a96768023b4125ad749dff4b992ee5c2b4f3ada4889e4ae62ec15d2db5969d730db307547f638c3185032b12f75fbb317e47df7b9292ae9e76a2c0a06fcad108cdd235f6e38d967b6379511ff6965c22f2c6680a12b0304eb2b296c99a76c2729d98e0a7824b67f3fe842d6f6ab273e894845b32dc6ddfc7a220f76bd965c69858183c8f357395fc57dc829defaacb5603a757868d5e562f9781ee39e0e94688ad3545b32dd7366b6b047e8d1d3d565997b236e7f7596c5f8d7c1c11bcf4a244620cbd21d559a7c9b3f: +7074568611a66dfca8307cae608bb26995844df435e5300e5b4d7291cc22907fddabddd15eaf83115ddd065d7e220b1efc262a61c52e914347442bde6d002506:ddabddd15eaf83115ddd065d7e220b1efc262a61c52e914347442bde6d002506:6c137423eac790b8e8e418b290e0579c7b86b14aed818de8ce53cea3f340a1a95391f984968f2b4229282a8161c09ab149cdacd66970b4013f52e5e68ea8c9db685b2c53073500e5b35e29ea0ba1f4d159a558d361b06516836cf7b9ea501fa0506b985f036a82d9e084489d3bfed34093e2d6d9edf55785ed35a90ce56c761686cc3ea1a2c76ada5ec8c145d818b047cc516eec5d2d6a93a55592d892e3d5cd10c250c04b049b38fc7ec0f39aba15824007336c2b0f7f81d64d5ca3e29d6fda4c23d9ba65d9fe3cb4e03913697287b46a0b1fccd2624e397ae95c5254bcd88d2c7c8f70fdc8173f64c1de32281ab4184693b48a349e6782bc8992b43c7de7cb9d33929bf95306c2af7e938d8486b386f9fd3f0f7161e0e6862d4f9281446865a1c9be2460efbc20151b06e79d014617d0300e671d48767458596625b76dffc558aa9b40612196ec827e1c6fff518fb7ad4bf8c46fcb278885aa491b77a28995cfb9d79640aad174c6df43938e3f1385205c54595b33dede50143746a1705e7e0b69af4a26c3b76515051892b15ca6e48c3d91fbc75e8fe4a0fe8ed2c26c1073beb70ea38d0927029278406755ae6e11da378653649515e0085b5ea7db3249208e33a6c8b6ae8cd80c9bd6b983e73e9b91dbec091fae995f8032427edec02cad9055eb8b7dbcfa80d4f64f5727a152f11c47e52d753a57b6e5fddf774cea4da910026819c41e32b4f199727e23c54ab5d70142b854a27b04e64cf44af2a8995e1200bd117c7a1674edef59bc53f73adaf638e0773b85b56334aff6e11743e3a3d3614aa8a375b3781ec814cc08e71efa7818519cb24af82c331dfd6ac78ec17fd7174b61021e8cf901a2aaa6adbc902a916b2a2f4f79e551501fbf01df6b8518504c1e94646938bed1a8509c2a38fb6a798a7858f409b0f2fb9b3f4817e568c52d9abfe2168cc3650fc43e0f9975fe29e33aed1a7bf30d8631150790650a3cb78c368f1aea9ac60c5eeb969a45f84aa37366a83977190f41ae421e0c46fda3fa01b926fcef8224fda36df4f8a87701fe79fe0628ef0cc02df2bd783207c7db87119a0369fe16eeb38fdc9fb35d9e195fe14f8c1038208ab97700af79f2e2e05496830207c7da8dbe8e9bb73bc471a43f1be650fa92819aeb5dc7eed7eed8171270d219257d19610b89d2d62d3f5b648e139eedf1ff74be01a5ef1d95f812922601ee92515157c4ecadfa3eef9f2a677c003ca4ab9b2c45472ce55e18f40a21fe1b0d45b50b50c52a0b1a5d7c37d8ebc15e020584d9edd7b56505f82078e0f899389135014c86d1e2ed49f9cd319076943553a312ae05ab333526e136714f09a402b3c8:7f653134c0b90f44a489f0b05fc40707ad9f1398f340b447a3c9861f511c9f1568803b7684a04a898c45154dd486bd50758998e126439378b3f59ff367492a0a6c137423eac790b8e8e418b290e0579c7b86b14aed818de8ce53cea3f340a1a95391f984968f2b4229282a8161c09ab149cdacd66970b4013f52e5e68ea8c9db685b2c53073500e5b35e29ea0ba1f4d159a558d361b06516836cf7b9ea501fa0506b985f036a82d9e084489d3bfed34093e2d6d9edf55785ed35a90ce56c761686cc3ea1a2c76ada5ec8c145d818b047cc516eec5d2d6a93a55592d892e3d5cd10c250c04b049b38fc7ec0f39aba15824007336c2b0f7f81d64d5ca3e29d6fda4c23d9ba65d9fe3cb4e03913697287b46a0b1fccd2624e397ae95c5254bcd88d2c7c8f70fdc8173f64c1de32281ab4184693b48a349e6782bc8992b43c7de7cb9d33929bf95306c2af7e938d8486b386f9fd3f0f7161e0e6862d4f9281446865a1c9be2460efbc20151b06e79d014617d0300e671d48767458596625b76dffc558aa9b40612196ec827e1c6fff518fb7ad4bf8c46fcb278885aa491b77a28995cfb9d79640aad174c6df43938e3f1385205c54595b33dede50143746a1705e7e0b69af4a26c3b76515051892b15ca6e48c3d91fbc75e8fe4a0fe8ed2c26c1073beb70ea38d0927029278406755ae6e11da378653649515e0085b5ea7db3249208e33a6c8b6ae8cd80c9bd6b983e73e9b91dbec091fae995f8032427edec02cad9055eb8b7dbcfa80d4f64f5727a152f11c47e52d753a57b6e5fddf774cea4da910026819c41e32b4f199727e23c54ab5d70142b854a27b04e64cf44af2a8995e1200bd117c7a1674edef59bc53f73adaf638e0773b85b56334aff6e11743e3a3d3614aa8a375b3781ec814cc08e71efa7818519cb24af82c331dfd6ac78ec17fd7174b61021e8cf901a2aaa6adbc902a916b2a2f4f79e551501fbf01df6b8518504c1e94646938bed1a8509c2a38fb6a798a7858f409b0f2fb9b3f4817e568c52d9abfe2168cc3650fc43e0f9975fe29e33aed1a7bf30d8631150790650a3cb78c368f1aea9ac60c5eeb969a45f84aa37366a83977190f41ae421e0c46fda3fa01b926fcef8224fda36df4f8a87701fe79fe0628ef0cc02df2bd783207c7db87119a0369fe16eeb38fdc9fb35d9e195fe14f8c1038208ab97700af79f2e2e05496830207c7da8dbe8e9bb73bc471a43f1be650fa92819aeb5dc7eed7eed8171270d219257d19610b89d2d62d3f5b648e139eedf1ff74be01a5ef1d95f812922601ee92515157c4ecadfa3eef9f2a677c003ca4ab9b2c45472ce55e18f40a21fe1b0d45b50b50c52a0b1a5d7c37d8ebc15e020584d9edd7b56505f82078e0f899389135014c86d1e2ed49f9cd319076943553a312ae05ab333526e136714f09a402b3c8: +7d7ca8e8d3b84344a5e4dea08b338d8faa5ffc119ce566ef656f0f4584775b210bde34b746d2c5490853064d48c6b4c1cbbc3ee7beff5e8f684c120f315d7e4e:0bde34b746d2c5490853064d48c6b4c1cbbc3ee7beff5e8f684c120f315d7e4e:0b727075345d619f5cdc7fc4c43cdc19105811d95d069f81c0a62fe1e1178cf1c35db05e2de87d11ae1a6f53ef38b39bf4ed8fbf56ef017a1d3c15b64fe4b2610bf69bd19ac7afd46a2b87b488b6c78ad456811c1dd6bd4a6b5da698739fd1a14ceb9f27f124b69f6bd16de5537aad80681c5633580394da3b84e9b7a55ebab8522d2d6bf1aa4e7b159cbf4e20b50bfe9c711aa047119f1dad8749260b87639e9c141def62026a990373dcfd99f77b0f5ea6adfd8f594b9ce41064a5ed307bf2d8d17370498ad7f45f9c4dd26c420f450f53623bb6d7f3f46a149d8f135bc2913310fb8f9043d099278bbeba39179fa367b01673e1c953effd2caea7311c47c0372744095b1c8f90eef5f1929db1996cd584f615d56fae3aecac3ee88bd0b296f449cc2713c52da695248faa8e389b05a0bcac69dce9719723194f433b0297eb0859019f141a207ce8ccb59882caa6e18f0b43bdddb90a0a85ffd577d6394a1d80489410f92afb85ba506aa9f3f427445d21224b9cb046c05f1bacd7b749fb7b1024d092e4ee4b30a46edf718470c99491c68f4879d62bfce7046d8138cbb9e7212999a4498b455fc90ac283e935de04df6fc999e4434be11063d6e4ee9e096a87bc716d2c819916c37a4e6298c49945366ec3f500720b06dc99d3d8ac303e6c264e28a7c2d419ec622a97a711544fb1f4735b11f8bb1d7e2c816a156287b4cc0c65aaa280b837737f0a84e36de2df2fc3a50df980918fb9e5834b42ac0e0c7278d7fe8db4dbdeca0141d5fef5dc6151f87b8634c241a8fa0a82717899773ae89f537890b9155a7a05bce47866ec2028a47898d485823a2e992319680eb699b0dd5358f546fc537c73d3a4b223a0941518b6d1e66b27676c1b1fc76a08320524a72e297fce17aa80d8ea7b388a55168e7dadb836e9dee707ed25c0ee4db25bee3c485b39649204efaf2820b2736368fc773ce090c385378002c471b094795cb266d39eb7580d701be4c8916f6b38bfe25fdf36d6c4adafa9ae9864c57bb737b49506ed38d62de60cc0599ec6bb1acf24b1d37d60efdeb7d942c53603a2f0476e9512c938b28d495a6f26a907c396b841aedd8e14ac447b495df1f676daccd5a740c042f5772b7db17f4f1a3a1c8e7c488370e736b51e690fd2ddcb5aa61957a7c7975acb2dcb915d074d744279ea1c4169f868873ac5c20890162c1df9656419975a43d3198e18c309a1eb7c1d87873fb15c6da47f548a01f69bdab9c39ef00d418a6f619dd73d7db45cbb6ad225a2de787ba777bc73d28fc304f10009f4022c2cf84de008d70fcdc8ba7f107c369859e9c90ca8a393b553f26605ffd7230c921490700f:d0c3e248a8cb2ddc7e9f21c9c5b009f70ea29da6897cd92c260f047ed68aa1c8b9657f9d826e88f4a512c5003be6406880741263ae7ce6860efe73ad54d482040b727075345d619f5cdc7fc4c43cdc19105811d95d069f81c0a62fe1e1178cf1c35db05e2de87d11ae1a6f53ef38b39bf4ed8fbf56ef017a1d3c15b64fe4b2610bf69bd19ac7afd46a2b87b488b6c78ad456811c1dd6bd4a6b5da698739fd1a14ceb9f27f124b69f6bd16de5537aad80681c5633580394da3b84e9b7a55ebab8522d2d6bf1aa4e7b159cbf4e20b50bfe9c711aa047119f1dad8749260b87639e9c141def62026a990373dcfd99f77b0f5ea6adfd8f594b9ce41064a5ed307bf2d8d17370498ad7f45f9c4dd26c420f450f53623bb6d7f3f46a149d8f135bc2913310fb8f9043d099278bbeba39179fa367b01673e1c953effd2caea7311c47c0372744095b1c8f90eef5f1929db1996cd584f615d56fae3aecac3ee88bd0b296f449cc2713c52da695248faa8e389b05a0bcac69dce9719723194f433b0297eb0859019f141a207ce8ccb59882caa6e18f0b43bdddb90a0a85ffd577d6394a1d80489410f92afb85ba506aa9f3f427445d21224b9cb046c05f1bacd7b749fb7b1024d092e4ee4b30a46edf718470c99491c68f4879d62bfce7046d8138cbb9e7212999a4498b455fc90ac283e935de04df6fc999e4434be11063d6e4ee9e096a87bc716d2c819916c37a4e6298c49945366ec3f500720b06dc99d3d8ac303e6c264e28a7c2d419ec622a97a711544fb1f4735b11f8bb1d7e2c816a156287b4cc0c65aaa280b837737f0a84e36de2df2fc3a50df980918fb9e5834b42ac0e0c7278d7fe8db4dbdeca0141d5fef5dc6151f87b8634c241a8fa0a82717899773ae89f537890b9155a7a05bce47866ec2028a47898d485823a2e992319680eb699b0dd5358f546fc537c73d3a4b223a0941518b6d1e66b27676c1b1fc76a08320524a72e297fce17aa80d8ea7b388a55168e7dadb836e9dee707ed25c0ee4db25bee3c485b39649204efaf2820b2736368fc773ce090c385378002c471b094795cb266d39eb7580d701be4c8916f6b38bfe25fdf36d6c4adafa9ae9864c57bb737b49506ed38d62de60cc0599ec6bb1acf24b1d37d60efdeb7d942c53603a2f0476e9512c938b28d495a6f26a907c396b841aedd8e14ac447b495df1f676daccd5a740c042f5772b7db17f4f1a3a1c8e7c488370e736b51e690fd2ddcb5aa61957a7c7975acb2dcb915d074d744279ea1c4169f868873ac5c20890162c1df9656419975a43d3198e18c309a1eb7c1d87873fb15c6da47f548a01f69bdab9c39ef00d418a6f619dd73d7db45cbb6ad225a2de787ba777bc73d28fc304f10009f4022c2cf84de008d70fcdc8ba7f107c369859e9c90ca8a393b553f26605ffd7230c921490700f: +d21fdd7b10e54a8b6be95a0224ad70664dd92112e2683a4fd279c407db3871bbf89c272e7d1cc93d69f694dec9cce05ac247734504829c56997413c8958b9330:f89c272e7d1cc93d69f694dec9cce05ac247734504829c56997413c8958b9330:b8644adbef9c7cab9120acedc8e75c433d036ffae0f955be6a488f1f427a68a8902d026e63dd6c9bf9d97de786b31dd4f4c9a4f8a622f1ffc84da6967ca77433c398f4d3f1c4434989b7ac9d0f3b1be0c8b352824f4e7a083f342ec1be1da8fb755242a654880ef298f05979ff026ddcc044860e6757a29cfaa222a3597e38f1779962a41a4c8ce6a65b878199b4d80f4a0390cac19c226eea4b6036e57ad830ecfc00693e2613d3edf465fc8c4fa293fd8cfc36dc8e37bcebabec0349ebd884e1b28bce824e0d55b6d015383801668b34f5ba723d2ac0a264fab2c728608f162de01179259be2ccb0815002fded8e0d78b02807313e910eb3a7337c534e846f9ee155426e4aef643661b0edb44596fddcd0b3e814c137817a422baa40c9053d0386c6ecdb589052594742677c48dcfc8cd4a93667ed4d87646001eda079e8b99d52ba21c5ec5669fedf6f40447a7ff8901db0ef1847d3cacf0198a2f3bd7bcf2dd811a097fc5e5188b03fdf54e517637a14501000d0d35516caf0699402b48f8d8cc3afb17a56132d08237035a0c95490bfe5d7b7fb40178f281e4d872e47a0e955ce9736f3c333a6adf50ad31994eb9f45327facc8c5d113fad4713fe7f198010d42046bbfe68b0daa79dcb8755929be92f9caa150dfbde3fc9e392b2b701c3021c240e4679de41124b1888e5db5a83d05ceaf49eb440dc45026d450bc984b8d6f02850ecb570eee0a3819b12bc26367b5b98e1b141c9b0a9690ea4a3700dad12395f975d11cd77f96368831f21f4e968cc5ba9ef82474038bc7aa26122d218b743041506aebbd1f987959fd160d6eb7d58d4f576f8c0ca8af868e39b5ea87203937e0308acbeae91e10607e44e8ab495bc01dd573fbadc94479ff92082c7bb7513479c70f0407769025d34d72140c25d821f034a39851a93c623b71c9400e942639f28bbd032e1d8d3c059f7c2cd31d7476462d2776035d07880202dbfe9e07d154622d7ac6175a5afa79fed4dcc13712620c41994e11d924308fb2ff3a1eda44c761bc736f345122f02a40ae6f7dbd03d9fe96ee3d7a3b4a5eefbfcc56dc42ef27bd8085176038b9ebae63aa75035275ec34e4185739d636246770acccc6dc620e2fc9156fa9483e0d9cae0e8c463948a3d97ae8dda5966c88f07093292cce22bbda062baafa7fe84d0ba2d2dd295b23458bcaeb2ef742a2ed1c834483cd709385afeadcbc0a9c6a4f387babf7e3dc36c810db209beb66c8666404c661dfe9d32c4c08afc6f3b1257d6484a755f5ac701eb13f87763fee330ffa0422cd80a92038c6f45292bdee5f89e94c7a652197fc1906b48258372449b1081c6b97134c43c89ee2:6d69e83b3e7ed55a85f9fc9d2519da0b0a1eb4daaee991a6651f5c89190c0de72373cd989d46be1367f9daf1b92fed3b52bba54a1e4cca5bc8726ed07f302501b8644adbef9c7cab9120acedc8e75c433d036ffae0f955be6a488f1f427a68a8902d026e63dd6c9bf9d97de786b31dd4f4c9a4f8a622f1ffc84da6967ca77433c398f4d3f1c4434989b7ac9d0f3b1be0c8b352824f4e7a083f342ec1be1da8fb755242a654880ef298f05979ff026ddcc044860e6757a29cfaa222a3597e38f1779962a41a4c8ce6a65b878199b4d80f4a0390cac19c226eea4b6036e57ad830ecfc00693e2613d3edf465fc8c4fa293fd8cfc36dc8e37bcebabec0349ebd884e1b28bce824e0d55b6d015383801668b34f5ba723d2ac0a264fab2c728608f162de01179259be2ccb0815002fded8e0d78b02807313e910eb3a7337c534e846f9ee155426e4aef643661b0edb44596fddcd0b3e814c137817a422baa40c9053d0386c6ecdb589052594742677c48dcfc8cd4a93667ed4d87646001eda079e8b99d52ba21c5ec5669fedf6f40447a7ff8901db0ef1847d3cacf0198a2f3bd7bcf2dd811a097fc5e5188b03fdf54e517637a14501000d0d35516caf0699402b48f8d8cc3afb17a56132d08237035a0c95490bfe5d7b7fb40178f281e4d872e47a0e955ce9736f3c333a6adf50ad31994eb9f45327facc8c5d113fad4713fe7f198010d42046bbfe68b0daa79dcb8755929be92f9caa150dfbde3fc9e392b2b701c3021c240e4679de41124b1888e5db5a83d05ceaf49eb440dc45026d450bc984b8d6f02850ecb570eee0a3819b12bc26367b5b98e1b141c9b0a9690ea4a3700dad12395f975d11cd77f96368831f21f4e968cc5ba9ef82474038bc7aa26122d218b743041506aebbd1f987959fd160d6eb7d58d4f576f8c0ca8af868e39b5ea87203937e0308acbeae91e10607e44e8ab495bc01dd573fbadc94479ff92082c7bb7513479c70f0407769025d34d72140c25d821f034a39851a93c623b71c9400e942639f28bbd032e1d8d3c059f7c2cd31d7476462d2776035d07880202dbfe9e07d154622d7ac6175a5afa79fed4dcc13712620c41994e11d924308fb2ff3a1eda44c761bc736f345122f02a40ae6f7dbd03d9fe96ee3d7a3b4a5eefbfcc56dc42ef27bd8085176038b9ebae63aa75035275ec34e4185739d636246770acccc6dc620e2fc9156fa9483e0d9cae0e8c463948a3d97ae8dda5966c88f07093292cce22bbda062baafa7fe84d0ba2d2dd295b23458bcaeb2ef742a2ed1c834483cd709385afeadcbc0a9c6a4f387babf7e3dc36c810db209beb66c8666404c661dfe9d32c4c08afc6f3b1257d6484a755f5ac701eb13f87763fee330ffa0422cd80a92038c6f45292bdee5f89e94c7a652197fc1906b48258372449b1081c6b97134c43c89ee2: +d336fd8408196d22fb698eb25b7654fda46f5de4c9b4d04950c398b59a44290af3cd96347cea63e500a4c92c3bf215662dd0400784dbf8b595dd3d395f90cc12:f3cd96347cea63e500a4c92c3bf215662dd0400784dbf8b595dd3d395f90cc12:fb49c19bc4444c28eb2625f31d996d5e36c57fa6fdd772e67b7199cec67eda5451712df7a69dbbd56e7c398796b2001def651c4b9c05ee31d95679535c812a37d31ddb3073199cd704ff7ca2981f7b9c927a7f7d776fb6f609f727e6ea709ce7f43a60793504169a8905d9b23109f0d867966aa3e300c7e11ddedb9cc117b904f62927e48e4d73fe1a6ceccc4ceb08e64ab55f25c98216cec937608ad793146998f14c2985e6c2910df7b1388f9dd863f1e4d7d1621479b8512cdb34e673eb02a48934e39c2d18d70f966d676a2bd75db543d25c5dcdc3ef3b8bc8201848c30961e915d968bdc31946b0d18ede7cb0166dbe1ffeff9439c9c3404af6016c73edeb253d93f562a1a6cdd57898a9b3422587d5f56af3d06b3f6c25751f44460fb3299656dc11227ef4837aabddee400fa53f69e5ced053c76dcecdf0adc9ef80f4b330542ff1fa2df0b8d43cd1c311b1b9955c632c8e5f0491931c04de434df8f7a394e5fef016db2eb7c87b2ac7a4a73043bd7f98ad0a4d453abfb0be8be4cb145742aa56aa5ef2dff12230a510e3b7f82f7847700eeea5905b0289696c4c142bf34bcf81a962d75b8d091055733779335b7fd47a20d17c948ab732947832674371e22e711134f5c919792357f79bf70c4470787528434fc0b4ca093ee92543420d1ca81124f5585317e250821a4f3d8ce0f919de9fbf0127087e676903f6cb39025bcc73a0762954b72e66a6be9b96c97b6f6030bf5ca0bc2727a9a179cf9d9405f3fe18f3492389079a5b65bcb13a0d5ef41c2cd97e702cee4a2feb1e6702bd4c63fe0a4ae994c4287a837bc3f64c2d898857cdb32acd4bd133676e51f77bc7110e3ce52d9204fd2691a6d37078f68e7bcef30fc9c483985822b661119238e40f9cfdcabef2d7b16b059ab24adc05003712bbb128096e37f91bc4c5c81508be27fa0b84940be36bced2e65cd36b39fbdc5ea68614159228ca65c5d8407baf663b528e7d87734c7bc77dc8431a1dd6873cfddfc3e757d9ad1fedd3c798f1fe60e715ee48a6bcbb13b616a89a38e336489d3d6ccb726914112a1bc5d977c9b2a3fac107ad094b038ab75468263c34bda817c056e07a6c56697cb64a0b1f966f6de0bb1c0a71c8a5fe133ba2036d24daccad3fa03b39cd27f832752751055a8155913d040f51dae78d71946ca04d83c7c894c280aaec285543e5fd5e327accca9abef156a13b9571446bd8007ff92dbc0fbaf23a9441b53c1cd740c34c282929101ad2ea8b85d70052991b774e92ff75cc85113e0900b51b863e1f2adaab2dbcf46af479ea248ec2889afbfe737408393a2b1b3301f65c1fac8b676795ab5bf447f05e0daf6776:af7e2df7529fd18d1b21b8fd4c0681505918e2511434fe4e4954e743c1cfa45e4109d36c3eecf2e25d209b9b5d25f7cbc380296d647752e30d3bea3b929b0903fb49c19bc4444c28eb2625f31d996d5e36c57fa6fdd772e67b7199cec67eda5451712df7a69dbbd56e7c398796b2001def651c4b9c05ee31d95679535c812a37d31ddb3073199cd704ff7ca2981f7b9c927a7f7d776fb6f609f727e6ea709ce7f43a60793504169a8905d9b23109f0d867966aa3e300c7e11ddedb9cc117b904f62927e48e4d73fe1a6ceccc4ceb08e64ab55f25c98216cec937608ad793146998f14c2985e6c2910df7b1388f9dd863f1e4d7d1621479b8512cdb34e673eb02a48934e39c2d18d70f966d676a2bd75db543d25c5dcdc3ef3b8bc8201848c30961e915d968bdc31946b0d18ede7cb0166dbe1ffeff9439c9c3404af6016c73edeb253d93f562a1a6cdd57898a9b3422587d5f56af3d06b3f6c25751f44460fb3299656dc11227ef4837aabddee400fa53f69e5ced053c76dcecdf0adc9ef80f4b330542ff1fa2df0b8d43cd1c311b1b9955c632c8e5f0491931c04de434df8f7a394e5fef016db2eb7c87b2ac7a4a73043bd7f98ad0a4d453abfb0be8be4cb145742aa56aa5ef2dff12230a510e3b7f82f7847700eeea5905b0289696c4c142bf34bcf81a962d75b8d091055733779335b7fd47a20d17c948ab732947832674371e22e711134f5c919792357f79bf70c4470787528434fc0b4ca093ee92543420d1ca81124f5585317e250821a4f3d8ce0f919de9fbf0127087e676903f6cb39025bcc73a0762954b72e66a6be9b96c97b6f6030bf5ca0bc2727a9a179cf9d9405f3fe18f3492389079a5b65bcb13a0d5ef41c2cd97e702cee4a2feb1e6702bd4c63fe0a4ae994c4287a837bc3f64c2d898857cdb32acd4bd133676e51f77bc7110e3ce52d9204fd2691a6d37078f68e7bcef30fc9c483985822b661119238e40f9cfdcabef2d7b16b059ab24adc05003712bbb128096e37f91bc4c5c81508be27fa0b84940be36bced2e65cd36b39fbdc5ea68614159228ca65c5d8407baf663b528e7d87734c7bc77dc8431a1dd6873cfddfc3e757d9ad1fedd3c798f1fe60e715ee48a6bcbb13b616a89a38e336489d3d6ccb726914112a1bc5d977c9b2a3fac107ad094b038ab75468263c34bda817c056e07a6c56697cb64a0b1f966f6de0bb1c0a71c8a5fe133ba2036d24daccad3fa03b39cd27f832752751055a8155913d040f51dae78d71946ca04d83c7c894c280aaec285543e5fd5e327accca9abef156a13b9571446bd8007ff92dbc0fbaf23a9441b53c1cd740c34c282929101ad2ea8b85d70052991b774e92ff75cc85113e0900b51b863e1f2adaab2dbcf46af479ea248ec2889afbfe737408393a2b1b3301f65c1fac8b676795ab5bf447f05e0daf6776: +6573227841f6f92831146c44c0e480cdf544bb876552cc5f9d42f15bdcc044b8192257a54ce5d04c19439fdc9ede18ec856e29870e24d3731fe2224799949b7e:192257a54ce5d04c19439fdc9ede18ec856e29870e24d3731fe2224799949b7e:6e7c6b122ab36bd135f69e2b85e7fccefb072c12cf088a3229d876eff532389f0577116f7af29f1195e3828839381380467178b229c5a18d7c4943ec970dd18bce723bd0ca91ffa95563546a324fe0b9bf6c0455d4276039e8d291fc7276aa55a1cd3ea05282654a7f9700adcbc78077c5dd0fc86eced48f4a60ccb76bfb8b4562bac22a02d19e4489394ab9719fc144f5db2ef039b37f3b51d1d657a0cf835d71f1a4af01eb9fd885c604a624cbe910bfde093ad3f0cbfd9a48307329d44234bd01191d56e522d72b54e1fe4733da3aec6827eab3554898e03e577b4e7b9dd3f308e616808d0294499f2886295e54c360199ca83a83ff46195ea3c484a66838d51acbe9611eee036ae281c6793cbd451f9271fb5d25ea7c1899ab5d43ed8b9d067bc56d8d4a15f1dab8d8d95d1b17af64cb18c1147551147addcbdd53fbccd9026f855547131bee95071639f649f2d035a25a3e42e38e22bbf038106ce8bc4ad6768ab92cd57afacd04ee55cf0714b768952dac240b1e9b2835ecf7b0d6c407c82524a923b9f54d1b8f12564a872144efad3f3a7d2397cd1217dc5a9c96e43b2960a8425e97e07a02b0dac90f346b91a346a23ed2bb7fe6919c22dff03f62da7dba176e8ddb22f3f3a668891d3f4e69548d0ac4e71e6d28ed5a67ab5ac611d460b67a201f4f56a5003ca7a7d1cd1db6c10075b09227cb8c5dc1666f8be710b4b7bc2b95ae60da4f64179a50d2f88744361591671d36b7296315f6996439ad79821da8e772dfbf55a90d5d52ef7d76b35ffebd42e3525f4530c54a0f23b4d07c5f5974470e89404d176eeff9ef2333619691c59b7aadd42c296b1d0d328d9a3bd59a54bba93a0c1f1d62418c2190c38174b6abea02db66e818320ec4b8bac1c12f18f30dade27e63c58f9e7caf4bf69b265a2f9d91800861acf479e65ec17e680577e058cb16c109bcf9b2909fce3361a2c2685c10be8540a1222db5ecf0cc4d53a4214b7bf6248adc3a861e34841a3779c46046c5364f1ea91a78c9700d462ecfaae36ba760c1bd6a237c961edf4022cedefe5e937bbed7051ae61b96d08b0487ce0568ff0d32740bbd49ad0db86e09102ab21a915616e9dfddc81ebfb36c903e07a40cd2dd119ff4a50b93fc6fdfc0f36e59e0148fcff3fe8e2cd6d30a9e4b8f015567d118b6274e1ed75b22e44ca9d9dbfc160742cfac581e1a0bf5ff3326bc5f7896b9ca05a811d55e97c834d37a6495cc26cf442bd2d90129895e9cc0ed01e2155293f47a07ab5880c6ca29ed44d9ccbcaada7f3eb60402181488654e04911578b1aa9cdd4b86b0dd2450df3a43081e4110ab58de763924d3c89152e99293e638f9acd8d7:538eace493de53384b1e985bb907c094f8168430dab14d37791be6e78ff3f5a306ec70dcac86d993a4c1f75850786d795f022b79be6a547769e41569c5a9a30a6e7c6b122ab36bd135f69e2b85e7fccefb072c12cf088a3229d876eff532389f0577116f7af29f1195e3828839381380467178b229c5a18d7c4943ec970dd18bce723bd0ca91ffa95563546a324fe0b9bf6c0455d4276039e8d291fc7276aa55a1cd3ea05282654a7f9700adcbc78077c5dd0fc86eced48f4a60ccb76bfb8b4562bac22a02d19e4489394ab9719fc144f5db2ef039b37f3b51d1d657a0cf835d71f1a4af01eb9fd885c604a624cbe910bfde093ad3f0cbfd9a48307329d44234bd01191d56e522d72b54e1fe4733da3aec6827eab3554898e03e577b4e7b9dd3f308e616808d0294499f2886295e54c360199ca83a83ff46195ea3c484a66838d51acbe9611eee036ae281c6793cbd451f9271fb5d25ea7c1899ab5d43ed8b9d067bc56d8d4a15f1dab8d8d95d1b17af64cb18c1147551147addcbdd53fbccd9026f855547131bee95071639f649f2d035a25a3e42e38e22bbf038106ce8bc4ad6768ab92cd57afacd04ee55cf0714b768952dac240b1e9b2835ecf7b0d6c407c82524a923b9f54d1b8f12564a872144efad3f3a7d2397cd1217dc5a9c96e43b2960a8425e97e07a02b0dac90f346b91a346a23ed2bb7fe6919c22dff03f62da7dba176e8ddb22f3f3a668891d3f4e69548d0ac4e71e6d28ed5a67ab5ac611d460b67a201f4f56a5003ca7a7d1cd1db6c10075b09227cb8c5dc1666f8be710b4b7bc2b95ae60da4f64179a50d2f88744361591671d36b7296315f6996439ad79821da8e772dfbf55a90d5d52ef7d76b35ffebd42e3525f4530c54a0f23b4d07c5f5974470e89404d176eeff9ef2333619691c59b7aadd42c296b1d0d328d9a3bd59a54bba93a0c1f1d62418c2190c38174b6abea02db66e818320ec4b8bac1c12f18f30dade27e63c58f9e7caf4bf69b265a2f9d91800861acf479e65ec17e680577e058cb16c109bcf9b2909fce3361a2c2685c10be8540a1222db5ecf0cc4d53a4214b7bf6248adc3a861e34841a3779c46046c5364f1ea91a78c9700d462ecfaae36ba760c1bd6a237c961edf4022cedefe5e937bbed7051ae61b96d08b0487ce0568ff0d32740bbd49ad0db86e09102ab21a915616e9dfddc81ebfb36c903e07a40cd2dd119ff4a50b93fc6fdfc0f36e59e0148fcff3fe8e2cd6d30a9e4b8f015567d118b6274e1ed75b22e44ca9d9dbfc160742cfac581e1a0bf5ff3326bc5f7896b9ca05a811d55e97c834d37a6495cc26cf442bd2d90129895e9cc0ed01e2155293f47a07ab5880c6ca29ed44d9ccbcaada7f3eb60402181488654e04911578b1aa9cdd4b86b0dd2450df3a43081e4110ab58de763924d3c89152e99293e638f9acd8d7: +a63c1f54b2ca058fed2ee2504b983ff33d570a9baba583c086cefe19f43ec49d329b866bca4194297fc1ad5a0eba0df956699c74ab7da5fa5462bd0661471020:329b866bca4194297fc1ad5a0eba0df956699c74ab7da5fa5462bd0661471020:791b86fd587713478f9234ff30cefc123cd7c3eb125fa74e4c6db64e7844f7c85b1686e71ed08d1a6a04e0ebbdff4ab160c976c8ab9b505f6a7eb0a18427e999a8828df10684f8c75b6a6b0a64c0afa4bb22bed1cb9325359cac3b8c508d98bcb0ebcd748dc132f1d6a360a4450d1292a1fefc4e57e4107a223f421e7d14a384b85c18844d0b9eed2ecb81bb74e8a12652d98505795a013116a7076ccb5493d6a711f7637e97a780e74da1b39b15cc7bbde2e6c4d0d3e8300597c836e80bcb8d8081d974e02432eac88368211d3aaae89a14417108e1ff6737083849c625b40d631f6c8357220c7f37380b3b2cc5d0e2df6b4d1196579dbc57b6c9ea0d41f4fa0e556f943c9448ef42fc78df5996648ce2f3de04d8a663f967f3d933d4f65357ab29ba5b6405fb162972578ddbb2367bed143c854c1088de921d79f5a92a854837eb7702e1ba925c6eac23d134ba1bafc5d46de2a1942c7f366f701b0afabb75cb1d808e1a1e4e3ae5de88e8e9989757458bddd8a806c110cc3a733d1d4ac58a405c4d81134fbc24ccde7d5afe420f9f1785f0a5020fafbb2261222508aa0528b7b48b567200958425efcb42934a880b133444bb109f2a954cfa35a2d17cb05ee3f16d06b321a15f91339abeda243ad6c0919fac51e907e053fdeed1cf03003734137793941b8adf9ab6af819c245d6d56f16964c8a75b0756a8cb0ca8c12ac6e6b3942eebec2f868835f81b109db498a4ca2e021fa765608d23d803dedc9e51453fc1d2a6a38a4aab257c0fe7d67d32a541e014b60e1013a92c1b3ad9e6f11be293b246f9a0c6440b0b54fee75fed2fb75cc91ecb32738c495831586a11242d87dcb4883edf6757a50b18843759b98dd0cef4a3fe10d76370ecda8c83fab87eee2656c5f261c340ea91a560d0e2c64289267f0036ba35944800a5a0aef3f1df839a724e181d79b8a3c16f65ae27953c4aae8ccd30ff5acc4b31e4765c68fb38319f10acf89247b5a39b3b08a191754a24aca9596a1f8a70b6e4f03a2004a9086ff6ed07652a926e1e2df7bdccd5bec16e5c4e968364a09abf9ded93df5fca0bcca5c812976e5cfb3c3493fc175d1d92ee8d1c98fb3382b3ab90c5c0e4bdf6a3ac94767b68d47e6b9c244265e3b1ab0623a8f0100273f2c607de89612c72d39be4c0b4d77a3c61368df40b3608652989d1e19c0aaf0e3c253e562c6409fe6448929b33753de162e6de5bd466a5114fc0e5f57102755e29544f03b28d4f78de9a024dd4c4e8c3c2d44115a7ae15edb4f558aa7dba6426e7e372c54f7940bd7714467f8c3a1add3c640189c31660d8cc01d3c5382e42abc104c723f948a804ca853047b6b87b5b6ef4:283359be41290a51e6a7c5d5725ca4ea0a68f14aca14b0f02566dee21f490da3c7e95f7ab739bc35a7f4f232e971aa157657a633eba0e72dc97af32cdb928702791b86fd587713478f9234ff30cefc123cd7c3eb125fa74e4c6db64e7844f7c85b1686e71ed08d1a6a04e0ebbdff4ab160c976c8ab9b505f6a7eb0a18427e999a8828df10684f8c75b6a6b0a64c0afa4bb22bed1cb9325359cac3b8c508d98bcb0ebcd748dc132f1d6a360a4450d1292a1fefc4e57e4107a223f421e7d14a384b85c18844d0b9eed2ecb81bb74e8a12652d98505795a013116a7076ccb5493d6a711f7637e97a780e74da1b39b15cc7bbde2e6c4d0d3e8300597c836e80bcb8d8081d974e02432eac88368211d3aaae89a14417108e1ff6737083849c625b40d631f6c8357220c7f37380b3b2cc5d0e2df6b4d1196579dbc57b6c9ea0d41f4fa0e556f943c9448ef42fc78df5996648ce2f3de04d8a663f967f3d933d4f65357ab29ba5b6405fb162972578ddbb2367bed143c854c1088de921d79f5a92a854837eb7702e1ba925c6eac23d134ba1bafc5d46de2a1942c7f366f701b0afabb75cb1d808e1a1e4e3ae5de88e8e9989757458bddd8a806c110cc3a733d1d4ac58a405c4d81134fbc24ccde7d5afe420f9f1785f0a5020fafbb2261222508aa0528b7b48b567200958425efcb42934a880b133444bb109f2a954cfa35a2d17cb05ee3f16d06b321a15f91339abeda243ad6c0919fac51e907e053fdeed1cf03003734137793941b8adf9ab6af819c245d6d56f16964c8a75b0756a8cb0ca8c12ac6e6b3942eebec2f868835f81b109db498a4ca2e021fa765608d23d803dedc9e51453fc1d2a6a38a4aab257c0fe7d67d32a541e014b60e1013a92c1b3ad9e6f11be293b246f9a0c6440b0b54fee75fed2fb75cc91ecb32738c495831586a11242d87dcb4883edf6757a50b18843759b98dd0cef4a3fe10d76370ecda8c83fab87eee2656c5f261c340ea91a560d0e2c64289267f0036ba35944800a5a0aef3f1df839a724e181d79b8a3c16f65ae27953c4aae8ccd30ff5acc4b31e4765c68fb38319f10acf89247b5a39b3b08a191754a24aca9596a1f8a70b6e4f03a2004a9086ff6ed07652a926e1e2df7bdccd5bec16e5c4e968364a09abf9ded93df5fca0bcca5c812976e5cfb3c3493fc175d1d92ee8d1c98fb3382b3ab90c5c0e4bdf6a3ac94767b68d47e6b9c244265e3b1ab0623a8f0100273f2c607de89612c72d39be4c0b4d77a3c61368df40b3608652989d1e19c0aaf0e3c253e562c6409fe6448929b33753de162e6de5bd466a5114fc0e5f57102755e29544f03b28d4f78de9a024dd4c4e8c3c2d44115a7ae15edb4f558aa7dba6426e7e372c54f7940bd7714467f8c3a1add3c640189c31660d8cc01d3c5382e42abc104c723f948a804ca853047b6b87b5b6ef4: +5b67a6d7c650dd92ddd036ce7a305bc959a497c5e515a68493035cb3850ee03d4c6fc1640505fb46669f93048f8ef557099f3fd92a53064b163363a31b7f00aa:4c6fc1640505fb46669f93048f8ef557099f3fd92a53064b163363a31b7f00aa:62ccde31772c57e4853aaf2a8181fdb53fb82790ea6501bfc8f5d4ae8dbd52de42ce2e8961ac1731f4bc085fb561ef09a2442970b6297901aeaa2ee555b7d5e3951c7c351239ddee95ff54f924da95cae7b15ba6a9a1337b8ce4921ed913cd791c1c6941080e548f3c36e845acbfd8d8ce35e2fdc2a2ad6c7e2461bfcbf1aabc55cf0fae428885be5e86533308c9756805219abd7ffc1657b6f4632920a0c10e0e363319d900fcd61e7ddbcd6e762a7db92480c363b2c0640c6bf32d690dd829d8405fa66e4783ebe1cbde9547954a90baad9f774e94549abbff2c1f5caec2bfd28e415d36429d58518c3e17e8699e1989d47b8d627ef9ab4d1e7d120b372c2141304f7fabd0265b8be41f5467f4de9e65c125ee1f27a289c4f7c9a1fbf25bfc2f8d308e7ff52191cb7644c6af204522f2ac87b5f40525fd43d308c8dbc6a861d25db23ee276678a1b6e8e91283be02470482ed6cc9f6e396351d11b1c7e22329c091fe7d368f60653f93b0f6a3f712c20f9d2d8a9a0819872f0c71d7b1c0bc1683a152b484bc21cf556093ab4c0ac16d322ff0bf452e5581e1e7241673884023c7d6e17e2de8059f60e4c18e13bd55fcfee623fd0469c0d0911611d099a257020f2f31bf5078e6e65a135d5bf407620236d6cc759310fa728ff8bb5ec56abbe1a3cd15153f892d958d30d162d01ee665f5b562781d8dcf8428059e5fd225ad78a99ea760fe5d9ee8219c95acb18d05622e10a9b6c67f6d4f6ed11635c5e2e0f85dd5d3cbda65aa423d594a80b40427bc321e0eef9afd2bc8746ab7399ff6d0e1287b661ddc4062d072018f4c10e86cfaed72d9e686ed09d5255d360e3eea2c29b9eaea05fc78c8cdb8c9d4afc7adc6d4aa067b7abfb0a4e940a77580ec206456cb9e9f95f6d565d536e535a167ede8e20ec36081e2fc55aefaf24d227fffe5e6cb03093f443b4c51655d91ca6f275959d1a802adeab44701b31e8b0fd0222c499966c72d1020ad9370e2802be04c9933f6b774f6e8c69fc0bfd315939a127b4e06d0f6f5ede671ce11612126b5187b53329b0a9cb7da3b1ccd67b8c07bab99a662df8ce851f502fc4e1ed1632b6ba555544018f7527e362efc7e3b2ba6f75a1254f428b3b7e0bea69549e7f9c736275550080aee3af5914e3a34be656c77f6b29420e5433f3dff3811f3528208e9d850aa3c29b0f778a2427d5fde30732dfe50443a9c1ad55c72a08ab26ffaf8efb90bcafd3726b00c005c8c0f0dbf2a1353086721e446545b813441194a755fd26b963afd977278d1b10f09001c7ed975403c15cbe7f992ab07b8470c939f866f420f77db779af839700329e0777a6116365d76c36d09d860472a5:0f073c9a586f6f5e08389a2a5e1808e270f0edb6af104496f93757623fea53133a731c445ac23578cd56a3883c08958668631fedf1446ce34f857f90822ba80a62ccde31772c57e4853aaf2a8181fdb53fb82790ea6501bfc8f5d4ae8dbd52de42ce2e8961ac1731f4bc085fb561ef09a2442970b6297901aeaa2ee555b7d5e3951c7c351239ddee95ff54f924da95cae7b15ba6a9a1337b8ce4921ed913cd791c1c6941080e548f3c36e845acbfd8d8ce35e2fdc2a2ad6c7e2461bfcbf1aabc55cf0fae428885be5e86533308c9756805219abd7ffc1657b6f4632920a0c10e0e363319d900fcd61e7ddbcd6e762a7db92480c363b2c0640c6bf32d690dd829d8405fa66e4783ebe1cbde9547954a90baad9f774e94549abbff2c1f5caec2bfd28e415d36429d58518c3e17e8699e1989d47b8d627ef9ab4d1e7d120b372c2141304f7fabd0265b8be41f5467f4de9e65c125ee1f27a289c4f7c9a1fbf25bfc2f8d308e7ff52191cb7644c6af204522f2ac87b5f40525fd43d308c8dbc6a861d25db23ee276678a1b6e8e91283be02470482ed6cc9f6e396351d11b1c7e22329c091fe7d368f60653f93b0f6a3f712c20f9d2d8a9a0819872f0c71d7b1c0bc1683a152b484bc21cf556093ab4c0ac16d322ff0bf452e5581e1e7241673884023c7d6e17e2de8059f60e4c18e13bd55fcfee623fd0469c0d0911611d099a257020f2f31bf5078e6e65a135d5bf407620236d6cc759310fa728ff8bb5ec56abbe1a3cd15153f892d958d30d162d01ee665f5b562781d8dcf8428059e5fd225ad78a99ea760fe5d9ee8219c95acb18d05622e10a9b6c67f6d4f6ed11635c5e2e0f85dd5d3cbda65aa423d594a80b40427bc321e0eef9afd2bc8746ab7399ff6d0e1287b661ddc4062d072018f4c10e86cfaed72d9e686ed09d5255d360e3eea2c29b9eaea05fc78c8cdb8c9d4afc7adc6d4aa067b7abfb0a4e940a77580ec206456cb9e9f95f6d565d536e535a167ede8e20ec36081e2fc55aefaf24d227fffe5e6cb03093f443b4c51655d91ca6f275959d1a802adeab44701b31e8b0fd0222c499966c72d1020ad9370e2802be04c9933f6b774f6e8c69fc0bfd315939a127b4e06d0f6f5ede671ce11612126b5187b53329b0a9cb7da3b1ccd67b8c07bab99a662df8ce851f502fc4e1ed1632b6ba555544018f7527e362efc7e3b2ba6f75a1254f428b3b7e0bea69549e7f9c736275550080aee3af5914e3a34be656c77f6b29420e5433f3dff3811f3528208e9d850aa3c29b0f778a2427d5fde30732dfe50443a9c1ad55c72a08ab26ffaf8efb90bcafd3726b00c005c8c0f0dbf2a1353086721e446545b813441194a755fd26b963afd977278d1b10f09001c7ed975403c15cbe7f992ab07b8470c939f866f420f77db779af839700329e0777a6116365d76c36d09d860472a5: +2631c8c34d2948ddd5996b4149cefd238ea7452ec22e246124dfa279ccc27db8c3906786ffb8a7c27c44c2447f9dde7d666dfe588cfc54f2d25040512a371bc1:c3906786ffb8a7c27c44c2447f9dde7d666dfe588cfc54f2d25040512a371bc1:6f9bdce1443f2856d4a2f22782835012b7818a0e020dbcc22a821658305f134234d14cea636100ed896c2a8fb0e87048ec6f8b31484f78eb171045add72c85710ec9f9b5d43623417b5653be86e7fbf8b4ff91110a808cb41acf66d436e89a737faea4eff3544960f114b833b0b4ebc2c14070b0bfb7b0057eebb842bd1c1ed458ad3428f8f72a1d1db3c4cb4797a399d47a1e6db74dcb2ee24ae81585cf66ef6d9bd223f0f54bc8c1cec1bb4460bef4ffd32ee805c3ca5ee976ff9c14559f8d756662a2bc19e4c5985406a07305c9950d866c9a79a3e5f6c5969753a170e0fc4cc09c6d87a12b44cdf3be1623159e90cab7a8a3e6f01f268595b021b1ef7d00769477270d5584c912e22a367438277f59df20c5620dd5beaa9bb60bee47f4af527d892957b2d12b678b5279a3f83264654c0a0f8d21e709668f30fb6e68f047d0d9a7c2ae9a28f7cb9dbf18f63fc1661f07d310e540c77631f5bdac5824685d7c9aba0fe1d09407a9662ef18eb3e28fd1e8bc892657bc38243a2e6453bdaeabb2791fc5489521295457ad04180ca871f6318792bd15fd1800ce59dd3ecc7e0b72979267d8183e804fdd45daad84fc4cafeb561ea8d6a74a7cde722d96253ab3e75f0adde02a61fd5e1f59cb1f5f1b2e052643589a9e4be4dd6ee64538cb0b109a113f30a58b3565624043662abe17f60e31e89c36c995e00ae07f56a9118a31aec24ad544bc965811218df827c1730bb904bb79b68613f6c994679b6990d775b5cb32db97194bd81019bea41f3a7eef501bf8491b0ea859388452e3ecbe16aa7d5691510a6606c493e4c293961bf40b4cd300d9d22ea1a7724c078b8bab1fd16504e989b136d9251ac9f1ed94a5e9acbd9c04f8058afe03049aed8ba29fa2e8fb44f8e8c04e8727f399e735e6c1496a91a9b2cd2ab02d43b285e9d7610293b6749df1044b30e2da99a564429a23e68c96fce92b08a00b7b742ba97a62ee58776d7dd565a490071d4b19dc648e03329cc5c825d387eba49e2eff6c4341865c464f13f1beb1827a7f268cc15a982480bf084fe3652c1b0e0b4ad26255859abf1c8a7f9b3bef098a9407fdea0a539eb008fdd749fa0186cc0169d9d9e68fe5e54cac32ce57b5c84c2d805eca39c2dbbdd2e02f7d228826712ff4a61411ca0aeb6f01a1f80ef29eeb071a43222d9497184bd85d9e44b166be97cfd2a732af4a233463d3ab543a7a3c7aec555656568840f4dfea217f6553aa98af324c12b2c3214ee76eec700670af68c8c1f36946efd7ff0933e5453f128e9715fdb3344ac10c4bb7ec8f10ddf5db71f1cf0efe40f75e5b6334ef8cf8429b3291e6e4ce379c178affcbc61030eb896d744d:0adc6fa40ffb81f6ef4e4187554917775cf465e7b5e857f2e1e7f400977106d2377ebc76abb1db924c64867e3c6fe38c0b4fcb1d0f9468e8fb235029a81ce6046f9bdce1443f2856d4a2f22782835012b7818a0e020dbcc22a821658305f134234d14cea636100ed896c2a8fb0e87048ec6f8b31484f78eb171045add72c85710ec9f9b5d43623417b5653be86e7fbf8b4ff91110a808cb41acf66d436e89a737faea4eff3544960f114b833b0b4ebc2c14070b0bfb7b0057eebb842bd1c1ed458ad3428f8f72a1d1db3c4cb4797a399d47a1e6db74dcb2ee24ae81585cf66ef6d9bd223f0f54bc8c1cec1bb4460bef4ffd32ee805c3ca5ee976ff9c14559f8d756662a2bc19e4c5985406a07305c9950d866c9a79a3e5f6c5969753a170e0fc4cc09c6d87a12b44cdf3be1623159e90cab7a8a3e6f01f268595b021b1ef7d00769477270d5584c912e22a367438277f59df20c5620dd5beaa9bb60bee47f4af527d892957b2d12b678b5279a3f83264654c0a0f8d21e709668f30fb6e68f047d0d9a7c2ae9a28f7cb9dbf18f63fc1661f07d310e540c77631f5bdac5824685d7c9aba0fe1d09407a9662ef18eb3e28fd1e8bc892657bc38243a2e6453bdaeabb2791fc5489521295457ad04180ca871f6318792bd15fd1800ce59dd3ecc7e0b72979267d8183e804fdd45daad84fc4cafeb561ea8d6a74a7cde722d96253ab3e75f0adde02a61fd5e1f59cb1f5f1b2e052643589a9e4be4dd6ee64538cb0b109a113f30a58b3565624043662abe17f60e31e89c36c995e00ae07f56a9118a31aec24ad544bc965811218df827c1730bb904bb79b68613f6c994679b6990d775b5cb32db97194bd81019bea41f3a7eef501bf8491b0ea859388452e3ecbe16aa7d5691510a6606c493e4c293961bf40b4cd300d9d22ea1a7724c078b8bab1fd16504e989b136d9251ac9f1ed94a5e9acbd9c04f8058afe03049aed8ba29fa2e8fb44f8e8c04e8727f399e735e6c1496a91a9b2cd2ab02d43b285e9d7610293b6749df1044b30e2da99a564429a23e68c96fce92b08a00b7b742ba97a62ee58776d7dd565a490071d4b19dc648e03329cc5c825d387eba49e2eff6c4341865c464f13f1beb1827a7f268cc15a982480bf084fe3652c1b0e0b4ad26255859abf1c8a7f9b3bef098a9407fdea0a539eb008fdd749fa0186cc0169d9d9e68fe5e54cac32ce57b5c84c2d805eca39c2dbbdd2e02f7d228826712ff4a61411ca0aeb6f01a1f80ef29eeb071a43222d9497184bd85d9e44b166be97cfd2a732af4a233463d3ab543a7a3c7aec555656568840f4dfea217f6553aa98af324c12b2c3214ee76eec700670af68c8c1f36946efd7ff0933e5453f128e9715fdb3344ac10c4bb7ec8f10ddf5db71f1cf0efe40f75e5b6334ef8cf8429b3291e6e4ce379c178affcbc61030eb896d744d: +39769a66f0ca1290fda14375b35c663f6a4b2ab3607179abd99063e2efa2c6a8f9fd4c191f38f12190d3285e20c6cee54cfd6ff315300a4efdc8a90e80af4083:f9fd4c191f38f12190d3285e20c6cee54cfd6ff315300a4efdc8a90e80af4083:ff4d8987e3fa36012b7586736b793d659754698cd12b65e5ba9d758cac1649288d20224377283ea5425dec10ab9917d18cd13d1bdf4a769f37044c84faa2a449c689e004c14e005c49da4106ff75ce1303361c6e3e34ccfee75ee9c31cbd06a4bcdbb42fd649be4dfcd664006d6a5f61077c04a6a81db36be86ba42c2951f051aeda64acea496cb924982b9f7d234ac9723fef98a8e12755e326a52fbe35851f411eeb867606d45b513f54526391c554635c180b8fd0ee451afc96e4efd360b61e6baf03dd6d19ba515c31ec1cdd3affffdb27354e3e6b56e9e1a1a1b7d4b57d9d7689bb2fea6c8d3f9ce0df2d9ee919c4230a1f20b85dfefe1ea3d7f77db470e4022429ef609b0ff44946440acb44cd13445bcfa3f20503c26c2fb663c89065fb9334a603eb9ab7152e62629233c44cb00e77716d9b72c84fd1b340634ff1cea347501576100ecb0fd1bb76ae0dff1c2b0948eb71ee2cc31e79d3015d72dbee224a980e0f95a69f793da83a2daa56efe57b2f8ceaac9e55f443ca9e732b48c75fac21c36fa77273c3f34835ffd83c96f00ac6e86cffed08153646c1cea223da9ca360cab97e03b2b6c8fba7c195a39ae52eb2ee864300ae56a10f547f99a3169872249f97774b1798935536f2f5f011ce57613a94fcb7e7286a6d49c10fd929d7671cbb8cf17dfcad4b2485c3d8fd79128721e55d84808763c2afa9c55e3b0cd7bf2f0a66b5e467bec5ee89ad570b60f188b3f7b4a511ff859312ded078d8d0091134fd49bc792d2d7d60b304941c7f23206f99e863b1e2d8c9ecffd2ff0a3a3c754985615a9a92edcead00fe0e05493b198d1f7c90088446bba46038a71f32653b5912b24f43137748b75aec2c15fe4bf5a6f86b8a6cdd9c7447f2ebb0f43b01ca1523e0d496240006ad7ffffafe0df5754b342caff3555d72a27d0b92ca1667665cec43bfb583077a9c1741fa492ce3dc2c7529cded81b8281a3f375948b8a7ced096b2facc25e39029e221b66a53d3979e1f405fd88afc06ec6e4309dc85e69d6ef2b4b49266164a9d9d1c31ee3921127b13381bfb740dd38dc1c7315921f9c2fe58b61b631a7d9fde2dd8a4be3ded0490ae3b8376791955c1c4b4fed00b9f4c38ab7350fc2e37a3150c18162b1faf0337894bc23e74f595e4be33466deab35458be97b4f7565897f06852f71c60fef9101d726b72e0102a97b2ca5211e3806834b0ac1a7df87c2a078df263ef8ba457dc891b7f2e627811ab622b9946f8c6b731f24078d17b06b200c3447f8032aa3e7a243ee422dda2e652fd75713afbce8a59ef8536653a48dcf42a70e7621f9b2802409be1c1a61f32e36789a5c5055e1a8268e9dc438c2e1527:1442dea2807e031159ec6a412d8e07bb3e299308090f218fa7c10a9c5068ef9b64ef11ca9fb92be1d0216b99318ff0f03cb871cd7dd63a38ae1702313e5b250cff4d8987e3fa36012b7586736b793d659754698cd12b65e5ba9d758cac1649288d20224377283ea5425dec10ab9917d18cd13d1bdf4a769f37044c84faa2a449c689e004c14e005c49da4106ff75ce1303361c6e3e34ccfee75ee9c31cbd06a4bcdbb42fd649be4dfcd664006d6a5f61077c04a6a81db36be86ba42c2951f051aeda64acea496cb924982b9f7d234ac9723fef98a8e12755e326a52fbe35851f411eeb867606d45b513f54526391c554635c180b8fd0ee451afc96e4efd360b61e6baf03dd6d19ba515c31ec1cdd3affffdb27354e3e6b56e9e1a1a1b7d4b57d9d7689bb2fea6c8d3f9ce0df2d9ee919c4230a1f20b85dfefe1ea3d7f77db470e4022429ef609b0ff44946440acb44cd13445bcfa3f20503c26c2fb663c89065fb9334a603eb9ab7152e62629233c44cb00e77716d9b72c84fd1b340634ff1cea347501576100ecb0fd1bb76ae0dff1c2b0948eb71ee2cc31e79d3015d72dbee224a980e0f95a69f793da83a2daa56efe57b2f8ceaac9e55f443ca9e732b48c75fac21c36fa77273c3f34835ffd83c96f00ac6e86cffed08153646c1cea223da9ca360cab97e03b2b6c8fba7c195a39ae52eb2ee864300ae56a10f547f99a3169872249f97774b1798935536f2f5f011ce57613a94fcb7e7286a6d49c10fd929d7671cbb8cf17dfcad4b2485c3d8fd79128721e55d84808763c2afa9c55e3b0cd7bf2f0a66b5e467bec5ee89ad570b60f188b3f7b4a511ff859312ded078d8d0091134fd49bc792d2d7d60b304941c7f23206f99e863b1e2d8c9ecffd2ff0a3a3c754985615a9a92edcead00fe0e05493b198d1f7c90088446bba46038a71f32653b5912b24f43137748b75aec2c15fe4bf5a6f86b8a6cdd9c7447f2ebb0f43b01ca1523e0d496240006ad7ffffafe0df5754b342caff3555d72a27d0b92ca1667665cec43bfb583077a9c1741fa492ce3dc2c7529cded81b8281a3f375948b8a7ced096b2facc25e39029e221b66a53d3979e1f405fd88afc06ec6e4309dc85e69d6ef2b4b49266164a9d9d1c31ee3921127b13381bfb740dd38dc1c7315921f9c2fe58b61b631a7d9fde2dd8a4be3ded0490ae3b8376791955c1c4b4fed00b9f4c38ab7350fc2e37a3150c18162b1faf0337894bc23e74f595e4be33466deab35458be97b4f7565897f06852f71c60fef9101d726b72e0102a97b2ca5211e3806834b0ac1a7df87c2a078df263ef8ba457dc891b7f2e627811ab622b9946f8c6b731f24078d17b06b200c3447f8032aa3e7a243ee422dda2e652fd75713afbce8a59ef8536653a48dcf42a70e7621f9b2802409be1c1a61f32e36789a5c5055e1a8268e9dc438c2e1527: +0c808b066f0c8e8dbb1c23d6c2cedd0be866d8425f241a9285700ea54536cf6d44ee72900450c56ab21f2686d29525d0663e0bdd87725beac5d68baceb69f1d2:44ee72900450c56ab21f2686d29525d0663e0bdd87725beac5d68baceb69f1d2:c945714100581f4e24da11fc0f6c6d0210433f9777525124c55ee072d85d798b705f9d31c8f977db6edfb7a65c78ad2d7d31d6b7b5be40ff1178d303b6839bb0c63210c1d338c103afa0d453eca1bca277d930778ad50802272f03dbe2184fc31ef8ea6abe216997199f7c1b337737968907272aa51bd49c07389c95468cef4fd99ae78ca4542a2bbc0e8aa95214ad1cfff9d5085a434394473b84b74be9bf2f0202ad1ee4616604ca1dd75f4a195342ebbf8fc59f3f79616554dc7bfdd556be437221c10bfad39e119e06045be5fed683d3534fb6cfed33891c96f9c330f28b684f8fbad47c01418eab6ceecc2ed777f4c218a27ac22582392315c53aa7309ec54c6175236e4424dc978465ab628d9544b0be84103eb56f1bafe5e5eaed04c98bfe2e8a2418c6c52a61eace85236b66c7b3b8707ed55641dd9d5da97c99c11cbeb9aa2db147820dc724800a9d80f505fa5af20921cad2435683bb4fc60bddd475f863e2f5950d236399d8d75b404b394a546737f93a62408700b3ab3c1e922b1a859a2915c2d35368815cd45b85b2ac083121ff000f050dcdf415e5275a5c42dae3b15400f3ddaf9339f20a1261a88cd90205639763211152df414a9a6a6218f56b35a2de9e8482449f6da77c9e3d4af0493015a726217f82ac58954fe3e2e34440356b112e06a6f671fb5a6ef4619a6ea7b4e04db3757fb664c396b341ca89001dc1604b51fa9153f9130c1020ff88909287823ab3915ccc85c4e35df6c2f8e6f902be82ba21297fd3835aff5ce02f3c07dc093fcb1aba26e06dfe6f02df79291aaca069ecab9381404c9c3ea1ad409adf292a91e3a582d5a7b68ffbe10a0305248e0967e6df372f281bd192e139979c9866ca8fe1e10e0616dc2d4f85e119e0cb4bfe8cc31d9f5c018b65408524000a3016a23d9914d57e955576e2660b0e0d96c8495a12c3d73122d200b0f0e5ebd446562b08f47934ab499a96991dcf99c96a62880739845d29820150553eae9be0bb41d53d3af01d9867bb4732c90bf6e137316e3b1edcc209a8a09fb062a6ef05f37e57f2c5d1d0cabaf07a8ed7d41455407b096754180aa96d3d96591945dd7a1040a2de60d8e1c054f7854652b732e7a8f5b6474c3baa1840fbe81b1e6b54e201ef0bc8d0f213d7cec1d824d22209ac72525a64b903e773b83f1b68f640279f15053d21ec15ce2ff75922176b7584a16bf1a1f0d636b7942a3d61862f6fd1309972d3141eb769314ca975d020bf02bfddf17d14b60eb786bf9f55989fe473320d4429677e301c682633f813ff26c0a3da92f6d0680616105b0425af338c2ea6153bdd5216fae2afe461e9249c05e32f76ad7c429d92534b686dd1:38c682cedefb13e46b11f7b5f800cc8120d45a83cd8d8dec10c577bb0153d509ba4fdf400998788b706007ce162b96945c7140beee74e19d0743afa4ecfd250ac945714100581f4e24da11fc0f6c6d0210433f9777525124c55ee072d85d798b705f9d31c8f977db6edfb7a65c78ad2d7d31d6b7b5be40ff1178d303b6839bb0c63210c1d338c103afa0d453eca1bca277d930778ad50802272f03dbe2184fc31ef8ea6abe216997199f7c1b337737968907272aa51bd49c07389c95468cef4fd99ae78ca4542a2bbc0e8aa95214ad1cfff9d5085a434394473b84b74be9bf2f0202ad1ee4616604ca1dd75f4a195342ebbf8fc59f3f79616554dc7bfdd556be437221c10bfad39e119e06045be5fed683d3534fb6cfed33891c96f9c330f28b684f8fbad47c01418eab6ceecc2ed777f4c218a27ac22582392315c53aa7309ec54c6175236e4424dc978465ab628d9544b0be84103eb56f1bafe5e5eaed04c98bfe2e8a2418c6c52a61eace85236b66c7b3b8707ed55641dd9d5da97c99c11cbeb9aa2db147820dc724800a9d80f505fa5af20921cad2435683bb4fc60bddd475f863e2f5950d236399d8d75b404b394a546737f93a62408700b3ab3c1e922b1a859a2915c2d35368815cd45b85b2ac083121ff000f050dcdf415e5275a5c42dae3b15400f3ddaf9339f20a1261a88cd90205639763211152df414a9a6a6218f56b35a2de9e8482449f6da77c9e3d4af0493015a726217f82ac58954fe3e2e34440356b112e06a6f671fb5a6ef4619a6ea7b4e04db3757fb664c396b341ca89001dc1604b51fa9153f9130c1020ff88909287823ab3915ccc85c4e35df6c2f8e6f902be82ba21297fd3835aff5ce02f3c07dc093fcb1aba26e06dfe6f02df79291aaca069ecab9381404c9c3ea1ad409adf292a91e3a582d5a7b68ffbe10a0305248e0967e6df372f281bd192e139979c9866ca8fe1e10e0616dc2d4f85e119e0cb4bfe8cc31d9f5c018b65408524000a3016a23d9914d57e955576e2660b0e0d96c8495a12c3d73122d200b0f0e5ebd446562b08f47934ab499a96991dcf99c96a62880739845d29820150553eae9be0bb41d53d3af01d9867bb4732c90bf6e137316e3b1edcc209a8a09fb062a6ef05f37e57f2c5d1d0cabaf07a8ed7d41455407b096754180aa96d3d96591945dd7a1040a2de60d8e1c054f7854652b732e7a8f5b6474c3baa1840fbe81b1e6b54e201ef0bc8d0f213d7cec1d824d22209ac72525a64b903e773b83f1b68f640279f15053d21ec15ce2ff75922176b7584a16bf1a1f0d636b7942a3d61862f6fd1309972d3141eb769314ca975d020bf02bfddf17d14b60eb786bf9f55989fe473320d4429677e301c682633f813ff26c0a3da92f6d0680616105b0425af338c2ea6153bdd5216fae2afe461e9249c05e32f76ad7c429d92534b686dd1: +049dac3c977d9df503496b43d76e5540e315001ad57f15ea9f0870cad2d4f9e9fc6f4b7eb39a711680f966d468a61abb13a9b6449bb99fda3d12ce1b506d1b4b:fc6f4b7eb39a711680f966d468a61abb13a9b6449bb99fda3d12ce1b506d1b4b:7f31e346f68da73716aacb16eea19bb24142dc283e7263ffc3f704a22ae5275a0ef95f0669bae5a54c7feb84bc74873cca0f335d6cff3d8b4a20056c64f5e882cbbbd2ac74207676467e5466ddd56aedf56e097c7f59d945915eb0ebd0c3c83d48888d3e9ede51ad2dd8a0ee1eab4cf87ffa78635afc4d6ef3e87dda3b65565c2985a4ad0acfdfb81cb0e61c67826a6ea0bed4c08aa1a541de60458704ac21ca12f1c8118bb3092c35a40c921e684564562c2c1049dcdc2b8d6a97e3567d356bffb5692a41d89ddda0ec3552152a27577f1cce57d00986dca77edf5e2518158200adf690affb31aaf2b574836839440999f15791cea85342ac94a96c7af7a19e494310ae26675f43c35258e85b6840b99c6b09cfa58d19f1e43a77e397b08c0db1830bca67b39ecd8752da611e0832c6cae7bb8ce74a82e7e7330be5062ed05aa5c84457b007fb5ccdc20a55d54d8e0409c8bd83883d2e029dff26ea5db275dce099e418659a0400f13be9ffdc14e7d645a94677ca846970b7e6ac527fa009a359454b3c49364905189fb49c9bacb650c03cd82875894e3546ba03c32e336fc6516a87676c50d5b80b3054273b157c5d767514e54574b8a101985a8e967e95da8f929800260e08148beee2d7781e9e85d463a94ffefdbb75c28fa8898015680999429cee798b3fd2d96737868a263fba9fb6f4aad56a15c6412ff85e7d3752102daaf25e745fa5f6f174a231fcce8624dd70856f9babcc209144ff6864648dea0d6884566a4c39147805be084e4740bc509309bcb142964bb0cfcf6726a0e04bbf32ae6834732bda0384cea8f4a4849bba0d18646c1c34471896b5bef149f8cab9ec83722b0fb209efe8a04c4a235dc8ddb20acd92765afbf3058740ea70b9c10d9c5aef8606298fe4151593b21f797d92ae9f1e0881b0d271b0d5b10c6ed83c349ec2473fbf2ff780dcd076d8cf0aeafa71fe2b8c5128015f8fbbcfecd5281cd5eacb6fe9ac6eaa6e47d667b9ad4b7e411e6cb7463d567607afbfd0418c4eb06afe847f5e40b499443828d5a273a4a87e46def21a919d73863af0054a099e3adc5450b8e32f51ea52c599a4a2a35351788af7cb71e5c44bcb8df54a601e6ec2c1828b48c4b1ae4463106f10efa5caf3091abf99aaba5252f484d3bbc62bfa6b2a806d23c6331a62fc46bc627679e73ec82dcc08f79143f4b71ecf357ea2f0d74e6d3058e606043f6e8fed704282c16b1f988ffa365cfae9a3cf792e0c5baad70ca7e25776018b5e7f0e9544e1d73f3e5d1e416a5e50fbed296dc1bf4b29a3fbe32efbd7e99c83015d27f535adecf175fc36c1ea4f4423b36dcdc054ba993278e85ac3622d435f5237ba61b49a:7532d1a61a981f303d7c2454354f99540cd484cde9ab337d6f7b51f179220f7fa2073476b41c71529f9836db6b1d0f5a482bbb4c68366176ed14d4d8eefade0d7f31e346f68da73716aacb16eea19bb24142dc283e7263ffc3f704a22ae5275a0ef95f0669bae5a54c7feb84bc74873cca0f335d6cff3d8b4a20056c64f5e882cbbbd2ac74207676467e5466ddd56aedf56e097c7f59d945915eb0ebd0c3c83d48888d3e9ede51ad2dd8a0ee1eab4cf87ffa78635afc4d6ef3e87dda3b65565c2985a4ad0acfdfb81cb0e61c67826a6ea0bed4c08aa1a541de60458704ac21ca12f1c8118bb3092c35a40c921e684564562c2c1049dcdc2b8d6a97e3567d356bffb5692a41d89ddda0ec3552152a27577f1cce57d00986dca77edf5e2518158200adf690affb31aaf2b574836839440999f15791cea85342ac94a96c7af7a19e494310ae26675f43c35258e85b6840b99c6b09cfa58d19f1e43a77e397b08c0db1830bca67b39ecd8752da611e0832c6cae7bb8ce74a82e7e7330be5062ed05aa5c84457b007fb5ccdc20a55d54d8e0409c8bd83883d2e029dff26ea5db275dce099e418659a0400f13be9ffdc14e7d645a94677ca846970b7e6ac527fa009a359454b3c49364905189fb49c9bacb650c03cd82875894e3546ba03c32e336fc6516a87676c50d5b80b3054273b157c5d767514e54574b8a101985a8e967e95da8f929800260e08148beee2d7781e9e85d463a94ffefdbb75c28fa8898015680999429cee798b3fd2d96737868a263fba9fb6f4aad56a15c6412ff85e7d3752102daaf25e745fa5f6f174a231fcce8624dd70856f9babcc209144ff6864648dea0d6884566a4c39147805be084e4740bc509309bcb142964bb0cfcf6726a0e04bbf32ae6834732bda0384cea8f4a4849bba0d18646c1c34471896b5bef149f8cab9ec83722b0fb209efe8a04c4a235dc8ddb20acd92765afbf3058740ea70b9c10d9c5aef8606298fe4151593b21f797d92ae9f1e0881b0d271b0d5b10c6ed83c349ec2473fbf2ff780dcd076d8cf0aeafa71fe2b8c5128015f8fbbcfecd5281cd5eacb6fe9ac6eaa6e47d667b9ad4b7e411e6cb7463d567607afbfd0418c4eb06afe847f5e40b499443828d5a273a4a87e46def21a919d73863af0054a099e3adc5450b8e32f51ea52c599a4a2a35351788af7cb71e5c44bcb8df54a601e6ec2c1828b48c4b1ae4463106f10efa5caf3091abf99aaba5252f484d3bbc62bfa6b2a806d23c6331a62fc46bc627679e73ec82dcc08f79143f4b71ecf357ea2f0d74e6d3058e606043f6e8fed704282c16b1f988ffa365cfae9a3cf792e0c5baad70ca7e25776018b5e7f0e9544e1d73f3e5d1e416a5e50fbed296dc1bf4b29a3fbe32efbd7e99c83015d27f535adecf175fc36c1ea4f4423b36dcdc054ba993278e85ac3622d435f5237ba61b49a: +f07d61b5ca1c2700cb50f900c26b7c28f6c6940808c7bafff74fca4b11f425d4eb243dfacc2dc6435776d554eced8bf92390604b35557cda51fd203eddb493fa:eb243dfacc2dc6435776d554eced8bf92390604b35557cda51fd203eddb493fa:c1c67843d69a0e62e7bf71f90206a3d5595ca3c482aaa767e931b0d6c2f4752ab86991f03583bb138e9f72fab58fd602a4b6b29602cf891408af5a1bfd3398c0178c441461e3f49bc81d64c0d97f5ded692c75d4d64dac5d80d63bd4dc5210c1d9350b142ba6e768f150807ab8a86cacdb59d84ddf660be56203c014fba1e0dc16fa6d32694e14b128edd1f6c6ab445a3ad34174fa9e4b01f25b1d5e6eb76983b4295ce4914d3ae48c704a30e554fc1f868b6272eff06da24bfe17e4e0f0fa46bb08ffb907cb61bebe52df311a64cb578b30fd627df11221ae4003a0b0c68e3c6f95a21c8500d41b2c589cc46a139cacff57dcf00759f52e9ca3dabdb1788ab6b38a5048f58e08e05c394f9d3c72113d452b7084c519f86c1689ffdbae506ed8450522cbe43de27aa3bfdd92a91b71e52a3cbf77c1bd2893eabd407a57fe5e146873bfb2043f4a6147df083e54a2208d1925813fa404e4c47406e7728643ebfb0b10142f909ef856fd3a916bc0851543b82a55f8cd529bd21d9e2909d6d7e77bdcea4673e545ff4a67fa37d65f1f63f11d5d0d55974a30abe188335db5dcbd356658f9b77682d96dabb258ea95951a0559aea4064d5ea1680501dcb4228f2c956f81d2101144af74c716bc8bf4296dc3b831725cc17d3bfd9066a29953b2ecd75059435b49a25ac525b4fbab1779022dfb6de525149dcd902ac8a7e21f344f5f0101480692d61608952c71413e30037945e206c5eeadfc3edc4bae0d796ca0c5f56d6ffb3f0969df9df8a794f5dc83a3b2f5c3ab36bb901bcc31551c550c63fa41d6a8d57bdb9b5c65bc610c3a989752ab28a015e7c2f6b2fbf199a76b9750c0d3d592119c8b4022fa45bade2fbb41432679b52acb4608a95c34aa40bffec10bc98f4729dfccb650b2a052dfb068959e648a92d5aa4dd2d17dde67cdf2e6377af0d4ae379607389d7e3596441b9f4222cff6af73b3300270ce54800bd934a9109a02563adc56ae46584451cdaf4a77538157e5870f4ae12dbc81870f5db41a2cb55e00db3d2231628f1727c3acb99ed3acd8b67156a8005a4cc8f3d3555b79a03773a931f14eebce40b9fe46ede5da0881fb220717e418e8b5a0fe5e477e7285c554e859e16441672b489934a3a9eeb88d78fcc5c1db2d1fbdde392773f6c939972ee8fa3189f4e9872b4abdc83b379c0c10e818dcff75c83d6870729284ced41f2ff55a87c960e63d1211f08071293f6ac63f9bdef38fd5919ca90b3f5e25a6c0c664c4ecf831c64e2d4c6e798a98a3a0f7be7a2463eadaa6a2a348f9a494717123cc0a28c0a5eae3f5b585f2cb8cb260c2c503e41578573cd9b7cba1408dca9d860ae4f8c3d3f322a45b58a2c4:c19b532b8248563932639701bf15bc015faebb17bb98d871616e1048d64ca5f955f558f63b5353a1576fa1acaef39bcbc9021756df5d1ab3bc741accf9059b04c1c67843d69a0e62e7bf71f90206a3d5595ca3c482aaa767e931b0d6c2f4752ab86991f03583bb138e9f72fab58fd602a4b6b29602cf891408af5a1bfd3398c0178c441461e3f49bc81d64c0d97f5ded692c75d4d64dac5d80d63bd4dc5210c1d9350b142ba6e768f150807ab8a86cacdb59d84ddf660be56203c014fba1e0dc16fa6d32694e14b128edd1f6c6ab445a3ad34174fa9e4b01f25b1d5e6eb76983b4295ce4914d3ae48c704a30e554fc1f868b6272eff06da24bfe17e4e0f0fa46bb08ffb907cb61bebe52df311a64cb578b30fd627df11221ae4003a0b0c68e3c6f95a21c8500d41b2c589cc46a139cacff57dcf00759f52e9ca3dabdb1788ab6b38a5048f58e08e05c394f9d3c72113d452b7084c519f86c1689ffdbae506ed8450522cbe43de27aa3bfdd92a91b71e52a3cbf77c1bd2893eabd407a57fe5e146873bfb2043f4a6147df083e54a2208d1925813fa404e4c47406e7728643ebfb0b10142f909ef856fd3a916bc0851543b82a55f8cd529bd21d9e2909d6d7e77bdcea4673e545ff4a67fa37d65f1f63f11d5d0d55974a30abe188335db5dcbd356658f9b77682d96dabb258ea95951a0559aea4064d5ea1680501dcb4228f2c956f81d2101144af74c716bc8bf4296dc3b831725cc17d3bfd9066a29953b2ecd75059435b49a25ac525b4fbab1779022dfb6de525149dcd902ac8a7e21f344f5f0101480692d61608952c71413e30037945e206c5eeadfc3edc4bae0d796ca0c5f56d6ffb3f0969df9df8a794f5dc83a3b2f5c3ab36bb901bcc31551c550c63fa41d6a8d57bdb9b5c65bc610c3a989752ab28a015e7c2f6b2fbf199a76b9750c0d3d592119c8b4022fa45bade2fbb41432679b52acb4608a95c34aa40bffec10bc98f4729dfccb650b2a052dfb068959e648a92d5aa4dd2d17dde67cdf2e6377af0d4ae379607389d7e3596441b9f4222cff6af73b3300270ce54800bd934a9109a02563adc56ae46584451cdaf4a77538157e5870f4ae12dbc81870f5db41a2cb55e00db3d2231628f1727c3acb99ed3acd8b67156a8005a4cc8f3d3555b79a03773a931f14eebce40b9fe46ede5da0881fb220717e418e8b5a0fe5e477e7285c554e859e16441672b489934a3a9eeb88d78fcc5c1db2d1fbdde392773f6c939972ee8fa3189f4e9872b4abdc83b379c0c10e818dcff75c83d6870729284ced41f2ff55a87c960e63d1211f08071293f6ac63f9bdef38fd5919ca90b3f5e25a6c0c664c4ecf831c64e2d4c6e798a98a3a0f7be7a2463eadaa6a2a348f9a494717123cc0a28c0a5eae3f5b585f2cb8cb260c2c503e41578573cd9b7cba1408dca9d860ae4f8c3d3f322a45b58a2c4: +50864a75aa0c69b59350077c204b20757f2b8b6855c37ed721b49f2ac917d6b2cff3ebd5ea0c8b5531d9211e2219e4cfe5ded991d8ec424df54cf53c8376f9bd:cff3ebd5ea0c8b5531d9211e2219e4cfe5ded991d8ec424df54cf53c8376f9bd:b365f476ac92e76012a7ffd8782af15a3f5ee147f603a367adf2f9724613e8765b037ac0eb1f673736e11363e352ed5ae9eb5a67125ed818900342ae93371c433b91f6021d4be2a052b0da43b3682e7f740ae801d0541057858eb0c9c28d98f03b45e128aaa342c6b602776792aa81241cad06f1338fa0c71757180f588c8301d91c27679b5021cd75d7f6171ee9f8d56e4377679812f6ec5ed46538caed500c1d15f5fc86eaf9ed9cf9a0606b22614faf676462134e3db3582332b483dfa54ca29a5eb0d6bae3380e19d060113453f32bbab7e118627b40bcabf1711bcfeab8957de339436c7088bb883101539a09d3bef088fc1f840764036ffbb33decd12aac57fd26f84823e19553d4d67e000e9436ca323de099bc1ce75ebf5ddccb448cd7a2e4bbd6b32e3f2024f96cc5c7152b8be8ed0bd8e436d324d1ce1dd3cfcc452a28c73a95af8482aa772ae53d5be1292e39d1716b43758fe563c8aa3b74bba5c02d04778d91e3d43dcc72bb7c7b043c05c8745b705ee75b5a4ec7b95b654359fb5e853338219851d40a8afbb4f91ecbb41eb81534196cc0cc9d3eb714396caf045b231722d4486503640419988480a7815808be974287372cfc489965aac5b8095c637581eb910f9055cd1c0a0a3b0b33aca90f7c5b8e6ef683abf0ce53aeba51bec4fc7b427a2347360fca8636d3f1469284f269a9abf0cb1a244a15d6b40465e75cf89092474a8beda033391dd311c499519a08c4f034e71918d7cad41845327c89e7b1e94afb0723782ce5c553ef36791bba63de17d746491894012cebd87b1837a821ef5c624bbc84cc5035f5e70cd9f21b42219a2dce30e0e65c250d0d194d2b52486b03ee66332981a5225174db17e5a8bb4a10ed9c8a445c41442f3bcdb6b4f49e4e1dc87661a7b6e41f35f55dd67bd4cbc6ff58bfbffaffd2c382fcad0cae8f0df9af6acf0940007618a54aee31d932cbd8e8b41ca03821c428a0ef8e58d2435eecd503c54da9c1628f3c749b770519f53bf2d57ed712d075d37337b77a2b10a72d2d590c20d5cec2cacc6c3a8dc113e2d16ef2d1b390ed96e4036acd304e0c7cef9d431f88218aa1f83828dda636b94aa761c7317ecf116cbfc611e5ba6d94c50e994693023bdf2d248ed603f85be73a0008b75adef951dccfa30e42e9f5bb05023ade797506cbf90bb6dce43cf3a1c3141a5cc5fd9a4f3cc557b90e18049b3c130f461e4f32299fa1d1cf9c7f2ea2053565e8160a341cddf99acddd491697fa705124abdab42a5e8fcf048dd9f179384ec92a469aeb11e8bc62b69dbcfcec6681754757e4c5d0fdd9b9cfda49af09b83a5a4a10aed9a4cf7ddfa289209d475ab3318cd4b965e007dce1:177455a71694f12b762fd17e08bdf010a7fc91d19141d7ae2399bd241a998a6a50a9722ac1232c59e4e2aaa828078b2b92f4a54cdf0efebba2c16dbeaf072203b365f476ac92e76012a7ffd8782af15a3f5ee147f603a367adf2f9724613e8765b037ac0eb1f673736e11363e352ed5ae9eb5a67125ed818900342ae93371c433b91f6021d4be2a052b0da43b3682e7f740ae801d0541057858eb0c9c28d98f03b45e128aaa342c6b602776792aa81241cad06f1338fa0c71757180f588c8301d91c27679b5021cd75d7f6171ee9f8d56e4377679812f6ec5ed46538caed500c1d15f5fc86eaf9ed9cf9a0606b22614faf676462134e3db3582332b483dfa54ca29a5eb0d6bae3380e19d060113453f32bbab7e118627b40bcabf1711bcfeab8957de339436c7088bb883101539a09d3bef088fc1f840764036ffbb33decd12aac57fd26f84823e19553d4d67e000e9436ca323de099bc1ce75ebf5ddccb448cd7a2e4bbd6b32e3f2024f96cc5c7152b8be8ed0bd8e436d324d1ce1dd3cfcc452a28c73a95af8482aa772ae53d5be1292e39d1716b43758fe563c8aa3b74bba5c02d04778d91e3d43dcc72bb7c7b043c05c8745b705ee75b5a4ec7b95b654359fb5e853338219851d40a8afbb4f91ecbb41eb81534196cc0cc9d3eb714396caf045b231722d4486503640419988480a7815808be974287372cfc489965aac5b8095c637581eb910f9055cd1c0a0a3b0b33aca90f7c5b8e6ef683abf0ce53aeba51bec4fc7b427a2347360fca8636d3f1469284f269a9abf0cb1a244a15d6b40465e75cf89092474a8beda033391dd311c499519a08c4f034e71918d7cad41845327c89e7b1e94afb0723782ce5c553ef36791bba63de17d746491894012cebd87b1837a821ef5c624bbc84cc5035f5e70cd9f21b42219a2dce30e0e65c250d0d194d2b52486b03ee66332981a5225174db17e5a8bb4a10ed9c8a445c41442f3bcdb6b4f49e4e1dc87661a7b6e41f35f55dd67bd4cbc6ff58bfbffaffd2c382fcad0cae8f0df9af6acf0940007618a54aee31d932cbd8e8b41ca03821c428a0ef8e58d2435eecd503c54da9c1628f3c749b770519f53bf2d57ed712d075d37337b77a2b10a72d2d590c20d5cec2cacc6c3a8dc113e2d16ef2d1b390ed96e4036acd304e0c7cef9d431f88218aa1f83828dda636b94aa761c7317ecf116cbfc611e5ba6d94c50e994693023bdf2d248ed603f85be73a0008b75adef951dccfa30e42e9f5bb05023ade797506cbf90bb6dce43cf3a1c3141a5cc5fd9a4f3cc557b90e18049b3c130f461e4f32299fa1d1cf9c7f2ea2053565e8160a341cddf99acddd491697fa705124abdab42a5e8fcf048dd9f179384ec92a469aeb11e8bc62b69dbcfcec6681754757e4c5d0fdd9b9cfda49af09b83a5a4a10aed9a4cf7ddfa289209d475ab3318cd4b965e007dce1: +e55f220fff8079148b254189bb294174f8e2c575e57f39d4bac8165c5e56e7697fd507d03fe1d6e3f911f059597b0e292ea096f5bc851852916bf1217cafdc6c:7fd507d03fe1d6e3f911f059597b0e292ea096f5bc851852916bf1217cafdc6c:1e2ce8bf0ea7875df285b1dbd34bbe67307f2e8ac8bc142c3ba314c1642c65a2d62eb2c783f916283ca4ec3e536d3eeb65cfdcc0549ac4f6a45f539ac5df79a6d5768219739d0c9a0cdbb31242296c3312b7ed560043f536cd1de9a9c2b289641a1c2d84f9a68b7c03b8b8567e5dc7138c2cb967c628aa25b2eab434d4490b23507409717cde94da59dc1dc25c7be42a8aa02edcf4d995368e6ba0ee1f953600db98d22de0f8d257020e0a406ee1669bd527b9fe1c611f9be5a3d7528e8b6151670a8663d2ed1a58d3e369bb722a6302d7c172a19bdaf357eedb02279156e3b9034431a7d68a39528eb4023587573eb88f30f94e833e8a23b9d0ac7b5ca87824596bbb0a3d0ca1b16a6878fdf7e2cea34a6ffb95a9ff4e888a97593735b868da75d8707bbfdb1d93eb86a51e2d215f1dd9dcf78388729a3eb0f066ddc941e950c92127198bce63a54868d997029572ffa6f6fea1d3a69164c9996953dc8b6f9dad0635c9b081f55f983340f0814bf5470803090e7997f7ab796c2b15adaf4021d67cffaf6e1ef62867503945c21a329664e08a95a41582300da9bed208444ce6aa12b3f867795c6ee4c4c9257018627361293bd527821a29a339b404a2da4bd9944f877040798bb54abd2d76cbb18df4297f4ce3337f64d20580aa64bdecac376a6a4ff74d0144b2fe74cef82d50a5e6bdd799e55ff69662bac537adcb6881228cb63704500c143a4f4d1db28d4556bee604a399ffd206546597dee92252547f6c657f36841a87d565f6552716c25a21151477bee9ef961855fb1af2da8068f28ce9ff70d5252c7a63a2e14ded6b8977b1d7691a77ed2e57d22ff2e1fc4cdbceb5e805858d903896ea6707e48b345f60e2818b2fcec4dba48caea9efa38279fb83d5b0f46a45e42c41765d0171baacd8d6dda7991314b34e15fd36127c467d1de01c01a3a78a8c1b103bee17a7a0b7ac5576fdc226dd2459773146cf38261417ca19135dbda9bdbe54cd17aa7ddd38fdcac2aba396b365ceae98919f6c5177fc583f5bee3f48704914306aa19ee90e3fd0de5591c669ff35ab16fef38dee187bae1e5aaa566df10544b7d6d4eb00da7ebeb4ecdcc4d8e32b49cbbdc6e66640bdb0f72e05918a05c35d9bff7e0e88f241d7c6c8cb2fedccdf65560af0e7833efe34af790db63189022cfd71fc8acf88860127bd4fbf026bcbe360e33a8995e636d03bb86dfd0198ada959342d8e9c9ed93e23297da98d66a0d4fc965162733bc86541b95a6c9097cb55a973c6fac194e8f8a164274c479c510e62d8a035eb751181b502afb614d8c4467b5445c268dc3dd0abbd577004c0bc47b15fcb801b79359757b5ea89cf8cf77fc6d160e6cd73c4:c1023a7068743ec4668f495eb7bd4db58129c11e58299ea87d6facd302bf296a98e298fdb48eddf9c44e79ae8641f734503bb83dc0b31f610df1d1e9d619a7051e2ce8bf0ea7875df285b1dbd34bbe67307f2e8ac8bc142c3ba314c1642c65a2d62eb2c783f916283ca4ec3e536d3eeb65cfdcc0549ac4f6a45f539ac5df79a6d5768219739d0c9a0cdbb31242296c3312b7ed560043f536cd1de9a9c2b289641a1c2d84f9a68b7c03b8b8567e5dc7138c2cb967c628aa25b2eab434d4490b23507409717cde94da59dc1dc25c7be42a8aa02edcf4d995368e6ba0ee1f953600db98d22de0f8d257020e0a406ee1669bd527b9fe1c611f9be5a3d7528e8b6151670a8663d2ed1a58d3e369bb722a6302d7c172a19bdaf357eedb02279156e3b9034431a7d68a39528eb4023587573eb88f30f94e833e8a23b9d0ac7b5ca87824596bbb0a3d0ca1b16a6878fdf7e2cea34a6ffb95a9ff4e888a97593735b868da75d8707bbfdb1d93eb86a51e2d215f1dd9dcf78388729a3eb0f066ddc941e950c92127198bce63a54868d997029572ffa6f6fea1d3a69164c9996953dc8b6f9dad0635c9b081f55f983340f0814bf5470803090e7997f7ab796c2b15adaf4021d67cffaf6e1ef62867503945c21a329664e08a95a41582300da9bed208444ce6aa12b3f867795c6ee4c4c9257018627361293bd527821a29a339b404a2da4bd9944f877040798bb54abd2d76cbb18df4297f4ce3337f64d20580aa64bdecac376a6a4ff74d0144b2fe74cef82d50a5e6bdd799e55ff69662bac537adcb6881228cb63704500c143a4f4d1db28d4556bee604a399ffd206546597dee92252547f6c657f36841a87d565f6552716c25a21151477bee9ef961855fb1af2da8068f28ce9ff70d5252c7a63a2e14ded6b8977b1d7691a77ed2e57d22ff2e1fc4cdbceb5e805858d903896ea6707e48b345f60e2818b2fcec4dba48caea9efa38279fb83d5b0f46a45e42c41765d0171baacd8d6dda7991314b34e15fd36127c467d1de01c01a3a78a8c1b103bee17a7a0b7ac5576fdc226dd2459773146cf38261417ca19135dbda9bdbe54cd17aa7ddd38fdcac2aba396b365ceae98919f6c5177fc583f5bee3f48704914306aa19ee90e3fd0de5591c669ff35ab16fef38dee187bae1e5aaa566df10544b7d6d4eb00da7ebeb4ecdcc4d8e32b49cbbdc6e66640bdb0f72e05918a05c35d9bff7e0e88f241d7c6c8cb2fedccdf65560af0e7833efe34af790db63189022cfd71fc8acf88860127bd4fbf026bcbe360e33a8995e636d03bb86dfd0198ada959342d8e9c9ed93e23297da98d66a0d4fc965162733bc86541b95a6c9097cb55a973c6fac194e8f8a164274c479c510e62d8a035eb751181b502afb614d8c4467b5445c268dc3dd0abbd577004c0bc47b15fcb801b79359757b5ea89cf8cf77fc6d160e6cd73c4: +d5e3a40671bd45f08842ddc78abe57de3b9ce5646b730d2e59fecf5a7df80f40416c37ae1ad15b632b0ea43932c17637282cd91d5979552e5eebb99a419d5c97:416c37ae1ad15b632b0ea43932c17637282cd91d5979552e5eebb99a419d5c97:09fe6ffa8bf0942a64921357659dbc6e4f8b63ca3b9ea475ea39d7925290a148d87bb155741dfa28ae1beadc1f3e1ab76737eb5d5ddaded0bb382d7e11ea81a5e7801612696260ba3bd09c80b623f636380aa0208fee0aff70812d5307b27183832343debaa3605ddad17ddd70d611400ddd10d638aa3d6c68a28cf0e97c1dedf6ccd9c731a84ff0405a3a22dcba00ab44d5b21844f14d1374ac0cb1e58df4a90c412563cfe69d882d350f6aafbfa64fa2f9ff826032326780aecf9305d8217c179dbb63c151541232eb65979265d876c4bc4305c02f40bc1d05dbaf7dcf4f7dd9232c17ee0f7a0555f504ba3774548488933e7571eb3f71c4cbb20cc4e4a7322f35ac0e79a59155798dd0f5b3c11319b7d8f3ea79ee3acc68bdb9f37c7d4c8f9caba1ebf8eb7f43b462aefd38e8c0d4c63979cf6631dec31ab5ced3937ef5b2362cb09c71dd096657700fd96bda555e22712f71aec11ae5e91b24bd1649498b8d9f867fb6c41e076080f740d074c2a25572d34e666b6367bf7cbb3dd42a2382dc1973961268605396810a456ac081bbfd3a54b44881fcfc45b4245ee72465b487d07f2ef3f74add71cdfdd16e92fe257d334645b0a9bc7d072613fb9c0cdea9db4c72bc87109e102d7cbaf366ecd67fbe3ded32747307a7aeef61735ad3aa5ce95deecc16a16eb2a0bcc7adc0a11d888032260e7c7ec9e54f5a2531702a7e5dfb87c36ce313a3147588aef962c72fa966d241637c388b83ddec9343bb86343e920b12ce1cc915c83b31e99862690674ea4935a48809d4d279054137546392ad9f08e7b8de61ae73e81e483d3c63b5ae734e18e7a22feed1233d0ca63355f3a48a33067e1a0e1971f36aa929fe0613c21c4aeff9418429c3b072a5984959287a5e5c40be02bd22b9a79c7f3f5359d2bbe493f556dacbb0cb4c293c7d941265e777392d148d68c07a13c8dec8e5d1e1c7f041e8983edddaa4649dac1572a39ae4c6480ca550e2e4462dcc849c1bab781d28a3552b2d98e02e1518e6555340fb76d68db58916d556a7b81563aba81d9a57ae50f04cf5686021847d79b6bb3da8017a60b1c3beefd48d2b3cd39c6f53c08bcc967d93069f562bb36e0c4f4ca6bccc5e57d35903cd800a61785a93770e377f4fe8e9f4b66680984968f9649e105e7a119d97636f3a05caeab1d7ea0bc81334b42d5cc080830ec24d369cf8673a490d59eb4cb08181da39a46d966e23fed8d38a5fabc7e843bcfb015a4474bfd46d4a43ff4a51a9567661e2696db87c3758d3b54ce7846d1391d7f46526ef30844d49320018d749b5d4dfd30d380c6e573fc414d8fefc5d710470756bec00d88ac4afc925d1ede37eaee6004a23ea0ef8b60e48:63de6a981142365a3e592631c8277237809739d1c98f5a1cb2cccd34067d1ca5dc8f2fc63b8ae1a689dcaa291ba6b69b1a6795c579a5db6dccee73f6a420ac0a09fe6ffa8bf0942a64921357659dbc6e4f8b63ca3b9ea475ea39d7925290a148d87bb155741dfa28ae1beadc1f3e1ab76737eb5d5ddaded0bb382d7e11ea81a5e7801612696260ba3bd09c80b623f636380aa0208fee0aff70812d5307b27183832343debaa3605ddad17ddd70d611400ddd10d638aa3d6c68a28cf0e97c1dedf6ccd9c731a84ff0405a3a22dcba00ab44d5b21844f14d1374ac0cb1e58df4a90c412563cfe69d882d350f6aafbfa64fa2f9ff826032326780aecf9305d8217c179dbb63c151541232eb65979265d876c4bc4305c02f40bc1d05dbaf7dcf4f7dd9232c17ee0f7a0555f504ba3774548488933e7571eb3f71c4cbb20cc4e4a7322f35ac0e79a59155798dd0f5b3c11319b7d8f3ea79ee3acc68bdb9f37c7d4c8f9caba1ebf8eb7f43b462aefd38e8c0d4c63979cf6631dec31ab5ced3937ef5b2362cb09c71dd096657700fd96bda555e22712f71aec11ae5e91b24bd1649498b8d9f867fb6c41e076080f740d074c2a25572d34e666b6367bf7cbb3dd42a2382dc1973961268605396810a456ac081bbfd3a54b44881fcfc45b4245ee72465b487d07f2ef3f74add71cdfdd16e92fe257d334645b0a9bc7d072613fb9c0cdea9db4c72bc87109e102d7cbaf366ecd67fbe3ded32747307a7aeef61735ad3aa5ce95deecc16a16eb2a0bcc7adc0a11d888032260e7c7ec9e54f5a2531702a7e5dfb87c36ce313a3147588aef962c72fa966d241637c388b83ddec9343bb86343e920b12ce1cc915c83b31e99862690674ea4935a48809d4d279054137546392ad9f08e7b8de61ae73e81e483d3c63b5ae734e18e7a22feed1233d0ca63355f3a48a33067e1a0e1971f36aa929fe0613c21c4aeff9418429c3b072a5984959287a5e5c40be02bd22b9a79c7f3f5359d2bbe493f556dacbb0cb4c293c7d941265e777392d148d68c07a13c8dec8e5d1e1c7f041e8983edddaa4649dac1572a39ae4c6480ca550e2e4462dcc849c1bab781d28a3552b2d98e02e1518e6555340fb76d68db58916d556a7b81563aba81d9a57ae50f04cf5686021847d79b6bb3da8017a60b1c3beefd48d2b3cd39c6f53c08bcc967d93069f562bb36e0c4f4ca6bccc5e57d35903cd800a61785a93770e377f4fe8e9f4b66680984968f9649e105e7a119d97636f3a05caeab1d7ea0bc81334b42d5cc080830ec24d369cf8673a490d59eb4cb08181da39a46d966e23fed8d38a5fabc7e843bcfb015a4474bfd46d4a43ff4a51a9567661e2696db87c3758d3b54ce7846d1391d7f46526ef30844d49320018d749b5d4dfd30d380c6e573fc414d8fefc5d710470756bec00d88ac4afc925d1ede37eaee6004a23ea0ef8b60e48: +4ed7048aa1284dbbcc248938b40c35742193597addafdde06413b8d4ccfbe137bf841fe444add1f7c3eacdfd0784b4e855d2405f4021cd9d8266071c32c8a273:bf841fe444add1f7c3eacdfd0784b4e855d2405f4021cd9d8266071c32c8a273:dcff9587d6046c1132be07df26df6382ff92cfc8eb5345c51dd50dd188ee769f10a4de5e8883d116967bea97d3b32bc8aebb9f013d6df952f251c1a312346e72cee135a1bfd76bf3080a35c838b44d755f263d210310fa8d28c4ca52f08cac5b83a8a3b1dfc46d9b752d9fc73649d00bb9ee992650639c225deac1f39b9e803689d19e6d9f8ef4f51f1d11601facf410db648bcc82bf648769a7dd59c6e8a237db239d3f661d7852c426d394a90509526a859b476459dedbe6d89936c0f3989995511d4a576e542cce5e0dd7eeefeb0326d33f25c22ab6e7690633f4c9ed2aadf1d24f94862123a464042cea193a2f0479d39bcd1bbd1c7a0ca7e6258ed3732372f54e0ed5e3f1e2e4d4a04c510bee08d1c6d570cfd63abf14b4eef0b96f39ca29e43c52f2ca3dfd460f66e30235b159aaef2cc156012969fd3d159978d6caa0a94522291f7989d8af10831996137b68d97fc17f6a9bc2845ef3dd47cbc386e8977a8654363412dac3ac51c63817b7c051878dcf458ab3630dd7aef68d270f8da7880a467b3304f5baedfba9173e7efd007c412d17209c56d23968e340b8a0edb41b7e2a4088bec01b532df89b5215813131107b7b474f03c2e47d4317f11c4f5160904304997e76a121a9560235208d79b2dab4f7e196793202c0902ce9c4bfc10b8fe397e35ca0256454662ae878efb0a0a606fac0a952c9f6baaeb2d45b258c617559c0ed2528a88b49aa44ee43035b0d793aad3953c1a5a3463866bc815b1ffce2ff2b65e0fd47dbc15f4e7a06bfabc290fc62090bf7d94853f77c0444a9b90efe77d1ceb4bd39e203bc884011624e6846e2a371058daba63c23f86c42c3e31eaa4bd7d7a42af2d524896e31baa3e20763f85dcfd52775f28072d89f0bd4fae30d0b137ee37ab063ba06fe9d4ec62abb2fea0f81b8cbeefc030080b8026a58fd1867f66be1154e65bfea7dcec55fe32d51fb0b4a8a5a8a044263943d6ac8011c6e6701beec3a88655840c4892d450d312b7652d2514769f23bfd6e7046467df29a287ff3c4c9d0e64e6d9e4edee1b935d07681d47004352886e847b0c6d5762fd45a81a53cce9476c887221aea6c0c82bbf3b297932e5b11e538a3245d63d7b7b091dfa1d7b9a0e2db6698a4c5e9fe931662d7c6ec6d9d5b92bc7e041555df4df0ca11cabc485f9c556138a71745f03b9783bb200b72d233697e8bcf6b4117ee6763d792d7422264852f4f30f8d1890e2ea08098040f7f288e4abe90b63cab2c14373060840ef827ecc846cd560e90a20b8305f463c36ea03884a5df4c25f1ba9ea125952dc091b97516de1d287c0e2bf529775ba6d2f8ede03cb42c1e400ec804a9df08e46f44b5066346e3f7c7a1a8:106a9deb2327f338ccb71bcc94e2fe3d2e973ce6dd8fa7baca808b4111813e3bc3b4d88efa6a00c4710bbfe53196f9ab3a150b1654b908feacf9c13df2d63802dcff9587d6046c1132be07df26df6382ff92cfc8eb5345c51dd50dd188ee769f10a4de5e8883d116967bea97d3b32bc8aebb9f013d6df952f251c1a312346e72cee135a1bfd76bf3080a35c838b44d755f263d210310fa8d28c4ca52f08cac5b83a8a3b1dfc46d9b752d9fc73649d00bb9ee992650639c225deac1f39b9e803689d19e6d9f8ef4f51f1d11601facf410db648bcc82bf648769a7dd59c6e8a237db239d3f661d7852c426d394a90509526a859b476459dedbe6d89936c0f3989995511d4a576e542cce5e0dd7eeefeb0326d33f25c22ab6e7690633f4c9ed2aadf1d24f94862123a464042cea193a2f0479d39bcd1bbd1c7a0ca7e6258ed3732372f54e0ed5e3f1e2e4d4a04c510bee08d1c6d570cfd63abf14b4eef0b96f39ca29e43c52f2ca3dfd460f66e30235b159aaef2cc156012969fd3d159978d6caa0a94522291f7989d8af10831996137b68d97fc17f6a9bc2845ef3dd47cbc386e8977a8654363412dac3ac51c63817b7c051878dcf458ab3630dd7aef68d270f8da7880a467b3304f5baedfba9173e7efd007c412d17209c56d23968e340b8a0edb41b7e2a4088bec01b532df89b5215813131107b7b474f03c2e47d4317f11c4f5160904304997e76a121a9560235208d79b2dab4f7e196793202c0902ce9c4bfc10b8fe397e35ca0256454662ae878efb0a0a606fac0a952c9f6baaeb2d45b258c617559c0ed2528a88b49aa44ee43035b0d793aad3953c1a5a3463866bc815b1ffce2ff2b65e0fd47dbc15f4e7a06bfabc290fc62090bf7d94853f77c0444a9b90efe77d1ceb4bd39e203bc884011624e6846e2a371058daba63c23f86c42c3e31eaa4bd7d7a42af2d524896e31baa3e20763f85dcfd52775f28072d89f0bd4fae30d0b137ee37ab063ba06fe9d4ec62abb2fea0f81b8cbeefc030080b8026a58fd1867f66be1154e65bfea7dcec55fe32d51fb0b4a8a5a8a044263943d6ac8011c6e6701beec3a88655840c4892d450d312b7652d2514769f23bfd6e7046467df29a287ff3c4c9d0e64e6d9e4edee1b935d07681d47004352886e847b0c6d5762fd45a81a53cce9476c887221aea6c0c82bbf3b297932e5b11e538a3245d63d7b7b091dfa1d7b9a0e2db6698a4c5e9fe931662d7c6ec6d9d5b92bc7e041555df4df0ca11cabc485f9c556138a71745f03b9783bb200b72d233697e8bcf6b4117ee6763d792d7422264852f4f30f8d1890e2ea08098040f7f288e4abe90b63cab2c14373060840ef827ecc846cd560e90a20b8305f463c36ea03884a5df4c25f1ba9ea125952dc091b97516de1d287c0e2bf529775ba6d2f8ede03cb42c1e400ec804a9df08e46f44b5066346e3f7c7a1a8: +c7eca83e948576bd9f278fd7b82800a41d92da9b72d5a1ccdbbc65581052568b076b8352dca8031e853c8d9099c2ef579337cc7b2b4c75d1a063ea3ec725b7fd:076b8352dca8031e853c8d9099c2ef579337cc7b2b4c75d1a063ea3ec725b7fd:8d8cefd673855ccd8eb8534c312d338005bb05f5b9507d58859e1e953b0a4d913be759d8edfa92898c6e70a53f81954fc344b4ad6246b0109481ba6f73ae6331abf2df108eb2e85ceb087c1f6fcfc9de2c1f139ba1771b72680302d811ccd0ccd4e0c7feb0132eb20b334e5aabe5f6119fd8947d9e8852e1eb1b74107e174100e3e6df0c3a68130ca6309402594bb50c1c8e2774f13214496a7b1f348385eabfbccbac165a5a2e7d9dea5ffd58b0bd88b49cb331ecb7f4e9d6bae9791ad788e6ab8926c1cc1615deaf4cc400c77a316197bca1904995e1365d1b9702648376116930f6f91166e6148629e75be2d06895f6a8d15d5a94ca69b712f33bcf95be0c1be6902bb78b8a230d7a8560c4d84e2389552a81571aa665c19c2e93b0d43e8c2cbd9e885d7052518b77c47e841d119dc28b65a7504f664271f06c7ff393f825b1e5930d02b9c70035e292411c4aedf66047006970e349dfca7fb41c10fd537e35252e109e3336d7a82a14de5d5540c6fc6571d5774f39b7c403e7b8875ec215877efc6cc8ea48b186b46821ea5ef2ba8bacd40d797e6add06413283145b60462b3503c5b881d79a592955d18afa08969e31457f5b27daec010338ed867f300878fd87ce321880b860a0c64284ca2dc15f5e5310e10e6a73a7ea650ea9d373694da4dd429ae7412ef9b29c83b3b068c74769f431ce0615f9ff4f82baac47b4bce90449ec41c2a2d573d92b92e05631486165bc710ef5840f80dae9f9dd5cffd4ebf5d10746510c5fcbfe62cb9703c0b154c86f10816672497670a3b0150bb4e1b03b3bd544c12a90c3edccd7900ebb5b31c91117cc8281a3c4ed04998e99aed41bb41fce9990a406485b14dbe3bc1a5fcf7719507990da3b0b3c68ad40d8950c0d49ced1019319a3f36aff6caf75d7f9a0933dd3abdd7692a1562f0613fe4a278d5ce4c8dafbb55b2ec2af2b24e8396f587b170c9ca6547508facde73490dfb01eb6657e3f4f272304b70bf047a43a2b58e5568bc52b2c8d4c03219a5a8bd3dc0643185913c0af7411f81b77be2a9bfd5cb26977113d2658a97192b41cf6c7011b0ff6a11cbff3505546322f0bef6097e46b36492b016a4562e092b67c3fccc7780ea274d96d595849f7e2a56d79edcb32d784049fc1324a5beefc24193a66e1cac4a13a811b909583cc910cf08d4b104dbdb8a6f2b21fbc1db1175a1a2356a63d3eea9dbb8537d2c68627543df0d1f8fd8d57a18b0dbd69b920cb9b286e3c07ae44ae2e1beec01cee6ba988b5d1afb99790b1dd910655c43d7f2a3ed3754ba46516d278705559f5741622a9abb5c8f23fa976a9d146948ade6ba6608a35e4e0d330e82e96a2be6c78ad0cd4d8704e57cea146:86996a1b8e495d425277e97cc0830549349bc2b6f3dcda60f3b7d3501b8b50b5b458cda58b436e23c02cd4a22b234813aa9bcc3c61f983c0b7efeca0f1bec20d8d8cefd673855ccd8eb8534c312d338005bb05f5b9507d58859e1e953b0a4d913be759d8edfa92898c6e70a53f81954fc344b4ad6246b0109481ba6f73ae6331abf2df108eb2e85ceb087c1f6fcfc9de2c1f139ba1771b72680302d811ccd0ccd4e0c7feb0132eb20b334e5aabe5f6119fd8947d9e8852e1eb1b74107e174100e3e6df0c3a68130ca6309402594bb50c1c8e2774f13214496a7b1f348385eabfbccbac165a5a2e7d9dea5ffd58b0bd88b49cb331ecb7f4e9d6bae9791ad788e6ab8926c1cc1615deaf4cc400c77a316197bca1904995e1365d1b9702648376116930f6f91166e6148629e75be2d06895f6a8d15d5a94ca69b712f33bcf95be0c1be6902bb78b8a230d7a8560c4d84e2389552a81571aa665c19c2e93b0d43e8c2cbd9e885d7052518b77c47e841d119dc28b65a7504f664271f06c7ff393f825b1e5930d02b9c70035e292411c4aedf66047006970e349dfca7fb41c10fd537e35252e109e3336d7a82a14de5d5540c6fc6571d5774f39b7c403e7b8875ec215877efc6cc8ea48b186b46821ea5ef2ba8bacd40d797e6add06413283145b60462b3503c5b881d79a592955d18afa08969e31457f5b27daec010338ed867f300878fd87ce321880b860a0c64284ca2dc15f5e5310e10e6a73a7ea650ea9d373694da4dd429ae7412ef9b29c83b3b068c74769f431ce0615f9ff4f82baac47b4bce90449ec41c2a2d573d92b92e05631486165bc710ef5840f80dae9f9dd5cffd4ebf5d10746510c5fcbfe62cb9703c0b154c86f10816672497670a3b0150bb4e1b03b3bd544c12a90c3edccd7900ebb5b31c91117cc8281a3c4ed04998e99aed41bb41fce9990a406485b14dbe3bc1a5fcf7719507990da3b0b3c68ad40d8950c0d49ced1019319a3f36aff6caf75d7f9a0933dd3abdd7692a1562f0613fe4a278d5ce4c8dafbb55b2ec2af2b24e8396f587b170c9ca6547508facde73490dfb01eb6657e3f4f272304b70bf047a43a2b58e5568bc52b2c8d4c03219a5a8bd3dc0643185913c0af7411f81b77be2a9bfd5cb26977113d2658a97192b41cf6c7011b0ff6a11cbff3505546322f0bef6097e46b36492b016a4562e092b67c3fccc7780ea274d96d595849f7e2a56d79edcb32d784049fc1324a5beefc24193a66e1cac4a13a811b909583cc910cf08d4b104dbdb8a6f2b21fbc1db1175a1a2356a63d3eea9dbb8537d2c68627543df0d1f8fd8d57a18b0dbd69b920cb9b286e3c07ae44ae2e1beec01cee6ba988b5d1afb99790b1dd910655c43d7f2a3ed3754ba46516d278705559f5741622a9abb5c8f23fa976a9d146948ade6ba6608a35e4e0d330e82e96a2be6c78ad0cd4d8704e57cea146: +7b469df9c8f78489ab47cc70a88503f1b8f3d929c33feab1c503f0969a3ac37ba814c7e373d0113b90624a8ab2bca5cf53bf528e39fc3d367de154b94bb22f1d:a814c7e373d0113b90624a8ab2bca5cf53bf528e39fc3d367de154b94bb22f1d:1c0fd7450e29675c93091638c2ac933ca997766e380ec33a92b8a7e1a1ed9821c75fccb5c5f3760e76d0e8810311ddc624ea8742131c1c4308f4178e04d04960693d846c1f51d8773b6deb3443d874b9e2de3b77785185518b2e9ee736c63a39c8212ca8669e161d131b1ab2264fdd72dc5628b11c06f2af9f0789047bdd4ebb5d55899f74dc4e12e7975363f63a8da76b5585c16bb6d55b05fade8713d19cad1a211640262691aac9b437a9ecf89a9246ecdba1ff0bea78494cee15296216ea6bb882479d2437c9494ac7fa4f3015d1d3149d5564d7c11a7e7b614f7d3e9d454f0a05b040a1e06fe7837c2a9da2794d918bffa9e61a0c3f089f6c9f7eeac586e34bf94470d913da41371cacdfc7ee8bd1135655566924eadf096ac030a65902c103b172d12e88f053fc56ee73f31870817083afa802f7668b815ee790f7d40b437a2e6db2f0fb26836b4b2331eba55539614c0fe17240242dd3af7383bcff7d3f47d6544b08720c0a52441f7411935dd4a952d38651a80005fa3eb0eaecc735d290e8bd5e31b740140e136b2c002523d8eb2a0ab5bd687002b3b926f75eb690d1da73ad235892f3b23a756b605a437c00e0621304e810f99e314c4d63e322d9b69815f382ffa1ec6280fc0e641c8a6f6f7f61985bd3567e0f440de9f7621715dacd07428c0090154d59ce6db40169c658ac5bf44b67671fe19e4b5b38aad2d3d4e190a550aad4188352f7981a6d88062502df86791350392d41cefacb24e37bc700cb029190c3b1821477e117d5a462fb3e79133b1073598966f52b63256dbf326ace14db0c80058cf00d689a0a58111af1692744bf791bcbb427a372246e9501a85cd520c61a1e59ee180e8c97192f60fa5d3ab05df8d8551c1ac6ca0a9a012ffeceb3c1f521411edb6509bc278a651e129e96b0adc7aed707221caeac229884413daa10595d22d1db7082125f4f969500a1d48dacdae80f4029c163dcd79ddc6468fcda1637b87ddcf2a3d9b4d299a0e5394df90ed03b62137ba67b9fea8ae1f0d22f91c63a24b5934f74c265c43f1b923db980adfcee8313da520176730ef9736b27e6ba32d17ea69dcac6f4a016edfe2db5a5bb3b64932f7011f1c453bbe88bbac8c7035f93fe39b581fcaa7aaf082fbed004fd1fd5a4e2d9c19716604b19ce199e2169a7be518d5fadd2ac31b95478082ac91306008de4ec0ef4c9f9d6f96d2f66d62fafc2194082808af0d67b9fba0d189b055f061ccac24b27610bfbd5a2232dd6f3c890a9b1266471b322e9e1bf97757bef72abcee93b051fc923cfd4e723be3e17143f38eebb900b5bbcf7304732b9c0a1c5fc9509a693580ae73a4cdfc5fbf20ce81ebc835c6c909d831141b194f6:18faf82d08e1068e9f983d812f05fdb6929d2723db1f77c45a74bb09cff27773b54ce8f43b3015419112e725ea7acda4b23b8120e7b0cf420153e5b03dd061091c0fd7450e29675c93091638c2ac933ca997766e380ec33a92b8a7e1a1ed9821c75fccb5c5f3760e76d0e8810311ddc624ea8742131c1c4308f4178e04d04960693d846c1f51d8773b6deb3443d874b9e2de3b77785185518b2e9ee736c63a39c8212ca8669e161d131b1ab2264fdd72dc5628b11c06f2af9f0789047bdd4ebb5d55899f74dc4e12e7975363f63a8da76b5585c16bb6d55b05fade8713d19cad1a211640262691aac9b437a9ecf89a9246ecdba1ff0bea78494cee15296216ea6bb882479d2437c9494ac7fa4f3015d1d3149d5564d7c11a7e7b614f7d3e9d454f0a05b040a1e06fe7837c2a9da2794d918bffa9e61a0c3f089f6c9f7eeac586e34bf94470d913da41371cacdfc7ee8bd1135655566924eadf096ac030a65902c103b172d12e88f053fc56ee73f31870817083afa802f7668b815ee790f7d40b437a2e6db2f0fb26836b4b2331eba55539614c0fe17240242dd3af7383bcff7d3f47d6544b08720c0a52441f7411935dd4a952d38651a80005fa3eb0eaecc735d290e8bd5e31b740140e136b2c002523d8eb2a0ab5bd687002b3b926f75eb690d1da73ad235892f3b23a756b605a437c00e0621304e810f99e314c4d63e322d9b69815f382ffa1ec6280fc0e641c8a6f6f7f61985bd3567e0f440de9f7621715dacd07428c0090154d59ce6db40169c658ac5bf44b67671fe19e4b5b38aad2d3d4e190a550aad4188352f7981a6d88062502df86791350392d41cefacb24e37bc700cb029190c3b1821477e117d5a462fb3e79133b1073598966f52b63256dbf326ace14db0c80058cf00d689a0a58111af1692744bf791bcbb427a372246e9501a85cd520c61a1e59ee180e8c97192f60fa5d3ab05df8d8551c1ac6ca0a9a012ffeceb3c1f521411edb6509bc278a651e129e96b0adc7aed707221caeac229884413daa10595d22d1db7082125f4f969500a1d48dacdae80f4029c163dcd79ddc6468fcda1637b87ddcf2a3d9b4d299a0e5394df90ed03b62137ba67b9fea8ae1f0d22f91c63a24b5934f74c265c43f1b923db980adfcee8313da520176730ef9736b27e6ba32d17ea69dcac6f4a016edfe2db5a5bb3b64932f7011f1c453bbe88bbac8c7035f93fe39b581fcaa7aaf082fbed004fd1fd5a4e2d9c19716604b19ce199e2169a7be518d5fadd2ac31b95478082ac91306008de4ec0ef4c9f9d6f96d2f66d62fafc2194082808af0d67b9fba0d189b055f061ccac24b27610bfbd5a2232dd6f3c890a9b1266471b322e9e1bf97757bef72abcee93b051fc923cfd4e723be3e17143f38eebb900b5bbcf7304732b9c0a1c5fc9509a693580ae73a4cdfc5fbf20ce81ebc835c6c909d831141b194f6: +dfecde7a56a18c1f19d80a19a4f1daddd0bcecb01eecad6dfca0f957a914ed7aafbaa6e73e85b02b25a4b587ecb8c4dfb79aa9202761efa8d1df2cd0aa6316c4:afbaa6e73e85b02b25a4b587ecb8c4dfb79aa9202761efa8d1df2cd0aa6316c4:ae6e8ff65ccde6f26484950826b43623058a5efe020bb19b7d8b4e25768b692734fe07c913b9e88126becbf14a0fd0205b39fcc2aec373f8c184c6a9bbbb84449a7ca3b920ada08801dfc66ff19aeb92f2555399a430277ae22d23754eaace3c73846797536dd71a56f4b5842c0f410d1989acac5d805d26572c0f3a64dd2071662212d52fe99e59d966047777f9030fa4fd2ee74b7a7c9f7c34a6dc7e03593a13d64ce62453ee3ca30d84672839f19f1c15d0c45d2755bb394acf4dcb7f7f0711ac40ea46612ea37a7607ad32e818265fab1933f5094e2d03bcfaa5f61667f3b37f00c4c58d9b41b9af3900482b0ffb4fa4376aa040009dec2f4525799cb005f39d74cb2d8dce8c20c2c3f5409703af156cfba28a9d916439cb29f83d2429ce6223519e75e15c7c7fa215119e073fa7974db14f7a01093faa94ad52ab1eadce1a89366ca13adb89066438a2beb73034170aa42d9c2ddb97c14a17c3094376d2a3ffd8095fc4053d91d16e06d27693a1310f01a75111cfeda892c3972a133a09addaa8f74145f88681b6d277964bfe38551a2c619fa3cae394acb29c9410b45e101b1740e8b2aa6febc3a45dadb9d9589d597e57cd947b684cc355246ce6c326dd98cf92b6eea3ba5ab03700622636324dc1222cd748fa07bfd39a1e069809e567141a613e2e8be9dd398ab6beaafd85ff3628ee2aa32d0a57bbacf956190b5c4242eb5b8587d2fdcb0741b9416a05f5fecb1fb2d64788dce783c1f63e60641fce5e1d2b18a9500cd6a1fd335cc1db46ef04752b2d22072e6dfcfcfa569bb25e457afeb63a4fbedc293ad9d1aba4e394aa1097e12b0fc90c89f76df0d6441fa99808b60be07dfcc7f9010bbf9033556d5ee2d448937b783493920f681e4da708671097e199481b8ef0e0150d7c2851df44c545122f9b0e5ba2eeff2d988d56d9bbb55d9896111151a436af065e0cad178a2c9fa8f6974ecdf09adf013300cffedaf4b8791b467ba7933ada5d632db44ed6dcf2aa648917be6337d2e2d206856d08f9ee7b5e2f14ddc6d3ac429215a87923ad32d5dcfee3686316ddd1b27bb193a5fc05c893a939a5b98987366c829e392f485ea15e22cd8f857a134afa98f37215576ddc5aab4f2d10caaf050059a335f24bcdcbac819f66db07aabdfb76271d17bce22cba463a80aa892d0d8e055f948df7f6e6c300daeffd3a236dddcf238fe10666a57c6e3ae7e3673d35578f8b8ea69d3c08e0140afd3ee030b22a372160f908a378f8101b5f5969fea310eed37a00d97302d5c2dbe8cc600075dccd33ad63d265aaf60e241ce311bed7dd5e2745241ae02ae532d15c18886e818138751afc51850e506c6d31a8eef451adfd4b3d266b415a7e:b4fde55b916cf60068f19b25351c1410dcf66bfc40f96d1ba2368bc2b9115aaa5b2d1cf0e3dfca02ac902a943e2489a5681bbafed39c6e33211a9cb2ff6e5409ae6e8ff65ccde6f26484950826b43623058a5efe020bb19b7d8b4e25768b692734fe07c913b9e88126becbf14a0fd0205b39fcc2aec373f8c184c6a9bbbb84449a7ca3b920ada08801dfc66ff19aeb92f2555399a430277ae22d23754eaace3c73846797536dd71a56f4b5842c0f410d1989acac5d805d26572c0f3a64dd2071662212d52fe99e59d966047777f9030fa4fd2ee74b7a7c9f7c34a6dc7e03593a13d64ce62453ee3ca30d84672839f19f1c15d0c45d2755bb394acf4dcb7f7f0711ac40ea46612ea37a7607ad32e818265fab1933f5094e2d03bcfaa5f61667f3b37f00c4c58d9b41b9af3900482b0ffb4fa4376aa040009dec2f4525799cb005f39d74cb2d8dce8c20c2c3f5409703af156cfba28a9d916439cb29f83d2429ce6223519e75e15c7c7fa215119e073fa7974db14f7a01093faa94ad52ab1eadce1a89366ca13adb89066438a2beb73034170aa42d9c2ddb97c14a17c3094376d2a3ffd8095fc4053d91d16e06d27693a1310f01a75111cfeda892c3972a133a09addaa8f74145f88681b6d277964bfe38551a2c619fa3cae394acb29c9410b45e101b1740e8b2aa6febc3a45dadb9d9589d597e57cd947b684cc355246ce6c326dd98cf92b6eea3ba5ab03700622636324dc1222cd748fa07bfd39a1e069809e567141a613e2e8be9dd398ab6beaafd85ff3628ee2aa32d0a57bbacf956190b5c4242eb5b8587d2fdcb0741b9416a05f5fecb1fb2d64788dce783c1f63e60641fce5e1d2b18a9500cd6a1fd335cc1db46ef04752b2d22072e6dfcfcfa569bb25e457afeb63a4fbedc293ad9d1aba4e394aa1097e12b0fc90c89f76df0d6441fa99808b60be07dfcc7f9010bbf9033556d5ee2d448937b783493920f681e4da708671097e199481b8ef0e0150d7c2851df44c545122f9b0e5ba2eeff2d988d56d9bbb55d9896111151a436af065e0cad178a2c9fa8f6974ecdf09adf013300cffedaf4b8791b467ba7933ada5d632db44ed6dcf2aa648917be6337d2e2d206856d08f9ee7b5e2f14ddc6d3ac429215a87923ad32d5dcfee3686316ddd1b27bb193a5fc05c893a939a5b98987366c829e392f485ea15e22cd8f857a134afa98f37215576ddc5aab4f2d10caaf050059a335f24bcdcbac819f66db07aabdfb76271d17bce22cba463a80aa892d0d8e055f948df7f6e6c300daeffd3a236dddcf238fe10666a57c6e3ae7e3673d35578f8b8ea69d3c08e0140afd3ee030b22a372160f908a378f8101b5f5969fea310eed37a00d97302d5c2dbe8cc600075dccd33ad63d265aaf60e241ce311bed7dd5e2745241ae02ae532d15c18886e818138751afc51850e506c6d31a8eef451adfd4b3d266b415a7e: +07828c580ebf9e1d825a59c3bf35f072ae123355bdcc249eec7f2fc5755e29b558e5ed85100bbd9b2221afc9c93184330ad59e1385606244bf003b8d2018501b:58e5ed85100bbd9b2221afc9c93184330ad59e1385606244bf003b8d2018501b:0edad5cae6ed9843e91c50d934cf55dd658f3d252039cd6c75be4f6b866fb75f35c8f98f1721d7e6d9d98a22e0b4934dcc129261bf6723b2fa7a995e35c4bd79c5816a321607d9dcce39fefa1d55de4e7617548ec385c3de01e366bf50c457a555e932070e2a5a0197b79efbe7006f0cec78b60ebb8fa8781d8eb7326edc30e62d3297a1e0a1117108c46ee5dbefc6594289335e780d55a084f552da3f36d3c4c6178ba74d4decefc5a3b8c47c16f534bdb60895d3d54cd2bb266b399e4d4fb48d7a8cde17f42412560737d3c06e29df524d0cbd3093efca1c8fedcaa124abb27abdac6a29e0e8246abd6f5f531950037f76323aa56cc3fefa603041d55f1929e277e72cda1f96541d2af3e90c0f0e28be196d8f6921f3cd57a7926b860aa1bc403576892a96b93190ae383f631b72802658b2e8451d52a2f45db4f8bc3b0e4e50b6d603a5bdd30c234200ad7debb963f58a4fa20330b3696449445aa371824842fbf326d901dfe3be045452a3740dd160e72733f6e2733525a29a865f6f50d53bf7191c599c876f5c9ca1e3fad7960648e0d471f7d5c01c673f42d659bc3d98dbf07d8febfb995d17f9a02cd6c39f2ddcd0f1d222b9e11f2dd7d3c7518224bb6bfb8b7c58fe8ac105405903a1b9da7516715b7afc38a555e6bbcdbad46e34e576fea34ce35734ed20af5d88eeb1047a2660648bbb113ad9db8c53edb6ed9871a1e44c9ed2df5656fb2b2806ecf03b1eca9eab50a6eaab55b933b2dd1f21d450de9d5cb2232f07a392081b0b4b885d54789e2f75bf2c4cdad878989b1d6dabd9ed23c7c5b0356a7d9e7335290d7c85b966e80184bd07998602886d7076193565c81cccda4cc7d33c85d905b1beb6e8e7418e8acaedf0d9a32a7d29d07cf44d3119d4e7896820b77de64b655e4f148800434af7bdb2a56b25eb94ea39f2169596bb2b11761f082baec08885f4a0eb6c95767135a7f7cd72e743d2dff144dd8bafb1b318006e5876f8e2cb44aa588f906266ac67119c17f5de114e72e42a1fb39944321a111fa795ff7017f2fb8caf482f55d77a80855428ded7ec20acecca83f8d1eb137b588ccb745c105f2b2ca41c3a9f49d3c6e9d7c648b003b9707c906462edad617a8cfbf9bcc6c5fb6fa984325d6582e28f62005383f338df5b38fa9d19c22a2a7ea1d68a92d1d93b7fb0b8f33bc8760f28aeb1439a8b07f3da58ddb155b498cb09c75a5596838a65013e24d5640d0842a7699322cf3ffcb5703f414ffd168860bad3e308b2b5bf3cdf7f363bf9aaf4b3bc424c146c6f5421430f9f476aa34a0c6ee80131fc4d4d970723a2186ae3625e286d17dddc435ccb00831678aba584a62dbff002bead6e11e23c54d33cf3a4b231a908:bb09360439a82dee5c7d85779e54c13f88e06d38f4b94960fe17a1ebcaa3ee2f330c649154bbc875a4076cf0bbf7eebf7b8d08d5aa4be7413881245fc2d2b6010edad5cae6ed9843e91c50d934cf55dd658f3d252039cd6c75be4f6b866fb75f35c8f98f1721d7e6d9d98a22e0b4934dcc129261bf6723b2fa7a995e35c4bd79c5816a321607d9dcce39fefa1d55de4e7617548ec385c3de01e366bf50c457a555e932070e2a5a0197b79efbe7006f0cec78b60ebb8fa8781d8eb7326edc30e62d3297a1e0a1117108c46ee5dbefc6594289335e780d55a084f552da3f36d3c4c6178ba74d4decefc5a3b8c47c16f534bdb60895d3d54cd2bb266b399e4d4fb48d7a8cde17f42412560737d3c06e29df524d0cbd3093efca1c8fedcaa124abb27abdac6a29e0e8246abd6f5f531950037f76323aa56cc3fefa603041d55f1929e277e72cda1f96541d2af3e90c0f0e28be196d8f6921f3cd57a7926b860aa1bc403576892a96b93190ae383f631b72802658b2e8451d52a2f45db4f8bc3b0e4e50b6d603a5bdd30c234200ad7debb963f58a4fa20330b3696449445aa371824842fbf326d901dfe3be045452a3740dd160e72733f6e2733525a29a865f6f50d53bf7191c599c876f5c9ca1e3fad7960648e0d471f7d5c01c673f42d659bc3d98dbf07d8febfb995d17f9a02cd6c39f2ddcd0f1d222b9e11f2dd7d3c7518224bb6bfb8b7c58fe8ac105405903a1b9da7516715b7afc38a555e6bbcdbad46e34e576fea34ce35734ed20af5d88eeb1047a2660648bbb113ad9db8c53edb6ed9871a1e44c9ed2df5656fb2b2806ecf03b1eca9eab50a6eaab55b933b2dd1f21d450de9d5cb2232f07a392081b0b4b885d54789e2f75bf2c4cdad878989b1d6dabd9ed23c7c5b0356a7d9e7335290d7c85b966e80184bd07998602886d7076193565c81cccda4cc7d33c85d905b1beb6e8e7418e8acaedf0d9a32a7d29d07cf44d3119d4e7896820b77de64b655e4f148800434af7bdb2a56b25eb94ea39f2169596bb2b11761f082baec08885f4a0eb6c95767135a7f7cd72e743d2dff144dd8bafb1b318006e5876f8e2cb44aa588f906266ac67119c17f5de114e72e42a1fb39944321a111fa795ff7017f2fb8caf482f55d77a80855428ded7ec20acecca83f8d1eb137b588ccb745c105f2b2ca41c3a9f49d3c6e9d7c648b003b9707c906462edad617a8cfbf9bcc6c5fb6fa984325d6582e28f62005383f338df5b38fa9d19c22a2a7ea1d68a92d1d93b7fb0b8f33bc8760f28aeb1439a8b07f3da58ddb155b498cb09c75a5596838a65013e24d5640d0842a7699322cf3ffcb5703f414ffd168860bad3e308b2b5bf3cdf7f363bf9aaf4b3bc424c146c6f5421430f9f476aa34a0c6ee80131fc4d4d970723a2186ae3625e286d17dddc435ccb00831678aba584a62dbff002bead6e11e23c54d33cf3a4b231a908: +f08ee8daa73e1feb61a88e062dfb1003c8578a0d53bd3bc9e589efb92f68be1476692ce8d116eccb897077edcaafdd3eb44ea1a486b90e49e97f966901015502:76692ce8d116eccb897077edcaafdd3eb44ea1a486b90e49e97f966901015502:64de90044d0e76bc02fcffcb75263667b3bd733b40bfb26c6c52fdb4b0782278cabae41e2129ea4017e94de86087964f66d86207987467a1688f9fab3ffb2f1d0063bf626c941367c12e319ab7ca3020c9b3a7215a19303e2d0e8988791de0d8e1632daa38c7f3e7f6e48ce122143d1e2cb661ba77c69e6a710911644bc110ff58bb00b5290820ce30970e7fde189e140e5c70c783eed53f0e2ac7ecae4f27db81d15b8646faa9c5a3ae2b7f47cd580d7707b002499b4cfeb8c591afdf1cc62af2595c184abcf0b2623a1bae60af7026b28d0540b41526e3020f81b894eb3fe31b72b21a3260dae3210c4ce4fd69e2e5ea0c8632a583262a12b3a8b16c9c1206ad73023037cf30653cb80aa7df8314b0f5bc6e9d5fa00b009d5552d83b7970b5bc4b9984f69d1cca9ce4cb74ddd2d879d37312a0e159d7a6afb77ac585e6b459c551304e1eebfbcab43a10b505924e03ea332f5d020a55c7aa683c541dcf7790a240af079baba94096b46060fd7afe9056ca99e688df280a9be8c8c73e6e6fb052a33eb3328a7f602542fe280c890e3ccaf22c7f34f87b5e5ba784b472b1e1a99347a9e0d240858d1277a5c6b349383fe4fd55cf92e69faad326b8d6db46233026221ee6d0a1c4246533c4a0e5bd172eb8936a9c0d30066538e3eb4ad5cb9877fd861b482b30150a06104161647e01d004d997403ee06726cb97e2e25f18c668eee4c5bf72529803189ee6a7aec238d5906ea5ae10722c9a61a78aea52af33eaac75406b1a60befbaad48476d9ff887fd283eb1655bcc07cf753331436db5b3b13032ff9c3d696380e9f5abf50d3556fda0df0b53897a737ac7a3b87c2a832b0c7273ea9fc54a767f1a812bf0164bf7521630b81b9dd930d92ee2ca28e3203b77bc082ceb37d55edbcb71df0b79236789a25d418cbb95544e2cef33bbdeb27a3f7909c1f498f47135ae9033adf250ad4f6575361e4cfcc9bcf4b90c3ad47a3442297a223cca843d7205ed08a9b87160a6d01b46a7d1c844e8d1f18f618682bfb22955f395b2a5790a51a696499d9e71a501f3fa546de9b10ae47bcee42ba7f869fb9ce4ed7c6453326c034cf05d9f1e3c200701ba752dabbd868521c3d8f80672d42f6cf4564f08cd7b390e6d49dd90090afdb84486ffcaa4e84d88682744dc0a878faa7cd440a8b276710902081f4dc84174619a66ea3a371f95505400d99fa999017710c8e2714be60949d461310f7d43a0dc123516d77d362213f9f75a5a1c393affc49ea151d46a81ffad239f28c07f65f59ea077d9a4d9c752de49b9ef36be60d112d795f588b00ef6e7730dea65e1016da0dd462370e0ba5c660001e457c08b436da2903b62906932084728c81671cbfb079bb29:66dfa4c1575beff2f5a230b28c58c3eea0736df379d75559bc9d37a9579d121c05c373e8484c9747ef4477e80c4b2cb4ddf16ae9fdfa08a07547d107dcea120364de90044d0e76bc02fcffcb75263667b3bd733b40bfb26c6c52fdb4b0782278cabae41e2129ea4017e94de86087964f66d86207987467a1688f9fab3ffb2f1d0063bf626c941367c12e319ab7ca3020c9b3a7215a19303e2d0e8988791de0d8e1632daa38c7f3e7f6e48ce122143d1e2cb661ba77c69e6a710911644bc110ff58bb00b5290820ce30970e7fde189e140e5c70c783eed53f0e2ac7ecae4f27db81d15b8646faa9c5a3ae2b7f47cd580d7707b002499b4cfeb8c591afdf1cc62af2595c184abcf0b2623a1bae60af7026b28d0540b41526e3020f81b894eb3fe31b72b21a3260dae3210c4ce4fd69e2e5ea0c8632a583262a12b3a8b16c9c1206ad73023037cf30653cb80aa7df8314b0f5bc6e9d5fa00b009d5552d83b7970b5bc4b9984f69d1cca9ce4cb74ddd2d879d37312a0e159d7a6afb77ac585e6b459c551304e1eebfbcab43a10b505924e03ea332f5d020a55c7aa683c541dcf7790a240af079baba94096b46060fd7afe9056ca99e688df280a9be8c8c73e6e6fb052a33eb3328a7f602542fe280c890e3ccaf22c7f34f87b5e5ba784b472b1e1a99347a9e0d240858d1277a5c6b349383fe4fd55cf92e69faad326b8d6db46233026221ee6d0a1c4246533c4a0e5bd172eb8936a9c0d30066538e3eb4ad5cb9877fd861b482b30150a06104161647e01d004d997403ee06726cb97e2e25f18c668eee4c5bf72529803189ee6a7aec238d5906ea5ae10722c9a61a78aea52af33eaac75406b1a60befbaad48476d9ff887fd283eb1655bcc07cf753331436db5b3b13032ff9c3d696380e9f5abf50d3556fda0df0b53897a737ac7a3b87c2a832b0c7273ea9fc54a767f1a812bf0164bf7521630b81b9dd930d92ee2ca28e3203b77bc082ceb37d55edbcb71df0b79236789a25d418cbb95544e2cef33bbdeb27a3f7909c1f498f47135ae9033adf250ad4f6575361e4cfcc9bcf4b90c3ad47a3442297a223cca843d7205ed08a9b87160a6d01b46a7d1c844e8d1f18f618682bfb22955f395b2a5790a51a696499d9e71a501f3fa546de9b10ae47bcee42ba7f869fb9ce4ed7c6453326c034cf05d9f1e3c200701ba752dabbd868521c3d8f80672d42f6cf4564f08cd7b390e6d49dd90090afdb84486ffcaa4e84d88682744dc0a878faa7cd440a8b276710902081f4dc84174619a66ea3a371f95505400d99fa999017710c8e2714be60949d461310f7d43a0dc123516d77d362213f9f75a5a1c393affc49ea151d46a81ffad239f28c07f65f59ea077d9a4d9c752de49b9ef36be60d112d795f588b00ef6e7730dea65e1016da0dd462370e0ba5c660001e457c08b436da2903b62906932084728c81671cbfb079bb29: +272d64de50b1312bee23d7f4cea508a8fccf3e9b324e97b1c8e72502f61fbf4533498c3b712ab9c01ec76b2efe2b83add1e1f2b5eb78f21692323451820cbe10:33498c3b712ab9c01ec76b2efe2b83add1e1f2b5eb78f21692323451820cbe10:d6260d7eec5d436208e7e737655e0971814270194405e36e39f8f17b649fbc16c0f3d7f2bef5ebc02bb1c4df48e8470a3eae8a3ccaf640abcc094aa91150ff1a8cf1169693ebf5ac0034b9b919ecf17db791dfe5fedc90918b23e54e9004a1ae771c213ed7ed7334434e5bc02c0dda2bd1a876fb824a197bc99613b1409e7052310b0820da71446929ae7cfd3afba042de54578a5bfd94c1544391a3d9acbd5663ef65c6920d78516dec1cd55f6eb7290ba0aaf9a171658200b24a47a071b96fea03c6ca7ed0d6fe675dd63761833d75bc5e58a958582db02a60c6ce0a63f42ba837ae77c17a32705fd9cafa587b555dd4619851079794e24eb44608835a6f4824920d577a270396c9573bc7d82fe2aa0465956613a2c508cf2432337a365e6c984cba917f0cf842af122dc89dea958d418cae44a6e4ed263a415ff994a5ffb2ff13913df214bbfe90a34b247e71ab73f7ff004c23acfd90c767611aa55814c66964168e568ba75bf34903597cdcac78c24bb9f14f5c86a51f364f9ab41e464aee64fa50a1c159cbd850832c504ab42a584a96d5aee082d82c1edda19338160b8dcfa3419b3af64d9cfb104f98f9d35e5394e23228e275c87db50ca867540b880c7af29fbf534294581c22240bcd4d7d2c20ffc36733ada27653d3ae1a8c2203eac626e2e9bb4b52ce523e5adb3b2c10dcf78c2a1e626a16ebfa1bdb8c161493a5aaa2d84bfaa0f2027ffe4e9eaeb332ebda7cbbb677769d78517adf72f823a7f844165a079878d258fd95225c21177837e69c19685a051ca92b120b7d86d78595471ffc42a5e6e6431be7b64f8076458bacd6c72903cc34fc63a40cf3df00eff9d6ee9a8f39d25ead81a8128888b0a1ac0e5e3ad927712c14146adf828770ff958709eb19288e77bb70734881e9e016cd29e7d0899341ff6b297ac796bbde486ec35949f6a32b2ca647385915ecba3b9f0225087145c18d6559d3a31d6f22fc49f8a6315f1d32abeeb7cf2c2c776ea7350fd5ebc0e0f265baccc2697a7c8ca40c135f6cfcb0b58a61431960ffa9065709a961a633d570b73fb4491de52ad0d7b204b6e997b037ede3f7eca820a7cdb2c69ac29148be3523508ae7e4c3d1a717f55a821d14c3b64f08ca9ae49613b115773ef618d321c908bd2156717a434e5089a5948c045c8da8a4bd86ed5fabc6b13466e6deda583207d2ada2b2ab9cb1543df7a3734dfbc6fc428106d4844724a13df42faab18ca89db20ac9bc27b85394667c5a2779ca63ed7ac2b7c0d4122391ee4602d61ea0381764fb72dcc224e65eae2bc4506b0f09e23205d0bb21c77d8287c165e0b42c551579778acb7258a2479d7cf25b902e8d0da429bde36b4590dae96f525481ac8378:33814c6ef375ab963769b2de4a25e7020fcd97f78f8fc93455c4b1c2bd45d4b01e192900e3122265fc552cd5c5f00e931e3a183cca5ba0802dafdebb79ebeb03d6260d7eec5d436208e7e737655e0971814270194405e36e39f8f17b649fbc16c0f3d7f2bef5ebc02bb1c4df48e8470a3eae8a3ccaf640abcc094aa91150ff1a8cf1169693ebf5ac0034b9b919ecf17db791dfe5fedc90918b23e54e9004a1ae771c213ed7ed7334434e5bc02c0dda2bd1a876fb824a197bc99613b1409e7052310b0820da71446929ae7cfd3afba042de54578a5bfd94c1544391a3d9acbd5663ef65c6920d78516dec1cd55f6eb7290ba0aaf9a171658200b24a47a071b96fea03c6ca7ed0d6fe675dd63761833d75bc5e58a958582db02a60c6ce0a63f42ba837ae77c17a32705fd9cafa587b555dd4619851079794e24eb44608835a6f4824920d577a270396c9573bc7d82fe2aa0465956613a2c508cf2432337a365e6c984cba917f0cf842af122dc89dea958d418cae44a6e4ed263a415ff994a5ffb2ff13913df214bbfe90a34b247e71ab73f7ff004c23acfd90c767611aa55814c66964168e568ba75bf34903597cdcac78c24bb9f14f5c86a51f364f9ab41e464aee64fa50a1c159cbd850832c504ab42a584a96d5aee082d82c1edda19338160b8dcfa3419b3af64d9cfb104f98f9d35e5394e23228e275c87db50ca867540b880c7af29fbf534294581c22240bcd4d7d2c20ffc36733ada27653d3ae1a8c2203eac626e2e9bb4b52ce523e5adb3b2c10dcf78c2a1e626a16ebfa1bdb8c161493a5aaa2d84bfaa0f2027ffe4e9eaeb332ebda7cbbb677769d78517adf72f823a7f844165a079878d258fd95225c21177837e69c19685a051ca92b120b7d86d78595471ffc42a5e6e6431be7b64f8076458bacd6c72903cc34fc63a40cf3df00eff9d6ee9a8f39d25ead81a8128888b0a1ac0e5e3ad927712c14146adf828770ff958709eb19288e77bb70734881e9e016cd29e7d0899341ff6b297ac796bbde486ec35949f6a32b2ca647385915ecba3b9f0225087145c18d6559d3a31d6f22fc49f8a6315f1d32abeeb7cf2c2c776ea7350fd5ebc0e0f265baccc2697a7c8ca40c135f6cfcb0b58a61431960ffa9065709a961a633d570b73fb4491de52ad0d7b204b6e997b037ede3f7eca820a7cdb2c69ac29148be3523508ae7e4c3d1a717f55a821d14c3b64f08ca9ae49613b115773ef618d321c908bd2156717a434e5089a5948c045c8da8a4bd86ed5fabc6b13466e6deda583207d2ada2b2ab9cb1543df7a3734dfbc6fc428106d4844724a13df42faab18ca89db20ac9bc27b85394667c5a2779ca63ed7ac2b7c0d4122391ee4602d61ea0381764fb72dcc224e65eae2bc4506b0f09e23205d0bb21c77d8287c165e0b42c551579778acb7258a2479d7cf25b902e8d0da429bde36b4590dae96f525481ac8378: +0c9fe559ad1ed3ba164daceacb023567b2430320b6715de732a03c59c7303130e70fc466fb2acd74e099c36e2c22fa51290bdde96df9c31b6dfbfdc2e2c14a40:e70fc466fb2acd74e099c36e2c22fa51290bdde96df9c31b6dfbfdc2e2c14a40:26ebc648cf8c7965ec6ebe965d9c792bed90655ad440183c6d70ea6467bb8e6f04ec843f333156917bf4c51d0ed0f28b7cd31bc12cf840686b82b0c2c350bbdac805333725d6b69c2ab7f34ee593fa1cccedf3f0642a688fcc1cd98b0987d01f713a2fa6416c961921de0cc2c9ec7a555855e7fcd4c7ddaa14fd91ecb04224e1761b7d6b35f4aa5618a500ca00d1ca2451b5d368afde3a407e783135f39019a5b984e82ac279c05e48c295ebd1563821a0743c52246b5d2b2034e3aeb6ce7c5cf919e74a9c7bbc9e25da30430eb16ecf3837eb38a0f559792a729890ba8310260f8aeb9b5af00eb633c12dee022628ba418d75cf18de2f2e65e49b1a69684d6127ef481ca861ecbce3be86497e65df4c5fcd0817c9716b59f2a263d5e9eb606839f85c5a365837b0fbe2c4274d66cb2c65ed365fabf58f15be52b51cb60118ca4f730d447359f7ef346b750217d47b2e79c86c0c62816a0c7c18a2ce2b688e0cce0d752321e79b423857dac59f8fbeb09411e71669ef9a2643f2e99f387ac183e0b0ac72c59a0c3c18c0de8b010878074acc1a2b39f9df99d9f8f8b52fefe4943c525fd4d06ad878e46608abf27a54bc5006f647db724851db7c4578ae66583dc4bb518ef028890347e8fce0927d7d9af3ab5d0d2d202a4026aa2ea7487962676a603298e7d2e7b90921ee1b52806d71a764e03e25ddd6848f61d46fad3d008e10ee5cd5a3390f9d158a4437ef615fc90ac5bf3a9d682e12c3398ac77680d22cd1a6a56ec3b25cede867edd383159c6164d63e9cd1c956ac7235fffae936166ccd35898e29c9b4ca4e2925da323b6fbf67cfd596c88a1a35a8359851ddcba8f6134a9faa244dcb47e691276ee625cc20adcec21cbe77a3acb9ba72f0c9d3da7e9cd5be3b95990ba54a9f31af171f95aeead3331cb188a5b2c6f539acb48b98b3f7341f60251cb60429ccd9cf32f009205f2753fbbb26aa53174342ad184dab6870c0fb52930119d9f97d8489a60076aadb2e96054ac7cb7f84e13c75bbf9e4d924d2272afef0871915e243ce66fc2a8888513535b10bb4079c806bd949281e28283523d0d210b31ef62a95dcae0cd25290c7edf2c24b432822debe347f1cae945f5728c71b5403ef14e72c3d8342e198b362ee20f809e46aca015f35477ff89ac4b37e6615856f7ea251fbfe13f9065259b0946aaef24943270a854de889780033d63dda5447998a3ed7e506aeb51ea37b681ac3076797acdbfcc27883630adb72260a46af0a60d53f6654566e20d6088cd48e23b28d81f0eed205b92aafd96164d6d3ca3fc8b171804ee9fce7abaed2ea4ddf9cb2b3ae73a70ed63de45e14101428d0a7a226db39ab6cd04374080e6983f018ce93da4c89ac:6cd8aed97d9c62d5fdae597d061c0c2bc37e42df06b8327a468f92b3f438a1e6b6b1ef2be78549a289fd3fc1a6299e5a33d5396cb4fac1e8e9982f0cb3d20d0726ebc648cf8c7965ec6ebe965d9c792bed90655ad440183c6d70ea6467bb8e6f04ec843f333156917bf4c51d0ed0f28b7cd31bc12cf840686b82b0c2c350bbdac805333725d6b69c2ab7f34ee593fa1cccedf3f0642a688fcc1cd98b0987d01f713a2fa6416c961921de0cc2c9ec7a555855e7fcd4c7ddaa14fd91ecb04224e1761b7d6b35f4aa5618a500ca00d1ca2451b5d368afde3a407e783135f39019a5b984e82ac279c05e48c295ebd1563821a0743c52246b5d2b2034e3aeb6ce7c5cf919e74a9c7bbc9e25da30430eb16ecf3837eb38a0f559792a729890ba8310260f8aeb9b5af00eb633c12dee022628ba418d75cf18de2f2e65e49b1a69684d6127ef481ca861ecbce3be86497e65df4c5fcd0817c9716b59f2a263d5e9eb606839f85c5a365837b0fbe2c4274d66cb2c65ed365fabf58f15be52b51cb60118ca4f730d447359f7ef346b750217d47b2e79c86c0c62816a0c7c18a2ce2b688e0cce0d752321e79b423857dac59f8fbeb09411e71669ef9a2643f2e99f387ac183e0b0ac72c59a0c3c18c0de8b010878074acc1a2b39f9df99d9f8f8b52fefe4943c525fd4d06ad878e46608abf27a54bc5006f647db724851db7c4578ae66583dc4bb518ef028890347e8fce0927d7d9af3ab5d0d2d202a4026aa2ea7487962676a603298e7d2e7b90921ee1b52806d71a764e03e25ddd6848f61d46fad3d008e10ee5cd5a3390f9d158a4437ef615fc90ac5bf3a9d682e12c3398ac77680d22cd1a6a56ec3b25cede867edd383159c6164d63e9cd1c956ac7235fffae936166ccd35898e29c9b4ca4e2925da323b6fbf67cfd596c88a1a35a8359851ddcba8f6134a9faa244dcb47e691276ee625cc20adcec21cbe77a3acb9ba72f0c9d3da7e9cd5be3b95990ba54a9f31af171f95aeead3331cb188a5b2c6f539acb48b98b3f7341f60251cb60429ccd9cf32f009205f2753fbbb26aa53174342ad184dab6870c0fb52930119d9f97d8489a60076aadb2e96054ac7cb7f84e13c75bbf9e4d924d2272afef0871915e243ce66fc2a8888513535b10bb4079c806bd949281e28283523d0d210b31ef62a95dcae0cd25290c7edf2c24b432822debe347f1cae945f5728c71b5403ef14e72c3d8342e198b362ee20f809e46aca015f35477ff89ac4b37e6615856f7ea251fbfe13f9065259b0946aaef24943270a854de889780033d63dda5447998a3ed7e506aeb51ea37b681ac3076797acdbfcc27883630adb72260a46af0a60d53f6654566e20d6088cd48e23b28d81f0eed205b92aafd96164d6d3ca3fc8b171804ee9fce7abaed2ea4ddf9cb2b3ae73a70ed63de45e14101428d0a7a226db39ab6cd04374080e6983f018ce93da4c89ac: +15d75ad8e4afb12634cc8e600f1a4267ef9584f4c4ac44fffe4b9fcb885c9d2a09d126f017e0169774e8c37ab379263a8075746127c2d11ecb0e4cb454709ff1:09d126f017e0169774e8c37ab379263a8075746127c2d11ecb0e4cb454709ff1:d1cea2b7e9afc1f0fab890d2700a5ae41e15e7d34d3bf19d0f34d9f9f0ab9812dc7c2a8dc44c8ee7f3788761ecd988ee72c736b62a7cac3cc9b738e938df7787377eb9ffd120d4ff58cf1c0675633f7e83c4b115548f14d2f70c6d482211443a8499599558c14277980fa42a78427907f73a41f5f6693b2f75fe5e7a6ff0a6c3a4e2ed1d0d968d5cc9d6f13d41c3d291396ae7e434e664b2ff243e7f6d88010210078c39b5a576caf409bb4711b3eefc486b67b7ffeae0cbac6a0fbdf5343fb2ae4e057edc8c9d2ed31eae9ec83d2bedd219eb989b2d4419618c2d3ce4490e35fbcad432b0124795f9c5cbdc1eb0c3072b4aa801d26fbcc7b07b8257f5fe47acd9bc587b5657cf07ca545bb568c9e4e73cddf6254e22f78ab2f8064519f8abfd16fcfa90f87687db0c4209be2c6c79a5521f44189678d932c54585700a2437702e56aab588a17cb2cc94c00e87570ef3ac5133d753038aa46510a260c1fe80479bc02eed9a8d1de99354ac2648b48b96ab1b80cca6cae1877f37d70428bb50850e0308db0b423087bf7dde279e096766f2ab3ab2385b0464a5bed7bbd8d457e935e200aaaa8d951570e053076db18a6a62f72b319579884a0826ba2b436371dd218b01a0c5e58d0cd5ff9825e4466fe966df05cc31c803e5212183ddf29cef7fb91648a4f8ee19fd5f8dbd8a56be7abf33659a9224a1e27a1024effdfb88e8806148d0d1780906af1ebe3e5f14363190d88cc6e5089444f125d063155dcf86ca9263f2f5f183c26974fe000b9342d24c781e2058287cb6f3f1e3270c22b7707b8323a5cc8db81aa906bb59d696cb97cc74e359595ffb8373cad3710ea09ea9744c20e9a12e05be5a95f085ac561678d7da432e4c7cb53e1271df5cd5a339d2d7520f1c1848d15071d8c69846b23c5d2432c73890f2eded37c3d2964a4b5b55225888e892f526d1cac31eac356f361c2bf336c462d60c82e82b616f2a519c2f67bf01290369be9b55e9f5c8cec4f2e1b2ab302506c903dc3e7b9c978141dc904b01b1c23d25004399bf8b73d69cd539c79af5e9a0a511eca221078a1ff7b0f604aea84246c3cb32db9381be121767e097bea517bfcd82dfe921379840efb4b6f02a48ecdaf12d2cd38930d4473adf97cd71dc4ea10382f4f5d1dd7562cd4bf5115932f6c4700aa8fe8deca9d5e7277902b8f886529765db2486074b23a19fd4b04356bfa6226c82baf69a087d9ca18823f8e3e68308e16b804c363df5b6307e76240db1ed841b612d65548ddfbe8367da60772c6aff554dc85d041948345e567da9333151858fdf6993273925bfdc7181b5f646d063a8c8f310569b0ed093bd9dff04febf0b41c6dc55169a14a3c862e5416f1e582fdee8fe87dc:a8f2f4b9e2072ca9fade37fdd62d8d0242fd4daa09fd856e75f4e343c7260ea677f753a627aed08cb96c444e29bdb5b5385d43843bbe79a3dda36e1e1101c50fd1cea2b7e9afc1f0fab890d2700a5ae41e15e7d34d3bf19d0f34d9f9f0ab9812dc7c2a8dc44c8ee7f3788761ecd988ee72c736b62a7cac3cc9b738e938df7787377eb9ffd120d4ff58cf1c0675633f7e83c4b115548f14d2f70c6d482211443a8499599558c14277980fa42a78427907f73a41f5f6693b2f75fe5e7a6ff0a6c3a4e2ed1d0d968d5cc9d6f13d41c3d291396ae7e434e664b2ff243e7f6d88010210078c39b5a576caf409bb4711b3eefc486b67b7ffeae0cbac6a0fbdf5343fb2ae4e057edc8c9d2ed31eae9ec83d2bedd219eb989b2d4419618c2d3ce4490e35fbcad432b0124795f9c5cbdc1eb0c3072b4aa801d26fbcc7b07b8257f5fe47acd9bc587b5657cf07ca545bb568c9e4e73cddf6254e22f78ab2f8064519f8abfd16fcfa90f87687db0c4209be2c6c79a5521f44189678d932c54585700a2437702e56aab588a17cb2cc94c00e87570ef3ac5133d753038aa46510a260c1fe80479bc02eed9a8d1de99354ac2648b48b96ab1b80cca6cae1877f37d70428bb50850e0308db0b423087bf7dde279e096766f2ab3ab2385b0464a5bed7bbd8d457e935e200aaaa8d951570e053076db18a6a62f72b319579884a0826ba2b436371dd218b01a0c5e58d0cd5ff9825e4466fe966df05cc31c803e5212183ddf29cef7fb91648a4f8ee19fd5f8dbd8a56be7abf33659a9224a1e27a1024effdfb88e8806148d0d1780906af1ebe3e5f14363190d88cc6e5089444f125d063155dcf86ca9263f2f5f183c26974fe000b9342d24c781e2058287cb6f3f1e3270c22b7707b8323a5cc8db81aa906bb59d696cb97cc74e359595ffb8373cad3710ea09ea9744c20e9a12e05be5a95f085ac561678d7da432e4c7cb53e1271df5cd5a339d2d7520f1c1848d15071d8c69846b23c5d2432c73890f2eded37c3d2964a4b5b55225888e892f526d1cac31eac356f361c2bf336c462d60c82e82b616f2a519c2f67bf01290369be9b55e9f5c8cec4f2e1b2ab302506c903dc3e7b9c978141dc904b01b1c23d25004399bf8b73d69cd539c79af5e9a0a511eca221078a1ff7b0f604aea84246c3cb32db9381be121767e097bea517bfcd82dfe921379840efb4b6f02a48ecdaf12d2cd38930d4473adf97cd71dc4ea10382f4f5d1dd7562cd4bf5115932f6c4700aa8fe8deca9d5e7277902b8f886529765db2486074b23a19fd4b04356bfa6226c82baf69a087d9ca18823f8e3e68308e16b804c363df5b6307e76240db1ed841b612d65548ddfbe8367da60772c6aff554dc85d041948345e567da9333151858fdf6993273925bfdc7181b5f646d063a8c8f310569b0ed093bd9dff04febf0b41c6dc55169a14a3c862e5416f1e582fdee8fe87dc: +bf3c0cbbbe20be2acfafb27a3611b48921a728ab17334b8afdee8305178f613b4500a03c3a3fc78ac79d0c6e03dfc27cfc3616a42ed2c8c187886d4e6e0c27fd:4500a03c3a3fc78ac79d0c6e03dfc27cfc3616a42ed2c8c187886d4e6e0c27fd:8f30ba2f792e9a97f6eafe29f976a48028cb8857b5c798bc2b6168c46444c0ce696070374c5e6a40c3d18a5dc7669fc41db9a81cff759b8ca0159871c3442e8c7512698fa447b5783ee01d1b611449abad237162922b02d1aec5de1d666f17da1613106301d30586d116e2ac09007dd71e8123ede4c5a6a9ac077fe3d93909da628e865870a4e25cb35591675a0690bec4af0281714fe6661bd5c00a27d79f959fb4d4fb1636a6a3575f4f01470663899d737472b096be4db723715367a41a3a4c13f742d908f4d921cfdd156e75868261ba9c10d85874ca2d6c0c9e7295e5662bd916a363c7a796ead617c4251e6794da06c3d08f2fdc3886944a7509e6409c906b593113b4b1f9850132960d9f3a4eeb7386fa592f6193beab8e0ff0f28908a0d548db87bae978b05abbca9b3e96d8795b88077f620f2124e31590eb099e94e0e6e3cd620ae6290f3e2d01467e5bef4fabdef79d9ab9239e753ec4fa0bb110ff1d393fca02243502d7e987991eb76d08f8be7eb2b1ee00c3b68bbf72a623baa15be896b3215ebe8a82313109fc629b0cce6491f813c24970e4ffe6869e40b46b4ed22986d0042155276c230de4c05d678552f2e851cacf5a472157dbb1a99a2b42ff4037f0dc6380672921c909206e80050e61a6b3056b17e3ae835009b20419a3b9846d374892e719f1b35bc1257da93ccc6d8f8fcaa8e609a8d204df108be7193467e7f105935282c3fe6670a5329442ea3edda2376a03a1cfe8723a909c064d30fe9bb0212c33afe2bea30c9143c001da01c7ed504559b97fe2cea09beb9db51900dc136705921e20297845ba72a97aa7c953814571be3f08cef968045a5ac34004f67fbfa54e996b311bd8dc527d89e1d4f53453a6713720101c45a60ee3a05c2ee66f134b5af40e4b70ef37ba3f0afdefc039f342c28af9198251381a1079a5dd035a8c28976c6b7f4db09ea383a3a87f0f851fd331aea7fa4bfcd95631d652fa2f50f1c23ff2bc137a0604e3d9f39ccb965145bca48b06dc8a817547b625effa796d000c3774bad198db1241be7a2c0dc4a4641b9a8cb9cb8c8c3887576f5272c33aaffe45615f51a96fae76cf5125bc69ad0a4038790799b5c2624421a6433dbab39cccb0b1787b5bce289594489d17edb5f9310374807d36c6e6734726bb33004ecae8bb691dcd387601f4ea911b4b90ebff756d7d8d9eb422cbb9aaf7f4772e0a5436430685e57b697454e82eeadce4aba062b77682cf219be1fd9b00f1cb1135a1021349539a4b93ae213f193d2932738ef72920499b7be2a81c9baaed17c54641a5974d27223241e3c6a095226bd237e0591e002b3af0565df3e976420f9764a09ae8bfa2795f8fad7fc687bd2de23d1488f449d8:8f8703bcf4c0329417339eb026f2b72d314d922e9accb5d8bb7eec87e07e6138551672a6132cb4f875508ed3299567b4a74134d2bdf0d857f980861d18be7e018f30ba2f792e9a97f6eafe29f976a48028cb8857b5c798bc2b6168c46444c0ce696070374c5e6a40c3d18a5dc7669fc41db9a81cff759b8ca0159871c3442e8c7512698fa447b5783ee01d1b611449abad237162922b02d1aec5de1d666f17da1613106301d30586d116e2ac09007dd71e8123ede4c5a6a9ac077fe3d93909da628e865870a4e25cb35591675a0690bec4af0281714fe6661bd5c00a27d79f959fb4d4fb1636a6a3575f4f01470663899d737472b096be4db723715367a41a3a4c13f742d908f4d921cfdd156e75868261ba9c10d85874ca2d6c0c9e7295e5662bd916a363c7a796ead617c4251e6794da06c3d08f2fdc3886944a7509e6409c906b593113b4b1f9850132960d9f3a4eeb7386fa592f6193beab8e0ff0f28908a0d548db87bae978b05abbca9b3e96d8795b88077f620f2124e31590eb099e94e0e6e3cd620ae6290f3e2d01467e5bef4fabdef79d9ab9239e753ec4fa0bb110ff1d393fca02243502d7e987991eb76d08f8be7eb2b1ee00c3b68bbf72a623baa15be896b3215ebe8a82313109fc629b0cce6491f813c24970e4ffe6869e40b46b4ed22986d0042155276c230de4c05d678552f2e851cacf5a472157dbb1a99a2b42ff4037f0dc6380672921c909206e80050e61a6b3056b17e3ae835009b20419a3b9846d374892e719f1b35bc1257da93ccc6d8f8fcaa8e609a8d204df108be7193467e7f105935282c3fe6670a5329442ea3edda2376a03a1cfe8723a909c064d30fe9bb0212c33afe2bea30c9143c001da01c7ed504559b97fe2cea09beb9db51900dc136705921e20297845ba72a97aa7c953814571be3f08cef968045a5ac34004f67fbfa54e996b311bd8dc527d89e1d4f53453a6713720101c45a60ee3a05c2ee66f134b5af40e4b70ef37ba3f0afdefc039f342c28af9198251381a1079a5dd035a8c28976c6b7f4db09ea383a3a87f0f851fd331aea7fa4bfcd95631d652fa2f50f1c23ff2bc137a0604e3d9f39ccb965145bca48b06dc8a817547b625effa796d000c3774bad198db1241be7a2c0dc4a4641b9a8cb9cb8c8c3887576f5272c33aaffe45615f51a96fae76cf5125bc69ad0a4038790799b5c2624421a6433dbab39cccb0b1787b5bce289594489d17edb5f9310374807d36c6e6734726bb33004ecae8bb691dcd387601f4ea911b4b90ebff756d7d8d9eb422cbb9aaf7f4772e0a5436430685e57b697454e82eeadce4aba062b77682cf219be1fd9b00f1cb1135a1021349539a4b93ae213f193d2932738ef72920499b7be2a81c9baaed17c54641a5974d27223241e3c6a095226bd237e0591e002b3af0565df3e976420f9764a09ae8bfa2795f8fad7fc687bd2de23d1488f449d8: +287fafd21374572f57810047d0d98cb1ff3d0120faa4886132245732c1a6ab78e8252063f5ad7e95bd05c502a8bc4a17556360869b9de0a3b858938e11117619:e8252063f5ad7e95bd05c502a8bc4a17556360869b9de0a3b858938e11117619:b3c443e4e5899c16d39e81b4f8074042a904a735074b2795d9ac06b1379ef7618d2a534b6bef81569e60719267bf29cd9d16acc9a174d8026b14b127d0d2d8b4583998895ad7ef72fedc53b8f08a2250100e1f1f0aab48bc7074643488e6b670e1b0727c385a34ff65a0d7e83ba86083b873dff0559209b14b2ac42bf7c572d0c5917ac42e4ae4dae1dd4235795276a076132cfe3e0c350b26580fbb3af81777b93ad95cb7ff17c2d980ce0d492f6d40fa90ba3fcaa21bb68735ee1ef208495ebf7b02276ffa1efc081658bb44cd2761ef5e3e1ca60ec8b5d816d4abacd0bcc80268d8f4df8b3a52049db0157e2b6e81acd6f3f28947c07627955cdac9eaa1de17d4b9daa361fb49782664d7d6d2ca5cec6d14893c3e80b6d16daacffcc0b75937e8bef6f9e112a87f4b035f9036070a2ccc55c2aad939df674f7e4e12685e016ea0e4902aaaafaffe38ddb2f90d9cf78537f61391696ff0330ae8f79a1c1ed5d52b4ee2a62d90fb82d9a48393fa33810b40d0455902d574ff052003e0160c0f47b5e580a078bceef06073dda8b2d1f104a595e90bb6a48eddd865f1cae4f178fe22e75f2f6124a9da0682447112b3db5be8c42472b241e944fd2370c2dc2715c05a41bdbc890c41c65fb08c2f593174391ac880f3cb67d1b74ff802ef962afef7b9f3ea326f9527e7fba698187924b64ccdd0866248c76ee64c79069be0a057b10ae190f38ff5aba844e39331cf1db13c900906bee0d7e7546ef52324e37c590675f139f58f573a494f4ae82c4ec81066a68e2d92900191c47d3062f0f9aaed191137cda9b83cd130e8262960e6244f8f6ef39f15a4fed13cb669edc19f5ce162ceb8d242b9addbfba8772ce74985a5f3720d590a920e1dca75a879b1aa459f7462fff2e95072761b209254fe38c54d833a8e2cb8fc40c598f3c7f7d6c5705715d0308dc30eaa84676d209d7b7b31344756e69a9a4cb4e4a251817a3786fea6728dd60822336b45ae5d47c704b45c4cad38c1e01ab93d141692d55d12fdb9740f1d181582f1c48ce5434860d930f0e7e70edcffb85560a53dba95d57b31e8924137bc2c19e34bb9c9866877174280e80c23978d57795864a7374aef383f3bf6375359bf63564740098461a6c76e8f238913288769a1cb1c95b22c32a9ebb3eceb048ee324cf0d7e85a389b04dedbbcbeef298d0527816085c0c83efaa298546e8390bd1bfe465ec1bafae69ee5218e72caedb9b649cf73eec454a2b484965179672debcf9441363995a8a907de17dc0684f2aea579a2fb4484195db4115ca32e970526dc00a5cacaf588711dbd469ce80bd297c4f41d6fa28a597c6372c0d214960b54598cd8bc849ebdca36d6225b20dec0d031169cebb36eadc3a:6201e30591d36b7b226e36fdf56434c47cd3051837af31313a9917fd02dded2b5bbb4bbc368b3bd15d062045f105b6e7341b15150d36f90087591d839901b801b3c443e4e5899c16d39e81b4f8074042a904a735074b2795d9ac06b1379ef7618d2a534b6bef81569e60719267bf29cd9d16acc9a174d8026b14b127d0d2d8b4583998895ad7ef72fedc53b8f08a2250100e1f1f0aab48bc7074643488e6b670e1b0727c385a34ff65a0d7e83ba86083b873dff0559209b14b2ac42bf7c572d0c5917ac42e4ae4dae1dd4235795276a076132cfe3e0c350b26580fbb3af81777b93ad95cb7ff17c2d980ce0d492f6d40fa90ba3fcaa21bb68735ee1ef208495ebf7b02276ffa1efc081658bb44cd2761ef5e3e1ca60ec8b5d816d4abacd0bcc80268d8f4df8b3a52049db0157e2b6e81acd6f3f28947c07627955cdac9eaa1de17d4b9daa361fb49782664d7d6d2ca5cec6d14893c3e80b6d16daacffcc0b75937e8bef6f9e112a87f4b035f9036070a2ccc55c2aad939df674f7e4e12685e016ea0e4902aaaafaffe38ddb2f90d9cf78537f61391696ff0330ae8f79a1c1ed5d52b4ee2a62d90fb82d9a48393fa33810b40d0455902d574ff052003e0160c0f47b5e580a078bceef06073dda8b2d1f104a595e90bb6a48eddd865f1cae4f178fe22e75f2f6124a9da0682447112b3db5be8c42472b241e944fd2370c2dc2715c05a41bdbc890c41c65fb08c2f593174391ac880f3cb67d1b74ff802ef962afef7b9f3ea326f9527e7fba698187924b64ccdd0866248c76ee64c79069be0a057b10ae190f38ff5aba844e39331cf1db13c900906bee0d7e7546ef52324e37c590675f139f58f573a494f4ae82c4ec81066a68e2d92900191c47d3062f0f9aaed191137cda9b83cd130e8262960e6244f8f6ef39f15a4fed13cb669edc19f5ce162ceb8d242b9addbfba8772ce74985a5f3720d590a920e1dca75a879b1aa459f7462fff2e95072761b209254fe38c54d833a8e2cb8fc40c598f3c7f7d6c5705715d0308dc30eaa84676d209d7b7b31344756e69a9a4cb4e4a251817a3786fea6728dd60822336b45ae5d47c704b45c4cad38c1e01ab93d141692d55d12fdb9740f1d181582f1c48ce5434860d930f0e7e70edcffb85560a53dba95d57b31e8924137bc2c19e34bb9c9866877174280e80c23978d57795864a7374aef383f3bf6375359bf63564740098461a6c76e8f238913288769a1cb1c95b22c32a9ebb3eceb048ee324cf0d7e85a389b04dedbbcbeef298d0527816085c0c83efaa298546e8390bd1bfe465ec1bafae69ee5218e72caedb9b649cf73eec454a2b484965179672debcf9441363995a8a907de17dc0684f2aea579a2fb4484195db4115ca32e970526dc00a5cacaf588711dbd469ce80bd297c4f41d6fa28a597c6372c0d214960b54598cd8bc849ebdca36d6225b20dec0d031169cebb36eadc3a: +9ad049100851d0f79b711225c98847795acfc3601c14b8a9778d6270cd4c05ede7cacf4f3714543c27a3e9ed833baf3bde4c09563bef59e763fab71fb5e4ff56:e7cacf4f3714543c27a3e9ed833baf3bde4c09563bef59e763fab71fb5e4ff56:c284bdd8f8275b49ac808c39045e50e1ed50c8a1afd011afe5db3dda620be8aec37f45605762e225d04111f21b49fcefca3f3d5f813b2020a52c49f95c4ad61ca214618ade7eed6cd8d314dc4c6355955277d457462f03b9fba2e225b1b537cd4b5237505c90d43205e1715c3963ccfbec379e6c1705e08034a31afce646727e78a20eed88aeb0dcdabc5c86e86979e63a5c26c3e2177973b6983cebfeda9f31479361b661763aa7261c0939cad48b71908ea90768bb6c9583d8eaeb9e0338515aca1242626dc6be04ecc4429e4cbb4ff336096192f7501ec471b596a99d4c027582cc69e204b6fbcddf59f5bf7462ddcd5989121fd10f11a0675b6c4e4f6520d27d7c61431ba7d174f57395a0bf72d38c1142736ded6b91e4811c0e8541a6c0d996c5a17dc97db388f721d2357d3c6af5c86b1d5e476ea0ac0b1c11d4387f769039bdf538a0216edd0045ee6dd89eef82a425a83faa1b12807038ca19ebec002e8b3c15344c61cfd1e5f0e3b0273deb37278cf197d8a83b13d992308a51373eb38114c9e45b438780277d1e32f3972962a3e14a8d08db9f09aec3dd32a5b99423e61f5e79944ab57a36f6ec07cc3204f9165ee021ada93e6fecb7ec456aa0288c378a75afd6e9dad6c6f88e959a2cf28bfe56d2e61b2adaecf0d86dd8928bceda26b0540246b7337f5cdcec11fb0c1a59d631fcca19408f9522b68a39f86ef970b883a0f0bd6b7b1415ec9aa043b52e19bac176d67b79e2a5dca8bfd29102ac608e473e9f982c3ec8932d8aa8cd565284491de52f516b9ebfb7dbe1299511ae732c2ad1ee4992b077faffc65f488f1ba215da6979600971196d0ff3a08ad9f00e829c1de1afca10ca476be664aad261889b0eb7aeb6ed8637618900acf481e2d224ec64a6e6cf4fa4df731b7a4feeff2580c99b6d75b4dcd0976965cb2b0b5635227842d08a7d907aaebc2fded8009811dcdd73354921753bc5dec017689335f56d0fb7ae213b41792b1f4eb14a24535977a305b19eb9838dc6b51528b98a39bda06010717a208c347aa158eecdfd9a0472d3b8d920f969e12b65919bda38b461949850cc9cc18d8e3baa8c886d93cd096a209d543ca3375fc4e7d65103cb6424beab44e8bc4a5b62c29a01bcf44dcc61e7675c025dec0724200194bde74d72c02e94a946a752f3608457fd91f292715771487d26cad4e5cf6ef7c6f71627a4daf8a4c9b891c1ee8f04aeaa99fe0c8b4e833b7609066b6132a968890e2695da22b2d857c8c0ad9187c96069e476e27e4632c447ee76714a31d1e5149ecb337ee132f3552da33ab2d6fa9d7e93f68a77cbf191cb06bc22f3470af6d7581e3accbeca0b6feb08a14b9a80c1ef59374ccdc0523c3684504c0104bba22c10:fec0af34cbc5cffc56e96dd5ed5968e52cbd4269844fc30e3ab0d3472b5d180c8d1b7690518f41f14438e7f3a83d5e8976cb9a26151fc4149a3298d7e42c0503c284bdd8f8275b49ac808c39045e50e1ed50c8a1afd011afe5db3dda620be8aec37f45605762e225d04111f21b49fcefca3f3d5f813b2020a52c49f95c4ad61ca214618ade7eed6cd8d314dc4c6355955277d457462f03b9fba2e225b1b537cd4b5237505c90d43205e1715c3963ccfbec379e6c1705e08034a31afce646727e78a20eed88aeb0dcdabc5c86e86979e63a5c26c3e2177973b6983cebfeda9f31479361b661763aa7261c0939cad48b71908ea90768bb6c9583d8eaeb9e0338515aca1242626dc6be04ecc4429e4cbb4ff336096192f7501ec471b596a99d4c027582cc69e204b6fbcddf59f5bf7462ddcd5989121fd10f11a0675b6c4e4f6520d27d7c61431ba7d174f57395a0bf72d38c1142736ded6b91e4811c0e8541a6c0d996c5a17dc97db388f721d2357d3c6af5c86b1d5e476ea0ac0b1c11d4387f769039bdf538a0216edd0045ee6dd89eef82a425a83faa1b12807038ca19ebec002e8b3c15344c61cfd1e5f0e3b0273deb37278cf197d8a83b13d992308a51373eb38114c9e45b438780277d1e32f3972962a3e14a8d08db9f09aec3dd32a5b99423e61f5e79944ab57a36f6ec07cc3204f9165ee021ada93e6fecb7ec456aa0288c378a75afd6e9dad6c6f88e959a2cf28bfe56d2e61b2adaecf0d86dd8928bceda26b0540246b7337f5cdcec11fb0c1a59d631fcca19408f9522b68a39f86ef970b883a0f0bd6b7b1415ec9aa043b52e19bac176d67b79e2a5dca8bfd29102ac608e473e9f982c3ec8932d8aa8cd565284491de52f516b9ebfb7dbe1299511ae732c2ad1ee4992b077faffc65f488f1ba215da6979600971196d0ff3a08ad9f00e829c1de1afca10ca476be664aad261889b0eb7aeb6ed8637618900acf481e2d224ec64a6e6cf4fa4df731b7a4feeff2580c99b6d75b4dcd0976965cb2b0b5635227842d08a7d907aaebc2fded8009811dcdd73354921753bc5dec017689335f56d0fb7ae213b41792b1f4eb14a24535977a305b19eb9838dc6b51528b98a39bda06010717a208c347aa158eecdfd9a0472d3b8d920f969e12b65919bda38b461949850cc9cc18d8e3baa8c886d93cd096a209d543ca3375fc4e7d65103cb6424beab44e8bc4a5b62c29a01bcf44dcc61e7675c025dec0724200194bde74d72c02e94a946a752f3608457fd91f292715771487d26cad4e5cf6ef7c6f71627a4daf8a4c9b891c1ee8f04aeaa99fe0c8b4e833b7609066b6132a968890e2695da22b2d857c8c0ad9187c96069e476e27e4632c447ee76714a31d1e5149ecb337ee132f3552da33ab2d6fa9d7e93f68a77cbf191cb06bc22f3470af6d7581e3accbeca0b6feb08a14b9a80c1ef59374ccdc0523c3684504c0104bba22c10: +de54e13f9e2cc754546c99b33b3d72f4d1f7715038a9659f33636577bb526adb36338db3326b005e5c61ff782be2eab166d4eb7234a98ea1cd855e1ad535e94c:36338db3326b005e5c61ff782be2eab166d4eb7234a98ea1cd855e1ad535e94c:dc4041ad61423a12a0411318a6e62a5ef64a19abe2d9852297be2d4a35eb8670ca36c521531b3038acdaeea2ea01a0b6187862a4e1a89d4b81c5318ed4d67131bc38f841a142a2f6f316dff076939dc0eb81b230fea9881f8f0ff7ed0b293f69b289fe770881fb3710808e8e59e64e190c1e379b9dd348b02c2347d7e20696790b62776a2e825bed6917037cb635c92fbc76b4c5851027e7f13852ee7e7c52573a9030b79f22b60d5869efe680c01664929fe9a06fa333052be1d6af3a0b482c332e18051e78b333839d6cb93d93ebfb277e4268fbeeeeba1e8f96a5c9e328c4267212cac251215bfaa78fd88a87417a80602dcd8828e80400da304e989862d13201082de3530925e0edc2c130a9a419071b31088da6f6ff4056301c129fc2135233628d16d8bf160f6ce86d83cd4e29ae0c73843d70b53056c5af3f3dc561271cb5aff393f0803ade072d9ceb745b6187b28d24696767d5c21f4d4ac58d5bb66c5cadfefb1626ef93f714c782b6ef3ccf4b44ee75f0bb757a25d9b46a9d931a03727d496a22810c634f5c1ae60cbdf2f1ea29b54607cff50d9f8e03a0a4513cf68dfb619773411b6180959a8aac30b2eee4ad327915f60ae52b90e04a9bcef8dc67e71ea10aca553db9895cd8008457d76f02ceb53500211109e89603f304d880aaf02861fe37c9534a9d672d83713cd326c9ab81c353764ca5ad5ac0e7f1ff880fb48acd9cbb949064e21183bc38fb1d90cfe619a8b8fbf5321889bb15c02a53e4d367fc668877b662281c4a2af678f86e691daa8afdcac1b820189fe5c2508ce36edd9c6f8f51575071839439a003352c1573e12768dd6debdf1ed4f94ac79df1ab6a0bc25079c0935477d9149988ec3b8793efcda859acc392ab3fa99493d7ae0a6575b695a1ce076532860287dd498967c46f7add49494c02e744c40280195782e2424476165e72cee23642e51cec432191116aec59b59fcf0a3683b95f760760a20bd67454d8de647c0f9ffc4f90f6e45ac93d802f338299ef280d3bb7a4a89db8c59a12526f2783024c8ade9002f00e3d529b78dcdd4903daf5767a2bed75145396efb69790712de6a5901e6d8c15280182388285021d0e70929215d9f2b799bb92f2ca56f48e8cbba2f19b085845126567cfafa603c2946ea1e7d274554a38bf7d86511f3e474f9fa5cb11105fb52fc68177f3385fe1397be584a70089dc741b4b0095bf7eb2993b418df87b14a1f97926e868df6e568beca2215f2dd7ce8a3c9ee849cb41346c684f7ffef0a792edf433ca99ef34c73f9272a7eb97587c8fce4a5136444737138d53eadf3a84f501bb10456e8e4a4047082c9e1435f576526c2164714d70b3d0a6e9c08a53e323840f4dcfe8f2d19f0be2c88e:37aca8f248394a9e04d06a7da84a7defa39de4da2bcb18d5f64cc34db08651af4abb19fa2a92a7dda56ec9930b81aebd23990511f684c6d15ba595f7d4a2740edc4041ad61423a12a0411318a6e62a5ef64a19abe2d9852297be2d4a35eb8670ca36c521531b3038acdaeea2ea01a0b6187862a4e1a89d4b81c5318ed4d67131bc38f841a142a2f6f316dff076939dc0eb81b230fea9881f8f0ff7ed0b293f69b289fe770881fb3710808e8e59e64e190c1e379b9dd348b02c2347d7e20696790b62776a2e825bed6917037cb635c92fbc76b4c5851027e7f13852ee7e7c52573a9030b79f22b60d5869efe680c01664929fe9a06fa333052be1d6af3a0b482c332e18051e78b333839d6cb93d93ebfb277e4268fbeeeeba1e8f96a5c9e328c4267212cac251215bfaa78fd88a87417a80602dcd8828e80400da304e989862d13201082de3530925e0edc2c130a9a419071b31088da6f6ff4056301c129fc2135233628d16d8bf160f6ce86d83cd4e29ae0c73843d70b53056c5af3f3dc561271cb5aff393f0803ade072d9ceb745b6187b28d24696767d5c21f4d4ac58d5bb66c5cadfefb1626ef93f714c782b6ef3ccf4b44ee75f0bb757a25d9b46a9d931a03727d496a22810c634f5c1ae60cbdf2f1ea29b54607cff50d9f8e03a0a4513cf68dfb619773411b6180959a8aac30b2eee4ad327915f60ae52b90e04a9bcef8dc67e71ea10aca553db9895cd8008457d76f02ceb53500211109e89603f304d880aaf02861fe37c9534a9d672d83713cd326c9ab81c353764ca5ad5ac0e7f1ff880fb48acd9cbb949064e21183bc38fb1d90cfe619a8b8fbf5321889bb15c02a53e4d367fc668877b662281c4a2af678f86e691daa8afdcac1b820189fe5c2508ce36edd9c6f8f51575071839439a003352c1573e12768dd6debdf1ed4f94ac79df1ab6a0bc25079c0935477d9149988ec3b8793efcda859acc392ab3fa99493d7ae0a6575b695a1ce076532860287dd498967c46f7add49494c02e744c40280195782e2424476165e72cee23642e51cec432191116aec59b59fcf0a3683b95f760760a20bd67454d8de647c0f9ffc4f90f6e45ac93d802f338299ef280d3bb7a4a89db8c59a12526f2783024c8ade9002f00e3d529b78dcdd4903daf5767a2bed75145396efb69790712de6a5901e6d8c15280182388285021d0e70929215d9f2b799bb92f2ca56f48e8cbba2f19b085845126567cfafa603c2946ea1e7d274554a38bf7d86511f3e474f9fa5cb11105fb52fc68177f3385fe1397be584a70089dc741b4b0095bf7eb2993b418df87b14a1f97926e868df6e568beca2215f2dd7ce8a3c9ee849cb41346c684f7ffef0a792edf433ca99ef34c73f9272a7eb97587c8fce4a5136444737138d53eadf3a84f501bb10456e8e4a4047082c9e1435f576526c2164714d70b3d0a6e9c08a53e323840f4dcfe8f2d19f0be2c88e: +8504fbcaaba67683f815499282b6ebd497a81a9156f53e025c2d3ecee0db6559e62da86493a0caf52921d5602fbdc3dd3a8436941f6be240b31509681238746d:e62da86493a0caf52921d5602fbdc3dd3a8436941f6be240b31509681238746d:6c63edbd40a03874ecaef81602cd6850c09f4915b7aaf418258c568364538e8392a8c379838b0c95345bf64c3dbc175853fb641f350f0b53a05a8ec290288c0326d435ff776f8683a273333f9bb2802184ecc53b06b28c2c402a54bf134c1a23299749a6ce2b51a7ba22232148797e993ff258286e947778a8742d3f36cc7842976043fc23da8a97ecb9715fc05fb0f23fa7321ddc1932861631604eba2ef25d8b756ce4733656bfd1e14708923ac7c60a79846136d741973ba5514189720bc0f7774b7bd3574595bde2515031b25b62654b161035778070ace14971df1fe0be4ea1ef55cf8747d3716c1ce707b1a7c8520e6deb334eb186338fc93000768eb2be40c6e0dc3f5df831b32c3a2c33e28898d6762a1522d3d48daee56a0269bddf6cfc9d73f8d178aeccbffef7ce164f98afea224a9b60ede46a95fadc9fc5d94d209c166d9b8de253381ea2248862946b9cf534947455c24458cf56683a0ec47a2c65075c694c7c3d6adf9ae5e8ad31ac769f83aa26e312c5b01a9a09404b15b814baa7666b3e03f06a8d6348ab8ccb9b60a4a4faf86f7135df039d955c07bd92e7b8e327ee6c1b40196a28b4446aa5a9b2b9773ab76e3ce21180f09d6c08d277c6771d67e22d84540fa43b38f634cfc46e5b8c33f15a568a77e4914aad9ab8c9f7fea47f7677c01880b3e85d2d0e3fbd6dc6e99e437ddc736f92b5a2ff2927e0b442142f0897d0b8a19ac203633df413feaf8ef50a5f767bedaf20f1c13f3b89d1e8b7bd18d591f9de116ee34f9824e4ead1ae9da2e8caaef88b29516aa942de77a7467b6fb26a666f30648c715a2ee9f946743b543a4428e0dfd06178e7e93ec6f26e003e058bec14a4aa2e3b8de11295a764cab30b313fcc5743b2fb89962ddc5cdc6aa0d2e4a306e77af76a05a598923f628a85df1cc73ad3bc01c4b979bd7cb296590a88b0a41b445d50a08423e4ed80f1763c716b6c457d845dfaa68d12b0d03c55fde8ae6b2b92bc6322943dbe54c706bc8e5fcee70654b26f3bfd877f5f5339ac182d5417bd4c0735d825bf70e85eab8216edda632ae7e22b3e53d078a8b20b5a7e2385337cf92b3c16b023563e11cb5043b704d37eb5ed9e85fcdc95cf7a6eade40803175a008ef653ac6136f16129abae1137c5823400748a81256254d317cfc939e26ea0cef9f6548db42890c48beb0479103ba089e514118038b1b90943d716f7a8d4cda5983a674b83a002d8ac9c65734a28b77b760c8e3803f8781ea9199f797ce729e06bfffe8c29b20bc85227c09cc05219ff2ba38e18051083732f83cbfccc310756450b261d5be183d9fb44ec18529f2cc9848c40119c607676bc4d9015fd4bd2fc918dc8031ec19a05ff362c184043be7fe066019ac5:c0ea074bf9addee2e3350a969e7c569e3aea1a4188ee5af34cb73f388298653d299b5dbd94163fba209e8f7dc2e2634d3a52a02810a88c6152945bc16bbdfb0c6c63edbd40a03874ecaef81602cd6850c09f4915b7aaf418258c568364538e8392a8c379838b0c95345bf64c3dbc175853fb641f350f0b53a05a8ec290288c0326d435ff776f8683a273333f9bb2802184ecc53b06b28c2c402a54bf134c1a23299749a6ce2b51a7ba22232148797e993ff258286e947778a8742d3f36cc7842976043fc23da8a97ecb9715fc05fb0f23fa7321ddc1932861631604eba2ef25d8b756ce4733656bfd1e14708923ac7c60a79846136d741973ba5514189720bc0f7774b7bd3574595bde2515031b25b62654b161035778070ace14971df1fe0be4ea1ef55cf8747d3716c1ce707b1a7c8520e6deb334eb186338fc93000768eb2be40c6e0dc3f5df831b32c3a2c33e28898d6762a1522d3d48daee56a0269bddf6cfc9d73f8d178aeccbffef7ce164f98afea224a9b60ede46a95fadc9fc5d94d209c166d9b8de253381ea2248862946b9cf534947455c24458cf56683a0ec47a2c65075c694c7c3d6adf9ae5e8ad31ac769f83aa26e312c5b01a9a09404b15b814baa7666b3e03f06a8d6348ab8ccb9b60a4a4faf86f7135df039d955c07bd92e7b8e327ee6c1b40196a28b4446aa5a9b2b9773ab76e3ce21180f09d6c08d277c6771d67e22d84540fa43b38f634cfc46e5b8c33f15a568a77e4914aad9ab8c9f7fea47f7677c01880b3e85d2d0e3fbd6dc6e99e437ddc736f92b5a2ff2927e0b442142f0897d0b8a19ac203633df413feaf8ef50a5f767bedaf20f1c13f3b89d1e8b7bd18d591f9de116ee34f9824e4ead1ae9da2e8caaef88b29516aa942de77a7467b6fb26a666f30648c715a2ee9f946743b543a4428e0dfd06178e7e93ec6f26e003e058bec14a4aa2e3b8de11295a764cab30b313fcc5743b2fb89962ddc5cdc6aa0d2e4a306e77af76a05a598923f628a85df1cc73ad3bc01c4b979bd7cb296590a88b0a41b445d50a08423e4ed80f1763c716b6c457d845dfaa68d12b0d03c55fde8ae6b2b92bc6322943dbe54c706bc8e5fcee70654b26f3bfd877f5f5339ac182d5417bd4c0735d825bf70e85eab8216edda632ae7e22b3e53d078a8b20b5a7e2385337cf92b3c16b023563e11cb5043b704d37eb5ed9e85fcdc95cf7a6eade40803175a008ef653ac6136f16129abae1137c5823400748a81256254d317cfc939e26ea0cef9f6548db42890c48beb0479103ba089e514118038b1b90943d716f7a8d4cda5983a674b83a002d8ac9c65734a28b77b760c8e3803f8781ea9199f797ce729e06bfffe8c29b20bc85227c09cc05219ff2ba38e18051083732f83cbfccc310756450b261d5be183d9fb44ec18529f2cc9848c40119c607676bc4d9015fd4bd2fc918dc8031ec19a05ff362c184043be7fe066019ac5: +eac0f06c2c14f37d434bc99897225dd2e3f1ed74aa7442c550339df77d0b7b3243e62055db6e1349c94d89029187882020cbcf9d75e03eb656fa0a15b19002d7:43e62055db6e1349c94d89029187882020cbcf9d75e03eb656fa0a15b19002d7:27b7fd0e71adf194cf5407b6771793060de0fca7ca0ae64835c43187408a704f533d5ea0c83a654387ba7db16ed58ec837226df57c1fe6382c5919e92213f6f18cbb5735d178a476af35d390b7cd2556217c530f3a1f8ab2339c1a5e8d969387efd39414b56bb784dfd5eb89b859e1f403a238eca2a941e6db56ac456b73450698d1455ec1e9b39a1e907d6bc7e6cff424a28eed579af16310115b67f5fcf7f8346b3fa0260c6da2e27755aca570babb3d303cc832460c963bfdd5c1ffb2fc19921929dda2a717fbcbeb2b8525761bd660ce4a0f7685285d7fad6115ab09f8e63f5f773914494e20be1b512d1114cce3f0f68c7d94f54857694f22af4c698d782ce837b0c1722bb7313bb2c41f6d3dd1a02877fb4296d8662a9e8625984dc1fd1a9510eba9d643ac58a886a045cd0e53c056a833f968b35d01320e9cc0b435d3f6bfad26f9eb5754d38ddf6d5c4bf615a7644a23f9826bcc976092d82d81d547000de0081b7a40a93fbddac13f7d99708ccdeeb9405cd634ca0748cad2c1d8f164f5d77a4f364ae488bedcf1f20eb954bc8a278af81432417856a900f8f152921afbe17914229a513bd71ab7e661cde129af93e25094c56118ed1f22db644428b474651fe36be82fa3695c41fc8699667e053743b0a41155c31f1e2679c6e8cb9c9d1f5f4b40a320a9fd9f47da9b94211ba601b22a115210d9f559c4496f01732458f49ac34eb386636c8b6c68c7bbc0078ab6f398a624b8bafb1c622958562d231dffd4db096196bb87479e42ea22acbdcde8deb10e311632f02fca14787fd3140569b9428991543ec6e834e10b149f23c74bb99ac7b3799a2096d22e387a712b6f9011ea34c5be4c468581ac62ce662063252e066a9a3b15c9570d065dc1619929f06bc75a3179468bc8a16e3ddc4fe185ceba0a92a546b8675fc1ade56307150c7e4c844f6aa5f1edbfb54ac632ca2b259c32a33ee2867856c3390a6740364cb0dfb976e53d0cc6c42a106a1c26918c8a6a033b2aa3c7f2e4392e79f8eca5b336bac5061d7698a3bfe7c2c292892554030de6ce7c0d06eefc54906f81e0097fcff27d14b9b7994a7970e1a5f5c6b6405dca22033dff0eae138ad899f6ee68120b8f22744b0269a9a8989b6f7e08affae77bca2168ade24058ae68a7f800e02e7c38391baf565dd40b55fa3ab3c247b9ceb4d967471775e663d6a1c6c7e17350bbd6b9a3eb1e484ac2e7a7a5c84f5083e5ace8730de89c47e8dcf8341e40ba345dbd66bae0f7f076a705b1bb7f470e3edfb2b78e4d6359413d18d33280b454a0dbb881d8606726fa9bea272475e79fea6a54cb4c0619541b4e77c170c8616874b954beb8d105b86bd1917e25cfba9267187ee2038b3f0078f4c318b587cf44:45f2803afeb0fc44d3aa965b12659bf502e47295706184b2a1c6f16d050613f596a2001394e00e2a44c46cf6505d5cf5b8ab8412f07eda951a15005e338f3c0e27b7fd0e71adf194cf5407b6771793060de0fca7ca0ae64835c43187408a704f533d5ea0c83a654387ba7db16ed58ec837226df57c1fe6382c5919e92213f6f18cbb5735d178a476af35d390b7cd2556217c530f3a1f8ab2339c1a5e8d969387efd39414b56bb784dfd5eb89b859e1f403a238eca2a941e6db56ac456b73450698d1455ec1e9b39a1e907d6bc7e6cff424a28eed579af16310115b67f5fcf7f8346b3fa0260c6da2e27755aca570babb3d303cc832460c963bfdd5c1ffb2fc19921929dda2a717fbcbeb2b8525761bd660ce4a0f7685285d7fad6115ab09f8e63f5f773914494e20be1b512d1114cce3f0f68c7d94f54857694f22af4c698d782ce837b0c1722bb7313bb2c41f6d3dd1a02877fb4296d8662a9e8625984dc1fd1a9510eba9d643ac58a886a045cd0e53c056a833f968b35d01320e9cc0b435d3f6bfad26f9eb5754d38ddf6d5c4bf615a7644a23f9826bcc976092d82d81d547000de0081b7a40a93fbddac13f7d99708ccdeeb9405cd634ca0748cad2c1d8f164f5d77a4f364ae488bedcf1f20eb954bc8a278af81432417856a900f8f152921afbe17914229a513bd71ab7e661cde129af93e25094c56118ed1f22db644428b474651fe36be82fa3695c41fc8699667e053743b0a41155c31f1e2679c6e8cb9c9d1f5f4b40a320a9fd9f47da9b94211ba601b22a115210d9f559c4496f01732458f49ac34eb386636c8b6c68c7bbc0078ab6f398a624b8bafb1c622958562d231dffd4db096196bb87479e42ea22acbdcde8deb10e311632f02fca14787fd3140569b9428991543ec6e834e10b149f23c74bb99ac7b3799a2096d22e387a712b6f9011ea34c5be4c468581ac62ce662063252e066a9a3b15c9570d065dc1619929f06bc75a3179468bc8a16e3ddc4fe185ceba0a92a546b8675fc1ade56307150c7e4c844f6aa5f1edbfb54ac632ca2b259c32a33ee2867856c3390a6740364cb0dfb976e53d0cc6c42a106a1c26918c8a6a033b2aa3c7f2e4392e79f8eca5b336bac5061d7698a3bfe7c2c292892554030de6ce7c0d06eefc54906f81e0097fcff27d14b9b7994a7970e1a5f5c6b6405dca22033dff0eae138ad899f6ee68120b8f22744b0269a9a8989b6f7e08affae77bca2168ade24058ae68a7f800e02e7c38391baf565dd40b55fa3ab3c247b9ceb4d967471775e663d6a1c6c7e17350bbd6b9a3eb1e484ac2e7a7a5c84f5083e5ace8730de89c47e8dcf8341e40ba345dbd66bae0f7f076a705b1bb7f470e3edfb2b78e4d6359413d18d33280b454a0dbb881d8606726fa9bea272475e79fea6a54cb4c0619541b4e77c170c8616874b954beb8d105b86bd1917e25cfba9267187ee2038b3f0078f4c318b587cf44: +e608d5de9797907db6d98e0345d5caf2ad33e0eddebf18b81d61e8373ecfb49960e0c16ada586e3646912a5f2bb318fbc3d50b57d36fabb637696f9d8d4dc761:60e0c16ada586e3646912a5f2bb318fbc3d50b57d36fabb637696f9d8d4dc761:e610fa7d8385c09c78989ed5ef7a230547f013cb7e8ddf31749ffc31cee10ab3efaca3f14ea194510f0985a818ef8b040e10c3a5114de1ac080f14c3d65d3c244f9242f75492cabae800fcfc9bc275ea1f27728c920c258fe7aa73948060299cb87835792edcc072150b73cefeb0d51562e53b46810e27a4d7f6abd32e959f7d731dde01d94bc41ed835efcd42c922437037a87dd366ffad2eecab6abaeb4fcf07392b3ab40cfaefeaa4266bc537671693c9093dabe8a0538cafd12c639a04bd2ba80ce0f29adbfc66bd4637ca0543a53b0e371d0e2e470d31ba360642a45ab4cfe3e790f587f6c5a5583fd15b18997838a200921c1c399c0b16278b7dd6d3aaab6f325b16afdf761a1bbf867de2bdd48615f15b526770ed20d79f0f30714beeeda58f52a3cc0c5a618315e522b9ebe7cd99b65ed532a62e0f0df72764d6ec6d6d1ba40ef40e05426360795d6dd85bb39f7321d3fb06275de096aae4a2fa2293f31b33f4ad4d7c251ac13e8e15c2bfb1f98f4962c54b6ce033b08aa626f2905d463f55b71cbdadecdb3e0b365dae07b170301983aeb83b1e9f2f28cf65419fd6b0a1a9c26cb54b5949f4bc01a98681844b43034c372a453d38f0473d0ddc709d9f49c8753a75b856c7e9775517df574a09a3953bde5daedf8e4a8da9d773a215120e269fa1861133cd4ceaeb91d5cca2606325458e50cb966d14055b22447eb65dc10118da0831df28c3b4ee8b11f0732f1521bb9482b11f5a86b22f18e83dd1d967d3944285e5d63a5a989817ab2418bc7ed891a373846747a12b527c2f44ee0197b946c67e67fa4aa1c29f3379d46fe07d3aab83da17f9d76bedd38436a055e34ca1d3af5a8754d38c17b9ba4e6419cbab515f431a2595954e428c2670fae3bed62b4596179cb59e21108708d071bcf9c621c6dff03d3cdc9202029454013b9d133847f26544811c0169770fdc6fe5638bfd7a720d8b38f7e30a7e6879060b5f28c8ab17b00200713207e8637bff4844d842d9ca788391340198a3fe0172dfa74de1e55adefbc2e9bc7e885476d1b9c055813408a47528434355bf03fdd4e27d8b3461b0fb66ab3e15a879a184457e9ed9ea6c51b663b31edc8c4a3cd454f69d9ce518d1b87888ee3d9dd5416e43e114ac05721352dffc2ca88597377bbc414009b0c2fd369be5ba35a6dce3478b6c11b33c0a33918b6ee5ac4cd4c2f1ca6bd190a000a838da38f53077560335596d1358937793963810a79a21b8d46140e768898dcda88a0faf8ddd0d633847aaea0e030be6455b41e3ede1e2873730eb8481acaa7a519cf9195847a86afa57f9071d44f4af4ca0d343c90c0d22d946146585f00ef3aef57f0f9e55e818c0128ae255dbc3116cf0fe02166d54859decbfdccc:0d8f095e42a2730a3c7bedf42d5c83398b5c0ee9c77c5a61d982291396a9182a0802a37f324bc4fb5d4aa4ed60444b66144bacbc865105d7690f140650691d03e610fa7d8385c09c78989ed5ef7a230547f013cb7e8ddf31749ffc31cee10ab3efaca3f14ea194510f0985a818ef8b040e10c3a5114de1ac080f14c3d65d3c244f9242f75492cabae800fcfc9bc275ea1f27728c920c258fe7aa73948060299cb87835792edcc072150b73cefeb0d51562e53b46810e27a4d7f6abd32e959f7d731dde01d94bc41ed835efcd42c922437037a87dd366ffad2eecab6abaeb4fcf07392b3ab40cfaefeaa4266bc537671693c9093dabe8a0538cafd12c639a04bd2ba80ce0f29adbfc66bd4637ca0543a53b0e371d0e2e470d31ba360642a45ab4cfe3e790f587f6c5a5583fd15b18997838a200921c1c399c0b16278b7dd6d3aaab6f325b16afdf761a1bbf867de2bdd48615f15b526770ed20d79f0f30714beeeda58f52a3cc0c5a618315e522b9ebe7cd99b65ed532a62e0f0df72764d6ec6d6d1ba40ef40e05426360795d6dd85bb39f7321d3fb06275de096aae4a2fa2293f31b33f4ad4d7c251ac13e8e15c2bfb1f98f4962c54b6ce033b08aa626f2905d463f55b71cbdadecdb3e0b365dae07b170301983aeb83b1e9f2f28cf65419fd6b0a1a9c26cb54b5949f4bc01a98681844b43034c372a453d38f0473d0ddc709d9f49c8753a75b856c7e9775517df574a09a3953bde5daedf8e4a8da9d773a215120e269fa1861133cd4ceaeb91d5cca2606325458e50cb966d14055b22447eb65dc10118da0831df28c3b4ee8b11f0732f1521bb9482b11f5a86b22f18e83dd1d967d3944285e5d63a5a989817ab2418bc7ed891a373846747a12b527c2f44ee0197b946c67e67fa4aa1c29f3379d46fe07d3aab83da17f9d76bedd38436a055e34ca1d3af5a8754d38c17b9ba4e6419cbab515f431a2595954e428c2670fae3bed62b4596179cb59e21108708d071bcf9c621c6dff03d3cdc9202029454013b9d133847f26544811c0169770fdc6fe5638bfd7a720d8b38f7e30a7e6879060b5f28c8ab17b00200713207e8637bff4844d842d9ca788391340198a3fe0172dfa74de1e55adefbc2e9bc7e885476d1b9c055813408a47528434355bf03fdd4e27d8b3461b0fb66ab3e15a879a184457e9ed9ea6c51b663b31edc8c4a3cd454f69d9ce518d1b87888ee3d9dd5416e43e114ac05721352dffc2ca88597377bbc414009b0c2fd369be5ba35a6dce3478b6c11b33c0a33918b6ee5ac4cd4c2f1ca6bd190a000a838da38f53077560335596d1358937793963810a79a21b8d46140e768898dcda88a0faf8ddd0d633847aaea0e030be6455b41e3ede1e2873730eb8481acaa7a519cf9195847a86afa57f9071d44f4af4ca0d343c90c0d22d946146585f00ef3aef57f0f9e55e818c0128ae255dbc3116cf0fe02166d54859decbfdccc: +0e86872c78620f10cb6dfc463d2c2872c4da660748c9cda01ab1456958afba7fde4989989269cabd8f4f409cf1a4d974038b275502273557f312d5553fab93c3:de4989989269cabd8f4f409cf1a4d974038b275502273557f312d5553fab93c3:a900f3e9c643a5649b076fb69c3b2ac084d52ccbafcdca5a9db1daa70500de9933d23d153f74954e1bd5f57b899fe8a4b134c195412b49833b6e5095a6554eaa6d844b11f1584c85055b87f41c999669046c71aeb5c0453fd6a3c437f815f068987c3868cc07aa2af65819046c307bafb7530de84f7130aea78ef005d5fff52f8deaf1d5e9c326d3217fc55b94f628aa104f6a24a395e62d1b62bd9c0d82436319c5d73e5765435f3ba856a4734fd60ae617f7f0c3ba5722a73366c88a6dfeca85c444639f441f2c55fdc464ecb299eee36d8eae063bb94bb2439da04fa5ebc5092338a5035e480f0834aeee8d711f28c46dc960de1be9df307c18c5c178b26296dc567f15bf60863a36710867e92fd51048865674c2af0c53b2e7a248ae5bd09a49aa030618495f82480c420ae106889bec006278b92272075709fec95487cfb10061e6722b93eebfc0bc587bf7ba5f6692b074f55a98d5c302760b1bf1d09f7e8668479ca6f01eeda2fdaf584ac2058fbf7cf3100d06b8091bfeab51c0c0b1d4ee3a8257f69b1617604fce953bb5f7f271c6a1880ea1b3f66267e2439f34580628917877c66ec0fed76e44e8bb2b91a8806df4baca6cc92889b8805070c9a617f807157530751cc17c47b09eeba94d22b4e547c370ce7a496fcaa3412affffb8c9b4de89b9f121aaec5f544b0c725ec5ee9d4b3476adc9d050edb0fdbaf02ca9e38af15f515015a267292ec9aa5444ed1decd9cd9e1ead6487a0ccef995b1c600a036935838660acab276d8b0e5b07d9f36353214bf80f941ac88cf40a08af917926234112eccdaa162dc99de3e25baff65bb01e49898986332bdc2d705d5aea40f9bc4fbb2806894496038da236e9dc29600c9cedeac3b616cc56d89ec2fa67389666c6c4fe233b639105023e101b874a6330fe573f80ace55d037cc612e6dfd5a6e686f9a83054fc46e15bb6da453d810cf138a178bf039d1e181614ff40cbe6bb3b473663752ea8025ff7f739ee4b67110f968089b2473cd044d48b009d0677f791f54e2df6afdc3acb9e99dd6958a450c0e1b6dd5e97a2cc46298b4f48ac6adaf013d75b2c42072d2ee13f733687ee83c3f70c4fdd9720fd1798c662fef3ba012bedd445c4729f2130484fe77ac1b4c4ddeb81faf60f76e3bd7d21a9a6c57a69a9cd9cc203fc63b59ee84b8915b3c18a5954e227c86ebbb7d4c4c1a08d0c5e467c68a06970751ef584bdd611e1dd1b48900ab354b99cec6e1df3bd4146ea0755350dc11c3a3f600d470a74f475e4feedaf0865276fa8a97713471d0ca9955c713588339dee79656e567e6ab1dbf9830703817ae620929a0684a5caf20fef81a8ee897be7e505ade6496b9aef0272bd8f350860233b338c2e36d3138db69538:2037e97741c3e6409c66fc6782aab389c5d778097ac778999e8576e49ef4f6a0c7730bd9e093dd3c0ae7ec76203380da657147d33a8d9dd65ed00cf76224d601a900f3e9c643a5649b076fb69c3b2ac084d52ccbafcdca5a9db1daa70500de9933d23d153f74954e1bd5f57b899fe8a4b134c195412b49833b6e5095a6554eaa6d844b11f1584c85055b87f41c999669046c71aeb5c0453fd6a3c437f815f068987c3868cc07aa2af65819046c307bafb7530de84f7130aea78ef005d5fff52f8deaf1d5e9c326d3217fc55b94f628aa104f6a24a395e62d1b62bd9c0d82436319c5d73e5765435f3ba856a4734fd60ae617f7f0c3ba5722a73366c88a6dfeca85c444639f441f2c55fdc464ecb299eee36d8eae063bb94bb2439da04fa5ebc5092338a5035e480f0834aeee8d711f28c46dc960de1be9df307c18c5c178b26296dc567f15bf60863a36710867e92fd51048865674c2af0c53b2e7a248ae5bd09a49aa030618495f82480c420ae106889bec006278b92272075709fec95487cfb10061e6722b93eebfc0bc587bf7ba5f6692b074f55a98d5c302760b1bf1d09f7e8668479ca6f01eeda2fdaf584ac2058fbf7cf3100d06b8091bfeab51c0c0b1d4ee3a8257f69b1617604fce953bb5f7f271c6a1880ea1b3f66267e2439f34580628917877c66ec0fed76e44e8bb2b91a8806df4baca6cc92889b8805070c9a617f807157530751cc17c47b09eeba94d22b4e547c370ce7a496fcaa3412affffb8c9b4de89b9f121aaec5f544b0c725ec5ee9d4b3476adc9d050edb0fdbaf02ca9e38af15f515015a267292ec9aa5444ed1decd9cd9e1ead6487a0ccef995b1c600a036935838660acab276d8b0e5b07d9f36353214bf80f941ac88cf40a08af917926234112eccdaa162dc99de3e25baff65bb01e49898986332bdc2d705d5aea40f9bc4fbb2806894496038da236e9dc29600c9cedeac3b616cc56d89ec2fa67389666c6c4fe233b639105023e101b874a6330fe573f80ace55d037cc612e6dfd5a6e686f9a83054fc46e15bb6da453d810cf138a178bf039d1e181614ff40cbe6bb3b473663752ea8025ff7f739ee4b67110f968089b2473cd044d48b009d0677f791f54e2df6afdc3acb9e99dd6958a450c0e1b6dd5e97a2cc46298b4f48ac6adaf013d75b2c42072d2ee13f733687ee83c3f70c4fdd9720fd1798c662fef3ba012bedd445c4729f2130484fe77ac1b4c4ddeb81faf60f76e3bd7d21a9a6c57a69a9cd9cc203fc63b59ee84b8915b3c18a5954e227c86ebbb7d4c4c1a08d0c5e467c68a06970751ef584bdd611e1dd1b48900ab354b99cec6e1df3bd4146ea0755350dc11c3a3f600d470a74f475e4feedaf0865276fa8a97713471d0ca9955c713588339dee79656e567e6ab1dbf9830703817ae620929a0684a5caf20fef81a8ee897be7e505ade6496b9aef0272bd8f350860233b338c2e36d3138db69538: +520354d85a87d7c22ca6f784714410ec98bf6a65f803ef9379bdc804359b2349d8511ceac2fd661acbffb01ba2741cad889934de6392961bdec6fa46123b7f0f:d8511ceac2fd661acbffb01ba2741cad889934de6392961bdec6fa46123b7f0f:a1d4ad486ebb7c1a0acb8f117013e8e4746789c6244a56c9edfbf1ef37ac1309aaf51c9375fc12cacd6897a4479545f2bf390ab7c0c0e5c592f5506e9938378a11b636bf857029b968547aa506c4a0829a15fd3995fead4f860fd7c623c63e8695436eae55816414778347092f5f4d422bb1b5e5a06966241efec14f1e4fca06639114718c30ebcadd4c6d8abe7fe93b25d17173533954188b1ab03fcb7792cb635ce36e9bdbdde7a561c5f66920d910cb269c8c1c3f593265090072c48932e692a9c738c704897489a715c2b394d5a86f7036a4cac5dcb5b85cfa162156e0bc6bfe02fb4c38608cfb23c92b8b6a3cb46e487d60e0dc97aa2e33e3dada925e4e6612cc5af125e5aca45817a2fd6c3ff10b18938b44bd4dd20d7fccf7f26b40a66f48aaffc9a541e6d37138fc55469868e2d10365eff37fac360fab3dc55437ac2d8fea7474405fb3630f7963d2d45958f909d14830286ff152aa752f510ce980bd5754e3fa32c69924dd95d5c152a737a8fadcfd0a4560e0b114f8e8aaa618d438b9877111da1740ef817c441939ecec799ba16b1b171ca9b649b7d78fa052d1497a507688bede4900abc53a9648da5917035ceffe0da21c25c09b06d6185bdda2d778f7ede6153e3eaff495c9796d4d166d2d2ea418e4a4aa6e678faf0696e752a09e02eaade763070e088e9964919ff4aa4c82f8629a3d5c797c2a64594d206835da0bfa43ccd9ddfcdb6aac4d486e03c84122375939a5270bc1519e0707e51c3f46f1e5c566b33a245fa0c202838472363de9f0edde2e791d82293095f750bff545e6c34739dcc54db0a36ae2e2aa39b07cb4f6a9646240d2d31488f67815b29545d220be929e3339f8281a937e05a8c5c3887e06048ea7b18a48f8d91b1e3af5cab5ceda0ebd71bf54edec203d37165e4c9f9f80461cd29fcd99ddea439693941b5d53ff94379cf642571dd559a11f8f383d943f2255cf715800af776b1045bf19a9c9bb095155dfb646b65f4a280f2a97ef927ddabe24a2f971a8170dd42a089276825cb9148c015aae1e9dadf22c10e7548c59bf6b868b20e86c83a9e7343aec2754ee6225f9fdceaf8e51c40e955bda49c35ded38fa8bcc1e6c8fc9c2412e9104c5c2368b1f9923e010fa2ede911d42b139f4007e3426922ffb6158eca97b47cfc997853512bb9d4ca2f017c2c263dc199f3bf1eb4f1508ef828b0e00db21002736a7f22ec91298194583139ad75f58e21b518daa49a4076c6375faa60891a69e52a656699d8034a7ab7fcbe42175491441fe61b1783e837857522215a5fac5590bed2e9d206606096d3be8ee92873bfc30cab15ce9f9910d01a117f89926cc3afa8d104f799ff38098de28b8ff0f038725c2903b24c1429cea4925249d8781:754e60d3f6f4ab4f5d0ddbb001532009166388487f780b76f60bd0bc9fefabfaab6be2ae7869573a64796ef2846e85e5cdae52db1044fefa796bacf48b968b0da1d4ad486ebb7c1a0acb8f117013e8e4746789c6244a56c9edfbf1ef37ac1309aaf51c9375fc12cacd6897a4479545f2bf390ab7c0c0e5c592f5506e9938378a11b636bf857029b968547aa506c4a0829a15fd3995fead4f860fd7c623c63e8695436eae55816414778347092f5f4d422bb1b5e5a06966241efec14f1e4fca06639114718c30ebcadd4c6d8abe7fe93b25d17173533954188b1ab03fcb7792cb635ce36e9bdbdde7a561c5f66920d910cb269c8c1c3f593265090072c48932e692a9c738c704897489a715c2b394d5a86f7036a4cac5dcb5b85cfa162156e0bc6bfe02fb4c38608cfb23c92b8b6a3cb46e487d60e0dc97aa2e33e3dada925e4e6612cc5af125e5aca45817a2fd6c3ff10b18938b44bd4dd20d7fccf7f26b40a66f48aaffc9a541e6d37138fc55469868e2d10365eff37fac360fab3dc55437ac2d8fea7474405fb3630f7963d2d45958f909d14830286ff152aa752f510ce980bd5754e3fa32c69924dd95d5c152a737a8fadcfd0a4560e0b114f8e8aaa618d438b9877111da1740ef817c441939ecec799ba16b1b171ca9b649b7d78fa052d1497a507688bede4900abc53a9648da5917035ceffe0da21c25c09b06d6185bdda2d778f7ede6153e3eaff495c9796d4d166d2d2ea418e4a4aa6e678faf0696e752a09e02eaade763070e088e9964919ff4aa4c82f8629a3d5c797c2a64594d206835da0bfa43ccd9ddfcdb6aac4d486e03c84122375939a5270bc1519e0707e51c3f46f1e5c566b33a245fa0c202838472363de9f0edde2e791d82293095f750bff545e6c34739dcc54db0a36ae2e2aa39b07cb4f6a9646240d2d31488f67815b29545d220be929e3339f8281a937e05a8c5c3887e06048ea7b18a48f8d91b1e3af5cab5ceda0ebd71bf54edec203d37165e4c9f9f80461cd29fcd99ddea439693941b5d53ff94379cf642571dd559a11f8f383d943f2255cf715800af776b1045bf19a9c9bb095155dfb646b65f4a280f2a97ef927ddabe24a2f971a8170dd42a089276825cb9148c015aae1e9dadf22c10e7548c59bf6b868b20e86c83a9e7343aec2754ee6225f9fdceaf8e51c40e955bda49c35ded38fa8bcc1e6c8fc9c2412e9104c5c2368b1f9923e010fa2ede911d42b139f4007e3426922ffb6158eca97b47cfc997853512bb9d4ca2f017c2c263dc199f3bf1eb4f1508ef828b0e00db21002736a7f22ec91298194583139ad75f58e21b518daa49a4076c6375faa60891a69e52a656699d8034a7ab7fcbe42175491441fe61b1783e837857522215a5fac5590bed2e9d206606096d3be8ee92873bfc30cab15ce9f9910d01a117f89926cc3afa8d104f799ff38098de28b8ff0f038725c2903b24c1429cea4925249d8781: +061bcf1aa6fd989897b322e591ccef5454ef4a5adb1a4800f32611cff2b5bc7873c80b734bfc9417d576890c20166da5c7fabd613f75474f7649732e00295be2:73c80b734bfc9417d576890c20166da5c7fabd613f75474f7649732e00295be2:d63bb9208c1f4c7d43326cf35fa5d83933151804ab891d49b0bdaf429e4c39a321428e0d90aa00318b97e08c7024c912cf388879f3cf974bb253a1e7a4c8eec193bf4c14af6fb9794df0d497850edb04d574c97ed76c702139968401b40eb54394ef4cfaa7e5d3cd943af12192538ddee593c2a24a267afa1371fd77feee2071f4369fbef87976e7ebd81d1e5b31d6e09e02d830357d36bff8596703e4146d0827bec9c0f87b26f31195c96c93b6d8c46767ec1bc6de39f0008a41ff875da050a3f865ab92cbf29c38a280f3bf69f68e92b5f430cdee3501981d0b3d189096e0aeacd64c33102421348812158bb61e51ae936592b2f8f1b910949ef3723258a9b44e4e1bdadf1ae2cfc18e37d2ed0dd1734404b8baa5f393cd56069ecebf7edd7c06cf6c8aa3e8e12fbf946d7b32d8453b6fbb6535526c8fb8fc1d5815560bb31b995df2adbd836add929a56fdd93a1747d93a40c05e129eb6f8583c2921cc9dbdda4225e176db386a02ec40af1032c9b62e95147025f4ac8dd58433b64ac073150c69b9c4154dcbb00344f308113cd9199ccfb5075801c705b8fc43b7c8bc167365e46293d06c4f4835c64ee5d5383f6890ca35a80af917748162df2518ab1468f153629899406cde66ce07fa7d2993dabe0c60089c91892488f3bcaaec408a0cd08c9aa98e0937e02c41ad52d241a99833e3b83f7d3f1b078c31d45c34fa0175abbd0f322b8fd2dc83491da292ad00762e3e577b9eee0aae08729070ac25e33bc94525bc0d2ab59704efec5c0148421a47928d34b1e45ce721ee6447fb082ac400b3e6846d204f7f9db6f0a32b2a69738b3ee9ddbb0dbd7e0f041d7ea53a5d647fb50b39ae24d78c8b07cfc4e052711f0d4639e721d5c36f31b588866712b757108a40cc7abbb9913083303aae05a0f1af0ec6878441a25cf8729aba42a3a94ce9b73888a0f5c9e40c9fc45410f0681fa7f90898562ccb4bbc55f0ab1fe9c70ea66026dda8d7090f7b38edb5aec1557b1166987cd41a7059cdee609b74d8fe06b7059b7724bff53007f7e110462f06ad14d07ee1b4d69ac823bcf576d2fa9e2e8ed7f3198040d471296063137c981adbf364cb20f0a1ad2054472f7cee2527f99809615d2e4b734b06f35deecbd62619663dde81d6e23528b0c97132af0a23bad63d9c08142a26e2743f8618ecfe723b19ffdd0b19abd9a3f4fe210b1e71acdfe38abebe23f7fdef66381cbc75f307e5577235b02e4cd9cfaa15030868ed1453da58f783b7352b04656844c042441efe6a3b4f8fec8f7de80744540c4fc7a107f4e1bfcbd99da25b9746095ddf0125d56da7e7f8603f04d359a088b4c044f936ccb7d8f89ed53cc991a3497ca952094ff3c33046f2609d07b29b633981369cb2f0eecd:5adaa94330a0353712a34dbe973b7518f9a2c713f8aad100251b086ae8de26f6d2b6ccf0528cc5dedca318df19cc7e45deae281e1324b96e32fef45aaf60b10cd63bb9208c1f4c7d43326cf35fa5d83933151804ab891d49b0bdaf429e4c39a321428e0d90aa00318b97e08c7024c912cf388879f3cf974bb253a1e7a4c8eec193bf4c14af6fb9794df0d497850edb04d574c97ed76c702139968401b40eb54394ef4cfaa7e5d3cd943af12192538ddee593c2a24a267afa1371fd77feee2071f4369fbef87976e7ebd81d1e5b31d6e09e02d830357d36bff8596703e4146d0827bec9c0f87b26f31195c96c93b6d8c46767ec1bc6de39f0008a41ff875da050a3f865ab92cbf29c38a280f3bf69f68e92b5f430cdee3501981d0b3d189096e0aeacd64c33102421348812158bb61e51ae936592b2f8f1b910949ef3723258a9b44e4e1bdadf1ae2cfc18e37d2ed0dd1734404b8baa5f393cd56069ecebf7edd7c06cf6c8aa3e8e12fbf946d7b32d8453b6fbb6535526c8fb8fc1d5815560bb31b995df2adbd836add929a56fdd93a1747d93a40c05e129eb6f8583c2921cc9dbdda4225e176db386a02ec40af1032c9b62e95147025f4ac8dd58433b64ac073150c69b9c4154dcbb00344f308113cd9199ccfb5075801c705b8fc43b7c8bc167365e46293d06c4f4835c64ee5d5383f6890ca35a80af917748162df2518ab1468f153629899406cde66ce07fa7d2993dabe0c60089c91892488f3bcaaec408a0cd08c9aa98e0937e02c41ad52d241a99833e3b83f7d3f1b078c31d45c34fa0175abbd0f322b8fd2dc83491da292ad00762e3e577b9eee0aae08729070ac25e33bc94525bc0d2ab59704efec5c0148421a47928d34b1e45ce721ee6447fb082ac400b3e6846d204f7f9db6f0a32b2a69738b3ee9ddbb0dbd7e0f041d7ea53a5d647fb50b39ae24d78c8b07cfc4e052711f0d4639e721d5c36f31b588866712b757108a40cc7abbb9913083303aae05a0f1af0ec6878441a25cf8729aba42a3a94ce9b73888a0f5c9e40c9fc45410f0681fa7f90898562ccb4bbc55f0ab1fe9c70ea66026dda8d7090f7b38edb5aec1557b1166987cd41a7059cdee609b74d8fe06b7059b7724bff53007f7e110462f06ad14d07ee1b4d69ac823bcf576d2fa9e2e8ed7f3198040d471296063137c981adbf364cb20f0a1ad2054472f7cee2527f99809615d2e4b734b06f35deecbd62619663dde81d6e23528b0c97132af0a23bad63d9c08142a26e2743f8618ecfe723b19ffdd0b19abd9a3f4fe210b1e71acdfe38abebe23f7fdef66381cbc75f307e5577235b02e4cd9cfaa15030868ed1453da58f783b7352b04656844c042441efe6a3b4f8fec8f7de80744540c4fc7a107f4e1bfcbd99da25b9746095ddf0125d56da7e7f8603f04d359a088b4c044f936ccb7d8f89ed53cc991a3497ca952094ff3c33046f2609d07b29b633981369cb2f0eecd: +2e19cd442f22a4a99dffc55e7bf625f89d1344b563f6785313a7eee973b4aa36ee3da76a8fcf403a2958d4551da0a72b2e738522b2e6b20fba6aa26b32307357:ee3da76a8fcf403a2958d4551da0a72b2e738522b2e6b20fba6aa26b32307357:1bfc5c6aa6a5354fbb861469796348ac6319124da3f10d20d50bbdc7159d41b5abb136c7996a773797122b525e8e2dca1954f6391707301d90f2101b46c7b086efa15877cadcd05812db34b996cb4f531abcd1e98db08a5cf1368e8f4b1109142e9562bd0085ffae5e660f59c930793ebdb6e80b0a2f4f3f59bf9d395c48d26e0a72a60f9d1ff87fd2d7a3f5383aa902adededebc6cd1befd038336162749d91a957ca2e3dd47091c5593113da87c3d66a02c80a6eddb535c48ca1f34a97fd1c95ebc2e570fc8fafe6e5d6546d1f3a9ba8daac334cf47bf117e1280d0ebdf14b0fcdbb43b8d248cc6b61320fdb0449ed5f5de8bab121af0d8554956e6a12016b42677b44367892c3b20afcc2cb9cfb5b100a95b51e8b07da9f51415f4cd7781a313765e20db27f2343e0f719ecea9af026956f3387e9ea7ed0a293759b4a262202807b41309fb80f50185db6a5f8bdca178841bec06addc7610df76017b514bc4142f26a36bf5bacecb012fa41710dd849bef7a7e451432836fe9b3265fd5b59ee40b04dad85cf48f891465a842cd4500a1024eefdf0f554f0ca17ec9f7b715256a9b9dbe27966386d8ac37d3c515896de0f7cdf7cf5b320ff7a8ef6b34ba820aba9066dd253c5b7763777f94b2d6ad8c710221e1137535dff8a1b7565ec81bd8ddeb502e3d58ff8f1fe6e86b8dc15a3aaec688bbbecd4688281db0f818de0f7261ba9cc58c8bc0d02e06632efe7287ad7a84331a824d9287344efaaa74f1fc576d0269430f856a8565265b9d6ef71fe134d2510ab06b60bf3c153b57ecfd2e6342403fe678b5886b6b734b7d3690662b6c8c6f6e250e5af6a8183166ddcd0a17f0cddc8636ef1a68498be50b6599539d46b4cea97130e08f94ca53e884644eda75d23cd2c038a5f17b591e21369378cd3fb5762d1a7c3e66a11ae6e91cbae616ad055e39dc41e154f4fced7b2696d9dc67380bb8eef474e9aa83cec47fafafb941d626564b2075bcc0856da8d6e1b0b8f18baf7513bbd14e491ed517968c4f7241af25098ee8df130b7a34d59736d7836d323fe3f43f508cdcb755895f59a00c804ed164cc33992f3aee962ae9e990b74272eb987b12d90b27314d57400e737d1343e970985c4271060876abcd7049e7c9fe244ff3ef98560995b7482d31bc7c09d9969f7cd41f4e4e252750dc16ccdb29b985314a0b6e749c95f9bd2838d5ac49ee031fd079bec3028dd9dd07db6fa622ad621b3b1e127e8fca37bd146e3cf703e911701b7a16c2d30369c94648ecc03df10d7dd5c0558fa9593425d948727d6860c3a14f811245106616d2a5fa981c6b7f47ec9def65412d132acc6919da4e88597aa9190ca614b218066a0f7b16997ee747c5a09785e50d0a891d95937863d613ceff7:28326b5b978e0dbdab5dde703785a667a7ef439d81ea47e066b089d116c25a34bb633f260d55f45bdf6bcda74803d7624b1927cec18eb1992260beefc399d90e1bfc5c6aa6a5354fbb861469796348ac6319124da3f10d20d50bbdc7159d41b5abb136c7996a773797122b525e8e2dca1954f6391707301d90f2101b46c7b086efa15877cadcd05812db34b996cb4f531abcd1e98db08a5cf1368e8f4b1109142e9562bd0085ffae5e660f59c930793ebdb6e80b0a2f4f3f59bf9d395c48d26e0a72a60f9d1ff87fd2d7a3f5383aa902adededebc6cd1befd038336162749d91a957ca2e3dd47091c5593113da87c3d66a02c80a6eddb535c48ca1f34a97fd1c95ebc2e570fc8fafe6e5d6546d1f3a9ba8daac334cf47bf117e1280d0ebdf14b0fcdbb43b8d248cc6b61320fdb0449ed5f5de8bab121af0d8554956e6a12016b42677b44367892c3b20afcc2cb9cfb5b100a95b51e8b07da9f51415f4cd7781a313765e20db27f2343e0f719ecea9af026956f3387e9ea7ed0a293759b4a262202807b41309fb80f50185db6a5f8bdca178841bec06addc7610df76017b514bc4142f26a36bf5bacecb012fa41710dd849bef7a7e451432836fe9b3265fd5b59ee40b04dad85cf48f891465a842cd4500a1024eefdf0f554f0ca17ec9f7b715256a9b9dbe27966386d8ac37d3c515896de0f7cdf7cf5b320ff7a8ef6b34ba820aba9066dd253c5b7763777f94b2d6ad8c710221e1137535dff8a1b7565ec81bd8ddeb502e3d58ff8f1fe6e86b8dc15a3aaec688bbbecd4688281db0f818de0f7261ba9cc58c8bc0d02e06632efe7287ad7a84331a824d9287344efaaa74f1fc576d0269430f856a8565265b9d6ef71fe134d2510ab06b60bf3c153b57ecfd2e6342403fe678b5886b6b734b7d3690662b6c8c6f6e250e5af6a8183166ddcd0a17f0cddc8636ef1a68498be50b6599539d46b4cea97130e08f94ca53e884644eda75d23cd2c038a5f17b591e21369378cd3fb5762d1a7c3e66a11ae6e91cbae616ad055e39dc41e154f4fced7b2696d9dc67380bb8eef474e9aa83cec47fafafb941d626564b2075bcc0856da8d6e1b0b8f18baf7513bbd14e491ed517968c4f7241af25098ee8df130b7a34d59736d7836d323fe3f43f508cdcb755895f59a00c804ed164cc33992f3aee962ae9e990b74272eb987b12d90b27314d57400e737d1343e970985c4271060876abcd7049e7c9fe244ff3ef98560995b7482d31bc7c09d9969f7cd41f4e4e252750dc16ccdb29b985314a0b6e749c95f9bd2838d5ac49ee031fd079bec3028dd9dd07db6fa622ad621b3b1e127e8fca37bd146e3cf703e911701b7a16c2d30369c94648ecc03df10d7dd5c0558fa9593425d948727d6860c3a14f811245106616d2a5fa981c6b7f47ec9def65412d132acc6919da4e88597aa9190ca614b218066a0f7b16997ee747c5a09785e50d0a891d95937863d613ceff7: +82109099d1eafeed5a85206046491b34d06dcde33f080960287b10fb23ff9f78081cfdf2d758654c41c447e1e6273810f8a738a733afc42294a2b1bbb769efce:081cfdf2d758654c41c447e1e6273810f8a738a733afc42294a2b1bbb769efce:84f47dd794977a6c1505ac8c05680c5615a2d5b057e39b04f85e3f9ff04960e0e016685a86eebcecf6fbce5fddcdac1a474c8a0d502c40e10f948646fdac6c81f1ffbb177a2a4963b67825903cde65b5dbe0d8941d546cffa2bf8a8ca8d6c6408530a6290f5d0882f1a1672dbf978e10c5c8af5e0a6239f0655ee7fd9e66963077a0e847137397d1f06999dc6f8a945c6003ea4ea7fd58378acb44ed5780eaa367796beea37ddc236999d012d6a716d7915649cc28e58875647e9f5ac0553c0f544df56469c67081d5e30395f3e960e6a52f0833192c548cd57c926b82db48c361bde70333a370083eaaa068dc2ae452d21ef1331aed190bd3e1289a104cf667834377cf7b5a29774807c3f1ea9e7b28831d0f6c4294785867b137b65028c14f932a1ba8e6f9f59624fe0c396843ea19e46fba09142cf9d42497312f360244032f1e00f38dd0de29f963b5ccc1ef12b2cc6204b994af1f3baf196d9e21e8fa4f097320c64404d0b7d5ab38560ca0655364b0b09cd6dc0f0e05b8c9110364f1424a9672b7efdf7e1f378e234550566dbe13b01578b04153e9c37b553e32a4441bc97e2953bec2e41455510f9802ef948dcbf13faddd722ede573627b258d55e83c0895b22919e4be5ce8d819ce6ad843b2dd09df64004c826c1dde7ce6480a271a858a1db169e1494d4469032bcc1ccd89653198b7c073f76a26a2999b5648cbadc1574c78ead8eece83b91e129c437f9eeec04c807459002e66dcca9bfc2caed9e6c0ba23d2355def75665749430ee92c532a695479fec929174f440ecb61a5ae8b2b7e958920558268978f7fb4da1b38b12014f5d61b0fdd7f6136ba4281b41a3a3cd188052b698765b6f05e41e78373ea830469787a37510993d12f93e96c72d72f4461984f691a41c7d3397ddd5a1b39237d1308864d415fc6c22b63f376cedde37f5252b51ec72e5155f3bdb4fcd5412498bd2e0c1f9850b3a85d1dfd25167a3cd771e8e4c9d868c95a7175e3775f6cef17e4e36497ce9e45532bd7f44b2776e40f91a07ca4fa1b95dbe81cf8f49e46b6c82a6ee4347918a7643b0d9a38857212c693eadacfd37a5f1d91558f5454dcdd05935f290e62d7e65006cd549f6553ce741df44d39644001eb479ca69568ad1f23bba099a41a47294db938731c530af1ceb9217d29bc2705613c1a1fe9c208d0b01ba6f4d9b4c7ba8f021df91ea2d578ce083123e83ba4b9c50407f6666fbe61158b0d1b9577772e3eaff8fb429d0f6d2e384126130f21b449fb1dc170db45af505bd3182678a9b5f9fdff65f0413b672c4786340fcf2522ea7f3d8ade8a059529649dbda9ce51ff05a2a2a3d66d2166bf2c9c6772ba0ef4105e68c055e0213d42c1ee123b3c1217843e6ec575d754df3c90a75:b3987f324bc7e776c0f287fa13ad28741695e2e7bce8d143e29fad5d00994758e225fb802100d23fd6ccafee8e0a95bc479be8c23a11319745765b7cd47e700684f47dd794977a6c1505ac8c05680c5615a2d5b057e39b04f85e3f9ff04960e0e016685a86eebcecf6fbce5fddcdac1a474c8a0d502c40e10f948646fdac6c81f1ffbb177a2a4963b67825903cde65b5dbe0d8941d546cffa2bf8a8ca8d6c6408530a6290f5d0882f1a1672dbf978e10c5c8af5e0a6239f0655ee7fd9e66963077a0e847137397d1f06999dc6f8a945c6003ea4ea7fd58378acb44ed5780eaa367796beea37ddc236999d012d6a716d7915649cc28e58875647e9f5ac0553c0f544df56469c67081d5e30395f3e960e6a52f0833192c548cd57c926b82db48c361bde70333a370083eaaa068dc2ae452d21ef1331aed190bd3e1289a104cf667834377cf7b5a29774807c3f1ea9e7b28831d0f6c4294785867b137b65028c14f932a1ba8e6f9f59624fe0c396843ea19e46fba09142cf9d42497312f360244032f1e00f38dd0de29f963b5ccc1ef12b2cc6204b994af1f3baf196d9e21e8fa4f097320c64404d0b7d5ab38560ca0655364b0b09cd6dc0f0e05b8c9110364f1424a9672b7efdf7e1f378e234550566dbe13b01578b04153e9c37b553e32a4441bc97e2953bec2e41455510f9802ef948dcbf13faddd722ede573627b258d55e83c0895b22919e4be5ce8d819ce6ad843b2dd09df64004c826c1dde7ce6480a271a858a1db169e1494d4469032bcc1ccd89653198b7c073f76a26a2999b5648cbadc1574c78ead8eece83b91e129c437f9eeec04c807459002e66dcca9bfc2caed9e6c0ba23d2355def75665749430ee92c532a695479fec929174f440ecb61a5ae8b2b7e958920558268978f7fb4da1b38b12014f5d61b0fdd7f6136ba4281b41a3a3cd188052b698765b6f05e41e78373ea830469787a37510993d12f93e96c72d72f4461984f691a41c7d3397ddd5a1b39237d1308864d415fc6c22b63f376cedde37f5252b51ec72e5155f3bdb4fcd5412498bd2e0c1f9850b3a85d1dfd25167a3cd771e8e4c9d868c95a7175e3775f6cef17e4e36497ce9e45532bd7f44b2776e40f91a07ca4fa1b95dbe81cf8f49e46b6c82a6ee4347918a7643b0d9a38857212c693eadacfd37a5f1d91558f5454dcdd05935f290e62d7e65006cd549f6553ce741df44d39644001eb479ca69568ad1f23bba099a41a47294db938731c530af1ceb9217d29bc2705613c1a1fe9c208d0b01ba6f4d9b4c7ba8f021df91ea2d578ce083123e83ba4b9c50407f6666fbe61158b0d1b9577772e3eaff8fb429d0f6d2e384126130f21b449fb1dc170db45af505bd3182678a9b5f9fdff65f0413b672c4786340fcf2522ea7f3d8ade8a059529649dbda9ce51ff05a2a2a3d66d2166bf2c9c6772ba0ef4105e68c055e0213d42c1ee123b3c1217843e6ec575d754df3c90a75: +65fcbd626d002111334baad4e6a8006e47a1f91397bee6dd6cd7da5a0e0248a420409a146b42c96beab0b42ea7f2c25193119d0df44dc2bf14d11a32fd733615:20409a146b42c96beab0b42ea7f2c25193119d0df44dc2bf14d11a32fd733615:e4c0947fc8ca78fa8863f4d044499d036e2e7ef8c17e838f2fac02675b7b5381e5f9abceafd0d8886a929d9d9b49fcb73861b29d1518ac5f83f7f8fc26bd1cebc22d873a9a08231406fb032e4866e5f55c7c0441c519041bb2cc73f9226dd5d07eceb660d6c967db23365574bee8fc10222928767713571a71c93a85278d42299a70599ca99326cc86f6d98daac000fdfa710562f481faa020c72a76e2067d154c235a7a4f29708cc544533bd799ed6363eb3b56aa4a6d0e379bbf07600595c23ab1f3f9f1708e0070261bbbf4bfeaf6d6ced4d7ff722c9cc52d9133ea68d495dc9489c3edf6830231351f65cb5272f5396e2c4a1a5c88661a101892249e23d6ce9fdb6a9abf74272c2f59c3d8fd8743cce461126ca0a8b832b4b218336b1ae14da677ba7f1b2cc5ca3c7158f727a9e1b8fdd9edf5c2187fcb83db862ad0c6b39216de3116919556465100ade0a42bd6ba10d95418b69a3e005e9f104589ea5948b2b51bc7b1a9a0749da8f013781bc05c805bb51e187761ac24c76414f668eb45fb0a5024dfe5a5ca06f0403a02e3b2fef7a2c4bcfb1d075d310d5197e659cd14023faec20e045cabcb86b221a1d4827113ff3267a64debe9939004cabac85e5c7461e7e82a975acfae0b6c516a1c605374cfea7d819044efd6d74654424fd5c90ff2574fcd8e007740d975861d0df5259fe43e43639e36e52895439ba2c27c1e889c93094104fe914921bd6f25d3985ab1f22ca557b0e49afc7375243c521c6d5fafe0381ccea828e88e647fd90976b3fbec19fe9adb113c6404bd352bfc000446d21005b5f950ae07e51c768ca3ff6177b2eac50f10dd2e64610fa8ab5788faeee29d129009d7fe46aa3da6b9d86c73065eb5161fbdbdfac5777c4e75452e6e16ae9fd66bb7d9aaa426bcb7a6915f0ff44a1f8ec71394e9352fdf20e02fafe1e0cefe50744c3194956f928f82533755373838dcc1296a891adf641c7382d69b4f5a43d4af7772a4a1ee879292d7a4f32ac35ee121c6c34ca5f98487a941fcb1e65b44d4456127eedb2fcc1c3f48eff9300981e52ac38b496ab8bbce144a85eb9c07638b31fdaa781744bce17e8d93dcdc60afeda488807617f88d6aa54422fd347ddaddeff37a563dbf19974b2a23be300fbfa6c7fc41f84c6905415269f195990b5b4de12668c71c87b504f41124bf94436f333045631518152c5162a2475c40efb6cbdaaf9af428fed325b3a7d94c17520fd89e00ddf08b22adf661f0acd723b3969dc6434ea6f92ef58e8dfae5b0cc2885ba987ea1d16c39b34ef65023009d6345e48e3691a41f02a77b7fe133ea9de7565f157a2078ae988bbb266d22d5fa91a7b263e98ad2dc0731fe5a29025a0cb436864a5a60db257f1e76b5c608f25cdecc87eae6:bc78e16ba674e0a7dba57a19094f9733c55d74b9d15f8a44d1bbc0a023f70155de2977111a417eefa8cb30ec12abc8384228167c70982a8206b1ffb72174af01e4c0947fc8ca78fa8863f4d044499d036e2e7ef8c17e838f2fac02675b7b5381e5f9abceafd0d8886a929d9d9b49fcb73861b29d1518ac5f83f7f8fc26bd1cebc22d873a9a08231406fb032e4866e5f55c7c0441c519041bb2cc73f9226dd5d07eceb660d6c967db23365574bee8fc10222928767713571a71c93a85278d42299a70599ca99326cc86f6d98daac000fdfa710562f481faa020c72a76e2067d154c235a7a4f29708cc544533bd799ed6363eb3b56aa4a6d0e379bbf07600595c23ab1f3f9f1708e0070261bbbf4bfeaf6d6ced4d7ff722c9cc52d9133ea68d495dc9489c3edf6830231351f65cb5272f5396e2c4a1a5c88661a101892249e23d6ce9fdb6a9abf74272c2f59c3d8fd8743cce461126ca0a8b832b4b218336b1ae14da677ba7f1b2cc5ca3c7158f727a9e1b8fdd9edf5c2187fcb83db862ad0c6b39216de3116919556465100ade0a42bd6ba10d95418b69a3e005e9f104589ea5948b2b51bc7b1a9a0749da8f013781bc05c805bb51e187761ac24c76414f668eb45fb0a5024dfe5a5ca06f0403a02e3b2fef7a2c4bcfb1d075d310d5197e659cd14023faec20e045cabcb86b221a1d4827113ff3267a64debe9939004cabac85e5c7461e7e82a975acfae0b6c516a1c605374cfea7d819044efd6d74654424fd5c90ff2574fcd8e007740d975861d0df5259fe43e43639e36e52895439ba2c27c1e889c93094104fe914921bd6f25d3985ab1f22ca557b0e49afc7375243c521c6d5fafe0381ccea828e88e647fd90976b3fbec19fe9adb113c6404bd352bfc000446d21005b5f950ae07e51c768ca3ff6177b2eac50f10dd2e64610fa8ab5788faeee29d129009d7fe46aa3da6b9d86c73065eb5161fbdbdfac5777c4e75452e6e16ae9fd66bb7d9aaa426bcb7a6915f0ff44a1f8ec71394e9352fdf20e02fafe1e0cefe50744c3194956f928f82533755373838dcc1296a891adf641c7382d69b4f5a43d4af7772a4a1ee879292d7a4f32ac35ee121c6c34ca5f98487a941fcb1e65b44d4456127eedb2fcc1c3f48eff9300981e52ac38b496ab8bbce144a85eb9c07638b31fdaa781744bce17e8d93dcdc60afeda488807617f88d6aa54422fd347ddaddeff37a563dbf19974b2a23be300fbfa6c7fc41f84c6905415269f195990b5b4de12668c71c87b504f41124bf94436f333045631518152c5162a2475c40efb6cbdaaf9af428fed325b3a7d94c17520fd89e00ddf08b22adf661f0acd723b3969dc6434ea6f92ef58e8dfae5b0cc2885ba987ea1d16c39b34ef65023009d6345e48e3691a41f02a77b7fe133ea9de7565f157a2078ae988bbb266d22d5fa91a7b263e98ad2dc0731fe5a29025a0cb436864a5a60db257f1e76b5c608f25cdecc87eae6: +b500768a2823915c4a6848d35f6487d43bd766d2ce0945f8a3ccdb8d82a3892bb8cea215a0124eed27005725d897781ea064dcefb21422c8bd2402c56a10571c:b8cea215a0124eed27005725d897781ea064dcefb21422c8bd2402c56a10571c:0a9fda8b8cfca7a5b05d78116fcee19ab803c1c6010ce11daa8e93a66d12c12e474eb91c2640d97a813d9a830d268868eb2e3770425f10c75840468e669dc7f61d3be2de88ae0e542bc809679113957a14da4eaff549bfde637d7cafdc6aa83994837397f86e4fde86d402fa9aef7f65549a214373e560e6d7a1c2769e0c7d5a0171e7cc00dff36e0429798b53aa621624bda74d6df0bffffbd8fd7bef1a64f36c000782f6ed031af5c2a74a18963598c9ba062392de9602036794b7b5e68c25c93fe7cfad47a7c5b979d476cd513a12bf0307cb1631740042a9fbf3eb0be5170620dafd5f16ed89342c2625d783e74ee0d784bf051943740c88b0bef7bc85e1a6a4a517d492fb737e776699590c93224cd4d9245d4e9371a367c0712f87490f9247c49add9313f277a4d9f26b75aae4ded6a3def85f83fc995910405548af670ed8aaa30524ab829ccb56a5005b58bce868c9e8074f07dd7f3818f299e4e086bed9eab902cf11b398d531b8632e7d523a8f877695f46ccf9ce24e62cab2c7cd0aaee17db52676a4b5058e9c1d7c47bffcb641b0ea2b0944f39a75665a7ef29b7f02a878db823883bdacfb0fbe5dfe5a9bed9fdac7e4142e3eb50d5e840bd0ac0becf4fa97e1fc4827c397a52465d916889954b3701b0fac61159b23092f4685f4788bad35d00da2679ecc54921f1a8647101657ab49477420567aed67c8605930444b5d07927c17eff1f8570cf2af29e719f85ca7849b895549f13dfeca68bbef71e3ce8b6cedd2ff68d32b02caf5951a0b3e6b0bae6a96c02058191f305e090711c46daddcd5aeee769c3a105e9a827bbd195d329231c26238479a9bb0071afb160ef955e874d7a420c56785f44ae0a18c52d8280c5998cf3888feaf89898134bc8d411fc9f6c5768ea7a249729413739e532b643937152cdfb8d2ff87fd48084dd8aeebeaf0f7b10d87b6e4423228c9fc8dc5e3852aa8b8acc545d18f25c55d73da1bb82e3eb376f9ef05b274d7ecb1845d65ca0cd2629f038a2d664d7a69781c84e98de2c209c46efc51162172856649469e673308dcc145eaf783f5cb5b4be7d9fd58ee0974c981a38fea8e31267abfa410e69e46482f5134f3da1ffe381bd69d8d0b78ea909b4af9396dcaff89960a049eda6946616fc27ccf9a9e5ba1a0135764f37719da4d28078185d04d72419c2c70f290d97e1f82b879f71b9e19d504d364cd3ba22cf905250fd37d58e5fe40209f6072a06d8b5ba70196230577877ec46153167a7c7aea270fa1098aba9e3a74acb36a11b09bd07a3b88ea654e268365625b589b2206c710d960f42ea419b7e4e3da4759fcbca50e4bf4cc55cf88f70b3180c805a7045086afa04c6be23223ecae5f82c146d54311d1807c2e4a53f9e0a4482b4e1e:e3db47a11e10e788925d14b1e28b54c9fcf9b6acc1df8c14f683a5672fd504dd4a475a3393b3ef8bceac2361dbba3530af25c246c3ec4c05899b517f6cd34f0a0a9fda8b8cfca7a5b05d78116fcee19ab803c1c6010ce11daa8e93a66d12c12e474eb91c2640d97a813d9a830d268868eb2e3770425f10c75840468e669dc7f61d3be2de88ae0e542bc809679113957a14da4eaff549bfde637d7cafdc6aa83994837397f86e4fde86d402fa9aef7f65549a214373e560e6d7a1c2769e0c7d5a0171e7cc00dff36e0429798b53aa621624bda74d6df0bffffbd8fd7bef1a64f36c000782f6ed031af5c2a74a18963598c9ba062392de9602036794b7b5e68c25c93fe7cfad47a7c5b979d476cd513a12bf0307cb1631740042a9fbf3eb0be5170620dafd5f16ed89342c2625d783e74ee0d784bf051943740c88b0bef7bc85e1a6a4a517d492fb737e776699590c93224cd4d9245d4e9371a367c0712f87490f9247c49add9313f277a4d9f26b75aae4ded6a3def85f83fc995910405548af670ed8aaa30524ab829ccb56a5005b58bce868c9e8074f07dd7f3818f299e4e086bed9eab902cf11b398d531b8632e7d523a8f877695f46ccf9ce24e62cab2c7cd0aaee17db52676a4b5058e9c1d7c47bffcb641b0ea2b0944f39a75665a7ef29b7f02a878db823883bdacfb0fbe5dfe5a9bed9fdac7e4142e3eb50d5e840bd0ac0becf4fa97e1fc4827c397a52465d916889954b3701b0fac61159b23092f4685f4788bad35d00da2679ecc54921f1a8647101657ab49477420567aed67c8605930444b5d07927c17eff1f8570cf2af29e719f85ca7849b895549f13dfeca68bbef71e3ce8b6cedd2ff68d32b02caf5951a0b3e6b0bae6a96c02058191f305e090711c46daddcd5aeee769c3a105e9a827bbd195d329231c26238479a9bb0071afb160ef955e874d7a420c56785f44ae0a18c52d8280c5998cf3888feaf89898134bc8d411fc9f6c5768ea7a249729413739e532b643937152cdfb8d2ff87fd48084dd8aeebeaf0f7b10d87b6e4423228c9fc8dc5e3852aa8b8acc545d18f25c55d73da1bb82e3eb376f9ef05b274d7ecb1845d65ca0cd2629f038a2d664d7a69781c84e98de2c209c46efc51162172856649469e673308dcc145eaf783f5cb5b4be7d9fd58ee0974c981a38fea8e31267abfa410e69e46482f5134f3da1ffe381bd69d8d0b78ea909b4af9396dcaff89960a049eda6946616fc27ccf9a9e5ba1a0135764f37719da4d28078185d04d72419c2c70f290d97e1f82b879f71b9e19d504d364cd3ba22cf905250fd37d58e5fe40209f6072a06d8b5ba70196230577877ec46153167a7c7aea270fa1098aba9e3a74acb36a11b09bd07a3b88ea654e268365625b589b2206c710d960f42ea419b7e4e3da4759fcbca50e4bf4cc55cf88f70b3180c805a7045086afa04c6be23223ecae5f82c146d54311d1807c2e4a53f9e0a4482b4e1e: +9eb5c9ef13535f808109f4a43cfad5684f80daf02eed5410ac0b0a09a6082d69367eea1ecb4e5eecdf7e471b90bb34f9b7982c8cd66d42555c240b41cd8739db:367eea1ecb4e5eecdf7e471b90bb34f9b7982c8cd66d42555c240b41cd8739db:2d7cb05e61dbae26258e3861c639ef0e1d17fc711a00f335ba3c027137e00708d708c1ff457ff2c65112f7dcd7d02f24d56f072158ea1c71832550a58366fd9197296bbe61aa4d00de18a453ef9174fa81968305c41c3455f42d447a9234f06e13bf8bcaa1babb11695fafdc08f7a584b2ea1f61e9389260ce7335a07de72c8911a58a313f1088dcdf5c8d4c456cba2dcb4f2d156b4943b95bd493ea4fe1a82d4e3ea02aa02972400b5ee17842832d59979fc179f843c44b03eb3c302416d0cdaf11c4ca8a66ccbb6997395edf6fca2ea004cf3486971004a42042af8ece005b94461d86dcde212a2eb1be3b914c783e48ac1ad46cacd73e1eb448368322d2678efcb2abff52093db0f259dce5c1e19a512820f235d6aeaf0e1a723c2c650cff1ee3b6b4f4cc989c0b7d6de3cd7e6daa39bb690710df00a7194c17201f0e81be64b6739e1c1e8176b7e12a353427c067c19314db642e5c76266b640eb1cc0c73f84fc0227e5a96060d814071cde2fed944767b7466f9001dfc223685429bc4e5e48f5c13a63a4e0d826133ad920d11772145ad6e13c93897398a8a401f93dbd103005c7dae44387f3e80b793607d05d2d8bc0d0351a3a452b8ce759c1ad48df7b9ba9e4a17df61fdabb9b577b5cec3e9461fbb5e128155a3c9c89f8f6bebb7322a16678e8ecb98953d958310db1b063448c349f36e168fac484cb3c0d4cb2c251bd92ef8e9262b44093d7e650a7d3bed3791fa88100fee6ef0d5e23d1e9a8099cc0335202a4f106c24777e98f81d26efba15c9ad1541e0adbf1d1d76076b0dfd7b7d6c8b82f9c093468cd196672dc5478e91ce701cdd7b68b353c97111f0429760635762f8683ae970564bceba9120517642e8b3a2baaa85c25b54a943766184904c72d929634ec5f0c28473415f12538906c678fca4e682db4879758492537e7850b9bfef3eb9053b43920d810e55be966aec68c9dd3b62ccf57e8178cb5ef6d16d172a56dd924f00f2d3b5e93aaa92b29fb8336d73e29e59d1c47ea6230cda1d5b03bba5dfdb331feb19443f123d2a03ff4f10eca166c2998588f1e584ed194dd6f73c8aca846631904d9fe4a98b367823e46edba2885129879e9277e150f029b8fa7bd11eab9ce1336777c80b56b3a1f0811adbca0f5b4025a5503c8196661aee90006e9c85bbfa4c5a0e902885c8ce51212ee67f0fe0b6afbc8bad453727543b3c68b890ddaba269d25fc1643f54835136a1a25ba18d916cedd6a47fc07adf6fc69fa508949dc10d9dc5e0261b52f3657170384eccd9c80541354b1ce0f6fb5ed3e8d54af0b5bf0a92835125c7d9bc4f092ff380e5e896fbf302552b14d5b61a224d86e301c7a66a66e4e4329aac0a66b156772374dc1c7168d5b561652f8f4387e4f289b6366a:429ce1fe846d250849eca7d456f8c59f8675b1f4c13f2be41688dfb8ca2a3b24ae29d5b6bf471157bcb6e2ec9d4a26b038e6ec28584cc23f2a03556dbb37e9002d7cb05e61dbae26258e3861c639ef0e1d17fc711a00f335ba3c027137e00708d708c1ff457ff2c65112f7dcd7d02f24d56f072158ea1c71832550a58366fd9197296bbe61aa4d00de18a453ef9174fa81968305c41c3455f42d447a9234f06e13bf8bcaa1babb11695fafdc08f7a584b2ea1f61e9389260ce7335a07de72c8911a58a313f1088dcdf5c8d4c456cba2dcb4f2d156b4943b95bd493ea4fe1a82d4e3ea02aa02972400b5ee17842832d59979fc179f843c44b03eb3c302416d0cdaf11c4ca8a66ccbb6997395edf6fca2ea004cf3486971004a42042af8ece005b94461d86dcde212a2eb1be3b914c783e48ac1ad46cacd73e1eb448368322d2678efcb2abff52093db0f259dce5c1e19a512820f235d6aeaf0e1a723c2c650cff1ee3b6b4f4cc989c0b7d6de3cd7e6daa39bb690710df00a7194c17201f0e81be64b6739e1c1e8176b7e12a353427c067c19314db642e5c76266b640eb1cc0c73f84fc0227e5a96060d814071cde2fed944767b7466f9001dfc223685429bc4e5e48f5c13a63a4e0d826133ad920d11772145ad6e13c93897398a8a401f93dbd103005c7dae44387f3e80b793607d05d2d8bc0d0351a3a452b8ce759c1ad48df7b9ba9e4a17df61fdabb9b577b5cec3e9461fbb5e128155a3c9c89f8f6bebb7322a16678e8ecb98953d958310db1b063448c349f36e168fac484cb3c0d4cb2c251bd92ef8e9262b44093d7e650a7d3bed3791fa88100fee6ef0d5e23d1e9a8099cc0335202a4f106c24777e98f81d26efba15c9ad1541e0adbf1d1d76076b0dfd7b7d6c8b82f9c093468cd196672dc5478e91ce701cdd7b68b353c97111f0429760635762f8683ae970564bceba9120517642e8b3a2baaa85c25b54a943766184904c72d929634ec5f0c28473415f12538906c678fca4e682db4879758492537e7850b9bfef3eb9053b43920d810e55be966aec68c9dd3b62ccf57e8178cb5ef6d16d172a56dd924f00f2d3b5e93aaa92b29fb8336d73e29e59d1c47ea6230cda1d5b03bba5dfdb331feb19443f123d2a03ff4f10eca166c2998588f1e584ed194dd6f73c8aca846631904d9fe4a98b367823e46edba2885129879e9277e150f029b8fa7bd11eab9ce1336777c80b56b3a1f0811adbca0f5b4025a5503c8196661aee90006e9c85bbfa4c5a0e902885c8ce51212ee67f0fe0b6afbc8bad453727543b3c68b890ddaba269d25fc1643f54835136a1a25ba18d916cedd6a47fc07adf6fc69fa508949dc10d9dc5e0261b52f3657170384eccd9c80541354b1ce0f6fb5ed3e8d54af0b5bf0a92835125c7d9bc4f092ff380e5e896fbf302552b14d5b61a224d86e301c7a66a66e4e4329aac0a66b156772374dc1c7168d5b561652f8f4387e4f289b6366a: +ef0948e13281f3cf352cbfaf8d89d117768552d5a1548ecbaf37412e97670fac58c2457f5a5e3cfbf47119a87f2aff1918f1e67ae6fa9171d3f41eee07a86872:58c2457f5a5e3cfbf47119a87f2aff1918f1e67ae6fa9171d3f41eee07a86872:7ec47f2f1fe3b70a6d1d82c7cd924b4bf9b2029fc12c52a6e1cc06cf5abfc0a442e7cf145c1542b9b135049665711035e3c29a91d4fdaed6127057a812c22cd75ad1879be1d2c6110e79e987524e4e8f27f16eda90cbd4733f111825b516d1067f81eca5e6948576d5bfedb3277c1abc1e60f374d0701b32ccfd6a5e9c8d1659aaf3d0818613613b7e288d845e9aaaba2e3e9b411d501dffe856fd313e9fcc9e7430b9983f20ab4ebf4eb616bd63e2c57743658995ed0a149ae620a395613719b3ed7ced4588d5915d70a2f0c687680ec34fe3e9f72392e189e13a4749d5ca9fac651b92c084c4066fdf98a869223e4e0c9bec5812b5c1900e6e60d3a188d48a74dfd415b5cad2e91ff76df75089d20a755f260756c8f1382a29f7b93726e731071cd477458c6f2022dfad7d4fc7ab2380541864f6b58774f9ae8e5f077c1a8da073c39853eb2fd477220b45a3d92263dc7e14d3bb2b36fca466c7ef8a247538725f2fce5c7221bc751cde1394604f5931d733360ccd47ce087712958180ad84fae713b543f05eef6abc0661433121ed3b4506a1465025316fb8f9d64535cc4538acd4064dd576b0740e1beb13bceaf155543dc89097ca5ca1cffa0ad65a10bcb759354eab8a42de734af909c2feba380d66409f325d5f17af9ca7f8cb4134fd6a2b6a528d9e60d9612b8e8b4062f8e0fad1e7eeb9cbfef6e9738ec7973e1cb2ba2327deca4ea46568f31e12f730e247c1d07029fd4422b298ff2398023b4120a3a425ffb652880c19ea69f3639e0f6df4f00876cc4528e267e81d5943199d0feb6cb4e1baf404bb6f8b39b12dbce9fdc35dc158066e9975ae5bd3b55f2a41a791baf3e8351ec604944790a22c933c80b1590ba197a4706f7f5128682edcd74dd78d435e787c2b76a57b3f4e7d7be2efd26da5f9a829119b01508b7072c7699ce52bb578cc5b1b93661b5172fb84daf1ba364d2cbd80e2c99bca9caea873cc0a1629eac384e9b206842a6e6183387591b4aa34a95fd89b49d8d15d91e21940e17dcaf1eff8a0a47a0d7a95daead82aa3df8204a0cd206924ae510fec8a9c4e8d85d466fdb4dd365dc99336b22ce0b956b5ee0017f29d25ee66fbdcecb0d996ffb97c8defde40a9ff9993193ca8f1685067c19c526e0efed236f8edb8def6c2a03e21952c8612d624e6886a311ffb9e2f15da44abe180d26a14b15f63561e097a730ecabb792c7c235fdd360f571f27ef68677a7d63beb4975982cb199a560f816ee12989445f7f75b83eb278d62825947d84099af2a6ff2eadbbf589b5eb2f72ed114c73151153ae0022bc9564d15c2d5cdbbaabbef638f03095f53eebac9683409ad3060cfb7c7037b9b0befe069c92a02be953388e9ea45d36ddf4f5a8389432ccf504c50808b07f69:cc12f69db63a678ec477a605a505c57dc2b810ef85e3e34519cb25c51063aa66355d3f1e2974695866edf6f17171ce37842fbab5075fc895d18ed743c546080c7ec47f2f1fe3b70a6d1d82c7cd924b4bf9b2029fc12c52a6e1cc06cf5abfc0a442e7cf145c1542b9b135049665711035e3c29a91d4fdaed6127057a812c22cd75ad1879be1d2c6110e79e987524e4e8f27f16eda90cbd4733f111825b516d1067f81eca5e6948576d5bfedb3277c1abc1e60f374d0701b32ccfd6a5e9c8d1659aaf3d0818613613b7e288d845e9aaaba2e3e9b411d501dffe856fd313e9fcc9e7430b9983f20ab4ebf4eb616bd63e2c57743658995ed0a149ae620a395613719b3ed7ced4588d5915d70a2f0c687680ec34fe3e9f72392e189e13a4749d5ca9fac651b92c084c4066fdf98a869223e4e0c9bec5812b5c1900e6e60d3a188d48a74dfd415b5cad2e91ff76df75089d20a755f260756c8f1382a29f7b93726e731071cd477458c6f2022dfad7d4fc7ab2380541864f6b58774f9ae8e5f077c1a8da073c39853eb2fd477220b45a3d92263dc7e14d3bb2b36fca466c7ef8a247538725f2fce5c7221bc751cde1394604f5931d733360ccd47ce087712958180ad84fae713b543f05eef6abc0661433121ed3b4506a1465025316fb8f9d64535cc4538acd4064dd576b0740e1beb13bceaf155543dc89097ca5ca1cffa0ad65a10bcb759354eab8a42de734af909c2feba380d66409f325d5f17af9ca7f8cb4134fd6a2b6a528d9e60d9612b8e8b4062f8e0fad1e7eeb9cbfef6e9738ec7973e1cb2ba2327deca4ea46568f31e12f730e247c1d07029fd4422b298ff2398023b4120a3a425ffb652880c19ea69f3639e0f6df4f00876cc4528e267e81d5943199d0feb6cb4e1baf404bb6f8b39b12dbce9fdc35dc158066e9975ae5bd3b55f2a41a791baf3e8351ec604944790a22c933c80b1590ba197a4706f7f5128682edcd74dd78d435e787c2b76a57b3f4e7d7be2efd26da5f9a829119b01508b7072c7699ce52bb578cc5b1b93661b5172fb84daf1ba364d2cbd80e2c99bca9caea873cc0a1629eac384e9b206842a6e6183387591b4aa34a95fd89b49d8d15d91e21940e17dcaf1eff8a0a47a0d7a95daead82aa3df8204a0cd206924ae510fec8a9c4e8d85d466fdb4dd365dc99336b22ce0b956b5ee0017f29d25ee66fbdcecb0d996ffb97c8defde40a9ff9993193ca8f1685067c19c526e0efed236f8edb8def6c2a03e21952c8612d624e6886a311ffb9e2f15da44abe180d26a14b15f63561e097a730ecabb792c7c235fdd360f571f27ef68677a7d63beb4975982cb199a560f816ee12989445f7f75b83eb278d62825947d84099af2a6ff2eadbbf589b5eb2f72ed114c73151153ae0022bc9564d15c2d5cdbbaabbef638f03095f53eebac9683409ad3060cfb7c7037b9b0befe069c92a02be953388e9ea45d36ddf4f5a8389432ccf504c50808b07f69: +903f3b5399892e29ccfafbafbd7cc4533c154a625682406c89bf894c889e43f48fa5ff5b6b26bd67df864046429df124b523005dd89444275c8ab7ebddb6f4db:8fa5ff5b6b26bd67df864046429df124b523005dd89444275c8ab7ebddb6f4db:a2c11b5fb884a822fae64da8dcb4452cfd7a04ca6d7a5abc8d8271e93f93449e1feb8e02975f496b9034400d3599ab97aa3997dad1c9ffab5b9f8df4aaa5b840d90d862fff7ff0cf73a60c66150009e01c937bd1af6807b5ba2ef612ee13d6def40bb09c46811a2d4e468e038b323055f9dfbd01829ae2f1a535ef0295ca1ed176e46de996cc87bace45356233211835b6f4757c99bd527e766a5f0b127c8cff8e6d66f8bab86d0000452cd7f67be557788513ec0709b537b007b42016e7a89683469bd8ff8d21eb10c14917d47f2dc4f826324f7c01b24f8dcff04aa6d85095d9ab154ba5c3bd919c9d728dbdc990d19ceb237b452907bdbe21f9f08cddae5be479276709b8ae73f8974c4b113841ad535d6ff6223eea47d185c8e8a65fdee2c2d45800c17cb556eafd676647d9968e55ca9c59232b9770ad10f955fcb5858edf0b7483adc1817c0f8d02240482caa76f43c6d2e96a4ff9591cd7b878ea619ea56d1b588631e7633c5ecb2ba6998398cb06e3cf75aeb3e08dab19632d454ff7dc0e2a41f09737e8ee823d1b9e24dda84a2ce0313cb9fce31cb663c55c05645e63401756e8ad38f5174c02a663d815ad64422ff7727d4fda16e48d4bf8f6602e7260da62330e6878c34764e129afbd552208f6bed4f7cee9b671f488388815d74b4951b8682ce76cfe31e938c470b8f7a45fd63a9691f426a75c58ed3dbce3ae8fd9d10a8352e47cc1b12c9192ac8626d1b384b77a18b986e71a998646c137992b67c4817e346345faf50a2659fdc5cad5c719648efee3847c0ff6bd7095c28b4c5195967c90cf84e1ef68a1ada01f6274ede363fb82e0b549a870245d608cae8234f6d84abeb61b718466093620d85c584ab01eeda091ee8aff1cf67a4675679a1f4003e66aaf43871b88ecda6a16dc5acb05395f2da9df70d3bdb61438e1c3d40981e034627d026ee1d2e79f65cbb8189fcbb3cc8b5c2e7e796b5d2889411d5641fb869c7b0a589c43254f8c5438aaf5ac423832f018d79a51b96f242e2de0c851cc5fc2b206bca4b5be836125aca144bbc38c8c638be0d3bbe025a1be8b3d03d5929baa649c3544a32a915e926a38791b134a971bc52d1b6ca625efb7c2f3bb47ab51d43c8e374d16cda882204b71cafe9093cb6078ef2bdfad59edeaf36d0c1a4dc425b9e718c45185225a9c3084b782bfe163492f8e8482ec9aa073f6901ff3d1117ce917e19122fa67650d858f8f82b37669723c226d721697e7ae3359f5a6b02424ee8794cbeaa641edbbf753b103a5fe158be0ba60d8a212d42f8c5c2af254bf1b9c80df6f1cf09d70793cae1abb4627b1780f1bce7f617ee50f6bd4b083b2fc7cd844afb72380d5cb6b255bf47ea71cad6c6c4df021f81b548f432c18ac366c6aecd03b6c8ce2:495a8f991941c629bd641a67471ab860bfd39b72f23355f7270909d5307c77b1b94bae3ed19450780e9085305f31b1e1683facf0d1fc8840aec77df67aeab302a2c11b5fb884a822fae64da8dcb4452cfd7a04ca6d7a5abc8d8271e93f93449e1feb8e02975f496b9034400d3599ab97aa3997dad1c9ffab5b9f8df4aaa5b840d90d862fff7ff0cf73a60c66150009e01c937bd1af6807b5ba2ef612ee13d6def40bb09c46811a2d4e468e038b323055f9dfbd01829ae2f1a535ef0295ca1ed176e46de996cc87bace45356233211835b6f4757c99bd527e766a5f0b127c8cff8e6d66f8bab86d0000452cd7f67be557788513ec0709b537b007b42016e7a89683469bd8ff8d21eb10c14917d47f2dc4f826324f7c01b24f8dcff04aa6d85095d9ab154ba5c3bd919c9d728dbdc990d19ceb237b452907bdbe21f9f08cddae5be479276709b8ae73f8974c4b113841ad535d6ff6223eea47d185c8e8a65fdee2c2d45800c17cb556eafd676647d9968e55ca9c59232b9770ad10f955fcb5858edf0b7483adc1817c0f8d02240482caa76f43c6d2e96a4ff9591cd7b878ea619ea56d1b588631e7633c5ecb2ba6998398cb06e3cf75aeb3e08dab19632d454ff7dc0e2a41f09737e8ee823d1b9e24dda84a2ce0313cb9fce31cb663c55c05645e63401756e8ad38f5174c02a663d815ad64422ff7727d4fda16e48d4bf8f6602e7260da62330e6878c34764e129afbd552208f6bed4f7cee9b671f488388815d74b4951b8682ce76cfe31e938c470b8f7a45fd63a9691f426a75c58ed3dbce3ae8fd9d10a8352e47cc1b12c9192ac8626d1b384b77a18b986e71a998646c137992b67c4817e346345faf50a2659fdc5cad5c719648efee3847c0ff6bd7095c28b4c5195967c90cf84e1ef68a1ada01f6274ede363fb82e0b549a870245d608cae8234f6d84abeb61b718466093620d85c584ab01eeda091ee8aff1cf67a4675679a1f4003e66aaf43871b88ecda6a16dc5acb05395f2da9df70d3bdb61438e1c3d40981e034627d026ee1d2e79f65cbb8189fcbb3cc8b5c2e7e796b5d2889411d5641fb869c7b0a589c43254f8c5438aaf5ac423832f018d79a51b96f242e2de0c851cc5fc2b206bca4b5be836125aca144bbc38c8c638be0d3bbe025a1be8b3d03d5929baa649c3544a32a915e926a38791b134a971bc52d1b6ca625efb7c2f3bb47ab51d43c8e374d16cda882204b71cafe9093cb6078ef2bdfad59edeaf36d0c1a4dc425b9e718c45185225a9c3084b782bfe163492f8e8482ec9aa073f6901ff3d1117ce917e19122fa67650d858f8f82b37669723c226d721697e7ae3359f5a6b02424ee8794cbeaa641edbbf753b103a5fe158be0ba60d8a212d42f8c5c2af254bf1b9c80df6f1cf09d70793cae1abb4627b1780f1bce7f617ee50f6bd4b083b2fc7cd844afb72380d5cb6b255bf47ea71cad6c6c4df021f81b548f432c18ac366c6aecd03b6c8ce2: +ee81e0fb052e23ad759de6aa9838de98e36d4820dc0e1b7b3ef1141ab9de334098f3c9880794de64fa269bdf336095e0e01b1a3b375f965b93700bbdf4b96869:98f3c9880794de64fa269bdf336095e0e01b1a3b375f965b93700bbdf4b96869:28d99e9518b88283c220e76de205d7b6162359b1dfec1fbaab98ec0ef1df8da40b6b7a775e9728450aeb2351fe5c16afda3aec0d71049da4cb7d4c63713a2410abb022f81611cc064587c8047d4383c00c3c562e9ceea35775095391b5f3dda0e373c4a77ff618a28ef68787ebfc3ebcccc5d1ce32ddf43bfce57203da76a8664b3c616a8869282db0b72811b5fd5a2a03a4ff66724b0489ea2e1073d781c3f189115d79ba20a46d1dfaf5b1a5847b2a2e31b2808737569e60b57231e6a99af26f58afeb15770810474812fe4afacf884506b8c314bc6751bb42b4bd6e87d2e5de70fec5f0014c4257b13472a3b0111a7a8cf83b1dc0cf962022cd44468a3ab1f0016b70cafb1d0246acd7053937c9ac40207cf13b50dd15e2a2e15f50a05bca2f28e770262371dacee02e25b2a59658ed90c0600fa265b7de3d44f8ef0721bf39ec4d4eca5888527b778067b1d659c00514c8d7056273a294cbafe45090d069bbd09f92f461e648f3e682882c71576e974debb0cb7e0e8316406660150dabb58e76246614a291c12ce9e0346c02774d4d09cecc23696712fee250c0bb5df7a2a4c43a5563331bcbbf84be3f2eeb0654532e85ec597b53b32f3954ccaf0cd426def91ec4b208416948af27de04d832705897a04c5e24a2e88b20040fd4eca3089fdb918a92e35c4d31da26850b9dd34118c74449a855ff4bc9fff0d1447839654b00417999fa4eb89102133cd320409153584957c10489db4b7244c95907988e83dc821271dc1ab643d6992d0fd820492ae642e24d19a179fa75d9363b321662606fd94a47fdb2e68d3f30c04673f809de0144945ea4d4183d48f175079eed50323c6b192e020e162a3503aa582fb08b403624a23e357eeda08d904386f358c36c64d314c77cd9d4d23d581ee53d81ff97ada019cfcf04eb9dcc1de9b74c3db6b811578bd4f219c5ca48ef4c826b09e6c96d031f65dd48b6e73d0c100586b21df0293a03d2ed7e5009ad025340c21d09060691f5cd8af2ab12f9b860ee87815e1a9f400c2a6f634ea8f9b3425a08d10b3c815367388f4d1be356318ecf9035d0ee975affa859caac28ebccd0599bb2f6f3523661bd178fc9e4cac378bb9dd4716bb06923fd2bbd56c959c42b95d50193f8bf299fcca3b2eea94ec5f98583924c080416e28b54fe57658458b055ce4de8a75fc82715cae91d375cf69281378051bb61fdd7bb0068f63efa6d6e83d8fd4257af80970f4a9e6924b2de0ad966dffe6fa4a113b0e772f1768785b3b42049f76c48ad80f2c67fb0f91a5fc4107912520d8d683c062c3a222bcda7e710bacd478ee88367b6a059a452fd26f114a5acbd6979ba019f7da68ac04a193026bc1c27e4837b1de29cce090e3380d5051a586409e628e3145665bb1d84ecd8:f0d873be15cf454c7434deab71de25cfe99e81a48d2dce6a35d1633714df0f8b4029e0582511efc4d06892f672850246bcf070c46fadc2faab44dc435045de0028d99e9518b88283c220e76de205d7b6162359b1dfec1fbaab98ec0ef1df8da40b6b7a775e9728450aeb2351fe5c16afda3aec0d71049da4cb7d4c63713a2410abb022f81611cc064587c8047d4383c00c3c562e9ceea35775095391b5f3dda0e373c4a77ff618a28ef68787ebfc3ebcccc5d1ce32ddf43bfce57203da76a8664b3c616a8869282db0b72811b5fd5a2a03a4ff66724b0489ea2e1073d781c3f189115d79ba20a46d1dfaf5b1a5847b2a2e31b2808737569e60b57231e6a99af26f58afeb15770810474812fe4afacf884506b8c314bc6751bb42b4bd6e87d2e5de70fec5f0014c4257b13472a3b0111a7a8cf83b1dc0cf962022cd44468a3ab1f0016b70cafb1d0246acd7053937c9ac40207cf13b50dd15e2a2e15f50a05bca2f28e770262371dacee02e25b2a59658ed90c0600fa265b7de3d44f8ef0721bf39ec4d4eca5888527b778067b1d659c00514c8d7056273a294cbafe45090d069bbd09f92f461e648f3e682882c71576e974debb0cb7e0e8316406660150dabb58e76246614a291c12ce9e0346c02774d4d09cecc23696712fee250c0bb5df7a2a4c43a5563331bcbbf84be3f2eeb0654532e85ec597b53b32f3954ccaf0cd426def91ec4b208416948af27de04d832705897a04c5e24a2e88b20040fd4eca3089fdb918a92e35c4d31da26850b9dd34118c74449a855ff4bc9fff0d1447839654b00417999fa4eb89102133cd320409153584957c10489db4b7244c95907988e83dc821271dc1ab643d6992d0fd820492ae642e24d19a179fa75d9363b321662606fd94a47fdb2e68d3f30c04673f809de0144945ea4d4183d48f175079eed50323c6b192e020e162a3503aa582fb08b403624a23e357eeda08d904386f358c36c64d314c77cd9d4d23d581ee53d81ff97ada019cfcf04eb9dcc1de9b74c3db6b811578bd4f219c5ca48ef4c826b09e6c96d031f65dd48b6e73d0c100586b21df0293a03d2ed7e5009ad025340c21d09060691f5cd8af2ab12f9b860ee87815e1a9f400c2a6f634ea8f9b3425a08d10b3c815367388f4d1be356318ecf9035d0ee975affa859caac28ebccd0599bb2f6f3523661bd178fc9e4cac378bb9dd4716bb06923fd2bbd56c959c42b95d50193f8bf299fcca3b2eea94ec5f98583924c080416e28b54fe57658458b055ce4de8a75fc82715cae91d375cf69281378051bb61fdd7bb0068f63efa6d6e83d8fd4257af80970f4a9e6924b2de0ad966dffe6fa4a113b0e772f1768785b3b42049f76c48ad80f2c67fb0f91a5fc4107912520d8d683c062c3a222bcda7e710bacd478ee88367b6a059a452fd26f114a5acbd6979ba019f7da68ac04a193026bc1c27e4837b1de29cce090e3380d5051a586409e628e3145665bb1d84ecd8: +69d01d829113081cbf5d0c6ef77b21775c8d9b680000056f03c75a7d0a0587d2ee8469dd61cf5de400da7d7a479a4418e6772e69ff5330ce5ca77859fe271755:ee8469dd61cf5de400da7d7a479a4418e6772e69ff5330ce5ca77859fe271755:0b9e110f29d19816a17b2c75478f13cee953811a1983014cb7eb0f75526912044c3ea6829780e657f817c5597d4661080d9034c9778722418f2c3aeecaef6b690c5bd3b593701086988e4340aec34e0172758eb24087d03a8f76e7cbca53aaafc4d2155c7532ab54be48872653066fa1fdd54acfe9daaeca356c290e6be63355b6d9fc52eb5e4fccbbc6083507132de485bfae9f42e19712232b716402c23fea74efa69d73c8c2e3a8662b8b65b0fd007741013e1f6e3cfe4345d5c830682fe60021d708e10a9e9f4052ff7a6abf28acb1d6b5fb038eed3f72513c355bbfd5c2274fa85fc4f446974b2d1bc036507a1eb5fcf55dbd44210e538274de808b900bf1c0fcc0241270db8dbdcd88349d67224f087e5f07f699b0bae68b2ebc9a4e27c70d3ac7d996fa7d4dabd568378e3f93905b1c89c652d384c16c2bcb1c9844c38f71bb13e0c6a2ea95b612e390c5f86d248ea531f2ec6f639a402dfaccf37217005344030745d1f1e520cc195dafdd7f295f377b8d614716703836219bb7b09fea7aae9ac33e42dcab65cc6142fcd8ce15e97717fdb33e9538c44f6cd9c1c65db62751f552f870f10142c96f9df1855abb39e42706a563ab154511fdce687c9576f9edc3b4ba55346ce66802fffef4b1b5e12015ce8b57de5458caa0daf341968128584288c2f27cbfb76eab286bac5f66aad0049e0ca60a9014e17901c4130e83ceaeb4c2713e971a235eff995a813ae4ea64a583ffdefdac82ac76eaf4d47c4ac8250fcbafd6b88faeb48015f5b42b5334a50b31d4502ea491da90dce93c08fd56f5c58eedb379166a23762be5e4adeaa6f4ae1c24e0cac4ddca0383458560cdc48b8cd1f42a3ba2f6ffb6077909fcb294ad1ef4a44c22ec4b3987ddbeef325b98ced56815ea7d5fccf5afdfe98e0e6d920f7ada2eb5c91624c76cbba2993a9c7a55021d127a667b39e235df4f81dee7dd142898778dbd92135b70b3acf59f6c29a2c9d4a7006ef11a918b3a2906264a15d6b529308cbc89f85601fc1ea1314d67f7566cf109165c7f92de1a18d70debe024349db3560a6e527e2ac3e06789468704e6b8f1871f16bae9827392b418f1086cc497086ced14b1249d6d8794f23bb8779d418648f2155656a6fda7440c56284d9b2188fa7d1736bccc9cff0be5b1e1f551ff8137ff5966ed9d0f7f01c3dff298e9102ffbd324bfca5ffe0968e66f9d82f487d303934f27f78b28378eb72c38272962a5f735d7392e5d333fd86de167269c17a165b92d31a4880a41e136f718960a919b3d7c4e74cbd73c73f921be513f739affb2e41f80426bb8cfb4564b98fc4de53255ce3f98b4d22ae6fce9190b55bf2c93861c1dcac101b5e16cf09991c5defa33f8d51056d934bb4b477b6520d4c7ae22ea7fb3109de7f4:408cefcf01417e2dc6a8a18284e411657f039250c31278db2819f9eaea4293fbf6831a2801fc1ea6871657b841e173f451b0d575a9379e35857e8c7297fa14040b9e110f29d19816a17b2c75478f13cee953811a1983014cb7eb0f75526912044c3ea6829780e657f817c5597d4661080d9034c9778722418f2c3aeecaef6b690c5bd3b593701086988e4340aec34e0172758eb24087d03a8f76e7cbca53aaafc4d2155c7532ab54be48872653066fa1fdd54acfe9daaeca356c290e6be63355b6d9fc52eb5e4fccbbc6083507132de485bfae9f42e19712232b716402c23fea74efa69d73c8c2e3a8662b8b65b0fd007741013e1f6e3cfe4345d5c830682fe60021d708e10a9e9f4052ff7a6abf28acb1d6b5fb038eed3f72513c355bbfd5c2274fa85fc4f446974b2d1bc036507a1eb5fcf55dbd44210e538274de808b900bf1c0fcc0241270db8dbdcd88349d67224f087e5f07f699b0bae68b2ebc9a4e27c70d3ac7d996fa7d4dabd568378e3f93905b1c89c652d384c16c2bcb1c9844c38f71bb13e0c6a2ea95b612e390c5f86d248ea531f2ec6f639a402dfaccf37217005344030745d1f1e520cc195dafdd7f295f377b8d614716703836219bb7b09fea7aae9ac33e42dcab65cc6142fcd8ce15e97717fdb33e9538c44f6cd9c1c65db62751f552f870f10142c96f9df1855abb39e42706a563ab154511fdce687c9576f9edc3b4ba55346ce66802fffef4b1b5e12015ce8b57de5458caa0daf341968128584288c2f27cbfb76eab286bac5f66aad0049e0ca60a9014e17901c4130e83ceaeb4c2713e971a235eff995a813ae4ea64a583ffdefdac82ac76eaf4d47c4ac8250fcbafd6b88faeb48015f5b42b5334a50b31d4502ea491da90dce93c08fd56f5c58eedb379166a23762be5e4adeaa6f4ae1c24e0cac4ddca0383458560cdc48b8cd1f42a3ba2f6ffb6077909fcb294ad1ef4a44c22ec4b3987ddbeef325b98ced56815ea7d5fccf5afdfe98e0e6d920f7ada2eb5c91624c76cbba2993a9c7a55021d127a667b39e235df4f81dee7dd142898778dbd92135b70b3acf59f6c29a2c9d4a7006ef11a918b3a2906264a15d6b529308cbc89f85601fc1ea1314d67f7566cf109165c7f92de1a18d70debe024349db3560a6e527e2ac3e06789468704e6b8f1871f16bae9827392b418f1086cc497086ced14b1249d6d8794f23bb8779d418648f2155656a6fda7440c56284d9b2188fa7d1736bccc9cff0be5b1e1f551ff8137ff5966ed9d0f7f01c3dff298e9102ffbd324bfca5ffe0968e66f9d82f487d303934f27f78b28378eb72c38272962a5f735d7392e5d333fd86de167269c17a165b92d31a4880a41e136f718960a919b3d7c4e74cbd73c73f921be513f739affb2e41f80426bb8cfb4564b98fc4de53255ce3f98b4d22ae6fce9190b55bf2c93861c1dcac101b5e16cf09991c5defa33f8d51056d934bb4b477b6520d4c7ae22ea7fb3109de7f4: +4b8ed29731f104795e97dee7c8b401a02afaa9a795e613353d2b95001765027af22298210b09fd617fc8b35074ca1801e6075dc92a8f50344b80e85405a038f5:f22298210b09fd617fc8b35074ca1801e6075dc92a8f50344b80e85405a038f5:cbb5f13a0ef2837b805d3b785109f9f2e0d0a017bfe7692d91ec23ddab7817330bef247fd91ab2c77dd4412519cbd38475ce0cb39b1480092bc738d4152b8a6d55248e3b9f32cdcd15ec5d059ec3c8847554ee47005394974d8eb23592d17f5a396e3c19f8e898370679fef5318c4dd299c6217d6abcc9b61a5b2d0cfef695d170ca20a83d6fd3c666c8fd1c10ad970e2fa6af10ff0ed0cbfe752246d03f3a3c6032dbb319bcfdac4dafc50bc3e6bf595f491dec388b3441b8cee0df91f55cc7807d07f8f541ed7322ffc39d18f89560e4123aec1d77969cf1877786f4cf94b1770b1090655e8c72eecea4572e46f580f963966db2a1085eeabc57bf4a84724b9c8599a433abf58bca804091d3d5e6e5048ec27bf8129b670cc2c88d9cac471859f469b918f3f6d70f7d6663501ffbefef026d79ea70927ccf6075ee5105423321e11aee9ad16f987efbdd00b62aff698e521adf9203b15e9f0f3ad07dcad9ddccaae9b490247f12c311dee6b73b8f9124fdce1299b47fb1914cee7e3a07814e312c3ce56927672c51b3185980cde57f3a759b50bcfc4cb0753b954d97135deb2a0532e98b66f39a7c08cf4d548539e2eb9f422f6649658893a7c3c25a4fc901f8c398b8c72733911a0072ed6bd2f4189389ae10a814f648d71f69c37e8295784428183b93c8013b964a9fef86b48f489316bc222e96b3bd15ff149b96820329551c15e0d095d1569b1e2131c78751565c3041f29785395b97151317f62e3582e407b1649e60d03a8599120a302a4695fa862b4120f94d22ecae72398d2094d108ad2dbc1b959735902142aa5fe6e7996559f6f601448aea02f356f8dcdd144340eb3619f9865bf7672aea326c4e93c99f0ed1f9ed866be15d3af2675f6dd6e296602ca373a815b0be46bc2a3fbba06b8805c731fe08007daa06050961b24d14693a72898ccfb8b8fedc60a4eef8ff79b6dd7592591833b576ef48294e5e0485942e57c119602eddf88b1faea517f2fc2e3d14d246a52cbd71a108c66b6cc4f2d45804a282ecedb1b0ad3dc3b4880ab2ff78b8ddde48f7466c14fed349e95b5053abf1bf0991126031d97547d143c2ae164928b61c0708af8ca3e4f55154d13d75e97db4ba3e69d36e9b37082368c2f721bd3f95126a1e004eb2a1bf268343ae21d2995044a2cadd67ffac9e1538175b3cc44db5d26f1d5cc89ca0e1c1ee8537a8a91d324c2e02e18b9fb9730d6dda55f72d843389693ebfcba7fbe1a0bcffb9aa284f4ae66f44a8b89302983b22736d0c72d6a044e4291624243a4e0ce65d5e5346d67fed3760ddb0c510b50ff3eef0a18a267de730476dd82dff7072cba0984825a004dd4bcd8c37fdaf1f683d1d9380e135a95d24b89fad0be941c548251bec90ccae015bc0567da84b371e50:2345886686eb39b5199caaa9615bc6b4896f076e8bd736c0038a6517f9c2b167e759f37372268a697e9b78605f2ed94725f6905a7900153fc9e8beed31ffae05cbb5f13a0ef2837b805d3b785109f9f2e0d0a017bfe7692d91ec23ddab7817330bef247fd91ab2c77dd4412519cbd38475ce0cb39b1480092bc738d4152b8a6d55248e3b9f32cdcd15ec5d059ec3c8847554ee47005394974d8eb23592d17f5a396e3c19f8e898370679fef5318c4dd299c6217d6abcc9b61a5b2d0cfef695d170ca20a83d6fd3c666c8fd1c10ad970e2fa6af10ff0ed0cbfe752246d03f3a3c6032dbb319bcfdac4dafc50bc3e6bf595f491dec388b3441b8cee0df91f55cc7807d07f8f541ed7322ffc39d18f89560e4123aec1d77969cf1877786f4cf94b1770b1090655e8c72eecea4572e46f580f963966db2a1085eeabc57bf4a84724b9c8599a433abf58bca804091d3d5e6e5048ec27bf8129b670cc2c88d9cac471859f469b918f3f6d70f7d6663501ffbefef026d79ea70927ccf6075ee5105423321e11aee9ad16f987efbdd00b62aff698e521adf9203b15e9f0f3ad07dcad9ddccaae9b490247f12c311dee6b73b8f9124fdce1299b47fb1914cee7e3a07814e312c3ce56927672c51b3185980cde57f3a759b50bcfc4cb0753b954d97135deb2a0532e98b66f39a7c08cf4d548539e2eb9f422f6649658893a7c3c25a4fc901f8c398b8c72733911a0072ed6bd2f4189389ae10a814f648d71f69c37e8295784428183b93c8013b964a9fef86b48f489316bc222e96b3bd15ff149b96820329551c15e0d095d1569b1e2131c78751565c3041f29785395b97151317f62e3582e407b1649e60d03a8599120a302a4695fa862b4120f94d22ecae72398d2094d108ad2dbc1b959735902142aa5fe6e7996559f6f601448aea02f356f8dcdd144340eb3619f9865bf7672aea326c4e93c99f0ed1f9ed866be15d3af2675f6dd6e296602ca373a815b0be46bc2a3fbba06b8805c731fe08007daa06050961b24d14693a72898ccfb8b8fedc60a4eef8ff79b6dd7592591833b576ef48294e5e0485942e57c119602eddf88b1faea517f2fc2e3d14d246a52cbd71a108c66b6cc4f2d45804a282ecedb1b0ad3dc3b4880ab2ff78b8ddde48f7466c14fed349e95b5053abf1bf0991126031d97547d143c2ae164928b61c0708af8ca3e4f55154d13d75e97db4ba3e69d36e9b37082368c2f721bd3f95126a1e004eb2a1bf268343ae21d2995044a2cadd67ffac9e1538175b3cc44db5d26f1d5cc89ca0e1c1ee8537a8a91d324c2e02e18b9fb9730d6dda55f72d843389693ebfcba7fbe1a0bcffb9aa284f4ae66f44a8b89302983b22736d0c72d6a044e4291624243a4e0ce65d5e5346d67fed3760ddb0c510b50ff3eef0a18a267de730476dd82dff7072cba0984825a004dd4bcd8c37fdaf1f683d1d9380e135a95d24b89fad0be941c548251bec90ccae015bc0567da84b371e50: +080d7f76182ee6bcea894b1e0060558b3b125a3499df3973b8dd6693408ee4694124713d7c2df50f93055730d1b281daec3028cf2c1e4858d128707a23d6deb0:4124713d7c2df50f93055730d1b281daec3028cf2c1e4858d128707a23d6deb0:ab0a6de2351b9a8498f68272d9a0a7a057365d34efa0fd34cc3bf862e49cdc302b2bd5a30d601a130ec4032f541ae6cb7ba97f84183d2d2581287ca701d7d7a9aba110ce58b946ac0824305df7929f3dd7fc9c8732238637e2b181d6e116c7f66e3226aae3ced1610262da1a0a4aa50a1b9443ec828329e4734d28fc25ab9c1de9b8987e5dc0c8131916c5f18928704a71e80622b1492bf2fec5d4b6dbe415c8af2ce3ef109b34dd5e64d56846f085935a4a5d1073497fb3fb8fb77e8f5d5e3fd00c30652e3c5cde40a335d14e5425ffba942885ed17bd36df506924237e75be84da821950b91424fd9f16c1b2c783e90f8cc2ccc7980ce915c7696b06a586730259e6d14588582bab9d2a39f69e98e7f2ae9bc0c2610d7e0457f26a5d66543be1d65b79c4b7c0d8ee73d0c2b67bf50d8082f006f96d119505873193dfdbd432bb1c9ee0d03ee54cf95d20e91f7f3a069b6256f42159cdc1e600a9a1c2f5a8e467d5c2a9dff8730e6be826fb2a1e6448bfc4fcaaaacdaa7662351faadc91f7caa7737dc82ec3d4b21936bca1bd7ce373ad66264af13241167549318cdd78e563827f85eab20e0b42bc554a712c0051a5010dc2f2c7db85acf6549f9d102c903c1be5a05292c30f21ab1b2b8abcbbf104723c63f0ebc554fbee42020ccb14f443478df77c6aa44db9a57f8fd44d97ea099e4774823ebe123fcf5016a66e837b2f65c1845e681ee2a7059fb1290cd0a933129855cc83c87e0b3bb61e44134addd3637850246cdcdaa29f15c41a3d4dd2c1d760062124333124cf091435fdce711f52316368999befa4c80a39b3750e4e386289e4e2855e97b619b0a25799912408b7d58a4dd9819571e901430f6d555529dd630a1867459b8022d0e0add6ab4f12f60baac75979bbff7f6258d28d6760b1ff243c39e4bbd6cf9bea572a9c082d05adcfd4ccf9fa026f2c904b6e782ed709df7748a307cd2dc3a0fc4123df580cbf49e05ceeabc9f39e57b7f300905d8b310091fb953f3def36deb3e8bf372f5916b51597df024ce85cc4c36eabdc580b5cf152994648f1d7f35fed5cd10f6e2949161a3359b3034d450ea6f61cdf1d5af76d40102b60294f4e49078249026d62fe35fdf224928b0c49ba2b5339ebb192c5ab7f05cdb946e37d671a4a5ef2a5827220b4438cbda05736292806648f5bdd52420fa76b84a6addb1263eb0c500e81566d718d5066026da097054a86631016ddfb706a5677d502ef84aa73b5863bc40fdc42cb7321ac5f00e2928fed7b0418596db4b6151dd6bc6e818f0253552bf13741e69680e966c92c293e13c90f7c9999bd1ec6afe3b4affb47340c89859829feb599db3a8c3d33fc8d45fa5381078ae9f75d85c1496f5fb5addf4e4009b764bcc9118e9275dc7219f281d0d1ef7158:185fb1b6d86dc4444810cf5ec6fef0abdafa2a6fccb45d11cfb54ba16a6843f280d380471002ae0d71508556c78ed5415e42338c161f2b621e74cba4f6a1d402ab0a6de2351b9a8498f68272d9a0a7a057365d34efa0fd34cc3bf862e49cdc302b2bd5a30d601a130ec4032f541ae6cb7ba97f84183d2d2581287ca701d7d7a9aba110ce58b946ac0824305df7929f3dd7fc9c8732238637e2b181d6e116c7f66e3226aae3ced1610262da1a0a4aa50a1b9443ec828329e4734d28fc25ab9c1de9b8987e5dc0c8131916c5f18928704a71e80622b1492bf2fec5d4b6dbe415c8af2ce3ef109b34dd5e64d56846f085935a4a5d1073497fb3fb8fb77e8f5d5e3fd00c30652e3c5cde40a335d14e5425ffba942885ed17bd36df506924237e75be84da821950b91424fd9f16c1b2c783e90f8cc2ccc7980ce915c7696b06a586730259e6d14588582bab9d2a39f69e98e7f2ae9bc0c2610d7e0457f26a5d66543be1d65b79c4b7c0d8ee73d0c2b67bf50d8082f006f96d119505873193dfdbd432bb1c9ee0d03ee54cf95d20e91f7f3a069b6256f42159cdc1e600a9a1c2f5a8e467d5c2a9dff8730e6be826fb2a1e6448bfc4fcaaaacdaa7662351faadc91f7caa7737dc82ec3d4b21936bca1bd7ce373ad66264af13241167549318cdd78e563827f85eab20e0b42bc554a712c0051a5010dc2f2c7db85acf6549f9d102c903c1be5a05292c30f21ab1b2b8abcbbf104723c63f0ebc554fbee42020ccb14f443478df77c6aa44db9a57f8fd44d97ea099e4774823ebe123fcf5016a66e837b2f65c1845e681ee2a7059fb1290cd0a933129855cc83c87e0b3bb61e44134addd3637850246cdcdaa29f15c41a3d4dd2c1d760062124333124cf091435fdce711f52316368999befa4c80a39b3750e4e386289e4e2855e97b619b0a25799912408b7d58a4dd9819571e901430f6d555529dd630a1867459b8022d0e0add6ab4f12f60baac75979bbff7f6258d28d6760b1ff243c39e4bbd6cf9bea572a9c082d05adcfd4ccf9fa026f2c904b6e782ed709df7748a307cd2dc3a0fc4123df580cbf49e05ceeabc9f39e57b7f300905d8b310091fb953f3def36deb3e8bf372f5916b51597df024ce85cc4c36eabdc580b5cf152994648f1d7f35fed5cd10f6e2949161a3359b3034d450ea6f61cdf1d5af76d40102b60294f4e49078249026d62fe35fdf224928b0c49ba2b5339ebb192c5ab7f05cdb946e37d671a4a5ef2a5827220b4438cbda05736292806648f5bdd52420fa76b84a6addb1263eb0c500e81566d718d5066026da097054a86631016ddfb706a5677d502ef84aa73b5863bc40fdc42cb7321ac5f00e2928fed7b0418596db4b6151dd6bc6e818f0253552bf13741e69680e966c92c293e13c90f7c9999bd1ec6afe3b4affb47340c89859829feb599db3a8c3d33fc8d45fa5381078ae9f75d85c1496f5fb5addf4e4009b764bcc9118e9275dc7219f281d0d1ef7158: +49846ada7ae684971dd91710799090b37fe5ad561d72a35f2efb405f196ab0ec4d370a8194a3045b09b3bdafa27fb9acd59943a54ae14cbaaa2200eb0f3da71b:4d370a8194a3045b09b3bdafa27fb9acd59943a54ae14cbaaa2200eb0f3da71b:ab398d94f928b1d42102a3e513ccd1cb10899011039410a8888bba26df1a0372bdba0ce8d854af51e9330a8daa93c10580906a8ac72d294aeb9566fe1c78ba8471c06c4a8a75113b34893f6276ed813292053b956a465d847d2ece86e2da8a9f0fe3db52a5aac746ef96485ef81f1362b5a42eaaee1fbb0646704471a21bf76367beaa07812b3d32adcdedded7539e3a501b83c05b19a49b520ededc9a78a5fc2d5012f1d4e381844e792ed90b0f57bce375c75a658b2c78c6ff7d9efcd4bfa35c4768cbb195e4823d9bbd835a374fa04ca1eaae9c566d8fd5aa7ca5efe0dfc317fffa409ef1022f1c3b376a935af557083e95287b07a98ac6c1b7bd8bb26b60fa7c4bc91973b201b29922b4b9d03dd6882a0bd3b7d9e5b81ee74c36bec665e4343c8c9ad336da3850c9b2697fe1cce29c378622a33c248f448c88f48df0260143b2a342f1ddee74d3b97ca3e1166b156993dad30c49d810d74048bc6d467652004d7edb65c6dac3a2c5d300b97ee3a10a9e14b69f3cad675972962e1f8ed97547adedc47d1cf3471ef3b22fdbf78e34f31a3bb7669c41bd9292c380bce9a42d84bc27ac928b8bfc3c63d20ccdb478df7ddf421fb1cd905ffc4c04786fd9aef06b8938ab8ef522217b2c04515f61a1c312ea83253f8458c0918fcfe874e6e7fb11275db2a2ec79a2d868303233c1b697952a3bfd3ad0a6f6cdd5e72cc9409f7410a40d5b4536dd46eb1611ae86703671b3a0515a0377bea15654ba0a0d1e4e9602632842f2acd4ef993236e993f2650d59923f24e2cd30932d8bf8aeec644472ba46a07881496c92a0135c675aeb0ce6181088db8f156cfe7435cac6c97da637db4a89f51331da13731e741fccc0355542ce11efa69d0538d3ef127aa68745ed3085d29da90dc583701b6b3a70a3ef3e16a924b33203b92396c4b945f127a7888fa05015c0603007566729237cc0782b30c020d9959547feec9f4d676460bfe0c5c19ceabaee0682db8be69135181ec0fdd9f7a66d50bdc379e4a2c598178f9593946aca6405b177fcade0f86421583ed67eba187222a1e44495b3ae544fdca28e2c14485eab0471aaa803c29a9d8a48926764fca1df51407ad33ec17e941e6e2617237a84309873dc71365587bde4274b5dc327ccb1e1e9c857e042ccca8d8552ba288c978cfa0af99d67cd034060628e23525dbca207679ce29690878448553cd38675bce07bf97b9317dc44468b768b158b0c111d63a572235655c40e16597ca059f40c3d8ac5bd61a487c15313846a704a7811b8bc0cee61e34762b6c1b7cea1c46e6087e9a36f89918a258b3fa77620be10c184c3fc39739024e98278fd65b82cad83699f3ad8c6eccbec8b7b1bd7914d3f6c3d02bf40283b1c1f1e98e308beaebbf894b8f5e91bbbc62535f923:a5c809d1ca4cfbb3dc70a2a3a1f267c27330420719e3606218a1471cac57cb674b9b42827c5e9a7b25c8139c13dff60bde6c2dbad3a8361197c1fb19d2cd520bab398d94f928b1d42102a3e513ccd1cb10899011039410a8888bba26df1a0372bdba0ce8d854af51e9330a8daa93c10580906a8ac72d294aeb9566fe1c78ba8471c06c4a8a75113b34893f6276ed813292053b956a465d847d2ece86e2da8a9f0fe3db52a5aac746ef96485ef81f1362b5a42eaaee1fbb0646704471a21bf76367beaa07812b3d32adcdedded7539e3a501b83c05b19a49b520ededc9a78a5fc2d5012f1d4e381844e792ed90b0f57bce375c75a658b2c78c6ff7d9efcd4bfa35c4768cbb195e4823d9bbd835a374fa04ca1eaae9c566d8fd5aa7ca5efe0dfc317fffa409ef1022f1c3b376a935af557083e95287b07a98ac6c1b7bd8bb26b60fa7c4bc91973b201b29922b4b9d03dd6882a0bd3b7d9e5b81ee74c36bec665e4343c8c9ad336da3850c9b2697fe1cce29c378622a33c248f448c88f48df0260143b2a342f1ddee74d3b97ca3e1166b156993dad30c49d810d74048bc6d467652004d7edb65c6dac3a2c5d300b97ee3a10a9e14b69f3cad675972962e1f8ed97547adedc47d1cf3471ef3b22fdbf78e34f31a3bb7669c41bd9292c380bce9a42d84bc27ac928b8bfc3c63d20ccdb478df7ddf421fb1cd905ffc4c04786fd9aef06b8938ab8ef522217b2c04515f61a1c312ea83253f8458c0918fcfe874e6e7fb11275db2a2ec79a2d868303233c1b697952a3bfd3ad0a6f6cdd5e72cc9409f7410a40d5b4536dd46eb1611ae86703671b3a0515a0377bea15654ba0a0d1e4e9602632842f2acd4ef993236e993f2650d59923f24e2cd30932d8bf8aeec644472ba46a07881496c92a0135c675aeb0ce6181088db8f156cfe7435cac6c97da637db4a89f51331da13731e741fccc0355542ce11efa69d0538d3ef127aa68745ed3085d29da90dc583701b6b3a70a3ef3e16a924b33203b92396c4b945f127a7888fa05015c0603007566729237cc0782b30c020d9959547feec9f4d676460bfe0c5c19ceabaee0682db8be69135181ec0fdd9f7a66d50bdc379e4a2c598178f9593946aca6405b177fcade0f86421583ed67eba187222a1e44495b3ae544fdca28e2c14485eab0471aaa803c29a9d8a48926764fca1df51407ad33ec17e941e6e2617237a84309873dc71365587bde4274b5dc327ccb1e1e9c857e042ccca8d8552ba288c978cfa0af99d67cd034060628e23525dbca207679ce29690878448553cd38675bce07bf97b9317dc44468b768b158b0c111d63a572235655c40e16597ca059f40c3d8ac5bd61a487c15313846a704a7811b8bc0cee61e34762b6c1b7cea1c46e6087e9a36f89918a258b3fa77620be10c184c3fc39739024e98278fd65b82cad83699f3ad8c6eccbec8b7b1bd7914d3f6c3d02bf40283b1c1f1e98e308beaebbf894b8f5e91bbbc62535f923: +83343e37ad091a85eec370701b81a58f9370a4b0423a070d60f92d8d1809844e50b68bf726eabca53ac6c90d4eac554703712d22105554f05bf79f9d08fcc493:50b68bf726eabca53ac6c90d4eac554703712d22105554f05bf79f9d08fcc493:c7dadcac5d8795e174b69138912e70ff41e7a725faf385b773ed15098972b30d9b739372d975b480ccfdfc580e2e2ddf5e3c27ee791279ab95e4382b1459dd8d41ae360d4a878846692924feef390c0dbbfa35e4b82d7cbc33ee1581c52bd949385b2ee40263a57da1174bb4acad37cd8ae2a6b45f7a6d6bbef5a798ce85b9e05e7647e334ecfc776378de174c497c0f4075e625af7aed502cd1cf7f588d0d807f02e32f4300f228a50a667b5ad1fbbc17e0b3c57051ddc602f576079f6fc5889b7f2900711334420fc666f66dbaff4126336c353f1e5b564a664537f83786da5c5627745406d7b2fe3233bfd58ef464a06c95cfd0b988a76d053a644bcc159cad53a7c5dbb40eef5cd047056a3f09265b1325699c7d159d5c902440173357ffab8f7a5e389f468c333b782f80170ae90983af153f2e73bd2bef125e3d3868c2ab9ecf03aff76ecbeb18167ca2f711cd565851d7f04ee9d9b01b6d83a7605722620d28c84d6c1af42f6a769258f53c1f66da36666da5caa9bd9e8fbc169211b1aed9c2558f6aaf5b145abc721abb00720194e027035468bde3fe0b88884f4e9b26e771e6c7a0a55ea36fc50dec8cef162f9bba5b4b16105afd6e374e038d5c8587cfd7dd88290b2c9cab45a264d6540ea1416e6e4e74a12f45a2ef13cc8a36e7b0a26b902c3d96e2e2229202e25765694b943373d16e600bd786d955a4b3f1021640c39a0b6c691500281ae0d098cc7f385e18a07e62fa4a101ef5b78551fa29bd15ee0353a1a5ef9b216e8b0fa50750a34162b635a0bc5e5d7230aa19afa128aba6422d38eb77a3f0bb9dd8e4652f12070a37361c3725503c9d22e2face2ea74a7002406247dd86975f07575c9e7c6f41b53b26d5cf52c5acc2c5d98271434e9fa509c6dfbd724372aa5c13451aae393de0a186464f5d337e9f627b4f1c2909467065e89a422ec40ee1d80a133900a62f4e4f7e94eb72615e7ec2996c6c2430c3e957ceae2105a1e90eaeac0d31affa9f57926d71d972a9a2de11258cc1e728599c9fb3872491847e10c67efaef6b696a030ff0533a583bea1d04df25f7eef3a13b8e31aad133857df1b4e5ffbdee37f40f38d224c70ae04ef33b41b02e7191a86656b0d72b2cbb53c4908ca206f75734b27708154fcd8a97429cfd1f2da2429778438003f5b5b9c21d9ed23b8ad8a228eb4f65c24c1c59699a5c90aff773e5c676db362a1930ba16aba76ef8daa42b3eb2ccc45c934d23d4929a7ad9e3ef468b06a4995c80dd236a7bcf3879d8b79467f72b3384c160cc181714e92f2035e7b972a2cc5242d932525eae7c50bd263b0fa09cbd9d6f984b9cf6152d9a133c27843202d1e87fa5a6e1235d9c756bb8e68b05b98da54195223fdf0210253250633c11c5f60b5e67d7eefcaa6c2daa523137:9c6989cbe17e16caa253ffb1a64a106fb01782c99b1722baf1acaa42ae5b36b79b2a2cd8fc91f5ad8923817025a77825a05df8c417ec53c4a3aa1c0efd5bbe0fc7dadcac5d8795e174b69138912e70ff41e7a725faf385b773ed15098972b30d9b739372d975b480ccfdfc580e2e2ddf5e3c27ee791279ab95e4382b1459dd8d41ae360d4a878846692924feef390c0dbbfa35e4b82d7cbc33ee1581c52bd949385b2ee40263a57da1174bb4acad37cd8ae2a6b45f7a6d6bbef5a798ce85b9e05e7647e334ecfc776378de174c497c0f4075e625af7aed502cd1cf7f588d0d807f02e32f4300f228a50a667b5ad1fbbc17e0b3c57051ddc602f576079f6fc5889b7f2900711334420fc666f66dbaff4126336c353f1e5b564a664537f83786da5c5627745406d7b2fe3233bfd58ef464a06c95cfd0b988a76d053a644bcc159cad53a7c5dbb40eef5cd047056a3f09265b1325699c7d159d5c902440173357ffab8f7a5e389f468c333b782f80170ae90983af153f2e73bd2bef125e3d3868c2ab9ecf03aff76ecbeb18167ca2f711cd565851d7f04ee9d9b01b6d83a7605722620d28c84d6c1af42f6a769258f53c1f66da36666da5caa9bd9e8fbc169211b1aed9c2558f6aaf5b145abc721abb00720194e027035468bde3fe0b88884f4e9b26e771e6c7a0a55ea36fc50dec8cef162f9bba5b4b16105afd6e374e038d5c8587cfd7dd88290b2c9cab45a264d6540ea1416e6e4e74a12f45a2ef13cc8a36e7b0a26b902c3d96e2e2229202e25765694b943373d16e600bd786d955a4b3f1021640c39a0b6c691500281ae0d098cc7f385e18a07e62fa4a101ef5b78551fa29bd15ee0353a1a5ef9b216e8b0fa50750a34162b635a0bc5e5d7230aa19afa128aba6422d38eb77a3f0bb9dd8e4652f12070a37361c3725503c9d22e2face2ea74a7002406247dd86975f07575c9e7c6f41b53b26d5cf52c5acc2c5d98271434e9fa509c6dfbd724372aa5c13451aae393de0a186464f5d337e9f627b4f1c2909467065e89a422ec40ee1d80a133900a62f4e4f7e94eb72615e7ec2996c6c2430c3e957ceae2105a1e90eaeac0d31affa9f57926d71d972a9a2de11258cc1e728599c9fb3872491847e10c67efaef6b696a030ff0533a583bea1d04df25f7eef3a13b8e31aad133857df1b4e5ffbdee37f40f38d224c70ae04ef33b41b02e7191a86656b0d72b2cbb53c4908ca206f75734b27708154fcd8a97429cfd1f2da2429778438003f5b5b9c21d9ed23b8ad8a228eb4f65c24c1c59699a5c90aff773e5c676db362a1930ba16aba76ef8daa42b3eb2ccc45c934d23d4929a7ad9e3ef468b06a4995c80dd236a7bcf3879d8b79467f72b3384c160cc181714e92f2035e7b972a2cc5242d932525eae7c50bd263b0fa09cbd9d6f984b9cf6152d9a133c27843202d1e87fa5a6e1235d9c756bb8e68b05b98da54195223fdf0210253250633c11c5f60b5e67d7eefcaa6c2daa523137: +da013221b2f588af40e211a0f975d44f9d65028160514c396189f27c7b0666ea07117c6b0db5b6fda1edc4396c47c22b54ee0ce5375c3ec633c83afc53ad6ce4:07117c6b0db5b6fda1edc4396c47c22b54ee0ce5375c3ec633c83afc53ad6ce4:bc93ee1ec4728ac636a6248fcc4551c9d15980db8e5f54b0ef075a71970e176a3cb9182e32da7a8c2ac0cd7e595774575f9c83506a606face89512135d032ab05e39fff9c8ca6c25cd5d78ecc3ac323290c9c81626735e190eb5ae345ca7a958409f7743b0b1614916832217c57eee1b4f8e622ac052a93dd5b39d0761e40e9fbd8396f60a3bf6660c5fa99cd8139f68cbe0894e5c67e168cc74b2724e9d91d6000a0cec587a11463f72ee6ed255bd87eb30fd457596f688ca0ea73f30497238de21c93fbb1294db61e4a56089106d1cf7ce5a65ec3d12170ce7840f088a8d0e3aef17e531de478003570258e927f156e7961065afa666af38582b353cc477ba775cae45946d08db75215914da3261b62294e92afb381459c21dda4ea6ed795f79257c094dd608dc8e1b7c40cd29fea222088f65697ea88895d10acea8797360dcbacee269c606600adffdcf9c7c381d0ad6696967d9ff03e61a24906502b295e76f4d0875655b01e6ffcacc8ef01129c72a5846b60ec80017374e75d306403d9eccf26495d298120a0633835c5d1eff17c9c62476f752c89710adfa4d51617b5918173cba722540e388ffbffb966874db00404d06b0ce1139ba74143c76b8f4d33b2116e1cce175173a96fc151ea239bfc20d66fbb6f52a666c0e81cc2b80209106e2480e4111c70e7be4aabb68422f0b8c6ba15c142f82e6c7f378d7800a09eaa4da253c2fd91e1263c6b655bf70255d7e3bb4775523a0a9e7ff03797ee3ffca8a50d10f20d5e5a889ec5e334ef26cf7998b0836f656456888e137f39d3e43e2ce3c6ef540d95d9a20c42cb8ae2d9d0f25a891c363ead9cc423f9a323fe232281fb67f5be1c0784361460468a87e95dfa35d7f0ffa2211be6b5fb32d42ba6518ab6ea93780f431d3006731be4440e712974f74baea419f4022fa2502e1b2398e9386167d93eca92ca60dd7d91fe82324f682d94aa7a86ab034f8a9e952e8fc95bff4dfed6a43313abb92401b30c33c79a7ba3efdbe1628040fbaf443f3f980846fdb283dccd93fab09708b7d54861d74b1fe8f10701f211ba3d390e8a6ae407739646a79a58337a717a872009c2df6761c2425a32a0018aaf9646470cbc87c3a65c0e0effbaa528fe4783c772ab266b8f28268cf14af234b15816d1a3a491af5f297e33d5729715d512c373fef5ecc3f3954a60a2a0f64d829474119ca1a18f10578d04d638d5eeafc371a946f6ce7efbd2acce34e20441cde9a37d5a87dc619b0a727596cd12e15cd9784bb91f1399a59fc0a7a4af68b0d575d93387172973375c465df5d2d5e061a2a9b23b4915a0a8b8c1f0942094af728c8c31145fa7aaf74a21a3b032bb09c392205bf095bda986e5dd6627c1e417f650326dfe3a9c9994c6e0e01276f91f2987d2b85deda965491:10cb52d610e4a81d32869bffce3807e6391f782fcd538b554d09037fda72285b9662b1b1107c408178ac009f0525967388a7d85fa12359d3ce3875037dcf6a04bc93ee1ec4728ac636a6248fcc4551c9d15980db8e5f54b0ef075a71970e176a3cb9182e32da7a8c2ac0cd7e595774575f9c83506a606face89512135d032ab05e39fff9c8ca6c25cd5d78ecc3ac323290c9c81626735e190eb5ae345ca7a958409f7743b0b1614916832217c57eee1b4f8e622ac052a93dd5b39d0761e40e9fbd8396f60a3bf6660c5fa99cd8139f68cbe0894e5c67e168cc74b2724e9d91d6000a0cec587a11463f72ee6ed255bd87eb30fd457596f688ca0ea73f30497238de21c93fbb1294db61e4a56089106d1cf7ce5a65ec3d12170ce7840f088a8d0e3aef17e531de478003570258e927f156e7961065afa666af38582b353cc477ba775cae45946d08db75215914da3261b62294e92afb381459c21dda4ea6ed795f79257c094dd608dc8e1b7c40cd29fea222088f65697ea88895d10acea8797360dcbacee269c606600adffdcf9c7c381d0ad6696967d9ff03e61a24906502b295e76f4d0875655b01e6ffcacc8ef01129c72a5846b60ec80017374e75d306403d9eccf26495d298120a0633835c5d1eff17c9c62476f752c89710adfa4d51617b5918173cba722540e388ffbffb966874db00404d06b0ce1139ba74143c76b8f4d33b2116e1cce175173a96fc151ea239bfc20d66fbb6f52a666c0e81cc2b80209106e2480e4111c70e7be4aabb68422f0b8c6ba15c142f82e6c7f378d7800a09eaa4da253c2fd91e1263c6b655bf70255d7e3bb4775523a0a9e7ff03797ee3ffca8a50d10f20d5e5a889ec5e334ef26cf7998b0836f656456888e137f39d3e43e2ce3c6ef540d95d9a20c42cb8ae2d9d0f25a891c363ead9cc423f9a323fe232281fb67f5be1c0784361460468a87e95dfa35d7f0ffa2211be6b5fb32d42ba6518ab6ea93780f431d3006731be4440e712974f74baea419f4022fa2502e1b2398e9386167d93eca92ca60dd7d91fe82324f682d94aa7a86ab034f8a9e952e8fc95bff4dfed6a43313abb92401b30c33c79a7ba3efdbe1628040fbaf443f3f980846fdb283dccd93fab09708b7d54861d74b1fe8f10701f211ba3d390e8a6ae407739646a79a58337a717a872009c2df6761c2425a32a0018aaf9646470cbc87c3a65c0e0effbaa528fe4783c772ab266b8f28268cf14af234b15816d1a3a491af5f297e33d5729715d512c373fef5ecc3f3954a60a2a0f64d829474119ca1a18f10578d04d638d5eeafc371a946f6ce7efbd2acce34e20441cde9a37d5a87dc619b0a727596cd12e15cd9784bb91f1399a59fc0a7a4af68b0d575d93387172973375c465df5d2d5e061a2a9b23b4915a0a8b8c1f0942094af728c8c31145fa7aaf74a21a3b032bb09c392205bf095bda986e5dd6627c1e417f650326dfe3a9c9994c6e0e01276f91f2987d2b85deda965491: +5a868fb75ea0721f7e86c7bc106d7413c8cf4d033ce14005df23ce4c155bbd276d1e29f39deda2bbfbb57cb01cb39e58808278e5196ada1c027646f20487d252:6d1e29f39deda2bbfbb57cb01cb39e58808278e5196ada1c027646f20487d252:d5aa11825b99448c80630623d8c746017cfe3de6fa8a0c6ed6627127cfc1f84d4e0a54e6a7d908d3719f1421d1d4c78b3cdd94769ab6033bce979dd90e106802eba9a03295d48f9b9a95d57ee7745402a48023bf3bddd5c6b91c773e491913a38ac3462605cf282deac75742fbd27529276e81dcce8dff9605035e8cf05df6a43db151f0415765bcbd1f1bb668ad6273b891c0dc4f3dba590ea82f8363769b9c77511947117375dc4904d48b88b68a255b28011b11048194093e98207ab1cf756ab8331f8d6f9d5be2e1190573e95e710f2a3501b53aa0825d6c12dcfb94ac80dc1082cb4ad262e6d493adceb6bc19145fbf738df76f2134fa04cbbe44ffc55ffe5f9d3e9bebd159a001aa9bf78892a16538a520823cde5d61e29a56a77ab96e49e300d9865962c7e7fb8bcf5de0b938297c3f4d6f6021e24dfdad9861652f340f421e7af2c71ed9a71587fc753b115549b2f7f7cb29690ea2b158a94cd2bc42e7063d619b939d523e3c237eb1f40810de0b44aa6937863d629edd5575e6c0475261b627473092775c84360011d57c57209c2e875a3f8963e8b241a7aa75ef30c4a718ac4dd466dc7a3e40e5874f157a849ed3a3a9d4aeb7d94df09bb55a0b2bc9f8b695c37179302367606367c5f324828ce75a944f50703a47906a8088f3a11cfe4a854e01f1741252c486337d06b1cc6c6b9b1295431ee07359357b3a78ef5075b65d7fed5eb742e5101598444b46623f89a303acc10c732449513b70dc456a79d37c48e5e726c2f558da0a1c46efbd2d920326a678b8a22f0944be4af55b6c71f453fbae400e6acc04e0e95ca200167e96ee98ea839316da93a12c2d76f11aeebeb78e65ea48f7feebbb137b2ac67eaef02a2d9e6471dd634a037d4f5d35a2f78af41a8ea5af5bc8150a99ed68a6a0ccff2b1d7965d8bc3ef9285ba6421d87c33aad8103a587be01926845bfbddbafc69c4b9252886720d418509f40f3dcf55765dccc3deed8277215e69f056ba31b8a30b50094ea8f144720760c8f8c055cf1a86964ffcbb8ee1bb2181276ea99a7b8e71067fa310ba4471e84279037bc492a55de205548e77b014504ee6664c4988cbb9ed91ff32e2259ed4cfd61a197d0dbc32c68f6549c0d29fc45f36acb26b164de97ccdc37900d93cdbcf9687ef53f1f4da1b1ae4225b884209e81ba4311520477ed4211b09240bd7b825e54739fe25d8624af04b86f6d1106d18170e5064d1a73c1fb1a27b289a948d771a2f6b8b09a635db96c6251c35a1876d369626699416c0e40298a681fdaf5255f58c2557759d8f5df148dec9dbe1ce6df041c36f83e69ccfb4aaca5cb48fa6a85c8ff66061524d8b11bd7ffaed99d0cd45c42010f21d36cc316ca860955635bffaa7d9aac572dccf3153d42ee8a2b12baa57c160bd0ad:38c48dba99a6524a188d5cd78a98e677dd263ef6b4df446b310b3dd89cafddb9b17a65bba8e13968bdc25b1d84b6e2436edf31aa756e3a48726d6f91c808ee0ed5aa11825b99448c80630623d8c746017cfe3de6fa8a0c6ed6627127cfc1f84d4e0a54e6a7d908d3719f1421d1d4c78b3cdd94769ab6033bce979dd90e106802eba9a03295d48f9b9a95d57ee7745402a48023bf3bddd5c6b91c773e491913a38ac3462605cf282deac75742fbd27529276e81dcce8dff9605035e8cf05df6a43db151f0415765bcbd1f1bb668ad6273b891c0dc4f3dba590ea82f8363769b9c77511947117375dc4904d48b88b68a255b28011b11048194093e98207ab1cf756ab8331f8d6f9d5be2e1190573e95e710f2a3501b53aa0825d6c12dcfb94ac80dc1082cb4ad262e6d493adceb6bc19145fbf738df76f2134fa04cbbe44ffc55ffe5f9d3e9bebd159a001aa9bf78892a16538a520823cde5d61e29a56a77ab96e49e300d9865962c7e7fb8bcf5de0b938297c3f4d6f6021e24dfdad9861652f340f421e7af2c71ed9a71587fc753b115549b2f7f7cb29690ea2b158a94cd2bc42e7063d619b939d523e3c237eb1f40810de0b44aa6937863d629edd5575e6c0475261b627473092775c84360011d57c57209c2e875a3f8963e8b241a7aa75ef30c4a718ac4dd466dc7a3e40e5874f157a849ed3a3a9d4aeb7d94df09bb55a0b2bc9f8b695c37179302367606367c5f324828ce75a944f50703a47906a8088f3a11cfe4a854e01f1741252c486337d06b1cc6c6b9b1295431ee07359357b3a78ef5075b65d7fed5eb742e5101598444b46623f89a303acc10c732449513b70dc456a79d37c48e5e726c2f558da0a1c46efbd2d920326a678b8a22f0944be4af55b6c71f453fbae400e6acc04e0e95ca200167e96ee98ea839316da93a12c2d76f11aeebeb78e65ea48f7feebbb137b2ac67eaef02a2d9e6471dd634a037d4f5d35a2f78af41a8ea5af5bc8150a99ed68a6a0ccff2b1d7965d8bc3ef9285ba6421d87c33aad8103a587be01926845bfbddbafc69c4b9252886720d418509f40f3dcf55765dccc3deed8277215e69f056ba31b8a30b50094ea8f144720760c8f8c055cf1a86964ffcbb8ee1bb2181276ea99a7b8e71067fa310ba4471e84279037bc492a55de205548e77b014504ee6664c4988cbb9ed91ff32e2259ed4cfd61a197d0dbc32c68f6549c0d29fc45f36acb26b164de97ccdc37900d93cdbcf9687ef53f1f4da1b1ae4225b884209e81ba4311520477ed4211b09240bd7b825e54739fe25d8624af04b86f6d1106d18170e5064d1a73c1fb1a27b289a948d771a2f6b8b09a635db96c6251c35a1876d369626699416c0e40298a681fdaf5255f58c2557759d8f5df148dec9dbe1ce6df041c36f83e69ccfb4aaca5cb48fa6a85c8ff66061524d8b11bd7ffaed99d0cd45c42010f21d36cc316ca860955635bffaa7d9aac572dccf3153d42ee8a2b12baa57c160bd0ad: +c54bd3431f2659281d31e93b30787668bcba6e5ee47db46e50deabe3f48c9ed81eba6eb3f7f24cdf80abf8a19d308c24f1e25ba15970eda7116707b0f12cf932:1eba6eb3f7f24cdf80abf8a19d308c24f1e25ba15970eda7116707b0f12cf932:6f8cdd75e1b856bbbe9cdc25537fdf7e8236cb029acd3984492110d0c30441d42184b5fb183da9f3140378dfa7d74ccc9ef500193cc9579fffa60bd2a8ab9e09581500cf06cd35abc171d9d12c6580d9682f9f49fe36d0a3177238fa50e7eb4c27e460f5e4580a56568a19e03d95b0ff4f4a231824cd2f3442e0ba400bc11b7a989d501f5df35e4301508f72a852014bfbf4001e28095473d9659eed6067baf68f92bef312c09b19aaf7c4fba3d902b9f6cf952eb9b9a53ca8bcbd042d842e9853b672a1d009d823838bebe5637c4c07ed1b1948554b23b32de1d6c116f933b354f28bbb779fa6548c48292b612c7f551a75fbc46c02736bf99e9c8ead56f05ab0427a6ec616e3dcc7757efdb7628d4e96325fe0ae254cef5cb7a704b35a920cb3fa2a03e961daf371821be0b30f19ae4952441e08a7d22f5431390a5be8097fd5797a1a6297664da42c2008d0321060ebe3181eb795a728925808da7867293b7208f377d3a771185e6d2c1c8ce18376fe3c0c1458c7f5be34f428a0d575931074c97cbfce8ad81313ecca73a9f3db434fbad4bbbff502bf7297e17a97a8864211e6789ba192036ea59a34d84ff2a111074c3f2373b10111b5daa789560cb35490954c88ea00c410df850ad00cae2f28e719fb06716988a9bb0bfc6c989d587e5685ae883c2c2e74ddbf915c9856aae8f3288fc625bfb2fe268d74f59f8b7d8363749769169007d5e67b7d0b8c8f5a9d9f9c7b745c0a4294762cbeca42d5384961e921a7efb65da8d1e03b6745cdf308097fb13d64fd2f8c10fa9509eb2d91387f00645ca7d0483b2cd14c206b8d7ae0a3fb7c09bc6843d102adcda19f8bbd851eb683c4435ceb4b3d23d38f56d4d1114eef0fc6f24df52770d8f1f3f82f4720e892b315244ef56c36b23fcd407978524140382e11740fd46fe4299923f52b88b4a9cff4b2b4b23a2e760ad81c78ba876931d9aaa4beed40fb10a799eb30d37f754778bac85bf0631d852be7d74a6431f384a4025c1091421d67a4e9c94c1be3690c6bf81d06bdaf32feabbaf1dc263f273a0b9ed65460baefcefcf6acccda0edd23df9e05128e29d661c4b44bd92d640faa853afd8370e563b40ae0149a1428e06e3dd8e66b79da21cc753ddc476e3d76e2f36f2b6c6bc1b65087d5f86c8ac354711a8c08f3486e479d6ae943f8846332d4e5b4bb2e8257e3083df4f81dd4f0c1ee1d97182166161a18597ee0b959de1c45591abf7c51033d7c66352deeb682e777aeae2fa8d3a77f470db78ddc1b1fc82840c4065776d9bfca9d392d9288ee9132aa3e4f2d19d0d93e01b666f3647abaf225c292419c8a82eba3e11ab103846fcd4935f41241477c0f152b7965ad54bb72bc3de2e0b79d6225e8fa7a6286b5fccbb35822e80c8bfea74cb48a22d241385395c2:df4541dff1a9797feb617f98e4b57aa7714131ee8ff545ed5082e3568efd1c399cdc56f5582991eb8785fb33864eef7f553f3e248262ed548a1a6888f92e920e6f8cdd75e1b856bbbe9cdc25537fdf7e8236cb029acd3984492110d0c30441d42184b5fb183da9f3140378dfa7d74ccc9ef500193cc9579fffa60bd2a8ab9e09581500cf06cd35abc171d9d12c6580d9682f9f49fe36d0a3177238fa50e7eb4c27e460f5e4580a56568a19e03d95b0ff4f4a231824cd2f3442e0ba400bc11b7a989d501f5df35e4301508f72a852014bfbf4001e28095473d9659eed6067baf68f92bef312c09b19aaf7c4fba3d902b9f6cf952eb9b9a53ca8bcbd042d842e9853b672a1d009d823838bebe5637c4c07ed1b1948554b23b32de1d6c116f933b354f28bbb779fa6548c48292b612c7f551a75fbc46c02736bf99e9c8ead56f05ab0427a6ec616e3dcc7757efdb7628d4e96325fe0ae254cef5cb7a704b35a920cb3fa2a03e961daf371821be0b30f19ae4952441e08a7d22f5431390a5be8097fd5797a1a6297664da42c2008d0321060ebe3181eb795a728925808da7867293b7208f377d3a771185e6d2c1c8ce18376fe3c0c1458c7f5be34f428a0d575931074c97cbfce8ad81313ecca73a9f3db434fbad4bbbff502bf7297e17a97a8864211e6789ba192036ea59a34d84ff2a111074c3f2373b10111b5daa789560cb35490954c88ea00c410df850ad00cae2f28e719fb06716988a9bb0bfc6c989d587e5685ae883c2c2e74ddbf915c9856aae8f3288fc625bfb2fe268d74f59f8b7d8363749769169007d5e67b7d0b8c8f5a9d9f9c7b745c0a4294762cbeca42d5384961e921a7efb65da8d1e03b6745cdf308097fb13d64fd2f8c10fa9509eb2d91387f00645ca7d0483b2cd14c206b8d7ae0a3fb7c09bc6843d102adcda19f8bbd851eb683c4435ceb4b3d23d38f56d4d1114eef0fc6f24df52770d8f1f3f82f4720e892b315244ef56c36b23fcd407978524140382e11740fd46fe4299923f52b88b4a9cff4b2b4b23a2e760ad81c78ba876931d9aaa4beed40fb10a799eb30d37f754778bac85bf0631d852be7d74a6431f384a4025c1091421d67a4e9c94c1be3690c6bf81d06bdaf32feabbaf1dc263f273a0b9ed65460baefcefcf6acccda0edd23df9e05128e29d661c4b44bd92d640faa853afd8370e563b40ae0149a1428e06e3dd8e66b79da21cc753ddc476e3d76e2f36f2b6c6bc1b65087d5f86c8ac354711a8c08f3486e479d6ae943f8846332d4e5b4bb2e8257e3083df4f81dd4f0c1ee1d97182166161a18597ee0b959de1c45591abf7c51033d7c66352deeb682e777aeae2fa8d3a77f470db78ddc1b1fc82840c4065776d9bfca9d392d9288ee9132aa3e4f2d19d0d93e01b666f3647abaf225c292419c8a82eba3e11ab103846fcd4935f41241477c0f152b7965ad54bb72bc3de2e0b79d6225e8fa7a6286b5fccbb35822e80c8bfea74cb48a22d241385395c2: +ea60da0179bcaf6b218142b1119046ffe6d85a741b0d166230bc6de3304f6773506b2ebb49bd9b9ff66e6b7b1fab9668cb181b4fb5e4343dddd3f8a9d702031c:506b2ebb49bd9b9ff66e6b7b1fab9668cb181b4fb5e4343dddd3f8a9d702031c:612d6ef6e4349ffae516e983e8fa7b52d9fd134282240d95143824bd4aae03234b76a8cd6d4068cf009e481c2685361c755042c4e6ab8703ecbf8f020cf5739a4c2a03c3731e9cf75aee25966153b9711515c6c39afa95f221ac3395b089c97ac9b514e17d55f796a3ecc135faaaee907aab1029647b48ac81749bab26627cf7095d74c2fcee35671c8bb46053f5151b0c2e5dabe0f2d6aa20413305020b2afd9ee3387b2c9ed0bc3fe2902af4100cec23327b0f1e4ca39ef6eaf6fdf5d5acf93fc868536d8cba401769329fbe93effc7ee6bf93a6e588bd551eaa512853952c81b245e5d229d294e41370b867808667887a6f9eba2a8d56a7a704e66b1c02f96e73895f483e44a5c566cb1af26573bfe2afce06b1fb5877e51ef3126a3f210fbf213ed65d5ca46c46ce4aa945bd8ca611e3836250f564f7ea35423982f9705fcd6bef46ae16cb0f6bc912c3f28642b8d87775b818e4e4e8061167899bd27a7e2fb8187ee9917d2d586bf9d499e8fabca83ddf58c7437eaacec4f444fb2bf745dccd8cae38944571dede2037dc41f0818a3d91e3020a7274c6674247876083d0e39746c9684061bf74ad588436ce1b763dbf4bfcf8de6e35c5a7626675c127292b21df3c16f81063322a75f3438886f1f0cebfc1a96f41384cbdd861b04f519ff6a9344d94f3d3a0aba8409dfcf18d01f2b5b455171639eea77dee706ea83dcd2b8b1fc5ec0d740761a5f05f7ec8d87ad1f292a50c8bae0ad32b03419a950d9fe3b3ecc4d8d3aa95e02b51b1831d83eadeaa44238635f9c65efe2f6744a70b9ae41ef15d97908c0533934412f79583d0e9b3d706a128e88fb51eedb65e46d8a2b38bbdd6455554967a8dc0c68bddfeae0f8f72f0b886c3c741fac4f91e5c491dbae9da4594836cf1d9fb6ee130025089aed350ef247bc9887a2050159dded1428ffd9b07b9ec2e3d4bbdc2ddb54e873b63f2475233e19133a14b6658509457008186d6225995a96726b529f44281aa24fefd1cff8f815d93a5986931662290b3ee16833c60f0afcef2cbc000623f3931909ca976a094e2b0fdb7dcf7c485e14988a36f19b66425385f5632cef65d1d3414623ae3ee816e763a5f606466622be6602114502951cf0c097c1648a72e2c43d9afa9689f2c3cfe026cdce3bd1bf9ebf777562ecd8ff1b0d775306d900443f30a843310b8de6a38ff108b723913d7899b9fbe7c3d766ef8bdfb6d8b0b52956cb1cec9936d70b487c01440a842b2fabe38e7b8851a387d358be7ef12a7e4f2b527e83090d67eb013c9c2cfd3de5a1a3f99748a41f4819d9036e500c504c988bfd24f617d6ebdcab2ddeaa61579414f360b469a33a6ded96ba1d8c140c4ffc94990d8adf78cd38780bd68663d1a0ee33f537cdf892d562e82dcd1d912cad38d65567d291406:27fb6b5f06528a64198a3e7d67c738840a8cff4b482b4d524b122d17d2aebcc0389be2c6e28e2cdfc484c18de425db56cdfa561c507cd970602d3a385d3aea0f612d6ef6e4349ffae516e983e8fa7b52d9fd134282240d95143824bd4aae03234b76a8cd6d4068cf009e481c2685361c755042c4e6ab8703ecbf8f020cf5739a4c2a03c3731e9cf75aee25966153b9711515c6c39afa95f221ac3395b089c97ac9b514e17d55f796a3ecc135faaaee907aab1029647b48ac81749bab26627cf7095d74c2fcee35671c8bb46053f5151b0c2e5dabe0f2d6aa20413305020b2afd9ee3387b2c9ed0bc3fe2902af4100cec23327b0f1e4ca39ef6eaf6fdf5d5acf93fc868536d8cba401769329fbe93effc7ee6bf93a6e588bd551eaa512853952c81b245e5d229d294e41370b867808667887a6f9eba2a8d56a7a704e66b1c02f96e73895f483e44a5c566cb1af26573bfe2afce06b1fb5877e51ef3126a3f210fbf213ed65d5ca46c46ce4aa945bd8ca611e3836250f564f7ea35423982f9705fcd6bef46ae16cb0f6bc912c3f28642b8d87775b818e4e4e8061167899bd27a7e2fb8187ee9917d2d586bf9d499e8fabca83ddf58c7437eaacec4f444fb2bf745dccd8cae38944571dede2037dc41f0818a3d91e3020a7274c6674247876083d0e39746c9684061bf74ad588436ce1b763dbf4bfcf8de6e35c5a7626675c127292b21df3c16f81063322a75f3438886f1f0cebfc1a96f41384cbdd861b04f519ff6a9344d94f3d3a0aba8409dfcf18d01f2b5b455171639eea77dee706ea83dcd2b8b1fc5ec0d740761a5f05f7ec8d87ad1f292a50c8bae0ad32b03419a950d9fe3b3ecc4d8d3aa95e02b51b1831d83eadeaa44238635f9c65efe2f6744a70b9ae41ef15d97908c0533934412f79583d0e9b3d706a128e88fb51eedb65e46d8a2b38bbdd6455554967a8dc0c68bddfeae0f8f72f0b886c3c741fac4f91e5c491dbae9da4594836cf1d9fb6ee130025089aed350ef247bc9887a2050159dded1428ffd9b07b9ec2e3d4bbdc2ddb54e873b63f2475233e19133a14b6658509457008186d6225995a96726b529f44281aa24fefd1cff8f815d93a5986931662290b3ee16833c60f0afcef2cbc000623f3931909ca976a094e2b0fdb7dcf7c485e14988a36f19b66425385f5632cef65d1d3414623ae3ee816e763a5f606466622be6602114502951cf0c097c1648a72e2c43d9afa9689f2c3cfe026cdce3bd1bf9ebf777562ecd8ff1b0d775306d900443f30a843310b8de6a38ff108b723913d7899b9fbe7c3d766ef8bdfb6d8b0b52956cb1cec9936d70b487c01440a842b2fabe38e7b8851a387d358be7ef12a7e4f2b527e83090d67eb013c9c2cfd3de5a1a3f99748a41f4819d9036e500c504c988bfd24f617d6ebdcab2ddeaa61579414f360b469a33a6ded96ba1d8c140c4ffc94990d8adf78cd38780bd68663d1a0ee33f537cdf892d562e82dcd1d912cad38d65567d291406: +b62c241878273513e0bf6f33d2104365b2ce9c5a1b786058e9c5b4d1d192f87fbbf6fc5198f3fba5ab007f8a632d28d1af865d290fa0a90faa9a9b5b9c13f3fb:bbf6fc5198f3fba5ab007f8a632d28d1af865d290fa0a90faa9a9b5b9c13f3fb:26a3c26a5a189cad407cbaa3a6867ac0a26088c75f9d0fa19bd50274cec5755a497109a473284d6fc81ad4b9ec29fa7ec9764fd3099f060e36836552ff2413e3d5095fe0b1a8bfcf67ee06aa9032e7bb3249698047714d281415273c9834ad9eb665a7d97220e72d9ca73f31afa7738675ba3162efefe7479a5bc4bce2e8b7af4741d703dc9bbd60b4cf4b9087f6cf86cf53aed02bf4ca6a18f607cb52a303d78e85ad88fdfc86dcb7187727b03be227745bea744fd006525bc59a4dddab915cef40a8f30802913b7913eaf974336552e2f1456ad803dc58c9b4b18efaf7f7e357e2cd77d138d90080e296d1364a2f324d3e0d6edc20b8bdaa9d2e871f5e7b051fb6fcdb5595f21d3f8de29fb78678fa479eaa32579c784d513ac5f836d954d0d3fc0e5fc8a6eeab90202b4c4a2bec24cf63ea67c470096218cd431e883105fc9c27f9ea77c18eda69bc00a2242bd420f095c9b9a92d956ccc5a8572b057a7fe173eeb2a3166cb2089d113a816462b25805b8abaff5b0b2287c508ec2b8c34b2195c332870d3cc396017a16b9e0da6182d071d3bf363d3f1e7b7da11d711250a58afd74ed3e3158d4718bad4d274bb3444cfc318074b53beba44a2a34ff8eb726e4a1daa911051621651898b887169f62b9c0f4020483ef544f8f572fa6a6640a4cffce976cb7024f847bdc95d1d7ce653505debfc6988ed289dd47a9eb261259e3e65e45fc9d714946935cd8ea13bc6db5eaab9e8b10dae0fdd6979c2035cfb8098252f2205443b808816bf7787b7f1e78bc98a7285e733d45fc4610c20977ca3229889bb8cd2b694ce9e3fe78303af83e106422542fb7961d32eb1d2c5fbe60751674b074773ee0616e02973f6a74a3ae4664a2650915a3e10493b9e66a39fa5c89c61d44735f107d33757ae679b43a8d43a01757ae1f3279e862442e150715550ee82e49c0d4943faf13f22791f0e66f24ac50ab3c003852b21e15b2f006edc2cd6a879c476ab5b352eb1099dad4c50372400faa5498d78c6b857034c25caf7b933faf6bd7c59fa3da57397b603de9cb9d80e51f7997baa462acd537e2c4194c76c7e0be6512bce4d63660b36c7cc46631fb9671ad8c5d28e2f2ee2edce81954421b8a3d9ff6f66699f4bce88bcb8ef192c262a74ab7e191eee9101a28d4b66282b5122093d141c6496c7aba4d352e472ee7440e05af60da0cfc93e303642ba8fb8e5c568687abd63afb3ed6a32b6dae56a7e5d73debaf41d35ca36adb97a22c0adbe718bec1fa51998de9b4b96a79c5b9655b0165d5e1b9a8cc552e8c9329ede58df74c67b2ba1a842fd3e8158c1fea3a99b56a2c2a96207853d26022cec170d7e79944d2f56aab1f191bfd48d725490ca82b8d906f0680e69eeb9575774fb9d604513fbc26f5d303b6885cac0bf8efee0538f92:c59039587b38dc141e055a93850104d629e380705b8fc918847c5e2a352da3a02fce7f7199f4ae2b1e2a59483418932e185f7e45b5050c642cecc7e78199850726a3c26a5a189cad407cbaa3a6867ac0a26088c75f9d0fa19bd50274cec5755a497109a473284d6fc81ad4b9ec29fa7ec9764fd3099f060e36836552ff2413e3d5095fe0b1a8bfcf67ee06aa9032e7bb3249698047714d281415273c9834ad9eb665a7d97220e72d9ca73f31afa7738675ba3162efefe7479a5bc4bce2e8b7af4741d703dc9bbd60b4cf4b9087f6cf86cf53aed02bf4ca6a18f607cb52a303d78e85ad88fdfc86dcb7187727b03be227745bea744fd006525bc59a4dddab915cef40a8f30802913b7913eaf974336552e2f1456ad803dc58c9b4b18efaf7f7e357e2cd77d138d90080e296d1364a2f324d3e0d6edc20b8bdaa9d2e871f5e7b051fb6fcdb5595f21d3f8de29fb78678fa479eaa32579c784d513ac5f836d954d0d3fc0e5fc8a6eeab90202b4c4a2bec24cf63ea67c470096218cd431e883105fc9c27f9ea77c18eda69bc00a2242bd420f095c9b9a92d956ccc5a8572b057a7fe173eeb2a3166cb2089d113a816462b25805b8abaff5b0b2287c508ec2b8c34b2195c332870d3cc396017a16b9e0da6182d071d3bf363d3f1e7b7da11d711250a58afd74ed3e3158d4718bad4d274bb3444cfc318074b53beba44a2a34ff8eb726e4a1daa911051621651898b887169f62b9c0f4020483ef544f8f572fa6a6640a4cffce976cb7024f847bdc95d1d7ce653505debfc6988ed289dd47a9eb261259e3e65e45fc9d714946935cd8ea13bc6db5eaab9e8b10dae0fdd6979c2035cfb8098252f2205443b808816bf7787b7f1e78bc98a7285e733d45fc4610c20977ca3229889bb8cd2b694ce9e3fe78303af83e106422542fb7961d32eb1d2c5fbe60751674b074773ee0616e02973f6a74a3ae4664a2650915a3e10493b9e66a39fa5c89c61d44735f107d33757ae679b43a8d43a01757ae1f3279e862442e150715550ee82e49c0d4943faf13f22791f0e66f24ac50ab3c003852b21e15b2f006edc2cd6a879c476ab5b352eb1099dad4c50372400faa5498d78c6b857034c25caf7b933faf6bd7c59fa3da57397b603de9cb9d80e51f7997baa462acd537e2c4194c76c7e0be6512bce4d63660b36c7cc46631fb9671ad8c5d28e2f2ee2edce81954421b8a3d9ff6f66699f4bce88bcb8ef192c262a74ab7e191eee9101a28d4b66282b5122093d141c6496c7aba4d352e472ee7440e05af60da0cfc93e303642ba8fb8e5c568687abd63afb3ed6a32b6dae56a7e5d73debaf41d35ca36adb97a22c0adbe718bec1fa51998de9b4b96a79c5b9655b0165d5e1b9a8cc552e8c9329ede58df74c67b2ba1a842fd3e8158c1fea3a99b56a2c2a96207853d26022cec170d7e79944d2f56aab1f191bfd48d725490ca82b8d906f0680e69eeb9575774fb9d604513fbc26f5d303b6885cac0bf8efee0538f92: +0f77f77a1c7e04bda8e534f4e3eff9a238cc14876b7e3eca8bede1923a3364061045ea9fe214583a0cdbc494932bc44afeeb080bec485cc234fddcff139cce00:1045ea9fe214583a0cdbc494932bc44afeeb080bec485cc234fddcff139cce00:0ecb746dbdb0161421afeb7adea7a37c2ea4408a592c9d781ed6ac6f4ee5cc65d5270e4cf27632f7c5c133d439b78d1f71aa6dd80713d90b151e19121bfa87710e84a4850a3b5b0265ba2603d0716e9b7e1122109c39c6f1027fce18798cbb4f6bc5e4d7aca4704690f5c981510871c313595798338681107f2b5794d46f6e0bde2cd064b3b1fc00ca47188bbbc1f4a0ce305cc6d8a896920eb9ebae579fd3385f8f1f35976288f4c58ffc4760f359b003c872e9a24055355ea9585e951069dca25fd0cc0b9db52aaeaf19d43f2eab4f835603ad12d2dc49b310256b94bed54896a16b69b09cb4c8ff5c23cce5593d87ade2a82ada50859e1544c18618a65c007ef424c9854a175b6e6c0e64b2c8eb8ad4d28b977d68e78169915198975394d3b9b269cab0d3261b2b56cd2cc4bddbd4f1439e0dbe2c9b3f3f7514edac5ebb4622b92a69a840a9028550b221db59ddfb001396f86392a17f08ccb194cd9e1a0081d7dd9cca2357feb8b795e517029f79c82a3be6f9a031dd1af1e79e4982bf8e76b310f9d355efcd5b1efa9f359c17cf3b510d513e8cd5786a0d3445dc59a8433a46488687b0f58b1bd6567c2af4873b51fc845e767e243005192f8f0674f281265a55d76cea322260c932cea6717adb98a2dda8c698e2e89255feb77da7648167bc1e58877feb72d1d14b0c304f07372d955675237c49f7a6dbc915e6814abae6cce4caf9f48087e9dfb282d8f340377c1e29c6731ccc2667da6695b712be0312d865111934f168d5544365ddae27abc64aefbcb322db7d97d90d957a637bd826c227e9eb180b45a431626a6fd890c0e5f4ed7e856474752f80b5aef6e73efdaa6c2c451bd74c1ef466ca3aaa2573bb52cb2b1ca96a1b574403ceae1cf05ffc53430e1e4cd5593bd1ef84bcbfe219f08160d166f2731d99b8d7a32b12991f77775a267ec08297ec512d7b72435632525c04000fb00a793f8b5f8f3747b55359df21b7e2c49f2b0b9ae082afc70a146871370b8d50086de00f9448be8902174ba2cc851fa379dd7031ca457a8869af4b6c2729dac519556b8bb4ab519ef1bb024ea8b7f01771c9aab748e57381a0192a6e398cbe6dd9f367cc7b3354f83b79bcda46b793a4ada85549c8d6bdd6168124362ff908aa1a0cb78aa330c42d5a5d481235acac3a919b969c50987266d404d15d0e706fd9007634f69e13c56ec47133884fcaddc16beeeed19e0cd917aa496367867dfcea274e1a47da774f3c9363021e7c8d6bf8f00053facc11cb68a9d6e1fc2d6d19175d6324ff7ca6c23058b8b693d8fd4e0b51dcbb113543f2fcc0452eb9d967ac0fa9b23e9e0b1da8d83a3c1fc9e9ec971f0f67fc745bb17376bc46245f528cb6e5fee11bcdda867b7f79019cf9db591858230aecb4d1e93d167cd86b42dd879a13fa0e:b20b9c4246f0d2970138af7dc9af629b68fbc37df87afdcadcb545c1768376a09c3babc3eb1af3b7519852f75fab1c9c119c662c5877fb2f7299cab57fad3d0e0ecb746dbdb0161421afeb7adea7a37c2ea4408a592c9d781ed6ac6f4ee5cc65d5270e4cf27632f7c5c133d439b78d1f71aa6dd80713d90b151e19121bfa87710e84a4850a3b5b0265ba2603d0716e9b7e1122109c39c6f1027fce18798cbb4f6bc5e4d7aca4704690f5c981510871c313595798338681107f2b5794d46f6e0bde2cd064b3b1fc00ca47188bbbc1f4a0ce305cc6d8a896920eb9ebae579fd3385f8f1f35976288f4c58ffc4760f359b003c872e9a24055355ea9585e951069dca25fd0cc0b9db52aaeaf19d43f2eab4f835603ad12d2dc49b310256b94bed54896a16b69b09cb4c8ff5c23cce5593d87ade2a82ada50859e1544c18618a65c007ef424c9854a175b6e6c0e64b2c8eb8ad4d28b977d68e78169915198975394d3b9b269cab0d3261b2b56cd2cc4bddbd4f1439e0dbe2c9b3f3f7514edac5ebb4622b92a69a840a9028550b221db59ddfb001396f86392a17f08ccb194cd9e1a0081d7dd9cca2357feb8b795e517029f79c82a3be6f9a031dd1af1e79e4982bf8e76b310f9d355efcd5b1efa9f359c17cf3b510d513e8cd5786a0d3445dc59a8433a46488687b0f58b1bd6567c2af4873b51fc845e767e243005192f8f0674f281265a55d76cea322260c932cea6717adb98a2dda8c698e2e89255feb77da7648167bc1e58877feb72d1d14b0c304f07372d955675237c49f7a6dbc915e6814abae6cce4caf9f48087e9dfb282d8f340377c1e29c6731ccc2667da6695b712be0312d865111934f168d5544365ddae27abc64aefbcb322db7d97d90d957a637bd826c227e9eb180b45a431626a6fd890c0e5f4ed7e856474752f80b5aef6e73efdaa6c2c451bd74c1ef466ca3aaa2573bb52cb2b1ca96a1b574403ceae1cf05ffc53430e1e4cd5593bd1ef84bcbfe219f08160d166f2731d99b8d7a32b12991f77775a267ec08297ec512d7b72435632525c04000fb00a793f8b5f8f3747b55359df21b7e2c49f2b0b9ae082afc70a146871370b8d50086de00f9448be8902174ba2cc851fa379dd7031ca457a8869af4b6c2729dac519556b8bb4ab519ef1bb024ea8b7f01771c9aab748e57381a0192a6e398cbe6dd9f367cc7b3354f83b79bcda46b793a4ada85549c8d6bdd6168124362ff908aa1a0cb78aa330c42d5a5d481235acac3a919b969c50987266d404d15d0e706fd9007634f69e13c56ec47133884fcaddc16beeeed19e0cd917aa496367867dfcea274e1a47da774f3c9363021e7c8d6bf8f00053facc11cb68a9d6e1fc2d6d19175d6324ff7ca6c23058b8b693d8fd4e0b51dcbb113543f2fcc0452eb9d967ac0fa9b23e9e0b1da8d83a3c1fc9e9ec971f0f67fc745bb17376bc46245f528cb6e5fee11bcdda867b7f79019cf9db591858230aecb4d1e93d167cd86b42dd879a13fa0e: +c5a5053477ae31158e7469dd1504867650d46f1589067f5cd881caf25c26cb2170f85db9807b26fcf3e6690b91724f7ae3d20ec3604ab7d6308d9094308b2d59:70f85db9807b26fcf3e6690b91724f7ae3d20ec3604ab7d6308d9094308b2d59:8571ff3903486a43a6126c323e7b3a74141d1385d4bd703f19e2d1b64b50281d27168ae3e769c6dd9df7d97864fb37822f0021852e3168ab7d845a6545ed0c377d9f7c048a2b96e8dcf445779684a058c2b9c21ac68a0c341d1d6c0981456457458eb7cebf66678740777eca26e01e1c8f53b5d4756cc5f0b90f0c5db05393cd4b8e44f6810caa5a116a33577724395d413af619632a6fed14e215c2f19d105ce2bf1498e6d2ab4f650f61ba5cf6d0c73bbbde98e30429910a4e67dfbc717cb091182d597058b5d765d097e6875831b588aaeb3e7327e856b42fa983fd254ef1f918b043d1dd3d7b7e30b315386eec91e7f94d598f4beb3b27b42f4ee1fbf7afb486bdcc6081ccb867f04111044f4bbbe3c8122edeadefa9d693906e0d6e133bf6f2da6158feedbda024410f12086e7accf1c68e1557f00c14e9c7ea76a5ed1337a054ac2c949c05977e030274f6a4f2a6b30a15c570ec9433f74f47528087c9ce9a6292951c54354996fb283c0dc4cf33c001bc96875ea6e1f46f837ff18dd9545fb9934655342b12c2990b9f1c6ff4d66489d6aedce75c7cb03ac134bfd39b181dfb7f9a97ce737fe570ad5f81345939a6de5a40a33a0e44bf957503d5ca0283512e57fba8a3a6f2c390687b1b7708676e0fd03b7c188d4561c1879163eaf2b596ddd5f3c1f4dadbc139c2164892820b2fe09cbc3d19088076364510254f2b6d410329e70f2e5a945bbacd2ca89bd4b6e1f5e2e1d4f4ed2fe0113bcf32962f00d5c33b1df988402ba0dc8804c1af66ccae2670efa3134c67fc90feed8d8deedccf6a46f22940454af2bb6754cf235ddbb0001c6c741bf874bcd8d41d9dba8162581c3746d7f30e73def69415af5181c149914295122d45982f94943e20b0ffc7fe6ddf19a022e87a52133357a1e80f37f28a4c4a8a61c148dd875c1e8ecdcd840dd863e44d9bcb16b6e5af0147b34a7a9052c8d3f452013d2d354f6803f9eaf6056f3b013c616e47f398819146320a5e3dbdf16843ea29def262cc9a343672cf96bccc6e87e6a6baf0712e6ee89aa60489f17cb72ddc44bad161587d87f54d67cc0a2778497d831088315ffeee3d268c59befe884c3aa0e0ae2296bbb60eac9097cdf8dc0987ceb1742b0586dfce79ec10425b28f4e64520d712e3f46ea83be2de6a1574073bc5c7557b8e25b6411184ea283d8800232c79069421811f883c2994e7b7e2ad9f8dc489c9347724394609c98909a6c26017b50f20d50ccacbde36b76ba646a76dc6a5b0f50649c5658bbdfdd3b5cafc5479a2f48ee51542f23e9fc92132060fd635eff452111cdaf3efbdb7db9e7d4716d0d6011c29118a55d4c1a436abe24e3cbf40235b76dd1923503c5f3598124e2df55a2d1f246e90de4b71645d5175b61b0174e7e57df1285ccf8c86b8382c258079:f5191b44bd6cc3ea281771df12549ba2be228b51eb791b9e5ed2815f862aa630b56967cdef8b6af0b9d21ab8c97a6dff681cced9f5019713d4357cb3e54c0d088571ff3903486a43a6126c323e7b3a74141d1385d4bd703f19e2d1b64b50281d27168ae3e769c6dd9df7d97864fb37822f0021852e3168ab7d845a6545ed0c377d9f7c048a2b96e8dcf445779684a058c2b9c21ac68a0c341d1d6c0981456457458eb7cebf66678740777eca26e01e1c8f53b5d4756cc5f0b90f0c5db05393cd4b8e44f6810caa5a116a33577724395d413af619632a6fed14e215c2f19d105ce2bf1498e6d2ab4f650f61ba5cf6d0c73bbbde98e30429910a4e67dfbc717cb091182d597058b5d765d097e6875831b588aaeb3e7327e856b42fa983fd254ef1f918b043d1dd3d7b7e30b315386eec91e7f94d598f4beb3b27b42f4ee1fbf7afb486bdcc6081ccb867f04111044f4bbbe3c8122edeadefa9d693906e0d6e133bf6f2da6158feedbda024410f12086e7accf1c68e1557f00c14e9c7ea76a5ed1337a054ac2c949c05977e030274f6a4f2a6b30a15c570ec9433f74f47528087c9ce9a6292951c54354996fb283c0dc4cf33c001bc96875ea6e1f46f837ff18dd9545fb9934655342b12c2990b9f1c6ff4d66489d6aedce75c7cb03ac134bfd39b181dfb7f9a97ce737fe570ad5f81345939a6de5a40a33a0e44bf957503d5ca0283512e57fba8a3a6f2c390687b1b7708676e0fd03b7c188d4561c1879163eaf2b596ddd5f3c1f4dadbc139c2164892820b2fe09cbc3d19088076364510254f2b6d410329e70f2e5a945bbacd2ca89bd4b6e1f5e2e1d4f4ed2fe0113bcf32962f00d5c33b1df988402ba0dc8804c1af66ccae2670efa3134c67fc90feed8d8deedccf6a46f22940454af2bb6754cf235ddbb0001c6c741bf874bcd8d41d9dba8162581c3746d7f30e73def69415af5181c149914295122d45982f94943e20b0ffc7fe6ddf19a022e87a52133357a1e80f37f28a4c4a8a61c148dd875c1e8ecdcd840dd863e44d9bcb16b6e5af0147b34a7a9052c8d3f452013d2d354f6803f9eaf6056f3b013c616e47f398819146320a5e3dbdf16843ea29def262cc9a343672cf96bccc6e87e6a6baf0712e6ee89aa60489f17cb72ddc44bad161587d87f54d67cc0a2778497d831088315ffeee3d268c59befe884c3aa0e0ae2296bbb60eac9097cdf8dc0987ceb1742b0586dfce79ec10425b28f4e64520d712e3f46ea83be2de6a1574073bc5c7557b8e25b6411184ea283d8800232c79069421811f883c2994e7b7e2ad9f8dc489c9347724394609c98909a6c26017b50f20d50ccacbde36b76ba646a76dc6a5b0f50649c5658bbdfdd3b5cafc5479a2f48ee51542f23e9fc92132060fd635eff452111cdaf3efbdb7db9e7d4716d0d6011c29118a55d4c1a436abe24e3cbf40235b76dd1923503c5f3598124e2df55a2d1f246e90de4b71645d5175b61b0174e7e57df1285ccf8c86b8382c258079: +05c719cae06e2bb7d87863ab3150272cb2f8c3aa2421912d87f98e7589638ce990211796fed3d53b81f8feeb1bad1ffc933e5f10d3bc1b36ddf210a47923df03:90211796fed3d53b81f8feeb1bad1ffc933e5f10d3bc1b36ddf210a47923df03:ec241918418e60522042e67339e6649499f31a6c7cf8925f1f61dde894603602ae8bb5f58809821f83344f23cd31e64ec9ffe79a986b7e29e4319a63414316bd6ee20e02a50da44012bd2d6f9f679e88ed0c8bb1e2cad55e565789883345b7546f3d54b1b362b1c650502c019d7313afbc82689b23a3a52d8f1af9f81e188dbdf203fb5300b4225bfb6773337be6750b3db88ce097343f62ee2c118574ef150cbd4c62760c3e43dcbc39218bd6d98565fa389811b1a674f617fd756733dcb567a92dbf3855b57b1f4a46d5b8974b39ac0d0e24d99d2037c04f60d9140f64b07a77d7eaa1ce8a78e844b1dcf0e37424f3f9d253a548561a0375a8d4341297bfedb7048c7935e1481418f9bba9271f9fd6026224e78e055d8a0939fa2fe1dbc0fc7b583e4cff3490e1d0f610b252e30d8497d00e4aacb375f19a4719f79ca1ea583a2f8b1406a4aa5cb55c08b6593b676eb5c34abe89392d62d23308a3348b57affbba7739cde8e1909d3425eeb20926a977d3a94a86e0ba10b386926698827e86b4fd6c6180047c87ec3b31619d05a9df34efd3d76a836962b2ef604d07af0975eb8f3dd22594323802564c929b3f65dacb572b32553d69b31a197690a9bb860b080a77cfbb3c175aafce0146a82a4d06e8c750521b726ef1cb29d021e5915e5e8462ede5395445245c9ae882eec4b1745e11791f7621d3fe702cac1525e1f7b46e1105cdd06da2afde26475dc1f78df8e2d72b0ec3ef7dd956193c996842a432696538cf123d7687211ffcd090b9381eabec879f769aac0d3564e16df794fa24728d7172fd07732eab077ed81c22084f6f781b626dac67428a9ddf3b0db0465251220d18b8bf620464c51a578decccbbaba545ed442cf12c4c66f6cb6e6901ea54aeda236ec45eef886a7ddd2c041caba3a6cee339715b6ce97e765ec3479f3d52824a8194bec2a89647e8c63ff7645ff6d05367c767bc48cc96baf05d6a415b2a5aff9bfb217948fad357b98f47dfed62ff1285eb9f468f0f29edd75adc0c8c2ff6a565edb8edfb48bea03b70c447369c52d881eea0eedb08c315cdf0bfeb979c1c0250946bb100c2866b4169b8cbd44d658f0236e1e9f3aa13bb8e8022a38ce997c94b5baf97e0ba621f7e09671ce638c2a39ee6c6e25a688019dd167675ceaec21c6b42a7c8c476d129dcc693c392a02be91b87437a08a0ebf1a7bd976ba23774766838b8d6024f5bb9b07f3c6b719b4de15b72448048ab70db3d4bea77ba359b51b1ec17dbe8010aef0244a8079ca8b9a2a797f3b1fe047c8dd5cab7fb486829239c4ef6d9a38370d488c47b7c030e49a5500c9abb39a9a5abfe72e918b76384ecaafe1627266cd14e696c09d2512e312582a8a911e7b7bfa04c21819af687f04c5e0cbe9a2ce24d4d3fd12190b253dabc12c63cabfa94:ba6eb751371df721b7707a5b3339edb55f138640b97be6334d6cda5191a3ff6367911761882a4a007f161b748cec95b19e995f2858c257cd6169256662301102ec241918418e60522042e67339e6649499f31a6c7cf8925f1f61dde894603602ae8bb5f58809821f83344f23cd31e64ec9ffe79a986b7e29e4319a63414316bd6ee20e02a50da44012bd2d6f9f679e88ed0c8bb1e2cad55e565789883345b7546f3d54b1b362b1c650502c019d7313afbc82689b23a3a52d8f1af9f81e188dbdf203fb5300b4225bfb6773337be6750b3db88ce097343f62ee2c118574ef150cbd4c62760c3e43dcbc39218bd6d98565fa389811b1a674f617fd756733dcb567a92dbf3855b57b1f4a46d5b8974b39ac0d0e24d99d2037c04f60d9140f64b07a77d7eaa1ce8a78e844b1dcf0e37424f3f9d253a548561a0375a8d4341297bfedb7048c7935e1481418f9bba9271f9fd6026224e78e055d8a0939fa2fe1dbc0fc7b583e4cff3490e1d0f610b252e30d8497d00e4aacb375f19a4719f79ca1ea583a2f8b1406a4aa5cb55c08b6593b676eb5c34abe89392d62d23308a3348b57affbba7739cde8e1909d3425eeb20926a977d3a94a86e0ba10b386926698827e86b4fd6c6180047c87ec3b31619d05a9df34efd3d76a836962b2ef604d07af0975eb8f3dd22594323802564c929b3f65dacb572b32553d69b31a197690a9bb860b080a77cfbb3c175aafce0146a82a4d06e8c750521b726ef1cb29d021e5915e5e8462ede5395445245c9ae882eec4b1745e11791f7621d3fe702cac1525e1f7b46e1105cdd06da2afde26475dc1f78df8e2d72b0ec3ef7dd956193c996842a432696538cf123d7687211ffcd090b9381eabec879f769aac0d3564e16df794fa24728d7172fd07732eab077ed81c22084f6f781b626dac67428a9ddf3b0db0465251220d18b8bf620464c51a578decccbbaba545ed442cf12c4c66f6cb6e6901ea54aeda236ec45eef886a7ddd2c041caba3a6cee339715b6ce97e765ec3479f3d52824a8194bec2a89647e8c63ff7645ff6d05367c767bc48cc96baf05d6a415b2a5aff9bfb217948fad357b98f47dfed62ff1285eb9f468f0f29edd75adc0c8c2ff6a565edb8edfb48bea03b70c447369c52d881eea0eedb08c315cdf0bfeb979c1c0250946bb100c2866b4169b8cbd44d658f0236e1e9f3aa13bb8e8022a38ce997c94b5baf97e0ba621f7e09671ce638c2a39ee6c6e25a688019dd167675ceaec21c6b42a7c8c476d129dcc693c392a02be91b87437a08a0ebf1a7bd976ba23774766838b8d6024f5bb9b07f3c6b719b4de15b72448048ab70db3d4bea77ba359b51b1ec17dbe8010aef0244a8079ca8b9a2a797f3b1fe047c8dd5cab7fb486829239c4ef6d9a38370d488c47b7c030e49a5500c9abb39a9a5abfe72e918b76384ecaafe1627266cd14e696c09d2512e312582a8a911e7b7bfa04c21819af687f04c5e0cbe9a2ce24d4d3fd12190b253dabc12c63cabfa94: +5311f3c96101cb8b7abc622bb9326b8f513c2b16d294df797f56dfd8203dda27230b7002f57c79ae2e6bfdb8df30db3e900756b54af3968c670ee2f32bb11e0a:230b7002f57c79ae2e6bfdb8df30db3e900756b54af3968c670ee2f32bb11e0a:61b15be37c4eb397d9e77e00151a28ed3e86d50a9552bb4850b621763f012e7e77bb5db8f3df7dcf769f2d1d46d8d60bae40c8ca6e25c6410b60078a93fd05902114bd91045c06192c70c42c9f41f8161ca46564ebc21a4bdd8190eba2aeb309823072ec2c0200ce6498f9d72b37b3fb466774326df37ad880d8eddb32af673e45d88eec49b1577b43b8639111c2e0b94187d2d4e0173c000f4c37be845d68810b7889ff2a049f3f9f245ec70f21def97780b611400a83c31a79d93a8e98b608fdcf2488b068fe1ae4217293a9367bb734b5bc7bd8819b377f090b4f8fdbff50799c76880d19133580e1ddfc2b9baaddbab34fc6fdc078014bd1ff739daafe5476f3f79d4dbec216fa7680ee8e84002dcb9ddbc7fc1e1c8ef4f1b2a2081b9282243da6153c1fce0905cf35f83a684c01b04557ec84f7e9a94fc2882e2ff19fea21d2ce6167861ce01df8b8d3c3e8d255610b7af2596cd5cf0016734942cc714c272c05fda9d34723626646a46130182cebcf179ec00a6a173bd8577fa845c44d19c6997944755f2b4e468563a75e9016523b87ddac3eee21bcbca08fcc29546a43cbe0d8d10a0e8ddcba172d1ded150378e18b368c7763913e4b407012fd76a872d2cb04930b8e22b308243d4cc278fdf2e1f940ae89ac891b9e0661aee553937bf350b407070a1bdfc4f7a3787ef399d2caf4ec74439c587376c77be0c3de539d3ac26089765b9be10b9038694636e262d7baa0b3a8941a2015967639f6044c67e59bc81cf2fba704ac0df48da6037405a8e8b8a7ce3c58ef38a883538b247ffe18097af095242b058bdd1e3e245eece0a71b75b97d52f20d6d51bb9766b0da0fc09c8ac2a30fb6e7b32ee06dadf46d7359cc066aa94785d8a882ff097d78a86be2d45600dd3d3060125f01c063e488d5c3efee1bca1e58516455ffcaec1b81ef433876bf09ffa51d6f5018585224579cb67b56ce1c216ec0a883e06c8e1563421ea72b0c10d4bb31e491c2ae2fe8139f249ec927d806ba08db52b1b506669047f0c116ff37ac5ba6cdb1eaaf33fdadb0705c799d35ac6d9c80da90c1438b585ffd59350a2686b1ec35166cb9b69ad0f56586aa03274d782e3f858db64adfbf04d5228a7b1c4a2048bbcdb941153a436d742c38b58b4d7d13c9f1d60e152aa2792349a3d94e7e6b1104aa1b870998c18dd7065654a85281bb6f027faad556b1f532e7a1e22d564069289587a0efc9c1585d135f31233c41f440466e71fe9012e5f9a0d74a7282ee392fb0165db79ff1d3176ed08afe1daa66cfbf4305ae16ac1792334399f71b1917ddec270acff665ea05d184c2c5cd2ccd902b22f9b7195e66a65556ca884ba6f5da04dcd4617f33dc2b44a0ea742aeb2b93f3a41df7957a026797a585ceee814b1975f523d2db5dbb9be0ca649d1d45dcfd:3cbbb2608870dea1efeebb3fbf681e27705c35e4ddeea86c1b342a77dc296b498419808eacbc78855611ffbc9265a74798e51827e6e5d811816d3ca21e8b9c0661b15be37c4eb397d9e77e00151a28ed3e86d50a9552bb4850b621763f012e7e77bb5db8f3df7dcf769f2d1d46d8d60bae40c8ca6e25c6410b60078a93fd05902114bd91045c06192c70c42c9f41f8161ca46564ebc21a4bdd8190eba2aeb309823072ec2c0200ce6498f9d72b37b3fb466774326df37ad880d8eddb32af673e45d88eec49b1577b43b8639111c2e0b94187d2d4e0173c000f4c37be845d68810b7889ff2a049f3f9f245ec70f21def97780b611400a83c31a79d93a8e98b608fdcf2488b068fe1ae4217293a9367bb734b5bc7bd8819b377f090b4f8fdbff50799c76880d19133580e1ddfc2b9baaddbab34fc6fdc078014bd1ff739daafe5476f3f79d4dbec216fa7680ee8e84002dcb9ddbc7fc1e1c8ef4f1b2a2081b9282243da6153c1fce0905cf35f83a684c01b04557ec84f7e9a94fc2882e2ff19fea21d2ce6167861ce01df8b8d3c3e8d255610b7af2596cd5cf0016734942cc714c272c05fda9d34723626646a46130182cebcf179ec00a6a173bd8577fa845c44d19c6997944755f2b4e468563a75e9016523b87ddac3eee21bcbca08fcc29546a43cbe0d8d10a0e8ddcba172d1ded150378e18b368c7763913e4b407012fd76a872d2cb04930b8e22b308243d4cc278fdf2e1f940ae89ac891b9e0661aee553937bf350b407070a1bdfc4f7a3787ef399d2caf4ec74439c587376c77be0c3de539d3ac26089765b9be10b9038694636e262d7baa0b3a8941a2015967639f6044c67e59bc81cf2fba704ac0df48da6037405a8e8b8a7ce3c58ef38a883538b247ffe18097af095242b058bdd1e3e245eece0a71b75b97d52f20d6d51bb9766b0da0fc09c8ac2a30fb6e7b32ee06dadf46d7359cc066aa94785d8a882ff097d78a86be2d45600dd3d3060125f01c063e488d5c3efee1bca1e58516455ffcaec1b81ef433876bf09ffa51d6f5018585224579cb67b56ce1c216ec0a883e06c8e1563421ea72b0c10d4bb31e491c2ae2fe8139f249ec927d806ba08db52b1b506669047f0c116ff37ac5ba6cdb1eaaf33fdadb0705c799d35ac6d9c80da90c1438b585ffd59350a2686b1ec35166cb9b69ad0f56586aa03274d782e3f858db64adfbf04d5228a7b1c4a2048bbcdb941153a436d742c38b58b4d7d13c9f1d60e152aa2792349a3d94e7e6b1104aa1b870998c18dd7065654a85281bb6f027faad556b1f532e7a1e22d564069289587a0efc9c1585d135f31233c41f440466e71fe9012e5f9a0d74a7282ee392fb0165db79ff1d3176ed08afe1daa66cfbf4305ae16ac1792334399f71b1917ddec270acff665ea05d184c2c5cd2ccd902b22f9b7195e66a65556ca884ba6f5da04dcd4617f33dc2b44a0ea742aeb2b93f3a41df7957a026797a585ceee814b1975f523d2db5dbb9be0ca649d1d45dcfd: +d290ffd93395bd5fc587d1ab511866e72b371a1735732d9d5c6a18dd465e9363fd4aad73b032461ca0aae871ca7016383b2be0169053fdbf6c5914fdd6dd6f92:fd4aad73b032461ca0aae871ca7016383b2be0169053fdbf6c5914fdd6dd6f92:ebd900bc910c5ecc4d97daf7cb5ebb5491500b7ad116e30660950709d8084bb6434c5bea4a8ccc1ed5a801bebb1a117878c03747003e148ed91434832e8966241a7fff22fe1d6d8c3c3ddd7215a1efaf4b07afee1b25673a1439eaac324e895d4be839e976c03ac001254876888ccaaf3912727a60106a87be69247c9e438c31fca8d9c61bae368c83e40901a99700dff839b513ba8dc42d93ce0987a2333470a9f983313f91988659da54039e499cd1af2b8fa0ebe750e24d55c2a5bd1ade3f680092542bd1be0b9735ba393ad5697d241e8e8b28646db27d2fb5a940e8faeaf0b6c9efda88615dec891ce732930813bfbbd0bc5f8210abe843beb5e4f028f49bea34f1e5b09eac4c6662c74fba39de4a9602a9694a85c7c1375fdadfda6a1957fc5b5987a687b03995e51697a1ab5bb6cb11b663c1372fade4c0aca8fbebb4eb54ce7ce36c6904eaf6eab2f34facd8c768c8d36da2397b1a02735aea72cfaad0393410db527a8ab236d4cdabdc888fac6f182148b132614425d390ff036e54855e4203c51203c1f43e37bbf6b9bf27f5b7e7c665151465401ac32cbe9e3350535edf48a7bc3603e2232e938f9a815ac4d1deec991ef9620948441f7a2f4a46e2c400ab914c4be51dcaad8ed8239cbbe977a9f09c02698319d9fe2a8c6eb60b799f29ae7659970d2ebdff3c6cf709bbf6f4bb55b9df4f61a241dec144b5993f087e784b97be1e53608c2e817ce3d9aaf914e6b723f5b4afffd2a6b9fe9d2d73915c7ad1ffb13efcb73c56238195645203984c99aafd0235f73b3f882e073939bf786657280138db05b86fcc9460b385ef4559204ecd81e2f12f5f062aa448dccc82ea8d89466dd1be46f82c4f87bf0db2b878acbb0d9112c8db6f51d35f6d42f749856b99e550b6c454e9e8be4da175f0b5e86be66c979fd878237e57f691f0d2acd028fbffa5b0668775034db1f21ddbe7114ee3dc0b44daca64c5a03a2feeaeabeb7063bfcccc559baf27f1ccb2202fa4d1b2bf44c04b2c2f81f94e281b1a5adc850da1b9479fcabddadea56a115bb5f06cc016f141c0fcb5e83ab248eaec90158d8be647aff12e7eeb5e57dbcc293cb3b6aacb55236d4a839a0620f4762387dd1714df5c135e3d9d6824f93b7c90d3ae38c518d607120c839570413b46b8ccd7370492d8ae5c609e00cf8251e2e7df81e5b4f9c16a5a539f0afcce41bb4362e5eaa5f940a1706f4afb6b14432c81d4ba1a33d322dbf10645ab63737eadc86fe6e0976f763397fb898637595dfd36934792d779e24c2a3f0bacf53e0473c5fda9c61284e4419bdc0eef5d22f4d9bf42e8c04933bb93b53c295d7ac9395abb6dcbd742b1e1bc3b0ea4434ea21b8eca9ae682d3315a41e9c3c3371840761dc59cac45da7e3813e28788dc89de355b5aee088090a38dd39d83e5e4:21704d5e626dcf6a9dcdef935429eb7fb5b257eecd7bf74acb0cd30ecfcf608d0c5b633a4a8a9ba2cc82a21e03355e01d85dae7ecac8896dc15dae0485707104ebd900bc910c5ecc4d97daf7cb5ebb5491500b7ad116e30660950709d8084bb6434c5bea4a8ccc1ed5a801bebb1a117878c03747003e148ed91434832e8966241a7fff22fe1d6d8c3c3ddd7215a1efaf4b07afee1b25673a1439eaac324e895d4be839e976c03ac001254876888ccaaf3912727a60106a87be69247c9e438c31fca8d9c61bae368c83e40901a99700dff839b513ba8dc42d93ce0987a2333470a9f983313f91988659da54039e499cd1af2b8fa0ebe750e24d55c2a5bd1ade3f680092542bd1be0b9735ba393ad5697d241e8e8b28646db27d2fb5a940e8faeaf0b6c9efda88615dec891ce732930813bfbbd0bc5f8210abe843beb5e4f028f49bea34f1e5b09eac4c6662c74fba39de4a9602a9694a85c7c1375fdadfda6a1957fc5b5987a687b03995e51697a1ab5bb6cb11b663c1372fade4c0aca8fbebb4eb54ce7ce36c6904eaf6eab2f34facd8c768c8d36da2397b1a02735aea72cfaad0393410db527a8ab236d4cdabdc888fac6f182148b132614425d390ff036e54855e4203c51203c1f43e37bbf6b9bf27f5b7e7c665151465401ac32cbe9e3350535edf48a7bc3603e2232e938f9a815ac4d1deec991ef9620948441f7a2f4a46e2c400ab914c4be51dcaad8ed8239cbbe977a9f09c02698319d9fe2a8c6eb60b799f29ae7659970d2ebdff3c6cf709bbf6f4bb55b9df4f61a241dec144b5993f087e784b97be1e53608c2e817ce3d9aaf914e6b723f5b4afffd2a6b9fe9d2d73915c7ad1ffb13efcb73c56238195645203984c99aafd0235f73b3f882e073939bf786657280138db05b86fcc9460b385ef4559204ecd81e2f12f5f062aa448dccc82ea8d89466dd1be46f82c4f87bf0db2b878acbb0d9112c8db6f51d35f6d42f749856b99e550b6c454e9e8be4da175f0b5e86be66c979fd878237e57f691f0d2acd028fbffa5b0668775034db1f21ddbe7114ee3dc0b44daca64c5a03a2feeaeabeb7063bfcccc559baf27f1ccb2202fa4d1b2bf44c04b2c2f81f94e281b1a5adc850da1b9479fcabddadea56a115bb5f06cc016f141c0fcb5e83ab248eaec90158d8be647aff12e7eeb5e57dbcc293cb3b6aacb55236d4a839a0620f4762387dd1714df5c135e3d9d6824f93b7c90d3ae38c518d607120c839570413b46b8ccd7370492d8ae5c609e00cf8251e2e7df81e5b4f9c16a5a539f0afcce41bb4362e5eaa5f940a1706f4afb6b14432c81d4ba1a33d322dbf10645ab63737eadc86fe6e0976f763397fb898637595dfd36934792d779e24c2a3f0bacf53e0473c5fda9c61284e4419bdc0eef5d22f4d9bf42e8c04933bb93b53c295d7ac9395abb6dcbd742b1e1bc3b0ea4434ea21b8eca9ae682d3315a41e9c3c3371840761dc59cac45da7e3813e28788dc89de355b5aee088090a38dd39d83e5e4: +d7fd73d1d229a65894420e4ba734270d5a20758364de897d8555e24197453c193c22772aec0a0c1559077f2cfd1f2465d4b48495c5d05f1f837c31845f34cad1:3c22772aec0a0c1559077f2cfd1f2465d4b48495c5d05f1f837c31845f34cad1:c9225859d555bc42011af1b4f14998e6e9b0a65e2172713e968380fb6ceedda22e022c51303031d9931ccef2f7bc705c9e215c1d089d488daddaee155c939b6202ca53bfc7f6e88e1529d82fb45e02b5d05a82bbb9db5f415c58ba8bd56cffd92270b24749e56d12c99ae90c7800f54f55254ea42da5dcfbe0e1d989cd2f6897e232df04707b34af75fa7fec33e55ed56aee39c22b045bedd161083bc5514c1f81ca907b7c760317a7fd5a5a02a5d40e2e823e24ad96aef6da8ea982b5161cc39d84aa2ffd9544c11b634037ab0a1c8e36ac63019da1b2d995cb7bd3d62fe574deabccbd0d3ae7a56e5bec91e4ba3f3db8bfea88e67da62e88278a6e3b418dceea0589f25f7dd8ad19dd845089419b472efccc879c172b32ee4a4dbc2e6c2e865bb3b8ca0adcb71fdf89e1973910ef242915f33e236d2f7c8e9f1ee5b07c6e3c25360f8cb1460be87db31a291d4dee34953e75c675bf181bb7a0b7b5c1befdc86ada072a48f6ac755d499bd68d625d8514525cc3ab8f54ce15a871291778de1305d2219361aa30e332a2e069077c5c53457520379d8b90d24bd8a3a7700ff766231cb5697f9ace521a99e896da54c40793bc7c1fb1584bb1c86194d2fb7a4b802f30885e0ee8af88d6886e3a3a4d4c854649cc01abdf35319a0856cc65d092a386f8869625cd0acac087e9351790ccb4a865f651a881c3ebf109072774f940f5aa98a2a2aa3dd36647d0de83001aa7cdc031cc4a4d75dc11ce551676a2ad43a3f6a16a4bc5aee80e5364206087364eb8b2b15fb705380a072d7c8b51995943aa762e8deb4c568cdaa1411ab68f28489e1323bb6156ce2500b06e7793c510a3de29150840bfdb0b2b7b21c2bb8a7746167c929dd0adad44fed8f36e8381b342080b2a7d82a3f81ff72630cb78df91f7b65a44eff6ed64d48afed109dd7a693a1ba8c37e008fcb157e37297d32eba765a6c7193e73bd97647985b16038c74a084a8f25654cd8cd2cdd27ff17334e06adaa058264017a3b2da78e5738a27e350d882f5fae199278d4e50b8badf57c2141dfdc3cff99df5de86fec293c76cb94b6b19ba3034e460f84c280a2e6412fab5698ce890207cababca0a95b5ad533ce114bf71a404a87590d35fa7cedba43131c4ee92344839f25cbfaeb12aeebc8040893951a346bd28fdd167bd20f71a1e59fb60d55e1c567f478f027cf679a37d1d9db867e17bfdd60b347d89d322639d315bb7a2c9134f00ea03a367f305ea4d60dc9d567cf924851e469ea954ed3ea63ea8606f79f077339bfa2b51ae49baa0fb25377821d7c11ef9ad4bb4c0fe489acbab0ef000d618c7af5efd205d68599fcbdd95e28f836e0916f9ff548d0ba17da62536e74646801eeb6122ba32c41073ae04e42c6c1d5d8d22976a56226ddf4b6ac95455fb53099f20215b2ebc907:400c3505f1dfa80df4b26db24c027eb81977f0fb9b5aca524ad51200f4bfb133db834823314195f4edc292d5f530d08556e7809caf2339768aa38029fdbc280fc9225859d555bc42011af1b4f14998e6e9b0a65e2172713e968380fb6ceedda22e022c51303031d9931ccef2f7bc705c9e215c1d089d488daddaee155c939b6202ca53bfc7f6e88e1529d82fb45e02b5d05a82bbb9db5f415c58ba8bd56cffd92270b24749e56d12c99ae90c7800f54f55254ea42da5dcfbe0e1d989cd2f6897e232df04707b34af75fa7fec33e55ed56aee39c22b045bedd161083bc5514c1f81ca907b7c760317a7fd5a5a02a5d40e2e823e24ad96aef6da8ea982b5161cc39d84aa2ffd9544c11b634037ab0a1c8e36ac63019da1b2d995cb7bd3d62fe574deabccbd0d3ae7a56e5bec91e4ba3f3db8bfea88e67da62e88278a6e3b418dceea0589f25f7dd8ad19dd845089419b472efccc879c172b32ee4a4dbc2e6c2e865bb3b8ca0adcb71fdf89e1973910ef242915f33e236d2f7c8e9f1ee5b07c6e3c25360f8cb1460be87db31a291d4dee34953e75c675bf181bb7a0b7b5c1befdc86ada072a48f6ac755d499bd68d625d8514525cc3ab8f54ce15a871291778de1305d2219361aa30e332a2e069077c5c53457520379d8b90d24bd8a3a7700ff766231cb5697f9ace521a99e896da54c40793bc7c1fb1584bb1c86194d2fb7a4b802f30885e0ee8af88d6886e3a3a4d4c854649cc01abdf35319a0856cc65d092a386f8869625cd0acac087e9351790ccb4a865f651a881c3ebf109072774f940f5aa98a2a2aa3dd36647d0de83001aa7cdc031cc4a4d75dc11ce551676a2ad43a3f6a16a4bc5aee80e5364206087364eb8b2b15fb705380a072d7c8b51995943aa762e8deb4c568cdaa1411ab68f28489e1323bb6156ce2500b06e7793c510a3de29150840bfdb0b2b7b21c2bb8a7746167c929dd0adad44fed8f36e8381b342080b2a7d82a3f81ff72630cb78df91f7b65a44eff6ed64d48afed109dd7a693a1ba8c37e008fcb157e37297d32eba765a6c7193e73bd97647985b16038c74a084a8f25654cd8cd2cdd27ff17334e06adaa058264017a3b2da78e5738a27e350d882f5fae199278d4e50b8badf57c2141dfdc3cff99df5de86fec293c76cb94b6b19ba3034e460f84c280a2e6412fab5698ce890207cababca0a95b5ad533ce114bf71a404a87590d35fa7cedba43131c4ee92344839f25cbfaeb12aeebc8040893951a346bd28fdd167bd20f71a1e59fb60d55e1c567f478f027cf679a37d1d9db867e17bfdd60b347d89d322639d315bb7a2c9134f00ea03a367f305ea4d60dc9d567cf924851e469ea954ed3ea63ea8606f79f077339bfa2b51ae49baa0fb25377821d7c11ef9ad4bb4c0fe489acbab0ef000d618c7af5efd205d68599fcbdd95e28f836e0916f9ff548d0ba17da62536e74646801eeb6122ba32c41073ae04e42c6c1d5d8d22976a56226ddf4b6ac95455fb53099f20215b2ebc907: +fda7cb084016ba513c7c4f8f7180480bb181e95695ea68737fa34a40ecbdf3efa2de3a0ef97298fd716106e2f3f54513057a40072d234c3518154c1bd12de037:a2de3a0ef97298fd716106e2f3f54513057a40072d234c3518154c1bd12de037:c21bb3f8e37befa367c913673101ba30d3b5c74bd8bdb09cd28640012db41120c2bcc4085de2a0f95c9215ddef8cb5fc8d8b1251b41527c67dfaa3f95ba3578391ea5a6629a733095fd0a43fdba40ffe260fff82acee2ebe980e9ececcfe7e10b2ed8c2e6b410d547a1286571df3d701174e579fcf19d3bd8086c0423f37117789f305d9670ad28c99674f52cf64211a081d0c6c3096da2c71bf5f5799a7910e6f38104a37a6557c2daef340814a1f830d593773c6cf48d83ea07294b94eb080b85d6970e28f4051d5066db10e961973a626a826aeaf8a06ec0d566b7e0c4ef60f0c5678fcbb5b2ac63f7bed06448a247b3d427b87086d33573fb2d7228c5c34ea6640eefa9564485a79638e9c97c0af84cfee7ce4a739220c8429e067143953d550668dadc84e7bed9ab070a5943390c611d75b1cb12873a37d9850661a0077bfa9ca9b8b263766c149ff0ee4b4adba25eaf7d7f501f362454256bc1269378ef3359a8ed6b960b86621fa3b613eb132122f49f2eb2ceb6832a3991e961cb0e78b742ef4d65e8de3469666fec7c5b874789571c5c99a2c02a053ff7d2fc90076bafe1f267fa81a3990f27ff14f03000af00c59286cb9bb98e204e90190ae2a50edef049ea92a1f785088f94adf6588fb43bb40fbe2324235cc7e168b80264b069f944f503692c949234d5b76bcffabe29ff9064bd7cbed9e00e5b7fdda4312eb801465f127d0ca68832a7f4ed0eaed8f559c1631cd4d34f0dc414d9fcfe849a91e25f3e0ff013a8cffa806ed8e93d08a1e5a757682ca3d26abc869c76f1c79007d559dfe67e78d8af0195808b0e771c71e64b5716fb36309c25025fae6414c28bbdbd4de597a74996c9da974920d59e6f4c2edfe110ff817fd480a5080978048865712058c5fe7b560b12b67f737ea6e2af9242cf07ad0a8a679f26430046adc3e70664cc9c0ee5abcef6d726b4e04176048b795be12851bdb74003a13204119b86864d6535ba095040a85d9781cf4f3480a304e227f787ad538e68f4bab014179e30d3fdef9eff11bcf471fa3a0bc74b5576f302d3a6b499f11f2ef326ac026c98db10e2741413f322228b3cff0f337ba2f294c78ef73f0e877878f8fc7ff6d10bce66ad6284379b80ca89327d4db0bf14e6d8f01b22ab202b716cc07e3c8866d168a5094bac5a495e73868eedc27222e6444f83bcf65acdc3ec89120bb50e8abfc28b78e6d980c775f4849a0e8cada80240bca245e39966e89a0344df8363a7dcc81b201ce9c753ad544e1124e21020d4c62deda9ed9b9d1f2fb7c54ca7ab09f383bef48cfc6848c271302a10fa687f56e00e0a7d093c927b4fdd8f1bedf6288a0e302848a8012f127a79d2d30a06ce17d94aa6f7f8a1e6eb9d0681c3774f614cc6dbcb2a813f925c6306a630572a83ec109d5f533c0584cb421d919:33614b7a94f75e036534d76e30147eccdd2a04e00cd4704ab6e807d6a2acc1e1d963b8eee0810d412d9d56e54556302b10730c15abf89c29a027303ea88ae701c21bb3f8e37befa367c913673101ba30d3b5c74bd8bdb09cd28640012db41120c2bcc4085de2a0f95c9215ddef8cb5fc8d8b1251b41527c67dfaa3f95ba3578391ea5a6629a733095fd0a43fdba40ffe260fff82acee2ebe980e9ececcfe7e10b2ed8c2e6b410d547a1286571df3d701174e579fcf19d3bd8086c0423f37117789f305d9670ad28c99674f52cf64211a081d0c6c3096da2c71bf5f5799a7910e6f38104a37a6557c2daef340814a1f830d593773c6cf48d83ea07294b94eb080b85d6970e28f4051d5066db10e961973a626a826aeaf8a06ec0d566b7e0c4ef60f0c5678fcbb5b2ac63f7bed06448a247b3d427b87086d33573fb2d7228c5c34ea6640eefa9564485a79638e9c97c0af84cfee7ce4a739220c8429e067143953d550668dadc84e7bed9ab070a5943390c611d75b1cb12873a37d9850661a0077bfa9ca9b8b263766c149ff0ee4b4adba25eaf7d7f501f362454256bc1269378ef3359a8ed6b960b86621fa3b613eb132122f49f2eb2ceb6832a3991e961cb0e78b742ef4d65e8de3469666fec7c5b874789571c5c99a2c02a053ff7d2fc90076bafe1f267fa81a3990f27ff14f03000af00c59286cb9bb98e204e90190ae2a50edef049ea92a1f785088f94adf6588fb43bb40fbe2324235cc7e168b80264b069f944f503692c949234d5b76bcffabe29ff9064bd7cbed9e00e5b7fdda4312eb801465f127d0ca68832a7f4ed0eaed8f559c1631cd4d34f0dc414d9fcfe849a91e25f3e0ff013a8cffa806ed8e93d08a1e5a757682ca3d26abc869c76f1c79007d559dfe67e78d8af0195808b0e771c71e64b5716fb36309c25025fae6414c28bbdbd4de597a74996c9da974920d59e6f4c2edfe110ff817fd480a5080978048865712058c5fe7b560b12b67f737ea6e2af9242cf07ad0a8a679f26430046adc3e70664cc9c0ee5abcef6d726b4e04176048b795be12851bdb74003a13204119b86864d6535ba095040a85d9781cf4f3480a304e227f787ad538e68f4bab014179e30d3fdef9eff11bcf471fa3a0bc74b5576f302d3a6b499f11f2ef326ac026c98db10e2741413f322228b3cff0f337ba2f294c78ef73f0e877878f8fc7ff6d10bce66ad6284379b80ca89327d4db0bf14e6d8f01b22ab202b716cc07e3c8866d168a5094bac5a495e73868eedc27222e6444f83bcf65acdc3ec89120bb50e8abfc28b78e6d980c775f4849a0e8cada80240bca245e39966e89a0344df8363a7dcc81b201ce9c753ad544e1124e21020d4c62deda9ed9b9d1f2fb7c54ca7ab09f383bef48cfc6848c271302a10fa687f56e00e0a7d093c927b4fdd8f1bedf6288a0e302848a8012f127a79d2d30a06ce17d94aa6f7f8a1e6eb9d0681c3774f614cc6dbcb2a813f925c6306a630572a83ec109d5f533c0584cb421d919: +a1ac48aa5ffa3d800819d03b7f62babf291f20904c11a6400e4f45205f103e380854e0340f814985fb122b78729479e3fde855c211cadeae56f0d4dc0828d5fa:0854e0340f814985fb122b78729479e3fde855c211cadeae56f0d4dc0828d5fa:d6f124ed752021c10926972a0c26f3b1838b3c7af247c18009a231ecce964bf6698637833f607dca836f8a606c72ae3cb170174447a2cce583f6e244dbc163e215b9820de7496ffc5b7050c48f2830246678cba4dc5caa07c1458563aa2d10dcb7770ef8fede027dd7f20ddc8cc78c3a2e2e958bd18c0006cf8fb82d44e53e1da7aa80fd1006f3b2300c9b079d8a66f1e4a3f47061f9e2f45dae35dc295204b19460ca5707ab57ce215a24c10faab3fa20bccd101e7a7d70077599f3d6725707552129cad757d6514c1b28997e471f94b0fded8fbbd065dead196d2c07d3dfa7b9fb3bae7680f76621200d099eebebbea0e8957df5b5e204ca3e9e2952b8a30f0a131a6867b1381e394b1b444310f076326656cf9341678008e9525147d8d61ce93d3bf53900cab912663717e0987293833d1902d7fb047b997b86026c467d7bb17cf45796738f7a774ac126764ed4eb45124309f4586260176ba465918d48330a9cc18c4ecea0ddaf38946acc0e361dd40a7e9133ceb50e1c317ea42bd0980a72b8ba3d8a6c7693dd5602f374f2664df4ba56df01e882fca42cb4db621f476c76e1ea9fd105911a74b77952d9914a5ac0f98a900c1b2e1a56c4ea8518a9ee47c4ed14d0bd35eca560319c8ea24755d71a4e030850bc4dc60389f325804021204ccebc25fedbd32edd8d8446aa23ce56a85f779e858d36af7c073c115e341f412c660fab800fe74c50e714ee086e2fbc8d7abbf3e98fb40ca27f1f01a9aadd8cc2275c2dd3f76e4c1d81c4b792daecc9fe66044941b8b2918486dd4acb562a7b58ad8c60c21b83cf48aefa7256a1ed809e669811f484364970bc5695089919bc32d28ea752e8e318ceff467f77ae1977c5ffd79c17c2da8bc7f823dd94398683189945f8b79238a4e815b142b866acbdbcb7aea7f143fffb7cc2b4b54bbf361afda913ad6df1e49dfd6b532642e63f55d893a470d40370665cfb74efd3f59cb0ff6006174ca35f53b97c543e08af4bf5bb75ff9031610652a3f6f2a0cfe97e7a521f3d2a289114ded34772b0e49817bde1cb924ff514e2866a09e3ede0782d2c0c98e6814b8c1e778cf8306348c933adb2e472dba09db954ff49648373395a2f0181958feb1ea2834c99532873db5c88eb5289c77e90015203ef502ac8e1c48fa1a06dafa6519d52dae3c5567570dd2434e671927c66363f783156893f138a84c75664b30ae4275112736d53d4f399ddda3d23067c073f521afba1f7be585513c2cec9c8f08d2a22c3c85392cd2ae50f3928251f86b310c69a0f8c4e853ab3f3e8129b0566ef4bbbe80b8c02c8928a4de56c0d119a45bbf5af1808d488852d8a45beb0d683248a4d65de1526b3d1d2ffc1f22215b608468cbc3bd39514b397fc0db0f113dbe6fce4652e82ff895b2b4387e041d7e4e7bde4694769665e81:c57e3c091ed24e5e84665bd9bb102db49797df9008f05557fa0d5ad7a295e5e4d2a4716b17f8c91cb12f5abfb1af027fb0411199acc5d285d842a4b65bde4902d6f124ed752021c10926972a0c26f3b1838b3c7af247c18009a231ecce964bf6698637833f607dca836f8a606c72ae3cb170174447a2cce583f6e244dbc163e215b9820de7496ffc5b7050c48f2830246678cba4dc5caa07c1458563aa2d10dcb7770ef8fede027dd7f20ddc8cc78c3a2e2e958bd18c0006cf8fb82d44e53e1da7aa80fd1006f3b2300c9b079d8a66f1e4a3f47061f9e2f45dae35dc295204b19460ca5707ab57ce215a24c10faab3fa20bccd101e7a7d70077599f3d6725707552129cad757d6514c1b28997e471f94b0fded8fbbd065dead196d2c07d3dfa7b9fb3bae7680f76621200d099eebebbea0e8957df5b5e204ca3e9e2952b8a30f0a131a6867b1381e394b1b444310f076326656cf9341678008e9525147d8d61ce93d3bf53900cab912663717e0987293833d1902d7fb047b997b86026c467d7bb17cf45796738f7a774ac126764ed4eb45124309f4586260176ba465918d48330a9cc18c4ecea0ddaf38946acc0e361dd40a7e9133ceb50e1c317ea42bd0980a72b8ba3d8a6c7693dd5602f374f2664df4ba56df01e882fca42cb4db621f476c76e1ea9fd105911a74b77952d9914a5ac0f98a900c1b2e1a56c4ea8518a9ee47c4ed14d0bd35eca560319c8ea24755d71a4e030850bc4dc60389f325804021204ccebc25fedbd32edd8d8446aa23ce56a85f779e858d36af7c073c115e341f412c660fab800fe74c50e714ee086e2fbc8d7abbf3e98fb40ca27f1f01a9aadd8cc2275c2dd3f76e4c1d81c4b792daecc9fe66044941b8b2918486dd4acb562a7b58ad8c60c21b83cf48aefa7256a1ed809e669811f484364970bc5695089919bc32d28ea752e8e318ceff467f77ae1977c5ffd79c17c2da8bc7f823dd94398683189945f8b79238a4e815b142b866acbdbcb7aea7f143fffb7cc2b4b54bbf361afda913ad6df1e49dfd6b532642e63f55d893a470d40370665cfb74efd3f59cb0ff6006174ca35f53b97c543e08af4bf5bb75ff9031610652a3f6f2a0cfe97e7a521f3d2a289114ded34772b0e49817bde1cb924ff514e2866a09e3ede0782d2c0c98e6814b8c1e778cf8306348c933adb2e472dba09db954ff49648373395a2f0181958feb1ea2834c99532873db5c88eb5289c77e90015203ef502ac8e1c48fa1a06dafa6519d52dae3c5567570dd2434e671927c66363f783156893f138a84c75664b30ae4275112736d53d4f399ddda3d23067c073f521afba1f7be585513c2cec9c8f08d2a22c3c85392cd2ae50f3928251f86b310c69a0f8c4e853ab3f3e8129b0566ef4bbbe80b8c02c8928a4de56c0d119a45bbf5af1808d488852d8a45beb0d683248a4d65de1526b3d1d2ffc1f22215b608468cbc3bd39514b397fc0db0f113dbe6fce4652e82ff895b2b4387e041d7e4e7bde4694769665e81: +f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e:278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e:08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0:0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a0308b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0: diff --git a/src/pycryptopp/testvectors/xsalsa20.txt b/src/pycryptopp/testvectors/xsalsa20.txt new file mode 100644 index 0000000..f7e81ca --- /dev/null +++ b/src/pycryptopp/testvectors/xsalsa20.txt @@ -0,0 +1,102 @@ + +COUNT=1 +KEY=a6a7251c1e72916d11c2cb214d3c252539121d8e234e652d651fa4c8cff88030 +IV=9e645a74e9e0a60d8243acd9177ab51a1beb8d5a2f5d700c +PLAINTEXT=093c5e5585579625337bd3ab619d615760d8c5b224a85b1d0efe0eb8a7ee163abb0376529fcc09bab506c618e13ce777d82c3ae9d1a6f972d4160287cbfe60bf2130fc0a6ff6049d0a5c8a82f429231f008082e845d7e189d37f9ed2b464e6b919e6523a8c1210bd52a02a4c3fe406d3085f5068d1909eeeca6369abc981a42e87fe665583f0ab85ae71f6f84f528e6b397af86f6917d9754b7320dbdc2fea81496f2732f532ac78c4e9c6cfb18f8e9bdf74622eb126141416776971a84f94d156beaf67aecbf2ad412e76e66e8fad7633f5b6d7f3d64b5c6c69ce29003c6024465ae3b89be78e915d88b4b5621d +CIPHERTEXT=b2af688e7d8fc4b508c05cc39dd583d6714322c64d7f3e63147aede2d9534934b04ff6f337b031815cd094bdbc6d7a92077dce709412286822ef0737ee47f6b7ffa22f9d53f11dd2b0a3bb9fc01d9a88f9d53c26e9365c2c3c063bc4840bfc812e4b80463e69d179530b25c158f543191cff993106511aa036043bbc75866ab7e34afc57e2cce4934a5faae6eabe4f221770183dd060467827c27a354159a081275a291f69d946d6fe28ed0b9ce08206cf484925a51b9498dbde178ddd3ae91a8581b91682d860f840782f6eea49dbb9bd721501d2c67122dea3b7283848c5f13e0c0de876bd227a856e4de593a3 + +COUNT=2 +KEY=9e1da239d155f52ad37f75c7368a536668b051952923ad44f57e75ab588e475a +IV=af06f17859dffa799891c4288f6635b5c5a45eee9017fd72 +PLAINTEXT=feac9d54fc8c115ae247d9a7e919dd76cfcbc72d32cae4944860817cbdfb8c04e6b1df76a16517cd33ccf1acda9206389e9e318f5966c093cfb3ec2d9ee2de856437ed581f552f26ac2907609df8c613b9e33d44bfc21ff79153e9ef81a9d66cc317857f752cc175fd8891fefebb7d041e6517c3162d197e2112837d3bc4104312ad35b75ea686e7c70d4ec04746b52ff09c421451459fb59f +CIPHERTEXT=2c261a2f4e61a62e1b27689916bf03453fcbc97bb2af6f329391ef063b5a219bf984d07d70f602d85f6db61474e9d9f5a2deecb4fcd90184d16f3b5b5e168ee03ea8c93f3933a22bc3d1a5ae8c2d8b02757c87c073409052a2a8a41e7f487e041f9a49a0997b540e18621cad3a24f0a56d9b19227929057ab3ba950f6274b121f193e32e06e5388781a1cb57317c0ba6305e910961d01002f0 + +COUNT=3 +KEY=d5c7f6797b7e7e9c1d7fd2610b2abf2bc5a7885fb3ff78092fb3abe8986d35e2 +IV=744e17312b27969d826444640e9c4a378ae334f185369c95 +PLAINTEXT=7758298c628eb3a4b6963c5445ef66971222be5d1a4ad839715d1188071739b77cc6e05d5410f963a64167629757 +CIPHERTEXT=27b8cfe81416a76301fd1eec6a4d99675069b2da2776c360db1bdfea7c0aa613913e10f7a60fec04d11e65f2d64e + +COUNT=4 +KEY=737d7811ce96472efed12258b78122f11deaec8759ccbd71eac6bbefa627785c +IV=6fb2ee3dda6dbd12f1274f126701ec75c35c86607adb3edd +PLAINTEXT=501325fb2645264864df11faa17bbd58312b77cad3d94ac8fb8542f0eb653ad73d7fce932bb874cb89ac39fc47f8267cf0f0c209f204b2d8578a3bdf461cb6a271a468bebaccd9685014ccbc9a73618c6a5e778a21cc8416c60ad24ddc417a130d53eda6dfbfe47d09170a7be1a708b7b5f3ad464310be36d9a2a95dc39e83d38667e842eb6411e8a23712297b165f690c2d7ca1b1346e3c1fccf5cafd4f8be0 +CIPHERTEXT=6724c372d2e9074da5e27a6c54b2d703dc1d4c9b1f8d90f00c122e692ace7700eadca942544507f1375b6581d5a8fb39981c1c0e6e1ff2140b082e9ec016fce141d5199647d43b0b68bfd0fea5e00f468962c7384dd6129aea6a3fdfe75abb210ed5607cef8fa0e152833d5ac37d52e557b91098a322e76a45bbbcf4899e790618aa3f4c2e5e0fc3de93269a577d77a5502e8ea02f717b1dd2df1ec69d8b61ca + +COUNT=5 +KEY=760158da09f89bbab2c99e6997f9523a95fcef10239bcca2573b7105f6898d34 +IV=43636b2cc346fc8b7c85a19bf507bdc3dafe953b88c69dba +PLAINTEXT=d30a6d42dff49f0ed039a306bae9dec8d9e88366cc19e8c3642fd58fa0794ebf8029d949730339b0823a51f0f49f0d2c71f1051c1e0e2c86941f172789cdb1b0107413e70f982ff9761877bb526ef1c3eb1106a948d60ef21bd35d32cfd64f89b79ed63ecc5cca56246af736766f285d8e6b0da9cb1cd21020223ffacc5a32 +CIPHERTEXT=c815b6b79b64f9369aec8dce8c753df8a50f2bc97c70ce2f014db33a65ac5816bac9e30ac08bdded308c65cb87e28e2e71b677dc25c5a6499c1553555daf1f55270a56959dffa0c66f24e0af00951ec4bb59ccc3a6c5f52e0981647e53e439313a52c40fa7004c855b6e6eb25b212a138e843a9ba46edb2a039ee82a263abe + +COUNT=6 +KEY=27ba7e81e7edd4e71be53c07ce8e633138f287e155c7fa9e84c4ad804b7fa1b9 +IV=ea05f4ebcd2fb6b000da0612861ba54ff5c176fb601391aa +PLAINTEXT=e09ff5d2cb050d69b2d42494bde5825238c756d6991d99d7a20d1ef0b83c371c89872690b2fc11d5369f4fc4971b6d3d6c078aef9b0f05c0e61ab89c025168054defeb03fef633858700c58b1262ce011300012673e893e44901dc18eee3105699c44c805897bdaf776af1833162a21a +CIPHERTEXT=a23e7ef93c5d0667c96d9e404dcbe6be62026fa98f7a3ff9ba5d458643a16a1cef7272dc6097a9b52f35983557c77a11b314b4f7d5dc2cca15ee47616f861873cbfed1d32372171a61e38e447f3cf362b3abbb2ed4170d89dcb28187b7bfd206a3e026f084a7e0ed63d319de6bc9afc0 + +COUNT=7 +KEY=6799d76e5ffb5b4920bc2768bafd3f8c16554e65efcf9a16f4683a7a06927c11 +IV=61ab951921e54ff06d9b77f313a4e49df7a057d5fd627989 +PLAINTEXT=472766 +CIPHERTEXT=8fd7df + +COUNT=8 +KEY=f68238c08365bb293d26980a606488d09c2f109edafa0bbae9937b5cc219a49c +IV=5190b51e9b708624820b5abdf4e40fad1fb950ad1adc2d26 +PLAINTEXT=47ec6b1f73c4b7ff5274a0bfd7f45f864812c85a12fbcb3c2cf8a3e90cf66ccf2eacb521e748363c77f52eb426ae57a0c6c78f75af71284569e79d1a92f949a9d69c4efc0b69902f1e36d7562765543e2d3942d9f6ff5948d8a312cff72c1afd9ea3088aff7640bfd265f7a9946e606abc77bcedae6bddc75a0dba0bd917d73e3bd1268f727e0096345da1ed25cf553ea7a98fea6b6f285732de37431561ee1b3064887fbcbd71935e02 +CIPHERTEXT=36160e88d3500529ba4edba17bc24d8cfaca9a0680b3b1fc97cf03f3675b7ac301c883a68c071bc54acdd3b63af4a2d72f985e51f9d60a4c7fd481af10b2fc75e252fdee7ea6b6453190617dcc6e2fe1cd56585fc2f0b0e97c5c3f8ad7eb4f31bc4890c03882aac24cc53acc1982296526690a220271c2f6e326750d3fbda5d5b63512c831f67830f59ac49aae330b3e0e02c9ea0091d19841f1b0e13d69c9fbfe8a12d6f30bb734d9d2 + +COUNT=9 +KEY=45b2bd0de4ed9293ec3e26c4840faaf64b7d619d51e9d7a2c7e36c83d584c3df +IV=546c8c5d6be8f90952cab3f36d7c1957baaa7a59abe3d7e5 +PLAINTEXT=5007c8cd5b3c40e17d7fe423a87ae0ced86bec1c39dc07a25772f3e96dabd56cd3fd7319f6c9654925f2d87087a700e1b130da796895d1c9b9acd62b266144067d373ed51e787498b03c52faad16bb3826fa511b0ed2a19a8663f5ba2d6ea7c38e7212e9697d91486c49d8a000b9a1935d6a7ff7ef23e720a45855481440463b4ac8c4f6e7062adc1f1e1e25d3d65a31812f58a71160 +CIPHERTEXT=8eacfba568898b10c0957a7d44100685e8763a71a69a8d16bc7b3f88085bb9a2f09642e4d09a9f0ad09d0aad66b22610c8bd02ff6679bb92c2c026a216bf425c6be35fb8dae7ff0c72b0efd6a18037c70eed0ca90062a49a3c97fdc90a8f9c2ea536bfdc41918a7582c9927fae47efaa3dc87967b7887dee1bf071734c7665901d9105dae2fdf66b4918e51d8f4a48c60d19fbfbbcba + +COUNT=10 +KEY=fe559c9a282beb40814d016d6bfcb2c0c0d8bf077b1110b8703a3ce39d70e0e1 +IV=b076200cc7011259805e18b304092754002723ebec5d6200 +PLAINTEXT=6db65b9ec8b114a944137c821fd606be75478d928366d5284096cdef782fcff7e8f59cb8ffcda979757902c5ffa6bc477ceaa4cb5d5ea76f94d91e833f823a6bc78f1055dfa6a97bea8965c1cde67a668e001257334a585727d9e0f7c1a06e88d3d25a4e6d9096c968bf138e116a3ebeffd4bb4808adb1fd698164ba0a35c709a47f16f1f4435a2345a9194a00b95abd51851d505809a6077da9baca5831afff31578c487ee68f2767974a98a7e803aac788da98319c4ea8eaa3d394855651f484cef543f537e35158ee29 +CIPHERTEXT=4dce9c8f97a028051b0727f34e1b9ef21f06f0760f36e71713204027902090ba2bb6b13436ee778d9f50530efbd7a32b0d41443f58ccaee781c7b716d3a96fdec0e3764ed7959f34c3941278591ea033b5cbadc0f1916032e9bebbd1a8395b83fb63b1454bd775bd20b3a2a96f951246ac14daf68166ba62f6cbff8bd121ac9498ff8852fd2be975df52b5daef3829d18eda42e715022dcbf930d0a789ee6a146c2c7088c35773c63c06b4af4559856ac199ced86863e4294707825337c5857970eb7fddeb263781309011 + +COUNT=11 +KEY=0ae10012d7e56614b03dcc89b14bae9242ffe630f3d7e35ce8bbb97bbc2c92c3 +IV=f96b025d6cf46a8a12ac2af1e2aef1fb83590adadaa5c5ea +PLAINTEXT=ea0f354e96f12bc72bbaa3d12b4a8ed879b042f0689878f46b651cc4116d6f78409b11430b3aaa30b2076891e8e1fa528f2fd169ed93dc9f84e24409eec2101daf4d057be2492d11de640cbd7b355ad29fb70400fffd7cd6d425abeeb732a0eaa4330af4c656252c4173deab653eb85c58462d7ab0f35fd12b613d29d473d330310dc323d3c66348bbdbb68a326324657cae7b77a9e34358f2cec50c85609e73056856796e3be8d62b6e2fe9f953 +CIPHERTEXT=e8abd48924b54e5b80866be7d4ebe5cf4274cafff08b39cb2d40a8f0b472398aedc776e0793812fbf1f60078635d2ed86b15efcdba60411ee23b07233592a44ec31b1013ce8964236675f8f183aef885e864f2a72edf4215b5338fa2b54653dfa1a8c55ce5d95cc605b9b311527f2e3463ffbec78a9d1d65dabad2f338769c9f43f133a791a11c7eca9af0b771a4ac32963dc8f631a2c11217ac6e1b9430c1aae1ceebe22703f429998a8fb8c641 + +COUNT=12 +KEY=082c539bc5b20f97d767cd3f229eda80b2adc4fe49c86329b5cd6250a9877450 +IV=845543502e8b64912d8f2c8d9fffb3c69365686587c08d0c +PLAINTEXT=a96bb7e910281a6dfad7c8a9c370674f0ceec1ad8d4f0de32f9ae4a23ed329e3d6bc708f876640a229153ac0e7281a8188dd77695138f01cda5f41d5215fd5c6bdd46d982cb73b1efe2997970a9fdbdb1e768d7e5db712068d8ba1af6067b5753495e23e6e1963af012f9c7ce450bf2de619d3d59542fb55f3 +CIPHERTEXT=835da74fc6de08cbda277a7966a07c8dcd627e7b17adde6d930b6581e3124b8baad096f693991fedb1572930601fc7709541839b8e3ffd5f033d2060d999c6c6e3048276613e648000acb5212cc632a916afce290e20ebdf612d08a6aa4c79a74b070d3f872a861f8dc6bb07614db515d363349d3a8e3336a3 + +COUNT=13 +KEY=3d02bff3375d403027356b94f514203737ee9a85d2052db3e4e5a217c259d18a +IV=74216c95031895f48c1dba651555ebfa3ca326a755237025 +PLAINTEXT=0d4b0f54fd09ae39baa5fa4baccf2e6682e61b257e01f42b8f +CIPHERTEXT=16c4006c28365190411eb1593814cf15e74c22238f210afc3d + +COUNT=14 +KEY=ad1a5c47688874e6663a0f3fa16fa7efb7ecadc175c468e5432914bdb480ffc6 +IV=e489eed440f1aae1fac8fb7a9825635454f8f8f1f52e2fcc +PLAINTEXT=aa6c1e53580f03a9abb73bfdadedfecada4c6b0ebe020ef10db745e54ba861caf65f0e40dfc520203bb54d29e0a8f78f16b3f1aa525d6bfa33c54726e59988cfbec78056 +CIPHERTEXT=02fe84ce81e178e7aabdd3ba925a766c3c24756eefae33942af75e8b464556b5997e616f3f2dfc7fce91848afd79912d9fb55201b5813a5a074d2c0d4292c1fd441807c5 + +COUNT=15 +KEY=053a02bedd6368c1fb8afc7a1b199f7f7ea2220c9a4b642a6850091c9d20ab9c +IV=c713eea5c26dad75ad3f52451e003a9cb0d649f917c89dde +PLAINTEXT=8f0a8a164760426567e388840276de3f95cb5e3fadc6ed3f3e4fe8bc169d9388804dcb94b6587dbb66cb0bd5f87b8e98b52af37ba290629b858e0e2aa7378047a26602 +CIPHERTEXT=516710e59843e6fbd4f25d0d8ca0ec0d47d39d125e9dad987e0518d49107014cb0ae405e30c2eb3794750bca142ce95e290cf95abe15e822823e2e7d3ab21bc8fbd445 + +COUNT=16 +KEY=5b14ab0fbed4c58952548a6cb1e0000cf4481421f41288ea0aa84add9f7deb96 +IV=54bf52b911231b952ba1a6af8e45b1c5a29d97e2abad7c83 +PLAINTEXT=37fb44a675978b560ff9a4a87011d6f3ad2d37a2c3815b45a3c0e6d1b1d8b1784cd468927c2ee39e1dccd4765e1c3d676a335be1ccd6900a45f5d41a317648315d8a8c24adc64eb285f6aeba05b9029586353d303f17a807658b9ff790474e1737bd5fdc604aeff8dfcaf1427dcc3aacbb0256badcd183ed75a2dc52452f87d3c1ed2aa583472b0ab91cda20614e9b6fdbda3b49b098c95823cc72d8e5b717f2314b0324e9ce +CIPHERTEXT=ae6deb5d6ce43d4b09d0e6b1c0e9f46157bcd8ab50eaa3197ff9fa2bf7af649eb52c68544fd3adfe6b1eb316f1f23538d470c30dbfec7e57b60cbcd096c782e7736b669199c8253e70214cf2a098fda8eac5da79a9496a3aae754d03b17c6d70d1027f42bf7f95ce3d1d9c338854e158fcc803e4d6262fb639521e47116ef78a7a437ca9427ba645cd646832feab822a208278e45e93e118d780b988d65397eddfd7a819526e + +COUNT=17 +KEY=d74636e3413a88d85f322ca80fb0bd650bd0bf0134e2329160b69609cd58a4b0 +IV=efb606aa1d9d9f0f465eaa7f8165f1ac09f5cb46fecf2a57 +PLAINTEXT=f85471b75f6ec81abac2799ec09e98e280b2ffd64ca285e5a0109cfb31ffab2d617b2c2952a2a8a788fc0da2af7f530758f74f1ab56391ab5ff2adbcc5be2d6c7f49fbe8118104c6ff9a23c6dfe52f57954e6a69dcee5db06f514f4a0a572a9a8525d961dae72269b987189d465df6107119c7fa790853e063cba0fab7800ca932e258880fd74c33c784675bedad0e7c09e9cc4d63dd5e9713d5d4a0196e6b562226ac31b4f57c04f90a181973737ddc7e80f364112a9fbb435ebdbcabf7d490ce52 +CIPHERTEXT=b2b795fe6c1d4c83c1327e015a67d4465fd8e32813575cbab263e20ef05864d2dc17e0e4eb81436adfe9f638dcc1c8d78f6b0306baf938e5d2ab0b3e05e735cc6fff2d6e02e3d60484bea7c7a8e13e23197fea7b04d47d48f4a4e5944174539492800d3ef51e2ee5e4c8a0bdf050c2dd3dd74fce5e7e5c37364f7547a11480a3063b9a0a157b15b10a5a954de2731ced055aa2e2767f0891d4329c426f3808ee867bed0dc75b5922b7cfb895700fda016105a4c7b7f0bb90f029f6bbcb04ac36ac16 diff --git a/versioneer.py b/versioneer.py new file mode 100644 index 0000000..c05d831 --- /dev/null +++ b/versioneer.py @@ -0,0 +1,648 @@ +#! /usr/bin/python + +"""versioneer.py + +(like a rocketeer, but for versions) + +* https://github.com/warner/python-versioneer +* Brian Warner +* License: Public Domain +* Version: 0.7 + +This file helps distutils-based projects manage their version number by just +creating version-control tags. + +For developers who work from a VCS-generated tree (e.g. 'git clone' etc), +each 'setup.py version', 'setup.py build', 'setup.py sdist' will compute a +version number by asking your version-control tool about the current +checkout. The version number will be written into a generated _version.py +file of your choosing, where it can be included by your __init__.py + +For users who work from a VCS-generated tarball (e.g. 'git archive'), it will +compute a version number by looking at the name of the directory created when +te tarball is unpacked. This conventionally includes both the name of the +project and a version number. + +For users who work from a tarball built by 'setup.py sdist', it will get a +version number from a previously-generated _version.py file. + +As a result, loading code directly from the source tree will not result in a +real version. If you want real versions from VCS trees (where you frequently +update from the upstream repository, or do new development), you will need to +do a 'setup.py version' after each update, and load code from the build/ +directory. + +You need to provide this code with a few configuration values: + + versionfile_source: + A project-relative pathname into which the generated version strings + should be written. This is usually a _version.py next to your project's + main __init__.py file. If your project uses src/myproject/__init__.py, + this should be 'src/myproject/_version.py'. This file should be checked + in to your VCS as usual: the copy created below by 'setup.py + update_files' will include code that parses expanded VCS keywords in + generated tarballs. The 'build' and 'sdist' commands will replace it with + a copy that has just the calculated version string. + + versionfile_build: + Like versionfile_source, but relative to the build directory instead of + the source directory. These will differ when your setup.py uses + 'package_dir='. If you have package_dir={'myproject': 'src/myproject'}, + then you will probably have versionfile_build='myproject/_version.py' and + versionfile_source='src/myproject/_version.py'. + + tag_prefix: a string, like 'PROJECTNAME-', which appears at the start of all + VCS tags. If your tags look like 'myproject-1.2.0', then you + should use tag_prefix='myproject-'. If you use unprefixed tags + like '1.2.0', this should be an empty string. + + parentdir_prefix: a string, frequently the same as tag_prefix, which + appears at the start of all unpacked tarball filenames. If + your tarball unpacks into 'myproject-1.2.0', this should + be 'myproject-'. + +To use it: + + 1: include this file in the top level of your project + 2: make the following changes to the top of your setup.py: + import versioneer + versioneer.versionfile_source = 'src/myproject/_version.py' + versioneer.versionfile_build = 'myproject/_version.py' + versioneer.tag_prefix = '' # tags are like 1.2.0 + versioneer.parentdir_prefix = 'myproject-' # dirname like 'myproject-1.2.0' + 3: add the following arguments to the setup() call in your setup.py: + version=versioneer.get_version(), + cmdclass=versioneer.get_cmdclass(), + 4: run 'setup.py update_files', which will create _version.py, and will + append the following to your __init__.py: + from _version import __version__ + 5: modify your MANIFEST.in to include versioneer.py + 6: add both versioneer.py and the generated _version.py to your VCS +""" + +import os, sys, re +from distutils.core import Command +from distutils.command.sdist import sdist as _sdist +from distutils.command.build import build as _build + +versionfile_source = None +versionfile_build = None +tag_prefix = None +parentdir_prefix = None + +VCS = "git" +IN_LONG_VERSION_PY = False + + +LONG_VERSION_PY = ''' +IN_LONG_VERSION_PY = True +# This file helps to compute a version number in source trees obtained from +# git-archive tarball (such as those provided by githubs download-from-tag +# feature). Distribution tarballs (build by setup.py sdist) and build +# directories (produced by setup.py build) will contain a much shorter file +# that just contains the computed version number. + +# This file is released into the public domain. Generated by +# versioneer-0.7 (https://github.com/warner/python-versioneer) + +# these strings will be replaced by git during git-archive +git_refnames = "%(DOLLAR)sFormat:%%d%(DOLLAR)s" +git_full = "%(DOLLAR)sFormat:%%H%(DOLLAR)s" + + +import subprocess + +def run_command(args, cwd=None, verbose=False): + try: + # remember shell=False, so use git.cmd on windows, not just git + p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd) + except EnvironmentError, e: + if verbose: + print "unable to run %%s" %% args[0] + print e + return None + stdout = p.communicate()[0].strip() + if p.returncode != 0: + if verbose: + print "unable to run %%s (error)" %% args[0] + return None + return stdout + + +import sys +import re +import os.path + +def get_expanded_variables(versionfile_source): + # the code embedded in _version.py can just fetch the value of these + # variables. When used from setup.py, we don't want to import + # _version.py, so we do it with a regexp instead. This function is not + # used from _version.py. + variables = {} + try: + for line in open(versionfile_source,"r").readlines(): + if line.strip().startswith("git_refnames ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + variables["refnames"] = mo.group(1) + if line.strip().startswith("git_full ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + variables["full"] = mo.group(1) + except EnvironmentError: + pass + return variables + +def versions_from_expanded_variables(variables, tag_prefix, verbose=False): + refnames = variables["refnames"].strip() + if refnames.startswith("$Format"): + if verbose: + print "variables are unexpanded, not using" + return {} # unexpanded, so not in an unpacked git-archive tarball + refs = set([r.strip() for r in refnames.strip("()").split(",")]) + for ref in list(refs): + if not re.search(r'\d', ref): + if verbose: + print "discarding '%%s', no digits" %% ref + refs.discard(ref) + # Assume all version tags have a digit. git's %%d expansion + # behaves like git log --decorate=short and strips out the + # refs/heads/ and refs/tags/ prefixes that would let us + # distinguish between branches and tags. By ignoring refnames + # without digits, we filter out many common branch names like + # "release" and "stabilization", as well as "HEAD" and "master". + if verbose: + print "remaining refs:", ",".join(sorted(refs)) + for ref in sorted(refs): + # sorting will prefer e.g. "2.0" over "2.0rc1" + if ref.startswith(tag_prefix): + r = ref[len(tag_prefix):] + if verbose: + print "picking %%s" %% r + return { "version": r, + "full": variables["full"].strip() } + # no suitable tags, so we use the full revision id + if verbose: + print "no suitable tags, using full revision id" + return { "version": variables["full"].strip(), + "full": variables["full"].strip() } + +def versions_from_vcs(tag_prefix, versionfile_source, verbose=False): + # this runs 'git' from the root of the source tree. That either means + # someone ran a setup.py command (and this code is in versioneer.py, so + # IN_LONG_VERSION_PY=False, thus the containing directory is the root of + # the source tree), or someone ran a project-specific entry point (and + # this code is in _version.py, so IN_LONG_VERSION_PY=True, thus the + # containing directory is somewhere deeper in the source tree). This only + # gets called if the git-archive 'subst' variables were *not* expanded, + # and _version.py hasn't already been rewritten with a short version + # string, meaning we're inside a checked out source tree. + + try: + here = os.path.abspath(__file__) + except NameError: + # some py2exe/bbfreeze/non-CPython implementations don't do __file__ + return {} # not always correct + + # versionfile_source is the relative path from the top of the source tree + # (where the .git directory might live) to this file. Invert this to find + # the root from __file__. + root = here + if IN_LONG_VERSION_PY: + for i in range(len(versionfile_source.split("/"))): + root = os.path.dirname(root) + else: + root = os.path.dirname(here) + if not os.path.exists(os.path.join(root, ".git")): + if verbose: + print "no .git in", root + return {} + + GIT = "git" + if sys.platform == "win32": + GIT = "git.cmd" + stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"], + cwd=root) + if stdout is None: + return {} + if not stdout.startswith(tag_prefix): + if verbose: + print "tag '%%s' doesn't start with prefix '%%s'" %% (stdout, tag_prefix) + return {} + tag = stdout[len(tag_prefix):] + stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root) + if stdout is None: + return {} + full = stdout.strip() + if tag.endswith("-dirty"): + full += "-dirty" + return {"version": tag, "full": full} + + +def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False): + if IN_LONG_VERSION_PY: + # We're running from _version.py. If it's from a source tree + # (execute-in-place), we can work upwards to find the root of the + # tree, and then check the parent directory for a version string. If + # it's in an installed application, there's no hope. + try: + here = os.path.abspath(__file__) + except NameError: + # py2exe/bbfreeze/non-CPython don't have __file__ + return {} # without __file__, we have no hope + # versionfile_source is the relative path from the top of the source + # tree to _version.py. Invert this to find the root from __file__. + root = here + for i in range(len(versionfile_source.split("/"))): + root = os.path.dirname(root) + else: + # we're running from versioneer.py, which means we're running from + # the setup.py in a source tree. sys.argv[0] is setup.py in the root. + here = os.path.abspath(sys.argv[0]) + root = os.path.dirname(here) + + # Source tarballs conventionally unpack into a directory that includes + # both the project name and a version string. + dirname = os.path.basename(root) + if not dirname.startswith(parentdir_prefix): + if verbose: + print "guessing rootdir is '%%s', but '%%s' doesn't start with prefix '%%s'" %% \ + (root, dirname, parentdir_prefix) + return None + return {"version": dirname[len(parentdir_prefix):], "full": ""} + +tag_prefix = "%(TAG_PREFIX)s" +parentdir_prefix = "%(PARENTDIR_PREFIX)s" +versionfile_source = "%(VERSIONFILE_SOURCE)s" + +def get_versions(default={"version": "unknown", "full": ""}, verbose=False): + variables = { "refnames": git_refnames, "full": git_full } + ver = versions_from_expanded_variables(variables, tag_prefix, verbose) + if not ver: + ver = versions_from_vcs(tag_prefix, versionfile_source, verbose) + if not ver: + ver = versions_from_parentdir(parentdir_prefix, versionfile_source, + verbose) + if not ver: + ver = default + return ver + +''' + + +import subprocess + +def run_command(args, cwd=None, verbose=False): + try: + # remember shell=False, so use git.cmd on windows, not just git + p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd) + except EnvironmentError, e: + if verbose: + print "unable to run %s" % args[0] + print e + return None + stdout = p.communicate()[0].strip() + if p.returncode != 0: + if verbose: + print "unable to run %s (error)" % args[0] + return None + return stdout + + +import sys +import re +import os.path + +def get_expanded_variables(versionfile_source): + # the code embedded in _version.py can just fetch the value of these + # variables. When used from setup.py, we don't want to import + # _version.py, so we do it with a regexp instead. This function is not + # used from _version.py. + variables = {} + try: + for line in open(versionfile_source,"r").readlines(): + if line.strip().startswith("git_refnames ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + variables["refnames"] = mo.group(1) + if line.strip().startswith("git_full ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + variables["full"] = mo.group(1) + except EnvironmentError: + pass + return variables + +def versions_from_expanded_variables(variables, tag_prefix, verbose=False): + refnames = variables["refnames"].strip() + if refnames.startswith("$Format"): + if verbose: + print "variables are unexpanded, not using" + return {} # unexpanded, so not in an unpacked git-archive tarball + refs = set([r.strip() for r in refnames.strip("()").split(",")]) + for ref in list(refs): + if not re.search(r'\d', ref): + if verbose: + print "discarding '%s', no digits" % ref + refs.discard(ref) + # Assume all version tags have a digit. git's %d expansion + # behaves like git log --decorate=short and strips out the + # refs/heads/ and refs/tags/ prefixes that would let us + # distinguish between branches and tags. By ignoring refnames + # without digits, we filter out many common branch names like + # "release" and "stabilization", as well as "HEAD" and "master". + if verbose: + print "remaining refs:", ",".join(sorted(refs)) + for ref in sorted(refs): + # sorting will prefer e.g. "2.0" over "2.0rc1" + if ref.startswith(tag_prefix): + r = ref[len(tag_prefix):] + if verbose: + print "picking %s" % r + return { "version": r, + "full": variables["full"].strip() } + # no suitable tags, so we use the full revision id + if verbose: + print "no suitable tags, using full revision id" + return { "version": variables["full"].strip(), + "full": variables["full"].strip() } + +def versions_from_vcs(tag_prefix, versionfile_source, verbose=False): + # this runs 'git' from the root of the source tree. That either means + # someone ran a setup.py command (and this code is in versioneer.py, so + # IN_LONG_VERSION_PY=False, thus the containing directory is the root of + # the source tree), or someone ran a project-specific entry point (and + # this code is in _version.py, so IN_LONG_VERSION_PY=True, thus the + # containing directory is somewhere deeper in the source tree). This only + # gets called if the git-archive 'subst' variables were *not* expanded, + # and _version.py hasn't already been rewritten with a short version + # string, meaning we're inside a checked out source tree. + + try: + here = os.path.abspath(__file__) + except NameError: + # some py2exe/bbfreeze/non-CPython implementations don't do __file__ + return {} # not always correct + + # versionfile_source is the relative path from the top of the source tree + # (where the .git directory might live) to this file. Invert this to find + # the root from __file__. + root = here + if IN_LONG_VERSION_PY: + for i in range(len(versionfile_source.split("/"))): + root = os.path.dirname(root) + else: + root = os.path.dirname(here) + if not os.path.exists(os.path.join(root, ".git")): + if verbose: + print "no .git in", root + return {} + + GIT = "git" + if sys.platform == "win32": + GIT = "git.cmd" + stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"], + cwd=root) + if stdout is None: + return {} + if not stdout.startswith(tag_prefix): + if verbose: + print "tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix) + return {} + tag = stdout[len(tag_prefix):] + stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root) + if stdout is None: + return {} + full = stdout.strip() + if tag.endswith("-dirty"): + full += "-dirty" + return {"version": tag, "full": full} + + +def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False): + if IN_LONG_VERSION_PY: + # We're running from _version.py. If it's from a source tree + # (execute-in-place), we can work upwards to find the root of the + # tree, and then check the parent directory for a version string. If + # it's in an installed application, there's no hope. + try: + here = os.path.abspath(__file__) + except NameError: + # py2exe/bbfreeze/non-CPython don't have __file__ + return {} # without __file__, we have no hope + # versionfile_source is the relative path from the top of the source + # tree to _version.py. Invert this to find the root from __file__. + root = here + for i in range(len(versionfile_source.split("/"))): + root = os.path.dirname(root) + else: + # we're running from versioneer.py, which means we're running from + # the setup.py in a source tree. sys.argv[0] is setup.py in the root. + here = os.path.abspath(sys.argv[0]) + root = os.path.dirname(here) + + # Source tarballs conventionally unpack into a directory that includes + # both the project name and a version string. + dirname = os.path.basename(root) + if not dirname.startswith(parentdir_prefix): + if verbose: + print "guessing rootdir is '%s', but '%s' doesn't start with prefix '%s'" % \ + (root, dirname, parentdir_prefix) + return None + return {"version": dirname[len(parentdir_prefix):], "full": ""} + +import sys + +def do_vcs_install(versionfile_source, ipy): + GIT = "git" + if sys.platform == "win32": + GIT = "git.cmd" + run_command([GIT, "add", "versioneer.py"]) + run_command([GIT, "add", versionfile_source]) + run_command([GIT, "add", ipy]) + present = False + try: + f = open(".gitattributes", "r") + for line in f.readlines(): + if line.strip().startswith(versionfile_source): + if "export-subst" in line.strip().split()[1:]: + present = True + f.close() + except EnvironmentError: + pass + if not present: + f = open(".gitattributes", "a+") + f.write("%s export-subst\n" % versionfile_source) + f.close() + run_command([GIT, "add", ".gitattributes"]) + + +SHORT_VERSION_PY = """ +# This file was generated by 'versioneer.py' (0.7) from +# revision-control system data, or from the parent directory name of an +# unpacked source archive. Distribution tarballs contain a pre-generated copy +# of this file. + +version_version = '%(version)s' +version_full = '%(full)s' +def get_versions(default={}, verbose=False): + return {'version': version_version, 'full': version_full} + +""" + +DEFAULT = {"version": "unknown", "full": "unknown"} + +def versions_from_file(filename): + versions = {} + try: + f = open(filename) + except EnvironmentError: + return versions + for line in f.readlines(): + mo = re.match("version_version = '([^']+)'", line) + if mo: + versions["version"] = mo.group(1) + mo = re.match("version_full = '([^']+)'", line) + if mo: + versions["full"] = mo.group(1) + return versions + +def write_to_version_file(filename, versions): + f = open(filename, "w") + f.write(SHORT_VERSION_PY % versions) + f.close() + print "set %s to '%s'" % (filename, versions["version"]) + + +def get_best_versions(versionfile, tag_prefix, parentdir_prefix, + default=DEFAULT, verbose=False): + # returns dict with two keys: 'version' and 'full' + # + # extract version from first of _version.py, 'git describe', parentdir. + # This is meant to work for developers using a source checkout, for users + # of a tarball created by 'setup.py sdist', and for users of a + # tarball/zipball created by 'git archive' or github's download-from-tag + # feature. + + variables = get_expanded_variables(versionfile_source) + if variables: + ver = versions_from_expanded_variables(variables, tag_prefix) + if ver: + if verbose: print "got version from expanded variable", ver + return ver + + ver = versions_from_file(versionfile) + if ver: + if verbose: print "got version from file %s" % versionfile, ver + return ver + + ver = versions_from_vcs(tag_prefix, versionfile_source, verbose) + if ver: + if verbose: print "got version from git", ver + return ver + + ver = versions_from_parentdir(parentdir_prefix, versionfile_source, verbose) + if ver: + if verbose: print "got version from parentdir", ver + return ver + + if verbose: print "got version from default", ver + return default + +def get_versions(default=DEFAULT, verbose=False): + assert versionfile_source is not None, "please set versioneer.versionfile_source" + assert tag_prefix is not None, "please set versioneer.tag_prefix" + assert parentdir_prefix is not None, "please set versioneer.parentdir_prefix" + return get_best_versions(versionfile_source, tag_prefix, parentdir_prefix, + default=default, verbose=verbose) +def get_version(verbose=False): + return get_versions(verbose=verbose)["version"] + +class cmd_version(Command): + description = "report generated version string" + user_options = [] + boolean_options = [] + def initialize_options(self): + pass + def finalize_options(self): + pass + def run(self): + ver = get_version(verbose=True) + print "Version is currently:", ver + + +class cmd_build(_build): + def run(self): + versions = get_versions(verbose=True) + _build.run(self) + # now locate _version.py in the new build/ directory and replace it + # with an updated value + target_versionfile = os.path.join(self.build_lib, versionfile_build) + print "UPDATING", target_versionfile + os.unlink(target_versionfile) + f = open(target_versionfile, "w") + f.write(SHORT_VERSION_PY % versions) + f.close() + +class cmd_sdist(_sdist): + def run(self): + versions = get_versions(verbose=True) + self._versioneer_generated_versions = versions + # unless we update this, the command will keep using the old version + self.distribution.metadata.version = versions["version"] + return _sdist.run(self) + + def make_release_tree(self, base_dir, files): + _sdist.make_release_tree(self, base_dir, files) + # now locate _version.py in the new base_dir directory (remembering + # that it may be a hardlink) and replace it with an updated value + target_versionfile = os.path.join(base_dir, versionfile_source) + print "UPDATING", target_versionfile + os.unlink(target_versionfile) + f = open(target_versionfile, "w") + f.write(SHORT_VERSION_PY % self._versioneer_generated_versions) + f.close() + +INIT_PY_SNIPPET = """ +from ._version import get_versions +__version__ = get_versions()['version'] +del get_versions +""" + +class cmd_update_files(Command): + description = "modify __init__.py and create _version.py" + user_options = [] + boolean_options = [] + def initialize_options(self): + pass + def finalize_options(self): + pass + def run(self): + ipy = os.path.join(os.path.dirname(versionfile_source), "__init__.py") + print " creating %s" % versionfile_source + f = open(versionfile_source, "w") + f.write(LONG_VERSION_PY % {"DOLLAR": "$", + "TAG_PREFIX": tag_prefix, + "PARENTDIR_PREFIX": parentdir_prefix, + "VERSIONFILE_SOURCE": versionfile_source, + }) + f.close() + try: + old = open(ipy, "r").read() + except EnvironmentError: + old = "" + if INIT_PY_SNIPPET not in old: + print " appending to %s" % ipy + f = open(ipy, "a") + f.write(INIT_PY_SNIPPET) + f.close() + else: + print " %s unmodified" % ipy + do_vcs_install(versionfile_source, ipy) + +def get_cmdclass(): + return {'version': cmd_version, + 'update_files': cmd_update_files, + 'build': cmd_build, + 'sdist': cmd_sdist, + } -- cgit v1.2.3