简体   繁体   中英

Object type <class 'tuple'> cannot be passed to C code when encrypting file in django

so i want to encrypt file.txt with keyword i was input. but i got error message

Object type <class 'tuple'> cannot be passed to C code

my problem is with this code:

aes = AES.new(key.encode('utf8'), AES.MODE_CTR, counter=ctr)

if i add encode to ctr, then i got error message 'dict' object has no attribute 'encode'

if i remove don't add any encode to key and ctr, then i got error message Object type <class 'str'> cannot be passed to C code

can someone please help me to fix it? i was using django to encrypt with AES 128 with method CTR. or maybe someone can give me example aes encryption with another method but can be run in django. here's my full function code:

# AES supports multiple key sizes: 16 (AES128), 24 (AES192), or 32 (AES256).
key_bytes = 16
# Takes as input a 32-byte key and an arbitrary-length plaintext and returns a
# pair (iv, ciphtertext). "iv" stands for initialization vector.
def encrypt(key, testpass):
    assert len(key) == key_bytes
    print(testpass)
    print(key)
    # Choose a random, 16-byte IV.
    iv = Random.new().read(AES.block_size)

    # Convert the IV to a Python integer.
    iv_int = int(binascii.hexlify(iv), 16)

    # Create a new Counter object with IV = iv_int.
    ctr = Counter.new(AES.block_size * 8, initial_value=iv_int)
    print(ctr)

    # Create AES-CTR cipher.
    aes = AES.new(key.encode('utf8'), AES.MODE_CTR, counter=ctr)

    # Encrypt and return IV and ciphertext.
    ciphertext = aes.encrypt(testpass)
    print(iv)
    print(ciphertext)
    return (iv, ciphertext)

here's how i called that function:

testpass = Audio_store.objects.all().values_list('password').last()
enkripsi = encrypt("testingtesting11", testpass)

when i print testpass, it contains ('testpass_3kEMV2T.txt',)

but when i print testpass.encode("utf-8"), it shows nothing

Your test data is ('testpass_3kEMV2T.txt',) , you need to pull out the element from the tuple and pass it in as bytes to your encrypt method, because the AES.encrypt method requires bytes | bytearray | memoryview bytes | bytearray | memoryview bytes | bytearray | memoryview as its argument. Here's a version of your encrypt that determines if the argument you pass it is a str and encodes it to bytes if so (but it doesn't check if it's otherwise bytes , I leave that as an exercise for you if you want more stringent checking).

import binascii


from Crypto.Cipher import AES
from Crypto.Util import Counter
from Crypto import Random

key_bytes = 16

# here's a rudimentary change that accepts bytes or
# str
def encrypt(key, plaintext):
    if isinstance(plaintext, str):
        plaintext = plaintext.encode("utf-8")

    assert len(key) == key_bytes
    # Choose a random, 16-byte IV.
    iv = Random.new().read(AES.block_size)

    # Convert the IV to a Python integer.
    iv_int = int(binascii.hexlify(iv), 16)

    # Create a new Counter object with IV = iv_int.
    ctr = Counter.new(AES.block_size * 8, initial_value=iv_int)
    print(ctr)

    # Create AES-CTR cipher.
    aes = AES.new(key.encode('utf8'), AES.MODE_CTR, counter=ctr)

    # Encrypt and return IV and ciphertext.
    ciphertext = aes.encrypt(plaintext)
    return (iv, ciphertext)

# for now, since you're getting your data from the db which is a 1-tuple, you have to pull out the first elem
testpass = ('testpass_3kEMV2T.txt',)
print(encrypt("a"*16, testpass[0]))

Output:

{'counter_len': 16, 'prefix': b'', 'suffix': b'', 'initial_value': 302861312392273214314458272471454024973, 'little_endian': False}
(b'\xe3\xd8\xf7\x90\xcd\x96m\xcb\xa5g)\xd1\xda\xc3\x85\r', b'-F)\x83\x9a\xf9\xe1\xc3\xfb\xfa_<^\x1c:q\x07\xa1@\xbb')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM