Не могу найти ошибку в реализации SHA1 на C#

195
18 апреля 2022, 00:20

Хэш не совпадает. Ошибка скорее всего в основном цикле, потому что массив numarr определяется верно. Для примера, подавая на вход string s = "A Test";, функция возвращает 2ec6add41a9dc5d7ca6634daeedb8a87c57f5cf4, хотя должна возвращать 8f0c0855915633e4a7de19468b3874c8901df043.

private string SHA_1(string input)
        {
            byte[] input_b = Encoding.ASCII.GetBytes(input);
            string[] input_s = new string[input.Length];
            for (int i = 0; i < input.Length; i++)
            {
                input_s[i] = Convert.ToString(input_b[i], 2);   // перевод двоичных кодов в строки
                while (input_s[i].Length < 8)
                    input_s[i] = '0' + input_s[i];  // дополнение до 8 незначащими нулями
            }
            string num = "";
            for (int i = 0; i < input.Length; i++)
                num += input_s[i];
            num += '1';     // добавление 1
            while (num.Length % 512 != 448)
                num += '0';     // добавление нулей
            string len = Convert.ToString(input.Length * 8, 2);     // длина сообщение в двоичном
            while (len.Length < 64)
                len = "0" + len;    // добавление до 64 незначащими нулями
            num += len;
            int l = num.Length / 512;
            int pos = 0;
            uint[,] numarr = new uint[l, 80];
            for (int i = 0; i < l; i++)
                for (int j = 0; j < 16; j++)
                {
                    numarr[i, j] = Convert.ToUInt32(num.Substring(pos, 32), 2);
                    pos += 32;
                }   // разбиение на блоки по 512 и подблоки по 32
            for (int i = 0; i < l; i++)
                for (int j = 16; j < 80; j++)
                {
                    numarr[i, j]= numarr[i, j - 3] ^ numarr[i, j - 8] ^ numarr[i, j - 14] ^ numarr[i, j - 16];
                    numarr[i, j] = (numarr[i, j] << 1) | ((numarr[i, j] >> 31) & UInt32.MaxValue); // дополнение до 80 чисел
                }
            uint h0 = 0x67452301, h1 = 0xEFCDAB89, h2 = 0x98BADCFE, h3 = 0x10325476, h4 = 0xC3D2E1F0;
            uint a = h0, b = h1, c = h2, d = h3, e = h4, f, k, temp;
            for (int i = 0; i < l; i++)  // основной цикл
            {
                for (int j = 0; j < 79; j++)
                {
                    if (i < 20)
                    {
                        f = (b & c) | (~b & d);
                        k = 0x5A827999;
                    }
                    else
                    if (i < 40)
                    {
                        f = b ^ c ^ d;
                        k = 0x6ED9EBA1;
                    }
                    else
                    if (i < 60)
                    {
                        f = (b & c) | (b & d) | (c & d);
                        k = 0x8F1BBCDC;
                    }
                    else
                    {
                        f = b ^ c ^ d;
                        k = 0xCA62C1D6;
                    }
                    temp = f + e + k + ((a << 5) | (a >> 27 & UInt32.MaxValue)) + numarr[i, j];
                    e = d;
                    d = c;
                    c = (b << 30) | (b >> 2 & UInt32.MaxValue);
                    b = a;
                    a = temp;
                }
                h0 += a;
                h1 += b;
                h2 += c;
                h3 += d;
                h4 += e;
            }
        string res = Convert.ToString(h0, 16) + Convert.ToString(h1, 16) + Convert.ToString(h2, 16) + Convert.ToString(h3, 16) + Convert.ToString(h4, 16);
        return res;
        }
Answer 1

Ошибка была в основном цикле: во всех условиях стоял i вместо j, а также условием работы for должно быть j < 80, а не j < 79. Рабочий метод:

private string SHA_1(string input)
        {
            byte[] input_b = Encoding.ASCII.GetBytes(input);
            string[] input_s = new string[input.Length];
            for (int i = 0; i < input.Length; i++)
            {
                input_s[i] = Convert.ToString(input_b[i], 2);   // перевод двоичных кодов в строки
                while (input_s[i].Length < 8)
                    input_s[i] = '0' + input_s[i];  // дополнение до 8 незначащими нулями
            }
            string num = "";
            for (int i = 0; i < input.Length; i++)
                num += input_s[i];
            num += '1';     // добавление 1
            while (num.Length % 512 != 448)
                num += '0';     // добавление нулей
            string len = Convert.ToString(input.Length * 8, 2);     // длина сообщение в двоичном
            while (len.Length < 64)
                len = "0" + len;    // добавление до 64 незначащими нулями
            num += len;
            int l = num.Length / 512;
            int pos = 0;
            uint[,] numarr = new uint[l, 80];
            for (int i = 0; i < l; i++)
                for (int j = 0; j < 16; j++)
                {
                    numarr[i, j] = Convert.ToUInt32(num.Substring(pos, 32), 2);
                    pos += 32;
                }   // разбиение на блоки по 512 и подблоки по 32
            for (int i = 0; i < l; i++)
                for (int j = 16; j < 80; j++)
                {
                    numarr[i, j] = numarr[i, j - 3] ^ numarr[i, j - 8] ^ numarr[i, j - 14] ^ numarr[i, j - 16];
                    numarr[i, j] = (numarr[i, j] << 1) | ((numarr[i, j] >> 31) & UInt32.MaxValue); // дополнение до 80 чисел
                }
            uint h0 = 0x67452301, h1 = 0xEFCDAB89, h2 = 0x98BADCFE, h3 = 0x10325476, h4 = 0xC3D2E1F0;
            uint a = h0, b = h1, c = h2, d = h3, e = h4, f, k, temp;
            for (int i = 0; i < l; i++)  // основной цикл
            {
                for (int j = 0; j < 80; j++)
                {
                    if (j < 20)
                    {
                        f = (b & c) | (~b & d);
                        k = 0x5A827999;
                    }
                    else
                    if (j < 40)
                    {
                        f = b ^ c ^ d;
                        k = 0x6ED9EBA1;
                    }
                    else
                    if (j < 60)
                    {
                        f = (b & c) | (b & d) | (c & d);
                        k = 0x8F1BBCDC;
                    }
                    else
                    {
                        f = b ^ c ^ d;
                        k = 0xCA62C1D6;
                    }
                    temp = f + e + k + ((a << 5) | ((a >> 27) & UInt32.MaxValue)) + numarr[i, j];
                    e = d;
                    d = c;
                    c = (b << 30) | ((b >> 2) & UInt32.MaxValue);
                    b = a;
                    a = temp;
                }
                h0 += a;
                h1 += b;
                h2 += c;
                h3 += d;
                h4 += e;
            }
            string res = Convert.ToString(h0, 16) + Convert.ToString(h1, 16) + Convert.ToString(h2, 16) + Convert.ToString(h3, 16) + Convert.ToString(h4, 16);
            textBox1.Text = res;
            return res;
        }
READ ALSO
Плавное изменение размера объекта unity

Плавное изменение размера объекта unity

помогите сделать плавное увеличение и уменьшение размеров кнопки программноЯ написал код, но он почему-то изменяется слишком быстро

139
Quartz.NET не работает вместе с Entity framework

Quartz.NET не работает вместе с Entity framework

Если в классе OrderTime создам конструктор c базой, то метод Execute перестает работатьКто знает как решить эту проблему? Может можно реализовать...

142
Чтение и замена в файле XML на C# [дубликат]

Чтение и замена в файле XML на C# [дубликат]

Понимаю вопрос от слова совсем нетПомогите

106
c# Телеграмм Бот

c# Телеграмм Бот

Доброе время суток, Хотел создать Бота для телеграмма, но подключение к боту не происходитВот сообственно код

122