Add SPHINCS+

This commit is contained in:
Zhi Guan
2026-01-06 21:59:21 +08:00
parent bd80a3d628
commit 22a9340576
3 changed files with 691 additions and 2 deletions

184
include/gmssl/sphincs.h Normal file
View File

@@ -0,0 +1,184 @@
/*
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#ifndef GMSSL_SPHINCS_H
#define GMSSL_SPHINCS_H
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <gmssl/sm3.h>
#include <gmssl/hash256.h>
#ifdef ENABLE_SHA2
#include <gmssl/sha2.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if defined(ENABLE_SPHINCS_CROSSCHECK) && defined(ENABLE_SHA2)
# define HASH256_CTX SHA256_CTX
# define hash256_init sha256_init
# define hash256_update sha256_update
# define hash256_finish sha256_finish
# define HASH256_BLOCK_SIZE SHA256_BLOCK_SIZE
#else
# define HASH256_CTX SM3_CTX
# define hash256_init sm3_init
# define hash256_update sm3_update
# define hash256_finish sm3_finish
# define HASH256_BLOCK_SIZE SM3_BLOCK_SIZE
#endif
/*
In order to make keeping track of the types easier throughout the pseudo-code in the rest of
this document, we refer to them respectively using the constants WOTS_HASH, WOTS_PK, TREE,
FORS_TREE, FORS_ROOTS, WOTS_PRF, and FORS_PRF.
*/
enum {
SPHINCS_ADRS_TYPE_WOTS_PRF = 0,
SPHINCS_ADRS_TYPE_WOTS_PK = 1,
SPHINCS_ADRS_TYPE_HASHTREE = 2,
SPHINCS_ADRS_TYPE_FORS_TREE = 3,
SPHINCS_ADRS_TYPE_FORS_ROOT = 4,
SPHINCS_ADRS_TYPE_WOTS_KEYGEN = 5,
SPHINCS_ADRS_TYPE_FORS_KEYGEN = 6,
};
typedef uint8_t sphincs_adrs_t[32];
typedef struct {
uint32_t layer_address;
uint32_t tree_address[3];
uint32_t type; // = 0
uint32_t keypair_address;
uint32_t chain_address;
uint32_t hash_address;
} SPHINCS_ADRS_WOTS_HASH;
void sphincs_adrs_copy_layer_address(sphincs_adrs_t dst, const sphincs_adrs_t src);
void sphincs_adrs_copy_tree_address(sphincs_adrs_t dst, const sphincs_adrs_t src);
void sphincs_adrs_copy_type(sphincs_adrs_t dst, const sphincs_adrs_t src);
void sphincs_adrs_copy_keypair_address(sphincs_adrs_t dst, const sphincs_adrs_t src);
void sphincs_adrs_copy_chain_address(sphincs_adrs_t dst, const sphincs_adrs_t src);
void sphincs_adrs_copy_hash_address(sphincs_adrs_t dst, const sphincs_adrs_t src);
void sphincs_adrs_set_layer_address(sphincs_adrs_t adrs, const uint32_t address);
void sphincs_adrs_set_tree_address(sphincs_adrs_t adrs, const uint64_t address);
void sphincs_adrs_set_type(sphincs_adrs_t adrs, const uint32_t type);
void sphincs_adrs_set_keypair_address(sphincs_adrs_t adrs, const uint32_t address);
void sphincs_adrs_set_chain_address(sphincs_adrs_t adrs, const uint32_t address);
void sphincs_adrs_set_hash_address(sphincs_adrs_t adrs, const uint32_t address);
// 所有的padding都在最后是否意味着可以不用padding?
typedef struct {
uint32_t layer_address;
uint32_t tree_address[3];
uint32_t type; // = 1
uint32_t keypair_address;
uint32_t padding[3]; // = {0,0,0}
} SPHINCS_ADRS_WOTS_PK_COMP;
typedef struct {
uint32_t layer_address;
uint32_t tree_address[3];
uint32_t type; // = 2
uint32_t padding; // = 0
uint32_t tree_height;
uint32_t tree_index;
} SPHINCS_ADRS_HASHTREE;
void sphincs_adrs_copy_tree_height(sphincs_adrs_t dst, const sphincs_adrs_t src);
void sphincs_adrs_copy_tree_index(sphincs_adrs_t dst, const sphincs_adrs_t src);
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);
typedef struct {
uint32_t layer_address;
uint32_t tree_address[3];
uint32_t type; // = 3
uint32_t keypair_address;
uint32_t tree_height;
uint32_t tree_index;
} SPHINCS_ADRS_FORS_TREE;
typedef struct {
uint32_t layer_address;
uint32_t tree_address[3];
uint32_t type; // = 4
uint32_t keypair_address;
uint32_t padding[2]; // = {0,0}
} SPHINCS_ADRS_FORS_ROOT;
typedef struct {
uint32_t layer_address;
uint32_t tree_address[3];
uint32_t type; // = 5
uint32_t keypair_address;
uint32_t chain_address;
uint32_t hash_address; // = 0
} SPHINCS_ADRS_WOTS_KEYGEN;
typedef struct {
uint32_t layer_address;
uint32_t tree_address[3];
uint32_t type; // = 6
uint32_t keypair_address;
uint32_t tree_height; // = 0
uint32_t tree_index;
} SPHINCS_ADRS_FORS_KEYGEN;
typedef uint8_t sphincs_adrsc_t[22];
void sphincs_adrs_compress(const sphincs_adrs_t adrs, sphincs_adrsc_t adrsc);
// 这里比较奇怪的是fors的参数以及哈希值是多少
// 哈希值被分成两部分一部分用来从hypertree上找到树的地址一个是用于fors的输入
typedef struct {
char *name;
size_t secret_size; // 这个是n当sm3/sha256时n==16
size_t height;
size_t layers;
size_t fors_height;
size_t fors_trees;
int winternitz_w;
int bitsec;
int sec_level;
size_t siglen;
} SPHINCS_PARAMS;
// sizeof(sphincs_secret_t) == n, when sm3/sha256, n == 16
typedef uint8_t sphincs_secret_t[16];
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);
typedef sphincs_secret_t sphincs_wots_key_t[35];
typedef sphincs_secret_t sphincs_wots_sig_t[35];
void sphincs_wots_derive_sk(const sphincs_secret_t secret,
const sphincs_secret_t seed, const sphincs_adrs_t adrs,
sphincs_wots_key_t sk);
#ifdef __cplusplus
}
#endif
#endif