Функции base64 на Ассемблере

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

Алгоритм Base64 использует две функции - кодирования данных и обратного декодирования. Для обеих функций кодирования и декодирования предварительно инициализируются следующие вспомогательные данные:
section '.data' data readable writeable
...
base64_table db "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
             db "abcdefghijklmnopqrstuvwxyz"
             db "0123456789+/"
 
decode_table rb 100h
...

А вот сами функции для работы с Base64:
;---------------------------------------------------------------
; Функция кодирования Base64
; Параметры:
; dFrom - указатель на исходные данные
; dTo   - указатель на буфер для приема кодированных данных
; dSize - размер исходных данных
; Функция ничего не возвращает
;---------------------------------------------------------------
proc    base64_encode dFrom:dword, dTo:dword, dSize:dword
        push    eax ecx edx esi edi
 
        mov     esi,[dFrom]
        mov     edi,[dTo]
        mov     ecx,[dSize]
 
        or      ecx,ecx
        jz      .r3
.encode_loop:
        lodsd
        mov     edx,eax
        cmp     ecx,3
        jae     .remainder_ok
        and     edx,0ffffh
        cmp     ecx,2
        jae     .remainder_ok
        and     edx,0ffh
.remainder_ok:
        bswap   edx
 
        mov     eax,edx
        shr     eax,26
        and     eax,00111111b
        mov     al,[base64_table+eax]
        stosb
 
        mov     eax,edx
        shr     eax,20
        and     eax,00111111b
        mov     al,[base64_table+eax]
        stosb
        dec     ecx
        jz      .r2
 
        mov     eax,edx
        shr     eax,14
        and     eax,00111111b
        mov     al,[base64_table+eax]
        stosb
        dec     ecx
        jz      .r1
 
        mov     eax,edx
        shr     eax,8
        and     eax,00111111b
        mov     al,[base64_table+eax]
        stosb
 
        dec     esi
        dec     ecx
        jnz     .encode_loop
 
        jmp     .r3
.r2:
        mov     al,'='
        stosb
.r1:
        mov     al,'='
        stosb
.r3:
        xor     eax,eax
        stosb
        pop     edi esi edx ecx eax
        ret
endp

В этой функции все параметры обязательные. Размер буфера-приемника должен быть примерно в 1,5 раза больше исходных данных, это обусловлено особенностями алгоритма кодирования.
;---------------------------------------------------------------
; Функция декодирования Base64
; Параметры:
; dFrom - указатель на кодированные данные
; dTo   - указатель на буфер для приема декодированных данных
; dSize - размер кодированных данных, необязательный параметр
; На выходе:
; EAX - длина декодированных данных
;---------------------------------------------------------------
proc    base64_decode dFrom:dword, dTo:dword, dSize:dword
        ; Если длина строки не указана, то рассчитать
        cmp     [dSize],0
        jnz     .len_not_zero
        ; Штатную функцию API не используем
        stdcall _lstrlen,[dFrom]
        mov     [dSize],eax
        cmp     eax,0
        jnz     .len_not_zero
        ; Если длина нулевая, то вернуть пустую строку
        mov     byte [dTo],0
        xor     eax,eax
        ret
.len_not_zero:
        push    ebx ecx edx esi edi
 
        mov     ecx,[dSize]
        mov     esi,[dFrom]
        mov     edi,[dTo]
 
        xor     eax,eax
        mov     ebx,63
.make_table:
        mov     al,[base64_table+ebx]
        mov     [decode_table+eax],bl
        dec     ebx
        jns     .make_table
        mov     [decode_table+'='],0
        xor     ebx,ebx
.load_dword:
        mov     edx,[esi]
        bswap   edx
        add     esi,4
        mov     al,dl
        mov     al,byte[decode_table+eax]
        shrd    ebx,eax,6
        shr     edx,8
        mov     al,dl
        mov     al,byte[decode_table+eax]
        shrd    ebx,eax,6
        shr     edx,8
        mov     al,dl
        mov     al,byte[decode_table+eax]
        shrd    ebx,eax,6
        shr     edx,8
        mov     al,dl
        mov     al,byte[decode_table+eax]
        shrd    ebx,eax,6
        bswap   ebx
        mov     [edi],ebx
        add     edi,3
        sub     ecx,4
        js      .exit_loop
        jnz     .load_dword
.exit_loop:
        mov     byte[edi],0
        inc     edi
        mov     eax,[dTo]
        sub     edi,eax
        mov     eax,edi
        dec     eax
        pop     edi esi edx ecx ebx
        ret
endp
 
;---------------------------------------------------------------
; Вспомогательная функция для расчета длины строки
; Параметры:
; lpBuff - указатель на строку в формате ASCIIZ
; На выходе:
; EAX - длина строки
;---------------------------------------------------------------
proc    _lstrlen lpBuff:dword
        push    edi ecx
        mov     edi,[lpBuff]
        xor     ecx,ecx
        dec     ecx
        xor     eax,eax
        repne   scasb
        not     ecx
        dec     ecx
        mov     eax,ecx
        pop     ecx edi
        ret
endp

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

Пример использования обеих функций:
section '.data' data readable writeable
...
base64_table db "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
             db "abcdefghijklmnopqrstuvwxyz"
             db "0123456789+/"
 
decode_table rb 100h
 
str1         db 'ManHunter / PCL'             ; Строка для кодирования
str2         db 'SGF2ZSBhIE5pY2UgRGF5IQ==',0  ; Закодированная строка
buffer       rb 100h                          ; Буфер-приемник
 
section '.code' code readable executable
        ...
        ; Закодировать строку. Длина строки обязательно указывается
        stdcall base64_encode,str1,buff,15
        ; Теперь buff содержит кодированную строку 'TWFuSHVudGVyIC8gUENM'
        ...
        ; Раскодировать строку. Длина рассчитается автоматически
        stdcall base64_decode,str2,buff,NULL
        ; buff содержит раскодированную строку 'Have a Nice Day!'
        ...
Теги:
base64
Добавлено: 10 Апреля 2018 19:52:06 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...