Esempio n. 1
0
        /// <summary>Returns the hash in a string format, which includes the generated salt.</summary>
        /// <param name="password">The password.</param>
        /// <param name="opsLimit">Represents a maximum amount of computations to perform.</param>
        /// <param name="memLimit">Is the maximum amount of RAM that the function will use, in bytes.</param>
        /// <returns>Returns an zero-terminated ASCII encoded string of the computed password and hash.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="OutOfMemoryException"></exception>
        public static string ArgonHashString(string password, long opsLimit, int memLimit)
        {
            if (password == null)
            {
                throw new ArgumentNullException("password", "Password cannot be null");
            }

            if (opsLimit < 3)
            {
                throw new ArgumentOutOfRangeException("opsLimit",
                                                      "opsLimit the number of passes, has to be at least 3");
            }

            if (memLimit <= 0)
            {
                throw new ArgumentOutOfRangeException("memLimit", "memLimit cannot be zero or negative");
            }

            byte[] buffer = new byte[ARGON_STRBYTES];
            byte[] pass   = Encoding.UTF8.GetBytes(password);

            SodiumCore.Init();
            int ret = SodiumLibrary.crypto_pwhash_str(buffer, pass, pass.GetLongLength(0), opsLimit, memLimit);

            if (ret != 0)
            {
                throw new OutOfMemoryException(
                          "Internal error, hash failed (usually because the operating system refused to allocate the amount of requested memory).");
            }

            return(Encoding.UTF8.GetString(buffer));
        }
Esempio n. 2
0
        /// <summary>Returns the hash in a string format, which includes the generated salt.</summary>
        /// <param name="password">The password.</param>
        /// <param name="opsLimit">Represents a maximum amount of computations to perform.</param>
        /// <param name="memLimit">Is the maximum amount of RAM that the function will use, in bytes.</param>
        /// <returns>Returns an zero-terminated ASCII encoded string of the computed password and hash.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="OutOfMemoryException"></exception>
        public static string ScryptHashString(string password, long opsLimit, int memLimit)
        {
            if (password == null)
            {
                throw new ArgumentNullException("password", "Password cannot be null");
            }

            if (opsLimit <= 0)
            {
                throw new ArgumentOutOfRangeException("opsLimit", "opsLimit cannot be zero or negative");
            }

            if (memLimit <= 0)
            {
                throw new ArgumentOutOfRangeException("memLimit", "memLimit cannot be zero or negative");
            }

            var buffer = new byte[SCRYPT_SALSA208_SHA256_STRBYTES];
            var pass   = Encoding.UTF8.GetBytes(password);

            SodiumCore.Init();
            var ret = SodiumLibrary.crypto_pwhash_scryptsalsa208sha256_str(buffer, pass, pass.Length, opsLimit, memLimit);

            if (ret != 0)
            {
                throw new OutOfMemoryException("Internal error, hash failed (usually because the operating system refused to allocate the amount of requested memory).");
            }

            return(Encoding.UTF8.GetString(buffer));
        }
Esempio n. 3
0
        public static byte[] ScryptHashLowLevel(byte[] password, byte[] salt, long N, int R, int P, uint bufferLength = SCRYPT_SALSA208_SHA256_STRBYTES)
        {
            var buffer = new byte[bufferLength];

            SodiumCore.Init();
            var ret = SodiumLibrary.crypto_pwhash_scryptsalsa208sha256_ll(password, password.Length, salt, salt.Length, N, R, P, buffer, buffer.Length);

            if (ret != 0)
            {
                throw new OutOfMemoryException("Internal error, hash failed (usually because the operating system refused to allocate the amount of requested memory).");
            }

            return(buffer);
        }
