예제 #1
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("password", "Password cannot be null");
            }

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

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

            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");
            }

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

            var buffer = new byte[outputLength];

            var ret = SodiumLibrary.crypto_pwhash_scryptsalsa208sha256(buffer, buffer.Length, password,
                                                                       password.LongLength, 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);
        }