base加密算法

在初期的学习中我们总是工具和脚本小子,这里想再次来学习这个熟悉的加密,巩固好再深入的学习

1.前言

我们再很多场景下可以看到base64加密处理的数据,为什么呢?

1.由来

最早的电子邮件只允许asc码传输,但是当存在非asc码的数据时,但是在传输时网关的解析会导致这个邮件直接变成乱码,所以衍生出base64算法来处理这个问题

2.定义

1.官方定义文件

ietf.org/rfc/rfc2045.txt

2.概述

base64算法是基于64个字符的编码算法,经过处理后的数据会变成原来长度的4/3倍,所以处理后的长度肯定为4的倍数

结合前面的来源,在规定中邮件的每一行数据为76个字符,并且每一行末都必须要有一个\r\n符号,即使这一行并没有满76个字符

(正常来说\r表示回到该行的开始,\n表示移动到下一行的开始,这里因为规范所以要组合使用,属于CRLF(Carriage Return Line Feed)约定)

3.字符映射表

根据官方的文档的对应码表

Freed & Borenstein          Standards Track                    [Page 24]

RFC 2045                Internet Message Bodies            November 1996


                   Table 1: The Base64 Alphabet

    Value Encoding  Value Encoding  Value Encoding  Value Encoding
        0 A            17 R            34 i            51 z
        1 B            18 S            35 j            52 0
        2 C            19 T            36 k            53 1
        3 D            20 U            37 l            54 2
        4 E            21 V            38 m            55 3
        5 F            22 W            39 n            56 4
        6 G            23 X            40 o            57 5
        7 H            24 Y            41 p            58 6
        8 I            25 Z            42 q            59 7
        9 J            26 a            43 r            60 8
       10 K            27 b            44 s            61 9
       11 L            28 c            45 t            62 +
       12 M            29 d            46 u            63 /
       13 N            30 e            47 v
       14 O            31 f            48 w         (pad) =
       15 P            32 g            49 x
       16 Q            33 h            50 y

value是指10进制编码

encoding是指字符(对应64个字符=26个英文字符大小写+10个数字+’+和/’)

=是用来补位的字符

4.衍生

由此衍生出很多base家族的算法

在http请求中的以get传参衍生出url base64算法,将原本base64中的62和63位替换为-_符号,并且将补位符号替换为.

但是注:Bouncy Castle使用”.”作为补位符,而Commons Codec则完全杜绝使用补位符

参考:ietf.org/rfc/rfc4648.txt

衍生出base32等算法

3.base64算法和加密

  1. Base64用途:用于“加密”数据,但不能视为真正的加密算法
  2. 原理:采用单表置换算法,将原文转为二进制,通过字符映射表生成“密文”
  3. 公开性问题
    • Base64算法公开,不违背柯克霍夫原则
    • 字符映射表公开,违背了柯克霍夫原则
  4. 加密强度:Base64加密强度不高,不能被视为现代加密算法
  5. 学习价值:遵循单表置换算法规则,是学习加密算法的良好范例
  6. 改造潜力:通过改造Base64算法并保密字符映射表,可以赋予其加密意义
  7. 常用用途:常用于密钥、密文和证书的存储编码格式,与加密算法密不可分

2.加密实现

1.简述

  1. 将给定的字符串转换为字符编码(asc码等)
  2. 将字符编码转换为二进制码
  3. 对二进制码,分组转换(将每三个8位二进制为一组转换为4个6位二进制为一组,不足6位时,低位补0)
  4. 对生成的4个6位二进制数据高位添加2位0,变成4个8位二进制数据
  5. 将得到的4个8位二级制数据转换为10进制码
  6. 获得的10进制对照码表进行转换

2.演示示例

1.ASCII码字符编码

字符             A
ASCII码         65
二进制码         01000001
4-6二进制码      010000       010000
4-8二进制码      00010000     00010000
十进制码         16           16
字符表映射码      Q            Q           =   =

结果转换为QQ==,这里的补位=

补位原理解析:这里进行处理的最小数据时3个8位即是24位数据,处理后刚好是4的倍数,但是这里因为原本的数据不是3的倍数,存在补位,所以要在后面补齐,并且因为原始数据满足3的倍数就不存在补位,所以我们最多补位的=是两个

