unit Tools.Crypt;
interface
uses
System.SysUtils, DECUtil, DECHash, DECCipherBase, DECCiphers, DECHashBase,
DECFormatBase, DECFormat, DECRandom, DECHashAuthentication;
const
conKey = 'aYr14iaz8u)xO7Ok';
var
//CipherAlgo: TCipher_Rijndael;
CipherMode: TCipherMode = cmCBCx;
HashClass : TDECHashClass = THash_SHA256;
TextFormat: TDECFormatClass = TFormat_Base64;
KDFIndex : Integer = 1; // Iterations
type
TToolsCrypt = class
public
class function Decrypt(aHash: string; aKey: string = ''): string;
class function Encrypt(aText: string; aKey: string = ''): string;
end;
implementation
{ TToolsCrypt }
class function TToolsCrypt.Decrypt(aHash, aKey: string): string;
var
Cipher: TCipher_Rijndael;
//Cipher: TDECCipher;
Salt, Data, Check, Pass, Mac: TBytes;
MacLength, SaltLen, DataLen: Integer;
begin
if aKey = '' then
begin
aKey := conKey;
end;
//Cipher:=ValidCipher(TCipher_Rijndael).Create; // the way it should be used ! but it fail now with DecodeBytes
Cipher := TCipher_Rijndael.Create;
try
MacLength := Cipher.Context.BlockSize;
SaltLen := Cipher.InitVectorSize;
Salt := ValidFormat(TextFormat).Decode(BytesOf(aHash));
DataLen := Length(Salt) - MacLength - Cipher.Context.BufferSize;
Data := Copy(Salt, MacLength, DataLen);
Check := Copy(Salt, DataLen + SaltLen, Cipher.Context.BufferSize);
SetLength(Salt, SaltLen);
Pass := ValidAuthenticationHash(HashClass).KDFx(aKey[Low(aKey)], Length(aKey) * SizeOf(Char), Salt[Low(Salt)], Length(Salt), Cipher.Context.KeySize, KDFIndex);
Cipher.Mode := CipherMode;
Cipher.Init(Pass, nil);
SetLength(Result, DataLen div SizeOf(Char));
Cipher.Decode(Data[Low(Data)], Result[Low(Result)], DataLen);
//Result := StringOf(Cipher.DecodeBytes(Data,TFormat_Copy));
Mac := BytesOf(Cipher.CalcMAC);
if MacLength < Length(Check) then
MacLength := Length(Check);
if (MacLength <> Cipher.Context.BlockSize) or (not CompareMem(Check, Mac, MacLength)) then
begin
Result := '';
end;
finally
Cipher.Free;
ProtectBytes(Salt);
ProtectBytes(Check);
ProtectBytes(Data);
ProtectBytes(Pass);
ProtectBytes(Mac);
end;
end;
class function TToolsCrypt.Encrypt(aText, aKey: string): string;
var
Cipher: TCipher_Rijndael;
Salt, Pass, Data, Mac: TBytes;
begin
if aKey = '' then
begin
aKey := conKey;
end;
Cipher := TCipher_Rijndael.Create;
try
Salt := RandomBytes(Cipher.InitVectorSize);
Pass := ValidAuthenticationHash(HashClass).KDFx(aKey[Low(aKey)], Length(aKey) * SizeOf(Char), Salt[Low(Salt)], Length(Salt), Cipher.Context.KeySize, KDFIndex);
Cipher.Mode := CipherMode;
Cipher.Mode := cmCBCx;
Cipher.Init(Pass, nil);
SetLength(Data, Length(aText) * SizeOf(Char));
Cipher.Encode(aText[Low(aText)], Data[Low(Data)], Length(Data));
Mac := BytesOf(Cipher.CalcMAC);
Result := StringOf(ValidFormat(TextFormat).Encode(Salt + Data + Mac));
finally
Cipher.Free;
ProtectBytes(Salt);
ProtectBytes(Pass);
ProtectBytes(Data);
ProtectBytes(Mac);
end;
end;
end.