AWS KMS 階層式鑰匙圈 - AWS 資料庫加密 SDK

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

AWS KMS 階層式鑰匙圈

我們的用戶端加密程式庫已重新命名為 AWS 資料庫加密 SDK。本開發人員指南仍提供 DynamoDB 加密用戶端的相關資訊。
注意

自 2023 年 7 月 24 日起,不支援在開發人員預覽期間建立的分支金鑰。建立新的分支金鑰,以繼續使用您在開發人員預覽期間建立的分支金鑰存放區。

使用 AWS KMS 階層式金鑰圈,您可以使用對稱式加密 KMS 金鑰保護加密資料,而無需在 AWS KMS 每次加密或解密記錄時呼叫。對於需要盡量減少呼叫的應用程式,以及可重複使用某些加密資料而不違反其安全性需求的應用程式來說 AWS KMS,這是一個不錯的選擇。

階層式金鑰圈是一種加密材料快取解決方案,可透過使用保存在 Amazon DynamoDB 表格中的 AWS KMS 受保護分支金鑰,然後在本機快取用於加密和解密作業的分支金鑰材料,以減少 AWS KMS 呼叫次數。DynamoDB 表可做為管理和保護分支金鑰的分支金鑰存放區。它存儲活動分支密鑰和分支密鑰的所有以前版本。動分支密鑰是最新的分支密鑰版本。分層密鑰環使用唯一的數據密鑰來加密每個字段,並使用從活動分支密鑰派生的唯一包裝密鑰對每個數據密鑰進行加密。分層密鑰環取決於活動分支密鑰及其派生包裝密鑰之間建立的層次結構。

分層密鑰環通常使用每個分支密鑰版本來滿足多個請求。但是您可以控制重複使用活動分支密鑰的程度,並確定活動分支鍵的旋轉頻率。分支索引鍵的作用中版本會保持作用中狀態,直到您旋轉它為止。以前版本的 Active 分支密鑰將不會用於執行加密操作,但仍然可以在解密操作中查詢和使用它們。

當您實例化分層密鑰環時,它會創建一個本地緩存。您可以指定一個快取限制,以定義分支索引鍵材料在到期並從快取中逐出之前儲存在本機快取中的時間上限。在作業中第一次指定 a branch-key-id 時,階層式金鑰圈會進行一次 AWS KMS 呼叫,以解密分支金鑰並組裝分支金鑰材料。然後,分支金鑰材料會儲存在本機快取中,並重複用於所有指定的加密和解密作業,branch-key-id直到快取限制到期為止。在本機快取中儲存分支金鑰材料可減少 AWS KMS 呼叫。例如,假設快取限制為 15 分鐘。如果您在該快取限制內執行 10,000 個加密作業,則傳統 AWS KMS 金鑰圈需要進行 10,000 次 AWS KMS 呼叫,才能滿足 10,000 個加密作業。如果您有一個作用中branch-key-id,階層式金鑰圈只需要進行一次 AWS KMS 呼叫即可滿足 10,000 個加密作業。

本機快取由兩個分割區組成,一個用於加密作業,另一個用於解密作業。加密分割區會儲存從使用中分支金鑰組合而來的分支金鑰材料,並在所有加密作業中重複使用,直到快取限制到期為止。解密分割區會儲存為解密作業中識別的其他分支金鑰版本所組合的分支金鑰材料。解密分區可以一次存儲多個活動分支密鑰材料版本。當它設定為針對多租戶資料庫使用分支金鑰 ID 供應商時,該加密分割區也可以一次儲存多個分支金鑰材料版本。如需詳細資訊,請參閱 搭配多租戶資料庫使用階層式金鑰圈

注意

AWS 數據庫加密 SDK 中分層密鑰環的所有提及都是指 AWS KMS 分層密鑰環。

運作方式

下列逐步解說說明階層式金鑰環如何組合加密和解密資料,以及金鑰圈針對加密和解密作業所進行的不同呼叫。如需有關包裝金鑰衍生和純文字資料金鑰加密程序的技術詳細資訊,請參閱AWS KMS 階層式金鑰圈技術詳細資料。

加密和簽署

