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:
The above updated, with encrypt-descrypt routines
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: