I have a video file which I am trying decrypt . The key is stored in a file. For some reasons it's not working and giving me this error "TypeError: Object type <class 'str'> cannot be passed to C code"
DecryptFile function I wrote takes 3 parameters
input file name ("input.ts")
output file name ("output.ts")
key for decryption ("k.kjs").
What I want it to do is decrypt the file with the key provided and save it with output name I gave . I am using Python 3.7.1
from Crypto.Cipher import AES
import os
def DecryptFile(infile,outfile,keyfile):
data = open(infile,"rb").read()
key = open(keyfile,"rb").read()
print(type(data))
iv = '\x00'*15 + chr(1)
aes_crypter = AES.new(key, AES.MODE_CBC, iv)
a = aes_crypter.decrypt(data)
with open(outfile, 'wb') as out_file:
out_file.write(a)
DecryptFile("input.ts","output.ts","k.kjs")
According to [ReadTheDocs.PyCryptodome]: AES - Crypto.Cipher.AES.new(key, mode, *args, **kwargs), iv should be:
Of type bytes
A kwarg
To get past this error, modify 2 lines of your code:
# ...
iv = b'\x00' * 15 + b'\x01'
aes_crypter = AES.new(key, AES.MODE_CBC, iv=iv)
# ...
Related
Basically, i am trying to encrypt 3 files in a folder with hybrid encryption, AES CBC. Successfully encrypted all the files, but having issues decrypting. The requirements for the task is:
2 seperate files, one for encrypting and one for decrypting
IV is 24 characters
IV can be hardcoded ,all files can use the same IV in or randomised (i randomised mine)
So far, only the last file is decrypted properly, the first 2 is giving me a ValueError error. However when i printed out the IV, it seems to be correct. Can someone advise me on this?
Encryption code
`#!/usr/bin/env python3
from base64 import b64encode
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Random import get_random_bytes
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import glob
for item in glob.glob("*.txt"):
skey = get_random_bytes(16)
recipent_key = RSA.import_key(open("receiver.pem").read())
file_out = open("encrypted_key.bin", "wb")
cipher_rsa = PKCS1_OAEP.new(recipent_key)
enc_data = cipher_rsa.encrypt(skey)
file_out.write(enc_data)
file_out.close()
data_in = open(item, 'rb')
data = data_in.read()
data_in.close()
cipher = AES.new(skey, AES.MODE_CBC)
ct_bytes = cipher.encrypt(pad(data, AES.block_size))
iv = b64encode(cipher.iv).decode('utf-8')
ct = b64encode(ct_bytes).decode('utf-8')
skey = b64encode(skey).decode('utf-8')
print(iv, ct, skey)
datain = (iv, ct)
Fileout = open(item,'w')
Fileout.writelines(datain)
Fileout.close()
`
Decryption code
`#!/usr/bin/env python3
from base64 import b64decode
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import os
import glob
for item in glob.glob("*.txt"):
file_in = open("encrypted_key.bin", "rb")
private_key = RSA.import_key(open("private.pem").read())
enc_data = file_in.read(private_key.size_in_bytes())
cipher_rsa = PKCS1_OAEP.new(private_key)
skey = cipher_rsa.decrypt(enc_data)
file_in.close()
in_file = open(item, "r")
data = in_file.read()
in_file.close()
print(data[0:24])
try:
iv = b64decode(data[0:24])
ct = b64decode(data[24:])
cipher = AES.new(skey, AES.MODE_CBC, iv)
pt = unpad(cipher.decrypt(ct), AES.block_size)
output = str(pt, 'utf-8')
print("the message was: ", output)
Fileout = open(item,'w')
Fileout.writelines(output)
Fileout.close()
except ValueError:
print("Incorrect decryption")
except KeyError:
print("incorrect key")
`
please send help :"")
EDIT: i realised, every round my loop goes, my key also randomise. that's the problem, i solved it :")
I am fairly new to AES en/decrypting so bare with me.
Using the Crypto (Cryptodome) Library, I am trying to decrypt a message with a known key and a known iv as String.
from base64 import b64decode
from Crypto.Cipher import AES
from Crypto.Util import Padding
key = "some_key_as_string" #
key = base64.b64decode(key)
key = key.rjust(16, "0")
iv = "some_iv_as_string"
iv = b64decode(iv)
cipher = AES.new(key, AES.MODE_CBC, iv)
ct = b'Test_ciphertext'
ct = ct.ljust(16, "0")
message = Padding.unpad(cipher.decrypt(ct), AES.block_size)
However this gives me an Error called 'Padding not correct' which I am not able to remove by myself.
The keysize should be 256 bit, not sure if I included this with the encoding.
Can you tell me what I am missing here?
Edit: I should add that rjust only worked for me when I encoded the "0".
So instead of
key = key.rjust(16, "0")
I used
r = str.encode("0")
key = key.rjust(16, r)
as well for the ct
I'm struggling to find the issue within the code:
I've txt file on my desktop that i want to encrypt, then decrypt.
I'm using AES CBC as my encryption method.
Assume the file contain the following string:
bla bla top secret!!
I'm able to encrypt it successfully with the following line: modify(r"C:\Users\XXXXX\Desktop\TEST.txt", encrypt_file) output: W¢ìPY#Šÿb[l®«fì]ßQzýµá˺cØäûE
Then I'm trying to decrypt it with the following line modify(r"C:\Users\XXXXX\Desktop\TEST.txt", decrypt_file)
I'm getting the following exception: ValueError: Padding is incorrect.
If I remove the unpad function i can see the text is partical unencrypted as follow: bla bla top secrv€\Èu¢Þ#xH‹AÄ
I can't find whats wrong here.
Any help will be appreciated.
import os
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
HARD_CODED_KEY = b"SOME KEY"
iv = b'1234567812345678'
def encrypt_file(file, key, blocksize=16):
cipher = AES.new(key, AES.MODE_CBC, iv)
ciphertext = cipher.encrypt(pad(file, blocksize))
return ciphertext
def decrypt_file(file, key, blocksize=16):
cipher = AES.new(key, AES.MODE_CBC, iv)
cleartext = unpad(cipher.decrypt(file), blocksize)
return cleartext
def modify(file, crypt, blocksize=16):
with open(file, "r+b") as f:
plaintext = f.read(blocksize)
while plaintext:
ciphertext = crypt(plaintext, HARD_CODED_KEY, blocksize)
f.seek(-len(plaintext), 1) # go back to the same point before the read
f.write(ciphertext)
plaintext = f.read(blocksize)
I want to make a script to decrypt my filess, but when I try to run my script then show me this message , how can I fix it?
Traceback (most recent call last): File "F:\bug_bounty\decrypt.py",
line 46, in File "F:\bug_bounty\decrypt.py", line 24, in
decrypt File
"C:\Python27\lib\site-packages\Crypto\Cipher\blockalgo.py", line 295,
in decrypt
return self._cipher.decrypt(ciphertext) ValueError: Input strings must be a multiple of 16 in length
from Crypto.Hash import SHA256
from Crypto.Cipher import AES
import os
import random
import sys
def decrypt(key, filename):
outFile = os.path.join(os.path.dirname(filename),
os.path.basename(filename[11:]))
chunksize = 64 * 1024
with open(filename, 'rb') as infile:
filesize = infile.read(16)
IV = infile.read(16)
decryptor = AES.new(key, AES.MODE_CBC, IV)
with open(outFile, 'wb') as outfile:
while True:
chunk = infile.read(chunksize)
if len(chunk) == 0:
break
outfile.write(decryptor.decrypt(chunk))
outfile.truncate(int(filesize))
def allfiles():
allFiles = []
for (root, subfiles, files) in os.walk(os.getcwd()):
for names in files:
allFiles.append(os.path.join(root, names))
return allFiles
password = 'M4st3rRul3zs'
files = allfiles();
for filename in files:
if os.path.basename(filename).startswith("(encrypted)"):
print "%s is already encrypted" %filename
pass
else:
decrypt(SHA256.new(password).digest(), filename)
print "Done decrypting %s" %filename
"""os.remove(filename)"""
Here is the small trick you could use while encrypting the data if your data size is not large.
plaintext = "some text"
encryptor = AES.new(key, AES.MODE_CBC, iv)
ciphertext = encryptor.encrypt(plaintext*16)
This will ensure that your input data is a multiple of 16. And of course, you would like to get the original data back when decrypting.
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypttext = cipher.decrypt(ciphertext)
decrypttext = decrypttext[0:len(plaintext)]
Now, decrpyttext has your original plaintext.
From Crypto++ wiki.
The block size is determined by AES::BLOCKSIZE. For AES, this is
always 16 bytes
AES is a block cipher, it works on 16-byte (128-bit) blocks. It can't work with data smaller or bigger than 16 bytes. Smaller data needs to be padded until they're 16 bytes, and larger data needs to be split into 16-byte blocks.
Also there are algorithms that help you achieve just that (work on data larger than the cipher's block size), they're called block cipher modes of operation.
Have a look at this How to encrypt more than 16 bytes using AES?
ValueError: Input strings must be a multiple of 16 in length
That is because AES works with blocks of 128 bits (16 chars). You can consider adding padding to fix this.
AES works with blocks of 16 chars. This how you can add extra padding
import random
import string
plaintext = "Encrypt me"
encryptor = AES.new(key, AES.MODE_CBC, iv)
while len(bytes(plaintext, encoding='utf-8')) % 16 != 0:
plaintext = plaintext + random.choice(string.ascii_letters)
ciphertext = encryptor.encrypt(plaintext)
I'm making programm for my school project and have one problem above.
Here's my code:
def aes():
#aes
os.system('cls')
print('1. Encrypt')
print('2. Decrypt')
c = input('Your choice:')
if int(c) == 1:
#cipher
os.system('cls')
print("Let's encrypt, alright")
print('Input a text to be encrypted')
text = input()
f = open('plaintext.txt', 'w')
f.write(text)
f.close()
BLOCK_SIZE = 32
PADDING = '{'
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
secret = os.urandom(BLOCK_SIZE)
f = open('aeskey.txt', 'w')
f.write(str(secret))
f.close()
f = open('plaintext.txt', 'r')
privateInfo = f.read()
f.close()
cipher = AES.new(secret)
encoded = EncodeAES(cipher, privateInfo)
f = open('plaintext.txt', 'w')
f.write(str(encoded))
f.close()
print(str(encoded))
if int(c) == 2:
os.system('cls')
print("Let's decrypt, alright")
f = open('plaintext.txt','r')
encryptedString = f.read()
f.close()
PADDING = '{'
DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)
encryption = encryptedString
f = open('aeskey.txt', 'r')
key = f.read()
f.close()
cipher = AES.new(key)
decoded = DecodeAES(cipher, encryption)
f = open('plaintext.txt', 'w')
f.write(decoded)
f.close()
print(decoded)
Full error text:
Traceback (most recent call last): File "C:/Users/vital/Desktop/Prog/Python/Enc_dec/Enc_dec.py", line 341, in aes()
File "C:/Users/vital/Desktop/Prog/Python/Enc_dec/Enc_dec.py", line 180, in aes cipher = AES.new(key)
File "C:\Users\vital\AppData\Local\Programs\Python\Python35-32\lib\site-packages\Crypto\Cipher\AES.py", line 179, in new return AESCipher(key, *args, **kwargs)
File "C:\Users\vital\AppData\Local\Programs\Python\Python35-32\lib\site-packages\Crypto\Cipher\AES.py", line 114, in init blockalgo.BlockAlgo.init(self, _AES, key, *args, **kwargs)
File "C:\Users\vital\AppData\Local\Programs\Python\Python35-32\lib\site-packages\Crypto\Cipher\blockalgo.py", line 401, in init self._cipher = factory.new(key, *args, **kwargs)
ValueError: AES key must be either 16, 24, or 32 bytes long
Process finished with exit code 1
What am I doing wrong?
The error is very clear. The key must be exactly of that size. os.urandom will return you the correct key. However this key is a bytes (binary string value). Furthermore, by using str(secret), the value of repr(secret) is written into the file instead of secret.
What is more confusing is that AES.new allows you to pass the key as Unicode! However, suppose the key was the ASCII bytes 1234123412341234. Now,
f.write(str(secret))
will write b'1234123412341234' to the text file! Instead of 16 bytes, it now contains those 16 bytes + the b, and two ' quote characters; 19 bytes in total.
Or if you take a random binary string from os.urandom,
>>> os.urandom(16)
b'\xd7\x82K^\x7fe[\x9e\x96\xcb9\xbf\xa0\xd9s\xcb'
now, instead of writing 16 bytes D7, 82,.. and so forth, it now writes that string into the file. And the error occurs because the decryption tries to use
"b'\\xd7\\x82K^\\x7fe[\\x9e\\x96\\xcb9\\xbf\\xa0\\xd9s\\xcb'"
as the decryption key, which, when encoded as UTF-8 results in
b"b'\\xd7\\x82K^\\x7fe[\\x9e\\x96\\xcb9\\xbf\\xa0\\xd9s\\xcb'"
which is a 49-bytes long bytes value.
You have 2 good choices. Either you continue to write your key to a text file, but convert it to hex, or write the key into a binary file; then the file should be exactly the key length in bytes. I am going for the latter here:
Thus for storing the key, use
with open('aeskey.bin', 'wb') as keyfile:
keyfile.write(secret)
and
with open('aeskey.bin', 'rb') as keyfile:
key = keyfile.read()
Same naturally applies to the cipher text (that is the encrypted binary), you must write and read it to and from a binary file:
with open('ciphertext.bin', 'wb') as f:
f.write(encoded)
and
with open('ciphertext.bin', 'rb') as f:
encryptedString = f.read()
If you want to base64-encode it, do note that base64.b64encode/decode are bytes-in/bytes-out.
By the way, plaintext is the original, unencrypted text; the encrypted text is called ciphertext. AES is a cipher that can encrypt plaintext to ciphertext and decrypt ciphertext to plaintext using a key.
Despite these being called "-text" neither of them is textual data per se, as understood by Python, but they're binary data, and should be represented as bytes.