2
votes

I'm trying to encrypt/decrypt some code on Delphi using DEC v5.2 and crypt/decrypt on C#. The idea is using AES128.

On Delphi I have following:

var
 ACipherClass: TDECCipherClass = TCipher_Rijndael;
 ACipherMode: TCipherMode = cmCBCx;
 ACipherFormat: TDECFormatClass = TFormat_MIME64;
 AHashClass: TDECHashClass = THash_MD5;
 AHashFormat: TDECFormatClass = TFormat_HEX;

function Encrypt(const AText: AnsiString; const APassword: AnsiString): AnsiString;
var
  AData, APass: Binary;
begin
  with ValidCipher(ACipherClass).Create, Context do
    try
      APass := ValidHash(AHashClass).CalcBinary(APassword,AHashFormat);
      Mode := ACipherMode;
      Init(APass);
      AData:=EncodeBinary(AText,ACipherFormat);
      Done;
      Result:=AData;
    finally
      Free;
      ProtectBinary(AData);
      ProtectBinary(APass);
    end;
end;

And on C# I have:

static public string Encrypt(string data, string key)
{
    using (var crypt = new Crypt2())
    {
        crypt.UnlockComponent("LICENSE_IS_HERE");

        crypt.CryptAlgorithm = "aes";
        crypt.CipherMode = "cbc";
        crypt.KeyLength = 128;

        //  Generate a binary secret key from a password string
        //  of any length.  For 128-bit encryption, GenEncodedSecretKey
        //  generates the MD5 hash of the password and returns it
        //  in the encoded form requested.  The 2nd param can be
        //  "hex", "base64", "url", "quoted-printable", etc.
        var hexKey = crypt.GenEncodedSecretKey(key,"hex");
        crypt.SetEncodedKey(hexKey,"hex");

        crypt.EncodingMode = "base64";

        crypt.Charset = "ansi";

        return crypt.EncryptStringENC(data);
    }
}

But the generated codes are not near similar. What am I doing wrong ? Have I missed anything?

3

3 Answers

2
votes

Check the padding method on both sides. The AES encryption itself is standard enough, but different libraries use different (default) padding methods when the plaintext is not a multiple of the blocklength. I got it working with null padding on the C# side and a) using DCPCrypt with manual #0 padding (DCPCrypt doesn't do padding) and with b) Turbopower LockBox 3 where the author Sean Durkin made an extension to it's code to handle the C# null padding.

Old D2007 test code, provided 'as is':

========== TPLB3 pas file ==============

unit uEncDecTests_LockBox;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, uTPLb_BaseNonVisualComponent,
  uTPLb_Codec, uTPLb_CryptographicLibrary;

type
  TFrmEncDecTests = class(TForm)
    EdtPlainText1: TEdit;
    EdtCypher: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    EdtPlainText2: TEdit;
    Label3: TLabel;
    Label4: TLabel;
    BiBEncrypt: TBitBtn;
    BiBDecrypt: TBitBtn;
    Label5: TLabel;
    EdtKey: TEdit;
    Label6: TLabel;
    EdtCypher64: TEdit;
    EdtIV: TEdit;
    Label7: TLabel;
    Label8: TLabel;
    EdtCypherHex: TEdit;
    AESCodec: TCodec;
    CryptographicLibrary1: TCryptographicLibrary;
    BtnInit: TButton;
    procedure BiBEncryptClick(Sender: TObject);
    procedure BiBDecryptClick(Sender: TObject);
    procedure BtnInitClick(Sender: TObject);
  private
    FOut: String;
  public
    { Public declarations }
  end;

var
  FrmEncDecTests: TFrmEncDecTests;

implementation

{$R *.dfm}

procedure TFrmEncDecTests.BiBDecryptClick(Sender: TObject);
var lPlainText: String;
begin
  AESCodec.DecryptString(FOut,lPlainText);
  EdtPlainText2.Text := lPlainText;
end;

procedure TFrmEncDecTests.BiBEncryptClick(Sender: TObject);
var
  lPlainText,
  sb,sh: String;
  b,o  : byte;
