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

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

クライアント側の暗号化では、Amazon S3 に送信する前にデータを暗号化します。クライアント側の暗号化を有効にするには、以下のオプションがあります。

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

  • アプリケーションに保存したマスターキーを使用します。

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

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

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

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

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

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

    注記

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

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

AWS KMS の詳細については、AWS Key Management Service Developer Guide の「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 から暗号化されたオブジェクトをダウンロードします。クライアントは、オブジェクトのメタデータ内の素材の説明を使用して、まず、データキーの復号にどのマスターキーを使用するかを判断します。クライアントはそのマスターキーを使用してデータキーを復号し、そのデータキーを使用してオブジェクトを復号します。

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

詳細については、「Client-Side Data Encryption with the AWS SDK for Java and 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();