Update xmss.c

This commit is contained in:
Zhi Guan
2026-01-04 15:51:18 +08:00
parent 14e4edede7
commit 456945781d

View File

@@ -37,7 +37,7 @@ static const uint8_t bn256_one[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
};
static const uint8_t bn256_two[] = {
static const uint8_t hash256_two[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -1188,7 +1188,7 @@ int xmss_sign_init(XMSS_SIGN_CTX *ctx, XMSS_KEY *key)
// H_msg(M) := HASH256(toByte(2, 32) || r || XMSS_ROOT || toByte(idx_sig, 32) || M)
hash256_init(&ctx->hash256_ctx);
hash256_update(&ctx->hash256_ctx, bn256_two, 32);
hash256_update(&ctx->hash256_ctx, hash256_two, 32);
hash256_update(&ctx->hash256_ctx, ctx->xmss_sig.random, 32);
hash256_update(&ctx->hash256_ctx, key->public_key.root, 32);
hash256_update(&ctx->hash256_ctx, index_buf, 32);
@@ -1254,7 +1254,7 @@ int xmss_verify_init(XMSS_SIGN_CTX *ctx, const XMSS_KEY *key, const uint8_t *sig
PUTU32(sig_index + 28, ctx->xmss_sig.index);
hash256_init(&ctx->hash256_ctx);
hash256_update(&ctx->hash256_ctx, bn256_two, 32);
hash256_update(&ctx->hash256_ctx, hash256_two, 32);
hash256_update(&ctx->hash256_ctx, ctx->xmss_sig.random, 32);
hash256_update(&ctx->hash256_ctx, key->public_key.root, 32);
hash256_update(&ctx->hash256_ctx, sig_index, 32);
@@ -1539,6 +1539,10 @@ int xmssmt_private_key_from_bytes(XMSSMT_KEY *key, const uint8_t **in, size_t *i
return 1;
}
// XMSSMT的密钥生成和密钥更新都是完全一样的
// 密钥生成的区别是需要生成最高层
int xmssmt_key_generate(XMSSMT_KEY *key, uint32_t xmssmt_type)
{
size_t height;
@@ -1548,6 +1552,14 @@ int xmssmt_key_generate(XMSSMT_KEY *key, uint32_t xmssmt_type)
hash256_t *tree;
uint8_t *xmss_root;
uint64_t index = 0;
uint64_t tree_address;
uint32_t tree_index;
if (!key) {
error_print();
return -1;
@@ -1586,59 +1598,67 @@ int xmssmt_key_generate(XMSSMT_KEY *key, uint32_t xmssmt_type)
error_print();
return -1;
}
tree = key->trees;
for (layer = 0; layer < layers - 1; layer++) {
// generate the leftmost tree of the level
for (layer = 0; layer < layers; layer++) {
// generate tree of the layer
adrs_set_layer_address(adrs, layer);
adrs_set_tree_address(adrs, 0);
adrs_set_tree_address(adrs, xmssmt_tree_address(index, height, layers, layer));
xmss_build_tree(key->secret, key->public_key.seed, adrs, height/layers, tree);
xmss_root = tree[tree_root_offset(height/layers)];
// sign xmss_root with higher layer
if (layer < layers - 1) {
adrs_set_layer_address(adrs, layer + 1);
adrs_set_tree_address(adrs, 0);
adrs_set_tree_address(adrs, xmssmt_tree_address(index, height, layers, layer + 1));
adrs_set_type(adrs, XMSS_ADRS_TYPE_OTS);
adrs_set_ots_address(adrs, 0); // 具体值由index决定
adrs_set_ots_address(adrs, xmssmt_tree_index(index, height, layers, layer + 1));
wots_derive_sk(key->secret, key->public_key.seed, adrs, key->wots_sigs[layer]);
//tree = key->trees + xmss_tree_num_nodes(height/layers) * layer;
xmss_root = tree[tree_root_offset(height/layers)];
wots_sign(key->wots_sigs[layer], key->public_key.seed, adrs, xmss_root, key->wots_sigs[layer]);
tree += tree_root_offset(height/layers) + 1;
tree += xmss_tree_num_nodes(height/layers);
}
}
// highest layer (without signatures)
adrs_set_layer_address(adrs, layer);
adrs_set_tree_address(adrs, 0);
xmss_build_tree(key->secret, key->public_key.seed, adrs, height/layers, tree);
xmss_root = tree[tree_root_offset(height/layers)];
// copy the top-level root
memcpy(key->public_key.root, xmss_root, sizeof(hash256_t));
tree = key->trees;
hash256_t root;
size_t i;
wots_key_t wots_pk;
for (i = 0; i < layers - 1; i++) {
adrs_set_layer_address(adrs, i + 1);
adrs_set_tree_address(adrs, 0); //
adrs_set_type(adrs, XMSS_ADRS_TYPE_OTS);
adrs_set_ots_address(adrs, 0); // FIXME: value from index
for (layer = 0; layer < layers - 1; layer++) {
uint8_t *dgst = tree[tree_root_offset(height/layers)];
wots_sig_to_pk(key->wots_sigs[i], key->public_key.seed, adrs, dgst, wots_pk);
tree_address = xmssmt_tree_address(index, height, layers, layer + 1);
tree_index = xmssmt_tree_index(index, height, layers, layer + 1);
adrs_set_layer_address(adrs, layer + 1);
adrs_set_tree_address(adrs, tree_address);
adrs_set_type(adrs, XMSS_ADRS_TYPE_OTS);
adrs_set_ots_address(adrs, tree_index);
wots_sig_to_pk(key->wots_sigs[layer], key->public_key.seed, adrs, dgst, wots_pk);
adrs_set_type(adrs, XMSS_ADRS_TYPE_LTREE);
adrs_set_tree_index(adrs, 0); //
adrs_set_tree_index(adrs, tree_index);
wots_pk_to_root(wots_pk, key->public_key.seed, adrs, root);
tree += xmss_tree_num_nodes(height/layers);
@@ -2007,12 +2027,62 @@ int xmssmt_signature_print(FILE *fp, int fmt, int ind, const char *label, const
return 1;
}
int xmssmt_sign_init(XMSSMT_SIGN_CTX *ctx, XMSSMT_KEY *key)
int xmssmt_key_update(XMSSMT_KEY *key)
{
hash256_t hash256_index = {0};
xmss_adrs_t adrs;
size_t height;
size_t layers;
size_t layer;
if (xmssmt_type_to_height_and_layers(key->public_key.xmssmt_type, &height, &layers) != 1) {
error_print();
return -1;
}
// 这里我们要检查当前的layer
for (layer = layers - 1; layer > 0; layer--) {
}
if (layer >= layers ) {
}
if (layer == 0) {
return 0;
}
for (; layer < layers; layer++) {
}
return 1;
}
int xmssmt_sign_init(XMSSMT_SIGN_CTX *ctx, XMSSMT_KEY *key)
{
size_t height;
size_t layers;
size_t layer;
uint64_t tree_address;
uint32_t tree_index;
hash256_t hash256_index;
xmss_adrs_t adrs;
if (!ctx || !key) {
error_print();
@@ -2022,56 +2092,67 @@ int xmssmt_sign_init(XMSSMT_SIGN_CTX *ctx, XMSSMT_KEY *key)
error_print();
return -1;
}
memset(ctx, 0, sizeof(*ctx));
// cache public key
// init sign ctx
memset(ctx, 0, sizeof(XMSSMT_SIGN_CTX));
// set ctx->xmssmt_public_key
ctx->xmssmt_public_key = key->public_key;
// key->index => xmssmt_sig.index
// copy index
ctx->xmssmt_sig.index = key->index;
// copy wots_sigs[1] to wots_sig[layers - 1] from key
for (layer = 1; layer < layers; layer++) {
memcpy(ctx->xmssmt_sig.wots_sigs[layer], key->wots_sigs[layer - 1], sizeof(wots_sig_t));
}
// build auth_path
for (layer = 0; layer < layers; layer++) {
hash256_t *tree;
hash256_t *auth_path;
tree = key->trees + xmss_tree_num_nodes(height/layers) * layer;
tree_index = xmssmt_tree_index(ctx->xmssmt_sig.index, height, layers, layer);
auth_path = ctx->xmssmt_sig.auth_path + (height/layers) * layer;
xmss_build_auth_path(tree, height/layers, tree_index, auth_path);
}
// derive ctx->xmssmt_sig.random
PUTU64(hash256_index + 24, key->index);
// r = PRF(SK_PRF, toByte(idx_sig, 32));
memset(hash256_index, 0, 24);
PUTU64(hash256_index + 24, ctx->xmssmt_sig.index);
hash256_init(&ctx->hash256_ctx);
hash256_update(&ctx->hash256_ctx, hash256_three, 32);
hash256_update(&ctx->hash256_ctx, key->sk_prf, 32);
hash256_update(&ctx->hash256_ctx, hash256_index, 32);
hash256_update(&ctx->hash256_ctx, hash256_three, sizeof(hash256_t));
hash256_update(&ctx->hash256_ctx, key->sk_prf, sizeof(hash256_t));
hash256_update(&ctx->hash256_ctx, hash256_index, sizeof(hash256_t));
hash256_finish(&ctx->hash256_ctx, ctx->xmssmt_sig.random);
// wots_sk => ctx->xmss_sig.wots_sig
adrs_set_layer_address(adrs, 0);
adrs_set_tree_address(adrs, 0); //
// derive wots_sk and save to wots_sigs[0]
layer = 0;
tree_address = xmssmt_tree_address(ctx->xmssmt_sig.index, height, layers, layer);
tree_index = xmssmt_tree_index(ctx->xmssmt_sig.index, height, layers, layer);
adrs_set_layer_address(adrs, layer);
adrs_set_tree_address(adrs, tree_address);
adrs_set_type(adrs, XMSS_ADRS_TYPE_OTS);
adrs_set_ots_address(adrs, key->index); //
adrs_set_ots_address(adrs, tree_index);
wots_derive_sk(key->secret, key->public_key.seed, adrs, ctx->xmssmt_sig.wots_sigs[0]);
//
// xmss_sig.auth_path
xmss_build_auth_path(key->trees, height, key->index, ctx->xmssmt_sig.auth_path);
// update key->index
key->index++;
// H_msg(M) := HASH256(toByte(2, 32) || r || XMSS_ROOT || toByte(idx_sig, 32) || M)
hash256_init(&ctx->hash256_ctx);
hash256_update(&ctx->hash256_ctx, bn256_two, 32);
hash256_update(&ctx->hash256_ctx, ctx->xmssmt_sig.random, 32);
hash256_update(&ctx->hash256_ctx, key->public_key.root, 32);
hash256_update(&ctx->hash256_ctx, hash256_index, 32);
hash256_update(&ctx->hash256_ctx, hash256_two, sizeof(hash256_t));
hash256_update(&ctx->hash256_ctx, ctx->xmssmt_sig.random, sizeof(hash256_t));
hash256_update(&ctx->hash256_ctx, key->public_key.root, sizeof(hash256_t));
hash256_update(&ctx->hash256_ctx, hash256_index, sizeof(hash256_t));
size_t remaining_signs;
size_t i;
for (i = 0; i < layers; i++) {
// 增加key_update
if (remaining_signs == 0) {
}
return -1;
return 1;
}
int xmssmt_sign_update(XMSSMT_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
@@ -2088,77 +2169,192 @@ int xmssmt_sign_update(XMSSMT_SIGN_CTX *ctx, const uint8_t *data, size_t datalen
int xmssmt_sign_finish_ex(XMSSMT_SIGN_CTX *ctx, XMSSMT_SIGNATURE *sig)
{
xmss_adrs_t adrs;
// generate message wots_sig as wots_sigs[0]
size_t height;
size_t layers;
size_t layer = 0;
uint64_t tree_address;
uint8_t dgst[32];
uint32_t tree_index;
xmss_adrs_t adrs;
hash256_t dgst;
if (!ctx || !sig) {
error_print();
return -1;
}
hash256_finish(&ctx->hash256_ctx, dgst);
if (xmssmt_type_to_height_and_layers(ctx->xmssmt_public_key.xmssmt_type, &height, &layers) != 1) {
error_print();
return -1;
}
tree_address = xmssmt_tree_address(ctx->xmssmt_sig.index, height, layers, layer);
tree_index = xmssmt_tree_index(ctx->xmssmt_sig.index, height, layers, layer);
tree_address = sig->index / layers;
hash256_finish(&ctx->hash256_ctx, dgst);
adrs_set_layer_address(adrs, 0);
adrs_set_layer_address(adrs, layer);
adrs_set_tree_address(adrs, tree_address);
adrs_set_type(adrs, XMSS_ADRS_TYPE_OTS);
adrs_set_ots_address(adrs, ctx->xmssmt_sig.index);
adrs_set_ots_address(adrs, tree_index);
wots_sign(ctx->xmssmt_sig.wots_sigs[0], ctx->xmssmt_public_key.seed, adrs, dgst,
ctx->xmssmt_sig.wots_sigs[0]);
*sig = ctx->xmssmt_sig;
return 1;
}
int xmssmt_sign_finish(XMSSMT_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen)
{
XMSSMT_SIGNATURE signature;
if (!ctx || !sig || !siglen) {
error_print();
return -1;
}
if (xmssmt_sign_finish_ex(ctx, &signature) != 1) {
error_print();
return -1;
}
*siglen = 0;
if (xmssmt_signature_to_bytes(&ctx->xmssmt_sig, ctx->xmssmt_public_key.xmssmt_type, &sig, siglen) != 1) {
error_print();
return -1;
}
return -1;
return 1;
}
int xmssmt_verify_init_ex(XMSSMT_SIGN_CTX *ctx, const XMSSMT_KEY *key, const XMSSMT_SIGNATURE *sig)
{
hash256_t hash256_index;
xmss_adrs_t adrs;
if (!ctx || !key || !sig) {
error_print();
return -1;
}
return -1;
// init sign ctx
memset(ctx, 0, sizeof(XMSSMT_SIGN_CTX));
// set ctx->xmssmt_public_key
ctx->xmssmt_public_key = key->public_key;
// copy ctx->xmssmt_sig
ctx->xmssmt_sig = *sig;
memset(hash256_index, 0, 24);
PUTU64(hash256_index + 24, ctx->xmssmt_sig.index);
// H_msg(M) := HASH256(toByte(2, 32) || r || XMSS_ROOT || toByte(idx_sig, 32) || M)
hash256_init(&ctx->hash256_ctx);
hash256_update(&ctx->hash256_ctx, hash256_two, sizeof(hash256_t));
hash256_update(&ctx->hash256_ctx, ctx->xmssmt_sig.random, sizeof(hash256_t));
hash256_update(&ctx->hash256_ctx, key->public_key.root, sizeof(hash256_t));
hash256_update(&ctx->hash256_ctx, hash256_index, sizeof(hash256_t));
return 1;
}
int xmssmt_verify_init(XMSSMT_SIGN_CTX *ctx, const XMSSMT_KEY *key, const uint8_t *sig, size_t siglen)
{
hash256_t hash256_index;
xmss_adrs_t adrs;
if (!ctx || !key || !sig) {
error_print();
return -1;
}
// init sign ctx
memset(ctx, 0, sizeof(XMSSMT_SIGN_CTX));
// set ctx->xmssmt_public_key
ctx->xmssmt_public_key = key->public_key;
if (xmssmt_signature_from_bytes(&ctx->xmssmt_sig, key->public_key.xmssmt_type, &sig, &siglen) != 1) {
error_print();
return -1;
}
if (siglen) {
error_print();
return -1;
}
memset(hash256_index, 0, 24);
PUTU64(hash256_index + 24, ctx->xmssmt_sig.index);
// H_msg(M) := HASH256(toByte(2, 32) || r || XMSS_ROOT || toByte(idx_sig, 32) || M)
hash256_init(&ctx->hash256_ctx);
hash256_update(&ctx->hash256_ctx, hash256_two, sizeof(hash256_t));
hash256_update(&ctx->hash256_ctx, ctx->xmssmt_sig.random, sizeof(hash256_t));
hash256_update(&ctx->hash256_ctx, key->public_key.root, sizeof(hash256_t));
hash256_update(&ctx->hash256_ctx, hash256_index, sizeof(hash256_t));
return 1;
}
int xmssmt_verify_update(XMSSMT_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
{
if (!ctx) {
error_print();
return -1;
}
if (data && datalen) {
hash256_update(&ctx->hash256_ctx, data, datalen);
}
return 1;
}
int xmssmt_verify_finish(XMSSMT_SIGN_CTX *ctx)
{
size_t height;
size_t layers;
size_t layer;
xmss_adrs_t adrs;
hash256_t dgst;
hash256_finish(&ctx->hash256_ctx, dgst);
if (xmssmt_type_to_height_and_layers(ctx->xmssmt_public_key.xmssmt_type, &height, &layers) != 1) {
error_print();
return -1;
}
for (layer = 0; layer < layers; layer++) {
uint64_t tree_address = xmssmt_tree_address(ctx->xmssmt_sig.index, height, layers, layer);
uint32_t tree_index = xmssmt_tree_index(ctx->xmssmt_sig.index, height, layers, layer);
wots_key_t wots_pk;
// wots_sig, dgst => wots_pk
adrs_set_layer_address(adrs, layer);
adrs_set_tree_address(adrs, tree_address);
adrs_set_type(adrs, XMSS_ADRS_TYPE_OTS);
adrs_set_ots_address(adrs, tree_index);
wots_sig_to_pk(ctx->xmssmt_sig.wots_sigs[layer], ctx->xmssmt_public_key.seed, adrs, dgst, wots_pk);
// wots_pk => wots_root
adrs_set_type(adrs, XMSS_ADRS_TYPE_LTREE);
adrs_set_ltree_address(adrs, tree_index);
wots_pk_to_root(wots_pk, ctx->xmssmt_public_key.seed, adrs, dgst);
// wots_root, auth_path => xmss_root (as dgst)
adrs_set_type(adrs, XMSS_ADRS_TYPE_HASHTREE);
adrs_set_padding(adrs, 0);
xmss_build_root(dgst, tree_index,
ctx->xmssmt_public_key.seed, adrs,
ctx->xmssmt_sig.auth_path + (height/layers) * layer, height/layers,
dgst);
}
// verify xmssmt_root (save in dgst)
if (memcmp(dgst, ctx->xmssmt_public_key.root, sizeof(hash256_t)) != 0) {
error_print();
return -1;
}
return 1;
}