base64编码
-
将给定的字符串转换成字节数组,进行步长为3的分割,每3个字节为一组,最后一组不够三个字节的,补0,如果最后一组是一个字节,剩下的两个字节补0;如果最后一组是两个字节,剩下的一个字节补0。
-
每6位组成一个新的字节,高位补00,构成一个新的二进制序列,最后根据base64索引表中的值找到对应的字符。
-
在第一步骤中,补了几个字节的0,就补几个=。
-
如将“abcd”经base64转码后得“YWJjZA==”。
def base_64(src:str): # str='abcd'
alphabet = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
ret = bytearray()
if isinstance(src,str):
src_code = src.encode() # 进行编码
else:
return
for offset in range(0,len(src_code),3):
temp = src_code[offset:offset+3] # b'abc'、b'd'
r = 3 - len(temp) # r:0,2
if r: # 如果r不为0,表示这是最后一组,
temp += b'\x00'* r # \x00表示两个十六进制真正的0(非字符0)
# 进行移位运算
x = int.from_bytes(temp,'big') # 大端模式,从左向右
# 01100001 01100010 01100011 (abc)---- 01100100 00000000 00000000 (d)
for i in range(18,-1,-6):
index = x >> i if i == 18 else x >> i & 0x3F # 0x3F表示16进制,是11 1111
ret.append(alphabet[index])
if r: # 补了几个字节的0,就添加几个=
ret[-r:] = b'='* r
return bytes(ret)
res= base_64('abcd')
print(res) # b'YWJjZA=='
base64解码
import re
def decoded_base64(src:bytes):
alphabet = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
pat_end = re.compile(b'[A-Za-z\d+/]{2,4}={0,2}')
pat_not_end = re.compile(b'[A-Za-z\d+/]{4}')
# 分块
step = 4
result = bytearray()
for offset in range(0,len(src),step):
end = offset+step
block = src[offset:end]
# 进行格式检查,分两种情况,结尾和不是结尾
end_flag = True if end == len(src) else False
length = len(re.match(pat_end,block).group(0)) if True else len(re.match(pat_not_end,block).group(0))
if length != 4:
print('不符合要求的输入')
return
# 符合字符串传入要求
#对每一个block进行解码
ret = 0
for i,item in enumerate(block):
# 分两种情况,结尾,不是结尾
index = alphabet.find(item) # 需要考虑index = -1,也就是item = '='的情况
if index == -1:
continue
if b'=' in block:
if block.find(b'=') == 2:
if i == 0:
ret += index << 2
if i == 1:
ret += index >> 4
elif block.find(b'=') == 3:
if i == 0:
ret += index << 10
if i == 1:
ret += index << 4
if i == 2:
ret += index >> 2
else:
ret += index << (step - 1- i) * 6
if block.find(b'=') == 2:
ret1 = ret.to_bytes(1, 'big')
elif block.find(b'=') == 3:
ret1 = ret.to_bytes(2, 'big')
else:
ret1 = ret.to_bytes(3, 'big') # 表示要转换成3个字节,大端模式
result.extend(ret1)
return bytes(result)
print(decoded_base64(b'YWJjZA=='))