Tool B4XEncryption : Decrypt from Delphi

dcoun

Member
Licensed User
Use DCPcrypt lib from https://sourceforge.net/p/dcpcrypt/code/HEAD/tree/
I took code from: http://keit.co/p/dcpcrypt-hmac-rfc2104/

The code:
B4X:
uses DCPcrypt2, DCPsha1,  DCPblockciphers, DCPrijndael;

function RPad(x: ansistring; c: AnsiChar; s: Integer): ansistring;          var i: Integer;
begin Result:=x; if Length(x)<s then for i:=1 to s-Length(x) do Result:=Result+c; end;

function XorBlock(s, x: ansistring): ansistring; inline;        var i: Integer;
begin SetLength(Result,Length(s)); for i:=1 to Length(s) do Result[i]:=AnsiChar(Byte(s[i]) xor Byte(x[i])); end;

function CalcDigest(text: ansistring): ansistring;      var x:TDCP_sha1;
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 CalcHMAC(mess,key: ansistring): ansistring;
const blocksize = 64;
begin  // Definition RFC 2104
if Length(key) > blocksize then key:=CalcDigest(key); key:=RPad(key,#0,blocksize);
Result:=CalcDigest(XorBlock(key,RPad('',#$36,blocksize))+mess);
Result:=CalcDigest(XorBlock(key,RPad('',#$5c,blocksize))+result); end;

function PBKDF1(pass, salt: ansistring; count: Integer): ansistring;
var i: Integer;
begin Result:=pass+salt; for i:=0 to count-1 do Result:=CalcDigest(Result); end;

function PBKDF2(pass, salt: ansistring; count, kLen: Integer; hash: TDCP_sha1): ansistring;
  function IntX(i: Integer): ansistring; inline;
  begin Result:=ansiChar(i shr 24)+ansiChar(i shr 16)+ansiChar(i shr 8)+ansiChar(i); end;
var D,I,J:Integer; T,F,U:ansistring;
begin T:=''; D:=Ceil(kLen/(hash.GetHashSize div 8)); for i:=1 to D do begin
F:=CalcHMAC(salt+IntX(i),pass); U:=F; for j:=2 to count do begin
U:=CalcHMAC(U,pass); F:=XorBlock(F,U); end; T:=T+F; end; Result:=Copy(T,1,kLen); end;

function encrypt(const data, password: string): string;
var n,i,m:integer; salt,iv,key,dat:rawbytestring; h:TDCP_sha1; ra:TDCP_rijndael; p:pwidechar;
begin setlength(iv,16); for n:=1 to 16 do iv[n]:=ansichar(Random(256));
setlength(salt,8); for n:=1 to 8 do salt[n]:=ansichar(random(256)); result:='';
dat:=UTF8Encode(data); i:=length(dat); m:=16-i mod 16; if m=0 then m:=16; i:=i+m;
setlength(dat,i); for n:=i-m+1 to i do dat[n]:=ansichar(m);
h:=TDCP_sha1.Create(nil); ra:=TDCP_rijndael.Create(nil); try
key:=UTF8Encode(password); h.Init; key:=PBKDF2(key,salt,1024,16,h);
ra.Init(key[1],128,@IV[1]); ra.encryptCBC(dat[1],dat[1],i); finally ra.Free; h.Free; end;
setlength(result,i+48); p:=@result[1]; BinToHex(@salt[1],p,8); inc(p,16);
BinToHex(@iv[1],p,16); inc(p,32); BinToHex(@dat[1],p,i); end;

function decrypt(const data,password: string): string;
var n,i:integer; h:TDCP_sha1; ra:TDCP_rijndael; dat,salt,iv,key:rawbytestring;
begin i:=(length(data) div 2)-24; setlength(dat,i); setlength(iv,16); setlength(salt,8);
result:=LowerCase(data); HexToBin(pwidechar(result),@salt[1],8);
system.Delete(result,1,16); HexToBin(pwidechar(result),@iv[1],16);
system.Delete(result,1,32); hextobin(pwidechar(result),@dat[1],i);
h:=TDCP_sha1.Create(nil); h.Init; ra:=TDCP_rijndael.Create(nil); try
key:=UTF8Encode(password); key:=PBKDF2(key,salt,1024,16,h); ra.Init(key[1],128,@IV[1]);
ra.DecryptCBC(dat[1],dat[1],i); finally ra.Free; h.Free; end;
if byte(dat[i])>16 then begin result:=''; exit; end;
dec(i,byte(dat[i])); setlength(dat,i); result:=UTF8Decode(dat); end;
The above updated, with encrypt-descrypt routines
 
Last edited:

dcoun

Member
Licensed User
It was late in the night, when I posted my first results. Today, I had the time to rewrite it and test it. Padding was added using PKCS7 standard. Passwords can be in any language. Tested in B4J and Delphi 10.1 and works ok. No extra dll needed. Lazarus is supported. modules for apache can use it.
Feel free to report any problem....
 
Last edited:
Top