From 4df06e71966e4bd8b263bbcf3d4fc79d1f1f3b5e Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Sat, 10 Jan 2026 23:30:00 +0800 Subject: [PATCH] Update SPHINCS+ --- include/gmssl/sphincs.h | 186 ++++++-- src/sphincs.c | 989 +++++++++++++++++++++++++++++----------- tests/sphincstest.c | 369 ++++++++++++++- 3 files changed, 1220 insertions(+), 324 deletions(-) diff --git a/include/gmssl/sphincs.h b/include/gmssl/sphincs.h index dc774fd8..8a0ddc16 100644 --- a/include/gmssl/sphincs.h +++ b/include/gmssl/sphincs.h @@ -133,6 +133,8 @@ void sphincs_adrs_set_hash_address(sphincs_adrs_t adrs, const uint32_t address); void sphincs_adrs_set_tree_height(sphincs_adrs_t adrs, uint32_t height); void sphincs_adrs_set_tree_index(sphincs_adrs_t adrs, uint32_t index); +int sphincs_adrs_print(FILE *fp, int fmt, int ind, const char *label, const sphincs_adrs_t adrs); + typedef struct { uint8_t layer_address; uint64_t tree_address; @@ -160,43 +162,37 @@ typedef struct { size_t siglen; } SPHINCS_PARAMS; -// sizeof(sphincs_secret_t) == n, when sm3/sha256, n == 16 -typedef uint8_t sphincs_secret_t[16]; +// sizeof(sphincs_hash128_t) == n, when sm3/sha256, n == 16 +typedef uint8_t sphincs_hash128_t[16]; -typedef sphincs_secret_t sphincs_wots_key_t[35]; -typedef sphincs_secret_t sphincs_wots_sig_t[35]; + + +#define SPHINCS_WOTS_NUM_CHAINS 35 + +typedef sphincs_hash128_t sphincs_wots_key_t[35]; +typedef sphincs_hash128_t sphincs_wots_sig_t[35]; int sphincs_wots_key_print(FILE *fp, int fmt, int ind, const char *label, const sphincs_wots_key_t key); int sphincs_wots_sig_print(FILE *fp, int fmt, int ind, const char *label, const sphincs_wots_sig_t sig); -void sphincs_wots_derive_sk(const sphincs_secret_t secret, - const sphincs_secret_t seed, const sphincs_adrs_t in_adrs, +void sphincs_wots_derive_sk(const sphincs_hash128_t secret, + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, sphincs_wots_key_t sk); -void sphincs_wots_chain(const sphincs_secret_t x, - const sphincs_secret_t seed, const sphincs_adrs_t ots_adrs, - int start, int steps, sphincs_secret_t y); +void sphincs_wots_chain(const sphincs_hash128_t x, + const sphincs_hash128_t seed, const sphincs_adrs_t ots_adrs, + int start, int steps, sphincs_hash128_t y); void sphincs_wots_sk_to_pk(const sphincs_wots_key_t sk, - const sphincs_secret_t seed, const sphincs_adrs_t ots_adrs, + const sphincs_hash128_t seed, const sphincs_adrs_t ots_adrs, sphincs_wots_key_t pk); -void sphincs_wots_pk_to_root(const sphincs_wots_key_t pk, - const sphincs_secret_t seed, const sphincs_adrs_t in_adrs, - sphincs_secret_t root); -void sphincs_base_w_and_checksum(const sphincs_secret_t dgst, int steps[35]); void sphincs_wots_sign(const sphincs_wots_key_t sk, - const sphincs_secret_t seed, const sphincs_adrs_t ots_adrs, - const sphincs_secret_t dgst, sphincs_wots_sig_t sig); + const sphincs_hash128_t seed, const sphincs_adrs_t ots_adrs, + const sphincs_hash128_t dgst, sphincs_wots_sig_t sig); void sphincs_wots_sig_to_pk(const sphincs_wots_sig_t sig, - const sphincs_secret_t seed, const sphincs_adrs_t ots_adrs, - const sphincs_secret_t dgst, sphincs_wots_key_t pk); - - - - -typedef struct { - uint32_t index; - sphincs_wots_sig_t wots_sig; - sphincs_secret_t auth_path[22]; // sphincs+_128f height = 22 -} SPHINCS_XMSS_SIGNATURE; + const sphincs_hash128_t seed, const sphincs_adrs_t ots_adrs, + const sphincs_hash128_t dgst, sphincs_wots_key_t pk); +void sphincs_wots_pk_to_root(const sphincs_wots_key_t pk, + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, + sphincs_hash128_t root); #if 1 // SPHINCS+_128s @@ -212,16 +208,138 @@ typedef struct { # define SPHINCS_FORS_NUM_TREES 33 #endif + + +#define SPHINCS_FORS_TREE_HEIGHT 12 +#define SPHINCS_FORS_TREE_NUM_NODES ((1 << (SPHINCS_FORS_TREE_HEIGHT + 1)) - 1) + + +#define SPHINCS_FORS_NUM_NODES (SPHINCS_FORS_TREE_NUM_NODES * SPHINCS_FORS_NUM_TRESS + 1) + + + + + +// FORS (Forest Of Random Subsets) + +// fors_tree +// fors_tree_height +// fors_tree_root +// fors_forest +// fors_num_trees +// fors_root + #define SPHINCS_XMSS_HEIGHT (SPHINCS_HYPERTREE_HEIGHT/SPHINCS_HYPERTREE_LAYERS) +#define SPHINCS_XMSS_NUM_NODES ((1 << (SPHINCS_XMSS_HEIGHT + 1)) - 1) + + + +/* + + SPHINCS+_128s/SM3 + + + H_msg(R, PK.seed, PK.root, M) + = MGF1-SM3(R + ||PK.seed + ||SM3(R||PK.seed||PK.root||M), + m), + + + 1. fors_index: 12 * 14 = 168 bits = 21 bytes + 2. tree_index: 63 - 63/7 = 54 bits = 7 bytes + 3. leaf_index: 9 bits = 2 bytes + total: 30 bytes, 1 MGF1-SM3 output + + + + SPHINCS+_128f/SM3 + + 1. fors_index: 6 * 33 = 198 bits = 25 bytes + 2. tree_address: 66 - 66/22 = 63 bits = 8 bytes + 3. keypair_address (leaf_index): 3 bits = 1 byte + total: 34 bytes, so need 2 MGF1-SM3 output + +*/ + + + +void sphincs_xmss_tree_hash( + const sphincs_hash128_t left_child, const sphincs_hash128_t right_child, + const sphincs_hash128_t seed, const sphincs_adrs_t adrs, + hash256_t parent); +void sphincs_xmss_build_tree(const sphincs_hash128_t secret, + const sphincs_hash128_t seed, const sphincs_adrs_t adrs, + sphincs_hash128_t tree[SPHINCS_XMSS_NUM_NODES]); +void sphincs_xmss_build_auth_path(const sphincs_hash128_t tree[SPHINCS_XMSS_NUM_NODES], + uint32_t tree_index, sphincs_hash128_t auth_path[SPHINCS_XMSS_HEIGHT]); +void sphincs_xmss_build_root(const sphincs_hash128_t wots_root, uint32_t tree_index, + const sphincs_hash128_t seed, const sphincs_adrs_t adrs, + const sphincs_hash128_t auth_path[SPHINCS_XMSS_HEIGHT], + hash256_t root); + + typedef struct { - sphincs_secret_t fors_sk[SPHINCS_FORS_HEIGHT]; - sphincs_secret_t auth_path[SPHINCS_FORS_NUM_TREES][SPHINCS_FORS_HEIGHT]; + sphincs_wots_sig_t wots_sig; + sphincs_hash128_t auth_path[22]; // sphincs+_128f height = 22 +} SPHINCS_XMSS_SIGNATURE; + +void sphincs_xmss_sign(const sphincs_hash128_t secret, + const sphincs_hash128_t seed, const sphincs_adrs_t adrs, uint32_t keypair_address, + const sphincs_hash128_t tbs_root, // to be signed xmss_root or fors_forest_root + SPHINCS_XMSS_SIGNATURE *sig); +void sphincs_xmss_sig_to_root(const SPHINCS_XMSS_SIGNATURE *sig, + const sphincs_hash128_t seed, const sphincs_adrs_t adrs, uint32_t keypair_address, + const sphincs_hash128_t tbs_root, // to be signed xmss_root or fors_forest_root + sphincs_hash128_t xmss_root); + + +void sphincs_hypertree_derive_root(const sphincs_hash128_t secret, const sphincs_hash128_t seed, + sphincs_hash128_t root); +void sphincs_hypertree_sign(const sphincs_hash128_t secret, + const sphincs_hash128_t seed, uint64_t tree_address, uint32_t keypair_address, + const sphincs_hash128_t tbs_fors_forest_root, + SPHINCS_XMSS_SIGNATURE sig[SPHINCS_HYPERTREE_LAYERS]); +int sphincs_hypertree_verify(const sphincs_hash128_t top_xmss_root, + const sphincs_hash128_t seed, uint64_t tree_address, uint32_t keypair_address, + const sphincs_hash128_t tbs_fors_forest_root, + const SPHINCS_XMSS_SIGNATURE sig[SPHINCS_HYPERTREE_LAYERS]); + + + +typedef uint8_t sphincs_fors_digest_t[21]; + + +void sphincs_fors_derive_sk(const sphincs_hash128_t secret, + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, + uint32_t fors_index, sphincs_hash128_t sk); + +void sphincs_fors_build_tree(const sphincs_hash128_t secret, + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, int tree_addr, + sphincs_hash128_t tree[SPHINCS_FORS_TREE_NUM_NODES]);; +void sphincs_fors_derive_root(const sphincs_hash128_t secret, + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, + sphincs_hash128_t root); + + +typedef struct { + sphincs_hash128_t fors_sk[SPHINCS_FORS_NUM_TREES]; + sphincs_hash128_t auth_path[SPHINCS_FORS_NUM_TREES][SPHINCS_FORS_HEIGHT]; } SPHINCS_FORS_SIGNATURE; +void sphincs_fors_sign(const sphincs_hash128_t secret, + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, + const uint8_t dgst[21], + SPHINCS_FORS_SIGNATURE *sig); +void sphincs_fors_sig_to_root(const SPHINCS_FORS_SIGNATURE *sig, + const sphincs_hash128_t seed, const sphincs_adrs_t adrs, + const uint8_t dgst[21], sphincs_hash128_t root); + + #define SPHINCS_FORS_SIGNATURE_SIZE sizeof(SPHINCS_FORS_SIGNATURE) int sphincs_fors_signature_to_bytes(const SPHINCS_FORS_SIGNATURE *sig, uint8_t **out, size_t *outlen); int sphincs_fors_signature_from_bytes(SPHINCS_FORS_SIGNATURE *sig, const uint8_t **in, size_t *inlen); @@ -230,14 +348,14 @@ int sphincs_fors_signature_print(FILE *fp, int fmt, int ind, const char *label, typedef struct { - sphincs_secret_t seed; - sphincs_secret_t root; + sphincs_hash128_t seed; + sphincs_hash128_t root; } SPHINCS_PUBLIC_KEY; typedef struct { SPHINCS_PUBLIC_KEY public_key; - sphincs_secret_t secret; - sphincs_secret_t sk_prf; + sphincs_hash128_t secret; + sphincs_hash128_t sk_prf; } SPHINCS_KEY; #define SPHINCS_PUBLIC_KEY_SIZE sizeof(SPHINCS_PUBLIC_KEY) @@ -253,7 +371,7 @@ void sphincs_key_cleanup(SPHINCS_KEY *key); typedef struct { - sphincs_secret_t random; + sphincs_hash128_t random; SPHINCS_FORS_SIGNATURE fors_sig; SPHINCS_XMSS_SIGNATURE xmss_sigs[SPHINCS_HYPERTREE_LAYERS]; } SPHINCS_SIGNATURE; diff --git a/src/sphincs.c b/src/sphincs.c index 12cecd2f..8a1c15b3 100644 --- a/src/sphincs.c +++ b/src/sphincs.c @@ -31,8 +31,6 @@ static const SPHINCS_PARAMS sphincs_params[] = { { "SPHINCS+_256f", 32, 68, 17, 9, 35, 16, 255, 5, 49856 }, }; - - void sphincs_adrs_copy_layer_address(sphincs_adrs_t dst, const sphincs_adrs_t src) { memcpy(dst, src, 4); } @@ -117,96 +115,96 @@ int sphincs_adrs_print(FILE *fp, int fmt, int ind, const char *label, const sphi ind += 4; layer_address = GETU32(adrs); - format_print(fp, fmt, ind, "layer_address: %"PRIu32"\n", layer_address); + format_print(fp, fmt, ind, "layer_address : %"PRIu32"\n", layer_address); adrs += 4; tree_address_hi32 = GETU32(adrs); - format_print(fp, fmt, ind, "tree_address : %"PRIu32"\n", tree_address_hi32); + format_print(fp, fmt, ind, "tree_address : %"PRIu32"\n", tree_address_hi32); adrs += 4; tree_address_lo64 = GETU64(adrs); - format_print(fp, fmt, ind, "tree_address : %"PRIu64"\n", tree_address_lo64); + format_print(fp, fmt, ind, "tree_address : %"PRIu64"\n", tree_address_lo64); adrs += 8; type = GETU32(adrs); - format_print(fp, fmt, ind, "type : %"PRIu32"\n", type); + format_print(fp, fmt, ind, "type : %"PRIu32"\n", type); adrs += 4; switch (type) { case SPHINCS_ADRS_TYPE_WOTS_HASH: keypair_address = GETU32(adrs); - format_print(fp, fmt, ind, "keypair_address : %"PRIu32"\n", keypair_address); + format_print(fp, fmt, ind, "keypair_address: %"PRIu32"\n", keypair_address); adrs += 4; chain_address = GETU32(adrs); - format_print(fp, fmt, ind, "chain_address: %"PRIu32"\n", chain_address); + format_print(fp, fmt, ind, "chain_address : %"PRIu32"\n", chain_address); adrs += 4; hash_address = GETU32(adrs); - format_print(fp, fmt, ind, "hash_address : %"PRIu32"\n", hash_address); + format_print(fp, fmt, ind, "hash_address : %"PRIu32"\n", hash_address); adrs += 4; break; case SPHINCS_ADRS_TYPE_WOTS_PK: keypair_address = GETU32(adrs); - format_print(fp, fmt, ind, "keypair_address : %"PRIu32"\n", keypair_address); + format_print(fp, fmt, ind, "keypair_address: %"PRIu32"\n", keypair_address); adrs += 4; padding = GETU32(adrs); - format_print(fp, fmt, ind, "padding : %"PRIu32"\n", padding); + format_print(fp, fmt, ind, "padding : %"PRIu32"\n", padding); adrs += 4; padding = GETU32(adrs); - format_print(fp, fmt, ind, "padding : %"PRIu32"\n", padding); + format_print(fp, fmt, ind, "padding : %"PRIu32"\n", padding); adrs += 4; break; case SPHINCS_ADRS_TYPE_TREE: padding = GETU32(adrs); - format_print(fp, fmt, ind, "padding : %"PRIu32"\n", padding); + format_print(fp, fmt, ind, "padding : %"PRIu32"\n", padding); adrs += 4; tree_height = GETU32(adrs); - format_print(fp, fmt, ind, "tree_height : %"PRIu32"\n", tree_height); + format_print(fp, fmt, ind, "tree_height : %"PRIu32"\n", tree_height); adrs += 4; tree_index = GETU32(adrs); - format_print(fp, fmt, ind, "tree_index : %"PRIu32"\n", tree_index); + format_print(fp, fmt, ind, "tree_index : %"PRIu32"\n", tree_index); adrs += 4; break; case SPHINCS_ADRS_TYPE_FORS_TREE: keypair_address = GETU32(adrs); - format_print(fp, fmt, ind, "keypair_address : %"PRIu32"\n", keypair_address); + format_print(fp, fmt, ind, "keypair_address: %"PRIu32"\n", keypair_address); adrs += 4; tree_height = GETU32(adrs); - format_print(fp, fmt, ind, "tree_height : %"PRIu32"\n", tree_height); + format_print(fp, fmt, ind, "tree_height : %"PRIu32"\n", tree_height); adrs += 4; tree_index = GETU32(adrs); - format_print(fp, fmt, ind, "tree_index : %"PRIu32"\n", tree_index); + format_print(fp, fmt, ind, "tree_index : %"PRIu32"\n", tree_index); adrs += 4; break; break; case SPHINCS_ADRS_TYPE_FORS_ROOTS: keypair_address = GETU32(adrs); - format_print(fp, fmt, ind, "keypair_address : %"PRIu32"\n", keypair_address); + format_print(fp, fmt, ind, "keypair_address: %"PRIu32"\n", keypair_address); adrs += 4; padding = GETU32(adrs); - format_print(fp, fmt, ind, "padding : %"PRIu32"\n", padding); + format_print(fp, fmt, ind, "padding : %"PRIu32"\n", padding); adrs += 4; padding = GETU32(adrs); - format_print(fp, fmt, ind, "padding : %"PRIu32"\n", padding); + format_print(fp, fmt, ind, "padding : %"PRIu32"\n", padding); adrs += 4; break; case SPHINCS_ADRS_TYPE_WOTS_PRF: keypair_address = GETU32(adrs); - format_print(fp, fmt, ind, "keypair_address : %"PRIu32"\n", keypair_address); + format_print(fp, fmt, ind, "keypair_address: %"PRIu32"\n", keypair_address); adrs += 4; chain_address = GETU32(adrs); - format_print(fp, fmt, ind, "chain_address: %"PRIu32"\n", chain_address); + format_print(fp, fmt, ind, "chain_address : %"PRIu32"\n", chain_address); adrs += 4; hash_address = GETU32(adrs); - format_print(fp, fmt, ind, "hash_address : %"PRIu32"\n", hash_address); + format_print(fp, fmt, ind, "hash_address : %"PRIu32"\n", hash_address); adrs += 4; break; case SPHINCS_ADRS_TYPE_FORS_PRF: keypair_address = GETU32(adrs); - format_print(fp, fmt, ind, "keypair_address : %"PRIu32"\n", keypair_address); + format_print(fp, fmt, ind, "keypair_address: %"PRIu32"\n", keypair_address); adrs += 4; tree_height = GETU32(adrs); - format_print(fp, fmt, ind, "tree_height : %"PRIu32"\n", tree_height); + format_print(fp, fmt, ind, "tree_height : %"PRIu32"\n", tree_height); adrs += 4; tree_index = GETU32(adrs); - format_print(fp, fmt, ind, "tree_index : %"PRIu32"\n", tree_index); + format_print(fp, fmt, ind, "tree_index : %"PRIu32"\n", tree_index); adrs += 4; break; default: @@ -245,7 +243,7 @@ int sphincs_wots_key_print(FILE *fp, int fmt, int ind, const char *label, const ind += 4; for (i = 0; i < 35; i++) { format_print(fp, fmt, ind, "%d", i); - format_bytes(fp, fmt, ind, "", key[i], sizeof(sphincs_secret_t)); + format_bytes(fp, fmt, 0, "", key[i], sizeof(sphincs_hash128_t)); } return 1; } @@ -257,13 +255,13 @@ int sphincs_wots_sig_print(FILE *fp, int fmt, int ind, const char *label, const ind += 4; for (i = 0; i < 35; i++) { format_print(fp, fmt, ind, "%d", i); - format_bytes(fp, fmt, ind, "", sig[i], sizeof(sphincs_secret_t)); + format_bytes(fp, fmt, 0, "", sig[i], sizeof(sphincs_hash128_t)); } return 1; } -void sphincs_wots_derive_sk(const sphincs_secret_t secret, - const sphincs_secret_t seed, const sphincs_adrs_t in_adrs, +void sphincs_wots_derive_sk(const sphincs_hash128_t secret, + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, sphincs_wots_key_t sk) { uint8_t block[HASH256_BLOCK_SIZE] = {0}; @@ -273,33 +271,33 @@ void sphincs_wots_derive_sk(const sphincs_secret_t secret, hash256_t dgst; int i; - memcpy(block, seed, sizeof(sphincs_secret_t)); + memcpy(block, seed, sizeof(sphincs_hash128_t)); sphincs_adrs_copy_layer_address(adrs, in_adrs); sphincs_adrs_copy_tree_address(adrs, in_adrs); sphincs_adrs_set_type(adrs, SPHINCS_ADRS_TYPE_WOTS_PRF); + sphincs_adrs_copy_keypair_address(adrs, in_adrs); for (i = 0; i < 35; i++) { sphincs_adrs_set_chain_address(adrs, i); sphincs_adrs_set_hash_address(adrs, 0); sphincs_adrs_compress(adrs, adrsc); - // sk[i] + // sk[i] = prf(secret, adrs) hash256_init(&ctx); hash256_update(&ctx, block, sizeof(block)); hash256_update(&ctx, adrsc, sizeof(adrsc)); - hash256_update(&ctx, secret, sizeof(sphincs_secret_t)); + hash256_update(&ctx, secret, sizeof(sphincs_hash128_t)); hash256_finish(&ctx, dgst); - format_bytes(stderr, 0, 0, "wots_sk[i]", dgst, 32); - - memcpy(sk[i], dgst, sizeof(sphincs_secret_t)); + memcpy(sk[i], dgst, sizeof(sphincs_hash128_t)); } } -void sphincs_wots_chain(const sphincs_secret_t x, - const sphincs_secret_t seed, const sphincs_adrs_t ots_adrs, - int start, int steps, sphincs_secret_t y) +// from fips 205 section 11.2.1, not sphincs+ r3.1 spec +void sphincs_wots_chain(const sphincs_hash128_t x, + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, + int start, int steps, sphincs_hash128_t y) { const uint8_t uint32_zero[4] = {0}; uint8_t block[HASH256_BLOCK_SIZE] = {0}; @@ -309,73 +307,143 @@ void sphincs_wots_chain(const sphincs_secret_t x, hash256_t dgst; int i; - memcpy(block, seed, sizeof(sphincs_secret_t)); + memcpy(block, seed, sizeof(sphincs_hash128_t)); - sphincs_adrs_copy_layer_address(adrs, ots_adrs); - sphincs_adrs_copy_tree_address(adrs, ots_adrs); - sphincs_adrs_copy_type(adrs, ots_adrs); - sphincs_adrs_copy_keypair_address(adrs, ots_adrs); - sphincs_adrs_copy_chain_address(adrs, ots_adrs); + sphincs_adrs_copy_layer_address(adrs, in_adrs); + sphincs_adrs_copy_tree_address(adrs, in_adrs); + sphincs_adrs_copy_type(adrs, in_adrs); + sphincs_adrs_copy_keypair_address(adrs, in_adrs); + sphincs_adrs_copy_chain_address(adrs, in_adrs); - memcpy(y, x, sizeof(sphincs_secret_t)); + memcpy(y, x, sizeof(sphincs_hash128_t)); for (i = 0; i < steps; i++) { sphincs_adrs_set_hash_address(adrs, start + i); sphincs_adrs_compress(adrs, adrsc); - // tmp = tmp xor mgf1(seed||ardsc) - hash256_init(&ctx); - hash256_update(&ctx, seed, sizeof(sphincs_secret_t)); - hash256_update(&ctx, adrsc, sizeof(sphincs_adrsc_t)); - hash256_update(&ctx, uint32_zero, sizeof(uint32_zero)); - hash256_finish(&ctx, dgst); - - gmssl_memxor(y, y, dgst, sizeof(sphincs_secret_t)); - // y = hash256(blockpad(seed) || adrsc || y) hash256_init(&ctx); hash256_update(&ctx, block, sizeof(block)); hash256_update(&ctx, adrsc, sizeof(sphincs_adrsc_t)); - hash256_update(&ctx, y, sizeof(sphincs_secret_t)); + hash256_update(&ctx, y, sizeof(sphincs_hash128_t)); hash256_finish(&ctx, dgst); - memcpy(y, dgst, sizeof(sphincs_secret_t)); + memcpy(y, dgst, sizeof(sphincs_hash128_t)); } } void sphincs_wots_sk_to_pk(const sphincs_wots_key_t sk, - const sphincs_secret_t seed, const sphincs_adrs_t ots_adrs, + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, sphincs_wots_key_t pk) { const int start = 0; const int steps = 16 - 1; sphincs_adrs_t adrs; - int chain; + uint32_t i; - sphincs_adrs_copy_layer_address(adrs, ots_adrs); - sphincs_adrs_copy_tree_address(adrs, ots_adrs); - sphincs_adrs_copy_type(adrs, ots_adrs); - sphincs_adrs_copy_keypair_address(adrs, ots_adrs); + sphincs_adrs_copy_layer_address(adrs, in_adrs); + sphincs_adrs_copy_tree_address(adrs, in_adrs); + sphincs_adrs_set_type(adrs, SPHINCS_ADRS_TYPE_WOTS_HASH); + sphincs_adrs_copy_keypair_address(adrs, in_adrs); - for (chain = 0; chain < 35; chain++) { - sphincs_adrs_set_chain_address(adrs, chain); - sphincs_adrs_set_hash_address(adrs, 0); - sphincs_wots_chain(sk[chain], seed, adrs, start, steps, pk[chain]); + for (i = 0; i < 35; i++) { + sphincs_adrs_set_chain_address(adrs, i); + sphincs_wots_chain(sk[i], seed, adrs, start, steps, pk[i]); + } +} + +static void sphincs_base_w_and_checksum(const sphincs_hash128_t dgst, int steps[35]) +{ + int csum = 0; + int sbits; + int i; + + // seperate 128-bit dgst into 32 4-bit base_w numbers + for (i = 0; i < 16; i++) { + steps[2 * i] = dgst[i] >> 4; + steps[2 * i + 1] = dgst[i] & 0xf; + } + + // compute checksum, maxium is (16 - 1) * 32 = 480, which is 9-bit and 3 base_w number + for (i = 0; i < 32; i++) { + csum += 15 - steps[i]; + } + +#if 0 + uint8_t csum_bytes[2]; + + // encode checksum (3 base_w) into 2-byte array + sbits = (8 - ((3 * 4) % 8)); + csum <<= sbits; + csum_bytes[0] = (csum >> 8) & 0xff; + csum_bytes[1] = csum & 0xff; + + // convert 2-byte array to 3 base_w number + steps[32] = csum_bytes[0] >> 4; + steps[33] = csum_bytes[0] & 0xf; + steps[34] = csum_bytes[1] >> 4; +#else + steps[32] = (csum >> 8) & 0x0f; + steps[33] = (csum >> 4) & 0x0f; + steps[34] = (csum >> 0) & 0x0f; +#endif +} + +void sphincs_wots_sign(const sphincs_wots_key_t sk, + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, + const sphincs_hash128_t dgst, sphincs_wots_sig_t sig) +{ + sphincs_adrs_t adrs; + const int start = 0; + int steps[35]; + uint32_t i; + + sphincs_adrs_copy_layer_address(adrs, in_adrs); + sphincs_adrs_copy_tree_address(adrs, in_adrs); + sphincs_adrs_set_type(adrs, SPHINCS_ADRS_TYPE_WOTS_HASH); + sphincs_adrs_copy_keypair_address(adrs, in_adrs); + + sphincs_base_w_and_checksum(dgst, steps); + + for (i = 0; i < 35; i++) { + sphincs_adrs_set_chain_address(adrs, i); + sphincs_wots_chain(sk[i], seed, adrs, start, steps[i], sig[i]); + } +} + +void sphincs_wots_sig_to_pk(const sphincs_wots_sig_t sig, + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, + const sphincs_hash128_t dgst, sphincs_wots_key_t pk) +{ + sphincs_adrs_t adrs; + int steps[35]; + int i; + + sphincs_adrs_copy_layer_address(adrs, in_adrs); + sphincs_adrs_copy_tree_address(adrs, in_adrs); + sphincs_adrs_set_type(adrs, SPHINCS_ADRS_TYPE_WOTS_HASH); + sphincs_adrs_copy_keypair_address(adrs, in_adrs); + + sphincs_base_w_and_checksum(dgst, steps); + + for (i = 0; i < 35; i++) { + sphincs_adrs_set_chain_address(adrs, i); + sphincs_wots_chain(sig[i], seed, adrs, steps[i], 15 - steps[i], pk[i]); } } void sphincs_wots_pk_to_root(const sphincs_wots_key_t pk, - const sphincs_secret_t seed, const sphincs_adrs_t in_adrs, - sphincs_secret_t root) + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, + sphincs_hash128_t root) { uint8_t block[HASH256_BLOCK_SIZE] = {0}; - sphincs_adrs_t adrs; + sphincs_adrs_t adrs = {0}; sphincs_adrsc_t adrsc; HASH256_CTX ctx; hash256_t dgst; int i; - memcpy(block, seed, sizeof(sphincs_secret_t)); + memcpy(block, seed, sizeof(sphincs_hash128_t)); sphincs_adrs_copy_layer_address(adrs, in_adrs); sphincs_adrs_copy_tree_address(adrs, in_adrs); @@ -386,110 +454,48 @@ void sphincs_wots_pk_to_root(const sphincs_wots_key_t pk, hash256_init(&ctx); hash256_update(&ctx, block, sizeof(block)); hash256_update(&ctx, adrsc, sizeof(adrsc)); - for (i = 0; i < 35; i++) { - hash256_update(&ctx, pk[i], sizeof(sphincs_secret_t)); - } + hash256_update(&ctx, pk[0], sizeof(sphincs_wots_key_t)); hash256_finish(&ctx, dgst); - memcpy(root, dgst, sizeof(sphincs_secret_t)); + memcpy(root, dgst, sizeof(sphincs_hash128_t)); } -void sphincs_base_w_and_checksum(const sphincs_secret_t dgst, int steps[35]) -{ - int csum = 0; - int sbits; - int i; - for (i = 0; i < 16; i++) { - steps[2 * i] = dgst[i] >> 4; - steps[2 * i + 1] = dgst[i] & 0xf; - } - for (i = 0; i < 32; i++) { - csum += 15 - steps[i]; - } - // csum = csum << (8 - ((len_2 * lg(w)) %8)) = (8 - (3*4)%8) = 8 - 4 = 4 - sbits = (8 - ((3 * 4) % 8)); - csum <<= sbits; - // len_2_bytes = ceil((len_2 * lg(w)) / 8) = ceil(12/8) = 2 - uint8_t csum_bytes[2]; - csum_bytes[0] = (csum >> 8) & 0xff; - csum_bytes[1] = csum & 0xff; - steps[32] = csum_bytes[0] >> 4; - steps[33] = csum_bytes[0] & 0xf; - steps[34] = csum_bytes[1] >> 4; -} -void sphincs_wots_sign(const sphincs_wots_key_t sk, - const sphincs_secret_t seed, const sphincs_adrs_t ots_adrs, - const sphincs_secret_t dgst, sphincs_wots_sig_t sig) -{ - sphincs_adrs_t adrs; - const int start = 0; - int steps[35]; - uint32_t i; - sphincs_adrs_copy_layer_address(adrs, ots_adrs); - sphincs_adrs_copy_tree_address(adrs, ots_adrs); - sphincs_adrs_copy_type(adrs, ots_adrs); - sphincs_adrs_copy_keypair_address(adrs, ots_adrs); - - sphincs_base_w_and_checksum(dgst, steps); - - for (i = 0; i < 35; i++) { - sphincs_adrs_set_chain_address(adrs, i); - sphincs_adrs_set_hash_address(adrs, 0); - sphincs_wots_chain(sk[i], seed, adrs, start, steps[i], sig[i]); - } -} - -void sphincs_wots_sig_to_pk(const sphincs_wots_sig_t sig, - const sphincs_secret_t seed, const sphincs_adrs_t ots_adrs, - const sphincs_secret_t dgst, sphincs_wots_key_t pk) -{ - sphincs_adrs_t adrs; - int steps[35]; - int i; - - sphincs_adrs_copy_layer_address(adrs, ots_adrs); - sphincs_adrs_copy_tree_address(adrs, ots_adrs); - sphincs_adrs_copy_type(adrs, ots_adrs); - sphincs_adrs_copy_keypair_address(adrs, ots_adrs); - - sphincs_base_w_and_checksum(dgst, steps); - - for (i = 0; i < 35; i++) { - sphincs_adrs_set_chain_address(adrs, i); - sphincs_wots_chain(sig[i], seed, adrs, steps[i], 15 - steps[i], pk[i]); - } -} - -void sphincs_xmss_tree_hash(const sphincs_secret_t left_child, const sphincs_secret_t right_child, - const sphincs_secret_t seed, const sphincs_adrs_t adrs, +void sphincs_tree_hash(const sphincs_hash128_t left_child, const sphincs_hash128_t right_child, + const sphincs_hash128_t seed, const sphincs_adrs_t adrs, hash256_t parent) { HASH256_CTX ctx; hash256_t dgst; hash256_init(&ctx); - hash256_update(&ctx, seed, sizeof(sphincs_secret_t)); + hash256_update(&ctx, seed, sizeof(sphincs_hash128_t)); hash256_update(&ctx, adrs, sizeof(sphincs_adrs_t)); - hash256_update(&ctx, left_child, sizeof(sphincs_secret_t)); - hash256_update(&ctx, right_child, sizeof(sphincs_secret_t)); + hash256_update(&ctx, left_child, sizeof(sphincs_hash128_t)); + hash256_update(&ctx, right_child, sizeof(sphincs_hash128_t)); hash256_finish(&ctx, dgst); - memcpy(parent, dgst, sizeof(sphincs_secret_t)); + memcpy(parent, dgst, sizeof(sphincs_hash128_t)); } -void sphincs_xmss_build_tree(const sphincs_secret_t secret, - const sphincs_secret_t seed, const sphincs_adrs_t in_adrs, - size_t height, sphincs_secret_t *tree) + + + + + + +void sphincs_xmss_build_tree(const sphincs_hash128_t secret, + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, + sphincs_hash128_t tree[SPHINCS_XMSS_NUM_NODES]) { - sphincs_adrs_t adrs; - sphincs_secret_t *children; - sphincs_secret_t *parents; - size_t n = 1 << height; + sphincs_adrs_t adrs = {0}; + sphincs_hash128_t *children; + sphincs_hash128_t *parents; + size_t n = 1 << SPHINCS_XMSS_HEIGHT; uint32_t h; // as tree_height uint32_t i; // as tree_index @@ -497,134 +503,259 @@ void sphincs_xmss_build_tree(const sphincs_secret_t secret, sphincs_adrs_copy_tree_address(adrs, in_adrs); // derive 2^h wots+ roots as leaves of xmss tree - sphincs_adrs_set_type(adrs, SPHINCS_ADRS_TYPE_WOTS_PRF); for (i = 0; i < n; i++) { + sphincs_wots_key_t wots_key; + sphincs_adrs_set_keypair_address(adrs, i); - //sphincs_wots_derive_root(secret, seed, adrs, tree[i]); + + // type = SPHINCS_ADRS_TYPE_WOTS_PRF + sphincs_wots_derive_sk(secret, seed, adrs, wots_key); + // type = SPHINCS_ADRS_TYPE_WOTS_HASH + sphincs_wots_sk_to_pk(wots_key, seed, adrs, wots_key); + // type = SPHINCS_ADRS_TYPE_WOTS_PK + sphincs_wots_pk_to_root(wots_key, seed, adrs, tree[i]); } - // build xmss tree + // keypair_address == TREE.padding, so reset adrs + memset(adrs, 0, sizeof(adrs)); sphincs_adrs_set_type(adrs, SPHINCS_ADRS_TYPE_TREE); - //sphincs_adrs_set_padding(adrs, 0); + sphincs_adrs_copy_layer_address(adrs, in_adrs); + sphincs_adrs_copy_tree_address(adrs, in_adrs); + // build xmss tree children = tree; parents = tree + n; - for (h = 0; h < height; h++) { + for (h = 0; h < SPHINCS_XMSS_HEIGHT; h++) { sphincs_adrs_set_tree_height(adrs, h + 1); n >>= 1; for (i = 0; i < n; i++) { sphincs_adrs_set_tree_index(adrs, i); - sphincs_xmss_tree_hash(children[2*i], children[2*i + 1], seed, adrs, parents[i]); + sphincs_tree_hash(children[2*i], children[2*i + 1], seed, adrs, parents[i]); } children = parents; parents += n; } } -// auth_path[height] -void sphincs_xmss_build_auth_path(const sphincs_secret_t *tree, size_t height, - uint32_t tree_index, sphincs_secret_t *auth_path) +void sphincs_xmss_build_auth_path(const sphincs_hash128_t tree[SPHINCS_XMSS_NUM_NODES], + uint32_t tree_index, sphincs_hash128_t auth_path[SPHINCS_XMSS_HEIGHT]) { size_t h; - for (h = 0; h < height; h++) { - memcpy(auth_path[h], tree[tree_index ^ 1], sizeof(sphincs_secret_t)); - tree += (1 << (height - h)); + for (h = 0; h < SPHINCS_XMSS_HEIGHT; h++) { + memcpy(auth_path[h], tree[tree_index ^ 1], sizeof(sphincs_hash128_t)); + tree += (1 << (SPHINCS_XMSS_HEIGHT - h)); tree_index >>= 1; } } -void sphincs_xmss_build_root(const sphincs_secret_t wots_root, uint32_t tree_index, - const sphincs_secret_t seed, const sphincs_adrs_t in_adrs, - const sphincs_secret_t *auth_path, size_t height, +void sphincs_xmss_build_root(const sphincs_hash128_t wots_root, uint32_t tree_index, + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, + const sphincs_hash128_t auth_path[SPHINCS_XMSS_HEIGHT], hash256_t root) { - sphincs_adrs_t adrs; + sphincs_adrs_t adrs = {0}; uint32_t h; sphincs_adrs_copy_layer_address(adrs, in_adrs); sphincs_adrs_copy_tree_address(adrs, in_adrs); sphincs_adrs_set_type(adrs, SPHINCS_ADRS_TYPE_TREE); - //sphincs_adrs_set_padding(adrs, 0); - memcpy(root, wots_root, sizeof(sphincs_secret_t)); + memcpy(root, wots_root, sizeof(sphincs_hash128_t)); - - for (h = 0; h < height; h++) { + for (h = 0; h < SPHINCS_XMSS_HEIGHT; h++) { int right_child = tree_index & 1; tree_index >>= 1; sphincs_adrs_set_tree_height(adrs, h + 1); sphincs_adrs_set_tree_index(adrs, tree_index); if (right_child) - sphincs_xmss_tree_hash(auth_path[h], root, seed, adrs, root); - else sphincs_xmss_tree_hash(root, auth_path[h], seed, adrs, root); + sphincs_tree_hash(auth_path[h], root, seed, adrs, root); + else sphincs_tree_hash(root, auth_path[h], seed, adrs, root); + + //format_bytes(stderr, 0, 4, "build_root", root, 16); } } -// TODO: index or tree_index? -void sphincs_xmss_sign(const sphincs_secret_t secret, uint32_t index, - const sphincs_secret_t seed, const sphincs_adrs_t in_adrs, - const sphincs_secret_t dgst, SPHINCS_XMSS_SIGNATURE *sig) +// in sphincs+, xmss sign the lower layer xmss_root or the fors_forest_root +// TODO: tree_index or keypair_address? + +void sphincs_xmss_sign(const sphincs_hash128_t secret, + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, uint32_t keypair_address, + const sphincs_hash128_t tbs_root, SPHINCS_XMSS_SIGNATURE *sig) { - size_t height = SPHINCS_XMSS_HEIGHT; - sphincs_adrs_t adrs; + sphincs_adrs_t adrs = {0}; sphincs_wots_key_t wots_sk; - sphincs_secret_t tree[(1 << (SPHINCS_XMSS_HEIGHT + 1)) - 1]; + sphincs_hash128_t tree[SPHINCS_XMSS_NUM_NODES]; + + + //fprintf(stderr, " sphincs_xmss_sign: keypair = %d\n", (int)keypair_address); // generate wots_sig + sphincs_adrs_copy_layer_address(adrs, in_adrs); + sphincs_adrs_copy_tree_address(adrs, in_adrs); + sphincs_adrs_set_keypair_address(adrs, keypair_address); + + + sphincs_wots_derive_sk(secret, seed, adrs, wots_sk); - sphincs_wots_sign(wots_sk, seed, adrs, dgst, sig->wots_sig); + + sphincs_wots_key_t wots_pk; + sphincs_hash128_t wots_root; + sphincs_wots_sk_to_pk(wots_sk, seed, adrs, wots_pk); + sphincs_wots_pk_to_root(wots_pk, seed, adrs, wots_root); + // format_bytes(stderr, 0, 4, "sphincs_xmss_sign: wots_root", wots_root, 16); + + + sphincs_wots_sign(wots_sk, seed, adrs, tbs_root, sig->wots_sig); + + + sphincs_wots_sig_to_pk(sig->wots_sig, seed, adrs, tbs_root, wots_pk); + sphincs_wots_pk_to_root(wots_pk, seed, adrs, wots_root); + + // format_bytes(stderr, 0, 4, "sphincs_xmss_sign: wots_root", wots_root, 16); + // build xmss_tree, then build auth_path - sphincs_xmss_build_tree(secret, seed, adrs, height, tree); - sphincs_xmss_build_auth_path(tree, height, index, sig->auth_path); + // note: build_tree use the original in_adrs (without keypair_address set) + sphincs_xmss_build_tree(secret, seed, in_adrs, tree); + + // format_bytes(stderr, 0, 4, "sphincs_xmss_sign: tree[0]", tree[0], 16); + // format_bytes(stderr, 0, 4, "sphincs_xmss_sign: tree[1022]", tree[1022], 16); + + + sphincs_xmss_build_auth_path(tree, keypair_address, sig->auth_path); + + + + // sphincs_xmss_build_root(wots_root, keypair_address, seed, adrs, sig->auth_path, wots_root); + // format_bytes(stderr, 0, 4, "sphincs_xmss_sign: xmss_root", wots_root, 16); + + } void sphincs_xmss_sig_to_root(const SPHINCS_XMSS_SIGNATURE *sig, - const sphincs_secret_t seed, const sphincs_adrs_t in_adrs, - const sphincs_secret_t dgst, sphincs_secret_t xmss_root) + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, uint32_t keypair_address, + const sphincs_hash128_t tbs_root, sphincs_hash128_t xmss_root) { sphincs_adrs_t adrs; sphincs_wots_key_t wots_pk; - sphincs_secret_t wots_root; - size_t height = SPHINCS_XMSS_HEIGHT; + sphincs_hash128_t wots_root; + sphincs_adrs_copy_layer_address(adrs, in_adrs); + sphincs_adrs_copy_tree_address(adrs, in_adrs); + sphincs_adrs_set_keypair_address(adrs, keypair_address); - sphincs_wots_sig_to_pk(sig->wots_sig, seed, adrs, dgst, wots_pk); + fprintf(stderr, "sphincs_xmss_sig_to_root\n"); + + // type == SPHINCS_ADRS_TYPE_WOTS_HASH + sphincs_wots_sig_to_pk(sig->wots_sig, seed, adrs, tbs_root, wots_pk); + // type == SPHINCS_ADRS_TYPE_WOTS_PK sphincs_wots_pk_to_root(wots_pk, seed, adrs, wots_root); + //format_bytes(stderr, 0, 4, "sphincs_xmss_sig_to_root: wots_root", wots_root, 16); - sphincs_xmss_build_root(wots_root, sig->index, seed, adrs, - sig->auth_path, height, - xmss_root); + + // type == SPHINCS_ADRS_TYPE_TREE + sphincs_xmss_build_root(wots_root, keypair_address, seed, adrs, sig->auth_path, xmss_root); + + fprintf(stderr, "\n"); } -// generate the highest layer xmss_tree root -void sphincs_hypertree_derive_root(const sphincs_secret_t secret, const sphincs_secret_t seed, - sphincs_secret_t root) + + + + + +// generate the highest layer xmss_tree root, which is the hypertree_root, and the sphincs_root +void sphincs_hypertree_derive_root(const sphincs_hash128_t secret, const sphincs_hash128_t seed, + sphincs_hash128_t root) { sphincs_adrs_t adrs; - sphincs_secret_t tree[(1 << (SPHINCS_XMSS_HEIGHT + 1)) - 1]; + sphincs_hash128_t tree[SPHINCS_XMSS_NUM_NODES]; + sphincs_adrs_set_layer_address(adrs, SPHINCS_HYPERTREE_LAYERS - 1); sphincs_adrs_set_tree_address(adrs, 0); - sphincs_xmss_build_tree(secret, seed, adrs, SPHINCS_XMSS_HEIGHT, tree); - root = tree[(1 << (SPHINCS_XMSS_HEIGHT + 1)) - 2]; + + sphincs_xmss_build_tree(secret, seed, adrs, tree); + + memcpy(root, tree[SPHINCS_XMSS_NUM_NODES - 1], sizeof(sphincs_hash128_t)); } -// FIXME: uint64_t for leaf_index? -void sphincs_hypertree_sign(const sphincs_secret_t secret, const sphincs_secret_t seed, - uint32_t tree_index, uint32_t leaf_index, +// hypertree sign the fors_forest_root, generate layers xmss_sig + + +void sphincs_hypertree_sign(const sphincs_hash128_t secret, const sphincs_hash128_t seed, + uint64_t tree_address, uint32_t keypair_address, + const sphincs_hash128_t fors_forest_root, SPHINCS_XMSS_SIGNATURE sig[SPHINCS_HYPERTREE_LAYERS]) { sphincs_adrs_t adrs = {0}; + sphincs_hash128_t xmss_root; + int i; + sphincs_adrs_set_layer_address(adrs, 0); + sphincs_adrs_set_tree_address(adrs, tree_address); + + // sign fors_forest_root with layer 0 xmss keypair + sphincs_xmss_sign(secret, seed, adrs, keypair_address, fors_forest_root, &sig[0]); + + + // sig0 => layer 0 xmss_root + sphincs_xmss_sig_to_root(&sig[0], seed, adrs, keypair_address, fors_forest_root, xmss_root); + + + for (i = 1; i < SPHINCS_HYPERTREE_LAYERS; i++) { + // layer +1 keypair_address is the lowest xmss_height bits of tree_address + keypair_address = tree_address & ((1 << SPHINCS_XMSS_HEIGHT) - 1); + tree_address >>= SPHINCS_XMSS_HEIGHT; + + sphincs_adrs_set_layer_address(adrs, i); + sphincs_adrs_set_tree_address(adrs, tree_address); + // sign xmss_root with layer +1 xmss_keypair + sphincs_xmss_sign(secret, seed, adrs, keypair_address, xmss_root, &sig[i]); + // xmss_sig => xmss_root, to be signed by next layer +1 + sphincs_xmss_sig_to_root(&sig[i], seed, adrs, keypair_address, xmss_root, xmss_root); + } } +// test pass! +int sphincs_hypertree_verify(const sphincs_hash128_t top_xmss_root, const sphincs_hash128_t seed, + uint64_t tree_address, uint32_t keypair_address, + const sphincs_hash128_t tbs_fors_forest_root, + const SPHINCS_XMSS_SIGNATURE sig[SPHINCS_HYPERTREE_LAYERS]) +{ + sphincs_adrs_t adrs = {0}; + sphincs_hash128_t xmss_root; + int i; -void sphincs_fors_derive_sk(const sphincs_secret_t secret, - const sphincs_secret_t seed, const sphincs_adrs_t in_adrs, - uint32_t fors_index, sphincs_secret_t sk) + sphincs_adrs_set_layer_address(adrs, 0); + sphincs_adrs_set_tree_address(adrs, tree_address); + + sphincs_xmss_sig_to_root(&sig[0], seed, adrs, keypair_address, tbs_fors_forest_root, xmss_root); + + + for (i = 1; i < SPHINCS_HYPERTREE_LAYERS; i++) { + keypair_address = tree_address & ((1 << SPHINCS_XMSS_HEIGHT) - 1); + tree_address >>= SPHINCS_XMSS_HEIGHT; + + sphincs_adrs_set_layer_address(adrs, i); + sphincs_adrs_set_tree_address(adrs, tree_address); + + // xmss_sig => xmss_root, to be signed by next layer +1 + sphincs_xmss_sig_to_root(&sig[i], seed, adrs, keypair_address, xmss_root, xmss_root); + } + + if (memcmp(xmss_root, top_xmss_root, sizeof(sphincs_hash128_t)) != 0) { + error_print(); + return 0; + } + return 1; +} + +void sphincs_fors_derive_sk(const sphincs_hash128_t secret, + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, + uint32_t fors_index, sphincs_hash128_t sk) { uint8_t block[HASH256_BLOCK_SIZE] = {0}; sphincs_adrs_t adrs; @@ -633,7 +764,7 @@ void sphincs_fors_derive_sk(const sphincs_secret_t secret, hash256_t dgst; // blockpad(seed) - memcpy(block, seed, sizeof(sphincs_secret_t)); + memcpy(block, seed, sizeof(sphincs_hash128_t)); sphincs_adrs_copy_layer_address(adrs, in_adrs); sphincs_adrs_copy_tree_address(adrs, in_adrs); @@ -649,44 +780,363 @@ void sphincs_fors_derive_sk(const sphincs_secret_t secret, hash256_init(&ctx); hash256_update(&ctx, block, sizeof(block)); hash256_update(&ctx, adrsc, sizeof(adrsc)); - hash256_update(&ctx, secret, sizeof(sphincs_secret_t)); + hash256_update(&ctx, secret, sizeof(sphincs_hash128_t)); hash256_finish(&ctx, dgst); - memcpy(sk, dgst, sizeof(sphincs_secret_t)); + memcpy(sk, dgst, sizeof(sphincs_hash128_t)); gmssl_secure_clear(dgst, sizeof(dgst)); } -void sphincs_fors_derive_root_ex(const sphincs_secret_t secret, - const sphincs_secret_t seed, const sphincs_adrs_t in_adrs, - size_t fors_height, size_t fors_trees, - sphincs_secret_t root) +void sphincs_fors_build_tree(const sphincs_hash128_t secret, + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, int tree_addr, + sphincs_hash128_t tree[SPHINCS_FORS_TREE_NUM_NODES]) { -} + uint8_t block[64] = {0}; + sphincs_adrs_t adrs = {0}; + sphincs_adrsc_t adrsc; + uint32_t n = 1 << SPHINCS_FORS_TREE_HEIGHT; + uint32_t tree_index; + HASH256_CTX ctx; + hash256_t dgst; + sphincs_hash128_t *children; + sphincs_hash128_t *parents; + uint32_t h; + uint32_t i; -void sphincs_fors_derive_root(const sphincs_secret_t secret, - const sphincs_secret_t seed, const sphincs_adrs_t in_adrs, - sphincs_secret_t root) -{ - size_t fors_height = SPHINCS_FORS_HEIGHT; - size_t fors_trees = SPHINCS_FORS_NUM_TREES; - sphincs_fors_derive_root_ex(secret, seed, in_adrs, fors_height, fors_trees, root); -} + memcpy(block, seed, sizeof(sphincs_hash128_t)); -void sphincs_fors_sign(const sphincs_secret_t secret, - const sphincs_secret_t seed, const sphincs_adrs_t in_adrs, - const uint8_t dgst[SPHINCS_FORS_DIGEST_SIZE], - SPHINCS_FORS_SIGNATURE *sig) -{ - sphincs_adrs_t adrs; - sphincs_secret_t fors_sk; - size_t i; + sphincs_adrs_copy_layer_address(adrs, in_adrs); + sphincs_adrs_copy_tree_address(adrs, in_adrs); + sphincs_adrs_set_type(adrs, SPHINCS_ADRS_TYPE_TREE); + sphincs_adrs_copy_keypair_address(adrs, in_adrs); + sphincs_adrs_set_tree_height(adrs, 0); - for (i = 0; i < SPHINCS_FORS_NUM_TREES; i++) { - //sphincs_fors_derive_sk(secret, seed, adrs, fors_index, fors_sk); + for (i = 0; i < n; i++) { + tree_index = n * tree_addr + i; + sphincs_fors_derive_sk(secret, seed, adrs, tree_index, tree[i]); + + sphincs_adrs_set_tree_index(adrs, tree_index); + sphincs_adrs_compress(adrs, adrsc); + + + hash256_init(&ctx); + hash256_update(&ctx, block, sizeof(block)); + hash256_update(&ctx, adrsc, sizeof(adrsc)); + hash256_update(&ctx, tree[i], sizeof(sphincs_hash128_t)); + hash256_finish(&ctx, dgst); + + memcpy(tree[i], dgst, sizeof(sphincs_hash128_t)); + } + + children = tree; + parents = tree + n; + for (h = 0; h < SPHINCS_FORS_TREE_HEIGHT; h++) { + sphincs_adrs_set_tree_height(adrs, h + 1); + n >>= 1; + for (i = 0; i < n; i++) { + tree_index = n * tree_addr + i; + sphincs_adrs_set_tree_index(adrs, tree_index); + sphincs_tree_hash(children[2*i], children[2*i + 1], seed, adrs, parents[i]); + } + children = parents; + parents += n; } } + +void sphincs_fors_derive_root(const sphincs_hash128_t secret, + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, + sphincs_hash128_t root) +{ + uint8_t block[64] = {0}; + sphincs_adrs_t adrs = {0}; + sphincs_adrsc_t adrsc; + sphincs_hash128_t tree[SPHINCS_FORS_TREE_NUM_NODES]; + sphincs_hash128_t roots[SPHINCS_FORS_NUM_TREES]; + HASH256_CTX ctx; + hash256_t dgst; + int i; + + memcpy(block, seed, sizeof(sphincs_hash128_t)); + + sphincs_adrs_copy_layer_address(adrs, in_adrs); + sphincs_adrs_copy_tree_address(adrs, in_adrs); + sphincs_adrs_set_type(adrs, SPHINCS_ADRS_TYPE_FORS_ROOTS); + sphincs_adrs_copy_keypair_address(adrs, in_adrs); + + // FORS_ROOTS has padding[2] = {0,0}, which will be modified by fors_build_tree + sphincs_adrs_compress(adrs, adrsc); + + for (i = 0; i < SPHINCS_FORS_NUM_TREES; i++) { + sphincs_fors_build_tree(secret, seed, adrs, i, tree); + memcpy(roots[i], tree[SPHINCS_FORS_TREE_NUM_NODES - 1], sizeof(sphincs_hash128_t)); + } + + hash256_init(&ctx); + hash256_update(&ctx, block, sizeof(block)); + hash256_update(&ctx, adrsc, sizeof(adrsc)); + hash256_update(&ctx, roots[0], sizeof(roots)); + hash256_finish(&ctx, dgst); + + memcpy(root, dgst, sizeof(sphincs_hash128_t)); +} + + +void split_bits(const uint8_t dgst[21], uint32_t index[14]) +{ + int i; + for (i = 0; i < 7; i++) { + index[0] = ((uint32_t)dgst[0] << 4) | (dgst[1] >> 4); + index[1] = ((uint32_t)(dgst[1] & 0x0f) << 8) | dgst[2]; + index += 2; + dgst += 3; + } + /* + for (i = 0; i < 14; i++) { + index[i] += (1 << SPHINCS_FORS_TREE_HEIGHT) * i; + } + */ +} + + + + +void sphincs_fors_sign(const sphincs_hash128_t secret, + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, + const uint8_t dgst[21], + SPHINCS_FORS_SIGNATURE *sig) +{ + uint32_t index[14]; + uint32_t tree_index; + uint32_t i, h; + sphincs_hash128_t fors_tree[SPHINCS_FORS_TREE_NUM_NODES]; + + + sphincs_hash128_t fors_root; + + + sphincs_fors_derive_root(secret, seed, in_adrs, fors_root); + + format_bytes(stderr, 0, 4, "--------fors_root", fors_root, 16); + + + + memset(sig, 0, sizeof(SPHINCS_FORS_SIGNATURE)); + + + split_bits(dgst, index); + + for (i = 0; i < 14; i++) { + tree_index = (1 << SPHINCS_FORS_TREE_HEIGHT) * i + index[i]; + + sphincs_fors_derive_sk(secret, seed, in_adrs, tree_index, sig->fors_sk[i]); + } + + + for (i = 0; i < 14; i++) { + + sphincs_hash128_t *tree = fors_tree; + + sphincs_fors_build_tree(secret, seed, in_adrs, i, tree); + + + format_bytes(stderr, 0, 4, "tree[0]", tree[0], 16); + format_bytes(stderr, 0, 4, "root", tree[SPHINCS_FORS_TREE_NUM_NODES - 1], 16); + + int k; + for (k = 0; k < SPHINCS_FORS_TREE_NUM_NODES; k++) { +// format_print(stderr, 0, 4, "tree[%d]", k); +// format_bytes(stderr, 0, 0, "", tree[k], 16); + } + + + + tree_index = index[i]; + + for (h = 0; h < SPHINCS_FORS_TREE_HEIGHT; h++) { + + memcpy(sig->auth_path[i][h], tree[tree_index ^ 1], sizeof(sphincs_hash128_t)); + tree += (1 << (SPHINCS_FORS_TREE_HEIGHT - h)); + tree_index >>= 1; + } + } + + + + + // sig->fors_sk[0], sig->auth_path[0] ==> fors_root[0] + + + if (0) { + uint8_t block[64] = {0}; + sphincs_adrs_t adrs; + sphincs_adrsc_t adrsc; + HASH256_CTX ctx; + hash256_t root; + + tree_index = index[0]; + + sphincs_adrs_copy_layer_address(adrs, in_adrs); + sphincs_adrs_copy_tree_address(adrs, in_adrs); + sphincs_adrs_set_type(adrs, SPHINCS_ADRS_TYPE_TREE); + sphincs_adrs_copy_keypair_address(adrs, in_adrs); + sphincs_adrs_set_tree_height(adrs, 0); + sphincs_adrs_set_tree_index(adrs, tree_index); + + sphincs_adrs_compress(adrs, adrsc); + + hash256_init(&ctx); + hash256_update(&ctx, block, sizeof(block)); + hash256_update(&ctx, adrsc, sizeof(adrsc)); + hash256_update(&ctx, sig->fors_sk[0], sizeof(sphincs_hash128_t)); + hash256_finish(&ctx, root); + + format_bytes(stderr, 0, 4, "fors_tree[0]", root, 16); + + + uint32_t n = 1 << SPHINCS_FORS_TREE_HEIGHT; + + + for (h = 0; h < SPHINCS_FORS_TREE_HEIGHT; h++) { + int right_child = tree_index & 1; + tree_index >>= 1; + n >>= 1; + + sphincs_adrs_set_tree_height(adrs, h + 1); + sphincs_adrs_set_tree_index(adrs, tree_index); + + if (right_child) + sphincs_tree_hash(sig->auth_path[0][h], root, seed, adrs, root); + else sphincs_tree_hash(root, sig->auth_path[0][h], seed, adrs, root); + } + + format_bytes(stderr, 0, 4, "fors_root", root, 16); + } + + + memset(fors_root, 0, 16); + + sphincs_fors_sig_to_root(sig, seed, in_adrs, dgst, fors_root); + format_bytes(stderr, 0, 4, ">>>>>>fors_root", fors_root, 16); + + +} + +void sphincs_fors_sig_to_root(const SPHINCS_FORS_SIGNATURE *sig, + const sphincs_hash128_t seed, const sphincs_adrs_t in_adrs, + const uint8_t tbs[21], sphincs_hash128_t root) +{ + + uint8_t block[64] = {0}; + sphincs_adrs_t adrs; + sphincs_adrsc_t adrsc; + HASH256_CTX ctx; + hash256_t dgst; + + uint32_t index[14]; + uint32_t tree_index; + uint32_t i, h; + + sphincs_hash128_t fors_roots[14]; + + + memcpy(block, seed, sizeof(sphincs_hash128_t)); + + split_bits(tbs, index); + + + fprintf(stderr, "sphincs_fors_sig_to_root\n"); + + for (i = 0; i < 14; i++) { + + tree_index = (1 << SPHINCS_FORS_TREE_HEIGHT) * i + index[i]; + + sphincs_adrs_copy_layer_address(adrs, in_adrs); + sphincs_adrs_copy_tree_address(adrs, in_adrs); + sphincs_adrs_set_type(adrs, SPHINCS_ADRS_TYPE_TREE); + sphincs_adrs_copy_keypair_address(adrs, in_adrs); + sphincs_adrs_set_tree_height(adrs, 0); + sphincs_adrs_set_tree_index(adrs, tree_index); + + sphincs_adrs_compress(adrs, adrsc); + + + hash256_init(&ctx); + hash256_update(&ctx, block, sizeof(block)); + hash256_update(&ctx, adrsc, sizeof(adrsc)); + hash256_update(&ctx, sig->fors_sk[i], sizeof(sphincs_hash128_t)); + hash256_finish(&ctx, dgst); + + memcpy(root, dgst, 16); + + + uint32_t n = 1 << SPHINCS_FORS_TREE_HEIGHT; + + + tree_index = index[i]; + + for (h = 0; h < SPHINCS_FORS_TREE_HEIGHT; h++) { + int right_child = tree_index & 1; + tree_index >>= 1; + n >>= 1; + + sphincs_adrs_set_tree_height(adrs, h + 1); + sphincs_adrs_set_tree_index(adrs, n * i + tree_index); + + if (right_child) + sphincs_tree_hash(sig->auth_path[i][h], root, seed, adrs, root); + else sphincs_tree_hash(root, sig->auth_path[i][h], seed, adrs, root); + } + + memcpy(fors_roots[i], root, 16); + + + format_print(stderr, 0, 4, "fors_roots[%d]", i); + format_bytes(stderr, 0, 0, "", fors_roots[i], 16); + + } + + + memset(adrs, 0, sizeof(adrs)); + sphincs_adrs_copy_layer_address(adrs, in_adrs); + sphincs_adrs_copy_tree_address(adrs, in_adrs); + sphincs_adrs_set_type(adrs, SPHINCS_ADRS_TYPE_FORS_ROOTS); + sphincs_adrs_copy_keypair_address(adrs, in_adrs); + + sphincs_adrs_compress(adrs, adrsc); + + + hash256_init(&ctx); + hash256_update(&ctx, block, sizeof(block)); + hash256_update(&ctx, adrsc, sizeof(adrsc)); + hash256_update(&ctx, fors_roots[0], sizeof(fors_roots)); + hash256_finish(&ctx, dgst); + + memcpy(root, dgst, 16); + + format_bytes(stderr, 0, 4, "fors_root", root, 16); + + +} + + + + + + + + + + + + + + + + + + int sphincs_fors_signature_to_bytes(const SPHINCS_FORS_SIGNATURE *sig, uint8_t **out, size_t *outlen) { if (!sig || !outlen) { @@ -694,13 +1144,13 @@ int sphincs_fors_signature_to_bytes(const SPHINCS_FORS_SIGNATURE *sig, uint8_t * return -1; } if (out && *out) { - memcpy(*out, sig->fors_sk, sizeof(sphincs_secret_t) * SPHINCS_FORS_HEIGHT); - *out += sizeof(sphincs_secret_t) * SPHINCS_FORS_HEIGHT; - memcpy(*out, sig->auth_path, sizeof(sphincs_secret_t) * SPHINCS_FORS_HEIGHT * SPHINCS_FORS_NUM_TREES); - *out += sizeof(sphincs_secret_t) * SPHINCS_FORS_HEIGHT * SPHINCS_FORS_NUM_TREES; + memcpy(*out, sig->fors_sk, sizeof(sphincs_hash128_t) * SPHINCS_FORS_NUM_TREES); + *out += sizeof(sphincs_hash128_t) * SPHINCS_FORS_NUM_TREES; + memcpy(*out, sig->auth_path, sizeof(sphincs_hash128_t) * SPHINCS_FORS_HEIGHT * SPHINCS_FORS_NUM_TREES); + *out += sizeof(sphincs_hash128_t) * SPHINCS_FORS_HEIGHT * SPHINCS_FORS_NUM_TREES; } - *outlen += sizeof(sphincs_secret_t) * SPHINCS_FORS_HEIGHT; - *outlen += sizeof(sphincs_secret_t) * SPHINCS_FORS_HEIGHT * SPHINCS_FORS_NUM_TREES; + *outlen += sizeof(sphincs_hash128_t) * SPHINCS_FORS_NUM_TREES; + *outlen += sizeof(sphincs_hash128_t) * SPHINCS_FORS_HEIGHT * SPHINCS_FORS_NUM_TREES; return 1; } @@ -714,12 +1164,12 @@ int sphincs_fors_signature_from_bytes(SPHINCS_FORS_SIGNATURE *sig, const uint8_t error_print(); return -1; } - memcpy(sig->fors_sk, *in, sizeof(sphincs_secret_t) * SPHINCS_FORS_HEIGHT); - *in += sizeof(sphincs_secret_t) * SPHINCS_FORS_HEIGHT; - *inlen += sizeof(sphincs_secret_t) * SPHINCS_FORS_HEIGHT; - memcpy(sig->auth_path, *in, sizeof(sphincs_secret_t) * SPHINCS_FORS_HEIGHT * SPHINCS_FORS_NUM_TREES); - *in += sizeof(sphincs_secret_t) * SPHINCS_FORS_HEIGHT * SPHINCS_FORS_NUM_TREES; - *inlen += sizeof(sphincs_secret_t) * SPHINCS_FORS_HEIGHT * SPHINCS_FORS_NUM_TREES; + memcpy(sig->fors_sk, *in, sizeof(sphincs_hash128_t) * SPHINCS_FORS_NUM_TREES); + *in += sizeof(sphincs_hash128_t) * SPHINCS_FORS_NUM_TREES; + *inlen += sizeof(sphincs_hash128_t) * SPHINCS_FORS_NUM_TREES; + memcpy(sig->auth_path, *in, sizeof(sphincs_hash128_t) * SPHINCS_FORS_HEIGHT * SPHINCS_FORS_NUM_TREES); + *in += sizeof(sphincs_hash128_t) * SPHINCS_FORS_HEIGHT * SPHINCS_FORS_NUM_TREES; + *inlen += sizeof(sphincs_hash128_t) * SPHINCS_FORS_HEIGHT * SPHINCS_FORS_NUM_TREES; return 1; } @@ -730,7 +1180,7 @@ int sphincs_fors_signature_print_ex(FILE *fp, int fmt, int ind, const char *labe format_print(fp, fmt, ind, "%s\n", label); ind += 4; for (i = 0; i < SPHINCS_FORS_HEIGHT; i++) { - format_bytes(fp, fmt, 0, "fork_sk", sig->fors_sk[i], sizeof(sphincs_secret_t)); + format_bytes(fp, fmt, 0, "fork_sk", sig->fors_sk[i], sizeof(sphincs_hash128_t)); format_print(fp, fmt, ind, "auth_path\n"); for (j = 0; i < SPHINCS_FORS_NUM_TREES; i++) { } @@ -750,12 +1200,12 @@ int sphincs_public_key_to_bytes(const SPHINCS_KEY *key, uint8_t **out, size_t *o return -1; } if (out && *out) { - memcpy(*out, key->public_key.seed, sizeof(sphincs_secret_t)); - *out += sizeof(sphincs_secret_t); - memcpy(*out, key->public_key.root, sizeof(sphincs_secret_t)); - *out += sizeof(sphincs_secret_t); + memcpy(*out, key->public_key.seed, sizeof(sphincs_hash128_t)); + *out += sizeof(sphincs_hash128_t); + memcpy(*out, key->public_key.root, sizeof(sphincs_hash128_t)); + *out += sizeof(sphincs_hash128_t); } - *outlen += sizeof(sphincs_secret_t) * 2; + *outlen += sizeof(sphincs_hash128_t) * 2; return 1; } @@ -765,16 +1215,16 @@ int sphincs_public_key_from_bytes(SPHINCS_KEY *key, const uint8_t **in, size_t * error_print(); return -1; } - if (*inlen < sizeof(sphincs_secret_t) * 2) { + if (*inlen < sizeof(sphincs_hash128_t) * 2) { error_print(); return -1; } - memcpy(key->public_key.seed, *in, sizeof(sphincs_secret_t)); - *in += sizeof(sphincs_secret_t); - *inlen -= sizeof(sphincs_secret_t); - memcpy(key->public_key.root, *in, sizeof(sphincs_secret_t)); - *in += sizeof(sphincs_secret_t); - *inlen -= sizeof(sphincs_secret_t); + memcpy(key->public_key.seed, *in, sizeof(sphincs_hash128_t)); + *in += sizeof(sphincs_hash128_t); + *inlen -= sizeof(sphincs_hash128_t); + memcpy(key->public_key.root, *in, sizeof(sphincs_hash128_t)); + *in += sizeof(sphincs_hash128_t); + *inlen -= sizeof(sphincs_hash128_t); return 1; } @@ -782,8 +1232,8 @@ int sphincs_public_key_print(FILE *fp, int fmt, int ind, const char *label, cons { format_print(fp, fmt, ind, "%s\n", label); ind += 4; - format_bytes(fp, fmt, ind, "seed", key->public_key.seed, sizeof(sphincs_secret_t)); - format_bytes(fp, fmt, ind, "root", key->public_key.root, sizeof(sphincs_secret_t)); + format_bytes(fp, fmt, ind, "seed", key->public_key.seed, sizeof(sphincs_hash128_t)); + format_bytes(fp, fmt, ind, "root", key->public_key.root, sizeof(sphincs_hash128_t)); return 1; } @@ -798,12 +1248,12 @@ int sphincs_private_key_to_bytes(const SPHINCS_KEY *key, uint8_t **out, size_t * return -1; } if (out && *out) { - memcpy(*out, key->secret, sizeof(sphincs_secret_t)); - *out += sizeof(sphincs_secret_t); - memcpy(*out, key->sk_prf, sizeof(sphincs_secret_t)); - *out += sizeof(sphincs_secret_t); + memcpy(*out, key->secret, sizeof(sphincs_hash128_t)); + *out += sizeof(sphincs_hash128_t); + memcpy(*out, key->sk_prf, sizeof(sphincs_hash128_t)); + *out += sizeof(sphincs_hash128_t); } - *outlen += sizeof(sphincs_secret_t) * 2; + *outlen += sizeof(sphincs_hash128_t) * 2; return 1; } @@ -829,16 +1279,17 @@ int sphincs_private_key_print(FILE *fp, int fmt, int ind, const char *label, con format_print(fp, fmt, ind, "%s\n", label); ind += 4; sphincs_public_key_print(fp, fmt, ind, "public_key", key); - format_bytes(fp, fmt, ind, "secret", key->secret, sizeof(sphincs_secret_t)); - format_bytes(fp, fmt, ind, "sk_prf", key->sk_prf, sizeof(sphincs_secret_t)); + format_bytes(fp, fmt, ind, "secret", key->secret, sizeof(sphincs_hash128_t)); + format_bytes(fp, fmt, ind, "sk_prf", key->sk_prf, sizeof(sphincs_hash128_t)); return 1; } void sphincs_key_cleanup(SPHINCS_KEY *key) { if (key) { - gmssl_secure_clear(key->secret, sizeof(sphincs_secret_t)); - gmssl_secure_clear(key->sk_prf, sizeof(sphincs_secret_t)); + gmssl_secure_clear(key->secret, sizeof(sphincs_hash128_t)); + gmssl_secure_clear(key->sk_prf, sizeof(sphincs_hash128_t)); } } + diff --git a/tests/sphincstest.c b/tests/sphincstest.c index 5ebd901c..0d8f6d98 100644 --- a/tests/sphincstest.c +++ b/tests/sphincstest.c @@ -17,16 +17,26 @@ #include -// 这个应该是用值去验证的 static int test_sphincs_wots_derive_sk(void) { - sphincs_secret_t secret; - sphincs_secret_t seed; - sphincs_adrs_t adrs; + sphincs_hash128_t secret; + sphincs_hash128_t seed; + sphincs_adrs_t adrs = {0}; sphincs_wots_key_t wots_sk; - sphincs_wots_derive_sk(secret, seed, adrs, wots_sk); + memset(secret, 0, sizeof(secret)); + memset(seed, 0, sizeof(seed)); + sphincs_adrs_set_layer_address(adrs, 0); + sphincs_adrs_set_tree_address(adrs, 0); + sphincs_adrs_set_type(adrs, SPHINCS_ADRS_TYPE_WOTS_PRF); + sphincs_adrs_set_keypair_address(adrs, 0); + format_bytes(stderr, 0, 4, "secret", secret, sizeof(secret)); + format_bytes(stderr, 0, 4, "seed", seed, sizeof(seed)); + sphincs_adrs_print(stderr, 0, 4, "adrs", adrs); + + memset(wots_sk, 0, sizeof(wots_sk)); + sphincs_wots_derive_sk(secret, seed, adrs, wots_sk); sphincs_wots_key_print(stderr, 0, 4, "wots_sk", wots_sk); printf("%s() ok\n", __FUNCTION__); @@ -35,13 +45,15 @@ static int test_sphincs_wots_derive_sk(void) static int test_sphincs_wots_chain(void) { - sphincs_secret_t x; - sphincs_secret_t seed; - sphincs_adrs_t adrs; - sphincs_secret_t y; + sphincs_hash128_t seed = {0}; + sphincs_adrs_t adrs = {0}; + sphincs_hash128_t x = {0}; + sphincs_hash128_t y = {0}; int start = 0; int steps = 15; + format_bytes(stderr, 0, 4, "seed", seed, sizeof(seed)); + sphincs_wots_chain(x, seed, adrs, start, steps, y); printf("%s() ok\n", __FUNCTION__); @@ -51,7 +63,7 @@ static int test_sphincs_wots_chain(void) static int test_sphincs_wots_sk_to_pk(void) { sphincs_wots_key_t wots_sk; - sphincs_secret_t seed; + sphincs_hash128_t seed; sphincs_adrs_t adrs; sphincs_wots_key_t wots_pk; @@ -66,9 +78,9 @@ static int test_sphincs_wots_sk_to_pk(void) static int test_sphincs_wots_pk_to_root(void) { sphincs_wots_key_t wots_pk; - sphincs_secret_t seed; + sphincs_hash128_t seed; sphincs_adrs_t adrs; - sphincs_secret_t wots_root; + sphincs_hash128_t wots_root; sphincs_wots_pk_to_root(wots_pk, seed, adrs, wots_root); @@ -79,9 +91,9 @@ static int test_sphincs_wots_pk_to_root(void) static int test_sphincs_wots_sign(void) { sphincs_wots_key_t wots_sk; - sphincs_secret_t seed; + sphincs_hash128_t seed; sphincs_adrs_t adrs; - sphincs_secret_t dgst; + sphincs_hash128_t dgst; sphincs_wots_sig_t wots_sig; sphincs_wots_sign(wots_sk, seed, adrs, dgst, wots_sig); @@ -93,9 +105,9 @@ static int test_sphincs_wots_sign(void) static int test_sphincs_wots_sig_to_pk(void) { sphincs_wots_sig_t wots_sig; - sphincs_secret_t seed; + sphincs_hash128_t seed; sphincs_adrs_t adrs; - sphincs_secret_t dgst; + sphincs_hash128_t dgst; sphincs_wots_key_t wots_pk; sphincs_wots_sig_to_pk(wots_sig, seed, adrs, dgst, wots_pk); @@ -104,41 +116,356 @@ static int test_sphincs_wots_sig_to_pk(void) return 1; } - static int test_sphincs_wots_sign_verify(void) { + sphincs_hash128_t secret = {0}; + sphincs_hash128_t seed = {0}; + sphincs_adrs_t adrs = {0}; + sphincs_hash128_t dgst = {0}; + sphincs_wots_key_t wots_sk; sphincs_wots_key_t wots_pk; - sphincs_secret_t seed; - sphincs_adrs_t adrs; - sphincs_secret_t dgst; sphincs_wots_sig_t wots_sig; sphincs_wots_key_t wots_pk2; + sphincs_hash128_t wots_root; + int i; + + sphincs_adrs_set_layer_address(adrs, 0); + sphincs_adrs_set_tree_address(adrs, 0); + sphincs_adrs_set_type(adrs, SPHINCS_ADRS_TYPE_WOTS_PRF); + sphincs_adrs_set_keypair_address(adrs, 0); + + sphincs_wots_derive_sk(secret, seed, adrs, wots_sk); + + format_print(stderr, 0, 4, "wots_sk\n"); + for (i = 0; i < 35; i++) { + format_print(stderr, 0, 8, "%d", i); + format_bytes(stderr, 0, 0, "", wots_sk[i], 16); + } sphincs_wots_sk_to_pk(wots_sk, seed, adrs, wots_pk); + format_print(stderr, 0, 4, "wots_pk\n"); + for (i = 0; i < 35; i++) { + format_print(stderr, 0, 8, "%d", i); + format_bytes(stderr, 0, 0, "", wots_pk[i], 16); + } + + + sphincs_wots_pk_to_root(wots_pk, seed, adrs, wots_root); + format_bytes(stderr, 0, 4, "wots_root (from pk)", wots_root, 16); + + + sphincs_wots_sign(wots_sk, seed, adrs, dgst, wots_sig); sphincs_wots_sig_to_pk(wots_sig, seed, adrs, dgst, wots_pk2); + format_print(stderr, 0, 4, "wots_pk\n"); + for (i = 0; i < 35; i++) { +// format_print(stderr, 0, 8, "%d", i); +// format_bytes(stderr, 0, 0, "", wots_pk[i], 16); + } + + sphincs_wots_pk_to_root(wots_pk2, seed, adrs, wots_root); + format_bytes(stderr, 0, 4, "wots_root (from sig)", wots_root, 16); + + if (memcmp(wots_pk2, wots_pk, sizeof(sphincs_wots_key_t)) != 0) { error_print(); return -1; } + + + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + + + +static int test_sphincs_xmss_build_tree(void) +{ + sphincs_hash128_t secret = {0}; + sphincs_hash128_t seed = {0}; + sphincs_adrs_t adrs = {0}; + sphincs_hash128_t tree[SPHINCS_XMSS_NUM_NODES] = {0}; + int i; + + sphincs_xmss_build_tree(secret, seed, adrs, tree); + + // for sphincs+_128s, height==9, num_nodes==1023 + format_print(stderr, 0, 4, "xmss_tree\n"); + for (i = 0; i < SPHINCS_XMSS_NUM_NODES; i++) { + format_print(stderr, 0, 8, "%d", i); + format_bytes(stderr, 0, 0, "", tree[i], sizeof(sphincs_hash128_t)); + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sphincs_xmss_build_auth_path(void) +{ + sphincs_hash128_t secret = {0}; + sphincs_hash128_t seed = {0}; + sphincs_adrs_t adrs = {0}; + sphincs_hash128_t tree[SPHINCS_XMSS_NUM_NODES] = {0}; + uint32_t tree_index = 0; + sphincs_hash128_t auth_path[SPHINCS_XMSS_HEIGHT]; + int i; + + sphincs_xmss_build_tree(secret, seed, adrs, tree); + + sphincs_xmss_build_auth_path(tree, tree_index, auth_path); + + format_print(stderr, 0, 4, "auth_path\n"); + for (i = 0; i < SPHINCS_XMSS_HEIGHT; i++) { + format_print(stderr, 0, 8, "%d", i); + format_bytes(stderr, 0, 0, "", auth_path[i], sizeof(sphincs_hash128_t)); + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sphincs_xmss_build_root(void) +{ + sphincs_hash128_t secret = {0}; + sphincs_hash128_t seed = {0}; + sphincs_adrs_t adrs = {0}; + sphincs_hash128_t tree[SPHINCS_XMSS_NUM_NODES] = {0}; + uint32_t tree_index = 0; + sphincs_hash128_t auth_path[SPHINCS_XMSS_HEIGHT]; + sphincs_hash128_t root; + + sphincs_xmss_build_tree(secret, seed, adrs, tree); + + sphincs_xmss_build_auth_path(tree, tree_index, auth_path); + + sphincs_xmss_build_root(tree[tree_index], tree_index, seed, adrs, auth_path, root); + + if (memcmp(root, tree[SPHINCS_XMSS_NUM_NODES - 1], sizeof(root)) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sphincs_xmss_sign(void) +{ + sphincs_hash128_t secret = {0}; + sphincs_hash128_t seed = {0}; + sphincs_adrs_t adrs = {0}; + uint32_t keypair_address = 0; + + sphincs_hash128_t xmss_tree[SPHINCS_XMSS_NUM_NODES]; + sphincs_hash128_t dgst = {0}; + SPHINCS_XMSS_SIGNATURE sig; + sphincs_hash128_t xmss_root; + sphincs_hash128_t auth_path[SPHINCS_XMSS_HEIGHT]; + + + sphincs_xmss_build_tree(secret, seed, adrs, xmss_tree); + + sphincs_xmss_build_auth_path(xmss_tree, keypair_address, auth_path); + + sphincs_xmss_build_root(xmss_tree[keypair_address], keypair_address, seed, adrs, auth_path, xmss_root); + + + format_bytes(stderr, 0, 4, "tree[0]", xmss_tree[0], 16); + format_bytes(stderr, 0, 4, "tree_root", xmss_tree[SPHINCS_XMSS_NUM_NODES-1], 16); + + + sphincs_xmss_sign(secret, seed, adrs, keypair_address, dgst, &sig); + + sphincs_xmss_sig_to_root(&sig, seed, adrs, keypair_address, dgst, xmss_root); + + if (memcmp(xmss_root, xmss_tree[SPHINCS_XMSS_NUM_NODES - 1], sizeof(sphincs_hash128_t)) != 0) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sphincs_xmss_sig_to_root(void) +{ + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sphincs_hypertree(void) +{ + sphincs_hash128_t secret = {0}; + sphincs_hash128_t seed = {0}; + uint64_t tree_address = 0; + uint32_t keypair_address = 0; + sphincs_hash128_t forest_root = {0}; + int i; + + sphincs_adrs_t adrs = {0}; + + sphincs_hash128_t trees[SPHINCS_XMSS_NUM_NODES * SPHINCS_HYPERTREE_LAYERS]; + sphincs_hash128_t *tree = trees; + + + + for (i = 0; i < SPHINCS_HYPERTREE_LAYERS; i++) { + sphincs_adrs_set_layer_address(adrs, i); + sphincs_adrs_set_tree_address(adrs, 0); + + sphincs_xmss_build_tree(secret, seed, adrs, tree); + + char label[64]; + snprintf(label, sizeof(label), "leaf[%d]", i); + + format_bytes(stderr, 0, 4, label, tree[0], 16); + + snprintf(label, sizeof(label), "root[%d]", i); + format_bytes(stderr, 0, 4, label, tree[1022], 16); + + + tree += SPHINCS_XMSS_NUM_NODES; + } + + SPHINCS_XMSS_SIGNATURE sig[SPHINCS_HYPERTREE_LAYERS]; + + sphincs_adrs_set_layer_address(adrs, 0); + sphincs_adrs_set_tree_address(adrs, keypair_address); + sphincs_xmss_sign(secret, seed, adrs, keypair_address, forest_root, &sig[0]); + + sphincs_hash128_t xmss_root; + sphincs_xmss_sig_to_root(&sig[0], seed, adrs, keypair_address, forest_root, xmss_root); + + format_bytes(stderr, 0, 4, "xmss_root[0]", xmss_root, 16); + + for (i = 1; i < SPHINCS_HYPERTREE_LAYERS; i++) { + // layer +1 keypair_address is the lowest xmss_height bits of tree_address + keypair_address = tree_address & ((1 << SPHINCS_XMSS_HEIGHT) - 1); + tree_address >>= SPHINCS_XMSS_HEIGHT; + + sphincs_adrs_set_layer_address(adrs, i); + sphincs_adrs_set_tree_address(adrs, tree_address); + // sign xmss_root with layer +1 xmss_keypair + sphincs_xmss_sign(secret, seed, adrs, keypair_address, xmss_root, &sig[i]); + // xmss_sig => xmss_root, to be signed by next layer +1 + sphincs_xmss_sig_to_root(&sig[i], seed, adrs, keypair_address, xmss_root, xmss_root); + + + + format_print(stderr, 0, 4, "xmss_root[%d]", i); + format_bytes(stderr, 0, 0, "", xmss_root, 16); + } + + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + + +static int test_sphincs_hypertree_sign(void) +{ + sphincs_hash128_t secret = {0}; + sphincs_hash128_t seed = {0}; + uint64_t tree_address = 0; + uint32_t keypair_address = 0; + sphincs_hash128_t forest_root = {0}; + + sphincs_hash128_t ht_root; + SPHINCS_XMSS_SIGNATURE ht_sig[SPHINCS_HYPERTREE_LAYERS]; + + sphincs_hypertree_derive_root(secret, seed, ht_root); + format_bytes(stderr, 0, 4, "hypertree_root", ht_root, 16); + + + sphincs_hypertree_sign(secret, seed, tree_address, keypair_address, forest_root, ht_sig); + + + if (sphincs_hypertree_verify(ht_root, seed, tree_address, keypair_address, forest_root, ht_sig) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; + +} + +static int test_sphincs_fors_sign(void) +{ + sphincs_hash128_t secret = {0}; + sphincs_hash128_t seed = {0}; + sphincs_adrs_t adrs = {0}; + const uint8_t dgst[21] = {0}; + + sphincs_hash128_t root; + sphincs_hash128_t sig_to_root; + SPHINCS_FORS_SIGNATURE sig; + + + + sphincs_fors_derive_root(secret, seed, adrs, root); + + sphincs_fors_sign(secret, seed, adrs, dgst, &sig); + + sphincs_fors_sig_to_root(&sig, seed, adrs, dgst, sig_to_root); + + if (memcmp(sig_to_root, root, 16) != 0) { + error_print(); + return -1; + } + + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_sphincs_sign(void) +{ + SPHINCS_KEY key; + sphincs_adrs_t adrs = {0}; + sphincs_hash128_t random; + + + uint32_t tree_index; + uint32_t leaf_index; + + sphincs_adrs_set_layer_address(adrs, 0); + sphincs_adrs_set_tree_address(adrs, tree_index); + sphincs_adrs_set_type(adrs, SPHINCS_ADRS_TYPE_FORS_TREE); + sphincs_adrs_set_keypair_address(adrs, leaf_index); + + printf("%s() ok\n", __FUNCTION__); return 1; } int main(void) { + if (test_sphincs_fors_sign() != 1) goto err; + //if (test_sphincs_xmss_build_tree() != 1) goto err; + //if (test_sphincs_hypertree() != 1) goto err; +// if (test_sphincs_hypertree_sign() != 1) goto err; + //if (test_sphincs_wots_sign_verify() != 1) goto err; + /* if (test_sphincs_wots_derive_sk() != 1) goto err; if (test_sphincs_wots_chain() != 1) goto err; if (test_sphincs_wots_sk_to_pk() != 1) goto err; if (test_sphincs_wots_pk_to_root() != 1) goto err; if (test_sphincs_wots_sign() != 1) goto err; if (test_sphincs_wots_sig_to_pk() != 1) goto err; - if (test_sphincs_wots_sign_verify() != 1) goto err; + + if (test_sphincs_xmss_build_auth_path() != 1) goto err; + */ + + //if (test_sphincs_xmss_build_root() != 1) goto err; + //if (test_sphincs_xmss_sign() != 1) goto err; + printf("%s all tests passed\n", __FILE__); return 0;