使用 DynamoDB 密用戶端 - AWS 資料庫加密 SDK

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

使用 DynamoDB 密用戶端

注意

我們的客戶端加密庫被重命名為 AWS 數據庫加密 SDK。下列主題提供有關版本 1 的資訊。 X-2. 適用於 Java 和版本 1 的 x 個加密用戶端。 X — 3. 適用於 Python 的 x 個 DynamoDB 密用戶端。如需詳細資訊,請參閱適用於 DynamoDB 版本支援的資AWS 料庫加密 SDK

本主題說明 Java 中 DynamoDB 加密用戶端的一些功能,這些功能可能在其他程式設計語言實作中找不到這些功能。

如需有關使用 DynamoDB 加密用戶端進行程式設計的詳細資訊,請參閱aws-dynamodb-encryption-java repository上 GitHub的 Java 範例、中的範例以及 DynamoDB 加密用戶端的 Javadoc

項目加密器: AttributeEncryptor 和 DynamoDBEncryptor

Java 中的 DynamoDB 加密用戶端有兩個項目加密器:較低層級的. AttributeEncryptor

AttributeEncryptor是一個協助程式類別,可協助您在 DynamoDB 加密用戶端中 AWS SDK for Java 搭配使用 DynamoDBMapperDynamoDB Encryptor當您搭配 DynamoDBMapper 使用 AttributeEncryptor 時,它會在您保存項目時,透明地加密和簽署您的項目。當您載入項目時,它也會透明地驗證和解密您的項目。

設定儲存行為

您可以使用AttributeEncryptorDynamoDBMapper來新增或取代為僅簽署或加密和已簽署的屬性的表格項目。對於這些任務,我們建議您將其設定為使用 PUT 儲存行為,如下列範例所示。否則,您將可能無法解密資料。

DynamoDBMapperConfig mapperConfig = DynamoDBMapperConfig.builder().withSaveBehavior(SaveBehavior.PUT).build(); DynamoDBMapper mapper = new DynamoDBMapper(ddb, mapperConfig, new AttributeEncryptor(encryptor));

如果您使用預設儲存行為 (此行為僅更新表格項目中模型化的屬性),則未建模的屬性不會包含在簽章中,且不會因表格寫入而變更。因此,稍後讀取所有屬性時,簽名將不會驗證,因為它不包含未建模的屬性。

您也可以使用 CLOBBER 儲存行為。這種行為與 PUT 儲存行為完全相同,差別在於它會停用樂觀鎖定並覆寫表格中的項目。

為了防止簽章錯誤,如果未設定或的儲存行為,則 DynamoDB 加密用戶端會擲回執行階段例外狀況。AttributeEncryptor DynamoDBMapper CLOBBER PUT

若要查看範例中使用的此程式碼使用 DynamoDBMapper,請參閱中aws-dynamodb-encryption-java存放庫中 GitHub的 AwsKmsEncryptedObject.java 範例。

Java 中的屬性動作

屬性動作決定哪些屬性值會加密並簽署,哪些屬性值只會簽署,以及哪些屬性值會予忽略。您用來指定屬性動作的方法取決於您使用的是 DynamoDBMapperAttributeEncryptor,還是較低層層級的 DynamoDBEncryptor

重要

使用屬性動作加密表格項目後,從資料模型新增或移除屬性可能會導致簽章驗證錯誤,讓您無法解密資料。如需更詳細的說明,請參閱變更您的資料模型

當您使用 DynamoDBMapperAttributeEncryptor 時,您可使用註釋來指定屬性動作。DynamoDB 加密用戶端使用標準 DynamoDB 屬性註釋來定義屬性類型,以決定如何保護屬性。除了主要索引鍵 (簽署但不加密) 以外,所有屬性都預設會進行加密和簽署。

注意

不要使用 @DynamoDB VersionAttribute 註釋加密屬性的值,儘管您可以(也應該)對其進行簽名。否則,使用其值的情況將會造成想不到的影響。

// Attributes are encrypted and signed @DynamoDBAttribute(attributeName="Description") // Partition keys are signed but not encrypted @DynamoDBHashKey(attributeName="Title") // Sort keys are signed but not encrypted @DynamoDBRangeKey(attributeName="Author")

若要指定例外狀況,請使用在適用於 Java 的 DynamoDB 加密用戶端中定義的加密註解。如果您在類別層級指定例外狀況,這些例外狀況就會成為類別的預設值。

// Sign only @DoNotEncrypt // Do nothing; not encrypted or signed @DoNotTouch

例如,這些註釋會簽署但不會加密 PublicationYear 屬性,且不會加密或簽署 ISBN 屬性值。

// Sign only (override the default) @DoNotEncrypt @DynamoDBAttribute(attributeName="PublicationYear") // Do nothing (override the default) @DoNotTouch @DynamoDBAttribute(attributeName="ISBN")

