base编码系列学习

 

一、base64编码

1.1表

  base64码表,“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/”。

1.2原理&分组

  将输入的字符串用base64字符表示,其中每3个字符可以用4个base64字符表示,根据字符表示的整数值对应base64码表进行转换。

1.3变化

  编码后的数据变更大了,三个字符变四个字符。

注:base64的索引表,base64字符选用了"A-Z、a-z、0-9、+、/" 64个字符。因为一共64个字符,可以用6位二进制位去表示。若剩余的输入字符不足三个,则用2个base64字符表示一个字符,空余的两个字符用“ == ”代替;用3个base64字符表示2个字符,空余的一个base64字符用 “ = ”。

1.4编/解码

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import base64
import string
 
#base64实现
base64_charset = string.ascii_uppercase + string.ascii_lowercase + string.digits + '+/'
 
 
def encode(origin_bytes):
     # 将每一位bytes转换为二进制字符串,{:0>8}意思是向右对齐,用0填充,长度为8
    base64_bytes = ['{:0>8}'.format(str(bin(b)).replace('0b', '')) for b in origin_bytes]
 
    resp = ''
    nums = len(base64_bytes) // 3
    remain = len(base64_bytes) % 3
 
    integral_part = base64_bytes[0:3 * nums]
    while integral_part:
        # 取三个字节,以每6比特,转换为4个整数
        tmp_unit = ''.join(integral_part[0:3])
        tmp_unit = [int(tmp_unit[x: x + 6], 2) for x in [0, 6, 12, 18]]
        # 取对应base64字符
        resp += ''.join([base64_charset[i] for i in tmp_unit])
        integral_part = integral_part[3:]
 
    if remain:
        # 补齐三个字节,每个字节补充 0000 0000
        remain_part = ''.join(base64_bytes[3 * nums:]) + (3 - remain) * '0' * 8
        # 取三个字节,以每6比特,转换为4个整数
        # 剩余1字节可构造2个base64字符,补充==;剩余2字节可构造3个base64字符,补充=
        tmp_unit = [int(remain_part[x: x + 6], 2) for x in [0, 6, 12, 18]][:remain + 1]
        resp += ''.join([base64_charset[i] for i in tmp_unit]) + (3 - remain) * '='
 
    return resp
 
 
def decode(base64_str):
    """
    解码base64字符串
    :param base64_str:base64字符串
    :return:解码后的bytearray;若入参不是合法base64字符串,返回空bytearray
    """
 
    # 对每一个base64字符取下标索引,并转换为6为二进制字符串
    base64_bytes = ['{:0>6}'.format(str(bin(base64_charset.index(s))).replace('0b', '')) for s in base64_str if
                    s != '=']
    resp = bytearray()
    nums = len(base64_bytes) // 4
    remain = len(base64_bytes) % 4
    integral_part = base64_bytes[0:4 * nums]
 
    while integral_part:
        # 取4个6位base64字符,作为3个字节
        tmp_unit = ''.join(integral_part[0:4])
        tmp_unit = [int(tmp_unit[x: x + 8], 2) for x in [0, 8, 16]]
        for i in tmp_unit:
            resp.append(i)
        integral_part = integral_part[4:]
 
    if remain:
        remain_part = ''.join(base64_bytes[nums * 4:])
        tmp_unit = [int(remain_part[i * 8:(i + 1) * 8], 2) for i in range(remain - 1)]
        for i in tmp_unit:
            resp.append(i)
 
    return resp
 
if __name__ == '__main__':
    s = b'One piece, all Blue'
    local_base64 = encode(s)
    print('使用本地base64加密:', local_base64)
    print('使用本地base64解密:', decode(local_base64).decode())
 
    b_base64 = base64.b64encode(s)
    print('使用base64加密:', b_base64)
    print('使用base64解密:', base64.b64decode(b_base64).decode())

 

 二、base16 编码

2.1表

  base16码表,“0123456789ABCDEF”。

2.2原理&分组

  将输入的字符串中的每一个字符拆成两部分,每部分4bit进行编码。

2.3变化

  编码后的数据变更大了,一个字符变两个字符。

2.4编/解码

