Always Encrypted 密碼編譯
適用於:SQL Server Azure SQL 資料庫 Azure SQL 受控執行個體
本文件描述加密演算法和機制,以衍生在 SQL Server 和 Azure SQL Database 上的 Always Encrypted 功能中使用的密碼編譯內容。
金鑰、金鑰存放區及金鑰加密演算法
Always Encrypted 使用兩種金鑰類型:資料行主要金鑰和資料行加密金鑰。
資料行主要金鑰 (CMK) 是加密金鑰的金鑰 (也就是用來加密其他金鑰的金鑰),其一律會由用戶端控制,並儲存於外部金鑰存放區中。 已啟用 Always Encrypted 的用戶端驅動程式會透過 CMK 存放區提供者來與金鑰存放區互動,其可以是驅動程式庫 (Microsoft/系統提供者) 的一部分或用戶端應用程式 (自訂提供者) 的一部分。 用戶端驅動程式庫目前包括適用於 Windows 憑證存放區的 Microsoft 金鑰存放區提供者和硬體安全性模組 (HSM)。 如需目前的提供者清單,請參閱 CREATE COLUMN MASTER KEY (Transact-SQL)。 應用程式開發人員可以針對任意存放區提供自訂提供者。
資料行加密金鑰 (CEK) 是受到 CMK 保護的內容加密金鑰 (例如:用來保護資料的金鑰)。
所有 Microsoft CMK 存放區提供者都會使用具備最佳非對稱加密填補的 RSA (RSA-OAEP) 來加密 CEK。 支援 Microsoft Cryptography API 的金鑰存放區提供者包括:.NET Framework 中的新一代 (CNG) (SqlColumnEncryptionCngProvider 類別) 使用 RFC 8017 在第 A.2.1 節指定的預設參數。 這些預設參數會使用 SHA-1 的雜湊函數及搭配 SHA-1 的 MGF1 遮罩產生函數。 所有其它的金鑰存放區提供者都使用 SHA-256。
Always Encrypted 會在內部使用以 FIPS 140-2 驗證的密碼編譯模組。
資料加密演算法
「永遠加密」會使用 AEAD_AES_256_CBC_HMAC_SHA_256 演算法來加密資料庫中的資料。
AEAD_AES_256_CBC_HMAC_SHA_256 衍生自 https://tools.ietf.org/html/draft-mcgrew-aead-aes-cbc-hmac-sha2-05 的規格草稿。 它會使用「驗證的加密」配置搭配相關聯的資料,遵循「加密然後 MAC」方法。 那就是,第一次加密純文字,並根據產生的加密文字產生 MAC。
為了隱藏模式, AEAD_AES_256_CBC_HMAC_SHA_256 會使用作業的加密區塊鏈結 (CBC) 模式,其中會將初始值送入名為初始化向量 (IV) 的系統中。 CBC 模式的完整描述請參閱 https://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf。
AEAD_AES_256_CBC_HMAC_SHA_256 會使用下列步驟,來計算指定純文字值的加密文字值。
步驟 1:產生初始化向量 (IV)
「永遠加密」支援 AEAD_AES_256_CBC_HMAC_SHA_256的兩種變化:
隨機化
具決定性
如果是隨機化加密,就會隨機產生 IV。 因此,每次加密相同的純文字時,都會產生不同的加密文字,這樣可防止任何資訊外洩。
When using randomized encryption: IV = Generate cryptographicaly random 128bits
若有具確定性的加密,便不會隨機產生 IV,而是會使用下列演算法從純文字的值衍生:
When using deterministic encryption: IV = HMAC-SHA-256( iv_key, cell_data ) truncated to 128 bits.
其中 iv_key 會以下列方式衍生自 CEK︰
iv_key = HMAC-SHA-256(CEK, "Microsoft SQL Server cell IV key" + algorithm + CEK_length)
執行 HMAC 值截斷以使其可以容納在 IV 所需要的一個資料區塊中。 因此,具決定性加密一律會針對指定的純文字值產生相同加密文字,這樣就能藉由比較兩個純文字值的對應加密文字值,來推斷其是否相等。 這個有限度的資料洩漏,讓資料庫系統能夠支援已加密資料行值上的相等比較。
相較於替代項目,具決定性加密在隱藏模式中更具效率,例如使用預先定義的 IV 值。
步驟 2:計算 AES_256_CBC 加密文字
計算 IV 之後,即會產生 AES_256_CBC 加密文字︰
aes_256_cbc_ciphertext = AES-CBC-256(enc_key, IV, cell_data) with PKCS7 padding.
其中的加密金鑰 (enc_key) 是衍生自 CEK,如下所示。
enc_key = HMAC-SHA-256(CEK, "Microsoft SQL Server cell encryption key" + algorithm + CEK_length )
步驟 3:計算 MAC
接著,使用下列演算法來計算 MAC︰
MAC = HMAC-SHA-256(mac_key, versionbyte + IV + Ciphertext + versionbyte_length)
其中:
versionbyte = 0x01 and versionbyte_length = 1
mac_key = HMAC-SHA-256(CEK, "Microsoft SQL Server cell MAC key" + algorithm + CEK_length)
步驟 4:串連
最後,會透過將演算法版本位元組、MAC、IV 和 AES_256_CBC 加密文字串連,來產生加密值:
aead_aes_256_cbc_hmac_sha_256 = versionbyte + MAC + IV + aes_256_cbc_ciphertext
加密文字長度
AEAD_AES_256_CBC_HMAC_SHA_256 加密文字的特定元件長度 (以位元組為單位) 如下︰
versionbyte:1
MAC: 32
IV: 16
aes_256_cbc_ciphertext︰
(FLOOR (DATALENGTH(cell_data)/ block_size) + 1)* block_size
,其中︰block_size 是 16 位元組
cell_data 是純文字值
因此,aes_256_cbc_ciphertext 的最小大小為 1 個區塊,也就是 16 個位元組。
您因而可使用以下公式來計算加密文字 (因為加密指定的純文字值 (cell_data) 而產生) 的長度︰
1 + 32 + 16 + (FLOOR(DATALENGTH(cell_data)/16) + 1) * 16
例如:
加密之後,4 個位元組長的 int 純文字值會變成 65 個位元組長的二進位值。
加密之後,2,000 個位元組長的 nchar(1000) 純文字值會變成 2,065 個位元組長的二進位值。
下表包含資料類型的完整清單以及每個類型的加密文字長度。
資料類型 | 加密文字長度 [位元組] |
---|---|
bigint | 65 |
binary | 變動。 使用上述公式。 |
bit | 65 |
char | 變動。 使用上述公式。 |
date | 65 |
datetime | 65 |
datetime2 | 65 |
datetimeoffset | 65 |
decimal | 81 |
float | 65 |
地理位置 | N/A (不支援) |
幾何 | N/A (不支援) |
hierarchyid | N/A (不支援) |
image | N/A (不支援) |
int | 65 |
money | 65 |
nchar | 變動。 使用上述公式。 |
ntext | N/A (不支援) |
numeric | 81 |
nvarchar | 變動。 使用上述公式。 |
real | 65 |
smalldatetime | 65 |
smallint | 65 |
smallmoney | 65 |
sql_variant | N/A (不支援) |
sysname | N/A (不支援) |
text | N/A (不支援) |
time | 65 |
timestamp (rowversion) |
N/A (不支援) |
tinyint | 65 |
uniqueidentifier | 81 |
varbinary | 變動。 使用上述公式。 |
varchar | 變動。 使用上述公式。 |
xml | N/A (不支援) |
.NET 參考
如需本文件所討論的演算法詳細資料,請參閱 .NET 參考中的 SqlAeadAes256CbcHmac256Algorithm.cs、SqlColumnEncryptionCertificateStoreProvider.cs 和 SqlColumnEncryptionCertificateStoreProvider.cs 檔案。