以下逐步解說說明「階層式金鑰圈」如何組合加密材料並衍生唯一的環繞金鑰。

  1. 加密方法會詢問加密材料的階層式金鑰圈。金鑰圈會產生純文字資料金鑰,然後檢查本機快取中是否有有效的分支材料來產生環繞金鑰。如果有有效的分支金鑰材料,金鑰圈會進入步驟 5

  2. 如果沒有有效的分支金鑰材料,階層式金鑰圈會查詢分支金鑰存放區以取得使用中的分支金鑰。

    1. 分支密鑰存儲調用 AWS KMS 以解密活動分支密鑰並返回明文活動分支密鑰。識別活動分支密鑰的數據被序列化,以在解密調用中提供額外的身份驗證數據(AAD)。 AWS KMS

    2. 分支密鑰存儲庫返回明文分支密鑰和標識它的數據,例如分支密鑰版本。

  3. 階層式金鑰圈會組合分支金鑰材料 (純文字分支金鑰和分支金鑰版本),並將它們的副本儲存在本機快取中。

  4. 分層密鑰環從明文分支密鑰和 16 字節隨機鹽派生一個唯一的包裝密鑰。它使用派生的包裝密鑰來加密純文本數據密鑰的副本。

加密方法使用加密材料對記錄進行加密和簽名。如需有關如何在資 AWS 料庫加密 SDK 中加密和簽署記錄的詳細資訊,請參閱加密和簽署。

解密和驗證

以下逐步解說說明「階層式金鑰圈」如何組合解密材料並解密加密的資料金鑰。

  1. 解密方法可從加密記錄的材料描述欄位中識別加密的資料金鑰,並將其傳遞至階層式金鑰圈。

  2. 階層式金鑰環還原序列化識別加密資料金鑰的資料,包括分支金鑰版本、16 位元組 salt,以及說明資料金鑰加密方式的其他資訊。

    如需詳細資訊,請參閱 AWS KMS分層鑰匙圈技術細節

  3. 階層式金鑰圈會檢查本機快取中是否有符合步驟 2 中所識別的分支金鑰版本的有效分支金鑰材料。如果有有效的分支金鑰材料,金鑰圈會進入步驟 6

  4. 如果沒有有效的分支金鑰材料,階層式金鑰圈會查詢分支金鑰存放區,找出與步驟 2 中所識別的分支金鑰版本相符的分支金鑰存放區。

    1. 分支密鑰存儲調用 AWS KMS 解密分支密鑰並返回明文活動分支密鑰。識別活動分支密鑰的數據被序列化,以在解密調用中提供額外的身份驗證數據(AAD)。 AWS KMS

    2. 分支密鑰存儲庫返回明文分支密鑰和標識它的數據,例如分支密鑰版本。

  5. 階層式金鑰圈會組合分支金鑰材料 (純文字分支金鑰和分支金鑰版本),並將它們的副本儲存在本機快取中。

  6. 階層式金鑰圈使用組裝好的分支金鑰材料和步驟 2 中識別的 16 位元組鹽來重現加密資料金鑰的唯一包裝金鑰。

  7. 階層式金鑰圈使用複製的包裝金鑰來解密資料金鑰,並傳回純文字資料金鑰。

解密方法使用解密材料和明文數據密鑰來解密和驗證記錄。如需有關如何在資 AWS 料庫加密 SDK 中解密和驗證記錄的詳細資訊,請參閱解密和驗證

必要條件

數 AWS 據庫加密 SDK 不需要 AWS 帳戶 ,它不依賴於任何 AWS 服務. 不過,階層式金鑰圈取決於 AWS KMS 和 Amazon DynamoDB。

若要使用階層式金鑰圈,您需要使用 K MS: 解密權限的對稱 AWS KMS key 加密。您也可以使用對稱加密多區域金鑰。如需有關權限的詳細資訊 AWS KMS keys,請參閱AWS Key Management Service 開發人員指南中的驗證和存取控制

在建立和使用階層式金鑰圈之前,您必須先建立分支金鑰存放區,並使用第一個使用中的分支金鑰來填入該分支金鑰存放區。

步驟 1:設定新的金鑰存放區服務

金鑰存放區服務提供數種作業,例如CreateKeyStoreCreateKey,可協助您組合階層式金鑰圈必要條件並管理分支金鑰存放區。

下列範例會建立金鑰存放區服務。您必須指定 DynamoDB 資料表名稱做為分支金鑰存放區的名稱、分支金鑰存放區的邏輯名稱,以及識別可保護分支金鑰之 KMS 金鑰的 KMS 金鑰 ARN。

邏輯金鑰存放區名稱會以密碼方式繫結至儲存在資料表中的所有資料,以簡化 DynamoDB 還原作業。邏輯金鑰存放區名稱可以與 DynamoDB 表名稱相同,但不一定要這樣做。強烈建議您在第一次設定金鑰存放區服務時,將 DynamoDB 表名稱指定為邏輯資料表名稱。您必須永遠指定相同的邏輯資料表名稱。如果您的分支金鑰存放區名稱在從備份還原 DynamoDB 表後變更,邏輯金鑰存放區名稱會對應至您指定的 DynamoDB 表名稱,以確保階層式金鑰圈仍可存取您的分支金鑰存放區。

