Хеш-функция Стрибог или в городе новый шериф

  • Tutorial
В 2012 году вся общественность, более или менее причастная к информационной безопасности, пристально следила за выборами нового стандарта хеширования данных SHA-3. На хабре достаточно широко освещалось это важное событие: публиковались результаты каждого раунда конкурса (раз, два, три), приводилось описание нового стандарта, и даже объяснялось почему новый стандарт так крут.
Однако, за всем этим ажиотажем совсем незамеченным осталось другое, не менее значимое событие: 1 января 2013 года в РФ также сменился стандарт хеш-функции.
Итак, встречайте: полное описание нового стандарта и его реализация на C#. Как говорится, лучше поздно, чем никогда.

В качестве нового стандарта, который получил номер 34.11-2012, была принята хеш-функция под названием Стрибог. Стрибог — это семейство хеш-функций, включающее в себя всего две функции. Функцию с длиной выходного значения в 256 бит и функцию с длиной выходного значения в 512 бит. Обе эти функции имеют одинаковую структуру и отличаются друг от друга только начальным внутренним состоянием. Входными данными для обеих функций является блок данных длиной 512 бит. В случае, если длина сообщения больше 512 бит, то происходит разбиение сообщения на блоки. В случае же, если длина меньше 512 бит, то производится дополнение сообщения.

Прежде чем приступать к описанию алгоритма, расскажем о преобразованиях, которые используются при вычислении хеш-функции.

Преобразования


  1. X-преобразование. На вход функции X подаются две последовательности длиной 512 бит каждая, выходом функции является XOR этих последовательностей.


  2. S-преобразование. Функция S является обычной функцией подстановки. Каждый байт из 512-битной входной последовательности заменяется соответствующим байтом из таблицы подстановок π

    Таблица π является константой и может быть записана в виде массива:
    Значение подстановки pi;

    byte[] Pi={
    0xFC, 0xEE, 0xDD, 0x11, 0xCF, 0x6E, 0x31, 0x16, 0xFB, 0xC4, 0xFA, 0xDA, 0x23, 0xC5, 0x04, 0x4D,
    0xE9, 0x77, 0xF0, 0xDB, 0x93, 0x2E, 0x99, 0xBA, 0x17, 0x36, 0xF1, 0xBB, 0x14, 0xCD, 0x5F, 0xC1,
    0xF9, 0x18, 0x65, 0x5A, 0xE2, 0x5C, 0xEF, 0x21, 0x81, 0x1C, 0x3C, 0x42, 0x8B, 0x01, 0x8E, 0x4F,
    0x05, 0x84, 0x02, 0xAE, 0xE3, 0x6A, 0x8F, 0xA0, 0x06, 0x0B, 0xED, 0x98, 0x7F, 0xD4, 0xD3, 0x1F,
    0xEB, 0x34, 0x2C, 0x51, 0xEA, 0xC8, 0x48, 0xAB, 0xF2, 0x2A, 0x68, 0xA2, 0xFD, 0x3A, 0xCE, 0xCC,
    0xB5, 0x70, 0x0E, 0x56, 0x08, 0x0C, 0x76, 0x12, 0xBF, 0x72, 0x13, 0x47, 0x9C, 0xB7, 0x5D, 0x87,
    0x15, 0xA1, 0x96, 0x29, 0x10, 0x7B, 0x9A, 0xC7, 0xF3, 0x91, 0x78, 0x6F, 0x9D, 0x9E, 0xB2, 0xB1,
    0x32, 0x75, 0x19, 0x3D, 0xFF, 0x35, 0x8A, 0x7E, 0x6D, 0x54, 0xC6, 0x80, 0xC3, 0xBD, 0x0D, 0x57,
    0xDF, 0xF5, 0x24, 0xA9, 0x3E, 0xA8, 0x43, 0xC9, 0xD7, 0x79, 0xD6, 0xF6, 0x7C, 0x22, 0xB9, 0x03,
    0xE0, 0x0F, 0xEC, 0xDE, 0x7A, 0x94, 0xB0, 0xBC, 0xDC, 0xE8, 0x28, 0x50, 0x4E, 0x33, 0x0A, 0x4A,
    0xA7, 0x97, 0x60, 0x73, 0x1E, 0x00, 0x62, 0x44, 0x1A, 0xB8, 0x38, 0x82, 0x64, 0x9F, 0x26, 0x41,
    0xAD, 0x45, 0x46, 0x92, 0x27, 0x5E, 0x55, 0x2F, 0x8C, 0xA3, 0xA5, 0x7D, 0x69, 0xD5, 0x95, 0x3B,
    0x07, 0x58, 0xB3, 0x40, 0x86, 0xAC, 0x1D, 0xF7, 0x30, 0x37, 0x6B, 0xE4, 0x88, 0xD9, 0xE7, 0x89,
    0xE1, 0x1B, 0x83, 0x49, 0x4C, 0x3F, 0xF8, 0xFE, 0x8D, 0x53, 0xAA, 0x90, 0xCA, 0xD8, 0x85, 0x61,
    0x20, 0x71, 0x67, 0xA4, 0x2D, 0x2B, 0x09, 0x5B, 0xCB, 0x9B, 0x25, 0xD0, 0xBE, 0xE5, 0x6C, 0x52,
    0x59, 0xA6, 0x74, 0xD2, 0xE6, 0xF4, 0xB4, 0xC0, 0xD1, 0x66, 0xAF, 0xC2, 0x39, 0x4B, 0x63, 0xB6
    };


  3. P-преобразование. Функция перестановки. Для каждой пары байт из входной последовательности происходит замена одного байта другим.

    Таблица перестановок τ также является константой:
    Значение перестановки tau
    byte[] Tau={
    0, 8, 16, 24, 32, 40, 48, 56,
    1, 9, 17, 25, 33, 41, 49, 57,
    2, 10, 18, 26, 34, 42, 50, 58,
    3, 11, 19, 27, 35, 43, 51, 59,
    4, 12, 20, 28, 36, 44, 52, 60,
    5, 13, 21, 29, 37, 45, 53, 61,
    6, 14, 22, 30, 38, 46, 54, 62,
    7, 15, 23, 31, 39, 47, 55, 63
    };


  4. L-преобразование. Представляет собой умножение 64-битного входного вектора на бинарную матрицу A размерами 64x64.

    Матрицу A можно представить как массив 64-битных слов:
    Значение матрицы A
    ulong[] A = {
    0x8e20faa72ba0b470, 0x47107ddd9b505a38, 0xad08b0e0c3282d1c, 0xd8045870ef14980e,
    0x6c022c38f90a4c07, 0x3601161cf205268d, 0x1b8e0b0e798c13c8, 0x83478b07b2468764,
    0xa011d380818e8f40, 0x5086e740ce47c920, 0x2843fd2067adea10, 0x14aff010bdd87508,
    0x0ad97808d06cb404, 0x05e23c0468365a02, 0x8c711e02341b2d01, 0x46b60f011a83988e,
    0x90dab52a387ae76f, 0x486dd4151c3dfdb9, 0x24b86a840e90f0d2, 0x125c354207487869,
    0x092e94218d243cba, 0x8a174a9ec8121e5d, 0x4585254f64090fa0, 0xaccc9ca9328a8950,
    0x9d4df05d5f661451, 0xc0a878a0a1330aa6, 0x60543c50de970553, 0x302a1e286fc58ca7,
    0x18150f14b9ec46dd, 0x0c84890ad27623e0, 0x0642ca05693b9f70, 0x0321658cba93c138,
    0x86275df09ce8aaa8, 0x439da0784e745554, 0xafc0503c273aa42a, 0xd960281e9d1d5215,
    0xe230140fc0802984, 0x71180a8960409a42, 0xb60c05ca30204d21, 0x5b068c651810a89e,
    0x456c34887a3805b9, 0xac361a443d1c8cd2, 0x561b0d22900e4669, 0x2b838811480723ba,
    0x9bcf4486248d9f5d, 0xc3e9224312c8c1a0, 0xeffa11af0964ee50, 0xf97d86d98a327728,
    0xe4fa2054a80b329c, 0x727d102a548b194e, 0x39b008152acb8227, 0x9258048415eb419d,
    0x492c024284fbaec0, 0xaa16012142f35760, 0x550b8e9e21f7a530, 0xa48b474f9ef5dc18,
    0x70a6a56e2440598e, 0x3853dc371220a247, 0x1ca76e95091051ad, 0x0edd37c48a08a6d8,
    0x07e095624504536c, 0x8d70c431ac02a736, 0xc83862965601dd1b, 0x641c314b2b8ee083
    };

