argon2-for-delphi
argon2-for-delphi copied to clipboard
TArgon2.DeriveBytes always returns an array of zeros no matter what passphrase is supplied
I tested using this code and I always get the same digest in the hash string.
Hash := TArgon2.HashPassword(Pwd);
Matched := TArgon2.CheckPassword(Pwd, Hash, Rehash);
the check password function is returning true with the hash strings.
Maybe I'm doing something wrong, i'm not sure
password:
$Argon2id $v=19 $m=131072,t=10000,p=1 $l9yGr4S9jB7D1mZhNLHYWQ== $AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
password1:
$Argon2id $v=19 $m=131072,t=10000,p=1 $l2UP21fItrhdXTlnkI2+tQ== $AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
password2:
$Argon2id $v=19 $m=131072,t=10000,p=1 $cVH50MP3v87ngjRAKUpqHA== $AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
I think this is the problem
TArgon2.GetBytes Aprox line 750
SetLength(Result, DesiredNumberOfBytes);
FillChar(Result[0], DesiredNumberOfBytes, 0);
looks like it will always return an array of zeros!
The real problem is that this implementation is nowhere near working, because neither the RFC, nor the white-papers, nor the reference implementations, explain how the algorithm works. Without being able to decipher the algorithm, i have no hope of implementing it.
Hopefully others can decipher the god-awful mess that the different RFC's are, and complete the implementation.
Because they are so badly written, i want to choke his tongue out.
I'm willing to give it a shot if you can let me know where to start looking
Also please add a comment to the home page to say the implementation is not finished or working
I've committed everything i was behind on.
There's five main pieces that make up Argon2; 1 is complete and tested, 2 more are mostly complete, but untestable, final 2 are completely unwritten.
-
Blake2: a hash algorithm that produces 64-byte digests. I have this implemented and test vectors match the separate Blake2 RFC. The algorithm was extraordinary poorly documented, and took months of reverse engineering to make a Delphi port work. I created an understandable version of the Blake2 algorithm on its wikipedia page
-
DeriveBytes: the main loop that performs the operations the specified number of times, on the parallelization number of lanes, on the specified amount of memory. This is mostly complete; but also untestable until the following two functions are written. This algorithm is horribly documented, but i believe i managed to decipher it correctly, and i created an understandable version on the Wikipedia page for Argon2
-
Hash: a variable length hash algorithm based on Blake2, that is capable of producing digests up to the needed 1024 bytes (while Blake2 digest is fixed at 64 bytes). I have implemented this function, but it is untestable, as Argon2 has no test vectors to verify. This algorithm is horribly documented, but i believe i managed to decipher it correctly, and i created an understandable version on the Wikipedia page for Argon2
-
GetBlockIndexes: the main
DeriveBytes
algorithm operates on memory in 1KB blocks arranged in a 2-d array. The i,j indexes that are operated on follow a separate algorithm. The algorithm to use depends on which variant of Argon2 you are using:- Argon2id
- Argon2d
- Argon2i
The algorithm that explains the 3 different algorithms of selecting indexes is horribly explained in the RFC and in various whitepapers. I have no idea how it works, and the implemention remains completely empty:
procedure TArgon2.GetBlockIndexes(i, j: Integer; out iRef, jRef: Integer);
begin
{
We are Argon2id.
}
//Since i cannot make heads nor tails of either their PDF, their RFC, their GitHub, nor their sample code, this is a todo
iRef := 0;
jRef := 0;
raise ENotImplemented.Create('Someone needs to figure out the 2id block schedule alorithm');
end;
-
G
: Both the RFC and the whitepapapers (and my translation of the main algorithm on Wikipedia) refer to a function known only asG
. The function is not documented anywhere. On the Wikipedia page i leave it completely unexplained:https://i.imgur.com/nT1mAYT.png
the same in true in the Delphi code:
//TODO: They don't document what the function G is
//B[i][j] = G(B[i][j-1], B[iref][jref])
I've committed the RFC and two variations of the whitepapers that "document" Argon2. Someone needs to decipher them, and create the GetBlockIndexes
and G
function.
- RFC: The memory-hard Argon2 password hash and proof-of-work function (updated August 3, 2017)
- Whitepaper: Argon2: the memory-hard function for password hashing and other applications (updated March 24, 2017)
Maybe i'm a fool or maybe Ii found the definition of G
2.1.4 Compression function G
Compression function G is built upon the Blake2b round function P (fully defined in Section 2.7.1). P operates on the 128-byte input, which can be viewed as 8 16-byte registers (see details below): P(A0, A1, . . . , A7) = (B0, B1, . . . , B7).
Compression function G(X, Y ) operates on two 1024-byte blocks X and Y . It first computes R = X ⊕ Y . Then R is viewed as a 8 × 8-matrix of 16-byte registers R0, R1, . . . , R63
. Then P is first applied rowwise, and then columnwise to get Z: Finally, G outputs Z ⊕ R:
Document attached below :)
now works?
This claims to support Argon2: https://github.com/Xor-el/HashLib4Pascal Perhaps you may be able to learn from it? I'd much rather use something standalone like your library