Пример #1
0
        /// <summary>
        /// Extracts the memory cost, time cost, etc. used to generate the Argon2 hash.
        /// <param name="formattedHash">An encoded Argon2 hash created by the Hash method</param>
        /// <returns>The hash metadata or null if the formattedHash was not a valid encoded Argon2 hash</returns>
        /// </summary>
        public static HashMetadata ExtractMetadata(string formattedHash)
        {
            CheckNull("ExtractMetadata", "formattedHash", formattedHash);

            var context = new Argon2Context
            {
                Out          = Marshal.AllocHGlobal(formattedHash.Length), // ensure the space to hold the hash is long enough
                OutLen       = (uint)formattedHash.Length,
                Pwd          = Marshal.AllocHGlobal(1),
                PwdLen       = 1,
                Salt         = Marshal.AllocHGlobal(formattedHash.Length), // ensure the space to hold the salt is long enough
                SaltLen      = (uint)formattedHash.Length,
                Secret       = Marshal.AllocHGlobal(1),
                SecretLen    = 1,
                AssocData    = Marshal.AllocHGlobal(1),
                AssocDataLen = 1,
                TimeCost     = 0,
                MemoryCost   = 0,
                Lanes        = 0,
                Threads      = 0
            };

            try
            {
                var type   = (formattedHash.StartsWith("$argon2i") ? Argon2Type.Argon2i : Argon2Type.Argon2d);
                var result = (Argon2Error)crypto_decode_string(context, Encoding.ASCII.GetBytes(formattedHash + "\0"), (int)type);

                if (result != Argon2Error.OK)
                {
                    return(null);
                }

                var salt = new byte[context.SaltLen];
                var hash = new byte[context.OutLen];
                Marshal.Copy(context.Salt, salt, 0, salt.Length);
                Marshal.Copy(context.Out, hash, 0, hash.Length);

                return(new HashMetadata
                {
                    ArgonType = type,
                    MemoryCost = context.MemoryCost,
                    TimeCost = context.TimeCost,
                    Parallelism = context.Threads,
                    Salt = salt,
                    Hash = hash
                });
            }
            finally
            {
                Marshal.FreeHGlobal(context.Out);
                Marshal.FreeHGlobal(context.Pwd);
                Marshal.FreeHGlobal(context.Salt);
                Marshal.FreeHGlobal(context.Secret);
                Marshal.FreeHGlobal(context.AssocData);
            }
        }
Пример #2
0
 private static extern int crypto_decode_string(Argon2Context ctx, byte[] str, int type);
Пример #3
0
        /// <summary>
        /// Extracts the memory cost, time cost, etc. used to generate the Argon2 hash.
        /// <param name="formattedHash">An encoded Argon2 hash created by the Hash method</param>
        /// <returns>The hash metadata or null if the formattedHash was not a valid encoded Argon2 hash</returns>
        /// </summary>
        public static HashMetadata ExtractMetadata(string formattedHash)
        {
            CheckNull("ExtractMetadata", "formattedHash", formattedHash);

            var context = new Argon2Context
            {
                Out = Marshal.AllocHGlobal(formattedHash.Length),  // ensure the space to hold the hash is long enough
                OutLen = (uint)formattedHash.Length,
                Pwd = Marshal.AllocHGlobal(1),
                PwdLen = 1,
                Salt = Marshal.AllocHGlobal(formattedHash.Length),  // ensure the space to hold the salt is long enough
                SaltLen = (uint)formattedHash.Length,
                Secret = Marshal.AllocHGlobal(1),
                SecretLen = 1,
                AssocData = Marshal.AllocHGlobal(1),
                AssocDataLen = 1,
                TimeCost = 0,
                MemoryCost = 0,
                Lanes = 0,
                Threads = 0
            };

            try
            {
                var type = (formattedHash.StartsWith("$argon2i") ? Argon2Type.Argon2i : Argon2Type.Argon2d);
                var result = (Argon2Error)crypto_decode_string(context, Encoding.ASCII.GetBytes(formattedHash + "\0"), (int)type);

                if (result != Argon2Error.OK)
                    return null;

                var salt = new byte[context.SaltLen];
                var hash = new byte[context.OutLen];
                Marshal.Copy(context.Salt, salt, 0, salt.Length);
                Marshal.Copy(context.Out, hash, 0, hash.Length);

                return new HashMetadata
                {
                    ArgonType = type,
                    MemoryCost = context.MemoryCost,
                    TimeCost = context.TimeCost,
                    Parallelism = context.Threads,
                    Salt = salt,
                    Hash = hash
                };
            }
            finally
            {
                Marshal.FreeHGlobal(context.Out);
                Marshal.FreeHGlobal(context.Pwd);
                Marshal.FreeHGlobal(context.Salt);
                Marshal.FreeHGlobal(context.Secret);
                Marshal.FreeHGlobal(context.AssocData);
            }
        }
Пример #4
0
 private static extern int crypto_decode_string(Argon2Context ctx, byte[] str, int type);