Функция сжатия


Основным элементом любой хеш-функции является функция сжатия. Опишем используемую в новом стандарте функцию сжатия gn в виде алгоритма.
Пусть h, N и m — 512-битные последовательности. Для вычисления функции g(N, m, h) необходимо проделать следующие шаги:
  1. Вычислить значение K = h ⊕ N;
  2. Присвоить значение K = S(K);
  3. Присвоить значение K = P(K);
  4. Присвоить значение K = L(K);
  5. Вычислить t = E(K, m);
  6. Присвоить значение t = h ⊕ t;
  7. Вычислить значение G = t ⊕ m;
  8. Вернуть G в качестве результата вычисления функции g(N, m, h).


Вы наверное заметили, что в описании функции g(N, m, h) используется незнакомая функция E(K, m), которая выполняет нижеприведенные действия:
  1. Вычислить значение state = K ⊕ m;
  2. Для i=0 по 11 выполнить:
    • Присвоить значение state = S(state);
    • Присвоить значение state = P(state);
    • Присвоить значение state = L(state);
    • Вычислить K=KeySchedule(K, i);
    • Присвоить значение state = state ⊕ K;
  3. Вернуть state в качестве результата.


И опять незнакомое понятие. На этот раз это функция KeySchedule(K, i), отвечающая за формирование временного ключа K на каждом раунде функции E(K, m). Восполним и этот пробел в описании алгоритма. Функция KeySchedule(K, i) производит следующие вычисления:
  1. Присвоить значение K = K ⊕ C[i];
  2. Присвоить значение K = S(K);
  3. Присвоить значение K = P(K);
  4. Присвоить значение K = L(K);
  5. Вернуть K в качестве результата функции.

