Created
April 1, 2009 07:49
-
-
Save ishikawa/88599 to your computer and use it in GitHub Desktop.
Java Sample Code for Calculating HMAC-SHA1 Signatures
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.security.InvalidKeyException; | |
import java.security.NoSuchAlgorithmException; | |
import java.security.SignatureException; | |
import java.util.Formatter; | |
import javax.crypto.Mac; | |
import javax.crypto.spec.SecretKeySpec; | |
/** | |
* The <tt>HmacSha1Signature</tt> shows how to calculate | |
* a message authentication code using HMAC-SHA1 algorithm. | |
* | |
* <pre> | |
* % java -version | |
* java version "1.6.0_11" | |
* % javac HmacSha1Signature.java | |
* % java -ea HmacSha1Signature | |
* 104152c5bfdca07bc633eebd46199f0255c9f49d | |
* </pre> | |
* | |
*/ | |
public class HmacSha1Signature { | |
private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1"; | |
private static String toHexString(byte[] bytes) { | |
Formatter formatter = new Formatter(); | |
for (byte b : bytes) { | |
formatter.format("%02x", b); | |
} | |
return formatter.toString(); | |
} | |
public static String calculateRFC2104HMAC(String data, String key) | |
throws SignatureException, NoSuchAlgorithmException, InvalidKeyException | |
{ | |
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM); | |
Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM); | |
mac.init(signingKey); | |
return toHexString(mac.doFinal(data.getBytes())); | |
} | |
public static void main(String[] args) throws Exception { | |
String hmac = calculateRFC2104HMAC("data", "key"); | |
System.out.println(hmac); | |
assert hmac.equals("104152c5bfdca07bc633eebd46199f0255c9f49d"); | |
} | |
} |
The correct way to generate a key is:
public static String generateRandomKey() throws NoSuchAlgorithmException {
SecureRandom secureRandom = new SecureRandom(SecureRandom.getSeed(32));
KeyGenerator keyGen = KeyGenerator.getInstance("HmacSHA1");
keyGen.init(secureRandom);
SecretKey secretKey = keyGen.generateKey();
String encodedKey = Base64.getEncoder().encodeToString(secretKey.getEncoded());
return encodedKey;
}
As an example, the above code can produce 0x6
as a key byte, or 00000110
. This binary value cannot be encoded as UTF-8: http://bit.ly/2nOaqFw
import java.security.SignatureException;
import java.util.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class HMAC_SHA1 {
public static String Signature(String xData, String AppKey) throws java.security.SignatureException {
try {
final Base64.Encoder encoder = Base64.getEncoder();
// get an hmac_sha1 key from the raw key bytes
SecretKeySpec signingKey = new SecretKeySpec(AppKey.getBytes("UTF-8"),"HmacSHA1");
// get an hmac_sha1 Mac instance and initialize with the signing key
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(signingKey);
// compute the hmac on input data bytes
byte[] rawHmac = mac.doFinal(xData.getBytes("UTF-8"));
String result = encoder.encodeToString(rawHmac);
return result;
} catch (Exception e) {
throw new SignatureException("Failed to generate HMAC : "+ e.getMessage());
}
}
}
Thank You!
thanks
nice.
{
final Base64.Encoder encoder = Base64.getEncoder();
SecretKeySpec signingKey;
try {
signingKey = new SecretKeySpec(encoder.encode(key.getBytes("UTF-8")), ""HmacSHA1"");
Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
mac.init(signingKey);
return toHexString(mac.doFinal(encoder.encode(data.getBytes("UTF-8"))));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
import java.security.SignatureException; import java.util.Base64; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; public class HMAC_SHA1 { public static String Signature(String xData, String AppKey) throws java.security.SignatureException { try { final Base64.Encoder encoder = Base64.getEncoder(); // get an hmac_sha1 key from the raw key bytes SecretKeySpec signingKey = new SecretKeySpec(AppKey.getBytes("UTF-8"),"HmacSHA1"); // get an hmac_sha1 Mac instance and initialize with the signing key Mac mac = Mac.getInstance("HmacSHA1"); mac.init(signingKey); // compute the hmac on input data bytes byte[] rawHmac = mac.doFinal(xData.getBytes("UTF-8")); String result = encoder.encodeToString(rawHmac); return result; } catch (Exception e) { throw new SignatureException("Failed to generate HMAC : "+ e.getMessage()); } } }
what is xData
for Scala (taken answer above):
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
import org.apache.commons.codec.binary.Base64
def encryptHMACSHA1(value: String, secretKey: String): String = {
val signingKey = new SecretKeySpec(secretKey.getBytes, "HmacSHA1")
val mac = Mac.getInstance("HmacSHA1")
mac.init(signingKey)
val rawHmac = mac.doFinal(value.getBytes)
Base64.encodeBase64String(rawHmac)
}
Perfect for my needs, thanks so much!
Thanks :)
Thanks!
Thanks
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just FYI, there's a common cryptography bug in the above code. A lot of your key bytes are guessable because you're using UTF8 encoding. That means no non-printable bytes will ever appear in your key and your key entropy is greatly reduced. Always always randomly generate your keys using a SecureRandom and Base64 encode them. Otherwise, only bytes that are printable will be used as key bytes and number of guesses a brute force attacker would have to do is GREATLY reduced!