Skip to content

Commit

Permalink
SLH-DSA integration into SPHINCS+
Browse files Browse the repository at this point in the history
This commit applies the changes from SPHINCS+ Round 3.1 to SLH-DSA.
The documentation is updated accordingly.
  • Loading branch information
FAlbertDev committed Sep 12, 2024
1 parent 0639e82 commit 6d4dacf
Show file tree
Hide file tree
Showing 42 changed files with 977 additions and 366 deletions.
17 changes: 9 additions & 8 deletions doc/api_ref/pubkey.rst
Original file line number Diff line number Diff line change
Expand Up @@ -145,19 +145,20 @@ signatures, then the whole scheme becomes insecure, and signatures can be
forged.

HSS-LMS
-------
~~~~~~~

A post-quantum secure hash-based signature scheme similar to XMSS. Contains
support for multitrees. It is stateful, meaning the private key changes after
each signature.

SPHINCS+
~~~~~~~~~
SLH-DSA
~~~~~~~

A post-quantum secure signature scheme whose security is based (only) on the
security of a hash function. Unlike XMSS, it is a stateless signature
scheme, meaning that the private key does not change with each signature. It
has high security but very long signatures and high runtime.
The Stateless Hash-Based Digital Signature Standard (SLH-DSA)
is the FIPS 205 post-quantum secure signature scheme whose security is solely
based on the security of a hash function. Unlike XMSS, it is a stateless
signature scheme, meaning that the private key does not change with each
signature. It has high security but very long signatures and high runtime.

FrodoKEM
~~~~~~~~
Expand Down Expand Up @@ -807,7 +808,7 @@ Botan implements the following signature algorithms:

#. Dilithium.
Takes the optional parameter ``Deterministic`` (default) or ``Randomized``.
#. SPHINCS+.
#. SLH-DSA.
Takes the optional parameter ``Deterministic`` (default) or ``Randomized``.
#. XMSS. Takes no parameter.
#. HSS-LMS. Takes no parameter.
Expand Down
4 changes: 2 additions & 2 deletions doc/credits.rst
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ snail-mail address (S), and Bitcoin address (B).
N: René Meusel
E: [email protected]
W: https://www.rohde-schwarz.com/cybersecurity
D: CI, TLS 1.3, Kyber, Dilithium, SPHINCS+, FrodoKEM
D: CI, TLS 1.3, Kyber, Dilithium, SLH-DSA, FrodoKEM
S: Berlin, Germany

N: Philippe Lieser
Expand All @@ -175,5 +175,5 @@ snail-mail address (S), and Bitcoin address (B).
N: Fabian Albert
E: [email protected]
W: https://www.rohde-schwarz.com/cybersecurity
D: SPHINCS+, HSS/LMS
D: SLH-DSA, HSS/LMS
S: Bochum, Germany
2 changes: 1 addition & 1 deletion readme.rst
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ Public Key Cryptography
* RSA signatures and encryption
* DH and ECDH key agreement
* Signature schemes ECDSA, DSA, Ed25519, Ed448, ECGDSA, ECKCDSA, SM2, GOST 34.10
* Post-quantum signature schemes Dilithium, HSS/LMS, SPHINCS+, XMSS
* Post-quantum signature schemes Dilithium, HSS/LMS, SLH-DSA, XMSS
* Post-quantum key agreement schemes McEliece, Kyber, and FrodoKEM
* ElGamal encryption
* Padding schemes OAEP, PSS, PKCS #1 v1.5, X9.31
Expand Down
28 changes: 28 additions & 0 deletions src/build-data/oids.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,34 @@
1.3.6.1.4.1.25258.1.12.3.5 = SphincsPlus-haraka-256s-r3.1
1.3.6.1.4.1.25258.1.12.3.6 = SphincsPlus-haraka-256f-r3.1

