#1 2017-12-12 16:52:50

ertank
Member
Registered: 2016-03-16
Posts: 163

Decrypt results differ for Win32 and Win64 (Delphi 10.2)

Hello,

I am using Delphi 10.2, mORMot commit version 1.18.3599

I do not know if this is something known.

I have switched my target platform to 64bit Windows for one of my applications. There is no code change at all. That 64bit application could not decrypt information crypt with Win32 executable using same mORMot version. Everything is normal if I switch back to Win32 platform.

My code for decrypt is as follows:

function DecryptItAES(const s: string; const AKey: string): string;
var
  Key: TSHA256Digest;
  Aes: TAESCFB;
  _s: RawByteString;
begin
  Result := EmptyStr;
  SynCommons.HexToBin(Pointer(SHA256(StringToUTF8(AKey))), @Key, 32);

  Aes := TAESCFB.Create(Key, 256);
  try
    _s     := StringToUTF8(s);
    _s     := Aes.DecryptPKCS7(Base64ToBin(_s), True);
    Result := UTF8ToString(_s);
  finally
    Aes.Free();
  end;
end;

There is no exception raising at all. It is simply decrypt content is not that it should be.

I appreciate any help.

Thanks & regards,
Ertan

Last edited by ertank (2017-12-12 16:53:59)

Offline

#2 2017-12-12 17:20:55

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: Decrypt results differ for Win32 and Win64 (Delphi 10.2)

Did you try with the latest mORMot revision (current is 1.18.4074)?

BTW the following code line does not make much sense:

SynCommons.HexToBin(Pointer(SHA256(StringToUTF8(AKey))), @Key, 32);

You may use

Key := SHA256Digest(StringToUTF8(AKey));

directly.

Offline

#3 2017-12-12 18:57:31

ertank
Member
Registered: 2016-03-16
Posts: 163

Re: Decrypt results differ for Win32 and Win64 (Delphi 10.2)

Just tried with 1.18.4071 revision.

That revision raise an exception saying "TAESCFB.DecryptPKCS7: Invalid Input" when Win64 executable.
Using same revision and Win32 executable everything works fine.

Offline

#4 2017-12-16 09:37:26

ertank
Member
Registered: 2016-03-16
Posts: 163

Re: Decrypt results differ for Win32 and Win64 (Delphi 10.2)

I tested with Revision 1.18.4080. Same problem continues. Working fine with 32Bit executable. Different decrypt result for 64bit executable using same code and inputs. Please check if you can reproduce using below information.

Delphi version: Embarcadero® RAD Studio 10.2 Version 25.0.26309.314
Decrypt text should be small letter "a"