begin
  lPlainText := EdtPlaintext1.Text;
  AESCodec.EncryptString(lPlainText,FOut);
  sh := '';
  sb := '';
  for B := 0 to Length(FOut) do begin
    o := Ord(FOut[b]);
    sh := sh + IntToHex(o,2) + ' ';
    if o < 10 then sb := sb + '0';
    if o < 100 then sb := sb + '0';
    sb := sb + inttostr(o) + ' ';
  end;
  EdtCypher.Text := FOut;
  EdtCypher64.Text := sb;
  EdtCypherHex.Text := sh;
end;

procedure TFrmEncDecTests.BtnInitClick(Sender: TObject);
var
  p : PChar;
  MS: TMemoryStream;
begin
  p := pChar(EdtKey.Text);
  MS := TMemoryStream.Create;
  MS.Write(P^,Length(EdtKey.Text));
  MS.Seek(soFromBeginning,0);
  AESCodec.InitFromStream(MS);
  MS.Free;
  BiBEncrypt.Enabled := true;
  BiBDecrypt.Enabled := true;
end;

end.

========== TPLB3 dfm file ==============

object FrmEncDecTests: TFrmEncDecTests
  Left = 0
  Top = 0
  Caption = 'Encryptie/decryptie tests (LockBox)'
  ClientHeight = 328
  ClientWidth = 535
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 16
    Top = 150
    Width = 114
    Height = 13
    Caption = 'Cyphertext (raw bytes)'
  end
  object Label2: TLabel
    Left = 16
    Top = 102
    Width = 46
    Height = 13
    Caption = 'Plaintext:'
  end
  object Label3: TLabel
    Left = 16
    Top = 280
    Width = 46
    Height = 13
    Caption = 'Plaintext:'
  end
  object Label4: TLabel
    Left = 16
    Top = 16
    Width = 22
    Height = 13
    Caption = 'Key:'
  end
  object Label5: TLabel
    Left = 339
    Top = 16
    Width = 182
    Height = 13
    Caption = 'Testing LockBox 3  AES-256, CBC'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'Tahoma'
    Font.Style = [fsBold]
    ParentFont = False
  end
  object Label6: TLabel
    Left = 16
    Top = 189
    Width = 101
    Height = 13
    Caption = 'Cyphertext (Base64)'
  end
  object Label7: TLabel
    Left = 16
    Top = 59
    Width = 14
    Height = 13
    Caption = 'IV:'
  end
  object Label8: TLabel
    Left = 17
    Top = 230
    Width = 85
    Height = 13
    Caption = 'Cyphertext (Hex)'
  end
  object EdtPlainText1: TEdit
    Left = 16
    Top = 118
    Width = 505
    Height = 21
    TabOrder = 0
    Text = 'somethingorother'
  end
  object EdtCypher: TEdit
    Left = 16
    Top = 166
    Width = 505
    Height = 21
    TabOrder = 1
  end
  object EdtPlainText2: TEdit
    Left = 16
    Top = 296
    Width = 505
    Height = 21
    TabOrder = 2
  end
  object BiBEncrypt: TBitBtn
    Left = 368
    Top = 141
    Width = 73
    Height = 23
    Caption = 'Encrypt'
    Enabled = False
    TabOrder = 3
    OnClick = BiBEncryptClick
    Glyph.Data = {
      76010000424D7601000000000000760000002800000020000000100000000100
      04000000000000010000120B0000120B00001000000000000000000000000000
      800000800000008080008000000080008000808000007F7F7F00BFBFBF000000
      FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
      333333333333333333333333333333333333333333333333FFF3333333333333
      00333333333333FF77F3333333333300903333333333FF773733333333330099
      0333333333FF77337F3333333300999903333333FF7733337333333700999990
      3333333777333337F3333333099999903333333373F333373333333330999903
      33333333F7F3337F33333333709999033333333F773FF3733333333709009033
      333333F7737737F3333333709073003333333F77377377F33333370907333733
      33333773773337333333309073333333333337F7733333333333370733333333
      3333377733333333333333333333333333333333333333333333}
    NumGlyphs = 2
  end
  object BiBDecrypt: TBitBtn
    Left = 368
    Top = 270
    Width = 73
    Height = 23
    Caption = 'Decrypt'
    Enabled = False
    TabOrder = 4
    OnClick = BiBDecryptClick
    Glyph.Data = {
      76010000424D7601000000000000760000002800000020000000100000000100
      04000000000000010000120B0000120B00001000000000000000000000000000
      800000800000008080008000000080008000808000007F7F7F00BFBFBF000000
      FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
      33333333333333333333333333333333333333FF333333333333300333333333
      33333773FF33333333333090033333333333373773FF33333333330990033333
      3333337F3773FF33333333099990033333333373F33773FFF333333099999007
      33333337F33337773333333099999903333333373F3333733333333309999033
      333333337F3337F333333333099990733333333373F3F77F3333333330900907
      3333333337F77F77F33333333003709073333333377377F77F33333337333709
      073333333733377F77F33333333333709033333333333377F7F3333333333337
      0733333333333337773333333333333333333333333333333333}
    NumGlyphs = 2
  end
  object EdtKey: TEdit
    Left = 16
    Top = 32
    Width = 265
    Height = 21
    TabOrder = 5
    Text = '12345678912345678912345678912345'
  end
  object EdtCypher64: TEdit
    Left = 16
    Top = 205
    Width = 505
    Height = 21
    TabOrder = 6
  end
  object EdtIV: TEdit
    Left = 16
    Top = 75
    Width = 265
    Height = 21
    TabOrder = 7
    Text = '1234567891234567'
  end
  object EdtCypherHex: TEdit
    Left = 17
    Top = 246
    Width = 505
    Height = 21
    TabOrder = 8
  end
  object BtnInit: TButton
    Left = 336
    Top = 80
    Width = 75
    Height = 25
    Caption = 'Init enc'
    TabOrder = 9
    OnClick = BtnInitClick
  end
  object AESCodec: TCodec
    AsymetricKeySizeInBits = 2048
    AdvancedOptions2 = []
    CryptoLibrary = CryptographicLibrary1
    Left = 336
    Top = 40
    StreamCipherId = 'native.StreamToBlock'
    BlockCipherId = 'native.AES-256'
    ChainId = 'native.CBC'
  end
  object CryptographicLibrary1: TCryptographicLibrary
    Left = 384
    Top = 40
  end
