Пример #1
0
        /// <summary>
        /// Returns an IV that's based solely on the contents of a buffer; useful for generating
        /// predictable IVs for ciphertexts that need to be cached. The output value is only
        /// appropriate for use as an IV and must not be used for any other purpose.
        /// </summary>
        /// <remarks>This method uses an iterated unkeyed SHA256 to calculate the IV.</remarks>
        /// <param name="buffer">The input buffer over which to calculate the IV.</param>
        /// <param name="ivBitLength">The requested length (in bits) of the IV to generate.</param>
        /// <returns>The calculated IV.</returns>
        public static byte[] CreatePredictableIV(byte[] buffer, int ivBitLength) {
            // Algorithm:
            // T_0 = SHA256(buffer)
            // T_n = SHA256(T_{n-1})
            // output = T_0 || T_1 || ... || T_n (as many blocks as necessary to reach ivBitLength)

            byte[] output = new byte[ivBitLength / 8];
            int bytesCopied = 0;
            int bytesRemaining = output.Length;

            using (SHA256 sha256 = CryptoAlgorithms.CreateSHA256()) {
                while (bytesRemaining > 0) {
                    byte[] hashed = sha256.ComputeHash(buffer);

                    int bytesToCopy = Math.Min(bytesRemaining, hashed.Length);
                    Buffer.BlockCopy(hashed, 0, output, bytesCopied, bytesToCopy);

                    bytesCopied += bytesToCopy;
                    bytesRemaining -= bytesToCopy;

                    buffer = hashed; // next iteration (if it occurs) will operate over the block just hashed
                }
            }

            return output;
        }
Пример #2
0
        public KeyedHashAlgorithm GetValidationAlgorithm()
        {
            switch (this.validation)
            {
            case "SHA1":
                return(CryptoAlgorithms.CreateHMACSHA1());

            case "HMACSHA256":
                return(CryptoAlgorithms.CreateHMACSHA256());

            case "HMACSHA384":
                return(CryptoAlgorithms.CreateHMACSHA384());

            case "HMACSHA512":
                return(CryptoAlgorithms.CreateHMACSHA512());

            default:
                return(null);    // unknown
            }
        }
Пример #3
0
        // Implements the KeyDerivationFunction delegate signature; public entry point to the API.
        public static CryptographicKey DeriveKey(CryptographicKey keyDerivationKey, Purpose purpose)
        {
            // After consultation with the crypto board, we have decided to use HMACSHA512 as the PRF
            // to our KDF. The reason for this is that our PRF is an HMAC, so the total entropy of the
            // PRF is given by MIN(key derivation key length, HMAC block size). It is conceivable that
            // a developer might specify a key greater than 256 bits in length, at which point using
            // a shorter PRF like HMACSHA256 starts discarding entropy. But from the crypto team's
            // perspective it is unreasonable for a developer to supply a key greater than 512 bits,
            // so there's no real harm in us limiting our PRF entropy to 512 bits (HMACSHA512).
            //
            // On 64-bit platforms, HMACSHA512 matches or outperforms HMACSHA256 in our perf testing.
            // On 32-bit platforms, HMACSHA512 is around 1/3 the speed of HMACSHA256. In both cases, we
            // try to cache the derived CryptographicKey wherever we can, so this shouldn't be a
            // bottleneck regardless.

            using (HMACSHA512 hmac = CryptoAlgorithms.CreateHMACSHA512(keyDerivationKey.GetKeyMaterial())) {
                byte[] label, context;
                purpose.GetKeyDerivationParameters(out label, out context);

                byte[] derivedKey = DeriveKeyImpl(hmac, label, context, keyDerivationKey.KeyLength);
                return(new CryptographicKey(derivedKey));
            }
        }
Пример #4
0
        public SymmetricAlgorithm GetEncryptionAlgorithm()
        {
            // We suppress CS0618 since some of the algorithms we support are marked with [Obsolete].
            // These deprecated algorithms are *not* enabled by default. Developers must opt-in to
            // them, so we're secure by default.
#pragma warning disable 618
            switch (this.encryption)
            {
            case "AES":
            case "Auto":         // currently "Auto" defaults to AES
                return(CryptoAlgorithms.CreateAes());

            case "DES":
                return(CryptoAlgorithms.CreateDES());

            case "3DES":
                return(CryptoAlgorithms.CreateTripleDES());

            default:
                return(null);        // unknown

#pragma warning restore 618
            }
        }
Пример #5
0
 /// <summary>
 /// Computes the SHA256 hash of a given segment in a buffer.
 /// </summary>
 /// <param name="buffer">The buffer over which to compute the hash.</param>
 /// <param name="offset">The offset at which to begin computing the hash.</param>
 /// <param name="count">The number of bytes in the buffer to include in the hash.</param>
 /// <returns>The binary hash (32 bytes) of the buffer segment.</returns>
 public static byte[] ComputeSHA256Hash(byte[] buffer, int offset, int count) {
     using (SHA256 sha256 = CryptoAlgorithms.CreateSHA256()) {
         return sha256.ComputeHash(buffer, offset, count);
     }
 }