適用於 Java 的 DynamoDB 加密用戶端的範例程式碼 - AWS 資料庫加密 SDK

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

適用於 Java 的 DynamoDB 加密用戶端的範例程式碼

注意

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

下列範例示範如何使用 DynamoDB Encryption Client for Java 來保護應用程式中的 DynamoDB 資料表項目。您可以在 上aws-dynamodb-encryption-java儲存庫的範例目錄中找到更多範例 (並自行貢獻) GitHub。

使用 DynamoDBEncryptor

此範例示範如何將較低層級 DynamoDBEncryptorDirect KMS Provider 搭配使用。Direct KMS Provider 會在您指定的 AWS KMS key AWS Key Management Service (AWS KMS) 中產生並保護其密碼編譯材料。

您可以搭配 使用任何相容的密碼編譯材料提供者 (CMP)DynamoDBEncryptor,也可以搭配 DynamoDBMapper和 使用 Direct KMS ProviderAttributeEncryptor

請參閱完整的程式碼範例:AwsKmsEncryptedItem.java

步驟 1:建立直接KMS提供者

建立具有指定區域的 AWS KMS 用戶端執行個體。然後,使用用戶端執行個體,使用您偏好的 建立 Direct KMS Provider 執行個體 AWS KMS key。

此範例使用 Amazon Resource Name (ARN) 來識別 AWS KMS key,但您可以使用任何有效的金鑰識別符

final String keyArn = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"; final String region = "us-west-2"; final AWSKMS kms = AWSKMSClientBuilder.standard().withRegion(region).build(); final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kms, keyArn);
步驟 2:建立項目

此範例定義代表範例資料表項目record HashMap 的 。

final String partitionKeyName = "partition_attribute"; final String sortKeyName = "sort_attribute"; final Map<String, AttributeValue> record = new HashMap<>(); record.put(partitionKeyName, new AttributeValue().withS("value1")); record.put(sortKeyName, new AttributeValue().withN("55")); record.put("example", new AttributeValue().withS("data")); record.put("numbers", new AttributeValue().withN("99")); record.put("binary", new AttributeValue().withB(ByteBuffer.wrap(new byte[]{0x00, 0x01, 0x02}))); record.put("test", new AttributeValue().withS("test-value"));
步驟 3:建立 DynamoDBEncryptor

DynamoDBEncryptor 使用 Direct KMS Provider 建立 的執行個體。

final DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(cmp);
步驟 4:建立 DynamoDB 加密內容

DynamoDB 加密內容包含資料表結構及其加密和簽署方式的相關資訊。如果您使用 DynamoDBMapperAttributeEncryptor 會為您建立加密細節。

final String tableName = "testTable"; final EncryptionContext encryptionContext = new EncryptionContext.Builder() .withTableName(tableName) .withHashKeyName(partitionKeyName) .withRangeKeyName(sortKeyName) .build();
步驟 5:建立屬性動作物件

屬性動作決定項目的哪些屬性會加密並簽署,哪些屬性只會簽署,以及哪些屬性不會加密或簽署。

在 Java 中,若要指定屬性動作,您可以建立屬性名稱和EncryptionFlags值對 HashMap 的 。

例如,下列 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: // fall through to the next case case sortKeyName: // Partition and sort keys must not be encrypted, but should be signed actions.put(attributeName, signOnly); break; case "test": // Neither encrypted nor signed break; default: // Encrypt and sign all other attributes actions.put(attributeName, encryptAndSign); break; } }
步驟 6:將項目加密並簽署

若要加密並簽署資料表項目,請在 encryptRecord 的執行個體上呼叫 DynamoDBEncryptor 方法。指定資料表項目 (record)、屬性動作 (actions) 及加密細節 (encryptionContext)。

final Map<String, AttributeValue> encrypted_record = encryptor.encryptRecord(record, actions, encryptionContext);
步驟 7:將項目放入 DynamoDB 資料表

最後,將加密和簽署的項目放入 DynamoDB 資料表。

final AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder.defaultClient(); ddb.putItem(tableName, encrypted_record);

使用 DynamoDBMapper

下列範例示範如何將 DynamoDB 映射器協助程式類別與 Direct KMS Provider 搭配使用。Direct KMS Provider 會在您指定的 AWS KMS key AWS Key Management Service (AWS KMS) 中產生並保護其密碼編譯材料。

您可以搭配 使用任何相容的密碼編譯材料提供者 (CMP)DynamoDBMapper,也可以搭配較低層級 使用 Direct KMS ProviderDynamoDBEncryptor

請參閱完整的程式碼範例:AwsKmsEncryptedObject.java

步驟 1:建立直接KMS提供者

建立具有指定區域的 AWS KMS 用戶端執行個體。然後,使用用戶端執行個體,使用您偏好的 建立 Direct KMS Provider 執行個體 AWS KMS key。

此範例使用 Amazon Resource Name (ARN) 來識別 AWS KMS key,但您可以使用任何有效的金鑰識別符

