Пример #1
0
        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;
        }
Пример #2
0
 /// <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);
 }
 /// <summary>
 /// Hash the given password to a Argon2 hash string.
 /// </summary>
 /// <param name="password">
 /// The password to hash. Gets UTF-8 encoded before hashing.
 /// </param>
 /// <param name="timeCost">
 /// The time cost to use. Defaults to 3.
 /// </param>
 /// <param name="memoryCost">
 /// The memory cost to use. Defaults to 65536 (64K).
 /// </param>
 /// <param name="parallelism">
 /// The parallelism to use. Default to 1 (single threaded).
 /// </param>
 /// <param name="type">
 /// Data-dependent or data-independent. Defaults to data-independent
 /// (as recommended for password hashing).
 /// </param>
 /// <param name="hashLength">
 /// The length of the hash in bytes. Note, the string returned base-64
 /// encodes this with other parameters so the resulting string is
 /// significantly longer.
 /// </param>
 /// <returns>
 /// The Argon2 hash of the given password.
 /// </returns>
 public static string Hash(
     string password,
     int timeCost    = 3,
     int memoryCost  = 65536,
     int parallelism = 1,
     Argon2Type type = Argon2Type.DataIndependentAddressing,
     int hashLength  = 32)
 {
     using (var passwordBuf = new SecureArray <byte>(Encoding.UTF8.GetByteCount(password)))
     {
         byte[] salt = new byte[16];
         System.Security.Cryptography.RandomNumberGenerator.Create().GetBytes(salt);
         Encoding.UTF8.GetBytes(password, 0, password.Length, passwordBuf.Buffer, 0);
         var argon2 =
             new Argon2(
                 new Argon2Config
         {
             TimeCost   = timeCost,
             MemoryCost = memoryCost,
             Threads    = parallelism,
             Lanes      = parallelism,
             Password   = passwordBuf.Buffer,
             Salt       = salt,
             HashLength = hashLength,
             Version    = Argon2Version.Nineteen
         });
         using (var hash = argon2.Hash())
         {
             return(argon2.config.EncodeString(hash.Buffer));
         }
     }
 }
 /// <summary>
 /// Hash the given password to a Argon2 hash string.
 /// </summary>
 /// <param name="password">
 /// The password to hash. Gets UTF-8 encoded before hashing.
 /// </param>
 /// <param name="secret">
 /// The secret to use in creating the hash. UTF-8 encoded before hashing. May be null. A
 /// <see cref="string"/>.<see cref="string.Empty"/> is treated the same as null.
 /// </param>
 /// <param name="timeCost">
 /// The time cost to use. Defaults to 3.
 /// </param>
 /// <param name="memoryCost">
 /// The memory cost to use. Defaults to 65536 (64K).
 /// </param>
 /// <param name="parallelism">
 /// The parallelism to use. Default to 1 (single threaded).
 /// </param>
 /// <param name="type">
 /// Data-dependent, data-independent, or hybrid. Defaults to hybrid
 /// (as recommended for password hashing).
 /// </param>
 /// <param name="hashLength">
 /// The length of the hash in bytes. Note, the string returned base-64
 /// encodes this with other parameters so the resulting string is
 /// significantly longer.
 /// </param>
 /// <param name="secureArrayCall">
 /// The methods that get called to secure arrays. A null value defaults to <see cref="SecureArray"/>.<see cref="SecureArray.DefaultCall"/>.
 /// </param>
 /// <returns>
 /// The Argon2 hash of the given password.
 /// </returns>
 public static string Hash(
     byte[] password,
     byte[] secret,
     int timeCost    = 3,
     int memoryCost  = 65536,
     int parallelism = 1,
     Argon2Type type = Argon2Type.HybridAddressing,
     int hashLength  = 32,
     SecureArrayCall secureArrayCall = null)
 {
     byte[] salt = new byte[16];
     RandomNumberGenerator.Create().GetBytes(salt);
     return(Hash(
                new Argon2Config
     {
         TimeCost = timeCost,
         MemoryCost = memoryCost,
         Threads = parallelism,
         Lanes = parallelism,
         Password = password,
         Secret = secret,
         Salt = salt,
         HashLength = hashLength,
         Version = Argon2Version.Nineteen,
         Type = type,
     }));
 }
