8359395: XML signature generation does not support user provided SecureRandom

Reviewed-by: mullan
This commit is contained in:
Weijun Wang 2025-07-31 14:45:31 +00:00
parent 53d152e7db
commit b2b56cfc00
4 changed files with 134 additions and 5 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,6 +32,10 @@ import javax.xml.crypto.dom.DOMCryptoContext;
import javax.xml.crypto.dsig.XMLSignContext;
import javax.xml.crypto.dsig.XMLSignature;
import java.security.Key;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.Signature;
import org.w3c.dom.Node;
/**
@ -46,6 +50,17 @@ import org.w3c.dom.Node;
* (for example, you should not use the same <code>DOMSignContext</code>
* instance to sign two different {@link XMLSignature} objects).
*
* @implNote
* The JDK implementation supports the following property that can be set
* using the {@link #setProperty setProperty} method.
* <ul>
* <li><code>jdk.xmldsig.SecureRandom</code>: value must be a
* {@link SecureRandom}. If specified, this object will be
* used to initialize the underlying {@code Signature} during signing
* using the {@link Signature#initSign(PrivateKey, SecureRandom)}
* method.
* </ul>
*
* @author Sean Mullan
* @author JSR 105 Expert Group
* @since 1.6

View File

@ -21,7 +21,7 @@
* under the License.
*/
/*
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
*/
package org.jcp.xml.dsig.internal.dom;
@ -33,6 +33,7 @@ import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.AlgorithmParameterSpec;
@ -59,6 +60,7 @@ import org.w3c.dom.Text;
public abstract class DOMRSAPSSSignatureMethod extends AbstractDOMSignatureMethod {
private static final String DOM_SIGNATURE_PROVIDER = "org.jcp.xml.dsig.internal.dom.SignatureProvider";
private static final String DOM_SIGNATURE_RANDOM = "jdk.xmldsig.SecureRandom";
private static final com.sun.org.slf4j.internal.Logger LOG =
com.sun.org.slf4j.internal.LoggerFactory.getLogger(DOMRSAPSSSignatureMethod.class);
@ -324,7 +326,12 @@ public abstract class DOMRSAPSSSignatureMethod extends AbstractDOMSignatureMetho
throw new XMLSignatureException(nsae);
}
}
signature.initSign((PrivateKey)key);
SecureRandom sr = (SecureRandom)context.getProperty(DOM_SIGNATURE_RANDOM);
if (sr != null) {
signature.initSign((PrivateKey) key, sr);
} else {
signature.initSign((PrivateKey) key);
}
try {
signature.setParameter(spec);
} catch (InvalidAlgorithmParameterException e) {

View File

@ -21,7 +21,7 @@
* under the License.
*/
/*
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
*/
package org.jcp.xml.dsig.internal.dom;
@ -33,6 +33,7 @@ import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.DSAKey;
@ -64,6 +65,7 @@ import sun.security.util.KeyUtil;
public abstract class DOMSignatureMethod extends AbstractDOMSignatureMethod {
private static final String DOM_SIGNATURE_PROVIDER = "org.jcp.xml.dsig.internal.dom.SignatureProvider";
private static final String DOM_SIGNATURE_RANDOM = "jdk.xmldsig.SecureRandom";
private static final com.sun.org.slf4j.internal.Logger LOG =
com.sun.org.slf4j.internal.LoggerFactory.getLogger(DOMSignatureMethod.class);
@ -390,7 +392,12 @@ public abstract class DOMSignatureMethod extends AbstractDOMSignatureMethod {
throw new XMLSignatureException(nsae);
}
}
signature.initSign((PrivateKey)key);
SecureRandom sr = (SecureRandom)context.getProperty(DOM_SIGNATURE_RANDOM);
if (sr != null) {
signature.initSign((PrivateKey) key, sr);
} else {
signature.initSign((PrivateKey) key);
}
LOG.debug("Signature provider: {}", signature.getProvider());
LOG.debug("JCA Algorithm: {}", getJCAAlgorithm());

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import jdk.test.lib.Asserts;
import jdk.test.lib.security.SeededSecureRandom;
import jdk.test.lib.security.XMLUtils;
import org.w3c.dom.Document;
import javax.xml.crypto.dsig.XMLSignatureException;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.Base64;
/**
* @test
* @bug 8359395
* @summary ensure properties are used
* @library /test/lib
*/
public class Properties {
private static final String DOM_SIGNATURE_PROVIDER
= "org.jcp.xml.dsig.internal.dom.SignatureProvider";
private static final String DOM_SIGNATURE_RANDOM
= "jdk.xmldsig.SecureRandom";
public static void main(String[] args) throws Exception {
// Do not test on RSA. It's always deterministic.
test("EC");
test("RSASSA-PSS");
}
static void test(String alg) throws Exception {
var kp = KeyPairGenerator.getInstance(alg).generateKeyPair();
var signer = XMLUtils.signer(kp.getPrivate(), kp.getPublic());
var n1 = getSignature(signer.sign("hello")); // random one
var n2 = getSignature(signer.sign("hello")); // another random one
signer.prop(DOM_SIGNATURE_RANDOM, new SeededSecureRandom(1L));
var s1 = getSignature(signer.sign("hello")); // deterministic one
signer.prop(DOM_SIGNATURE_RANDOM, new SeededSecureRandom(1L));
var s1again = getSignature(signer.sign("hello")); // deterministic one repeated
signer.prop(DOM_SIGNATURE_RANDOM, new SeededSecureRandom(2L));
var s2 = getSignature(signer.sign("hello")); // deterministic two
Asserts.assertEqualsByteArray(s1, s1again);
assertsAllDifferent(n1, n2, s1, s2);
signer.prop(DOM_SIGNATURE_PROVIDER, Security.getProvider("SunJCE"));
// Asserts throwing XMLSignatureException with cause NoSuchAlgorithmException
Asserts.assertEquals(
Asserts.assertThrows(XMLSignatureException.class,
() -> signer.sign("hello")).getCause().getClass(),
NoSuchAlgorithmException.class);
}
private static void assertsAllDifferent(byte[]... inputs) {
for (var a : inputs) {
for (var b : inputs) {
if (a != b) {
Asserts.assertNotEqualsByteArray(a, b);
}
}
}
}
static byte[] getSignature(Document doc) {
for (var n = doc.getDocumentElement().getFirstChild();
n != null; n = n.getNextSibling()) {
if ("SignatureValue".equals(n.getLocalName())) {
return Base64.getMimeDecoder().decode(n.getTextContent());
}
}
throw new IllegalArgumentException("Not found");
}
}