Здесь С — это набор 512-битных значений. Значение С является постоянным.
Значение С
byte[][] C = {
new byte[64]{
0xb1,0x08,0x5b,0xda,0x1e,0xca,0xda,0xe9,0xeb,0xcb,0x2f,0x81,0xc0,0x65,0x7c,0x1f,
0x2f,0x6a,0x76,0x43,0x2e,0x45,0xd0,0x16,0x71,0x4e,0xb8,0x8d,0x75,0x85,0xc4,0xfc,
0x4b,0x7c,0xe0,0x91,0x92,0x67,0x69,0x01,0xa2,0x42,0x2a,0x08,0xa4,0x60,0xd3,0x15,
0x05,0x76,0x74,0x36,0xcc,0x74,0x4d,0x23,0xdd,0x80,0x65,0x59,0xf2,0xa6,0x45,0x07
},
new byte[64]{
0x6f,0xa3,0xb5,0x8a,0xa9,0x9d,0x2f,0x1a,0x4f,0xe3,0x9d,0x46,0x0f,0x70,0xb5,0xd7,
0xf3,0xfe,0xea,0x72,0x0a,0x23,0x2b,0x98,0x61,0xd5,0x5e,0x0f,0x16,0xb5,0x01,0x31,
0x9a,0xb5,0x17,0x6b,0x12,0xd6,0x99,0x58,0x5c,0xb5,0x61,0xc2,0xdb,0x0a,0xa7,0xca,
0x55,0xdd,0xa2,0x1b,0xd7,0xcb,0xcd,0x56,0xe6,0x79,0x04,0x70,0x21,0xb1,0x9b,0xb7
},
new byte[64]{
0xf5,0x74,0xdc,0xac,0x2b,0xce,0x2f,0xc7,0x0a,0x39,0xfc,0x28,0x6a,0x3d,0x84,0x35,
0x06,0xf1,0x5e,0x5f,0x52,0x9c,0x1f,0x8b,0xf2,0xea,0x75,0x14,0xb1,0x29,0x7b,0x7b,
0xd3,0xe2,0x0f,0xe4,0x90,0x35,0x9e,0xb1,0xc1,0xc9,0x3a,0x37,0x60,0x62,0xdb,0x09,
0xc2,0xb6,0xf4,0x43,0x86,0x7a,0xdb,0x31,0x99,0x1e,0x96,0xf5,0x0a,0xba,0x0a,0xb2
},
new byte[64]{
0xef,0x1f,0xdf,0xb3,0xe8,0x15,0x66,0xd2,0xf9,0x48,0xe1,0xa0,0x5d,0x71,0xe4,0xdd,
0x48,0x8e,0x85,0x7e,0x33,0x5c,0x3c,0x7d,0x9d,0x72,0x1c,0xad,0x68,0x5e,0x35,0x3f,
0xa9,0xd7,0x2c,0x82,0xed,0x03,0xd6,0x75,0xd8,0xb7,0x13,0x33,0x93,0x52,0x03,0xbe,
0x34,0x53,0xea,0xa1,0x93,0xe8,0x37,0xf1,0x22,0x0c,0xbe,0xbc,0x84,0xe3,0xd1,0x2e
},
new byte[64]{
0x4b,0xea,0x6b,0xac,0xad,0x47,0x47,0x99,0x9a,0x3f,0x41,0x0c,0x6c,0xa9,0x23,0x63,
0x7f,0x15,0x1c,0x1f,0x16,0x86,0x10,0x4a,0x35,0x9e,0x35,0xd7,0x80,0x0f,0xff,0xbd,
0xbf,0xcd,0x17,0x47,0x25,0x3a,0xf5,0xa3,0xdf,0xff,0x00,0xb7,0x23,0x27,0x1a,0x16,
0x7a,0x56,0xa2,0x7e,0xa9,0xea,0x63,0xf5,0x60,0x17,0x58,0xfd,0x7c,0x6c,0xfe,0x57
},
new byte[64]{
0xae,0x4f,0xae,0xae,0x1d,0x3a,0xd3,0xd9,0x6f,0xa4,0xc3,0x3b,0x7a,0x30,0x39,0xc0,
0x2d,0x66,0xc4,0xf9,0x51,0x42,0xa4,0x6c,0x18,0x7f,0x9a,0xb4,0x9a,0xf0,0x8e,0xc6,
0xcf,0xfa,0xa6,0xb7,0x1c,0x9a,0xb7,0xb4,0x0a,0xf2,0x1f,0x66,0xc2,0xbe,0xc6,0xb6,
0xbf,0x71,0xc5,0x72,0x36,0x90,0x4f,0x35,0xfa,0x68,0x40,0x7a,0x46,0x64,0x7d,0x6e
},
new byte[64]{
0xf4,0xc7,0x0e,0x16,0xee,0xaa,0xc5,0xec,0x51,0xac,0x86,0xfe,0xbf,0x24,0x09,0x54,
0x39,0x9e,0xc6,0xc7,0xe6,0xbf,0x87,0xc9,0xd3,0x47,0x3e,0x33,0x19,0x7a,0x93,0xc9,
0x09,0x92,0xab,0xc5,0x2d,0x82,0x2c,0x37,0x06,0x47,0x69,0x83,0x28,0x4a,0x05,0x04,
0x35,0x17,0x45,0x4c,0xa2,0x3c,0x4a,0xf3,0x88,0x86,0x56,0x4d,0x3a,0x14,0xd4,0x93
},
new byte[64]{
0x9b,0x1f,0x5b,0x42,0x4d,0x93,0xc9,0xa7,0x03,0xe7,0xaa,0x02,0x0c,0x6e,0x41,0x41,
0x4e,0xb7,0xf8,0x71,0x9c,0x36,0xde,0x1e,0x89,0xb4,0x44,0x3b,0x4d,0xdb,0xc4,0x9a,
0xf4,0x89,0x2b,0xcb,0x92,0x9b,0x06,0x90,0x69,0xd1,0x8d,0x2b,0xd1,0xa5,0xc4,0x2f,
0x36,0xac,0xc2,0x35,0x59,0x51,0xa8,0xd9,0xa4,0x7f,0x0d,0xd4,0xbf,0x02,0xe7,0x1e
},
new byte[64]{
0x37,0x8f,0x5a,0x54,0x16,0x31,0x22,0x9b,0x94,0x4c,0x9a,0xd8,0xec,0x16,0x5f,0xde,
0x3a,0x7d,0x3a,0x1b,0x25,0x89,0x42,0x24,0x3c,0xd9,0x55,0xb7,0xe0,0x0d,0x09,0x84,
0x80,0x0a,0x44,0x0b,0xdb,0xb2,0xce,0xb1,0x7b,0x2b,0x8a,0x9a,0xa6,0x07,0x9c,0x54,
0x0e,0x38,0xdc,0x92,0xcb,0x1f,0x2a,0x60,0x72,0x61,0x44,0x51,0x83,0x23,0x5a,0xdb
},
new byte[64]{
0xab,0xbe,0xde,0xa6,0x80,0x05,0x6f,0x52,0x38,0x2a,0xe5,0x48,0xb2,0xe4,0xf3,0xf3,
0x89,0x41,0xe7,0x1c,0xff,0x8a,0x78,0xdb,0x1f,0xff,0xe1,0x8a,0x1b,0x33,0x61,0x03,
0x9f,0xe7,0x67,0x02,0xaf,0x69,0x33,0x4b,0x7a,0x1e,0x6c,0x30,0x3b,0x76,0x52,0xf4,
0x36,0x98,0xfa,0xd1,0x15,0x3b,0xb6,0xc3,0x74,0xb4,0xc7,0xfb,0x98,0x45,0x9c,0xed
},
new byte[64]{
0x7b,0xcd,0x9e,0xd0,0xef,0xc8,0x89,0xfb,0x30,0x02,0xc6,0xcd,0x63,0x5a,0xfe,0x94,
0xd8,0xfa,0x6b,0xbb,0xeb,0xab,0x07,0x61,0x20,0x01,0x80,0x21,0x14,0x84,0x66,0x79,
0x8a,0x1d,0x71,0xef,0xea,0x48,0xb9,0xca,0xef,0xba,0xcd,0x1d,0x7d,0x47,0x6e,0x98,
0xde,0xa2,0x59,0x4a,0xc0,0x6f,0xd8,0x5d,0x6b,0xca,0xa4,0xcd,0x81,0xf3,0x2d,0x1b
},
new byte[64]{
0x37,0x8e,0xe7,0x67,0xf1,0x16,0x31,0xba,0xd2,0x13,0x80,0xb0,0x04,0x49,0xb1,0x7a,
0xcd,0xa4,0x3c,0x32,0xbc,0xdf,0x1d,0x77,0xf8,0x20,0x12,0xd4,0x30,0x21,0x9f,0x9b,
0x5d,0x80,0xef,0x9d,0x18,0x91,0xcc,0x86,0xe7,0x1d,0xa4,0xaa,0x88,0xe1,0x28,0x52,
0xfa,0xf4,0x17,0xd5,0xd9,0xb2,0x1b,0x99,0x48,0xbc,0x92,0x4a,0xf1,0x1b,0xd7,0x20
}
};


Вычисление хеш-функции


Теперь опишем процедуру формирования хеш-значения. Для любого входного сообщения M:
  1. Присвоить начальные значения внутренних переменных:
    • Для хеш-функции с длиной выхода 512 бит: h=iv=0x0064. Для хеш-функции с длиной выхода 256 бит: h=iv=0x0164.
    • N = 0512
    • Σ = 0512
  2. Проверить следующее условие: длина сообщения M<512. Если условие выполняется перейти к пункту 3. В противном случае выполнить последовательность вычислений:
    • m — последние 512 бит сообщения M
    • h = g(N, m, h)
    • N = (N + 512) mod 2512
    • Σ = (Σ + m) mod 2512
    • Обрезать M, убрав последние 512 бит
    • Перейти к шагу 2
  3. Произвести дополнение сообщения M до длины в 512 бит по следующему правилу:
    m = 0511-|M|||1||M, где |M| — длина сообщения M в битах.
  4. Вычислить h = g(N, m, h)
  5. Вычислить N = (N + |M|) mod 2512
  6. Вычислить Σ = (Σ + m) mod 2512
  7. Вычислить h = g(0, h, N)
  8. Вычислить h = g(0, h, Σ)
  9. Для хеш-функции с длиной выхода в 512 бит возвращаем h в качестве результата. Для функции с длиной выхода 256 бит возвращаем MSB256(h).