Пример #5
0
 public Argon2Hasher(int hashLength = 32, Argon2Type argonType = Argon2Type.Argon2I, uint iterations = 10, uint costMemKb = 131072, uint parallelism = 1)
 {
     _iterations  = iterations;
     _costMemKb   = costMemKb;
     _parallelism = parallelism;
     _argonType   = argonType;
     _hashLength  = hashLength;
 }
Пример #6
0
        } // end cctr

        protected Argon2ParametersBuilder(Argon2Type a_Type)
        {
            Lanes      = DEFAULT_LANES;
            Memory     = 1 << DEFAULT_MEMORY_COST;
            Iterations = DEFAULT_ITERATIONS;
            Type       = a_Type;
            Version    = DEFAULT_VERSION;
        } //
Пример #7
0
        public Argon2Kdf(Argon2Type t)
        {
            if ((t != Argon2Type.D) && (t != Argon2Type.ID))
            {
                throw new NotSupportedException();
            }

            m_t = t;
        }
Пример #8
0
 /// <summary>
 /// Initialize the Argon2 PasswordHasher with the performance and algorithm settings to use while hashing
 /// <param name="timeCost">How many iterations of the Argon2 hash to perform (default: 3, must be at least 1)</param>
 /// <param name="memoryCost">How much memory to use while hashing in kibibytes (KiB) (default: 8192 KiB [8 MiB], must be at least 8 KiB)</param>
 /// <param name="parallelism">How many threads to use while hashing (default: 1, must be at least 1)</param>
 /// <param name="argonType">The type of Argon2 hashing algorithm to use (Independent [default] or Dependent)</param>
 /// <param name="hashLength">The length of the resulting hash in bytes (default: 32)</param>
 /// </summary>
 public PasswordHasher(uint timeCost = 3, uint memoryCost = 8192, uint parallelism = 1, Argon2Type argonType = Argon2Type.Argon2i, uint hashLength = 32)
 {
     TimeCost       = timeCost;
     MemoryCost     = memoryCost;
     Parallelism    = parallelism;
     ArgonType      = argonType;
     HashLength     = hashLength;
     StringEncoding = Encoding.UTF8;
 }
 /// <summary>
 /// Hash the given password to a Argon2 hash string.
 /// </summary>
 /// <param name="password">
 /// The password to hash. Gets UTF-8 encoded before hashing.
 /// </param>
 /// <param name="timeCost">
 /// The time cost to use. Defaults to 3.
 /// </param>
 /// <param name="memoryCost">
 /// The memory cost to use. Defaults to 65536 (64K).
 /// </param>
 /// <param name="parallelism">
 /// The parallelism to use. Default to 1 (single threaded).
 /// </param>
 /// <param name="type">
 /// Data-dependent, data-independent, or hybrid. Defaults to hybrid
 /// (as recommended for password hashing).
 /// </param>
 /// <param name="hashLength">
 /// The length of the hash in bytes. Note, the string returned base-64
 /// encodes this with other parameters so the resulting string is
 /// significantly longer.
 /// </param>
 /// <param name="secureArrayCall">
 /// The methods that get called to secure arrays. A null value defaults to <see cref="SecureArray"/>.<see cref="SecureArray.DefaultCall"/>.
 /// </param>
 /// <returns>
 /// The Argon2 hash of the given password.
 /// </returns>
 public static string Hash(
     string password,
     int timeCost    = 3,
     int memoryCost  = 65536,
     int parallelism = 1,
     Argon2Type type = Argon2Type.HybridAddressing,
     int hashLength  = 32,
     SecureArrayCall secureArrayCall = null)
 {
     return(Hash(password, null, timeCost, memoryCost, parallelism, type, hashLength, secureArrayCall));
 }
Пример #10
0
 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;
 }
Пример #11
0
        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
Пример #12
0
        /// <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;
        }
Пример #13
0
 public Argon2PasswordHasher(
     uint time                 = 3,
     uint memory               = 8192,
     uint parallel             = 1,
     Argon2Type type           = Argon2Type.Argon2i,
     uint hashLength           = 32,
     uint saltLength           = 16,
     Encoding encoding         = null,
     RandomNumberGenerator rng = null
     )
 {
     TimeCost       = time;
     MemoryCost     = memory;
     Parallelism    = parallel;
     ArgonType      = type;
     HashLength     = hashLength;
     SaltLength     = saltLength;
     StringEncoding = encoding ?? Encoding.UTF8;
     Rng            = rng ?? RandomNumberGenerator.Create();
 }