Esempio n. 4
0
        /// <summary>
        ///     Derives a secret key of any size from a password and a salt.
        /// </summary>
        /// <param name="password">The password.</param>
        /// <param name="salt">The salt.</param>
        /// <param name="opsLimit">Represents a maximum amount of computations to perform.</param>
        /// <param name="memLimit">Is the maximum amount of RAM that the function will use, in bytes.</param>
        /// <param name="outputLength">The length of the computed output array.</param>
        /// <returns>Returns a byte array of the given size.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="SaltOutOfRangeException"></exception>
        /// <exception cref="OutOfMemoryException"></exception>
        public static byte[] ArgonHashBinary(byte[] password, byte[] salt, long opsLimit, int memLimit,
                                             long outputLength = ARGON_SALTBYTES)
        {
            if (password == null)
            {
                throw new ArgumentNullException("password", "Password cannot be null");
            }

            if (salt == null)
            {
                throw new ArgumentNullException("salt", "Salt cannot be null");
            }

            if (salt.Length != ARGON_SALTBYTES)
            {
                throw new SaltOutOfRangeException(string.Format("Salt must be {0} bytes in length.", ARGON_SALTBYTES));
            }

            if (opsLimit < 2)
            {
                throw new ArgumentOutOfRangeException("opsLimit",
                                                      "opsLimit the number of passes, has to be at least 3");
            }

            if (memLimit <= 0)
            {
                throw new ArgumentOutOfRangeException("memLimit", "memLimit cannot be zero or negative");
            }

            if (outputLength <= 0)
            {
                throw new ArgumentOutOfRangeException("outputLength", "OutputLength cannot be zero or negative");
            }

            byte[] buffer = new byte[outputLength];

            SodiumCore.Init();

            int ret = SodiumLibrary.crypto_pwhash(buffer, buffer.Length, password, password.GetLongLength(0), salt,
                                                  opsLimit, memLimit, ARGON_ALGORITHM_DEFAULT);

            if (ret != 0)
            {
                throw new OutOfMemoryException(
                          "Internal error, hash failed (usually because the operating system refused to allocate the amount of requested memory).");
            }

            return(buffer);
        }
Esempio n. 5
0
        /// <summary>Verifies that a hash generated with ScryptHashString matches the supplied password.</summary>
        /// <param name="hash">The hash.</param>
        /// <param name="password">The password.</param>
        /// <returns><c>true</c> on success; otherwise, <c>false</c>.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static bool ScryptHashStringVerify(byte[] hash, byte[] password)
        {
            if (password == null)
            {
                throw new ArgumentNullException(nameof(password), "Password cannot be null");
            }
            if (hash == null)
            {
                throw new ArgumentNullException(nameof(hash), "Hash cannot be null");
            }

            SodiumCore.Init();

            var ret = SodiumLibrary.crypto_pwhash_scryptsalsa208sha256_str_verify(hash, password, password.Length);

            return(ret == 0);
        }
Esempio n. 6
0
        /// <summary>
        /// Derives a secret key of any size from a password and a salt.
        /// </summary>
        /// <param name="password">The password.</param>
        /// <param name="salt">The salt.</param>
        /// <param name="opsLimit">Represents a maximum amount of computations to perform.</param>
        /// <param name="memLimit">Is the maximum amount of RAM that the function will use, in bytes.</param>
        /// <param name="outputLength">The length of the computed output array.</param>
        /// <param name="alg">Argon Algorithm</param>
        /// <returns>Returns a byte array of the given size.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="SaltOutOfRangeException"></exception>
        /// <exception cref="OutOfMemoryException"></exception>
        public static byte[] ArgonHashBinary(byte[] password, byte[] salt, long opsLimit, int memLimit, long outputLength = ARGON_SALTBYTES,
                                             ArgonAlgorithm alg = ArgonAlgorithm.Argon_2I13)
        {
            if (password == null)
            {
                throw new ArgumentNullException(nameof(password), "Password cannot be null");
            }

            if (salt == null)
            {
                throw new ArgumentNullException(nameof(salt), "Salt cannot be null");
            }

            if (salt.Length != ARGON_SALTBYTES)
            {
                throw new SaltOutOfRangeException($"Salt must be {ARGON_SALTBYTES} bytes in length.");
            }

            if (opsLimit < 3)
            {
                throw new ArgumentOutOfRangeException(nameof(opsLimit), "opsLimit the number of passes, has to be at least 3");
            }

            if (memLimit <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(memLimit), "memLimit cannot be zero or negative");
            }

            if (outputLength <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(outputLength), "OutputLength cannot be zero or negative");
            }

            var buffer = new byte[outputLength];

            SodiumCore.Init();

            var ret = SodiumLibrary.crypto_pwhash(buffer, buffer.Length, password, password.Length, salt, opsLimit, memLimit, (int)alg);

            if (ret != 0)
            {
                throw new OutOfMemoryException("Internal error, hash failed (usually because the operating system refused to allocate the amount of requested memory).");
            }

            return(buffer);
        }
