View Javadoc

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.impl;
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.SignedInfo;
24  import org.apache.xml.security.signature.XMLSignature;
25  import org.opensaml.xml.Configuration;
26  import org.opensaml.xml.io.Unmarshaller;
27  import org.opensaml.xml.io.UnmarshallingException;
28  import org.opensaml.xml.signature.KeyInfo;
29  import org.opensaml.xml.signature.Signature;
30  import org.opensaml.xml.util.DatatypeHelper;
31  import org.opensaml.xml.util.XMLConstants;
32  import org.opensaml.xml.util.XMLHelper;
33  import org.slf4j.Logger;
34  import org.slf4j.LoggerFactory;
35  import org.w3c.dom.Element;
36  
37  /**
38   * An unmarshaller for {@link org.opensaml.xml.signature.Signature} objects.
39   */
40  public class SignatureUnmarshaller implements Unmarshaller {
41  
42      /** Class logger. */
43      private final Logger log = LoggerFactory.getLogger(SignatureUnmarshaller.class);
44  
45      /** Constructor. */
46      public SignatureUnmarshaller() {
47          if (!Init.isInitialized()) {
48              log.debug("Initializing XML security library");
49              Init.init();
50          }
51      }
52  
53      /** {@inheritDoc} */
54      public Signature unmarshall(Element signatureElement) throws UnmarshallingException {
55          log.debug("Starting to unmarshall Apache XML-Security-based SignatureImpl element");
56  
57          SignatureImpl signature = new SignatureImpl(signatureElement.getNamespaceURI(),
58                  signatureElement.getLocalName(), signatureElement.getPrefix());
59  
60          try {
61              log.debug("Constructing Apache XMLSignature object");
62  
63              XMLSignature xmlSignature = new XMLSignature(signatureElement, "");
64  
65              SignedInfo signedInfo = xmlSignature.getSignedInfo();
66  
67              log.debug("Adding canonicalization and signing algorithms, and HMAC output length to Signature");
68              signature.setCanonicalizationAlgorithm(signedInfo.getCanonicalizationMethodURI());
69              signature.setSignatureAlgorithm(signedInfo.getSignatureMethodURI());
70              signature.setHMACOutputLength(getHMACOutputLengthValue(signedInfo.getSignatureMethodElement()));
71  
72              org.apache.xml.security.keys.KeyInfo xmlSecKeyInfo = xmlSignature.getKeyInfo();
73              if (xmlSecKeyInfo != null) {
74                  log.debug("Adding KeyInfo to Signature");
75                  Unmarshaller unmarshaller = Configuration.getUnmarshallerFactory().getUnmarshaller(
76                          xmlSecKeyInfo.getElement());
77                  KeyInfo keyInfo = (KeyInfo) unmarshaller.unmarshall(xmlSecKeyInfo.getElement());
78                  signature.setKeyInfo(keyInfo);
79              }
80              signature.setXMLSignature(xmlSignature);
81              signature.setDOM(signatureElement);
82              return signature;
83          } catch (XMLSecurityException e) {
84              log.error("Error constructing Apache XMLSignature instance from Signature element: {}", e.getMessage());
85              throw new UnmarshallingException("Unable to unmarshall Signature with Apache XMLSignature", e);
86          }
87      }
88  
89      /**
90       * Find and return the integer value contained within the HMACOutputLength element, if present.
91       * 
92       * @param signatureMethodElement the ds:SignatureMethod element
93       * @return the HMAC output length value, or null if not present
94       */
95      private Integer getHMACOutputLengthValue(Element signatureMethodElement) {
96          if (signatureMethodElement == null) {
97              return null;
98          }
99          // Should be at most one element
100         List<Element> children = XMLHelper.getChildElementsByTagNameNS(signatureMethodElement, XMLConstants.XMLSIG_NS,
101                 "HMACOutputLength");
102         if (!children.isEmpty()) {
103             Element hmacElement = children.get(0);
104             String value = DatatypeHelper.safeTrimOrNullString(hmacElement.getTextContent());
105             if (value != null) {
106                 return new Integer(value);
107             }
108         }
109         return null;
110     }
111 }