GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — add six new SLH-DSA parameter sets from NIST SP 800-230 by chen-cht · Pull Request #2292 · bcgit/bc-java

Conversation

@chen-cht

@chen-cht chen-cht commented May 5, 2026

Copy link
Copy Markdown

Overview

This PR adds six new SLH-DSA parameter sets defined in NIST SP 800-230 (Initial Public Draft).

New Parameter Sets Added

The following SLH-DSA parameter sets are introduced:

  • SHA2-based:

    • sha2-128-24
    • sha2-192-24
    • sha2-256-24
  • SHAKE-based:

    • shake-128-24
    • shake-192-24
    • shake-256-24

Changes

  • Modified SLHDSAParameters.java
  • Modified SLHDSAEngine.java

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
dghgit and others added 30 commits March 4, 2026 11:55
@dghgit
Merge branch 'pgpainless-fixHashedSubpacketsNull'
81196e6
@dghgit
Merge branch 'fixSelfSigSelection' of https://github.com/pgpainless/b…
c39c027
…c-java into pgpainless-fixSelfSigSelection
@dghgit
Merge branch 'pgpainless-fixSelfSigSelection'
657b7d0
@dghgit
Merge branch 'pgpsecretkeyV6directkeysig' of https://github.com/pgpai…
9eab8ed
…nless/bc-java into pgpainless-pgpsecretkeyV6directkeysig
@dghgit
Merge branch 'pgpainless-pgpsecretkeyV6directkeysig'
13ce3ad
@dghgit
Merge branch 'rsaKeyGeneration' of https://github.com/pgpainless/bc-java
a1553af
 into pgpainless-rsaKeyGeneration
