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; | |
} |
@hardikdgsa the credentials should be sent over TLS protocol to prevent the interception on the way to the end user.
Why can't you just send the data over TLS?
@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
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