AES加密Python代码运行报错:TypeError:字符串类型无法传入C代码
AES加密代码运行报错排查与解决
问题描述
正在学习计算机安全领域的AES加密技术,编写了两段实现AES加解密的代码(encryption.py和decryption.py),运行代码时输入密码"test"触发TypeError,无法正常完成加解密操作。
encryption.py 代码
# AES 256 encryption/decryption using pycrypto library import base64 import hashlib from Crypto.Cipher import AES from Crypto import Random BLOCK_SIZE = 16 pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE) unpad = lambda s: s[:-ord(s[len(s) - 1:])] password = input("Enter encryption password: ") def encrypt(raw, password): private_key = hashlib.sha256(password.encode("utf-8")).digest() raw = pad(raw) iv = Random.new().read(AES.block_size) cipher = AES.new(private_key, AES.MODE_CBC, iv) return base64.b64encode(iv + cipher.encrypt(raw)) def decrypt(enc, password): private_key = hashlib.sha256(password.encode("utf-8")).digest() enc = base64.b64decode(enc) iv = enc[:16] cipher = AES.new(private_key, AES.MODE_CBC, iv) return unpad(cipher.decrypt(enc[16:])) # First let us encrypt secret message encrypted = encrypt("This is a secret message", password) print(encrypted) # Let us decrypt using our original password decrypted = decrypt(encrypted, password) print(bytes.decode(decrypted))
decryption.py 代码
import base64 from Crypto.Cipher import AES from Crypto import Random from Crypto.Protocol.KDF import PBKDF2 BLOCK_SIZE = 16 pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE) unpad = lambda s: s[:-ord(s[len(s) - 1:])] password = input("Enter encryption password: ") def get_private_key(password): salt = b"this is a salt" kdf = PBKDF2(password, salt, 64, 1000) key = kdf[:32] return key def encrypt(raw, password): private_key = get_private_key(password) raw = pad(raw) iv = Random.new().read(AES.block_size) cipher = AES.new(private_key, AES.MODE_CBC, iv) return base64.b64encode(iv + cipher.encrypt(raw)) def decrypt(enc, password): private_key = get_private_key(password) enc = base64.b64decode(enc) iv = enc[:16] cipher = AES.new(private_key, AES.MODE_CBC, iv) return unpad(cipher.decrypt(enc[16:])) # First let us encrypt secret message encrypted = encrypt("This is a secret message", password) print(encrypted) # Let us decrypt using our original password decrypted = decrypt(encrypted, password) print(bytes.decode(decrypted))
报错信息
Enter encryption password: test Traceback (most recent call last): File "c:\AES testing\encryptionAES.py", line 31, in <module> encrypted = encrypt("This is a secret message", password) File "c:\AES testing\encryptionAES.py", line 19, in encrypt return base64.b64encode(iv + cipher.encrypt(raw)) File "C:\Users\xxxx\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\Crypto\Cipher\_mode_cbc.py", line 178, in encrypt c_uint8_ptr(plaintext), File "C:\Users\xxxx\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\Crypto\Util\_raw_api.py", line 242, in c_uint8_ptr raise TypeError("Object type %s cannot be passed to C code" % type(data)) TypeError: Object type <class 'str'> cannot be passed to C code
问题原因
报错的核心原因是:PyCryptodome库的AES加密函数cipher.encrypt()要求输入的明文必须是字节串(bytes类型),但代码中传入的是字符串(str类型)。库的底层C实现无法直接处理Python字符串,因此抛出类型错误。
解决方法
需要对两个代码文件中的encrypt和decrypt函数做如下修改,确保数据类型匹配:
1. 修改 encryption.py
- encrypt函数:补位完成后,将字符串编码为字节串再传入加密函数
- decrypt函数:解密得到字节串后,先解码为字符串再执行去补位操作
修改后的代码片段:
def encrypt(raw, password): private_key = hashlib.sha256(password.encode("utf-8")).digest() raw = pad(raw).encode('utf-8') # 补位后转字节串 iv = Random.new().read(AES.block_size) cipher = AES.new(private_key, AES.MODE_CBC, iv) return base64.b64encode(iv + cipher.encrypt(raw)) def decrypt(enc, password): private_key = hashlib.sha256(password.encode("utf-8")).digest() enc = base64.b64decode(enc) iv = enc[:16] cipher = AES.new(private_key, AES.MODE_CBC, iv) decrypted_bytes = cipher.decrypt(enc[16:]) return unpad(decrypted_bytes.decode('utf-8')) # 先转字符串再去补位
2. 修改 decryption.py
做同样的类型适配修改:
def encrypt(raw, password): private_key = get_private_key(password) raw = pad(raw).encode('utf-8') # 补位后转字节串 iv = Random.new().read(AES.block_size) cipher = AES.new(private_key, AES.MODE_CBC, iv) return base64.b64encode(iv + cipher.encrypt(raw)) def decrypt(enc, password): private_key = get_private_key(password) enc = base64.b64decode(enc) iv = enc[:16] cipher = AES.new(private_key, AES.MODE_CBC, iv) decrypted_bytes = cipher.decrypt(enc[16:]) return unpad(decrypted_bytes.decode('utf-8')) # 先转字符串再去补位
验证修改效果
修改后重新运行代码,输入密码"test",即可正常输出加密后的字节串,以及解密还原后的明文This is a secret message。
内容的提问来源于stack exchange,提问作者Abigiya Terefe
相关产品推荐
相关产品推荐

