python实现AES算法及AES-CFB8加解密源码
作者:看到请叫我去学习 发布时间:2022-06-14 01:24:01
标签:AES,AES-CFB8,加解密,算法
Python实现AES算法
密码学课程老师留的作业,我觉得用python实现更简单,就用python写了一个加解密的程序。
程序分成三个部分,一个部分是生成轮密钥,一个加密,一个是解密。
生成轮密钥
这个部分要看是不是四的倍数,非四的倍数是简单的,直接异或就可以了。如果是4的倍数,这时就需要执行字节代替和异或运算。
for i in range(4):#把16进制转成十进制
for j in range(0, 8, 2 ):
self.subkey[i].append('0x'+key[i*8+j:i*8+j+2])
for i in range(4,44):#生成密钥
if i%4 !=0:
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])
tmp1 = self.S_box(tmp1) #字节代替
tmp1 = xor_32(tmp1,self.Rcon[i/4])#和Rcon异或
self.subkey.append(xor_32(tmp1,self.subkey[i-4]))
加密
加密时最难实现的是列混淆,因为要实现域上的乘法,没想到用递归实现的好方法,还是把一个一个用if判断来进行运算。
解密
解密的时候最难的仍然是逆列混淆运算,仍然是最傻的if判断。
完整代码如下
# -*- coding: utf-8 -*-
"""
Created on Fri Nov 1 18:47:24 2019
@author: pkill
"""
class AesCryption:
s_box = { #字节替换s盒
0:['0x63', '0x7c', '0x77', '0x7b', '0xf2', '0x6b', '0x6f', '0xc5', '0x30', '0x01', '0x67', '0x2b',
'0xfe', '0xd7', '0xab', '0x76'],
1:['0xca', '0x82', '0xc9', '0x7d', '0xfa', '0x59', '0x47', '0xf0', '0xad', '0xd4', '0xa2', '0xaf', '0x9c', '0xa4', '0x72', '0xc0'],
2:['0xb7', '0xfd', '0x93', '0x26', '0x36', '0x3f', '0xf7', '0xcc', '0x34', '0xa5', '0xe5', '0xf1', '0x71', '0xd8', '0x31', '0x15'],
3:['0x04', '0xc7', '0x23', '0xc3', '0x18', '0x96', '0x05', '0x9a', '0x07', '0x12', '0x80', '0xe2', '0xeb', '0x27', '0xb2', '0x75'],
4:['0x09', '0x83', '0x2c', '0x1a', '0x1b', '0x6e', '0x5a', '0xa0', '0x52', '0x3b', '0xd6', '0xb3', '0x29', '0xe3', '0x2f', '0x84'],
5:['0x53', '0xd1', '0x00', '0xed', '0x20', '0xfc', '0xb1', '0x5b', '0x6a', '0xcb', '0xbe', '0x39', '0x4a', '0x4c', '0x58', '0xcf'],
6:['0xd0', '0xef', '0xaa', '0xfb', '0x43', '0x4d', '0x33', '0x85', '0x45', '0xf9', '0x02', '0x7f',
'0x50', '0x3c', '0x9f', '0xa8'],
7:['0x51', '0xa3', '0x40', '0x8f', '0x92', '0x9d', '0x38', '0xf5', '0xbc', '0xb6', '0xda', '0x21',
'0x10', '0xff', '0xf3', '0xd2'],
8:['0xcd', '0x0c', '0x13', '0xec', '0x5f', '0x97', '0x44', '0x17', '0xc4', '0xa7', '0x7e', '0x3d',
'0x64', '0x5d', '0x19', '0x73'],
9:['0x60', '0x81', '0x4f', '0xdc', '0x22', '0x2a', '0x90', '0x88', '0x46', '0xee', '0xb8', '0x14',
'0xde', '0x5e', '0x0b', '0xdb'],
10:['0xe0', '0x32', '0x3a', '0x0a', '0x49', '0x06', '0x24', '0x5c', '0xc2', '0xd3', '0xac', '0x62', '0x91', '0x95', '0xe4', '0x79'],
11:['0xe7', '0xc8', '0x37', '0x6d', '0x8d', '0xd5', '0x4e', '0xa9', '0x6c', '0x56', '0xf4', '0xea', '0x65', '0x7a', '0xae', '0x08'],
12:['0xba', '0x78', '0x25', '0x2e', '0x1c', '0xa6', '0xb4', '0xc6', '0xe8', '0xdd', '0x74', '0x1f', '0x4b', '0xbd', '0x8b', '0x8a'],
13:['0x70', '0x3e', '0xb5', '0x66', '0x48', '0x03', '0xf6', '0x0e', '0x61', '0x35', '0x57', '0xb9', '0x86', '0xc1', '0x1d', '0x9e'],
14:['0xe1', '0xf8', '0x98', '0x11', '0x69', '0xd9', '0x8e', '0x94', '0x9b', '0x1e', '0x87', '0xe9', '0xce', '0x55', '0x28', '0xdf'],
15:['0x8c', '0xa1', '0x89', '0x0d', '0xbf', '0xe6', '0x42', '0x68', '0x41', '0x99', '0x2d', '0x0f', '0xb0', '0x54', '0xbb', '0x16']
}
s_1_box = { #逆字节替换s盒
0:['0x52', '0x09', '0x6a', '0xd5', '0x30', '0x36', '0xa5', '0x38', '0xbf', '0x40', '0xa3', '0x9e', '0x81', '0xf3', '0xd7', '0xfb'],
1:['0x7c', '0xe3', '0x39', '0x82', '0x9b', '0x2f', '0xff', '0x87', '0x34', '0x8e', '0x43', '0x44', '0xc4', '0xde', '0xe9', '0xcb'],
2:['0x54', '0x7b', '0x94', '0x32', '0xa6', '0xc2', '0x23', '0x3d', '0xee', '0x4c', '0x95', '0x0b', '0x42', '0xfa', '0xc3', '0x4e'],
3:['0x08', '0x2e', '0xa1', '0x66', '0x28', '0xd9', '0x24', '0xb2', '0x76', '0x5b', '0xa2', '0x49', '0x6d', '0x8b', '0xd1', '0x25'],
4:['0x72', '0xf8', '0xf6', '0x64', '0x86', '0x68', '0x98', '0x16', '0xd4', '0xa4', '0x5c', '0xcc', '0x5d', '0x65', '0xb6', '0x92'],
5:['0x6c', '0x70', '0x48', '0x50', '0xfd', '0xed', '0xb9', '0xda', '0x5e', '0x15', '0x46', '0x57', '0xa7', '0x8d', '0x9d', '0x84'],
6:['0x90', '0xd8', '0xab', '0x00', '0x8c', '0xbc', '0xd3', '0x0a', '0xf7', '0xe4', '0x58', '0x05', '0xb8', '0xb3', '0x45', '0x06'],
7:['0xd0', '0x2c', '0x1e', '0x8f', '0xca', '0x3f', '0x0f', '0x02', '0xc1', '0xaf', '0xbd', '0x03', '0x01', '0x13', '0x8a', '0x6b'],
8:['0x3a', '0x91', '0x11', '0x41', '0x4f', '0x67', '0xdc', '0xea', '0x97', '0xf2', '0xcf', '0xce', '0xf0', '0xb4', '0xe6', '0x73'],
9:['0x96', '0xac', '0x74', '0x22', '0xe7', '0xad', '0x35', '0x85', '0xe2', '0xf9', '0x37', '0xe8', '0x1c', '0x75', '0xdf', '0x6e'],
10:['0x47', '0xf1', '0x1a', '0x71', '0x1d', '0x29', '0xc5', '0x89', '0x6f', '0xb7', '0x62', '0x0e', '0xaa', '0x18', '0xbe', '0x1b'],
11:['0xfc', '0x56', '0x3e', '0x4b', '0xc6', '0xd2', '0x79', '0x20', '0x9a', '0xdb', '0xc0', '0xfe', '0x78', '0xcd', '0x5a', '0xf4'],
12:['0x1f', '0xdd', '0xa8', '0x33', '0x88', '0x07', '0xc7', '0x31', '0xb1', '0x12', '0x10', '0x59', '0x27', '0x80', '0xec', '0x5f'],
13:['0x60', '0x51', '0x7f', '0xa9', '0x19', '0xb5', '0x4a', '0x0d', '0x2d', '0xe5', '0x7a', '0x9f', '0x93', '0xc9', '0x9c', '0xef'],
14:['0xa0', '0xe0', '0x3b', '0x4d', '0xae', '0x2a', '0xf5', '0xb0', '0xc8', '0xeb', '0xbb', '0x3c', '0x83', '0x53', '0x99', '0x61'],
15:['0x17', '0x2b', '0x04', '0x7e', '0xba', '0x77', '0xd6', '0x26', '0xe1', '0x69', '0x14', '0x63', '0x55', '0x21', '0x0c', '0x7d']
}
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']
]
InvMatrix = [ #逆列混淆
['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):#把16进制转成十进制
for j in range(0, 8, 2 ):
self.subkey[i].append('0x'+key[i*8+j:i*8+j+2])
for i in range(4,44):#生成密钥
if i%4 !=0:
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])
tmp1 = self.S_box(tmp1) #字节代替
tmp1 = xor_32(tmp1,self.Rcon[i/4])#和Rcon异或
self.subkey.append(xor_32(tmp1,self.subkey[i-4]))
def AddRoundKey(self,round):#轮密钥加函数
for i in range(4):
self.plaintext[i] = xor_32(self.plaintext[i],self.subkey[round*4+i])
def PlainSubBytes(self):#明文字节代替函数
for i in range(4):
self.plaintext[i] = self.S_box(self.plaintext[i])
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
def S_box(self,row):#s盒函数
a = []
for i in range(4):
a.append(self.s_box[int(row[i][2],16)][int(row[i][3],16)])
return a
def S_1_box(self,row):#逆s盒函数
a = []
for i in range(4):
a.append(self.s_1_box[int(row[i][2],16)][int(row[i][3],16)])
return a
def MixColumns(self):#列混淆函数
for i in range(4):
for j in range(4):
self.plaintext1[i].append(mc(self.Matrix[j],self.plaintext[i]))
def InvShiftRows(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 InvSubBytes(self):#逆字节代替
for i in range(4):
self.plaintext[i] = self.S_1_box(self.plaintext[i])
def InvMixColumns(self):#逆列混淆
for i in range(4):
for j in range(4):
self.plaintext1[i].append(mc(self.InvMatrix[j],self.plaintext[i]))
def AesEncrypt(self,plain):#加密函数
for i in range(4):
for j in range(0, 8, 2 ):
self.plaintext[i].append('0x'+plain[i*8+j:i*8+j+2])#把16进制转化成二进制
self.AddRoundKey(0)#第一轮密钥加
for i in range(9):
self.PlainSubBytes()#字节代替
self.ShiftRows()#行移位
self.MixColumns()#列混淆
self.plaintext = self.plaintext1#把列混淆生成的密钥赋值给plaintext
self.plaintext1 = [[],[],[],[]]#重置
self.AddRoundKey(i+1)
self.PlainSubBytes()#最后一轮字节代替
self.ShiftRows()#最后一轮行移位
self.AddRoundKey(10)#最后一轮轮密钥加
return Matrixtostr(self.plaintext)#把二进制转换成诗十六进制
def AesDecrypt(self,cipher):
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.AddRoundKey(10)#轮密钥加
for i in range(9):
self.InvShiftRows()#逆行移位
self.InvSubBytes()#逆字节代替
self.AddRoundKey(9-i)#轮密钥加
self.InvMixColumns()#逆列混淆
self.plaintext = self.plaintext1
self.plaintext1 = [[],[],[],[]]
self.InvShiftRows()
self.InvSubBytes()
self.AddRoundKey(0)
return Matrixtostr(self.plaintext)#把二进制转换成十六进制
def hextobin(word):#把十六进制转换成二进制
word = bin(int(word,16))[2:]
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')#0x5-->0x05
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 Fa(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,Fa(2,Fa(2,Fa(2,b))))
elif a == 11:
tmp_b = b
return xor_8(tmp_b, xor_8(Fa(2,Fa(2,Fa(2,b))),Fa(2,b)))
elif a == 13:
tmp_b = b
return xor_8(tmp_b, xor_8(Fa(2,Fa(2,Fa(2,b))),Fa(2,Fa(2,b))))
elif a == 14:
return xor_8(Fa(2,b), xor_8(Fa(2,Fa(2,Fa(2,b))),Fa(2,Fa(2,b))))
def mc(s1,s2):#列混淆中的矩阵乘法
result = []
s3 = []
for i in range(4):
s3.append(hextobin(s2[i]))
for i in range(4):
result.append(Fa(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 Matrixtostr(matrix):#矩阵转成字符串
result = ""
for i in range(4):
for j in range(4):
result += matrix[i][j][2:]
return result
测试
输入和输出都是16进制格式的字符串:
测试例子:
key = 2b7e151628aed2a6abf7158809cf4f3c
plain = 3243f6a8885a308d313198a2e0370734
cipher = 3925841d02dc09fbdc118597196a0b32
测试程序
# -*- coding: utf-8 -*-
"""
Created on Fri Nov 1 19:37:00 2019
@author: whoami
"""
from AesCryption import AesCryption
key = input("key = ")
plain = input("plain = ")
cipher = input("cipher = ")
aesencrypt = AesCryption(key)
print('密文是:'+aesencrypt.AesEncrypt(plain))
print()
print('明文是:'+aesencrypt.AesDecrypt(cipher))
Python实现AES-CFB8加解密
import json
from base64 import b64encode, b64decode
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
def cfb_encrypt(data, key, iv=None):
if iv is None:
iv = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8)
ct_bytes = cipher.encrypt(data)
ct = b64encode(ct_bytes).decode('utf-8')
iv = b64encode(iv).decode('utf-8')
return encrypt_data, iv
def cfb8_decrypt(ciphertext, iv, key):
iv = b64decode(iv)
ct = b64decode(ciphertext)
cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=8)
decrypt_data = cipher.decrypt(ct)
return decrypt_data
来源:https://blog.csdn.net/lwuis_/article/details/102885002
0
投稿
猜你喜欢
- PDO::queryPDO::query — 执行 SQL 语句,返回PDOStatement对象,可以理解为结果集(PHP 5 >=
- 一、套接字套接字是为特定网络协议(例如TCP/IP,ICMP/IP,UDP/IP等)套件对上的网络应用程序提供者提供当前可移植标准的对象。它
- 其实就是利用文件“global.asa”!许多ASP编程新手都想知道这东西是什么?事实上,global.asa就是一个事件驱动程序,其中共包
- 对想要在可视化的环境下制作复杂网页的专业网页制作者来说,Dreamweaver 已经渐渐在网页编辑工具市场中展露头角,成为专业人士
- 1 动机greenlet 包是 Stackless 的副产品,其将微线程称为 “tasklet” 。tasklet运
- 当你在IE中点击一个Realplayer连接时,系统会自动启动Realplayer软件,不仅占用系统内存,而且在上网时Realplayer容
- IE5及其以后版本支持在CSS中使用expression,用来把CSS属性和Javascript表达式关联起来,这里的CSS属性可以是元素固
- 正在学习javascript 的朋友可以把它当作小练习动手做一做。加强自己的动手编码能力。参考代码:<!DOCTYPE HTML PU
- 本文给大家介绍PHP中Http协议post请求参数,具体内容如下所示:WEB开发中信息基本全是在POST与GET请求与响应中进行,GET因其
- 为什么使用Python 假设我们有这么一项任务:简单测试局域网中的电脑是否连通.这些电脑的ip范围从19
- 一:数据源介绍本篇文章介绍的是使用python实现对葵花8号卫星数据进行自动下载。葵花8号卫星是日本的一颗静止轨道气象卫星,覆盖范围为60S
- pandas获取groupby分组里最大值所在的行方法如下面这个DataFrame,按照Mt分组,取出Count最大的那行import pa
- 前言笔者用的是mac开发,但是mac自带的php功能安装十分不方便,并且和线上的linux开发环境不一致。在没有用docker之前一直用va
- 前面说到了urllib2的简单入门,下面整理了一部分urllib2的使用细节。1.Proxy 的设置urllib2 默认会使用环境变量 ht
- 如何做一个密码“生成器”?randompassword.asp<% Dim i, intNum,&nbs
- 当我们建好数据库及表后,首先想到的就是向数据库的表中输入数据.下面我们就来探讨一下如何向数据库增加数据:1.常用的方法是insert语句in
- 如果需要一个简单的Web Server,而不是安装那些复杂的HTTP服务程序,比如:Apache,Nginx等。那么可以使用Python自带
- 本文实例讲述了Python正则表达式实现截取成对括号的方法。分享给大家供大家参考,具体如下:strs = '1(2(3(4(5(67
- master库对于SQLServer来说,是很重要的系统数据库,保存着所有Sqlserver的用户信息、数据库信息等,当数据库崩溃时,mas
- 最近尝试了mysql的最新版本5.5.581.最新发布的mysql 5.5.8没有适合solaris 9的版本;这个在安装时需要注意2.它发