View Javadoc
1   /*
2    * Copyright 2001-2008 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   */
17  package org.apache.juddi.v3.tck;
18  
19  import java.io.BufferedReader;
20  import java.io.FileOutputStream;
21  import java.io.InputStream;
22  import java.io.InputStreamReader;
23  import java.security.InvalidAlgorithmParameterException;
24  import java.security.NoSuchAlgorithmException;
25  import java.security.PrivateKey;
26  import java.security.PublicKey;
27  import java.security.cert.Certificate;
28  import java.security.cert.X509Certificate;
29  import java.util.ArrayList;
30  import java.util.Collections;
31  import java.util.Iterator;
32  import java.util.List;
33  import javax.xml.XMLConstants;
34  
35  import javax.xml.crypto.dsig.CanonicalizationMethod;
36  import javax.xml.crypto.dsig.DigestMethod;
37  import javax.xml.crypto.dsig.Reference;
38  import javax.xml.crypto.dsig.SignatureMethod;
39  import javax.xml.crypto.dsig.SignedInfo;
40  import javax.xml.crypto.dsig.Transform;
41  import javax.xml.crypto.dsig.XMLSignature;
42  import javax.xml.crypto.dsig.XMLSignatureFactory;
43  import javax.xml.crypto.dsig.dom.DOMSignContext;
44  import javax.xml.crypto.dsig.dom.DOMValidateContext;
45  import javax.xml.crypto.dsig.keyinfo.KeyInfo;
46  import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
47  import javax.xml.crypto.dsig.keyinfo.X509Data;
48  import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
49  import javax.xml.crypto.dsig.spec.TransformParameterSpec;
50  import javax.xml.transform.Transformer;
51  import javax.xml.transform.TransformerFactory;
52  import javax.xml.transform.dom.DOMSource;
53  import javax.xml.transform.stream.StreamResult;
54  
55  import org.w3c.dom.Element;
56  import org.w3c.dom.Node;
57  import org.w3c.dom.NodeList;
58  
59  public class TckSigningUtil {
60  
61      private static XMLSignatureFactory initXMLSigFactory() {
62          XMLSignatureFactory fac = XMLSignatureFactory.getInstance();
63          return fac;
64      }
65  
66      private static Reference initReference(XMLSignatureFactory fac) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
67          List transformers = new ArrayList();
68          transformers.add(fac.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null));
69          Reference ref = fac.newReference("", fac.newDigestMethod(DigestMethod.SHA1, null), transformers, null, null);
70          return ref;
71      }
72  
73      private static SignedInfo initSignedInfo(XMLSignatureFactory fac) throws Exception {
74          Reference ref = initReference(fac);
75          SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE, (C14NMethodParameterSpec) null), fac.newSignatureMethod(SignatureMethod.DSA_SHA1, null), Collections.singletonList(ref));
76          return si;
77      }
78  
79      public static boolean verifySignature(Element element, PublicKey validatingKey) {
80          XMLSignatureFactory fac = initXMLSigFactory();
81          NodeList nl = element.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
82          if (nl.getLength() == 0) {
83              throw new RuntimeException("Cannot find Signature element");
84          }
85          DOMValidateContext valContext = new DOMValidateContext(validatingKey, nl.item(0));
86          try {
87              valContext.setProperty("javax.xml.crypto.dsig.cacheReference", Boolean.TRUE);
88              XMLSignature signature = fac.unmarshalXMLSignature(valContext);
89              boolean coreValidity = signature.validate(valContext);
90              // Check core validation status.
91              if (coreValidity == false) {
92                  System.err.println("Signature failed core validation");
93                  boolean sv = signature.getSignatureValue().validate(valContext);
94                  System.out.println("signature validation status: " + sv);
95                  // Check the validation status of each Reference.
96                  @SuppressWarnings("unchecked")
97                  Iterator<Reference> i = signature.getSignedInfo().getReferences().iterator();
98                  System.out.println("---------------------------------------------");
99                  for (int j = 0; i.hasNext(); j++) {
100                     Reference ref = (Reference) i.next();
101                     boolean refValid = ref.validate(valContext);
102                     System.out.println("ref[" + j + "] validity status: " + refValid);
103                     System.out.println("Ref type: " + ref.getType() + ", URI: " + ref.getURI());
104                     for (Object xform : ref.getTransforms()) {
105                         System.out.println("Transform: " + xform);
106                     }
107                     String calcDigValStr = digestToString(ref.getCalculatedDigestValue());
108                     String expectedDigValStr = digestToString(ref.getDigestValue());
109                     System.out.println("    Calc Digest: " + calcDigValStr);
110                     System.out.println("Expected Digest: " + expectedDigValStr);
111                     InputStream is = ref.getDigestInputStream();
112                     InputStreamReader isr = new InputStreamReader(is);
113                     BufferedReader br = new BufferedReader(isr);
114                     String line;
115                     while ((line = br.readLine()) != null) {
116                         System.out.println(line);
117                     }
118                     is.close();
119                     System.out.println("---------------------------------------------");
120                 }
121             } else {
122                 System.out.println("Signature passed core validation");
123             }
124             return coreValidity;
125         } catch (Exception e) {
126             throw new RuntimeException(e);
127         }
128     }
129 
130     private static String digestToString(byte[] digest) {
131         StringBuilder sb = new StringBuilder();
132         for (byte b : digest) {
133             String hex = Integer.toHexString(0xFF & b);
134             if (hex.length() == 1) {
135                 sb.append('0');
136             }
137             sb.append(hex);
138         }
139         return sb.toString();
140     }
141 
142     public static void signDOM(Node node, PrivateKey privateKey, Certificate origCert) {
143         XMLSignatureFactory fac = initXMLSigFactory();
144         X509Certificate cert = (X509Certificate) origCert;
145         // Create the KeyInfo containing the X509Data.
146         KeyInfoFactory kif = fac.getKeyInfoFactory();
147         List<Object> x509Content = new ArrayList<Object>();
148         x509Content.add(cert.getSubjectX500Principal().getName());
149         x509Content.add(cert);
150         X509Data xd = kif.newX509Data(x509Content);
151         KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));
152 
153         // Create a DOMSignContext and specify the RSA PrivateKey and
154         // location of the resulting XMLSignature's parent element.
155         DOMSignContext dsc = new DOMSignContext(privateKey, node);
156         dsc.putNamespacePrefix("http://www.w3.org/2000/09/xmldsig#", "ns2");
157 
158         // Create the XMLSignature, but don't sign it yet.
159         try {
160             SignedInfo si = initSignedInfo(fac);
161             XMLSignature signature = fac.newXMLSignature(si, ki);
162 
163             // Marshal, generate, and sign the enveloped signature.
164             signature.sign(dsc);
165         } catch (Exception e) {
166             throw new RuntimeException(e);
167         }
168     }
169     
170     public static void serializeNode(Node node, String filename) {
171         try {
172             TransformerFactory transFactory = TransformerFactory.newInstance();
173             transFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
174             transFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
175             Transformer transformer = transFactory.newTransformer();
176             DOMSource domSrc = new DOMSource(node);
177             FileOutputStream fos = new FileOutputStream(filename);
178             StreamResult streamResult = new StreamResult(fos);
179             transformer.transform(domSrc, streamResult);
180             fos.close();
181         } catch (Exception e) {
182             throw new RuntimeException(e);
183         }
184     }
185 }