객체 무결성 확인 - Amazon Simple Storage Service

객체 무결성 확인

Amazon S3는 체크섬 값을 사용하여 Amazon S3에 업로드하거나 Amazon S3에서 다운로드하는 데이터의 무결성을 확인합니다. 또한 Amazon S3에 저장하는 모든 객체에 대해 다른 체크섬 값을 계산하도록 요청할 수 있습니다. 데이터를 업로드하거나 복사할 때 사용할 여러 체크섬 알고리즘 중 하나를 선택할 수 있습니다. Amazon S3는 이 알고리즘을 사용하여 추가 체크섬 값을 계산하고 객체 메타데이터의 일부로 저장합니다. 추가 체크섬을 사용하여 데이터 무결성을 확인하는 방법에 대한 자세한 내용은 자습서: 추가 체크섬을 사용하여 Amazon S3 내 데이터 무결성 확인을 참조하십시오.

객체를 업로드할 때 필요에 따라 미리 계산된 체크섬을 요청의 일부로 포함할 수 있습니다. Amazon S3는 제공된 체크섬을 지정된 알고리즘을 사용하여 계산한 체크섬과 비교합니다. 두 값이 일치하지 않으면 Amazon S3가 오류를 보고합니다.

지원되는 체크섬 알고리즘 사용

Amazon S3는 업로드 또는 다운로드 중에 데이터를 검증하는 데 사용하는 체크섬 알고리즘을 선택할 수 있는 옵션을 제공합니다. 다음 SHA(보안 해시 알고리즘) 또는 CRC(순환 중복 검사) 데이터 무결성 확인 알고리즘 중 하나를 선택할 수 있습니다.

  • 2013년 8월 9일

  • CRC32C

  • SHA-1

  • SHA-256

객체를 업로드할 때 사용할 알고리즘을 지정할 수 있습니다.

  • AWS Management Console을 사용하고 있는 경우 사용할 체크섬 알고리즘을 선택합니다. 이렇게 하면 필요에 따라 객체의 체크섬 값을 지정할 수 있습니다. Amazon S3가 객체를 수신하면 지정한 알고리즘을 사용하여 체크섬 값을 계산합니다. 두 체크섬 값이 일치하지 않으면 Amazon S3가 오류를 생성합니다.

  • SDK를 사용하고 있는 경우 x-amz-sdk-checksum-algorithm 파라미터의 값을 Amazon S3에서 체크섬 값을 계산할 때 사용할 알고리즘으로 설정합니다. Amazon S3가 자동으로 체크섬 값을 계산합니다.

  • REST API를 사용하고 있는 경우 x-amz-sdk-checksum-algorithm 파라미터를 사용하면 안 됩니다. 그 대신 알고리즘별 헤더 중 하나를 사용합니다(예: x-amz-checksum-crc32).

객체 업로드에 대한 자세한 내용은 객체 업로드 단원을 참조하십시오.

Amazon S3에 이미 업로드된 객체에 이러한 체크섬 값을 적용하려면 객체를 복사하면 됩니다. 객체를 복사할 때 기존 체크섬 알고리즘을 사용할지 아니면 새 체크섬 알고리즘을 사용할지 지정할 수 있습니다. S3 배치 작업을 포함하여 객체 복사에 지원되는 메커니즘을 사용할 때 체크섬 알고리즘을 지정할 수 있습니다. S3 배치 작업에 대한 자세한 내용은 Amazon S3 객체에 대한 대규모 배치 작업 수행 섹션을 참조하십시오.

중요

추가 체크섬과 함께 멀티파트 업로드를 사용하는 경우 멀티파트 부분 번호는 연속 부분 번호를 사용해야 합니다. 추가 체크섬을 사용할 때 연속되지 않는 부분 번호로 멀티파트 업로드 요청을 완료하려고 하면 Amazon S3가 HTTP 500 Internal Server Error 오류를 생성합니다.

객체를 업로드한 후 체크섬 값을 가져와 미리 계산되거나 동일한 알고리즘을 사용하여 계산된 이전에 저장된 체크섬 값과 비교할 수 있습니다.

