2013-01-08 28 views
5

Tôi có một ví dụ mã java để thực hiện một phép tính tiêu hóa bằng thuật toán HMAC-SHA1 (RFC 2104.), sau đó được mã hóa bằng cách sử dụng mã hóa Base64 (RFC 2045).C# so với Java HmacSHA1 và sau đó base64

đây là mã 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()); 
    } 
} 

Tôi tìm thấy câu trả lời ở đây trong Stack Overflow vì vậy đây là đoạn code 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; 
    } 

Tôi không nhận được kết quả đúng hiển thị trong tutorial that I am following

+0

Tại sao bạn chuyển khóa như một chuỗi trong phiên bản Java? Bạn có chắc rằng kết quả của phương thức Java 'key.getBytes()' tương đương với mảng byte mà bạn đang sử dụng trong phiên bản C# không? Nếu tôi hiểu mã C# của bạn một cách chính xác, nó cũng trả về mã hex HMAC, trong khi phiên bản Java sử dụng Base64. – jarnbjo

Trả lời

7

Hãy thử cách này:

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

Tôi không nghĩ rằng bạn đang chuyển đổi giá trị băm thành chuỗi cơ số 64 chính xác.

2

Tôi sử dụng chức năng này để thực hiện xác thực các cuộc gọi dịch vụ web REST. Điều quan trọng là người gửi và người nhận sử dụng cùng một mã hóa.

Thật không may, tôi mất một lúc để tìm một HAMACimplementation PHP phù hợp với phiên bản C# này.

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

Hy vọng điều đó sẽ hữu ích!

+0

Nếu bạn định sử dụng trình tạo chuỗi không nối các chuỗi trong phương thức chắp thêm! Nếu bạn muốn thêm một dòng mới ở cuối chuỗi của bạn, hãy làm điều này thay vào đó: 'strToSign.AppendLine (data.HttpMethod)' – RobH

+0

@RobH bạn nói đúng - đã lâu rồi tôi viết nó. – Andreas

Các vấn đề liên quan