https://pypi.org/project/pycryptodome/
https://www.pycryptodome.org/en/latest/src/introduction.html
https://stackoverflow.com/questions/19623267/importerror-no-module-named-crypto-cipher
最佳实践:虚拟环境
为了避免不同版本的pip包或者安装在同一个文件夹下的包出现问题(即. pycrypto 和 pycryptodome) 你可以利用一个所谓的 虚拟环境. 在那里,可以为每个项目单独管理已安装的 pip 包.
要安装虚拟环境并设置所有内容,请使用以下命令:
# install python3 and pip3sudo apt updatesudo apt upgradesudo apt install python3sudo apt install python3-pip# install virtualenvpip3 install virtualenv# install and create a virtual environment in your target foldermkdir target_foldercd target_folderpython3 -m virtualenv .# now activate your venv and install pycryptodomesource bin/activatepip3 install pycryptodome# check if everything worked:# start the interactive python console and import the Crypto module# when there is no import error then it workedpython>>> from Crypto.Cipher import AES>>> exit()# don't forget to deactivate your venv againdeactivate
有关详细信息,请参阅 docs.python-guide.org.
aes
- cbc CBC加密需要一个十六位的key(密钥)和一个十六位iv(偏移量)
- ecb ECB加密不需要iv
aes cbc
CBC加密需要一个十六位的key(密钥)和一个十六位iv(偏移量) ```python
from Crypto.Cipher import AES from binascii import b2a_hex, a2b_hex
如果text不足16位的倍数就用空格补足为16位
def add_to_16(text): if len(text.encode(‘utf-8’)) % 16: add = 16 - (len(text.encode(‘utf-8’)) % 16) else: add = 0 text = text + (‘\0’ * add) return text.encode(‘utf-8’)
加密函数
def encrypt(text): key = ‘9999999999999999’.encode(‘utf-8’) mode = AES.MODE_CBC iv = b’qqqqqqqqqqqqqqqq’ text = add_to_16(text) cryptos = AES.new(key, mode, iv) cipher_text = cryptos.encrypt(text)
# 因为AES加密后的字符串不一定是ascii字符集的,输出保存可能存在问题,所以这里转为16进制字符串return b2a_hex(cipher_text)
解密后,去掉补足的空格用strip() 去掉
def decrypt(text): key = ‘9999999999999999’.encode(‘utf-8’) iv = b’qqqqqqqqqqqqqqqq’ mode = AES.MODE_CBC cryptos = AES.new(key, mode, iv) plain_text = cryptos.decrypt(a2b_hex(text)) return bytes.decode(plain_text).rstrip(‘\0’)
if name == ‘main‘: e = encrypt(“hello world”) # 加密 d = decrypt(e) # 解密 print(“加密:”, e) print(“解密:”, d)
<a name="IJFT6"></a>### aes ecbECB加密不需要iv```pythonimport base64from Crypto.Cipher import AES'''采用AES对称加密算法'''# str不是32的倍数那就补足为16的倍数def add_to_32(value):while len(value) % 32 != 0:value += '\0'return str.encode(value) # 返回bytesdef add_to_16(value):while len(value) % 16 != 0:value += '\0'return str.encode(value) # 返回bytes#加密方法def encrypt_oracle(text):# 秘钥key = 'VW1lMjAxMlRyaXAwMzA5AA=='# 待加密文本# 初始化加密器aes = AES.new(add_to_16(key), AES.MODE_ECB)#先进行aes加密encrypt_aes = aes.encrypt(add_to_16(text))#用base64转成字符串形式encrypted_text = str(base64.encodebytes(encrypt_aes), encoding='utf-8') # 执行加密并转码返回bytesprint(encrypted_text)return encrypted_text#解密方法def decrypt_oralce(text):# 秘钥key = 'VW1lMjAxMlRyaXAwMzA5AA=='# 密文# 初始化加密器aes = AES.new(add_to_16(key), AES.MODE_ECB)#优先逆向解密base64成bytesbase64_decrypted = base64.decodebytes(text.encode(encoding='utf-8'))#执行解密密并转码返回strdecrypted_text = str(aes.decrypt(base64_decrypted),encoding='utf-8').replace('\0','')print('decrypted_text',decrypted_text)return decrypted_textif __name__ == '__main__':text = '''{'aaa': '111', 'bbb': '222'}'''entrypted_text = encrypt_oracle(text)decrypt_oralce(entrypted_text)
hwmg aes
# coding=utf-8# AES AES/CBC/PKCS5|Zerofrom binascii import a2b_hex, b2a_heximport sysfrom Crypto.Cipher import AES'''采用AES对称加密算法'''# str不是16的倍数那就补足为16的倍数. ZeroPadding'''在PKCS5Padding中,明确定义Block的大小是8位而在PKCS7Padding定义中,对于块的大小是不确定的,可以在1-255之间PKCS #7 填充字符串由一个字节序列组成,每个字节填充该字节序列的长度。假定块长度为 8,数据长度为 9,数据: FF FF FF FF FF FF FF FF FFPKCS7 填充: FF FF FF FF FF FF FF FF FF 01 01 01 01 01 01 01 ?应该是填充01python3:填充bytes(这个说法不对,AES的参数是字符串,不是byte)length = 16 - (len(data) % 16)data += bytes([length])*lengthpython2:填充字符串length = 16 - (len(data) % 16)data += chr(length)*lengthpad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)unpad = lambda s : s[0:-ord(s[-1])]'''def add_to_16(value: str) -> bytes:"""将字符串转换为字节,如果长度取余 16有余数,使用 \0 补全长度为16的倍数"""value_byte = str.encode(value, encoding='utf8')while len(value_byte) % 16 != 0:value_byte += bytes('\0', encoding='utf8')return value_bytedef ZeroPadding(value, bs):while len(value) % bs != 0:value += '\0'return str.encode(value) # 返回bytes# 对于python,不需要zerounpadding? 去掉尾部的\0def encrypt_oracle(text: str) -> str:"""AES 加密基于 mode_cbc 加密, iv = key"""key = iv = add_to_16('0000000000000000')aes = AES.new(key, AES.MODE_CBC, iv)bs = AES.block_sizetext_16 = add_to_16(text)encrypt_aes = aes.encrypt(text_16)return b2a_hex(encrypt_aes).decode('utf8').lower()def decrypt_oralce(text: str):"""aes解密Args:text: hex strReturns:_description_"""# 秘钥key = iv = add_to_16('0000000000000000')aes = AES.new(key, AES.MODE_CBC, iv)decrypted_text = str(aes.decrypt(a2b_hex(text)), encoding='utf-8')return decrypted_textif __name__ == '__main__':filename = sys.argv[1]import randomimport stringtemp = list()for i in range(500):temp.append(''.join(random.choices(string.ascii_lowercase, k=random.randint(3, 9))) + ".docx")print(temp)for t in temp:# 加密crypt_name = encrypt_oracle(t)# 解密uncrypt_name = decrypt_oralce(crypt_name)# print(t, uncrypt_name)if uncrypt_name != t:print(f"err ===原文 {t}, 加密后 {crypt_name} 解密后 {uncrypt_name}")
