AWS KMS 手动密钥轮换和旧的加密数据

AWS KMS manual key rotation and old encrypted data

我正在尝试按照以下指南对上传到 AWS S3 的数据启用客户端加密:https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/kms-keys-s3-encryption.html。 我在 KMS 中创建了一个 CMK,禁用了自动轮换并使用了别名 test。一切正常,我可以将加密数据上传到 s3,然后从 s3 解密。 我正在尝试按照此处的指南执行手动轮换: https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html(手动旋转键) 根据文档,我需要创建一个新的 KMS 密钥并将别名更新为 test。 现在我想获取并解密已经上传到 s3 但使用旧密钥加密的数据。我得到这个(我在应用程序中使用别名而不是 keyId):

The key ID in the request does not identify a CMK that can perform this operation

这是有道理的,因为它是不同的密钥,如果我可以使用任何密钥来解密数据,那就很奇怪了。根据我的阅读,通过自动轮换,您可以免费获得这种行为,但是手动轮换呢?我是否需要解密所有数据并使用新密钥对其进行加密?也许我可以用相同的密钥 material 以某种方式创建一个新的 KMS 密钥,这样它的工作方式类似于自动轮换?

误导性的部分是文档页面上的 注释 说:

Note
When you begin using the new KMS key, be sure to keep the original KMS key enabled so that AWS KMS can decrypt data that the original KMS key encrypted.

这表明我可以只更改别名并且应该能够使用新的 CMS 密钥解密数据?我错过了什么?

var kmsEncryptionMaterials = new EncryptionMaterialsV2("alias/test", KmsType.KmsContext, new Dictionary<string, string>());

 var s3EncClient = new AmazonS3EncryptionClientV2(credentials, config, kmsEncryptionMaterials);

 var result = await s3EncClient.GetObjectAsync(new GetObjectRequest() {Key = "upload-test", BucketName = configuration.Bucket});

答案其实很简单。当 AmazonS3EncryptionClientV2 上传数据时,它使用“加密”(通过 GenerateDataKey 为您提供密钥的加密和未加密版本。加密密钥然后在元数据中上传到 S3。加密密钥的一部分包含 CMK 的信息是用来生成密钥的,也就是说我们解密数据的时候不需要再发送KeyId了。 在 AmazonS3EncryptionClientV2 中,我通过以下方式对 PutObjectAsyncGetObjectAsync 使用了相同的加密材料:

new EncryptionMaterialsV2(configuration.KeyId, KmsType.KmsContext, new Dictionary<string, string>());

不幸的是,当我们调用 GetObjectAsync 时,库使用提供的 KeyId 来解密数据。对于对称算法,这是可选参数,因为 KeyId 是上传的 s3 对象中元数据的一部分,因此无需再次提供它。解决方案非常简单,我们只需要重新创建 AmazonS3EncryptionClientV2 而无需提供密钥 ID。

 var s3EncClient2 = new AmazonS3EncryptionClientV2(credentials, config, new EncryptionMaterialsV2(null, KmsType.KmsContext, new Dictionary<string, string>()));