# NIST: SLH-DSA
2.16.840.1.101.3.4.3.20 = SLH-DSA-SHA2-128s
2.16.840.1.101.3.4.3.21 = SLH-DSA-SHA2-128f
2.16.840.1.101.3.4.3.22 = SLH-DSA-SHA2-192s
2.16.840.1.101.3.4.3.23 = SLH-DSA-SHA2-192f
2.16.840.1.101.3.4.3.24 = SLH-DSA-SHA2-256s
2.16.840.1.101.3.4.3.25 = SLH-DSA-SHA2-256f
2.16.840.1.101.3.4.3.26 = SLH-DSA-SHAKE-128s
2.16.840.1.101.3.4.3.27 = SLH-DSA-SHAKE-128f
2.16.840.1.101.3.4.3.28 = SLH-DSA-SHAKE-192s
2.16.840.1.101.3.4.3.29 = SLH-DSA-SHAKE-192f
2.16.840.1.101.3.4.3.30 = SLH-DSA-SHAKE-256s
2.16.840.1.101.3.4.3.31 = SLH-DSA-SHAKE-256f

# NIST: SLH-DSA (pre-hash)
2.16.840.1.101.3.4.3.20 = Hash-SLH-DSA-SHA2-128s-with-SHA256
2.16.840.1.101.3.4.3.21 = Hash-SLH-DSA-SHA2-128f-with-SHA256
2.16.840.1.101.3.4.3.22 = Hash-SLH-DSA-SHA2-192s-with-SHA512
2.16.840.1.101.3.4.3.23 = Hash-SLH-DSA-SHA2-192f-with-SHA512
2.16.840.1.101.3.4.3.24 = Hash-SLH-DSA-SHA2-256s-with-SHA512
2.16.840.1.101.3.4.3.25 = Hash-SLH-DSA-SHA2-256f-with-SHA512
2.16.840.1.101.3.4.3.26 = Hash-SLH-DSA-SHAKE-128s-with-SHAKE128
2.16.840.1.101.3.4.3.27 = Hash-SLH-DSA-SHAKE-128f-with-SHAKE128
2.16.840.1.101.3.4.3.28 = Hash-SLH-DSA-SHAKE-192s-with-SHAKE256
2.16.840.1.101.3.4.3.29 = Hash-SLH-DSA-SHAKE-192f-with-SHAKE256
2.16.840.1.101.3.4.3.30 = Hash-SLH-DSA-SHAKE-256s-with-SHAKE256
2.16.840.1.101.3.4.3.31 = Hash-SLH-DSA-SHAKE-256f-with-SHAKE256

# XMSS
1.3.6.1.4.1.25258.1.5 = XMSS-draft6
1.3.6.1.4.1.25258.1.8 = XMSS-draft12
Expand Down
57 changes: 28 additions & 29 deletions src/cli/speed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@
#include <botan/hss_lms.h>
#endif

#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
#if defined(BOTAN_HAS_SPHINCS_PLUS_COMMON)
#include <botan/sphincsplus.h>
#endif

