Как расшифровать куки с помощью 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);

В этом Вопросы и ответы упоминаются различия в версиях 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 с помощью этого алгоритма или вы можете предложить какой-либо другой?


person asdf_enel_hak    schedule 19.01.2016    source источник
comment
Проблема, с которой вы столкнулись, заключается в том, что ваш cipherText для блочного шифра AES в режиме CBC не выровнен по блокам (т. е. его длина не делится на размер блока шифра, который составляет 16 байтов для AES). Попробуйте удалить последние восемь символов (четыре шестнадцатеричных байта) из файла cookie (например, 1224FAE8), так как они могут быть частью тега целостности сообщения. См. здесь для возможной расшифровки и проверьте свой открытый текст (по крайней мере, часть мне кажется, это нормально, так как он содержит допустимые значения UTF-16)... дайте мне знать   -  person vlp    schedule 10.10.2016
comment
Вы читали этот вопрос?   -  person vlp    schedule 10.10.2016
comment
@vlp Я не в этой теме.. извините   -  person asdf_enel_hak    schedule 10.10.2016
comment
надеюсь, что эта ссылка может немного помочь lollyrock.com/articles/nodejs-encryption/,let я знаю :)   -  person Pritish Vaidya    schedule 15.10.2016
comment
@asdf_enel_hak (я понимаю, что вас больше не интересует этот вопрос, но) разве у вас нет используемого значения ключа проверки? Было бы интересно проверить тег аутентификации...   -  person vlp    schedule 15.10.2016
comment
@vlp, к сожалению, это был старый проект, и у меня больше нет среды :(   -  person asdf_enel_hak    schedule 15.10.2016
comment
@asdf_enel_hak хорошо, спасибо за ответ... удачи в новых проектах!   -  person vlp    schedule 15.10.2016


Ответы (1)


[Предположим, что вы пытаетесь расшифровать файл cookie .NET framework]:

(Примечание: этот ответ был полностью переписан, так как все было не так просто, как казалось)

Схема шифрования описана здесь с указанием интересных частей:

ПРОВЕРИТЬ + РАСШИФРОВАТЬ ДАННЫЕ (fEncrypt = false, signData = true)

  • Ввод: buf представляет зашифрованный текст для расшифровки, модификатор представляет данные, которые нужно удалить из конца открытого текста (поскольку это не данные открытого текста)
  • Ввод (buf): E(iv + m + модификатор) + HMAC(E(iv + 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 и не являюсь экспертом по криптографии, поэтому, пожалуйста, подтвердите мои мысли.

Удачи!

person vlp    schedule 09.10.2016
comment
HMACSHA256_HASH_SIZE = 32 Это 32 байта (256 бит), а не 32 бита. Весь смысл HMAC заключается в проверке целостности. Это не поможет вам, если вы просто откажетесь от него. - person Phil; 15.10.2016
comment
Извините, это моя ошибка. Не увидел ваш последний пункт. Возможно, заполнение отключено, потому что вы недостаточно обрезали для hmac. - person Phil; 15.10.2016
comment
@Phil_1984_ Вы определенно правы - я дважды неправильно понял исходный код: 1. Длина подписи указана в байтах (я не перепроверял ее). 2. SHA-1 HMAC используется вместе с шифрованием AES (а не на основе SHA256 по умолчанию)... Теперь даже заполнение PKCS#7 в порядке (моя ошибка, а также то, что я проглядел его в открытом тексте). Благодарю вас! (Жаль, что сообщение не содержит ключа проверки, поскольку ответ был бы намного полезнее с проверкой HMAC) - person vlp; 15.10.2016
comment
Обычно ключ проверки совпадает с ключом дешифрования. Вы пробовали это? Я предполагаю, что с другим ключом проверки это позволяет проверять стороннюю сторону без возможности расшифровки. - person Phil; 16.10.2016
comment
@Phil_1984_ Я пробовал, и тег аутентификации другой. Наличие одного и того же значения ключа для шифрования и аутентификации нарушит принцип одноразового использования одного ключа. Интересное обсуждение этого конкретного случая здесь - person vlp; 17.10.2016
comment
Интересный. Есть ли у вас какие-либо ссылки о принципе одноразового использования одного ключа? Гугл у меня не работает. Я не могу придумать причину иметь разные ключи, поскольку и шифрователю, и дешифратору все равно нужны оба. - person Phil; 19.10.2016
comment
@Phil_1984_ Ищите принцип разделения ключей (мне следовало использовать этот термин), например здесь, здесь. - person vlp; 19.10.2016
comment
Спасибо за это. Так что обычно ключи не идентичны (я ошибался), но один ключ получается из первого ключа с использованием известного KDF. Я все еще не вижу смысла использовать два совершенно разных ключа, как это выглядит, как это делает крипто, но, возможно, я просто не умею читать ASP/.NET. - person Phil; 20.10.2016
comment
@Phil_1984_ Когда я пишу в ответе, я взял ключ проверки здесь (ключи HMAC могут быть произвольно длинными - они хэшируется, если слишком длинный). Если бы вы могли предоставить несколько полных тестовых векторов (decKey, authKey, m, modifier, cookie), я был бы признателен. - person vlp; 20.10.2016
comment
@Phil_1984_ Что касается получения ключа, я не изучал его, но правильный подход (ИМХО) должен состоять в том, чтобы сгенерировать два независимых ключа или иметь один главный ключ и получить из него оба ключа auth/dec. Первый подход используется для параметра AutoGenerate (см. здесь) - person vlp; 20.10.2016
comment
@v0id - я отклонил ваше редактирование, поскольку, насколько мне известно, длина предшествующего IV равна длине ключа (см. записи). Если вы уверены, что длина IV равна размеру блока, сообщите мне об этом. Удачи! - person vlp; 24.01.2018
comment
@vlp: знаете ли вы, какая сериализация используется в расшифрованном значении cookie? - person byrnedo; 15.01.2019
comment
@byrnedo Я не знаю, у тебя есть еще тестовые векторы? - person vlp; 16.01.2019
comment
@vlp действительно нашел то, что искал здесь: referencesource.microsoft. com/#system.web/Безопасность/ - person byrnedo; 16.01.2019