Example #1
0
        /// <summary>
        /// Reads from the derived key stream.
        /// </summary>
        /// <param name="count">The number of bytes to read.</param>
        /// <returns>Bytes from the derived key stream.</returns>
        public byte[] Read(int count)
        {
            Check.Range("count", count, 0, int.MaxValue);

            byte[] buffer = new byte[count];
            int    bytes  = Read(buffer, 0, count);

            if (bytes < count)
            {
                throw Exceptions.Argument("count", "Can only return {0} bytes.", bytes);
            }

            return(buffer);
        }
Example #2
0
        /// <summary>
        /// Creates a new PBKDF2 stream.
        /// </summary>
        /// <param name="hmacAlgorithm">
        ///     The HMAC algorithm to use, for example <see cref="HMACSHA256"/>.
        ///     Make sure to set <see cref="KeyedHashAlgorithm.Key"/>.
        /// </param>
        /// <param name="salt">
        ///     The salt.
        ///     A unique salt means a unique PBKDF2 stream, even if the original key is identical.
        /// </param>
        /// <param name="iterations">The number of iterations to apply.</param>
        public Pbkdf2(KeyedHashAlgorithm hmacAlgorithm, byte[] salt, int iterations)
        {
            Check.Null("hmacAlgorithm", hmacAlgorithm);
            Check.Null("salt", salt);
            Check.Length("salt", salt, 0, int.MaxValue - 4);
            Check.Range("iterations", iterations, 1, int.MaxValue);
            if (hmacAlgorithm.HashSize == 0 || hmacAlgorithm.HashSize % 8 != 0)
            {
                throw Exceptions.Argument("hmacAlgorithm", "Unsupported hash size.");
            }

            int hmacLength = hmacAlgorithm.HashSize / 8;

            _saltBuffer = new byte[salt.Length + 4]; Array.Copy(salt, _saltBuffer, salt.Length);
            _iterations = iterations; _hmacAlgorithm = hmacAlgorithm;
            _digest     = new byte[hmacLength]; _digestT1 = new byte[hmacLength];
        }
Example #3
0
        /// <inheritdoc />
        public override long Seek(long offset, SeekOrigin origin)
        {
            long pos;

            switch (origin)
            {
            case SeekOrigin.Begin: pos = offset; break;

            case SeekOrigin.Current: pos = Position + offset; break;

            case SeekOrigin.End: pos = Length + offset; break;

            default: throw Exceptions.ArgumentOutOfRange("origin", "Unknown seek type.");
            }

            if (pos < 0)
            {
                throw Exceptions.Argument("offset", "Can't seek before the stream start.");
            }
            Position = pos; return(pos);
        }