콘솔 사용 방법과 객체를 업로드할 때 사용할 체크섬 알고리즘을 지정하는 방법을 자세히 알아보려면 객체 업로드자습서: 추가 체크섬을 사용하여 Amazon S3 내 데이터 무결성 확인을 참조하십시오.

다음 예제는 AWS SDK를 사용하여 멀티파트 업로드로 대량의 파일을 업로드 및 다운로드하고, 파일 확인을 위한 SHA-256을 사용하여 멀티파트 업로드 파일을 확인하는 방법을 보여줍니다.

Java
예제: SHA-256을 사용하여 대량의 파일 업로드, 다운로드 및 확인

실제 예제를 작성 및 테스트하는 방법에 대한 자세한 내용은 Amazon S3 Java 코드 예제 테스트 섹션을 참조하십시오.

import software.amazon.awssdk.auth.credentials.AwsCredentials; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; import software.amazon.awssdk.core.ResponseInputStream; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.AbortMultipartUploadRequest; import software.amazon.awssdk.services.s3.model.ChecksumAlgorithm; import software.amazon.awssdk.services.s3.model.ChecksumMode; import software.amazon.awssdk.services.s3.model.CompleteMultipartUploadRequest; import software.amazon.awssdk.services.s3.model.CompleteMultipartUploadResponse; import software.amazon.awssdk.services.s3.model.CompletedMultipartUpload; import software.amazon.awssdk.services.s3.model.CompletedPart; import software.amazon.awssdk.services.s3.model.CreateMultipartUploadRequest; import software.amazon.awssdk.services.s3.model.CreateMultipartUploadResponse; import software.amazon.awssdk.services.s3.model.GetObjectAttributesRequest; import software.amazon.awssdk.services.s3.model.GetObjectAttributesResponse; import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.GetObjectResponse; import software.amazon.awssdk.services.s3.model.GetObjectTaggingRequest; import software.amazon.awssdk.services.s3.model.ObjectAttributes; import software.amazon.awssdk.services.s3.model.PutObjectTaggingRequest; import software.amazon.awssdk.services.s3.model.Tag; import software.amazon.awssdk.services.s3.model.Tagging; import software.amazon.awssdk.services.s3.model.UploadPartRequest; import software.amazon.awssdk.services.s3.model.UploadPartResponse; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Base64; import java.util.List; public class LargeObjectValidation { private static String FILE_NAME = "sample.file"; private static String BUCKET = "sample-bucket"; //Optional, if you want a method of storing the full multipart object checksum in S3. private static String CHECKSUM_TAG_KEYNAME = "fullObjectChecksum"; //If you have existing full-object checksums that you need to validate against, you can do the full object validation on a sequential upload. private static String SHA256_FILE_BYTES = "htCM5g7ZNdoSw8bN/mkgiAhXt5MFoVowVg+LE9aIQmI="; //Example Chunk Size - this must be greater than or equal to 5MB. private static int CHUNK_SIZE = 5 * 1024 * 1024; public static void main(String[] args) { S3Client s3Client = S3Client.builder() .region(Region.US_EAST_1) .credentialsProvider(new AwsCredentialsProvider() { @Override public AwsCredentials resolveCredentials() { return new AwsCredentials() { @Override public String accessKeyId() { return Constants.ACCESS_KEY; } @Override public String secretAccessKey() { return Constants.SECRET; } }; } }) .build(); uploadLargeFileBracketedByChecksum(s3Client); downloadLargeFileBracketedByChecksum(s3Client); validateExistingFileAgainstS3Checksum(s3Client); } public static void uploadLargeFileBracketedByChecksum(S3Client s3Client) { System.out.println("Starting uploading file validation"); File file = new File(FILE_NAME); try (InputStream in = new FileInputStream(file)) { MessageDigest sha256 = MessageDigest.getInstance("SHA-256"); CreateMultipartUploadRequest createMultipartUploadRequest = CreateMultipartUploadRequest.builder() .bucket(BUCKET) .key(FILE_NAME) .checksumAlgorithm(ChecksumAlgorithm.SHA256) .build(); CreateMultipartUploadResponse createdUpload = s3Client.createMultipartUpload(createMultipartUploadRequest); List<CompletedPart> completedParts = new ArrayList<CompletedPart>(); int partNumber = 1; byte[] buffer = new byte[CHUNK_SIZE]; int read = in.read(buffer); while (read != -1) { UploadPartRequest uploadPartRequest = UploadPartRequest.builder() .partNumber(partNumber).uploadId(createdUpload.uploadId()).key(FILE_NAME).bucket(BUCKET).checksumAlgorithm(ChecksumAlgorithm.SHA256).build(); UploadPartResponse uploadedPart = s3Client.uploadPart(uploadPartRequest, RequestBody.fromByteBuffer(ByteBuffer.wrap(buffer, 0, read))); CompletedPart part = CompletedPart.builder().partNumber(partNumber).checksumSHA256(uploadedPart.checksumSHA256()).eTag(uploadedPart.eTag()).build(); completedParts.add(part); sha256.update(buffer, 0, read); read = in.read(buffer); partNumber++; } String fullObjectChecksum = Base64.getEncoder().encodeToString(sha256.digest()); if (!fullObjectChecksum.equals(SHA256_FILE_BYTES)) { //Because the SHA256 is uploaded after the part is uploaded; the upload is bracketed and the full object can be fully validated. s3Client.abortMultipartUpload(AbortMultipartUploadRequest.builder().bucket(BUCKET).key(FILE_NAME).uploadId(createdUpload.uploadId()).build()); throw new IOException("Byte mismatch between stored checksum and upload, do not proceed with upload and cleanup"); } CompletedMultipartUpload completedMultipartUpload = CompletedMultipartUpload.builder().parts(completedParts).build(); CompleteMultipartUploadResponse completedUploadResponse = s3Client.completeMultipartUpload( CompleteMultipartUploadRequest.builder().bucket(BUCKET).key(FILE_NAME).uploadId(createdUpload.uploadId()).multipartUpload(completedMultipartUpload).build()); Tag checksumTag = Tag.builder().key(CHECKSUM_TAG_KEYNAME).value(fullObjectChecksum).build(); //Optionally, if you need the full object checksum stored with the file; you could add it as a tag after completion. s3Client.putObjectTagging(PutObjectTaggingRequest.builder().bucket(BUCKET).key(FILE_NAME).tagging(Tagging.builder().tagSet(checksumTag).build()).build()); } catch (IOException | NoSuchAlgorithmException e) { e.printStackTrace(); } GetObjectAttributesResponse objectAttributes = s3Client.getObjectAttributes(GetObjectAttributesRequest.builder().bucket(BUCKET).key(FILE_NAME) .objectAttributes(ObjectAttributes.OBJECT_PARTS, ObjectAttributes.CHECKSUM).build()); System.out.println(objectAttributes.objectParts().parts()); System.out.println(objectAttributes.checksum().checksumSHA256()); } public static void downloadLargeFileBracketedByChecksum(S3Client s3Client) { System.out.println("Starting downloading file validation"); File file = new File("DOWNLOADED_" + FILE_NAME); try (OutputStream out = new FileOutputStream(file)) { GetObjectAttributesResponse objectAttributes = s3Client.getObjectAttributes(GetObjectAttributesRequest.builder().bucket(BUCKET).key(FILE_NAME) .objectAttributes(ObjectAttributes.OBJECT_PARTS, ObjectAttributes.CHECKSUM).build()); //Optionally if you need the full object checksum, you can grab a tag you added on the upload List<Tag> objectTags = s3Client.getObjectTagging(GetObjectTaggingRequest.builder().bucket(BUCKET).key(FILE_NAME).build()).tagSet(); String fullObjectChecksum = null; for (Tag objectTag : objectTags) { if (objectTag.key().equals(CHECKSUM_TAG_KEYNAME)) { fullObjectChecksum = objectTag.value(); break; } } MessageDigest sha256FullObject = MessageDigest.getInstance("SHA-256"); MessageDigest sha256ChecksumOfChecksums = MessageDigest.getInstance("SHA-256"); //If you retrieve the object in parts, and set the ChecksumMode to enabled, the SDK will automatically validate the part checksum for (int partNumber = 1; partNumber <= objectAttributes.objectParts().totalPartsCount(); partNumber++) { MessageDigest sha256Part = MessageDigest.getInstance("SHA-256"); ResponseInputStream<GetObjectResponse> response = s3Client.getObject(GetObjectRequest.builder().bucket(BUCKET).key(FILE_NAME).partNumber(partNumber).checksumMode(ChecksumMode.ENABLED).build()); GetObjectResponse getObjectResponse = response.response(); byte[] buffer = new byte[CHUNK_SIZE]; int read = response.read(buffer); while (read != -1) { out.write(buffer, 0, read); sha256FullObject.update(buffer, 0, read); sha256Part.update(buffer, 0, read); read = response.read(buffer); } byte[] sha256PartBytes = sha256Part.digest(); sha256ChecksumOfChecksums.update(sha256PartBytes); //Optionally, you can do an additional manual validation again the part checksum if needed in addition to the SDK check String base64PartChecksum = Base64.getEncoder().encodeToString(sha256PartBytes); String base64PartChecksumFromObjectAttributes = objectAttributes.objectParts().parts().get(partNumber - 1).checksumSHA256(); if (!base64PartChecksum.equals(getObjectResponse.checksumSHA256()) || !base64PartChecksum.equals(base64PartChecksumFromObjectAttributes)) { throw new IOException("Part checksum didn't match for the part"); } System.out.println(partNumber + " " + base64PartChecksum); } //Before finalizing, do the final checksum validation. String base64FullObject = Base64.getEncoder().encodeToString(sha256FullObject.digest()); String base64ChecksumOfChecksums = Base64.getEncoder().encodeToString(sha256ChecksumOfChecksums.digest()); if (fullObjectChecksum != null && !fullObjectChecksum.equals(base64FullObject)) { throw new IOException("Failed checksum validation for full object"); } System.out.println(fullObjectChecksum); String base64ChecksumOfChecksumFromAttributes = objectAttributes.checksum().checksumSHA256(); if (base64ChecksumOfChecksumFromAttributes != null && !base64ChecksumOfChecksums.equals(base64ChecksumOfChecksumFromAttributes)) { throw new IOException("Failed checksum validation for full object checksum of checksums"); } System.out.println(base64ChecksumOfChecksumFromAttributes); out.flush(); } catch (IOException | NoSuchAlgorithmException e) { //Cleanup bad file file.delete(); e.printStackTrace(); } } public static void validateExistingFileAgainstS3Checksum(S3Client s3Client) { System.out.println("Starting existing file validation"); File file = new File("DOWNLOADED_" + FILE_NAME); GetObjectAttributesResponse objectAttributes = s3Client.getObjectAttributes(GetObjectAttributesRequest.builder().bucket(BUCKET).key(FILE_NAME) .objectAttributes(ObjectAttributes.OBJECT_PARTS, ObjectAttributes.CHECKSUM).build()); try (InputStream in = new FileInputStream(file)) { MessageDigest sha256ChecksumOfChecksums = MessageDigest.getInstance("SHA-256"); MessageDigest sha256Part = MessageDigest.getInstance("SHA-256"); byte[] buffer = new byte[CHUNK_SIZE]; int currentPart = 0; int partBreak = objectAttributes.objectParts().parts().get(currentPart).size(); int totalRead = 0; int read = in.read(buffer); while (read != -1) { totalRead += read; if (totalRead >= partBreak) { int difference = totalRead - partBreak; byte[] partChecksum; if (totalRead != partBreak) { sha256Part.update(buffer, 0, read - difference); partChecksum = sha256Part.digest(); sha256ChecksumOfChecksums.update(partChecksum); sha256Part.reset(); sha256Part.update(buffer, read - difference, difference); } else { sha256Part.update(buffer, 0, read); partChecksum = sha256Part.digest(); sha256ChecksumOfChecksums.update(partChecksum); sha256Part.reset(); } String base64PartChecksum = Base64.getEncoder().encodeToString(partChecksum); if (!base64PartChecksum.equals(objectAttributes.objectParts().parts().get(currentPart).checksumSHA256())) { throw new IOException("Part checksum didn't match S3"); } currentPart++; System.out.println(currentPart + " " + base64PartChecksum); if (currentPart < objectAttributes.objectParts().totalPartsCount()) { partBreak += objectAttributes.objectParts().parts().get(currentPart - 1).size(); } } else { sha256Part.update(buffer, 0, read); } read = in.read(buffer); } if (currentPart != objectAttributes.objectParts().totalPartsCount()) { currentPart++; byte[] partChecksum = sha256Part.digest(); sha256ChecksumOfChecksums.update(partChecksum); String base64PartChecksum = Base64.getEncoder().encodeToString(partChecksum); System.out.println(currentPart + " " + base64PartChecksum); } String base64CalculatedChecksumOfChecksums = Base64.getEncoder().encodeToString(sha256ChecksumOfChecksums.digest()); System.out.println(base64CalculatedChecksumOfChecksums); System.out.println(objectAttributes.checksum().checksumSHA256()); if (!base64CalculatedChecksumOfChecksums.equals(objectAttributes.checksum().checksumSHA256())) { throw new IOException("Full object checksum of checksums don't match S3"); } } catch (IOException | NoSuchAlgorithmException e) { e.printStackTrace(); } } }

REST 요청을 전송하고 체크섬 값을 사용하여 객체를 업로드하여 PutObject로 데이터의 무결성을 확인할 수 있습니다. GetObject 또는 HeadObject를 사용하여 객체의 체크섬 값을 검색할 수도 있습니다.

PUT 요청을 보내 한 번의 작업으로 최대 5GB의 객체를 업로드할 수 있습니다. 자세한 내용은 AWS CLI 명령 참조PutObject를 참조하십시오. get-objecthead-object를 사용하여 이미 업로드된 객체의 체크섬을 검색함으로써 데이터 무결성을 확인할 수도 있습니다.

자세한 내용은 AWS Command Line Interface 사용 설명서의 Amazon S3 CLI FAQ를 참조하세요.

객체를 업로드할 때 Content-MD5 사용

업로드 후 객체의 무결성을 확인하는 또 다른 방법은 객체를 업로드할 때 객체의 MD5 다이제스트를 제공하는 것입니다. 객체에 대한 MD5 다이제스트를 계산하면 Content-MD5 헤더를 사용하여 PUT 명령으로 다이제스트를 제공할 수 있습니다.

객체를 업로드한 후 Amazon S3는 객체의 MD5 다이제스트를 계산하여 사용자가 제공한 값과 비교합니다. 두 다이제스트가 일치하는 경우에만 요청이 성공합니다.

MD5 다이제스트를 제공할 필요는 없지만 업로드 프로세스의 일부로 객체의 무결성을 확인하는 데 사용할 수 있습니다.

Content-MD5 및 ETag를 사용하여 업로드된 객체 확인

객체의 엔터티 태그(ETag)는 해당 객체의 특정 버전을 나타냅니다. ETag는 객체의 콘텐츠에 대한 변경 사항만 반영하고 메타데이터에 대한 변경을 반영하지 않는다는 점을 명심하십시오. 객체의 메타데이터만 변경되는 경우 ETag는 동일하게 유지됩니다.

객체에 따라 객체의 ETag가 객체 데이터의 MD5 다이제스트일 수 있습니다.

  • 객체가 PutObject, PostObject 또는 CopyObject 작업으로, 또는 AWS Management Console을 통해 생성되며 해당 객체가 일반 텍스트 또는 Amazon S3 관리형 키(SSE-S3)를 통한 서버 측 암호화를 사용하여 암호화되는 경우 해당 객체에는 객체 데이터의 MD5 다이제스트인 ETag가 있습니다.

  • 객체가 PutObject, PostObject 또는 CopyObject 작업으로, 또는 AWS Management Console을 통해 생성되며 해당 객체가 고객 제공 키를 통한 서버 측 암호화(SSE-C) 또는 AWS Key Management Service(AWS KMS) 키를 통한 서버 측 암호화(SSE-KMS)를 사용하여 암호화되는 경우 해당 객체에는 객체 데이터의 MD5 다이제스트가 아닌 ETag가 있습니다.

  • 객체가 Multipart Upload 또는 Part Copy 작업으로 생성되는 경우 암호화 방법에 관계없이 객체의 ETag는 MD5 다이제스트가 아닙니다. 객체가 16MB보다 큰 경우 AWS Management Console은 해당 객체를 멀티파트 업로드로 업로드하거나 복사하므로 ETag가 MD5 다이제스트가 아닙니다.

ETag가 객체의 Content-MD5 다이제스트인 객체의 경우 해당 객체의 ETag 값을 계산된 또는 이전에 저장된 Content-MD5 다이제스트와 비교할 수 있습니다.

후행 체크섬 사용

Amazon S3에 객체를 업로드할 때 객체에 대해 미리 계산된 체크섬을 제공하거나 AWS SDK를 사용하여 사용자를 대신하여 후행 체크섬을 자동으로 생성하도록 할 수 있습니다. 후행 체크섬을 사용하기로 한 경우 Amazon S3는 지정된 알고리즘을 사용하여 자동으로 체크섬을 생성하고 이를 사용하여 업로드 중에 객체의 무결성을 확인합니다.

AWS SDK를 사용할 때 후행 체크섬을 생성하려면 ChecksumAlgorithm 파라미터를 원하는 알고리즘으로 채웁니다. SDK는 해당 알고리즘을 사용하여 객체(또는 객체 부분)에 대한 체크섬을 계산하고 업로드 요청 끝에 자동으로 추가합니다. 이 동작은 Amazon S3가 단일 패스로 데이터의 확인 및 업로드를 모두 수행하므로 시간을 절약할 수 있습니다.

중요

S3 객체 Lambda를 사용하는 경우 S3 객체 Lambda에 대한 모든 요청은 s3 대신 s3-object-lambda를 사용하여 서명됩니다. 이 동작은 후행 체크섬 값의 서명에 영향을 줍니다. S3 객체 Lambda에 대한 자세한 내용은 S3 객체 Lambda를 사용하여 객체 변환 섹션을 참조하십시오.

멀티파트 업로드에 부분 수준의 체크섬 사용

객체를 Amazon S3에 업로드할 때 단일 객체로 업로드하거나 멀티파트 업로드 프로세스를 통해 업로드할 수 있습니다. 16MB보다 크며 콘솔을 통해 업로드한 객체는 멀티파트 업로드를 사용하여 자동으로 업로드됩니다. 멀티파트 업로드에 대한 자세한 내용은 멀티파트 업로드를 사용한 객체 업로드 및 복사 섹션을 참조하십시오.

객체가 멀티파트 업로드로 업로드되면 객체의 ETag는 전체 객체의 MD5 다이제스트가 아닙니다. Amazon S3는 업로드될 때 각 개별 부분의 MD5 다이제스트를 계산합니다. MD5 다이제스트는 최종 객체의 ETag를 결정하는 데 사용됩니다. Amazon S3는 MD5 다이제스트에 대한 바이트를 함께 연결한 다음 이러한 연결된 값의 MD5 다이제스트를 계산합니다. ETag를 생성하는 마지막 단계는 Amazon S3가 끝에 총 부분 수와 함께 대시를 추가하는 것입니다.

예를 들어, C9A5A6878D97B48CC965C1E41859F034-14의 ETag가 있는 객체를 멀티파트 업로드를 통해 업로드한다고 가정해 보겠습니다.. 이 경우 C9A5A6878D97B48CC965C1E41859F034는 함께 연결된 모든 다이제스트의 MD5 다이제스트입니다. -14는 이 객체의 멀티파트 업로드와 연관된 부분이 14개임을 나타냅니다.

멀티파트 객체에 대해 추가 체크섬 값을 사용한 경우 Amazon S3가 지정된 체크섬 알고리즘을 사용하여 각 개별 부분에 대한 체크섬을 계산합니다. 완료된 객체의 체크섬은 Amazon S3가 멀티파트 업로드에 대한 MD5 다이제스트를 계산하는 것과 동일한 방식으로 계산됩니다. 이 체크섬을 사용하여 객체의 무결성을 확인할 수 있습니다.

전체 객체를 구성하는 부분 수를 포함하여 객체에 대한 정보를 검색하려면 GetObjectAttributes 작업을 사용하면 됩니다. 추가 체크섬을 사용하면 각 부분의 체크섬 값을 비롯한 각 개별 부분에 대한 정보를 복구할 수도 있습니다.

GetObject 또는 HeadObject 작업을 사용하고 단일 부분에 부합하는 부분 번호나 바이트 범위를 지정하여 개별 부분의 체크섬을 가져올 수도 있습니다. 이 방법을 사용하면 데이터 무결성을 확인하기 전에 모든 부분의 업로드를 완료할 때까지 기다릴 필요 없이 해당 체크섬을 사용하여 개별 부분의 유효성을 검사할 수 있습니다. 이 방법을 사용하는 경우 무결성 테스트에 실패한 개별 부분만 요청할 수도 있습니다.

Amazon S3가 멀티파트 객체에 대한 체크섬을 계산하는 방식 때문에 객체를 복사할 경우 객체의 체크섬 값이 변경될 수 있습니다. SDK 또는 REST API를 사용하고 있으며 CopyObject를 호출하는 경우 Amazon S3는 CopyObject API 작업의 크기 제한에 도달할 때까지 객체를 복사합니다. Amazon S3는 객체가 단일 요청으로 업로드되었는지 또는 멀티파트 업로드의 일부로 업로드되었는지 여부에 관계없이 이 복사 작업을 단일 작업으로 수행합니다. 복사 명령을 사용하면 객체의 체크섬은 전체 객체의 직접 체크섬입니다. 객체가 원래 멀티파트 업로드를 사용하여 업로드된 경우 데이터가 변경되지 않는 경우에도 체크섬 값이 변경됩니다.

참고

CopyObject API 작업의 크기 제한보다 큰 객체는 멀티파트 복사 명령을 사용해야 합니다.

중요

AWS Management Console을 사용하여 일부 작업을 수행할 때 객체의 크기가 16MB를 초과하는 경우 Amazon S3는 멀티파트 업로드를 사용합니다. 이 경우 체크섬은 전체 객체의 직접 체크섬이 아니라 각 개별 부분의 체크섬 값을 기반으로 한 계산입니다.

예를 들어 REST API를 사용하여 단일 부분 직접 업로드로 업로드한 100MB 크기의 객체를 가정해 보겠습니다. 이 경우 체크섬은 전체 객체의 체크섬입니다. 나중에 콘솔을 사용하여 객체의 이름을 바꾸거나, 복사하거나, 스토리지 클래스를 변경하거나, 메타데이터를 편집하는 경우 Amazon S3는 멀티파트 업로드 기능을 사용하여 객체를 업데이트합니다. 따라서 Amazon S3는 개별 부분의 체크섬 값을 기준으로 계산되는 객체의 새 체크섬 값을 생성합니다.

위의 콘솔 작업 목록은 Amazon S3가 멀티파트 업로드 기능을 사용하여 객체를 업데이트한 결과 AWS Management Console에서 취할 수 있는 가능한 모든 조치의 전체 목록이 아닙니다. 콘솔을 사용하여 크기가 16MB를 초과하는 객체에 대해 조치를 취할 때마다 체크섬 값이 전체 객체의 체크섬이 아닐 수 있음을 명심하십시오.