Обещанную реализацию алгоритма на C# вы смотрите под спойлером:
C# класс GOST
class GOST
    {
        // Matrix A for MixColumns (L) function
        private ulong[] A = {
        0x8e20faa72ba0b470, 0x47107ddd9b505a38, 0xad08b0e0c3282d1c, 0xd8045870ef14980e,
        0x6c022c38f90a4c07, 0x3601161cf205268d, 0x1b8e0b0e798c13c8, 0x83478b07b2468764,
        0xa011d380818e8f40, 0x5086e740ce47c920, 0x2843fd2067adea10, 0x14aff010bdd87508,
        0x0ad97808d06cb404, 0x05e23c0468365a02, 0x8c711e02341b2d01, 0x46b60f011a83988e,
        0x90dab52a387ae76f, 0x486dd4151c3dfdb9, 0x24b86a840e90f0d2, 0x125c354207487869,
        0x092e94218d243cba, 0x8a174a9ec8121e5d, 0x4585254f64090fa0, 0xaccc9ca9328a8950,
        0x9d4df05d5f661451, 0xc0a878a0a1330aa6, 0x60543c50de970553, 0x302a1e286fc58ca7,
        0x18150f14b9ec46dd, 0x0c84890ad27623e0, 0x0642ca05693b9f70, 0x0321658cba93c138,
        0x86275df09ce8aaa8, 0x439da0784e745554, 0xafc0503c273aa42a, 0xd960281e9d1d5215,
        0xe230140fc0802984, 0x71180a8960409a42, 0xb60c05ca30204d21, 0x5b068c651810a89e,
        0x456c34887a3805b9, 0xac361a443d1c8cd2, 0x561b0d22900e4669, 0x2b838811480723ba,
        0x9bcf4486248d9f5d, 0xc3e9224312c8c1a0, 0xeffa11af0964ee50, 0xf97d86d98a327728,
        0xe4fa2054a80b329c, 0x727d102a548b194e, 0x39b008152acb8227, 0x9258048415eb419d,
        0x492c024284fbaec0, 0xaa16012142f35760, 0x550b8e9e21f7a530, 0xa48b474f9ef5dc18,
        0x70a6a56e2440598e, 0x3853dc371220a247, 0x1ca76e95091051ad, 0x0edd37c48a08a6d8,
        0x07e095624504536c, 0x8d70c431ac02a736, 0xc83862965601dd1b, 0x641c314b2b8ee083
        };

        // Substitution for SubBytes function
        private byte[] Sbox={
        0xFC, 0xEE, 0xDD, 0x11, 0xCF, 0x6E, 0x31, 0x16, 0xFB, 0xC4, 0xFA, 0xDA, 0x23, 0xC5, 0x04, 0x4D,
        0xE9, 0x77, 0xF0, 0xDB, 0x93, 0x2E, 0x99, 0xBA, 0x17, 0x36, 0xF1, 0xBB, 0x14, 0xCD, 0x5F, 0xC1,
        0xF9, 0x18, 0x65, 0x5A, 0xE2, 0x5C, 0xEF, 0x21, 0x81, 0x1C, 0x3C, 0x42, 0x8B, 0x01, 0x8E, 0x4F,
        0x05, 0x84, 0x02, 0xAE, 0xE3, 0x6A, 0x8F, 0xA0, 0x06, 0x0B, 0xED, 0x98, 0x7F, 0xD4, 0xD3, 0x1F,
        0xEB, 0x34, 0x2C, 0x51, 0xEA, 0xC8, 0x48, 0xAB, 0xF2, 0x2A, 0x68, 0xA2, 0xFD, 0x3A, 0xCE, 0xCC,
        0xB5, 0x70, 0x0E, 0x56, 0x08, 0x0C, 0x76, 0x12, 0xBF, 0x72, 0x13, 0x47, 0x9C, 0xB7, 0x5D, 0x87,
        0x15, 0xA1, 0x96, 0x29, 0x10, 0x7B, 0x9A, 0xC7, 0xF3, 0x91, 0x78, 0x6F, 0x9D, 0x9E, 0xB2, 0xB1,
        0x32, 0x75, 0x19, 0x3D, 0xFF, 0x35, 0x8A, 0x7E, 0x6D, 0x54, 0xC6, 0x80, 0xC3, 0xBD, 0x0D, 0x57,
        0xDF, 0xF5, 0x24, 0xA9, 0x3E, 0xA8, 0x43, 0xC9, 0xD7, 0x79, 0xD6, 0xF6, 0x7C, 0x22, 0xB9, 0x03,
        0xE0, 0x0F, 0xEC, 0xDE, 0x7A, 0x94, 0xB0, 0xBC, 0xDC, 0xE8, 0x28, 0x50, 0x4E, 0x33, 0x0A, 0x4A,
        0xA7, 0x97, 0x60, 0x73, 0x1E, 0x00, 0x62, 0x44, 0x1A, 0xB8, 0x38, 0x82, 0x64, 0x9F, 0x26, 0x41,
        0xAD, 0x45, 0x46, 0x92, 0x27, 0x5E, 0x55, 0x2F, 0x8C, 0xA3, 0xA5, 0x7D, 0x69, 0xD5, 0x95, 0x3B,
        0x07, 0x58, 0xB3, 0x40, 0x86, 0xAC, 0x1D, 0xF7, 0x30, 0x37, 0x6B, 0xE4, 0x88, 0xD9, 0xE7, 0x89,
        0xE1, 0x1B, 0x83, 0x49, 0x4C, 0x3F, 0xF8, 0xFE, 0x8D, 0x53, 0xAA, 0x90, 0xCA, 0xD8, 0x85, 0x61,
        0x20, 0x71, 0x67, 0xA4, 0x2D, 0x2B, 0x09, 0x5B, 0xCB, 0x9B, 0x25, 0xD0, 0xBE, 0xE5, 0x6C, 0x52,
        0x59, 0xA6, 0x74, 0xD2, 0xE6, 0xF4, 0xB4, 0xC0, 0xD1, 0x66, 0xAF, 0xC2, 0x39, 0x4B, 0x63, 0xB6
        };

        // Substitution for Transposition (P) function
        private byte[] Tau={
        0, 8, 16, 24, 32, 40, 48, 56,
        1, 9, 17, 25, 33, 41, 49, 57,
        2, 10, 18, 26, 34, 42, 50, 58,
        3, 11, 19, 27, 35, 43, 51, 59,
        4, 12, 20, 28, 36, 44, 52, 60,
        5, 13, 21, 29, 37, 45, 53, 61,
        6, 14, 22, 30, 38, 46, 54, 62,
        7, 15, 23, 31, 39, 47, 55, 63
        };

        // Constant values for KeySchedule function
        private byte[][] C = {
        new byte[64]{
        0xb1,0x08,0x5b,0xda,0x1e,0xca,0xda,0xe9,0xeb,0xcb,0x2f,0x81,0xc0,0x65,0x7c,0x1f,
        0x2f,0x6a,0x76,0x43,0x2e,0x45,0xd0,0x16,0x71,0x4e,0xb8,0x8d,0x75,0x85,0xc4,0xfc,
        0x4b,0x7c,0xe0,0x91,0x92,0x67,0x69,0x01,0xa2,0x42,0x2a,0x08,0xa4,0x60,0xd3,0x15,
        0x05,0x76,0x74,0x36,0xcc,0x74,0x4d,0x23,0xdd,0x80,0x65,0x59,0xf2,0xa6,0x45,0x07
        },
        new byte[64]{
        0x6f,0xa3,0xb5,0x8a,0xa9,0x9d,0x2f,0x1a,0x4f,0xe3,0x9d,0x46,0x0f,0x70,0xb5,0xd7,
        0xf3,0xfe,0xea,0x72,0x0a,0x23,0x2b,0x98,0x61,0xd5,0x5e,0x0f,0x16,0xb5,0x01,0x31,
        0x9a,0xb5,0x17,0x6b,0x12,0xd6,0x99,0x58,0x5c,0xb5,0x61,0xc2,0xdb,0x0a,0xa7,0xca,
        0x55,0xdd,0xa2,0x1b,0xd7,0xcb,0xcd,0x56,0xe6,0x79,0x04,0x70,0x21,0xb1,0x9b,0xb7
        },
        new byte[64]{
        0xf5,0x74,0xdc,0xac,0x2b,0xce,0x2f,0xc7,0x0a,0x39,0xfc,0x28,0x6a,0x3d,0x84,0x35,
        0x06,0xf1,0x5e,0x5f,0x52,0x9c,0x1f,0x8b,0xf2,0xea,0x75,0x14,0xb1,0x29,0x7b,0x7b,
        0xd3,0xe2,0x0f,0xe4,0x90,0x35,0x9e,0xb1,0xc1,0xc9,0x3a,0x37,0x60,0x62,0xdb,0x09,
        0xc2,0xb6,0xf4,0x43,0x86,0x7a,0xdb,0x31,0x99,0x1e,0x96,0xf5,0x0a,0xba,0x0a,0xb2
        },
        new byte[64]{
        0xef,0x1f,0xdf,0xb3,0xe8,0x15,0x66,0xd2,0xf9,0x48,0xe1,0xa0,0x5d,0x71,0xe4,0xdd,
        0x48,0x8e,0x85,0x7e,0x33,0x5c,0x3c,0x7d,0x9d,0x72,0x1c,0xad,0x68,0x5e,0x35,0x3f,
        0xa9,0xd7,0x2c,0x82,0xed,0x03,0xd6,0x75,0xd8,0xb7,0x13,0x33,0x93,0x52,0x03,0xbe,
        0x34,0x53,0xea,0xa1,0x93,0xe8,0x37,0xf1,0x22,0x0c,0xbe,0xbc,0x84,0xe3,0xd1,0x2e
        },
        new byte[64]{
        0x4b,0xea,0x6b,0xac,0xad,0x47,0x47,0x99,0x9a,0x3f,0x41,0x0c,0x6c,0xa9,0x23,0x63,
        0x7f,0x15,0x1c,0x1f,0x16,0x86,0x10,0x4a,0x35,0x9e,0x35,0xd7,0x80,0x0f,0xff,0xbd,
        0xbf,0xcd,0x17,0x47,0x25,0x3a,0xf5,0xa3,0xdf,0xff,0x00,0xb7,0x23,0x27,0x1a,0x16,
        0x7a,0x56,0xa2,0x7e,0xa9,0xea,0x63,0xf5,0x60,0x17,0x58,0xfd,0x7c,0x6c,0xfe,0x57
        },
        new byte[64]{
        0xae,0x4f,0xae,0xae,0x1d,0x3a,0xd3,0xd9,0x6f,0xa4,0xc3,0x3b,0x7a,0x30,0x39,0xc0,
        0x2d,0x66,0xc4,0xf9,0x51,0x42,0xa4,0x6c,0x18,0x7f,0x9a,0xb4,0x9a,0xf0,0x8e,0xc6,
        0xcf,0xfa,0xa6,0xb7,0x1c,0x9a,0xb7,0xb4,0x0a,0xf2,0x1f,0x66,0xc2,0xbe,0xc6,0xb6,
        0xbf,0x71,0xc5,0x72,0x36,0x90,0x4f,0x35,0xfa,0x68,0x40,0x7a,0x46,0x64,0x7d,0x6e
        },
        new byte[64]{
        0xf4,0xc7,0x0e,0x16,0xee,0xaa,0xc5,0xec,0x51,0xac,0x86,0xfe,0xbf,0x24,0x09,0x54,
        0x39,0x9e,0xc6,0xc7,0xe6,0xbf,0x87,0xc9,0xd3,0x47,0x3e,0x33,0x19,0x7a,0x93,0xc9,
        0x09,0x92,0xab,0xc5,0x2d,0x82,0x2c,0x37,0x06,0x47,0x69,0x83,0x28,0x4a,0x05,0x04,
        0x35,0x17,0x45,0x4c,0xa2,0x3c,0x4a,0xf3,0x88,0x86,0x56,0x4d,0x3a,0x14,0xd4,0x93
        },
        new byte[64]{
        0x9b,0x1f,0x5b,0x42,0x4d,0x93,0xc9,0xa7,0x03,0xe7,0xaa,0x02,0x0c,0x6e,0x41,0x41,
        0x4e,0xb7,0xf8,0x71,0x9c,0x36,0xde,0x1e,0x89,0xb4,0x44,0x3b,0x4d,0xdb,0xc4,0x9a,
        0xf4,0x89,0x2b,0xcb,0x92,0x9b,0x06,0x90,0x69,0xd1,0x8d,0x2b,0xd1,0xa5,0xc4,0x2f,
        0x36,0xac,0xc2,0x35,0x59,0x51,0xa8,0xd9,0xa4,0x7f,0x0d,0xd4,0xbf,0x02,0xe7,0x1e
        },
        new byte[64]{
        0x37,0x8f,0x5a,0x54,0x16,0x31,0x22,0x9b,0x94,0x4c,0x9a,0xd8,0xec,0x16,0x5f,0xde,
        0x3a,0x7d,0x3a,0x1b,0x25,0x89,0x42,0x24,0x3c,0xd9,0x55,0xb7,0xe0,0x0d,0x09,0x84,
        0x80,0x0a,0x44,0x0b,0xdb,0xb2,0xce,0xb1,0x7b,0x2b,0x8a,0x9a,0xa6,0x07,0x9c,0x54,
        0x0e,0x38,0xdc,0x92,0xcb,0x1f,0x2a,0x60,0x72,0x61,0x44,0x51,0x83,0x23,0x5a,0xdb
        },
        new byte[64]{
        0xab,0xbe,0xde,0xa6,0x80,0x05,0x6f,0x52,0x38,0x2a,0xe5,0x48,0xb2,0xe4,0xf3,0xf3,
        0x89,0x41,0xe7,0x1c,0xff,0x8a,0x78,0xdb,0x1f,0xff,0xe1,0x8a,0x1b,0x33,0x61,0x03,
        0x9f,0xe7,0x67,0x02,0xaf,0x69,0x33,0x4b,0x7a,0x1e,0x6c,0x30,0x3b,0x76,0x52,0xf4,
        0x36,0x98,0xfa,0xd1,0x15,0x3b,0xb6,0xc3,0x74,0xb4,0xc7,0xfb,0x98,0x45,0x9c,0xed
        },
        new byte[64]{
        0x7b,0xcd,0x9e,0xd0,0xef,0xc8,0x89,0xfb,0x30,0x02,0xc6,0xcd,0x63,0x5a,0xfe,0x94,
        0xd8,0xfa,0x6b,0xbb,0xeb,0xab,0x07,0x61,0x20,0x01,0x80,0x21,0x14,0x84,0x66,0x79,
        0x8a,0x1d,0x71,0xef,0xea,0x48,0xb9,0xca,0xef,0xba,0xcd,0x1d,0x7d,0x47,0x6e,0x98,
        0xde,0xa2,0x59,0x4a,0xc0,0x6f,0xd8,0x5d,0x6b,0xca,0xa4,0xcd,0x81,0xf3,0x2d,0x1b
        },
        new byte[64]{
        0x37,0x8e,0xe7,0x67,0xf1,0x16,0x31,0xba,0xd2,0x13,0x80,0xb0,0x04,0x49,0xb1,0x7a,
        0xcd,0xa4,0x3c,0x32,0xbc,0xdf,0x1d,0x77,0xf8,0x20,0x12,0xd4,0x30,0x21,0x9f,0x9b,
        0x5d,0x80,0xef,0x9d,0x18,0x91,0xcc,0x86,0xe7,0x1d,0xa4,0xaa,0x88,0xe1,0x28,0x52,
        0xfa,0xf4,0x17,0xd5,0xd9,0xb2,0x1b,0x99,0x48,0xbc,0x92,0x4a,0xf1,0x1b,0xd7,0x20
        }
        };

        private byte[] iv =new byte[64];

        private byte[] N =new byte[64];

        private byte[] Sigma = new byte[64];

        public int outLen = 0;

        public GOST(int outputLenght)
        {
            if (outputLenght == 512)
            {
                for (int i = 0; i < 64; i++)
                {
                    N[i] = 0x00;
                    Sigma[i] = 0x00;
                    iv[i] = 0x00;
                }
                outLen = 512;
            }
            else if (outputLenght == 256)
            {
                for (int i = 0; i < 64; i++)
                {
                    N[i] = 0x00;
                    Sigma[i] = 0x00;
                    iv[i] = 0x01;
                }
                outLen = 256;
            }
        }

        private byte[] AddModulo512(byte[] a, byte[] b)
        {
            byte[] temp = new byte[64];
            int i = 0, t = 0;
            byte[] tempA = new byte[64];
            byte[] tempB = new byte[64];
            Array.Copy(a, 0, tempA, 64 - a.Length, a.Length);
            Array.Copy(b, 0, tempB, 64 - b.Length, b.Length);
            for (i = 63; i >= 0; i--)
            {
                t = tempA[i] + tempB[i] + (t >> 8);
                temp[i] = (byte)(t & 0xFF);
            }
            return temp;
        }

        private byte[] AddXor512(byte[] a, byte[] b)
        {
            byte[] c = new byte[64];
            for (int i = 0; i < 64; i++)
                c[i] = (byte)(a[i] ^ b[i]);
            return c;
        }

        private byte[] S(byte[] state)
        {
            byte[] result = new byte[64];
            for (int i = 0; i < 64; i++)
                result[i] = Sbox[state[i]];
            return result;
        }

        private byte[] P(byte[] state)
        {
            byte[] result = new byte[64];
            for (int i = 0; i < 64; i++)
            {
                result[i] = state[Tau[i]];
            }
            return result;
        }

        private byte[] L(byte[] state)
        {
            byte[] result = new byte[64];            
            for (int i = 0; i < 8; i++)
            {
                ulong t = 0;
                byte[] tempArray = new byte[8];
                Array.Copy(state, i * 8, tempArray, 0, 8);
                tempArray = tempArray.Reverse().ToArray();
                BitArray tempBits1 = new BitArray(tempArray);
                bool[] tempBits=new bool[64];
                tempBits1.CopyTo(tempBits, 0);
                tempBits=tempBits.Reverse().ToArray();
                for (int j = 0; j < 64; j++)
                {
                    if (tempBits[j] != false)
                        t = t ^ A[j];
                }
                byte[] ResPart = BitConverter.GetBytes(t).Reverse().ToArray();
                Array.Copy(ResPart, 0, result, i * 8, 8);
            }
            return result;
        }

        private byte[] KeySchedule(byte[] K, int i)
        {
            K=AddXor512(K, C[i]);
            K = S(K);
            K = P(K);
            K = L(K);
            return K;
        }

        private byte[] E(byte[] K, byte[] m)
        {
            byte[] state = AddXor512(K, m);
            for (int i = 0; i < 12; i++)
            {
                state=S(state);
                state = P(state);
                state = L(state);                
                K=KeySchedule(K, i);
                state = AddXor512(state, K);
            }
            return state;
        }

        private byte[] G_n(byte[] N, byte[] h, byte[] m)
        {
            byte[] K = AddXor512(h, N);
            K=S(K);
            K=P(K);
            K=L(K);
            byte[] t= E(K, m);
            t=AddXor512(t, h);
            byte[] newh = AddXor512(t, m);
            return newh;
        }

        public byte[] GetHash(byte[] message)
        {
            byte[] paddedMes=new byte[64];
            int len = message.Length * 8;
            byte[] h = new byte[64];
            Array.Copy(iv, h, 64);
            byte[] N_0 ={
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
            };
            if (outLen == 512)
            {
                for (int i = 0; i < 64; i++)
                {
                    N[i] = 0x00;
                    Sigma[i] = 0x00;
                    iv[i] = 0x00;
                }                
            }
            else if (outLen == 256)
            {
                for (int i = 0; i < 64; i++)
                {
                    N[i] = 0x00;
                    Sigma[i] = 0x00;
                    iv[i] = 0x01;
                }                
            }
            byte[] N_512 = BitConverter.GetBytes(512);
            int inc = 0;
            while (len >= 512)
            {
                inc++;
                byte[] tempMes = new byte[64];
                Array.Copy(message, message.Length - inc*64, tempMes, 0, 64);                
                h=G_n(N, h, tempMes);
                N = AddModulo512(N, N_512.Reverse().ToArray());
                Sigma=AddModulo512(Sigma, tempMes);
                len -= 512;                
            }
            byte[] message1 = new byte[message.Length - inc * 64];
            Array.Copy(message, 0, message1, 0, message.Length - inc * 64);
            if (message1.Length < 64)
            {
                for (int i = 0; i < (64 - message1.Length - 1); i++)
                {
                    paddedMes[i] = 0;
                }
                paddedMes[64 - message1.Length - 1] = 0x01;
                Array.Copy(message1, 0, paddedMes, 64 - message1.Length, message1.Length);
            }            
            h=G_n(N, h, paddedMes);
            byte[] MesLen = BitConverter.GetBytes(message1.Length * 8);
            N = AddModulo512(N, MesLen.Reverse().ToArray());
            Sigma = AddModulo512(Sigma, paddedMes);            
            h = G_n(N_0, h, N);
            h = G_n(N_0, h, Sigma);
            if (outLen == 512)
                return h;
            else
            {
                byte[] h256 = new byte[32];
                Array.Copy(h, 0, h256, 0, 32);
                return h256;
            }
        }
    }


