SPHINCS+ Python Code
This page has the Python code we used to reproduce the example values in the previous pages.
Some of this Python code is a bit crude. It is not meant as an example of good or efficient coding practice. The intention is to demonstrate specific examples with hardcoded input and show we get the desired output. All the binary values are converted back and forth with hexadecimal encoding - this, again, is for clarity, not efficiency.
We find it easier to work through small self-contained blocks of code that do something simple, rather than obscure code hidden inside layers of abstraction. YMMV.
At the end, we pull it all together to compute the SPHINCS+ signature in one go. Beware, lots of hardcoded constants!
Then we do the same program slightly rewritten to re-compute all the 100 test cases for SPHINCS+-SHA2-128f-simple
using data from a separate JSON file.
We use the SHA-256 functions from our CryptoSys PKI toolkit library and its Python interface. There is an alternative interface using the pure Python hashlib and hmac libraries.
This was tested using Python 3.11.0 [MSC v.1933 64 bit (AMD64)] on 64-bit Windows 10.
spx_adrs.py | SPHINCS+ ADRS Class. |
spx_sha256.py | SPHINCS+-SHA-256 crypto functions. |
spx_util.py | SPHINCS+ utilities for tree calculations. |
hashlib_pki.py | SHA-256 functions using cryptosyspki. |
hashlib_pure.py | SHA-256 functions using hashlib and hmac libraries. |
merkle_tree_4byte.py | Generate a Merkle tree using weak 4-byte hash function. |
merkle_authpath_verify.py | Verify authentication path for a simple Merkle tree. |
PRF_msg.py | Compute the 16-byte randomizer R. |
H_msg.py | Compute H_msg from the message, public key and randomizer. |
message_to_indices.py | Interpret 25-byte mhash as 33 * 6-bit unsigned integers. |
fors_sk_basic.py | Compute the FORS secret keys for i=0,1,32 with hardcoded ADRS |
fors_sig_sk_all.py | Compute all the 33 FORS signature secret keys. |
fors_authpath_basic.py | Initial basic calcs for authpath of first FORS tree. |
fors_sk_pk_0.py | Compute the 64 FORS secret and public keys for the first tree. |
fors_PKgen.py | Compute the FORS public key given the roots of the k FORS trees. |
fors_authpath_0.py | Compute the authpath for the first FORS tree. |
fors_authpath_01_32.py | Compute the authpaths from scratch for the FORS trees with i=1 and i=32. |
fors_authpath_verify.py | Verify the first FORS authpath. |
wots_len.py | Compute len_1 and len_2 given n and w. |
wots_checksum.py | Split 16-byte message into 4-bit blocks then append 3 x 4-bit checksum. |
wots_sig_0.py | Compute the first WOTS signature. |
wots_pk.py | Compute the WOTS public key for the bottom HT subtree. |
wots_PKgen.py | Compute the first WOTS public key with hardcoded root values. |
wots_PKgen_sk.py | Compute WOTS secret key then derive public key. |
wots_PKgenRoot.py | Generate WOTS public key root value. |
wots_ht_0.py | Compute root node and authpath for bottom HT subtree at layer 0. |
wots_authpath_verify.py | Verify the authpath in the first WOTS subtree. |
wots_layers.py | Compute the WOTS tree address for each layer. |
wots_gen_pk.py | Compute root node of the top-most HT subtree = PK.root. |
spx_makesig.py | Do it all to make a SPHINCS+ signature in one go. |
spx_makesigs100.py | Reproduce all 100 SPHINCS+-SHA2-128f-simple test cases. |
spx_inputkat100.json | JSON data for SPHINCS+ test cases. |
In the Python code, spx_makesig.py
, we reproduce the first two test cases in the SPHINCS+ October 2020 round 3 submission for sphincs-sha256-128f-simple
.
All the required information is in the file PQCsignKAT_64.rsp except the value of OptRand
, the optional randomness added when computing the randomizer, R.
The value of OptRand can only be found by running the implementation code with its specific random bit generator.
The SHA256 hash of the signature value is also computed separately.
<< previous: The Hyper Tree Signature (SIG_HT) | Contents | next: SPHINCS+ References >> |
Contact us
To comment on this page or to contact us, please send us a message.
This page first published 17 March 2023. Last updated 9 September 2025.