若要在您直接使用 DynamoDBEncryptor 時指定屬性動作,請建立 HashMap 物件,其中的名稱值組代表屬性名稱和指定的動作。

屬性動作的有效值會定義於 EncryptionFlags 列舉類型中。您可以同時使用 ENCRYPTSIGN、單獨使用 SIGN,或省略兩者。但是,如果您ENCRYPT單獨使用,DynamoDB 加密用戶端會擲回錯誤。您無法加密您未簽署的屬性。

ENCRYPT SIGN
警告

請勿加密主索引鍵的屬性。它們必須保持純文字格式,以便 DynamoDB 可以在不執行完整表格掃描的情況下尋找項目。

如果您在加密內容中指定主金鑰,然後ENCRYPT在任一主索引鍵屬性的屬性動作中指定,DynamoDB 加密用戶端會擲回例外狀況。

例如,下列 Java 程式碼會建立一actions HashMap 個加密並簽署record項目中的所有屬性。例外狀況是分割索引鍵和排序索引鍵屬性 (已簽署但未加密),以及未簽署或加密的 test 屬性。

final EnumSet<EncryptionFlags> signOnly = EnumSet.of(EncryptionFlags.SIGN); final EnumSet<EncryptionFlags> encryptAndSign = EnumSet.of(EncryptionFlags.ENCRYPT, EncryptionFlags.SIGN); final Map<String, Set<EncryptionFlags>> actions = new HashMap<>(); for (final String attributeName : record.keySet()) { switch (attributeName) { case partitionKeyName: // no break; falls through to next case case sortKeyName: // Partition and sort keys must not be encrypted, but should be signed actions.put(attributeName, signOnly); break; case "test": // Don't encrypt or sign break; default: // Encrypt and sign everything else actions.put(attributeName, encryptAndSign); break; } }

然後,當您呼叫的 En encryptRecord 方法時DynamoDBEncryptor,請將對應指定為參數的attributeFlags值。例如,encryptRecord 的這項呼叫會使用 actions 映射。

// Encrypt the plaintext record final Map<String, AttributeValue> encrypted_record = encryptor.encryptRecord(record, actions, encryptionContext);

覆寫表格名稱

在 DynamoDB 加密用戶端中,DynamoDB 表格的名稱是 DynamoDB 加密內容的一個元素,會傳遞至加密和解密方法。當您加密或簽署表格項目時,DynamoDB 加密內容 (包括資料表名稱) 會以密碼編譯方式繫結至加密文字。如果傳遞至解密方法的 DynamoDB 加密內容與傳遞給加密方法的 DynamoDB 加密內容不符,解密作業就會失敗。

有時候,資料表名稱會變更,例如當您備份資料表或執行point-in-time 復原時。解密或驗證這些項目的簽章時,您必須傳入用於加密和簽署項目的相同 DynamoDB 加密內容,包括原始表格名稱。目前的表格名稱是不需要的。

使用時DynamoDBEncryptor,您可以手動組合 DynamoDB 加密內容。但是,如果您使用的是DynamoDBMapper,會為您AttributeEncryptor建立 DynamoDB 加密內容,包括目前的表格名稱。若要告訴 AttributeEncryptor 建立具有不同資料表名稱的加密內容,請使用 EncryptionContextOverrideOperator

例如,下列程式碼會建立密碼編譯材料提供者 (CMP) 和 DynamoDBEncryptor。然後它會呼叫 DynamoDBEncryptorsetEncryptionContextOverrideOperator 方法。它使用覆寫一個表格名稱的 overrideEncryptionContextTableName 運算子。以這種方式進行設定時,AttributeEncryptor會建立一個 DynamoDB 加密內容,其newTableName中包含代替. oldTableName 如需完整範例,請參閱 EncryptionContextOverridesWithDynamoDBMapper.java

final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kms, keyArn); final DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(cmp); encryptor.setEncryptionContextOverrideOperator(EncryptionContextOperators.overrideEncryptionContextTableName( oldTableName, newTableName));

當您呼叫 DynamoDBMapper (解密和驗證項目) 的載入方法時,您可以指定原始資料表名稱。

mapper.load(itemClass, DynamoDBMapperConfig.builder() .withTableNameOverride(DynamoDBMapperConfig.TableNameOverride.withTableNameReplacement(oldTableName)) .build());

您也可以使用 overrideEncryptionContextTableNameUsingMap 運算子,該運算子會覆寫多個表格名稱。

表格名稱覆寫運算子通常用於解密資料和驗證簽章。不過,您可以使用它們在加密和簽署時,將 DynamoDB 加密內容中的表格名稱設定為不同的值。

如果您使用的是 DynamoDBEncryptor,請勿使用表格名稱覆寫運算子。請改為使用原始表格名稱建立加密內容,並將其提交至解密方法。