EVP_SIGNATURE-SLH-DSA(7ossl)

πŸ“¦
version 15.1 Β· 2 versions
, in freebsd 15.1

πŸ’… EVP_SIGNATURE-SLH-DSA(7ossl) β€” the SLH-DSA signature glow-up

okay so bestie, welcome to the manual page for the EVP_SIGNATURE-SLH-DSA family β€” there's literally twelve of them and they all slay in their own way:

  • EVP_SIGNATURE-SLH-DSA
  • EVP_SIGNATURE-SLH-DSA-SHA2-128s
  • EVP_SIGNATURE-SLH-DSA-SHA2-128f
  • EVP_SIGNATURE-SLH-DSA-SHA2-192s
  • EVP_SIGNATURE-SLH-DSA-SHA2-192f
  • EVP_SIGNATURE-SLH-DSA-SHA2-256s
  • EVP_SIGNATURE-SLH-DSA-SHA2-256f
  • EVP_SIGNATURE-SLH-DSA-SHAKE-128s
  • EVP_SIGNATURE-SLH-DSA-SHAKE-128f
  • EVP_SIGNATURE-SLH-DSA-SHAKE-192s
  • EVP_SIGNATURE-SLH-DSA-SHAKE-192f
  • EVP_SIGNATURE-SLH-DSA-SHAKE-256s
  • EVP_SIGNATURE-SLH-DSA-SHAKE-256f

these are the EVP_PKEY SLH-DSA signature implementations, and yes the name is a mouthful, we know, we love her anyway 🫢


✨ DESCRIPTION ✨

so here's the tea πŸ“. The SLH-DSA-SHA2-128s, EVP_PKEY-SLH-DSA-SHA2-128f, SLH-DSA-SHA2-192s, EVP_PKEY-SLH-DSA-SHA2-192f, SLH-DSA-SHA2-256s, EVP_PKEY-SLH-DSA-SHA2-256f, SLH-DSA-SHAKE-128s, EVP_PKEY-SLH-DSA-SHAKE-128f, SLH-DSA-SHAKE-192s, EVP_PKEY-SLH-DSA-SHAKE-192f, SLH-DSA-SHAKE-256s and EVP_PKEY-SLH-DSA-SHAKE-256f EVP_PKEY implementations support key generation, one-shot sign and verify β€” all using the SLH-DSA signature schemes from FIPS 205. iconic behavior, no notes πŸ’…

these different algorithm names? they map directly onto the parameter sets defined in FIPS 205 Section 11 Table 2. so:

  • the s types have smaller signature sizes
  • the f variants are faster
  • signatures range from ~8K to ~50K depending on the type you pick (yes, K. like, kilobytes. she's a big girl, that's the post-quantum tax 😭)
  • there are also 3 different security categories, again depending on the type 🌈

and when you actually want to use one, EVP_SIGNATURE_fetch(3) lets you explicitly fetch any of the 12 algorithms, which then plays nicely with EVP_PKEY_sign_message_init(3), EVP_PKEY_sign(3), EVP_PKEY_verify_message_init(3) and EVP_PKEY_verify(3) for one-shot message signing or verification. that's the whole squad πŸŽ€

🌸 the signing process, explained (the way that…)

the normal signing process β€” the one officially called Pure SLH-DSA Signature Generation β€” encodes the message internally like this:

0x00 || len(ctx) || ctx || message

where ctx is some optional value of size 0x00..0xFF.

OpenSSL also lets you not encode the message, which is required for testing. and heads up, bestie: OpenSSL does not support Pre Hash SLH-DSA Signature Generation β€” but you can totally do it yourself by doing the Pre hash encoding externally and then picking the option to not encode the message. diy queen πŸ‘‘

πŸ¦‹ SLH-DSA Signature Parameters

the "context-string" parameter (described right below) can be used for both signing and verification. set it by passing an OSSL_PARAM array to EVP_PKEY_sign_init_ex2(3) or EVP_PKEY_verify_init_ex2(3).

  • "context-string" (OSSL_SIGNATURE_PARAM_CONTEXT_STRING) <octet string> β€” a string of octets with length at most 255. by default it's the empty string.

the following parameters can be used when signing β€” set them by passing an OSSL_PARAM array to EVP_PKEY_sign_init_ex2(3):

  • "message-encoding" (OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING) <integer> β€” the default value of 1 uses 'Pure SLH-DSA Signature Generation' like we described above. setting it to 0 does not encode the message β€” that's used for testing, but it can also be used for 'Pre Hash SLH-DSA Signature Generation'.
  • "test-entropy" (OSSL_SIGNATURE_PARAM_TEST_ENTROPY) <octet string> β€” used for testing, to pass an optional random value.
  • "deterministic" (OSSL_SIGNATURE_PARAM_DETERMINISTIC) <integer> β€” the default value of 0 generates a random value (using a DRBG), which is what gets used when processing the message. setting this to 1 causes the private key seed to be used instead. this value is ignored if "test-entropy" is set. iykyk ✨
πŸ’– want the key side of things? see EVP_PKEY-SLH-DSA(7) for information related to SLH-DSA keys.

πŸ’€ NOTES πŸ’€

for backwards compatibility reasons, EVP_DigestSignInit_ex(), EVP_DigestSign(), EVP_DigestVerifyInit_ex() and EVP_DigestVerify() may also be used β€” but the digest passed in mdname must be NULL. that's not a suggestion, bestie, that's a requirement πŸ™ˆ


πŸ”₯ EXAMPLES πŸ”₯

to sign a message using an SLH-DSA EVP_PKEY structure:

void do_sign(EVP_PKEY *key, unsigned char *msg, size_t msg_len)
{
    size_t sig_len;
    unsigned char *sig = NULL;
    const OSSL_PARAM params[] = {
        OSSL_PARAM_octet_string("context-string", (unsigned char *)"A context string", 33),
        OSSL_PARAM_END
    };
    EVP_PKEY_CTX *sctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
    EVP_SIGNATURE *sig_alg = EVP_SIGNATURE_fetch(NULL, "SLH-DSA-SHA2-128s", NULL);

    EVP_PKEY_sign_message_init(sctx, sig_alg, params);
    /* Calculate the required size for the signature by passing a NULL buffer. */
    EVP_PKEY_sign(sctx, NULL, &sig_len, msg, msg_len);
    sig = OPENSSL_zalloc(sig_len);
    EVP_PKEY_sign(sctx, sig, &sig_len, msg, msg_len);
    ...
    OPENSSL_free(sig);
    EVP_SIGNATURE_free(sig_alg);
    EVP_PKEY_CTX_free(sctx);
}

that NULL-buffer trick to get sig_len first? main character energy, honestly πŸ‘‘


🧚 SEE ALSO 🧚


⭐ HISTORY ⭐

this functionality was added in OpenSSL 3.5 πŸŽ‰


Copyright 2024-2026 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.


and that's the page, bestie 🫢 mwah πŸ’‹ β€” this was version 3.5.6, dated 2026-04-07, and you've been reading EVP_SIGNATURE-SLH-DSA(7ossl). go forth and sign something enormous πŸ’–

πŸ“¦ where this page comes from