Skip to content

Instantly share code, notes, and snippets.

@rjz
Last active March 11, 2024 20:11
Show Gist options
  • Star 54 You must be signed in to star a gist
  • Fork 18 You must be signed in to fork a gist
  • Save rjz/15baffeab434b8125ca4d783f4116d81 to your computer and use it in GitHub Desktop.
Save rjz/15baffeab434b8125ca4d783f4116d81 to your computer and use it in GitHub Desktop.
example using node.js crypto API with aes-256-gcm
const buffer = require('buffer');
const crypto = require('crypto');
// Demo implementation of using `aes-256-gcm` with node.js's `crypto` lib.
const aes256gcm = (key) => {
const ALGO = 'aes-256-gcm';
// encrypt returns base64-encoded ciphertext
const encrypt = (str) => {
// The `iv` for a given key must be globally unique to prevent
// against forgery attacks. `randomBytes` is convenient for
// demonstration but a poor way to achieve this in practice.
//
// See: e.g. https://csrc.nist.gov/publications/detail/sp/800-38d/final
const iv = new Buffer(crypto.randomBytes(12), 'utf8');
const cipher = crypto.createCipheriv(ALGO, key, iv);
// Hint: Larger inputs (it's GCM, after all!) should use the stream API
let enc = cipher.update(str, 'utf8', 'base64');
enc += cipher.final('base64');
return [enc, iv, cipher.getAuthTag()];
};
// decrypt decodes base64-encoded ciphertext into a utf8-encoded string
const decrypt = (enc, iv, authTag) => {
const decipher = crypto.createDecipheriv(ALGO, key, iv);
decipher.setAuthTag(authTag);
let str = decipher.update(enc, 'base64', 'utf8');
str += decipher.final('utf8');
return str;
};
return {
encrypt,
decrypt,
};
};
const KEY = new Buffer(crypto.randomBytes(32), 'utf8');
const aesCipher = aes256gcm(KEY);
const [encrypted, iv, authTag] = aesCipher.encrypt('hello, world');
const decrypted = aesCipher.decrypt(encrypted, iv, authTag);
console.log(decrypted); // 'hello, world'
@tolgaatam
Copy link

I agree with your points @coryhardman , GCM is not a method that can blindly be thrown into a project. Yes, it is quite a secure one, but it is a "double-edged sword" per se. Only with a well-implemented key and IV generation process, it shines.

@nielsnl68
Copy link

Reading the above, i'm wondering how to send the encrypted message over the internet?
Is it save to send all 3 of values or do we need to send the tag an other way?

@hardikdgsa
Copy link

hardikdgsa commented Oct 5, 2021

Reading the above, i'm wondering how to send the encrypted message over the internet? Is it save to send all 3 of values or do we need to send the tag an other way?

@nielsnl68 Did you find any better option for this? to send this over the internet?

@nielsnl68
Copy link

I did not implemented it, and stick to the CBC variant for now. Also, I'm not an expert and don't dear to advice anything.

@ronnieroyston
Copy link

Most applications should consider using the new KeyObject API instead of passing keys as strings or 
Buffers due to improved security features. -https://nodejs.org/api/crypto.html#class-keyobject

e.g. generateKey('aes', { length: 256 }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment