Amazon Simple Storage Service
개발자 안내서 (API 버전 2006-03-01)

AWS SDK for Java를 사용하여 고객 제공 암호화 키로 서버 측 암호화 지정

다음 예제에서는 객체에 대해 고객 제공 키를 사용한 서버 측 암호화(SSE-C)를 요청하는 방법을 보여줍니다. 이 예제에서는 다음 작업을 수행합니다. 각 작업에서는 요청에 SSE-C 관련 헤더를 지정하는 방법을 보여 줍니다.

  • 객체 업로드 - 고객 제공 암호화 키를 사용하여 객체를 업로드하고 서버 측 암호화를 요청합니다.

  • 객체 가져오기 - 앞 단계에서 업로드한 객체를 다운로드합니다. 요청 시 객체가 업로드되었을 때 제공한 것과 동일한 암호화 정보를 제공합니다. Amazon S3는 객체를 암호화하여 사용자에게 반환하기 위해 이 정보가 필요합니다.

  • 객체 메타데이터 가져오기 - 객체의 메타데이터를 가져옵니다. 객체 생성 시 사용한 것과 동일한 암호화 정보를 제공합니다.

  • 객체 복사 - 이전에 업로드한 객체의 복사본을 만듭니다. 원본 객체가 SSE-C를 사용하여 저장되기 때문에 복사 요청에 암호화 정보를 제공해야 합니다. 기본적으로, Amazon S3에서는 명시적으로 요청한 경우에만 객체의 사본을 암호화합니다. 이 예제에서는 Amazon S3에 새 SSE-C 키를 사용하여 객체의 암호화된 사본을 저장하도록 지시합니다.

참고

이 예제에서는 단일 작업으로 객체를 업로드하는 방법을 보여 줍니다. 멀티파트 업로드 API를 사용하여 대용량 객체를 업로드할 때는 다음 예제에서 보여주는 방식과 동일한 방식으로 암호화 정보를 제공합니다. AWS SDK for Java를 사용하는 멀티파트 업로드에 대한 예제는 멀티파트 업로드용 AWS Java SDK(상위 수준 API) 사용멀티파트 업로드용 AWS Java SDK(하위 수준 API) 사용 단원을 참조하십시오.

필요한 암호화 정보를 추가하려면 요청에 SSECustomerKey를 포함합니다. SSECustomerKey 클래스에 대한 자세한 내용은 SSE-C 사용 단원을 참조하십시오.

SSE-C에 대한 자세한 내용은 고객 제공 암호화 키(SSE-C)로 서버 측 암호화를 사용하여 데이터 보호 단원을 참조하십시오. 실제 예제를 작성 및 테스트하는 방법에 대한 자세한 내용은 Amazon S3 Java 코드 예제 테스트 단원을 참조하십시오.

import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import javax.crypto.KeyGenerator; import com.amazonaws.AmazonServiceException; import com.amazonaws.SdkClientException; import com.amazonaws.auth.profile.ProfileCredentialsProvider; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; import com.amazonaws.services.s3.model.CopyObjectRequest; import com.amazonaws.services.s3.model.GetObjectMetadataRequest; import com.amazonaws.services.s3.model.GetObjectRequest; import com.amazonaws.services.s3.model.ObjectMetadata; import com.amazonaws.services.s3.model.PutObjectRequest; import com.amazonaws.services.s3.model.S3Object; import com.amazonaws.services.s3.model.S3ObjectInputStream; import com.amazonaws.services.s3.model.SSECustomerKey; public class ServerSideEncryptionUsingClientSideEncryptionKey { private static SSECustomerKey SSE_KEY; private static AmazonS3 S3_CLIENT; private static KeyGenerator KEY_GENERATOR; public static void main(String[] args) throws IOException, NoSuchAlgorithmException { String clientRegion = "*** Client region ***"; String bucketName = "*** Bucket name ***"; String keyName = "*** Key name ***"; String uploadFileName = "*** File path ***"; String targetKeyName = "*** Target key name ***"; // Create an encryption key. KEY_GENERATOR = KeyGenerator.getInstance("AES"); KEY_GENERATOR.init(256, new SecureRandom()); SSE_KEY = new SSECustomerKey(KEY_GENERATOR.generateKey()); try { S3_CLIENT = AmazonS3ClientBuilder.standard() .withCredentials(new ProfileCredentialsProvider()) .withRegion(clientRegion) .build(); // Upload an object. uploadObject(bucketName, keyName, new File(uploadFileName)); // Download the object. downloadObject(bucketName, keyName); // Verify that the object is properly encrypted by attempting to retrieve it // using the encryption key. retrieveObjectMetadata(bucketName, keyName); // Copy the object into a new object that also uses SSE-C. copyObject(bucketName, keyName, targetKeyName); } catch(AmazonServiceException e) { // The call was transmitted successfully, but Amazon S3 couldn't process // it, so it returned an error response. e.printStackTrace(); } catch(SdkClientException e) { // Amazon S3 couldn't be contacted for a response, or the client // couldn't parse the response from Amazon S3. e.printStackTrace(); } } private static void uploadObject(String bucketName, String keyName, File file) { PutObjectRequest putRequest = new PutObjectRequest(bucketName, keyName, file).withSSECustomerKey(SSE_KEY); S3_CLIENT.putObject(putRequest); System.out.println("Object uploaded"); } private static void downloadObject(String bucketName, String keyName) throws IOException { GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, keyName).withSSECustomerKey(SSE_KEY); S3Object object = S3_CLIENT.getObject(getObjectRequest); System.out.println("Object content: "); displayTextInputStream(object.getObjectContent()); } private static void retrieveObjectMetadata(String bucketName, String keyName) { GetObjectMetadataRequest getMetadataRequest = new GetObjectMetadataRequest(bucketName, keyName) .withSSECustomerKey(SSE_KEY); ObjectMetadata objectMetadata = S3_CLIENT.getObjectMetadata(getMetadataRequest); System.out.println("Metadata retrieved. Object size: " + objectMetadata.getContentLength()); } private static void copyObject(String bucketName, String keyName, String targetKeyName) throws NoSuchAlgorithmException { // Create a new encryption key for target so that the target is saved using SSE-C. SSECustomerKey newSSEKey = new SSECustomerKey(KEY_GENERATOR.generateKey()); CopyObjectRequest copyRequest = new CopyObjectRequest(bucketName, keyName, bucketName, targetKeyName) .withSourceSSECustomerKey(SSE_KEY) .withDestinationSSECustomerKey(newSSEKey); S3_CLIENT.copyObject(copyRequest); System.out.println("Object copied"); } private static void displayTextInputStream(S3ObjectInputStream input) throws IOException { // Read one line at a time from the input stream and display each line. BufferedReader reader = new BufferedReader(new InputStreamReader(input)); String line; while ((line = reader.readLine()) != null) { System.out.println(line); } System.out.println(); } }

AWS SDK for Java를 사용하는 SSE-C가 적용된 기타 Amazon S3 작업

이전 단원의 예제에서는 PUT, GET, Head 및 Copy 작업에서 고객 제공 키로 서버 측 암호화(SSE-C)를 요청하는 방법을 보여 줍니다. 이 단원에서는 SSE-C를 지원하는 기타 API에 대해 소개합니다.

멀티파트 업로드 API를 사용하여 대형 객체를 업로드할 수 있습니다(멀티파트 업로드 API를 사용한 객체 업로드 참조). 상위 수준 또는 하위 수준의 API를 사용하여 대형 객체를 업로드할 수 있습니다. 이들 API는 요청의 암호화 관련 헤더를 지원합니다.

다음 예제에서는 TransferManager를 사용하여 객체를 만들고 SSE-C 관련 정보를 제공하는 방법을 보여 줍니다. 이 예제는 다음을 수행합니다.

  • TransferManager.upload() 메서드를 사용하여 객체를 생성합니다. PutObjectRequest 인스턴스에서 요청할 암호화 키 정보를 제공합니다. Amazon S3에서는 고객이 제공하는 암호화 키를 사용하여 객체를 암호화합니다.

  • TransferManager.copy() 메서드를 호출하여 객체의 복사본을 생성합니다. 이 예제에서는 Amazon S3에 새 SSECustomerKey를 사용하여 객체 복사본을 암호화합니다. 원본 객체가 SSE-C를 사용하여 암호화되기 때문에 Amazon S3에서 복사할 수 있기 전에 객체의 암호를 해독할 수 있도록 CopyObjectRequest 실행 시 원본 객체의 암호화 키도 제공됩니다.

import java.io.File; import java.security.SecureRandom; import javax.crypto.KeyGenerator; import com.amazonaws.AmazonServiceException; import com.amazonaws.SdkClientException; import com.amazonaws.auth.profile.ProfileCredentialsProvider; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; import com.amazonaws.services.s3.model.CopyObjectRequest; import com.amazonaws.services.s3.model.PutObjectRequest; import com.amazonaws.services.s3.model.SSECustomerKey; import com.amazonaws.services.s3.transfer.Copy; import com.amazonaws.services.s3.transfer.TransferManager; import com.amazonaws.services.s3.transfer.TransferManagerBuilder; import com.amazonaws.services.s3.transfer.Upload; public class ServerSideEncryptionCopyObjectUsingHLwithSSEC { public static void main(String[] args) throws Exception { String clientRegion = "*** Client region ***"; String bucketName = "*** Bucket name ***"; String fileToUpload = "*** File path ***"; String keyName = "*** New object key name ***"; String targetKeyName = "*** Key name for object copy ***"; try { AmazonS3 s3Client = AmazonS3ClientBuilder.standard() .withRegion(clientRegion) .withCredentials(new ProfileCredentialsProvider()) .build(); TransferManager tm = TransferManagerBuilder.standard() .withS3Client(s3Client) .build(); // Create an object from a file. PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, keyName, new File(fileToUpload)); // Create an encryption key. KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); keyGenerator.init(256, new SecureRandom()); SSECustomerKey sseCustomerEncryptionKey = new SSECustomerKey(keyGenerator.generateKey()); // Upload the object. TransferManager uploads asynchronously, so this call returns immediately. putObjectRequest.setSSECustomerKey(sseCustomerEncryptionKey); Upload upload = tm.upload(putObjectRequest); // Optionally, wait for the upload to finish before continuing. upload.waitForCompletion(); System.out.println("Object created."); // Copy the object and store the copy using SSE-C with a new key. CopyObjectRequest copyObjectRequest = new CopyObjectRequest(bucketName, keyName, bucketName, targetKeyName); SSECustomerKey sseTargetObjectEncryptionKey = new SSECustomerKey(keyGenerator.generateKey()); copyObjectRequest.setSourceSSECustomerKey(sseCustomerEncryptionKey); copyObjectRequest.setDestinationSSECustomerKey(sseTargetObjectEncryptionKey); // Copy the object. TransferManager copies asynchronously, so this call returns immediately. Copy copy = tm.copy(copyObjectRequest); // Optionally, wait for the upload to finish before continuing. copy.waitForCompletion(); System.out.println("Copy complete."); } catch(AmazonServiceException e) { // The call was transmitted successfully, but Amazon S3 couldn't process // it, so it returned an error response. e.printStackTrace(); } catch(SdkClientException e) { // Amazon S3 couldn't be contacted for a response, or the client // couldn't parse the response from Amazon S3. e.printStackTrace(); } } }