适用于 Java 的 DynamoDB 加密客户端的示例代码 - AWS 数据库加密 SDK

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

适用于 Java 的 DynamoDB 加密客户端的示例代码

注意

我们的客户端加密库已重命名为 AWS 数据库加密SDK。以下主题提供有关适用于 Java 的 DynamoDB 加密客户端版本 1.x—2.x 以及适用于 Python 的 DynamoDB 加密客户端版本 1.x—3.x 的信息。有关更多信息,请参阅 DynamoDB 版本支持的AWS 数据库加密SDK

以下示例为您演示如何使用适用于 Java 的 DynamoDB 加密客户端来保护应用程序中的 DynamoDB 表项目。你可以在上aws-dynamodb-encryption-java存储库的示例目录中找到更多示例(并贡献自己的示例) GitHub。

使用 D ynamoDBEncryptor

此示例说明如何将较低级别的 D ynamoDBEncryptor直接KMS提供程序一起使用。直接KMS提供商根据您指定的 AWS KMS keyin AWS Key Management Service (AWS KMS) 生成和保护其加密材料。

您可以将任何兼容的加密材料提供程序 (CMP) 与一起使用DynamoDBEncryptor,也可以将直接KMS提供程序与DynamoDBMapperAttributeEncryptor一起使用。

查看完整的代码示例AwsKmsEncryptedItem.java

步骤 1:创建直接KMS提供商

创建指定区域的 AWS KMS 客户端实例。然后,使用该客户端实例创建您首选的直接KMS提供商实例 AWS KMS key。

此示例使用 Amazon 资源名称 (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:创建 D ynamoDBEncryptor

使用直接KMS提供商创建DynamoDBEncryptor的实例。

final DynamoDBEncryptor encryptor = DynamoDBEncryptor.getInstance(cmp);
步骤 4:创建 DynamoDB 加密上下文

DynamoDB 加密上下文包含有关表结构以及其如何加密和签名的信息。如果使用的是 DynamoDBMapper,则 AttributeEncryptor 会为您创建加密上下文。

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);

使用 D ynamoDBMapper

以下示例向您展示如何将 DynamoDB 映射器帮助程序类与直接提供程序一起使用。KMS直接KMS提供商根据您指定的 AWS KMS keyin AWS Key Management Service (AWS KMS) 生成和保护其加密材料。

您可以将任何兼容的加密材料提供程序 (CMP) 与一起使用DynamoDBMapper,也可以将直接KMS提供程序与较低级别DynamoDBEncryptor的提供程序一起使用。

查看完整的代码示例AwsKmsEncryptedObject.java

步骤 1:创建直接KMS提供商

创建指定区域的 AWS KMS 客户端实例。然后,使用该客户端实例创建您首选的直接KMS提供商实例 AWS KMS key。

此示例使用 Amazon 资源名称 (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 加密器和 D ynamoDBMapper

使用您在上一步中创建的直接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 类。

在此示例表中,将为主键属性签名,但不进行加密。这适用于使用 @DynamoDBHashKey 进行注释的 partition_attribute 以及使用 @DynamoDBRangeKey 进行注释的 sort_attribute

将为使用 @DynamoDBAttribute 进行注释的属性(如 some numbers)加密并签名。使用 @DoNotEncrypt(仅签名)或 DynamoDB 加密客户端定义的 @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);