final String keyArn = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"; final String region = "us-west-2"; final AWSKMS kms = AWSKMSClientBuilder.standard().withRegion(region).build(); final DirectKmsMaterialProvider cmp = new DirectKmsMaterialProvider(kms, keyArn);
步驟 2:建立 DynamoDB 加密程式和 DynamoDBMapper

使用您在上一個步驟中建立的直接KMS提供者來建立 DynamoDB 加密程式 的執行個體。您需要實例化較低層級的 DynamoDB Encryptor,才能使用 DynamoDB Mapper。

接下來,建立 DynamoDB 資料庫的執行個體和映射器組態,並使用它們來建立 DynamoDB Mapper 的執行個體。

重要

使用 DynamoDBMapper 加入或編輯已簽署 (或已加密並簽署) 的項目時,請將其設定成使用儲存行為 (例如 PUT) 納入所有屬性,如以下範例所示。否則,您將可能無法解密資料。

final DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(cmp) final AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder.standard().withRegion(region).build(); DynamoDBMapperConfig mapperConfig = DynamoDBMapperConfig.builder().withSaveBehavior(SaveBehavior.PUT).build(); DynamoDBMapper mapper = new DynamoDBMapper(ddb, mapperConfig, new AttributeEncryptor(encryptor));
步驟 3:定義 DynamoDB 資料表

接下來,定義您的 DynamoDB 資料表。請使用註釋指定屬性動作。此範例會建立代表資料表項目的 DynamoDB 資料表ExampleTable、 和 DataPoJo類別。

該範例資料表的主索引鍵屬性將經過簽署但未加密。這包括了標註 @DynamoDBHashKeypartition_attribute,以及標註 @DynamoDBRangeKeysort_attribute

凡是標註 @DynamoDBAttribute 的屬性 (例如 some numbers) 都將進行加密並簽署。例外是使用 DynamoDB Encryption Client 定義的 @DoNotEncrypt (僅簽署) 或 @DoNotTouch(不加密或簽署) 加密註釋的屬性。例如,leave me 屬性由於設有 @DoNotTouch 註釋,其將不會進行加密或簽署。

@DynamoDBTable(tableName = "ExampleTable") public static final class DataPoJo { private String partitionAttribute; private int sortAttribute; private String example; private long someNumbers; private byte[] someBinary; private String leaveMe; @DynamoDBHashKey(attributeName = "partition_attribute") public String getPartitionAttribute() { return partitionAttribute; } public void setPartitionAttribute(String partitionAttribute) { this.partitionAttribute = partitionAttribute; } @DynamoDBRangeKey(attributeName = "sort_attribute") public int getSortAttribute() { return sortAttribute; } public void setSortAttribute(int sortAttribute) { this.sortAttribute = sortAttribute; } @DynamoDBAttribute(attributeName = "example") public String getExample() { return example; } public void setExample(String example) { this.example = example; } @DynamoDBAttribute(attributeName = "some numbers") public long getSomeNumbers() { return someNumbers; } public void setSomeNumbers(long someNumbers) { this.someNumbers = someNumbers; } @DynamoDBAttribute(attributeName = "and some binary") public byte[] getSomeBinary() { return someBinary; } public void setSomeBinary(byte[] someBinary) { this.someBinary = someBinary; } @DynamoDBAttribute(attributeName = "leave me") @DoNotTouch public String getLeaveMe() { return leaveMe; } public void setLeaveMe(String leaveMe) { this.leaveMe = leaveMe; } @Override public String toString() { return "DataPoJo [partitionAttribute=" + partitionAttribute + ", sortAttribute=" + sortAttribute + ", example=" + example + ", someNumbers=" + someNumbers + ", someBinary=" + Arrays.toString(someBinary) + ", leaveMe=" + leaveMe + "]"; } }
步驟 4:加密並儲存資料表項目

現在,當您建立資料表項目並使用 DynamoDB Mapper 儲存該項目時,該項目會在新增至資料表之前自動加密和簽署。

本範例定義的資料表項目名為 record。該項目儲存至資料表之前,其屬性將根據 DataPoJo 類別中的註釋進行加密與簽署。就本例而言,所有屬性除了 PartitionAttributeSortAttributeLeaveMe 以外都將加密並簽署。PartitionAttributeSortAttributes 只會進行簽署,而 LeaveMe 屬性則完全未加密或簽署。

若要加密並簽署 record 項目,然後將其加入至 ExampleTable,請呼叫 DynamoDBMapper 類別的 save 方法。由於您的 DynamoDB Mapper 已設定為使用PUT儲存行為,因此項目會使用相同的主索引鍵取代任何項目,而不是更新它。這可確保簽章相符,而且您從資料表取得該項目後便能將其解密。

DataPoJo record = new DataPoJo(); record.setPartitionAttribute("is this"); record.setSortAttribute(55); record.setExample("data"); record.setSomeNumbers(99); record.setSomeBinary(new byte[]{0x00, 0x01, 0x02}); record.setLeaveMe("alone"); mapper.save(record);