Шифрование данных с помощью рубиновой расшифровки с помощью узла - PullRequest
8 голосов
/ 25 августа 2011

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

//js
var crypto = require('crypto');

var key = crypto.createHash('sha1').update('key').digest('hex');
console.log(key); // a62f2225bf70bfaccbc7f1ef2a397836717377de

var encrypted = "";
var cipher = crypto.createCipher('bf-cbc', key);

encrypted += cipher.update('text');
encrypted += cipher.final('hex');

console.log(encrypted); //outputs 4eafd5542875bd3c

Итакпохоже, что я получаю шестнадцатеричную строку из кодировки.

#ruby
require 'openssl'
require 'digest/sha1'
c = OpenSSL::Cipher::Cipher.new("bf-cbc")
c.encrypt
# your pass is what is used to encrypt/decrypt
c.key = key = Digest::SHA1.hexdigest("key")
p key # a62f2225bf70bfaccbc7f1ef2a397836717377de
e = c.update("text")
e << c.final
p e # 皋?;??

Есть ли какая-то проблема с кодировкой, которую мне не хватает.Я попытался декодировать e с помощью base64, но это не дало того же результата, что и приложение узла.Любые указатели?

ОБНОВЛЕНИЕ: Так что это как близкий друг, и я могу получить: https://gist.github.com/a880ea13d3b65a21a99d. Блин, я просто хочу зашифровать что-то в ruby ​​и расшифровать это в узле.

ОБНОВЛЕНИЕ2: Хорошо, код в этом выпуске помогает мне понять: https://github.com/joyent/node/issues/1395

Ответы [ 3 ]

4 голосов
/ 25 августа 2011

Есть несколько тонких вещей, которые делают это неудачей.Самый важный из них - вы не указываете IV в своем коде, поэтому для вас будет сгенерировано случайное значение.Вы могли бы заметить, что таким способом вы даже не можете расшифровать свой зашифрованный текст на одном и том же языке программирования.

Так что вам нужно предоставить явный IV для обеих реализаций.Но прежде чем я покажу вам код, несколько советов:

Генерация ключей :

Blowfish работает на 64-битных блоках, размер ключа варьируется, но OpenSSL (который в настоящее время работаетРеализация шифров как в Ruby, так и в node.js) по умолчанию использует 128 бит, то есть 16 байтов.

Таким образом, ваш ключ нарушает два принципа - первый: он просто слишком длинный.Это шестнадцатеричное представление хэша SHA-1, которое составляет 20 байтов * 2 = 40 байтов вместо 16. В большинстве случаев это нормально, потому что реализация соответствующим образом усекает значения, но это то, что вы не должны зависит от.

Вторая ошибка, гораздо более серьезная, заключается в том, что вы используете шестнадцатеричное представление вместо необработанных байтов: большая проблема безопасности!Шестнадцатеричные символы не являются случайными вообще, поэтому вы фактически уменьшаете энтропию вашего ввода до половины длины (потому что нижележащие байты были случайными).

Безопасный способ генерации случайных ключей - использование OpenSSL :: Random

key = OpenSSL::Random.random_bytes(cipher_key_len)

Третья ошибка заключается в том, чтобы сохранить ваш ключ жестко закодированным в источниках.Это плохая идея.Минимум, что вам нужно сделать, это сохранить его в другом месте в файловой системе, где доступ строго ограничен.Смотрите также мой ответ на другой вопрос.Ключ должен храниться вне диапазона и только динамически загружаться в приложение.

Шифр ​​:

Blowfish стареет.Он по-прежнему считается непрерывным в том смысле, что грубое принуждение - единственный способ его сломать.Но пространство поиска 2 ^ 64 не доступно для находчивых злоумышленников.Поэтому вам действительно следует перейти к AES.

Padding :

Пэды OpenSSL с использованием PKCS5Padding (также известный как PKCS7Padding) по умолчанию.Ruby извлекает из этого выгоду, и моя ставка - это node.js, который тоже этим пользуется - поэтому вы должны быть в безопасности.

Теперь перейдем к рабочему решению.Нам нужно сгенерировать IV, Blowfish требует, чтобы он был 64-битным - 8 байтов.Вам понадобятся rbytes, чтобы получить безопасные случайные числа в узле.IV может быть жестко закодирован в ваших источниках (это общедоступная информация, не влияет на безопасность), но он должен быть одинаковым для обеих сторон.Вы должны предварительно сгенерировать значение и использовать его как для node.js, так и для Ruby.

/*node.js*/

var rbytes = require('rbytes');
var iv = rbytes.randomBytes(8);

/*see advice above - this should be out-of-band*/
var key = rbytes.randomBytes(16);
var encrypted = "";
var cipher = crypto.createCipheriv('bf-cbc', key, iv);

encrypted += cipher.update('text');
encrypted += cipher.final('hex');

Теперь часть Ruby:

require 'openssl'

c = OpenSSL::Cipher::Cipher.new("bf-cbc")
c.encrypt
# should be out-of-band again
c.key = OpenSSL::Random.random_bytes(16)
# may be public but has to be the same for Ruby and node
iv = OpenSSL::Random.random_bytes(8)
c.iv = iv 
e = c.update("text")
e << c.final
puts e.unpack('H*')[0]
0 голосов
/ 26 августа 2011

OK.Я хочу поблагодарить всех за помощь.В основном эта ветка отвечает на мой вопрос: https://github.com/joyent/node/issues/1395. Я собираюсь опубликовать две программы на случай, если кому-то еще придется пройти через эту ригамаролу.Имейте в виду, что это не означает быть жестко защищенным, это ступенька для рубинового шифрования данных и дешифрования узла.Вам нужно будет предпринять дополнительные шаги, чтобы убедиться, что приняты более строгие меры безопасности.

Код находится в этой сущности: https://gist.github.com/799d6021890f34734470

Они были запущены на ruby ​​1.9.2p290 и узле 0.40,10

0 голосов
/ 25 августа 2011

Ваш зашифрованный текст будет представлять собой несколько случайно выглядящих байтов.Эти байты могут быть выражены в виде hex, Base64 или другими способами.Похоже, ваш код ruby ​​выводит необработанные байты.Я предлагаю вам преобразовать эти необработанные байты в шестнадцатеричные для сравнения.

Глядя на свой код, вы также должны перейти с Blowfish ("bf") на AES.Blowfish имеет 64-битный размер блока и теперь устарел.

Вы бы хорошо явно указали заполнение, PKCS7 является общим

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...