클라이언트 측 암호화를 사용하여 데이터 보호 - Amazon Simple Storage Service

클라이언트 측 암호화를 사용하여 데이터 보호

클라이언트 측 암호화는 Amazon S3로 보내기 전에 데이터를 암호화하는 것을 가리킵니다.

클라이언트 측 암호화를 활성화하기 위한 다음 옵션이 있습니다.

  • AWS Key Management Service(AWS KMS)에 저장된 AWS KMS key를 사용합니다.

  • 애플리케이션 내에 저장한 키를 사용합니다.

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 개발자 안내서를 참조하세요.

Amazon S3 클라이언트 측 암호화를 위한 AWS SDK 지원

다음 AWS SDK에서 클라이언트 측 암호화를 지원합니다.

자세한 내용 및 예제는 AWS 일반 참조AWS클라이언트 측 암호화를 위한 SDK 지원을 참조하세요.

옵션 1: AWS KMS에 저장된 KMS 키 사용

이 옵션을 사용하면 Amazon S3에서 데이터를 업로드하거나 다운로드할 때 클라이언트 측 암호화에 AWS KMS key를 사용할 수 있습니다.

  • 객체를 업로드할 때 - KMS 키 ID를 사용하여 클라이언트가 먼저 AWS KMS로 객체 데이터를 암호화하는 데 사용할 수 있는 새 대칭 키를 요청합니다. AWS KMS는 임의로 생성된 데이터 키의 다음 두 가지 버전을 반환합니다.

    • 클라이언트가 객체 데이터를 암호화하는 데 사용하는 일반 텍스트 버전의 데이터 키

    • 클라이언트가 Amazon S3에 객체 메타데이터로 업로드하는 동일한 데이터 키의 암호 BLOB

    참고

    클라이언트는 업로드하는 각 객체에 대해 고유한 데이터 키를 가져옵니다.

  • 객체를 다운로드할 때 - 클라이언트가 Amazon S3에서 암호화된 객체를 객체 메타데이터로 저장된 데이터 키의 암호 BLOB 버전과 함께 다운로드합니다. 그런 다음 클라이언트가 암호 BLOB를 AWS KMS로 보내 객체 데이터의 암호 해독을 위해 일반 텍스트 버전의 데이터 키를 가져옵니다.

AWS KMS에 대한 자세한 내용은 AWS Key Management Service 개발자 안내서AWS Key Management Service란 무엇입니까?를 참조하세요.

다음 코드 예제에서는 AWS SDK for Java와 함께 AWS KMS를 사용하여 Amazon S3에 객체를 업로드하는 방법을 보여 줍니다. 이 예제에서는 데이터를 Amazon S3로 업로드하기 전에 AWS 관리형 키를 사용하여 클라이언트 측 데이터를 암호화합니다. KMS 키가 이미 있는 경우에는 예제 코드에서 keyId 변수의 값을 지정하여 이 키를 사용할 수 있습니다. KMS 키가 없거나 다른 키가 필요한 경우 Java API를 통해 하나를 생성할 수 있습니다. 예제 코드는 사용할 KMS 키를 자동으로 생성합니다.

실제 예제를 작성 및 테스트하는 방법에 대한 자세한 내용은 Amazon S3 Java 코드 예제 테스트 단원을 참조하세요.

AWSKMS kmsClient = AWSKMSClientBuilder.standard() .withRegion(Regions.DEFAULT_REGION) .build(); // create KMS key for for testing this example CreateKeyRequest createKeyRequest = new CreateKeyRequest(); CreateKeyResult createKeyResult = kmsClient.createKey(createKeyRequest); // -- // specify an AWS KMS key 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 KMS key 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 암호화 클라이언트에서 일회용 대칭 키(즉 데이터 암호화 키 또는 데이터 키)를 로컬로 생성합니다. 또한 데이터 키를 사용하여 단일 Amazon S3 객체의 데이터를 암호화합니다. 클라이언트는 각 객체에 대한 개별 데이터 키를 생성합니다.

    2. 클라이언트에서 사용자가 제공하는 루트 키를 사용하여 데이터 암호화 키를 암호화합니다. 클라이언트에서 암호화된 데이터 키 및 해당 구성 요소 설명을 객체 메타데이터의 일부로 업로드합니다. 클라이언트는 구성 요소 설명을 사용하여 어떤 클라이언트 측 루트 키를 암호화에 사용할지 결정합니다.

    3. 그런 다음 클라이언트에서 기본적으로 암호화된 데이터를 Amazon S3에 업로드하고 암호화된 데이터 키를 객체 메타데이터(x-amz-meta-x-amz-key)로 Amazon S3에 저장합니다.

  • 객체를 다운로드할 때 - 클라이언트가 먼저 Amazon S3에서 암호화된 객체를 다운로드합니다. 클라이언트에서 먼저 객체 메타데이터의 구성 요소 설명을 사용하여 데이터 키의 암호 복호화에 어떤 루트 키를 사용할지를 결정합니다. 클라이언트는 해당 루트 키를 사용하여 데이터 키를 복호화하고 나서 데이터 키를 사용하여 객체를 복호화합니다.

사용자가 제공하는 클라이언트 측 루트 키는 대칭 키 또는 퍼블릭/프라이빗 키 페어일 수 있습니다. 다음 코드 예제에서는 각 유형의 키를 사용하는 방법을 보여줍니다.

자세한 내용은 AWS SDK for Java 및 Amazon S3를 사용하여 클라이언트 측 암호화클라이언트 측 암호화를 위한 AWS SDK 지원을 참조하세요.

참고

처음으로 암호화 API를 사용할 때 암호 암호화 오류 메시지가 표시되는 경우 사용 중인 버전의 JDK에 암호화 및 암호 해독 변환에 대한 최대 키 길이를 128비트로 제한하는 Java Cryptography Extension(JCE) Jurisdiction Policy File이 있을 수 있습니다. AWS SDK에서는 최대 키 길이가 256비트여야 합니다.

최대 키 길이를 확인하려면 getMaxAllowedKeyLength() 클래스의 javax.crypto.Cipher 메서드를 사용하세요. 키 길이 제한을 제거하려면 Java Cryptography Extension(JCE) Unlimited Strength Jurisdiction Policy File을 설치하세요.

다음 코드 예제에서는 이러한 작업을 수행하는 방법을 보여줍니다.

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