使用客户端加密保护数据 - Amazon Simple Storage Service
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

如果我们为英文版本指南提供翻译,那么如果存在任何冲突,将以英文版本指南为准。在提供翻译时使用机器翻译。

使用客户端加密保护数据

客户端加密 在将数据发送到 Amazon S3. 要启用客户端加密,您可以选择以下方法:

  • 使用存储在 AWS Key Management Service (AWS KMS)。

  • 使用您在应用程序内存储的主密钥。

以下 AWS 开发工具包支持客户端加密:

选项 1 使用存储在 AWS KMS

使用此选项,您使用 AWS KMS 在上传或下载 Amazon S3.

  • 上传对象时 — 使用CMKID,客户端首先将请求发送到 AWS KMS 对于可用于加密对象数据的CMK。 AWS KMS 返回随机生成的数据密钥的两个版本:

    • 客户端用于加密对象数据的数据密钥的纯文本版本

    • 客户端将作为对象元数据上传到 Amazon S3 的同一数据密钥的密码 blob

    注意

    客户端将为其上传的每个对象获取一个唯一的数据密钥。

  • 下载对象时 — 客户端从 Amazon S3 以及存储为对象元数据的数据密钥的CipherBlob版本。然后,客户端将密码 blob 发送到 AWS KMS 以获取密钥的纯文本版本,以便让客户端解密对象数据。

有关 AWS KMS,参见 什么是 AWS Key Management Service?AWS Key Management Service Developer Guide.

以下代码示例展示了如何上传对象 Amazon S3 使用 AWS KMS 与 AWS SDK for Java. 示例使用 AWS 管理CMK在上传到客户端的数据之前加密数据 Amazon S3. 如果您已经有CMK,可以通过指定 keyId 示例代码中的变量。如果没有 CMK,或需要另一个 CMK,则可以通过 Java API 生成一个。示例代码自动生成要使用的CMK。

有关创建和测试有效示例的说明,请参阅测试 Amazon S3 Java 代码示例.

AWSKMS kmsClient = AWSKMSClientBuilder.standard() .withRegion(Regions.DEFAULT_REGION) .build(); // create CMK for for testing this example CreateKeyRequest createKeyRequest = new CreateKeyRequest(); CreateKeyResult createKeyResult = kmsClient.createKey(createKeyRequest); // -- // specify an Amazon KMS customer master key (CMK) ID String keyId = createKeyResult.getKeyMetadata().getKeyId(); String s3ObjectKey = "EncryptedContent1.txt"; String s3ObjectContent = "This is the 1st content to encrypt"; // -- AmazonS3EncryptionV2 s3Encryption = AmazonS3EncryptionClientV2Builder.standard() .withRegion(Regions.US_WEST_2) .withCryptoConfiguration(new CryptoConfigurationV2().withCryptoMode(CryptoMode.StrictAuthenticatedEncryption)) .withEncryptionMaterialsProvider(new KMSEncryptionMaterialsProvider(keyId)) .build(); s3Encryption.putObject(bucket_name, s3ObjectKey, s3ObjectContent); System.out.println(s3Encryption.getObjectAsString(bucket_name, s3ObjectKey)); // schedule deletion of CMK generated for testing ScheduleKeyDeletionRequest scheduleKeyDeletionRequest = new ScheduleKeyDeletionRequest().withKeyId(keyId).withPendingWindowInDays(7); kmsClient.scheduleKeyDeletion(scheduleKeyDeletionRequest); s3Encryption.shutdown(); kmsClient.shutdown();

选项 2:使用应用程序内存储的主密钥

使用此选项,您可以使用存储在您的客户端数据加密应用程序内的主密钥。

重要

客户端主密钥和未加密的数据从来不会发送到 AWS. 务必安全地管理加密密钥。如果您丢失了加密密钥,您就不能解密数据了。

