Как вычислить HMAC SHA256 в c # - PullRequest
2 голосов
/ 28 мая 2019

Редактировать: я исправил кодировку 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);
        }
    }

1 Ответ

2 голосов
/ 28 мая 2019

Вы конвертируете свой ключ напрямую в байты, а не интерпретируете его как шестнадцатеричную строку.Используя функцию строки в байты из здесь :

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);
...