bugl
bugl
HomeLearnPatternsSearch
HomeLearnPatternsSearch

Loading lesson path

Learn/Node.js/Node.js Reference
Node.js•Node.js Reference

Node.js Decipher Reference

Concept visual

Node.js Decipher Reference

Pointer walk
two pointers
leftright102132436485116
left=0
right=6
1
3

Start at both ends

Decipher Object

The Decipher class is part of Node.js's crypto module. It provides a way to decrypt data that was encrypted using the Cipher class. Decipher instances are created using the crypto.createDecipheriv() method.

Note:

The crypto.createDecipher() method is deprecated since Node.js v10.0.0 due to security concerns. Always use crypto.createDecipheriv() instead, which requires an explicit initialization vector (IV).

Import Crypto Module

// Import the crypto module const crypto = require('crypto');
// Create a decipher with createDecipheriv const algorithm = 'aes-256-cbc';
const key = Buffer.from('your-encryption-key-in-hex', 'hex'); // 32 bytes for AES-256 const iv = Buffer.from('your-iv-in-hex', 'hex');              // 16 bytes for AES
const decipher = crypto.createDecipheriv(algorithm, key, iv);

Decipher Methods

Method

Description decipher.update(data[, inputEncoding][, outputEncoding]) Updates the decipher with data. If inputEncoding is provided, data is a string using the specified encoding. If outputEncoding is specified, the returned value will be a string using the specified encoding. If not, a Buffer is returned. decipher.final([outputEncoding])

Returns any remaining deciphered contents. If outputEncoding is specified, a string is returned; otherwise, a Buffer is returned.
decipher.setAAD(buffer[, options])
When using an AEAD algorithm (like GCM or CCM), sets the Additional Authenticated Data (AAD).
decipher.setAuthTag(buffer)
When using an AEAD algorithm, sets the authentication tag that will be used to verify the data's integrity.
decipher.setAutoPadding([autoPadding])
When autoPadding is true (default), padding is automatically removed from the result. Disable when the data was not padded or was manually unpadded.

Basic Decryption Example

Formula

The following example demonstrates how to decrypt data that was encrypted with AES - 256 - CBC:
const crypto = require('crypto');

// Encryption key and initialization vector

// In a real application, these would be securely stored and retrieved const key = Buffer.from('1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', 'hex');
const iv = Buffer.from('1234567890abcdef1234567890abcdef', 'hex');
// Encrypted text (from a previous encryption)
const encryptedText = '7a9c2c7157819144ede3cb9532263cb97c94a7b45d95163bb79aa1af55d4101d';
// Create a decipher const algorithm = 'aes-256-cbc';
const decipher = crypto.createDecipheriv(algorithm, key, iv);
// Decrypt the data let decrypted = decipher.update(encryptedText, 'hex', 'utf8');
decrypted += decipher.final('utf8');
console.log('Encrypted Text:', encryptedText);
console.log('Decrypted Text:', decrypted);

Complete Encryption/Decryption Example

Here's a complete example showing both encryption and decryption:

const crypto = require('crypto');
// The message to encrypt const message = 'This is a secret message that needs to be encrypted';

// Generate encryption key and IV

const key = crypto.randomBytes(32);
const iv = crypto.randomBytes(16);
// Encryption function using Cipher function encrypt(text) {
// Create cipher const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
// Encrypt data let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
return encrypted;
}
// Decryption function using Decipher function decrypt(encryptedText) {

// Create decipher with the same key and IV

const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
// Decrypt data let decrypted = decipher.update(encryptedText, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
// Encrypt the message const encryptedMessage = encrypt(message);
console.log('Original Message:', message);
console.log('Encrypted Message:', encryptedMessage);
// Decrypt the message const decryptedMessage = decrypt(encryptedMessage);
console.log('Decrypted Message:', decryptedMessage);
// Verify the result console.log('Decryption successful:', message === decryptedMessage);

Decrypting Binary Data

You can decrypt binary data such as encrypted files:

const crypto = require('crypto');
const fs = require('fs');
// Read the encryption key and IV (saved during encryption)
const key = Buffer.from(fs.readFileSync('encryption_key.txt', 'utf8'), 'hex');
const iv = Buffer.from(fs.readFileSync('encryption_iv.txt', 'utf8'), 'hex');
// Create read and write streams const readStream = fs.createReadStream('encrypted.jpg.enc');
const writeStream = fs.createWriteStream('decrypted.jpg');
// Create decipher stream const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
// Decrypt the file readStream.pipe(decipher).pipe(writeStream);
writeStream.on('finish', () => {
console.log('File decryption completed');
});

Using AEAD Decryption

Authenticated Encryption with Associated Data (AEAD) provides both confidentiality and data integrity. Here's how to decrypt data that was encrypted with an AEAD algorithm:

const crypto = require('crypto');
// Encryption values (would be stored and retrieved securely in a real application)
const key = Buffer.from('1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', 'hex');
const iv = Buffer.from('123456789012123456789012', 'hex'); // 12 bytes for GCM
const encryptedData = 'af56c283ae95963c1e1877adb558d860';
const authTag = Buffer.from('1234567890abcdef1234567890abcdef', 'hex');
const associatedData = 'Additional data that was authenticated';

Formula

// Create decipher using AES - GCM
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
// Set the Additional Authenticated Data (AAD)
decipher.setAAD(Buffer.from(associatedData));
// Set the authentication tag decipher.setAuthTag(authTag);
try {
// Decrypt the data let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
decrypted += decipher.final('utf8');
console.log('Decrypted Text:', decrypted);
console.log('Authentication verified successfully');
} catch (error) {
console.error('Authentication failed:', error.message);

// If authentication fails, the decryption will throw an error

}

AEAD Complete Example

Here's a complete example of AEAD encryption and decryption:

const crypto = require('crypto');
// Data to encrypt const plainText = 'Secret message';
const associatedData = 'Additional data to authenticate';
// Generate key and IV (nonce)
const key = crypto.randomBytes(32);
const iv = crypto.randomBytes(12); // 12 bytes (96 bits) is recommended for GCM
// === ENCRYPTION ===

Formula

// Create cipher using AES - GCM
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
// Set the Additional Authenticated Data (AAD)
cipher.setAAD(Buffer.from(associatedData));
// Encrypt the data let encrypted = cipher.update(plainText, 'utf8', 'hex');
encrypted += cipher.final('hex');
// Get the authentication tag const authTag = cipher.getAuthTag();
console.log('Encrypted Text:', encrypted);
console.log('Auth Tag (hex):', authTag.toString('hex'));
console.log('Associated Data:', associatedData);
// === DECRYPTION ===
// Create decipher const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);

// Set the same AAD

decipher.setAAD(Buffer.from(associatedData));
// Set the authentication tag decipher.setAuthTag(authTag);
try {
// Decrypt let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
console.log('Decrypted Text:', decrypted);
console.log('Decryption successful:', plainText === decrypted);
} catch (error) {
console.error('Decryption failed:', error.message);
}
// === DECRYPTION WITH WRONG AUTH TAG (will fail) ===
try {
const wrongDecipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
wrongDecipher.setAAD(Buffer.from(associatedData));
// Set a wrong authentication tag const wrongAuthTag = crypto.randomBytes(16);
wrongDecipher.setAuthTag(wrongAuthTag);
// Try to decrypt let wrongDecrypted = wrongDecipher.update(encrypted, 'hex', 'utf8');
wrongDecrypted += wrongDecipher.final('utf8'); // This will throw console.log('Should not reach here');
} catch (error) {
console.error('Decryption with wrong auth tag failed (expected):', error.message);
}

Manual Padding Control

You can control the padding behavior for decryption manually:

const crypto = require('crypto');

// Generate key and IV

const key = crypto.randomBytes(32);
const iv = crypto.randomBytes(16);
// Data to encrypt const plainText = 'This is a test message';
// First encrypt with disabled auto padding const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
cipher.setAutoPadding(false);
// Manually pad to block size (16 bytes for AES) function padToBlockSize(text, blockSize = 16) {
const padLength = blockSize - (text.length % blockSize);
return text + '\0'.repeat(padLength);
}
// Encrypt manually padded data const paddedText = padToBlockSize(plainText);
let encrypted = cipher.update(paddedText, 'utf8', 'hex');
encrypted += cipher.final('hex');
// Now decrypt with auto padding disabled function decryptWithPadding(encryptedText, usePadding) {
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
decipher.setAutoPadding(usePadding);
try {
let decrypted = decipher.update(encryptedText, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
} catch (error) {
return `Error: ${error.message}`;
}
}
// With auto padding (default)
console.log('With auto padding:', decryptWithPadding(encrypted, true));
// Without auto padding (will include padding bytes)
const manualDecrypted = decryptWithPadding(encrypted, false);
console.log('Without auto padding:', manualDecrypted);
// Manually remove padding (trim null bytes) function removeNullPadding(paddedText) {
return paddedText.replace(/\0+$/, '');
}
console.log('With manual padding removal:', removeNullPadding(manualDecrypted));

Password-Based Decryption

Formula

Decrypt data that was encrypted using a password - derived key:
const crypto = require('crypto');
// Password and salt (from the encryption process)
const password = 'mysecretpassword';
const salt = Buffer.from('0123456789abcdef0123456789abcdef', 'hex');
// Encrypted data and IV from the encryption process const encryptedData = '7a9c2c7157819144ede3cb9532263cb97c94a7b45d95163bb79aa1af55d4101d';
const iv = Buffer.from('0123456789abcdef0123456789abcdef', 'hex');
// Generate a key from the password function getKeyFromPassword(password, salt) {
// Use PBKDF2 to derive a key from the password return crypto.pbkdf2Sync(password, salt, 100000, 32, 'sha256');
}
// Decrypt data function decryptWithPassword(encryptedText, password, salt, iv) {
// Generate key from password const key = getKeyFromPassword(password, salt);
// Create decipher const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
// Decrypt data let decrypted = decipher.update(encryptedText, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
try {
// Decrypt the data const decryptedText = decryptWithPassword(encryptedData, password, salt, iv);
console.log('Decrypted:', decryptedText);
} catch (error) {
console.error('Decryption failed:', error.message);
}
// Try with wrong password try {
const wrongPassword = 'wrongpassword';
const decryptedWithWrongPass = decryptWithPassword(encryptedData, wrongPassword, salt, iv);
console.log('Decrypted with wrong password:', decryptedWithWrongPass);
} catch (error) {
console.log('Decryption with wrong password failed (expected):', error.message);
}

