Blog. Just Blog

Алгоритм хеширования SipHash-2-4 на Ассемблере

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Алгоритм хеширования SipHash-2-4 на Ассемблере
Алгоритм хеширования SipHash-2-4 на Ассемблере

В начале 2010-х годов исследователи обнаружили тревожную уязвимость в архитектуре множества веб-сервисов и языков программирования. Злоумышленник мог отправить специально подобранный HTTP-запрос с параметрами, ключи которых вызывали максимальное количество коллизий в хеш-таблицах. Поскольку большинство реализаций использовали незащищенные хеш-функции (например, FNV или MurmurHash), атакующий легко предсказывал их поведение. Тогда-то и появился SipHash, а именно его вариант SipHash-2-4, разработанный в 2012 году Жаном-Филиппом Омассоном и Дэниелем Бернштейном.

SipHash-2-4 решает эту проблему за счет использования секретного ключа. Без знания ключа невозможно предсказать хеш-значения или целенаправленно создать коллизии. При этом скорость работы SipHash-2-4 на коротких строках - типичных для словарных ключей, URL или заголовков - остается сопоставимой с лучшими незащищенными аналогами. Главное правило при его использовании одно: всегда применяйте секретный случайный ключ. Только в этом случае SipHash обеспечивает заявленную защиту.

