You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We’d like to add a new AES-256-GCM encryption (v4) method, because GCM provides both encryption and tamper protection.
This will help secure stored secrets (API keys, backup codes) while ensuring that any unauthorized modifications can be detected.
More details
Keep existing encryption functions (v1, v2, v3) for backward compatibility.
Add a new encryptV4 and decryptV4 using AES-256-GCM.
Use a random 16-byte IV each time and handle the GCM authTag properly.
Update relevant documentation and tests to show how to migrate to v4 encryption.
Potentially deprecate older methods in the future once v4 is widely adopted.
require('dotenv').config();constcrypto=require('node:crypto');const{ webcrypto }=crypto;// Legacy keys for v1, v2, v3 (for demonstration only!)constkey=Buffer.from(process.env.CREDS_KEY,'hex');constiv=Buffer.from(process.env.CREDS_IV,'hex');// used for v1// AES-CBC (v1/v2) and AES-256-CTR (v3) code ...// -- existing code left as-is --// --- v4: AES-256-GCM using Node's crypto functions ---constalgorithm_v4='aes-256-gcm';/** * Encrypts a value using AES-256-GCM (v4). * * @param {string} plaintext - The string to encrypt. * @returns {string} The encrypted string containing the IV, AuthTag, and ciphertext, joined by “:”, prefixed with “v4:”. */functionencryptV4(plaintext){// Ensure key is 32 bytes for AES-256if(key.length!==32){thrownewError(`Invalid key length: expected 32 bytes, got ${key.length} bytes`);}// Generate random 16-byte IVconstiv_v4=crypto.randomBytes(16);// Create cipherconstcipher=crypto.createCipheriv(algorithm_v4,key,iv_v4);// Encryptconstencrypted=Buffer.concat([cipher.update(plaintext,'utf8'),cipher.final()]);// Retrieve the auth tag generated by GCMconstauthTag=cipher.getAuthTag();// Format: v4:iv:tag:ciphertextreturn`v4:${iv_v4.toString('hex')}:${authTag.toString('hex')}:${encrypted.toString('hex')}`;}/** * Decrypts a value produced by `encryptV4`. * * @param {string} encryptedValue - String in the format “v4:ivHex:tagHex:ciphertextHex”. * @returns {string} Decrypted plaintext. */functiondecryptV4(encryptedValue){constparts=encryptedValue.split(':');if(parts[0]!=='v4'){thrownewError('Not a v4 encrypted value');}constiv_v4=Buffer.from(parts[1],'hex');constauthTag=Buffer.from(parts[2],'hex');constciphertext=Buffer.from(parts[3],'hex');// Create decipherconstdecipher=crypto.createDecipheriv(algorithm_v4,key,iv_v4);// Set the auth tag *before* finalizingdecipher.setAuthTag(authTag);// Decryptconstdecrypted=Buffer.concat([decipher.update(ciphertext),decipher.final()]);returndecrypted.toString('utf8');}/** * Hash a given string with SHA-256. * * @param {string} str * @returns {Promise<string>} Returns a hex-encoded hash of the string. */asyncfunctionhashToken(str){constdata=newTextEncoder().encode(str);consthashBuffer=awaitwebcrypto.subtle.digest('SHA-256',data);returnBuffer.from(hashBuffer).toString('hex');}/** * Computes SHA-256 hash for a backup code (example usage). * * @param {string} input * @returns {Promise<string>} */asyncfunctionhashBackupCode(input){constencoder=newTextEncoder();constdata=encoder.encode(input);consthashBuffer=awaitwebcrypto.subtle.digest('SHA-256',data);consthashArray=Array.from(newUint8Array(hashBuffer));returnhashArray.map((b)=>b.toString(16).padStart(2,'0')).join('');}/** * Returns a string of random values (hex-encoded). * * @param {number} length * @returns {Promise<string>} */asyncfunctiongetRandomValues(length){if(!Number.isInteger(length)||length<=0){thrownewError('Length must be a positive integer');}constrandomValues=newUint8Array(length);webcrypto.getRandomValues(randomValues);returnBuffer.from(randomValues).toString('hex');}// Exports: keep v1, v2, v3 for backward compatibility, add v4module.exports={// --- v1/v2 code below here (AES-CBC) ---
encrypt,
decrypt,
encryptV2,
decryptV2,// --- v3: AES-256-CTR ---
encryptV3,
decryptV3,// --- v4: AES-256-GCM ---
encryptV4,
decryptV4,// Hash & random
hashToken,
hashBackupCode,
getRandomValues,};
Which components are impacted by your request?
General, Other
Pictures
No response
Code of Conduct
I agree to follow this project's Code of Conduct
The text was updated successfully, but these errors were encountered:
What features would you like to see added?
We’d like to add a new AES-256-GCM encryption (v4) method, because GCM provides both encryption and tamper protection.
This will help secure stored secrets (API keys, backup codes) while ensuring that any unauthorized modifications can be detected.
More details
encryptV4
anddecryptV4
using AES-256-GCM.Which components are impacted by your request?
General, Other
Pictures
No response
Code of Conduct
The text was updated successfully, but these errors were encountered: