Creé una aplicación simple que cifra el texto, pero ¿cómo muestro un error cuando se proporciona una contraseña incorrecta o sal? Lo alojé en repetición . Pero cuando doy una contraseña incorrecta o sal, simplemente la descifra. No hay una devolución de llamada o función en crypto para crypto.createDecipheriv()
const app = { encrypt(text, password, salt) { password = password.repeat(32).substr(0, 32); salt = salt.repeat(16).substr(0, 16); crypto.pbkdf2(password, salt, 10, 16, 'sha512', (err, key) => { if (err) { console.log(err); } else { key = key.toString('hex'); const cipher = crypto.createCipheriv('aes-256-gcm', key, salt); let encrypted = cipher.update(text, 'utf8', 'hex'); console.log(encrypted); } }); }, decrypt(text, password, salt) { password = password.repeat(32).substr(0, 32); salt = salt.repeat(16).substr(0, 16); crypto.pbkdf2(password, salt, 10, 16, 'sha512', (err, key) => { if (err) { console.log(err); } else { key = key.toString('hex'); const cipher = crypto.createDecipheriv('aes-256-gcm', key, salt); let decrypted = cipher.update(text, 'hex', 'utf8'); console.log(decrypted); } }); } } const message = 'Hello World'; app.encrypt(message, 'password', 'salt'); const cipherText = 'a0a4e0ad97133494856502'; app.decrypt(cipherText, 'password', 'salt');GCM genera una etiqueta de autenticación (16 bytes de forma predeterminada) durante el cifrado, que se utiliza para la autenticación durante el descifrado.
Algunas bibliotecas (por ejemplo, Java) concatenan implícitamente el texto cifrado y la etiqueta (ciphertext|tag) durante el cifrado y los separan implícitamente durante el descifrado (esto no es crítico ya que la etiqueta no es secreta).
El módulo criptográfico de NodeJS, por otro lado, maneja el texto cifrado y la etiqueta de forma independiente, por lo que la etiqueta debe considerarse explícitamente. Puede determinarse durante el cifrado con getAuthTag() y debe configurarse durante el descifrado con setAuthTag() . Ambos faltan en el código publicado.
También faltan las llamadas final() que generan la etiqueta en el cifrado y realizan la autenticación en el descifrado.
Para pasar la etiqueta al descifrado en este ejemplo, la siguiente solución concatena la etiqueta con el texto cifrado durante el cifrado y lo separa durante el descifrado (siguiendo el patrón de Java).
Si se solucionan estos problemas, el descifrado funciona para los datos correctos y muestra un mensaje correspondiente para los datos incorrectos: Error: Unsupported state or unable to authenticate data.
Código fijo, vea los comentarios para más detalles:
const crypto = require('crypto'); const app = { encrypt(text, password, salt) { password = password.repeat(32).substr(0, 32); salt = salt.repeat(16).substr(0, 16); crypto.pbkdf2(password, salt, 10, 16, 'sha512', (err, key) => { if (err) { console.log(err); } else { key = key.toString('hex'); const cipher = crypto.createCipheriv('aes-256-gcm', key, salt); let encrypted = cipher.update(text, 'utf8', 'hex') + cipher.final('hex'); // Fix 1a: call final(): create tag let tag = cipher.getAuthTag(); // Fix 2a: get tag console.log(encrypted + tag.toString('hex')); // Fix 3a: concat ciphertext and tag } }); }, decrypt(text, password, salt) { var tag = Buffer.from(text.substr(-32, 32), 'hex'); // Fix 3b: Separate ciphertext and tag var ciphertext = text.substr(0, text.length - 32); password = password.repeat(32).substr(0, 32); salt = salt.repeat(16).substr(0, 16); crypto.pbkdf2(password, salt, 10, 16, 'sha512', (err, key) => { if (err) { console.log(err); } else { key = key.toString('hex'); const cipher = crypto.createDecipheriv('aes-256-gcm', key, salt); cipher.setAuthTag(tag); // Fix 2b: set tag try { let decrypted = cipher.update(ciphertext, 'hex', 'utf8') + cipher.final('utf8'); // Fix 1b: call final(): authenticate console.log(decrypted); } catch (e) { console.log("Authentication failed!"); } } }); } } const message = 'Hello World'; app.encrypt(message, 'password', 'salt'); const cipherText = 'a0a4e0ad971334948565023568ae285d45b9cefc80abe3afcf9155'; app.decrypt(cipherText, 'password', 'salt'); app.decrypt(cipherText, 'password123', 'salt');