以下是具体工作原理:

  • 上传对象时 — 您提供客户端主键到 Amazon S3 加密客户端。该客户端仅使用该主密钥来加密客户端随机生成的数据加密密钥。

    以下步骤描述了流程:

    1. TheThethe Amazon S3 加密客户端生成一次性使用对称密钥(也称为 数据加密密钥数据密钥)当地。它使用数据密钥加密单个 Amazon S3 对象的数据。该客户端将为每个对象生成一个单独的数据密钥。

    2. 该客户端使用您提供的主密钥来加密数据加密密钥。客户端会将加密的数据密钥及其材料说明作为对象元数据的一部分上传。该客户端利用材料描述来确定要用于解密的客户端主密钥。

    3. 客户端将加密数据上传到 Amazon S3 将加密的数据密钥保存为对象元数据(x-amz-meta-x-amz-key)中) Amazon S3.

  • 下载对象时 — 客户端从 Amazon S3. 通过使用对象元数据中的材料说明,该客户端将确定要用于解密数据密钥的主密钥。该客户端将使用该主密钥解密数据密钥,然后使用该数据密钥对对象进行解密。

您提供的客户端主密钥可以是对称密钥,也可以是公有/私有密钥对。以下代码示例显示如何使用每种类型的密钥。

有关详细信息,请参阅 客户端数据加密与 AWS SDK for Java 和 Amazon S3.

注意

如果您第一次使用加密API获得密码加密错误消息,JDK的版本可能会有一个Java密码扩展(JCE)管辖区策略文件,该文件将加密和解密转换的最大密钥长度限制为128位。TheThethe AWS SDK要求最大密钥长度为256位。

要检查您的最大密钥长度,请使用 getMaxAllowedKeyLength() 方法 javax.crypto.Cipher 类。要删除密钥长度限制,请安装 Java密码扩展(JCE)无限强度管辖权政策文件.

以下代码示例显示如何执行以下任务:

  • 生成 256 位 AES 密钥

  • 将数据发送到 之前在客户端上使用 AES 密钥加密数据Amazon S3.

  • 使用 AES 密钥解密从 接收的数据Amazon S3.

  • 打印解密对象的字符串表示。

有关创建和测试有效示例的说明,请参阅测试 Amazon S3 Java 代码示例.

KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); keyGenerator.init(256); // -- // generate a symmetric encryption key for testing SecretKey secretKey = keyGenerator.generateKey(); String s3ObjectKey = "EncryptedContent2.txt"; String s3ObjectContent = "This is the 2nd content to encrypt"; // -- AmazonS3EncryptionV2 s3Encryption = AmazonS3EncryptionClientV2Builder.standard() .withRegion(Regions.DEFAULT_REGION) .withClientConfiguration(new ClientConfiguration()) .withCryptoConfiguration(new CryptoConfigurationV2().withCryptoMode(CryptoMode.AuthenticatedEncryption)) .withEncryptionMaterialsProvider(new StaticEncryptionMaterialsProvider(new EncryptionMaterials(secretKey))) .build(); s3Encryption.putObject(bucket_name, s3ObjectKey, s3ObjectContent); System.out.println(s3Encryption.getObjectAsString(bucket_name, s3ObjectKey)); s3Encryption.shutdown();

以下代码示例显示如何执行以下任务:

  • 生成2048位RSA密钥对用于测试目的。

  • 将数据发送到 之前在客户端上使用 RSA 密钥加密数据。Amazon S3.

  • 使用 RSA 密钥解密从 接收的数据。Amazon S3.

  • 打印解密对象的字符串表示。

有关创建和测试有效示例的说明,请参阅测试 Amazon S3 Java 代码示例.

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(2048); // -- // generate an asymmetric key pair for testing KeyPair keyPair = keyPairGenerator.generateKeyPair(); String s3ObjectKey = "EncryptedContent3.txt"; String s3ObjectContent = "This is the 3rd content to encrypt"; // -- AmazonS3EncryptionV2 s3Encryption = AmazonS3EncryptionClientV2Builder.standard() .withRegion(Regions.US_WEST_2) .withCryptoConfiguration(new CryptoConfigurationV2().withCryptoMode(CryptoMode.StrictAuthenticatedEncryption)) .withEncryptionMaterialsProvider(new StaticEncryptionMaterialsProvider(new EncryptionMaterials(keyPair))) .build(); s3Encryption.putObject(bucket_name, s3ObjectKey, s3ObjectContent); System.out.println(s3Encryption.getObjectAsString(bucket_name, s3ObjectKey)); s3Encryption.shutdown();