2009-10-22 8 views
46

私はこのPHPの呼び出しと同じJavaを探しています:java.crypto.Macを使用して、Javaの同等のHMAC-SHA1

hash_hmac('sha1', "test", "secret") 

私はこれを試してみましたが、両者が同意しない:

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()); 
} 

key = "secret"とtest = "test"の出力が一致していないようです。

+2

どのように違いますか? sha1のテストパターンに一致するものはどれですか? PHPドキュメントの概要は、 "raw_output"オプションを示しています。 –

+0

いくつかのテスト入力と出力を送ります(バイナリパラメータに16進エンコーディングまたは64進数を使用します)。 – erickson

答えて

37

実際、彼らは同意します。
Hans Doggenは既に、raw出力パラメータをtrueに設定しない限り、PHPは16進表記を使用してメッセージダイジェストを出力すると述べています。
あなたはJavaで同様の表記を使用する場合は、それに応じて出力をフォーマットする

for (byte b : digest) { 
    System.out.format("%02x", b); 
} 
System.out.println(); 

のようなものを使用することができます。

3

PHPは、Javaが生成するバイト(1a = 26)に16進表記を使用していますが、表現全体をチェックしませんでした。

thisページのメソッドでバイト配列を実行するとどうなりますか?

1

はそれをテストしたが、これを試していないがあります:

 BigInteger hash = new BigInteger(1, digest); 
     String enc = hash.toString(16); 
     if ((enc.length() % 2) != 0) { 
      enc = "0" + enc; 
     } 

これは、JavaのMD5とSHA1マッチPHPを作る私の方法からスナップショットです。

+0

もちろん、新しいStringBuilder(digest.length * 2)、for/nextループ、およびappend(String.format( "%02X")、digest [i]&0xFF]を使用するとメモリの消費量が少なくなり、 。 –

+0

if文はwhileループである必要があります。複数の先行ゼロの場合は機能しません。 – slushi

4

これは私の実装です:

 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; 
+0

それは私のために働く唯一の解決策です。どうもありがとう! –

11

あなたは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(); 
} 
1

HMACMD5のための私の実装 - ただ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); 
1

この方法私はPHPでhash_hmacを使っていたのと全く同じ文字列を得ることができました

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) { 

} 
+0

これは正解です。多くの人が16進数のエンコードステップを逃しています。 – Krishnaraj