Совместимость 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
,
Также посмотрите этот вопрос с такой же проблемой, как у вас: