private static void InitialKat(byte[] buffer, Argon2 hasher) { if (VectorFileName != null) { using (var fout = new FileStream(VectorFileName, FileMode.Append)) using (var sout = new StreamWriter(fout)) { sout.WriteLine("======================================="); switch (hasher.config.Type) { case Argon2Type.DataDependentAddressing: sout.WriteLine($"Argon2d version number {(int)hasher.config.Version}"); break; case Argon2Type.DataIndependentAddressing: sout.WriteLine($"Argon2i version number {(int)hasher.config.Version}"); break; } sout.WriteLine("======================================="); sout.WriteLine( $"Memory: {hasher.config.MemoryCost} KiB, Iterations: {hasher.config.TimeCost}, " + $"Parallelism: {hasher.config.Lanes} lanes, Tag length: " + $"{hasher.config.HashLength} bytes"); var pwText = hasher.config.ClearPassword ? "CLEARED" : BitConverter.ToString(hasher.config.Password).ToLower().Replace('-', ' '); sout.WriteLine($"Password[{hasher.config.Password.Length}]: {pwText} "); sout.WriteLine( $"Salt[{hasher.config.Salt?.Length ?? 0}]: " + $"{(hasher.config.Salt == null ? string.Empty : BitConverter.ToString(hasher.config.Salt).ToLower().Replace('-', ' '))} "); sout.WriteLine( $"Secret[{hasher.config.Secret?.Length ?? 0}]: " + $"{(hasher.config.Secret == null ? string.Empty : BitConverter.ToString(hasher.config.Secret).ToLower().Replace('-', ' '))} "); sout.WriteLine( $"Associated data[{hasher.config.AssociatedData?.Length ?? 0}]: " + $"{(hasher.config.AssociatedData == null ? string.Empty : BitConverter.ToString(hasher.config.AssociatedData).ToLower().Replace('-', ' '))} "); sout.WriteLine( $"Pre-hashing digest: {BitConverter.ToString(buffer, 0, PrehashDigestLength).ToLower().Replace('-', ' ')} "); } } }
private static void InternalKat(Argon2 hasher, int passNumber) { if (VectorFileName != null) { using (var fout = new FileStream(VectorFileName, FileMode.Append)) using (var sout = new StreamWriter(fout)) { sout.WriteLine(); sout.WriteLine($" After pass {passNumber}:"); for (int i = 0; i < hasher.MemoryBlockCount; ++i) { int howManyWords = (hasher.MemoryBlockCount > QwordsInBlock) ? 1 : QwordsInBlock; for (int j = 0; j < howManyWords; ++j) { sout.WriteLine($"Block {i:D4} [{j, 3}]: {hasher.Memory[i][j] :x16}"); } } } } }
/// <summary> /// Verify the given Argon2 hash as being that of the given password. /// </summary> /// <param name="encoded"> /// The Argon2 hash string. This has the actual hash along with other parameters used in the hash. /// </param> /// <param name="configToVerify"> /// The configuration that contains the values used to created <paramref name="encoded"/>. /// </param> /// <returns> /// True on success; false otherwise. /// </returns> public static bool Verify( string encoded, Argon2Config configToVerify) { SecureArray <byte> hash = null; try { if (!configToVerify.DecodeString(encoded, out hash) || hash == null) { return(false); } using var hasherToVerify = new Argon2(configToVerify); using var hashToVerify = hasherToVerify.Hash(); return(!hash.Buffer.Where((b, i) => b != hashToVerify[i]).Any()); } finally { hash?.Dispose(); } }