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
CodePudding user response:
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
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')