365 Architect

04 — Few-Time Signatures (FORS)

The Problem WOTS+ Leaves

WOTS+ signs one message securely. To sign 2h2^h messages, we need a Merkle tree of 2h2^h WOTS+ keys. But what if we want a simpler structure without managing thousands of WOTS+ keys?

FORS (Forest of Random Subsets) provides a middle ground: sign a few messages with one public key, using a different approach.

How FORS Works

Setup

  1. Choose parameters:

    • kk = number of subsets (e.g., 33)
    • aa = tree height per subset (e.g., 14)
    • t=2at = 2^a = number of leaves per subset
  2. Generate kk independent Merkle trees, each with tt random leaf values:

Tree 1          Tree 2          ...     Tree k
Root_1          Root_2                  Root_k
  |               |                       |
 / \             / \                     / \
L L ...         L L ...                 L L ...
(2^a leaves)    (2^a leaves)            (2^a leaves)
  1. The public key is the hash of all tree roots: pk=Hash(Root1Root2...Rootk)pk = Hash(Root_1 || Root_2 || ... || Root_k)

Signing

  1. Hash the message to a k×ak \times a-bit digest.
  2. Split into kk indices: idx1,idx2,...,idxkidx_1, idx_2, ..., idx_k (each in [0,2a1][0, 2^a-1]).
  3. For each tree ii, select the leaf at index idxiidx_i.
  4. Include:
    • The kk selected leaf values
    • The Merkle path for each selected leaf (to prove it's in the tree)
  5. The signature is: σ=(leaf1,path1,leaf2,path2,...,leafk,pathk)\sigma = (leaf_1, path_1, leaf_2, path_2, ..., leaf_k, path_k)

Verification

  1. Hash the message to get the same kk indices.
  2. For each tree ii:
    • Use leafileaf_i and pathipath_i to compute RootiRoot_i'
  3. Check: Hash(Root1Root2...Rootk)==pkHash(Root_1' || Root_2' || ... || Root_k') == pk

Security Analysis

FORS is secure for a few signatures because:

First signature: Reveals kk random leaves (one from each tree). Second signature: Reveals kk more random leaves.

The probability of collision (same index chosen twice in the same tree):

P(collision)=1(11t)ksignatures\displaystyle P(\text{collision}) = 1 - (1 - \frac{1}{t})^{k \cdot \text{signatures}}

For t=214=16,384t = 2^{14} = 16,384 and k=33k = 33:

  • After 1 signature: negligible collision risk
  • After 10 signatures: still very low
  • After 100 signatures: ~2% collision risk (too high)

That's why FORS is "few-time" — safe for a small number of signatures, unsafe for many.

FORS Parameters

Parameter Symbol Typical Value Meaning
Number of trees k 33 Number of subsets
Tree height a 14 Leaves per tree = 2^14 = 16,384
Security parameter n 32 SHA-256 output size
Signature size k × (n + a × n) = ~33 × (32 + 14×32) ~16 KB

FORS vs. WOTS+

Property WOTS+ FORS
Messages per key 1 Few (typically < 10)
Signature size ~2 KB ~16 KB
Public key size ~2 KB 32 B (hash of roots)
Hash operations (sign) ~w × len = ~1,000 ~k × a = ~500
Best for Single messages in a tree Multiple messages in a tree

FORS in SLH-DSA

SLH-DSA uses FORS for the bottom layer of signatures (the actual message signing), and WOTS+ for the upper layers (signing the FORS public keys and tree navigation).

Message
   |
   v
FORS signature (few-time, large)
   |
   v
WOTS+ signatures (one-time, chain up the tree)
   |
   v
Hypertree root (long-term public key)

This hybrid approach balances security and efficiency.

Resources

  • Bernstein et al., "SPHINCS+ — Submission to the NIST post-quantum project" (2020), v3.1
  • NIST FIPS 205, Section 6: FORS Algorithm
  • Hülsing et al., "XMSS-T: Hash-based signatures with tight security" (2017), PQCrypto
Share on LinkedIn