2012-07-30 72 views
2

我想加密/解密使用DEC V5.2和隱窩Delphi的一些代碼/解密在C#。這個想法是使用AES128。德爾福加密綱要5.2 VS奇爾卡特加密

德爾福我有以下幾點:

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

但是生成的代碼是不近相同。我究竟做錯了什麼 ?我錯過了什麼?

回答

0

1)嘗試兩種Delphi和C#等AES128實現。例如Delphi的LockBox 3。也可以找到其他的網點。這可以讓你檢查一些庫是否在你的環境中被破壞。 2)如果德爾福的所有庫在它們之間保持一致,並且C#的所有庫在它們之間將是一致的,但是那些結果不同的集羣,那麼你知道對於那些字符串你有不同的BINARY數據。

不同版本的Delphi有不同的字符串表示,不指定德爾福版本(有德爾福特定的版本標籤上SO)和顯示瓦爾類型聲明,你也很難顯示背後的字符串二進制數據。

Java中使用UCS-2在早期版本字符串,現在它採用UTF-16。

不知道點網。

但是 - 你必須做的頭腦實驗和跟蹤串到原始字節數組。然後確保這些數組完全匹配。 這會讓你學習字符串的實現,或者總是將字符串轉換爲字節,並返回到自定義的橋接例程中,這將永遠在你的完全控制之下。

而且 - 畢竟 - 你最好有對廣泛的單元測試。因此,如果在庫的任何稍後更改之後,語言或編譯器設置都會影響cypering - 您會立即知道它。一個月前,我對Spring4D哈希函數進行了Win64 asm優化,而不知道一些關於加密的內容 - 僅僅感謝那些單元測試:-)

2

檢查兩邊的填充方法。 AES加密本身足夠標準,但是當明文不是塊長度的倍數時,不同的庫使用不同的(默認)填充方法。我在C#端使用了null填充和a)使用帶有手動#0填充(DCPCrypt不做填充)的DCPCrypt和b)Turbopower LockBox 3,其中作者Sean Durkin對其代碼進行了擴展,以處理C#null填充。

舊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.