/// <summary> /// Initializes a new instance of the <see cref="Argon2TestVector"/> class. /// </summary> /// <param name="name"> /// name of the vector /// </param> /// <param name="type"> /// Data-driven or independent. /// </param> /// <param name="version"> /// The Argon2 version. /// </param> /// <param name="iterations"> /// The number of iterations. /// </param> /// <param name="memoryKBytes"> /// The memory to use. /// </param> /// <param name="parallelism"> /// The number of threads to use. /// </param> /// <param name="tagLength"> /// How many bytes to output. /// </param> /// <param name="password"> /// The password to hash. /// </param> /// <param name="salt"> /// The salt to use in the hash. Minimum of 8 bytes. 16 recommended. /// </param> /// <param name="secret"> /// The secret to use in the hash. /// </param> /// <param name="associatedData"> /// The associated data to use in the hash (like a salt but can be shorter). /// </param> /// <param name="tag"> /// The expected hash created from the above parameters. /// </param> public Argon2TestVector( string name, Argon2Type type, Argon2Version version, int iterations, int memoryKBytes, int parallelism, int tagLength, string password, string salt, string secret, string associatedData, string tag) { this.Name = name; this.Type = type; this.Version = version; this.Iterations = iterations; this.MemoryKBytes = memoryKBytes; this.Parallelism = parallelism; this.TagLength = tagLength; this.Password = ToBytes(password); this.Salt = ToBytes(salt); this.Secret = ToBytes(secret); this.AssociatedData = ToBytes(associatedData); this.Tag = ToBytes(tag); }
private void HashTestOthers(IArgon2ParametersBuilder a_Argon2ParametersBuilder, Argon2Version a_Version, Int32 a_Iterations, Int32 a_Memory, Int32 a_Parallelism, string a_Password, string a_Salt, string a_PasswordRef, Int32 a_OutputLength) { IPBKDF_Argon2 LGenerator; byte[] LSalt, LPassword; string LActual; IArgon2Parameters LArgon2Parameter; LSalt = Converters.ConvertStringToBytes(a_Salt, Encoding.ASCII); LPassword = Converters.ConvertStringToBytes(a_Password, Encoding.ASCII); a_Argon2ParametersBuilder.WithVersion(a_Version).WithIterations(a_Iterations) .WithMemoryPowOfTwo(a_Memory).WithParallelism(a_Parallelism).WithSalt(LSalt); // // Set the password. // LArgon2Parameter = a_Argon2ParametersBuilder.Build(); a_Argon2ParametersBuilder.Clear(); LGenerator = HashFactory.KDF.PBKDF_Argon2.CreatePBKDF_Argon2(LPassword, LArgon2Parameter); LActual = Converters.ConvertBytesToHexString(LGenerator.GetBytes(a_OutputLength), false); LArgon2Parameter.Clear(); LGenerator.Clear(); Assert.AreEqual(a_PasswordRef, LActual, String.Format("Expected {0} but got {1}.", a_PasswordRef, LActual)); } //
public Argon2Parameters(Argon2Type type, byte[] salt, byte[] secret, byte[] additional, int iterations, int memory, int lanes, Argon2Version version) { if (salt == null) { throw new ArgumentNullException(nameof(salt)); } if (secret == null) { throw new ArgumentNullException(nameof(secret)); } if (additional == null) { throw new ArgumentNullException(nameof(additional)); } _salt = ArrayUtils.Clone(salt); _secret = ArrayUtils.Clone(secret); _additional = ArrayUtils.Clone(additional); Iterations = iterations; Memory = memory; Lanes = lanes; Type = type; Version = version; }
} // end cctr protected Argon2ParametersBuilder(Argon2Type a_Type) { Lanes = DEFAULT_LANES; Memory = 1 << DEFAULT_MEMORY_COST; Iterations = DEFAULT_ITERATIONS; Type = a_Type; Version = DEFAULT_VERSION; } //
private Argon2ParametersBuilder() { _salt = new byte[0]; _secret = new byte[0]; _additional = new byte[0]; _type = DEFAULT_TYPE; _version = DEFAULT_VERSION; _iterations = DEFAULT_ITERATIONS; _memory = 1 << DEFAULT_MEMORY_COST; _lanes = DEFAULT_LANES; }
protected Argon2ParametersBuilder(Argon2Type a_Type, byte[] a_Salt, byte[] a_Secret, byte[] a_Additional, Int32 a_Iterations, Int32 a_Memory, Int32 a_Lanes, Argon2Version a_Version) { Salt = a_Salt.DeepCopy(); Secret = a_Secret.DeepCopy(); Additional = a_Additional.DeepCopy(); Iterations = a_Iterations; Memory = a_Memory; Lanes = a_Lanes; Type = a_Type; Version = a_Version; } // end cctr
/// <summary> /// Initializes a new instance of the <see cref="Argon2HashAlgorithm"/> class with the specified parameters. /// </summary> /// <param name="type">The Argon2 algorithm type to use.</param> /// <param name="version">The Argon2 version to use.</param> /// <param name="parallelism">The number of lanes to use while processing the hash.</param> /// <param name="memorySize">The amount of memory (in MB) to use while processing the hash.</param> /// <param name="hashLength">The size of the output hash (in bytes). 16 bytes is recommended for password hashing.</param> public Argon2HashAlgorithm(Argon2Type type, Argon2Version version, int parallelism, int memorySize, int hashLength = 16) : base($"{type}V{(int)version}-{hashLength * 8}-{parallelism}P-{memorySize}MB") { // Inputs: // password (P): Bytes (0..2^32-1) Password (or message) to be hashed // salt (S): Bytes (8..2^32-1) Salt (16 bytes recommended for password hashing) // parallelism (p): Number (1..2^24-1) Degree of parallelism (i.e. number of threads) // tagLength (T): Number (4..2^32-1) Desired number of returned bytes // memorySizeKB (m): Number (8p..2^32-1) Amount of memory (in kibibytes) to use // iterations (t): Number (1..2^32-1) Number of iterations to perform // version (v): Number (0x13) The current version is 0x13 (19 decimal) // key (K): Bytes (0..2^32-1) Optional key (Errata: PDF says 0..32 bytes, RFC says 0..232 bytes) // associatedData (X): Bytes (0..2^32-1) Optional arbitrary extra data // hashType (y): Number (0=Argon2d, 1=Argon2i, 2=Argon2id) // Output: // tag: Bytes (tagLength) The resulting generated bytes, tagLength bytes long if (!Enum.IsDefined(typeof(Argon2Type), type)) { throw new ArgumentOutOfRangeException(nameof(type)); } if (!Enum.IsDefined(typeof(Argon2Version), version)) { throw new ArgumentOutOfRangeException(nameof(version)); } if (parallelism < 1) { throw new ArgumentOutOfRangeException(nameof(parallelism)); } if (memorySize * 1024 < parallelism * 8 || memorySize > 4194303) { throw new ArgumentOutOfRangeException(nameof(memorySize)); } if (hashLength < 4) { throw new ArgumentOutOfRangeException(nameof(hashLength)); } Parallelism = parallelism; MemorySize = memorySize; HashLength = hashLength; }
private void HashTestFromInternetDraft(IArgon2ParametersBuilder a_Argon2ParametersBuilder, Argon2Version a_Version, Int32 a_Iterations, Int32 a_MemoryAsKB, Int32 a_Parallelism, string a_Additional, string a_Secret, string a_Salt, string a_Password, string a_PasswordRef, Int32 a_OutputLength) { IPBKDF_Argon2 LGenerator; string LActual; byte[] LAdditional, LSecret, LSalt, LPassword; IArgon2Parameters LArgon2Parameter; LAdditional = Converters.ConvertHexStringToBytes(a_Additional); LSecret = Converters.ConvertHexStringToBytes(a_Secret); LSalt = Converters.ConvertHexStringToBytes(a_Salt); LPassword = Converters.ConvertHexStringToBytes(a_Password); a_Argon2ParametersBuilder.WithVersion(a_Version).WithIterations(a_Iterations) .WithMemoryAsKB(a_MemoryAsKB).WithParallelism(a_Parallelism) .WithAdditional(LAdditional).WithSecret(LSecret).WithSalt(LSalt); // // Set the password. // LArgon2Parameter = (IArgon2Parameters)a_Argon2ParametersBuilder.Build(); a_Argon2ParametersBuilder.Clear(); LGenerator = HashFactory.KDF.PBKDF_Argon2.CreatePBKDF_Argon2(LPassword, LArgon2Parameter); LActual = Converters.ConvertBytesToHexString(LGenerator.GetBytes(a_OutputLength), false); LArgon2Parameter.Clear(); LGenerator.Clear(); Assert.AreEqual(a_PasswordRef, LActual, String.Format("Expected {0} but got {1}.", a_PasswordRef, LActual)); } //
} // public IArgon2ParametersBuilder WithVersion(Argon2Version a_Version) { Version = a_Version; return(this as IArgon2ParametersBuilder); } //
public Argon2ParametersBuilder WithVersion(Argon2Version version) { _version = version; return(this); }
private static string TestFromDraft() { // from draft-irtf-cfrg-argon2-03 // They have this code in version 3 of the draft but it is gone in version 4. var testPwd = Encoding.ASCII.GetBytes("pasword"); var testSalt = Encoding.ASCII.GetBytes("somesalt"); const int testTimeCost = 3; const int testMemoryCost = 1 << 12; const int testParallelism = 1; const Argon2Version testArgon2VersionNumber = Argon2Version.Nineteen; bool Run(byte[] pwd, byte[] salt, int timeCost, int memoryCost, int threads, Argon2Type argon2Type, Argon2Version version, byte[] expectedHash) { using (var hash = new Argon2( new Argon2Config { HashLength = expectedHash.Length, TimeCost = timeCost, MemoryCost = memoryCost, Lanes = threads, Threads = threads, Password = pwd, Salt = salt, Version = version, Type = argon2Type, }).Hash()) { Console.WriteLine($" Actual Hash: {BitConverter.ToString(hash.Buffer)}"); Console.WriteLine($" Expected Hash: {BitConverter.ToString(expectedHash)}"); return(!hash.Buffer.Where((b, i) => b != expectedHash[i]).Any()); } } bool Argon2ISelftest() { byte[] expectedHash = { 0x95, 0x7f, 0xc0, 0x72, 0x7d, 0x83, 0xf4, 0x06, 0x0b, 0xb0, 0xf1, 0x07, 0x1e, 0xb5, 0x90, 0xa1, 0x9a, 0x8c, 0x44, 0x8f, 0xc0, 0x20, 0x94, 0x97, 0xee, 0x4f, 0x54, 0xca, 0x24, 0x1f, 0x3c, 0x90, }; return(Run( testPwd, testSalt, testTimeCost, testMemoryCost, testParallelism, Argon2Type.DataIndependentAddressing, testArgon2VersionNumber, expectedHash)); } bool Argon2DSelftest() { byte[] expectedHash = { 0x0b, 0x3f, 0x09, 0xe7, 0xb8, 0xd0, 0x36, 0xe5, 0x8c, 0xcd, 0x08, 0xf0, 0x8c, 0xb6, 0xba, 0xbf, 0x7e, 0x5e, 0x24, 0x63, 0xc2, 0x6b, 0xcf, 0x2a, 0x9e, 0x4e, 0xa7, 0x0d, 0x74, 0x7c, 0x40, 0x98, }; return(Run( testPwd, testSalt, testTimeCost, testMemoryCost, testParallelism, Argon2Type.DataDependentAddressing, testArgon2VersionNumber, expectedHash)); } bool Argon2IdSelftest() { byte[] expectedHash = { 0xf5, 0x55, 0x35, 0xbf, 0xe9, 0x48, 0x71, 0x00, 0x51, 0x42, 0x4c, 0x74, 0x24, 0xb1, 0x1b, 0xa9, 0xa1, 0x3a, 0x50, 0x23, 0x9b, 0x04, 0x59, 0xf5, 0x6c, 0xa6, 0x95, 0xea, 0x14, 0xbc, 0x19, 0x5e, }; return(Run( testPwd, testSalt, testTimeCost, testMemoryCost, testParallelism, Argon2Type.HybridAddressing, testArgon2VersionNumber, expectedHash)); } var argon2IResult = $"draft-irtf-cfrg-argon2-03 Argon2i - {(Argon2ISelftest() ? "Passed" : "FAIL")}"; Console.WriteLine(argon2IResult); var argon2DResult = $"draft-irtf-cfrg-argon2-03 Argon2d - {(Argon2DSelftest() ? "Passed" : "FAIL")}"; Console.WriteLine(argon2DResult); var argon2IdResult = $"draft-irtf-cfrg-argon2-03 Argon2id - {(Argon2IdSelftest() ? "Passed" : "FAIL")}"; Console.WriteLine(argon2IdResult); return(string.Join($"{Environment.NewLine} ", argon2IResult, argon2DResult, argon2IdResult)); }