目录
一、概述
二、原理
三、算法源码
四、TK版源码
Base64编码是一种基于64个可打印字符来表示二进制数据的方法。
为什么会有Base64编码呢?因为有些网络传送渠道并不支持所有的字节,例如:传统的邮件只支持可见字符的传送,像ASCII码的控制字符就不能通过邮件传送。这样用途就受到了很大的限制。图片的二进制流的每个字节不可能全部是可见字符,这就导致图片的二进制流无法传送。最好的解决方式就是在不改变传统协议的情况下,做一种扩展方案来支持二进制文件的传送。即把不可打印的字符也能用可打印字符来表示,问题就解决了。Base64编码就是为了实现这一方案而设计的编码格式。
Base64就是一种基于64个可打印字符来表示二进制数据的表示方法。
1.通过将待转换的字符串每三个字节分为一组,每个字节占8个二进制位,那么共有24个二进制位。
2.每24个二进制位分为每6个一组,则每3个字节可分为4组
3.在每组前面添加两个0,每组由6个二进制位变为8个二进制位,总共32个二进制位,即四个字节。
4.根据Base64编码索引表获得对应的值。
索引表
原理图1:
原理图2:
IndexTable='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
#base64加密算法
import base64
#base64算法编码:byte-->str
def encryption(byteData):
# 打印字节数据
print('byte数据: ', byteData)
# print(len(byteData))
#将字节数据转为二进制数
binData = ''
for i in byteData:
#每个字节二进制记得左侧补零
binData = binData + bin(i)[2:].zfill(8)
print('转后二进制数: ', binData)
#每3个字节24位,右侧补零
fillZero = (24 - len(binData) % 24) % 24
print('补零数: ', fillZero)
binData = binData + ''.zfill(fillZero)
print('补零后二进制数: ', binData)
#每6位进行一次编码
pos = 0
resStr = ''
print('每六位的值进行索引编码:')
while(True):
if pos>=len(binData):
break
sixBin = binData[pos:pos+6]
print(sixBin.zfill(8))
indexOfNum = int(sixBin.zfill(8), 2)
resStr = resStr + IndexTable[indexOfNum]
pos = pos + 6
# 补零数如果需要8位,最终结果最后一位A替换一个等号。 16位,最终结果最后二位AA替换为二个等号。
if fillZero == 8:
resStr = resStr[:-1] + '='
elif fillZero == 16:
resStr = resStr[:-2] + '=='
return resStr
#base64解密算法
def decryption(base64Str):
binDataStr = ''
for j in base64Str:
#查出每个字符在索引表中的值
index = IndexTable.find(j)
#将值转为2进制数
if index != -1:
binDataStr = binDataStr + bin(index)[2:].zfill(6)
else:
binDataStr = binDataStr + '000000'
print('解码后二进制数: ', binDataStr)
#如果是1个等号,去掉1个自己8个0, 2个等号,去掉2个字节16个0
if base64Str.count('=') == 1:
binDataStr = binDataStr[:-8]
elif base64Str.count('=') == 2:
binDataStr = binDataStr[:-16]
print('去零后二进制数: ', binDataStr)
print('每八位取ascii值:')
pos = 0
resHex = ''
while(True):
if pos >= len(binDataStr):
break
eightBin = binDataStr[pos:pos+8]
print(eightBin)
# 转为十进制
indexOfNum = int(eightBin, 2)
# 转为16进制,并拼接
resHex = resHex + hex(indexOfNum).replace('0x', '')
pos = pos + 8
print('转为16进制字符串: ', resHex)
#将每个字节的16进制转为字节串
byteContent = bytes().fromhex(resHex)
print('转为字节串: ', byteContent)
#utf-8解码,最终结果
res = byteContent.decode('utf-8')
return res
content = '我的ab'
#python自带base64编码
contentToByte = content.encode('utf-8')
base64_data = base64.b64encode(contentToByte)
print('python自带base64编码: ', base64_data.decode('utf-8'))
#python自带base64解码
contentByte = base64.b64decode(base64_data)
print('python自带base64解码: ', contentByte.decode('utf-8'))
#base64算法编码
print('*'*20, '以下为编码过程', '*'*20)
print('原文: ', content)
contentToByte = content.encode('utf-8')
encryContent = encryption(contentToByte)
print('base64算法编码:', encryContent)
#base64算法解码
print('*'*20, '以下为解码过程', '*'*20)
decryContent = decryption(encryContent)
print('base64算法解码:', decryContent)
#!/usr/bin/env python
# Author:Veray Zhou
import tkinter as tk
IndexTable='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
#base64算法编码:byte-->str
def encryption(byteData):
# 打印字节数据
print('byte数据: ', byteData)
# print(len(byteData))
#将字节数据转为二进制数
binData = ''
for i in byteData:
#每个字节二进制记得左侧补零
binData = binData + bin(i)[2:].zfill(8)
print('转后二进制数: ', binData)
#每3个字节24位,右侧补零
fillZero = (24 - len(binData) % 24) % 24
print('补零数: ', fillZero)
binData = binData + ''.zfill(fillZero)
print('补零后二进制数: ', binData)
#每6位进行一次编码
pos = 0
resStr = ''
print('每六位的值进行索引编码:')
while(True):
if pos>=len(binData):
break
sixBin = binData[pos:pos+6]
print(sixBin.zfill(8))
indexOfNum = int(sixBin.zfill(8), 2)
resStr = resStr + IndexTable[indexOfNum]
pos = pos + 6
# 补零数如果需要8位,最终结果最后一位A替换一个等号。 16位,最终结果最后二位AA替换为二个等号。
if fillZero == 8:
resStr = resStr[:-1] + '='
elif fillZero == 16:
resStr = resStr[:-2] + '=='
return resStr
#base64解密算法
def decryption(base64Str):
binDataStr = ''
for j in base64Str:
#查出每个字符在索引表中的值
index = IndexTable.find(j)
#将值转为2进制数
if index != -1:
binDataStr = binDataStr + bin(index)[2:].zfill(6)
else:
binDataStr = binDataStr + '000000'
print('解码后二进制数: ', binDataStr)
#如果是1个等号,去掉1个自己8个0, 2个等号,去掉2个字节16个0
if base64Str.count('=') == 1:
binDataStr = binDataStr[:-8]
elif base64Str.count('=') == 2:
binDataStr = binDataStr[:-16]
print('去零后二进制数: ', binDataStr)
print('每八位取ascii值:')
pos = 0
resHex = ''
while(True):
if pos >= len(binDataStr):
break
eightBin = binDataStr[pos:pos+8]
print(eightBin)
# 转为十进制
indexOfNum = int(eightBin, 2)
# 转为16进制,并拼接
resHex = resHex + hex(indexOfNum).replace('0x', '')
pos = pos + 8
print('转为16进制字符串: ', resHex)
#将每个字节的16进制转为字节串
byteContent = bytes().fromhex(resHex)
print('转为字节串: ', byteContent)
#utf-8解码,最终结果
res = byteContent.decode('utf-8')
return res
window = tk.Tk()
window.title('BASE64编码和解码算法')
window.geometry('600x800')
def encry():
content = t.get('1.0','end')[:-1]
contentToByte = content.encode('utf-8')
encryContent = encryption(contentToByte)
t1.delete('1.0', 'end')
t1.insert(1.0, encryContent)
def decry():
encryContent = t1.get('1.0','end')[:-1]
decryContent = decryption(encryContent)
t2.delete('1.0', 'end')
t2.insert(1.0, decryContent)
tk.Label(window, text='请输入文本内容: ').pack()
t = tk.Text(window, height=10)
t.pack()
b = tk.Button(window, text='BASE64编码', command=encry)
b.pack()
t1 = tk.Text(height=20)
t1.pack()
b = tk.Button(window, text='BASE64解码', command=decry)
b.pack()
t2 = tk.Text(height=20)
t2.pack()
window.mainloop()