2012-11-24 1 views
3

Java 기반 코드를 C#으로 변환하려고합니다.java 및 C# (winrt)에 대해 동일한 hmac_sha1 결과를 얻을 수 없습니다.

원본 자바 코드;

String str2 = "5f1fa09364a6ae7e35a090b434f182652ab8dd76:{\"expiration\": 1353759442.0991001, \"channel\": \"dreamhacksc2\", \"user_agent\": \".*" 

Mac localMac = Mac.getInstance("HmacSHA1"); 
localMac.init(new SecretKeySpec("Wd75Yj9sS26Lmhve".getBytes(), localMac.getAlgorithm())); 
String str3 = new BigInteger(1, localMac.doFinal(str2.getBytes())).toString(16); 
Object[] arrayOfObject2 = new Object[2]; 
arrayOfObject2[0] = str3; 
arrayOfObject2[1] = URLEncoder.encode(str2); 
String str4 = String.format("%s:%s", arrayOfObject2); 

그리고 여기 내 WinRT 기반의 C# 코드

var token="5f1fa09364a6ae7e35a090b434f182652ab8dd76:{\"expiration\": 1353759442.0991001, \"channel\": \"dreamhacksc2\", \"user_agent\": \".*"; 

var encoding = new System.Text.UTF8Encoding(); 
var key = encoding.GetBytes("Wd75Yj9sS26Lmhve"); 
//var key = Convert.FromBase64String("Wd75Yj9sS26Lmhve"); 

var tokenData = encoding.GetBytes(token); 

var result = HmacSha1(key, tokenData); 

var hexString = new BigInteger(result).ToString("x"); 
var urlEncoded = System.Net.WebUtility.UrlEncode(token); 

var combined = String.Format("{0}:{1}", hexString, urlEncoded); 

내가 WinRT에서 실행 해요로 HMACSHA1 기능입니다;

public static byte[] HmacSha1(byte[] key, byte[] data) 
    { 
     var crypt = Windows.Security.Cryptography.Core.MacAlgorithmProvider.OpenAlgorithm("HMAC_SHA1"); 
     var keyBuffer = Windows.Security.Cryptography.CryptographicBuffer.CreateFromByteArray(key); 
     var cryptKey = crypt.CreateKey(keyBuffer); 

     var dataBuffer = Windows.Security.Cryptography.CryptographicBuffer.CreateFromByteArray(data); 
     var signBuffer = Windows.Security.Cryptography.Core.CryptographicEngine.Sign(cryptKey, dataBuffer); 

     byte[] result; 
     Windows.Security.Cryptography.CryptographicBuffer.CopyToByteArray(signBuffer, out result); 

     return result; 
    } 

그래서 여기에 해당하는 아웃 퍼스가 있습니다. 상술 한 바와 같이

