a6427c85ee
Reviewed-by: rhalade, weijun
237 lines
9.1 KiB
Java
237 lines
9.1 KiB
Java
/*
|
|
* Copyright (c) 2005, 2021, 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.
|
|
*/
|
|
|
|
/**
|
|
* @test
|
|
* @bug 4635230 6365103 6366054 6824440 7131084 8046724 8079693
|
|
* @summary Basic unit tests for validating XML Signatures with JSR 105
|
|
* @modules java.base/sun.security.util
|
|
* java.base/sun.security.x509
|
|
* java.xml.crypto/org.jcp.xml.dsig.internal.dom
|
|
* @library /test/lib
|
|
* @compile -XDignore.symbol.file KeySelectors.java SignatureValidator.java
|
|
* X509KeySelector.java ValidationTests.java
|
|
* @run main/othervm ValidationTests
|
|
* @author Sean Mullan
|
|
*/
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.security.*;
|
|
import javax.xml.crypto.Data;
|
|
import javax.xml.crypto.KeySelector;
|
|
import javax.xml.crypto.MarshalException;
|
|
import javax.xml.crypto.OctetStreamData;
|
|
import javax.xml.crypto.URIDereferencer;
|
|
import javax.xml.crypto.URIReference;
|
|
import javax.xml.crypto.URIReferenceException;
|
|
import javax.xml.crypto.XMLCryptoContext;
|
|
import javax.xml.crypto.dsig.XMLSignatureException;
|
|
import javax.xml.crypto.dsig.XMLSignatureFactory;
|
|
|
|
import jdk.test.lib.security.SecurityUtils;
|
|
|
|
public class ValidationTests {
|
|
|
|
private static SignatureValidator validator;
|
|
private final static String DIR = System.getProperty("test.src", ".");
|
|
private final static String DATA_DIR =
|
|
DIR + System.getProperty("file.separator") + "data";
|
|
private final static String KEYSTORE =
|
|
DATA_DIR + System.getProperty("file.separator") + "certs" +
|
|
System.getProperty("file.separator") + "xmldsig.jks";
|
|
private final static String STYLESHEET =
|
|
"http://www.w3.org/TR/xml-stylesheet";
|
|
private final static String STYLESHEET_B64 =
|
|
"http://www.w3.org/Signature/2002/04/xml-stylesheet.b64";
|
|
|
|
static class Test {
|
|
String file;
|
|
KeySelector ks;
|
|
Class exception;
|
|
|
|
Test(String file, KeySelector ks, Class exception) {
|
|
this.file = file;
|
|
this.ks = ks;
|
|
this.exception = exception;
|
|
}
|
|
|
|
// XMLSignatureException is expected by default
|
|
Test(String file, KeySelector ks) {
|
|
this(file, ks, XMLSignatureException.class);
|
|
}
|
|
}
|
|
|
|
static KeySelector skks;
|
|
static {
|
|
try {
|
|
skks =
|
|
new KeySelectors.SecretKeySelector("secret".getBytes("ASCII"));
|
|
} catch (Exception e) {
|
|
//should not occur
|
|
}
|
|
}
|
|
private final static KeySelector SKKS = skks;
|
|
private final static KeySelector KVKS =
|
|
new KeySelectors.KeyValueKeySelector();
|
|
private final static KeySelector CKS =
|
|
new KeySelectors.CollectionKeySelector(new File(DATA_DIR));
|
|
private final static KeySelector RXKS =
|
|
new KeySelectors.RawX509KeySelector();
|
|
private final static KeySelector XKS = null;
|
|
private static URIDereferencer httpUd = null;
|
|
|
|
private final static Test[] VALID_TESTS = {
|
|
new Test("signature-enveloped-dsa.xml", KVKS),
|
|
new Test("signature-enveloping-b64-dsa.xml", KVKS),
|
|
new Test("signature-enveloping-dsa.xml", KVKS),
|
|
new Test("signature-enveloping-rsa.xml", KVKS),
|
|
new Test("signature-enveloping-p256-sha1.xml", KVKS),
|
|
new Test("signature-enveloping-p384-sha1.xml", KVKS),
|
|
new Test("signature-enveloping-p521-sha1.xml", KVKS),
|
|
new Test("signature-enveloping-hmac-sha1.xml", SKKS),
|
|
new Test("signature-external-dsa.xml", KVKS),
|
|
new Test("signature-external-b64-dsa.xml", KVKS),
|
|
new Test("signature-retrievalmethod-rawx509crt.xml", CKS),
|
|
new Test("signature-keyname.xml", CKS),
|
|
new Test("signature-x509-crt-crl.xml", RXKS),
|
|
new Test("signature-x509-crt.xml", RXKS),
|
|
new Test("signature-x509-is.xml", CKS),
|
|
new Test("signature-x509-ski.xml", CKS),
|
|
new Test("signature-x509-sn.xml", CKS),
|
|
new Test("signature.xml", XKS),
|
|
new Test("exc-signature.xml", KVKS),
|
|
new Test("sign-spec.xml", RXKS),
|
|
new Test("xmldsig-xfilter2.xml", KVKS)
|
|
};
|
|
|
|
private final static Test[] INVALID_TESTS = {
|
|
new Test("signature-enveloping-hmac-sha1-40.xml", SKKS),
|
|
new Test("signature-enveloping-hmac-sha1-trunclen-0-attack.xml", SKKS),
|
|
new Test("signature-enveloping-hmac-sha1-trunclen-8-attack.xml", SKKS),
|
|
new Test("signature-extra-text-in-signed-info.xml", SKKS,
|
|
MarshalException.class),
|
|
new Test("signature-wrong-canonicalization-method-algorithm.xml", SKKS,
|
|
MarshalException.class),
|
|
new Test("signature-wrong-transform-algorithm.xml", SKKS,
|
|
MarshalException.class),
|
|
new Test("signature-no-reference-uri.xml", SKKS),
|
|
new Test("signature-wrong-signature-method-algorithm.xml", SKKS,
|
|
MarshalException.class),
|
|
new Test("signature-wrong-tag-names.xml", SKKS, MarshalException.class)
|
|
};
|
|
|
|
public static void main(String args[]) throws Exception {
|
|
// Re-enable sha1 algs
|
|
SecurityUtils.removeAlgsFromDSigPolicy("sha1");
|
|
|
|
httpUd = new HttpURIDereferencer();
|
|
|
|
validator = new SignatureValidator(new File(DATA_DIR));
|
|
|
|
boolean atLeastOneFailed = false;
|
|
for (Test test : VALID_TESTS) {
|
|
System.out.println("Validating " + test.file);
|
|
if (test_signature(test)) {
|
|
System.out.println("PASSED");
|
|
} else {
|
|
System.out.println("FAILED");
|
|
atLeastOneFailed = true;
|
|
}
|
|
}
|
|
// test with reference caching enabled
|
|
System.out.println("Validating sign-spec.xml with caching enabled");
|
|
if (test_signature(new Test("sign-spec.xml", RXKS), true)) {
|
|
System.out.println("PASSED");
|
|
} else {
|
|
System.out.println("FAILED");
|
|
atLeastOneFailed = true;
|
|
}
|
|
|
|
for (Test test : INVALID_TESTS) {
|
|
System.out.println("Validating " + test.file);
|
|
try {
|
|
test_signature(test);
|
|
System.out.println("FAILED");
|
|
atLeastOneFailed = true;
|
|
} catch (Exception e) {
|
|
System.out.println("Exception: " + e);
|
|
if (e.getClass() != test.exception) {
|
|
System.out.println("FAILED: unexpected exception");
|
|
atLeastOneFailed = true;
|
|
} else {
|
|
System.out.println("PASSED");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (atLeastOneFailed) {
|
|
throw new Exception
|
|
("At least one signature did not validate as expected");
|
|
}
|
|
}
|
|
|
|
public static boolean test_signature(Test test) throws Exception {
|
|
return test_signature(test, false);
|
|
}
|
|
|
|
public static boolean test_signature(Test test, boolean cache)
|
|
throws Exception
|
|
{
|
|
if (test.ks == null) {
|
|
KeyStore keystore = KeyStore.getInstance("JKS");
|
|
try (FileInputStream fis = new FileInputStream(KEYSTORE)) {
|
|
keystore.load(fis, "changeit".toCharArray());
|
|
test.ks = new X509KeySelector(keystore, false);
|
|
}
|
|
}
|
|
return validator.validate(test.file, test.ks, httpUd, cache);
|
|
}
|
|
|
|
/**
|
|
* This URIDereferencer returns locally cached copies of http content to
|
|
* avoid test failures due to network glitches, etc.
|
|
*/
|
|
private static class HttpURIDereferencer implements URIDereferencer {
|
|
private URIDereferencer defaultUd;
|
|
|
|
HttpURIDereferencer() {
|
|
defaultUd = XMLSignatureFactory.getInstance().getURIDereferencer();
|
|
}
|
|
|
|
public Data dereference(final URIReference ref, XMLCryptoContext ctx)
|
|
throws URIReferenceException {
|
|
String uri = ref.getURI();
|
|
if (uri.equals(STYLESHEET) || uri.equals(STYLESHEET_B64)) {
|
|
try {
|
|
FileInputStream fis = new FileInputStream(new File
|
|
(DATA_DIR, uri.substring(uri.lastIndexOf('/'))));
|
|
return new OctetStreamData(fis,ref.getURI(),ref.getType());
|
|
} catch (Exception e) { throw new URIReferenceException(e); }
|
|
}
|
|
|
|
// fallback on builtin deref
|
|
return defaultUd.dereference(ref, ctx);
|
|
}
|
|
}
|
|
}
|