From: Niels Möller Date: Wed, 12 Feb 2025 18:33:47 +0000 (+0100) Subject: Implement fors, part of slh-dsa. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2dacb72b1dff6897ea8554b33b7f295ff97dfc6e;p=thirdparty%2Fnettle.git Implement fors, part of slh-dsa. --- diff --git a/ChangeLog b/ChangeLog index 542255e5..b897d5e5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,9 +9,11 @@ * slh-dsa-internal.h (struct slh_merkle_ctx_public) (struct slh_merkle_ctx_secret): New structs. (merkle_leaf_hash_func, merkle_node_hash_func): New typedefs. - * Makefile.in (hogweed_SOURCES): Add slh-merkle.c, slh-shake.c and - slh-xmss.c. - * testsuite/slh-dsa-test.c: Add xmss and merkle tests. + * slh-fors.c (_fors_gen, fors_leaf, fors_node, _fors_sign) + (_fors_verify): New file, new functions. + * Makefile.in (hogweed_SOURCES): Add slh-fors.c, slh-merkle.c, + slh-shake.c and slh-xmss.c. + * testsuite/slh-dsa-test.c: Add merkle, xmss and fors tests. 2025-02-11 Niels Möller diff --git a/Makefile.in b/Makefile.in index f38a5779..fad3ee31 100644 --- a/Makefile.in +++ b/Makefile.in @@ -227,7 +227,7 @@ hogweed_SOURCES = sexp.c sexp-format.c \ ed25519-sha512-sign.c ed25519-sha512-verify.c \ ed448-shake256.c ed448-shake256-pubkey.c \ ed448-shake256-sign.c ed448-shake256-verify.c \ - slh-merkle.c slh-shake.c slh-wots.c slh-xmss.c + slh-fors.c slh-merkle.c slh-shake.c slh-wots.c slh-xmss.c OPT_SOURCES = fat-arm.c fat-arm64.c fat-ppc.c fat-s390x.c fat-x86_64.c mini-gmp.c diff --git a/slh-dsa-internal.h b/slh-dsa-internal.h index 862155a9..d6a06edc 100644 --- a/slh-dsa-internal.h +++ b/slh-dsa-internal.h @@ -43,6 +43,9 @@ #define _merkle_root _nettle_merkle_root #define _merkle_sign _nettle_merkle_sign #define _merkle_verify _nettle_merkle_verify +#define _fors_gen _nettle_fors_gen +#define _fors_sign _nettle_fors_sign +#define _fors_verify _nettle_fors_verify #define _xmss_gen _nettle_xmss_gen #define _xmss_sign _nettle_xmss_sign #define _xmss_verify _nettle_xmss_verify @@ -144,6 +147,29 @@ void _merkle_verify (const struct slh_merkle_ctx_public *ctx, merkle_node_hash_func *node_hash, unsigned height, unsigned idx, const uint8_t *signature, uint8_t *hash); +/* Use k Merkle trees, each of size 2^a. Signs messages of size + k * a = 168 bits or 21 octets. */ +#define FORS_A 12 +#define FORS_K 14 + +#define FORS_MSG_SIZE 21 +/* 2912 bytes */ +#define FORS_SIGNATURE_SIZE (FORS_K * (FORS_A + 1) * _SLH_DSA_128_SIZE) + +/* Generates a single secret value, and corresponding leaf hash. */ +void +_fors_gen (const struct slh_merkle_ctx_secret *ctx, unsigned index, uint8_t *sk, uint8_t *leaf); + +/* Computes a fors signature as well as the public key. */ +void +_fors_sign (const struct slh_merkle_ctx_secret *fors_ctx, + const uint8_t *msg, uint8_t *signature, uint8_t *pub); + +/* Computes candidate public key from signature. */ +void +_fors_verify (const struct slh_merkle_ctx_public *ctx, + const uint8_t *msg, const uint8_t *signature, uint8_t *pub); + #define XMSS_H 9 /* Just the auth path, excluding the wots signature, 144 bytes. */ #define XMSS_AUTH_SIZE (XMSS_H * _SLH_DSA_128_SIZE) diff --git a/slh-fors.c b/slh-fors.c new file mode 100644 index 00000000..27a31a82 --- /dev/null +++ b/slh-fors.c @@ -0,0 +1,178 @@ +/* slh-fors.c + + Forest of Random Subsets, part of SLH-DSA (FIPS 205) + + Copyright (C) 2025 Niels Möller + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "bswap-internal.h" +#include "sha3.h" +#include "slh-dsa-internal.h" + +void +_fors_gen (const struct slh_merkle_ctx_secret *ctx, + unsigned idx, uint8_t *sk, uint8_t *leaf) +{ + struct slh_address_hash ah = + { + bswap32_if_le (SLH_FORS_PRF), + bswap32_if_le (ctx->pub.keypair), + 0, + bswap32_if_le(idx), + }; + assert (idx < (FORS_K << FORS_A)); + + _slh_shake (ctx->pub.seed, &ctx->pub.at, &ah, ctx->secret_seed, sk); + + ah.type = bswap32_if_le (SLH_FORS_TREE); + _slh_shake (ctx->pub.seed, &ctx->pub.at, &ah, sk, leaf); +} + +static void +fors_leaf (const struct slh_merkle_ctx_secret *ctx, unsigned idx, uint8_t *out) +{ + _fors_gen (ctx, idx, out, out); +} + +static void +fors_node (const struct slh_merkle_ctx_public *ctx, unsigned height, unsigned index, + const uint8_t *left, const uint8_t *right, uint8_t *out) +{ + struct sha3_256_ctx sha3; + struct slh_address_hash ah = + { + bswap32_if_le (SLH_FORS_TREE), + bswap32_if_le (ctx->keypair), + bswap32_if_le (height), + bswap32_if_le (index), + }; + _slh_shake_init (&sha3, ctx->seed, &ctx->at, &ah); + sha3_256_update (&sha3, _SLH_DSA_128_SIZE, left); + sha3_256_update (&sha3, _SLH_DSA_128_SIZE, right); + sha3_256_shake (&sha3, _SLH_DSA_128_SIZE, out); +} + +static void +fors_sign_one (const struct slh_merkle_ctx_secret *ctx, + unsigned idx, uint8_t *signature, struct sha3_256_ctx *pub) +{ + uint8_t hash[_SLH_DSA_128_SIZE]; + assert (idx < (FORS_K << FORS_A)); + + _fors_gen (ctx, idx, signature, hash); + + _merkle_sign (ctx, fors_leaf, fors_node, FORS_A, idx, + signature + _SLH_DSA_128_SIZE); + _merkle_verify (&ctx->pub, fors_node, FORS_A, idx, signature + _SLH_DSA_128_SIZE, hash); + + sha3_256_update (pub, _SLH_DSA_128_SIZE, hash); +} + +void +_fors_sign (const struct slh_merkle_ctx_secret *ctx, + const uint8_t *msg, uint8_t *signature, uint8_t *pub) +{ + struct slh_address_hash ah = + { + bswap32_if_le(SLH_FORS_ROOTS), + bswap32_if_le(ctx->pub.keypair), + 0, 0, + }; + struct sha3_256_ctx sha3; + unsigned i; + + assert (FORS_A == 12); /* Specialized code */ + + _slh_shake_init (&sha3, ctx->pub.seed, &ctx->pub.at, &ah); + + for (i = 0; i < FORS_K; i += 2, msg += 3, signature += 2*(FORS_A + 1) * _SLH_DSA_128_SIZE) + { + unsigned m0 = ((unsigned) msg[0] << 4) + (msg[1] >> 4); + unsigned m1 = ((msg[1] & 0xf) << 8) + msg[2]; + fors_sign_one (ctx, (i << FORS_A) + m0, signature, &sha3); + fors_sign_one (ctx,((i+1) << FORS_A) + m1, + signature + (FORS_A + 1) * _SLH_DSA_128_SIZE, &sha3); + } + + sha3_256_shake (&sha3, _SLH_DSA_128_SIZE, pub); +} + +static void +fors_verify_one (const struct slh_merkle_ctx_public *ctx, + unsigned idx, const uint8_t *signature, struct sha3_256_ctx *pub) +{ + uint8_t root[_SLH_DSA_128_SIZE]; + struct slh_address_hash ah = + { + bswap32_if_le (SLH_FORS_TREE), + bswap32_if_le (ctx->keypair), + 0, + bswap32_if_le(idx), + }; + assert (idx < (FORS_K << FORS_A)); + + _slh_shake (ctx->seed, &ctx->at, &ah, signature, root); + _merkle_verify (ctx, fors_node, FORS_A, idx, signature + _SLH_DSA_128_SIZE, root); + + sha3_256_update (pub, _SLH_DSA_128_SIZE, root); +} + +void +_fors_verify (const struct slh_merkle_ctx_public *ctx, + const uint8_t *msg, const uint8_t *signature, uint8_t *pub) +{ + struct sha3_256_ctx sha3; + unsigned i; + struct slh_address_hash ah = + { + bswap32_if_le (SLH_FORS_ROOTS), + bswap32_if_le (ctx->keypair), + 0, 0, + }; + + assert (FORS_A == 12); /* Specialized code */ + + _slh_shake_init (&sha3, ctx->seed, &ctx->at, &ah); + + for (i = 0; i < FORS_K; i += 2, msg += 3, signature += 2*(FORS_A + 1) * _SLH_DSA_128_SIZE) + { + unsigned m0 = ((unsigned) msg[0] << 4) + (msg[1] >> 4); + unsigned m1 = ((msg[1] & 0xf) << 8) + msg[2]; + fors_verify_one (ctx, (i << FORS_A) + m0, signature, &sha3); + fors_verify_one (ctx, ((i+1) << FORS_A) + m1, + signature + (FORS_A + 1) * _SLH_DSA_128_SIZE, &sha3); + } + sha3_256_shake (&sha3, _SLH_DSA_128_SIZE, pub); +} diff --git a/testsuite/slh-dsa-test.c b/testsuite/slh-dsa-test.c index 3c00878b..7a2064b5 100644 --- a/testsuite/slh-dsa-test.c +++ b/testsuite/slh-dsa-test.c @@ -136,6 +136,63 @@ test_merkle (const struct tstring *public_seed, const struct tstring *secret_see ASSERT (MEMEQ(sizeof(pub), pub, exp_pub->data)); } +static void +test_fors_gen(const struct tstring *public_seed, const struct tstring *secret_seed, + unsigned layer, uint64_t tree_idx, unsigned keypair, unsigned idx, + const struct tstring *exp_sk, const struct tstring *exp_leaf) +{ + struct slh_merkle_ctx_secret ctx = + { + { + public_seed->data, + { bswap32_if_le(layer), 0, bswap64_if_le(tree_idx) }, + keypair, + }, + secret_seed->data, + }; + uint8_t sk[_SLH_DSA_128_SIZE]; + uint8_t leaf[_SLH_DSA_128_SIZE]; + ASSERT (public_seed->length == _SLH_DSA_128_SIZE); + ASSERT (secret_seed->length == _SLH_DSA_128_SIZE); + ASSERT (exp_sk->length == _SLH_DSA_128_SIZE); + ASSERT (exp_leaf->length == _SLH_DSA_128_SIZE); + + _fors_gen (&ctx, idx, sk, leaf); + ASSERT (MEMEQ(sizeof(sk), sk, exp_sk->data)); + ASSERT (MEMEQ(sizeof(leaf), leaf, exp_leaf->data)); +} + +static void +test_fors_sign (const struct tstring *public_seed, const struct tstring *secret_seed, + unsigned layer, uint64_t tree_idx, unsigned keypair, const struct tstring *msg, + const struct tstring *exp_pub, const struct tstring *exp_sig) +{ + struct slh_merkle_ctx_secret ctx = + { + { + public_seed->data, + { bswap32_if_le(layer), 0, bswap64_if_le(tree_idx) }, + keypair, + }, + secret_seed->data, + }; + uint8_t pub[_SLH_DSA_128_SIZE]; + uint8_t sig[FORS_SIGNATURE_SIZE]; + ASSERT (public_seed->length == _SLH_DSA_128_SIZE); + ASSERT (secret_seed->length == _SLH_DSA_128_SIZE); + ASSERT (msg->length == FORS_MSG_SIZE); + ASSERT (exp_pub->length == _SLH_DSA_128_SIZE); + ASSERT (exp_sig->length == FORS_SIGNATURE_SIZE); + + _fors_sign (&ctx, msg->data, sig, pub); + ASSERT (MEMEQ(sizeof(sig), sig, exp_sig->data)); + ASSERT (MEMEQ(sizeof(pub), pub, exp_pub->data)); + + memset (pub, 0, sizeof(pub)); + _fors_verify (&ctx.pub, msg->data, sig, pub); + ASSERT (MEMEQ(sizeof(pub), pub, exp_pub->data)); +} + static void test_xmss_gen(const struct tstring *public_seed, const struct tstring *secret_seed, const struct tstring *exp_pub) @@ -229,6 +286,113 @@ test_main(void) "a467897bbed0d3a0 9d50e9deaadff78d e9ac65c1fd05d076 10a79c8c465141ad" "65e60340531fab08 f1f433ef823283fe")); + test_fors_gen (public_seed, secret_seed, 0, UINT64_C(0x29877722d7c079), 0x156, 0x203, + SHEX("1ba66d6f782bdd2485589ea15d2b8ff0"), + SHEX("4d9783fd544a53ee7a485ef229b35965")); + test_fors_gen (public_seed, secret_seed, 0, UINT64_C(0x29877722d7c079), 0x156, 0, + SHEX("be19da5abd01818bbcae2fc2d728c83b"), + SHEX("40b0edc79104214adda356341b3950ab")); + test_fors_gen (public_seed, secret_seed, 0, UINT64_C(0x29877722d7c079), 0x156, 1, + SHEX("ed98099d2fd9d94ac48cae4c142a4c78"), + SHEX("64fccb8a3cf088faeb39353aad5f624c")); + test_fors_gen (public_seed, secret_seed, 0, UINT64_C(0x29877722d7c079), 0x156, 0x4e1e, + SHEX("17f55905e41a6dc6e5bab2c9f0c1d5d3"), + SHEX("15325ef3d2914cbd401327244cdb633d")); + test_fors_sign (public_seed, secret_seed, 0, UINT64_C(0x29877722d7c079), 0x156, + SHEX("2033c1a4df6fc230c699522a21bed913" + "0dda231526"), + SHEX("3961b2cab15e08c633be827744a07f01"), + SHEX("1ba66d6f782bdd24 85589ea15d2b8ff0 a00c06eaedc8c22d cb86f3df8b52a3bd" + "144d4ed6f1167431 a95dc6018879b6b0 f9813797204ec2b0 558bad17b32e6dd9" + "88086a032c0acbcf 2c1349ffc16c4af7 59365ff74afe4b8d c3fac5b2cda7ba65" + "6c36c086e58468c0 1eddfc959fbdc853 2d75e79cf3374756 cc0491cfef555921" + "ec8567bff0b6f216 ac4a4f200da63b5c 6d3a5c3273aa7a42 66adf083d3126103" + "c73fe63a6e05e47e 8b9a520f00f32a69 7d0ff3a5ee840931 3773188f300b39e5" + "b4967febf77c0f23 226785ee9dce335c efb1ce84b0673058 1bcef4d45f24aee4" + "96a60bd4759b7b20 692241850eae1de7 0c7c4287b9f3b962 a66e0f23d1301b84" + "48bb3dc545be0ef8 d0ec0be045d33ae4 b2dc0c5d002c2699 e8f49bf3bcb13676" + "beefe11186a20a95 7027ac48ee6dd33b c0895df9847fd1c6 7a753777d21ac464" + "2751139061cca836 99822c13567833b9 41fe5954bff0969a 4b20e0829d77e24e" + "d0e02a00a2ce9f7e 64923fa61f0da1af dc5978dc063afeac b7108ee08aaa55b7" + "11df00bbf1c71d69 8b389e6ad0ee2af4 fad1d8f8c87d53ee ac1f82a162a95cd5" + "cce6dfc9908a1de3 3a2b26b41bbc4ffd a8e136879f10341a 713d62c107f3238c" + "38693aff2e1fe15a dd8380671b2fac8f db3a4ffacd143f5a 00e21caccbe7d95d" + "4c31c4daf7110529 de599fb6e8aa4f71 8c6172f4f10c4c1d d7310f8e44d18fb9" + "bb6b906ae7ce973d eadfc82d6704762e d61165f6ca118313 4b6c834bf6b4e4ce" + "19700bb54fb2d0f2 82b11ee5b7f68c72 cf32ff9e7d1356bd 53fdcce0d03c43d0" + "ebf6f7d8841a16dd b49944d01374ecb9 45e6c5f0659d5f51 de0b27a834e2e7be" + "a78a609da75d7f2c 6a40ba9110a2c331 9db7775bf6226b9a 8e324dc4411824a8" + "8db95cc2fd96e4bc 24f1ecb6ce2b9293 020c28deacec1eb3 313d4e3dfd24b403" + "686f16272cac3aca 95080257071a54f7 45ffb4708ff2d02d e94d7e9bf8d45f64" + "5917c7135d6bc0a1 ca0a99bc4e33a689 07aa65a58b586c56 e1d81af6cb57fa5d" + "56b3567687ecef53 2bb5aaaf2041b510 1538294296ae4c11 89a5100eb19b5531" + "2016c575cbbb688f 20ba186dd48e4161 64c29b2eb7b59979 814b5a8e76553997" + "99bf79eeab3ee76d 4c97df282265564f 2fa8971a1ecca0c4 6b59cc6ba253531c" + "17ab7125cf2aad60 a120c7d4b631b1ba f187182c7d7582da 3232251215ffd6a2" + "a55c627ba8d5cafe 761504d8341f293e 713987d6e0ca2eab 373c5131c2d38051" + "c35b17918937b9fe e98382c277640de0 ccec45ba22d9d189 eea505a21c8594dd" + "9b12e69a7faf58ed 269b718abeea4621 391d7fb4c6e0037b daf4a9ac73191674" + "9e2a17d704cf5616 8d97c17b257e2483 16aa9da15d822ee3 c325bc0519173641" + "7007ea82088618d7 531ffcef255b2de2 bf9fcaeb29d83e56 7a08dd3d3c229209" + "af96ba71d8274fda e324702878d99ac0 5e990e0d6f34c879 d19279f57541f294" + "96645cad4a636793 385b0a5dc21d5659 37fc36384dea4beb b5746c10748efcbd" + "6b1925a74e3ac467 d7af456e0ba1e47a 2fab24e8311c14d8 40b499c9140e99a4" + "993379b9b762b3ad c9499d5c86d07bc6 a159876a9962d8a4 43514e812f75c60d" + "c50028388c627329 6e7208a3fa618256 2d10d7142a99da06 86ef8f05e564446c" + "6bb32ffdee9edd13 aee58027d29e7195 48b67d75efe9581a 3374c66f65a1cd9e" + "f9e98e6b57c40321 2739df6fd2de6c8a 39decc7cd33e37db 3a0f43296cb987e8" + "756d4b29dc227733 bdee1d2f01679dab 92ce506e2fc77a70 798787b2e95be8e9" + "bf80d0b64af8eaa6 ceda80fe85a0ceaf 81f335b99a1899a3 d9d609e7ba606eb2" + "ababf2bbce1bc8f9 9eaf6074cf1c7e07 9896eb09827c16d0 cd4833377c46a337" + "a7950b31b6566624 02e8ba838668a315 ac531315a9a56af1 8729ee25f53711c0" + "9d25c173aa0e4d2b ec72db4b9cb4210d 52a8fb2f8b2671b1 ec711a4da8a357df" + "bb0d2ec9734a50e1 db92352ace0f26f5 0cfb76fd17a08dec bb19c2417a9dc719" + "f2ecac4a8e7c4827 5533def5c08788dc 4b47ec81960b25a5 7dba2762f5a07003" + "7c50a4883fe902eb cb1574998dd5e8b1 e34ea5aea20bbbef fdb5d6163688e4e1" + "bdc9619f12b78d20 e8c073f81da8bbe4 8bde8934bc7186da 9d29d1f670a322bf" + "9febca92915e393c 1878895c04b8c365 e4d399ac551a55c5 4264e3fc6176cbcd" + "101790863cdab395 74a4dd5c9edd69a0 1df20a10e5abff31 b4e204f5cf7e1dc9" + "a27626ec3bf06d28 fad08c10674830d7 abc54772d95ace66 765757340007a353" + "63d270f410a6bcf2 0f2ca54dfdb00d9b e8fa7ea5b79bf818 2f16b95f9850ce4c" + "acff1e66bec202b5 7b85b37cdd2c3900 1d2950666368afa2 1de5ce68f54833a8" + "8da17b49c4e66243 560ec61a6efd5d3a 2966a76df2dc08c4 e5f02f8b8cd71b90" + "4ddd4bfd73a5c848 9b7eb813ca3da6b8 dbea536354e01428 dd6dc42db23257a2" + "0e322f685bb82b20 f0edc48351c22b75 e0aa8adc567f172e 654360e094c19754" + "2f39965bd9004621 c9ee3297870ed818 f980a71ec4a8f818 1e9be5be1ef6a660" + "cbf68637e54b5afa bbc5f9dc61933014 cb52b4d2624a24ac a3c6f5ca80dd5aee" + "93d0155af703c0ac a4a9266cd9b56f3f 152fc4fca8e7dce3 21a188682fb36e6f" + "7a736fd4e9972a9f 71f11d50c351551e 3c455f1b051befcb c1fd83239b748951" + "f7e18c2027627339 712df2772dcd57de 9a15f218e25a4493 ce20d039e2880881" + "69445f244f14d56e 6efe9ed005094333 1a4ef297119cf5c0 e21e2bbc535daebf" + "3fce3caf9d86b62c 37a4c9bd8991b8ff 01e992f26a77e987 ca8ddf6cf47d47d5" + "439eb6622b241172 a8d5a251dcb5d4d2 26a68bef9d2e77df e4db3ebd4342f49b" + "ee82b28fc35063e9 36589f86f8ff2db0 f2a7fcbf0d461484 184f64bf18e5bff6" + "84545e6112f87662 60987bcfe76bed5a 17dfb88a9b7d7cac cb4283afb4ee21ef" + "b43d698c413de813 48309bc1ec10cdb3 3a7e2e4aaed41cfe bf808b08e7f64f8f" + "6f250960375c3a3e d0617000ac6e54a6 12727861daf4d893 7ae133a5e99c607e" + "09e8097f876ef8cd 75e244b78eaabf83 1db9efd0ba405b52 715825974579a627" + "9f7775ab87de6e26 9979530e3fff6d8f f6421ab3ba1ec61b 9ebc1a2a7aa59002" + "ac916c26f55bc369 b2e11030f3346548 28285930228ad081 2500c822bd41ead4" + "80b530331f8642f2 6d5454fe75cc3870 d807ef92496b27e0 45b3317f10e98533" + "59875ec041117f3b b37d88c526ef1a34 2b6ea289fa69bc91 4d8fef84a27329f3" + "0a7326c84710f972 5432a525f3bf9af3 d93f9faded5766f9 067a5b1b7a0dac92" + "75207b6776c404b1 7801a7372666f153 78cdf91bb4c29d6a cf79eed16918947c" + "769283e829ec1e97 cb90630473224d88 95f2a0219d309507 173f42594372696f" + "6ef8468b843d4ad5 81ad78c221bbb877 0ca2323858016dc6 f9c311bd451a5b68" + "ce23c6feb8c1f543 82a8512d286e6bd5 62ada1c6c8c7c46d 7a9722d7a909b7cc" + "fce3258bb37b78c0 d076e4bb587bfe05 95257c988543edeb d2f24f9e124dd0e3" + "35ea2add17201df7 f2e68fbcc02da7d4 3b7a9a8f83de7375 be2c61b4c2b872bb" + "de25ea659a59b1a6 3cbc9c5efb6c449d 9818245291c6c232 17ae6cb018cdf7a9" + "a49240f37a484361 b450ba8fccedd4f4 556ca8423fd1e907 6a876306958ee264" + "4646633c2777280a c7a82e441d79b556 c629d7c97b4c7895 4bae0e76cb4ab1b2" + "0b51126ac8f125e2 f01c266df31b2ae6 d50eb02f96b39044 81a32254799bc233" + "88f7d86b6b60876d 20cf9e8a4468fb3e be4883fb90765a50 5d6ae99827a0ff96" + "d5eb284ac7df815c 0fd5aa2bdffa560b dc37beb9a7a6a4e3 fc074a9f812132a8" + "6be3a1f73433a198 0a168bbe54910ff5 95a47b6747f43a67 8fe5a7c96e636b4b" + "874f348d24b79337 db4315cb10fd0e56 2431511c323353cf 1e59fd5a55357e5f" + "6b7cce60f1f8211f d1f5be68f7c8bd70 c29f03c0a6613c64 dd10a65db5e0c546" + "f5382403ff8ba36b ad49879231912a4b 219a08a19858b12c 2744fd65603775b5" + "6bf4459512e79188 92da55f87d7cc02c 6885c0ec02550b60 9e3fa7d9fb0d13ab")); test_xmss_gen (public_seed, secret_seed, SHEX("ac524902fc81f503 2bc27b17d9261ebd"));