0

There are a few variations of this question around but i haven't been able to pin the problem down. Trying to encrypt/unencrypt in PHP and Delphi I assume I have missed some setting in Delphi and its to do with UTF-8

using http://aesencryption.net/ as a PHP Example the result we are trying to get. Image Blow
Password = 123
Key = Test
128 bit
Encrypts to uuIikEZSC9Sa1HAt/XKfGQ==

I want to be able to unencrypt this in Delphi
I'm using Delphi XE5
with https://github.com/SeanBDurkin/tplockbox
I can get encrypt/DeCrypt working inside Delphi but the PHP encrypted version string is different

Delphi encrypts 123 to vpdeLlfnxTGrSsa2TpbFvg==

Here is a quick example of the Delphi Encrypt

function TForm3.EncryptV2(plainText: UTF8String): String;
var CipherText : string;
    FLibrary: TCryptographicLibrary;
    FCodec: TCodec;
begin
  mmo1.Lines.Add('plaintext = ' + plainText);

 FLibrary := TCryptographicLibrary.Create(Self);
  try
    FCodec := TCodec.Create(Self);
    try
      FCodec.CryptoLibrary := FLibrary;
      FCodec.StreamCipherId := BlockCipher_ProgId;
      FCodec.BlockCipherId := Format(AES_ProgId, [256]);
      FCodec.ChainModeId := ECB_ProgId; ;
      FCodec.UTF8Password := 'test';
      FCodec.EncryptString( plainText, CipherText, Tencoding.UTF8 );
      FCodec.Burn;

      result := CipherText;
    finally
      FCodec.Free;
    end;
  finally
    FLibrary.Free;
  end;
end;

Decrypt

function TForm3.DecryptV2(encryptedText: UTF8String): String;
  var plainText : string;
    FLibrary: TCryptographicLibrary;
    FCodec: TCodec;
begin
  FLibrary := TCryptographicLibrary.Create(Self);
  try
    FCodec := TCodec.Create(Self);
    try
      FCodec.CryptoLibrary := FLibrary;
      FCodec.StreamCipherId := BlockCipher_ProgId;
      FCodec.BlockCipherId := Format(AES_ProgId, [256]);
      FCodec.ChainModeId := ECB_ProgId; ;
      FCodec.UTF8Password := 'test';

      mmo1.Lines.Add('Encrypted Text = ' + encryptedText);
      FCodec.DecryptString( plainText, encryptedText,Tencoding.UTF8 );
      mmo1.Lines.Add('DeCrypted Text = ' + plainText);
      result := plainText;
    finally
      FCodec.Free;
    end;
  finally
    FLibrary.Free;
  end;
end;

Anyone have any suggestions?

enter image description here