Java
final KeyStore keystore = KeyStore.builder().KeyStoreConfig( KeyStoreConfig.builder() .ddbClient(DynamoDbClient.create()) .ddbTableName(keyStoreName) .logicalKeyStoreName(logicalKeyStoreName) .kmsClient(KmsClient.create()) .kmsConfiguration(KMSConfiguration.builder() .kmsKeyArn(kmsKeyArn) .build()) .build()).build();
C# / .NET
var kmsConfig = new KMSConfiguration { KmsKeyArn = kmsKeyArn }; var keystoreConfig = new KeyStoreConfig { KmsClient = new AmazonKeyManagementServiceClient(), KmsConfiguration = kmsConfig, DdbTableName = keyStoreName, DdbClient = new AmazonDynamoDBClient(), LogicalKeyStoreName = logicalKeyStoreName }; var keystore = new KeyStore(keystoreConfig);
步驟 2:CreateKeyStore打電話創建分支密鑰存儲

以下操作會創建將持續存儲並保護您的分支密鑰的分支密鑰存儲區。

Java
keystore.CreateKeyStore(CreateKeyStoreInput.builder().build());
C# / .NET
var createKeyStoreOutput = keystore.CreateKeyStore(new CreateKeyStoreInput());

CreateKeyStore作業會使用您在步驟 1 中指定的資料表名稱和下列必要值建立 DynamoDB 表格。

分割區索引鍵 排序索引鍵
基本資料表 branch-key-id type
注意

您可以手動建立做為分支金鑰存放區的 DynamoDB 表格,而非使用此作業。CreateKeyStore如果您選擇手動建立分支金鑰存放區,則必須為分割區和排序索引鍵指定下列字串值:

  • 分區索引鍵: branch-key-id

  • 排序索引鍵:type

步驟 3:打電話創CreateKey建一個新的活動分支密鑰

下列作業會使用您在步驟 1 中指定的 KMS 金鑰建立新的作用中分支金鑰,並將作用中分支金鑰新增至您在步驟 2 中建立的 DynamoDB 表格。

撥打電話時CreateKey,您可以選擇指定下列選用值。

