簡體   English   中英

如何使用nodejs解密cookie

[英]How to decrypt cookie with nodejs

我想試試這個

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中 ,它提到了有關節點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 version:4.1.2和crypto version 0.0.3

如何使用此算法正確解密cookie,或者您可以建議其他任何?

[假設您正在嘗試解密.NET框架cookie]:

(注意:這個答案完全重寫了,因為事情並不像看起來那么簡單)

這里描述加密模式,引用了有趣的部分:

驗證+解密數據(fEncrypt = false,signData = true)

  • 輸入:buf表示要解密的密文,修飾符表示要從明文末尾刪除的數據(因為它不是真正的純文本數據)
  • 輸入(buf):E(iv + m +修飾符)+ HMAC(E(iv + m +修飾符))
  • 輸出:m

  • 以上描述中的“iv”不是實際的IV。 相反,如果ivType => IVType.Random,我們會在將明文提供給加密算法之前將隨機字節('iv')添加到明文中。 在算法的早期引入隨機性可以防止用戶檢查兩個密文以查看明文是否相關。 如果ivType = IVType.None,則'iv'只是一個空字符串。 如果ivType = IVType.Hash,我們使用明文的非鍵控哈希。

  • 上面描述中的“修飾符”是一段元數據,應該與明文一起加密,但實際上並不是明文本身的一部分。 它可用於存儲諸如生成此明文的用戶名,生成明文的頁面等內容。在解密時,將修飾符參數與存儲在加密流中的修飾符進行比較,並將其從返回純文本之前的消息。

哪個(希望)使用以下腳本實現:

// 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用於身份驗證

  • 因為使用的身份驗證密鑰未知,所以完整性檢查條件被注釋掉並且使用來自這個非常相關的問題的驗證密鑰(這是認證標簽不匹配的原因)

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

  • “修飾符”字段假定為空。 如果不是這種情況,您必須檢查它並從明文中刪除它

  • 對於生產環境,你肯定應該檢查身份驗證標記(否則你會暴露自己討厭的攻擊)

  • 為了避免更嚴重的攻擊,應該在恆定時間內測試身份驗證標記是否相等(在nodejs中實現可能很棘手)。 請注意,注釋掉的代碼很可能容易受到時間攻擊。

  • IV長度等於密鑰長度(見這里的原因)

免責聲明:我沒有徹底研究原始的.NET代碼,也不是加密專家,所以請確認我的想法

祝好運!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM