2013-01-08 42 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