Expand Down Expand Up @@ -427,7 +427,7 @@ class Speed final : public Command {
"X448",
"McEliece",
"Kyber",
"SPHINCS+",
"SLH-DSA",
"FrodoKEM",
"HSS-LMS",
};
Expand Down Expand Up @@ -660,8 +660,8 @@ class Speed final : public Command {
bench_hss_lms(provider, msec);
}
#endif
#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
else if(algo == "SPHINCS+") {
#if defined(BOTAN_HAS_SPHINCS_PLUS_COMMON)
else if(algo == "SLH-DSA") {
bench_sphincs_plus(provider, msec);
}
#endif
Expand Down Expand Up @@ -2263,36 +2263,35 @@ class Speed final : public Command {
}
#endif

#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
#if defined(BOTAN_HAS_SPHINCS_PLUS_COMMON)
void bench_sphincs_plus(const std::string& provider, std::chrono::milliseconds msec) {
// Sphincs_Parameter_Set set, Sphincs_Hash_Type hash
std::vector<std::string> sphincs_params{"SphincsPlus-sha2-128s-r3.1",
"SphincsPlus-sha2-128f-r3.1",
"SphincsPlus-sha2-192s-r3.1",
"SphincsPlus-sha2-192f-r3.1",
"SphincsPlus-sha2-256s-r3.1",
"SphincsPlus-sha2-256f-r3.1",
"SphincsPlus-shake-128s-r3.1",
"SphincsPlus-shake-128f-r3.1",
"SphincsPlus-shake-192s-r3.1",
"SphincsPlus-shake-192f-r3.1",
"SphincsPlus-shake-256s-r3.1",
"SphincsPlus-shake-256f-r3.1"};

for(auto params : sphincs_params) {
try {
auto keygen_timer = make_timer(params, provider, "keygen");

std::unique_ptr<Botan::Private_Key> key(
keygen_timer->run([&] { return Botan::create_private_key("SPHINCS+", rng(), params); }));
std::vector<std::string> sphincs_params{
"SphincsPlus-sha2-128s-r3.1", "SphincsPlus-sha2-128f-r3.1", "SphincsPlus-sha2-192s-r3.1",
"SphincsPlus-sha2-192f-r3.1", "SphincsPlus-sha2-256s-r3.1", "SphincsPlus-sha2-256f-r3.1",
"SphincsPlus-shake-128s-r3.1", "SphincsPlus-shake-128f-r3.1", "SphincsPlus-shake-192s-r3.1",
"SphincsPlus-shake-192f-r3.1", "SphincsPlus-shake-256s-r3.1", "SphincsPlus-shake-256f-r3.1",

"SLH-DSA-SHA2-128s", "SLH-DSA-SHA2-128f", "SLH-DSA-SHA2-192s",
"SLH-DSA-SHA2-192f", "SLH-DSA-SHA2-256s", "SLH-DSA-SHA2-256f",
"SLH-DSA-SHAKE-128s", "SLH-DSA-SHAKE-128f", "SLH-DSA-SHAKE-192s",
"SLH-DSA-SHAKE-192f", "SLH-DSA-SHAKE-256s", "SLH-DSA-SHAKE-256f",
};

record_result(keygen_timer);
if(bench_pk_sig(*key, params, provider, "", msec) == 1) {
break;
}
} catch(Botan::Not_Implemented&) {
for(auto params_str : sphincs_params) {
auto sp_params = Botan::Sphincs_Parameters::create(params_str);
if(!sp_params.is_available()) {
continue;
}
auto keygen_timer = make_timer(params_str, provider, "keygen");

std::unique_ptr<Botan::Private_Key> key(
keygen_timer->run([&] { return Botan::create_private_key("SLH-DSA", rng(), params_str); }));

record_result(keygen_timer);
if(bench_pk_sig(*key, params_str, provider, "", msec) == 1) {
break;
}
}
}
#endif
Expand Down
38 changes: 37 additions & 1 deletion src/lib/asn1/oid_maps.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* OID maps
*
* This file was automatically generated by ./src/scripts/dev_tools/gen_oids.py on 2024-07-23
* This file was automatically generated by ./src/scripts/dev_tools/gen_oids.py on 2024-09-10
*
* All manual edits to this file will be lost. Edit the script
* then regenerate this source file.
Expand Down Expand Up @@ -267,7 +267,19 @@ std::unordered_map<std::string, std::string> OID_Map::load_oid2str_map() {
{"2.16.840.1.101.3.4.3.15", "RSA/EMSA3(SHA-3(384))"},
{"2.16.840.1.101.3.4.3.16", "RSA/EMSA3(SHA-3(512))"},
{"2.16.840.1.101.3.4.3.2", "DSA/SHA-256"},
{"2.16.840.1.101.3.4.3.20", "Hash-SLH-DSA-SHA2-128s-with-SHA256"},
{"2.16.840.1.101.3.4.3.21", "Hash-SLH-DSA-SHA2-128f-with-SHA256"},
{"2.16.840.1.101.3.4.3.22", "Hash-SLH-DSA-SHA2-192s-with-SHA512"},
{"2.16.840.1.101.3.4.3.23", "Hash-SLH-DSA-SHA2-192f-with-SHA512"},
{"2.16.840.1.101.3.4.3.24", "Hash-SLH-DSA-SHA2-256s-with-SHA512"},
{"2.16.840.1.101.3.4.3.25", "Hash-SLH-DSA-SHA2-256f-with-SHA512"},
{"2.16.840.1.101.3.4.3.26", "Hash-SLH-DSA-SHAKE-128s-with-SHAKE128"},
{"2.16.840.1.101.3.4.3.27", "Hash-SLH-DSA-SHAKE-128f-with-SHAKE128"},
{"2.16.840.1.101.3.4.3.28", "Hash-SLH-DSA-SHAKE-192s-with-SHAKE256"},
{"2.16.840.1.101.3.4.3.29", "Hash-SLH-DSA-SHAKE-192f-with-SHAKE256"},
{"2.16.840.1.101.3.4.3.3", "DSA/SHA-384"},
{"2.16.840.1.101.3.4.3.30", "Hash-SLH-DSA-SHAKE-256s-with-SHAKE256"},
{"2.16.840.1.101.3.4.3.31", "Hash-SLH-DSA-SHAKE-256f-with-SHAKE256"},
{"2.16.840.1.101.3.4.3.4", "DSA/SHA-512"},
{"2.16.840.1.101.3.4.3.5", "DSA/SHA-3(224)"},
{"2.16.840.1.101.3.4.3.6", "DSA/SHA-3(256)"},
Expand Down Expand Up @@ -414,6 +426,18 @@ std::unordered_map<std::string, OID> OID_Map::load_str2oid_map() {
{"HMAC(SHA-512-256)", OID({1, 2, 840, 113549, 2, 13})},
{"HSS-LMS", OID({1, 2, 840, 113549, 1, 9, 16, 3, 17})},
{"HSS-LMS-Private-Key", OID({1, 3, 6, 1, 4, 1, 25258, 1, 13})},
{"Hash-SLH-DSA-SHA2-128f-with-SHA256", OID({2, 16, 840, 1, 101, 3, 4, 3, 21})},
{"Hash-SLH-DSA-SHA2-128s-with-SHA256", OID({2, 16, 840, 1, 101, 3, 4, 3, 20})},
{"Hash-SLH-DSA-SHA2-192f-with-SHA512", OID({2, 16, 840, 1, 101, 3, 4, 3, 23})},
{"Hash-SLH-DSA-SHA2-192s-with-SHA512", OID({2, 16, 840, 1, 101, 3, 4, 3, 22})},
{"Hash-SLH-DSA-SHA2-256f-with-SHA512", OID({2, 16, 840, 1, 101, 3, 4, 3, 25})},
{"Hash-SLH-DSA-SHA2-256s-with-SHA512", OID({2, 16, 840, 1, 101, 3, 4, 3, 24})},
{"Hash-SLH-DSA-SHAKE-128f-with-SHAKE128", OID({2, 16, 840, 1, 101, 3, 4, 3, 27})},
{"Hash-SLH-DSA-SHAKE-128s-with-SHAKE128", OID({2, 16, 840, 1, 101, 3, 4, 3, 26})},
{"Hash-SLH-DSA-SHAKE-192f-with-SHAKE256", OID({2, 16, 840, 1, 101, 3, 4, 3, 29})},
{"Hash-SLH-DSA-SHAKE-192s-with-SHAKE256", OID({2, 16, 840, 1, 101, 3, 4, 3, 28})},
{"Hash-SLH-DSA-SHAKE-256f-with-SHAKE256", OID({2, 16, 840, 1, 101, 3, 4, 3, 31})},
{"Hash-SLH-DSA-SHAKE-256s-with-SHAKE256", OID({2, 16, 840, 1, 101, 3, 4, 3, 30})},
{"KeyWrap.AES-128", OID({2, 16, 840, 1, 101, 3, 4, 1, 5})},
{"KeyWrap.AES-192", OID({2, 16, 840, 1, 101, 3, 4, 1, 25})},
{"KeyWrap.AES-256", OID({2, 16, 840, 1, 101, 3, 4, 1, 45})},
Expand Down Expand Up @@ -488,6 +512,18 @@ std::unordered_map<std::string, OID> OID_Map::load_str2oid_map() {
{"SHA-512-256", OID({2, 16, 840, 1, 101, 3, 4, 2, 6})},
{"SHAKE-128", OID({2, 16, 840, 1, 101, 3, 4, 2, 11})},
{"SHAKE-256", OID({2, 16, 840, 1, 101, 3, 4, 2, 12})},
{"SLH-DSA-SHA2-128f", OID({2, 16, 840, 1, 101, 3, 4, 3, 21})},
{"SLH-DSA-SHA2-128s", OID({2, 16, 840, 1, 101, 3, 4, 3, 20})},
{"SLH-DSA-SHA2-192f", OID({2, 16, 840, 1, 101, 3, 4, 3, 23})},
{"SLH-DSA-SHA2-192s", OID({2, 16, 840, 1, 101, 3, 4, 3, 22})},
{"SLH-DSA-SHA2-256f", OID({2, 16, 840, 1, 101, 3, 4, 3, 25})},
{"SLH-DSA-SHA2-256s", OID({2, 16, 840, 1, 101, 3, 4, 3, 24})},
{"SLH-DSA-SHAKE-128f", OID({2, 16, 840, 1, 101, 3, 4, 3, 27})},
{"SLH-DSA-SHAKE-128s", OID({2, 16, 840, 1, 101, 3, 4, 3, 26})},
{"SLH-DSA-SHAKE-192f", OID({2, 16, 840, 1, 101, 3, 4, 3, 29})},
{"SLH-DSA-SHAKE-192s", OID({2, 16, 840, 1, 101, 3, 4, 3, 28})},
{"SLH-DSA-SHAKE-256f", OID({2, 16, 840, 1, 101, 3, 4, 3, 31})},
{"SLH-DSA-SHAKE-256s", OID({2, 16, 840, 1, 101, 3, 4, 3, 30})},
{"SM2", OID({1, 2, 156, 10197, 1, 301, 1})},
{"SM2_Enc", OID({1, 2, 156, 10197, 1, 301, 3})},
{"SM2_Kex", OID({1, 2, 156, 10197, 1, 301, 2})},
Expand Down
16 changes: 9 additions & 7 deletions src/lib/pubkey/pk_algs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
#include <botan/dilithium.h>
#endif

#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
#if defined(BOTAN_HAS_SPHINCS_PLUS_COMMON)
#include <botan/sphincsplus.h>
#endif

Expand Down Expand Up @@ -230,8 +230,9 @@ std::unique_ptr<Public_Key> load_public_key(const AlgorithmIdentifier& alg_id,
}
#endif

#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
if(alg_name == "SPHINCS+" || alg_name.starts_with("SphincsPlus-")) {
#if defined(BOTAN_HAS_SPHINCS_PLUS_COMMON)
if(alg_name == "SPHINCS+" || alg_name.starts_with("SphincsPlus-") || alg_name.starts_with("SLH-DSA-") ||
alg_name.starts_with("Hash-SLH-DSA-")) {
return std::make_unique<SphincsPlus_PublicKey>(alg_id, key_bits);
}
#endif
Expand Down Expand Up @@ -365,8 +366,9 @@ std::unique_ptr<Private_Key> load_private_key(const AlgorithmIdentifier& alg_id,
}
#endif

#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
if(alg_name == "SPHINCS+" || alg_name.starts_with("SphincsPlus-")) {
#if defined(BOTAN_HAS_SPHINCS_PLUS_COMMON)
if(alg_name == "SPHINCS+" || alg_name.starts_with("SphincsPlus-") || alg_name.starts_with("SLH-DSA-") ||
alg_name.starts_with("Hash-SLH-DSA-")) {
return std::make_unique<SphincsPlus_PrivateKey>(alg_id, key_bits);
}
#endif
Expand Down Expand Up @@ -507,8 +509,8 @@ std::unique_ptr<Private_Key> create_private_key(std::string_view alg_name,
}
#endif

#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
if(alg_name == "SPHINCS+" || alg_name == "SphincsPlus-") {
#if defined(BOTAN_HAS_SPHINCS_PLUS_COMMON)
if(alg_name == "SPHINCS+" || alg_name == "SphincsPlus" || alg_name == "SLH-DSA") {
auto sphincs_params = Sphincs_Parameters::create(params);

return std::make_unique<SphincsPlus_PrivateKey>(rng, sphincs_params);
Expand Down
4 changes: 2 additions & 2 deletions src/lib/pubkey/sphincsplus/sphincsplus_common/info.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ SPHINCS_PLUS_COMMON -> 20230426
</defines>

<module_info>
name -> "SPHINCS+ (common)"
brief -> "Base implementation of SPHINCS+"
name -> "SLH-DSA (common)"
brief -> "Base implementation of SLH-DSA"
type -> "Internal"
</module_info>

Expand Down
9 changes: 5 additions & 4 deletions src/lib/pubkey/sphincsplus/sphincsplus_common/sp_address.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/*
* SPHINCS+ Address
* SLH-DSA Address
* (C) 2023 Jack Lloyd
* 2023 Fabian Albert, René Meusel, Amos Treiber - Rohde & Schwarz Cybersecurity
*
* Botan is released under the Simplified BSD License (see license.txt)
**/
*/

#ifndef BOTAN_SPHINCS_PLUS_ADDRESS_H_
#define BOTAN_SPHINCS_PLUS_ADDRESS_H_
Expand All @@ -28,11 +28,12 @@ enum class Sphincs_Address_Type : uint32_t {
};

/**
* Representation of a SPHINCS+ hash function address as specified in
* SPHINCS+ Specification Round 3.1, Section 2.7.3
* Representation of a SLH-DSA hash function address as specified in
* FIPS 205, Section 4.2
*/
class BOTAN_TEST_API Sphincs_Address final {
private:
// Offsets of the address fields in the address array. Counted in 32-bit words.
static constexpr size_t layer_offset = 0;
static constexpr size_t tree_offset = 1; // tree address is 3 words wide
static constexpr size_t type_offset = 4;
Expand Down
17 changes: 11 additions & 6 deletions src/lib/pubkey/sphincsplus/sphincsplus_common/sp_fors.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
/*
* FORS - Forest of Random Subsets
* FORS - Forest of Random Subsets (FIPS 205, Section 8)
* (C) 2023 Jack Lloyd
* 2023 Fabian Albert, René Meusel, Amos Treiber - Rohde & Schwarz Cybersecurity
*
* Parts of this file have been adapted from https://github.com/sphincs/sphincsplus
*
* Botan is released under the Simplified BSD License (see license.txt)
**/
*/

#include <botan/internal/sp_fors.h>

Expand All @@ -18,13 +20,11 @@
#include <botan/internal/sp_types.h>
#include <botan/internal/stl_util.h>

#include <functional>
#include <utility>

namespace Botan {

namespace {

/// FIPS 205, Algorithm 4: base_2^b(X,b,out_len) with b = a and out_len = k (for usage in FORS)
std::vector<TreeNodeIndex> fors_message_to_indices(std::span<const uint8_t> message, const Sphincs_Parameters& params) {
BOTAN_ASSERT_NOMSG((message.size() * 8) >= (params.k() * params.a()));

Expand All @@ -34,7 +34,12 @@ std::vector<TreeNodeIndex> fors_message_to_indices(std::span<const uint8_t> mess

for(auto& idx : indices) {
for(uint32_t i = 0; i < params.a(); ++i, ++offset) {
idx ^= (((message[offset >> 3] >> (offset & 0x7)) & 0x1) << i);
// This is one of the few places where SPHINCS+ round 3.1 and SLH-DSA differ
if(params.is_slh_dsa()) {
idx ^= (((message[offset >> 3] >> (~offset & 0x7)) & 0x1) << (params.a() - 1 - i));
} else {
idx ^= (((message[offset >> 3] >> (offset & 0x7)) & 0x1) << i);
}
}
}

Expand Down
Loading

0 comments on commit 6d4dacf

Please sign in to comment.