This is an automated email from the ASF dual-hosted git repository.
coheigea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ws-wss4j.git
The following commit(s) were added to refs/heads/master by this push:
new add6d92ea Finishing DER work (#727)
add6d92ea is described below
commit add6d92eabf6541c6b977c988428267c732ce877
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Tue Sep 22 10:01:43 2026 +0100
Finishing DER work (#727)
---
src/site/asciidoc/wss4j40.adoc | 38 +++++++++---
.../wss4j/common/crypto/BouncyCastleUtils.java | 68 ++++++++++++++++++++++
...ierTest.java => X509KeyIdentifierUtilTest.java} | 31 ++++++++--
3 files changed, 125 insertions(+), 12 deletions(-)
diff --git a/src/site/asciidoc/wss4j40.adoc b/src/site/asciidoc/wss4j40.adoc
index 9d25ca610..db0f3eaea 100644
--- a/src/site/asciidoc/wss4j40.adoc
+++ b/src/site/asciidoc/wss4j40.adoc
@@ -17,10 +17,34 @@
// under the License.
//
-=== Apache WSS4J 4.0.0 Migration Guide
+=== Apache WSS4J 4.0.x Migration Guide
-This section is a migration guide for helping Apache WSS4J 3.0.x users to
migrate
-to the 4.0.x releases.
+This section covers changes within the 4.0.x releases that may affect existing
+code. Everything described below was introduced in 4.0.2.
+
+==== BouncyCastleUtils renamed to X509KeyIdentifierUtil
+
+`org.apache.wss4j.common.crypto.BouncyCastleUtils` is now
+`org.apache.wss4j.common.crypto.X509KeyIdentifierUtil`. The class no longer
uses
+Bouncy Castle, so the old name was misleading. Its two methods,
+`getSubjectKeyIdentifierBytes` and `getAuthorityKeyIdentifierBytes`, keep their
+names and signatures.
+
+`BouncyCastleUtils` is retained as a deprecated class that delegates to the new
+one, so code written against 4.0.1 and earlier keeps working. It is marked for
+removal and will be dropped in a later release, so move to
+`X509KeyIdentifierUtil` when convenient.
+
+==== DOMX509SKI signals a malformed SubjectKeyIdentifier
+
+`org.apache.wss4j.common.token.DOMX509SKI`'s
+`DOMX509SKI(Document, X509Certificate)` constructor now declares
+`throws WSSecurityException`, raised when the certificate's
SubjectKeyIdentifier
+extension is present but will not decode. Previously it threw an unchecked
+exception from a constructor with no throws clause.
+
+Code constructing this class directly must handle or propagate the exception.
+This is a source compatibility change only; existing compiled callers still
link.
==== Stricter DER decoding of X.509 key identifiers
@@ -45,10 +69,10 @@ The encodings that change behaviour are:
the `[0]` field.
Such a certificate now causes an `IllegalArgumentException` from
-`BouncyCastleUtils.getSubjectKeyIdentifierBytes` and
-`BouncyCastleUtils.getAuthorityKeyIdentifierBytes`, and a `WSSecurityException`
-from `Crypto.getSKIBytesFromCert`. This surfaces when signing with an SKI key
-identifier (`DOMX509SKI`) and when establishing trust with `MerlinAKI`.
+`X509KeyIdentifierUtil.getSubjectKeyIdentifierBytes` and
+`X509KeyIdentifierUtil.getAuthorityKeyIdentifierBytes`, and a
+`WSSecurityException` from `Crypto.getSKIBytesFromCert`, from `DOMX509SKI` when
+signing with an SKI key identifier, and from `MerlinAKI` when establishing
trust.
If you hit this, the certificate is malformed and should be reissued. There is
no
configuration option to restore the previous tolerance.
diff --git
a/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/BouncyCastleUtils.java
b/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/BouncyCastleUtils.java
new file mode 100644
index 000000000..f7966328d
--- /dev/null
+++
b/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/BouncyCastleUtils.java
@@ -0,0 +1,68 @@
+/**
+ * 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.crypto;
+
+import java.security.cert.X509Certificate;
+
+/**
+ * Decodes the X.509 key identifier extensions.
+ *
+ * @deprecated the decoding no longer uses Bouncy Castle, so this class was
renamed to
+ * {@link X509KeyIdentifierUtil}. This name is retained for
callers compiled against
+ * 4.0.1 and earlier, and delegates to the new class. Use
+ * {@link X509KeyIdentifierUtil} instead.
+ */
+@Deprecated(since = "4.0.2", forRemoval = true)
+public final class BouncyCastleUtils {
+
+ private BouncyCastleUtils() {
+ // complete
+ }
+
+ /**
+ * Read the keyIdentifier of the AuthorityKeyIdentifier extension
(2.5.29.35) of the
+ * given certificate.
+ *
+ * @param cert the certificate to read the AuthorityKeyIdentifier from.
+ * @return an empty array if the certificate has no AuthorityKeyIdentifier
extension, null if
+ * the extension is present but carries no keyIdentifier,
otherwise the keyIdentifier.
+ * @throws IllegalArgumentException if the extension is present but is not
valid DER.
+ * @deprecated use {@link
X509KeyIdentifierUtil#getAuthorityKeyIdentifierBytes(X509Certificate)}
+ */
+ @Deprecated(since = "4.0.2", forRemoval = true)
+ public static byte[] getAuthorityKeyIdentifierBytes(X509Certificate cert) {
+ return X509KeyIdentifierUtil.getAuthorityKeyIdentifierBytes(cert);
+ }
+
+ /**
+ * Read the SubjectKeyIdentifier extension (2.5.29.14) of the given
certificate.
+ *
+ * @param cert the certificate to read the SubjectKeyIdentifier from.
+ * @return an empty array if the certificate has no SubjectKeyIdentifier
extension, otherwise
+ * the key identifier.
+ * @throws IllegalArgumentException if the extension is present but is not
valid DER.
+ * @deprecated use {@link
X509KeyIdentifierUtil#getSubjectKeyIdentifierBytes(X509Certificate)}
+ */
+ @Deprecated(since = "4.0.2", forRemoval = true)
+ public static byte[] getSubjectKeyIdentifierBytes(X509Certificate cert) {
+ return X509KeyIdentifierUtil.getSubjectKeyIdentifierBytes(cert);
+ }
+
+}
diff --git
a/ws-security-common/src/test/java/org/apache/wss4j/common/crypto/AuthorityKeyIdentifierTest.java
b/ws-security-common/src/test/java/org/apache/wss4j/common/crypto/X509KeyIdentifierUtilTest.java
similarity index 84%
rename from
ws-security-common/src/test/java/org/apache/wss4j/common/crypto/AuthorityKeyIdentifierTest.java
rename to
ws-security-common/src/test/java/org/apache/wss4j/common/crypto/X509KeyIdentifierUtilTest.java
index 95c6e1a37..f63bd31d0 100644
---
a/ws-security-common/src/test/java/org/apache/wss4j/common/crypto/AuthorityKeyIdentifierTest.java
+++
b/ws-security-common/src/test/java/org/apache/wss4j/common/crypto/X509KeyIdentifierUtilTest.java
@@ -36,12 +36,12 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
/**
- * This is a test for extracting AuthorityKeyIdentifier/SubjectKeyIdentifier
information from
- * certificates.
+ * This is a test for X509KeyIdentifierUtil, which extracts
AuthorityKeyIdentifier and
+ * SubjectKeyIdentifier information from certificates.
*/
-public class AuthorityKeyIdentifierTest {
+public class X509KeyIdentifierUtilTest {
- public AuthorityKeyIdentifierTest() {
+ public X509KeyIdentifierUtilTest() {
WSProviderConfig.init();
}
@@ -120,6 +120,27 @@ public class AuthorityKeyIdentifierTest {
);
}
+ /**
+ * BouncyCastleUtils is the pre-4.0.2 name of this class, kept as a
deprecated delegate so
+ * that code written against 4.0.1 and earlier still compiles and behaves
the same.
+ */
+ @Test
+ @SuppressWarnings("removal")
+ public void testDeprecatedBouncyCastleUtilsDelegates() throws Exception {
+ KeyStore keyStore = loadKeyStore("keys/wss40.jks", "security");
+ X509Certificate cert =
(X509Certificate)keyStore.getCertificate("wss40");
+ assertNotNull(cert);
+
+ assertArrayEquals(
+ X509KeyIdentifierUtil.getAuthorityKeyIdentifierBytes(cert),
+ BouncyCastleUtils.getAuthorityKeyIdentifierBytes(cert)
+ );
+ assertArrayEquals(
+ X509KeyIdentifierUtil.getSubjectKeyIdentifierBytes(cert),
+ BouncyCastleUtils.getSubjectKeyIdentifierBytes(cert)
+ );
+ }
+
@Test
public void testMerlinAKI() throws Exception {
// Load the keystore
@@ -153,7 +174,7 @@ public class AuthorityKeyIdentifierTest {
private KeyStore loadKeyStore(String path, String password) throws
Exception {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
- ClassLoader loader =
Loader.getClassLoader(AuthorityKeyIdentifierTest.class);
+ ClassLoader loader =
Loader.getClassLoader(X509KeyIdentifierUtilTest.class);
InputStream input = Merlin.loadInputStream(loader, path);
keyStore.load(input, password.toCharArray());
input.close();