View Javadoc

1   /*
2    * Copyright 2009-2010 Capgemini
3    * Licensed under the Apache License, Version 2.0 (the "License"); 
4    * you may not use this file except in compliance with the License. 
5    * You may obtain a copy of the License at 
6    * 
7    * http://www.apache.org/licenses/LICENSE-2.0 
8    * 
9    * Unless required by applicable law or agreed to in writing, software 
10   * distributed under the License is distributed on an "AS IS" BASIS, 
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
12   * See the License for the specific language governing permissions and 
13   * limitations under the License. 
14   * 
15   */
16  package net.sourceforge.statelessfilter.utils;
17  
18  import java.io.UnsupportedEncodingException;
19  import java.security.InvalidKeyException;
20  import java.security.NoSuchAlgorithmException;
21  import java.security.SignatureException;
22  
23  import javax.crypto.Mac;
24  import javax.crypto.spec.SecretKeySpec;
25  
26  import org.apache.commons.codec.binary.Hex;
27  
28  /**
29   * HMAC utility methods.
30   */
31  public final class HmacUtils {
32  
33  	private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
34  
35  	/**
36  	 * Private constructor
37  	 */
38  	private HmacUtils() {
39  	}
40  
41  	public static String calculateRFC2104HMAC(String data, String key)
42  			throws SignatureException {
43  		String result;
44  
45  		if (data == null || key == null) {
46  			throw new IllegalArgumentException(
47  					"data and key must be not null. data:" + data + " key: "
48  							+ key == null ? "null" : "not null");
49  		}
50  		// Get an hmac_sha1 key from the raw key bytes
51  		byte[] keyBytes = key.getBytes();
52  		SecretKeySpec signingKey = new SecretKeySpec(keyBytes,
53  				HMAC_SHA1_ALGORITHM);
54  
55  		try {
56  			// Get an hmac_sha1 Mac instance and initialize with the signing key
57  			Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
58  			mac.init(signingKey);
59  
60  			// Compute the hmac on input data bytes
61  			byte[] rawHmac = mac.doFinal(data.getBytes());
62  
63  			// Convert raw bytes to Hex
64  			byte[] hexBytes = new Hex().encode(rawHmac);
65  
66  			// Covert array of Hex bytes to a String
67  			result = new String(hexBytes, "ISO-8859-1");
68  		} catch (InvalidKeyException e) {
69  			throw new SignatureException("Failed to generate HMAC : "
70  					+ e.getMessage(), e);
71  		} catch (NoSuchAlgorithmException e) {
72  			throw new SignatureException("Failed to generate HMAC : "
73  					+ e.getMessage(), e);
74  		} catch (UnsupportedEncodingException e) {
75  			throw new SignatureException("Failed to generate HMAC : "
76  					+ e.getMessage(), e);
77  		}
78  
79  		return result;
80  	}
81  
82  	public static String signRFC2104HMAC(String data, String key,
83  			String separator) throws SignatureException {
84  
85  		String hash = HmacUtils.calculateRFC2104HMAC(data, key);
86  		String signedData = data + separator + hash;
87  
88  		return signedData;
89  	}
90  
91  	public static String verifyRFC2104HMAC(String data, String key,
92  			String separator) throws SignatureException {
93  		int idx = data.lastIndexOf(separator);
94  		if (idx >= 0) {
95  			String unsignedValue = data.substring(0, idx);
96  
97  			String hash = data.substring(idx + 1);
98  
99  			if (hash.equals(calculateRFC2104HMAC(unsignedValue, key))) {
100 				return unsignedValue;
101 			}
102 		}
103 		return null;
104 	}
105 }