Dangas56
  • 849
  • 1
  • 8
  • 32
  • 1
    Please don't use aesencryption.net as a reference for encryption, because it uses a bad mode (ECB), a bad padding (Zero padding) and doesn't support authentication. – Artjom B. Aug 05 '16 at 16:57
  • 1
    **Never use [ECB mode](http://crypto.stackexchange.com/q/14487/13022)**. It's deterministic and therefore not semantically secure. You should at the very least use a randomized mode like [CBC](http://crypto.stackexchange.com/q/22260/13022) or [CTR](http://crypto.stackexchange.com/a/2378/13022). It is better to authenticate your ciphertexts so that attacks like a [padding oracle attack](http://crypto.stackexchange.com/q/18185/13022) are not possible. This can be done with authenticated modes like GCM or EAX, or with an [encrypt-then-MAC](http://crypto.stackexchange.com/q/202/13022) scheme. – Artjom B. Aug 05 '16 at 16:57
  • I couldn't get Cbc or any other ones to match up either. Thought I'd try and get the easy one going first then see if it's the same reason the other ones don't match – Dangas56 Aug 06 '16 at 00:27
  • 1
    If you are trying to get things working use full length keys, there is no standard for key padding, it can range from 0x00 characters to whatever garbage bytes follow the key in memory. Go back and provide a sample with a full key of 16-bytes and a full block of data, again 16-bytes and add the results to the question. It also makes things more clear to use hexadecimal in place to Base64 encoding for sample data. Dump the input text in hex and it will be clear if the string encoding us UTF-8 or UTF-16. – zaph Aug 06 '16 at 00:32
  • I'll give that a try and update the question – Dangas56 Aug 06 '16 at 00:43

1 Answers1

0

Not sure what is wrong with lockbox, but here is code that matches aesencryption using OpenSSL, OverbyteIcsLibeay unit is from ICS library http://wiki.overbyte.be/wiki/index.php/ICS_Download

{$APPTYPE CONSOLE}
program aestest;

uses System.SysUtils, System.NetEncoding, OverbyteIcsLibeay;

type
  TKey128 = packed array [0..15] of byte;
  TIV128  = packed array [0..15] of byte;

function AES128EncryptDecrypt(var Source: TBytes; const Key: TKey128;
  const InitializationVector: TIV128; Encrypt: boolean): boolean;
var
  IV: TIV128;
  CipherCtx: PEVP_CIPHER_CTX;
  Dest: TBytes;
  OutLen: Integer;
begin
  Result := False;
  IV := InitializationVector;
  LoadLibeayEx;
  SetLength(Dest, Length(Source) + Length(Key));
  CipherCtx := f_EVP_CIPHER_CTX_new;
  try
    f_EVP_CIPHER_CTX_init(CipherCtx);
    if Encrypt then
    begin
      if f_EVP_EncryptInit_ex(CipherCtx, f_EVP_aes_128_ecb(), nil, @Key[0], @IV[0]) then
      begin
        Result := f_EVP_EncryptUpdate(CipherCtx, @Dest[Low(Dest)], OutLen, @Source[Low(Source)], Length(Source));
        if Result then
          Source := Copy(Dest, Low(Dest), OutLen);
      end;
    end
    else
    begin
      if f_EVP_DecryptInit_ex(CipherCtx, f_EVP_aes_128_ecb(), nil, @Key[0], @IV[0]) then
      begin
        SetLength(Source, Length(Source) + Length(Key));
        Result := f_EVP_DecryptUpdate(CipherCtx, @Dest[Low(Dest)], OutLen, @Source[Low(Source)], Length(Source));
        if Result then
          Source := Copy(Dest, Low(Dest), OutLen);
      end;
    end;
    f_EVP_CIPHER_CTX_cleanup(CipherCtx);
  finally
    f_EVP_CIPHER_CTX_free(CipherCtx);
  end;
end;

function AES128Encrypt(var Source: TBytes; const Key: TKey128;
  const InitializationVector: TIV128): boolean;
begin
  Result := AES128EncryptDecrypt(Source, Key, InitializationVector, True);
end;

function AES128Decrypt(var Source: TBytes; const Key: TKey128;
  const InitializationVector: TIV128): boolean;
begin
  Result := AES128EncryptDecrypt(Source, Key, InitializationVector, False);
end;

const
  DefaultInitializationVector: TIV128 = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);

var
  B: TBytes;
  KeyBytes: TBytes;
  KeyPass: TKey128;
begin
  // padding text with zeroes up to 16 bytes
  B := TEncoding.UTF8.GetBytes('123'#0#0#0#0#0#0#0#0#0#0#0#0#0);

  // encrypting
  KeyBytes := TEncoding.UTF8.GetBytes('test');
  Move(KeyBytes[0], KeyPass[0], Length(KeyBytes));
  AES128Encrypt(B, KeyPass, DefaultInitializationVector);
  Writeln(TNetEncoding.Base64.EncodeBytesToString(B));

  // decrypting
  AES128Decrypt(B, KeyPass, DefaultInitializationVector);
  Writeln(TEncoding.UTF8.GetString(B));
end.

Also f_EVP_aes_128_ecb function is currently not included in OverbyteIcsLibeay, so you'll need to add this line to interface section

f_EVP_aes_128_ecb         : function: PEVP_CIPHER; cdecl = nil;

and these lines to LoadLibeay procedure

f_EVP_aes_128_ecb := GetProcAddress(GLIBEAY_DLL_Handle, 'EVP_aes_128_ecb');
if not Assigned(f_EVP_aes_128_ecb) then
    raise Exception.Create(Msg + 'EVP_aes_128_ecb');
EugeneK
  • 2,164
  • 1
  • 16
  • 21