I’m trying to encrypt files (trying with png) in Javascript (ReactJs) and I want to be able to decrypt the files and restore their original state in Python.
I’ve tried multiple approaches but the below JS code was the only one I got working properly. With the JS code, I’m able to get back the png in its original form. However, I seem to be missing something with padding as I keep getting:
Traceback (most recent call last):
File "***/encrypt_decrypt_using_aes.py", line 110, in <module>
decrypted = decrypt(encData, key, iv)
File "***/encrypt_decrypt_using_aes.py", line 103, in decrypt
return unpad(cipher.decrypt(enc),16)
File "/usr/local/lib/python3.9/site-packages/Crypto/Util/Padding.py", line 90, in unpad
raise ValueError("Padding is incorrect.")
ValueError: Padding is incorrect.
I tried playing with ZeroPadding, NoPadding, PKCS7 but nothing worked.
Any ideas on what I am missing?
JS code:
function decrypt(input) {
var file = input;
var reader = new FileReader();
reader.onload = () => {
var key = "1234567887654321";
var decrypted = CryptoJS.AES.decrypt(reader.result, key, {mode: CryptoJS.mode.CBC}); // Decryption: I: Base64 encoded string (OpenSSL-format) -> O: WordArray
var typedArray = convertWordArrayToUint8Array(decrypted); // Convert: WordArray -> typed array
var fileDec = new Blob([typedArray]); // Create blob from typed array
var a = document.createElement("a");
var url = window.URL.createObjectURL(fileDec);
var filename = file.name.substr(0, file.name.length - 4);
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
};
reader.readAsText(file);
}
function encrypt(input) {
var file = input
console.log("In Encrypt")
console.log(file)
var reader = new FileReader();
var iv = CryptoJS.enc.Utf8.parse('53509bee-8207-11');
reader.onload = () => {
var key = "1234567887654321";
var wordArray = CryptoJS.lib.WordArray.create(reader.result); // Convert: ArrayBuffer -> WordArray
var encrypted = CryptoJS.AES.encrypt(wordArray, key, {iv: iv, mode: CryptoJS.mode.CBC}).toString(); // Encryption: I: WordArray -> O: -> Base64 encoded string (OpenSSL-format)
var fileEnc = new Blob([encrypted]); // Create blob from string
// var a = document.createElement("a");
// var url = window.URL.createObjectURL(fileEnc);
var filename = input.name + ".enc";
console.log(filename)
var file = new File([fileEnc], filename);
// a.href = url;
// a.download = filename;
// a.click();
// window.URL.revokeObjectURL(url);
setFiles2State(files2State => ({
fileList2: [...files2State.fileList2, file],
}));
console.log("OUT LIST")
console.log(files2State)
};
reader.readAsArrayBuffer(file);
}
Python code (Not working):
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad,unpad
def encrypt(data,key,iv):
data= pad(data.encode(),16)
cipher = AES.new(key.encode('utf-8'),AES.MODE_CBC,iv)
return base64.b64encode(cipher.encrypt(data))
def decrypt(enc,key,iv=None):
enc = base64.b64decode(enc)
# enc = enc.encode('utf-8')
if iv == None:
cipher = AES.new(key.encode('utf-8'), AES.MODE_CBC)
else:
cipher = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv)
return unpad(cipher.decrypt(enc),16)
with open("demo_file.png.enc", "r+") as fileIn:
encData = fileIn.read()
key = "1234567887654321"
iv = "53509bee-8207-11".encode('utf-8')
decrypted = decrypt(encData, key, iv)
with open("demo_file.png", "wb") as fileOut:
fileOut.write(decrypted)