fix: add SLH-DSA security strength estimation for policy enforcement

Extend SecurityStrengthAdvisor to recognize SLH-DSA keys and map their
parameter sets (128/192/256) to NIST security strengths.

This enables CryptoPolicy.minStrength(...) to enforce SLH-DSA profiles
consistently with other PQC algorithms.

Signed-off-by: Leo Galambos <lg@hq.egothor.org>
This commit is contained in:
2025-12-25 17:43:00 +01:00
parent 8f228c7ada
commit 2b4559884f

View File

@@ -70,6 +70,8 @@ import javax.crypto.SecretKey;
* {@code key.getAlgorithm()} (for example, 512, 768, 1024 for ML-KEM;
* 640/976/1344 for FrodoKEM) or from NIST security levels labeled as L1/L3/L5.
* If neither is present, defaults to 128.</li>
* <li><b>SLH-DSA:</b> parse 128/192/256 from {@code key.getAlgorithm()}
* similarly to SPHINCS+; else default 128.</li>
* <li><b>SPHINCS+:</b> parses the parameter size 128/192/256 from the algorithm
* string; otherwise defaults to 128.</li>
* <li><b>EdDSA:</b> returns fixed strengths (Ed25519 -> 128, Ed448 ->
@@ -122,6 +124,7 @@ public final class SecurityStrengthAdvisor { // NOPMD
private static final Pattern SPHINCS_STRENGTH_PATTERN = Pattern.compile("(128|192|256)");
private static final Pattern HMAC_SHA_PATTERN = Pattern.compile("HMAC(?:-)?SHA(?:-)?(1|224|256|384|512)",
Pattern.CASE_INSENSITIVE);
private static final Pattern SLHDSA_STRENGTH_PATTERN = Pattern.compile("(128|192|256)");
private SecurityStrengthAdvisor() {
}
@@ -161,6 +164,7 @@ public final class SecurityStrengthAdvisor { // NOPMD
case "NTRU" -> ntruStrength(key);
case "SNTRUPRIME" -> sntruPrimeStrength(key);
case "NTRULPRIME" -> ntruLPrimeStrength(key);
case "SLH-DSA", "SLHDSA" -> slhDsaStrength(key);
case "SPHINCS+", "SPHINCSPLUS" -> sphincsPlusStrength(key);
case "DIGEST" -> 128;
default -> 128;
@@ -356,6 +360,31 @@ public final class SecurityStrengthAdvisor { // NOPMD
return 128;
}
private static int slhDsaStrength(Key key) {
// Provider strings observed: "SLH-DSA-SHAKE-128S", "slh-dsa-sha2-192f",
// sometimes with separators or additional tokens. We normalize and then parse.
String a = safeAlgo(key);
String normalized = a.toLowerCase(Locale.ROOT).replace('_', '-');
// Prefer explicit numeric strength markers (128/192/256) in the algorithm name.
Matcher m = SLHDSA_STRENGTH_PATTERN.matcher(normalized);
if (m.find()) {
int v = parseIntSafe(m.group(1));
if (v == 128 || v == 192 || v == 256) {
return v;
}
}
// Fall back to L1/L3/L5 markers when present.
int byLevel = mapByNistLevel(key, 128, 192, 256);
if (byLevel != 0) {
return byLevel;
}
// Conservative default.
return 128;
}
private static int mapByNistLevel(Key key, int l1, int l3, int l5) {
String a = safeAlgo(key);