Python 實現 AES 加密 解密

2021-09-24 11:50:43 字數 4194 閱讀 3092

一、前言

金鑰 k:用來加密明文的密碼,在對稱加密演算法中,加密與解密的金鑰是相同的。金鑰為接收方與傳送方協商產生,但不可以直接在網路上傳輸,否則會導致金鑰洩漏,通常是通過非對稱加密演算法加密金鑰,然後再通過網路傳輸給對方,或者直接面對面商量金鑰。金鑰是絕對不可以洩漏的,否則會被攻擊者還原密文,竊取機密資料。

aes 加密函式:設 aes 加密函式為 e,則 c = e(k, p),其中 p 為明文,k 為金鑰,c 為密文。也就是說,把明文 p 和金鑰 k 作為加密函式的引數輸入,則加密函式 e 會輸出密文 c。

密文 c:經過 aes 加密後的資料。

aes 解密函式:設 aes 解密函式為 d,則 p = d(k, c),其中 c 為密文,k 為金鑰,p 為明文。也就是說,把密文 c 和金鑰 k 作為解密函式的引數輸入,則解密函式會輸出明文 p。

aes 只是個基本演算法,實現 aes 有幾種模式,主要有 ecb、cbc、cfb 和 ofb 這幾種(其實還有個 ctr)。本章主要介紹最常用的 ecb 和 cbc 模式。

二、**實現與解析

1.ecb 模式

from crypto.cipher import aes

import base64

block_size = 16 # bytes

pad = lambda s: s + (block_size - len(s) % block_size) * \

chr(block_size - len(s) % block_size)

unpad = lambda s: s[:-ord(s[len(s) - 1:])]

def aesencrypt(key, data):

'''aes的ecb模式加密方法

:param key: 金鑰

:param data:被加密字串(明文)

:return:密文

'''key = key.encode('utf8')

# 字串補位

data = pad(data)

cipher = aes.new(key, aes.mode_ecb)

# 加密後得到的是bytes型別的資料,使用base64進行編碼,返回byte字串

result = cipher.encrypt(data.encode())

encodestrs = base64.b64encode(result)

enctext = encodestrs.decode('utf8')

print(enctext)

return enctext

def aesdecrypt(key, data):

''':param key: 金鑰

:param data: 加密後的資料(密文)

:return:明文

'''key = key.encode('utf8')

data = base64.b64decode(data)

cipher = aes.new(key, aes.mode_ecb)

# 去補位

text_decrypted = unpad(cipher.decrypt(data))

text_decrypted = text_decrypted.decode('utf8')

print(text_decrypted)

return text_decrypted

if __name__ == '__main__':

data = 'herish acorn'

ecdata = aesencrypt(key, data)

aesdecrypt(key, ecdata)

結果如下:

0fyqsxu3q9q13jgf4f74ja==

herish acorn

ecb 是最簡單的塊密碼加密模式,加密前根據加密塊大小(如 aes 為128位)分成若干塊,之後將每塊使用相同的金鑰單獨加密,解密同理。相對其他模式沒有偏移量的設定,簡單點,安全性差點。

aes 加密有 aes-128、aes-192、aes-256 三種,分別對應三種金鑰長度 128bits(16位元組)、192bits(24位元組)、256bits(32位元組)。當然,金鑰越長,安全性越高,加解密花費時間也越長。預設的是aes-128,其安全性完全夠用。

pad 和 unpad 分別是填充函式和逆填充函式。因為 aes 加密對加密文字有長度要求,必須是金鑰位元組數的倍數。這裡的 key 的長度是 16 個位元組。

關於填充演算法,簡單解釋就是缺幾位就補幾:填充字串由乙個位元組序列組成,每個位元組填充該填充位元組序列的長度。python **中 ecb 模式進行 aes 加密預設就是 pkcs7padding 填充。

2.cbc 模式

cbc 模式對於每個待加密的密碼塊在加密前會先與前乙個密碼塊的密文異或然後再用加密器加密。第乙個明文塊與乙個叫初始化向量的資料塊異或。

from crypto.cipher  import aes

import base64

# 金鑰(key), 密斯偏移量(iv) cbc模式加密

block_size = 16 # bytes

pad = lambda s: s + (block_size - len(s) % block_size) * \

chr(block_size - len(s) % block_size)

unpad = lambda s: s[:-ord(s[len(s) - 1:])]

vi = '0102030405060708'

def aes_encrypt(key, data):

data = pad(data)

# 字串補位

cipher = aes.new(key.encode('utf8'), aes.mode_cbc, vi.encode('utf8'))

encryptedbytes = cipher.encrypt(data.encode('utf8'))

# 加密後得到的是bytes型別的資料,使用base64進行編碼,返回byte字串

encodestrs = base64.b64encode(encryptedbytes)

# 對byte字串按utf-8進行解碼

enctext = encodestrs.decode('utf8')

return enctext

def aes_decrypt(key, data):

data = data.encode('utf8')

encodebytes = base64.decodebytes(data)

# 將加密資料轉換位bytes型別資料

cipher = aes.new(key.encode('utf8'), aes.mode_cbc, vi.encode('utf8'))

text_decrypted = cipher.decrypt(encodebytes)

# 去補位

text_decrypted = unpad(text_decrypted)

text_decrypted = text_decrypted.decode('utf8')

print(text_decrypted)

return text_decrypted

if __name__ == '__main__':

data = 'herish acorn'

enctext = aes_encrypt(key, data)

print(enctext)

aes_decrypt(key, enctext)

結果如下:

相比 ecb 模式,cbc 模式主要是多了偏移量這一要素,偏移量的取值,至少 16 位,或者為 16 的倍數。

Python實現AES加密解密

報錯 typeerror decrypt cannot be called after encrypt 原因 cryptor不能寫在主函式中同時給加密函式與解密函式使用,儘管加密解密都是用 cryptor aes.new key,mode,iv 但若將其定義在main並分別傳給加密解密同時使用時,會...

python 乍見(實現AES 加密解密)

coding utf8 import sysfrom crypto.cipher import aesfrom binascii import b2a hex,a2b hex class prpcrypt def init self,key self.key key self.mode aes.mo...

python實現AES的加密解密

了解aes aes advanced encryption standard 是一種對稱加密演算法,相較於des和3des演算法而言,aes演算法有著更高的速度和資源使用效率,安全級別也較之更高 公式 c e k,p 明文p,金鑰k,aes加密函式組成e,密文c。主要要了解以下幾點 aes金鑰的長度...