I've created a TypeScript example from MDN example as verbatim as I could to illustrate. It encrypts and decrypts just fine. I just noticed that, for Decryption to work, it requires the same init_vector
from encryption. Isn't the init_vector
supposed to be a nonce?
How is the person receiving the message going to know what the init_vector
I've used for encryption if decryption is a separate process done at a different place and time?
const message_plain: string = "Hello World!";
const password_plain: string = "letmein";
// AES-GCM - ENCRYPTION
const pbkdf2_salt: Uint8Array = crypto.getRandomValues(new Uint8Array(16)); // 128 bits
const pbkdf2_iterations: number = 100000;
const init_vector: Uint8Array = crypto.getRandomValues(new Uint8Array(12)); // 96 bits
const utf8_encoder: TextEncoder = new TextEncoder();
const message_bytes: Uint8Array = utf8_encoder.encode(message_plain);
const password_bytes: Uint8Array = utf8_encoder.encode(password_plain);
const crypto_key_material: CryptoKey = await crypto.subtle.importKey(
"raw",
password_bytes,
{ name: "PBKDF2" },
false,
["deriveBits", "deriveKey"],
);
const crypto_key_derived: CryptoKey = await crypto.subtle.deriveKey(
{
"name": "PBKDF2",
salt: pbkdf2_salt,
"iterations": pbkdf2_iterations,
"hash": "SHA-256",
},
crypto_key_material,
{ "name": "AES-GCM", "length": 256 },
true,
["encrypt", "decrypt"],
);
const message_encrypted: ArrayBuffer = await crypto.subtle.encrypt(
{ name: "AES-GCM", iv: init_vector },
crypto_key_derived,
message_bytes,
);
const message_encrypted_bytes: Uint8Array = new Uint8Array(message_encrypted);
console.log(
`[${message_encrypted.byteLength} bytes total] -> ${message_encrypted_bytes}`,
);
// AES-GCM - DECRYPTION
const utf8Decoder: TextDecoder = new TextDecoder();
try {
const message_decrypted: ArrayBuffer = await crypto.subtle.decrypt(
{ name: "AES-GCM", iv: init_vector },
crypto_key_derived,
message_encrypted,
);
const message_decrypted_bytes: Uint8Array = new Uint8Array(message_decrypted);
console.log(utf8Decoder.decode(message_decrypted_bytes));
} catch (e) {
console.log("*** Decryption error ***");
}
CodePudding user response:
You should use asymmetric encryption like RSA which has a public / private key, for example this node-rsa package.
In terms of having the same initial vector, I found this snippet taken from this answer:
In any case, the IV never needs to be kept secret — if it did, it would be a key, not an IV. Indeed, in most cases, keeping the IV secret would not be practical even if you wanted to since the recipient needs to know it in order to decrypt the data (or verify the hash, etc.).