2.非ASCII码字符编码

asc编码的范围有限,无法显示中文等其他,所以这个地方我们采用UTF-8来进行编码,UTF-8编码采用3个字节表示一个汉字,而6位二进制码添加高2位0的处理可以解决网关无法解析的问题

字符     汉
UTF-8码     -26       -89     -124
二进制码     11011010   10101011 10000100
4-6二进制码 110110     101010   101110   000100
4-8二进制码 00110110   00101010 00101110 00000100
十进制码     54         42       46       4
字符表映射码 2         q       u       E

3.加密实现

1.c语言

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Base64 字符表
const char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

// Base64 加密函数
char* base64_encode(const unsigned char *input, size_t input_len) {
   size_t output_len = 4 * ((input_len + 2) / 3); //确保填充
   char *encoded = (char *)malloc(output_len + 1); //分配空间存储输出后的代码

   if (encoded == NULL) return NULL;

   size_t i, j;
   for (i = 0, j = 0; i < input_len;) {
       uint32_t octet_a = i < input_len ? input[i++] : 0;//从输入数据中读取第一个字节,如果 i 小于 input_len(数组索引未越界),则取对应的字节值并将 i 自增;否则设为0
       uint32_t octet_b = i < input_len ? input[i++] : 0;
       uint32_t octet_c = i < input_len ? input[i++] : 0;

       uint32_t triple = (octet_a << 16) + (octet_b << 8) + octet_c;//将这三个字节组合成一个24位的数值 triple,分别左移16位、8位和0位后相加得到

       encoded[j++] = base64_table[(triple >> 18) & 0x3F];//取 triple 的高6位(右移18位后与 0x3F 进行与操作)对应的Base64字符
       encoded[j++] = base64_table[(triple >> 12) & 0x3F];//取接下来6位的字符
       encoded[j++] = base64_table[(triple >> 6) & 0x3F];//最后取剩余的低6位对应的字符
       encoded[j++] = base64_table[triple & 0x3F];//将 triple 变量中的低6位(即 triple & 0x3F 的结果)转换成对应的 Base64 字符,并将其存储到 encoded 数组中的当前位置j
  }

   // 填充 '='
   for (i = 0; i < (3 - input_len % 3) % 3; i++) {
       encoded[output_len - 1 - i] = '=';
  }

   encoded[output_len] = '\0';
   return encoded;
}

int main() {
   const char *input = "Hello, World!";
   size_t input_len = strlen(input);

   // 对输入字符串进行 Base64 加密
   char *encoded = base64_encode((const unsigned char *)input, input_len);
   if (encoded) {
       printf("Base64 加密结果: %s\n", encoded);
       free(encoded);
  } else {
       printf("失败.\n");
  }

   return 0;
}

2.python实现

直接用库不香嘛

import base64

def base64_encode(input_string):
   # 将输入的字符串转换为字节序列
   input_bytes = input_string.encode('utf-8')
   
   # 使用Python标准库中的base64编码函数
   encoded_bytes = base64.b64encode(input_bytes)
   
   # 将编码后的字节序列转换回UTF-8编码的字符串
   encoded_string = encoded_bytes.decode('utf-8')
   
   return encoded_string

# 示例用法:
input_string = "hello"
encoded_string = base64_encode(input_string)
print("Base64编码结果:", encoded_string)

3.x86汇编实现

section .data
   input db 'Hello, World!', 0
   base64_table db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', 0
   output db 22 dup(0) ; Base64编码结果最多是原始数据的4/3长度
   len equ $ - input

section .text
   global _start

_start:
   ; 初始化寄存器
   mov esi, input      ; 输入数据指针
   mov edi, output     ; 输出数据指针
   xor eax, eax        ; 清空eax
   xor ebx, ebx        ; 清空ebx
   xor ecx, ecx        ; 清空ecx

