Disclaimer: I suppose this would be more on-topic on security.se or even StackOverflow, as it's essentially about how software uses an existing piece of cryptographic software in a black-box manner.
TL; DR the leading argon2
identifies Django's wrapper class around the argon2-cffi
library. The remainder is that library's output.
First, according to the Django documentation on password storage, the format they claim to use is the following:
<algorithm>$<iterations>$<salt>$<hash>
However this format is limiting, in that it assumes that each algorithm has exactly one parameter each for iterations
, salt
, and hash
. I do suppose this format would be correct if you used the default, PBKDF2-based, password hashing - less so if using something like Argon2, with its plethora of parameters.
In general then, the format it actually uses is:
<algorithm>$<output>
Where algorithm
uniquely identifies the specific implementation (in terms of a Python class) of password hashing which was used, and output
is simply that one's output. Indeed you can observe this behaviour e.g. here, where you see that Django first checks the first component of the stored value to identify the wrapper class to use, which is later used to compare a hash with a supplied password.
Then your observed output becomes clear. The first argon2
identifies Django's Argon2 wrapper, and argon2id$v=19$m=102400,t=2,p=8$...
is its output.
Following the chain a bit more we learn that Django relies on the argon2-cffi
library for Argon2 hashing, which indeed produces output similar to what you observed.