예제 #1
0
        /// <summary>
        /// Computes a derived key.
        /// </summary>
        /// <param name="hmacAlgorithm">
        ///     The HMAC primitive instance to use. Must be pre-initialised.
        /// </param>
        /// <param name="salt">
        ///     The salt.
        ///     A unique salt means a unique derived key, even if the original key is identical.
        /// </param>
        /// <param name="iterations">The number of iterations to apply.</param>
        /// <param name="derivedKeyLength">The desired length of the derived key.</param>
        /// <returns>The derived key.</returns>
        public static byte[] ComputeDerivedKey(IMac hmacAlgorithm, byte[] salt, int iterations,
                                               int derivedKeyLength)
        {
            Helper.CheckRange("derivedKeyLength", derivedKeyLength, 0, int.MaxValue);

            using (Pbkdf2 kdf = new Pbkdf2(hmacAlgorithm, salt, iterations))
            {
                return(kdf.Read(derivedKeyLength));
            }
        }
예제 #2
0
        /// <summary>
        ///     Computes a derived key.
        /// </summary>
        /// <param name="key">The key to derive from.</param>
        /// <param name="salt">
        ///     The salt.
        ///     A unique salt means a unique SCrypt stream, even if the original key is identical.
        /// </param>
        /// <param name="cost">
        ///     The cost parameter, typically a fairly large number such as 262144.
        ///     Memory usage and CPU time scale approximately linearly with this parameter.
        /// </param>
        /// <param name="blockSize">
        ///     The mixing block size, typically 8.
        ///     Memory usage and CPU time scale approximately linearly with this parameter.
        /// </param>
        /// <param name="parallel">
        ///     The level of parallelism, typically 1.
        ///     CPU time scales approximately linearly with this parameter.
        /// </param>
        /// <param name="maxThreads">
        ///     The maximum number of threads to spawn to derive the key.
        ///     This is limited by the <paramref name="parallel" /> value.
        ///     <c>null</c> will use as many threads as possible.
        /// </param>
        /// <param name="derivedKeyLength">The desired length of the derived key.</param>
        /// <returns>The derived key.</returns>
        public static byte[] ComputeDerivedKey(byte[] key, byte[] salt,
                                               int cost, int blockSize, int parallel, int?maxThreads,
                                               int derivedKeyLength)
        {
            Helper.CheckRange("derivedKeyLength", derivedKeyLength, 0, int.MaxValue);

            using (Pbkdf2 kdf = GetStream(key, salt, cost, blockSize, parallel, maxThreads)) {
                return(kdf.Read(derivedKeyLength));
            }
        }
예제 #3
0
        /// <summary>
        ///     Creates a derived key stream from which a derived key can be read.
        /// </summary>
        /// <param name="key">The key to derive from.</param>
        /// <param name="salt">
        ///     The salt.
        ///     A unique salt means a unique scrypt stream, even if the original key is identical.
        /// </param>
        /// <param name="cost">
        ///     The cost parameter, typically a fairly large number such as 262144.
        ///     Memory usage and CPU time scale approximately linearly with this parameter.
        /// </param>
        /// <param name="blockSize">
        ///     The mixing block size, typically 8.
        ///     Memory usage and CPU time scale approximately linearly with this parameter.
        /// </param>
        /// <param name="parallel">
        ///     The level of parallelism, typically 1.
        ///     CPU time scales approximately linearly with this parameter.
        /// </param>
        /// <param name="maxThreads">
        ///     The maximum number of threads to spawn to derive the key.
        ///     This is limited by the <paramref name="parallel" /> value.
        ///     <c>null</c> will use as many threads as possible.
        /// </param>
        /// <returns>The derived key stream.</returns>
        public static Pbkdf2 GetStream(byte[] key, byte[] salt,
                                       int cost, int blockSize, int parallel, int?maxThreads)
        {
            byte[] B    = GetEffectivePbkdf2Salt(key, salt, cost, blockSize, parallel, maxThreads);
            IMac   hmac = AuthenticatorFactory.CreateHmacPrimitive(HashFunction.Sha256, key, null);
            var    kdf  = new Pbkdf2(hmac, B, 1);

            //Security.Clear(B);
            Array.Clear(B, 0, B.Length);
            return(kdf);
        }
예제 #4
0
        private static byte[] MFcrypt(byte[] P, byte[] S,
                                      int cost, int blockSize, int parallel, int?maxThreads)
        {
            int MFLen = blockSize * 128;

            if (maxThreads == null)
            {
                maxThreads = int.MaxValue;
            }

            if (!(cost > 0 && cost % 2 == 0))
            {
                throw new ArgumentOutOfRangeException("cost", "Cost must be a positive power of 2.");
            }
            Helper.CheckRange("blockSize", blockSize, 1, int.MaxValue / 128);
            Helper.CheckRange("parallel", parallel, 1, int.MaxValue / MFLen);
            Helper.CheckRange("maxThreads", (int)maxThreads, 1, int.MaxValue);

            IMac hmac = AuthenticatorFactory.CreateHmacPrimitive(HashFunction.Sha256, P);

            byte[] B = Pbkdf2.ComputeDerivedKey(hmac, S, 1, parallel * MFLen);

            var B0 = new uint[B.Length / sizeof(uint)];

            for (int i = 0; i < B0.Length; i++)
            {
                B0[i] = B.LittleEndianToUInt32_NoChecks(i * sizeof(uint));
            } // code is easier with uint[]

            ThreadSMixCalls(B0, MFLen, cost, blockSize, parallel, (int)maxThreads);
            for (int i = 0; i < B0.Length; i++)
            {
                B0[i].ToLittleEndian_NoChecks(B, i * sizeof(uint));
            }
            B0.SecureWipe();

            return(B);
        }