Example #1
0
        // Password-Based Key Derivation Function 2. Used to generate "pseudorandom" keys from a given password and salt using a certain PRF applied a certain amount of times (iterations).
        // dklen specified the "derived key length" in bytes. It is recommended to use a high number for the iterations variable (somewhere around 4096 is the standard for SHA1 currently)
        public static byte[] PBKDF2(PRF function, byte[] password, byte[] salt, int iterations, int dklen)
        {
            byte[] dk   = new byte[0]; // Create a placeholder for the derived key
            uint   iter = 1;           // Track the iterations

            while (dk.Length < dklen)
            {
                // F-function
                // The F-function (PRF) takes the amount of iterations performed in the opposite endianness format from what C# uses, so we have to swap the endianness
                byte[] u    = function(password, Support.Concatenate(salt, Support.WriteToArray(new byte[4], Support.SwapEndian(iter), 0)));
                byte[] ures = new byte[u.Length];
                Array.Copy(u, ures, u.Length);
                for (int i = 1; i < iterations; ++i)
                {
                    // Iteratively apply the PRF
                    u = function(password, u);
                    for (int j = 0; j < u.Length; ++j)
                    {
                        ures[j] ^= u[j];
                    }
                }

                // Concatenate the result to the dk
                dk = Support.Concatenate(dk, ures);

                ++iter;
            }

            // Clip aby bytes past what we needed (yes, that's really what the standard is)
            return(dk.ToLength(dklen));
        }
Example #2
0
        // Hash-based Message Authentication Codes: generates a code for verifying the sender of a message and the like
        public static byte[] HMAC(byte[] key, byte[] message, HashFunction func, int blockSizeBytes)
        {
            if (key.Length > blockSizeBytes)
            {
                key = func(key);
            }
            else if (key.Length < blockSizeBytes)
            {
                byte[] b = new byte[blockSizeBytes];
                Array.Copy(key, b, key.Length);
                key = b;
            }

            byte[] o_key_pad = new byte[blockSizeBytes]; // Outer padding
            byte[] i_key_pad = new byte[blockSizeBytes]; // Inner padding
            for (int i = 0; i < blockSizeBytes; ++i)
            {
                // Combine padding with key
                o_key_pad[i] = (byte)(key[i] ^ 0x5c);
                i_key_pad[i] = (byte)(key[i] ^ 0x36);
            }
            return(func(Support.Concatenate(o_key_pad, func(Support.Concatenate(message, i_key_pad)))));
        }