2015-09-18 4 views
1

Я пытаюсь расшифровать файл, зашифрованный с помощью openssl, с помощью CryptoJS 3.1.5.Decrypt openssl AES с CryptoJS

Все работает нормально, если я шифрую и расшифровываю с помощью CryptoJS, то же самое касается OpenSSL в оболочке, но когда я пытаюсь смешивать CryptoJS с OpenSSL, все идет не так.

Файл создается с помощью следующей команды:

openssl enc -aes-256-cbc -in file.txt -out file.enc -k password 

, и я пытаюсь расшифровать так:

fs.readFile('file.enc', function(err, data) { 
    var decrypted = CryptoJS.AES.decrypt(
        data.toString(), 
        "password", 
        { mode : CryptoJS.mode.CBC } 
       ); 

    console.log(decrypted.toString(CryptoJS.enc.Utf8)); 
}); 

// Give me this err: Uncaught Error: Malformed UTF-8 data 

И по-другому, я:

fs.readFile('file.txt', function(err, data) { 
    var encrypted = CryptoJS.AES.encrypt(
        data.toString(), 
        "password", 
        { mode : CryptoJS.mode.CBC }); 

    fs.writeFile('file.enc', encrypted); 
}); 

А затем в Shell:

openssl enc -d -aes-256-cbc -in file.enc -out file2.txt -k password 
// Give me this err: bad magic number 

Я пропустил что-то очевидное?

+0

Почему вы используете CryptoJS в Node.js, если есть интегрированный модуль 'crypto'. Кроме того, какой модуль CryptoJS вы используете? –

+0

Мне нужен CryptoJS 3.1.5 Я столкнулся с подобной проблемой, используя модуль crypto nodejs, я могу опубликовать больше кода примера, если вы хотите. – Tagada

+0

Извините, я использую этот: https://www.npmjs.com/package/crypto-js – Tagada

ответ

0

не определенно ответ, но еще слишком много для комментариев:

Commandline openssl enc по умолчанию использует пароль на основе шифрования (PBE) с солью, что означает фактический ключ шифрования и IV, когда это применимо, которые он для CBC , вычисляются по данному паролю и случайному значению соли на Password Based Key Derivation Function, что затрудняет попытку противника попытаться атаковать с помощью пароля. Я не знаю вашего JS-модуля (или много JS вообще), но веб-страница, которую вы связываете, содержит список примитивов низкого уровня, предполагающих, что это не автоматически делает PBE. Текстовая строка типа «пароль» (возможно) подходит для PBE, но не для прямого шифрования AES, где ключ должен быть ровно 128, 192 или 256 бит и должен быть случайными двоичными данными.

Если вы хотите использовать полустандарт openssl PBE, совместите его со стороной JS; возможно, полезно использовать пункт evpkey, так как EVP - это модуль openssl, и я не знаю никакой другой (PB) схемы KDF, которая будет называться EVP. Если нет, то enc по умолчанию PBE - это всего лишь MD5 паролей, соединенных с солью, и повторяется с обратной связью столько раз, сколько необходимо, что в этом случае равно трем. См. https://superuser.com/questions/455463/openssl-hash-function-for-generating-aes-key для примера в (в основном) perl. OpenSSL префикс 8 символов ASCII «Salted__» и 8 байтов соли для файла, поэтому вам нужно удалить их (и использовать соль) перед расшифровкой или добавить их после шифрования.

Если вы хотите сырец шифрования, выбрать более подходящий ключ (на какой стороне), а также уникальный и непредсказуемый IV, если вы всегда использовать новый ключ в этом случае вы можете использовать фиксированный IV, и на OpenSSL боковое использование -K (примечание в верхнем регистре) и -iv для указания этих значений в гексагоне. См. Справочную страницу в любой системе Unix с установленным openssl или https://www.openssl.org/docs/manmaster/apps/enc.html.

Плюс в любом случае enc по умолчанию "PKCS # 5" (действительно PKCS # 7) прокладка. Я не знаю, работает ли ваш JS-модуль; если нет, вы должны указать его. Если вы не можете гарантировать, что ваш открытый текст всегда будет кратным 16 байт (после любой кодировки, такой как UTF8); то вы можете указать (или, может быть, по умолчанию) отсутствие прокладки на стороне JS и указать -nopad на стороне openssl.

+0

Спасибо, что именно такая информация я искал. Я обновлю основной вопрос с моим окончательным кодом, когда он будет работать – Tagada

+1

CryptoJS на самом деле делает PBE в OpenSSL-совместимом способе воссоздания EVP_BytesToKey. Вероятно, проблема связана с какой-то странной проблемой кодирования, поскольку код OP должен работать. –

2

Этот PHP-код, который включает в командной строке, OpenSSL шифрования:

http://pastebin.com/sivmZvSw

... совместима с этим CryptoJS код, который я обычно запускается из командной строки с помощью jsc на мой Mac:

http://pastebin.com/LcDBG7yj

(Этот код был написан с CryptoJS 3.1.2, хотя я бы не стал ожидать большую разницу между этим и 3.1.5)

Трюки являются:.

  1. Как указано в другой ответ, вы должны указать точный ключ и IV с обеих сторон, чтобы он работал.

  2. Несмотря на то, что AES-256 теоретически может обрабатывать 128-битные ключи, я обнаружил, что работают только 256-битные ключи.

  3. В этих примерах я избежал использования значения соли. Вы могли бы сделать его более безопасным, включив соль, но убедитесь, что вы правильно указали его в обоих местах.

  4. Другая вещь, которая ловит людей, - они думают, что могут просто передать строку функции CryptoJS.decrypt(). Это неверно. CryptoJS.decrypt() ожидает cipherParams объект. (Смотри пример.)

  5. Что касается дополнения: как CryptoJS и OpenSSL по умолчанию для PKCS # 7, который функционально эквивалентен PKCS # 5, за исключением PKCS # 7 может обрабатывать любой размер блока. Когда мы говорим о размерах блоков в 8 байтов, они идентичны. В любом случае вам не нужно указывать заполнение в CrytoJS.

Удачи вам!

6

Для записи, это как я дешифровать файл openssl.

//openssl enc -aes-256-cbc -in file.txt -out file.enc -k password 

fs.readFile('file.enc', function(err, data) { 
    var salt   = data.toString("hex", 8, 16), 
     enc   = data.toString("hex", 16, data.length), 
     derivedParams = CryptoJS.kdf.OpenSSL.execute(
         password, 
         256/32, 
         128/32, 
         CryptoJS.enc.Hex.parse(salt) 
        ), 
     cipherParams = CryptoJS.lib.CipherParams.create({ 
         ciphertext : CryptoJS.enc.Hex.parse(enc) 
        }), 
     decrypted  = CryptoJS.AES.decrypt(
         cipherParams, 
         derivedParams.key, 
         { iv : derivedParams.iv } 
        ); 

    console.log(hex2a(decrypted.toString())); // result is in hexa 
}); 

И это, как я шифровать, чтобы сделать его работу с OpenSSL

fs.readFile('file.txt', function(err, data) { 
    var encrypted = CryptoJS.AES.encrypt(data.toString(), password); 
     buff  = new Buffer(encrypted.toString(), "base64"); 

    fs.writeFile('file.enc', buff); 
}); 

// openssl enc -d -aes-256-cbc -in file.enc -out file2.txt -k password 

Надеюсь, это поможет кому-то :)

+0

Поддерживает ли этот метод параметр '-salt', который поддерживает openssl? – Jaap

Смежные вопросы