Пример #14
0
        /// <summary>
        /// Hash the given password to a Argon2 hash string.
        /// </summary>
        /// <param name="password">
        /// The password to hash. Gets UTF-8 encoded before hashing.
        /// </param>
        /// <param name="secret">
        /// The secret to use in creating the hash. UTF-8 encoded before hashing. May be null. A
        /// <see cref="string"/>.<see cref="string.Empty"/> is treated the same as null.
        /// </param>
        /// <param name="timeCost">
        /// The time cost to use. Defaults to 3.
        /// </param>
        /// <param name="memoryCost">
        /// The memory cost to use. Defaults to 65536 (64K).
        /// </param>
        /// <param name="parallelism">
        /// The parallelism to use. Default to 1 (single threaded).
        /// </param>
        /// <param name="type">
        /// Data-dependent, data-independent, or hybrid. Defaults to hybrid
        /// (as recommended for password hashing).
        /// </param>
        /// <param name="hashLength">
        /// The length of the hash in bytes. Note, the string returned base-64
        /// encodes this with other parameters so the resulting string is
        /// significantly longer.
        /// </param>
        /// <param name="secureArrayCall">
        /// The methods that get called to secure arrays. A null value defaults to <see cref="SecureArray"/>.<see cref="SecureArray.DefaultCall"/>.
        /// </param>
        /// <returns>
        /// The Argon2 hash of the given password.
        /// </returns>
        public static string Hash(
            string password,
            string secret,
            int timeCost    = 3,
            int memoryCost  = 65536,
            int parallelism = 1,
            Argon2Type type = Argon2Type.HybridAddressing,
            int hashLength  = 32,
            SecureArrayCall secureArrayCall = null)
        {
            var secretBuf = string.IsNullOrEmpty(secret)
                                ? null
                                : SecureArray <byte> .Best(Encoding.UTF8.GetByteCount(secret), secureArrayCall);

            try
            {
                if (secretBuf != null)
                {
                    Encoding.UTF8.GetBytes(secret, 0, secret.Length, secretBuf.Buffer, 0);
                }

                using (var passwordBuf = SecureArray <byte> .Best(Encoding.UTF8.GetByteCount(password), secureArrayCall))
                {
                    Encoding.UTF8.GetBytes(password, 0, password.Length, passwordBuf.Buffer, 0);
                    return(Hash(
                               passwordBuf.Buffer,
                               secretBuf?.Buffer,
                               timeCost,
                               memoryCost,
                               parallelism,
                               type,
                               hashLength,
                               secureArrayCall));
                }
            }
            finally
            {
                secretBuf?.Dispose();
            }
        }
Пример #15
0
        static void Main(string[] args)
        {
            uint       m_cost      = (uint)(1 << LOG_M_COST_DEF);
            uint       t_cost      = T_COST_DEF;
            uint       threads     = THREADS_DEF;
            uint       hash_len    = HASH_LEN_DEF;
            Argon2Type type        = Argon2Type.Argon2i;
            bool       rawOnly     = false;
            bool       encodedOnly = false;

            if (args.Length == 0)
            {
                Usage();
                Environment.Exit(30);
            }

            var pwd = Console.In.ReadToEnd();

            if (pwd.EndsWith("\r\n"))
            {
                pwd = pwd.Substring(0, pwd.Length - 2);
            }
            else if (pwd.EndsWith("\n"))
            {
                pwd = pwd.Substring(0, pwd.Length - 1);
            }

            if (args[0].Length > SALT_LEN)
            {
                Fatal("salt too long");
            }

            var salt = args[0] + new string('\0', SALT_LEN - args[0].Length);

            for (var i = 1; i < args.Length; i++)
            {
                switch (args[i])
                {
                case "-m": m_cost = (1U << (int)ReadArg(args, ++i, "-m", 1, 32)); break;

                case "-t": t_cost = ReadArg(args, ++i, "-t", 1, int.MaxValue); break;

                case "-p": threads = ReadArg(args, ++i, "-p", 1, 0xFFFFFF); break;

                case "-h": hash_len = ReadArg(args, ++i, "-h", 4, int.MaxValue); break;

                case "-d": type = Argon2Type.Argon2d; break;

                case "-e":
                case "-encoded":
                    encodedOnly = true;
                    break;

                case "-r":
                case "-raw":
                    rawOnly = true;
                    break;

                default:
                    Fatal("unknown argument " + args[i]);
                    break;
                }
            }

            if (encodedOnly && rawOnly)
            {
                Fatal("Only one of -e or -r may be specified");
            }

            if (!encodedOnly && !rawOnly)
            {
                Console.WriteLine("Type:\t\t{0}", type);
                Console.WriteLine("Iterations:\t{0}", t_cost);
                Console.WriteLine("Memory:\t\t{0} KiB", m_cost);
                Console.WriteLine("Parallelism:\t{0}", threads);
            }

            var hasher = new PasswordHasher(t_cost, m_cost, threads, type, hash_len);

            Run(hasher, pwd, salt, rawOnly, encodedOnly);
        }
