HMC SHA1-хеш - C# производит другой хеш-вывод, чем PHP
У меня есть код на PHP, и он находится ниже, когда я выполняю код PHP ниже и когда я запускаю код C#, который находится ниже кода PHP, я получил другой результат. Я не знаю, где я ошибаюсь.
$accessID = "member-1681fca809";
$secretKey = "63f22236ab43b69462b3272b110e3c78";
$expires = 1357039353;
$stringToSign = $accessID."\n".$expires;
$binarySignature = hash_hmac('sha1', $stringToSign, $secretKey, true);
$urlSafeSignature = urlencode(base64_encode($binarySignature));
print_r($expires);
print_r($urlSafeSignature);
I got Output
1357039353
M1PZW2DYVzdRV1l4ZHBPAmiv9iM%3D
В то время как я запускаю тот же код в C#, я получил другой вывод
string accessid = "member-1681fca809";
string secretekey = "63f22236ab43b69462b3272b110e3c78";
int Expire = 1357039353;
string stringTosign = accessid + Environment.NewLine + Expire;
byte[] secret = UTF8Encoding.UTF8.GetBytes(secretekey);
HMACSHA1 myhmacsha1 = new HMACSHA1(secret);
byte[] byteArray = Encoding.ASCII.GetBytes(stringTosign);
MemoryStream stream = new MemoryStream(byteArray);
byte[] hashValue = myhmacsha1.ComputeHash(stream);
string k = Convert.ToBase64String(Encoding.ASCII.GetBytes(hashValue.ToString()));
console.WriteLine(Expire);
console.WriteLine(k);
I Got OutPut
1357039353
U3lzdGVtLkJ5dGVbXQ==
3 ответа
Немного изменил ваш код.
string accessid = "member-1681fca809";
string secretekey = "63f22236ab43b69462b3272b110e3c78";
int Expire = 1357039353;
string stringTosign = accessid + "\n" + Expire;
byte[] secret = UTF8Encoding.UTF8.GetBytes(secretekey);
HMACSHA1 myhmacsha1 = new HMACSHA1(secret);
byte[] byteArray = Encoding.ASCII.GetBytes(stringTosign);
MemoryStream stream = new MemoryStream(byteArray);
byte[] hashValue = myhmacsha1.ComputeHash(stream);
string k = Convert.ToBase64String(hashValue);
Console.WriteLine(Expire);
Console.WriteLine(k);
Единственным отличием будет последний символ, так как вы используете url_encode, который преобразует символ "=".
Когда вы получите разные результаты для HMACSHA1/hash_hmac('sha1', ...), начните сплит-тестирование версий PHP и C# с очень простыми входными данными, такими как input = "a", key = "b". Если вы кодируете ключ перед передачей его в HMACSHA1, проверьте, правильно ли вы его кодируете. Я часами думал, что проблема в хешировании HMACSHA1, хотя в действительности это была плохая реализация пакета ('H*'...).
public static string Encode(string input, byte[] key)
{
HMACSHA1 myhmacsha1 = new HMACSHA1(key);
byte[] byteArray = Encoding.ASCII.GetBytes(input);
MemoryStream stream = new MemoryStream(byteArray);
return myhmacsha1.ComputeHash(stream).Aggregate("", (s, e) => s + String.Format("{0:x2}", e), s => s);
}
и упаковать ('H*'...) C# реализацию:
public static byte[] PackH(string hex)
{
if ((hex.Length % 2) == 1) hex += '0';
byte[] bytes = new byte[hex.Length / 2];
for (int i = 0; i < hex.Length; i += 2)
{
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
}
return bytes;
}
НЕ конвертируйте вещи из байтового массива в строку и обратно в байтовый массив, когда вы передаете вещи в функцию Encode, просто передайте byte[] и сохраняйте вещи простыми.
Спасибо! Проблема решена, все же хотел поделиться своим опытом.
Ошибка, которую я делал, заключалась в том, что я использовал строитель строк sbr.Append вместо sbr.AppendLine() или прямую конкатенацию строк, как вы делали, когда \n читается как новая строка.