private bool VerifyPasswordHash(string password, string storedHash, string metadata) { try { var obj = JsonConvert.DeserializeObject(metadata); if (obj == null) { return(false); } dynamic metadataObject = obj; if (metadataObject.HashType != "Argon2d") { return(false); } var passwordBytes = Encoding.UTF8.GetBytes(password); var argon = new Argon2d(passwordBytes) { DegreeOfParallelism = metadataObject.DegreeOfParallelism, MemorySize = metadataObject.MemorySize, Iterations = metadataObject.Iterations, Salt = metadataObject.Salt }; var hashBytes = argon.GetBytes(64); var storedHashBytes = Convert.FromBase64String(storedHash); return(CompareSlowly(hashBytes, storedHashBytes)); } catch (Exception) { return(false); } }
public static byte[] ToRawArgon2(byte[] data, byte[] salt, uint iterations, uint memorySizeKiB, uint parallelism, Argon2Variant variant = Argon2Variant.Argon2id, uint derivedKeyLength = Argon2DerivedKeyLength) { switch (variant) { case Argon2Variant.Argon2d: Argon2d argon2d = new Argon2d(data); argon2d.Salt = salt; argon2d.Iterations = (int)iterations; argon2d.MemorySize = (int)memorySizeKiB; argon2d.DegreeOfParallelism = (int)parallelism; return(argon2d.GetBytes((int)derivedKeyLength)); case Argon2Variant.Argon2i: Argon2i argon2i = new Argon2i(data); argon2i.Salt = salt; argon2i.Iterations = (int)iterations; argon2i.MemorySize = (int)memorySizeKiB; argon2i.DegreeOfParallelism = (int)parallelism; return(argon2i.GetBytes((int)derivedKeyLength)); case Argon2Variant.Argon2id: Argon2id argon2id = new Argon2id(data); argon2id.Salt = salt; argon2id.Iterations = (int)iterations; argon2id.MemorySize = (int)memorySizeKiB; argon2id.DegreeOfParallelism = (int)parallelism; return(argon2id.GetBytes((int)derivedKeyLength)); default: throw new Exception("Invalid Argon2 variant"); } }
private void CreatePasswordHash(string password, out string hash, out string metadata) { byte[] salt = new byte[32]; using (var rng = RandomNumberGenerator.Create()) { rng.GetBytes(salt); } var metadataObject = new { HashType = "Argon2d", DegreeOfParallelism = 2, MemorySize = 65536, Iterations = 10, Salt = salt }; metadata = JsonConvert.SerializeObject(metadataObject); var passwordBytes = Encoding.UTF8.GetBytes(password); var argon = new Argon2d(passwordBytes) { DegreeOfParallelism = metadataObject.DegreeOfParallelism, MemorySize = metadataObject.MemorySize, Iterations = metadataObject.Iterations, Salt = metadataObject.Salt }; var hashBytes = argon.GetBytes(64); hash = Convert.ToBase64String(hashBytes); }
public static byte[] HashPasswordArgon2(byte[] password, byte[] salt, byte[] associatedData = null, byte[] knownSecret = null, Argon2Algorithm algorithm = Argon2Algorithm.i, int degreeOfParallelism = 2, int memorySize = 5120, int iterations = 10, int resultLength = 256) { Argon2 argon2; switch (algorithm) { case Argon2Algorithm.i: argon2 = new Argon2i(password); break; case Argon2Algorithm.d: argon2 = new Argon2d(password); break; case Argon2Algorithm.id: default: throw new NotSupportedException(); } argon2.DegreeOfParallelism = degreeOfParallelism; argon2.MemorySize = memorySize; argon2.Iterations = iterations; argon2.Salt = salt; argon2.AssociatedData = associatedData; argon2.KnownSecret = knownSecret; var hash = argon2.GetBytes(resultLength); argon2.Dispose(); return(hash); }
/// <summary> /// Method for Argon2 algorythm /// </summary> /// <param name="pw"></param> /// <param name="salt"></param> /// <returns> returns enrypted bytes</returns> private byte[] HashPasswordWithSalt(byte[] pw, byte[] salt) { var argon2 = new Argon2d(pw); argon2.DegreeOfParallelism = 16; argon2.MemorySize = 8192; argon2.Iterations = 4; argon2.Salt = salt; return(argon2.GetBytes(128)); }
/// <summary> /// ハッシュ値を取得します /// </summary> /// <param name="password"></param> /// <returns></returns> private (Task <byte[]> hash, byte[] salt) GetArgon2Hash(string password) { argon2 = new Argon2d(Encoding.UTF8.GetBytes(password)) { DegreeOfParallelism = 16, MemorySize = 8192, Iterations = 40, Salt = GetSalt(32) }; return(argon2.GetBytesAsync(32), argon2.Salt); }
public async Task Argon2dRfcVector() { byte[] password = new byte[32]; for (int i = 0; i < 32; i++) { password[i] = 1; } byte[] salt = new byte[16]; for (int i = 0; i < 16; i++) { salt[i] = 2; } byte[] secret = new byte[8]; for (int i = 0; i < 8; i++) { secret[i] = 3; } byte[] data = new byte[12]; for (int i = 0; i < 12; i++) { data[i] = 4; } Argon2d engine = new Argon2d( password, salt, secret, data, 4, 32, 32, 3 ); byte[] output = new byte[32]; await engine.HashAsync(output, CancellationToken.None); byte[] expectedOutput = new byte[32] { 0x51, 0x2b, 0x39, 0x1b, 0x6f, 0x11, 0x62, 0x97, 0x53, 0x71, 0xd3, 0x09, 0x19, 0x73, 0x42, 0x94, 0xf8, 0x68, 0xe3, 0xbe, 0x39, 0x84, 0xf3, 0xc1, 0xa1, 0x3a, 0x4d, 0xb9, 0xfa, 0xbe, 0x4a, 0xcb }; for (int i = 0; i < 16; i++) { Assert.AreEqual(expectedOutput[i], output[i], $"out[{i}]"); } }
/// <summary> /// Asynchronously computes the number of iterations required to get to one second of runtime. /// </summary> /// <returns>A task that resolves to the desired number of Argon2 iterations.</returns> public async Task <ulong> ComputeOneSecondDelay() { CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(1)); Argon2d instance = this.algoParams.CreateArgonInstance(new byte[32]); byte[] buffer = new byte[instance.TagLength]; int iterations = await instance.HashAsync(buffer, cts.Token, Argon2HashingMode.Indefinite).ConfigureAwait(false); return((ulong)iterations); }
public static async Task <byte[]> Argon2IdHashPassword(string password, byte[] salt) { var argon2 = new Argon2d(Encoding.UTF8.GetBytes(password)) { Salt = salt, DegreeOfParallelism = DegreeOfParallelism, Iterations = Iterations, MemorySize = MemorySize }; return(await argon2.GetBytesAsync(16)); }
public byte[] Derive(byte[] password, byte[] salt) { // TODO: Move this to Crypto? var argon2d = new Argon2d(password) { Salt = salt, MemorySize = MemoryCost, Iterations = TimeCost, DegreeOfParallelism = Parallelism, }; return(argon2d.GetBytes(32)); }
public string GetEncryptedPasswordAsString() { var argon2 = new Argon2d(Encoding.UTF8.GetBytes(plainPassword)) { Salt = Encoding.UTF8.GetBytes(salt.ToString()), KnownSecret = Encoding.UTF8.GetBytes(Resource.String.pepper.ToString()), DegreeOfParallelism = 16, Iterations = 40, MemorySize = 8 * 1024 }; return(Encoding.UTF8.GetString(argon2.GetBytes(16))); }
public async Task Argon2HeavyMultiThread() { byte[] password = new byte[32]; for (int i = 0; i < 32; i++) { password[i] = 1; } byte[] salt = new byte[16]; for (int i = 0; i < 16; i++) { salt[i] = 2; } byte[] secret = new byte[8]; for (int i = 0; i < 8; i++) { secret[i] = 3; } byte[] data = new byte[12]; for (int i = 0; i < 12; i++) { data[i] = 4; } Argon2d engine = new Argon2d( password, salt, secret, data, 8, 16, 40960, 8 ); byte[] output = new byte[16]; await engine.HashAsync(output, CancellationToken.None); byte[] expectedOutput = new byte[16] { 0x23, 0xb8, 0x9e, 0x2f, 0x01, 0xce, 0x60, 0xa1, 0xd3, 0x2b, 0xe8, 0xa0, 0x92, 0x64, 0xc2, 0x80 }; for (int i = 0; i < 16; i++) { Assert.AreEqual(expectedOutput[i], output[i], $"out[{i}]"); } }
/// <summary> /// Asynchronously transforms the user's key. /// </summary> /// <param name="rawKey">The key to transform.</param> /// <param name="token">Token used to cancel the transform task.</param> /// <returns>The transformed key.</returns> public async Task <IBuffer> TransformKeyAsync(IBuffer rawKey, CancellationToken token) { if (rawKey == null) { throw new ArgumentNullException(nameof(rawKey)); } Argon2d instance = this.algoParams.CreateArgonInstance(rawKey.ToArray()); byte[] buffer = new byte[instance.TagLength]; await instance.HashAsync(buffer, token).ConfigureAwait(false); return(buffer.AsBuffer()); }
public async Task Argon2LongerSegments() { byte[] password = new byte[32]; for (int i = 0; i < 32; i++) { password[i] = 1; } byte[] salt = new byte[16]; for (int i = 0; i < 16; i++) { salt[i] = 2; } byte[] secret = new byte[8]; for (int i = 0; i < 8; i++) { secret[i] = 3; } byte[] data = new byte[12]; for (int i = 0; i < 12; i++) { data[i] = 4; } Argon2d engine = new Argon2d( password, salt, secret, data, 2, 8, 32, 5 ); byte[] output = new byte[8]; await engine.HashAsync(output, CancellationToken.None); byte[] expectedOutput = new byte[8] { 0xa4, 0x26, 0xcc, 0xef, 0x1b, 0x72, 0x4a, 0xaf }; for (int i = 0; i < 8; i++) { Assert.AreEqual(expectedOutput[i], output[i], $"out[{i}]"); } }
private static string GenerateHash(string password, Guid id) { var argon2 = new Argon2d(Encoding.UTF8.GetBytes(password)) { DegreeOfParallelism = 1, MemorySize = 256, Iterations = 2, Salt = Encoding.UTF8.GetBytes(id.ToString()) }; var hash = argon2.GetBytes(128); var hashedString = Convert.ToBase64String(hash); return(hashedString); }
private Task <byte[]> GetArgon2Hash(string password, FileStream fs) { argon2 = new Argon2d(Encoding.UTF8.GetBytes(password)) { DegreeOfParallelism = 16, MemorySize = 8192, Iterations = 40 }; byte[] salt = new byte[32]; fs.Read(salt, 0, 32);//埋め込んでいたSaltを読み取る argon2.Salt = salt; return(argon2.GetBytesAsync(32)); }
private static string CreateHashedPassword(string password, string salt) { byte[] passwordBytesTable = Encoding.ASCII.GetBytes(password); byte[] saltBytesTable = Encoding.ASCII.GetBytes(salt); Argon2 hashedPassword = new Argon2d(passwordBytesTable) { Salt = saltBytesTable, Iterations = 6, MemorySize = 258, DegreeOfParallelism = 8 }; byte[] bytesHashedPassword = hashedPassword.GetBytes(128); return(Encoding.UTF8.GetString(bytesHashedPassword)); }
private Argon2d SetHashObject(string password, HashingConfig config) { var bytePassword = Encoding.ASCII.GetBytes(password); byte[] userUuidBytes = Encoding.ASCII.GetBytes(config.AssociatedData); byte[] byteSecret = Encoding.ASCII.GetBytes(config.KnownSecret); var argon2 = new Argon2d(bytePassword); argon2.DegreeOfParallelism = config.DegreeOfParallelism; argon2.MemorySize = config.MemorySize; argon2.Iterations = config.Iterations; argon2.AssociatedData = userUuidBytes; argon2.KnownSecret = byteSecret; return(argon2); }
public async Task Argon2SimpleSingleThread() { byte[] password = new byte[16]; for (int i = 0; i < 16; i++) { password[i] = 0; } byte[] salt = new byte[16]; for (int i = 0; i < 16; i++) { salt[i] = 1; } Argon2d engine = new Argon2d( password, salt, new byte[0], new byte[0], 1, 16, 8, 3 ); byte[] output = new byte[16]; await engine.HashAsync(output, CancellationToken.None); byte[] expectedOutput = new byte[16] { 0x6d, 0x1a, 0x2c, 0x5f, 0x65, 0x4a, 0x27, 0x7e, 0x03, 0x9e, 0xad, 0xe2, 0x03, 0x68, 0x21, 0x61 }; for (int i = 0; i < 16; i++) { Assert.AreEqual(expectedOutput[i], output[i], $"out[{i}]"); } }
internal static byte[] DeriveMasterKeyArgon2(byte[] compositeMasterKey, Dictionary <string, object> parameters) { InternalErrorException MakeError(string name) => new InternalErrorException($"Argon2 KDF parameter '{name}' not found or it is of incorrect type"); if (!(parameters.GetOrDefault("S", null) is byte[] salt)) { throw MakeError("S"); } if (!(parameters.GetOrDefault("I", null) is ulong iterations)) { throw MakeError("I"); } if (!(parameters.GetOrDefault("M", null) is ulong memoryCost)) { throw MakeError("M"); } if (!(parameters.GetOrDefault("P", null) is uint parallelism)) { throw MakeError("P"); } // TODO: Do we need to support "K" and "A"? using var argon2d = new Argon2d(compositeMasterKey) { Salt = salt, MemorySize = (int)(memoryCost / 1024), Iterations = (int)iterations, DegreeOfParallelism = (int)parallelism, }; return(argon2d.GetBytes(32)); }
public static string CalcArgon2(string password, string salt) { // defaults int iterations = 3; int memoryCost = 1024; int parallelism = 2; int hashLength = 20; string justSalt = salt; Argon2 argon2 = null; // check if salt has settings encoded in it if (salt.StartsWith("$argon2")) { // apparently has settings encoded in it - use these if (salt.StartsWith("$argon2i")) { argon2 = new Argon2i(Encoding.UTF8.GetBytes(password)); } String[] saltComponents = salt.Split('$'); if (saltComponents.Length == 5) { // make sure Base64 encoded salt length is a multiple of 4 - if not pad justSalt = Encoding.UTF8.GetString(DecodeBase64(saltComponents[4])); String[] saltParams = saltComponents[3].Split(','); foreach (string saltParam in saltParams) { String[] saltParamValues = saltParam.Split('='); switch (saltParamValues[0]) { case "t": if (!int.TryParse(saltParamValues[1], out iterations)) { iterations = 3; } break; case "m": if (!int.TryParse(saltParamValues[1], out memoryCost)) { memoryCost = 1024; } break; case "p": if (!int.TryParse(saltParamValues[1], out parallelism)) { parallelism = 2; } break; case "l": if (!int.TryParse(saltParamValues[1], out hashLength)) { hashLength = 20; } break; } } } } if (argon2 == null) { argon2 = new Argon2d(Encoding.UTF8.GetBytes(password)); } argon2.DegreeOfParallelism = parallelism; argon2.MemorySize = memoryCost; argon2.Iterations = iterations; argon2.Salt = Encoding.UTF8.GetBytes(justSalt); var bytes = argon2.GetBytes(hashLength); var result = BitConverter.ToString(bytes).Replace("-", "").ToLower(); return(result); }