View Javadoc
1   /*
2    * Created on Jan 7, 2005
3    * 
4    * www.grants.gov WebServices Code
5    */
6   package org.kuali.coeus.s2sgen.impl.hash;
7   
8   import org.apache.xml.security.algorithms.MessageDigestAlgorithm;
9   import org.apache.xml.security.c14n.CanonicalizationException;
10  import org.apache.xml.security.c14n.Canonicalizer;
11  import org.apache.xml.security.c14n.InvalidCanonicalizerException;
12  import org.apache.xml.security.signature.XMLSignatureException;
13  import org.apache.xml.security.utils.Base64;
14  import org.apache.xml.security.utils.DigesterOutputStream;
15  import org.kuali.coeus.s2sgen.api.core.S2SException;
16  import org.kuali.coeus.s2sgen.impl.util.XPathExecutor;
17  import org.slf4j.Logger;
18  import org.slf4j.LoggerFactory;
19  import org.w3c.dom.Document;
20  import org.w3c.dom.Node;
21  
22  import javax.xml.transform.TransformerException;
23  
24  /**
25   * This is a convenience object that simplifies the hashing processing to one
26   * method call.
27   * 
28   * @author David Wong
29   */
30  public class GrantApplicationHash {
31  
32  	private static final Logger log = LoggerFactory.getLogger(GrantApplicationHash.class
33              .getName());
34  
35  	static java.security.MessageDigest messageDigester = null;
36  
37  	static {
38  		org.apache.xml.security.Init.init();
39  		try {
40  			messageDigester = java.security.MessageDigest.getInstance("SHA-1");
41  		} catch (Exception ex) {
42  			log.error(
43  					"Unable to get instance of java.security.MessageDigester",
44  					ex);
45  		}
46  	}
47  
48  	/**
49  	 * Added private constructor to prevent creation by user.
50  	 */
51  	private GrantApplicationHash() {
52  
53  	}
54  
55  	/**
56  	 * Computes the hash value for the Grants.gov application XML.
57  	 * 
58  	 * @param xml
59  	 *            The Grants.gov application XML.
60  	 * @return The SHA-1 hash value of <grant:forms> tag inside the
61  	 *         application XML.
62  	 * @throws Exception
63  	 *             When the XML cannot be parsed.
64  	 */
65  	public final static String computeGrantFormsHash(String xml) throws S2SException {
66  		GrantApplicationXpath xpath;
67          try {
68              xpath = new GrantApplicationXpath(xml);
69              return _hash(xpath);
70          }catch (Exception e) {
71              log.error(e.getMessage(), e);
72              throw new S2SException(e.getMessage(),e);
73          }
74  	}
75  
76  	/**
77  	 * Computes the hash of an binary attachment.
78  	 * 
79  	 * @param attachment
80  	 * @return The SHA-1 hash value of the attachment byte array.
81  	 * @throws Exception
82  	 */
83  	public final static String computeAttachmentHash(byte[] attachment) {
84  
85  		byte[] rawDigest = messageDigester.digest(attachment);
86  
87  		return Base64.encode(rawDigest);
88  
89  	}
90  
91  	/**
92  	 * Computes the hash value for the Grants.gov application XML.
93  	 * 
94  	 * @param xpath
95  	 *            An xpath object holding the Grants.gov application XML.
96  	 * @return The SHA-1 hash value of <grant:forms> tag inside the
97  	 *         application XML.
98  	 * @throws Exception
99  	 *             When the XML cannot be parsed.
100 	 */
101 	public final static String computeGrantFormsHash(GrantApplicationXpath xpath)
102 			throws Exception {
103 		return _hash(xpath);
104 	}
105 
106 	/**
107 	 * Computes the hash value for the Grants.gov application XML.
108 	 * 
109 	 * @param xml
110 	 *            The Grants.gov application XML.
111 	 * @return The SHA-1 hash value of <grant:forms> tag inside the
112 	 *         application XML.
113 	 * @throws Exception
114 	 *             When the XML cannot be parsed.
115 	 */
116 	public final static String computeGrantFormsHash(Document xml) throws Exception {
117 		XPathExecutor executor = new XPathExecutor(null);
118 		executor.setDoc(xml);
119 		GrantApplicationXpath xpath = new GrantApplicationXpath(null);
120 		xpath.setExecutor(executor);
121 		return _hash(xpath);
122 	}
123 
124 	private static String _hash(GrantApplicationXpath xpath)
125 			throws TransformerException, XMLSignatureException,
126 			InvalidCanonicalizerException, CanonicalizationException {
127 		Node formsNode = xpath.getFormsNode();
128 		DigesterOutputStream digester = _createDigesterOutputStream(xpath
129 				.getExecutor().getDoc());
130 		Canonicalizer canonicalizer = Canonicalizer
131 				.getInstance(Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
132 		canonicalizer.setWriter(digester);
133 		canonicalizer.canonicalizeSubtree(formsNode);
134 		byte[] hash = digester.getDigestValue();
135 		return Base64.encode(hash);
136 	}
137 
138 	private static DigesterOutputStream _createDigesterOutputStream(Document doc)
139 			throws XMLSignatureException {
140 		DigesterOutputStream stream = null;
141 		if (doc != null) {
142 			stream = new DigesterOutputStream(MessageDigestAlgorithm
143 					.getInstance(doc,
144 							MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA1));
145 		}
146 		return stream;
147 	}
148 }