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 包.
要安装虚拟环境并设置所有内容,请使用以下命令:

  1. # install python3 and pip3
  2. sudo apt update
  3. sudo apt upgrade
  4. sudo apt install python3
  5. sudo apt install python3-pip
  6. # install virtualenv
  7. pip3 install virtualenv
  8. # install and create a virtual environment in your target folder
  9. mkdir target_folder
  10. cd target_folder
  11. python3 -m virtualenv .
  12. # now activate your venv and install pycryptodome
  13. source bin/activate
  14. pip3 install pycryptodome
  15. # check if everything worked:
  16. # start the interactive python console and import the Crypto module
  17. # when there is no import error then it worked
  18. python
  19. >>> from Crypto.Cipher import AES
  20. >>> exit()
  21. # don't forget to deactivate your venv again
  22. 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)

  1. # 因为AES加密后的字符串不一定是ascii字符集的,输出保存可能存在问题,所以这里转为16进制字符串
  2. 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)

  1. <a name="IJFT6"></a>
  2. ### aes ecb
  3. ECB加密不需要iv
  4. ```python
  5. import base64
  6. from Crypto.Cipher import AES
  7. '''
  8. 采用AES对称加密算法
  9. '''
  10. # str不是32的倍数那就补足为16的倍数
  11. def add_to_32(value):
  12. while len(value) % 32 != 0:
  13. value += '\0'
  14. return str.encode(value) # 返回bytes
  15. def add_to_16(value):
  16. while len(value) % 16 != 0:
  17. value += '\0'
  18. return str.encode(value) # 返回bytes
  19. #加密方法
  20. def encrypt_oracle(text):
  21. # 秘钥
  22. key = 'VW1lMjAxMlRyaXAwMzA5AA=='
  23. # 待加密文本
  24. # 初始化加密器
  25. aes = AES.new(add_to_16(key), AES.MODE_ECB)
  26. #先进行aes加密
  27. encrypt_aes = aes.encrypt(add_to_16(text))
  28. #用base64转成字符串形式
  29. encrypted_text = str(base64.encodebytes(encrypt_aes), encoding='utf-8') # 执行加密并转码返回bytes
  30. print(encrypted_text)
  31. return encrypted_text
  32. #解密方法
  33. def decrypt_oralce(text):
  34. # 秘钥
  35. key = 'VW1lMjAxMlRyaXAwMzA5AA=='
  36. # 密文
  37. # 初始化加密器
  38. aes = AES.new(add_to_16(key), AES.MODE_ECB)
  39. #优先逆向解密base64成bytes
  40. base64_decrypted = base64.decodebytes(text.encode(encoding='utf-8'))
  41. #执行解密密并转码返回str
  42. decrypted_text = str(aes.decrypt(base64_decrypted),encoding='utf-8').replace('\0','')
  43. print('decrypted_text',decrypted_text)
  44. return decrypted_text
  45. if __name__ == '__main__':
  46. text = '''{'aaa': '111', 'bbb': '222'}'''
  47. entrypted_text = encrypt_oracle(text)
  48. decrypt_oralce(entrypted_text)

hwmg aes

  1. # coding=utf-8
  2. # AES AES/CBC/PKCS5|Zero
  3. from binascii import a2b_hex, b2a_hex
  4. import sys
  5. from Crypto.Cipher import AES
  6. '''
  7. 采用AES对称加密算法
  8. '''
  9. # str不是16的倍数那就补足为16的倍数. ZeroPadding
  10. '''
  11. 在PKCS5Padding中,明确定义Block的大小是8位
  12. 而在PKCS7Padding定义中,对于块的大小是不确定的,可以在1-255之间
  13. PKCS #7 填充字符串由一个字节序列组成,每个字节填充该字节序列的长度。
  14. 假定块长度为 8,数据长度为 9,
  15. 数据: FF FF FF FF FF FF FF FF FF
  16. PKCS7 填充: FF FF FF FF FF FF FF FF FF 01 01 01 01 01 01 01 ?应该是填充01
  17. python3:填充bytes(这个说法不对,AES的参数是字符串,不是byte)
  18. length = 16 - (len(data) % 16)
  19. data += bytes([length])*length
  20. python2:填充字符串
  21. length = 16 - (len(data) % 16)
  22. data += chr(length)*length
  23. pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
  24. unpad = lambda s : s[0:-ord(s[-1])]
  25. '''
  26. def add_to_16(value: str) -> bytes:
  27. """
  28. 将字符串转换为字节,如果长度取余 16有余数,使用 \0 补全长度为16的倍数
  29. """
  30. value_byte = str.encode(value, encoding='utf8')
  31. while len(value_byte) % 16 != 0:
  32. value_byte += bytes('\0', encoding='utf8')
  33. return value_byte
  34. def ZeroPadding(value, bs):
  35. while len(value) % bs != 0:
  36. value += '\0'
  37. return str.encode(value) # 返回bytes
  38. # 对于python,不需要zerounpadding? 去掉尾部的\0
  39. def encrypt_oracle(text: str) -> str:
  40. """
  41. AES 加密
  42. 基于 mode_cbc 加密, iv = key
  43. """
  44. key = iv = add_to_16('0000000000000000')
  45. aes = AES.new(key, AES.MODE_CBC, iv)
  46. bs = AES.block_size
  47. text_16 = add_to_16(text)
  48. encrypt_aes = aes.encrypt(text_16)
  49. return b2a_hex(encrypt_aes).decode('utf8').lower()
  50. def decrypt_oralce(text: str):
  51. """aes解密
  52. Args:
  53. text: hex str
  54. Returns:
  55. _description_
  56. """
  57. # 秘钥
  58. key = iv = add_to_16('0000000000000000')
  59. aes = AES.new(key, AES.MODE_CBC, iv)
  60. decrypted_text = str(aes.decrypt(a2b_hex(text)), encoding='utf-8')
  61. return decrypted_text
  62. if __name__ == '__main__':
  63. filename = sys.argv[1]
  64. import random
  65. import string
  66. temp = list()
  67. for i in range(500):
  68. temp.append(''.join(random.choices(string.ascii_lowercase, k=random.randint(3, 9))) + ".docx")
  69. print(temp)
  70. for t in temp:
  71. # 加密
  72. crypt_name = encrypt_oracle(t)
  73. # 解密
  74. uncrypt_name = decrypt_oralce(crypt_name)
  75. # print(t, uncrypt_name)
  76. if uncrypt_name != t:
  77. print(f"err ===原文 {t}, 加密后 {crypt_name} 解密后 {uncrypt_name}")