1 /*
2 * Copyright [2006] [University Corporation for Advanced Internet Development, Inc.]
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.opensaml.xml.signature;
18
19 import java.util.List;
20
21 import org.apache.xml.security.Init;
22 import org.apache.xml.security.exceptions.XMLSecurityException;
23 import org.apache.xml.security.signature.XMLSignature;
24 import org.opensaml.xml.security.SecurityHelper;
25 import org.opensaml.xml.signature.impl.SignatureImpl;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 /**
30 * This class is responsible for creating the digital signatures for the given signable XMLObjects.
31 *
32 * This must be done as a seperate step because in order to support the following cases:
33 * <ul>
34 * <li>Multiple signable objects appear in the DOM tree, in which case the order that the objects should be signed in
35 * is not known (e.g. object 1 could appear first in the tree, but contain a reference to signable object 2)</li>
36 * <li>The DOM tree resulting from marshalling of the XMLObject tree is grafted onto another DOM tree which may cause
37 * element ID conflicts that would invalidate the signature</li>
38 * </ul>
39 */
40 public class Signer {
41
42 /** Constructor. */
43 protected Signer() {
44
45 }
46
47 /**
48 * Signs the given XMLObject in the order provided.
49 *
50 * @param xmlObjects an orderded list of XMLObject to be signed
51 * @throws SignatureException thrown if there is an error computing the signature
52 */
53 public static void signObjects(List<Signature> xmlObjects) throws SignatureException {
54 for (Signature xmlObject : xmlObjects) {
55 signObject(xmlObject);
56 }
57 }
58
59 /**
60 * Signs a single XMLObject.
61 *
62 * @param signature the signature to computer the signature on
63 * @throws SignatureException thrown if there is an error computing the signature
64 */
65 public static void signObject(Signature signature) throws SignatureException {
66 Logger log = getLogger();
67 try {
68 XMLSignature xmlSignature = ((SignatureImpl) signature).getXMLSignature();
69
70 if (xmlSignature == null) {
71 log.error("Unable to compute signature, Signature XMLObject does not have the XMLSignature "
72 + "created during marshalling.");
73 throw new SignatureException("XMLObject does not have an XMLSignature instance, unable to compute signature");
74 }
75 log.debug("Computing signature over XMLSignature object");
76 xmlSignature.sign(SecurityHelper.extractSigningKey(signature.getSigningCredential()));
77 } catch (XMLSecurityException e) {
78 log.error("An error occured computing the digital signature", e);
79 throw new SignatureException("Signature computation error", e);
80 }
81 }
82
83 /**
84 * Get an SLF4J Logger.
85 *
86 * @return a Logger instance
87 */
88 private static Logger getLogger() {
89 return LoggerFactory.getLogger(Signer.class);
90 }
91
92 /*
93 * Initialize the Apache XML security library if it hasn't been already
94 */
95 static {
96 Logger log = getLogger();
97 if (!Init.isInitialized()) {
98 log.debug("Initializing XML security library");
99 Init.init();
100 }
101 }
102 }