-
-
Save ishikawa/88599 to your computer and use it in GitHub Desktop.
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; | |
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"); | |
} | |
} |
Great!
thanks man!
Thanks!
👍
nice, thanks
thanks!
Great job man !
Thanks!
Thanks!
Here's the same thing in Kotlin for your convenience:
import java.security.InvalidKeyException
import java.security.NoSuchAlgorithmException
import java.security.SignatureException
import java.util.*
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
object HmacSha1Signature {
private val HMAC_SHA1_ALGORITHM = "HmacSHA1"
private fun toHexString(bytes: ByteArray): String {
val formatter = Formatter()
for (b in bytes) {
formatter.format("%02x", b)
}
return formatter.toString()
}
@Throws(SignatureException::class, NoSuchAlgorithmException::class, InvalidKeyException::class)
fun calculateRFC2104HMAC(data: String, key: String): String {
val signingKey = SecretKeySpec(key.toByteArray(), HMAC_SHA1_ALGORITHM)
val mac = Mac.getInstance(HMAC_SHA1_ALGORITHM)
mac.init(signingKey)
return toHexString(mac.doFinal(data.toByteArray()))
}
}
Thanks! @ishikawa and @JohannesRudolph.
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!
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
thanks!