/// <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); }
public static CryptographicKey DeriveKey(CryptographicKey keyDerivationKey, Purpose purpose) { CryptographicKey result; using (HMACSHA512 hMACSHA = CryptoAlgorithms.CreateHMACSHA512(keyDerivationKey.GetKeyMaterial())) { byte[] label; byte[] context; purpose.GetKeyDerivationParameters(out label, out context); result = new CryptographicKey(SP800_108.DeriveKeyImpl(hMACSHA, label, context, keyDerivationKey.KeyLength)); } return(result); }
/// <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)); } }