[英]Problems while porting php to C# with hash_hmac
I'm trying to port a script from php to C#. 我正在尝试将脚本从php移植到C#。 The script is to create a key for authentication for my school intranet.
该脚本是为我的学校Intranet创建用于身份验证的密钥。 I got the most part but the output of the two differ.
我得到了大部分,但两者的输出却不同。
Code in PHP: PHP中的代码:
/**
* 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);
Code in C#: C#中的代码:
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;
}
The output produces for example: 输出产生例如:
gr001 cmVzdC1leGFtcGxl:NmY4ZTgzMWI4NGRhYmExYTEzMjdmMzQ3Nzg3ZWU0MDNjZWQ1ZTFhOQ==
gr001 cmVzdC1leGFtcGxl:MTUzMzlEMTQyNjRBNzZEQ0I2QkJERUE4MjEyMkNCQ0Q4ODhCQjE2MQ==
The first one (the correct one) doesn't match the second one in C#. 第一个(正确的)与C#中的第二个不匹配。 What I've debugged so far is that
userPasswd
is generated correctly but as soon as I get to the hmac hashing part it doesn't match anymore. 到目前为止,我调试的是正确生成了
userPasswd
,但是一旦我进入hmac哈希部分,它就不再匹配了。
Also here is all I got from the documentation: 这也是我从文档中得到的全部:
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)
I figured it out! 我想到了!
I made two mistakes: 我犯了两个错误:
I used DateTime.Now
instead of DateTime.UtcNow
so the dates of the two functions didn't match. 我使用
DateTime.Now
而不是DateTime.UtcNow
所以两个函数的日期不匹配。 (I don't know how I missed that...) (我不知道我怎么想念...)
While the hash_hmac
function in php returns the hex string as lowercase the C# function returns in uppercase and therefore I get a different result in Convert.ToBase64String
虽然php中的
hash_hmac
函数以小写形式返回十六进制字符串,而C#函数以大写形式返回,因此我在Convert.ToBase64String
得到了不同的结果
Thanks for the help anyways. 无论如何,谢谢您的帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.