encode_loop:
   ; 读取3个字节到eax
   mov al, byte [esi]
   mov ah, byte [esi + 1]
   mov dl, byte [esi + 2]

   ; 第一个6位块
   mov bl, al
   shr bl, 2
   movzx ebx, byte [base64_table + ebx]
   mov [edi], bl

   ; 第二个6位块
   mov bl, al
   and bl, 3
   shl bl, 4
   mov bh, ah
   shr bh, 4
   or bl, bh
   movzx ebx, byte [base64_table + ebx]
   mov [edi + 1], bl

   ; 第三个6位块
   mov bl, ah
   and bl, 15
   shl bl, 2
   mov bh, dl
   shr bh, 6
   or bl, bh
   movzx ebx, byte [base64_table + ebx]
   mov [edi + 2], bl

   ; 第四个6位块
   mov bl, dl
   and bl, 63
   movzx ebx, byte [base64_table + ebx]
   mov [edi + 3], bl

   ; 更新指针和计数器
   add esi, 3
   add edi, 4
   sub len, 3
   jg encode_loop

   ; 处理剩余字节
   cmp len, 1
   je encode_last_byte
   cmp len, 2
   je encode_last_two_bytes
   jmp done

encode_last_byte:
   ; 处理最后一个字节
   mov al, byte [esi]
   mov bl, al
   shr bl, 2
   movzx ebx, byte [base64_table + ebx]
   mov [edi], bl
   mov bl, al
   and bl, 3
   shl bl, 4
   movzx ebx, byte [base64_table + ebx]
   mov [edi + 1], bl
   mov byte [edi + 2], '='
   mov byte [edi + 3], '='
   jmp done

encode_last_two_bytes:
   ; 处理最后两个字节
   mov al, byte [esi]
   mov ah, byte [esi + 1]
   mov bl, al
   shr bl, 2
   movzx ebx, byte [base64_table + ebx]
   mov [edi], bl
   mov bl, al
   and bl, 3
   shl bl, 4
   mov bh, ah
   shr bh, 4
   or bl, bh
   movzx ebx, byte [base64_table + ebx]
   mov [edi + 1], bl
   mov bl, ah
   and bl, 15
   shl bl, 2
   movzx ebx, byte [base64_table + ebx]
   mov [edi + 2], bl
   mov byte [edi + 3], '='

done:
   ; 系统调用退出
   mov eax, 1
   xor ebx, ebx
   int 0x80

2.ARMv7汇编实现

section .data
   input db 'Hello, World!', 0
   base64_table db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', 0
   output db 22 dup(0) ; Base64编码结果最多是原始数据的4/3长度
   len equ $ - input

section .text
   global _start

_start:
   ; 初始化寄存器
   mov esi, input      ; 输入数据指针
   mov edi, output     ; 输出数据指针
   xor eax, eax        ; 清空eax
   xor ebx, ebx        ; 清空ebx
   xor ecx, ecx        ; 清空ecx

encode_loop:
   ; 读取3个字节到eax
   mov al, byte [esi]
   mov ah, byte [esi + 1]
   mov dl, byte [esi + 2]

   ; 第一个6位块
   mov bl, al
   shr bl, 2
   movzx ebx, byte [base64_table + ebx]
   mov [edi], bl

   ; 第二个6位块
   mov bl, al
   and bl, 3
   shl bl, 4
   mov bh, ah
   shr bh, 4
   or bl, bh
   movzx ebx, byte [base64_table + ebx]
   mov [edi + 1], bl

   ; 第三个6位块
   mov bl, ah
   and bl, 15
   shl bl, 2
   mov bh, dl
   shr bh, 6
   or bl, bh
   movzx ebx, byte [base64_table + ebx]
   mov [edi + 2], bl

   ; 第四个6位块
   mov bl, dl
   and bl, 63
   movzx ebx, byte [base64_table + ebx]
   mov [edi + 3], bl

   ; 更新指针和计数器
   add esi, 3
   add edi, 4
   sub len, 3
   jg encode_loop

   ; 处理剩余字节
   cmp len, 1
   je encode_last_byte
   cmp len, 2
   je encode_last_two_bytes
   jmp done

encode_last_byte:
   ; 处理最后一个字节
   mov al, byte [esi]
   mov bl, al
   shr bl, 2
   movzx ebx, byte [base64_table + ebx]
   mov [edi], bl
   mov bl, al
   and bl, 3
   shl bl, 4
   movzx ebx, byte [base64_table + ebx]
   mov [edi + 1], bl
   mov byte [edi + 2], '='
   mov byte [edi + 3], '='
   jmp done

