From 9e65af386782c25846d674f4eda6891539f0a6c1 Mon Sep 17 00:00:00 2001 From: Miguel Aranda Date: Wed, 19 Aug 2026 11:38:48 +0000 Subject: [PATCH] Project import generated by Copybara. PiperOrigin-RevId: 967137298 --- common/src/jni/main/cpp/conscrypt/native_crypto.cc | 10 ++++------ common/src/jni/main/include/conscrypt/jniutil.h | 8 ++++++++ .../metrics/TlsEncryptedClientHelloHandshake.java | 8 +++++--- common/src/test/java/org/conscrypt/SlhDsaTest.java | 14 ++++++++++---- .../java/security/KeyPairGeneratorTest.java | 11 ++++++++--- common/src/test/resources/crypto/slhdsa.txt | 7 +++++++ 6 files changed, 42 insertions(+), 16 deletions(-) diff --git a/common/src/jni/main/cpp/conscrypt/native_crypto.cc b/common/src/jni/main/cpp/conscrypt/native_crypto.cc index 276927ca5..3614da7f3 100644 --- a/common/src/jni/main/cpp/conscrypt/native_crypto.cc +++ b/common/src/jni/main/cpp/conscrypt/native_crypto.cc @@ -9033,8 +9033,7 @@ static SSL_SESSION* server_session_requested_callback(SSL* ssl, const uint8_t* i return ssl_session_ptr; } -static jint NativeCrypto_EVP_has_aes_hardware(JNIEnv* env, jclass) { - CHECK_ERROR_QUEUE_ON_RETURN; +static jint NativeCrypto_EVP_has_aes_hardware(CRITICAL_JNI_PARAMS) { int ret = 0; ret = EVP_has_aes_hardware(); JNI_TRACE("EVP_has_aes_hardware => %d", ret); @@ -10512,9 +10511,8 @@ static jlong NativeCrypto_SSL_get_timeout(JNIEnv* env, jclass, jlong ssl_address return result; } -static jint NativeCrypto_SSL_get_signature_algorithm_key_type(JNIEnv* env, jclass, +static jint NativeCrypto_SSL_get_signature_algorithm_key_type(CRITICAL_JNI_PARAMS_COMMA jint signatureAlg) { - CHECK_ERROR_QUEUE_ON_RETURN; return SSL_get_signature_algorithm_key_type(signatureAlg); } @@ -11000,7 +10998,7 @@ static jint NativeCrypto_SSL_get_error(JNIEnv* env, jclass, jlong ssl_address, return SSL_get_error(ssl, ret); } -static void NativeCrypto_SSL_clear_error(JNIEnv*, jclass) { +static void NativeCrypto_SSL_clear_error(CRITICAL_JNI_PARAMS) { ERR_clear_error(); } @@ -11556,7 +11554,7 @@ static int NativeCrypto_ENGINE_SSL_write_direct(JNIEnv* env, jclass, jlong ssl_a /** * public static native bool usesBoringSsl_FIPS_mode(); */ -static jboolean NativeCrypto_usesBoringSsl_FIPS_mode() { +static jboolean NativeCrypto_usesBoringSsl_FIPS_mode(CRITICAL_JNI_PARAMS) { return FIPS_mode(); } diff --git a/common/src/jni/main/include/conscrypt/jniutil.h b/common/src/jni/main/include/conscrypt/jniutil.h index a7751aeea..7ac5bb09c 100644 --- a/common/src/jni/main/include/conscrypt/jniutil.h +++ b/common/src/jni/main/include/conscrypt/jniutil.h @@ -26,6 +26,14 @@ namespace conscrypt { namespace jniutil { +#if defined __ANDROID__ && !defined(CONSCRYPT_UNBUNDLED) + #define CRITICAL_JNI_PARAMS + #define CRITICAL_JNI_PARAMS_COMMA +#else + #define CRITICAL_JNI_PARAMS JNIEnv*, jclass + #define CRITICAL_JNI_PARAMS_COMMA JNIEnv*, jclass, +#endif + extern JavaVM* gJavaVM; extern jclass cryptoUpcallsClass; extern jclass openSslInputStreamClass; diff --git a/common/src/main/java/org/conscrypt/metrics/TlsEncryptedClientHelloHandshake.java b/common/src/main/java/org/conscrypt/metrics/TlsEncryptedClientHelloHandshake.java index 0bff5cf7a..e41eb97a1 100644 --- a/common/src/main/java/org/conscrypt/metrics/TlsEncryptedClientHelloHandshake.java +++ b/common/src/main/java/org/conscrypt/metrics/TlsEncryptedClientHelloHandshake.java @@ -212,12 +212,14 @@ private UsageReason calculateUsageReason() { } if (policy.getDomainEncryptionMode("") == DomainEncryptionMode.OPPORTUNISTIC || - policy.getDomainEncryptionMode(hostname) == DomainEncryptionMode.OPPORTUNISTIC) { + policy.getDomainEncryptionMode(hostname) == DomainEncryptionMode.OPPORTUNISTIC || + policy.getDomainEncryptionMode("") == DomainEncryptionMode.ENABLED || + policy.getDomainEncryptionMode(hostname) == DomainEncryptionMode.ENABLED) { + // ECH mode was default opportunistic for 26Q2, and default enabled for 26Q4 onwards return UsageReason.DEFAULT; } - return (policy.getDomainEncryptionMode("") == DomainEncryptionMode.ENABLED || - policy.getDomainEncryptionMode("") == DomainEncryptionMode.REQUIRED) + return policy.getDomainEncryptionMode("") == DomainEncryptionMode.REQUIRED ? UsageReason.NSC_APP_OPT_IN : UsageReason.NSC_DOMAIN_OPT_IN; } diff --git a/common/src/test/java/org/conscrypt/SlhDsaTest.java b/common/src/test/java/org/conscrypt/SlhDsaTest.java index 664a13c0b..0a6b7296d 100644 --- a/common/src/test/java/org/conscrypt/SlhDsaTest.java +++ b/common/src/test/java/org/conscrypt/SlhDsaTest.java @@ -312,23 +312,29 @@ public void testVectors() throws Exception { List vectors = TestUtils.readTestVectors("crypto/slhdsa.txt"); for (TestVector vector : vectors) { - String errMsg = vector.getString("name"); String algorithm = vector.getString("algorithm"); byte[] privateKey = vector.getBytes("private_key"); byte[] publicKey = vector.getBytes("public_key"); byte[] message = vector.getBytes("message"); byte[] signature = vector.getBytes("signature"); - assertEquals(errMsg + ", algorithm:", "SLH-DSA-SHA2-128S", algorithm); + if (!algorithm.equals("SLH-DSA-SHA2-128S") && !algorithm.equals("SLH-DSA-SHA2-128S-WITH-SHA384")) { + throw new IllegalArgumentException("Unexpected algorithm: " + algorithm); + } + + if (algorithm.equals("SLH-DSA-SHA2-128S-WITH-SHA384")) { + // not yet implemented. + continue; + } KeyFactory keyFactory = KeyFactory.getInstance("SLH-DSA-SHA2-128S", conscryptProvider); - Signature signer = Signature.getInstance("SLH-DSA-SHA2-128S", conscryptProvider); + Signature signer = Signature.getInstance(algorithm, conscryptProvider); signer.initSign(keyFactory.generatePrivate(new RawKeySpec(privateKey))); signer.update(message); byte[] sig = signer.sign(); - Signature verifier = Signature.getInstance("SLH-DSA-SHA2-128S", conscryptProvider); + Signature verifier = Signature.getInstance(algorithm, conscryptProvider); verifier.initVerify(keyFactory.generatePublic(new RawKeySpec(publicKey))); verifier.update(message); assertTrue(verifier.verify(sig)); diff --git a/common/src/test/java/org/conscrypt/java/security/KeyPairGeneratorTest.java b/common/src/test/java/org/conscrypt/java/security/KeyPairGeneratorTest.java index 6a1aa48eb..bc30973bd 100644 --- a/common/src/test/java/org/conscrypt/java/security/KeyPairGeneratorTest.java +++ b/common/src/test/java/org/conscrypt/java/security/KeyPairGeneratorTest.java @@ -27,9 +27,7 @@ // android-add: import libcore.test.reasons.NonMtsReasons; import org.conscrypt.TestUtils; -import org.junit.ClassRule; import org.junit.Test; -import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -46,7 +44,6 @@ import java.security.Provider; import java.security.PublicKey; import java.security.SecureRandom; -import java.security.Security; import java.security.interfaces.DSAParams; import java.security.interfaces.DSAPrivateKey; import java.security.interfaces.DSAPublicKey; @@ -94,6 +91,14 @@ public void test_getInstance() throws Exception { // provider, which doesn't exist on OpenJDK 7, and thus totally fails. This appears // to be a bug introduced into later revisions of OpenJDK 7. .skipProvider("SunPKCS11-NSS") + // Skip all composite signature algorithms that include "RSA3072" and "RSA4096", + // because they are very slow. It's enough to just test the "RSA2048" variants only. + .skipAlgorithm("MLDSA65-RSA3072-PSS-SHA512") + .skipAlgorithm("MLDSA65-RSA3072-PKCS15-SHA512") + .skipAlgorithm("MLDSA87-RSA3072-PSS-SHA512") + .skipAlgorithm("MLDSA65-RSA4096-PSS-SHA512") + .skipAlgorithm("MLDSA65-RSA4096-PKCS15-SHA512") + .skipAlgorithm("MLDSA87-RSA4096-PSS-SHA512") .run(new ServiceTester.Test() { @Override // g3-add: @SuppressWarnings("InsecureCryptoUsage") diff --git a/common/src/test/resources/crypto/slhdsa.txt b/common/src/test/resources/crypto/slhdsa.txt index 997652774..c6ae8aad3 100644 --- a/common/src/test/resources/crypto/slhdsa.txt +++ b/common/src/test/resources/crypto/slhdsa.txt @@ -7,3 +7,10 @@ private_key = d44f6f06a73a07451096ad4bfbd240cb54b779330a65ed34ec0cd372c96fe48bf2 public_key = f2b907c6b73d52125c3930a195ef650baf7f68a07f4f3435408ac5ecaafaf4f3 message = 6d657373616765 signature = 677020005c0922919fb6b837c42783b93a71a10db1794c86683f5f22dd1f0b984a66f7493cac79fc4a344ba07d1c2b7921e7b2ce50d7e5de20a47c9883059dd8e800a433d962a332c3a884f0ae8cc14977baa4d0c9067ea9ac54c52ff9bd715ea8dc5210ff5dee5bdf00541bb3d5a05305ba6da0920d35a596040a53f7704a430fa4eee2a21bc6d9dd942fa201cd93160d8e15347460bbef6ca99b0963c6050626855738d98201e8927e8543595422897954c62e8263e09a7f97d16a4a268afb7dbe022cc468bb3ff8fdf4cc865675045a010226a67663a1299d05913fed902eb3738cf326c45a712ac54ec462eee8bffd0624e7f40d34f24ffec7dd00b3c73aa92e3558c003a4103c404790eef989f2dd6c98bf225e5a465a5120b40133fc975fbe82c42c8a15435d55a72b97b13835e4bc6d71cb336659bb6b1ed4d4ceba4e98acd61e1180da27efc2ac6879a389b214bc8c4bf450410c786b82c0533a65ea6ce971281ba93de15f3983b57accb464dc9134490e88da36604f0b8bfeee10566c9a7c12cc18a42be2449cf5237c4d4c42ec384d77a02bbfeec73b0929dd08dddde0aefc26509c2db2de6c337af131e61487005ab54a3af835942a79a6abaffbd51056cc83231d894d0ca89013af28e93758dd6e913326ba459c0261df519b200b849cbd9994b55bfb8b89add46796cea6832fc9cfcda7c4181abc2fc119fbe7a264da627a4093e922032fb09f1d87765f3fe03fdd4695b6ffac1e1ea638141157960e539630e1b3f8e74b4ec62ed68a349a2020f08c59689e13eabaa7371fd198df194c985d2df93647ebd910f9ccbfc3465fed3fa015d6a890f42e1dd1359b7cd4c59a4b0d2743f1acf733efe9f9fc349745048c0fef0e1852fd0e9f5189eae8fb04f98cc3bee0a1574f46c4c54a700a0a669175867395a6c7bba1c0c4881db0b8688666beef55cf98c9aae3357f7c5c659daf36e72c2ae7dc2e757957bc45086c207aa2151eca1399f596732d25ba17f9de45188eec6782f919daa18e2f7a37cb51a75421bf5d1b9397cad979bbef09a87c7c57a871c3cbe0ebf36633281531b2bc9fbde43da9164101fb98204a56fea1d015a0518fd5930020cfaf26486c8e20ae54590a2a026ed5f240f38675fbd25b27caa2af4920645bd6df2dc49fd393adc95593cc3596c8f9b0c6183389b6bd4a1d1a5b682a41cfaac0dd4727df26b4443bc886ed5bda5101a7b2582f59ee41aade795e21e6cb9abc4fcdc3b150c9cea6eb49207b806b25020a369563a5ccbff289d808f005460f133dfbf4a621e9c93fc7d74edc0716993aa727c4038b8c4855216f2d0301a22541ec1e93846f6c89f1f16dfe5b916bf16e82a5e35a09f8865ad28d55833e9a566f7c12cb338e48c1d22c5233d2e17fee5b09eed81dfc655fb003f4045082b5269ce7263234bcb68225e403626249bd462f259ffaa065cf3831840312d7993219f79e96e42e1e46801c7e809131510007b3aac2ff7c8f897d75109a26fb0d4ee8c76a316a666f335a453ef8507a409809dfef3c4b1cf1f89ccf677a649084519dda826ead3d348a290bd1d39eff5f4a21487c210c37aac96e66e4bc9604ef988242a88ae0c24c7b034cc1063f3daff93a6c3edcaed6d27fecc521155787389d0398b268e233b1803a35ffc59b94847acdb4685efecafa383971a9d1ff64f093db635221fbca2ddbf90b25cb8e45ce3a474d16a9dd3018bd8b9a60287325000c0580004c9486fe4a65f0a9a6370523e1063d08f5862ff966e8277ccf27860505944b431e372cc2f85036828e2a3b5c50456bc41deb27aec611b5650b202d13634eba83ed4715f9220b1c6eff1e378a6241b9f400dffd06ac588439a2c25ee4b2796ade04d1d4bb2c616a0c6d37c95c0db4bab167f95c2e62682f17e585610562f5db06127a1478fdf166ef1e309f1618595b2eddf045f41899697f69bc383b1ca6f2594375f1541cc60c9be199d5ebc585daed75d8856e156c356b65d7bb253534102c790d6a14d0556c3949f38e3102bf2388ff8afeb0ad0338fdc1e0351293bb84b2164c5922fab682b966d7777109d9b180749604c5cadebcaa9b668ce966a93ea0945b8ea7b763c56f23b1b266c7d7e155008d50c18d47c8d2ea11fb78e2f97018229c2d78c9815aa50b81ab39eda8e393b3f74ca4ad466cafdccdc0cb3eecd992a6941464cdc1d8f14fcc7ed6314efe601c4340eaf9edf0d185d5430c26d593100d3dfc0462cd5be9537d973ac4e035b19081a994a6b7041898eda75393007013954764a90c4bcab67bccbc19e938c421fcc06f1a30e05fc138930f174674b9210d86ab26e8b5bf0e6adda4bfa9bce04addcf15b0005d508e59fd40b4d0b6ff7ace35b37a88fcb7234d6857d0eed91090c9d866b601a8715fdc4aa44a2d19c98a29fe3d68a1530b58f862f164530dcd30152d3d048ec3f8b24f17bb1616bab31075a05b120d864cdda3071e89f5dfdf3f6050c4456b35d6f4d1a2106fb25c8bf4fc813bcd8b788b1719d0f7b836fd65a4c9a0b0c4e64a8fcefd4e9b36093a54019e07d2f2204f4ba1077d388e9bb87ff3a285f7fe70f1f43054a05478485dede6c3e88b890d01709baf64cac191fc4b87f4879b51b975e9c21c0cd2a9288dce44fa998c5fe998748530a5e9c4bacc8d57073c6e0d3068d127f60e55eaae6c0cc205fd7ff17654b4150c5e728907440e96eb49ac1e3a06dc3ddc9615c66d4d29f2267211c41d3b2e4281e6c022d5a1fd8ae20475a638ebe5ee520a4f9cb404c0df3fade560e9fae29d22098377e392b2f39fd273a553d881658df7c6650edaf62a4e15d2573e18e1c2fe194173ca84b23426463fe14d235a758ab6ad0ca4f17b12801cfa9e3461640a7ced3ec1fd2e9a72786315e8d2da081cf93e14f67ebf7d6482d9bc0f9e4abc1e8e8529e6480a3dabb86d927cafb3d08bb9275788230d81c2071540f1aaea0751ebbffb673949f69e6a5fdb6f5c9d0f28b9a827bc7325517ab4b30e742f3e98cad59c48fa12b0ef9e885a03bb832c1efe721070cb8c177206d00f286a93f5bea0377ba86f7129dea527caae1e9f4ae9b0cd4be6fb174019e04e9d2b0273ce44393d0867a81938625fa7d114b1f36a727614c8cee27b25dd4b9411a4c4fc6a9b3007d682abb5f00f8ee12ec52979fe93069bab61349248b9a7829731c29b56e87095df83d2d02ec8513886bb7573fe755df88545fd142f682ab9792b9771e9cf4df891a28a218ee9f60f266a292834b4fecebcdb6baf1857b622a3a0a6486773b9872dc1e4b393ed149669f4a6c30acb931b578c2e0bca6e6d85171af86529500e1d05da6c830ff0bf1eb90c3ccfb0c578903565a7d733466cbf85041bce8c138a8f0f3b6e55b201570d252b57d85eb92abcf2ab59a309fb94a78f9207bfd5bf1b828e6c1781f4ef4decf2feedba845be48415bf09bf525942be085f426fcd2ad6a2f1f4ec92b189050a1546e7fec1d061c738c29d00e2462f2ce72c483f5b4613ea0c82def0bc289df9e5ba9eebdb0b870a9ab71f08c720e4883f72dfa49a05f88d002afc4e43e00e38480fb576ec07b4c014c2973eb994fb67771b1b46d632764f7371976219da13d1ea6586fc08e5691a41ebd19da2cdcd730b8d118ce1d8322a60262ebd2e0e03b64ef6ea93b2d76c9b7626d760b2efa8d72f00a4667741b749c6aa706895c299d57e6822c7a7616efed153a9c3fd907119e9c7309ae428f8154f4ddec1953f9731cc39f98982518cdb0e476d46b3873073d0297d4eb0c33df597814fe378cb11bcb74c1737625b0d8444e13e9c29e7eab66c06c3dfd63c71fc267199e9df570306cc340d5c31e28a6cbe4a78bb81f8f720c5f712ec19931f9df1efb445e1247f8db0e219d03d19b5151e50fa162d346dcc39bff43e0b2b4ecb6c5e4977b485a965d4c717ed060378beda79b32126052c537cf829a204b81a5b1d76a121d55a00e810beb36b67bb4960480cfb85465db65cac24368885190d59e6424a40c95edc82e9b1088c03339043a88ddb8fc071bf8a74e8c7d26b3576be535a66ce7bede9ce6442402472c43bbbd3306b39275118397a92ce70af9fbeb07ff1b7492316c1f9186ea5117ad26ec621d318786597b3d12d8426a7b98f1308eb8d911e501f500f6ba8dd0420e3c6cd06ca9207f2841403404a1c7e1d72982558805fab2104d4b35506b137fa56960099a06f5d824ad0d3a545cfc3215e9b0ce7af8be1ff774357614bd95e61a8d5c8919ef2204bf03be20415139eb8e06cffb797445441d3d77c6c98da65d694c285cac42657000636ea9bf4c689552a6baedddcd4bc79b3f48aeb68668ae1eee796bc13fbf4d23352d1dcf1c501105f0e9785e44ccecf271d08c4c0d5f6578995ecfdd6144398184a9855d37e7ea4e3364a876e80da9e025d0e8b5e8e4f61470b0f37d8b8a6739eba236d6065953f8d125555e1798e1e8ea9a7042bca0c24aba2c6d3156f99a7ee9644f6c608b07817f6706e15f0e77b75ab72fc09789a9e86bdf83685ad0c276d85f119382d2d461cb8bb8a39a8574bf7dc49d9b09f1a05c243f9c9b5fbc3f0f09c3169ef44df7fc1b8f7d211139ed0941d2b9d91c6513ad67ea19abe63d9959eba1fe354b234a51f9db4c4954e25ca9e14aa4a47838128ccefe8fc7c34034c2e3438eb95e5232af4a47191a4bee9e3c00230543382053760a782e0ab533d07327776adad619ad4a2cff7fefdcf9b290d07807c5b23fa7a696b914e40f90530581ecf2270e28eec1a0c485311e0f57a4807edeabe2eb7a89c4d8411d889c6164a6ff0fc9604e410606ad9a3f6837809316d3551491278b141d22e20a2c3eaba47657e08b5e849593332b3d1db5f6efd4ace89bd37a3b5d4049b1c06a58c0a9901bd1a9525cfd020b8dc16dd8154473789960b47903f66f50e89d23ce637f360076b055c21ab597f45560cc2b7d48f463a7d3120e03579371778928c41b36ccc276f52b1e4ffe7603cce185f8acb70f902b749e500685bd3973f33ac7232e9b6e57cdbe584db93d852ad1a2654e9bea68a6425a3b21059f4e44688de3f301bd042cc897795c83215438157831cb00dd94bb4d9cb42c31c15b6b33b982db25c9abd89b008a44846120489b71c24bfd1794cd110799e8d3fe4296a12d35d506dc31cfdae7a905e191cff535e12315f35100ddfa87f0004dcb0d549ac3d27e3541a1e90cb51eb2e7bc46b98d4eaad72d11fdfebd10ee7f0c55075ab95839c5e7f7f57f142485e15a966e590ee4c697ab4260046731aec31e7a5011026bdaef234dd56c55ced28b18b7aa91940ebb509e3a5ea4ba168c553f583c665a82076fd278cf3da36afa1ad3c43bf394aab56170639ad3a885532d563e2c285eb8a716e93f04ee1329c8b14e77f8c3c49bb3857bdae9cf91a437cc492d24ac74ceab9319459b382035e1026519a17b2c5d6b4923815889694750ed17737f478838bd842057f3642515c41fabd0ecc07729c5bbffa788800d916d70d2662c096d434cf47794dbb6db5d17ba9b8f47664759cfc7394aa69219a4c4c58d90cc520dd0c7411e32d7ac9f614de165cbe188a19dcea6569ae8468977aecb5f75abc80f30ece39a9b0e79d7047b189d1e00cb69a9fb2e57bca08c50e9693eab405dec5792c92a174beed639f08a85b7011ca43a1e7854426996857fb5df6d1951e45846a9f233050d0542d968dd2bf265c3ffa47560861fa4ac19438898fdbe6f417e7fea8ef09d6685ac2bcca20020b77baa7b56ed3515ce0da3db93d1b101be93e12eca5265501c061d23deb9b5faab13d5f69b0897374c6596bc83c20ab4cf05219a5288beb48614e0bd1e47203ce2dfb56503d076ed30096e47106d755e1b2a6ea9a5e7927cecc2373f52c17d8f99b329d4db48b1ad5122ad6604c0e8a4628f08549d5317a0ed383aa82f86275d167f04dc5e0a74907b5975557eeababb6e32b26938a90cfbb854e1fa0d6aafac8b00c513bed22816919251e231c9476ac4e3b4e8ea317758d18d015af56d29c772b00c168a7c7c23e3710a8151325b8795a3ead2144445ce0b7c3e4b2f73dce681352f04becbdcc3800d07a822150bc96b81a90962de171c837fdd263d323f25547aff50701f22469310ee209b41b15c0f192325ad475b0ed269ba84244f405f66c08fdaf3e2301108914699af8e2b63c6d29093358a30039b06a0b830f263c972210fa429de1e5669ce2a6529effd80260121d481d7fc8f111edd46af020209b2d8c668c37fb1a82645413ccf4d6d0c25c4542cbfb55e65c02d5c7ee631615973f2a0a32ed413a7ff07c0c6f804f3c03db1ef539a1b151540fc32849b45696797fddf3b970f840b2233f08377783e9cecfd77c4dd2da0c7aafb765c6ccbecbffaad01f8460c1c2a649720f8fb61693d430623603b96d98a31401c666787df53720f81aec8eeea773dc20279c0892028f3ab7639d98c41ef082f140463dbb7ef533544c7fa14ad9e0501223f2f9ba544bd5f80c5cfae08876c77333cbb8746324160082fe9ae9ba505ad16d5ebb921c6dad8cbc75b33cb3ab792266fd49a1b109a2121df8dde069a2a51f63eb5c90fc5e7f8df11f123f1b7a7d057b8895d24f5c4471e749aa6e00ff57fb081a6602405f1c89a48bfd8479dcd2f6910e1f7305964e0e35c081b5aafd04c8ad7fdbc8c6b3d44099cbfcb451907726481a04109e25c8fd70a76cd5ca80cc018384a9ae6a557d645b0f54d3e9f76b2978a326211c67a26ced1171703b576b17d8332b38c014853e0e9a3f5aa6cc5e30d888f2b32c54f915dfdd6dfcae626c747e85f9a0f8658c11e738bd9c8c724160c79acd3d9ceb4e80495d6e7b48fb63f1e55f4a9e310e92fa5ba5d93580718ae678c9ded688a0c8e75197a334d4bc8501b34cda264cb7e0a3232e2c788f218f8e3979f0f7b280ca8f85f59c75b1a2740911c381f93b016d8c79453cf87dedebc2f127c65426555d9e37d971d5ede6ba1f6b97d0b8d1558be4e72545285972961e28b70efe2d7a41076ce394d6f17a0cead75d3f5fb62b852ecb18a85698e82dfe332f80dd8492012d5f988e66a426532c36ba2365f5fe55b92d1b8652e83e40da5201b2f75ab8cacbe61d9800df3a7282d4c4130f3cca6aa45c6fe73732799e612d1ef694757fc163fa3dd161c894227673a7f3193be0b652c01226ef9519f415b0d7bb823fb240077dd1217f69445262122e74c015c2c3506f8924dba9897712168c54f604a4ef0697265f3a3e54aaf3c93ca933bad4d707cd2b4728054b12dee2ac8ec172e9f58924cd452aa01dbee114201d719edd8d052e1284ec9522492f4415725e76994456af3b930778d67b891c167621fe68d9257c64fd0e14ae6d7b63bf95a1d2dab75c90f50c8c0451bde828fdee84cf966f032bf9976aa1ea96d18aeaf0aa327071e87c19cece6d537a2fac6bb69f0ef8b733bc7fe3fdc9a26e0da75b6422416ea6bfe69d1ee921a0937b3699069d71f9f42e9e66a1ffff14b7d86d0209a8e7bf215cd645e52b8736c433c3191af6432164a25ed6b4c2050d2d5709b52337d061637b230efa98f4cfe81dc46c4ffa8e4b92b17689af9a26915540604f5614a68cf0e0f43f98e3c7d4765a7aee54770b279c21d4c4439af654cc486ce192b36748f4b06a64ddb6a2d84feb7b318e18d65a5fbc307c8399a62d6954bec2485d9d924810adf675247fa3940e1702da6ae864af97996a20679e6e52c8e18fc8ef18a32fdabc4d826f919622928e1900a8054ea8015eae3b6538b5833011e72488616f3033a55e1eb998e48ac443f3efba7d8e7349c43b0ab4df18f106d8f235bed643ec051f5c524f0e0493239cb177e9c2d3d6ebeec99a222ed365cc54563efe18984b13bd3a6480adba03c255ae10c4c8a259fca9e7ea26d487279933ca1b81718f830f8d5059416e22b7f53a2e675e4591810de04483881f6ad08c69f027723220168d870d0e41520091fad771fe2937daa9196833f49a69822a7c7d71dd557c5206d2d00ccd067707aa407e29739de1898bc45978599099c5e0068414b5a559539717c4fa8eadc9638fe9065aaa0112cd08989b35a318ba5c09354f2e46f437ac321c89a0d6ef3201ed13f681c6962d78d5f0d0774639e42febea7dc85512c1f0f278c7aaab29c50323a23c852c01bcd9a0f6c86c8af9d68ffc32f40ef267849f895fc8735c08f1ef9b09a26f1724e83b5f039950a6fb8029f13ed7cfd91068f05d4abda87f698aad0beb5b1463edca5b6320a71ed493c78f54bf4111928969e627d791fadbecf38c5e96f221eff2abaa66494acf6bdad1c45db239541e43159c1dc4c240b1f5117823843c1cb01c92813354094f11e7200d963226fb265d61c496ab296a27894bce9cf1b25a9ea9725ffe2a1b7b34652281e683f5bddd34ad920736cc179476cef3eae7f5971e4954885c9586025d65bd37f3011ae466dc152ad67d3fd6535637eadafb5de121abbb773fa54584074dbd83f7039a7fb10b87f424a24bf65fc1a7aefd998ba53ceac8ca3f272f4364a2f6e0ade0369eb57d97fbed155a5533cf03b61ff7f5933c66b57fe8bc364d9e6c96851b9464bc50f469598646f7157efe551695d283409b397bdf2f2402cd0a7629986d011e871c84af690738ac8fe727736bbf00aec9736a4c846a7f76ebfbeebd7c2c1dcb5784cb569cb86c287d4ac04905061fe5754323335c4a0a806fa8a253c1fa3c933512650be1c0c65cfe98851accfc80fd76226fe33785003c176790cdccf459800f5631da92d1636f17e7e0a6eb2121e45dd1091be5ed2de90eae77c6dce6e9bd3d1871d2cae994e7c84fed03aa0ddb99104ff4bcf725ef9554e5ea0d7f0bb91d7938c052df93c875e6dec129bdea6e4c7192ed11f646dd3de7ca0671841cf925400396879956719be890eb54fa62bbc061b8416d18f47f9275b935c055e6a01dfa8b80d6b87b0223719d52f6c02b9e18e52faf141099f1dfa84ad237743486702715a52e43ed5ce9edc7e9f3a4801ad0391df7af438a329bf09e0c05a0af22871f14fe31d2160a84707002383d2f5c6943a8cd430d9f6d852b79ae14a155fd8135e8fd96cb2fc0bdbc2db636eca660dd7f95b58c35b06371858e3c424de3bb66898f107cf2c91a3ca1e5339ed0ed70801b66755161c01f6bac92f465fe51f829bd23d2d60e5efbc976388f67e721103888eccfe06b98d61bb06725947e6d1b40005d6841cee60a4a44b1aea78d0e29b8d9559835bd6f30b5a6709da9dad96061f31c459968e8738ba35285ad5cbc43f8f8a756c4575624492516e2b8d8d0e6006ed969aa7d20ec67ccdabaec8eda981946984d77f763e3fdb67e64a9952791882b0678f2d3466426542c79821b1b5aafbb8fde9d0a7d05655bb6c08f4426a819859844115ed8d5fea9bb2a97da52b7f5f79a21e199ee167675a660a7c340ca598a968e3107dadfc5b96030dae6dd8c4380c3e97f4321ce3e477099bf0f8e675b4dfa10e9aa655c8582828fb20c85fface950f79df90cda4820d2ea21939cad07d8aacdfe47c3e2176663815114cdf351a5184a51a29da690b8f75010e3196fda09957e74c3dcd9b94a677bbf40392b65eee6c1fcc254fb1fbe846b665d42b597f58528e804250bcf81735b2c5593de39da267c4309f5d1288c4674eda10ee6ba43520368ac3ed832d3dd57b5f9c7e449b6fd631fbef0c19996527273f695afd5b42f6eeb2db00a3e16210a1d9322122cbff34497065f921a61ee4bff495a7dc932481e008c05f24d080cba5c993ffa8f842e5de3e15c0d536b2111b886d3ec307be777a5e91523278bca5ea52864ae0861546cecaeb99db0dd3146e582bc192bd85c6dc9b8ffbffef3b490275cbbf26f4bb8066f874d093e6f29f7cb6a9aad327fd2390f62d87758de01f60139b25fae885e26575f25c6996332d2ab0ee19b1b11e6bd920ef10a204ac60160dbf7908eb31fc4e9ee183b94055ff93c5d61c65633b2613587815fdd7d7140c0169ac6c395013d1dd940ea6eaf1e03a407af2ef43826bf9b5ba8fb5606eba499a55c25dee71fea4d90dd0487ff878da4ae12ce3bd9ca213fa2d02d218f7fd0288ce856303dc1c25094843eec22342b8b583549a7c34fdb82b8b304b34da42d7730e4fbbc4632178934acfe2b1914a50c1db64615463db5b5c62c898a65cd794d6b8a21b9c0295e406a9136d7e663f6070512dd9912a17f1f02d8f1f02909503c5d54fefee23886d23f17c030dbc16c6e5b89b5270c4de69b77fa8ed2b976c381879854590f2a2636688d382e27d11f29ae73db88abe4275db37622a7650ca9eccb7cebc59693170796f4297e7846d2c9605b2362c52ec6c9601bff0a13176e491fb6f35e45f03d6773a2e6581cc436286c40501cd05e4dd25ee9ed23cf692a227b90179884a4e340156289fa433225426540da3c40426197b70acdf0f096cd049264c6f2273c308aae61648b7358c3ef110811464779e0aec392eed07d3c19a0487022965f5a588aa27bcb08af860610174210a9b6dcad1fd5664eff817cf90e745233e303eea0233640080920febe47372eaa67b32215982d8d268389b0fa2746c91049dd689726821d823d3afc4f9ef2e547086aa15f6ddfd8e287e517181ba9c6b4330720201667665ac24c6c7b73779eef718035065710b4236d132e94202f3f2cfa9dbf52c3d448f163f0c4427cf8d933bedd364f370aeec777e79743d8184d052343720867a14911d35c6fd86dc51a655fd23b34ab33307f50a5de8852f607fb11a7a9fcdb7997498a56fa7fc212b26209edcb7ac03d3be52d261e2f7f8120eec51391f386badd591a9fee82e49b375095b31048af565178c21d89e4f1017f32457e62e41013e49a68d3eec723d4dd16c7d6e11c1d784c5706b9740f3ad6acb5e3bd2ec10eb4f1226d947605fdc85f0d703eec9cb739d6be581b1a2acc37bd4d90aff0b2687e3b3464a48011ee0b9a1c571c02fc4efb94091dbce2357266713e160718d8b5ab1bacb6cb5330ff2e9dea49d11a18eb924d1c3edb7b4fff9a6c60f23dfd1cc4c9 + +name = Test case 2 +algorithm = SLH-DSA-SHA2-128S-WITH-SHA384 +private_key = c10df59aac52f72003826c0c2ce7c9fa22196004ae8e6b13821cd859252d933ddd83b61948df11c86eb2f60d44f817f4157de306d009641096aa65bdd4f31f16 +public_key = dd83b61948df11c86eb2f60d44f817f4157de306d009641096aa65bdd4f31f16 +message = 6d65737361676520746f206265207369676e6564 +signature = 359f871a841ee9ac3a9dcedaa6d12f0c87e6544be43acd94f4b91a4985ea0caf11694f52d7ba0c7365df8270b207c20a07ce34b672f30e1a7e3cc46c5dc15b94cc38ea4ca06da202a335cfacf24d5716f755c0a46bc32ace96b41d0474504f958f49ccc867ffd4a28439f556b6a385776a7a90475161fea833ca71df2eea5e34e901fc3bd2acafaa0bae1608f5e1ea625559719fb26129938b85f8ca924a22c8531a6dc60e07a45fc525215f3394469ac93437bfd7eb16c3b089402a55d9d2587bf342bd864f889d75acd1c2fedf13e1521c7c7083229d82b13ae3c7164a5b68806522fab8564c82532e68bd178fd749d97ded7ef328cb996029deb50cd6a202d848192782166203389a7c72f9805e556960d48c247a02dd077fa59167e43c3be43dae8be8ed91c8e77cce775eea24958cfa9c25b97684858cd24c675b3f26a806fbf8d11d4a5214c0b7332b9409f6072161ab48562839fc4b1db781a0eeb2985d1ca946c014db4bd9bec0c5e10a1db702840c5abbb277af61a6cb4345610ef8f70d0f59e4bcc60ca07889bccbd73aa54abaf3b4bc8254c260557b5b3cbef53aecceb979106ee68da3497670534b52596bdb590c793ab101a0cd42244f047d7597a32c206a4067d8c25744cdd43c84d9c9422ed3ca1d5a8e6927255cbf757852eeb3a8a96b6e67427d0b26adcd19dae996f448be6547cc896304946c62453f54ac602dec81b1cefb342757fa45d994337288a4d5f56ece69d7da9e2a51f6547a970425411cca9783f460997b3afac0cc7677cc7722f8f180af923d83240768e10fb6de482bf04cd5c26d830360b4a459c5c679ad1f36c8c2881484ccae445818a438e20623069cc978c514f64191d6cd7b4fdc43547154a5f2a0dbba88f8e1e1a6a6b8588928029c563ad27ce80f31f780bba1ea3bb06f19e014ef67406fd6636006ed7d925679bcc7f58b8ed27accd566fc175037007408a0a84d3e63988893871403aa69eef388b252ff99fb27e6dff942f90fad9d0fe3fb57eba6519618e28e5ae47da8432fdffdd70f24ea5c4a5f78b25a69971e712a2773fa79158207bd172d442a85099a52aa3455b0d48f311e68805c29080bdf3a72f2223f070d071350b3de86b16b7f749feeda6ae5cc0c1964d074d9db7318faa6d3a077b93fa30703878fbf0b9874d42a698dbce6f9f6596afa3491a25e07541ce6dceef905bc8c19802fe96ca6218be12bd66f328617c9d05cef26cc33340451dffe2f106289082b0eed128a3b68faab0f3538745c3c7ee7c2903a48c8c223b2684031bed153aaaacb6a1af04c44f08fef569975b7c3fdafcad728b052f4dc3f621ed353f58bbbabe99ea731eed2ac9c4a9b7ed7ef59a12334f736415e6d73f64f80fbf7633d74e089bb51a70cf5370631228b303e63cbcffd0613444ae6e78e683545332987f33a9d13fc7fbe25a4fd3cb8812580183e264468632932a9b2c852caeda5f52e427a034e9870baf3bc7ee8f087e6d0cbac8558f8be7de9cc512318816176135d1fde4b4ea343ab74aaefd4cde674b0d6c91386a2c7eb416e474ec24e3ba7acd93602c27c91dd478d87ad7fd6f9cc67530ddd6c01ce091eba39863207f72dfb1ccd60691af6fa65e9ee75a8d8b79b32a300887097ec775e7b5b2c07a76b7bc15efebe79e006e7c05ce9dd9e96db696f685747cc1465d665f833fe0cd6f56688dd86ae1dfdb095e312df978d9f63f2fdd9a7543c86e156056b53441a16e4b44f8189ff22bdbcde15317927a4a63f71ecfe2092d5fe3955cab86ba93ef756f9f69dfac6f81982b8175f7b936aa50b9bcca8ba62bd783d7874058b17b3acee9e1408663687ecbedc2e5b4c2986de08f9c82c74a4fbf6105d9ba4f7267441dd2fc3fc040d2ed7cf1b6371d28164adcea32873fedb2a577135d557a5638007b0b93e98363c6eaccc743cf3ab314d1b847d8fee771d51418955ac774f2b4abc32f9187fbbf8bb0e0e063003da0810dcdfd49f3c934b9eec973443eacedbb427489044c688a2ada3cf62f9a2f76e3c6a8b19c1df18521f1a02d38bbdd10f813e077c1937c317052b718f6d80575499b760fc5ea052f490b52a1a9f7903c9ca7974a95cd561aac761e1a4d9c55d51e0ae50542b8ea03ff6142bc80ad8dfe5e3fafe7f4053eef146f59a5fecf2cdc24d35b9379eeb24969fd050aeee4226ba287e2bb9d6e1c16b0c69a28b82c1159a86906b44408ba188c42fd9753897e61b87f1a04e8b7320d616544e0d397c12bed265dfc82a8010c1d702480e19ab4a54d1d9327fc9a07d9d4c04f4200023fc25fc149237a8fded4b6f6a1ef65a4a89b828a15838b29d6a34e50de6bd741fff7ee418da841b123f10d51594b71653c6895de098cdb1a98e2ad4836adcb83fc14e21ecca28dced205fef1590cc315028b9b05f7cd91dc2672cde6fae606be07372f4b416e81d21388b201be1dd87b9304f11bf207f5af35bd3c31814598e1c9fce43e822ae0f5d61684bb78439f28951419dd553f3236f724444a6de595398869cb747b6eff36bb36575cc4041cb55094fb23f75a771f793fd9e83c40dc6c3563ef0eeff36040e2f475c0745982f6fbaca858c23cc0cfdb578c14ee7590c038f5d19adce6ae2991252f5a212aee775d2158a397886122b79a10cf07f634e5b885ffaa59f437bccb0589fabeead7b4239405db02ec9d0dee507a5ed492a886dd2527aa9cf4b6426f4aecded5acc09b1ee1d3d74374a97f00dd51630823bae9a33ad6aebe5baba8bafeb3e1ddc0104ebb7e7d1aedb9416c3ae7e293f9dc046e58b2745afa1fa9c7222c0fb17abe46aaaeda9dafd1b357cff92551beb345af6920f5874abe52ed172e64f297b44295f5b9b5d2f886cc1bd406d26f8afcb66aca0e6e926a3f2f06e0e3a9f4a80786ba9e54da4a8ed53ff8bb4b818fa565781ac7b5ad8ac9a1eb61d64f14d0c3910a27ccfc22a303c43c1378a7a4cde23d48c228653697b1782561fbe364068ddf1662e29432900e869721ad6818d2f9e637c747320052a21733b00dbd3c65aa3a7e3fea7233dfd1130daa654be305a0b2457d7aafa8672c6a8d5e35d4e65ae714bebe461ac64dd539c3019d54458a1db1db924e60259bdf888d3999baa9e48f6811abd397e269eeab74b7503ae61f9f638726bf436818587b262d9ef5de694636c7635e6d06301d2a3814bd764f82c100a292ecb1b5141f69dad585d6cece54305ca40c5536c12246fdc534f4046c94df8d45610494a320a0fe3d321581cf5923c58796ed32ef2f39a03d2c50bc71cdcbfd1834dfbcd24bea69c600ccff4e22f09fa89427ba1ab293ca17d35660776f2aec5a73076defe449897b722c6108a611bc8b3868f93a1462d023b687eef78b6da4e860c82ab7c6830561516d7e77fd86b5551a1fb75c61acd171120a81aec35fa4cf96ac231dcb124039734aa3d84e03e9217b31dcf427dde168fb0560f7679930ddce74b62af39e7257d9375c46742f0dbe9b18f415bd20e3180c67de6b0aa4321f02c25127d008585b364504023f26ff2a386017efff5dacbdaa7a37fd39969b89ed8591d9a10d24bdd3e61d55264fab12d8e33a6a03df5709aa11cfd7dd970ac4461c3225bd43e6cf9fd7984e7c728db4b9be536b009f946695f8bc66ccd7aaa9f04332097fc03330312b701ac6e1f0e382da3db7485fcea61daadc7d9a25bebd4d47ef237846b7a00c5d32fb31d80044703186c9d2c1051e8b7cb864514afd9e23b05ee996b901372de63c10134220a86fa19f5eca91161aba904ce7095ed983d4bcb56c10a6381e028399a3b5a52ce9843517420b340cc949837f41bf8368df637d5bbd18fefb5aab1ca577a2cffce69747d452998948d47f8d2b97179ad7fbb84677c9c5af43600e03c4c3557b8a31817f6219c8287f963b2d70c9175ad74640270933e0a5c6e2166b2bdef20e62d849b2df6d1468bca966eca9381562e266183dbb7cc1bff981c8eab6a70a3bff5f15d56eb78f28bf6a5e68d2ae4fb85aeacc635975e34da6277c097663d1cab8662967c3c178f03cedd34dc55a8e39e3fdd7f1fc2824d3684c33b0d23a3fdd7129635dcadf6506c8992ec5547c76124db2fc090e57757040e1d69fa1c4433f84a48eb3c1bcdcb4e9639d7fa51c4beee9a2339a5f0f6c9a318b56fd7a250830cfdba59be3497374e0b0ceedcfff7cae485f190c9126350a65d5b3a0adf91186308d7010ae3275b71857e4f00ebbfc4378554d138cf0eb910e8644f4d9b697d0eddb4fafd857c3022b8c57d6407406d678ad07f1fb4b3256972de4337d8e57ea93eaef5269b84609eb6212aaee7b847d79a70feb32c80e238e630a33fdbdcbfcf654e8d7ee8b88db7b68ba8bd7744722d079d23fea28323f180b08fda655bab394ac4c1bf190f307637fc8c63bdb2926c2eda6c8ccbd37a1f29d613726e5556699b67175be8a5ffcb5e04a68c23060b72c5ff06921414d50ba67fd003885943872ab39e6a61fecc3e5ee150e1d895a86d1edf0d7de1ea275731f0ea1e1980456c5892ed4f3ee310683144158ef9392031e7148900b5e6f95fafc5dc79a56c3c4ebc2561021dd43538e9ef09dd2759f903a7895dc315827c3528a15ed499745b0440029843550190532b7f70b542502711a0b16d04d7c509cde431a7d8c8da6822114fdf9384e3db2c567db731ea1d1e6eec3a35df085b7993a6ae0839d1c23dee2638054cf45ed864d5bf321a4016486dd3794f7596b67f651829559f674996aad00aea8733f33f8ebbcb047b2656c8e3173e68c0653a34712ccd50453ecf539e718d20d3b0f72f53767f76aae2b0cc893708836809af3a04bd50f600e544073233714ba11a149514ca3668b96a2cc84d0373c4ff26488c40bdf226e5c43f65b41e81804120a242c14c26e340b9c3065219e7a69d99c32b3d95c810a569f4ecc564928ee4f75629949638f395cfacb9b10d91ba17618ef88322ee0a3b5883da7aa572e320f48a30662aad8021643c0280eac520ad118c0e00b67098ac62d8fca228ee2c34890dc2a23cb85dabbc908ece6800ed02f76e8f6d379faf7d33f80aef0c27f019003e57e464bcc415d63cce45a4c34b448a8ca510c29bb9f4e9e4ad564c3199e102c33fd9e98fc82c1332442013977a225eb51e115379c590ee99d790800f534ab85d459a969c629c8c1ab702cc6f9fd7c364500941df287adfc08a81735e12fc4ab4eba7c940911fb063ba914e8e319437259fa86368583d03ce7e6ee2a0dc016d77b544f91e1ad70839d7b2f9e00f84af7411279ed8bb57267805be8dc49f4b8b2c115e3d950f0d1e039e5d8a2de34fe0604e7655d60a90df6a9b32578f29295cfad31828a5dbe2fc081a6dc90c716b7b50420da84bc6e1f99961c2fd75f6b4eb662e64ed4ed68a251785bae069851dc006d87dabbe9fed668a127a4264201e7e020ee3a6a96ece9668d5aa4f593ea7b04d50fcc399090700a60f1882240dd38209cc60e7454087da9a55b998c14b18b1c759c47c8b5cd4b019a1a1c1d9f6c2c7b08c740ed46cbc5f4e011f4b94db57b4f2bfff9364c3aa1be8eda98556819fa8d8b787cb4415dc877974223395b6d9c87f91d00f72501d04402f561223ddb613f28541e9a64bcf124f3369cf05287dde7bd2dd7f0da32e74a98bd1cbf2ae44d29113038c4034cb19b1725bfd65d820961badfd36369790fbfac9491d27afdfa09c99720577035526e3e6997a658c93c8377b7b3e98fa1099828ed2170d7d3eeb633deaa15e24dfcabac28d716c4b7dc5d1e02a7edf9857723230255979604645da3aefa3b09509af043783282155ac007dbfa586adfed83ab56f1a9bea2e76c7271b3aa08c68d67eb18e74d18b6cd4a5226f05d294c0c8ca1cb3d4368987f2609cc9dce12315f472a842a897dc7b3237b5570ad85ae08cf9c1a01dee86cdc995baf20b227f1b05b98fcb02d96a17420741cfc115f1a551d1c2b3d928c182ce73e4451cc4e35413f26e8b4c699c840ff25eaa0fb7ceb7a3e33378eac749109bb82eb77f5afbd4f5339243588202144c3eaec0e180031cce950dc159e95632835a045436cce3405215e01e277ae25fa534a1c26ac3afd524041a3f82635e773a867bec821e97c3f8f0b83b94f61adc93633c5d856e188f8e64bef10d4747c32520d0e33565bc0eeb081cafb3722234c774569dee4a244d57f96840546c3cf942867ba8dbf875ed25dae5b17d66f0783671695db1fa2c199d09c87b2c2020c94c1a4dbe1cc34e755c4b6136e0d681d9f1f258e982ec57fb0286031261f277ebf1eea39b43ade8bc58a5ea7d3d21f8cf418b6018b01b44221a8f1daa4353a251e5a9f559fadfbf6ef66836bc01788c7ca2371b354d4aac38a8e91270528c6f3751616f54b6cadde78c2a503e8bb7c2fcfc32d7f27a2b45e7045273b61a252026a258cd14fe0b413b4ab139a070382ea9204ae7ec29a5f4d4f505404b05a96bdf55d2aa21452ef038bcc313402e39848e620e23da3547992c6be478f55f4e0b5544498fe5b5914b442a6b555d2625bbe4f596ce37a9e55c866732a041ba796052f3e8e0f35abcd5e4826a0a81a5a07e8beb6afe1cc648e2c0acec94d53889ed89407acc3481b3f291d0b7160fcd591bfc1ab84ed6fe0a452ddbbeb33a633458f318ad3cca23f560a71c783a5496bf65d39a65db7bf8b14fe8aaf631cf75aaa789f9bb75797f72bf9de70ebbf59ee95ec2f2ddf5fd07d945f2b241aa283a90acd4db87e7bbfcdf2586f6e1a4b6d1f7503fb0f61f7188fb49ff181f4baf2b902b8412e9d8902ee1abd02fed943ce8afb905c7619592d07ee5c687ee924dcd938169aa109c7029f0078a83d6c67fa8c788636f2158518a6a7f69ffdf1c3f8e9c672974b971863a5c62dda2ad47d0f5a24b36bb5de10b8f4e92829da27825e7daeb7e53d37b291e7d30a955695541b3fd5a4c8e9e69122973c46693e54ecae81b8c681ca4ea4e1450585999b927f843d2ebffafb95cde5ac40ccea182bd76b24c2862a01c53727b81d241f3dfe67c3913e01efc0bd2fd3830c149dff347ace55207d8fcdb4f60f32da808bafbe794c285ca56e1b3903d0e07e744d6e2d4a79288fbed67a77e1aa5f57e15c4d816ee8db4cc7ab61dff6c32417e1c06d877b2fc14c3dd9c4ae79c1cd8b07b2e8b14e9f0e85fc667fc7942420d6d19a1721fbdb4349082148920420d8e98e5df62c5955e54b954e2cd10df2cc0a26c47b9a1174a13b84097ae78efc989bc5c85d9ce4518ec485f5bbab35bcb5b341dbf6f68c08057f115311686ee58cc9e2b05130649a671e4da5b3823a04156db4b387781a383fedaaf9c1cd9070cd162c31b75a268c462139c5cd0708468fb9aacb7d7a0913bcb05c249e6fde98c09238f7cab97ee0c3f5bd73b9c86a1714f3de2a4e700967bd4ff28e57fb3f9baad9efa9d947c3d9045d2911db9a7797dc75ebd334c80b17a912997f382bb1f5f4c0b1054d962f64d345ee9609867be0540a59aad8decba3660be1a82ceea95b5a305a22e2e51a3aba5c401a561ae3e7a1386da29c237e8bd4dd32d80b8305ca9b8459019a940146b008808f9dc45d96af4a53db78398add7c24e6d4b249eff53c650e2037dc893e834746c0264049919ce2b6c5a326e16755f870ccca91d7d54103da4d293f0d0e30c06000dea64ba70e3467acfa37ad9629caaca89d8589f04ff80ba9f46bdf5317fb304df8809e3450f0271ec8a13c7e44ecae608022075ea84f74e6bd5c28a831dafcb41f4aeaf32d162c18ab8124ff15807229fc7d68d8d522d3e3efbec53e3b1120935ee23a211fb7fd1e265ea41063f5a21a1fef2fc2f8d3b0f4121af4cd28a1247029736f21065cdecfac7869bb0200fe685e988e1b9bcca4eaa3743f287beed494a9de37f65960544388fc906ed91853f1d2a422d8181e9b949c9ec5fc31d3f561634b12fd63148c97fbc8d13e90d0434cfee180f34b8274a779593d23514c6917595485a99780794bceb0915264dcfa0076e0c08116b61a9ad9892615a56fd451e07d932aa1da7bfa72abe8c0ed64e9f3c4a7ffec1843056ffb58f4223b5f17d20f64ac770d1bd54a475e05cb1c0051a9c23bd6c32cc6064beba1d3437a02a19435b872624d1064e104420f032c2ccfbeee6615fddfd2c93ffb0261d41d360420731ff81256ef3ed08f1793030ce0a03079a0ce086c7810f991de89449763edabf2ec62729e80302a19447e1f93e9d3f8a178e7a9ca023b6826fc70750be8063dfbe2950987bd5263627a6192deaeff96fc311dec9dc229da59db38a0c9864c7952d16460db61739ed81f453af9f4c7a178e3af8ac1442e5d3ee988465f2749668342d3337eb62a76eda0a3d0055e834cf5b6ff2a579f76ab9a067649991ce69fdb1f3441a6b20836d18310641988f917812451f27c6f582657ad06399b0321bb844cde4474f7d7ffe395bde58e84a0d684fc8f078512b61bf79470099524521ab70e026fdb3e1d35267fdef10e4e1848282897b3ca14dac04a99d35270aa0f31055e24943fa926e1c2a3d7a300bbb614f1b4a832ac6a4e76e096cdaa4400b192e646caf3acc906cfd1e3f7ff40f8d7eae95b24a56360b90d7b53c34cd0204ccb54c895b5a2ed0f616dce8c62f20aba964aa115958194a9b65227808c30018775100c99392ad1d41c83853aedcc3533803f58c46bc066bf38f682aceafe2f150672765d7a3351ee97d74592d3acdd012ecd4e303f2157b1c25ca8ab690084a3acaed2ea677e7431ec627068ed1b68581b33f588e3e795888757252dfd375045665d61c87a90a26cd39b952180992f66f5df581c30692a7b06fe4398cb1e72ecd74af2b5bd74faf6813a0034cb602e5efa0f89c3cea74699a36ca6562fd74338f73a369261c5e62690e12dc025cdae6cb6d06182f5c29d18b34bf7fe8aa0ecdf42d0e322cfa2f829a8bbc2831c447d2042a88e433be800192cc301c7f776f3b572099ae91b767ef51086bcff52fabe97f4308f03bf3dd1e49d6ac6e1593cd5e34924641d5ba7381cd321028b35fb50ce668ea3f8cb576b982392f236e61617905ff907f3946560b830877f6b81fcba46ad91553776c63a8baa7153b62edcd5cab0daffcbcd61794b6831076edda11873c8993cc42fc9abb5fb470fba1b6ed6a01d41544f1415b2a0af91370c1f4af2dde694ce5f5fd2e5d717793e3552a6f604cc6b5881fb28c0b743b946da0cba4adfb4b250c0f9057a1f186a4a02d9648d0a86d7ab56afe577de7b3dc05095640ad9903bdcc46b7971f93ec692a3e6d570f840e2bf1cf875c7e093bf3d9cf115a528ebd4d386795672f611c7e03b37a251cda198a5c23dd84f74f6ef2cd4b512626f11fafe08490b2ecbcf5a92cdb8e6a7beccbd94fba42dfcd649e066bbc42eb7ca99fe97f95b16880728126af84167706c8202ff05227b7ebcbd3866015f1775de65d2ceb8b0993eae77d4c1053e58b4053b915475ed2e06580e2316e27cdb511a36166d21d088d4c3e2c9a1396c1d4c22ad34ba31d814a1f7a8353bf840b956e07b7f2758a3b71f5e70c91b35666fdc200791d1a06e938d60c94b8def7a19f3d5a46e57ab140e408b445b411b23907bbbfe43768bd87ce4648ed527cd127faeae337c97ff3785b5366d09002d757971cdc676a4faa10140c51ca787d41b663cd716d6731f32fbdca6172e380d1158f593629a7fed9392e9d83ba3ce89564d4f124b7f6364f9a1412ca8f601339494bd2c109e09d35a5b5c933b538928a80896460f0f73b9edbd6e6c4d590de162cae9d04adb7b6db61b3979c18b7a77d747ffc12b3a0f6c0d03df862f3681f89edb0a2e63affb69cfefa0e2850db2b32513d8b38ab169f7ccfa0b38a9868d97ee0050c744b435bd4ff603b64d4f7d3f0e7d0655919e6ef86d210846ebbff563a03dbf3573a2219577198752fc41a14188ba269698d0fdf52b8158d5567103ef41f1d6364cf648a424035f61060ebe640125c636cb17ec1f53abd6869435b4d697b9ad621d4c1ccfccf88f1952b48d91f6e25d8bf244b47af4fbbd1573a6199307a4a7b9ad34289df8683a4b4324143eb8a6dfedffa92da5896d47f1e84454367b1e0d38930d047c7c1a523b54f42adaede72d46a76c9bfa4651ce28e3e5c275d0144417dac775c2ff2a63f851a882367ce046806667a41a7ce47f13ba8399a36706055af088de6e1767fc63ef8f2dd5d6191b1f3b96da8ad2589ecdc417dccf722cfcc891d80b0ca52fd2e5bf9e5b33efc696fc1071275b9c0834b3434486dbaac9a7404ae3dd36da3b8b9b2431eab23685799ac557b3cf129ed07f4ec72a17db587e070a8b7ca9781aecee3465c04d4eba1ac831481d6ce0bb06b37b015731de22163363a05c39a9e7f7ca1c938acb5a6d527f0c0f35d683cd7481d2a7f6613cafaca389d3e1875e2e988744119fd6c6fd1404dbf3f68cea2d9bfcce9a8726b52489143b36f16ffc912108717eae5de0bd781b8413db194bbb6a6af3963dd31ae3a7249e76e74e0692220b7c9b2c1314ca412b6c9a93a7552f1a11de9ba301ec73c3f9c3790c180c661c989b75deb084eaa1ae7a4f02a16fff70f784c3aca43e17fee2d882ca111fc0c52f5fa0cedd8a9527f782320b813a05d0ddd73ade28e9950aa308d6e20484008a61a0e96f8462b57b1a408b042243fc00047c4d6e4ae053e2fd10224aaae04e1777a8eb4dadf3d99d69b07c4b0e32e90c02531d20b36e6145561ba948ad18e52f16be631673df777c45d83f7b2d090cc2c4603149641a57b3238268b4a39bc3ea5f71d86e0b34c78668430c5f9ec9c88daca11ca0220f0b27bceb822de5e0ddf0a461f588152fdef515958441ca8d969078a3dd9057d81cd0973f4e31aaf4475046e1ce748db41e596224f907237377adb26d80d57d4d5777fdf9e29fbab3e1f771e390787f1900022691327068947890ddaa0df461978e662a3d5f6f5523422528273cd5c782fc26bd91981cc93fdce6f23699be7a9e463d7b9d5cd1d1aabdfd295373af51e1605c6d049e3530d858cb1a6e0e1d3c69a6ddd0de9eec40b6ce952db2f