Last active
May 15, 2024 19:52
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//---------------------------------------------------------------- | |
// ------------------- 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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@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.