end

========== DCPCrypt pas file ==============

unit uEncDecTests_DCPCrypt;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, LbCipher, LbClass, DCPcrypt2, DCPblockciphers,
  DCPrijndael;

const
  cOutBufSize = 1024;

type
  TFrmEncDecTests = class(TForm)
    EdtPlainText1: TEdit;
    EdtCypher: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    EdtPlainText2: TEdit;
    Label3: TLabel;
    Label4: TLabel;
    BiBEncrypt: TBitBtn;
    BiBDecrypt: TBitBtn;
    Label5: TLabel;
    EdtKey: TEdit;
    Label6: TLabel;
    EdtCypher64: TEdit;
    EdtIV: TEdit;
    Label7: TLabel;
    Label8: TLabel;
    EdtCypherHex: TEdit;
    BtnKAT: TButton;
    DCP_rijndael1: TDCP_rijndael;
    BtnHexConvert: TButton;
    procedure BiBEncryptClick(Sender: TObject);
    procedure BiBDecryptClick(Sender: TObject);
    procedure BtnKATClick(Sender: TObject);
    procedure BtnHexConvertClick(Sender: TObject);
  private
  public
  end;

var
  FrmEncDecTests: TFrmEncDecTests;

implementation

{$R *.dfm}

Uses
  DCPbase64,
  uRijndael,
  uKATVectors, uHexConvert;

procedure TFrmEncDecTests.BiBEncryptClick(Sender: TObject);
type
  KeyBuffer  = Array[1..32] of Byte;
  IVBuffer   = Array[1..16] of Byte;
var
  KeyHex, IVHex, PlainTxt, PlainHex, CypherStr, CypherHex, CypherB64, CypherBytes: String;
  i   : Integer;
