使用適用於 Java 的 DynamoDB Encryption Client - AWS 資料庫加密 SDK

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

使用適用於 Java 的 DynamoDB Encryption Client

注意

我們的用戶端加密程式庫已重新命名為 AWS 資料庫加密 SDK。下列主題提供有關適用於 Java 的 DynamoDB Encryption Client 版本 1.x —2.x 和適用於 Python 的 DynamoDB Encryption Client 版本 1.x —3.x 的資訊。如需詳細資訊,請參閱AWS 支援 SDK的 DynamoDB 資料庫加密版本

本主題說明了 Java 中 DynamoDB Encryption Client 的某些功能,這些功能在其他程式設計語言實作中可能找不到。

如需使用 DynamoDB Encryption Client 進行程式設計的詳細資訊,請參閱 Java 範例aws-dynamodb-encryption-java repository 上的範例 GitHub,以及 DynamoDB Encryption Client 的 Javadoc

項目加密器: AttributeEncryptor 和 DynamoDBEncryptor

Java 中的 DynamoDB Encryption Client 有兩個項目加密器:較低層級的 DynamoDBEncryptor 和 AttributeEncryptor。

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

設定儲存行為

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

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

如果您使用預設儲存行為,只會更新資料表項目中建模的屬性,則未建模的屬性不會包含在簽章中,也不會透過資料表寫入變更。因此,在所有屬性的稍後讀取中,簽章將不會驗證,因為它不包含未建模的屬性。

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

為了防止簽章錯誤,如果 AttributeEncryptor 與未設定為 CLOBBER或 的儲存行為DynamoDBMapper的 搭配使用,DynamoDB Encryption Client 會擲回執行期例外狀況PUT

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

Java 中的屬性動作

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

重要

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

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

注意

不要使用 @D ynamoDBVersion屬性註釋 加密屬性的值,雖然您可以 (且應該) 簽署它們。否則,使用其值的情況將會造成想不到的影響。

// 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")

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

// 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 Encryption Client 會擲回錯誤。您無法加密您未簽署的屬性。

ENCRYPT SIGN
警告

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

如果您在加密內容中指定主金鑰,然後在任一主金鑰屬性的屬性動作ENCRYPT中指定 ,則 DynamoDB Encryption Client 會擲回例外狀況。

例如,下列 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; } }

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

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

覆寫表格名稱

在 DynamoDB Encryption Client 中,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,請勿使用表格名稱覆寫運算子。請改為使用原始表格名稱建立加密內容,並將其提交至解密方法。