2016-09-06 145 views
1

我有這樣一段代碼在C#:HMAC-SHA256用Java /翻譯從C#

byte[] bytes = Encoding.Default.GetBytes("secret key"); 
int value = checked((int)Math.Round((currentDateTime - dateTimeOf1970).TotalSeconds)); 
HMACSHA256 hMACSHA = new HMACSHA256(bytes); 
string text2 = this.toHexString(hMACSHA.ComputeHash(Encoding.Default.GetBytes(value.ToString() + "/" + url))); 

其中方法toHexString是這樣的:

private string toHexString (byte[] bytes) 
    { 
     string text = ""; 
     checked 
     { 
      for (int i = 0; i < bytes.Length; i++) 
      { 
       byte b = bytes[i]; 
       int num = (int)b; 
       string text2 = num.ToString("X").ToLower(); 
       if (text2.Length < 2) 
       { 
        text2 = "0" + text2; 
       } 
       text += text2; 
      } 
      return text; 
     } 
    } 

現在我想有在Java中,由於我的Java技能不如我的C#技能,所以我正在弄清楚如何翻譯它。我這樣翻譯的toHexString方法:

private static String toHexString (byte[] bytes) { 
    String text = ""; 
    for (int i = 0; i < bytes.length; i++) { 
     byte b = bytes[i]; 
     int num = (int) b; 
     String text2 = Integer.toHexString(num); 
     if (text2.length() < 2) { 
      text2 = "0" + text2; 
     } 
     text += text2; 

    } 

    return text; 

} 

這很好,產生與C#版本相同的輸出。

我們其他的方法(與HMCAS-SHA256),多數民衆贊成在它翻譯我去:

//creating the timestamp 
    long timestamp = System.currentTimeMillis()/1000; 
    //getting the int value of it 
    int value = (int) timestamp; 

    //just a string that is the value of the hmac 
    String input = String.valueOf(value) + "/" + url; 
    //new hmac instance 
    Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); 
    //my secret key where bytes is "my key".getBytes(); 
    SecretKeySpec secret_key = new SecretKeySpec(bytes, "HmacSHA256"); 
    sha256_HMAC.init(secret_key); 
    //trying to have as string 
    String txt2 = toHexString (sha256_HMAC.doFinal(input.getBytes())); 

問題是,它不產生相同的輸出,

C#版本(如何應該是):

12eb558b98dd9a5429e7676640f3dd4122941a575ffa9dc20318... 

Java版本:

fffffff8fffffff87215ffffffb232ffffffeeffffff9069fffffffc6d4cffffffb667ff... 

任何幫助,將不勝感激!

+1

你的C#版本可以通過擺脫整個「如果長度小於2,前置一個0」位並將'ToString()'參數從'X'改爲'X2'來改進。另一個改進是使用'StringBuilder'來構建'text'而不是進行一連串的連接。 – itsme86

+0

謝謝,剛剛編寫了它,但是一旦我想到它在Java中的工作原理,一定會用你提出的建議來改進它。 – user3024750

回答

2

您的主要問題是您的Java toHexString()方法被搞砸了。

的Java總是與符號值工作,因此Integer.toHexString(num);返回大量的負32位數字(可以在輸出中看到的ff

因此,如果您轉換一個字節的(無符號)詮釋你總是要添加& 0xFF:。

Integer.toHexString(0xff & num); 

反正一個字節數組到十六進制字符串的方法是提供了大量的庫因此,沒有必要再編寫它,我寧願從Apache Hex類commons codec library。

順便說一句:你在C#和Java中使用的默認編碼,但即使在同一臺機器上,這並不一定意味着編碼是相同的。改用UTF-8等固定的。

+0

非常感謝,解決了這個問題。我還編輯了編碼,以便我現在只使用UTF-8。 – user3024750