Совместимость LockBox / Node Crypto

Я пытаюсь (и не могу) расшифровать в Delphi с помощью LockBox 3 сообщение, которое было зашифровано с использованием крипто-библиотеки Node.js.

код node.js:

var crypto = require('crypto');
var cipher = crypto.createCipher('aes-256-ctr', 'my password');
var crypted = cipher.update('hello world', 'utf8', 'base64');
crypted += cipher.final(output_encoding);
console.log(crypted);

Результатом этого является

oyC1KRVx3JZBLlI=

Код Delphi:

var
  Codec: TCodec;
  CipherText: AnsiString;
begin
  Codec := TCodec.Create(nil);
  try
    Codec.CryptoLibrary := TCryptographicLibrary.Create(Codec);
    //
    Codec.StreamCipherId = 'native.StreamToBlock';
    Codec.BlockCipherId  = 'native.AES-256';
    Codec.ChainModeId    = 'native.CTR';
    //
    Codec.Password := 'my password';
    Codec.DecryptAnsiString(CipherText, 'oyC1KRVx3JZBLlI=');
    //
    Result := string(CipherText);
  finally
    Codec.Free;
  end;
end;

Что мне не хватает?

1 ответ

Решение

В чем проблема?

Проблема состоит в том, что обе библиотеки используют разные ключи и векторы инициализации (IV) внутри.

Помните, что шифр AES работает не с паролями, а с ключами и IV.

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

Этот механизм неочевиден, но обычно описывается в документации по криптографическим библиотекам.

Документация crypto модуль в node.js говорит, что использует EVP_BytesToKey Функция OpenSSL для получения ключа и IV:

crypto.createCipher (алгоритм, пароль) - создает и возвращает объект Cipher, который использует данный алгоритм и пароль.

...

Пароль используется для получения ключа шифра и вектора инициализации (IV). Значение должно быть либо двоичной кодированной строкой, либо [Buffer [].

Реализация crypto.createCipher () получает ключи, используя функцию OpenSSL EVP_BytesToKey с алгоритмом дайджеста, установленным в MD5, одна итерация и без соли. Отсутствие соли допускает атаки по словарю, так как один и тот же пароль всегда создает один и тот же ключ. Низкое количество итераций и некриптографически безопасный алгоритм хеширования позволяют очень быстро тестировать пароли.

Цитата из Node.js v5.6.0 Документация.

Как решить проблему?

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

Быстрое и грязное (и крайне небезопасное) решение - найти процедуру Delphi, эквивалентную EVP_BytesToKey и просто используйте это, чтобы заставить это работать.

Не забудьте также проверить, что вы используете ту же схему заполнения. TCodec должен позволить вам выбрать PaddingScheme из padPKCS, который должен быть совместим с тем, который используется криптомодулем в node.js, Если это не работает, попробуйте и другие варианты.


Другой вариант - использовать OpenSSL в Delphi, который уже должен быть совместим с тем, что используется в node.js,


Также посмотрите этот вопрос с такой же проблемой, как у вас:

Другие вопросы по тегам