Java
final Map<String, String> additionalEncryptionContext = Collections.singletonMap("Additional Encryption Context for", "custom branch key id"); final String BranchKey = keystore.CreateKey( CreateKeyInput.builder() .branchKeyIdentifier(custom-branch-key-id) //OPTIONAL .encryptionContext(additionalEncryptionContext) //OPTIONAL .build()).branchKeyIdentifier();
C# / .NET
var additionalEncryptionContext = new Dictionary<string, string>(); additionalEncryptionContext.Add("Additional Encryption Context for", "custom branch key id"); var branchKeyId = keystore.CreateKey(new CreateKeyInput { BranchKeyIdentifier = "custom-branch-key-id", // OPTIONAL EncryptionContext = additionalEncryptionContext // OPTIONAL });

首先,作CreateKey業會產生下列值。

然後,作CreateKey業會呼叫 kms:GenerateDataKeyWithoutPlaintext使用下列要求。

{ "EncryptionContext": { "branch-key-id" : "branch-key-id", "type" : "type", "create-time" : "timestamp", "logical-key-store-name" : "the logical table name for your branch key store", "kms-arn" : the KMS key ARN, "hierarchy-version" : "1", "aws-crypto-ec:contextKey": "contextValue" }, "KeyId": "the KMS key ARN you specified in Step 1", "NumberOfBytes": "32" }
注意

即使您尚未將資料庫設定為可搜尋的加密,CreateKey作業也會建立作用中的分支金鑰和信標金鑰。兩個密鑰都存儲在您的分支密鑰存儲中。如需詳細資訊,請參閱使用階層式金鑰圈進行可搜尋的加密

接下來,CreateKey作業會呼叫 kms: ReEncrypt 透過更新加密內容來建立分支金鑰的使用中記錄。

最後,CreateKey操作調用 ddb: TransactWriteItems 編寫一個新項目,該項目將在步驟 2 中創建的表中保留分支密鑰。此項目具有下列屬性。

{ "branch-key-id" : branch-key-id, "type" : "branch:ACTIVE", "enc" : the branch key returned by the GenerateDataKeyWithoutPlaintext call, "version": "branch:version:the branch key version UUID", "create-time" : "timestamp", "kms-arn" : "the KMS key ARN you specified in Step 1", "hierarchy-version" : "1", "aws-crypto-ec:contextKey": "contextValue" }

建立階層式金鑰圈

若要初始化階層式金鑰圈,您必須提供下列值:

  • 分支金鑰存放區名稱

    您建立做為分支金鑰存放區使用的 DynamoDB 表的名稱。

  • 快取限制存留時間 (TTL)

    本機快取中的分支金鑰材料項目在到期前可以使用的時間 (以秒為單位)。快取限制 TTL 指定用戶端呼叫 AWS KMS 授權使用分支金鑰的頻率。該值必須大於零。當快取限制 TTL 到期時,會從本機快取中逐出項目。

  • 分支密鑰標識符

    識別分支金鑰存放區中作用中分支金鑰的。branch-key-id

    注意

    若要初始化多租戶使用的階層式金鑰環,您必須指定分支金鑰 ID 供應商,而不是指定. branch-key-id 如需詳細資訊,請參閱 搭配多租戶資料庫使用階層式金鑰圈

  • (可選)授予令牌列表

    如果您使用授權控制階層式金鑰圈中 KMS 金鑰的存取,則必須在初始化金鑰環時提供所有必要的授權權杖。

下列範例示範如何使用 DynamoDB 用戶端的 AWS 資料庫加密 SDK 初始化階層式金鑰圈。下列範例會指定 600 秒的快取限制 TTL。

Java
final MaterialProviders matProv = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); final CreateAwsKmsHierarchicalKeyringInput keyringInput = CreateAwsKmsHierarchicalKeyringInput.builder() .keyStore(branchKeyStoreName) .branchKeyId(branch-key-id) .ttlSeconds(600) .build(); final Keyring hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
C# / .NET
var matProv = new MaterialProviders(new MaterialProvidersConfig()); var keyringInput = new CreateAwsKmsHierarchicalKeyringInput { KeyStore = keystore, BranchKeyIdSupplier = branchKeyIdSupplier, TtlSeconds = 600 }; var hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);

旋轉您的活動分支密鑰

每個分支密鑰一次只能有一個活動版本。分層密鑰環通常使用每個活動分支密鑰版本來滿足多個請求。但是您可以控制重複使用活動分支密鑰的程度,並確定活動分支鍵的旋轉頻率。

分支密鑰不用於加密純文本數據密鑰。它們被用來派生加密明文數據密鑰的唯一包裝密鑰。包裝密鑰派生過程會產生具有 28 個字節隨機性的唯一 32 字節包裝密鑰。這意味著在發生密碼編譯耗損之前,分支密鑰可以導出超過 79 個八進制或 2 96 個唯一包裝密鑰。儘管這種用盡風險非常低,但由於業務或合約規則或政府法規,您可能需要輪換活動中的分支密鑰。

分支索引鍵的作用中版本會保持作用中狀態,直到您旋轉它為止。以前版本的 Active 分支密鑰將不會用於執行加密操作,也無法用於導出新的包裝密鑰。但是仍然可以查詢它們並提供包裝密鑰以解密它們在活動時加密的數據密鑰。

使用金鑰存放區服務VersionKey作業輪換作用中的分支金鑰。當您旋轉作用中的分支索引鍵時,會建立新的分支索引鍵來取代先前的版本。當您旋轉作用中的分支索引鍵時,不branch-key-id會變更。您必須在branch-key-id呼叫時指定識別目前作用中分支索引鍵的VersionKey

Java
keystore.VersionKey( VersionKeyInput.builder() .branchKeyIdentifier("branch-key-id") .build() );
C# / .NET
keystore.VersionKey(new VersionKeyInput{BranchKeyIdentifier = branchKeyId});

搭配多租戶資料庫使用階層式金鑰圈

透過為資料庫中的每個租用戶建立分支金鑰,您可以使用在作用中分支金鑰及其衍生包裝金鑰之間建立的金鑰階層來支援多租戶資料庫。然後,階層式金鑰圈會使用其不同的分支金鑰加密並簽署指定租用戶的所有資料。這可讓您將多租戶資料儲存在單一資料庫中,並透過分支金鑰隔離租用戶資料。

每個承租人都有自己的分支索引鍵,由唯一定義branch-key-id。一次只能有一個branch-key-id作用中版本。

分支金鑰 ID 供應商

您必須先為每個承租人建立分支金鑰,並建立分支金鑰 ID 供應商,才能初始化多租戶使用的階層式金鑰環。分支金鑰 ID 供應商會使用儲存在加密內容中的欄位來決定解密記錄所需的租用戶分支金鑰。根據預設,只有分割區和排序索引鍵會包含在加密內容中。但是,您可以使用SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT密碼編譯動作在加密內容中包含其他欄位。

注意

若要使用加SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT密動作,您必須使用 3.3 版或更新版本的 AWS 資料庫加密 SDK。在更新要包含的資料模型之前,請先將新版本部署至所有讀取器SIGN_AND_INCLUDE_IN_ENCRYPTION_CONTEXT

您可以使用分支金鑰 ID 供應商為您建立易記名稱,branch-key-ids以便輕鬆識別租用戶branch-key-id的正確名稱。例如,易記名稱可讓您參考分支索引鍵,tenant1而不是b3f61619-4d35-48ad-a275-050f87e15122

對於解密作業,您可以靜態設定單一階層式金鑰環,以限制對單一承租人的解密,或者您可以使用分支金鑰識別碼供應商來識別負責解密記錄的承租人。

首先,遵循先決條件程序的步驟 1 和步驟 2。然後,使用下列程序為每個承租人建立分支金鑰、建立分支金鑰識別碼供應商,並初始化階層式金鑰圈以供多租戶使用。

步驟 1:為資料庫中的每個租用戶建立分支金鑰

呼叫CreateKey資料庫中的每個租用戶。

下列作業會使用您在建立金鑰存放區服務時指定的 KMS 金鑰建立兩個分支金鑰,並將分支金鑰新增至您建立做為分支金鑰存放區使用的 DynamoDB 表格。相同的 KMS 金鑰必須保護所有分支金鑰。

Java
CreateKeyOutput branchKeyId1 = keystore.CreateKey(CreateKeyInput.builder().build()); CreateKeyOutput branchKeyId2 = keystore.CreateKey(CreateKeyInput.builder().build());
C# / .NET
var branchKeyId1 = keystore.CreateKey(new CreateKeyInput()); var branchKeyId2 = keystore.CreateKey(new CreateKeyInput());
步驟 2:建立分支金鑰 ID 供應商

下列範例會從步驟 1 中建立的兩個分支金鑰建立好記名稱,並呼叫CreateDynamoDbEncryptionBranchKeyIdSupplier使用 DynamoDB 用戶端的 AWS 資料庫加密 SDK 建立分支金鑰 ID 供應商。

Java
// Create friendly names for each branch-key-id class ExampleBranchKeyIdSupplier implements IDynamoDbKeyBranchKeyIdSupplier { private static String branchKeyIdForTenant1; private static String branchKeyIdForTenant2; public ExampleBranchKeyIdSupplier(String tenant1Id, String tenant2Id) { this.branchKeyIdForTenant1 = tenant1Id; this.branchKeyIdForTenant2 = tenant2Id; } // Create the branch key ID supplier final DynamoDbEncryption ddbEnc = DynamoDbEncryption.builder() .DynamoDbEncryptionConfig(DynamoDbEncryptionConfig.builder().build()) .build(); final BranchKeyIdSupplier branchKeyIdSupplier = ddbEnc.CreateDynamoDbEncryptionBranchKeyIdSupplier( CreateDynamoDbEncryptionBranchKeyIdSupplierInput.builder() .ddbKeyBranchKeyIdSupplier(new ExampleBranchKeyIdSupplier(branch-key-ID-tenant1, branch-key-ID-tenant2)) .build()).branchKeyIdSupplier();
C# / .NET
// Create friendly names for each branch-key-id class ExampleBranchKeyIdSupplier : DynamoDbKeyBranchKeyIdSupplierBase { private String _branchKeyIdForTenant1; private String _branchKeyIdForTenant2; public ExampleBranchKeyIdSupplier(String tenant1Id, String tenant2Id) { this._branchKeyIdForTenant1 = tenant1Id; this._branchKeyIdForTenant2 = tenant2Id; } // Create the branch key ID supplier var ddbEnc = new DynamoDbEncryption(new DynamoDbEncryptionConfig()); var branchKeyIdSupplier = ddbEnc.CreateDynamoDbEncryptionBranchKeyIdSupplier( new CreateDynamoDbEncryptionBranchKeyIdSupplierInput { DdbKeyBranchKeyIdSupplier = new ExampleBranchKeyIdSupplier(branch-key-ID-tenant1, branch-key-ID-tenant2) }).BranchKeyIdSupplier;
步驟 3:使用分支密鑰 ID 供應商初始化分層密鑰環

若要初始化階層式金鑰圈,您必須提供下列值:

  • 分支金鑰存放區名稱

  • 快取限制存留時間 (TTL)

  • 分支金鑰 ID 供應商

  • (選擇性) 快取

    如果您想要自訂快取類型或可儲存在本機快取中的分支金鑰材料項目數目,請在初始化金鑰環時指定快取類型和項目容量。

    緩存類型定義了線程模型。階層式金鑰環提供三種支援多租戶資料庫的快取類型:預設值、、 MultiThreaded. StormTracking

    如果您未指定快取,階層式金鑰圈會自動使用預設快取類型,並將項目容量設定為 1000。

    Default (Recommended)

    對於大多數用戶來說,默認緩存滿足他們的線程要求。默認緩存被設計為支持大量多線程環境。當分支密鑰材料條目到期時,默認緩存通知一個線程,該分支密鑰材料條目將提前 10 秒到期,以防止多個線程調 AWS KMS 用。這確保只有一個線程發送一個請求 AWS KMS 來刷新緩存。

    若要使用預設快取來初始化階層式金鑰圈,請指定下列值:

    • 目容量:限制可儲存在本機快取中的分支金鑰材料項目數量。

    Java
    .cache(CacheType.builder() .Default(DefaultCache.builder() .entryCapacity(100) .build())
    C#/.
    CacheType defaultCache = new CacheType { Default = new DefaultCache{EntryCapacity = 100} };

    預設值和 StormTracking 快取支援相同的執行緒模型,但您只需要指定項目容量,即可使用預設快取來初始化階層式金鑰環。如需更精細的快取自訂項目,請使用 StormTracking 快取。

    MultiThreaded

    MultiThreaded 快取可在多執行緒環境中安全使用,但不提供任何可減少 AWS KMS 或 Amazon DynamoDB 呼叫的功能。因此,當分支金鑰材料項目到期時,所有執行緒都會同時收到通知。這可能會導致多次 AWS KMS 呼叫以重新整理快取。

    若要使用 MultiThreaded 快取來初始化階層式金鑰圈,請指定下列值:

    • 目容量:限制可儲存在本機快取中的分支金鑰材料項目數量。

    • 目修剪尾端大小:定義達到入口容量時要修剪的項目數。

    Java
    .cache(CacheType.builder() .MultiThreaded(MultiThreadedCache.builder() .entryCapacity(100) .entryPruningTailSize(1) .build())
    C#/.
    CacheType multithreadedCache = new CacheType { MultiThreaded = new MultiThreadedCache { EntryCapacity = 100, EntryPruningTailSize = 1 } };
    StormTracking

    該 StormTracking 緩存被設計為支持大量多線程環境。當分支密鑰材料條目到期時, StormTracking 緩存通知一個線程,該分支密鑰材料條目將提前過期,以防止多個線程調 AWS KMS 用。這確保只有一個線程發送一個請求 AWS KMS 來刷新緩存。

    若要使用 StormTracking 快取來初始化階層式金鑰圈,請指定下列值:

    • 目容量:限制可儲存在本機快取中的分支金鑰材料項目數量。

    • 目修剪尾部大小:定義一次要修剪的分支關鍵材料項目數。

      預設值:1 個項目

    • 寬限期:定義嘗試重新整理分支金鑰材料到期前的秒數。

      預設值:10 秒

    • 寬限間隔:定義嘗試重新整理分支金鑰材料之間的秒數。

      預設值:1 秒

    • 扇出:定義可同時嘗試重新整理分支金鑰材料的次數。

      預設值:20 次嘗試

    • 存留時間 (TTL):定義嘗試重新整理分支金鑰材料逾時之前的秒數。每當緩存返回NoSuchEntry以響應 a 時GetCacheEntry,該分支密鑰都會被視為處於飛行狀態,直到用條目寫PutCache入相同的密鑰為止。

      預設值:20 秒

    • 睡眠:定義如果超過執行緒應該睡眠的秒數。fanOut

      預設值:20 毫秒

    Java
    .cache(CacheType.builder() .StormTracking(StormTrackingCache.builder() .entryCapacity(100) .entryPruningTailSize(1) .gracePeriod(10) .graceInterval(1) .fanOut(20) .inFlightTTL(20) .sleepMilli(20) .build())
    C#/.
    CacheType stormTrackingCache = new CacheType { StormTracking = new StormTrackingCache { EntryCapacity = 100, EntryPruningTailSize = 1, FanOut = 20, GraceInterval = 1, GracePeriod = 10, InFlightTTL = 20, SleepMilli = 20 } };
  • (可選)授予令牌列表

    如果您使用授權控制階層式金鑰圈中 KMS 金鑰的存取,則必須在初始化金鑰環時提供所有必要的授權權杖。

下列範例會使用在步驟 2 中建立的分支金鑰 ID 供應商、快取限制 TLL 600 秒,最大快取大小為 1000,初始化階層式金鑰圈。此範例使用 DynamoDB 用戶端的 AWS 資料庫加密 SDK 初始化階層式金鑰圈。

Java
final MaterialProviders matProv = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); final CreateAwsKmsHierarchicalKeyringInput keyringInput = CreateAwsKmsHierarchicalKeyringInput.builder() .keyStore(keystore) .branchKeyIdSupplier(branchKeyIdSupplier) .ttlSeconds(600) .cache(CacheType.builder() //OPTIONAL .Default(DefaultCache.builder() .entryCapacity(100) .build()) .build(); final Keyring hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
C# / .NET
var matProv = new MaterialProviders(new MaterialProvidersConfig()); var keyringInput = new CreateAwsKmsHierarchicalKeyringInput { KeyStore = keystore, BranchKeyIdSupplier = branchKeyIdSupplier, TtlSeconds = 600, Cache = new CacheType { Default = new DefaultCache { EntryCapacity = 100 } } }; var hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);

使用階層式金鑰圈進行可搜尋的加密

可搜索的加密使您無需解密整個數據庫即可搜索加密記錄。這是透過使用信標對加密欄位的純文字值進行索引來完成的。若要實作可搜尋的加密,您必須使用階層式金鑰圈。

金鑰儲存區CreateKey作業會同時產生分支索引鍵和信標金鑰。分支密鑰用於記錄加密和解密操作。信標索引鍵是用來產生信標。

分支金鑰和信標金鑰會受到您在建立金鑰存放區服務時指定的相同 AWS KMS key 保護。CreateKey作業呼叫 AWS KMS 產生分支金鑰後,會呼叫 kms:GenerateDataKeyWithoutPlaintext第二次使用下列要求產生信標金鑰。

{ "EncryptionContext": { "branch-key-id" : "branch-key-id", "type" : type, "create-time" : "timestamp", "logical-key-store-name" : "the logical table name for your branch key store", "kms-arn" : the KMS key ARN, "hierarchy-version" : 1 }, "KeyId": "the KMS key ARN", "NumberOfBytes": "32" }

產生這兩個金鑰之後,CreateKey作業會呼叫 ddb: TransactWriteItems 撰寫兩個新項目,這兩個新項目會在您的分支金鑰存放區中保留分支索引鍵和 Beacon 索引鍵。

設定標準信標時, AWS 資料庫加密 SDK 會查詢信標金鑰的分支金鑰存放區。然後,它使用基於 HMAC 的 extract-and-expand 密鑰派生函數(HKDF)將信標密鑰與標準信標的名稱相結合,以創建給定信標的 HMAC 密鑰。

與分支金鑰不同,分支金鑰存放區branch-key-id中每個只有一個信標金鑰版本。信標鍵永遠不會旋轉。

定義信標金鑰來源

當您定義標準和複合信標的信標版本時,必須識別信標 (Beacon) 索引鍵,並定義信標主要原物料的快取存留時間 (TTL)。信標金鑰材料會儲存在與分支金鑰不同的本機快取中。下列程式碼片段示範如何為單租keySource用戶資料庫定義。透過與其關聯的信標金鑰branch-key-id來識別您的信標金鑰。

Java
keySource(BeaconKeySource.builder() .single(SingleKeyStore.builder() .keyId(branch-key-id) .cacheTTL(6000) .build()) .build())
C# / .NET
KeySource = new BeaconKeySource { Single = new SingleKeyStore { KeyId = branch-key-id, CacheTTL = 6000 } }
在多租戶資料庫中定義信標來源

如果您有多租戶資料庫,則必須在設定. keySource

  • keyFieldName

    定義欄位名稱,此欄位名稱會儲存branch-key-id與指定承租人產生之信標所用之信標之信標關聯的信標索引鍵。keyFieldName可以是任何字串,但資料庫中所有其他欄位必須是唯一的。當您將新記錄寫入資料庫時,此欄位會儲存識別用來產生該記錄之任何信標的信標索引鍵。branch-key-id您必須在信標查詢中包含此欄位,並識別重新計算信標所需的適當信標主要材料。如需詳細資訊,請參閱 查詢多租戶資料庫中的信標

  • 快取記憶體

    區域信標快取記憶體中的信標主要材料項目在到期之前,可以使用的時間 (秒)。該值必須大於零。當快取限制 TTL 到期時,會從本機快取中逐出項目。

  • (選擇性) 快取

    如果您想要自訂快取類型或可儲存在本機快取中的分支金鑰材料項目數目,請在初始化金鑰環時指定快取類型和項目容量。

    緩存類型定義了線程模型。階層式金鑰環提供三種支援多租戶資料庫的快取類型:預設值、、 MultiThreaded. StormTracking

    如果您未指定快取,階層式金鑰圈會自動使用預設快取類型,並將項目容量設定為 1000。

    Default (Recommended)

    對於大多數用戶來說,默認緩存滿足他們的線程要求。默認緩存被設計為支持大量多線程環境。當分支密鑰材料條目到期時,默認緩存通知一個線程,該分支密鑰材料條目將提前 10 秒到期,以防止多個線程調 AWS KMS 用。這確保只有一個線程發送一個請求 AWS KMS 來刷新緩存。

    若要使用預設快取來初始化階層式金鑰圈,請指定下列值:

    • 目容量:限制可儲存在本機快取中的分支金鑰材料項目數量。

    Java
    .cache(CacheType.builder() .Default(DefaultCache.builder() .entryCapacity(100) .build())
    C#/.
    CacheType defaultCache = new CacheType { Default = new DefaultCache{EntryCapacity = 100} };

    預設值和 StormTracking 快取支援相同的執行緒模型,但您只需要指定項目容量,即可使用預設快取來初始化階層式金鑰環。如需更精細的快取自訂項目,請使用 StormTracking 快取。

    MultiThreaded

    MultiThreaded 快取可在多執行緒環境中安全使用,但不提供任何可減少 AWS KMS 或 Amazon DynamoDB 呼叫的功能。因此,當分支金鑰材料項目到期時,所有執行緒都會同時收到通知。這可能會導致多次 AWS KMS 呼叫以重新整理快取。

    若要使用 MultiThreaded 快取來初始化階層式金鑰圈,請指定下列值:

    • 目容量:限制可儲存在本機快取中的分支金鑰材料項目數量。

    • 目修剪尾端大小:定義達到入口容量時要修剪的項目數。

    Java
    .cache(CacheType.builder() .MultiThreaded(MultiThreadedCache.builder() .entryCapacity(100) .entryPruningTailSize(1) .build())
    C#/.
    CacheType multithreadedCache = new CacheType { MultiThreaded = new MultiThreadedCache { EntryCapacity = 100, EntryPruningTailSize = 1 } };
    StormTracking

    該 StormTracking 緩存被設計為支持大量多線程環境。當分支密鑰材料條目到期時, StormTracking 緩存通知一個線程,該分支密鑰材料條目將提前過期,以防止多個線程調 AWS KMS 用。這確保只有一個線程發送一個請求 AWS KMS 來刷新緩存。

    若要使用 StormTracking 快取來初始化階層式金鑰圈,請指定下列值:

    • 目容量:限制可儲存在本機快取中的分支金鑰材料項目數量。

    • 目修剪尾部大小:定義一次要修剪的分支關鍵材料項目數。

      預設值:1 個項目

    • 寬限期:定義嘗試重新整理分支金鑰材料到期前的秒數。

      預設值:10 秒

    • 寬限間隔:定義嘗試重新整理分支金鑰材料之間的秒數。

      預設值:1 秒

    • 扇出:定義可同時嘗試重新整理分支金鑰材料的次數。

      預設值:20 次嘗試

    • 存留時間 (TTL):定義嘗試重新整理分支金鑰材料逾時之前的秒數。每當緩存返回NoSuchEntry以響應 a 時GetCacheEntry,該分支密鑰都會被視為處於飛行狀態,直到用條目寫PutCache入相同的密鑰為止。

      預設值:20 秒

    • 睡眠:定義如果超過執行緒應該睡眠的秒數。fanOut

      預設值:20 毫秒

    Java
    .cache(CacheType.builder() .StormTracking(StormTrackingCache.builder() .entryCapacity(100) .entryPruningTailSize(1) .gracePeriod(10) .graceInterval(1) .fanOut(20) .inFlightTTL(20) .sleepMilli(20) .build())
    C#/.
    CacheType stormTrackingCache = new CacheType { StormTracking = new StormTrackingCache { EntryCapacity = 100, EntryPruningTailSize = 1, FanOut = 20, GraceInterval = 1, GracePeriod = 10, InFlightTTL = 20, SleepMilli = 20 } };

下列範例會使用在步驟 2 中建立的分支金鑰 ID 供應商、快取限制 TLL 600 秒,以及 1000 的項目容量,初始化階層式金鑰圈。

Java
final MaterialProviders matProv = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); final CreateAwsKmsHierarchicalKeyringInput keyringInput = CreateAwsKmsHierarchicalKeyringInput.builder() .keyStore(branchKeyStoreName) .branchKeyIdSupplier(branchKeyIdSupplier) .ttlSeconds(600) .cache(CacheType.builder() //OPTIONAL .Default(DefaultCache.builder() .entryCapacity(1000) .build()) .build(); final IKeyring hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);
C# / .NET
var matProv = new MaterialProviders(new MaterialProvidersConfig()); var keyringInput = new CreateAwsKmsHierarchicalKeyringInput { KeyStore = keystore, BranchKeyIdSupplier = branchKeyIdSupplier, TtlSeconds = 600, Cache = new CacheType { Default = new DefaultCache { EntryCapacity = 1000 } } }; var hierarchicalKeyring = matProv.CreateAwsKmsHierarchicalKeyring(keyringInput);