1
2
3
4
5
6
#base16解码
import base64
#输入的数据必须是比特流
s = b'aaaa'
enc = base64.b16encode(s)
print(base64.b16decode(enc))

  

 三、base24 编码

3.1表

  base24码表,“BCDFGHJKMPQRTVWXY2346789”。

3.2原理&分组

  将输入的字符串中的每一个字符拆成两部分,每部分4bit进行编码,但是过程与base16有点不同,具体看代码实现。

3.3变化

  编码后的数据变更大了,一个字符变两个字符。

3.4编/解码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
static const char sel[] = {
    'B','C','D','F','G',
    'H','J','K','M','P',
    'Q','R','T','V','W',
    'X','Y','2','3','4',
    '6','7','8','9', '\0'};
  
char *b24e(char *buf, unsigned char *byst, size_t sizeOfBytes)
{
    int i = 0;
    unsigned char *p = byst;
    while ((size_t)(i = (p-byst)) < sizeOfBytes) {
        buf[2*i] = sel[((*p) >> 4)];
        buf[(2*i)+1] = sel[23 - ((*p) & 0x0f)];
        p++;
    }
    buf[(2*i)+1] = '\0';
    return buf;
}
  
unsigned char *b24d(unsigned char *buf, char *str, size_t countOfChars)
{
    size_t i;
    char *p = str;
    char *loc[2];
    unsigned char n[2];
    if (countOfChars % 2)
        return NULL;
    for (i = 0; i < (countOfChars>>1); i++) {
  
        loc[0] = strchr( sel, str[2*i] );
        loc[1] = strchr( sel, str[ ( 2*i ) + 1 ] );
        if (loc[0] == NULL || loc[1] == NULL)
            return NULL;
        n[0] = (unsigned char)( loc[0] - sel );
        n[1] = 23 - (unsigned char)( loc[1] - sel );
        buf[i] = (unsigned char)((n[0] << 4) | n[1]);
    }
    return buf;
}

  

 四、base32 编码

4.1表

  base32码表,“ABCDEFGHIJKLMNOPQRSTUVWXYZ234567”。

4.2原理&分组

  以5 bit为一组进行分组,对切分而成的每个组进行编码得到1个可显示字符。

4.3变化

  编码后的数据变更大了,每5个字符变8个字符。如果编码的字符串不足5的倍数,那么余下的部分用‘ = ’填充。

4.4编/解码

1
2
3
4
5
6
#base32解码
import base64
#输入的数据必须是比特流
s = b'aaaa'
enc = base64.b32encode(s)
print(base64.b32decode(enc))

 

五、base58 编码

5.1表

  base58码表,“123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz”。

5.2原理&分组

  不再以根据位分组的方式进行编码,而是通过辗转相除法的方式去编码。实质上就是将每个字符变成一个大整数,然后用58进制去表示,然后这个58进制里面每一位进行编码。(注:base62好像也是这样,暂时先放着。)

5.3变化

  编码后的数据变更大了,具体变多大还得看编码的数据内容。

5.4编/解码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
def b58encode(tmp:str) -> str:
    tmp = list(map(ord,tmp))
    temp = tmp[0]
    base58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
    for i in range(len(tmp)-1):
        temp = temp * 256 + tmp[i+1]
    tmp = []
    while True:
        tmp.insert(0,temp % 58)
        temp = temp // 58
        if temp == 0:
            break
    temp = ""
    for i in tmp:
        temp += base58[i]
    return temp
 
def b58decode(tmp:str) -> str:
    import binascii
    base58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
    temp = []
    for i in tmp:
        temp.append(base58.index(i))
    tmp = temp[0]
    for i in range(len(temp)-1):
        tmp = tmp * 58 + temp[i+1]
    return binascii.unhexlify(hex(tmp)[2:].encode("utf-8")).decode("UTF-8")
 
print(b58encode("ABDCDEFGA"))
print(b58decode("qBLiPgShKjap"))

  

六、base60 编码

6.1表

  base60码表,“0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx”。

6.2原理&分组

  未知。

 

 

6.3变化

  未知。

6.4编/解码

1
https://github.com/chai2010/base60

  

 

posted @   An2i  阅读(646)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2019-07-02 Ubantu ping通IP,ping不通baidu
点击右上角即可分享
微信分享提示