Зашифровать строку AES в Delphi (10 Seattle) с помощью DCrypt, расшифровать с помощью PHP/OpenSSL

Учитывая этот код в Delphi с использованием DCrypt:

Uses DCPcrypt2, DCPblockciphers, DCPrijndael, DCPbase64;

procedure TForm1.Button1Click(Sender: TObject);
var Cipher : TDCP_rijndael;
    ss, k, Data, Key, IV : Ansistring;
const
  KeySize = 32; // 32 bytes = 256 bits
  BlockSize = 16; // 16 bytes = 128 bits // IV
begin
  key := '12345678901234567890123456789012';
  iv  := '1234567890123456';
  Data := 'thisis128bitstxt';

  Cipher := TDCP_rijndael.Create(nil);
  Cipher.Init(Key[1],128,@IV[1]);
  Cipher.EncryptCBC(Data[1],Data[1],Length(Data));
  Cipher.Free;

  Data := DCPBase64.Base64EncodeStr(Data);
  Memo1.Lines.Add(Data);
end;

Я получаю следующее: Eq7iMlVKysMMXdhR0rtrwA==

Попытка того же в PHP с OpenSSL:

<?
    $s = "thisis128bitstxt";
    $s = openssl_encrypt($s, "AES-128-CBC", "12345678901234567890123456789012", 0, "1234567890123456");
    echo $s . "</br>";
?>

возвращает: Eq7iMlVKysMMXdhR0rtrwEbhkypNJyuwGafLILvwpbY=

Что не так?

Если я попытаюсь расшифровать вывод delphi, я получу пустую строку:

$s = "Eq7iMlVKysMMXdhR0rtrwA==";
$s = openssl_decrypt($s, "AES-128-CBC", "12345678901234567890123456789012", 0, "1234567890123456");
echo $s . "</br>";

person hikari    schedule 22.12.2016    source источник
comment
Похоже, вам не хватает прокладки   -  person David Heffernan    schedule 22.12.2016
comment
Какая у вас версия Дельфи? Пожалуйста, отредактируйте вопрос и добавьте правильный тег   -  person Arioch 'The    schedule 22.12.2016
comment
Когда дело доходит до криптографии, нет такой вещи, как строка. Есть последовательности байтов. Но разве строки не являются последовательностями байтов? они есть, но есть много разных правил преобразования текста в байты и байтов в текст. Они называются наборами символов, кодировками и чем-то еще. Вы исправили строку Delphi на AnsiString... Выглядит хорошо. Вдвойне, если ваша копия DCPCrypt также использует этот тип, а не двусмысленный подстановочный знак string. Но что использует PHP? ВСЕ, ЧТО ваш редактор поместил в файл: php. сеть/руководство/ru/   -  person Arioch 'The    schedule 22.12.2016
comment
Строка SO PHP... Ну, что угодно. Что-либо, что ожидает веб-сервер, или что-либо, что ожидает PHP IDE .... Итак, я бы начал с противоположного направления: взял строку, сгенерированную PHP, и попытался декодировать ее в Delphi в TBytes или другую необработанную последовательность байтов, а затем увидел какую кодировку можно использовать для преобразования этих байтов в текст. UTF-16, UTF-8, что-то еще...   -  person Arioch 'The    schedule 22.12.2016
comment
текст, который мне нужно обработать, полностью анси   -  person hikari    schedule 22.12.2016


Ответы (1)


Дэвид Хеффернан уже указал вам правильное направление. Я вот завершаю.

вы не должны пропустить заполнение. Я исправил ваш код следующим образом.

procedure TForm1.Button1Click(Sender: TObject);
var Cipher : TDCP_rijndael;
    Data, Key, IV : ansistring;
    index, dataLength, bsize, pad: integer;
begin
  key := '12345678901234567890123456789012';
  IV  := '1234567890123456';
  Data := 'thisis128bitstxt';

  Cipher := TDCP_rijndael.Create(nil);
  try
    Cipher.Init(Key[1],128,@IV[1]);

    //don't miss padding
    {start padding}
    dataLength := Length(Data);
    bsize := (Cipher.BlockSize div 8);
    pad := bsize - (dataLength mod bsize);
    for index := 1 to pad do
      Data := Data+chr(pad);
    {end padding}

    Cipher.EncryptCBC(Data[1],Data[1],Length(Data));
  finally
    Cipher.Free;
  end;

  Data := DCPBase64.Base64EncodeStr(Data);
  Memo1.Lines.Add(Data);
end;

вы получите тот же результат, что и php.

person Loghman    schedule 22.12.2016
comment
С этим есть проблема, если теперь я хочу расшифровать данные, я не получу тот же исходный ввод, так как есть дополнительное дополнение, как бы вы определили, сколько нужно удалить из конца файла, чтобы вернуть 100% оригинальный контент? - person hikari; 10.01.2017
comment
nvm что, перешел на CTR, то прокладка мне не нужна. - person hikari; 10.01.2017
comment
@hikari Это легко. последний символ показывает, сколько вы должны удалить. slen:=Length(src); cipher.Init(key[0], 128, @iv[0]); cipher.Decrypt(src[0], dest[0], slen); pad := dest[slen - 1]; SetLength(dest, slen - pad); result := TEncoding.ASCII.GetString(dest); - person Loghman; 10.01.2017
comment
но тогда как вы различите, является ли это дополнением или фактическими данными? - person hikari; 10.01.2017