Контрольный пример


Вычислим хеш-функцию для массива данных:
0x32,0x31,0x30,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30,0x39,0x38,0x37,
0x36,0x35,0x34,0x33,0x32,0x31,0x30,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,
0x30,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30,0x39,0x38,0x37,0x36,0x35,
0x34,0x33,0x32,0x31,0x30,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30


Для этого воспользуемся процедурой:
private void ComputeHash()
        {
            GOST G = new GOST(256);
            GOST G512 = new GOST(512);
            byte[] message={
                                0x32,0x31,0x30,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30,0x39,0x38,0x37,
                                0x36,0x35,0x34,0x33,0x32,0x31,0x30,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,
                                0x30,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30,0x39,0x38,0x37,0x36,0x35,
                                0x34,0x33,0x32,0x31,0x30,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30};          
            byte[] res = G.GetHash(message);
            byte[] res2 = G512.GetHash(message);            
            string h256 = BitConverter.ToString(res);
            string h512 = BitConverter.ToString(res2);
        }

В результате получим значения:

h256=00-55-7B-E5-E5-84-FD-52-A4-49-B1-6B-02-51-D0-5D-27-F9-4A-B7-6C-BA-A6-DA-89-0B-59-D8-EF-1E-15-9D

h512=48-6F-64-C1-91-78-79-41-7F-EF-08-2B-33-81-A4-E2-11-C3-24-F0-74-65-4C-38-82-3A-7B-76-F8-30-AD-00-FA-1F-BA-E4-2B-12-85-C0-35-2F-22-75-24-BC-9A-B1-62-54-28-8D-D6-86-3D-CC-D5-B9-F5-4A-1A-D0-54-1B

