summaryrefslogtreecommitdiff
path: root/lib/crypto/test/crypto_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/crypto/test/crypto_SUITE.erl')
-rw-r--r--lib/crypto/test/crypto_SUITE.erl158
1 files changed, 144 insertions, 14 deletions
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index a2adaf8ed0..0572feaf33 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -1,7 +1,7 @@
%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2022. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2023. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -82,6 +82,8 @@
generate_compute/1,
hash/0,
hash/1,
+ hash_xof/0,
+ hash_xof/1,
hash_info/0,
hash_info/1,
hmac/0,
@@ -250,6 +252,8 @@ groups() ->
{group, sha3_384},
{group, sha3_512},
{group, sha512},
+ {group, shake128},
+ {group, shake256},
{group, sha},
{group, dh},
@@ -375,6 +379,8 @@ groups() ->
{sha3_256, [], [hash, hmac, hmac_update]},
{sha3_384, [], [hash, hmac, hmac_update]},
{sha3_512, [], [hash, hmac, hmac_update]},
+ {shake128, [], [hash_xof]},
+ {shake256, [], [hash_xof]},
{blake2b, [], [hash, hmac, hmac_update]},
{blake2s, [], [hash, hmac, hmac_update]},
{no_blake2b, [], [no_hash, no_hmac]},
@@ -405,11 +411,11 @@ groups() ->
{ecdh, [], [compute, generate, use_all_ecdh_generate_compute]},
{eddh, [], [compute, generate, use_all_eddh_generate_compute]},
{srp, [], [generate_compute]},
- {des_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
+ {des_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac, cmac_update]},
{des_cfb, [], [api_ng, api_ng_one_shot, api_ng_tls]},
- {des_ede3_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac]},
+ {des_ede3_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac, cmac_update]},
{des_ede3_cfb, [], [api_ng, api_ng_one_shot, api_ng_tls]},
- {rc2_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
+ {rc2_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac, cmac_update]},
{aes_cfb8, [], []},
{aes_128_cfb8, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{aes_192_cfb8, [], [api_ng, api_ng_one_shot, api_ng_tls]},
@@ -420,7 +426,7 @@ groups() ->
{aes_192_cfb128, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{aes_256_cfb128, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{no_aes_cfb128, [], [no_support]},
- {blowfish_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
+ {blowfish_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac, cmac_update]},
{blowfish_ecb, [], [api_ng, api_ng_one_shot]},
{blowfish_cfb64, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{blowfish_ofb64, [], [api_ng, api_ng_one_shot, api_ng_tls]},
@@ -467,15 +473,15 @@ groups() ->
{des_ede3_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{des_ede3_cfb, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{aes_128_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac, cmac_update]},
- {aes_192_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
- {aes_256_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac]},
+ {aes_192_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac, cmac_update]},
+ {aes_256_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls, cmac, cmac_update]},
{aes_128_ctr, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{aes_192_ctr, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{aes_256_ctr, [], [api_ng, api_ng_one_shot, api_ng_tls]},
{aes_128_ccm, [], [aead_ng, aead_bad_tag]},
{aes_192_ccm, [], [aead_ng, aead_bad_tag]},
{aes_256_ccm, [], [aead_ng, aead_bad_tag]},
- {aes_128_ecb, [], [api_ng, api_ng_one_shot, cmac_update]},
+ {aes_128_ecb, [], [api_ng, api_ng_one_shot]},
{aes_192_ecb, [], [api_ng, api_ng_one_shot]},
{aes_256_ecb, [], [api_ng, api_ng_one_shot]},
{aes_128_gcm, [], [aead_ng, aead_bad_tag]},
@@ -776,6 +782,14 @@ hash(Config) when is_list(Config) ->
hash(Type, Msgs, Digests),
hash(Type, lists:map(fun iolistify/1, Msgs), Digests),
hash_increment(Type, Inc, IncrDigest).
+
+hash_xof() ->
+ [{doc, "Test all different hash_xof functions"}].
+hash_xof(Config) when is_list(Config) ->
+ {Type, MsgsLE, Digests, Lengths} = proplists:get_value(hash_xof, Config),
+ Msgs = lazy_eval(MsgsLE),
+ hash_xof(Type, Msgs, Digests, Lengths).
+
%%--------------------------------------------------------------------
no_hash() ->
[{doc, "Test all disabled hash functions"}].
@@ -1249,7 +1263,7 @@ use_all_ec_sign_verify(_Config) ->
Msg = <<"hello world!">>,
Sups = crypto:supports(),
Curves = proplists:get_value(curves, Sups),
- Hashs = proplists:get_value(hashs, Sups),
+ Hashs = proplists:get_value(hashs, Sups) -- [shake128, shake256],
ct:log("Lib: ~p~nFIPS: ~p~nCurves:~n~p~nHashs: ~p", [crypto:info_lib(),
crypto:info_fips(),
Curves,
@@ -1552,6 +1566,16 @@ hash(Type, [Msg | RestMsg], [Digest| RestDigest]) ->
ct:fail({{crypto, hash, [Type, Msg]}, {expected, Digest}, {got, Other}})
end.
+hash_xof(_, [], [], []) ->
+ ok;
+hash_xof(Type, [Msg | RestMsg], [Digest | RestDigest], [Length | RestLength]) ->
+ case crypto:hash_xof(Type, Msg, Length) of
+ Digest ->
+ hash_xof(Type, RestMsg, RestDigest, RestLength);
+ Other ->
+ ct:fail({{crypto, hash_xof, [Type, Msg, Length]}, {expected, Digest}, {got, Other}})
+ end.
+
hash_increment(Type, Increments, Digest) ->
State = crypto:hash_init(Type),
case hash_increment(State, Increments) of
@@ -2178,6 +2202,12 @@ group_config(sha3_384 = Type, Config) ->
group_config(sha3_512 = Type, Config) ->
{Msgs,Digests} = sha3_test_vectors(Type),
[{hash, {Type, Msgs, Digests}} | Config];
+group_config(shake128 = Type, Config) ->
+ {Msgs,Digests,Lengths} = sha3_shake128_test_vectors(Type),
+ [{hash_xof, {Type, Msgs, Digests, Lengths}} | Config];
+group_config(shake256 = Type, Config) ->
+ {Msgs,Digests,Lengths} = sha3_shake256_test_vectors(Type),
+ [{hash_xof, {Type, Msgs, Digests, Lengths}} | Config];
group_config(blake2b = Type, Config) ->
{Msgs, Digests} = blake2_test_vectors(Type),
[{hash, {Type, Msgs, Digests}} | Config];
@@ -2348,6 +2378,8 @@ do_configure_mac(cmac, Cipher, Config) ->
case Cipher of
aes_128_cbc ->
fun() -> read_rsp(Config, Cipher, ["CMACGenAES128.rsp", "CMACVerAES128.rsp"]) end;
+ aes_192_cbc ->
+ fun() -> read_rsp(Config, Cipher, ["CMACGenAES192.rsp", "CMACVerAES192.rsp"]) end;
aes_256_cbc ->
fun() -> read_rsp(Config, Cipher, ["CMACGenAES256.rsp", "CMACVerAES256.rsp"]) end;
des_ede3_cbc ->
@@ -2574,7 +2606,106 @@ sha3_test_vectors(sha3_512) ->
]
}.
-
+%%% https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/secure-hashing
+sha3_shake128_test_vectors(shake128) ->
+ {[%% SHAKE128 ShortMsg
+ hexstr2bin(""),
+ hexstr2bin("0e"),
+ hexstr2bin("d9e8"),
+ hexstr2bin("4c386d97ace346b2a06faab35663ce8a4c54c295b5b9f6161efafce451ca8f617ab7d5ab88ffe117d6a67cdb0bc5250a3f2556c65f0c09b1d2577ba45cc930a443a33711b175af215a338a8d5e8b918a7176a8fb390e54e5f79f7a236a006a5bf1241b30efecb8b9733f5c32195d1bf22b70419d0c65de9bd7f982c94317456eca610a700a0d05c86bf27b3302e2c92ab53ba815a0b9afbcb88e1afe"),
+ hexstr2bin("5d8f84b2f208b58a68e88ce8efb543a8404f0ec0c9805c760ad359d13faab84d3f8bb1d2a4bb45e72c0ec9245ffda2e572f94e466cffa44b876d5c5ed914d1ff338e06b74ad1e74d1405d23d759356661b7f3b03a7f7c2dc0d2c2dbe3d60822803408d472b752424ea76af1d79a0e7920388dde0c1903e9364b8d6d7b3b75430754b4d6b91cd83d5740866aab34bdbd0f1bd3dc504f1a1d753ba5f938241ce7f52544e0cc2018cc67b6401ce6abdbc8aafc5629bb643730fa3daced8f425787d61069910073ac760c631876fe81d1127034a544820ad3aa51cbf2d904f8cda936c063561a8a0bd0b1f1801777394630fb6f11cb68a588000861283a2dc9d7d2739ff2ae5ed5af5304cc176cd544a39a99064c1cb3b6bcc88a97ad9f6e381e8a3929781861e91f73516d3ee59d3661b5f584b4b717d0fa7a54da03674ac5fa36d3d76412a826c4c8445f7720337119198"),
+ %% SHAKE128 LongMsg
+ hexstr2bin("a6fe00064257aa318b621c5eb311d32bb8004c2fa1a969d205d71762cc5d2e633907992629d1b69d9557ff6d5e8deb454ab00f6e497c89a4fea09e257a6fa2074bd818ceb5981b3e3faefd6e720f2d1edd9c5e4a5c51e5009abf636ed5bca53fe159c8287014a1bd904f5c8a7501625f79ac81eb618f478ce21cae6664acffb30572f059e1ad0fc2912264e8f1ca52af26c8bf78e09d75f3dd9fc734afa8770abe0bd78c90cc2ff448105fb16dd2c5b7edd8611a62e537db9331f5023e16d6ec150cc6e706d7c7fcbfff930c7281831fd5c4aff86ece57ed0db882f59a5fe403105d0592ca38a081fed84922873f538ee774f13b8cc09bd0521db4374aec69f4bae6dcb66455822c0b84c91a3474ffac2ad06f0a4423cd2c6a49d4f0d6242d6a1890937b5d9835a5f0ea5b1d01884d22a6c1718e1f60b3ab5e232947c76ef70b344171083c688093b5f1475377e3069863"),
+ hexstr2bin("c747ee72b00680920ef1f2e16d32567e7d8900b76749832a61a3dc2a8126ec65ce872cc39d9e9c911bb2fcde26f63f2561533d2d8768a82effd04135b1a34bc9193f40cf9948c4ab14edd7a8b86d4e9a1bda84c28a1e4df19e3b2bf00fd7c520cdf7945e4d0be029212beb07cca06c24d4a63e3d19705abc646d032543ca40b015388f3861efd8536cf2a0c30a957f0db43dd467db68b7d77ced2f9af584a5c3178899247cfc94711acd5ea31956709be229ac08790d4c8a0c431918cc0edd9ffb721aeb463bfccb56418d70a2eb281787f230e89a67011d3df82766706fcf8cea7b7a5569b3f9a946d895f24c5a8ec9ca1ec7cee77fbfd73693c34e8aaf62d40c2d222a8a6c71521219def1c0ad89f8d437d883075c6c02209c5496c2d780be880f7832546f4e0fe38cd035a5ec03edccc5cdd0a306f2e4229b4207bfed109186a9e5356cc37628e1bad485a41de3f1db4e0d7b638637c56519f4692afcf9963084d2fa7d70d3e5332a50ab654a114a295c004ceee325ef109ed484aa092515ac27a54a2d7f4b8d0264ae6d8f7a7440dd760e0ded25a3a94cb0491fe81e7b55221ac8ed24f7c86a75f15494cab6f61d20259f840755983a41d9bb048b42e3a0bbe6a1ab0be031c2b558ace8c0057e2719ef1b7ae57aeeeb16a092f93c7e453c9e129a4c8a436edee9211c30166ff5a8f15feab82f9c8c04f48d37c7a3d98972f5261997482766063ad50e3677fc41e6cffa74038cc35acd02291036675b988ae5ab8855ee940382d0fbe9c089b54b2adc4a2226a4f8408d69fb860d310c58cc98284e4e23922c99d21b1597f4a1fbbb3fd65ae72042268e508c0216a8f5b2803625d34a902ac99468befa8361c83ae321268510a8aaf416e062ea17751d8eede62a7f11dd63c3bbbc6b004b7833eee8aac30c67e337926e4007a7d93f8cd55cd1c0ba6ab1460056f3aa8fb9e0e90013013455b57af1e8de9a03a224af4b6d151f6eec1fb4d969ad38030f9342f259ac4f01cac114e0dfad13dc42bf6d614060f7bd7df68f26e608b1ffe8a24557dffbbbb3d2555a0d5d25d51cee7420d635858134d5b8ea3560ae862582ae921f7c476ed1d437f47f4b8c084a100970b333cbe75b5c2d6c0cbde8e0fd457fd05217da90e33a30893e922bd3ef0f4707ff247c4eba7b1cbeb5e7fee7109adca8f998fa48716b08c153184a5f9253f68ac2efdee0da984e8838c438c2e5e78ec21be6f0be04cf8746c5c731d4bb44dea4047c3ac5421d8c719b3edd9a05955ec5c0eb041b23ce75bd9c862759f34ac6fbceb3d7257a709c21e83c3796f60d115af08e7d8757d099d1e13c7516c0cd7837277cff270bfb464127a58cdf42b67228b4b7a529273dbc289bd36434ad35ba0118bff8f37c2454795e63259c70f748d8134ec22a1b7da66ad2323adb3fea5501a8640bb255558c70975d4af6093a5a11163c1db1bbf81f408e413f32005411dedf53808c1ff5b8cfd97b431594e6717cc467fee79017ef52d8e8bd6277dbb540c5749fa8606c9e3d2da55720996355c025b8acf42140dd47b70ffa922ce80bd163afaf2fa321076399c3cf3fa118ce86411771fff6dcb3c7349e3feba8e1d936c0edfa486d7ebae828bdf39c336fa476216d93309854377c567dd4957230e81ae414c61c48ea8176df7b0b5cd7cf9e37cca05bb08e0e320b259501b7123b0023d80e5cd3bbcd22b2c8e65faa15a086724a9a11a760746b1fa9cc0e7a116ce8f9a3c104944f906646eae437ac764b22cea441fd3d97edac5eeb0b4205f62a6a454d1706878a9915da4d5eda8a81363bf4e17f6798bae0bb70f23be78149dc4cafdff7a9d5f751f715fa3d916dbfca988b093b96e351b761fec642431593ec57de604836a61b20d3a0f867a47db66f033c255dd344e5d966b0700a9eea5ac1537bd8f4f521806f73224fc65be1f08e42af3bcc66e3fdae922df779422729c3082d50e22e6fada49d440841fdc2f58d1e8b567297e9219ead1e637976f5855a3e9dcefa29b72a291aae2abfd4474bd65f797b36ae7ed9117e2abdf1817cf8eebc735d242d228064b207bd2a26997ccfcd20b400f2c9ae6fcefa0cc8ace309e74b56024884d836bf2cf8ca693cdf10e22f2908b8acf32720653558e83f5341adb3eec74e7400d4a0522857645e428d764f3b80472423cd8c0b84a93882f326a8bce4b31e46c3e271ea406f03d4ea7df2f3ff2293a282261c888f08a0bcec42412de0cea14248e999bde7172ee5fe67c0e41cf8856e38bc36a3fd7c0837651dded08921bdafb8718093c659cddaa6d447ea3b0a05cf6c174425770e5839873de96b88b35bd73a008e34843cc8fb0c4befcc045efc0f47bdacd7a4c5780b792cc8c7848d6400f7202b67cac80790555420541efe5074f038d87e2da951f56472e5ac26b5be731658bff5400672e1ac77424832f2eb478f102ee5b9c2c93e7095a6e216355378c030b2a78dfdf236373dbd71e740b3cf4ecb18d3f119c930c41f7530fb1509561d316c435ab66dd61e2dfa97e6f2925653f3fc0f7cb53a118998b95f7e5bca5754e256914e37cc0a8ad05f82d7106f22c60f4462049e022ae686d93746117dc18eccd65b128af81aa3ac55f960a0317cd0a857942edd0bc304733f80fc3e0addf27555674db7d84e904b45c62cacc2ac99459d6da4793b240be6520247eb58f3a9673c7ea8c453ed7a3595afe13b09fa486e7eb50e7a7c9422687a85d01f514bda2af168cbbb534188f0af7d2856eeae05ac623313e9b55d71801fd03ee2dc2cae44deed5da3bf90e306f9f8a804590ffa85b1b05ccdcec521b6a9ac3a3ce1e04d3f69d507857e23b2ffdde70a4d32664c83d3f4912eae155a9281e16c3649addea3fce770687a421e61c113f53961fb262e31c759143f94439d0d377bd7fadc89f6feec40549a354fb60f4512d1cf16ae0d31f15c88688c055eb6761028ddb478c2d7ad2152c6436c852e43091c62ff0ca83c3943911143c75de465d22fda7fd08eeeefb968e6b59d5786d5812203fd6987bb68b6382202b22300cd6af6da83bce3ad7db0a1e3d30cb37fc522ec9b5aed3314465c848411ee3770767f85c30a62487b1eaf02a3e5de2181da9581105cbf33b19bde7d1db8a2219e28bae27f5aea45c0995e950f333e29f4db82ea4c4c080ff82fe32bd63ff76af0abc317f4bb7d62e5b764610f0552544091902d3572ef5053ca149798ed1499d0c6412c0c77432850406a6e8ca24229cdc46854b5159d7d293319c8490c2136a543dc27add5631e6afc17c56c533731043bb266b37e391ee13399c6d2e248cad7e83d12c11c05cd9bb2146d996059f24bc0156c16f6ecbbe5923d9a1cb8afdcce7e0cf42f9553bb4c2c086ef911cff60b19396dc8c3dedd9c18ac4b0ed57ef4f1ccf0d6df887272e3309cd176adc2c5ad0fc771b02d360b6e8c8ee18f83de9aaa9c92bfb93c8d7aca87789df77e59e5976a6781b67e1dcec3b88d658908f75761b49ab7a5fbca5967f943da63cabde033f2c0a3c2fcbaad03624fdee3adf0b27cddafc78b0b5199244da590a4da153ee86f7be1bcf1363096537c5485baf13464df79f553b54bc1684d48c8a1f68a851da83f438ca3b8dfe553bdcf577724638182a24be541e05a9abfd18a4266443f3c66b5d01b5b6943562aba58402bafca3b8ecfd129f737eb246cebdc6f716af3ac7185904f6070e3529f1af62b20baeefbcaaa8e081f79fc6d1c3cc81060242ad591568b11fcf647427b85b2fd9c6e5927ffdb8a6800cd16dd966c550d7b9c6b1f8ed0ca4a7523f88c86a5939fe8f29229f50acd33e35cc0dca4248b4e0af73ef22f9c54e0141e7d9a881fa1f94c6f216774de604f104e82d20c0c73bc55602bb63d6231bd21105ed2499ee4f30f0d8f4b44ff4aa6cfcae42797cb143da4fdbbd381c96ac7e420249e90c865767bf3623b2c16931e68f86f430d0a77ba3ef675b1c07a06e8a477566527452b68d64a25a1f6cb44a12201aa8f3670a21c6c74e2b8c51d0d07ab3c7c8ed4be3eb369395de468c56316470d1d71daa69f49769f88515759880b3f981f8360dba73d7ce9946c4badfb641d435152c053762ba49ef1e23dd67edea9b3c6ab93436df0578251a1662a1175edcccd9bb1202da93d9aa5d5403df76731b4f96e349f98b2412b1deb83e5af30fed019b275b4ceaa8bba2a902836fb8e1ec440340d96316d840c7fb26885dc7d9a76be01d4b96018d4270a7dbd68933bba0a2465e4d13e08664eff5edeb3a14407e643ee96d4ecda6108cd02c67cc6564baf2c6982f7ca6b30192557ad17056d8e4930e382af79d87a86f9890d199dc71adae1a9afb1da7e29947a059d5810e177c70e4761f20ffa67c9187958e81e766fb4c98b32a778299be885d1761fca860a876482fb45b6286ff8b13a7091534c92656e78d580ab54cc3cce21ff133c458fb2bafc184e774adb3b4d341dbb442fca1458d95ee57ce705b9de5e01dd6d074d6f991c80b85948f3bc73cf260ef80860e90d14967df1ca8e873cf1452465b28de7874cfa29650affa0ab73553477c09c0d179345f115e5afcd704090912d2f97410ef45049a27847127e8870d2c93dc6a8febc33e8ed20b0b403b5adcccc67b3a6b67a48c2187b133872764093f76926e148f9270b8364d8637cb7627c4a41293e0647ab39cff9aa3a11a58d1c072b04e17fb1eb02de97710263ad7949b0a4403086c34059d0db5541e37d1f18046aa7d02a4b457406a3c1bb4101b8dd057a41a5be56d1c7220a5c756f67bd2df31058d5d231fe09046e11b49d1ae8dd51aa74c43769242ecd6d07fd3dc93103de045f18fecade6adfe2a815ff60d1f49c1c21b678620334daeb9d01d50c4143cc2e04c2367eac3f9fe6d007ef3b3ac8efb890a209ab3481506e68abc099b695c6768ffb03b5322f4d61cfb2f613ec01516609b173aa7fbe37ddae2185d757a0d3c447eaebd736e3ef3dee3d9b50b048cb0ed30b3dc9ae93971fb88bac2dee0dfb0075b8784c8103906175d0675a4c45649837d7ef6f87a7791ece12bd0541834612618c327ddb3635b5ac95e19a889f24ec7d3e1203d4a3e4c138de41c61aabbde2538fa0d00b24e821dab191762efe13f2ed672def5b2ee1f03d16c0d73f2d675993e94aaedb76b08d494fff57040c3a93ce7ac89ae5f1779326e2c0a278b04d5d68c1b88011d496e13f95b4a6d46ea0b56aa16b6c3994ae933b6bcb8e8fdc75d71c3f73ac76e5a00505ab37c964cf4d4107029fcd21be8ed6c4d968034a5be9b0f58d029cd252d8e1e3ba102a7cd54a20eec5eb25631720450954206973d2b1ce3cd0edb6edc2465e20eac82fe6289e386713d8dcc8486bc852037929d0ecd31b3833bd648edef1620662e64269715173b914ed5a18f97748e60efda92a4f597e33dbf90d7f4ee1d6db4bf2cacc586cb82eefb2081bd14dab0e9e345248a34ade73f3291886b91ea3e8cc742fd884f6ee0ccdaf4c9879f4db12dba58cf491af2541a1d5ef6cc8b1af750ef5d8559ef7ff9cd56d8f599974be3aecd8c0f4c08f3ae50d86f9f822a1e4ca39fd2f0b4d78d22630733a24d8d63ecdf9555411daf205a761c39ef46ff6292e74129bc13a7f4ff20549b3c2de2142152ca5b21384e16ecfc215462659b865ebe7be84410d175e477d7864fb545db158ab4f40c268625da45a03595886f08247bb8852516d45e76fc087b396e29375df9edb68e62e80ba6f51153f509ea6678b18f86eba0213d2b0f5fe0a5d2fca75f22ed191467e406d78cfd361d74ae0fcfe25973e43758807534466d016e40a99d982ba22abfeac5e07fbc625b432a829ea0bec2bb66eac6f9fd6456d8aa85bc9dbc41e85dd59cb7664fd75f4b1fd05d695f1809eda9488f0ded326498124c6ed41198321a435a59bd7fe6837945300eb4800d9fd7690237356638eccc30052ed54ab735ec83b43b6a726285426de9f504b6081b1530986e151ac075e17e308b159a275a41012acb01d9c3cb52f43eceee638002339a8b72015d918674675ee229b26125b4562e86f81892cc0772defab61b0dcbaef15c01aea104a4f195f0f26615dd0eb2fd500dd1b1481dfc542af7003f29fdd3ff7a8b51a79237e554970a6f2723abd9611fbe13266c279e22a34261623d0f6eff778dbec3e2d5cc5da1b8b978bd53742bee1620fa677f5978e86b3e06ef86cc8bc3773a784f05230bb17bb98d12bc2fb85bb4afbfd29bdaa16ae01aaf99ea792efed659476f3c65d946c203d6bc3c7880e90803c935f38e369b3f6bbec4a0f1537a399fb39be21150c23a1ce8125acb20068ec1a8fa1ce0c309d7c5d70850c183d60f624f8d9cc20cb4225923ddadb41034b76df1977e7eb12747ad6add50665a82c6656d9cd2d467ad496d2c569bafdc14206d15b6aeb4ab841d76fcac565c2210fd1da0420ae4fc1dedbd6415ab3addf54843a7a0142efc90c7d70efda91f850121df9a25db602476adce6da362c1b088ad860a1c555a2eedb5321469ef2cfdc3c33f8db09ac28b57f814ab7838f0de2eaea8cf63c8a2dcfb841c9f498f00e6e96fb22d6aefa89b226b24902cc434c157fa205a1f04a5713aa2fb22450f47fad265dbebcd307ede766572ce096b0a04a4ee915cb69fee763ba0522fc4f64e842f64213b4013b1cfb47583c7b6b3ed02961a5029c2d0ca666eeab62a41caa12d40e906ae7bffedd97d19dbefbd255a659bfc0153bc6de5cc5500aba453f2cc50c74310b7d95b8fa630d0efd88545de883702096d1bcdad027e80871074154c892320b3e9d0bd139060294404878be5f4e7dafcd85956acc35bc8ed111a989e50d50084b6faab16329b815ce66c6e0d363ed530180dbf51697d785208cff32e225d40f791cf9c14073387af008c62c0c69c8f67ce915e377f43ed3a79fccb98883c80712cc8167978d89acee570108d109167f84e9cc9bb7f4fb62ae7396859fcf33da5ca6c80c311eb392107afeddebebe0d662a887879e4014187d2fe8feefb01e6fa0d35819d7cfbf139e99451423b62ee35e4dce0ef48094df5bfc478c3fcf90ae257bb9f44f48b419dfde5f133f12068ebf012998805b809e92023d9759d4917f35c4710761309a8b1c6fd34407a972bfcfeb218d0b7ae23d68685187036629ca16d90ab9d7307a509d74290e4520795ed4343d565d85c1a326570cc4062d617711e00c7178ef5b52aa16ead8bf222353170306593e2326ba13f6f4b62ad3406e6e02fd990b1645788b7c9d0c3e557986e08103ff76fc1869796e93c636fdcf9875666798594c40aa87d0ca118a6182df77d5bcb0ccb99f989ee6715af45515db6e35d1d62a3a55d0e737f94f6bef47472329b9d50a02c32fcb8714dc2a831a20a096c4bb45878bd3f4dbb32ea9a7cea42da283d4f67e8d17487906b2a12fe65054b2c7af74dceb99f3e47f160b3021e0dd6aa11759d604365de3cf4621008251d2b0621a7de17b0b2f7ae66f5b3348e17ba99b04fab2317552edf5fe729ef50d62b91d64293d4511efc36fa15f5749914f86fa05a3b81abc6ec102445bb2476a4cf581f5409951947aeaa214e0452ed6a12a44811a93c9f4fb847e7fa5e48052d78b15358a9ca57a19150730a5a4ff9ab8bd04e028e946033f61ef1618dba9ac4ca4618dcfef4bad146d275e781dc2c4dd66bf89956397d3837edf737c40ca60f367ee63d6394b13b31989041f58813c584dffe629a8c64b0e03d5fd99bae95514fd43206823ab963e41b58c63fc43ea719b4b5eac61db522a195a1c37f21075f78de92d4d55751dfc0f345c0cb111b670782c59e535dcd21de8f5381d8f46a7e44066f04d76b18f36a98ddee221f2889c0b293f9dcdd3b230972eb9143a94d3223e44d32f2e65d634374878adf2ee483e7dca799cd0c7daab4e8d08e49b00e1faae0a3dbd279bd93ee2ee9434cc0dde9ef5976daae7c131d6379b8b555995bab4b84196bd065a809cd1069940585832049c19848fbac8a1f877dfab2e1d584498867045f876abb3952e18ef993dd62cb89ad72612f0e4125b39e1d0398e5368ed3d1fb4361d945a721eacfe07248fb5011659bcfd311d6a45a32a633c558d0ffd08d74a3fa3205d7ccb4b2d52b58cb3293828ac16277c92ffdd41ca00190e1f0e0d1e6fdab154a4f85d7ce64197d410762acb6026780872d110ae6f4d83df8269747f8bd1ef3a1831fcc8919d736fb23111ca3ef4cccaf20264fab8eb3b071e56667f06ea04d99f6eceb6942ef06683a118aeb04accc8fbdc00ac0fa1e88edd1c0ba849ee993922f6fece58bcb7c0691064fe1dee1f0c73a50d4cdb38327da5058a81baa455638a12b298450f6f854ec42042eda96e9e44a6b2638479c3db60570b92c2d6e15ebd0a139dc4eec1be190672038743618454271878722940b0f55bb864ca4ae432a52648643b235572b21e82c755849fc88d7066130c1354044c59b77e38c907e829ae79751374d2a901547919be34d172d5c8c5bcbcfea5e04d993068751bf28730e9d059b5aae16bedf07f7e2a1a9e8816795dfceab1db4be0624cabea084c17a4207297878d29c16039bb8001ffaf1437c9555afcf59f4eedfe32cefe58bda16c9b8ab7f3e453b2427856a6acabab1d2001d65f5b9299f05cb30c5918d2ef2b70a23e426079064779f6787891e63bacb96807916f50703915caffd5a24087c0987db6bf3612eb87eef8477f197807c8ea48117ba0f7cc31008a35c903683065cc731bb6dc78a97a89c9ee42ac28b6799be71ba2574e57e1063dd6bda3129024f4cd95afbc73e92833b0934ab3bff1c7b48f4e90fa1eb6500d290939ea084f04f8d44b333dca539ad2f45f1d94065fbb1d86d2ccf32f9486fe98f7c64011160ec0cd66c9c7478ed74fde7945b9c2a95cbe14cedea849978cc2d0c8eb0df48d4834030dfac2b043e793b6094a88be76b37f836a4f833467693f1aa331b97a5bbc3dbd694d96ce19d385c439b26bc16fc64919d0a5eab7ad255fbdb01fac6b2872c142a24aac69b9a20c4f2f07c9923c9f0220256b479c11c90903193d4e8f9e70a9dbdf796a49ca5c12a113d00afa844694de942601a93a5c2532031308ad63c0ded048633935f50a7e000e9695c1efc1e59c426080a7d1e69a93982a408f1f6a4769078f82f6e2b238b548e0d4af271adfa15aa02c5d7d70526e00095ffb7b74cbee4185ab54385f2707e8362e8bd1596937026f6d95e700340b6338ceba1ee854a621ce1e17a016354016200b1f98846aa46254ab15b7a128b1e840f494b2cdc9daccf14107c1e149a7fc27d33121a5cc31a4d74ea6945816a9b7a83850dc2c11d26d767eec44c74b83bfd2ef8a17c37626ed80be10262fe63cf9f804b8460c16d62ae63c8dd0d1241d8aaac5f220e750cb68d8631b162d80afd6b9bf929875bf2e2bc8e2b30e05babd8336be31e41842673a66a68f0c5acd4d7572d0a77970f42199a4da26a56df6aad2fe420e0d5e34448eb2ed33afbfb35dffaba1bf92039df89c038bae3e11c02ea08aba5240c10ea88a45a1d0a8631b269bec99a28b39a3fc5b6b5d1381f7018f15638cc5274ab8dc56a62b2e9e4feef172be20170b17ec72ff67b81c15299f165810222f6a001a281b5df1153a891206aca89ee7baa761a5af7c0493a3af840b9219e358b1ec1dd301f35d4d241b71ad70337bda42f0eadc9434a93ed28f96b6ea073608a314a7272fefd69d030cf22ee6e520b848fa705ed6160fe54bd3bf5e89608506e882a16aced9c3cf80657cd03749f34977ced9749caa9f52b683e64d96af371b293ef4e5053a8ea9422df9dd8be45d5574730f660e79bf4cbaa5f3c93a79b40f0e4e86e0fd999ef4f26c509b0940c7a3eaf1f87c560ad89aff43cd1b9d4863aa3ebc41a3dd7e5b77372b6953dae497fc7f517efe99e553052e645e8be6a3aeb362900c75ce712dfcba712c4c25583728db9a883302939655ef118d603e13fcf421d0cea0f8fb7c49224681d013250defa7d4fd64b69b0b52e95142e4cc1fb6332486716a82a3b02818b25025ccd283198b07c7d9e08519c3c52c655db94f423912b9dc1c95f2315e44be819477e7ff6d2e3ccddaa6da27722aaadf142c2b09ce9472f7fd586f68b64d71fc653decebb4397bf7af30219f25c1d496514e3c73b952b8aa57f4a2bbf7dcd4a9e0456aaeb653ca2d9fa7e2e8a532b1735c4609e9c4f393dd70901393e898ed704db8e9b03b253357f333a66aba24495e7c3d1ad1b5200b7892554b59532ac63af3bdef590b57bd5df4fbf38d2b3fa540fa5bf89455802963036bd173fe3967ed1b7d0611ed907027e72854b9c22cccff1ec72a9b6cbcf4870bf92d4bb16ed6730d1fb540ab78559e17e14e564593c68530aa384dc27b75caf427e84736711db211cc854e0bb873a8cb4f6bcc7d1b9cb8782bab111e66b215041f89d154e944946facfca3d6f8d32e4a9a3283326d55823e730a514a24b55185069850d27e51006ee6a4a7d3df7b19dde92be42c31f9cac9a9dd740c5e8664bd079d2c79d94edd57a305c3cc16754fcc64df55320e917862f6ade22dbc2b38f54721cc11a24215720aa55d8745c9ba5f35d53f0eac24735182000275e5aeb374f1ac9a6280368f07440edfce137d41de81950b86b4baa5de74613eab8216bf842bc4fd331c31335e78c8af67289bcb9073a81f63ce5bf551f555fd993a6c436b1df35d4d1e3be9bfcf59371a2d2a42be3095e56ca1104bf12c66a805b6b72672f1c023792d5c9971714bddb1ca338db0e3e4c36bd6e08f07421ba5b89eff52e1ccb3b57df19d2bbd85260bf2a6bd94aeb21e232614d4a9db5efc5d7a994dae00d8557c21140587eb337028a76ad03f00c5ca6c6704f382b5a99238124fa822163d2de02f3b9d9643a5b39c96bd7476ed457006f44e4500dd4b649f4a6918966d23c44a6d106c3e0c0076ce8848b221be5a99599599d20c9a6bfbf8e88fa5f24bb1a020a53b7a68906f422844b39128bc2bcccd148da38f3631ddacb568581ef90f4bcb9d64cffd15189e1194a51a732ce191ca38d3bf6ff7c69424799d3803bf664db41e3274e3e42312f13ec654ea59a370b8c8132e962652a8c7fcd54d87e4de2c42ef4d700445b926310bbf47768a9af2ff8df4f9ea0afc9ffc05b9a093b29e72dcda5ecb467f026337c338fbfd06ee9e074f1f2755eded032d5ef138106fcfa6eca50d8d93dc25506c2ed8796816c6fc38d53cc0be154d5bc1cd241ee4649851d91901bfd2a24a76381348c8a0024a95fbe9f2cd0ccb4330201bfa58f9d922fa0bfee369eb1a9b5b043c30f08c12a4f0b651e9542957f709b2101df035169429ea1c5a91c58c3d89366f36fa138ef996d3d6ca60fc01926ede7332ed82621767de3a0f414a405b88387505ed1fbd740db8403df66d113ce70f0ee458c707d33a4f22a980617d1bde701643d197e83adfcf57e92064ce1cfdaaa7d838ec4bef2da59ad157f28da515481999ae625776937ee377e5c9825b371807b995d87794c5486b2fcce6b622b52648ae8d6a524eb22fab8e4e8473201ec1f62d7875d2e98ca05d6aea2341ba4474692b759621eac34978d7617ee994380d3bdce8aaa6170916372bb69276944c9945b76fce0b734e3412fa289d2edf1065a070ed5f3945c410c3193a1b9cd954fda4fb82fa5911dc57419eabca89282b2feb8e8f7cd59c46f7c7dd7da7fcb0e5084e9eb60354ebf41ccd6bf1ee419713d4e5e0d7eac04416340c1e871cdf4286220a4913cf412a1eea7d0b02ef9f564fbd560ecc8f4264bc2d5a8561648bb7bfb3a1a4a2476bf5e22a1a23e6b7eb8a675106c07654a524c14c78ba126549361823dc566a531975c9426c5ea52c6d5ee3f7bc9dde212fadacf83064a20960e71ada810873dc92d25a9b3b6148386cf84c19424d0bdf2a270598482b1a361af34c415861c6c81f331e9d4fd7d7c232802a1e5e790574dcba559689b981d6bd8236be2b0a6a0108c09bb0706658b1051f036ed9c9d5ca8e8c2259bbb3dfd092bb61bac0aa676d95a35b3d65b6d5ef2efc61717ae482c887c8f749a6c43c0ce1c7549ee0eac6f60e01e6aaf7705563f441cb8f0b731455119459ce1192a172f2ce97d053728e83ba05c261ee3ce1f5a113ca30521d945b7218d250c6c515ea0cf7b3bae1e9c7fbe2d479c812c1808d7c9ce5bc198b09c1f37ee9378b06a15c786a2fc252f87a48ce9993492aa83a13cc04a49b26647b6fdceb27eb29fd4cb07f5093526d46ae51c67a964b0098176fda738f354151f34c758912d468511ece67d168d1fb7c6bfe129f0c365a3a208aee102ff234fa77420580345b0faa1f9e781435a7c441b937f9317c7101365c4a4f030b3bc6061238d6f815e6e8b25809fc42823b903ea1e4c4586f66bd33d4984775ab76be1ec9172e183bdfb90ed0f53982d8f7271a2aedbc3b6c7c55d98e5d1c8e980de5e9a6c5560830ac4b698f4c78fdbd42517e5d3a2603fb1b93d2947f177559660310b02b96f17cb766699ef401dabc84d51240b44dd7a4ab3dc3eee8805376ebe03aef3135fba566d1b604d71c425a267c7dde4178e0f0941c57a27e9f4f780243106cc07d4d352356f9c9db115d218e0e683ccaee46663ff834ba2bbb92e615f5392ebeb410b455bbdaf6ea27529825537a6438f8308f1299023dd51e43488bbf5e3d15236ba863c90092eba84a4753125c5d71dec6f176c66a34660e8b27cc6727a2ab12879bb74814a5c5da6cb78115b52f5fe83216d44913a6c5d4920940b53b646ac98b14b800bd386206e16f15222ee3e95e998692e8a79bdab87f794f73438b388fa09cceb9a451a973d0f779026f7ff68726c71a6ccb1c8d017afc6167e620ffaeeeba613a71fb826b62d8137d1f0e70acfe63d29c292fc6f9ad1cde5acd2aa66c9cf6d94ccb3bd534bf994d5ae6953e154ce2244269df6de63e602e15a0b11512d3d89fb75a1b8a170ec28e636e1e480a36ca772433316a115550b95d06be34e7bae91943c7a28a5c78dc3d5e5cb076d3e4a5320c2d2fa5c21b75e7fda757eb357ab0b0b7bad8bb4b246ec4145b54b0b77ffabfc002e00741b75621bb2c8722423ab5ccdddac6062c3a008a4d1111deff2f528508584c76d5527ccd613d53c1582381d67bd0735346e41af7d026efe8f41b34ecaed87cdbc7146d55b581c5b0bd5d9b345a43e88be24845736743f6b6db6c285c7829771f5f24b31f80a1e4d7b90f8b5042dc2b94488e0866d8102f30ff49b63d30f34528e5abd6958944b81e9661da91fb434658c0dfec38ec34a13fa7db67f79ce0efe0a1d05c1d9a134a6e9a7c0f5e4c1f40be926378516b5854c91a4ac2f285967c2edbbccf2179b6a1ad0f88b221fe1922ad0541341a1d2351b7a1bd5097b2bdf4f9da96b608efd4c5c53bac4c41d9d8f30f62a2a8f9ca3e9ff2845c974cedfe602be7879a3ac415bf9c67116426a505bbcbf1ad5d57395046610b50217afc01c7ab4ab7021fc023961cdadf82382a4783c9fa8bda9d33024feb7ec1768aa86d31614b4d761faba3522cde3d2edf304752f1c563a73180fcc17a24d61ce2b9eaa63532727ea24c40fcb3b953f1837eac302b9a5e4d7de8e5a4f546b89decf7222f0f464da3106ca09b9bb44a528cdd1f255fc0a453e7336501432c8f810f2abad3d7d0076cd1d36b37cb174ada6215483a75805c41d92826df4e1e824eb2195d9b7518c7624d494ad92b2a7a0f6deece765522aea0ba90cd46fd64b98e3f8db18dd166b60bec96e487a335037b15305ae2e7eec3f6f233053e38455dc81d4e5eb4d402fcf21781e34b1b7f0da6c3a29384142bc3cee9d974d0e70a9685b4240d156433c09c34d4ec2d7b51bf17dd0d2266c223d6ad064ac203f3fc8b4c6cd766ba6a432a93ad55aa34abf34156cd39ae90da1c221db34d98e0426065a5ad2e10aacf78635ee8cdc26893adbcebf9eee008455fd2a558ac9e6dbd814b18dff2b4ed791b93854f03dfd11cc7585fcbf460d8e9340cce5b2d7bb44ca6662e6aebf98c5273e19048c1a7782c883c38a912d508b0e2f81e2599d7bdd816de6eb6e1888e41ca76083dcdc264ac399101fd12e79e81b3c01f1eb75c8e471ada612b9c08fb2d667a7595f0d99d85227e3f2eba3fa443ed8959ae51b03183fa828d32e322db0090145db8f2942c9d8b2c7ca4d38521e0d97e533e2d7bae72feff7c31807e37a1906c4a0e9b9a18debcc23fc724611e3fbfc4953415660bfe6e79b69239c316f8aeabc3ffb394692ffc6911ff7779a248e786a7face18520e9117c1bbd79981ed32f951f301292877954979b49278b5e398ea12f6233a8b89b002271622aa7f68637d7a524e025ca0cd89ff4e3e045ff81c185d92db74bc5913627009e19b18518b60c98462c60d91ed522b3543c5a96fb9391035bd6def65025e22fede175490f0c9c3f1051e43323ccb86d169659a30b875b34693ce2b95c51ec75cdfc43c0ddae1f201ffb2076b041d978b78893b2461f3cf2f233e79d1a3cbe68bad4ad7b193d0dd1d172960248b6fe6c937db9231fbdceb573666e001e68d08f310522e6262bd0cab172c57451beafcf46f03aa40d057902693ee680dd48bb4fccf8447098ed00815c562f3b6fab56075e8a9883a268d4504047d19ddb6ee720eb4872c8f603358c1e9743c5f70fa9ab26a74360546a692594fbbfc5ad3ddca918504e5da200b84194d093a29c7de3315bd0cbb8b78c9ff8d3d52186a758145ed0ba278d416831583b8caf6fa458bb205a81a1fb2031e150896e775f6e2026a8a0e0aef6489c09269f15e77bc34299feaf5466a6431ce5b3322251ce76387c2d056e35171c3ed8332c16fc555dadf832b6a37a58848015a74a8b114234038d428aad6a7e50a307046f0a2e9af80d6e532d096d80691de9834f2366594c13e28f8d38bf8a7a7b1e20d46a1eab06d364d66ee0a09c6548e9fdcc65a18212ec146a99aa94c9fe29961ef8b14d042eb26432f8e3c42afd939f7d2edc534b1cee8b7a4c5d9acb50210735486a2a44c40ce50f576d38aab670526802f20c12eeadc02501cc21ed1513da2a400f46db5b557fb206f78eaa2471db64c5313c87fcac5af14690daddb15497547c1b2336792e9cd1841d3687ac2a72fa023454f8cb6ca465a72615ebb975c74a59183fe491fab4d46b48b0f1c1ecc17e3655f613df613508900673b591f9c2826380fd743a4c603109049e470a3b3f87de208037ad1c95508dbc64b9df43418337dffc53d686277df9cb4f15e9b8559d662e93f2b9114db41cb279670604acd3229fbd11fb4a5321ca1753dcf4c69c356adaa1c387c1b6c9b983225b8a907cd8d04aa02d1d0babb2d6733d0a9ff88bd658af2a389db078f7e098eff5f1892a2aad6b5603c04c79a7cb697b3d6fd09cf6bc269da06f5ffcd52e8e42c4bf514d3f367c3f34698f5586f5649ed3c8b1581d01db8cb98142cac80fbdbb56688b4e9ce7f7dc4d8d36b7c700ef086c5f4d45cfc63877e257eb6b66e0b1ca196189b6ba5e58bdadbfe528ee6a83487587e6de7575c7df9967cc47385df4ef8c5eff0e1df62943d3561d11639eabff7dc7309aa4ad04346d4567e6a2d411ac3da53dcd4e4be40f6d044119dd09d36de3b19cf2e3b86816dc6540d23cff72809bd8d87cb1cc1390c92ef39aa158944445cb9e8fa9347de7453be9926d1ca1fd256e5184eef32248765a972c66f758f32279a7b97bbdb026565db49fc9d82a8268da2b7e5c5dbac7030bce478462abfaf8406b18b190a9647e3f4462c99e76a0e4a0e8e19068277cedb6eb64803717dc45b43b260179c4223b451b83e2fc00e91756fc2711af02da94d0811be0c107178949aa59d1c58ad00c23ac6bac6d73bb8f60e7e7669ed770970d11c63cacf42d31753b2cb8f0780e6f4f79829c5f29a8ab533e8ae5c41fdf72b1300bea57898ddccb60371da7162de32cf571396dad20f9a2628a359b3667a6614e45806d11d9f9c0bbd17645efcee640c2bfea0578c4f8e2e67ddc90c5a9b091ef1b753a477206d990b469596f62172f43b744b3170537794cde315148361fd774e65f6b74e6829a91384d5e0f77c45d0b0fcff2f25223fa1813ca39386d4286725ea55d24b80b683fd5c8c06a709c3e7b11f241a54c4cc9aac73dd510efc73389bccdabf156ffe6ff25322ceafcfd583676322baa44208ca750d2a15c1e2c630da95eb45553de7b51af3ff01b7d664eafa5362d7bea3d9780594f1a9478d0a990accf22bb3f35b9c9cc38c676627566591744a3949ef29eb83909cd3490525b952fa563ad698416da04b2fc765c9953c545043a7ee2edf6c1887925c6f5301d9dba67f3a67348071501451ea5bc407b76c6eb6eb5569e343ec033b0c607e8540cd58d5f30dd002edd2a55b99f121961e015609cb25a81db8268bffaac58e98384f99c02c7172ae2c4e86b39acfe729b83a91a61007f17513efa84600458c240789efa8af3b256c75ed40c3b59c1ea7ce40a6f382a24ed39b6ee078d4897f10f6a4e5f54212ee240fd65af2b401cefaa83b1d5ae89fc61f99ccbefdef386f444dc8000fae9ed7be43335ca75da500098e527f410ba561415530c73d19fb64a7541cca5eba88e7235929cf4c7a31bcbcc8ad5212b45d282117c385a1197a672353c9ca4b3078263999e23a48d14c08fb9d752134a96e22a727ac7f8fb95c7f9f91f6883cd6159de94a8625032b9feeae57d2710fb38258bccc143d70bf4ab50457cc8d9a7608531cb63c18e54fd175bd3cebcc0b993ed046502348adf4eb1038ed7360ced6f850b8232d9c56078ba51095e9b990254c942ef90027ac20e898249b12893ebf8e9da6da8138be19758790a9f3c1061d54ac5d10d462d70be855b0a9d29154f87241cf235f75854e362223c2326ad54afd1ebadcc682957c9450c55edaff774b4b441a45efda136e777fb226ce3f6574f0f42ca7ff0e4d3d94904903535b0e7ec2af6e8a5befd041dfa4261eeec51f62d5369db7a78e69148f1d26e0642e835a7e89b538c83c258e179b65f2ba8669de53eaf456e58a50ca2d00423d36fe3da728dad698604a781fc66c59ea5b09acae121a19cae18b6a2717408762f056a42d67abb9f24ba032ba951de84ef9d6519bbbcdf35bc4181ff2f5e5db96bbbb20b3e403468eb1c6bc282cb8fc65bb76be6df60c6c53b6bad7f56ef82823bfb7190346ea65b3b9457c3132447c78ca705dec6ade6bf8def8faf62b7f554f23d1f7e33668feab8ba4dc9c50ca50cf4e4c95e0c04bd994655af0bed4854a631092221c5c86f9bc506b43332d5160b26e93cd109f5b9c6d72682115100fefa6ad8003765f4b3e2f302319bc72e1946952cc6f45b0179dcb2eabf6c287272c62232500b8e8c0b54c5253c500c682d43b237fe2479b86c4f8c1aad58fe2d4e9dd990982ac9eeb475adf83b1c7d23d087209348ede07b0fa3b52ed2742c91f0e6138b2f2182ad6daa3fe3b44d93d1918542b74dbd29c9e25db09fd55a4e30e833427aab6c53389576dd804e6fdb01fec2ab2c631ea03572e210f61c57dd9ac309e8f79387b620aa7019565fffdd3566c3bc5b3f8efe4e3fe558ca1e19552fefde998a5de015f63b0a75ce7f79f4dc681d18dc298aae64b7cbfa74610b3f70ed35b69b81221d19c5ca6551037acc7771132327b79e0b2968fa689d7b9a170e3983e2b3a3ba160bb9248a96b25ebe87205a7db66035cf0cc21545adc4625648536d805b1c04ab5ca3ad3807d2a2659be4678b00c9fe547f6190f41de1e087cfd937220a70be478d03b9001d0af23c163bbeddaf4b3425f1b5e206664a9115f529953a4a3833751d67fc755eb1aabc96a4b4e81a6a93ce143dacff2f64f0ab58c2ec5b82e900ae6e3edc0a356d48619dae0e2ccabe79b757674630d1c78b928b43c0e84cf9a27e2ff6dc2149a467c58bb61f2e48ad727c2bd1426de5f8ce85ed0aa77310e0954eb32e716d03ed7552e15b5c6f1cbdfa7711fa25e8e46f35dffeb6048e773465aa9854305fecaeed845f1c6a61af769e529a50754445a15e1b40a46c9cd87b701c6ff69d5c7c6f5cf42567bda8795dca79356295029215b3b253744420cd1c510e7a942ce52bb5300d04dbca9612da0b6573af19965252b35f97942facbd9d851b689b43ac831703395dd715dd0471dda1c5947791feeee95d8d9283a3328598adbaaa85f50aeb432390e823cfb6cbbda8abc143680020d246c5dde4a6c45ae84fe11078713bc87c465e8d88f0b23e2804a6a3e19afebeeaa5a0f4c729db84107c6c8b7f838e251b0c174599d27f5fa92046baf6ad431fbef4df75bfaef0a79dbdbd6a2fae8a97abff4b9eeb078696bd95fc84d71195a9bbaeb1cf12989c2bdc7e643aed74b976ab9a7bf800e26079d1d04880276a4f035d4dc86f748936877948f17c5d588368966818ff5005857f8269bb3b5c09d7b3306c93d569f37850e0a7d5bce3ec80e408d2b3037ce36e2e5bbcb524e982d81fc165a4af4769ba0eaf15917b15832a5f5f84caa2cc0e92fcaa63c6bb4467c8cf8cc36b4bb15e7417311ca51566cef85116d8d06be1e99c610ad9709d112b1238ff2068392c344f011327913a5c12636fdb5964bd42f6d30209984318c43f4cf294e71bf60cada362c1b0d6486a1003e20980e81553c8ef46031aaedcd236f162eaa20710f70d09a2c952f4de152a527e1dd9db12b8d249a3a3fb2447cf8478306ccbaa186fe4ea5796887d49e1d3c79aa4eece23d6a56ab1589433f820ba79b197ce855adbb7edd7b5cbc04a54aedbae2b1a31c731b4cae59d906e4c5a4b5e8d08452976cf186cc9a3877e2de21e274f0cf6a67b5e72f2b6df5a33d2e0b99f191ab9f6eabe68efa3fc65f7831ea402e3e70e7cceb1827aabba5c152a5877c3ec5b878e352e4bfeed0cc1dcd87ec3271335bc552fdf45bb4aab3082913618658d57484fc49314030b71358e9c670dec4375aaa02d3c4f4d0a2e522cc5ee2dec627a76cc378153a485a63b9d5d8be6cafb2333fe256cf19870b05b443704fad102518d740c8dad5bf2384e898a31e05ba0caf2bfd6c5ff3604ed969942ff31abf36916e7a1fc6381b793d8c3a11d8d16eae961658febaaae3d12ae6c985154e5ac1d8d97967238ce7c3574dc40933f752feb0aafdf5296598fdbfd6ea59fc706930b7bf458637f8a86b9bd53d72789fef65c58cf337f44c083a62dffd92f1a974eaf3c8e7664ba5e8d8cec9ad36f0f3cb4c9c6742ae6388baf1d9a90c1a3c210457579d66eda6bb2e72bbd41c3ce0187019fee1f340be413688eddd1ed825ffa0dfaae6ca05926103a1299c936c93396636b3a20cd74c9e056966233cb4f46cd1eab34a1b9555bfeecddfc919ae507c33098353985a56c8aefa0c226d96f08f1ee03b72628438fe775ea604b7ea5e0961fc369c9cb124e7b9a5a783b96662910f290a06a7bc834626bc46f5740806097875932422c4fe22afd1feed280c92992c2de8adf0247ebe844f874358f090a4fede6394317b2ca117e5da09c371c8d0fe559d0f47a4718f188031966b8b44017d9e6e93d2bef58d794b037f917b4c5d0c07f0d5b324a3e06ab50b98b6bf69497c1d7cca0c75a30e5d6a41f69a136569deacaba73d8c5dda0357deef407549a384c355e1e7887c4b4caa5c17e7225d1cfdad942cebc4e7a56acf724311962a381cf8c07f6bdfc96dce731b897f8e7a9df070740dc7b5896827848f3d32085530cc24874ca162d19b692d47f46b4105153f5f12f2d9458b4cc3ddfd84aab512b21caf70f290fadefea740a802b12145ab73e13881285d3478c54483c18183a9e695014416408d36be0f1506595b188488135dac65bce6cd14b520eb9cc05c61f5be82ca63ba042202291229a1700d08d3a73d37449dc69e4a1cd8fbbc6e2783071f9bcc7e0548eaf27ea0d983f9e71bb5b8e8a1c7d4e7ef4081d67cca93cc574341b210122940d6b79528dda6fd900356cdc6b295672f081e6c81356d383225d2ab3160c52fd32e79f610feb484ef08dd6e3f32576188300d6541f04e634335dce57e823f1eeb395f2ac1045297ec747323bbe8b4c7d9b135f57e73151fe6ce8878033e29fe6f4092b8a4b72a3c6f8d3f75a29d55a30ad1bda3a0876971033afeeb265e2bd8468b3a2820dee47d609d6aeb5c19e1fc02d9cdf80ff4f26383bf67c651a8ecb35a627d039c432862a7ea1b0e512401dbab118f7b348259fc4ca6eb92ebe61597920d86d082ac9cf22dbd7b64ea865d47ecc029b475f946444737b1d65cde4d8cd6d37b1739e2eb35d85db2778d069c48ad2fc32b3b2060445cb9e21a0b593d9b0efe856129adbb339114e7cfa36e66e6d6a78669efc050037476a5e7621e8dcb22d4cb34bad4b5f5412842f29584652a506e99f5f7a1bd8975b423c3c8f7e425fb9e761b54218082cee2ec6ac9113e1b01cc2557bd8b50df49bc8339a5aaeaaf7fa3ad9b5f5ac4e2228a0dbfa9dc9cc2d20b5218a746b10cd6d6eece62004873972d993e43482b1e2368cc779caf2525ab7247bf1f99871806498c0c65c1a6792c82618b68b35b3dbbc3521c0950814e75482dd48c4e7b0cbf5f847a17b5abc724eb2f0a3763fc47d1e5c7355a88594516d62bdf562b34efeb5effa0e0a3006769b02844161fb7454c14524bf61f551078646a69e4f95bc9718f240729554d61e11976c06eb0343e16991be545dd1cb9813912f9a07f97a3393a1c36589139bb766e4106a8df1a3a16bc4b8baf8a57481b9f4a18f18791842ba70eb5d7206c7f0ff6b09f2a72114134c40ac69cedadc32ddc3a4d3fd7f0742f1d230d0cca8fb593faec125e31c35c58fb7f1c74cfc7349f390b20f3395d7b2de683c561564a63ecc21de7abe6d5926aa7d3179ff84ca259fee519737280a20d4855653c8e4493019669a77857f2ec52112d3f8530e5164273efc1284d00f0b78cc2760738264cbabefbd92f4dc070f881b61b8f3f3a9744e0529f7a91866e13f9f17f291d9797ff81f9053790e728453e963323ecf22d468c353cd205b9220ad90a080a05407bb8298cb4f8e8101c1f92f40fab00b6e031c0c11e967342168272379912b8c800cdfcdb6cda1de35370c3f8388d442db9ebc41ecf30a1c852640e9ebba9fdd92e26430fb845f607d51e1acc35337d00bf5de073d70657f4dc99f367f5379d180eac454f1da13d25aa12df958e0376d6fb6f5ce8bc825f6ebe0869bbd024612fa7454cc42556b8e4db355a7ecc67f658730a7fa7080a80dd0098bac2d3d80ec601da9e9557cc30ed6e6ed3ac76c6c42e311492d5420881e9a8332ca386bc6f84255484eb3b6b6ce76ea4914a1487a9ff3d77dd9df3e32b3bc0c0098771364b121a9946ee5a9c367be0c1dd7e2e146d739d19a825a203467b4f2697951daf6917e8932cc53bc55451ceacff704dd4d8335be43b95d7d09a515e4f1ff61190923c98287e9967508f103f4d3f4af82fb1e77fbedd161bb2ee63f422e8d1d53f8e293142839164a3af603c8ce431b88dc2370f91d8d0f4110b5c19873c4ff2262585bbc884d6bc287cebcc51384f1456d1c9154472eaed55bae2d5666198efab1ff93fa2c98ff645be56f78481cc94f2a74898bff48c8be6c19d31a7a0d35438432cc3b89ae59b643c4cc50d08d0c0ca0c5aa1eaa6e0582ce83734334128aa345ac752f23f0032ecbf733fd415822144c8a737adcf0bdb90f955e7f08cc077072c71f138ff0743450f736cc2f00a3ec9a2d862f0b8389c78baa250c7c9c3461881d3aa72242357d6f4f555bde0919fc263952a9baa8d244df5c379a03f599cd121948488f47bf50936a100ae2e3fcd95d3859896eb32fa7870636a6437a80399d45d8862b838a5459c1e777e233b4facba51b3c9c350a65ff4282af9f9db02d861d6bce8b781eff3ef15c21305aead6de0a1841c7c0fb16c48bac049cd1822f791a62a033b7f5c79f72de7571cbf70420d1b11785d96a20636c2373bfb87e95c2c76da998a5973407c0ff031b2971f92086a64c3ad0e019484e894b6ca52e170faedd293ed38bcb04662e4880d5d42c49a3485e7b59e5780fbd3e1a4849e929bc2b41cdaac44c0311ccfcc46763a62428b227acabd6f2a31632c26ec6f9683464e72c0550fa4062cc8feaf5235560673a3db4d560ca9050f849a6976d35f3cd764d0c4eb5e8117071096959492d8b6bfa9080671ec736d8225c6b42afa2445b8cd763286e002792cbd4087f4d5e8fa8e6750ab05a3f5ecf210570ef02b0b274f510b110dde50b60197a38b5a45b05b48a35c46f97a5809c70bf680b0ad3c6906b7386a67a09256f06568acae2b55605526d3de35b9c44d69df4b1052c9e09344c9a4447e6ef1df60f136efd8cf02921eb85e7ca1a8603e4154fdc8bec71f2d704df7a7399095dbb901b65ec079dd770920a527258f5566b531b5b0dcef20c0f40cdb9c804da5d1625e8f004f710e997f284fe7a9b5ca4d2e401acf95880cd337cef6293bef4a4ac5d06add6bfebe80e99605c41563e8791547d52dcfdc0aefa15af05952bcabcd491eeffefd6a15b2ad336ec751e1d774d00f8dd27331439b9a7a7231aefdf1e25612c56aeefb3ab935c733f74577bec6c960ebc76ad0df5f8af424bb35f943115472952924fa561de71afb5dda6dc5f5660197139a0105c3d991adfed0facae3ab07064489af90642df36ffff60a168b11bc38beed0cdd50ef19b6026846addfc499c1c2046111186e1c36e78297d610315776d14a38908d3554e6d0e326158e05f06dab7c5900c0115bf91d675c300a2d9bfb5398ce4603110ae66f2be22a76d7d3b308dbe086e5807960a78ba14a036f506c4cc1162638ec025de726c21321a30b3be0083ccb0e223e128fd8ae4c825e3e74c4ac5859b62f05f441be0ef917cf61ac3bebb5f6c35f71b8dd35ca5f10622cb9c441dc070540db5384da0d03dec59aaf216c95308d9fdcf997893fab34e3e4e35368e956ab894c21b861085a00eb81eb9b7322a0f24a457ec7be535776492c9b7a09c97132702006e53d472505abdd09b0e8a66f7cc875ef74bb4f8b5efdcd89400cc27e225f1eac1455128d736c75b069b367c4b38234f3a7687b7175658f54ad591da601bd0fb84d91b1bad4951289ccbcaec81ede493267ad1e2e42ea39a4c9d9221059f2bbd596d96bd3af907c3be4ecc2a245457e55bc7281ed4df495239d7218e5b166eaa9f9158a018dc47b6fb629ed7bb0209904ae9fedd41fec6977300d494c928164dc7d2d546bf599d7cd4c5c757be8d563e6461ca80b3f387e488a93fb6e83abf0172a09123a6f7757fcad6ea3c974cea4a48bd1fabb35429c3fb4ea77720c4c580209920b9583c6c5a5e145bf8edc7124e586a72d0c8a718a03b5fc0581b5cc624421ae89a5baeee76ff1cb11f1a928aa523d848825c52c123d95afecc30793d7857b46d2919b578503e4e6e01b625a0093ba52522f6eddfa955ded765f89097e6f1d432f82af6a6908c28076348f6eec4f05f7d4510eeb0bb2149de97ec49621a8118be8a07c8d5a2793801963b8ce372e245d56b42cbe0d3dc2a78e473ea386d85f0845128c291f0860ce12d066e1a9da216a1f7f50bec8dd6ff2ade3819676a80da08e0167a781523052a9a4200f09f8030879db0253043b24688e7915d9b9bf253d0a94936d48ae0cf425076fc02133d31eaaf0cbe588ffe9f0783280d217c7aec602f49ae53cc3fb9cd020da5cb7309893fbe532dc1dd0c472b5364ceb5865b123be480476243a0532f018e94b949a5a51b4e3c0a08b56bfd78bac008b4343353c86b95787caba329ece1624f68017223f1d11fb999a3ae10543bc2519a20942f9a26f1d82f4ec8bc8b24314c3424ff7457e986d2f112432e5249042ff3b5fe0425991ddce6b771798e3c7401ba4ece14b1e9f9ecbbabbbb5f784ddfa4d6eb18fff54820d3f705dff7abc930676c93e839464f15d35ba8835c851e85703d58f118bcbb6df95f3be9cb50716d0d63ee15f73ed05ab1bd9392c29529bacb374c7475f7134ca86d"),
+ %% SHAKE128 VariableOut
+ hexstr2bin("84e950051876050dc851fbd99e6247b8"),
+ hexstr2bin("1822b7cc3c4ea4f2440a362b117f808a"),
+ hexstr2bin("2ab3a70f3b01836d8efceb67490c3c38"),
+ hexstr2bin("0a13ad2c7a239b4ba73ea6592ae84ea9")
+ ],
+ [%% SHAKE128 ShortMsg
+ hexstr2bin("7f9c2ba4e88f827d616045507605853e"),
+ hexstr2bin("fa996dafaa208d72287c23bc4ed4bfd5"),
+ hexstr2bin("c7211512340734235bb8d3c4651495aa"),
+ hexstr2bin("ac71d8e087ae133f3da590e1a2b54d48"),
+ hexstr2bin("b4813895ae01b43c9d9ed85a8b03aaf4"),
+ %% SHAKE128 LongMsg
+ hexstr2bin("3109d9472ca436e805c6b3db2251a9bc"),
+ hexstr2bin("0f994e4aa804282cff22ad7d6229ef2c"),
+ %% SHAKE128 VariableOut
+ hexstr2bin("8599bd89f63a848c49ca593ec37a12c6"),
+ hexstr2bin("19e740d7d87bc322edeee86a05eb59b64bb86f90dc7b98f781720b7cac37fdaf293ce6bd047a14fe"),
+ hexstr2bin("ca7ca55bf123aba45287268c4050ab030b1415f4497d5fe8dbc5386ae37d24384a2fd6a715fcad48ff9e810c1d378fa70f1503767e9e338e33697206f863dc8015b4d1e9b8f81ddee22aac59d52055a1b0784a364369cc50f403045a1bdb25b639"),
+ hexstr2bin("5feaf99c15f48851943ff9baa6e5055d8377f0dd347aa4dbece51ad3a6d9ce0c01aee9fe2260b80a4673a909b532adcdd1e421c32d6460535b5fe392a58d2634979a5a104d6c470aa3306c400b061db91c463b2848297bca2bc26d1864ba49d7ff949ebca50fbf79a5e63716dc82b600bd52ca7437ed774d169f6bf02e46487956fba2230f34cd2a0485484d")
+ ],
+ [%% SHAKE128 ShortMsg
+ 128,
+ 128,
+ 128,
+ 128,
+ 128,
+ %% SHAKE128 LongMsg
+ 128,
+ 128,
+ %% SHAKE128 VariableOut
+ 128,
+ 320,
+ 776,
+ 1120
+ ]
+ }.
+
+%%% https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/secure-hashing
+sha3_shake256_test_vectors(shake256) ->
+ {[%% SHAKE256 ShortMsg
+ hexstr2bin(""),
+ hexstr2bin("0f"),
+ hexstr2bin("0dc1"),
+ hexstr2bin("a4d7897eaf5c49979b361c39a67f47e26c2f75e5ffe0645539d4de245138eb8cadaa45aef7fa0c7a732dbbce90c85be2bd4bf6e37dfb4fdebee4d0e0671fc45c3051c6ccb674799bcfda7a431a6e93b3db3e32f30636190a9a2e5620302876e0d4d2f6201353fac4554341df6efb591c6f100f5dc21a2aa176ba592bd7db69e14237bbf2371df6bbb072f9ecb1f714e621c97768d82eea6bf98ebf4a82c005262188ff894a5dd549866f88b00ee82bd99872515d71fac230ccb472c55a60"),
+ hexstr2bin("104fefe89f08d15d36a2233f42a7defa917c5ad2642e06cac56d5cc51ad914ecfb7d984f4199b9cf5fa5a03bf69207b9a353a9681c9cf6437bea0c49d9c3e3db1f3fc76519c70c40cc1dfdd70a9c150943c272cf9eeb861f485f10100c8f4a3e259c6470501932782512225ba64d70b219cf9d5013a21d25d6d65062dcc6b3deb49d58b90d18933f118df70ff42c807ccc851233a34a221eca56b38971ef858475488988794a975d3894633a19c1ae2f05e9b9c0756affd3cfe823ccf29228f60fa7e025bc39a79943325126409460926b057a3fb28a1b098b938872883804fd2bc245d7fd6d29bcda6ca6198f2eff6ea7e03ef78133de8ba65fc8c45a688160719fa1e7646d878ea44c4b5c2e16f48b"),
+ %% SHAKE256 LongMsg
+ hexstr2bin("dc5a100fa16df1583c79722a0d72833d3bf22c109b8889dbd35213c6bfce205813edae3242695cfd9f59b9a1c203c1b72ef1a5423147cb990b5316a85266675894e2644c3f9578cebe451a09e58c53788fe77a9e850943f8a275f830354b0593a762bac55e984db3e0661eca3cb83f67a6fb348e6177f7dee2df40c4322602f094953905681be3954fe44c4c902c8f6bba565a788b38f13411ba76ce0f9f6756a2a2687424c5435a51e62df7a8934b6e141f74c6ccf539e3782d22b5955d3baf1ab2cf7b5c3f74ec2f9447344e937957fd7f0bdfec56d5d25f61cde18c0986e244ecf780d6307e313117256948d4230ebb9ea62bb302cfe80d7dfebabc4a51d7687967ed5b416a139e974c005fff507a96"),
+ hexstr2bin("8488b6b0a5cb3b778d9e6169cddfdd7468127361da571661589a51e95a0ae5c057ccb457cff0dd588fa4298131a7a6b3e201914668f279a06328a206d234a8b1da3f6425c3f913be44d3b58c006eb4615053c62743e41477e3939c68ba51d4a5954990c388cf25d13293cf30421b50a53a70daac74172f0f624207b81948b2c31153fed826585bb8e34d3d150096c2a729c0957c02711290679fab9df8018a34d5c3770da67efd9cdf67c8e442c75290a5abbf40f5dc05217b114fc05e64a4206903c30a0f2852a4ac4b38450e96488834991f9f553f4fea2500bdc8535947ae5679aa76693ea3f9d45f55df6eebebb660f27e422b813914edd4bb5ee0c8bc06238ff4f9bda738c2df0de75b69ae8443b01ea4d07e8c0bc75bf6122a0b994c5158ac683c124d592853bcb56007c75b56ac8559f257470d2af8cc8ad3deb43cb77e37d0e770174e53bad38897511eb818dd8f6550bd9a86664bbfea026101d75f1c9af2a2dfed5e6a9bbc28a84e9be3b1caa58f91b86dc0a2dc38fc5e9b696472ba3c961368b7d3957fde5d3a07272348fc2da05e50a80107349d869094d22a17e08586e5125df3feeda1eff582a8c205f991615e8e3492bdda57513f5426727717dd89bee6c807ca6d6da583c90806114b37973a79f7bbeb56cf2514e44b84b9e6ac6647eade562487aa4889e42d389479890d991adac3ba316cc9b74b2ba807d65ae62728882a32c4c0a0b2d9019fb50ced8a2477c5f451f29507cf91ac26866e4fd106a8afc91cab1875a3b26a859d8bcdd5839aa194d921b4a504bfb8456036f4ef8e71397c0bc5188f07775230747e90b75d8b54ec7947306c00db364fbdb6af07658a108b279829b6842ea0e9616e9ef85a50c8445aeb712468f00d8ac477e9e333fe1a3e97aeb4b1c2e13cf88ce25f6023f3e3e4a395df95e703273f9e000b49a1d241dd848f1f496a970da51e623bb6607c8f137dcde286231e6bb572d97b0256106baf15c1d3462459fd383f769ac4b8f1b31a101ce2c1c448c136698ba3d6fbc082fd73ce3970972ef3f816a7e450d45c37418309470c738a1108ab9dea8c38e86d0fc53eb88e6c1ed82fcc7c81235cc402d0fe1d7930d8eb43745f97b7eeb492142d3497b76a4b319223887ed905f732fe0fabdee0f59a7340c2ae0274c218c55f9fe863a0cada700a1c733354be4dad1246b0d6e422612aee3abf6488d10b8a36ac0829da77c4e22864b5255b15073d26bc358dee81d7193624bb485be336e8819ebc72cd39af8fd54275dc54d3cdea23ba638a64d8a24700c7c93355c041e728bb2ec5e1d74480f7fddbdfa9c046bdef886155b0f06abc356c12afde2fd38f134c83aa7e1b2abc77de11b6c0a41bbd736e58763891d881bb5bbd435ef994e92b98e6a90ccb094b3e2d3ce90347f4f397b470756682939d7cdcf3783de62efc56e97d4bf3b08b3633328700d871776544a1d0dba18d44185f37dcd4e3be46d07d8570179b9256843d341884a9e94f1d607ea130507893fb4bb39fe1b849876e89b5e8966d39123d467d17fddd782223d4930afadd0c274d2a996527254f96dd60c10d4ecf6c686a3553adf1dce6997d892834c3af11a916e331552d90971e25ecf106c92af5ff12f2ff02ea0efb5b35668547122e4fc05e5ec3987b62eac54f138dfc8fe79a813d64c83d6fdb7e115352f26a70c28e152e8397559904103362bfdc16266c2493f375f88609ab3962dd37b6c564d395508d3af5b510dcd11166d7277d18235adf3d0cd6073ee6f2f7ddfc1a8176c92d18846b24e06654f5076443b658ed72060d2211a9e599f472775a8966c62e0c1e151afe6dfd26d343bc62ebd1d02bc3eec5ab6dba4b9f3d818b5dc6e2bb150430f057db1834d5c084d96bb7c00d5c7ddbaedf06515fda2ae6dbed9bd589b21a2a5143ea6daffd858005848fca3607089670c6c5b549d1216b0e12f089578db4d6dfe714b3932589ffe9b75b3973b5cce4b4689230320c8bd6ccd4ad444e2f3cfa434a3f340bd634c92d0b0353eeed319022ce56084214d1f0bf3cba4f961f185f257454363c97eea578896f61cc379f6061fff786a07059818d51fff256e5b2cd2b6e3c0251f01f5d723787aa381b7e1e1a035ff275a88d51de1c6474b70a700c003fdde070692fb7c41f347858223690f4e37494e845d4275ba3d21fe015bce34aef2117c28b877c16495c1154d32f7f98a620b322ce95cdabf02f39f98efd1bb287eff16edd8d740fbbe8be55b7d1b2ad544a994acb3a09770b650b2cfe9a7cdf0e2eb49ce8aa66587fc1c7835485f3dcf6da8c89c42aa467fa5add9fecfdce7a8cc8a97632461b999dcd740535b108cd92b7d50742cd6622c7f8f77ae08dd92a0aa4182145ca5c791bf60d04dfbfba2733cbbcebcc8b16517a25a0e662b265988eaa49c8a99cefa00323d9a7dc15d192defd885eebcc7e9b19cb210bfbd4396b23c28391e4269cb75d3c2117b21d15b89d35838726f864a9aed1c210325b1e4cced410a480cf2d662f282d7bec3d4e3e775bf38f05779122401fcb1d90b0dce399c8362a05fe685483d145fc0fdf43cf7558219d10b1cdafd89d845c9c393bd78b863e4bf91d172a601eb1c2a56abd119d1255dad00fdff87d3335f3de5f03d1acf7702ee693008fcff7b8f4364684acf972d76dccf791a437c9250ade8afb78050113fc53c8ec2cd644a4ba48da60499160ee7f8cd2a95c0e479dca2523ec759d8d71dcc924a2a980edbb3d659019906bc5e3389909f0c70b95e55a3a909e6f7d84d0f7cf0fecadd2db46a514cf76289187febf7a022e8e359b45e3a53bd90fabcc7975edf190e0d6f48c1ade0040ba0b90873db7272b589542058def8a65fd314fb47dab3257eb9321d7c349893feddfc6c6d9d9dfaece31706c7f9fe709e017f3c837923a0976114b6dc8dfd33b6a171303bc67918198130ec3e23db98e6063a2ffcc29716e28595897522846fcd8bb5e850de9a76a5d430552dd5168bd261f439f64f8404daa72329d89ab4a49e0d18f95f5e88832c5c73b6199645c5cda52bef126880d70a364bfc794f048ec2a638d7b9ceb9ca17aa99a383efdfc332405fb3d3b60419dbc38e95d9b7fa6ab5d78427f297a4b7e21f1091ff3a5b20caa3fe1cbcb09459d9df596a6c8e1ce4f211995e9c51dfd9365a56f5de0e3e6ad17085ae2fd098038eda3b0eb419d26a0204d6e00975d1aa6ebcfb63b2e3ffedf11684ecbf9ea5935554b1e742e3b1865ff1cb50dc8c10a805e76c5010541636a4068a3cfe8333a5e7cf3c889b8430b68698e52587fd235e964a384f78c727d164e0f4234f26d8a790ba69672073e676f04ac2e29e51604a8a55ddb64ec59b4abe06613423e1fb04fa969707642b49343787d2fc82217dd87cbacb2924c7f71f0a173fe43f5d116a8ff463edf912bf9ac6e093e7c5d5d294c7b98f1c7d56a1aae3640ec7d3e0c234cb444e8f31d2d00718e59448fbe6e51c05f2a804cafa419ad4ad5c33942563f02716b56fb0e41105c7f7427476ed4bbab1f69476901b5d4b583386dbf283ad293dec4713e8cf09133ea62d1ed9517d1d5635e2f65f323b58e8973d057193d44c8a2561f06bec0ebbf762c28c85abdfa05d20f1e8aaf7822ff058ed6493de9fe67662a4999cc3b87c8ccd91622e6509d051486fd1e5a3b85d29f8f66dcbbc56638d146d840dfe9cb16937182416158249bd2cbb56a1ff545cdfe80675abc59e5058cb4b2431f51207074fd536ef25bf690b4e42cb6242dcab9cb68c309672ee4943e7cc1eab3fbef9f178473f1c1e37bab61db4c4a916b7c5dad506132e5cbc9ae90a4eb7dc36f9e6c230ec912f7771bb682b8fc6d8f38c3834d3f291c5db8fd1b2a361a437936979c41a43d19bca03e77be812368461a07f1523d0311f87ee9a3b3393585fbd740fa184cb74d37e44cb8be40ab83dd9bb0706553d757dea4f40ed4b6248b71da034d51101ff891cead3f29fc7b067c4326c82e878d3736b2852334b4cf9d04c8475c93f85d60f1e3c9d4a8be7b394d99d1c154e30df9283106ab7c3b1e03db2773f0870b5acd80ad0941e38d936475251a23806f3fe5dea8de6f5354f9042082f1d1d451fc8966b3d34d8171abce1f6f67b559320c437d9f7534620548eaf85e28c723d22cdbca7d90bf2b72abc07100214088345a5a309e33c55058f3fb8d45809a1c97d30ad494a96088997b82935fb18cb47d13731d2e80e9c655e28007be611166a7d75fae7f84f841ed045cae147d6186161dd66cd6c4676c03fdc08e5233f6aa0a22227dc68b4ffd762c96eaa8ef87a60662cb461f6708e96a2d0548875e0f8fc99a9b6cf2252c653ddc776ea26ec5bb55c89ad390d194e692589560e84a25beeb2911a08ab9582049fd48638a61e56d0b398a3ab16ad30a8467b9fcfa60ffde78b6ce4416b19cd7a37552f0e932ad66319ce4a40a9b8cfe4743b945470667987928187e1e74be32512eda3e4548e64bcfd8f13824ca8969e3d2dd6256a52394f56938762b6a86d85d0e2b75290b58c7ebd7f61f866190f461fe6d7bafa6fc79f4607656c4fbbe72ceff8cbc1ae3ca808f803e80b8c66a47c8aeb0badb6fbaf07ef51943728f2ca7ade8443ba238051ec2bb10844363df0920caef45616a25a09c106b67bc8e9a2001b09c1b4872d24a8d70b352ae9eb6e271397244c9fe04325599b2ea2a60ce85d241dc8494f9f7acf687701481e1b97cc4e581e09c92214db27837f4446d907d29824c9d0f363ceb08e98fef4593ae7c20b564406090429ab99642ab931eaab00d5b338f408f6bafc87c580d811b5e8d8e91628ea05f30c074d91a3a9ed9e2c786b4db81b06d4aa240291296bde391551561c5efe167b368eb2a09c7ed07026a9c758a9ce539a36a77d907b281520e7cbd0dd38dad10923a2572557b0911d0405887890869593caf75727d8756d09fab8e7ed5908bc297dd2a97477d795d15f2c1d020ecc437dd1a43ddbd40c3c50a8a919a122004e588fa028327f6c5559827df3996707c395052e8030f03519918c0cd4ad4639fe12e38b61c3d0d76602388bbaa35be1bc95c006ccbbaf886b591f64a776184e41e51404c4cd0eb13e57cbd5c0c43fb294ec8ccd81c0849ed7f3dd3110703a95b05b9b9cff92ab7244e6c6dcb4509522c305d5d33e03f1b0b60e40029e4fffb8dfc2d4c440d919a3202bb400e3fcfe9aed6e35c85fea8996ac14d249af4a0a1016c77a1b56f4ebcc46931e02fe0dde836aa2270d65e8be8910841e86d212dc33fbe5d5f2907a94462eb96f235127a784d13e1422fe83033089f88f4a951ed8bd058a82fa9bde95a94f0b12129bcefc17979ea7a9784dea058eceaef566e291f3ba420b83c795828e3e04b1212c685ea454403bf171adf5708592f817d5f2aa708088ca3ea233cd3d6232c70f817811b36ddf5b9b6927981a04c1e53250c354cc0eeb597bba3de86f6211ce1e4992e7ed6aa87117cd4f546a82f800d565d9535eabd643db8e18667c943e30ddc33d338ac14836f71c89bcda9691d57183a908c0edd5f3de8c67c9ed9ef489eebcdb7744084af7a9e57b23f2b62bdd7748b7076b4b66e3e54380754ae8e1539165023581b60d5db0a6784c3b482283871387b1d65b05be8022070b1ce89108867a25f0cc411bb3abde15782ce3125201829faa9a833ede4fc6700dcc3460233e5acb3b9c3002a3dc0ae74a400d77e387047344206a7ebda4af3fcfe152fb2e298566787a194e98f1ab42350d2dcf9278178730e06741e71f2aeaf3e4aabea3c8989c29de534c2d6d3ddabaecda85f9553a5fd3830024e52fe7f60c5ec2170e9bf2b0d24174a7bbbf41056e778a3772cefb71ce60cb94225754d56ba83fb0d9242259143c03ddde584356a235c360b915c9415412302c4916002da4695a089df1b6093236775b0fd8b333089ffc7e16fa2263370fc439a3ec6853491ac78ac7751c35eeb945abcaa12f4f042ebc0c36cca53bd9b1fe58dd5afbeacc24feb3e03ec3539c4cf54c8951f5ff275a8877730da05faec155165fe24958a020761062af5a06bd6a1cb9e65bd5c7d4bbc86c564dd23338965eeea602bf215785a42cd9573eb3d48912704c3f1d3daecb12377b0d895b19a9723e4a4cfbd964dd2f65beb6efef74328d0c357c5ac527f0fc853bbd543b948345a1a7115de55a8f7e578d5efc1e1eeec2ea3c840cf2b2d5cdc232edb1596bac3fa5570073d9ab25078ecfbfc1c427267a96bbf6a25ad1d22c7adb0f3f38e1acc6b5d49acc3ad9265157e04a0f764f621aae5e34c942278e8f0baea24c5eb8dd714faa30c56d571be26f899e03a8da3a197d7dded05d06537c111847673f33d6d5ff42630df5c77e4112061c6cd06a16fda0a545661000d96a17c25f1e5ef5215b3127b1f4788cb5e40bf055998171713d946f18d8efb978df8c1759e0326f458781d4ae174a296b4199c2ca183072d15fe525c9c76062ca42fa91e84b6e249bd17de3a7f50f1ff6f06817fa777200dfeb0f83c8aff6cf464acfcc5abe4697cccf61af400c2bf2f166d34a5725aa8dc5656fe396013731654d882151c7605b30d7e9c206cb1524e31b87e470a16e8c5a35a2dfc259965bbfd1b02b3de55fb1609172b65cc07f483484e270d789128ee6f234d2de179880ae5de464af96796cf472a8e6b27abeaf6e497f79ec3b5b07f411926749d9b252c9687148076961d034f1d8edb85857fd08cfbb6a3f368c7a1a2a47f7760e78348988035fd5cc9d7ddaa5af35dee7dfa39c9e22bc31194b67b192c22e13245ec87712f716ab3e80d82df4785986b7ba25822b41fa72420c6372e19d5581b9da611abfe8f6f84da081d764e0b350367c1561fd95af734f43cfa69d3618424d7fa0dcd5459b3d6890dd4f8d64fdbbf299d5a48baa45a4af863ef53c28e0f54db30a3609895dfb1dc67cfec461733a5a97e8d26bdc5786c14823b734f239eb49190fdeb340c9a1dbb5c37da082ce5c0d0ae17404b84faa530e00951e0eadc4ae16240f68f868d230e36344a8356981584741f1ecdaa88fa34c67f76dfa96e20b4ed970a11cb60cabd3bedc51f5cf4aeae17cd49a9ffc975087cc569b229ff3ef07a28ae22a2ba1bb1b48bd24408a39237e04a48494b661d944a04b2c33235aa7f511b6a2ad4431cd0e835fa5a204ac90517bea3135606fac17864da788cb86e47ba99c6912aa4d7032114c4c96d945c020451e371e85215754d0c683bfe319232fdca4bbf69855433a550b8fab7265214ee298fcac8f275991225e47351481c2761d5801d5c8d9a46be105e53c6abb3251f712f85bf8d221610d6d7874da4160d2fe2ed11ca65b126b17c3f3d61c9871cdd4f4c0c95cb25d28c48c8e1baee87ceb01b1b047ab5a1b9c9bee2215228d7e171eb6dc6125685b7d1a23fe860cd785129a6915f352472e94dfbcf655f71aa5c236e1a1bfdd34aac260dc40407eaf07ee5abd788c35a2d9c845e8f73514c09753a00db7320ed7d98d2b1e09d76ecf73d2b5376e9ec00dabcb70ca9b1ef60fb1400c83936414a25651eb51a1b767c957642c5f5e878be7f302f30a58903568821bbefbbcc29924afa5242fbe7cf42d311732adcef2e3b26e031f00c6253d5b884b49cea9ea06ef43fb67f0a6749e5b8f606aab465d720d6b4087465a3a986942533f84c126e862c1c9195cf04ab0e4d0e436c04b23b149894fbe538b6cb1123ec7f2b6b915a81f9792dabd226bf64993f7199543d22c07368516b0e02811d6ec2e25ccf842d07643ed0ea9c364b90a472da582d7054cb6f18532d6def95527b8da2b4fe51afc27453c37ab49a18397690c4d215b298de948c4954e0e5cd5a5437085a8262a85731a04e82a2bcee08187f782f966cb8a1ebad7b07ec4cf3da01a65c76e31de071a30eb82aef0395a591293e9638047abb7b61306f1b8ccd7d88c4e632a7ec1fb6d3834b9c22d6d4b7e9745d2f82e3a7d54c91b1b4f40d24e8f377edb458362ccec8e84dfdc39f74e6284a1f23fc710796672647fdff38bfc64aa9bb247d62d0628a2607785ac53edc5792ca9a2e1661a7d3063872c57368bd934196ab9fdad31a2223c13270b0f73e7e34a7bba13b7eaf981bcc3dcd27e575d827c7714505fd9d97c9c3568cc76ab7a317feafdc462757bf4b4d839fbdff982043969df74b1594f1ff540a37745eedd025179e67a122474f80016fc49b7ecb747d4a573e14e5a639acbd76f81f9a880c4539afcbb2372650a13226c32b2ab8dbbd2dc9a0c8337c76ba47c4572ee731605fae0a8fe3309dcb9626d324d4cb075deb8518a7cfc8bdb0103719dc0a0d90d25cbcd83b9bd453c647259c70fd286002ef9b6fdb926c12ef96d8a0101bd44c6d22ac415841eaf14c9c79a92e100a69d3b1b7f4c377e6233c34717e7ac9040d369ac66c6d3f3b1e627d6923e67439cdd71921cfe7e700979ed249dea37d647d37ac518202fc8f8312d23c3221917d3216102029cf4b80171e58a9e6119dbd42774197aa9fe0adc763833bfd65cf9e41997cfd2a04092f4ac3aed9be4e93d704fe3fde0dcd535f935e78aead3d9663a1674701f90d8bd5d995bd218fe2c57a6cd5906fd213bd6b8f0999dd692e4e95fa885771bf72373a6b9c6bc981539d6e21031a9222fa869a626ecf0f5ac25ffcf6059698a3bc7725a9e1a118bb2b817acc90c78e250916b4b595008da88031603be5eabdce72b2603a6b485766f1db6815857dad02c8d6812f8415a07af02c8971303d27671c4fb1c84246cfa92e12fea3e92635e2bf2cc97945f78ef89bb93f41ef761f9742b8e1f86f85c5ad698e051fc4a96fec7781533ae08c9f4c083e4953297ded866d54b874f9eb84992ab744301eeea349773ee81b5bbe1d9bbf25704ee63ad95b248bfde4e8625396faf5857f00dd192047c950c4c0744e1049d47cda2e952b3ff0c57aef45d179cc5fb08eb4715e189a708c53dc17967cd02db535a00a762a59586af53e171f3f62e35028767a59e9df79edb80c660bed06f32e624881c51fd2e4e237796636ed810e3d1b6d22b6d516ea5649fbb7bde9d824a9cd7a9c6a52d11c9608473afdcb5067df2f42715d22684c2ecc511193ba6e478d3cdd624d0b7f89ec2f509c5c20f8769f2c9d6f3618fc25dd0ab87d75a7f1e4427819db569203b24d763d933b36a0c3e3d925252a01fb00cbcbd6014bf789843049d70f6e2e861f22a3b628825371d714ff839a1f238c6260d753a8fdf35daebf76bf077b293059d17f626219c093399b665fd6fec8d8d504f5d87774e396ea57c978ca66c928e7c4d2ea49e9c52d71ded65fe2b03606e01fef0d78960f5bc06008ab60185797516164f5e5d8a9670847172ec51cb53f0c198b99b24cbed5b942fcffd2781aa42012fc2c3fcfb66a853df07287298fabdf5a92252d7f392c5c656d1d276d5c78db3e64375eb7325e70272bd431c10a71e34acb58f215c987313123ac67e1633a0a4c62bd4a76666b526f8efbcacb70baa05100db08f8b40ec10fe5559abb791336a6bf660cf69ab7b17ce2905a2e07ad9dd8f755770e42eb93657cc0c9e3e42be6b342dcab1d166d18b6ee3aead418736245796f4841bd43309cb194fc40eca9a2dbb5c42fd521b30c857ca280a4ea3377024ed182776b411e1d4a7939bcdbb6f286dec9a10504b11751526f2786c71665753e222d9a960ae74f0f198a3ef7795f1c879108950891c082394ae462f544b308110a529184c91299ca19f6af8a1b700576c46c6c72788f80f9dbc120bde4e9228e33f7447da42865412485f5dac3aeaa740bd5748d900db45ac9c5a9671e8f2a7f42279bcbc3b01a3de040f9309a9f71480e4c94a001c18424bdf8e33b1c2e8aaae2e77eb54f321f86f52ea3d3c8cdc3bc74d8b4f2f334591e5e63b781034da9d7b941d5827037dee40c58dc0d74c00996e582bccc8dec9c12550d0d80fe75efd06f3c887b4d46be1fcdc48a24c6fea99f0b519576f773b3c649ffce81322dc45cade07fe80fe727fedf7c9661e7110d9f8b4d25385a510802e33fe0cccafd90421b36a311dda2814beb88e90cff819b5e107e555ade0c0190cbd72da9ec6dbb4b6045da3de00035cc98ee6a6d35d4bda340ed0e23aa2e0837a8ce9c60c106ad3f24160db54088a94a8fb800cbb294da37c3a136dde73f84be222d1438704fcfe611af25c224c3468c77ee95709e4859e342a2b6cebcc5ddeee2fb7f7a21d18707cd1a08aab437745cf99610a22079a46d65f9773e524a7a8f9040c46ffe123e6c005fa0b51a6e9c80bdba58aa60ae229dd3ad6077d055c569d405cb5c2c9c5ddb5384d32d7bf024c16a6157d0876f3b3d35c658c05f6f254354517c8cd6f74a1d6d938b58024376e7a894f45bbd455713324d4960271e02e6bb2cbf4622a96ffaf893af80d4f1f8ba215a179529b6dee973491aa04fedc51baf9e7cd1383c3339998d27eb1c8214027abba8c4f44c38859fc2b3c80061d4a8d8b09b764138fda4fa88dbe1007c31865ebf9031458fceaf5fc0fc2061049855e069047d65233701c38cb3aca869b60f736fb524450606315b4cddef9b5d79ec6cd29f2ecb8748199ca297933dd00d6561d200e41c3949d23a6d3e7fd5f4e03327f155d09ceb98b42bd06fdde73a9d50d1f059bbf1b00059a52c0716385233f4b6d00cadffd88f9a1b2023d3cd2ece986bd2a9efecf4918f438f20fdecfedbf5c477ad0b1dd59592129a9bbd18340804d67fd6c9378c663cbda1717c188041fff7ec21331e6a1265b845bfe3efd4b35dbbffca91f700e528ba67e2dae461ccd9f7394e6d291f6edbb729788c7b97376bc15b6b8f57d9781ae3eb5c617928e34d6d661e01667d11bcb44eac01e404fdf6919aa30b7d9e86dbe034c557ff5df02101797836fe0b63d05abd448b51a46bc6d2c4594c91d77734584a07059d895a1e5a7c43551951cddf4e7d2970eafdeaa22de2759bbc0cb2eaf33608b37c33890c217669a6ded8b5b03b9641f8d999e3544afbde4025c6a1c85affb2a9c4e3e5b3fd70d1717627840cc711766d4300bca2d0177e83f68cab9535adeb2e9c21d6da977163fe09c7a3bb9af5af1553b8df55683e3cab54e738182b499d8b2c76c44b96810794be3e78855d4ad43a2e4bb235b9790002695eb01ae5d9af099d6917cca3a8a57dbd166d32b818cc22ff419f096ccfb2ce5d797c630b6809ee1783372666ef25ff2fd6e98952688115ec200c9b28493b5858c002bb44fb9382c14a8c21865d6f633c075453d441da5d1d7263b196ee81e881bcabea389c350fc4487f84acfb6cf10b301558e5acbf41bbbe0b145dc66dc600f4dfb79052d7db480576197fd002f0c5d996602eb01808ee8d6c8c26d9e739fef007ecf426612f7408daa6a8e41aaa918b3e335755cdfbdd66eee09930d88aa339894f0b1ebb5370d914f4ce3f9d6598cc759807a3c762b1d1f9da5dd226021656cfa97e45cd8f65008acb9aea716a0127a359e6a3ec859156f5401bc7bbe780cf3fc1f4a0802b7b05a6f2b4ec8001f521303c9d5c25aba67e4adb7a187d81082d43611639ba6ed971cf33c34db0719c44850ad4d65b1d18d0607323cc561ad7f7424f8c1764a2a8cc6c546f15eb041d17088a321a74240ed5a0d0bdeb2df814b5a454fd42670d0f9ce71e624d1800a1222286602f5a06b01370b9f17ee964e8f0d03812c3a9f7376ba75941fd1fae4fee3bc4061df30b271439f7678b74a67b2e30c372a114aa47c014cdb72be8565002bc0ecbed297d9b606453c61db506f4fa2bbdc5e48f6d682496416ae15a40cbe60b2a57a6e2a2337d5792b73994cc7bd929edb5950187c21e957f02265fb3e92392e0535008c418f57c7fe1e9f93f3a55921ce8ba54417c36794d2803def9d240b8fa67f4822972503ae1ed34cca856f5cf12065e6fe3bff4aa74847ec058adc5e43e3a9938196814f87f8223f54ffa414697b8863ab5b2e191bcbda2eb19a23b8076754712de22cb202249bc5d7c4cc26073a63c9dfe7e8494ec7b744883db29f368bf06f8bfc9fc1992e909ea7774ff856d778780084a651cce68febfe07d17a5ddc1dfd20385304b970b1285879b811e4fd370cb193f0d92282a473976b38dfe9c23d988f37dee1ef957de17f6e9ce91df64fd667a85035cc369579c8fa314666f8cfd02d7dabefa7f7475860a857048e6cf38397343cfe467ce37d2717533451ca45229f7c32847f30bdfbc0c98efa92bbf292d4ba1fa90db00eec1645273036c14e0e39a61b56d1bc3249f4349d11e78dad7284cc80bcae9a88453b2625b082784af1909dcecd4bf454d19f9c1a00e93c84a13bce08af9576e026ea1cc73bc159bc8b48d5b56e4a93962117427e3e145328ad7e4100084eef96ffc7bb94388fd02329a6c067906a045696efea423fe56c0a05a0c81f4d576f2d3e4865054d2a961f5b5ee06dfa06b146c1add60e7cf8e1993867c5bee53b700360e0bba2d03df5f1aeb5d83101cd34c72fc5982b7bbb5e66b427bc5766679cca162511e568468a4a726ffa493e0a09684fcbc331b2a92ce307552e7157683fe1bc8a2a558bc0cd9a74d1e92ef569a99a9024c9a9c84ee7aeb094aea52eb9e3dad284476ba1292a61f480075afe488fee9f653e0c1329191a4e5a9f6b62e92315e6a80bb04f0c4b219ffed7458f4346c4cc0172c139a43bc61f1b732c8a5278336769e99bfbd68a69c5a2fb774ed648cdb49e1a71925cca32c15bec710b924db3d34e63a72e04729b1410d678a37e1069d77f8785b3bf3ed0c3904dd16d253e07c8da0c6a5c329e45f9cceac233a73819b33a6c9614581430a45d29a63597a3bfa671364e0cdd67eae53bbadc65de1a5db6631bfb4a93f4c2c2170297eb46294bfac883dac6615a0a64e1c93fb0bf51b67f6e284dbd1f2b17cb626b0ef4dd391d442477990f6aff2507539854ba9758b47cd01405e23651902ea3c583f8b95dd4013983f15e56d1bb3b159ac3ca02a9c81d1d61ac6095f2dc5a6f948f5d56f1e0b05c3b7c19c15c4d7e8c5305858dcf71feca83b99eaa795cdd3a7a999952afd3e020f0b1f816f94c503c638273953442805c1cb622e06f822578ca2b3328e21e0f1c660b4fd453484eba2ec30ac562aa50367f1a63c44fecd1cf05ccc146333f9b92ee10a795d4b1c86a175fb17af519dd0e3d5ef7e2950d5081dfe6ba371da92448fb3a85b808296be0dfb10e3246218537da0c45b7c9642055ab1194780bfb1793301160c7681f97a2ca5f8797e051f747c7aae3b07771cfaee9d5d685789614061f1ddf507ef4da2489c3a3f84e1b81b2a8a3486909c6cce22e9bf6ebfe1a78160ab847dfb759b1da7085e9f009fee30cdf9dea5e0ad3a6b3ebec7c1806f8d247958930b19baead59110ec00b8e6c69baeee34febf518cb88a43fec962da1a12f42092092a6742b150dc6dca765f4a441592bffaf5306c9d4da1ebee2dcb5631192a0adef623ab992b95696400b28114490d060149f3e102d1ff1799a8e94a6a2f9f83f245972e75696366381e8673f19486917c8442f3cf5c8608309cddfda680a683addf6ad22d536deead9a8329c43c25e9d16ec4abec375d481dd14e77cb526894778c45a0aa31dc882b3b52aa768a14956acf221042aaae5fc60fe5c1c2ee0d3db813d09ed24bd7bd1ac89bfeedc6781dad6f042bb7fc9ed3951e4ae2749cbc07d83db2d68ee88713e30a052e13387c0a041610023477572ef0c524e2c8a49d783fd29450c7511414ecc93941cf2845e3d68bf1a0a26101f741cd1bcaa54dd91a559a1d1363cfa5489eccdf3f08ddfe308b974d0ae703c3b7efffd8a1f5e09875835cf6274ca8623661dd9e31a8a0cd7a8b02cd4aeda5c6f56221036f9fa5010f2fe2c694682474669ec21e1e96b9da473d9418669a8f323902fb443d8be43d72c3f23662a18d0360bb44080eba704e220b14d769d8082e0c37574112a1e57326a555ee9add2936ad222b0409fc0c51905c4cb1588e59e2f469fba5f6c9efccb13fd39544064236d4393fb91844d70a1b99024f3da4cb777b00b016f1eb4c709df733d366031e2b5d6a48d0427a17a24a28ff581f01a41529643e3c0cef428672373f520abc053cd11c0df090861541a5720b75078f2ce385fd6dc14ebd1a37b666bdb737194191b6b657c20850190db5dfed4efc35ad0a1734054ac03d1caaf3eb76adf602195397a2eeeeb5c16b3101d86f8a06db6db2676fcd8268588f08b03032da4e5fd4aaf9479a1b9cbf52d312c357d12d69b501fe178e0e50f4bd78769cb8e64718bbbd660d23f1c733181c6e096ecd7ac8cd226395109980faec23cc97d27ae91516b5655c501a3d0603339f137c24f4defd3b1e4f1bc9fe5365303a89463e3d3f2db97f9cea3b061e5c402d48497ea4948d75b8af7746d4e570c848daddd94a7c47f23a35b9ff2b656a6d9e0f9c8490d3c4f7b81cebb90a9a54137ff35ff418b5ad882190850bb3c277e07cd23fddc281eceaa6fe41caa6595b38663a9436b0d3a8a2b913160aa61cc9c14ef8f83242874b750bbc3f20b209cb608618444819bc7e688c2734a20c5da9399de9902b16ce29c16dc0ae643594edb265f636d15b5a77032135a67bee6c5f70f00ccf6f483dd0f55771553d38e109578d3a337a7f93dd9b00a3353e5331338dcfcb7ca7e0bb873a4e37fe54c2d86776864e03eb8c51f657b2daa99344946db8c28d617ae43295b8dc7a6f50db614e38d6986ecb8a7b0c60be43ca21c87d541b52bb44915e89439688a271db8b6408c507823cc282f965deac455f91e7d431db06bbee9355a8d9fdda17cc9adbc9db44a172347a7bb349f80547328aa9814c2367f62729d2779f145b424837d27810dd2ad21f987d9002d64fb309b5176ced19fcd4b6fbdcdddc049289ad5a795aeeba2c09c5c7907bd7a115f0adba387e5ce54dbe65b07bc5daf40855c2aad655bf002e7feeadbd590f81dc66e640159de0b0e21afaf1b714df0d430f50d0f452c9dab99c62f20b13f39d2e7d7befb4b2c3a244513e6599b33476cd1d1f73d83a566e54c8e83f8391cb1e929d36711fa64be2faccf9b5288a21582ee9f73c8cf3ace4876b4a3c2bbbdf2b912edd6b5e5fc1998cf2f3886d81eddbecd9a0d317671365daed4e900d7976edb298398877c76dee832af3876e81e2269157e1df817cd519d6b6bde331b4d98c7d43126d74c5960a65dec35a35704662a5ca8409d21c3927022e5edf9d52512f7a9830c55c408514bd7529a8ca3862b6ae9a4ff8132e86b7e6befb2a5b3d24fe32fd5a36382283351057ee1933bf7e4b362e0b544c9a05f30bcc5a6c735b9a222cdb5a680f52d695e8ebda567aefe249c4f080c78348fe01f8c2444eeb96fdc3f09bf605e9b8c65bcc9bb407a7aed5d7e14775f7c220b80935068177cdd5930807a3f7b2cf3c9db045cf46d4c0e6a01d139bb38c10097d344b02d9912100a61af85d2419c7c6a1bbdaed5663cf7e8c44e555032f76ee93a9c11c1441edfe7c214b2f47e2dc3e1ca5135ead5fdb5edf74dcdb2b88fab443911fbef9313bb95d44898326b5138c5495788a136eed6ee1d48296f33ea744d514ee4f5209121893ab39c08b38769892b492d94f380c96dc8d5eee25fa82869159b537e5707b03657fe34e3c160c4a1d29e8b42b6640be16c6f84c87639562bf89fcdd7b0f7c621ae80f9501f5dd8b3f1d02816da091ced8a8d916e322e7c1a6cb4cabdb8e201dfb0d46fda47ef2413eb869a9de8d08ae6a5b88b6ffde80898f482b08cf946c1d50170feeeb5852566321a49546d6ac4614068d92a34069a4c228245c1dc96a48612df3d0a02b05b0f6813bac6d23867e1ed2711499efa9f88792bc108ed721877578790b89a114393fffb7551a1b9c3fcfe6bba2a894486f26ae7d8aea6399c3d52029076f6086d785c49ffa1766f86f716bf3a697d74ff0e6a5ee33f918dbe2ca4c8b2c1910637412f87b022aada2f84a88a2872f5fc562119f9773829beece9a2428e3515ab4f72cc1d4d51c98a0c0a3664fad38d5b2afedc301b34f97da6d8dd18792dde680481c4a30dbb4cefcb1c32c82807ae01ebec33ab35926b2a8a9ed7b30a3865bcf4f2ab91a7cbcf8beb2f403c368bc291277da2c35cfd0945f680049ac7c1461a9f49d371720fabdecaa7c139bcdc85895c27cc0107b15e60794106482874fa2171fbfebb12f38c69083a48391176414b087ef1ecbc7bc50a91463f43a2affc320b8d6fe6f113cbab124b47c2eae59056aae7c6fee1a8f794bd041205dcfeb6fcda72b97d92ece425875f425f8fa6ed4cb1f6bdb02db540af8b0f41072dddc4c25d406df78eeb8068c5eaba779646d29dbc304898e74d4aab59cc3ed01bc9a023027aefed3bac1ad55c7232939521caba3808fa21a4cd7028c7cf5df92d3ed3af6896d1b73f8b0e0bb98a2d4bf2d45032a3f534d2ecb25ba8438d30dae8c9d9c80e0895ede124e46c7b971cf935eaed978e999b353598579a5b8a5a0dc4e71cfd5164bf09e6e63888012d8433d4b20d49664a9fb105ec0e7f8e5b3bfa582327cfd11fbf93b76b74def8c1e58455e629c8b9acb4eee429ead84a54493908ea84a01bbe1a03b90113e1a0d8d3534fe3eda5f7147d4746de77352e1a14425db9be2e8fa450e28263a020b7e6b0392927a361bd364b42a4863e0688213f9ecd1d3ebbab86e6b899ffb42cac801e9e584df57c6a76b179839da9dd06ee0da6ed8170e7fdca5dee7631aa65dd19710b73b35e668d5a42447a91352928f5010325931f3404e328fc9da5fd5ce8375a08f1f448a0a445704be01d7a6b4cbadc3c0bae74105f65da7b76c947825c5e2c0f698d3ecb2deccde85a7ee41400c3d1aa16502a0d4bc6e4e39817f36687e2898730eacb36b8a4bdb250520cc3d394a3e5cc04abab788acabd881eab8a1988d518ee995883a301b23258135efb43a1a5779358634b54260e71bd49ba6d7fa5a13cf91571329b985dd0d85f451acf7f58c812b80b9d6d2d2298be25aa7138cd605bf6fbafb3f0bd1326678269b2d572505fb0afeef23204a9aae13f1635c364b50e5e985e9840f4749b6c293744045f1eb6f39c97ea31410620fd02683bae0ff1bc968828401ad2e4b88cb0385eba6a0666522a90f5f976ba8337fc3af35723b8ff4557775bdced05f61fa3e7638637b9d662c654a5d8fa594a48a8e8ed6d447d4ed162d63c05873aecbb90bee2f64cab9f9bfc7d6a7e60450e95750c9a4ef6b113c156cf71335605f4d703495d791d5e1a743955c4582d1018a50d007a7a9ef6f6ab8fbd9bd4bdf9b70857f1438d2e33ef72098833d4d53d20fdbd8f1e8eb1a15fe69a4b0c684378aba61b5135a103df871bf98f4992dd4e901622e2f6e9e362b808f2d2437c6b253b56c9e3946312c369d865d56610c9a6ee84c9b6842a889db79915fdf17fb961fe90e012f031ff62004deae529bd1ee8a4a01e7446af35c4b70d902866e0a2c15ddb0a79d99c0e3df2d30549051641864b1e9da6df065f6a3edcedec445dbbc5e19b8592911fe3d9ba0e218b78aad6026a46c3c88dbe8a10c78d8ba3ea3568e212590dd7e72c04a7be65ec06f4f930ef5acf2d4403463a3ae9a5f609f9063e9878a9efb42c4ed54a8860a1462a70169fc50e36b3a02bd45b0dacb968d14ea17b8cf4c7d1e0f6fa14a0850de369adcba6018a7c9214de0cf3ac18525b038d35edb7c0129b95c2d7988f597e493300d494c8ca6b69b1eb38976d6f3d5b2030607181924c9bcb20f268ad446ef22727c5ee63548fa507c1eba8aa17e6d387e6b59982f1f23ce1afdef792dc7c78a671141569af65cea6f09ac9eaa8eb7edafeb9e83455900989bdf1b7d8981347417b539c54316a60eff5ca5db7a8c7976a06c1c01e43a27c13d9df3bd6edcfe888b4e905bb9129e6635ffee6898de7c7e59d71d38932a62f20820bf626740ec6dcac58c3f83500d9a18dbcf6e8cee88abe015e753da9177d3054ec793f915c8ccdc03769a293aba52b0d68f15df2365a53f0dc27841d72f0b3b105279aec3584ccaef969334366f3506d9788418e4da157ea6f8d051645243b34fa93b0db265969b7033532baef2eb21cdd0e4bf9bb0a3a3cad08291a1a82273f115039e4bb6515770960196090c1d0a98e05c5cafaff6b86091b68af4f85185dfdcf6eaf4152607d608c6feaf8573c724f01578889fb7c44f8496c2c60c77f002463e781648bdb28acfcae9082594625748379a8e488dd081f147c380aa3dbd419d03d01a18bd60733334e27cb429e21b2fe94b297221e3dd20f415889b4bf383276c7b664dcf197b7e2c6e73f9d95057ef5312c1e41b054b58c33e48a7489ab22ea20064af9ae689f6dc1755bd4db3f3ce9e77be67223eb3e2dcc82695ddbbb5f8cde77b05c7ce86e56a648ac82c13d615f20288c3de97fd06683b8c2fb15d74cd13b91219fdda5891fedd7ae21f79ea0b763c87c0f817120c8f1de13b6d88d7f79ffd93b1e511e843c10b8dd3ceeb16fa53ac232518c7d83c78f88d82b844c6bd973b6596267b1e42da752c62e0744228b0dbc5bce5ad38de4c53f8cc3b9a296624fcf0906920e2d872a4bd59fe1956deb64fd34b08d31a3932b78ae19d91e83b6dc69c6756091d4bb11eaa7ecfe43b648d92b79b2841679653abab888732eb849b24d1e2943db5e4be6d599afcdcd7025c2cd774eefe053dd7b7c38ba1841a89d59bf7caccc494ebc21834742c0913004ba39d9e0212de76e5633ab0928f5e9144b576e7a5a7a0a8e4a8a1d60874d8a5848170e00b85d989a53878c0035b9de50ff9b601c8edc3624da40a8637240c3b2c4db703b25fddbd40bde5829bf1c1ce60ef20e0dc9ee4632494d64d622198086e90dcd09ea9d45cde7be9c00358b0925c201a4b8ac3ebf192016df33174655570d1460c776ba5aca6f8ed40e29854792d130d0c7a62bf55bf7237404b245a695a985d82e7ab38f6c1be57cbe1ba93cdfb5062e953864ad7d26f9cfc59395e8e556e89f99473758157559129a8c457d4ed607fabbe3473bef48004ee02bc5b0a89d9323826ca44978f430122dec187d82ccace1a627622544c2ed7dfefb438261d63c00846b98d7e9112117e2bb60b1fdf16b5fde8533fdf03007d97c829dd2a39949b319c46387f8649280439adcbf12fcd9e1df7d4b3a8407f5ede3424325e07f32b7bcf7c2de29671ad7dadadae984476f04338ff64f72c31e27cdbab1e09ac08d9ae886054efe8110ab232bf9e5b4599133552de3b14efa0723866c98c75535b0b916efc95eea5b1a6686eea83815bbf6fbcee792046b05474db7d8361e822752aed2a57d926f4dae96a09364353ad6f6c9fb4d6fcd697d4522dc7e386ab41dd9f8a637906e0fe123b7facabc719643172a84bffb50ccda872f6edf0e306d91bd130c26b0664eae4046eff52f71ba78de99d5cfc35307a583efe96b2604012b827a7ee34bffae1d5ac00a932bba09f0c39478e"),
+ %% SHAKE256 VariableOut
+ hexstr2bin("3e20cf32669fa3fd6e94e519b52a1dba33cd1f3a6947975e9829e4db326d2a18"),
+ hexstr2bin("6ae23f058f0f2264a18cd609acc26dd4dbc00f5c3ee9e13ecaea2bb5a2f0bb6b"),
+ hexstr2bin("e3ef127eadfafaf40408cebb28705df30b68d99dfa1893507ef3062d85461715"),
+ hexstr2bin("afc9ef4e2e46c719120b68a65aa872273d0873fc6ea353859ff6f034443005e6"),
+ hexstr2bin("8d8001e2c096f1b88e7c9224a086efd4797fbf74a8033a2d422a2b6b8f6747e4")
+ ],
+ [%% SHAKE256 ShortMsg
+ hexstr2bin("46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762f"),
+ hexstr2bin("aabb07488ff9edd05d6a603b7791b60a16d45093608f1badc0c9cc9a9154f215"),
+ hexstr2bin("8e2df9d379bb034aee064e965f960ebb418a9bb535025fb96427f678cf207877"),
+ hexstr2bin("9510ff5231813a865918badd0011f05915364165492ef17b85929a63e4951589"),
+ hexstr2bin("46293a63c235750d58a24edca5ba637b96cae74325c6c8122c4155c0d15805e6"),
+ %% SHAKE256 LongMsg
+ hexstr2bin("2bac5716803a9cda8f9e84365ab0a681327b5ba34fdedfb1c12e6e807f45284b"),
+ hexstr2bin("51b560fe5c3cc4c9e457e65f15f1b1619d18dbac916ca83a67a4d022301d5229"),
+ %% SHAKE256 VariableOut
+ hexstr2bin("3389aea66244b91428f089"),
+ hexstr2bin("b9b92544fb25cfe4ec6fe437d8da2bbe00f7bdaface3de97b8775a44d753c3adca3f7c6f183cc864"),
+ hexstr2bin("7314002948c057006d4fc21e3e19c258fb5bdd57728fe93c9c6ef265b6d9f559ca73da32c427e135ba0db900d9003b19c9cf116f542a760418b1a435ac75ed5ab4ef151808c3849c3bce11c3cd285dd75e5c9fd0a0b32a89640a68e6e5b270f966f33911cfdffd03488b52b4c7fd1b2219de133e77519c426a63b9d8afac2ccab273ebd23765616b04446d6ac403f46ac0c147eda629eb7583c8bd00dc7c30fcd6711b36f99f80ac"),
+ hexstr2bin("45c65255731e3679b4662f55b02bc5d1c8038a1d778fe91144a5c7d3a286c78c54f52135134a3c6a19a9e6e546de21b2e8a7e280290709f0e482a51bffa95137a381268d10195862818309b2a4954c656d1725c7ad1a29973162832d62afd538cf74e1b70d1775a9f77dc7c7380ea034f5b1869af46c1c26bce29e1980f0de9e55543e7eda19a56453c8b7d58a28ad7a33bc243c7242ffda5409cfd8f8ffd4b350c6d0023f27f93e9eb46a871367706170074d8a2080f0a8b68b8fc6b14b8b4da256e9e64dcb7771640e992eea2334e641"),
+ hexstr2bin("2e975f6a8a14f0704d51b13667d8195c219f71e6345696c49fa4b9d08e9225d3d39393425152c97e71dd24601c11abcfa0f12f53c680bd3ae757b8134a9c10d429615869217fdd5885c4db174985703a6d6de94a667eac3023443a8337ae1bc601b76d7d38ec3c34463105f0d3949d78e562a039e4469548b609395de5a4fd43c46ca9fd6ee29ada5efc07d84d553249450dab4a49c483ded250c9338f85cd937ae66bb436f3b4026e859fda1ca571432f3bfc09e7c03ca4d183b741111ca0483d0edabc03feb23b17ee48e844ba2408d9dcfd0139d2e8c7310125aee801c61ab7900d1efc47c078281766f361c5e6111346235e1dc38325666c")
+ ],
+ [%% SHAKE256 ShortMsg
+ 256,
+ 256,
+ 256,
+ 256,
+ 256,
+ %% SHAKE256 LongMsg
+ 256,
+ 256,
+ %% SHAKE256 VariableOut
+ 88,
+ 320,
+ 1344,
+ 1672,
+ 2000
+ ]
+ }.
%%% http://www.wolfgang-ehrhardt.de/hmac-sha3-testvectors.html
@@ -2804,10 +2935,9 @@ hmac_inc(_) ->
[<<"Sampl">>, <<"e #1">>].
-cmac_key(aes_128_cbc) ->
- hexstr2bin("8eeca0d146fd09ffbbe0d47edcddfcec");
-cmac_key(aes_128_ecb) ->
- hexstr2bin("8eeca0d146fd09ffbbe0d47edcddfcec").
+cmac_key(SubType) ->
+ rand:bytes(
+ maps:get(key_length, crypto:cipher_info(SubType))).
cmac_inc(_) ->
[<<"Sampl">>, <<"e #1">>].