base家族编码详解

base家族编码包含多种编码方式,每种都有不同的特点,本篇文章从初学的角度学习一下base家族编码。base家族编码是较为基础的加密算法,需要掌握;

base16编码

base16编码也称为十六进制编码或Hex编码,是一种将二进制数据表示为十六进制数字和字符的方法。它使用16个字符(0-9和A-F)来表示4位二进制数的每个组合。

编码原理:

由于4bit就可以表示2^4 = 16个字符。所以用4bit可以表示所有的十六进制数。

1byte=8bit 所以1byte = 俩个十六进制数据。

这里就涉及一个字节序的问题:是用大端模式还是小端模式?Base16编码明确表明是用小端模式存储。

编码过程:

1.将二进制数据分割为4个一组

2.映射,将每四位二进制数据映射到对应的base16字符。如下:

0000 -> 0
0001 -> 1
0010 -> 2
0011 -> 3
0100 -> 4
0101 -> 5
0110 -> 6
0111 -> 7
1000 -> 8
1001 -> 9
1010 -> A
1011 -> B
1100 -> C
1101 -> D
1110 -> E
1111 -> F

3.编码

4.填充(可选):若二进制数据不是4的倍数,就在后面填充0;

base32编码

Base32编码是一种将二进制数据转换为使用32个不同字符表示的文本编码方式

由于5bit就可以表示2^5 = 32个字符。所以base32就是将二进制数据分割成5个一组,如果结尾不满足5的倍数,就用“=”填充,之后再根据base32索引表,进行编码。

base32索引表

00000 -> A
00001 -> B
00010 -> C
00011 -> D
00100 -> E
00101 -> F
00110 -> G
00111 -> H
01000 -> I
01001 -> J
01010 -> K
01011 -> L
01100 -> M
01101 -> N
01110 -> O
01111 -> P
10000 -> Q
10001 -> R
10010 -> S
10011 -> T
10100 -> U
10101 -> V
10110 -> W
10111 -> X
11000 -> Y
11001 -> Z
11010 -> 2
11011 -> 3
11100 -> 4
11101 -> 5
11110 -> 6
11111 -> 7

 Base32编码通常用于需要在文本环境中表示二进制数据的场景,例如电子邮件中的附件编码、URL中的参数传递等。

base58编码

Base58编码是一种将二进制数据转换为文本编码的方法,通常用于表示加密货币地址和其他数据。

原理:

  1. 准备要编码的二进制数据: 将要编码的二进制数据准备好,通常是字节的形式。

  2. 添加版本前缀(可选): 在某些应用中,可以在二进制数据前添加一个版本前缀,以标识数据的类型或用途。这是可选的步骤,具体取决于编码的需求。

  3. 计算校验和(可选): 在某些情况下,可以计算二进制数据的校验和并附加到数据的末尾,以增加数据的完整性和安全性。这也是可选的步骤。

  4. Base58编码: 将经过前两步(添加版本前缀和计算校验和,如果适用)的二进制数据转换为Base58编码的文本。编码过程如下:

    • Base58字符集通常包括58个字符,通常是由除去易混淆的字符(如0、O、I和l)以及可能引起歧义的字符(如+和/)的字符集构成。
    • 将二进制数据视为一个大整数,使用Base58字符集中的字符作为数字的基数。
    • 将大整数除以58,记录余数,并继续除以58,直到商为零。这将生成Base58编码的每个字符。
    • 最后,反转生成的字符顺序以获得最终的Base58编码字符串。
  5. 输出Base58编码: 最终得到的Base58编码字符串就是表示输入二进制数据的文本表示形式。

Base58编码的主要特点是它不包含易混淆的字符和可能引起歧义的字符,以增加可读性,并且在加密货币领域非常常见。请注意,Base58编码不是标准编码,不同的实现可能有略微不同的字符集和特殊规则。不同的加密货币可能会使用不同的Base58编码方案。

base58索引表:

base64编码

Base64编码是一种将二进制数据转换为文本编码的方法,通常用于在文本协议中传输二进制数据,如电子邮件附件或在URL中传递数据。

原理:

  1. 准备要编码的二进制数据: 将要编码的二进制数据准备好,通常是字节的形式。

  2. 分组: 将二进制数据分成固定大小的组,每组通常为3字节(24位)。如果最后一组不足3字节,通常需要进行填充,以便每组都有3字节。

  3. 将每个组的二进制数据转换为十进制: 将每个3字节的二进制数据视为一个8bit*3=24bit位的二进制整数,再转化为一个十进制整数。

  4. Base64编码: 将每个十进制整数编码为Base64字符。

    • Base64字符集通常包括64个字符,通常是大写字母A到Z、小写字母a到z、数字0到9以及两个额外的字符(通常是"+"和"/")。
    • 以24位整数为例,将它分成4组,每组6位。这4组6位整数将被编码为4个Base64字符。
    • 每个6位整数对应一个Base64字符,根据其在Base64字符集中的位置来选择。
    • 如果原始数据不足3字节,会添加一个或两个额外的0位,以确保每个6位整数都有6位。
    • Base64编码的结果是一个文本字符串,其中包含一系列Base64字符,每4个字符分为一组,每组表示一个24位整数。
  5. 填充(可选): 如果原始数据的长度不是3的倍数,可以使用一个或两个填充字符“=”来补全Base64编码,以确保编码长度是4的倍数。

最终,Base64编码的结果就是表示输入二进制数据的文本字符串。在解码时,可以根据相同的算法将Base64编码的文本字符串还原为原始的二进制数据。

Base64编码是一种常见的数据表示方式,用于在各种情境中传输和存储二进制数据,因为它可以将二进制数据转换为纯文本,并且广泛支持各种编程语言和应用程序。

