ValidationTests.java revision 12057:5d60882157c9
1/*
2 * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/**
25 * @test
26 * @bug 4635230 6365103 6366054 6824440 7131084 8046724 8079693
27 * @summary Basic unit tests for validating XML Signatures with JSR 105
28 * @modules java.base/sun.security.util
29 *          java.base/sun.security.x509
30 *          java.xml.crypto/org.jcp.xml.dsig.internal.dom
31 * @compile -XDignore.symbol.file KeySelectors.java SignatureValidator.java
32 *     X509KeySelector.java ValidationTests.java
33 * @run main/othervm ValidationTests
34 * @author Sean Mullan
35 */
36import java.io.File;
37import java.io.FileInputStream;
38import java.security.*;
39import javax.xml.crypto.Data;
40import javax.xml.crypto.KeySelector;
41import javax.xml.crypto.MarshalException;
42import javax.xml.crypto.OctetStreamData;
43import javax.xml.crypto.URIDereferencer;
44import javax.xml.crypto.URIReference;
45import javax.xml.crypto.URIReferenceException;
46import javax.xml.crypto.XMLCryptoContext;
47import javax.xml.crypto.dsig.XMLSignatureException;
48import javax.xml.crypto.dsig.XMLSignatureFactory;
49
50public class ValidationTests {
51
52    private static SignatureValidator validator;
53    private final static String DIR = System.getProperty("test.src", ".");
54    private final static String DATA_DIR =
55        DIR + System.getProperty("file.separator") + "data";
56    private final static String KEYSTORE =
57        DATA_DIR + System.getProperty("file.separator") + "certs" +
58        System.getProperty("file.separator") + "xmldsig.jks";
59    private final static String STYLESHEET =
60        "http://www.w3.org/TR/xml-stylesheet";
61    private final static String STYLESHEET_B64 =
62        "http://www.w3.org/Signature/2002/04/xml-stylesheet.b64";
63
64    static class Test {
65        String file;
66        KeySelector ks;
67        Class exception;
68
69        Test(String file, KeySelector ks, Class exception) {
70            this.file = file;
71            this.ks = ks;
72            this.exception = exception;
73        }
74
75        // XMLSignatureException is expected by default
76        Test(String file, KeySelector ks) {
77            this(file, ks, XMLSignatureException.class);
78        }
79    }
80
81    static KeySelector skks;
82    static {
83        try {
84            skks =
85                new KeySelectors.SecretKeySelector("secret".getBytes("ASCII"));
86        } catch (Exception e) {
87            //should not occur
88        }
89    }
90    private final static KeySelector SKKS = skks;
91    private final static KeySelector KVKS =
92        new KeySelectors.KeyValueKeySelector();
93    private final static KeySelector CKS =
94        new KeySelectors.CollectionKeySelector(new File(DATA_DIR));
95    private final static KeySelector RXKS =
96        new KeySelectors.RawX509KeySelector();
97    private final static KeySelector XKS = null;
98    private static URIDereferencer httpUd = null;
99
100    private final static Test[] VALID_TESTS = {
101        new Test("signature-enveloped-dsa.xml", KVKS),
102        new Test("signature-enveloping-b64-dsa.xml", KVKS),
103        new Test("signature-enveloping-dsa.xml", KVKS),
104        new Test("signature-enveloping-rsa.xml", KVKS),
105        new Test("signature-enveloping-p256-sha1.xml", KVKS),
106        new Test("signature-enveloping-p384-sha1.xml", KVKS),
107        new Test("signature-enveloping-p521-sha1.xml", KVKS),
108        new Test("signature-enveloping-hmac-sha1.xml", SKKS),
109        new Test("signature-external-dsa.xml", KVKS),
110        new Test("signature-external-b64-dsa.xml", KVKS),
111        new Test("signature-retrievalmethod-rawx509crt.xml", CKS),
112        new Test("signature-keyname.xml", CKS),
113        new Test("signature-x509-crt-crl.xml", RXKS),
114        new Test("signature-x509-crt.xml", RXKS),
115        new Test("signature-x509-is.xml", CKS),
116        new Test("signature-x509-ski.xml", CKS),
117        new Test("signature-x509-sn.xml", CKS),
118        new Test("signature.xml", XKS),
119        new Test("exc-signature.xml", KVKS),
120        new Test("sign-spec.xml", RXKS),
121        new Test("xmldsig-xfilter2.xml", KVKS)
122    };
123
124    private final static Test[] INVALID_TESTS = {
125        new Test("signature-enveloping-hmac-sha1-40.xml", SKKS),
126        new Test("signature-enveloping-hmac-sha1-trunclen-0-attack.xml", SKKS),
127        new Test("signature-enveloping-hmac-sha1-trunclen-8-attack.xml", SKKS),
128        new Test("signature-extra-text-in-signed-info.xml", SKKS,
129                MarshalException.class),
130        new Test("signature-wrong-canonicalization-method-algorithm.xml", SKKS,
131                MarshalException.class),
132        new Test("signature-wrong-transform-algorithm.xml", SKKS,
133                MarshalException.class),
134        new Test("signature-no-reference-uri.xml", SKKS),
135        new Test("signature-wrong-signature-method-algorithm.xml", SKKS,
136                MarshalException.class),
137        new Test("signature-wrong-tag-names.xml", SKKS, MarshalException.class)
138    };
139
140    public static void main(String args[]) throws Exception {
141        httpUd = new HttpURIDereferencer();
142
143        validator = new SignatureValidator(new File(DATA_DIR));
144
145        boolean atLeastOneFailed = false;
146        for (Test test : VALID_TESTS) {
147            System.out.println("Validating " + test.file);
148            if (test_signature(test)) {
149                System.out.println("PASSED");
150            } else {
151                System.out.println("FAILED");
152                atLeastOneFailed = true;
153            }
154        }
155        // test with reference caching enabled
156        System.out.println("Validating sign-spec.xml with caching enabled");
157        if (test_signature(new Test("sign-spec.xml", RXKS), true)) {
158            System.out.println("PASSED");
159        } else {
160            System.out.println("FAILED");
161            atLeastOneFailed = true;
162        }
163
164        for (Test test : INVALID_TESTS) {
165            System.out.println("Validating " + test.file);
166            try {
167                test_signature(test);
168                System.out.println("FAILED");
169                atLeastOneFailed = true;
170            } catch (Exception e) {
171                System.out.println("Exception: " + e);
172                if (e.getClass() != test.exception) {
173                    System.out.println("FAILED: unexpected exception");
174                    atLeastOneFailed = true;
175                } else {
176                    System.out.println("PASSED");
177                }
178            }
179        }
180
181        if (atLeastOneFailed) {
182            throw new Exception
183                ("At least one signature did not validate as expected");
184        }
185    }
186
187    public static boolean test_signature(Test test) throws Exception {
188        return test_signature(test, false);
189    }
190
191    public static boolean test_signature(Test test, boolean cache)
192        throws Exception
193    {
194        if (test.ks == null) {
195            KeyStore keystore = KeyStore.getInstance("JKS");
196            try (FileInputStream fis = new FileInputStream(KEYSTORE)) {
197                keystore.load(fis, "changeit".toCharArray());
198                test.ks = new X509KeySelector(keystore, false);
199            }
200        }
201        return validator.validate(test.file, test.ks, httpUd, cache);
202    }
203
204    /**
205     * This URIDereferencer returns locally cached copies of http content to
206     * avoid test failures due to network glitches, etc.
207     */
208    private static class HttpURIDereferencer implements URIDereferencer {
209        private URIDereferencer defaultUd;
210
211        HttpURIDereferencer() {
212            defaultUd = XMLSignatureFactory.getInstance().getURIDereferencer();
213        }
214
215        public Data dereference(final URIReference ref, XMLCryptoContext ctx)
216        throws URIReferenceException {
217            String uri = ref.getURI();
218            if (uri.equals(STYLESHEET) || uri.equals(STYLESHEET_B64)) {
219                try {
220                    FileInputStream fis = new FileInputStream(new File
221                        (DATA_DIR, uri.substring(uri.lastIndexOf('/'))));
222                    return new OctetStreamData(fis,ref.getURI(),ref.getType());
223                } catch (Exception e) { throw new URIReferenceException(e); }
224            }
225
226            // fallback on builtin deref
227            return defaultUd.dereference(ref, ctx);
228        }
229    }
230}
231