Skip to content

Instantly share code, notes, and snippets.

@shahinghasemi
Last active October 18, 2023 08:48
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save shahinghasemi/8008ba4918feeed08b14f7b9b3a32610 to your computer and use it in GitHub Desktop.
Save shahinghasemi/8008ba4918feeed08b14f7b9b3a32610 to your computer and use it in GitHub Desktop.
FullStack AES-GCM Encryption Decryption using NodeJS and Browser standard libraries (native crypto API)
//----------------------------------------------------------------
// ------------------- ServerSide(NODE.JS) -------------------
//----------------------------------------------------------------
function encrypt(message){
const KEY = crypto.randomBytes(32)
const IV = crypto.randomBytes(16)
const ALGORITHM = 'aes-256-gcm';
const cipher = crypto.createCipheriv(ALGORITHM, KEY, IV);
let encrypted = cipher.update(message, 'utf8', 'hex');
encrypted += cipher.final('hex');
const tag = cipher.getAuthTag()
let output = {
encrypted,
KEY: KEY.toString('hex'),
IV: IV.toString('hex'),
TAG: tag.toString('hex'),
}
return output;
}
//------------------------------------------------------------------
// ------------------- ClientSide -------------------
//------------------------------------------------------------------
function decrypt() {
let KEY = hexStringToArrayBuffer(data.KEY);
let IV = hexStringToArrayBuffer(data.IV);
let encrypted = hexStringToArrayBuffer(data.encrypted + data.TAG);
window.crypto.subtle.importKey('raw', KEY, 'AES-GCM', true, ['decrypt']).then((importedKey)=>{
console.log('importedKey: ', importedKey);
window.crypto.subtle.decrypt(
{
name: "AES-GCM",
iv: IV,
},
importedKey,
encrypted
).then((decodedBuffer)=>{
let plaintext = new TextDecoder('utf8').decode(decodedBuffer);
console.log('plainText: ', plaintext);
})
})
function hexStringToArrayBuffer(hexString) {
hexString = hexString.replace(/^0x/, '');
if (hexString.length % 2 != 0) {
console.log('WARNING: expecting an even number of characters in the hexString');
}
var bad = hexString.match(/[G-Z\s]/i);
if (bad) {
console.log('WARNING: found non-hex characters', bad);
}
var pairs = hexString.match(/[\dA-F]{2}/gi);
var integers = pairs.map(function(s) {
return parseInt(s, 16);
});
var array = new Uint8Array(integers);
return array.buffer;
}
@hardikdgsa
Copy link

hardikdgsa commented Oct 5, 2021

What will be the security on the front side that it is used by only real user only. if we are sending all this things over the internet.
If we are sending
let output = {
encrypted,
KEY: KEY.toString('hex'),
IV: IV.toString('hex'),
TAG: tag.toString('hex'),
}
Anyone can decrypt it if they know the algorithm

@shahinghasemi
Copy link
Author

@hardikdgsa the credentials should be sent over TLS protocol to prevent the interception on the way to the end user.

@Goutham0110
Copy link

Why can't you just send the data over TLS?

@shahinghasemi
Copy link
Author

@Goutham0110 The TLS is not a concern, the time that the user can decrypt the data is the real concern. In our case, to prevent the server load we needed to send the encrypted data to the users first, then users request the keys from the server afterward.
This way the traffic is spread.

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