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 pip3
sudo apt update
sudo apt upgrade
sudo apt install python3
sudo apt install python3-pip
# install virtualenv
pip3 install virtualenv
# install and create a virtual environment in your target folder
mkdir target_folder
cd target_folder
python3 -m virtualenv .
# now activate your venv and install pycryptodome
source bin/activate
pip3 install pycryptodome
# check if everything worked:
# start the interactive python console and import the Crypto module
# when there is no import error then it worked
python
>>> from Crypto.Cipher import AES
>>> exit()
# don't forget to deactivate your venv again
deactivate
有关详细信息,请参阅 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 ecb
ECB加密不需要iv
```python
import base64
from Crypto.Cipher import AES
'''
采用AES对称加密算法
'''
# str不是32的倍数那就补足为16的倍数
def add_to_32(value):
while len(value) % 32 != 0:
value += '\0'
return str.encode(value) # 返回bytes
def 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') # 执行加密并转码返回bytes
print(encrypted_text)
return encrypted_text
#解密方法
def decrypt_oralce(text):
# 秘钥
key = 'VW1lMjAxMlRyaXAwMzA5AA=='
# 密文
# 初始化加密器
aes = AES.new(add_to_16(key), AES.MODE_ECB)
#优先逆向解密base64成bytes
base64_decrypted = base64.decodebytes(text.encode(encoding='utf-8'))
#执行解密密并转码返回str
decrypted_text = str(aes.decrypt(base64_decrypted),encoding='utf-8').replace('\0','')
print('decrypted_text',decrypted_text)
return decrypted_text
if __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|Zero
from binascii import a2b_hex, b2a_hex
import sys
from 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 FF
PKCS7 填充: FF FF FF FF FF FF FF FF FF 01 01 01 01 01 01 01 ?应该是填充01
python3:填充bytes(这个说法不对,AES的参数是字符串,不是byte)
length = 16 - (len(data) % 16)
data += bytes([length])*length
python2:填充字符串
length = 16 - (len(data) % 16)
data += chr(length)*length
pad = 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_byte
def ZeroPadding(value, bs):
while len(value) % bs != 0:
value += '\0'
return str.encode(value) # 返回bytes
# 对于python,不需要zerounpadding? 去掉尾部的\0
def 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_size
text_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 str
Returns:
_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_text
if __name__ == '__main__':
filename = sys.argv[1]
import random
import string
temp = 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}")