équivalent java à hmac-SHA1 de php
-
05-07-2019 - |
Question
Je recherche un équivalent Java à cet appel php:
hash_hmac('sha1', "test", "secret")
J'ai essayé cela en utilisant java.crypto.Mac. , mais les deux ne sont pas d'accord:
String mykey = "secret";
String test = "test";
try {
Mac mac = Mac.getInstance("HmacSHA1");
SecretKeySpec secret = new SecretKeySpec(mykey.getBytes(),"HmacSHA1");
mac.init(secret);
byte[] digest = mac.doFinal(test.getBytes());
String enc = new String(digest);
System.out.println(enc);
} catch (Exception e) {
System.out.println(e.getMessage());
}
Les sorties avec key = " secret " et test = " test " ne semblent pas correspondre.
La solution
En fait, ils sont d'accord.
Comme Hans Doggen l'a déjà indiqué, PHP génère le résumé du message en utilisant la notation hexadécimale, sauf si vous définissez le paramètre de sortie brut sur true.
Si vous souhaitez utiliser la même notation en Java, vous pouvez utiliser quelque chose comme
for (byte b : digest) {
System.out.format("%02x", b);
}
System.out.println();
pour formater la sortie en conséquence.
Autres conseils
Vous pouvez essayer ceci en Java:
private static String computeSignature(String baseString, String keyString) throws GeneralSecurityException, UnsupportedEncodingException {
SecretKey secretKey = null;
byte[] keyBytes = keyString.getBytes();
secretKey = new SecretKeySpec(keyBytes, "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(secretKey);
byte[] text = baseString.getBytes();
return new String(Base64.encodeBase64(mac.doFinal(text))).trim();
}
Voici mon implémentation:
String hmac = "";
Mac mac = Mac.getInstance("HmacSHA1");
SecretKeySpec secret = new SecretKeySpec(llave.getBytes(), "HmacSHA1");
mac.init(secret);
byte[] digest = mac.doFinal(cadena.getBytes());
BigInteger hash = new BigInteger(1, digest);
hmac = hash.toString(16);
if (hmac.length() % 2 != 0) {
hmac = "0" + hmac;
}
return hmac;
Il me semble que PHP utilise la notation HEX pour les octets générés par Java (1a = 26) - mais je n'ai pas vérifié l'expression entière.
Que se passe-t-il si vous exécutez le tableau d'octets via la méthode sur this page?
Mon implémentation pour HmacMD5 - il suffit de changer l'algorithme en HmacSHA1:
SecretKeySpec keySpec = new SecretKeySpec("secretkey".getBytes(), "HmacMD5");
Mac mac = Mac.getInstance("HmacMD5");
mac.init(keySpec);
byte[] hashBytes = mac.doFinal("text2crypt".getBytes());
return Hex.encodeHexString(hashBytes);
Je ne l'ai pas testé, mais essayez ceci:
BigInteger hash = new BigInteger(1, digest);
String enc = hash.toString(16);
if ((enc.length() % 2) != 0) {
enc = "0" + enc;
}
C’est un instantané de ma méthode qui fait que le md5 de java et sha1 correspondent à php.
De cette façon, je pourrais obtenir exactement la même chaîne que je obtenais avec hash_hmac en php
String result;
try {
String data = "mydata";
String key = "myKey";
// Get an hmac_sha1 key from the raw key bytes
byte[] keyBytes = key.getBytes();
SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "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(data.getBytes());
// Convert raw bytes to Hex
byte[] hexBytes = new Hex().encode(rawHmac);
// Covert array of Hex bytes to a String
result = new String(hexBytes, "ISO-8859-1");
out.println("MAC : " + result);
}
catch (Exception e) {
}