22 */ |
22 */ |
23 package com.sun.org.apache.xml.internal.security.signature; |
23 package com.sun.org.apache.xml.internal.security.signature; |
24 |
24 |
25 import java.io.ByteArrayInputStream; |
25 import java.io.ByteArrayInputStream; |
26 import java.io.IOException; |
26 import java.io.IOException; |
|
27 import java.io.InputStream; |
27 import java.io.OutputStream; |
28 import java.io.OutputStream; |
|
29 |
28 import javax.crypto.SecretKey; |
30 import javax.crypto.SecretKey; |
29 import javax.crypto.spec.SecretKeySpec; |
31 import javax.crypto.spec.SecretKeySpec; |
30 import javax.xml.XMLConstants; |
|
31 import javax.xml.parsers.ParserConfigurationException; |
32 import javax.xml.parsers.ParserConfigurationException; |
32 |
33 |
33 import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithm; |
34 import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithm; |
34 import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException; |
35 import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException; |
35 import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer; |
36 import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer; |
36 import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException; |
37 import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException; |
37 import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; |
38 import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; |
|
39 import com.sun.org.apache.xml.internal.security.transforms.params.InclusiveNamespaces; |
38 import com.sun.org.apache.xml.internal.security.utils.Constants; |
40 import com.sun.org.apache.xml.internal.security.utils.Constants; |
39 import com.sun.org.apache.xml.internal.security.utils.XMLUtils; |
41 import com.sun.org.apache.xml.internal.security.utils.XMLUtils; |
40 import com.sun.org.apache.xml.internal.security.transforms.params.InclusiveNamespaces; |
|
41 import org.w3c.dom.Document; |
42 import org.w3c.dom.Document; |
42 import org.w3c.dom.Element; |
43 import org.w3c.dom.Element; |
43 import org.w3c.dom.Node; |
44 import org.w3c.dom.Node; |
44 import org.xml.sax.SAXException; |
45 import org.xml.sax.SAXException; |
45 |
46 |
46 /** |
47 /** |
47 * Handles <code><ds:SignedInfo></code> elements |
48 * Handles {@code <ds:SignedInfo>} elements |
48 * This <code>SignedInfo<code> element includes the canonicalization algorithm, |
49 * This {@code SignedInfo} element includes the canonicalization algorithm, |
49 * a signature algorithm, and one or more references. |
50 * a signature algorithm, and one or more references. |
50 * |
51 * |
51 * @author Christian Geuer-Pollmann |
|
52 */ |
52 */ |
53 public class SignedInfo extends Manifest { |
53 public class SignedInfo extends Manifest { |
54 |
54 |
55 /** Field signatureAlgorithm */ |
55 /** Field signatureAlgorithm */ |
56 private SignatureAlgorithm signatureAlgorithm = null; |
56 private SignatureAlgorithm signatureAlgorithm; |
57 |
57 |
58 /** Field c14nizedBytes */ |
58 /** Field c14nizedBytes */ |
59 private byte[] c14nizedBytes = null; |
59 private byte[] c14nizedBytes; |
60 |
60 |
61 private Element c14nMethod; |
61 private Element c14nMethod; |
62 private Element signatureMethod; |
62 private Element signatureMethod; |
63 |
63 |
64 /** |
64 /** |
65 * Overwrites {@link Manifest#addDocument} because it creates another |
65 * Overwrites {@link Manifest#addDocument} because it creates another |
66 * Element. |
66 * Element. |
67 * |
67 * |
68 * @param doc the {@link Document} in which <code>XMLsignature</code> will |
68 * @param doc the {@link Document} in which {@code XMLsignature} will |
69 * be placed |
69 * be placed |
70 * @throws XMLSecurityException |
70 * @throws XMLSecurityException |
71 */ |
71 */ |
72 public SignedInfo(Document doc) throws XMLSecurityException { |
72 public SignedInfo(Document doc) throws XMLSecurityException { |
73 this(doc, XMLSignature.ALGO_ID_SIGNATURE_DSA, |
73 this(doc, XMLSignature.ALGO_ID_SIGNATURE_DSA, |
107 int hMACOutputLength, String canonicalizationMethodURI |
107 int hMACOutputLength, String canonicalizationMethodURI |
108 ) throws XMLSecurityException { |
108 ) throws XMLSecurityException { |
109 super(doc); |
109 super(doc); |
110 |
110 |
111 c14nMethod = |
111 c14nMethod = |
112 XMLUtils.createElementInSignatureSpace(this.doc, Constants._TAG_CANONICALIZATIONMETHOD); |
112 XMLUtils.createElementInSignatureSpace(getDocument(), Constants._TAG_CANONICALIZATIONMETHOD); |
113 |
113 |
114 c14nMethod.setAttributeNS(null, Constants._ATT_ALGORITHM, canonicalizationMethodURI); |
114 c14nMethod.setAttributeNS(null, Constants._ATT_ALGORITHM, canonicalizationMethodURI); |
115 this.constructionElement.appendChild(c14nMethod); |
115 appendSelf(c14nMethod); |
116 XMLUtils.addReturnToElement(this.constructionElement); |
116 addReturnToSelf(); |
117 |
117 |
118 if (hMACOutputLength > 0) { |
118 if (hMACOutputLength > 0) { |
119 this.signatureAlgorithm = |
119 this.signatureAlgorithm = |
120 new SignatureAlgorithm(this.doc, signatureMethodURI, hMACOutputLength); |
120 new SignatureAlgorithm(getDocument(), signatureMethodURI, hMACOutputLength); |
121 } else { |
121 } else { |
122 this.signatureAlgorithm = new SignatureAlgorithm(this.doc, signatureMethodURI); |
122 this.signatureAlgorithm = new SignatureAlgorithm(getDocument(), signatureMethodURI); |
123 } |
123 } |
124 |
124 |
125 signatureMethod = this.signatureAlgorithm.getElement(); |
125 signatureMethod = this.signatureAlgorithm.getElement(); |
126 this.constructionElement.appendChild(signatureMethod); |
126 appendSelf(signatureMethod); |
127 XMLUtils.addReturnToElement(this.constructionElement); |
127 addReturnToSelf(); |
128 } |
128 } |
129 |
129 |
130 /** |
130 /** |
131 * @param doc |
131 * @param doc |
132 * @param signatureMethodElem |
132 * @param signatureMethodElem |
137 Document doc, Element signatureMethodElem, Element canonicalizationMethodElem |
137 Document doc, Element signatureMethodElem, Element canonicalizationMethodElem |
138 ) throws XMLSecurityException { |
138 ) throws XMLSecurityException { |
139 super(doc); |
139 super(doc); |
140 // Check this? |
140 // Check this? |
141 this.c14nMethod = canonicalizationMethodElem; |
141 this.c14nMethod = canonicalizationMethodElem; |
142 this.constructionElement.appendChild(c14nMethod); |
142 appendSelf(c14nMethod); |
143 XMLUtils.addReturnToElement(this.constructionElement); |
143 addReturnToSelf(); |
144 |
144 |
145 this.signatureAlgorithm = |
145 this.signatureAlgorithm = |
146 new SignatureAlgorithm(signatureMethodElem, null); |
146 new SignatureAlgorithm(signatureMethodElem, null); |
147 |
147 |
148 signatureMethod = this.signatureAlgorithm.getElement(); |
148 signatureMethod = this.signatureAlgorithm.getElement(); |
149 this.constructionElement.appendChild(signatureMethod); |
149 appendSelf(signatureMethod); |
150 |
150 |
151 XMLUtils.addReturnToElement(this.constructionElement); |
151 addReturnToSelf(); |
152 } |
152 } |
153 |
153 |
154 /** |
154 /** |
155 * Build a {@link SignedInfo} from an {@link Element} |
155 * Build a {@link SignedInfo} from an {@link Element} |
156 * |
156 * |
157 * @param element <code>SignedInfo</code> |
157 * @param element {@code SignedInfo} |
158 * @param baseURI the URI of the resource where the XML instance was stored |
158 * @param baseURI the URI of the resource where the XML instance was stored |
159 * @throws XMLSecurityException |
159 * @throws XMLSecurityException |
160 * @see <A HREF="http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001OctDec/0033.html"> |
160 * @see <A HREF="http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001OctDec/0033.html"> |
161 * Question</A> |
161 * Question</A> |
162 * @see <A HREF="http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001OctDec/0054.html"> |
162 * @see <A HREF="http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001OctDec/0054.html"> |
163 * Answer</A> |
163 * Answer</A> |
164 */ |
164 */ |
165 public SignedInfo(Element element, String baseURI) throws XMLSecurityException { |
165 public SignedInfo(Element element, String baseURI) throws XMLSecurityException { |
166 this(element, baseURI, false); |
166 this(element, baseURI, true); |
167 } |
167 } |
168 |
168 |
169 /** |
169 /** |
170 * Build a {@link SignedInfo} from an {@link Element} |
170 * Build a {@link SignedInfo} from an {@link Element} |
171 * |
171 * |
172 * @param element <code>SignedInfo</code> |
172 * @param element {@code SignedInfo} |
173 * @param baseURI the URI of the resource where the XML instance was stored |
173 * @param baseURI the URI of the resource where the XML instance was stored |
174 * @param secureValidation whether secure validation is enabled or not |
174 * @param secureValidation whether secure validation is enabled or not |
175 * @throws XMLSecurityException |
175 * @throws XMLSecurityException |
176 * @see <A HREF="http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001OctDec/0033.html"> |
176 * @see <A HREF="http://lists.w3.org/Archives/Public/w3c-ietf-xmldsig/2001OctDec/0033.html"> |
177 * Question</A> |
177 * Question</A> |
180 */ |
180 */ |
181 public SignedInfo( |
181 public SignedInfo( |
182 Element element, String baseURI, boolean secureValidation |
182 Element element, String baseURI, boolean secureValidation |
183 ) throws XMLSecurityException { |
183 ) throws XMLSecurityException { |
184 // Parse the Reference children and Id attribute in the Manifest |
184 // Parse the Reference children and Id attribute in the Manifest |
185 super(reparseSignedInfoElem(element), baseURI, secureValidation); |
185 super(reparseSignedInfoElem(element, secureValidation), baseURI, secureValidation); |
186 |
186 |
187 c14nMethod = XMLUtils.getNextElement(element.getFirstChild()); |
187 c14nMethod = XMLUtils.getNextElement(element.getFirstChild()); |
188 signatureMethod = XMLUtils.getNextElement(c14nMethod.getNextSibling()); |
188 signatureMethod = XMLUtils.getNextElement(c14nMethod.getNextSibling()); |
189 this.signatureAlgorithm = |
189 this.signatureAlgorithm = |
190 new SignatureAlgorithm(signatureMethod, this.getBaseURI(), secureValidation); |
190 new SignatureAlgorithm(signatureMethod, this.getBaseURI(), secureValidation); |
191 } |
191 } |
192 |
192 |
193 private static Element reparseSignedInfoElem(Element element) |
193 private static Element reparseSignedInfoElem(Element element, boolean secureValidation) |
194 throws XMLSecurityException { |
194 throws XMLSecurityException { |
195 /* |
195 /* |
196 * If a custom canonicalizationMethod is used, canonicalize |
196 * If a custom canonicalizationMethod is used, canonicalize |
197 * ds:SignedInfo, reparse it into a new document |
197 * ds:SignedInfo, reparse it into a new document |
198 * and replace the original not-canonicalized ds:SignedInfo by |
198 * and replace the original not-canonicalized ds:SignedInfo by |
210 // the c14n is not a secure one and can rewrite the URIs or like |
210 // the c14n is not a secure one and can rewrite the URIs or like |
211 // so reparse the SignedInfo to be sure |
211 // so reparse the SignedInfo to be sure |
212 try { |
212 try { |
213 Canonicalizer c14nizer = |
213 Canonicalizer c14nizer = |
214 Canonicalizer.getInstance(c14nMethodURI); |
214 Canonicalizer.getInstance(c14nMethodURI); |
|
215 c14nizer.setSecureValidation(secureValidation); |
215 |
216 |
216 byte[] c14nizedBytes = c14nizer.canonicalizeSubtree(element); |
217 byte[] c14nizedBytes = c14nizer.canonicalizeSubtree(element); |
217 javax.xml.parsers.DocumentBuilderFactory dbf = |
218 javax.xml.parsers.DocumentBuilder db = |
218 javax.xml.parsers.DocumentBuilderFactory.newInstance(); |
219 XMLUtils.createDocumentBuilder(false, secureValidation); |
219 dbf.setNamespaceAware(true); |
220 try (InputStream is = new ByteArrayInputStream(c14nizedBytes)) { |
220 dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE); |
221 Document newdoc = db.parse(is); |
221 javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder(); |
222 Node imported = element.getOwnerDocument().importNode( |
222 Document newdoc = |
223 newdoc.getDocumentElement(), true); |
223 db.parse(new ByteArrayInputStream(c14nizedBytes)); |
224 element.getParentNode().replaceChild(imported, element); |
224 Node imported = |
225 return (Element) imported; |
225 element.getOwnerDocument().importNode(newdoc.getDocumentElement(), true); |
226 } |
226 |
|
227 element.getParentNode().replaceChild(imported, element); |
|
228 |
|
229 return (Element) imported; |
|
230 } catch (ParserConfigurationException ex) { |
227 } catch (ParserConfigurationException ex) { |
231 throw new XMLSecurityException("empty", ex); |
228 throw new XMLSecurityException(ex); |
232 } catch (IOException ex) { |
229 } catch (IOException ex) { |
233 throw new XMLSecurityException("empty", ex); |
230 throw new XMLSecurityException(ex); |
234 } catch (SAXException ex) { |
231 } catch (SAXException ex) { |
235 throw new XMLSecurityException("empty", ex); |
232 throw new XMLSecurityException(ex); |
236 } |
233 } |
237 } |
234 } |
238 return element; |
235 return element; |
239 } |
236 } |
240 |
237 |
264 } |
261 } |
265 |
262 |
266 /** |
263 /** |
267 * Returns getCanonicalizedOctetStream |
264 * Returns getCanonicalizedOctetStream |
268 * |
265 * |
269 * @return the canonicalization result octet stream of <code>SignedInfo</code> element |
266 * @return the canonicalization result octet stream of {@code SignedInfo} element |
270 * @throws CanonicalizationException |
267 * @throws CanonicalizationException |
271 * @throws InvalidCanonicalizerException |
268 * @throws InvalidCanonicalizerException |
272 * @throws XMLSecurityException |
269 * @throws XMLSecurityException |
273 */ |
270 */ |
274 public byte[] getCanonicalizedOctetStream() |
271 public byte[] getCanonicalizedOctetStream() |
275 throws CanonicalizationException, InvalidCanonicalizerException, XMLSecurityException { |
272 throws CanonicalizationException, InvalidCanonicalizerException, XMLSecurityException { |
276 if (this.c14nizedBytes == null) { |
273 if (this.c14nizedBytes == null) { |
277 Canonicalizer c14nizer = |
274 Canonicalizer c14nizer = |
278 Canonicalizer.getInstance(this.getCanonicalizationMethodURI()); |
275 Canonicalizer.getInstance(this.getCanonicalizationMethodURI()); |
279 |
276 c14nizer.setSecureValidation(isSecureValidation()); |
280 this.c14nizedBytes = |
277 |
281 c14nizer.canonicalizeSubtree(this.constructionElement); |
278 String inclusiveNamespaces = this.getInclusiveNamespaces(); |
|
279 if (inclusiveNamespaces == null) { |
|
280 this.c14nizedBytes = c14nizer.canonicalizeSubtree(getElement()); |
|
281 } else { |
|
282 this.c14nizedBytes = c14nizer.canonicalizeSubtree(getElement(), inclusiveNamespaces); |
|
283 } |
282 } |
284 } |
283 |
285 |
284 // make defensive copy |
286 // make defensive copy |
285 return this.c14nizedBytes.clone(); |
287 return this.c14nizedBytes.clone(); |
286 } |
288 } |
295 public void signInOctetStream(OutputStream os) |
297 public void signInOctetStream(OutputStream os) |
296 throws CanonicalizationException, InvalidCanonicalizerException, XMLSecurityException { |
298 throws CanonicalizationException, InvalidCanonicalizerException, XMLSecurityException { |
297 if (this.c14nizedBytes == null) { |
299 if (this.c14nizedBytes == null) { |
298 Canonicalizer c14nizer = |
300 Canonicalizer c14nizer = |
299 Canonicalizer.getInstance(this.getCanonicalizationMethodURI()); |
301 Canonicalizer.getInstance(this.getCanonicalizationMethodURI()); |
|
302 c14nizer.setSecureValidation(isSecureValidation()); |
300 c14nizer.setWriter(os); |
303 c14nizer.setWriter(os); |
301 String inclusiveNamespaces = this.getInclusiveNamespaces(); |
304 String inclusiveNamespaces = this.getInclusiveNamespaces(); |
302 |
305 |
303 if (inclusiveNamespaces == null) { |
306 if (inclusiveNamespaces == null) { |
304 c14nizer.canonicalizeSubtree(this.constructionElement); |
307 c14nizer.canonicalizeSubtree(getElement()); |
305 } else { |
308 } else { |
306 c14nizer.canonicalizeSubtree(this.constructionElement, inclusiveNamespaces); |
309 c14nizer.canonicalizeSubtree(getElement(), inclusiveNamespaces); |
307 } |
310 } |
308 } else { |
311 } else { |
309 try { |
312 try { |
310 os.write(this.c14nizedBytes); |
313 os.write(this.c14nizedBytes); |
311 } catch (IOException e) { |
314 } catch (IOException e) { |
356 */ |
359 */ |
357 public SecretKey createSecretKey(byte[] secretKeyBytes) { |
360 public SecretKey createSecretKey(byte[] secretKeyBytes) { |
358 return new SecretKeySpec(secretKeyBytes, this.signatureAlgorithm.getJCEAlgorithmString()); |
361 return new SecretKeySpec(secretKeyBytes, this.signatureAlgorithm.getJCEAlgorithmString()); |
359 } |
362 } |
360 |
363 |
361 protected SignatureAlgorithm getSignatureAlgorithm() { |
364 public SignatureAlgorithm getSignatureAlgorithm() { |
362 return signatureAlgorithm; |
365 return signatureAlgorithm; |
363 } |
366 } |
364 |
367 |
365 /** |
368 /** |
366 * Method getBaseLocalName |
369 * Method getBaseLocalName |
367 * @inheritDoc |
370 * {@inheritDoc} |
368 * |
371 * |
369 */ |
372 */ |
370 public String getBaseLocalName() { |
373 public String getBaseLocalName() { |
371 return Constants._TAG_SIGNEDINFO; |
374 return Constants._TAG_SIGNEDINFO; |
372 } |
375 } |
373 |
376 |
374 public String getInclusiveNamespaces() { |
377 public String getInclusiveNamespaces() { |
375 String c14nMethodURI = c14nMethod.getAttributeNS(null, Constants._ATT_ALGORITHM); |
378 String c14nMethodURI = getCanonicalizationMethodURI(); |
376 if (!(c14nMethodURI.equals("http://www.w3.org/2001/10/xml-exc-c14n#") || |
379 if (!(c14nMethodURI.equals("http://www.w3.org/2001/10/xml-exc-c14n#") || |
377 c14nMethodURI.equals("http://www.w3.org/2001/10/xml-exc-c14n#WithComments"))) { |
380 c14nMethodURI.equals("http://www.w3.org/2001/10/xml-exc-c14n#WithComments"))) { |
378 return null; |
381 return null; |
379 } |
382 } |
380 |
383 |