encode_last_two_bytes:
   ; 处理最后两个字节
   mov al, byte [esi]
   mov ah, byte [esi + 1]
   mov bl, al
   shr bl, 2
   movzx ebx, byte [base64_table + ebx]
   mov [edi], bl
   mov bl, al
   and bl, 3
   shl bl, 4
   mov bh, ah
   shr bh, 4
   or bl, bh
   movzx ebx, byte [base64_table + ebx]
   mov [edi + 1], bl
   mov bl, ah
   and bl, 15
   shl bl, 2
   movzx ebx, byte [base64_table + ebx]
   mov [edi + 2], bl
   mov byte [edi + 3], '='

done:
   ; 系统调用退出
   mov eax, 1
   xor ebx, ebx
   int 0x80

3.MIPS汇编实现

看看就行,这破东西不是人写的

.data
input: .asciiz "Hello, World!"   # 输入字符串
base64_table: .asciiz "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"  # Base64字符表
output: .space 22               # 输出缓冲区,大小为22字节

.text
.globl main

main:
   la $t0, input          # 加载输入字符串指针到$t0
   la $t1, output         # 加载输出缓冲区指针到$t1
   la $t2, base64_table   # 加载Base64字符表指针到$t2

encode_loop:
   lb $t3, 0($t0)         # 读取第一个字节
   lb $t4, 1($t0)         # 读取第二个字节
   lb $t5, 2($t0)         # 读取第三个字节

   srl $t6, $t3, 2        # 处理第一个6位块
   lb $t6, ($t2, $t6)
   sb $t6, 0($t1)

   sll $t6, $t3, 4
   srl $t6, $t6, 2
   srl $t7, $t4, 4
   or $t6, $t6, $t7       # 处理第二个6位块
   andi $t6, $t6, 0x3F
   lb $t6, ($t2, $t6)
   sb $t6, 1($t1)

   sll $t6, $t4, 2
   srl $t6, $t6, 2
   srl $t7, $t5, 6
   or $t6, $t6, $t7       # 处理第三个6位块
   andi $t6, $t6, 0x3F
   lb $t6, ($t2, $t6)
   sb $t6, 2($t1)

   andi $t6, $t5, 0x3F    # 处理第四个6位块
   lb $t6, ($t2, $t6)
   sb $t6, 3($t1)

   addi $t0, $t0, 3       # 更新输入指针
   addi $t1, $t1, 4       # 更新输出指针

   la $t7, input
   addi $t7, $t7, 13      # 输入字符串结束位置(假设输入长度为13)
   bne $t0, $t7, encode_loop

done:
   li $v0, 10             # syscall number (sys_exit)
   syscall                # 调用内核退出

4.base64解密实现

c语言实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Base64 字符集
const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";

// 查找给定字符在 Base64 字符集中的索引
int base64_char_value(char c) {
const char *p = strchr(base64_chars, c);
if (p) {
return p - base64_chars;
}
return -1; // 不合法字符返回 -1
}

// 解码 Base64 字符串
unsigned char* base64_decode(const char *input, size_t *output_len) {
size_t input_len = strlen(input);
// 验证输入长度
if (input_len % 4 != 0) {
return NULL; // 不合法的 Base64 输入
}

size_t output_buf_len = input_len / 4 * 3;
if (input[input_len - 1] == '=') output_buf_len--;
if (input[input_len - 2] == '=') output_buf_len--;

unsigned char *output = (unsigned char*)malloc(output_buf_len);
if (output == NULL) {
return NULL; // 内存分配失败
}

size_t o = 0;
for (size_t i = 0; i < input_len;) {
int sextet_a = input[i] == '=' ? 0 & i++ : base64_char_value(input[i++]);
int sextet_b = input[i] == '=' ? 0 & i++ : base64_char_value(input[i++]);
int sextet_c = input[i] == '=' ? 0 & i++ : base64_char_value(input[i++]);
int sextet_d = input[i] == '=' ? 0 & i++ : base64_char_value(input[i++]);

if (sextet_a == -1 || sextet_b == -1 || sextet_c == -1 || sextet_d == -1) {
free(output);
return NULL; // 不合法字符
}

unsigned int triple = (sextet_a << 18)
+ (sextet_b << 12)
+ (sextet_c << 6)
+ sextet_d;

if (o < output_buf_len) output[o++] = (triple >> 16) & 0xFF;
if (o < output_buf_len) output[o++] = (triple >> 8) & 0xFF;
if (o < output_buf_len) output[o++] = triple & 0xFF;
}

*output_len = output_buf_len;
return output;
}

