Symmetric Key Decryption Methods with PBKDF2 key derivationIn this case we will create cipher text using a random IV value, and a key derived using PBKDF2. For this we will generate a random IV for the encryption method, and then use a defined password, salt and hashing method for the generation of the encryption key using PBKDF2. |
Outline
The code used is:
const crypto = require("crypto"); var message="Hello"; var algorithm="aes-128-cbc"; var password="qwerty"; var hash="sha256"; var salt="salt"; var args = process.argv; if (args.length>2) message=args[2]; if (args.length>3) algorithm=args[3]; if (args.length>4) password=args[4]; if (args.length>5) hash=args[5]; if (args.length>6) salt=args[6]; var key=crypto.randomBytes(16); var iv = crypto.randomBytes(16); var err=null; keysize=16; var info=crypto.getCipherInfo(algorithm); if (algorithm.indexOf("ecb")>-1) { iv = null; } else { iv=crypto.randomBytes(info.ivLength); } keysize=info.keyLength; crypto.pbkdf2(password, salt, 100, keysize, hash, (err, key) => { const cipher = crypto.createCipheriv(algorithm, Buffer.from(key),iv,{ authTagLength: 16 }); let encrypted = cipher.update(message); console.log("Message: ",message); encrypted = Buffer.concat([encrypted, cipher.final()]); var decipher; var decrypted; decipher = crypto.createDecipheriv(algorithm, Buffer.from(key),iv,{ authTagLength: 16 }); if (algorithm=="aes-128-gcm" || algorithm=="aes-128-ocb" || algorithm=="aes-128-ccm" || algorithm=="aes-256-gcm" || algorithm=="aes-256-ocb" || algorithm=="aes-256-ccm" ) { const tag = cipher.getAuthTag(); decipher.setAuthTag(tag); console.log("Tag:\t",tag.toString('hex')); } decrypted = decipher.update(encrypted); decrypted = Buffer.concat([decrypted, decipher.final()]); console.log("\nEncryption Algorithm: ",algorithm); if (iv!=null) console.log(" IV:\t",iv.toString('hex')); console.log("\nPassword:\t",password); console.log(" Hashing:\t",hash); console.log(" Salt:\t\t",salt); console.log("\nDerived Key:\t",key.toString('hex')); console.log("\nEncrypted:\t",encrypted.toString('hex')); console.log("Encrypted:\t",encrypted.toString('base64')); console.log("\nDecrypted:\t",decrypted.toString()); });
As we can see, the requirement for the size of the IV value for the key, and the size of the key varies for different methods. For GCM, we have a stream cipher, and where the length of the cipher will equal the length of the plaintext:
Message: Test Tag: 62184a7f7f522fdf14025a8d63c8957c Encryption Algorithm: aes-256-gcm IV: 0489971c251849c77ce778cd Password: qwerty Hashing: sha256 Salt: salt Derived Key: 9d8e59add49d9c4c3677035028bee6bf689693990a9caf5b2eddfd7272b7a4cb Encrypted: d0d98f82 Encrypted: 0NmPgg== Decrypted: Test
For CBC mode, we have a block cipher, so the size of the cipher will relate to the number of blocks that are filled:
Message: Test Encryption Algorithm: aes-128-cbc IV: 5b625969baa2b89bff5bf1ba2847b4c5 Password: qwerty Hashing: sha256 Salt: salt Derived Key: 9d8e59add49d9c4c3677035028bee6bf Encrypted: 87ec2f875f6905983911b48ce6296cf6 Encrypted: h+wvh19pBZg5EbSM5ils9g== Decrypted: Test