python實現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
以上就是python實現AES算法及AES-CFB8加解密源碼的詳細內容,更多關於Python實現AES-CFB8加解密算法的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- Python使用Crypto庫實現加密解密的示例詳解
- python des,aes,rsa加解密的實現
- Python爬蟲實戰JS逆向AES逆向加密爬取
- 通過Golang編寫一個AES加密解密工具
- python密碼學換位密碼及換位解密轉置加密教程