Ссылки


  1. Полное описание стандарта вы можете скачать отсюда.
  2. Сравнение старого и нового стандартов.
  3. Разобраться с алгоритмом мне очень помогла реализация пользователя okazymyrov на языке С, доступная здесь.
  4. Реализация на assembler, пользователя omegicus
Share post

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 55

    +2
    Входными данными для обоих функций является блок данных длиной 512 бит.

    Думаю, следует уточнить, что это относится непосредственно к хэшированию, но в стандарте также описаны функции сжатия (для сообщений больших 512 бит) и дополнения (для сообщений меньших 512 бит).

    P.S. Нормативным написанием является «хэширование», «хэш», а не «хешеривание», «хеш». Собственно даже по названию стандартов (что старого, что нового) это видно. Да и логически, по-моему, сложнее обосновать преобразование «hash» в «хеш», чем в «хэш».
      +1
      Вы совершенно правы. Вычисления х{е, э}ш-функции возможно для сообщений любой длины. Однако, на каждой итерации обрабатывается блок длиной именно в 512 бит.
      Что касается вашего замечания касательно правильности написания слова х{е, э}ш, то тема эта не нова и в интернете уже давно ведется обсуждение этого вопроса. Например вот в этой ветке. однако к какому то определенному решению так никто и не пришел, кому то ближе слово хеш, а кому то хэш. Я из числа первых, поэтому всегда использовал вариант с буквой е. Может быть он и неправильный, что спорно, но более привычный. Поэтому я все таки оставлю текущий вариант, и надеюсь на ваше понимание:)
        0
        По-моему неплохо бы этот момент уточнить прямо в посте, рядом с процитированной фразой. А то я полез читать сам стандарт, чтобы уточнить этот момент :)

        Слово «хеш» (и аналогичные, например «кеш») мне лично не нравятся прежде всего потому-что допускают двоякое прочтение на русском. Уже сталкивался в реале с прочтением через «е». Потому обрадовался когда обратил внимание, что в ГОСТе (ещё старом) используется «мой» вариант. Хотя иногда бессознательно подстраиваешься под собеседника и пишешь через «е».

          +1
          Добавил следующий текст:
          В случае, если длина сообщения больше 512 бит, то происходит разбиение сообщения на блоки. В случае же, если длина меньше 512 бит, то производится дополнение сообщения.

          Думаю, так станет понятнее.
          Спасибо за замечание)
            0
            Ну, чисто аутентичное произношение звучит как «хаш» (Google Translate, YourDictionary.Com)
              +1
              соу хаш литл бэйби доооуунт йу край…
                0
                Там другое слово в тексте песни.
                  0
                  хабр скушал тэг «сарказм».

                  Далеко не все звуки из одного языка можно перенести в другой без потерь. И если утверждать что Hash — это Хаш, то Hush транскрибировать придется точно так же вместе с add — ад и bad — бад.
                    0
                    > bad — бад.
                    Ну, примерно, так и есть, только в случае американского акцента. Я говорил про него.
                0
                А я вот слышу «э». И если верить словарям, то транскрипция /hæʃ/, а в других источниках /æ/ характеризуется как «Долгое «э» с широко раскрытым ртом и сильно опущенной нижней челюстью, среднее между «а» и «э»». Но пускай среднее, но всё долгое «э», а не «а». А уж е откуда взяло вообще не понять. Вроде как оно может заменять английское «a» после русских «ж», «ш» и «ч», но про «х» или «к» не упоминается.
      • UFO just landed and posted this here
          +3
          Или Свиборг :)
            –1
            Индийские корни? Т.е. город Стрий в Львовской области имеет какое-то сакральное отношение к Индии? =)
            Всё более популярна сейчас идея как раз об обратном переносе культуры — от древних славян-многобожцев в Индию.
            • UFO just landed and posted this here
                0
                Имя Стрибога восходит к древнему корню «стрег», что означает «старший», «дядя по отцу». godsbay.ru/slavs/stribog.html

                Возможно, что это не у русских слов индийские корни, а у санскрита славянские корни, потому то многие слова и похожи.
                • UFO just landed and posted this here
                    +9
                    Технари не могут в лингвистику, да? Санскрит и русский — равноправные потомки праиндоевропейского языка, с точки зрения официальной науки.
                      +1
                      Причем санскрит законсервировался намного раньше, и куда ближе к ПИЕ, чем русский (или даже древневосточнославянский).
                      +7
                      А что за свидетельства? Просто во времена ведического санскрита (~1500 лет до н.э) протославянский язык ещё толком не отпочковался от балтославянской общности. Кстати, балтийские языки в этом смысле к санскриту ещё ближе, в т.ч. по грамматическим свойствам. Так что у литовского в этом отношении даже побольше прав записываться в «прародители санскрита» :)

                      Но с учётом миграций индоевропейских племён ситуация, при которой давно ушедшие на северо-запад балтославяне каким-то образом дают начало индийскому языку, кажется очень сомнительной. Намного логичней рассматривать ситуацию, при которой и та и другая группа ветвь языков — соседние и развивающиеся из общего корня, а сохранение в славянских языках архаичных черт легко объясняется тем, что славяне селились преимущественно на не слишком заселённых территориях и не были подвержены действию языкового субстрата автохтонных племён (как это произошло, например, с германскими и романскими племенами — Западная Европа к моменту их прибытия была уже весьма заселена неиндоевропейским населением)
                  +5
                  Почему-то в глазах многих термин «индоевропейские» ассоциируется прежде всего с Индией.
                  • UFO just landed and posted this here
                    +5
                    Грешновато.
                    • UFO just landed and posted this here
                      • UFO just landed and posted this here
                          +1
                          Тогда еще нужно будет переименовать всех демонов в «прислужники» например. А вот что делать с 666 — я еще не придумал :(
                      –3
                      И чем им sha 3 не угодил…
                        +1
                        Ну как минимум тем, то стандарта sha3 ещё нет даже черновой версии. А ГОСТ 34.11-2012 уже введён в действие с 01.01.2013.
                          –2
                          Все прекрасно знали о сроках принятия, кандидатах и всем остальном. Так что, смысла торопиться со своим велосипедом не было.
                            0
                            Не думаю, что это велосипед, в плане шифрования у нас всегда всё нормально было
                          +1
                          Мне вот кстати тоже непонятно это желание быть «не такими как все». Это еще можно было понять в конце 80-х, начале 90-х когда принимались старые стандарты. Но сейчас… хз, может они знают что то, чего не знаем мы.
                        • UFO just landed and posted this here
                            +7
                            Радует, что появился еще один хэш-алгоритм. Но хочется понять его приемущества:
                            1) насколько он устойчив к коллизиям по сравнению например с SHA2 или SHA2?
                            2) насколько он требователен к вычислительным ресурсам по сравнению с другими?
                            3) на каких аппаратных архитектурах ожидаются лучшие результаты?
                            4) рекомендации к применению этого алгоритма: где он к месту, а где лучше использовать другие?
                            Для прикладных программистов ситуация пока в тумане.
                            • UFO just landed and posted this here
                                0
                                Случайность недостаточно хороша, как минимум. да и как вы дешифровывать будете?
                                Таблицы подбираются для усложнения взлома.
                                • UFO just landed and posted this here
                                    0
                                    Вам ничто не мешает для своих нужд применять доморощенные таблицы замен, вычисленные каким угодно способом. Только потом не говорите, что вас не предупреждали, если ваш хеш будет взломан. И вообще, надеюсь, вы имеете профессиональный опыт в криптографии, потому что чуть более, чем всегда, бывает так, что «усовершенствования», вносимые в стандартный криптоалгоритм дилетантами, приводят к образованию в нем фатальных уязвимостей.

                                    При чем здесь дороги с двусторонним движением? Может лучше вообще отказаться от автомобилей? Ведь из-за них в день так много смертей случается? И переход на дороги с односторонним движением может лишь сократить, но не устранить эти случаи гибели людей.
                                    • UFO just landed and posted this here
                                      0
                                      Мне как-то говорили, что изобретают свои криптографические алгоритмы 2 типа людей: гении и глупцы. Вы так уверены, что взятие дополнительной функции от сообщения вместо константы увеличит криптостойкость? Я вот нет.
                                      • UFO just landed and posted this here
                                        • UFO just landed and posted this here
                                            0
                                            Для «генерации хаоса» ни в коем случае нельзя использовать исходные сообщения в общем случае, ибо исходное сообщение, в реальных применениях, имеет какой-либо практический смысл, следовательно, оно не является случайным!

                                            Так что использовав исходное сообщение мы практически наверняка понизим криптостойкость.
                                            • UFO just landed and posted this here
                                    +2
                                    Хоть бы ссылку на оригинальную реализацию дали. А то подстановка сначала «Pi», а потом «Sbox» обзывается…
                                      0
                                      Указал. Я правильно понимаю, что это ваша реализация и вы являетесь одним из авторов алгоритма?
                                        +3
                                        Да, реализация моя. Она ориентирована в первую очередь на кроссплатформенность, а потом уже на производительность. И нет, я не один из авторов стандарта, просто независимый эксперт.
                                      +2
                                      В стандарте в качестве примера используются следующие строки:

                                      Строка: 210987654321098765432109876543210987654321098765432109876543210
                                      512: 486f64c1917879417fef082b3381a4e211c324f074654c38823a7b76f830ad00fa1fbae42b1285c0352f227524bc9ab16254288dd6863dccd5b9f54a1ad0541b
                                      256:
                                      00557be5e584fd52a449b16b0251d05d27f94ab76cbaa6da890b59d8ef1e159d

                                      Строка: ыверогИ ыкълп яырбарх ан ималертс яром с ътюев, ицунв ижобиртС, иртев еС
                                      512: 28fbc9bada033b1460642bdcddb90c3fb3e56c497ccd0f62b8a2ad4935e85f037613966de4ee00531ae60f3b5a47f8dae06915d5f2f194996fcabf2622e6881e
                                      256:
                                      508f7e553c06501d749a66fc28c6cac0b005746d97537fa85d9e40904efed29d
                                        +1
                                        О Бояне, соловію стараго времени!
                                          +1
                                          С первой строкой согласен, а во второй у вас ошибочка с запятыми)
                                          Вот так она должна выглядеть:
                                          ыверогИ ыкълп яырбарх ан ималертс яром с ътюев, ицунв ижобиртС, иртев еС
                                            0
                                            Упс, оказывается это хабр пробелы перед запятыми глотает. В общем там пробелы не после запятых а перед должны стоять.
                                          +1
                                          omegicus.com/gost_34.11-2012_stribog/ — сделал на flat assembler (x86 + mmx)
                                            0
                                            Круто!
                                            Добавлю в пост, если вы не против.
                                              0
                                              только, за правда пока она недооптимизирована, но обещаю доделать по скорости и файлы хешить
                                            0
                                            В псевдокоде у вас написано что пункты 7 и 8 следующие
                                            7. Вычислить h = g(0, m, h)
                                            8. Для хеш-функции с длиной выхода в 512 бит возвращаем h в качестве результата. Для функции с длиной выхода 256 бит возвращаем MSB256(h).
                                            но в C#
                                            h = G_n(N_0, h, N);
                                            h = G_n(N_0, h, Sigma);
                                            Получается 8 шаг должен быть
                                            h = g(0, Σ, h)
                                              0
                                              Спасибо за замечание. Я в описании псевдокода последний шаг пропустил.

                                            Only users with full accounts can post comments. Log in, please.