Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get Argon2 version number #30

Open
outkst opened this issue Feb 6, 2019 · 5 comments
Open

Get Argon2 version number #30

outkst opened this issue Feb 6, 2019 · 5 comments

Comments

@outkst
Copy link

outkst commented Feb 6, 2019

Continuing from closed Issue #19 — Can you please provide a way to programmatically obtain the version number of the current Argon2 implementation being used? From page 20 of the Argon2 documentation, the current version 1.3 is stored as a byte in the form of 0x13, and either this would be kept the same or like some other ports of Argon2 would simply become an integer (e.g. 19).

C.1 v.1.3
• The blocks are XORed with, not overwritten in the second pass and later;
• The version number byte is now 0x13.

This number would be stored inside of the database in case the algorithm is ever changed and breaks compatibility with older versions.

@kmaragon
Copy link
Owner

kmaragon commented Feb 7, 2019

This is a very good point. Though I would argue that rather than simply returning a version byte somewhere, the library needs a facility for selecting a version and acting accordingly. i.e. a constructor parameter specifying a version to use, with the default value being the latest version. Then a getter that just returns the version that the class was constructed with would do what you're asking. I think this is an important layer of abstraction that this library is missing. I will work on a non-breaking change to do that under the hood and maybe use the opportunity to support 1.2(.x)... While of course still generating 1.3 hashes by default.

@SparkDustJoe
Copy link

SparkDustJoe commented Feb 8, 2019 via email

@ghost
Copy link

ghost commented Feb 15, 2019

Are there any plans to support encoding/decoding (i.e. $argon2i$v=19$m=65536,t=2,p=4$c29tZXNhbHQ$RdescudvJCsgt3ub+b+dWRWJTmaaJObG)?

@outkst
Copy link
Author

outkst commented Feb 15, 2019

@mrfrankbell I think the string encoding is the eventual goal here—once a Version property is introduced. The string encoding will allow the storage of the version number, cost options, and salt alongside the hash just like in the original implementation.

$argon2i$v=19$m=65536,t=2,p=4$c29tZXNhbHQ$RdescudvJCsgt3ub+b+dWRWJTmaaJObG

The string encoding above can then be obtained in this implementation by doing something like the following:

CalculateArgon2iHash("password"); // implicit
CalculateArgon2iHash("password", "somesalt", Argon2Version.Newest); // same as below
CalculateArgon2iHash("password", "somesalt", 19); // same as above
CalculateArgon2iHash("password", "somesalt", 19, 65536, 2, 4, 32); // explicit

// NEW ENUM
public enum Argon2Version {
    Unknown = 0,
    V13 = 19, // 0x13
    V10 = 16, // 0x10
    Newest = V13
}
public static string CalculateArgon2iHash(string plaintextPassword, byte[] salt = null, Argon2Version version = Argon2Version.Newest, int? memorySize = null, int? iterations = null, int? parallelism = null, int? hashLength = null) {
    memorySize = memorySize ?? MEMORY_SIZE;
    iterations = iterations ?? ITERATIONS;
    parallelism = parallelism ?? DEGREE_OF_PARALLELISM;
    salt = salt ?? GenerateSalt(SALT_LENGTH);
    hashLength = hashLength ?? HASH_LENGTH;

    string encodedPassword;

    using (Argon2i argon2 = new Argon2i(Encoding.UTF8.GetBytes(plaintextPassword)))
    {
        argon2.Version = version; // NEW ENUM
        argon2.MemorySize = (int)memorySize;
        argon2.Iterations = (int)iterations;
        argon2.DegreeOfParallelism = (int)parallelism;
        argon2.Salt = salt;

        encodedPassword = String.Format("${0}$v={1}$m={2},t={3},p={4}${5}${6}",
            argon2.GetType().Name.ToLower(),
            argon2.Version, // NEW ENUM
            argon2.MemorySize,
            argon2.Iterations,
            argon2.DegreeOfParallelism,
            Convert.ToBase64String(argon2.Salt),
            Convert.ToBase64String(argon2.GetBytes((int)hashLength))
        );
    }

    return encodedPassword; // $argon2i$v=19$m=65536,t=2,p=4$c29tZXNhbHQ$RdescudvJCsgt3ub+b+dWRWJTmaaJObG
}

@kmaragon
Copy link
Owner

kmaragon commented Mar 7, 2019

I have no intention of adding support for the stringification of the argon2 hash as in the argon2 reference command-line program (as opposed to the core library). You'll also notice that the command line program doesn't support various attributes laid out in the spec... But I do have every intention of making the version number a property that can be used for someone to do so - as well as to control how the hash is generated. But generally, keep in mind that the most secure use of this (or argon2 in-general) would be to keep the pieces entirely separately.

For example, if you are generating an API Key, you could embed the Iterations directly into the API key at the edge layer in the one time you give it to the client. And then simply validate it min < x < max before plugging it into the algorithm to validate the keys. And then you could use a key service i.e. AWS KMS to assign specific KnownSecret (one of those attributes laid out in the spec that the command line program doesn't support) values to subsets of keys. Embedding these into the final hash undermine good security design without asking the engineer to go and parse out the output to extract the pieces rather than store them.

The GetBytes API is also just that - an API to get bytes. It will be up to the developer to figure out where the pieces go to reconstruct those bytes. But I also don't intend to make the above code sample impossible to implement. Nor do I plan to make it impossible to validate old hashes as the versions are updated (as it is now). So I will be adding version as well as backwards compatibility... As soon as I have time to spin back up my .NET environment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants