I made the following MRE to illustrate my problem. My Python code is taking a string, encrypting it with an ad-hoc created key and posting it to a Node server that is supposed to use the provided key for decryption.
- Using the console output I can see that the Python output (key and encrypted message) are the same on both systems (after base64 conversion for transfer).
- Also from another post on stackoverflow, I understand that the key generated by Pyhon is already base64 encoded and the decoded value needs to be split to extract the iv and key respectively.
However, I get an error saying that the iv length is invalid. I am not sure what I am doing wrong. Thanks for your hints.
Python Code fernet.py (Python 3.10.5 on Windows 11)
import requests
import base64
from cryptography.fernet import Fernet
def get_key():
key = Fernet.generate_key()
return key
def enc(input, key):
f = Fernet(key)
encrypted = f.encrypt(input.encode())
return encrypted
msg = "hello world"
key = get_key()
cypher = enc(msg, key)
print("msg: " + msg)
print("key: " + key.decode())
print("cyp: " + cypher.decode())
url='http://.../test'
headers = {'Content-type': 'application/json'}
r = requests.post(url, data={"key": key, "msg": base64.b64encode(cypher)})
Output:
msg: hello world
key: bOe3HCoveTPhHi04FvvG697O2rEkwF9vuXeZcGgbu9k=
cyp: gAAAAABi0WYLxwlMG7RGKqISZABsPlmenUmN8Ii81rJBIQdSPGzi1-IHss4atZuGp4eZIdaiR7mpBah6cQmlXxw2DzY3Ct9d7A==
Here is my node server (12.22.09 running on a Ubuntu 22.04 VM)
const express = require('express');
const url = require('url');
const crypto = require('crypto');
const app = express();
const port = 8088;
app.use(express.urlencoded({extended: true, limit:'100mb', parameterLimit:1000000}));
app.disable('x-powered-by');
function decrypt(message, fernet) {
let iv = Buffer.from(fernet, 'base64').toString('binary', 0, 16)
let key = Buffer.from(fernet, 'base64').toString('binary', 16,32);
let decoded_msg = Buffer.from(message, 'base64').toString('utf8');
let decipher = crypto.createDecipheriv('aes-128-cbc', key, iv);
let decrypted = decipher.update(decoded_msg, 'binary', 'utf8') + decipher.final('utf8');
console.log(decrypted);
return decrypted
}
app.post("/test", function(req, res) {
let fernet = req.body.key;
let message = req.body.msg;
console.log("key: " + fernet);
console.log("msg: " + Buffer.from(message, 'base64').toString('utf8'));
let dec = decrypt(message, fernet);
console.log("dec: " + dec);
res.writeHead(200, {"Content-Type": "application/json"});
res.end(JSON.stringify({"status": "OK"}));
});
app.listen(port, () => {
console.log("Listening on localhost:" + port);
});
Output:
key: bOe3HCoveTPhHi04FvvG697O2rEkwF9vuXeZcGgbu9k=
msg: gAAAAABi0WYLxwlMG7RGKqISZABsPlmenUmN8Ii81rJBIQdSPGzi1-IHss4atZuGp4eZIdaiR7mpBah6cQmlXxw2DzY3Ct9d7A==
Error: Invalid IV length
at Decipheriv.createCipherBase (internal/crypto/cipher.js:103:19)
at Decipheriv.createCipherWithIV (internal/crypto/cipher.js:121:20)
at new Decipheriv (internal/crypto/cipher.js:262:22)
at Object.createDecipheriv (crypto.js:131:10)
at decrypt (/.../app.js:55:24)