クライアント側の暗号化を使用したデータの保護 - Amazon Simple Storage Service

クライアント側の暗号化を使用したデータの保護

クライアント側の暗号化では、Amazon S3 に送信する前にデータを暗号化します。

クライアント側の暗号化を有効にするには、以下のオプションがあります。

  • AWS Key Management Service (AWS KMS) に保存されているカスタマーマスターキー (CMK) を使用する。

  • アプリケーション内に保存したキーを使用する。

AWS Encryption SDK

AWS Encryption SDK は、言語固有の SDK とは別のクライアント側の暗号化ライブラリです。この暗号化ライブラリを使用すると、Amazon S3 で暗号化のベストプラクティスをより簡単に実装できます。言語固有の AWS SDK の Amazon S3 暗号化クライアントとは異なり、AWS Encryption SDK には Amazon S3 に関連付けられておらず、任意の場所に保存されたデータの暗号化と復号化に使用できます。

AWS Encryption SDK と Amazon S3 の暗号化クライアントは、これらが異なるデータ形式で暗号化テキストを生成するため、互換性がありません。AWS Encryption SDK の詳細については、AWS Encryption SDK デベロッパーガイドを参照してください。

AWSAmazon S3 クライアント側の暗号化の SDK によるサポート

以下の AWS SDK はクライアント側の暗号化をサポートしています。

オプション1: AWS KMS に保存されている CMK を使用する

このオプションでは、Amazon S3 でデータをアップロードまたはダウンロードするときに、クライアント側の暗号化に AWS KMS CMK を使用します。

  • オブジェクトのアップロード時 — まず、クライアントはカスタマーマスターキー (CMK) ID を使用して、オブジェクトデータの暗号化に使用できる 新しい対称キーのリクエストを AWS KMS に送信します。AWS KMS は、ランダムに生成された 2 つのバージョンのデータキーを返します。

    • クライアントがオブジェクトデータの暗号化に使用するプレーンテキストのデータキー。

    • クライアントが Amazon S3 にオブジェクトのメタデータとしてアップロードする同じデータキーの暗号 BLOB。

    注記

    クライアントは、アップロードするオブジェクトごとに一意のデータキーを取得します。

  • オブジェクトのダウンロード時 — クライアントは、Amazon S3 から暗号化されたオブジェクトとオブジェクトのメタデータとして保存されているデータキーの暗号 BLOB をダウンロードします。次に、オブジェクトデータを復号できるように、AWS KMS に暗号 BLOB を送信して、データキーのプレーンテキストバージョンを取得します。

AWS KMS の詳細については、AWS Key Management Service デベロッパーガイドAWS Key Management Service とはを参照してください。

次のコードの例は、AWS KMS と AWS SDK for Java を使用して Amazon S3 にオブジェクトをアップロードする方法を示しています。AWS 管理の CMK を使用して、Amazon S3 にアップロードする前にクライアント側でデータを暗号化します。すでに CMK がある場合は、このコードの例の keyId 変数の値を指定することによって、その CMK を使用できます。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. Amazon S3 暗号化クライアントは、1 回限りの使用の対称キー (つまり、データ暗号化キーまたはデータキー) をローカルに生成します。データキーを使用して、単一の Amazon S3 オブジェクトのデータが暗号化されます。クライアントは、オブジェクトごとに個別のデータキーを生成します。

    2. クライアントは、提供されたマスターキーを使用して、データ暗号化キーを暗号化します。クライアントは、暗号化されたデータキーとその素材の説明を、オブジェクトメタデータの一部としてアップロードします。クライアントは、素材の説明を使用して、復号に使用するクライアント側のマスターキーを決定します。

    3. クライアントは暗号化されたデータを Amazon S3 にアップロードし、暗号化されたデータキーをオブジェクトメタデータ (x-amz-meta-x-amz-key) として Amazon S3 に保存します。

  • オブジェクトのダウンロード時 — クライアントは、Amazon S3 から暗号化されたオブジェクトをダウンロードします。クライアントは、オブジェクトのメタデータ内の素材の説明を使用して、まず、データキーの復号にどのマスターキーを使用するかを判断します。クライアントはそのマスターキーを使用してデータキーを復号し、そのデータキーを使用してオブジェクトを復号します。

提供するクライアント側のマスターキーは、対称キーにすることも、パブリック/プライベートのキーペアにすることもできます。以下のコードの例は、それぞれのタイプのキーを使用する方法を示しています。

詳細については、AWS SDK for Java と Amazon S3 でのクライアント側のデータ暗号化を参照してください。

注記

暗号化 API を初めて使用するときに暗号化のエラーメッセージが表示される場合は、使用する JDK のバージョンに暗号化と復号に使用するキーの最大長を 128 ビットに制限する Java Cryptography Extension (JCE) 管轄ポリシーファイルが含まれている可能性があります。AWS SDK では最大 256 ビットのキー長を必要とします。

最大キー長を確認するには、getMaxAllowedKeyLength() クラスの javax.crypto.Cipher メソッドを使用します。キー長の制限をなくすには、Java Cryptography Extension (JCE) 無制限暗号強度管轄ポリシーファイルをインストールします。

次のコードの例は、以下のタスクを行う方法を示しています。

  • 256 ビットの AES キーを生成する

  • Amazon S3 に送信する前に、AES キーを使用して、クライアント側でデータを暗号化する

  • 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 キーペアを生成する

  • Amazon S3 に送信する前に、RSA キーを使用して、クライアント側でデータを暗号化する

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