AES算法流程
稍微百度下就可知道,AES算法分为四个步骤:轮密钥加,字节代替,行移位和列混淆,本文以一个实例来讲解AES算法中的每一个步骤干了什么,精确到每个数字的变换。
写在前面
AES算法其实有很多种,根据秘钥长度的不同分为AES-128,AES-192,AES-256,本文以AES-128为例。
至于AES的加密模式,ECB,CBC等,其实和AES加密流程没有关系,不同的模式只是对输入的数据做处理(异或等),加密过程没有丝毫差别。
最后的实现采用python完成,无第三方模块。
密钥扩展
在开始加密之前,至少需要一个密钥,AES-128代表密钥长度为128位,也就是16字节。而加密流程一共要循环10轮,每一轮都需要不同的密钥,我们自然不可能设置长度为1280位的密钥,所以需要密钥扩展这个步骤,这个流程将产生10组长度均为128位的密钥。
假设现在有个密钥为’2b7e151628aed2a6abf7158809cf4f3c’,那么扩展秘钥是多少?
很明显,这个密钥长度是16字节(128位),每两位十六进制的数代表1字节。那么可以将这个密钥化为矩阵的形式:
下一步,官方说法是将初始密钥转为4个32位的字,其实就是将这个密钥分成四组,每一列就是一组,这样就有了四个变量:W0=2B7E1516,W1=28AED2A6,W2=ABF71588,W3=09CF4F3C。
现在,就要求扩展秘钥了,其实就是求W4,W5,W6…W43,而且很明显,每四个W组成完整的一组密钥。
怎么求呢?现在先交个底,求每组密钥的第一个分组(W4,W8,W12…)比其他的分组要复杂得多。
先把公式给出来,看不懂也没关系,有个印象就好:
可以看到,在求W4,W8…时走的是另一条路,重点在于函数g干了什么,我也不想直接甩概念性的东西出来,那个没有意义,还是看实例来的清楚。
现在是正式的过程,W4很明显是W0与g(W3)的进行异或得结果,那么函数g对W3干了什么?下面就是。
先将W3左移一个字节,得到W3’=CF4F3C09,然后将这个值进行S盒映射,这个S盒呢,是个固定的东西,可以理解为一个一对一的字典,它的样子如下:
查字典的方法不用我多说,将W3’进行S盒映射后,得到W3"=8A84EB01。
有些烧脑了,现在呢要将W3"与一个叫做Rcon的向量异或,这个向量长这样:
Rcon=[0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1B,0x36]
其实Rcon就是一个长度为10的数组,里面的每个数字都是十六进制形式,计算的密钥分组是属于哪个密钥的,就与Rcon中对应序号的值做异或,比如现在所求得W4属于第一组密钥,那么W3"就要与RCon[0]做异或,以此类推,求第十组密钥W40时需要W39"与Rcon[9]做异或。
现在好像有问题了,这两个值位数不一样怎么异或?其实很简单,就像下面这样:
不足的位数在后面补0就行了,实质上所有Rcon中的值都只影响W3"的第一个字节(前8位),通过异或,就得到了W3"’,写成十六进制形式是W3"’=8B84EB01。
上述呢,其实就是函数g干的事,下面就可以得出结果了。
最后,将W3"'与W0进行异或,就得到了W4,也就是第一组扩展密钥的第一组。
将W4写成十六进制形式W4=A0FAFE17。
然后,就是把第一组扩展密钥的其他分组(W5,W6,W7)求出来,这三组就简单得多,根据公式,W5是W1与W4异或得到,W6是W2与W5异或得到,W7是W3与W5异或得到,过程如下:
将W5写成十六进制形式就是W5=88542CB1,以此类推,W6=23A33939,W7=2A6C7605。
现在,就完整求出了第一组扩展密钥,同样写成矩阵形式:
下一步,就是求扩展密钥的第二组(W8,W9,W10,W11),过程和上面几乎一样,W8需要W4与g(W7)异或得到,其余的就是直接异或。直至求出第十组扩展密钥。
加密过程
密钥有了,现在来完整梳理一下加密的流程,其实百度就一大堆,这里简单说一下,加密过程就是:先进行一次轮密钥加(使用初始秘钥),然后循环9次字节代替,行移位,列混淆,轮密钥加(使用9组扩展秘钥),最后再进行一次字节代替,行移位,轮密钥加(使用最后一组扩展秘钥)。
轮密钥加
初始时刻,需要对明文进行处理,使其长度变为和密钥一样的128位,这里先不讨论,因为这不是加密的过程,后面我会放上详细的明文初始化过程。
现在,我们已经有了经过处理的明文’3243f6a8885a308d313198a2e0370734’,同样写成4×4的矩阵形式:
那么轮密钥加之后的结果是多少?假设密钥如下:
轮密钥加其实很简单,其实就是明文与密文的异或运算而已,只是计算过程繁杂。
相同位置的明文和密文都化为二进制形式,进行异或运算,以第一个字节为例:
其他结果依次类推,异或后的矩阵为:
字节代替
这个比较简单,字节代替是通过S盒映射完成的,和密钥扩展的S盒一样,可以直接查S盒。跟查字典一样,和前面密钥扩展的步骤一模一样。上面经过轮密钥加的矩阵再经过字节代替的结果如下:
行移位
这个也比较简单,就是矩阵的第一行不变,第二行循环左移一位,第三行循环左移两位,第四行循环左移三位,如下:
列混淆
我认为列混淆是AES加密中最复杂的了,但过程却是一句话就可以概括:左乘一个固定的矩阵。
固定矩阵如下:
过程图解如下:
“⊕”是异或,但那个“×”号不是简单的乘法,规则如下:
- 满足乘法分配律,即03×S=01×S⊕02×S。
- ×01和普通乘法×1一样,是其本身。
- ×02表示左移一位,最右边补0,若原始的数值最高位为1,需要将移位后的结果与1B(00011011)进行异或,如果不是则不用异或。
假设原始矩阵为求经过列混淆的矩阵。
同样以第一个字节为例,左乘是行×列,即固定矩阵的一行与原始矩阵的一列相乘。
其他元素是同样的方法,最终得到的结果矩阵如下:
至此,AES加密算法的所有步骤都已经介绍完毕,剩下的就是上述步骤的不断重复。
明文初始化
关于明文的初始化,就是将明文化为128位(16字节)的过程,转化过程其实很简单,就是将数据(可识别的文字,如hello word)转为字节流,然后再将字节流转为十六进制字符串就OK,转换的方法百度一大堆。
稍微有点儿问题的就是假设转换的字符串的位数不够128位怎么办?其实这个就是AES加密中的字符填充问题,将原本不足128位的字符填充至128位。至于超过128位的,分组就可以了,一组128位,最后一组同样需要字符填充,然后将每组数据加密后得到的密文连接起来就是完整密文。
字符填充的办法,其实也是百度一大堆的,这里简单说两种:
- PKCS7Padding:差几个字节就填充几,假设明文有10个字节,距离16字节差6字节,就在十六进制字符串后添加6个06,如果刚好16字节,就要在后面添加16个16。
- ZerosPadding:缺多少补多少个0,差6个字节就在后面补6个00。
关于解密
解密其实就是加密的逆推,第一步同样是轮密钥加,而后进入循环解密阶段,一共10轮,按顺序分别执行逆行移位,逆字节代替,轮密钥加,逆向列混淆,同样第10轮去掉逆向列混淆输出明文,但此时扩展秘钥的顺序要反过来。
逆行移位:第一行不变,第二行循环右移一位,第三行循环右移两位,第四行循环右移三位。
逆字节代替:操作步骤和字节代替一样,只不过需要映射的S盒变成了逆S盒,其实就是S盒反过来,键值互换,这点用python做非常方便。
逆列混淆:步骤和列混淆一样,仅仅是固定矩阵不同。
这里的乘法也是和列混淆中的乘法一样,所有的9,B,D,E其实都是通过分解为1或者2进行计算的。
逆列混淆矩阵和列混淆矩阵的乘积刚好是单位矩阵。
实现(python)
python解释器是python3.6
# -*- coding: utf-8 -*-
import re
import binascii
class Aes:
s_box = { # 字节替换s盒
'0x00': '0x63', '0x01': '0x7c', '0x02': '0x77', '0x03': '0x7b', '0x04': '0xf2', '0x05': '0x6b', '0x06': '0x6f', '0x07': '0xc5', '0x08': '0x30', '0x09': '0x01', '0x0a': '0x67', '0x0b': '0x2b', '0x0c': '0xfe', '0x0d': '0xd7', '0x0e': '0xab', '0x0f': '0x76',
'0x10': '0xca', '0x11': '0x82', '0x12': '0xc9', '0x13': '0x7d', '0x14': '0xfa', '0x15': '0x59', '0x16': '0x47', '0x17': '0xf0', '0x18': '0xad', '0x19': '0xd4', '0x1a': '0xa2', '0x1b': '0xaf', '0x1c': '0x9c', '0x1d': '0xa4', '0x1e': '0x72', '0x1f': '0xc0',
'0x20': '0xb7', '0x21': '0xfd', '0x22': '0x93', '0x23': '0x26', '0x24': '0x36', '0x25': '0x3f', '0x26': '0xf7', '0x27': '0xcc', '0x28': '0x34', '0x29': '0xa5', '0x2a': '0xe5', '0x2b': '0xf1', '0x2c': '0x71', '0x2d': '0xd8', '0x2e': '0x31', '0x2f': '0x15',
'0x30': '0x04', '0x31': '0xc7', '0x32': '0x23', '0x33': '0xc3', '0x34': '0x18', '0x35': '0x96', '0x36': '0x05', '0x37': '0x9a', '0x38': '0x07', '0x39': '0x12', '0x3a': '0x80', '0x3b': '0xe2', '0x3c': '0xeb', '0x3d': '0x27', '0x3e': '0xb2', '0x3f': '0x75',
'0x40': '0x09', '0x41': '0x83', '0x42': '0x2c', '0x43': '0x1a', '0x44': '0x1b', '0x45': '0x6e', '0x46': '0x5a', '0x47': '0xa0', '0x48': '0x52', '0x49': '0x3b', '0x4a': '0xd6', '0x4b': '0xb3', '0x4c': '0x29', '0x4d': '0xe3', '0x4e': '0x2f', '0x4f': '0x84',
'0x50': '0x53', '0x51': '0xd1', '0x52': '0x00', '0x53': '0xed', '0x54': '0x20', '0x55': '0xfc', '0x56': '0xb1', '0x57': '0x5b', '0x58': '0x6a', '0x59': '0xcb', '0x5a': '0xbe', '0x5b': '0x39', '0x5c': '0x4a', '0x5d': '0x4c', '0x5e': '0x58', '0x5f': '0xcf',
'0x60': '0xd0', '0x61': '0xef', '0x62': '0xaa', '0x63': '0xfb', '0x64': '0x43', '0x65': '0x4d', '0x66': '0x33', '0x67': '0x85', '0x68': '0x45', '0x69': '0xf9', '0x6a': '0x02', '0x6b': '0x7f', '0x6c': '0x50', '0x6d': '0x3c', '0x6e': '0x9f', '0x6f': '0xa8',
'0x70': '0x51', '0x71': '0xa3', '0x72': '0x40', '0x73': '0x8f', '0x74': '0x92', '0x75': '0x9d', '0x76': '0x38', '0x77': '0xf5', '0x78': '0xbc', '0x79': '0xb6', '0x7a': '0xda', '0x7b': '0x21', '0x7c': '0x10', '0x7d': '0xff', '0x7e': '0xf3', '0x7f': '0xd2',
'0x80': '0xcd', '0x81': '0x0c', '0x82': '0x13', '0x83': '0xec', '0x84': '0x5f', '0x85': '0x97', '0x86': '0x44', '0x87': '0x17', '0x88': '0xc4', '0x89': '0xa7', '0x8a': '0x7e', '0x8b': '0x3d', '0x8c': '0x64', '0x8d': '0x5d', '0x8e': '0x19', '0x8f': '0x73',
'0x90': '0x60', '0x91': '0x81', '0x92': '0x4f', '0x93': '0xdc', '0x94': '0x22', '0x95': '0x2a', '0x96': '0x90', '0x97': '0x88', '0x98': '0x46', '0x99': '0xee', '0x9a': '0xb8', '0x9b': '0x14', '0x9c': '0xde', '0x9d': '0x5e', '0x9e': '0x0b', '0x9f': '0xdb',
'0xa0': '0xe0', '0xa1': '0x32', '0xa2': '0x3a', '0xa3': '0x0a', '0xa4': '0x49', '0xa5': '0x06', '0xa6': '0x24', '0xa7': '0x5c', '0xa8': '0xc2', '0xa9': '0xd3', '0xaa': '0xac', '0xab': '0x62', '0xac': '0x91', '0xad': '0x95', '0xae': '0xe4', '0xaf': '0x79',
'0xb0': '0xe7', '0xb1': '0xc8', '0xb2': '0x37', '0xb3': '0x6d', '0xb4': '0x8d', '0xb5': '0xd5', '0xb6': '0x4e', '0xb7': '0xa9', '0xb8': '0x6c', '0xb9': '0x56', '0xba': '0xf4', '0xbb': '0xea', '0xbc': '0x65', '0xbd': '0x7a', '0xbe': '0xae', '0xbf': '0x08',
'0xc0': '0xba', '0xc1': '0x78', '0xc2': '0x25', '0xc3': '0x2e', '0xc4': '0x1c', '0xc5': '0xa6', '0xc6': '0xb4', '0xc7': '0xc6', '0xc8': '0xe8', '0xc9': '0xdd', '0xca': '0x74', '0xcb': '0x1f', '0xcc': '0x4b', '0xcd': '0xbd', '0xce': '0x8b', '0xcf': '0x8a',
'0xd0': '0x70', '0xd1': '0x3e', '0xd2': '0xb5', '0xd3': '0x66', '0xd4': '0x48', '0xd5': '0x03', '0xd6': '0xf6', '0xd7': '0x0e', '0xd8': '0x61', '0xd9': '0x35', '0xda': '0x57', '0xdb': '0xb9', '0xdc': '0x86', '0xdd': '0xc1', '0xde': '0x1d', '0xdf': '0x9e',
'0xe0': '0xe1', '0xe1': '0xf8', '0xe2': '0x98', '0xe3': '0x11', '0xe4': '0x69', '0xe5': '0xd9', '0xe6': '0x8e', '0xe7': '0x94', '0xe8': '0x9b', '0xe9': '0x1e', '0xea': '0x87', '0xeb': '0xe9', '0xec': '0xce', '0xed': '0x55', '0xee': '0x28', '0xef': '0xdf',
'0xf0': '0x8c', '0xf1': '0xa1', '0xf2': '0x89', '0xf3': '0x0d', '0xf4': '0xbf', '0xf5': '0xe6', '0xf6': '0x42', '0xf7': '0x68', '0xf8': '0x41', '0xf9': '0x99', '0xfa': '0x2d', '0xfb': '0x0f', '0xfc': '0xb0', '0xfd': '0x54', '0xfe': '0xbb', '0xff': '0x16'
}
ns_box = { # 逆字节替换s盒
}
Rcon = { # Rcon生成密钥的表
1: ['0x01', '0x00', '0x00', '0x00'],
2: ['0x02', '0x00', '0x00', '0x00'],
3: ['0x04', '0x00', '0x00', '0x00'],
4: ['0x08', '0x00', '0x00', '0x00'],
5: ['0x10', '0x00', '0x00', '0x00'],
6: ['0x20', '0x00', '0x00', '0x00'],
7: ['0x40', '0x00', '0x00', '0x00'],
8: ['0x80', '0x00', '0x00', '0x00'],
9: ['0x1B', '0x00', '0x00', '0x00'],
10: ['0x36', '0x00', '0x00', '0x00']
}
Matrix = [ # 列混淆
['0x02', '0x03', '0x01', '0x01'],
['0x01', '0x02', '0x03', '0x01'],
['0x01', '0x01', '0x02', '0x03'],
['0x03', '0x01', '0x01', '0x02']
]
ReMatrix = [ # 逆列混淆
['0x0e', '0x0b', '0x0d', '0x09'],
['0x09', '0x0e', '0x0b', '0x0d'],
['0x0d', '0x09', '0x0e', '0x0b'],
['0x0b', '0x0d', '0x09', '0x0e']
]
plaintext = [[], [], [], []] # 存放明文
plaintext1 = [[], [], [], []] # 最后输出的密文
subkey = [[], [], [], []] # 存放密钥
def __init__(self, key): # 构造函数,同时生成密钥
for i in range(4):
for j in range(0, 8, 2):
self.subkey[i].append("0x" + key[i * 8 + j:i * 8 + j + 2]) # 将密钥变成二维矩阵
# print(self.subkey)
for i in range(4, 44): # 生成密钥
if i % 4 != 0: # 如果不是4的倍数,那么直接异或
tmp = xor_32(self.subkey[i - 1], self.subkey[i - 4])
self.subkey.append(tmp)
else: # 4的倍数的时候执行
tmp1 = self.subkey[i - 1][1:]
tmp1.append(self.subkey[i - 1][0])
# print(tmp1)
for m in range(4):
tmp1[m] = self.s_box[tmp1[m]]
# tmp1 = self.s_box['cf'] # 字节代替
tmp1 = xor_32(tmp1, self.Rcon[i / 4]) # 和Rcon异或
self.subkey.append(xor_32(tmp1, self.subkey[i - 4]))
# print(self.subkey)
def AddRoundKey(self, round): # 轮密钥加
for i in range(4):
self.plaintext[i] = xor_32(self.plaintext[i], self.subkey[round * 4 + i])
# print(self.plaintext)
def PlainSubBytes(self): # 字节代替
for i in range(4):
for j in range(4):
self.plaintext[i][j] = self.s_box[self.plaintext[i][j]]
# print(self.plaintext)
def RePlainSubBytes(self): # 逆字节代替
for i in range(4):
for j in range(4):
self.plaintext[i][j] = self.ns_box[self.plaintext[i][j]]
def ShiftRows(self): # 行移位
p1, p2, p3, p4 = self.plaintext[0][1], self.plaintext[1][1], self.plaintext[2][1], self.plaintext[3][1]
self.plaintext[0][1] = p2
self.plaintext[1][1] = p3
self.plaintext[2][1] = p4
self.plaintext[3][1] = p1
p1, p2, p3, p4 = self.plaintext[0][2], self.plaintext[1][2], self.plaintext[2][2], self.plaintext[3][2]
self.plaintext[0][2] = p3
self.plaintext[1][2] = p4
self.plaintext[2][2] = p1
self.plaintext[3][2] = p2
p1, p2, p3, p4 = self.plaintext[0][3], self.plaintext[1][3], self.plaintext[2][3], self.plaintext[3][3]
self.plaintext[0][3] = p4
self.plaintext[1][3] = p1
self.plaintext[2][3] = p2
self.plaintext[3][3] = p3
# print(self.plaintext)
def ReShiftRows(self): # 逆行移位
p1, p2, p3, p4 = self.plaintext[0][1], self.plaintext[1][1], self.plaintext[2][1], self.plaintext[3][1]
self.plaintext[3][1] = p3
self.plaintext[2][1] = p2
self.plaintext[0][1] = p4
self.plaintext[1][1] = p1
p1, p2, p3, p4 = self.plaintext[0][2], self.plaintext[1][2], self.plaintext[2][2], self.plaintext[3][2]
self.plaintext[0][2] = p3
self.plaintext[1][2] = p4
self.plaintext[2][2] = p1
self.plaintext[3][2] = p2
p1, p2, p3, p4 = self.plaintext[0][3], self.plaintext[1][3], self.plaintext[2][3], self.plaintext[3][3]
self.plaintext[0][3] = p2
self.plaintext[1][3] = p3
self.plaintext[2][3] = p4
self.plaintext[3][3] = p1
def MixColumns(self): # 列混淆
for i in range(4):
for j in range(4):
self.plaintext1[i].append(MatrixMulti(self.Matrix[j], self.plaintext[i]))
# print(self.plaintext1)
def ReMixColumns(self): # 逆列混淆
for i in range(4):
for j in range(4):
self.plaintext1[i].append(MatrixMulti(self.ReMatrix[j], self.plaintext[i]))
def AESEncryption(self, plaintext): # AES单组加密函数
self.plaintext = [[], [], [], []]
for i in range(4):
for j in range(0, 8, 2):
self.plaintext[i].append("0x" + plaintext[i * 8 + j:i * 8 + j + 2])
self.AddRoundKey(0)
for i in range(9):
self.PlainSubBytes()
self.ShiftRows()
self.MixColumns()
self.plaintext = self.plaintext1
self.plaintext1 = [[], [], [], []] # 重置
self.AddRoundKey(i + 1)
self.PlainSubBytes() # 最后一轮字节代替
self.ShiftRows() # 最后一轮行移位
self.AddRoundKey(10) # 最后一轮轮密钥加
return Matrixtostr(self.plaintext)
def AESDecryption(self, cipher): # AES单组解密函数
self.plaintext = [[], [], [], []]
for i in range(4):
for j in range(0, 8, 2):
self.plaintext[i].append('0x' + cipher[i * 8 + j:i * 8 + j + 2]) # 16进制转成2进制
self.ns_box = dict(zip(self.s_box.values(), self.s_box.keys())) # s盒键值互换,变为逆S盒
# print(self.ns_box)
self.AddRoundKey(10)
for i in range(9):
self.ReShiftRows()
self.RePlainSubBytes()
self.AddRoundKey(9-i)
self.ReMixColumns()
self.plaintext = self.plaintext1
self.plaintext1 = [[], [], [], []]
self.ReShiftRows()
self.RePlainSubBytes()
self.AddRoundKey(0)
return Matrixtostr(self.plaintext)
def Encryption(self, text): # 加密函数
group = PlaintextGroup(TextToByte(text), 32, 1)
# print(group)
cipher = ""
for i in range(len(group)):
cipher = cipher + self.AESEncryption(group[i])
return cipher
def Decryption(self, cipher): # 解密函数
group = PlaintextGroup(cipher, 32, 0)
# print(group)
text = ''
for i in range(len(group)):
text = text + self.AESDecryption(group[i])
text = ByteToText(text)
return text
def xor_32(start, end): # 32位进行异或
a = []
for i in range(0, 4):
xor_tmp = ""
b = hextobin(start[i])
c = hextobin(end[i])
for j in range(8):
xor_tmp += str(int(b[j], 10) ^ int(c[j], 10))
a.append(bintohex(xor_tmp))
return a
def xor_8(begin, end): # 8位异或
xor_8_tmp = ""
for i in range(8):
xor_8_tmp += str(int(begin[i]) ^ int(end[i]))
return xor_8_tmp
def hextobin(word): # 把十六进制转换成二进制
word = bin(int(word, 16))[2:] # 去除掉最前面的0b
for i in range(0, 8-len(word)): # 补全八位
word = '0'+word
return word
def bintohex(word): # 把二进制转换十六进制
word = hex(int(word, 2))
if len(word) == 4:
return word
elif len(word) < 4:
return word.replace('x', 'x0')
def MatrixMulti(s1, s2): # 列混淆中的矩阵乘法
result = []
s3 = []
for i in range(4):
s3.append(hextobin(s2[i])) # s3保存原始矩阵一行的四个二进制值
for i in range(4):
result.append(MultiProcess(int(s1[i], 16), s3[i]))
for i in range(3):
result[0] = xor_8(result[0], result[i+1])
return bintohex(result[0])
def MultiProcess(a, b): # 列混淆中的乘法运算的具体过程
if a == 1:
return b
elif a == 2:
if b[0] == '0':
b = b[1:] + '0'
else:
b = b[1:] + '0'
b = xor_8(b, '00011011')
return b
elif a == 3:
tmp_b = b
if b[0] == '0':
b = b[1:] + '0'
else:
b = b[1:] + '0'
b = xor_8(b, '00011011')
return xor_8(b, tmp_b)
elif a == 9:
tmp_b = b
return xor_8(tmp_b, MultiProcess(2, MultiProcess(2, MultiProcess(2, b))))
elif a == 11:
tmp_b = b
return xor_8(tmp_b, xor_8(MultiProcess(2, MultiProcess(2, MultiProcess(2, b))), MultiProcess(2, b)))
elif a == 13:
tmp_b = b
return xor_8(tmp_b, xor_8(MultiProcess(2, MultiProcess(2, MultiProcess(2, b))), MultiProcess(2, MultiProcess(2, b))))
elif a == 14:
return xor_8(MultiProcess(2, b), xor_8(MultiProcess(2, MultiProcess(2, MultiProcess(2, b))), MultiProcess(2, MultiProcess(2, b))))
def Matrixtostr(matrix): # 矩阵转成字符串
result = ""
for i in range(4):
for j in range(4):
result += matrix[i][j][2:]
return result
def PlaintextGroup(plaintext, length, flag): # 明文分组和填充
group = re.findall('.{'+str(length)+'}', plaintext)
group.append(plaintext[len(group)*length:])
if group[-1] == '' and flag:
group[-1] = '16161616161616161616161616161616'
elif len(group[-1]) < length and flag:
tmp = int((length-len(group[-1])) / 2)
if tmp < 10:
for i in range(tmp):
group[-1] = group[-1] + '0'+str(tmp)
else:
for i in range(tmp):
group[-1] = group[-1] + str(tmp)
elif not flag:
del group[-1]
return group
def TextToByte(words): # 明文转成十六进制字节流
text = words.encode('utf-8').hex()
return text
def ByteToText(encode): # 十六进制字节流转成明文
tmp = int(encode[-2:])
word = ''
for i in range(len(encode)-tmp*2):
word = word + encode[i]
# print(word)
word = bytes.decode(binascii.a2b_hex(word))
return word
key = '2b7e151628aed2a6abf7158809cf4f3c'
# plaintext = '68656c6c6f20776f726c640505050505'
# A1 = Aes(key)
# abc = A1.AESEncryption(plaintext)
# print(abc)
# print(A1.AESDecryption(abc))
AESDemo = Aes(key)
plaintext = input("请输入要加密的文字:\n")
a = AESDemo.Encryption(plaintext)
print("密文为:" + a)
print("明文为:" + AESDemo.Decryption(a))
测试
其实这个程序有个小小的bug,后面再想想能不能消除吧,就这样了。