С момента своего появления SipHash-2-4 прошел суровую проверку на практике: выдержал десятки независимых криптоанализов, был интегрирован в ядро Linux, стал основой хеширования в стандартных библиотеках Python, Ruby, Rust, Swift и других языков. Эти наработки легли в основу решений, применяемых сегодня в критически важных проектах. Несмотря на появление альтернативных решений, SipHash-2-4 по-прежнему обеспечивает тщательно сбалансированное решение, сочетающее криптографическую стойкость, высокую скорость на коротких данных и минимальную сложность реализации.
  1. ;---------------------------------------------
  2. ; Функция вычисления хеша SipHash-2-4
  3. ; Copyright (C) ManHunter / PCL
  4. ; https://www.manhunter.ru
  5. ;---------------------------------------------
  6. ; Параметры:
  7. ;       lpData - указатель на строку
  8. ;       dSize  - длина строки
  9. ;       pKey   - 16-байтовый ключ
  10. ; На выходе:
  11. ;       EDX:EAX = полученный хеш
  12. ;---------------------------------------------
  13. proc    SipHash lpData:DWORD, dSize:DWORD, pKey:DWORD
  14.         locals
  15.           ; Внутреннее состояние (v0, v1, v2, v3)
  16.           v0_L dd 0
  17.           v0_H dd 0
  18.           v1_L dd 0
  19.           v1_H dd 0
  20.           v2_L dd 0
  21.           v2_H dd 0
  22.           v3_L dd 0
  23.           v3_H dd 0
  24.           last_L dd 0
  25.           last_H dd 0
  26.         endl
  27.  
  28.         push    ebx ecx esi edi
  29.  
  30.         ; Инициализация состояния
  31.         mov     edi,[pKey]
  32.  
  33.         ; v0 = k0 ^ C0
  34.         mov     eax,[edi]
  35.         xor     eax,0x70736575
  36.         mov     [v0_L],eax
  37.         mov     eax,[edi+4]
  38.         xor     eax,0x736f6d65
  39.         mov     [v0_H],eax
  40.  
  41.         ; v1 = k1 ^ C1
  42.         mov     eax,[edi+8]
  43.         xor     eax,0x6e646f6d
  44.         mov     [v1_L],eax
  45.         mov     eax,[edi+12]
  46.         xor     eax,0x646f7261
  47.         mov     [v1_H],eax
  48.  
  49.         ; v2 = k0 ^ C2
  50.         mov     eax,[edi]
  51.         xor     eax,0x6e657261
  52.         mov     [v2_L],eax
  53.         mov     eax,[edi+4]
  54.         xor     eax,0x6c796765
  55.         mov     [v2_H],eax
  56.  
  57.         ; v3 = k1 ^ C3
  58.         mov     eax,[edi+8]
  59.         xor     eax,0x79746573
  60.         mov     [v3_L],eax
  61.         mov     eax,[edi+12]
  62.         xor     eax,0x74656462
  63.         mov     [v3_H],eax
  64.  
  65.         ; Обработка 8-байтовых блоков
  66.         mov     esi,[lpData]
  67.         mov     ecx,[dSize]
  68.         mov     ebx,ecx
  69.         ; Количество полных блоков
  70.         shr     ebx,3
  71.         jz      .loc_padding
  72.  
  73. .loop_blocks:
  74.         mov     eax,[esi]
  75.         mov     edx,[esi+4]
  76.         xor     [v3_L],eax
  77.         xor     [v3_H],edx
  78.  
  79.         stdcall SipRound
  80.         stdcall SipRound
  81.  
  82.         mov     eax,[esi]
  83.         mov     edx,[esi+4]
  84.         xor     [v0_L],eax
  85.         xor     [v0_H],edx
  86.  
  87.         ; Следующий блок
  88.         add     esi,8
  89.         dec     ebx
  90.         jnz     .loop_blocks
  91.  
  92. .loc_padding:
  93.         ; last7 = (uint64_t)(len & 0xff) << 56
  94.         xor     eax,eax
  95.         mov     edx,[dSize]
  96.         ; Записываем длину в старший байт 64-битного слова
  97.         shl     edx,24
  98.  
  99.         mov     ebx,[dSize]
  100.         ; Остаток байт (0-7)
  101.         and     ebx,7
  102.         jz      .finish_pad
  103.  
  104.         ; last7 = (uint64_t)(len & 0xff) << 56
  105.         mov     ecx, [dSize]
  106.         mov     ebx, 0
  107.         movzx   eax, cl
  108.         mov     edx, ebx
  109.         and     edx, 0
  110.         mov     edx, eax
  111.         mov     eax, 0
  112.         shl     edx, 18h
  113.         mov     [last_L],eax
  114.         mov     [last_H],edx
  115.  
  116.         ; Загрузка остатка в little-endian стиле
  117.         cmp     ebx,1
  118.         je      .tail_1
  119.         cmp     ebx,2
  120.         je      .tail_2
  121.         cmp     ebx,3
  122.         je      .tail_3
  123.         cmp     ebx,4
  124.         je      .tail_4
  125.         cmp     ebx,5
  126.         je      .tail_5
  127.         cmp     ebx,6
  128.         je      .tail_6
  129. .tail_7:
  130.         ; last7 |= (uint64_t)m[6] << 48
  131.         mov     ecx,esi
  132.         add     ecx,6
  133.         movzx   eax,byte [ecx]
  134.         mov     edx,0
  135.         mov     ecx,eax
  136.         mov     ebx,edx
  137.         mov     ebx,ecx
  138.         mov     ecx,0
  139.         shl     ebx,10h
  140.         mov     eax,[last_L]
  141.         or      eax,ecx
  142.         mov     edx,[last_H]
  143.         or      edx,ebx
  144.         mov     [last_L],eax
  145.         mov     [last_H],edx
  146. .tail_6:
  147.         ; last7 |= (uint64_t)m[5] << 40
  148.         mov     ecx,esi
  149.         add     ecx,5
  150.         movzx   eax,byte [ecx]
  151.         mov     edx, 0
  152.         mov     ecx, eax
  153.         mov     ebx, edx
  154.         mov     ebx, ecx
  155.         mov     ecx, 0
  156.         shl     ebx, 8
  157.         mov     eax,[last_L]
  158.         or      eax,ecx
  159.         mov     edx,[last_H]
  160.         or      edx,ebx
  161.         mov     [last_L],eax
  162.         mov     [last_H],edx
  163. .tail_5:
  164.         ; last7 |= (uint64_t)m[4] << 32
  165.         mov     ecx,esi
  166.         add     ecx,4
  167.         movzx   eax,byte [ecx]
  168.         mov     edx,0
  169.         mov     ecx,eax
  170.         mov     ebx,edx
  171.         mov     ebx,ecx
  172.         mov     ecx,0
  173.         mov     eax,[last_L]
  174.         or      eax,ecx
  175.         mov     edx,[last_H]
  176.         or      edx,ebx
  177.         mov     [last_L],eax
  178.         mov     [last_H],edx
  179. .tail_4:
  180.         ; last7 |= (uint64_t)m[3] << 24
  181.         mov     ecx,esi
  182.         add     ecx,3
  183.         movzx   eax,byte [ecx]
  184.         mov     edx, 0
  185.         mov     ecx,eax
  186.         mov     ebx,edx
  187.         shld    ebx,ecx,18h
  188.         shl     ecx,18h
  189.         mov     eax,[last_L]
  190.         or      eax,ecx
  191.         mov     edx,[last_H]
  192.         or      edx,ebx
  193.         mov     [last_L],eax
  194.         mov     [last_H],edx
  195. .tail_3:
  196.         ; last7 |= (uint64_t)m[2] << 16
  197.         mov     ecx,esi
  198.         add     ecx,2
  199.         movzx   eax,byte [ecx]
  200.         mov     edx,0
  201.         mov     ecx,eax
  202.         mov     ebx,edx
  203.         shld    ebx,ecx,10h
  204.         shl     ecx,10h
  205.         mov     eax,[last_L]
  206.         or      eax,ecx
  207.         mov     edx,[last_H]
  208.         or      edx,ebx
  209.         mov     [last_L],eax
  210.         mov     [last_H],edx
  211. .tail_2:
  212.         ; last7 |= (uint64_t)m[1] << 8
  213.         mov     ecx,esi
  214.         add     ecx,1
  215.         movzx   eax,byte [ecx]
  216.         mov     edx,0
  217.         mov     ecx,eax
  218.         mov     ebx,edx
  219.         shld    ebx,ecx,8
  220.         shl     ecx,8
  221.         mov     eax,[last_L]
  222.         or      eax,ecx
  223.         mov     edx,[last_H]
  224.         or      edx,ebx
  225.         mov     [last_L],eax
  226.         mov     [last_H],edx
  227. .tail_1:
  228.         ; last7 |= (uint64_t)m[0]
  229.         movzx   ecx, byte [esi]
  230.         mov     ebx, 0
  231.         mov     eax,[last_L]
  232.         or      eax,ecx
  233.         mov     edx,[last_H]
  234.         or      edx,ebx
  235. .finish_pad:
  236.         ; v3 ^= last7
  237.         mov     [last_L],eax
  238.         mov     [last_H],edx
  239.         xor     [v3_L],eax
  240.         xor     [v3_H],edx
  241.  
  242.         stdcall SipRound
  243.         stdcall SipRound
  244.  
  245.         ; v0 ^= last7
  246.         mov     eax,[last_L]
  247.         mov     edx,[last_H]
  248.         xor     [v0_L],eax
  249.         xor     [v0_H],edx
  250.  
  251.         ; Финализация: v2 ^= 0xFF
  252.         xor     [v2_L],0xFF
  253.  
  254.         stdcall SipRound
  255.         stdcall SipRound
  256.         stdcall SipRound
  257.         stdcall SipRound
  258.  
  259.         ; Результат: v0 ^ v1 ^ v2 ^ v3
  260.         mov     eax,[v0_L]
  261.         mov     edx,[v0_H]
  262.         xor     eax,[v1_L]
  263.         xor     edx,[v1_H]
  264.         xor     eax,[v2_L]
  265.         xor     edx,[v2_H]
  266.         xor     eax,[v3_L]
  267.         xor     edx,[v3_H]
  268. .loc_ret:
  269.         pop     edi esi ecx ebx
  270.         ret
  271.  
  272. ;---------------------------------------------------------
  273. ; Вспомогательная процедура SipRound
  274. ;---------------------------------------------------------
  275. SipRound:
  276.         push    esi edi ebx
  277.  
  278.         ; v0 += v1
  279.         mov     eax,[v1_L]
  280.         mov     edx,[v1_H]
  281.         add     [v0_L],eax
  282.         adc     [v0_H],edx
  283.         ; v1 = rol(v1, 13)
  284.         mov     eax,[v1_L]
  285.         mov     esi,eax
  286.         shr     esi,13h
  287.         mov     eax,[v1_H]
  288.         mov     edi,eax
  289.         shl     edi,0Dh
  290.         mov     eax,[v1_H]
  291.         mov     ebx,eax
  292.         shr     ebx,13h
  293.         mov     eax,[v1_L]
  294.         mov     ecx,eax
  295.         shl     ecx,0Dh
  296.         mov     edx,esi
  297.         or      edx,edi
  298.         mov     eax,ebx
  299.         or      eax,ecx
  300.         mov     [v1_L],eax
  301.         mov     [v1_H],edx
  302.         ; v1 ^= v0
  303.         mov     eax,[v0_L]
  304.         mov     edx,[v0_H]
  305.         xor     [v1_L],eax
  306.         xor     [v1_H],edx
  307.         ; v0 = rol(v0, 32)
  308.         mov     eax,[v0_L]
  309.         mov     edx,[v0_H]
  310.         mov     [v0_L],edx
  311.         mov     [v0_H],eax
  312.         ; v2 += v3
  313.         mov     eax,[v3_L]
  314.         mov     edx,[v3_H]
  315.         add     [v2_L],eax
  316.         adc     [v2_H],edx
  317.         ; v3 = rol(v3, 16)
  318.         mov     eax,[v3_L]
  319.         mov     esi,eax
  320.         shr     esi,10h
  321.         mov     eax,[v3_H]
  322.         mov     edi,eax
  323.         shl     edi,10h
  324.         mov     eax,[v3_H]
  325.         mov     ebx,eax
  326.         shr     ebx,10h
  327.         mov     eax,[v3_L]
  328.         mov     ecx,eax
  329.         shl     ecx,10h
  330.         mov     edx,esi
  331.         or      edx,edi
  332.         mov     eax,ebx
  333.         or      eax,ecx
  334.         mov     [v3_L],eax
  335.         mov     [v3_H],edx
  336.         ; v3 ^= v2
  337.         mov     eax,[v2_L]
  338.         mov     edx,[v2_H]
  339.         xor     [v3_L],eax
  340.         xor     [v3_H],edx
  341.         ; v0 += v3
  342.         mov     eax,[v3_L]
  343.         mov     edx,[v3_H]
  344.         add     [v0_L],eax
  345.         adc     [v0_H],edx
  346.         ; v3 = rol(v3, 21)
  347.         mov     eax,[v3_L]
  348.         mov     esi,eax
  349.         shr     esi,0Bh
  350.         mov     eax,[v3_H]
  351.         mov     edi,eax
  352.         shl     edi,15h
  353.         mov     eax,[v3_H]
  354.         mov     ebx,eax
  355.         shr     ebx,0Bh
  356.         mov     eax,[v3_L]
  357.         mov     ecx,eax
  358.         shl     ecx,15h
  359.         mov     edx,esi
  360.         or      edx,edi
  361.         mov     eax,ebx
  362.         or      eax,ecx
  363.         mov     [v3_L],eax
  364.         mov     [v3_H],edx
  365.         ; v3 ^= v0
  366.         mov     eax,[v0_L]
  367.         mov     edx,[v0_H]
  368.         xor     [v3_L],eax
  369.         xor     [v3_H],edx
  370.         ; v2 += v1
  371.         mov     eax,[v1_L]
  372.         mov     edx,[v1_H]
  373.         add     [v2_L],eax
  374.         adc     [v2_H],edx
  375.         ; v1 = rol(v1, 17)
  376.         mov     eax,[v1_L]
  377.         mov     esi,eax
  378.         shr     esi,0Fh
  379.         mov     eax,[v1_H]
  380.         mov     edi,eax
  381.         shl     edi,11h
  382.         mov     eax,[v1_H]
  383.         mov     ebx,eax
  384.         shr     ebx,0Fh
  385.         mov     eax,[v1_L]
  386.         mov     ecx,eax
  387.         shl     ecx,11h
  388.         mov     edx,esi
  389.         or      edx,edi
  390.         mov     eax,ebx
  391.         or      eax,ecx
  392.         mov     [v1_L],eax
  393.         mov     [v1_H],edx
  394.         ; v1 ^= v2
  395.         mov     eax,[v2_L]
  396.         mov     edx,[v2_H]
  397.         xor     [v1_L],eax
  398.         xor     [v1_H],edx
  399.         ; v2 = rol(v2, 32)
  400.         mov     eax,[v2_L]
  401.         mov     edx,[v2_H]
  402.         mov     [v2_L],edx
  403.         mov     [v2_H],eax
  404.  
  405.         pop     ebx edi esi
  406.         retn
  407. endp
Функция принимает три параметра: lpData - указатель на входную строку (DWORD), dSize - ее длина в байтах, pKey - 128-битный секретный ключ (16 байт). В приведенном примере используется тестовый ключ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, но в реальных сценариях его необходимо заменять на криптографически случайный. Результат возвращается в паре регистров EDX:EAX как 64-битное хеш-значение.

В приложении пример программы с исходным текстом, которая считает хеш SipHash-2-4 для введенной строки.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

SipHash-2-4.Demo.zip (4,466 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 188 | Комментариев: 0

Метки: Assembler, хеши

Комментарии

Отзывы посетителей сайта о статье
Комментариeв нет

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2026
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0035 сек.) / Память: 4.5 Mb
Наверх