blob: 453bbf459896e06ae85387d242b3f5d3f1e28a4d [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * reserved comment block
3 * DO NOT REMOVE OR ALTER!
4 */
5/*
6 * Copyright 1999-2004 The Apache Software Foundation.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 */
21package com.sun.org.apache.xml.internal.security.signature;
22
23
24
25import java.io.ByteArrayInputStream;
26import java.io.IOException;
27import java.io.OutputStream;
28
29import javax.crypto.SecretKey;
30import javax.crypto.spec.SecretKeySpec;
31import javax.xml.parsers.ParserConfigurationException;
32
33import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithm;
34import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;
35import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer;
36import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException;
37import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
38import com.sun.org.apache.xml.internal.security.utils.Constants;
39import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
40import com.sun.org.apache.xml.internal.security.transforms.params.InclusiveNamespaces;
41import org.w3c.dom.Document;
42import org.w3c.dom.Element;
43import org.w3c.dom.Node;
44import org.xml.sax.SAXException;
45
46
47/**
48 * Handles <code>&lt;ds:SignedInfo&gt;</code> elements
49 * This <code>SignedInfo<code> element includes the canonicalization algorithm,
50 * a signature algorithm, and one or more references
51 * @author Christian Geuer-Pollmann
52 */
53public class SignedInfo extends Manifest {
54
55 /** Field _signatureAlgorithm */
56 private SignatureAlgorithm _signatureAlgorithm = null;
57
58 /** Field _c14nizedBytes */
59 private byte[] _c14nizedBytes = null;
60
61 /**
62 * Overwrites {@link Manifest#addDocument} because it creates another Element.
63 *
64 * @param doc the {@link Document} in which <code>XMLsignature</code> will be placed
65 * @throws XMLSecurityException
66 */
67 public SignedInfo(Document doc) throws XMLSecurityException {
68 this(doc, XMLSignature.ALGO_ID_SIGNATURE_DSA, Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS);
69 }
70
71 /**
72 * Constructs {@link SignedInfo} using given Canoicaliztion algorithm and Signature algorithm
73 *
74 * @param doc <code>SignedInfo</code> is placed in this document
75 * @param CanonicalizationMethodURI URI representation of the Canonicalization method
76 * @param SignatureMethodURI URI representation of the Digest and Signature algorithm
77 * @throws XMLSecurityException
78 */
79 public SignedInfo(
80 Document doc, String SignatureMethodURI, String CanonicalizationMethodURI)
81 throws XMLSecurityException {
82 this(doc, SignatureMethodURI, 0, CanonicalizationMethodURI);
83 }
84
85 /**
86 * Constructor SignedInfo
87 *
88 * @param doc
89 * @param CanonicalizationMethodURI
90 * @param SignatureMethodURI
91 * @param HMACOutputLength
92 * @throws XMLSecurityException
93 */
94 public SignedInfo(
95 Document doc, String SignatureMethodURI, int HMACOutputLength, String CanonicalizationMethodURI)
96 throws XMLSecurityException {
97
98 super(doc);
99
100 // XMLUtils.addReturnToElement(this._constructionElement);
101 {
102 Element canonElem = XMLUtils.createElementInSignatureSpace(this._doc,
103 Constants._TAG_CANONICALIZATIONMETHOD);
104
105 canonElem.setAttributeNS(null, Constants._ATT_ALGORITHM,
106 CanonicalizationMethodURI);
107 this._constructionElement.appendChild(canonElem);
108 XMLUtils.addReturnToElement(this._constructionElement);
109 }
110 {
111 if (HMACOutputLength > 0) {
112 this._signatureAlgorithm = new SignatureAlgorithm(this._doc,
113 SignatureMethodURI, HMACOutputLength);
114 } else {
115 this._signatureAlgorithm = new SignatureAlgorithm(this._doc,
116 SignatureMethodURI);
117 }
118
119 this._constructionElement
120 .appendChild(this._signatureAlgorithm.getElement());
121 XMLUtils.addReturnToElement(this._constructionElement);
122 }
123 }
124
125 /**
126 * @param doc
127 * @param SignatureMethodElem
128 * @param CanonicalizationMethodElem
129 * @throws XMLSecurityException
130 */
131 public SignedInfo(
132 Document doc, Element SignatureMethodElem, Element CanonicalizationMethodElem)
133 throws XMLSecurityException {
134
135 super(doc);
136
137 this._constructionElement.appendChild(CanonicalizationMethodElem);
138 XMLUtils.addReturnToElement(this._constructionElement);
139
140 this._signatureAlgorithm = new SignatureAlgorithm(SignatureMethodElem, null);
141
142 this._constructionElement
143 .appendChild(this._signatureAlgorithm.getElement());
144 XMLUtils.addReturnToElement(this._constructionElement);
145 }
146
147 /**
148 * Build a {@link SignedInfo} from an {@link Element}
149 *
150 * @param element <code>SignedInfo</code>
151 * @param BaseURI the URI of the resource where the XML instance was stored
152 * @throws XMLSecurityException
153 * @see <A HREF="http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001OctDec/0033.html">Question</A>
154 * @see <A HREF="http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001OctDec/0054.html">Answer</A>
155 */
156 public SignedInfo(Element element, String BaseURI)
157 throws XMLSecurityException {
158
159 // Parse the Reference children and Id attribute in the Manifest
160 super(element, BaseURI);
161
162 /* canonicalize ds:SignedInfo, reparse it into a new document
163 * and replace the original not-canonicalized ds:SignedInfo by
164 * the re-parsed canonicalized one.
165 */
166 String c14nMethodURI=this.getCanonicalizationMethodURI();
167 if (!(c14nMethodURI.equals("http://www.w3.org/TR/2001/REC-xml-c14n-20010315") ||
168 c14nMethodURI.equals("http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments") ||
169 c14nMethodURI.equals("http://www.w3.org/2001/10/xml-exc-c14n#") ||
170 c14nMethodURI.equals("http://www.w3.org/2001/10/xml-exc-c14n#WithComments"))) {
171 //The c14n is not a secure one and can rewrite the URIs or like that reparse the SignedInfo to be sure
172 try {
173 Canonicalizer c14nizer =
174 Canonicalizer.getInstance(this.getCanonicalizationMethodURI());
175
176 this._c14nizedBytes =
177 c14nizer.canonicalizeSubtree(this._constructionElement);
178 javax.xml.parsers.DocumentBuilderFactory dbf =
179 javax.xml.parsers.DocumentBuilderFactory.newInstance();
180
181 dbf.setNamespaceAware(true);
182
183 javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder();
184 org.w3c.dom.Document newdoc =
185 db.parse(new ByteArrayInputStream(this._c14nizedBytes));
186 Node imported = this._doc.importNode(newdoc.getDocumentElement(),
187 true);
188
189 this._constructionElement.getParentNode().replaceChild(imported,
190 this._constructionElement);
191
192 this._constructionElement = (Element) imported;
193 } catch (ParserConfigurationException ex) {
194 throw new XMLSecurityException("empty", ex);
195 } catch (IOException ex) {
196 throw new XMLSecurityException("empty", ex);
197 } catch (SAXException ex) {
198 throw new XMLSecurityException("empty", ex);
199 }
200 }
201 this._signatureAlgorithm =
202 new SignatureAlgorithm(this.getSignatureMethodElement(),
203 this.getBaseURI());
204 }
205
206 /**
207 * Tests core validation process
208 *
209 * @return true if verification was successful
210 * @throws MissingResourceFailureException
211 * @throws XMLSecurityException
212 */
213 public boolean verify()
214 throws MissingResourceFailureException, XMLSecurityException {
215 return super.verifyReferences(false);
216 }
217
218 /**
219 * Tests core validation process
220 *
221 * @param followManifests defines whether the verification process has to verify referenced <CODE>ds:Manifest</CODE>s, too
222 * @return true if verification was successful
223 * @throws MissingResourceFailureException
224 * @throws XMLSecurityException
225 */
226 public boolean verify(boolean followManifests)
227 throws MissingResourceFailureException, XMLSecurityException {
228 return super.verifyReferences(followManifests);
229 }
230
231 /**
232 * Returns getCanonicalizedOctetStream
233 *
234 * @return the canonicalization result octedt stream of <code>SignedInfo</code> element
235 * @throws CanonicalizationException
236 * @throws InvalidCanonicalizerException
237 * @throws XMLSecurityException
238 */
239 public byte[] getCanonicalizedOctetStream()
240 throws CanonicalizationException, InvalidCanonicalizerException,
241 XMLSecurityException {
242
243 if ((this._c14nizedBytes == null)
244 /*&& (this._state == ElementProxy.MODE_SIGN)*/) {
245 Canonicalizer c14nizer =
246 Canonicalizer.getInstance(this.getCanonicalizationMethodURI());
247
248 this._c14nizedBytes =
249 c14nizer.canonicalizeSubtree(this._constructionElement);
250 }
251
252 // make defensive copy
253 byte[] output = new byte[this._c14nizedBytes.length];
254
255 System.arraycopy(this._c14nizedBytes, 0, output, 0, output.length);
256
257 return output;
258 }
259
260 /**
261 * Output the C14n stream to the give outputstream.
262 * @param os
263 * @throws CanonicalizationException
264 * @throws InvalidCanonicalizerException
265 * @throws XMLSecurityException
266 */
267 public void signInOctectStream(OutputStream os)
268 throws CanonicalizationException, InvalidCanonicalizerException,
269 XMLSecurityException {
270
271 if ((this._c14nizedBytes == null)) {
272 Canonicalizer c14nizer =
273 Canonicalizer.getInstance(this.getCanonicalizationMethodURI());
274 c14nizer.setWriter(os);
275 String inclusiveNamespaces = this.getInclusiveNamespaces();
276
277 if(inclusiveNamespaces == null)
278 c14nizer.canonicalizeSubtree(this._constructionElement);
279 else
280 c14nizer.canonicalizeSubtree(this._constructionElement, inclusiveNamespaces);
281 } else {
282 try {
283 os.write(this._c14nizedBytes);
284 } catch (IOException e) {
285 throw new RuntimeException(""+e);
286 }
287 }
288 }
289
290 /**
291 * Returns the Canonicalization method URI
292 *
293 * @return the Canonicalization method URI
294 */
295 public String getCanonicalizationMethodURI() {
296
297 Element el= XMLUtils.selectDsNode(this._constructionElement.getFirstChild(),
298 Constants._TAG_CANONICALIZATIONMETHOD,0);
299 if (el==null) {
300 return null;
301 }
302 return el.getAttributeNS(null, Constants._ATT_ALGORITHM);
303 }
304
305 /**
306 * Returns the Signature method URI
307 *
308 * @return the Signature method URI
309 */
310 public String getSignatureMethodURI() {
311
312 Element signatureElement = this.getSignatureMethodElement();
313
314 if (signatureElement != null) {
315 return signatureElement.getAttributeNS(null, Constants._ATT_ALGORITHM);
316 }
317
318 return null;
319 }
320
321 /**
322 * Method getSignatureMethodElement
323 * @return gets The SignatureMethod Node.
324 *
325 */
326 public Element getSignatureMethodElement() {
327 return XMLUtils.selectDsNode(this._constructionElement.getFirstChild(),
328 Constants._TAG_SIGNATUREMETHOD,0);
329 }
330
331 /**
332 * Creates a SecretKey for the appropriate Mac algorithm based on a
333 * byte[] array password.
334 *
335 * @param secretKeyBytes
336 * @return the secret key for the SignedInfo element.
337 */
338 public SecretKey createSecretKey(byte[] secretKeyBytes)
339 {
340
341 return new SecretKeySpec(secretKeyBytes,
342 this._signatureAlgorithm
343 .getJCEAlgorithmString());
344 }
345
346 /**
347 * Method getBaseLocalName
348 * @inheritDoc
349 *
350 */
351 public String getBaseLocalName() {
352 return Constants._TAG_SIGNEDINFO;
353 }
354
355 public String getInclusiveNamespaces() {
356
357 Element el= XMLUtils.selectDsNode(this._constructionElement.getFirstChild(),
358 Constants._TAG_CANONICALIZATIONMETHOD,0);
359 if (el==null) {
360 return null;
361 }
362
363 String c14nMethodURI = el.getAttributeNS(null, Constants._ATT_ALGORITHM);
364 if(!(c14nMethodURI.equals("http://www.w3.org/2001/10/xml-exc-c14n#") ||
365 c14nMethodURI.equals("http://www.w3.org/2001/10/xml-exc-c14n#WithComments"))) {
366 return null;
367 }
368
369 Element inclusiveElement = XMLUtils.selectNode(
370 el.getFirstChild(),InclusiveNamespaces.ExclusiveCanonicalizationNamespace,
371 InclusiveNamespaces._TAG_EC_INCLUSIVENAMESPACES,0);
372
373 if(inclusiveElement != null)
374 {
375 try
376 {
377 String inclusiveNamespaces = new InclusiveNamespaces(inclusiveElement,
378 InclusiveNamespaces.ExclusiveCanonicalizationNamespace).getInclusiveNamespaces();
379 return inclusiveNamespaces;
380 }
381 catch (XMLSecurityException e)
382 {
383 return null;
384 }
385 }
386 return null;
387 }
388}