예제 #1
0
        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);
            }
        }
예제 #2
0
        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");
            }
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        /// <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));
        }
예제 #6
0
 /// <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);
 }
예제 #7
0
        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}]");
            }
        }
예제 #8
0
        /// <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);
        }
예제 #9
0
        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));
        }
예제 #10
0
            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));
            }
예제 #11
0
        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)));
        }
예제 #12
0
        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}]");
            }
        }
예제 #13
0
        /// <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());
        }
예제 #14
0
        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}]");
            }
        }
예제 #15
0
        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);
        }
예제 #16
0
        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));
        }
예제 #17
0
        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));
        }
예제 #18
0
        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);
        }
예제 #19
0
        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}]");
            }
        }
예제 #20
0
        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));
        }
예제 #21
0
        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);
        }