begin
  KeyHex      := EdtKey.Text;
  IVHex       := EdtIV.Text;
  PlainTxt    := EdtPlainText1.Text;
  PlainHex    := StringToHex(PlainTxt);
  CypherHex   := RijndaelEncryptHex(KeyHex, IVHex, PlainHex);
  CypherStr   := HexToString(CypherHex);
  CypherB64   := Base64EncodeStr(CypherStr);
  CypherBytes := '';
  CypherBytes := '';  for i := 1 to Length(CypherStr) do CypherBytes := CypherBytes + IntToStr(Ord(CypherStr[i])) + ' ';
  EdtCypherHex.Text := CypherHex;
  EdtCypher.Text    := CypherBytes;
  EdtCypher64.Text  := CypherB64;
end;

procedure TFrmEncDecTests.BiBDecryptClick(Sender: TObject);
var
  KeyHex, IVHex, PlainHex: String;
begin
  KeyHex   := EdtKey.Text;
  IVHex    := EdtIV.Text;
  PlainHex := RijndaelDecryptHex(KeyHex,IVHex,EdtCypherHex.Text);
  EdtPlainText2.Text := HexToString(PlainHex);
end;

procedure TFrmEncDecTests.BtnHexConvertClick(Sender: TObject);
begin
  FrmHexConvert.ShowModal;
end;

procedure TFrmEncDecTests.BtnKATClick(Sender: TObject);
begin
   FrmKATVectors.ShowModal;
end;

end.

========== DCPCrypt dfm file ==============

object FrmEncDecTests: TFrmEncDecTests
  Left = 0
  Top = 0
  Caption = 'Encryptie/decryptie tests (DCPCrypt)'
  ClientHeight = 328
  ClientWidth = 535
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 16
    Top = 150
    Width = 114
    Height = 13
    Caption = 'Cyphertext (raw bytes)'
  end
  object Label2: TLabel
    Left = 16
    Top = 102
    Width = 129
    Height = 13
    Caption = 'Plaintext (readable string):'
  end
  object Label3: TLabel
    Left = 16
    Top = 280
    Width = 46
    Height = 13
    Caption = 'Plaintext:'
  end
  object Label4: TLabel
    Left = 16
    Top = 16
    Width = 78
    Height = 13
    Caption = 'Key (hexstring):'
  end
  object Label5: TLabel
    Left = 301
    Top = 16
    Width = 232
    Height = 13
    Caption = 'Testing DCPCrypt Rijndael (key 256, CBC)'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'Tahoma'
    Font.Style = [fsBold]
    ParentFont = False
  end
  object Label6: TLabel
    Left = 16
    Top = 189
    Width = 101
    Height = 13
    Caption = 'Cyphertext (Base64)'
  end
  object Label7: TLabel
    Left = 16
    Top = 59
    Width = 70
    Height = 13
    Caption = 'IV (hexstring):'
  end
  object Label8: TLabel
    Left = 17
    Top = 230
    Width = 85
    Height = 13
    Caption = 'Cyphertext (Hex)'
  end
  object EdtPlainText1: TEdit
    Left = 16
    Top = 118
    Width = 505
    Height = 21
    TabOrder = 0
    Text = 'timetellbvencryptiemethode'
  end
  object EdtCypher: TEdit
    Left = 16
    Top = 166
    Width = 505
    Height = 21
    TabOrder = 1
  end
  object EdtPlainText2: TEdit
    Left = 16
    Top = 296
    Width = 505
    Height = 21
    TabOrder = 2
  end
  object BiBEncrypt: TBitBtn
    Left = 368
    Top = 141
    Width = 73
    Height = 23
    Caption = 'Encrypt'
    TabOrder = 3
    OnClick = BiBEncryptClick
    Glyph.Data = {
      76010000424D7601000000000000760000002800000020000000100000000100
      04000000000000010000120B0000120B00001000000000000000000000000000
      800000800000008080008000000080008000808000007F7F7F00BFBFBF000000
      FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
      333333333333333333333333333333333333333333333333FFF3333333333333
      00333333333333FF77F3333333333300903333333333FF773733333333330099
      0333333333FF77337F3333333300999903333333FF7733337333333700999990
      3333333777333337F3333333099999903333333373F333373333333330999903
      33333333F7F3337F33333333709999033333333F773FF3733333333709009033
      333333F7737737F3333333709073003333333F77377377F33333370907333733
      33333773773337333333309073333333333337F7733333333333370733333333
      3333377733333333333333333333333333333333333333333333}
    NumGlyphs = 2
  end
  object BiBDecrypt: TBitBtn
    Left = 368
    Top = 270
    Width = 73
    Height = 23
    Caption = 'Decrypt'
    TabOrder = 4
    OnClick = BiBDecryptClick
    Glyph.Data = {
      76010000424D7601000000000000760000002800000020000000100000000100
      04000000000000010000120B0000120B00001000000000000000000000000000
      800000800000008080008000000080008000808000007F7F7F00BFBFBF000000
      FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333333333
      33333333333333333333333333333333333333FF333333333333300333333333
      33333773FF33333333333090033333333333373773FF33333333330990033333
      3333337F3773FF33333333099990033333333373F33773FFF333333099999007
      33333337F33337773333333099999903333333373F3333733333333309999033
      333333337F3337F333333333099990733333333373F3F77F3333333330900907
      3333333337F77F77F33333333003709073333333377377F77F33333337333709
      073333333733377F77F33333333333709033333333333377F7F3333333333337
      0733333333333337773333333333333333333333333333333333}
    NumGlyphs = 2
  end
  object EdtKey: TEdit
    Left = 16
    Top = 32
    Width = 265
    Height = 21
    TabOrder = 5
    Text = ''
  end
  object EdtCypher64: TEdit
    Left = 16
    Top = 205
    Width = 505
    Height = 21
    TabOrder = 6
  end
  object EdtIV: TEdit
    Left = 16
    Top = 75
    Width = 265
    Height = 21
    TabOrder = 7
    Text = ''
  end
  object EdtCypherHex: TEdit
    Left = 17
    Top = 246
    Width = 505
    Height = 21
    TabOrder = 8
  end
  object BtnKAT: TButton
    Left = 301
    Top = 47
    Width = 201
    Height = 25
    Caption = 'Known Answer Test (KAT) Vectors'
    TabOrder = 9
    OnClick = BtnKATClick
  end
  object BtnHexConvert: TButton
    Left = 301
    Top = 80
    Width = 75
    Height = 20
    Caption = 'Hex conversie'
    TabOrder = 10
    OnClick = BtnHexConvertClick
  end
  object DCP_rijndael1: TDCP_rijndael
    Id = 9
    Algorithm = 'Rijndael'
    MaxKeySize = 256
    BlockSize = 128
    Left = 432
    Top = 80
  end
