TypeError: Object type <class 'str'> cannot be passed to C code using pycryptodome

TypeError: Object type <class 'str'> cannot be passed to C code using pycryptodome

我有这段代码,它曾经在 Python 3.6 或 3.7 中工作(我不记得是哪个版本)

现在我在 Python 3.9.1 中尝试使用相同的代码,但出现错误。我正在使用 pycryptodome

from base64 import b64encode, b64decode
from Crypto.Cipher import AES

SOME_SECRET_KEY = 'HPo7OLqB4Fkk4E2yGOtwqw8H5fHR9kNx67OR4g4UdlA='
SOME_IV = 'p5ldmBPdd/9pjC0bDC/nSg=='
secret_key_in_bytes = bytes(b64decode(SOME_SECRET_KEY))
iv_in_bytes = bytes(b64decode(SOME_IV))

def decrypt_with_padding(data):
    cypto_obj = AES.new(secret_key_in_bytes, AES.MODE_CBC, iv_in_bytes)
    decrypted = cypto_obj.decrypt(b64decode(data))
    bytes_to_string = decrypted.decode("utf-8")
    decrypted_data = pkcs5_unpad(bytes_to_string)
    return decrypted_data


def encrypt_with_padding(data):
    cypto_obj = AES.new(secret_key_in_bytes, AES.MODE_CBC, iv_in_bytes)
    encrypted_data = cypto_obj.encrypt(pkcs5_pad(str(data)))
    return b64encode(encrypted_data).decode()


def pkcs5_pad(s, BLOCK_SIZE=16):
    return s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(
        BLOCK_SIZE - len(s) % BLOCK_SIZE
    )


def pkcs5_unpad(s):
    return s[0: -ord(s[-1])]


if __name__ == "__main__":
    data = '{"idServicio":79, "idProducto":209 , "referencia": "40425475190118187271", "montoPago": 9999, "telefono":"1111111111", "horaLocal":"20200401222821"}'
    encrypted = encrypt_with_padding(data)
    print(encrypted)
    decrypted = decrypt_with_padding(encrypted)
    print(decrypted)

这是错误

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-d94343c778d2> in <module>
     33 if __name__ == "__main__":
     34     data = '{"idServicio":79, "idProducto":209 , "referencia": "40425475190118187271", "montoPago": 9999, "telefono":"1111111111", "horaLocal":"20200401222821"}'
---> 35     encrypted = encrypt_with_padding(data)
     36     print(encrypted)
     37     decrypted = decrypt_with_padding(encrypted)

<ipython-input-3-d94343c778d2> in encrypt_with_padding(data)
     17 def encrypt_with_padding(data):
     18     cypto_obj = AES.new(secret_key_in_bytes, AES.MODE_CBC, iv_in_bytes)
---> 19     encrypted_data = cypto_obj.encrypt(pkcs5_pad(str(data)))
     20     return b64encode(encrypted_data).decode()
     21 

/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/Crypto/Cipher/_mode_cbc.py in encrypt(self, plaintext, output)
    176 
    177         result = raw_cbc_lib.CBC_encrypt(self._state.get(),
--> 178                                          c_uint8_ptr(plaintext),
    179                                          c_uint8_ptr(ciphertext),
    180                                          c_size_t(len(plaintext)))

/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/Crypto/Util/_raw_api.py in c_uint8_ptr(data)
    136             return data
    137         else:
--> 138             raise TypeError("Object type %s cannot be passed to C code" % type(data))
    139 
    140     class VoidPointer_cffi(_VoidPointer):

TypeError: Object type <class 'str'> cannot be passed to C code

我尝试使用数据变量的前缀 b'string' 将字符串转换为字节,但它都不起作用。

感谢您的宝贵时间

将str转换为byte的方法是使用.encode('utf-8')。 cypto_obj.encrypt接收一个字节对象,所以需要对pkcs5_pad的输出进行编码:

def pkcs5_pad(s, BLOCK_SIZE=16):                                                                                                                                                              
    return (s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(                                                                                                                                     
        BLOCK_SIZE - len(s) % BLOCK_SIZE                                                                                                                                                      
    )).encode('utf-8')