const
    KeyPC :   Array of Char =  [#00,  #101, #02,  #03,  #40,  #05,  #106, #07,
                                #08,  #09,  #07,  #100, #110, #201, #117, #45,
                                #10,  #11,  #12,  #13,  #140, #150, #160, #170,
                                #13,  #1,   #17,  #130, #40,  #16,  #106, #70,
                                #180, #190, #174, #200, #0,   #1,   #11,  #15,
                                #80,  #91,  #72,  #130, #101, #111, #107, #45];

implementation

uses
  SynCommons,
  SynCrypto;

function DecryptItAES(const s, AKey: string; out Value: string): Boolean;
var
  Key: TSHA256Digest;
  Aes: TAESCFB;
  Utf8String: RawByteString;
begin
  if s = EmptyStr then Exit(False);

  //SynCommons.HexToBin(Pointer(SHA256(StringToUTF8(aKey))), @key, 32);
  Key := SHA256Digest(StringToUTF8(AKey));

  Aes := TAESCFB.Create(Key, 256);
  try
    Utf8String := StringToUTF8(s);

    try
      Utf8String := Aes.DecryptPKCS7(Base64ToBin(Utf8String), True);
    except
      on E: Exception do
      begin
        ShowMessage(E.Message);
        Value  := EmptyStr;
        Exit(False);
      end;
    end;

    Value := UTF8ToString(Utf8String);
  finally
    Aes.Free();
  end;

  Result := True;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  DecryptItAES('oWN2TRhEkb4sJ8IrfqQSm+9qhW5u+xty7qbigw9yk4A=', string(KeyPC), PlainText);
  Memo1.Lines.Add('Plain: ' + QuotedStr(PlainText));
end;

BTW, I cannot debug 64bit applications. Couldn't find what problem is with debugging 64bit executable. Execution do not stop at break points even I have compiler and linker debugging information set on.

However, when I try to display exception on the screen I see that there is indeed an exception raised and it is saying:

TAESCFB.DecryptPKCS7: Invalid Input

No such exception in 32bit executable and result is displayed just fine.

Last edited by ertank (2017-12-16 09:38:29)

Offline

#5 2017-12-16 15:16:01

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: Decrypt results differ for Win32 and Win64 (Delphi 10.2)

Are you using the 10.2 with the update 1?
There was a big bug in the Delphi compiler, for plain 10.2, with x64.
See http://blog.synopse.info/post/2017/03/2 … C64-broken

Anyway, I have included tests vectors to the regression unit, so that we may identify any problem for a specific platform.
I found not problem with Delphi 5, Delphi 6, Delphi 7, Delphi 2007, Delphi XE4 32, Delphi XE6 32/64, Delphi XE7 32/64, FPC Win32/Win64/LinuxX86/LinuxX64.
But I don't have Delphi 10.2 at hand (no licence any more, since I changed my daily job to switch into a FPC-powered startup).
See https://synopse.info/fossil/info/004fedca24

So I'm afraid there may be something wrong in your test code.

Offline

#6 2017-12-16 20:11:04

ertank
Member
Registered: 2016-03-16
Posts: 163

Re: Decrypt results differ for Win32 and Win64 (Delphi 10.2)

I am using plain Delphi 10.2 with April hotfix applied.

Thanks for additional regression tests.

I am not sure it is the test code having something wrong. I am not changing any code but target platform. Win32 it works and Win64 it does not.
I will wait for a while with the hope that someone in the forum who has Delphi 10.2 (plain or update 1, 2) to test above code example just to be sure.
Both update 1 and update 2 has their own issues and I simply do not want to install neither at the moment.

I might prepare a virtual machine to test with update 1 or update 2 if I can find the time to test the code.

Offline

#7 2017-12-17 11:28:19

ertank
Member
Registered: 2016-03-16
Posts: 163

Re: Decrypt results differ for Win32 and Win64 (Delphi 10.2)

I just tested same code on Delphi 10.2.2
I got exception on 64bit executable where I have correct result on 32bit executable.
I also got exception encrypt text on 64bit system and trying to decrypt it in 32bit system.

If I encrypt using 64bit executable, it can decrypt that information on 64bit system.
If I encrypt using 32bit executable, it can decrypt that information on 32bit system.

It seems encrypt information is not 32bit <-> 64bit exchangeable. At least on Windows platforms.

Encryption code I used is:

function EncryptItAES(const s, aKey: string; out Value: string): Boolean;
var
  Key: TSHA256Digest;
  Aes: TAESCFB;
  Utf8String: RawByteString;
begin
  if s = EmptyStr then Exit(False);

  //SynCommons.HexToBin(Pointer(SHA256(StringToUTF8(aKey))), @key, 32);
  Key := SHA256Digest(StringToUTF8(AKey));

  Aes := TAESCFB.Create(key, 256);
  try
    Utf8String := StringToUTF8(s);
    try
      Utf8String := BinToBase64(Aes.EncryptPKCS7(Utf8String, True));
    except
      Exit(False);
    end;
    Value := UTF8ToString(Utf8String);
  finally
    Aes.Free();
  end;

  Result := True;
end;

Last edited by ertank (2017-12-17 11:29:00)

Offline

#8 2017-12-17 13:18:30

zed
Member
From: Belarus
Registered: 2015-02-26
Posts: 105

Re: Decrypt results differ for Win32 and Win64 (Delphi 10.2)

ertank
Bug in this expression in your code: string(KeyPC)

To get Key as a string, use this code:

function GetKey: string;
const
  KeyPC: array of Char = [
    #00,  #101, #02,  #03,  #40,  #05,  #106, #07,
    #08,  #09,  #07,  #100, #110, #201, #117, #45,
    #10,  #11,  #12,  #13,  #140, #150, #160, #170,
    #13,  #1,   #17,  #130, #40,  #16,  #106, #70,
    #180, #190, #174, #200, #0,   #1,   #11,  #15,
    #80,  #91,  #72,  #130, #101, #111, #107, #45
  ];
var
  I: Integer;
begin
  SetLength(Result, Length(KeyPC));
  for I := 0 to Length(KeyPC) - 1 do begin
    Result[I+1] := KeyPC[I];
  end;
end;

Offline

#9 2017-12-17 14:46:27

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: Decrypt results differ for Win32 and Win64 (Delphi 10.2)

Or just

SetString(KeyStr, @KeyPC, SizeOf(KeyPC));

But it is obvious that how the key is constructed in the code is somewhat confusing and wrong.
Using "array of char" with 8-bit values sounds plain wrong.
Use "array of bytes", or bintobase64/bintohex, and THash128 or THash256 for key storage.

Offline

#10 2017-12-17 19:17:08

ertank
Member
Registered: 2016-03-16
Posts: 163

Re: Decrypt results differ for Win32 and Win64 (Delphi 10.2)

Yes, it is my mistake. Sorry for all the fuss.

Below is the current code which is working in both 32bit and 64bit platforms. Encrypt text in one platform can be decrypt in another platform just fine.

unit Unit1;

interface

uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Variants,
  System.Classes,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    Edit1: TEdit;
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

const
    KeyPC :   Array of Byte =  [00,  101, 02,  03,  40,  05,  106, 07,
                                08,  09,  07,  100, 110, 201, 117, 45,
                                10,  11,  12,  13,  140, 150, 160, 170,
                                13,  1,   17,  130, 40,  16,  106, 70,
                                180, 190, 174, 200, 0,   1,   11,  15,
                                80,  91,  72,  130, 101, 111, 107, 45];
var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  SynCommons,
  SynCrypto;


function DecryptItAES(const s: string; AKey: Array of Byte; out Value: string): Boolean;
var
  Key: TSHA256Digest;
  Aes: TAESCFB;
  Utf8Str: RawByteString;
begin
  if s = EmptyStr then Exit(False);

  Key := SHA256Digest(Pointer(@AKey), SizeOf(AKey));

  Aes := TAESCFB.Create(Key, 256);
  try
    Utf8Str := StringToUTF8(s);

    try
      Utf8Str := Aes.DecryptPKCS7(Base64ToBin(Utf8Str), True);
    except
      Value  := EmptyStr;
      Exit(False);
    end;

    Value := UTF8ToString(Utf8Str);
  finally
    Aes.Free();
  end;

  Result := True;
end;

function EncryptItAES(const s: string; aKey: Array of Byte; out Value: string): Boolean;
var
  Key: TSHA256Digest;
  Aes: TAESCFB;
  Utf8Str: RawByteString;
begin
  if s = EmptyStr then Exit(False);

  Key := SHA256Digest(Pointer(@AKey), SizeOf(AKey));

  Aes := TAESCFB.Create(Key, 256);
  try
    Utf8Str := StringToUTF8(s);
    try
      Utf8Str := BinToBase64(Aes.EncryptPKCS7(Utf8Str, True));
    except
      Exit(False);
    end;
    Value := UTF8ToString(Utf8Str);
  finally
    Aes.Free();
  end;

  Result := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  TempString: string;
begin
  EncryptItAES(Edit1.Text, KeyPC, TempString);
  Memo1.Lines.Add(EmptyStr);
  Memo1.Lines.Add(TempString);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  TempString: string;
begin
  TempString := EmptyStr;
  DecryptItAES(Edit1.Text, KeyPC, TempString);
  Memo1.Lines.Add('Plain: ' + QuotedStr(TempString));
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Memo1.Lines.Clear();
end;

end.

@zed appreciate you pointing me my bug.
@ab appreciate you correct my basic definition type for KeyPC

That is a good lesson learned for me as I now need to update quite some applications running in different locations.

Regards,
Ertan

Offline

#11 2017-12-17 22:04:27

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: Decrypt results differ for Win32 and Win64 (Delphi 10.2)

Your code is somewhat wrong: SizeOf(AKey) returns the pointer size, not the array size...

Offline

#12 2017-12-18 05:53:09

ertank
Member
Registered: 2016-03-16
Posts: 163

Re: Decrypt results differ for Win32 and Win64 (Delphi 10.2)

I actually checked it and it returns 48 and not the size of the pointer. That is same for 32bit and 64bit.

My usage is very similar to below code:

const
  Test: Array of Byte = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

procedure TestMe(const Key: array of Byte);
begin
  ShowMessage('TestMe: ' + IntToStr(SizeOf(Key)));  // Here you get 10
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ShowMessage(IntToStr(SizeOf(Test)));  // Here you get 4
  TestMe(Test);
end;

Last edited by ertank (2017-12-18 06:15:48)

Offline

#13 2017-12-18 10:06:26

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: Decrypt results differ for Win32 and Win64 (Delphi 10.2)

This is something new in pascal then...

When Embarcadero implemented dynamic arrays initialization, they broke the previous behavior, existing since the introduction of dynamic arrays, in 1998:

var
  Test: Array of Byte;
begin
  writeln(SizeOf(Test));  // Here you get 4 (pointer size) since Delphi 4

IMHO that sizeof(Test) returns the length of a dynamic array, and not the pointer size of the dynamic array variable, is a bug of the current Delphi compiler.
Embarcadero seems to like breaking backward compatibility.

Anyway, using "array of byte" for a constant array is IMHO just confusing, slower, and not convenient.
The propery way is to write:

const
  Test: array[0..9] of byte = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

Then use sizeof(Test).
This is safe, efficient, and clean.
The fact that you need to specify the array length is a feature: you are sure that your constant array has the specified number of items, not more, not less.

Offline

#14 2017-12-18 15:18:30

hnb
Member
Registered: 2015-06-15
Posts: 291

Re: Decrypt results differ for Win32 and Win64 (Delphi 10.2)

@ab seems that open array behave in different way than dynamic array

procedure TestMe(const Key: TArray<Byte>);

works as expected.


best regards,
Maciej Izak

Offline

Board footer

Powered by FluxBB