Python3 实现Base64

  • 支持自定义64字符
def b64_encode(data, *, letters=None):
    import struct
    if not isinstance(data, bytes):
        raise ValueError('type of the data which to be encoded must be bytes')
    if letters is None:
        letters = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    if not isinstance(letters, bytes):
        raise ValueError('type of the letters which to be trans must be bytes')
    if len(letters) != 64:
        raise ValueError('letters length must 64')

    res = bytearray()

    for i in range(0, len(data), 3):
        v = data[i:i + 3]
        v_len = len(v)
        if v_len == 3:
            n = struct.unpack('>I', b'\x00' + v)[0]
            res.append(letters[n >> 18 & 0x3f])
            res.append(letters[n >> 12 & 0x3f])
            res.append(letters[n >> 6 & 0x3f])
            res.append(letters[n >> 0 & 0x3f])
        elif v_len == 1:
            n = struct.unpack('>I', b'\x00\x00' + v + b'\x00')[0]
            res.append(letters[n >> 10 & 0x3f])
            res.append(letters[n >> 4 & 0x3f])
        else:
            n = struct.unpack('>I', b'\x00' + v + b'\x00')[0]
            res.append(letters[n >> 18 & 0x3f])
            res.append(letters[n >> 12 & 0x3f])
            res.append(letters[n >> 6 & 0x3f])

    if len(res) % 4:
        res.extend(b'=' * (4 - len(res) % 4))
    return bytes(res)


def b64_decode(data, *, letters=None):
    import struct
    if not isinstance(data, bytes):
        raise ValueError('type of the data which to be encoded must be bytes')
    if letters is None:
        letters = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    if not isinstance(letters, bytes):
        raise ValueError('type of the letters which to be trans must be bytes')
    if len(letters) != 64:
        raise ValueError('letters length must 64')

    res = bytearray()
    data = data.rstrip(b'=')
    for i in range(0, len(data), 4):
        v = data[i:i + 4]
        v_len = len(v)
        if v_len == 4:
            n = 0
            for _k in range(4):
                n <<= 6
                n |= letters.index(v[_k])
            res.extend(n.to_bytes(3, byteorder='big'))
        elif v_len == 2:
            n = 0
            n |= letters.index(v[0])
            n <<= 2
            n |= (letters.index(v[1]) >> 4)
            res.extend(n.to_bytes(1, byteorder='big'))
        else:
        	# v_len == 3
            n = 0
            n |= letters.index(v[0])
            n <<= 6
            n |= letters.index(v[1])
            n <<= 4
            n |= (letters.index(v[2]) >> 2)
            res.extend(n.to_bytes(2, byteorder='big'))

    return bytes(res)


def test(f1, f2, d1, d2):
    import os
    for i in range(500):
        for j in range(50):
            data = os.urandom(i)
            v1 = f1(data)
            v2 = f2(data)
            if not v1 == v2:
                print(data, v1, v2)
                return
            dd1 = d1(v2)
            dd2 = d2(v1)
            if not (dd1 == dd2 == data):
                print(data, v1, v2, dd1, dd2)
                return


def test_letters():
    import random
    import os
    letters = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    b = bytearray(letters)
    random.shuffle(b)
    b = bytes(b)
    print('letters', b)

    for i in range(500):
        for j in range(50):
            data = os.urandom(i)
            if not (b64_decode(b64_encode(data)) == data):
                print('Error', data)
                return


if __name__ == '__main__':
    import base64
    test(b64_encode, base64.b64encode, b64_decode, base64.b64decode)
    test_letters()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值