//------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // // balnee // krishnib //------------------------------------------------------------------------------ namespace System.Data.SqlClient { using System; using System.Data.SqlClient; using System.Text; /// /// Encryption key class containing 4 keys. This class is used by SqlAeadAes256CbcHmac256Algorithm and SqlAes256CbcAlgorithm /// 1) root key - Main key that is used to derive the keys used in the encryption algorithm /// 2) encryption key - A derived key that is used to encrypt the plain text and generate cipher text /// 3) mac_key - A derived key that is used to compute HMAC of the cipher text /// 4) iv_key - A derived key that is used to generate a synthetic IV from plain text data. /// internal class SqlAeadAes256CbcHmac256EncryptionKey : SqlClientSymmetricKey { /// /// Key size in bits /// internal const int KeySize = 256; /// /// Encryption Key Salt format. This is used to derive the encryption key from the root key. /// private const string _encryptionKeySaltFormat = @"Microsoft SQL Server cell encryption key with encryption algorithm:{0} and key length:{1}"; /// /// MAC Key Salt format. This is used to derive the MAC key from the root key. /// private const string _macKeySaltFormat = @"Microsoft SQL Server cell MAC key with encryption algorithm:{0} and key length:{1}"; /// /// IV Key Salt format. This is used to derive the IV key from the root key. This is only used for Deterministic encryption. /// private const string _ivKeySaltFormat = @"Microsoft SQL Server cell IV key with encryption algorithm:{0} and key length:{1}"; /// /// Encryption Key /// private readonly SqlClientSymmetricKey _encryptionKey; /// /// MAC key /// private readonly SqlClientSymmetricKey _macKey; /// /// IV Key /// private readonly SqlClientSymmetricKey _ivKey; /// /// The name of the algorithm this key will be used with. /// private readonly string _algorithmName; /// /// Derives all the required keys from the given root key /// /// Root key used to derive all the required derived keys internal SqlAeadAes256CbcHmac256EncryptionKey(byte[] rootKey, string algorithmName): base(rootKey) { _algorithmName = algorithmName; int keySizeInBytes = KeySize / 8; // Key validation if (rootKey.Length != keySizeInBytes) { throw SQL.InvalidKeySize(_algorithmName, rootKey.Length, keySizeInBytes); } // Derive keys from the root key // // Derive encryption key string encryptionKeySalt = string.Format(_encryptionKeySaltFormat, _algorithmName, KeySize); byte[] buff1 = new byte[keySizeInBytes]; SqlSecurityUtility.GetHMACWithSHA256(Encoding.Unicode.GetBytes(encryptionKeySalt), RootKey, buff1); _encryptionKey = new SqlClientSymmetricKey(buff1); // Derive mac key string macKeySalt = string.Format(_macKeySaltFormat, _algorithmName, KeySize); byte[] buff2 = new byte[keySizeInBytes]; SqlSecurityUtility.GetHMACWithSHA256(Encoding.Unicode.GetBytes(macKeySalt),RootKey,buff2); _macKey = new SqlClientSymmetricKey(buff2); // Derive iv key string ivKeySalt = string.Format(_ivKeySaltFormat, _algorithmName, KeySize); byte[] buff3 = new byte[keySizeInBytes]; SqlSecurityUtility.GetHMACWithSHA256(Encoding.Unicode.GetBytes(ivKeySalt),RootKey,buff3); _ivKey = new SqlClientSymmetricKey(buff3); } /// /// Encryption key should be used for encryption and decryption /// internal byte[] EncryptionKey { get { return _encryptionKey.RootKey; } } /// /// MAC key should be used to compute and validate HMAC /// internal byte[] MACKey { get { return _macKey.RootKey; } } /// /// IV key should be used to compute synthetic IV from a given plain text /// internal byte[] IVKey { get { return _ivKey.RootKey; } } } }