This is an automated email from the ASF dual-hosted git repository.
coheigea pushed a commit to branch 3_0_x-fixes
in repository https://gitbox.apache.org/repos/asf/ws-wss4j.git
The following commit(s) were added to refs/heads/3_0_x-fixes by this push:
new b4141b62b Put a lower bound of 16 bytes on minimum derived key length
(#667)
b4141b62b is described below
commit b4141b62b1ff5fa76ddd25285d9d68e2f50a7c75
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Thu Sep 3 16:27:09 2026 +0100
Put a lower bound of 16 bytes on minimum derived key length (#667)
---
.../wss4j/common/derivedKey/DerivedKeyUtils.java | 16 +++++
.../common/derivedKey/DerivedKeyUtilsTest.java | 70 ++++++++++++++++++++++
.../output/DerivedKeyTokenOutputProcessor.java | 6 +-
3 files changed, 90 insertions(+), 2 deletions(-)
diff --git
a/ws-security-common/src/main/java/org/apache/wss4j/common/derivedKey/DerivedKeyUtils.java
b/ws-security-common/src/main/java/org/apache/wss4j/common/derivedKey/DerivedKeyUtils.java
index 4d1c88929..08fe625ee 100644
---
a/ws-security-common/src/main/java/org/apache/wss4j/common/derivedKey/DerivedKeyUtils.java
+++
b/ws-security-common/src/main/java/org/apache/wss4j/common/derivedKey/DerivedKeyUtils.java
@@ -24,6 +24,15 @@ import org.apache.wss4j.common.ext.WSSecurityException;
public final class DerivedKeyUtils {
+ /**
+ * The minimum length in bytes of a derived key (128 bits). The wsc:Length
value is
+ * attacker-controlled message content: a shorter derived key (e.g.
Length=1) reduces
+ * an HMAC signature key to a trivially brute-forceable keyspace. No
standard
+ * WS-SecurityPolicy algorithm suite derives keys shorter than 128 bits,
so this is
+ * enforced as a hard engine-level floor, independent of any configured
AlgorithmSuite.
+ */
+ public static final int MINIMUM_DERIVED_KEY_LENGTH = 16;
+
private DerivedKeyUtils() {
// complete
}
@@ -55,6 +64,13 @@ public final class DerivedKeyUtils {
if (keyLength <= 0) {
keyLength = 32L;
}
+ if (keyLength < MINIMUM_DERIVED_KEY_LENGTH) {
+ throw new
WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY,
+ "unsupportedKeyId",
+ new Object[] {"Requested derived key length of " + keyLength
+ + " byte(s) is less than the minimum allowed ("
+ + MINIMUM_DERIVED_KEY_LENGTH + " bytes)"});
+ }
return algo.createKey(secret, seed, offset, keyLength);
}
}
diff --git
a/ws-security-common/src/test/java/org/apache/wss4j/common/derivedKey/DerivedKeyUtilsTest.java
b/ws-security-common/src/test/java/org/apache/wss4j/common/derivedKey/DerivedKeyUtilsTest.java
new file mode 100644
index 000000000..bf50941bd
--- /dev/null
+++
b/ws-security-common/src/test/java/org/apache/wss4j/common/derivedKey/DerivedKeyUtilsTest.java
@@ -0,0 +1,70 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.wss4j.common.derivedKey;
+
+import org.apache.wss4j.common.ext.WSSecurityException;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+class DerivedKeyUtilsTest {
+
+ private static final byte[] SECRET =
"0123456789abcdef".getBytes(java.nio.charset.StandardCharsets.UTF_8);
+ private static final byte[] NONCE =
"abcdefghijklmnop".getBytes(java.nio.charset.StandardCharsets.UTF_8);
+
+ @Test
+ void rejectsPositiveDerivedKeyLengthsBelowMinimum() {
+ WSSecurityException exception =
Assertions.assertThrows(WSSecurityException.class,
+ () -> DerivedKeyUtils.deriveKey(
+ ConversationConstants.DerivationAlgorithm.P_SHA_1,
+ null,
+ DerivedKeyUtils.MINIMUM_DERIVED_KEY_LENGTH - 1,
+ SECRET,
+ NONCE,
+ 0));
+
+
Assertions.assertEquals(WSSecurityException.ErrorCode.INVALID_SECURITY,
exception.getErrorCode());
+ }
+
+ @Test
+ void acceptsMinimumDerivedKeyLength() throws Exception {
+ byte[] key = DerivedKeyUtils.deriveKey(
+ ConversationConstants.DerivationAlgorithm.P_SHA_1,
+ null,
+ DerivedKeyUtils.MINIMUM_DERIVED_KEY_LENGTH,
+ SECRET,
+ NONCE,
+ 0);
+
+ Assertions.assertEquals(DerivedKeyUtils.MINIMUM_DERIVED_KEY_LENGTH,
key.length);
+ }
+
+ @Test
+ void preservesDefaultDerivedKeyLength() throws Exception {
+ byte[] key = DerivedKeyUtils.deriveKey(
+ ConversationConstants.DerivationAlgorithm.P_SHA_1,
+ null,
+ 0,
+ SECRET,
+ NONCE,
+ 0);
+
+ Assertions.assertEquals(32, key.length);
+ }
+}
diff --git
a/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/DerivedKeyTokenOutputProcessor.java
b/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/DerivedKeyTokenOutputProcessor.java
index a0fe52dff..929809569 100644
---
a/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/DerivedKeyTokenOutputProcessor.java
+++
b/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/processor/output/DerivedKeyTokenOutputProcessor.java
@@ -88,7 +88,8 @@ public class DerivedKeyTokenOutputProcessor extends
AbstractOutputProcessor {
} else {
length =
JCEAlgorithmMapper.getKeyLengthFromURI(getSecurityProperties().getSignatureAlgorithm())
/ 8;
if (length == 0) {
- length =
KeyUtils.getKeyLength(getSecurityProperties().getSignatureAlgorithm()) / 8;
+ // KeyUtils.getKeyLength already returns a length in
bytes
+ length =
KeyUtils.getKeyLength(getSecurityProperties().getSignatureAlgorithm());
}
}
} else if
(WSSConstants.ENCRYPTION_WITH_DERIVED_KEY.equals(action)) {
@@ -97,7 +98,8 @@ public class DerivedKeyTokenOutputProcessor extends
AbstractOutputProcessor {
} else {
length =
JCEAlgorithmMapper.getKeyLengthFromURI(getSecurityProperties().getEncryptionSymAlgorithm())
/ 8;
if (length == 0) {
- length =
KeyUtils.getKeyLength(getSecurityProperties().getEncryptionSymAlgorithm()) / 8;
+ // KeyUtils.getKeyLength already returns a length in
bytes
+ length =
KeyUtils.getKeyLength(getSecurityProperties().getEncryptionSymAlgorithm());
}
}
}