本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
使用适用于 Java 的 DynamoDB 加密客户端
注意
我们的客户端加密库已重命名为 “ AWS 数据库加密 SDK”。以下主题提供有关适用于 Java 的 DynamoDB 加密客户端版本 1.x—2.x 以及适用于 Python 的 DynamoDB 加密客户端版本 1.x—3.x 的信息。有关更多信息,请参阅 DynamoDB 版本支持的AWS 数据库加密SDK。
本主题介绍了 Java 中的 DynamoDB 加密客户端的可能在其他编程语言实施中找不到的一些功能。
有关使用 DynamoDB 加密客户端进行编程的详细信息,请参阅 Java 示例、 GitHub上面的示例以及 DynamoDB 加密客户端的 Javadoc。aws-dynamodb-encryption-java repository
物品加密器: AttributeEncryptor 和 D ynamoDBEncryptor
Java 中的 DynamoDB 加密客户端有两个项目加密器:较低级别的 D 和。ynamoDBEncryptor AttributeEncryptor
AttributeEncryptor
是一个帮助程序类,可帮助您ynamoDBMapper在 DynamoD B 加密DynamoDB Encryptor
客户端中使用中的 D。 AWS SDK for Java 如果您结合使用 AttributeEncryptor
和 DynamoDBMapper
,则当您保存项目时,它会透明对项目进行加密并签名。当您加载项目时,它还会透明地验证和解密您的项目。
配置保存行为
您可以使用 AttributeEncryptor
和 DynamoDBMapper
来添加或替换具有仅已签名(或已加密和签名)的属性的表项目。对于这些任务,我们建议您将其配置为使用 PUT
保存行为,如以下示例所示。否则,您可能无法解密您的数据。
DynamoDBMapperConfig mapperConfig = DynamoDBMapperConfig.builder().withSaveBehavior(SaveBehavior.PUT).build(); DynamoDBMapper mapper = new DynamoDBMapper(ddb, mapperConfig, new AttributeEncryptor(encryptor));
如果您使用默认保存行为(仅更新在表项目中建模的属性),则未建模的属性将不会包含在签名中,且不会由表写入更改。因此,在以后读取所有的属性时,签名将无法验证,因为它不包括未建模的属性。
您也可以使用 CLOBBER
保存行为。该行为与 PUT
保存行为相同,只不过它将禁用乐观锁并覆盖表中的项目。
为防止签名错误,如果 AttributeEncryptor
与未配置 CLOBBER
或 PUT
保存行为的 DynamoDBMapper
一起使用,则 DynamoDB 加密客户端会抛出运行时系统异常。
要查看示例中使用的此代码,请参阅使用 D ynamoDBMapper和中aws-dynamodb-encryption-java
存储库中的 AwsKmsEncryptedObject GitHub.java
Java 中的属性操作
属性操作确定加密并签名的属性值、仅签名的属性值以及忽略的属性值。用于指定属性操作的方法取决于您使用的是DynamoDBMapper
和AttributeEncryptor
还是较低级别的 D ynamoDBEncryptor
重要
使用属性操作对表项进行加密后,在数据模型中添加或删除属性可能会导致签名验证错误,从而使您无法解密数据。有关详细说明,请参阅更改数据模型。
当您使用 DynamoDBMapper
和 AttributeEncryptor
时,使用注释指定属性操作。DynamoDB 加密客户端使用标准 DynamoDB 属性注释,该注释可定义属性类型以确定如何保护属性。默认情况下,除主键以外的所有属性均加密并签名,主键已签名但未加密。
注意
不要使用 @D Attribut ynamoDBVersion e 注解对属性的值进行加密,尽管你可以(也应该)对它们进行签名。否则,使用其值的情况将产生意外后果。
// 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")
要在ynamoDBEncryptor直接使用 DHashMap
对象,其中名称/值对表示属性名称和指定操作。
有效值适用于在 EncryptionFlags
枚举类型中定义的属性操作。您可以结合使用 ENCRYPT
和 SIGN
,单独使用 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; } }
然后,当您调用的encryptRecordDynamoDBEncryptor
,将映射指定为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
然后,它调用 DynamoDBEncryptor
的 setEncryptionContextOverrideOperator
方法。它使用 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
,请不要使用表名称覆盖运算符。而是使用原始表名称创建一个加密上下文,并将其提交给解密方法。