@dghgit
Merge branch 'pgpainless-rsaKeyGeneration'
7b094ad
@peterdettman
Fix Frodo error sampling to be constant-time
94abbd5
@peterdettman
Refactor AESTest
9643807
@peterdettman
Use AESEngine.newInstance
c6ec8c2
@peterdettman
Refactoring in constant-time utils
97fbab5
@peterdettman
More Pack methods
9f14109
@peterdettman
More Nat methods
5c22553
@peterdettman
Refactoring in pqc.crypto.frodo
8692e6b
oreste
PKCS12KeyStoreSpi.java in tls can now write as well as read PBMAC1 pk…
bd43571
…cs12 objects
@xipki @peterdettman
Adaptedtls to support custom certificate types.
8ce7aa8
This adaption allows one to support new certificate type, e.g. the C509 certificate, without modifying the bouncycastle classes.
@peterdettman
Followup for CertificateType changes (github bcgit#2165)
91263d1
@dghgit
removed unused file, removed interal dependencies on prov module.
48e8857
Marijus Gudiskis
updated unit tests to track if the piped thread is stuck bcgit#2245
d275858
Marijus Gudiskis
read whole stream to prevent piped thread stuck bcgit#2245
dc12926
Marijus Gudiskis
fixed styling for java brackets bcgit#2245
8939236
@peterdettman
NTRU only in BCPQC
5afa4ad
@peterdettman
Use CryptoServicesRegistrar for auto-created SecureRandom
d91537f
@peterdettman
Re-enable tests that need java.security conf
c463222
@peterdettman
Fix package for jdk17 KEM tests
10f2143
@peterdettman
Rename jdk17 test classes to avoid conflicts
031922a
@peterdettman
Rename jdk17 test classes to avoid conflicts
510d7e4
@peterdettman
CMS: Use BCPQC for NTRU tests
e363a8e
@peterdettman
Refactor, include some missing ".OID." entries
32979da
@peterdettman
From JDK11, test for NamedParameterSpec
ca8f1a9
dghgit and others added 25 commits May 3, 2026 06:25
@dghgit
added SM2 patch
0a01811
@dghgit
corrected expiry time check to allow for later packets which increase…
5086e68
… or remove it. Relates to github bcgit#1749
@dghgit
Fixed case issues in Falcon name.
b80da46
@dghgit
Updated validity test.
4e28866
@dghgit
Added legacy parsing of encrypted EdEC keys. Relates to github bcgit#…
153da24
…1238
@dghgit
Added use of Exceptions class to propogate cause for IOException, rel…
6b169b3
…ates to github bcgit#2250
@dghgit
Added cause to GeneralSecurityException throw, relates to github bcgi…
eaebef1
…t#2250
@dghgit
Added null check to prevent attempt to validate trust anchor without …
527488a
…cert in it, relates to github bcgit#1420
@dghgit
Added additional methods to SimplePKIResponse and builder class, rela…
22e9e8d
…tes to github bcgit#1452
@dghgit
Added basic KeyGrip calculator for RSA keys, relates to github bcgit#676
cf2f521
@dghgit
Added support for SM2 as a CMS KeyTransport cipher, relates to github b…
5490432
…cgit#584
@dghgit
Added certificate based SM2 test, relates to github bcgit#584
cbfae08
@dghgit
Initial support for SecretBag, relates to github bcgit#890
31fe836
@dghgit
Added PBMAC1 support to pkcs package MAC verifier provider.
a46adf3
Added BC provider support for LEA, relates to github bcgit#1880.
@dghgit
Added name and OID search, relates to github bcgit#1230
63a0d11
@dghgit
initial CLAUDE.md
a0aeb44
@dghgit
removed possible recursion on misconfigured CertPath validations, rel…
790ac4b
…ates to github bcgit#2291
@dghgit
generalized openSSH ECDSA key encoding, relates to github bcgit#2240
aa7d3f6
@dghgit
tweak on misconfigured CertPath validations, relates to github bcgit#…
71ede26
…2291
@dghgit
re-added commented out tests.
cace5d1
@dghgit
added missing tests
c7f57bd
@dghgit
added missing tests
65e218e
@dghgit
added external hash to HashMLDSASigner, relates to github bcgit#2198
c2cb354
@chen-cht
Update SLHDSAParameters.java
c2c5d52
add SLH-DSA parameter sets from NIST-SP-800-230
@chen-cht
Update SLHDSAEngine.java
f67f7ef
add SLH-DSA parameter sets from NIST SP 800-230
@dghgit dghgit self-assigned this May 13, 2026
@dghgit

dghgit commented May 13, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

Thanks for the PR. There's been some new suggestions on the PQC mailing list for these - putting on hold while the discussion pans out.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@hubot
hubot force-pushed the main branch from d3d00d9 to 88c6a3a Compare July 29, 2026 06:49
@Arpan0995

Arpan0995 commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

I know this is on hold pending the pqc-forum discussion, so this is for whenever it gets picked back up. The issues below apply to any SP 800-230 support regardless of the final parameter choices.

Thanks for taking this on. Adding the SP 800-230 limited-signature SLH-DSA sets (the "-24" family, capped at 2^24 signatures per key) is worth having in BC, and the parameter tuples are numerically right where they land: 128-24 = (16,4,1,24,6,22), 192-24 = (24,8,1,25,9,21), 256-24 = (32,4,1,25,12,21) as (n,w,d,a,k,h), with SHA2 and SHAKE matching per level, w=4 for the 128/256 sets and w=8 for 192, and d=1 throughout. Those reproduce the correct signature sizes (3856 / 7752 / 14944), so a size check passes. I ran the sets against the spec math and the existing engine code, and there are a few blocking issues before this can merge.

1. WOTS+ checksum / base-w decode is wrong for 128-24 and 192-24 (blocker)

File: core/src/main/java/org/bouncycastle/pqc/crypto/slhdsa/WotsPlus.java. This code is unchanged from base, but the new sets exercise it with lg_w values it was never written for. There are two distinct root causes, and only 256-24 escapes both.

128-24 (w=4, lg_w=2): checksum decodes to a constant zero. In the checksum encode (lines 84-91), the left-shift is csum << (8 - ((WOTS_LEN2 * WOTS_LOGW) % 8)). The SPHINCS+ reference implementation this code is ported from wraps that shift in an outer mod 8: csum << ((8 - ((len2*lg_w) % 8)) % 8) (wots.c, wots_checksum). For 128-24, len2*lg_w = 4*2 = 8, so the correct shift is 0 but this code shifts by 8, one whole byte too far. Combined with len_2_bytes = 1 and the read at offset 4 - len_2_bytes = 3, base_w then reads the vacated zero byte, so the checksum digits are [0,0,0,0] for every message. I reproduced this over 200 messages using the exact engine-constant and WotsPlus checksum code: the 128-24 checksum encodes to [0,0,0,0] every time (two messages with different real checksums encode identically), while the standard w=16 set varies correctly as a control. The omitted mod 8 was latent because len2*lg_w is never a multiple of 8 for any w=16 set; 128-24 is the first set to hit it. A constant WOTS+ checksum removes the mechanism that stops an attacker from advancing every message chain forward, so I would treat this as a correctness and security defect, not a size or interop nit.

192-24 (w=8, lg_w=3): base_w mis-decodes both the message and the checksum. WotsPlus.base_w refills total one byte at a time (total = X[XOff++]) and does bits -= WOTS_LOGW. That single-byte-replace form is only correct when lg_w divides 8. lg_w=3 does not, so bits goes negative, the read straddles bytes, and Java signed-byte sign-extension compounds it. On sample inputs the checksum decodes wrong: a true checksum of 448 comes out as digits [7,0,1] instead of [7,0,0], 447 as [6,7,1] instead of [6,7,7], and small values collapse (csum=1 gives [0,0,0]). The message base-w digits themselves are wrong too. The correct general routine already exists in this codebase: Fors.java (lines 149-161) uses an accumulating base_2b (total = total.shiftLeft(8).add(...)) precisely because the FORS a values (6, 9, 12, 14) also do not divide 8. WOTS+ should use that same accumulating form for lg_w that does not divide 8.

Because sign() and pkFromSig() encode the checksum identically for these parameters, BC still verifies its own signatures, so an internal round-trip test stays green and does not catch this. Of the three sets, only 256-24 encodes the WOTS+ layer correctly (0 of 200 message and checksum errors in the same test); 128-24 and 192-24 do not.

2. Sets landed only on the deprecated tree

The six sets are added at core/src/main/java/org/bouncycastle/pqc/crypto/slhdsa/SLHDSAParameters.java:56-77, whose class javadoc reads @deprecated use org.bouncycastle.crypto.params.SLHDSAParameters. The modern crypto/params/SLHDSAParameters.java is byte-identical to base and still holds only the 24 standard w=16 sets. New standards-track functionality on the deprecated path only is not reachable by the consumers the project points forward to.

3. Modern engine rejects w=4/w=8

If you move the sets to the modern tree (the right fix), they fail at construction: core/src/main/java/org/bouncycastle/crypto/signers/slhdsa/SLHDSAEngine.java accepts only w==16 or w==256 and otherwise throws "wots_w assumed 16 or 256" (line 82). The w=4/w=8 branches were added only to the deprecated pqc engine. Moving the params means also widening this guard and porting the LEN math, after fixing #1 in WotsPlus.

4. No JCA provider or public spec entry point

prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/SLHDSA.java and jcajce/spec/SLHDSAParameterSpec.java register only the 24 standard sets. There is no *-24 name, so an application cannot select these sets through KeyPairGenerator / Signature / ParameterSpec. The feature is not wired end to end.

5. Diff is not reviewable

The PR reports 264,657 additions / 122,102 deletions across 3,807 files, while the real change is roughly 40 lines. The head branch has diverged substantially from base, which pulls in thousands of unrelated files plus some stray ones (CLAUDE.md, build/CI scripts, a rewritten build.gradle). Please rebase onto current base so the diff shows only the intended change, and drop the stray files.

6. No test vectors

core/src/test/java/org/bouncycastle/pqc/crypto/test/SLHDSATest.java has no coverage for any of the six sets: they are absent from parametersMap, from PARAMETER_SETS (the round-trip driver behind testConsistency), and from every KAT harness. Since SP 800-230 is an Initial Public Draft with no published NIST reference vectors yet, at minimum add a self-consistency sign/verify round-trip per set (mirroring testConsistency). A test that decodes the WOTS+ checksum and asserts it is not constant-zero would have caught #1.

Minor notes

  • No OIDs / ASN.1 for the new sets. This is inherent to the IPD (it assigns none), so it is not something to fix here, but it does mean no X.509 / PKCS#8 / CMS path until NIST allocates identifiers. Worth a code comment so it is not read as an oversight.
  • In the added w=4/w=8 branches, WOTS_LEN2 is computed with a runtime float log, (int)(Math.log(WOTS_LEN1*(w-1))/Math.log(w))+1, rather than the integer tables the standard sets use. It gives the correct 4/3/5 here with a wide margin, so there is no bug, but an integer computation would match the surrounding style.

Objective checks you can run

Signature size: sig = (1 + k*(1+a) + h + d*len) * n, with len = len1 + len2, len1 = ceil(8n / lg_w), len2 = floor(log2(len1*(w-1)) / lg_w) + 1. For these sets that gives 241*16 = 3856, 323*24 = 7752, 467*32 = 14944. The stronger check is to sign a fixed message, decode the WOTS+ checksum digits back out, and confirm they are not constant-zero and that they track the message hash. That is what exposes #1.

What would make this mergeable

  1. Fix the WOTS+ base-w / checksum encoding for w=4 and w=8 in WotsPlus.java (missing outer mod 8 in the checksum shift for 128-24; accumulating base_2b for the lg_w=3 case of 192-24), and confirm 128-24's checksum is no longer constant-zero.
  2. Add the six sets to the modern crypto/params tree and widen the core SLHDSAEngine w-guard with the w=4/w=8 LEN math so they are constructible on the supported path.
  3. Wire the JCA provider and a public SLHDSAParameterSpec so the sets are selectable through the standard API.
  4. Add a round-trip test per set, and external KATs once NIST publishes them.
  5. Rebase onto current base and drop the unrelated files so the diff is only the intended change.

The parameter values are right, so the foundation is sound once the encoding and the plumbing are fixed. Happy to look again once the checksum fix and a round-trip test are in place.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@dghgit dghgit mentioned this pull request Aug 22, 2026
Support additional SLH-DSA parameter sets from NIST FIPS 800-230 (limited signature use cases) #2402
Open
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

@dghgit dghgit

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

11 participants

@chen-cht @dghgit @Arpan0995 @peterdettman @crlorentzen @xipki @Joowon-Seo @xSammyKang @ligefeiBouncycastle @vanitasvitae @Razumain
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.