end

========== uRijndael.pas ==============

unit uRijndael;
// Helper functions for 256-bit Rijndael/AES encryption with DCPcrypt

interface

Uses
  StdCtrls;

function RijndaelEncryptHex(hexstrKey,hexstrIV,hexstrPlain: String; MMo: TMemo = nil): String;
function RijndaelDecryptHex(hexstrKey,hexstrIV,hexstrCypher: String; MMo: TMemo = nil): String;
// Input en output zijn strings met hex waarden ('014730f80ac625fe84f026c60bfd547d')
//
// Deze routines gebruiken een 256-key AES/Rijndael encryptie, waarbij de plaintext
// met NULL waarden ge-pad wordt tot een veelvoud van de blocksize.
// Merk op dat de initializatievector even groot moet zijn als de blocksize (128 bits, dus een hex string van 32 tekens).
//
// Als TMemo gespecificeerd is wordt daar naar toe gelogd.

// Helper routines:
function HexToString(H: String): String;
function StringtoHex(Data: string; WithSpaces: Boolean = false): string;
function HexToInt(HexNum: string): LongInt;

implementation

Uses
  SysUtils,
  DCPbase64, DCPcrypt2, DCPblockciphers, DCPrijndael;

type
  KeyBuffer  = Array[1..32] of Byte;
  IVBuffer   = Array[1..16] of Byte;

function HexToString(H: String): String;
var I : Integer;
begin
  Result:= '';
  for I := 1 to length (H) div 2 do
    Result:= Result+Char(StrToInt('$'+Copy(H,(I-1)*2+1,2)));
end;

function StringtoHex(Data: string; WithSpaces: Boolean = false): string;
var
  i, i2: Integer;
  s: string;
