2016-07-12 2 views
0

Я создаю приложение, которое использует Socket для связи (сервер < -> клиент).Delphi и NodeJS - Шифровать массив байтового буфера (Rijndael cipher)

Сервер выполнен в NodeJS и клиенте в Delphi.

Для шифрования пакетов на стороне сервера я использую 128-битный ECB Rijndael. Я должен быть в состоянии зашифровать и расшифровать с двух сторон.

Это пример кода на стороне сервера NodeJS скрипт:

var MCrypt = require('mcrypt').MCrypt; 

var desEcb = new MCrypt('rijndael-128', 'ecb'); 
desEcb.open('123456789', 'abcdefghijklmnop'); // key and IV 

var encrypted_buffer = desEcb.encrypt(new Buffer([0x4d,0x79,0x20,0x64,0x61,0x74,0x61])); 
console.log(encrypted_buffer); 

Выходной буфер: 4f ce 37 97 7a dc 11 a9 11 75 97 e6 a3 a4 ae 28

И, в Delphi, это мой код (я использую DCPCrypt2 LIB):

procedure EncryptBuf; 
const 
    buf: array[0..6] of byte = ($4d, $79, $20, $64, $61, $74, $61); 
var 
    Cipher : TDCP_Rijndael; 
    Key, IV : string; 
    data: TByteArray; //32768 bytes 
begin 
    // Pad Key, IV and Data with zeros as appropriate 
    Key := PadWithZeros('123456789', 16); 
    IV := PadWithZeros('abcdefghijklmnop', 16); 

    // Create the cipher and initialise according to the key length 
    Cipher := TDCP_Rijndael.Create(nil); 

    Cipher.Init(Key[1], 128, @IV[1]); {128, 192, 256} 

    Cipher.EncryptECB(buf[0], data[0]); 

    form1.memo1.lines.add(BufferToHex(data[0], length(data))); 

    // Free the cipher and clear sensitive information 
    Cipher.Free; 
    FillChar(Key[1],Length(Key),0); 
end; 

Однако выходной буфер у меня есть: 06 03 AA D5 51 EB 2B 8C 24 D5 4E BF D3 55 2E AA

Что я делаю неправильно? Кто-нибудь может мне с этим помочь?

Спасибо.

+1

Лучше всего не использовать mcrypt, он является отказом, не обновлялся годами и не поддерживает стандартные дополнения PKCS # 7 (née PKCS # 5), только нестандартное нулевое заполнение, которое невозможно даже использовать с двоичными данными. В mcrypt было много выдающихся [ошибок] (https://sourceforge.net/p/mcrypt/bugs/), относящихся к 2003 году. Вместо этого подумайте об использовании [defuse] (https://github.com/defuse/php-encryption), он поддерживается и является правильным. – zaph

ответ

1

Ваш Node.js код использует нулевой блок набивка (я использовал TForge библиотеку, чтобы обнаружить его):

program Project14; 

{$APPTYPE CONSOLE} 

uses 
    SysUtils, tfTypes, tfBytes, tfCiphers; 

procedure Test; 
var 
    Cipher: TCipher; 
    PlainText, EncryptedText, Key, IV: ByteArray; 

begin 
    Key:= ByteArray.FromText('123456789'); 
// IV is not needed in ECB mode 
// IV:= ByteArray.FromText('abcdefghijklmnop'); 
    PlainText:= ByteArray.Parse('0x4d,0x79,0x20,0x64,0x61,0x74,0x61', ','); 
    Writeln(PlainText.ToHex); 

    EncryptedText:= TCipher.AES 
//     .ExpandKey(Key, ECB_ENCRYPT or PADDING_ZERO, IV) 
        .ExpandKey(Key, ECB_ENCRYPT or PADDING_ZERO) 
        .EncryptData(PlainText); 
    Writeln(EncryptedText.ToHex); 

// Cipher:= TCipher.AES.ExpandKey(Key, ECB_DECRYPT or PADDING_ZERO, IV); 
    Cipher:= TCipher.AES.ExpandKey(Key, ECB_DECRYPT or PADDING_ZERO); 
    PlainText:= Cipher.DecryptData(EncryptedText); 
    Writeln(PlainText.ToHex); 

    readln; 
end; 

begin 
    try 
    Test; 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
end. 

Обратите внимание, что заполнение нулями не позволяет правильно дешифрования (расшифрованный данные также дополняется нулями, а приведенный выше код).

DCPCrypt не поддерживает прокладку, поэтому вам нужно самостоятельно прокладывать свои данные незашифрованного текста. Это легко в случае нулевого заполнения - просто введите свой обычный текст buf с нулями до 16 байтов (не установлен DCPCrypt, не можете протестировать).

+0

Привет @ user246408, спасибо за ответ. Какую версию Delphi и TForge вы используете? Я использую Delphi 7, и я получаю много ошибок при компиляции TForge 075. И, в случае использования DCPCrypt, почему мне приходится заполнять buf до 16 байтов? Что, если мой buf больше 16 байт? – paulohr

+0

TForge не поддерживает Delphi 7 (минимальная поддерживаемая версия - Delphi 2009). – kludg

+0

И не используйте DCPCrypt, если вы можете перейти с Delphi 7. – kludg

1

Сценарий NodeJS использует режим ECB, который не использует iv, но один предоставляется. Также существует разрыв между именем var desEcb, который, по-видимому, подразумевает шифрование DES, но алгоритм указан как rijndael-128, который по существу является AES-шифрованием.

В коде Delphi используется режим ECB, который не использует iv, но один из них предоставляется.

Лучше всего предоставить ключ шифрования точно такой длины (128, 192, 256 бит для AES), потому что заполнение клавиш не указано, а другая реализация может быть разной.

Обычно требуется заполнить, а стандарт - PKCS#7 padding, а не пробел. Обратите внимание, что двоичные данные не могут использоваться с нулевым заполнением.

Примечание: не используйте режим ECB, он небезопасен, см. ECB mode, прокрутите вниз до пингвина.

Вместо режима ECB используйте режим CBC со случайным iv, просто добавьте iv к зашифрованным данным для использования при расшифровке.

Если вы хотите протестировать свое шифрование в режиме онлайн, используйте AES CALCULATOR от Cryptomathic.

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