#!/usr/bin/env python # -*- coding=utf-8 -*- """ AES加密解密工具类 @author jzx @date 2018/10/24 此工具类加密解密结果与 http://tool.chacuo.net/cryptaes 结果一致 数据块128位 key 为16位 iv 为16位,且与key相等 字符集utf-8 输出为base64 AES加密模式 为cbc 填充 pkcs7padding """ import base64 from Crypto.Cipher import AES import random def pkcs7padding(text): """ 明文使用PKCS7填充 最终调用AES加密方法时,传入的是一个byte数组,要求是16的整数倍,因此需要对明文进行处理 :param text: 待加密内容(明文) :return: """ bs = AES.block_size # 16 length = len(text) bytes_length = len(bytes(text, encoding='utf-8')) # tips:utf-8编码时,英文占1个byte,而中文占3个byte padding_size = length if (bytes_length == length) else bytes_length padding = bs - padding_size % bs # tips:chr(padding)看与其它语言的约定,有的会使用'\0' padding_text = chr(padding) * padding return text + padding_text def pkcs7unpadding(text): """ 处理使用PKCS7填充过的数据 :param text: 解密后的字符串 :return: """ length = len(text) unpadding = ord(text[length - 1]) return text[0:length - unpadding] def encrypt(key, content): """ AES加密 key,iv使用同一个 模式cbc 填充pkcs7 :param key: 密钥 :param content: 加密内容 :return: """ key_bytes = bytes(key, encoding='utf-8') iv = key_bytes cipher = AES.new(key_bytes, AES.MODE_CBC, iv) # 处理明文 content_padding = pkcs7padding(content) # 加密 encrypt_bytes = cipher.encrypt(bytes(content_padding, encoding='utf-8')) # 重新编码 result = str(base64.b64encode(encrypt_bytes), encoding='utf-8') return result def decrypt(key, content): """ AES解密 key,iv使用同一个 模式cbc 去填充pkcs7 :param key: :param content: :return: """ key_bytes = bytes(key, encoding='utf-8') iv = key_bytes cipher = AES.new(key_bytes, AES.MODE_CBC, iv) # base64解码 encrypt_bytes = base64.b64decode(content) # 解密 decrypt_bytes = cipher.decrypt(encrypt_bytes) # 重新编码 result = str(decrypt_bytes, encoding='utf-8') # 去除填充内容 result = pkcs7unpadding(result) return result def get_key(n): """ 获取密钥 n 密钥长度 :return: """ c_length = int(n) source = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678' length = len(source) - 1 result = '' for i in range(c_length): result += source[random.randint(0, length)] return result if __name__ == "__main__": # Test # 非16字节的情况 aes_key = get_key(16) print('aes_key:' + aes_key) # 对英文加密 source_en = 'Hello!+world' encrypt_en = encrypt(aes_key, source_en) print(encrypt_en) # 解密 decrypt_en = decrypt(aes_key, encrypt_en) print(decrypt_en) print(source_en == decrypt_en) # 中英文混合加密 source_mixed = 'Hello, 韩- 梅 -梅' encrypt_mixed = encrypt(aes_key, source_mixed) print(encrypt_mixed) decrypt_mixed = decrypt(aes_key, encrypt_mixed) print(decrypt_mixed) print(decrypt_mixed == source_mixed) # 刚好16字节的情况 en_16 = 'abcdefgj10124567' encrypt_en = encrypt(aes_key, en_16) print(encrypt_en) # 解密 decrypt_en = decrypt(aes_key, encrypt_en) print(decrypt_en) print(en_16 == decrypt_en) mix_16 = 'abx张三丰12sa' encrypt_mixed = encrypt(aes_key, mix_16) print(encrypt_mixed) decrypt_mixed = decrypt(aes_key, encrypt_mixed) print(decrypt_mixed) print(decrypt_mixed == mix_16)