5 回答
TA贡献1812条经验 获得超5个赞
这是完整的代码,以防有人仍在寻找。
测试针对:
python3.6
python3.8
** 使用pycryptodome
encrypt_aes.py
import hashlib
from Crypto.Cipher import AES
import base64
class AES_pkcs5:
def __init__(self,key:str, mode:AES.MODE_ECB=AES.MODE_ECB,block_size:int=16):
self.key = self.setKey(key)
self.mode = mode
self.block_size = block_size
def pad(self,byte_array:bytearray):
"""
pkcs5 padding
"""
pad_len = self.block_size - len(byte_array) % self.block_size
return byte_array + (bytes([pad_len]) * pad_len)
# pkcs5 - unpadding
def unpad(self,byte_array:bytearray):
return byte_array[:-ord(byte_array[-1:])]
def setKey(self,key:str):
# convert to bytes
key = key.encode('utf-8')
# get the sha1 method - for hashing
sha1 = hashlib.sha1
# and use digest and take the last 16 bytes
key = sha1(key).digest()[:16]
# now zero pad - just incase
key = key.zfill(16)
return key
def encrypt(self,message:str)->str:
# convert to bytes
byte_array = message.encode("UTF-8")
# pad the message - with pkcs5 style
padded = self.pad(byte_array)
# new instance of AES with encoded key
cipher = AES.new(self.key, AES.MODE_ECB)
# now encrypt the padded bytes
encrypted = cipher.encrypt(padded)
# base64 encode and convert back to string
return base64.b64encode(encrypted).decode('utf-8')
def decrypt(self,message:str)->str:
# convert the message to bytes
byte_array = message.encode("utf-8")
# base64 decode
message = base64.b64decode(byte_array)
# AES instance with the - setKey()
cipher= AES.new(self.key, AES.MODE_ECB)
# decrypt and decode
decrypted = cipher.decrypt(message).decode('utf-8')
# unpad - with pkcs5 style and return
return self.unpad(decrypted)
if __name__ == '__main__':
# message to encrypt
message = 'hello world'
secret_key = "65715AC165715AC165715AC165715AC1"
AES_pkcs5_obj = AES_pkcs5(secret_key)
encrypted_message = AES_pkcs5_obj.encrypt(message)
print(encrypted_message)
decrypted_message = AES_pkcs5_obj.decrypt(encrypted_message)
print(decrypted_message)
输出:
>>> python encrypt_aes.py
>>> PDhIFEVqLrJiZQC90FPHiQ== # encrypted message
>>> hello world # and the decrypted one
我已经测试了许多已经可用的代码,但没有一个提供像 java 那样的精确加密。所以,这是所有找到的博客和早期编写的与 python2 兼容的代码的组合
TA贡献1859条经验 获得超6个赞
我已经用下面的代码构建了 PKCS5 填充,并且按预期工作。
block_size=16
pad = lambda s: s + (block_size - len(s) % block_size) * chr(block_size - len(s) % block_size)
加密方法重写如下:
def encrypt(plainText,key):
aes = AES.new(key, AES.MODE_ECB)
encrypt_aes = aes.encrypt(pad(plainText))
encrypted_text = str(base64.encodebytes (encrypt_aes), encoding = 'utf-8')
return encrypted_text
TA贡献1796条经验 获得超4个赞
PKCS 5(或7)填充不是添加0个字节,而是添加一个c
字节with value
c (where
1 <= c <= 16 ) if you're
c`字节,短于块长度倍数。
因此,如果您已经有 16 的倍数,请添加完整的 16 个字节的值 16,并且如果您的最后一个块是“停止”(4 个字节),我们将添加 12 个字节的值(十六进制的 12)来填充该块0xc
。ETC。
这样,接收者(在解密最终块之后)可以检查最后一个字节c
并检查该值是否为1 <= c <= 16
(如果不是,则拒绝解密),然后检查最后一个c
字节确实都是相同的值,然后将它们从解密。这样,接收方不必猜测最后一个块的多少字节只是填充或实际上是纯文本的一部分。以 PKCS 方式执行此操作是明确的。
我将把编码留给你。
TA贡献1831条经验 获得超10个赞
您可以使用aes-pkcs5
包。我是作者,它使用cryptography
包而不是pycrypto
其他答案中使用的过时的包,并且与 Python 3.7+ 兼容。
您可以通过 pip 安装:
pip install aes-pkcs5
您使用以下方式发布的相同代码aes-pkcs5
:
from aes_pkcs5.algorithms.aes_ecb_pkcs5_padding import AESECBPKCS5Padding
key = "92oifgGh893*cj%7"
cipher = AESECBPKCS5Padding(key, "b64")
text = '{ "Message": "hello this is a plain text" , "user":"john.doe", "Email":"john.doe@example.com}'
encrypted_text = cipher.encrypt(text)
TA贡献1851条经验 获得超4个赞
有时,您可以使用由空字节分隔的随机字符串进行填充,以添加一点随机性。
import random
import string
from Crypto.Cipher import AES
NULL_BYTE = '\x00'
def random_string(size: int) -> str:
return ''.join([
random.choice(string.printable) for _ in range(size)
])
def encode_aes(value: str, key: str) -> bytes:
cipher = AES.new(key[:32], AES.MODE_ECB)
mod = len(value) % cipher.block_size
padding = (cipher.block_size - mod) % cipher.block_size
if padding > 0:
value += NULL_BYTE + random_string(padding - 1)
return cipher.encrypt(value)
def decode_aes(value: bytes, key: str) -> str:
cipher = AES.new(key[:32], AES.MODE_ECB)
decrypted = cipher.decrypt(value).decode('utf8')
return decrypted.rsplit(NULL_BYTE, 1)[0]
添加回答
举报