我正在尝试使用DEC v5.2在Delphi上加密/解密一些代码,并在C#上加密/解密。这个想法是使用AES128。

在Delphi上,我有以下内容:

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;


在C#上,我有:

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);
    }
}


但是生成的代码并不相似。我究竟做错了什么 ?我错过了什么吗?

最佳答案

检查两侧的填充方法。
AES加密本身已经足够标准,但是当明文不是块长度的倍数时,不同的库使用不同的(默认)填充方法。我在C#端使用null填充进行工作,并且a)使用具有手动#0填充的DCPCrypt(DCPCrypt不进行填充),以及使用b)Turbopower LockBox 3,作者Sean Durkin对其代码进行了扩展以处理C#空填充。

旧的D2007测试代码,按“原样”提供:

TPLB3 pas文件==============

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文件===============

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文件==============

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文件==============

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.

10-04 11:31