int main() {
const char *encoded_string = "SGVsbG8gV29ybGQ=";
size_t decoded_len;

unsigned char *decoded_data = base64_decode(encoded_string, &decoded_len);
if (decoded_data != NULL) {
printf("Decoded data: ");
for (size_t i = 0; i < decoded_len; ++i) {
putchar(decoded_data[i]);
}
printf("\n");
free(decoded_data); // 释放分配的内存
} else {
printf("Failed to decode Base64 string.\n");
}

return 0;
}

python实现

import base64

def base64_decode(encoded_string):
# 使用 base64.b64decode 函数解码
decoded_bytes = base64.b64decode(encoded_string)
return decoded_bytes

def main():
encoded_string = "SGVsbG8gV29ybGQ="
decoded_data = base64_decode(encoded_string)

print("Decoded data:", decoded_data)
print("Decoded string:", decoded_data.decode('utf-8'))

if __name__ == "__main__":
main()

5.拓展base32

这就简单说说base32

Base32 是一种基于 32 个字符的编码方案,用于将二进制数据编码成可打印的 ASCII 字符串

Base32 编码主要用于在不支持二进制数据的环境中传输数据,例如在某些邮件系统和 URL 中

Base32 字母表

Base32 字母表由以下 32 个字符组成:

ABCDEFGHIJKLMNOPQRSTUVWXYZ234567

即:

  • 大写字母 A-Z
  • 数字 2-7

Base32 编码过程

Base32 编码过程如下:

  1. 将输入数据按 5 个比特一组进行分组(因为 2^5 = 32,五个比特可以表示一个 Base32 字符)
  2. 填充不足的比特。如果最后一个组的比特数不足 5 位,需要进行零填充,使其长度达到 5 位
  3. 将每个组转换成 Base32 字母表中的字符
  4. 在编码结尾添加填充字符。如果最后一个组经过零填充,那么在结尾会添加相应数量的 = 号使其长度达到最近的 8 的倍数

Base32 示例

例如要编码以下 ASCII 字符串:

"Hello"
  1. 将其转换成二进制:
H: 01001000
e: 01100101
l: 01101100
l: 01101100
o: 01101111

合并成一个二进制字符串:
01001000 01100101 01101100 01101100 01101111
  1. 按 5 个比特为一组进行分组:
01001 00001 10010 10110 11000 11011 00110 11111
  1. 将每个组转换成 Base32 字母表中的字符:
01001 (9)   -> J
00001 (1) -> B
10010 (18) -> S
10110 (22) -> W
11000 (24) -> Y
11011 (27) -> 3
00110 (6) -> G
11111 (31) -> 7
  1. 结果:
Hello -> JBSWY3DP

Python 中的 Base32 编码

在 Python 中,可以通过标准库 base64 来进行 Base32 编码和解码。示例如下:

import base64

def base32_encode(data):
# 使用 base64.b32encode 进行 Base32 编码
encoded_data = base64.b32encode(data.encode('utf-8'))
return encoded_data.decode('utf-8')

def base32_decode(encoded_data):
# 使用 base64.b32decode 进行 Base32 解码
decoded_bytes = base64.b32decode(encoded_data)
return decoded_bytes.decode('utf-8')

def main():
original_data = "Hello"
encoded_data = base32_encode(original_data)
print("Encoded data:", encoded_data)

decoded_data = base32_decode(encoded_data)
print("Decoded data:", decoded_data)

if __name__ == "__main__":
main()

运行上述代码将显示:

Encoded data: JBSWY3DP
Decoded data: Hello
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