node.js - 如何用nodejs解密cookie

标签 node.js cookies encryption machinekey

我正在尝试制作 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);

在这个 Q&A 中,它提到了关于 Node js 版本的差异,我尝试应用那个但没有成功:

res = c.update(cipherText, "binary", "utf8");

行结果这样的结果

�sJ舸=�X7D������G����}x���T

res += c.final('utf8'); 

给出这个错误

0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length

nodejs 版本:4.1.2 和加密版本 0.0.3

我怎样才能用这个算法正确地解密 cookie 或者你能推荐任何其他算法吗?

最佳答案

[假设您正在尝试解密 .NET 框架 cookie]:

(注意:这个答案被完全重写了,因为事情并不像看起来那么简单)

加密模式在 here 中被描述,引用了有趣的部分:

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.

(希望)使用以下脚本实现:

// 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'));

给出结果:

Expected HMAC: 88e332b9a27b8f6f8d805ae718c562c1c8b721ed
Actual   HMAC: 6beaff25834e72357fd40e80e76458091224fae8
HEX: 010112ea9a47b2f2ce08fe121e7d78b6f2ce0801085400650073007400550073006500720016540065007300740020007400650073007400730073006f006e002c00200072006f006c0066007a006f007200012f00ff1d892908d9c497bd804f5f22eab043ff6368702c
UTF-8: ��G���}x�TestUserTest testsson, rolfzor/���ė��O_"��C�chp,

关于此代码的一些(随机)注释:

  • 假设使用AES加密,HMAC-SHA1认证

  • 由于使用的身份验证 key 未知,完整性检查条件被注释掉并使用来自 this very related question 的验证 key (这是身份验证标签不匹配的原因)

  • 用于 AES 加密的填充是 PKCS#7

  • “修饰符”字段假定为空。如果不是这种情况,您将不得不检查它并将其从明文中删除

  • 对于生产环境,你绝对应该检查身份验证标签(否则你会让自己暴露在恶劣的攻击之下)

  • 为了避免更严重的攻击,应该在恒定时间内测试身份验证标记是否相等(这在 nodejs 中可能很难实现)。请注意,注释掉的代码很可能容易受到定时攻击。

  • IV长度等于key长度(原因见here)

免责声明:我没有深入研究原始 .NET 代码,也不是加密专家,所以请验证我的想法

祝你好运!

关于node.js - 如何用nodejs解密cookie,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34882672/

相关文章:

javascript - Node.js:可控并发while循环

javascript - Koa cookie 返回 `undefined`

javascript - 加密文本每次都改变 -Msrcrypto

android - 如何在 Android 中播放加密文件

javascript - 无法使 mongoose 过期/ttl 工作

node.js - 使用 n :m assosiations 续写高内存使用率

javascript - 为什么 Express 应用程序的 use/all 方法不起作用?

php - 构造函数中无法获取cookie

jquery - sessionStorage 工作但需要 cookie

javascript - 在客户端JS中加密请求参数,在Java中解密请求参数(Spring Controller )