begin
  i2 := 1;
  for i := 1 to Length(Data) do
  begin
    Inc(i2);
    if i2 = 2 then
    begin
      if WithSpaces then s  := s + ' ';
      i2 := 1;
    end;
    s := s + IntToHex(Ord(Data[i]), 2);
  end;
  Result := s;
end;

function HexToInt(HexNum: string): LongInt;
begin
   Result := StrToInt('$' + HexNum) ;
end;

function FilterHex(S: String): String;
// Filters all hex characters 0..F (case insensitive) uit S
var
   SOut: String;
   l   : Word;
begin
   SOut := '';
   for l := 1 to Length(S) do
      if not (S[l] in ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','A','B','C','D','E','F']) then
         SOut := SOut + S[l];
   Result := SOut;
end;

function RijndaelEncryptHex(hexstrKey,hexstrIV,hexstrPlain: String; MMo: TMemo = nil): String;
var
  InBuf,OutBuf  : array of byte;
  BufSizeInBytes: Word;
  KeyBuf        : KeyBuffer;
  IVBuf         : IVBuffer;
  l,i           : Integer;
  Bytes,SOut    : String;
  DCPR          : TDCP_rijndael;
begin
  l := Length(HexStrKey);
  Assert(l=64,'Key heeft ongeldige lengte (moet 64 chars zijn): ' + IntToStr(l));
  Assert(FilterHex(HexStrKey) = '','Key heeft ongeldige tekens: ' + HexStrKey);
  l := Length(HexStrIV);
  Assert(l=32,'IV heeft ongeldige lengte (moet 32 chars zijn): ' + IntToStr(l));
  Assert(FilterHex(HexStrIV) = '','IV heeft ongeldige tekens: ' + HexStrIV);
  Assert(FilterHex(hexstrPlain) = '','Plaintext heeft ongeldige tekens: ' + hexstrPlain);
  l := Length(hexstrPlain);
  Assert(l MOD 2 = 0,'Plaintext heeft oneven lengte: ' + hexstrPlain);
  if Mmo<> nil then begin
    Mmo.Lines.Add('Key: ' + hexstrKey);
    Mmo.Lines.Add('IV: ' + hexstrIV);
    Mmo.Lines.Add('Plaintext: ' + hexstrPlain);
    end;
  l := Length(hexstrKey) DIV 2;
  for i := 1 to l do KeyBuf[i] := HexToInt(Copy(hexstrKey,2*(i-1)+1,2));
  l := Length(hexstrIV) DIV 2;
  for i := 1 to l do IVBuf[i] := HexToInt(Copy(hexstrIV,2*(i-1)+1,2));
  // Pad with zeroes:
  while Length(hexstrPlain) MOD 32 <> 0 do hexstrPlain := hexstrPlain + '00';
  BufSizeInBytes := Length(hexstrPlain) DIV 2;
  SetLength(InBuf,BufSizeInBytes);
  SetLength(OutBuf,BufSizeInBytes);
  for i := 0 to BufSizeInBytes-1 do InBuf[i] := HexToInt(Copy(hexstrPlain,2*i+1,2));
  DCPR := TDCP_rijndael.Create(nil);
  DCPR.Init(KeyBuf,256,@IVBuf);
  DCPR.EncryptCBC(InBuf[0],OutBuf[0],BufSizeInBytes);
  DCPR.Burn; // Leeg memory buffers voor security
  DCPR.Free;
  SOut := '';
  for i := 0 to BufSizeInBytes-1 do begin SOut := SOut + Chr(OutBuf[i]); Bytes := Bytes + IntToStr(OutBuf[i]) + ' '; end;
  if Mmo<> nil then begin
    Mmo.Lines.Add('Cyphertext (bytes): ' + Bytes);
    Mmo.Lines.Add('Cyphertext (base64): ' + Base64EncodeStr(SOut));
    end;
  SOut := LowerCase(StringToHex(SOut));
  if Mmo<> nil then begin
    Mmo.Lines.Add('Cyphertext (hex): ' + SOut);
    Mmo.Lines.Add('');
    end;
  Result := SOut;
end; { RijndaelEncryptHex }


function RijndaelDecryptHex(hexstrKey,hexstrIV,hexstrCypher: String; MMo: TMemo = nil): String;
var
  InBuf,
  OutBuf: array of byte;
  BufSizeInBytes : Word;
  KeyBuf: KeyBuffer;
  IVBuf : IVBuffer;
  l,i   : Integer;
  SOut  : String;
  DCPR  : TDCP_rijndael;
begin
  l := Length(HexStrKey);
  Assert(l=64,'Key heeft ongeldige lengte (moet 64 chars zijn): ' + IntToStr(l));
  Assert(FilterHex(HexStrKey) = '','Key heeft ongeldige tekens: ' + HexStrKey);
  l := Length(HexStrIV);
  Assert(l=32,'IV heeft ongeldige lengte (moet 32 chars zijn): ' + IntToStr(l));
  Assert(FilterHex(HexStrIV) = '','IV heeft ongeldige tekens: ' + HexStrIV);
  Assert(FilterHex(hexstrCypher) = '','Cyphertext heeft ongeldige tekens: ' + hexstrCypher);
  l := Length(hexstrCypher);
  Assert(l MOD 2 = 0,'Cyphertext heeft oneven lengte: ' + hexstrCypher);
  if Mmo<> nil then begin
    Mmo.Lines.Add('Key: ' + hexstrKey);
    Mmo.Lines.Add('IV: ' + hexstrIV);
    Mmo.Lines.Add('CypherText: ' + hexstrCypher);
    end;
  l := Length(hexstrKey) DIV 2;
  for i := 1 to l do KeyBuf[i] := HexToInt(Copy(hexstrKey,2*(i-1)+1,2));
  l := Length(hexstrIV) DIV 2;
  for i := 1 to l do IVBuf[i] := HexToInt(Copy(hexstrIV,2*(i-1)+1,2));
  // Pad with zeroes:
  BufSizeInBytes := Length(hexstrCypher) DIV 2;
  SetLength(InBuf,BufSizeInBytes);
  SetLength(OutBuf,BufSizeInBytes);
  for i := 0 to BufSizeInBytes-1 do InBuf[i] := HexToInt(Copy(hexstrCypher,2*i+1,2));
  DCPR := TDCP_rijndael.Create(nil);
  DCPR.Init(KeyBuf,256,@IVBuf);
  DCPR.DecryptCBC(InBuf[0],OutBuf[0],BufSizeInBytes);
  DCPR.Burn;
  DCPR.Free;
  SOut := '';
  for i := 0 to BufSizeInBytes-1 do SOut := SOut + Chr(OutBuf[i]);
  SOut := LowerCase(StringToHex(SOut));
  if Mmo<> nil then begin
    Mmo.Lines.Add('Plaintext (hex): ' + SOut);
    Mmo.Lines.Add('');
  end;
  Result := SOut;
end; { RijndaelDecryptHex }

end.
0
votes

1) try other AES128 implementations for both Delphi and C#. For example LockBox 3 for Delphi. Find smth else for dot-net also. That would let you check if some of libraries are broken in your environment.

2) if all libraries for Delphi would be consistent between them, and all libs for C# would be consistent between them, but those clusters having different results, then you know that you have different BINARY data for that very strings.

Different Delphi versions had different string representations, without specifying Delphi version (there are tags for Delphi specific version on SO) and showing vars' type declarations you can hardly show binary data behind strings.

Java used UCS-2 in early versions for string and now it uses UTF-16.

Don't know about dot-net.

But - you have to do mind experiment and track the strings down to raw array of bytes. And then make sure that those arrays are matchign exactly. That would either take you to learn about strings implementations or to always convert strings to bytes and back in your custom bridge routines, that you would always had under your full control.

And - afterall - you'd better have extensive unit testing on that. So that if after any later change in the library, language or compiler settings would affect the cypering - you would know it instantly. Month ago i made Win64 asm optimizations for Spring4D hash functions without knowing a bit about crypto - just thanks to those unit tests :-)

0
votes

there are many parameters in encryption such as:

key length, encoding mode, oaep, charset and many more So it is rational to use one component in both sides chilkat is much more complete than others. so if it possible for you use it on both sides.