
Алгоритм хеширования 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 по-прежнему обеспечивает тщательно сбалансированное решение, сочетающее криптографическую стойкость, высокую скорость на коротких данных и минимальную сложность реализации.
Code (Assembler) : Убрать нумерацию
- ;---------------------------------------------
- ; Функция вычисления хеша SipHash-2-4
- ; Copyright (C) ManHunter / PCL
- ; https://www.manhunter.ru
- ;---------------------------------------------
- ; Параметры:
- ; lpData - указатель на строку
- ; dSize - длина строки
- ; pKey - 16-байтовый ключ
- ; На выходе:
- ; EDX:EAX = полученный хеш
- ;---------------------------------------------
- proc SipHash lpData:DWORD, dSize:DWORD, pKey:DWORD
- locals
- ; Внутреннее состояние (v0, v1, v2, v3)
- v0_L dd 0
- v0_H dd 0
- v1_L dd 0
- v1_H dd 0
- v2_L dd 0
- v2_H dd 0
- v3_L dd 0
- v3_H dd 0
- last_L dd 0
- last_H dd 0
- endl
- push ebx ecx esi edi
- ; Инициализация состояния
- mov edi,[pKey]
- ; v0 = k0 ^ C0
- mov eax,[edi]
- xor eax,0x70736575
- mov [v0_L],eax
- mov eax,[edi+4]
- xor eax,0x736f6d65
- mov [v0_H],eax
- ; v1 = k1 ^ C1
- mov eax,[edi+8]
- xor eax,0x6e646f6d
- mov [v1_L],eax
- mov eax,[edi+12]
- xor eax,0x646f7261
- mov [v1_H],eax
- ; v2 = k0 ^ C2
- mov eax,[edi]
- xor eax,0x6e657261
- mov [v2_L],eax
- mov eax,[edi+4]
- xor eax,0x6c796765
- mov [v2_H],eax
- ; v3 = k1 ^ C3
- mov eax,[edi+8]
- xor eax,0x79746573
- mov [v3_L],eax
- mov eax,[edi+12]
- xor eax,0x74656462
- mov [v3_H],eax
- ; Обработка 8-байтовых блоков
- mov esi,[lpData]
- mov ecx,[dSize]
- mov ebx,ecx
- ; Количество полных блоков
- shr ebx,3
- jz .loc_padding
- .loop_blocks:
- mov eax,[esi]
- mov edx,[esi+4]
- xor [v3_L],eax
- xor [v3_H],edx
- stdcall SipRound
- stdcall SipRound
- mov eax,[esi]
- mov edx,[esi+4]
- xor [v0_L],eax
- xor [v0_H],edx
- ; Следующий блок
- add esi,8
- dec ebx
- jnz .loop_blocks
- .loc_padding:
- ; last7 = (uint64_t)(len & 0xff) << 56
- xor eax,eax
- mov edx,[dSize]
- ; Записываем длину в старший байт 64-битного слова
- shl edx,24
- mov ebx,[dSize]
- ; Остаток байт (0-7)
- and ebx,7
- jz .finish_pad
- ; last7 = (uint64_t)(len & 0xff) << 56
- mov ecx, [dSize]
- mov ebx, 0
- movzx eax, cl
- mov edx, ebx
- and edx, 0
- mov edx, eax
- mov eax, 0
- shl edx, 18h
- mov [last_L],eax
- mov [last_H],edx
- ; Загрузка остатка в little-endian стиле
- cmp ebx,1
- je .tail_1
- cmp ebx,2
- je .tail_2
- cmp ebx,3
- je .tail_3
- cmp ebx,4
- je .tail_4
- cmp ebx,5
- je .tail_5
- cmp ebx,6
- je .tail_6
- .tail_7:
- ; last7 |= (uint64_t)m[6] << 48
- mov ecx,esi
- add ecx,6
- movzx eax,byte [ecx]
- mov edx,0
- mov ecx,eax
- mov ebx,edx
- mov ebx,ecx
- mov ecx,0
- shl ebx,10h
- mov eax,[last_L]
- or eax,ecx
- mov edx,[last_H]
- or edx,ebx
- mov [last_L],eax
- mov [last_H],edx
- .tail_6:
- ; last7 |= (uint64_t)m[5] << 40
- mov ecx,esi
- add ecx,5
- movzx eax,byte [ecx]
- mov edx, 0
- mov ecx, eax
- mov ebx, edx
- mov ebx, ecx
- mov ecx, 0
- shl ebx, 8
- mov eax,[last_L]
- or eax,ecx
- mov edx,[last_H]
- or edx,ebx
- mov [last_L],eax
- mov [last_H],edx
- .tail_5:
- ; last7 |= (uint64_t)m[4] << 32
- mov ecx,esi
- add ecx,4
- movzx eax,byte [ecx]
- mov edx,0
- mov ecx,eax
- mov ebx,edx
- mov ebx,ecx
- mov ecx,0
- mov eax,[last_L]
- or eax,ecx
- mov edx,[last_H]
- or edx,ebx
- mov [last_L],eax
- mov [last_H],edx
- .tail_4:
- ; last7 |= (uint64_t)m[3] << 24
- mov ecx,esi
- add ecx,3
- movzx eax,byte [ecx]
- mov edx, 0
- mov ecx,eax
- mov ebx,edx
- shld ebx,ecx,18h
- shl ecx,18h
- mov eax,[last_L]
- or eax,ecx
- mov edx,[last_H]
- or edx,ebx
- mov [last_L],eax
- mov [last_H],edx
- .tail_3:
- ; last7 |= (uint64_t)m[2] << 16
- mov ecx,esi
- add ecx,2
- movzx eax,byte [ecx]
- mov edx,0
- mov ecx,eax
- mov ebx,edx
- shld ebx,ecx,10h
- shl ecx,10h
- mov eax,[last_L]
- or eax,ecx
- mov edx,[last_H]
- or edx,ebx
- mov [last_L],eax
- mov [last_H],edx
- .tail_2:
- ; last7 |= (uint64_t)m[1] << 8
- mov ecx,esi
- add ecx,1
- movzx eax,byte [ecx]
- mov edx,0
- mov ecx,eax
- mov ebx,edx
- shld ebx,ecx,8
- shl ecx,8
- mov eax,[last_L]
- or eax,ecx
- mov edx,[last_H]
- or edx,ebx
- mov [last_L],eax
- mov [last_H],edx
- .tail_1:
- ; last7 |= (uint64_t)m[0]
- movzx ecx, byte [esi]
- mov ebx, 0
- mov eax,[last_L]
- or eax,ecx
- mov edx,[last_H]
- or edx,ebx
- .finish_pad:
- ; v3 ^= last7
- mov [last_L],eax
- mov [last_H],edx
- xor [v3_L],eax
- xor [v3_H],edx
- stdcall SipRound
- stdcall SipRound
- ; v0 ^= last7
- mov eax,[last_L]
- mov edx,[last_H]
- xor [v0_L],eax
- xor [v0_H],edx
- ; Финализация: v2 ^= 0xFF
- xor [v2_L],0xFF
- stdcall SipRound
- stdcall SipRound
- stdcall SipRound
- stdcall SipRound
- ; Результат: v0 ^ v1 ^ v2 ^ v3
- mov eax,[v0_L]
- mov edx,[v0_H]
- xor eax,[v1_L]
- xor edx,[v1_H]
- xor eax,[v2_L]
- xor edx,[v2_H]
- xor eax,[v3_L]
- xor edx,[v3_H]
- .loc_ret:
- pop edi esi ecx ebx
- ret
- ;---------------------------------------------------------
- ; Вспомогательная процедура SipRound
- ;---------------------------------------------------------
- SipRound:
- push esi edi ebx
- ; v0 += v1
- mov eax,[v1_L]
- mov edx,[v1_H]
- add [v0_L],eax
- adc [v0_H],edx
- ; v1 = rol(v1, 13)
- mov eax,[v1_L]
- mov esi,eax
- shr esi,13h
- mov eax,[v1_H]
- mov edi,eax
- shl edi,0Dh
- mov eax,[v1_H]
- mov ebx,eax
- shr ebx,13h
- mov eax,[v1_L]
- mov ecx,eax
- shl ecx,0Dh
- mov edx,esi
- or edx,edi
- mov eax,ebx
- or eax,ecx
- mov [v1_L],eax
- mov [v1_H],edx
- ; v1 ^= v0
- mov eax,[v0_L]
- mov edx,[v0_H]
- xor [v1_L],eax
- xor [v1_H],edx
- ; v0 = rol(v0, 32)
- mov eax,[v0_L]
- mov edx,[v0_H]
- mov [v0_L],edx
- mov [v0_H],eax
- ; v2 += v3
- mov eax,[v3_L]
- mov edx,[v3_H]
- add [v2_L],eax
- adc [v2_H],edx
- ; v3 = rol(v3, 16)
- mov eax,[v3_L]
- mov esi,eax
- shr esi,10h
- mov eax,[v3_H]
- mov edi,eax
- shl edi,10h
- mov eax,[v3_H]
- mov ebx,eax
- shr ebx,10h
- mov eax,[v3_L]
- mov ecx,eax
- shl ecx,10h
- mov edx,esi
- or edx,edi
- mov eax,ebx
- or eax,ecx
- mov [v3_L],eax
- mov [v3_H],edx
- ; v3 ^= v2
- mov eax,[v2_L]
- mov edx,[v2_H]
- xor [v3_L],eax
- xor [v3_H],edx
- ; v0 += v3
- mov eax,[v3_L]
- mov edx,[v3_H]
- add [v0_L],eax
- adc [v0_H],edx
- ; v3 = rol(v3, 21)
- mov eax,[v3_L]
- mov esi,eax
- shr esi,0Bh
- mov eax,[v3_H]
- mov edi,eax
- shl edi,15h
- mov eax,[v3_H]
- mov ebx,eax
- shr ebx,0Bh
- mov eax,[v3_L]
- mov ecx,eax
- shl ecx,15h
- mov edx,esi
- or edx,edi
- mov eax,ebx
- or eax,ecx
- mov [v3_L],eax
- mov [v3_H],edx
- ; v3 ^= v0
- mov eax,[v0_L]
- mov edx,[v0_H]
- xor [v3_L],eax
- xor [v3_H],edx
- ; v2 += v1
- mov eax,[v1_L]
- mov edx,[v1_H]
- add [v2_L],eax
- adc [v2_H],edx
- ; v1 = rol(v1, 17)
- mov eax,[v1_L]
- mov esi,eax
- shr esi,0Fh
- mov eax,[v1_H]
- mov edi,eax
- shl edi,11h
- mov eax,[v1_H]
- mov ebx,eax
- shr ebx,0Fh
- mov eax,[v1_L]
- mov ecx,eax
- shl ecx,11h
- mov edx,esi
- or edx,edi
- mov eax,ebx
- or eax,ecx
- mov [v1_L],eax
- mov [v1_H],edx
- ; v1 ^= v2
- mov eax,[v2_L]
- mov edx,[v2_H]
- xor [v1_L],eax
- xor [v1_H],edx
- ; v2 = rol(v2, 32)
- mov eax,[v2_L]
- mov edx,[v2_H]
- mov [v2_L],edx
- mov [v2_H],eax
- pop ebx edi esi
- retn
- endp
В приложении пример программы с исходным текстом, которая считает хеш SipHash-2-4 для введенной строки.
Просмотров: 188 | Комментариев: 0
Комментарии
Отзывы посетителей сайта о статье
Комментариeв нет
Добавить комментарий
Заполните форму для добавления комментария
Пример программы с исходным текстом (FASM)