Complete Password-Based Example

Formula

Here's a complete example of password - based encryption and decryption:
const crypto = require('crypto');
// Password and message const password = 'mysecretpassword';
const message = 'This is a secret message protected by a password';
// Password-based encryption function encryptWithPassword(text, password) {
// Generate a random salt const salt = crypto.randomBytes(16);
// Derive a key from the password const key = crypto.pbkdf2Sync(password, salt, 100000, 32, 'sha256');

// Generate random IV

const iv = crypto.randomBytes(16);
// Create cipher const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
// Encrypt data let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
// Return all values needed for decryption return {
salt: salt.toString('hex'), iv: iv.toString('hex'), encrypted: encrypted
};
}
// Password-based decryption function decryptWithPassword(encryptedInfo, password) {
// Parse the values const salt = Buffer.from(encryptedInfo.salt, 'hex');
const iv = Buffer.from(encryptedInfo.iv, 'hex');
const encrypted = encryptedInfo.encrypted;
// Derive the same key const key = crypto.pbkdf2Sync(password, salt, 100000, 32, 'sha256');
// Create decipher const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
// Decrypt data let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
// Encrypt the message const encryptedInfo = encryptWithPassword(message, password);
console.log('Encrypted information:', encryptedInfo);
// Decrypt the message const decryptedMessage = decryptWithPassword(encryptedInfo, password);
console.log('Decrypted message:', decryptedMessage);
console.log('Decryption successful:', message === decryptedMessage);
// Try with wrong password try {
const wrongPassword = 'wrongpassword';
const decryptedWithWrong = decryptWithPassword(encryptedInfo, wrongPassword);
console.log('Decrypted with wrong password:', decryptedWithWrong);
} catch (error) {
console.log('Decryption with wrong password failed (expected):', error.message);
}

Handling Errors

Decryption can fail for various reasons. It's important to handle these errors properly:

const crypto = require('crypto');

// Generate key and IV

const key = crypto.randomBytes(32);
const iv = crypto.randomBytes(16);
// Create sample encrypted data const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
const validEncrypted = cipher.update('valid data', 'utf8', 'hex') + cipher.final('hex');
// Function to attempt decryption and handle errors function tryDecrypt(encryptedText, decryptKey, decryptIv) {
try {
const decipher = crypto.createDecipheriv('aes-256-cbc', decryptKey, decryptIv);
const decrypted = decipher.update(encryptedText, 'hex', 'utf8') + decipher.final('utf8');
return { success: true, data: decrypted };
} catch (error) {
return { success: false, error: error.message };
}
}

// Case 1: Correct key and IV

const result1 = tryDecrypt(validEncrypted, key, iv);
console.log('Case 1 (correct key and IV):', result1);

Formula

// Case 2: Wrong key const wrongKey = crypto.randomBytes(32);
const result2 = tryDecrypt(validEncrypted, wrongKey, iv);
console.log('Case 2 (wrong key):', result2);

// Case 3: Wrong IV

const wrongIv = crypto.randomBytes(16);
const result3 = tryDecrypt(validEncrypted, key, wrongIv);
console.log('Case 3 (wrong IV):', result3);

Formula

// Case 4: Invalid encrypted data const result4 = tryDecrypt('invalidhexdata', key, iv);
console.log('Case 4 (invalid data):', result4);

Formula

// Case 5: Corrupted encrypted data const corruptedData = validEncrypted.substring(0, validEncrypted.length - 2);
const result5 = tryDecrypt(corruptedData, key, iv);
console.log('Case 5 (corrupted data):', result5);

Security Best Practices

Use createDecipheriv()

instead of the deprecated createDecipher() : This ensures you're explicitly providing the IV.

Secure key and IV storage

: Store encryption keys securely, consider using a key management service.

Verify decryption

: When possible, include a way to verify that decryption was successful (e.g., using authenticated encryption).

Protect against chosen-ciphertext attacks

: Use authenticated encryption (AEAD) to prevent tampering with encrypted data.

Handle errors securely

: Avoid leaking information about the decryption process in error messages.

Use constant-time comparison

Formula

: When verifying authentication tags or other sensitive values, use constant - time comparisons to prevent timing attacks.

Previous

Node.js Cipher Reference

Next

Node.js DiffieHellman Reference