Blog. Just Blog

Кодирование и декодирование чисел по алгоритму Base58

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Base58 - вариант кодирования чисел в виде буквенно-цифрового текста на основе цифр и символов латинского алфавита. Алфавит Base58, как можно догадаться из названия, содержит 58 символов. Base58 был разработан для передачи данных и уменьшения количества ошибок у пользователей, которые вручную вводят данные на основе распечатанного текста или фотографии, то есть без возможности машинного копирования и вставки. Так, к примеру, Base58 используется для кодирования идентификаторов кошельков Bitcoin, для создания коротких ссылок на фотохостингах и т.п. В отличие от кодирования Base64, позволяющего работать с неограниченными объемами двоичных данных, Base58 предназначен для кодирования только одиночных числовых значений.

Согласно спецификации, в алфавит Base58 не входят буквенно-цифровые символы, которые имеют сходное написание и могут неоднозначно восприниматься человеком (например, буква "О" и цифра "0"), а также символы, используемые при формировании URL. Вместе с тем, порядок следования символов в алфавите ничем не регламентирован, зависит только от сферы применения кодирования и может быть любым. Для этой статьи я выбрал следующий алфавит Base58:
  1. alpha db '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'
  2. alpha_len=$-alpha
Использования своего собственного порядка символов также позволяет добавить немного секурности вашему проекту, затрудняя перебор последовательных идентификаторов. Но вы должны понимать, что целиком надеяться на это ни в коем случае не стоит.

Теперь переходим к функции кодирования. Из-за использования 32-битной математики, максимальное значение, доступное для кодирования, не может превышать 0xFFFFFFFFh
  1. ;-----------------------------------------------------
  2. ; Кодирование числа по алгоритму Base58
  3. ;-----------------------------------------------------
  4. proc base58_encode dValue:DWORD, szOut:DWORD
  5.         pusha
  6.  
  7.         mov     edi,[szOut]
  8.         mov     eax,[dValue]
  9.         mov     ecx,alpha_len
  10. @@:
  11.         xor     edx,edx
  12.         div     ecx
  13.         push    eax
  14.         mov     al,byte [alpha+edx]
  15.         stosb
  16.         pop     eax
  17.         or      eax,eax
  18.         jnz     @b
  19.         stosb
  20.  
  21.         popa
  22.         ret
  23. endp
Параметры вызова: dValue - кодируемое число, szOut - указатель на память, куда будет записана строка в формате ASCIIZ c закодированным значением.

А вот функция для обратного декодирования строки из Base58 в числовое значение:
  1. ;-----------------------------------------------------
  2. ; Декодирование строки в число по алгоритму Base58
  3. ;-----------------------------------------------------