HMAC-SHA256 Algorithm for signature calculation
I am trying to create a signature using the HMAC-SHA256 algorithm and this is my code. I am using US ASCII encoding.
final Charset asciiCs = Charset.forName("US-ASCII");
final Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
final SecretKeySpec secret_key = new javax.crypto.spec.SecretKeySpec(asciiCs.encode("key").array(), "HmacSHA256");
sha256_HMAC.init(secret_key);
final byte[] mac_data = sha256_HMAC.doFinal(asciiCs.encode("The quick brown fox jumps over the lazy dog").array());
String result = "";
for (final byte element : mac_data)
{
result += Integer.toString((element & 0xff) + 0x100, 16).substring(1);
}
System.out.println("Result:[" + result + "]");
The result that I am getting from the above code is:
f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8
This is 开发者_Go百科same as to that of shown in the wiki
HMAC_SHA256("key", "The quick brown fox jumps over the lazy dog") = 0x f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8
except for the 0x
.
I am looking for ideas/comments if I am doing everything right or may be I can improve my code.
Here is my solution:
public static String encode(String key, String data) throws Exception {
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
sha256_HMAC.init(secret_key);
return Hex.encodeHexString(sha256_HMAC.doFinal(data.getBytes("UTF-8")));
}
public static void main(String [] args) throws Exception {
System.out.println(encode("key", "The quick brown fox jumps over the lazy dog"));
}
Or you can return the hash encoded in Base64:
Base64.encodeBase64String(sha256_HMAC.doFinal(data.getBytes("UTF-8")));
The output in hex is as expected:
f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8
The 0x just denotes that the characters after it represent a hex string.
0x1A == 1Ah == 26 == 1A
So the 0x is just to clarify what format the output is in, no need to worry about it.
If you're using Guava, its latest release now lets you use
Hashing.hmacSha256()
One example of using this:
String hash = Hashing.hmacSha256("mykey".getBytes(StandardCharsets.UTF_8)).hashString("my_message", StandardCharsets.UTF_8).toString()
Further documentation here: https://guava.dev/releases/23.0/api/docs/com/google/common/hash/Hashing.html#hmacSha256-byte:A-
The answer that you got there is correct. One minor thing in the code above, you need to init(key) before you can call doFinal()
final Charset charSet = Charset.forName("US-ASCII");
final Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
final SecretKeySpec secret_key = new javax.crypto.spec.SecretKeySpec(charSet.encode("key").array(), "HmacSHA256");
try {
sha256_HMAC.init(secret_key);
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
...
This is working fine for me
I have add dependency
compile 'commons-codec:commons-codec:1.9'
ref: http://mvnrepository.com/artifact/commons-codec/commons-codec/1.9
my function
public String encode(String key, String data) {
try {
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
sha256_HMAC.init(secret_key);
return Hex.encodeHexString(sha256_HMAC.doFinal(data.getBytes(StandardCharsets.UTF_8)));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
Try this
Sorry for being late, I have tried all above answers but none of them is giving me correct value, After doing the lot of R&D I have found a simple way that gives me exact value.
Declare this method in your class
private String hmacSha(String KEY, String VALUE, String SHA_TYPE) { try { SecretKeySpec signingKey = new SecretKeySpec(KEY.getBytes("UTF-8"), SHA_TYPE); Mac mac = Mac.getInstance(SHA_TYPE); mac.init(signingKey); byte[] rawHmac = mac.doFinal(VALUE.getBytes("UTF-8")); byte[] hexArray = {(byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'}; byte[] hexChars = new byte[rawHmac.length * 2]; for ( int j = 0; j < rawHmac.length; j++ ) { int v = rawHmac[j] & 0xFF; hexChars[j * 2] = hexArray[v >>> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; } return new String(hexChars); } catch (Exception ex) { throw new RuntimeException(ex); }
}
Use this like
Log.e("TAG", "onCreate: "+hmacSha("key","text","HmacSHA256"));
Verification
1.Android studio output
2. Online HMAC generator Output(Visit here for Online Genrator)Java simple code to generate encoded(HMAC-x) signatures. (Tried using Java-8 and Eclipse)
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import com.sun.org.apache.xml.internal.security.utils.Base64;
/**
* Encryption class to show how to generate encoded(HMAC-x) signatures.
*
*/
public class Encryption {
public static void main(String args[]) {
String message = "This is my message.";
String key = "your_key";
String algorithm = "HmacMD5"; // OPTIONS= HmacSHA512, HmacSHA256, HmacSHA1, HmacMD5
try {
// 1. Get an algorithm instance.
Mac sha256_hmac = Mac.getInstance(algorithm);
// 2. Create secret key.
SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), algorithm);
// 3. Assign secret key algorithm.
sha256_hmac.init(secret_key);
// 4. Generate Base64 encoded cipher string.
String hash = Base64.encode(sha256_hmac.doFinal(message.getBytes("UTF-8")));
// You can use any other encoding format to get hash text in that encoding.
System.out.println(hash);
/**
* Here are the outputs for given algorithms:-
*
* HmacMD5 = hpytHW6XebJ/hNyJeX/A2w==
* HmacSHA1 = CZbtauhnzKs+UkBmdC1ssoEqdOw=
* HmacSHA256 =gCZJBUrp45o+Z5REzMwyJrdbRj8Rvfoy33ULZ1bySXM=
* HmacSHA512 = OAqi5yEbt2lkwDuFlO6/4UU6XmU2JEDuZn6+1pY4xLAq/JJGSNfSy1if499coG1K2Nqz/yyAMKPIx9C91uLj+w==
*/
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
}
}
NOTE: You can use any other Algorithms and can try generating
HmacMD5
,HmacSHA1
,HmacSHA256
,HmacSHA512
signatures.
If but any chance you found a solution how to calculate HMAC-SHA256 here, but you're getting an exception like this one:
java.lang.NoSuchMethodError: No static method encodeHexString([B)Ljava/lang/String; in class Lorg/apache/commons/codec/binary/Hex; or its super classes (declaration of 'org.apache.commons.codec.binary.Hex' appears in /system/framework/org.apache.http.legacy.boot.jar)
Then use:
public static String encode(String key, String data) {
try {
Mac hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
hmac.init(secret_key);
return new String(Hex.encodeHex(hmac.doFinal(data.getBytes("UTF-8"))));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Here is my solution:
public String HMAC_SHA256(String secret, String message)
{
String hash="";
try{
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
sha256_HMAC.init(secret_key);
hash = Base64.encodeToString(sha256_HMAC.doFinal(message.getBytes()), Base64.DEFAULT);
}catch (Exception e)
{
}
return hash.trim();
}
精彩评论