I have a vb.net Windows form app that encrypts a string to a file. I now need JavaScript to decrypt that value. I have attempted to use CryptoJS but I am struggling with syntax and how to get the passphrase, salt and init vector in the right format to use in CryptoJS.PBKDF2 (assuming that is the right thing to use).
Calling Method
Dim encryptedComplianceValue = encrypt2(complianceValue, "Password", "Salt Value", "SHA1", 2, "@1B2c3D4e5F6g7H8", 256)
Encryption Method
Public Function encrypt2(ByVal plainText As String, ByVal passPhrase As String, ByVal saltValue As String, ByVal hashAlgorithm As String, ByVal passwordIterations As Integer, ByVal initVector As String, ByVal keySize As Integer) As String
Dim initVectorBytes As Byte()
initVectorBytes = Encoding.ASCII.GetBytes(initVector)
Dim saltValueBytes As Byte()
saltValueBytes = Encoding.ASCII.GetBytes(saltValue)
Dim plainTextBytes As Byte()
plainTextBytes = Encoding.UTF8.GetBytes(plainText)
Dim password As Rfc2898DeriveBytes
password = New Rfc2898DeriveBytes(passPhrase, saltValueBytes, passwordIterations)
Dim keyBytes As Byte()
keyBytes = password.GetBytes(keySize / 8)
Dim symmetricKey As RijndaelManaged
symmetricKey = New RijndaelManaged()
symmetricKey.Mode = CipherMode.CBC
Dim encryptor As ICryptoTransform
encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes)
Dim memoryStream As MemoryStream
memoryStream = New MemoryStream()
Dim cryptoStream As CryptoStream
cryptoStream = New CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length)
cryptoStream.FlushFinalBlock()
Dim cipherTextBytes As Byte()
cipherTextBytes = memoryStream.ToArray()
memoryStream.Close()
cryptoStream.Close()
Dim cipherText As String
cipherText = Convert.ToBase64String(cipherTextBytes)
Return cipherText
End Function
JavaScript
function decryptMsg256()
{
var keySize = 256;
var iterations = 2;
var algorithm = 'AES-256-CBC';
// the password that user provides
var userPass = "Password";
console.log("user pass : " + userPass);
// get the encrypted msg
var encMsg64 = "v6shkblimfQMOoa8VxICjQ==";
var encMsg = CryptoJS.enc.Base64.parse(encMsg64);
//var salt =CryptoJS.enc.Utf8.parse("Mon,07-Mar-2016 18:50:46 GMT");
var salt = "Salt Value";
console.log('salt: '+ salt);
var saltbytes = [];
for (var i = 0; i <salt.length; ++i) {
saltbytes .push(salt.charCodeAt(i));
}
console.log('saltbytes: '+ saltbytes );
//var iv =CryptoJS.enc.Utf8.parse("@1B2c3D4e5F6g7H8");
var iv = "@1B2c3D4e5F6g7H8";
console.log('IV: '+ iv);
var ivbytes = [];
for (var i = 0; i <iv.length; ++i) {
ivbytes.push(iv.charCodeAt(i));
}
console.log('ivbytes: '+ ivbytes );
//var saltBuffer = new Buffer(salt);
//var passwordBuffer = new Buffer(userPass);
var key = CryptoJS.PBKDF2(userPass, saltbytes,{keyBytes: 32, iterations: 2 });
//var key = CryptoJS.PBKDF2(userPass, salt, iterations, keySize/8);
//var decipher = CryptoJS.createDecipheriv(algorithm, key, iv);
console.log( 'key: '+ key);
var keybytes = [];
for (var i = 0; i <key.length; ++i) {
keybytes.push(key.charCodeAt(i));
}
console.log('keybytes: '+ keybytes);
//var plainText="Hello, World!";
//console.log('Plain Text '+ plainText );
//var encMsg = CryptoJS.AES.encrypt(plainText, key, {
// iv:iv,
// mode: CryptoJS.mode.CBC,
// padding: CryptoJS.pad.Pkcs7
// });
//console.log('Encrypted Message '+ encMsg );
var decText = '';
var decMsg = CryptoJS.AES.decrypt( encMsg, key, {
iv:iv,
mode: CryptoJS.mode.CBC,
//padding: CryptoJS.pad.Pkcs7
} );
//console.log( "decryptedData = " + decMsg );
// convert to UTF8 string
decText = decMsg.toString( CryptoJS.enc.Utf8);
console.log( "decryptedText = " + decText );
}
You have multiple issues:
Your IV is a simple ASCII string, so you can easily parse it to a binary format with
var iv = CryptoJS.enc.Utf8.parse("@1B2c3D4e5F6g7H8");
Don't use your custom "binary" format with saltbytes.push(salt.charCodeAt(i));
or similar. You need to use CryptoJS' native format, which is available through
CryptoJS.enc.<Encoder>.parse(string)
The output size of PBKDF2 is specified with keySize
and not keyBytes
:
var key = CryptoJS.PBKDF2(userPass, salt, {keySize: 256/32, iterations: 2 });
The decryption function expects the ciphertext to be a CipherParams object. Good thing, duck-typing works:
var decMsg = CryptoJS.AES.decrypt({
ciphertext: encMsg
}, key, {
iv: iv
});