为了账号安全,请及时绑定邮箱和手机立即绑定

在 Python 中实现 AES/ECB/PKCS5 填充

在 Python 中实现 AES/ECB/PKCS5 填充

当年话下 2023-10-06 19:23:44
我正在尝试实现一个 python 程序来使用 AES/ECB/PKCS5 填充来加密纯文本。我得到的输出与预期略有不同。Python3程序:import base64from Crypto.Cipher import AES def add_to_16(value):    while len(value) % 16 != 0:        value += '\0'    return str.encode (value) # returns bytes # Encryption methoddef encrypt(text):         # Secret key     key='92oifgGh893*cj%7'          # Text to be encrypted         # Initialize encryptor    aes = AES.new(key, AES.MODE_ECB)          # Aes encryption to be    encrypt_aes = aes.encrypt(add_to_16(text))          # Converted into a string with base64    encrypted_text = str(base64.encodebytes (encrypt_aes), encoding = 'utf-8')    print(encrypted_text)    return encrypted_textif __name__ == '__main__':     text = '{  "Message": "hello this is a plain text" , "user":"john.doe", "Email":"john.doe@example.com}'    entrypted_text = encrypt(text)上述程序的输出是:oo8jwHQNQnBwVUsJ5piShFRM3PFFIfULwcoFOEQhPMTAvexSr6eE9aFLVQTpAKBFkGi8vNbtScvyexSxHBlwVapJ5Szz1JPR9q9cHHJYYMzGocln4TRPFQ6S3e8jjVud使用第三方工具在线验证时,结果为:oo8jwHQNQnBwVUsJ5piShFRM3PFFIfULwcoFOEQhPMTAvexSr6eE9aFLVQTpAKBFkGi8vNbtScvyexSxHBlwVapJ5Szz1JPR9q9cHHJYYMwnIIuNCUVn/IExpxebqXV1有人可以指导我哪里做错了吗?
查看完整描述

5 回答

?
慕雪6442864

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 兼容的代码的组合


查看完整回答
反对 回复 2023-10-06
?
BIG阳

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


查看完整回答
反对 回复 2023-10-06
?
SMILET

TA贡献1796条经验 获得超4个赞

PKCS 5(或7)填充不是添加0个字节,而是添加一个c字节with value(where1 <= c <= 16 ) if you're c`字节,短于块长度倍数。

因此,如果您已经有 16 的倍数,请添加完整的 16 个字节的值 16,并且如果您的最后一个块是“停止”(4 个字节),我们将添加 12 个字节的值(十六进制的 12)来填充该块0xc。ETC。

这样,接收者(在解密最终块之后)可以检查最后一个字节c并检查该值是否为1 <= c <= 16(如果不是,则拒绝解密),然后检查最后一个c字节确实都是相同的值,然后将它们从解密。这样,接收方不必猜测最后一个块的多少字节只是填充或实际上是纯文本的一部分。以 PKCS 方式执行此操作是明确的。

我将把编码留给你。


查看完整回答
反对 回复 2023-10-06
?
慕哥6287543

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)


查看完整回答
反对 回复 2023-10-06
?
繁花不似锦

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]


查看完整回答
反对 回复 2023-10-06
  • 5 回答
  • 0 关注
  • 190 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信