Обновлено: я исправил кодировку ascii, как указано @DavidG.
Я создаю интеграцию с поставщиком, и интеграция требует, чтобы я подписал сообщение с помощью алгоритма HMAC-SHA256.
Простой тест, который я получил от поставщика, заключается в том, что мы собираемся использовать эти данные:
key: "1234567890ABCDEF1234567890ABCDEF" (hex)
data: "00000000" (ascii)
expected output (only first 32 chars): FF365893D899291C3BF505FB3175E880 (hex)
Я проверил несколько онлайн-генераторов hmac и обнаружил, что они возвращают мне разные результаты, некоторые правильные, а некоторые неправильные.
Correct reply: https://www.liavaag.org/English/SHA-Generator/HMAC/
Correct reply: https://cryptii.com/pipes/hmac
Incorrect reply: https://codebeautify.org/hmac-generator
Incorrect reply: http://billatnapier.com/security01.aspx
Может ли кто-нибудь помочь мне или указать мне правильное направление здесь? Из-за этого я очень скоро облысею...
[TestClass()]
public class AutogiroConcentFileWriterTests
{
[TestMethod()]
public void ManualKVVTest()
{
String key = "1234567890ABCDEF1234567890ABCDEF";
String message = "00000000";
String expected = "FF365893D899291C3BF505FB3175E880";
Encoding ascii = Encoding.ASCII;
Byte[] key_bytes = this.KeyData(key);
Byte[] message_bytes = ascii.GetBytes(message);
System.Security.Cryptography.HMACSHA256 hmacSHA256 = new System.Security.Cryptography.HMACSHA256(key_bytes);
Byte[] hash = hmacSHA256.ComputeHash(message_bytes);
String data = this.ByteToString(hash);
// only compare first 32 chars of the hash
Assert.AreEqual(expected, data.Substring(0, 32));
//Assert.AreEqual failed.
//Expected:<FF365893D899291C3BF505FB3175E880>.
//Actual:<997BBD8C79F0D98FCA6470723CDB65D3>.
}
private Byte[] KeyData(String key)
{
if (key.Length % 2 == 1)
throw new Exception("The binary key cannot have an odd number of digits");
byte[] arr = new byte[key.Length >> 1];
Int32 pos = 0;
for (int i = 0; i < key.Length; i += 2)
{
Int32 b1 = key[i] - (key[i] < 58 ? 48 : 55);
Int32 b2 = key[i + 1] - (key[i + 1] < 58 ? 48 : 55);
arr[pos++] = (byte)((b1 << 4) + b2);
}
return arr;
}
private String ByteToString(Byte[] buff)
{
Char[] retval = new char[buff.Length * 2];
for (int i = 0; i < buff.Length; i++)
{
String t = buff[i].ToString("X2");
retval[i * 2] = t[0];
retval[i * 2 + 1] = t[1];
}
return new String(retval);
}
}
О, я понял, что вы делаете, напишу ответ.
Encoding.ASCII не является шестнадцатеричным кодировщиком
Если вы хотите использовать HMAC-SHA256, не делайте этого new HMACSHA1().
@Mormegil Мормегил Я предполагаю, что это опечатка, исходный пост сделал это правильно.
Да, вы правы, что я запутался. Я проверил и забыл изменить обратно.





Вы конвертируете свой ключ непосредственно в байты, а не интерпретируете его как шестнадцатеричную строку. Использование функции преобразования строки в байты из здесь:
public static byte[] StringToByteArray(string hex)
{
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
Измените свой код на это:
Byte[] key_bytes = StringToByteArray(key);
Спасибо, что указали на это @DavidG. Однако результат тестового примера все еще неверен. :( Assert.AreEqual не удалось. Ожидаемый: <FF365893D899291C3BF505FB3175E880>. Фактический: <997BBD8C79F0D98FCA6470723CDB65D3>.
Вы переключились на использование неправильной функции, измените код обратно на использование HMACSHA256.
Спасибо DavidG! Где-то в конце концов мое разочарование взяло верх, и я просто сошел с ума от своего кода. При изменении его обратно на HMACSHA256 он работает. :) Спасибо за помощь в поиске моей досадной ошибки!
@DavidG: это указано продавцом как правильный ответ.