Botan 3.13.0
Crypto and TLS for C&
sphincsplus.cpp
Go to the documentation of this file.
1/*
2* SLH-DSA - Stateless Hash-Based Digital Signature Standard - FIPS 205
3* (C) 2023 Jack Lloyd
4* 2023 Fabian Albert, René Meusel, Amos Treiber - Rohde & Schwarz Cybersecurity
5*
6* Botan is released under the Simplified BSD License (see license.txt)
7**/
8
9#include <botan/sphincsplus.h>
10
11#include <botan/rng.h>
12#include <botan/internal/buffer_slicer.h>
13#include <botan/internal/buffer_stuffer.h>
14#include <botan/internal/concat_util.h>
15#include <botan/internal/int_utils.h>
16#include <botan/internal/pk_ops_impl.h>
17#include <botan/internal/sp_fors.h>
18#include <botan/internal/sp_hash.h>
19#include <botan/internal/sp_hypertree.h>
20#include <botan/internal/sp_treehash.h>
21#include <botan/internal/sp_types.h>
22#include <botan/internal/sp_wots.h>
23#include <botan/internal/sp_xmss.h>
24
25#include <utility>
26
27#if !defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) and !defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE) and \
28 !defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) and !defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
29static_assert(
30 false,
31 "botan module 'sphincsplus_common' is useful only when enabling at least 'sphincsplus_sha2', 'sphincsplus_shake', 'slh_dsa_sha2', or 'slh_dsa_shake'");
32#endif
33
34namespace Botan {
35
36namespace {
37// FIPS 205, Algorithm 22, line 8
39 const Sphincs_Parameters& params,
41 BOTAN_ARG_CHECK(params.is_slh_dsa() || context.empty(), "Context is not supported for SPHINCS+");
42#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) || defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
43 if(params.is_slh_dsa()) {
44 // prefix (no pre-hash mode): input mode byte + |ctx| + ctx
45 const uint8_t input_mode_byte = 0x00; // Pure (TODO: pre-hash mode: 0x01)
46 return {
48 store_be(input_mode_byte), store_be(checked_cast_to<uint8_t>(context.size())), context),
49 .message = std::move(msg),
50 };
51 }
52#endif
53#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
54 if(!params.is_slh_dsa()) {
55 // SPHINCS+ Round 3.1 uses the message without any prefix
56 return {
57 .prefix = {}, // SPHINCS+ has no prefix
58 .message = std::move(msg),
59 };
60 }
61#endif
62 throw Internal_Error("Missing message preparation logic for SLH-DSA or SPHINCS+");
63}
64} // namespace
65
66class SphincsPlus_PublicKeyInternal final {
67 public:
68 SphincsPlus_PublicKeyInternal(Sphincs_Parameters params,
69 SphincsPublicSeed public_seed,
70 SphincsTreeNode sphincs_root) :
71 m_params(params), m_public_seed(std::move(public_seed)), m_sphincs_root(std::move(sphincs_root)) {}
72
73 SphincsPlus_PublicKeyInternal(Sphincs_Parameters params, std::span<const uint8_t> key_bits) : m_params(params) {
74 if(key_bits.size() != m_params.public_key_bytes()) {
75 throw Decoding_Error("SLH-DSA (or SPHINCS+) Public Key doesn't have the expected length");
76 }
77
78 BufferSlicer s(key_bits);
79 m_public_seed = s.copy<SphincsPublicSeed>(params.n());
80 m_sphincs_root = s.copy<SphincsTreeNode>(params.n());
81
82 BOTAN_ASSERT_NOMSG(s.empty());
83 }
84
85 std::vector<uint8_t> key_bits() const { return concat<std::vector<uint8_t>>(m_public_seed, m_sphincs_root); }
86
87 const SphincsPublicSeed& seed() const { return m_public_seed; }
88
89 const SphincsTreeNode& root() const { return m_sphincs_root; }
90
91 const Sphincs_Parameters& parameters() const { return m_params; }
92
93 private:
94 Sphincs_Parameters m_params;
95 SphincsPublicSeed m_public_seed;
96 SphincsTreeNode m_sphincs_root;
97};
98
99class SphincsPlus_PrivateKeyInternal final {
100 public:
101 SphincsPlus_PrivateKeyInternal(SphincsSecretSeed secret_seed, SphincsSecretPRF prf) :
102 m_secret_seed(std::move(secret_seed)), m_prf(std::move(prf)) {}
103
104 SphincsPlus_PrivateKeyInternal(const Sphincs_Parameters& params, std::span<const uint8_t> key_bits) {
105 if(key_bits.size() != params.private_key_bytes() - params.public_key_bytes()) {
106 throw Decoding_Error("SLH-DSA (or SPHINCS+) Private Key doesn't have the expected length");
107 }
108
109 BufferSlicer s(key_bits);
110 m_secret_seed = s.copy<SphincsSecretSeed>(params.n());
111 m_prf = s.copy<SphincsSecretPRF>(params.n());
112
113 BOTAN_ASSERT_NOMSG(s.empty());
114 }
115
116 const SphincsSecretSeed& seed() const { return m_secret_seed; }
117
118 const SphincsSecretPRF& prf() const { return m_prf; }
119
120 secure_vector<uint8_t> key_bits() const { return concat<secure_vector<uint8_t>>(m_secret_seed, m_prf); }
121
122 private:
123 SphincsSecretSeed m_secret_seed;
124 SphincsSecretPRF m_prf;
125};
126
127SphincsPlus_PublicKey::SphincsPlus_PublicKey(std::span<const uint8_t> pub_key,
129 Sphincs_Hash_Type hash) :
130 SphincsPlus_PublicKey(pub_key, Sphincs_Parameters::create(type, hash)) {}
131
132SphincsPlus_PublicKey::SphincsPlus_PublicKey(std::span<const uint8_t> pub_key, Sphincs_Parameters params) :
133 m_public(std::make_shared<SphincsPlus_PublicKeyInternal>(params, pub_key)) {
134 if(!params.is_available()) {
135 throw Not_Implemented("This SPHINCS+ parameter set is not available in this configuration");
136 }
137}
138
139SphincsPlus_PublicKey::SphincsPlus_PublicKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) :
140 SphincsPlus_PublicKey(key_bits, Sphincs_Parameters::create(alg_id.oid())) {
141 // The parameter set is identified by the OID; no parameters are defined.
142 if(!alg_id.parameters_are_empty()) {
143 throw Decoding_Error("Unexpected parameters for SLH-DSA/SPHINCS+ public key");
144 }
145}
146
148
150 return m_public->parameters().n() * 8;
151}
152
154 return m_public->parameters().is_slh_dsa() ? "SLH-DSA" : "SPHINCS+";
155}
156
158 return m_public->parameters().bitsec();
159}
160
162 return m_public->parameters().algorithm_identifier();
163}
164
166 return m_public->parameters().object_identifier();
167}
168
169bool SphincsPlus_PublicKey::check_key(RandomNumberGenerator& /*rng*/, bool /*strong*/) const {
170 // Nothing to check for the public key. It's literally just hashes. :-)
171 return true;
172}
173
174std::vector<uint8_t> SphincsPlus_PublicKey::raw_public_key_bits() const {
175 return m_public->key_bits();
176}
177
178std::vector<uint8_t> SphincsPlus_PublicKey::public_key_bits() const {
179 // Currently, there isn't a finalized definition of an ASN.1 structure for
180 // SLH-DSA or SPHINCS+ public keys. Therefore, we return the raw public key bits.
181 return raw_public_key_bits();
182}
183
184std::unique_ptr<Private_Key> SphincsPlus_PublicKey::generate_another(RandomNumberGenerator& rng) const {
185 return std::make_unique<SphincsPlus_PrivateKey>(rng, m_public->parameters());
186}
187
188namespace {
189
190class SphincsPlus_Verification_Operation final : public PK_Ops::Verification {
191 public:
192 explicit SphincsPlus_Verification_Operation(std::shared_ptr<const SphincsPlus_PublicKeyInternal> pub_key) :
193 m_public(std::move(pub_key)),
194 m_hashes(Botan::Sphincs_Hash_Functions::create(m_public->parameters(), m_public->seed())),
195 m_context(/* TODO: Add API */ {}) {
196 BOTAN_ARG_CHECK(m_context.size() <= 255, "Context must not exceed 255 bytes");
197
198 if(!m_public->parameters().is_available()) {
199 throw Not_Implemented("This SPHINCS+ parameter set is not available in this configuration");
200 }
201 }
202
203 /**
204 * Add more data to the message currently being signed
205 * @param msg the message
206 */
207 void update(std::span<const uint8_t> msg) override {
208 // TODO(For Pre-Hash Mode): We need to stream the message into a hash function.
209 m_msg_buffer.get().insert(m_msg_buffer.end(), msg.begin(), msg.end());
210 }
211
212 /**
213 * Perform a verification operation
214 */
215 bool is_valid_signature(std::span<const uint8_t> sig) override {
216 const auto internal_msg = prepare_message(std::exchange(m_msg_buffer, {}), m_public->parameters(), m_context);
217 return slh_verify_internal(internal_msg, sig);
218 }
219
220 std::string hash_function() const override { return m_hashes->msg_hash_function_name(); }
221
222 private:
223 /// FIPS 205, Algorithm 20
224 bool slh_verify_internal(const SphincsMessageInternal& msg, std::span<const uint8_t> sig) {
225 const auto& p = m_public->parameters();
226 if(sig.size() != p.sphincs_signature_bytes()) {
227 return false;
228 }
229
230 BufferSlicer s(sig);
231 // Compute leaf and tree index from R
232 const auto msg_random_s = s.take<SphincsMessageRandomness>(p.n());
233 auto [mhash, tree_idx, leaf_idx] = m_hashes->H_msg(msg_random_s, m_public->root(), msg);
234
235 // Reconstruct the FORS tree
236 Sphincs_Address fors_addr(Sphincs_Address_Type::ForsTree);
237 fors_addr.set_tree_address(tree_idx).set_keypair_address(leaf_idx);
238 const auto fors_sig_s = s.take<ForsSignature>(p.fors_signature_bytes());
239 auto fors_root = fors_public_key_from_signature(mhash, fors_sig_s, fors_addr, p, *m_hashes);
240
241 // Verify the hypertree signature
242 const auto ht_sig_s = s.take<SphincsHypertreeSignature>(p.ht_signature_bytes());
243 BOTAN_ASSERT_NOMSG(s.empty());
244 return ht_verify(fors_root, ht_sig_s, m_public->root(), tree_idx, leaf_idx, p, *m_hashes);
245 }
246
247 std::shared_ptr<const SphincsPlus_PublicKeyInternal> m_public;
248 std::unique_ptr<Sphincs_Hash_Functions> m_hashes;
249 SphincsInputMessage m_msg_buffer;
250 SphincsContext m_context;
251};
252
253} // namespace
254
255std::unique_ptr<PK_Ops::Verification> SphincsPlus_PublicKey::create_verification_op(std::string_view /*params*/,
256 std::string_view provider) const {
257 if(provider.empty() || provider == "base") {
258 return std::make_unique<SphincsPlus_Verification_Operation>(m_public);
259 }
260 throw Provider_Not_Found(algo_name(), provider);
261}
262
263std::unique_ptr<PK_Ops::Verification> SphincsPlus_PublicKey::create_x509_verification_op(
264 const AlgorithmIdentifier& signature_algorithm, std::string_view provider) const {
265 if(provider.empty() || provider == "base") {
266 // RFC 9909 Section 3:
267 // The contents of the parameters component for each algorithm MUST be absent.
268 if(signature_algorithm.oid() != this->object_identifier() || !signature_algorithm.parameters_are_empty()) {
269 throw Decoding_Error("Unexpected AlgorithmIdentifier for SLH-DSA (or SPHINCS+) signature");
270 }
271 return std::make_unique<SphincsPlus_Verification_Operation>(m_public);
272 }
273 throw Provider_Not_Found(algo_name(), provider);
274}
275
279
280namespace {
281
282std::span<const uint8_t> slice_off_public_key(const OID& oid, std::span<const uint8_t> key_bits) {
283 const auto params = Sphincs_Parameters::create(oid);
284 // Note: We need to transiently instantiate the `Sphincs_Parameters` object
285 // to know the size of the public/private key. That's slightly
286 // inefficient but was the best we could do. Once we get rid of the
287 // PublicKey-PrivateKey inheritance, we might want to reconsider this
288 // control flow.
289 if(key_bits.size() != params.private_key_bytes()) {
290 throw Decoding_Error("Sphincs Private Key doesn't have the expected length");
291 }
292
293 return key_bits.subspan(params.private_key_bytes() - params.public_key_bytes());
294}
295
296} // namespace
297
298SphincsPlus_PrivateKey::SphincsPlus_PrivateKey(std::span<const uint8_t> private_key,
300 Sphincs_Hash_Type hash) :
301 SphincsPlus_PrivateKey(private_key, Sphincs_Parameters::create(type, hash)) {}
302
303SphincsPlus_PrivateKey::SphincsPlus_PrivateKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) :
304 SphincsPlus_PrivateKey(key_bits, Sphincs_Parameters::create(alg_id.oid())) {
305 // The parameter set is identified by the OID; no parameters are defined.
306 if(!alg_id.parameters_are_empty()) {
307 throw Decoding_Error("Unexpected parameters for SLH-DSA/SPHINCS+ private key");
308 }
309}
310
311SphincsPlus_PrivateKey::SphincsPlus_PrivateKey(std::span<const uint8_t> private_key, Sphincs_Parameters params) :
312 SphincsPlus_PublicKey(slice_off_public_key(params.object_identifier(), private_key), params) {
313 if(!params.is_available()) {
314 throw Not_Implemented("This SPHINCS+ parameter set is not available in this configuration");
315 }
316
317 const auto private_portion_bytes = params.private_key_bytes() - params.public_key_bytes();
318 BOTAN_ASSERT_NOMSG(private_key.size() >= private_portion_bytes);
319
320 m_private = std::make_shared<SphincsPlus_PrivateKeyInternal>(params, private_key.first(private_portion_bytes));
321}
322
327
328// FIPS 205, Algorithm 21
330 if(!params.is_available()) {
331 throw Not_Implemented("This SPHINCS+ parameter set is not available in this configuration");
332 }
333 auto sk_seed = rng.random_vec<SphincsSecretSeed>(params.n());
334 auto sk_prf = rng.random_vec<SphincsSecretPRF>(params.n());
335
336 m_private = std::make_shared<SphincsPlus_PrivateKeyInternal>(std::move(sk_seed), std::move(sk_prf));
337
338 auto pub_seed = rng.random_vec<SphincsPublicSeed>(params.n());
339 auto hashes = Sphincs_Hash_Functions::create(params, pub_seed);
340 auto root = xmss_gen_root(params, m_private->seed(), *hashes);
341
342 m_public = std::make_shared<SphincsPlus_PublicKeyInternal>(params, std::move(pub_seed), std::move(root));
343}
344
346
348 return concat(m_private->key_bits(), m_public->key_bits());
349}
350
354
355std::unique_ptr<Public_Key> SphincsPlus_PrivateKey::public_key() const {
356 return std::make_unique<SphincsPlus_PublicKey>(*this);
357}
358
360 if(strong) {
361 // Check that the embedded public root is consistent with the secret
362 // seed by recomputing it. This costs about as much as a key generation,
363 // but much less than a sign/verify roundtrip.
364 const auto& params = m_public->parameters();
365 auto hashes = Sphincs_Hash_Functions::create(params, m_public->seed());
366 const auto root = xmss_gen_root(params, m_private->seed(), *hashes);
367 return root == m_public->root();
368 }
369 return true;
370}
371
372namespace {
373
374class SphincsPlus_Signature_Operation final : public PK_Ops::Signature {
375 public:
376 SphincsPlus_Signature_Operation(std::shared_ptr<const SphincsPlus_PrivateKeyInternal> private_key,
377 std::shared_ptr<const SphincsPlus_PublicKeyInternal> public_key,
378 bool randomized) :
379 m_private(std::move(private_key)),
380 m_public(std::move(public_key)),
381 m_hashes(Botan::Sphincs_Hash_Functions::create(m_public->parameters(), m_public->seed())),
382 m_randomized(randomized),
383 m_context(/* TODO: add API for context */ {}) {
384 BOTAN_ARG_CHECK(m_context.size() <= 255, "Context must not exceed 255 bytes");
385 BOTAN_ARG_CHECK(m_public->parameters().is_available(),
386 "The selected SLH-DSA (or SPHINCS+) instance is not available in this build.");
387 }
388
389 void update(std::span<const uint8_t> msg) override {
390 // TODO(For Pre-Hash Mode): We need to stream the message into a hash function.
391 m_msg_buffer.get().insert(m_msg_buffer.end(), msg.begin(), msg.end());
392 }
393
394 std::vector<uint8_t> sign(RandomNumberGenerator& rng) override {
395 std::optional<SphincsOptionalRandomness> addrnd = std::nullopt;
396 if(m_randomized) {
397 addrnd = rng.random_vec<SphincsOptionalRandomness>(m_public->parameters().n());
398 }
399 auto internal_msg = prepare_message(std::exchange(m_msg_buffer, {}), m_public->parameters(), m_context);
400
401 return slh_sign_internal(internal_msg, addrnd);
402 }
403
404 size_t signature_length() const override { return m_public->parameters().sphincs_signature_bytes(); }
405
406 AlgorithmIdentifier algorithm_identifier() const override {
407 return m_public->parameters().algorithm_identifier();
408 }
409
410 std::string hash_function() const override { return m_hashes->msg_hash_function_name(); }
411
412 private:
413 // FIPS 205, Algorithm 19
414 std::vector<uint8_t> slh_sign_internal(const SphincsMessageInternal& message,
415 std::optional<StrongSpan<const SphincsOptionalRandomness>> addrnd) {
416 const auto& p = m_public->parameters();
417
418 std::vector<uint8_t> sphincs_sig_buffer(p.sphincs_signature_bytes());
419 BufferStuffer sphincs_sig(sphincs_sig_buffer);
420
421 // Compute and append the digest randomization value (R of spec).
422 // Use addrng for the randomized variant. Use the public seed for the deterministic one.
423 const auto opt_rand =
424 (addrnd.has_value()) ? addrnd.value() : StrongSpan<const SphincsOptionalRandomness>(m_public->seed());
425
426 auto msg_random_s = sphincs_sig.next<SphincsMessageRandomness>(p.n());
427 m_hashes->PRF_msg(msg_random_s, m_private->prf(), opt_rand, message);
428
429 // Derive the message digest and leaf index from R, PK and M.
430 auto [mhash, tree_idx, leaf_idx] = m_hashes->H_msg(msg_random_s, m_public->root(), message);
431
432 // Compute and append the FORS signature
433 Sphincs_Address fors_addr(Sphincs_Address_Type::ForsTree);
434 fors_addr.set_tree_address(tree_idx).set_keypair_address(leaf_idx);
435 auto fors_root = fors_sign_and_pkgen(sphincs_sig.next<ForsSignature>(p.fors_signature_bytes()),
436 mhash,
437 m_private->seed(),
438 fors_addr,
439 p,
440 *m_hashes);
441
442 // Compute and append the XMSS hypertree signature
443 ht_sign(sphincs_sig.next<SphincsHypertreeSignature>(p.ht_signature_bytes()),
444 fors_root,
445 m_private->seed(),
446 tree_idx,
447 leaf_idx,
448 p,
449 *m_hashes);
450
451 BOTAN_ASSERT_NOMSG(sphincs_sig.full());
452 return sphincs_sig_buffer;
453 }
454
455 std::shared_ptr<const SphincsPlus_PrivateKeyInternal> m_private;
456 std::shared_ptr<const SphincsPlus_PublicKeyInternal> m_public;
457 std::unique_ptr<Sphincs_Hash_Functions> m_hashes;
458 SphincsInputMessage m_msg_buffer;
459 bool m_randomized;
460 SphincsContext m_context;
461};
462
463} // namespace
464
466 std::string_view params,
467 std::string_view provider) const {
468 BOTAN_UNUSED(rng);
469 BOTAN_ARG_CHECK(params.empty() || params == "Deterministic" || params == "Randomized",
470 "Unexpected parameters for signing with SLH-DSA (or SPHINCS+)");
471
472 // FIPS 205, Section 9.2
473 // The hedged variant is the default and should be used on platforms where
474 // side-channel attacks are a concern.
475 const bool randomized = (params.empty() || params == "Randomized");
476 if(provider.empty() || provider == "base") {
477 return std::make_unique<SphincsPlus_Signature_Operation>(m_private, m_public, randomized);
478 }
479 throw Provider_Not_Found(algo_name(), provider);
480}
481
482} // namespace Botan
#define BOTAN_UNUSED
Definition assert.h:144
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:33
bool parameters_are_empty() const
Definition asn1_obj.h:715
const OID & oid() const
Definition asn1_obj.h:688
void random_vec(std::span< uint8_t > v)
Definition rng.h:244
secure_vector< uint8_t > raw_private_key_bits() const override
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, std::string_view params, std::string_view provider) const override
SphincsPlus_PrivateKey(std::span< const uint8_t > private_key, Sphincs_Parameter_Set type, Sphincs_Hash_Type hash)
secure_vector< uint8_t > private_key_bits() const override
bool check_key(RandomNumberGenerator &rng, bool strong) const override
std::unique_ptr< Public_Key > public_key() const override
std::vector< uint8_t > public_key_bits() const override
std::vector< uint8_t > raw_public_key_bits() const override
std::shared_ptr< const SphincsPlus_PublicKeyInternal > m_public
Definition sphincsplus.h:68
std::unique_ptr< PK_Ops::Verification > create_x509_verification_op(const AlgorithmIdentifier &signature_algorithm, std::string_view provider) const override
std::unique_ptr< PK_Ops::Verification > create_verification_op(std::string_view params, std::string_view provider) const override
bool supports_operation(PublicKeyOperation op) const override
std::string algo_name() const override
size_t key_length() const override
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const final
bool check_key(RandomNumberGenerator &rng, bool strong) const override
AlgorithmIdentifier algorithm_identifier() const override
size_t estimated_strength() const override
SphincsPlus_PublicKey(std::span< const uint8_t > pub_key, Sphincs_Parameter_Set type, Sphincs_Hash_Type hash)
OID object_identifier() const override
static std::unique_ptr< Sphincs_Hash_Functions > create(const Sphincs_Parameters &sphincs_params, const SphincsPublicSeed &pub_seed)
Definition sp_hash.cpp:32
uint32_t private_key_bytes() const
uint32_t public_key_bytes() const
static Sphincs_Parameters create(Sphincs_Parameter_Set set, Sphincs_Hash_Type hash)
Gf448Elem root(const Gf448Elem &elem)
Compute the root of elem in the field.
Strong< std::vector< uint8_t >, struct SphincsTreeNode_ > SphincsTreeNode
Either an XMSS or FORS tree node or leaf.
Definition sp_types.h:70
SphincsTreeNode xmss_gen_root(const Sphincs_Parameters &params, const SphincsSecretSeed &secret_seed, Sphincs_Hash_Functions &hashes)
Definition sp_xmss.cpp:58
Strong< secure_vector< uint8_t >, struct SphincsMessageRandomness_ > SphincsMessageRandomness
Definition sp_types.h:64
Sphincs_Parameter_Set
SphincsTreeNode fors_sign_and_pkgen(StrongSpan< ForsSignature > sig_out, const SphincsHashedMessage &hashed_message, const SphincsSecretSeed &secret_seed, const Sphincs_Address &address, const Sphincs_Parameters &params, Sphincs_Hash_Functions &hashes)
FIPS 205, Algorithm 16: fors_sign (with simultaneous FORS pk generation).
Definition sp_fors.cpp:63
Strong< std::vector< uint8_t >, struct ForsSignature_ > ForsSignature
Definition sp_types.h:72
constexpr RT checked_cast_to(AT i)
Definition int_utils.h:104
void ht_sign(StrongSpan< SphincsHypertreeSignature > out_sig, const SphincsTreeNode &message_to_sign, const SphincsSecretSeed &secret_seed, XmssTreeIndexInLayer tree_index_in_layer, TreeNodeIndex idx_leaf, const Sphincs_Parameters &params, Sphincs_Hash_Functions &hashes)
FIPS 205, Algorithm 12: ht_sign.
Sphincs_Hash_Type
bool ht_verify(const SphincsTreeNode &signed_msg, StrongSpan< const SphincsHypertreeSignature > ht_sig, const SphincsTreeNode &pk_root, XmssTreeIndexInLayer tree_index_in_layer, TreeNodeIndex idx_leaf, const Sphincs_Parameters &params, Sphincs_Hash_Functions &hashes)
FIPS 205, Algorithm 13: ht_verify.
Strong< std::vector< uint8_t >, struct SphincsXmssSignature_ > SphincsHypertreeSignature
Definition sp_types.h:66
Strong< std::vector< uint8_t >, struct SphincsInputMessage_ > SphincsInputMessage
Definition sp_types.h:49
Strong< std::vector< uint8_t >, struct SphincsPublicSeed_ > SphincsPublicSeed
Definition sp_types.h:60
Strong< secure_vector< uint8_t >, struct SphincsSecretSeed_ > SphincsSecretSeed
Definition sp_types.h:61
Strong< secure_vector< uint8_t >, struct SphincsSecretPRF_ > SphincsSecretPRF
Definition sp_types.h:62
PublicKeyOperation
Definition pk_keys.h:46
constexpr auto concat(Rs &&... ranges)
Definition concat_util.h:90
SphincsTreeNode fors_public_key_from_signature(const SphincsHashedMessage &hashed_message, StrongSpan< const ForsSignature > signature, const Sphincs_Address &address, const Sphincs_Parameters &params, Sphincs_Hash_Functions &hashes)
FIPS 205, Algorithm 17: fors_pkFromSig.
Definition sp_fors.cpp:130
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:128
Strong< secure_vector< uint8_t >, struct SphincsOptionalRandomness_ > SphincsOptionalRandomness
Definition sp_types.h:63
constexpr auto store_be(ParamTs &&... params)
Definition loadstor.h:745
Strong< std::vector< uint8_t >, struct SphincsContext_ > SphincsContext
Definition sp_types.h:57
M' representation of FIPS 205 (the input to slh_sign_internal and slh_verify_internal).
Definition sp_types.h:52