(JAVA) 92e893efe72a2f7df6ed409ce35819faba191a63:5f1fa09364a6ae7e35a090b434f182652ab8dd76%3A%7B%22expiration%22%3A+1353759442.0991001%2C+%22channel%22%3A+%22dreamhacksc2%22%2C+%22user_agent%22%3A+%22.* 
    (C#) 63b10e1d8e9f99cd7fba2ed46fe8e4a4a40222f5:5f1fa09364a6ae7e35a090b434f182652ab8dd76%3A%7B%22expiration%22%3A+1353759442.0991001%2C+%22channel%22%3A+%22dreamhacksc2%22%2C+%22user_agent%22%3A+%22.* 

는 자바 및 C#에서의 HMAC_SHA1으로 출력한다은 동일하지 않다. 어떤 아이디어? 인코딩 문제가 있습니까?

+0

내가 코멘트 내가 쓸 종류의 것 f 당신은 질문에 대해 찬성표를 던집니다. – HuseyinUslu

+0

C# 및 Java 출력이 올바르지 않을 때 명확하지 않을 때 질문을 수정하지 않기 때문에. 이것은 꽤 현지화 된 질문입니다. 이것을 디버깅하는 가장 좋은 방법은 HMAC 코드에 전달하기 전에 16 진수 인코딩을 사용하여 모든 키와 데이터를 인쇄하는 것입니다. –

답변

4

간단하고 코드를 동일하게 유지하십시오.

자바 :

public static String toHexString(byte[] bytes) { 
    StringBuilder sb = new StringBuilder(bytes.length * 2); 
    for (int i = 0; i < bytes.length; ++i) { 
     sb.append(String.format("%02x", bytes[i])); 
    } 
    return sb.toString(); 
} 

public static void main(String[] args) { 
    String str2 = "5f1fa09364a6ae7e35a090b434f182652ab8dd76:{\"expiration\": 1353759442.0991001, \"channel\": \"dreamhacksc2\", \"user_agent\": \".*"; 
    Mac localMac; 
    try { 
     localMac = Mac.getInstance("HmacSHA1"); 

     localMac.init(new SecretKeySpec("Wd75Yj9sS26Lmhve" 
       .getBytes("UTF-8"), localMac.getAlgorithm())); 
     byte[] result = localMac.doFinal(str2.getBytes("UTF-8")); 
     String hexString = toHexString(result); 
     System.out.println(hexString); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } catch (InvalidKeyException e) { 
     e.printStackTrace(); 
    } catch (IllegalStateException e) { 
     e.printStackTrace(); 
    } catch (UnsupportedEncodingException e) { 
     e.printStackTrace(); 
    } 

} 

결과 :

f52202a4a4e4e86fd42eba7fcd999f8e1d0eb163 

C 번호 :

var token = "5f1fa09364a6ae7e35a090b434f182652ab8dd76:{\"expiration\": 1353759442.0991001, \"channel\": \"dreamhacksc2\", \"user_agent\": \".*"; 

var encoding = new System.Text.UTF8Encoding(); 
var privateKey = "Wd75Yj9sS26Lmhve"; 
HMACSHA1 hmac_sha1 = new HMACSHA1(encoding.GetBytes(privateKey)); 
hmac_sha1.Initialize(); 
byte[] result = hmac_sha1.ComputeHash(encoding.GetBytes(token)); 

string hexString = String.Join("", result.Select(a => a.ToString("x2"))); 

Console.WriteLine(hexString); 

결과 :

f52202a4a4e4e86fd42eba7fcd999f8e1d0eb163 
4

세 가지 팁 : f52202a4a4e4e86fd42eba7fcd999f8e1d0eb163 자바와 C#은 당신에 의해 게시 된 결과와 다르다 : 나는 당신의 자바 코드를 테스트

  1. , 나는 STR3이 값을 받았다.

  2. 위키 백과는 example 포함 (This online tool도. 내 결과를 계산), 그리고 자바 코드와 온라인 계산기를 기반으로 올바른 것 같다. 첫 번째 단계에서는 Java 및 C# 코드를 "The quick brown fox jumps over the lazy dog", "key", "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9" 세 쌍으로 테스트합니다.

  3. 바이트 배열이 0 이상의 숫자 (또는 hexit?)로 시작될 때 BigInterger.toString (16)을 사용하여 바이트 배열을 16 진수 문자열로 변환하는 것은 좋지 않습니다. 변환 된 16 진수 문자열은 선두 문자 0 개를 포함합니다.

+0

맞습니다, [코드] (https://compilr.com/raistlinthewiz/hmac-sha1-test)는 출력으로 f52202a4a4e4e86fd42eba7fcd999f8e1d0eb163을 계산합니다. 이제 C# 코드를 먼저 수정하려고합니다. – HuseyinUslu

+0

그리고 이제 완전히 다른 해시가 생겼어. [C# code] (https://compilr.com/raistlinthewiz/hmac-sha1-csharp-test)와 함께 .net 4.0의 System.Security.Cryptography stuff를 사용하는 70F4E22B2600225A3151727323B0CAB40B325045. 나는 지금 완전히 혼란 스럽다. .. – HuseyinUslu

1

문자열을 바이트와 혼동하고 있습니다. getBytes()의 결과는 기본값 인 에 따라 다르며 시스템마다 다를 수 있습니다.

+0

그래서 Windows 기반 호스트에서 java의 기본 인코딩에 대한 아이디어가 있습니까? – HuseyinUslu

+0

@HuseyinUslu 보이는 언어 설정에 따라 다릅니다. 일반적으로 UTF-8이 아닌 8 비트 문자 인코딩 용 ISO 8859 표준을 기반으로하는 Windows 독점 스키마 중 하나입니다. ASCII의 경우 UTF-8과 호환되어야합니다. 별로 다른 것 (상당히 일반적인 UTF-16 기반 스키마 포함). –