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. ;-----------------------------------------------------
  4. proc base58_decode szIn:DWORD
  5.         locals
  6.                 res dd ?
  7.         endl
  8.  
  9.         pusha
  10.  
  11.         mov     esi,[szIn]
  12.         mov     ebx,1
  13.         mov     [res],0
  14. @@:
  15.         lodsb
  16.         or      al,al
  17.         jz      @f
  18.  
  19.         mov     edi,alpha
  20.         mov     ecx,alpha_len
  21.         repne   scasb
  22.         inc     ecx
  23.         neg     ecx
  24.         add     ecx,alpha_len
  25.         mov     eax,ebx
  26.         imul    eax,ecx
  27.         add     [res],eax
  28.  
  29.         imul    ebx,alpha_len
  30.         jmp     @b
  31. @@:
  32.         popa
  33.  
  34.         ; Результат
  35.         mov     eax,[res]
  36.         ret
  37. endp
Единственный параметр вызова - szIn - указатель на строку, содержащую закодированное число. Опять же из-за использования 32-битной математики оно не должно превышать 0xFFFFFFFF. Декодированное число возвращается в регистре EAX. Также здесь предполагается, что строка содержит корректные символы из алфавита Base58, никаких дополнительных проверок по этому поводу не производится. В реальных проектах надо в обязательном порядке проверять все данные, полученные извне.

В приложении примеры программ с исходными текстами для кодирования чисел по алгоритму Base58 и для декодирования полученных строк обратно в числа.

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

Base58.Demo.zip (4,625 bytes)


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

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
ManHunter (10.02.2020 в 17:10):
Нет, и этой темой вообще не интересуюсь.
cTpaHHuK (10.02.2020 в 17:02):
ManHunter, а у тебя нет примера функций на асме как кодировать , декодировать base58 адреса и приватные ключи в биткоине?
ManHunter (25.02.2019 в 08:15):
Так он для чисел и предназначен, чтобы в ссылке указывать не /article/1234, а что-то типа /article/fjR. Про BigInt согласен.
DimitarSerg (25.02.2019 в 05:59):
Хм, странно работает, оно получается кодирует именно hex-value (точнее даже dec), а не ascii, но и в этом случае работает не то чтобы криво, но не по стандарту, пример: у тебя 12 кодируется в d, но в моем коде d декодируется в 0x0C.
А так то все эти бейзы реализовываются одной функцией с передачей в ней длинны алфавита и, собственно, самого алфавита, нюанс - использовать либу для больших чисел нужно, если язык из коробки не поддерживает.

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

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

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