Пример #16
0
        public static string CalcArgon2(string password, string salt)
        {
            // defaults
            uint       iterations  = 3;
            uint       memoryCost  = 1024;
            uint       parallelism = 2;
            uint       hashLength  = 20;
            Argon2Type argonType   = Argon2Type.Argon2d;
            string     justSalt    = salt;

            // check if salt has settings encoded in it
            if (salt.StartsWith("$argon2"))
            {
                // apparently has settings encoded in it - use these
                if (salt.StartsWith("$argon2i"))
                {
                    argonType = Argon2Type.Argon2i;
                }

                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 (!uint.TryParse(saltParamValues[1], out iterations))
                            {
                                iterations = 3;
                            }
                            break;

                        case "m":
                            if (!uint.TryParse(saltParamValues[1], out memoryCost))
                            {
                                memoryCost = 1024;
                            }
                            break;

                        case "p":
                            if (!uint.TryParse(saltParamValues[1], out parallelism))
                            {
                                parallelism = 2;
                            }
                            break;

                        case "l":
                            if (!uint.TryParse(saltParamValues[1], out hashLength))
                            {
                                hashLength = 20;
                            }
                            break;
                        }
                    }
                }
            }

            return(new PasswordHasher(iterations, memoryCost, parallelism, argonType, hashLength).Hash(password, justSalt));
        }
Пример #17
0
 /// <summary> Creates an Argon2 <see cref="HashFn"/> with the given parameters. </summary>
 /// <param name="iterations"> Iterations/'timeCost' to use </param>
 /// <param name="secret"> Optional secret to use </param>
 /// <param name="memoryCost"> Memory Cost to use </param>
 /// <param name="threads"> Threads to use </param>
 /// <param name="type"> Variant of Argon2 to use </param>
 /// <param name="size"> Hash length </param>
 /// <returns> <see cref="HashFn"/> that performs Argon2 with the given parameters </returns>
 public static HashFn Argon2Hash(int iterations = 3, int memoryCost = 1024 *32, int threads = 8, string secret = null, Argon2Type type = Argon2Type.HybridAddressing, int size = 32)
 {
     return((pass) => {
         DateTime start = DateTime.UtcNow;
         var result = Argon2.Hash(pass, secret, iterations, memoryCost, threads, type, size);
         DateTime end = DateTime.UtcNow;
         Log.Debug($"Argon2.Hash({iterations}, {memoryCost}, {threads}, {type}, {size}) completed in {(end - start).TotalMilliseconds}ms");
         return result;
     });
 }
Пример #18
0
 /// <summary>
 /// Initialize the Argon2 PasswordHasher with the performance and algorithm settings to use while hashing
 /// <param name="timeCost">How many iterations of the Argon2 hash to perform (default: 3, must be at least 1)</param>
 /// <param name="memoryCost">How much memory to use while hashing in kibibytes (KiB) (default: 8192 KiB [8 MiB], must be at least 8 KiB)</param>
 /// <param name="parallelism">How many threads to use while hashing (default: 1, must be at least 1)</param>
 /// <param name="argonType">The type of Argon2 hashing algorithm to use (Independent [default] or Dependent)</param>
 /// <param name="hashLength">The length of the resulting hash in bytes (default: 32)</param>
 /// </summary>
 public PasswordHasher(uint timeCost = 3, uint memoryCost = 8192, uint parallelism = 1, Argon2Type argonType = Argon2Type.Argon2i, uint hashLength = 32)
 {
     TimeCost = timeCost;
     MemoryCost = memoryCost;
     Parallelism = parallelism;
     ArgonType = argonType;
     HashLength = hashLength;
     StringEncoding = Encoding.UTF8;
 }
Пример #19
0
 public Argon2ParametersBuilder WithType(Argon2Type type)
 {
     _type = type;
     return(this);
 }