Esempio n. 7
0
        /// <summary>
        /// Derives a secret key of any size from a password and a salt.
        /// </summary>
        /// <param name="password">The password.</param>
        /// <param name="salt">The salt.</param>
        /// <param name="opsLimit">Represents a maximum amount of computations to perform.</param>
        /// <param name="memLimit">Is the maximum amount of RAM that the function will use, in bytes.</param>
        /// <param name="outputLength">The length of the computed output array.</param>
        /// <returns>Returns a byte array of the given size.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="SaltOutOfRangeException"></exception>
        /// <exception cref="OutOfMemoryException"></exception>
        public static byte[] ScryptHashBinary(byte[] password, byte[] salt, long opsLimit, int memLimit, long outputLength = SCRYPT_SALSA208_SHA256_SALTBYTES)
        {
            if (password == null)
            {
                throw new ArgumentNullException(nameof(password), "Password cannot be null");
            }

            if (salt == null)
            {
                throw new ArgumentNullException(nameof(salt), "Salt cannot be null");
            }

            if (salt.Length != SCRYPT_SALSA208_SHA256_SALTBYTES)
            {
                throw new SaltOutOfRangeException($"Salt must be {SCRYPT_SALSA208_SHA256_SALTBYTES} bytes in length.");
            }

            if (opsLimit <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(opsLimit), "opsLimit cannot be zero or negative");
            }

            if (memLimit <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(memLimit), "memLimit cannot be zero or negative");
            }

            if (outputLength < 16)
            {
                throw new ArgumentOutOfRangeException(nameof(outputLength), "OutputLength cannot be less than 16 bytes");
            }

            var buffer = new byte[outputLength];

            SodiumCore.Init();

            var ret = SodiumLibrary.crypto_pwhash_scryptsalsa208sha256(buffer, buffer.Length, password, password.Length, salt, opsLimit, memLimit);

            if (ret != 0)
            {
                throw new OutOfMemoryException("Internal error, hash failed (usually because the operating system refused to allocate the amount of requested memory).");
            }

            return(buffer);
        }
Esempio n. 8
0
        /// <summary>
        /// Checks if the current password hash needs rehashing
        /// </summary>
        /// <param name="password">Password that needs rehashing</param>
        /// <param name="opsLimit"></param>
        /// <param name="memLimit"></param>
        /// <returns></returns>
        public static bool ArgonPasswordNeedsRehash(byte[] password, long opsLimit, int memLimit)
        {
            if (password == null)
            {
                throw new ArgumentNullException("password", "Password cannot be null");
            }

            SodiumCore.Init();

            int status = SodiumLibrary.crypto_pwhash_str_needs_rehash(password, opsLimit, memLimit);

            if (status == -1)
            {
                throw new InvalidArgonPasswordString();
            }

            return(status == 1);
        }
Esempio n. 9
0
        /// <summary>Detect if the current CPU supports the required instructions (SSSE3, aesni, pcmul).</summary>
        /// <returns><c>true</c> if the CPU supports the necessary instructions, otherwise <c>false</c></returns>
        /// <remarks>Use <see cref="SecretAead" /> if portability is required.</remarks>
        public static bool IsAvailable()
        {
            SodiumCore.Init();

            return(SodiumLibrary.crypto_aead_aes256gcm_is_available() != 0);
        }