0

I'm converting a Delphi XE5 app to Delphi 11.1 and having issues getting the same encrypted strings using the same version of Lockbox on each.

EncryptSymStr() calls TCodec.EncryptString(), which calls TSimpleCodec.EncryptString(), which then calls Stream_to_Base64(). Up to the call to Stream_to_Base64(), everything looks the same in debug.

The first difference I see is in Stream_to_Base64() for the variable ThreeBytes.

In XE5, I see:

ThreeBytes [0] = 253
           [1] = 206
           [2] = 0

In Delphi 11, I see:

ThreeBytes [0] = 105
           [1] = 155
           [2] = 1

Since I am using the same version of Lockbox in both environments, I assume there is some difference in the data types from XE5 to 11.

var
oCodeRDL:   TCodec;

cmdstr := '...---... ETS4162735 BUBBA '; 
cmdStr := EncryptSymStr(cmdStr);

function EncryptSymStr(Value: string): string;
var
   CipherText: ansistring;
begin
   if AllowEncryption then
   begin
      oCodeRDL.EncryptString(Value, CipherText);
      Result := CipherText;
   end
   else
      Result := Value;      
end;

procedure TCodec.EncryptString(
  const Plaintext: string; var CipherText_Base64: ansistring);
begin
InterfacesAreCached := True;
BeginEncDec;
FCodec.EncryptString( Plaintext, CipherText_Base64);
EndEncDec
end;

procedure TSimpleCodec.EncryptString(
  const Plaintext: string;
  var CipherText_Base64: ansistring);
var
  Temp: TMemoryStream;
  L: integer;
begin
Temp := TMemoryStream.Create;
try
  Begin_EncryptMemory( Temp);
  L := Length( Plaintext) * SizeOf( Char);
  if L > 0 then
    EncryptMemory( Plaintext[1], L);
  End_EncryptMemory;
  if FisUserAborted then
      CipherText_Base64 := ''
    else
      begin
      Temp.Position := 0;
      if isNotBase64Converter then
          CipherText_Base64 := Stream_to_Base64( Temp)
        else
          // If its already a Base64 encoder, no point in double-encoding it as base64.
          CipherText_Base64 := Stream_to_AnsiString( Temp)
      end
finally
  Temp.Free
end end;

  function  Stream_to_Base64( Source: TStream): ansistring;
var
  ThreeBytes: packed array[ 0..2 ] of byte;
  BytesRead: integer;
  P, j, i: integer;

begin
SetLength( result, (Source.Size + 2) div 3 * 4);
Source.Position := 0;
P := 1;
repeat
  BytesRead := Source.Read( ThreeBytes, 3);
  if BytesRead = 0 then break;
  for j := BytesRead to 2 do
    ThreeBytes[j] := 0;
  for j := 0 to BytesRead do
    begin
    result[ P ] := Base64Chars[ ( ThreeBytes[0] shr 2) + 1];
    Inc( P);
    for i := 0 to 1 do
      ThreeBytes[i] := (ThreeBytes[i] shl 6) + (ThreeBytes[i+1] shr 2);
    ThreeBytes[ 2] := ThreeBytes[ 2] shl 6
    end
until BytesRead < 3;
if BytesRead > 0 then
  for j := BytesRead to 2 do
    begin
    result[ P] := '=';
    Inc( P)
    end
end;
  • You didn't provide the full code of `Stream_To_Base64()`, particularly the part that actually populates `ThreeBytes`. I'm assuming it calls `Source.Read(Buffer|Data)`, is that right? There are multiple overloads available, so maybe 11.1 is calling a different overload than XE5 did? Also, did you inspect the contents of the `TMemoryStream` itself to make sure the encrypted bytes are even the same in both versions? Perhaps there is a problem in `EncryptMemory()` rather than in `Stream_To_Base64()`? – Remy Lebeau Oct 06 '22 at 15:47
  • @RemyLebeau, updated to show full Stream_To_Base64. Will inspect TMemoryStream and report back. – David Kroll Oct 06 '22 at 16:54
  • @RemyLebeau - after End_EncryptMemory - Delphi 11 Temp TMemoryStream = ($1C7B9050, 64, 64, 8192) - XE5 - ($103D9600, 64, 64, 8192) – David Kroll Oct 06 '22 at 16:59
  • `$1C7B9050` and `$103D9600` are just pointers to the actual byte arrays. Did you compare the actual bytes themselves to make sure both versions are producing the same encrypted result? A properly implemented encryption should always produce the same bytes if the same input and same salt are being used. – Remy Lebeau Oct 06 '22 at 17:26
  • @RemyLebeau Same input and salt are being used, it's the same code for my application and Lockbox being used in both Delphi versions. What else should I be comparing? – David Kroll Oct 06 '22 at 17:31
  • I already told you what to compare. The actual bytes in the `TMemoryStream`'s internal byte array (which is accessible via the `TMemoryStream.Memory` property). We can see in your earlier comment that 64 bytes are being written to the stream in both versions. Do those 64 bytes match in both versions? If they do, then the problem is in `Stream_to_Base64()`. If they do not, then the problem is in `(Begin_|End_)EncryptMemory()` instead. – Remy Lebeau Oct 06 '22 at 17:36
  • @RemyLebeau sorry, haven't done much in this area. After EncryptMemory, I saved TMemorystream to file. D11 = ;C7-œ*„+2š,»€“uÇr2ˆ@¿¢ÉAŽþ 9(Í‹œØ¡îÄÃÀ\Y9: XE5 = %âÉ»BŒi²gö§?þVÜHfj6@æHL7N²”Ÿž‹nöþY}n4U÷£Y}¥ In D11, I used the Memory Analyzer to look at TMemoryStream and the Hex shows that value above. I didn't see a way to look at the Hex in XE5. – David Kroll Oct 06 '22 at 18:11
  • Well, as you can see, the two outputs are different. So the problem is not in the `String_To_Base64` code, it has to be in the `EncryptMemory` code. So focus your debugging efforts there instead. And you should contact the LockBox author for help. – Remy Lebeau Oct 06 '22 at 19:56
  • @rohit I think this comment is plain wrong. Are you confusing XE5 with 5. XE5 was a Unicode Delphi. Very hard to see how AnsiString could be useful here. – David Heffernan Oct 07 '22 at 06:02
  • @DavidHeffernan Quite right, I was totally confused. What had changed in 11 was the default winapi mapping, changing the string type . – Rohit Gupta Oct 07 '22 at 07:46
  • @RohitGupta no, I don't believe that is true – David Heffernan Oct 07 '22 at 10:21

0 Answers0