1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 package org.apache.xml.security.test.interop;
20 
21 import java.io.File;
22 import java.security.PublicKey;
23 import java.security.cert.X509Certificate;
24 import java.util.Iterator;
25 
26 import javax.xml.xpath.XPath;
27 import javax.xml.xpath.XPathConstants;
28 import javax.xml.xpath.XPathFactory;
29 
30 import org.apache.xml.security.keys.KeyInfo;
31 import org.apache.xml.security.signature.Reference;
32 import org.apache.xml.security.signature.SignedInfo;
33 import org.apache.xml.security.signature.XMLSignature;
34 import org.apache.xml.security.signature.reference.ReferenceData;
35 import org.apache.xml.security.signature.reference.ReferenceNodeSetData;
36 import org.apache.xml.security.signature.reference.ReferenceOctetStreamData;
37 import org.apache.xml.security.test.DSNamespaceContext;
38 import org.apache.xml.security.utils.resolver.ResourceResolverSpi;
39 import org.w3c.dom.Element;
40 import org.w3c.dom.Node;
41 
42 public class InteropTestBase extends org.junit.Assert {
43 
44     /** {@link org.apache.commons.logging} logging facility */
45     static org.apache.commons.logging.Log log =
46         org.apache.commons.logging.LogFactory.getLog(InteropTestBase.class.getName());
47 
48     /** Field dbf */
49     static javax.xml.parsers.DocumentBuilderFactory dbf = null;
50 
51     /**
52      * Method setUp
53      *
54      */
InteropTestBase()55     public InteropTestBase() {
56         dbf = javax.xml.parsers.DocumentBuilderFactory.newInstance();
57         dbf.setNamespaceAware(true);
58     }
59 
60 
61     /**
62      * Method verifyHMAC
63      *
64      * @param filename
65      * @param resolver
66      * @param hmacKey
67      *
68      * @throws Exception
69      */
verifyHMAC( String filename, ResourceResolverSpi resolver, boolean followManifests, byte[] hmacKey )70     public boolean verifyHMAC(
71         String filename, ResourceResolverSpi resolver, boolean followManifests, byte[] hmacKey
72     ) throws Exception {
73         File f = new File(filename);
74         javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder();
75         org.w3c.dom.Document doc = db.parse(new java.io.FileInputStream(f));
76 
77         XPathFactory xpf = XPathFactory.newInstance();
78         XPath xpath = xpf.newXPath();
79         xpath.setNamespaceContext(new DSNamespaceContext());
80 
81         String expression = "//ds:Signature[1]";
82         Element sigElement =
83             (Element) xpath.evaluate(expression, doc, XPathConstants.NODE);
84         XMLSignature signature = new XMLSignature(sigElement, f.toURI().toURL().toString());
85 
86         if (resolver != null) {
87             signature.addResourceResolver(resolver);
88         }
89         signature.setFollowNestedManifests(followManifests);
90 
91         byte keybytes[] = hmacKey;
92         javax.crypto.SecretKey sk = signature.createSecretKey(keybytes);
93 
94         return signature.checkSignatureValue(sk);
95     }
96 
97     /**
98      * Method verify
99      *
100      * @param filename
101      * @param resolver
102      *
103      * @throws Exception
104      */
verify(String filename, ResourceResolverSpi resolver, boolean followManifests)105     public boolean verify(String filename, ResourceResolverSpi resolver, boolean followManifests)
106         throws Exception {
107         File f = new File(filename);
108         javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder();
109         org.w3c.dom.Document doc = db.parse(f);
110 
111         XPathFactory xpf = XPathFactory.newInstance();
112         XPath xpath = xpf.newXPath();
113         xpath.setNamespaceContext(new DSNamespaceContext());
114 
115         String expression = "//ds:Signature[1]";
116         Element sigElement =
117             (Element) xpath.evaluate(expression, doc, XPathConstants.NODE);
118         XMLSignature signature = new XMLSignature(sigElement, f.toURI().toURL().toString());
119 
120         if (resolver != null) {
121             signature.addResourceResolver(resolver);
122         }
123         signature.setFollowNestedManifests(followManifests);
124 
125 
126         KeyInfo ki = signature.getKeyInfo();
127         boolean result = false;
128         if (ki != null) {
129             X509Certificate cert = ki.getX509Certificate();
130 
131             if (cert != null) {
132                 result = signature.checkSignatureValue(cert);
133             } else {
134                 PublicKey pk = ki.getPublicKey();
135 
136                 if (pk != null) {
137                     result = signature.checkSignatureValue(pk);
138                 } else {
139                     throw new RuntimeException(
140                     "Did not find a public key, so I can't check the signature");
141                 }
142             }
143             checkReferences(signature);
144         } else {
145             throw new RuntimeException("Did not find a KeyInfo");
146         }
147         if (!result) {
148             for (int i = 0; i < signature.getSignedInfo().getLength(); i++) {
149                 boolean refVerify =
150                     signature.getSignedInfo().getVerificationResult(i);
151 
152                 if (refVerify) {
153                     log.debug("Reference " + i + " was OK");
154                 } else {
155                     // JavaUtils.writeBytesToFilename(filename + i + ".apache.txt", signature.getSignedInfo().item(i).getContentsAfterTransformation().getBytes());
156                     log.debug("Reference " + i + " was not OK");
157                 }
158             }
159             checkReferences(signature);
160             //throw new RuntimeException("Falle:"+sb.toString());
161         }
162 
163         return result;
164     }
165 
checkReferences(XMLSignature xmlSignature)166     private void checkReferences(XMLSignature xmlSignature) throws Exception {
167         SignedInfo signedInfo = xmlSignature.getSignedInfo();
168         assertTrue(signedInfo.getLength() > 0);
169         for (int i = 0; i < signedInfo.getLength(); i++) {
170             Reference reference = signedInfo.item(i);
171             assertNotNull(reference);
172             ReferenceData referenceData = reference.getReferenceData();
173             assertNotNull(referenceData);
174 
175             if (referenceData instanceof ReferenceNodeSetData) {
176                 Iterator<Node> iter = ((ReferenceNodeSetData)referenceData).iterator();
177                 assertTrue(iter.hasNext());
178                 boolean found = false;
179                 while (iter.hasNext()) {
180                     Node n = (Node)iter.next();
181                     if (n instanceof Element) {
182                         found = true;
183                         break;
184                     }
185                 }
186                 assertTrue(found);
187             } else if (referenceData instanceof ReferenceOctetStreamData) {
188                 assertNotNull(((ReferenceOctetStreamData)referenceData).getOctetStream());
189             }
190         }
191     }
192 
193 }
194