2014-07-21 2 views
0

PHP에서 C#으로 스크립트를 이식하려고합니다. 스크립트는 학교 인트라넷의 인증을위한 키를 만드는 것입니다. 나는 가장 많은 부분을 가졌지 만 두 가지 결과물은 다릅니다. PHP에서hash_hmac와 함께 C#으로 PHP를 이식 할 때의 문제

코드 : C에서 #

/** 
* Generate authorization headers 
* 
* @param string $username 
* @param string $password 
* @param string $prefix 
* @param string $hashAlgorithm 
* 
* @return array(
*   'X-gr-AuthDate': uncrypted date 
*   'Authorization': encrypted token 
*) 
*/ 

function generateHeaders($username, $password, $prefix, $hashAlgorithm = 'sha1') 
{ 
    $rfc_1123_date = gmdate('D, d M Y H:i:s T', time()); 
    $xgrdate = utf8_encode($rfc_1123_date); 
    $userPasswd = base64_encode(hash($hashAlgorithm, $password, true)); 

    $signature = base64_encode(hash_hmac($hashAlgorithm, $userPasswd, $xgrdate)); 
    $auth = $prefix . " " . base64_encode($username) . ":" . $signature; 
    $headers = array(
        'X-gr-AuthDate' => $xgrdate, 
        'Authorization' => $auth 
    ); 

    return $headers; 
} 

$headers = generateHeaders("rest-example", "topsecret", "gr001"); 

header('Content-Type: application/json'); 

echo json_encode($headers); 

코드 : 출력은 예를 들어 생성

public static void Main (string[] args) 
    { 
     // Get data from php function 
     WebClient wc = new WebClient(); 
     byte[] res = wc.DownloadData ("http://localhost/test.php"); 
     JObject obj = JObject.Parse (System.Text.Encoding.UTF8.GetString (res)); 
     Console.WriteLine ((string)obj["Authorization"]); 

     // Generate auth data 
     string[] test = ConstructHeaders ("rest-example", "topsecret", "gr001"); 
     Console.WriteLine (test [0]); 
    } 

    public static string[] ConstructHeaders(string username, string password, string prefix) 
    { 
     Encoding utf8 = Encoding.UTF8; 
     SHA1 sha = new SHA1CryptoServiceProvider(); 

     // Get current date 
     DateTime now = DateTime.Now; 
     string rfc_date = now.ToString ("ddd, dd MMM yyyy HH:mm:ss") + " GMT"; // TODO: Automatically add timezone 


     string userPasswd = Convert.ToBase64String(sha.ComputeHash (utf8.GetBytes(password))); 
     string signature = Convert.ToBase64String(utf8.GetBytes(EncodeHMac (userPasswd, rfc_date))); 

     string auth = prefix + " " + Convert.ToBase64String(utf8.GetBytes(username)) + ":" + signature; 
     return new string[] {auth, rfc_date}; 
    } 

    static string EncodeHMac(string message, string key) 
    { 
     var keyByte = Encoding.UTF8.GetBytes(key); 
     using (var hmacsha1 = new HMACSHA1(keyByte)) 
     { 
      hmacsha1.ComputeHash(Encoding.UTF8.GetBytes(message)); 

      return ByteToString(hmacsha1.Hash); 
     } 
    } 
    static string ByteToString(byte[] buff) 
    { 
     string sbinary = ""; 
     for (int i = 0; i < buff.Length; i++) 
      sbinary += buff[i].ToString("X2"); /* hex format */ 
     return sbinary; 
    } 

:

gr001 cmVzdC1leGFtcGxl:NmY4ZTgzMWI4NGRhYmExYTEzMjdmMzQ3Nzg3ZWU0MDNjZWQ1ZTFhOQ== 
gr001 cmVzdC1leGFtcGxl:MTUzMzlEMTQyNjRBNzZEQ0I2QkJERUE4MjEyMkNCQ0Q4ODhCQjE2MQ== 

첫번째 (정확한)을하지 않는다 C#에서 두 번째 것과 일치합니다. 지금까지 디버깅 한 내용은 userPasswd이 올바르게 생성되었지만 hmac 해싱 부분에 도달하면 더 이상 일치하지 않습니다.

또한 여기에 내가 문서에서 가져온 모든입니다 :

X-gr-AuthDate: date 
Authorization: prefix encoded_username:signature 



where 

    date = according to RFC 822, updated by RFC 1123, e.g 'Sun, 06 Nov 1994 08:49:37 GMT' 
    prefix = gr001 (provided with your account's security credentials) 
    encoded_username = Base64(username) 
    signature = Base64(HMAC-Sha1(secret-token, date)) 



    where 

     secret-token = hash(user-password), hash function to use is provided with your account's security credentials (SHA-1) 
+0

이 도구는 어떤 도움이 될까요? http : //www.freeformatter.com/hmac-generator.html – doctorbobapplications

+0

해당 사이트에서 생성 된 코드와 일치하지 않으므로 잘못 입력 했어야합니다. 나는 오늘 다시 시간이 없어서 나중에 다시 올 것이다. – JensV

답변

0

내가 그것을 알아 냈어! 내가 그렇게 두 함수의 날짜가 일치하지 않습니다 DateTime.UtcNow 대신 DateTime.Now를 사용

  1. :

    나는 두 가지 실수를했다. PHP에서 hash_hmac 함수는 16 진수 문자열을 반환하는 동안 대문자 C#을 함수가 반환을 소문자로

  2. 을 (내가 ... 내가 그 놓친 방법을 모른다) 때문에 나는 Convert.ToBase64String

에서 다른 결과를 얻을 수

어쨌든 도움에 감사드립니다.

관련 문제