I am trying to make run this
function hex2a(hex) {
var str = '';
for (var i = 0; i < hex.length; i += 2)
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
return str;
}
//Raw cookie
var cookie = "B417B464CA63FE780584563D2DA4709B03F6195189044C26A29770F3203881DD90B1428139088D945CF6807CA408F201DABBADD59CE1D740F853A894692273F1CA83EC3F26493744E3D25D720374E03393F71E21BE2D96B6110CB7AC12E44447FFBD810D3D57FBACA8DF5249EB503C3DFD255692409F084650EFED205388DD8C08BF7B941E1AC1B3B70B9A8E09118D756BEAFF25834E72357FD40E80E76458091224FAE8";
//decryptionKey from issuers <machineKey>
var deckey = "FFA87B82D4A1BEAA15C06F6434A7EB2251976A838784E134900E6629B9F954B7";
var crypto = require('crypto');
var ivc = cookie, iv, cipherText, ivSize = 16, res = "";
ivc = new Buffer(ivc, 'hex');
iv = new Buffer(ivSize);
cipherText = new Buffer(ivc.length - ivSize);
ivc.copy(iv, 0, 0, ivSize);
ivc.copy(cipherText, 0, ivSize);
c = crypto.createDecipheriv('aes-256-cbc', hex2a(deckey), iv.toString('binary'));
res = c.update(cipherText, "binary", "utf8");
res += c.final('utf8');
console.log(res);
In this Q&A, it mentions about differences about node js versions, I tried that apply that one but with out success:
res = c.update(cipherText, "binary", "utf8");
line result such result
�sJ舸=�X7D������G����}x���T
and
res += c.final('utf8');
gives this error
0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length
nodejs version: 4.1.2 and crypto version 0.0.3
How can I properly decrypt cookie with this algorith or can you suggest any other?
We can check cookies by visiting localhost:3000/setcookie. This will show a message as cookies are added. We can check the cookies by visiting localhost:3000/getcookie. Now we can see that our cookies are added to the cookies object as shown above.
Decrypt the cookie and check the digest: Decrypt de key of the cookie: do Base64 decoding, then decrypt it using your institution's private RSA key. Decrypt the data using the decrypted AES key. Check the digest using secutix public certificate. The following example in java will show you how to proceed.
Cookies are small text files to hold values within browser. As cookies are stored in a plain text file it is very easy to read and modify content of the cookies. However you can encrypt and decrypt cookies to provide some security.
NodeJS provides inbuilt library crypto to encrypt and decrypt data in NodeJS. We can use this library to encrypt data of any type. You can do the cryptographic operations on a string, buffer, and even a stream of data. The crypto also holds multiple crypto algorithms for encryption.
[Assuming you are trying to decrypt a .NET framework cookie]:
(Note: This answer was completely rewritten as things were not as simple as it seemed)
The encryption schema is described here, citing interesting parts:
VERIFY + DECRYPT DATA (fEncrypt = false, signData = true)
- Input: buf represents ciphertext to decrypt, modifier represents data to be removed from the end of the plaintext (since it's not really plaintext data)
- Input (buf): E(iv + m + modifier) + HMAC(E(iv + m + modifier))
- Output: m
The 'iv' in the above descriptions isn't an actual IV. Rather, if ivType = > IVType.Random, we'll prepend random bytes ('iv') to the plaintext before feeding it to the crypto algorithms. Introducing randomness early in the algorithm prevents users from inspecting two ciphertexts to see if the plaintexts are related. If ivType = IVType.None, then 'iv' is simply an empty string. If ivType = IVType.Hash, we use a non-keyed hash of the plaintext.
The 'modifier' in the above descriptions is a piece of metadata that should be encrypted along with the plaintext but which isn't actually part of the plaintext itself. It can be used for storing things like the user name for whom this plaintext was generated, the page that generated the plaintext, etc. On decryption, the modifier parameter is compared against the modifier stored in the crypto stream, and it is stripped from the message before the plaintext is returned.
Which is (hopefully) implemented with the following script:
// Input
var cookie = "B417B464CA63FE780584563D2DA4709B03F6195189044C26A29770F3203881DD90B1428139088D945CF6807CA408F201DABBADD59CE1D740F853A894692273F1CA83EC3F26493744E3D25D720374E03393F71E21BE2D96B6110CB7AC12E44447FFBD810D3D57FBACA8DF5249EB503C3DFD255692409F084650EFED205388DD8C08BF7B941E1AC1B3B70B9A8E09118D756BEAFF25834E72357FD40E80E76458091224FAE8";
var decryptionKey = "FFA87B82D4A1BEAA15C06F6434A7EB2251976A838784E134900E6629B9F954B7";
var validationKey = "A5326FFC9D3B74527AECE124D0B7BE5D85D58AFB12AAB3D76319B27EE57608A5A7BCAB5E34C7F1305ECE5AC78DB1FFEC0A9435C316884AB4C83D2008B533CFD9";
// Parameters
var hmacSize=20
// Make buffers for input
var cookieBuffer = new Buffer(cookie, 'hex');
var decryptionKeyBuffer = new Buffer(decryptionKey, 'hex');
var validationKeyBuffer = new Buffer(validationKey, 'hex');
// Parse cookie
var curOffset=0;
var cipherText = new Buffer(cookieBuffer.length - hmacSize);
curOffset+=cookieBuffer.copy(cipherText, 0, curOffset, curOffset+cipherText.length);
var hmac = new Buffer(hmacSize);
curOffset+=cookieBuffer.copy(hmac, 0, curOffset, curOffset+hmac.length);
// Verify HMAC
var crypto = require('crypto');
var h = crypto.createHmac('sha1', validationKeyBuffer);
h.update(cipherText);
var expectedHmac = h.digest();
console.log('Expected HMAC: ' + expectedHmac.toString('hex'));
console.log('Actual HMAC: ' + hmac.toString('hex'));
//if(!expectedHmac.equals(hmac)) { // Note: Requires nodejs v0.11.13
// throw 'Cookie integrity error';
//}
// Decrypt
var zeroIv = new Buffer("00000000000000000000000000000000", 'hex');
var c = crypto.createDecipheriv('aes-256-cbc', decryptionKeyBuffer, zeroIv);
var plaintext = Buffer.concat([c.update(cipherText), c.final()]);
// Strip IV (which is the same length as decryption key -- see notes below)
var res = new Buffer(plaintext.length-decryptionKeyBuffer.length);
plaintext.copy(res, 0, decryptionKeyBuffer.length, plaintext.length);
// Output
console.log('HEX: ' + res.toString('hex'));
console.log('UTF-8: ' + res.toString('utf8'));
Giving result:
Expected HMAC: 88e332b9a27b8f6f8d805ae718c562c1c8b721ed
Actual HMAC: 6beaff25834e72357fd40e80e76458091224fae8
HEX: 010112ea9a47b2f2ce08fe121e7d78b6f2ce0801085400650073007400550073006500720016540065007300740020007400650073007400730073006f006e002c00200072006f006c0066007a006f007200012f00ff1d892908d9c497bd804f5f22eab043ff6368702c
UTF-8: ��G���}x�TestUserTest testsson, rolfzor/���ė��O_"��C�chp,
Some (random) notes about this code:
it assumes that AES is used for encryption and HMAC-SHA1 is used for authentication
as the used authentication key is not known, the integrity check condition is commented out and verification key from this very related question is used (which is the reason for authentication tag mismatch)
the padding used for AES encryption is PKCS#7
the 'modifier' field is assumed empty. If this is not the case you would have to check it and remove it from the plaintext
for production environment you definitely should check the authentication tag (otherwise you would expose yourself to nasty attacks)
to avoid even nastier attacks, the authentication tag should be tested for equality in constant time (which might be tricky to implement in nodejs). Please note that the commented-out code is very probably vulnerable to timing-attacks.
the IV length is equal to the key length (see here for the reason)
Disclaimer: I did not study the original .NET code thoroughly, nor am I a crypto expert so please do validate my thoughts
Good luck!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With