I need to make a client-server connection from node.js/javascript server to a client written in Rust. The message had to be encrypted with AES-GCM-256. While in Rust (version 1.67.0) I use aes-gcm crate.
The Rust code below throws an error: aead::Error
. What's wrong with the cipher.decrypt()
here ?
I'm sure that the node.js implementation is correct. I think that the key
variable in Rust code should be the same key from the node.js (12341234123412341234123412341234
)
Implementation in Node.js / sender side
const crypto = require('crypto')
const aes256gcm = (key) => {
const encrypt = (str) => {
const iv = new crypto.randomBytes(12);
const ivString = iv.toString("base64")
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
let enc1 = cipher.update(str, 'utf8');
let enc2 = cipher.final();
let result = Buffer.concat([enc1, enc2, iv, cipher.getAuthTag()]).toString("base64");
return { result, iv: ivString }
};
const decrypt = (enc) => {
enc = Buffer.from(enc, "base64");
const iv = enc.slice(enc.length - 28, enc.length - 16);
const tag = enc.slice(enc.length - 16);
enc = enc.slice(0, enc.length - 28);
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
decipher.setAuthTag(tag);
let str = decipher.update(enc, null, 'utf8');
str += decipher.final('utf8');
return str;
};
return {
encrypt,
decrypt,
};
};
const cipher = aes256gcm("12341234123412341234123412341234"); // just a test key must be 32
const ct = cipher.encrypt('Hello world!!!');
console.log("encrypted message: ", ct.result)
console.log("iv / nonce : ", ct.iv)
const pt = cipher.decrypt(ct.result);
console.log("decrypted message: ", pt); // this works flawlessly!
Encryption Result by Node.js
encrypted message: Zf5aB0bbVGGX3k9Yt6x+9daxCGZO0MmwYW8VUsOY4j3gNYXP47hvfGgd
iv / nonce : fvXWsQhmTtDJsGFv
decrypted message: Hello world!!!
The decryption part (Rust) / Receiver Side
use aes_gcm::{
aead::{Aead, KeyInit, OsRng},
Aes256Gcm, Nonce,
};
use base64::{engine::general_purpose, Engine as _};
fn main() {
// should this be random or should I also get the same key from the sender ?
let master = "12341234123412341234123412341234".as_bytes();
let cipher = Aes256Gcm::new_from_slice(master).unwrap();
// nonce / iv from sender
let nonce_str_base64 = "fvXWsQhmTtDJsGFv";
let nonce_str: Vec<u8> = general_purpose::STANDARD.decode(nonce_str_base64).unwrap();
let nonce = Nonce::from_slice(&nonce_str); // 96-bits; unique per message
// encrypted text from sender
let ciphertext_base64 = "Zf5aB0bbVGGX3k9Yt6x+9daxCGZO0MmwYW8VUsOY4j3gNYXP47hvfGgd";
let ciphertext = general_purpose::STANDARD.decode(ciphertext_base64).unwrap();
// gets aead::Error here
match cipher.decrypt(nonce, ciphertext.as_slice()) {
Ok(decrypted) => {
let result = String::from_utf8(decrypted).unwrap();
println!("result: {}", result);
}
Err(err) => print!("{}", err), <--- prints error: aead::Error
};
}