Example #4
0
        /// <summary>
        /// Applies the Salsa20 hash function.
        /// It maps a 16 element input to an output of the same size.
        /// </summary>
        /// <param name="rounds">The number of rounds. SCrypt uses 8.</param>
        /// <param name="input">The input buffer.</param>
        /// <param name="inputOffset">The offset into the input buffer.</param>
        /// <param name="output">The output buffer.</param>
        /// <param name="outputOffset">The offset into the output buffer.</param>
        public static void Compute(int rounds,
                                   uint[] input, int inputOffset, uint[] output, int outputOffset)
        {
            if (rounds < 2 || rounds > 20 || (rounds & 1) == 1)
            {
                throw Exceptions.Argument("rounds", "Must be even and in the range 2 to 20.");
            }

            try
            {
                // .NET's bounds checking hurts performance in tight loops like this one.
                // So, I unroll the array to eliminate it - a 50% speed increase.
                uint x0  = input[inputOffset + 0];
                uint x1  = input[inputOffset + 1];
                uint x2  = input[inputOffset + 2];
                uint x3  = input[inputOffset + 3];
                uint x4  = input[inputOffset + 4];
                uint x5  = input[inputOffset + 5];
                uint x6  = input[inputOffset + 6];
                uint x7  = input[inputOffset + 7];
                uint x8  = input[inputOffset + 8];
                uint x9  = input[inputOffset + 9];
                uint x10 = input[inputOffset + 10];
                uint x11 = input[inputOffset + 11];
                uint x12 = input[inputOffset + 12];
                uint x13 = input[inputOffset + 13];
                uint x14 = input[inputOffset + 14];
                uint x15 = input[inputOffset + 15];

                for (int i = rounds; i > 0; i -= 2)
                {
                    x4  ^= R(x0 + x12, 7); x8 ^= R(x4 + x0, 9);
                    x12 ^= R(x8 + x4, 13); x0 ^= R(x12 + x8, 18);
                    x9  ^= R(x5 + x1, 7); x13 ^= R(x9 + x5, 9);
                    x1  ^= R(x13 + x9, 13); x5 ^= R(x1 + x13, 18);
                    x14 ^= R(x10 + x6, 7); x2 ^= R(x14 + x10, 9);
                    x6  ^= R(x2 + x14, 13); x10 ^= R(x6 + x2, 18);
                    x3  ^= R(x15 + x11, 7); x7 ^= R(x3 + x15, 9);
                    x11 ^= R(x7 + x3, 13); x15 ^= R(x11 + x7, 18);
                    x1  ^= R(x0 + x3, 7); x2 ^= R(x1 + x0, 9);
                    x3  ^= R(x2 + x1, 13); x0 ^= R(x3 + x2, 18);
                    x6  ^= R(x5 + x4, 7); x7 ^= R(x6 + x5, 9);
                    x4  ^= R(x7 + x6, 13); x5 ^= R(x4 + x7, 18);
                    x11 ^= R(x10 + x9, 7); x8 ^= R(x11 + x10, 9);
                    x9  ^= R(x8 + x11, 13); x10 ^= R(x9 + x8, 18);
                    x12 ^= R(x15 + x14, 7); x13 ^= R(x12 + x15, 9);
                    x14 ^= R(x13 + x12, 13); x15 ^= R(x14 + x13, 18);
                }

                output[outputOffset + 0]  = input[inputOffset + 0] + x0; x0 = 0;
                output[outputOffset + 1]  = input[inputOffset + 1] + x1; x1 = 0;
                output[outputOffset + 2]  = input[inputOffset + 2] + x2; x2 = 0;
                output[outputOffset + 3]  = input[inputOffset + 3] + x3; x3 = 0;
                output[outputOffset + 4]  = input[inputOffset + 4] + x4; x4 = 0;
                output[outputOffset + 5]  = input[inputOffset + 5] + x5; x5 = 0;
                output[outputOffset + 6]  = input[inputOffset + 6] + x6; x6 = 0;
                output[outputOffset + 7]  = input[inputOffset + 7] + x7; x7 = 0;
                output[outputOffset + 8]  = input[inputOffset + 8] + x8; x8 = 0;
                output[outputOffset + 9]  = input[inputOffset + 9] + x9; x9 = 0;
                output[outputOffset + 10] = input[inputOffset + 10] + x10; x10 = 0;
                output[outputOffset + 11] = input[inputOffset + 11] + x11; x11 = 0;
                output[outputOffset + 12] = input[inputOffset + 12] + x12; x12 = 0;
                output[outputOffset + 13] = input[inputOffset + 13] + x13; x13 = 0;
                output[outputOffset + 14] = input[inputOffset + 14] + x14; x14 = 0;
                output[outputOffset + 15] = input[inputOffset + 15] + x15; x15 = 0;
            }
            catch (IndexOutOfRangeException)
            {
                // For speed, don't bounds-check until .NET throws from a bounds error.
                Check.Null("input", input); Check.Bounds("input", input, inputOffset, 16);
                Check.Null("output", output); Check.Bounds("output", output, outputOffset, 16);
                throw;
            }
        }