编码示例:base64编码 Man

编码示例:Base64的末尾补足

base64索引表:

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

 需要注意的是上述base编码的索引表都是可以改变的。下面是一个base64换表的解密脚本

import base64

str1 = "cPQebAcRp+n+ZeP+YePEWfP7bej4YefCYd/7cuP7WfcPb/URYeMRbesObi/=" # 待解密的base64编码

string1 = "LMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJK"    #替换的表
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

print (base64.b64decode(str1.translate(str.maketrans(string1,string2))))

base85编码

Base85编码,也称为ASCII85编码,是一种将二进制数据转换为ASCII字符的编码方法。它通常用于在文本协议中传输二进制数据,尤其在Adobe的PostScript和PDF文件格式中使用。

原理:

  1. 准备要编码的二进制数据: 将要编码的二进制数据准备好,通常是字节的形式。

  2. 分组: 将二进制数据分成固定大小的组,每组通常为4字节(32位)。

  3. 将每个组的二进制数据转换为整数: 将每个4字节的二进制数据视为一个32位的二进制整数,然后将它转换为一个十进制整数。这个整数的范围通常是0到4294967295(2^32-1)。

  4. Base85编码: 将每个十进制整数编码为Base85字符。

    • Base85字符集通常包括85个字符,通常是ASCII字符集中的可打印字符,除去易混淆的字符和可能引起歧义的字符。
    • 以32位整数为例,将它分成5组,每组将被编码为5个Base85字符。
    • 每个5个字符的组对应一个32位整数,根据其在Base85字符集中的位置来选择。
    • Base85编码的结果是一个文本字符串,其中包含一系列Base85字符,每5个字符分为一组,每组表示一个32位整数。
  5. 填充(可选): 如果原始数据的长度不是4字节的倍数,可以使用"z"字符作为填充字符,以确保编码长度是5的倍数。

base91编码

Base91编码是一种将二进制数据转换为文本编码的方法,通常用于在文本协议中传输二进制数据。与Base64相比,Base91编码具有更高的数据密度,但编码后的文本相对较长。 

原理:

  1. 准备要编码的二进制数据: 将要编码的二进制数据准备好,通常是字节的形式。

  2. 分组: 将二进制数据分成固定大小的组,每组通常为3字节(24位)。如果最后一组不足3字节,可以进行填充。

  3. Base91编码: 将每个3字节的二进制数据编码为Base91字符。

    • Base91字符集通常包括91个字符,通常是可打印ASCII字符集中的字符,除去易混淆的字符和可能引起歧义的字符。
    • 以24位的二进制数据为例,将其分成4组,每组将被编码为4个Base91字符。
    • 每个4字符的组对应一个24位的整数,根据其在Base91字符集中的位置来选择。
    • Base91编码的结果是一个文本字符串,其中包含一系列Base91字符,每4个字符分为一组,每组表示一个24位整数。
  4. 填充(可选): 如果原始数据的长度不是3字节的倍数,可以使用一或多个填充字符来确保编码长度是4的倍数

base100编码

base100是一种对称加密,加密后全是emoji表情。

总结

base家族编码都不算难,根据特征特点找到对应的加解密方式就可以了。下面总结一下各个base编码的特点。

base16特征:由大写字母(A-Z)和数字(0-9)组成,通常不需要“=”填充

base32特征:由大写字母(A-Z)和数字(2-7)组成,需要“=”填充

base64特征:大小写字母(a-Z)和数字(0-9)以及特殊字符('+','/')不满3的倍数用“=”补齐

base58特征:同base64相比,少了数字‘0’和字母‘O'数字’1‘和字母’I‘以及'+'和'/'符号,也没有“=”

base85特征:有很多奇怪的符号,但一般没有“=”

base91特征:由91个字符(0-9,a-z,A-Z,!#$%&()*+,./:;<=>?@[]^_`{|}~”)组成

base100特征:全是emoji表情。

加解密网站:

Base64编码转换工具,Base64加密解密

Base58编码/解码 - 一个工具箱 - 好用的在线工具都在这里!

Base85编码/解码 - 一个工具箱 - 好用的在线工具都在这里!

Base91编码/解码 - 一个工具箱 - 好用的在线工具都在这里!

Base100编码/解码 - 一个工具箱 - 好用的在线工具都在这里!

CTF在线工具-CTF工具|CTF编码|CTF密码学|CTF加解密|程序员工具|在线编解码

CyberChef

python实现base64

"""
base64实现
"""

import base64
import string

# base 字符集

base64_charset = string.ascii_uppercase + string.ascii_lowercase + string.digits + '+/'


def encode(origin_bytes):
    """
    将bytes类型编码为base64
    :param origin_bytes:需要编码的bytes
    :return:base64字符串
    """

    # 将每一位bytes转换为二进制字符串
    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
    """
    if not valid_base64_str(base64_str):
        return 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


def valid_base64_str(b_str):
    """
    验证是否为合法base64字符串
    :param b_str: 待验证的base64字符串
    :return:是否合法
    """
    if len(b_str) % 4:
        return False

    for m in b_str:
        if m not in base64_charset:
            return False
    return True


if __name__ == '__main__':
    s = '都看到这里了可以点个关注吗'.encode()
    local_base64 = encode(s)
    print('使用本地base64加密:', local_base64)
    b_base64 = base64.b64encode(s)
    print('使用base64加密:', b_base64.decode())

    print('使用本地base64解密:', decode(local_base64).decode())
    print('使用base64解密:', base64.b64decode(b_base64).decode())

    a = ''.encode()
    b = base64.b64decode(a).decode()
    print(b)


  • 9
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sciurdae

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值