I am trying to send encrypted data from flash (client side) to javascript (running as jscript in asp) on the server side.
There are several javascript Aes libraries, but they are virtually undocumented. I'm trying with crypto-js, but cant get the code to work. The below example generates an empty output, it should generate "6bc1bee22e409f96e93d7e117393172a".
<html xmlns="">
<head>
</head>
<body>
<script src=".1/build/rollups/aes.js"></script>
<script src=".1/build/components/mode-ecb.js"></script>
<script src=".1/build/components/pad-nopadding.js"></script>
<script>
var key = CryptoJS.enc.Hex.parse('2b7e151628aed2a6abf7158809cf4f3c');
var data = CryptoJS.enc.Hex.parse('3ad77bb40d7a3660a89ecaf32466ef97');
var decrypted3 = CryptoJS.AES.decrypt(data, key, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding });
document.write("<br /> dec3: " + decrypted3.toString());
</script>
</body>
</html>
I took a documented working key and encrypted data from
I am using ECB because its the only version which doesn't require an IV or salt, as the server wont know the IV or salt used on the client, so would not be able to decrypt the data.
Does anyone have any clue why the above fails to decrypt the data, or know where any documentation is?
Update: After some hours of trial and error, I came up with a combination which produces the output: 7c121d95a84573b6120ada2ffff1ce3118561eba40555c0b However, this is still incorrect. The change made to produce this was:
var decrypted3 = CryptoJS.AES.decrypt('3ad77bb40d7a3660a89ecaf32466ef97', key, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding });
I.e. I passed the data in as a string of hex, which cant be right, but does produce output at least.
The next problem will be padding issues. On the client I am using AS3 hurlant libraries, which only offer two padding strategies: NONE and PKCS#5. In crypto-js, the available strategies are:
Pkcs7 (the default)
Iso97971
AnsiX923
Iso10126
ZeroPadding
NoPadding
Does this mean there will be no chance to every decrypt data between the two libraries? Before I have had to write my own padding hacks (between AS3 and java), to add or remove trailing data, but this took days of trial and error with binary data - there must be an easier way to send a single encrypted string from client to server.
SSL is not an option as the client user can simply use Charles proxy or similar to see and tamper with the unencrypted data.
I am trying to send encrypted data from flash (client side) to javascript (running as jscript in asp) on the server side.
There are several javascript Aes libraries, but they are virtually undocumented. I'm trying with crypto-js, but cant get the code to work. The below example generates an empty output, it should generate "6bc1bee22e409f96e93d7e117393172a".
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/mode-ecb.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/pad-nopadding.js"></script>
<script>
var key = CryptoJS.enc.Hex.parse('2b7e151628aed2a6abf7158809cf4f3c');
var data = CryptoJS.enc.Hex.parse('3ad77bb40d7a3660a89ecaf32466ef97');
var decrypted3 = CryptoJS.AES.decrypt(data, key, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding });
document.write("<br /> dec3: " + decrypted3.toString());
</script>
</body>
</html>
I took a documented working key and encrypted data from http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors
I am using ECB because its the only version which doesn't require an IV or salt, as the server wont know the IV or salt used on the client, so would not be able to decrypt the data.
Does anyone have any clue why the above fails to decrypt the data, or know where any documentation is?
Update: After some hours of trial and error, I came up with a combination which produces the output: 7c121d95a84573b6120ada2ffff1ce3118561eba40555c0b However, this is still incorrect. The change made to produce this was:
var decrypted3 = CryptoJS.AES.decrypt('3ad77bb40d7a3660a89ecaf32466ef97', key, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding });
I.e. I passed the data in as a string of hex, which cant be right, but does produce output at least.
The next problem will be padding issues. On the client I am using AS3 hurlant libraries, which only offer two padding strategies: NONE and PKCS#5. In crypto-js, the available strategies are:
Pkcs7 (the default)
Iso97971
AnsiX923
Iso10126
ZeroPadding
NoPadding
Does this mean there will be no chance to every decrypt data between the two libraries? Before I have had to write my own padding hacks (between AS3 and java), to add or remove trailing data, but this took days of trial and error with binary data - there must be an easier way to send a single encrypted string from client to server.
SSL is not an option as the client user can simply use Charles proxy or similar to see and tamper with the unencrypted data.
Share Improve this question edited Jan 14, 2013 at 22:31 wingnut asked Jan 14, 2013 at 21:35 wingnutwingnut 1,1932 gold badges17 silver badges25 bronze badges 2- I was trying the same thing, it does not seem to work. I was encrypting with Crypto.JS using ECB, then trying to decrypt using CryptoJS with ECB the same hash that CryptoJS produced, but it didn't work. I did manage to get an output, but it is wrong. I feel like something doesn't work properly with the library. The only thing that works is giving the entire object that CryptoJS returns you when you encrypt to the decryptor. That is stupid, because I'm going to want to send that to someone else to decrypt. – Didier A. Commented Mar 15, 2013 at 22:09
- Do not use ECB mode, it is insecure, see ECB mode, scroll down to the Penguin. Instead use CBC mode with a random IV, just prefix the encrypted data with the IV for use in decryption. – zaph Commented Nov 21, 2016 at 12:52
3 Answers
Reset to default 9The example below returns the desired output using AES and ECB.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/mode-ecb.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/pad-nopadding.js"></script>
<script>
var encrypted = '3ad77bb40d7a3660a89ecaf32466ef97',
key = CryptoJS.enc.Hex.parse('2b7e151628aed2a6abf7158809cf4f3c'),
cipherParams = CryptoJS.lib.CipherParams.create({
ciphertext: CryptoJS.enc.Hex.parse(encrypted)
});
var decrypted3 = CryptoJS.AES.decrypt(cipherParams, key, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.NoPadding });
document.write("<br /> dec3: " + CryptoJS.enc.Hex.stringify(decrypted3));
</script>
</body>
</html>
The only real differences is creating a cypherParams object using CryptoJS.lib.CipherParams.create(). According to the official docs a cypherParams object "gives you access to all the parameters used during encryption" including key, iv, salt and the original cypherText. Basically all the info needed to decrypt it. In our case we needed to convert the encrypted data to cypherParam with only the cypherText property. Incidentally the cypherParam can be stringified using standard formats, which is how it is communicated to other systems.
Regarding the padding, as I understand it Pkcs7 is an extension of Pkcs5 and should work for any cypher created using Pkcs5. When I tried the code sample above without the NoPadding option (defaulting to Pkcs7) it didn't work, but I can't tell what was used in creating that encrypted data. At least that AES Test Vectors page you linked to doesn't tell us.
Gave up with ECB, tried various permutations with CBC, and got one to work. It also seems that it is OK to send the IV in plain text from client to server.
Here is the version which correctly outputs "6bc1bee22e409f96e93d7e117393172a". Shock.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script>
<!--script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/mode-cbc.js"></script-->
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/pad-nopadding.js"></script>
<script>
var key = CryptoJS.enc.Hex.parse('2b7e151628aed2a6abf7158809cf4f3c');
var iv = CryptoJS.enc.Hex.parse('000102030405060708090A0B0C0D0E0F');
var data = CryptoJS.enc.Hex.parse('7649abac8119b246cee98e9b12e9197d');
var encrypted = {};
encrypted.key=key;
encrypted.iv=iv;
encrypted.ciphertext = data;
var decrypted = CryptoJS.AES.decrypt(encrypted, key, { iv: iv, padding: CryptoJS.pad.NoPadding });
document.write("<br /> dec3: " + CryptoJS.enc.Hex.stringify(decrypted));
</script>
</body>
</html>
This a working and updated answer, with updated CDN links and a function that converts the resultant decrypted data into plaintext.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/core.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/cipher-core.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/aes.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/mode-ecb.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/pad-nopadding.js"></script>
<script>
var encrypted = 'B655564D4428C56E7F9E44D81770CFDBC3FB0FCEA8FFDF7CC936FFE6C7A595A0FE085FAA65796C4C24D0862FAF56CAA1880DCD281A891DD1E999F953F2B669291B41B486E0FEC5E11BE7B7348703665081E4FF79F815C35803506468548F3C5EE13B5783A0E22D91E08CB1897E4D135DA8C4E650A1D51FFDDD210311A0835FD8E8EE08CC968F8A0B0EF811554872A093',
key = CryptoJS.enc.Hex.parse('844AF9144552AFAE26A9C45FD5882718'),
cipherParams = CryptoJS.lib.CipherParams.create({
ciphertext: CryptoJS.enc.Hex.parse(encrypted)
});
var decrypted3 = CryptoJS.AES.decrypt(cipherParams, key,
{mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.NoPadding });
document.write("<br />" + hex2a(CryptoJS.enc.Hex.stringify(decrypted3)));
function hex2a(hexx) {
var hex = hexx.toString();//force conversion
var str = '';
for (var i = 0; i < hex.length; i += 2)
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
return str;
}
</script>
</body>
</html>