С# эквивалент hash_hmac в PHP
используя .NET и С#, я должен предоставить строку целостности, используя HMAC SHA512 для PHP-сервера.
Использование в С#:
Encoding encoding = Encoding.UTF8;
byte[] keyByte = encoding.GetBytes(key);
HMACSHA512 hmacsha512 = new HMACSHA512(keyByte);
byte[] messageBytes = encoding.GetBytes(message);
byte[] hashmessage = hmacsha512.ComputeHash(messageBytes);
return(ByteToString(hashmessage).toUpper());
Но это не соответствует PHP hash_hmac()
PHP-код:
$hmac = strtoupper(hash_hmac($pbx_hash, $msg, $binKey));
Я пытаюсь изменить кодировку на С# (utf8, ASCII, Unicode). Без успеха.
Я пробовал много решений, найденных в сети, но ничто не дает одну и ту же строку: (
Я не могу изменить PHP-код и не вижу, что не так в С#
Изменить. Это ByteToString
(скопировано из комментария):
static string ByteToString(byte[] buff)
{
string sbinary = "";
for (int i = 0; i < buff.Length; i++)
{
sbinary += buff[i].ToString("X2"); /* hex format */
}
return (sbinary);
}
После многих тэгов найдено, что я получаю те же результаты, если PHP hash_hmac key - это строка, а не байтовый массив. Кажется, проблема связана с функцией преобразования PHP $binKey = pack ( "H *", $keyTest);
Ответы
Ответ 1
Проблема должна быть фактическим представлением данных ключа/сообщения.
См. следующие тесты:
PHP
#!/usr/bin/php
<?php
print strtoupper(hash_hmac("sha256", "message", "key"));
?>
Выход (через http://writecodeonline.com/php/):
6E9EF29B75FFFC5B7ABAE527D58FDADB2FE42E7219011976917343065F58ED4A
C#
using System;
using System.Text;
using System.Security.Cryptography;
public class Program
{
private const string key = "key";
private const string message = "message";
private static readonly Encoding encoding = Encoding.UTF8;
static void Main(string[] args)
{
var keyByte = encoding.GetBytes(key);
using (var hmacsha256 = new HMACSHA256(keyByte))
{
hmacsha256.ComputeHash(encoding.GetBytes(message));
Console.WriteLine("Result: {0}", ByteToString(hmacsha256.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;
}
}
Выход (через http://ideone.com/JdpeL):
Result: 6E9EF29B75FFFC5B7ABAE527D58FDADB2FE42E7219011976917343065F58ED4A
Итак, проверьте набор символов/кодировку входных данных PHP. Также проверьте фактический алгоритм (в $pbx_hash
).
Ответ 2
private static string HashHmac(string message, string secret)
{
Encoding encoding = Encoding.UTF8;
using (HMACSHA512 hmac = new HMACSHA512(encoding.GetBytes(secret)))
{
var msg = encoding.GetBytes(message);
var hash = hmac.ComputeHash(msg);
return BitConverter.ToString(hash).ToLower().Replace("-", string.Empty);
}
}
Ответ 3
Как сказано выше, проблема заключалась в функции PHP Pack (H *), используемой для преобразования ключа в массив байтов.
С# Getbytes не дает того же результата (utf8, asci, unicode...).
Решение найдено здесь: http://www.nuronconsulting.com/c-pack-h.aspx было в порядке для меня.
теперь HMAC из С# соответствует PHP!
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;
}
Ману спасибо всем за вашу помощь.