Using DEC (Delphi Encryption Compendium Version 5.2) in Delphi XE2, I encrypt a string with the following code below.
However, AFTER EACH PROGRAM START the same sequence of encryption results are generated. I have tried to use Randomize in FormCreate, but it does not help.
uses
DECUtil, DECCipher, DECHash, DECFmt;
const
MyPW = 'MyPassword';
var
AKDFIndex: LongWord = 1;
function MyEncryptEx(const AText: string;
const APassword: string;
ATextFormat: TDECFormatClass;
AHashClass: TDECHashClass;
ACipherMode: TCipherMode;
ACipherClass: TDECCipherClass): string;
var
ASalt: Binary;
AData: Binary;
APass: Binary;
begin
with ValidCipher(ACipherClass).Create, Context do
try
ASalt := RandomBinary(16);
APass := ValidHash(AHashClass).KDFx(APassword[1], length(APassword) * SizeOf(APassword[1]),
ASalt[1], length(ASalt), KeySize, TFormat_Copy, AKDFIndex);
Mode := ACipherMode;
Init(APass);
SetLength(AData, length(AText) * SizeOf(AText[1]));
Encode(AText[1], AData[1], length(AData));
Result := ValidFormat(ATextFormat).Encode(ASalt + AData + CalcMAC);
finally
Free;
ProtectBinary(ASalt);
ProtectBinary(AData);
ProtectBinary(APass);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Randomize;
end;
procedure TForm1.btnTestClick(Sender: TObject);
var
EncrText: string;
begin
EncrText := MyEncryptEx(edtHWID.Text, MyPW, TFormat_ESCAPE, THash_Whirlpool, cmCBCx, TCipher_Rijndael);
end;
It seems that some Randomizer is not initialized after program start.
So how can I get different encryption results after each program start?
I found some source code. Looks like DECUtil's RandomBinary uses its own seed. You could try calling RandomSeed(RandomSystemTime, 4) instead of Randomize.
Related
I have the following code written in delphi.
with TIdHashMessageDigest5.Create do begin
st2.Position := 0;
Digest := HashValue( st2 );
SetLength( Hash, 16 );
Move( Digest, Hash[1], 16);
Free;
end;
I need to convert that to use SHA1 hash. I couldn't find SHA1 type in the library. Can anyone help? I have looked for help on the internet but couldn't find any.
See here:
https://sergworks.wordpress.com/2014/10/25/high-performance-hash-library/
SHA1 hashing in Delphi XE
https://sourceforge.net/projects/sha1implementat/
http://www.colorfultyping.com/generating-a-sha-1-checksum-for-a-given-class-type/
BTW, you didn't mention your Delphi version. If you are using a modern version (XE onwards), I suppose that its standard libraries should support SHA-1, MD5, etc.
You could do it like this:
uses IdHashSHA;
function SHA1FromString(const AString: string): string;
var
SHA1: TIdHashSHA1;
begin
SHA1 := TIdHashSHA1.Create;
try
Result := SHA1.HashStringAsHex(AString);
finally
SHA1.Free;
end;
end;
Just in case, in latest Delphi versions You can try:
uses
System.Hash;
...
function getHashCode(const s : string) : string;
begin
Result := THashSHA1.GetHashString(s);
end;
You appear to be using Indy 9, which does not support SHA1. SHA1 (and a few other hashes, including several other SHAs) was added in Indy 10. The interface for TIdHash was also re-written in Indy 10. Amongst other changes, the HashValue() method was replaced with new Hash...() and Hash...AsHex() methods (HashString(AsHex), HashStream(AsHex), HashBytes(AsHex)), eg:
uses
..., IdHash, IdHashMessageDigest;
var
Hash: TIdBytes;
begin
with TIdHashMessageDigest5.Create do
try
st2.Position := 0;
Hash := HashStream( st2 );
finally
Free;
end;
// use Hash as needed...
end;
uses
..., IdHash, IdHashSHA;
var
Hash: TIdBytes;
begin
with TIdHashSHA1.Create do
try
st2.Position := 0;
Hash := HashStream( st2 );
finally
Free;
end;
// use Hash as needed...
end;
Two more options:
http://www.spring4d.org
unit Spring.Cryptography.SHA;
TSHA1 = class(THashAlgorithmBase, ISHA1)
http://lockbox.seanbdurkin.id.au/HomePage
unit LbProc;
procedure StreamHashSHA1(var Digest : TSHA1Digest; AStream : TStream);
procedure FileHashSHA1(var Digest : TSHA1Digest; const AFileName : string);
In older versions also (tested in maXbox4):
function SHA1FromFile(const filename: string): string;
var SHA1: TIdHashSHA1;
fs: TFileStream;
begin
SHA1:= TIdHashSHA1.Create;
fs:= TFileStream.Create(fileName, fmOpenRead or fmShareDenyWrite);
try
result:= SHA1.AsHex(SHA1.hashvalue1((fs),0,fs.size));
finally
SHA1.Free;
fs.Free;
end;
end;
I have scowered the net trying to find an example of a function, how to hash text with Sha1 and DCPcrypt.
I have the below example. Seems to pop up the whole time.
But it returns chinese characters every time. Please assist in corecting the function.
function TForm1.EncryptThis(aString : string) : string;
var
Cipher: TDCP_cast256;
KeyStr: string;
begin
KeyStr:= '';
Cipher:= TDCP_cast256.Create(Self);
Cipher.InitStr(KeyStr,TDCP_sha1);
result := Cipher.EncryptString(aString);
Cipher.Burn;
Cipher.Free;
end;
UPDATE:
Using the links and info belowe, I built these functions. But as I said, This does not make alot of sense to me. So please excuse the ignorance.
THe code however does not work. Its output is: 3F3F3F3F3F3F3F3F3F3F00000000000000000000 whereas it should be 40bd001563085fc35165329ea1ff5c5ecbdbbeef since i told the program to has 123.
Please help.
function CalcDigest(text: string): string;
var
x: TDCP_hash;
begin
x := TDCP_sha1.Create(nil);
try
x.Init;
x.UpdateStr(text);
SetLength(Result, x.GetHashSize div 8);
x.Final(Result[1]);
finally
x.Free;
end;
end;
function String2Hex(const Buffer: Ansistring): string;
begin
SetLength(result, 2*Length(Buffer));
BinToHex(#Buffer[1], PWideChar(#result[1]), Length(Buffer));
end;
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
begin
memo2.Lines.Add(String2Hex(CalcDigest(memo1.Lines.Strings[0])));
end;
Judging by this, you can do it this way:
function CalcDigest(text: string): string;
var
x: TDCP_hash;
begin
x := TDCP_sha1.Create(nil);
try
x.Init;
x.UpdateStr(text);
SetLength(Result, x.GetHashSize div 8);
x.Final(Result[1]);
finally
x.Free;
end;
end;
You may want to encode the hash before printing, because the output is binary. See for example this question.
I am not very familiar with DCPCrypt. You can also use other libraries.
1) Indy - usually included in Delphi
function SHA1Text(const s: string): string;
begin
with TIdHashSHA1.Create do
try
Result:=LowerCase(HashStringAsHex(s));
finally
Free;
end;
end;
2) Wolfgang Ehrhardt's libraries (fastest as far as I know) from
http://www.wolfgang-ehrhardt.de/crchash_en.html
function SHA1Text(const s: string): string;
var
Context: THashContext;
SHA1Digest: TSHA1Digest;
begin
SHA1Init(Context);
SHA1Update(Context, pChar(s), length(s));
SHA1Final(Context, SHA1Digest);
Result:=HexStr(#SHA1Digest, SizeOf(SHA1Digest));
end;
NOTE: it is from Delphi 7. You will need to update it if you use unicode Delphi.
How can I properly free the component once i make it with a loop like this? If I free it like I do now I get some GETMEM.INC exception. I am coming from Indy so i don't really know ICS too much.
Thanks
const
URLs : array[0..3] of string =
(
'http://www.example.com',
'http://www.example.com',
'http://www.example.com',
'http://www.example.com'
) ;
var
Output: array of TStringList;
S: array of TMemoryStream;
Async: array of TSslHttpCli;
implementation
procedure RequestDone(Sender: TObject; RqType: THttpRequest;
ErrCode: Word);
begin
with Sender as TSSLHTTPCLI do begin
S[Tag].Position:=0;
Output[Tag].LoadFromStream(S[Tag]);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
begin
for i := 0 to High(URLS) do begin
S[i]:=TMemoryStream.Create;
Output[i]:=TStringList.Create;
Async[i]:=TSslHttpCli.Create(nil);
Async[i].Tag:=i;
Async[i].FollowRelocation:=true;
Async[i].NoCache:=true;
Async[i].SocketFamily:=sfAny;
Async[i].OnRequestDone:=RequestDone;
Async[i].RcvdStream:=S[i];
Async[i].URL:= URLs[i];
Async[i].MultiThreaded:=true;
Async[i].GetASync;
end;
end;
procedure TForm1.Button4Click(Sender: TObject);
var
i:integer;
begin
for i := 0 to High(URLS) do begin
Output[i].Free;
Async[i].RcvdStream.Free;
Async[i].Free; // << -- EXCEPTION
// S[i].Free;
end;
end;
You never allocate any memory for Result, Asynch, or S. You need to SetLength on each of them before you can put anything into them (or take anything back out).
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
begin
SetLength(Result, Length(URLS));
SetLength(S, Length(URLS));
SetLength(Asynch, Length(URLS));
for i := 0 to High(URLS) do begin
S[i]:=TMemoryStream.Create;
Result[i]:=TStringList.Create;
Async[i]:=TSslHttpCli.Create(nil);
// etc.
end;
end;
BTW, Result is a terrible name for a variable, especially one that's global in scope. It's the return value from a function that's automatically generated by the compiler, and use anywhere but in a function makes your code hard to read. See this, for instance:
var
Result: string = '';
procedure AddToReslt(CharToAdd: Char);
begin
// Many many lines of code
// go in here. Maybe a few loops
// of if statements.
Result := Result + CharToAdd;
end;
function DoSomeMath: Integer;
begin
// Some really complex numeric code, maybe
// calculating the value of `pi` to the 900th
// digit
Result := 2 * 2;
end;
Now quickly - remembering that each of them containss lots of code - which one is a function and which is a procedure?
I'm in the process of implementing XML digital signatures. I'm starting with little steps, so right now I want to solve the problem of SHA-1 hashing.
There are lots of questions about this in SO:
Digitially Sign Key with Lockbox
Encryption library for Delphi
Convert this php digital signing to Delphi
Delphi: is there a version of LockBox for Delphi-XE
Delphi 2010 Cryptography libraries
...and probably more. However, I'm using Delphi XE. So far, I've tried LockBox 2 (both the Songbeamer and Sourceforge versions), Lock Box 3, DCPCrypto2 and some others (Hashes is an easy to use unit which uses Windows crypto functions)
I prepared a small test rig that gives me the following:
LockBox2
FAILED: 1 ('abc')
Got: '9f04f41a848514162050e3d68c1a7abb441dc2b5'
Expected: 'a9993e364706816aba3e25717850c26c9cd0d89d'
FAILED: 2 ('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')
Got: '51d7d8769ac72c409c5b0e3f69c60adc9a039014'
Expected: '84983e441c3bd26ebaae4aa1f95129e5e54670f1'
LockBox3
FAILED: 1 ('abc')
Got: '9f04f41a848514162050e3d68c1a7abb441dc2b5'
Expected: 'a9993e364706816aba3e25717850c26c9cd0d89d'
FAILED: 2 ('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')
Got: '51d7d8769ac72c409c5b0e3f69c60adc9a039014'
Expected: '84983e441c3bd26ebaae4aa1f95129e5e54670f1'
DCPCrypto2
FAILED: 1 ('abc')
Got: '9f04f41a848514162050e3d68c1a7abb441dc2b5'
Expected: 'a9993e364706816aba3e25717850c26c9cd0d89d'
FAILED: 2 ('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')
Got: '51d7d8769ac72c409c5b0e3f69c60adc9a039014'
Expected: '84983e441c3bd26ebaae4aa1f95129e5e54670f1'
Hashes
Test 1 passes
Test 2 passes
Have you succeeded in compile the mentioned libraries under Delphi XE and make them give the appropriate values? I'm particularly interested in DCPCrypt2 SelfTest procedure.
Edit: I've added this answer with the fixed source code. Thank you all for your help, it is most appreciated.
Leonardo, i think which your problem is the UNICODE when you uses a function to hash a string you are passing a array (buffer) of bytes. so when you pass the abc string in Delphi XE, your are hashing a buffer like this 61 00 62 00 63 00 (Hex representation)
check this sample application which uses the Windows crypto functions from the Jwscl library (JEDI Windows Security Code Lib)
program Jwscl_TestHash;
{$APPTYPE CONSOLE}
uses
JwsclTypes,
JwsclCryptProvider,
Classes,
SysUtils;
function GetHashString(Algorithm: TJwHashAlgorithm; Buffer : Pointer;Size:Integer) : AnsiString;
var
Hash: TJwHash;
HashSize: Cardinal;
HashData: Pointer;
i : Integer;
begin
Hash := TJwHash.Create(Algorithm);
try
Hash.HashData(Buffer,Size);
HashData := Hash.RetrieveHash(HashSize);
try
SetLength(Result,HashSize*2);
BinToHex(PAnsiChar(HashData),PAnsiChar(Result),HashSize);
finally
TJwHash.FreeBuffer(HashData);
end;
finally
Hash.Free;
end;
end;
function GetHashSHA(FBuffer : AnsiString): AnsiString;
begin
Result:=GetHashString(haSHA,#FBuffer[1],Length(FBuffer));
end;
function GetHashSHA_Unicode(FBuffer : String): String;
begin
Result:=GetHashString(haSHA,#FBuffer[1],Length(FBuffer)*SizeOf(Char));
end;
begin
try
Writeln(GetHashSHA('abc'));
Writeln(GetHashSHA('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'));
Writeln(GetHashSHA_Unicode('abc'));
Writeln(GetHashSHA_Unicode('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'));
Readln;
except
on E:Exception do
begin
Writeln(E.Classname, ':', E.Message);
Readln;
end;
end;
end.
this return
abc AnsiString
A9993E364706816ABA3E25717850C26C9CD0D89D
abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq AnsiString
84983E441C3BD26EBAAE4AA1F95129E5E54670F1 for
abc unicode
9F04F41A848514162050E3D68C1A7ABB441DC2B5
abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq Unicode
51D7D8769AC72C409C5B0E3F69C60ADC9A039014
My Cygwin command-prompt tells me it is indeed Unicode that's confusing you:
~$ printf 'a\0b\0c\0' | sha1sum
9f04f41a848514162050e3d68c1a7abb441dc2b5 *-
~$ printf 'abc' | sha1sum
a9993e364706816aba3e25717850c26c9cd0d89d *-
Could the expected value be for an ANSI string and the hash you are getting is for a unicode string?
Okay, so it was Unicode issues. Just in case you want to know, this is my Unit1.pas source. You need a form with a memo and a button. Requires DCPCrypt2, LockBox2, LockBox3 and the Hashes unit.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, LbCipher, LbClass, StdCtrls, DCPcrypt2, DCPsha1, Hashes,
uTPLb_CryptographicLibrary, uTPLb_BaseNonVisualComponent, uTPLb_Hash;
type
THashProc = reference to procedure(src: AnsiString; var output: AnsiString);
TForm1 = class(TForm)
Memo1: TMemo;
btnTest: TButton;
function Display(Buf: TBytes): String;
procedure LockBox2Test;
procedure LockBox3Test;
procedure DCPCrypto2Test;
procedure HashesTest;
procedure btnTestClick(Sender: TObject);
private
{ Private declarations }
procedure RunTests(Name: String; HashFunc: THashProc);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses uTPLb_StreamUtils;
{$R *.dfm}
procedure TForm1.btnTestClick(Sender: TObject);
begin
LockBox2Test;
LockBox3Test;
DCPCrypto2Test;
HashesTest;
end;
procedure TForm1.DCPCrypto2Test;
begin
RunTests('DCPCrypto2', procedure(src: AnsiString; var output: AnsiString)
var
Digest: TSHA1Digest;
Bytes : TBytes;
SHA1 : TDCP_sha1;
begin
SHA1 := TDCP_sha1.Create(nil);
SHA1.Init;
SHA1.UpdateStr(src);
SHA1.Final(Digest);
SHA1.Destroy;
SetLength(Bytes, 20);
Move(Digest, Bytes[0], 20);
output := Form1.Display(Bytes);
end);
end;
function TForm1.Display(Buf: TBytes): String;
var
i: Integer;
begin
Result := '';
for i := 0 to 19 do
Result := Result + Format('%0.2x', [Buf[i]]);
Result := LowerCase(Trim(Result));
end;
procedure TForm1.HashesTest;
begin
RunTests('Hashes', procedure(src: AnsiString; var output: AnsiString)
begin
output := CalcHash2(src, haSHA1)
end)
end;
procedure TForm1.LockBox2Test;
begin
RunTests('LockBox2', procedure(src: AnsiString; var output: AnsiString)
var
Digest: TSHA1Digest;
Bytes : TBytes;
SHA1 : TLbSHA1;
begin
SHA1 := TLbSHA1.Create(nil);
SHA1.HashStringA(src);
SHA1.GetDigest(Digest);
SHA1.Destroy;
SetLength(Bytes, 20);
Move(Digest, Bytes[0], 20);
output := Form1.Display(Bytes);
end);
end;
procedure TForm1.LockBox3Test;
begin
RunTests('LockBox3', procedure(src: AnsiString; var output: AnsiString)
var
Digest: TSHA1Digest;
bytes : TBytes;
P, Sz: integer;
aByte: byte;
s: string;
SHA1 : THash;
Lib : TCryptographicLibrary;
begin
Lib := TCryptographicLibrary.Create(nil);
SHA1 := THash.Create(nil);
SHA1.CryptoLibrary := Lib;
SHA1.HashId := 'native.hash.SHA-1';
SHA1.Begin_Hash;
SHA1.HashAnsiString(src);
if not assigned(SHA1.HashOutputValue) then
output := 'nil'
else
begin
SetLength(Bytes, 20);
Sz := SHA1.HashOutputValue.Size;
if Sz <> 20 then
output := Format('wrong size: %d', [Sz])
else
begin
P := 0;
SHA1.HashOutputValue.Position := 0;
while SHA1.HashOutputValue.Read(aByte, 1) = 1 do
begin
bytes[P] := aByte;
Inc(P);
end;
output := Form1.Display(Bytes);
end;
end;
SHA1.Destroy;
Lib.Destroy;
end)
end;
procedure TForm1.RunTests(Name: String; HashFunc: THashProc);
var
i: Integer;
Tests: array [1 .. 2, 1 .. 2] of AnsiString;
src, res: AnsiString;
expected: String;
begin
// http://www.nsrl.nist.gov/testdata/
Tests[1][1] := 'abc';
Tests[1][2] := 'a9993e364706816aba3e25717850c26c9cd0d89d';
Tests[2][1] := 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq';
Tests[2][2] := '84983e441c3bd26ebaae4aa1f95129e5e54670f1';
Memo1.Lines.Add('');
Memo1.Lines.Add('**' + Name + '**');
Memo1.Lines.Add('');
for i := 1 to 2 do
begin
src := Tests[i][1];
expected := Tests[i][2];
HashFunc(src, res);
res := Trim(LowerCase(res));
if res = expected then
begin
Memo1.Lines.Add(Format(' Test %d passes', [i]))
end
else
begin
Memo1.Lines.Add(Format(' FAILED: %d (''%s'') ', [i, src]));
Memo1.Lines.Add(Format(' Got: ''%s''', [res]));
Memo1.Lines.Add(Format(' Expected: ''%s''', [expected]));
end;
end;
end;
end.
I have a IV (initialization vector) and key, also a cryptogram. I need do decrypt the cryptogram. From the internet i found DCPcrypt Cryptographic Component Library v2.
So, now i've reached to coding.
procedure TForm1.Button1Click(Sender: TObject);
var
key:Ansistring;
ivector,indata,outdata:string;
begin
key := 'abc12345679'; //<--key for decrypting
dcp_rijndael1.InitStr(key,TDCP_sha1); //I don't understand why i need hashing!?
ivector := edit2.Text; //initialization vector
dcp_rijndael1.SetIV(ivector);
dcp_rijndael1.BlockSize := Length(ivector); //'This variable should be the same size as the block size' says the documentation
indata := edit1.Text; //getting the cryptogram
dcp_rijndael1.CipherMode := cmCBC;
dcp_rijndael1.DecryptCBC(indata,outdata,Length(indata));
label3.Caption := outdata; //output to label
end;
This code gives me an error. "Local Variables" window shows indata, outdata, ivector, key variables as 'Inaccessible value'.
Or maybe is there another way to do it. This seems pretty straight forward, though.
Thanks in advance.
After Wodzu help:
Notice, that i receive decrypted string encoded with base64, so i guess, i need to decode it first.
var
Form1: TForm1;
StringToEncrypt, StringToDecrypt, DecryptedString: string;
vector:string;
procedure TForm1.Button2Click(Sender: TObject);
begin
vector := '1234567812345678'; //Length 16
stringtodecrypt := '2YOXZ20Z7B3TRI/Ut8iH/GpEZWboE2tnnWU';
stringtodecrypt := Decode64(stringtodecrypt); //after encrypted string is sent over internet, it is encoded with base64, so i need to decode it.
SetLength(DecryptedString, 36); //36 is the length of the output
DCP_rijndael1.Init('MyKey:128bit', 128, #Vector[1]);
DCP_rijndael1.SetIV(Vector);
DCP_rijndael1.BlockSize := Length(Vector); //Should this be also 128
DCP_rijndael1.DecryptCBC(StringToDecrypt[1], DecryptedString[1], Length(StringToDecrypt)*2); //Here i get hieroglyph as a result. Why is length multiplied with 2?
decryptedstring := Encode64(decryptedstring); //Here i get less hieroglyph, but would like to get correct decrypted string. I doubt the necessity of encoding
ShowMessage(DecryptedString);
end;
I can't make this code to decrypt data that somebody else is encrypting (with PHP) (after encrypting the data is encoded with base64).
Note! encrypted text length is not the same as the decrypted text length!
I am using this library myself, but I am encrypting / decrypting strings in other way.
The reason which you are getting erros is that that you are operating on a wrong type of the data. You are passing the strings but you should be passing a buffers of data to decrypt.
In this line of code:
dcp_rijndael1.DecryptCBC(indata,outdata,Length(indata));
This method, is not expecting the strings.
Change your code like this:
procedure TForm1.Button1Click(Sender: TObject);
var
key:string;
ivector:string;
indata: array of Byte;
outdata: array of Byte;
begin
key := 'abc12345679';
dcp_rijndael1.InitStr(key,TDCP_sha1);
ivector := edit2.Text;
dcp_rijndael1.SetIV(ivector);
dcp_rijndael1.BlockSize := Length(ivector);
// indata := edit1.Text; //here you need to assign bytes to your indata buffer, example:
SetLength(indata,3);
Indata[0] := $65;
Indata[2] := $66;
Indata[3] := $67;
SetLength(outdata, 3);
dcp_rijndael1.CipherMode := cmCBC;
dcp_rijndael1.DecryptCBC(indata[0],outdata[0],Length(indata));
// label3.Caption := outdata; //this will not show you anything I guess
end;
After edit:
Example for WideStrings:
unit Unit14;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DCPcrypt2, DCPsha1, DCPblockciphers, DCPrijndael, StdCtrls;
type
TForm14 = class(TForm)
btnEncrypt: TButton;
DCP_rijndael1: TDCP_rijndael;
DCP_sha11: TDCP_sha1;
btnDecrypt: TButton;
procedure btnEncryptClick(Sender: TObject);
procedure btnDecryptClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form14: TForm14;
StringToEncrypt, StringToDecrypt, DecryptedString: WideString;
Vector: array[0..3] of Byte;
implementation
{$R *.dfm}
procedure TForm14.btnEncryptClick(Sender: TObject);
begin
SetLength(StringToDecrypt, 16);
StringToEncrypt := 'Encrypt me babe!';
DCP_rijndael1.Init('1234', 32, #Vector[0]);
DCP_rijndael1.SetIV(Vector);
DCP_rijndael1.BlockSize := 4;
DCP_rijndael1.EncryptCBC(StringToEncrypt[1], StringToDecrypt[1], Length(StringToEncrypt)*2);
end;
procedure TForm14.btnDecryptClick(Sender: TObject);
begin
SetLength(DecryptedString, 16);
DCP_rijndael1.Init('1234', 32, #Vector[0]);
DCP_rijndael1.SetIV(Vector);
DCP_rijndael1.BlockSize := 4;
DCP_rijndael1.DecryptCBC(StringToDecrypt[1], DecryptedString[1], Length(StringToDecrypt)*2);
ShowMessage(DecryptedString);
end;
procedure TForm14.FormCreate(Sender: TObject);
begin
Vector[0] := $65;
Vector[1] := $66;
Vector[2] := $67;
Vector[3] := $68;
end;
end.
Hope this helps.
If your having trouble with the code i posted before try this version with streams.
procedure TForm1.Decrypt(const aKey: AnsiString; aPVector: Pointer;
var aInData, aOutData: TMemoryStream);
var
Cipher : TDCP_rijndael;
begin
Cipher := TDCP_rijndael.Create(nil);
try
Cipher.Init(aKey, Length(aKey)*8, aPVector);
Cipher.CipherMode := cmCBC;
Cipher.DecryptStream(aInData, aOutData, aInData.Size);
finally
Cipher.Burn;
Cipher.Free;
end;
end;
and here is how to use it:
var
din, dout: TMemoryStream;
Vector: array of byte;
begin
SetLength(Vector, 16);
Vector[1] := 1;
Vector[2] := 2;
Vector[3] := 9;
Vector[4] := 0;
Vector[5] := 6;
Vector[6] := 1;
Vector[7] := 6;
Vector[8] := 7;
Vector[9] := 5;
Vector[10] := 8;
Vector[11] := 3;
Vector[12] := 1;
Vector[13] := 7;
Vector[14] := 3;
Vector[15] := 3;
Vector[16] := 8;
din := TMemoryStream.Create;
dout := TMemoryStream.Create;
try
din.LoadFromFile('Encrypted.DAT');
din.Position := 0;
decrypt('4tkF4tGN1KSiwc4E', addr(Vector[1]), din, dout);
dout.SaveToFile('Decrypted.DAT');
finally
din.Free;
dout.Free;
end;
and a version for strings:
procedure TForm1.Decrypt(const aKey: AnsiString; aPVector: Pointer;
const aInData: AnsiString; var aOutData: AnsiString);
var
Cipher : TDCP_rijndael;
begin
Cipher := TDCP_rijndael.Create(nil);
try
Cipher.Init(aKey, Length(aKey)*8, aPVector);
Cipher.CipherMode := cmCBC;
aOutData := Cipher.DecryptString(aInData);
finally
Cipher.Burn;
Cipher.Free;
end;
end;
if you need any more help let me know.
Are you having some issues with the demo they provided:
http://www.cityinthesky.co.uk/files/dcpdemos.zip
Also, did you try other libraries that might clear things up:
Free Encryption library for Delphi
If you are using Delphi .NET: Help using Rijndael Algorithm in Delphi 2007. Net
I use the DCPCrypt components regularly and have written a wrapper class for them to make it easier to use.
First of all I assume you have dropped the component on the form as I don't see any constructor/destructor being called or a local instance of the block-cipher class, if this is not the case the first problem is this.
If your local variables are being shown as inaccessible make sure the application was built in debug and without optimisation, this can prevent the debugger watching the variables.
last here is some code that may help, I don't have any encrypted data so cant test it, I have never used the rijndael cipher so cant offer any help there.
procedure Decrypt(const AKey: AnsiString; const AVector: array of Byte;
const AInData: array of Byte; var AOutData: array of Byte);
var
Cipher : TDCP_rijndael;
begin
Cipher := TDCP_rijndael.Create(nil);
try
Cipher.Init(AKey, Length(AKey)*8, #AVector[0]);
Cipher.CipherMode := cmCBC;
Cipher.DecryptCBC(AInData[0], AOutData[0], Length(AInData));
finally
Cipher.Burn;
Cipher.Free;
end;
end;
IN this code the vector is a dynamic array and should have its length set and populated with the data before calling the procedure, also the key is a string containing the either a hash digest or a simple key depending on how the data was encrypted.
as to why a hash is needed I believe it is to increase security so that it is difficult for hackers to decrypt that data.