赞
踩
有时需要对数据进行对称加解密,常用的有:
区块加密算法采用对称密钥,可以加密固定长度的较短(区块数量)的数据。为了处理任意长度的数据,加密算法必须指定加密模式。常用的加密模式如下:
不应该再使用此模式
。经典的加密模式,比如CBC mode只能保证机密性,但不能保证完整性。
基于这个原因,经典模式经常会和MAC算法(比如Crypto.Hash.HMAC)搭配使用,但是这种结合不够直观,有效和安全。
因此,有一些新的同时具有加密和验证完整性的模式设计出来:
鉴于pycrypto已不再安全,建议使用pycryptodome。pycyrptodome 是pycrypto的分支,在安全性方面有较大提升。
pip install pycryptodome
# -*- coding:utf-8 -*- import json from base64 import b64encode,b64decode from Crypto.Cipher import AES from Crypto.Util.Padding import pad,unpad from Crypto.Random import get_random_bytes class AESClassicCipher: def __init__(self, key): self.bs = AES.block_size self.key = key self.mode = AES.MODE_CBC def encrypt(self, data): cipher = AES.new(self.key, self.mode) ct_bytes = cipher.encrypt(pad(data, self.bs)) iv = b64encode(cipher.iv).decode('utf-8') ct = b64encode(ct_bytes).decode('utf-8') return json.dumps({'iv':iv, 'ciphertext':ct}) def decrypt(self, json_input): try: b64 = json.loads(json_input) iv = b64decode(b64['iv']) ct = b64decode(b64['ciphertext']) cipher = AES.new(self.key, self.mode, iv) plaintext = unpad(cipher.decrypt(ct), self.bs) return plaintext.decode('utf-8') except (ValueError, KeyError) as err: print("Incorrect decryption ", err) return None if __name__ == "__main__": data = "你的CBC密文".encode('utf-8') key = get_random_bytes(16) aes_cipher = AESClassicCipher(key) encrypt_reuslt = aes_cipher.encrypt(data) print("Encryption was: ", encrypt_reuslt) plaintext = aes_cipher.decrypt(encrypt_reuslt) print("The message was: ", plaintext)
输出结果为
Encryption was: {"iv": "B6VyPVmqTvpa9deaZgCGxg==", "ciphertext": "UJormRNFuE/oHynbtIVCIw=="}
The message was: 你的CBC密文
# -*- coding:utf-8 -*- import json from base64 import b64encode, b64decode from Crypto.Cipher import AES from Crypto.Random import get_random_bytes class AESModernCipher: def __init__(self, key): self.bs = AES.block_size self.key = key self.mode = AES.MODE_OCB self.json_k = [ 'nonce', 'header', 'ciphertext', 'tag' ] def encrypt(self, header, data): header = header cipher = AES.new(self.key, self.mode) cipher.update(header) ciphertext, tag = cipher.encrypt_and_digest(data) json_v = [ b64encode(x).decode('utf-8') for x in [cipher.nonce, header, ciphertext, tag] ] return json.dumps(dict(zip(self.json_k, json_v))) def decrypt(self, json_input): try: b64 = json.loads(json_input) jv = {k:b64decode(b64[k]) for k in self.json_k} cipher = AES.new(self.key, self.mode, nonce=jv['nonce']) cipher.update(jv['header']) plaintext = cipher.decrypt_and_verify(jv['ciphertext'], jv['tag']) return plaintext.decode('utf-8') except (ValueError, KeyError) as err: print("Incorrect decryption ", err) return None if __name__ == "__main__": data = "你的OCB密文".encode('utf-8') key = get_random_bytes(16) header = b'header' aes_cipher = AESModernCipher(key) encrypt_reuslt = aes_cipher.encrypt(header, data) print("Encryption was: ", encrypt_reuslt) plaintext = aes_cipher.decrypt(encrypt_reuslt) print("The message was: ", plaintext)
输出结果为:
Encryption was: {"nonce": "Sa8Fah2cNmMnIST22XL2", "header": "aGVhZGVy", "ciphertext": "sQqARVVaflyuyB0BV6FE", "tag": "BBMDIbVbjv7lVCYBWIuOdw=="}
The message was: 你的OCB密文
from Crypto.Cipher import AES
运行上面语句会报错:
from Crypto.Cipher import AES
ModuleNotFoundError: No module named ‘Crypto’
可能原因是安装有crypto, pycrypto, pycryptodome中的多个库。
解决办法:先将其全部卸载,然后再重新安装 pycryptodome.
pip uninstall crypto pycrypto pycryptodome
pip install pycryptodome
参考文章:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。