2013-01-08 108 views
5

我有一個java代碼示例,使用HMAC-SHA1算法(RFC 2104)計算摘要,然後使用Base64編碼(RFC 2045)進行編碼。C#vs Java HmacSHA1然後base64

這裏是Java代碼

public static String buildDigest(String key, String idString) throws SignatureException { 


try { 
    String algorithm = "HmacSHA1"; 
    Charset charset = Charset.forName("utf-8"); 
    SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), algorithm); 
    Mac mac = Mac.getInstance(algorithm); 
    mac.init(signingKey); 
    return new String(Base64.encodeBase64(mac.doFinal(idString.getBytes(charset))), charset); 
    } catch (Exception e) { 
    throw new SignatureException("Failed to generate HMAC : " + e.getMessage()); 
    } 
} 

我在這裏找到答案在堆棧溢出所以這裏的C#代碼

private string EncodeHMAC(string input, byte[] key) 
    { 
     HMACSHA1 myhmacsha1 = new HMACSHA1(key); 
     byte[] byteArray = Encoding.UTF8.GetBytes(input); 
     // MemoryStream stream = new MemoryStream(byteArray); 
     var hashValue = myhmacsha1.ComputeHash(byteArray); 
     return hashValue.Aggregate("", (s, e) => s + String.Format("{0:x2}", e), s => s); 
    } 

    private string EncodeTo64(string toEncode) 
    { 
     byte[] toEncodeAsBytes = System.Text.UTF8Encoding.UTF8.GetBytes(toEncode); 

     string returnValue = System.Convert.ToBase64String(toEncodeAsBytes); 

     return returnValue; 
    } 

我沒有收到在tutorial that I am following

+0

爲什麼在Java版本中將密鑰作爲字符串傳遞?您確定Java方法'key.getBytes()'的結果等同於您在C#版本中使用的字節數組嗎?如果我正確理解你的C#代碼,它也會返回HMAC十六進制編碼,而Java版本使用Base64。 – jarnbjo

回答

7
出正確的結果

試試這個:

// This method will return the base 64 encoded string using the given input and key. 
private string EncodeHMAC(string input, byte[] key) 
{ 
    HMACSHA1 hmac = new HMACSHA1(key); 
    byte[] stringBytes = Encoding.UTF8.GetBytes(input); 
    byte[] hashedValue = hmac.ComputeHash(stringBytes); 
    return Convert.ToBase64String(hashedValue); 
} 

我不認爲你正在將哈希值轉換爲基本64字符串。

2

我使用此函數來實現REST Web服務調用的身份驗證。 發送者和接收者使用相同的編碼是很重要的。

不幸的是,我花了一段時間才找到一個匹配的PHP HAMACimplementation到這個C#版本。

private bool ValidateHash(String uid, String hash, DataToSign data) { 
     StringBuilder strToSign = new StringBuilder(); 

     strToSign.Append(data.HttpMethod + '\n'); 
     strToSign.Append(data.Date.ToString("r") + '\n'); 
     strToSign.Append(data.Uri); 

     Byte[] secretBytes = UTF8Encoding.UTF8.GetBytes(this._secretKey); 
     HMACSHA1 hmac = new HMACSHA1(secretBytes); 

     Byte[] dataBytes = UTF8Encoding.UTF8.GetBytes(strToSign.ToString()); 
     Byte[] calcHash = hmac.ComputeHash(dataBytes); 
     String calcHashString = Convert.ToBase64String(calcHash); 

     if (calcHashString.Equals(hash)) { 
      if (log.IsDebugEnabled) log.Debug(uid + " - [ValidateHash] HMAC is valid."); 
      return true; 
     } 
     return false; 
    } 

希望有幫助!

+0

如果您打算使用字符串生成器,請不要在append方法內連接字符串!如果你想在你的字符串末尾添加一個新行,可以這樣做:'strToSign.AppendLine(data.HttpMethod)' – RobH

+0

@RobH你是對的 - 我寫了這段代碼已經有一段時間了。 – Andreas